@syncedco/flow 0.3.1 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -19,6 +19,8 @@
19
19
  --step-6: clamp(2.986rem, 2.5863rem + 1.7763vw, 4.2915rem);
20
20
  --step-7: clamp(3.5832rem, 3.0379rem + 2.4235vw, 5.3644rem);
21
21
  --step-8: clamp(4.2998rem, 3.5634rem + 3.2731vw, 6.7055rem);
22
+ --type-caption-sm: var(--step--2);
23
+ --text-base: var(--step-0);
22
24
 
23
25
  --space-3xs: clamp(0.25rem, 0.2404rem + 0.0425vw, 0.2813rem);
24
26
  --space-2xs: clamp(0.5rem, 0.4809rem + 0.085vw, 0.5625rem);
@@ -88,7 +90,9 @@
88
90
  --color-destructive: var(--sf-colour-destructive, oklch(55% 0.2 28));
89
91
  --color-destructive-foreground: var(--sf-colour-destructive-foreground, oklch(98% 0.01 95));
90
92
  --color-border: var(--sf-colour-border, oklch(100% 0 0 / 0.12));
93
+ --color-border-subtle: var(--sf-colour-border-subtle, oklch(100% 0 0 / 0.08));
91
94
  --color-input: var(--sf-colour-input, oklch(100% 0 0 / 0.12));
95
+ --color-backdrop: var(--sf-colour-backdrop, oklch(0% 0 0 / 0.56));
92
96
  --color-ring: var(--sf-colour-ring, oklch(69% 0.18 44));
93
97
  --color-heading: var(--sf-colour-heading, oklch(20% 0.02 18));
94
98
  --color-page-text: var(--sf-colour-page-text, oklch(23% 0.02 18));
@@ -97,6 +101,14 @@
97
101
  --color-subdued: var(--sf-colour-subdued, oklch(42% 0.02 20));
98
102
  --color-surface: var(--sf-colour-surface, oklch(96% 0.015 80));
99
103
  --color-surface-alt: var(--sf-colour-surface-alt, oklch(96.6% 0.018 82));
104
+ --color-surface-hover: var(--sf-colour-surface-hover, color-mix(in oklch, var(--color-surface-alt) 86%, var(--color-primary)));
105
+ --color-surface-raised-2: var(--sf-colour-surface-raised-2, color-mix(in oklch, var(--color-surface) 86%, white));
106
+ --color-categorical-1: var(--sf-colour-categorical-1, var(--color-primary));
107
+ --color-categorical-2: var(--sf-colour-categorical-2, var(--color-green));
108
+ --color-categorical-3: var(--sf-colour-categorical-3, var(--color-deco-blue));
109
+ --color-categorical-4: var(--sf-colour-categorical-4, var(--color-deco-lime));
110
+ --color-categorical-5: var(--sf-colour-categorical-5, var(--color-warm-icon));
111
+ --color-categorical-6: var(--sf-colour-categorical-6, var(--color-purple-icon));
100
112
  --color-hero-bg: oklch(8% 0.02 260);
101
113
  --color-green: var(--sf-colour-green, oklch(55% 0.12 148));
102
114
  --color-green-dark: var(--sf-colour-green-dark, oklch(45% 0.12 148));
@@ -172,19 +184,19 @@
172
184
  --color-surface-elevated: var(--sf-colour-surface-elevated);
173
185
  --sf-colour-border: oklch(18% 0.026 250 / 0.12);
174
186
  --color-border: var(--sf-colour-border);
175
- --sf-colour-primary: oklch(68% 0.18 44);
187
+ --sf-colour-primary: oklch(50% 0.16 40);
176
188
  --color-primary: var(--sf-colour-primary);
177
- --sf-colour-primary-hover: oklch(60% 0.17 42);
189
+ --sf-colour-primary-hover: oklch(44% 0.14 40);
178
190
  --color-primary-hover: var(--sf-colour-primary-hover);
179
191
  --sf-colour-primary-foreground: oklch(100% 0 0);
180
192
  --color-primary-foreground: var(--sf-colour-primary-foreground);
181
193
  --sf-colour-accent: oklch(70% 0.12 205);
182
194
  --color-accent: var(--sf-colour-accent);
183
- --sf-colour-link: oklch(58% 0.17 42);
195
+ --sf-colour-link: oklch(50% 0.16 40);
184
196
  --color-link: var(--sf-colour-link);
185
- --sf-colour-link-hover: oklch(68% 0.18 44);
197
+ --sf-colour-link-hover: oklch(44% 0.14 40);
186
198
  --color-link-hover: var(--sf-colour-link-hover);
187
- --sf-colour-ring: oklch(68% 0.18 44);
199
+ --sf-colour-ring: oklch(50% 0.16 40);
188
200
  --color-ring: var(--sf-colour-ring);
189
201
  --sf-button-radius: 0.5rem;
190
202
  --button-radius: 0.5rem;
@@ -202,7 +214,7 @@
202
214
  @layer reset {
203
215
  *, *::before, *::after { box-sizing: border-box; }
204
216
  *:where(:not(dialog)) { margin: 0; }
205
- html { -webkit-text-size-adjust: 100%; text-size-adjust: 100%; }
217
+ html { font-size: 100%; -webkit-text-size-adjust: 100%; text-size-adjust: 100%; }
206
218
  body { min-block-size: 100%; }
207
219
  img, picture, video, canvas, svg { display: block; max-inline-size: 100%; }
208
220
  img, video { block-size: auto; }
@@ -212,11 +224,15 @@
212
224
  }
213
225
 
214
226
  @layer base {
227
+ html {
228
+ font-size: 100%;
229
+ }
230
+
215
231
  body {
216
232
  background: var(--color-background);
217
233
  color: var(--color-foreground);
218
234
  font-family: var(--font-inter, var(--sf-font-sans, ui-sans-serif, system-ui, sans-serif));
219
- font-size: var(--step-0);
235
+ font-size: var(--text-base);
220
236
  line-height: 1.5;
221
237
  font-feature-settings: "rlig" 1, "calt" 1;
222
238
  -webkit-font-smoothing: antialiased;
@@ -244,7 +260,7 @@
244
260
  :where(button:disabled, [aria-disabled="true"]) { cursor: not-allowed; }
245
261
 
246
262
  :where(:focus-visible) {
247
- outline: 2px solid var(--color-ring);
263
+ outline: 0.125rem solid var(--color-ring);
248
264
  outline-offset: .2rem;
249
265
  }
250
266
 
@@ -330,11 +346,47 @@
330
346
  }
331
347
 
332
348
  .sf-app-shell {
349
+ --sf-app-header-height: 4rem;
350
+ --sf-app-sidebar-collapsed-width: 4.75rem;
333
351
  background: var(--color-background);
334
352
  color: var(--color-foreground);
335
353
  display: grid;
336
354
  grid-template-columns: minmax(14rem, var(--sf-app-sidebar-width, 16rem)) minmax(0, 1fr);
337
355
  min-block-size: 100dvh;
356
+ position: relative;
357
+ transition: grid-template-columns var(--duration-normal) var(--ease-standard);
358
+ }
359
+
360
+ .sf-app-header {
361
+ align-items: center;
362
+ background: var(--color-card);
363
+ border-block-end: 1px solid var(--color-border);
364
+ display: flex;
365
+ gap: var(--space-s);
366
+ grid-column: 1 / -1;
367
+ justify-content: space-between;
368
+ min-block-size: var(--sf-app-header-height);
369
+ padding-inline: var(--space-s-m);
370
+ z-index: 20;
371
+ }
372
+
373
+ .sf-app-shell[data-layout~="fixed-header"] {
374
+ grid-template-rows: var(--sf-app-header-height) minmax(0, 1fr);
375
+ }
376
+
377
+ .sf-app-shell[data-layout~="fixed-header"] .sf-app-header {
378
+ inset-block-start: 0;
379
+ position: sticky;
380
+ }
381
+
382
+ .sf-app-shell[data-layout~="fixed-header"] .sf-app-sidebar {
383
+ inset-block-start: var(--sf-app-header-height);
384
+ max-block-size: calc(100dvh - var(--sf-app-header-height));
385
+ min-block-size: calc(100dvh - var(--sf-app-header-height));
386
+ }
387
+
388
+ .sf-app-shell[data-collapsed="true"] {
389
+ grid-template-columns: var(--sf-app-sidebar-collapsed-width) minmax(0, 1fr);
338
390
  }
339
391
 
340
392
  .sf-app-sidebar {
@@ -350,6 +402,7 @@
350
402
  padding: var(--space-s);
351
403
  position: sticky;
352
404
  inset-block-start: 0;
405
+ transition: transform var(--duration-normal) var(--ease-standard), inline-size var(--duration-normal) var(--ease-standard);
353
406
  }
354
407
 
355
408
  .sf-app-sidebar__brand {
@@ -402,6 +455,58 @@
402
455
  padding: var(--sf-app-main-padding, var(--space-m-l));
403
456
  }
404
457
 
458
+ .sf-app-shell[data-collapsed="true"] .sf-app-sidebar {
459
+ overflow-x: hidden;
460
+ }
461
+
462
+ .sf-app-shell[data-collapsed="true"] .sf-app-sidebar__brand,
463
+ .sf-app-shell[data-collapsed="true"] .sf-app-sidebar .sf-nav__link {
464
+ justify-content: center;
465
+ }
466
+
467
+ .sf-app-shell[data-collapsed="true"] [data-hide-collapsed="true"] {
468
+ display: none;
469
+ }
470
+
471
+ .sf-app-backdrop {
472
+ display: none;
473
+ }
474
+
475
+ @media (max-width: 48rem) {
476
+ .sf-app-shell[data-mobile="drawer"] {
477
+ display: block;
478
+ }
479
+
480
+ .sf-app-shell[data-mobile="drawer"] .sf-app-header {
481
+ position: sticky;
482
+ inset-block-start: 0;
483
+ }
484
+
485
+ .sf-app-shell[data-mobile="drawer"] .sf-app-sidebar {
486
+ box-shadow: var(--shadow-xl);
487
+ inline-size: min(18rem, calc(100vw - var(--space-l)));
488
+ inset-block: 0;
489
+ inset-inline-start: 0;
490
+ max-block-size: none;
491
+ min-block-size: 100dvh;
492
+ position: fixed;
493
+ transform: translateX(-100%);
494
+ z-index: 30;
495
+ }
496
+
497
+ .sf-app-shell[data-mobile="drawer"][data-sidebar-open="true"] .sf-app-sidebar {
498
+ transform: translateX(0);
499
+ }
500
+
501
+ .sf-app-shell[data-mobile="drawer"][data-sidebar-open="true"] .sf-app-backdrop {
502
+ background: var(--color-backdrop);
503
+ display: block;
504
+ inset: 0;
505
+ position: fixed;
506
+ z-index: 25;
507
+ }
508
+ }
509
+
405
510
  .sf-grid {
406
511
  display: grid;
407
512
  gap: var(--grid-gutter);
@@ -725,9 +830,279 @@
725
830
  overflow: hidden;
726
831
  }
727
832
 
833
+ .sf-progress {
834
+ accent-color: var(--progress-color, var(--color-primary));
835
+ block-size: var(--progress-size, .625rem);
836
+ inline-size: 100%;
837
+ }
838
+
839
+ .sf-progress::-webkit-progress-bar {
840
+ background: var(--color-surface-alt);
841
+ border-radius: var(--radius-full);
842
+ }
843
+
844
+ .sf-progress::-webkit-progress-value,
845
+ .sf-progress::-moz-progress-bar {
846
+ background: var(--progress-color, var(--color-primary));
847
+ border-radius: var(--radius-full);
848
+ }
849
+
850
+ .sf-skeleton {
851
+ background: color-mix(in oklch, var(--color-surface-alt) 82%, var(--color-foreground));
852
+ border-radius: var(--skeleton-radius, var(--radius-md));
853
+ color: transparent;
854
+ min-block-size: var(--skeleton-block-size, 1em);
855
+ }
856
+
857
+ @media (prefers-reduced-motion: no-preference) {
858
+ .sf-skeleton {
859
+ animation: sf-skeleton-pulse 1.4s var(--ease-standard) infinite alternate;
860
+ }
861
+ }
862
+
863
+ @keyframes sf-skeleton-pulse {
864
+ to { opacity: .62; }
865
+ }
866
+
867
+ .sf-filter-bar {
868
+ align-items: end;
869
+ background: var(--color-card);
870
+ border: 1px solid var(--color-border);
871
+ border-radius: var(--radius-lg);
872
+ display: flex;
873
+ flex-wrap: wrap;
874
+ gap: var(--space-xs);
875
+ padding: var(--space-s);
876
+ }
877
+
878
+ .sf-filter-bar > :where(.sf-field, form, label) {
879
+ flex: 1 1 min(100%, 14rem);
880
+ }
881
+
882
+ .sf-filter-bar > :where(.sf-button, button, a) {
883
+ flex: 0 0 auto;
884
+ }
885
+
886
+ .sf-data-table {
887
+ border-collapse: collapse;
888
+ inline-size: 100%;
889
+ min-inline-size: var(--data-table-min, 44rem);
890
+ }
891
+
892
+ .sf-data-table :where(th, td) {
893
+ border-block-end: 1px solid var(--color-border);
894
+ padding-block: var(--data-table-padding-block, var(--space-xs));
895
+ padding-inline: var(--data-table-padding-inline, var(--space-s));
896
+ text-align: start;
897
+ vertical-align: middle;
898
+ }
899
+
900
+ .sf-data-table :where(th) {
901
+ background: var(--color-surface-alt);
902
+ color: var(--color-muted-foreground);
903
+ font-size: var(--step--1);
904
+ font-weight: 800;
905
+ }
906
+
907
+ .sf-data-table :where(tbody tr:hover) {
908
+ background: color-mix(in oklch, var(--color-primary) 6%, transparent);
909
+ }
910
+
911
+ .sf-data-table[data-density="compact"] {
912
+ --data-table-padding-block: var(--space-2xs);
913
+ --data-table-padding-inline: var(--space-xs);
914
+ }
915
+
916
+ .sf-data-table :where(th button, .sf-table-sort) {
917
+ align-items: center;
918
+ background: transparent;
919
+ border: 0;
920
+ color: inherit;
921
+ display: inline-flex;
922
+ font: inherit;
923
+ font-weight: inherit;
924
+ gap: var(--space-3xs);
925
+ padding: 0;
926
+ }
927
+
928
+ .sf-data-table th[aria-sort] :where(button, .sf-table-sort)::after {
929
+ color: var(--color-muted-foreground);
930
+ content: "\2195";
931
+ font-size: var(--step--2);
932
+ }
933
+
934
+ .sf-data-table th[aria-sort="ascending"] :where(button, .sf-table-sort)::after { content: "\2191"; }
935
+ .sf-data-table th[aria-sort="descending"] :where(button, .sf-table-sort)::after { content: "\2193"; }
936
+
937
+ .sf-data-table tr[data-clickable="true"] {
938
+ cursor: pointer;
939
+ }
940
+
941
+ .sf-data-table tr[data-clickable="true"]:focus-within {
942
+ outline: 0.125rem solid var(--color-ring);
943
+ outline-offset: -0.125rem;
944
+ }
945
+
946
+ @container (max-width: 38rem) {
947
+ .sf-table-wrap[data-view="cards"] {
948
+ border: 0;
949
+ overflow: visible;
950
+ }
951
+
952
+ .sf-table-wrap[data-view="cards"] .sf-data-table,
953
+ .sf-table-wrap[data-view="cards"] .sf-data-table :where(thead, tbody, tr, th, td) {
954
+ display: block;
955
+ min-inline-size: 0;
956
+ }
957
+
958
+ .sf-table-wrap[data-view="cards"] .sf-data-table thead {
959
+ display: none;
960
+ }
961
+
962
+ .sf-table-wrap[data-view="cards"] .sf-data-table tr {
963
+ background: var(--color-card);
964
+ border: 1px solid var(--color-border);
965
+ border-radius: var(--radius-lg);
966
+ margin-block-end: var(--space-xs);
967
+ padding: var(--space-xs);
968
+ }
969
+
970
+ .sf-table-wrap[data-view="cards"] .sf-data-table td {
971
+ align-items: center;
972
+ border: 0;
973
+ display: flex;
974
+ gap: var(--space-s);
975
+ justify-content: space-between;
976
+ padding-block: var(--space-2xs);
977
+ padding-inline: 0;
978
+ }
979
+
980
+ .sf-table-wrap[data-view="cards"] .sf-data-table td::before {
981
+ color: var(--color-muted-foreground);
982
+ content: attr(data-label);
983
+ font-size: var(--step--1);
984
+ font-weight: 800;
985
+ }
986
+ }
987
+
988
+ .sf-status {
989
+ align-items: center;
990
+ background: var(--status-bg, var(--color-surface-alt));
991
+ border: 1px solid var(--status-border, var(--color-border));
992
+ border-radius: var(--radius-full);
993
+ color: var(--status-color, var(--color-foreground));
994
+ display: inline-flex;
995
+ font-size: var(--step--1);
996
+ font-weight: 700;
997
+ gap: var(--space-3xs);
998
+ line-height: 1;
999
+ min-block-size: 1.75rem;
1000
+ padding-inline: .7em;
1001
+ }
1002
+
1003
+ .sf-status[data-size="sm"] {
1004
+ font-size: var(--step--2);
1005
+ min-block-size: 1.35rem;
1006
+ padding-inline: .55em;
1007
+ }
1008
+
1009
+ .sf-status::before {
1010
+ background: var(--status-dot, currentColor);
1011
+ block-size: .42em;
1012
+ border-radius: var(--radius-full);
1013
+ content: "";
1014
+ inline-size: .42em;
1015
+ }
1016
+
1017
+ .sf-status[data-tone="success"] {
1018
+ --status-bg: var(--sf-colour-success-soft, oklch(62% 0.13 150 / 0.12));
1019
+ --status-border: color-mix(in oklch, var(--sf-colour-success, oklch(62% 0.13 150)) 34%, transparent);
1020
+ --status-color: var(--color-foreground);
1021
+ --status-dot: var(--sf-colour-success, oklch(62% 0.13 150));
1022
+ }
1023
+
1024
+ .sf-status[data-tone="warning"] {
1025
+ --status-bg: var(--sf-colour-warning-soft, oklch(78% 0.15 82 / 0.16));
1026
+ --status-border: color-mix(in oklch, var(--sf-colour-warning, oklch(78% 0.15 82)) 38%, transparent);
1027
+ --status-color: var(--color-foreground);
1028
+ --status-dot: color-mix(in oklch, var(--sf-colour-warning, oklch(78% 0.15 82)) 60%, var(--color-foreground));
1029
+ }
1030
+
1031
+ .sf-status[data-tone="danger"] {
1032
+ --status-bg: var(--sf-colour-danger-soft, oklch(56% 0.2 28 / 0.12));
1033
+ --status-border: color-mix(in oklch, var(--sf-colour-danger, var(--color-destructive)) 34%, transparent);
1034
+ --status-color: var(--color-foreground);
1035
+ --status-dot: var(--sf-colour-danger, var(--color-destructive));
1036
+ }
1037
+
1038
+ .sf-status[data-tone="info"] {
1039
+ --status-bg: var(--sf-colour-info-soft, oklch(70% 0.12 205 / 0.14));
1040
+ --status-border: color-mix(in oklch, var(--sf-colour-info, oklch(70% 0.12 205)) 34%, transparent);
1041
+ --status-color: var(--color-foreground);
1042
+ --status-dot: color-mix(in oklch, var(--sf-colour-info, oklch(70% 0.12 205)) 68%, var(--color-foreground));
1043
+ }
1044
+
1045
+ .sf-data-list {
1046
+ display: grid;
1047
+ }
1048
+
1049
+ .sf-data-list > * {
1050
+ align-items: center;
1051
+ border-block-end: 1px solid var(--color-border);
1052
+ display: flex;
1053
+ flex-wrap: wrap;
1054
+ gap: var(--space-xs);
1055
+ justify-content: space-between;
1056
+ padding-block: var(--space-xs);
1057
+ }
1058
+
1059
+ .sf-data-list > :last-child {
1060
+ border-block-end: 0;
1061
+ }
1062
+
1063
+ .sf-empty-state {
1064
+ align-items: center;
1065
+ background: var(--color-surface-alt);
1066
+ border: 1px dashed var(--color-border);
1067
+ border-radius: var(--radius-lg);
1068
+ color: var(--color-muted-foreground);
1069
+ display: grid;
1070
+ gap: var(--space-xs);
1071
+ justify-items: center;
1072
+ padding: var(--space-l);
1073
+ text-align: center;
1074
+ }
1075
+
1076
+ .sf-settings-section,
1077
+ .sf-detail-panel {
1078
+ background: var(--color-card);
1079
+ border: 1px solid var(--color-border);
1080
+ border-radius: var(--radius-lg);
1081
+ display: grid;
1082
+ gap: var(--space-s);
1083
+ padding: var(--space-m);
1084
+ }
1085
+
1086
+ .sf-detail-panel {
1087
+ background: var(--color-surface-alt);
1088
+ }
1089
+
1090
+ .sf-form {
1091
+ display: grid;
1092
+ gap: var(--form-gap, var(--space-s));
1093
+ grid-template-columns: minmax(0, 1fr);
1094
+ }
1095
+
728
1096
  .sf-field {
729
1097
  display: grid;
730
1098
  gap: var(--space-2xs);
1099
+ grid-template-columns: minmax(0, 1fr);
1100
+ }
1101
+
1102
+ .sf-form[data-density="compact"],
1103
+ .sf-field[data-density="compact"] {
1104
+ --input-block-size: 2.25rem;
1105
+ --input-padding-inline: var(--space-xs);
731
1106
  }
732
1107
 
733
1108
  .sf-field > label {
@@ -742,7 +1117,41 @@
742
1117
  border-radius: var(--input-radius, var(--radius-md));
743
1118
  color: var(--color-foreground);
744
1119
  min-block-size: var(--input-block-size, 2.75rem);
745
- padding-inline: var(--space-s);
1120
+ padding-inline: var(--input-padding-inline, var(--space-s));
1121
+ }
1122
+
1123
+ .sf-search {
1124
+ position: relative;
1125
+ }
1126
+
1127
+ .sf-search::before {
1128
+ block-size: .75em;
1129
+ border: 0.125em solid currentColor;
1130
+ border-radius: var(--radius-full);
1131
+ color: var(--color-muted-foreground);
1132
+ content: "";
1133
+ inline-size: .75em;
1134
+ inset-block-start: 50%;
1135
+ inset-inline-start: var(--space-xs);
1136
+ line-height: 1;
1137
+ position: absolute;
1138
+ transform: translateY(-58%);
1139
+ }
1140
+
1141
+ .sf-search::after {
1142
+ background: var(--color-muted-foreground);
1143
+ block-size: .125em;
1144
+ content: "";
1145
+ inline-size: .45em;
1146
+ inset-block-start: 50%;
1147
+ inset-inline-start: calc(var(--space-xs) + .58em);
1148
+ position: absolute;
1149
+ transform: translateY(120%) rotate(45deg);
1150
+ transform-origin: inline-start center;
1151
+ }
1152
+
1153
+ .sf-search > .sf-input {
1154
+ padding-inline-start: var(--space-l);
746
1155
  }
747
1156
 
748
1157
  .sf-input:focus-visible {
@@ -750,6 +1159,130 @@
750
1159
  outline: 0.125rem solid color-mix(in oklch, var(--color-ring) 24%, transparent);
751
1160
  outline-offset: 0;
752
1161
  }
1162
+
1163
+ .sf-spinner {
1164
+ animation: sf-spinner-rotate .75s linear infinite;
1165
+ block-size: var(--spinner-size, 1em);
1166
+ border: .125em solid color-mix(in oklch, currentColor 28%, transparent);
1167
+ border-block-start-color: currentColor;
1168
+ border-radius: var(--radius-full);
1169
+ display: inline-block;
1170
+ flex: 0 0 auto;
1171
+ inline-size: var(--spinner-size, 1em);
1172
+ }
1173
+
1174
+ @keyframes sf-spinner-rotate { to { transform: rotate(1turn); } }
1175
+
1176
+ .sf-input-group {
1177
+ align-items: stretch;
1178
+ background: var(--color-card);
1179
+ border: 1px solid var(--color-border);
1180
+ border-radius: var(--input-radius, var(--radius-md));
1181
+ display: flex;
1182
+ inline-size: 100%;
1183
+ min-block-size: var(--input-block-size, 2.75rem);
1184
+ overflow: clip;
1185
+ }
1186
+
1187
+ .sf-input-group:focus-within {
1188
+ border-color: var(--color-ring);
1189
+ outline: .125rem solid color-mix(in oklch, var(--color-ring) 24%, transparent);
1190
+ }
1191
+
1192
+ .sf-input-group > .sf-input { background: transparent; border: 0; border-radius: 0; flex: 1 1 0%; inline-size: auto; min-inline-size: 0; outline: 0; }
1193
+ .sf-input-group__leading,
1194
+ .sf-input-group__trailing { align-items: center; color: var(--color-muted-foreground); display: inline-flex; flex: 0 0 auto; padding-inline: var(--space-xs); white-space: nowrap; }
1195
+ .sf-input-group__leading { border-inline-end: 1px solid var(--color-border); }
1196
+ .sf-input-group__trailing,
1197
+ .sf-input-group__action { border-inline-start: 1px solid var(--color-border); }
1198
+ .sf-input-group__action { background: transparent; border-block: 0; border-inline-end: 0; color: var(--color-foreground); font-weight: 700; padding-inline: var(--space-xs); }
1199
+ .sf-input-group[data-invalid="true"],
1200
+ .sf-field[data-invalid="true"] .sf-input-group { border-color: var(--color-destructive, var(--color-danger)); }
1201
+ .sf-input-group:has(:disabled) { background: var(--color-surface-alt); opacity: .72; }
1202
+
1203
+ .sf-file-input {
1204
+ background: var(--color-card);
1205
+ border: 1px solid var(--color-border);
1206
+ border-radius: var(--input-radius, var(--radius-md));
1207
+ color: var(--color-muted-foreground);
1208
+ inline-size: 100%;
1209
+ min-block-size: var(--input-block-size, 2.75rem);
1210
+ padding: var(--space-3xs);
1211
+ }
1212
+
1213
+ .sf-file-input::file-selector-button { background: var(--color-surface-alt); border: 1px solid var(--color-border); border-radius: var(--radius-sm); color: var(--color-foreground); font: inherit; font-weight: 700; margin-inline-end: var(--space-xs); min-block-size: 2.25rem; padding-inline: var(--space-xs); }
1214
+ .sf-range { accent-color: var(--color-primary); inline-size: 100%; min-block-size: var(--input-block-size, 2.75rem); }
1215
+ .sf-range:focus-visible,
1216
+ .sf-file-input:focus-visible { outline: .125rem solid var(--color-ring); outline-offset: .125rem; }
1217
+ .sf-file-input[aria-invalid="true"],
1218
+ .sf-field[data-invalid="true"] .sf-file-input { border-color: var(--color-destructive, var(--color-danger)); }
1219
+ :where(.sf-file-input, .sf-range):disabled { opacity: .55; }
1220
+
1221
+ .sf-switch { align-items: center; display: inline-grid; gap: var(--space-xs); grid-template-columns: auto 1fr; position: relative; }
1222
+ .sf-switch > input[type="checkbox"],
1223
+ .sf-segmented-control__option > input[type="radio"] { block-size: .0625rem; clip: rect(0 0 0 0); clip-path: inset(50%); inline-size: .0625rem; overflow: hidden; position: absolute; white-space: nowrap; }
1224
+ .sf-switch__control { background: var(--color-surface-alt); border: 1px solid var(--color-border); border-radius: var(--radius-full); block-size: 1.5rem; display: inline-flex; inline-size: 2.75rem; padding: .1875rem; }
1225
+ .sf-switch__control::before { background: var(--color-foreground); border-radius: var(--radius-full); content: ""; inline-size: 1rem; transition: transform var(--duration-fast) var(--ease-standard); }
1226
+ .sf-switch > input:checked + .sf-switch__control { background: var(--color-primary); border-color: var(--color-primary); }
1227
+ .sf-switch > input:checked + .sf-switch__control::before { background: var(--color-primary-foreground); transform: translateX(1.1875rem); }
1228
+ .sf-switch > input:focus-visible + .sf-switch__control { outline: .125rem solid var(--color-ring); outline-offset: .125rem; }
1229
+ .sf-switch__label { color: var(--color-foreground); font-weight: 700; }
1230
+ .sf-switch:has(input:disabled) { cursor: not-allowed; opacity: .55; }
1231
+
1232
+ .sf-segmented-control { background: var(--color-surface-alt); border: 1px solid var(--color-border); border-radius: var(--radius-md); display: inline-flex; flex-wrap: wrap; gap: var(--space-3xs); padding: var(--space-3xs); }
1233
+ .sf-segmented-control__option { cursor: pointer; position: relative; }
1234
+ .sf-segmented-control__label { align-items: center; border: 1px solid transparent; border-radius: var(--radius-sm); color: var(--color-muted-foreground); display: inline-flex; font-size: var(--step--1); font-weight: 700; min-block-size: 2.25rem; padding-inline: var(--space-xs); }
1235
+ .sf-segmented-control__option > input:checked + .sf-segmented-control__label { background: var(--color-card); border-color: var(--color-border); color: var(--color-foreground); }
1236
+ .sf-segmented-control__option > input:focus + .sf-segmented-control__label { outline: .125rem solid var(--color-ring); outline-offset: .125rem; }
1237
+ .sf-segmented-control__option:has(input:disabled) { cursor: not-allowed; opacity: .55; }
1238
+
1239
+ .sf-combobox { position: relative; }
1240
+ .sf-combobox__listbox { background: var(--color-card); border: 1px solid var(--color-border); border-radius: var(--radius-md); box-shadow: var(--shadow-lg); display: grid; gap: var(--space-3xs); inset-block-start: calc(100% + var(--space-3xs)); inset-inline: 0; list-style: none; max-block-size: min(18rem, 50dvh); overflow: auto; padding: var(--space-2xs); position: absolute; z-index: 40; }
1241
+ .sf-combobox__option { border-radius: var(--radius-sm); cursor: pointer; padding: var(--space-2xs) var(--space-xs); }
1242
+ .sf-combobox__option:hover,
1243
+ .sf-combobox__option[aria-selected="true"],
1244
+ .sf-combobox__option[data-active="true"] { background: var(--color-surface-alt); }
1245
+ .sf-combobox__empty { color: var(--color-muted-foreground); padding: var(--space-xs); }
1246
+
1247
+ .sf-bulk-actions { align-items: center; background: color-mix(in oklch, var(--color-primary) 12%, transparent); border: 1px solid color-mix(in oklch, var(--color-primary) 30%, var(--color-border)); border-radius: var(--radius-md); display: flex; flex-wrap: wrap; gap: var(--space-xs); justify-content: space-between; padding: var(--space-xs); }
1248
+ .sf-bulk-actions__count { font-size: var(--step--1); font-weight: 800; }
1249
+ .sf-bulk-actions__controls,
1250
+ .sf-pagination__controls,
1251
+ .sf-pagination__pages,
1252
+ .sf-pagination__jump { align-items: center; display: flex; flex-wrap: wrap; gap: var(--space-2xs); }
1253
+
1254
+ .sf-pagination { align-items: center; display: flex; flex-wrap: wrap; gap: var(--space-2xs); list-style: none; padding-inline-start: 0; }
1255
+ .sf-pagination[data-layout="complete"] { justify-content: space-between; row-gap: var(--space-xs); }
1256
+ .sf-pagination__summary,
1257
+ .sf-pagination__jump { color: var(--color-muted-foreground); font-size: var(--step--1); }
1258
+ .sf-pagination__jump .sf-input { inline-size: 5rem; }
1259
+
1260
+ .sf-stepper { counter-reset: sf-step; display: grid; gap: var(--space-xs); list-style: none; padding-inline-start: 0; }
1261
+ .sf-stepper__step { align-items: center; color: var(--color-muted-foreground); counter-increment: sf-step; display: grid; gap: var(--space-xs); grid-template-columns: auto 1fr; }
1262
+ .sf-stepper__marker { align-items: center; border: 1px solid var(--color-border); border-radius: var(--radius-full); block-size: 2rem; display: inline-flex; font-size: var(--step--1); font-weight: 800; inline-size: 2rem; justify-content: center; }
1263
+ .sf-stepper__marker:empty::before { content: counter(sf-step); }
1264
+ .sf-stepper__step[aria-current="step"] { color: var(--color-foreground); }
1265
+ .sf-stepper__step[aria-current="step"] .sf-stepper__marker { background: var(--color-primary); border-color: var(--color-primary); color: var(--color-primary-foreground); }
1266
+ .sf-stepper__label { font-weight: 700; }
1267
+ .sf-wizard-actions { align-items: center; display: flex; flex-wrap: wrap; gap: var(--space-xs); justify-content: space-between; }
1268
+
1269
+ @media (prefers-reduced-motion: reduce) {
1270
+ .sf-spinner { animation: none; border-color: currentColor; border-inline-end-color: transparent; }
1271
+ .sf-switch__control::before { transition: none; }
1272
+ }
1273
+
1274
+ @media (forced-colors: active) {
1275
+ :where(.sf-input-group, .sf-file-input, .sf-combobox__listbox, .sf-bulk-actions) { border-color: ButtonText; forced-color-adjust: auto; }
1276
+ :where(.sf-switch__control, .sf-segmented-control__label, .sf-stepper__marker) { background: Canvas; border-color: ButtonText; color: ButtonText; forced-color-adjust: none; }
1277
+ .sf-switch > input:focus-visible + .sf-switch__control,
1278
+ .sf-segmented-control__option > input:focus + .sf-segmented-control__label { outline: .125rem solid Highlight; outline-offset: .125rem; }
1279
+ .sf-switch > input:checked + .sf-switch__control,
1280
+ .sf-segmented-control__option > input:checked + .sf-segmented-control__label,
1281
+ .sf-stepper__step[aria-current="step"] .sf-stepper__marker { background: Highlight; border-color: Highlight; color: HighlightText; }
1282
+ .sf-switch__control::before { background: ButtonText; }
1283
+ .sf-switch > input:checked + .sf-switch__control::before { background: HighlightText; }
1284
+ .sf-stepper__step[data-complete="true"] .sf-stepper__marker { background: Canvas; border-color: LinkText; color: LinkText; }
1285
+ }
753
1286
  }
754
1287
 
755
1288
  @layer utilities {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@syncedco/flow",
3
- "version": "0.3.1",
3
+ "version": "0.4.1",
4
4
  "description": "AI-friendly fluid CSS design system for brand-consistent websites and agency builds.",
5
5
  "type": "module",
6
6
  "packageManager": "pnpm@11.2.2",
@@ -77,16 +77,27 @@
77
77
  "scripts": {
78
78
  "build": "node scripts/build-css.mjs && tsc -p tsconfig.build.json",
79
79
  "build:css": "node scripts/build-css.mjs",
80
- "check": "node scripts/build-css.mjs --check && tsc --noEmit && node scripts/guardrails.mjs",
80
+ "build:types": "tsc -p tsconfig.build.json",
81
+ "check": "pnpm check:generated && tsc --noEmit && node scripts/guardrails.mjs",
82
+ "check:generated": "pnpm build:types && node scripts/check-generated-css.mjs",
81
83
  "guardrails": "node scripts/guardrails.mjs",
82
84
  "clean": "rm -rf dist",
83
85
  "prepack": "node scripts/build-css.mjs && tsc -p tsconfig.build.json",
84
86
  "prepare": "node scripts/build-css.mjs && tsc -p tsconfig.build.json",
85
- "test": "pnpm build && node --test tests/*.test.mjs",
87
+ "test": "pnpm check:generated && pnpm build && pnpm test:unit",
88
+ "test:unit": "node --test tests/*.test.mjs",
89
+ "test:browser": "playwright test --project=chromium",
90
+ "test:browser:all": "playwright test",
86
91
  "type-check": "tsc --noEmit"
87
92
  },
88
93
  "devDependencies": {
94
+ "@axe-core/playwright": "^4.13.0",
95
+ "@playwright/test": "^1.63.0",
89
96
  "@types/node": "^22.15.21",
97
+ "@types/react": "^19.2.18",
98
+ "@types/react-test-renderer": "19.1.0",
99
+ "react": "^19.2.8",
100
+ "react-test-renderer": "19.2.8",
90
101
  "typescript": "^5.8.3"
91
102
  },
92
103
  "engines": {