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