diff --git a/assets/svgs/flags/abkhazia_flag.svg b/assets/svgs/flags/abkhazia_flag.svg new file mode 100644 index 0000000..b2d7b22 --- /dev/null +++ b/assets/svgs/flags/abkhazia_flag.svg @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/afghanistan_flag.svg b/assets/svgs/flags/afghanistan_flag.svg new file mode 100644 index 0000000..7b38b2c --- /dev/null +++ b/assets/svgs/flags/afghanistan_flag.svg @@ -0,0 +1,68 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/aland_islands_flag.svg b/assets/svgs/flags/aland_islands_flag.svg new file mode 100644 index 0000000..edd92ae --- /dev/null +++ b/assets/svgs/flags/aland_islands_flag.svg @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/albania_flag.svg b/assets/svgs/flags/albania_flag.svg new file mode 100644 index 0000000..70d990d --- /dev/null +++ b/assets/svgs/flags/albania_flag.svg @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/algeria_flag.svg b/assets/svgs/flags/algeria_flag.svg new file mode 100644 index 0000000..d2b0038 --- /dev/null +++ b/assets/svgs/flags/algeria_flag.svg @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/american_samoa_flag.svg b/assets/svgs/flags/american_samoa_flag.svg new file mode 100644 index 0000000..745aaa3 --- /dev/null +++ b/assets/svgs/flags/american_samoa_flag.svg @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/andorra_flag.svg b/assets/svgs/flags/andorra_flag.svg new file mode 100644 index 0000000..361ea2b --- /dev/null +++ b/assets/svgs/flags/andorra_flag.svg @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/angola_flag.svg b/assets/svgs/flags/angola_flag.svg new file mode 100644 index 0000000..8b58b49 --- /dev/null +++ b/assets/svgs/flags/angola_flag.svg @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/anguilla_flag.svg b/assets/svgs/flags/anguilla_flag.svg new file mode 100644 index 0000000..6365583 --- /dev/null +++ b/assets/svgs/flags/anguilla_flag.svg @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/antigua_and_barbuda_flag.svg b/assets/svgs/flags/antigua_and_barbuda_flag.svg new file mode 100644 index 0000000..b0cc218 --- /dev/null +++ b/assets/svgs/flags/antigua_and_barbuda_flag.svg @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/argentina_flag.svg b/assets/svgs/flags/argentina_flag.svg new file mode 100644 index 0000000..3f00d94 --- /dev/null +++ b/assets/svgs/flags/argentina_flag.svg @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/armenia_flag.svg b/assets/svgs/flags/armenia_flag.svg new file mode 100644 index 0000000..99ac8d0 --- /dev/null +++ b/assets/svgs/flags/armenia_flag.svg @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/aruba_flag.svg b/assets/svgs/flags/aruba_flag.svg new file mode 100644 index 0000000..75da388 --- /dev/null +++ b/assets/svgs/flags/aruba_flag.svg @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/australia_flag.svg b/assets/svgs/flags/australia_flag.svg new file mode 100644 index 0000000..9f8ddc9 --- /dev/null +++ b/assets/svgs/flags/australia_flag.svg @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/austria_flag.svg b/assets/svgs/flags/austria_flag.svg new file mode 100644 index 0000000..4facf03 --- /dev/null +++ b/assets/svgs/flags/austria_flag.svg @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/azerbaijan_flag.svg b/assets/svgs/flags/azerbaijan_flag.svg new file mode 100644 index 0000000..8ca0ad7 --- /dev/null +++ b/assets/svgs/flags/azerbaijan_flag.svg @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/azores_islands_flag.svg b/assets/svgs/flags/azores_islands_flag.svg new file mode 100644 index 0000000..faed170 --- /dev/null +++ b/assets/svgs/flags/azores_islands_flag.svg @@ -0,0 +1,66 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/bahamas_flag.svg b/assets/svgs/flags/bahamas_flag.svg new file mode 100644 index 0000000..6056d0c --- /dev/null +++ b/assets/svgs/flags/bahamas_flag.svg @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/bahrain_flag.svg b/assets/svgs/flags/bahrain_flag.svg new file mode 100644 index 0000000..ee6a75f --- /dev/null +++ b/assets/svgs/flags/bahrain_flag.svg @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/balearic_islands_flag.svg b/assets/svgs/flags/balearic_islands_flag.svg new file mode 100644 index 0000000..e2a468b --- /dev/null +++ b/assets/svgs/flags/balearic_islands_flag.svg @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/bangladesh_flag.svg b/assets/svgs/flags/bangladesh_flag.svg new file mode 100644 index 0000000..981e7da --- /dev/null +++ b/assets/svgs/flags/bangladesh_flag.svg @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/barbados_flag.svg b/assets/svgs/flags/barbados_flag.svg new file mode 100644 index 0000000..e398bc9 --- /dev/null +++ b/assets/svgs/flags/barbados_flag.svg @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/basque_country_flag.svg b/assets/svgs/flags/basque_country_flag.svg new file mode 100644 index 0000000..6304b64 --- /dev/null +++ b/assets/svgs/flags/basque_country_flag.svg @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/belarus_flag.svg b/assets/svgs/flags/belarus_flag.svg new file mode 100644 index 0000000..c40210d --- /dev/null +++ b/assets/svgs/flags/belarus_flag.svg @@ -0,0 +1,81 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/belgium_flag.svg b/assets/svgs/flags/belgium_flag.svg new file mode 100644 index 0000000..82a72cd --- /dev/null +++ b/assets/svgs/flags/belgium_flag.svg @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/belize_flag.svg b/assets/svgs/flags/belize_flag.svg new file mode 100644 index 0000000..2261507 --- /dev/null +++ b/assets/svgs/flags/belize_flag.svg @@ -0,0 +1,193 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/benin_flag.svg b/assets/svgs/flags/benin_flag.svg new file mode 100644 index 0000000..3b0962a --- /dev/null +++ b/assets/svgs/flags/benin_flag.svg @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/bermuda_flag.svg b/assets/svgs/flags/bermuda_flag.svg new file mode 100644 index 0000000..0efea5b --- /dev/null +++ b/assets/svgs/flags/bermuda_flag.svg @@ -0,0 +1,95 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/bhutan_flag.svg b/assets/svgs/flags/bhutan_flag.svg new file mode 100644 index 0000000..a3d4131 --- /dev/null +++ b/assets/svgs/flags/bhutan_flag.svg @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/bolivia_flag.svg b/assets/svgs/flags/bolivia_flag.svg new file mode 100644 index 0000000..4c091ab --- /dev/null +++ b/assets/svgs/flags/bolivia_flag.svg @@ -0,0 +1,101 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/bonaire_flag.svg b/assets/svgs/flags/bonaire_flag.svg new file mode 100644 index 0000000..2dc0ff8 --- /dev/null +++ b/assets/svgs/flags/bonaire_flag.svg @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/bosnia_and_herzegovina_flag.svg b/assets/svgs/flags/bosnia_and_herzegovina_flag.svg new file mode 100644 index 0000000..d1737a3 --- /dev/null +++ b/assets/svgs/flags/bosnia_and_herzegovina_flag.svg @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/botswana_flag.svg b/assets/svgs/flags/botswana_flag.svg new file mode 100644 index 0000000..4029b7f --- /dev/null +++ b/assets/svgs/flags/botswana_flag.svg @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/brazil_flag.svg b/assets/svgs/flags/brazil_flag.svg new file mode 100644 index 0000000..a00f0c2 --- /dev/null +++ b/assets/svgs/flags/brazil_flag.svg @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/british_columbia_flag.svg b/assets/svgs/flags/british_columbia_flag.svg new file mode 100644 index 0000000..09047af --- /dev/null +++ b/assets/svgs/flags/british_columbia_flag.svg @@ -0,0 +1,76 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/british_indian_ocean_territory_flag.svg b/assets/svgs/flags/british_indian_ocean_territory_flag.svg new file mode 100644 index 0000000..5c6256b --- /dev/null +++ b/assets/svgs/flags/british_indian_ocean_territory_flag.svg @@ -0,0 +1,55 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/british_virgin_islands_flag.svg b/assets/svgs/flags/british_virgin_islands_flag.svg new file mode 100644 index 0000000..a3175d5 --- /dev/null +++ b/assets/svgs/flags/british_virgin_islands_flag.svg @@ -0,0 +1,81 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/brunei_flag.svg b/assets/svgs/flags/brunei_flag.svg new file mode 100644 index 0000000..8ae0bfb --- /dev/null +++ b/assets/svgs/flags/brunei_flag.svg @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/bulgaria_flag.svg b/assets/svgs/flags/bulgaria_flag.svg new file mode 100644 index 0000000..5b996c7 --- /dev/null +++ b/assets/svgs/flags/bulgaria_flag.svg @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/burkina_faso_flag.svg b/assets/svgs/flags/burkina_faso_flag.svg new file mode 100644 index 0000000..cfb3a4b --- /dev/null +++ b/assets/svgs/flags/burkina_faso_flag.svg @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/burundi_flag.svg b/assets/svgs/flags/burundi_flag.svg new file mode 100644 index 0000000..dd5c8c6 --- /dev/null +++ b/assets/svgs/flags/burundi_flag.svg @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/cambodia_flag.svg b/assets/svgs/flags/cambodia_flag.svg new file mode 100644 index 0000000..daa1c01 --- /dev/null +++ b/assets/svgs/flags/cambodia_flag.svg @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/cameroon_flag.svg b/assets/svgs/flags/cameroon_flag.svg new file mode 100644 index 0000000..f003846 --- /dev/null +++ b/assets/svgs/flags/cameroon_flag.svg @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/canada_flag.svg b/assets/svgs/flags/canada_flag.svg new file mode 100644 index 0000000..462fae8 --- /dev/null +++ b/assets/svgs/flags/canada_flag.svg @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/canary_islands_flag.svg b/assets/svgs/flags/canary_islands_flag.svg new file mode 100644 index 0000000..67f8056 --- /dev/null +++ b/assets/svgs/flags/canary_islands_flag.svg @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/cape_verde_flag.svg b/assets/svgs/flags/cape_verde_flag.svg new file mode 100644 index 0000000..ed54969 --- /dev/null +++ b/assets/svgs/flags/cape_verde_flag.svg @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/cayman_islands_flag.svg b/assets/svgs/flags/cayman_islands_flag.svg new file mode 100644 index 0000000..a7d3abb --- /dev/null +++ b/assets/svgs/flags/cayman_islands_flag.svg @@ -0,0 +1,131 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/central_african_republic_flag.svg b/assets/svgs/flags/central_african_republic_flag.svg new file mode 100644 index 0000000..8b79cc7 --- /dev/null +++ b/assets/svgs/flags/central_african_republic_flag.svg @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/ceuta_flag.svg b/assets/svgs/flags/ceuta_flag.svg new file mode 100644 index 0000000..fa82c0d --- /dev/null +++ b/assets/svgs/flags/ceuta_flag.svg @@ -0,0 +1,88 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/chad_flag.svg b/assets/svgs/flags/chad_flag.svg new file mode 100644 index 0000000..d81e233 --- /dev/null +++ b/assets/svgs/flags/chad_flag.svg @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/chile_flag.svg b/assets/svgs/flags/chile_flag.svg new file mode 100644 index 0000000..b7e74c4 --- /dev/null +++ b/assets/svgs/flags/chile_flag.svg @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/china_flag.svg b/assets/svgs/flags/china_flag.svg new file mode 100644 index 0000000..3c9a055 --- /dev/null +++ b/assets/svgs/flags/china_flag.svg @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/christmas_island_flag.svg b/assets/svgs/flags/christmas_island_flag.svg new file mode 100644 index 0000000..4d2abfd --- /dev/null +++ b/assets/svgs/flags/christmas_island_flag.svg @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/cocos_island_flag.svg b/assets/svgs/flags/cocos_island_flag.svg new file mode 100644 index 0000000..caa8710 --- /dev/null +++ b/assets/svgs/flags/cocos_island_flag.svg @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/colombia_flag.svg b/assets/svgs/flags/colombia_flag.svg new file mode 100644 index 0000000..17b72d5 --- /dev/null +++ b/assets/svgs/flags/colombia_flag.svg @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/comoros_flag.svg b/assets/svgs/flags/comoros_flag.svg new file mode 100644 index 0000000..c97367e --- /dev/null +++ b/assets/svgs/flags/comoros_flag.svg @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/cook_islands_flag.svg b/assets/svgs/flags/cook_islands_flag.svg new file mode 100644 index 0000000..ea615d5 --- /dev/null +++ b/assets/svgs/flags/cook_islands_flag.svg @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/corsica_flag.svg b/assets/svgs/flags/corsica_flag.svg new file mode 100644 index 0000000..d0b8d8e --- /dev/null +++ b/assets/svgs/flags/corsica_flag.svg @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/costa_rica_flag.svg b/assets/svgs/flags/costa_rica_flag.svg new file mode 100644 index 0000000..cfe9c26 --- /dev/null +++ b/assets/svgs/flags/costa_rica_flag.svg @@ -0,0 +1,111 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/croatia_flag.svg b/assets/svgs/flags/croatia_flag.svg new file mode 100644 index 0000000..cdf92bb --- /dev/null +++ b/assets/svgs/flags/croatia_flag.svg @@ -0,0 +1,101 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/cuba_flag.svg b/assets/svgs/flags/cuba_flag.svg new file mode 100644 index 0000000..7d1690c --- /dev/null +++ b/assets/svgs/flags/cuba_flag.svg @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/curacao_flag.svg b/assets/svgs/flags/curacao_flag.svg new file mode 100644 index 0000000..3a9aedd --- /dev/null +++ b/assets/svgs/flags/curacao_flag.svg @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/czech_republic_flag.svg b/assets/svgs/flags/czech_republic_flag.svg new file mode 100644 index 0000000..2bde001 --- /dev/null +++ b/assets/svgs/flags/czech_republic_flag.svg @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/democratic_republic_of_congo_flag.svg b/assets/svgs/flags/democratic_republic_of_congo_flag.svg new file mode 100644 index 0000000..207edc6 --- /dev/null +++ b/assets/svgs/flags/democratic_republic_of_congo_flag.svg @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/denmark_flag.svg b/assets/svgs/flags/denmark_flag.svg new file mode 100644 index 0000000..ece427b --- /dev/null +++ b/assets/svgs/flags/denmark_flag.svg @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/djibouti_flag.svg b/assets/svgs/flags/djibouti_flag.svg new file mode 100644 index 0000000..dc52cee --- /dev/null +++ b/assets/svgs/flags/djibouti_flag.svg @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/dominica_flag.svg b/assets/svgs/flags/dominica_flag.svg new file mode 100644 index 0000000..5dc34da --- /dev/null +++ b/assets/svgs/flags/dominica_flag.svg @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/dominican_republic_flag.svg b/assets/svgs/flags/dominican_republic_flag.svg new file mode 100644 index 0000000..ef9e9c0 --- /dev/null +++ b/assets/svgs/flags/dominican_republic_flag.svg @@ -0,0 +1,103 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/east_timor_flag.svg b/assets/svgs/flags/east_timor_flag.svg new file mode 100644 index 0000000..cd99e8c --- /dev/null +++ b/assets/svgs/flags/east_timor_flag.svg @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/ecuador_flag.svg b/assets/svgs/flags/ecuador_flag.svg new file mode 100644 index 0000000..0500822 --- /dev/null +++ b/assets/svgs/flags/ecuador_flag.svg @@ -0,0 +1,87 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/egypt_flag.svg b/assets/svgs/flags/egypt_flag.svg new file mode 100644 index 0000000..48d8c74 --- /dev/null +++ b/assets/svgs/flags/egypt_flag.svg @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/el_salvador_flag.svg b/assets/svgs/flags/el_salvador_flag.svg new file mode 100644 index 0000000..f0d2ca0 --- /dev/null +++ b/assets/svgs/flags/el_salvador_flag.svg @@ -0,0 +1,115 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/england_flag.svg b/assets/svgs/flags/england_flag.svg new file mode 100644 index 0000000..4f146f5 --- /dev/null +++ b/assets/svgs/flags/england_flag.svg @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/equatorial_guinea_flag.svg b/assets/svgs/flags/equatorial_guinea_flag.svg new file mode 100644 index 0000000..7931618 --- /dev/null +++ b/assets/svgs/flags/equatorial_guinea_flag.svg @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/eritrea_flag.svg b/assets/svgs/flags/eritrea_flag.svg new file mode 100644 index 0000000..be4a9e6 --- /dev/null +++ b/assets/svgs/flags/eritrea_flag.svg @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/estonia_flag.svg b/assets/svgs/flags/estonia_flag.svg new file mode 100644 index 0000000..3145db8 --- /dev/null +++ b/assets/svgs/flags/estonia_flag.svg @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/ethiopia_flag.svg b/assets/svgs/flags/ethiopia_flag.svg new file mode 100644 index 0000000..2f617ee --- /dev/null +++ b/assets/svgs/flags/ethiopia_flag.svg @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/european_union_flag.svg b/assets/svgs/flags/european_union_flag.svg new file mode 100644 index 0000000..9cd01c5 --- /dev/null +++ b/assets/svgs/flags/european_union_flag.svg @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/falkland_islands_flag.svg b/assets/svgs/flags/falkland_islands_flag.svg new file mode 100644 index 0000000..7d66b1a --- /dev/null +++ b/assets/svgs/flags/falkland_islands_flag.svg @@ -0,0 +1,79 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/fiji_flag.svg b/assets/svgs/flags/fiji_flag.svg new file mode 100644 index 0000000..4b8d454 --- /dev/null +++ b/assets/svgs/flags/fiji_flag.svg @@ -0,0 +1,85 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/finland_flag.svg b/assets/svgs/flags/finland_flag.svg new file mode 100644 index 0000000..a54a39b --- /dev/null +++ b/assets/svgs/flags/finland_flag.svg @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/france_flag.svg b/assets/svgs/flags/france_flag.svg new file mode 100644 index 0000000..573ba7a --- /dev/null +++ b/assets/svgs/flags/france_flag.svg @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/french_polynesia_flag.svg b/assets/svgs/flags/french_polynesia_flag.svg new file mode 100644 index 0000000..bb9c70e --- /dev/null +++ b/assets/svgs/flags/french_polynesia_flag.svg @@ -0,0 +1,63 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/gabon_flag.svg b/assets/svgs/flags/gabon_flag.svg new file mode 100644 index 0000000..04e05f4 --- /dev/null +++ b/assets/svgs/flags/gabon_flag.svg @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/galapagos_islands_flag.svg b/assets/svgs/flags/galapagos_islands_flag.svg new file mode 100644 index 0000000..323eabf --- /dev/null +++ b/assets/svgs/flags/galapagos_islands_flag.svg @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/gambia_flag.svg b/assets/svgs/flags/gambia_flag.svg new file mode 100644 index 0000000..4164887 --- /dev/null +++ b/assets/svgs/flags/gambia_flag.svg @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/georgia_flag.svg b/assets/svgs/flags/georgia_flag.svg new file mode 100644 index 0000000..da45beb --- /dev/null +++ b/assets/svgs/flags/georgia_flag.svg @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/germany_flag.svg b/assets/svgs/flags/germany_flag.svg new file mode 100644 index 0000000..5748a7a --- /dev/null +++ b/assets/svgs/flags/germany_flag.svg @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/ghana_flag.svg b/assets/svgs/flags/ghana_flag.svg new file mode 100644 index 0000000..f437ca5 --- /dev/null +++ b/assets/svgs/flags/ghana_flag.svg @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/gibraltar_flag.svg b/assets/svgs/flags/gibraltar_flag.svg new file mode 100644 index 0000000..e21fd0f --- /dev/null +++ b/assets/svgs/flags/gibraltar_flag.svg @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/greece_flag.svg b/assets/svgs/flags/greece_flag.svg new file mode 100644 index 0000000..9df38f0 --- /dev/null +++ b/assets/svgs/flags/greece_flag.svg @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/greenland_flag.svg b/assets/svgs/flags/greenland_flag.svg new file mode 100644 index 0000000..03f259f --- /dev/null +++ b/assets/svgs/flags/greenland_flag.svg @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/grenada_flag.svg b/assets/svgs/flags/grenada_flag.svg new file mode 100644 index 0000000..f41e1cc --- /dev/null +++ b/assets/svgs/flags/grenada_flag.svg @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/guam_flag.svg b/assets/svgs/flags/guam_flag.svg new file mode 100644 index 0000000..c8a6dbd --- /dev/null +++ b/assets/svgs/flags/guam_flag.svg @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/guatemala_flag.svg b/assets/svgs/flags/guatemala_flag.svg new file mode 100644 index 0000000..7fa1993 --- /dev/null +++ b/assets/svgs/flags/guatemala_flag.svg @@ -0,0 +1,109 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/guernsey_flag.svg b/assets/svgs/flags/guernsey_flag.svg new file mode 100644 index 0000000..041c2d1 --- /dev/null +++ b/assets/svgs/flags/guernsey_flag.svg @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/guinea_bissau_flag.svg b/assets/svgs/flags/guinea_bissau_flag.svg new file mode 100644 index 0000000..10cf79f --- /dev/null +++ b/assets/svgs/flags/guinea_bissau_flag.svg @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/guinea_flag.svg b/assets/svgs/flags/guinea_flag.svg new file mode 100644 index 0000000..d4859fe --- /dev/null +++ b/assets/svgs/flags/guinea_flag.svg @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/haiti_flag.svg b/assets/svgs/flags/haiti_flag.svg new file mode 100644 index 0000000..c676e9a --- /dev/null +++ b/assets/svgs/flags/haiti_flag.svg @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/hawaii_flag.svg b/assets/svgs/flags/hawaii_flag.svg new file mode 100644 index 0000000..1a791fd --- /dev/null +++ b/assets/svgs/flags/hawaii_flag.svg @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/honduras_flag.svg b/assets/svgs/flags/honduras_flag.svg new file mode 100644 index 0000000..9202d20 --- /dev/null +++ b/assets/svgs/flags/honduras_flag.svg @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/hong_kong_flag.svg b/assets/svgs/flags/hong_kong_flag.svg new file mode 100644 index 0000000..b64516f --- /dev/null +++ b/assets/svgs/flags/hong_kong_flag.svg @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/hungary_flag.svg b/assets/svgs/flags/hungary_flag.svg new file mode 100644 index 0000000..54d4278 --- /dev/null +++ b/assets/svgs/flags/hungary_flag.svg @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/iceland_flag.svg b/assets/svgs/flags/iceland_flag.svg new file mode 100644 index 0000000..56a52cb --- /dev/null +++ b/assets/svgs/flags/iceland_flag.svg @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/india_flag.svg b/assets/svgs/flags/india_flag.svg new file mode 100644 index 0000000..201153e --- /dev/null +++ b/assets/svgs/flags/india_flag.svg @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/indonesia_flag.svg b/assets/svgs/flags/indonesia_flag.svg new file mode 100644 index 0000000..0ccfc6c --- /dev/null +++ b/assets/svgs/flags/indonesia_flag.svg @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/iran_flag.svg b/assets/svgs/flags/iran_flag.svg new file mode 100644 index 0000000..69e764b --- /dev/null +++ b/assets/svgs/flags/iran_flag.svg @@ -0,0 +1,81 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/iraq_flag.svg b/assets/svgs/flags/iraq_flag.svg new file mode 100644 index 0000000..1ee6581 --- /dev/null +++ b/assets/svgs/flags/iraq_flag.svg @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/ireland_flag.svg b/assets/svgs/flags/ireland_flag.svg new file mode 100644 index 0000000..16cbb9d --- /dev/null +++ b/assets/svgs/flags/ireland_flag.svg @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/isle_of_man_flag.svg b/assets/svgs/flags/isle_of_man_flag.svg new file mode 100644 index 0000000..dc99bbd --- /dev/null +++ b/assets/svgs/flags/isle_of_man_flag.svg @@ -0,0 +1,101 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/israel_flag.svg b/assets/svgs/flags/israel_flag.svg new file mode 100644 index 0000000..40fc449 --- /dev/null +++ b/assets/svgs/flags/israel_flag.svg @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/italy_flag.svg b/assets/svgs/flags/italy_flag.svg new file mode 100644 index 0000000..a5cd519 --- /dev/null +++ b/assets/svgs/flags/italy_flag.svg @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/ivory_coast_flag.svg b/assets/svgs/flags/ivory_coast_flag.svg new file mode 100644 index 0000000..1c01b4d --- /dev/null +++ b/assets/svgs/flags/ivory_coast_flag.svg @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/jamaica_flag.svg b/assets/svgs/flags/jamaica_flag.svg new file mode 100644 index 0000000..49e56e1 --- /dev/null +++ b/assets/svgs/flags/jamaica_flag.svg @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/japan_flag.svg b/assets/svgs/flags/japan_flag.svg new file mode 100644 index 0000000..7795309 --- /dev/null +++ b/assets/svgs/flags/japan_flag.svg @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/jersey_flag.svg b/assets/svgs/flags/jersey_flag.svg new file mode 100644 index 0000000..69249f5 --- /dev/null +++ b/assets/svgs/flags/jersey_flag.svg @@ -0,0 +1,89 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/jordan_flag.svg b/assets/svgs/flags/jordan_flag.svg new file mode 100644 index 0000000..8f2889c --- /dev/null +++ b/assets/svgs/flags/jordan_flag.svg @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/kazakhstan_flag.svg b/assets/svgs/flags/kazakhstan_flag.svg new file mode 100644 index 0000000..46fde15 --- /dev/null +++ b/assets/svgs/flags/kazakhstan_flag.svg @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/kenya_flag.svg b/assets/svgs/flags/kenya_flag.svg new file mode 100644 index 0000000..5ab0f68 --- /dev/null +++ b/assets/svgs/flags/kenya_flag.svg @@ -0,0 +1,55 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/kiribati_flag.svg b/assets/svgs/flags/kiribati_flag.svg new file mode 100644 index 0000000..81dbfe7 --- /dev/null +++ b/assets/svgs/flags/kiribati_flag.svg @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/kosovo_flag.svg b/assets/svgs/flags/kosovo_flag.svg new file mode 100644 index 0000000..b2d77fe --- /dev/null +++ b/assets/svgs/flags/kosovo_flag.svg @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/kwait_flag.svg b/assets/svgs/flags/kwait_flag.svg new file mode 100644 index 0000000..d73340d --- /dev/null +++ b/assets/svgs/flags/kwait_flag.svg @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/kyrgyzstan_flag.svg b/assets/svgs/flags/kyrgyzstan_flag.svg new file mode 100644 index 0000000..605b139 --- /dev/null +++ b/assets/svgs/flags/kyrgyzstan_flag.svg @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/laos_flag.svg b/assets/svgs/flags/laos_flag.svg new file mode 100644 index 0000000..b53d0f6 --- /dev/null +++ b/assets/svgs/flags/laos_flag.svg @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/latvia_flag.svg b/assets/svgs/flags/latvia_flag.svg new file mode 100644 index 0000000..e4aeda6 --- /dev/null +++ b/assets/svgs/flags/latvia_flag.svg @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/lebanon_flag.svg b/assets/svgs/flags/lebanon_flag.svg new file mode 100644 index 0000000..75658e5 --- /dev/null +++ b/assets/svgs/flags/lebanon_flag.svg @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/lesotho_flag.svg b/assets/svgs/flags/lesotho_flag.svg new file mode 100644 index 0000000..f1e15d9 --- /dev/null +++ b/assets/svgs/flags/lesotho_flag.svg @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/liberia_flag.svg b/assets/svgs/flags/liberia_flag.svg new file mode 100644 index 0000000..0dc08f3 --- /dev/null +++ b/assets/svgs/flags/liberia_flag.svg @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/libya_flag.svg b/assets/svgs/flags/libya_flag.svg new file mode 100644 index 0000000..e0a0ab0 --- /dev/null +++ b/assets/svgs/flags/libya_flag.svg @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/liechtenstein_flag.svg b/assets/svgs/flags/liechtenstein_flag.svg new file mode 100644 index 0000000..256efd2 --- /dev/null +++ b/assets/svgs/flags/liechtenstein_flag.svg @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/lithuania_flag.svg b/assets/svgs/flags/lithuania_flag.svg new file mode 100644 index 0000000..c7f1292 --- /dev/null +++ b/assets/svgs/flags/lithuania_flag.svg @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/luxembourg_flag.svg b/assets/svgs/flags/luxembourg_flag.svg new file mode 100644 index 0000000..4d7387c --- /dev/null +++ b/assets/svgs/flags/luxembourg_flag.svg @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/macao_flag.svg b/assets/svgs/flags/macao_flag.svg new file mode 100644 index 0000000..c785725 --- /dev/null +++ b/assets/svgs/flags/macao_flag.svg @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/madagascar_flag.svg b/assets/svgs/flags/madagascar_flag.svg new file mode 100644 index 0000000..e578348 --- /dev/null +++ b/assets/svgs/flags/madagascar_flag.svg @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/madeira_flag.svg b/assets/svgs/flags/madeira_flag.svg new file mode 100644 index 0000000..7842329 --- /dev/null +++ b/assets/svgs/flags/madeira_flag.svg @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/malasya_flag.svg b/assets/svgs/flags/malasya_flag.svg new file mode 100644 index 0000000..b68184a --- /dev/null +++ b/assets/svgs/flags/malasya_flag.svg @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/malawi_flag.svg b/assets/svgs/flags/malawi_flag.svg new file mode 100644 index 0000000..5bc8d8b --- /dev/null +++ b/assets/svgs/flags/malawi_flag.svg @@ -0,0 +1,63 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/maldives_flag.svg b/assets/svgs/flags/maldives_flag.svg new file mode 100644 index 0000000..4dfd61d --- /dev/null +++ b/assets/svgs/flags/maldives_flag.svg @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/mali_flag.svg b/assets/svgs/flags/mali_flag.svg new file mode 100644 index 0000000..32601a0 --- /dev/null +++ b/assets/svgs/flags/mali_flag.svg @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/malta_flag.svg b/assets/svgs/flags/malta_flag.svg new file mode 100644 index 0000000..9f1bcfb --- /dev/null +++ b/assets/svgs/flags/malta_flag.svg @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/marshall_island_flag.svg b/assets/svgs/flags/marshall_island_flag.svg new file mode 100644 index 0000000..a20cdc7 --- /dev/null +++ b/assets/svgs/flags/marshall_island_flag.svg @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/martinique_flag.svg b/assets/svgs/flags/martinique_flag.svg new file mode 100644 index 0000000..62d1f10 --- /dev/null +++ b/assets/svgs/flags/martinique_flag.svg @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/mauritania_flag.svg b/assets/svgs/flags/mauritania_flag.svg new file mode 100644 index 0000000..0d0d170 --- /dev/null +++ b/assets/svgs/flags/mauritania_flag.svg @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/mauritius_flag.svg b/assets/svgs/flags/mauritius_flag.svg new file mode 100644 index 0000000..f2fce5a --- /dev/null +++ b/assets/svgs/flags/mauritius_flag.svg @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/melilla_flag.svg b/assets/svgs/flags/melilla_flag.svg new file mode 100644 index 0000000..8764b59 --- /dev/null +++ b/assets/svgs/flags/melilla_flag.svg @@ -0,0 +1,139 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/mexico_flag.svg b/assets/svgs/flags/mexico_flag.svg new file mode 100644 index 0000000..e92f1e1 --- /dev/null +++ b/assets/svgs/flags/mexico_flag.svg @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/micronesia_flag.svg b/assets/svgs/flags/micronesia_flag.svg new file mode 100644 index 0000000..2c1c167 --- /dev/null +++ b/assets/svgs/flags/micronesia_flag.svg @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/moldova_flag.svg b/assets/svgs/flags/moldova_flag.svg new file mode 100644 index 0000000..edb37af --- /dev/null +++ b/assets/svgs/flags/moldova_flag.svg @@ -0,0 +1,89 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/monaco_flag.svg b/assets/svgs/flags/monaco_flag.svg new file mode 100644 index 0000000..bfe4350 --- /dev/null +++ b/assets/svgs/flags/monaco_flag.svg @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/mongolia_flag.svg b/assets/svgs/flags/mongolia_flag.svg new file mode 100644 index 0000000..ee410a1 --- /dev/null +++ b/assets/svgs/flags/mongolia_flag.svg @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/montenegro_flag.svg b/assets/svgs/flags/montenegro_flag.svg new file mode 100644 index 0000000..2deb698 --- /dev/null +++ b/assets/svgs/flags/montenegro_flag.svg @@ -0,0 +1,62 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/montserrat_flag.svg b/assets/svgs/flags/montserrat_flag.svg new file mode 100644 index 0000000..41dea1d --- /dev/null +++ b/assets/svgs/flags/montserrat_flag.svg @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/morocco_flag.svg b/assets/svgs/flags/morocco_flag.svg new file mode 100644 index 0000000..5c058b2 --- /dev/null +++ b/assets/svgs/flags/morocco_flag.svg @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/mozambique_flag.svg b/assets/svgs/flags/mozambique_flag.svg new file mode 100644 index 0000000..b7adfb9 --- /dev/null +++ b/assets/svgs/flags/mozambique_flag.svg @@ -0,0 +1,55 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/myanmar_flag.svg b/assets/svgs/flags/myanmar_flag.svg new file mode 100644 index 0000000..6b5bffb --- /dev/null +++ b/assets/svgs/flags/myanmar_flag.svg @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/namibia_flag.svg b/assets/svgs/flags/namibia_flag.svg new file mode 100644 index 0000000..58d6cbc --- /dev/null +++ b/assets/svgs/flags/namibia_flag.svg @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/nato_flag.svg b/assets/svgs/flags/nato_flag.svg new file mode 100644 index 0000000..a3b79bb --- /dev/null +++ b/assets/svgs/flags/nato_flag.svg @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/nauru_flag.svg b/assets/svgs/flags/nauru_flag.svg new file mode 100644 index 0000000..a2fbc97 --- /dev/null +++ b/assets/svgs/flags/nauru_flag.svg @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/nepal_flag.svg b/assets/svgs/flags/nepal_flag.svg new file mode 100644 index 0000000..3051fef --- /dev/null +++ b/assets/svgs/flags/nepal_flag.svg @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/netherlands_flag.svg b/assets/svgs/flags/netherlands_flag.svg new file mode 100644 index 0000000..318128e --- /dev/null +++ b/assets/svgs/flags/netherlands_flag.svg @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/new_zealand_flag.svg b/assets/svgs/flags/new_zealand_flag.svg new file mode 100644 index 0000000..f975ed3 --- /dev/null +++ b/assets/svgs/flags/new_zealand_flag.svg @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/nicaragua_flag.svg b/assets/svgs/flags/nicaragua_flag.svg new file mode 100644 index 0000000..c7637ae --- /dev/null +++ b/assets/svgs/flags/nicaragua_flag.svg @@ -0,0 +1,82 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/niger_flag.svg b/assets/svgs/flags/niger_flag.svg new file mode 100644 index 0000000..15b32a9 --- /dev/null +++ b/assets/svgs/flags/niger_flag.svg @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/nigeria_flag.svg b/assets/svgs/flags/nigeria_flag.svg new file mode 100644 index 0000000..569ae03 --- /dev/null +++ b/assets/svgs/flags/nigeria_flag.svg @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/niue_flag.svg b/assets/svgs/flags/niue_flag.svg new file mode 100644 index 0000000..aa3ea5e --- /dev/null +++ b/assets/svgs/flags/niue_flag.svg @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/norfolk_island_flag.svg b/assets/svgs/flags/norfolk_island_flag.svg new file mode 100644 index 0000000..95d7051 --- /dev/null +++ b/assets/svgs/flags/norfolk_island_flag.svg @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/north_korea_flag.svg b/assets/svgs/flags/north_korea_flag.svg new file mode 100644 index 0000000..84df7e6 --- /dev/null +++ b/assets/svgs/flags/north_korea_flag.svg @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/northern_cyprus_flag.svg b/assets/svgs/flags/northern_cyprus_flag.svg new file mode 100644 index 0000000..7bcc924 --- /dev/null +++ b/assets/svgs/flags/northern_cyprus_flag.svg @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/northern_marianas_islands_flag.svg b/assets/svgs/flags/northern_marianas_islands_flag.svg new file mode 100644 index 0000000..5f6ba18 --- /dev/null +++ b/assets/svgs/flags/northern_marianas_islands_flag.svg @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/norway_flag.svg b/assets/svgs/flags/norway_flag.svg new file mode 100644 index 0000000..43a37f5 --- /dev/null +++ b/assets/svgs/flags/norway_flag.svg @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/oman_flag.svg b/assets/svgs/flags/oman_flag.svg new file mode 100644 index 0000000..037e410 --- /dev/null +++ b/assets/svgs/flags/oman_flag.svg @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/ossetia_flag.svg b/assets/svgs/flags/ossetia_flag.svg new file mode 100644 index 0000000..15b3680 --- /dev/null +++ b/assets/svgs/flags/ossetia_flag.svg @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/pakistan_flag.svg b/assets/svgs/flags/pakistan_flag.svg new file mode 100644 index 0000000..4715cf0 --- /dev/null +++ b/assets/svgs/flags/pakistan_flag.svg @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/palau_flag.svg b/assets/svgs/flags/palau_flag.svg new file mode 100644 index 0000000..7d39516 --- /dev/null +++ b/assets/svgs/flags/palau_flag.svg @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/palestine_flag.svg b/assets/svgs/flags/palestine_flag.svg new file mode 100644 index 0000000..720463d --- /dev/null +++ b/assets/svgs/flags/palestine_flag.svg @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/panama_flag.svg b/assets/svgs/flags/panama_flag.svg new file mode 100644 index 0000000..757723a --- /dev/null +++ b/assets/svgs/flags/panama_flag.svg @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/papua_new_guinea_flag.svg b/assets/svgs/flags/papua_new_guinea_flag.svg new file mode 100644 index 0000000..187085b --- /dev/null +++ b/assets/svgs/flags/papua_new_guinea_flag.svg @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/paraguay_flag.svg b/assets/svgs/flags/paraguay_flag.svg new file mode 100644 index 0000000..de7ceb2 --- /dev/null +++ b/assets/svgs/flags/paraguay_flag.svg @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/peru_flag.svg b/assets/svgs/flags/peru_flag.svg new file mode 100644 index 0000000..0084958 --- /dev/null +++ b/assets/svgs/flags/peru_flag.svg @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/philippines_flag.svg b/assets/svgs/flags/philippines_flag.svg new file mode 100644 index 0000000..72f2d3d --- /dev/null +++ b/assets/svgs/flags/philippines_flag.svg @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/pitcairn_islands_flag.svg b/assets/svgs/flags/pitcairn_islands_flag.svg new file mode 100644 index 0000000..523eba5 --- /dev/null +++ b/assets/svgs/flags/pitcairn_islands_flag.svg @@ -0,0 +1,113 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/poland_flag.svg b/assets/svgs/flags/poland_flag.svg new file mode 100644 index 0000000..6928411 --- /dev/null +++ b/assets/svgs/flags/poland_flag.svg @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/portugal_flag.svg b/assets/svgs/flags/portugal_flag.svg new file mode 100644 index 0000000..0c1344e --- /dev/null +++ b/assets/svgs/flags/portugal_flag.svg @@ -0,0 +1,55 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/puerto_rico_flag.svg b/assets/svgs/flags/puerto_rico_flag.svg new file mode 100644 index 0000000..d8a494a --- /dev/null +++ b/assets/svgs/flags/puerto_rico_flag.svg @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/qatar_flag.svg b/assets/svgs/flags/qatar_flag.svg new file mode 100644 index 0000000..963cd8b --- /dev/null +++ b/assets/svgs/flags/qatar_flag.svg @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/rapa_nui_flag.svg b/assets/svgs/flags/rapa_nui_flag.svg new file mode 100644 index 0000000..aa0699b --- /dev/null +++ b/assets/svgs/flags/rapa_nui_flag.svg @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/republic_of_macedonia_flag.svg b/assets/svgs/flags/republic_of_macedonia_flag.svg new file mode 100644 index 0000000..c01c693 --- /dev/null +++ b/assets/svgs/flags/republic_of_macedonia_flag.svg @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/republic_of_the_congo_flag.svg b/assets/svgs/flags/republic_of_the_congo_flag.svg new file mode 100644 index 0000000..a0b450e --- /dev/null +++ b/assets/svgs/flags/republic_of_the_congo_flag.svg @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/romania_flag.svg b/assets/svgs/flags/romania_flag.svg new file mode 100644 index 0000000..91db646 --- /dev/null +++ b/assets/svgs/flags/romania_flag.svg @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/russia_flag.svg b/assets/svgs/flags/russia_flag.svg new file mode 100644 index 0000000..441b532 --- /dev/null +++ b/assets/svgs/flags/russia_flag.svg @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/rwanda_flag.svg b/assets/svgs/flags/rwanda_flag.svg new file mode 100644 index 0000000..f0109c5 --- /dev/null +++ b/assets/svgs/flags/rwanda_flag.svg @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/saba_island_flag.svg b/assets/svgs/flags/saba_island_flag.svg new file mode 100644 index 0000000..2ff9477 --- /dev/null +++ b/assets/svgs/flags/saba_island_flag.svg @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/sahrawi_arab_democratic_republic_flag.svg b/assets/svgs/flags/sahrawi_arab_democratic_republic_flag.svg new file mode 100644 index 0000000..5d3cb17 --- /dev/null +++ b/assets/svgs/flags/sahrawi_arab_democratic_republic_flag.svg @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/saint_kitts_and_nevis_flag.svg b/assets/svgs/flags/saint_kitts_and_nevis_flag.svg new file mode 100644 index 0000000..1d3f50b --- /dev/null +++ b/assets/svgs/flags/saint_kitts_and_nevis_flag.svg @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/samoa_flag.svg b/assets/svgs/flags/samoa_flag.svg new file mode 100644 index 0000000..8f1a5cc --- /dev/null +++ b/assets/svgs/flags/samoa_flag.svg @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/san_marino_flag.svg b/assets/svgs/flags/san_marino_flag.svg new file mode 100644 index 0000000..4d71cee --- /dev/null +++ b/assets/svgs/flags/san_marino_flag.svg @@ -0,0 +1,118 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/sao_tome_and_prince_flag.svg b/assets/svgs/flags/sao_tome_and_prince_flag.svg new file mode 100644 index 0000000..bc2e157 --- /dev/null +++ b/assets/svgs/flags/sao_tome_and_prince_flag.svg @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/sardinia_flag.svg b/assets/svgs/flags/sardinia_flag.svg new file mode 100644 index 0000000..798a37d --- /dev/null +++ b/assets/svgs/flags/sardinia_flag.svg @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/saudi_arabia_flag.svg b/assets/svgs/flags/saudi_arabia_flag.svg new file mode 100644 index 0000000..c5eccfb --- /dev/null +++ b/assets/svgs/flags/saudi_arabia_flag.svg @@ -0,0 +1,62 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/scotland_flag.svg b/assets/svgs/flags/scotland_flag.svg new file mode 100644 index 0000000..f15fa7f --- /dev/null +++ b/assets/svgs/flags/scotland_flag.svg @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/senegal_flag.svg b/assets/svgs/flags/senegal_flag.svg new file mode 100644 index 0000000..f467173 --- /dev/null +++ b/assets/svgs/flags/senegal_flag.svg @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/serbia_flag.svg b/assets/svgs/flags/serbia_flag.svg new file mode 100644 index 0000000..32032ab --- /dev/null +++ b/assets/svgs/flags/serbia_flag.svg @@ -0,0 +1,79 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/seychelles_flag.svg b/assets/svgs/flags/seychelles_flag.svg new file mode 100644 index 0000000..67afc80 --- /dev/null +++ b/assets/svgs/flags/seychelles_flag.svg @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/sicily_flag.svg b/assets/svgs/flags/sicily_flag.svg new file mode 100644 index 0000000..5a92f2a --- /dev/null +++ b/assets/svgs/flags/sicily_flag.svg @@ -0,0 +1,93 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/sierra_leone_flag.svg b/assets/svgs/flags/sierra_leone_flag.svg new file mode 100644 index 0000000..c08d8f3 --- /dev/null +++ b/assets/svgs/flags/sierra_leone_flag.svg @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/singapore_flag.svg b/assets/svgs/flags/singapore_flag.svg new file mode 100644 index 0000000..44555c8 --- /dev/null +++ b/assets/svgs/flags/singapore_flag.svg @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/sint_eustatius_flag.svg b/assets/svgs/flags/sint_eustatius_flag.svg new file mode 100644 index 0000000..bd93078 --- /dev/null +++ b/assets/svgs/flags/sint_eustatius_flag.svg @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/sint_maarten_flag.svg b/assets/svgs/flags/sint_maarten_flag.svg new file mode 100644 index 0000000..1ecb12e --- /dev/null +++ b/assets/svgs/flags/sint_maarten_flag.svg @@ -0,0 +1,62 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/slovakia_flag.svg b/assets/svgs/flags/slovakia_flag.svg new file mode 100644 index 0000000..fba150e --- /dev/null +++ b/assets/svgs/flags/slovakia_flag.svg @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/slovenia_flag.svg b/assets/svgs/flags/slovenia_flag.svg new file mode 100644 index 0000000..4eee008 --- /dev/null +++ b/assets/svgs/flags/slovenia_flag.svg @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/solomon_islands_flag.svg b/assets/svgs/flags/solomon_islands_flag.svg new file mode 100644 index 0000000..5a872de --- /dev/null +++ b/assets/svgs/flags/solomon_islands_flag.svg @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/somalia_flag.svg b/assets/svgs/flags/somalia_flag.svg new file mode 100644 index 0000000..400445a --- /dev/null +++ b/assets/svgs/flags/somalia_flag.svg @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/somaliland_flag.svg b/assets/svgs/flags/somaliland_flag.svg new file mode 100644 index 0000000..dd6be97 --- /dev/null +++ b/assets/svgs/flags/somaliland_flag.svg @@ -0,0 +1,64 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/south_africa_flag.svg b/assets/svgs/flags/south_africa_flag.svg new file mode 100644 index 0000000..65a676c --- /dev/null +++ b/assets/svgs/flags/south_africa_flag.svg @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/south_korea_flag.svg b/assets/svgs/flags/south_korea_flag.svg new file mode 100644 index 0000000..96d7b70 --- /dev/null +++ b/assets/svgs/flags/south_korea_flag.svg @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/south_sudan_flag.svg b/assets/svgs/flags/south_sudan_flag.svg new file mode 100644 index 0000000..3a32739 --- /dev/null +++ b/assets/svgs/flags/south_sudan_flag.svg @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/spain_flag.svg b/assets/svgs/flags/spain_flag.svg new file mode 100644 index 0000000..439c850 --- /dev/null +++ b/assets/svgs/flags/spain_flag.svg @@ -0,0 +1,92 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/sri_lanka_flag.svg b/assets/svgs/flags/sri_lanka_flag.svg new file mode 100644 index 0000000..bdf68a5 --- /dev/null +++ b/assets/svgs/flags/sri_lanka_flag.svg @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/st_barts_flag.svg b/assets/svgs/flags/st_barts_flag.svg new file mode 100644 index 0000000..c03a13a --- /dev/null +++ b/assets/svgs/flags/st_barts_flag.svg @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/st_lucia_flag.svg b/assets/svgs/flags/st_lucia_flag.svg new file mode 100644 index 0000000..14db4f7 --- /dev/null +++ b/assets/svgs/flags/st_lucia_flag.svg @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/st_vincent_and_the_grenadines_flag.svg b/assets/svgs/flags/st_vincent_and_the_grenadines_flag.svg new file mode 100644 index 0000000..dcac0b6 --- /dev/null +++ b/assets/svgs/flags/st_vincent_and_the_grenadines_flag.svg @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/sudan_flag.svg b/assets/svgs/flags/sudan_flag.svg new file mode 100644 index 0000000..05b1fe3 --- /dev/null +++ b/assets/svgs/flags/sudan_flag.svg @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/suriname_flag.svg b/assets/svgs/flags/suriname_flag.svg new file mode 100644 index 0000000..27ae032 --- /dev/null +++ b/assets/svgs/flags/suriname_flag.svg @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/swaziland_flag.svg b/assets/svgs/flags/swaziland_flag.svg new file mode 100644 index 0000000..51d6b28 --- /dev/null +++ b/assets/svgs/flags/swaziland_flag.svg @@ -0,0 +1,94 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/sweden_flag.svg b/assets/svgs/flags/sweden_flag.svg new file mode 100644 index 0000000..052f714 --- /dev/null +++ b/assets/svgs/flags/sweden_flag.svg @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/switzerland_flag.svg b/assets/svgs/flags/switzerland_flag.svg new file mode 100644 index 0000000..0a474a1 --- /dev/null +++ b/assets/svgs/flags/switzerland_flag.svg @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/syria_flag.svg b/assets/svgs/flags/syria_flag.svg new file mode 100644 index 0000000..903e09e --- /dev/null +++ b/assets/svgs/flags/syria_flag.svg @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/taiwan_flag.svg b/assets/svgs/flags/taiwan_flag.svg new file mode 100644 index 0000000..bcfdd36 --- /dev/null +++ b/assets/svgs/flags/taiwan_flag.svg @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/tajikistan_flag.svg b/assets/svgs/flags/tajikistan_flag.svg new file mode 100644 index 0000000..4dfb1fd --- /dev/null +++ b/assets/svgs/flags/tajikistan_flag.svg @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/tanzania_flag.svg b/assets/svgs/flags/tanzania_flag.svg new file mode 100644 index 0000000..5e6032c --- /dev/null +++ b/assets/svgs/flags/tanzania_flag.svg @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/thailand_flag.svg b/assets/svgs/flags/thailand_flag.svg new file mode 100644 index 0000000..563982a --- /dev/null +++ b/assets/svgs/flags/thailand_flag.svg @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/tibet_flag.svg b/assets/svgs/flags/tibet_flag.svg new file mode 100644 index 0000000..fb9de4c --- /dev/null +++ b/assets/svgs/flags/tibet_flag.svg @@ -0,0 +1,206 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/togo_flag.svg b/assets/svgs/flags/togo_flag.svg new file mode 100644 index 0000000..ab4a0c8 --- /dev/null +++ b/assets/svgs/flags/togo_flag.svg @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/tokelau_flag.svg b/assets/svgs/flags/tokelau_flag.svg new file mode 100644 index 0000000..7cdd88c --- /dev/null +++ b/assets/svgs/flags/tokelau_flag.svg @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/tonga_flag.svg b/assets/svgs/flags/tonga_flag.svg new file mode 100644 index 0000000..870e1a4 --- /dev/null +++ b/assets/svgs/flags/tonga_flag.svg @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/transnistria_flag.svg b/assets/svgs/flags/transnistria_flag.svg new file mode 100644 index 0000000..3734616 --- /dev/null +++ b/assets/svgs/flags/transnistria_flag.svg @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/trinidad_and_tobago_flag.svg b/assets/svgs/flags/trinidad_and_tobago_flag.svg new file mode 100644 index 0000000..7e98936 --- /dev/null +++ b/assets/svgs/flags/trinidad_and_tobago_flag.svg @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/tunisia_flag.svg b/assets/svgs/flags/tunisia_flag.svg new file mode 100644 index 0000000..3f32eda --- /dev/null +++ b/assets/svgs/flags/tunisia_flag.svg @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/turkey_flag.svg b/assets/svgs/flags/turkey_flag.svg new file mode 100644 index 0000000..ab1d93d --- /dev/null +++ b/assets/svgs/flags/turkey_flag.svg @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/turkmenistan_flag.svg b/assets/svgs/flags/turkmenistan_flag.svg new file mode 100644 index 0000000..f6469ff --- /dev/null +++ b/assets/svgs/flags/turkmenistan_flag.svg @@ -0,0 +1,91 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/turks_and_caicos_flag.svg b/assets/svgs/flags/turks_and_caicos_flag.svg new file mode 100644 index 0000000..ff725af --- /dev/null +++ b/assets/svgs/flags/turks_and_caicos_flag.svg @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/tuvalu_flag.svg b/assets/svgs/flags/tuvalu_flag.svg new file mode 100644 index 0000000..2f1fb9d --- /dev/null +++ b/assets/svgs/flags/tuvalu_flag.svg @@ -0,0 +1,55 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/uganda_flag.svg b/assets/svgs/flags/uganda_flag.svg new file mode 100644 index 0000000..e6ed302 --- /dev/null +++ b/assets/svgs/flags/uganda_flag.svg @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/ukraine_flag.svg b/assets/svgs/flags/ukraine_flag.svg new file mode 100644 index 0000000..89a8fa8 --- /dev/null +++ b/assets/svgs/flags/ukraine_flag.svg @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/united_arab_emirates_flag.svg b/assets/svgs/flags/united_arab_emirates_flag.svg new file mode 100644 index 0000000..5569e5a --- /dev/null +++ b/assets/svgs/flags/united_arab_emirates_flag.svg @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/united_kingdom_flag.svg b/assets/svgs/flags/united_kingdom_flag.svg new file mode 100644 index 0000000..58ad231 --- /dev/null +++ b/assets/svgs/flags/united_kingdom_flag.svg @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/united_nations_flag.svg b/assets/svgs/flags/united_nations_flag.svg new file mode 100644 index 0000000..b7bbdf2 --- /dev/null +++ b/assets/svgs/flags/united_nations_flag.svg @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/united_states_flag.svg b/assets/svgs/flags/united_states_flag.svg new file mode 100644 index 0000000..a57bee3 --- /dev/null +++ b/assets/svgs/flags/united_states_flag.svg @@ -0,0 +1,88 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/uruguay_flag.svg b/assets/svgs/flags/uruguay_flag.svg new file mode 100644 index 0000000..d38b338 --- /dev/null +++ b/assets/svgs/flags/uruguay_flag.svg @@ -0,0 +1,79 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/uzbekistn_flag.svg b/assets/svgs/flags/uzbekistn_flag.svg new file mode 100644 index 0000000..6b96876 --- /dev/null +++ b/assets/svgs/flags/uzbekistn_flag.svg @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/vanuatu_flag.svg b/assets/svgs/flags/vanuatu_flag.svg new file mode 100644 index 0000000..fa37e16 --- /dev/null +++ b/assets/svgs/flags/vanuatu_flag.svg @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/vatican_city_flag.svg b/assets/svgs/flags/vatican_city_flag.svg new file mode 100644 index 0000000..88dcc4d --- /dev/null +++ b/assets/svgs/flags/vatican_city_flag.svg @@ -0,0 +1,96 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/venezuela_flag.svg b/assets/svgs/flags/venezuela_flag.svg new file mode 100644 index 0000000..8b58ab6 --- /dev/null +++ b/assets/svgs/flags/venezuela_flag.svg @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/vietnam_flag.svg b/assets/svgs/flags/vietnam_flag.svg new file mode 100644 index 0000000..33b38f8 --- /dev/null +++ b/assets/svgs/flags/vietnam_flag.svg @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/virgin_islands_flag.svg b/assets/svgs/flags/virgin_islands_flag.svg new file mode 100644 index 0000000..c81045d --- /dev/null +++ b/assets/svgs/flags/virgin_islands_flag.svg @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/wales_flag.svg b/assets/svgs/flags/wales_flag.svg new file mode 100644 index 0000000..f54bdfa --- /dev/null +++ b/assets/svgs/flags/wales_flag.svg @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/yemen_flag.svg b/assets/svgs/flags/yemen_flag.svg new file mode 100644 index 0000000..33bcfd2 --- /dev/null +++ b/assets/svgs/flags/yemen_flag.svg @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/zambia_flag.svg b/assets/svgs/flags/zambia_flag.svg new file mode 100644 index 0000000..b48e4c6 --- /dev/null +++ b/assets/svgs/flags/zambia_flag.svg @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svgs/flags/zimbabwe_flag.svg b/assets/svgs/flags/zimbabwe_flag.svg new file mode 100644 index 0000000..a1c95ac --- /dev/null +++ b/assets/svgs/flags/zimbabwe_flag.svg @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/controllers/grx_animated_loading_button.controller.dart b/lib/controllers/grx_animated_loading_button.controller.dart new file mode 100644 index 0000000..4c31952 --- /dev/null +++ b/lib/controllers/grx_animated_loading_button.controller.dart @@ -0,0 +1,49 @@ +import 'package:flutter/foundation.dart'; +import 'package:rounded_loading_button_plus/rounded_loading_button.dart'; + +class GrxAnimatedLoadingButtonController + extends RoundedLoadingButtonController { + GrxAnimatedLoadingButtonController({ + this.resetStateDuration = const Duration(seconds: 3), + }); + + final Duration? resetStateDuration; + final hasStarted = ValueNotifier(false); + + @override + void start() { + super.start(); + + _setHasStarted(true); + } + + @override + void success() { + super.success(); + + _resetButtonState(); + } + + @override + void error() { + super.error(); + + _resetButtonState(); + } + + void _resetButtonState() { + if (resetStateDuration != null && resetStateDuration!.inMilliseconds > 0) { + Future.delayed(resetStateDuration!, () { + reset(); + _setHasStarted(false); + }); + } + } + + void _setHasStarted(bool value) { + Future.delayed( + const Duration(milliseconds: 300), + () => hasStarted.value = value, + ); + } +} diff --git a/lib/delegates/grx_animated_sliver_header.delegate.dart b/lib/delegates/grx_animated_sliver_header.delegate.dart new file mode 100644 index 0000000..f74b165 --- /dev/null +++ b/lib/delegates/grx_animated_sliver_header.delegate.dart @@ -0,0 +1,67 @@ +import 'dart:math' as math; +import 'dart:ui'; + +import 'package:flutter/material.dart'; + +import '../animations/grx_fade_transition.animation.dart'; + +const double _kToolbarExtent = 60.0; + +class GrxAnimatedSliverHeaderDelegate extends SliverPersistentHeaderDelegate { + GrxAnimatedSliverHeaderDelegate({ + required this.animationController, + required this.builder, + this.topSafePadding = 0.0, + this.toolbarExtent, + }); + + final AnimationController animationController; + final Widget Function(double progress) builder; + final double topSafePadding; + final double? toolbarExtent; + + late final Animation topBarAnimation = + Tween(begin: 0, end: 1).animate( + CurvedAnimation( + parent: animationController, + curve: const Interval(0, 0.6, curve: Curves.fastOutSlowIn), + ), + ); + + @override + Widget build( + BuildContext context, + double shrinkOffset, + bool overlapsContent, + ) { + final progress = clampDouble(shrinkOffset / maxExtent, 0.0, 1.0); + + return FlexibleSpaceBar.createSettings( + minExtent: minExtent, + maxExtent: maxExtent, + currentExtent: math.max(minExtent, maxExtent - shrinkOffset), + toolbarOpacity: progress, + isScrolledUnder: shrinkOffset > maxExtent - minExtent, + child: AnimatedBuilder( + animation: animationController, + child: builder(progress), + builder: (context, child) { + return GrxFadeTransition( + animation: topBarAnimation, + child: child!, + ); + }, + ), + ); + } + + @override + double get maxExtent => (toolbarExtent ?? _kToolbarExtent) + topSafePadding; + + @override + double get minExtent => (toolbarExtent ?? _kToolbarExtent) + topSafePadding; + + @override + bool shouldRebuild(covariant SliverPersistentHeaderDelegate oldDelegate) => + true; +} diff --git a/lib/delegates/grx_searchable_sliver_header.delegate.dart b/lib/delegates/grx_searchable_sliver_header.delegate.dart index 29d194e..c3162dc 100644 --- a/lib/delegates/grx_searchable_sliver_header.delegate.dart +++ b/lib/delegates/grx_searchable_sliver_header.delegate.dart @@ -8,17 +8,20 @@ import '../widgets/buttons/grx_add_button.widget.dart'; import '../widgets/buttons/grx_filter_button.widget.dart'; import '../widgets/headers/grx_searchable_header.widget.dart'; -const double _kToolbarExtent = 130.0; -const double _kFilterFieldExtent = 70.0; +const double _kToolbarExtent = 60.0; +const double _kFilterFieldExtent = 56.0; +const double _kTotalWidgetExtent = 36.0; class GrxSearchableSliverHeaderDelegate extends SliverPersistentHeaderDelegate { const GrxSearchableSliverHeaderDelegate({ required this.animationController, required this.title, required this.filterButtonText, + this.topSafePadding = 0.0, this.onFilter, this.onAdd, this.onQuickSearchHandler, + this.onTotalWidgetBuilder, this.hintText, this.canPop = false, }); @@ -26,9 +29,11 @@ class GrxSearchableSliverHeaderDelegate extends SliverPersistentHeaderDelegate { final AnimationController animationController; final String title; final String filterButtonText; + final double topSafePadding; final void Function()? onFilter; final void Function()? onAdd; final void Function(String)? onQuickSearchHandler; + final Widget Function(double progress)? onTotalWidgetBuilder; final String? hintText; final bool canPop; @@ -67,17 +72,28 @@ class GrxSearchableSliverHeaderDelegate extends SliverPersistentHeaderDelegate { ), ], onQuickSearchHandler: onQuickSearchHandler, + extraWidget: onTotalWidgetBuilder?.call(progress), ), ); } @override double get maxExtent => - _kToolbarExtent + (onQuickSearchHandler != null ? _kFilterFieldExtent : 0); + _kToolbarExtent + + topSafePadding + + (onQuickSearchHandler != null + ? _kFilterFieldExtent + (onTotalWidgetBuilder == null ? 8.0 : 0.0) + : 0.0) + + (onTotalWidgetBuilder != null ? _kTotalWidgetExtent : 0.0); @override double get minExtent => - _kToolbarExtent + (onQuickSearchHandler != null ? _kFilterFieldExtent : 0); + _kToolbarExtent + + topSafePadding + + (onQuickSearchHandler != null + ? _kFilterFieldExtent + (onTotalWidgetBuilder == null ? 8.0 : 0.0) + : 0.0) + + (onTotalWidgetBuilder != null ? _kTotalWidgetExtent : 0); @override bool shouldRebuild(covariant SliverPersistentHeaderDelegate oldDelegate) => diff --git a/lib/enums/grx_country_id.enum.dart b/lib/enums/grx_country_id.enum.dart new file mode 100644 index 0000000..eece9d5 --- /dev/null +++ b/lib/enums/grx_country_id.enum.dart @@ -0,0 +1,220 @@ +// ignore_for_file: constant_identifier_names + +export '../extensions/grx_country_id.extension.dart'; + +enum GrxCountryId { + AE, + AF, + ZA, + AL, + DE, + AD, + AO, + AI, + AG, + SA, + DZ, + AR, + AM, + AW, + AU, + AT, + AZ, + BS, + BD, + BB, + BH, + BE, + BZ, + BJ, + BM, + BY, + BO, + BA, + BW, + BR, + BN, + BG, + BI, + BT, + CA, + CC, + CI, + CK, + CL, + CN, + CR, + CY, + CO, + CU, + CX, + DJ, + DK, + DM, + EC, + EE, + EG, + ER, + ES, + ET, + FI, + FJ, + FR, + GA, + GD, + GE, + GH, + GI, + GL, + GM, + GN, + GR, + GU, + GT, + GW, + HK, + HR, + HN, + HT, + HU, + KH, + KM, + KP, + KR, + KY, + KZ, + MH, + MP, + MV, + NF, + NL, + PH, + SB, + SI, + SV, + SK, + US, + TD, + VG, + VI, + YE, + IN, + ID, + IR, + IQ, + IE, + ISL, + IL, + IT, + JM, + JP, + JO, + KI, + KW, + LA, + LS, + LV, + LB, + LR, + LY, + LI, + LT, + LU, + MO, + MK, + MG, + MY, + ML, + MW, + MT, + MA, + MQ, + MU, + MR, + MX, + FM, + MZ, + MD, + MC, + MN, + ME, + MS, + MM, + NA, + NR, + NP, + NI, + NE, + NG, + NU, + NO, + NZ, + OM, + PW, + PS, + PA, + PG, + PK, + PY, + PE, + PF, + PL, + PR, + PT, + QA, + KE, + KG, + GB, + CF, + DO, + CZ, + RO, + RW, + RU, + WS, + AS, + LC, + KN, + SM, + ST, + VC, + SC, + SN, + SL, + RS, + SG, + SY, + SO, + LK, + SD, + SS, + SE, + CH, + SR, + TJ, + TH, + TW, + TZ, + IO, + TL, + TG, + TK, + TO, + TT, + TN, + TC, + TM, + TR, + TV, + UA, + UG, + UY, + UZ, + VU, + VA, + VE, + VN, + ZM, + ZW, + unknown, +} diff --git a/lib/extensions/grx_country_id.extension.dart b/lib/extensions/grx_country_id.extension.dart new file mode 100644 index 0000000..dea121a --- /dev/null +++ b/lib/extensions/grx_country_id.extension.dart @@ -0,0 +1,8 @@ +import '../enums/grx_country_id.enum.dart'; + +extension GrxCountryIdExtension on GrxCountryId { + GrxCountryId getValue(String? value) => GrxCountryId.values.firstWhere( + (id) => id.name.toUpperCase() == value?.toUpperCase(), + orElse: () => GrxCountryId.BR, + ); +} diff --git a/lib/extensions/list.extension.dart b/lib/extensions/list.extension.dart new file mode 100644 index 0000000..1899c20 --- /dev/null +++ b/lib/extensions/list.extension.dart @@ -0,0 +1,6 @@ +extension ListExtension on List { + void assignAll(final Iterable items) { + clear(); + addAll(items); + } +} diff --git a/lib/grex_ds.dart b/lib/grex_ds.dart index 53b4279..2760a8f 100644 --- a/lib/grex_ds.dart +++ b/lib/grex_ds.dart @@ -1,14 +1,24 @@ library grex_ds; -export 'package:rounded_loading_button/rounded_loading_button.dart' - show RoundedLoadingButtonController; +export 'package:infinite_scroll_pagination/infinite_scroll_pagination.dart'; -export 'enums/grx_align.enum.dart' show GrxAlign; +/// Animations +export 'animations/grx_fade_transition.animation.dart' show GrxFadeTransition; +/// Controllers +export 'controllers/grx_animated_loading_button.controller.dart' + show GrxAnimatedLoadingButtonController; /// Enums +export 'enums/grx_align.enum.dart' show GrxAlign; +export 'enums/grx_country_id.enum.dart' show GrxCountryId; export 'enums/grx_text_transform.enum.dart' show GrxTextTransform; +export 'extensions/grx_country_id.extension.dart' show GrxCountryIdExtension; /// Extensions export 'extensions/uint8_list.extension.dart' show Uint8ListExtension; +/// Models +export 'models/grx_country.model.dart' show GrxCountry; +export 'models/grx_federative_unit.model.dart' show GrxFederativeUnit; /// Services +export 'services/grx_bottom_sheet.service.dart' show GrxBottomSheetService; export 'services/grx_image_picker.service.dart' show GrxImagePickerService; export 'services/grx_toast.service.dart' show GrxToastService; /// Themes/Colors @@ -46,6 +56,7 @@ export 'themes/typography/styles/grx_text.style.dart' show GrxTextStyle; /// Themes/Typography/Utils export 'themes/typography/utils/grx_font_families.dart' show GrxFontFamilies; export 'themes/typography/utils/grx_font_weights.dart' show GrxFontWeights; +export 'utils/grx_country.util.dart' show GrxCountryUtils; export 'utils/grx_linkify.util.dart' show GrxLinkify; export 'utils/grx_regex.util.dart' show GrxRegexUtils; /// Utils @@ -78,20 +89,28 @@ export 'widgets/checkbox/grx_rounded_checkbox.widget.dart' /// Widgets/Cupertino export 'widgets/cupertino/cupertino_switch_list_tile.dart' show CupertinoSwitchListTile; +/// Widget/Fields/Controllers +export 'widgets/fields/controllers/grx_form_field.controller.dart' + show GrxFormFieldController; +export 'widgets/fields/grx_autocomplete_dropdown_form_field.widget.dart' + show GrxAutocompleteDropdownFormField; +/// Widgets/Fields export 'widgets/fields/grx_custom_dropdown_form_field.widget.dart' show GrxCustomDropdownFormField; export 'widgets/fields/grx_date_time_picker_form_field.widget.dart' show GrxDateTimePickerFormField; export 'widgets/fields/grx_dropdown_form_field.widget.dart' show GrxDropdownFormField; -export 'widgets/fields/grx_filter_field.widget.dart' show GrxFilterField; export 'widgets/fields/grx_multi_select_form_field.widget.dart' show GrxMultiSelectFormField; +export 'widgets/fields/grx_phone_form_field.widget.dart' show GrxPhoneFormField; +export 'widgets/fields/grx_search_field.widget.dart' show GrxSearchField; export 'widgets/fields/grx_switch_form_field.widget.dart' show GrxSwitchFormField; -/// Widgets/Fields export 'widgets/fields/grx_text_field.widget.dart' show GrxTextField; export 'widgets/fields/grx_text_form_field.widget.dart' show GrxTextFormField; +///Widgets/Card +export 'widgets/grx_card.widget.dart' show GrxCard; /// Widget/Chip export 'widgets/grx_chip.widget.dart' show GrxChip; /// Widget/DashedDivider @@ -101,15 +120,29 @@ export 'widgets/grx_dismissible_scaffold.widget.dart' show GrxDismissibleScaffold; /// Widget/Divider export 'widgets/grx_divider.widget.dart' show GrxDivider; +/// Widgets/Help +export 'widgets/grx_help.widget.dart' show GrxHelpWidget; +/// Widgets/Lists +export 'widgets/grx_sliver_animated_list.widget.dart' + show GrxSliverAnimatedList; +/// Widget/Loading +export 'widgets/grx_spinner_loading.widget.dart' show GrxSpinnerLoading; /// Widget/Avatar export 'widgets/grx_user_avatar.widget.dart' show GrxUserAvatar; +export 'widgets/headers/grx_animated_sliver_header.widget.dart' + show GrxAnimatedSliverHeader; /// Widget/Headers export 'widgets/headers/grx_header.widget.dart' show GrxHeader; export 'widgets/headers/grx_searchable_header.widget.dart' show GrxSearchableHeader; export 'widgets/headers/grx_searchable_sliver_header.widget.dart' show GrxSearchableSliverHeader; -///Widgets/Media +/// Widgets/Layout +export 'widgets/layout/grx_responsive_layout.widget.dart' + show GrxResponsiveLayout; +export 'widgets/list/grx_list_empty.widget.dart' show GrxListEmpty; +export 'widgets/list/grx_list_error.widget.dart' show GrxListError; +/// Widgets/Media export 'widgets/media/grx_svg.widget.dart' show GrxSvg; /// Widgets/Typography export 'widgets/typography/grx_body_text.widget.dart' show GrxBodyText; diff --git a/lib/models/grx_button_options.model.dart b/lib/models/grx_button_options.model.dart new file mode 100644 index 0000000..5d39502 --- /dev/null +++ b/lib/models/grx_button_options.model.dart @@ -0,0 +1,19 @@ +import 'package:flutter/widgets.dart'; + +import '../themes/colors/grx_colors.dart'; + +class GrxButtonOptions { + const GrxButtonOptions({ + required this.title, + this.onPressed, + this.icon, + this.backgroundColor, + this.foregroundColor = GrxColors.cffffffff, + }); + + final String title; + final Color foregroundColor; + final VoidCallback? onPressed; + final IconData? icon; + final Color? backgroundColor; +} diff --git a/lib/models/grx_country.model.dart b/lib/models/grx_country.model.dart new file mode 100644 index 0000000..d6faccb --- /dev/null +++ b/lib/models/grx_country.model.dart @@ -0,0 +1,53 @@ +import 'dart:convert'; + +import '../enums/grx_country_id.enum.dart'; +import 'grx_federative_unit.model.dart'; + +class GrxCountry { + const GrxCountry({ + required this.id, + required this.code, + required this.name, + required this.flag, + this.language, + this.phoneMasks = const [], + this.zipcodeMasks = const [], + this.states = const [], + }); + + final GrxCountryId id; + final String code; + final String name; + final String flag; + final String? language; + final List phoneMasks; + final List zipcodeMasks; + final List states; + + GrxCountry.fromJson(Map json) + : id = GrxCountryId.unknown.getValue(json['id']), + code = json['code'], + name = json['name'], + flag = json['flag'], + language = json['language'], + phoneMasks = json['phoneMasks'] ?? [], + zipcodeMasks = json['zipcodeMasks'] ?? [], + states = List.from(json['states'] ?? []) + .map((x) => GrxFederativeUnit.fromJson(x)) + .toList(); + + Map toJson() { + return { + 'id': id.name, + 'code': code, + 'name': name, + 'flag': flag, + 'language': language, + 'phoneMasks': phoneMasks, + 'zipcodeMasks': zipcodeMasks, + 'states': states.map>((e) => e.toJson()), + }; + } + + String stringify() => json.encode(toJson()); +} diff --git a/lib/models/grx_federative_unit.model.dart b/lib/models/grx_federative_unit.model.dart new file mode 100644 index 0000000..3de3226 --- /dev/null +++ b/lib/models/grx_federative_unit.model.dart @@ -0,0 +1,18 @@ +class GrxFederativeUnit { + const GrxFederativeUnit({ + required this.id, + required this.name, + }); + + final String id; + final String name; + + GrxFederativeUnit.fromJson(Map json) + : id = json['id'], + name = json['name']; + + Map toJson() => { + 'id': id, + 'name': name, + }; +} diff --git a/lib/services/grx_bottom_sheet.service.dart b/lib/services/grx_bottom_sheet.service.dart index 36bd3b4..573c4de 100644 --- a/lib/services/grx_bottom_sheet.service.dart +++ b/lib/services/grx_bottom_sheet.service.dart @@ -16,18 +16,13 @@ class GrxBottomSheetService { final String? title; final Color backgroundColor; - bool isBottomSheetOpen = false; + bool isOpened = false; Widget _buildBottomSheet({ ScrollController? controller, final bool hideGrabber = false, }) { - final view = View.of(context); - return Container( - margin: EdgeInsets.only( - top: MediaQueryData.fromView(view).padding.top + 10, - ), decoration: _border(), child: Column( mainAxisSize: MainAxisSize.min, @@ -64,7 +59,7 @@ class GrxBottomSheetService { final double minSize = 0.25, final double initSize = 1.0, }) { - isBottomSheetOpen = true; + isOpened = true; return showModalBottomSheet( backgroundColor: Colors.transparent, @@ -80,48 +75,53 @@ class GrxBottomSheetService { ); }, ).then((value) { - isBottomSheetOpen = false; + isOpened = false; return value; }); } - Future showUndisposable() { - isBottomSheetOpen = true; + Future showUndisposable({ + final bool isScrollControlled = true, + }) { + isOpened = true; return showModalBottomSheet( context: context, backgroundColor: Colors.transparent, - isScrollControlled: true, + isScrollControlled: isScrollControlled, enableDrag: false, isDismissible: false, - builder: (_) => WillPopScope( - onWillPop: () async => false, + builder: (_) => PopScope( + canPop: false, child: _buildBottomSheet( hideGrabber: true, ), ), ).then((value) { - isBottomSheetOpen = false; + isOpened = false; return value; }); } - Future show() { - isBottomSheetOpen = true; + Future show({ + final bool isScrollControlled = true, + }) { + isOpened = true; return showModalBottomSheet( context: context, backgroundColor: Colors.transparent, - isScrollControlled: true, + isScrollControlled: isScrollControlled, + useSafeArea: true, builder: (_) => _buildBottomSheet(), ).then((value) { - isBottomSheetOpen = false; + isOpened = false; return value; }); } void dispose() { - if (isBottomSheetOpen) { + if (isOpened) { Navigator.of(context).pop(); } } diff --git a/lib/services/grx_static_values.service.dart b/lib/services/grx_static_values.service.dart new file mode 100644 index 0000000..d929a91 --- /dev/null +++ b/lib/services/grx_static_values.service.dart @@ -0,0 +1,158 @@ +import '../models/grx_federative_unit.model.dart'; + +abstract class GrxStaticValuesService { + static const brStates = [ + GrxFederativeUnit(id: 'AC', name: 'Acre'), + GrxFederativeUnit(id: 'AL', name: 'Alagoas'), + GrxFederativeUnit(id: 'AP', name: 'Amapá'), + GrxFederativeUnit(id: 'AM', name: 'Amazonas'), + GrxFederativeUnit(id: 'BA', name: 'Bahía'), + GrxFederativeUnit(id: 'CE', name: 'Ceará'), + GrxFederativeUnit(id: 'DF', name: 'Distrito Federal'), + GrxFederativeUnit(id: 'ES', name: 'Espírito Santo'), + GrxFederativeUnit(id: 'GO', name: 'Goiás'), + GrxFederativeUnit(id: 'MA', name: 'Maranhão'), + GrxFederativeUnit(id: 'MT', name: 'Mato Grosso'), + GrxFederativeUnit(id: 'MS', name: 'Mato Grosso do Sul'), + GrxFederativeUnit(id: 'MG', name: 'Minas Geraís'), + GrxFederativeUnit(id: 'PA', name: 'Pará'), + GrxFederativeUnit(id: 'PB', name: 'Paraíba'), + GrxFederativeUnit(id: 'PR', name: 'Paraná'), + GrxFederativeUnit(id: 'PE', name: 'Pernambuco'), + GrxFederativeUnit(id: 'PI', name: 'Piauí'), + GrxFederativeUnit(id: 'RJ', name: 'Rio de Janeiro'), + GrxFederativeUnit(id: 'RN', name: 'Rio Grande do Norte'), + GrxFederativeUnit(id: 'RS', name: 'Rio Grande do Sul'), + GrxFederativeUnit(id: 'RO', name: 'Rondônia'), + GrxFederativeUnit(id: 'RR', name: 'Roraima'), + GrxFederativeUnit(id: 'SC', name: 'Santa Catarina'), + GrxFederativeUnit(id: 'SP', name: 'São Paulo'), + GrxFederativeUnit(id: 'SE', name: 'Sergipe'), + GrxFederativeUnit(id: 'TO', name: 'Tocantins'), + GrxFederativeUnit(id: 'UKN', name: 'Não Informado'), + ]; + + static const usStates = [ + GrxFederativeUnit(id: 'AL', name: 'Alabama'), + GrxFederativeUnit(id: 'AK', name: 'Alaska'), + GrxFederativeUnit(id: 'AZ', name: 'Arizona'), + GrxFederativeUnit(id: 'AR', name: 'Arkansas'), + GrxFederativeUnit(id: 'CA', name: 'California'), + GrxFederativeUnit(id: 'CZ', name: 'Canal Zone'), + GrxFederativeUnit(id: 'CO', name: 'Colorado'), + GrxFederativeUnit(id: 'CT', name: 'Connecticut'), + GrxFederativeUnit(id: 'DE', name: 'Delaware'), + GrxFederativeUnit(id: 'DC', name: 'District of Columbia'), + GrxFederativeUnit(id: 'FL', name: 'Florida'), + GrxFederativeUnit(id: 'GA', name: 'Georgia'), + GrxFederativeUnit(id: 'GU', name: 'Guam'), + GrxFederativeUnit(id: 'HI', name: 'Hawaii'), + GrxFederativeUnit(id: 'ID', name: 'Idaho'), + GrxFederativeUnit(id: 'IL', name: 'Illinois'), + GrxFederativeUnit(id: 'IN', name: 'Indiana'), + GrxFederativeUnit(id: 'IA', name: 'Iowa'), + GrxFederativeUnit(id: 'KS', name: 'Kansas'), + GrxFederativeUnit(id: 'KY', name: 'Kentucky'), + GrxFederativeUnit(id: 'LA', name: 'Louisiana'), + GrxFederativeUnit(id: 'ME', name: 'Maine'), + GrxFederativeUnit(id: 'MD', name: 'Maryland'), + GrxFederativeUnit(id: 'MA', name: 'Massachusetts'), + GrxFederativeUnit(id: 'MI', name: 'Michigan'), + GrxFederativeUnit(id: 'MN', name: 'Minnesota'), + GrxFederativeUnit(id: 'MS', name: 'Mississippi'), + GrxFederativeUnit(id: 'MO', name: 'Missouri'), + GrxFederativeUnit(id: 'MT', name: 'Montana'), + GrxFederativeUnit(id: 'NE', name: 'Nebraska'), + GrxFederativeUnit(id: 'NV', name: 'Nevada'), + GrxFederativeUnit(id: 'NH', name: 'New Hampshire'), + GrxFederativeUnit(id: 'NJ', name: 'New Jersey'), + GrxFederativeUnit(id: 'NM', name: 'New Mexico'), + GrxFederativeUnit(id: 'NY', name: 'New York'), + GrxFederativeUnit(id: 'NC', name: 'North Carolina'), + GrxFederativeUnit(id: 'ND', name: 'North Dakota'), + GrxFederativeUnit(id: 'OH', name: 'Ohio'), + GrxFederativeUnit(id: 'OK', name: 'Oklahoma'), + GrxFederativeUnit(id: 'OR', name: 'Oregon'), + GrxFederativeUnit(id: 'PA', name: 'Pennsylvania'), + GrxFederativeUnit(id: 'PR', name: 'Puerto Rico'), + GrxFederativeUnit(id: 'RI', name: 'Rhode Island'), + GrxFederativeUnit(id: 'SC', name: 'South Carolina'), + GrxFederativeUnit(id: 'SD', name: 'South Dakota'), + GrxFederativeUnit(id: 'TN', name: 'Tennessee'), + GrxFederativeUnit(id: 'TX', name: 'Texas'), + GrxFederativeUnit(id: 'UT', name: 'Utah'), + GrxFederativeUnit(id: 'VT', name: 'Vermont'), + GrxFederativeUnit(id: 'VI', name: 'Virgin Islands'), + GrxFederativeUnit(id: 'VA', name: 'Virginia'), + GrxFederativeUnit(id: 'WA', name: 'Washington'), + GrxFederativeUnit(id: 'WV', name: 'West Virginia'), + GrxFederativeUnit(id: 'WI', name: 'Wisconsin'), + GrxFederativeUnit(id: 'WY', name: 'Wyoming'), + GrxFederativeUnit(id: 'UKN', name: 'Não Informado'), + ]; + + static const arStates = [ + GrxFederativeUnit(id: 'DF', name: 'Autonomous City of Buenos Aires'), + GrxFederativeUnit(id: 'BA', name: 'Buenos Aires'), + GrxFederativeUnit(id: 'CT', name: 'Catamarca'), + GrxFederativeUnit(id: 'CC', name: 'Chaco'), + GrxFederativeUnit(id: 'CH', name: 'Chubut'), + GrxFederativeUnit(id: 'CB', name: 'Córdoba'), + GrxFederativeUnit(id: 'CN', name: 'Corrientes'), + GrxFederativeUnit(id: 'ER', name: 'Entre Ríos'), + GrxFederativeUnit(id: 'FM', name: 'Formosa'), + GrxFederativeUnit(id: 'JY', name: 'Jujuy'), + GrxFederativeUnit(id: 'LP', name: 'La Pampa'), + GrxFederativeUnit(id: 'LR', name: 'La Rioja'), + GrxFederativeUnit(id: 'MZ', name: 'Mendoza'), + GrxFederativeUnit(id: 'MN', name: 'Misiones'), + GrxFederativeUnit(id: 'NQ', name: 'Neuquén'), + GrxFederativeUnit(id: 'RN', name: 'Río Negro'), + GrxFederativeUnit(id: 'SA', name: 'Salta'), + GrxFederativeUnit(id: 'SJ', name: 'San Juan'), + GrxFederativeUnit(id: 'SL', name: 'San Luis'), + GrxFederativeUnit(id: 'SC', name: 'Santa Cruz'), + GrxFederativeUnit(id: 'SF', name: 'Santa Fe'), + GrxFederativeUnit(id: 'SE', name: 'Santiago del Estero'), + GrxFederativeUnit( + id: 'TF', + name: 'Tierra del Fuego, Antártida e Islas del Atlántico Sur'), + GrxFederativeUnit(id: 'TM', name: 'Tucumán'), + ]; + + static const uyStates = [ + GrxFederativeUnit(id: 'AR', name: 'Artigas'), + GrxFederativeUnit(id: 'CA', name: 'Canelones'), + GrxFederativeUnit(id: 'CL', name: 'Cerro Largo'), + GrxFederativeUnit(id: 'CO', name: 'Colonia'), + GrxFederativeUnit(id: 'DU', name: 'Durazno'), + GrxFederativeUnit(id: 'FS', name: 'Flores'), + GrxFederativeUnit(id: 'FD', name: 'Florida'), + GrxFederativeUnit(id: 'LA', name: 'Lavalleja'), + GrxFederativeUnit(id: 'MA', name: 'Maldonado'), + GrxFederativeUnit(id: 'MO', name: 'Montevideo'), + GrxFederativeUnit(id: 'PA', name: 'Paysandú'), + GrxFederativeUnit(id: 'RN', name: 'Río Negro'), + GrxFederativeUnit(id: 'RV', name: 'Rivera'), + GrxFederativeUnit(id: 'RO', name: 'Rocha'), + GrxFederativeUnit(id: 'SA', name: 'Salto'), + GrxFederativeUnit(id: 'SJ', name: 'San José'), + GrxFederativeUnit(id: 'SO', name: 'Soriano'), + GrxFederativeUnit(id: 'TA', name: 'Tacuarembó'), + GrxFederativeUnit(id: 'TT', name: 'Treinta y Tres'), + ]; + + static const mzStates = [ + GrxFederativeUnit(id: '1', name: '1 - Niassa'), + GrxFederativeUnit(id: '2', name: '2 - Cabo Delgado'), + GrxFederativeUnit(id: '3', name: '3 - Nampula'), + GrxFederativeUnit(id: '4', name: '4 - Zambézia'), + GrxFederativeUnit(id: '5', name: '5 - Tete'), + GrxFederativeUnit(id: '6', name: '6 - Manica'), + GrxFederativeUnit(id: '7', name: '7 - Sofala'), + GrxFederativeUnit(id: '8', name: '8 - Inhambane'), + GrxFederativeUnit(id: '9', name: '9 - Gaza'), + GrxFederativeUnit(id: '10', name: '10 - Maputo'), + GrxFederativeUnit(id: '11', name: '11 - Maputo'), + ]; +} diff --git a/lib/services/grx_toast.service.dart b/lib/services/grx_toast.service.dart index 8b932da..c7f812a 100644 --- a/lib/services/grx_toast.service.dart +++ b/lib/services/grx_toast.service.dart @@ -1,4 +1,5 @@ -import 'package:another_flushbar/flushbar.dart'; +import 'package:delightful_toast/delight_toast.dart'; +import 'package:delightful_toast/toast/components/toast_card.dart'; import 'package:flutter/services.dart'; import 'package:flutter/widgets.dart'; @@ -14,61 +15,68 @@ abstract class GrxToastService { static void init(BuildContext context) => _context = context; static void showError({ - required String message, - String? title, + required String title, + String? subtitle, Duration? toastDuration, BuildContext? context, + bool permanent = false, }) => _show( - message: message, + title: title, icon: _getIcon(GrxIcons.cancel), backgroundColor: GrxColors.cffffa5a5, - title: title, + subtitle: subtitle, toastDuration: toastDuration, context: context, + permanent: permanent, ); static void showWarning({ - required String message, - String? title, + required String title, + String? subtitle, Duration? toastDuration, BuildContext? context, + bool permanent = false, }) => _show( - message: message, + title: title, icon: _getIcon(GrxIcons.warning_amber), backgroundColor: GrxColors.fffff6a8, - title: title, + subtitle: subtitle, toastDuration: toastDuration, context: context, + permanent: permanent, ); static void showSuccess({ - required String message, - String? title, + required String title, + String? subtitle, Duration? toastDuration, BuildContext? context, + bool permanent = false, }) => _show( - message: message, + title: title, icon: _getIcon(GrxIcons.check_circle_outline), backgroundColor: GrxColors.cff90e6bc, - title: title, + subtitle: subtitle, toastDuration: toastDuration, context: context, + permanent: permanent, ); static void _show({ - required String message, + required String title, required Icon icon, required Color backgroundColor, - String? title, + String? subtitle, Duration? toastDuration, BuildContext? context, + bool permanent = false, }) { _validateContext(context); - int milliseconds = (message.length * 100 + (title?.length ?? 0) * 100); + int milliseconds = (title.length * 100 + (subtitle?.length ?? 0) * 100); if (milliseconds <= 3000) { milliseconds = 3000; @@ -81,33 +89,62 @@ abstract class GrxToastService { final buildContext = (context ?? _context)!; - Flushbar( - titleText: (title?.isNotEmpty ?? false) - ? GrxHeadlineSmallText( - title!, - color: GrxColors.cff202c44, - ) - : null, - messageText: GrxCaptionLargeText( - message, - color: GrxColors.cff202c44, - ), - flushbarPosition: FlushbarPosition.BOTTOM, - flushbarStyle: FlushbarStyle.GROUNDED, - backgroundColor: backgroundColor, - mainButton: GrxIconButton( - icon: GrxIcons.close, - color: GrxColors.cff202c44, - onPressed: Navigator.of(buildContext).pop, - ), - shouldIconPulse: false, - padding: const EdgeInsets.symmetric( - vertical: 18.0, - horizontal: 16.0, + // Flushbar( + // titleText: (title?.isNotEmpty ?? false) + // ? GrxHeadlineSmallText( + // title!, + // color: GrxColors.cff202c44, + // ) + // : null, + // messageText: GrxCaptionLargeText( + // message, + // color: GrxColors.cff202c44, + // ), + // flushbarPosition: FlushbarPosition.BOTTOM, + // flushbarStyle: FlushbarStyle.GROUNDED, + // backgroundColor: backgroundColor, + // mainButton: GrxIconButton( + // icon: GrxIcons.close, + // color: GrxColors.cff202c44, + // onPressed: Navigator.of(buildContext).pop, + // ), + // shouldIconPulse: false, + // padding: const EdgeInsets.symmetric( + // vertical: 18.0, + // horizontal: 16.0, + // ), + // icon: icon, + // duration: duration, + // ).show(buildContext); + + DelightToastBar? toast; + + toast = DelightToastBar( + autoDismiss: !permanent, + snackbarDuration: + permanent ? const Duration(milliseconds: 5000) : duration, + builder: (context) => ToastCard( + leading: icon, + title: GrxCaptionLargeText( + title, + color: GrxColors.cff202c44, + overflow: TextOverflow.visible, + ), + subtitle: (subtitle?.isNotEmpty ?? false) + ? GrxHeadlineSmallText( + subtitle!, + color: GrxColors.cff202c44, + overflow: TextOverflow.visible, + ) + : null, + trailing: GrxIconButton( + icon: GrxIcons.close, + color: GrxColors.cff202c44, + onPressed: () => toast?.remove(), + ), + color: backgroundColor, ), - icon: icon, - duration: duration, - ).show(buildContext); + )..show(buildContext); } static Icon _getIcon(IconData data) => Icon( diff --git a/lib/themes/colors/grx_colors.dart b/lib/themes/colors/grx_colors.dart index f1c3ab2..a1884eb 100644 --- a/lib/themes/colors/grx_colors.dart +++ b/lib/themes/colors/grx_colors.dart @@ -32,8 +32,11 @@ abstract class GrxColors { static const Color cff202c44 = Color(0xff202c44); static const Color cff365278 = Color(0xff365278); static const Color cff289fff = Color(0xff289fff); + static const Color cff429af1 = Color(0xff429af1); + static const Color cff50a2f2 = Color(0xff50a2f2); static const Color cff5c95e4 = Color(0xff5c95e4); static const Color cff6bbaf0 = Color(0xff6bbaf0); + static const Color cffa3d1ff = Color(0xffa3d1ff); static const Color cffc8e2ff = Color(0xffc8e2ff); static const Color cff83a6cf = Color(0xff83a6cf); static const Color cff7593b5 = Color(0xff7593b5); @@ -44,6 +47,7 @@ abstract class GrxColors { static const Color cffd2dfe6 = Color(0xffd2dfe6); static const Color cffd6dfea = Color(0xffd6dfea); static const Color cffdce2e8 = Color(0xffdce2e8); + static const Color cffdeeaf3 = Color(0xffdeeaf3); static const Color cffe0efff = Color(0xffe0efff); static const Color cffe8f2ff = Color(0xffe8f2ff); static const Color cfff2f7fd = Color(0xfff2f7fd); @@ -56,6 +60,6 @@ abstract class GrxColors { static const Color cfffc5858 = Color(0xfffc5858); static const Color cffef6969 = Color(0xffef6969); static const Color cffffa5a5 = Color(0xffffa5a5); - + static const Color fffff6a8 = Color(0xfffff6a8); } diff --git a/lib/themes/fields/grx_field_styles.theme.dart b/lib/themes/fields/grx_field_styles.theme.dart index d2981bc..6b8b3ab 100644 --- a/lib/themes/fields/grx_field_styles.theme.dart +++ b/lib/themes/fields/grx_field_styles.theme.dart @@ -21,11 +21,11 @@ abstract class GrxFieldStyles { GrxCaptionTextStyle(color: GrxColors.cfffc5858); static const underlineInputBorder = UnderlineInputBorder( - borderSide: BorderSide(color: GrxColors.cff75f3ab), + borderSide: BorderSide(color: GrxColors.primarySwatch), ); static const underlineInputFocusedBorder = UnderlineInputBorder( - borderSide: BorderSide(color: GrxColors.cff75f3ab, width: 2), + borderSide: BorderSide(color: GrxColors.primarySwatch, width: 2), ); static const underlineInputErrorBorder = UnderlineInputBorder( diff --git a/lib/themes/grx_theme_data.theme.dart b/lib/themes/grx_theme_data.theme.dart index 3c3bcac..9331043 100644 --- a/lib/themes/grx_theme_data.theme.dart +++ b/lib/themes/grx_theme_data.theme.dart @@ -11,5 +11,8 @@ abstract class GrxThemeData { splashColor: GrxColors.cff7593b5.withOpacity(.3), highlightColor: GrxColors.cff7593b5.withOpacity(.2), textTheme: const GrxTextTheme(), + progressIndicatorTheme: const ProgressIndicatorThemeData( + color: GrxColors.primarySwatch, + ), ); } diff --git a/lib/themes/icons/grx_icons.dart b/lib/themes/icons/grx_icons.dart index 96f8d8a..3fd6510 100644 --- a/lib/themes/icons/grx_icons.dart +++ b/lib/themes/icons/grx_icons.dart @@ -1,18 +1,3 @@ -/// Flutter icons GrxIcons -/// Copyright (C) 2022 by original authors @ fluttericon.com, fontello.com -/// This font was generated by FlutterIcon.com, which is derived from Fontello. -/// -/// To use this font, place it in your fonts/ directory and include the -/// following in your pubspec.yaml -/// -/// flutter: -/// fonts: -/// - family: GrxIcons -/// fonts: -/// - asset: fonts/GrxIcons.ttf -/// -/// -/// // ignore_for_file: constant_identifier_names import 'package:flutter/widgets.dart'; diff --git a/lib/themes/typography/styles/grx_body_text.style.dart b/lib/themes/typography/styles/grx_body_text.style.dart index b3fea04..645a3c6 100644 --- a/lib/themes/typography/styles/grx_body_text.style.dart +++ b/lib/themes/typography/styles/grx_body_text.style.dart @@ -9,6 +9,9 @@ class GrxBodyTextStyle extends GrxTextStyle { const GrxBodyTextStyle({ super.color, super.decoration, + super.decorationColor, + super.decorationStyle, + super.decorationThickness, super.overflow, final FontWeight? fontWeight, }) : super( diff --git a/lib/themes/typography/styles/grx_caption_large_text.style.dart b/lib/themes/typography/styles/grx_caption_large_text.style.dart index 74088c1..1261493 100644 --- a/lib/themes/typography/styles/grx_caption_large_text.style.dart +++ b/lib/themes/typography/styles/grx_caption_large_text.style.dart @@ -9,6 +9,9 @@ class GrxCaptionLargeTextStyle extends GrxTextStyle { const GrxCaptionLargeTextStyle({ super.color, super.decoration, + super.decorationColor, + super.decorationStyle, + super.decorationThickness, super.overflow, final FontWeight? fontWeight, }) : super( diff --git a/lib/themes/typography/styles/grx_caption_small_text.style.dart b/lib/themes/typography/styles/grx_caption_small_text.style.dart index 9bb1682..9455991 100644 --- a/lib/themes/typography/styles/grx_caption_small_text.style.dart +++ b/lib/themes/typography/styles/grx_caption_small_text.style.dart @@ -9,6 +9,9 @@ class GrxCaptionSmallTextStyle extends GrxTextStyle { const GrxCaptionSmallTextStyle({ super.color, super.decoration, + super.decorationColor, + super.decorationStyle, + super.decorationThickness, super.overflow, final FontWeight? fontWeight, }) : super( diff --git a/lib/themes/typography/styles/grx_caption_text.style.dart b/lib/themes/typography/styles/grx_caption_text.style.dart index 526e77f..b888560 100644 --- a/lib/themes/typography/styles/grx_caption_text.style.dart +++ b/lib/themes/typography/styles/grx_caption_text.style.dart @@ -1,4 +1,4 @@ -import 'dart:ui'; +import 'package:flutter/material.dart'; import '../utils/grx_font_weights.dart'; import 'grx_text.style.dart'; @@ -9,6 +9,9 @@ class GrxCaptionTextStyle extends GrxTextStyle { const GrxCaptionTextStyle({ super.color, super.decoration, + super.decorationColor, + super.decorationStyle, + super.decorationThickness, super.overflow, final FontWeight? fontWeight, }) : super( diff --git a/lib/themes/typography/styles/grx_headline_large_text.style.dart b/lib/themes/typography/styles/grx_headline_large_text.style.dart index 9c486f7..448e367 100644 --- a/lib/themes/typography/styles/grx_headline_large_text.style.dart +++ b/lib/themes/typography/styles/grx_headline_large_text.style.dart @@ -9,6 +9,9 @@ class GrxHeadlineLargeTextStyle extends GrxTextStyle { const GrxHeadlineLargeTextStyle({ super.color, super.decoration, + super.decorationColor, + super.decorationStyle, + super.decorationThickness, super.overflow, final FontWeight? fontWeight, }) : super( diff --git a/lib/themes/typography/styles/grx_headline_medium_text.style.dart b/lib/themes/typography/styles/grx_headline_medium_text.style.dart index 54cfb1a..365170e 100644 --- a/lib/themes/typography/styles/grx_headline_medium_text.style.dart +++ b/lib/themes/typography/styles/grx_headline_medium_text.style.dart @@ -9,6 +9,9 @@ class GrxHeadlineMediumTextStyle extends GrxTextStyle { const GrxHeadlineMediumTextStyle({ super.color, super.decoration, + super.decorationColor, + super.decorationStyle, + super.decorationThickness, super.overflow, final FontWeight? fontWeight, }) : super( diff --git a/lib/themes/typography/styles/grx_headline_small_text.style.dart b/lib/themes/typography/styles/grx_headline_small_text.style.dart index f916478..014fbc6 100644 --- a/lib/themes/typography/styles/grx_headline_small_text.style.dart +++ b/lib/themes/typography/styles/grx_headline_small_text.style.dart @@ -9,6 +9,9 @@ class GrxHeadlineSmallTextStyle extends GrxTextStyle { const GrxHeadlineSmallTextStyle({ super.color, super.decoration, + super.decorationColor, + super.decorationStyle, + super.decorationThickness, super.overflow, final FontWeight? fontWeight, }) : super( diff --git a/lib/themes/typography/styles/grx_headline_text.style.dart b/lib/themes/typography/styles/grx_headline_text.style.dart index 8ea452f..c462b98 100644 --- a/lib/themes/typography/styles/grx_headline_text.style.dart +++ b/lib/themes/typography/styles/grx_headline_text.style.dart @@ -9,6 +9,9 @@ class GrxHeadlineTextStyle extends GrxTextStyle { const GrxHeadlineTextStyle({ super.color, super.decoration, + super.decorationColor, + super.decorationStyle, + super.decorationThickness, super.overflow, final FontWeight? fontWeight, }) : super( diff --git a/lib/themes/typography/styles/grx_overline_text.style.dart b/lib/themes/typography/styles/grx_overline_text.style.dart index 49f058e..2a45bb5 100644 --- a/lib/themes/typography/styles/grx_overline_text.style.dart +++ b/lib/themes/typography/styles/grx_overline_text.style.dart @@ -9,6 +9,9 @@ class GrxOverlineTextStyle extends GrxTextStyle { const GrxOverlineTextStyle({ super.color, super.decoration, + super.decorationColor, + super.decorationStyle, + super.decorationThickness, super.overflow, final FontWeight? fontWeight, }) : super( diff --git a/lib/themes/typography/styles/grx_text.style.dart b/lib/themes/typography/styles/grx_text.style.dart index f08ac17..53f4bda 100644 --- a/lib/themes/typography/styles/grx_text.style.dart +++ b/lib/themes/typography/styles/grx_text.style.dart @@ -11,9 +11,13 @@ class GrxTextStyle extends TextStyle { super.fontWeight, super.color, super.decoration, - super.overflow = TextOverflow.ellipsis, + super.decorationColor, + super.decorationStyle, + super.decorationThickness, + final TextOverflow? overflow, }) : super( package: GrxUtils.packageName, fontFamily: GrxFontFamilies.montserrat, + overflow: overflow ?? TextOverflow.ellipsis, ); } diff --git a/lib/utils/grx_country.util.dart b/lib/utils/grx_country.util.dart new file mode 100644 index 0000000..43a7150 --- /dev/null +++ b/lib/utils/grx_country.util.dart @@ -0,0 +1,1323 @@ +import '../enums/grx_country_id.enum.dart'; +import '../models/grx_country.model.dart'; +import '../services/grx_static_values.service.dart'; + +abstract class GrxCountryUtils { + static GrxCountry? getCountry(final GrxCountryId? id) => countries + .map((x) => x) + .firstWhere((country) => country!.id == id, orElse: () => null); + + static const countries = [ + GrxCountry( + id: GrxCountryId.BR, + code: '+55', + name: 'Brasil', + flag: 'brazil_flag', + language: 'pt-BR', + phoneMasks: [ + '(##) ####-#####', + '(##) #####-####', + ], + zipcodeMasks: [ + '#####-###', + ], + states: GrxStaticValuesService.brStates, + ), + GrxCountry( + id: GrxCountryId.US, + code: '+1', + name: 'Estados Unidos', + flag: 'united_states_flag', + language: 'en-US', + phoneMasks: [ + '(###) ###-####', + ], + states: GrxStaticValuesService.usStates, + ), + GrxCountry( + id: GrxCountryId.AR, + code: '+54', + name: 'Argentina', + flag: 'argentina_flag', + language: 'es', + phoneMasks: [ + '### ####-####', + ], + states: GrxStaticValuesService.arStates, + ), + GrxCountry( + id: GrxCountryId.UY, + code: '+598', + name: 'Uruguai', + flag: 'uruguay_flag', + language: 'es', + phoneMasks: [ + '### ####-####', + ], + states: GrxStaticValuesService.uyStates, + ), + GrxCountry( + id: GrxCountryId.AF, + code: '+93', + name: 'Afeganistão', + flag: 'afghanistan_flag', + ), + GrxCountry( + id: GrxCountryId.ZA, + code: '+27', + name: 'África do Sul', + flag: 'south_africa_flag', + ), + GrxCountry( + id: GrxCountryId.AL, + code: '+355', + name: 'Albânia', + flag: 'albania_flag', + ), + GrxCountry( + id: GrxCountryId.DE, + code: '+49', + name: 'Alemanha', + flag: 'germany_flag', + ), + GrxCountry( + id: GrxCountryId.AD, + code: '+376', + name: 'Andorra', + flag: 'andorra_flag', + ), + GrxCountry( + id: GrxCountryId.AO, + code: '+244', + name: 'Angola', + flag: 'angola_flag', + ), + GrxCountry( + id: GrxCountryId.AI, + code: '+1', + name: 'Anguilla', + flag: 'anguilla_flag', + ), + GrxCountry( + id: GrxCountryId.AG, + code: '+1', + name: 'Antígua e Barbuda', + flag: 'antigua_and_barbuda_flag', + ), + GrxCountry( + id: GrxCountryId.SA, + code: '+966', + name: 'Arábia Saudita', + flag: 'saudi_arabia_flag', + ), + GrxCountry( + id: GrxCountryId.DZ, + code: '+213', + name: 'Argélia', + flag: 'algeria_flag', + ), + GrxCountry( + id: GrxCountryId.AM, + code: '+374', + name: 'Armênia', + flag: 'armenia_flag', + ), + GrxCountry( + id: GrxCountryId.AW, + code: '+297', + name: 'Aruba', + flag: 'aruba_flag', + ), + GrxCountry( + id: GrxCountryId.AU, + code: '+61', + name: 'Austrália', + flag: 'australia_flag', + ), + GrxCountry( + id: GrxCountryId.AT, + code: '+43', + name: 'Áustria', + flag: 'austria_flag', + ), + GrxCountry( + id: GrxCountryId.AZ, + code: '+994', + name: 'Azerbaijão', + flag: 'azerbaijan_flag', + ), + GrxCountry( + id: GrxCountryId.BS, + code: '+1', + name: 'Bahamas', + flag: 'bahamas_flag', + ), + GrxCountry( + id: GrxCountryId.BD, + code: '+880', + name: 'Bangladesh', + flag: 'bangladesh_flag', + ), + GrxCountry( + id: GrxCountryId.BB, + code: '+1', + name: 'Barbados', + flag: 'barbados_flag', + ), + GrxCountry( + id: GrxCountryId.BH, + code: '+973', + name: 'Bahrein', + flag: 'bahrain_flag', + ), + GrxCountry( + id: GrxCountryId.BE, + code: '+32', + name: 'Bélgica', + flag: 'belgium_flag', + ), + GrxCountry( + id: GrxCountryId.BZ, + code: '+501', + name: 'Belize', + flag: 'belize_flag', + ), + GrxCountry( + id: GrxCountryId.BJ, + code: '+229', + name: 'Benim', + flag: 'benin_flag', + ), + GrxCountry( + id: GrxCountryId.BM, + code: '+1', + name: 'Bermudas', + flag: 'bermuda_flag', + ), + GrxCountry( + id: GrxCountryId.BY, + code: '+375', + name: 'Bielorrússia', + flag: 'belarus_flag', + ), + GrxCountry( + id: GrxCountryId.BO, + code: '+591', + name: 'Bolívia', + flag: 'bolivia_flag', + ), + GrxCountry( + id: GrxCountryId.BA, + code: '+387', + name: 'Bósnia e Herzegovina', + flag: 'bosnia_and_herzegovina_flag', + ), + GrxCountry( + id: GrxCountryId.BW, + code: '+267', + name: 'Botswana', + flag: 'botswana_flag', + ), + GrxCountry( + id: GrxCountryId.BN, + code: '+673', + name: 'Brunei', + flag: 'brunei_flag', + ), + GrxCountry( + id: GrxCountryId.BG, + code: '+359', + name: 'Bulgária', + flag: 'bulgaria_flag', + ), + GrxCountry( + id: GrxCountryId.BI, + code: '+257', + name: 'Burundi', + flag: 'burundi_flag', + ), + GrxCountry( + id: GrxCountryId.BT, + code: '+975', + name: 'Butão', + flag: 'bhutan_flag', + ), + GrxCountry( + id: GrxCountryId.KH, + code: '+855', + name: 'Camboja', + flag: 'cambodia_flag', + ), + GrxCountry( + id: GrxCountryId.CA, + code: '+1', + name: 'Canadá', + flag: 'canada_flag', + ), + GrxCountry( + id: GrxCountryId.KZ, + code: '+7', + name: 'Cazaquistão', + flag: 'kazakhstan_flag', + ), + GrxCountry( + id: GrxCountryId.TD, + code: '+235', + name: 'Chade', + flag: 'chad_flag', + ), + GrxCountry( + id: GrxCountryId.CL, + code: '+56', + name: 'Chile', + flag: 'chile_flag', + ), + GrxCountry( + id: GrxCountryId.CN, + code: '+86', + name: 'China', + flag: 'china_flag', + ), + GrxCountry( + id: GrxCountryId.CY, + code: '+357', + name: 'Chipre', + flag: 'northern_cyprus_flag', + ), + GrxCountry( + id: GrxCountryId.CO, + code: '+57', + name: 'Colômbia', + flag: 'colombia_flag', + ), + GrxCountry( + id: GrxCountryId.KM, + code: '+269', + name: 'Comores', + flag: 'comoros_flag', + ), + GrxCountry( + id: GrxCountryId.KP, + code: '+850', + name: 'Coreia do Norte', + flag: 'north_korea_flag', + ), + GrxCountry( + id: GrxCountryId.KR, + code: '+82', + name: 'Coreia do Sul', + flag: 'south_korea_flag', + ), + GrxCountry( + id: GrxCountryId.CI, + code: '+225', + name: 'Costa do Marfim', + flag: 'ivory_coast_flag', + ), + GrxCountry( + id: GrxCountryId.CR, + code: '+506', + name: 'Costa Rica', + flag: 'costa_rica_flag', + ), + GrxCountry( + id: GrxCountryId.HR, + code: '+385', + name: 'Croácia', + flag: 'croatia_flag', + ), + GrxCountry( + id: GrxCountryId.CU, + code: '+53', + name: 'Cuba', + flag: 'cuba_flag', + ), + GrxCountry( + id: GrxCountryId.DK, + code: '+45', + name: 'Dinamarca', + flag: 'denmark_flag', + ), + GrxCountry( + id: GrxCountryId.DJ, + code: '+253', + name: 'Dijibuti', + flag: 'djibouti_flag', + ), + GrxCountry( + id: GrxCountryId.DM, + code: '+1', + name: 'Dominica', + flag: 'dominica_flag', + ), + GrxCountry( + id: GrxCountryId.EG, + code: '+20', + name: 'Egito', + flag: 'egypt_flag', + ), + GrxCountry( + id: GrxCountryId.SV, + code: '+503', + name: 'El Salvador', + flag: 'el_salvador_flag', + ), + GrxCountry( + id: GrxCountryId.AE, + code: '+971', + name: 'Emirados Árabes Unidos', + flag: 'united_arab_emirates_flag', + ), + GrxCountry( + id: GrxCountryId.EC, + code: '+593', + name: 'Equador', + flag: 'ecuador_flag', + ), + GrxCountry( + id: GrxCountryId.ER, + code: '+291', + name: 'Eritreia', + flag: 'eritrea_flag', + ), + GrxCountry( + id: GrxCountryId.SK, + code: '+421', + name: 'Eslováquia', + flag: 'slovakia_flag', + ), + GrxCountry( + id: GrxCountryId.SI, + code: '+386', + name: 'Eslovênia', + flag: 'slovenia_flag', + ), + GrxCountry( + id: GrxCountryId.ES, + code: '+34', + name: 'Espanha', + flag: 'spain_flag', + ), + GrxCountry( + id: GrxCountryId.EE, + code: '+372', + name: 'Estônia', + flag: 'estonia_flag', + ), + GrxCountry( + id: GrxCountryId.ET, + code: '+251', + name: 'Etiópia', + flag: 'ethiopia_flag', + ), + GrxCountry( + id: GrxCountryId.FJ, + code: '+679', + name: 'Fiji', + flag: 'fiji_flag', + ), + GrxCountry( + id: GrxCountryId.PH, + code: '+63', + name: 'Filipinas', + flag: 'philippines_flag', + ), + GrxCountry( + id: GrxCountryId.FI, + code: '+358', + name: 'Finlândia', + flag: 'finland_flag', + ), + GrxCountry( + id: GrxCountryId.FR, + code: '+33', + name: 'França', + flag: 'france_flag', + ), + GrxCountry( + id: GrxCountryId.GA, + code: '+241', + name: 'Gabão', + flag: 'gabon_flag', + ), + GrxCountry( + id: GrxCountryId.GM, + code: '+220', + name: 'Gâmbia', + flag: 'gambia_flag', + ), + GrxCountry( + id: GrxCountryId.GH, + code: '+233', + name: 'Ghana', + flag: 'ghana_flag', + ), + GrxCountry( + id: GrxCountryId.GE, + code: '+995', + name: 'Geórgia', + flag: 'georgia_flag', + ), + GrxCountry( + id: GrxCountryId.GI, + code: '+350', + name: 'Gibraltar', + flag: 'gibraltar_flag', + ), + GrxCountry( + id: GrxCountryId.GD, + code: '+1', + name: 'Granada', + flag: 'grenada_flag', + ), + GrxCountry( + id: GrxCountryId.GR, + code: '+30', + name: 'Grécia', + flag: 'greece_flag', + ), + GrxCountry( + id: GrxCountryId.GL, + code: '+299', + name: 'Groenlândia', + flag: 'greenland_flag', + ), + GrxCountry( + id: GrxCountryId.GU, + code: '+671', + name: 'Guam', + flag: 'guam_flag', + ), + GrxCountry( + id: GrxCountryId.GT, + code: '+502', + name: 'Guatemala', + flag: 'guatemala_flag', + ), + GrxCountry( + id: GrxCountryId.GN, + code: '+224', + name: 'Guiné', + flag: 'guinea_flag', + ), + GrxCountry( + id: GrxCountryId.GW, + code: '+245', + name: 'Guiné-Bissau', + flag: 'guinea_bissau_flag', + ), + GrxCountry( + id: GrxCountryId.HT, + code: '+509', + name: 'Haiti', + flag: 'haiti_flag', + ), + GrxCountry( + id: GrxCountryId.NL, + code: '+31', + name: 'Holanda', + flag: 'netherlands_flag', + ), + GrxCountry( + id: GrxCountryId.HN, + code: '+504', + name: 'Honduras', + flag: 'honduras_flag', + ), + GrxCountry( + id: GrxCountryId.HK, + code: '+852', + name: 'Hong Kong', + flag: 'hong_kong_flag', + ), + GrxCountry( + id: GrxCountryId.HU, + code: '+36', + name: 'Hungria', + flag: 'hungary_flag', + ), + GrxCountry( + id: GrxCountryId.YE, + code: '+967', + name: 'Iêmen', + flag: 'yemen_flag', + ), + GrxCountry( + id: GrxCountryId.KY, + code: '+1', + name: 'Ilhas Cayman', + flag: 'cayman_islands_flag', + ), + GrxCountry( + id: GrxCountryId.CX, + code: '+672', + name: 'Ilha Christmas', + flag: 'christmas_island_flag', + ), + GrxCountry( + id: GrxCountryId.CC, + code: '+672', + name: 'Ilhas Cocos', + flag: 'cocos_island_flag', + ), + GrxCountry( + id: GrxCountryId.CK, + code: '+682', + name: 'Ilhas Cook', + flag: 'cook_islands_flag', + ), + GrxCountry( + id: GrxCountryId.MV, + code: '+960', + name: 'Maldivas', + flag: 'maldives_flag', + ), + GrxCountry( + id: GrxCountryId.MP, + code: '+1', + name: 'Ilhas Marianas do Norte', + flag: 'northern_marianas_islands_flag', + ), + GrxCountry( + id: GrxCountryId.MH, + code: '+692', + name: 'Ilhas Marshall', + flag: 'marshall_island_flag', + ), + GrxCountry( + id: GrxCountryId.NF, + code: '+672', + name: 'Ilha Norfolk', + flag: 'norfolk_island_flag', + ), + GrxCountry( + id: GrxCountryId.SB, + code: '+677', + name: 'Ilhas Salomão', + flag: 'solomon_islands_flag', + ), + GrxCountry( + id: GrxCountryId.VI, + code: '+1', + name: 'Ilhas Virgens Americanas', + flag: 'virgin_islands_flag', + ), + GrxCountry( + id: GrxCountryId.VG, + code: '+1', + name: 'Ilhas Virgens Britânicas', + flag: 'british_virgin_islands_flag', + ), + GrxCountry( + id: GrxCountryId.IN, + code: '+91', + name: 'Índia', + flag: 'india_flag', + ), + GrxCountry( + id: GrxCountryId.ID, + code: '+62', + name: 'Indonésia', + flag: 'indonesia_flag', + ), + GrxCountry( + id: GrxCountryId.IR, + code: '+98', + name: 'Irã', + flag: 'iran_flag', + ), + GrxCountry( + id: GrxCountryId.IQ, + code: '+964', + name: 'Iraque', + flag: 'iraq_flag', + ), + GrxCountry( + id: GrxCountryId.IE, + code: '+353', + name: 'Irlanda', + flag: 'ireland_flag', + ), + GrxCountry( + id: GrxCountryId.ISL, + code: '+354', + name: 'Islândia', + flag: 'iceland_flag', + ), + GrxCountry( + id: GrxCountryId.IL, + code: '+972', + name: 'Israel', + flag: 'israel_flag', + ), + GrxCountry( + id: GrxCountryId.IT, + code: '+39', + name: 'Itália', + flag: 'italy_flag', + ), + GrxCountry( + id: GrxCountryId.JM, + code: '+1', + name: 'Jamaica', + flag: 'jamaica_flag', + ), + GrxCountry( + id: GrxCountryId.JP, + code: '+81', + name: 'Japão', + flag: 'japan_flag', + ), + GrxCountry( + id: GrxCountryId.JO, + code: '+962', + name: 'Jordânia', + flag: 'jordan_flag', + ), + GrxCountry( + id: GrxCountryId.KI, + code: '+686', + name: 'Kiribati', + flag: 'kiribati_flag', + ), + // GrxCountry( + // code: '+383', + // name: 'Kosovo', + // flag: 'kosovo_flag', + // ), + GrxCountry( + id: GrxCountryId.KW, + code: '+965', + name: 'Kuwait', + flag: 'kwait_flag', + ), + GrxCountry( + id: GrxCountryId.LA, + code: '+856', + name: 'Laos', + flag: 'laos_flag', + ), + GrxCountry( + id: GrxCountryId.LS, + code: '+266', + name: 'Lesoto', + flag: 'lesotho_flag', + ), + GrxCountry( + id: GrxCountryId.LV, + code: '+371', + name: 'Letônia', + flag: 'latvia_flag', + ), + GrxCountry( + id: GrxCountryId.LB, + code: '+961', + name: 'Líbano', + flag: 'lebanon_flag', + ), + GrxCountry( + id: GrxCountryId.LR, + code: '+231', + name: 'Libéria', + flag: 'liberia_flag', + ), + GrxCountry( + id: GrxCountryId.LY, + code: '+218', + name: 'Líbia', + flag: 'libya_flag', + ), + GrxCountry( + id: GrxCountryId.LI, + code: '+237', + name: 'Liechtenstein', + flag: 'liechtenstein_flag', + ), + GrxCountry( + id: GrxCountryId.LT, + code: '+370', + name: 'Lituânia', + flag: 'lithuania_flag', + ), + GrxCountry( + id: GrxCountryId.LU, + code: '+352', + name: 'Luxemburgo', + flag: 'luxembourg_flag', + ), + GrxCountry( + id: GrxCountryId.MO, + code: '+853', + name: 'Macau', + flag: 'macao_flag', + ), + GrxCountry( + id: GrxCountryId.MK, + code: '+389', + name: 'Macedônia', + flag: 'republic_of_macedonia_flag', + ), + GrxCountry( + id: GrxCountryId.MG, + code: '+261', + name: 'Madagascar', + flag: 'madagascar_flag', + ), + GrxCountry( + id: GrxCountryId.MY, + code: '+60', + name: 'Malásia', + flag: 'malasya_flag', + ), + GrxCountry( + id: GrxCountryId.MY, + code: '+265', + name: 'Malawi', + flag: 'malawi_flag', + ), + GrxCountry( + id: GrxCountryId.ML, + code: '+223', + name: 'Mali', + flag: 'mali_flag', + ), + GrxCountry( + id: GrxCountryId.MT, + code: '+356', + name: 'Malta', + flag: 'malta_flag', + ), + GrxCountry( + id: GrxCountryId.MA, + code: '+212', + name: 'Marrocos', + flag: 'morocco_flag', + ), + GrxCountry( + id: GrxCountryId.MQ, + code: '+596', + name: 'Martinica', + flag: 'martinique_flag', + ), + GrxCountry( + id: GrxCountryId.MU, + code: '+230', + name: 'Maurícia', + flag: 'mauritius_flag', + ), + GrxCountry( + id: GrxCountryId.MR, + code: '+222', + name: 'Mauritânia', + flag: 'mauritania_flag', + ), + GrxCountry( + id: GrxCountryId.MX, + code: '+52', + name: 'México', + flag: 'mexico_flag', + ), + GrxCountry( + id: GrxCountryId.FM, + code: '+237', + name: 'Micronesia', + flag: 'micronesia_flag', + ), + GrxCountry( + id: GrxCountryId.MZ, + code: '+258', + name: 'Moçambique', + flag: 'mozambique_flag', + phoneMasks: [ + '## ### ####', + ], + states: GrxStaticValuesService.mzStates, + ), + GrxCountry( + id: GrxCountryId.MD, + code: '+373', + name: 'Moldávia', + flag: 'moldova_flag', + ), + GrxCountry( + id: GrxCountryId.MC, + code: '+377', + name: 'Mônaco', + flag: 'monaco_flag', + ), + GrxCountry( + id: GrxCountryId.MN, + code: '+976', + name: 'Mongólia', + flag: 'mongolia_flag', + ), + GrxCountry( + id: GrxCountryId.ME, + code: '+382', + name: 'Montenegro', + flag: 'montenegro_flag', + ), + GrxCountry( + id: GrxCountryId.MS, + code: '+1', + name: 'Montserrat', + flag: 'montserrat_flag', + ), + GrxCountry( + id: GrxCountryId.MM, + code: '+95', + name: 'Myanmar', + flag: 'myanmar_flag', + ), + GrxCountry( + id: GrxCountryId.NA, + code: '+264', + name: 'Namíbia', + flag: 'namibia_flag', + ), + GrxCountry( + id: GrxCountryId.NR, + code: '+674', + name: 'Nauru', + flag: 'nauru_flag', + ), + GrxCountry( + id: GrxCountryId.NP, + code: '+977', + name: 'Nepal', + flag: 'nepal_flag', + ), + GrxCountry( + id: GrxCountryId.NI, + code: '+505', + name: 'Nicarágua', + flag: 'nicaragua_flag', + ), + GrxCountry( + id: GrxCountryId.NE, + code: '+227', + name: 'Níger', + flag: 'niger_flag', + ), + GrxCountry( + id: GrxCountryId.NG, + code: '+234', + name: 'Nigéria', + flag: 'nigeria_flag', + ), + GrxCountry( + id: GrxCountryId.NU, + code: '+683', + name: 'Niue', + flag: 'niue_flag', + ), + GrxCountry( + id: GrxCountryId.NO, + code: '+47', + name: 'Noruega', + flag: 'norway_flag', + ), + GrxCountry( + id: GrxCountryId.NZ, + code: '+64', + name: 'Nova Zelândia', + flag: 'new_zealand_flag', + ), + GrxCountry( + id: GrxCountryId.OM, + code: '+968', + name: 'Omã', + flag: 'oman_flag', + ), + GrxCountry( + id: GrxCountryId.PW, + code: '+680', + name: 'Palau', + flag: 'palau_flag', + ), + GrxCountry( + id: GrxCountryId.PS, + code: '+970', + name: 'Palestina', + flag: 'palestine_flag', + ), + GrxCountry( + id: GrxCountryId.PA, + code: '+507', + name: 'Panamá', + flag: 'panama_flag', + ), + GrxCountry( + id: GrxCountryId.PG, + code: '+675', + name: 'Papua-Nova Guiné', + flag: 'papua_new_guinea_flag', + ), + GrxCountry( + id: GrxCountryId.PK, + code: '+92', + name: 'Paquistão', + flag: 'pakistan_flag', + ), + GrxCountry( + id: GrxCountryId.PY, + code: '+595', + name: 'Paraguai', + flag: 'paraguay_flag', + ), + GrxCountry( + id: GrxCountryId.PE, + code: '+51', + name: 'Peru', + flag: 'peru_flag', + ), + GrxCountry( + id: GrxCountryId.PF, + code: '+689', + name: 'Polinésia Francesa', + flag: 'french_polynesia_flag', + ), + GrxCountry( + id: GrxCountryId.PL, + code: '+48', + name: 'Polônia', + flag: 'poland_flag', + ), + GrxCountry( + id: GrxCountryId.PR, + code: '+1', + name: 'Porto Rico', + flag: 'puerto_rico_flag', + ), + GrxCountry( + id: GrxCountryId.PT, + code: '+351', + name: 'Portugal', + flag: 'portugal_flag', + ), + GrxCountry( + id: GrxCountryId.QA, + code: '+974', + name: 'Qatar', + flag: 'qatar_flag', + ), + GrxCountry( + id: GrxCountryId.KE, + code: '+254', + name: 'Quênia', + flag: 'kenya_flag', + ), + GrxCountry( + id: GrxCountryId.KG, + code: '+996', + name: 'Quirguistão', + flag: 'kyrgyzstan_flag', + ), + GrxCountry( + id: GrxCountryId.GB, + code: '+44', + name: 'Reino Unido', + flag: 'united_kingdom_flag', + ), + GrxCountry( + id: GrxCountryId.CF, + code: '+236', + name: 'República Centro-Africana', + flag: 'central_african_republic_flag', + ), + GrxCountry( + id: GrxCountryId.DO, + code: '+1', + name: 'República Dominicana', + flag: 'dominican_republic_flag', + ), + GrxCountry( + id: GrxCountryId.CZ, + code: '+420', + name: 'República Tcheca', + flag: 'czech_republic_flag', + ), + GrxCountry( + id: GrxCountryId.RO, + code: '+40', + name: 'Romênia', + flag: 'romania_flag', + ), + GrxCountry( + id: GrxCountryId.RW, + code: '+250', + name: 'Ruanda', + flag: 'rwanda_flag', + ), + GrxCountry( + id: GrxCountryId.RU, + code: '+7', + name: 'Rússia', + flag: 'russia_flag', + ), + GrxCountry( + id: GrxCountryId.WS, + code: '+685', + name: 'Samoa', + flag: 'samoa_flag', + ), + GrxCountry( + id: GrxCountryId.AS, + code: '+1', + name: 'Samoa Americana', + flag: 'american_samoa_flag', + ), + GrxCountry( + id: GrxCountryId.LC, + code: '+1', + name: 'Santa Lúcia', + flag: 'st_lucia_flag', + ), + GrxCountry( + id: GrxCountryId.KN, + code: '+1', + name: 'São Cristóvão e Nevis', + flag: 'saint_kitts_and_nevis_flag', + ), + GrxCountry( + id: GrxCountryId.SM, + code: '+378', + name: 'São Marinho', + flag: 'san_marino_flag', + ), + GrxCountry( + id: GrxCountryId.ST, + code: '+239', + name: 'São Tomé e Príncipe', + flag: 'sao_tome_and_prince_flag', + ), + GrxCountry( + id: GrxCountryId.VC, + code: '+1', + name: 'São Vicente e Granadinas', + flag: 'st_vincent_and_the_grenadines_flag', + ), + GrxCountry( + id: GrxCountryId.SC, + code: '+248', + name: 'Seicheles', + flag: 'seychelles_flag', + ), + GrxCountry( + id: GrxCountryId.SN, + code: '+221', + name: 'Senegal', + flag: 'senegal_flag', + ), + GrxCountry( + id: GrxCountryId.SL, + code: '+232', + name: 'Serra Leoa', + flag: 'sierra_leone_flag', + ), + GrxCountry( + id: GrxCountryId.RS, + code: '+381', + name: 'Sérvia', + flag: 'serbia_flag', + ), + GrxCountry( + id: GrxCountryId.SG, + code: '+65', + name: 'Singapura', + flag: 'singapore_flag', + ), + GrxCountry( + id: GrxCountryId.SY, + code: '+963', + name: 'Síria', + flag: 'syria_flag', + ), + GrxCountry( + id: GrxCountryId.SO, + code: '+252', + name: 'Somália', + flag: 'somalia_flag', + ), + GrxCountry( + id: GrxCountryId.LK, + code: '+94', + name: 'Sri Lanka', + flag: 'sri_lanka_flag', + ), + GrxCountry( + id: GrxCountryId.SD, + code: '+249', + name: 'Sudão', + flag: 'sudan_flag', + ), + GrxCountry( + id: GrxCountryId.SS, + code: '+211', + name: 'Sudão do Sul', + flag: 'south_sudan_flag', + ), + GrxCountry( + id: GrxCountryId.SE, + code: '+46', + name: 'Suécia', + flag: 'sweden_flag', + ), + GrxCountry( + id: GrxCountryId.CH, + code: '+41', + name: 'Suíça', + flag: 'switzerland_flag', + ), + GrxCountry( + id: GrxCountryId.SR, + code: '+597', + name: 'Suriname', + flag: 'suriname_flag', + ), + GrxCountry( + id: GrxCountryId.TJ, + code: '+992', + name: 'Tadjiquistão', + flag: 'tajikistan_flag', + ), + GrxCountry( + id: GrxCountryId.TH, + code: '+66', + name: 'Tailândia', + flag: 'thailand_flag', + ), + GrxCountry( + id: GrxCountryId.TW, + code: '+886', + name: 'Taiwan', + flag: 'taiwan_flag', + ), + GrxCountry( + id: GrxCountryId.TZ, + code: '+255', + name: 'Tanzânia', + flag: 'tanzania_flag', + ), + GrxCountry( + id: GrxCountryId.IO, + code: '+246', + name: 'Território Britânico do Oceano Índico', + flag: 'british_indian_ocean_territory_flag', + ), + GrxCountry( + id: GrxCountryId.TL, + code: '+670', + name: 'Timor Leste', + flag: 'east_timor_flag', + ), + GrxCountry( + id: GrxCountryId.TG, + code: '+228', + name: 'Togo', + flag: 'togo_flag', + ), + GrxCountry( + id: GrxCountryId.TK, + code: '+690', + name: 'Tokelau', + flag: 'tokelau_flag', + ), + GrxCountry( + id: GrxCountryId.TO, + code: '+676', + name: 'Tonga', + flag: 'tonga_flag', + ), + GrxCountry( + id: GrxCountryId.TT, + code: '+1', + name: 'Trinidad e Tobago', + flag: 'trinidad_and_tobago_flag', + ), + GrxCountry( + id: GrxCountryId.TN, + code: '+216', + name: 'Tunísia', + flag: 'tunisia_flag', + ), + GrxCountry( + id: GrxCountryId.TC, + code: '+1', + name: 'Turcas e Caicos', + flag: 'turks_and_caicos_flag', + ), + GrxCountry( + id: GrxCountryId.TM, + code: '+993', + name: 'Turquemenistão', + flag: 'turkmenistan_flag', + ), + GrxCountry( + id: GrxCountryId.TR, + code: '+90', + name: 'Turquia', + flag: 'turkey_flag', + ), + GrxCountry( + id: GrxCountryId.TV, + code: '+638', + name: 'Tuvalu', + flag: 'tuvalu_flag', + ), + GrxCountry( + id: GrxCountryId.UA, + code: '+380', + name: 'Ucrânia', + flag: 'ukraine_flag', + ), + GrxCountry( + id: GrxCountryId.UG, + code: '+256', + name: 'Uganda', + flag: 'uganda_flag', + ), + GrxCountry( + id: GrxCountryId.UZ, + code: '+998', + name: 'Uzbequistão', + flag: 'uzbekistn_flag', + ), + GrxCountry( + id: GrxCountryId.VU, + code: '+678', + name: 'Vanuatu', + flag: 'vanuatu_flag', + ), + GrxCountry( + id: GrxCountryId.VA, + code: '+379', + name: 'Vaticano', + flag: 'vatican_city_flag', + ), + GrxCountry( + id: GrxCountryId.VE, + code: '+58', + name: 'Venezuela', + flag: 'venezuela_flag', + ), + GrxCountry( + id: GrxCountryId.VN, + code: '+84', + name: 'Vietnã', + flag: 'vietnam_flag', + ), + GrxCountry( + id: GrxCountryId.ZM, + code: '+260', + name: 'Zâmbia', + flag: 'zambia_flag', + ), + GrxCountry( + id: GrxCountryId.ZW, + code: '+263', + name: 'Zimbábue', + flag: 'zimbabwe_flag', + ), + ]; +} diff --git a/lib/utils/grx_form_field.util.dart b/lib/utils/grx_form_field.util.dart index 8f9eb7d..3069374 100644 --- a/lib/utils/grx_form_field.util.dart +++ b/lib/utils/grx_form_field.util.dart @@ -1,18 +1,25 @@ import 'package:flutter/material.dart'; +import 'package:flutter/scheduler.dart'; + +import '../widgets/fields/controllers/grx_form_field.controller.dart'; abstract class GrxFormFieldUtils { static onValueChange( FormFieldState field, - TextEditingController controller, { + GrxFormFieldController controller, { void Function(String)? onChanged, }) { + if (controller.hasListeners) return; + void onChangedHandler(String value) { if (field.mounted && field.value != value) { if (onChanged != null) { onChanged(value); } - field.didChange(value); + SchedulerBinding.instance.addPostFrameCallback( + (_) => field.didChange(value), + ); } } diff --git a/lib/utils/grx_utils.util.dart b/lib/utils/grx_utils.util.dart index 28b3a40..baaa2ce 100644 --- a/lib/utils/grx_utils.util.dart +++ b/lib/utils/grx_utils.util.dart @@ -1,10 +1,6 @@ -import 'package:flutter/widgets.dart'; /// All utility constants that are used by this Design System. abstract class GrxUtils { static const packageName = 'grex_ds'; - static const defaultAnimationDuration = Duration(milliseconds: 300); - static final defaultCardBorder = RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8), - ); + static const defaultAnimationDuration = Duration(milliseconds: 400); } diff --git a/lib/widgets/bottom_sheet/ds_bottom_sheet_countries.widget.dart b/lib/widgets/bottom_sheet/ds_bottom_sheet_countries.widget.dart new file mode 100644 index 0000000..ae24dd8 --- /dev/null +++ b/lib/widgets/bottom_sheet/ds_bottom_sheet_countries.widget.dart @@ -0,0 +1,140 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:super_sliver_list/super_sliver_list.dart'; + +import '../../extensions/list.extension.dart'; +import '../../models/grx_country.model.dart'; +import '../../themes/colors/grx_colors.dart'; +import '../../utils/grx_country.util.dart'; +import '../../utils/grx_utils.util.dart'; +import '../checkbox/grx_rounded_checkbox.widget.dart'; +import '../fields/grx_search_field.widget.dart'; +import '../grx_card.widget.dart'; +import '../typography/grx_body_text.widget.dart'; +import '../typography/grx_headline_small_text.widget.dart'; + +class GrxBottomSheetCountries extends StatefulWidget { + const GrxBottomSheetCountries({ + super.key, + required this.selectedCountry, + }); + + final GrxCountry selectedCountry; + + @override + State createState() => _GrxBottomSheetCountriesState(); +} + +class _GrxBottomSheetCountriesState extends State { + final searchFieldController = TextEditingController(); + final _filteredCountries = [...GrxCountryUtils.countries]; + + bool showClearButton = false; + late GrxCountry selectedCountry = widget.selectedCountry; + + Future _onSearch(final String searchString) async { + setState(() { + showClearButton = searchString.isNotEmpty; + _filteredCountries.assignAll( + GrxCountryUtils.countries.where((country) => + country.name.toLowerCase().contains(searchString.toLowerCase()) || + country.code.toLowerCase().contains(searchString.toLowerCase())), + ); + }); + } + + @override + Widget build(BuildContext context) { + final mediaQuery = MediaQuery.of(context); + final viewInsets = mediaQuery.viewInsets; + final padding = mediaQuery.padding; + + return ColoredBox( + color: GrxColors.cfff2f7fd, + child: CustomScrollView( + slivers: [ + SliverAppBar( + titleSpacing: 0.0, + toolbarHeight: 65.0, + backgroundColor: Colors.transparent, + automaticallyImplyLeading: false, + title: Container( + padding: const EdgeInsets.symmetric( + vertical: 10.0, + horizontal: 8.0, + ), + child: GrxSearchField( + // searchFieldController: widget.quickSearchFieldController!, + searchFieldController: searchFieldController, + onChanged: _onSearch, + hintText: 'Search', + ), + ), + ), + SliverPadding( + padding: EdgeInsets.only( + left: 8.0, + top: 8.0, + right: 8.0, + bottom: viewInsets.bottom + padding.bottom + 8.0, + ), + sliver: SuperSliverList( + delegate: SliverChildBuilderDelegate( + childCount: _filteredCountries.length, + (context, index) { + final country = _filteredCountries[index]; + + return InkWell( + onTap: () { + setState(() { + selectedCountry = country; + }); + Navigator.pop(context, country); + }, + child: GrxCard( + child: Padding( + padding: const EdgeInsets.all( + 16.0, + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Flexible( + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + SvgPicture.asset( + 'assets/svgs/flags/${country.flag}.svg', + width: 22.0, + package: GrxUtils.packageName, + ), + Padding( + padding: const EdgeInsets.symmetric( + horizontal: 6.0, + ), + child: GrxBodyText(country.name), + ), + GrxHeadlineSmallText(country.code), + ], + ), + ), + GrxRoundedCheckbox( + value: selectedCountry.code == country.code && + selectedCountry.name == country.name, + radius: 8.0, + isTappable: false, + ) + ], + ), + ), + ), + ); + }, + ), + ), + ), + ], + ), + ); + } +} diff --git a/lib/widgets/bottom_sheet/grx_bottom_sheet_form_field_body.widget.dart b/lib/widgets/bottom_sheet/grx_bottom_sheet_form_field_body.widget.dart index 4df04b1..336b024 100644 --- a/lib/widgets/bottom_sheet/grx_bottom_sheet_form_field_body.widget.dart +++ b/lib/widgets/bottom_sheet/grx_bottom_sheet_form_field_body.widget.dart @@ -1,9 +1,10 @@ import 'package:flutter/material.dart'; +import 'package:super_sliver_list/super_sliver_list.dart'; import '../../themes/colors/grx_colors.dart'; import '../buttons/grx_primary_button.widget.dart'; import '../buttons/grx_secondary_button.widget.dart'; -import '../fields/grx_filter_field.widget.dart'; +import '../fields/grx_search_field.widget.dart'; import '../typography/grx_caption_large_text.widget.dart'; class GrxBottomSheetFormFieldBody extends StatefulWidget { @@ -57,7 +58,8 @@ class GrxBottomSheetFormFieldBody extends StatefulWidget { State createState() => _GrxBottomSheetFormFieldBodyState(); } -class _GrxBottomSheetFormFieldBodyState extends State> { +class _GrxBottomSheetFormFieldBodyState + extends State> { final _list = []; final _selectedValues = []; @@ -116,98 +118,105 @@ class _GrxBottomSheetFormFieldBodyState extends State _onItemCheckedChange(item), - _selectedValues.any( - (element) => - widget.valueKey!(element) == - widget.valueKey!(item), - ), - ); - } else { - return InkWell( - onTap: () { - Navigator.pop(context, true); - - if (widget.onSelectItem != null) { - widget.onSelectItem!(item); - } - widget.onChangeState!(item); - }, - child: widget.itemBuilder( + ) + : SliverPadding( + padding: EdgeInsets.only( + left: 8, + top: 8, + right: 8, + bottom: !widget.multiSelect + ? MediaQuery.of(context).viewInsets.bottom + + MediaQuery.of(context).padding.bottom + + 8 + : 0, + ), + sliver: SuperSliverList( + delegate: SliverChildBuilderDelegate( + childCount: _list.length, + (context, index) { + final item = _list.toList()[index]; + + if (widget.multiSelect) { + return widget.itemBuilder( context, index, item, - null, - false, - ), - ); - } - }, + () => _onItemCheckedChange(item), + _selectedValues.any( + (element) => + widget.valueKey!(element) == + widget.valueKey!(item), + ), + ); + } else { + return InkWell( + onTap: () { + Navigator.pop(context, true); + + if (widget.onSelectItem != null) { + widget.onSelectItem!(item); + } + widget.onChangeState!(item); + }, + child: widget.itemBuilder( + context, + index, + item, + null, + false, + ), + ); + } + }, + ), ), ), - ), - ], + ], + ), ), ), if (widget.multiSelect) Container( decoration: const BoxDecoration( - color: GrxColors.cfff2f7fd, + color: GrxColors.cffffffff, border: Border( top: BorderSide( color: GrxColors.cffe0efff, diff --git a/lib/widgets/bottom_sheet/grx_bottom_sheet_grabber.widget.dart b/lib/widgets/bottom_sheet/grx_bottom_sheet_grabber.widget.dart index cfc5cd2..4c779ed 100644 --- a/lib/widgets/bottom_sheet/grx_bottom_sheet_grabber.widget.dart +++ b/lib/widgets/bottom_sheet/grx_bottom_sheet_grabber.widget.dart @@ -23,7 +23,7 @@ class _GrxBottomSheetGrabberState extends State { children: [ Container( decoration: const BoxDecoration( - color: GrxColors.cfff2f7fd, + color: GrxColors.cffffffff, borderRadius: BorderRadius.only( topLeft: Radius.circular(20), topRight: Radius.circular(20), @@ -35,7 +35,7 @@ class _GrxBottomSheetGrabberState extends State { children: [ Container( decoration: const BoxDecoration( - color: GrxColors.cff9bb2ce, + color: GrxColors.cffd6dfea, borderRadius: BorderRadius.all( Radius.circular(2), ), @@ -47,7 +47,7 @@ class _GrxBottomSheetGrabberState extends State { padding: const EdgeInsets.all(15), child: GrxHeadlineMediumText( widget.title ?? 'Selecione uma Opção', - color: GrxColors.cff83a6cf, + color: GrxColors.cff2e2e2e, textAlign: TextAlign.center, ), ), diff --git a/lib/widgets/buttons/grx_animated_loading_button.widget.dart b/lib/widgets/buttons/grx_animated_loading_button.widget.dart index 432096c..9f54a1e 100644 --- a/lib/widgets/buttons/grx_animated_loading_button.widget.dart +++ b/lib/widgets/buttons/grx_animated_loading_button.widget.dart @@ -1,6 +1,7 @@ import 'package:flutter/widgets.dart'; -import 'package:rounded_loading_button/rounded_loading_button.dart'; +import 'package:rounded_loading_button_plus/rounded_loading_button.dart'; +import '../../controllers/grx_animated_loading_button.controller.dart'; import '../../enums/grx_text_transform.enum.dart'; import '../../themes/colors/grx_colors.dart'; import '../typography/grx_headline_small_text.widget.dart'; @@ -18,12 +19,14 @@ class GrxAnimatedLoadingButton extends StatelessWidget { this.width, this.margin, this.animateOnTap = false, - final RoundedLoadingButtonController? controller, - }) : controller = controller ?? RoundedLoadingButtonController(), + final double? borderRadius, + final GrxAnimatedLoadingButtonController? controller, + }) : controller = controller ?? GrxAnimatedLoadingButtonController(), + borderRadius = borderRadius ?? height / 2.0, assert(text != null || textSpan != null); - final RoundedLoadingButtonController controller; - final void Function(RoundedLoadingButtonController controller) onPressed; + final GrxAnimatedLoadingButtonController controller; + final void Function(GrxAnimatedLoadingButtonController controller) onPressed; final String? text; final InlineSpan? textSpan; final GrxTextTransform transform; @@ -31,6 +34,7 @@ class GrxAnimatedLoadingButton extends StatelessWidget { final Color backgroundColor; final double height; final double? width; + final double borderRadius; final EdgeInsets? margin; final bool animateOnTap; @@ -40,17 +44,13 @@ class GrxAnimatedLoadingButton extends StatelessWidget { return Container( margin: margin, - child: RoundedLoadingButton( - controller: controller, - onPressed: () => onPressed(controller), - borderRadius: height / 2, - color: backgroundColor, - errorColor: GrxColors.cfffc5858, - successColor: GrxColors.cff75f3ab, - animateOnTap: animateOnTap, - width: this.width ?? width, + child: ValueListenableBuilder( + valueListenable: controller.hasStarted, child: Padding( - padding: const EdgeInsets.symmetric(vertical: 12.0, horizontal: 20.0), + padding: const EdgeInsets.symmetric( + vertical: 12.0, + horizontal: 24.0, + ), child: textSpan != null ? GrxHeadlineSmallText.rich( textSpan, @@ -65,6 +65,20 @@ class GrxAnimatedLoadingButton extends StatelessWidget { transform: transform, ), ), + builder: (BuildContext context, bool value, child) { + return RoundedLoadingButton( + controller: controller, + onPressed: () => onPressed(controller), + borderRadius: + controller.hasStarted.value ? height / 2 : borderRadius, + color: backgroundColor, + errorColor: GrxColors.cfffc5858, + successColor: GrxColors.primarySwatch, + animateOnTap: animateOnTap, + width: this.width ?? width, + child: child!, + ); + }, ), ); } diff --git a/lib/widgets/buttons/grx_bottom_button.widget.dart b/lib/widgets/buttons/grx_bottom_button.widget.dart index b91d535..3854127 100644 --- a/lib/widgets/buttons/grx_bottom_button.widget.dart +++ b/lib/widgets/buttons/grx_bottom_button.widget.dart @@ -17,6 +17,7 @@ class GrxBottomButton extends StatelessWidget { this.iconSize = 23, this.iconColor, this.iconPadding = 5, + this.isLoading = false, }); final String text; @@ -27,6 +28,7 @@ class GrxBottomButton extends StatelessWidget { final double iconSize; final Color? iconColor; final double iconPadding; + final bool isLoading; @override Widget build(BuildContext context) { @@ -39,9 +41,13 @@ class GrxBottomButton extends StatelessWidget { left: 25, top: 22, right: 25, - bottom: 22 + MediaQuery.of(context).viewPadding.bottom, + bottom: 22 + MediaQuery.viewPaddingOf(context).bottom, ), - backgroundColor: GrxColors.cff69efa3, + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.zero, + side: BorderSide.none, + ), + backgroundColor: GrxColors.primarySwatch, foregroundColor: GrxColors.cffffffff, style: const GrxHeadlineMediumTextStyle(), icon: icon, @@ -50,6 +56,7 @@ class GrxBottomButton extends StatelessWidget { iconColor: iconColor, iconPadding: iconPadding, onPressed: onPressed, + isLoading: isLoading, ); } } diff --git a/lib/widgets/buttons/grx_button.widget.dart b/lib/widgets/buttons/grx_button.widget.dart index 297c16d..3bc5454 100644 --- a/lib/widgets/buttons/grx_button.widget.dart +++ b/lib/widgets/buttons/grx_button.widget.dart @@ -1,11 +1,14 @@ import 'package:flutter/material.dart'; +import 'package:flutter/scheduler.dart'; +import 'package:grex_ds/utils/grx_utils.util.dart'; import '../../enums/grx_align.enum.dart'; import '../../enums/grx_text_transform.enum.dart'; import '../../themes/colors/grx_colors.dart'; +import '../grx_measure_size.widget.dart'; import '../typography/grx_headline_small_text.widget.dart'; -class GrxButton extends StatelessWidget { +class GrxButton extends StatefulWidget { const GrxButton({ super.key, required this.foregroundColor, @@ -26,6 +29,7 @@ class GrxButton extends StatelessWidget { this.shape, this.padding = const EdgeInsets.symmetric(vertical: 12, horizontal: 20), this.style, + this.isLoading = false, }) : assert(text != null || textSpan != null); final String? text; @@ -46,20 +50,28 @@ class GrxButton extends StatelessWidget { final OutlinedBorder? shape; final EdgeInsetsGeometry padding; final TextStyle? style; + final bool isLoading; + + @override + State createState() => _GrxButtonState(); +} + +class _GrxButtonState extends State { + Size? childSize; Widget _createWidgetIcon() { - final iconAlignLeft = iconAlign == GrxAlign.left; + final iconAlignLeft = widget.iconAlign == GrxAlign.left; return Visibility( - visible: icon != null, + visible: widget.icon != null, child: Padding( padding: EdgeInsets.only( - left: iconAlignLeft ? 0 : iconPadding, - right: iconAlignLeft ? iconPadding : 0), + left: iconAlignLeft ? 0 : widget.iconPadding, + right: iconAlignLeft ? widget.iconPadding : 0), child: Icon( - icon, - size: iconSize, - color: iconColor ?? foregroundColor, + widget.icon, + size: widget.iconSize, + color: widget.iconColor ?? widget.foregroundColor, ), ), ); @@ -69,60 +81,83 @@ class GrxButton extends StatelessWidget { required final Widget child, required final ButtonStyle style, }) => - backgroundColor != null + widget.backgroundColor != null ? ElevatedButton( - onPressed: onPressed, + onPressed: widget.onPressed, style: style, child: child, ) : TextButton( - onPressed: onPressed, + onPressed: widget.onPressed, style: style, child: child, ); @override Widget build(BuildContext context) { - final isTextButton = backgroundColor == null; + final isTextButton = widget.backgroundColor == null; final children = [ _createWidgetIcon(), Flexible( - child: textSpan != null + child: widget.textSpan != null ? GrxHeadlineSmallText.rich( - textSpan, - color: foregroundColor, + widget.textSpan, + color: widget.foregroundColor, textAlign: TextAlign.center, - transform: transform, + transform: widget.transform, ) : GrxHeadlineSmallText( - text, - color: foregroundColor, + widget.text, + color: widget.foregroundColor, textAlign: TextAlign.center, - transform: transform, + transform: widget.transform, ), ), ]; return Container( - margin: margin, - height: height, + margin: widget.margin, + height: widget.height, child: _getButton( style: ElevatedButton.styleFrom( foregroundColor: GrxColors.cff7593b5, - elevation: isTextButton ? null : elevation, - padding: padding, - backgroundColor: backgroundColor, + elevation: isTextButton ? null : widget.elevation, + padding: widget.padding, + backgroundColor: widget.backgroundColor, disabledBackgroundColor: isTextButton ? Theme.of(context).colorScheme.onSurface.withOpacity(0.12) : null, - shape: shape, + shape: widget.shape, ), - child: Row( - mainAxisSize: isTextButton ? MainAxisSize.min : mainAxisSize, - mainAxisAlignment: MainAxisAlignment.center, - children: iconAlign == GrxAlign.left - ? children - : children.reversed.toList(), + child: AnimatedSwitcher( + duration: GrxUtils.defaultAnimationDuration, + child: widget.isLoading + ? SizedBox( + height: childSize?.height, + width: childSize?.height, + child: Center( + child: CircularProgressIndicator( + strokeWidth: 2.5, + valueColor: AlwaysStoppedAnimation( + widget.foregroundColor, + ), + ), + ), + ) + : MeasureSize( + onChange: (size) { + SchedulerBinding.instance.addPostFrameCallback( + (_) => setState( + () => childSize = size, + ), + ); + }, + child: Row( + mainAxisSize: widget.mainAxisSize, + mainAxisAlignment: MainAxisAlignment.center, + children: children, + ), + ), ), ), ); diff --git a/lib/widgets/buttons/grx_floating_action_button.widget.dart b/lib/widgets/buttons/grx_floating_action_button.widget.dart index dede430..1138121 100644 --- a/lib/widgets/buttons/grx_floating_action_button.widget.dart +++ b/lib/widgets/buttons/grx_floating_action_button.widget.dart @@ -4,7 +4,7 @@ import '../../themes/colors/grx_colors.dart'; import '../../themes/icons/grx_icons.dart'; import '../../utils/grx_utils.util.dart'; -const _kSize = 70.0; +const _kSize = 50.0; const _kBorder = _kSize / 2.0; const _kBorderRadius = BorderRadius.all(Radius.circular(_kBorder)); final _kShape = @@ -24,10 +24,8 @@ class GrxFloatingActionButton extends StatelessWidget { @override Widget build(BuildContext context) { - return ElevatedButton( - onPressed: isLoading ? null : onPressed, - style: ElevatedButton.styleFrom( - shape: _kShape, padding: const EdgeInsets.all(0.0), elevation: 0), + return InkWell( + onTap: isLoading ? null : onPressed, child: Material( elevation: 10, shape: _kShape, diff --git a/lib/widgets/buttons/grx_icon_button.widget.dart b/lib/widgets/buttons/grx_icon_button.widget.dart index 0a800ed..1da5db0 100644 --- a/lib/widgets/buttons/grx_icon_button.widget.dart +++ b/lib/widgets/buttons/grx_icon_button.widget.dart @@ -8,7 +8,7 @@ class GrxIconButton extends StatelessWidget { required this.icon, required this.onPressed, this.iconSize = 24.0, - this.color = GrxColors.cff75f3ab, + this.color = GrxColors.primarySwatch, this.margin, }); diff --git a/lib/widgets/buttons/grx_primary_button.widget.dart b/lib/widgets/buttons/grx_primary_button.widget.dart index 5404371..dba58dd 100644 --- a/lib/widgets/buttons/grx_primary_button.widget.dart +++ b/lib/widgets/buttons/grx_primary_button.widget.dart @@ -15,6 +15,7 @@ class GrxPrimaryButton extends GrxRoundedButton { super.iconSize, super.iconColor, super.iconPadding, + super.borderRadius, }) : super( backgroundColor: GrxColors.cff69efa3, foregroundColor: GrxColors.cffffffff, diff --git a/lib/widgets/buttons/grx_rounded_button.widget.dart b/lib/widgets/buttons/grx_rounded_button.widget.dart index d73a956..7ad4fea 100644 --- a/lib/widgets/buttons/grx_rounded_button.widget.dart +++ b/lib/widgets/buttons/grx_rounded_button.widget.dart @@ -22,7 +22,8 @@ class GrxRoundedButton extends StatelessWidget { this.iconColor, this.iconPadding = 5.0, this.elevation = 5.0, - }); + final double? borderRadius, + }) : borderRadius = borderRadius ?? height / 2.0; final String? text; final InlineSpan? textSpan; @@ -39,6 +40,7 @@ class GrxRoundedButton extends StatelessWidget { final Color? iconColor; final double iconPadding; final double elevation; + final double borderRadius; @override Widget build(BuildContext context) { @@ -60,7 +62,7 @@ class GrxRoundedButton extends StatelessWidget { elevation: elevation, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular( - (height / 2), + borderRadius, ), ), ); diff --git a/lib/widgets/buttons/grx_secondary_button.widget.dart b/lib/widgets/buttons/grx_secondary_button.widget.dart index 260b96e..db0fcb5 100644 --- a/lib/widgets/buttons/grx_secondary_button.widget.dart +++ b/lib/widgets/buttons/grx_secondary_button.widget.dart @@ -15,6 +15,7 @@ class GrxSecondaryButton extends GrxRoundedButton { super.iconSize, super.iconColor, super.iconPadding, + super.borderRadius, }) : super( backgroundColor: GrxColors.cffffffff, foregroundColor: GrxColors.cff7593b5, diff --git a/lib/widgets/buttons/grx_tertiary_button.widget.dart b/lib/widgets/buttons/grx_tertiary_button.widget.dart index f195219..21305ef 100644 --- a/lib/widgets/buttons/grx_tertiary_button.widget.dart +++ b/lib/widgets/buttons/grx_tertiary_button.widget.dart @@ -15,5 +15,6 @@ class GrxTertiaryButton extends GrxRoundedButton { super.iconSize, super.iconColor, super.iconPadding, + super.borderRadius, }); } diff --git a/lib/widgets/checkbox/grx_checkbox.widget.dart b/lib/widgets/checkbox/grx_checkbox.widget.dart index e3b5f54..488542b 100644 --- a/lib/widgets/checkbox/grx_checkbox.widget.dart +++ b/lib/widgets/checkbox/grx_checkbox.widget.dart @@ -6,12 +6,12 @@ import '../../utils/grx_utils.util.dart'; class GrxCheckbox extends StatelessWidget { const GrxCheckbox({ super.key, - this.isChecked = false, + this.value = false, this.enabled = true, this.isLoading = false, }); - final bool isChecked; + final bool value; final bool enabled; final bool isLoading; @@ -35,7 +35,7 @@ class GrxCheckbox extends StatelessWidget { child: AnimatedContainer( duration: GrxUtils.defaultAnimationDuration, decoration: BoxDecoration( - color: isChecked ? GrxColors.cff289fff : Colors.transparent, + color: value ? GrxColors.cff289fff : Colors.transparent, borderRadius: BorderRadius.circular(2.0), ), ), diff --git a/lib/widgets/checkbox/grx_checkbox_list_tile.widget.dart b/lib/widgets/checkbox/grx_checkbox_list_tile.widget.dart index 679927d..213a088 100644 --- a/lib/widgets/checkbox/grx_checkbox_list_tile.widget.dart +++ b/lib/widgets/checkbox/grx_checkbox_list_tile.widget.dart @@ -6,7 +6,7 @@ import 'grx_checkbox.widget.dart'; class GrxCheckboxListTile extends StatelessWidget { final String title; - final bool isChecked; + final bool value; final void Function()? onTap; final bool enabled; final bool isLoading; @@ -14,7 +14,7 @@ class GrxCheckboxListTile extends StatelessWidget { const GrxCheckboxListTile({ super.key, required this.title, - this.isChecked = false, + this.value = false, this.onTap, this.enabled = true, this.isLoading = false, @@ -32,7 +32,7 @@ class GrxCheckboxListTile extends StatelessWidget { mainAxisAlignment: MainAxisAlignment.start, children: [ GrxCheckbox( - isChecked: isChecked, + value: value, enabled: enabled, isLoading: isLoading, ), diff --git a/lib/widgets/checkbox/grx_rounded_checkbox.widget.dart b/lib/widgets/checkbox/grx_rounded_checkbox.widget.dart index 16f5074..0f7a3dd 100644 --- a/lib/widgets/checkbox/grx_rounded_checkbox.widget.dart +++ b/lib/widgets/checkbox/grx_rounded_checkbox.widget.dart @@ -6,7 +6,7 @@ import '../../utils/grx_utils.util.dart'; class GrxRoundedCheckbox extends StatefulWidget { const GrxRoundedCheckbox({ super.key, - this.initialValue = false, + this.value = false, this.radius = 18, this.onChanged, this.isTappable = true, @@ -14,7 +14,7 @@ class GrxRoundedCheckbox extends StatefulWidget { this.isLoading = false, }); - final bool initialValue; + final bool value; final double radius; final Function(bool)? onChanged; final bool isTappable; @@ -32,14 +32,14 @@ class _GrxRoundedCheckboxState extends State { void initState() { super.initState(); - _value = widget.initialValue; + _value = widget.value; } @override void didUpdateWidget(GrxRoundedCheckbox oldWidget) { super.didUpdateWidget(oldWidget); - _value = widget.initialValue; + _value = widget.value; } @override diff --git a/lib/widgets/fields/controllers/grx_form_field.controller.dart b/lib/widgets/fields/controllers/grx_form_field.controller.dart new file mode 100644 index 0000000..e48f386 --- /dev/null +++ b/lib/widgets/fields/controllers/grx_form_field.controller.dart @@ -0,0 +1,92 @@ +import 'dart:async'; + +import 'package:flutter/material.dart'; +import 'package:mask_text_input_formatter/mask_text_input_formatter.dart'; + +class GrxFormFieldController extends TextEditingController { + GrxFormFieldController({ + super.text, + final String? mask, + }) : maskFormatter = mask?.isNotEmpty ?? false + ? MaskTextInputFormatter( + mask: '#####-###', + filter: { + "#": RegExp(r'[0-9]'), + }, + initialText: text, + type: text?.isNotEmpty ?? false + ? MaskAutoCompletionType.eager + : MaskAutoCompletionType.lazy, + ) + : null; + + final StreamController onClearStream = StreamController.broadcast(); + final StreamController> onDidUpdateData = + StreamController.broadcast(); + final StreamController<(T?, bool)> onDidUpdateValue = + StreamController.broadcast(); + + late final MaskTextInputFormatter? maskFormatter; + + @override + bool get hasListeners => super.hasListeners; + + @override + void dispose() { + onClearStream.close(); + onDidUpdateData.close(); + onDidUpdateValue.close(); + + super.dispose(); + } + + @override + void clear() { + super.clear(); + + onClearStream.sink.add(null); + } + + void updateData(Iterable data) { + onDidUpdateData.sink.add(data); + } + + void updateValue( + T? value, { + bool notifyListeners = true, + }) { + if (maskFormatter != null) { + if (value is String) { + value = maskText(value)! as T; + + maskFormatter?.updateMask( + mask: maskFormatter?.getMask(), + newValue: TextEditingValue( + text: value as String, + ), + ); + } + } + + onDidUpdateValue.sink.add((value, notifyListeners)); + } + + TextEditingValue? updateMask( + String? mask, { + TextEditingValue? newValue, + }) => + maskFormatter?.updateMask( + mask: mask, + newValue: newValue, + ); + + String? getMaskedText() => maskFormatter?.getMaskedText(); + + String? getUnmaskedText() => maskFormatter?.getUnmaskedText(); + + String? maskText(String text) => maskFormatter?.maskText(text); + + String? getMask() => maskFormatter?.getMask(); + + void clearMask() => maskFormatter?.clear(); +} diff --git a/lib/widgets/fields/grx_autocomplete_dropdown_form_field.widget.dart b/lib/widgets/fields/grx_autocomplete_dropdown_form_field.widget.dart new file mode 100644 index 0000000..2d350fd --- /dev/null +++ b/lib/widgets/fields/grx_autocomplete_dropdown_form_field.widget.dart @@ -0,0 +1,249 @@ +import 'dart:async'; + +import 'package:flutter/material.dart'; + +import '../../extensions/list.extension.dart'; +import '../../utils/grx_form_field.util.dart'; +import '../grx_stateful.widget.dart'; +import '../typography/grx_caption_text.widget.dart'; +import 'controllers/grx_form_field.controller.dart'; +import 'grx_form_field.widget.dart'; +import 'grx_text_field.widget.dart'; +import 'shimmers/grx_form_field_shimmer.widget.dart'; + +class GrxAutocompleteDropdownFormField extends GrxStatefulWidget { + GrxAutocompleteDropdownFormField({ + final Key? key, + required this.labelText, + required this.displayText, + this.controller, + this.itemBuilder, + this.onSaved, + this.hintText, + this.selectBottomSheetTitle, + this.value, + this.defaultValue, + this.autovalidateMode = AutovalidateMode.always, + this.onSelectItem, + this.onSearch, + this.validator, + this.searchable = false, + this.enabled = true, + this.flexible = false, + this.isLoading = false, + this.setValueOnSelectItem = true, + }) : super( + key: key ?? ValueKey(labelText.hashCode), + ); + + final GrxFormFieldController? controller; + final String labelText; + final String? hintText; + final String? selectBottomSheetTitle; + final Widget Function(BuildContext context, int index, T item, + void Function(T) onSelectItem)? itemBuilder; + final String Function(T data) displayText; + final String? value; + final String? defaultValue; + final AutovalidateMode autovalidateMode; + final void Function(T?)? onSelectItem; + final Future?> Function(String?)? onSearch; + final FormFieldSetter? onSaved; + final FormFieldValidator? validator; + final bool searchable; + final bool enabled; + final bool flexible; + final bool isLoading; + final bool setValueOnSelectItem; + + @override + State createState() => _GrxDropdownStateFormField(); +} + +class _GrxDropdownStateFormField + extends State> { + final List _list = []; + + late final GrxFormFieldController controller; + final MenuController menuController = MenuController(); + final TextEditingController quickSearchFieldController = + TextEditingController(); + + Timer? _timer; + bool _isSearching = false; + var _notifyListeners = true; + + @override + void initState() { + super.initState(); + + _list.clear(); + + controller = widget.controller ?? GrxFormFieldController(); + + if (widget.value != null) { + controller.text = widget.value!; + } + + _subscribeStreams(); + } + + @override + void dispose() { + if (widget.controller == null) { + controller.dispose(); + } + + _cancelTimer(); + + super.dispose(); + } + + void _subscribeStreams() { + controller.onClearStream.stream.listen((_) { + _list.clear(); + }); + + controller.onDidUpdateValue.stream.listen((data) { + final (value, notifyListeners) = data; + + _notifyListeners = notifyListeners; + + if (value?.isEmpty ?? true) { + controller.clear(); + return; + } + + controller.text = value!; + }); + } + + void _cancelTimer() { + if (_timer?.isActive ?? false) { + _timer?.cancel(); + } + } + + void _onSelectItem(T item) { + if (widget.setValueOnSelectItem) { + _notifyListeners = false; + + this.controller.text = widget.displayText(item); + } + + widget.onSelectItem?.call(item); + } + + @override + Widget build(BuildContext context) { + if (widget.isLoading) { + return GrxFormFieldShimmer( + labelText: widget.labelText, + ); + } + + return GrxFormField( + initialValue: controller.text, + autovalidateMode: widget.autovalidateMode, + validator: (value) => widget.validator?.call(value), + onSaved: (value) => widget.onSaved?.call(value), + enabled: widget.enabled, + flexible: widget.flexible, + builder: (FormFieldState field) { + GrxFormFieldUtils.onValueChange( + field, + controller, + onChanged: (value) { + if (!_notifyListeners) { + _notifyListeners = true; + return; + } + + _cancelTimer(); + + _timer = Timer( + const Duration(milliseconds: 500), + () async { + try { + setState(() { + _isSearching = true; + }); + final result = await widget.onSearch?.call(value); + + if (result != null) { + setState(() { + _list.clear(); + _list.assignAll(result); + }); + + if (result.isNotEmpty) { + menuController.open(); + } else { + menuController.close(); + } + } + } finally { + setState(() { + _isSearching = false; + }); + } + }, + ); + }, + ); + + return LayoutBuilder( + builder: (context, constraints) { + return MenuAnchor( + controller: menuController, + menuChildren: _list + .map( + (item) => + widget.itemBuilder?.call(context, _list.indexOf(item), + item, _onSelectItem) ?? + MenuItemButton( + onPressed: () => _onSelectItem(item), + child: SizedBox( + width: constraints.constrainWidth() - 24, + child: GrxCaptionText( + widget.displayText(item), + ), + ), + ), + ) + .toList(), + child: GrxTextField( + controller: controller, + hintText: widget.hintText, + labelText: widget.labelText, + errorText: field.errorText, + enabled: widget.enabled, + suffix: _isSearching + ? const CircularProgressIndicator.adaptive( + strokeWidth: 2.0, + ) + : const SizedBox.shrink(), + onClear: () { + menuController.close(); + + if (widget.defaultValue?.isNotEmpty ?? false) { + controller.text = widget.defaultValue!; + } else { + controller.clear(); + } + }, + onTap: () async { + if (menuController.isOpen) { + menuController.close(); + } else if (_list.isNotEmpty) { + menuController.open(); + } + }, + ), + ); + }, + ); + }, + ); + } +} diff --git a/lib/widgets/fields/grx_custom_dropdown_form_field.widget.dart b/lib/widgets/fields/grx_custom_dropdown_form_field.widget.dart index 151b40a..3ceaf99 100644 --- a/lib/widgets/fields/grx_custom_dropdown_form_field.widget.dart +++ b/lib/widgets/fields/grx_custom_dropdown_form_field.widget.dart @@ -3,6 +3,8 @@ import 'package:flutter/material.dart'; import '../../services/grx_bottom_sheet.service.dart'; import '../../utils/grx_form_field.util.dart'; import '../grx_stateful.widget.dart'; +import 'controllers/grx_form_field.controller.dart'; +import 'grx_form_field.widget.dart'; import 'grx_text_field.widget.dart'; import 'shimmers/grx_form_field_shimmer.widget.dart'; @@ -15,26 +17,34 @@ class GrxCustomDropdownFormField extends GrxStatefulWidget { this.controller, this.onSaved, this.hintText, - this.initialValue, + this.selectBottomSheetTitle, + this.value, + this.defaultValue, + this.autovalidateMode = AutovalidateMode.always, this.onSelectItem, this.validator, this.enabled = true, + this.flexible = false, this.isLoading = false, }) : super( key: key ?? ValueKey(labelText.hashCode), ); - final TextEditingController? controller; + final GrxFormFieldController? controller; final String labelText; final String? hintText; + final String? selectBottomSheetTitle; final Widget Function(ScrollController? scrollController, T? selectedValue) builder; final String Function(T data) displayText; - final T? initialValue; + final T? value; + final T? defaultValue; + final AutovalidateMode autovalidateMode; final void Function(T?)? onSelectItem; - final void Function(T?)? onSaved; - final String? Function(String?)? validator; + final FormFieldSetter? onSaved; + final FormFieldValidator? validator; final bool enabled; + final bool flexible; final bool isLoading; @override @@ -44,23 +54,52 @@ class GrxCustomDropdownFormField extends GrxStatefulWidget { class _GrxDropdownStateFormField extends State> { T? value; - late final TextEditingController controller; + late final GrxFormFieldController controller; final TextEditingController quickSearchFieldController = TextEditingController(); @override void initState() { - controller = widget.controller ?? TextEditingController(); + super.initState(); + + controller = widget.controller ?? GrxFormFieldController(); - if (widget.initialValue != null && value == null) { - value = widget.initialValue; + if (widget.value != null && value == null) { + value = widget.value; controller.text = widget.displayText(value as T); if (widget.onSelectItem != null) { widget.onSelectItem!(value); } } - super.initState(); + _subscribeStreams(); + } + + @override + void dispose() { + if (widget.controller == null) { + controller.dispose(); + } + + super.dispose(); + } + + void _subscribeStreams() { + controller.onClearStream.stream.listen((_) { + value = null; + }); + + controller.onDidUpdateValue.stream.listen((data) { + final (value, _) = data; + + if (value == null) { + controller.clear(); + return; + } + + this.value = value; + controller.text = widget.displayText(value); + }); } @override @@ -71,19 +110,20 @@ class _GrxDropdownStateFormField ); } - return FormField( + return GrxFormField( initialValue: controller.text, - autovalidateMode: AutovalidateMode.always, - validator: widget.validator, - onSaved: (_) => widget.onSaved != null ? widget.onSaved!(value) : null, + autovalidateMode: widget.autovalidateMode, + validator: (_) => widget.validator?.call(value), + onSaved: (_) => widget.onSaved?.call(value), enabled: widget.enabled, + flexible: widget.flexible, builder: (FormFieldState field) { GrxFormFieldUtils.onValueChange( field, controller, onChanged: (value) { - if (value.isEmpty && widget.onSelectItem != null) { - widget.onSelectItem!(null); + if (value.isEmpty) { + widget.onSelectItem?.call(null); this.value = null; } }, @@ -96,9 +136,24 @@ class _GrxDropdownStateFormField labelText: widget.labelText, errorText: field.errorText, enabled: widget.enabled, + onClear: () { + setState( + () { + value = widget.defaultValue; + + if (widget.defaultValue != null) { + controller.text = + widget.displayText(widget.defaultValue as T); + } else { + controller.clear(); + } + }, + ); + }, onTap: () async { final bottomSheet = GrxBottomSheetService( context: context, + title: widget.selectBottomSheetTitle, builder: (controller) => widget.builder( controller, value, diff --git a/lib/widgets/fields/grx_date_time_picker_form_field.widget.dart b/lib/widgets/fields/grx_date_time_picker_form_field.widget.dart index 2ba57cf..2030087 100644 --- a/lib/widgets/fields/grx_date_time_picker_form_field.widget.dart +++ b/lib/widgets/fields/grx_date_time_picker_form_field.widget.dart @@ -3,6 +3,8 @@ import 'package:intl/intl.dart'; import '../../utils/grx_form_field.util.dart'; import '../grx_stateful.widget.dart'; +import 'controllers/grx_form_field.controller.dart'; +import 'grx_form_field.widget.dart'; import 'grx_text_field.widget.dart'; import 'shimmers/grx_form_field_shimmer.widget.dart'; @@ -11,36 +13,42 @@ class GrxDateTimePickerFormField extends GrxStatefulWidget { final Key? key, required this.labelText, this.controller, - this.initialValue, + this.value, this.hintText, this.dialogConfirmText = 'Confirm', this.dialogCancelText = 'Cancel', this.dialogErrorFormatText = 'Invalid Format', this.dialogErrorInvalidText = 'Provided date is not valid', + this.autovalidateMode = AutovalidateMode.always, this.onSelectItem, this.onSaved, this.validator, + this.focusNode, this.isDateTime = false, this.enabled = true, + this.flexible = false, this.futureDate = false, this.isLoading = false, }) : super( key: key ?? ValueKey(labelText.hashCode), ); - final TextEditingController? controller; - final DateTime? initialValue; + final GrxFormFieldController? controller; + final DateTime? value; final String labelText; final String? hintText; final String dialogConfirmText; final String dialogCancelText; final String dialogErrorFormatText; final String dialogErrorInvalidText; + final AutovalidateMode autovalidateMode; final void Function(DateTime?)? onSelectItem; final FormFieldSetter? onSaved; - final FormFieldValidator? validator; + final FormFieldValidator? validator; + final FocusNode? focusNode; final bool isDateTime; final bool enabled; + final bool flexible; final bool futureDate; final bool isLoading; @@ -51,29 +59,58 @@ class GrxDateTimePickerFormField extends GrxStatefulWidget { class _GrxDateTimePickerFormFieldState extends State { late final String locale; - late final TextEditingController controller; + late final GrxFormFieldController controller; DateTime? value; @override void initState() { - controller = widget.controller ?? TextEditingController(); + super.initState(); + + controller = widget.controller ?? GrxFormFieldController(); - if (widget.initialValue != null && value == null) { - value = widget.initialValue; + if (widget.value != null && value == null) { + value = widget.value; controller.text = _formatValue(value!); if (widget.onSelectItem != null) { widget.onSelectItem!(value); } } - super.initState(); + _subscribeStreams(); + } + + @override + void dispose() { + if (widget.controller == null) { + controller.dispose(); + } + + super.dispose(); } String _formatValue(DateTime value) { return '${DateFormat.yMd().format(value)}${widget.isDateTime ? ' ${DateFormat.Hm().format(value)}' : ''}'; } + void _subscribeStreams() { + controller.onClearStream.stream.listen((_) { + value = null; + }); + + controller.onDidUpdateValue.stream.listen((data) { + final (value, _) = data; + + if (value == null) { + controller.clear(); + return; + } + + this.value = value; + controller.text = _formatValue(value); + }); + } + @override Widget build(_) { if (widget.isLoading) { @@ -82,18 +119,20 @@ class _GrxDateTimePickerFormFieldState ); } - return FormField( - autovalidateMode: AutovalidateMode.always, - initialValue: widget.initialValue?.toIso8601String(), - validator: widget.validator, - onSaved: (_) => widget.onSaved != null ? widget.onSaved!(value) : null, + return GrxFormField( + initialValue: widget.value?.toIso8601String(), + autovalidateMode: widget.autovalidateMode, + validator: (_) => widget.validator?.call(value), + onSaved: (_) => widget.onSaved?.call(value), + enabled: widget.enabled, + flexible: widget.flexible, builder: (FormFieldState field) { GrxFormFieldUtils.onValueChange( field, controller, onChanged: (value) { - if (value.isEmpty && widget.onSelectItem != null) { - widget.onSelectItem!(null); + if (value.isEmpty) { + widget.onSelectItem?.call(null); this.value = null; } }, @@ -104,6 +143,7 @@ class _GrxDateTimePickerFormFieldState readOnly: true, hintText: widget.hintText, labelText: widget.labelText, + focusNode: widget.focusNode, errorText: field.errorText, onTap: () async { final today = DateTime.now(); diff --git a/lib/widgets/fields/grx_dropdown_form_field.widget.dart b/lib/widgets/fields/grx_dropdown_form_field.widget.dart index edc2fdf..5261095 100644 --- a/lib/widgets/fields/grx_dropdown_form_field.widget.dart +++ b/lib/widgets/fields/grx_dropdown_form_field.widget.dart @@ -1,12 +1,15 @@ import 'package:flutter/material.dart'; +import '../../extensions/list.extension.dart'; import '../../services/grx_bottom_sheet.service.dart'; -import '../../themes/colors/grx_colors.dart'; import '../../utils/grx_form_field.util.dart'; import '../bottom_sheet/grx_bottom_sheet_form_field_body.widget.dart'; import '../checkbox/grx_rounded_checkbox.widget.dart'; +import '../grx_card.widget.dart'; import '../grx_stateful.widget.dart'; -import '../typography/grx_headline_medium_text.widget.dart'; +import '../typography/grx_headline_small_text.widget.dart'; +import 'controllers/grx_form_field.controller.dart'; +import 'grx_form_field.widget.dart'; import 'grx_text_field.widget.dart'; import 'shimmers/grx_form_field_shimmer.widget.dart'; @@ -20,28 +23,36 @@ class GrxDropdownFormField extends GrxStatefulWidget { this.itemBuilder, this.onSaved, this.hintText, - this.initialValue, + this.selectBottomSheetTitle, + this.value, + this.defaultValue, + this.autovalidateMode = AutovalidateMode.always, this.onSelectItem, this.validator, this.searchable = false, this.enabled = true, + this.flexible = false, this.isLoading = false, }) : super( key: key ?? ValueKey(labelText.hashCode), ); - final TextEditingController? controller; + final GrxFormFieldController? controller; final String labelText; final String? hintText; + final String? selectBottomSheetTitle; final Iterable data; final Widget Function(BuildContext, int, T)? itemBuilder; final String Function(T data) displayText; - final T? initialValue; + final T? value; + final T? defaultValue; + final AutovalidateMode autovalidateMode; final void Function(T?)? onSelectItem; - final void Function(T?)? onSaved; - final String? Function(String?)? validator; + final FormFieldSetter? onSaved; + final FormFieldValidator? validator; final bool searchable; final bool enabled; + final bool flexible; final bool isLoading; @override @@ -51,54 +62,78 @@ class GrxDropdownFormField extends GrxStatefulWidget { class _GrxDropdownStateFormField extends State> { T? value; final List _list = []; - late final TextEditingController controller; + late final GrxFormFieldController controller; final TextEditingController quickSearchFieldController = TextEditingController(); @override void initState() { + super.initState(); + _list.clear(); _list.addAll(widget.data); - controller = widget.controller ?? TextEditingController(); + controller = widget.controller ?? GrxFormFieldController(); - if (widget.initialValue != null && value == null) { - value = widget.initialValue; + if (widget.value != null && value == null) { + value = widget.value; controller.text = widget.displayText(value as T); if (widget.onSelectItem != null) { widget.onSelectItem!(value); } } - super.initState(); + _subscribeStreams(); } - Widget _defaultItemBuild(BuildContext context, int index, T value) { - const decoration = BoxDecoration( - border: Border( - bottom: BorderSide( - width: 1.0, - color: GrxColors.cffe0efff, - ), - ), - ); + @override + void dispose() { + if (widget.controller == null) { + controller.dispose(); + } + + super.dispose(); + } + + void _subscribeStreams() { + controller.onClearStream.stream.listen((_) { + value = null; + }); + + controller.onDidUpdateData.stream.listen((data) { + _list.assignAll(data); + }); - return Container( - padding: const EdgeInsets.symmetric(vertical: 20.0, horizontal: 10.0), - decoration: index == widget.data.length - 1 ? null : decoration, - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - GrxHeadlineMediumText( - widget.displayText(value), - ), - if (this.value == value) - const GrxRoundedCheckbox( + controller.onDidUpdateValue.stream.listen((data) { + final (value, _) = data; + + if (value == null) { + controller.clear(); + return; + } + + this.value = value; + controller.text = widget.displayText(value); + }); + } + + Widget _defaultItemBuild(BuildContext context, int index, T value) { + return GrxCard( + child: Container( + padding: const EdgeInsets.all(16.0), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + GrxHeadlineSmallText( + widget.displayText(value), + ), + GrxRoundedCheckbox( radius: 8.0, isTappable: false, - initialValue: true, + value: this.value == value, ), - ], + ], + ), ), ); } @@ -111,12 +146,13 @@ class _GrxDropdownStateFormField extends State> { ); } - return FormField( + return GrxFormField( initialValue: controller.text, - autovalidateMode: AutovalidateMode.always, - validator: widget.validator, - onSaved: (_) => widget.onSaved != null ? widget.onSaved!(value) : null, + autovalidateMode: widget.autovalidateMode, + validator: (_) => widget.validator?.call(value), + onSaved: (_) => widget.onSaved?.call(value), enabled: widget.enabled, + flexible: widget.flexible, builder: (FormFieldState field) { GrxFormFieldUtils.onValueChange( field, @@ -136,9 +172,26 @@ class _GrxDropdownStateFormField extends State> { labelText: widget.labelText, errorText: field.errorText, enabled: widget.enabled, + onClear: () { + setState( + () { + value = widget.defaultValue; + + if (widget.defaultValue != null) { + controller.text = + widget.displayText(widget.defaultValue as T); + + widget.onSelectItem?.call(value); + } else { + controller.clear(); + } + }, + ); + }, onTap: () async { final bottomSheet = GrxBottomSheetService( context: context, + title: widget.selectBottomSheetTitle, builder: (controller) { return StatefulBuilder( builder: (BuildContext context, StateSetter setModalState) { diff --git a/lib/widgets/fields/grx_filter_field.widget.dart b/lib/widgets/fields/grx_filter_field.widget.dart deleted file mode 100644 index 2f8ec49..0000000 --- a/lib/widgets/fields/grx_filter_field.widget.dart +++ /dev/null @@ -1,75 +0,0 @@ -import 'package:flutter/material.dart'; - -import '../../themes/colors/grx_colors.dart'; -import '../../themes/icons/grx_icons.dart'; -import '../../themes/typography/styles/grx_caption_large_text.style.dart'; -import '../buttons/grx_clear_input_button.widget.dart'; - -const _inputTextStyle = GrxCaptionLargeTextStyle(color: GrxColors.cff7892b7); - -class GrxFilterField extends StatelessWidget { - final TextEditingController searchFieldController; - final Function(String) onChanged; - final String hintText; - - const GrxFilterField({ - super.key, - required this.searchFieldController, - required this.onChanged, - required this.hintText, - }); - - @override - Widget build(BuildContext context) { - return FormField( - builder: (FormFieldState field) { - return TextField( - controller: searchFieldController, - autocorrect: false, - style: _inputTextStyle, - decoration: InputDecoration( - suffixIconConstraints: const BoxConstraints( - minHeight: 24, - minWidth: 40, - ), - isDense: true, - border: const OutlineInputBorder( - borderRadius: BorderRadius.all( - Radius.circular(5.0), - ), - borderSide: BorderSide( - width: 0, - style: BorderStyle.none, - ), - ), - focusedBorder: const OutlineInputBorder( - borderRadius: BorderRadius.all( - Radius.circular(5.0), - ), - borderSide: BorderSide( - width: 0, - style: BorderStyle.none, - ), - ), - fillColor: GrxColors.cffe8f2ff, - filled: true, - suffixIcon: searchFieldController.text.isEmpty - ? const Icon( - GrxIcons.search, - color: GrxColors.cff9bb2ce, - ) - : GrxClearInputButton( - onClear: () { - searchFieldController.clear(); - onChanged(searchFieldController.text); - }, - ), - hintText: hintText, - hintStyle: _inputTextStyle, - ), - onChanged: onChanged, - ); - }, - ); - } -} diff --git a/lib/widgets/fields/grx_form_field.widget.dart b/lib/widgets/fields/grx_form_field.widget.dart new file mode 100644 index 0000000..5c5923b --- /dev/null +++ b/lib/widgets/fields/grx_form_field.widget.dart @@ -0,0 +1,40 @@ +import 'package:flutter/material.dart'; + +class GrxFormField extends StatelessWidget { + const GrxFormField({ + super.key, + required this.builder, + this.initialValue, + this.autovalidateMode = AutovalidateMode.always, + this.validator, + this.onSaved, + this.enabled = true, + this.flexible = false, + }); + + final Widget Function(FormFieldState) builder; + final T? initialValue; + final AutovalidateMode? autovalidateMode; + final String? Function(T?)? validator; + final void Function(T?)? onSaved; + final bool enabled; + final bool flexible; + + @override + Widget build(BuildContext context) { + final formField = FormField( + initialValue: initialValue, + autovalidateMode: autovalidateMode, + validator: validator, + onSaved: onSaved, + enabled: enabled, + builder: builder, + ); + + return flexible + ? Flexible( + child: formField, + ) + : formField; + } +} diff --git a/lib/widgets/fields/grx_input_decoration.widget.dart b/lib/widgets/fields/grx_input_decoration.widget.dart index e048f09..a984880 100644 --- a/lib/widgets/fields/grx_input_decoration.widget.dart +++ b/lib/widgets/fields/grx_input_decoration.widget.dart @@ -12,9 +12,12 @@ class GrxInputDecoration extends InputDecoration { super.contentPadding, super.hintMaxLines, super.errorText, + super.prefix, + super.suffixIconConstraints, this.onClear, super.enabled = true, this.showClearButton = false, + final Widget? suffix, }) : super( labelStyle: GrxFieldStyles.labelTextStyle, floatingLabelStyle: GrxFieldStyles.labelTextStyle, @@ -27,8 +30,12 @@ class GrxInputDecoration extends InputDecoration { errorStyle: GrxFieldStyles.inputErrorTextStyle, focusedErrorBorder: GrxFieldStyles.underlineInputFocusedErrorBorder, hintStyle: GrxFieldStyles.inputHintTextStyle, - suffix: showClearButton - ? Padding( + suffix: Row( + mainAxisSize: MainAxisSize.min, + children: [ + if (suffix != null) suffix, + if (showClearButton) + Padding( padding: const EdgeInsets.symmetric(horizontal: 10), child: Container( padding: const EdgeInsets.all(3), @@ -41,7 +48,8 @@ class GrxInputDecoration extends InputDecoration { ), ), ) - : null, + ], + ), ); final void Function()? onClear; diff --git a/lib/widgets/fields/grx_multi_select_form_field.widget.dart b/lib/widgets/fields/grx_multi_select_form_field.widget.dart index f4d45ad..f19e58d 100644 --- a/lib/widgets/fields/grx_multi_select_form_field.widget.dart +++ b/lib/widgets/fields/grx_multi_select_form_field.widget.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; +import '../../extensions/list.extension.dart'; import '../../services/grx_bottom_sheet.service.dart'; import '../../themes/colors/grx_colors.dart'; import '../../themes/fields/grx_field_styles.theme.dart'; @@ -7,6 +8,8 @@ import '../bottom_sheet/grx_bottom_sheet_form_field_body.widget.dart'; import '../grx_chip.widget.dart'; import '../grx_stateful.widget.dart'; import '../typography/grx_caption_text.widget.dart'; +import 'controllers/grx_form_field.controller.dart'; +import 'grx_form_field.widget.dart'; import 'grx_input_decoration.widget.dart'; import 'shimmers/grx_form_field_shimmer.widget.dart'; @@ -21,10 +24,13 @@ class GrxMultiSelectFormField extends GrxStatefulWidget { this.onSaved, this.controller, this.hintText, - this.initialValue, + this.selectBottomSheetTitle, + this.value, + this.autovalidateMode = AutovalidateMode.always, this.onSelectItems, this.validator, this.enabled = true, + this.flexible = false, this.searchable = false, this.confirmButtonLabel, this.cancelButtonLabel, @@ -33,19 +39,22 @@ class GrxMultiSelectFormField extends GrxStatefulWidget { key: key ?? ValueKey(labelText.hashCode), ); - final TextEditingController? controller; + final GrxFormFieldController? controller; final String labelText; final String? hintText; + final String? selectBottomSheetTitle; final Iterable data; final Widget Function(BuildContext context, int index, T value, void Function()? onChanged, bool isSelected) itemBuilder; final String Function(T data) displayText; final int Function(T data) valueKey; - final Iterable? initialValue; + final Iterable? value; + final AutovalidateMode autovalidateMode; final void Function(Iterable?)? onSelectItems; final FormFieldSetter>? onSaved; final FormFieldValidator>? validator; final bool enabled; + final bool flexible; final bool searchable; final bool isLoading; final String? confirmButtonLabel; @@ -59,26 +68,59 @@ class _GrxMultiSelectStateFormField extends State> { Iterable? values; final List _list = []; - late final TextEditingController controller; + late final GrxFormFieldController controller; final TextEditingController quickSearchFieldController = TextEditingController(); final FocusNode inputFocusNode = FocusNode(); @override void initState() { + super.initState(); + _list.clear(); _list.addAll(widget.data); - controller = widget.controller ?? TextEditingController(); + controller = widget.controller ?? GrxFormFieldController(); - if (widget.initialValue != null && values == null) { - values = widget.initialValue; + if (widget.value != null && values == null) { + values = widget.value; if (widget.onSelectItems != null) { widget.onSelectItems!(values); } } - super.initState(); + _subscribeStreams(); + } + + @override + void dispose() { + if (widget.controller == null) { + controller.dispose(); + } + + super.dispose(); + } + + void _subscribeStreams() { + controller.onClearStream.stream.listen((_) { + values = null; + }); + + controller.onDidUpdateData.stream.listen((data) { + _list.assignAll(data); + }); + + controller.onDidUpdateValue.stream.listen((data) { + final (value, _) = data; + + if (value == null) { + controller.clear(); + return; + } + + this.values = [...(this.values?.toList() ?? []), value]; + controller.text = widget.displayText(value); + }); } @override @@ -89,12 +131,13 @@ class _GrxMultiSelectStateFormField ); } - return FormField>( - initialValue: widget.initialValue, - autovalidateMode: AutovalidateMode.always, + return GrxFormField>( + initialValue: widget.value, + autovalidateMode: widget.autovalidateMode, validator: widget.validator, onSaved: (_) => widget.onSaved != null ? widget.onSaved!(values) : null, enabled: widget.enabled, + flexible: widget.flexible, builder: (FormFieldState> field) { List buildSelectedOptions(state) { List selectedOptions = []; @@ -132,6 +175,7 @@ class _GrxMultiSelectStateFormField final bottomSheet = GrxBottomSheetService( context: field.context, + title: widget.selectBottomSheetTitle, builder: (controller) { return StatefulBuilder( builder: (BuildContext context, StateSetter setModalState) { diff --git a/lib/widgets/fields/grx_phone_form_field.widget.dart b/lib/widgets/fields/grx_phone_form_field.widget.dart new file mode 100644 index 0000000..b29bd6e --- /dev/null +++ b/lib/widgets/fields/grx_phone_form_field.widget.dart @@ -0,0 +1,239 @@ +import 'package:flutter/material.dart'; +import 'package:mask_text_input_formatter/mask_text_input_formatter.dart'; + +import '../../enums/grx_country_id.enum.dart'; +import '../../models/grx_country.model.dart'; +import '../../services/grx_bottom_sheet.service.dart'; +import '../../themes/colors/grx_colors.dart'; +import '../../themes/icons/grx_icons.dart'; +import '../../utils/grx_country.util.dart'; +import '../../utils/grx_utils.util.dart'; +import '../bottom_sheet/ds_bottom_sheet_countries.widget.dart'; +import '../grx_stateful.widget.dart'; +import '../media/grx_svg.widget.dart'; +import '../typography/grx_caption_large_text.widget.dart'; +import 'controllers/grx_form_field.controller.dart'; +import 'grx_text_form_field.widget.dart'; + +class GrxPhoneFormField extends GrxStatefulWidget { + GrxPhoneFormField({ + final Key? key, + required this.labelText, + this.controller, + this.value, + this.country, + this.keyboardType, + this.obscureText = false, + this.onChanged, + this.onSaved, + this.validator, + this.contentPadding, + this.textCapitalization = TextCapitalization.sentences, + this.textAlignVertical = TextAlignVertical.center, + this.maxLines = 1, + this.alignLabelWithHint = false, + this.hintText, + this.selectBottomSheetTitle, + this.hintMaxLines, + this.autovalidateMode = AutovalidateMode.always, + this.textInputAction = TextInputAction.next, + this.onFieldSubmitted, + this.focusNode, + this.autoFocus = false, + this.enabled = true, + this.flexible = false, + this.isLoading = false, + }) : super( + key: key ?? ValueKey(labelText.hashCode), + ); + + final GrxFormFieldController? controller; + final String? value; + final GrxCountryId? country; + final String labelText; + final TextInputType? keyboardType; + final bool obscureText; + final void Function(String? value, GrxCountryId? country)? onChanged; + final void Function(String? value, GrxCountryId? country)? onSaved; + final FormFieldValidator? validator; + final EdgeInsets? contentPadding; + final TextCapitalization textCapitalization; + final TextAlignVertical textAlignVertical; + final int? maxLines; + final bool alignLabelWithHint; + final String? hintText; + final String? selectBottomSheetTitle; + final int? hintMaxLines; + final AutovalidateMode autovalidateMode; + final TextInputAction textInputAction; + final void Function(String? value, GrxCountryId? country)? onFieldSubmitted; + final FocusNode? focusNode; + final bool autoFocus; + final bool enabled; + final bool flexible; + final bool isLoading; + + @override + State createState() => _GrxPhoneFormFieldState(); +} + +class _GrxPhoneFormFieldState extends State { + late final controller = widget.controller ?? GrxFormFieldController(); + late final maskFormatter = MaskTextInputFormatter( + mask: _getMask( + country: selectedCountry, + value: widget.value, + ), + filter: { + "#": RegExp(r'[0-9]'), + }, + initialText: widget.value, + type: widget.value?.isNotEmpty ?? false + ? MaskAutoCompletionType.eager + : MaskAutoCompletionType.lazy, + ); + + late GrxCountry selectedCountry = + GrxCountryUtils.getCountry(widget.country) ?? + GrxCountryUtils.countries.first; + + String _getMask({ + required final GrxCountry country, + final String? value, + }) { + switch (country.id) { + case GrxCountryId.BR: + return (value?.replaceAll(RegExp('[^0-9]'), '').length ?? 0) <= 10 + ? country.phoneMasks[0] + : country.phoneMasks[1]; + default: + return country.phoneMasks.isNotEmpty + ? country.phoneMasks[0] + : '###############'; + } + } + + String? _getFullNumber() { + final phone = maskFormatter.getUnmaskedText(); + return phone.isNotEmpty + ? '${selectedCountry.code}${maskFormatter.getUnmaskedText()}' + : null; + } + + @override + void dispose() { + if (widget.controller == null) { + controller.dispose(); + } + + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return GrxTextFormField( + controller: controller, + value: maskFormatter.getMaskedText(), + labelText: widget.labelText, + keyboardType: widget.keyboardType, + obscureText: widget.obscureText, + prefix: Row( + mainAxisSize: MainAxisSize.min, + children: [ + InkWell( + onTap: () async { + final bottomSheet = GrxBottomSheetService( + context: context, + title: widget.selectBottomSheetTitle ?? 'Select Country', + builder: (controller) { + return GrxBottomSheetCountries( + selectedCountry: selectedCountry, + ); + }, + ); + + final result = await bottomSheet.show(); + + if (result != null) { + setState(() { + selectedCountry = result; + }); + + controller.value = maskFormatter.updateMask( + mask: _getMask( + country: selectedCountry, + value: controller.text, + ), + ); + } + }, + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + GrxSvg( + 'assets/svgs/flags/${selectedCountry.flag}.svg', + package: GrxUtils.packageName, + width: 22.0, + ), + const Padding( + padding: EdgeInsets.symmetric(horizontal: 4.0), + child: Icon( + GrxIcons.arrow_drop_down, + size: 18.0, + color: GrxColors.cff2e2e2e, + ), + ), + ], + ), + ), + Padding( + padding: const EdgeInsets.only(right: 4.0), + child: GrxCaptionLargeText( + selectedCountry.code, + ), + ), + ], + ), + onChanged: (value) { + if (value?.isNotEmpty ?? false) { + final rawText = maskFormatter.getUnmaskedText(); + + if (rawText.length == 10 || rawText.length == 11) { + controller.value = maskFormatter.updateMask( + mask: _getMask( + country: selectedCountry, + value: rawText, + ), + ); + } + } else { + maskFormatter.clear(); + } + + widget.onChanged?.call(value, selectedCountry.id); + }, + onSaved: (value) => + widget.onSaved?.call(_getFullNumber(), selectedCountry.id), + validator: widget.validator, + contentPadding: widget.contentPadding, + textCapitalization: widget.textCapitalization, + textAlignVertical: widget.textAlignVertical, + maxLines: widget.maxLines, + alignLabelWithHint: widget.alignLabelWithHint, + hintText: widget.hintText, + hintMaxLines: widget.hintMaxLines, + autovalidateMode: widget.autovalidateMode, + textInputAction: widget.textInputAction, + onFieldSubmitted: (value) => + widget.onFieldSubmitted?.call(_getFullNumber(), selectedCountry.id), + focusNode: widget.focusNode, + autoFocus: widget.autoFocus, + enabled: widget.enabled, + flexible: widget.flexible, + inputFormatters: [ + maskFormatter, + ], + isLoading: widget.isLoading, + ); + } +} diff --git a/lib/widgets/fields/grx_search_field.widget.dart b/lib/widgets/fields/grx_search_field.widget.dart index b774278..79f7249 100644 --- a/lib/widgets/fields/grx_search_field.widget.dart +++ b/lib/widgets/fields/grx_search_field.widget.dart @@ -1,8 +1,14 @@ import 'package:flutter/material.dart'; import '../../themes/colors/grx_colors.dart'; -import '../../themes/fields/grx_field_styles.theme.dart'; import '../../themes/icons/grx_icons.dart'; +import '../../themes/typography/styles/grx_caption_large_text.style.dart'; +import '../buttons/grx_clear_input_button.widget.dart'; +import 'grx_form_field.widget.dart'; + +const _inputTextStyle = GrxCaptionLargeTextStyle( + color: GrxColors.cff365278, +); class GrxSearchField extends StatelessWidget { const GrxSearchField({ @@ -10,48 +16,66 @@ class GrxSearchField extends StatelessWidget { required this.onChanged, required this.hintText, this.searchFieldController, + this.flexible = false, }); + final TextEditingController? searchFieldController; final Function(String) onChanged; final String hintText; - final TextEditingController? searchFieldController; + final bool flexible; @override Widget build(BuildContext context) { - return TextFormField( - controller: searchFieldController, - autocorrect: false, - decoration: InputDecoration( - isDense: true, - contentPadding: const EdgeInsets.only(left: 15), - border: const OutlineInputBorder( - borderRadius: BorderRadius.all( - Radius.circular(5.0), - ), - borderSide: BorderSide( - width: 0, - style: BorderStyle.none, - ), - ), - focusedBorder: const OutlineInputBorder( - borderRadius: BorderRadius.all( - Radius.circular(5.0), - ), - borderSide: BorderSide( - width: 0, - style: BorderStyle.none, + return GrxFormField( + flexible: flexible, + builder: (FormFieldState field) { + return TextField( + controller: searchFieldController, + autocorrect: false, + style: _inputTextStyle, + decoration: InputDecoration( + suffixIconConstraints: const BoxConstraints( + minHeight: 24, + minWidth: 40, + ), + isDense: true, + border: const OutlineInputBorder( + borderRadius: BorderRadius.all( + Radius.circular(5.0), + ), + borderSide: BorderSide( + width: 0, + style: BorderStyle.none, + ), + ), + focusedBorder: const OutlineInputBorder( + borderRadius: BorderRadius.all( + Radius.circular(5.0), + ), + borderSide: BorderSide( + width: 0, + style: BorderStyle.none, + ), + ), + fillColor: GrxColors.cffffffff, + filled: true, + suffixIcon: searchFieldController?.text.isEmpty ?? true + ? const Icon( + GrxIcons.search, + color: GrxColors.cff9bb2ce, + ) + : GrxClearInputButton( + onClear: () { + searchFieldController?.clear(); + onChanged(searchFieldController?.text ?? ''); + }, + ), + hintText: hintText, + hintStyle: _inputTextStyle, ), - ), - fillColor: GrxColors.cffe8f2ff, - filled: true, - suffixIcon: const Icon( - GrxIcons.search, - color: GrxColors.cff9bb2ce, - ), - hintText: hintText, - hintStyle: GrxFieldStyles.inputHintTextStyle, - ), - onChanged: onChanged, + onChanged: onChanged, + ); + }, ); } } diff --git a/lib/widgets/fields/grx_switch_form_field.widget.dart b/lib/widgets/fields/grx_switch_form_field.widget.dart index dda80f3..c260e39 100644 --- a/lib/widgets/fields/grx_switch_form_field.widget.dart +++ b/lib/widgets/fields/grx_switch_form_field.widget.dart @@ -1,35 +1,36 @@ -import 'dart:io'; - +import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/scheduler.dart'; import '../../themes/colors/grx_colors.dart'; import '../../themes/typography/styles/grx_headline_small_text.style.dart'; import '../cupertino/cupertino_switch_list_tile.dart'; +import 'grx_form_field.widget.dart'; /// A Design System's [FormField] used like a switch -class GrxSwitchFormField extends FormField { +class GrxSwitchFormField extends GrxFormField { GrxSwitchFormField({ final Key? key, required this.labelText, this.onChanged, + this.overflow, this.changeOnInitialValue = false, + this.isLoading = false, final void Function(bool)? onSaved, final TextStyle? style, - final bool? initialValue, - final bool enabled = true, - this.isLoading = false, + final bool? value, + super.enabled, + super.flexible, }) : super( key: key ?? ValueKey(labelText.hashCode), - initialValue: initialValue, + initialValue: value, onSaved: onSaved != null ? (value) => onSaved(value ?? false) : null, autovalidateMode: AutovalidateMode.always, - enabled: enabled, builder: (FormFieldState state) { if (changeOnInitialValue) { SchedulerBinding.instance.addPostFrameCallback((_) { - if (state.value != initialValue) { - state.didChange(initialValue); + if (state.value != value) { + state.didChange(value); } }); } @@ -45,11 +46,12 @@ class GrxSwitchFormField extends FormField { color: GrxColors.cff2e2e2e.withOpacity(opacity), ); - return Platform.isIOS + return defaultTargetPlatform == TargetPlatform.iOS ? CupertinoSwitchListTile( title: Text( labelText, style: style ?? defaultInputLabel, + overflow: overflow, ), value: state.value ?? false, activeColor: GrxColors.cff6bbaf0, @@ -60,6 +62,7 @@ class GrxSwitchFormField extends FormField { title: Text( labelText, style: style ?? defaultInputLabel, + overflow: overflow, ), value: state.value ?? false, activeColor: GrxColors.cff6bbaf0, @@ -71,6 +74,7 @@ class GrxSwitchFormField extends FormField { final String labelText; final void Function(bool)? onChanged; + final TextOverflow? overflow; final bool changeOnInitialValue; final bool isLoading; } diff --git a/lib/widgets/fields/grx_text_field.widget.dart b/lib/widgets/fields/grx_text_field.widget.dart index 2d44539..9f9410c 100644 --- a/lib/widgets/fields/grx_text_field.widget.dart +++ b/lib/widgets/fields/grx_text_field.widget.dart @@ -15,28 +15,31 @@ class GrxTextField extends TextField { super.autofocus, super.inputFormatters, super.onTap, - required final TextEditingController controller, + super.onChanged, + super.autofillHints, + required TextEditingController super.controller, final String? labelText, final bool enabled = true, - final bool autocorrect = false, + super.autocorrect = false, final EdgeInsets? contentPadding, - final TextCapitalization textCapitalization = TextCapitalization.sentences, - final TextAlignVertical textAlignVertical = TextAlignVertical.center, + super.textCapitalization = TextCapitalization.sentences, + TextAlignVertical super.textAlignVertical = TextAlignVertical.center, final int? maxLines = 1, final bool alignLabelWithHint = false, final String? hintText, final int? hintMaxLines, final String? errorText, - final TextInputAction textInputAction = TextInputAction.done, + TextInputAction super.textInputAction = TextInputAction.next, + final void Function()? onClear, + final bool showClearButton = true, + final Widget? prefix, + final Widget? suffix, + final TextStyle? style, + final BoxConstraints? suffixIconConstraints, }) : super( - controller: controller, - textCapitalization: textCapitalization, - autocorrect: autocorrect, - cursorColor: GrxColors.cff70efa7, - style: GrxFieldStyles.inputTextStyle, - textInputAction: textInputAction, + cursorColor: GrxColors.primarySwatch, + style: style ?? GrxFieldStyles.inputTextStyle, maxLines: obscureText ? 1 : maxLines, - textAlignVertical: textAlignVertical, decoration: GrxInputDecoration( labelText: labelText, alignLabelWithHint: alignLabelWithHint, @@ -45,8 +48,12 @@ class GrxTextField extends TextField { hintMaxLines: hintMaxLines, errorText: errorText, enabled: enabled, - onClear: controller.clear, - showClearButton: controller.text.isNotEmpty && enabled, + onClear: onClear?.call ?? controller.clear, + showClearButton: + showClearButton && controller.text.isNotEmpty && enabled, + prefix: prefix, + suffix: suffix, + suffixIconConstraints: suffixIconConstraints, ), ); } diff --git a/lib/widgets/fields/grx_text_form_field.widget.dart b/lib/widgets/fields/grx_text_form_field.widget.dart index b955a22..386983b 100644 --- a/lib/widgets/fields/grx_text_form_field.widget.dart +++ b/lib/widgets/fields/grx_text_form_field.widget.dart @@ -3,6 +3,8 @@ import 'package:flutter/services.dart'; import '../../utils/grx_form_field.util.dart'; import '../grx_stateful.widget.dart'; +import 'controllers/grx_form_field.controller.dart'; +import 'grx_form_field.widget.dart'; import 'grx_text_field.widget.dart'; import 'shimmers/grx_form_field_shimmer.widget.dart'; @@ -12,7 +14,7 @@ class GrxTextFormField extends GrxStatefulWidget { final Key? key, required this.labelText, this.controller, - this.initialValue, + this.value, this.keyboardType, this.obscureText = false, this.onChanged, @@ -26,24 +28,28 @@ class GrxTextFormField extends GrxStatefulWidget { this.hintText, this.hintMaxLines, this.autovalidateMode = AutovalidateMode.always, - this.textInputAction = TextInputAction.done, + this.textInputAction = TextInputAction.next, this.onFieldSubmitted, this.focusNode, + this.autofillHints, this.autoFocus = false, this.enabled = true, + this.flexible = false, this.inputFormatters, this.isLoading = false, + this.prefix, + this.mask, }) : super( key: key ?? ValueKey(labelText.hashCode), ); - final TextEditingController? controller; - final String? initialValue; + final GrxFormFieldController? controller; + final String? value; final String labelText; final TextInputType? keyboardType; final bool obscureText; final void Function(String?)? onChanged; - final void Function(String?)? onSaved; + final FormFieldSetter? onSaved; final FormFieldValidator? validator; final EdgeInsets? contentPadding; final TextCapitalization textCapitalization; @@ -56,30 +62,63 @@ class GrxTextFormField extends GrxStatefulWidget { final TextInputAction textInputAction; final void Function(String?)? onFieldSubmitted; final FocusNode? focusNode; + final Iterable? autofillHints; final bool autoFocus; final bool enabled; + final bool flexible; final List? inputFormatters; final bool isLoading; + final Widget? prefix; + final String? mask; @override State createState() => _GrxTextFormFieldState(); } class _GrxTextFormFieldState extends State { - late final TextEditingController controller; + late final GrxFormFieldController controller; + + var _notifyListeners = true; @override void initState() { - controller = widget.controller ?? TextEditingController(); + super.initState(); - if (widget.initialValue != null) { - controller.text = widget.initialValue!; + controller = + widget.controller ?? GrxFormFieldController(mask: widget.mask); + + if (widget.value != null) { + controller.text = widget.value!; if (widget.onChanged != null) { widget.onChanged!(controller.text); } } - super.initState(); + _subscribeStreams(); + } + + @override + void dispose() { + if (widget.controller == null) { + controller.dispose(); + } + + super.dispose(); + } + + void _subscribeStreams() { + controller.onDidUpdateValue.stream.listen((data) { + final (value, notifyListeners) = data; + + _notifyListeners = notifyListeners; + + if (value?.isEmpty ?? true) { + controller.clear(); + return; + } + + controller.text = value!; + }); } @override @@ -90,16 +129,25 @@ class _GrxTextFormFieldState extends State { ); } - return FormField( + return GrxFormField( autovalidateMode: widget.autovalidateMode, - initialValue: widget.initialValue, + initialValue: widget.value, onSaved: widget.onSaved, validator: widget.validator, + enabled: widget.enabled, + flexible: widget.flexible, builder: (FormFieldState field) { GrxFormFieldUtils.onValueChange( field, controller, - onChanged: widget.onChanged, + onChanged: (value) { + if (!_notifyListeners) { + _notifyListeners = true; + return; + } + + widget.onChanged?.call(value); + }, ); return GrxTextField( @@ -114,7 +162,11 @@ class _GrxTextFormFieldState extends State { maxLines: widget.obscureText ? 1 : widget.maxLines, textAlignVertical: widget.textAlignVertical, onSubmitted: widget.onFieldSubmitted, - inputFormatters: widget.inputFormatters, + autofillHints: widget.autofillHints, + inputFormatters: [ + if (controller.maskFormatter != null) controller.maskFormatter!, + ...(widget.inputFormatters ?? []), + ], labelText: widget.labelText, alignLabelWithHint: widget.alignLabelWithHint, contentPadding: widget.contentPadding, @@ -122,6 +174,7 @@ class _GrxTextFormFieldState extends State { hintMaxLines: widget.hintMaxLines, errorText: field.errorText, enabled: widget.enabled, + prefix: widget.prefix, ); }, ); diff --git a/lib/widgets/grx_card.widget.dart b/lib/widgets/grx_card.widget.dart new file mode 100644 index 0000000..97ed66f --- /dev/null +++ b/lib/widgets/grx_card.widget.dart @@ -0,0 +1,20 @@ +import 'package:flutter/material.dart'; + +class GrxCard extends Card { + GrxCard({ + super.key, + super.borderOnForeground, + super.child, + super.clipBehavior, + super.color, + super.elevation, + super.margin, + super.semanticContainer, + super.shadowColor, + super.surfaceTintColor = Colors.transparent, + }) : super( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8.0), + ), + ); +} diff --git a/lib/widgets/grx_chip.widget.dart b/lib/widgets/grx_chip.widget.dart index be90a81..a35b080 100644 --- a/lib/widgets/grx_chip.widget.dart +++ b/lib/widgets/grx_chip.widget.dart @@ -4,25 +4,33 @@ class GrxChip extends StatelessWidget { const GrxChip({ super.key, required this.label, - required this.backgroundColor, - this.contentPadding, - }); + this.backgroundColor = Colors.transparent, + this.borderColor = Colors.transparent, + this.contentPadding = const EdgeInsets.symmetric( + horizontal: 16.0, + vertical: 8.0, + ), + }) : assert( + backgroundColor != Colors.transparent || + borderColor != Colors.transparent, + ); final Widget label; final Color backgroundColor; - final EdgeInsetsGeometry? contentPadding; + final Color borderColor; + final EdgeInsetsGeometry contentPadding; @override Widget build(BuildContext context) { return Material( - shape: const StadiumBorder(), + shape: StadiumBorder( + side: BorderSide( + color: borderColor, + ), + ), color: backgroundColor, child: Padding( - padding: contentPadding ?? - const EdgeInsets.symmetric( - horizontal: 16, - vertical: 8, - ), + padding: contentPadding, child: label, ), ); diff --git a/lib/widgets/grx_dashed_divider.widget.dart b/lib/widgets/grx_dashed_divider.widget.dart index 9cd6180..da7322d 100644 --- a/lib/widgets/grx_dashed_divider.widget.dart +++ b/lib/widgets/grx_dashed_divider.widget.dart @@ -63,7 +63,7 @@ class GrxDashedDivider extends StatelessWidget { padding: const EdgeInsets.only(right: 10), child: GrxOverlineText( title!, - color: GrxColors.cffb2c1d0, + color: GrxColors.cff7892b7, ), ) : const SizedBox.shrink(), diff --git a/lib/widgets/grx_divider.widget.dart b/lib/widgets/grx_divider.widget.dart index 7bd4c0b..a963a0b 100644 --- a/lib/widgets/grx_divider.widget.dart +++ b/lib/widgets/grx_divider.widget.dart @@ -5,7 +5,7 @@ import '../themes/colors/grx_colors.dart'; class GrxDivider extends Divider { const GrxDivider({ super.key, - super.color = GrxColors.cffe0efff, + super.color = GrxColors.cffdeeaf3, super.height, super.thickness = 1, }); diff --git a/lib/widgets/grx_help.widget.dart b/lib/widgets/grx_help.widget.dart new file mode 100644 index 0000000..86df2d6 --- /dev/null +++ b/lib/widgets/grx_help.widget.dart @@ -0,0 +1,54 @@ +import 'package:flutter/material.dart'; +import 'package:popover/popover.dart'; + +import '../themes/colors/grx_colors.dart'; +import '../themes/icons/grx_icons.dart'; +import '../utils/grx_utils.util.dart'; +import 'typography/grx_caption_text.widget.dart'; + +class GrxHelpWidget extends StatelessWidget { + const GrxHelpWidget({ + super.key, + this.text, + this.body, + this.width, + }) : assert(text != null || body != null); + + final String? text; + final Widget? body; + final double? width; + + @override + Widget build(BuildContext context) { + final size = MediaQuery.of(context).size; + + return GestureDetector( + child: const Icon( + GrxIcons.help_outline, + color: GrxColors.cff83a6cf, + size: 20.0, + ), + onTap: () { + showPopover( + context: context, + direction: PopoverDirection.top, + transitionDuration: GrxUtils.defaultAnimationDuration, + width: width ?? size.width - 32.0, + arrowHeight: 15, + arrowWidth: 30, + bodyBuilder: (context) => + body ?? + Container( + padding: const EdgeInsets.all( + 15.0, + ), + child: GrxCaptionText( + text!, + overflow: TextOverflow.visible, + ), + ), + ); + }, + ); + } +} diff --git a/lib/widgets/grx_measure_size.widget.dart b/lib/widgets/grx_measure_size.widget.dart new file mode 100644 index 0000000..26687a9 --- /dev/null +++ b/lib/widgets/grx_measure_size.widget.dart @@ -0,0 +1,45 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/rendering.dart'; + +typedef OnWidgetSizeChange = void Function(Size size); + +class GrxMeasureSizeRenderObject extends RenderProxyBox { + Size? oldSize; + OnWidgetSizeChange onChange; + + GrxMeasureSizeRenderObject(this.onChange); + + @override + void performLayout() { + super.performLayout(); + + Size newSize = child!.size; + if (oldSize == newSize) return; + + oldSize = newSize; + WidgetsBinding.instance.addPostFrameCallback((_) { + onChange(newSize); + }); + } +} + +class MeasureSize extends SingleChildRenderObjectWidget { + final OnWidgetSizeChange onChange; + + const MeasureSize({ + super.key, + required this.onChange, + required Widget super.child, + }); + + @override + RenderObject createRenderObject(BuildContext context) { + return GrxMeasureSizeRenderObject(onChange); + } + + @override + void updateRenderObject( + BuildContext context, covariant GrxMeasureSizeRenderObject renderObject) { + renderObject.onChange = onChange; + } +} diff --git a/lib/widgets/grx_sliver_animated_list.widget.dart b/lib/widgets/grx_sliver_animated_list.widget.dart new file mode 100644 index 0000000..0bbf239 --- /dev/null +++ b/lib/widgets/grx_sliver_animated_list.widget.dart @@ -0,0 +1,161 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter/foundation.dart'; +import 'package:infinite_scroll_pagination/infinite_scroll_pagination.dart'; +import 'package:super_sliver_list/super_sliver_list.dart'; + +import '../animations/grx_fade_transition.animation.dart'; +import 'grx_spinner_loading.widget.dart'; +import 'headers/grx_searchable_sliver_header.widget.dart'; +import 'list/grx_list_empty.widget.dart'; +import 'list/grx_list_error.widget.dart'; +import 'list/grx_list_infinite_loading.widget.dart'; +import 'list/grx_list_infinite_loading_error.widget.dart'; +import 'list/grx_list_loading.widget.dart'; + +class GrxSliverAnimatedList extends StatelessWidget { + const GrxSliverAnimatedList({ + super.key, + required this.animationController, + required this.itemBuilder, + this.separatorBuilder, + this.loadingItemBuilder, + this.onRefresh, + this.list, + this.pagingController, + this.title, + this.header, + this.padding, + this.canPop = false, + }) : assert(title != null || header != null), + assert(list != null || pagingController != null); + + final AnimationController animationController; + final Widget Function(T item, int index) itemBuilder; + final Widget Function(BuildContext context, int index)? separatorBuilder; + final Widget Function()? loadingItemBuilder; + final Future Function()? onRefresh; + final Iterable? list; + final PagingController? pagingController; + final String? title; + final Widget? header; + final EdgeInsets? padding; + final bool canPop; + + Widget _buildItem(Widget child, int length, int index) { + final begin = clampDouble((1 / (length / index * 12)) * index, 0, 1); + + final contentAnimation = Tween(begin: 0.0, end: 1.0).animate( + CurvedAnimation( + parent: animationController, + curve: Interval( + begin, + 1.0, + curve: Curves.fastOutSlowIn, + ), + ), + ); + + return AnimatedBuilder( + animation: animationController, + child: child, + builder: (context, child) { + return GrxFadeTransition( + animation: contentAnimation, + child: child!, + ); + }, + ); + } + + @override + Widget build(BuildContext context) { + final padding = MediaQuery.of(context).padding; + + return CustomScrollView( + physics: [TargetPlatform.iOS, TargetPlatform.macOS] + .any((platform) => platform == defaultTargetPlatform) + ? null + : const BouncingScrollPhysics(), + slivers: [ + header ?? + GrxSearchableSliverHeader( + animationController: animationController, + canPop: canPop, + title: title!, + ), + if (onRefresh != null) + CupertinoSliverRefreshControl( + onRefresh: onRefresh!, + builder: (_, __, ___, ____, _____) => const Center( + child: Padding( + padding: EdgeInsets.all(8.0), + child: GrxSpinnerLoading(), + ), + ), + ), + SliverPadding( + padding: EdgeInsets.only( + left: this.padding?.left ?? 0.0, + top: this.padding?.top ?? 0.0, + right: this.padding?.right ?? 0.0, + bottom: (this.padding?.bottom ?? 16.0) + padding.bottom, + ), + sliver: pagingController != null + ? PagedSliverList.separated( + pagingController: pagingController!, + separatorBuilder: separatorBuilder ?? + (context, index) => const SizedBox.shrink(), + builderDelegate: PagedChildBuilderDelegate( + firstPageProgressIndicatorBuilder: (context) { + const loadingListSize = 10; + + return GrxListLoading( + itemBuilder: (index) => _buildItem( + loadingItemBuilder!(), + loadingListSize, + index, + ), + separatorBuilder: separatorBuilder, + animationController: animationController, + ); + }, + firstPageErrorIndicatorBuilder: (context) => GrxListError( + title: 'Algo deu errado!', + subTitle: + 'Encontramos um erro desconhecido ao tentar processar seus dados, por gentileza, tente novamente!', + animationController: animationController, + ), + noItemsFoundIndicatorBuilder: (context) => GrxListEmpty( + title: 'Nenhum item encontrado!', + subTitle: 'Não encontramos nenhum item para exibir.', + animationController: animationController, + ), + newPageErrorIndicatorBuilder: (context) => + GrxListInfiniteLoadingError( + text: 'Algo deu errado, por favor, tente novamente!', + onTap: pagingController!.retryLastFailedRequest, + ), + newPageProgressIndicatorBuilder: (context) => + const GrxListInfiniteLoading(), + itemBuilder: (context, item, index) => _buildItem( + itemBuilder(item, index), + pagingController!.itemList!.length, + index, + ), + ), + ) + : SuperSliverList( + delegate: SliverChildBuilderDelegate( + (context, index) => _buildItem( + itemBuilder(list!.elementAt(index), index), + list!.length, + index, + ), + childCount: list!.length, + ), + ), + ), + ], + ); + } +} diff --git a/lib/widgets/grx_spinner_loading.widget.dart b/lib/widgets/grx_spinner_loading.widget.dart new file mode 100644 index 0000000..0906acb --- /dev/null +++ b/lib/widgets/grx_spinner_loading.widget.dart @@ -0,0 +1,129 @@ +import 'dart:math'; + +import 'package:flutter/material.dart'; + +import '../themes/colors/grx_colors.dart'; + +class GrxSpinnerLoading extends StatefulWidget { + const GrxSpinnerLoading({ + super.key, + this.color = GrxColors.cff289fff, + this.lineWidth = 5.0, + this.size = 30.0, + this.duration = const Duration(milliseconds: 500), + this.controller, + }); + + final Color color; + final double size; + final double lineWidth; + final Duration duration; + final AnimationController? controller; + + @override + GrxSpinnerLoadingState createState() => GrxSpinnerLoadingState(); +} + +class GrxSpinnerLoadingState extends State + with SingleTickerProviderStateMixin { + late AnimationController _controller; + late Animation _animation; + + @override + void initState() { + super.initState(); + + _controller = (widget.controller ?? + AnimationController(vsync: this, duration: widget.duration)) + ..addListener(() => setState(() {})) + ..repeat(); + + _animation = Tween(begin: 0.0, end: 1.0).animate( + CurvedAnimation( + parent: _controller, + curve: const Interval(0.0, 1.0, curve: Curves.linear), + ), + ); + } + + @override + void dispose() { + if (widget.controller == null) { + _controller.dispose(); + } + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Stack( + children: [ + SizedBox.fromSize( + size: Size.square(widget.size), + child: Container( + decoration: BoxDecoration( + shape: BoxShape.circle, + color: Colors.transparent, + border: Border.all( + width: widget.lineWidth, + color: GrxColors.cffd2dfe6, + style: BorderStyle.solid, + ), + ), + ), + ), + Transform( + transform: Matrix4.identity() + ..rotateZ((_animation.value) * 6.0 * pi / 6.0), + alignment: FractionalOffset.center, + child: SizedBox.fromSize( + size: Size.square(widget.size), + child: CustomPaint( + foregroundPainter: Painter( + paintWidth: widget.lineWidth, + trackColor: widget.color, + progressPercent: _animation.value, + startAngle: pi * _animation.value, + ), + ), + ), + ), + ], + ); + } +} + +class Painter extends CustomPainter { + Painter({ + required this.paintWidth, + this.progressPercent, + this.startAngle, + required this.trackColor, + }) : trackPaint = Paint() + ..color = trackColor + ..style = PaintingStyle.stroke + ..strokeWidth = paintWidth + ..strokeCap = StrokeCap.round; + + final double paintWidth; + final Paint trackPaint; + final Color trackColor; + final double? progressPercent; + final double? startAngle; + + @override + void paint(Canvas canvas, Size size) { + final center = Offset(size.width / 2, size.height / 2); + final radius = (min(size.width, size.height) - paintWidth) / 2; + canvas.drawArc( + Rect.fromCircle(center: center, radius: radius), + startAngle!, + 1, + false, + trackPaint, + ); + } + + @override + bool shouldRepaint(CustomPainter oldDelegate) => true; +} diff --git a/lib/widgets/grx_stateful.widget.dart b/lib/widgets/grx_stateful.widget.dart index e82d237..aa9f934 100644 --- a/lib/widgets/grx_stateful.widget.dart +++ b/lib/widgets/grx_stateful.widget.dart @@ -1,7 +1,11 @@ import 'package:flutter/material.dart'; abstract class GrxStatefulWidget extends StatefulWidget { - GrxStatefulWidget({Key? key}) : super(key: key ?? UniqueKey()); + GrxStatefulWidget({ + Key? key, + }) : super( + key: key ?? UniqueKey(), + ); @override @factory diff --git a/lib/widgets/grx_user_avatar.widget.dart b/lib/widgets/grx_user_avatar.widget.dart index f4445d5..5730b40 100644 --- a/lib/widgets/grx_user_avatar.widget.dart +++ b/lib/widgets/grx_user_avatar.widget.dart @@ -66,85 +66,96 @@ class _GrxUserAvatarState extends State { ); } - return Stack( - fit: StackFit.loose, - clipBehavior: Clip.none, - children: [ - widget.imageFile != null - ? _buildAvatar( - context, - FileImage(widget.imageFile!), - ) - : widget.uri != null - ? CachedNetworkImage( - imageUrl: widget.uri.toString(), - imageBuilder: (context, image) => GestureDetector( - onTap: widget.openPreview - ? () { - Navigator.of(context).push( - FadePageRoute( - builder: (context) => ImagePreview( - image: image, - title: 'Preview', - heroTag: widget.heroTag, + return Container( + padding: const EdgeInsets.all(2.0), + decoration: BoxDecoration( + border: Border.all( + color: GrxColors.cff289fff, + width: 1.5, + ), + borderRadius: BorderRadius.circular(widget.radius + 2.0), + ), + child: Stack( + fit: StackFit.loose, + clipBehavior: Clip.none, + children: [ + widget.imageFile != null + ? _buildAvatar( + context, + FileImage(widget.imageFile!), + ) + : widget.uri != null + ? CachedNetworkImage( + imageUrl: widget.uri.toString(), + imageBuilder: (context, image) => GestureDetector( + onTap: widget.openPreview + ? () { + Navigator.of(context).push( + FadePageRoute( + builder: (context) => ImagePreview( + image: image, + title: 'Preview', + heroTag: widget.heroTag, + ), ), - ), - ); - } - : null, - child: widget.heroTag != null - ? Hero( - tag: widget.heroTag!, - transitionOnUserGestures: true, - child: _buildAvatar(context, image), - ) - : _buildAvatar(context, image), - ), - progressIndicatorBuilder: (context, url, downloadProgress) { - return SizedBox.fromSize( - size: Size.fromRadius(widget.radius), - child: CircularProgressIndicator( - value: downloadProgress.progress, - strokeWidth: 1, - ), - ); - }, - errorWidget: (context, url, error) => - const Icon(Icons.error), - ) - : (widget.text?.isNotEmpty ?? false) - ? CircleAvatar( - radius: widget.radius, - backgroundColor: widget.backgroundColor, - child: Padding( - padding: const EdgeInsets.all(2), - child: GrxBodyText( - RegExp( - widget.text!.split(' ').length >= 2 - ? GrxRegexUtils.fullNameAvatarRgx - : GrxRegexUtils.singleNameAvatarRgx, - ) - .allMatches(widget.text!) - .map((m) => m.group(0)) - .join() - .toUpperCase() - .substring(0, 2), - color: widget.textColor, - overflow: TextOverflow.clip, - textAlign: TextAlign.center, + ); + } + : null, + child: widget.heroTag != null + ? Hero( + tag: widget.heroTag!, + transitionOnUserGestures: true, + child: _buildAvatar(context, image), + ) + : _buildAvatar(context, image), + ), + progressIndicatorBuilder: + (context, url, downloadProgress) { + return SizedBox.fromSize( + size: Size.fromRadius(widget.radius), + child: CircularProgressIndicator( + value: downloadProgress.progress, + strokeWidth: 1, + ), + ); + }, + errorWidget: (context, url, error) => + const Icon(Icons.error), + ) + : (widget.text?.isNotEmpty ?? false) + ? CircleAvatar( + radius: widget.radius, + backgroundColor: widget.backgroundColor, + child: Padding( + padding: const EdgeInsets.all(2), + child: GrxBodyText( + RegExp( + widget.text!.split(' ').length >= 2 + ? GrxRegexUtils.fullNameAvatarRgx + : GrxRegexUtils.singleNameAvatarRgx, + ) + .allMatches(widget.text!) + .map((m) => m.group(0)) + .join() + .toUpperCase() + .substring(0, 2), + color: widget.textColor, + overflow: TextOverflow.clip, + textAlign: TextAlign.center, + ), + ), + ) + : CircleAvatar( + radius: widget.radius, + backgroundColor: widget.backgroundColor, + backgroundImage: const AssetImage( + 'assets/images/default-avatar.png', + package: GrxUtils.packageName, ), ), - ) - : CircleAvatar( - radius: widget.radius, - backgroundColor: widget.backgroundColor, - backgroundImage: const AssetImage( - 'assets/images/default-avatar.png', - package: GrxUtils.packageName, - ), - ), - _buildAvatarPickerIcon(context), - ], + _buildAvatarPickerIcon(context), + ], + ), ); } diff --git a/lib/widgets/headers/grx_animated_sliver_header.widget.dart b/lib/widgets/headers/grx_animated_sliver_header.widget.dart new file mode 100644 index 0000000..92cb904 --- /dev/null +++ b/lib/widgets/headers/grx_animated_sliver_header.widget.dart @@ -0,0 +1,30 @@ +import 'package:flutter/material.dart'; + +import '../../delegates/grx_animated_sliver_header.delegate.dart'; + +class GrxAnimatedSliverHeader extends StatelessWidget { + const GrxAnimatedSliverHeader({ + super.key, + required this.animationController, + required this.builder, + this.topOffset = 0.0, + }); + + final AnimationController animationController; + final Widget Function(double progress) builder; + final double topOffset; + + @override + Widget build(BuildContext context) { + final padding = MediaQuery.of(context).padding; + + return SliverPersistentHeader( + delegate: GrxAnimatedSliverHeaderDelegate( + animationController: animationController, + builder: builder, + topSafePadding: padding.top + topOffset, + ), + pinned: true, + ); + } +} diff --git a/lib/widgets/headers/grx_header.widget.dart b/lib/widgets/headers/grx_header.widget.dart index 4cf5c0c..6ad4c8e 100644 --- a/lib/widgets/headers/grx_header.widget.dart +++ b/lib/widgets/headers/grx_header.widget.dart @@ -42,9 +42,13 @@ class GrxHeader extends StatelessWidget implements PreferredSizeWidget { @override Widget build(BuildContext context) { return AppBar( + surfaceTintColor: Colors.transparent, title: Padding( - padding: EdgeInsets.lerp(EdgeInsets.zero, - const EdgeInsets.only(left: 8.0), animationProgress)!, + padding: EdgeInsets.lerp( + EdgeInsets.zero, + const EdgeInsets.only(left: 4.0), + animationProgress, + )!, child: GrxText( title, style: TextStyle.lerp( @@ -64,11 +68,11 @@ class GrxHeader extends StatelessWidget implements PreferredSizeWidget { child: GrxBackButton( onPressed: Navigator.of(context).pop, color: foregroundColor, - iconSize: 20.0, + iconSize: 20.0 - 2.0 * animationProgress, ), ), leadingWidth: showBackButton ? 48.0 : 16.0, - titleSpacing: 0, + titleSpacing: 0.0, toolbarHeight: height, actions: showCloseButton ? [ diff --git a/lib/widgets/headers/grx_searchable_header.widget.dart b/lib/widgets/headers/grx_searchable_header.widget.dart index 70f035c..459d396 100644 --- a/lib/widgets/headers/grx_searchable_header.widget.dart +++ b/lib/widgets/headers/grx_searchable_header.widget.dart @@ -12,22 +12,24 @@ class GrxSearchableHeader extends StatefulWidget { const GrxSearchableHeader({ super.key, required this.title, + required this.animationController, this.animationProgress = 0, - this.animationController, this.hintText, this.actions, this.onQuickSearchHandler, this.searchFieldController, + this.extraWidget, this.canPop = false, }); final String title; + final AnimationController animationController; final double animationProgress; - final AnimationController? animationController; final String? hintText; final List? actions; final void Function(String)? onQuickSearchHandler; final TextEditingController? searchFieldController; + final Widget? extraWidget; final bool canPop; @override @@ -37,13 +39,13 @@ class GrxSearchableHeader extends StatefulWidget { } class _GrxSearchableHeaderState extends State { - late final animationController = widget.animationController!; + late final animationController = widget.animationController; late final Animation topBarAnimation = - Tween(begin: 0, end: 1).animate( + Tween(begin: .2, end: 1).animate( CurvedAnimation( parent: animationController, - curve: const Interval(0, 0.6, curve: Curves.fastOutSlowIn), + curve: const Interval(0, 0.9, curve: Curves.fastOutSlowIn), ), ); @@ -55,6 +57,14 @@ class _GrxSearchableHeaderState extends State { ), ); + late final Animation extraWidgetAnimation = + Tween(begin: 0.2, end: 1).animate( + CurvedAnimation( + parent: animationController, + curve: const Interval(0, 0.8, curve: Curves.fastOutSlowIn), + ), + ); + Timer? _debounce; @override @@ -78,31 +88,43 @@ class _GrxSearchableHeaderState extends State { return GrxFadeTransition( animation: topBarAnimation, child: Container( + clipBehavior: Clip.antiAlias, decoration: BoxDecoration( - color: GrxColors.cfff2f7fd.withOpacity( - widget.animationProgress, - ), - borderRadius: const BorderRadius.only( - bottomLeft: Radius.circular(32), + color: GrxColors.cff429af1 + // .withOpacity( + // clampDouble( + // (widget.animationProgress + 1) * .95, + // 0.0, + // 1.0, + // ), + // ) + , + borderRadius: BorderRadius.only( + bottomLeft: Radius.lerp( + const Radius.circular(0), + const Radius.circular(32.0), + widget.animationProgress, + )!, ), boxShadow: [ BoxShadow( color: GrxColors.cff8795a9 - .withOpacity(0.4 * widget.animationProgress), + .withOpacity(.4 * widget.animationProgress), offset: const Offset(1.1, 1.1), blurRadius: 10, ), ], ), child: Column( + mainAxisSize: MainAxisSize.min, children: [ Padding( padding: EdgeInsets.lerp( EdgeInsets.only( - bottom: widget.onQuickSearchHandler == null ? 0 : 15, + bottom: widget.onQuickSearchHandler == null ? 0.0 : 8.0, ), EdgeInsets.only( - bottom: widget.onQuickSearchHandler == null ? 0 : 0, + bottom: widget.onQuickSearchHandler == null ? 0.0 : 0, ), widget.animationProgress, )!, @@ -111,7 +133,8 @@ class _GrxSearchableHeaderState extends State { actions: widget.actions ?? [], showBackButton: widget.canPop, animationProgress: widget.animationProgress, - systemOverlayStyle: GrxSystemOverlayStyle.dark, + foregroundColor: GrxColors.cffffffff, + systemOverlayStyle: GrxSystemOverlayStyle.light, ), ), if (widget.onQuickSearchHandler != null) @@ -122,8 +145,11 @@ class _GrxSearchableHeaderState extends State { animation: searchBarAnimation, child: Padding( padding: EdgeInsets.lerp( - const EdgeInsets.symmetric( - horizontal: 8.0, + EdgeInsets.only( + left: 8.0, + right: 8.0, + bottom: + widget.extraWidget != null ? 0.0 : 8.0, ), EdgeInsets.zero, widget.animationProgress, @@ -145,7 +171,8 @@ class _GrxSearchableHeaderState extends State { const Duration( milliseconds: 500, ), () { - if (widget.onQuickSearchHandler != null) { + if (widget.onQuickSearchHandler != + null) { widget.onQuickSearchHandler!( value, ); @@ -153,7 +180,7 @@ class _GrxSearchableHeaderState extends State { }); }, hintText: - widget.hintText ?? 'Pesquise Aqui', + widget.hintText ?? 'Pesquise aqui', ), ), ), @@ -161,7 +188,18 @@ class _GrxSearchableHeaderState extends State { ), ); }, - ) + ), + if (widget.extraWidget != null) + AnimatedBuilder( + animation: animationController, + child: widget.extraWidget!, + builder: (context, child) { + return GrxFadeTransition( + animation: extraWidgetAnimation, + child: child!, + ); + }, + ), ], ), ), diff --git a/lib/widgets/headers/grx_searchable_sliver_header.widget.dart b/lib/widgets/headers/grx_searchable_sliver_header.widget.dart index 84c3996..fd08fba 100644 --- a/lib/widgets/headers/grx_searchable_sliver_header.widget.dart +++ b/lib/widgets/headers/grx_searchable_sliver_header.widget.dart @@ -10,6 +10,7 @@ class GrxSearchableSliverHeader extends StatelessWidget { this.onFilter, this.onAdd, this.onQuickSearchHandler, + this.totalWidget, this.filterButtonText = 'Filtros', this.hintText, this.canPop = false, @@ -20,22 +21,39 @@ class GrxSearchableSliverHeader extends StatelessWidget { final void Function()? onFilter; final void Function()? onAdd; final void Function(String)? onQuickSearchHandler; + final Widget? totalWidget; final String filterButtonText; final String? hintText; final bool canPop; @override Widget build(BuildContext context) { + final padding = MediaQuery.of(context).padding; + return SliverPersistentHeader( delegate: GrxSearchableSliverHeaderDelegate( animationController: animationController, title: title, onFilter: onFilter, + topSafePadding: padding.top, onAdd: onAdd, onQuickSearchHandler: onQuickSearchHandler, filterButtonText: filterButtonText, hintText: hintText, canPop: canPop, + onTotalWidgetBuilder: totalWidget != null + ? (progress) { + return Opacity( + opacity: (1 - progress * 1.5).clamp(0.0, 1.0), + child: SizedBox( + height: (36.0 - (36.0 * progress * 1.5)).clamp(0.0, 36.0), + child: Center( + child: totalWidget!, + ), + ), + ); + } + : null, ), pinned: true, ); diff --git a/lib/widgets/layout/grx_responsive_layout.widget.dart b/lib/widgets/layout/grx_responsive_layout.widget.dart new file mode 100644 index 0000000..3d4cf0c --- /dev/null +++ b/lib/widgets/layout/grx_responsive_layout.widget.dart @@ -0,0 +1,28 @@ +import 'package:flutter/widgets.dart'; + +const mobileWidth = 900; +const desktopWidth = 1180; + +class GrxResponsiveLayout extends StatelessWidget { + const GrxResponsiveLayout({ + super.key, + required this.mobileView, + required this.desktopView, + }); + + final Widget mobileView; + final Widget desktopView; + + @override + Widget build(BuildContext context) { + return LayoutBuilder( + builder: (context, dimensions) { + if (dimensions.maxWidth <= mobileWidth) { + return mobileView; + } else { + return desktopView; + } + }, + ); + } +} diff --git a/lib/widgets/list/grx_list_empty.widget.dart b/lib/widgets/list/grx_list_empty.widget.dart new file mode 100644 index 0000000..f62a305 --- /dev/null +++ b/lib/widgets/list/grx_list_empty.widget.dart @@ -0,0 +1,103 @@ +import 'package:flutter/material.dart'; + +import '../../animations/grx_fade_transition.animation.dart'; +import '../../models/grx_button_options.model.dart'; +import '../../themes/colors/grx_colors.dart'; +import '../../themes/icons/grx_icons.dart'; +import '../buttons/grx_rounded_button.widget.dart'; +import '../typography/grx_caption_large_text.widget.dart'; +import '../typography/grx_headline_text.widget.dart'; + +class GrxListEmpty extends StatelessWidget { + GrxListEmpty({ + super.key, + required this.title, + required this.subTitle, + this.icon = const Icon( + GrxIcons.format_list_bulleted, + color: GrxColors.primarySwatch, + size: 86.0, + ), + this.animationController, + this.buttonOptions, + }) : animation = animationController != null + ? Tween(begin: 0.0, end: 1.0).animate( + CurvedAnimation( + parent: animationController, + curve: const Interval( + .0, + .9, + curve: Curves.fastOutSlowIn, + ), + ), + ) + : null; + + final String title; + final String subTitle; + final Widget? icon; + final GrxButtonOptions? buttonOptions; + final AnimationController? animationController; + final Animation? animation; + + Widget _buildEmptyListWidget() { + return Center( + child: Padding( + padding: const EdgeInsets.symmetric( + vertical: 8.0, + horizontal: 32.0, + ), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + if (icon != null) + Padding( + padding: const EdgeInsets.only( + bottom: 24.0, + ), + child: icon, + ), + GrxHeadlineText( + title, + textAlign: TextAlign.center, + ), + const SizedBox( + height: 8.0, + ), + GrxCaptionLargeText( + subTitle, + textAlign: TextAlign.center, + ), + if (buttonOptions != null) + Padding( + padding: const EdgeInsets.symmetric(vertical: 32.0), + child: GrxRoundedButton( + text: buttonOptions!.title, + foregroundColor: buttonOptions!.foregroundColor, + backgroundColor: buttonOptions!.backgroundColor, + icon: buttonOptions!.icon, + onPressed: buttonOptions!.onPressed, + ), + ), + ], + ), + ), + ); + } + + @override + Widget build(BuildContext context) { + return animationController != null + ? AnimatedBuilder( + animation: animationController!, + child: _buildEmptyListWidget(), + builder: (context, child) { + return GrxFadeTransition( + animation: animation!, + child: child!, + ); + }, + ) + : _buildEmptyListWidget(); + } +} diff --git a/lib/widgets/list/grx_list_error.widget.dart b/lib/widgets/list/grx_list_error.widget.dart new file mode 100644 index 0000000..948e0b4 --- /dev/null +++ b/lib/widgets/list/grx_list_error.widget.dart @@ -0,0 +1,105 @@ +import 'package:flutter/widgets.dart'; + +import '../../animations/grx_fade_transition.animation.dart'; +import '../../models/grx_button_options.model.dart'; +import '../../themes/colors/grx_colors.dart'; +import '../../themes/icons/grx_icons.dart'; +import '../buttons/grx_rounded_button.widget.dart'; +import '../typography/grx_caption_large_text.widget.dart'; +import '../typography/grx_headline_text.widget.dart'; + +class GrxListError extends StatelessWidget { + GrxListError({ + super.key, + required this.title, + required this.subTitle, + this.icon = const Icon( + GrxIcons.error_outline, + size: 86.0, + color: GrxColors.cff7593b5, + ), + this.buttonOptions, + this.animationController, + }) : animation = animationController != null + ? Tween(begin: 0.0, end: 1.0).animate( + CurvedAnimation( + parent: animationController, + curve: const Interval( + .3, + 1.0, + curve: Curves.fastOutSlowIn, + ), + ), + ) + : null; + + final String title; + final String subTitle; + final Widget? icon; + final GrxButtonOptions? buttonOptions; + final AnimationController? animationController; + final Animation? animation; + + Widget _buildErrorListWidget() { + return Center( + child: Padding( + padding: const EdgeInsets.symmetric( + vertical: 8.0, + horizontal: 32.0, + ), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + if (icon != null) + Padding( + padding: const EdgeInsets.only( + bottom: 24.0, + ), + child: icon, + ), + GrxHeadlineText( + title, + overflow: TextOverflow.visible, + textAlign: TextAlign.center, + ), + const SizedBox( + height: 8.0, + ), + GrxCaptionLargeText( + subTitle, + overflow: TextOverflow.visible, + textAlign: TextAlign.center, + ), + if (buttonOptions != null) + Padding( + padding: const EdgeInsets.symmetric(vertical: 32.0), + child: GrxRoundedButton( + text: buttonOptions!.title, + foregroundColor: buttonOptions!.foregroundColor, + backgroundColor: buttonOptions!.backgroundColor, + icon: buttonOptions!.icon, + onPressed: buttonOptions!.onPressed, + ), + ), + ], + ), + ), + ); + } + + @override + Widget build(BuildContext context) { + return animationController != null + ? AnimatedBuilder( + animation: animationController!, + child: _buildErrorListWidget(), + builder: (context, child) { + return GrxFadeTransition( + animation: animation!, + child: child!, + ); + }, + ) + : _buildErrorListWidget(); + } +} diff --git a/lib/widgets/list/grx_list_infinite_loading.widget.dart b/lib/widgets/list/grx_list_infinite_loading.widget.dart new file mode 100644 index 0000000..05207ca --- /dev/null +++ b/lib/widgets/list/grx_list_infinite_loading.widget.dart @@ -0,0 +1,19 @@ +import 'package:flutter/material.dart'; + +import '../grx_spinner_loading.widget.dart'; + +class GrxListInfiniteLoading extends StatelessWidget { + const GrxListInfiniteLoading({ + super.key, + }); + + @override + Widget build(BuildContext context) => const Padding( + padding: EdgeInsets.symmetric( + vertical: 16.0, + ), + child: Center( + child: GrxSpinnerLoading(), + ), + ); +} diff --git a/lib/widgets/list/grx_list_infinite_loading_error.widget.dart b/lib/widgets/list/grx_list_infinite_loading_error.widget.dart new file mode 100644 index 0000000..f11c9c8 --- /dev/null +++ b/lib/widgets/list/grx_list_infinite_loading_error.widget.dart @@ -0,0 +1,42 @@ +import 'package:flutter/material.dart'; + +import '../../themes/icons/grx_icons.dart'; +import '../typography/grx_caption_large_text.widget.dart'; + +class GrxListInfiniteLoadingError extends StatelessWidget { + const GrxListInfiniteLoadingError({ + super.key, + required this.text, + this.onTap, + }); + + final String text; + final VoidCallback? onTap; + + @override + Widget build(BuildContext context) => InkWell( + onTap: onTap, + child: Padding( + padding: const EdgeInsets.symmetric( + vertical: 16.0, + ), + child: Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + GrxCaptionLargeText( + text, + textAlign: TextAlign.center, + ), + const SizedBox( + height: 4.0, + ), + const Icon( + GrxIcons.refresh, + ), + ], + ), + ), + ), + ); +} diff --git a/lib/widgets/list/grx_list_loading.widget.dart b/lib/widgets/list/grx_list_loading.widget.dart new file mode 100644 index 0000000..3d9c412 --- /dev/null +++ b/lib/widgets/list/grx_list_loading.widget.dart @@ -0,0 +1,63 @@ +import 'package:flutter/widgets.dart'; + +import '../../animations/grx_fade_transition.animation.dart'; +import '../grx_spinner_loading.widget.dart'; + +class GrxListLoading extends StatelessWidget { + GrxListLoading({ + super.key, + this.listSize = 10, + this.itemBuilder, + this.separatorBuilder, + this.animationController, + }) : animation = animationController != null + ? Tween(begin: 0.0, end: 1.0).animate( + CurvedAnimation( + parent: animationController, + curve: const Interval( + 0.2, + 1.0, + curve: Curves.fastOutSlowIn, + ), + ), + ) + : null; + + final int listSize; + final Widget Function(int index)? itemBuilder; + final Widget Function(BuildContext context, int index)? separatorBuilder; + final AnimationController? animationController; + final Animation? animation; + + @override + Widget build(BuildContext context) { + const defaultLoadingWidget = Center( + child: GrxSpinnerLoading(), + ); + + return itemBuilder != null + ? Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + for (var i = 0; i < listSize; i++) ...[ + itemBuilder!(i), + if (i < listSize && separatorBuilder != null) + separatorBuilder!(context, i), + ], + ], + ) + : animationController != null + ? AnimatedBuilder( + animation: animationController!, + child: defaultLoadingWidget, + builder: (context, child) { + return GrxFadeTransition( + animation: animation!, + child: child!, + ); + }, + ) + : defaultLoadingWidget; + } +} diff --git a/lib/widgets/typography/grx_body_text.widget.dart b/lib/widgets/typography/grx_body_text.widget.dart index 45c1910..925c6f3 100644 --- a/lib/widgets/typography/grx_body_text.widget.dart +++ b/lib/widgets/typography/grx_body_text.widget.dart @@ -20,7 +20,8 @@ class GrxBodyText extends StatelessWidget { this.decoration, this.overflow, this.isLoading = false, - }) : textSpan = null; + }) : textSpan = null, + style = null; const GrxBodyText.rich( this.textSpan, { @@ -32,7 +33,32 @@ class GrxBodyText extends StatelessWidget { this.decoration, this.overflow, this.isLoading = false, - }) : text = null; + }) : text = null, + style = null; + + GrxBodyText.lerp( + this.text, { + super.key, + required final GrxBodyTextStyle style, + required final double t, + this.textAlign, + this.transform = GrxTextTransform.none, + this.color = GrxColors.cff2e2e2e, + this.fontWeight, + this.decoration, + this.overflow, + this.isLoading = false, + }) : textSpan = null, + style = TextStyle.lerp( + GrxBodyTextStyle( + color: color, + decoration: decoration, + overflow: overflow, + fontWeight: fontWeight, + ), + style, + t, + )!; final String? text; final InlineSpan? textSpan; @@ -43,15 +69,17 @@ class GrxBodyText extends StatelessWidget { final TextDecoration? decoration; final TextOverflow? overflow; final bool isLoading; + final TextStyle? style; @override Widget build(BuildContext context) { - final style = GrxBodyTextStyle( - color: color, - decoration: decoration, - overflow: overflow, - fontWeight: fontWeight, - ); + final style = this.style ?? + GrxBodyTextStyle( + color: color, + decoration: decoration, + overflow: overflow, + fontWeight: fontWeight, + ); return textSpan != null ? GrxText.rich( diff --git a/lib/widgets/typography/grx_caption_large_text.widget.dart b/lib/widgets/typography/grx_caption_large_text.widget.dart index 36a18cb..dbdc1e8 100644 --- a/lib/widgets/typography/grx_caption_large_text.widget.dart +++ b/lib/widgets/typography/grx_caption_large_text.widget.dart @@ -20,7 +20,8 @@ class GrxCaptionLargeText extends StatelessWidget { this.decoration, this.overflow, this.isLoading = false, - }) : textSpan = null; + }) : textSpan = null, + style = null; const GrxCaptionLargeText.rich( this.textSpan, { @@ -32,7 +33,32 @@ class GrxCaptionLargeText extends StatelessWidget { this.decoration, this.overflow, this.isLoading = false, - }) : text = null; + }) : text = null, + style = null; + + GrxCaptionLargeText.lerp( + this.text, { + super.key, + required final GrxCaptionLargeTextStyle style, + required final double t, + this.textAlign, + this.transform = GrxTextTransform.none, + this.color = GrxColors.cff2e2e2e, + this.fontWeight, + this.decoration, + this.overflow, + this.isLoading = false, + }) : textSpan = null, + style = TextStyle.lerp( + GrxCaptionLargeTextStyle( + color: color, + decoration: decoration, + overflow: overflow, + fontWeight: fontWeight, + ), + style, + t, + )!; final String? text; final InlineSpan? textSpan; @@ -43,15 +69,17 @@ class GrxCaptionLargeText extends StatelessWidget { final TextDecoration? decoration; final TextOverflow? overflow; final bool isLoading; + final TextStyle? style; @override Widget build(BuildContext context) { - final style = GrxCaptionLargeTextStyle( - color: color, - decoration: decoration, - overflow: overflow, - fontWeight: fontWeight, - ); + final style = this.style ?? + GrxCaptionLargeTextStyle( + color: color, + decoration: decoration, + overflow: overflow, + fontWeight: fontWeight, + ); return textSpan != null ? GrxText.rich( diff --git a/lib/widgets/typography/grx_caption_small_text.widget.dart b/lib/widgets/typography/grx_caption_small_text.widget.dart index 771863a..a65634b 100644 --- a/lib/widgets/typography/grx_caption_small_text.widget.dart +++ b/lib/widgets/typography/grx_caption_small_text.widget.dart @@ -20,7 +20,8 @@ class GrxCaptionSmallText extends StatelessWidget { this.decoration, this.overflow, this.isLoading = false, - }) : textSpan = null; + }) : textSpan = null, + style = null; const GrxCaptionSmallText.rich( this.textSpan, { @@ -32,7 +33,32 @@ class GrxCaptionSmallText extends StatelessWidget { this.decoration, this.overflow, this.isLoading = false, - }) : text = null; + }) : text = null, + style = null; + + GrxCaptionSmallText.lerp( + this.text, { + super.key, + required final GrxCaptionSmallTextStyle style, + required final double t, + this.textAlign, + this.transform = GrxTextTransform.none, + this.color = GrxColors.cff2e2e2e, + this.fontWeight, + this.decoration, + this.overflow, + this.isLoading = false, + }) : textSpan = null, + style = TextStyle.lerp( + GrxCaptionSmallTextStyle( + color: color, + decoration: decoration, + overflow: overflow, + fontWeight: fontWeight, + ), + style, + t, + )!; final String? text; final InlineSpan? textSpan; @@ -43,15 +69,17 @@ class GrxCaptionSmallText extends StatelessWidget { final TextDecoration? decoration; final TextOverflow? overflow; final bool isLoading; + final TextStyle? style; @override Widget build(BuildContext context) { - final style = GrxCaptionSmallTextStyle( - color: color, - decoration: decoration, - overflow: overflow, - fontWeight: fontWeight, - ); + final style = this.style ?? + GrxCaptionSmallTextStyle( + color: color, + decoration: decoration, + overflow: overflow, + fontWeight: fontWeight, + ); return textSpan != null ? GrxText.rich( diff --git a/lib/widgets/typography/grx_caption_text.widget.dart b/lib/widgets/typography/grx_caption_text.widget.dart index 16e32ba..597e57e 100644 --- a/lib/widgets/typography/grx_caption_text.widget.dart +++ b/lib/widgets/typography/grx_caption_text.widget.dart @@ -20,7 +20,8 @@ class GrxCaptionText extends StatelessWidget { this.decoration, this.overflow, this.isLoading = false, - }) : textSpan = null; + }) : textSpan = null, + style = null; const GrxCaptionText.rich( this.textSpan, { @@ -32,7 +33,32 @@ class GrxCaptionText extends StatelessWidget { this.decoration, this.overflow, this.isLoading = false, - }) : text = null; + }) : text = null, + style = null; + + GrxCaptionText.lerp( + this.text, { + super.key, + required final GrxCaptionTextStyle style, + required final double t, + this.textAlign, + this.transform = GrxTextTransform.none, + this.color = GrxColors.cff2e2e2e, + this.fontWeight, + this.decoration, + this.overflow, + this.isLoading = false, + }) : textSpan = null, + style = TextStyle.lerp( + GrxCaptionTextStyle( + color: color, + decoration: decoration, + overflow: overflow, + fontWeight: fontWeight, + ), + style, + t, + )!; final String? text; final InlineSpan? textSpan; @@ -43,15 +69,17 @@ class GrxCaptionText extends StatelessWidget { final TextDecoration? decoration; final TextOverflow? overflow; final bool isLoading; + final TextStyle? style; @override Widget build(BuildContext context) { - final style = GrxCaptionTextStyle( - color: color, - decoration: decoration, - overflow: overflow, - fontWeight: fontWeight, - ); + final style = this.style ?? + GrxCaptionTextStyle( + color: color, + decoration: decoration, + overflow: overflow, + fontWeight: fontWeight, + ); return textSpan != null ? GrxText.rich( diff --git a/lib/widgets/typography/grx_headline_large_text.widget.dart b/lib/widgets/typography/grx_headline_large_text.widget.dart index 608d64e..a0df883 100644 --- a/lib/widgets/typography/grx_headline_large_text.widget.dart +++ b/lib/widgets/typography/grx_headline_large_text.widget.dart @@ -20,7 +20,8 @@ class GrxHeadlineLargeText extends StatelessWidget { this.decoration, this.overflow, this.isLoading = false, - }) : textSpan = null; + }) : textSpan = null, + style = null; const GrxHeadlineLargeText.rich( this.textSpan, { @@ -32,7 +33,32 @@ class GrxHeadlineLargeText extends StatelessWidget { this.decoration, this.overflow, this.isLoading = false, - }) : text = null; + }) : text = null, + style = null; + + GrxHeadlineLargeText.lerp( + this.text, { + super.key, + required final GrxHeadlineLargeTextStyle style, + required final double t, + this.textAlign, + this.transform = GrxTextTransform.none, + this.color = GrxColors.cff2e2e2e, + this.fontWeight, + this.decoration, + this.overflow, + this.isLoading = false, + }) : textSpan = null, + style = TextStyle.lerp( + GrxHeadlineLargeTextStyle( + color: color, + decoration: decoration, + overflow: overflow, + fontWeight: fontWeight, + ), + style, + t, + )!; final String? text; final InlineSpan? textSpan; @@ -43,15 +69,17 @@ class GrxHeadlineLargeText extends StatelessWidget { final TextDecoration? decoration; final TextOverflow? overflow; final bool isLoading; + final TextStyle? style; @override Widget build(BuildContext context) { - final style = GrxHeadlineLargeTextStyle( - color: color, - decoration: decoration, - overflow: overflow, - fontWeight: fontWeight, - ); + final style = this.style ?? + GrxHeadlineLargeTextStyle( + color: color, + decoration: decoration, + overflow: overflow, + fontWeight: fontWeight, + ); return textSpan != null ? GrxText.rich( diff --git a/lib/widgets/typography/grx_headline_medium_text.widget.dart b/lib/widgets/typography/grx_headline_medium_text.widget.dart index d555b64..a2c3b65 100644 --- a/lib/widgets/typography/grx_headline_medium_text.widget.dart +++ b/lib/widgets/typography/grx_headline_medium_text.widget.dart @@ -20,7 +20,8 @@ class GrxHeadlineMediumText extends StatelessWidget { this.decoration, this.overflow, this.isLoading = false, - }) : textSpan = null; + }) : textSpan = null, + style = null; const GrxHeadlineMediumText.rich( this.textSpan, { @@ -32,7 +33,32 @@ class GrxHeadlineMediumText extends StatelessWidget { this.decoration, this.overflow, this.isLoading = false, - }) : text = null; + }) : text = null, + style = null; + + GrxHeadlineMediumText.lerp( + this.text, { + super.key, + required final GrxHeadlineMediumTextStyle style, + required final double t, + this.textAlign, + this.transform = GrxTextTransform.none, + this.color = GrxColors.cff2e2e2e, + this.fontWeight, + this.decoration, + this.overflow, + this.isLoading = false, + }) : textSpan = null, + style = TextStyle.lerp( + GrxHeadlineMediumTextStyle( + color: color, + decoration: decoration, + overflow: overflow, + fontWeight: fontWeight, + ), + style, + t, + )!; final String? text; final InlineSpan? textSpan; @@ -43,15 +69,17 @@ class GrxHeadlineMediumText extends StatelessWidget { final TextDecoration? decoration; final TextOverflow? overflow; final bool isLoading; + final TextStyle? style; @override Widget build(BuildContext context) { - final style = GrxHeadlineMediumTextStyle( - color: color, - decoration: decoration, - overflow: overflow, - fontWeight: fontWeight, - ); + final style = this.style ?? + GrxHeadlineMediumTextStyle( + color: color, + decoration: decoration, + overflow: overflow, + fontWeight: fontWeight, + ); return textSpan != null ? GrxText.rich( diff --git a/lib/widgets/typography/grx_headline_small_text.widget.dart b/lib/widgets/typography/grx_headline_small_text.widget.dart index c7775a1..c185241 100644 --- a/lib/widgets/typography/grx_headline_small_text.widget.dart +++ b/lib/widgets/typography/grx_headline_small_text.widget.dart @@ -20,7 +20,8 @@ class GrxHeadlineSmallText extends StatelessWidget { this.decoration, this.overflow, this.isLoading = false, - }) : textSpan = null; + }) : textSpan = null, + style = null; const GrxHeadlineSmallText.rich( this.textSpan, { @@ -32,7 +33,32 @@ class GrxHeadlineSmallText extends StatelessWidget { this.decoration, this.overflow, this.isLoading = false, - }) : text = null; + }) : text = null, + style = null; + + GrxHeadlineSmallText.lerp( + this.text, { + super.key, + required final GrxHeadlineSmallTextStyle style, + required final double t, + this.textAlign, + this.transform = GrxTextTransform.none, + this.color = GrxColors.cff2e2e2e, + this.fontWeight, + this.decoration, + this.overflow, + this.isLoading = false, + }) : textSpan = null, + style = TextStyle.lerp( + GrxHeadlineSmallTextStyle( + color: color, + decoration: decoration, + overflow: overflow, + fontWeight: fontWeight, + ), + style, + t, + )!; final String? text; final InlineSpan? textSpan; @@ -43,15 +69,17 @@ class GrxHeadlineSmallText extends StatelessWidget { final TextDecoration? decoration; final TextOverflow? overflow; final bool isLoading; + final TextStyle? style; @override Widget build(BuildContext context) { - final style = GrxHeadlineSmallTextStyle( - color: color, - decoration: decoration, - overflow: overflow, - fontWeight: fontWeight, - ); + final style = this.style ?? + GrxHeadlineSmallTextStyle( + color: color, + decoration: decoration, + overflow: overflow, + fontWeight: fontWeight, + ); return textSpan != null ? GrxText.rich( diff --git a/lib/widgets/typography/grx_headline_text.widget.dart b/lib/widgets/typography/grx_headline_text.widget.dart index 0a483ec..104558c 100644 --- a/lib/widgets/typography/grx_headline_text.widget.dart +++ b/lib/widgets/typography/grx_headline_text.widget.dart @@ -20,7 +20,8 @@ class GrxHeadlineText extends StatelessWidget { this.decoration, this.overflow, this.isLoading = false, - }) : textSpan = null; + }) : textSpan = null, + style = null; const GrxHeadlineText.rich( this.textSpan, { @@ -32,7 +33,32 @@ class GrxHeadlineText extends StatelessWidget { this.decoration, this.overflow, this.isLoading = false, - }) : text = null; + }) : text = null, + style = null; + + GrxHeadlineText.lerp( + this.text, { + super.key, + required final GrxHeadlineTextStyle style, + required final double t, + this.textAlign, + this.transform = GrxTextTransform.none, + this.color = GrxColors.cff2e2e2e, + this.fontWeight, + this.decoration, + this.overflow, + this.isLoading = false, + }) : textSpan = null, + style = TextStyle.lerp( + GrxHeadlineTextStyle( + color: color, + decoration: decoration, + overflow: overflow, + fontWeight: fontWeight, + ), + style, + t, + )!; final String? text; final InlineSpan? textSpan; @@ -43,15 +69,17 @@ class GrxHeadlineText extends StatelessWidget { final TextDecoration? decoration; final TextOverflow? overflow; final bool isLoading; + final TextStyle? style; @override Widget build(BuildContext context) { - final style = GrxHeadlineTextStyle( - color: color, - decoration: decoration, - overflow: overflow, - fontWeight: fontWeight, - ); + final style = this.style ?? + GrxHeadlineTextStyle( + color: color, + decoration: decoration, + overflow: overflow, + fontWeight: fontWeight, + ); return textSpan != null ? GrxText.rich( diff --git a/lib/widgets/typography/grx_overline_text.widget.dart b/lib/widgets/typography/grx_overline_text.widget.dart index 8eb0c33..6b4869a 100644 --- a/lib/widgets/typography/grx_overline_text.widget.dart +++ b/lib/widgets/typography/grx_overline_text.widget.dart @@ -20,7 +20,8 @@ class GrxOverlineText extends StatelessWidget { this.decoration, this.overflow, this.isLoading = false, - }) : textSpan = null; + }) : textSpan = null, + style = null; const GrxOverlineText.rich( this.textSpan, { @@ -32,7 +33,32 @@ class GrxOverlineText extends StatelessWidget { this.decoration, this.overflow, this.isLoading = false, - }) : text = null; + }) : text = null, + style = null; + + GrxOverlineText.lerp( + this.text, { + super.key, + required final GrxOverlineTextStyle style, + required final double t, + this.textAlign, + this.transform = GrxTextTransform.uppercase, + this.color = GrxColors.cff2e2e2e, + this.fontWeight, + this.decoration, + this.overflow, + this.isLoading = false, + }) : textSpan = null, + style = TextStyle.lerp( + GrxOverlineTextStyle( + color: color, + decoration: decoration, + overflow: overflow, + fontWeight: fontWeight, + ), + style, + t, + )!; final String? text; final InlineSpan? textSpan; @@ -43,15 +69,17 @@ class GrxOverlineText extends StatelessWidget { final TextDecoration? decoration; final TextOverflow? overflow; final bool isLoading; + final TextStyle? style; @override Widget build(BuildContext context) { - final style = GrxOverlineTextStyle( - color: color, - decoration: decoration, - overflow: overflow, - fontWeight: fontWeight, - ); + final style = this.style ?? + GrxOverlineTextStyle( + color: color, + decoration: decoration, + overflow: overflow, + fontWeight: fontWeight, + ); return textSpan != null ? GrxText.rich( diff --git a/lib/widgets/typography/grx_text.widget.dart b/lib/widgets/typography/grx_text.widget.dart index d0e9a19..107005a 100644 --- a/lib/widgets/typography/grx_text.widget.dart +++ b/lib/widgets/typography/grx_text.widget.dart @@ -1,3 +1,5 @@ +import 'dart:ui'; + import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; @@ -19,7 +21,6 @@ class GrxText extends StatelessWidget { this.textDirection, this.locale, this.softWrap, - this.textScaleFactor, this.maxLines, this.semanticsLabel, this.textWidthBasis, @@ -39,7 +40,6 @@ class GrxText extends StatelessWidget { this.textDirection, this.locale, this.softWrap, - this.textScaleFactor, this.maxLines, this.semanticsLabel, this.textWidthBasis, @@ -58,7 +58,6 @@ class GrxText extends StatelessWidget { final TextDirection? textDirection; final Locale? locale; final bool? softWrap; - final double? textScaleFactor; final int? maxLines; final String? semanticsLabel; final TextWidthBasis? textWidthBasis; @@ -70,28 +69,27 @@ class GrxText extends StatelessWidget { @override Widget build(BuildContext context) { if (isLoading) { - return LayoutBuilder( - builder: (BuildContext context, BoxConstraints constraints) { - final renderParagraph = RenderParagraph( - textSpan ?? - TextSpan( - text: _capitalize(text), - style: style, - ), - textDirection: TextDirection.ltr, - maxLines: maxLines ?? 1, - ); + final renderParagraph = RenderParagraph( + textSpan ?? + TextSpan( + text: _capitalize(text), + style: style, + ), + textDirection: TextDirection.ltr, + maxLines: maxLines ?? 1, + ); - renderParagraph.layout(constraints); + final size = MediaQuery.sizeOf(context); + renderParagraph.layout( + BoxConstraints(maxHeight: size.height, maxWidth: size.width), + ); - final height = renderParagraph.getMinIntrinsicHeight(style.fontSize!); - final width = renderParagraph.getMinIntrinsicWidth(style.fontSize!); + final height = renderParagraph.getMinIntrinsicHeight(style.fontSize!) + 3.0; + final width = renderParagraph.getMinIntrinsicWidth(style.fontSize!); - return GrxShimmer( - height: height, - width: width, - ); - }, + return GrxShimmer( + height: clampDouble(height, height, size.height), + width: clampDouble(width, width, size.width), ); } @@ -108,7 +106,6 @@ class GrxText extends StatelessWidget { textDirection: textDirection, locale: locale, softWrap: softWrap, - textScaleFactor: textScaleFactor, maxLines: maxLines, semanticsLabel: semanticsLabel, textWidthBasis: textWidthBasis, diff --git a/pubspec.yaml b/pubspec.yaml index 3562b04..1c73420 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,34 +1,38 @@ name: grex_ds description: Grex Design System for Flutter. -version: 0.0.7 +version: 0.0.8 homepage: https://grex.com.br repository: https://github.com/grex-corp/grex_ds_flutter environment: - sdk: '>=3.0.0 <4.0.0' + sdk: '>=3.3.0 <4.0.0' flutter: '>=1.17.0' dependencies: flutter: sdk: flutter - cached_network_image: ^3.2.2 - image_cropper: ^4.0.1 - image_picker: ^0.8.6 - path_provider: ^2.0.11 + cached_network_image: ^3.3.1 + image_cropper: ^5.0.1 + image_picker: ^1.0.7 + path_provider: ^2.1.2 photo_view: ^0.14.0 shimmer: ^3.0.0 - rounded_loading_button: ^2.1.0 - another_flushbar: ^1.12.29 - intl: ^0.18.0 - flutter_svg: ^2.0.5 + rounded_loading_button_plus: ^3.0.1 + delightful_toast: ^1.1.0 + intl: ^0.18.1 + flutter_svg: ^2.0.10+1 linkify: ^5.0.0 - url_launcher: ^6.1.11 + url_launcher: ^6.2.5 + mask_text_input_formatter: ^2.9.0 + popover: ^0.3.0 + infinite_scroll_pagination: ^4.0.0 + super_sliver_list: ^0.4.1 dev_dependencies: flutter_test: sdk: flutter - flutter_lints: ^2.0.0 + flutter_lints: ^3.0.1 # For information on the generic Dart part of this file, see the # following page: https://dart.dev/tools/pub/pubspec @@ -43,6 +47,7 @@ flutter: # To add assets to your package, add an assets section, like this: assets: - assets/images/ + - assets/svgs/flags/ # # For details regarding assets in packages, see # https://flutter.dev/assets-and-images/#from-packages diff --git a/sample/.metadata b/sample/.metadata index 0e4c9a7..d00a406 100644 --- a/sample/.metadata +++ b/sample/.metadata @@ -1,11 +1,11 @@ # This file tracks properties of this Flutter project. # Used by Flutter tool to assess capabilities and perform upgrades etc. # -# This file should be version controlled. +# This file should be version controlled and should not be manually edited. version: - revision: d9111f64021372856901a1fd5bfbc386cade3318 - channel: stable + revision: "d211f42860350d914a5ad8102f9ec32764dc6d06" + channel: "stable" project_type: app @@ -13,20 +13,11 @@ project_type: app migration: platforms: - platform: root - create_revision: d9111f64021372856901a1fd5bfbc386cade3318 - base_revision: d9111f64021372856901a1fd5bfbc386cade3318 - - platform: android - create_revision: d9111f64021372856901a1fd5bfbc386cade3318 - base_revision: d9111f64021372856901a1fd5bfbc386cade3318 - - platform: ios - create_revision: d9111f64021372856901a1fd5bfbc386cade3318 - base_revision: d9111f64021372856901a1fd5bfbc386cade3318 - - platform: linux - create_revision: d9111f64021372856901a1fd5bfbc386cade3318 - base_revision: d9111f64021372856901a1fd5bfbc386cade3318 - - platform: windows - create_revision: d9111f64021372856901a1fd5bfbc386cade3318 - base_revision: d9111f64021372856901a1fd5bfbc386cade3318 + create_revision: d211f42860350d914a5ad8102f9ec32764dc6d06 + base_revision: d211f42860350d914a5ad8102f9ec32764dc6d06 + - platform: web + create_revision: d211f42860350d914a5ad8102f9ec32764dc6d06 + base_revision: d211f42860350d914a5ad8102f9ec32764dc6d06 # User provided section diff --git a/sample/android/app/src/main/AndroidManifest.xml b/sample/android/app/src/main/AndroidManifest.xml index 5c5de8f..206af25 100644 --- a/sample/android/app/src/main/AndroidManifest.xml +++ b/sample/android/app/src/main/AndroidManifest.xml @@ -1,5 +1,17 @@ + + + + + + + + + + + = 2.7.5) - TOCropViewController (2.6.1) + - url_launcher_ios (0.0.1): + - Flutter DEPENDENCIES: - Flutter (from `Flutter`) - image_cropper (from `.symlinks/plugins/image_cropper/ios`) - image_picker_ios (from `.symlinks/plugins/image_picker_ios/ios`) - - path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/ios`) + - path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`) - sqflite (from `.symlinks/plugins/sqflite/ios`) + - url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`) SPEC REPOS: trunk: @@ -36,19 +39,22 @@ EXTERNAL SOURCES: image_picker_ios: :path: ".symlinks/plugins/image_picker_ios/ios" path_provider_foundation: - :path: ".symlinks/plugins/path_provider_foundation/ios" + :path: ".symlinks/plugins/path_provider_foundation/darwin" sqflite: :path: ".symlinks/plugins/sqflite/ios" + url_launcher_ios: + :path: ".symlinks/plugins/url_launcher_ios/ios" SPEC CHECKSUMS: Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854 FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a - image_cropper: 60c2789d1f1a78c873235d4319ca0c34a69f2d98 + image_cropper: a3291c624a953049bc6a02e1f8c8ceb162a24b25 image_picker_ios: 4a8aadfbb6dc30ad5141a2ce3832af9214a705b5 - path_provider_foundation: c68054786f1b4f3343858c1e1d0caaded73f0be9 - sqflite: 6d358c025f5b867b29ed92fc697fd34924e11904 + path_provider_foundation: 29f094ae23ebbca9d3d0cec13889cd9060c0e943 + sqflite: 31f7eba61e3074736dff8807a9b41581e4f7f15a TOCropViewController: edfd4f25713d56905ad1e0b9f5be3fbe0f59c863 + url_launcher_ios: bf5ce03e0e2088bad9cc378ea97fa0ed5b49673b PODFILE CHECKSUM: ef19549a9bc3046e7bb7d2fab4d021637c0c58a3 -COCOAPODS: 1.12.0 +COCOAPODS: 1.13.0 diff --git a/sample/ios/Runner.xcodeproj/project.pbxproj b/sample/ios/Runner.xcodeproj/project.pbxproj index a55845f..12e124b 100644 --- a/sample/ios/Runner.xcodeproj/project.pbxproj +++ b/sample/ios/Runner.xcodeproj/project.pbxproj @@ -156,7 +156,7 @@ 97C146E61CF9000F007C117D /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 1300; + LastUpgradeCheck = 1430; ORGANIZATIONNAME = ""; TargetAttributes = { 97C146ED1CF9000F007C117D = { @@ -205,6 +205,7 @@ files = ( ); inputPaths = ( + "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}", ); name = "Thin Binary"; outputPaths = ( diff --git a/sample/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/sample/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index c87d15a..a6b826d 100644 --- a/sample/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/sample/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -1,6 +1,6 @@ createState() => _DashboardAppPageState(); +} + +class _DashboardAppPageState extends State + with TickerProviderStateMixin { + final formKey = GlobalKey(); + late Person person; + late AnimationController iconAnimationController; + late final AnimationController animationController; + File? selectedImage; + + @override + void initState() { + person = Person( + id: 22, + name: 'Leonardo Gabriel', + phone: '54992099544', + birthDate: DateTime.now(), + leadership: _leaders.first, + roles: [ + _roles.first, + ], + ); + + iconAnimationController = AnimationController( + vsync: this, + duration: GrxUtils.defaultAnimationDuration, + ); + iconAnimationController.forward(); + + animationController = AnimationController( + vsync: this, + duration: GrxUtils.defaultAnimationDuration, + ); + + super.initState(); + } + + bool _validateForm() { + final form = formKey.currentState; + + if (form?.validate() ?? false) { + form!.save(); + return true; + } + + return false; + } + + @override + Widget build(BuildContext context) { + // This method is rerun every time setState is called, for instance as done + // by the _incrementCounter method above. + // + // The Flutter framework has been optimized to make rerunning build methods + // fast, so that you can just rebuild anything that needs updating rather + // than having to individually change instances of widgets. + return Scaffold( + backgroundColor: Colors.white, + appBar: GrxHeader( + // Here we take the value from the DashboardAppPage object that was created by + // the App.build method, and use it to set our appbar title. + title: 'Dashboard Page', + backgroundColor: GrxColors.cff365278, + foregroundColor: GrxColors.cffffffff, + ), + body: Padding( + padding: EdgeInsets.only( + bottom: MediaQuery.paddingOf(context).bottom + 120, + ), + child: Column( + children: [ + Flexible( + child: ListView( + // Column is also a layout widget. It takes a list of children and + // arranges them vertically. By default, it sizes itself to fit its + // children horizontally, and tries to be as tall as its parent. + // + // Invoke "debug painting" (press "p" in the console, choose the + // "Toggle Debug Paint" action from the Flutter Inspector in Android + // Studio, or the "Toggle Debug Paint" command in Visual Studio Code) + // to see the wireframe for each widget. + // + // Column has various properties to control how it sizes itself and + // how it positions its children. Here we use mainAxisAlignment to + // center the children vertically; the main axis here is the vertical + // axis because Columns are vertical (the cross axis would be + // horizontal). + // mainAxisAlignment: MainAxisAlignment.center, + children: [ + const TypoSample(), + Form( + key: formKey, + child: Column( + children: [ + FieldsSampleApp( + person: person, + leaders: _leaders, + roles: _roles, + ), + GrxFloatingActionButton( + isLoading: false, + icon: AnimatedIcon( + icon: AnimatedIcons.close_menu, + progress: iconAnimationController, + color: GrxColors.cffffffff, + size: 30, + ), + onPressed: () { + if (iconAnimationController.isCompleted) { + iconAnimationController.reverse(); + } else { + iconAnimationController.forward(); + } + }, + ), + GrxPrimaryButton( + text: 'Enviar', + margin: const EdgeInsets.symmetric( + vertical: 20, + horizontal: 16, + ), + icon: GrxIcons.check, + onPressed: () {}, + ), + Row( + mainAxisSize: MainAxisSize.min, + children: [ + GrxIconButton( + icon: GrxIcons.whatsapp, + margin: + const EdgeInsets.only(bottom: 16, right: 10), + iconSize: 30, + onPressed: () {}, + ), + GrxIconButton( + icon: GrxIcons.phone, + margin: const EdgeInsets.only(bottom: 16), + iconSize: 30, + onPressed: () {}, + ), + ], + ), + GrxTextIconButton( + icon: GrxIcons.whatsapp, + text: 'WhatsApp', + iconSize: 50, + margin: const EdgeInsets.only(bottom: 16), + onPressed: () {}, + ), + GrxUserAvatar( + radius: 40, + uri: Uri.parse( + 'https://firebasestorage.googleapis.com/v0/b/appgrexdb.appspot.com/o/Images%2FPeople%2FWK242KO734Q9nPKThs9B?alt=media&token=e8906f71-58d5-42cb-9184-6f77a6c15694'), + heroTag: 4, + // openPreview: false, + // editable: true, + // isLoading: true, + ), + const SizedBox( + height: 16, + ), + GrxUserAvatar( + radius: 70, + imageFile: selectedImage, + uri: Uri.parse( + 'https://firebasestorage.googleapis.com/v0/b/appgrexdb.appspot.com/o/Images%2FPeople%2FWK242KO734Q9nPKThs9B?alt=media&token=e8906f71-58d5-42cb-9184-6f77a6c15694'), + heroTag: 5, + // openPreview: false, + editable: true, + // isLoading: true, + onPickAvatar: (file) async { + selectedImage = file; + setState(() {}); + }, + ), + const SizedBox( + height: 16, + ), + GrxSecondaryButton( + text: 'Cadastrar', + mainAxisSize: MainAxisSize.min, + margin: const EdgeInsets.symmetric( + horizontal: 16, + ), + icon: GrxIcons.person_add_right, + onPressed: () { + setState(() { + person = Person( + id: 22, + name: 'Pâmela Gabriel', + birthDate: DateTime.now(), + createUser: true, + single: true, + leadership: _leaders.last, + ); + }); + + GrxToastService.showSuccess( + title: 'Nova pessoa criada', + subtitle: 'Cadastro realizado com sucesso', + context: context, + ); + }, + ), + GrxTertiaryButton( + text: 'Whatsapp', + margin: const EdgeInsets.symmetric( + vertical: 20, + horizontal: 16, + ), + icon: GrxIcons.whatsapp, + iconAlign: GrxAlign.right, + foregroundColor: GrxColors.cff1eb35e, + onPressed: () { + setState(() { + _leaders.add( + Person(id: 8, name: '8th Person'), + ); + }); + }, + ), + GrxAnimatedLoadingButton( + textSpan: const TextSpan( + children: [ + TextSpan( + text: 'Confirmar', + ), + WidgetSpan( + child: SizedBox( + width: 5, + ), + ), + TextSpan( + text: 'Desligamento', + style: GrxHeadlineSmallTextStyle( + color: GrxColors.cffef6969, + ), + ) + ], + ), + margin: const EdgeInsets.symmetric( + horizontal: 16, + ), + backgroundColor: GrxColors.cff365278, + onPressed: (controller) async { + controller.start(); + + await Future.delayed(const Duration(seconds: 4)); + + controller.error(); + + Timer( + const Duration(seconds: 2), + () { + controller.reset(); + }, + ); + }, + ), + GrxAnimatedLoadingButton( + text: 'login.signin.button.text'.translate, + margin: const EdgeInsets.symmetric( + horizontal: 16, + vertical: 8.0, + ), + backgroundColor: GrxColors.cff75f3ab, + onPressed: (controller) async { + controller.start(); + + await Future.delayed(const Duration(seconds: 4)); + + controller.success(); + + Timer( + const Duration(seconds: 2), + () { + controller.reset(); + }, + ); + }, + ), + const SizedBox( + height: 20, + ), + Wrap( + spacing: 8.0, + runSpacing: 16.0, + children: [ + GrxSecondaryButton( + mainAxisSize: MainAxisSize.min, + text: 'Show Error', + onPressed: () => GrxToastService.showError( + title: 'Error message inside error toast', + context: context, + ), + ), + GrxSecondaryButton( + mainAxisSize: MainAxisSize.min, + text: 'Show Warning', + onPressed: () => GrxToastService.showWarning( + title: 'Warning message inside warning toast', + context: context, + ), + ), + GrxSecondaryButton( + mainAxisSize: MainAxisSize.min, + text: 'Show Success', + onPressed: () => GrxToastService.showSuccess( + title: 'Success message inside success toast', + context: context, + ), + ), + GrxSecondaryButton( + mainAxisSize: MainAxisSize.min, + text: 'Show Permanent Warning', + onPressed: () => GrxToastService.showWarning( + title: 'Showing permanent warning toast', + subtitle: + 'Adding a subtitle to show how it works', + context: context, + permanent: true, + ), + ), + ], + ), + const SizedBox( + height: 20, + ), + GrxHeader( + title: 'Preview Header', + showCloseButton: true, + ), + GrxHeader( + title: 'Preview Header With Back Button', + showBackButton: true, + backgroundColor: Colors.blue, + foregroundColor: Colors.white, + ), + GrxHeader( + title: 'Preview Header With Actions a bit long', + height: 70.0, + actions: [ + GrxFilterButton( + text: 'Filtros', + onPressed: () {}, + ), + GrxAddButton( + onPressed: () {}, + margin: const EdgeInsets.only(right: 10.0), + ), + ], + ), + const SizedBox( + height: 20.0, + ), + const GrxSvg( + 'assets/images/sheep.svg', + ), + ], + ), + ), + ], + ), + ), + GrxBottomButton( + text: 'save'.translate, + icon: GrxIcons.check, + onPressed: _validateForm, + ), + ], + ), + ), + floatingActionButton: FloatingActionButton( + onPressed: () {}, + tooltip: 'Increment', + child: const Icon(GrxIcons.save_alt), + ), // This trailing comma makes auto-formatting nicer for build methods. + ); + } +} diff --git a/sample/lib/app/widgets/fields_sample.app.widget.dart b/sample/lib/app/widgets/fields_sample.app.widget.dart new file mode 100644 index 0000000..a802f9c --- /dev/null +++ b/sample/lib/app/widgets/fields_sample.app.widget.dart @@ -0,0 +1,233 @@ +import 'package:flutter/material.dart'; +import 'package:grex_ds/grex_ds.dart'; + +import '../../enums/parent_worship_type.dart'; +import '../../extensions/string_extension.dart'; +import '../../models/knowledge_trail_model.dart'; +import '../../models/person.model.dart'; +import '../../models/role.model.dart'; +import '../../pages/knowledge_trail_select.page.dart'; + +class FieldsSampleApp extends StatefulWidget { + const FieldsSampleApp({ + super.key, + required this.person, + required this.leaders, + required this.roles, + }); + + final Person person; + final List leaders; + final List roles; + + @override + State createState() => _FieldsSampleAppState(); +} + +class _FieldsSampleAppState extends State { + bool _isLoading = true; + + @override + void initState() { + super.initState(); + + Future.delayed(const Duration(seconds: 5), () { + setState(() { + _isLoading = false; + }); + }); + } + + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 16.0), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + GrxTextFormField( + value: widget.person.name, + labelText: 'pages.people.name'.translate, + hintText: 'José Algusto', + onSaved: (value) => widget.person.name = value!, + validator: (value) => + (value?.isEmpty ?? true) ? 'Insira o nome da pessoa' : null, + isLoading: _isLoading, + ), + GrxPhoneFormField( + value: widget.person.phone, + labelText: 'pages.people.phone'.translate, + onSaved: (value, _) { + print('Phone: $value'); + widget.person.phone = value!; + }, + validator: (value) => + (value?.isEmpty ?? true) ? 'Insira o telefone da pessoa' : null, + isLoading: _isLoading, + ), + GrxDateTimePickerFormField( + value: widget.person.birthDate, + labelText: 'pages.people.birth-date'.translate, + // hintText: 'fields.datetime.hint'.translate, + dialogConfirmText: 'confirm'.translate, + dialogCancelText: 'cancel'.translate, + dialogErrorFormatText: 'fields.datetime.error-format'.translate, + dialogErrorInvalidText: 'fields.datetime.error-invalid'.translate, + isDateTime: true, + onSelectItem: (value) => print('Selected birth date: $value'), + onSaved: (value) { + print('Saved Birthdate: $value'); + + widget.person.birthDate = value; + }, + // validator: (value) => (value?.isEmpty ?? true) + // ? 'Insira a data de nascimento' + // : null, + isLoading: _isLoading, + ), + GrxDropdownFormField( + value: widget.person.leadership, + labelText: 'Liderança Direta', + onSelectItem: (value) => print('Selected Value: ${value?.name}'), + data: widget.leaders, + searchable: true, + itemBuilder: (context, index, value) => SizedBox( + height: 50, + child: Center( + child: Row( + children: [ + GrxHeadlineMediumText(value.name), + ], + ), + ), + ), + displayText: (value) => value.name, + onSaved: (value) { + print('Saved leader: $value'); + + widget.person.leadership = value; + }, + validator: (value) => + value == null ? 'O líder deve ser informado' : null, + isLoading: _isLoading, + ), + GrxDropdownFormField( + value: widget.person.fatherType, + labelText: 'O Pai é?', + onSelectItem: (value) => print('Selected Value: ${value?.name}'), + data: ParentWorshipType.values, + displayText: (value) => value.getDescription(), + onSaved: (value) { + print('Saved leader: $value'); + + widget.person.fatherType = value ?? ParentWorshipType.unknown; + }, + validator: (value) => + value == null ? 'O Tipo deve ser informado' : null, + isLoading: _isLoading, + ), + GrxAutocompleteDropdownFormField( + value: ParentWorshipType.unknown.getDescription(), + labelText: 'Rua', + onSelectItem: (value) => + print('Selected Value Rua: ${value?.name}'), + onSearch: (value) async { + if (value?.isEmpty ?? true) return null; + + await Future.delayed(const Duration(seconds: 2)); + + return ParentWorshipType.values + .where((element) => element.getDescription().contains(value!)) + .toList(); + }, + displayText: (value) => value.getDescription(), + onSaved: (value) { + print('Saved Street: $value'); + }, + validator: (value) => + value?.isEmpty ?? true ? 'A rua deve ser informada' : null, + isLoading: _isLoading, + ), + GrxMultiSelectFormField( + value: widget.person.roles, + searchable: true, + labelText: 'Funções', + onSelectItems: (value) => print('Selected Value: ${value?.length}'), + data: widget.roles, + itemBuilder: (context, index, value, onChanged, isSelected) => + InkWell( + onTap: onChanged, + child: SizedBox( + height: 50, + child: Center( + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + GrxHeadlineMediumText(value.name), + GrxRoundedCheckbox( + value: isSelected, + radius: 10, + ), + ], + ), + ), + ), + ), + displayText: (value) => value.name, + valueKey: (person) => person.id, + onSaved: (value) => widget.person.roles = value!, + validator: (value) => (value?.isEmpty ?? true) + ? 'Ao menos uma função deve ser informada' + : null, + isLoading: _isLoading, + ), + GrxCustomDropdownFormField( + value: widget.person.trail, + labelText: 'Trilho do Vencedor', + onSelectItem: (value) => print('Selected Value: ${value?.name}'), + builder: (controller, selectedValue) => KnowledgeTrailSelectPage( + data: selectedValue, + controller: controller, + ), + displayText: (value) => value.name, + onSaved: (value) { + print('Saved trail: $value'); + + widget.person.trail = value; + }, + // validator: (value) => (value?.isEmpty ?? true) + // ? 'O líder deve ser informado' + // : null, + isLoading: _isLoading, + ), + const GrxDashedDivider( + padding: EdgeInsets.symmetric(vertical: 15.0), + ), + GrxSwitchFormField( + value: widget.person.createUser, + labelText: 'Criar usuário', + onSaved: (value) => widget.person.createUser = value, + isLoading: _isLoading, + ), + const GrxDashedDivider( + title: 'Dados Auxiliares', + ), + GrxCheckboxListTile( + title: 'Solteiro', + value: widget.person.single, + isLoading: _isLoading, + onTap: () { + setState(() { + widget.person.single = !widget.person.single; + }); + }, + ), + GrxRoundedCheckbox( + value: widget.person.single, + isLoading: _isLoading, + ), + ], + ), + ); + } +} diff --git a/sample/lib/fields_sample.dart b/sample/lib/fields_sample.dart deleted file mode 100644 index 7bcb1d5..0000000 --- a/sample/lib/fields_sample.dart +++ /dev/null @@ -1,197 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:grex_ds/grex_ds.dart'; -import 'package:sample/extensions/string_extension.dart'; - -import 'enums/parent_worship_type.dart'; -import 'models/knowledge_trail_model.dart'; -import 'models/person.model.dart'; -import 'models/role.model.dart'; -import 'pages/knowledge_trail_select.page.dart'; - -class FieldsSample extends StatefulWidget { - const FieldsSample({ - super.key, - required this.person, - required this.leaders, - required this.roles, - }); - - final Person person; - final List leaders; - final List roles; - - @override - State createState() => _FieldsSampleState(); -} - -class _FieldsSampleState extends State { - bool _isLoading = true; - - @override - void initState() { - super.initState(); - - Future.delayed(const Duration(seconds: 5), () { - setState(() { - _isLoading = false; - }); - }); - } - - @override - Widget build(BuildContext context) { - return Column( - mainAxisSize: MainAxisSize.min, - children: [ - GrxTextFormField( - initialValue: widget.person.name, - labelText: 'pages.people.name'.translate, - hintText: 'José Algusto', - onSaved: (value) => widget.person.name = value!, - validator: (value) => - (value?.isEmpty ?? true) ? 'Insira o nome da pessoa' : null, - isLoading: _isLoading, - ), - GrxDateTimePickerFormField( - initialValue: widget.person.birthDate, - labelText: 'pages.people.birth-date'.translate, - // hintText: 'fields.datetime.hint'.translate, - dialogConfirmText: 'confirm'.translate, - dialogCancelText: 'cancel'.translate, - dialogErrorFormatText: 'fields.datetime.error-format'.translate, - dialogErrorInvalidText: 'fields.datetime.error-invalid'.translate, - isDateTime: true, - onSelectItem: (value) => print('Selected birth date: $value'), - onSaved: (value) { - print('Saved Birthdate: $value'); - - widget.person.birthDate = value; - }, - // validator: (value) => (value?.isEmpty ?? true) - // ? 'Insira a data de nascimento' - // : null, - isLoading: _isLoading, - ), - GrxDropdownFormField( - initialValue: widget.person.leadership, - labelText: 'Liderança Direta', - onSelectItem: (value) => print('Selected Value: ${value?.name}'), - data: widget.leaders, - searchable: true, - itemBuilder: (context, index, value) => SizedBox( - height: 50, - child: Center( - child: Row( - children: [ - GrxHeadlineMediumText(value.name), - ], - ), - ), - ), - displayText: (value) => value.name, - onSaved: (value) { - print('Saved leader: $value'); - - widget.person.leadership = value; - }, - validator: (value) => - (value?.isEmpty ?? true) ? 'O líder deve ser informado' : null, - isLoading: _isLoading, - ), - GrxDropdownFormField( - initialValue: widget.person.fatherType, - labelText: 'O Pai é?', - onSelectItem: (value) => print('Selected Value: ${value?.name}'), - data: ParentWorshipType.values, - displayText: (value) => value.getDescription(), - onSaved: (value) { - print('Saved leader: $value'); - - widget.person.fatherType = value ?? ParentWorshipType.unknown; - }, - validator: (value) => - (value?.isEmpty ?? true) ? 'O Tipo deve ser informado' : null, - isLoading: _isLoading, - ), - GrxMultiSelectFormField( - initialValue: widget.person.roles, - searchable: true, - labelText: 'Funções', - onSelectItems: (value) => print('Selected Value: ${value?.length}'), - data: widget.roles, - itemBuilder: (context, index, value, onChanged, isSelected) => - InkWell( - onTap: onChanged, - child: SizedBox( - height: 50, - child: Center( - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - GrxHeadlineMediumText(value.name), - GrxRoundedCheckbox( - initialValue: isSelected, - radius: 10, - ), - ], - ), - ), - ), - ), - displayText: (value) => value.name, - valueKey: (person) => person.id, - onSaved: (value) => widget.person.roles = value!, - validator: (value) => (value?.isEmpty ?? true) - ? 'Ao menos uma função deve ser informada' - : null, - isLoading: _isLoading, - ), - GrxCustomDropdownFormField( - initialValue: widget.person.trail, - labelText: 'Trilho do Vencedor', - onSelectItem: (value) => print('Selected Value: ${value?.name}'), - builder: (controller, selectedValue) => KnowledgeTrailSelectPage( - data: selectedValue, - controller: controller, - ), - displayText: (value) => value.name, - onSaved: (value) { - print('Saved trail: $value'); - - widget.person.trail = value; - }, - // validator: (value) => (value?.isEmpty ?? true) - // ? 'O líder deve ser informado' - // : null, - isLoading: _isLoading, - ), - const GrxDashedDivider( - padding: EdgeInsets.symmetric(vertical: 15.0), - ), - GrxSwitchFormField( - initialValue: widget.person.createUser, - labelText: 'Criar usuário', - onSaved: (value) => widget.person.createUser = value, - isLoading: _isLoading, - ), - const GrxDashedDivider( - title: 'Dados Auxiliares', - ), - GrxCheckboxListTile( - title: 'Solteiro', - isChecked: widget.person.single, - isLoading: _isLoading, - onTap: () { - setState(() { - widget.person.single = !widget.person.single; - }); - }, - ), - GrxRoundedCheckbox( - initialValue: widget.person.single, - isLoading: _isLoading, - ), - ], - ); - } -} diff --git a/sample/lib/models/person.model.dart b/sample/lib/models/person.model.dart index b118de3..7ac614e 100644 --- a/sample/lib/models/person.model.dart +++ b/sample/lib/models/person.model.dart @@ -5,6 +5,7 @@ import 'role.model.dart'; class Person { int id; String name; + String? phone; Person? leadership; DateTime? birthDate; bool createUser; @@ -17,6 +18,7 @@ class Person { Person({ required this.id, required this.name, + this.phone, this.leadership, this.birthDate, this.createUser = false, diff --git a/sample/lib/pages/home_page.dart b/sample/lib/pages/home_page.dart index 7bb8c8d..6b0478d 100644 --- a/sample/lib/pages/home_page.dart +++ b/sample/lib/pages/home_page.dart @@ -1,11 +1,12 @@ import 'package:flutter/material.dart'; import 'package:grex_ds/grex_ds.dart'; -import 'package:sample/extensions/string_extension.dart'; +import '../../extensions/string_extension.dart'; +import '../app/pages/dashboard.app.page.dart'; import '../models/tab_icon_data.model.dart'; +import '../web/pages/dashboard.web.page.dart'; import '../widgets/bottom_bar.widget.dart'; import 'cellules_list.page.dart'; -import 'dashboard.page.dart'; import 'people_list.page.dart'; import 'settings.page.dart'; @@ -50,10 +51,19 @@ class _HomePageState extends State with TickerProviderStateMixin { ), ]; - Widget tabBody = Container( - color: GrxColors.cfff2f7fd, + late final _defaultBody = GrxResponsiveLayout( + mobileView: DashboardAppPage( + key: widget.key, + animationController: animationController, + ), + desktopView: DashboardWebPage( + key: widget.key, + animationController: animationController, + ), ); + late Widget tabBody = _defaultBody; + @override void initState() { super.initState(); @@ -64,14 +74,9 @@ class _HomePageState extends State with TickerProviderStateMixin { tabIconsList[0].isSelected = true; animationController = AnimationController( - duration: const Duration(milliseconds: 600), + duration: const Duration(milliseconds: 2000), vsync: this, ); - - tabBody = DashboardPage( - key: widget.key, - animationController: animationController, - ); } @override @@ -95,8 +100,7 @@ class _HomePageState extends State with TickerProviderStateMixin { return; } setState(() { - tabBody = - DashboardPage(animationController: animationController); + tabBody = _defaultBody; }); }); } else if (index == 1) { diff --git a/sample/lib/pages/knowledge_trail_select.page.dart b/sample/lib/pages/knowledge_trail_select.page.dart index 6b55970..2fa8d27 100644 --- a/sample/lib/pages/knowledge_trail_select.page.dart +++ b/sample/lib/pages/knowledge_trail_select.page.dart @@ -55,10 +55,9 @@ class _KnowledgeTrailStateSelectPage extends State { bottom: mediaQuery.viewInsets.bottom + mediaQuery.padding.bottom + 8.0, ), color: GrxColors.cfff2f7fd, - child: Card( + child: GrxCard( color: Colors.white, elevation: 0, - shape: GrxUtils.defaultCardBorder, // margin: const EdgeInsets.only(left: 15, right: 15, bottom: 15), child: Column( mainAxisSize: MainAxisSize.min, @@ -135,8 +134,8 @@ class _KnowledgeTrailStateSelectPage extends State { child: Container( // margin: const EdgeInsets.only(bottom: 20), child: GrxRoundedCheckbox( + value: trail.priority == _data.priority, radius: 10, - initialValue: trail.priority == _data.priority, isTappable: false, ), ), diff --git a/sample/lib/pages/people_list.page.dart b/sample/lib/pages/people_list.page.dart index 4f53044..57d4d55 100644 --- a/sample/lib/pages/people_list.page.dart +++ b/sample/lib/pages/people_list.page.dart @@ -1,4 +1,3 @@ -import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:grex_ds/grex_ds.dart'; @@ -12,57 +11,29 @@ class PeopleListPage extends StatelessWidget { @override Widget build(BuildContext context) { - return Scaffold( - body: CustomScrollView( - slivers: [ - GrxSearchableSliverHeader( - animationController: animationController, - title: 'Title', - ), - SliverList( - delegate: SliverChildBuilderDelegate( - (context, index) { - final begin = - clampDouble((1 / (100 / index * 12)) * index, 0, 1); - - final contentAnimation = - Tween(begin: 0.0, end: 1.0).animate( - CurvedAnimation( - parent: animationController, - curve: Interval(begin, 1.0, curve: Curves.fastOutSlowIn), - ), - ); + animationController.forward(); - animationController.forward(); - - return AnimatedBuilder( - animation: animationController, - builder: (context, child) { - return FadeTransition( - opacity: contentAnimation, - child: Transform( - transform: Matrix4.translationValues( - 0.0, 30 * (1.0 - contentAnimation.value), 0.0), - child: const Padding( - padding: EdgeInsets.all(10.0), - child: Card( - child: Padding( - padding: EdgeInsets.all( - 40, - ), - child: Text('22'), - ), - ), - ), - ), - ); - }, - ); - }, - childCount: 100, + return Scaffold( + body: GrxSliverAnimatedList( + animationController: animationController, + title: 'Title', + list: List.filled(100, 1), + padding: const EdgeInsets.only( + bottom: 120.0, + ), + itemBuilder: (item, index) { + return Padding( + padding: const EdgeInsets.all(10.0), + child: GrxCard( + child: Padding( + padding: const EdgeInsets.all( + 40.0, + ), + child: Text('$index'), + ), ), - ), - ], + ); + }, ), ); } diff --git a/sample/lib/typo_sample.dart b/sample/lib/typo_sample.dart index 956a86f..cf9e2b2 100644 --- a/sample/lib/typo_sample.dart +++ b/sample/lib/typo_sample.dart @@ -6,9 +6,9 @@ class TypoSample extends StatelessWidget { @override Widget build(BuildContext context) { - return Column( + return const Column( mainAxisSize: MainAxisSize.min, - children: const [ + children: [ GrxHeadlineLargeText('Healine Large Text'), GrxHeadlineLargeText( 'Healine Large Text', diff --git a/sample/lib/pages/dashboard.page.dart b/sample/lib/web/pages/dashboard.web.page.dart similarity index 87% rename from sample/lib/pages/dashboard.page.dart rename to sample/lib/web/pages/dashboard.web.page.dart index de7e261..92ae3ba 100644 --- a/sample/lib/pages/dashboard.page.dart +++ b/sample/lib/web/pages/dashboard.web.page.dart @@ -3,12 +3,12 @@ import 'dart:io'; import 'package:flutter/material.dart'; import 'package:grex_ds/grex_ds.dart'; -import 'package:sample/extensions/string_extension.dart'; -import '../fields_sample.dart'; -import '../models/person.model.dart'; -import '../models/role.model.dart'; -import '../typo_sample.dart'; +import '../../extensions/string_extension.dart'; +import '../../models/person.model.dart'; +import '../../models/role.model.dart'; +import '../../typo_sample.dart'; +import '../widgets/fields_sample.web.widget.dart'; final _leaders = [ Person(id: 1, name: '1st Person'), @@ -56,8 +56,8 @@ final _roles = [ Role(id: 20, name: '20th Role', priority: 20), ]; -class DashboardPage extends StatefulWidget { - const DashboardPage({ +class DashboardWebPage extends StatefulWidget { + const DashboardWebPage({ super.key, required this.animationController, }); @@ -65,10 +65,10 @@ class DashboardPage extends StatefulWidget { final AnimationController animationController; @override - State createState() => _DashboardPageState(); + State createState() => _DashboardWebPageState(); } -class _DashboardPageState extends State +class _DashboardWebPageState extends State with TickerProviderStateMixin { final formKey = GlobalKey(); late Person person; @@ -76,11 +76,14 @@ class _DashboardPageState extends State late final AnimationController animationController; File? selectedImage; + bool isLoading = false; + @override void initState() { person = Person( id: 22, name: 'Leonardo Gabriel', + phone: '54992099544', birthDate: DateTime.now(), leadership: _leaders.first, roles: [ @@ -102,15 +105,28 @@ class _DashboardPageState extends State super.initState(); } - bool _validateForm() { - final form = formKey.currentState; + Future _validateForm() async { + try { + final form = formKey.currentState; - if (form?.validate() ?? false) { - form!.save(); - return true; - } + if (form?.validate() ?? false) { + setState(() { + isLoading = true; + }); + await Future.delayed( + const Duration(milliseconds: 4000), + ); + + form!.save(); + return true; + } - return false; + return false; + } finally { + setState(() { + isLoading = false; + }); + } } @override @@ -124,7 +140,7 @@ class _DashboardPageState extends State return Scaffold( backgroundColor: Colors.white, appBar: GrxHeader( - // Here we take the value from the DashboardPage object that was created by + // Here we take the value from the DashboardWebPage object that was created by // the App.build method, and use it to set our appbar title. title: 'Dashboard Page', backgroundColor: GrxColors.cff365278, @@ -149,13 +165,16 @@ class _DashboardPageState extends State // axis because Columns are vertical (the cross axis would be // horizontal). // mainAxisAlignment: MainAxisAlignment.center, + padding: EdgeInsets.only( + bottom: MediaQuery.paddingOf(context).bottom + 120, + ), children: [ const TypoSample(), Form( key: formKey, child: Column( children: [ - FieldsSample( + FieldsSampleWeb( person: person, leaders: _leaders, roles: _roles, @@ -260,7 +279,7 @@ class _DashboardPageState extends State GrxToastService.showSuccess( title: 'Nova pessoa criada', - message: 'Cadastro realizado com sucesso', + subtitle: 'Cadastro realizado com sucesso', context: context, ); }, @@ -351,7 +370,7 @@ class _DashboardPageState extends State mainAxisSize: MainAxisSize.min, text: 'Show Error', onPressed: () => GrxToastService.showError( - message: 'Error message inside error toast', + title: 'Error message inside error toast', context: context, ), ), @@ -359,7 +378,7 @@ class _DashboardPageState extends State mainAxisSize: MainAxisSize.min, text: 'Show Warning', onPressed: () => GrxToastService.showWarning( - message: 'Warning message inside warning toast', + title: 'Warning message inside warning toast', context: context, ), ), @@ -367,7 +386,18 @@ class _DashboardPageState extends State mainAxisSize: MainAxisSize.min, text: 'Show Success', onPressed: () => GrxToastService.showSuccess( - message: 'Success message inside success toast', + title: 'Success message inside success toast', + context: context, + ), + ), + GrxSecondaryButton( + mainAxisSize: MainAxisSize.min, + text: 'Show Permanent Warning', + onPressed: () => GrxToastService.showWarning( + permanent: true, + title: 'Showing permanent warning toast', + subtitle: + 'Adding a subtitle to show how it works', context: context, ), ), @@ -409,14 +439,15 @@ class _DashboardPageState extends State ], ), ), + GrxBottomButton( + text: 'save'.translate, + icon: GrxIcons.check, + onPressed: _validateForm, + isLoading: isLoading, + ), ], ), ), - GrxBottomButton( - text: 'save'.translate, - icon: GrxIcons.check, - onPressed: _validateForm, - ), ], ), floatingActionButton: FloatingActionButton( diff --git a/sample/lib/web/widgets/fields_sample.web.widget.dart b/sample/lib/web/widgets/fields_sample.web.widget.dart new file mode 100644 index 0000000..d9b7dfe --- /dev/null +++ b/sample/lib/web/widgets/fields_sample.web.widget.dart @@ -0,0 +1,100 @@ +import 'package:flutter/material.dart'; +import 'package:grex_ds/grex_ds.dart'; + +import '../../extensions/string_extension.dart'; +import '../../models/person.model.dart'; +import '../../models/role.model.dart'; + +class FieldsSampleWeb extends StatefulWidget { + const FieldsSampleWeb({ + super.key, + required this.person, + required this.leaders, + required this.roles, + }); + + final Person person; + final List leaders; + final List roles; + + @override + State createState() => _FieldsSampleWebState(); +} + +class _FieldsSampleWebState extends State { + bool _isLoading = true; + + @override + void initState() { + super.initState(); + + Future.delayed(const Duration(seconds: 5), () { + setState(() { + _isLoading = false; + }); + }); + } + + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsets.symmetric(vertical: 16.0), + child: Row( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + GrxTextFormField( + value: widget.person.name, + labelText: 'pages.people.name'.translate, + hintText: 'José Algusto', + onSaved: (value) => widget.person.name = value!, + validator: (value) => + (value?.isEmpty ?? true) ? 'Insira o nome da pessoa' : null, + isLoading: _isLoading, + ), + GrxPhoneFormField( + value: widget.person.phone, + labelText: 'pages.people.phone'.translate, + onSaved: (value, _) { + print('Phone: $value'); + widget.person.phone = value!; + }, + validator: (value) => + (value?.isEmpty ?? true) ? 'Insira o telefone da pessoa' : null, + isLoading: _isLoading, + ), + GrxDateTimePickerFormField( + value: widget.person.birthDate, + labelText: 'pages.people.birth-date'.translate, + // hintText: 'fields.datetime.hint'.translate, + dialogConfirmText: 'confirm'.translate, + dialogCancelText: 'cancel'.translate, + dialogErrorFormatText: 'fields.datetime.error-format'.translate, + dialogErrorInvalidText: 'fields.datetime.error-invalid'.translate, + isDateTime: true, + onSelectItem: (value) => print('Selected birth date: $value'), + onSaved: (value) { + print('Saved Birthdate: $value'); + + widget.person.birthDate = value; + }, + // validator: (value) => (value?.isEmpty ?? true) + // ? 'Insira a data de nascimento' + // : null, + isLoading: _isLoading, + ), + ] + .map( + (child) => Flexible( + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 8.0, + ), + child: child, + ), + ), + ) + .toList(), + ), + ); + } +} diff --git a/sample/linux/flutter/generated_plugin_registrant.cc b/sample/linux/flutter/generated_plugin_registrant.cc index f6f23bf..7299b5c 100644 --- a/sample/linux/flutter/generated_plugin_registrant.cc +++ b/sample/linux/flutter/generated_plugin_registrant.cc @@ -6,9 +6,13 @@ #include "generated_plugin_registrant.h" +#include #include void fl_register_plugins(FlPluginRegistry* registry) { + g_autoptr(FlPluginRegistrar) file_selector_linux_registrar = + fl_plugin_registry_get_registrar_for_plugin(registry, "FileSelectorPlugin"); + file_selector_plugin_register_with_registrar(file_selector_linux_registrar); g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar = fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin"); url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar); diff --git a/sample/linux/flutter/generated_plugins.cmake b/sample/linux/flutter/generated_plugins.cmake index f16b4c3..786ff5c 100644 --- a/sample/linux/flutter/generated_plugins.cmake +++ b/sample/linux/flutter/generated_plugins.cmake @@ -3,6 +3,7 @@ # list(APPEND FLUTTER_PLUGIN_LIST + file_selector_linux url_launcher_linux ) diff --git a/sample/pubspec.lock b/sample/pubspec.lock index e640143..1dee8cf 100644 --- a/sample/pubspec.lock +++ b/sample/pubspec.lock @@ -1,22 +1,14 @@ # Generated by pub # See https://dart.dev/tools/pub/glossary#lockfile packages: - another_flushbar: - dependency: transitive - description: - name: another_flushbar - sha256: "19bf9520230ec40b300aaf9dd2a8fefcb277b25ecd1c4838f530566965befc2a" - url: "https://pub.dev" - source: hosted - version: "1.12.30" args: dependency: transitive description: name: args - sha256: c372bb384f273f0c2a8aaaa226dad84dc27c8519a691b888725dec59518ad53a + sha256: eef6c46b622e0494a36c5a12d10d77fb4e855501a91c1b9ef9339326e58f0596 url: "https://pub.dev" source: hosted - version: "2.4.1" + version: "2.4.2" async: dependency: transitive description: @@ -37,26 +29,26 @@ packages: dependency: transitive description: name: cached_network_image - sha256: fd3d0dc1d451f9a252b32d95d3f0c3c487bc41a75eba2e6097cb0b9c71491b15 + sha256: "28ea9690a8207179c319965c13cd8df184d5ee721ae2ce60f398ced1219cea1f" url: "https://pub.dev" source: hosted - version: "3.2.3" + version: "3.3.1" cached_network_image_platform_interface: dependency: transitive description: name: cached_network_image_platform_interface - sha256: bb2b8403b4ccdc60ef5f25c70dead1f3d32d24b9d6117cfc087f496b178594a7 + sha256: "9e90e78ae72caa874a323d78fa6301b3fb8fa7ea76a8f96dc5b5bf79f283bf2f" url: "https://pub.dev" source: hosted - version: "2.0.0" + version: "4.0.0" cached_network_image_web: dependency: transitive description: name: cached_network_image_web - sha256: b8eb814ebfcb4dea049680f8c1ffb2df399e4d03bf7a352c775e26fa06e02fa0 + sha256: "42a835caa27c220d1294311ac409a43361088625a4f23c820b006dd9bffb3316" url: "https://pub.dev" source: hosted - version: "1.0.2" + version: "1.1.1" characters: dependency: transitive description: @@ -77,18 +69,18 @@ packages: dependency: transitive description: name: collection - sha256: "4a07be6cb69c84d677a6c3096fcf960cc3285a8330b4603e0d463d15d9bd934c" + sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a url: "https://pub.dev" source: hosted - version: "1.17.1" + version: "1.18.0" cross_file: dependency: transitive description: name: cross_file - sha256: "0b0036e8cccbfbe0555fd83c1d31a6f30b77a96b598b35a5d36dd41f718695e9" + sha256: "55d7b444feb71301ef6b8838dbc1ae02e63dd48c8773f3810ff53bb1e2945b32" url: "https://pub.dev" source: hosted - version: "0.3.3+4" + version: "0.3.4+1" crypto: dependency: transitive description: @@ -101,10 +93,18 @@ packages: dependency: "direct main" description: name: cupertino_icons - sha256: e35129dc44c9118cee2a5603506d823bab99c68393879edb440e0090d07586be + sha256: d57953e10f9f8327ce64a508a355f0b1ec902193f66288e8cb5070e7c47eeb2d url: "https://pub.dev" source: hosted - version: "1.0.5" + version: "1.0.6" + delightful_toast: + dependency: transitive + description: + name: delightful_toast + sha256: "93d0b9e89a65947e42daa8aafe552596487dbedc15f68d0480654e789e94bc5b" + url: "https://pub.dev" + source: hosted + version: "1.1.0" fake_async: dependency: transitive description: @@ -117,47 +117,87 @@ packages: dependency: transitive description: name: ffi - sha256: ed5337a5660c506388a9f012be0288fb38b49020ce2b45fe1f8b8323fe429f99 + sha256: "493f37e7df1804778ff3a53bd691d8692ddf69702cf4c1c1096a2e41b4779e21" url: "https://pub.dev" source: hosted - version: "2.0.2" + version: "2.1.2" file: dependency: transitive description: name: file - sha256: "1b92bec4fc2a72f59a8e15af5f52cd441e4a7860b49499d69dfa817af20e925d" + sha256: "5fc22d7c25582e38ad9a8515372cd9a93834027aacf1801cf01164dac0ffa08c" + url: "https://pub.dev" + source: hosted + version: "7.0.0" + file_selector_linux: + dependency: transitive + description: + name: file_selector_linux + sha256: "045d372bf19b02aeb69cacf8b4009555fb5f6f0b7ad8016e5f46dd1387ddd492" + url: "https://pub.dev" + source: hosted + version: "0.9.2+1" + file_selector_macos: + dependency: transitive + description: + name: file_selector_macos + sha256: b15c3da8bd4908b9918111fa486903f5808e388b8d1c559949f584725a6594d6 + url: "https://pub.dev" + source: hosted + version: "0.9.3+3" + file_selector_platform_interface: + dependency: transitive + description: + name: file_selector_platform_interface + sha256: a3994c26f10378a039faa11de174d7b78eb8f79e4dd0af2a451410c1a5c3f66b + url: "https://pub.dev" + source: hosted + version: "2.6.2" + file_selector_windows: + dependency: transitive + description: + name: file_selector_windows + sha256: d3547240c20cabf205c7c7f01a50ecdbc413755814d6677f3cb366f04abcead0 + url: "https://pub.dev" + source: hosted + version: "0.9.3+1" + fixnum: + dependency: transitive + description: + name: fixnum + sha256: "25517a4deb0c03aa0f32fd12db525856438902d9c16536311e76cdc57b31d7d1" url: "https://pub.dev" source: hosted - version: "6.1.4" + version: "1.1.0" flutter: dependency: "direct main" description: flutter source: sdk version: "0.0.0" - flutter_blurhash: + flutter_animate: dependency: transitive description: - name: flutter_blurhash - sha256: "05001537bd3fac7644fa6558b09ec8c0a3f2eba78c0765f88912882b1331a5c6" + name: flutter_animate + sha256: "7c8a6594a9252dad30cc2ef16e33270b6248c4dedc3b3d06c86c4f3f4dc05ae5" url: "https://pub.dev" source: hosted - version: "0.7.0" + version: "4.5.0" flutter_cache_manager: dependency: transitive description: name: flutter_cache_manager - sha256: "32cd900555219333326a2d0653aaaf8671264c29befa65bbd9856d204a4c9fb3" + sha256: "8207f27539deb83732fdda03e259349046a39a4c767269285f449ade355d54ba" url: "https://pub.dev" source: hosted - version: "3.3.0" + version: "3.3.1" flutter_lints: dependency: "direct dev" description: name: flutter_lints - sha256: aeb0b80a8b3709709c9cc496cdc027c5b3216796bc0af0ce1007eaf24464fd4c + sha256: "9e8c3858111da373efc5aa341de011d9bd23e2c5c5e0c62bccf32438e192d7b1" url: "https://pub.dev" source: hosted - version: "2.0.1" + version: "3.0.2" flutter_localizations: dependency: "direct main" description: flutter @@ -167,18 +207,34 @@ packages: dependency: transitive description: name: flutter_plugin_android_lifecycle - sha256: "96af49aa6b57c10a312106ad6f71deed5a754029c24789bbf620ba784f0bd0b0" + sha256: b068ffc46f82a55844acfa4fdbb61fad72fa2aef0905548419d97f0f95c456da + url: "https://pub.dev" + source: hosted + version: "2.0.17" + flutter_shaders: + dependency: transitive + description: + name: flutter_shaders + sha256: "02750b545c01ff4d8e9bbe8f27a7731aa3778402506c67daa1de7f5fc3f4befe" + url: "https://pub.dev" + source: hosted + version: "0.1.2" + flutter_staggered_grid_view: + dependency: transitive + description: + name: flutter_staggered_grid_view + sha256: "19e7abb550c96fbfeb546b23f3ff356ee7c59a019a651f8f102a4ba9b7349395" url: "https://pub.dev" source: hosted - version: "2.0.14" + version: "0.7.0" flutter_svg: dependency: transitive description: name: flutter_svg - sha256: f991fdb1533c3caeee0cdc14b04f50f0c3916f0dbcbc05237ccbe4e3c6b93f3f + sha256: "7b4ca6cf3304575fe9c8ec64813c8d02ee41d2afe60bcfe0678bcb5375d596a2" url: "https://pub.dev" source: hosted - version: "2.0.5" + version: "2.0.10+1" flutter_test: dependency: "direct dev" description: flutter @@ -193,10 +249,10 @@ packages: dependency: "direct main" description: name: get - sha256: "2ba20a47c8f1f233bed775ba2dd0d3ac97b4cf32fc17731b3dfc672b06b0e92a" + sha256: e4e7335ede17452b391ed3b2ede016545706c01a02292a6c97619705e7d2a85e url: "https://pub.dev" source: hosted - version: "4.6.5" + version: "4.6.6" grex_ds: dependency: "direct main" description: @@ -208,10 +264,10 @@ packages: dependency: transitive description: name: http - sha256: "5895291c13fa8a3bd82e76d5627f69e0d85ca6a30dcac95c4ea19a5d555879c2" + sha256: "761a297c042deedc1ffbb156d6e2af13886bb305c2a343a4d972504cd67dd938" url: "https://pub.dev" source: hosted - version: "0.13.6" + version: "1.2.1" http_parser: dependency: transitive description: @@ -224,74 +280,106 @@ packages: dependency: transitive description: name: image_cropper - sha256: "542c3453109d16bcc388e43ae2276044d2cd6a6d20c68bdcff2c94ab9363ea15" + sha256: f4bad5ed2dfff5a7ce0dfbad545b46a945c702bb6182a921488ef01ba7693111 url: "https://pub.dev" source: hosted - version: "4.0.1" + version: "5.0.1" image_cropper_for_web: dependency: transitive description: name: image_cropper_for_web - sha256: "89c936aa772a35b69ca67b78049ae9fa163a4fb8da2f6dee3893db8883fb49d2" + sha256: "865d798b5c9d826f1185b32e5d0018c4183ddb77b7b82a931e1a06aa3b74974e" url: "https://pub.dev" source: hosted - version: "2.0.0" + version: "3.0.0" image_cropper_platform_interface: dependency: transitive description: name: image_cropper_platform_interface - sha256: b232175c132b2f7ede3e1f101652bcd635cb4079a77c6dded8e6d32e6578d685 + sha256: ee160d686422272aa306125f3b6fb1c1894d9b87a5e20ed33fa008e7285da11e url: "https://pub.dev" source: hosted - version: "4.0.0" + version: "5.0.0" image_picker: dependency: transitive description: name: image_picker - sha256: "3da954c3b8906d82ecb50fd5e2b5401758f06d5678904eed6cbc06172283a263" + sha256: "26222b01a0c9a2c8fe02fc90b8208bd3325da5ed1f4a2acabf75939031ac0bdd" url: "https://pub.dev" source: hosted - version: "0.8.7+4" + version: "1.0.7" image_picker_android: dependency: transitive description: name: image_picker_android - sha256: cc3e183c6dc00b24f3d07a913cc30f4fb7b54ec9aac1c135df27e3b5faf487be + sha256: "42c098e7fb6334746be37cdc30369ade356ed4f14d48b7a0313f95a9159f4321" url: "https://pub.dev" source: hosted - version: "0.8.6+12" + version: "0.8.9+5" image_picker_for_web: dependency: transitive description: name: image_picker_for_web - sha256: "98f50d6b9f294c8ba35e25cc0d13b04bfddd25dbc8d32fa9d566a6572f2c081c" + sha256: "6a1704fdd75022272e7e7a897a9068e9c2ff3cd6a66820bf3ded810633eac954" url: "https://pub.dev" source: hosted - version: "2.1.12" + version: "3.0.3" image_picker_ios: dependency: transitive description: name: image_picker_ios - sha256: a1546ff5861fc15812953d4733b520c3d371cec3d2859a001ff04c46c4d81883 + sha256: "917a5cadd67d052554cfb258595e54217de53fac5b52939426e26319a02e6297" + url: "https://pub.dev" + source: hosted + version: "0.8.9+2" + image_picker_linux: + dependency: transitive + description: + name: image_picker_linux + sha256: "4ed1d9bb36f7cd60aa6e6cd479779cc56a4cb4e4de8f49d487b1aaad831300fa" + url: "https://pub.dev" + source: hosted + version: "0.2.1+1" + image_picker_macos: + dependency: transitive + description: + name: image_picker_macos + sha256: "3f5ad1e8112a9a6111c46d0b57a7be2286a9a07fc6e1976fdf5be2bd31d4ff62" url: "https://pub.dev" source: hosted - version: "0.8.7+3" + version: "0.2.1+1" image_picker_platform_interface: dependency: transitive description: name: image_picker_platform_interface - sha256: "1991219d9dbc42a99aff77e663af8ca51ced592cd6685c9485e3458302d3d4f8" + sha256: "3d2c323daea9d60608f1caf30be32a938916f4975434b8352e6f73dae496da38" + url: "https://pub.dev" + source: hosted + version: "2.9.4" + image_picker_windows: + dependency: transitive + description: + name: image_picker_windows + sha256: "6ad07afc4eb1bc25f3a01084d28520496c4a3bb0cb13685435838167c9dcedeb" + url: "https://pub.dev" + source: hosted + version: "0.2.1+1" + infinite_scroll_pagination: + dependency: transitive + description: + name: infinite_scroll_pagination + sha256: b68bce20752fcf36c7739e60de4175494f74e99e9a69b4dd2fe3a1dd07a7f16a url: "https://pub.dev" source: hosted - version: "2.6.3" + version: "4.0.0" intl: dependency: transitive description: name: intl - sha256: a3715e3bc90294e971cb7dc063fbf3cd9ee0ebf8604ffeafabd9e6f16abbdbe6 + sha256: "3bc132a9dbce73a7e4a21a17d06e1878839ffbf975568bc875c60537824b0c4d" url: "https://pub.dev" source: hosted - version: "0.18.0" + version: "0.18.1" js: dependency: transitive description: @@ -300,6 +388,30 @@ packages: url: "https://pub.dev" source: hosted version: "0.6.7" + leak_tracker: + dependency: transitive + description: + name: leak_tracker + sha256: "78eb209deea09858f5269f5a5b02be4049535f568c07b275096836f01ea323fa" + url: "https://pub.dev" + source: hosted + version: "10.0.0" + leak_tracker_flutter_testing: + dependency: transitive + description: + name: leak_tracker_flutter_testing + sha256: b46c5e37c19120a8a01918cfaf293547f47269f7cb4b0058f21531c2465d6ef0 + url: "https://pub.dev" + source: hosted + version: "2.0.1" + leak_tracker_testing: + dependency: transitive + description: + name: leak_tracker_testing + sha256: a597f72a664dbd293f3bfc51f9ba69816f84dcd403cdac7066cb3f6003f3ab47 + url: "https://pub.dev" + source: hosted + version: "2.0.1" linkify: dependency: transitive description: @@ -312,50 +424,66 @@ packages: dependency: transitive description: name: lints - sha256: "5e4a9cd06d447758280a8ac2405101e0e2094d2a1dbdd3756aec3fe7775ba593" + sha256: cbf8d4b858bb0134ef3ef87841abdf8d63bfc255c266b7bf6b39daa1085c4290 url: "https://pub.dev" source: hosted - version: "2.0.1" + version: "3.0.0" + mask_text_input_formatter: + dependency: transitive + description: + name: mask_text_input_formatter + sha256: "978c58ec721c25621ceb468e633f4eef64b64d45424ac4540e0565d4f7c800cd" + url: "https://pub.dev" + source: hosted + version: "2.9.0" matcher: dependency: transitive description: name: matcher - sha256: "6501fbd55da300384b768785b83e5ce66991266cec21af89ab9ae7f5ce1c4cbb" + sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb url: "https://pub.dev" source: hosted - version: "0.12.15" + version: "0.12.16+1" material_color_utilities: dependency: transitive description: name: material_color_utilities - sha256: d92141dc6fe1dad30722f9aa826c7fbc896d021d792f80678280601aff8cf724 + sha256: "0e0a020085b65b6083975e499759762399b4475f766c21668c4ecca34ea74e5a" url: "https://pub.dev" source: hosted - version: "0.2.0" + version: "0.8.0" meta: dependency: transitive description: name: meta - sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3" + sha256: d584fa6707a52763a52446f02cc621b077888fb63b93bbcb1143a7be5a0c0c04 + url: "https://pub.dev" + source: hosted + version: "1.11.0" + mime: + dependency: transitive + description: + name: mime + sha256: "2e123074287cc9fd6c09de8336dae606d1ddb88d9ac47358826db698c176a1f2" url: "https://pub.dev" source: hosted - version: "1.9.1" + version: "1.0.5" octo_image: dependency: transitive description: name: octo_image - sha256: "107f3ed1330006a3bea63615e81cf637433f5135a52466c7caa0e7152bca9143" + sha256: "45b40f99622f11901238e18d48f5f12ea36426d8eced9f4cbf58479c7aa2430d" url: "https://pub.dev" source: hosted - version: "1.0.2" + version: "2.0.0" path: dependency: transitive description: name: path - sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917" + sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af" url: "https://pub.dev" source: hosted - version: "1.8.3" + version: "1.9.0" path_parsing: dependency: transitive description: @@ -368,66 +496,58 @@ packages: dependency: transitive description: name: path_provider - sha256: "3087813781ab814e4157b172f1a11c46be20179fcc9bea043e0fba36bc0acaa2" + sha256: b27217933eeeba8ff24845c34003b003b2b22151de3c908d0e679e8fe1aa078b url: "https://pub.dev" source: hosted - version: "2.0.15" + version: "2.1.2" path_provider_android: dependency: transitive description: name: path_provider_android - sha256: "2cec049d282c7f13c594b4a73976b0b4f2d7a1838a6dd5aaf7bd9719196bee86" + sha256: "477184d672607c0a3bf68fbbf601805f92ef79c82b64b4d6eb318cbca4c48668" url: "https://pub.dev" source: hosted - version: "2.0.27" + version: "2.2.2" path_provider_foundation: dependency: transitive description: name: path_provider_foundation - sha256: "1995d88ec2948dac43edf8fe58eb434d35d22a2940ecee1a9fefcd62beee6eb3" + sha256: "5a7999be66e000916500be4f15a3633ebceb8302719b47b9cc49ce924125350f" url: "https://pub.dev" source: hosted - version: "2.2.3" + version: "2.3.2" path_provider_linux: dependency: transitive description: name: path_provider_linux - sha256: "2ae08f2216225427e64ad224a24354221c2c7907e448e6e0e8b57b1eb9f10ad1" + sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279 url: "https://pub.dev" source: hosted - version: "2.1.10" + version: "2.2.1" path_provider_platform_interface: dependency: transitive description: name: path_provider_platform_interface - sha256: "57585299a729335f1298b43245842678cb9f43a6310351b18fb577d6e33165ec" + sha256: "88f5779f72ba699763fa3a3b06aa4bf6de76c8e5de842cf6f29e2e06476c2334" url: "https://pub.dev" source: hosted - version: "2.0.6" + version: "2.1.2" path_provider_windows: dependency: transitive description: name: path_provider_windows - sha256: d3f80b32e83ec208ac95253e0cd4d298e104fbc63cb29c5c69edaed43b0c69d6 + sha256: "8bc9f22eee8690981c22aa7fc602f5c85b497a6fb2ceb35ee5a5e5ed85ad8170" url: "https://pub.dev" source: hosted - version: "2.1.6" - pedantic: - dependency: transitive - description: - name: pedantic - sha256: "67fc27ed9639506c856c840ccce7594d0bdcd91bc8d53d6e52359449a1d50602" - url: "https://pub.dev" - source: hosted - version: "1.11.1" + version: "2.2.1" petitparser: dependency: transitive description: name: petitparser - sha256: "49392a45ced973e8d94a85fdb21293fbb40ba805fc49f2965101ae748a3683b4" + sha256: c15605cd28af66339f8eb6fbe0e541bfe2d1b72d5825efc6598f3e0a31b9ad27 url: "https://pub.dev" source: hosted - version: "5.1.0" + version: "6.0.2" photo_view: dependency: transitive description: @@ -440,34 +560,34 @@ packages: dependency: transitive description: name: platform - sha256: "4a451831508d7d6ca779f7ac6e212b4023dd5a7d08a27a63da33756410e32b76" + sha256: "12220bb4b65720483f8fa9450b4332347737cf8213dd2840d8b2c823e47243ec" url: "https://pub.dev" source: hosted - version: "3.1.0" + version: "3.1.4" plugin_platform_interface: dependency: transitive description: name: plugin_platform_interface - sha256: "6a2128648c854906c53fa8e33986fc0247a1116122f9534dd20e3ab9e16a32bc" + sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02" url: "https://pub.dev" source: hosted - version: "2.1.4" - process: + version: "2.1.8" + popover: dependency: transitive description: - name: process - sha256: "53fd8db9cec1d37b0574e12f07520d582019cb6c44abf5479a01505099a34a09" + name: popover + sha256: ca3bef9d88ebf5c5c3823946a5de3ce8360018fbb6a3e25819586a7d5a203db2 url: "https://pub.dev" source: hosted - version: "4.2.4" - rounded_loading_button: + version: "0.3.0" + rounded_loading_button_plus: dependency: transitive description: - name: rounded_loading_button - sha256: ec4af194330ba688527749059b7c1a3d1ddda6c18794ec4b0696f0cb3b9784ff + name: rounded_loading_button_plus + sha256: "8baad9b66c4a81b02b597edf7691cf78f7267a999c08a68937e391af7b2da653" url: "https://pub.dev" source: hosted - version: "2.1.0" + version: "3.0.1" rxdart: dependency: transitive description: @@ -489,46 +609,62 @@ packages: description: flutter source: sdk version: "0.0.99" + sliver_tools: + dependency: transitive + description: + name: sliver_tools + sha256: eae28220badfb9d0559207badcbbc9ad5331aac829a88cb0964d330d2a4636a6 + url: "https://pub.dev" + source: hosted + version: "0.2.12" source_span: dependency: transitive description: name: source_span - sha256: dd904f795d4b4f3b870833847c461801f6750a9fa8e61ea5ac53f9422b31f250 + sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c" + url: "https://pub.dev" + source: hosted + version: "1.10.0" + sprintf: + dependency: transitive + description: + name: sprintf + sha256: "1fc9ffe69d4df602376b52949af107d8f5703b77cda567c4d7d86a0693120f23" url: "https://pub.dev" source: hosted - version: "1.9.1" + version: "7.0.0" sqflite: dependency: transitive description: name: sqflite - sha256: "3a82c9a216b46b88617e3714dd74227eaca20c501c4abcc213e56db26b9caa00" + sha256: a9016f495c927cb90557c909ff26a6d92d9bd54fc42ba92e19d4e79d61e798c6 url: "https://pub.dev" source: hosted - version: "2.2.8+2" + version: "2.3.2" sqflite_common: dependency: transitive description: name: sqflite_common - sha256: e77abf6ff961d69dfef41daccbb66b51e9983cdd5cb35bf30733598057401555 + sha256: "3da423ce7baf868be70e2c0976c28a1bb2f73644268b7ffa7d2e08eab71f16a4" url: "https://pub.dev" source: hosted - version: "2.4.5" + version: "2.5.4" stack_trace: dependency: transitive description: name: stack_trace - sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5 + sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b" url: "https://pub.dev" source: hosted - version: "1.11.0" + version: "1.11.1" stream_channel: dependency: transitive description: name: stream_channel - sha256: "83615bee9045c1d322bbbd1ba209b7a749c2cbcdcb3fdd1df8eb488b3279c1c8" + sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7 url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.1.2" string_scanner: dependency: transitive description: @@ -541,10 +677,10 @@ packages: dependency: transitive description: name: synchronized - sha256: "5fcbd27688af6082f5abd611af56ee575342c30e87541d0245f7ff99faa02c60" + sha256: "539ef412b170d65ecdafd780f924e5be3f60032a1128df156adad6c5b373d558" url: "https://pub.dev" source: hosted - version: "3.1.0" + version: "3.1.0+1" term_glyph: dependency: transitive description: @@ -557,10 +693,10 @@ packages: dependency: transitive description: name: test_api - sha256: eb6ac1540b26de412b3403a163d919ba86f6a973fe6cc50ae3541b80092fdcfb + sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b" url: "https://pub.dev" source: hosted - version: "0.5.1" + version: "0.6.1" typed_data: dependency: transitive description: @@ -573,98 +709,98 @@ packages: dependency: transitive description: name: url_launcher - sha256: eb1e00ab44303d50dd487aab67ebc575456c146c6af44422f9c13889984c00f3 + sha256: "0ecc004c62fd3ed36a2ffcbe0dd9700aee63bd7532d0b642a488b1ec310f492e" url: "https://pub.dev" source: hosted - version: "6.1.11" + version: "6.2.5" url_launcher_android: dependency: transitive description: name: url_launcher_android - sha256: eed4e6a1164aa9794409325c3b707ff424d4d1c2a785e7db67f8bbda00e36e51 + sha256: d4ed0711849dd8e33eb2dd69c25db0d0d3fdc37e0a62e629fe32f57a22db2745 url: "https://pub.dev" source: hosted - version: "6.0.35" + version: "6.3.0" url_launcher_ios: dependency: transitive description: name: url_launcher_ios - sha256: "9af7ea73259886b92199f9e42c116072f05ff9bea2dcb339ab935dfc957392c2" + sha256: "9149d493b075ed740901f3ee844a38a00b33116c7c5c10d7fb27df8987fb51d5" url: "https://pub.dev" source: hosted - version: "6.1.4" + version: "6.2.5" url_launcher_linux: dependency: transitive description: name: url_launcher_linux - sha256: "207f4ddda99b95b4d4868320a352d374b0b7e05eefad95a4a26f57da413443f5" + sha256: ab360eb661f8879369acac07b6bb3ff09d9471155357da8443fd5d3cf7363811 url: "https://pub.dev" source: hosted - version: "3.0.5" + version: "3.1.1" url_launcher_macos: dependency: transitive description: name: url_launcher_macos - sha256: "91ee3e75ea9dadf38036200c5d3743518f4a5eb77a8d13fda1ee5764373f185e" + sha256: b7244901ea3cf489c5335bdacda07264a6e960b1c1b1a9f91e4bc371d9e68234 url: "https://pub.dev" source: hosted - version: "3.0.5" + version: "3.1.0" url_launcher_platform_interface: dependency: transitive description: name: url_launcher_platform_interface - sha256: "6c9ca697a5ae218ce56cece69d46128169a58aa8653c1b01d26fcd4aad8c4370" + sha256: "552f8a1e663569be95a8190206a38187b531910283c3e982193e4f2733f01029" url: "https://pub.dev" source: hosted - version: "2.1.2" + version: "2.3.2" url_launcher_web: dependency: transitive description: name: url_launcher_web - sha256: "6bb1e5d7fe53daf02a8fee85352432a40b1f868a81880e99ec7440113d5cfcab" + sha256: "3692a459204a33e04bc94f5fb91158faf4f2c8903281ddd82915adecdb1a901d" url: "https://pub.dev" source: hosted - version: "2.0.17" + version: "2.3.0" url_launcher_windows: dependency: transitive description: name: url_launcher_windows - sha256: "254708f17f7c20a9c8c471f67d86d76d4a3f9c1591aad1e15292008aceb82771" + sha256: ecf9725510600aa2bb6d7ddabe16357691b6d2805f66216a97d1b881e21beff7 url: "https://pub.dev" source: hosted - version: "3.0.6" + version: "3.1.1" uuid: dependency: transitive description: name: uuid - sha256: "648e103079f7c64a36dc7d39369cabb358d377078a051d6ae2ad3aa539519313" + sha256: cd210a09f7c18cbe5a02511718e0334de6559871052c90a90c0cca46a4aa81c8 url: "https://pub.dev" source: hosted - version: "3.0.7" + version: "4.3.3" vector_graphics: dependency: transitive description: name: vector_graphics - sha256: ea8d3fc7b2e0f35de38a7465063ecfcf03d8217f7962aa2a6717132cb5d43a79 + sha256: "32c3c684e02f9bc0afb0ae0aa653337a2fe022e8ab064bcd7ffda27a74e288e3" url: "https://pub.dev" source: hosted - version: "1.1.5" + version: "1.1.11+1" vector_graphics_codec: dependency: transitive description: name: vector_graphics_codec - sha256: a5eaa5d19e123ad4f61c3718ca1ed921c4e6254238d9145f82aa214955d9aced + sha256: c86987475f162fadff579e7320c7ddda04cd2fdeffbe1129227a85d9ac9e03da url: "https://pub.dev" source: hosted - version: "1.1.5" + version: "1.1.11+1" vector_graphics_compiler: dependency: transitive description: name: vector_graphics_compiler - sha256: "15edc42f7eaa478ce854eaf1fbb9062a899c0e4e56e775dd73b7f4709c97c4ca" + sha256: "12faff3f73b1741a36ca7e31b292ddeb629af819ca9efe9953b70bd63fc8cd81" url: "https://pub.dev" source: hosted - version: "1.1.5" + version: "1.1.11+1" vector_math: dependency: transitive description: @@ -673,30 +809,46 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.4" + vm_service: + dependency: transitive + description: + name: vm_service + sha256: b3d56ff4341b8f182b96aceb2fa20e3dcb336b9f867bc0eafc0de10f1048e957 + url: "https://pub.dev" + source: hosted + version: "13.0.0" + web: + dependency: transitive + description: + name: web + sha256: "97da13628db363c635202ad97068d47c5b8aa555808e7a9411963c533b449b27" + url: "https://pub.dev" + source: hosted + version: "0.5.1" win32: dependency: transitive description: name: win32 - sha256: "5a751eddf9db89b3e5f9d50c20ab8612296e4e8db69009788d6c8b060a84191c" + sha256: "0a989dc7ca2bb51eac91e8fd00851297cfffd641aa7538b165c62637ca0eaa4a" url: "https://pub.dev" source: hosted - version: "4.1.4" + version: "5.4.0" xdg_directories: dependency: transitive description: name: xdg_directories - sha256: ee1505df1426458f7f60aac270645098d318a8b4766d85fde75f76f2e21807d1 + sha256: faea9dee56b520b55a566385b84f2e8de55e7496104adada9962e0bd11bcff1d url: "https://pub.dev" source: hosted - version: "1.0.0" + version: "1.0.4" xml: dependency: transitive description: name: xml - sha256: "979ee37d622dec6365e2efa4d906c37470995871fe9ae080d967e192d88286b5" + sha256: b015a8ad1c488f66851d762d3090a21c600e479dc75e68328c52774040cf9226 url: "https://pub.dev" source: hosted - version: "6.2.2" + version: "6.5.0" sdks: - dart: ">=3.0.0 <4.0.0" - flutter: ">=3.7.0-0" + dart: ">=3.3.0 <4.0.0" + flutter: ">=3.19.0" diff --git a/sample/pubspec.yaml b/sample/pubspec.yaml index 47a82d4..d2794ac 100644 --- a/sample/pubspec.yaml +++ b/sample/pubspec.yaml @@ -20,7 +20,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev version: 1.0.0+1 environment: - sdk: '>=2.19.6 <3.0.0' + sdk: '>=3.3.0 <4.0.0' # Dependencies specify other packages that your package needs in order to work. # To automatically upgrade your package dependencies to the latest versions @@ -50,7 +50,7 @@ dev_dependencies: # activated in the `analysis_options.yaml` file located at the root of your # package. See that file for information about deactivating specific lint # rules and activating additional ones. - flutter_lints: ^2.0.0 + flutter_lints: ^3.0.1 # For information on the generic Dart part of this file, see the # following page: https://dart.dev/tools/pub/pubspec diff --git a/sample/web/favicon.png b/sample/web/favicon.png new file mode 100644 index 0000000..8aaa46a Binary files /dev/null and b/sample/web/favicon.png differ diff --git a/sample/web/icons/Icon-192.png b/sample/web/icons/Icon-192.png new file mode 100644 index 0000000..b749bfe Binary files /dev/null and b/sample/web/icons/Icon-192.png differ diff --git a/sample/web/icons/Icon-512.png b/sample/web/icons/Icon-512.png new file mode 100644 index 0000000..88cfd48 Binary files /dev/null and b/sample/web/icons/Icon-512.png differ diff --git a/sample/web/icons/Icon-maskable-192.png b/sample/web/icons/Icon-maskable-192.png new file mode 100644 index 0000000..eb9b4d7 Binary files /dev/null and b/sample/web/icons/Icon-maskable-192.png differ diff --git a/sample/web/icons/Icon-maskable-512.png b/sample/web/icons/Icon-maskable-512.png new file mode 100644 index 0000000..d69c566 Binary files /dev/null and b/sample/web/icons/Icon-maskable-512.png differ diff --git a/sample/web/index.html b/sample/web/index.html new file mode 100644 index 0000000..90cdc55 --- /dev/null +++ b/sample/web/index.html @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + sample + + + + + + + + + + diff --git a/sample/web/manifest.json b/sample/web/manifest.json new file mode 100644 index 0000000..84e0c27 --- /dev/null +++ b/sample/web/manifest.json @@ -0,0 +1,35 @@ +{ + "name": "sample", + "short_name": "sample", + "start_url": ".", + "display": "standalone", + "background_color": "#0175C2", + "theme_color": "#0175C2", + "description": "A new Flutter project.", + "orientation": "portrait-primary", + "prefer_related_applications": false, + "icons": [ + { + "src": "icons/Icon-192.png", + "sizes": "192x192", + "type": "image/png" + }, + { + "src": "icons/Icon-512.png", + "sizes": "512x512", + "type": "image/png" + }, + { + "src": "icons/Icon-maskable-192.png", + "sizes": "192x192", + "type": "image/png", + "purpose": "maskable" + }, + { + "src": "icons/Icon-maskable-512.png", + "sizes": "512x512", + "type": "image/png", + "purpose": "maskable" + } + ] +} diff --git a/sample/windows/flutter/generated_plugin_registrant.cc b/sample/windows/flutter/generated_plugin_registrant.cc index 4f78848..043a96f 100644 --- a/sample/windows/flutter/generated_plugin_registrant.cc +++ b/sample/windows/flutter/generated_plugin_registrant.cc @@ -6,9 +6,12 @@ #include "generated_plugin_registrant.h" +#include #include void RegisterPlugins(flutter::PluginRegistry* registry) { + FileSelectorWindowsRegisterWithRegistrar( + registry->GetRegistrarForPlugin("FileSelectorWindows")); UrlLauncherWindowsRegisterWithRegistrar( registry->GetRegistrarForPlugin("UrlLauncherWindows")); } diff --git a/sample/windows/flutter/generated_plugins.cmake b/sample/windows/flutter/generated_plugins.cmake index 88b22e5..a95e267 100644 --- a/sample/windows/flutter/generated_plugins.cmake +++ b/sample/windows/flutter/generated_plugins.cmake @@ -3,6 +3,7 @@ # list(APPEND FLUTTER_PLUGIN_LIST + file_selector_windows url_launcher_windows )