cursedbelt 5.32.0 → 5.34.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/dist/react/Toast.d.ts +1 -1
- package/dist/react/Toast.d.ts.map +1 -1
- package/dist/react/Toast.js +19 -4
- package/dist/react/Toast.js.map +1 -1
- package/dist/react/components/Button.d.ts +16 -1
- package/dist/react/components/Button.d.ts.map +1 -1
- package/dist/react/components/Button.js +34 -5
- package/dist/react/components/Button.js.map +1 -1
- package/dist/react/components/ChoiceGroup.d.ts +20 -1
- package/dist/react/components/ChoiceGroup.d.ts.map +1 -1
- package/dist/react/components/ChoiceGroup.js +15 -2
- package/dist/react/components/ChoiceGroup.js.map +1 -1
- package/dist/react/components/CopyButton.d.ts +10 -1
- package/dist/react/components/CopyButton.d.ts.map +1 -1
- package/dist/react/components/CopyButton.js +2 -2
- package/dist/react/components/CopyButton.js.map +1 -1
- package/dist/react/components/DataTable/DataTable.d.ts +27 -2
- package/dist/react/components/DataTable/DataTable.d.ts.map +1 -1
- package/dist/react/components/DataTable/DataTable.js +168 -44
- package/dist/react/components/DataTable/DataTable.js.map +1 -1
- package/dist/react/components/DataTable/RowActions.d.ts +4 -1
- package/dist/react/components/DataTable/RowActions.d.ts.map +1 -1
- package/dist/react/components/DataTable/RowActions.js +2 -2
- package/dist/react/components/DataTable/RowActions.js.map +1 -1
- package/dist/react/components/DataTable/columnPriority.d.ts +30 -0
- package/dist/react/components/DataTable/columnPriority.d.ts.map +1 -0
- package/dist/react/components/DataTable/columnPriority.js +45 -0
- package/dist/react/components/DataTable/columnPriority.js.map +1 -0
- package/dist/react/components/DataTable/types.d.ts +14 -0
- package/dist/react/components/DataTable/types.d.ts.map +1 -1
- package/dist/react/components/DataTable/types.js.map +1 -1
- package/dist/react/components/EmptyState.d.ts.map +1 -1
- package/dist/react/components/EmptyState.js +2 -2
- package/dist/react/components/EmptyState.js.map +1 -1
- package/dist/react/components/ErrorCard.d.ts +13 -1
- package/dist/react/components/ErrorCard.d.ts.map +1 -1
- package/dist/react/components/ErrorCard.js +3 -2
- package/dist/react/components/ErrorCard.js.map +1 -1
- package/dist/react/components/Field.d.ts +37 -12
- package/dist/react/components/Field.d.ts.map +1 -1
- package/dist/react/components/Field.js +19 -8
- package/dist/react/components/Field.js.map +1 -1
- package/dist/react/components/Menu.d.ts +58 -0
- package/dist/react/components/Menu.d.ts.map +1 -0
- package/dist/react/components/Menu.js +86 -0
- package/dist/react/components/Menu.js.map +1 -0
- package/dist/react/components/Modal.d.ts +1 -0
- package/dist/react/components/Modal.d.ts.map +1 -1
- package/dist/react/components/Modal.js +3 -2
- package/dist/react/components/Modal.js.map +1 -1
- package/dist/react/components/SaveIndicator.d.ts +36 -0
- package/dist/react/components/SaveIndicator.d.ts.map +1 -0
- package/dist/react/components/SaveIndicator.js +48 -0
- package/dist/react/components/SaveIndicator.js.map +1 -0
- package/dist/react/components/SelectionBar.d.ts +26 -0
- package/dist/react/components/SelectionBar.d.ts.map +1 -0
- package/dist/react/components/SelectionBar.js +21 -0
- package/dist/react/components/SelectionBar.js.map +1 -0
- package/dist/react/components/Switch.d.ts +16 -2
- package/dist/react/components/Switch.d.ts.map +1 -1
- package/dist/react/components/Switch.js +10 -3
- package/dist/react/components/Switch.js.map +1 -1
- package/dist/react/components/Tooltip.d.ts +1 -1
- package/dist/react/components/Tooltip.d.ts.map +1 -1
- package/dist/react/components/Tooltip.js +14 -1
- package/dist/react/components/Tooltip.js.map +1 -1
- package/dist/react/components/TooltipImpl.d.ts.map +1 -1
- package/dist/react/components/TooltipImpl.js +37 -7
- package/dist/react/components/TooltipImpl.js.map +1 -1
- package/dist/react/components/UnstyledButton.d.ts +37 -0
- package/dist/react/components/UnstyledButton.d.ts.map +1 -0
- package/dist/react/components/UnstyledButton.js +46 -0
- package/dist/react/components/UnstyledButton.js.map +1 -0
- package/dist/react/components/auth/SignInCard.d.ts +15 -1
- package/dist/react/components/auth/SignInCard.d.ts.map +1 -1
- package/dist/react/components/auth/SignInCard.js +6 -2
- package/dist/react/components/auth/SignInCard.js.map +1 -1
- package/dist/react/components/dialog.d.ts.map +1 -1
- package/dist/react/components/dialog.js +35 -3
- package/dist/react/components/dialog.js.map +1 -1
- package/dist/react/hooks/useCopyToClipboard.d.ts +10 -2
- package/dist/react/hooks/useCopyToClipboard.d.ts.map +1 -1
- package/dist/react/hooks/useCopyToClipboard.js +13 -4
- package/dist/react/hooks/useCopyToClipboard.js.map +1 -1
- package/dist/react/icons.d.ts +12 -1
- package/dist/react/icons.d.ts.map +1 -1
- package/dist/react/icons.js +12 -22
- package/dist/react/icons.js.map +1 -1
- package/dist/react/index.d.ts +8 -4
- package/dist/react/index.d.ts.map +1 -1
- package/dist/react/index.js +7 -3
- package/dist/react/index.js.map +1 -1
- package/dist/react/lib/hoverIntent.d.ts +21 -0
- package/dist/react/lib/hoverIntent.d.ts.map +1 -1
- package/dist/react/lib/hoverIntent.js +24 -0
- package/dist/react/lib/hoverIntent.js.map +1 -1
- package/dist/react/lib/openDialogs.d.ts +5 -0
- package/dist/react/lib/openDialogs.d.ts.map +1 -0
- package/dist/react/lib/openDialogs.js +45 -0
- package/dist/react/lib/openDialogs.js.map +1 -0
- package/dist/styles-areas/analytics.css +16 -16
- package/dist/styles-areas/calendar.css +7 -7
- package/dist/styles-areas/chat.css +9 -10
- package/dist/styles-areas/core.css +69 -62
- package/dist/styles-areas/data-table.css +16 -16
- package/dist/styles-areas/disk-usage.css +7 -7
- package/dist/styles-areas/emoji.css +3 -3
- package/dist/styles-areas/fields.css +10 -10
- package/dist/styles-areas/filter-rail.css +7 -8
- package/dist/styles-areas/layout-engine.css +5 -6
- package/dist/styles-areas/master-detail.css +6 -7
- package/dist/styles-areas/media-gallery.css +2 -2
- package/dist/styles-areas/media.css +2 -2
- package/dist/styles-areas/nav.css +17 -18
- package/dist/styles-areas/notifications.css +5 -5
- package/dist/styles-areas/overlays.css +5 -5
- package/dist/styles-areas/sharing.css +2 -2
- package/dist/styles-areas/stats.css +4 -4
- package/dist/styles-areas/wizard.css +3 -3
- package/dist/styles-areas/workbench.css +18 -19
- package/dist/styles-utilities.css +72 -0
- package/dist/testing/tooltip.d.ts.map +1 -1
- package/dist/testing/tooltip.js +8 -18
- package/dist/testing/tooltip.js.map +1 -1
- package/package.json +81 -3
- package/scripts/guardrails-baseline.json +1 -1
- package/scripts/styleAreas.ts +4 -0
- package/src/react/Toast.spec.tsx +17 -1
- package/src/react/Toast.tsx +20 -3
- package/src/react/components/Button.spec.tsx +49 -1
- package/src/react/components/Button.tsx +63 -6
- package/src/react/components/ChoiceGroup.spec.tsx +32 -0
- package/src/react/components/ChoiceGroup.tsx +78 -23
- package/src/react/components/CopyButton.spec.tsx +35 -0
- package/src/react/components/CopyButton.tsx +11 -2
- package/src/react/components/DataTable/DataTable.spec.tsx +16 -0
- package/src/react/components/DataTable/DataTable.tsx +266 -37
- package/src/react/components/DataTable/RowActions.tsx +5 -2
- package/src/react/components/DataTable/columnPriority.spec.ts +97 -0
- package/src/react/components/DataTable/columnPriority.ts +54 -0
- package/src/react/components/DataTable/types.ts +14 -0
- package/src/react/components/DataTable/virtualize.spec.tsx +47 -2
- package/src/react/components/EmptyState.spec.tsx +7 -0
- package/src/react/components/EmptyState.tsx +3 -0
- package/src/react/components/ErrorCard.spec.tsx +32 -0
- package/src/react/components/ErrorCard.tsx +17 -1
- package/src/react/components/Field.spec.tsx +61 -0
- package/src/react/components/Field.tsx +84 -27
- package/src/react/components/Menu.spec.tsx +90 -0
- package/src/react/components/Menu.tsx +204 -0
- package/src/react/components/Modal.spec.tsx +84 -0
- package/src/react/components/Modal.tsx +4 -1
- package/src/react/components/SaveIndicator.spec.tsx +35 -0
- package/src/react/components/SaveIndicator.tsx +85 -0
- package/src/react/components/SelectionBar.spec.tsx +32 -0
- package/src/react/components/SelectionBar.tsx +49 -0
- package/src/react/components/Switch.spec.tsx +25 -0
- package/src/react/components/Switch.tsx +49 -4
- package/src/react/components/Tooltip.spec.tsx +183 -2
- package/src/react/components/Tooltip.tsx +14 -2
- package/src/react/components/TooltipImpl.tsx +42 -8
- package/src/react/components/UnstyledButton.spec.tsx +61 -0
- package/src/react/components/UnstyledButton.tsx +83 -0
- package/src/react/components/auth/SignInCard.spec.tsx +34 -0
- package/src/react/components/auth/SignInCard.tsx +36 -3
- package/src/react/components/dialog.tsx +49 -9
- package/src/react/hooks/useCopyToClipboard.ts +17 -4
- package/src/react/icons.spec.ts +32 -1
- package/src/react/icons.tsx +59 -0
- package/src/react/index.ts +23 -2
- package/src/react/lib/hoverIntent.ts +28 -0
- package/src/react/lib/openDialogs.ts +48 -0
- package/src/styles-areas/analytics.css +16 -16
- package/src/styles-areas/calendar.css +7 -7
- package/src/styles-areas/chat.css +9 -10
- package/src/styles-areas/core.css +69 -62
- package/src/styles-areas/data-table.css +16 -16
- package/src/styles-areas/disk-usage.css +7 -7
- package/src/styles-areas/emoji.css +3 -3
- package/src/styles-areas/fields.css +10 -10
- package/src/styles-areas/filter-rail.css +7 -8
- package/src/styles-areas/layout-engine.css +5 -6
- package/src/styles-areas/master-detail.css +6 -7
- package/src/styles-areas/media-gallery.css +2 -2
- package/src/styles-areas/media.css +2 -2
- package/src/styles-areas/nav.css +17 -18
- package/src/styles-areas/notifications.css +5 -5
- package/src/styles-areas/overlays.css +5 -5
- package/src/styles-areas/sharing.css +2 -2
- package/src/styles-areas/stats.css +4 -4
- package/src/styles-areas/wizard.css +3 -3
- package/src/styles-areas/workbench.css +18 -19
- package/src/styles-utilities.css +72 -0
- package/src/testing/tooltip.spec.ts +19 -0
- package/src/testing/tooltip.ts +17 -1
|
@@ -18,14 +18,14 @@
|
|
|
18
18
|
* after an app's responsive variant (task 2124). An app that imports every area gets exactly
|
|
19
19
|
* what `cursedbelt/styles-utilities.css` emits — proved rule by rule in
|
|
20
20
|
* src/stylesAreas.spec.ts, which is also what fails when this file is stale.
|
|
21
|
-
*
|
|
21
|
+
* 62 candidate(s).
|
|
22
22
|
*
|
|
23
23
|
* Written by scripts/generateAreaStyles.ts (`bun run styles:areas`), which
|
|
24
24
|
* `bun run build` runs. The map of what is in which area, and why the areas are
|
|
25
25
|
* import closures rather than a hand-written list, is scripts/styleAreas.ts.
|
|
26
26
|
*/
|
|
27
|
-
@source inline("[&_svg]:size-3 border-field-error border-l border-r collapse
|
|
28
|
-
@source inline("data-[ending-style]:
|
|
27
|
+
@source inline("[&_svg]:size-3 border-field-error border-l border-r collapse data-[ending-style]:opacity-0");
|
|
28
|
+
@source inline("data-[ending-style]:scale-95 data-[highlighted]:bg-accent/10");
|
|
29
29
|
@source inline("data-[highlighted]:text-accent-strong data-[starting-style]:opacity-0");
|
|
30
30
|
@source inline("data-[starting-style]:scale-95 data-[state=closed]:slide-out-to-bottom");
|
|
31
31
|
@source inline("data-[state=closed]:slide-out-to-left data-[state=closed]:slide-out-to-right");
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
* after an app's responsive variant (task 2124). An app that imports every area gets exactly
|
|
19
19
|
* what `cursedbelt/styles-utilities.css` emits — proved rule by rule in
|
|
20
20
|
* src/stylesAreas.spec.ts, which is also what fails when this file is stale.
|
|
21
|
-
*
|
|
21
|
+
* 103 candidate(s).
|
|
22
22
|
*
|
|
23
23
|
* Written by scripts/generateAreaStyles.ts (`bun run styles:areas`), which
|
|
24
24
|
* `bun run build` runs. The map of what is in which area, and why the areas are
|
|
@@ -26,21 +26,20 @@
|
|
|
26
26
|
*/
|
|
27
27
|
@source inline("-my-0.5 [&::-webkit-scrollbar]:hidden [&_svg]:size-3.5 [scrollbar-width:none] bg-accent/15");
|
|
28
28
|
@source inline("bg-accent/40 bg-accent/8 bg-border-strong bg-card-overlay/85 bg-muted/40 bg-muted/60");
|
|
29
|
-
@source inline("bg-success/8 border-
|
|
30
|
-
@source inline("border-
|
|
31
|
-
@source inline("data-[state=closed]:slide-out-to-
|
|
32
|
-
@source inline("data-[state=
|
|
33
|
-
@source inline("data-[state=open]:slide-in-from-
|
|
34
|
-
@source inline("
|
|
35
|
-
@source inline("hover:border-
|
|
36
|
-
@source inline("max-h-[
|
|
37
|
-
@source inline("min-
|
|
38
|
-
@source inline("
|
|
39
|
-
@source inline("peer-focus:
|
|
40
|
-
@source inline("
|
|
41
|
-
@source inline("
|
|
42
|
-
@source inline("
|
|
43
|
-
@source inline("text-
|
|
44
|
-
@source inline("text-tone-
|
|
45
|
-
@source inline("
|
|
46
|
-
@source inline("w-2/3 w-3.5 w-[352px]");
|
|
29
|
+
@source inline("bg-success/8 border-2 border-8 border-accent-solid border-accent/70 border-border-strong/60");
|
|
30
|
+
@source inline("border-dashed border-l border-r border-solid bottom-6 data-[state=closed]:slide-out-to-bottom");
|
|
31
|
+
@source inline("data-[state=closed]:slide-out-to-left data-[state=closed]:slide-out-to-right");
|
|
32
|
+
@source inline("data-[state=open]:slide-in-from-bottom data-[state=open]:slide-in-from-left");
|
|
33
|
+
@source inline("data-[state=open]:slide-in-from-right duration-150 flex-row h-3.5 h-40 h-[420px]");
|
|
34
|
+
@source inline("hover:bg-card-overlay hover:bg-muted-foreground/10 hover:bg-muted/80 hover:border-border-strong");
|
|
35
|
+
@source inline("hover:border-field-ring hover:shadow-popover italic left-0 max-h-[40dvh] max-h-[65dvh]");
|
|
36
|
+
@source inline("max-h-[85dvh] max-h-full min-h min-h-20 min-h-[2.25rem] min-h-[44px] min-h-dvh min-h-full");
|
|
37
|
+
@source inline("min-w-40 min-w-[5rem] opacity-100 pb-0.5 pb-4 pb-[max(env(safe-area-inset-bottom,0px),0.5rem)]");
|
|
38
|
+
@source inline("peer-focus peer-focus:outline-none peer-focus:ring-2 peer-focus:ring-field-ring/40");
|
|
39
|
+
@source inline("peer-focus:rounded-lg pl-1 pl-3 pointer-coarse:h-12 pointer-coarse:w-12 resize-none right-4");
|
|
40
|
+
@source inline("ring-1 ring-4 ring-accent/20 ring-accent/30 ring-accent/40 ring-border ring-inset ring-ring");
|
|
41
|
+
@source inline("rotate-90 rounded-[2.5rem] rounded-l-xl rounded-r-xl rounded-t-xl scale-[1.01] self-center");
|
|
42
|
+
@source inline("self-stretch shrink-[2] sm:w-56 text-muted-foreground/60 text-tone-amber-ink text-tone-cyan-ink");
|
|
43
|
+
@source inline("text-tone-emerald-ink text-tone-orange-ink text-tone-purple-ink text-tone-rose-ink");
|
|
44
|
+
@source inline("text-tone-sky-ink text-tone-slate-ink text-xl transition-[opacity,transform] translate-y-0");
|
|
45
|
+
@source inline("translate-y-2 w-1/2 w-2/3 w-3.5 w-[352px]");
|
|
@@ -797,6 +797,9 @@
|
|
|
797
797
|
.min-h-full {
|
|
798
798
|
min-height: 100%;
|
|
799
799
|
}
|
|
800
|
+
.w-0\! {
|
|
801
|
+
width: 0px !important;
|
|
802
|
+
}
|
|
800
803
|
.w-0\.5 {
|
|
801
804
|
width: calc(var(--spacing) * 0.5);
|
|
802
805
|
}
|
|
@@ -1004,6 +1007,9 @@
|
|
|
1004
1007
|
.min-w-0 {
|
|
1005
1008
|
min-width: 0px;
|
|
1006
1009
|
}
|
|
1010
|
+
.min-w-0\! {
|
|
1011
|
+
min-width: 0px !important;
|
|
1012
|
+
}
|
|
1007
1013
|
.min-w-3\.5 {
|
|
1008
1014
|
min-width: calc(var(--spacing) * 3.5);
|
|
1009
1015
|
}
|
|
@@ -1634,6 +1640,9 @@
|
|
|
1634
1640
|
.border-border {
|
|
1635
1641
|
border-color: var(--border);
|
|
1636
1642
|
}
|
|
1643
|
+
.border-border\! {
|
|
1644
|
+
border-color: var(--border) !important;
|
|
1645
|
+
}
|
|
1637
1646
|
.border-border-strong {
|
|
1638
1647
|
border-color: var(--border-strong);
|
|
1639
1648
|
}
|
|
@@ -2033,6 +2042,12 @@
|
|
|
2033
2042
|
background-color: color-mix(in oklab, var(--muted-foreground) 50%, transparent);
|
|
2034
2043
|
}
|
|
2035
2044
|
}
|
|
2045
|
+
.bg-muted-foreground\/60 {
|
|
2046
|
+
background-color: var(--muted-foreground);
|
|
2047
|
+
@supports (color: color-mix(in lab, red, red)) {
|
|
2048
|
+
background-color: color-mix(in oklab, var(--muted-foreground) 60%, transparent);
|
|
2049
|
+
}
|
|
2050
|
+
}
|
|
2036
2051
|
.bg-muted\/20 {
|
|
2037
2052
|
background-color: var(--muted);
|
|
2038
2053
|
@supports (color: color-mix(in lab, red, red)) {
|
|
@@ -2066,6 +2081,9 @@
|
|
|
2066
2081
|
.bg-popover {
|
|
2067
2082
|
background-color: var(--popover);
|
|
2068
2083
|
}
|
|
2084
|
+
.bg-popover\! {
|
|
2085
|
+
background-color: var(--popover) !important;
|
|
2086
|
+
}
|
|
2069
2087
|
.bg-purple-100 {
|
|
2070
2088
|
background-color: var(--color-purple-100);
|
|
2071
2089
|
}
|
|
@@ -2282,6 +2300,9 @@
|
|
|
2282
2300
|
.p-0 {
|
|
2283
2301
|
padding: 0px;
|
|
2284
2302
|
}
|
|
2303
|
+
.p-0\! {
|
|
2304
|
+
padding: 0px !important;
|
|
2305
|
+
}
|
|
2285
2306
|
.p-0\.5 {
|
|
2286
2307
|
padding: calc(var(--spacing) * 0.5);
|
|
2287
2308
|
}
|
|
@@ -2471,6 +2492,9 @@
|
|
|
2471
2492
|
.pl-3 {
|
|
2472
2493
|
padding-left: calc(var(--spacing) * 3);
|
|
2473
2494
|
}
|
|
2495
|
+
.pl-4 {
|
|
2496
|
+
padding-left: calc(var(--spacing) * 4);
|
|
2497
|
+
}
|
|
2474
2498
|
.pl-5 {
|
|
2475
2499
|
padding-left: calc(var(--spacing) * 5);
|
|
2476
2500
|
}
|
|
@@ -2630,6 +2654,9 @@
|
|
|
2630
2654
|
.break-all {
|
|
2631
2655
|
word-break: break-all;
|
|
2632
2656
|
}
|
|
2657
|
+
.whitespace-normal {
|
|
2658
|
+
white-space: normal;
|
|
2659
|
+
}
|
|
2633
2660
|
.whitespace-nowrap {
|
|
2634
2661
|
white-space: nowrap;
|
|
2635
2662
|
}
|
|
@@ -2708,6 +2735,9 @@
|
|
|
2708
2735
|
.text-muted-foreground {
|
|
2709
2736
|
color: var(--muted-foreground);
|
|
2710
2737
|
}
|
|
2738
|
+
.text-muted-foreground\! {
|
|
2739
|
+
color: var(--muted-foreground) !important;
|
|
2740
|
+
}
|
|
2711
2741
|
.text-muted-foreground\/50 {
|
|
2712
2742
|
color: var(--muted-foreground);
|
|
2713
2743
|
@supports (color: color-mix(in lab, red, red)) {
|
|
@@ -3547,6 +3577,9 @@
|
|
|
3547
3577
|
.hover\:text-foreground:hover {
|
|
3548
3578
|
color: var(--foreground);
|
|
3549
3579
|
}
|
|
3580
|
+
.hover\:text-foreground\!:hover {
|
|
3581
|
+
color: var(--foreground) !important;
|
|
3582
|
+
}
|
|
3550
3583
|
.hover\:text-warning:hover {
|
|
3551
3584
|
color: var(--warning);
|
|
3552
3585
|
}
|
|
@@ -3630,6 +3663,12 @@
|
|
|
3630
3663
|
.focus-visible\:bg-destructive-solid:focus-visible {
|
|
3631
3664
|
background-color: var(--destructive-solid);
|
|
3632
3665
|
}
|
|
3666
|
+
.focus-visible\:bg-destructive\/10:focus-visible {
|
|
3667
|
+
background-color: var(--destructive);
|
|
3668
|
+
@supports (color: color-mix(in lab, red, red)) {
|
|
3669
|
+
background-color: color-mix(in oklab, var(--destructive) 10%, transparent);
|
|
3670
|
+
}
|
|
3671
|
+
}
|
|
3633
3672
|
.focus-visible\:bg-muted:focus-visible {
|
|
3634
3673
|
background-color: var(--muted);
|
|
3635
3674
|
}
|
|
@@ -3752,6 +3791,9 @@
|
|
|
3752
3791
|
.disabled\:hover\:border-border:disabled:hover {
|
|
3753
3792
|
border-color: var(--border);
|
|
3754
3793
|
}
|
|
3794
|
+
.disabled\:hover\:bg-transparent:disabled:hover {
|
|
3795
|
+
background-color: transparent;
|
|
3796
|
+
}
|
|
3755
3797
|
.disabled\:hover\:text-muted-foreground:disabled:hover {
|
|
3756
3798
|
color: var(--muted-foreground);
|
|
3757
3799
|
}
|
|
@@ -3762,9 +3804,36 @@
|
|
|
3762
3804
|
.aria-disabled\:pointer-events-none[aria-disabled="true"] {
|
|
3763
3805
|
pointer-events: none;
|
|
3764
3806
|
}
|
|
3807
|
+
.aria-disabled\:cursor-not-allowed[aria-disabled="true"] {
|
|
3808
|
+
cursor: not-allowed;
|
|
3809
|
+
}
|
|
3765
3810
|
.aria-disabled\:opacity-30[aria-disabled="true"] {
|
|
3766
3811
|
opacity: 30%;
|
|
3767
3812
|
}
|
|
3813
|
+
.aria-disabled\:opacity-50[aria-disabled="true"] {
|
|
3814
|
+
opacity: 50%;
|
|
3815
|
+
}
|
|
3816
|
+
@media (hover: hover) {
|
|
3817
|
+
.aria-disabled\:hover\:bg-transparent[aria-disabled="true"]:hover {
|
|
3818
|
+
background-color: transparent;
|
|
3819
|
+
}
|
|
3820
|
+
}
|
|
3821
|
+
.aria-pressed\:border[aria-pressed="true"] {
|
|
3822
|
+
border-style: var(--tw-border-style);
|
|
3823
|
+
border-width: 1px;
|
|
3824
|
+
}
|
|
3825
|
+
.aria-pressed\:border-accent[aria-pressed="true"] {
|
|
3826
|
+
border-color: var(--accent);
|
|
3827
|
+
}
|
|
3828
|
+
.aria-pressed\:bg-accent\/10[aria-pressed="true"] {
|
|
3829
|
+
background-color: var(--accent);
|
|
3830
|
+
@supports (color: color-mix(in lab, red, red)) {
|
|
3831
|
+
background-color: color-mix(in oklab, var(--accent) 10%, transparent);
|
|
3832
|
+
}
|
|
3833
|
+
}
|
|
3834
|
+
.aria-pressed\:text-accent[aria-pressed="true"] {
|
|
3835
|
+
color: var(--accent);
|
|
3836
|
+
}
|
|
3768
3837
|
.aria-\[invalid\=true\]\:border-field-error[aria-invalid="true"] {
|
|
3769
3838
|
border-color: var(--field-error);
|
|
3770
3839
|
}
|
|
@@ -3915,6 +3984,9 @@
|
|
|
3915
3984
|
--tw-ring-shadow: var(--tw-ring-inset,) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color, currentcolor);
|
|
3916
3985
|
box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
|
|
3917
3986
|
}
|
|
3987
|
+
.data-\[state\=checked\]\:ring-accent[data-state="checked"] {
|
|
3988
|
+
--tw-ring-color: var(--accent);
|
|
3989
|
+
}
|
|
3918
3990
|
.data-\[state\=checked\]\:ring-foreground[data-state="checked"] {
|
|
3919
3991
|
--tw-ring-color: var(--foreground);
|
|
3920
3992
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tooltip.d.ts","sourceRoot":"","sources":["../../src/testing/tooltip.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"tooltip.d.ts","sourceRoot":"","sources":["../../src/testing/tooltip.ts"],"names":[],"mappings":"AA6CA,wEAAwE;AACxE,wBAAsB,YAAY,CAAC,IAAI,EAAE,MAAM,WAAW,GAAG,IAAI,GAAG,OAAO,CAAC,WAAW,CAAC,CASvF;AAED;;;;;;GAMG;AACH,wBAAsB,SAAS,CAAC,IAAI,EAAE,MAAM,WAAW,GAAG,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,CAa/E"}
|
package/dist/testing/tooltip.js
CHANGED
|
@@ -1,21 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
* 1. The Radix implementation is a dynamic `import()`, so nothing is wired at first
|
|
8
|
-
* paint. A test must WAIT for the upgrade.
|
|
9
|
-
* 2. The upgrade re-parents the trigger under Radix's `Trigger`, which React
|
|
10
|
-
* reconciles as a remount — so a node captured before the upgrade is detached.
|
|
11
|
-
* Every helper here re-queries rather than holding a reference.
|
|
12
|
-
*
|
|
13
|
-
* The reason a spec cares at all: `title=""` used to be the fleet's hover hint, and
|
|
14
|
-
* `DESIGN.md` §4 forbids it (the OS draws it after a second, in its own box, and a
|
|
15
|
-
* phone never draws it). A spec that asserted `getAttribute('title')` was asserting
|
|
16
|
-
* the defect; these helpers are what it should assert instead.
|
|
17
|
-
*/
|
|
18
|
-
import { fireEvent, waitFor } from "@testing-library/react";
|
|
1
|
+
let cached;
|
|
2
|
+
async function testingLibraryReact() {
|
|
3
|
+
if (!cached)
|
|
4
|
+
cached = await import("@testing-library/react");
|
|
5
|
+
return cached;
|
|
6
|
+
}
|
|
19
7
|
/**
|
|
20
8
|
* Radix renders the bubble's content TWICE — once visibly and once inside a
|
|
21
9
|
* `VisuallyHidden` node that becomes the trigger's accessible description — so the
|
|
@@ -30,6 +18,7 @@ function deduplicateAriaCopy(text) {
|
|
|
30
18
|
}
|
|
31
19
|
/** Wait until the lazy implementation has replaced the bare trigger. */
|
|
32
20
|
export async function tooltipReady(find) {
|
|
21
|
+
const { waitFor } = await testingLibraryReact();
|
|
33
22
|
await waitFor(() => {
|
|
34
23
|
const el = find();
|
|
35
24
|
if (!el?.getAttribute("data-state"))
|
|
@@ -48,6 +37,7 @@ export async function tooltipReady(find) {
|
|
|
48
37
|
* hover is dispatched.
|
|
49
38
|
*/
|
|
50
39
|
export async function hoverHint(find) {
|
|
40
|
+
const { fireEvent, waitFor } = await testingLibraryReact();
|
|
51
41
|
const el = await tooltipReady(find);
|
|
52
42
|
// Radix opens on `pointermove` over the trigger (not `pointerenter`, which React
|
|
53
43
|
// synthesizes and therefore never sees from a direct dispatch).
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tooltip.js","sourceRoot":"","sources":["../../src/testing/tooltip.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"tooltip.js","sourceRoot":"","sources":["../../src/testing/tooltip.ts"],"names":[],"mappings":"AA2BA,IAAI,MAAuC,CAAC;AAC5C,KAAK,UAAU,mBAAmB;IACjC,IAAI,CAAC,MAAM;QAAE,MAAM,GAAG,MAAM,MAAM,CAAC,wBAAwB,CAAC,CAAC;IAC7D,OAAO,MAAM,CAAC;AACf,CAAC;AAED;;;;;GAKG;AACH,SAAS,mBAAmB,CAAC,IAAY;IACxC,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IACvC,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC;IAC7B,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AAC9E,CAAC;AAED,wEAAwE;AACxE,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,IAA8B;IAChE,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,mBAAmB,EAAE,CAAC;IAChD,MAAM,OAAO,CAAC,GAAG,EAAE;QAClB,MAAM,EAAE,GAAG,IAAI,EAAE,CAAC;QAClB,IAAI,CAAC,EAAE,EAAE,YAAY,CAAC,YAAY,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAC;IAC/E,CAAC,CAAC,CAAC;IACH,MAAM,EAAE,GAAG,IAAI,EAAE,CAAC;IAClB,IAAI,CAAC,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAC;IACxD,OAAO,EAAE,CAAC;AACX,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,IAA8B;IAC7D,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,GAAG,MAAM,mBAAmB,EAAE,CAAC;IAC3D,MAAM,EAAE,GAAG,MAAM,YAAY,CAAC,IAAI,CAAC,CAAC;IACpC,iFAAiF;IACjF,gEAAgE;IAChE,SAAS,CAAC,WAAW,CAAC,EAAE,EAAE,EAAE,WAAW,EAAE,OAAO,EAAE,CAAC,CAAC;IACpD,IAAI,IAAI,GAAG,EAAE,CAAC;IACd,MAAM,OAAO,CAAC,GAAG,EAAE;QAClB,MAAM,MAAM,GAAG,QAAQ,CAAC,aAAa,CAAC,mBAAmB,CAAC,CAAC;QAC3D,IAAI,CAAC,MAAM,EAAE,WAAW;YAAE,MAAM,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAC;QACnE,IAAI,GAAG,mBAAmB,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;IAChD,CAAC,CAAC,CAAC;IACH,OAAO,IAAI,CAAC;AACb,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cursedbelt",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.34.0",
|
|
4
4
|
"license": "ISC",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "The React design system of the cursedbelt split — components, styles, theme. cursedbelt-core below it; server tier in cursedbelt-server.",
|
|
@@ -128,6 +128,12 @@
|
|
|
128
128
|
"source": "./src/react/analytics/index.ts",
|
|
129
129
|
"import": "./dist/react/analytics/index.js"
|
|
130
130
|
},
|
|
131
|
+
"./react/badge": {
|
|
132
|
+
"types": "./dist/react/components/Badge.d.ts",
|
|
133
|
+
"bun": "./src/react/components/Badge.tsx",
|
|
134
|
+
"source": "./src/react/components/Badge.tsx",
|
|
135
|
+
"import": "./dist/react/components/Badge.js"
|
|
136
|
+
},
|
|
131
137
|
"./react/button": {
|
|
132
138
|
"types": "./dist/react/components/Button.d.ts",
|
|
133
139
|
"bun": "./src/react/components/Button.tsx",
|
|
@@ -158,6 +164,12 @@
|
|
|
158
164
|
"source": "./src/react/clipboard/index.ts",
|
|
159
165
|
"import": "./dist/react/clipboard/index.js"
|
|
160
166
|
},
|
|
167
|
+
"./react/code-chip": {
|
|
168
|
+
"types": "./dist/react/components/CodeChip.d.ts",
|
|
169
|
+
"bun": "./src/react/components/CodeChip.tsx",
|
|
170
|
+
"source": "./src/react/components/CodeChip.tsx",
|
|
171
|
+
"import": "./dist/react/components/CodeChip.js"
|
|
172
|
+
},
|
|
161
173
|
"./react/code-editor": {
|
|
162
174
|
"types": "./dist/react/code-editor/index.d.ts",
|
|
163
175
|
"bun": "./src/react/code-editor/index.ts",
|
|
@@ -206,12 +218,30 @@
|
|
|
206
218
|
"source": "./src/react/components/DropdownMenu.tsx",
|
|
207
219
|
"import": "./dist/react/components/DropdownMenu.js"
|
|
208
220
|
},
|
|
221
|
+
"./react/empty-state": {
|
|
222
|
+
"types": "./dist/react/components/EmptyState.d.ts",
|
|
223
|
+
"bun": "./src/react/components/EmptyState.tsx",
|
|
224
|
+
"source": "./src/react/components/EmptyState.tsx",
|
|
225
|
+
"import": "./dist/react/components/EmptyState.js"
|
|
226
|
+
},
|
|
209
227
|
"./react/engagement-beacon": {
|
|
210
228
|
"types": "./dist/react/engagement/index.d.ts",
|
|
211
229
|
"bun": "./src/react/engagement/index.ts",
|
|
212
230
|
"source": "./src/react/engagement/index.ts",
|
|
213
231
|
"import": "./dist/react/engagement/index.js"
|
|
214
232
|
},
|
|
233
|
+
"./react/error-card": {
|
|
234
|
+
"types": "./dist/react/components/ErrorCard.d.ts",
|
|
235
|
+
"bun": "./src/react/components/ErrorCard.tsx",
|
|
236
|
+
"source": "./src/react/components/ErrorCard.tsx",
|
|
237
|
+
"import": "./dist/react/components/ErrorCard.js"
|
|
238
|
+
},
|
|
239
|
+
"./react/field": {
|
|
240
|
+
"types": "./dist/react/components/Field.d.ts",
|
|
241
|
+
"bun": "./src/react/components/Field.tsx",
|
|
242
|
+
"source": "./src/react/components/Field.tsx",
|
|
243
|
+
"import": "./dist/react/components/Field.js"
|
|
244
|
+
},
|
|
215
245
|
"./react/file-tree": {
|
|
216
246
|
"types": "./dist/react/file-tree/index.d.ts",
|
|
217
247
|
"bun": "./src/react/file-tree/index.ts",
|
|
@@ -242,6 +272,12 @@
|
|
|
242
272
|
"source": "./src/react/components/IconButton.tsx",
|
|
243
273
|
"import": "./dist/react/components/IconButton.js"
|
|
244
274
|
},
|
|
275
|
+
"./react/icons": {
|
|
276
|
+
"types": "./dist/react/icons.d.ts",
|
|
277
|
+
"bun": "./src/react/icons.tsx",
|
|
278
|
+
"source": "./src/react/icons.tsx",
|
|
279
|
+
"import": "./dist/react/icons.js"
|
|
280
|
+
},
|
|
245
281
|
"./react/info-hint": {
|
|
246
282
|
"types": "./dist/react/components/InfoHint.d.ts",
|
|
247
283
|
"bun": "./src/react/components/InfoHint.tsx",
|
|
@@ -398,6 +434,36 @@
|
|
|
398
434
|
"source": "./src/react/hooks/useTableSort.ts",
|
|
399
435
|
"import": "./dist/react/hooks/useTableSort.js"
|
|
400
436
|
},
|
|
437
|
+
"./react/menu": {
|
|
438
|
+
"types": "./dist/react/components/Menu.d.ts",
|
|
439
|
+
"bun": "./src/react/components/Menu.tsx",
|
|
440
|
+
"source": "./src/react/components/Menu.tsx",
|
|
441
|
+
"import": "./dist/react/components/Menu.js"
|
|
442
|
+
},
|
|
443
|
+
"./react/save-indicator": {
|
|
444
|
+
"types": "./dist/react/components/SaveIndicator.d.ts",
|
|
445
|
+
"bun": "./src/react/components/SaveIndicator.tsx",
|
|
446
|
+
"source": "./src/react/components/SaveIndicator.tsx",
|
|
447
|
+
"import": "./dist/react/components/SaveIndicator.js"
|
|
448
|
+
},
|
|
449
|
+
"./react/selection-bar": {
|
|
450
|
+
"types": "./dist/react/components/SelectionBar.d.ts",
|
|
451
|
+
"bun": "./src/react/components/SelectionBar.tsx",
|
|
452
|
+
"source": "./src/react/components/SelectionBar.tsx",
|
|
453
|
+
"import": "./dist/react/components/SelectionBar.js"
|
|
454
|
+
},
|
|
455
|
+
"./react/unstyled-button": {
|
|
456
|
+
"types": "./dist/react/components/UnstyledButton.d.ts",
|
|
457
|
+
"bun": "./src/react/components/UnstyledButton.tsx",
|
|
458
|
+
"source": "./src/react/components/UnstyledButton.tsx",
|
|
459
|
+
"import": "./dist/react/components/UnstyledButton.js"
|
|
460
|
+
},
|
|
461
|
+
"./react/modal": {
|
|
462
|
+
"types": "./dist/react/components/Modal.d.ts",
|
|
463
|
+
"bun": "./src/react/components/Modal.tsx",
|
|
464
|
+
"source": "./src/react/components/Modal.tsx",
|
|
465
|
+
"import": "./dist/react/components/Modal.js"
|
|
466
|
+
},
|
|
401
467
|
"./react/multi-select-field": {
|
|
402
468
|
"types": "./dist/react/components/MultiSelectField.d.ts",
|
|
403
469
|
"bun": "./src/react/components/MultiSelectField.tsx",
|
|
@@ -434,6 +500,18 @@
|
|
|
434
500
|
"source": "./src/react/components/Switch.tsx",
|
|
435
501
|
"import": "./dist/react/components/Switch.js"
|
|
436
502
|
},
|
|
503
|
+
"./react/toast": {
|
|
504
|
+
"types": "./dist/react/Toast.d.ts",
|
|
505
|
+
"bun": "./src/react/Toast.tsx",
|
|
506
|
+
"source": "./src/react/Toast.tsx",
|
|
507
|
+
"import": "./dist/react/Toast.js"
|
|
508
|
+
},
|
|
509
|
+
"./react/tooltip": {
|
|
510
|
+
"types": "./dist/react/components/Tooltip.d.ts",
|
|
511
|
+
"bun": "./src/react/components/Tooltip.tsx",
|
|
512
|
+
"source": "./src/react/components/Tooltip.tsx",
|
|
513
|
+
"import": "./dist/react/components/Tooltip.js"
|
|
514
|
+
},
|
|
437
515
|
"./react/upload-direct": {
|
|
438
516
|
"types": "./dist/react/lib/directUpload.d.ts",
|
|
439
517
|
"bun": "./src/react/lib/directUpload.ts",
|
|
@@ -725,8 +803,8 @@
|
|
|
725
803
|
"@types/react-dom": "^19.2.3",
|
|
726
804
|
"@vidstack/react": "1.15.6",
|
|
727
805
|
"@vitejs/plugin-react": "^5.2.0",
|
|
728
|
-
"cursedbelt-server": "^4.40.
|
|
729
|
-
"cursedops": "^0.
|
|
806
|
+
"cursedbelt-server": "^4.40.3",
|
|
807
|
+
"cursedops": "^0.12.0",
|
|
730
808
|
"diff": "^9.0.0",
|
|
731
809
|
"emoji-mart": "^5.6.0",
|
|
732
810
|
"hls.js": "^1.5.0",
|
package/scripts/styleAreas.ts
CHANGED
|
@@ -173,6 +173,7 @@ export const AREAS: readonly Area[] = [
|
|
|
173
173
|
'components/IconButton.tsx',
|
|
174
174
|
'components/InfoHint.tsx',
|
|
175
175
|
'components/Input.tsx',
|
|
176
|
+
'components/Menu.tsx',
|
|
176
177
|
'components/Modal.tsx',
|
|
177
178
|
'components/OnlineDot.tsx',
|
|
178
179
|
'components/Page.tsx',
|
|
@@ -196,6 +197,9 @@ export const AREAS: readonly Area[] = [
|
|
|
196
197
|
'components/Tooltip.tsx',
|
|
197
198
|
'components/TooltipImpl.tsx',
|
|
198
199
|
'components/TruncatedText.tsx',
|
|
200
|
+
'components/UnstyledButton.tsx',
|
|
201
|
+
'components/SaveIndicator.tsx',
|
|
202
|
+
'components/SelectionBar.tsx',
|
|
199
203
|
'components/dialog.tsx',
|
|
200
204
|
'components/layout.tsx',
|
|
201
205
|
'components/revealOnHover.ts',
|
package/src/react/Toast.spec.tsx
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { afterEach, describe, expect, test } from 'bun:test';
|
|
2
|
-
import { cleanup, render } from '@testing-library/react';
|
|
2
|
+
import { act, cleanup, render, waitFor } from '@testing-library/react';
|
|
3
3
|
import { Toaster, toast } from './Toast.js';
|
|
4
4
|
|
|
5
5
|
afterEach(cleanup);
|
|
@@ -15,4 +15,20 @@ describe('Toast', () => {
|
|
|
15
15
|
test('Toaster mounts without throwing', () => {
|
|
16
16
|
expect(() => render(<Toaster />)).not.toThrow();
|
|
17
17
|
});
|
|
18
|
+
|
|
19
|
+
test("the toaster answers sonner's own colour variables with the belt's tokens", async () => {
|
|
20
|
+
render(<Toaster />);
|
|
21
|
+
act(() => {
|
|
22
|
+
toast('Saved');
|
|
23
|
+
});
|
|
24
|
+
const toaster = await waitFor(() => {
|
|
25
|
+
const found = document.querySelector<HTMLElement>('[data-sonner-toaster]');
|
|
26
|
+
if (!found) throw new Error('no toaster yet');
|
|
27
|
+
return found;
|
|
28
|
+
});
|
|
29
|
+
// sonner's theme sets these on the same element; an inline value is what outranks it.
|
|
30
|
+
expect(toaster.style.getPropertyValue('--normal-bg')).toBe('var(--popover)');
|
|
31
|
+
expect(toaster.style.getPropertyValue('--normal-border')).toBe('var(--border)');
|
|
32
|
+
expect(toaster.style.getPropertyValue('--normal-text')).toBe('var(--popover-foreground)');
|
|
33
|
+
});
|
|
18
34
|
});
|
package/src/react/Toast.tsx
CHANGED
|
@@ -17,19 +17,36 @@ export { toast };
|
|
|
17
17
|
|
|
18
18
|
export type ToasterProps = React.ComponentProps<typeof SonnerToaster>;
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
/**
|
|
21
|
+
* 🔴 sonner paints a toast from its OWN variables (`--normal-bg`, `--normal-border`,
|
|
22
|
+
* `--normal-text`), set per `data-sonner-theme` on the toaster — and its rule outranks the
|
|
23
|
+
* `bg-popover`/`border-border` classes below wherever the app's utilities are not layered
|
|
24
|
+
* above it. Measured in desk, 2026-09-30 (forge task 2413): a white toast on the dark theme,
|
|
25
|
+
* because sonner's theme defaults to light. Answering the variables with the belt's tokens on
|
|
26
|
+
* the toaster itself makes the toast follow the app's theme whatever sonner thinks it is.
|
|
27
|
+
*/
|
|
28
|
+
const TOKEN_VARS = {
|
|
29
|
+
'--normal-bg': 'var(--popover)',
|
|
30
|
+
'--normal-border': 'var(--border)',
|
|
31
|
+
'--normal-text': 'var(--popover-foreground)',
|
|
32
|
+
} as React.CSSProperties;
|
|
33
|
+
|
|
34
|
+
export function Toaster({ style, ...props }: ToasterProps) {
|
|
21
35
|
return (
|
|
22
36
|
<SonnerToaster
|
|
37
|
+
style={{ ...TOKEN_VARS, ...style }}
|
|
23
38
|
position='bottom-right'
|
|
24
39
|
closeButton
|
|
25
40
|
toastOptions={{
|
|
26
41
|
classNames: {
|
|
27
42
|
toast: 'rounded-lg border border-border bg-popover text-foreground shadow-overlay',
|
|
28
43
|
title: 'text-sm font-medium',
|
|
29
|
-
|
|
44
|
+
// `!` because sonner colours these two with element rules of its own (`#3f3f3f` for a
|
|
45
|
+
// description, its grey scale for the close button) that no variable reaches.
|
|
46
|
+
description: 'text-xs text-muted-foreground!',
|
|
30
47
|
actionButton: 'bg-accent-solid text-white text-xs px-2 py-1 rounded-sm',
|
|
31
48
|
cancelButton: 'bg-muted text-foreground text-xs px-2 py-1 rounded-sm',
|
|
32
|
-
closeButton: 'border-border bg-popover text-muted-foreground hover:text-foreground',
|
|
49
|
+
closeButton: 'border-border! bg-popover! text-muted-foreground! hover:text-foreground!',
|
|
33
50
|
error: 'border-destructive/50 [&_[data-icon]]:text-destructive',
|
|
34
51
|
success: 'border-success/50 [&_[data-icon]]:text-success',
|
|
35
52
|
warning: 'border-warning/50 [&_[data-icon]]:text-warning',
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { afterEach, describe, expect, test } from 'bun:test';
|
|
2
|
-
import { cleanup, render } from '@testing-library/react';
|
|
2
|
+
import { cleanup, fireEvent, render } from '@testing-library/react';
|
|
3
3
|
import { createRef } from 'react';
|
|
4
4
|
import { Button } from './Button.js';
|
|
5
5
|
import { ButtonGroup } from './ButtonGroup.js';
|
|
@@ -119,6 +119,54 @@ describe('Button', () => {
|
|
|
119
119
|
expect((getByRole('button') as HTMLButtonElement).disabled).toBe(true);
|
|
120
120
|
});
|
|
121
121
|
|
|
122
|
+
test('unavailableReason REFUSES the press but stays focusable: aria-disabled, not disabled', () => {
|
|
123
|
+
let clicks = 0;
|
|
124
|
+
let keys = 0;
|
|
125
|
+
const { getByRole } = render(
|
|
126
|
+
<Button tooltip='Sync' unavailableReason='Sync needs the Mac' onClick={() => clicks++} onKeyDown={() => keys++}>
|
|
127
|
+
Sync
|
|
128
|
+
</Button>,
|
|
129
|
+
);
|
|
130
|
+
const btn = getByRole('button') as HTMLButtonElement;
|
|
131
|
+
expect(btn.disabled).toBe(false); // still in the tab order, still hoverable
|
|
132
|
+
expect(btn.getAttribute('aria-disabled')).toBe('true');
|
|
133
|
+
btn.click();
|
|
134
|
+
expect(clicks).toBe(0);
|
|
135
|
+
fireEvent.keyDown(btn, { key: 'Enter' });
|
|
136
|
+
fireEvent.keyDown(btn, { key: ' ' });
|
|
137
|
+
expect(keys).toBe(0);
|
|
138
|
+
fireEvent.keyDown(btn, { key: 'Tab' }); // every other key still reaches the caller
|
|
139
|
+
expect(keys).toBe(1);
|
|
140
|
+
btn.focus();
|
|
141
|
+
expect(document.activeElement).toBe(btn);
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
test('an empty unavailableReason is no refusal, and disabled wins over one', () => {
|
|
145
|
+
let clicks = 0;
|
|
146
|
+
const { getByRole, rerender } = render(
|
|
147
|
+
<Button tooltip='Go' unavailableReason=' ' onClick={() => clicks++}>
|
|
148
|
+
Go
|
|
149
|
+
</Button>,
|
|
150
|
+
);
|
|
151
|
+
getByRole('button').click();
|
|
152
|
+
expect(clicks).toBe(1);
|
|
153
|
+
expect(getByRole('button').getAttribute('aria-disabled')).toBeNull();
|
|
154
|
+
rerender(
|
|
155
|
+
<Button tooltip='Go' unavailableReason='Busy' disabled onClick={() => clicks++}>
|
|
156
|
+
Go
|
|
157
|
+
</Button>,
|
|
158
|
+
);
|
|
159
|
+
expect((getByRole('button') as HTMLButtonElement).disabled).toBe(true);
|
|
160
|
+
expect(getByRole('button').getAttribute('aria-disabled')).toBeNull();
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
test('a pressed toggle and a refused control are drawn by the variant classes', () => {
|
|
164
|
+
const cls = render(<Button tooltip='B'>B</Button>).getByRole('button').className;
|
|
165
|
+
expect(cls).toContain('aria-pressed:border-accent');
|
|
166
|
+
expect(cls).toContain('aria-disabled:opacity-50');
|
|
167
|
+
expect(cls).not.toContain('aria-disabled:pointer-events-none'); // the reason must stay reachable
|
|
168
|
+
});
|
|
169
|
+
|
|
122
170
|
test('asChild styles the child element directly (no nested button element, no span wrapper)', () => {
|
|
123
171
|
const { container, getByRole } = render(
|
|
124
172
|
<Button tooltip='Action' asChild variant='primary'>
|