cursedbelt 5.59.0 → 5.63.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. package/dist/react/components/ColorSwatches.d.ts +33 -0
  2. package/dist/react/components/ColorSwatches.d.ts.map +1 -0
  3. package/dist/react/components/ColorSwatches.js +42 -0
  4. package/dist/react/components/ColorSwatches.js.map +1 -0
  5. package/dist/react/components/EditorPage.d.ts +1 -0
  6. package/dist/react/components/EditorPage.d.ts.map +1 -1
  7. package/dist/react/components/EditorPage.js +6 -1
  8. package/dist/react/components/EditorPage.js.map +1 -1
  9. package/dist/react/components/FormPreviewLayout.d.ts +1 -0
  10. package/dist/react/components/FormPreviewLayout.d.ts.map +1 -1
  11. package/dist/react/components/FormPreviewLayout.js +2 -1
  12. package/dist/react/components/FormPreviewLayout.js.map +1 -1
  13. package/dist/react/components/PropertyList.d.ts +17 -3
  14. package/dist/react/components/PropertyList.d.ts.map +1 -1
  15. package/dist/react/components/PropertyList.js +11 -3
  16. package/dist/react/components/PropertyList.js.map +1 -1
  17. package/dist/react/components/SwatchPicker.d.ts +37 -9
  18. package/dist/react/components/SwatchPicker.d.ts.map +1 -1
  19. package/dist/react/components/SwatchPicker.js +52 -9
  20. package/dist/react/components/SwatchPicker.js.map +1 -1
  21. package/dist/react/components/TreeView.d.ts +39 -4
  22. package/dist/react/components/TreeView.d.ts.map +1 -1
  23. package/dist/react/components/TreeView.js +54 -15
  24. package/dist/react/components/TreeView.js.map +1 -1
  25. package/dist/react/components/editorPage.css +1 -7
  26. package/dist/react/components/formKit.css +5 -6
  27. package/dist/react/components/scrollRegion.css +31 -0
  28. package/dist/react/index.d.ts +2 -1
  29. package/dist/react/index.d.ts.map +1 -1
  30. package/dist/react/index.js +1 -0
  31. package/dist/react/index.js.map +1 -1
  32. package/dist/react/master-detail/MasterDetail.d.ts.map +1 -1
  33. package/dist/react/master-detail/MasterDetail.js +1 -1
  34. package/dist/react/master-detail/MasterDetail.js.map +1 -1
  35. package/dist/scripts/guardrailsEnforce.d.ts.map +1 -1
  36. package/dist/styles-areas/core.css +6 -6
  37. package/dist/styles-areas/disk-usage.css +7 -7
  38. package/dist/styles-areas/fields.css +24 -22
  39. package/dist/styles-areas/master-detail.css +2 -2
  40. package/dist/styles-areas/nav.css +25 -26
  41. package/dist/styles-areas/workbench.css +2 -2
  42. package/dist/styles-utilities.css +31 -0
  43. package/dist/theme.css +23 -20
  44. package/package.json +24 -5
  45. package/scripts/guardrails-baseline.json +2 -2
  46. package/scripts/guardrailsEnforce.spec.ts +31 -0
  47. package/scripts/guardrailsEnforce.ts +37 -2
  48. package/scripts/styleAreas.ts +1 -0
  49. package/src/react/components/ColorSwatches.spec.tsx +62 -0
  50. package/src/react/components/ColorSwatches.tsx +100 -0
  51. package/src/react/components/EditorPage.spec.tsx +18 -0
  52. package/src/react/components/EditorPage.tsx +12 -2
  53. package/src/react/components/FormPreviewLayout.tsx +2 -1
  54. package/src/react/components/PropertyList.spec.tsx +33 -0
  55. package/src/react/components/PropertyList.tsx +31 -6
  56. package/src/react/components/SwatchPicker.spec.tsx +92 -0
  57. package/src/react/components/SwatchPicker.tsx +119 -33
  58. package/src/react/components/TreeView.spec.tsx +157 -0
  59. package/src/react/components/TreeView.tsx +161 -14
  60. package/src/react/components/editorPage.css +1 -7
  61. package/src/react/components/formKit.css +5 -6
  62. package/src/react/components/formKit.spec.tsx +9 -0
  63. package/src/react/components/scrollRegion.css +31 -0
  64. package/src/react/index.ts +2 -0
  65. package/src/react/master-detail/MasterDetail.spec.tsx +21 -0
  66. package/src/react/master-detail/MasterDetail.tsx +7 -3
  67. package/src/styles-areas/core.css +6 -6
  68. package/src/styles-areas/disk-usage.css +7 -7
  69. package/src/styles-areas/fields.css +24 -22
  70. package/src/styles-areas/master-detail.css +2 -2
  71. package/src/styles-areas/nav.css +25 -26
  72. package/src/styles-areas/workbench.css +2 -2
  73. package/src/styles-utilities.css +31 -0
  74. package/src/theme.css +23 -20
  75. package/src/themeDarkScopeAliases.spec.ts +30 -0
@@ -15,7 +15,7 @@
15
15
  * after an app's responsive variant (task 2124). An app that imports every area gets exactly
16
16
  * what `cursedbelt/styles-utilities.css` emits — proved rule by rule in
17
17
  * src/stylesAreas.spec.ts, which is also what fails when this file is stale.
18
- * 863 candidate(s).
18
+ * 864 candidate(s).
19
19
  *
20
20
  * Written by scripts/generateAreaStyles.ts (`bun run styles:areas`), which
21
21
  * `bun run build` runs. The map of what is in which area, and why the areas are
@@ -64,11 +64,11 @@
64
64
  @source inline("border-field-border border-rule border-success/30 border-success/40 border-success/50 border-t");
65
65
  @source inline("border-tone-sky-fg/30 border-tone-slate-fg/30 border-transparent border-warning/30");
66
66
  @source inline("border-warning/40 border-warning/50 border-x-4 border-x-transparent bot bottom bottom-0 break");
67
- @source inline("break-all break-words c ca cap capitalize co com contain container content contents cursor");
68
- @source inline("cursor-col-resize cursor-default cursor-ew-resize cursor-not-allowed cursor-pointer");
69
- @source inline("cursor-row-resize d dark dark:bg-card-overlay dark:bg-card-raised dark:bg-gray-800 data");
70
- @source inline("data-[disabled]:hover:bg-border data-[disabled]:opacity-50 data-[disabled]:pointer-events-none");
71
- @source inline("data-[interactive=true]:duration-[var(--duration-base)]");
67
+ @source inline("break-all break-words c ca cap capitalize co col-span-full com contain container content");
68
+ @source inline("contents cursor cursor-col-resize cursor-default cursor-ew-resize cursor-not-allowed");
69
+ @source inline("cursor-pointer cursor-row-resize d dark dark:bg-card-overlay dark:bg-card-raised");
70
+ @source inline("dark:bg-gray-800 data data-[disabled]:hover:bg-border data-[disabled]:opacity-50");
71
+ @source inline("data-[disabled]:pointer-events-none data-[interactive=true]:duration-[var(--duration-base)]");
72
72
  @source inline("data-[interactive=true]:ease-[var(--ease-out)] data-[interactive=true]:hover:-translate-y-0.5");
73
73
  @source inline("data-[interactive=true]:hover:border-border-strong data-[interactive=true]:transition-all");
74
74
  @source inline("data-[interactive=true]:transition-colors data-[placeholder]:text-muted-foreground");
@@ -18,15 +18,15 @@
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
- * 32 candidate(s).
21
+ * 33 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 bg-accent/60 collapse cursor-help duration-150 focus-within:border-field-ring");
28
- @source inline("focus-within:ring-2 focus-within:ring-field-ring/30 group-focus-visible/tile:opacity-100");
29
- @source inline("group-hover/du-row:opacity-100 group-hover/tile:opacity-100 group/du-row group/tile");
30
- @source inline("hover:bg-muted-foreground/10 italic max-w-56 max-w-96 mb-2 min-h-8 min-w-24 min-w-56 mr-0.5");
31
- @source inline("opacity-100 pl-2 pr-1 ring-inset ring-ring self-stretch text-3xl text-[length:var(--text-glyph)]");
32
- @source inline("text-muted-foreground/60 text-success");
27
+ @source inline("[&_svg]:size-3 bg-accent/60 collapse cursor-help duration-150 first:pt-1");
28
+ @source inline("focus-within:border-field-ring focus-within:ring-2 focus-within:ring-field-ring/30");
29
+ @source inline("group-focus-visible/tile:opacity-100 group-hover/du-row:opacity-100 group-hover/tile:opacity-100");
30
+ @source inline("group/du-row group/tile hover:bg-muted-foreground/10 italic max-w-56 max-w-96 mb-2 min-h-8");
31
+ @source inline("min-w-24 min-w-56 mr-0.5 opacity-100 pl-2 pr-1 ring-inset ring-ring self-stretch text-3xl");
32
+ @source inline("text-[length:var(--text-glyph)] text-muted-foreground/60 text-success");
@@ -18,35 +18,37 @@
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
- * 114 candidate(s).
21
+ * 121 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("-mx-1 [&::-webkit-scrollbar]:hidden [&_svg]:size-3 [scrollbar-width:none] appearance-none");
28
- @source inline("bg-accent/15 bg-surface-sunken/80 bg-warning/10 border-border/40 border-field-error border-l");
29
- @source inline("border-r caret-transparent cursor-text data-[ending-style]:opacity-0");
30
- @source inline("data-[ending-style]:scale-95 data-[highlighted]:bg-accent/10");
31
- @source inline("data-[highlighted]:text-accent-strong data-[starting-style]:opacity-0");
32
- @source inline("data-[starting-style]:scale-95 data-[state=checked]:ring-foreground");
33
- @source inline("data-[state=checked]:ring-offset-1 data-[state=closed]:slide-out-to-bottom");
34
- @source inline("data-[state=closed]:slide-out-to-left data-[state=closed]:slide-out-to-right");
35
- @source inline("data-[state=open]:slide-in-from-bottom data-[state=open]:slide-in-from-left");
36
- @source inline("data-[state=open]:slide-in-from-right disabled:hover:scale-100 disabled:opacity-40 duration-100");
37
- @source inline("focus-visible:border-border-strong focus-visible:ring-0 focus-visible:ring-field-ring/40");
38
- @source inline("focus-within:border-field-ring focus-within:ring-2 focus-within:ring-field-ring/30");
39
- @source inline("group-focus-within:opacity-100 h-105 h-12 h-3.5 has-[[aria-invalid=true]]:border-field-error");
40
- @source inline("hover:bg-muted/50 hover:border-field-ring hover:scale-110 hover:text-warning italic leading-5");
41
- @source inline("left-0 left-2.5 li list-none max-h-64 max-h-[var(--sheet-h-lg)] max-h-[var(--sheet-h-md)]");
42
- @source inline("max-h-[var(--sheet-h-sm)] max-w-sm md:flex-col md:gap-0.5 md:justify-start md:overflow-visible");
43
- @source inline("md:text-left md:w-full min-h-20 min-w-24 min-w-64 min-w-[var(--anchor-width)] min-w-full");
44
- @source inline("min-w-max mix-blend-difference mr-2 pl-1.5 pl-2 pl-2.5 pointer-coarse:before:-left-1");
45
- @source inline("pointer-coarse:before:-right-1 pointer-coarse:before:absolute");
46
- @source inline("pointer-coarse:before:bottom-[calc(var(--hit-slop-y)*-1)]");
27
+ @source inline("-mx-1 [&::-webkit-scrollbar]:hidden [&_svg]:size-3");
28
+ @source inline("[background:var(--cb-swatch-fill,var(--muted))] [scrollbar-width:none] appearance-none");
29
+ @source inline("aria-checked:ring-2 aria-checked:ring-foreground aria-checked:ring-offset-1 bg-accent/15");
30
+ @source inline("bg-surface-sunken/80 bg-warning/10 border-border/40 border-field-error border-l border-r");
31
+ @source inline("caret-transparent cursor-text data-[ending-style]:opacity-0 data-[ending-style]:scale-95");
32
+ @source inline("data-[highlighted]:bg-accent/10 data-[highlighted]:text-accent-strong");
33
+ @source inline("data-[starting-style]:opacity-0 data-[starting-style]:scale-95");
34
+ @source inline("data-[state=checked]:ring-foreground data-[state=checked]:ring-offset-1");
35
+ @source inline("data-[state=closed]:slide-out-to-bottom data-[state=closed]:slide-out-to-left");
36
+ @source inline("data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-bottom");
37
+ @source inline("data-[state=open]:slide-in-from-left data-[state=open]:slide-in-from-right");
38
+ @source inline("disabled:hover:scale-100 disabled:opacity-40 duration-100 focus-visible:border-border-strong");
39
+ @source inline("focus-visible:ring-0 focus-visible:ring-field-ring/40 focus-within:border-field-ring");
40
+ @source inline("focus-within:ring-2 focus-within:ring-field-ring/30 focus-within:ring-offset-1");
41
+ @source inline("focus-within:ring-ring group-focus-within:opacity-100 h-105 h-12 h-3.5");
42
+ @source inline("has-[[aria-invalid=true]]:border-field-error hover:bg-muted/50 hover:border-field-ring");
43
+ @source inline("hover:scale-110 hover:text-warning italic leading-5 left-0 left-2.5 li list-none max-h-64");
44
+ @source inline("max-h-[var(--sheet-h-lg)] max-h-[var(--sheet-h-md)] max-h-[var(--sheet-h-sm)] max-w-sm");
45
+ @source inline("md:flex-col md:gap-0.5 md:justify-start md:overflow-visible md:text-left md:w-full min-h-20");
46
+ @source inline("min-w-24 min-w-64 min-w-[var(--anchor-width)] min-w-full min-w-max mix-blend-difference mr-2");
47
+ @source inline("pl-1.5 pl-2 pl-2.5 pointer-coarse:before:-left-1 pointer-coarse:before:-right-1");
48
+ @source inline("pointer-coarse:before:absolute pointer-coarse:before:bottom-[calc(var(--hit-slop-y)*-1)]");
47
49
  @source inline("pointer-coarse:before:top-[calc(var(--hit-slop-y)*-1)] pointer-coarse:items-center pr-1 pr-16");
48
50
  @source inline("pr-2 pr-3 pr-9 pt-1 resize-none resize-y right-1.5 right-3 ring-accent/30 ring-field-error/30");
49
- @source inline("rounded-l-xl rounded-r-xl rounded-t-xl self-stretch size-7 size-9 sm:w-11 sm:w-56");
51
+ @source inline("rounded-l-xl rounded-r-xl rounded-t-xl self-stretch size-7 size-9 size-full sm:w-11 sm:w-56");
50
52
  @source inline("text-field-placeholder text-success text-xl top-1.5 transition-[transform,opacity] w-20 w-32");
51
53
  @source inline("w-36 w-40 w-88 w-fit w-max whitespace-pre");
52
54
  @source inline('pointer-coarse:before:content-[""]');
@@ -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
- * 24 candidate(s).
21
+ * 25 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
@@ -28,4 +28,4 @@
28
28
  @source inline("bg-accent/15 border-[var(--border)] flex-row focus-within:border-field-ring focus-within:ring-2");
29
29
  @source inline("focus-within:ring-field-ring/30 has-[[aria-invalid=true]]:border-field-error");
30
30
  @source inline("hover:bg-[var(--muted)] hover:bg-muted/80 mb-1.5 mb-4 min-h min-h-full pb-0.5 pr-1 ring-1");
31
- @source inline("ring-[var(--accent)]/40 ring-accent/30 ring-inset self-stretch");
31
+ @source inline("ring-[var(--accent)]/40 ring-accent/30 ring-inset self-stretch shrink-[1000]");
@@ -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
- * 143 candidate(s).
21
+ * 144 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
@@ -30,28 +30,27 @@
30
30
  @source inline("[&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:tracking-wide");
31
31
  @source inline("[&_[cmdk-group-heading]]:uppercase [&_[data-cb-banner-icon]]:text-accent");
32
32
  @source inline("[&_[data-cb-banner-icon]]:text-destructive [&_[data-cb-banner-icon]]:text-warning");
33
- @source inline("[&_svg]:size-3.5 [scrollbar-width:none] bg-accent/15 bg-destructive/10 bg-warning/10");
34
- @source inline("border-border/40 border-dashed border-l border-r collapse cursor-grab");
35
- @source inline("data-[disabled=true]:opacity-50 data-[disabled=true]:pointer-events-none");
36
- @source inline("data-[selected=true]:bg-muted data-[selected=true]:text-foreground");
37
- @source inline("data-[state=checked]:ring-foreground data-[state=checked]:ring-offset-1");
38
- @source inline("data-[state=closed]:slide-out-to-bottom data-[state=closed]:slide-out-to-left");
39
- @source inline("data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-bottom");
40
- @source inline("data-[state=open]:slide-in-from-left data-[state=open]:slide-in-from-right");
41
- @source inline("data-[state=open]:slide-in-from-top-2 disabled:hover:scale-100 disabled:opacity-40");
42
- @source inline("focus-within:opacity-100 g grid-cols-4 group-hover/navitem:opacity-100");
43
- @source inline("group-hover/tile:opacity-100 group/navitem group/tile h-12 h-[var(--header-h)]");
44
- @source inline("h-[var(--header-h-dense)] h-[var(--header-h-roomy)] h-dvh hover:border-foreground/20");
45
- @source inline("hover:decoration-border hover:scale-110 hover:underline-offset-4 inset-x-2 inset-x-3 inset-y-1");
46
- @source inline("inset-y-1.5 items-stretch justify-around leading-4 left-0 left-3 lg:flex lg:flex-col lg:hidden");
47
- @source inline("lg:shrink-0 list-none max-h-72 max-h-[inherit] max-h-[var(--palette-max-h)]");
48
- @source inline("max-h-[var(--sheet-h-lg)] max-h-[var(--sheet-h-md)] max-h-[var(--sheet-h-sm)] max-md:-right-0.5");
49
- @source inline("max-md:-top-0.5 max-md:absolute max-md:hidden max-sm:flex-none max-sm:justify-center max-sm:px-0");
50
- @source inline("max-sm:w-10 max-w max-w-48 max-w-64 max-w-80 max-w-sm md:flex md:flex-col md:gap-4 md:hidden");
51
- @source inline("md:pointer-coarse:w-auto md:px-3 md:px-6 md:shrink-0 min-h-10 min-h-12 min-h-dvh min-w-3.5");
52
- @source inline("min-w-8 min-w-9 mix-blend-difference mt-auto mx-1 no-underline opacity-55 opacity-80");
53
- @source inline("pb-[env(safe-area-inset-bottom,0px)] pl-11 pl-9 place-items-center");
54
- @source inline("placeholder:text-muted-foreground pr-3 pr-9 pt-0 pt-1 px-0.5 py-8 right-1 rotate-180");
55
- @source inline("rounded-l-xl rounded-r-xl rounded-t-xl shadow-lg size-7 size-9 sm:inline sm:inline-block");
56
- @source inline("sm:inline-flex space-y-0.5 space-y-2 top-[var(--palette-top)] w-52 w-56 w-60 w-[calc(100%-2rem)]");
57
- @source inline("w-[var(--rail-w)] w-[var(--rail-w-collapsed)] w-max");
33
+ @source inline("[&_svg]:size-3.5 [scrollbar-width:none] aria-checked:ring-2 aria-checked:ring-foreground");
34
+ @source inline("aria-checked:ring-offset-1 bg-accent/15 bg-destructive/10 bg-warning/10 border-border/40");
35
+ @source inline("border-dashed border-l border-r collapse cursor-grab data-[disabled=true]:opacity-50");
36
+ @source inline("data-[disabled=true]:pointer-events-none data-[selected=true]:bg-muted");
37
+ @source inline("data-[selected=true]:text-foreground data-[state=closed]:slide-out-to-bottom");
38
+ @source inline("data-[state=closed]:slide-out-to-left data-[state=closed]:slide-out-to-right");
39
+ @source inline("data-[state=open]:slide-in-from-bottom data-[state=open]:slide-in-from-left");
40
+ @source inline("data-[state=open]:slide-in-from-right data-[state=open]:slide-in-from-top-2");
41
+ @source inline("disabled:hover:scale-100 disabled:opacity-40 focus-within:opacity-100 g grid-cols-4");
42
+ @source inline("group-hover/navitem:opacity-100 group-hover/tile:opacity-100 group/navitem group/tile h-12");
43
+ @source inline("h-[var(--header-h)] h-[var(--header-h-dense)] h-[var(--header-h-roomy)] h-dvh");
44
+ @source inline("hover:border-foreground/20 hover:decoration-border hover:scale-110 hover:underline-offset-4");
45
+ @source inline("inset-x-2 inset-x-3 inset-y-1 inset-y-1.5 items-stretch justify-around leading-4 left-0 left-3");
46
+ @source inline("lg:flex lg:flex-col lg:hidden lg:shrink-0 list-none max-h-72 max-h-[inherit]");
47
+ @source inline("max-h-[var(--palette-max-h)] max-h-[var(--sheet-h-lg)] max-h-[var(--sheet-h-md)]");
48
+ @source inline("max-h-[var(--sheet-h-sm)] max-md:-right-0.5 max-md:-top-0.5 max-md:absolute max-md:hidden");
49
+ @source inline("max-sm:flex-none max-sm:justify-center max-sm:px-0 max-sm:w-10 max-w max-w-48 max-w-64 max-w-80");
50
+ @source inline("max-w-sm md:flex md:flex-col md:gap-4 md:hidden md:pointer-coarse:w-auto md:px-3 md:px-6");
51
+ @source inline("md:shrink-0 min-h-10 min-h-12 min-h-dvh min-w-3.5 min-w-8 min-w-9 mix-blend-difference mt-auto");
52
+ @source inline("mx-1 no-underline opacity-55 opacity-80 pb-[env(safe-area-inset-bottom,0px)] pl-11 pl-9");
53
+ @source inline("place-items-center placeholder:text-muted-foreground pr-3 pr-9 pt-0 pt-1 px-0.5 py-8 right-1");
54
+ @source inline("rotate-180 rounded-l-xl rounded-r-xl rounded-t-xl shadow-lg size-7 size-9 sm:inline");
55
+ @source inline("sm:inline-block sm:inline-flex space-y-0.5 space-y-2 top-[var(--palette-top)] w-52 w-56 w-60");
56
+ @source inline("w-[calc(100%-2rem)] w-[var(--rail-w)] w-[var(--rail-w-collapsed)] w-max");
@@ -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
- * 108 candidate(s).
21
+ * 109 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
@@ -30,7 +30,7 @@
30
30
  @source inline("border-dashed border-l border-r border-solid bottom-6 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");
32
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 disabled:opacity-0 duration-150 flex-row");
33
+ @source inline("data-[state=open]:slide-in-from-right disabled:opacity-0 duration-150 first:pt-1 flex-row");
34
34
  @source inline("group-hover:disabled:opacity-50 h-105 h-40 hover:bg-card-overlay hover:bg-muted-foreground/10");
35
35
  @source inline("hover:bg-muted/80 hover:border-border-strong hover:border-field-ring hover:shadow-popover italic");
36
36
  @source inline("left-0 left-2.5 max-h-[var(--sheet-h-lg)] max-h-[var(--sheet-h-md)] max-h-[var(--sheet-h-sm)]");
@@ -366,6 +366,9 @@
366
366
  .col-span-12 {
367
367
  grid-column: span 12 / span 12;
368
368
  }
369
+ .col-span-full {
370
+ grid-column: 1 / -1;
371
+ }
369
372
  .col-start-2 {
370
373
  grid-column-start: 2;
371
374
  }
@@ -631,6 +634,10 @@
631
634
  width: calc(var(--spacing) * 20);
632
635
  height: calc(var(--spacing) * 20);
633
636
  }
637
+ .size-full {
638
+ width: 100%;
639
+ height: 100%;
640
+ }
634
641
  .h-0\.5 {
635
642
  height: calc(var(--spacing) * 0.5);
636
643
  }
@@ -1171,6 +1178,9 @@
1171
1178
  .shrink-\[2\] {
1172
1179
  flex-shrink: 2;
1173
1180
  }
1181
+ .shrink-\[1000\] {
1182
+ flex-shrink: 1000;
1183
+ }
1174
1184
  .grow {
1175
1185
  flex-grow: 1;
1176
1186
  }
@@ -3422,6 +3432,9 @@
3422
3432
  .\[-webkit-touch-callout\:none\] {
3423
3433
  -webkit-touch-callout: none;
3424
3434
  }
3435
+ .\[background\:var\(--cb-swatch-fill\,var\(--muted\)\)\] {
3436
+ background: var(--cb-swatch-fill,var(--muted));
3437
+ }
3425
3438
  .\[overflow-clip-margin\:calc\(var\(--spacing\)\*1\)\] {
3426
3439
  overflow-clip-margin: calc(var(--spacing) * 1);
3427
3440
  }
@@ -3580,6 +3593,9 @@
3580
3593
  .first\:mt-0:first-child {
3581
3594
  margin-top: 0px;
3582
3595
  }
3596
+ .first\:pt-1:first-child {
3597
+ padding-top: var(--spacing);
3598
+ }
3583
3599
  .first\:pl-1:first-child {
3584
3600
  padding-left: var(--spacing);
3585
3601
  }
@@ -3627,6 +3643,10 @@
3627
3643
  --tw-ring-offset-width: 0px;
3628
3644
  --tw-ring-offset-shadow: var(--tw-ring-inset,) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
3629
3645
  }
3646
+ .focus-within\:ring-offset-1:focus-within {
3647
+ --tw-ring-offset-width: 1px;
3648
+ --tw-ring-offset-shadow: var(--tw-ring-inset,) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
3649
+ }
3630
3650
  @media (hover: hover) {
3631
3651
  .hover\:scale-110:hover {
3632
3652
  --tw-scale-x: 110%;
@@ -4056,6 +4076,17 @@
4056
4076
  .has-\[\[aria-invalid\=true\]\]\:border-field-error:has(:is([aria-invalid=true])) {
4057
4077
  border-color: var(--field-error);
4058
4078
  }
4079
+ .aria-checked\:ring-2[aria-checked="true"] {
4080
+ --tw-ring-shadow: var(--tw-ring-inset,) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color, currentcolor);
4081
+ box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
4082
+ }
4083
+ .aria-checked\:ring-foreground[aria-checked="true"] {
4084
+ --tw-ring-color: var(--foreground);
4085
+ }
4086
+ .aria-checked\:ring-offset-1[aria-checked="true"] {
4087
+ --tw-ring-offset-width: 1px;
4088
+ --tw-ring-offset-shadow: var(--tw-ring-inset,) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
4089
+ }
4059
4090
  .aria-disabled\:pointer-events-none[aria-disabled="true"] {
4060
4091
  pointer-events: none;
4061
4092
  }
package/dist/theme.css CHANGED
@@ -785,26 +785,29 @@
785
785
 
786
786
  .cb-aurora.dark,
787
787
  .dark .cb-aurora {
788
- /* The elevation ladder the "premium dark SaaS" look runs on: never #000 (it
789
- destroys depth), always a hint of indigo, each step lighter than the last —
790
- canvas < panel < card < raised < overlay. Contrast against `--card` is
791
- measured, not guessed: `--muted-foreground` 6.98:1 (AA at metadata sizes),
792
- `--border-strong` 3.29:1 (the WCAG non-text floor for interactive edges),
793
- `--border` 1.59:1 (quiet but traceable — the default theme's is 1.60:1). */
794
- --background: #080b16; /* guardrails-ignore no-hardcoded-colors: this file IS the theme token source of truth — every value here is necessarily a literal color definition */
795
- --foreground: #eef2ff; /* guardrails-ignore no-hardcoded-colors: this file IS the theme token source of truth — every value here is necessarily a literal color definition */
796
- --surface: #0e1424; /* guardrails-ignore no-hardcoded-colors: this file IS the theme token source of truth — every value here is necessarily a literal color definition */
797
- --card: #111830; /* guardrails-ignore no-hardcoded-colors: this file IS the theme token source of truth — every value here is necessarily a literal color definition */
798
- --card-foreground: #eef2ff; /* guardrails-ignore no-hardcoded-colors: this file IS the theme token source of truth — every value here is necessarily a literal color definition */
799
- --card-raised: #161e38; /* guardrails-ignore no-hardcoded-colors: this file IS the theme token source of truth — every value here is necessarily a literal color definition */
800
- --card-overlay: #1d2647; /* guardrails-ignore no-hardcoded-colors: this file IS the theme token source of truth — every value here is necessarily a literal color definition */
801
- --popover: #161e38; /* guardrails-ignore no-hardcoded-colors: this file IS the theme token source of truth — every value here is necessarily a literal color definition */
802
- --popover-foreground: #eef2ff; /* guardrails-ignore no-hardcoded-colors: this file IS the theme token source of truth — every value here is necessarily a literal color definition */
803
- --muted: #1a2238; /* guardrails-ignore no-hardcoded-colors: this file IS the theme token source of truth — every value here is necessarily a literal color definition */
804
- --muted-foreground: #97a3c4; /* guardrails-ignore no-hardcoded-colors: this file IS the theme token source of truth — every value here is necessarily a literal color definition */
805
- --surface-sunken: #070b15; /* guardrails-ignore no-hardcoded-colors: this file IS the theme token source of truth — every value here is necessarily a literal color definition */
806
- --border: #2f3b5c; /* guardrails-ignore no-hardcoded-colors: this file IS the theme token source of truth — every value here is necessarily a literal color definition */
807
- --border-strong: #5f6b82; /* guardrails-ignore no-hardcoded-colors: this file IS the theme token source of truth — every value here is necessarily a literal color definition */
788
+ /* 🔴 NEUTRAL since 5.63.0 — the same ramp as `.dark` above, value for value. 5.58.0 moved
789
+ `.dark` to Linear's ramp so "the chrome recedes and the hues that mean something are the
790
+ only colour on the page", and its report said every app had changed — but ten of the
791
+ eleven apps put `cb-aurora` on <html>, and this block re-bound them straight back to an
792
+ indigo ladder (#080b16 / #111830 / #2f3b5c). Seen on vault-stage, dark, 2026-10-05 (forge
793
+ task 2849): the neutral ramp had reached desk and binary-server and nothing else. The
794
+ scope keeps what makes it aurora — the glass, the ambient field, the lifted shadows —
795
+ and its grounds are the belt's grounds. `themeDarkScopeAliases.spec.ts` holds the pair
796
+ equal, so the two cannot drift apart again. */
797
+ --background: #08090a; /* guardrails-ignore no-hardcoded-colors: this file IS the theme token source of truth — every value here is necessarily a literal color definition */
798
+ --foreground: #f7f8f8; /* guardrails-ignore no-hardcoded-colors: this file IS the theme token source of truth — every value here is necessarily a literal color definition */
799
+ --surface: #101113; /* guardrails-ignore no-hardcoded-colors: this file IS the theme token source of truth — every value here is necessarily a literal color definition */
800
+ --card: #101113; /* guardrails-ignore no-hardcoded-colors: this file IS the theme token source of truth — every value here is necessarily a literal color definition */
801
+ --card-foreground: #f7f8f8; /* guardrails-ignore no-hardcoded-colors: this file IS the theme token source of truth — every value here is necessarily a literal color definition */
802
+ --card-raised: #16171a; /* guardrails-ignore no-hardcoded-colors: this file IS the theme token source of truth — every value here is necessarily a literal color definition */
803
+ --card-overlay: #1d1e22; /* guardrails-ignore no-hardcoded-colors: this file IS the theme token source of truth — every value here is necessarily a literal color definition */
804
+ --popover: #17181b; /* guardrails-ignore no-hardcoded-colors: this file IS the theme token source of truth — every value here is necessarily a literal color definition */
805
+ --popover-foreground: #f7f8f8; /* guardrails-ignore no-hardcoded-colors: this file IS the theme token source of truth — every value here is necessarily a literal color definition */
806
+ --muted: #202126; /* guardrails-ignore no-hardcoded-colors: this file IS the theme token source of truth — every value here is necessarily a literal color definition */
807
+ --muted-foreground: #9b9ea7; /* guardrails-ignore no-hardcoded-colors: this file IS the theme token source of truth — every value here is necessarily a literal color definition */
808
+ --surface-sunken: #0b0c0d; /* guardrails-ignore no-hardcoded-colors: this file IS the theme token source of truth — every value here is necessarily a literal color definition */
809
+ --border: #31333a; /* guardrails-ignore no-hardcoded-colors: this file IS the theme token source of truth — every value here is necessarily a literal color definition */
810
+ --border-strong: #62666f; /* guardrails-ignore no-hardcoded-colors: this file IS the theme token source of truth — every value here is necessarily a literal color definition */
808
811
  --rule: color-mix(in srgb, var(--border) 55%, transparent);
809
812
  /* The "lift the panel off the page" shadow the dark look needs; a near-black
810
813
  canvas swallows the default 1px anchor entirely. */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cursedbelt",
3
- "version": "5.59.0",
3
+ "version": "5.63.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.",
@@ -42,7 +42,8 @@
42
42
  ],
43
43
  "directoryImport": [
44
44
  "./react",
45
- "./react/disk-usage"
45
+ "./react/disk-usage",
46
+ "./react/tree-view"
46
47
  ]
47
48
  },
48
49
  "unpeered": {
@@ -182,6 +183,12 @@
182
183
  "source": "./src/react/components/CodeChip.tsx",
183
184
  "import": "./dist/react/components/CodeChip.js"
184
185
  },
186
+ "./react/color-swatches": {
187
+ "types": "./dist/react/components/ColorSwatches.d.ts",
188
+ "bun": "./src/react/components/ColorSwatches.tsx",
189
+ "source": "./src/react/components/ColorSwatches.tsx",
190
+ "import": "./dist/react/components/ColorSwatches.js"
191
+ },
185
192
  "./react/copy-button": {
186
193
  "types": "./dist/react/components/CopyButton.d.ts",
187
194
  "bun": "./src/react/components/CopyButton.tsx",
@@ -500,6 +507,12 @@
500
507
  "source": "./src/react/components/SelectionBar.tsx",
501
508
  "import": "./dist/react/components/SelectionBar.js"
502
509
  },
510
+ "./react/tree-view": {
511
+ "types": "./dist/react/components/TreeView.d.ts",
512
+ "bun": "./src/react/components/TreeView.tsx",
513
+ "source": "./src/react/components/TreeView.tsx",
514
+ "import": "./dist/react/components/TreeView.js"
515
+ },
503
516
  "./react/unstyled-button": {
504
517
  "types": "./dist/react/components/UnstyledButton.d.ts",
505
518
  "bun": "./src/react/components/UnstyledButton.tsx",
@@ -584,6 +597,12 @@
584
597
  "source": "./src/react/spreadsheet/index.ts",
585
598
  "import": "./dist/react/spreadsheet/index.js"
586
599
  },
600
+ "./react/swatch-picker": {
601
+ "types": "./dist/react/components/SwatchPicker.d.ts",
602
+ "bun": "./src/react/components/SwatchPicker.tsx",
603
+ "source": "./src/react/components/SwatchPicker.tsx",
604
+ "import": "./dist/react/components/SwatchPicker.js"
605
+ },
587
606
  "./react/switch": {
588
607
  "types": "./dist/react/components/Switch.d.ts",
589
608
  "bun": "./src/react/components/Switch.tsx",
@@ -900,8 +919,8 @@
900
919
  "@types/react-dom": "^19.2.3",
901
920
  "@vidstack/react": "1.15.6",
902
921
  "@vitejs/plugin-react": "^5.2.0",
903
- "cursedbelt-server": "^4.40.4",
904
- "cursedops": "^0.13.1",
922
+ "cursedbelt-server": "^4.43.1",
923
+ "cursedops": "^0.15.0",
905
924
  "diff": "^9.0.0",
906
925
  "emoji-mart": "^5.6.0",
907
926
  "hls.js": "^1.5.0",
@@ -966,7 +985,7 @@
966
985
  },
967
986
  "repository": {
968
987
  "type": "git",
969
- "url": "git+https://github.com/curtwphillips/cursedbelt.git"
988
+ "url": "git+https://github.com/wizardmordamir/cursedforge-cursedbelt.git"
970
989
  },
971
990
  "gate": {
972
991
  "stages": [
@@ -22,8 +22,8 @@
22
22
  "no-hand-rolled-surface": 0,
23
23
  "no-inline-style": 73,
24
24
  "no-arbitrary-length": 0,
25
- "opt-out-count": 273,
26
- "opt-out-needs-cause": 256
25
+ "opt-out-count": 272,
26
+ "opt-out-needs-cause": 255
27
27
  },
28
28
  "cursedshell": {
29
29
  "no-raw-action-button": 0,
@@ -254,6 +254,37 @@ describe('no-raw-overflow', () => {
254
254
  `;
255
255
  expect(check('no-raw-overflow', source)).toHaveLength(0);
256
256
  });
257
+
258
+ // forge task 2827: the form kit's plain-CSS scroller is accepted while it is ScrollArea's
259
+ // equal, and is a raw overflow the moment it is not.
260
+ const cssCheck = (source: string) => RULES['no-raw-overflow'].check('formKit.css', source);
261
+ const plainScroll = (body: string, selector = '.cbfk-scroll') => `@layer base {\n\t${selector} {\n${body}\n\t}\n}\n`;
262
+ const CLEARANCE = [
263
+ '\t\toverflow: auto;',
264
+ '\t\toverscroll-behavior: contain;',
265
+ '\t\tscroll-padding-bottom: calc(var(--keyboard-inset, 0px) + 1rem);',
266
+ ];
267
+
268
+ test('accepts the .cbfk-scroll rule that carries the keyboard clearance', () => {
269
+ expect(cssCheck(plainScroll(CLEARANCE.join('\n')))).toHaveLength(0);
270
+ });
271
+
272
+ test('flags .cbfk-scroll once its keyboard scroll padding is gone', () => {
273
+ expect(cssCheck(plainScroll(CLEARANCE.filter((l) => !l.includes('scroll-padding')).join('\n')))).toHaveLength(1);
274
+ });
275
+
276
+ test('flags .cbfk-scroll without overscroll containment', () => {
277
+ expect(cssCheck(plainScroll(CLEARANCE.filter((l) => !l.includes('overscroll')).join('\n')))).toHaveLength(1);
278
+ });
279
+
280
+ test('flags another selector that copies the clearance instead of taking the class', () => {
281
+ expect(cssCheck(plainScroll(CLEARANCE.join('\n'), '.cbfk-page-form'))).toHaveLength(1);
282
+ expect(cssCheck(plainScroll(CLEARANCE.join('\n'), '.cbfk-scroll-y'))).toHaveLength(1);
283
+ });
284
+
285
+ test('accepts it only in a stylesheet', () => {
286
+ expect(check('no-raw-overflow', plainScroll(CLEARANCE.join('\n')))).toHaveLength(1);
287
+ });
257
288
  });
258
289
 
259
290
  describe('no-raw-inputs', () => {
@@ -821,7 +821,12 @@ const rawButtonResetsFace: Rule = {
821
821
  * offending value, an opt-out comment recognized on the match's own line or either of
822
822
  * the two lines immediately above it (covers both an inline trailing comment and a
823
823
  * comment placed on its own line before the offending statement). */
824
- function makeValueRule(name: string, description: string, valueRe: RegExp): Rule {
824
+ function makeValueRule(
825
+ name: string,
826
+ description: string,
827
+ valueRe: RegExp,
828
+ accepts?: (filePath: string, scannable: string, index: number) => boolean,
829
+ ): Rule {
825
830
  const ignoreRe = new RegExp(`guardrails-ignore\\s+${name}\\s*:`);
826
831
  return {
827
832
  name,
@@ -837,6 +842,7 @@ function makeValueRule(name: string, description: string, valueRe: RegExp): Rule
837
842
  const windowStart = Math.max(0, line - 3);
838
843
  const context = lines.slice(windowStart, line).join("\n");
839
844
  if (ignoreRe.test(context)) continue;
845
+ if (accepts?.(filePath, scannable, match.index ?? 0)) continue;
840
846
  violations.push({
841
847
  file: filePath,
842
848
  line,
@@ -851,10 +857,39 @@ function makeValueRule(name: string, description: string, valueRe: RegExp): Rule
851
857
  const OVERFLOW_VALUE_RE =
852
858
  /overflow(?:-?[xy])?\s*:\s*['"`]?\s*(?:auto|scroll)\b|\boverflow(?:-[xy])?-(?:auto|scroll)\b/gi;
853
859
 
860
+ // The form kit's plain-CSS scroller (forge task 2827). `ScrollArea` draws with Tailwind
861
+ // utilities, so a host with no Tailwind (desk) cannot use it; `.cbfk-scroll` in
862
+ // `src/react/components/scrollRegion.css` is the same scroller as one plain rule, and a box that
863
+ // scrolls takes that class instead of writing `overflow` itself. Its own `overflow: auto` is
864
+ // accepted — the way `raw-button-resets-face` accepts `RAW_BUTTON` — but only while the rule
865
+ // still carries what ScrollArea carries: the `--keyboard-inset` scroll padding that keeps a
866
+ // focused field above a phone's keyboard, and `overscroll-behavior: contain`. Strip either and
867
+ // it is a raw overflow again. Exactly the one selector: a second class copying the three lines
868
+ // is the drift this replaced (two boxes, each with its own opt-out).
869
+ const PLAIN_SCROLL_CLASS = "cbfk-scroll";
870
+ const PLAIN_SCROLL_RULE_RE = new RegExp(`(^|[}\\s;])\\.${PLAIN_SCROLL_CLASS}\\s*\\{([^{}]*)\\}`, "g");
871
+
872
+ function insidePlainScrollRule(filePath: string, scannable: string, index: number): boolean {
873
+ if (!filePath.endsWith(".css")) return false;
874
+ PLAIN_SCROLL_RULE_RE.lastIndex = 0;
875
+ for (const m of scannable.matchAll(PLAIN_SCROLL_RULE_RE)) {
876
+ const bodyStart = (m.index ?? 0) + m[0].indexOf("{");
877
+ const bodyEnd = (m.index ?? 0) + m[0].length;
878
+ if (index < bodyStart || index > bodyEnd) continue;
879
+ const body = m[2] ?? "";
880
+ return (
881
+ /overscroll-behavior\s*:\s*contain\b/.test(body) &&
882
+ /scroll-padding-bottom\s*:[^;]*var\(\s*--keyboard-inset\b/.test(body)
883
+ );
884
+ }
885
+ return false;
886
+ }
887
+
854
888
  const noRawOverflow: Rule = makeValueRule(
855
889
  "no-raw-overflow",
856
- "STANDARDS.md §4: no hand-written overflow:auto|scroll (inline style or Tailwind utility) — use the cursedbelt ScrollArea primitive.",
890
+ "STANDARDS.md §4: no hand-written overflow:auto|scroll (inline style or Tailwind utility) — use the cursedbelt ScrollArea primitive (or, in a plain stylesheet, the form kit's .cbfk-scroll).",
857
891
  OVERFLOW_VALUE_RE,
892
+ insidePlainScrollRule,
858
893
  );
859
894
 
860
895
  // ── 🔴 The `sr-only` input: refused outright, whatever the opt-out ───────────────
@@ -253,6 +253,7 @@ export const AREAS: readonly Area[] = [
253
253
  'components/CodeChip.tsx',
254
254
  'components/CodeFieldInput.tsx',
255
255
  'components/ColorField.tsx',
256
+ 'components/ColorSwatches.tsx',
256
257
  'components/ComboboxField.tsx',
257
258
  // The control-studio parameter panel and the shared label column (forge task 2463).
258
259
  'components/ControlPanel.tsx',