diff --git a/coverage/lcov.info b/coverage/lcov.info index d124677af..c2dc2f871 100644 --- a/coverage/lcov.info +++ b/coverage/lcov.info @@ -1,123 +1,110 @@ SF:lib/src/helpers/compare_mixin.dart -DA:8,4 -DA:9,16 -DA:16,29 -DA:22,29 -DA:23,58 -DA:26,49 -DA:27,29 -DA:28,29 -DA:31,45 -DA:32,16 -DA:35,56 -DA:36,12 -DA:39,75 -DA:43,25 -DA:53,29 -DA:54,29 -DA:60,4 -DA:62,4 -DA:63,2 -DA:64,10 -DA:65,4 -DA:66,8 -DA:72,4 -DA:73,0 -DA:76,4 -DA:77,4 -DA:78,4 -DA:81,4 -DA:85,12 -DA:86,16 -DA:88,8 -DA:92,4 -DA:93,16 -DA:94,8 -DA:96,16 -DA:102,3 -DA:103,9 -DA:105,5 -DA:107,10 -DA:108,1 -DA:110,2 -DA:114,3 -DA:116,3 -DA:127,4 -DA:130,53 -DA:133,49 -DA:134,147 -DA:135,144 -DA:139,9 -DA:140,45 -DA:143,0 -DA:144,0 +DA:10,3 +DA:11,12 +DA:18,32 +DA:24,32 +DA:25,64 +DA:28,54 +DA:29,32 +DA:30,32 +DA:33,46 +DA:34,14 +DA:37,64 +DA:38,12 +DA:41,84 +DA:45,28 +DA:55,32 +DA:56,32 +DA:62,3 +DA:64,3 +DA:65,2 +DA:66,10 +DA:67,4 +DA:68,8 +DA:74,3 +DA:75,0 +DA:78,3 +DA:79,4 +DA:80,4 +DA:83,4 +DA:87,9 +DA:88,12 +DA:90,6 +DA:94,3 +DA:95,12 +DA:96,6 +DA:98,12 +DA:104,2 +DA:105,6 +DA:107,3 +DA:109,5 +DA:110,1 +DA:112,1 +DA:116,2 +DA:118,2 +DA:129,3 +DA:132,58 +DA:135,51 +DA:136,153 +DA:137,150 +DA:141,8 +DA:142,40 +DA:145,0 DA:147,0 -DA:149,0 DA:150,0 -DA:151,0 +DA:152,0 DA:153,0 DA:154,0 -DA:155,0 +DA:156,0 DA:157,0 DA:158,0 -DA:159,0 +DA:160,0 DA:161,0 DA:162,0 -DA:163,0 DA:164,0 -DA:168,0 -DA:175,4 -DA:177,16 +DA:165,0 +DA:166,0 +DA:167,0 +DA:171,0 +DA:178,3 +DA:180,12 LF:69 LH:51 end_of_record -SF:lib/src/helpers/string_ext.dart -DA:25,36 -DA:27,24 -DA:28,12 -DA:29,12 -DA:30,12 -DA:36,12 -DA:37,12 -DA:38,12 -DA:39,24 -DA:41,36 -DA:42,12 -DA:43,60 -DA:45,24 -DA:49,12 -DA:52,24 -DA:53,24 -DA:56,24 -DA:57,12 -DA:65,6 -DA:68,6 -DA:71,3 -DA:72,15 -DA:73,3 -DA:74,9 -DA:77,3 -DA:81,18 -DA:84,4 -DA:85,4 -DA:86,8 -DA:87,8 -DA:89,12 -DA:90,20 -DA:94,8 -DA:97,8 -DA:100,44 -DA:103,3 -DA:104,15 -DA:107,1 -DA:108,2 -DA:109,1 -DA:111,3 -DA:113,1 -DA:120,55 -DA:123,10 -LF:44 -LH:44 +SF:lib/src/widgets/gap_widget.dart +DA:9,1 +DA:13,1 +DA:15,2 +DA:18,0 +DA:20,0 +DA:27,1 +DA:30,1 +DA:31,1 +DA:33,1 +DA:34,1 +DA:38,0 +DA:39,0 +DA:40,0 +DA:41,0 +DA:42,0 +DA:45,1 +DA:47,1 +DA:48,1 +DA:52,2 +DA:53,0 +DA:54,1 +DA:55,2 +DA:56,0 +DA:57,1 +DA:58,1 +DA:59,3 +DA:60,3 +DA:63,1 +DA:68,0 +DA:70,0 +DA:71,0 +LF:31 +LH:19 end_of_record SF:lib/src/attributes/border/border_attribute.dart DA:10,3 @@ -137,7 +124,7 @@ LF:13 LH:11 end_of_record SF:lib/src/attributes/border/border_dto.dart -DA:21,9 +DA:21,10 DA:30,6 DA:31,6 DA:32,6 @@ -155,41 +142,41 @@ DA:49,0 DA:56,3 DA:57,3 DA:60,21 -DA:62,11 -DA:64,15 -DA:66,3 -DA:67,6 +DA:62,9 +DA:64,17 +DA:66,2 +DA:67,4 DA:70,0 DA:77,3 -DA:80,3 -DA:81,3 -DA:82,3 -DA:83,3 -DA:84,3 -DA:85,3 -DA:86,3 -DA:87,3 +DA:80,2 +DA:81,2 +DA:82,2 +DA:83,2 +DA:84,2 +DA:85,2 +DA:86,2 +DA:87,2 DA:91,0 DA:92,0 DA:93,0 DA:94,0 DA:95,0 DA:96,0 -DA:103,6 -DA:105,6 +DA:103,7 +DA:105,7 DA:106,3 DA:107,6 DA:108,6 DA:109,6 DA:110,6 -DA:114,6 -DA:115,12 -DA:116,12 -DA:117,12 -DA:118,12 -DA:122,3 -DA:123,21 -DA:133,10 +DA:114,7 +DA:115,14 +DA:116,14 +DA:117,14 +DA:118,14 +DA:122,2 +DA:123,14 +DA:133,11 DA:140,7 DA:141,7 DA:142,14 @@ -208,136 +195,105 @@ DA:168,3 DA:169,2 DA:170,1 DA:171,1 -DA:175,7 -DA:179,7 -DA:180,15 -DA:181,7 -DA:182,9 -DA:183,10 +DA:175,8 +DA:179,8 +DA:180,17 +DA:181,8 +DA:182,10 +DA:183,12 DA:187,3 DA:188,15 LF:79 LH:69 end_of_record SF:lib/src/attributes/border/border_radius_attribute.dart -DA:12,3 -DA:14,0 -DA:17,0 -DA:18,0 -DA:22,0 -DA:25,0 -DA:28,2 -DA:29,4 -DA:31,2 -DA:32,4 -DA:34,2 -DA:35,4 -DA:37,2 -DA:38,4 -DA:40,2 -DA:41,4 -DA:43,2 -DA:44,4 +DA:12,2 +DA:14,1 +DA:15,2 +DA:17,1 +DA:18,2 +DA:20,1 +DA:21,2 +DA:23,1 +DA:24,2 +DA:26,1 +DA:27,2 +DA:29,1 +DA:30,2 +DA:32,1 +DA:33,2 +DA:35,1 +DA:36,2 +DA:38,0 +DA:42,0 +DA:45,1 DA:46,2 -DA:47,4 +DA:48,1 DA:49,2 -DA:50,4 -DA:52,1 -DA:56,4 -DA:59,2 -DA:60,4 -DA:62,2 -DA:63,4 -DA:67,1 -DA:69,1 -DA:70,1 -DA:71,1 -DA:80,1 -DA:86,1 -DA:87,1 -DA:96,1 -DA:97,1 -DA:105,1 -DA:106,1 -DA:114,1 -DA:115,2 -DA:120,1 -DA:122,1 -DA:123,1 -DA:124,1 -DA:133,1 -DA:139,1 -DA:140,1 -DA:149,1 -DA:153,1 -DA:161,1 -DA:165,1 -DA:173,1 -DA:174,2 -LF:54 -LH:49 +LF:23 +LH:21 end_of_record SF:lib/src/attributes/border/border_radius_dto.dart -DA:20,6 -DA:31,4 -DA:32,4 -DA:33,4 -DA:34,4 -DA:35,4 -DA:36,4 -DA:37,4 -DA:41,0 -DA:42,0 -DA:43,0 -DA:44,0 -DA:45,0 -DA:46,0 -DA:50,0 -DA:57,3 -DA:58,3 -DA:61,4 -DA:62,4 -DA:63,4 -DA:64,4 -DA:65,4 -DA:67,2 -DA:71,2 -DA:72,3 -DA:73,3 -DA:74,3 -DA:75,3 -DA:76,4 -DA:77,4 -DA:78,4 -DA:79,4 -DA:83,4 -DA:87,4 -DA:88,1 -DA:89,1 -DA:90,1 -DA:91,1 -DA:92,1 -DA:94,4 -DA:95,4 -DA:96,4 -DA:97,4 -DA:98,4 -DA:102,4 -DA:103,4 -DA:104,4 -DA:105,4 -DA:106,4 -DA:107,4 -DA:108,4 -DA:109,4 -DA:110,4 -DA:111,4 +DA:31,8 +DA:42,4 +DA:43,4 +DA:44,4 +DA:45,4 +DA:46,4 +DA:47,4 +DA:48,4 +DA:52,0 +DA:53,0 +DA:54,0 +DA:55,0 +DA:56,0 +DA:57,0 +DA:61,0 +DA:68,3 +DA:69,3 +DA:72,5 +DA:73,5 +DA:74,5 +DA:75,5 +DA:76,5 +DA:78,2 +DA:82,1 +DA:83,2 +DA:84,2 +DA:85,2 +DA:86,2 +DA:87,2 +DA:88,2 +DA:89,2 +DA:90,2 +DA:94,5 +DA:98,5 +DA:99,1 +DA:100,1 +DA:101,1 +DA:102,1 +DA:103,1 +DA:105,5 +DA:106,5 +DA:107,5 +DA:108,5 +DA:109,5 +DA:113,3 +DA:114,3 +DA:115,3 +DA:116,3 +DA:117,3 +DA:118,3 +DA:119,3 +DA:120,3 +DA:121,3 +DA:122,3 LF:54 LH:47 end_of_record SF:lib/src/attributes/border/border_radius_util.dart -DA:32,66 -DA:33,1 +DA:32,3 +DA:33,2 DA:47,1 DA:48,2 DA:62,1 @@ -363,15 +319,15 @@ DA:193,1 DA:194,1 DA:195,2 DA:200,3 -DA:203,2 -DA:209,4 -DA:210,2 -DA:241,2 -DA:266,2 -DA:267,2 -DA:268,2 -DA:269,2 -DA:270,2 +DA:203,3 +DA:209,6 +DA:210,3 +DA:241,3 +DA:266,3 +DA:267,3 +DA:268,3 +DA:269,3 +DA:270,3 DA:277,1 DA:278,1 DA:291,1 @@ -399,13 +355,13 @@ LF:59 LH:52 end_of_record SF:lib/src/attributes/border/border_util.dart -DA:37,67 +DA:37,5 DA:39,1 DA:43,1 -DA:51,2 -DA:52,2 -DA:76,2 -DA:77,10 +DA:51,3 +DA:52,3 +DA:76,3 +DA:77,15 DA:102,1 DA:103,3 DA:128,1 @@ -429,7 +385,7 @@ DA:293,2 DA:294,1 DA:321,0 DA:327,0 -DA:359,2 +DA:359,3 DA:361,1 DA:367,3 DA:392,4 @@ -437,340 +393,252 @@ DA:409,1 DA:410,3 DA:424,2 DA:438,2 -DA:457,2 -DA:463,2 -DA:464,2 -DA:470,4 +DA:457,3 +DA:463,3 +DA:464,3 +DA:470,6 LF:42 LH:35 end_of_record SF:lib/src/attributes/color/color_dto.dart -DA:10,24 -DA:12,5 -DA:13,5 -DA:15,20 -DA:17,20 -DA:19,20 -DA:22,3 -DA:24,4 -DA:27,8 -DA:28,16 +DA:10,34 +DA:12,6 +DA:13,6 +DA:15,22 +DA:17,22 +DA:19,22 +DA:22,6 +DA:24,10 +DA:27,11 +DA:28,22 LF:10 LH:10 end_of_record -SF:lib/src/attributes/constraints/constraints_attribute.dart -DA:11,5 -DA:18,5 +SF:lib/src/attributes/color/color_util.dart +DA:14,12 +DA:16,0 +DA:18,0 +DA:19,0 DA:20,0 DA:21,0 +DA:22,0 DA:23,0 DA:24,0 -DA:27,1 -DA:31,4 -DA:34,1 -DA:36,2 +DA:25,0 +DA:26,0 +DA:27,0 +DA:28,0 +DA:29,0 +DA:30,0 +DA:31,0 +DA:32,0 +DA:33,0 +DA:34,0 +DA:35,0 +DA:36,0 +DA:37,0 +DA:38,0 +DA:39,0 +DA:40,0 +DA:41,0 DA:42,0 +DA:43,0 DA:44,0 DA:45,0 +DA:46,0 +DA:47,0 +DA:48,0 +DA:49,0 +DA:50,0 DA:51,0 +DA:52,0 DA:53,0 DA:54,0 -LF:16 -LH:6 -end_of_record -SF:lib/src/attributes/constraints/constraints_util.dart -DA:29,65 -DA:30,0 -DA:43,2 -DA:57,2 -DA:71,2 -DA:85,2 -DA:87,1 -DA:93,2 -DA:94,1 -LF:9 -LH:8 -end_of_record -SF:lib/src/attributes/decoration/decoration_attribute.dart -DA:12,4 -DA:14,1 -DA:18,5 -DA:20,4 -DA:23,1 -DA:25,2 -LF:6 -LH:6 -end_of_record -SF:lib/src/attributes/decoration/decoration_util.dart -DA:20,64 -DA:21,0 -DA:23,0 -DA:24,0 -DA:25,0 -DA:29,0 -DA:30,0 -DA:31,0 -DA:38,3 -DA:39,2 -DA:41,3 -DA:49,6 -DA:50,3 +DA:55,0 +DA:56,0 +DA:57,0 +DA:58,0 +DA:59,0 +DA:60,0 DA:61,0 DA:62,0 -DA:65,1 -DA:66,3 -DA:69,1 -DA:70,1 -DA:71,2 -DA:75,1 -DA:76,3 -DA:79,1 -DA:80,2 -DA:81,1 -DA:85,1 -DA:86,2 -DA:87,1 -DA:91,1 -DA:92,2 -DA:93,1 -DA:97,3 -DA:105,3 -DA:106,2 -DA:107,3 -DA:108,2 -DA:109,1 -DA:110,1 -DA:118,0 +DA:63,0 +DA:64,0 +DA:65,0 +DA:66,0 +DA:67,0 +DA:68,0 +DA:69,0 +DA:70,0 +DA:71,0 +DA:72,0 +DA:73,0 +DA:74,0 +DA:75,0 +DA:76,0 +DA:77,0 +DA:78,0 +DA:79,0 +DA:80,0 +DA:81,0 +DA:82,0 +DA:83,0 +DA:84,0 +DA:85,0 +DA:86,0 +DA:88,0 +DA:90,0 +DA:91,0 +DA:92,0 +DA:93,0 +DA:94,0 +DA:95,0 +DA:96,0 +DA:97,0 +DA:98,0 +DA:99,0 +DA:100,0 +DA:101,0 +DA:102,0 +DA:103,0 +DA:104,0 +DA:105,0 +DA:106,0 +DA:112,0 +DA:113,0 DA:119,0 DA:121,0 +DA:122,0 +DA:123,0 +DA:124,0 +DA:125,0 +DA:126,0 DA:127,0 DA:128,0 -DA:137,0 +DA:129,0 +DA:130,0 +DA:132,0 DA:138,0 +DA:140,0 DA:141,0 DA:142,0 +DA:143,0 DA:145,0 -DA:146,0 -DA:147,0 -DA:151,0 -DA:152,0 -DA:155,0 -DA:161,0 -DA:162,0 -DA:163,0 -DA:164,0 -LF:57 -LH:29 -end_of_record -SF:lib/src/attributes/gradient/gradient_attribute.dart -DA:17,1 -DA:22,0 -DA:23,0 -DA:32,0 -DA:36,0 -DA:37,0 -DA:41,1 -DA:46,2 -DA:48,1 -DA:51,2 -LF:10 -LH:5 -end_of_record -SF:lib/src/attributes/gradient/gradient_util.dart -DA:48,65 -DA:51,1 -DA:52,2 -DA:56,2 -DA:57,4 -DA:61,1 -DA:62,2 -DA:68,2 -DA:69,2 -DA:70,2 -DA:71,2 -DA:72,4 -DA:73,1 -DA:74,2 -DA:76,0 -DA:77,0 -DA:107,65 -DA:123,1 -DA:124,3 -DA:141,1 -DA:142,3 -DA:159,1 -DA:160,3 -DA:177,0 -DA:178,0 -DA:192,0 -DA:205,0 -DA:218,0 -DA:231,0 -DA:245,1 -DA:246,3 -DA:260,1 -DA:270,1 -DA:277,4 -DA:281,2 -DA:309,66 -DA:327,1 -DA:328,2 -DA:329,3 -DA:349,1 -DA:350,2 -DA:351,3 -DA:371,1 -DA:372,1 -DA:373,4 -DA:392,0 -DA:393,0 -DA:394,0 -DA:413,0 -DA:430,0 -DA:449,2 -DA:450,6 -DA:468,1 -DA:476,1 -DA:481,2 -DA:485,2 -DA:514,65 -DA:530,1 -DA:531,2 -DA:532,3 -DA:550,1 -DA:551,2 -DA:552,3 -DA:570,0 -DA:571,0 -DA:572,0 -DA:587,0 -DA:600,0 -DA:613,0 -DA:626,0 -DA:640,1 -DA:641,3 -DA:655,1 -DA:664,1 -DA:670,2 -DA:674,2 -LF:76 -LH:56 +LF:109 +LH:1 end_of_record SF:lib/src/attributes/scalars/scalar_util.dart -DA:11,465 -DA:13,4 -DA:15,14 -DA:16,14 -DA:24,76 -DA:26,10 -DA:31,6 -DA:36,10 -DA:41,135 -DA:43,0 -DA:45,6 -DA:50,66 -DA:52,0 +DA:11,544 +DA:13,5 +DA:15,18 +DA:16,18 +DA:24,18 +DA:27,10 +DA:32,15 +DA:37,30 +DA:42,87 +DA:44,0 +DA:46,12 +DA:51,6 DA:53,3 -DA:54,0 +DA:54,6 DA:55,3 DA:56,6 -DA:57,3 -DA:58,0 -DA:59,0 -DA:60,0 -DA:61,0 -DA:63,0 -DA:64,0 -DA:79,1 -DA:93,1 -DA:109,0 -DA:111,0 -DA:127,65 -DA:129,0 -DA:130,0 -DA:150,1 -DA:151,3 -DA:152,3 -DA:157,1 -DA:158,0 -DA:159,0 -DA:175,66 -DA:176,3 -DA:177,3 -DA:178,6 +DA:57,12 +DA:58,6 +DA:59,3 +DA:60,3 +DA:61,3 +DA:62,1 +DA:63,1 +DA:67,3 +DA:68,3 +DA:83,4 +DA:97,1 +DA:113,0 +DA:115,0 +DA:131,75 +DA:133,0 +DA:134,0 +DA:154,2 +DA:155,3 +DA:156,6 +DA:161,2 +DA:162,3 +DA:163,3 DA:179,6 -DA:195,1 -DA:196,3 -DA:197,3 -DA:202,0 -DA:220,0 -DA:222,0 -DA:223,0 -DA:226,0 -DA:227,0 -DA:228,0 -DA:243,1 -DA:244,3 -DA:245,3 -DA:261,2 -DA:262,3 -DA:263,6 -DA:264,3 -DA:280,1 -DA:281,0 -DA:282,3 -DA:298,1 -DA:299,3 -DA:300,0 -DA:301,0 -DA:302,0 -DA:318,0 -DA:320,0 -DA:339,0 -DA:341,0 -DA:342,0 -DA:343,0 -DA:344,0 -DA:345,0 -DA:346,0 -DA:362,1 -DA:363,3 -DA:364,3 -DA:365,3 +DA:180,3 +DA:181,3 +DA:182,9 +DA:183,9 +DA:199,1 +DA:200,3 +DA:201,3 +DA:206,0 +DA:224,2 +DA:226,3 +DA:227,2 +DA:230,6 +DA:231,3 +DA:232,3 +DA:247,2 +DA:248,6 +DA:249,6 +DA:265,2 +DA:266,3 +DA:267,6 +DA:268,3 +DA:284,3 +DA:285,3 +DA:286,9 +DA:302,2 +DA:303,6 +DA:304,3 +DA:305,3 +DA:306,0 +DA:322,1 +DA:324,4 +DA:343,2 +DA:345,4 +DA:346,4 +DA:347,4 +DA:348,4 +DA:349,1 +DA:350,3 +DA:366,2 DA:367,3 DA:368,3 DA:369,3 -DA:385,1 -DA:386,3 -DA:387,3 -DA:388,3 -DA:389,3 +DA:371,3 +DA:372,3 +DA:373,3 +DA:389,2 DA:390,3 -DA:406,1 -DA:407,3 -DA:408,3 -DA:420,1 -DA:438,1 -DA:439,3 -DA:440,3 -DA:441,3 -DA:442,3 -DA:455,0 -DA:457,0 -DA:461,1 -DA:480,1 -DA:481,3 -DA:482,3 -DA:483,3 -DA:484,3 +DA:391,3 +DA:392,3 +DA:393,3 +DA:394,3 +DA:410,2 +DA:411,3 +DA:412,6 +DA:424,1 +DA:442,1 +DA:443,3 +DA:444,3 +DA:445,3 +DA:446,3 +DA:459,1 +DA:461,4 +DA:465,1 +DA:484,1 DA:485,3 DA:486,3 DA:487,3 -DA:502,1 -DA:504,3 -DA:505,3 -DA:506,3 -DA:507,3 +DA:488,3 +DA:489,3 +DA:490,3 +DA:491,3 +DA:506,1 DA:508,3 DA:509,3 DA:510,3 @@ -780,10 +648,10 @@ DA:513,3 DA:514,3 DA:515,3 DA:516,3 -DA:517,0 -DA:518,0 -DA:519,0 -DA:520,0 +DA:517,3 +DA:518,3 +DA:519,3 +DA:520,3 DA:521,0 DA:522,0 DA:523,0 @@ -796,263 +664,660 @@ DA:529,0 DA:530,0 DA:531,0 DA:532,0 -DA:550,2 -DA:551,6 -DA:552,3 -DA:570,2 -DA:571,3 -DA:572,0 -DA:592,1 -DA:594,3 -DA:595,0 -DA:596,0 -DA:597,0 -DA:615,2 -DA:617,3 -DA:618,0 -DA:636,1 -DA:638,3 -DA:640,0 -DA:642,4 -DA:663,1 -DA:665,0 -DA:666,0 -DA:667,0 -DA:668,3 -DA:669,0 -DA:687,2 -DA:689,3 -DA:690,6 -DA:709,1 -DA:710,3 -DA:711,3 -DA:712,3 -DA:730,1 -DA:731,3 -DA:732,3 -DA:754,1 -DA:755,3 -DA:756,3 -DA:757,3 -DA:758,3 -DA:759,3 -DA:760,3 -LF:180 -LH:117 +DA:533,0 +DA:534,0 +DA:535,0 +DA:536,0 +DA:554,2 +DA:555,6 +DA:556,3 +DA:575,3 +DA:576,6 +DA:577,3 +DA:578,3 +DA:579,3 +DA:580,3 +DA:581,3 +DA:582,3 +DA:583,3 +DA:584,3 +DA:585,3 +DA:586,3 +DA:606,2 +DA:608,6 +DA:609,3 +DA:610,3 +DA:611,3 +DA:629,3 +DA:631,6 +DA:632,3 +DA:650,2 +DA:652,3 +DA:654,4 +DA:656,8 +DA:677,2 +DA:679,3 +DA:680,3 +DA:681,3 +DA:682,6 +DA:683,3 +DA:701,3 +DA:703,6 +DA:704,6 +DA:723,1 +DA:724,3 +DA:725,3 +DA:726,3 +DA:744,1 +DA:745,3 +DA:746,3 +DA:768,1 +DA:769,3 +DA:770,3 +DA:771,3 +DA:772,3 +DA:773,3 +DA:774,3 +LF:190 +LH:167 end_of_record -SF:lib/src/attributes/scalars/scalars_attribute.dart -DA:12,16 -DA:14,7 -DA:17,2 -DA:18,4 -DA:23,2 -DA:25,1 -DA:26,0 -DA:32,3 -DA:34,1 -DA:35,0 -DA:37,1 -DA:39,2 -DA:47,5 -DA:49,1 -DA:50,0 -DA:52,1 -DA:54,2 -DA:61,3 -DA:63,1 -DA:64,0 -DA:70,2 -DA:72,1 -DA:73,0 -DA:75,0 -DA:79,0 -DA:82,1 -DA:84,2 -LF:27 -LH:20 +SF:lib/src/attributes/constraints/constraints_dto.dart +DA:8,10 +DA:26,10 +DA:34,3 +DA:35,3 +DA:36,3 +DA:37,3 +DA:38,3 +DA:39,3 +DA:46,0 +DA:47,0 +DA:51,3 +DA:53,3 +DA:54,3 +DA:55,3 +DA:56,3 +DA:57,3 +DA:62,3 +DA:66,3 +DA:67,5 +DA:68,6 +DA:69,5 +DA:70,4 +DA:74,5 +DA:75,25 +LF:24 +LH:22 end_of_record -SF:lib/src/attributes/shadow/shadow_dto.dart -DA:14,7 -DA:25,3 -DA:27,1 -DA:28,1 +SF:lib/src/attributes/constraints/constraints_util.dart +DA:28,2 DA:29,1 -DA:30,2 -DA:31,1 -DA:35,0 -DA:36,0 -DA:39,2 -DA:43,2 -DA:44,4 -DA:45,2 -DA:46,2 -DA:50,1 -DA:54,1 -DA:55,1 -DA:56,1 -DA:57,1 -DA:61,0 -DA:62,0 -DA:68,6 -DA:75,4 -DA:76,4 -DA:77,8 -DA:78,4 -DA:79,4 -DA:80,4 -DA:84,0 -DA:85,0 -DA:88,4 -DA:92,4 -DA:93,8 -DA:94,4 -DA:95,4 -DA:96,4 +DA:43,1 +DA:44,3 +DA:58,1 +DA:59,3 +DA:74,1 +DA:75,3 +DA:90,1 +DA:91,3 +DA:94,1 DA:100,2 -DA:104,2 -DA:105,2 -DA:106,2 -DA:107,2 -DA:108,2 -DA:112,4 -DA:113,20 -LF:44 -LH:38 +DA:101,1 +LF:13 +LH:13 end_of_record -SF:lib/src/attributes/shadow/shadow_util.dart -DA:32,1 -DA:35,1 -DA:36,1 -DA:42,2 -DA:59,0 -DA:60,0 +SF:lib/src/attributes/decoration/decoration_dto.dart +DA:17,13 +DA:19,0 +DA:22,0 +DA:23,0 +DA:25,0 +DA:26,0 +DA:29,0 +DA:30,0 +DA:52,13 +DA:62,3 +DA:63,3 +DA:64,6 +DA:65,6 +DA:66,6 +DA:67,6 +DA:68,9 +DA:69,3 +DA:76,0 DA:77,0 -DA:78,0 -DA:94,0 -DA:97,1 -DA:98,1 -DA:99,1 -DA:111,1 -DA:125,1 -DA:126,4 +DA:81,7 +DA:83,7 +DA:84,13 +DA:85,10 +DA:86,9 +DA:87,7 +DA:88,8 +DA:89,7 +DA:94,4 +DA:98,4 +DA:99,11 +DA:100,9 +DA:102,10 +DA:103,8 +DA:104,8 +DA:108,5 +DA:110,35 +DA:120,4 +DA:127,1 +DA:128,1 +DA:129,2 +DA:130,1 +DA:131,2 +DA:132,3 DA:136,0 -DA:148,0 -DA:149,0 -DA:162,0 -DA:163,0 -DA:176,0 -DA:188,0 -DA:191,0 -DA:197,0 -DA:204,0 -DA:214,1 -DA:226,1 -DA:227,2 -DA:229,4 -DA:233,0 -DA:234,0 -DA:235,0 -DA:236,0 -DA:237,0 -DA:238,0 -DA:239,0 -DA:240,0 -DA:241,0 -DA:242,0 -DA:243,0 -LF:40 -LH:14 +DA:137,0 +DA:140,1 +DA:142,1 +DA:143,1 +DA:144,2 +DA:145,5 +DA:146,1 +DA:150,1 +DA:154,1 +DA:155,2 +DA:156,2 +DA:157,1 +DA:158,2 +DA:162,2 +DA:163,10 +LF:59 +LH:48 end_of_record -SF:lib/src/attributes/spacing/edge_insets_dto.dart -DA:18,8 -DA:27,12 -DA:32,3 -DA:33,21 +SF:lib/src/attributes/decoration/decoration_util.dart +DA:20,6 +DA:21,5 +DA:23,6 +DA:24,11 +DA:25,10 +DA:29,1 +DA:30,1 +DA:31,0 +DA:38,7 +DA:39,6 +DA:41,6 +DA:49,12 +DA:50,6 +DA:61,4 +DA:62,12 +DA:65,2 +DA:66,6 +DA:69,2 +DA:70,2 +DA:71,4 +DA:75,1 +DA:76,3 +DA:79,1 +DA:80,2 +DA:81,1 +DA:85,1 +DA:86,2 +DA:87,1 +DA:91,1 +DA:92,2 +DA:93,1 +DA:97,1 +DA:98,2 +DA:99,2 +DA:103,3 +DA:111,3 +DA:112,2 +DA:113,3 +DA:114,2 +DA:115,1 +DA:116,1 +DA:124,2 +DA:125,1 +DA:127,1 +DA:133,2 +DA:134,1 +DA:143,1 +DA:144,3 +DA:147,1 +DA:148,3 +DA:151,1 +DA:152,1 +DA:153,2 +DA:157,1 +DA:158,3 +DA:161,1 +DA:167,1 +DA:168,1 +DA:169,1 +DA:170,4 +LF:60 +LH:59 +end_of_record +SF:lib/src/attributes/gradient/gradient_attribute.dart +DA:17,1 +DA:22,0 +DA:23,0 +DA:32,0 +DA:36,0 +DA:37,0 +DA:41,1 +DA:46,2 +DA:48,1 +DA:51,2 +LF:10 +LH:5 +end_of_record +SF:lib/src/attributes/gradient/gradient_dto.dart +DA:27,7 +DA:31,4 +DA:32,4 +DA:33,4 +DA:35,2 +DA:36,2 +DA:38,1 +DA:39,1 +DA:42,0 +DA:48,3 +DA:49,3 +DA:60,0 +DA:61,0 +DA:81,7 +DA:91,5 +DA:92,5 +DA:93,5 +DA:94,5 +DA:95,5 +DA:96,5 +DA:97,15 +DA:98,5 +DA:105,0 +DA:106,0 +DA:110,3 +DA:112,3 +DA:113,3 +DA:114,3 +DA:115,16 +DA:116,9 +DA:117,3 +DA:118,3 +DA:123,1 +DA:127,1 +DA:128,1 +DA:129,1 +DA:130,2 +DA:131,2 +DA:132,3 +DA:133,3 +DA:137,4 +DA:138,28 +DA:183,4 +DA:195,3 +DA:196,3 +DA:197,3 +DA:198,3 +DA:199,3 +DA:200,3 +DA:201,3 +DA:202,3 +DA:203,9 +DA:204,3 +DA:211,0 +DA:212,0 +DA:216,2 +DA:218,2 +DA:219,2 +DA:220,2 +DA:221,11 +DA:222,8 +DA:223,2 +DA:224,2 +DA:225,2 +DA:226,2 +DA:231,1 +DA:235,1 +DA:236,1 +DA:237,1 +DA:238,2 +DA:239,2 +DA:240,2 +DA:241,2 +DA:242,3 +DA:243,3 +DA:247,3 +DA:249,27 +DA:271,3 +DA:282,2 +DA:283,2 +DA:284,2 +DA:285,2 +DA:286,2 +DA:287,2 +DA:288,2 +DA:289,6 +DA:290,2 +DA:297,0 +DA:298,0 +DA:302,2 +DA:304,2 +DA:305,2 +DA:306,2 +DA:307,2 +DA:308,11 +DA:309,8 +DA:310,2 +DA:311,2 +DA:316,1 +DA:320,1 +DA:321,1 +DA:322,1 +DA:323,1 +DA:324,2 +DA:325,2 +DA:326,3 +DA:327,3 +DA:331,2 +DA:333,16 +LF:109 +LH:100 +end_of_record +SF:lib/src/attributes/gradient/gradient_util.dart +DA:48,75 +DA:51,1 +DA:52,2 +DA:56,2 +DA:57,4 +DA:61,1 +DA:62,2 +DA:68,2 +DA:69,2 +DA:70,2 +DA:71,2 +DA:72,4 +DA:73,1 +DA:74,2 +DA:76,0 +DA:77,0 +DA:107,75 +DA:123,1 +DA:124,3 +DA:141,1 +DA:142,3 +DA:159,1 +DA:160,3 +DA:177,0 +DA:178,0 +DA:192,0 +DA:205,0 +DA:218,0 +DA:231,0 +DA:245,1 +DA:246,3 +DA:260,1 +DA:270,1 +DA:277,4 +DA:281,2 +DA:309,76 +DA:327,1 +DA:328,2 +DA:329,3 +DA:349,1 +DA:350,2 +DA:351,3 +DA:371,1 +DA:372,1 +DA:373,4 +DA:392,0 +DA:393,0 +DA:394,0 +DA:413,0 +DA:430,0 +DA:449,2 +DA:450,6 +DA:468,1 +DA:476,1 +DA:481,2 +DA:485,2 +DA:514,75 +DA:530,1 +DA:531,2 +DA:532,3 +DA:550,1 +DA:551,2 +DA:552,3 +DA:570,0 +DA:571,0 +DA:572,0 +DA:587,0 +DA:600,0 +DA:613,0 +DA:626,0 +DA:640,1 +DA:641,3 +DA:655,1 +DA:664,1 +DA:670,2 +DA:674,2 +LF:76 +LH:56 +end_of_record +SF:lib/src/attributes/scalars/scalars_attribute.dart +DA:10,15 +DA:12,6 +DA:15,1 +DA:16,2 LF:4 LH:4 end_of_record -SF:lib/src/attributes/spacing/spacing_attribute.dart -DA:13,6 -DA:15,0 -DA:17,3 -DA:18,3 -DA:19,3 -DA:20,3 -DA:21,3 -DA:22,3 -DA:24,0 -DA:26,0 -DA:32,6 -DA:34,1 -DA:36,4 -DA:42,6 -DA:44,1 -DA:46,4 -LF:16 -LH:13 +SF:lib/src/attributes/shadow/shadow_dto.dart +DA:14,8 +DA:33,4 +DA:36,2 +DA:37,2 +DA:38,2 +DA:39,4 +DA:40,2 +DA:47,1 +DA:48,1 +DA:52,2 +DA:56,2 +DA:57,4 +DA:58,2 +DA:59,2 +DA:64,1 +DA:68,1 +DA:69,1 +DA:70,1 +DA:71,1 +DA:75,0 +DA:76,0 +DA:90,7 +DA:98,5 +DA:99,5 +DA:100,10 +DA:101,5 +DA:102,5 +DA:103,5 +DA:108,1 +DA:109,1 +DA:113,4 +DA:117,4 +DA:118,8 +DA:119,4 +DA:120,4 +DA:121,4 +DA:126,1 +DA:130,1 +DA:131,3 +DA:132,1 +DA:133,1 +DA:134,1 +DA:138,3 +DA:139,15 +LF:44 +LH:42 +end_of_record +SF:lib/src/attributes/shadow/shadow_util.dart +DA:32,2 +DA:35,2 +DA:36,2 +DA:42,4 +DA:59,1 +DA:60,3 +DA:77,1 +DA:78,3 +DA:94,0 +DA:97,2 +DA:98,2 +DA:99,2 +DA:111,1 +DA:125,1 +DA:126,4 +DA:136,3 +DA:138,2 +DA:144,2 +DA:151,4 +DA:164,1 +DA:165,3 +DA:178,1 +DA:179,3 +DA:192,1 +DA:193,3 +DA:206,1 +DA:207,3 +DA:211,2 +DA:217,2 +DA:218,2 +DA:232,1 +DA:244,1 +DA:245,2 +DA:247,4 +DA:251,0 +DA:252,0 +DA:253,0 +DA:254,0 +DA:255,0 +DA:256,0 +DA:257,0 +DA:258,0 +DA:259,0 +DA:260,0 +DA:261,0 +LF:45 +LH:33 end_of_record -SF:lib/src/attributes/spacing/spacing_util.dart -DA:33,64 -DA:35,1 +SF:lib/src/attributes/spacing/edge_insets_dto.dart +DA:18,12 +DA:27,15 +DA:32,5 +DA:33,35 +LF:4 +LH:4 +end_of_record +SF:lib/src/attributes/spacing/spacing_dto.dart +DA:10,12 +DA:19,8 +DA:26,3 +DA:35,2 DA:36,2 +DA:37,1 +DA:38,1 +DA:39,1 +DA:40,1 +DA:41,1 +DA:43,2 +DA:44,2 +DA:45,2 +DA:46,2 +DA:47,2 +DA:48,2 +DA:52,0 +DA:59,3 +DA:60,1 +DA:63,5 +DA:67,3 +DA:68,3 +DA:69,3 +DA:70,3 +DA:71,3 +DA:72,6 +DA:73,6 +DA:77,5 +DA:79,5 +DA:80,0 +DA:81,0 +DA:82,0 +DA:83,0 +DA:84,0 +DA:86,5 +DA:87,15 +DA:88,15 +DA:89,15 +DA:90,15 +LF:39 +LH:33 +end_of_record +SF:lib/src/attributes/spacing/spacing_util.dart +DA:32,7 +DA:34,1 +DA:35,2 +DA:54,1 DA:55,1 -DA:56,1 -DA:57,2 +DA:56,2 +DA:77,1 DA:78,1 -DA:79,1 -DA:80,2 +DA:79,2 +DA:100,1 DA:101,1 DA:102,1 DA:103,1 -DA:104,1 -DA:126,1 -DA:127,3 -DA:148,1 -DA:149,3 -DA:164,1 -DA:165,3 -DA:180,1 -DA:181,3 +DA:125,1 +DA:126,3 +DA:147,1 +DA:148,3 +DA:163,1 +DA:164,3 +DA:179,1 +DA:180,3 +DA:201,0 DA:202,0 -DA:203,0 +DA:223,0 DA:224,0 -DA:225,0 -DA:246,2 -DA:254,4 -DA:255,2 -DA:283,2 -DA:297,2 +DA:245,3 +DA:253,6 +DA:254,3 +DA:282,3 +DA:296,3 +DA:334,1 DA:335,1 -DA:336,1 +DA:351,0 DA:352,0 DA:353,0 -DA:354,0 -DA:373,1 -DA:374,3 -DA:392,1 -DA:393,3 +DA:372,1 +DA:373,3 +DA:391,1 +DA:392,3 +DA:410,0 DA:411,0 -DA:412,0 +DA:429,0 DA:430,0 -DA:431,0 +DA:448,0 DA:449,0 -DA:450,0 +DA:462,0 DA:463,0 DA:464,0 -DA:465,0 -DA:489,1 -DA:504,1 -DA:525,1 -DA:526,2 -DA:527,1 -DA:570,2 -DA:582,4 -DA:594,4 -DA:606,4 -DA:618,4 -DA:630,4 -DA:642,4 -DA:657,3 +DA:488,1 +DA:503,1 +DA:524,1 +DA:525,2 +DA:526,1 +DA:569,3 +DA:581,4 +DA:593,4 +DA:605,4 +DA:617,4 +DA:629,4 +DA:641,4 +DA:656,6 LF:61 LH:45 end_of_record @@ -1063,6 +1328,77 @@ DA:13,4 LF:3 LH:3 end_of_record +SF:lib/src/attributes/strut_style/strut_style_dto.dart +DA:17,7 +DA:28,3 +DA:29,3 +DA:30,3 +DA:31,3 +DA:32,3 +DA:33,3 +DA:34,3 +DA:35,3 +DA:36,3 +DA:37,3 +DA:41,0 +DA:42,0 +DA:45,3 +DA:49,2 +DA:50,3 +DA:51,4 +DA:52,4 +DA:53,3 +DA:54,4 +DA:55,3 +DA:56,3 +DA:57,4 +DA:61,5 +DA:65,5 +DA:66,6 +DA:67,7 +DA:68,5 +DA:69,6 +DA:70,6 +DA:71,6 +DA:72,6 +DA:73,7 +DA:77,4 +DA:78,4 +DA:79,4 +DA:80,4 +DA:81,4 +DA:82,4 +DA:83,4 +DA:84,4 +DA:85,4 +DA:86,4 +LF:43 +LH:41 +end_of_record +SF:lib/src/attributes/strut_style/strut_style_util.dart +DA:10,1 +DA:11,0 +DA:13,1 +DA:14,3 +DA:17,1 +DA:18,3 +DA:21,1 +DA:22,3 +DA:25,1 +DA:26,3 +DA:29,1 +DA:30,1 +DA:31,2 +DA:35,2 +DA:37,2 +DA:39,0 +DA:40,0 +DA:42,1 +DA:52,1 +DA:63,2 +LF:20 +LH:17 +end_of_record SF:lib/src/attributes/style_mix_attribute.dart DA:12,1 DA:16,1 @@ -1100,6 +1436,134 @@ DA:15,0 LF:3 LH:1 end_of_record +SF:lib/src/attributes/text_style/text_style_dto.dart +DA:41,5 +DA:65,0 +DA:89,1 +DA:90,1 +DA:91,0 +DA:92,1 +DA:93,1 +DA:94,1 +DA:95,2 +DA:96,1 +DA:97,1 +DA:98,1 +DA:99,1 +DA:100,1 +DA:101,1 +DA:102,1 +DA:103,1 +DA:104,1 +DA:105,1 +DA:106,1 +DA:107,1 +DA:108,1 +DA:109,1 +DA:110,1 +DA:111,1 +DA:112,1 +DA:113,1 +DA:117,0 +DA:118,0 +DA:121,10 +DA:123,1 +DA:127,2 +DA:131,1 +DA:132,2 +DA:133,2 +DA:134,1 +DA:135,2 +DA:136,1 +DA:137,1 +DA:138,1 +DA:139,2 +DA:140,2 +DA:141,1 +DA:142,1 +DA:143,1 +DA:145,2 +DA:146,1 +DA:147,1 +DA:148,1 +DA:149,2 +DA:150,1 +DA:151,1 +DA:152,1 +DA:153,2 +DA:154,1 +DA:155,1 +DA:159,5 +DA:161,5 +DA:162,5 +DA:163,10 +DA:164,6 +DA:165,5 +DA:166,5 +DA:167,5 +DA:168,5 +DA:169,5 +DA:170,5 +DA:171,5 +DA:172,5 +DA:173,5 +DA:174,5 +DA:175,9 +DA:176,5 +DA:177,5 +DA:178,7 +DA:179,5 +DA:180,5 +DA:181,5 +DA:182,5 +DA:183,5 +DA:185,0 +DA:188,2 +DA:189,2 +DA:190,2 +DA:191,2 +DA:192,2 +DA:193,2 +DA:194,2 +DA:195,2 +DA:196,2 +DA:197,2 +DA:198,2 +DA:199,2 +DA:200,2 +DA:201,2 +DA:202,2 +DA:203,2 +DA:204,2 +DA:205,2 +DA:206,2 +DA:207,2 +DA:208,2 +DA:209,2 +DA:210,2 +DA:211,2 +DA:218,5 +DA:220,4 +DA:243,8 +DA:268,15 +DA:270,0 +DA:271,0 +DA:274,1 +DA:275,2 +DA:278,0 +DA:279,0 +DA:288,5 +DA:290,5 +DA:291,15 +DA:292,7 +DA:293,5 +DA:296,2 +DA:298,4 +DA:301,2 +DA:302,4 +LF:124 +LH:115 +end_of_record SF:lib/src/attributes/text_style/text_style_util.dart DA:43,4 DA:45,1 @@ -1161,20 +1625,20 @@ LF:56 LH:30 end_of_record SF:lib/src/attributes/variant_attribute.dart -DA:15,4 -DA:17,6 -DA:19,6 -DA:21,0 -DA:23,0 -DA:25,0 +DA:15,5 +DA:17,9 +DA:19,8 +DA:21,1 +DA:23,3 +DA:25,5 DA:28,1 DA:29,3 -DA:39,3 -DA:41,3 -DA:42,9 -DA:44,0 -DA:46,0 -DA:48,0 +DA:39,4 +DA:41,4 +DA:42,12 +DA:44,1 +DA:46,3 +DA:48,5 DA:52,0 DA:53,0 DA:54,0 @@ -1193,22 +1657,26 @@ DA:81,0 DA:83,0 DA:85,0 DA:87,0 -LF:32 -LH:16 +DA:93,0 +DA:95,0 +DA:97,0 +DA:99,0 +LF:36 +LH:22 end_of_record SF:lib/src/core/attribute.dart -DA:8,757 -DA:12,752 -DA:19,44 -DA:75,719 -DA:80,8 -DA:87,20 -DA:89,5 -DA:90,10 -DA:92,3 -DA:95,6 -DA:96,12 -DA:112,15 +DA:8,427 +DA:12,421 +DA:19,50 +DA:75,397 +DA:80,12 +DA:87,8 +DA:89,2 +DA:90,4 +DA:92,1 +DA:95,2 +DA:96,4 +DA:112,319 DA:114,0 DA:115,0 DA:117,0 @@ -1222,39 +1690,39 @@ LF:21 LH:16 end_of_record SF:lib/src/core/attributes_map.dart -DA:14,40 -DA:16,64 -DA:18,40 -DA:19,80 -DA:22,40 -DA:25,40 -DA:26,54 -DA:27,14 -DA:30,14 -DA:31,7 -DA:36,9 -DA:38,9 -DA:41,2 +DA:14,45 +DA:16,74 +DA:18,45 +DA:19,90 +DA:22,45 +DA:25,45 +DA:26,63 +DA:27,18 +DA:30,18 +DA:31,6 +DA:36,12 +DA:38,12 +DA:41,6 DA:48,6 DA:50,3 DA:52,0 -DA:54,129 +DA:54,150 DA:56,1 DA:57,3 DA:59,0 -DA:61,10 -DA:62,30 -DA:64,3 -DA:65,12 -DA:68,4 -DA:69,9 -DA:75,40 -DA:77,64 -DA:79,40 -DA:80,80 -DA:83,40 -DA:86,40 -DA:87,42 +DA:61,14 +DA:62,42 +DA:64,4 +DA:65,16 +DA:68,5 +DA:69,11 +DA:75,45 +DA:77,74 +DA:79,45 +DA:80,90 +DA:83,45 +DA:86,45 +DA:87,47 DA:88,2 DA:91,2 DA:93,2 @@ -1262,15 +1730,15 @@ DA:96,0 DA:103,3 DA:105,3 DA:107,0 -DA:109,13 -DA:111,36 -DA:112,84 +DA:109,17 +DA:111,40 +DA:112,97 DA:114,0 DA:115,0 -DA:117,3 -DA:118,12 -DA:121,3 -DA:122,6 +DA:117,4 +DA:118,16 +DA:121,4 +DA:122,8 LF:49 LH:43 end_of_record @@ -1310,55 +1778,48 @@ LF:21 LH:18 end_of_record SF:lib/src/core/extensions/values_ext.dart -DA:23,2 -DA:25,3 -DA:29,0 -DA:32,1 -DA:33,2 +DA:20,2 +DA:22,3 +DA:26,0 +DA:29,1 +DA:30,2 +DA:31,0 +DA:32,0 DA:34,0 -DA:35,0 -DA:37,0 -DA:42,2 -DA:46,0 -DA:50,0 -DA:54,10 -DA:56,1 -DA:57,2 -DA:62,0 -DA:66,4 -DA:70,24 -DA:75,1 -DA:76,1 -DA:81,2 -DA:83,3 -DA:88,0 -DA:92,1 -DA:93,2 +DA:39,2 +DA:43,0 +DA:47,0 +DA:51,10 +DA:53,1 +DA:54,2 +DA:59,0 +DA:63,6 +DA:67,28 +DA:74,4 +DA:81,0 +DA:82,0 +DA:83,0 +DA:85,0 +DA:90,4 DA:94,2 -DA:96,0 -DA:99,3 -DA:103,2 -DA:107,2 -DA:111,1 -DA:112,2 -DA:115,3 -DA:116,3 +DA:98,1 +DA:99,2 +DA:102,3 +DA:103,3 +DA:109,0 +DA:110,0 +DA:112,0 +DA:117,2 DA:121,2 -DA:124,0 DA:125,0 -DA:127,0 -DA:132,0 -DA:136,2 -DA:140,2 -DA:144,0 -DA:145,0 -DA:150,6 -DA:154,1 -DA:155,4 -DA:160,2 -DA:162,3 -LF:47 -LH:32 +DA:126,0 +DA:131,6 +DA:135,1 +DA:136,4 +DA:141,2 +DA:143,3 +LF:40 +LH:24 end_of_record SF:lib/src/decorators/clip_decorator.dart DA:10,3 @@ -1421,7 +1882,7 @@ DA:151,0 DA:152,0 DA:153,0 DA:155,0 -DA:161,64 +DA:161,74 DA:162,0 DA:164,0 DA:165,0 @@ -1433,7 +1894,7 @@ LF:68 LH:43 end_of_record SF:lib/src/decorators/decorator.dart -DA:8,6 +DA:8,7 DA:13,5 DA:15,0 LF:3 @@ -1493,25 +1954,26 @@ LF:3 LH:0 end_of_record SF:lib/src/deprecations.dart -DA:13,0 -DA:15,0 -DA:18,0 -DA:20,0 -DA:23,0 -DA:27,0 -DA:30,0 -DA:32,0 -DA:35,0 -DA:39,0 -DA:41,0 -DA:44,0 -DA:46,0 -DA:49,0 -DA:53,0 -DA:56,0 -DA:60,0 -DA:63,0 -DA:65,0 +DA:12,0 +DA:14,0 +DA:17,0 +DA:19,0 +DA:22,0 +DA:26,0 +DA:29,0 +DA:31,0 +DA:34,0 +DA:38,0 +DA:40,0 +DA:43,0 +DA:45,0 +DA:48,0 +DA:52,0 +DA:55,0 +DA:59,0 +DA:62,0 +DA:64,0 +DA:74,0 DA:75,0 DA:76,0 DA:77,0 @@ -1523,247 +1985,278 @@ DA:82,0 DA:83,0 DA:84,0 DA:85,0 -DA:86,0 -DA:89,0 -DA:91,0 -DA:95,0 -DA:98,0 -DA:101,0 -DA:104,0 -DA:107,0 -DA:110,0 -DA:113,0 -DA:116,0 -DA:119,0 -DA:122,0 -DA:125,0 -DA:128,0 -DA:131,0 -DA:137,0 -DA:139,0 -DA:143,0 +DA:88,0 +DA:90,0 +DA:94,0 +DA:97,0 +DA:100,0 +DA:103,0 +DA:106,0 +DA:109,0 +DA:112,0 +DA:115,0 +DA:118,0 +DA:121,0 +DA:124,0 +DA:127,0 +DA:130,0 +DA:136,0 +DA:138,0 +DA:142,0 +DA:203,0 DA:204,0 -DA:205,0 +DA:207,0 DA:208,0 -DA:209,0 +DA:211,0 DA:212,0 -DA:213,0 +DA:215,0 DA:216,0 -DA:217,0 +DA:219,0 DA:220,0 -DA:221,0 +DA:223,0 DA:224,0 -DA:225,0 +DA:227,0 DA:228,0 -DA:229,0 +DA:231,0 DA:232,0 -DA:233,0 +DA:235,0 DA:236,0 -DA:237,0 +DA:239,0 DA:240,0 -DA:241,0 +DA:243,0 DA:244,0 -DA:245,0 +DA:247,0 DA:248,0 -DA:249,0 +DA:251,0 DA:252,0 -DA:253,0 +DA:255,0 DA:256,0 -DA:257,0 +DA:259,0 DA:260,0 -DA:261,0 +DA:263,0 DA:264,0 -DA:265,0 +DA:267,0 DA:268,0 -DA:269,0 +DA:271,0 DA:272,0 -DA:273,0 +DA:275,0 DA:276,0 -DA:277,0 +DA:279,0 DA:280,0 -DA:281,0 +DA:287,0 DA:288,0 -DA:289,0 -DA:296,0 -DA:299,0 -DA:302,0 -DA:305,0 -DA:308,0 -DA:311,0 -DA:314,0 -DA:317,0 -DA:320,0 -DA:325,0 -DA:327,0 -DA:329,0 -DA:331,0 -DA:333,0 -DA:335,0 -DA:337,0 -DA:339,0 -DA:341,0 -DA:344,0 -DA:347,0 +DA:292,0 +DA:295,0 +DA:298,0 +DA:301,0 +DA:304,0 +DA:307,0 +DA:310,0 +DA:313,0 +DA:316,0 +DA:319,0 +DA:322,0 +DA:324,0 +DA:326,0 +DA:328,0 +DA:330,0 +DA:332,0 +DA:334,0 +DA:336,0 +DA:338,0 +DA:340,0 +DA:343,0 +DA:346,0 +DA:349,0 +DA:352,0 +DA:354,0 DA:355,0 -DA:356,0 +DA:357,0 DA:358,0 -DA:359,0 +DA:360,0 DA:361,0 -DA:362,0 -DA:365,0 -DA:367,0 -DA:369,0 -DA:372,0 -DA:374,0 -DA:377,0 -DA:379,0 -DA:382,0 -DA:384,0 -DA:387,0 -DA:389,0 -DA:392,0 -DA:394,0 -DA:397,0 -DA:399,0 -DA:409,0 -DA:412,0 -DA:415,0 -DA:418,0 -DA:421,0 -DA:424,0 -DA:427,0 -DA:430,0 -DA:433,0 -DA:436,0 +DA:364,0 +DA:366,0 +DA:368,0 +DA:371,0 +DA:373,0 +DA:376,0 +DA:378,0 +DA:381,0 +DA:383,0 +DA:386,0 +DA:388,0 +DA:391,0 +DA:393,0 +DA:396,0 +DA:398,0 +DA:402,0 +DA:405,0 +DA:408,0 +DA:411,0 +DA:414,0 +DA:417,0 +DA:420,0 +DA:423,0 +DA:426,0 +DA:429,0 +DA:432,0 +DA:435,0 +DA:438,0 DA:441,0 -DA:443,0 -DA:446,0 -DA:448,0 -DA:451,0 +DA:444,0 +DA:447,0 +DA:450,0 DA:453,0 -DA:457,0 +DA:456,0 DA:459,0 +DA:461,0 DA:463,0 -DA:465,0 +DA:466,0 DA:468,0 -DA:470,0 +DA:471,0 DA:473,0 -DA:475,0 -DA:478,0 -DA:480,0 +DA:477,0 +DA:479,0 DA:483,0 DA:485,0 -DA:489,0 -DA:492,0 +DA:488,0 +DA:490,0 +DA:493,0 DA:495,0 DA:498,0 -DA:501,0 -DA:504,0 -DA:507,0 -DA:510,0 -DA:513,0 -DA:516,0 -DA:519,0 -DA:522,0 -DA:525,0 -DA:528,0 -DA:531,0 -DA:534,0 -DA:537,0 -DA:540,0 -DA:543,0 -DA:546,0 -DA:549,0 -DA:552,0 -DA:555,0 -DA:558,0 -DA:561,0 -DA:564,0 -DA:567,0 -DA:570,0 -DA:573,0 -DA:576,0 -DA:579,0 -DA:582,0 -DA:585,0 -DA:591,3 -DA:594,0 -DA:600,0 -DA:604,0 -DA:607,0 +DA:500,0 +DA:503,0 +DA:505,0 +DA:509,0 +DA:512,0 +DA:515,0 +DA:518,0 +DA:521,0 +DA:524,0 +DA:527,0 +DA:530,0 +DA:533,0 +DA:536,0 +DA:539,0 +DA:542,0 +DA:545,0 +DA:548,0 +DA:551,0 +DA:554,0 +DA:557,0 +DA:560,0 +DA:563,0 +DA:566,0 +DA:569,0 +DA:572,0 +DA:575,0 +DA:578,0 +DA:581,0 +DA:584,0 +DA:587,0 +DA:590,0 +DA:593,0 +DA:596,0 +DA:599,0 +DA:602,0 +DA:605,0 +DA:608,0 DA:611,0 DA:614,0 -DA:616,0 -DA:619,0 -DA:621,0 -DA:622,0 -LF:204 +DA:620,0 +DA:623,0 +DA:626,0 +DA:629,5 +DA:632,0 +DA:636,0 +DA:639,0 +DA:643,0 +DA:646,0 +DA:648,0 +DA:651,0 +DA:653,0 +DA:654,0 +DA:659,0 +DA:662,0 +DA:665,0 +LF:226 LH:1 end_of_record SF:lib/src/factory/mix_provider.dart -DA:11,3 -DA:14,4 -DA:15,4 -DA:19,0 -DA:20,0 -DA:22,0 -DA:31,0 -DA:32,0 -DA:46,3 -DA:51,3 -DA:56,6 +DA:16,4 +DA:19,2 +DA:20,2 +DA:24,0 +DA:25,0 +DA:27,0 +DA:36,0 +DA:37,0 +DA:51,0 +DA:56,0 +DA:61,0 LF:11 -LH:6 +LH:3 end_of_record SF:lib/src/factory/mix_provider_data.dart -DA:24,36 -DA:30,36 -DA:31,36 -DA:33,72 -DA:35,36 -DA:37,36 -DA:44,16 -DA:49,1 +DA:25,40 +DA:31,40 +DA:32,40 +DA:34,40 +DA:36,40 +DA:38,40 +DA:45,18 DA:50,1 -DA:55,1 -DA:56,2 -DA:59,10 -DA:60,20 -DA:61,10 -DA:63,10 -DA:69,0 +DA:51,1 +DA:56,1 +DA:57,2 +DA:60,14 +DA:61,28 +DA:62,14 +DA:64,11 DA:70,0 -DA:73,0 -DA:76,0 +DA:71,0 +DA:74,0 DA:77,0 -DA:79,0 +DA:78,0 DA:80,0 DA:81,0 -DA:90,1 +DA:82,0 DA:91,1 DA:92,1 -DA:93,3 -DA:98,0 +DA:93,1 +DA:94,3 DA:99,0 -DA:102,36 -DA:107,108 -DA:109,72 -DA:110,72 -DA:113,36 -DA:114,108 -DA:117,2 +DA:100,0 +DA:103,40 +DA:108,120 +DA:110,80 +DA:111,80 +DA:114,40 +DA:115,120 DA:118,1 -DA:121,1 -DA:122,0 +DA:119,1 +DA:121,2 +DA:122,2 +DA:123,0 DA:125,1 -DA:128,1 -DA:133,3 -DA:136,10 -DA:137,10 -DA:139,10 -DA:140,0 -LF:46 -LH:34 +DA:129,1 +DA:130,0 +DA:131,0 +DA:133,0 +DA:137,2 +DA:138,1 +DA:143,1 +DA:144,0 +DA:147,1 +DA:150,1 +DA:155,3 +DA:158,11 +DA:159,11 +DA:161,11 +DA:162,0 +LF:56 +LH:40 end_of_record SF:lib/src/factory/style_group.dart DA:4,0 @@ -1771,94 +2264,95 @@ LF:1 LH:0 end_of_record SF:lib/src/factory/style_mix.dart -DA:47,0 -DA:48,0 -DA:49,0 -DA:50,0 -DA:51,0 -DA:52,0 -DA:54,104 -DA:70,13 -DA:92,13 -DA:95,13 -DA:97,13 -DA:109,40 -DA:110,40 -DA:111,40 -DA:113,54 -DA:114,14 -DA:115,14 -DA:116,3 +DA:39,0 +DA:40,0 +DA:41,0 +DA:42,0 +DA:43,0 +DA:44,0 +DA:49,212 +DA:53,45 +DA:69,17 +DA:91,17 +DA:94,17 +DA:96,17 +DA:108,45 +DA:109,45 +DA:110,45 +DA:112,63 +DA:113,18 +DA:114,18 +DA:115,3 +DA:116,2 DA:117,2 -DA:118,2 +DA:118,4 DA:119,4 -DA:120,4 -DA:122,2 -DA:126,40 -DA:127,40 -DA:128,40 -DA:140,1 +DA:121,2 +DA:125,45 +DA:126,45 +DA:127,45 +DA:139,1 +DA:156,1 DA:157,1 -DA:158,1 -DA:160,3 -DA:182,1 -DA:188,12 -DA:191,5 -DA:194,2 -DA:199,3 -DA:226,1 -DA:227,2 -DA:233,3 -DA:237,3 +DA:159,3 +DA:181,1 +DA:187,12 +DA:190,5 +DA:193,2 +DA:198,3 +DA:225,1 +DA:226,2 +DA:232,4 +DA:236,4 +DA:237,0 DA:238,0 -DA:239,0 -DA:249,4 -DA:252,9 -DA:253,9 -DA:255,3 -DA:284,1 -DA:286,1 +DA:248,5 +DA:251,12 +DA:252,12 +DA:254,4 +DA:283,1 +DA:285,1 +DA:290,1 DA:291,1 -DA:292,1 -DA:296,1 -DA:301,3 +DA:295,1 +DA:300,3 +DA:301,1 DA:302,1 -DA:303,1 -DA:305,1 -DA:310,2 -DA:313,2 -DA:314,1 -DA:316,1 +DA:304,1 +DA:309,2 +DA:312,2 +DA:313,1 +DA:315,1 +DA:320,1 DA:321,1 DA:322,1 -DA:323,1 -DA:327,1 -DA:333,5 -DA:336,1 -DA:339,1 -DA:365,1 -DA:369,1 -DA:373,3 -DA:374,2 -DA:375,1 -DA:378,2 -DA:383,4 -DA:385,1 +DA:326,1 +DA:332,5 +DA:335,1 +DA:338,1 +DA:364,1 +DA:368,1 +DA:372,3 +DA:373,2 +DA:374,1 +DA:377,2 +DA:382,4 +DA:384,1 +DA:410,1 DA:411,1 -DA:412,1 -DA:414,2 -DA:415,1 -DA:416,2 -DA:420,1 -DA:423,4 -DA:424,12 -DA:437,1 -DA:440,0 +DA:413,2 +DA:414,1 +DA:415,2 +DA:419,1 +DA:422,5 +DA:423,15 +DA:436,1 +DA:439,0 +DA:441,0 DA:442,0 -DA:443,0 -DA:445,0 -LF:86 -LH:74 +DA:444,0 +LF:87 +LH:75 end_of_record SF:lib/src/factory/style_mix_ext.dart DA:12,1 @@ -1888,48 +2382,155 @@ LF:23 LH:23 end_of_record SF:lib/src/recipes/container/container_attribute.dart -DA:28,68 -DA:41,4 -DA:42,4 -DA:44,4 +DA:23,7 +DA:35,6 +DA:37,6 +DA:38,6 +DA:39,10 +DA:40,10 +DA:41,8 +DA:42,12 +DA:43,6 +DA:44,6 DA:45,6 DA:46,6 -DA:47,6 -DA:48,5 -DA:49,5 -DA:50,5 -DA:51,6 -DA:52,5 -DA:53,4 +DA:50,4 DA:54,4 -DA:55,4 -DA:58,4 -DA:60,4 -DA:61,4 +DA:55,6 +DA:56,12 +DA:57,14 +DA:58,10 +DA:59,12 +DA:60,6 +DA:61,6 DA:62,6 DA:63,6 -DA:64,5 -DA:65,7 -DA:66,4 -DA:67,4 -DA:68,5 -DA:69,4 -DA:70,4 +DA:67,1 +DA:68,1 +DA:69,1 +DA:70,1 +DA:71,1 +DA:72,1 +DA:73,1 +DA:74,1 +DA:75,1 +DA:76,1 +DA:77,1 +LF:34 +LH:34 +end_of_record +SF:lib/src/recipes/container/container_spec.dart +DA:17,6 +DA:29,222 +DA:40,1 +DA:53,1 +DA:54,1 +DA:55,1 +DA:56,1 +DA:57,1 +DA:58,1 +DA:59,1 +DA:60,1 +DA:61,0 +DA:62,0 +DA:66,1 +DA:68,1 +DA:69,3 +DA:70,3 +DA:71,3 +DA:72,3 +DA:73,3 DA:74,4 -DA:78,2 -DA:79,4 -DA:80,6 -DA:81,6 -DA:82,4 -DA:83,4 -DA:84,4 -DA:85,4 -DA:86,4 -DA:87,4 -DA:88,4 -DA:92,0 +DA:75,2 +DA:76,3 +DA:77,3 +DA:81,1 +DA:82,1 +DA:83,1 +DA:84,1 +DA:85,1 +DA:86,1 +DA:87,1 +DA:88,1 +DA:89,1 +DA:90,1 +DA:91,1 +LF:35 +LH:33 +end_of_record +SF:lib/src/recipes/container/container_util.dart +DA:24,75 +DA:26,5 +DA:37,10 +DA:38,5 +DA:52,5 +DA:53,15 +DA:56,3 +DA:57,9 +DA:117,3 +DA:118,7 +DA:178,3 +DA:179,7 +DA:183,8 +DA:185,0 +DA:187,1 +DA:188,1 +DA:189,0 +DA:193,1 +DA:194,3 +DA:197,3 +DA:198,9 +DA:202,4 +DA:204,1 +DA:205,3 +DA:207,0 +DA:209,0 +DA:212,0 +DA:214,0 +DA:216,0 +DA:218,0 +DA:220,4 +DA:222,1 +DA:223,3 +DA:225,3 +DA:236,3 +DA:238,3 +DA:239,3 +DA:240,1 +DA:241,1 +DA:248,6 +LF:40 +LH:32 +end_of_record +SF:lib/src/recipes/container/container_widget.dart +DA:11,3 +DA:15,3 +DA:17,6 +DA:18,6 +DA:21,6 +DA:27,0 +DA:40,0 +DA:42,0 +DA:43,0 +DA:46,0 +DA:48,0 +DA:49,0 +DA:50,0 +DA:57,4 +DA:62,4 +DA:64,4 +DA:65,8 +DA:66,8 +DA:67,8 +DA:68,8 +DA:69,8 +DA:70,8 +DA:71,8 +DA:72,8 +DA:73,8 +DA:74,4 +DA:80,0 DA:93,0 -DA:94,0 DA:95,0 DA:96,0 DA:97,0 @@ -1939,175 +2540,56 @@ DA:100,0 DA:101,0 DA:102,0 DA:103,0 -LF:51 -LH:39 +DA:104,0 +DA:105,0 +DA:106,0 +DA:107,0 +LF:41 +LH:18 end_of_record -SF:lib/src/recipes/container/container_spec.dart -DA:18,4 -DA:31,0 -DA:43,0 -DA:47,0 -DA:48,0 -DA:49,0 -DA:50,0 -DA:51,0 -DA:52,0 -DA:53,0 -DA:54,0 -DA:55,0 -DA:56,0 -DA:57,0 +SF:lib/src/recipes/flex/flex_attribute.dart +DA:19,152 +DA:31,2 +DA:32,2 +DA:35,3 +DA:37,3 +DA:38,3 +DA:39,3 +DA:40,3 +DA:41,3 +DA:42,3 +DA:43,3 +DA:44,3 +DA:45,3 +DA:46,3 +DA:50,1 +DA:54,1 +DA:55,1 +DA:56,1 +DA:57,1 +DA:58,1 +DA:59,1 +DA:60,1 DA:61,1 +DA:62,1 +DA:63,1 +DA:67,1 +DA:68,1 +DA:69,1 +DA:70,1 +DA:71,1 +DA:72,1 +DA:73,1 DA:74,1 DA:75,1 DA:76,1 DA:77,1 -DA:78,1 -DA:79,1 -DA:80,1 -DA:81,1 -DA:82,1 -DA:83,0 -DA:84,0 -DA:88,1 -DA:90,1 -DA:91,3 -DA:92,3 -DA:93,3 -DA:94,3 -DA:95,3 -DA:96,4 -DA:97,2 -DA:98,3 -DA:99,3 -DA:100,3 -DA:104,0 -DA:105,0 -DA:106,0 -DA:107,0 -DA:108,0 -DA:109,0 -DA:110,0 -DA:111,0 -DA:112,0 -DA:113,0 -DA:114,0 -DA:115,0 -LF:50 -LH:23 -end_of_record -SF:lib/src/recipes/container/container_util.dart -DA:159,0 -DA:160,0 -DA:173,3 -DA:186,3 -DA:199,3 -DA:212,3 -DA:232,64 -DA:234,2 -DA:246,4 -DA:247,2 -DA:262,2 -DA:263,6 -DA:266,0 -DA:267,0 -DA:270,0 -DA:271,0 -DA:274,0 -DA:275,0 -DA:278,0 -DA:279,0 -DA:282,0 -DA:283,0 -DA:284,0 -DA:288,0 -DA:289,0 -DA:292,0 -DA:293,0 -DA:296,0 -DA:298,0 -DA:300,0 -DA:312,0 -DA:314,0 -DA:315,0 -DA:316,0 -DA:317,0 -DA:320,0 -DA:325,0 -LF:37 -LH:10 -end_of_record -SF:lib/src/recipes/container/container_widget.dart -DA:11,2 -DA:15,2 -DA:17,2 -DA:18,2 -DA:19,0 -DA:22,4 -DA:23,2 -DA:24,2 -DA:26,2 -DA:28,4 -DA:34,3 -DA:39,3 -DA:41,3 -DA:42,6 -DA:43,6 -DA:44,6 -DA:45,6 -DA:46,6 -DA:47,6 -DA:48,6 -DA:49,6 -DA:50,6 -DA:51,6 -DA:52,3 -LF:24 -LH:23 -end_of_record -SF:lib/src/recipes/flex/flex_attribute.dart -DA:18,194 -DA:30,1 -DA:31,1 -DA:34,2 -DA:36,2 -DA:37,2 -DA:38,2 -DA:39,2 -DA:40,2 -DA:41,2 -DA:42,2 -DA:43,2 -DA:44,2 -DA:45,2 -DA:49,1 -DA:53,1 -DA:54,2 -DA:55,2 -DA:56,2 -DA:57,2 -DA:58,2 -DA:59,2 -DA:60,2 -DA:61,2 -DA:62,2 -DA:66,0 -DA:67,0 -DA:68,0 -DA:69,0 -DA:70,0 -DA:71,0 -DA:72,0 -DA:73,0 -DA:74,0 -DA:75,0 -DA:76,0 LF:36 -LH:25 +LH:36 end_of_record SF:lib/src/recipes/flex/flex_spec.dart -DA:20,3 -DA:32,0 +DA:20,4 +DA:32,74 DA:43,1 DA:44,2 DA:46,0 @@ -2122,144 +2604,124 @@ DA:60,3 DA:61,3 DA:62,3 DA:63,3 -DA:67,0 -DA:69,0 -DA:70,0 -DA:71,0 -DA:72,0 -DA:73,0 -DA:74,0 -DA:75,0 -DA:76,0 -DA:77,0 -DA:78,0 -DA:82,1 +DA:67,1 +DA:79,1 +DA:80,0 +DA:81,0 +DA:82,0 +DA:83,0 +DA:84,0 +DA:85,0 +DA:86,0 +DA:87,0 +DA:88,0 +DA:92,1 +DA:93,1 DA:94,1 -DA:95,0 -DA:96,0 -DA:97,0 -DA:98,0 -DA:99,0 -DA:100,0 -DA:101,0 -DA:102,0 -DA:103,0 -DA:107,1 -DA:108,1 -DA:109,1 -DA:110,1 -DA:111,1 -DA:112,1 -DA:113,1 -DA:114,1 -DA:115,1 -DA:116,1 -DA:117,1 -LF:49 -LH:27 +DA:95,1 +DA:96,1 +DA:97,1 +DA:98,1 +DA:99,1 +DA:100,1 +DA:101,1 +DA:102,1 +LF:38 +LH:28 end_of_record SF:lib/src/recipes/flex/flex_util.dart -DA:6,0 -DA:10,0 -DA:12,0 -DA:14,0 -DA:15,0 -DA:18,0 -DA:19,0 -DA:20,0 -DA:24,0 -DA:25,0 -DA:26,0 -DA:30,0 -DA:31,0 -DA:32,0 -DA:36,0 -DA:37,0 -DA:38,0 -DA:42,0 -DA:43,0 -DA:44,0 -DA:48,0 -DA:49,0 -DA:50,0 -DA:54,0 -DA:55,0 -DA:58,0 -DA:59,0 -DA:62,0 -DA:63,0 -DA:65,0 -DA:76,0 -DA:88,0 +DA:9,0 +DA:13,0 +DA:15,1 +DA:17,1 +DA:18,3 +DA:21,1 +DA:22,1 +DA:23,2 +DA:27,1 +DA:28,1 +DA:29,2 +DA:33,1 +DA:34,1 +DA:35,2 +DA:39,1 +DA:40,1 +DA:41,2 +DA:45,1 +DA:46,1 +DA:47,2 +DA:51,1 +DA:52,1 +DA:53,2 +DA:57,1 +DA:58,3 +DA:61,1 +DA:62,3 +DA:65,3 +DA:66,3 +DA:68,1 +DA:79,1 +DA:91,2 LF:32 -LH:0 +LH:30 end_of_record SF:lib/src/recipes/flex/flex_widget.dart DA:30,1 DA:41,1 -DA:43,1 -DA:44,1 -DA:45,0 -DA:48,2 -DA:49,1 -DA:50,1 -DA:52,1 -DA:54,1 -DA:55,1 -DA:58,1 -DA:59,0 -DA:60,0 -DA:61,0 -DA:65,1 +DA:43,2 +DA:44,2 +DA:46,1 +DA:47,1 +DA:50,1 +DA:51,0 +DA:52,0 +DA:53,0 +DA:57,1 +DA:59,1 +DA:60,1 DA:67,1 -DA:68,1 -DA:75,1 -DA:86,1 -DA:88,1 +DA:78,1 +DA:80,1 +DA:81,1 +DA:83,3 +DA:84,3 +DA:86,3 +DA:88,3 DA:89,1 -DA:91,3 -DA:92,3 -DA:94,3 -DA:96,3 -DA:97,1 -DA:119,1 -DA:124,1 -DA:144,1 -DA:149,1 -DA:171,1 -DA:182,1 -DA:184,2 -DA:185,2 -DA:186,2 -DA:188,1 -DA:190,1 -DA:192,1 -DA:193,1 -DA:216,1 -DA:221,1 -DA:241,1 -DA:246,1 -LF:44 -LH:40 +DA:111,1 +DA:116,1 +DA:136,1 +DA:141,1 +DA:163,1 +DA:174,1 +DA:176,2 +DA:178,2 +DA:180,1 +DA:183,1 +DA:185,3 +DA:207,1 +DA:212,1 +DA:232,1 +DA:237,1 +LF:37 +LH:34 end_of_record SF:lib/src/recipes/icon/icon_attribute.dart -DA:10,195 -DA:12,1 -DA:13,1 -DA:16,3 -DA:18,12 -DA:21,1 -DA:25,1 -DA:26,2 -DA:27,2 -DA:31,0 -DA:32,0 -LF:11 +DA:11,79 +DA:13,4 +DA:15,15 +DA:18,1 +DA:22,1 +DA:23,1 +DA:24,1 +DA:28,1 +DA:29,3 +LF:9 LH:9 end_of_record SF:lib/src/recipes/icon/icon_spec.dart -DA:11,5 -DA:13,0 +DA:11,6 +DA:13,74 DA:17,2 DA:18,4 DA:20,0 @@ -2267,17 +2729,15 @@ DA:23,2 DA:25,2 DA:26,6 DA:27,6 -DA:31,0 -DA:33,0 -DA:36,2 -DA:42,2 -DA:45,0 -DA:46,0 -LF:15 -LH:9 +DA:31,2 +DA:37,2 +DA:40,0 +DA:41,0 +LF:13 +LH:10 end_of_record SF:lib/src/recipes/icon/icon_util.dart -DA:14,64 +DA:14,74 DA:16,0 DA:17,0 DA:20,0 @@ -2290,92 +2750,76 @@ end_of_record SF:lib/src/recipes/icon/icon_widget.dart DA:8,1 DA:21,1 -DA:23,1 -DA:24,1 -DA:25,0 -DA:28,2 +DA:23,2 +DA:24,2 +DA:27,1 +DA:28,1 DA:29,1 DA:30,1 +DA:31,1 DA:32,1 -DA:34,1 -DA:35,1 -DA:36,1 -DA:37,1 -DA:38,1 -DA:39,1 -DA:46,0 +DA:39,0 +DA:54,0 +DA:56,0 +DA:57,0 +DA:60,0 DA:61,0 +DA:62,0 DA:63,0 +DA:64,0 DA:65,0 -DA:68,0 -DA:69,0 -DA:70,0 -DA:72,0 -DA:74,0 -DA:75,0 -DA:76,0 -DA:77,0 -DA:78,0 -DA:79,0 -DA:80,0 -LF:30 -LH:14 +DA:66,0 +LF:21 +LH:10 end_of_record SF:lib/src/recipes/image/image_attribute.dart -DA:16,64 -DA:24,0 -DA:26,0 -DA:27,0 -DA:28,0 -DA:29,0 -DA:30,0 -DA:31,0 -DA:35,0 -DA:39,0 -DA:40,0 -DA:41,0 -DA:42,0 -DA:43,0 -DA:44,0 -DA:48,0 -DA:49,0 +DA:16,77 +DA:24,2 +DA:26,2 +DA:27,2 +DA:28,2 +DA:29,3 +DA:30,2 +DA:31,2 +DA:35,1 +DA:39,1 +DA:40,1 +DA:41,1 +DA:42,1 +DA:43,1 +DA:44,1 +DA:48,1 +DA:49,6 LF:17 -LH:1 +LH:17 end_of_record SF:lib/src/recipes/image/image_spec.dart -DA:17,0 +DA:17,3 DA:25,0 -DA:32,0 -DA:33,0 -DA:35,0 -DA:38,0 -DA:40,0 -DA:41,0 -DA:42,0 -DA:43,0 -DA:44,0 -DA:45,0 -DA:49,0 -DA:51,0 -DA:52,0 -DA:53,0 -DA:54,0 -DA:55,0 -DA:56,0 +DA:32,1 +DA:33,1 +DA:35,1 +DA:38,1 +DA:40,1 +DA:41,3 +DA:42,3 +DA:43,3 +DA:44,2 +DA:45,2 +DA:49,1 +DA:58,1 +DA:59,0 DA:60,0 -DA:69,0 -DA:70,0 -DA:71,0 -DA:72,0 -DA:73,0 -DA:74,0 -DA:78,0 -DA:79,0 -LF:28 -LH:0 +DA:61,0 +DA:62,0 +DA:63,0 +DA:67,1 +DA:68,6 +LF:21 +LH:15 end_of_record SF:lib/src/recipes/image/image_util.dart -DA:14,64 +DA:14,74 DA:16,0 DA:17,0 DA:20,0 @@ -2390,53 +2834,48 @@ LF:11 LH:1 end_of_record SF:lib/src/recipes/stack/stack_attribute.dart -DA:13,130 -DA:23,2 -DA:24,2 -DA:27,2 -DA:29,2 -DA:30,2 -DA:31,2 -DA:32,2 -DA:33,2 -DA:37,1 -DA:41,1 -DA:42,2 -DA:43,2 -DA:44,2 -DA:45,2 -DA:49,0 -DA:50,0 +DA:13,78 +DA:23,3 +DA:24,3 +DA:27,3 +DA:29,3 +DA:30,3 +DA:31,3 +DA:32,3 +DA:33,3 +DA:37,2 +DA:41,2 +DA:42,3 +DA:43,3 +DA:44,3 +DA:45,3 +DA:49,1 +DA:50,5 LF:17 -LH:15 +LH:17 end_of_record -SF:lib/src/recipes/stack/stack_spec.dart -DA:11,3 -DA:18,1 -DA:20,1 -DA:21,3 -DA:22,2 -DA:23,2 -DA:24,2 -DA:28,0 -DA:30,0 -DA:31,0 -DA:32,0 -DA:33,0 -DA:34,0 -DA:38,1 -DA:45,1 -DA:46,0 -DA:47,0 -DA:48,0 -DA:49,0 -DA:53,1 -DA:54,5 -LF:21 -LH:11 +SF:lib/src/recipes/stack/stack_spec.dart +DA:11,4 +DA:18,74 +DA:24,1 +DA:26,1 +DA:27,3 +DA:28,2 +DA:29,2 +DA:30,2 +DA:34,1 +DA:41,1 +DA:42,0 +DA:43,0 +DA:44,0 +DA:45,0 +DA:49,1 +DA:50,5 +LF:16 +LH:12 end_of_record SF:lib/src/recipes/stack/stack_util.dart -DA:13,64 +DA:13,74 DA:15,1 DA:21,1 DA:28,2 @@ -2457,34 +2896,29 @@ end_of_record SF:lib/src/recipes/stack/stack_widget.dart DA:11,1 DA:19,1 -DA:21,1 -DA:22,1 -DA:23,0 -DA:26,2 -DA:27,1 -DA:28,1 +DA:21,2 +DA:22,2 +DA:24,2 DA:30,1 -DA:32,2 -DA:38,1 -DA:43,1 -DA:45,1 -DA:46,2 -DA:47,2 -DA:48,2 -DA:49,2 -DA:50,1 -DA:56,1 -DA:65,1 -DA:67,2 +DA:35,1 +DA:37,1 +DA:38,2 +DA:39,2 +DA:40,2 +DA:41,2 +DA:42,1 +DA:48,1 +DA:57,1 +DA:59,2 +DA:61,2 +DA:63,2 +DA:66,1 DA:68,2 -DA:69,2 -DA:71,1 -DA:73,2 -LF:25 -LH:24 +LF:20 +LH:20 end_of_record SF:lib/src/recipes/text/text_attribute.dart -DA:25,70 +DA:25,6 DA:39,2 DA:40,2 DA:42,2 @@ -2503,7 +2937,7 @@ DA:57,3 DA:58,3 DA:59,3 DA:60,3 -DA:61,4 +DA:61,5 DA:65,3 DA:69,3 DA:70,5 @@ -2529,1221 +2963,797 @@ DA:92,1 DA:93,1 DA:94,1 DA:95,1 -DA:96,1 -LF:46 -LH:46 -end_of_record -SF:lib/src/recipes/text/text_spec.dart -DA:19,4 -DA:34,0 -DA:57,2 -DA:60,6 -DA:63,0 -DA:67,0 -DA:68,0 -DA:69,0 -DA:70,0 -DA:71,0 -DA:72,0 -DA:73,0 -DA:74,0 -DA:75,0 -DA:76,0 -DA:77,0 -DA:78,0 -DA:82,1 -DA:86,1 -DA:87,3 -DA:88,3 -DA:89,3 -DA:91,3 -DA:92,3 -DA:93,3 -DA:94,3 -DA:96,3 -DA:97,3 -DA:98,3 -DA:99,3 -DA:103,1 -DA:117,1 -DA:118,0 -DA:119,0 -DA:120,0 -DA:121,0 -DA:122,0 -DA:123,0 -DA:124,0 -DA:125,0 -DA:126,0 -DA:127,0 -DA:128,0 -DA:132,1 -DA:133,1 -DA:134,1 -DA:135,1 -DA:136,1 -DA:137,1 -DA:138,1 -DA:139,1 -DA:140,1 -DA:141,1 -DA:142,1 -DA:143,1 -DA:144,1 -LF:56 -LH:31 -end_of_record -SF:lib/src/recipes/text/text_util.dart -DA:19,64 -DA:21,0 -DA:22,0 -DA:25,0 -DA:26,0 -DA:29,0 -DA:30,0 -DA:33,0 -DA:34,0 -DA:37,2 -DA:38,6 -DA:41,0 -DA:42,0 -DA:43,0 -DA:47,0 -DA:48,0 -DA:49,0 -DA:53,0 -DA:54,0 -DA:55,0 -DA:59,0 -DA:60,0 -DA:63,0 -DA:64,0 -DA:67,0 -DA:68,0 -DA:71,2 -DA:84,2 -DA:98,4 -DA:101,0 -DA:114,0 -DA:116,0 -DA:120,0 -DA:128,0 -LF:34 -LH:6 -end_of_record -SF:lib/src/recipes/text/text_widget.dart -DA:8,1 -DA:21,1 -DA:23,1 -DA:25,0 -DA:28,2 -DA:29,1 -DA:30,1 -DA:32,1 -DA:34,1 -DA:35,2 -DA:36,1 -DA:37,1 -DA:38,1 -DA:39,1 -DA:40,1 -DA:41,1 -DA:42,1 -DA:43,1 -DA:44,1 -DA:45,1 -DA:46,1 -DA:47,1 -LF:22 -LH:21 -end_of_record -SF:lib/src/theme/mix_theme.dart -DA:12,11 -DA:14,39 -DA:15,46 -DA:16,37 -DA:19,1 -DA:20,2 -DA:25,0 -DA:26,0 -DA:37,94 -DA:45,51 -DA:46,0 -DA:54,43 -DA:61,43 -DA:70,3 -DA:77,3 -DA:78,3 -DA:79,3 -DA:80,3 -DA:81,3 -DA:82,3 -DA:86,0 -DA:93,0 -DA:94,0 -DA:95,0 -DA:96,0 -DA:97,0 -DA:98,0 -DA:102,0 -DA:103,0 -DA:106,0 -DA:108,0 -DA:109,0 -DA:112,0 -DA:114,0 -DA:115,0 -DA:118,0 -DA:119,0 -DA:121,0 -DA:122,0 -DA:123,0 -DA:125,0 -DA:128,0 -DA:129,0 -DA:131,0 -DA:134,1 -DA:135,6 -DA:142,36 -DA:144,1 -DA:145,4 -DA:148,0 -DA:150,1 -DA:151,4 -DA:154,0 -DA:156,1 -DA:157,4 -DA:160,0 -DA:162,4 -DA:163,4 -DA:164,0 -DA:166,0 -DA:169,0 -DA:170,0 -LF:62 -LH:28 -end_of_record -SF:lib/src/theme/tokens/breakpoints.dart -DA:15,65 -DA:20,2 -DA:21,12 -DA:43,64 -DA:45,0 -DA:46,0 -LF:6 -LH:4 -end_of_record -SF:lib/src/theme/tokens/color_token.dart -DA:6,4 -DA:8,0 -DA:10,2 -DA:11,4 -DA:22,4 -DA:24,1 -DA:28,4 -DA:31,1 -DA:32,2 -LF:9 -LH:8 -end_of_record -SF:lib/src/theme/tokens/material_tokens.dart -DA:12,3 -DA:17,3 -DA:22,3 -DA:27,3 -DA:32,3 -DA:37,3 -DA:42,3 -DA:47,3 -DA:52,3 -DA:57,3 -DA:62,3 -DA:67,3 -DA:70,1 +DA:96,1 +LF:46 +LH:46 +end_of_record +SF:lib/src/recipes/text/text_spec.dart +DA:19,4 +DA:34,0 +DA:57,2 +DA:60,6 +DA:63,1 +DA:67,1 +DA:68,3 +DA:69,3 +DA:70,3 +DA:72,3 +DA:73,3 +DA:74,3 +DA:75,3 +DA:77,3 +DA:78,3 DA:79,3 -DA:83,3 -DA:87,3 -DA:91,3 -DA:95,3 -DA:99,3 -DA:103,3 -DA:107,3 -DA:111,3 -DA:115,3 -DA:119,3 -DA:123,3 -DA:127,3 -DA:131,3 -DA:135,3 -DA:140,3 -DA:144,3 -DA:148,3 -DA:152,3 -DA:156,3 -DA:160,3 -DA:164,3 -DA:168,3 -DA:172,3 -DA:176,3 -DA:180,3 -DA:184,3 -DA:188,3 -DA:191,1 -DA:194,3 -DA:195,3 -DA:201,1 -DA:205,3 -DA:206,3 -DA:210,0 -DA:211,0 -DA:212,0 -DA:213,0 -DA:214,0 -DA:215,0 -DA:216,0 -DA:217,0 -DA:218,0 -DA:219,0 -DA:220,0 -DA:221,0 -DA:225,0 -DA:226,0 -DA:227,0 -DA:228,0 -DA:229,0 -DA:230,0 -DA:231,0 -DA:232,0 -DA:233,0 -DA:234,0 -DA:235,0 -DA:236,0 -DA:237,0 -DA:238,0 -DA:239,0 -DA:240,0 -DA:241,0 -DA:242,0 -DA:243,0 -DA:244,0 -DA:245,0 -DA:246,0 -DA:247,0 -DA:248,0 -DA:249,0 -DA:250,0 -DA:251,0 -DA:252,0 -LF:87 -LH:47 +DA:80,3 +DA:84,1 +DA:98,1 +DA:99,0 +DA:100,0 +DA:101,0 +DA:102,0 +DA:103,0 +DA:104,0 +DA:105,0 +DA:106,0 +DA:107,0 +DA:108,0 +DA:109,0 +DA:113,1 +DA:114,1 +DA:115,1 +DA:116,1 +DA:117,1 +DA:118,1 +DA:119,1 +DA:120,1 +DA:121,1 +DA:122,1 +DA:123,1 +DA:124,1 +DA:125,1 +LF:43 +LH:31 end_of_record -SF:lib/src/theme/tokens/mix_token.dart -DA:15,201 -DA:17,0 -DA:18,0 +SF:lib/src/recipes/text/text_util.dart +DA:19,74 DA:21,0 DA:22,0 DA:25,0 DA:26,0 -DA:29,4 -DA:31,4 -DA:35,9 -DA:37,21 -DA:40,5 -DA:41,20 -DA:56,68 -DA:59,64 -DA:61,5 -DA:62,18 -DA:64,11 -DA:69,0 -DA:70,0 -DA:73,0 -DA:74,0 -LF:22 -LH:12 -end_of_record -SF:lib/src/theme/tokens/radius_token.dart -DA:15,66 -DA:17,1 -DA:19,1 -DA:20,2 -DA:32,2 -DA:34,1 -DA:38,4 -DA:41,1 -DA:42,2 -DA:51,1 -DA:53,0 -DA:57,0 -DA:60,3 -DA:62,3 -DA:64,3 -DA:66,3 -LF:16 -LH:14 -end_of_record -SF:lib/src/theme/tokens/space_token.dart -DA:32,65 -DA:34,1 -DA:35,3 -LF:3 -LH:3 -end_of_record -SF:lib/src/theme/tokens/text_style_token.dart -DA:9,3 -DA:11,1 -DA:13,2 -DA:17,4 -DA:29,2 -DA:31,1 -DA:35,4 -DA:38,0 -DA:39,0 +DA:29,0 +DA:30,0 +DA:33,0 +DA:34,0 +DA:37,2 +DA:38,6 DA:41,0 DA:42,0 -DA:44,0 -DA:45,0 +DA:43,0 DA:47,0 DA:48,0 -DA:50,0 -DA:51,0 +DA:49,0 DA:53,0 DA:54,0 -DA:56,0 -DA:57,0 +DA:55,0 DA:59,0 DA:60,0 -DA:62,0 DA:63,0 -DA:65,0 -DA:66,0 +DA:64,0 +DA:67,0 DA:68,0 -DA:70,0 -DA:72,0 -DA:73,0 -DA:75,0 -DA:76,0 -DA:78,0 -DA:79,0 -DA:81,0 -DA:82,0 -DA:84,0 -DA:85,0 -DA:87,0 -DA:89,0 -DA:91,0 -DA:92,0 -DA:94,0 -DA:95,0 -DA:97,0 -DA:99,0 +DA:71,2 +DA:84,2 +DA:98,4 DA:101,0 -DA:102,0 -DA:104,0 -DA:105,0 -DA:107,1 -DA:108,2 -DA:111,0 -DA:112,0 -DA:119,0 -DA:121,0 -DA:123,0 -LF:58 -LH:9 -end_of_record -SF:lib/src/theme/tokens/token_util.dart -DA:7,0 -DA:18,1 -DA:23,65 -DA:24,2 -DA:25,2 -DA:26,2 -DA:27,2 -DA:28,2 -DA:29,2 -DA:33,64 -DA:37,64 -LF:11 -LH:10 -end_of_record -SF:lib/src/utils/context_variant_util/on_breakpoint_util.dart -DA:12,3 -DA:15,3 -DA:18,3 -DA:21,3 -DA:28,0 -DA:29,0 -DA:34,0 -DA:36,0 -DA:37,0 -DA:38,0 -DA:39,0 -DA:41,0 -DA:51,1 -DA:52,1 -DA:53,3 -DA:54,1 -DA:55,2 -DA:57,1 -DA:59,1 -DA:61,1 -LF:20 -LH:12 -end_of_record -SF:lib/src/utils/context_variant_util/on_brightness_util.dart -DA:10,9 -DA:13,9 -DA:20,3 -DA:21,3 -DA:22,9 -DA:23,3 -DA:24,9 -LF:7 -LH:7 -end_of_record -SF:lib/src/utils/context_variant_util/on_directionality_util.dart -DA:7,3 -DA:10,3 -DA:19,1 -DA:20,1 -DA:21,3 -DA:22,3 -LF:6 +DA:114,0 +DA:116,0 +DA:120,0 +DA:128,0 +LF:34 LH:6 end_of_record -SF:lib/src/utils/context_variant_util/on_helper_util.dart -DA:12,4 -DA:13,4 -DA:14,8 -DA:15,12 -LF:4 -LH:4 +SF:lib/src/recipes/text/text_widget.dart +DA:7,1 +DA:20,1 +DA:22,2 +DA:23,2 +DA:25,1 +DA:26,2 +DA:27,1 +DA:28,1 +DA:29,1 +DA:30,1 +DA:31,1 +DA:32,1 +DA:33,1 +DA:34,1 +DA:35,1 +DA:36,1 +DA:37,1 +DA:38,1 +LF:18 +LH:18 end_of_record -SF:lib/src/utils/context_variant_util/on_orientation_util.dart -DA:9,3 -DA:14,3 -DA:23,1 -DA:24,1 -DA:25,3 +SF:lib/src/theme/mix_theme.dart +DA:15,12 +DA:17,7 +DA:19,14 +DA:21,7 DA:26,1 DA:27,2 -LF:7 -LH:7 +DA:32,0 +DA:33,0 +DA:44,72 +DA:52,61 +DA:53,0 +DA:61,11 +DA:68,11 +DA:69,11 +DA:70,11 +DA:72,33 +DA:73,33 +DA:74,33 +DA:78,1 +DA:85,2 +DA:86,1 +DA:96,1 +DA:103,1 +DA:105,1 +DA:106,1 +DA:108,1 +DA:109,1 +DA:110,1 +DA:114,1 +DA:115,1 +DA:116,3 +DA:117,3 +DA:118,3 +DA:119,3 +DA:120,3 +DA:124,0 +DA:125,0 +DA:128,44 +DA:137,44 +DA:143,44 +DA:154,40 +DA:156,3 +DA:158,0 +DA:160,3 +DA:162,0 +DA:164,3 +DA:166,0 +DA:168,0 +DA:170,5 +DA:171,5 +DA:174,0 +LF:51 +LH:41 end_of_record -SF:lib/src/utils/decorators_util.dart -DA:21,0 -DA:22,0 -DA:24,1 -DA:25,1 -DA:32,64 -DA:37,2 +SF:lib/src/theme/tokens/breakpoints_token.dart +DA:17,149 +DA:19,2 +DA:20,12 +DA:36,74 DA:38,0 -DA:39,2 +DA:39,0 DA:41,1 -DA:42,1 -DA:47,64 -DA:48,3 -DA:49,3 -DA:50,3 -DA:52,3 -DA:56,64 -LF:16 -LH:13 -end_of_record -SF:lib/src/utils/helper_util.dart -DA:8,129 -DA:10,1 -DA:32,3 -DA:35,1 -LF:4 -LH:4 +DA:43,3 +DA:45,1 +DA:46,0 +DA:49,1 +DA:50,0 +DA:60,0 +DA:68,0 +LF:14 +LH:8 end_of_record -SF:lib/src/utils/pressable_util.dart -DA:9,3 -DA:10,3 -DA:11,3 -DA:12,6 -DA:14,8 -DA:16,3 -DA:18,1 -DA:19,1 +SF:lib/src/theme/tokens/color_token.dart +DA:8,76 +DA:10,2 +DA:11,2 +DA:13,2 +DA:15,6 +DA:17,2 +DA:18,0 DA:21,2 -DA:25,2 -DA:26,2 -DA:27,6 -DA:28,2 -DA:29,2 -DA:31,4 +DA:22,2 +DA:31,2 +DA:38,4 +DA:40,0 +DA:44,0 +DA:47,0 +DA:48,0 LF:15 -LH:15 -end_of_record -SF:lib/src/variants/context_variant.dart -DA:50,10 -DA:52,3 -DA:75,3 -DA:78,3 -DA:81,6 -DA:84,1 -DA:85,3 -LF:7 -LH:7 +LH:10 end_of_record -SF:lib/src/variants/multi_variant.dart -DA:57,3 -DA:59,3 -DA:63,3 -DA:64,15 -DA:65,12 -DA:67,3 -DA:73,3 -DA:74,3 -DA:80,2 -DA:81,2 -DA:97,2 -DA:98,6 -DA:100,4 -DA:101,2 -DA:102,0 -DA:121,2 -DA:122,2 -DA:123,4 -DA:125,4 -DA:126,4 -DA:127,2 -DA:145,1 -DA:146,2 -DA:148,2 -DA:149,4 -DA:150,4 -DA:151,4 -DA:158,1 -DA:181,1 -DA:184,1 -DA:186,2 +SF:lib/src/theme/tokens/material_tokens.dart +DA:16,1 +DA:19,3 +DA:20,1 +DA:21,5 +DA:22,5 +DA:23,5 +DA:24,5 +DA:25,5 +DA:26,5 +DA:27,5 +DA:28,5 +DA:29,5 +DA:30,5 +DA:31,5 +DA:32,5 +DA:34,1 +DA:35,5 +DA:36,5 +DA:37,5 +DA:38,5 +DA:39,5 +DA:40,5 +DA:41,5 +DA:42,5 +DA:43,5 +DA:44,5 +DA:45,5 +DA:46,5 +DA:47,5 +DA:48,5 +DA:49,5 +DA:50,5 +DA:51,5 +DA:52,5 +DA:53,5 +DA:54,5 +DA:55,5 +DA:56,5 +DA:57,5 +DA:58,5 +DA:59,5 +DA:60,5 +DA:61,5 +DA:62,5 +DA:92,74 +DA:138,74 +DA:142,3 +DA:143,3 +DA:147,0 +DA:148,0 +DA:149,0 +DA:150,0 +DA:151,0 +DA:152,0 +DA:153,0 +DA:154,0 +DA:155,0 +DA:156,0 +DA:157,0 +DA:158,0 +DA:162,0 +DA:163,0 +DA:164,0 +DA:165,0 +DA:166,0 +DA:167,0 +DA:168,0 +DA:169,0 +DA:170,0 +DA:171,0 +DA:172,0 +DA:173,0 +DA:174,0 +DA:175,0 +DA:176,0 +DA:177,0 +DA:178,0 +DA:179,0 +DA:180,0 +DA:181,0 +DA:182,0 +DA:183,0 +DA:184,0 +DA:185,0 +DA:186,0 +DA:187,0 +DA:188,0 DA:189,0 -DA:190,0 -LF:33 -LH:30 +LF:88 +LH:48 end_of_record -SF:lib/src/variants/variant.dart -DA:45,65 -DA:57,3 -DA:69,3 -DA:75,1 -DA:97,1 -DA:100,1 -DA:102,2 -DA:105,3 -DA:106,6 -LF:9 -LH:9 +SF:lib/src/theme/tokens/mix_token.dart +DA:14,301 +DA:16,0 +DA:18,0 +DA:20,0 +DA:26,7 +DA:30,9 +DA:32,12 +DA:35,12 +DA:36,36 +DA:56,85 +DA:59,74 +DA:61,18 +DA:65,0 +DA:66,0 +DA:69,11 +DA:73,22 +DA:75,22 +DA:77,11 +DA:80,0 +DA:81,0 +LF:20 +LH:13 +end_of_record +SF:lib/src/theme/tokens/radius_token.dart +DA:16,75 +DA:18,1 +DA:19,1 +DA:21,1 +DA:23,3 +DA:25,1 +DA:26,0 +DA:30,1 +DA:41,0 +DA:49,2 +DA:51,1 +DA:55,4 +DA:58,0 +DA:59,0 +DA:68,1 +DA:70,0 +DA:74,0 +DA:77,3 +DA:79,3 +DA:81,3 +DA:83,3 +LF:21 +LH:15 end_of_record -SF:lib/src/widgets/empty_widget.dart -DA:4,1 -DA:6,0 -LF:2 -LH:1 +SF:lib/src/theme/tokens/space_token.dart +DA:11,0 +DA:12,0 +DA:15,0 +DA:16,0 +DA:19,0 +DA:48,75 +DA:50,1 +DA:51,3 +DA:53,0 +DA:55,0 +DA:57,0 +DA:58,0 +LF:12 +LH:3 end_of_record -SF:lib/src/widgets/gap_widget.dart -DA:9,1 +SF:lib/src/theme/tokens/text_style_token.dart +DA:10,76 +DA:12,1 DA:13,1 DA:15,2 -DA:18,0 +DA:17,6 +DA:19,2 DA:20,0 -DA:27,1 -DA:30,1 -DA:31,1 -DA:33,1 -DA:34,1 -DA:38,0 -DA:39,0 -DA:40,0 -DA:41,0 -DA:42,0 -DA:45,1 -DA:47,1 -DA:48,1 -DA:52,2 -DA:53,0 -DA:54,1 -DA:55,2 -DA:56,0 -DA:57,1 -DA:58,1 -DA:59,3 -DA:60,3 -DA:63,1 -DA:68,0 -DA:70,0 -DA:71,0 -LF:31 -LH:19 -end_of_record -SF:lib/src/widgets/pressable/pressable.notifier.dart -DA:6,3 -DA:13,3 -DA:14,3 -DA:21,1 -DA:23,6 -LF:5 -LH:5 -end_of_record -SF:lib/src/widgets/pressable/pressable_widget.dart -DA:7,1 -DA:27,1 -DA:30,1 +DA:23,2 +DA:24,2 DA:36,1 -DA:38,1 -DA:39,4 -DA:42,1 -DA:43,4 +DA:44,1 DA:46,0 -DA:48,0 -DA:49,0 DA:50,0 -DA:54,1 -DA:56,4 -DA:57,1 -DA:65,5 -DA:67,1 -DA:68,4 -DA:73,1 -DA:77,1 -DA:81,1 +DA:53,0 +DA:82,0 +DA:83,0 +DA:84,0 +DA:86,0 +DA:87,0 DA:89,0 DA:90,0 -DA:91,0 DA:92,0 -DA:97,0 +DA:93,0 +DA:95,0 +DA:96,0 DA:98,0 -DA:101,1 -DA:103,1 -DA:104,1 -DA:105,1 -DA:107,3 -DA:108,2 -DA:109,1 +DA:99,0 +DA:101,0 +DA:102,0 +DA:104,0 +DA:105,0 +DA:107,0 +DA:108,0 DA:110,0 DA:111,0 -DA:112,0 DA:113,0 DA:114,0 -DA:115,2 DA:116,0 -DA:117,0 -DA:118,2 -DA:119,1 -DA:120,1 -DA:121,1 -DA:122,2 +DA:118,0 +DA:120,0 +DA:121,0 DA:123,0 DA:124,0 -DA:125,2 -DA:126,1 -DA:127,1 -DA:128,1 -DA:129,2 -LF:54 -LH:35 -end_of_record -SF:lib/src/widgets/styled_widget.dart -DA:8,3 -DA:22,3 -DA:23,6 -DA:31,0 -LF:4 -LH:3 -end_of_record -SF:lib/src/attributes/color/color_util.dart -DA:11,66 -DA:16,0 -LF:2 -LH:1 +DA:126,0 +DA:127,0 +DA:129,0 +DA:130,0 +DA:132,0 +DA:133,0 +DA:135,0 +DA:137,0 +DA:139,0 +DA:140,0 +DA:142,0 +DA:143,0 +DA:145,0 +DA:147,0 +DA:149,0 +DA:150,0 +DA:152,0 +DA:153,0 +DA:155,0 +DA:156,0 +DA:159,0 +DA:160,0 +DA:167,0 +DA:169,0 +DA:171,0 +LF:68 +LH:10 end_of_record -SF:lib/src/attributes/color/color_attribute.dart -DA:11,2 -DA:16,1 -DA:17,2 -DA:19,0 -DA:20,0 -LF:5 -LH:3 +SF:lib/src/theme/tokens/token_util.dart +DA:7,0 +DA:18,1 +DA:23,75 +DA:24,2 +DA:25,2 +DA:26,2 +DA:27,2 +DA:28,2 +DA:29,2 +DA:33,74 +DA:37,74 +LF:11 +LH:10 end_of_record -SF:lib/src/attributes/constraints/constraints_dto.dart -DA:8,7 -DA:18,7 -DA:25,3 -DA:26,3 -DA:27,3 -DA:28,3 -DA:29,3 -DA:30,3 +SF:lib/src/utils/context_variant_util/on_breakpoint_util.dart +DA:12,3 +DA:15,3 +DA:18,3 +DA:21,3 +DA:28,0 +DA:29,0 +DA:31,0 +DA:33,0 DA:34,0 DA:35,0 -DA:38,4 -DA:42,4 -DA:43,2 -DA:44,1 -DA:45,1 -DA:46,4 -DA:47,4 -DA:48,4 -DA:49,4 -DA:50,4 -DA:57,2 -DA:61,2 -DA:62,2 -DA:63,4 -DA:64,2 -DA:65,4 -DA:69,3 -DA:70,15 -LF:28 -LH:26 -end_of_record -SF:lib/src/attributes/decoration/decoration_dto.dart -DA:17,9 -DA:19,0 -DA:22,0 -DA:23,0 -DA:25,0 -DA:26,0 -DA:29,0 -DA:30,0 -DA:44,9 -DA:53,3 -DA:54,3 -DA:55,6 -DA:56,6 -DA:57,6 -DA:58,6 -DA:59,9 -DA:60,3 -DA:64,0 -DA:65,0 -DA:68,6 -DA:70,6 -DA:71,11 -DA:72,9 -DA:73,8 -DA:74,10 -DA:75,8 -DA:76,6 -DA:80,2 -DA:84,2 -DA:85,6 -DA:86,6 -DA:88,6 -DA:89,6 -DA:90,6 -DA:94,4 -DA:96,28 -DA:106,3 -DA:113,1 -DA:114,1 -DA:115,2 -DA:116,1 -DA:117,2 -DA:118,3 -DA:122,0 -DA:123,0 -DA:126,2 -DA:128,2 -DA:129,2 -DA:130,4 -DA:131,10 -DA:132,2 -DA:136,1 -DA:140,1 -DA:141,2 -DA:142,2 -DA:143,1 -DA:144,2 -DA:148,2 -DA:149,10 -LF:59 -LH:48 +DA:36,0 +DA:38,0 +DA:48,1 +DA:49,1 +DA:50,3 +DA:51,1 +DA:52,1 +DA:54,1 +DA:56,1 +LF:19 +LH:11 end_of_record -SF:lib/src/attributes/gradient/gradient_dto.dart -DA:34,5 -DA:38,3 -DA:39,3 -DA:40,3 -DA:42,1 -DA:43,1 -DA:45,0 -DA:46,0 -DA:49,0 -DA:56,3 -DA:57,3 -DA:69,0 -DA:70,0 -DA:121,5 -DA:130,4 -DA:131,4 -DA:132,4 -DA:133,4 -DA:134,4 -DA:135,4 -DA:136,12 -DA:137,4 -DA:141,0 -DA:142,0 -DA:145,3 -DA:147,3 -DA:148,3 -DA:149,3 -DA:150,16 -DA:151,6 -DA:152,3 -DA:153,3 -DA:157,1 -DA:161,1 -DA:162,1 -DA:163,1 -DA:164,1 -DA:165,2 -DA:166,3 -DA:167,3 -DA:171,4 -DA:172,28 -DA:230,2 -DA:241,2 -DA:242,2 -DA:243,2 -DA:244,2 -DA:245,2 -DA:246,2 -DA:247,2 -DA:248,2 -DA:249,6 -DA:250,2 -DA:254,0 -DA:255,0 -DA:258,2 -DA:260,2 -DA:261,2 -DA:262,2 -DA:263,11 -DA:264,5 -DA:265,2 -DA:266,2 -DA:267,2 -DA:268,2 -DA:272,0 -DA:276,0 -DA:277,0 -DA:278,0 -DA:279,0 -DA:280,0 -DA:281,0 -DA:282,0 -DA:283,0 -DA:284,0 -DA:288,2 -DA:290,18 -DA:347,1 -DA:357,1 -DA:358,1 -DA:359,1 -DA:360,1 -DA:361,1 -DA:362,1 -DA:363,1 -DA:364,3 -DA:365,1 -DA:369,0 -DA:370,0 -DA:373,1 -DA:375,1 -DA:376,1 -DA:377,1 -DA:378,1 -DA:379,6 -DA:380,4 -DA:381,1 -DA:382,1 -DA:386,0 -DA:390,0 -DA:391,0 -DA:392,0 -DA:393,0 -DA:394,0 -DA:395,0 -DA:396,0 -DA:397,0 -DA:401,1 -DA:403,8 -LF:109 -LH:79 +SF:lib/src/utils/context_variant_util/on_brightness_util.dart +DA:10,9 +DA:13,9 +DA:20,3 +DA:21,3 +DA:22,9 +DA:23,3 +DA:24,9 +LF:7 +LH:7 end_of_record -SF:lib/src/attributes/spacing/spacing_dto.dart -DA:10,8 +SF:lib/src/utils/context_variant_util/on_directionality_util.dart +DA:7,3 +DA:10,3 DA:19,1 DA:20,1 -DA:21,1 -DA:22,1 +DA:21,3 +DA:22,3 +LF:6 +LH:6 +end_of_record +SF:lib/src/utils/context_variant_util/on_helper_util.dart +DA:12,2 +DA:13,2 +DA:14,4 +DA:15,6 +LF:4 +LH:4 +end_of_record +SF:lib/src/utils/context_variant_util/on_orientation_util.dart +DA:9,3 +DA:14,3 DA:23,1 DA:24,1 +DA:25,3 +DA:26,1 +DA:27,2 +LF:7 +LH:7 +end_of_record +SF:lib/src/utils/decorators_util.dart +DA:21,0 +DA:22,0 +DA:24,1 DA:25,1 -DA:27,1 -DA:28,1 -DA:29,1 -DA:30,1 -DA:31,1 -DA:32,1 -DA:36,0 -DA:43,0 -DA:44,0 -DA:47,3 -DA:51,2 +DA:32,74 +DA:37,2 +DA:38,0 +DA:39,2 +DA:41,1 +DA:42,1 +DA:47,74 +DA:48,3 +DA:49,3 +DA:50,3 DA:52,3 -DA:53,3 -DA:54,3 -DA:55,3 -DA:56,4 -DA:57,4 -DA:61,4 -DA:63,4 -DA:64,1 -DA:65,3 -DA:66,3 -DA:67,3 -DA:68,3 -DA:70,4 -DA:71,12 -DA:72,12 -DA:73,12 -DA:74,12 -LF:37 -LH:34 +DA:56,74 +LF:16 +LH:13 end_of_record -SF:lib/src/attributes/strut_style/strut_style_dto.dart -DA:17,7 -DA:28,3 -DA:29,3 -DA:30,3 -DA:31,3 +SF:lib/src/utils/helper_util.dart +DA:8,149 +DA:10,1 DA:32,3 -DA:33,3 -DA:34,3 -DA:35,3 -DA:36,3 -DA:37,3 -DA:41,0 -DA:42,0 -DA:45,3 -DA:49,2 -DA:50,3 -DA:51,4 -DA:52,4 -DA:53,3 -DA:54,4 +DA:35,1 +LF:4 +LH:4 +end_of_record +SF:lib/src/variants/context_variant.dart +DA:50,11 +DA:52,3 +DA:75,3 +DA:78,3 +DA:81,6 +DA:84,1 +DA:85,3 +DA:90,2 +LF:8 +LH:8 +end_of_record +SF:lib/src/variants/multi_variant.dart +DA:57,3 +DA:59,3 +DA:63,3 +DA:64,15 +DA:65,12 +DA:67,3 +DA:73,3 +DA:74,3 +DA:80,2 +DA:81,2 +DA:84,0 +DA:85,0 +DA:101,2 +DA:102,6 +DA:104,4 +DA:105,2 +DA:106,0 +DA:125,2 +DA:126,2 +DA:127,4 +DA:129,4 +DA:130,4 +DA:131,2 +DA:149,1 +DA:150,2 +DA:152,2 +DA:153,4 +DA:154,4 +DA:155,4 +DA:162,1 +DA:185,1 +DA:188,1 +DA:190,2 +DA:193,0 +DA:194,0 +LF:35 +LH:30 +end_of_record +SF:lib/src/variants/variant.dart +DA:45,77 +DA:57,3 +DA:69,3 +DA:75,1 +DA:97,1 +DA:100,1 +DA:102,2 +DA:105,3 +DA:106,6 +LF:9 +LH:9 +end_of_record +SF:lib/src/widgets/empty_widget.dart +DA:4,1 +DA:6,0 +LF:2 +LH:1 +end_of_record +SF:lib/src/widgets/pressable/gesture_state.notifier.dart +DA:12,4 +DA:19,60 +DA:25,2 +DA:31,2 +DA:32,0 +DA:33,0 +DA:34,0 +DA:35,0 +DA:39,1 +DA:40,5 DA:55,3 -DA:56,3 -DA:57,4 -DA:61,5 -DA:65,5 -DA:66,6 -DA:67,7 -DA:68,5 -DA:69,6 -DA:70,6 -DA:71,6 -DA:72,6 -DA:73,7 -DA:77,4 -DA:78,4 -DA:79,4 -DA:80,4 -DA:81,4 -DA:82,4 -DA:83,4 -DA:84,4 -DA:85,4 -DA:86,4 -LF:43 -LH:41 +DA:61,3 +DA:63,3 +DA:64,3 +DA:69,1 +DA:71,3 +LF:16 +LH:12 end_of_record -SF:lib/src/attributes/strut_style/strut_style_util.dart -DA:10,1 -DA:11,0 -DA:13,1 -DA:14,3 -DA:17,1 -DA:18,3 +SF:lib/src/widgets/pressable/gesture_util.dart +DA:5,3 +DA:6,3 +DA:8,3 +DA:9,6 +DA:11,3 +DA:13,4 +DA:16,3 +DA:18,4 DA:21,1 -DA:22,3 -DA:25,1 -DA:26,3 -DA:29,1 -DA:30,1 -DA:31,2 -DA:35,2 -DA:37,2 +DA:22,1 +DA:23,3 +DA:24,4 +DA:28,2 +DA:29,2 +DA:30,6 +DA:31,8 +LF:16 +LH:16 +end_of_record +SF:lib/src/widgets/pressable/gesture_widget.dart +DA:8,0 +DA:32,0 +DA:34,0 +DA:35,0 +DA:36,0 +DA:37,0 +DA:38,0 DA:39,0 DA:40,0 -DA:42,1 -DA:52,1 -DA:63,2 -LF:20 -LH:17 -end_of_record -SF:lib/src/attributes/text_style/text_style_dto.dart -DA:41,5 -DA:65,0 -DA:88,1 -DA:89,1 -DA:90,1 +DA:41,0 +DA:42,0 +DA:48,1 +DA:72,1 +DA:73,1 +DA:84,1 +DA:86,1 +DA:87,4 +DA:88,3 DA:91,1 -DA:92,2 -DA:93,1 -DA:94,1 +DA:92,4 DA:95,1 -DA:96,1 -DA:97,1 DA:98,1 -DA:99,1 DA:100,1 -DA:101,1 -DA:102,1 -DA:103,1 -DA:104,1 -DA:105,1 -DA:106,1 -DA:107,1 -DA:108,1 -DA:109,1 -DA:110,1 -DA:114,0 -DA:115,0 -DA:118,10 +DA:105,0 +DA:107,0 +DA:108,0 +DA:109,0 +DA:111,0 +DA:112,0 +DA:116,1 +DA:118,3 DA:120,1 -DA:124,2 -DA:128,1 -DA:129,2 -DA:130,2 -DA:131,1 -DA:132,2 -DA:133,1 -DA:134,1 -DA:135,1 -DA:136,2 -DA:137,2 -DA:138,1 +DA:123,0 +DA:124,0 +DA:125,0 +DA:126,0 +DA:129,0 +DA:132,0 +DA:133,0 +DA:134,0 +DA:137,1 DA:139,1 -DA:140,1 -DA:142,2 +DA:141,2 DA:143,1 -DA:144,1 DA:145,1 -DA:146,2 -DA:147,1 -DA:148,1 -DA:149,1 +DA:146,1 +DA:149,2 DA:150,2 DA:151,1 -DA:152,1 -DA:156,5 -DA:158,5 +DA:152,0 +DA:153,0 +DA:154,2 +DA:155,0 +DA:156,0 +DA:157,2 +DA:158,0 DA:159,0 -DA:160,5 -DA:161,10 -DA:162,6 -DA:163,5 -DA:164,5 -DA:165,5 -DA:166,5 -DA:167,5 -DA:168,5 -DA:169,5 -DA:170,5 -DA:171,5 -DA:172,5 -DA:173,9 -DA:174,5 -DA:175,5 -DA:176,7 -DA:177,5 -DA:178,5 -DA:179,5 -DA:180,5 -DA:181,5 -DA:185,2 -DA:186,2 -DA:187,2 -DA:188,2 -DA:189,2 -DA:190,2 -DA:191,2 -DA:192,2 -DA:193,2 -DA:194,2 -DA:195,2 -DA:196,2 -DA:197,2 -DA:198,2 -DA:199,2 -DA:200,2 -DA:201,2 -DA:202,2 -DA:203,2 -DA:204,2 -DA:205,2 -DA:206,2 -DA:207,2 -DA:208,2 -DA:215,5 -DA:217,4 -DA:240,8 -DA:265,5 -DA:266,10 -DA:269,0 -DA:270,0 -DA:273,1 -DA:274,2 -DA:277,0 -DA:278,0 -DA:287,5 -DA:289,5 -DA:290,15 -DA:291,7 -DA:292,5 -DA:295,2 -DA:297,4 -DA:300,2 -DA:301,4 -LF:123 -LH:115 +DA:160,2 +DA:161,1 +DA:163,1 +DA:164,2 +DA:165,0 +DA:166,0 +DA:167,2 +DA:168,1 +DA:169,1 +DA:170,1 +DA:173,1 +DA:175,2 +LF:69 +LH:36 end_of_record -SF:lib/src/helpers/build_context_ext.dart -DA:8,8 -DA:13,2 -DA:16,2 -DA:19,0 -DA:22,3 -DA:25,2 -DA:28,3 -DA:31,3 -DA:34,2 -DA:37,3 -DA:40,3 -DA:43,3 -LF:12 -LH:11 +SF:lib/src/widgets/styled_widget.dart +DA:9,4 +DA:23,4 +DA:24,5 +DA:26,8 +DA:28,0 +DA:30,8 +DA:38,0 +LF:7 +LH:5 +end_of_record +SF:lib/src/helpers/string_ext.dart +DA:25,36 +DA:27,24 +DA:28,12 +DA:29,12 +DA:30,12 +DA:36,12 +DA:37,12 +DA:38,12 +DA:39,24 +DA:41,36 +DA:42,12 +DA:43,60 +DA:45,24 +DA:49,12 +DA:52,24 +DA:53,24 +DA:56,24 +DA:57,12 +DA:65,6 +DA:68,6 +DA:71,3 +DA:72,15 +DA:73,3 +DA:74,9 +DA:77,3 +DA:81,18 +DA:84,4 +DA:85,4 +DA:86,8 +DA:87,8 +DA:89,12 +DA:90,20 +DA:94,8 +DA:97,8 +DA:100,44 +DA:103,3 +DA:104,15 +DA:107,1 +DA:108,2 +DA:109,1 +DA:111,3 +DA:113,1 +DA:120,55 +DA:123,10 +LF:44 +LH:44 end_of_record SF:lib/src/helpers/deep_collection_equality.dart -DA:2,65 -DA:3,5 -DA:4,15 -DA:5,8 -DA:6,16 -DA:14,6 -DA:16,18 -DA:18,12 -DA:19,18 -DA:20,18 +DA:2,75 +DA:3,6 +DA:4,18 +DA:5,10 +DA:6,20 +DA:14,5 +DA:16,15 +DA:18,10 +DA:19,15 +DA:20,15 DA:31,1 DA:32,3 DA:33,2 @@ -3751,12 +3761,12 @@ DA:34,1 DA:42,13 DA:44,33 DA:46,10 -DA:47,5 -DA:48,6 +DA:47,6 +DA:48,5 DA:49,1 -DA:50,6 -DA:51,6 -DA:54,6 +DA:50,5 +DA:51,5 +DA:54,5 DA:57,1 DA:58,1 DA:59,3 @@ -3770,6 +3780,22 @@ DA:72,1 LF:33 LH:33 end_of_record +SF:lib/src/helpers/build_context_ext.dart +DA:8,2 +DA:13,2 +DA:16,2 +DA:19,0 +DA:22,3 +DA:25,2 +DA:28,3 +DA:31,3 +DA:34,2 +DA:37,3 +DA:40,3 +DA:43,3 +LF:12 +LH:11 +end_of_record SF:lib/src/helpers/lerp_helpers.dart DA:15,1 DA:16,5 diff --git a/demo/lib/app_shell.dart b/demo/lib/app_shell.dart index d1b22cba4..8d1996e02 100644 --- a/demo/lib/app_shell.dart +++ b/demo/lib/app_shell.dart @@ -29,7 +29,7 @@ class AppShell extends HookConsumerWidget { final darkMode = ref.watch(darkModeProvider); return MixTheme( - data: MixThemeData(), + data: MixThemeData.withMaterialTokens(), child: AdaptiveNavigationScaffold( appBar: AppBar( title: const Text('Mix Gallery'), diff --git a/demo/lib/components/box.dart b/demo/lib/components/box.dart new file mode 100644 index 000000000..afc567099 --- /dev/null +++ b/demo/lib/components/box.dart @@ -0,0 +1,51 @@ +import 'package:flutter/material.dart'; +import 'package:mix/mix.dart'; +import 'package:widgetbook_annotation/widgetbook_annotation.dart' as widgetbook; + +@widgetbook.UseCase( + name: 'Box with BoxDecoration', + type: Box, +) +Widget boxDecorationContainer(BuildContext context) { + final boxStyle = StyleMix( + box.color.red(), + onPress( + box.color.blue(), + ), + opacity(0.5), + (onHover & onDark)( + box.color.orange(), + ), + onHover( + box.color.grey(), + ), + box.padding.horizontal(15.0), + box.padding.vertical(8.0), + box.borderRadius(5), + box.width(100), + box.height(100), + onDark( + box.color.purple(), + ), + box.alignment.center(), + text.style.bold(), + ); + + return Center( + child: Column( + children: [ + GestureBox( + style: boxStyle, + onPressed: () {}, + child: const StyledText('Press me'), + ), + Pressable( + child: AnimatedBox( + style: boxStyle, + child: const StyledText('Press me Animated'), + ), + ) + ], + ), + ); +} diff --git a/demo/lib/components/examples/box/box.dart b/demo/lib/components/examples/box/box.dart deleted file mode 100644 index 9da276a16..000000000 --- a/demo/lib/components/examples/box/box.dart +++ /dev/null @@ -1,22 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:mix/mix.dart'; - -import 'box.mix.dart'; - -class BoxExample extends StatelessWidget { - const BoxExample({Key? key}) : super(key: key); - - @override - Widget build(BuildContext context) { - return SingleChildScrollView( - child: Column( - children: [ - StyledContainer( - style: button, - child: const StyledText('Details'), - ), - ], - ), - ); - } -} diff --git a/demo/lib/components/examples/box/box.mix.dart b/demo/lib/components/examples/box/box.mix.dart deleted file mode 100644 index acb8c762b..000000000 --- a/demo/lib/components/examples/box/box.mix.dart +++ /dev/null @@ -1,16 +0,0 @@ -import 'package:mix/mix.dart'; - -StyleMix get button { - return StyleMix( - text.style.as($textStyles.bodyMedium), - text.style.bold(), - text.style(fontSize: 16.0), - backgroundColor($colors.primary), - onHover( - backgroundColor($colors.secondary), - ), - padding.horizontal(15.0), - padding.vertical(8.0), - borderRadius(5), - ); -} diff --git a/demo/lib/docs/variants/and_operator.dart b/demo/lib/docs/variants/and_operator.dart index 753ee238b..d04f3095b 100644 --- a/demo/lib/docs/variants/and_operator.dart +++ b/demo/lib/docs/variants/and_operator.dart @@ -7,12 +7,12 @@ class VariantsAndOperator extends StatelessWidget { @override Widget build(BuildContext context) { final mix = StyleMix( - padding(20.0), - textStyle(color: Colors.white), + box.padding(20.0), + text.style(color: Colors.white), (onHover & onEnabled)( // When it's hovering AND pressing - textStyle(color: Colors.black), - bold(), + text.style(color: Colors.black), + text.style.bold(), ), ); diff --git a/demo/lib/docs/variants/catalog/pressable.dart b/demo/lib/docs/variants/catalog/pressable.dart index 67c3664a4..af824f720 100644 --- a/demo/lib/docs/variants/catalog/pressable.dart +++ b/demo/lib/docs/variants/catalog/pressable.dart @@ -9,19 +9,23 @@ class VariantsCatalogPressable extends StatelessWidget { return Row(children: [ buildBlock( 'Hover', - StyleMix(onHover( - border(color: $colors.primary, width: 2), - padding(4.0), - )), + StyleMix( + onHover( + box.border(color: $colors.primary(), width: 2), + box.padding(4.0), + ), + ), const Text('Hover this to show the highlight'), ), const VerticalDivider(), buildBlock( 'Focus', - StyleMix(onFocus( - border(color: $colors.primary, width: 2), - padding(4.0), - )), + StyleMix( + onFocus( + box.border(color: $colors.primary(), width: 2), + box.padding(4.0), + ), + ), const Text('Focus this to show the highlight'), ), const VerticalDivider(), @@ -29,11 +33,11 @@ class VariantsCatalogPressable extends StatelessWidget { 'Press', StyleMix( onPress( - border( - color: $colors.primary, + box.border( + color: $colors.primary(), width: 2, ), - padding(4.0), + box.padding(4.0), ), ), const Text('Press this to show the highlight'), diff --git a/demo/lib/docs/variants/default.dart b/demo/lib/docs/variants/default.dart index bd027de63..0120580e9 100644 --- a/demo/lib/docs/variants/default.dart +++ b/demo/lib/docs/variants/default.dart @@ -7,11 +7,11 @@ class VariantsDefaultExample extends StatelessWidget { @override Widget build(BuildContext context) { final style = StyleMix( - backgroundColor($colors.secondary), - textStyle(color: $colors.onSecondary), + box.color($colors.secondary()), + text.style.color.of($colors.onSecondary), onHover( - backgroundColor($colors.primary), - textStyle(color: $colors.onPrimary), + box.color.of($colors.primary), + text.style(color: $colors.onPrimary()), ), ); diff --git a/demo/lib/docs/variants/or_operator.dart b/demo/lib/docs/variants/or_operator.dart index 29c7e4685..d695916e2 100644 --- a/demo/lib/docs/variants/or_operator.dart +++ b/demo/lib/docs/variants/or_operator.dart @@ -7,12 +7,12 @@ class VariantsOrOperator extends StatelessWidget { @override Widget build(BuildContext context) { final mix = StyleMix( - padding(20.0), + box.padding(20.0), + // Whether it's small OR medium (onSmall | onMedium)( - // Whether it's small OR medium - width(300), - height(400), - backgroundColor(Colors.white), + box.width(300), + box.height(400), + box.color.white(), ), ); diff --git a/demo/lib/main.dart b/demo/lib/main.dart index 336f01b54..fe4263cde 100644 --- a/demo/lib/main.dart +++ b/demo/lib/main.dart @@ -2,7 +2,6 @@ import 'package:desktop_window/desktop_window.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; -import 'package:mix/mix.dart'; import 'app_shell.dart'; import 'docs/docs.dart'; @@ -66,11 +65,8 @@ class MyApp extends StatelessWidget { }); }, builder: (context, child) { - return MixTheme( - data: MixThemeData(), - child: Material( - child: child ?? const SizedBox.shrink(), - ), + return Material( + child: child ?? const SizedBox.shrink(), ); }, ); diff --git a/demo/lib/styles.dart b/demo/lib/styles.dart index 4388c6ff3..dd14bff7b 100644 --- a/demo/lib/styles.dart +++ b/demo/lib/styles.dart @@ -19,5 +19,5 @@ StyleMix get flexAlign => StyleMix( flex.mainAxisAlignment.start(), flex.crossAxisAlignment.start(), flex.mainAxisSize.max(), - width(double.infinity), + box.width(double.infinity), ); diff --git a/demo/lib/views/basic_example.dart b/demo/lib/views/basic_example.dart index 8862e106a..e4504076a 100644 --- a/demo/lib/views/basic_example.dart +++ b/demo/lib/views/basic_example.dart @@ -10,22 +10,22 @@ class BasicExample extends HookWidget { @override Widget build(BuildContext context) { final mix = StyleMix.create([ - height(300), - width(300), - borderRadius(10), - elevation(2), - margin(10), - alignment.center(), - backgroundColor(Colors.purple), + box.height(300), + box.width(300), + box.borderRadius(10), + box.elevation(2), + box.margin(10), + box.alignment.center(), + box.color(Colors.purple), text.style(color: Colors.white), onPress( - backgroundColor(Colors.black), + box.color(Colors.black), ), onHover( opacity(0.5), ), onLongPress( - backgroundColor(Colors.green), + box.color(Colors.green), ), ]); @@ -73,10 +73,10 @@ class BasicExample extends HookWidget { style: onSurfaceMix.merge( StyleMix( onLight( - text.style(color: $colors.error), + text.style.color.of($colors.error), ), onDark( - text.style(color: $colors.primary), + text.style.color.of($colors.primary), ), ), ), @@ -111,7 +111,7 @@ class BasicExample extends HookWidget { style: onSurfaceMix.merge( StyleMix( icon(size: 70), - icon(color: $colors.secondary), + icon.color.of($colors.secondary), ), ), ), diff --git a/demo/lib/views/button_example.dart b/demo/lib/views/button_example.dart index eebf85ac3..113d468a2 100644 --- a/demo/lib/views/button_example.dart +++ b/demo/lib/views/button_example.dart @@ -22,7 +22,7 @@ class ButtonSizeVariants { } StyleMix get _baseStyle => StyleMix( - borderRadius(4), + box.borderRadius(4), onPress( scale(0.95), ), @@ -31,28 +31,28 @@ StyleMix get _baseStyle => StyleMix( // added because of lack of style parameters (yellow lines) decoration: TextDecoration.none, fontWeight: FontWeight.w600, - fontFamily: $textStyles.bodySmall.fontFamily, ), + text.style.of($textStyles.bodySmall), flex.mainAxisSize.min(), ButtonSizeVariants.small( - padding.horizontal(10), - padding.vertical(10), + box.padding.horizontal(10), + box.padding.vertical(10), text.style( fontSize: 16, ), icon(size: 24), ), ButtonSizeVariants.medium( - padding.horizontal(4), - padding.vertical(16), + box.padding.horizontal(4), + box.padding.vertical(16), text.style( fontSize: 16, ), icon(size: 24), ), ButtonSizeVariants.large( - padding.horizontal(4), - padding.vertical(2), + box.padding.horizontal(4), + box.padding.vertical(2), text.style( fontSize: 16, ), @@ -143,12 +143,12 @@ StyleMix get _style => StyleMix( text.style( color: const Color(0xFFFF004C), ), - backgroundColor(const Color(0x0F07E2FF)), - icon(color: $colors.onBackground), + box.color(const Color(0x0F07E2FF)), + icon.color.of($colors.onBackground), onDisabled( - backgroundColor($colors.background.withOpacity(0.3)), - text.style(color: $colors.onBackground.withOpacity(0.3)), - icon(color: $colors.onBackground.withOpacity(0.3)), + box.color.of($colors.background), + text.style.color.of($colors.onBackground), + icon.color.of($colors.onBackground), ), ); diff --git a/demo/lib/views/example.dart b/demo/lib/views/example.dart index 1046df6cd..35c0b2deb 100644 --- a/demo/lib/views/example.dart +++ b/demo/lib/views/example.dart @@ -61,18 +61,18 @@ class CustomMixWidget extends StatelessWidget { @override Widget build(BuildContext context) { final style = StyleMix( - height(100), - margin.vertical(10), - elevation(10), - borderRadius(10), - backgroundColor($colors.primary), - text.style.as($textStyles.bodyMedium), - text.style(color: $colors.onPrimary), + box.height(100), + box.margin.vertical(10), + box.elevation(10), + box.borderRadius(10), + box.color($colors.primary()), + text.style.of($textStyles.bodyMedium), + text.style(color: $colors.onPrimary()), onHover( - elevation(2), - padding(20), - backgroundColor($colors.secondary), - text.style(color: $colors.onSecondary), + box.elevation(2), + box.padding(20), + box.color.of($colors.secondary), + text.style.color.of($colors.onSecondary), ), ); diff --git a/demo/lib/views/layout_example.dart b/demo/lib/views/layout_example.dart index e4126383f..f3ee3fb42 100644 --- a/demo/lib/views/layout_example.dart +++ b/demo/lib/views/layout_example.dart @@ -4,13 +4,13 @@ import 'package:mix/mix.dart'; import '../styles.dart'; StyleMix get mix => StyleMix( - height(300), - width(300), - borderRadius(10), - elevation(2), - backgroundColor($colors.surface), - alignment.center(), - text.style(color: $colors.onSurface), + box.height(300), + box.width(300), + box.borderRadius(10), + box.elevation(2), + box.color.of($colors.surface), + box.alignment.center(), + text.style.color.of($colors.onSurface), ); class LayoutExample extends StatelessWidget { @@ -42,9 +42,9 @@ class LayoutExample extends StatelessWidget { StyledContainer( style: mix.merge( StyleMix( - width(200), - height(100), - backgroundColor(Colors.green), + box.width(200), + box.height(100), + box.color(Colors.green), ), ), child: StyledText( diff --git a/demo/lib/views/typography_example.dart b/demo/lib/views/typography_example.dart index 3f7b4d7b5..a0b22ba1d 100644 --- a/demo/lib/views/typography_example.dart +++ b/demo/lib/views/typography_example.dart @@ -4,15 +4,15 @@ import 'package:mix/mix.dart'; import '../styles.dart'; StyleMix get button => StyleMix( - text.style.as($textStyles.bodyMedium), - padding.top(10), + text.style.of($textStyles.bodyMedium), + box.padding.top(10), text.style.bold(), text.style(fontSize: 6.0), - backgroundColor($colors.primary), + box.color.of($colors.primary), onHover( - backgroundColor($colors.secondary), + box.color.of($colors.secondary), ), - padding(8, 15), + box.padding(8, 15), ); class TypographyExample extends StatelessWidget { @@ -37,8 +37,8 @@ class TypographyExample extends StatelessWidget { "This is a StyledText with a custom textStyle!", style: headingMix.merge( StyleMix( - textStyle( - color: $colors.surface, + text.style( + color: $colors.surface(), fontWeight: FontWeight.bold, fontStyle: FontStyle.italic, letterSpacing: 2, @@ -46,14 +46,14 @@ class TypographyExample extends StatelessWidget { height: 1.5, shadows: [ Shadow( - color: $colors.secondary, + color: $colors.secondary(), offset: const Offset(2, 2), blurRadius: 2, ), ], ), onDark( - textStyle(color: $colors.surface), + text.style.color.of($colors.surface), ), ), ), diff --git a/demo/lib/views/variants.dart b/demo/lib/views/variants.dart index 144d08e23..85afe44cf 100644 --- a/demo/lib/views/variants.dart +++ b/demo/lib/views/variants.dart @@ -10,29 +10,29 @@ class VariantsExample extends HookWidget { @override Widget build(BuildContext context) { final baseStyle = StyleMix( - height(300), - width(300), - borderRadius(10), - elevation(2), - margin(10), - alignment.center(), + box.height(300), + box.width(300), + box.borderRadius(10), + box.elevation(2), + box.margin(10), + box.alignment.center(), ); final style = StyleMix( - backgroundColor($colors.primary), - text.style(color: $colors.onPrimary), + box.color($colors.primary()), + text.style(color: $colors.onPrimary()), onHover( - backgroundColor($colors.secondary), - text.style(color: $colors.onPrimary), + box.color($colors.secondary()), + text.style(color: $colors.onPrimary()), ), ).merge(baseStyle); final onDarkStyle = StyleMix( - backgroundColor($colors.primary), - text.style(color: $colors.onPrimary), + box.color($colors.primary()), + text.style(color: $colors.onPrimary()), onDark( - backgroundColor(Colors.red), - text.style(color: $colors.onPrimary), + box.color(Colors.red), + text.style(color: $colors.onPrimary()), ), ).merge(baseStyle); diff --git a/demo/lib/widgetbook.dart b/demo/lib/widgetbook.dart new file mode 100644 index 000000000..e700902ff --- /dev/null +++ b/demo/lib/widgetbook.dart @@ -0,0 +1,47 @@ +// widgetbook.dart + +import 'package:flutter/material.dart'; +import 'package:mix/mix.dart'; +import 'package:widgetbook/widgetbook.dart'; +import 'package:widgetbook_annotation/widgetbook_annotation.dart' as widgetbook; + +// Import the generated directories variable +import 'widgetbook.directories.g.dart'; + +final materialTheme = MaterialThemeAddon( + themes: [ + WidgetbookTheme( + name: 'Light', + data: ThemeData.light(), + ), + WidgetbookTheme( + name: 'Dark', + data: ThemeData.dark(), + ), + ], + initialTheme: WidgetbookTheme( + name: 'Light', + data: ThemeData.light(), + ), +); + +void main() { + runApp(const WidgetbookApp()); +} + +@widgetbook.App() +class WidgetbookApp extends StatelessWidget { + const WidgetbookApp({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return MixTheme( + data: MixThemeData.withMaterialTokens(), + child: Widgetbook.material( + directories: directories, + addons: [materialTheme], + integrations: [], + ), + ); + } +} diff --git a/demo/lib/widgetbook.directories.g.dart b/demo/lib/widgetbook.directories.g.dart new file mode 100644 index 000000000..63c2a28b1 --- /dev/null +++ b/demo/lib/widgetbook.directories.g.dart @@ -0,0 +1,33 @@ +// coverage:ignore-file +// ignore_for_file: type=lint +// ignore_for_file: unused_import, prefer_relative_imports, directives_ordering + +// GENERATED CODE - DO NOT MODIFY BY HAND + +// ************************************************************************** +// AppGenerator +// ************************************************************************** + +// ignore_for_file: no_leading_underscores_for_library_prefixes +import 'package:demo/components/box.dart' as _i2; +import 'package:widgetbook/widgetbook.dart' as _i1; + +final directories = <_i1.WidgetbookNode>[ + _i1.WidgetbookFolder( + name: 'recipes', + children: [ + _i1.WidgetbookFolder( + name: 'container', + children: [ + _i1.WidgetbookLeafComponent( + name: 'StyledContainer', + useCase: _i1.WidgetbookUseCase( + name: 'Box with BoxDecoration', + builder: _i2.boxDecorationContainer, + ), + ) + ], + ) + ], + ) +]; diff --git a/demo/pubspec.lock b/demo/pubspec.lock index 07de17759..ad049d730 100644 --- a/demo/pubspec.lock +++ b/demo/pubspec.lock @@ -1,6 +1,22 @@ # Generated by pub # See https://dart.dev/tools/pub/glossary#lockfile packages: + _fe_analyzer_shared: + dependency: transitive + description: + name: _fe_analyzer_shared + sha256: eb376e9acf6938204f90eb3b1f00b578640d3188b4c8a8ec054f9f479af8d051 + url: "https://pub.dev" + source: hosted + version: "64.0.0" + accessibility_tools: + dependency: transitive + description: + name: accessibility_tools + sha256: "0a16adc8dfa3a7ebd38775135d86443011a65d4ecbb438913e4992b5d29135fe" + url: "https://pub.dev" + source: hosted + version: "1.0.0" adaptive_breakpoints: dependency: transitive description: @@ -17,6 +33,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.0.9" + analyzer: + dependency: transitive + description: + name: analyzer + sha256: "69f54f967773f6c26c7dcb13e93d7ccee8b17a641689da39e878d5cf13b06893" + url: "https://pub.dev" + source: hosted + version: "6.2.0" archive: dependency: transitive description: @@ -49,6 +73,70 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.1" + build: + dependency: transitive + description: + name: build + sha256: "80184af8b6cb3e5c1c4ec6d8544d27711700bc3e6d2efad04238c7b5290889f0" + url: "https://pub.dev" + source: hosted + version: "2.4.1" + build_config: + dependency: transitive + description: + name: build_config + sha256: bf80fcfb46a29945b423bd9aad884590fb1dc69b330a4d4700cac476af1708d1 + url: "https://pub.dev" + source: hosted + version: "1.1.1" + build_daemon: + dependency: transitive + description: + name: build_daemon + sha256: "0343061a33da9c5810b2d6cee51945127d8f4c060b7fbdd9d54917f0a3feaaa1" + url: "https://pub.dev" + source: hosted + version: "4.0.1" + build_resolvers: + dependency: transitive + description: + name: build_resolvers + sha256: "64e12b0521812d1684b1917bc80945625391cb9bdd4312536b1d69dcb6133ed8" + url: "https://pub.dev" + source: hosted + version: "2.4.1" + build_runner: + dependency: "direct dev" + description: + name: build_runner + sha256: "67d591d602906ef9201caf93452495ad1812bea2074f04e25dbd7c133785821b" + url: "https://pub.dev" + source: hosted + version: "2.4.7" + build_runner_core: + dependency: transitive + description: + name: build_runner_core + sha256: c9e32d21dd6626b5c163d48b037ce906bbe428bc23ab77bcd77bb21e593b6185 + url: "https://pub.dev" + source: hosted + version: "7.2.11" + built_collection: + dependency: transitive + description: + name: built_collection + sha256: "376e3dd27b51ea877c28d525560790aee2e6fbb5f20e2f85d5081027d94e2100" + url: "https://pub.dev" + source: hosted + version: "5.1.1" + built_value: + dependency: transitive + description: + name: built_value + sha256: "69acb7007eb2a31dc901512bfe0f7b767168be34cb734835d54c070bfa74c1b2" + url: "https://pub.dev" + source: hosted + version: "8.8.0" characters: dependency: transitive description: @@ -81,6 +169,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.1.1" + code_builder: + dependency: transitive + description: + name: code_builder + sha256: b2151ce26a06171005b379ecff6e08d34c470180ffe16b8e14b6d52be292b55f + url: "https://pub.dev" + source: hosted + version: "4.8.0" collection: dependency: transitive description: @@ -129,6 +225,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.6" + dart_style: + dependency: transitive + description: + name: dart_style + sha256: "40ae61a5d43feea6d24bd22c0537a6629db858963b99b4bc1c3db80676f32368" + url: "https://pub.dev" + source: hosted + version: "2.3.4" desktop_window: dependency: "direct main" description: @@ -137,6 +241,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.4.0" + device_frame: + dependency: transitive + description: + name: device_frame + sha256: afe76182aec178d171953d9b4a50a43c57c7cf3c77d8b09a48bf30c8fa04dd9d + url: "https://pub.dev" + source: hosted + version: "1.1.0" fake_async: dependency: transitive description: @@ -153,6 +265,22 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.0" + file: + dependency: transitive + description: + name: file + sha256: "5fc22d7c25582e38ad9a8515372cd9a93834027aacf1801cf01164dac0ffa08c" + url: "https://pub.dev" + source: hosted + version: "7.0.0" + fixnum: + dependency: transitive + description: + name: fixnum + sha256: "25517a4deb0c03aa0f32fd12db525856438902d9c16536311e76cdc57b31d7d1" + url: "https://pub.dev" + source: hosted + version: "1.1.0" flutter: dependency: "direct main" description: flutter @@ -208,6 +336,30 @@ packages: description: flutter source: sdk version: "0.0.0" + freezed_annotation: + dependency: transitive + description: + name: freezed_annotation + sha256: c3fd9336eb55a38cc1bbd79ab17573113a8deccd0ecbbf926cca3c62803b5c2d + url: "https://pub.dev" + source: hosted + version: "2.4.1" + frontend_server_client: + dependency: transitive + description: + name: frontend_server_client + sha256: "408e3ca148b31c20282ad6f37ebfa6f4bdc8fede5b74bc2f08d9d92b55db3612" + url: "https://pub.dev" + source: hosted + version: "3.2.0" + glob: + dependency: transitive + description: + name: glob + sha256: "0e7014b3b7d4dac1ca4d6114f82bf1782ee86745b9b42a92c9289c23d8a0ab63" + url: "https://pub.dev" + source: hosted + version: "2.1.2" google_fonts: dependency: "direct main" description: @@ -216,6 +368,14 @@ packages: url: "https://pub.dev" source: hosted version: "5.1.0" + graphs: + dependency: transitive + description: + name: graphs + sha256: aedc5a15e78fc65a6e23bcd927f24c64dd995062bcd1ca6eda65a3cff92a4d19 + url: "https://pub.dev" + source: hosted + version: "2.3.1" hooks_riverpod: dependency: "direct main" description: @@ -240,6 +400,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.1.0" + http_multi_server: + dependency: transitive + description: + name: http_multi_server + sha256: "97486f20f9c2f7be8f514851703d0119c3596d14ea63227af6f7a481ef2b2f8b" + url: "https://pub.dev" + source: hosted + version: "3.2.1" http_parser: dependency: transitive description: @@ -256,6 +424,22 @@ packages: url: "https://pub.dev" source: hosted version: "3.3.0" + inspector: + dependency: transitive + description: + name: inspector + sha256: "40ba0ac1c819c85139bfec9d1e283804581a8985c91f19d00e93212cf29226b1" + url: "https://pub.dev" + source: hosted + version: "2.1.0" + io: + dependency: transitive + description: + name: io + sha256: "2ec25704aba361659e10e3e5f5d672068d332fc8ac516421d483a11e5cbd061e" + url: "https://pub.dev" + source: hosted + version: "1.0.4" js: dependency: transitive description: @@ -280,6 +464,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.1" + logging: + dependency: transitive + description: + name: logging + sha256: "623a88c9594aa774443aa3eb2d41807a48486b5613e67599fb4c41c0ad47c340" + url: "https://pub.dev" + source: hosted + version: "1.2.0" matcher: dependency: transitive description: @@ -304,6 +496,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.9.1" + mime: + dependency: transitive + description: + name: mime + sha256: e4ff8e8564c03f255408decd16e7899da1733852a9110a58fe6d1b817684a63e + url: "https://pub.dev" + source: hosted + version: "1.0.4" mix: dependency: "direct main" description: @@ -311,6 +511,22 @@ packages: relative: true source: path version: "0.0.7" + nested: + dependency: transitive + description: + name: nested + sha256: "03bac4c528c64c95c722ec99280375a6f2fc708eec17c7b3f07253b626cd2a20" + url: "https://pub.dev" + source: hosted + version: "1.0.0" + package_config: + dependency: transitive + description: + name: package_config + sha256: "1c5b77ccc91e4823a5af61ee74e6b972db1ef98c2ff5a18d3161c982a55448bd" + url: "https://pub.dev" + source: hosted + version: "2.1.0" path: dependency: transitive description: @@ -399,6 +615,38 @@ packages: url: "https://pub.dev" source: hosted version: "3.7.3" + pool: + dependency: transitive + description: + name: pool + sha256: "20fe868b6314b322ea036ba325e6fc0711a22948856475e2c2b6306e8ab39c2a" + url: "https://pub.dev" + source: hosted + version: "1.5.1" + pub_semver: + dependency: transitive + description: + name: pub_semver + sha256: "40d3ab1bbd474c4c2328c91e3a7df8c6dd629b79ece4c4bd04bee496a224fb0c" + url: "https://pub.dev" + source: hosted + version: "2.1.4" + pubspec_parse: + dependency: transitive + description: + name: pubspec_parse + sha256: c63b2876e58e194e4b0828fcb080ad0e06d051cb607a6be51a9e084f47cb9367 + url: "https://pub.dev" + source: hosted + version: "1.2.3" + resizable_widget: + dependency: transitive + description: + name: resizable_widget + sha256: db2919754b93f386b9b3fb15e9f48f6c9d6d41f00a24397629133c99df86606a + url: "https://pub.dev" + source: hosted + version: "1.0.5" riverpod: dependency: transitive description: @@ -407,11 +655,35 @@ packages: url: "https://pub.dev" source: hosted version: "2.4.0" + shelf: + dependency: transitive + description: + name: shelf + sha256: ad29c505aee705f41a4d8963641f91ac4cee3c8fad5947e033390a7bd8180fa4 + url: "https://pub.dev" + source: hosted + version: "1.4.1" + shelf_web_socket: + dependency: transitive + description: + name: shelf_web_socket + sha256: "9ca081be41c60190ebcb4766b2486a7d50261db7bd0f5d9615f2d653637a84c1" + url: "https://pub.dev" + source: hosted + version: "1.0.4" sky_engine: dependency: transitive description: flutter source: sdk version: "0.0.99" + source_gen: + dependency: transitive + description: + name: source_gen + sha256: fc0da689e5302edb6177fdd964efcb7f58912f43c28c2047a808f5bfff643d16 + url: "https://pub.dev" + source: hosted + version: "1.4.0" source_span: dependency: transitive description: @@ -444,6 +716,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.1" + stream_transform: + dependency: transitive + description: + name: stream_transform + sha256: "14a00e794c7c11aa145a170587321aedce29769c08d7f58b1d141da75e3b1c6f" + url: "https://pub.dev" + source: hosted + version: "2.1.0" string_scanner: dependency: transitive description: @@ -468,6 +748,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.6.0" + timing: + dependency: transitive + description: + name: timing + sha256: "70a3b636575d4163c477e6de42f247a23b315ae20e86442bebe32d3cabf61c32" + url: "https://pub.dev" + source: hosted + version: "1.0.1" typed_data: dependency: transitive description: @@ -492,6 +780,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.4" + watcher: + dependency: transitive + description: + name: watcher + sha256: "3d2ad6751b3c16cf07c7fca317a1413b3f26530319181b37e3b9039b84fc01d8" + url: "https://pub.dev" + source: hosted + version: "1.1.0" web: dependency: transitive description: @@ -500,6 +796,38 @@ packages: url: "https://pub.dev" source: hosted version: "0.1.4-beta" + web_socket_channel: + dependency: transitive + description: + name: web_socket_channel + sha256: d88238e5eac9a42bb43ca4e721edba3c08c6354d4a53063afaa568516217621b + url: "https://pub.dev" + source: hosted + version: "2.4.0" + widgetbook: + dependency: "direct main" + description: + name: widgetbook + sha256: "37bb71322ed2b024b4b321f9ac0791f6b4510a9abcd42a108c11bec97ac4688a" + url: "https://pub.dev" + source: hosted + version: "3.5.0" + widgetbook_annotation: + dependency: "direct main" + description: + name: widgetbook_annotation + sha256: c2d881d0241525b36aa3777d0ac406d198528ed28b84ca73b7dd9f59189d6bb0 + url: "https://pub.dev" + source: hosted + version: "3.1.0" + widgetbook_generator: + dependency: "direct dev" + description: + name: widgetbook_generator + sha256: e60bb3ca46246bc8d5d3a0bed1994d90268b4913704a298093fcf7b6d781c6e0 + url: "https://pub.dev" + source: hosted + version: "3.3.0" win32: dependency: transitive description: @@ -534,4 +862,4 @@ packages: version: "3.1.2" sdks: dart: ">=3.1.0-185.0.dev <4.0.0" - flutter: ">=3.7.0" + flutter: ">=3.10.0" diff --git a/demo/pubspec.yaml b/demo/pubspec.yaml index 9a56482b5..0781eae19 100644 --- a/demo/pubspec.yaml +++ b/demo/pubspec.yaml @@ -20,6 +20,8 @@ dependencies: google_fonts: ^5.1.0 desktop_window: ^0.4.0 community_material_icon: ^5.9.55 + widgetbook_annotation: ^3.1.0 + widgetbook: ^3.5.0 dev_dependencies: flutter_test: @@ -27,6 +29,8 @@ dev_dependencies: flutter_lints: ^2.0.1 flutter_launcher_icons: ^0.10.0 flutter_native_splash: ^2.2.11 + widgetbook_generator: ^3.3.0 + build_runner: ^2.4.7 flutter: uses-material-design: true diff --git a/docs/doc_dto.md b/docs/doc_dto.md new file mode 100644 index 000000000..78c4df75b --- /dev/null +++ b/docs/doc_dto.md @@ -0,0 +1,360 @@ +# DTOs + +DTO's or Data Transfer Objects are references to other `data classes` within flutter. However the main difference is that they set all the fields as optional which allow for better composability and composition by the utilities, while also allow for better support for value tokens. + +## Example + +Shadow and BoxShadow, they normally have default values which are set when constructed. By using DTO's we can have nullablev values for each, and also have value tokens like `ColorDto`. + +```dart +import 'package:flutter/material.dart'; + +import '../../core/attribute.dart'; +import '../../factory/mix_provider_data.dart'; +import '../color/color_dto.dart'; + +@immutable +abstract class ShadowDtoImpl, + Value extends Shadow> extends Dto with Mergeable { + final ColorDto? color; + final Offset? offset; + final double? blurRadius; + + const ShadowDtoImpl({this.blurRadius, this.color, this.offset}); + + @override + Value resolve(MixData mix); + + @override + Self merge(Self? other); +} + +@immutable +class ShadowDto extends ShadowDtoImpl { + const ShadowDto({super.blurRadius, super.color, super.offset}); + + static ShadowDto from(Shadow shadow) { + return ShadowDto( + blurRadius: shadow.blurRadius, + color: ColorDto.maybeFrom(shadow.color), + offset: shadow.offset, + ); + } + + static ShadowDto? maybeFrom(Shadow? shadow) { + return shadow == null ? null : from(shadow); + } + + @override + Shadow resolve(MixData mix) { + const defaultShadow = Shadow(); + + return Shadow( + color: color?.resolve(mix) ?? defaultShadow.color, + offset: offset ?? defaultShadow.offset, + blurRadius: blurRadius ?? defaultShadow.blurRadius, + ); + } + + @override + ShadowDto merge(covariant ShadowDto? other) { + if (other == null) return this; + + return ShadowDto( + blurRadius: other.blurRadius ?? blurRadius, + color: other.color ?? color, + offset: other.offset ?? offset, + ); + } + + @override + get props => [color, offset, blurRadius]; +} + +class BoxShadowDto extends ShadowDtoImpl { + final double? spreadRadius; + + const BoxShadowDto({ + super.color, + super.offset, + super.blurRadius, + this.spreadRadius, + }); + + static BoxShadowDto from(BoxShadow shadow) { + return BoxShadowDto( + color: ColorDto.maybeFrom(shadow.color), + offset: shadow.offset, + blurRadius: shadow.blurRadius, + spreadRadius: shadow.spreadRadius, + ); + } + + static BoxShadowDto? maybeFrom(BoxShadow? shadow) { + return shadow == null ? null : from(shadow); + } + + @override + BoxShadow resolve(MixData mix) { + const defaultShadow = BoxShadow(); + + return BoxShadow( + color: color?.resolve(mix) ?? defaultShadow.color, + offset: offset ?? defaultShadow.offset, + blurRadius: blurRadius ?? defaultShadow.blurRadius, + spreadRadius: spreadRadius ?? defaultShadow.spreadRadius, + ); + } + + @override + BoxShadowDto merge(BoxShadowDto? other) { + if (other == null) return this; + + return BoxShadowDto( + color: other.color ?? color, + offset: other.offset ?? offset, + blurRadius: other.blurRadius ?? blurRadius, + spreadRadius: other.spreadRadius ?? spreadRadius, + ); + } + + @override + get props => [color, offset, blurRadius, spreadRadius]; +} + +``` + +### Mergeable + +- It is important that DTO's are mergeable and allow for values to be set by default to the `other` DTO, unles it does not exist then it should use the current value. +- Also is importantt o know that some fields can be DTO's themselves. In that case we need to merge them as well. + +### Resolvable + +- It is important that DTO's are resolvable, this means that they can be resolved to their respective data class. + +## Tests + +It's is very important that DTOs are tested, since they are the main building blocks of the utilities. They are the ones that will be used to create the `Mix` class and the `MixData` class. + +Important tests to have are: + +- Construct DTO using the constructor. +- Has a from method that creates the DTO from the data class. +- Has a maybeFrom method that creates the DTO from the data class if it is not null. +- Has a resolve method that resolves the DTO to the data class. +- Has a merge method that merges the DTO with another DTO. + +## Utilities + +```dart +import 'package:flutter/material.dart'; + +import '../../core/attribute.dart'; +import '../../core/extensions/values_ext.dart'; +import '../color/color_dto.dart'; +import '../color/color_util.dart'; +import '../scalars/scalar_util.dart'; +import 'shadow_dto.dart'; + +/// Utility class for creating and manipulating attributes with [Shadow] +/// +/// Allows setting of color, offset, and blur radius for a shadow. This class +/// provides a convenient way to configure and apply shadow effects to [T] +/// +/// Accepts a builder function that returns [T] and takes a [ShadowDto] as a parameter. +/// +/// Example usage: +/// +/// ```dart +// final shadow = ShadowUtility(builder); +// final attribute = shadow( +// color: Colors.black, +// offset: Offset(2.0, 2.0), +// blurRadius: 4.0, +// ); +/// ``` +/// +/// See also: +/// * [ShadowDto], the data transfer object for [Shadow] +/// * [MixUtility], the utility class that [ShadowUtility] extends +class ShadowUtility extends MixUtility { + const ShadowUtility(super.builder); + + // Internal method to create a shadow with optional parameters. + T _only({ColorDto? color, Offset? offset, double? blurRadius}) { + final shadow = ShadowDto( + blurRadius: blurRadius, + color: color, + offset: offset, + ); + + return builder(shadow); + } + + /// Returns a [ColorUtility] for setting the color of the shadow. + /// + /// Example usage: + /// + /// ```dart + /// final shadow = ShadowUtility(builder); + /// final attribute = shadow.color(Colors.black); + /// ``` + /// + /// Attribute now holds a [ShadowAttribute] with a [ShadowDto] that has a color value of `Colors.black`. + /// + /// See also: + /// * [ColorUtility], the utility class for manipulating [Color] + /// * [ColorDto], the data transfer object for [Color] + ColorUtility get color { + return ColorUtility((color) => _only(color: color)); + } + + /// Returns an [OffsetUtility] for setting the offset of the shadow. + /// + /// Example usage: + /// + /// ```dart + /// final shadow = ShadowUtility(builder); + /// final attribute = shadow.offset(Offset(2.0, 2.0)); + /// ``` + /// + /// Attribute now holds a [ShadowAttribute] with a [ShadowDto] that has an offset value of `Offset(2.0, 2.0)`. + /// + /// See also: + /// * [OffsetUtility], the utility class for manipulating [Offset] + /// * [Offset], the data transfer object for [Offset] + OffsetUtility get offset { + return OffsetUtility((offset) => _only(offset: offset)); + } + + /// Method to set the blur radius of the shadow. + /// + /// Example usage: + /// + /// ```dart + /// final shadow = ShadowUtility(builder); + /// final attribute = shadow.blurRadius(4.0); + /// ``` + /// + /// Attribute now holds a [ShadowAttribute] with a [ShadowDto] that has a blur radius value of `4.0`. + /// + /// See also: + /// * [DoubleUtility], the utility class for manipulating [double] + T blurRadius(double blurRadius) => _only(blurRadius: blurRadius); + + /// Method to create a shadow with provided parameters. + T call({Color? color, Offset? offset, double? blurRadius}) { + return _only( + color: color?.toDto(), + offset: offset, + blurRadius: blurRadius, + ); + } +} + +/// Utility class for creating and manipulating a list of [BoxShadow] attributes. +/// +/// Allows for the creation of a list of box shadows, useful for applying multiple shadows to a single element. +class BoxShadowListUtility + extends MixUtility> { + const BoxShadowListUtility(super.builder); + + /// Method to create a list of box shadows from a list of [BoxShadow]. + /// + /// Example usage: + /// + /// ```dart + /// final boxShadowList = BoxShadowListUtility(builder); + /// final attribute = boxShadowList([ + /// BoxShadow(color: Colors.black, blurRadius: 4.0, offset: Offset(2.0, 2.0)) + /// ]); + /// ``` + /// + /// Attribute now holds a list of [BoxShadowAttribute] with corresponding [BoxShadowDto] values. + T call(List shadows) { + return builder(shadows.map(BoxShadowDto.from).toList()); + } +} + +/// Utility class for creating and manipulating [BoxShadow] attributes. +/// +/// Allows setting of color, offset, blur radius, and spread radius for a box shadow. +/// Useful for adding depth and elevation effects to Flutter widgets. +class BoxShadowUtility + extends MixUtility { + const BoxShadowUtility(super.builder); + + /// Returns a [ColorUtility] for setting the color of the box shadow. + /// + /// Example usage: + /// + /// ```dart + /// final boxShadow = BoxShadowUtility(builder); + /// final attribute = boxShadow.color(Colors.black); + /// ``` + /// + /// Attribute now holds a [BoxShadowAttribute] with a [BoxShadowDto] that has a color value of `Colors.black`. + ColorUtility get color { + return ColorUtility((color) => call(color: color)); + } + + /// Returns an [OffsetUtility] for setting the offset of the box shadow. + /// + /// Example usage: + /// + /// ```dart + /// final boxShadow = BoxShadowUtility(builder); + /// final attribute = boxShadow.offset(Offset(2.0, 2.0)); + /// ``` + /// + /// Attribute now holds a [BoxShadowAttribute] with a [BoxShadowDto] that has an offset value of `Offset(2.0, 2.0)`. + OffsetUtility get offset { + return OffsetUtility((offset) => call(offset: offset)); + } + + /// Method to set the spread radius of the box shadow. + /// + /// Example usage: + /// + /// ```dart + /// final boxShadow = BoxShadowUtility(builder); + /// final attribute = boxShadow.spreadRadius(1.0); + /// ``` + /// + /// Attribute now holds a [BoxShadowAttribute] with a [BoxShadowDto] that has a spread radius value of `1.0`. + T spreadRadius(double spreadRadius) => call(spreadRadius: spreadRadius); + + /// Method to set the blur radius of the box shadow. + /// + /// Example usage: + /// + /// ```dart + /// final boxShadow = BoxShadowUtility(builder); + /// final attribute = boxShadow.blurRadius(4.0); + /// ``` + /// + /// Attribute now holds a [BoxShadowAttribute] with a [BoxShadowDto] that has a blur radius value of `4.0`. + T blurRadius(double blurRadius) => call(blurRadius: blurRadius); + + /// Method to create a box shadow with provided parameters. + T call({ + ColorDto? color, + Offset? offset, + double? blurRadius, + double? spreadRadius, + }) { + final shadow = BoxShadowDto( + color: color, + offset: offset, + blurRadius: blurRadius, + spreadRadius: spreadRadius, + ); + + return builder(shadow); + } +} + + + +``` diff --git a/lib/exports.dart b/lib/exports.dart index 2576490e3..653673a1f 100644 --- a/lib/exports.dart +++ b/lib/exports.dart @@ -5,23 +5,28 @@ export 'src/attributes/border/border_radius_dto.dart'; export 'src/attributes/border/border_radius_util.dart'; export 'src/attributes/border/border_util.dart'; export 'src/attributes/color/color_dto.dart'; -export 'src/attributes/constraints/constraints_attribute.dart'; +export 'src/attributes/color/color_util.dart'; +export 'src/attributes/constraints/constraints_dto.dart'; export 'src/attributes/constraints/constraints_util.dart'; -export 'src/attributes/decoration/decoration_attribute.dart'; +export 'src/attributes/decoration/decoration_dto.dart'; export 'src/attributes/decoration/decoration_util.dart'; export 'src/attributes/gradient/gradient_attribute.dart'; +export 'src/attributes/gradient/gradient_dto.dart'; export 'src/attributes/gradient/gradient_util.dart'; export 'src/attributes/scalars/scalar_util.dart'; export 'src/attributes/scalars/scalars_attribute.dart'; export 'src/attributes/shadow/shadow_dto.dart'; export 'src/attributes/shadow/shadow_util.dart'; export 'src/attributes/spacing/edge_insets_dto.dart'; -export 'src/attributes/spacing/spacing_attribute.dart'; +export 'src/attributes/spacing/spacing_dto.dart'; export 'src/attributes/spacing/spacing_util.dart'; export 'src/attributes/strut_style/strut_style_attribute.dart'; +export 'src/attributes/strut_style/strut_style_dto.dart'; +export 'src/attributes/strut_style/strut_style_util.dart'; export 'src/attributes/style_mix_attribute.dart'; export 'src/attributes/text_directives_util.dart'; export 'src/attributes/text_style/text_style_attribute.dart'; +export 'src/attributes/text_style/text_style_dto.dart'; export 'src/attributes/text_style/text_style_util.dart'; export 'src/attributes/variant_attribute.dart'; export 'src/core/attribute.dart'; @@ -63,7 +68,7 @@ export 'src/recipes/text/text_spec.dart'; export 'src/recipes/text/text_util.dart'; export 'src/recipes/text/text_widget.dart'; export 'src/theme/mix_theme.dart'; -export 'src/theme/tokens/breakpoints.dart'; +export 'src/theme/tokens/breakpoints_token.dart'; export 'src/theme/tokens/color_token.dart'; export 'src/theme/tokens/material_tokens.dart'; export 'src/theme/tokens/mix_token.dart'; @@ -78,13 +83,13 @@ export 'src/utils/context_variant_util/on_helper_util.dart'; export 'src/utils/context_variant_util/on_orientation_util.dart'; export 'src/utils/decorators_util.dart'; export 'src/utils/helper_util.dart'; -export 'src/utils/pressable_util.dart'; export 'src/variants/context_variant.dart'; export 'src/variants/multi_variant.dart'; export 'src/variants/variant.dart'; export 'src/widgets/empty_widget.dart'; export 'src/widgets/gap_widget.dart'; -export 'src/widgets/pressable/pressable.notifier.dart'; -export 'src/widgets/pressable/pressable_state.dart'; -export 'src/widgets/pressable/pressable_widget.dart'; +export 'src/widgets/pressable/gesture_state.dart'; +export 'src/widgets/pressable/gesture_state.notifier.dart'; +export 'src/widgets/pressable/gesture_util.dart'; +export 'src/widgets/pressable/gesture_widget.dart'; export 'src/widgets/styled_widget.dart'; diff --git a/lib/src/attributes/border/border_radius_dto.dart b/lib/src/attributes/border/border_radius_dto.dart index 98d7e8dd1..1f69947b8 100644 --- a/lib/src/attributes/border/border_radius_dto.dart +++ b/lib/src/attributes/border/border_radius_dto.dart @@ -3,6 +3,17 @@ import 'package:flutter/material.dart'; import '../../core/attribute.dart'; import '../../factory/mix_provider_data.dart'; +/// Represents a [Dto] Data transfer object of [BorderRadiusGeometry] +/// +/// This is used to allow for resolvable value tokens, and also the correct +/// merge and combining behavior. It allows to be merged, and resolved to a [BorderRadiusGeometry] +/// +/// This Dto implements `BorderRadius` and `BorderRadiusDirectional` Flutter classes to allow for +/// better merging support, and cleaner API for the utilities +/// +/// See also: +/// - [BorderRadiusGeometry], which is the Flutter counterpart of this class. + @immutable class BorderRadiusGeometryDto extends Dto with Mergeable { diff --git a/lib/src/attributes/border/border_radius_util.dart b/lib/src/attributes/border/border_radius_util.dart index abb03f4ce..8ea29b01c 100644 --- a/lib/src/attributes/border/border_radius_util.dart +++ b/lib/src/attributes/border/border_radius_util.dart @@ -5,7 +5,6 @@ import 'package:flutter/material.dart'; import '../../core/attribute.dart'; import '../../core/extensions/values_ext.dart'; import '../scalars/scalar_util.dart'; -import 'border_radius_attribute.dart'; import 'border_radius_dto.dart'; /// Utility class for creating and manipulating attributes with [BorderRadiusGeometry] diff --git a/lib/src/attributes/color/color_attribute.dart b/lib/src/attributes/color/color_attribute.dart deleted file mode 100644 index a11c85648..000000000 --- a/lib/src/attributes/color/color_attribute.dart +++ /dev/null @@ -1,21 +0,0 @@ -import 'package:flutter/material.dart'; - -import '../../core/attribute.dart'; -import '../../factory/mix_provider_data.dart'; -import 'color_dto.dart'; - -@immutable -abstract class ColorAttribute> - extends ResolvableAttribute { - final ColorDto value; - const ColorAttribute(this.value); - - @override - Self merge(Self? other); - - @override - Color resolve(MixData mix) => value.resolve(mix); - - @override - get props => [value]; -} diff --git a/lib/src/attributes/color/color_util.dart b/lib/src/attributes/color/color_util.dart index b59b50698..2b4715720 100644 --- a/lib/src/attributes/color/color_util.dart +++ b/lib/src/attributes/color/color_util.dart @@ -1,6 +1,9 @@ +// ignore_for_file: avoid-non-null-assertion + import 'package:flutter/material.dart'; import '../../core/attribute.dart'; +import '../../theme/tokens/color_token.dart'; import '../scalars/scalar_util.dart'; import 'color_dto.dart'; @@ -9,9 +12,135 @@ class ColorUtility extends DtoUtility with CallableDtoUtilityMixin { const ColorUtility(super.builder) : super(valueToDto: ColorDto.new); + + T _buildColor(Color color) => builder(valueToDto(color)); + + MaterialColorUtility get red => MaterialColorUtility(builder, Colors.red); + MaterialColorUtility get pink => + MaterialColorUtility(builder, Colors.pink); + MaterialColorUtility get purple => + MaterialColorUtility(builder, Colors.purple); + MaterialColorUtility get deepPurple => + MaterialColorUtility(builder, Colors.deepPurple); + MaterialColorUtility get indigo => + MaterialColorUtility(builder, Colors.indigo); + MaterialColorUtility get blue => + MaterialColorUtility(builder, Colors.blue); + MaterialColorUtility get lightBlue => + MaterialColorUtility(builder, Colors.lightBlue); + MaterialColorUtility get cyan => + MaterialColorUtility(builder, Colors.cyan); + MaterialColorUtility get teal => + MaterialColorUtility(builder, Colors.teal); + MaterialColorUtility get green => + MaterialColorUtility(builder, Colors.green); + MaterialColorUtility get lightGreen => + MaterialColorUtility(builder, Colors.lightGreen); + MaterialColorUtility get lime => + MaterialColorUtility(builder, Colors.lime); + MaterialColorUtility get yellow => + MaterialColorUtility(builder, Colors.yellow); + MaterialColorUtility get amber => + MaterialColorUtility(builder, Colors.amber); + MaterialColorUtility get orange => + MaterialColorUtility(builder, Colors.orange); + MaterialColorUtility get deepOrange => + MaterialColorUtility(builder, Colors.deepOrange); + MaterialColorUtility get brown => + MaterialColorUtility(builder, Colors.brown); + MaterialColorUtility get grey => + MaterialColorUtility(builder, Colors.grey); + MaterialColorUtility get blueGrey => + MaterialColorUtility(builder, Colors.blueGrey); + MaterialAccentColorUtility get redAccent => + MaterialAccentColorUtility(builder, Colors.redAccent); + MaterialAccentColorUtility get pinkAccent => + MaterialAccentColorUtility(builder, Colors.pinkAccent); + MaterialAccentColorUtility get purpleAccent => + MaterialAccentColorUtility(builder, Colors.purpleAccent); + MaterialAccentColorUtility get deepPurpleAccent => + MaterialAccentColorUtility(builder, Colors.deepPurpleAccent); + MaterialAccentColorUtility get indigoAccent => + MaterialAccentColorUtility(builder, Colors.indigoAccent); + MaterialAccentColorUtility get blueAccent => + MaterialAccentColorUtility(builder, Colors.blueAccent); + MaterialAccentColorUtility get lightBlueAccent => + MaterialAccentColorUtility(builder, Colors.lightBlueAccent); + MaterialAccentColorUtility get cyanAccent => + MaterialAccentColorUtility(builder, Colors.cyanAccent); + MaterialAccentColorUtility get tealAccent => + MaterialAccentColorUtility(builder, Colors.tealAccent); + MaterialAccentColorUtility get greenAccent => + MaterialAccentColorUtility(builder, Colors.greenAccent); + MaterialAccentColorUtility get lightGreenAccent => + MaterialAccentColorUtility(builder, Colors.lightGreenAccent); + MaterialAccentColorUtility get limeAccent => + MaterialAccentColorUtility(builder, Colors.limeAccent); + MaterialAccentColorUtility get yellowAccent => + MaterialAccentColorUtility(builder, Colors.yellowAccent); + MaterialAccentColorUtility get amberAccent => + MaterialAccentColorUtility(builder, Colors.amberAccent); + MaterialAccentColorUtility get orangeAccent => + MaterialAccentColorUtility(builder, Colors.orangeAccent); + MaterialAccentColorUtility get deepOrangeAccent => + MaterialAccentColorUtility(builder, Colors.deepOrangeAccent); + + T of(ColorToken ref) => _buildColor(ref()); + + T transparent() => _buildColor(const Color(0x00000000)); + T black() => _buildColor(const Color(0xFF000000)); + T black87() => _buildColor(const Color(0xDD000000)); + T black54() => _buildColor(const Color(0x8A000000)); + T black45() => _buildColor(const Color(0x73000000)); + T black38() => _buildColor(const Color(0x61000000)); + T black26() => _buildColor(const Color(0x42000000)); + T black12() => _buildColor(const Color(0x1F000000)); + T white() => _buildColor(const Color(0xFFFFFFFF)); + T white70() => _buildColor(const Color(0xB3FFFFFF)); + T white60() => _buildColor(const Color(0x99FFFFFF)); + T white54() => _buildColor(const Color(0x8AFFFFFF)); + T white38() => _buildColor(const Color(0x62FFFFFF)); + T white30() => _buildColor(const Color(0x4DFFFFFF)); + T white24() => _buildColor(const Color(0x3DFFFFFF)); + T white12() => _buildColor(const Color(0x1FFFFFFF)); + T white10() => _buildColor(const Color(0x1AFFFFFF)); +} + +abstract class ColorSwatchUtility + extends MixUtility { + final ColorSwatch color; + const ColorSwatchUtility(super.builder, this.color); + T _buildColor(Color color) => builder(ColorDto(color)); } @immutable -class ColorAttributeUtility extends ColorUtility { - const ColorAttributeUtility(super.builder); +class MaterialColorUtility + extends ColorSwatchUtility { + const MaterialColorUtility(super.builder, super.color); + + T shade50() => _buildColor(color[50]!); + T shade100() => _buildColor(color[100]!); + T shade200() => _buildColor(color[200]!); + T shade300() => _buildColor(color[300]!); + T shade400() => _buildColor(color[400]!); + T shade500() => _buildColor(color[500]!); + T shade600() => _buildColor(color[600]!); + T shade700() => _buildColor(color[700]!); + T shade800() => _buildColor(color[800]!); + T shade900() => _buildColor(color[900]!); + + T call() => _buildColor(color[500]!); +} + +@immutable +class MaterialAccentColorUtility + extends ColorSwatchUtility { + const MaterialAccentColorUtility(super.builder, super.color); + + T shade100() => _buildColor(color[100]!); + T shade200() => _buildColor(color[200]!); + T shade400() => _buildColor(color[400]!); + T shade700() => _buildColor(color[700]!); + + T call() => _buildColor(color[400]!); } diff --git a/lib/src/attributes/constraints/constraints_attribute.dart b/lib/src/attributes/constraints/constraints_attribute.dart deleted file mode 100644 index f25cca240..000000000 --- a/lib/src/attributes/constraints/constraints_attribute.dart +++ /dev/null @@ -1,56 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter/rendering.dart'; - -import '../../core/attribute.dart'; -import '../../factory/mix_provider_data.dart'; -import '../scalars/scalars_attribute.dart'; -import 'constraints_dto.dart'; - -abstract class ConstraintsAttribute, - Value extends Constraints> extends DtoAttribute { - const ConstraintsAttribute(super.value); -} - -class BoxConstraintsAttribute extends ConstraintsAttribute< - BoxConstraintsAttribute, - BoxConstraintsDto, - BoxConstraints> with SingleChildRenderAttributeMixin { - const BoxConstraintsAttribute(super.value); - - static BoxConstraintsAttribute from(BoxConstraints constraints) => - BoxConstraintsAttribute(BoxConstraintsDto.from(constraints)); - - static BoxConstraintsAttribute? maybeFrom(BoxConstraints? constraints) { - return constraints == null ? null : from(constraints); - } - - @override - BoxConstraintsAttribute merge(BoxConstraintsAttribute? other) { - return other == null - ? this - : BoxConstraintsAttribute(value.merge(other.value)); - } - - @override - ConstrainedBox build(MixData mix, Widget child) { - return ConstrainedBox(constraints: resolve(mix), child: child); - } -} - -@immutable -class WidthAttribute extends ScalarAttribute { - const WidthAttribute(super.value); - - static WidthAttribute? maybeFrom(double? value) { - return value == null ? null : WidthAttribute(value); - } -} - -@immutable -class HeightAttribute extends ScalarAttribute { - const HeightAttribute(super.value); - - static HeightAttribute? maybeFrom(double? value) { - return value == null ? null : HeightAttribute(value); - } -} diff --git a/lib/src/attributes/constraints/constraints_dto.dart b/lib/src/attributes/constraints/constraints_dto.dart index f48fa2ec4..9deeec280 100644 --- a/lib/src/attributes/constraints/constraints_dto.dart +++ b/lib/src/attributes/constraints/constraints_dto.dart @@ -4,10 +4,18 @@ import '../../core/attribute.dart'; import '../../factory/mix_provider_data.dart'; abstract class ConstraintsDto, - Value extends Constraints> extends Dto { + Value extends Constraints> extends Dto with Mergeable { const ConstraintsDto(); } +/// Represents a [Dto] Data transfer object of [BoxConstraints] +/// +/// This is used to allow for resolvable value tokens, and also the correct +/// merge and combining behavior. It allows to be merged, and resolved to a `[BoxConstraints] +/// +/// See also: +/// - [BoxConstraints], which is the Flutter counterpart of this class. +/// - [ConstraintsDto], which is the base class for this class. class BoxConstraintsDto extends ConstraintsDto { final double? minWidth; @@ -22,6 +30,7 @@ class BoxConstraintsDto this.maxHeight, }); + /// Creates a [BoxConstraintsDto] from a given [BoxConstraints]. static BoxConstraintsDto from(BoxConstraints constraints) { return BoxConstraintsDto( minWidth: constraints.minWidth, @@ -31,29 +40,25 @@ class BoxConstraintsDto ); } + /// Creates a [BoxConstraintsDto] from a given [BoxConstraints]. + /// + /// Returns null if the constraints are null. static BoxConstraintsDto? maybeFrom(BoxConstraints? constraints) { return constraints == null ? null : from(constraints); } + /// Resolves this [BoxConstraintsDto] with a given [MixData] to a [BoxConstraints] @override BoxConstraints resolve(MixData mix) { - BoxConstraints? constraints; - - if (minWidth != null || - maxWidth != null || - minHeight != null || - maxHeight != null) { - constraints = BoxConstraints( - minWidth: minWidth ?? 0, - maxWidth: maxWidth ?? double.infinity, - minHeight: minHeight ?? 0, - maxHeight: maxHeight ?? double.infinity, - ); - } - - return constraints ?? const BoxConstraints(); + return BoxConstraints( + minWidth: minWidth ?? 0, + maxWidth: maxWidth ?? double.infinity, + minHeight: minHeight ?? 0, + maxHeight: maxHeight ?? double.infinity, + ); } + /// Merges this [BoxConstraintsDto] with `other` [BoxConstraintsDto] @override BoxConstraintsDto merge(BoxConstraintsDto? other) { if (other == null) return this; diff --git a/lib/src/attributes/constraints/constraints_util.dart b/lib/src/attributes/constraints/constraints_util.dart index 34f3fec12..6ebd96cd8 100644 --- a/lib/src/attributes/constraints/constraints_util.dart +++ b/lib/src/attributes/constraints/constraints_util.dart @@ -2,7 +2,6 @@ import 'package:flutter/material.dart'; import '../../core/attribute.dart'; import '../scalars/scalar_util.dart'; -import 'constraints_attribute.dart'; import 'constraints_dto.dart'; /// Utility class for building box constraints-related style attributes. @@ -29,32 +28,36 @@ class BoxConstraintsUtility const BoxConstraintsUtility(super.builder) : super(valueToDto: BoxConstraintsDto.from); - /// Sets the minimum width of the box constraints. + /// Sets the maximum width of the box constraints. /// - /// The `width` parameter sets the smallest width that the box can be. + /// The `width` parameter sets the largest width that the box can be. /// /// Example: + /// /// ```dart /// final boxConstraints = BoxConstraintsUtility(builder); - /// final attribute = boxConstraints.minWidth(100); + /// final attribute = boxConstraints.maxWidth(100); /// ``` /// - /// Attribute now holds a [T] with a [BoxConstraintsAttribute] that has a minWidth value of `100`. - T minWidth(double width) => call(minWidth: width); + /// Attribute now holds a [T] with a [BoxConstraintsAttribute] that has a maxWidth value of `100`. + DoubleUtility get maxWidth { + return DoubleUtility((value) => call(maxWidth: value)); + } - /// Sets the maximum width of the box constraints. + /// Sets the minimum width of the box constraints. /// - /// The `width` parameter sets the largest width that the box can be. + /// The `width` parameter sets the smallest width that the box can be. /// /// Example: - /// /// ```dart /// final boxConstraints = BoxConstraintsUtility(builder); - /// final attribute = boxConstraints.maxWidth(100); + /// final attribute = boxConstraints.minWidth(100); /// ``` /// - /// Attribute now holds a [T] with a [BoxConstraintsAttribute] that has a maxWidth value of `100`. - T maxWidth(double width) => call(maxWidth: width); + /// Attribute now holds a [T] with a [BoxConstraintsAttribute] that has a minWidth value of `100`. + DoubleUtility get minWidth { + return DoubleUtility((value) => call(minWidth: value)); + } /// Sets the minimum height of the box constraints. /// @@ -68,7 +71,9 @@ class BoxConstraintsUtility /// ``` /// /// Attribute now holds a [T] with a [BoxConstraintsAttribute] that has a minHeight value of `100`. - T minHeight(double height) => call(minHeight: height); + DoubleUtility get minHeight { + return DoubleUtility((value) => call(minHeight: value)); + } /// Sets the maximum height of the box constraints. /// @@ -82,7 +87,9 @@ class BoxConstraintsUtility /// ``` /// /// Attribute now holds a [T] with a [BoxConstraintsAttribute] that has a maxHeight value of `100`. - T maxHeight(double height) => call(maxHeight: height); + DoubleUtility get maxHeight { + return DoubleUtility((value) => call(maxHeight: value)); + } T call({ double? minWidth, diff --git a/lib/src/attributes/decoration/decoration_attribute.dart b/lib/src/attributes/decoration/decoration_attribute.dart deleted file mode 100644 index 179a45a29..000000000 --- a/lib/src/attributes/decoration/decoration_attribute.dart +++ /dev/null @@ -1,85 +0,0 @@ -// ignore_for_file: no_leading_underscores_for_local_identifiers - -import 'package:flutter/material.dart'; - -import '../../core/attribute.dart'; -import 'decoration_dto.dart'; - -@immutable -class DecorationAttribute - extends DtoAttribute - with SingleChildRenderAttributeMixin { - const DecorationAttribute(super.value); - - @override - DecorationAttribute merge(covariant DecorationAttribute? other) { - if (other == null) return this; - - if (value.runtimeType != other.value.runtimeType) return other; - - return DecorationAttribute(value.merge(other.value)); - } - - @override - DecoratedBox build(mix, child) { - return DecoratedBox(decoration: resolve(mix), child: child); - } -} - -// @immutable -// class BoxDecorationAttribute extends DecorationAttribute { -// const BoxDecorationAttribute(super.value); - -// factory BoxDecorationAttribute.only({ -// ColorDto? color, -// GradientDto? gradient, -// BoxShape? shape, -// BorderRadiusGeometryDto? borderRadius, -// List? boxShadow, -// BoxBorderDto? border, -// }) { -// return BoxDecorationAttribute( -// BoxDecorationDto( -// color: color, -// border: border, -// borderRadius: borderRadius, -// gradient: gradient, -// boxShadow: boxShadow, -// shape: shape, -// ), -// ); -// } - -// @override -// BoxDecorationAttribute _mergeWith(BoxDecorationAttribute other) { -// return BoxDecorationAttribute(value.merge(other.value)); -// } -// } - -// @immutable -// class ShapeDecorationAttribute extends DecorationAttribute< -// ShapeDecorationAttribute, ShapeDecorationDto, ShapeDecoration> { -// const ShapeDecorationAttribute(super.value); - -// factory ShapeDecorationAttribute.only({ -// ColorDto? color, -// GradientDto? gradient, -// ShapeBorder? shape, -// List? shadows, -// }) { -// return ShapeDecorationAttribute( -// ShapeDecorationDto( -// color: color, -// shape: shape, -// gradient: gradient, -// shadows: shadows, -// ), -// ); -// } - -// @override -// ShapeDecorationAttribute _mergeWith(ShapeDecorationAttribute other) { -// return ShapeDecorationAttribute(value.merge(other.value)); -// } -// } diff --git a/lib/src/attributes/decoration/decoration_dto.dart b/lib/src/attributes/decoration/decoration_dto.dart index d99d0ff5c..170dd4ce9 100644 --- a/lib/src/attributes/decoration/decoration_dto.dart +++ b/lib/src/attributes/decoration/decoration_dto.dart @@ -32,6 +32,14 @@ abstract class DecorationDto extends Dto } } +/// Represents a [Dto] Data transfer object of [BoxDecoration] +/// +/// This is used to allow for resolvable value tokens, and also the correct +/// merge and combining behavior. It allows to be merged, and resolved to a `[BoxDecoration] +/// +/// See also: +/// * [BoxDecoration], which is the Flutter counterpart of this class. +/// * [DecorationDto], which is the base class for this class. @immutable class BoxDecorationDto extends DecorationDto { final ColorDto? color; @@ -50,6 +58,7 @@ class BoxDecorationDto extends DecorationDto { this.shape, }); + /// Creates a [BoxDecorationDto] from a given [BoxDecoration]. static BoxDecorationDto from(BoxDecoration decoration) { return BoxDecorationDto( color: ColorDto.maybeFrom(decoration.color), @@ -61,10 +70,14 @@ class BoxDecorationDto extends DecorationDto { ); } + /// Creates a [BoxDecorationDto] from a given [BoxDecoration]. + /// + /// Returns null if the decoration is null. static BoxDecorationDto? maybeFrom(BoxDecoration? decoration) { return decoration == null ? null : from(decoration); } + /// Resolves this [BoxDecorationDto] with a given [MixData] to a [BoxDecoration] @override BoxDecoration resolve(MixData mix) { return BoxDecoration( @@ -77,6 +90,7 @@ class BoxDecorationDto extends DecorationDto { ); } + /// Merges this [BoxDecorationDto] with `other` [BoxDecorationDto] @override BoxDecorationDto merge(BoxDecorationDto? other) { if (other == null) return this; diff --git a/lib/src/attributes/decoration/decoration_util.dart b/lib/src/attributes/decoration/decoration_util.dart index 0bd61c2d9..38a51882a 100644 --- a/lib/src/attributes/decoration/decoration_util.dart +++ b/lib/src/attributes/decoration/decoration_util.dart @@ -88,9 +88,15 @@ class BoxDecorationUtility }); } - BoxShadowListUtility get boxShadow { - return BoxShadowListUtility((List boxShadow) { - return _only(boxShadow: boxShadow); + BoxShadowListUtility get boxShadows { + return BoxShadowListUtility((List boxShadows) { + return _only(boxShadow: boxShadows); + }); + } + + BoxShadowUtility get boxShadow { + return BoxShadowUtility((BoxShadowDto boxShadow) { + return _only(boxShadow: [boxShadow]); }); } diff --git a/lib/src/attributes/gradient/gradient_dto.dart b/lib/src/attributes/gradient/gradient_dto.dart index 745a71bdb..2cfa0edf1 100644 --- a/lib/src/attributes/gradient/gradient_dto.dart +++ b/lib/src/attributes/gradient/gradient_dto.dart @@ -5,32 +5,25 @@ import '../../core/extensions/iterable_ext.dart'; import '../../factory/mix_provider_data.dart'; import '../color/color_dto.dart'; -/// Abstract class representing a [Dto] Data transfer object for a gradient. -/// It provides common properties and methods for different types of gradients. +/// Represents a base [Dto] Data transfer object of [Gradient] /// -/// This is used to allow for resolvable value tokens, and also the correct merge and combining behavior. -/// It extends the [Dto] class and implements the [resolve] and [merge] methods. -/// It also overrides the [props] getter to provide a list of properties used for equality comparison. +/// This is used to allow for resolvable value tokens, and also the correct +/// merge and combining behavior. It allows to be merged, and resolved to a `[Gradient] /// /// See also: -/// * [GradientDto], which is the base class for this class. -/// * [LinearGradientDto], which is a type of gradient DTO. -/// * [RadialGradientDto], which is a type of gradient DTO. -/// * [SweepGradientDto], which is a type of gradient DTO. /// * [Gradient], which is the Flutter counterpart of this class. +/// * [LinearGradientDto], which extends this class. +/// * [RadialGradientDto], which extends this class. +/// * [SweepGradientDto], which extends this class. @immutable abstract class GradientDto extends Dto with Mergeable> { - /// The list of stops for the gradient. final List? stops; - /// The list of color DTOs for the gradient. final List? colors; - /// The transform applied to the gradient. final GradientTransform? transform; - /// Constructs a [GradientDto] with the given [stops], [colors], and [transform]. const GradientDto({this.stops, this.colors, this.transform}); /// Creates a [GradientDto] from a given [gradient]. @@ -51,61 +44,28 @@ abstract class GradientDto extends Dto /// Creates a [GradientDto] from a given [gradient]. /// - /// Utility method for internal implementation /// Returns null if the gradient is null. static GradientDto? maybeFrom(Gradient? gradient) { return gradient == null ? null : from(gradient); } - /// Resolves the gradient DTO into a concrete gradient based on the given [mix] data. + /// Resolves [GradientDto] given a [MixData] into a [Gradient @override T resolve(MixData mix); - /// Merges this gradient DTO with another [other] gradient DTO. + /// Merges [GradientDto] with another `other` [GradientDto] @override GradientDto merge(covariant GradientDto? other); - /// The list of properties used for equality comparison. @override get props => [stops, colors, transform]; } -/// A data transfer object [Dto] representing a linear gradient. -/// -/// This DTO extends the [GradientDto] class and provides additional properties -/// specific to linear gradients, such as the [begin] and [end] alignment points, -/// [tileMode], and [transform]. -/// -/// Linear gradients can be created using the [LinearGradientDto.from] method, -/// which takes a [LinearGradient] object and returns a corresponding -/// [LinearGradientDto] instance. -/// -/// Linear gradients can also be resolved using the [resolve] method, which -/// takes a [MixData] object and returns a resolved [LinearGradient] instance. -/// -/// Linear gradients can be merged using the [merge] method, which takes -/// another [LinearGradientDto] object and returns a new [LinearGradientDto] -/// instance with merged properties. If the provided [LinearGradientDto] is null, -/// the merge operation returns the original [LinearGradientDto] instance. -/// -/// Example usage: -/// ```dart -/// final gradient1 = LinearGradientDto( -/// begin: Alignment.topLeft, -/// end: Alignment.bottomRight, -/// colors: [Colors.red, Colors.blue], -/// stops: [0.0, 1.0], -/// ); +/// Represents a [Dto] Data transfer object of [LinearGradient] /// -/// final gradient2 = LinearGradientDto( -/// begin: Alignment.centerLeft, -/// end: Alignment.centerRight, -/// colors: [Colors.green, Colors.yellow], -/// stops: [0.0, 1.0], -/// ); +/// This is used to allow for resolvable value tokens, and also the correct +/// merge and combining behavior. It allows to be merged, and resolved to a `[LinearGradient] /// -/// final mergedGradient = gradient1.merge(gradient2); -/// ``` /// See also: /// * [LinearGradient], which is the Flutter counterpart of this class. /// * [GradientDto], which is the base class for this class. @@ -127,6 +87,7 @@ class LinearGradientDto extends GradientDto { super.stops, }); + /// Creates a [LinearGradientDto] from a given [gradient]. static LinearGradientDto from(LinearGradient gradient) { return LinearGradientDto( begin: gradient.begin, @@ -138,10 +99,14 @@ class LinearGradientDto extends GradientDto { ); } + /// Creates a [LinearGradientDto] from a given [gradient]. + /// + /// Returns null if the gradient is null. static LinearGradientDto? maybeFrom(LinearGradient? gradient) { return gradient == null ? null : from(gradient); } + /// Resolves [LinearGradientDto] given a [MixData] into a [LinearGradient] @override LinearGradient resolve(MixData mix) { return LinearGradient( @@ -154,6 +119,7 @@ class LinearGradientDto extends GradientDto { ); } + /// Merges [LinearGradientDto] with another `other` [LinearGradientDto @override LinearGradientDto merge(LinearGradientDto? other) { if (other == null) return this; @@ -172,23 +138,10 @@ class LinearGradientDto extends GradientDto { List get props => [begin, end, colors, stops, tileMode, transform]; } -/// A data transfer object [Dto] representing a radial gradient. -/// -/// This DTO extends the [GradientDto] class and provides additional properties -/// specific to radial gradients, such as the [center], [radius], [focalRadius], -/// [focal], and [tileMode]. +/// Represents a [Dto] Data transfer object of [RadialGradient] /// -/// Radial gradients can be created using the [RadialGradientDto.from] method, -/// which takes a [RadialGradient] object and returns a corresponding -/// [RadialGradientDto] instance. -/// -/// Radial gradients can also be resolved using the [resolve] method, which -/// takes a [MixData] object and returns a resolved [RadialGradient] instance. -/// -/// Radial gradients can be merged using the [merge] method, which takes -/// another [RadialGradientDto] object and returns a new [RadialGradientDto] -/// instance with merged properties. If the provided [RadialGradientDto] is null, -/// the merge operation returns the original [RadialGradientDto] instance. +/// This is used to allow for resolvable value tokens, and also the correct +/// merge and combining behavior. It allows to be merged, and resolved to a `[RadialGradient] /// /// Example usage: /// @@ -238,6 +191,7 @@ class RadialGradientDto extends GradientDto { super.stops, }); + /// Creates a [RadialGradientDto] from a given [RadialGradient]. static RadialGradientDto from(RadialGradient gradient) { return RadialGradientDto( center: gradient.center, @@ -251,10 +205,14 @@ class RadialGradientDto extends GradientDto { ); } + /// Creates a [RadialGradientDto] from a given [RadialGradient]. + /// + /// Returns null if the gradient is null. static RadialGradientDto? maybeFrom(RadialGradient? gradient) { return gradient == null ? null : from(gradient); } + /// Resolves [RadialGradientDto] given a [MixData] into a [RadialGradient @override RadialGradient resolve(MixData mix) { return RadialGradient( @@ -269,19 +227,20 @@ class RadialGradientDto extends GradientDto { ); } + /// Merges [RadialGradientDto] with another `other` [RadialGradientDto] @override RadialGradientDto merge(RadialGradientDto? other) { if (other == null) return this; return RadialGradientDto( - center: center, - radius: radius ?? other.radius, + center: other.center ?? center, + radius: other.radius ?? radius, tileMode: other.tileMode ?? tileMode, - focal: focal, + focal: other.focal ?? focal, focalRadius: other.focalRadius ?? focalRadius, transform: other.transform ?? transform, - colors: colors?.merge(other.colors), - stops: stops?.merge(other.stops), + colors: colors?.merge(other.colors) ?? other.colors, + stops: stops?.merge(other.stops) ?? other.stops, ); } @@ -290,45 +249,10 @@ class RadialGradientDto extends GradientDto { [center, radius, colors, stops, tileMode, focal, transform, focalRadius]; } -/// A data transfer object [Dto] representing a sweep gradient. +/// Represents a [Dto] Data transfer object of [SweepGradient] /// -/// This DTO extends the [GradientDto] class and provides additional properties -/// specific to sweep gradients, such as the [center], [startAngle], [endAngle], -/// and [tileMode]. -/// -/// Sweep gradients can be created using the [SweepGradientDto.from] method, -/// which takes a [SweepGradient] object and returns a corresponding -/// [SweepGradientDto] instance. -/// -/// Sweep gradients can also be resolved using the [resolve] method, which -/// takes a [MixData] object and returns a resolved [SweepGradient] instance. -/// -/// Sweep gradients can be merged using the [merge] method, which takes -/// another [SweepGradientDto] object and returns a new [SweepGradientDto] -/// instance with merged properties. If the provided [SweepGradientDto] is null, -/// the merge operation returns the original [SweepGradientDto] instance. -/// -/// Example usage: -/// -/// ```dart -/// final gradient1 = SweepGradientDto( -/// center: Alignment.center, -/// startAngle: 0.0, -/// endAngle: 0.5, -/// colors: [Colors.red, Colors.blue], -/// stops: [0.0, 1.0], -/// ); -/// -/// final gradient2 = SweepGradientDto( -/// center: Alignment.center, -/// startAngle: 0.0, -/// endAngle: 0.5, -/// colors: [Colors.green, Colors.yellow], -/// stops: [0.0, 1.0], -/// ); -/// -/// final mergedGradient = gradient1.merge(gradient2); -/// ``` +/// This is used to allow for resolvable value tokens, and also the correct +/// merge and combining behavior. It allows to be merged, and resolved to a `[SweepGradient] /// /// See also: /// * [SweepGradient], which is the Flutter counterpart of this class. @@ -354,6 +278,7 @@ class SweepGradientDto extends GradientDto { super.stops, }); + /// Creates a [SweepGradientDto] from a given [SweepGradient]. static SweepGradientDto from(SweepGradient gradient) { return SweepGradientDto( center: gradient.center, @@ -366,10 +291,14 @@ class SweepGradientDto extends GradientDto { ); } + /// Creates a [SweepGradientDto] from a given [SweepGradient]. + /// + /// Returns null if the gradient is null. static SweepGradientDto? maybeFrom(SweepGradient? gradient) { return gradient == null ? null : from(gradient); } + /// Resolves [SweepGradientDto] given a [MixData] into a [SweepGradient] @override SweepGradient resolve(MixData mix) { return SweepGradient( @@ -383,18 +312,19 @@ class SweepGradientDto extends GradientDto { ); } + /// Merges [SweepGradientDto] with another `other` [SweepGradientDto] @override SweepGradientDto merge(SweepGradientDto? other) { if (other == null) return this; return SweepGradientDto( center: other.center ?? center, - startAngle: startAngle ?? other.startAngle, - endAngle: endAngle ?? other.endAngle, + startAngle: other.startAngle ?? startAngle, + endAngle: other.endAngle ?? endAngle, tileMode: other.tileMode ?? tileMode, transform: other.transform ?? transform, - colors: colors?.merge(other.colors), - stops: stops?.merge(other.stops), + colors: colors?.merge(other.colors) ?? other.colors, + stops: stops?.merge(other.stops) ?? other.stops, ); } diff --git a/lib/src/attributes/scalars/scalar_util.dart b/lib/src/attributes/scalars/scalar_util.dart index 3d415d180..caa1d65ea 100644 --- a/lib/src/attributes/scalars/scalar_util.dart +++ b/lib/src/attributes/scalars/scalar_util.dart @@ -23,6 +23,7 @@ abstract class DtoUtility, const DtoUtility(super.builder, {required this.valueToDto}); + /// Returns a new [StyleAttribute] with the given [value]. Attr as(Value value) => _builder(valueToDto(value)); } @@ -58,7 +59,10 @@ class AlignmentUtility T bottomLeft() => builder(Alignment.bottomLeft); T bottomCenter() => builder(Alignment.bottomCenter); T bottomRight() => builder(Alignment.bottomRight); - T only(double? x, double? y, double? start) { + T only({double? x, double? y, double? start}) { + assert(x == null || start == null, + 'Cannot provide both an x and a start parameter.'); + return start == null ? builder(Alignment(x ?? 0, y ?? 0)) : builder(AlignmentDirectional(start, y ?? 0)); @@ -74,8 +78,8 @@ class AlignmentUtility /// final utility = DoubleUtility(builder); /// final tenValue = utility(10); /// ``` -abstract class DoubleUtility - extends ScalarUtility with CallableUtilityMixin { +class DoubleUtility extends ScalarUtility + with CallableUtilityMixin { const DoubleUtility(super.builder); } @@ -298,7 +302,7 @@ class TileModeUtility const TileModeUtility(super.builder); T clamp() => builder(TileMode.clamp); T mirror() => builder(TileMode.mirror); - T repeat() => builder(TileMode.repeated); + T repeated() => builder(TileMode.repeated); T decal() => builder(TileMode.decal); } @@ -562,6 +566,7 @@ class BoxShapeUtility /// final fontWeight = FontWeightUtility(builder); /// final bold = fontWeight.bold(); /// final normal = fontWeight.normal(); +/// final w100 = fontWeight.w100(); /// ``` /// /// See [FontWeight] for more information. @@ -570,6 +575,15 @@ class FontWeightUtility const FontWeightUtility(super.builder); T bold() => _builder(FontWeight.bold); T normal() => _builder(FontWeight.normal); + T w100() => _builder(FontWeight.w100); + T w200() => _builder(FontWeight.w200); + T w300() => _builder(FontWeight.w300); + T w400() => _builder(FontWeight.w400); + T w500() => _builder(FontWeight.w500); + T w600() => _builder(FontWeight.w600); + T w700() => _builder(FontWeight.w700); + T w800() => _builder(FontWeight.w800); + T w900() => _builder(FontWeight.w900); } /// Utility for setting `TextDecoration` values. diff --git a/lib/src/attributes/scalars/scalars_attribute.dart b/lib/src/attributes/scalars/scalars_attribute.dart index 68697761f..07a635f0f 100644 --- a/lib/src/attributes/scalars/scalars_attribute.dart +++ b/lib/src/attributes/scalars/scalars_attribute.dart @@ -2,8 +2,6 @@ import 'package:flutter/material.dart'; import 'package:flutter/widgets.dart'; import '../../core/attribute.dart'; -import '../color/color_attribute.dart'; -import '../color/color_dto.dart'; @immutable abstract class ScalarAttribute, Value> @@ -17,70 +15,3 @@ abstract class ScalarAttribute, Value> @override get props => [value]; } - -@immutable -class AxisAttribute extends ScalarAttribute { - const AxisAttribute(super.value); - - static AxisAttribute? maybeFrom(Axis? value) => - value == null ? null : AxisAttribute(value); -} - -@immutable -class TransformAttribute extends ScalarAttribute - with SingleChildRenderAttributeMixin { - const TransformAttribute(super.value); - - static TransformAttribute? maybeFrom(Matrix4? value) => - value == null ? null : TransformAttribute(value); - - @override - Transform build(mix, child) { - return Transform(transform: value, child: child); - } -} - -@immutable -class AlignmentGeometryAttribute - extends ScalarAttribute - with SingleChildRenderAttributeMixin { - const AlignmentGeometryAttribute(super.value); - - static AlignmentGeometryAttribute? maybeFrom(AlignmentGeometry? value) => - value == null ? null : AlignmentGeometryAttribute(value); - - @override - Align build(mix, child) { - return Align(alignment: value, child: child); - } -} - -@immutable -class ClipBehaviorAttribute - extends ScalarAttribute { - const ClipBehaviorAttribute(super.value); - - static ClipBehaviorAttribute? maybeFrom(Clip? value) => - value == null ? null : ClipBehaviorAttribute(value); -} - -@immutable -class BackgroundColorAttribute extends ColorAttribute - with SingleChildRenderAttributeMixin { - const BackgroundColorAttribute(super.value); - - static BackgroundColorAttribute? maybeFrom(Color? value) => - value == null ? null : BackgroundColorAttribute(ColorDto(value)); - - @override - BackgroundColorAttribute merge(BackgroundColorAttribute? other) { - return other == null - ? this - : BackgroundColorAttribute(value.merge(other.value)); - } - - @override - ColoredBox build(mix, child) { - return ColoredBox(color: resolve(mix), child: child); - } -} diff --git a/lib/src/attributes/shadow/shadow_dto.dart b/lib/src/attributes/shadow/shadow_dto.dart index e165c057a..5f91e42a6 100644 --- a/lib/src/attributes/shadow/shadow_dto.dart +++ b/lib/src/attributes/shadow/shadow_dto.dart @@ -17,13 +17,22 @@ abstract class ShadowDtoImpl, Value resolve(MixData mix); @override - Self merge(covariant Self? other); + Self merge(Self? other); } +/// Represents a [Dto] Data transfer object of [Shadow] +/// +/// This is used to allow for resolvable value tokens, and also the correct +/// merge and combining behavior. It allows to be merged, and resolved to a [Shadow] +/// +/// See also: +/// - [Shadow], which is the Flutter counterpart of this class. +/// - [ShadowDtoImpl], which is the base class for this class. @immutable class ShadowDto extends ShadowDtoImpl { const ShadowDto({super.blurRadius, super.color, super.offset}); + /// Creates a [ShadowDto] from a [Shadow] static ShadowDto from(Shadow shadow) { return ShadowDto( blurRadius: shadow.blurRadius, @@ -32,10 +41,14 @@ class ShadowDto extends ShadowDtoImpl { ); } + /// Creates a [ShadowDto] from a [Shadow] + /// + /// Returns null if [shadow] is null static ShadowDto? maybeFrom(Shadow? shadow) { return shadow == null ? null : from(shadow); } + /// Resolves this [ShadowDto] with a given [MixData] to a [Shadow] @override Shadow resolve(MixData mix) { const defaultShadow = Shadow(); @@ -47,8 +60,9 @@ class ShadowDto extends ShadowDtoImpl { ); } + /// Merges this [ShadowDto] with `other` [ShadowDto] @override - ShadowDto merge(covariant ShadowDto? other) { + ShadowDto merge(ShadowDto? other) { if (other == null) return this; return ShadowDto( @@ -62,6 +76,14 @@ class ShadowDto extends ShadowDtoImpl { get props => [color, offset, blurRadius]; } +/// Represents a [Dto] Data transfer object of [BoxShadow] +/// +/// This is used to allow for resolvable value tokens, and also the correct +/// merge and combining behavior. It allows to be merged, and resolved to a `[BoxShadow] +/// +/// See also: +/// - [BoxShadow], which is the Flutter counterpart of this class. +/// - [ShadowDtoImpl], which is the base class for this class. class BoxShadowDto extends ShadowDtoImpl { final double? spreadRadius; @@ -72,6 +94,7 @@ class BoxShadowDto extends ShadowDtoImpl { this.spreadRadius, }); + /// Creates a [BoxShadowDto] from a [BoxShadow] static BoxShadowDto from(BoxShadow shadow) { return BoxShadowDto( color: ColorDto.maybeFrom(shadow.color), @@ -81,10 +104,12 @@ class BoxShadowDto extends ShadowDtoImpl { ); } + /// Creates a [BoxShadowDto] from a [BoxShadow] static BoxShadowDto? maybeFrom(BoxShadow? shadow) { return shadow == null ? null : from(shadow); } + /// Resolves this [BoxShadowDto] with a given [MixData] to a [BoxShadow] @override BoxShadow resolve(MixData mix) { const defaultShadow = BoxShadow(); @@ -97,12 +122,13 @@ class BoxShadowDto extends ShadowDtoImpl { ); } + /// Merges this [BoxShadowDto] with `other` [BoxShadowDto] @override BoxShadowDto merge(BoxShadowDto? other) { if (other == null) return this; return BoxShadowDto( - color: other.color ?? color, + color: color?.merge(other.color) ?? other.color, offset: other.offset ?? offset, blurRadius: other.blurRadius ?? blurRadius, spreadRadius: other.spreadRadius ?? spreadRadius, diff --git a/lib/src/attributes/shadow/shadow_util.dart b/lib/src/attributes/shadow/shadow_util.dart index 293d3827d..5689208c4 100644 --- a/lib/src/attributes/shadow/shadow_util.dart +++ b/lib/src/attributes/shadow/shadow_util.dart @@ -132,8 +132,24 @@ class BoxShadowListUtility /// Allows setting of color, offset, blur radius, and spread radius for a box shadow. /// Useful for adding depth and elevation effects to Flutter widgets. class BoxShadowUtility - extends MixUtility { - const BoxShadowUtility(super.builder); + extends DtoUtility { + const BoxShadowUtility(super.builder) : super(valueToDto: BoxShadowDto.from); + + T _only({ + ColorDto? color, + Offset? offset, + double? blurRadius, + double? spreadRadius, + }) { + final shadow = BoxShadowDto( + color: color, + offset: offset, + blurRadius: blurRadius, + spreadRadius: spreadRadius, + ); + + return builder(shadow); + } /// Returns a [ColorUtility] for setting the color of the box shadow. /// @@ -146,7 +162,7 @@ class BoxShadowUtility /// /// Attribute now holds a [BoxShadowAttribute] with a [BoxShadowDto] that has a color value of `Colors.black`. ColorUtility get color { - return ColorUtility((color) => call(color: color)); + return ColorUtility((color) => _only(color: color)); } /// Returns an [OffsetUtility] for setting the offset of the box shadow. @@ -163,45 +179,47 @@ class BoxShadowUtility return OffsetUtility((offset) => call(offset: offset)); } - /// Method to set the spread radius of the box shadow. + /// Method to set the blur radius of the box shadow. /// /// Example usage: /// /// ```dart /// final boxShadow = BoxShadowUtility(builder); - /// final attribute = boxShadow.spreadRadius(1.0); + /// final attribute = boxShadow.blurRadius(4.0); /// ``` /// - /// Attribute now holds a [BoxShadowAttribute] with a [BoxShadowDto] that has a spread radius value of `1.0`. - T spreadRadius(double spreadRadius) => call(spreadRadius: spreadRadius); + /// Attribute now holds a [BoxShadowAttribute] with a [BoxShadowDto] that has a blur radius value of `4.0`. + DoubleUtility get blurRadius { + return DoubleUtility((blurRadius) => call(blurRadius: blurRadius)); + } - /// Method to set the blur radius of the box shadow. + /// Method to set the spread radius of the box shadow. /// /// Example usage: /// /// ```dart /// final boxShadow = BoxShadowUtility(builder); - /// final attribute = boxShadow.blurRadius(4.0); + /// final attribute = boxShadow.spreadRadius(1.0); /// ``` /// - /// Attribute now holds a [BoxShadowAttribute] with a [BoxShadowDto] that has a blur radius value of `4.0`. - T blurRadius(double blurRadius) => call(blurRadius: blurRadius); + /// Attribute now holds a [BoxShadowAttribute] with a [BoxShadowDto] that has a spread radius value of `1.0`. + DoubleUtility get spreadRadius { + return DoubleUtility((spreadRadius) => call(spreadRadius: spreadRadius)); + } /// Method to create a box shadow with provided parameters. T call({ - ColorDto? color, + Color? color, Offset? offset, double? blurRadius, double? spreadRadius, }) { - final shadow = BoxShadowDto( - color: color, + return _only( + color: color?.toDto(), offset: offset, blurRadius: blurRadius, spreadRadius: spreadRadius, ); - - return builder(shadow); } } diff --git a/lib/src/attributes/spacing/spacing_attribute.dart b/lib/src/attributes/spacing/spacing_attribute.dart deleted file mode 100644 index ba35471f3..000000000 --- a/lib/src/attributes/spacing/spacing_attribute.dart +++ /dev/null @@ -1,48 +0,0 @@ -// ignore_for_file: unnecessary_overrides, prefer-moving-to-variable - -import 'package:flutter/material.dart'; - -import '../../core/attribute.dart'; -import '../../factory/mix_provider_data.dart'; -import 'spacing_dto.dart'; - -@immutable -abstract class SpacingAttribute> - extends DtoAttribute - with SingleChildRenderAttributeMixin { - const SpacingAttribute(super.value); - - bool get isDirectional => value.isDirectional; - - double? get top => value.top; - double? get bottom => value.bottom; - double? get left => value.left; - double? get right => value.right; - double? get start => value.start; - double? get end => value.end; - - @override - Padding build(MixData mix, Widget child) { - return Padding(padding: resolve(mix), child: child); - } -} - -@immutable -class PaddingAttribute extends SpacingAttribute { - const PaddingAttribute(super.value); - - @override - PaddingAttribute merge(PaddingAttribute? other) { - return other == null ? this : PaddingAttribute(value.merge(other.value)); - } -} - -@immutable -class MarginAttribute extends SpacingAttribute { - const MarginAttribute(super.value); - - @override - MarginAttribute merge(MarginAttribute? other) { - return other == null ? this : MarginAttribute(value.merge(other.value)); - } -} diff --git a/lib/src/attributes/spacing/spacing_dto.dart b/lib/src/attributes/spacing/spacing_dto.dart index 3dbf8bc45..c6ddf26b7 100644 --- a/lib/src/attributes/spacing/spacing_dto.dart +++ b/lib/src/attributes/spacing/spacing_dto.dart @@ -7,7 +7,7 @@ import 'edge_insets_dto.dart'; @immutable class SpacingDto extends EdgeInsetsGeometryDto { - const SpacingDto({ + const SpacingDto._({ super.top, super.bottom, super.left, @@ -16,16 +16,32 @@ class SpacingDto extends EdgeInsetsGeometryDto { super.end, }); + const SpacingDto.only({ + double? top, + double? bottom, + double? left, + double? right, + double? start, + double? end, + }) : this._( + top: top, + bottom: bottom, + left: left, + right: right, + start: start, + end: end, + ); + static SpacingDto from(EdgeInsetsGeometry edgeInsets) { if (edgeInsets is EdgeInsetsDirectional) { - return SpacingDto( + return SpacingDto._( top: edgeInsets.top, bottom: edgeInsets.bottom, start: edgeInsets.start, end: edgeInsets.end, ); } else if (edgeInsets is EdgeInsets) { - return SpacingDto( + return SpacingDto._( top: edgeInsets.top, bottom: edgeInsets.bottom, left: edgeInsets.left, @@ -48,7 +64,7 @@ class SpacingDto extends EdgeInsetsGeometryDto { SpacingDto merge(SpacingDto? other) { if (other == null) return this; - return SpacingDto( + return SpacingDto._( top: other.top ?? top, bottom: other.bottom ?? bottom, left: other.left ?? left, diff --git a/lib/src/attributes/spacing/spacing_util.dart b/lib/src/attributes/spacing/spacing_util.dart index c452087f3..94842a741 100644 --- a/lib/src/attributes/spacing/spacing_util.dart +++ b/lib/src/attributes/spacing/spacing_util.dart @@ -3,7 +3,6 @@ import 'package:flutter/material.dart'; import '../../core/attribute.dart'; import '../../theme/tokens/space_token.dart'; import '../scalars/scalar_util.dart'; -import 'spacing_attribute.dart'; import 'spacing_dto.dart'; /// A utility class for defining spacing attributes like padding and margin in Flutter widgets. @@ -252,7 +251,7 @@ class SpacingUtility double? end, }) { return builder( - SpacingDto( + SpacingDto.only( top: top, bottom: bottom, left: left, @@ -524,7 +523,7 @@ class SpacingDirectionalUtility /// * [SpacingDto], the data transfer object for [SpacingAttribute] T only({double? top, double? bottom, double? start, double? end}) { return builder( - SpacingDto(top: top, bottom: bottom, start: start, end: end), + SpacingDto.only(top: top, bottom: bottom, start: start, end: end), ); } } diff --git a/lib/src/attributes/text_style/text_style_dto.dart b/lib/src/attributes/text_style/text_style_dto.dart index 6f925c16a..b7584f551 100644 --- a/lib/src/attributes/text_style/text_style_dto.dart +++ b/lib/src/attributes/text_style/text_style_dto.dart @@ -13,7 +13,7 @@ import '../color/color_dto.dart'; import '../shadow/shadow_dto.dart'; @immutable -class TextStyleDataDto extends Dto with Mergeable { +class TextStyleData extends Dto with Mergeable { final String? fontFamily; final FontWeight? fontWeight; final FontStyle? fontStyle; @@ -36,9 +36,9 @@ class TextStyleDataDto extends Dto with Mergeable { final double? decorationThickness; final List? fontFamilyFallback; - final TextStyleToken? token; + final TextStyleRef? ref; - const TextStyleDataDto({ + const TextStyleData({ this.background, this.backgroundColor, this.color, @@ -60,10 +60,11 @@ class TextStyleDataDto extends Dto with Mergeable { this.shadows, this.textBaseline, this.wordSpacing, - }) : token = null; + }) : ref = null; - const TextStyleDataDto.token(this.token) - : background = null, + const TextStyleData.tokenRef(TextStyleRef tokenRef) + : ref = tokenRef, + background = null, backgroundColor = null, color = null, debugLabel = null, @@ -85,47 +86,49 @@ class TextStyleDataDto extends Dto with Mergeable { textBaseline = null, wordSpacing = null; - static TextStyleDataDto from(TextStyle style) { - return TextStyleDataDto( - background: style.background, - backgroundColor: style.backgroundColor?.toDto(), - color: style.color?.toDto(), - debugLabel: style.debugLabel, - decoration: style.decoration, - decorationColor: style.decorationColor?.toDto(), - decorationStyle: style.decorationStyle, - decorationThickness: style.decorationThickness, - fontFamily: style.fontFamily, - fontFamilyFallback: style.fontFamilyFallback, - fontFeatures: style.fontFeatures, - fontSize: style.fontSize, - fontStyle: style.fontStyle, - fontWeight: style.fontWeight, - foreground: style.foreground, - height: style.height, - letterSpacing: style.letterSpacing, - locale: style.locale, - shadows: style.shadows?.map((e) => e.toDto()).toList(), - textBaseline: style.textBaseline, - wordSpacing: style.wordSpacing, - ); + static TextStyleData from(TextStyle style) { + return style is TextStyleRef + ? TextStyleData.tokenRef(style) + : TextStyleData( + background: style.background, + backgroundColor: style.backgroundColor?.toDto(), + color: style.color?.toDto(), + debugLabel: style.debugLabel, + decoration: style.decoration, + decorationColor: style.decorationColor?.toDto(), + decorationStyle: style.decorationStyle, + decorationThickness: style.decorationThickness, + fontFamily: style.fontFamily, + fontFamilyFallback: style.fontFamilyFallback, + fontFeatures: style.fontFeatures, + fontSize: style.fontSize, + fontStyle: style.fontStyle, + fontWeight: style.fontWeight, + foreground: style.foreground, + height: style.height, + letterSpacing: style.letterSpacing, + locale: style.locale, + shadows: style.shadows?.map((e) => e.toDto()).toList(), + textBaseline: style.textBaseline, + wordSpacing: style.wordSpacing, + ); } - static TextStyleDataDto? maybeFrom(TextStyle? style) { - return style == null ? null : TextStyleDataDto.from(style); + static TextStyleData? maybeFrom(TextStyle? style) { + return style == null ? null : TextStyleData.from(style); } - bool get isTokenRef => token != null; + bool get isTokenRef => ref != null; @override - TextStyleDataDto merge(TextStyleDataDto? other) { + TextStyleData merge(TextStyleData? other) { if (other == null) return this; assert( - token == null && other.token == null, + ref == null && other.ref == null, 'Cannot merge token refs', ); - return TextStyleDataDto( + return TextStyleData( background: other.background ?? background, backgroundColor: other.backgroundColor ?? backgroundColor, color: other.color ?? color, @@ -155,9 +158,8 @@ class TextStyleDataDto extends Dto with Mergeable { @override TextStyle resolve(MixData mix) { - return isTokenRef - ? mix.tokens.textStyleToken(token!) - : TextStyle( + return ref == null + ? TextStyle( color: color?.resolve(mix), backgroundColor: backgroundColor?.resolve(mix), fontSize: fontSize, @@ -179,7 +181,8 @@ class TextStyleDataDto extends Dto with Mergeable { debugLabel: debugLabel, fontFamily: fontFamily, fontFamilyFallback: fontFamilyFallback, - ); + ) + : mix.tokens.textStyleRef(ref!); } @override @@ -205,14 +208,14 @@ class TextStyleDataDto extends Dto with Mergeable { foreground, decorationThickness, fontFamilyFallback, - token, + ref, ]; } @immutable class TextStyleDto extends Dto with Mergeable { - final List value; - const TextStyleDto.raw(this.value); + final List value; + const TextStyleDto._(this.value); factory TextStyleDto.only({ ColorDto? color, @@ -237,7 +240,7 @@ class TextStyleDto extends Dto with Mergeable { String? fontFamily, List? fontFamilyFallback, }) { - return TextStyleDto(TextStyleDataDto( + return TextStyleDto(TextStyleData( background: background, backgroundColor: backgroundColor, color: color, @@ -262,20 +265,18 @@ class TextStyleDto extends Dto with Mergeable { )); } - factory TextStyleDto(TextStyleDataDto value) { - return TextStyleDto.raw([value]); - } + factory TextStyleDto(TextStyleData value) => TextStyleDto._([value]); - factory TextStyleDto.token(TextStyleToken token) { - return TextStyleDto(TextStyleDataDto.token(token)); + factory TextStyleDto.of(TextStyleToken token) { + return TextStyleDto(TextStyleData.tokenRef(token())); } - static TextStyleDto from(TextStyle style) { - return TextStyleDto(TextStyleDataDto.from(style)); + static TextStyleDto as(TextStyle style) { + return TextStyleDto(TextStyleData.from(style)); } - static TextStyleDto? maybeFrom(TextStyle? style) { - return style == null ? null : TextStyleDto.from(style); + static TextStyleDto? maybeAs(TextStyle? style) { + return style == null ? null : TextStyleDto.as(style); } // This method resolves the TextStyleAttribute to a TextStyle. @@ -287,14 +288,14 @@ class TextStyleDto extends Dto with Mergeable { @override TextStyle resolve(MixData mix) { return value - .map((e) => e.isTokenRef ? TextStyleDataDto.from(e.resolve(mix)) : e) + .map((e) => e.isTokenRef ? TextStyleData.from(e.resolve(mix)) : e) .reduce((value, element) => value.merge(element)) .resolve(mix); } @override TextStyleDto merge(TextStyleDto? other) { - return other == null ? this : TextStyleDto.raw([...value, ...other.value]); + return other == null ? this : TextStyleDto._([...value, ...other.value]); } @override diff --git a/lib/src/attributes/text_style/text_style_util.dart b/lib/src/attributes/text_style/text_style_util.dart index 1aae80197..372ffe519 100644 --- a/lib/src/attributes/text_style/text_style_util.dart +++ b/lib/src/attributes/text_style/text_style_util.dart @@ -40,7 +40,7 @@ import 'text_style_dto.dart'; class TextStyleUtility extends DtoUtility { - const TextStyleUtility(super.builder) : super(valueToDto: TextStyleDto.from); + const TextStyleUtility(super.builder) : super(valueToDto: TextStyleDto.as); T _only({ ColorDto? color, @@ -65,7 +65,7 @@ class TextStyleUtility double? height, }) { final textStyle = TextStyleDto( - TextStyleDataDto( + TextStyleData( background: background, backgroundColor: backgroundColor, color: color, @@ -432,7 +432,7 @@ class TextStyleUtility /// /// See also: /// * [TextStyleToken] - T token(TextStyleToken token) => builder(TextStyleDto.token(token)); + T of(TextStyleToken token) => builder(TextStyleDto.of(token)); /// Callable method for setting multiple values at once. /// diff --git a/lib/src/attributes/variant_attribute.dart b/lib/src/attributes/variant_attribute.dart index 416d094f0..832d9cb43 100644 --- a/lib/src/attributes/variant_attribute.dart +++ b/lib/src/attributes/variant_attribute.dart @@ -87,3 +87,15 @@ class MultiVariantAttribute extends VariantAttribute return MultiVariantAttribute(variant, _style.merge(other._style)); } } + +@immutable +class GestureContextVariantAttribute extends ContextVariantAttribute { + const GestureContextVariantAttribute(super.variant, super.style); + + @override + GestureContextVariantAttribute merge(GestureContextVariantAttribute other) { + if (other.variant != variant) throw throwArgumentError(other); + + return GestureContextVariantAttribute(variant, _style.merge(other._style)); + } +} diff --git a/lib/src/core/attribute.dart b/lib/src/core/attribute.dart index 5ea5206c8..6093604b1 100644 --- a/lib/src/core/attribute.dart +++ b/lib/src/core/attribute.dart @@ -108,7 +108,7 @@ mixin MultiChildRenderAttributeMixin @immutable abstract class Spec> extends ThemeExtension - with Comparable, Mergeable { + with Comparable { const Spec(); Duration lerpDuration(Duration a, Duration b, double t) { diff --git a/lib/src/core/extensions/values_ext.dart b/lib/src/core/extensions/values_ext.dart index 3eccb3476..ad1cdb1e9 100644 --- a/lib/src/core/extensions/values_ext.dart +++ b/lib/src/core/extensions/values_ext.dart @@ -5,13 +5,10 @@ import '../../attributes/border/border_dto.dart'; import '../../attributes/border/border_radius_attribute.dart'; import '../../attributes/border/border_radius_dto.dart'; import '../../attributes/color/color_dto.dart'; -import '../../attributes/constraints/constraints_attribute.dart'; import '../../attributes/constraints/constraints_dto.dart'; -import '../../attributes/decoration/decoration_attribute.dart'; import '../../attributes/decoration/decoration_dto.dart'; import '../../attributes/gradient/gradient_attribute.dart'; import '../../attributes/gradient/gradient_dto.dart'; -import '../../attributes/scalars/scalars_attribute.dart'; import '../../attributes/shadow/shadow_dto.dart'; import '../../attributes/spacing/spacing_dto.dart'; import '../../attributes/strut_style/strut_style_attribute.dart'; @@ -71,22 +68,14 @@ extension ColorExt on Color { } // Extension for Alignment -extension AlignmentGeometryExt on AlignmentGeometry { - AlignmentGeometryAttribute toAttribute() { - return AlignmentGeometryAttribute(this); - } -} +extension AlignmentGeometryExt on AlignmentGeometry {} extension BoxConstraintsExt on BoxConstraints { BoxConstraintsDto toDto() => BoxConstraintsDto.from(this); - - BoxConstraintsAttribute toAttribute() => BoxConstraintsAttribute(toDto()); } // Extension for Axis -extension AxisExt on Axis { - AxisAttribute toAttribute() => AxisAttribute(this); -} +extension AxisExt on Axis {} extension DecorationExt on Decoration { DecorationDto toDto() { @@ -95,8 +84,6 @@ extension DecorationExt on Decoration { throw UnimplementedError('$runtimeType is not implemented.'); } - - DecorationAttribute toAttribute() => DecorationAttribute(toDto()); } extension BoxDecorationExt on BoxDecoration { @@ -118,8 +105,6 @@ extension BorderRadiusGeometryExt on BorderRadiusGeometry { } extension Matrix4Ext on Matrix4 { - TransformAttribute toAttribute() => TransformAttribute(this); - /// Merge [other] into this matrix. Matrix4 merge(Matrix4? other) { if (other == null || other == this) return this; @@ -128,10 +113,6 @@ extension Matrix4Ext on Matrix4 { } } -extension ClipExt on Clip { - ClipBehaviorAttribute toAttribute() => ClipBehaviorAttribute(this); -} - extension BorderSideExt on BorderSide { BorderSideDto toDto() => BorderSideDto.from(this); } @@ -157,7 +138,7 @@ extension ListBoxShadowExt on List { } extension TextStyleExt on TextStyle { - TextStyleDto toDto() => TextStyleDto.from(this); + TextStyleDto toDto() => TextStyleDto.as(this); TextStyleAttribute toAttribute() => TextStyleAttribute(toDto()); } diff --git a/lib/src/deprecations.dart b/lib/src/deprecations.dart index acbce422b..3efee4da8 100644 --- a/lib/src/deprecations.dart +++ b/lib/src/deprecations.dart @@ -3,7 +3,6 @@ import 'dart:ui'; import 'package:flutter/material.dart'; import '../mix.dart'; -import 'attributes/text_style/text_style_dto.dart'; const kShortAliasDeprecation = 'Short aliases will be deprecated, you can create your own. Example: final p = padding;'; @@ -87,8 +86,8 @@ extension WithSpaceTokensExt } @Deprecated('Use mainAxisAlignment instead') -FlexMixAttribute mainAxis(MainAxisAlignment mainAxisAlignment) { - return FlexMixAttribute(mainAxisAlignment: mainAxisAlignment); +FlexSpecAttribute mainAxis(MainAxisAlignment mainAxisAlignment) { + return FlexSpecAttribute(mainAxisAlignment: mainAxisAlignment); } @Deprecated('Use onXSmall instead') @@ -290,7 +289,7 @@ StyleMixAttribute _apply(Iterable mixes) { } @Deprecated(kShortAliasDeprecation) -const p = padding; +final p = box.padding; @Deprecated(kShortAliasDeprecation) final pt = paddingTop; @@ -317,10 +316,10 @@ final px = paddingHorizontal; final py = paddingVertical; @Deprecated(kShortAliasDeprecation) -final pi = padding.as; +final pi = box.padding.as; @Deprecated(kShortAliasDeprecation) -const m = margin; +final m = box.margin; @Deprecated(kShortAliasDeprecation) final mt = marginTop; @Deprecated(kShortAliasDeprecation) @@ -346,23 +345,23 @@ final marginX = marginHorizontal; @Deprecated(kShortAliasDeprecation) final marginY = marginVertical; -@Deprecated('Use borderRadius instead') -const rounded = borderRadius; +@Deprecated('Use box.borderRadius instead') +final rounded = box.borderRadius; -@Deprecated('Use borderRadius instead') -const r = borderRadius; +@Deprecated('Use box.borderRadius instead') +final r = box.borderRadius; -@Deprecated('Use borderRadius.horizontal instead') +@Deprecated('Use box.borderRadius.horizontal instead') dynamic get roundedH => UnimplementedError(); -@Deprecated('use borderRadius.vertical instead') +@Deprecated('use box.borderRadius.vertical instead') dynamic get roundedV => UnimplementedError(); @Deprecated(kShortAliasDeprecation) dynamic get roundedDH => UnimplementedError(); @Deprecated(kShortAliasDeprecation) -final roundedTL = borderRadius.topLeft; +final roundedTL = box.borderRadius.topLeft; @Deprecated(kShortAliasDeprecation) BorderRadiusGeometryAttribute roundedTR() { @@ -400,69 +399,90 @@ BorderRadiusGeometryAttribute roundedBE() { } @Deprecated(kShortAliasDeprecation) -const h = height; +final h = box.height; + +@Deprecated('Use box.height instead') +final height = box.height; @Deprecated(kShortAliasDeprecation) -const w = width; +final w = box.width; + +@Deprecated('Use box.width instead') +final width = box.width; @Deprecated(kShortAliasDeprecation) -final maxH = maxHeight; +final maxH = box.maxWidth; + +@Deprecated('Use box.maxHeight instead') +final maxHeight = box.maxHeight; @Deprecated(kShortAliasDeprecation) final maxW = maxWidth; +@Deprecated('Use box.maxWidth instead') +final maxWidth = box.maxWidth; + @Deprecated(kShortAliasDeprecation) -final minH = minHeight; +final minH = box.minHeight; + +@Deprecated('Use box.minHeight instead') +final minHeight = box.minHeight; @Deprecated(kShortAliasDeprecation) -final minW = minWidth; +final minW = box.minWidth; + +@Deprecated('Use box.minWidth instead') +final minWidth = box.minWidth; @Deprecated(kShortAliasDeprecation) -final bt = border.top; +final bt = box.border.top; @Deprecated(kShortAliasDeprecation) -final bb = border.bottom; +final bb = box.border.bottom; @Deprecated(kShortAliasDeprecation) -final bl = border.left; +final bl = box.border.left; @Deprecated(kShortAliasDeprecation) -final br = border.right; +final br = box.border.right; @Deprecated(kShortAliasDeprecation) -final bs = border.start; +final bs = box.border.start; @Deprecated(kShortAliasDeprecation) -final be = border.end; +final be = box.border.end; + +@Deprecated('Use box.alignment instead') +final align = box.alignment; -@Deprecated('Use alignment instead') -const align = alignment; +@Deprecated('Use box.alignment instead') +final alignment = box.alignment; @Deprecated('Use stack instead') -AlignmentGeometryAttribute zAligmnent(Alignment alignment) { - return alignment.toAttribute(); +ContainerSpecAttribute zAligmnent(Alignment alignment) { + return box.alignment(alignment); } @Deprecated('Use stackFit instead') -StackMixAttribute zFit(StackFit fit) { - return StackMixAttribute(fit: fit); +StackSpecAttribute zFit(StackFit fit) { + return StackSpecAttribute(fit: fit); } @Deprecated('Use stack instead') -StackMixAttribute zClip(Clip clip) { - return StackMixAttribute(clipBehavior: clip); +StackSpecAttribute zClip(Clip clip) { + return StackSpecAttribute(clipBehavior: clip); } // Create a FlexAttributes for the direction axis. @Deprecated('Use axis() instead') -AxisAttribute direction(Axis direction) { - return AxisAttribute(direction); +FlexSpecAttribute directionAxis(Axis axis) { + return FlexSpecAttribute(direction: axis); } // Create a FlexAttributes for the cross axis. @Deprecated('Use crossAxisAlignment() instead') -FlexMixAttribute crossAxis(CrossAxisAlignment crossAxisAlignment) { - return FlexMixAttribute(crossAxisAlignment: crossAxisAlignment); +FlexSpecAttribute crossAxis(CrossAxisAlignment crossAxisAlignment) { + return FlexSpecAttribute(crossAxisAlignment: crossAxisAlignment); } @Deprecated('Use textDirective(directive)') @@ -485,104 +505,113 @@ TextMixAttribute overflow(TextOverflow overflow) { return TextMixAttribute(overflow: overflow); } -@Deprecated('use margin.only instead') -final marginOnly = margin.only; +@Deprecated('Use box.margin instead') +final margin = box.margin; -@Deprecated('use margin.only instead') -final marginDirectionalOnly = margin.only; +@Deprecated('use box.margin.only instead') +final marginOnly = box.margin.only; -@Deprecated('use margin.all instead') -final marginAll = margin.all; +@Deprecated('use box.margin.only instead') +final marginDirectionalOnly = box.margin.only; -@Deprecated('use margin.top instead') -final marginTop = margin.top; +@Deprecated('use box.margin.all instead') +final marginAll = box.margin.all; -@Deprecated('use margin.bottom instead') -final marginBottom = margin.bottom; +@Deprecated('use box.margin.top instead') +final marginTop = box.margin.top; -@Deprecated('use margin.left instead') -final marginLeft = margin.left; +@Deprecated('use box.margin.bottom instead') +final marginBottom = box.margin.bottom; -@Deprecated('use margin.right instead') -final marginRight = margin.right; +@Deprecated('use box.margin.left instead') +final marginLeft = box.margin.left; -@Deprecated('use margin.start instead') -final marginStart = margin.start; +@Deprecated('use box.margin.right instead') +final marginRight = box.margin.right; -@Deprecated('use margin.end instead') -final marginEnd = margin.end; +@Deprecated('use box.margin.start instead') +final marginStart = box.margin.start; -@Deprecated('use margin.horizontal instead') -final marginHorizontal = margin.horizontal; +@Deprecated('use box.margin.end instead') +final marginEnd = box.margin.end; -@Deprecated('use margin.vertical instead') -final marginVertical = margin.vertical; +@Deprecated('use box.margin.horizontal instead') +final marginHorizontal = box.margin.horizontal; -@Deprecated('use marginFrom instead') -final marginFrom = margin.as; +@Deprecated('use box.margin.vertical instead') +final marginVertical = box.margin.vertical; -@Deprecated('use padding.only instead') -final paddingOnly = padding.only; +@Deprecated('use box.margin.as instead') +final marginFrom = box.margin.as; -@Deprecated('use padding.only instead') -final paddingDirectionalOnly = padding.only; +@Deprecated('use box.padding instead') +final padding = box.padding; -@Deprecated('use padding.all instead') -final paddingAll = padding.all; +@Deprecated('use box.padding.only instead') +final paddingOnly = box.padding.only; -@Deprecated('use padding.top instead') -final paddingTop = padding.top; +@Deprecated('use box.padding.only instead') +final paddingDirectionalOnly = box.padding.only; -@Deprecated('use padding.bottom instead') -final paddingBottom = padding.bottom; +@Deprecated('use box.padding.all instead') +final paddingAll = box.padding.all; -@Deprecated('use padding.left instead') -final paddingLeft = padding.left; +@Deprecated('use box.padding.top instead') +final paddingTop = box.padding.top; -@Deprecated('use padding.right instead') -final paddingRight = padding.right; +@Deprecated('use box.padding.bottom instead') +final paddingBottom = box.padding.bottom; -@Deprecated('use padding.start instead') -final paddingStart = padding.start; +@Deprecated('use box.padding.left instead') +final paddingLeft = box.padding.left; -@Deprecated('use padding.end instead') -final paddingEnd = padding.end; +@Deprecated('use box.padding.right instead') +final paddingRight = box.padding.right; -@Deprecated('use padding.horizontal instead') -final paddingHorizontal = padding.horizontal; +@Deprecated('use box.padding.start instead') +final paddingStart = box.padding.start; -@Deprecated('use padding.vertical instead') -final paddingVertical = padding.vertical; +@Deprecated('use box.padding.end instead') +final paddingEnd = box.padding.end; -@Deprecated('use paddingFrom instead') -final paddingFrom = padding.as; +@Deprecated('use box.padding.horizontal instead') +final paddingHorizontal = box.padding.horizontal; -@Deprecated('use border.top instead') -final borderTop = border.top; +@Deprecated('use box.padding.vertical instead') +final paddingVertical = box.padding.vertical; -@Deprecated('use border.bottom instead') -final borderBottom = border.bottom; +@Deprecated('use box.margin.as instead') +final paddingFrom = box.padding.as; -@Deprecated('use border.left instead') -final borderLeft = border.left; +@Deprecated('Use box.border') +final border = box.border; -@Deprecated('use border.right instead') -final borderRight = border.right; +@Deprecated('use box.border.top instead') +final borderTop = box.border.top; -@Deprecated('use border.start instead') -final borderStart = border.start; +@Deprecated('use box.border.bottom instead') +final borderBottom = box.border.bottom; -@Deprecated('use border.end instead') -final borderEnd = border.end; +@Deprecated('use box.border.left instead') +final borderLeft = box.border.left; -@Deprecated('use border.horizontal instead') -final borderHorizontal = border.horizontal; +@Deprecated('use box.border.right instead') +final borderRight = box.border.right; -@Deprecated('use border.vertical instead') -final borderVertical = border.vertical; +@Deprecated('use box.border.start instead') +final borderStart = box.border.start; -@Deprecated('use border.all instead') -final borderAll = border.all; +@Deprecated('use box.border.end instead') +final borderEnd = box.border.end; + +@Deprecated('use box.border.horizontal instead') +final borderHorizontal = box.border.horizontal; + +@Deprecated('use box.border.vertical instead') +final borderVertical = box.border.vertical; + +@Deprecated('use box.border.all instead') +final borderAll = box.border.all; @Deprecated('Use StyledText now') typedef TextMix = StyledText; @@ -593,26 +622,29 @@ final textStyle = text.style; @Deprecated('Use text.style.shadow instead') final shadow = text.style.shadow; -@Deprecated('use backgroundColor instead') -const bgColor = backgroundColor; +@Deprecated('use box.color instead') +final bgColor = box.decoration.box.color; + +@Deprecated('use box.color instead') +final backgroundColor = box.decoration.box.color; // do no tuse main axisaligmnet use flex.mainAxisAlignment instead @Deprecated( 'use flex(mainAxisAlignment:value) instead or flex.mainAxisAlignment', ) -FlexMixAttribute mainAxisAlignment(MainAxisAlignment mainAxisAlignment) { - return FlexMixAttribute(mainAxisAlignment: mainAxisAlignment); +FlexSpecAttribute mainAxisAlignment(MainAxisAlignment mainAxisAlignment) { + return FlexSpecAttribute(mainAxisAlignment: mainAxisAlignment); } @Deprecated( 'use flex(crossAxisAlignment:value) instead or flex.crossAxisAlignment', ) -FlexMixAttribute crossAlignment(CrossAxisAlignment crossAxisAlignment) { - return FlexMixAttribute(crossAxisAlignment: crossAxisAlignment); +FlexSpecAttribute crossAlignment(CrossAxisAlignment crossAxisAlignment) { + return FlexSpecAttribute(crossAxisAlignment: crossAxisAlignment); } @Deprecated('use flex(mainAxisSize:value) instead or flex.mainAxisSize') -FlexMixAttribute mainAxisSize(MainAxisSize mainAxisSize) { +FlexSpecAttribute mainAxisSize(MainAxisSize mainAxisSize) { return flex(mainAxisSize: mainAxisSize); } @@ -622,3 +654,12 @@ TextMixAttribute bold() { style: TextStyleDto.only(fontWeight: FontWeight.bold), ); } + +@Deprecated('use box.border.radius') +final borderRadius = box.borderRadius; + +@Deprecated('use box.elevation instead') +final elevation = box.elevation; + +@Deprecated('use box.clipBehavior instead') +final clipBehavior = box.clipBehavior; diff --git a/lib/src/factory/mix_provider_data.dart b/lib/src/factory/mix_provider_data.dart index fa935fbe5..0e71b2b09 100644 --- a/lib/src/factory/mix_provider_data.dart +++ b/lib/src/factory/mix_provider_data.dart @@ -6,6 +6,7 @@ import '../core/attributes_map.dart'; import '../decorators/decorator.dart'; import '../helpers/compare_mixin.dart'; import '../theme/mix_theme.dart'; +import '../variants/context_variant.dart'; import 'style_mix.dart'; /// This class is used for encapsulating all [MixData] related operations. @@ -30,7 +31,7 @@ class MixData with Comparable { factory MixData.create(BuildContext context, StyleMix style) { final styleMix = applyContextToVisualAttributes(context, style); - final resolver = MixTokenResolver(context, MixTheme.of(context)); + final resolver = MixTokenResolver(context); return MixData._( resolver: resolver, @@ -114,12 +115,33 @@ List applyContextToVisualAttributes( return mix.styles.values.toList(); } + List contextVariantTypes = []; + List gestureVariantTypes = []; + for (ContextVariantAttribute attr in contextVariants) { - style = _applyVariants(context, style, attr); + if (attr.variant is GestureVariant) { + gestureVariantTypes.add(attr); + } else { + contextVariantTypes.add(attr); + } } for (MultiVariantAttribute attr in multiVariants) { - style = _applyVariants(context, style, attr); + if (attr.variant.hasGestureVariant) { + gestureVariantTypes.add(attr); + } else { + contextVariantTypes.add(attr); + } + } + + for (WhenVariant variant in contextVariantTypes) { + style = _applyVariants(context, style, variant); + } + + // Gesture Variants are applied after Context Variants + // As they take precedence over Context Variants from a styling perspective + for (WhenVariant variant in gestureVariantTypes) { + style = _applyVariants(context, style, variant); } return applyContextToVisualAttributes(context, style); diff --git a/lib/src/factory/style_mix.dart b/lib/src/factory/style_mix.dart index cc510843d..d50dfb8de 100644 --- a/lib/src/factory/style_mix.dart +++ b/lib/src/factory/style_mix.dart @@ -30,26 +30,25 @@ typedef Mix = StyleMix; /// final updatedStyle = style.selectVariant(myVariant); /// ``` class StyleMix with Comparable { - /// A constant, empty mix for use with const constructor widgets. - /// - /// This can be used as a default or initial value where a `StyleMix` is required. - static const empty = StyleMix._( - styles: StyleAttributeMap.empty(), - variants: VariantAttributeMap.empty(), - ); - /// Visual attributes contained in this mix. final StyleAttributeMap styles; /// The variant attributes contained in this mix. final VariantAttributeMap variants; - static final stack = SpreadFunctionParams(_styleType()); + static final stack = SpreadFunctionParams(_styleType()); static final text = SpreadFunctionParams(_styleType()); static final image = SpreadFunctionParams(_styleType()); static final container = SpreadFunctionParams(_styleType()); - static final flex = SpreadFunctionParams(_styleType()); + static final flex = SpreadFunctionParams(_styleType()); + + /// A constant, empty mix for use with const constructor widgets. + /// + /// This can be used as a default or initial value where a `StyleMix` is required. + const StyleMix.empty() + : styles = const StyleAttributeMap.empty(), + variants = const VariantAttributeMap.empty(); const StyleMix._({required this.styles, required this.variants}); @@ -142,7 +141,7 @@ class StyleMix with Comparable { StyleMix style, [ StyleMix? fallback, ]) { - return condition ? style : fallback ?? StyleMix.empty; + return condition ? style : fallback ?? const StyleMix.empty(); } /// Combines an optional positional list of [mixes] into a single `StyleMix`. @@ -156,7 +155,7 @@ class StyleMix with Comparable { /// ``` factory StyleMix.combineList(Iterable mixes) { return mixes.isEmpty - ? StyleMix.empty + ? const StyleMix.empty() : mixes.reduce((combinedStyle, mix) => combinedStyle.merge(mix)); } @@ -376,7 +375,7 @@ class StyleMix with Comparable { } } if (pickedVariants.isEmpty || matchedVariants.isEmpty) { - return isRecursive ? this : StyleMix.empty; + return isRecursive ? this : const StyleMix.empty(); } final pickedStyle = diff --git a/lib/src/helpers/compare_mixin.dart b/lib/src/helpers/compare_mixin.dart index dfd4a1d27..2dfe6d72c 100644 --- a/lib/src/helpers/compare_mixin.dart +++ b/lib/src/helpers/compare_mixin.dart @@ -1,5 +1,7 @@ // ignore_for_file: avoid-mutating-parameters +import 'package:flutter/material.dart'; + import '../core/extensions/iterable_ext.dart'; import 'deep_collection_equality.dart'; @@ -140,6 +142,7 @@ mixin Comparable { int get hashCode => runtimeType.hashCode ^ _mapPropsToHashCode(props); // Returns a list of properties that differ between this object and another. + @visibleForTesting List getDiff(Object other) { final diff = []; diff --git a/lib/src/recipes/container/container_attribute.dart b/lib/src/recipes/container/container_attribute.dart index fa35f0922..0ceeeb337 100644 --- a/lib/src/recipes/container/container_attribute.dart +++ b/lib/src/recipes/container/container_attribute.dart @@ -1,12 +1,7 @@ import 'package:flutter/material.dart'; -import '../../attributes/color/color_dto.dart'; -import '../../attributes/constraints/constraints_attribute.dart'; import '../../attributes/constraints/constraints_dto.dart'; -import '../../attributes/decoration/decoration_attribute.dart'; import '../../attributes/decoration/decoration_dto.dart'; -import '../../attributes/scalars/scalars_attribute.dart'; -import '../../attributes/spacing/spacing_attribute.dart'; import '../../attributes/spacing/spacing_dto.dart'; import '../../core/attribute.dart'; import '../../factory/mix_provider_data.dart'; @@ -21,7 +16,7 @@ class ContainerSpecAttribute final DecorationDto? decoration; final Matrix4? transform; final Clip? clipBehavior; - final ColorDto? color; + final double? width; final double? height; @@ -33,28 +28,10 @@ class ContainerSpecAttribute this.decoration, this.transform, this.clipBehavior, - this.color, this.width, this.height, }); - static ContainerSpecAttribute of(MixData mix) { - final attribute = mix.attributeOf(); - - return ContainerSpecAttribute( - alignment: mix.attributeOf()?.value, - padding: mix.attributeOf()?.value, - margin: mix.attributeOf()?.value, - constraints: mix.attributeOf()?.value, - decoration: mix.attributeOf()?.value, - transform: mix.attributeOf()?.value, - clipBehavior: mix.attributeOf()?.value, - color: mix.attributeOf()?.value, - width: mix.attributeOf()?.value, - height: mix.attributeOf()?.value, - ).merge(attribute); - } - @override ContainerSpec resolve(MixData mix) { return ContainerSpec( @@ -65,7 +42,6 @@ class ContainerSpecAttribute decoration: decoration?.resolve(mix), transform: transform, clipBehavior: clipBehavior, - color: color?.resolve(mix), width: width, height: height, ); @@ -83,7 +59,6 @@ class ContainerSpecAttribute decoration: decoration?.merge(other.decoration) ?? other.decoration, transform: other.transform ?? transform, clipBehavior: other.clipBehavior ?? clipBehavior, - color: color?.merge(other.color) ?? other.color, width: other.width ?? width, height: other.height ?? height, ); @@ -98,7 +73,6 @@ class ContainerSpecAttribute decoration, transform, clipBehavior, - color, width, height, ]; diff --git a/lib/src/recipes/container/container_spec.dart b/lib/src/recipes/container/container_spec.dart index c70c53340..600d40214 100644 --- a/lib/src/recipes/container/container_spec.dart +++ b/lib/src/recipes/container/container_spec.dart @@ -12,7 +12,6 @@ class ContainerSpec extends Spec { final Decoration? decoration; final Matrix4? transform; final Clip? clipBehavior; - final Color? color; final double? width, height; const ContainerSpec({ @@ -23,7 +22,6 @@ class ContainerSpec extends Spec { required this.decoration, required this.transform, required this.clipBehavior, - required this.color, required this.width, required this.height, }); @@ -35,29 +33,10 @@ class ContainerSpec extends Spec { constraints = null, decoration = null, transform = null, - color = null, width = null, height = null, clipBehavior = null; - @override - ContainerSpec merge(ContainerSpec? other) { - if (other == null) return this; - - return copyWith( - alignment: other.alignment, - padding: other.padding, - margin: other.margin, - constraints: other.constraints, - decoration: other.decoration, - width: other.width, - height: other.height, - transform: other.transform, - clipBehavior: other.clipBehavior, - color: other.color, - ); - } - @override ContainerSpec copyWith({ AlignmentGeometry? alignment, @@ -79,7 +58,6 @@ class ContainerSpec extends Spec { decoration: decoration ?? this.decoration, transform: transform ?? this.transform, clipBehavior: clipBehavior ?? this.clipBehavior, - color: color ?? this.color, width: width ?? this.width, height: height ?? this.height, ); @@ -95,7 +73,6 @@ class ContainerSpec extends Spec { decoration: Decoration.lerp(decoration, other.decoration, t), transform: Matrix4Tween(begin: transform, end: other.transform).lerp(t), clipBehavior: t < 0.5 ? clipBehavior : other.clipBehavior, - color: Color.lerp(color, other.color, t), width: lerpDouble(width, other.width, t), height: lerpDouble(height, other.height, t), ); @@ -112,6 +89,5 @@ class ContainerSpec extends Spec { decoration, transform, clipBehavior, - color, ]; } diff --git a/lib/src/recipes/container/container_util.dart b/lib/src/recipes/container/container_util.dart index 040946f61..e60ca5217 100644 --- a/lib/src/recipes/container/container_util.dart +++ b/lib/src/recipes/container/container_util.dart @@ -1,231 +1,23 @@ import 'package:flutter/material.dart'; -import '../../../exports.dart'; +import '../../attributes/border/border_radius_util.dart'; +import '../../attributes/border/border_util.dart'; import '../../attributes/color/color_util.dart'; import '../../attributes/constraints/constraints_dto.dart'; +import '../../attributes/constraints/constraints_util.dart'; import '../../attributes/decoration/decoration_dto.dart'; +import '../../attributes/decoration/decoration_util.dart'; +import '../../attributes/scalars/scalar_util.dart'; +import '../../attributes/shadow/shadow_util.dart'; import '../../attributes/spacing/spacing_dto.dart'; +import '../../attributes/spacing/spacing_util.dart'; +import '../../core/attribute.dart'; +import '../../core/extensions/values_ext.dart'; +import 'container_attribute.dart'; const container = ContainerUtility.selfBuilder; const box = ContainerUtility.selfBuilder; -const border = BoxBorderUtility(BoxBorderAttribute.new); - -/// Utility of `ClipUtility` that returns a `ClipBehaviorAttribute` instance -/// -/// Useful for defining the clipping behavior of widgets. -/// Includes predefined values of `Clip` such as `none`, `hardEdge`, and `antiAlias`. -/// Example: -/// ```dart -/// final noneClip = clipBehavior.none(); -/// final hardEdge = clipBehavior.hardEdge(); -/// final antiAlias = clipBehavior.antiAlias(); -/// ``` -/// See also: -/// - [ClipBehaviorAttribute] -/// - [Clip] -/// - [ClipUtility] -const clipBehavior = ClipUtility(ClipBehaviorAttribute.new); - -/// `padding` - Provides a comprehensive utility for defining padding attribute -/// -/// `padding` is an instance of `SpacingUtility`, offering a range of methods to apply custom padding -/// to various sides of a widget. Each method returns an object that can be used to construct a widget with -/// the specified padding attributes. -/// -/// Examples: -/// -/// Applying uniform padding: -/// ```dart -/// final uniform = padding.all(10); // Applies 10 units of padding on all sides. -/// ``` -/// -/// Applying horizontal padding: -/// ```dart -/// final horizontal = padding.horizontal(15); // Applies 15 units of padding on the left and right. -/// ``` -/// -/// Applying vertical padding: -/// ```dart -/// final vertical = padding.vertical(20); // Applies 20 units of padding on the top and bottom. -/// ``` -/// -/// Applying different padding values for each side: -/// ```dart -/// final custom = padding.only(top: 10, bottom: 20, left: 30, right: 40); -/// // Applies 10 units on top, 20 units on bottom, 30 units on left, and 40 units on right. -/// ``` -/// -/// Applying padding to a specific side: -/// ```dart -/// final top = padding.top(5); // Applies 5 units of padding at the top. -/// final bottom = padding.bottom(5); // Applies 5 units of padding at the bottom. -/// final left = padding.left(8); // Applies 8 units of padding on the left side. -/// final right = padding.right(8); // Applies 8 units of padding on the right side. -/// ``` -/// -/// Applying directional padding in RTL (Right-to-Left) layouts: -/// ```dart -/// final start = padding.start(10); // Applies 10 units of padding at the start side (considering text direction). -/// final end = padding.end(10); // Applies 10 units of padding at the end side (considering text direction). -/// ``` -/// -/// Using `SpacingUtility` callable method for flexible padding: -/// - 1 parameter: uniform spacing on all sides. -/// - 2 parameters: first for top and bottom, second for left and right. -/// - 3 parameters: first for top, second for left and right, third for bottom. -/// - 4 parameters: applied to top, right, bottom, and left respectively. -/// -/// Examples: -/// - `padding(10)`: uniform padding of 10 units on all sides. -/// - `padding(10, 20)`: top and bottom padding of 10 units, left and right padding of 20 units. -/// - `padding(10, 20, 30)`: top padding of 10 units, left and right padding of 20 units, bottom padding of 30 units. -/// - `padding(10, 20, 30, 40)`: top padding of 10 units, right padding of 20 units, bottom padding of 30 units, left padding of 40 units. -/// -/// `padding` effectively leverages `SpacingUtility` to create a versatile and readable way of applying padding, -/// making it easier to manage spacing in Flutter's layout system. -const padding = SpacingUtility(PaddingAttribute.new); - -/// `margin` - Provides a comprehensive utility for defining margin attribute -/// -/// `margin` is an instance of `SpacingUtility`, offering a range of methods to apply custom margin -/// to various sides of a widget. Each method returns an object that can be used to construct a widget with -/// the specified margin attributes. -/// -/// Examples: -/// -/// Applying uniform margin: -/// ```dart -/// final uniform = margin.all(10); // Applies 10 units of margin on all sides. -/// ``` -/// -/// Applying horizontal margin: -/// ```dart -/// final horizontal = margin.horizontal(15); // Applies 15 units of margin on the left and right. -/// ``` -/// -/// Applying vertical margin: -/// ```dart -/// final vertical = margin.vertical(20); // Applies 20 units of margin on the top and bottom. -/// ``` -/// -/// Applying different margin values for each side: -/// ```dart -/// final custom = margin.only(top: 10, bottom: 20, left: 30, right: 40); -/// // Applies 10 units on top, 20 units on bottom, 30 units on left, and 40 units on right. -/// ``` -/// -/// Applying margin to a specific side: -/// ```dart -/// final top = margin.top(5); // Applies 5 units of margin at the top. -/// final bottom = margin.bottom(5); // Applies 5 units of margin at the bottom. -/// final left = margin.left(8); // Applies 8 units of margin on the left side. -/// final right = margin.right(8); // Applies 8 units of margin on the right side. -/// ``` -/// -/// Applying directional margin in RTL (Right-to-Left) layouts: -/// ```dart -/// final start = margin.start(10); // Applies 10 units of margin at the start side (considering text direction). -/// final end = margin.end(10); // Applies 10 units of margin at the end side (considering text direction). -/// ``` -/// -/// Using `SpacingUtility` callable method for flexible margin: -/// - 1 parameter: uniform spacing on all sides. -/// - 2 parameters: first for top and bottom, second for left and right. -/// - 3 parameters: first for top, second for left and right, third for bottom. -/// - 4 parameters: applied to top, right, bottom, and left respectively. -/// -/// Examples: -/// - `margin(10)`: uniform margin of 10 units on all sides. -/// - `margin(10, 20)`: top and bottom margin of 10 units, left and right margin of 20 units. -/// - `margin(10, 20, 30)`: top margin of 10 units, left and right margin of 20 units, bottom margin of 30 units. -/// - `margin(10, 20, 30, 40)`: top margin of 10 units, right margin of 20 units, bottom margin of 30 units, left margin of 40 units. -/// -/// `margin` effectively leverages `SpacingUtility` to create a versatile and readable way of applying margin, -/// making it easier to manage spacing in Flutter's layout system. -const margin = SpacingUtility(MarginAttribute.new); - -// Provides an utility for creating a uniform BorderRadiusAttribute for all corners. -const borderRadius = - BorderRadiusGeometryUtility(BorderRadiusGeometryAttribute.new); -const alignment = AlignmentUtility(AlignmentGeometryAttribute.new); - -const backgroundColor = ColorUtility(BackgroundColorAttribute.new); - -const _decoration = DecorationUtility(DecorationAttribute.new); - -const _constraints = BoxConstraintsUtility(BoxConstraintsAttribute.new); - -final elevation = _decoration.box.elevation; -final boxShadow = _decoration.box.boxShadow; - -/// Defines a [BoxConstraintsAttribute] with a minimum width [minWidth]. -/// -/// This function sets a lower bound on the width of the box constraints but -/// doesn't set a fixed width. It allows flexibility above the specified [minWidth]. -/// -/// Equivalent to BoxConstraints(minWidth: minWidth). -/// -/// See also: -/// - [BoxConstraintsAttribute] -/// - [BoxConstraints] -/// - [BoxConstraintsUtility] -final minWidth = _constraints.minWidth; - -/// Defines a [BoxConstraintsAttribute] with a maximum width [maxWidth]. -/// -/// This function sets an upper limit on the width of the box constraints. The width -/// can be any value up to [maxWidth], offering flexibility in sizing. -/// -/// Equivalent to BoxConstraints(maxWidth: maxWidth). -/// -/// See also: -/// - [BoxConstraintsAttribute] -/// - [BoxConstraints] -/// - [BoxConstraintsUtility] -final maxWidth = _constraints.maxWidth; - -/// Creates a [BoxConstraintsAttribute] with a minimum height [minHeight]. -/// -/// This function sets a lower limit on the height of the box constraints, allowing -/// any height above the specified [minHeight], thereby providing vertical sizing flexibility. -/// -/// Equivalent to BoxConstraints(minHeight: minHeight). -/// -/// See also: -/// - [BoxConstraintsAttribute] -/// - [BoxConstraints] -/// - [BoxConstraintsUtility] -final minHeight = _constraints.minHeight; - -/// Creates a [BoxConstraintsAttribute] with a maximum height [maxHeight]. -/// -/// This function sets an upper bound on the height of the box constraints. The height -/// can be any value up to [maxHeight], enabling flexibility in vertical sizing. -/// -/// Equivalent to BoxConstraints(maxHeight: maxHeight). -/// -/// See also: -/// - [BoxConstraintsAttribute] -/// - [BoxConstraints] -/// - [BoxConstraintsUtility] -final maxHeight = _constraints.maxHeight; - -/// Creates a [WidthAttribute] with a specific [width]. -/// -/// The returned [WidthAttribute] instance imposes the given [width] as -/// a fixed size, ignoring any minimum or maximum width constraints. -/// -/// [width]: The fixed width value for the constraints. -const width = WidthAttribute.new; - -/// Creates a [HeightAttriubte] with a specific [height]. -/// -/// The returned [HeightAttribute] instance imposes the given [height] as -/// a fixed size, ignoring any minimum or maximum height constraints. -/// [height]: The fixed height value for the constraints. -const height = HeightAttribute.new; - class ContainerUtility extends MixUtility { static const selfBuilder = ContainerUtility(MixUtility.selfBuilder); @@ -241,7 +33,6 @@ class ContainerUtility double? height, Matrix4? transform, Clip? clipBehavior, - ColorDto? color, }) { return builder( ContainerSpecAttribute( @@ -252,32 +43,146 @@ class ContainerUtility decoration: decoration, transform: transform, clipBehavior: clipBehavior, - color: color, width: width, height: height, ), ); } - BoxDecorationUtility get decoration { - return BoxDecorationUtility((decoration) => _only(decoration: decoration)); + DecorationUtility get decoration { + return DecorationUtility((decoration) => _only(decoration: decoration)); } AlignmentUtility get alignment { return AlignmentUtility((alignment) => call(alignment: alignment)); } + /// `padding` - Provides a comprehensive utility for defining padding attribute + /// + /// `padding` is an instance of `SpacingUtility`, offering a range of methods to apply custom padding + /// to various sides of a widget. Each method returns an object that can be used to construct a widget with + /// the specified padding attributes. + /// + /// Examples: + /// + /// Applying uniform padding: + /// ```dart + /// final uniform = padding.all(10); // Applies 10 units of padding on all sides. + /// ``` + /// + /// Applying horizontal padding: + /// ```dart + /// final horizontal = padding.horizontal(15); // Applies 15 units of padding on the left and right. + /// ``` + /// + /// Applying vertical padding: + /// ```dart + /// final vertical = padding.vertical(20); // Applies 20 units of padding on the top and bottom. + /// ``` + /// + /// Applying different padding values for each side: + /// ```dart + /// final custom = padding.only(top: 10, bottom: 20, left: 30, right: 40); + /// // Applies 10 units on top, 20 units on bottom, 30 units on left, and 40 units on right. + /// ``` + /// + /// Applying padding to a specific side: + /// ```dart + /// final top = padding.top(5); // Applies 5 units of padding at the top. + /// final bottom = padding.bottom(5); // Applies 5 units of padding at the bottom. + /// final left = padding.left(8); // Applies 8 units of padding on the left side. + /// final right = padding.right(8); // Applies 8 units of padding on the right side. + /// ``` + /// + /// Applying directional padding in RTL (Right-to-Left) layouts: + /// ```dart + /// final start = padding.start(10); // Applies 10 units of padding at the start side (considering text direction). + /// final end = padding.end(10); // Applies 10 units of padding at the end side (considering text direction). + /// ``` + /// + /// Using `SpacingUtility` callable method for flexible padding: + /// - 1 parameter: uniform spacing on all sides. + /// - 2 parameters: first for top and bottom, second for left and right. + /// - 3 parameters: first for top, second for left and right, third for bottom. + /// - 4 parameters: applied to top, right, bottom, and left respectively. + /// + /// Examples: + /// - `padding(10)`: uniform padding of 10 units on all sides. + /// - `padding(10, 20)`: top and bottom padding of 10 units, left and right padding of 20 units. + /// - `padding(10, 20, 30)`: top padding of 10 units, left and right padding of 20 units, bottom padding of 30 units. + /// - `padding(10, 20, 30, 40)`: top padding of 10 units, right padding of 20 units, bottom padding of 30 units, left padding of 40 units. + /// + /// `padding` effectively leverages `SpacingUtility` to create a versatile and readable way of applying padding, + /// making it easier to manage spacing in Flutter's layout system. SpacingUtility get padding { return SpacingUtility((padding) => _only(padding: padding)); } + /// `margin` - Provides a comprehensive utility for defining margin attribute + /// + /// `margin` is an instance of `SpacingUtility`, offering a range of methods to apply custom margin + /// to various sides of a widget. Each method returns an object that can be used to construct a widget with + /// the specified margin attributes. + /// + /// Examples: + /// + /// Applying uniform margin: + /// ```dart + /// final uniform = margin.all(10); // Applies 10 units of margin on all sides. + /// ``` + /// + /// Applying horizontal margin: + /// ```dart + /// final horizontal = margin.horizontal(15); // Applies 15 units of margin on the left and right. + /// ``` + /// + /// Applying vertical margin: + /// ```dart + /// final vertical = margin.vertical(20); // Applies 20 units of margin on the top and bottom. + /// ``` + /// + /// Applying different margin values for each side: + /// ```dart + /// final custom = margin.only(top: 10, bottom: 20, left: 30, right: 40); + /// // Applies 10 units on top, 20 units on bottom, 30 units on left, and 40 units on right. + /// ``` + /// + /// Applying margin to a specific side: + /// ```dart + /// final top = margin.top(5); // Applies 5 units of margin at the top. + /// final bottom = margin.bottom(5); // Applies 5 units of margin at the bottom. + /// final left = margin.left(8); // Applies 8 units of margin on the left side. + /// final right = margin.right(8); // Applies 8 units of margin on the right side. + /// ``` + /// + /// Applying directional margin in RTL (Right-to-Left) layouts: + /// ```dart + /// final start = margin.start(10); // Applies 10 units of margin at the start side (considering text direction). + /// final end = margin.end(10); // Applies 10 units of margin at the end side (considering text direction). + /// ``` + /// + /// Using `SpacingUtility` callable method for flexible margin: + /// - 1 parameter: uniform spacing on all sides. + /// - 2 parameters: first for top and bottom, second for left and right. + /// - 3 parameters: first for top, second for left and right, third for bottom. + /// - 4 parameters: applied to top, right, bottom, and left respectively. + /// + /// Examples: + /// - `margin(10)`: uniform margin of 10 units on all sides. + /// - `margin(10, 20)`: top and bottom margin of 10 units, left and right margin of 20 units. + /// - `margin(10, 20, 30)`: top margin of 10 units, left and right margin of 20 units, bottom margin of 30 units. + /// - `margin(10, 20, 30, 40)`: top margin of 10 units, right margin of 20 units, bottom margin of 30 units, left margin of 40 units. + /// + /// `margin` effectively leverages `SpacingUtility` to create a versatile and readable way of applying margin, + /// making it easier to manage spacing in Flutter's layout system. SpacingUtility get margin { return SpacingUtility((margin) => _only(margin: margin)); } - ColorUtility get color { - return ColorUtility((color) => _only(color: color)); - } + // We use BoxDecoration for better Decoration support to avoid weird issues + ColorUtility get color => decoration.box.color; + + ElevationUtility get elevation => decoration.box.elevation; BoxConstraintsUtility get constraints { return BoxConstraintsUtility( @@ -293,9 +198,29 @@ class ContainerUtility return ClipUtility((clipBehavior) => call(clipBehavior: clipBehavior)); } - T height(double height) => _only(height: height); + /// Decoration Utilities + BoxBorderUtility get border => decoration.box.border; + + BorderRadiusGeometryUtility get borderRadius => + decoration.box.borderRadius; + + BoxShadowListUtility get shadows => decoration.box.boxShadows; + + BoxShadowUtility get shadow => decoration.box.boxShadow; + + /// Constraints utilities + DoubleUtility get maxWidth => constraints.maxWidth; + + DoubleUtility get minWidth => constraints.minWidth; + + DoubleUtility get maxHeight => constraints.maxHeight; + + DoubleUtility get minHeight => constraints.minHeight; + + DoubleUtility get width => DoubleUtility((width) => _only(width: width)); - T width(double width) => _only(width: width); + DoubleUtility get height => + DoubleUtility((height) => _only(height: height)); T call({ AlignmentGeometry? alignment, @@ -307,7 +232,6 @@ class ContainerUtility BoxDecoration? decoration, Matrix4? transform, Clip? clipBehavior, - Color? color, }) { final attribute = ContainerSpecAttribute( alignment: alignment, @@ -317,7 +241,6 @@ class ContainerUtility decoration: decoration?.toDto(), transform: transform, clipBehavior: clipBehavior, - color: color?.toDto(), width: width, height: height, ); diff --git a/lib/src/recipes/container/container_widget.dart b/lib/src/recipes/container/container_widget.dart index e13507a62..981da2431 100644 --- a/lib/src/recipes/container/container_widget.dart +++ b/lib/src/recipes/container/container_widget.dart @@ -1,11 +1,11 @@ import 'package:flutter/material.dart'; -import '../../helpers/build_context_ext.dart'; import '../../widgets/styled_widget.dart'; import 'container_attribute.dart'; import 'container_spec.dart'; typedef Box = StyledContainer; +typedef AnimatedBox = AnimatedStyleContainer; class StyledContainer extends StyledWidget { const StyledContainer({super.style, super.key, super.inherit, this.child}); @@ -14,41 +14,96 @@ class StyledContainer extends StyledWidget { @override Widget build(BuildContext context) { - final contextMix = context.mix; - final inheritedAttribute = inherit && contextMix != null - ? ContainerSpecAttribute.of(contextMix) - : const ContainerSpecAttribute(); - return withMix(context, (mix) { - final attribute = ContainerSpecAttribute.of(mix); - final merged = inheritedAttribute.merge(attribute); + final spec = mix.attributeOf()?.resolve(mix) ?? + const ContainerSpec.empty(); + + return ContainerSpecWidget(spec, child: child); + }); + } +} + +class AnimatedStyleContainer extends StyledWidget { + const AnimatedStyleContainer({ + super.style, + super.key, + super.inherit, + this.child, + this.curve, + this.duration, + }); - final mixture = merged.resolve(mix); + final Widget? child; + final Curve? curve; + final Duration? duration; + + @override + Widget build(BuildContext context) { + return withMix(context, (mix) { + final spec = mix.attributeOf()?.resolve(mix) ?? + const ContainerSpec.empty(); - return MixedContainer(mixture, child: child); + return AnimatedContainerSpecWidget( + spec, + curve: curve, + duration: duration, + child: child, + ); }); } } -class MixedContainer extends StatelessWidget { - const MixedContainer(this.mixture, {super.key, this.child}); +class ContainerSpecWidget extends StatelessWidget { + const ContainerSpecWidget(this.spec, {super.key, this.child}); final Widget? child; - final ContainerSpec mixture; + final ContainerSpec spec; @override Widget build(BuildContext context) { return Container( - alignment: mixture.alignment, - padding: mixture.padding, - color: mixture.color, - decoration: mixture.decoration, - width: mixture.width, - height: mixture.height, - constraints: mixture.constraints, - margin: mixture.margin, - transform: mixture.transform, - clipBehavior: mixture.clipBehavior ?? Clip.none, + alignment: spec.alignment, + padding: spec.padding, + decoration: spec.decoration, + width: spec.width, + height: spec.height, + constraints: spec.constraints, + margin: spec.margin, + transform: spec.transform, + clipBehavior: spec.clipBehavior ?? Clip.none, + child: child, + ); + } +} + +class AnimatedContainerSpecWidget extends StatelessWidget { + const AnimatedContainerSpecWidget( + this.spec, { + super.key, + this.child, + this.curve, + this.duration, + }); + + final Widget? child; + final Curve? curve; + final Duration? duration; + final ContainerSpec spec; + + @override + Widget build(BuildContext context) { + return AnimatedContainer( + alignment: spec.alignment, + padding: spec.padding, + decoration: spec.decoration, + width: spec.width, + height: spec.height, + constraints: spec.constraints, + margin: spec.margin, + transform: spec.transform, + clipBehavior: spec.clipBehavior ?? Clip.none, + curve: curve ?? Curves.linear, + duration: duration ?? const Duration(milliseconds: 150), child: child, ); } diff --git a/lib/src/recipes/flex/flex_attribute.dart b/lib/src/recipes/flex/flex_attribute.dart index 10f29c7aa..499118aa6 100644 --- a/lib/src/recipes/flex/flex_attribute.dart +++ b/lib/src/recipes/flex/flex_attribute.dart @@ -4,7 +4,8 @@ import '../../core/attribute.dart'; import '../../factory/mix_provider_data.dart'; import 'flex_spec.dart'; -class FlexMixAttribute extends ResolvableAttribute { +class FlexSpecAttribute + extends ResolvableAttribute { final Axis? direction; final MainAxisAlignment? mainAxisAlignment; final CrossAxisAlignment? crossAxisAlignment; @@ -15,7 +16,7 @@ class FlexMixAttribute extends ResolvableAttribute { final Clip? clipBehavior; final double? gap; - const FlexMixAttribute({ + const FlexSpecAttribute({ this.direction, this.mainAxisAlignment, this.crossAxisAlignment, @@ -27,8 +28,8 @@ class FlexMixAttribute extends ResolvableAttribute { this.gap, }); - static FlexMixAttribute of(MixData mix) { - return mix.attributeOf() ?? const FlexMixAttribute(); + static FlexSpecAttribute of(MixData mix) { + return mix.attributeOf() ?? const FlexSpecAttribute(); } @override @@ -47,10 +48,10 @@ class FlexMixAttribute extends ResolvableAttribute { } @override - FlexMixAttribute merge(covariant FlexMixAttribute? other) { + FlexSpecAttribute merge(covariant FlexSpecAttribute? other) { if (other == null) return this; - return FlexMixAttribute( + return FlexSpecAttribute( direction: other.direction ?? direction, mainAxisAlignment: other.mainAxisAlignment ?? mainAxisAlignment, crossAxisAlignment: other.crossAxisAlignment ?? crossAxisAlignment, diff --git a/lib/src/recipes/flex/flex_spec.dart b/lib/src/recipes/flex/flex_spec.dart index f21998777..093ad8885 100644 --- a/lib/src/recipes/flex/flex_spec.dart +++ b/lib/src/recipes/flex/flex_spec.dart @@ -41,9 +41,9 @@ class FlexSpec extends Spec { gap = null; static FlexSpec resolve(MixData mix) { - final recipe = mix.attributeOf()?.resolve(mix); + final recipe = mix.attributeOf()?.resolve(mix); - return recipe ?? const FlexMixAttribute().resolve(mix); + return recipe ?? const FlexSpecAttribute().resolve(mix); } @override @@ -64,21 +64,6 @@ class FlexSpec extends Spec { ); } - @override - FlexSpec merge(FlexSpec? other) { - return copyWith( - direction: other?.direction, - mainAxisAlignment: other?.mainAxisAlignment, - crossAxisAlignment: other?.crossAxisAlignment, - mainAxisSize: other?.mainAxisSize, - verticalDirection: other?.verticalDirection, - textDirection: other?.textDirection, - textBaseline: other?.textBaseline, - clipBehavior: other?.clipBehavior, - gap: other?.gap, - ); - } - @override FlexSpec copyWith({ Axis? direction, diff --git a/lib/src/recipes/flex/flex_util.dart b/lib/src/recipes/flex/flex_util.dart index 86ab05b79..3d44ff6e1 100644 --- a/lib/src/recipes/flex/flex_util.dart +++ b/lib/src/recipes/flex/flex_util.dart @@ -1,12 +1,15 @@ import 'package:flutter/material.dart'; -import '../../../mix.dart'; +import '../../attributes/scalars/scalar_util.dart'; +import '../../attributes/spacing/spacing_util.dart'; +import '../../core/attribute.dart'; +import 'flex_attribute.dart'; -/// A utility class for building [FlexMixAttribute]s. +/// A utility class for building [FlexSpecAttribute]s. final flex = FlexSpecUtility.selfBuilder; class FlexSpecUtility - extends MixUtility { + extends MixUtility { static final selfBuilder = FlexSpecUtility((value) => value); const FlexSpecUtility(super.builder); @@ -73,7 +76,7 @@ class FlexSpecUtility Clip? clipBehavior, double? gap, }) { - final attriubte = FlexMixAttribute( + final attriubte = FlexSpecAttribute( direction: direction, mainAxisAlignment: mainAxisAlignment, crossAxisAlignment: crossAxisAlignment, diff --git a/lib/src/recipes/flex/flex_widget.dart b/lib/src/recipes/flex/flex_widget.dart index c91c4ad31..77c7cd283 100644 --- a/lib/src/recipes/flex/flex_widget.dart +++ b/lib/src/recipes/flex/flex_widget.dart @@ -1,9 +1,9 @@ import 'package:flutter/widgets.dart'; -import '../../helpers/build_context_ext.dart'; import '../../widgets/gap_widget.dart'; import '../../widgets/styled_widget.dart'; import '../container/container_attribute.dart'; +import '../container/container_spec.dart'; import '../container/container_widget.dart'; import 'flex_attribute.dart'; import 'flex_spec.dart'; @@ -40,19 +40,11 @@ class StyledFlex extends StyledWidget { @override Widget build(BuildContext context) { - final contextMix = context.mix; - final inheritedAttribute = inherit && contextMix != null - ? FlexMixAttribute.of(contextMix) - : const FlexMixAttribute(); - return withMix(context, (mix) { - final attribute = FlexMixAttribute.of(mix); - final merged = inheritedAttribute.merge(attribute); - - final mixture = merged.resolve(mix); + final spec = FlexSpecAttribute.of(mix).resolve(mix); List renderSpacedChildren() { - final gap = mixture.gap; + final gap = spec.gap; return gap == null ? children @@ -63,7 +55,7 @@ class StyledFlex extends StyledWidget { } return MixedFlex( - mixture, + spec, direction: direction, children: renderSpacedChildren(), ); @@ -182,16 +174,15 @@ class FlexBox extends StyledWidget { @override Widget build(BuildContext context) { return withMix(context, (mix) { - final containerStyle = ContainerSpecAttribute.of(mix).resolve(mix); - final flexStyle = FlexMixAttribute.of(mix).resolve(mix); - - return MixedContainer( - containerStyle, - child: MixedFlex( - flexStyle, - direction: direction, - children: children, - ), + final containerSpec = + mix.attributeOf()?.resolve(mix) ?? + const ContainerSpec.empty(); + final flexSpec = mix.attributeOf()?.resolve(mix) ?? + const FlexSpec.empty(); + + return ContainerSpecWidget( + containerSpec, + child: MixedFlex(flexSpec, direction: direction, children: children), ); }); } diff --git a/lib/src/recipes/icon/icon_attribute.dart b/lib/src/recipes/icon/icon_attribute.dart index 5900a9bb2..96a214fac 100644 --- a/lib/src/recipes/icon/icon_attribute.dart +++ b/lib/src/recipes/icon/icon_attribute.dart @@ -3,15 +3,12 @@ import '../../core/attribute.dart'; import '../../factory/mix_provider_data.dart'; import 'icon_spec.dart'; -class IconMixAttribute extends ResolvableAttribute { +class IconSpecAttribute + extends ResolvableAttribute { final double? size; final ColorDto? color; - const IconMixAttribute({this.size, this.color}); - - static IconMixAttribute of(MixData mix) { - return mix.attributeOf() ?? const IconMixAttribute(); - } + const IconSpecAttribute({this.size, this.color}); @override IconSpec resolve(MixData mix) { @@ -19,10 +16,10 @@ class IconMixAttribute extends ResolvableAttribute { } @override - IconMixAttribute merge(covariant IconMixAttribute? other) { + IconSpecAttribute merge(covariant IconSpecAttribute? other) { if (other == null) return this; - return IconMixAttribute( + return IconSpecAttribute( size: size ?? other.size, color: color ?? other.color, ); diff --git a/lib/src/recipes/icon/icon_spec.dart b/lib/src/recipes/icon/icon_spec.dart index 658c44e5e..2ceb379c0 100644 --- a/lib/src/recipes/icon/icon_spec.dart +++ b/lib/src/recipes/icon/icon_spec.dart @@ -15,9 +15,9 @@ class IconSpec extends Spec { size = null; static IconSpec resolve(MixData mix) { - final recipe = mix.attributeOf()?.resolve(mix); + final recipe = mix.attributeOf()?.resolve(mix); - return recipe ?? const IconMixAttribute().resolve(mix); + return recipe ?? const IconSpecAttribute().resolve(mix); } @override @@ -28,11 +28,6 @@ class IconSpec extends Spec { ); } - @override - IconSpec merge(IconSpec? other) { - return copyWith(color: other?.color, size: other?.size); - } - @override IconSpec copyWith({ Color? color, diff --git a/lib/src/recipes/icon/icon_util.dart b/lib/src/recipes/icon/icon_util.dart index 05f8ef55c..056b45876 100644 --- a/lib/src/recipes/icon/icon_util.dart +++ b/lib/src/recipes/icon/icon_util.dart @@ -9,19 +9,19 @@ import 'icon_attribute.dart'; const icon = IconUtility.selfBuilder; class IconUtility - extends MixUtility { + extends MixUtility { static const selfBuilder = IconUtility(MixUtility.selfBuilder); const IconUtility(super.builder); ColorUtility get color { - return ColorUtility((color) => builder(IconMixAttribute(color: color))); + return ColorUtility((color) => builder(IconSpecAttribute(color: color))); } T size(double size) { - return builder(IconMixAttribute(size: size)); + return builder(IconSpecAttribute(size: size)); } - IconMixAttribute call({double? size, Color? color}) { - return IconMixAttribute(size: size, color: color?.toDto()); + IconSpecAttribute call({double? size, Color? color}) { + return IconSpecAttribute(size: size, color: color?.toDto()); } } diff --git a/lib/src/recipes/icon/icon_widget.dart b/lib/src/recipes/icon/icon_widget.dart index 0a66410ee..62d8878d5 100644 --- a/lib/src/recipes/icon/icon_widget.dart +++ b/lib/src/recipes/icon/icon_widget.dart @@ -1,8 +1,8 @@ import 'package:flutter/material.dart'; -import '../../helpers/build_context_ext.dart'; import '../../widgets/styled_widget.dart'; import 'icon_attribute.dart'; +import 'icon_spec.dart'; class StyledIcon extends StyledWidget { const StyledIcon( @@ -10,7 +10,7 @@ class StyledIcon extends StyledWidget { this.semanticLabel, super.style, super.key, - super.inherit, + super.inherit = true, this.textDirection, }); @@ -20,21 +20,14 @@ class StyledIcon extends StyledWidget { @override Widget build(BuildContext context) { - final contextMix = context.mix; - final inheritedAttribute = inherit && contextMix != null - ? IconMixAttribute.of(contextMix) - : const IconMixAttribute(); - return withMix(context, (mix) { - final attribute = IconMixAttribute.of(mix); - final merged = inheritedAttribute.merge(attribute); - - final mixture = merged.resolve(mix); + final spec = mix.attributeOf()?.resolve(mix) ?? + const IconSpec.empty(); return Icon( icon, - size: mixture.size, - color: mixture.color, + size: spec.size, + color: spec.color, semanticLabel: semanticLabel, textDirection: textDirection, ); @@ -60,22 +53,15 @@ class AnimatedStyledIcon extends StyledWidget { @override Widget build(BuildContext context) { - final inheritedAttribute = inherit && context.mix != null - // ignore: avoid-non-null-assertion - ? IconMixAttribute.of(context.mix!) - : const IconMixAttribute(); - return withMix(context, (mix) { - final attribute = IconMixAttribute.of(mix); - final merged = inheritedAttribute.merge(attribute); - - final mixture = merged.resolve(mix); + final spec = mix.attributeOf()?.resolve(mix) ?? + const IconSpec.empty(); return AnimatedIcon( icon: icon, progress: progress, - color: mixture.color, - size: mixture.size, + color: spec.color, + size: spec.size, semanticLabel: semanticLabel, textDirection: textDirection, ); diff --git a/lib/src/recipes/image/image_attribute.dart b/lib/src/recipes/image/image_attribute.dart index ff1506ca8..3108f2186 100644 --- a/lib/src/recipes/image/image_attribute.dart +++ b/lib/src/recipes/image/image_attribute.dart @@ -37,11 +37,11 @@ class ImageMixAttribute if (other == null) return this; return ImageMixAttribute( - width: width ?? other.width, - height: height ?? other.height, - color: color ?? other.color, - repeat: repeat ?? other.repeat, - fit: fit ?? other.fit, + width: other.width ?? width, + height: other.height ?? height, + color: other.color ?? color, + repeat: other.repeat ?? repeat, + fit: other.fit ?? fit, ); } diff --git a/lib/src/recipes/image/image_spec.dart b/lib/src/recipes/image/image_spec.dart index 9d8051417..29a06d07a 100644 --- a/lib/src/recipes/image/image_spec.dart +++ b/lib/src/recipes/image/image_spec.dart @@ -35,17 +35,6 @@ class ImageSpec extends Spec { return recipe ?? const ImageMixAttribute().resolve(mix); } - @override - ImageSpec merge(ImageSpec? other) { - return copyWith( - width: other?.width, - height: other?.height, - color: other?.color, - repeat: other?.repeat, - fit: other?.fit, - ); - } - @override ImageSpec lerp(ImageSpec? other, double t) { return ImageSpec( diff --git a/lib/src/recipes/stack/stack_attribute.dart b/lib/src/recipes/stack/stack_attribute.dart index abaf356b0..633f885c3 100644 --- a/lib/src/recipes/stack/stack_attribute.dart +++ b/lib/src/recipes/stack/stack_attribute.dart @@ -4,13 +4,13 @@ import '../../core/attribute.dart'; import '../../factory/mix_provider_data.dart'; import 'stack_spec.dart'; -class StackMixAttribute - extends ResolvableAttribute { +class StackSpecAttribute + extends ResolvableAttribute { final Clip? _clipBehavior; final TextDirection? _textDirection; final StackFit? _fit; final AlignmentGeometry? _alignment; - const StackMixAttribute({ + const StackSpecAttribute({ AlignmentGeometry? alignment, StackFit? fit, TextDirection? textDirection, @@ -20,8 +20,8 @@ class StackMixAttribute _fit = fit, _alignment = alignment; - static StackMixAttribute of(MixData mix) { - return mix.attributeOf() ?? const StackMixAttribute(); + static StackSpecAttribute of(MixData mix) { + return mix.attributeOf() ?? const StackSpecAttribute(); } @override @@ -35,10 +35,10 @@ class StackMixAttribute } @override - StackMixAttribute merge(covariant StackMixAttribute? other) { + StackSpecAttribute merge(covariant StackSpecAttribute? other) { if (other == null) return this; - return StackMixAttribute( + return StackSpecAttribute( alignment: other._alignment ?? _alignment, fit: other._fit ?? _fit, textDirection: other._textDirection ?? _textDirection, diff --git a/lib/src/recipes/stack/stack_spec.dart b/lib/src/recipes/stack/stack_spec.dart index 93d1d272c..4b3487009 100644 --- a/lib/src/recipes/stack/stack_spec.dart +++ b/lib/src/recipes/stack/stack_spec.dart @@ -15,6 +15,12 @@ class StackSpec extends Spec { this.clipBehavior, }); + const StackSpec.empty() + : alignment = null, + fit = null, + textDirection = null, + clipBehavior = null; + @override StackSpec lerp(StackSpec other, double t) { return StackSpec( @@ -25,16 +31,6 @@ class StackSpec extends Spec { ); } - @override - StackSpec merge(StackSpec? other) { - return copyWith( - alignment: other?.alignment, - fit: other?.fit, - textDirection: other?.textDirection, - clipBehavior: other?.clipBehavior, - ); - } - @override StackSpec copyWith({ AlignmentGeometry? alignment, diff --git a/lib/src/recipes/stack/stack_util.dart b/lib/src/recipes/stack/stack_util.dart index 96838e61a..e7d1eabbc 100644 --- a/lib/src/recipes/stack/stack_util.dart +++ b/lib/src/recipes/stack/stack_util.dart @@ -7,7 +7,7 @@ import 'stack_attribute.dart'; const stack = StackSpecUtility.selfBuilder; class StackSpecUtility - extends MixUtility { + extends MixUtility { static const selfBuilder = StackSpecUtility(MixUtility.selfBuilder); const StackSpecUtility(super.builder); @@ -18,7 +18,7 @@ class StackSpecUtility TextDirection? textDirection, Clip? clipBehavior, }) { - final stack = StackMixAttribute( + final stack = StackSpecAttribute( alignment: alignment, fit: fit, textDirection: textDirection, diff --git a/lib/src/recipes/stack/stack_widget.dart b/lib/src/recipes/stack/stack_widget.dart index b40805c04..14efc9328 100644 --- a/lib/src/recipes/stack/stack_widget.dart +++ b/lib/src/recipes/stack/stack_widget.dart @@ -1,8 +1,8 @@ import 'package:flutter/widgets.dart'; -import '../../helpers/build_context_ext.dart'; import '../../widgets/styled_widget.dart'; import '../container/container_attribute.dart'; +import '../container/container_spec.dart'; import '../container/container_widget.dart'; import 'stack_attribute.dart'; import 'stack_spec.dart'; @@ -18,24 +18,16 @@ class StyledStack extends StyledWidget { final List children; @override Widget build(BuildContext context) { - final contextMix = context.mix; - final inheritedAttribute = inherit && contextMix != null - ? StackMixAttribute.of(contextMix) - : const StackMixAttribute(); - return withMix(context, (mix) { - final attribute = StackMixAttribute.of(mix); - final merged = inheritedAttribute.merge(attribute); - - final mixture = merged.resolve(mix); + final spec = StackSpecAttribute.of(mix).resolve(mix); - return MixedStack(mixture, children: children); + return StackSpecWidget(spec, children: children); }); } } -class MixedStack extends StatelessWidget { - const MixedStack(this.mixture, {super.key, this.children}); +class StackSpecWidget extends StatelessWidget { + const StackSpecWidget(this.mixture, {super.key, this.children}); final List? children; final StackSpec mixture; @@ -65,12 +57,15 @@ class ZBox extends StyledWidget { @override Widget build(BuildContext context) { return withMix(context, (mix) { - final containerMix = ContainerSpecAttribute.of(mix).resolve(mix); - final stackMix = StackMixAttribute.of(mix).resolve(mix); + final containerSpec = + mix.attributeOf()?.resolve(mix) ?? + const ContainerSpec.empty(); + final stackSpec = mix.attributeOf()?.resolve(mix) ?? + const StackSpec.empty(); - return MixedContainer( - containerMix, - child: MixedStack(stackMix, children: children), + return ContainerSpecWidget( + containerSpec, + child: StackSpecWidget(stackSpec, children: children), ); }); } diff --git a/lib/src/recipes/text/text_spec.dart b/lib/src/recipes/text/text_spec.dart index 600fb05d3..eff8b404e 100644 --- a/lib/src/recipes/text/text_spec.dart +++ b/lib/src/recipes/text/text_spec.dart @@ -60,25 +60,6 @@ class TextSpec extends Spec { return directives.fold(text, (text, directive) => directive(text)); } - @override - TextSpec merge(TextSpec? other) { - if (other == null) return this; - - return copyWith( - softWrap: other.softWrap, - overflow: other.overflow, - strutStyle: other.strutStyle, - textAlign: other.textAlign, - textScaleFactor: other.textScaleFactor, - maxLines: other.maxLines, - style: other.style, - textWidthBasis: other.textWidthBasis, - textHeightBehavior: other.textHeightBehavior, - directives: other.directives, - textDirection: other.textDirection, - ); - } - @override TextSpec lerp(TextSpec other, double t) { // Define a helper method for snapping diff --git a/lib/src/recipes/text/text_widget.dart b/lib/src/recipes/text/text_widget.dart index 5f2d46df8..680fe3938 100644 --- a/lib/src/recipes/text/text_widget.dart +++ b/lib/src/recipes/text/text_widget.dart @@ -1,6 +1,5 @@ import 'package:flutter/material.dart'; -import '../../helpers/build_context_ext.dart'; import '../../widgets/styled_widget.dart'; import 'text_attribute.dart'; @@ -10,7 +9,7 @@ class StyledText extends StyledWidget { this.semanticsLabel, super.style, super.key, - super.inherit, + super.inherit = true, this.locale, }); @@ -20,31 +19,23 @@ class StyledText extends StyledWidget { @override Widget build(BuildContext context) { - final inheritedAttribute = inherit && context.mix != null - // ignore: avoid-non-null-assertion - ? TextMixAttribute.of(context.mix!) - : const TextMixAttribute(); - return withMix(context, (mix) { - final attribute = TextMixAttribute.of(mix); - final merged = inheritedAttribute.merge(attribute); - - final mixture = merged.resolve(mix); + final spec = TextMixAttribute.of(mix).resolve(mix); return Text( - mixture.applyTextDirectives(text), - style: mixture.style, - strutStyle: mixture.strutStyle, - textAlign: mixture.textAlign, - textDirection: mixture.textDirection ?? TextDirection.ltr, + spec.applyTextDirectives(text), + style: spec.style, + strutStyle: spec.strutStyle, + textAlign: spec.textAlign, + textDirection: spec.textDirection ?? TextDirection.ltr, locale: locale, - softWrap: mixture.softWrap, - overflow: mixture.overflow, - textScaleFactor: mixture.textScaleFactor, - maxLines: mixture.maxLines, + softWrap: spec.softWrap, + overflow: spec.overflow, + textScaleFactor: spec.textScaleFactor, + maxLines: spec.maxLines, semanticsLabel: semanticsLabel, - textWidthBasis: mixture.textWidthBasis, - textHeightBehavior: mixture.textHeightBehavior, + textWidthBasis: spec.textWidthBasis, + textHeightBehavior: spec.textHeightBehavior, ); }); } diff --git a/lib/src/theme/mix_theme.dart b/lib/src/theme/mix_theme.dart index 299d459a1..ac267f200 100644 --- a/lib/src/theme/mix_theme.dart +++ b/lib/src/theme/mix_theme.dart @@ -1,8 +1,11 @@ +// ignore_for_file: avoid-non-null-assertion + import 'package:flutter/material.dart'; import '../helpers/compare_mixin.dart'; -import 'tokens/breakpoints.dart'; +import 'tokens/breakpoints_token.dart'; import 'tokens/color_token.dart'; +import 'tokens/material_tokens.dart'; import 'tokens/mix_token.dart'; import 'tokens/radius_token.dart'; import 'tokens/space_token.dart'; @@ -12,8 +15,12 @@ class MixTheme extends InheritedWidget { const MixTheme({required super.child, required this.data, super.key}); static MixThemeData of(BuildContext context) { - return context.dependOnInheritedWidgetOfExactType()?.data ?? - MixThemeData(); + final themeData = + context.dependOnInheritedWidgetOfExactType()?.data; + + assert(themeData != null, 'No MixTheme found in context'); + + return themeData!; } static MixThemeData? maybeOf(BuildContext context) { @@ -31,142 +38,138 @@ class MixThemeData with Comparable { final StyledTokens radii; final StyledTokens colors; final StyledTokens textStyles; - final StyledTokens breakpoints; + final StyledTokens breakpoints; final StyledTokens space; const MixThemeData.raw({ - required this.breakpoints, - required this.colors, required this.textStyles, + required this.colors, + required this.breakpoints, required this.radii, required this.space, }); const MixThemeData.empty() : this.raw( - breakpoints: const StyledTokens.empty(), - colors: const StyledTokens.empty(), textStyles: const StyledTokens.empty(), + colors: const StyledTokens.empty(), + breakpoints: const StyledTokens.empty(), radii: const StyledTokens.empty(), space: const StyledTokens.empty(), ); factory MixThemeData({ - StyledTokens? breakpoints, - StyledTokens? colors, - StyledTokens? space, - StyledTokens? textStyles, - StyledTokens? radii, + Map? breakpoints, + Map? colors, + Map? space, + Map? textStyles, + Map? radii, }) { return MixThemeData.raw( - breakpoints: breakpoints ?? const StyledTokens.empty(), - colors: colors ?? const StyledTokens.empty(), - textStyles: textStyles ?? const StyledTokens.empty(), - radii: radii ?? const StyledTokens.empty(), - space: space ?? const StyledTokens.empty(), + textStyles: StyledTokens(textStyles ?? const {}), + colors: StyledTokens(colors ?? const {}), + breakpoints: + _breakpointTokenMap.merge(StyledTokens(breakpoints ?? const {})), + radii: _radiusTokenMap.merge(StyledTokens(radii ?? const {})), + space: _spaceTokenMap.merge(StyledTokens(space ?? const {})), ); } - factory MixThemeData.tokenMap({ - TokenMap? breakpoints, - TokenMap? colors, - TokenMap? space, - TokenMap? textStyles, - TokenMap? radii, + factory MixThemeData.withMaterialTokens({ + Map? breakpoints, + Map? colors, + Map? space, + Map? textStyles, + Map? radii, }) { - return MixThemeData.raw( - breakpoints: StyledTokens(breakpoints ?? const {}), - colors: StyledTokens(colors ?? const {}), - textStyles: StyledTokens(textStyles ?? const {}), - radii: StyledTokens(radii ?? const {}), - space: StyledTokens(space ?? const {}), + return materialMixTheme.merge( + MixThemeData( + breakpoints: breakpoints, + colors: colors, + space: space, + textStyles: textStyles, + radii: radii, + ), ); } MixThemeData copyWith({ - StyledTokens? breakpoints, - StyledTokens? colors, - StyledTokens? space, - StyledTokens? textStyles, - StyledTokens? radii, + Map? breakpoints, + Map? colors, + Map? space, + Map? textStyles, + Map? radii, }) { return MixThemeData.raw( - breakpoints: breakpoints ?? this.breakpoints, - colors: colors ?? this.colors, - textStyles: textStyles ?? this.textStyles, - radii: radii ?? this.radii, - space: space ?? this.space, + textStyles: + textStyles == null ? this.textStyles : StyledTokens(textStyles), + colors: colors == null ? this.colors : StyledTokens(colors), + breakpoints: + breakpoints == null ? this.breakpoints : StyledTokens(breakpoints), + radii: radii == null ? this.radii : StyledTokens(radii), + space: space == null ? this.space : StyledTokens(space), ); } - Color colorToken(BuildContext context, ColorToken token) { - return colors(token, context); - } - - Color colorRef(BuildContext context, ColorRef ref) => ref.resolve(context); - - Radius radiiToken(BuildContext context, RadiusToken token) { - return radii(token, context); - } - - Radius radiiRef(BuildContext context, RadiusRef ref) => ref.resolve(context); - - TextStyle textStyleToken(BuildContext context, TextStyleToken token) { - return textStyles(token, context); - } - - TextStyle textStyleRef(BuildContext context, TextStyleRef ref) => - ref.resolve(context); - - double spaceTokenRef(BuildContext context, SpaceRef value) { - if (value >= 0) return value; - final token = space.findByValue(value); - - return token == null ? 0.0 : spaceToken(context, token); - } - - double spaceToken(BuildContext context, SpaceToken token) { - final value = space(token, context); - - return value >= 0 ? value : token.value; + MixThemeData merge(MixThemeData other) { + return MixThemeData.raw( + textStyles: textStyles.merge(other.textStyles), + colors: colors.merge(other.colors), + breakpoints: breakpoints.merge(other.breakpoints), + radii: radii.merge(other.radii), + space: space.merge(other.space), + ); } @override get props => [space, breakpoints, colors, textStyles, radii]; } +final _spaceTokenMap = StyledTokens({ + SpaceToken.xsmall: 4.0, + SpaceToken.small: 8.0, + SpaceToken.medium: 16.0, + SpaceToken.large: 24.0, + SpaceToken.xlarge: 32.0, + SpaceToken.xxlarge: 40.0, +}); + +final _radiusTokenMap = StyledTokens({ + RadiusToken.small: const Radius.circular(4), + RadiusToken.medium: const Radius.circular(8), + RadiusToken.large: const Radius.circular(16), +}); + +final _breakpointTokenMap = StyledTokens({ + BreakpointToken.xsmall: const Breakpoint(maxWidth: 599), + BreakpointToken.small: const Breakpoint(minWidth: 600, maxWidth: 1023), + BreakpointToken.medium: const Breakpoint(minWidth: 1024, maxWidth: 1439), + BreakpointToken.large: + const Breakpoint(minWidth: 1440, maxWidth: double.infinity), +}); + class MixTokenResolver { final BuildContext _context; - final MixThemeData _theme; - const MixTokenResolver(this._context, this._theme); + const MixTokenResolver(this._context); - Color colorToken(ColorToken token) { - return _theme.colors(token, _context); - } + Color colorToken(ColorToken token) => token.resolve(_context); - Color colorRef(ColorRef ref) => ref.resolve(_context); + Color colorRef(ColorRef ref) => colorToken(ref.token); - Radius radiiToken(RadiusToken token) { - return _theme.radii(token, _context); - } + Radius radiiToken(RadiusToken token) => token.resolve(_context); - Radius radiiRef(RadiusRef ref) => ref.resolve(_context); + Radius radiiRef(RadiusRef ref) => radiiToken(ref.token); - TextStyle textStyleToken(TextStyleToken token) { - return _theme.textStyles(token, _context); - } + TextStyle textStyleToken(TextStyleToken token) => token.resolve(_context); - TextStyle textStyleRef(TextStyleRef ref) => ref.resolve(_context); + TextStyle textStyleRef(TextStyleRef ref) => textStyleToken(ref.token); - double spaceTokenRef(SpaceRef value) { - if (value >= 0) return value; - final token = _theme.space.findByValue(value); + double spaceToken(SpaceToken token) => token.resolve(_context); - return token == null ? 0.0 : spaceToken(_context, token); + double spaceTokenRef(SpaceRef spaceRef) { + return spaceRef < 0 ? spaceRef.resolve(_context) : spaceRef; } - double spaceToken(BuildContext context, SpaceToken token) { - return _theme.space(token, context); - } + Breakpoint breakpointToken(BreakpointToken token) => token.resolve(_context); } diff --git a/lib/src/theme/tokens/breakpoints.dart b/lib/src/theme/tokens/breakpoints.dart deleted file mode 100644 index 9b5b420ce..000000000 --- a/lib/src/theme/tokens/breakpoints.dart +++ /dev/null @@ -1,47 +0,0 @@ -import 'package:flutter/material.dart'; - -import 'mix_token.dart'; - -enum BreakpointOrientation { - portrait, - landscape, - all, -} - -class BreakpointConstraint { - final double minWidth; - final double maxWidth; - - const BreakpointConstraint({ - this.minWidth = 0, - this.maxWidth = double.infinity, - }); - - bool matches(Size size) { - return size.width >= minWidth && size.width <= maxWidth; - } -} - -class BreakpointToken extends MixToken { - static const xsmall = BreakpointToken( - 'mix.breakpoint.xsmall', - BreakpointConstraint(maxWidth: 599), - ); - static const small = BreakpointToken( - 'mix.breakpoint.small', - BreakpointConstraint(minWidth: 600, maxWidth: 1023), - ); - static const medium = BreakpointToken( - 'mix.breakpoint.medium', - BreakpointConstraint(minWidth: 1024, maxWidth: 1439), - ); - static const large = BreakpointToken( - 'mix.breakpoint.large', - BreakpointConstraint(minWidth: 1440, maxWidth: double.infinity), - ); - - const BreakpointToken(super.name, super.value); - - @override - BreakpointConstraint call() => value; -} diff --git a/lib/src/theme/tokens/breakpoints_token.dart b/lib/src/theme/tokens/breakpoints_token.dart new file mode 100644 index 000000000..c1e606a92 --- /dev/null +++ b/lib/src/theme/tokens/breakpoints_token.dart @@ -0,0 +1,69 @@ +import 'package:flutter/material.dart'; + +import '../mix_theme.dart'; +import 'mix_token.dart'; + +@Deprecated('Dont use this anymore') +enum BreakpointOrientation { + portrait, + landscape, + all, +} + +class Breakpoint { + final double minWidth; + final double maxWidth; + + const Breakpoint({this.minWidth = 0, this.maxWidth = double.infinity}); + + bool matches(Size size) { + return size.width >= minWidth && size.width <= maxWidth; + } +} + +const _breakpointXsmall = BreakpointToken('mix.breakpoint.xsmall'); +const _breakpointSmall = BreakpointToken('mix.breakpoint.small'); +const _breakpointMedium = BreakpointToken('mix.breakpoint.medium'); +const _breakpointLarge = BreakpointToken('mix.breakpoint.large'); + +@immutable +class BreakpointToken extends MixToken { + static const xsmall = _breakpointXsmall; + static const small = _breakpointSmall; + static const medium = _breakpointMedium; + static const large = _breakpointLarge; + + const BreakpointToken(super.name); + + @override + Breakpoint call() => BreakpointRef(this); + + @override + Breakpoint resolve(BuildContext context) { + final themeValue = MixTheme.of(context).breakpoints[this]; + assert( + themeValue != null, + 'BreakpointToken $name is not defined in the theme', + ); + + return themeValue is BreakpointResolver + ? themeValue.resolve(context) + : themeValue ?? const Breakpoint(); + } +} + +@immutable +class BreakpointResolver extends Breakpoint with WithTokenResolver { + @override + final BuildContextResolver resolve; + + const BreakpointResolver(this.resolve); +} + +@immutable +class BreakpointRef extends Breakpoint + with TokenRef { + @override + final BreakpointToken token; + const BreakpointRef(this.token); +} diff --git a/lib/src/theme/tokens/color_token.dart b/lib/src/theme/tokens/color_token.dart index f69b55799..e8812303b 100644 --- a/lib/src/theme/tokens/color_token.dart +++ b/lib/src/theme/tokens/color_token.dart @@ -1,33 +1,49 @@ import 'package:flutter/material.dart'; +import '../mix_theme.dart'; import 'mix_token.dart'; +@immutable class ColorToken extends MixToken { - const ColorToken(super.name, super.value); + const ColorToken(super.name); - const ColorToken.name(String name) : this(name, Colors.transparent); + @override + ColorRef call() => ColorRef(this); - factory ColorToken.resolvable(String name, TokenResolver resolver) { - return ColorToken(name, ColorRef(name, resolver)); + @override + Color resolve(BuildContext context) { + final themeValue = MixTheme.of(context).colors[this]; + assert( + themeValue != null, + 'ColorToken $name is not defined in the theme', + ); + + return themeValue is ColorResolver + ? themeValue.resolve(context) + : themeValue ?? Colors.transparent; } } -class ColorRef extends Color with ValueRef { +class ColorResolver extends Color with WithTokenResolver { @override - final String tokenName; + final BuildContextResolver resolve; + + const ColorResolver(this.resolve) : super(0); +} +class ColorRef extends Color with TokenRef { @override - final TokenResolver resolve; + final ColorToken token; - const ColorRef(this.tokenName, this.resolve) : super(0); + const ColorRef(this.token) : super(0); @override operator ==(Object other) { if (identical(this, other)) return true; - return other is ColorRef && other.tokenName == tokenName; + return other is ColorRef && other.token == token; } @override - int get hashCode => tokenName.hashCode; + int get hashCode => token.hashCode; } diff --git a/lib/src/theme/tokens/material_tokens.dart b/lib/src/theme/tokens/material_tokens.dart index 69aae7ee3..f46f19282 100644 --- a/lib/src/theme/tokens/material_tokens.dart +++ b/lib/src/theme/tokens/material_tokens.dart @@ -2,203 +2,140 @@ import 'package:flutter/material.dart'; +import '../mix_theme.dart'; import 'color_token.dart'; import 'text_style_token.dart'; +const _cm = _MaterialColorTokens(); +const _ts = _MaterialTextStyles(); + +@immutable +class MaterialTokens { + final colors = _cm; + final textStyles = _ts; + const MaterialTokens(); +} + +final materialMixTheme = MixThemeData( + colors: { + _cm.primary: ColorResolver((c) => c.color.primary), + _cm.secondary: ColorResolver((c) => c.color.secondary), + _cm.tertiary: ColorResolver((c) => c.color.tertiary), + _cm.surface: ColorResolver((c) => c.color.surface), + _cm.background: ColorResolver((c) => c.color.background), + _cm.error: ColorResolver((c) => c.color.error), + _cm.onPrimary: ColorResolver((c) => c.color.onPrimary), + _cm.onSecondary: ColorResolver((c) => c.color.onSecondary), + _cm.onTertiary: ColorResolver((c) => c.color.onTertiary), + _cm.onSurface: ColorResolver((c) => c.color.onSurface), + _cm.onBackground: ColorResolver((context) => context.color.onBackground), + _cm.onError: ColorResolver((context) => context.color.onError), + }, + textStyles: { + _ts.displayLarge: TextStyleResolver((c) => c.text.displayLarge!), + _ts.displayMedium: TextStyleResolver((c) => c.text.displayMedium!), + _ts.displaySmall: TextStyleResolver((c) => c.text.displaySmall!), + _ts.headlineLarge: TextStyleResolver((c) => c.text.headlineLarge!), + _ts.headlineMedium: TextStyleResolver((c) => c.text.headlineMedium!), + _ts.headlineSmall: TextStyleResolver((c) => c.text.headlineSmall!), + _ts.titleLarge: TextStyleResolver((c) => c.text.titleLarge!), + _ts.titleMedium: TextStyleResolver((c) => c.text.titleMedium!), + _ts.titleSmall: TextStyleResolver((c) => c.text.titleSmall!), + _ts.bodyLarge: TextStyleResolver((c) => c.text.bodyLarge!), + _ts.bodyMedium: TextStyleResolver((c) => c.text.bodyMedium!), + _ts.bodySmall: TextStyleResolver((c) => c.text.bodySmall!), + _ts.labelLarge: TextStyleResolver((c) => c.text.labelLarge!), + _ts.labelMedium: TextStyleResolver((c) => c.text.labelMedium!), + _ts.labelSmall: TextStyleResolver((c) => c.text.labelSmall!), + _ts.headline1: TextStyleResolver((c) => c.text.headline1!), + _ts.headline2: TextStyleResolver((c) => c.text.headline2!), + _ts.headline3: TextStyleResolver((c) => c.text.headline3!), + _ts.headline4: TextStyleResolver((c) => c.text.headline4!), + _ts.headline5: TextStyleResolver((c) => c.text.headline5!), + _ts.headline6: TextStyleResolver((c) => c.text.headline6!), + _ts.subtitle1: TextStyleResolver((c) => c.text.subtitle1!), + _ts.subtitle2: TextStyleResolver((c) => c.text.subtitle2!), + _ts.bodyText1: TextStyleResolver((c) => c.text.bodyText1!), + _ts.bodyText2: TextStyleResolver((c) => c.text.bodyText2!), + _ts.caption: TextStyleResolver((c) => c.text.caption!), + _ts.button: TextStyleResolver((c) => c.text.button!), + _ts.overline: TextStyleResolver((c) => c.text.overline!), + }, +); + @immutable class _MaterialColorTokens { - final primary = ColorToken.resolvable( - 'md.color.primary', - (context) => context.color.primary, - ); + final primary = const ColorToken('md.color.primary'); - final secondary = ColorToken.resolvable( - 'md.color.secondary', - (context) => context.color.secondary, - ); + final secondary = const ColorToken('md.color.secondary'); - final tertiary = ColorToken.resolvable( - 'md.color.tertiary', - (context) => context.color.tertiary, - ); + final tertiary = const ColorToken('md.color.tertiary'); - final surface = ColorToken.resolvable( - 'md.color.surface', - (context) => context.color.surface, - ); + final surface = const ColorToken('md.color.surface'); - final background = ColorToken.resolvable( - 'md.color.background', - (context) => context.color.background, - ); + final background = const ColorToken('md.color.background'); - final error = ColorToken.resolvable( - 'md.color.error', - (context) => context.color.error, - ); + final error = const ColorToken('md.color.error'); - final onPrimary = ColorToken.resolvable( - 'md.color.on.primary', - (context) => context.color.onPrimary, - ); + final onPrimary = const ColorToken('md.color.on.primary'); - final onSecondary = ColorToken.resolvable( - 'md.color.on.secondary', - (context) => context.color.onSecondary, - ); + final onSecondary = const ColorToken('md.color.on.secondary'); - final onTertiary = ColorToken.resolvable( - 'md.color.on.tertiary', - (context) => context.color.onTertiary, - ); + final onTertiary = const ColorToken('md.color.on.tertiary'); - final onSurface = ColorToken.resolvable( - 'md.color.on.surface', - (context) => context.color.onSurface, - ); + final onSurface = const ColorToken('md.color.on.surface'); - final onBackground = ColorToken.resolvable( - 'md.color.on.background', - (context) => context.color.onBackground, - ); + final onBackground = const ColorToken('md.color.on.background'); - final onError = ColorToken.resolvable( - 'md.color.on.error', - (context) => context.color.onError, - ); + final onError = const ColorToken('md.color.on.error'); - _MaterialColorTokens(); + const _MaterialColorTokens(); } @immutable // Material 3 TextTheme Tokens. class _MaterialTextStyles { // Material 3 text styles - final displayLarge = TextStyleToken.resolvable( - 'md3.text.theme.display.large', - (context) => context.text.displayLarge!, - ); - final displayMedium = TextStyleToken.resolvable( + final displayLarge = const TextStyleToken('md3.text.theme.display.large'); + final displayMedium = const TextStyleToken( 'md3.text.theme.display.medium', - (context) => context.text.displayMedium!, ); - final displaySmall = TextStyleToken.resolvable( - 'md3.text.theme.display.small', - (context) => context.text.displaySmall!, - ); - final headlineLarge = TextStyleToken.resolvable( + final displaySmall = const TextStyleToken('md3.text.theme.display.small'); + final headlineLarge = const TextStyleToken( 'md3.text.theme.headline.large', - (context) => context.text.headlineLarge!, ); - final headlineMedium = TextStyleToken.resolvable( + final headlineMedium = const TextStyleToken( 'md3.text.theme.headline.medium', - (context) => context.text.headlineMedium!, ); - final headlineSmall = TextStyleToken.resolvable( + final headlineSmall = const TextStyleToken( 'md3.text.theme.headline.small', - (context) => context.text.headlineSmall!, - ); - final titleLarge = TextStyleToken.resolvable( - 'md3.text.theme.title.large', - (context) => context.text.titleLarge!, - ); - final titleMedium = TextStyleToken.resolvable( - 'md3.text.theme.title.medium', - (context) => context.text.titleMedium!, - ); - final titleSmall = TextStyleToken.resolvable( - 'md3.text.theme.title.small', - (context) => context.text.titleSmall!, - ); - final bodyLarge = TextStyleToken.resolvable( - 'md3.text.theme.body.large', - (context) => context.text.bodyLarge!, - ); - final bodyMedium = TextStyleToken.resolvable( - 'md3.text.theme.body.medium', - (context) => context.text.bodyMedium!, - ); - final bodySmall = TextStyleToken.resolvable( - 'md3.text.theme.body.small', - (context) => context.text.bodySmall!, - ); - final labelLarge = TextStyleToken.resolvable( - 'md3.text.theme.label.large', - (context) => context.text.labelLarge!, - ); - final labelMedium = TextStyleToken.resolvable( - 'md3.text.theme.label.medium', - (context) => context.text.labelMedium!, - ); - final labelSmall = TextStyleToken.resolvable( - 'md3.text.theme.label.small', - (context) => context.text.labelSmall!, - ); - // Material 2 text styles - final headline1 = TextStyleToken.resolvable( - 'md2.text.theme.headline1', - (context) => context.text.headline1!, - ); - final headline2 = TextStyleToken.resolvable( - 'md2.text.theme.headline2', - (context) => context.text.headline2!, - ); - final headline3 = TextStyleToken.resolvable( - 'md2.text.theme.headline3', - (context) => context.text.headline3!, - ); - final headline4 = TextStyleToken.resolvable( - 'md2.text.theme.headline4', - (context) => context.text.headline4!, - ); - final headline5 = TextStyleToken.resolvable( - 'md2.text.theme.headline5', - (context) => context.text.headline5!, - ); - final headline6 = TextStyleToken.resolvable( - 'md2.text.theme.headline6', - (context) => context.text.headline6!, - ); - final subtitle1 = TextStyleToken.resolvable( - 'md2.text.theme.subtitle1', - (context) => context.text.subtitle1!, - ); - final subtitle2 = TextStyleToken.resolvable( - 'md2.text.theme.subtitle2', - (context) => context.text.subtitle2!, - ); - final bodyText1 = TextStyleToken.resolvable( - 'md2.text.theme.bodyText1', - (context) => context.text.bodyText1!, - ); - final bodyText2 = TextStyleToken.resolvable( - 'md2.text.theme.bodyText2', - (context) => context.text.bodyText2!, - ); - final caption = TextStyleToken.resolvable( - 'md2.text.theme.caption', - (context) => context.text.caption!, - ); - final button = TextStyleToken.resolvable( - 'md2.text.theme.button', - (context) => context.text.button!, - ); - final overline = TextStyleToken.resolvable( - 'md2.text.theme.overline', - (context) => context.text.overline!, ); - _MaterialTextStyles(); -} - -final _colors = _MaterialColorTokens(); -final _textStyles = _MaterialTextStyles(); - -@immutable -class MaterialTokens { - final colors = _colors; - final textStyles = _textStyles; - MaterialTokens(); + final titleLarge = const TextStyleToken('md3.text.theme.title.large'); + final titleMedium = const TextStyleToken('md3.text.theme.title.medium'); + final titleSmall = const TextStyleToken('md3.text.theme.title.small'); + final bodyLarge = const TextStyleToken('md3.text.theme.body.large'); + final bodyMedium = const TextStyleToken('md3.text.theme.body.medium'); + final bodySmall = const TextStyleToken('md3.text.theme.body.small'); + final labelLarge = const TextStyleToken('md3.text.theme.label.large'); + final labelMedium = const TextStyleToken('md3.text.theme.label.medium'); + final labelSmall = const TextStyleToken('md3.text.theme.label.small'); + // Material 2 text styles + final headline1 = const TextStyleToken('md2.text.theme.headline1'); + final headline2 = const TextStyleToken('md2.text.theme.headline2'); + final headline3 = const TextStyleToken('md2.text.theme.headline3'); + final headline4 = const TextStyleToken('md2.text.theme.headline4'); + final headline5 = const TextStyleToken('md2.text.theme.headline5'); + final headline6 = const TextStyleToken('md2.text.theme.headline6'); + final subtitle1 = const TextStyleToken('md2.text.theme.subtitle1'); + final subtitle2 = const TextStyleToken('md2.text.theme.subtitle2'); + final bodyText1 = const TextStyleToken('md2.text.theme.bodyText1'); + final bodyText2 = const TextStyleToken('md2.text.theme.bodyText2'); + final caption = const TextStyleToken('md2.text.theme.caption'); + final button = const TextStyleToken('md2.text.theme.button'); + final overline = const TextStyleToken('md2.text.theme.overline'); + + const _MaterialTextStyles(); } extension on BuildContext { @@ -207,47 +144,47 @@ extension on BuildContext { } mixin MaterialColorTokensMixin { - Color get primary => _colors.primary(); - Color get secondary => _colors.secondary(); - Color get tertiary => _colors.tertiary(); - Color get surface => _colors.surface(); - Color get background => _colors.background(); - Color get error => _colors.error(); - Color get onPrimary => _colors.onPrimary(); - Color get onSecondary => _colors.onSecondary(); - Color get onTertiary => _colors.onTertiary(); - Color get onSurface => _colors.onSurface(); - Color get onBackground => _colors.onBackground(); - Color get onError => _colors.onError(); + ColorToken get primary => _cm.primary; + ColorToken get secondary => _cm.secondary; + ColorToken get tertiary => _cm.tertiary; + ColorToken get surface => _cm.surface; + ColorToken get background => _cm.background; + ColorToken get error => _cm.error; + ColorToken get onPrimary => _cm.onPrimary; + ColorToken get onSecondary => _cm.onSecondary; + ColorToken get onTertiary => _cm.onTertiary; + ColorToken get onSurface => _cm.onSurface; + ColorToken get onBackground => _cm.onBackground; + ColorToken get onError => _cm.onError; } mixin MaterialTextStyleTokensMixin { - TextStyle get displayLarge => _textStyles.displayLarge(); - TextStyle get displayMedium => _textStyles.displayMedium(); - TextStyle get displaySmall => _textStyles.displaySmall(); - TextStyle get headlineLarge => _textStyles.headlineLarge(); - TextStyle get headlineMedium => _textStyles.headlineMedium(); - TextStyle get headlineSmall => _textStyles.headlineSmall(); - TextStyle get titleLarge => _textStyles.titleLarge(); - TextStyle get titleMedium => _textStyles.titleMedium(); - TextStyle get titleSmall => _textStyles.titleSmall(); - TextStyle get bodyLarge => _textStyles.bodyLarge(); - TextStyle get bodyMedium => _textStyles.bodyMedium(); - TextStyle get bodySmall => _textStyles.bodySmall(); - TextStyle get labelLarge => _textStyles.labelLarge(); - TextStyle get labelMedium => _textStyles.labelMedium(); - TextStyle get labelSmall => _textStyles.labelSmall(); - TextStyle get headline1 => _textStyles.headline1(); - TextStyle get headline2 => _textStyles.headline2(); - TextStyle get headline3 => _textStyles.headline3(); - TextStyle get headline4 => _textStyles.headline4(); - TextStyle get headline5 => _textStyles.headline5(); - TextStyle get headline6 => _textStyles.headline6(); - TextStyle get subtitle1 => _textStyles.subtitle1(); - TextStyle get subtitle2 => _textStyles.subtitle2(); - TextStyle get bodyText1 => _textStyles.bodyText1(); - TextStyle get bodyText2 => _textStyles.bodyText2(); - TextStyle get caption => _textStyles.caption(); - TextStyle get button => _textStyles.button(); - TextStyle get overline => _textStyles.overline(); + TextStyleToken get displayLarge => _ts.displayLarge; + TextStyleToken get displayMedium => _ts.displayMedium; + TextStyleToken get displaySmall => _ts.displaySmall; + TextStyleToken get headlineLarge => _ts.headlineLarge; + TextStyleToken get headlineMedium => _ts.headlineMedium; + TextStyleToken get headlineSmall => _ts.headlineSmall; + TextStyleToken get titleLarge => _ts.titleLarge; + TextStyleToken get titleMedium => _ts.titleMedium; + TextStyleToken get titleSmall => _ts.titleSmall; + TextStyleToken get bodyLarge => _ts.bodyLarge; + TextStyleToken get bodyMedium => _ts.bodyMedium; + TextStyleToken get bodySmall => _ts.bodySmall; + TextStyleToken get labelLarge => _ts.labelLarge; + TextStyleToken get labelMedium => _ts.labelMedium; + TextStyleToken get labelSmall => _ts.labelSmall; + TextStyleToken get headline1 => _ts.headline1; + TextStyleToken get headline2 => _ts.headline2; + TextStyleToken get headline3 => _ts.headline3; + TextStyleToken get headline4 => _ts.headline4; + TextStyleToken get headline5 => _ts.headline5; + TextStyleToken get headline6 => _ts.headline6; + TextStyleToken get subtitle1 => _ts.subtitle1; + TextStyleToken get subtitle2 => _ts.subtitle2; + TextStyleToken get bodyText1 => _ts.bodyText1; + TextStyleToken get bodyText2 => _ts.bodyText2; + TextStyleToken get caption => _ts.caption; + TextStyleToken get button => _ts.button; + TextStyleToken get overline => _ts.overline; } diff --git a/lib/src/theme/tokens/mix_token.dart b/lib/src/theme/tokens/mix_token.dart index d8c8c485f..04df630b8 100644 --- a/lib/src/theme/tokens/mix_token.dart +++ b/lib/src/theme/tokens/mix_token.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:flutter/widgets.dart'; +import '../../core/attribute.dart'; import '../../core/extensions/iterable_ext.dart'; import '../../helpers/compare_mixin.dart'; import 'color_token.dart'; @@ -10,23 +11,17 @@ import 'text_style_token.dart'; @immutable abstract class MixToken { final String name; - final T value; + const MixToken(this.name); - const MixToken(this.name, this.value); + static ColorToken color(String name) => ColorToken(name); - static ColorToken color(String name, Color value) { - return ColorToken(name, value); - } + static TextStyleToken textStyle(String name) => TextStyleToken(name); - static TextStyleToken textStyle(String name, TextStyle value) { - return TextStyleToken(name, value); - } + static RadiusToken radius(String name) => RadiusToken(name); - static RadiusToken radius(String name, Radius value) { - return RadiusToken(name, value); - } + T call(); - T call() => value; + T resolve(BuildContext context); @override operator ==(Object other) { @@ -34,40 +29,52 @@ abstract class MixToken { if (runtimeType != other.runtimeType) return false; - return other is MixToken && other.name == name && other.value == value; + return other is MixToken && other.name == name; } @override - int get hashCode => Object.hash(name, value, runtimeType); + int get hashCode => Object.hash(name, runtimeType); } -mixin ValueRef { - String get tokenName; - TokenResolver get resolve; +mixin TokenRef, V> { + T get token; } -typedef TokenResolver = T Function(BuildContext context); +mixin DtoRef, V> { + T get data; +} -typedef TokenMap, V> = Map>; +mixin WithTokenResolver { + BuildContextResolver get resolve; +} + +typedef BuildContextResolver = T Function(BuildContext context); class StyledTokens, V> with Comparable { - final Map> _map; + final Map _map; const StyledTokens(this._map); // empty const StyledTokens.empty() : this(const {}); - V call(T token, BuildContext context) { - final value = _map[token]?.call(context) ?? token.value; - - return value is ValueRef ? value.resolve(context) : value; - } + V? operator [](T token) => _map[token]; // Looks for the token the value set within the MixToken // TODO: Needs to be optimized, but this is a temporary solution - T? findByValue(V value) { - return _map.keys.firstWhereOrNull((token) => token.value == value); + T? findByRef(V value) { + return _map.keys.firstWhereOrNull((token) => token() == value); + } + + StyledTokens merge(StyledTokens other) { + // TODO: This is a temporary solution, but it works for now + // ovrite the keys on this _map with the keys from the other _map + + final newMap = Map.from(_map); + + newMap.addAll(other._map); + + return StyledTokens(newMap); } @override diff --git a/lib/src/theme/tokens/radius_token.dart b/lib/src/theme/tokens/radius_token.dart index 96ba2dd24..951d50d3f 100644 --- a/lib/src/theme/tokens/radius_token.dart +++ b/lib/src/theme/tokens/radius_token.dart @@ -1,45 +1,62 @@ import 'package:flutter/material.dart'; import 'package:flutter/widgets.dart'; +import '../mix_theme.dart'; import 'mix_token.dart'; -const _small = RadiusToken('mix.radii.small', Radius.circular(4)); -const _medium = RadiusToken('mix.radii.medium', Radius.circular(8)); -const _large = RadiusToken('mix.radii.large', Radius.circular(16)); +const _small = RadiusToken('mix.radii.small'); +const _medium = RadiusToken('mix.radii.medium'); +const _large = RadiusToken('mix.radii.large'); class RadiusToken extends MixToken { static const small = _small; static const medium = _medium; static const large = _large; - const RadiusToken(super.name, super.value); + const RadiusToken(super.name); - const RadiusToken.name(String name) : this(name, Radius.zero); + @override + RadiusRef call() => RadiusRef(this); + + @override + Radius resolve(BuildContext context) { + final themeValue = MixTheme.of(context).radii[this]; + assert( + themeValue != null, + 'RadiusToken $name is not defined in the theme and has no default value', + ); + + final resolvedValue = + themeValue is RadiusResolver ? themeValue.resolve(context) : themeValue; - factory RadiusToken.resolvable(String name, TokenResolver resolver) { - return RadiusToken(name, RadiusRef(name, resolver)); + return resolvedValue ?? const Radius.circular(0); } } @immutable -class RadiusRef extends Radius with ValueRef { +class RadiusResolver extends Radius with WithTokenResolver { @override - final String tokenName; + final BuildContextResolver resolve; + const RadiusResolver(this.resolve) : super.circular(0); +} + +@immutable +class RadiusRef extends Radius with TokenRef { @override - final TokenResolver resolve; + final RadiusToken token; - const RadiusRef(this.tokenName, this.resolve) : super.circular(0); + const RadiusRef(this.token) : super.circular(0); @override operator ==(Object other) { if (identical(this, other)) return true; - return other is RadiusRef && other.tokenName == tokenName; + return other is RadiusRef && other.token == token; } @override - int get hashCode => tokenName.hashCode; + int get hashCode => token.hashCode; } // // Helper class to wrap functions that can return diff --git a/lib/src/theme/tokens/space_token.dart b/lib/src/theme/tokens/space_token.dart index c806a06b4..e790ad8be 100644 --- a/lib/src/theme/tokens/space_token.dart +++ b/lib/src/theme/tokens/space_token.dart @@ -1,15 +1,31 @@ +// ignore_for_file: avoid-non-null-assertion + import 'package:flutter/material.dart'; +import '../mix_theme.dart'; import 'mix_token.dart'; typedef SpaceRef = double; -const _xsmall = SpaceToken('mix.space.xsmall', 4.0); -const _small = SpaceToken('mix.space.small', 8.0); -const _medium = SpaceToken('mix.space.medium', 16.0); -const _large = SpaceToken('mix.space.large', 24.0); -const _xlarge = SpaceToken('mix.space.xlarge', 32.0); -const _xxlarge = SpaceToken('mix.space.xxlarge', 40.0); +extension SpaceRefExt on SpaceRef { + double resolve(BuildContext context) { + final token = MixTheme.of(context).space.findByRef(this); + + assert( + token != null, + 'SpaceRef $this is not defined in the theme', + ); + + return token?.resolve(context) ?? 0.0; + } +} + +const _xsmall = SpaceToken('mix.space.xsmall'); +const _small = SpaceToken('mix.space.small'); +const _medium = SpaceToken('mix.space.medium'); +const _large = SpaceToken('mix.space.large'); +const _xlarge = SpaceToken('mix.space.xlarge'); +const _xxlarge = SpaceToken('mix.space.xxlarge'); /// A class representing a space token, which extends `MixToken` class /// and uses the `SizeTokenMixin` mixin. @@ -29,8 +45,19 @@ class SpaceToken extends MixToken { /// Name needs to be unique per token /// /// [name] is used to initialize the superclass `MixToken`. - const SpaceToken(super.name, super.value); + const SpaceToken(super.name); @override double call() => hashCode * -1.0; + + @override + double resolve(BuildContext context) { + final themeValue = MixTheme.of(context).space[this]; + assert( + themeValue != null, + 'SpaceToken $name is not defined in the theme', + ); + + return themeValue!; + } } diff --git a/lib/src/theme/tokens/text_style_token.dart b/lib/src/theme/tokens/text_style_token.dart index 3a86ddcd7..f05f839f0 100644 --- a/lib/src/theme/tokens/text_style_token.dart +++ b/lib/src/theme/tokens/text_style_token.dart @@ -3,109 +3,157 @@ import 'dart:ui'; import 'package:flutter/material.dart'; import 'package:flutter/widgets.dart'; +import '../mix_theme.dart'; import 'mix_token.dart'; class TextStyleToken extends MixToken { - const TextStyleToken(super.name, super.value); + const TextStyleToken(super.name); - const TextStyleToken.name(String name) : this(name, const TextStyle()); + @override + TextStyleRef call() => TextStyleRef(this); + + @override + TextStyle resolve(BuildContext context) { + final themeValue = MixTheme.of(context).textStyles[this]; + assert( + themeValue != null, + 'TextStyleToken $name is not defined in the theme', + ); - factory TextStyleToken.resolvable( - String name, - TokenResolver resolver, - ) { - return TextStyleToken(name, TextStyleRef(name, resolver)); + final resolvedValue = themeValue is TextStyleResolver + ? themeValue.resolve(context) + : themeValue; + + return resolvedValue ?? const TextStyle(); } } @immutable -class TextStyleRef extends TextStyle with ValueRef { +class TextStyleResolver extends TextStyle with WithTokenResolver { @override - final String tokenName; + final BuildContextResolver resolve; + const TextStyleResolver(this.resolve); +} + +@immutable +class TextStyleRef extends TextStyle with TokenRef { @override - final TokenResolver resolve; + final TextStyleToken token; - const TextStyleRef(this.tokenName, this.resolve); + const TextStyleRef(this.token); @override operator ==(Object other) { if (identical(this, other)) return true; - return other is TextStyleRef && other.tokenName == tokenName; + return other is TextStyleRef && other.token == token; } @override - bool get inherit => throw _e(tokenName, 'inherit'); + TextStyle copyWith({ + bool? inherit, + Color? color, + Color? backgroundColor, + double? fontSize, + FontWeight? fontWeight, + FontStyle? fontStyle, + double? letterSpacing, + double? wordSpacing, + TextBaseline? textBaseline, + double? height, + TextLeadingDistribution? leadingDistribution, + Locale? locale, + Paint? foreground, + Paint? background, + List? shadows, + List? fontFeatures, + List? fontVariations, + TextDecoration? decoration, + Color? decorationColor, + TextDecorationStyle? decorationStyle, + double? decorationThickness, + String? debugLabel, + String? fontFamily, + List? fontFamilyFallback, + String? package, + TextOverflow? overflow, + }) => + throw _e(token.name, 'copyWith'); + @override + String get fontFamily => throw _e(token.name, 'fontFamily'); + + @override + bool get inherit => throw _e(token.name, 'inherit'); @override - Color get color => throw _e(tokenName, 'color'); + Color get color => throw _e(token.name, 'color'); @override - Color get backgroundColor => throw _e(tokenName, 'backgroundColor'); + Color get backgroundColor => throw _e(token.name, 'backgroundColor'); @override - double get fontSize => throw _e(tokenName, 'fontSize'); + double get fontSize => throw _e(token.name, 'fontSize'); @override - FontWeight get fontWeight => throw _e(tokenName, 'fontWeight'); + FontWeight get fontWeight => throw _e(token.name, 'fontWeight'); @override - FontStyle get fontStyle => throw _e(tokenName, 'fontStyle'); + FontStyle get fontStyle => throw _e(token.name, 'fontStyle'); @override - double get letterSpacing => throw _e(tokenName, 'letterSpacing'); + double get letterSpacing => throw _e(token.name, 'letterSpacing'); @override - double get wordSpacing => throw _e(tokenName, 'wordSpacing'); + double get wordSpacing => throw _e(token.name, 'wordSpacing'); @override - TextBaseline get textBaseline => throw _e(tokenName, 'textBaseline'); + TextBaseline get textBaseline => throw _e(token.name, 'textBaseline'); @override - double get height => throw _e(tokenName, 'height'); + double get height => throw _e(token.name, 'height'); @override TextLeadingDistribution get leadingDistribution => - throw _e(tokenName, 'leadingDistribution'); + throw _e(token.name, 'leadingDistribution'); @override - Locale get locale => throw _e(tokenName, 'locale'); + Locale get locale => throw _e(token.name, 'locale'); @override - Paint get foreground => throw _e(tokenName, 'foreground'); + Paint get foreground => throw _e(token.name, 'foreground'); @override - Paint get background => throw _e(tokenName, 'background'); + Paint get background => throw _e(token.name, 'background'); @override - List get shadows => throw _e(tokenName, 'shadows'); + List get shadows => throw _e(token.name, 'shadows'); @override - List get fontFeatures => throw _e(tokenName, 'fontFeatures'); + List get fontFeatures => throw _e(token.name, 'fontFeatures'); @override List get fontVariations => - throw _e(tokenName, 'fontVariations'); + throw _e(token.name, 'fontVariations'); @override - TextDecoration get decoration => throw _e(tokenName, 'decoration'); + TextDecoration get decoration => throw _e(token.name, 'decoration'); @override - Color get decorationColor => throw _e(tokenName, 'decorationColor'); + Color get decorationColor => throw _e(token.name, 'decorationColor'); @override TextDecorationStyle get decorationStyle => - throw _e(tokenName, 'decorationStyle'); + throw _e(token.name, 'decorationStyle'); @override - double get decorationThickness => throw _e(tokenName, 'decorationThickness'); + double get decorationThickness => throw _e(token.name, 'decorationThickness'); @override - String get debugLabel => throw _e(tokenName, 'debugLabel'); + String get debugLabel => throw _e(token.name, 'debugLabel'); @override - int get hashCode => tokenName.hashCode; + int get hashCode => token.name.hashCode; } TokenFieldAccessError _e(String token, String field) { diff --git a/lib/src/utils/context_variant_util/on_breakpoint_util.dart b/lib/src/utils/context_variant_util/on_breakpoint_util.dart index a6e3cc2ed..96cfb4f5d 100644 --- a/lib/src/utils/context_variant_util/on_breakpoint_util.dart +++ b/lib/src/utils/context_variant_util/on_breakpoint_util.dart @@ -2,7 +2,7 @@ import 'package:flutter/material.dart'; import '../../helpers/string_ext.dart'; import '../../theme/mix_theme.dart'; -import '../../theme/tokens/breakpoints.dart'; +import '../../theme/tokens/breakpoints_token.dart'; import '../../variants/context_variant.dart'; /// Global breakpoint context variants based on predefined screen sizes. @@ -26,10 +26,7 @@ final onLarge = onBreakpointToken(BreakpointToken.large); /// the orientation constraint. This function returns a [ContextVariant] which will apply /// when the screen size matches these constraints. ContextVariant onBreakpoint({minWidth = 0, maxWidth = double.infinity}) { - final constraints = BreakpointConstraint( - minWidth: minWidth, - maxWidth: maxWidth, - ); + final constraints = Breakpoint(minWidth: minWidth, maxWidth: maxWidth); final constraintName = 'minWidth-${constraints.minWidth}-maxWidth-${constraints.maxWidth}'; @@ -52,11 +49,9 @@ ContextVariant onBreakpointToken(BreakpointToken token) { return ContextVariant( 'on-${token.name.paramCase}', when: (BuildContext context) { - final breakpoints = MixTheme.of(context).breakpoints; - final size = MediaQuery.sizeOf(context); - final selectedbreakpoint = breakpoints(token, context); + final selectedbreakpoint = token.resolve(context); return selectedbreakpoint.matches(size); }, diff --git a/lib/src/utils/pressable_util.dart b/lib/src/utils/pressable_util.dart deleted file mode 100644 index 3d0732841..000000000 --- a/lib/src/utils/pressable_util.dart +++ /dev/null @@ -1,34 +0,0 @@ -import 'package:flutter/material.dart'; - -import '../helpers/string_ext.dart'; -import '../variants/context_variant.dart'; -import '../widgets/pressable/pressable.notifier.dart'; -import '../widgets/pressable/pressable_state.dart'; -import 'context_variant_util/on_helper_util.dart'; - -final onPress = _onState(PressableState.pressed); -final onLongPress = _onState(PressableState.longPressed); -final onHover = _onState(PressableState.hover); -final onDisabled = _onState(PressableState.disabled); - -final onEnabled = onNot(onDisabled); - -final onFocus = ContextVariant( - 'on-focus', - when: (BuildContext context) { - final pressable = PressableNotifier.of(context); - - return pressable?.focus == true; - }, -); - -ContextVariant _onState(PressableState state) { - return ContextVariant( - 'on-${state.name.paramCase}', - when: (BuildContext context) { - final pressable = PressableNotifier.of(context); - - return pressable?.state == state; - }, - ); -} diff --git a/lib/src/variants/context_variant.dart b/lib/src/variants/context_variant.dart index 7dfb617fb..4a7a86e4f 100644 --- a/lib/src/variants/context_variant.dart +++ b/lib/src/variants/context_variant.dart @@ -84,3 +84,8 @@ class ContextVariant extends Variant { @override get props => [name, when]; } + +@immutable +class GestureVariant extends ContextVariant { + const GestureVariant(super.name, {required super.when}); +} diff --git a/lib/src/variants/multi_variant.dart b/lib/src/variants/multi_variant.dart index 89fb75e21..4eafbc860 100644 --- a/lib/src/variants/multi_variant.dart +++ b/lib/src/variants/multi_variant.dart @@ -81,6 +81,10 @@ class MultiVariant extends Variant { return MultiVariant(variants, type: MultiVariantOperator.or); } + bool get hasGestureVariant { + return variants.any((variant) => variant is GestureVariant); + } + /// Removes specified variants from this `MultiVariant`. /// /// This method returns a new variant after removing the specified [variantsToRemove]. diff --git a/lib/src/widgets/pressable/gesture_state.dart b/lib/src/widgets/pressable/gesture_state.dart new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/lib/src/widgets/pressable/gesture_state.dart @@ -0,0 +1 @@ + diff --git a/lib/src/widgets/pressable/gesture_state.notifier.dart b/lib/src/widgets/pressable/gesture_state.notifier.dart new file mode 100644 index 000000000..63c90ebe8 --- /dev/null +++ b/lib/src/widgets/pressable/gesture_state.notifier.dart @@ -0,0 +1,73 @@ +import 'package:flutter/widgets.dart'; + +import '../../helpers/compare_mixin.dart'; + +@immutable +class GestureData with Comparable { + final bool focus; + final bool hover; + final GestureStatus status; + final GestureState state; + + const GestureData({ + required this.focus, + required this.status, + required this.state, + required this.hover, + }); + + const GestureData.none() + : focus = false, + hover = false, + status = GestureStatus.disabled, + state = GestureState.none; + + GestureData copyWith({ + bool? focus, + bool? hover, + GestureStatus? status, + GestureState? state, + }) { + return GestureData( + focus: focus ?? this.focus, + status: status ?? this.status, + state: state ?? this.state, + hover: hover ?? this.hover, + ); + } + + @override + get props => [focus, status, state, hover]; +} + +enum GestureStatus { + enabled, + disabled, +} + +enum GestureState { + none, + pressed, + longPressed, +} + +class GestureStateNotifier extends InheritedWidget { + const GestureStateNotifier({ + super.key, + required super.child, + required this.data, + }); + + static GestureData? of(BuildContext context) { + return context + .dependOnInheritedWidgetOfExactType() + ?.data; + } + + final GestureData data; + + @override + bool updateShouldNotify(GestureStateNotifier oldWidget) { + return oldWidget.data != data; + } +} diff --git a/lib/src/widgets/pressable/gesture_util.dart b/lib/src/widgets/pressable/gesture_util.dart new file mode 100644 index 000000000..ad6add268 --- /dev/null +++ b/lib/src/widgets/pressable/gesture_util.dart @@ -0,0 +1,33 @@ +import '../../helpers/string_ext.dart'; +import '../../variants/context_variant.dart'; +import 'gesture_state.notifier.dart'; + +final onPress = _onState(GestureState.pressed); +final onLongPress = _onState(GestureState.longPressed); +// final onHover = _onState(GestureState.hover); +final onDisabled = _onStatus(GestureStatus.disabled); +final onEnabled = _onStatus(GestureStatus.enabled); + +final onFocus = ContextVariant( + 'on-focus', + when: (context) => GestureStateNotifier.of(context)?.focus == true, +); + +final onHover = ContextVariant( + 'on-hover', + when: (context) => GestureStateNotifier.of(context)?.hover == true, +); + +GestureVariant _onState(GestureState state) { + return GestureVariant( + 'on-${state.name.paramCase}', + when: (context) => GestureStateNotifier.of(context)?.state == state, + ); +} + +GestureVariant _onStatus(GestureStatus status) { + return GestureVariant( + 'on-${status.name.paramCase}', + when: (context) => GestureStateNotifier.of(context)?.status == status, + ); +} diff --git a/lib/src/widgets/pressable/gesture_widget.dart b/lib/src/widgets/pressable/gesture_widget.dart new file mode 100644 index 000000000..894a060fe --- /dev/null +++ b/lib/src/widgets/pressable/gesture_widget.dart @@ -0,0 +1,182 @@ +import 'package:flutter/material.dart'; + +import '../../factory/style_mix.dart'; +import '../../recipes/container/container_widget.dart'; +import 'gesture_state.notifier.dart'; + +class GestureBox extends StatelessWidget { + const GestureBox({ + super.key, + this.onPressed, + this.onLongPress, + this.focusNode, + this.autofocus = false, + this.unpressDelay = const Duration(milliseconds: 250), + this.onFocusChange, + this.behavior, + required this.child, + this.style, + }); + + final StyleMix? style; + final Widget child; + final VoidCallback? onPressed; + final VoidCallback? onLongPress; + final FocusNode? focusNode; + final bool autofocus; + final Duration unpressDelay; + final Function(bool focus)? onFocusChange; + + final HitTestBehavior? behavior; + + @override + Widget build(BuildContext context) { + return Pressable( + behavior: behavior, + focusNode: focusNode, + autofocus: autofocus, + onFocusChange: onFocusChange, + onLongPress: onLongPress, + unpressDelay: unpressDelay, + onPressed: onPressed, + child: Box(style: style, child: child), + ); + } +} + +class Pressable extends StatefulWidget { + const Pressable({ + this.behavior, + this.focusNode, + this.autofocus = false, + required this.child, + this.onFocusChange, + this.onLongPress, + this.unpressDelay = const Duration(milliseconds: 100), + this.onPressed, + this.disabled = false, + super.key, + }); + + final Widget child; + final VoidCallback? onPressed; + final VoidCallback? onLongPress; + final FocusNode? focusNode; + final bool autofocus; + final bool disabled; + final Duration unpressDelay; + final Function(bool focus)? onFocusChange; + + final HitTestBehavior? behavior; + + @override + PressableWidgetState createState() => PressableWidgetState(); +} + +class PressableWidgetState extends State { + late FocusNode _node; + bool _isInternalNode = false; + bool _hover = false; + bool _focus = false; + bool _pressed = false; + bool _longpressed = false; + + @override + void initState() { + super.initState(); + _node = widget.focusNode ?? _createFocusNode(); + _isInternalNode = widget.focusNode == null; + } + + FocusNode _createFocusNode() { + return FocusNode(debugLabel: '${widget.runtimeType}'); + } + + GestureState get _currentGesture { + // Long pressed has priority over pressed + // Due to delay of removing the _press state + if (_longpressed) return GestureState.longPressed; + + if (_pressed) return GestureState.pressed; + + return GestureState.none; + } + + @override + void didUpdateWidget(Pressable oldWidget) { + super.didUpdateWidget(oldWidget); + if (widget.focusNode != oldWidget.focusNode) { + if (_isInternalNode) _node.dispose(); + + _node = widget.focusNode ?? _createFocusNode(); + _isInternalNode = widget.focusNode == null; + } + } + + @override + void dispose() { + if (_isInternalNode) _node.dispose(); + + super.dispose(); + } + + void handleUnpress() { + void unpress() { + if (!_pressed) return; + updateState(() => _pressed = false); + } + + Future.delayed(widget.unpressDelay, unpress); + } + + updateState(void Function() fn) { + if (!mounted) return; + setState(fn); + } + + @override + Widget build(BuildContext context) { + final currentGesture = _currentGesture; + final currentStatus = + widget.disabled ? GestureStatus.disabled : GestureStatus.enabled; + + final onEnabled = currentStatus == GestureStatus.enabled; + + return MergeSemantics( + child: Semantics( + enabled: onEnabled, + button: true, + focusable: onEnabled && _node.canRequestFocus, + focused: _node.hasFocus, + child: GestureDetector( + onTapDown: (_) => updateState(() => _pressed = true), + onTapUp: (_) => handleUnpress(), + onTap: widget.onPressed, + onTapCancel: () => handleUnpress(), + onLongPressCancel: () => updateState(() => _longpressed = false), + onLongPress: widget.onLongPress, + onLongPressStart: (_) => updateState(() => _longpressed = true), + onLongPressEnd: (_) => updateState(() => _longpressed = false), + behavior: widget.behavior, + child: FocusableActionDetector( + enabled: onEnabled, + focusNode: _node, + autofocus: widget.autofocus, + onShowFocusHighlight: (v) => updateState(() => _focus = v), + onShowHoverHighlight: (v) => updateState(() => _hover = v), + onFocusChange: widget.onFocusChange, + child: GestureStateNotifier( + data: GestureData( + focus: _focus, + status: currentStatus, + state: currentGesture, + hover: _hover, + ), + child: widget.child, + ), + ), + ), + ), + ); + } +} diff --git a/lib/src/widgets/pressable/pressable.notifier.dart b/lib/src/widgets/pressable/pressable.notifier.dart deleted file mode 100644 index 525639131..000000000 --- a/lib/src/widgets/pressable/pressable.notifier.dart +++ /dev/null @@ -1,25 +0,0 @@ -import 'package:flutter/widgets.dart'; - -import 'pressable_state.dart'; - -class PressableNotifier extends InheritedWidget { - const PressableNotifier({ - super.key, - required super.child, - required this.state, - this.focus = false, - }); - - static PressableNotifier? of(BuildContext context) { - return context.dependOnInheritedWidgetOfExactType(); - } - - final PressableState state; - - final bool focus; - - @override - bool updateShouldNotify(PressableNotifier oldWidget) { - return oldWidget.focus != focus || oldWidget.state != state; - } -} diff --git a/lib/src/widgets/pressable/pressable_state.dart b/lib/src/widgets/pressable/pressable_state.dart deleted file mode 100644 index 80e5ac762..000000000 --- a/lib/src/widgets/pressable/pressable_state.dart +++ /dev/null @@ -1,7 +0,0 @@ -enum PressableState { - disabled, - inactive, - hover, - pressed, - longPressed, -} diff --git a/lib/src/widgets/pressable/pressable_widget.dart b/lib/src/widgets/pressable/pressable_widget.dart deleted file mode 100644 index d5a43da90..000000000 --- a/lib/src/widgets/pressable/pressable_widget.dart +++ /dev/null @@ -1,136 +0,0 @@ -import 'package:flutter/material.dart'; - -import 'pressable.notifier.dart'; -import 'pressable_state.dart'; - -class Pressable extends StatefulWidget { - const Pressable({ - this.autofocus = false, - this.behavior, - required this.child, - this.focusNode, - super.key, - this.onFocusChange, - this.onLongPress, - required this.onPressed, - }); - - final Widget child; - final VoidCallback? onPressed; - final VoidCallback? onLongPress; - final FocusNode? focusNode; - final bool autofocus; - final Function(bool focus)? onFocusChange; - - final HitTestBehavior? behavior; - - @override - // Ignore no need to make this api public. - // ignore: library_private_types_in_public_api - _PressableWidgetState createState() => _PressableWidgetState(); -} - -class _PressableWidgetState extends State { - late FocusNode _node; - - @override - void initState() { - super.initState(); - _node = widget.focusNode ?? _createFocusNode(); - } - - FocusNode _createFocusNode() { - return FocusNode(debugLabel: '${widget.runtimeType}'); - } - - @override - void didUpdateWidget(Pressable oldWidget) { - super.didUpdateWidget(oldWidget); - if (widget.focusNode != oldWidget.focusNode) { - _node = widget.focusNode ?? _node; - } - } - - @override - void dispose() { - if (widget.focusNode == null) _node.dispose(); - super.dispose(); - } - - bool _hover = false; - bool _focus = false; - bool _pressed = false; - bool _longpressed = false; - - bool get _onEnabled => widget.onPressed != null || widget.onLongPress != null; - - PressableState get _state { - if (widget.onPressed == null && widget.onLongPress == null) { - return PressableState.disabled; - } - // Long pressed has priority over pressed - // Due to delay of removing the _press state - if (_longpressed) { - return PressableState.longPressed; - } - - if (_pressed) { - return PressableState.pressed; - } - - if (_hover) { - return PressableState.hover; - } - - // ignore: prefer-returning-conditional-expressions - return PressableState.inactive; - } - - void handleUnpress() { - Future.delayed(const Duration(milliseconds: 100), () { - if (_pressed) { - updateState(() => _pressed = false); - } - }); - } - - updateState(void Function() fn) { - if (mounted) setState(fn); - } - - @override - Widget build(BuildContext context) { - return MergeSemantics( - child: Semantics( - enabled: _onEnabled, - button: true, - focusable: _onEnabled && _node.canRequestFocus, - focused: _node.hasFocus, - child: GestureDetector( - onTapDown: (_) => updateState(() => _pressed = true), - onTapUp: (_) => handleUnpress(), - onTap: () => widget.onPressed?.call(), - onTapCancel: () => handleUnpress(), - onLongPressCancel: () => updateState(() => _longpressed = false), - onLongPress: widget.onLongPress, - onLongPressStart: (_) => updateState(() => _longpressed = true), - onLongPressEnd: (_) => updateState(() => _longpressed = false), - behavior: widget.behavior, - child: FocusableActionDetector( - enabled: _onEnabled, - focusNode: _node, - autofocus: widget.autofocus, - onShowFocusHighlight: (v) => updateState(() => _focus = v), - onShowHoverHighlight: (v) => updateState(() => _hover = v), - onFocusChange: widget.onFocusChange, - child: PressableNotifier( - state: _state, - focus: _focus, - child: widget.child, - ), - ), - ), - ), - ); - } -} diff --git a/lib/src/widgets/styled_widget.dart b/lib/src/widgets/styled_widget.dart index ec1510406..4f51e32ba 100644 --- a/lib/src/widgets/styled_widget.dart +++ b/lib/src/widgets/styled_widget.dart @@ -1,26 +1,33 @@ import 'package:flutter/material.dart'; import '../factory/mix_provider.dart'; +import '../factory/mix_provider_data.dart'; import '../factory/style_mix.dart'; abstract class StyledWidget extends StatelessWidget { /// Constructor. const StyledWidget({ - this.style = StyleMix.empty, + required StyleMix? style, super.key, /// Inherit beavhior is off by default and allows to inherit the style from the parent Context. /// Only WidgetAttributes are inherited. Decorators will not be inherited as /// decorators should have already been applied to the parent Widget. this.inherit = false, - }); + }) : style = style ?? const StyleMix.empty(); final StyleMix style; final bool inherit; Widget withMix(BuildContext context, MixBuilder builder) { - return MixProvider.build(context, style: style, builder: builder); + final inheritedMix = inherit ? MixProvider.maybeOf(context) : null; + + final mixData = MixData.create(context, style); + + final mergedMixData = inheritedMix?.merge(mixData) ?? mixData; + + return MixProvider(data: mergedMixData, child: builder(mergedMixData)); } @override diff --git a/test/bechmarks/widget_build_test.dart b/test/bechmarks/widget_build_test.dart index 1a4fa503b..9437563ad 100644 --- a/test/bechmarks/widget_build_test.dart +++ b/test/bechmarks/widget_build_test.dart @@ -1,45 +1,209 @@ import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:mix/mix.dart'; -int expensiveFunction() { - int result = 0; - for (int i = 0; i < 10000000; i++) { - result += i; - } +import '../helpers/testing_utils.dart'; + +class StyledContainerExample extends StatelessWidget { + const StyledContainerExample({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + final paddingAttr = box.padding(10); + final marginAttr = box.margin(15); + final alignmentAttr = box.alignment.center(); + final clipAttr = box.clipBehavior.hardEdge(); + + final borderAttribute = box.border.all( + color: Colors.red, + width: 1, + style: BorderStyle.solid, + ); + + final radiusAttribute = box.borderRadius(10); + + final colorAttribute = box.color(Colors.red); - return result; + return StyledContainer( + style: StyleMix( + paddingAttr, + marginAttr, + alignmentAttr, + clipAttr, + borderAttribute, + radiusAttribute, + colorAttribute, + ), + child: const SizedBox( + width: 100, + height: 100, + ), + ); + } } -class ExpensiveWidget extends StatelessWidget { - const ExpensiveWidget({Key? key}) : super(key: key); +class StyleWidgetExpensiveAttributge extends StatelessWidget { + const StyleWidgetExpensiveAttributge({Key? key}) : super(key: key); @override Widget build(BuildContext context) { - expensiveFunction(); + final paddingAttr = box.padding(10); + final marginAttr = box.margin(15); + final alignmentAttr = box.alignment.center(); + final clipAttr = box.clipBehavior.hardEdge(); + + final borderAttribute = box.border.all( + color: Colors.red, + width: 1, + style: BorderStyle.solid, + ); + + final radiusAttribute = box.borderRadius(10); + + final colorAttribute = box.color(Colors.red); + + StyleMix buildStyle() { + return StyleMix( + paddingAttr, + marginAttr, + alignmentAttr, + clipAttr, + borderAttribute, + radiusAttribute, + colorAttribute, + ); + } + + StyleMix mergedStyle = buildStyle(); + // merge 100 times buildStyles() + for (int i = 0; i < 10000; i++) { + mergedStyle = mergedStyle.merge(buildStyle()); + } + + return StyledContainer( + style: mergedStyle, + child: const SizedBox( + width: 100, + height: 100, + ), + ); + } +} + +class ContainerExample extends StatelessWidget { + const ContainerExample({super.key}); + + @override + Widget build(BuildContext context) { return Container( - width: 100, - height: 100, - color: Colors.blue, + padding: const EdgeInsets.all(10), + margin: const EdgeInsets.all(15), + alignment: Alignment.center, + clipBehavior: Clip.hardEdge, + decoration: BoxDecoration( + border: Border.all( + color: Colors.red, + width: 1, + style: BorderStyle.solid, + ), + borderRadius: BorderRadius.circular(10), + color: Colors.red, + ), + child: const SizedBox( + width: 100, + height: 100, + ), ); } } void main() { - testWidgets('Build time test', (WidgetTester tester) async { - final widget = Container(width: 100, height: 100, color: Colors.blue); + testWidgets('Is fast enough', (WidgetTester tester) async { + const iterationCount = 10000; + + Future buildWidget(Widget widget) async { + return await tester.runAsync(() async { + final stopwatch = Stopwatch()..start(); + for (int i = 0; i < iterationCount; i++) { + await tester.pumpWidget(widget); + } + stopwatch.stop(); + return stopwatch.elapsedMilliseconds; + }) ?? + 0; + } - const expensiveWidget = ExpensiveWidget(); + // warm up + await buildWidget(const ContainerExample()); + await buildWidget(const StyledContainerExample()); + + // ignore: prefer_const_constructors + final styledContainerTime = await buildWidget(StyledContainer()); + // ignore: prefer_const_constructors + final containerTime = await buildWidget(ContainerExample()); + + final elapsedStyledContainerTime = styledContainerTime / iterationCount; + final elapsedContainerTime = containerTime / iterationCount; + + // print('StyledContainer: $elapsedStyledContainerTime ms'); + // print('Container: $elapsedContainerTime ms'); + // StyledContainer shoudl not b slower than 0.01 ms + expect(elapsedStyledContainerTime, lessThan(elapsedContainerTime + 0.02), + reason: 'StyledContainer is too slow'); + }); + + // test perfromance for StyleMix.create + test('StyleMix.create', () { + const iterations = 10000; + final stopwatch = Stopwatch()..start(); + for (int i = 0; i < iterations; i++) { + StyleMix.create([ + box.padding(10), + box.margin(15), + box.alignment.center(), + box.clipBehavior.hardEdge(), + box.border.all( + color: Colors.red, + width: 1, + style: BorderStyle.solid, + ), + box.borderRadius(10), + box.color(Colors.red), + ]); + } + stopwatch.stop(); + + final elapsedTime = stopwatch.elapsedMilliseconds / iterations; + print('StyleMix.create: $elapsedTime ms'); + }); + // test performance for MixData.create + test('MixData.create', () { + const iterations = 10000; final stopwatch = Stopwatch()..start(); - await tester.pumpWidget(widget); - final elapsed = stopwatch.elapsedMilliseconds; + for (int i = 0; i < iterations; i++) { + MixData.create( + MockBuildContext(), + StyleMix( + box.padding(10), + box.margin(15), + box.alignment.center(), + box.clipBehavior.hardEdge(), + box.border.all( + color: Colors.red, + width: 1, + style: BorderStyle.solid, + ), + box.borderRadius(10), + box.color(Colors.red), + ), + ); + } - stopwatch.reset(); - await tester.pumpWidget(expensiveWidget); - final elapsedExpensive = stopwatch.elapsedMilliseconds; + stopwatch.stop(); + final timeElapsed = stopwatch.elapsedMilliseconds / iterations; - debugPrint('Elapsed: $elapsed'); - debugPrint('Elapsed Expensive: $elapsedExpensive'); + print('MixData.create: $timeElapsed ms'); }); } diff --git a/test/helpers/testing_utils.dart b/test/helpers/testing_utils.dart index aa0c64e91..030c66d67 100644 --- a/test/helpers/testing_utils.dart +++ b/test/helpers/testing_utils.dart @@ -21,7 +21,7 @@ MixData MockMixData( final EmptyMixData = MixData.create( MockBuildContext(), - StyleMix.empty, + const StyleMix.empty(), ); MediaQuery createMediaQuery(Size size) { @@ -96,7 +96,7 @@ Widget createWithMixTheme( extension WidgetTesterExt on WidgetTester { Future pumpWithMix( Widget widget, { - StyleMix style = StyleMix.empty, + StyleMix style = const StyleMix.empty(), MixThemeData theme = const MixThemeData.empty(), }) async { await pumpWithMixTheme( @@ -129,14 +129,21 @@ extension WidgetTesterExt on WidgetTester { Future pumpWithPressable( Widget widget, { - PressableState state = PressableState.pressed, + GestureData data = const GestureData.none(), + GestureState state = GestureState.none, + GestureStatus status = GestureStatus.enabled, bool focus = false, + bool hover = false, }) async { await pumpWidget( MaterialApp( - home: PressableNotifier( - state: state, - focus: focus, + home: GestureStateNotifier( + data: data.copyWith( + state: state, + status: status, + hover: hover, + focus: focus, + ), child: widget, ), ), diff --git a/test/src/attributes/constraints/constraints_attribute_test.dart b/test/src/attributes/constraints/constraints_attribute_test.dart deleted file mode 100644 index bdd1fb07b..000000000 --- a/test/src/attributes/constraints/constraints_attribute_test.dart +++ /dev/null @@ -1,82 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_test/flutter_test.dart'; -import 'package:mix/mix.dart'; -import 'package:mix/src/attributes/constraints/constraints_dto.dart'; - -import '../../../helpers/attribute_generator.dart'; -import '../../../helpers/testing_utils.dart'; - -void main() { - group('BoxConstraintsAttribute', () { - final constraints = RandomGenerator.boxConstraints(); - final boxConstraintsDto = BoxConstraintsDto.from(constraints); - test('constructor should set the value correctly', () { - final attribute = BoxConstraintsAttribute(boxConstraintsDto); - - expect(attribute.value, isA()); - expect(attribute.value, equals(boxConstraintsDto)); - }); - - test('merge should return the same attribute if other is null', () { - final attribute = BoxConstraintsAttribute(boxConstraintsDto); - final mergedAttribute = attribute.merge(null); - - expect(mergedAttribute, equals(attribute)); - }); - - test('merge should return the same attribute if value types are different', - () { - const constraints1 = BoxConstraintsDto(minWidth: 50, minHeight: 100); - const constraints2 = BoxConstraintsDto(minWidth: 100, minHeight: 200); - const attribute1 = BoxConstraintsAttribute(constraints1); - const attribute2 = BoxConstraintsAttribute(constraints2); - final mergedAttribute = attribute1.merge(attribute2); - - expect(mergedAttribute, equals(attribute2)); - }); - - test('merge should return a new attribute with merged value', () { - final constraints1 = - BoxConstraintsDto.from(RandomGenerator.boxConstraints()); - final constraints2 = - BoxConstraintsDto.from(RandomGenerator.boxConstraints()); - - final attribute1 = BoxConstraintsAttribute(constraints1); - final attribute2 = BoxConstraintsAttribute(constraints2); - final mergedAttribute = attribute1.merge(attribute2); - - expect(mergedAttribute.value, equals(constraints1.merge(constraints2))); - }); - - test('resolve should return the constraints value', () { - const constraints = BoxConstraintsDto( - minWidth: 50, minHeight: 100, maxWidth: 100, maxHeight: 200); - const attribute = BoxConstraintsAttribute(constraints); - - final resolvedConstraints = attribute.resolve(EmptyMixData); - - expect(resolvedConstraints.minWidth, 50); - expect(resolvedConstraints.minHeight, 100); - expect(resolvedConstraints.maxWidth, 100); - expect(resolvedConstraints.maxHeight, 200); - }); - - testWidgets('build', (widgetTester) async { - const constraints = BoxConstraintsDto(minWidth: 50, minHeight: 100); - const attribute = BoxConstraintsAttribute(constraints); - final widget = attribute.build(EmptyMixData, Container()); - - await widgetTester.pumpMaterialApp(widget); - - final finder = find.byWidget(widget); - - final constrainedBox = widgetTester.widget(finder); - - final boxConstraints = constrainedBox.constraints; - - expect(boxConstraints, isA()); - expect(boxConstraints.minWidth, 50); - expect(boxConstraints.minHeight, 100); - }); - }); -} diff --git a/test/src/attributes/constraints/constraints_util_test.dart b/test/src/attributes/constraints/constraints_util_test.dart index 14c8479cb..bbb50bbeb 100644 --- a/test/src/attributes/constraints/constraints_util_test.dart +++ b/test/src/attributes/constraints/constraints_util_test.dart @@ -1,10 +1,11 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:mix/mix.dart'; -import 'package:mix/src/attributes/constraints/constraints_dto.dart'; + +import '../../../helpers/testing_utils.dart'; void main() { group('BoxConstraintsUtility', () { - const boxConstraints = BoxConstraintsUtility(BoxConstraintsAttribute.new); + const boxConstraints = BoxConstraintsUtility(UtilityTestAttribute.new); test('boxConstraints()', () { final result = boxConstraints( minWidth: 50.0, @@ -13,7 +14,6 @@ void main() { maxHeight: 200.0, ); - expect(result, isA()); expect(result.value, isA()); expect(result.value.minWidth, 50.0); expect(result.value.maxWidth, 150.0); @@ -22,7 +22,7 @@ void main() { }); test('minWidth()', () { - final result = minWidth(50.0); + final result = boxConstraints.minWidth(50.0); expect(result.value.minWidth, 50.0); expect(result.value.maxWidth, isNull); expect(result.value.minHeight, isNull); @@ -30,7 +30,7 @@ void main() { }); test('maxWidth()', () { - final result = maxWidth(150.0); + final result = boxConstraints.maxWidth(150.0); expect(result.value.minWidth, isNull); expect(result.value.maxWidth, 150.0); expect(result.value.minHeight, isNull); @@ -38,7 +38,7 @@ void main() { }); test('minHeight()', () { - final result = minHeight(100.0); + final result = boxConstraints.minHeight(100.0); expect(result.value.minWidth, isNull); expect(result.value.maxWidth, isNull); expect(result.value.minHeight, 100.0); @@ -46,7 +46,7 @@ void main() { }); test('maxHeight()', () { - final result = maxHeight(200.0); + final result = boxConstraints.maxHeight(200.0); expect(result.value.minWidth, isNull); expect(result.value.maxWidth, isNull); expect(result.value.minHeight, isNull); diff --git a/test/src/attributes/decoration/decoration_attribute_test.dart b/test/src/attributes/decoration/decoration_attribute_test.dart deleted file mode 100644 index cc9a5180b..000000000 --- a/test/src/attributes/decoration/decoration_attribute_test.dart +++ /dev/null @@ -1,79 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_test/flutter_test.dart'; -import 'package:mix/mix.dart'; -import 'package:mix/src/attributes/decoration/decoration_dto.dart'; - -import '../../../helpers/attribute_generator.dart'; -import '../../../helpers/testing_utils.dart'; - -void main() { - group('DecorationAttribute', () { - final border = RandomGenerator.border(); - final boxDecorationDto = BoxDecorationDto( - color: const ColorDto(Colors.red), - shape: BoxShape.circle, - border: BoxBorderDto.from(border), - ); - test('constructor should set the value correctly', () { - final attribute = DecorationAttribute(boxDecorationDto); - - expect(attribute.value, isA()); - expect(attribute.value, equals(boxDecorationDto)); - }); - - test('merge should return the same attribute if other is null', () { - final attribute = DecorationAttribute(boxDecorationDto); - final mergedAttribute = attribute.merge(null); - - expect(mergedAttribute, equals(attribute)); - }); - - test('merge should return the same attribute if value types are different', - () { - const decoration1 = BoxDecorationDto(color: ColorDto(Colors.red)); - const decoration2 = BoxDecorationDto(color: ColorDto(Colors.blue)); - const attribute1 = DecorationAttribute(decoration1); - const attribute2 = DecorationAttribute(decoration2); - final mergedAttribute = attribute1.merge(attribute2); - - expect(mergedAttribute, equals(attribute2)); - }); - - test('merge should return a new attribute with merged value', () { - final decoration1 = - BoxDecorationDto.from(RandomGenerator.boxDecoration()); - final decoration2 = - BoxDecorationDto.from(RandomGenerator.boxDecoration()); - - final attribute1 = DecorationAttribute(decoration1); - final attribute2 = DecorationAttribute(decoration2); - final mergedAttribute = attribute1.merge(attribute2); - - expect(mergedAttribute.value, equals(decoration1.merge(decoration2))); - }); - - test('resolve should return the decoration value', () { - const decoration = BoxDecorationDto(color: ColorDto(Colors.red)); - const attribute = DecorationAttribute(decoration); - final resolvedDecoration = attribute.resolve(EmptyMixData); - - expect( - resolvedDecoration, - equals( - const BoxDecoration(color: Colors.red), - )); - }); - - testWidgets('build', (widgetTester) async { - const decoration = BoxDecorationDto(color: ColorDto(Colors.red)); - const attribute = DecorationAttribute(decoration); - final widget = attribute.build(EmptyMixData, Container()); - - await widgetTester.pumpWidget(widget); - final decorationBox = - widgetTester.widget(find.byType(DecoratedBox)); - expect( - decorationBox.decoration, equals(decoration.resolve(EmptyMixData))); - }); - }); -} diff --git a/test/src/attributes/decoration/decoration_dto_test.dart b/test/src/attributes/decoration/decoration_dto_test.dart index 31a37fcb3..3f0962aff 100644 --- a/test/src/attributes/decoration/decoration_dto_test.dart +++ b/test/src/attributes/decoration/decoration_dto_test.dart @@ -1,8 +1,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:mix/mix.dart'; -import 'package:mix/src/attributes/decoration/decoration_dto.dart'; -import 'package:mix/src/attributes/gradient/gradient_dto.dart'; import '../../../helpers/attribute_generator.dart'; import '../../../helpers/testing_utils.dart'; diff --git a/test/src/attributes/decoration/decoration_util_test.dart b/test/src/attributes/decoration/decoration_util_test.dart index f2d983f59..65690fc47 100644 --- a/test/src/attributes/decoration/decoration_util_test.dart +++ b/test/src/attributes/decoration/decoration_util_test.dart @@ -1,16 +1,29 @@ import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:mix/mix.dart'; -import 'package:mix/src/attributes/decoration/decoration_dto.dart'; -import 'package:mix/src/attributes/gradient/gradient_dto.dart'; import '../../../helpers/attribute_generator.dart'; import '../../../helpers/testing_utils.dart'; void main() { - const boxDecoration = BoxDecorationUtility(UtilityTestAttribute.new); + // DecorationUtility + group('DecorationUtility', () { + const decorationUtility = DecorationUtility(UtilityTestAttribute.new); + // box + test('box returns correct instance', () { + final box = decorationUtility.box; + expect(box, isA()); + }); + + // shape + test('shape returns correct instance', () { + final shape = decorationUtility.shape; + expect(shape, isA()); + }); + }); group('BoxDecorationUtility', () { + const boxDecoration = BoxDecorationUtility(UtilityTestAttribute.new); test('call', () { final refBoxDecoration = RandomGenerator.boxDecoration(); @@ -45,7 +58,8 @@ void main() { expect(result.value.shape, equals(refBoxDecoration.shape)); }); test('color setting', () { - final result = boxDecoration(color: Colors.red); + final result = boxDecoration.color(Colors.red); + expect(result.value.color, equals(Colors.red.toDto())); }); @@ -77,15 +91,23 @@ void main() { }); test('boxShadow setting', () { - final boxShadow = [ - const BoxShadow( - color: Colors.black, - blurRadius: 10.0, - offset: Offset(5.0, 5.0), - ) - ]; - final result = boxDecoration.boxShadow(boxShadow); - expect(result.value.boxShadow, equals(boxShadow.toDto())); + const boxShadow = BoxShadow( + color: Colors.black, + blurRadius: 10.0, + offset: Offset(5.0, 5.0), + spreadRadius: 2.0, + ); + + final result = boxDecoration.boxShadows([boxShadow]); + + final resultSingle = boxDecoration.boxShadow( + color: Colors.black, + blurRadius: 10.0, + offset: const Offset(5.0, 5.0), + spreadRadius: 2.0, + ); + expect(result.value.boxShadow, equals([boxShadow].toDto())); + expect(resultSingle.value.boxShadow?.first, equals(boxShadow.toDto())); }); test('elevation setting', () { @@ -95,4 +117,77 @@ void main() { expect(boxShadows, equals(kElevationToShadow[9]!)); }); }); + + // ShapeDecorationUtility + group('ShapeDecorationUtility', () { + const shapeDecoration = ShapeDecorationUtility(UtilityTestAttribute.new); + const boxShadow = BoxShadow( + color: Colors.black, + blurRadius: 10.0, + offset: Offset(5.0, 5.0), + ); + + const linearGradient = LinearGradient( + begin: Alignment.topLeft, + end: Alignment.bottomRight, + colors: [Colors.red, Colors.blue], + ); + + // call() + test('call() returns correct instance', () { + final result = shapeDecoration( + color: Colors.blue, + gradient: linearGradient, + shadows: const [boxShadow], + ); + + expect(result.value.color, equals(Colors.blue.toDto())); + expect( + result.value.gradient, + equals(GradientDto.from( + linearGradient, + ))); + expect( + result.value.shadows, + equals( + const [boxShadow].map((e) => BoxShadowDto.from(e)).toList(), + )); + }); + + // color() + test('color() returns correct instance', () { + final result = shapeDecoration.color(Colors.blue); + + expect(result.value.color, equals(Colors.blue.toDto())); + }); + + // gradient() + test('gradient() returns correct instance', () { + final result = shapeDecoration.gradient.as(linearGradient); + + expect( + result.value.gradient, + equals(GradientDto.from( + linearGradient, + ))); + }); + + // shadows() + test('shadows() returns correct instance', () { + final result = shapeDecoration.shadows([boxShadow]); + + expect( + result.value.shadows, + equals( + const [boxShadow].map((e) => BoxShadowDto.from(e)).toList(), + )); + }); + + // shape() + test('shape() returns correct instance', () { + final result = shapeDecoration.shape.circle(); + + expect(result.value.shape, equals(const CircleBorder())); + }); + }); } diff --git a/test/src/attributes/gradient/gradient_dto_test.dart b/test/src/attributes/gradient/gradient_dto_test.dart index 8b1378917..3726a84d9 100644 --- a/test/src/attributes/gradient/gradient_dto_test.dart +++ b/test/src/attributes/gradient/gradient_dto_test.dart @@ -1 +1,384 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:mix/mix.dart'; +import '../../../helpers/testing_utils.dart'; + +void main() { + // GradientDto + group('GradientDto', () { + test('from method correctly converts Gradient to GradientDto', () { + const linearGradient = LinearGradient( + begin: Alignment.topLeft, + end: Alignment.bottomRight, + colors: [Colors.red, Colors.blue], + stops: [0.0, 1.0], + ); + + const radialGradient = RadialGradient( + center: Alignment.center, + radius: 0.5, + colors: [Colors.red, Colors.blue], + stops: [0.0, 1.0], + ); + + const sweepGradient = SweepGradient( + center: Alignment.center, + startAngle: 0.0, + endAngle: 1.0, + colors: [Colors.red, Colors.blue], + stops: [0.0, 1.0], + ); + + final linearGradientDto = GradientDto.from(linearGradient); + final radialGradientDto = GradientDto.from(radialGradient); + final sweepGradientDto = GradientDto.from(sweepGradient); + + expect(linearGradientDto, isA()); + expect(radialGradientDto, isA()); + expect(sweepGradientDto, isA()); + + final resolvedLinearGradient = linearGradientDto.resolve(EmptyMixData); + final resolvedRadialGradient = radialGradientDto.resolve(EmptyMixData); + final resolvedSweepGradient = sweepGradientDto.resolve(EmptyMixData); + + expect(resolvedLinearGradient, isA()); + expect(resolvedLinearGradient, linearGradient); + expect(resolvedRadialGradient, isA()); + expect(resolvedRadialGradient, radialGradient); + expect(resolvedSweepGradient, isA()); + expect(resolvedSweepGradient, sweepGradient); + }); + }); + + group('LinearGradientDto', () { + test('Constructor assigns correct properties', () { + const gradientDto = LinearGradientDto( + begin: Alignment.topLeft, + end: Alignment.bottomRight, + colors: [ColorDto(Colors.red), ColorDto(Colors.blue)], + stops: [0.0, 1.0], + tileMode: TileMode.clamp, + ); + + expect(gradientDto.begin, Alignment.topLeft); + expect(gradientDto.end, Alignment.bottomRight); + expect(gradientDto.colors?.length, 2); + expect(gradientDto.stops, [0.0, 1.0]); + expect(gradientDto.tileMode, TileMode.clamp); + }); + + test('from method correctly converts LinearGradient to LinearGradientDto', + () { + const linearGradient = LinearGradient( + begin: Alignment.topLeft, + end: Alignment.bottomRight, + colors: [Colors.red, Colors.blue], + stops: [0.0, 1.0], + ); + final gradientDto = LinearGradientDto.from(linearGradient); + + expect(gradientDto.begin, linearGradient.begin); + expect(gradientDto.end, linearGradient.end); + expect(gradientDto.colors?.length, linearGradient.colors.length); + expect(gradientDto.stops, linearGradient.stops); + }); + + test('resolve method returns correct LinearGradient', () { + const gradientDto = LinearGradientDto( + begin: Alignment.topLeft, + end: Alignment.bottomRight, + colors: [ColorDto(Colors.red), ColorDto(Colors.blue)], + stops: [0.0, 1.0], + ); + + final resolvedGradient = gradientDto.resolve(EmptyMixData); + + expect(resolvedGradient, isA()); + expect(resolvedGradient.colors.length, 2); + }); + + test('merge method correctly merges two LinearGradientDtos', () { + const gradientDto1 = LinearGradientDto( + begin: Alignment.topLeft, + end: Alignment.bottomRight, + colors: [ColorDto(Colors.red), ColorDto(Colors.blue)], + stops: [0.0, 1.0], + ); + const gradientDto2 = LinearGradientDto( + begin: Alignment.centerLeft, + end: Alignment.centerRight, + colors: [ColorDto(Colors.green), ColorDto(Colors.yellow)], + stops: [0.25, 0.75], + ); + + final mergedGradient = gradientDto1.merge(gradientDto2); + + expect(mergedGradient.begin, gradientDto2.begin); + expect(mergedGradient.end, gradientDto2.end); + expect(mergedGradient.colors, isNotNull); + expect(mergedGradient.colors?.length, 2); + expect(mergedGradient.stops, [0.25, 0.75]); + }); + + test('== operator returns true for equal objects', () { + const gradientDto1 = LinearGradientDto( + begin: Alignment.topLeft, + end: Alignment.bottomRight, + colors: [ColorDto(Colors.red), ColorDto(Colors.blue)], + stops: [0.0, 1.0], + ); + const gradientDto2 = LinearGradientDto( + begin: Alignment.topLeft, + end: Alignment.bottomRight, + colors: [ColorDto(Colors.red), ColorDto(Colors.blue)], + stops: [0.0, 1.0], + ); + + expect(gradientDto1 == gradientDto2, true); + }); + + test('== operator returns false for different objects', () { + const gradientDto1 = LinearGradientDto( + begin: Alignment.topLeft, + end: Alignment.bottomRight, + colors: [ColorDto(Colors.red), ColorDto(Colors.blue)], + stops: [0.0, 1.0], + ); + const gradientDto2 = LinearGradientDto( + begin: Alignment.centerLeft, + end: Alignment.centerRight, + colors: [ColorDto(Colors.green), ColorDto(Colors.yellow)], + stops: [0.25, 0.75], + ); + + expect(gradientDto1 == gradientDto2, false); + }); + }); + + // RadialGradientDto + group('RadialGradientDto', () { + test('Constructor assigns correct properties', () { + const gradientDto = RadialGradientDto( + center: Alignment.center, + radius: 0.5, + colors: [ColorDto(Colors.red), ColorDto(Colors.blue)], + stops: [0.0, 1.0], + tileMode: TileMode.clamp, + ); + + expect(gradientDto.center, Alignment.center); + expect(gradientDto.radius, 0.5); + expect(gradientDto.colors?.length, 2); + expect(gradientDto.stops, [0.0, 1.0]); + expect(gradientDto.tileMode, TileMode.clamp); + }); + + test('from method correctly converts RadialGradient to RadialGradientDto', + () { + const radialGradient = RadialGradient( + center: Alignment.center, + radius: 0.5, + colors: [Colors.red, Colors.blue], + stops: [0.0, 1.0], + ); + final gradientDto = RadialGradientDto.from(radialGradient); + + expect(gradientDto.center, radialGradient.center); + expect(gradientDto.radius, radialGradient.radius); + expect(gradientDto.colors?.length, radialGradient.colors.length); + expect(gradientDto.stops, radialGradient.stops); + }); + + test('resolve method returns correct RadialGradient', () { + const gradientDto = RadialGradientDto( + center: Alignment.center, + radius: 0.5, + colors: [ColorDto(Colors.red), ColorDto(Colors.blue)], + stops: [0.0, 1.0], + ); + + final resolvedGradient = gradientDto.resolve(EmptyMixData); + + expect(resolvedGradient, isA()); + expect(resolvedGradient.colors.length, 2); + }); + + test('merge method correctly merges two RadialGradientDtos', () { + const gradientDto1 = RadialGradientDto( + center: Alignment.center, + radius: 0.5, + colors: [ColorDto(Colors.red), ColorDto(Colors.blue)], + stops: [0.0, 1.0], + ); + const gradientDto2 = RadialGradientDto( + center: Alignment.centerLeft, + radius: 0.75, + colors: [ColorDto(Colors.green), ColorDto(Colors.yellow)], + stops: [0.25, 0.75], + ); + + final mergedGradient = gradientDto1.merge(gradientDto2); + + expect(mergedGradient.center, gradientDto2.center); + expect(mergedGradient.radius, gradientDto2.radius); + expect(mergedGradient.colors, isNotNull); + expect(mergedGradient.colors?.length, 2); + expect(mergedGradient.stops, [0.25, 0.75]); + }); + + test('== operator returns true for equal objects', () { + const gradientDto1 = RadialGradientDto( + center: Alignment.center, + radius: 0.5, + colors: [ColorDto(Colors.red), ColorDto(Colors.blue)], + stops: [0.0, 1.0], + ); + const gradientDto2 = RadialGradientDto( + center: Alignment.center, + radius: 0.5, + colors: [ColorDto(Colors.red), ColorDto(Colors.blue)], + stops: [0.0, 1.0], + ); + + expect(gradientDto1 == gradientDto2, true); + }); + + test('== operator returns false for different objects', () { + const gradientDto1 = RadialGradientDto( + center: Alignment.center, + radius: 0.5, + colors: [ColorDto(Colors.red), ColorDto(Colors.blue)], + stops: [0.0, 1.0], + ); + const gradientDto2 = RadialGradientDto( + center: Alignment.centerLeft, + radius: 0.75, + colors: [ColorDto(Colors.green), ColorDto(Colors.yellow)], + stops: [0.25, 0.75], + ); + + expect(gradientDto1 == gradientDto2, false); + }); + }); + + // SweepGradientDto + group('SweepGradientDto', () { + test('Constructor assigns correct properties', () { + const gradientDto = SweepGradientDto( + center: Alignment.center, + startAngle: 0.0, + endAngle: 1.0, + colors: [ColorDto(Colors.red), ColorDto(Colors.blue)], + stops: [0.0, 1.0], + tileMode: TileMode.clamp, + ); + expect(gradientDto.center, Alignment.center); + expect(gradientDto.startAngle, 0.0); + expect(gradientDto.endAngle, 1.0); + expect(gradientDto.colors?.length, 2); + expect(gradientDto.stops, [0.0, 1.0]); + expect(gradientDto.tileMode, TileMode.clamp); + }); + + test('from method correctly converts SweepGradient to SweepGradientDto', + () { + const sweepGradient = SweepGradient( + center: Alignment.center, + startAngle: 0.0, + endAngle: 1.0, + colors: [Colors.red, Colors.blue], + stops: [0.0, 1.0], + ); + final gradientDto = SweepGradientDto.from(sweepGradient); + + expect(gradientDto.center, sweepGradient.center); + expect(gradientDto.startAngle, sweepGradient.startAngle); + expect(gradientDto.endAngle, sweepGradient.endAngle); + expect(gradientDto.colors?.length, sweepGradient.colors.length); + expect(gradientDto.stops, sweepGradient.stops); + }); + + test('resolve method returns correct SweepGradient', () { + const gradientDto = SweepGradientDto( + center: Alignment.center, + startAngle: 0.0, + endAngle: 1.0, + colors: [ColorDto(Colors.red), ColorDto(Colors.blue)], + stops: [0.0, 1.0], + ); + + final resolvedGradient = gradientDto.resolve(EmptyMixData); + + expect(resolvedGradient, isA()); + expect(resolvedGradient.colors.length, 2); + }); + + test('merge method correctly merges two SweepGradientDtos', () { + const gradientDto1 = SweepGradientDto( + center: Alignment.center, + startAngle: 0.0, + endAngle: 1.0, + colors: [ColorDto(Colors.red), ColorDto(Colors.blue)], + stops: [0.0, 1.0], + ); + + const gradientDto2 = SweepGradientDto( + center: Alignment.centerLeft, + startAngle: 0.25, + endAngle: 0.75, + colors: [ColorDto(Colors.green), ColorDto(Colors.yellow)], + stops: [0.25, 0.75], + ); + + final mergedGradient = gradientDto1.merge(gradientDto2); + + expect(mergedGradient.center, gradientDto2.center); + expect(mergedGradient.startAngle, gradientDto2.startAngle); + expect(mergedGradient.endAngle, gradientDto2.endAngle); + expect(mergedGradient.colors, isNotNull); + expect(mergedGradient.colors?.length, 2); + expect(mergedGradient.stops, [0.25, 0.75]); + }); + + test('== operator returns true for equal objects', () { + const gradientDto1 = SweepGradientDto( + center: Alignment.center, + startAngle: 0.0, + endAngle: 1.0, + colors: [ColorDto(Colors.red), ColorDto(Colors.blue)], + stops: [0.0, 1.0], + ); + + const gradientDto2 = SweepGradientDto( + center: Alignment.center, + startAngle: 0.0, + endAngle: 1.0, + colors: [ColorDto(Colors.red), ColorDto(Colors.blue)], + stops: [0.0, 1.0], + ); + + expect(gradientDto1 == gradientDto2, true); + }); + + test('== operator returns false for different objects', () { + const gradientDto1 = SweepGradientDto( + center: Alignment.center, + startAngle: 0.0, + endAngle: 1.0, + colors: [ColorDto(Colors.red), ColorDto(Colors.blue)], + stops: [0.0, 1.0], + ); + + const gradientDto2 = SweepGradientDto( + center: Alignment.centerLeft, + startAngle: 0.25, + endAngle: 0.75, + colors: [ColorDto(Colors.green), ColorDto(Colors.yellow)], + stops: [0.25, 0.75], + ); + + expect(gradientDto1 == gradientDto2, false); + }); + }); +} diff --git a/test/src/attributes/scalars/scalar_util_test.dart b/test/src/attributes/scalars/scalar_util_test.dart index c0a5ca510..e4c0558a1 100644 --- a/test/src/attributes/scalars/scalar_util_test.dart +++ b/test/src/attributes/scalars/scalar_util_test.dart @@ -170,6 +170,89 @@ void main() { }); }); + // AlignmentUtility + group('AlignmentUtility Tests', () { + const utility = AlignmentUtility(UtilityTestAttribute.new); + + // only + test('only() returns correct instance', () { + final alignment = utility.only(x: 10, y: 8); + final alignmnetDirectional = utility.only(start: 10, y: 8); + + expect(alignment.value, equals(const Alignment(10, 8))); + expect(alignmnetDirectional.value, + equals(const AlignmentDirectional(10, 8))); + + expect(() => utility.only(x: 10, start: 8), throwsAssertionError); + }); + test('Properties are initialized correctly', () { + expect(utility.topLeft().value, isA()); + expect(utility.topCenter().value, isA()); + expect(utility.topRight().value, isA()); + expect(utility.centerLeft().value, isA()); + expect(utility.center().value, isA()); + expect(utility.centerRight().value, isA()); + expect(utility.bottomLeft().value, isA()); + expect(utility.bottomCenter().value, isA()); + expect(utility.bottomRight().value, isA()); + expect(utility.topLeft().value, Alignment.topLeft); + expect(utility.topCenter().value, Alignment.topCenter); + expect(utility.topRight().value, Alignment.topRight); + expect(utility.centerLeft().value, Alignment.centerLeft); + expect(utility.center().value, Alignment.center); + expect(utility.centerRight().value, Alignment.centerRight); + expect(utility.bottomLeft().value, Alignment.bottomLeft); + expect(utility.bottomCenter().value, Alignment.bottomCenter); + expect(utility.bottomRight().value, Alignment.bottomRight); + }); + }); + +// BorderStyleUtility + group('BorderStyleUtility Tests', () { + const utility = BorderStyleUtility(UtilityTestAttribute.new); + test('Properties are initialized correctly', () { + expect(utility.none().value, isA()); + expect(utility.solid().value, isA()); + expect(utility.none().value, BorderStyle.none); + expect(utility.solid().value, BorderStyle.solid); + }); + }); + + // ShapeBorderUtility + + group('ShapeBorderUtility', () { + const utility = ShapeBorderUtility(UtilityTestAttribute.new); + + // circle() + test('circle() returns correct instance', () { + final shapeBorder = utility.circle(); + + expect(shapeBorder.value, isA()); + }); + + // stadium() + test('stadium() returns correct instance', () { + final shapeBorder = utility.stadium(); + + expect(shapeBorder.value, isA()); + }); + + // rounded() + test('rounded() returns correct instance', () { + final shapeBorder = utility.rounded(20); + + expect(shapeBorder.value, isA()); + expect((shapeBorder.value as RoundedRectangleBorder).borderRadius, + BorderRadius.circular(20)); + }); + + // beveled() + test('beveled() returns correct instance', () { + final shapeBorder = utility.beveled(); + + expect(shapeBorder.value, isA()); + }); + }); group('BoxFitUtility Tests', () { const utility = BoxFitUtility(UtilityTestAttribute.new); test('Properties are initialized correctly', () { @@ -200,6 +283,69 @@ void main() { }); }); + // TextDirectionUtility + group('TextDirectionUtility Tests', () { + const utility = TextDirectionUtility(UtilityTestAttribute.new); + test('Properties are initialized correctly', () { + expect(utility.ltr().value, isA()); + expect(utility.rtl().value, isA()); + expect(utility.ltr().value, TextDirection.ltr); + expect(utility.rtl().value, TextDirection.rtl); + }); + }); + + // TileModeUtility + group('TileModeUtility Tests', () { + const utility = TileModeUtility(UtilityTestAttribute.new); + test('Properties are initialized correctly', () { + expect(utility.clamp().value, isA()); + expect(utility.mirror().value, isA()); + expect(utility.repeated().value, isA()); + expect(utility.clamp().value, TileMode.clamp); + expect(utility.mirror().value, TileMode.mirror); + expect(utility.repeated().value, TileMode.repeated); + }); + }); + + // GradientTransformUtility + group('GradientTransformUtility Tests', () { + const utility = GradientTransformUtility(UtilityTestAttribute.new); + test('rotate', () { + expect(utility.rotate(20).value, isA()); + expect(utility.rotate(20).value, const GradientRotation(20)); + }); + }); + + // Matrix4Utility + group('Matrix4Utility Tests', () { + const utility = Matrix4Utility(UtilityTestAttribute.new); + test('identity', () { + expect(utility.identity().value, isA()); + expect(utility.identity().value, Matrix4.identity()); + }); + + test('rotationX', () { + expect(utility.rotationX(20).value, isA()); + expect(utility.rotationX(20).value, Matrix4.rotationX(20)); + }); + + test('rotationY', () { + expect(utility.rotationY(20).value, isA()); + expect(utility.rotationY(20).value, Matrix4.rotationY(20)); + }); + + test('rotationZ', () { + expect(utility.rotationZ(20).value, isA()); + expect(utility.rotationZ(20).value, Matrix4.rotationZ(20)); + }); + + test('translation', () { + expect(utility.translationValues(20, 20, 20).value, isA()); + expect(utility.translationValues(20, 20, 20).value, + Matrix4.translationValues(20, 20, 20)); + }); + }); + group('BlendModeUtility Tests', () { test('Properties are initialized correctly', () { const utility = BlendModeUtility(UtilityTestAttribute.new); @@ -218,4 +364,120 @@ void main() { expect(utility.plus().value, BlendMode.plus); }); }); + + // BlendModeUtility + group('BlendModeUtility Tests', () { + const utility = BlendModeUtility(UtilityTestAttribute.new); + test('Properties are initialized correctly', () { + expect(utility.clear().value, isA()); + expect(utility.src().value, isA()); + expect(utility.dst().value, isA()); + expect(utility.srcOver().value, isA()); + expect(utility.dstOver().value, isA()); + expect(utility.srcIn().value, isA()); + expect(utility.dstIn().value, isA()); + expect(utility.srcOut().value, isA()); + expect(utility.dstOut().value, isA()); + expect(utility.srcATop().value, isA()); + expect(utility.dstATop().value, isA()); + expect(utility.xor().value, isA()); + expect(utility.plus().value, isA()); + expect(utility.clear().value, BlendMode.clear); + expect(utility.src().value, BlendMode.src); + expect(utility.dst().value, BlendMode.dst); + expect(utility.srcOver().value, BlendMode.srcOver); + expect(utility.dstOver().value, BlendMode.dstOver); + expect(utility.srcIn().value, BlendMode.srcIn); + expect(utility.dstIn().value, BlendMode.dstIn); + expect(utility.srcOut().value, BlendMode.srcOut); + expect(utility.dstOut().value, BlendMode.dstOut); + expect(utility.srcATop().value, BlendMode.srcATop); + expect(utility.dstATop().value, BlendMode.dstATop); + expect(utility.xor().value, BlendMode.xor); + expect(utility.plus().value, BlendMode.plus); + }); + }); + + // FontWeightUtility + group('FontWeightUtility Tests', () { + const utility = FontWeightUtility(UtilityTestAttribute.new); + test('Properties are initialized correctly', () { + expect(utility.bold().value, isA()); + expect(utility.normal().value, isA()); + expect(utility.bold().value, FontWeight.bold); + expect(utility.normal().value, FontWeight.normal); + expect(utility.w100().value, isA()); + expect(utility.w200().value, isA()); + expect(utility.w300().value, isA()); + expect(utility.w400().value, isA()); + expect(utility.w500().value, isA()); + expect(utility.w600().value, isA()); + expect(utility.w700().value, isA()); + expect(utility.w800().value, isA()); + expect(utility.w900().value, isA()); + expect(utility.w100().value, FontWeight.w100); + expect(utility.w200().value, FontWeight.w200); + expect(utility.w300().value, FontWeight.w300); + expect(utility.w400().value, FontWeight.w400); + expect(utility.w500().value, FontWeight.w500); + expect(utility.w600().value, FontWeight.w600); + expect(utility.w700().value, FontWeight.w700); + expect(utility.w800().value, FontWeight.w800); + expect(utility.w900().value, FontWeight.w900); + }); + }); + + // TextDecorationUtility + group('TextDecorationUtility Tests', () { + const utility = TextDecorationUtility(UtilityTestAttribute.new); + test('Properties are initialized correctly', () { + expect(utility.none().value, isA()); + expect(utility.underline().value, isA()); + expect(utility.overline().value, isA()); + expect(utility.lineThrough().value, isA()); + expect(utility.none().value, TextDecoration.none); + expect(utility.underline().value, TextDecoration.underline); + expect(utility.overline().value, TextDecoration.overline); + expect(utility.lineThrough().value, TextDecoration.lineThrough); + }); + }); + + // FontStyleUtility + group('FontStyleUtility Tests', () { + const utility = FontStyleUtility(UtilityTestAttribute.new); + test('Properties are initialized correctly', () { + expect(utility.normal().value, isA()); + expect(utility.italic().value, isA()); + expect(utility.normal().value, FontStyle.normal); + expect(utility.italic().value, FontStyle.italic); + }); + }); + + // RadiusUtility + group('RadiusUtility Tests', () { + const utility = RadiusUtility(UtilityTestAttribute.new); + test('Properties are initialized correctly', () { + expect(utility.circular(10).value, isA()); + expect(utility.circular(10).value, const Radius.circular(10)); + expect(utility.elliptical(10, 20).value, isA()); + expect(utility.elliptical(10, 20).value, const Radius.elliptical(10, 20)); + }); + }); + + // TextDecorationStyleUtility + group('TextDecorationStyleUtility Tests', () { + const utility = TextDecorationStyleUtility(UtilityTestAttribute.new); + test('Properties are initialized correctly', () { + expect(utility.solid().value, isA()); + expect(utility.double().value, isA()); + expect(utility.dotted().value, isA()); + expect(utility.dashed().value, isA()); + expect(utility.wavy().value, isA()); + expect(utility.solid().value, TextDecorationStyle.solid); + expect(utility.double().value, TextDecorationStyle.double); + expect(utility.dotted().value, TextDecorationStyle.dotted); + expect(utility.dashed().value, TextDecorationStyle.dashed); + expect(utility.wavy().value, TextDecorationStyle.wavy); + }); + }); } diff --git a/test/src/attributes/scalars/scalars_attribute_test.dart b/test/src/attributes/scalars/scalars_attribute_test.dart deleted file mode 100644 index ad5532085..000000000 --- a/test/src/attributes/scalars/scalars_attribute_test.dart +++ /dev/null @@ -1,95 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_test/flutter_test.dart'; -import 'package:mix/mix.dart'; - -import '../../../helpers/testing_utils.dart'; - -void main() { - group('AxisAttribute Tests', () { - test('initializes correctly', () { - const axisAttribute = AxisAttribute(Axis.vertical); - expect(axisAttribute.value, Axis.vertical); - }); - - // maybeFrom - test('maybeFrom returns null if value is null', () { - final axisAttribute = AxisAttribute.maybeFrom(null); - expect(axisAttribute, isNull); - }); - }); - - group('TransformAttribute Tests', () { - test('initializes correctly', () { - final transformAttribute = TransformAttribute(Matrix4.identity()); - expect(transformAttribute.value, Matrix4.identity()); - }); - - test('maybeFrom returns null if value is null', () { - final transformAttribute = TransformAttribute.maybeFrom(null); - expect(transformAttribute, isNull); - }); - - test('build returns a Transform widget', () { - final transformAttribute = TransformAttribute(Matrix4.identity()); - final transform = transformAttribute.build(EmptyMixData, Container()); - expect(transform, isA()); - expect(transform.transform, Matrix4.identity()); - }); - }); - - group('AlignmentGeometryAttribute Tests', () { - test('initializes correctly', () { - const alignmentGeometryAttribute = - AlignmentGeometryAttribute(Alignment.center); - expect(alignmentGeometryAttribute.value, Alignment.center); - }); - - test('maybeFrom returns null if value is null', () { - final alignmentGeometryAttribute = - AlignmentGeometryAttribute.maybeFrom(null); - expect(alignmentGeometryAttribute, isNull); - }); - - test('build returns an Align widget', () { - const alignmentGeometryAttribute = - AlignmentGeometryAttribute(Alignment.topLeft); - final align = alignmentGeometryAttribute.build(EmptyMixData, Container()); - expect(align, isA()); - expect(align.alignment, Alignment.topLeft); - }); - }); - - group('ClipBehaviorAttribute Tests', () { - test('initializes correctly', () { - const clipBehaviorAttribute = ClipBehaviorAttribute(Clip.hardEdge); - expect(clipBehaviorAttribute.value, Clip.hardEdge); - }); - - test('maybeFrom returns null if value is null', () { - final clipBehaviorAttribute = ClipBehaviorAttribute.maybeFrom(null); - expect(clipBehaviorAttribute, isNull); - }); - }); - - group('BackgroundColorAttribute Tests', () { - test('initializes correctly', () { - const backgroundColorAttribute = - BackgroundColorAttribute(ColorDto(Colors.red)); - expect(backgroundColorAttribute.value.value, Colors.red); - }); - - test('maybeFrom returns null if value is null', () { - final backgroundColorAttribute = BackgroundColorAttribute.maybeFrom(null); - expect(backgroundColorAttribute, isNull); - }); - - test('build returns a ColoredBox widget', () { - const backgroundColorAttribute = - BackgroundColorAttribute(ColorDto(Colors.red)); - final coloredBox = - backgroundColorAttribute.build(EmptyMixData, Container()); - expect(coloredBox, isA()); - expect(coloredBox.color, Colors.red); - }); - }); -} diff --git a/test/src/attributes/shadow/shadow_dto_test.dart b/test/src/attributes/shadow/shadow_dto_test.dart index db47743db..10e52f80b 100644 --- a/test/src/attributes/shadow/shadow_dto_test.dart +++ b/test/src/attributes/shadow/shadow_dto_test.dart @@ -6,78 +6,167 @@ import 'package:mix/src/attributes/shadow/shadow_dto.dart'; import '../../../helpers/testing_utils.dart'; void main() { - group('ShadowDto and BoxShadowDto', () { - test('ShadowDto correctly resolves attributes', () { + // ShadowDto + group('ShadowDto', () { + test('Constructor assigns correct properties', () { const shadowDto = ShadowDto( - color: ColorDto(Colors.green), - offset: Offset(1, 1), - blurRadius: 2.0, + blurRadius: 10.0, + color: ColorDto(Colors.blue), + offset: Offset(10, 10), + ); + + expect(shadowDto.blurRadius, 10.0); + expect(shadowDto.color?.resolve(EmptyMixData), Colors.blue); + expect(shadowDto.offset, const Offset(10, 10)); + }); + + test('from() creates correct instance', () { + const shadow = Shadow( + blurRadius: 10.0, + color: Colors.blue, + offset: Offset(10, 10), + ); + + final shadowDto = ShadowDto.from(shadow); + + expect(shadowDto.blurRadius, 10.0); + expect(shadowDto.color?.resolve(EmptyMixData), Colors.blue); + expect(shadowDto.offset, const Offset(10, 10)); + }); + + test('maybeFrom() creates correct instance', () { + const shadow = Shadow( + blurRadius: 10.0, + color: Colors.blue, + offset: Offset(10, 10), ); - final resultShadow = shadowDto.resolve(EmptyMixData); + final shadowDto = ShadowDto.maybeFrom(shadow); - expect(resultShadow.color, Colors.green); - expect(resultShadow.offset, const Offset(1, 1)); - expect(resultShadow.blurRadius, 2.0); + expect(shadowDto?.blurRadius, 10.0); + expect(shadowDto?.color?.resolve(EmptyMixData), Colors.blue); + expect(shadowDto?.offset, const Offset(10, 10)); }); - test('ShadowDto correctly merges attributes', () { - const shadowDto1 = ShadowDto( - color: ColorDto(Colors.green), - offset: Offset(1, 1), - blurRadius: 2.0, + test('resolve() returns correct instance', () { + const shadowDto = ShadowDto( + blurRadius: 10.0, + color: ColorDto(Colors.blue), + offset: Offset(10, 10), ); - const shadowDto2 = ShadowDto( + final shadow = shadowDto.resolve(EmptyMixData); + + expect(shadow.blurRadius, 10.0); + expect(shadow.color, Colors.blue); + expect(shadow.offset, const Offset(10, 10)); + }); + + test('merge() returns correct instance', () { + const shadowDto = ShadowDto( + blurRadius: 10.0, color: ColorDto(Colors.blue), - offset: Offset(2, 2), - blurRadius: 4.0, + offset: Offset(10, 10), ); - final resultShadow = shadowDto1.merge(shadowDto2); + final mergedShadowDto = shadowDto.merge( + const ShadowDto( + blurRadius: 20.0, + color: ColorDto(Colors.red), + offset: Offset(20, 20), + ), + ); - expect(resultShadow.color?.value, Colors.blue); - expect(resultShadow.offset, const Offset(2, 2)); - expect(resultShadow.blurRadius, 4.0); + expect(mergedShadowDto.blurRadius, 20.0); + expect(mergedShadowDto.color?.resolve(EmptyMixData), Colors.red); + expect(mergedShadowDto.offset, const Offset(20, 20)); }); + }); - test('BoxShadowDto correctly resolves attributes', () { + group('BoxShadowDto', () { + test('Constructor assigns correct properties', () { const boxShadowDto = BoxShadowDto( - color: ColorDto(Colors.green), - offset: Offset(1, 1), - blurRadius: 2.0, - spreadRadius: 3.0, + blurRadius: 10.0, + color: ColorDto(Colors.blue), + offset: Offset(10, 10), + spreadRadius: 5.0, ); - final resultBoxShadow = boxShadowDto.resolve(EmptyMixData); + expect(boxShadowDto.blurRadius, 10.0); + expect(boxShadowDto.color?.resolve(EmptyMixData), Colors.blue); + expect(boxShadowDto.offset, const Offset(10, 10)); + expect(boxShadowDto.spreadRadius, 5.0); + }); + + test('from() creates correct instance', () { + const boxShadow = BoxShadow( + blurRadius: 10.0, + color: Colors.blue, + offset: Offset(10, 10), + spreadRadius: 5.0, + ); + + final boxShadowDto = BoxShadowDto.from(boxShadow); - expect(resultBoxShadow.color, Colors.green, reason: 'color'); - expect(resultBoxShadow.offset, const Offset(1, 1), reason: 'offset'); - expect(resultBoxShadow.blurRadius, 2.0, reason: 'blurRadius'); - expect(resultBoxShadow.spreadRadius, 3.0, reason: 'spreadRadius'); + expect(boxShadowDto.blurRadius, 10.0); + expect(boxShadowDto.color?.resolve(EmptyMixData), Colors.blue); + expect(boxShadowDto.offset, const Offset(10, 10)); + expect(boxShadowDto.spreadRadius, 5.0); }); - test('BoxShadowDto correctly merges attributes', () { - const boxShadowDto1 = BoxShadowDto( - color: ColorDto(Colors.green), - offset: Offset(1, 1), - blurRadius: 2.0, - spreadRadius: 3.0, + test('maybeFrom() creates correct instance', () { + const boxShadow = BoxShadow( + blurRadius: 10.0, + color: Colors.blue, + offset: Offset(10, 10), + spreadRadius: 5.0, ); - const boxShadowDto2 = BoxShadowDto( + final boxShadowDto = BoxShadowDto.maybeFrom(boxShadow); + + expect(boxShadowDto?.blurRadius, 10.0); + expect(boxShadowDto?.color?.resolve(EmptyMixData), Colors.blue); + expect(boxShadowDto?.offset, const Offset(10, 10)); + expect(boxShadowDto?.spreadRadius, 5.0); + }); + + test('resolve() returns correct instance', () { + const boxShadowDto = BoxShadowDto( + blurRadius: 10.0, color: ColorDto(Colors.blue), - offset: Offset(2, 2), - blurRadius: 4.0, + offset: Offset(10, 10), spreadRadius: 5.0, ); - final resultBoxShadow = boxShadowDto1.merge(boxShadowDto2); + final boxShadow = boxShadowDto.resolve(EmptyMixData); + + expect(boxShadow.blurRadius, 10.0); + expect(boxShadow.color, Colors.blue); + expect(boxShadow.offset, const Offset(10, 10)); + expect(boxShadow.spreadRadius, 5.0); + }); + + test('merge() returns correct instance', () { + const boxShadowDto = BoxShadowDto( + blurRadius: 10.0, + color: ColorDto(Colors.blue), + offset: Offset(10, 10), + spreadRadius: 5.0, + ); + + final mergedBoxShadowDto = boxShadowDto.merge( + const BoxShadowDto( + blurRadius: 20.0, + color: ColorDto(Colors.red), + offset: Offset(20, 20), + spreadRadius: 10.0, + ), + ); - expect(resultBoxShadow.color?.value, Colors.blue); - expect(resultBoxShadow.offset, const Offset(2, 2)); - expect(resultBoxShadow.blurRadius, 4.0); - expect(resultBoxShadow.spreadRadius, 5.0); + expect(mergedBoxShadowDto.blurRadius, 20.0); + expect(mergedBoxShadowDto.color?.resolve(EmptyMixData), Colors.red); + expect(mergedBoxShadowDto.offset, const Offset(20, 20)); + expect(mergedBoxShadowDto.spreadRadius, 10.0); }); }); } diff --git a/test/src/attributes/shadow/shadow_util_test.dart b/test/src/attributes/shadow/shadow_util_test.dart new file mode 100644 index 000000000..503f3a05b --- /dev/null +++ b/test/src/attributes/shadow/shadow_util_test.dart @@ -0,0 +1,85 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:mix/mix.dart'; + +import '../../../helpers/testing_utils.dart'; + +void main() { + // ShadowUtility + group('ShadowUtility', () { + const shadowUtility = ShadowUtility(UtilityTestAttribute.new); + + test('call() returns correct instance', () { + final shadow = shadowUtility( + blurRadius: 10.0, + color: Colors.blue, + offset: const Offset(10, 10), + ); + + expect(shadow.value.blurRadius, 10.0); + expect(shadow.value.color, const ColorDto(Colors.blue)); + expect(shadow.value.offset, const Offset(10, 10)); + }); + + // color() + test('color() returns correct instance', () { + final shadow = shadowUtility.color(Colors.blue); + + expect(shadow.value.color, const ColorDto(Colors.blue)); + }); + + // offset() + test('offset() returns correct instance', () { + final shadow = shadowUtility.offset(10, 10); + + expect(shadow.value.offset, const Offset(10, 10)); + }); + }); + + // BoxShadowUtility + group('BoxShadowUtility', () { + const boxShadowUtility = BoxShadowUtility(UtilityTestAttribute.new); + + test('call() returns correct instance', () { + final boxShadow = boxShadowUtility( + blurRadius: 10.0, + color: Colors.blue, + offset: const Offset(10, 10), + spreadRadius: 10.0, + ); + + expect(boxShadow.value.blurRadius, 10.0); + expect(boxShadow.value.color, const ColorDto(Colors.blue)); + expect(boxShadow.value.offset, const Offset(10, 10)); + expect(boxShadow.value.spreadRadius, 10.0); + }); + + // color() + test('color() returns correct instance', () { + final boxShadow = boxShadowUtility.color(Colors.blue); + + expect(boxShadow.value.color, const ColorDto(Colors.blue)); + }); + + // offset() + test('offset() returns correct instance', () { + final boxShadow = boxShadowUtility.offset(10, 10); + + expect(boxShadow.value.offset, const Offset(10, 10)); + }); + + // spreadRadius() + test('spreadRadius() returns correct instance', () { + final boxShadow = boxShadowUtility.spreadRadius(10); + + expect(boxShadow.value.spreadRadius, 10); + }); + + // blurRadius() + test('blurRadius() returns correct instance', () { + final boxShadow = boxShadowUtility.blurRadius(10); + + expect(boxShadow.value.blurRadius, 10); + }); + }); +} diff --git a/test/src/attributes/spacing/spacing_attribute_test.dart b/test/src/attributes/spacing/spacing_attribute_test.dart deleted file mode 100644 index a28f7a537..000000000 --- a/test/src/attributes/spacing/spacing_attribute_test.dart +++ /dev/null @@ -1,235 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_test/flutter_test.dart'; -import 'package:mix/mix.dart'; -import 'package:mix/src/attributes/spacing/spacing_dto.dart'; - -import '../../../helpers/testing_utils.dart'; - -void main() { - group('PaddingAttribute', () { - // Constructor Tests - test('constructs correctly with all properties', () { - const padding = - PaddingAttribute(SpacingDto(top: 10, bottom: 5, left: 3, right: 7)); - - expect(padding.top, 10); - expect(padding.bottom, 5); - expect(padding.left, 3); - expect(padding.right, 7); - expect(padding.start, null); - expect(padding.end, null); - }); - - test('constructs correctly with no properties', () { - const padding = PaddingAttribute(SpacingDto()); - expect(padding.top, null); - expect(padding.bottom, null); - expect(padding.left, null); - expect(padding.right, null); - expect(padding.start, null); - expect(padding.end, null); - }); - - // Merge Function Tests - test('merge function merges correctly', () { - const padding1 = PaddingAttribute(SpacingDto(top: 10, bottom: 5)); - - const padding2 = PaddingAttribute(SpacingDto(left: 3, right: 7)); - - final merged = padding1.merge(padding2); - - expect(merged.top, 10); - expect(merged.bottom, 5); - expect(merged.left, 3); - expect(merged.right, 7); - }); - - test('merge returns itself if other is null', () { - const padding = PaddingAttribute(SpacingDto(top: 10, bottom: 5)); - final merged = padding.merge(null); - - expect(merged, equals(padding)); - }); - - // Equality Tests - test('equality holds when properties are the same', () { - const padding1 = PaddingAttribute(SpacingDto(top: 10, bottom: 5)); - - const padding2 = PaddingAttribute(SpacingDto(top: 10, bottom: 5)); - - expect(padding1, equals(padding2)); - }); - - test('equality fails when properties are different', () { - const padding1 = PaddingAttribute(SpacingDto(top: 10, bottom: 5)); - const padding2 = PaddingAttribute(SpacingDto(top: 5, bottom: 10)); - - expect(padding1, isNot(equals(padding2))); - }); - }); - - group('PaddingAttribute Directional', () { - // Constructor Tests - test('constructs correctly with all properties', () { - const padding = - PaddingAttribute(SpacingDto(top: 10, bottom: 5, start: 3, end: 7)); - - expect(padding.top, 10); - expect(padding.bottom, 5); - expect(padding.start, 3); - expect(padding.end, 7); - }); - test('constructs correctly with no properties', () { - const padding = PaddingAttribute(SpacingDto()); - expect(padding.top, isNull); - expect(padding.bottom, isNull); - expect(padding.start, isNull); - expect(padding.end, isNull); - }); - - // Merge Function Tests - test('merge function merges correctly', () { - const padding1 = PaddingAttribute(SpacingDto(top: 10, bottom: 5)); - - const padding2 = PaddingAttribute(SpacingDto(start: 3, end: 7)); - - final merged = padding1.merge(padding2); - - expect(merged.top, 10); - expect(merged.bottom, 5); - expect(merged.end, 7); - expect(merged.start, 3); - }); - - test('merge returns itself if other is null', () { - const padding = PaddingAttribute(SpacingDto(top: 10, bottom: 5)); - final merged = padding.merge(null); - - expect(merged, equals(padding)); - }); - - // Resolve Function Tests - // Assuming a mock for MixData and its resolver - test('resolve function returns correct EdgeInsetsDirectional', () { - const padding = - PaddingAttribute(SpacingDto(top: 10, bottom: 5, start: 3, end: 7)); - - final resolvedValue = padding.resolve(EmptyMixData); - - expect( - resolvedValue, - equals( - const EdgeInsetsDirectional.only( - top: 10, bottom: 5, start: 3, end: 7), - ), - ); - }); - - // Equality Tests - test('equality holds when properties are the same', () { - const padding1 = PaddingAttribute(SpacingDto(top: 10, bottom: 5)); - const padding2 = PaddingAttribute(SpacingDto(top: 10, bottom: 5)); - - expect(padding1, equals(padding2)); - }); - - test('equality fails when properties are different', () { - const padding1 = PaddingAttribute(SpacingDto(top: 10, bottom: 5)); - - const padding2 = PaddingAttribute(SpacingDto(top: 5, bottom: 10)); - - expect(padding1, isNot(equals(padding2))); - }); - }); - - // MarginAttribute - group('MarginAttribute', () { - // Constructor Tests - test('constructs correctly with all properties', () { - const margin = - MarginAttribute(SpacingDto(top: 10, bottom: 5, left: 3, right: 7)); - - expect(margin.top, 10); - expect(margin.bottom, 5); - expect(margin.left, 3); - expect(margin.right, 7); - expect(margin.start, null); - expect(margin.end, null); - }); - - test('constructs correctly with no properties', () { - const margin = MarginAttribute(SpacingDto()); - expect(margin.top, null); - expect(margin.bottom, null); - expect(margin.left, null); - expect(margin.right, null); - expect(margin.start, null); - expect(margin.end, null); - }); - - // Merge Function Tests - test('merge function merges correctly', () { - const margin1 = MarginAttribute(SpacingDto(top: 10, bottom: 5)); - - const margin2 = MarginAttribute(SpacingDto(left: 3, right: 7)); - - final merged = margin1.merge(margin2); - - expect(merged.top, 10); - expect(merged.bottom, 5); - expect(merged.left, 3); - expect(merged.right, 7); - }); - - test('merge returns itself if other is null', () { - const margin = MarginAttribute(SpacingDto(top: 10, bottom: 5)); - final merged = margin.merge(null); - - expect(merged, equals(margin)); - }); - - // Resolve Function Tests - // Assuming a mock for MixData and its resolver - test('resolve function returns correct EdgeInsets', () { - const margin = - MarginAttribute(SpacingDto(top: 10, bottom: 5, left: 3, right: 7)); - - final resolvedValue = margin.resolve(EmptyMixData); - - expect( - resolvedValue, - equals( - const EdgeInsets.only(top: 10, bottom: 5, left: 3, right: 7), - ), - ); - }); - - // Equality Tests - test('equality holds when properties are the same', () { - const margin1 = MarginAttribute(SpacingDto(top: 10, bottom: 5)); - - const margin2 = MarginAttribute(SpacingDto(top: 10, bottom: 5)); - - expect(margin1, equals(margin2)); - }); - - test(' equality fails when properties are different', () { - const margin1 = MarginAttribute(SpacingDto(top: 10, bottom: 5)); - - const margin2 = MarginAttribute(SpacingDto(top: 5, bottom: 10)); - - expect(margin1, isNot(equals(margin2))); - }); - - // Directional MarginAttribute - test('constructs correctly with all properties', () { - const margin = - MarginAttribute(SpacingDto(top: 10, bottom: 5, start: 3, end: 7)); - - expect(margin.top, 10); - expect(margin.bottom, 5); - expect(margin.start, 3); - expect(margin.end, 7); - }); - }); -} diff --git a/test/src/attributes/spacing/spacing_dto_test.dart b/test/src/attributes/spacing/spacing_dto_test.dart index c4a63efb6..b030943b6 100644 --- a/test/src/attributes/spacing/spacing_dto_test.dart +++ b/test/src/attributes/spacing/spacing_dto_test.dart @@ -7,7 +7,7 @@ import '../../../helpers/testing_utils.dart'; void main() { group('SpacingDto', () { test('resolves to EdgeInsets.only with correct values', () { - const spacingDto = SpacingDto( + const spacingDto = SpacingDto.only( top: 10, bottom: 20, left: 30, @@ -26,13 +26,13 @@ void main() { }); test('merges correctly with another SpacingDto', () { - const spacingDto1 = SpacingDto( + const spacingDto1 = SpacingDto.only( top: 10, bottom: 20, left: 30, right: 40, ); - const spacingDto2 = SpacingDto( + const spacingDto2 = SpacingDto.only( top: 5, bottom: 15, left: 25, @@ -41,7 +41,7 @@ void main() { final mergedSpacingDto = spacingDto1.merge(spacingDto2); expect( mergedSpacingDto, - const SpacingDto( + const SpacingDto.only( top: 5, bottom: 15, left: 25, diff --git a/test/src/attributes/spacing/spacing_util_test.dart b/test/src/attributes/spacing/spacing_util_test.dart index e74723344..3e7576c58 100644 --- a/test/src/attributes/spacing/spacing_util_test.dart +++ b/test/src/attributes/spacing/spacing_util_test.dart @@ -1,610 +1,312 @@ import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:mix/mix.dart'; -import 'package:mix/src/attributes/spacing/spacing_dto.dart'; + +import '../../../helpers/testing_utils.dart'; void main() { - group('Padding Utils', () { + group('Spacing Utils', () { + const spacingUtils = SpacingUtility(UtilityTestAttribute.new); test('padding()', () { expect( - padding(10), - const PaddingAttribute( - SpacingDto(top: 10, bottom: 10, left: 10, right: 10)), + spacingUtils(10).value, + const SpacingDto.only(top: 10, bottom: 10, left: 10, right: 10), ); expect( - padding(10, 20), - const PaddingAttribute( - SpacingDto(top: 10, bottom: 10, left: 20, right: 20)), + spacingUtils(10, 20).value, + const SpacingDto.only(top: 10, bottom: 10, left: 20, right: 20), ); expect( - padding(10, 20, 30), - const PaddingAttribute( - SpacingDto(top: 10, bottom: 30, left: 20, right: 20)), + spacingUtils(10, 20, 30).value, + const SpacingDto.only(top: 10, bottom: 30, left: 20, right: 20), ); expect( - padding(10, 20, 30, 40), - const PaddingAttribute( - SpacingDto(top: 10, bottom: 30, left: 40, right: 20)), + spacingUtils(10, 20, 30, 40).value, + const SpacingDto.only(top: 10, bottom: 30, left: 40, right: 20), ); }); - test('padding.directional()', () { + test('spacingUtils.directional()', () { expect( - padding.directional(10), - const PaddingAttribute( - SpacingDto(start: 10, end: 10, top: 10, bottom: 10)), + spacingUtils.directional(10).value, + const SpacingDto.only(start: 10, end: 10, top: 10, bottom: 10), reason: '1', ); expect( - padding.directional(10, 20), - const PaddingAttribute( - SpacingDto(top: 10, bottom: 10, start: 20, end: 20)), + spacingUtils.directional(10, 20).value, + const SpacingDto.only(top: 10, bottom: 10, start: 20, end: 20), reason: '2', ); expect( - padding.directional(10, 20, 30), - const PaddingAttribute( - SpacingDto(top: 10, bottom: 30, start: 20, end: 20)), + spacingUtils.directional(10, 20, 30).value, + const SpacingDto.only(top: 10, bottom: 30, start: 20, end: 20), reason: '3', ); expect( - padding.directional(10, 20, 30, 40), - const PaddingAttribute( - SpacingDto(top: 10, end: 20, bottom: 30, start: 40)), + spacingUtils.directional(10, 20, 30, 40).value, + const SpacingDto.only(top: 10, end: 20, bottom: 30, start: 40), reason: '4', ); }); - test('padding.from', () { + test('spacingUtils.from', () { expect( - padding.as(const EdgeInsets.all(10)), - const PaddingAttribute( - SpacingDto(top: 10, bottom: 10, left: 10, right: 10)), + spacingUtils + .as( + const EdgeInsets.all(10), + ) + .value, + const SpacingDto.only(top: 10, bottom: 10, left: 10, right: 10), reason: '1', ); expect( - padding.as(const EdgeInsets.only(top: 10)), - const PaddingAttribute( - SpacingDto(top: 10, bottom: 0, left: 0, right: 0)), + spacingUtils + .as( + const EdgeInsets.only(top: 10), + ) + .value, + const SpacingDto.only(top: 10, bottom: 0, left: 0, right: 0), reason: '2', ); expect( - padding.as(const EdgeInsets.only(left: 10)), - const PaddingAttribute( - SpacingDto(left: 10, bottom: 0, top: 0, right: 0)), + spacingUtils + .as( + const EdgeInsets.only(left: 10), + ) + .value, + const SpacingDto.only(left: 10, bottom: 0, top: 0, right: 0), reason: '3', ); expect( - padding.as(const EdgeInsets.only(right: 10)), - const PaddingAttribute( - SpacingDto(right: 10, bottom: 0, top: 0, left: 0)), + spacingUtils + .as( + const EdgeInsets.only(right: 10), + ) + .value, + const SpacingDto.only(right: 10, bottom: 0, top: 0, left: 0), reason: '4', ); expect( - padding.as(const EdgeInsets.only(bottom: 10)), - const PaddingAttribute( - SpacingDto(bottom: 10, top: 0, left: 0, right: 0)), + spacingUtils + .as( + const EdgeInsets.only(bottom: 10), + ) + .value, + const SpacingDto.only(bottom: 10, top: 0, left: 0, right: 0), reason: '5', ); expect( - padding.as(const EdgeInsets.symmetric(horizontal: 10)), - const PaddingAttribute( - SpacingDto(left: 10, right: 10, top: 0, bottom: 0)), + spacingUtils + .as( + const EdgeInsets.symmetric(horizontal: 10), + ) + .value, + const SpacingDto.only(left: 10, right: 10, top: 0, bottom: 0), reason: '6', ); expect( - padding.as(const EdgeInsets.symmetric(vertical: 10)), - const PaddingAttribute( - SpacingDto(top: 10, bottom: 10, left: 0, right: 0)), + spacingUtils + .as( + const EdgeInsets.symmetric(vertical: 10), + ) + .value, + const SpacingDto.only(top: 10, bottom: 10, left: 0, right: 0), reason: '7', ); expect( - padding.directional.as(const EdgeInsetsDirectional.only(start: 10)), - const PaddingAttribute( - SpacingDto(start: 10, end: 0, top: 0, bottom: 0)), + spacingUtils.directional + .as( + const EdgeInsetsDirectional.only(start: 10), + ) + .value, + const SpacingDto.only(start: 10, end: 0, top: 0, bottom: 0), reason: '8', ); expect( - padding.directional.as(const EdgeInsetsDirectional.only(end: 10)), - const PaddingAttribute( - SpacingDto(end: 10, start: 0, top: 0, bottom: 0)), + spacingUtils.directional + .as( + const EdgeInsetsDirectional.only(end: 10), + ) + .value, + const SpacingDto.only(end: 10, start: 0, top: 0, bottom: 0), reason: '9', ); expect( - padding.directional.as(const EdgeInsetsDirectional.only(top: 10)), - const PaddingAttribute( - SpacingDto(top: 10, bottom: 0, start: 0, end: 0)), + spacingUtils.directional + .as( + const EdgeInsetsDirectional.only(top: 10), + ) + .value, + const SpacingDto.only(top: 10, bottom: 0, start: 0, end: 0), reason: '10', ); expect( - padding.directional.as(const EdgeInsetsDirectional.only(bottom: 10)), - const PaddingAttribute( - SpacingDto(bottom: 10, top: 0, start: 0, end: 0)), + spacingUtils.directional + .as( + const EdgeInsetsDirectional.only(bottom: 10), + ) + .value, + const SpacingDto.only(bottom: 10, top: 0, start: 0, end: 0), reason: '11', ); expect( - padding.directional - .as(const EdgeInsetsDirectional.only(start: 10, end: 20)), - const PaddingAttribute( - SpacingDto(start: 10, end: 20, top: 0, bottom: 0)), + spacingUtils.directional + .as( + const EdgeInsetsDirectional.only(start: 10, end: 20), + ) + .value, + const SpacingDto.only(start: 10, end: 20, top: 0, bottom: 0), reason: '12', ); expect( - padding.directional - .as(const EdgeInsetsDirectional.only(start: 10, end: 20, top: 30)), - const PaddingAttribute( - SpacingDto(start: 10, end: 20, top: 30, bottom: 0)), + spacingUtils.directional + .as( + const EdgeInsetsDirectional.only(start: 10, end: 20, top: 30), + ) + .value, + const SpacingDto.only(start: 10, end: 20, top: 30, bottom: 0), reason: '13', ); expect( - padding.directional.as( - const EdgeInsetsDirectional.only( - start: 10, - end: 20, - top: 30, - bottom: 40, - ), - ), - const PaddingAttribute( - SpacingDto(start: 10, end: 20, top: 30, bottom: 40)), + spacingUtils.directional + .as( + const EdgeInsetsDirectional.only( + start: 10, + end: 20, + top: 30, + bottom: 40, + ), + ) + .value, + const SpacingDto.only(start: 10, end: 20, top: 30, bottom: 40), reason: '14', ); }); - // padding.directionalFrom - - test('padding.only', () { - expect( - padding.only(top: 10), - const PaddingAttribute(SpacingDto(top: 10)), - ); - - expect( - padding.only(left: 10), - const PaddingAttribute(SpacingDto(left: 10)), - ); - - expect( - padding.only(right: 10), - const PaddingAttribute(SpacingDto(right: 10)), - ); - - expect( - padding.only(bottom: 10), - const PaddingAttribute(SpacingDto(bottom: 10)), - ); - }); - - test('padding.top', () { - expect( - padding.top(10), - const PaddingAttribute(SpacingDto(top: 10)), - ); - }); - - test('padding.bottom', () { - expect( - padding.bottom(10), - const PaddingAttribute(SpacingDto(bottom: 10)), - ); - }); - - test('padding.left', () { - expect( - padding.left(10), - const PaddingAttribute(SpacingDto(left: 10)), - ); - }); - - test('padding.right', () { - expect( - padding.right(10), - const PaddingAttribute(SpacingDto(right: 10)), - ); - }); - - test('padding.directional.start', () { - expect( - padding.directional.start(10), - const PaddingAttribute(SpacingDto(start: 10)), - ); - }); - - test('padding.directional.end', () { - expect( - padding.directional.end(10), - const PaddingAttribute(SpacingDto(end: 10)), - ); - }); - - test('padding.horizontal', () { - expect( - padding.horizontal(10), - const PaddingAttribute(SpacingDto(left: 10, right: 10)), - ); - }); - - test('padding.vertical', () { - expect( - padding.vertical(10), - const PaddingAttribute(SpacingDto(top: 10, bottom: 10)), - ); - }); - - test('padding.all', () { - expect( - padding.all(10), - const PaddingAttribute( - SpacingDto(top: 10, bottom: 10, left: 10, right: 10)), - ); - }); - - test('padding.directional.only', () { - expect( - padding.directional.only(start: 10), - const PaddingAttribute(SpacingDto(start: 10)), - ); - - expect( - padding.directional.only(end: 10), - const PaddingAttribute(SpacingDto(end: 10)), - ); - - expect( - padding.directional.only(start: 10, end: 20), - const PaddingAttribute(SpacingDto(start: 10, end: 20)), - ); - - expect( - padding.directional.only(start: 10, end: 20, top: 30), - const PaddingAttribute(SpacingDto(start: 10, end: 20, top: 30)), - ); - - expect( - padding.directional.only(start: 10, end: 20, top: 30, bottom: 40), - const PaddingAttribute( - SpacingDto(start: 10, end: 20, top: 30, bottom: 40)), - ); - }); - }); - - group('Margin Utils', () { - test('margin()', () { - expect( - margin(10), - const MarginAttribute( - SpacingDto(top: 10, bottom: 10, left: 10, right: 10), - ), - ); - expect( - margin(10, 20), - const MarginAttribute( - SpacingDto(top: 10, bottom: 10, left: 20, right: 20), - ), - ); - expect( - margin(10, 20, 30), - const MarginAttribute( - SpacingDto(top: 10, bottom: 30, left: 20, right: 20), - ), - ); - expect( - margin(10, 20, 30, 40), - const MarginAttribute( - SpacingDto(top: 10, bottom: 30, left: 40, right: 20), - ), - ); - }); - - // margin.directional() - test('margin.directional()', () { - expect( - margin.directional(10), - const MarginAttribute( - SpacingDto( - start: 10, - end: 10, - top: 10, - bottom: 10, - ), - ), - reason: '1', - ); - expect( - margin.directional(10, 20), - const MarginAttribute( - SpacingDto( - top: 10, - bottom: 10, - start: 20, - end: 20, - ), - ), - reason: '2', - ); - expect( - margin.directional(10, 20, 30), - const MarginAttribute( - SpacingDto( - top: 10, - bottom: 30, - start: 20, - end: 20, - ), - ), - reason: '3', - ); - expect( - margin.directional(10, 20, 30, 40), - const MarginAttribute( - SpacingDto( - top: 10, - end: 20, - bottom: 30, - start: 40, - ), - ), - reason: '4', - ); - }); - - test('margin.only', () { + test('spacingUtils.only', () { expect( - margin.only(top: 10), - const MarginAttribute( - SpacingDto(top: 10), - ), + spacingUtils.only(top: 10).value, + const SpacingDto.only(top: 10), ); expect( - margin.only(left: 10), - const MarginAttribute( - SpacingDto(left: 10), - ), + spacingUtils.only(left: 10).value, + const SpacingDto.only(left: 10), ); expect( - margin.only(right: 10), - const MarginAttribute( - SpacingDto(right: 10), - ), + spacingUtils.only(right: 10).value, + const SpacingDto.only(right: 10), ); expect( - margin.only(bottom: 10), - const MarginAttribute( - SpacingDto(bottom: 10), - ), + spacingUtils.only(bottom: 10).value, + const SpacingDto.only(bottom: 10), ); }); - test('margin.top', () { + test('spacingUtils.top', () { expect( - margin.top(10), - const MarginAttribute( - SpacingDto(top: 10), - ), + spacingUtils.top(10).value, + const SpacingDto.only(top: 10), ); }); - test('margin.bottom', () { + test('spacingUtils.bottom', () { expect( - margin.bottom(10), - const MarginAttribute( - SpacingDto(bottom: 10), - ), + spacingUtils.bottom(10).value, + const SpacingDto.only(bottom: 10), ); }); - test('margin.left', () { + test('spacingUtils.left', () { expect( - margin.left(10), - const MarginAttribute( - SpacingDto(left: 10), - ), + spacingUtils.left(10).value, + const SpacingDto.only(left: 10), ); }); - test('margin.right', () { + test('spacingUtils.right', () { expect( - margin.right(10), - const MarginAttribute( - SpacingDto(right: 10), - ), + spacingUtils.right(10).value, + const SpacingDto.only(right: 10), ); }); - test('margin.directional.start', () { + test('spacingUtils.directional.start', () { expect( - margin.directional.start(10), - const MarginAttribute( - SpacingDto(start: 10), - ), + spacingUtils.directional.start(10).value, + const SpacingDto.only(start: 10), ); }); - test('margin.directional.end', () { + test('spacingUtils.directional.end', () { expect( - margin.directional.end(10), - const MarginAttribute( - SpacingDto(end: 10), - ), + spacingUtils.directional.end(10).value, + const SpacingDto.only(end: 10), ); }); - test('margin.horizontal', () { + test('spacingUtils.horizontal', () { expect( - margin.horizontal(10), - const MarginAttribute( - SpacingDto(left: 10, right: 10), - ), + spacingUtils.horizontal(10).value, + const SpacingDto.only(left: 10, right: 10), ); }); - test('margin.vertical', () { + test('spacingUtils.vertical', () { expect( - margin.vertical(10), - const MarginAttribute(SpacingDto(top: 10, bottom: 10)), + spacingUtils.vertical(10).value, + const SpacingDto.only(top: 10, bottom: 10), ); }); - test('margin.all', () { - expect( - margin.all(10), - const MarginAttribute( - SpacingDto(top: 10, bottom: 10, left: 10, right: 10), - ), - ); - }); - - test('margin.as', () { - expect( - margin.as(const EdgeInsets.all(10)), - const MarginAttribute( - SpacingDto(top: 10, bottom: 10, left: 10, right: 10), - ), - ); - - expect( - margin.as(const EdgeInsets.only(top: 10)), - const MarginAttribute( - SpacingDto(top: 10, bottom: 0, left: 0, right: 0), - ), - ); - - expect( - margin.as(const EdgeInsets.only(left: 10)), - const MarginAttribute( - SpacingDto(left: 10, bottom: 0, top: 0, right: 0), - ), - ); - - expect( - margin.as(const EdgeInsets.only(right: 10)), - const MarginAttribute( - SpacingDto(right: 10, bottom: 0, top: 0, left: 0), - ), - ); - - expect( - margin.as(const EdgeInsets.only(bottom: 10)), - const MarginAttribute( - SpacingDto(bottom: 10, top: 0, left: 0, right: 0), - ), - ); - - expect( - margin.as(const EdgeInsets.symmetric(horizontal: 10)), - const MarginAttribute( - SpacingDto(left: 10, right: 10, top: 0, bottom: 0), - ), - ); - - expect( - margin.as(const EdgeInsets.symmetric(vertical: 10)), - const MarginAttribute( - SpacingDto(top: 10, bottom: 10, left: 0, right: 0), - ), - ); - - expect( - margin.directional.as(const EdgeInsetsDirectional.only(start: 10)), - const MarginAttribute( - SpacingDto(start: 10, end: 0, top: 0, bottom: 0), - ), - ); - - expect( - margin.directional.as(const EdgeInsetsDirectional.only(end: 10)), - const MarginAttribute( - SpacingDto(end: 10, start: 0, top: 0, bottom: 0), - ), - ); - - expect( - margin.directional.as(const EdgeInsetsDirectional.only(top: 10)), - const MarginAttribute(SpacingDto(top: 10, bottom: 0, start: 0, end: 0)), - ); - - expect( - margin.directional.as(const EdgeInsetsDirectional.only(bottom: 10)), - const MarginAttribute( - SpacingDto(bottom: 10, top: 0, start: 0, end: 0), - ), - ); - - expect( - margin.directional - .as(const EdgeInsetsDirectional.only(start: 10, end: 20)), - const MarginAttribute( - SpacingDto(start: 10, end: 20, top: 0, bottom: 0), - ), - ); - - expect( - margin.directional - .as(const EdgeInsetsDirectional.only(start: 10, end: 20, top: 30)), - const MarginAttribute( - SpacingDto(start: 10, end: 20, top: 30, bottom: 0), - ), - ); - + test('spacingUtils.all', () { expect( - margin.directional.as(const EdgeInsetsDirectional.only( - start: 10, end: 20, top: 30, bottom: 40)), - const MarginAttribute( - SpacingDto(start: 10, end: 20, top: 30, bottom: 40), - ), + spacingUtils.all(10).value, + const SpacingDto.only(top: 10, bottom: 10, left: 10, right: 10), ); }); - test('margin.directional.only', () { + test('spacingUtils.directional.only', () { expect( - margin.directional.only(start: 10), - const MarginAttribute( - SpacingDto(start: 10), - ), + spacingUtils.directional.only(start: 10).value, + const SpacingDto.only(start: 10), ); expect( - margin.directional.only(end: 10), - const MarginAttribute( - SpacingDto(end: 10), - ), + spacingUtils.directional.only(end: 10).value, + const SpacingDto.only(end: 10), ); expect( - margin.directional.only(start: 10, end: 20), - const MarginAttribute( - SpacingDto(start: 10, end: 20), - ), + spacingUtils.directional.only(start: 10, end: 20).value, + const SpacingDto.only(start: 10, end: 20), ); expect( - margin.directional.only(start: 10, end: 20, top: 30), - const MarginAttribute( - SpacingDto(start: 10, end: 20, top: 30), - ), + spacingUtils.directional.only(start: 10, end: 20, top: 30).value, + const SpacingDto.only(start: 10, end: 20, top: 30), ); expect( - margin.directional.only(start: 10, end: 20, top: 30, bottom: 40), - const MarginAttribute( - SpacingDto(start: 10, end: 20, top: 30, bottom: 40), - ), + spacingUtils.directional + .only(start: 10, end: 20, top: 30, bottom: 40) + .value, + const SpacingDto.only(start: 10, end: 20, top: 30, bottom: 40), ); }); }); diff --git a/test/src/attributes/variant_attribute_test.dart b/test/src/attributes/variant_attribute_test.dart new file mode 100644 index 000000000..295544461 --- /dev/null +++ b/test/src/attributes/variant_attribute_test.dart @@ -0,0 +1,106 @@ +// @immutable +// class VariantAttribute extends Attribute +// with Mergeable> { +// final T variant; +// final StyleMix _style; + +// const VariantAttribute(this.variant, StyleMix style) : _style = style; + +// Key get mergeKey => ObjectKey(variant); + +// StyleMix get value => _style; + +// @override +// VariantAttribute merge(covariant VariantAttribute other) { +// if (other.variant != variant) throw throwArgumentError(other); + +// return VariantAttribute(variant, _style.merge(other._style)); +// } + +// @override +// get props => [variant, value]; +// } + +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:mix/mix.dart'; + +import '../../helpers/testing_utils.dart'; + +void main() { + // VariantAttribute + group('VariantAttribute', () { + const variant = Variant('custom_variant'); + final style = StyleMix(const MockIntScalarAttribute(8)); + test('Constructor assigns correct properties', () { + final variantAttribute = VariantAttribute(variant, style); + + expect(variantAttribute.variant, variant); + expect(variantAttribute.value, style); + }); + + // mergeKey + test('mergeKey returns correct instance', () { + final variantAttribute = VariantAttribute(variant, style); + + expect(variantAttribute.mergeKey, const ObjectKey(variant)); + }); + + // merge() + test('merge() returns correct instance', () { + final variantAttribute = VariantAttribute(variant, style); + + final otherStyle = StyleMix(const MockDoubleDecoratorAttribute(10)); + final otherAttribute = VariantAttribute(variant, otherStyle); + + final result = variantAttribute.merge(otherAttribute); + + expect(result, isA()); + expect(result.variant, variant); + expect(result.value, style.merge(otherStyle)); + }); + }); + + // ContextVariantAttribute + group('ContextVariantAttribute', () { + final variant = ContextVariant('custom_variant', when: (_) => true); + + final style = StyleMix(const MockIntScalarAttribute(8)); + test('Constructor assigns correct properties', () { + final variantAttribute = ContextVariantAttribute(variant, style); + + expect(variantAttribute.variant, variant); + expect(variantAttribute.value, style); + }); + + // mergeKey + test('mergeKey returns correct instance', () { + final variantAttribute = ContextVariantAttribute(variant, style); + + expect(variantAttribute.mergeKey, ObjectKey(variant)); + }); + + // merge() + test('merge() returns correct instance', () { + final variantAttribute = ContextVariantAttribute(variant, style); + + final otherStyle = StyleMix(const MockDoubleDecoratorAttribute(10)); + final otherAttribute = ContextVariantAttribute(variant, otherStyle); + + final result = variantAttribute.merge(otherAttribute); + + expect(result, isA()); + expect(result.variant, variant); + expect(result.value, style.merge(otherStyle)); + }); + + // when() + test('when() returns correct instance', () { + final variantAttribute = ContextVariantAttribute(variant, style); + + final result = variantAttribute.when(MockBuildContext()); + + expect(result, isTrue); + }); + }); +} diff --git a/test/src/core/extensions/values_ext_test.dart b/test/src/core/extensions/values_ext_test.dart index 87b0d5b81..d62117012 100644 --- a/test/src/core/extensions/values_ext_test.dart +++ b/test/src/core/extensions/values_ext_test.dart @@ -1,10 +1,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:mix/mix.dart'; -import 'package:mix/src/attributes/constraints/constraints_dto.dart'; -import 'package:mix/src/attributes/decoration/decoration_dto.dart'; -import 'package:mix/src/attributes/strut_style/strut_style_dto.dart'; -import 'package:mix/src/attributes/text_style/text_style_dto.dart'; import '../../../helpers/testing_utils.dart'; @@ -34,16 +30,6 @@ void main() { expect(attribute.resolve(EmptyMixData), value); }); - test('AlignmentGeometry', () { - const alignment = Alignment.topCenter; - - const attribute = AlignmentGeometryAttribute(alignment); - - expect(alignment.toAttribute(), attribute); - - expect(attribute.value, alignment); - }); - test('ShapeDecoration', () { final value = ShapeDecoration( shape: Border.all(), @@ -52,17 +38,9 @@ void main() { ); final dto = ShapeDecorationDto.from(value); - final attribute = DecorationAttribute(dto); - expect(value.toAttribute(), isA()); - expect(value.toAttribute(), attribute); expect(value.toDto(), isA()); expect(value.toDto(), dto); - - expect(attribute.value, dto); - - // Resolves correctly - expect(attribute.resolve(EmptyMixData), value); }); test('BoxConstraints toAttribute', () { @@ -74,25 +52,9 @@ void main() { ); final dto = BoxConstraintsDto.from(value); - final attribute = BoxConstraintsAttribute(dto); - expect(value.toAttribute(), isA()); - expect(value.toAttribute(), attribute); expect(value.toDto(), isA()); expect(value.toDto(), dto); - - expect(attribute.value, dto); - - // Resolves correctly - expect(attribute.resolve(EmptyMixData), value); - }); - - test('Axis toAttribute', () { - const value = Axis.horizontal; - - const attribute = AxisAttribute(value); - - expect(attribute.value, Axis.horizontal); }); test('BoxDecoration toAttribute', () { @@ -105,17 +67,9 @@ void main() { ); final dto = BoxDecorationDto.from(value); - final attribute = DecorationAttribute(dto); - expect(value.toAttribute(), isA()); - expect(value.toAttribute(), attribute); expect(value.toDto(), isA()); expect(value.toDto(), dto); - - expect(attribute.value, dto); - - // Resolves correctly - expect(attribute.resolve(EmptyMixData), value); }); test('BorderRadiusGeometry', () { @@ -135,12 +89,6 @@ void main() { expect(attribute.resolve(EmptyMixData), value); }); - test('Matrix4 toAttribute', () { - final matrix4 = Matrix4.identity(); - final attribute = matrix4.toAttribute(); - expect(attribute.value, Matrix4.identity()); - }); - test('BorderSide', () { const value = BorderSide( color: Colors.blue, @@ -231,7 +179,7 @@ void main() { fontWeight: FontWeight.bold, ); - final dto = TextStyleDto.from(value); + final dto = TextStyleDto.as(value); final attribute = TextStyleAttribute(dto); expect(value.toAttribute(), isA()); diff --git a/test/src/factory/style_mix_ext_test.dart b/test/src/factory/style_mix_ext_test.dart index d1528ed50..973a0c36f 100644 --- a/test/src/factory/style_mix_ext_test.dart +++ b/test/src/factory/style_mix_ext_test.dart @@ -9,7 +9,7 @@ void main() { testWidgets('StyleMix.container matches StyledContainer(style:StyleMix)', (tester) async { final style = StyleMix( - box.decoration( + box.decoration.box( border: Border.all( color: Colors.red, ), @@ -28,7 +28,7 @@ void main() { ), StyledContainer( key: keyThree, - style: StyleMix.empty, + style: const StyleMix.empty(), child: const SizedBox(), ), ], @@ -48,7 +48,7 @@ void main() { testWidgets('StyleMix.box matches StyledContainer(style:StyleMix)', (tester) async { final style = StyleMix( - box.decoration( + box.decoration.box( border: Border.all(color: Colors.red), ), ); @@ -65,7 +65,7 @@ void main() { ), StyledContainer( key: keyThree, - style: StyleMix.empty, + style: const StyleMix.empty(), child: const SizedBox(), ), ], @@ -84,7 +84,7 @@ void main() { testWidgets('StyleMix.hbox matches HBox(style:StyleMix)', (tester) async { final style = - StyleMix(box.decoration(border: Border.all(color: Colors.red))); + StyleMix(box.decoration.box(border: Border.all(color: Colors.red))); await tester.pumpWidget( MaterialApp( @@ -98,7 +98,7 @@ void main() { ), HBox( key: keyThree, - style: StyleMix.empty, + style: const StyleMix.empty(), children: const [SizedBox()], ), ], @@ -116,8 +116,11 @@ void main() { }); testWidgets('StyleMix.row matches StyledRow(style:StyleMix)', (tester) async { - final style = - StyleMix(box.decoration(border: Border.all(color: Colors.red))); + final style = StyleMix( + box.decoration.box( + border: Border.all(color: Colors.red), + ), + ); await tester.pumpWidget( MaterialApp( @@ -131,7 +134,7 @@ void main() { ), StyledRow( key: keyThree, - style: StyleMix.empty, + style: const StyleMix.empty(), children: const [SizedBox()], ), ], @@ -150,7 +153,7 @@ void main() { testWidgets('StyleMix.text matches StyledText(style:StyleMix)', (tester) async { - final style = StyleMix(textStyle(color: Colors.red)); + final style = StyleMix(text.style(color: Colors.red)); await tester.pumpWidget( MaterialApp( @@ -165,7 +168,7 @@ void main() { StyledText( 'text', key: keyThree, - style: StyleMix.empty, + style: const StyleMix.empty(), ), ], ), @@ -183,7 +186,7 @@ void main() { testWidgets('StyleMix.vbox matches VBox(style:StyleMix)', (tester) async { final style = - StyleMix(box.decoration(border: Border.all(color: Colors.red))); + StyleMix(box.decoration.box(border: Border.all(color: Colors.red))); await tester.pumpWidget( MaterialApp( @@ -197,7 +200,7 @@ void main() { ), VBox( key: keyThree, - style: StyleMix.empty, + style: const StyleMix.empty(), children: const [SizedBox()], ), ], @@ -216,8 +219,13 @@ void main() { testWidgets('StyleMix.column matches StyledColumn(style:StyleMix)', (tester) async { - final style = - StyleMix(box.decoration(border: Border.all(color: Colors.red))); + final style = StyleMix( + container.decoration.box( + border: Border.all( + color: Colors.red, + ), + ), + ); await tester.pumpWidget( MaterialApp( @@ -231,7 +239,7 @@ void main() { ), StyledColumn( key: keyThree, - style: StyleMix.empty, + style: const StyleMix.empty(), children: const [SizedBox()], ), ], @@ -265,7 +273,7 @@ void main() { StyledIcon( Icons.ac_unit, key: keyThree, - style: StyleMix.empty, + style: const StyleMix.empty(), ), ], ), diff --git a/test/src/recipes/container/container_attribute_test.dart b/test/src/recipes/container/container_attribute_test.dart new file mode 100644 index 000000000..fdad7a114 --- /dev/null +++ b/test/src/recipes/container/container_attribute_test.dart @@ -0,0 +1,255 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:mix/mix.dart'; + +import '../../../helpers/testing_utils.dart'; + +void main() { + group('ContainerSpecAttribute', () { + test('Constructor assigns correct properties', () { + final containerSpecAttribute = ContainerSpecAttribute( + alignment: Alignment.center, + clipBehavior: Clip.antiAlias, + constraints: const BoxConstraintsDto(maxHeight: 100), + decoration: const BoxDecorationDto(color: ColorDto(Colors.blue)), + height: 100, + margin: const SpacingDto.only( + bottom: 10, + left: 10, + right: 10, + top: 10, + ), + padding: + const SpacingDto.only(bottom: 20, left: 20, right: 20, top: 20), + transform: Matrix4.identity(), + width: 100, + ); + + expect(containerSpecAttribute.alignment, Alignment.center); + expect(containerSpecAttribute.clipBehavior, Clip.antiAlias); + + expect(containerSpecAttribute.constraints, + const BoxConstraintsDto(maxHeight: 100)); + expect(containerSpecAttribute.decoration, + const BoxDecorationDto(color: ColorDto(Colors.blue))); + + expect(containerSpecAttribute.height, 100); + expect( + containerSpecAttribute.margin, + const SpacingDto.only( + bottom: 10, + left: 10, + right: 10, + top: 10, + )); + expect( + containerSpecAttribute.padding, + const SpacingDto.only(bottom: 20, left: 20, right: 20, top: 20), + ); + expect(containerSpecAttribute.transform, Matrix4.identity()); + expect(containerSpecAttribute.width, 100); + }); + + // resolve() + test('resolve() returns correct instance', () { + final containerSpecAttribute = ContainerSpecAttribute( + alignment: Alignment.center, + clipBehavior: Clip.antiAlias, + constraints: const BoxConstraintsDto(maxHeight: 100), + decoration: const BoxDecorationDto(color: ColorDto(Colors.blue)), + height: 100, + margin: const SpacingDto.only( + bottom: 10, + left: 10, + right: 10, + top: 10, + ), + padding: + const SpacingDto.only(bottom: 20, left: 20, right: 20, top: 20), + transform: Matrix4.identity(), + width: 100, + ); + + final containerSpec = containerSpecAttribute.resolve(EmptyMixData); + + expect(containerSpec.alignment, Alignment.center); + expect(containerSpec.clipBehavior, Clip.antiAlias); + + expect(containerSpec.constraints, + const BoxConstraints(maxHeight: 100, maxWidth: double.infinity)); + expect(containerSpec.decoration, const BoxDecoration(color: Colors.blue)); + + expect(containerSpec.height, 100); + expect( + containerSpec.margin, + const EdgeInsets.only( + bottom: 10, + left: 10, + right: 10, + top: 10, + )); + expect( + containerSpec.padding, + const EdgeInsets.only(bottom: 20, left: 20, right: 20, top: 20), + ); + expect(containerSpec.transform, Matrix4.identity()); + expect(containerSpec.width, 100); + }); + + // merge() + test('merge() returns correct instance', () { + final containerSpecAttribute = ContainerSpecAttribute( + alignment: Alignment.center, + clipBehavior: Clip.antiAlias, + constraints: const BoxConstraintsDto(maxHeight: 100), + decoration: const BoxDecorationDto(color: ColorDto(Colors.blue)), + height: 100, + margin: const SpacingDto.only( + bottom: 10, + left: 10, + right: 10, + top: 10, + ), + padding: + const SpacingDto.only(bottom: 20, left: 20, right: 20, top: 20), + transform: Matrix4.identity(), + width: 100, + ); + + final mergedContainerSpecAttribute = containerSpecAttribute.merge( + ContainerSpecAttribute( + alignment: Alignment.centerLeft, + clipBehavior: Clip.antiAliasWithSaveLayer, + constraints: const BoxConstraintsDto(maxHeight: 200), + decoration: const BoxDecorationDto(color: ColorDto(Colors.red)), + height: 200, + margin: const SpacingDto.only( + bottom: 20, + left: 20, + right: 20, + top: 20, + ), + padding: + const SpacingDto.only(bottom: 30, left: 30, right: 30, top: 30), + transform: Matrix4.identity(), + width: 200, + ), + ); + + expect(mergedContainerSpecAttribute.alignment, Alignment.centerLeft); + expect(mergedContainerSpecAttribute.clipBehavior, + Clip.antiAliasWithSaveLayer); + + expect(mergedContainerSpecAttribute.constraints, + const BoxConstraintsDto(maxHeight: 200)); + expect(mergedContainerSpecAttribute.decoration, + const BoxDecorationDto(color: ColorDto(Colors.red))); + + expect(mergedContainerSpecAttribute.height, 200); + expect( + mergedContainerSpecAttribute.margin, + const SpacingDto.only( + bottom: 20, + left: 20, + right: 20, + top: 20, + )); + expect( + mergedContainerSpecAttribute.padding, + const SpacingDto.only(bottom: 30, left: 30, right: 30, top: 30), + ); + expect(mergedContainerSpecAttribute.transform, Matrix4.identity()); + expect(mergedContainerSpecAttribute.width, 200); + }); + + // equality + test('equality', () { + final containerSpecAttribute = ContainerSpecAttribute( + alignment: Alignment.center, + clipBehavior: Clip.antiAlias, + constraints: const BoxConstraintsDto(maxHeight: 100), + decoration: const BoxDecorationDto(color: ColorDto(Colors.blue)), + height: 100, + margin: const SpacingDto.only( + bottom: 10, + left: 10, + right: 10, + top: 10, + ), + padding: + const SpacingDto.only(bottom: 20, left: 20, right: 20, top: 20), + transform: Matrix4.identity(), + width: 100, + ); + + expect( + containerSpecAttribute, + equals( + ContainerSpecAttribute( + alignment: Alignment.center, + clipBehavior: Clip.antiAlias, + constraints: const BoxConstraintsDto(maxHeight: 100), + decoration: const BoxDecorationDto(color: ColorDto(Colors.blue)), + height: 100, + margin: const SpacingDto.only( + bottom: 10, + left: 10, + right: 10, + top: 10, + ), + padding: + const SpacingDto.only(bottom: 20, left: 20, right: 20, top: 20), + transform: Matrix4.identity(), + width: 100, + ), + ), + ); + }); + + // not equals + test('not equals', () { + final containerSpecAttribute = ContainerSpecAttribute( + alignment: Alignment.center, + clipBehavior: Clip.antiAlias, + constraints: const BoxConstraintsDto(maxHeight: 100), + decoration: const BoxDecorationDto(color: ColorDto(Colors.blue)), + height: 100, + margin: const SpacingDto.only( + bottom: 10, + left: 10, + right: 10, + top: 10, + ), + padding: + const SpacingDto.only(bottom: 20, left: 20, right: 20, top: 20), + transform: Matrix4.identity(), + width: 100, + ); + + expect( + containerSpecAttribute, + isNot( + equals( + ContainerSpecAttribute( + alignment: Alignment.centerLeft, + clipBehavior: Clip.antiAliasWithSaveLayer, + constraints: const BoxConstraintsDto(maxHeight: 200), + decoration: const BoxDecorationDto(color: ColorDto(Colors.red)), + height: 200, + margin: const SpacingDto.only( + bottom: 20, + left: 20, + right: 20, + top: 20, + ), + padding: const SpacingDto.only( + bottom: 30, left: 30, right: 30, top: 30), + transform: Matrix4.identity(), + width: 200, + ), + ), + ), + ); + }); + }); +} diff --git a/test/src/recipes/container/container_spec_test.dart b/test/src/recipes/container/container_spec_test.dart index 7abe90058..eec140ccf 100644 --- a/test/src/recipes/container/container_spec_test.dart +++ b/test/src/recipes/container/container_spec_test.dart @@ -3,9 +3,6 @@ import 'dart:ui'; import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:mix/mix.dart'; -import 'package:mix/src/attributes/constraints/constraints_dto.dart'; -import 'package:mix/src/attributes/decoration/decoration_dto.dart'; -import 'package:mix/src/attributes/spacing/spacing_dto.dart'; import '../../../helpers/testing_utils.dart'; @@ -15,37 +12,46 @@ void main() { final mix = MixData.create( MockBuildContext(), StyleMix( - const AlignmentGeometryAttribute(Alignment.center), - const PaddingAttribute(SpacingDto(top: 8, bottom: 16)), - const MarginAttribute(SpacingDto(top: 10.0, bottom: 12.0)), - const BoxConstraintsAttribute( - BoxConstraintsDto(maxWidth: 300.0, minHeight: 200.0), - ), - const DecorationAttribute( - BoxDecorationDto(color: ColorDto(Colors.blue)), - ), - TransformAttribute(Matrix4.translationValues(10.0, 10.0, 0.0)), - const ClipBehaviorAttribute(Clip.antiAlias), + // const AlignmentGeometryAttribute(Alignment.center), + // const PaddingAttribute(SpacingDto.only(top: 8, bottom: 16)), + // const MarginAttribute(SpacingDto.only(top: 10.0, bottom: 12.0)), + // const BoxConstraintsAttribute( + // BoxConstraintsDto(maxWidth: 300.0, minHeight: 200.0), + // ), + // const DecorationAttribute( + // BoxDecorationDto(color: ColorDto(Colors.blue)), + // ), + // TransformAttribute(Matrix4.translationValues(10.0, 10.0, 0.0)), + ContainerSpecAttribute( + alignment: Alignment.center, + padding: const SpacingDto.only(top: 8, bottom: 16), + margin: const SpacingDto.only(top: 10.0, bottom: 12.0), + constraints: + const BoxConstraintsDto(maxWidth: 300.0, minHeight: 200.0), + decoration: const BoxDecorationDto(color: ColorDto(Colors.blue)), + transform: Matrix4.translationValues(10.0, 10.0, 0.0), + clipBehavior: Clip.antiAlias, + width: 300, + height: 200), ), ); - final mixture = ContainerSpecAttribute.of(mix).resolve(mix); + final spec = mix.attributeOf()!.resolve(mix); - expect(mixture.alignment, Alignment.center); - expect(mixture.padding, const EdgeInsets.only(bottom: 16.0, top: 8.0)); - expect(mixture.margin, const EdgeInsets.only(top: 10.0, bottom: 12.0)); - expect(mixture.constraints, + expect(spec.alignment, Alignment.center); + expect(spec.padding, const EdgeInsets.only(bottom: 16.0, top: 8.0)); + expect(spec.margin, const EdgeInsets.only(top: 10.0, bottom: 12.0)); + expect(spec.constraints, const BoxConstraints(maxWidth: 300.0, minHeight: 200.0)); - expect(mixture.decoration, const BoxDecoration(color: Colors.blue)); + expect(spec.decoration, const BoxDecoration(color: Colors.blue)); - expect(mixture.transform, Matrix4.translationValues(10.0, 10.0, 0.0)); - expect(mixture.clipBehavior, Clip.antiAlias); + expect(spec.transform, Matrix4.translationValues(10.0, 10.0, 0.0)); + expect(spec.clipBehavior, Clip.antiAlias); }); test('copyWith', () { final spec = ContainerSpec( alignment: Alignment.center, - color: null, width: 300, height: 200, padding: const EdgeInsets.all(16.0), @@ -67,12 +73,13 @@ void main() { expect(copiedSpec.transform, Matrix4.translationValues(10.0, 10.0, 0.0)); expect(copiedSpec.clipBehavior, Clip.antiAlias); + expect(copiedSpec.width, 250.0); + expect(copiedSpec.height, 150.0); }); test('lerp', () { final spec1 = ContainerSpec( alignment: Alignment.topLeft, - color: null, width: 300, height: 200, padding: const EdgeInsets.all(8.0), @@ -85,7 +92,6 @@ void main() { final spec2 = ContainerSpec( alignment: Alignment.bottomRight, - color: null, width: 400, height: 300, padding: const EdgeInsets.all(16.0), @@ -129,5 +135,103 @@ void main() { .lerp(t)); expect(lerpedSpec.clipBehavior, t < 0.5 ? Clip.none : Clip.antiAlias); }); + + // equality + test('equality', () { + final spec1 = ContainerSpec( + alignment: Alignment.topLeft, + width: 300, + height: 200, + padding: const EdgeInsets.all(8.0), + margin: const EdgeInsets.only(top: 4.0), + constraints: const BoxConstraints(maxWidth: 200.0), + decoration: const BoxDecoration(color: Colors.red), + transform: Matrix4.identity(), + clipBehavior: Clip.none, + ); + + final spec2 = ContainerSpec( + alignment: Alignment.topLeft, + width: 300, + height: 200, + padding: const EdgeInsets.all(8.0), + margin: const EdgeInsets.only(top: 4.0), + constraints: const BoxConstraints(maxWidth: 200.0), + decoration: const BoxDecoration(color: Colors.red), + transform: Matrix4.identity(), + clipBehavior: Clip.none, + ); + + expect(spec1, spec2); + }); + + // merge() + test('merge() returns correct instance', () { + final containerSpecAttribute = ContainerSpecAttribute( + alignment: Alignment.center, + clipBehavior: Clip.antiAlias, + constraints: const BoxConstraintsDto(maxHeight: 100), + decoration: const BoxDecorationDto(color: ColorDto(Colors.blue)), + height: 100, + margin: const SpacingDto.only( + bottom: 10, + left: 10, + right: 10, + top: 10, + ), + padding: + const SpacingDto.only(bottom: 20, left: 20, right: 20, top: 20), + transform: Matrix4.identity(), + width: 100, + ); + + final mergedContainerSpecAttribute = containerSpecAttribute.merge( + ContainerSpecAttribute( + alignment: Alignment.centerLeft, + clipBehavior: Clip.antiAliasWithSaveLayer, + constraints: const BoxConstraintsDto(maxHeight: 200), + decoration: const BoxDecorationDto(color: ColorDto(Colors.red)), + height: 200, + margin: const SpacingDto.only( + bottom: 20, + left: 20, + right: 20, + top: 20, + ), + padding: + const SpacingDto.only(bottom: 30, left: 30, right: 30, top: 30), + transform: Matrix4.identity(), + width: 200, + ), + ); + + expect(mergedContainerSpecAttribute.alignment, Alignment.centerLeft); + expect(mergedContainerSpecAttribute.clipBehavior, + Clip.antiAliasWithSaveLayer); + + expect(mergedContainerSpecAttribute.constraints, + const BoxConstraintsDto(maxHeight: 200)); + expect(mergedContainerSpecAttribute.decoration, + const BoxDecorationDto(color: ColorDto(Colors.red))); + expect(mergedContainerSpecAttribute.height, 200); + expect( + mergedContainerSpecAttribute.margin, + const SpacingDto.only( + bottom: 20, + left: 20, + right: 20, + top: 20, + )); + expect( + mergedContainerSpecAttribute.padding, + const SpacingDto.only( + bottom: 30, + left: 30, + right: 30, + top: 30, + )); + expect(mergedContainerSpecAttribute.transform, Matrix4.identity()); + expect(mergedContainerSpecAttribute.width, 200); + }); }); } diff --git a/test/src/recipes/container/container_util_test.dart b/test/src/recipes/container/container_util_test.dart new file mode 100644 index 000000000..1e1b47421 --- /dev/null +++ b/test/src/recipes/container/container_util_test.dart @@ -0,0 +1,109 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:mix/mix.dart'; + +import '../../../helpers/attribute_generator.dart'; +import '../../../helpers/testing_utils.dart'; + +void main() { + group( + 'ContainerUtility', + () { + const containerUtility = ContainerUtility(UtilityTestAttribute.new); + test('call() returns correct instance', () { + final container = containerUtility( + alignment: Alignment.center, + clipBehavior: Clip.antiAlias, + constraints: const BoxConstraints( + maxHeight: 100, maxWidth: 200, minWidth: 50, minHeight: 40), + decoration: RandomGenerator.boxDecoration(), + height: 10, + margin: const EdgeInsets.all(10), + padding: const EdgeInsets.all(10), + transform: Matrix4.identity(), + width: 10, + ); + + expect(container.value.alignment, Alignment.center); + expect(container.value.clipBehavior, Clip.antiAlias); + + expect( + container.value.constraints, + const BoxConstraintsDto( + maxHeight: 100, maxWidth: 200, minWidth: 50, minHeight: 40)); + expect(container.value.decoration, isA()); + + expect(container.value.height, 10); + expect(container.value.margin, + const SpacingDto.only(bottom: 10, left: 10, right: 10, top: 10)); + expect(container.value.padding, + const SpacingDto.only(bottom: 10, left: 10, right: 10, top: 10)); + expect(container.value.transform, Matrix4.identity()); + expect(container.value.width, 10); + }); + + // alignment() + test('alignment() returns correct instance', () { + final container = containerUtility.alignment(Alignment.center); + + expect(container.value.alignment, Alignment.center); + }); + + // clipBehavior() + test('clipBehavior() returns correct instance', () { + final container = containerUtility.clipBehavior(Clip.antiAlias); + + expect(container.value.clipBehavior, Clip.antiAlias); + }); + + // color() + test('color() returns correct instance', () { + final container = containerUtility.color(Colors.blue); + + expect((container.value.decoration as BoxDecorationDto).color, + const ColorDto(Colors.blue)); + }); + + // constraints() + test('constraints() returns correct instance', () { + expect(container.constraints, isA()); + }); + + // decoration() + test('decoration() returns correct instance', () { + expect(containerUtility.decoration, isA()); + }); + + // height() + test('height() returns correct instance', () { + final container = containerUtility.height(10); + + expect(container.value.height, 10); + }); + + // margin() + test('margin() returns correct instance', () { + expect(containerUtility.margin, isA()); + }); + + // padding() + test('padding() returns correct instance', () { + expect(containerUtility.padding, isA()); + }); + + // transform() + test('transform() returns correct instance', () { + final container = containerUtility.transform(Matrix4.identity()); + + expect(container.value.transform, Matrix4.identity()); + }); + + // width() + test('width() returns correct instance', () { + final container = containerUtility.width(10); + + expect(container.value.width, 10); + }); + }, + ); +} diff --git a/test/src/recipes/container/container_widget_test.dart b/test/src/recipes/container/container_widget_test.dart index 098b9d634..b2e4494c4 100644 --- a/test/src/recipes/container/container_widget_test.dart +++ b/test/src/recipes/container/container_widget_test.dart @@ -6,12 +6,12 @@ import '../../../helpers/testing_utils.dart'; void main() { testWidgets('StyledContainer', (WidgetTester tester) async { - final paddingAttr = padding(10); - final marginAttr = margin(15); - final alignmentAttr = alignment.center(); - final clipAttr = clipBehavior.hardEdge(); + final paddingAttr = box.padding(10); + final marginAttr = box.margin(15); + final alignmentAttr = box.alignment.center(); + final clipAttr = box.clipBehavior.hardEdge(); - final boxDecorationAttr = box.decoration( + final boxDecorationAttr = box.decoration.box( border: Border.all(color: Colors.red, width: 1, style: BorderStyle.solid), borderRadius: BorderRadius.circular(10), color: Colors.red, diff --git a/test/src/recipes/flex/flex_attribute_test.dart b/test/src/recipes/flex/flex_attribute_test.dart new file mode 100644 index 000000000..d7711e03c --- /dev/null +++ b/test/src/recipes/flex/flex_attribute_test.dart @@ -0,0 +1,111 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:mix/mix.dart'; + +import '../../../helpers/testing_utils.dart'; + +void main() { + group('FlexMixAttribute', () { + test('of returns correct FlexMixAttribute', () { + final attribute = FlexSpecAttribute.of(EmptyMixData); + + expect(attribute.direction, null); + expect(attribute.mainAxisAlignment, null); + expect(attribute.crossAxisAlignment, null); + expect(attribute.mainAxisSize, null); + expect(attribute.verticalDirection, null); + expect(attribute.textDirection, null); + expect(attribute.textBaseline, null); + expect(attribute.clipBehavior, null); + expect(attribute.gap, null); + }); + + test('resolve returns correct FlexSpec', () { + const attribute = FlexSpecAttribute( + direction: Axis.horizontal, + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.max, + verticalDirection: VerticalDirection.up, + textDirection: TextDirection.rtl, + textBaseline: TextBaseline.alphabetic, + clipBehavior: Clip.antiAlias, + gap: 10.0, + ); + final mixData = MixData.create(MockBuildContext(), StyleMix(attribute)); + final resolvedSpec = attribute.resolve(mixData); + + expect(resolvedSpec.crossAxisAlignment, CrossAxisAlignment.start); + expect(resolvedSpec.mainAxisAlignment, MainAxisAlignment.center); + expect(resolvedSpec.mainAxisSize, MainAxisSize.max); + expect(resolvedSpec.verticalDirection, VerticalDirection.up); + expect(resolvedSpec.direction, Axis.horizontal); + expect(resolvedSpec.textDirection, TextDirection.rtl); + expect(resolvedSpec.textBaseline, TextBaseline.alphabetic); + expect(resolvedSpec.clipBehavior, Clip.antiAlias); + expect(resolvedSpec.gap, 10.0); + }); + + test('merge returns correct FlexMixAttribute', () { + const attribute1 = FlexSpecAttribute( + direction: Axis.horizontal, + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.max, + verticalDirection: VerticalDirection.up, + textDirection: TextDirection.rtl, + textBaseline: TextBaseline.alphabetic, + clipBehavior: Clip.antiAlias, + gap: 10.0, + ); + const attribute2 = FlexSpecAttribute( + direction: Axis.vertical, + mainAxisAlignment: MainAxisAlignment.end, + crossAxisAlignment: CrossAxisAlignment.end, + mainAxisSize: MainAxisSize.min, + verticalDirection: VerticalDirection.down, + textDirection: TextDirection.ltr, + textBaseline: TextBaseline.ideographic, + clipBehavior: Clip.hardEdge, + gap: 20.0, + ); + final mergedAttribute = attribute1.merge(attribute2); + + expect(mergedAttribute.direction, Axis.vertical); + expect(mergedAttribute.mainAxisAlignment, MainAxisAlignment.end); + expect(mergedAttribute.crossAxisAlignment, CrossAxisAlignment.end); + expect(mergedAttribute.mainAxisSize, MainAxisSize.min); + expect(mergedAttribute.verticalDirection, VerticalDirection.down); + expect(mergedAttribute.textDirection, TextDirection.ltr); + expect(mergedAttribute.textBaseline, TextBaseline.ideographic); + expect(mergedAttribute.clipBehavior, Clip.hardEdge); + expect(mergedAttribute.gap, 20.0); + }); + + test('props returns correct list of properties', () { + const attribute = FlexSpecAttribute( + direction: Axis.horizontal, + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.max, + verticalDirection: VerticalDirection.up, + textDirection: TextDirection.rtl, + textBaseline: TextBaseline.alphabetic, + clipBehavior: Clip.antiAlias, + gap: 10.0, + ); + final props = attribute.props; + + expect(props.length, 9); + expect(props[0], Axis.horizontal); + expect(props[1], MainAxisAlignment.center); + expect(props[2], CrossAxisAlignment.start); + expect(props[3], MainAxisSize.max); + expect(props[4], VerticalDirection.up); + expect(props[5], TextDirection.rtl); + expect(props[6], TextBaseline.alphabetic); + expect(props[7], Clip.antiAlias); + expect(props[8], 10.0); + }); + }); +} diff --git a/test/src/recipes/flex/flex_spec_test.dart b/test/src/recipes/flex/flex_spec_test.dart index 01412268e..6e9a9a3a4 100644 --- a/test/src/recipes/flex/flex_spec_test.dart +++ b/test/src/recipes/flex/flex_spec_test.dart @@ -12,7 +12,7 @@ void main() { final mix = MixData.create( MockBuildContext(), StyleMix( - const FlexMixAttribute( + const FlexSpecAttribute( crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center, mainAxisSize: MainAxisSize.min, diff --git a/test/src/recipes/flex/flex_util_test.dart b/test/src/recipes/flex/flex_util_test.dart new file mode 100644 index 000000000..9036d5b08 --- /dev/null +++ b/test/src/recipes/flex/flex_util_test.dart @@ -0,0 +1,111 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:mix/mix.dart'; + +import '../../../helpers/testing_utils.dart'; + +void main() { + group('FlexUtility', () { + const flexUtility = FlexSpecUtility(UtilityTestAttribute.new); + test('call() returns correct instance', () { + final flex = flexUtility( + direction: Axis.horizontal, + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisSize: MainAxisSize.max, + ); + + expect(flex.value.direction, Axis.horizontal); + expect(flex.value.mainAxisAlignment, MainAxisAlignment.center); + expect(flex.value.crossAxisAlignment, CrossAxisAlignment.center); + expect(flex.value.mainAxisSize, MainAxisSize.max); + }); + + // direction() + test('direction() returns correct instance', () { + final flex = flexUtility.direction(Axis.horizontal); + + expect(flex.value.direction, Axis.horizontal); + }); + + // mainAxisAlignment() + test('mainAxisAlignment() returns correct instance', () { + final flex = flexUtility.mainAxisAlignment(MainAxisAlignment.center); + + expect(flex.value.mainAxisAlignment, MainAxisAlignment.center); + }); + + // crossAxisAlignment() + test('crossAxisAlignment() returns correct instance', () { + final flex = flexUtility.crossAxisAlignment(CrossAxisAlignment.center); + + expect(flex.value.crossAxisAlignment, CrossAxisAlignment.center); + }); + + // mainAxisSize() + test('mainAxisSize() returns correct instance', () { + final flex = flexUtility.mainAxisSize(MainAxisSize.max); + final helper = flexUtility.mainAxisSize.max(); + + expect(flex.value.mainAxisSize, MainAxisSize.max); + expect(helper.value.mainAxisSize, MainAxisSize.max); + }); + + // verticalDirection() + test('verticalDirection() returns correct instance', () { + final flex = flexUtility.verticalDirection(VerticalDirection.down); + final helper = flexUtility.verticalDirection.down(); + + expect(flex.value.verticalDirection, VerticalDirection.down); + expect(helper.value.verticalDirection, VerticalDirection.down); + }); + + // textDirection() + test('textDirection() returns correct instance', () { + final flex = flexUtility.textDirection(TextDirection.ltr); + final helper = flexUtility.textDirection.ltr(); + + expect(flex.value.textDirection, TextDirection.ltr); + expect(helper.value.textDirection, TextDirection.ltr); + }); + + // textBaseline() + test('textBaseline() returns correct instance', () { + final flex = flexUtility.textBaseline(TextBaseline.alphabetic); + final helper = flexUtility.textBaseline.alphabetic(); + + expect(flex.value.textBaseline, TextBaseline.alphabetic); + expect(helper.value.textBaseline, TextBaseline.alphabetic); + }); + + // clipBehavior() + test('clipBehavior() returns correct instance', () { + final flex = flexUtility.clipBehavior(Clip.antiAlias); + final helper = flexUtility.clipBehavior.antiAlias(); + + expect(flex.value.clipBehavior, Clip.antiAlias); + expect(helper.value.clipBehavior, Clip.antiAlias); + }); + + // gap() + test('gap() returns correct instance', () { + final flex = flexUtility.gap(10); + + expect(flex.value.gap, 10); + }); + + // row() + test('row() returns correct instance', () { + final flex = flexUtility.row(); + + expect(flex.value.direction, Axis.horizontal); + }); + + // column() + test('column() returns correct instance', () { + final flex = flexUtility.column(); + + expect(flex.value.direction, Axis.vertical); + }); + }); +} diff --git a/test/src/recipes/icon/icon_attribute_test.dart b/test/src/recipes/icon/icon_attribute_test.dart new file mode 100644 index 000000000..04804a56e --- /dev/null +++ b/test/src/recipes/icon/icon_attribute_test.dart @@ -0,0 +1,46 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:mix/mix.dart'; + +import '../../../helpers/testing_utils.dart'; + +void main() { + group( + 'IconMixAttribute', + () { + test( + 'resolve should return an instance of IconSpec', + () { + const attribute = IconSpecAttribute(); + final resolvedSpec = attribute.resolve(EmptyMixData); + expect(resolvedSpec, isA()); + }, + ); + + test( + 'merge should return a new instance of IconMixAttribute', + () { + const attribute1 = + IconSpecAttribute(size: 24, color: ColorDto(Colors.red)); + const attribute2 = + IconSpecAttribute(size: 32, color: ColorDto(Colors.green)); + final mergedAttribute = attribute1.merge(attribute2); + expect(mergedAttribute, isA()); + expect(mergedAttribute.size, equals(24)); + expect(mergedAttribute.color, equals(const ColorDto(Colors.red))); + }, + ); + + test( + 'props should return a list of size and color', + () { + const attribute = + IconSpecAttribute(size: 24, color: ColorDto(Colors.red)); + final props = attribute.props; + expect(props, contains(24)); + expect(props, contains(const ColorDto(Colors.red))); + }, + ); + }, + ); +} diff --git a/test/src/recipes/icon/icon_spec_test.dart b/test/src/recipes/icon/icon_spec_test.dart index dbeb40bab..cca6212a6 100644 --- a/test/src/recipes/icon/icon_spec_test.dart +++ b/test/src/recipes/icon/icon_spec_test.dart @@ -12,7 +12,7 @@ void main() { final mix = MixData.create( MockBuildContext(), StyleMix( - IconMixAttribute(color: Colors.red.toDto(), size: 20.0), + IconSpecAttribute(color: Colors.red.toDto(), size: 20.0), ), ); diff --git a/test/src/recipes/icon_spec_test.dart b/test/src/recipes/icon_spec_test.dart index 899353419..3a676f365 100644 --- a/test/src/recipes/icon_spec_test.dart +++ b/test/src/recipes/icon_spec_test.dart @@ -12,7 +12,7 @@ void main() { final mix = MixData.create( MockBuildContext(), StyleMix( - IconMixAttribute(color: Colors.red.toDto(), size: 20.0), + IconSpecAttribute(color: Colors.red.toDto(), size: 20.0), ), ); diff --git a/test/src/recipes/image/image_attribute_test.dart b/test/src/recipes/image/image_attribute_test.dart new file mode 100644 index 000000000..953cc95e3 --- /dev/null +++ b/test/src/recipes/image/image_attribute_test.dart @@ -0,0 +1,69 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:mix/mix.dart'; + +import '../../../helpers/testing_utils.dart'; + +void main() { + group('ImageMixAttribute', () { + test('resolve returns correct ImageSpec', () { + const attribute = ImageMixAttribute( + width: 100, + height: 200, + color: ColorDto(Colors.red), + repeat: ImageRepeat.repeat, + fit: BoxFit.cover, + ); + + final spec = attribute.resolve(EmptyMixData); + + expect(spec.width, 100); + expect(spec.height, 200); + expect(spec.color, Colors.red); + expect(spec.repeat, ImageRepeat.repeat); + expect(spec.fit, BoxFit.cover); + }); + + test('merge returns correct ImageMixAttribute', () { + const attribute1 = ImageMixAttribute( + width: 100, + height: 200, + color: ColorDto(Colors.red), + repeat: ImageRepeat.repeat, + fit: BoxFit.cover, + ); + const attribute2 = ImageMixAttribute( + width: 150, + height: 250, + color: ColorDto(Colors.blue), + repeat: ImageRepeat.noRepeat, + fit: BoxFit.fill, + ); + final mergedAttribute = attribute1.merge(attribute2); + + expect(mergedAttribute.width, 150); + expect(mergedAttribute.height, 250); + expect(mergedAttribute.color, const ColorDto(Colors.blue)); + expect(mergedAttribute.repeat, ImageRepeat.noRepeat); + expect(mergedAttribute.fit, BoxFit.fill); + }); + + test('props returns correct list of properties', () { + const attribute = ImageMixAttribute( + width: 100, + height: 200, + color: ColorDto(Colors.red), + repeat: ImageRepeat.repeat, + fit: BoxFit.cover, + ); + final props = attribute.props; + + expect(props.length, 5); + expect(props[0], 100); + expect(props[1], 200); + expect(props[2], const ColorDto(Colors.red)); + expect(props[3], ImageRepeat.repeat); + expect(props[4], BoxFit.cover); + }); + }); +} diff --git a/test/src/recipes/image/image_spec_test.dart b/test/src/recipes/image/image_spec_test.dart new file mode 100644 index 000000000..61300fd92 --- /dev/null +++ b/test/src/recipes/image/image_spec_test.dart @@ -0,0 +1,86 @@ +import 'dart:ui'; + +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:mix/mix.dart'; + +import '../../../helpers/testing_utils.dart'; + +void main() { + group('ImageSpec', () { + test('resolve returns correct recipe', () { + final recipe = ImageSpec.resolve(EmptyMixData); + + expect(recipe.width, null); + expect(recipe.height, null); + expect(recipe.color, null); + expect(recipe.repeat, null); + expect(recipe.fit, null); + }); + + test('lerp returns correct ImageSpec', () { + const spec1 = ImageSpec( + width: 100, + height: 200, + color: Colors.red, + repeat: ImageRepeat.repeat, + fit: BoxFit.cover, + ); + const spec2 = ImageSpec( + width: 150, + height: 250, + color: Colors.blue, + repeat: ImageRepeat.noRepeat, + fit: BoxFit.fill, + ); + final lerpSpec = spec1.lerp(spec2, 0.5); + + expect(lerpSpec.width, lerpDouble(100, 150, 0.5)); + expect(lerpSpec.height, lerpDouble(200, 250, 0.5)); + expect(lerpSpec.color, Color.lerp(Colors.red, Colors.blue, 0.5)); + expect(lerpSpec.repeat, ImageRepeat.noRepeat); + expect(lerpSpec.fit, BoxFit.fill); + }); + + test('copyWith returns correct ImageSpec', () { + const spec = ImageSpec( + width: 100, + height: 200, + color: Colors.red, + repeat: ImageRepeat.repeat, + fit: BoxFit.cover, + ); + final copiedSpec = spec.copyWith( + width: 150, + height: 250, + color: Colors.blue, + repeat: ImageRepeat.noRepeat, + fit: BoxFit.fill, + ); + + expect(copiedSpec.width, 150); + expect(copiedSpec.height, 250); + expect(copiedSpec.color, Colors.blue); + expect(copiedSpec.repeat, ImageRepeat.noRepeat); + expect(copiedSpec.fit, BoxFit.fill); + }); + + test('props returns correct list of properties', () { + const spec = ImageSpec( + width: 100, + height: 200, + color: Colors.red, + repeat: ImageRepeat.repeat, + fit: BoxFit.cover, + ); + final props = spec.props; + + expect(props.length, 5); + expect(props[0], 100); + expect(props[1], 200); + expect(props[2], Colors.red); + expect(props[3], ImageRepeat.repeat); + expect(props[4], BoxFit.cover); + }); + }); +} diff --git a/test/src/recipes/stack/stack_attribute_test.dart b/test/src/recipes/stack/stack_attribute_test.dart new file mode 100644 index 000000000..8caacb0ce --- /dev/null +++ b/test/src/recipes/stack/stack_attribute_test.dart @@ -0,0 +1,78 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:mix/mix.dart'; + +import '../../../helpers/testing_utils.dart'; + +void main() { + group('StackMixAttribute', () { + test( + 'of returns default attribute when mix does not have StackMixAttribute', + () { + final mix = MixData.create(MockBuildContext(), StyleMix()); + final attribute = StackSpecAttribute.of(mix); + + final resolved = attribute.resolve(mix); + + expect(resolved.alignment, null); + expect(resolved.fit, null); + expect(resolved.textDirection, null); + expect(resolved.clipBehavior, null); + }); + + test('resolve returns correct StackSpec', () { + const attribute = StackSpecAttribute( + alignment: Alignment.center, + fit: StackFit.expand, + textDirection: TextDirection.ltr, + clipBehavior: Clip.antiAlias, + ); + final mix = MixData.create(MockBuildContext(), StyleMix(attribute)); + final spec = attribute.resolve(mix); + + expect(spec.alignment, Alignment.center); + expect(spec.fit, StackFit.expand); + expect(spec.textDirection, TextDirection.ltr); + expect(spec.clipBehavior, Clip.antiAlias); + }); + + test('merge returns correct StackMixAttribute', () { + const attribute1 = StackSpecAttribute( + alignment: Alignment.center, + fit: StackFit.expand, + textDirection: TextDirection.ltr, + clipBehavior: Clip.antiAlias, + ); + const attribute2 = StackSpecAttribute( + alignment: Alignment.topLeft, + fit: StackFit.loose, + textDirection: TextDirection.rtl, + clipBehavior: Clip.hardEdge, + ); + final mergedAttribute = attribute1.merge(attribute2); + + final resolved = mergedAttribute.resolve(EmptyMixData); + + expect(resolved.alignment, Alignment.topLeft); + expect(resolved.fit, StackFit.loose); + expect(resolved.textDirection, TextDirection.rtl); + expect(resolved.clipBehavior, Clip.hardEdge); + }); + + test('props returns correct list of properties', () { + const attribute = StackSpecAttribute( + alignment: Alignment.center, + fit: StackFit.expand, + textDirection: TextDirection.ltr, + clipBehavior: Clip.antiAlias, + ); + final props = attribute.props; + + expect(props.length, 4); + expect(props[0], Alignment.center); + expect(props[1], StackFit.expand); + expect(props[2], TextDirection.ltr); + expect(props[3], Clip.antiAlias); + }); + }); +} diff --git a/test/src/recipes/stack/stack_spec_test.dart b/test/src/recipes/stack/stack_spec_test.dart index 8b634b59a..7f4cf1c1a 100644 --- a/test/src/recipes/stack/stack_spec_test.dart +++ b/test/src/recipes/stack/stack_spec_test.dart @@ -10,7 +10,7 @@ void main() { final mix = MixData.create( MockBuildContext(), StyleMix( - const StackMixAttribute( + const StackSpecAttribute( fit: StackFit.expand, clipBehavior: Clip.antiAlias, alignment: Alignment.center, @@ -19,7 +19,7 @@ void main() { ), ); - final mixture = StackMixAttribute.of(mix).resolve(mix); + final mixture = StackSpecAttribute.of(mix).resolve(mix); expect(mixture.alignment, Alignment.center); expect(mixture.fit, StackFit.expand); diff --git a/test/src/recipes/stack/stack_widget_test.dart b/test/src/recipes/stack/stack_widget_test.dart index eb25e46e9..045c4548e 100644 --- a/test/src/recipes/stack/stack_widget_test.dart +++ b/test/src/recipes/stack/stack_widget_test.dart @@ -63,7 +63,7 @@ void main() { expect(find.byType(Container), findsOneWidget); - expect(container.color, Colors.red); + expect((container.decoration as BoxDecoration).color, Colors.red); expect(stackWidget.alignment, Alignment.topCenter); expect(stackWidget.fit, StackFit.expand); diff --git a/test/src/recipes/text/text_spec_test.dart b/test/src/recipes/text/text_spec_test.dart index 4ffabefaa..dcdf69077 100644 --- a/test/src/recipes/text/text_spec_test.dart +++ b/test/src/recipes/text/text_spec_test.dart @@ -1,8 +1,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:mix/mix.dart'; -import 'package:mix/src/attributes/strut_style/strut_style_dto.dart'; -import 'package:mix/src/attributes/text_style/text_style_dto.dart'; import '../../../helpers/testing_utils.dart'; diff --git a/test/src/theme/mix_theme_test.dart b/test/src/theme/mix_theme_test.dart index 826194349..6362bbfd4 100644 --- a/test/src/theme/mix_theme_test.dart +++ b/test/src/theme/mix_theme_test.dart @@ -5,13 +5,13 @@ import 'package:mix/mix.dart'; import '../../helpers/testing_utils.dart'; void main() { - const primaryColor = ColorToken('primary', Colors.red); + const primaryColor = ColorToken('primary'); group('MixTheme', () { testWidgets('MixTheme.of', (tester) async { final theme = MixThemeData( - colors: StyledTokens({ - primaryColor: (_) => Colors.blue, - }), + colors: { + primaryColor: Colors.blue, + }, ); await tester.pumpWithMixTheme(Container(), theme: theme); @@ -29,7 +29,7 @@ void main() { final context = tester.element(find.byType(Container)); expect(MixTheme.maybeOf(context), null); - expect(MixTheme.of(context), MixThemeData()); + expect(() => MixTheme.of(context), throwsAssertionError); }); }); } diff --git a/test/src/theme/tokens/breakpoints_test.dart b/test/src/theme/tokens/breakpoints_token_test.dart similarity index 58% rename from test/src/theme/tokens/breakpoints_test.dart rename to test/src/theme/tokens/breakpoints_token_test.dart index c96638131..1a167fa7a 100644 --- a/test/src/theme/tokens/breakpoints_test.dart +++ b/test/src/theme/tokens/breakpoints_token_test.dart @@ -2,39 +2,38 @@ import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:mix/mix.dart'; -import '../../../helpers/testing_utils.dart'; - void main() { test('MixBreakpointsTokens', () { final breakpoints = MixThemeData().breakpoints; - final context = MockBuildContext(); - final large = breakpoints(BreakpointToken.large, context); - final medium = breakpoints(BreakpointToken.medium, context); - final small = breakpoints(BreakpointToken.small, context); - final xsmall = breakpoints(BreakpointToken.xsmall, context); + + final large = breakpoints[BreakpointToken.large]!; + + final medium = breakpoints[BreakpointToken.medium]!; + final small = breakpoints[BreakpointToken.small]!; + final xsmall = breakpoints[BreakpointToken.xsmall]!; expect( large, - const BreakpointConstraint(minWidth: 1440, maxWidth: double.infinity), + const Breakpoint(minWidth: 1440, maxWidth: double.infinity), ); expect( medium, - const BreakpointConstraint(minWidth: 1024, maxWidth: 1439), + const Breakpoint(minWidth: 1024, maxWidth: 1439), ); expect( small, - const BreakpointConstraint(minWidth: 600, maxWidth: 1023), + const Breakpoint(minWidth: 600, maxWidth: 1023), ); expect( xsmall, - const BreakpointConstraint(minWidth: 0, maxWidth: 599), + const Breakpoint(minWidth: 0, maxWidth: 599), ); }); test('MixBreakpointsTokens large matches correctly', () { final breakpoints = MixThemeData().breakpoints; - final context = MockBuildContext(); - final large = breakpoints(BreakpointToken.large, context); + + final large = breakpoints[BreakpointToken.large]!; expect( large.matches(const Size(1440, 1024)), @@ -49,8 +48,8 @@ void main() { test('MixBreakpointsTokens medium matches correctly', () { final breakpoints = MixThemeData().breakpoints; - final context = MockBuildContext(); - final medium = breakpoints(BreakpointToken.medium, context); + + final medium = breakpoints[BreakpointToken.medium]!; expect( medium.matches(const Size(1024, 1024)), @@ -65,8 +64,8 @@ void main() { test('MixBreakpointsTokens small matches correctly', () { final breakpoints = MixThemeData().breakpoints; - final context = MockBuildContext(); - final small = breakpoints(BreakpointToken.small, context); + + final small = breakpoints[BreakpointToken.small]!; expect( small.matches(const Size(600, 1024)), @@ -81,8 +80,8 @@ void main() { test('MixBreakpointsTokens xsmall matches correctly', () { final breakpoints = MixThemeData().breakpoints; - final context = MockBuildContext(); - final xsmall = breakpoints(BreakpointToken.xsmall, context); + + final xsmall = breakpoints[BreakpointToken.xsmall]!; expect( xsmall.matches(const Size(0, 1024)), diff --git a/test/src/theme/tokens/color_token_test.dart b/test/src/theme/tokens/color_token_test.dart index 2326ca2fe..d69be08dd 100644 --- a/test/src/theme/tokens/color_token_test.dart +++ b/test/src/theme/tokens/color_token_test.dart @@ -8,42 +8,43 @@ void main() { group('ColorToken Tests', () { // Constructor Test test('Constructor assigns name correctly', () { - const colorToken = ColorToken('testName', Colors.black); + const colorToken = ColorToken('testName'); expect(colorToken.name, 'testName'); - expect(colorToken.value, Colors.black); + expect(colorToken().token, colorToken); }); // Equality Operator Test test('Equality operator works correctly', () { - const colorToken1 = ColorToken('testName', Colors.black); - const colorToken2 = ColorToken('testName', Colors.black); - const colorToken3 = ColorToken('testName', Colors.black12); - const colorToken4 = ColorToken('differentName', Colors.black); + const colorToken1 = ColorToken('testName'); + const colorToken2 = ColorToken('testName'); + + const colorToken3 = ColorToken('differentName'); expect(colorToken1 == colorToken2, isTrue); + expect(colorToken1 == colorToken3, isFalse); - expect(colorToken1 == colorToken4, isFalse); expect(colorToken1 == Object(), isFalse); }); // HashCode Test test('hashCode is consistent with name', () { - const colorToken1 = ColorToken('testName', Colors.black); - const colorToken2 = ColorToken('testName', Colors.black); - const colorToken3 = ColorToken('differentName', Colors.black); + const colorToken1 = ColorToken('testName'); + const colorToken2 = ColorToken('testName'); + const colorToken3 = ColorToken('differentName'); expect(colorToken1.hashCode, colorToken2.hashCode); expect(colorToken1.hashCode, isNot(colorToken3.hashCode)); }); testWidgets('Test it resolves correctly', (tester) async { - const redcolorToken = ColorToken('red', Colors.red); - const greencolorToken = ColorToken('green', Colors.green); - const bluecolorToken = ColorToken('blue', Colors.blue); - final theme = MixThemeData.tokenMap( + const redcolorToken = ColorToken('red'); + const greencolorToken = ColorToken('green'); + const bluecolorToken = ColorToken('blue'); + final theme = MixThemeData( colors: { - redcolorToken: (_) => Colors.redAccent, - bluecolorToken: (_) => Colors.blueAccent, + greencolorToken: Colors.green, + redcolorToken: Colors.redAccent, + bluecolorToken: Colors.blueAccent, }, ); @@ -51,58 +52,11 @@ void main() { final context = tester.element(find.byType(Container)); - final mixData = MixData.create(context, StyleMix.empty); + final mixData = MixData.create(context, const StyleMix.empty()); expect(mixData.tokens.colorToken(redcolorToken), Colors.redAccent); expect(mixData.tokens.colorToken(greencolorToken), Colors.green); expect(mixData.tokens.colorToken(bluecolorToken), Colors.blueAccent); }); }); - - group('ColorToken.resolvable', () { - test('Constructor assigns name correctly', () { - final colorToken = ColorToken.resolvable('testName', (_) => Colors.red); - expect(colorToken.name, 'testName'); - }); - - // Equality Operator Test - test('Equality operator works correctly', () { - final colorToken1 = ColorToken.resolvable('testName', (_) => Colors.red); - final colorToken2 = ColorToken.resolvable('testName', (_) => Colors.red); - final colorToken3 = - ColorToken.resolvable('differentName', (_) => Colors.red); - - expect(colorToken1 == colorToken2, isTrue); - expect(colorToken1 == colorToken3, isFalse); - expect(colorToken1 == Object(), isFalse); - }); - - // HashCode Test - test('hashCode is consistent with name', () { - final colorToken1 = ColorToken.resolvable('testName', (_) => Colors.red); - final colorToken2 = ColorToken.resolvable('testName', (_) => Colors.red); - final colorToken3 = - ColorToken.resolvable('differentName', (_) => Colors.red); - - expect(colorToken1.hashCode, colorToken2.hashCode); - expect(colorToken1.hashCode, isNot(colorToken3.hashCode)); - }); - - testWidgets('Test it resolves correctly', (tester) async { - final redcolorToken = ColorToken.resolvable('red', (_) => Colors.red); - final greencolorToken = - ColorToken.resolvable('green', (_) => Colors.green); - final bluecolorToken = ColorToken.resolvable('blue', (_) => Colors.blue); - - await tester.pumpMaterialApp(Container()); - - final context = tester.element(find.byType(Container)); - - final mixData = MixData.create(context, StyleMix.empty); - - expect(mixData.tokens.colorToken(redcolorToken), Colors.red); - expect(mixData.tokens.colorToken(greencolorToken), Colors.green); - expect(mixData.tokens.colorToken(bluecolorToken), Colors.blue); - }); - }); } diff --git a/test/src/theme/tokens/material_tokens_test.dart b/test/src/theme/tokens/material_tokens_test.dart index ada26d628..5fa86991a 100644 --- a/test/src/theme/tokens/material_tokens_test.dart +++ b/test/src/theme/tokens/material_tokens_test.dart @@ -4,120 +4,123 @@ import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:mix/mix.dart'; +import '../../../helpers/testing_utils.dart'; + void main() { // Create a test that checks if all the values of these tokens match the ThemeData from the MaterialApp group('Material tokens', () { + Value refResolver, T extends MixToken, + Value>(R ref, BuildContext context) { + return ref.token.resolve(context); + } + testWidgets('colors', (tester) async { final theme = ThemeData.light(); - await tester.pumpWidget( - MaterialApp(theme: theme, home: Container()), + await tester.pumpWithMixTheme( + Container(), + theme: MixThemeData.withMaterialTokens().copyWith(), ); final context = tester.element(find.byType(Container)); - final colors = MaterialTokens().colors; - expect((colors.primary() as ColorRef).resolve(context), - theme.colorScheme.primary); - expect((colors.secondary() as ColorRef).resolve(context), + final colors = const MaterialTokens().colors; + + expect(refResolver(colors.primary(), context), theme.colorScheme.primary); + expect(refResolver(colors.secondary(), context), theme.colorScheme.secondary); - expect((colors.tertiary() as ColorRef).resolve(context), - theme.colorScheme.tertiary); - expect((colors.surface() as ColorRef).resolve(context), - theme.colorScheme.surface); - expect((colors.background() as ColorRef).resolve(context), + expect( + refResolver(colors.tertiary(), context), theme.colorScheme.tertiary); + expect(refResolver(colors.surface(), context), theme.colorScheme.surface); + expect(refResolver(colors.background(), context), theme.colorScheme.background); - expect((colors.error() as ColorRef).resolve(context), - theme.colorScheme.error); - expect((colors.onPrimary() as ColorRef).resolve(context), + expect(refResolver(colors.error(), context), theme.colorScheme.error); + expect(refResolver(colors.onPrimary(), context), theme.colorScheme.onPrimary); - expect((colors.onSecondary() as ColorRef).resolve(context), + expect(refResolver(colors.onSecondary(), context), theme.colorScheme.onSecondary); - expect((colors.onTertiary() as ColorRef).resolve(context), + expect(refResolver(colors.onTertiary(), context), theme.colorScheme.onTertiary); - expect((colors.onSurface() as ColorRef).resolve(context), + expect(refResolver(colors.onSurface(), context), theme.colorScheme.onSurface); - expect( - (colors.onBackground() as ColorRef).resolve(context), - theme.colorScheme.onBackground, - ); - expect((colors.onError() as ColorRef).resolve(context), - theme.colorScheme.onError); + expect(refResolver(colors.onBackground(), context), + theme.colorScheme.onBackground); + expect(refResolver(colors.onError(), context), theme.colorScheme.onError); }); testWidgets('Material 3 textStyles', (tester) async { - await tester.pumpWidget( - MaterialApp( - theme: ThemeData.light(useMaterial3: true), home: Container()), + await tester.pumpWithMixTheme( + Container(), + theme: MixThemeData.withMaterialTokens(), ); final context = tester.element(find.byType(Container)); final theme = Theme.of(context); - final textStyles = MaterialTokens().textStyles; - expect((textStyles.displayLarge() as TextStyleRef).resolve(context), + final textStyles = const MaterialTokens().textStyles; + expect(refResolver(textStyles.displayLarge(), context), theme.textTheme.displayLarge); - expect((textStyles.displayMedium() as TextStyleRef).resolve(context), + expect(refResolver(textStyles.displayMedium(), context), theme.textTheme.displayMedium); - expect((textStyles.displaySmall() as TextStyleRef).resolve(context), + expect(refResolver(textStyles.displaySmall(), context), theme.textTheme.displaySmall); - expect((textStyles.headlineLarge() as TextStyleRef).resolve(context), + expect(refResolver(textStyles.headlineLarge(), context), theme.textTheme.headlineLarge); - expect((textStyles.headlineMedium() as TextStyleRef).resolve(context), + expect(refResolver(textStyles.headlineMedium(), context), theme.textTheme.headlineMedium); - expect((textStyles.headlineSmall() as TextStyleRef).resolve(context), + expect(refResolver(textStyles.headlineSmall(), context), theme.textTheme.headlineSmall); - expect((textStyles.titleLarge() as TextStyleRef).resolve(context), + expect(refResolver(textStyles.titleLarge(), context), theme.textTheme.titleLarge); - expect((textStyles.titleMedium() as TextStyleRef).resolve(context), + expect(refResolver(textStyles.titleMedium(), context), theme.textTheme.titleMedium); - expect((textStyles.titleSmall() as TextStyleRef).resolve(context), + expect(refResolver(textStyles.titleSmall(), context), theme.textTheme.titleSmall); - expect((textStyles.bodyLarge() as TextStyleRef).resolve(context), + expect(refResolver(textStyles.bodyLarge(), context), theme.textTheme.bodyLarge); - expect((textStyles.bodyMedium() as TextStyleRef).resolve(context), + expect(refResolver(textStyles.bodyMedium(), context), theme.textTheme.bodyMedium); - expect((textStyles.bodySmall() as TextStyleRef).resolve(context), + expect(refResolver(textStyles.bodySmall(), context), theme.textTheme.bodySmall); - expect((textStyles.labelLarge() as TextStyleRef).resolve(context), + expect(refResolver(textStyles.labelLarge(), context), theme.textTheme.labelLarge); - expect((textStyles.labelMedium() as TextStyleRef).resolve(context), + expect(refResolver(textStyles.labelMedium(), context), theme.textTheme.labelMedium); - expect((textStyles.labelSmall() as TextStyleRef).resolve(context), + expect(refResolver(textStyles.labelSmall(), context), theme.textTheme.labelSmall); }); testWidgets('Material 2 text styles', (tester) async { - await tester.pumpWidget( - MaterialApp(theme: ThemeData.light(), home: Container()), + await tester.pumpWithMixTheme( + Container(), + theme: MixThemeData.withMaterialTokens(), ); final context = tester.element(find.byType(Container)); final theme = Theme.of(context); - final textStyles = MaterialTokens().textStyles; - expect((textStyles.headline1() as TextStyleRef).resolve(context), + final textStyles = const MaterialTokens().textStyles; + expect(refResolver(textStyles.headline1(), context), theme.textTheme.headline1); - expect((textStyles.headline2() as TextStyleRef).resolve(context), + expect(refResolver(textStyles.headline2(), context), theme.textTheme.headline2); - expect((textStyles.headline3() as TextStyleRef).resolve(context), + expect(refResolver(textStyles.headline3(), context), theme.textTheme.headline3); - expect((textStyles.headline4() as TextStyleRef).resolve(context), + expect(refResolver(textStyles.headline4(), context), theme.textTheme.headline4); - expect((textStyles.headline5() as TextStyleRef).resolve(context), + expect(refResolver(textStyles.headline5(), context), theme.textTheme.headline5); - expect((textStyles.headline6() as TextStyleRef).resolve(context), + expect(refResolver(textStyles.headline6(), context), theme.textTheme.headline6); - expect((textStyles.subtitle1() as TextStyleRef).resolve(context), + expect(refResolver(textStyles.subtitle1(), context), theme.textTheme.subtitle1); - expect((textStyles.subtitle2() as TextStyleRef).resolve(context), + expect(refResolver(textStyles.subtitle2(), context), theme.textTheme.subtitle2); - expect((textStyles.bodyText1() as TextStyleRef).resolve(context), + expect(refResolver(textStyles.bodyText1(), context), theme.textTheme.bodyText1); - expect((textStyles.bodyText2() as TextStyleRef).resolve(context), + expect(refResolver(textStyles.bodyText2(), context), theme.textTheme.bodyText2); - expect((textStyles.caption() as TextStyleRef).resolve(context), - theme.textTheme.caption); - expect((textStyles.button() as TextStyleRef).resolve(context), - theme.textTheme.button); - expect((textStyles.overline() as TextStyleRef).resolve(context), + expect( + refResolver(textStyles.caption(), context), theme.textTheme.caption); + expect(refResolver(textStyles.button(), context), theme.textTheme.button); + expect(refResolver(textStyles.overline(), context), theme.textTheme.overline); }); }); diff --git a/test/src/theme/tokens/radius_token_test.dart b/test/src/theme/tokens/radius_token_test.dart index 76678c6f4..8328ff0aa 100644 --- a/test/src/theme/tokens/radius_token_test.dart +++ b/test/src/theme/tokens/radius_token_test.dart @@ -7,14 +7,14 @@ import '../../../helpers/testing_utils.dart'; void main() { group('RadiusToken', () { test('Constructor assigns name correctly', () { - const radiusRef = RadiusToken.name('testName'); + const radiusRef = RadiusToken('testName'); expect(radiusRef.name, 'testName'); }); test('Equality operator works correctly', () { - const radiusRef1 = RadiusToken.name('testName'); - const radiusRef2 = RadiusToken.name('testName'); - const radiusRef3 = RadiusToken.name('differentName'); + const radiusRef1 = RadiusToken('testName'); + const radiusRef2 = RadiusToken('testName'); + const radiusRef3 = RadiusToken('differentName'); expect(radiusRef1 == radiusRef2, isTrue); expect(radiusRef1 == radiusRef3, isFalse); @@ -22,23 +22,23 @@ void main() { }); test('hashCode is consistent with name', () { - const radiusRef1 = RadiusToken.name('testName'); - const radiusRef2 = RadiusToken.name('testName'); - const radiusRef3 = RadiusToken.name('differentName'); + const radiusRef1 = RadiusToken('testName'); + const radiusRef2 = RadiusToken('testName'); + const radiusRef3 = RadiusToken('differentName'); expect(radiusRef1.hashCode, radiusRef2.hashCode); expect(radiusRef1.hashCode, isNot(radiusRef3.hashCode)); }); testWidgets('Test it resolves correctly', (tester) async { - const redRadiusRef = RadiusToken.name('red'); - const greenRadiusRef = RadiusToken.name('green'); - const blueRadiusRef = RadiusToken.name('blue'); - final theme = MixThemeData.tokenMap( + const redRadiusRef = RadiusToken('red'); + const greenRadiusRef = RadiusToken('green'); + const blueRadiusRef = RadiusToken('blue'); + final theme = MixThemeData( radii: { - redRadiusRef: (_) => const Radius.circular(1), - greenRadiusRef: (_) => const Radius.circular(2), - blueRadiusRef: (_) => const Radius.circular(3), + redRadiusRef: const Radius.circular(1), + greenRadiusRef: const Radius.circular(2), + blueRadiusRef: const Radius.circular(3), }, ); @@ -46,60 +46,7 @@ void main() { final context = tester.element(find.byType(Container)); - final mixData = MixData.create(context, StyleMix.empty); - - expect(mixData.tokens.radiiToken(redRadiusRef), const Radius.circular(1)); - expect( - mixData.tokens.radiiToken(greenRadiusRef), const Radius.circular(2)); - expect( - mixData.tokens.radiiToken(blueRadiusRef), const Radius.circular(3)); - }); - }); - - group('RadiusToken.resolvable', () { - test('Constructor assigns name correctly', () { - final radiusRef = RadiusToken.resolvable('testName', (_) => Radius.zero); - expect(radiusRef.name, 'testName'); - }); - - test('Equality operator works correctly', () { - final radiusRef1 = - RadiusToken.resolvable('testName', (_) => const Radius.circular(1)); - final radiusRef2 = - RadiusToken.resolvable('testName', (_) => const Radius.circular(1)); - final radiusRef3 = RadiusToken.resolvable( - 'differentName', (_) => const Radius.circular(1)); - - expect(radiusRef1 == radiusRef2, isTrue); - expect(radiusRef1 == radiusRef3, isFalse); - expect(radiusRef1 == Object(), isFalse); - }); - - test('hashCode is consistent with name', () { - final radiusRef1 = - RadiusToken.resolvable('testName', (_) => const Radius.circular(1)); - final radiusRef2 = - RadiusToken.resolvable('testName', (_) => const Radius.circular(1)); - final radiusRef3 = RadiusToken.resolvable( - 'differentName', (_) => const Radius.circular(1)); - - expect(radiusRef1.hashCode, radiusRef2.hashCode); - expect(radiusRef1.hashCode, isNot(radiusRef3.hashCode)); - }); - - testWidgets('Test it resolves correctly', (tester) async { - final redRadiusRef = - RadiusToken.resolvable('red', (_) => const Radius.circular(1)); - final greenRadiusRef = - RadiusToken.resolvable('green', (_) => const Radius.circular(2)); - final blueRadiusRef = - RadiusToken.resolvable('blue', (_) => const Radius.circular(3)); - - await tester.pumpMaterialApp(Container()); - - final context = tester.element(find.byType(Container)); - - final mixData = MixData.create(context, StyleMix.empty); + final mixData = MixData.create(context, const StyleMix.empty()); expect(mixData.tokens.radiiToken(redRadiusRef), const Radius.circular(1)); expect( diff --git a/test/src/theme/tokens/space_token_test.dart b/test/src/theme/tokens/space_token_test.dart index 3754df1e0..b28970fcb 100644 --- a/test/src/theme/tokens/space_token_test.dart +++ b/test/src/theme/tokens/space_token_test.dart @@ -7,7 +7,7 @@ void main() { group('SpaceToken tests', () { test('SpaceToken.xsmall() returns correct value', () { expect(SpaceToken.xsmall(), SpaceToken.xsmall()); - expect(const SpaceToken('mix.space.xsmall', 4.0), SpaceToken.xsmall); + expect(const SpaceToken('mix.space.xsmall'), SpaceToken.xsmall); expect('mix.space.xsmall', SpaceToken.xsmall.name); expect('mix.space.xsmall'.hashCode, SpaceToken.xsmall.name.hashCode); @@ -17,7 +17,7 @@ void main() { test('SpaceToken.small() returns correct value', () { expect(SpaceToken.small(), SpaceToken.small()); - expect(const SpaceToken('mix.space.small', 8.0), SpaceToken.small); + expect(const SpaceToken('mix.space.small'), SpaceToken.small); expect('mix.space.small', SpaceToken.small.name); expect('mix.space.small'.hashCode, SpaceToken.small.name.hashCode); @@ -27,7 +27,7 @@ void main() { test('SpaceToken.medium() returns correct value', () { expect(SpaceToken.medium(), SpaceToken.medium()); - expect(const SpaceToken('mix.space.medium', 16.0), SpaceToken.medium); + expect(const SpaceToken('mix.space.medium'), SpaceToken.medium); expect('mix.space.medium', SpaceToken.medium.name); expect('mix.space.medium'.hashCode, SpaceToken.medium.name.hashCode); @@ -37,14 +37,14 @@ void main() { test('SpaceToken.large() returns correct value', () { expect(SpaceToken.large(), SpaceToken.large()); - expect(const SpaceToken('mix.space.large', 24.0), SpaceToken.large); + expect(const SpaceToken('mix.space.large'), SpaceToken.large); expect('mix.space.large', SpaceToken.large.name); expect('mix.space.large'.hashCode, SpaceToken.large.name.hashCode); }); test('SpaceToken.xlarge() returns correct value', () { expect(SpaceToken.xlarge(), SpaceToken.xlarge()); - expect(const SpaceToken('mix.space.xlarge', 32.0), SpaceToken.xlarge); + expect(const SpaceToken('mix.space.xlarge'), SpaceToken.xlarge); expect('mix.space.xlarge', SpaceToken.xlarge.name); expect('mix.space.xlarge'.hashCode, SpaceToken.xlarge.name.hashCode); @@ -54,7 +54,7 @@ void main() { test('SpaceToken.xxlarge() returns correct value', () { expect(SpaceToken.xxlarge(), SpaceToken.xxlarge()); - expect(const SpaceToken('mix.space.xxlarge', 40.0), SpaceToken.xxlarge); + expect(const SpaceToken('mix.space.xxlarge'), SpaceToken.xxlarge); expect('mix.space.xxlarge', SpaceToken.xxlarge.name); expect('mix.space.xxlarge'.hashCode, SpaceToken.xxlarge.name.hashCode); diff --git a/test/src/theme/tokens/text_style_token_test.dart b/test/src/theme/tokens/text_style_token_test.dart index 47de709f6..65b7d83fe 100644 --- a/test/src/theme/tokens/text_style_token_test.dart +++ b/test/src/theme/tokens/text_style_token_test.dart @@ -10,14 +10,14 @@ import '../../../helpers/testing_utils.dart'; void main() { group('TextStyleToken', () { test('Constructor assigns name correctly', () { - const textStyleToken = TextStyleToken.name('testName'); + const textStyleToken = TextStyleToken('testName'); expect(textStyleToken.name, 'testName'); }); test('Equality operator works correctly', () { - const textStyleToken1 = TextStyleToken.name('testName'); - const textStyleToken2 = TextStyleToken.name('testName'); - const textStyleToken3 = TextStyleToken.name('differentName'); + const textStyleToken1 = TextStyleToken('testName'); + const textStyleToken2 = TextStyleToken('testName'); + const textStyleToken3 = TextStyleToken('differentName'); expect(textStyleToken1 == textStyleToken2, isTrue); expect(textStyleToken1 == textStyleToken3, isFalse); @@ -25,23 +25,23 @@ void main() { }); test('hashCode is consistent with name', () { - const textStyleToken1 = TextStyleToken.name('testName'); - const textStyleToken2 = TextStyleToken.name('testName'); - const textStyleToken3 = TextStyleToken.name('differentName'); + const textStyleToken1 = TextStyleToken('testName'); + const textStyleToken2 = TextStyleToken('testName'); + const textStyleToken3 = TextStyleToken('differentName'); expect(textStyleToken1.hashCode, textStyleToken2.hashCode); expect(textStyleToken1.hashCode, isNot(textStyleToken3.hashCode)); }); testWidgets('Test it resolves correctly', (tester) async { - const redtextStyleToken = TextStyleToken.name('red'); - const greentextStyleToken = TextStyleToken.name('green'); - const bluetextStyleToken = TextStyleToken.name('blue'); - final theme = MixThemeData.tokenMap( + const redtextStyleToken = TextStyleToken('red'); + const greentextStyleToken = TextStyleToken('green'); + const bluetextStyleToken = TextStyleToken('blue'); + final theme = MixThemeData( textStyles: { - redtextStyleToken: (_) => const TextStyle(color: Colors.red), - greentextStyleToken: (_) => const TextStyle(color: Colors.green), - bluetextStyleToken: (_) => const TextStyle(color: Colors.blue), + redtextStyleToken: const TextStyle(color: Colors.red), + greentextStyleToken: const TextStyle(color: Colors.green), + bluetextStyleToken: const TextStyle(color: Colors.blue), }, ); @@ -49,63 +49,7 @@ void main() { final context = tester.element(find.byType(Container)); - final mixData = MixData.create(context, StyleMix.empty); - - expect(mixData.tokens.textStyleToken(redtextStyleToken), - const TextStyle(color: Colors.red)); - expect(mixData.tokens.textStyleToken(greentextStyleToken), - const TextStyle(color: Colors.green)); - expect(mixData.tokens.textStyleToken(bluetextStyleToken), - const TextStyle(color: Colors.blue)); - }); - }); - - // Resolvable TextStyle Token - group('TextStyleResolvableToken', () { - test('Constructor assigns name correctly', () { - final textStyleToken = - TextStyleToken.resolvable('testName', (_) => const TextStyle()); - expect(textStyleToken.name, 'testName'); - }); - - test('Equality operator works correctly', () { - final textStyleToken1 = - TextStyleToken.resolvable('testName', (_) => const TextStyle()); - final textStyleToken2 = - TextStyleToken.resolvable('testName', (_) => const TextStyle()); - final textStyleToken3 = - TextStyleToken.resolvable('differentName', (_) => const TextStyle()); - - expect(textStyleToken1 == textStyleToken2, isTrue); - expect(textStyleToken1 == textStyleToken3, isFalse); - expect(textStyleToken1 == Object(), isFalse); - }); - - test('hashCode is consistent with name', () { - final textStyleToken1 = - TextStyleToken.resolvable('testName', (_) => const TextStyle()); - final textStyleToken2 = - TextStyleToken.resolvable('testName', (_) => const TextStyle()); - final textStyleToken3 = - TextStyleToken.resolvable('differentName', (_) => const TextStyle()); - - expect(textStyleToken1.hashCode, textStyleToken2.hashCode); - expect(textStyleToken1.hashCode, isNot(textStyleToken3.hashCode)); - }); - - testWidgets('Test it resolves correctly', (tester) async { - final redtextStyleToken = TextStyleToken.resolvable( - 'red', (_) => const TextStyle(color: Colors.red)); - final greentextStyleToken = TextStyleToken.resolvable( - 'green', (_) => const TextStyle(color: Colors.green)); - final bluetextStyleToken = TextStyleToken.resolvable( - 'blue', (_) => const TextStyle(color: Colors.blue)); - - await tester.pumpMaterialApp(Container()); - - final context = tester.element(find.byType(Container)); - - final mixData = MixData.create(context, StyleMix.empty); + final mixData = MixData.create(context, const StyleMix.empty()); expect(mixData.tokens.textStyleToken(redtextStyleToken), const TextStyle(color: Colors.red)); diff --git a/test/src/widgets/pressable/gesture_state.notifier_test.dart b/test/src/widgets/pressable/gesture_state.notifier_test.dart new file mode 100644 index 000000000..13d9c7996 --- /dev/null +++ b/test/src/widgets/pressable/gesture_state.notifier_test.dart @@ -0,0 +1,68 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:mix/mix.dart'; + +import '../../../helpers/testing_utils.dart'; + +void main() { + group('PressableNotifier', () { + const gestureData = GestureData( + state: GestureState.pressed, + status: GestureStatus.enabled, + focus: true, + hover: false, + ); + test('constructor', () { + final notifier = GestureStateNotifier( + data: gestureData, + child: Container(), + ); + + expect(notifier.data.state, GestureState.pressed); + expect(notifier.data.focus, true); + expect(notifier.child, isA()); + }); + + test('of', () { + final notifier = GestureStateNotifier( + data: gestureData, + child: Container(), + ); + + final otherNotifier = GestureStateNotifier( + data: const GestureData( + focus: false, + state: GestureState.none, + status: GestureStatus.disabled, + hover: false, + ), + child: Container(), + ); + + final sameNotifier = GestureStateNotifier( + data: gestureData, + child: Container(), + ); + + expect(notifier.updateShouldNotify(otherNotifier), true); + expect(notifier.updateShouldNotify(sameNotifier), false); + expect(GestureStateNotifier.of(MockBuildContext()), null); + }); + + testWidgets('can get it from context', (tester) async { + await tester.pumpWithPressable( + Container(), + state: GestureState.pressed, + focus: true, + ); + + final context = tester.element(find.byType(Container)); + + final notifier = GestureStateNotifier.of(context); + + expect(notifier, isA()); + expect(notifier!.state, GestureState.pressed); + expect(notifier.focus, true); + }); + }); +} diff --git a/test/src/utils/pressable_util_test.dart b/test/src/widgets/pressable/gesture_util_test.dart similarity index 91% rename from test/src/utils/pressable_util_test.dart rename to test/src/widgets/pressable/gesture_util_test.dart index af6fd62f8..e6b224a45 100644 --- a/test/src/utils/pressable_util_test.dart +++ b/test/src/widgets/pressable/gesture_util_test.dart @@ -3,7 +3,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:mix/mix.dart'; -import '../../helpers/testing_utils.dart'; +import '../../../helpers/testing_utils.dart'; void main() { group('Pressable Util', () { @@ -13,7 +13,7 @@ void main() { testWidgets('press state', (tester) async { await tester.pumpWithPressable( Container(), - state: PressableState.pressed, + state: GestureState.pressed, focus: true, ); @@ -30,7 +30,7 @@ void main() { testWidgets('long press state', (tester) async { await tester.pumpWithPressable( Container(), - state: PressableState.longPressed, + state: GestureState.longPressed, focus: true, ); @@ -50,7 +50,7 @@ void main() { testWidgets('hover state', (tester) async { await tester.pumpWithPressable( Container(), - state: PressableState.hover, + hover: true, focus: true, ); @@ -67,7 +67,7 @@ void main() { testWidgets('disabled state', (tester) async { await tester.pumpWithPressable( Container(), - state: PressableState.disabled, + status: GestureStatus.disabled, focus: true, ); @@ -88,7 +88,7 @@ void main() { testWidgets('enabled state', (tester) async { await tester.pumpWithPressable( Container(), - state: PressableState.pressed, + state: GestureState.pressed, focus: true, ); @@ -101,7 +101,7 @@ void main() { onEnabledAttr.value, StyleMix(attribute1, attribute2, attribute3), ); - expect(onEnabledAttr.variant.name, 'not(on-disabled)'); + expect(onEnabledAttr.variant.name, 'on-enabled'); expect(onEnabledAttr.variant.when(context), true); }); @@ -109,7 +109,7 @@ void main() { testWidgets('focus state', (tester) async { await tester.pumpWithPressable( Container(), - state: PressableState.pressed, + state: GestureState.pressed, focus: true, ); diff --git a/test/src/widgets/pressable/pressable_widget_test.dart b/test/src/widgets/pressable/gesture_widget_test.dart similarity index 79% rename from test/src/widgets/pressable/pressable_widget_test.dart rename to test/src/widgets/pressable/gesture_widget_test.dart index 518977c8f..a8c11e132 100644 --- a/test/src/widgets/pressable/pressable_widget_test.dart +++ b/test/src/widgets/pressable/gesture_widget_test.dart @@ -22,6 +22,7 @@ void main() { ), Pressable( onPressed: null, + disabled: true, child: Container( key: secondKey, ), @@ -34,12 +35,12 @@ void main() { final firstContext = tester.element(find.byKey(firstKey)); final secondContext = tester.element(find.byKey(secondKey)); - final firstNotifier = PressableNotifier.of(firstContext); - final secondNotifier = PressableNotifier.of(secondContext); + final firstNotifier = GestureStateNotifier.of(firstContext); + final secondNotifier = GestureStateNotifier.of(secondContext); expect(onEnabledAttr.when(firstContext), true); - expect(firstNotifier!.state, PressableState.inactive); + expect(firstNotifier!.status, GestureStatus.enabled); expect(onEnabledAttr.when(secondContext), false); - expect(secondNotifier!.state, PressableState.disabled); + expect(secondNotifier!.status, GestureStatus.disabled); }); } diff --git a/test/src/widgets/pressable/pressable.notifier_test.dart b/test/src/widgets/pressable/pressable.notifier_test.dart deleted file mode 100644 index 2d2f39cc9..000000000 --- a/test/src/widgets/pressable/pressable.notifier_test.dart +++ /dev/null @@ -1,61 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_test/flutter_test.dart'; -import 'package:mix/mix.dart'; - -import '../../../helpers/testing_utils.dart'; - -void main() { - group('PressableNotifier', () { - test('constructor', () { - final notifier = PressableNotifier( - state: PressableState.pressed, - focus: true, - child: Container(), - ); - - expect(notifier.state, PressableState.pressed); - expect(notifier.focus, true); - expect(notifier.child, isA()); - }); - - test('of', () { - final notifier = PressableNotifier( - state: PressableState.pressed, - focus: true, - child: Container(), - ); - - final otherNotifier = PressableNotifier( - state: PressableState.hover, - focus: false, - child: Container(), - ); - - final sameNotifier = PressableNotifier( - focus: true, - state: PressableState.pressed, - child: Container(), - ); - - expect(notifier.updateShouldNotify(otherNotifier), true); - expect(notifier.updateShouldNotify(sameNotifier), false); - expect(PressableNotifier.of(MockBuildContext()), null); - }); - - testWidgets('can get it from context', (tester) async { - await tester.pumpWithPressable( - Container(), - state: PressableState.pressed, - focus: true, - ); - - final context = tester.element(find.byType(Container)); - - final notifier = PressableNotifier.of(context); - - expect(notifier, isA()); - expect(notifier!.state, PressableState.pressed); - expect(notifier.focus, true); - }); - }); -} diff --git a/website/pages/docs/concepts/variants.mdx b/website/pages/docs/concepts/variants.mdx index b13d42627..a91f74599 100644 --- a/website/pages/docs/concepts/variants.mdx +++ b/website/pages/docs/concepts/variants.mdx @@ -11,6 +11,8 @@ import Code from "../../../components/Code.js"; Variants in Mix are a foundational concept for creating dynamic and modular style definitions. They enable developers to encapsulate and manage groups of styling attributes, which can be applied to various aspects of a Flutter application's UI. +- Variants could be also use-cases for Design Systems + ## The Role of Variants Variants allow for the efficient organization of style attributes, facilitating the easy application and switching between different style sets. This approach provides a streamlined method for handling diverse styling requirements across different components, contributing to a more maintainable and consistent design system within your applications. By using Variants, developers can craft adaptable and cohesive UI components, enhancing both the functionality and aesthetic of their Flutter projects. diff --git a/website/pages/docs/overview/concepts.mdx b/website/pages/docs/overview/concepts.mdx new file mode 100644 index 000000000..8bee813a5 --- /dev/null +++ b/website/pages/docs/overview/concepts.mdx @@ -0,0 +1,10 @@ +# Concepts + +- Attributes +- Directives +- Variant +- Context Variant +- Tokens +- Refs +- Decorator +- Dtos diff --git a/website/pages/docs/overview/overview.mdx b/website/pages/docs/overview/overview.mdx new file mode 100644 index 000000000..07dd0c5c7 --- /dev/null +++ b/website/pages/docs/overview/overview.mdx @@ -0,0 +1 @@ +# Overview diff --git a/website/pages/docs/overview/why-mix.mdx b/website/pages/docs/overview/why-mix.mdx new file mode 100644 index 000000000..cb28a17cd --- /dev/null +++ b/website/pages/docs/overview/why-mix.mdx @@ -0,0 +1,100 @@ +--- +id: why-mix +title: "Why Mix?" +--- + +## With and without Mix + +Mix provides a lot of different benefits on how you can define and organize your design tokens, and no documentation would be complete without a syntax comparison between **Mix vs. Without Mix**. + +Let's go ahead and take a look at the code. Don't worry about understanding each line, the docs will go into more detail about each item. + +### With Mix + +```dart +class CustomMixWidget extends StatelessWidget { + const CustomMixWidget({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + final style = StyleMix( + height(100), + animated(), + marginY(10), + elevation(10), + borderRadius(10), + backgroundColor(MaterialTokens.colorScheme.primary), + textStyle($button), + textStyle(color: $onPrimary), + onHover( + elevation(2), + padding(20), + backgroundColor($secondary), + textStyle(color: $onSecondary), + ), + ); + return Box( + style: style, + child: const TextMix('Custom Widget'), + ); + } +} +``` + +### Without Mix + +```dart +class CustomWidget extends StatefulWidget { + const CustomWidget({ + Key? key, + }) : super(key: key); + + @override + _CustomWidgetState createState() => _CustomWidgetState(); +} + +class _CustomWidgetState extends State { + bool _isHover = false; + @override + void initState() { + super.initState(); + } + + @override + Widget build(BuildContext context) { + final colorScheme = Theme.of(context).colorScheme; + + return MouseRegion( + onEnter: (event) { + setState(() => _isHover = true); + }, + onExit: (event) { + setState(() => _isHover = false); + }, + child: Material( + elevation: _isHover ? 2 : 10, + child: AnimatedContainer( + curve: Curves.linear, + duration: const Duration(milliseconds: 100), + height: 100, + padding: + _isHover ? const EdgeInsets.all(20) : const EdgeInsets.all(0), + margin: const EdgeInsets.symmetric(vertical: 10), + decoration: BoxDecoration( + color: _isHover ? colorScheme.secondary : colorScheme.primary, + borderRadius: BorderRadius.circular(10), + ), + child: Text( + 'Custom Widget', + style: Theme.of(context).textTheme.button?.copyWith( + color: _isHover + ? colorScheme.onSecondary + : colorScheme.onPrimary, + ), + ), + ), + ), + ); + } +} +``` diff --git a/website/readme.md b/website/readme.md index 5d5dde8d9..53aecc08b 100644 --- a/website/readme.md +++ b/website/readme.md @@ -35,4 +35,4 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d -This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome! \ No newline at end of file +This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome!