@duro-app/cli 5.1.0 → 5.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.
package/registry.json CHANGED
@@ -251,7 +251,8 @@
251
251
  "success",
252
252
  "warning",
253
253
  "error",
254
- "info"
254
+ "info",
255
+ "highlight"
255
256
  ]
256
257
  },
257
258
  {
@@ -353,6 +354,24 @@
353
354
  "required": false,
354
355
  "type": "string"
355
356
  },
357
+ {
358
+ "description": "For a button that shows or hides another element (a disclosure, a panel).",
359
+ "name": "aria-expanded",
360
+ "required": false,
361
+ "type": "boolean"
362
+ },
363
+ {
364
+ "description": "Id of the element this button controls.",
365
+ "name": "aria-controls",
366
+ "required": false,
367
+ "type": "string"
368
+ },
369
+ {
370
+ "description": "The underlying <button>, e.g. to anchor a Popover or return focus to it. Web only: on native the ref is not attached.",
371
+ "name": "ref",
372
+ "required": false,
373
+ "type": "Ref<HTMLButtonElement>"
374
+ },
356
375
  {
357
376
  "name": "children",
358
377
  "required": true,
@@ -365,9 +384,19 @@
365
384
  "importPath": "@duro-app/ui",
366
385
  "kind": "component",
367
386
  "meta": {
368
- "description": "Groups related buttons together with consistent spacing and layout. Supports horizontal and vertical orientation with alignment control.",
387
+ "description": "Groups related buttons together with consistent spacing and layout. Supports horizontal and vertical orientation with alignment control. With `attached`, the group renders one joined control (shared borders, square inner corners) from any mix of Button, Toggle and Select/Menu/Popover triggers.",
369
388
  "example": "<ButtonGroup align=\"end\" gap=\"sm\">\n <Button variant=\"secondary\">Cancel</Button>\n <Button variant=\"primary\">Save</Button>\n</ButtonGroup>",
370
389
  "relatedTo": [
390
+ {
391
+ "component": "Toolbar",
392
+ "kind": "composition",
393
+ "relationship": "Put attached groups in a Toolbar for one tab stop and arrow keys across them; a ButtonGroup alone leaves every control its own tab stop"
394
+ },
395
+ {
396
+ "component": "ToggleGroup",
397
+ "kind": "contrast",
398
+ "relationship": "ToggleGroup owns a selection (single or multiple) across Toggles; ButtonGroup attached only joins controls visually, each keeps its own state"
399
+ },
371
400
  {
372
401
  "component": "Inline",
373
402
  "kind": "contrast",
@@ -387,7 +416,8 @@
387
416
  "whenToUse": [
388
417
  "Dialog footers with Save/Cancel actions",
389
418
  "Toolbar-style groupings of related actions",
390
- "Form submission areas with multiple actions"
419
+ "Form submission areas with multiple actions",
420
+ "`attached`: a segmented control of mixed controls — [Normal | Arial | 15px] as three Selects, [B | I | U | link] as Toggles and a Popover trigger"
391
421
  ]
392
422
  },
393
423
  "name": "ButtonGroup",
@@ -420,10 +450,23 @@
420
450
  },
421
451
  {
422
452
  "default": "'sm'",
423
- "description": "Gap between buttons. Default: 'sm'",
453
+ "description": "Gap between buttons. Default: 'sm' (ignored when `attached`)",
424
454
  "name": "gap",
425
455
  "required": false,
426
456
  "type": "ButtonGroupGap"
457
+ },
458
+ {
459
+ "default": "false",
460
+ "description": "One joined control: no gap, shared borders, square inner corners. Holds Buttons, Toggles and the Select, Menu and Popover triggers, in any mix.",
461
+ "name": "attached",
462
+ "required": false,
463
+ "type": "boolean"
464
+ },
465
+ {
466
+ "description": "Names the group for assistive tech (a toolbar segment: \"Text style\").",
467
+ "name": "aria-label",
468
+ "required": false,
469
+ "type": "string"
427
470
  }
428
471
  ],
429
472
  "sourcePath": "packages/ui/src/components/ButtonGroup/ButtonGroup.tsx"
@@ -1603,7 +1646,7 @@
1603
1646
  "Portal"
1604
1647
  ]
1605
1648
  },
1606
- "description": "Modal dialog with backdrop overlay. Centered on screen with scale+fade animation. Traps focus, dismisses on backdrop click or Escape. Use for confirmations, forms, or content that requires user attention before continuing.",
1649
+ "description": "Modal dialog with backdrop overlay. Centered on screen with scale+fade animation. Moves focus in on open (initialFocus, else the first focusable element, else the dialog) and back on close; dismisses on backdrop click (dismissable) or Escape (closeOnEscape, independent of dismissable). Use for confirmations, forms, or content that requires user attention before continuing.",
1607
1650
  "example": "<Dialog.Root open={open} onOpenChange={setOpen}>\n <Dialog.Trigger>\n <Button>Open dialog</Button>\n </Dialog.Trigger>\n <Dialog.Portal size=\"md\">\n <Dialog.Header>\n <Dialog.Title>Confirm action</Dialog.Title>\n <Dialog.Close />\n </Dialog.Header>\n <Dialog.Body>\n <Text>Are you sure you want to proceed?</Text>\n </Dialog.Body>\n <Dialog.Footer>\n <Button variant=\"secondary\" onClick={() => setOpen(false)}>Cancel</Button>\n <Button variant=\"danger\" onClick={handleConfirm}>Confirm</Button>\n </Dialog.Footer>\n </Dialog.Portal>\n</Dialog.Root>",
1608
1651
  "relatedTo": [
1609
1652
  {
@@ -1749,11 +1792,24 @@
1749
1792
  },
1750
1793
  {
1751
1794
  "default": "true",
1752
- "description": "Whether clicking backdrop closes the dialog. Default: true",
1795
+ "description": "Whether clicking the backdrop closes the dialog. Default: true",
1753
1796
  "name": "dismissable",
1754
1797
  "required": false,
1755
1798
  "type": "boolean"
1756
1799
  },
1800
+ {
1801
+ "default": "true",
1802
+ "description": "Whether Escape closes the dialog. Default: true, also when `dismissable` is false. Turning it off leaves the keyboard no way out but a Dialog.Close, so render one.",
1803
+ "name": "closeOnEscape",
1804
+ "required": false,
1805
+ "type": "boolean"
1806
+ },
1807
+ {
1808
+ "description": "Element to focus on open. Default: the first focusable element, else the dialog itself.",
1809
+ "name": "initialFocus",
1810
+ "required": false,
1811
+ "type": "RefObject<HTMLElement | null>"
1812
+ },
1757
1813
  {
1758
1814
  "default": "'fast'",
1759
1815
  "description": "Motion token for the close animation. Default: 'fast' (150ms)",
@@ -2526,7 +2582,7 @@
2526
2582
  "importPath": "@duro-app/ui",
2527
2583
  "kind": "component",
2528
2584
  "meta": {
2529
- "description": "Grid layout. Columns are a count (1-6), a list of weights ([1, 2] for one-third / two-thirds), responsive auto-fit via minColumnWidth, or a named split layout (list/detail, nav/content) that collapses to one column on the width of its own container, so it is safe to nest and to place beside a DetailPanel. Weights rather than CSS template strings, so the same props render as CSS grid on web and as a wrapping flex row on native.",
2585
+ "description": "Grid layout. Columns are a count (1-6), a list of weights ([1, 2] for one-third / two-thirds), responsive auto-fit via minColumnWidth, or a named split layout (list/detail, nav/content) that collapses to one column on the width of its own container, so it is safe to nest and to place beside a DetailPanel. Weights rather than CSS template strings, so the same props render as CSS grid on web and as a wrapping flex row on native. For a fixed track beside fractions (content + a 320px aside), tracks takes a token track list — tracks={['1fr', 'asideW']} — web only, equal columns on native.",
2530
2586
  "example": "// Split: list ≥ sizes.gridColSm (240px) beside a detail pane, one column below md\n<Grid layout=\"split\" gap=\"lg\">\n <List.Root>…</List.Root>\n <Panel.Root>…</Panel.Root>\n</Grid>\n\n// Responsive: columns auto-fit based on min width\n<Grid minColumnWidth=\"gridColMd\" gap=\"md\">\n <Card>A</Card>\n <Card>B</Card>\n <Card>C</Card>\n</Grid>\n\n// Fixed: always 3 columns\n<Grid columns={3} gap=\"md\">\n <Card>A</Card>\n <Card>B</Card>\n <Card>C</Card>\n</Grid>\n\n// Weighted: a one-third / two-thirds split (works on native too)\n<Grid columns={[1, 2]} gap=\"md\">\n <Card>Sidebar</Card>\n <Card>Content</Card>\n</Grid>",
2531
2587
  "relatedTo": [
2532
2588
  {
@@ -2586,6 +2642,12 @@
2586
2642
  "required": false,
2587
2643
  "type": "GridLayout"
2588
2644
  },
2645
+ {
2646
+ "description": "An explicit track list, for columns that are not all fractions: a size token for a fixed track (`['1fr', 'asideW']`), or `minmax()` / `fit-content()` of tokens and fractions (`'minmax(gridColXs, 1fr)'`). A px is a type error. Web only — on native it falls back to equal columns, one per track. Wins over `columns` / `minColumnWidth`; `layout` wins over it.",
2647
+ "name": "tracks",
2648
+ "required": false,
2649
+ "type": "readonly GridTrack[]"
2650
+ },
2589
2651
  {
2590
2652
  "name": "children",
2591
2653
  "required": true,
@@ -2819,7 +2881,7 @@
2819
2881
  "importPath": "@duro-app/ui",
2820
2882
  "kind": "component",
2821
2883
  "meta": {
2822
- "description": "Text input with automatic Field/Form integration. Variant auto-switches to error when inside an invalid Field.",
2884
+ "description": "Text input with automatic Field/Form integration. Variant auto-switches to error when inside an invalid Field. variant=\"ghost\" reads as text until hovered (hairline border) or focused (accent border and ring): only for inline edit where a visible Field.Label names it; it shows the error state when the Field is invalid.",
2823
2885
  "example": "<Field.Root name=\"email\">\n <Field.Label>Email</Field.Label>\n <Input type=\"email\" placeholder=\"you@example.com\" autoComplete=\"email\" />\n <Field.Error />\n</Field.Root>",
2824
2886
  "relatedTo": [
2825
2887
  {
@@ -2840,22 +2902,26 @@
2840
2902
  ],
2841
2903
  "whenNotToUse": [
2842
2904
  "Multi-line text — use Textarea",
2843
- "Picking from predefined options — use Select"
2905
+ "Picking from predefined options — use Select",
2906
+ "A ghost field without a visible label — it reads as plain text, so the label is what says it is editable"
2844
2907
  ],
2845
2908
  "whenToUse": [
2846
- "Single-line text entry (text, email, password, url, tel, number, search)"
2909
+ "Single-line text entry (text, email, password, url, tel, number, search)",
2910
+ "Inline edit of a labelled value in place (a ticket title) — variant=\"ghost\""
2847
2911
  ]
2848
2912
  },
2849
2913
  "name": "Input",
2850
2914
  "props": [
2851
2915
  {
2852
2916
  "default": "'default'",
2917
+ "description": "`ghost` reads as text until hovered or focused — only for inline edit where a visible label names the field (Field.Label). It shows the error state when the Field is invalid.",
2853
2918
  "name": "variant",
2854
2919
  "required": false,
2855
2920
  "type": "InputVariant",
2856
2921
  "union": [
2857
2922
  "default",
2858
- "error"
2923
+ "error",
2924
+ "ghost"
2859
2925
  ]
2860
2926
  },
2861
2927
  {
@@ -3072,6 +3138,12 @@
3072
3138
  "required": false,
3073
3139
  "type": "Length"
3074
3140
  },
3141
+ {
3142
+ "description": "Accessible name of a clickable addon (it renders a button). Required when its content is an icon (copy, reveal): without it the button has no name.",
3143
+ "name": "aria-label",
3144
+ "required": false,
3145
+ "type": "string"
3146
+ },
3075
3147
  {
3076
3148
  "name": "children",
3077
3149
  "required": true,
@@ -3363,6 +3435,197 @@
3363
3435
  "props": null,
3364
3436
  "sourcePath": "packages/ui/src/components/List/List.tsx"
3365
3437
  },
3438
+ "Listbox": {
3439
+ "importPath": "@duro-app/ui",
3440
+ "kind": "compound",
3441
+ "meta": {
3442
+ "anatomy": {
3443
+ "optional": [
3444
+ "Empty"
3445
+ ],
3446
+ "required": [
3447
+ "Root",
3448
+ "Option"
3449
+ ]
3450
+ },
3451
+ "description": "Popup list of options for an input that keeps focus — an editor typeahead (mentions, slash commands) or a custom combobox. The anchor owns focus and the keyboard: it sets the controlled highlightedId and spreads Listbox.getAnchorProps() for aria-controls / aria-expanded / aria-activedescendant. A press on an option never takes focus from the anchor. Portalled and placed against anchor() (an input rect or a caret rect), capped at a size-token maxHeight (default listMaxH).",
3452
+ "example": "const id = useId()\nconst [highlightedId, setHighlightedId] = useState<string | null>(null)\nconst optionId = (value: string) => `${id}-${value}`\n// On the editor root: Object.entries(Listbox.getAnchorProps({id, open, highlightedId}))\n<Listbox.Root\n id={id}\n open={open}\n anchor={() => caretRect()}\n highlightedId={highlightedId}\n onHighlight={setHighlightedId}\n onSelect={(value) => insertMention(value)}\n getOptionId={optionId}\n aria-label=\"Mentions\"\n>\n {people.map((p) => (\n <Listbox.Option key={p.id} value={p.id}>{p.name}</Listbox.Option>\n ))}\n {people.length === 0 && <Listbox.Empty>No match</Listbox.Empty>}\n</Listbox.Root>",
3453
+ "relatedTo": [
3454
+ {
3455
+ "component": "Combobox",
3456
+ "kind": "contrast",
3457
+ "relationship": "Combobox is a ready-made input + Listbox; Listbox alone serves an anchor you own (an editor)"
3458
+ },
3459
+ {
3460
+ "component": "Menu",
3461
+ "kind": "contrast",
3462
+ "relationship": "Menu takes focus and triggers actions; Listbox leaves focus on its anchor and offers values"
3463
+ }
3464
+ ],
3465
+ "whenNotToUse": [
3466
+ "Picking a value from a filterable list in a form — use Combobox (built on Listbox)",
3467
+ "A short fixed list — use Select",
3468
+ "Actions — use Menu"
3469
+ ],
3470
+ "whenToUse": [
3471
+ "Typeahead inside a rich-text editor, where focus must stay in the editor",
3472
+ "A custom combobox whose input is not Combobox.Input"
3473
+ ]
3474
+ },
3475
+ "name": "Listbox",
3476
+ "parts": {
3477
+ "Empty": {
3478
+ "name": "Empty",
3479
+ "props": [
3480
+ {
3481
+ "name": "children",
3482
+ "required": true,
3483
+ "type": "ReactNode"
3484
+ }
3485
+ ],
3486
+ "sourcePath": "packages/ui/src/components/Listbox/Listbox.tsx"
3487
+ },
3488
+ "Option": {
3489
+ "name": "Option",
3490
+ "props": [
3491
+ {
3492
+ "name": "value",
3493
+ "required": true,
3494
+ "type": "string"
3495
+ },
3496
+ {
3497
+ "description": "DOM id. Default: Root's getOptionId(value).",
3498
+ "name": "id",
3499
+ "required": false,
3500
+ "type": "string"
3501
+ },
3502
+ {
3503
+ "default": "false",
3504
+ "description": "The committed choice (aria-selected).",
3505
+ "name": "selected",
3506
+ "required": false,
3507
+ "type": "boolean"
3508
+ },
3509
+ {
3510
+ "default": "false",
3511
+ "name": "disabled",
3512
+ "required": false,
3513
+ "type": "boolean"
3514
+ },
3515
+ {
3516
+ "name": "children",
3517
+ "required": true,
3518
+ "type": "ReactNode"
3519
+ },
3520
+ {
3521
+ "name": "ref",
3522
+ "required": false,
3523
+ "type": "Ref<HTMLDivElement>"
3524
+ }
3525
+ ],
3526
+ "sourcePath": "packages/ui/src/components/Listbox/Listbox.tsx"
3527
+ },
3528
+ "Root": {
3529
+ "name": "Root",
3530
+ "props": [
3531
+ {
3532
+ "description": "DOM id of the list; pass the same to getAnchorProps.",
3533
+ "name": "id",
3534
+ "required": true,
3535
+ "type": "string"
3536
+ },
3537
+ {
3538
+ "name": "open",
3539
+ "required": true,
3540
+ "type": "boolean"
3541
+ },
3542
+ {
3543
+ "description": "The rect the list is placed against: the input, or the editor's caret.",
3544
+ "name": "anchor",
3545
+ "required": true,
3546
+ "type": "() => DOMRect | null | undefined"
3547
+ },
3548
+ {
3549
+ "default": "false",
3550
+ "description": "Give the list the anchor's width (a Combobox under its input).",
3551
+ "name": "matchAnchorWidth",
3552
+ "required": false,
3553
+ "type": "boolean"
3554
+ },
3555
+ {
3556
+ "description": "Id of the highlighted option, controlled by the anchor's keyboard handling.",
3557
+ "name": "highlightedId",
3558
+ "required": true,
3559
+ "type": "string | null"
3560
+ },
3561
+ {
3562
+ "description": "Pointer hover asks to move the highlight.",
3563
+ "name": "onHighlight",
3564
+ "required": false,
3565
+ "type": "(id: string | null) => void"
3566
+ },
3567
+ {
3568
+ "description": "A press on an option.",
3569
+ "name": "onSelect",
3570
+ "required": false,
3571
+ "type": "(value: string) => void"
3572
+ },
3573
+ {
3574
+ "description": "Option value → DOM id. Default: defaultOptionId(id, value).",
3575
+ "name": "getOptionId",
3576
+ "required": false,
3577
+ "type": "(value: string) => string"
3578
+ },
3579
+ {
3580
+ "description": "Accessible name of the list.",
3581
+ "name": "aria-label",
3582
+ "required": false,
3583
+ "type": "string"
3584
+ },
3585
+ {
3586
+ "default": "'listMaxH'",
3587
+ "description": "Size-token key capping the list's height; longer lists scroll. Default: listMaxH.",
3588
+ "name": "maxHeight",
3589
+ "required": false,
3590
+ "type": "ListboxMaxHeight",
3591
+ "union": [
3592
+ "listMaxH",
3593
+ "listMaxHSm"
3594
+ ]
3595
+ },
3596
+ {
3597
+ "name": "children",
3598
+ "required": true,
3599
+ "type": "ReactNode"
3600
+ }
3601
+ ],
3602
+ "sourcePath": "packages/ui/src/components/Listbox/Listbox.tsx"
3603
+ },
3604
+ "getAnchorProps": {
3605
+ "name": "getAnchorProps",
3606
+ "props": [
3607
+ {
3608
+ "name": "id",
3609
+ "required": true,
3610
+ "type": "string"
3611
+ },
3612
+ {
3613
+ "name": "open",
3614
+ "required": true,
3615
+ "type": "boolean"
3616
+ },
3617
+ {
3618
+ "name": "highlightedId",
3619
+ "required": true,
3620
+ "type": "string | null | undefined"
3621
+ }
3622
+ ],
3623
+ "sourcePath": "packages/ui/src/components/Listbox/Listbox.tsx"
3624
+ }
3625
+ },
3626
+ "props": null,
3627
+ "sourcePath": "packages/ui/src/components/Listbox/Listbox.tsx"
3628
+ },
3366
3629
  "Menu": {
3367
3630
  "importPath": "@duro-app/ui",
3368
3631
  "kind": "compound",
@@ -3379,7 +3642,7 @@
3379
3642
  "Item"
3380
3643
  ]
3381
3644
  },
3382
- "description": "Dropdown action menu. Triggers actions (not value selection). Compound component — Root is required (throws without it). Menu.Trigger renders the button itself: give it the label (text, an Icon), never a Button.",
3645
+ "description": "Dropdown action menu. Triggers actions (not value selection). Compound component — Root is required (throws without it). Menu.Trigger renders the button itself: give it the label (text, an Icon), never a Button; an icon-only trigger takes aria-label, and variant=\"ghost\" suits toolbars. The popup is portalled and placed against the trigger (never clipped by a sticky or overflow ancestor), capped at sizes.listMaxH with scrolling, and takes focus on open (WAI-ARIA menu button); Escape closes only the menu, not an enclosing Popover or Dialog.",
3383
3646
  "example": "<Menu.Root>\n <Menu.Trigger>Actions</Menu.Trigger>\n <Menu.Popup>\n <Menu.Item onClick={() => console.log('edit')}>Edit</Menu.Item>\n <Menu.Item onClick={() => console.log('duplicate')}>Duplicate</Menu.Item>\n <Menu.Separator />\n <Menu.LinkItem href=\"/settings\">Settings</Menu.LinkItem>\n </Menu.Popup>\n</Menu.Root>",
3384
3647
  "relatedTo": [
3385
3648
  {
@@ -3401,7 +3664,8 @@
3401
3664
  "whenToUse": [
3402
3665
  "Context menu or \"more actions\" dropdown",
3403
3666
  "Navigation links in a dropdown",
3404
- "Overflow menu for toolbar actions"
3667
+ "Overflow menu for toolbar actions",
3668
+ "A toolbar dropdown (align, insert) in an editor — Menu.Trigger variant=\"ghost\""
3405
3669
  ]
3406
3670
  },
3407
3671
  "name": "Menu",
@@ -3462,6 +3726,24 @@
3462
3726
  "name": "children",
3463
3727
  "required": true,
3464
3728
  "type": "ReactNode"
3729
+ },
3730
+ {
3731
+ "description": "Controlled open state.",
3732
+ "name": "open",
3733
+ "required": false,
3734
+ "type": "boolean"
3735
+ },
3736
+ {
3737
+ "description": "Initial open state (uncontrolled).",
3738
+ "name": "defaultOpen",
3739
+ "required": false,
3740
+ "type": "boolean"
3741
+ },
3742
+ {
3743
+ "description": "Called when the menu opens or closes.",
3744
+ "name": "onOpenChange",
3745
+ "required": false,
3746
+ "type": "(open: boolean) => void"
3465
3747
  }
3466
3748
  ],
3467
3749
  "sourcePath": "packages/ui/src/components/Menu/Menu.tsx"
@@ -3478,6 +3760,24 @@
3478
3760
  "name": "children",
3479
3761
  "required": true,
3480
3762
  "type": "ReactNode"
3763
+ },
3764
+ {
3765
+ "description": "Accessible name — required when the label is an icon only.",
3766
+ "name": "aria-label",
3767
+ "required": false,
3768
+ "type": "string"
3769
+ },
3770
+ {
3771
+ "default": "'default'",
3772
+ "description": "`ghost`: no border or fill until hover, for toolbars. Default: `default`.",
3773
+ "name": "variant",
3774
+ "required": false,
3775
+ "type": "MenuTriggerVariant"
3776
+ },
3777
+ {
3778
+ "name": "ref",
3779
+ "required": false,
3780
+ "type": "Ref<HTMLButtonElement>"
3481
3781
  }
3482
3782
  ],
3483
3783
  "sourcePath": "packages/ui/src/components/Menu/Menu.tsx"
@@ -3898,6 +4198,18 @@
3898
4198
  "name": "children",
3899
4199
  "required": true,
3900
4200
  "type": "ReactNode"
4201
+ },
4202
+ {
4203
+ "description": "Accessible name: required when the label is an icon only.",
4204
+ "name": "aria-label",
4205
+ "required": false,
4206
+ "type": "string"
4207
+ },
4208
+ {
4209
+ "description": "The trigger <button>, e.g. to measure it or return focus to it.",
4210
+ "name": "ref",
4211
+ "required": false,
4212
+ "type": "Ref<HTMLButtonElement>"
3901
4213
  }
3902
4214
  ],
3903
4215
  "sourcePath": "packages/ui/src/components/Popover/Popover.tsx"
@@ -5677,45 +5989,117 @@
5677
5989
  ],
5678
5990
  "sourcePath": "packages/diagrams/src/components/Text/Text.tsx"
5679
5991
  },
5680
- "Textarea": {
5992
+ "TextLink": {
5681
5993
  "importPath": "@duro-app/ui",
5682
5994
  "kind": "component",
5683
5995
  "meta": {
5684
- "description": "Multi-line text input with automatic Field/Form integration. Same Field binding behavior as Input.",
5685
- "example": "<Field.Root name=\"message\">\n <Field.Label>Message</Field.Label>\n <Textarea placeholder=\"Tell us what you think...\" rows={4} />\n <Field.Description>At least 10 characters</Field.Description>\n <Field.Error />\n</Field.Root>",
5996
+ "description": "Inline hyperlink for running text and standalone text links (\"View all\", \"Edit profile\"). Always underlined, so colour is never the only cue: default is accent text with an accent underline; subtle keeps the surrounding text colour with a muted underline and turns accent on hover. target=\"_blank\" defaults rel to noopener noreferrer.",
5997
+ "example": "<Text>\n Read the <TextLink href=\"/docs/migrate\">migration guide</TextLink> before you change seats, or{' '}\n <TextLink href=\"/plans\" variant=\"subtle\">compare plans</TextLink> first.\n</Text>",
5686
5998
  "relatedTo": [
5687
5999
  {
5688
- "component": "Input",
6000
+ "component": "LinkButton",
5689
6001
  "kind": "contrast",
5690
- "relationship": "Input for single-line entry; Textarea for multi-line"
6002
+ "relationship": "LinkButton is a hyperlink styled as a button; TextLink is a hyperlink styled as text"
5691
6003
  },
5692
6004
  {
5693
- "component": "Field",
5694
- "kind": "composition",
5695
- "relationship": "Wrap in Field.Root for label + error"
6005
+ "component": "Button",
6006
+ "kind": "contrast",
6007
+ "relationship": "Button runs an action; TextLink navigates"
5696
6008
  }
5697
6009
  ],
5698
6010
  "whenNotToUse": [
5699
- "Single-line input — use Input"
6011
+ "A link that should look like a button — use LinkButton",
6012
+ "An action that does not navigate — use Button (variant=\"link\" for a text-styled action)",
6013
+ "A link inside a dropdown — use Menu.LinkItem"
5700
6014
  ],
5701
6015
  "whenToUse": [
5702
- "Multi-line text entry (comments, messages, descriptions)"
6016
+ "A link inside a sentence or paragraph",
6017
+ "A standalone text link under a list or card (\"View all requests\")",
6018
+ "A quiet link in dense UI (variant=\"subtle\")"
5703
6019
  ]
5704
6020
  },
5705
- "name": "Textarea",
6021
+ "name": "TextLink",
5706
6022
  "props": [
5707
6023
  {
5708
- "default": "'default'",
5709
- "name": "variant",
5710
- "required": false,
5711
- "type": "TextareaVariant",
5712
- "union": [
5713
- "default",
5714
- "error"
5715
- ]
6024
+ "name": "href",
6025
+ "required": true,
6026
+ "type": "string"
5716
6027
  },
5717
6028
  {
5718
- "name": "name",
6029
+ "description": "`_blank` opens a new tab; `rel` then defaults to `noopener noreferrer`.",
6030
+ "name": "target",
6031
+ "required": false,
6032
+ "type": "'_blank' | '_self'"
6033
+ },
6034
+ {
6035
+ "name": "rel",
6036
+ "required": false,
6037
+ "type": "string"
6038
+ },
6039
+ {
6040
+ "default": "'default'",
6041
+ "description": "`default`: accent text with an accent underline. `subtle`: the surrounding text colour with a muted underline, accent on hover. Both stay underlined, so colour is never the only cue in running text.",
6042
+ "name": "variant",
6043
+ "required": false,
6044
+ "type": "TextLinkVariant",
6045
+ "union": [
6046
+ "default",
6047
+ "subtle"
6048
+ ]
6049
+ },
6050
+ {
6051
+ "description": "Accessible name, when the visible text alone does not say where it goes.",
6052
+ "name": "aria-label",
6053
+ "required": false,
6054
+ "type": "string"
6055
+ },
6056
+ {
6057
+ "name": "children",
6058
+ "required": true,
6059
+ "type": "ReactNode"
6060
+ }
6061
+ ],
6062
+ "sourcePath": "packages/ui/src/components/TextLink/TextLink.tsx"
6063
+ },
6064
+ "Textarea": {
6065
+ "importPath": "@duro-app/ui",
6066
+ "kind": "component",
6067
+ "meta": {
6068
+ "description": "Multi-line text input with automatic Field/Form integration. Same Field binding behavior as Input.",
6069
+ "example": "<Field.Root name=\"message\">\n <Field.Label>Message</Field.Label>\n <Textarea placeholder=\"Tell us what you think...\" rows={4} />\n <Field.Description>At least 10 characters</Field.Description>\n <Field.Error />\n</Field.Root>",
6070
+ "relatedTo": [
6071
+ {
6072
+ "component": "Input",
6073
+ "kind": "contrast",
6074
+ "relationship": "Input for single-line entry; Textarea for multi-line"
6075
+ },
6076
+ {
6077
+ "component": "Field",
6078
+ "kind": "composition",
6079
+ "relationship": "Wrap in Field.Root for label + error"
6080
+ }
6081
+ ],
6082
+ "whenNotToUse": [
6083
+ "Single-line input — use Input"
6084
+ ],
6085
+ "whenToUse": [
6086
+ "Multi-line text entry (comments, messages, descriptions)"
6087
+ ]
6088
+ },
6089
+ "name": "Textarea",
6090
+ "props": [
6091
+ {
6092
+ "default": "'default'",
6093
+ "name": "variant",
6094
+ "required": false,
6095
+ "type": "TextareaVariant",
6096
+ "union": [
6097
+ "default",
6098
+ "error"
6099
+ ]
6100
+ },
6101
+ {
6102
+ "name": "name",
5719
6103
  "required": false,
5720
6104
  "type": "string"
5721
6105
  },
@@ -6069,6 +6453,76 @@
6069
6453
  ],
6070
6454
  "sourcePath": "packages/ui/src/components/ToggleGroup/ToggleGroup.tsx"
6071
6455
  },
6456
+ "Toolbar": {
6457
+ "importPath": "@duro-app/ui",
6458
+ "kind": "component",
6459
+ "meta": {
6460
+ "anatomy": {
6461
+ "optional": [
6462
+ "ButtonGroup attached",
6463
+ "Toggle",
6464
+ "Button",
6465
+ "Select",
6466
+ "Menu",
6467
+ "Popover"
6468
+ ],
6469
+ "required": [
6470
+ "Toolbar",
6471
+ "aria-label"
6472
+ ]
6473
+ },
6474
+ "description": "A row of controls with one tab stop (the WAI-ARIA toolbar pattern): Tab enters at the last focused control, Left/Right move across every control inside — through attached ButtonGroups too — and Home/End jump to the ends. A Select or Menu trigger keeps its own keys, and a control whose popup is open keeps Left/Right.",
6475
+ "example": "<Toolbar aria-label=\"Formatting\">\n <ButtonGroup attached aria-label=\"Text style\">\n <Toggle aria-label=\"Bold\" pressed={bold} onPressedChange={setBold}>B</Toggle>\n <Toggle aria-label=\"Italic\" pressed={italic} onPressedChange={setItalic}>I</Toggle>\n </ButtonGroup>\n <Menu.Root>\n <Menu.Trigger>Insert</Menu.Trigger>\n <Menu.Popup>…</Menu.Popup>\n </Menu.Root>\n</Toolbar>",
6476
+ "relatedTo": [
6477
+ {
6478
+ "component": "ButtonGroup",
6479
+ "kind": "composition",
6480
+ "relationship": "Place attached ButtonGroups inside a Toolbar: the group joins the controls visually, the toolbar gives them one tab stop and arrow keys"
6481
+ },
6482
+ {
6483
+ "component": "ToggleGroup",
6484
+ "kind": "composition",
6485
+ "relationship": "A ToggleGroup inside a Toolbar hands its arrow keys to the toolbar (one roving handler)"
6486
+ },
6487
+ {
6488
+ "component": "ActionBar",
6489
+ "kind": "contrast",
6490
+ "relationship": "ActionBar floats over a selection; Toolbar sits in the layout"
6491
+ }
6492
+ ],
6493
+ "whenNotToUse": [
6494
+ "A dialog footer or a form action row — use ButtonGroup (every button its own tab stop)",
6495
+ "A floating bulk-selection bar — use ActionBar",
6496
+ "A vertical toolbar holding a Select: a closed Select takes ArrowDown/ArrowUp to open, so use the horizontal orientation (a Menu is fine: its closed trigger handles no arrow key, Enter or Space opens it)"
6497
+ ],
6498
+ "whenToUse": [
6499
+ "An editor toolbar: text style, format toggles, insert menus",
6500
+ "A dense set of related actions that should cost one Tab, not one per control"
6501
+ ]
6502
+ },
6503
+ "name": "Toolbar",
6504
+ "props": [
6505
+ {
6506
+ "description": "Names the toolbar (\"Formatting\"). Required: a toolbar is a landmark-like widget.",
6507
+ "name": "aria-label",
6508
+ "required": true,
6509
+ "type": "string"
6510
+ },
6511
+ {
6512
+ "default": "'horizontal'",
6513
+ "description": "Arrow keys follow the orientation: Left/Right (default) or Up/Down. A vertical toolbar cannot hold a Select, whose closed trigger opens on ArrowDown/ArrowUp. A Menu can: its closed trigger handles no arrow key, so Up/Down move past it and Enter or Space opens it.",
6514
+ "name": "orientation",
6515
+ "required": false,
6516
+ "type": "Orientation"
6517
+ },
6518
+ {
6519
+ "name": "children",
6520
+ "required": true,
6521
+ "type": "ReactNode"
6522
+ }
6523
+ ],
6524
+ "sourcePath": "packages/ui/src/components/Toolbar/Toolbar.tsx"
6525
+ },
6072
6526
  "Tooltip": {
6073
6527
  "importPath": "@duro-app/ui",
6074
6528
  "kind": "compound",
@@ -6410,6 +6864,38 @@
6410
6864
  ],
6411
6865
  "sourcePath": "packages/ui/src/components/VirtualTable/VirtualTable.tsx"
6412
6866
  },
6867
+ "VisuallyHidden": {
6868
+ "importPath": "@duro-app/ui",
6869
+ "kind": "component",
6870
+ "meta": {
6871
+ "description": "Text for assistive tech only: kept in the accessibility tree, clipped off screen. Gives words to an icon-only control or a visual-only cue.",
6872
+ "example": "<Button variant=\"secondary\">\n <Icon name=\"search\" size=\"sm\" />\n <VisuallyHidden>Search</VisuallyHidden>\n</Button>",
6873
+ "whenNotToUse": [
6874
+ "Naming a control that takes aria-label — pass aria-label instead",
6875
+ "Hiding content from everyone — render nothing, or use display: none"
6876
+ ],
6877
+ "whenToUse": [
6878
+ "A label for an icon inside a control that has no aria-label prop",
6879
+ "Spelling out what a colour or icon shows (a status dot, \"(opens in a new tab)\")",
6880
+ "A heading that structures a page for screen readers without a visible title"
6881
+ ]
6882
+ },
6883
+ "name": "VisuallyHidden",
6884
+ "props": [
6885
+ {
6886
+ "name": "children",
6887
+ "required": true,
6888
+ "type": "ReactNode"
6889
+ },
6890
+ {
6891
+ "description": "For aria-describedby / aria-labelledby to point at.",
6892
+ "name": "id",
6893
+ "required": false,
6894
+ "type": "string"
6895
+ }
6896
+ ],
6897
+ "sourcePath": "packages/ui/src/components/VisuallyHidden/VisuallyHidden.tsx"
6898
+ },
6413
6899
  "useColorMode": {
6414
6900
  "importPath": "@duro-app/ui",
6415
6901
  "kind": "hook",
@@ -7006,15 +7492,6 @@
7006
7492
  },
7007
7493
  "severity": "error"
7008
7494
  },
7009
- {
7010
- "description": "Disallow non-zero flexGrow in css.create styles (react-strict-dom forces flex-grow: 0 on web)",
7011
- "fixable": "none",
7012
- "id": "duro/no-flex-grow-web",
7013
- "messages": {
7014
- "flexGrowForced": "flexGrow has no effect under react-strict-dom on web — the runtime forces computed flex-grow: 0, so this layout silently collapses. Lay out with a plain DOM scaffold, or absolute-position against a measured container."
7015
- },
7016
- "severity": "warn"
7017
- },
7018
7495
  {
7019
7496
  "description": "Disallow raw px breakpoints in media-query strings; use breakpoints.<key>",
7020
7497
  "fixable": "autofix",
@@ -7031,6 +7508,7 @@
7031
7508
  "messages": {
7032
7509
  "ambiguousMeasure": "{{value}} on `{{property}}` matches several {{group}} tokens ({{tokens}}). Pick the one that says what this measure is, from {{pkg}}/tokens/{{group}}.css.",
7033
7510
  "missingMeasureToken": "{{value}} on `{{property}}` has no token. Add a token (design-system.a-missing-token-is-added-not-approximated) instead of using a raw value.",
7511
+ "nearestMeasureRole": "{{value}} on `{{property}}` has no token; nearest role: {{nearest}}. If this measure plays that role, use its token and take its value; if not, add a token (design-system.a-missing-token-is-added-not-approximated).",
7034
7512
  "offScaleRadius": "{{value}} on `{{property}}` is off the radius scale ({{scale}}px). Use the nearest `radii.*` token from {{pkg}}/tokens/spacing.css, or disable this line with the reason.",
7035
7513
  "offScaleSpacing": "{{value}} on `{{property}}` is off the spacing scale ({{scale}}px). Use the nearest `spacing.*` token from {{pkg}}/tokens/spacing.css, or disable this line with the reason.",
7036
7514
  "rawBreakpoint": "{{value}}px in `{{key}}` is a raw breakpoint. Use `breakpoints.{{token}}` from {{pkg}}/tokens/breakpoints.css in a template-literal key (the scale is {{scale}}px).",
@@ -7044,6 +7522,7 @@
7044
7522
  "rawMicroSpacing": "{{value}} on `{{property}}` is off the spacing scale; it is the {{token}} micro-spacing token. Use `microSpacing.{{token}}` from {{pkg}}/tokens/spacing.css, or the scale if the nudge is not needed.",
7045
7523
  "rawRadius": "{{value}} on `{{property}}` is the {{token}} radius token. Use `radii.{{token}}` from {{pkg}}/tokens/spacing.css.",
7046
7524
  "rawShadow": "'{{value}}' on `boxShadow` is a raw shadow. Use `shadows.{{token}}` from {{pkg}}/tokens/shadows.css.",
7525
+ "rawShadowLength": "{{value}} on `boxShadow` builds a shadow from a raw px length. Use a `shadows.*` token from {{pkg}}/tokens/shadows.css.",
7047
7526
  "rawSpacing": "{{value}} on `{{property}}` is the {{token}} spacing token. Use `spacing.{{token}}` from {{pkg}}/tokens/spacing.css.",
7048
7527
  "rawTrack": "{{value}} on `{{property}}` sizes a track in px. Put a size token inside it: `minmax(${sizes.gridColSm}, 1fr)` from {{pkg}}/tokens/sizes.css.",
7049
7528
  "replaceWithToken": "Replace with {{replacement}}"
@@ -7061,6 +7540,18 @@
7061
7540
  },
7062
7541
  "severity": "error"
7063
7542
  },
7543
+ {
7544
+ "description": "Prefer the layers (z-index) and effects tokens over raw z-index and blur values in css.create styles",
7545
+ "fixable": "suggestion",
7546
+ "id": "duro/no-raw-layer-values",
7547
+ "messages": {
7548
+ "offScaleZIndex": "{{value}} on `zIndex` is not a layer; it sits {{nearest}}. Use a `layers.*` token from {{pkg}}/tokens/layers.css when it plays that role; a stacking value local to one component has no token yet.",
7549
+ "rawEffect": "'{{value}}' on `{{property}}` is a raw effect{{tokenText}}. Use the `effects.*` tokens from {{pkg}}/tokens/effects.css.",
7550
+ "rawZIndex": "{{value}} on `zIndex` is the layers.{{token}} token. Use it from {{pkg}}/tokens/layers.css.",
7551
+ "replaceWithToken": "Replace with {{replacement}}"
7552
+ },
7553
+ "severity": "warn"
7554
+ },
7064
7555
  {
7065
7556
  "description": "Require deep imports from @duro-app/tokens (barrel imports break StyleX)",
7066
7557
  "fixable": "autofix",
@@ -7361,6 +7852,38 @@
7361
7852
  "light": "#1e40af"
7362
7853
  }
7363
7854
  },
7855
+ {
7856
+ "key": "highlight",
7857
+ "values": {
7858
+ "dark": "#c084fc",
7859
+ "highContrast": "#d8b4fe",
7860
+ "light": "#6b21a8"
7861
+ }
7862
+ },
7863
+ {
7864
+ "key": "highlightBg",
7865
+ "values": {
7866
+ "dark": "rgba(192, 132, 252, 0.1)",
7867
+ "highContrast": "rgba(216, 180, 254, 0.15)",
7868
+ "light": "rgba(107, 33, 168, 0.08)"
7869
+ }
7870
+ },
7871
+ {
7872
+ "key": "highlightBorder",
7873
+ "values": {
7874
+ "dark": "rgba(192, 132, 252, 0.3)",
7875
+ "highContrast": "rgba(216, 180, 254, 0.5)",
7876
+ "light": "rgba(107, 33, 168, 0.3)"
7877
+ }
7878
+ },
7879
+ {
7880
+ "key": "highlightText",
7881
+ "values": {
7882
+ "dark": "#d8b4fe",
7883
+ "highContrast": "#e9d5ff",
7884
+ "light": "#581c87"
7885
+ }
7886
+ },
7364
7887
  {
7365
7888
  "key": "scrim",
7366
7889
  "values": {
@@ -7408,11 +7931,53 @@
7408
7931
  "highContrast": "#ffffff",
7409
7932
  "light": "#ffffff"
7410
7933
  }
7934
+ },
7935
+ {
7936
+ "key": "overlayLight",
7937
+ "values": {
7938
+ "dark": "rgba(255, 255, 255, 0.78)",
7939
+ "highContrast": "rgba(255, 255, 255, 0.78)",
7940
+ "light": "rgba(255, 255, 255, 0.78)"
7941
+ }
7942
+ },
7943
+ {
7944
+ "key": "contrastSurface",
7945
+ "values": {
7946
+ "dark": "#f5f5f5",
7947
+ "highContrast": "#ffffff",
7948
+ "light": "#1a1a1a"
7949
+ }
7950
+ },
7951
+ {
7952
+ "key": "onContrastSurface",
7953
+ "values": {
7954
+ "dark": "#1a1a1a",
7955
+ "highContrast": "#000000",
7956
+ "light": "#e5e5e5"
7957
+ }
7958
+ },
7959
+ {
7960
+ "key": "contrastBorder",
7961
+ "values": {
7962
+ "dark": "rgba(0, 0, 0, 0.42)",
7963
+ "highContrast": "rgba(0, 0, 0, 0.42)",
7964
+ "light": "rgba(255, 255, 255, 0.33)"
7965
+ }
7411
7966
  }
7412
7967
  ],
7413
7968
  "exportName": "colors",
7414
7969
  "importPath": "@duro-app/tokens/tokens/colors.css"
7415
7970
  },
7971
+ "effects": {
7972
+ "entries": [
7973
+ {
7974
+ "key": "overlayBlur",
7975
+ "value": "blur(2px)"
7976
+ }
7977
+ ],
7978
+ "exportName": "effects",
7979
+ "importPath": "@duro-app/tokens/tokens/effects.css"
7980
+ },
7416
7981
  "iconSizes": {
7417
7982
  "entries": [
7418
7983
  {
@@ -7439,6 +8004,48 @@
7439
8004
  "exportName": "ICON_SIZES",
7440
8005
  "importPath": "@duro-app/tokens/keys"
7441
8006
  },
8007
+ "layers": {
8008
+ "entries": [
8009
+ {
8010
+ "key": "raised",
8011
+ "value": "1"
8012
+ },
8013
+ {
8014
+ "key": "floating",
8015
+ "value": "50"
8016
+ },
8017
+ {
8018
+ "key": "overlay",
8019
+ "value": "1000"
8020
+ },
8021
+ {
8022
+ "key": "modal",
8023
+ "value": "1001"
8024
+ },
8025
+ {
8026
+ "key": "popover",
8027
+ "value": "1040"
8028
+ },
8029
+ {
8030
+ "key": "popupBackdrop",
8031
+ "value": "1049"
8032
+ },
8033
+ {
8034
+ "key": "popup",
8035
+ "value": "1050"
8036
+ },
8037
+ {
8038
+ "key": "toast",
8039
+ "value": "1060"
8040
+ },
8041
+ {
8042
+ "key": "portal",
8043
+ "value": "1100"
8044
+ }
8045
+ ],
8046
+ "exportName": "layers",
8047
+ "importPath": "@duro-app/tokens/tokens/layers.css"
8048
+ },
7442
8049
  "layoutSpacing": {
7443
8050
  "entries": [
7444
8051
  {
@@ -7612,6 +8219,14 @@
7612
8219
  {
7613
8220
  "key": "lg",
7614
8221
  "value": "0 8px 24px rgba(0, 0, 0, 0.5)"
8222
+ },
8223
+ {
8224
+ "key": "dropReady",
8225
+ "value": "inset 0 0 0 1px #333333"
8226
+ },
8227
+ {
8228
+ "key": "dropOver",
8229
+ "value": "inset 0 0 0 2px #6aaffc"
7615
8230
  }
7616
8231
  ],
7617
8232
  "exportName": "shadows",
@@ -7810,6 +8425,138 @@
7810
8425
  {
7811
8426
  "key": "pageLg",
7812
8427
  "value": "1200px"
8428
+ },
8429
+ {
8430
+ "key": "sidebarW",
8431
+ "value": "240px"
8432
+ },
8433
+ {
8434
+ "key": "pageXs",
8435
+ "value": "480px"
8436
+ },
8437
+ {
8438
+ "key": "pageXl",
8439
+ "value": "1440px"
8440
+ },
8441
+ {
8442
+ "key": "asideW",
8443
+ "value": "320px"
8444
+ },
8445
+ {
8446
+ "key": "gridColXs",
8447
+ "value": "200px"
8448
+ },
8449
+ {
8450
+ "key": "fieldMinWSm",
8451
+ "value": "80px"
8452
+ },
8453
+ {
8454
+ "key": "fieldMinW",
8455
+ "value": "160px"
8456
+ },
8457
+ {
8458
+ "key": "popoverWSm",
8459
+ "value": "240px"
8460
+ },
8461
+ {
8462
+ "key": "popoverW",
8463
+ "value": "320px"
8464
+ },
8465
+ {
8466
+ "key": "popupMaxW",
8467
+ "value": "280px"
8468
+ },
8469
+ {
8470
+ "key": "meterH",
8471
+ "value": "6px"
8472
+ },
8473
+ {
8474
+ "key": "skeletonChipW",
8475
+ "value": "96px"
8476
+ },
8477
+ {
8478
+ "key": "dropZoneMinH",
8479
+ "value": "128px"
8480
+ },
8481
+ {
8482
+ "key": "canvasMinH",
8483
+ "value": "480px"
8484
+ },
8485
+ {
8486
+ "key": "editorMinH",
8487
+ "value": "160px"
8488
+ },
8489
+ {
8490
+ "key": "toolbarH",
8491
+ "value": "36px"
8492
+ },
8493
+ {
8494
+ "key": "embedW",
8495
+ "value": "550px"
8496
+ },
8497
+ {
8498
+ "key": "colorPickerW",
8499
+ "value": "196px"
8500
+ },
8501
+ {
8502
+ "key": "colorAreaH",
8503
+ "value": "150px"
8504
+ },
8505
+ {
8506
+ "key": "colorTrackH",
8507
+ "value": "12px"
8508
+ },
8509
+ {
8510
+ "key": "colorSwatch",
8511
+ "value": "20px"
8512
+ },
8513
+ {
8514
+ "key": "colorPreviewH",
8515
+ "value": "22px"
8516
+ },
8517
+ {
8518
+ "key": "handle",
8519
+ "value": "16px"
8520
+ },
8521
+ {
8522
+ "key": "chip",
8523
+ "value": "24px"
8524
+ },
8525
+ {
8526
+ "key": "placeholderMinH",
8527
+ "value": "80px"
8528
+ },
8529
+ {
8530
+ "key": "previewMaxH",
8531
+ "value": "320px"
8532
+ },
8533
+ {
8534
+ "key": "barH",
8535
+ "value": "4px"
8536
+ },
8537
+ {
8538
+ "key": "readoutW",
8539
+ "value": "40px"
8540
+ },
8541
+ {
8542
+ "key": "sliderW",
8543
+ "value": "96px"
8544
+ },
8545
+ {
8546
+ "key": "paletteMinW",
8547
+ "value": "96px"
8548
+ },
8549
+ {
8550
+ "key": "deviceBarW",
8551
+ "value": "96px"
8552
+ },
8553
+ {
8554
+ "key": "timeGutterW",
8555
+ "value": "64px"
8556
+ },
8557
+ {
8558
+ "key": "dayHeaderH",
8559
+ "value": "46px"
7813
8560
  }
7814
8561
  ],
7815
8562
  "exportName": "sizes",
@@ -7960,7 +8707,7 @@
7960
8707
  "importPath": "@duro-app/tokens/tokens/typography.css"
7961
8708
  }
7962
8709
  },
7963
- "mockupCss": "/*\n * GENERATED by scripts/generate-mockup-css.mjs — do not edit.\n *\n * The design tokens as resolved values, for HTML that loads no stylesheet\n * (mockup artboards, static previews). Same names as vars.css; where vars.css\n * follows the live theme, this file carries every theme and switches on\n * <html data-theme=\"light|high-contrast\">.\n *\n * Inside the component library and the apps, never use this: go through\n * css.create() and the token imports, or vars.css from plain CSS.\n */\n:root {\n color-scheme: dark;\n /* colors */\n --duro-color-accent: #6aaffc;\n --duro-color-accent-contrast: #000000;\n --duro-color-accent-hover: #93c5fd;\n --duro-color-bg: #0f0f0f;\n --duro-color-bg-card: #1a1a1a;\n --duro-color-bg-card-hover: #242424;\n --duro-color-border: #333333;\n --duro-color-error: #f87171;\n --duro-color-error-bg: rgba(248, 113, 113, 0.1);\n --duro-color-error-border: rgba(248, 113, 113, 0.3);\n --duro-color-error-contrast: #000000;\n --duro-color-error-hover: #fca5a5;\n --duro-color-error-text: #fca5a5;\n --duro-color-fixed-light: #ffffff;\n --duro-color-info: #6aaffc;\n --duro-color-info-bg: rgba(106, 175, 252, 0.1);\n --duro-color-info-border: rgba(106, 175, 252, 0.3);\n --duro-color-info-text: #93c5fd;\n --duro-color-inverse-border: rgba(0, 0, 0, 0.55);\n --duro-color-inverse-border-hover: rgba(0, 0, 0, 0.70);\n --duro-color-inverse-fill: rgba(0, 0, 0, 0.10);\n --duro-color-inverse-fill-hover: rgba(0, 0, 0, 0.18);\n --duro-color-scrim: rgba(0, 0, 0, 0.4);\n --duro-color-success: #22c55e;\n --duro-color-success-bg: rgba(34, 197, 94, 0.1);\n --duro-color-success-border: rgba(34, 197, 94, 0.3);\n --duro-color-success-text: #86efac;\n --duro-color-text: #e5e5e5;\n --duro-color-text-muted: #b0b0b0;\n --duro-color-warning: #fbbf24;\n --duro-color-warning-bg: rgba(251, 191, 36, 0.1);\n --duro-color-warning-border: rgba(251, 191, 36, 0.3);\n --duro-color-warning-text: #fde68a;\n /* shadows */\n --duro-shadow-lg: 0 8px 24px rgba(0, 0, 0, 0.5);\n --duro-shadow-md: 0 4px 12px rgba(0, 0, 0, 0.4);\n --duro-shadow-sm: 0 2px 4px rgba(0, 0, 0, 0.3);\n /* spacing */\n --duro-spacing-lg: 24px;\n --duro-spacing-md: 16px;\n --duro-spacing-ms: 12px;\n --duro-spacing-sm: 8px;\n --duro-spacing-xl: 32px;\n --duro-spacing-xs: 4px;\n --duro-spacing-xxl: 48px;\n --duro-spacing-xxxl: 64px;\n /* microSpacing */\n --duro-micro-spacing-px1: 1px;\n --duro-micro-spacing-px2: 2px;\n --duro-micro-spacing-px3: 3px;\n --duro-micro-spacing-px5: 5px;\n --duro-micro-spacing-px6: 6px;\n /* radii */\n --duro-radius-full: 9999px;\n --duro-radius-lg: 16px;\n --duro-radius-md: 12px;\n --duro-radius-px6: 6px;\n --duro-radius-sm: 8px;\n --duro-radius-xs: 4px;\n /* sizes */\n --duro-size-check-mark-h: 9px;\n --duro-size-check-mark-w: 5px;\n --duro-size-control-lg: 40px;\n --duro-size-control-md: 39px;\n --duro-size-control-sm: 28px;\n --duro-size-dialog-lg: 680px;\n --duro-size-dialog-md: 520px;\n --duro-size-dialog-sm: 400px;\n --duro-size-divider: 1px;\n --duro-size-edge-fade: 32px;\n --duro-size-glyph-md: 16px;\n --duro-size-glyph-sm: 12px;\n --duro-size-glyph-xs: 10px;\n --duro-size-grid-col-md: 280px;\n --duro-size-grid-col-sm: 240px;\n --duro-size-icon-button: 32px;\n --duro-size-icon-button-sm: 28px;\n --duro-size-icon-lg: 24px;\n --duro-size-icon-md: 18px;\n --duro-size-icon-sm: 16px;\n --duro-size-icon-xl: 36px;\n --duro-size-icon-xxl: 48px;\n --duro-size-indicator: 18px;\n --duro-size-indicator-dot: 8px;\n --duro-size-label-min-w: 120px;\n --duro-size-list-max-h: 280px;\n --duro-size-list-max-h-sm: 200px;\n --duro-size-nav-marker-h: 18px;\n --duro-size-nav-marker-w: 3px;\n --duro-size-page-lg: 1200px;\n --duro-size-page-md: 800px;\n --duro-size-page-sm: 600px;\n --duro-size-panel-lg: 640px;\n --duro-size-panel-md: 480px;\n --duro-size-panel-sm: 360px;\n --duro-size-popup-min-w: 160px;\n --duro-size-scrollbar: 8px;\n --duro-size-spinner-lg: 40px;\n --duro-size-spinner-md: 24px;\n --duro-size-spinner-sm: 16px;\n --duro-size-swatch-h: 34px;\n --duro-size-swatch-w: 44px;\n --duro-size-switch-thumb: 16px;\n --duro-size-switch-track-h: 20px;\n --duro-size-switch-track-w: 36px;\n --duro-size-tab-indicator: 2px;\n --duro-size-toast-max-w: 440px;\n --duro-size-touch-target: 44px;\n /* borders */\n --duro-border-accent: 3px;\n --duro-border-focus-offset: 2px;\n --duro-border-focus-offset-sm: 1px;\n --duro-border-focus-ring: 2px;\n --duro-border-hairline: 1px;\n --duro-border-strong: 2px;\n /* layoutSpacing */\n --duro-layout-spacing-container-lg: 32px;\n --duro-layout-spacing-container-md: 24px;\n --duro-layout-spacing-container-sm: 16px;\n --duro-layout-spacing-inline-lg: 24px;\n --duro-layout-spacing-inline-md: 16px;\n --duro-layout-spacing-inline-sm: 8px;\n --duro-layout-spacing-inline-xs: 4px;\n --duro-layout-spacing-stack-lg: 24px;\n --duro-layout-spacing-stack-md: 16px;\n --duro-layout-spacing-stack-sm: 8px;\n --duro-layout-spacing-stack-xl: 48px;\n --duro-layout-spacing-stack-xs: 4px;\n /* typography */\n --duro-typography-font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;\n --duro-typography-font-family-mono: \"SF Mono\", \"Fira Code\", \"Fira Mono\", \"Roboto Mono\", \"Courier New\", monospace;\n --duro-typography-font-size-heading: 1.5rem;\n --duro-typography-font-size-lg: 1.125rem;\n --duro-typography-font-size-md: 1rem;\n --duro-typography-font-size-sm: 0.875rem;\n --duro-typography-font-size-xl: 1.25rem;\n --duro-typography-font-size-xs: 0.75rem;\n --duro-typography-font-weight-bold: 700;\n --duro-typography-font-weight-medium: 500;\n --duro-typography-font-weight-normal: 400;\n --duro-typography-font-weight-semibold: 600;\n --duro-typography-line-height: 1.5;\n /* typeScale */\n --duro-type-scale-display-lg: clamp(3.5rem, 2rem + 3.5vw, 4.5rem);\n --duro-type-scale-display-md: clamp(2.75rem, 1.75rem + 2.5vw, 3.75rem);\n --duro-type-scale-display-sm: clamp(2.25rem, 1.5rem + 2vw, 3rem);\n --duro-type-scale-font-size1: 0.75rem;\n --duro-type-scale-font-size2: 0.8125rem;\n --duro-type-scale-font-size3: 0.875rem;\n --duro-type-scale-font-size4: 1rem;\n --duro-type-scale-font-size5: 1.125rem;\n --duro-type-scale-font-size6: 1.25rem;\n --duro-type-scale-font-size7: 1.5rem;\n --duro-type-scale-font-size8: 1.875rem;\n --duro-type-scale-font-size9: 2.25rem;\n --duro-type-scale-letter-spacing-normal: 0;\n --duro-type-scale-letter-spacing-tight: -0.02em;\n --duro-type-scale-letter-spacing-wide: 0.04em;\n --duro-type-scale-line-height1: 1rem;\n --duro-type-scale-line-height2: 1.25rem;\n --duro-type-scale-line-height3: 1.25rem;\n --duro-type-scale-line-height4: 1.5rem;\n --duro-type-scale-line-height5: 1.5rem;\n --duro-type-scale-line-height6: 1.75rem;\n --duro-type-scale-line-height7: 2rem;\n --duro-type-scale-line-height8: 2.25rem;\n --duro-type-scale-line-height9: 2.75rem;\n /* duration */\n --duro-duration-base: 200ms;\n --duro-duration-brisk: 160ms;\n --duro-duration-fast: 150ms;\n --duro-duration-instant: 0ms;\n --duro-duration-minimal: 1ms;\n --duro-duration-quick: 120ms;\n --duro-duration-slow: 280ms;\n /* easing */\n --duro-easing-ease-in: cubic-bezier(0.72, 0, 0.68, 0.28);\n --duro-easing-ease-out: cubic-bezier(0.32, 0.72, 0, 1);\n --duro-easing-linear: linear;\n --duro-easing-standard: ease;\n /* breakpoints */\n --duro-breakpoint-lg: 1024px;\n --duro-breakpoint-md: 768px;\n --duro-breakpoint-sm: 640px;\n --duro-breakpoint-xl: 1280px;\n --duro-breakpoint-xs: 480px;\n}\n\n:root[data-theme=\"light\"] {\n color-scheme: light;\n /* colors */\n --duro-color-accent: #1e40af;\n --duro-color-accent-contrast: #ffffff;\n --duro-color-accent-hover: #1a3799;\n --duro-color-bg: #ffffff;\n --duro-color-bg-card: #f5f5f5;\n --duro-color-bg-card-hover: #ebebeb;\n --duro-color-border: #d4d4d4;\n --duro-color-error: #991b1b;\n --duro-color-error-bg: rgba(153, 27, 27, 0.08);\n --duro-color-error-border: rgba(153, 27, 27, 0.3);\n --duro-color-error-contrast: #ffffff;\n --duro-color-error-hover: #7f1d1d;\n --duro-color-error-text: #7f1d1d;\n --duro-color-fixed-light: #ffffff;\n --duro-color-info: #1e40af;\n --duro-color-info-bg: rgba(30, 64, 175, 0.08);\n --duro-color-info-border: rgba(30, 64, 175, 0.3);\n --duro-color-info-text: #1e40af;\n --duro-color-inverse-border: rgba(0, 0, 0, 0.55);\n --duro-color-inverse-border-hover: rgba(0, 0, 0, 0.70);\n --duro-color-inverse-fill: rgba(0, 0, 0, 0.10);\n --duro-color-inverse-fill-hover: rgba(0, 0, 0, 0.18);\n --duro-color-scrim: rgba(0, 0, 0, 0.4);\n --duro-color-success: #166534;\n --duro-color-success-bg: rgba(22, 101, 52, 0.08);\n --duro-color-success-border: rgba(22, 101, 52, 0.3);\n --duro-color-success-text: #14532d;\n --duro-color-text: #1a1a1a;\n --duro-color-text-muted: #4a4a4a;\n --duro-color-warning: #92400e;\n --duro-color-warning-bg: rgba(146, 64, 14, 0.08);\n --duro-color-warning-border: rgba(146, 64, 14, 0.3);\n --duro-color-warning-text: #78350f;\n /* shadows */\n --duro-shadow-lg: 0 8px 24px rgba(0, 0, 0, 0.16);\n --duro-shadow-md: 0 4px 12px rgba(0, 0, 0, 0.12);\n --duro-shadow-sm: 0 2px 4px rgba(0, 0, 0, 0.08);\n}\n\n:root[data-theme=\"high-contrast\"] {\n color-scheme: dark;\n /* colors */\n --duro-color-accent: #60a5fa;\n --duro-color-accent-contrast: #000000;\n --duro-color-accent-hover: #93c5fd;\n --duro-color-bg: #000000;\n --duro-color-bg-card: #111111;\n --duro-color-bg-card-hover: #1a1a1a;\n --duro-color-border: #555555;\n --duro-color-error: #f87171;\n --duro-color-error-bg: rgba(248, 113, 113, 0.15);\n --duro-color-error-border: rgba(248, 113, 113, 0.5);\n --duro-color-error-contrast: #000000;\n --duro-color-error-hover: #fca5a5;\n --duro-color-error-text: #fca5a5;\n --duro-color-fixed-light: #ffffff;\n --duro-color-info: #60a5fa;\n --duro-color-info-bg: rgba(96, 165, 250, 0.15);\n --duro-color-info-border: rgba(96, 165, 250, 0.5);\n --duro-color-info-text: #bfdbfe;\n --duro-color-inverse-border: rgba(0, 0, 0, 0.55);\n --duro-color-inverse-border-hover: rgba(0, 0, 0, 0.70);\n --duro-color-inverse-fill: rgba(0, 0, 0, 0.10);\n --duro-color-inverse-fill-hover: rgba(0, 0, 0, 0.18);\n --duro-color-scrim: rgba(0, 0, 0, 0.4);\n --duro-color-success: #4ade80;\n --duro-color-success-bg: rgba(74, 222, 128, 0.15);\n --duro-color-success-border: rgba(74, 222, 128, 0.5);\n --duro-color-success-text: #86efac;\n --duro-color-text: #ffffff;\n --duro-color-text-muted: #b0b0b0;\n --duro-color-warning: #fcd34d;\n --duro-color-warning-bg: rgba(252, 211, 77, 0.15);\n --duro-color-warning-border: rgba(252, 211, 77, 0.5);\n --duro-color-warning-text: #fef08a;\n /* shadows */\n --duro-shadow-lg: 0 8px 24px rgba(0, 0, 0, 0.8);\n --duro-shadow-md: 0 4px 12px rgba(0, 0, 0, 0.7);\n --duro-shadow-sm: 0 2px 4px rgba(0, 0, 0, 0.6);\n}\n"
8710
+ "mockupCss": "/*\n * GENERATED by scripts/generate-mockup-css.mjs — do not edit.\n *\n * The design tokens as resolved values, for HTML that loads no stylesheet\n * (mockup artboards, static previews). Same names as vars.css; where vars.css\n * follows the live theme, this file carries every theme and switches on\n * <html data-theme=\"light|high-contrast\">.\n *\n * Inside the component library and the apps, never use this: go through\n * css.create() and the token imports, or vars.css from plain CSS.\n */\n:root {\n color-scheme: dark;\n /* colors */\n --duro-color-accent: #6aaffc;\n --duro-color-accent-contrast: #000000;\n --duro-color-accent-hover: #93c5fd;\n --duro-color-bg: #0f0f0f;\n --duro-color-bg-card: #1a1a1a;\n --duro-color-bg-card-hover: #242424;\n --duro-color-border: #333333;\n --duro-color-contrast-border: rgba(0, 0, 0, 0.42);\n --duro-color-contrast-surface: #f5f5f5;\n --duro-color-error: #f87171;\n --duro-color-error-bg: rgba(248, 113, 113, 0.1);\n --duro-color-error-border: rgba(248, 113, 113, 0.3);\n --duro-color-error-contrast: #000000;\n --duro-color-error-hover: #fca5a5;\n --duro-color-error-text: #fca5a5;\n --duro-color-fixed-light: #ffffff;\n --duro-color-highlight: #c084fc;\n --duro-color-highlight-bg: rgba(192, 132, 252, 0.1);\n --duro-color-highlight-border: rgba(192, 132, 252, 0.3);\n --duro-color-highlight-text: #d8b4fe;\n --duro-color-info: #6aaffc;\n --duro-color-info-bg: rgba(106, 175, 252, 0.1);\n --duro-color-info-border: rgba(106, 175, 252, 0.3);\n --duro-color-info-text: #93c5fd;\n --duro-color-inverse-border: rgba(0, 0, 0, 0.55);\n --duro-color-inverse-border-hover: rgba(0, 0, 0, 0.70);\n --duro-color-inverse-fill: rgba(0, 0, 0, 0.10);\n --duro-color-inverse-fill-hover: rgba(0, 0, 0, 0.18);\n --duro-color-on-contrast-surface: #1a1a1a;\n --duro-color-overlay-light: rgba(255, 255, 255, 0.78);\n --duro-color-scrim: rgba(0, 0, 0, 0.4);\n --duro-color-success: #22c55e;\n --duro-color-success-bg: rgba(34, 197, 94, 0.1);\n --duro-color-success-border: rgba(34, 197, 94, 0.3);\n --duro-color-success-text: #86efac;\n --duro-color-text: #e5e5e5;\n --duro-color-text-muted: #b0b0b0;\n --duro-color-warning: #fbbf24;\n --duro-color-warning-bg: rgba(251, 191, 36, 0.1);\n --duro-color-warning-border: rgba(251, 191, 36, 0.3);\n --duro-color-warning-text: #fde68a;\n /* shadows */\n --duro-shadow-drop-over: inset 0 0 0 2px #6aaffc;\n --duro-shadow-drop-ready: inset 0 0 0 1px #333333;\n --duro-shadow-lg: 0 8px 24px rgba(0, 0, 0, 0.5);\n --duro-shadow-md: 0 4px 12px rgba(0, 0, 0, 0.4);\n --duro-shadow-sm: 0 2px 4px rgba(0, 0, 0, 0.3);\n /* spacing */\n --duro-spacing-lg: 24px;\n --duro-spacing-md: 16px;\n --duro-spacing-ms: 12px;\n --duro-spacing-sm: 8px;\n --duro-spacing-xl: 32px;\n --duro-spacing-xs: 4px;\n --duro-spacing-xxl: 48px;\n --duro-spacing-xxxl: 64px;\n /* microSpacing */\n --duro-micro-spacing-px1: 1px;\n --duro-micro-spacing-px2: 2px;\n --duro-micro-spacing-px3: 3px;\n --duro-micro-spacing-px5: 5px;\n --duro-micro-spacing-px6: 6px;\n /* radii */\n --duro-radius-full: 9999px;\n --duro-radius-lg: 16px;\n --duro-radius-md: 12px;\n --duro-radius-px6: 6px;\n --duro-radius-sm: 8px;\n --duro-radius-xs: 4px;\n /* sizes */\n --duro-size-aside-w: 320px;\n --duro-size-bar-h: 4px;\n --duro-size-canvas-min-h: 480px;\n --duro-size-check-mark-h: 9px;\n --duro-size-check-mark-w: 5px;\n --duro-size-chip: 24px;\n --duro-size-color-area-h: 150px;\n --duro-size-color-picker-w: 196px;\n --duro-size-color-preview-h: 22px;\n --duro-size-color-swatch: 20px;\n --duro-size-color-track-h: 12px;\n --duro-size-control-lg: 40px;\n --duro-size-control-md: 39px;\n --duro-size-control-sm: 28px;\n --duro-size-day-header-h: 46px;\n --duro-size-device-bar-w: 96px;\n --duro-size-dialog-lg: 680px;\n --duro-size-dialog-md: 520px;\n --duro-size-dialog-sm: 400px;\n --duro-size-divider: 1px;\n --duro-size-drop-zone-min-h: 128px;\n --duro-size-edge-fade: 32px;\n --duro-size-editor-min-h: 160px;\n --duro-size-embed-w: 550px;\n --duro-size-field-min-w: 160px;\n --duro-size-field-min-w-sm: 80px;\n --duro-size-glyph-md: 16px;\n --duro-size-glyph-sm: 12px;\n --duro-size-glyph-xs: 10px;\n --duro-size-grid-col-md: 280px;\n --duro-size-grid-col-sm: 240px;\n --duro-size-grid-col-xs: 200px;\n --duro-size-handle: 16px;\n --duro-size-icon-button: 32px;\n --duro-size-icon-button-sm: 28px;\n --duro-size-icon-lg: 24px;\n --duro-size-icon-md: 18px;\n --duro-size-icon-sm: 16px;\n --duro-size-icon-xl: 36px;\n --duro-size-icon-xxl: 48px;\n --duro-size-indicator: 18px;\n --duro-size-indicator-dot: 8px;\n --duro-size-label-min-w: 120px;\n --duro-size-list-max-h: 280px;\n --duro-size-list-max-h-sm: 200px;\n --duro-size-meter-h: 6px;\n --duro-size-nav-marker-h: 18px;\n --duro-size-nav-marker-w: 3px;\n --duro-size-page-lg: 1200px;\n --duro-size-page-md: 800px;\n --duro-size-page-sm: 600px;\n --duro-size-page-xl: 1440px;\n --duro-size-page-xs: 480px;\n --duro-size-palette-min-w: 96px;\n --duro-size-panel-lg: 640px;\n --duro-size-panel-md: 480px;\n --duro-size-panel-sm: 360px;\n --duro-size-placeholder-min-h: 80px;\n --duro-size-popover-w: 320px;\n --duro-size-popover-w-sm: 240px;\n --duro-size-popup-max-w: 280px;\n --duro-size-popup-min-w: 160px;\n --duro-size-preview-max-h: 320px;\n --duro-size-readout-w: 40px;\n --duro-size-scrollbar: 8px;\n --duro-size-sidebar-w: 240px;\n --duro-size-skeleton-chip-w: 96px;\n --duro-size-slider-w: 96px;\n --duro-size-spinner-lg: 40px;\n --duro-size-spinner-md: 24px;\n --duro-size-spinner-sm: 16px;\n --duro-size-swatch-h: 34px;\n --duro-size-swatch-w: 44px;\n --duro-size-switch-thumb: 16px;\n --duro-size-switch-track-h: 20px;\n --duro-size-switch-track-w: 36px;\n --duro-size-tab-indicator: 2px;\n --duro-size-time-gutter-w: 64px;\n --duro-size-toast-max-w: 440px;\n --duro-size-toolbar-h: 36px;\n --duro-size-touch-target: 44px;\n /* borders */\n --duro-border-accent: 3px;\n --duro-border-focus-offset: 2px;\n --duro-border-focus-offset-sm: 1px;\n --duro-border-focus-ring: 2px;\n --duro-border-hairline: 1px;\n --duro-border-strong: 2px;\n /* layers */\n --duro-layer-floating: 50;\n --duro-layer-modal: 1001;\n --duro-layer-overlay: 1000;\n --duro-layer-popover: 1040;\n --duro-layer-popup: 1050;\n --duro-layer-popup-backdrop: 1049;\n --duro-layer-portal: 1100;\n --duro-layer-raised: 1;\n --duro-layer-toast: 1060;\n /* effects */\n --duro-effect-overlay-blur: blur(2px);\n /* layoutSpacing */\n --duro-layout-spacing-container-lg: 32px;\n --duro-layout-spacing-container-md: 24px;\n --duro-layout-spacing-container-sm: 16px;\n --duro-layout-spacing-inline-lg: 24px;\n --duro-layout-spacing-inline-md: 16px;\n --duro-layout-spacing-inline-sm: 8px;\n --duro-layout-spacing-inline-xs: 4px;\n --duro-layout-spacing-stack-lg: 24px;\n --duro-layout-spacing-stack-md: 16px;\n --duro-layout-spacing-stack-sm: 8px;\n --duro-layout-spacing-stack-xl: 48px;\n --duro-layout-spacing-stack-xs: 4px;\n /* typography */\n --duro-typography-font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;\n --duro-typography-font-family-mono: \"SF Mono\", \"Fira Code\", \"Fira Mono\", \"Roboto Mono\", \"Courier New\", monospace;\n --duro-typography-font-size-heading: 1.5rem;\n --duro-typography-font-size-lg: 1.125rem;\n --duro-typography-font-size-md: 1rem;\n --duro-typography-font-size-sm: 0.875rem;\n --duro-typography-font-size-xl: 1.25rem;\n --duro-typography-font-size-xs: 0.75rem;\n --duro-typography-font-weight-bold: 700;\n --duro-typography-font-weight-medium: 500;\n --duro-typography-font-weight-normal: 400;\n --duro-typography-font-weight-semibold: 600;\n --duro-typography-line-height: 1.5;\n /* typeScale */\n --duro-type-scale-display-lg: clamp(3.5rem, 2rem + 3.5vw, 4.5rem);\n --duro-type-scale-display-md: clamp(2.75rem, 1.75rem + 2.5vw, 3.75rem);\n --duro-type-scale-display-sm: clamp(2.25rem, 1.5rem + 2vw, 3rem);\n --duro-type-scale-font-size1: 0.75rem;\n --duro-type-scale-font-size2: 0.8125rem;\n --duro-type-scale-font-size3: 0.875rem;\n --duro-type-scale-font-size4: 1rem;\n --duro-type-scale-font-size5: 1.125rem;\n --duro-type-scale-font-size6: 1.25rem;\n --duro-type-scale-font-size7: 1.5rem;\n --duro-type-scale-font-size8: 1.875rem;\n --duro-type-scale-font-size9: 2.25rem;\n --duro-type-scale-letter-spacing-normal: 0;\n --duro-type-scale-letter-spacing-tight: -0.02em;\n --duro-type-scale-letter-spacing-wide: 0.04em;\n --duro-type-scale-line-height1: 1rem;\n --duro-type-scale-line-height2: 1.25rem;\n --duro-type-scale-line-height3: 1.25rem;\n --duro-type-scale-line-height4: 1.5rem;\n --duro-type-scale-line-height5: 1.5rem;\n --duro-type-scale-line-height6: 1.75rem;\n --duro-type-scale-line-height7: 2rem;\n --duro-type-scale-line-height8: 2.25rem;\n --duro-type-scale-line-height9: 2.75rem;\n /* duration */\n --duro-duration-base: 200ms;\n --duro-duration-brisk: 160ms;\n --duro-duration-fast: 150ms;\n --duro-duration-instant: 0ms;\n --duro-duration-minimal: 1ms;\n --duro-duration-quick: 120ms;\n --duro-duration-slow: 280ms;\n /* easing */\n --duro-easing-ease-in: cubic-bezier(0.72, 0, 0.68, 0.28);\n --duro-easing-ease-out: cubic-bezier(0.32, 0.72, 0, 1);\n --duro-easing-linear: linear;\n --duro-easing-standard: ease;\n /* breakpoints */\n --duro-breakpoint-lg: 1024px;\n --duro-breakpoint-md: 768px;\n --duro-breakpoint-sm: 640px;\n --duro-breakpoint-xl: 1280px;\n --duro-breakpoint-xs: 480px;\n}\n\n:root[data-theme=\"light\"] {\n color-scheme: light;\n /* colors */\n --duro-color-accent: #1e40af;\n --duro-color-accent-contrast: #ffffff;\n --duro-color-accent-hover: #1a3799;\n --duro-color-bg: #ffffff;\n --duro-color-bg-card: #f5f5f5;\n --duro-color-bg-card-hover: #ebebeb;\n --duro-color-border: #d4d4d4;\n --duro-color-contrast-border: rgba(255, 255, 255, 0.33);\n --duro-color-contrast-surface: #1a1a1a;\n --duro-color-error: #991b1b;\n --duro-color-error-bg: rgba(153, 27, 27, 0.08);\n --duro-color-error-border: rgba(153, 27, 27, 0.3);\n --duro-color-error-contrast: #ffffff;\n --duro-color-error-hover: #7f1d1d;\n --duro-color-error-text: #7f1d1d;\n --duro-color-fixed-light: #ffffff;\n --duro-color-highlight: #6b21a8;\n --duro-color-highlight-bg: rgba(107, 33, 168, 0.08);\n --duro-color-highlight-border: rgba(107, 33, 168, 0.3);\n --duro-color-highlight-text: #581c87;\n --duro-color-info: #1e40af;\n --duro-color-info-bg: rgba(30, 64, 175, 0.08);\n --duro-color-info-border: rgba(30, 64, 175, 0.3);\n --duro-color-info-text: #1e40af;\n --duro-color-inverse-border: rgba(0, 0, 0, 0.55);\n --duro-color-inverse-border-hover: rgba(0, 0, 0, 0.70);\n --duro-color-inverse-fill: rgba(0, 0, 0, 0.10);\n --duro-color-inverse-fill-hover: rgba(0, 0, 0, 0.18);\n --duro-color-on-contrast-surface: #e5e5e5;\n --duro-color-overlay-light: rgba(255, 255, 255, 0.78);\n --duro-color-scrim: rgba(0, 0, 0, 0.4);\n --duro-color-success: #166534;\n --duro-color-success-bg: rgba(22, 101, 52, 0.08);\n --duro-color-success-border: rgba(22, 101, 52, 0.3);\n --duro-color-success-text: #14532d;\n --duro-color-text: #1a1a1a;\n --duro-color-text-muted: #4a4a4a;\n --duro-color-warning: #92400e;\n --duro-color-warning-bg: rgba(146, 64, 14, 0.08);\n --duro-color-warning-border: rgba(146, 64, 14, 0.3);\n --duro-color-warning-text: #78350f;\n /* shadows */\n --duro-shadow-drop-over: inset 0 0 0 2px #1e40af;\n --duro-shadow-drop-ready: inset 0 0 0 1px #d4d4d4;\n --duro-shadow-lg: 0 8px 24px rgba(0, 0, 0, 0.16);\n --duro-shadow-md: 0 4px 12px rgba(0, 0, 0, 0.12);\n --duro-shadow-sm: 0 2px 4px rgba(0, 0, 0, 0.08);\n}\n\n:root[data-theme=\"high-contrast\"] {\n color-scheme: dark;\n /* colors */\n --duro-color-accent: #60a5fa;\n --duro-color-accent-contrast: #000000;\n --duro-color-accent-hover: #93c5fd;\n --duro-color-bg: #000000;\n --duro-color-bg-card: #111111;\n --duro-color-bg-card-hover: #1a1a1a;\n --duro-color-border: #555555;\n --duro-color-contrast-border: rgba(0, 0, 0, 0.42);\n --duro-color-contrast-surface: #ffffff;\n --duro-color-error: #f87171;\n --duro-color-error-bg: rgba(248, 113, 113, 0.15);\n --duro-color-error-border: rgba(248, 113, 113, 0.5);\n --duro-color-error-contrast: #000000;\n --duro-color-error-hover: #fca5a5;\n --duro-color-error-text: #fca5a5;\n --duro-color-fixed-light: #ffffff;\n --duro-color-highlight: #d8b4fe;\n --duro-color-highlight-bg: rgba(216, 180, 254, 0.15);\n --duro-color-highlight-border: rgba(216, 180, 254, 0.5);\n --duro-color-highlight-text: #e9d5ff;\n --duro-color-info: #60a5fa;\n --duro-color-info-bg: rgba(96, 165, 250, 0.15);\n --duro-color-info-border: rgba(96, 165, 250, 0.5);\n --duro-color-info-text: #bfdbfe;\n --duro-color-inverse-border: rgba(0, 0, 0, 0.55);\n --duro-color-inverse-border-hover: rgba(0, 0, 0, 0.70);\n --duro-color-inverse-fill: rgba(0, 0, 0, 0.10);\n --duro-color-inverse-fill-hover: rgba(0, 0, 0, 0.18);\n --duro-color-on-contrast-surface: #000000;\n --duro-color-overlay-light: rgba(255, 255, 255, 0.78);\n --duro-color-scrim: rgba(0, 0, 0, 0.4);\n --duro-color-success: #4ade80;\n --duro-color-success-bg: rgba(74, 222, 128, 0.15);\n --duro-color-success-border: rgba(74, 222, 128, 0.5);\n --duro-color-success-text: #86efac;\n --duro-color-text: #ffffff;\n --duro-color-text-muted: #b0b0b0;\n --duro-color-warning: #fcd34d;\n --duro-color-warning-bg: rgba(252, 211, 77, 0.15);\n --duro-color-warning-border: rgba(252, 211, 77, 0.5);\n --duro-color-warning-text: #fef08a;\n /* shadows */\n --duro-shadow-drop-over: inset 0 0 0 2px #60a5fa;\n --duro-shadow-drop-ready: inset 0 0 0 1px #555555;\n --duro-shadow-lg: 0 8px 24px rgba(0, 0, 0, 0.8);\n --duro-shadow-md: 0 4px 12px rgba(0, 0, 0, 0.7);\n --duro-shadow-sm: 0 2px 4px rgba(0, 0, 0, 0.6);\n}\n"
7964
8711
  },
7965
8712
  "unions": {
7966
8713
  "AlertVariant": [
@@ -7978,7 +8725,8 @@
7978
8725
  "success",
7979
8726
  "warning",
7980
8727
  "error",
7981
- "info"
8728
+ "info",
8729
+ "highlight"
7982
8730
  ],
7983
8731
  "Breakpoint": [
7984
8732
  "xs",
@@ -8110,7 +8858,8 @@
8110
8858
  ],
8111
8859
  "InputVariant": [
8112
8860
  "default",
8113
- "error"
8861
+ "error",
8862
+ "ghost"
8114
8863
  ],
8115
8864
  "LabelPosition": [
8116
8865
  "top",
@@ -8129,6 +8878,10 @@
8129
8878
  "single",
8130
8879
  "multiple"
8131
8880
  ],
8881
+ "ListboxMaxHeight": [
8882
+ "listMaxH",
8883
+ "listMaxHSm"
8884
+ ],
8132
8885
  "PageShellMaxWidth": [
8133
8886
  "sm",
8134
8887
  "md",
@@ -8162,7 +8915,9 @@
8162
8915
  "ShadowToken": [
8163
8916
  "sm",
8164
8917
  "md",
8165
- "lg"
8918
+ "lg",
8919
+ "dropReady",
8920
+ "dropOver"
8166
8921
  ],
8167
8922
  "SpacingKey": [
8168
8923
  "xs",
@@ -8229,6 +8984,10 @@
8229
8984
  "success",
8230
8985
  "warning"
8231
8986
  ],
8987
+ "TextLinkVariant": [
8988
+ "default",
8989
+ "subtle"
8990
+ ],
8232
8991
  "TextVariant": [
8233
8992
  "t",
8234
8993
  "ts",