@seekalfred/primitives 0.5.1 → 0.6.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 (215) hide show
  1. package/README.md +664 -9
  2. package/dist/accordion/accordion.js +10 -4
  3. package/dist/accordion/accordion.js.map +1 -1
  4. package/dist/action-button/action-button.d.ts +50 -0
  5. package/dist/action-button/action-button.js +159 -0
  6. package/dist/action-button/action-button.js.map +1 -0
  7. package/dist/action-button/index.d.ts +2 -0
  8. package/dist/action-button/index.js +2 -0
  9. package/dist/alert/alert.d.ts +15 -1
  10. package/dist/alert/alert.js +116 -20
  11. package/dist/alert/alert.js.map +1 -1
  12. package/dist/avatar/avatar.d.ts +6 -0
  13. package/dist/avatar/avatar.js +47 -16
  14. package/dist/avatar/avatar.js.map +1 -1
  15. package/dist/badge/badge.d.ts +11 -4
  16. package/dist/badge/badge.js +35 -5
  17. package/dist/badge/badge.js.map +1 -1
  18. package/dist/breadcrumb/breadcrumb.d.ts +0 -27
  19. package/dist/breadcrumb/breadcrumb.js +20 -6
  20. package/dist/breadcrumb/breadcrumb.js.map +1 -1
  21. package/dist/button/button.d.ts +35 -22
  22. package/dist/button/button.js +177 -34
  23. package/dist/button/button.js.map +1 -1
  24. package/dist/button-group/button-group.d.ts +76 -0
  25. package/dist/button-group/button-group.js +403 -0
  26. package/dist/button-group/button-group.js.map +1 -0
  27. package/dist/button-group/index.d.ts +2 -0
  28. package/dist/button-group/index.js +2 -0
  29. package/dist/calendar/calendar.d.ts +1 -1
  30. package/dist/calendar/calendar.js +257 -30
  31. package/dist/calendar/calendar.js.map +1 -1
  32. package/dist/card/card.d.ts +9 -2
  33. package/dist/card/card.js +15 -4
  34. package/dist/card/card.js.map +1 -1
  35. package/dist/checkbox/checkbox.d.ts +0 -7
  36. package/dist/checkbox/checkbox.js +24 -27
  37. package/dist/checkbox/checkbox.js.map +1 -1
  38. package/dist/confirm-morph/confirm-morph.d.ts +85 -0
  39. package/dist/confirm-morph/confirm-morph.js +652 -0
  40. package/dist/confirm-morph/confirm-morph.js.map +1 -0
  41. package/dist/confirm-morph/index.d.ts +2 -0
  42. package/dist/confirm-morph/index.js +2 -0
  43. package/dist/copy-button/copy-button.d.ts +32 -0
  44. package/dist/copy-button/copy-button.js +134 -0
  45. package/dist/copy-button/copy-button.js.map +1 -0
  46. package/dist/copy-button/index.d.ts +2 -0
  47. package/dist/copy-button/index.js +2 -0
  48. package/dist/date-picker/date-picker.d.ts +51 -0
  49. package/dist/date-picker/date-picker.js +241 -0
  50. package/dist/date-picker/date-picker.js.map +1 -0
  51. package/dist/date-picker/date-range-picker.d.ts +78 -0
  52. package/dist/date-picker/date-range-picker.js +1015 -0
  53. package/dist/date-picker/date-range-picker.js.map +1 -0
  54. package/dist/date-picker/index.d.ts +4 -0
  55. package/dist/date-picker/index.js +4 -0
  56. package/dist/date-picker/picker-parts.d.ts +46 -0
  57. package/dist/date-picker/picker-parts.js +135 -0
  58. package/dist/date-picker/picker-parts.js.map +1 -0
  59. package/dist/dialog/dialog.d.ts +10 -14
  60. package/dist/dialog/dialog.js +39 -11
  61. package/dist/dialog/dialog.js.map +1 -1
  62. package/dist/empty-state/empty-state.d.ts +44 -0
  63. package/dist/empty-state/empty-state.js +83 -0
  64. package/dist/empty-state/empty-state.js.map +1 -0
  65. package/dist/empty-state/index.d.ts +2 -0
  66. package/dist/empty-state/index.js +2 -0
  67. package/dist/expanding-button-group/expanding-button-group.d.ts +54 -0
  68. package/dist/expanding-button-group/expanding-button-group.js +350 -0
  69. package/dist/expanding-button-group/expanding-button-group.js.map +1 -0
  70. package/dist/expanding-button-group/index.d.ts +2 -0
  71. package/dist/expanding-button-group/index.js +2 -0
  72. package/dist/file-drop-zone/file-drop-zone.d.ts +71 -0
  73. package/dist/file-drop-zone/file-drop-zone.js +116 -0
  74. package/dist/file-drop-zone/file-drop-zone.js.map +1 -0
  75. package/dist/file-drop-zone/index.d.ts +2 -0
  76. package/dist/file-drop-zone/index.js +2 -0
  77. package/dist/filter-bar/filter-bar.d.ts +121 -0
  78. package/dist/filter-bar/filter-bar.js +300 -0
  79. package/dist/filter-bar/filter-bar.js.map +1 -0
  80. package/dist/filter-bar/index.d.ts +2 -0
  81. package/dist/filter-bar/index.js +2 -0
  82. package/dist/floating-button-group/floating-button-group.d.ts +61 -0
  83. package/dist/floating-button-group/floating-button-group.js +340 -0
  84. package/dist/floating-button-group/floating-button-group.js.map +1 -0
  85. package/dist/floating-button-group/index.d.ts +2 -0
  86. package/dist/floating-button-group/index.js +2 -0
  87. package/dist/icon-morph/icon-morph.d.ts +55 -0
  88. package/dist/icon-morph/icon-morph.js +331 -0
  89. package/dist/icon-morph/icon-morph.js.map +1 -0
  90. package/dist/icon-morph/index.d.ts +2 -0
  91. package/dist/icon-morph/index.js +2 -0
  92. package/dist/index.d.ts +24 -2
  93. package/dist/index.js +29 -7
  94. package/dist/input/input.d.ts +22 -0
  95. package/dist/input/input.js +36 -12
  96. package/dist/input/input.js.map +1 -1
  97. package/dist/lib/count-to.js +113 -0
  98. package/dist/lib/count-to.js.map +1 -0
  99. package/dist/lib/eye-morph.js +62 -0
  100. package/dist/lib/eye-morph.js.map +1 -0
  101. package/dist/lib/field-message.js +336 -0
  102. package/dist/lib/field-message.js.map +1 -0
  103. package/dist/lib/field-shell.js +81 -0
  104. package/dist/lib/field-shell.js.map +1 -0
  105. package/dist/lib/field-surface.js +4 -2
  106. package/dist/lib/field-surface.js.map +1 -1
  107. package/dist/lib/flip.js +80 -0
  108. package/dist/lib/flip.js.map +1 -0
  109. package/dist/lib/height-follow.js +59 -0
  110. package/dist/lib/height-follow.js.map +1 -0
  111. package/dist/lib/icon-swap.js +47 -0
  112. package/dist/lib/icon-swap.js.map +1 -0
  113. package/dist/lib/leaving-list.js +57 -0
  114. package/dist/lib/leaving-list.js.map +1 -0
  115. package/dist/lib/merge-refs.js +3 -3
  116. package/dist/lib/merge-refs.js.map +1 -1
  117. package/dist/lib/morph-text.js +128 -0
  118. package/dist/lib/morph-text.js.map +1 -0
  119. package/dist/lib/motion.js +162 -0
  120. package/dist/lib/motion.js.map +1 -0
  121. package/dist/lib/pausable-timeout.js +67 -0
  122. package/dist/lib/pausable-timeout.js.map +1 -0
  123. package/dist/lib/rolling-value.js +31 -0
  124. package/dist/lib/rolling-value.js.map +1 -0
  125. package/dist/lib/spring-progress.js +114 -0
  126. package/dist/lib/spring-progress.js.map +1 -0
  127. package/dist/lib/svg-id.js +10 -0
  128. package/dist/lib/svg-id.js.map +1 -0
  129. package/dist/lib/swap-text.js +77 -0
  130. package/dist/lib/swap-text.js.map +1 -0
  131. package/dist/lib/use-copy-feedback.js +36 -0
  132. package/dist/lib/use-copy-feedback.js.map +1 -0
  133. package/dist/page-header/index.d.ts +2 -0
  134. package/dist/page-header/index.js +2 -0
  135. package/dist/page-header/page-header.d.ts +75 -0
  136. package/dist/page-header/page-header.js +83 -0
  137. package/dist/page-header/page-header.js.map +1 -0
  138. package/dist/password-field/index.d.ts +2 -0
  139. package/dist/password-field/index.js +2 -0
  140. package/dist/password-field/password-field.d.ts +37 -0
  141. package/dist/password-field/password-field.js +101 -0
  142. package/dist/password-field/password-field.js.map +1 -0
  143. package/dist/password-strength/index.d.ts +2 -0
  144. package/dist/password-strength/index.js +2 -0
  145. package/dist/password-strength/password-strength.d.ts +127 -0
  146. package/dist/password-strength/password-strength.js +455 -0
  147. package/dist/password-strength/password-strength.js.map +1 -0
  148. package/dist/popover/popover.d.ts +8 -0
  149. package/dist/popover/popover.js +3 -3
  150. package/dist/popover/popover.js.map +1 -1
  151. package/dist/progress/progress.js +46 -5
  152. package/dist/progress/progress.js.map +1 -1
  153. package/dist/radio-group/radio-group.js +7 -6
  154. package/dist/radio-group/radio-group.js.map +1 -1
  155. package/dist/scroll-area/scroll-area.d.ts +10 -0
  156. package/dist/scroll-area/scroll-area.js +25 -3
  157. package/dist/scroll-area/scroll-area.js.map +1 -1
  158. package/dist/search-field/index.d.ts +2 -0
  159. package/dist/search-field/index.js +2 -0
  160. package/dist/search-field/search-field.d.ts +26 -0
  161. package/dist/search-field/search-field.js +155 -0
  162. package/dist/search-field/search-field.js.map +1 -0
  163. package/dist/select/select.js +79 -21
  164. package/dist/select/select.js.map +1 -1
  165. package/dist/sheet/sheet.js +2 -1
  166. package/dist/sheet/sheet.js.map +1 -1
  167. package/dist/side-nav/index.d.ts +2 -0
  168. package/dist/side-nav/index.js +2 -0
  169. package/dist/side-nav/side-nav.d.ts +72 -0
  170. package/dist/side-nav/side-nav.js +142 -0
  171. package/dist/side-nav/side-nav.js.map +1 -0
  172. package/dist/skeleton/skeleton.d.ts +8 -2
  173. package/dist/skeleton/skeleton.js +6 -2
  174. package/dist/skeleton/skeleton.js.map +1 -1
  175. package/dist/slider/slider.js +61 -7
  176. package/dist/slider/slider.js.map +1 -1
  177. package/dist/split-button/index.d.ts +2 -0
  178. package/dist/split-button/index.js +2 -0
  179. package/dist/split-button/split-button.d.ts +46 -0
  180. package/dist/split-button/split-button.js +122 -0
  181. package/dist/split-button/split-button.js.map +1 -0
  182. package/dist/stat-card/index.d.ts +2 -0
  183. package/dist/stat-card/index.js +2 -0
  184. package/dist/stat-card/stat-card.d.ts +81 -0
  185. package/dist/stat-card/stat-card.js +152 -0
  186. package/dist/stat-card/stat-card.js.map +1 -0
  187. package/dist/styles.css +1 -1
  188. package/dist/switch/switch.js +9 -8
  189. package/dist/switch/switch.js.map +1 -1
  190. package/dist/table/index.d.ts +2 -2
  191. package/dist/table/index.js +2 -2
  192. package/dist/table/table.d.ts +36 -5
  193. package/dist/table/table.js +112 -11
  194. package/dist/table/table.js.map +1 -1
  195. package/dist/tabs/tabs.js +142 -6
  196. package/dist/tabs/tabs.js.map +1 -1
  197. package/dist/textarea/textarea.d.ts +23 -0
  198. package/dist/textarea/textarea.js +24 -2
  199. package/dist/textarea/textarea.js.map +1 -1
  200. package/dist/theme-switch/index.d.ts +2 -0
  201. package/dist/theme-switch/index.js +2 -0
  202. package/dist/theme-switch/theme-switch.d.ts +37 -0
  203. package/dist/theme-switch/theme-switch.js +123 -0
  204. package/dist/theme-switch/theme-switch.js.map +1 -0
  205. package/dist/time-picker/index.d.ts +2 -0
  206. package/dist/time-picker/index.js +2 -0
  207. package/dist/time-picker/time-picker.d.ts +54 -0
  208. package/dist/time-picker/time-picker.js +201 -0
  209. package/dist/time-picker/time-picker.js.map +1 -0
  210. package/dist/toast/toast.js +58 -38
  211. package/dist/toast/toast.js.map +1 -1
  212. package/dist/tooltip/tooltip.d.ts +1 -1
  213. package/dist/tooltip/tooltip.js +63 -14
  214. package/dist/tooltip/tooltip.js.map +1 -1
  215. package/package.json +83 -3
@@ -4,7 +4,7 @@ import { selectionLabelVariants, selectionRingVariants } from "../lib/selection-
4
4
  import { cva } from "class-variance-authority";
5
5
  import { forwardRef } from "react";
6
6
  import { Checkbox } from "react-aria-components";
7
- import { Fragment, jsx, jsxs } from "react/jsx-runtime";
7
+ import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
8
8
  //#region src/checkbox/checkbox.tsx
9
9
  /**
10
10
  * Checkbox, rebuilt on React Aria.
@@ -46,12 +46,11 @@ const checkboxBoxVariants = cva([
46
46
  "inline-flex size-4 shrink-0 items-center justify-center",
47
47
  "rounded-2xs border-(length:--border-width)",
48
48
  "box-border",
49
- "bg-background border-border",
50
- "motion-safe:transition-colors motion-safe:duration-(--duration-fast) motion-safe:ease-standard",
51
- "group-data-[selected]:bg-primary group-data-[selected]:border-primary-strong",
52
- "group-data-[selected]:text-primary-foreground",
53
- "group-data-[indeterminate]:bg-primary group-data-[indeterminate]:border-primary-strong",
54
- "group-data-[indeterminate]:text-primary-foreground",
49
+ "bg-background border-border text-primary-foreground",
50
+ "checkbox-box",
51
+ "group-data-[selected]:border-primary-strong",
52
+ "group-data-[indeterminate]:border-primary-strong",
53
+ "group-data-[hovered]:not-group-data-[selected]:not-group-data-[indeterminate]:border-muted-foreground",
55
54
  selectionRingVariants()
56
55
  ]);
57
56
  const Checkbox$1 = forwardRef(function Checkbox$2({ className, children, ...props }, ref) {
@@ -60,30 +59,28 @@ const Checkbox$1 = forwardRef(function Checkbox$2({ className, children, ...prop
60
59
  inputRef: ref,
61
60
  "data-slot": "checkbox",
62
61
  className: cn(checkboxVariants(), className),
63
- children: ({ isSelected, isIndeterminate }) => /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("span", {
62
+ children: ({ isSelected, isIndeterminate }) => /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsxs("span", {
64
63
  "aria-hidden": "true",
65
64
  "data-slot": "checkbox-box",
66
65
  className: checkboxBoxVariants(),
67
- children: isIndeterminate ? /* @__PURE__ */ jsx("svg", {
68
- "data-slot": "checkbox-indeterminate",
69
- viewBox: "0 0 16 16",
66
+ children: [/* @__PURE__ */ jsx("span", {
67
+ "data-slot": "checkbox-fill",
68
+ className: "checkbox-fill"
69
+ }), /* @__PURE__ */ jsx("svg", {
70
+ "data-slot": "checkbox-mark",
71
+ "data-mark": isIndeterminate ? "indeterminate" : isSelected ? "check" : void 0,
72
+ viewBox: "0 0 18 18",
70
73
  fill: "none",
71
- stroke: "currentColor",
72
- strokeWidth: "2.5",
73
- strokeLinecap: "round",
74
- className: "size-3",
75
- children: /* @__PURE__ */ jsx("path", { d: "M4 8h8" })
76
- }) : isSelected ? /* @__PURE__ */ jsx("svg", {
77
- "data-slot": "checkbox-check",
78
- viewBox: "0 0 16 16",
79
- fill: "none",
80
- stroke: "currentColor",
81
- strokeWidth: "2.5",
82
- strokeLinecap: "round",
83
- strokeLinejoin: "round",
84
- className: "size-3",
85
- children: /* @__PURE__ */ jsx("path", { d: "m3.5 8.5 3 3 6-6" })
86
- }) : null
74
+ className: "absolute -inset-px size-4 overflow-visible",
75
+ children: /* @__PURE__ */ jsx("path", {
76
+ className: "checkbox-mark",
77
+ pathLength: "1",
78
+ stroke: "currentColor",
79
+ strokeWidth: "2",
80
+ strokeLinecap: "round",
81
+ strokeLinejoin: "round"
82
+ })
83
+ })]
87
84
  }), children == null ? null : /* @__PURE__ */ jsx("span", {
88
85
  "data-slot": "checkbox-label",
89
86
  children
@@ -1 +1 @@
1
- {"version":3,"file":"checkbox.js","names":["Checkbox","AriaCheckbox"],"sources":["../../src/checkbox/checkbox.tsx"],"sourcesContent":["\"use client\";\n\nimport { cva } from \"class-variance-authority\";\nimport { forwardRef, type ReactNode } from \"react\";\nimport {\n Checkbox as AriaCheckbox,\n type CheckboxProps as AriaCheckboxProps,\n} from \"react-aria-components\";\n\nimport { cn } from \"../lib/cn.js\";\nimport { selectionLabelVariants, selectionRingVariants } from \"../lib/selection-control.js\";\n\n/**\n * Checkbox, rebuilt on React Aria.\n *\n * THE CENSUS FOUND ZERO CALL SITES. It is ported anyway because forms and\n * table row selection are unbuildable without it, but that fact changes what\n * this is: with no usage to be faithful to and no call site to break, it is a\n * rewrite rather than a restyling. Four things the legacy component got\n * wrong are therefore simply fixed rather than carried:\n *\n * - **No accessible name.** It rendered a bare `<input type=\"checkbox\">` with\n * no label, no `aria-label` and no `id`, so every use was an axe `label`\n * violation. Here the label is `children`, and React Aria wraps the input\n * in it.\n * - **The fill never showed.** `checked:bg-primary` on a native input with no\n * `appearance-none` is painted over by the user-agent checkbox.\n * - **`border-primary` cannot be a boundary.** Brand orange is 2.44:1 on\n * white, under even the 3:1 non-text floor (WCAG 1.4.11).\n * - **`focus-visible:ring-2` is a box-shadow**, which forced-colors discards,\n * taking the only focus indication with it.\n *\n * React Aria renders a `<label>` around a visually-hidden real `<input>` and\n * NOTHING else -- there is no visual box in the box. Drawing one, and keeping\n * it in step with `data-selected` / `data-indeterminate`, is what this\n * component owns.\n *\n * Every string in the cva blocks below is a STATIC literal. Tailwind scans\n * source text, so a class assembled at runtime is invisible to it and would\n * simply never be emitted.\n */\n/**\n * The label geometry now lives in lib/selection-control.ts, shared with\n * Radio and Switch. Three controls with the same 24px target and the same\n * typography is the Rule of Three, and this migration has twice found a\n * legacy pair that styled one surface twice and silently drifted.\n */\nexport const checkboxVariants = cva([selectionLabelVariants()]);\n\nexport const checkboxBoxVariants = cva([\n \"inline-flex size-4 shrink-0 items-center justify-center\",\n // rounded-2xs, not rounded-sm. --radius-sm is 8px, which on a 16px box\n // is exactly half its width -- a circle, indistinguishable from a radio\n // button. A screenshot caught that; no assertion in this suite did, which\n // is why NotACircle now exists. --radius-xs (6px) is still 75% of the way\n // there, so the scale gained a 4px step rather than this reaching for a\n // bracket value that check:hardcoding would rightly reject.\n \"rounded-2xs border-(length:--border-width)\",\n\n // box-border: content-box would add the border to the 16px box and make it\n // 18, which is the same opt-in-reset exposure as everywhere else.\n \"box-border\",\n\n // Unselected: a neutral boundary, NOT the legacy border-primary. Brand\n // orange is 2.44:1 on white and cannot legally be the only thing describing\n // a control's edge.\n \"bg-background border-border\",\n\n \"motion-safe:transition-colors motion-safe:duration-(--duration-fast) motion-safe:ease-standard\",\n\n // Selected and indeterminate paint the same: both mean \"this control has a\n // value\", and the glyph inside says which.\n //\n // primary-strong on the border, not primary: a filled orange box is 2.44:1\n // against the page, so the FILL cannot satisfy 1.4.11 and the boundary has\n // to. Same reasoning, and the same token, as the Button's outline variant.\n \"group-data-[selected]:bg-primary group-data-[selected]:border-primary-strong\",\n \"group-data-[selected]:text-primary-foreground\",\n \"group-data-[indeterminate]:bg-primary group-data-[indeterminate]:border-primary-strong\",\n \"group-data-[indeterminate]:text-primary-foreground\",\n\n // Shared with Radio and Switch. The ring goes on the BOX rather than the\n // input, because React Aria's input is visually hidden.\n selectionRingVariants(),\n]);\n\n/**\n * A checkbox.\n *\n * @example\n * <Checkbox defaultSelected>Email me about new courses</Checkbox>\n * <Checkbox aria-label=\"Select row\" />\n */\nexport interface CheckboxProps\n extends Omit<AriaCheckboxProps, \"className\" | \"style\" | \"children\"> {\n /**\n * The label, and the control's accessible name.\n *\n * Omit it only for a genuinely label-less checkbox -- a table row selector\n * -- and pass `aria-label` instead. A checkbox with neither has no\n * accessible name, which is what every legacy call site would have been.\n */\n children?: ReactNode;\n /** Extra classes for the label. Merged last, so they win conflicts. */\n className?: string;\n}\n\nexport const Checkbox = forwardRef<HTMLInputElement, CheckboxProps>(function Checkbox(\n { className, children, ...props },\n ref,\n) {\n return (\n <AriaCheckbox\n {...props}\n // inputRef, not ref: AriaCheckbox's own ref targets the label it\n // renders around a visually-hidden native input, and a label cannot\n // be focused -- ref.current.focus() would silently no-op. inputRef is\n // React Aria's own escape hatch to the real control.\n inputRef={ref}\n data-slot=\"checkbox\"\n // `group` is load-bearing: React Aria puts data-selected,\n // data-indeterminate and data-focus-visible on the LABEL, and CSS\n // cannot look upward from the box to them.\n className={cn(checkboxVariants(), className)}\n >\n {({ isSelected, isIndeterminate }) => (\n <>\n {/*\n aria-hidden: the real <input> already carries the state. A\n decorative box announced as well would say everything twice.\n */}\n <span aria-hidden=\"true\" data-slot=\"checkbox-box\" className={checkboxBoxVariants()}>\n {/*\n Chosen in JS rather than toggled with CSS. Two rules that both\n apply -- show-when-selected and hide-when-indeterminate -- have\n equal specificity, so which wins comes down to the order\n Tailwind happened to emit them in. Rendering one glyph makes\n the precedence explicit and puts it in the DOM, where a test\n can read it.\n\n Indeterminate wins: both states can be true at once (a \"select\n all\" box that has been partially cleared), and a tick there\n would say the opposite of the aria-checked=\"mixed\" beside it.\n */}\n {isIndeterminate ? (\n <svg\n data-slot=\"checkbox-indeterminate\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n strokeLinecap=\"round\"\n className=\"size-3\"\n >\n <path d=\"M4 8h8\" />\n </svg>\n ) : isSelected ? (\n <svg\n data-slot=\"checkbox-check\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className=\"size-3\"\n >\n <path d=\"m3.5 8.5 3 3 6-6\" />\n </svg>\n ) : null}\n </span>\n {children == null ? null : <span data-slot=\"checkbox-label\">{children}</span>}\n </>\n )}\n </AriaCheckbox>\n );\n});\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+CA,MAAa,mBAAmB,IAAI,CAAC,uBAAuB,CAAC,CAAC;AAE9D,MAAa,sBAAsB,IAAI;CACrC;CAOA;CAIA;CAKA;CAEA;CAQA;CACA;CACA;CACA;CAIA,sBAAsB;AACxB,CAAC;AAuBD,MAAaA,aAAW,WAA4C,SAASA,WAC3E,EAAE,WAAW,UAAU,GAAG,SAC1B,KACA;CACA,OACE,oBAACC,UAAD;EACE,GAAI;EAKJ,UAAU;EACV,aAAU;EAIV,WAAW,GAAG,iBAAiB,GAAG,SAAS;EAEzC,WAAA,EAAE,YAAY,sBACd,qBAAA,UAAA,EAAA,UAAA,CAKE,oBAAC,QAAD;GAAM,eAAY;GAAO,aAAU;GAAe,WAAW,oBAAoB;GAa9E,UAAA,kBACC,oBAAC,OAAD;IACE,aAAU;IACV,SAAQ;IACR,MAAK;IACL,QAAO;IACP,aAAY;IACZ,eAAc;IACd,WAAU;IAEV,UAAA,oBAAC,QAAD,EAAM,GAAE,SAAU,CAAA;GACf,CAAA,IACH,aACF,oBAAC,OAAD;IACE,aAAU;IACV,SAAQ;IACR,MAAK;IACL,QAAO;IACP,aAAY;IACZ,eAAc;IACd,gBAAe;IACf,WAAU;IAEV,UAAA,oBAAC,QAAD,EAAM,GAAE,mBAAoB,CAAA;GACzB,CAAA,IACH;EACA,CAAA,GACL,YAAY,OAAO,OAAO,oBAAC,QAAD;GAAM,aAAU;GAAkB;EAAe,CAAA,CAC5E,EAAA,CAAA;CAEQ,CAAA;AAElB,CAAC"}
1
+ {"version":3,"file":"checkbox.js","names":["Checkbox","AriaCheckbox"],"sources":["../../src/checkbox/checkbox.tsx"],"sourcesContent":["\"use client\";\n\nimport { cva } from \"class-variance-authority\";\nimport { forwardRef, type ReactNode } from \"react\";\nimport {\n Checkbox as AriaCheckbox,\n type CheckboxProps as AriaCheckboxProps,\n} from \"react-aria-components\";\n\nimport { cn } from \"../lib/cn.js\";\nimport { selectionLabelVariants, selectionRingVariants } from \"../lib/selection-control.js\";\n\n/**\n * Checkbox, rebuilt on React Aria.\n *\n * THE CENSUS FOUND ZERO CALL SITES. It is ported anyway because forms and\n * table row selection are unbuildable without it, but that fact changes what\n * this is: with no usage to be faithful to and no call site to break, it is a\n * rewrite rather than a restyling. Four things the legacy component got\n * wrong are therefore simply fixed rather than carried:\n *\n * - **No accessible name.** It rendered a bare `<input type=\"checkbox\">` with\n * no label, no `aria-label` and no `id`, so every use was an axe `label`\n * violation. Here the label is `children`, and React Aria wraps the input\n * in it.\n * - **The fill never showed.** `checked:bg-primary` on a native input with no\n * `appearance-none` is painted over by the user-agent checkbox.\n * - **`border-primary` cannot be a boundary.** Brand orange is 2.44:1 on\n * white, under even the 3:1 non-text floor (WCAG 1.4.11).\n * - **`focus-visible:ring-2` is a box-shadow**, which forced-colors discards,\n * taking the only focus indication with it.\n *\n * React Aria renders a `<label>` around a visually-hidden real `<input>` and\n * NOTHING else -- there is no visual box in the box. Drawing one, and keeping\n * it in step with `data-selected` / `data-indeterminate`, is what this\n * component owns.\n *\n * Every string in the cva blocks below is a STATIC literal. Tailwind scans\n * source text, so a class assembled at runtime is invisible to it and would\n * simply never be emitted.\n */\n/**\n * The label geometry now lives in lib/selection-control.ts, shared with\n * Radio and Switch. Three controls with the same 24px target and the same\n * typography is the Rule of Three, and this migration has twice found a\n * legacy pair that styled one surface twice and silently drifted.\n */\nexport const checkboxVariants = cva([selectionLabelVariants()]);\n\nexport const checkboxBoxVariants = cva([\n \"inline-flex size-4 shrink-0 items-center justify-center\",\n \"rounded-2xs border-(length:--border-width)\",\n\n // box-border: the size is the whole square, border included.\n \"box-border\",\n\n \"bg-background border-border text-primary-foreground\",\n\n // Border colour eases, the square presses to .95 and springs back (see checkbox-box).\n \"checkbox-box\",\n\n // The border takes the strong tone once chosen; the colour itself is the fill below.\n \"group-data-[selected]:border-primary-strong\",\n \"group-data-[indeterminate]:border-primary-strong\",\n // Hover darkens an unchosen box's border.\n \"group-data-[hovered]:not-group-data-[selected]:not-group-data-[indeterminate]:border-muted-foreground\",\n\n selectionRingVariants(),\n]);\n\nexport interface CheckboxProps\n extends Omit<AriaCheckboxProps, \"className\" | \"style\" | \"children\"> {\n /**\n * The label, and the control's accessible name.\n *\n * Omit it only for a genuinely label-less checkbox -- a table row selector\n * -- and pass `aria-label` instead. A checkbox with neither has no\n * accessible name, which is what every legacy call site would have been.\n */\n children?: ReactNode;\n /** Extra classes for the label. Merged last, so they win conflicts. */\n className?: string;\n}\n\nexport const Checkbox = forwardRef<HTMLInputElement, CheckboxProps>(function Checkbox(\n { className, children, ...props },\n ref,\n) {\n return (\n <AriaCheckbox\n {...props}\n // inputRef, not ref: AriaCheckbox's own ref targets the label it\n // renders around a visually-hidden native input, and a label cannot\n // be focused -- ref.current.focus() would silently no-op. inputRef is\n // React Aria's own escape hatch to the real control.\n inputRef={ref}\n data-slot=\"checkbox\"\n // `group` is load-bearing: React Aria puts data-selected,\n // data-indeterminate and data-focus-visible on the LABEL, and CSS\n // cannot look upward from the box to them.\n className={cn(checkboxVariants(), className)}\n >\n {({ isSelected, isIndeterminate }) => (\n <>\n {/*\n aria-hidden: the real <input> already carries the state. A\n decorative box announced as well would say everything twice.\n */}\n <span aria-hidden=\"true\" data-slot=\"checkbox-box\" className={checkboxBoxVariants()}>\n <span data-slot=\"checkbox-fill\" className=\"checkbox-fill\" />\n {/*\n One mark, always rendered: the state decides what it shows. Both\n states can be true at once (a \"select all\" box that has been\n partially cleared) and indeterminate wins, which the path's\n `d` carries in CSS -- the same precedence the old two-glyph\n branch pinned in JS.\n */}\n <svg\n data-slot=\"checkbox-mark\"\n data-mark={isIndeterminate ? \"indeterminate\" : isSelected ? \"check\" : undefined}\n viewBox=\"0 0 18 18\"\n fill=\"none\"\n className=\"absolute -inset-px size-4 overflow-visible\"\n >\n <path\n className=\"checkbox-mark\"\n pathLength=\"1\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </svg>\n </span>\n {children == null ? null : <span data-slot=\"checkbox-label\">{children}</span>}\n </>\n )}\n </AriaCheckbox>\n );\n});\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+CA,MAAa,mBAAmB,IAAI,CAAC,uBAAuB,CAAC,CAAC;AAE9D,MAAa,sBAAsB,IAAI;CACrC;CACA;CAGA;CAEA;CAGA;CAGA;CACA;CAEA;CAEA,sBAAsB;AACxB,CAAC;AAgBD,MAAaA,aAAW,WAA4C,SAASA,WAC3E,EAAE,WAAW,UAAU,GAAG,SAC1B,KACA;CACA,OACE,oBAACC,UAAD;EACE,GAAI;EAKJ,UAAU;EACV,aAAU;EAIV,WAAW,GAAG,iBAAiB,GAAG,SAAS;EAEzC,WAAA,EAAE,YAAY,sBACd,qBAAA,YAAA,EAAA,UAAA,CAKE,qBAAC,QAAD;GAAM,eAAY;GAAO,aAAU;GAAe,WAAW,oBAAoB;GAAjF,UAAA,CACE,oBAAC,QAAD;IAAM,aAAU;IAAgB,WAAU;GAAiB,CAAA,GAQ3D,oBAAC,OAAD;IACE,aAAU;IACV,aAAW,kBAAkB,kBAAkB,aAAa,UAAU,KAAA;IACtE,SAAQ;IACR,MAAK;IACL,WAAU;IAEV,UAAA,oBAAC,QAAD;KACE,WAAU;KACV,YAAW;KACX,QAAO;KACP,aAAY;KACZ,eAAc;KACd,gBAAe;IAChB,CAAA;GACE,CAAA,CACD;EACL,CAAA,GAAA,YAAY,OAAO,OAAO,oBAAC,QAAD;GAAM,aAAU;GAAkB;EAAe,CAAA,CAC5E,EAAA,CAAA;CAEQ,CAAA;AAElB,CAAC"}
@@ -0,0 +1,85 @@
1
+ import { ReactNode } from "react";
2
+ //#region src/confirm-morph/confirm-morph.d.ts
3
+ /** Where the control is in its life: resting, asking, working, finished, or failed. */
4
+ export type ConfirmMorphState = "idle" | "confirming" | "pending" | "done" | "error";
5
+ /** How the question is answered: a press, a press held until the fill completes, or a press followed by a short countdown. */
6
+ export type ConfirmMorphMode = "press" | "hold" | "countdown";
7
+ /**
8
+ * A button for destructive or important actions that asks in place. Pressing it
9
+ * morphs the same pill into an inline question with Cancel and Confirm, then into
10
+ * a spinner, then into a result with Undo. The width springs to each face while
11
+ * the faces crossfade at their natural width, so text never squashes and nothing
12
+ * around the control jumps. Escape, an outside press, or the timeout all return
13
+ * it to rest.
14
+ *
15
+ * Use it where a modal dialog would be heavy: deleting a project, revoking
16
+ * access, discarding a draft.
17
+ */
18
+ export interface ConfirmMorphProps {
19
+ /** The resting label, such as "Delete project". */
20
+ label: ReactNode;
21
+ /** A plain icon before the resting label. Mark it `aria-hidden`. */
22
+ icon?: ReactNode;
23
+ /** The question shown while confirming, such as "Delete 3 files?". Defaults to the label with a question mark. */
24
+ prompt?: ReactNode;
25
+ confirmLabel?: string;
26
+ cancelLabel?: string;
27
+ /** Shown beside the spinner while `onConfirm` resolves. */
28
+ pendingLabel?: string;
29
+ doneLabel?: string;
30
+ errorLabel?: string;
31
+ retryLabel?: string;
32
+ undoLabel?: string;
33
+ /** Shown beside the spinner while `onUndo` resolves. */
34
+ undoingLabel?: string;
35
+ /**
36
+ * `danger` (default) gives the confirm button the destructive colour, for
37
+ * actions that destroy something. `neutral` gives it the primary colour, for
38
+ * important actions that can be reversed. The resting button is neutral either way.
39
+ */
40
+ tone?: "danger" | "neutral";
41
+ /** `press` confirms on a press. `hold` asks for a press held for `holdDuration`. `countdown` confirms, then counts down `countdown` seconds that Cancel or Escape can still stop. */
42
+ confirmMode?: ConfirmMorphMode;
43
+ /** Milliseconds the confirm button must be held in `hold` mode. */
44
+ holdDuration?: number;
45
+ /** Seconds counted down before the action runs in `countdown` mode. */
46
+ countdown?: number;
47
+ /** Text before the seconds in `countdown` mode, such as "Deleting in". Defaults to the pending label followed by "in". */
48
+ countdownLabel?: string;
49
+ /** Runs on confirm. Return a promise to show the pending face; a rejection shows the error face with Retry. */
50
+ onConfirm?: () => void | Promise<unknown>;
51
+ /** Offering it adds Undo to the result. Return a promise to show a pending face while it runs. */
52
+ onUndo?: () => void | Promise<unknown>;
53
+ onCancel?: () => void;
54
+ /** Controlled state. Pair it with `onStateChange`. */
55
+ state?: ConfirmMorphState;
56
+ /** Starting state when uncontrolled. */
57
+ defaultState?: ConfirmMorphState;
58
+ onStateChange?: (state: ConfirmMorphState) => void;
59
+ /** Milliseconds before an unanswered question returns to rest. Resting the pointer on the control pauses it. 0 turns it off. */
60
+ confirmTimeout?: number;
61
+ /** Milliseconds a result stays before returning to rest. Resting the pointer on the control pauses it. 0 turns it off. */
62
+ resultTimeout?: number;
63
+ /** A press outside the control cancels an open question. Defaults to true. */
64
+ cancelOnOutsidePress?: boolean;
65
+ isDisabled?: boolean;
66
+ /** Extra classes for the root. Merged last, so they win conflicts with ours. */
67
+ className?: string;
68
+ }
69
+ /**
70
+ * A button for an action that deserves a second thought, without a dialog. It
71
+ * asks in place: the pill morphs into a question with Cancel and Confirm, then
72
+ * a spinner, then a result with Undo, its width springing to each face while the
73
+ * faces crossfade at their natural width.
74
+ *
75
+ * Escape, a press outside, or the timeout answer the question with no. Focus
76
+ * follows the control between faces, but only when it was already inside, so a
77
+ * timeout never steals it. A live region announces each step.
78
+ *
79
+ * @example
80
+ * <ConfirmMorph label="Delete project" onConfirm={() => deleteProject()} onUndo={() => restore()} />
81
+ * <ConfirmMorph label="Delete project" confirmMode="hold" onConfirm={deleteProject} />
82
+ */
83
+ export declare const ConfirmMorph: import("react").ForwardRefExoticComponent<ConfirmMorphProps & import("react").RefAttributes<HTMLDivElement>>;
84
+ //#endregion
85
+ //# sourceMappingURL=confirm-morph.d.ts.map