gbs-add-block 2.0.4 → 2.3.0

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.
Files changed (129) hide show
  1. package/.gbs/skills/gbs-components/SKILL.md +190 -134
  2. package/.gbs/skills/gbs-components/references/install.md +25 -3
  3. package/.gbs/skills/gbs-components/references/styling.md +246 -201
  4. package/CHANGELOG.md +74 -0
  5. package/README.md +157 -11
  6. package/index.cjs +212 -3
  7. package/package.json +41 -10
  8. package/schema/passport-v1.schema.json +204 -0
  9. package/source/beta-components/accordion/passport.json +259 -0
  10. package/source/beta-components/accordion/styles.css +207 -208
  11. package/source/beta-components/alert/passport.json +250 -0
  12. package/source/beta-components/alert/styles.css +154 -155
  13. package/source/beta-components/avatar/passport.json +294 -0
  14. package/source/beta-components/avatar/styles.css +201 -203
  15. package/source/beta-components/badge/passport.json +332 -0
  16. package/source/beta-components/badge/styles.css +203 -204
  17. package/source/beta-components/breadcrumb/passport.json +243 -0
  18. package/source/beta-components/breadcrumb/styles.css +138 -139
  19. package/source/beta-components/button/passport.json +402 -0
  20. package/source/beta-components/button/passport.manual.json +31 -0
  21. package/source/beta-components/button/styles.css +232 -233
  22. package/source/beta-components/card/passport.json +337 -0
  23. package/source/beta-components/card/styles.css +230 -231
  24. package/source/beta-components/checkbox/passport.json +456 -0
  25. package/source/beta-components/checkbox/styles.css +211 -212
  26. package/source/beta-components/combobox/passport.json +456 -0
  27. package/source/beta-components/combobox/styles.css +419 -417
  28. package/source/beta-components/data-grid/agent/coerce.ts +368 -0
  29. package/source/beta-components/data-grid/agent/contract.ts +410 -0
  30. package/source/beta-components/data-grid/agent/dataset.ts +92 -0
  31. package/source/beta-components/data-grid/agent/engine.ts +470 -0
  32. package/source/beta-components/data-grid/agent/executors.ts +155 -0
  33. package/source/beta-components/data-grid/agent/index.ts +79 -0
  34. package/source/beta-components/data-grid/agent/intent.ts +324 -0
  35. package/source/beta-components/data-grid/agent/operations.ts +335 -0
  36. package/source/beta-components/data-grid/agent/validate.ts +630 -0
  37. package/source/beta-components/data-grid/agent/webmcp.ts +107 -0
  38. package/source/beta-components/data-grid/index.ts +14 -7
  39. package/source/beta-components/data-grid/passport.json +1051 -0
  40. package/source/beta-components/data-grid/passport.manual.json +255 -0
  41. package/source/beta-components/data-grid/react/AskGrid.tsx +164 -0
  42. package/source/beta-components/data-grid/react/DataGrid.tsx +39 -0
  43. package/source/beta-components/data-grid/styles.css +874 -717
  44. package/source/beta-components/date-picker/passport.json +407 -0
  45. package/source/beta-components/date-picker/styles.css +445 -446
  46. package/source/beta-components/dialog/passport.json +344 -0
  47. package/source/beta-components/dialog/styles.css +280 -278
  48. package/source/beta-components/file-uploader/passport.json +518 -0
  49. package/source/beta-components/file-uploader/styles.css +394 -395
  50. package/source/beta-components/input/passport.json +536 -0
  51. package/source/beta-components/input/styles.css +295 -296
  52. package/source/beta-components/menu/passport.json +322 -0
  53. package/source/beta-components/menu/styles.css +224 -222
  54. package/source/beta-components/modal/passport.json +289 -0
  55. package/source/beta-components/modal/styles.css +241 -239
  56. package/source/beta-components/number-input/passport.json +541 -0
  57. package/source/beta-components/number-input/styles.css +230 -231
  58. package/source/beta-components/popover/passport.json +238 -0
  59. package/source/beta-components/popover/styles.css +148 -146
  60. package/source/beta-components/progress/passport.json +270 -0
  61. package/source/beta-components/progress/styles.css +200 -202
  62. package/source/beta-components/radio-group/passport.json +477 -0
  63. package/source/beta-components/radio-group/styles.css +241 -242
  64. package/source/beta-components/shared/core/agent/adapter.ts +65 -0
  65. package/source/beta-components/shared/core/agent/history.ts +120 -0
  66. package/source/beta-components/shared/core/agent/index.ts +46 -0
  67. package/source/beta-components/shared/core/agent/numbers.ts +217 -0
  68. package/source/beta-components/shared/core/agent/schema.ts +180 -0
  69. package/source/beta-components/shared/core/agent/types.ts +169 -0
  70. package/source/beta-components/shared/core/agent/webmcp.ts +328 -0
  71. package/source/beta-components/shared/index.ts +9 -0
  72. package/source/beta-components/shared/react/GramproAIProvider.tsx +50 -0
  73. package/source/beta-components/shared/react/useAskAgent.ts +217 -0
  74. package/source/beta-components/shared/styles.css +79 -0
  75. package/source/beta-components/shared/version.json +4 -4
  76. package/source/beta-components/shared/version.ts +6 -6
  77. package/source/beta-components/skeleton/passport.json +251 -0
  78. package/source/beta-components/skeleton/styles.css +185 -186
  79. package/source/beta-components/spinner/passport.json +245 -0
  80. package/source/beta-components/spinner/styles.css +145 -146
  81. package/source/beta-components/switch/passport.json +421 -0
  82. package/source/beta-components/switch/styles.css +194 -196
  83. package/source/beta-components/tabs/passport.json +315 -0
  84. package/source/beta-components/tabs/styles.css +234 -235
  85. package/source/beta-components/textarea/passport.json +382 -0
  86. package/source/beta-components/textarea/styles.css +158 -159
  87. package/source/beta-components/toaster/passport.json +221 -0
  88. package/source/beta-components/toaster/styles.css +282 -283
  89. package/source/beta-components/tooltip/passport.json +170 -0
  90. package/source/beta-components/tooltip/styles.css +71 -72
  91. package/tools/env.cjs +61 -0
  92. package/tools/passport/cli.cjs +79 -0
  93. package/tools/passport/extract.cjs +493 -0
  94. package/tools/passport/index.cjs +185 -0
  95. package/tools/passport/merge.cjs +131 -0
  96. package/tools/passport/policy.cjs +65 -0
  97. package/tools/passport/validate.cjs +277 -0
  98. package/tools/ts-require.cjs +79 -0
  99. package/source/beta-components/accordion/__tests__/core.test.ts +0 -58
  100. package/source/beta-components/alert/__tests__/core.test.ts +0 -17
  101. package/source/beta-components/avatar/__tests__/core.test.ts +0 -88
  102. package/source/beta-components/badge/__tests__/core.test.ts +0 -46
  103. package/source/beta-components/breadcrumb/__tests__/core.test.ts +0 -58
  104. package/source/beta-components/button/__tests__/core.test.ts +0 -31
  105. package/source/beta-components/card/__tests__/core.test.ts +0 -57
  106. package/source/beta-components/checkbox/__tests__/core.test.ts +0 -40
  107. package/source/beta-components/combobox/__tests__/core.test.ts +0 -134
  108. package/source/beta-components/data-grid/__tests__/core.test.ts +0 -356
  109. package/source/beta-components/data-grid/__tests__/export.test.ts +0 -70
  110. package/source/beta-components/data-grid/__tests__/pdf.test.ts +0 -209
  111. package/source/beta-components/date-picker/__tests__/core.test.ts +0 -273
  112. package/source/beta-components/dialog/__tests__/core.test.ts +0 -86
  113. package/source/beta-components/file-uploader/__tests__/core.test.ts +0 -395
  114. package/source/beta-components/input/__tests__/core.test.ts +0 -75
  115. package/source/beta-components/menu/__tests__/core.test.ts +0 -120
  116. package/source/beta-components/modal/__tests__/core.test.ts +0 -55
  117. package/source/beta-components/number-input/__tests__/core.test.ts +0 -151
  118. package/source/beta-components/progress/__tests__/core.test.ts +0 -56
  119. package/source/beta-components/radio-group/__tests__/core.test.ts +0 -64
  120. package/source/beta-components/shared/__tests__/boundaries.test.ts +0 -95
  121. package/source/beta-components/shared/__tests__/core.test.ts +0 -55
  122. package/source/beta-components/shared/__tests__/position.test.ts +0 -143
  123. package/source/beta-components/skeleton/__tests__/core.test.ts +0 -41
  124. package/source/beta-components/spinner/__tests__/core.test.ts +0 -48
  125. package/source/beta-components/switch/__tests__/core.test.ts +0 -64
  126. package/source/beta-components/tabs/__tests__/core.test.ts +0 -51
  127. package/source/beta-components/textarea/__tests__/core.test.ts +0 -38
  128. package/source/beta-components/toaster/__tests__/core.test.ts +0 -256
  129. package/source/beta-components/tooltip/__tests__/core.test.ts +0 -42
@@ -1,395 +1,394 @@
1
- /*
2
- * FileUploader styles.
3
- *
4
- * Tokens read the shared --gbs-* variables when they are set on an ancestor
5
- * (set them on :root to theme every component at once) and fall back to the
6
- * same default palette otherwise. Rules live in the `components` layer, so utility classes passed
7
- * through `className` / `classNames` override them.
8
- */
9
- @layer theme, base, components, utilities;
10
-
11
- @layer components {
12
- .fu-root {
13
- --fu-bg: var(--gbs-bg, var(--dg-bg, light-dark(#ffffff, #0b0b0e)));
14
- --fu-fg: var(--gbs-fg, var(--dg-fg, light-dark(#18181b, #f4f4f5)));
15
- --fu-muted: var(--gbs-muted, var(--dg-muted, light-dark(#71717a, #a1a1aa)));
16
- --fu-border: var(--gbs-border, var(--dg-border, light-dark(#e4e4e7, #27272a)));
17
- --fu-hover: var(--gbs-hover, var(--dg-hover, light-dark(#f4f4f5, #1f1f23)));
18
- --fu-input-bg: var(--gbs-input-bg, var(--dg-input-bg, light-dark(#ffffff, #121216)));
19
- --fu-accent: var(--gbs-accent, var(--dg-accent, light-dark(#2563eb, #60a5fa)));
20
- --fu-accent-fg: var(--gbs-accent-fg, var(--dg-accent-fg, light-dark(#ffffff, #0b1220)));
21
- --fu-accent-soft: var(--gbs-accent-soft, var(--dg-accent-soft, light-dark(#eff6ff, #172554)));
22
- --fu-focus: var(--gbs-focus, var(--dg-focus, light-dark(#2563eb, #60a5fa)));
23
- --fu-danger: var(--gbs-danger, var(--dg-danger, light-dark(#dc2626, #f87171)));
24
- --fu-success: var(--gbs-success, light-dark(#15803d, #4ade80));
25
- --fu-radius: var(--gbs-radius, var(--dg-radius, 8px));
26
- --fu-font-size: var(--gbs-font-size, var(--dg-font-size, 13px));
27
- --fu-dropzone-py: 20px;
28
- --fu-thumb-size: 40px;
29
-
30
- color-scheme: inherit;
31
- display: flex;
32
- flex-direction: column;
33
- gap: 8px;
34
- width: 100%;
35
- min-width: 0;
36
- font-size: var(--fu-font-size);
37
- line-height: 1.4;
38
- color: var(--fu-fg);
39
- }
40
-
41
- :where(.dark, [data-theme="dark"]) .fu-root {
42
- color-scheme: dark;
43
- }
44
- :where(.light, [data-theme="light"]) .fu-root {
45
- color-scheme: light;
46
- }
47
-
48
- :where(.fu-root) *,
49
- :where(.fu-root) *::before,
50
- :where(.fu-root) *::after {
51
- box-sizing: border-box;
52
- }
53
-
54
- .fu-root[data-size="sm"] {
55
- --fu-font-size: 12px;
56
- --fu-dropzone-py: 12px;
57
- --fu-thumb-size: 32px;
58
- }
59
- .fu-root[data-size="lg"] {
60
- --fu-font-size: 14px;
61
- --fu-dropzone-py: 32px;
62
- --fu-thumb-size: 48px;
63
- }
64
-
65
- .fu-label {
66
- font-weight: 500;
67
- }
68
- .fu-label[data-required]::after {
69
- content: " *";
70
- color: var(--fu-danger);
71
- }
72
- .fu-description {
73
- color: var(--fu-muted);
74
- font-size: 0.92em;
75
- }
76
- .fu-error {
77
- color: var(--fu-danger);
78
- font-size: 0.92em;
79
- }
80
-
81
- /* ------------------------------------------------------------ dropzone */
82
-
83
- .fu-dropzone {
84
- position: relative;
85
- border: 1.5px dashed color-mix(in oklab, var(--fu-border), var(--fu-fg) 20%);
86
- border-radius: var(--fu-radius);
87
- background: var(--fu-input-bg);
88
- transition:
89
- border-color 120ms ease,
90
- background-color 120ms ease;
91
- }
92
- .fu-dropzone:hover:not(:has(.fu-trigger:disabled)) {
93
- border-color: color-mix(in oklab, var(--fu-border), var(--fu-fg) 40%);
94
- }
95
- .fu-dropzone[data-dragging] {
96
- border-color: var(--fu-accent);
97
- background: var(--fu-accent-soft);
98
- }
99
- .fu-root[data-invalid] .fu-dropzone {
100
- border-color: var(--fu-danger);
101
- }
102
-
103
- .fu-trigger {
104
- display: flex;
105
- flex-direction: column;
106
- align-items: center;
107
- gap: 4px;
108
- width: 100%;
109
- padding: var(--fu-dropzone-py) 16px;
110
- border: 0;
111
- border-radius: inherit;
112
- background: transparent;
113
- color: inherit;
114
- font: inherit;
115
- text-align: center;
116
- cursor: pointer;
117
- }
118
- .fu-trigger:focus-visible {
119
- outline: 2px solid var(--fu-focus);
120
- outline-offset: 2px;
121
- }
122
- .fu-trigger:disabled {
123
- opacity: 0.55;
124
- cursor: not-allowed;
125
- }
126
- .fu-dropzone-icon {
127
- color: var(--fu-muted);
128
- }
129
- .fu-dropzone[data-dragging] .fu-dropzone-icon {
130
- color: var(--fu-accent);
131
- }
132
- .fu-browse {
133
- color: var(--fu-accent);
134
- font-weight: 500;
135
- text-decoration: underline;
136
- text-underline-offset: 2px;
137
- }
138
- .fu-hint {
139
- color: var(--fu-muted);
140
- font-size: 0.92em;
141
- }
142
-
143
- /* ---------------------------------------------------------- rejections */
144
-
145
- .fu-rejections {
146
- display: flex;
147
- flex-direction: column;
148
- gap: 4px;
149
- margin: 0;
150
- padding: 0;
151
- list-style: none;
152
- }
153
- .fu-rejection {
154
- display: flex;
155
- align-items: center;
156
- gap: 8px;
157
- padding: 4px 4px 4px 10px;
158
- border-radius: 6px;
159
- background: color-mix(in oklab, var(--fu-danger), transparent 90%);
160
- color: var(--fu-danger);
161
- }
162
- .fu-rejection > span {
163
- flex: 1 1 auto;
164
- min-width: 0;
165
- }
166
-
167
- /* --------------------------------------------------------------- files */
168
-
169
- .fu-list {
170
- display: flex;
171
- flex-direction: column;
172
- gap: 6px;
173
- margin: 0;
174
- padding: 0;
175
- list-style: none;
176
- }
177
- .fu-item {
178
- display: flex;
179
- align-items: center;
180
- gap: 10px;
181
- padding: 8px 8px 8px 10px;
182
- border: 1px solid var(--fu-border);
183
- border-radius: var(--fu-radius);
184
- background: var(--fu-bg);
185
- }
186
- .fu-item[data-status="error"] {
187
- border-color: color-mix(in oklab, var(--fu-danger), var(--fu-border) 55%);
188
- }
189
-
190
- .fu-thumb {
191
- --fu-kind: var(--fu-muted);
192
-
193
- position: relative;
194
- display: grid;
195
- flex: none;
196
- place-items: center;
197
- width: var(--fu-thumb-size);
198
- height: var(--fu-thumb-size);
199
- overflow: hidden;
200
- border-radius: 6px;
201
- background: color-mix(in oklab, var(--fu-kind), transparent 88%);
202
- color: var(--fu-kind);
203
- }
204
- .fu-thumb img {
205
- position: absolute;
206
- inset: 0;
207
- width: 100%;
208
- height: 100%;
209
- object-fit: cover;
210
- }
211
- .fu-thumb[data-kind="image"] {
212
- --fu-kind: light-dark(#2563eb, #60a5fa);
213
- }
214
- .fu-thumb[data-kind="video"] {
215
- --fu-kind: light-dark(#9333ea, #c084fc);
216
- }
217
- .fu-thumb[data-kind="audio"] {
218
- --fu-kind: light-dark(#d97706, #fbbf24);
219
- }
220
- .fu-thumb[data-kind="pdf"] {
221
- --fu-kind: light-dark(#dc2626, #f87171);
222
- }
223
- .fu-thumb[data-kind="spreadsheet"] {
224
- --fu-kind: light-dark(#16a34a, #4ade80);
225
- }
226
- .fu-thumb[data-kind="document"] {
227
- --fu-kind: light-dark(#0891b2, #22d3ee);
228
- }
229
-
230
- .fu-body {
231
- display: flex;
232
- flex: 1 1 auto;
233
- flex-direction: column;
234
- gap: 1px;
235
- min-width: 0;
236
- }
237
- .fu-name,
238
- .fu-meta,
239
- .fu-item-error {
240
- overflow: hidden;
241
- text-overflow: ellipsis;
242
- white-space: nowrap;
243
- }
244
- .fu-name {
245
- font-weight: 500;
246
- }
247
- .fu-meta {
248
- color: var(--fu-muted);
249
- font-size: 0.92em;
250
- font-variant-numeric: tabular-nums;
251
- }
252
- .fu-item[data-status="success"] .fu-meta {
253
- color: var(--fu-success);
254
- }
255
- .fu-item[data-status="error"] .fu-meta,
256
- .fu-item-error {
257
- color: var(--fu-danger);
258
- font-size: 0.92em;
259
- }
260
-
261
- .fu-progress {
262
- height: 4px;
263
- margin-top: 4px;
264
- overflow: hidden;
265
- border-radius: 999px;
266
- background: var(--fu-hover);
267
- }
268
- /* Scaling instead of width: moving the bar never triggers layout. */
269
- .fu-progress-bar {
270
- display: block;
271
- height: 100%;
272
- background: var(--fu-accent);
273
- transform-origin: left;
274
- transition: transform 150ms linear;
275
- }
276
- .fu-progress-bar:dir(rtl) {
277
- transform-origin: right;
278
- }
279
- .fu-item[data-status="paused"] .fu-progress-bar {
280
- background: var(--fu-muted);
281
- }
282
- .fu-item[data-status="error"] .fu-progress-bar {
283
- background: var(--fu-danger);
284
- }
285
-
286
- .fu-actions {
287
- display: flex;
288
- flex: none;
289
- align-items: center;
290
- gap: 2px;
291
- color: var(--fu-muted);
292
- }
293
- .fu-icon-button {
294
- display: inline-grid;
295
- place-items: center;
296
- width: 28px;
297
- height: 28px;
298
- padding: 0;
299
- border: 0;
300
- border-radius: 6px;
301
- background: transparent;
302
- color: inherit;
303
- cursor: pointer;
304
- }
305
- .fu-icon-button:hover:not(:disabled) {
306
- background: var(--fu-hover);
307
- color: var(--fu-fg);
308
- }
309
- .fu-icon-button:focus-visible {
310
- outline: 2px solid var(--fu-focus);
311
- outline-offset: 1px;
312
- }
313
- .fu-icon-button:disabled {
314
- opacity: 0.4;
315
- cursor: default;
316
- }
317
-
318
- /* -------------------------------------------------------------- footer */
319
-
320
- .fu-footer {
321
- display: flex;
322
- align-items: center;
323
- justify-content: flex-end;
324
- gap: 8px;
325
- }
326
- .fu-footer .fu-progress {
327
- flex: 1 1 auto;
328
- margin: 0;
329
- }
330
- .fu-footer-text {
331
- color: var(--fu-muted);
332
- font-size: 0.92em;
333
- font-variant-numeric: tabular-nums;
334
- white-space: nowrap;
335
- }
336
- .fu-button {
337
- height: 32px;
338
- padding: 0 12px;
339
- border: 1px solid var(--fu-border);
340
- border-radius: 6px;
341
- background: var(--fu-bg);
342
- color: inherit;
343
- font: inherit;
344
- font-weight: 500;
345
- white-space: nowrap;
346
- cursor: pointer;
347
- }
348
- .fu-button:hover:not(:disabled) {
349
- background: var(--fu-hover);
350
- }
351
- .fu-button[data-variant="primary"] {
352
- border-color: var(--fu-accent);
353
- background: var(--fu-accent);
354
- color: var(--fu-accent-fg);
355
- }
356
- .fu-button[data-variant="primary"]:hover:not(:disabled) {
357
- background: color-mix(in oklab, var(--fu-accent), var(--fu-fg) 12%);
358
- }
359
- .fu-button:focus-visible {
360
- outline: 2px solid var(--fu-focus);
361
- outline-offset: 1px;
362
- }
363
- .fu-button:disabled {
364
- opacity: 0.55;
365
- cursor: not-allowed;
366
- }
367
-
368
- .fu-sr-only {
369
- position: absolute;
370
- width: 1px;
371
- height: 1px;
372
- margin: -1px;
373
- padding: 0;
374
- overflow: hidden;
375
- clip-path: inset(50%);
376
- white-space: nowrap;
377
- border: 0;
378
- }
379
-
380
- @media (prefers-reduced-motion: reduce) {
381
- .fu-dropzone,
382
- .fu-progress-bar {
383
- transition: none;
384
- }
385
- }
386
-
387
- @media (forced-colors: active) {
388
- .fu-progress-bar {
389
- background: Highlight;
390
- }
391
- .fu-dropzone[data-dragging] {
392
- border-color: Highlight;
393
- }
394
- }
395
- }
1
+ /*
2
+ * FileUploader styles.
3
+ *
4
+ * Tokens read the shared --gbs-* variables when they are set on an ancestor
5
+ * (set them on :root to theme every component at once) and fall back to the
6
+ * same default palette otherwise. Rules are unlayered: they beat a framework
7
+ * reset on specificity, and lose to anything you pass through `className`.
8
+ * With Tailwind v4, import this file after the framework and inside its
9
+ * components layer - see the README.
10
+ */
11
+
12
+ .fu-root {
13
+ --fu-bg: var(--gbs-bg, var(--dg-bg, light-dark(#ffffff, #0b0b0e)));
14
+ --fu-fg: var(--gbs-fg, var(--dg-fg, light-dark(#18181b, #f4f4f5)));
15
+ --fu-muted: var(--gbs-muted, var(--dg-muted, light-dark(#71717a, #a1a1aa)));
16
+ --fu-border: var(--gbs-border, var(--dg-border, light-dark(#e4e4e7, #27272a)));
17
+ --fu-hover: var(--gbs-hover, var(--dg-hover, light-dark(#f4f4f5, #1f1f23)));
18
+ --fu-input-bg: var(--gbs-input-bg, var(--dg-input-bg, light-dark(#ffffff, #121216)));
19
+ --fu-accent: var(--gbs-accent, var(--dg-accent, light-dark(#2563eb, #60a5fa)));
20
+ --fu-accent-fg: var(--gbs-accent-fg, var(--dg-accent-fg, light-dark(#ffffff, #0b1220)));
21
+ --fu-accent-soft: var(--gbs-accent-soft, var(--dg-accent-soft, light-dark(#eff6ff, #172554)));
22
+ --fu-focus: var(--gbs-focus, var(--dg-focus, light-dark(#2563eb, #60a5fa)));
23
+ --fu-danger: var(--gbs-danger, var(--dg-danger, light-dark(#dc2626, #f87171)));
24
+ --fu-success: var(--gbs-success, light-dark(#15803d, #4ade80));
25
+ --fu-radius: var(--gbs-radius, var(--dg-radius, 8px));
26
+ --fu-font-size: var(--gbs-font-size, var(--dg-font-size, 13px));
27
+ --fu-dropzone-py: 20px;
28
+ --fu-thumb-size: 40px;
29
+
30
+ color-scheme: inherit;
31
+ display: flex;
32
+ flex-direction: column;
33
+ gap: 8px;
34
+ width: 100%;
35
+ min-width: 0;
36
+ font-size: var(--fu-font-size);
37
+ line-height: 1.4;
38
+ color: var(--fu-fg);
39
+ }
40
+
41
+ :where(.dark, [data-theme="dark"]) .fu-root {
42
+ color-scheme: dark;
43
+ }
44
+ :where(.light, [data-theme="light"]) .fu-root {
45
+ color-scheme: light;
46
+ }
47
+
48
+ :where(.fu-root) *,
49
+ :where(.fu-root) *::before,
50
+ :where(.fu-root) *::after {
51
+ box-sizing: border-box;
52
+ }
53
+
54
+ .fu-root[data-size="sm"] {
55
+ --fu-font-size: 12px;
56
+ --fu-dropzone-py: 12px;
57
+ --fu-thumb-size: 32px;
58
+ }
59
+ .fu-root[data-size="lg"] {
60
+ --fu-font-size: 14px;
61
+ --fu-dropzone-py: 32px;
62
+ --fu-thumb-size: 48px;
63
+ }
64
+
65
+ .fu-label {
66
+ font-weight: 500;
67
+ }
68
+ .fu-label[data-required]::after {
69
+ content: " *";
70
+ color: var(--fu-danger);
71
+ }
72
+ .fu-description {
73
+ color: var(--fu-muted);
74
+ font-size: 0.92em;
75
+ }
76
+ .fu-error {
77
+ color: var(--fu-danger);
78
+ font-size: 0.92em;
79
+ }
80
+
81
+ /* ------------------------------------------------------------ dropzone */
82
+
83
+ .fu-dropzone {
84
+ position: relative;
85
+ border: 1.5px dashed color-mix(in oklab, var(--fu-border), var(--fu-fg) 20%);
86
+ border-radius: var(--fu-radius);
87
+ background: var(--fu-input-bg);
88
+ transition:
89
+ border-color 120ms ease,
90
+ background-color 120ms ease;
91
+ }
92
+ .fu-dropzone:hover:not(:has(.fu-trigger:disabled)) {
93
+ border-color: color-mix(in oklab, var(--fu-border), var(--fu-fg) 40%);
94
+ }
95
+ .fu-dropzone[data-dragging] {
96
+ border-color: var(--fu-accent);
97
+ background: var(--fu-accent-soft);
98
+ }
99
+ .fu-root[data-invalid] .fu-dropzone {
100
+ border-color: var(--fu-danger);
101
+ }
102
+
103
+ .fu-trigger {
104
+ display: flex;
105
+ flex-direction: column;
106
+ align-items: center;
107
+ gap: 4px;
108
+ width: 100%;
109
+ padding: var(--fu-dropzone-py) 16px;
110
+ border: 0;
111
+ border-radius: inherit;
112
+ background: transparent;
113
+ color: inherit;
114
+ font: inherit;
115
+ text-align: center;
116
+ cursor: pointer;
117
+ }
118
+ .fu-trigger:focus-visible {
119
+ outline: 2px solid var(--fu-focus);
120
+ outline-offset: 2px;
121
+ }
122
+ .fu-trigger:disabled {
123
+ opacity: 0.55;
124
+ cursor: not-allowed;
125
+ }
126
+ .fu-dropzone-icon {
127
+ color: var(--fu-muted);
128
+ }
129
+ .fu-dropzone[data-dragging] .fu-dropzone-icon {
130
+ color: var(--fu-accent);
131
+ }
132
+ .fu-browse {
133
+ color: var(--fu-accent);
134
+ font-weight: 500;
135
+ text-decoration: underline;
136
+ text-underline-offset: 2px;
137
+ }
138
+ .fu-hint {
139
+ color: var(--fu-muted);
140
+ font-size: 0.92em;
141
+ }
142
+
143
+ /* ---------------------------------------------------------- rejections */
144
+
145
+ .fu-rejections {
146
+ display: flex;
147
+ flex-direction: column;
148
+ gap: 4px;
149
+ margin: 0;
150
+ padding: 0;
151
+ list-style: none;
152
+ }
153
+ .fu-rejection {
154
+ display: flex;
155
+ align-items: center;
156
+ gap: 8px;
157
+ padding: 4px 4px 4px 10px;
158
+ border-radius: 6px;
159
+ background: color-mix(in oklab, var(--fu-danger), transparent 90%);
160
+ color: var(--fu-danger);
161
+ }
162
+ .fu-rejection > span {
163
+ flex: 1 1 auto;
164
+ min-width: 0;
165
+ }
166
+
167
+ /* --------------------------------------------------------------- files */
168
+
169
+ .fu-list {
170
+ display: flex;
171
+ flex-direction: column;
172
+ gap: 6px;
173
+ margin: 0;
174
+ padding: 0;
175
+ list-style: none;
176
+ }
177
+ .fu-item {
178
+ display: flex;
179
+ align-items: center;
180
+ gap: 10px;
181
+ padding: 8px 8px 8px 10px;
182
+ border: 1px solid var(--fu-border);
183
+ border-radius: var(--fu-radius);
184
+ background: var(--fu-bg);
185
+ }
186
+ .fu-item[data-status="error"] {
187
+ border-color: color-mix(in oklab, var(--fu-danger), var(--fu-border) 55%);
188
+ }
189
+
190
+ .fu-thumb {
191
+ --fu-kind: var(--fu-muted);
192
+
193
+ position: relative;
194
+ display: grid;
195
+ flex: none;
196
+ place-items: center;
197
+ width: var(--fu-thumb-size);
198
+ height: var(--fu-thumb-size);
199
+ overflow: hidden;
200
+ border-radius: 6px;
201
+ background: color-mix(in oklab, var(--fu-kind), transparent 88%);
202
+ color: var(--fu-kind);
203
+ }
204
+ .fu-thumb img {
205
+ position: absolute;
206
+ inset: 0;
207
+ width: 100%;
208
+ height: 100%;
209
+ object-fit: cover;
210
+ }
211
+ .fu-thumb[data-kind="image"] {
212
+ --fu-kind: light-dark(#2563eb, #60a5fa);
213
+ }
214
+ .fu-thumb[data-kind="video"] {
215
+ --fu-kind: light-dark(#9333ea, #c084fc);
216
+ }
217
+ .fu-thumb[data-kind="audio"] {
218
+ --fu-kind: light-dark(#d97706, #fbbf24);
219
+ }
220
+ .fu-thumb[data-kind="pdf"] {
221
+ --fu-kind: light-dark(#dc2626, #f87171);
222
+ }
223
+ .fu-thumb[data-kind="spreadsheet"] {
224
+ --fu-kind: light-dark(#16a34a, #4ade80);
225
+ }
226
+ .fu-thumb[data-kind="document"] {
227
+ --fu-kind: light-dark(#0891b2, #22d3ee);
228
+ }
229
+
230
+ .fu-body {
231
+ display: flex;
232
+ flex: 1 1 auto;
233
+ flex-direction: column;
234
+ gap: 1px;
235
+ min-width: 0;
236
+ }
237
+ .fu-name,
238
+ .fu-meta,
239
+ .fu-item-error {
240
+ overflow: hidden;
241
+ text-overflow: ellipsis;
242
+ white-space: nowrap;
243
+ }
244
+ .fu-name {
245
+ font-weight: 500;
246
+ }
247
+ .fu-meta {
248
+ color: var(--fu-muted);
249
+ font-size: 0.92em;
250
+ font-variant-numeric: tabular-nums;
251
+ }
252
+ .fu-item[data-status="success"] .fu-meta {
253
+ color: var(--fu-success);
254
+ }
255
+ .fu-item[data-status="error"] .fu-meta,
256
+ .fu-item-error {
257
+ color: var(--fu-danger);
258
+ font-size: 0.92em;
259
+ }
260
+
261
+ .fu-progress {
262
+ height: 4px;
263
+ margin-top: 4px;
264
+ overflow: hidden;
265
+ border-radius: 999px;
266
+ background: var(--fu-hover);
267
+ }
268
+ /* Scaling instead of width: moving the bar never triggers layout. */
269
+ .fu-progress-bar {
270
+ display: block;
271
+ height: 100%;
272
+ background: var(--fu-accent);
273
+ transform-origin: left;
274
+ transition: transform 150ms linear;
275
+ }
276
+ .fu-progress-bar:dir(rtl) {
277
+ transform-origin: right;
278
+ }
279
+ .fu-item[data-status="paused"] .fu-progress-bar {
280
+ background: var(--fu-muted);
281
+ }
282
+ .fu-item[data-status="error"] .fu-progress-bar {
283
+ background: var(--fu-danger);
284
+ }
285
+
286
+ .fu-actions {
287
+ display: flex;
288
+ flex: none;
289
+ align-items: center;
290
+ gap: 2px;
291
+ color: var(--fu-muted);
292
+ }
293
+ .fu-icon-button {
294
+ display: inline-grid;
295
+ place-items: center;
296
+ width: 28px;
297
+ height: 28px;
298
+ padding: 0;
299
+ border: 0;
300
+ border-radius: 6px;
301
+ background: transparent;
302
+ color: inherit;
303
+ cursor: pointer;
304
+ }
305
+ .fu-icon-button:hover:not(:disabled) {
306
+ background: var(--fu-hover);
307
+ color: var(--fu-fg);
308
+ }
309
+ .fu-icon-button:focus-visible {
310
+ outline: 2px solid var(--fu-focus);
311
+ outline-offset: 1px;
312
+ }
313
+ .fu-icon-button:disabled {
314
+ opacity: 0.4;
315
+ cursor: default;
316
+ }
317
+
318
+ /* -------------------------------------------------------------- footer */
319
+
320
+ .fu-footer {
321
+ display: flex;
322
+ align-items: center;
323
+ justify-content: flex-end;
324
+ gap: 8px;
325
+ }
326
+ .fu-footer .fu-progress {
327
+ flex: 1 1 auto;
328
+ margin: 0;
329
+ }
330
+ .fu-footer-text {
331
+ color: var(--fu-muted);
332
+ font-size: 0.92em;
333
+ font-variant-numeric: tabular-nums;
334
+ white-space: nowrap;
335
+ }
336
+ .fu-button {
337
+ height: 32px;
338
+ padding: 0 12px;
339
+ border: 1px solid var(--fu-border);
340
+ border-radius: 6px;
341
+ background: var(--fu-bg);
342
+ color: inherit;
343
+ font: inherit;
344
+ font-weight: 500;
345
+ white-space: nowrap;
346
+ cursor: pointer;
347
+ }
348
+ .fu-button:hover:not(:disabled) {
349
+ background: var(--fu-hover);
350
+ }
351
+ .fu-button[data-variant="primary"] {
352
+ border-color: var(--fu-accent);
353
+ background: var(--fu-accent);
354
+ color: var(--fu-accent-fg);
355
+ }
356
+ .fu-button[data-variant="primary"]:hover:not(:disabled) {
357
+ background: color-mix(in oklab, var(--fu-accent), var(--fu-fg) 12%);
358
+ }
359
+ .fu-button:focus-visible {
360
+ outline: 2px solid var(--fu-focus);
361
+ outline-offset: 1px;
362
+ }
363
+ .fu-button:disabled {
364
+ opacity: 0.55;
365
+ cursor: not-allowed;
366
+ }
367
+
368
+ .fu-sr-only {
369
+ position: absolute;
370
+ width: 1px;
371
+ height: 1px;
372
+ margin: -1px;
373
+ padding: 0;
374
+ overflow: hidden;
375
+ clip-path: inset(50%);
376
+ white-space: nowrap;
377
+ border: 0;
378
+ }
379
+
380
+ @media (prefers-reduced-motion: reduce) {
381
+ .fu-dropzone,
382
+ .fu-progress-bar {
383
+ transition: none;
384
+ }
385
+ }
386
+
387
+ @media (forced-colors: active) {
388
+ .fu-progress-bar {
389
+ background: Highlight;
390
+ }
391
+ .fu-dropzone[data-dragging] {
392
+ border-color: Highlight;
393
+ }
394
+ }