@entifix/react-controls 0.18.2 → 0.19.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 (180) hide show
  1. package/README.md +5 -5
  2. package/dist/i18n/catalog/en.d.ts.map +1 -1
  3. package/dist/i18n/catalog/en.js +13 -1
  4. package/dist/i18n/catalog/en.js.map +1 -1
  5. package/dist/i18n/catalog/es.d.ts +12 -0
  6. package/dist/i18n/catalog/es.d.ts.map +1 -1
  7. package/dist/i18n/catalog/es.js +13 -1
  8. package/dist/i18n/catalog/es.js.map +1 -1
  9. package/dist/i18n/catalog/index.d.ts +24 -0
  10. package/dist/i18n/catalog/index.d.ts.map +1 -1
  11. package/dist/index.d.ts +7 -0
  12. package/dist/index.d.ts.map +1 -1
  13. package/dist/index.js +7 -0
  14. package/dist/index.js.map +1 -1
  15. package/dist/primitives.d.ts +7 -0
  16. package/dist/primitives.d.ts.map +1 -1
  17. package/dist/primitives.js +7 -0
  18. package/dist/primitives.js.map +1 -1
  19. package/dist/theme/theme-context.d.ts +23 -7
  20. package/dist/theme/theme-context.d.ts.map +1 -1
  21. package/dist/theme/theme-context.js +76 -14
  22. package/dist/theme/theme-context.js.map +1 -1
  23. package/dist/theme/theme-script.d.ts +4 -3
  24. package/dist/theme/theme-script.d.ts.map +1 -1
  25. package/dist/theme/theme-script.js +8 -3
  26. package/dist/theme/theme-script.js.map +1 -1
  27. package/dist/theme/types.d.ts +19 -3
  28. package/dist/theme/types.d.ts.map +1 -1
  29. package/dist/theme/types.js.map +1 -1
  30. package/dist/ui/atoms/alert/alert-dismiss.d.ts +9 -0
  31. package/dist/ui/atoms/alert/alert-dismiss.d.ts.map +1 -0
  32. package/dist/ui/atoms/alert/alert-dismiss.js +28 -0
  33. package/dist/ui/atoms/alert/alert-dismiss.js.map +1 -0
  34. package/dist/ui/atoms/alert/alert.d.ts +24 -0
  35. package/dist/ui/atoms/alert/alert.d.ts.map +1 -0
  36. package/dist/ui/atoms/alert/alert.js +50 -0
  37. package/dist/ui/atoms/alert/alert.js.map +1 -0
  38. package/dist/ui/atoms/alert/index.d.ts +3 -0
  39. package/dist/ui/atoms/alert/index.d.ts.map +1 -0
  40. package/dist/ui/atoms/alert/index.js +4 -0
  41. package/dist/ui/atoms/alert/index.js.map +1 -0
  42. package/dist/ui/atoms/alert/tone.d.ts +8 -0
  43. package/dist/ui/atoms/alert/tone.d.ts.map +1 -0
  44. package/dist/ui/atoms/alert/tone.js +11 -0
  45. package/dist/ui/atoms/alert/tone.js.map +1 -0
  46. package/dist/ui/atoms/button/button-recipe.js +1 -1
  47. package/dist/ui/atoms/button/button-recipe.js.map +1 -1
  48. package/dist/ui/atoms/button/index.d.ts +1 -0
  49. package/dist/ui/atoms/button/index.d.ts.map +1 -1
  50. package/dist/ui/atoms/button/index.js +1 -0
  51. package/dist/ui/atoms/button/index.js.map +1 -1
  52. package/dist/ui/atoms/button/submit-button.d.ts +13 -0
  53. package/dist/ui/atoms/button/submit-button.d.ts.map +1 -0
  54. package/dist/ui/atoms/button/submit-button.js +29 -0
  55. package/dist/ui/atoms/button/submit-button.js.map +1 -0
  56. package/dist/ui/atoms/cell-value/cell-value.d.ts +6 -1
  57. package/dist/ui/atoms/cell-value/cell-value.d.ts.map +1 -1
  58. package/dist/ui/atoms/cell-value/cell-value.js +20 -2
  59. package/dist/ui/atoms/cell-value/cell-value.js.map +1 -1
  60. package/dist/ui/atoms/field/checkbox.d.ts.map +1 -1
  61. package/dist/ui/atoms/field/checkbox.js +21 -1
  62. package/dist/ui/atoms/field/checkbox.js.map +1 -1
  63. package/dist/ui/atoms/field/field.js +1 -1
  64. package/dist/ui/atoms/field/field.js.map +1 -1
  65. package/dist/ui/atoms/field-control/field-control.d.ts +6 -1
  66. package/dist/ui/atoms/field-control/field-control.d.ts.map +1 -1
  67. package/dist/ui/atoms/field-control/field-control.js +23 -3
  68. package/dist/ui/atoms/field-control/field-control.js.map +1 -1
  69. package/dist/ui/atoms/money/index.d.ts +4 -0
  70. package/dist/ui/atoms/money/index.d.ts.map +1 -0
  71. package/dist/ui/atoms/money/index.js +5 -0
  72. package/dist/ui/atoms/money/index.js.map +1 -0
  73. package/dist/ui/atoms/money/money-input.d.ts +19 -0
  74. package/dist/ui/atoms/money/money-input.d.ts.map +1 -0
  75. package/dist/ui/atoms/money/money-input.js +75 -0
  76. package/dist/ui/atoms/money/money-input.js.map +1 -0
  77. package/dist/ui/atoms/money/money-math.d.ts +21 -0
  78. package/dist/ui/atoms/money/money-math.d.ts.map +1 -0
  79. package/dist/ui/atoms/money/money-math.js +36 -0
  80. package/dist/ui/atoms/money/money-math.js.map +1 -0
  81. package/dist/ui/atoms/money/money.d.ts +19 -0
  82. package/dist/ui/atoms/money/money.d.ts.map +1 -0
  83. package/dist/ui/atoms/money/money.js +26 -0
  84. package/dist/ui/atoms/money/money.js.map +1 -0
  85. package/dist/ui/atoms/number-input/index.d.ts +3 -0
  86. package/dist/ui/atoms/number-input/index.d.ts.map +1 -0
  87. package/dist/ui/atoms/number-input/index.js +4 -0
  88. package/dist/ui/atoms/number-input/index.js.map +1 -0
  89. package/dist/ui/atoms/number-input/number-input.d.ts +10 -0
  90. package/dist/ui/atoms/number-input/number-input.d.ts.map +1 -0
  91. package/dist/ui/atoms/number-input/number-input.js +23 -0
  92. package/dist/ui/atoms/number-input/number-input.js.map +1 -0
  93. package/dist/ui/atoms/number-input/quantity-input.d.ts +22 -0
  94. package/dist/ui/atoms/number-input/quantity-input.d.ts.map +1 -0
  95. package/dist/ui/atoms/number-input/quantity-input.js +99 -0
  96. package/dist/ui/atoms/number-input/quantity-input.js.map +1 -0
  97. package/dist/ui/atoms/skeleton/skeleton.js +1 -1
  98. package/dist/ui/atoms/skeleton/skeleton.js.map +1 -1
  99. package/dist/ui/atoms/status-tag/index.d.ts +2 -0
  100. package/dist/ui/atoms/status-tag/index.d.ts.map +1 -0
  101. package/dist/ui/atoms/status-tag/index.js +3 -0
  102. package/dist/ui/atoms/status-tag/index.js.map +1 -0
  103. package/dist/ui/atoms/status-tag/status-tag.d.ts +17 -0
  104. package/dist/ui/atoms/status-tag/status-tag.d.ts.map +1 -0
  105. package/dist/ui/atoms/status-tag/status-tag.js +37 -0
  106. package/dist/ui/atoms/status-tag/status-tag.js.map +1 -0
  107. package/dist/ui/atoms/switch/switch.d.ts.map +1 -1
  108. package/dist/ui/atoms/switch/switch.js +6 -3
  109. package/dist/ui/atoms/switch/switch.js.map +1 -1
  110. package/dist/ui/molecules/breadcrumbs/breadcrumbs.d.ts +11 -2
  111. package/dist/ui/molecules/breadcrumbs/breadcrumbs.d.ts.map +1 -1
  112. package/dist/ui/molecules/breadcrumbs/breadcrumbs.js +9 -7
  113. package/dist/ui/molecules/breadcrumbs/breadcrumbs.js.map +1 -1
  114. package/dist/ui/molecules/column-settings/column-settings.js +1 -1
  115. package/dist/ui/molecules/column-settings/column-settings.js.map +1 -1
  116. package/dist/ui/molecules/confirm-dialog/confirm-dialog.js +2 -2
  117. package/dist/ui/molecules/confirm-dialog/confirm-dialog.js.map +1 -1
  118. package/dist/ui/molecules/description-list/description-list.d.ts +17 -0
  119. package/dist/ui/molecules/description-list/description-list.d.ts.map +1 -0
  120. package/dist/ui/molecules/description-list/description-list.js +36 -0
  121. package/dist/ui/molecules/description-list/description-list.js.map +1 -0
  122. package/dist/ui/molecules/description-list/index.d.ts +2 -0
  123. package/dist/ui/molecules/description-list/index.d.ts.map +1 -0
  124. package/dist/ui/molecules/description-list/index.js +3 -0
  125. package/dist/ui/molecules/description-list/index.js.map +1 -0
  126. package/dist/ui/molecules/drawer/drawer.js +3 -3
  127. package/dist/ui/molecules/drawer/drawer.js.map +1 -1
  128. package/dist/ui/molecules/empty-state/empty-state.d.ts +15 -0
  129. package/dist/ui/molecules/empty-state/empty-state.d.ts.map +1 -0
  130. package/dist/ui/molecules/empty-state/empty-state.js +29 -0
  131. package/dist/ui/molecules/empty-state/empty-state.js.map +1 -0
  132. package/dist/ui/molecules/empty-state/index.d.ts +2 -0
  133. package/dist/ui/molecules/empty-state/index.d.ts.map +1 -0
  134. package/dist/ui/molecules/empty-state/index.js +3 -0
  135. package/dist/ui/molecules/empty-state/index.js.map +1 -0
  136. package/dist/ui/molecules/entity-link-input/entity-link-input.d.ts.map +1 -1
  137. package/dist/ui/molecules/entity-link-input/entity-link-input.js +7 -4
  138. package/dist/ui/molecules/entity-link-input/entity-link-input.js.map +1 -1
  139. package/dist/ui/molecules/entity-link-picker/entity-link-picker.js +2 -2
  140. package/dist/ui/molecules/entity-link-picker/entity-link-picker.js.map +1 -1
  141. package/dist/ui/molecules/media-gallery/index.d.ts +2 -0
  142. package/dist/ui/molecules/media-gallery/index.d.ts.map +1 -0
  143. package/dist/ui/molecules/media-gallery/index.js +3 -0
  144. package/dist/ui/molecules/media-gallery/index.js.map +1 -0
  145. package/dist/ui/molecules/media-gallery/media-gallery.d.ts +31 -0
  146. package/dist/ui/molecules/media-gallery/media-gallery.d.ts.map +1 -0
  147. package/dist/ui/molecules/media-gallery/media-gallery.js +64 -0
  148. package/dist/ui/molecules/media-gallery/media-gallery.js.map +1 -0
  149. package/dist/ui/molecules/menu/menu.d.ts.map +1 -1
  150. package/dist/ui/molecules/menu/menu.js +6 -4
  151. package/dist/ui/molecules/menu/menu.js.map +1 -1
  152. package/dist/ui/molecules/nav-menu/nav-menu.js +4 -4
  153. package/dist/ui/molecules/nav-menu/nav-menu.js.map +1 -1
  154. package/dist/ui/molecules/segmented-nav/segment-classes.d.ts +3 -3
  155. package/dist/ui/molecules/segmented-nav/segment-classes.d.ts.map +1 -1
  156. package/dist/ui/molecules/segmented-nav/segment-classes.js +2 -2
  157. package/dist/ui/molecules/segmented-nav/segment-classes.js.map +1 -1
  158. package/dist/ui/molecules/segmented-nav/segmented-nav.d.ts +14 -4
  159. package/dist/ui/molecules/segmented-nav/segmented-nav.d.ts.map +1 -1
  160. package/dist/ui/molecules/segmented-nav/segmented-nav.js +6 -5
  161. package/dist/ui/molecules/segmented-nav/segmented-nav.js.map +1 -1
  162. package/dist/ui/molecules/split-view/split-view.js +3 -3
  163. package/dist/ui/molecules/split-view/split-view.js.map +1 -1
  164. package/dist/ui/molecules/tab-strip/tab-strip.d.ts +51 -12
  165. package/dist/ui/molecules/tab-strip/tab-strip.d.ts.map +1 -1
  166. package/dist/ui/molecules/tab-strip/tab-strip.js +125 -34
  167. package/dist/ui/molecules/tab-strip/tab-strip.js.map +1 -1
  168. package/dist/ui/molecules/toast-region/toast-region.js +1 -1
  169. package/dist/ui/molecules/toast-region/toast-region.js.map +1 -1
  170. package/dist/ui/organisms/command-palette/command-palette.js +6 -6
  171. package/dist/ui/organisms/command-palette/command-palette.js.map +1 -1
  172. package/dist/ui/organisms/entity-detail-grid/entity-detail-grid.d.ts.map +1 -1
  173. package/dist/ui/organisms/entity-detail-grid/entity-detail-grid.js +8 -2
  174. package/dist/ui/organisms/entity-detail-grid/entity-detail-grid.js.map +1 -1
  175. package/dist/ui/organisms/entity-form/entity-form.js +4 -2
  176. package/dist/ui/organisms/entity-form/entity-form.js.map +1 -1
  177. package/dist/ui/organisms/entity-table/entity-table.d.ts.map +1 -1
  178. package/dist/ui/organisms/entity-table/entity-table.js +2 -1
  179. package/dist/ui/organisms/entity-table/entity-table.js.map +1 -1
  180. package/package.json +5 -5
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/ui/atoms/number-input/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAC;AAClC,cAAc,qBAAqB,CAAC"}
@@ -0,0 +1,4 @@
1
+ export * from './number-input.js';
2
+ export * from './quantity-input.js';
3
+
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/ui/atoms/number-input/index.ts"],"sourcesContent":["export * from './number-input.js';\nexport * from './quantity-input.js';\n"],"names":[],"mappings":"AAAA,cAAc,oBAAoB;AAClC,cAAc,sBAAsB"}
@@ -0,0 +1,10 @@
1
+ import type { ComponentPropsWithoutRef } from 'react';
2
+ export type NumberInputProps = Omit<ComponentPropsWithoutRef<'input'>, 'type'>;
3
+ /**
4
+ * A number typed as text: `inputmode` brings up the numeric keyboard, and the
5
+ * value stays exactly what was typed, in the reader's own decimal separator,
6
+ * rather than a native `type="number"` that rejects `64,99` in a Spanish
7
+ * locale and spins on a scroll wheel. Tabular figures. Server-safe.
8
+ */
9
+ export declare function NumberInput({ className, inputMode, ...props }: NumberInputProps): import("react").JSX.Element;
10
+ //# sourceMappingURL=number-input.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"number-input.d.ts","sourceRoot":"","sources":["../../../../src/ui/atoms/number-input/number-input.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,OAAO,CAAC;AAKtD,MAAM,MAAM,gBAAgB,GAAG,IAAI,CAAC,wBAAwB,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC,CAAC;AAE/E;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,EAC1B,SAAS,EACT,SAAqB,EACrB,GAAG,KAAK,EACT,EAAE,gBAAgB,+BASlB"}
@@ -0,0 +1,23 @@
1
+ import { _ as _extends } from "@swc/helpers/_/_extends";
2
+ import { _ as _object_without_properties_loose } from "@swc/helpers/_/_object_without_properties_loose";
3
+ import { jsx as _jsx } from "react/jsx-runtime";
4
+ import { cn } from '../../utils/cn.js';
5
+ import { TextInput } from '../field/field.js';
6
+ /**
7
+ * A number typed as text: `inputmode` brings up the numeric keyboard, and the
8
+ * value stays exactly what was typed, in the reader's own decimal separator,
9
+ * rather than a native `type="number"` that rejects `64,99` in a Spanish
10
+ * locale and spins on a scroll wheel. Tabular figures. Server-safe.
11
+ */ export function NumberInput(_0) {
12
+ let { className, inputMode = 'decimal' } = _0, props = _object_without_properties_loose(_0, [
13
+ "className",
14
+ "inputMode"
15
+ ]);
16
+ return /*#__PURE__*/ _jsx(TextInput, _extends({
17
+ type: "text",
18
+ inputMode: inputMode,
19
+ className: cn('tabular-nums', className)
20
+ }, props));
21
+ }
22
+
23
+ //# sourceMappingURL=number-input.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/ui/atoms/number-input/number-input.tsx"],"sourcesContent":["import type { ComponentPropsWithoutRef } from 'react';\n\nimport { cn } from '../../utils/cn.js';\nimport { TextInput } from '../field/field.js';\n\nexport type NumberInputProps = Omit<ComponentPropsWithoutRef<'input'>, 'type'>;\n\n/**\n * A number typed as text: `inputmode` brings up the numeric keyboard, and the\n * value stays exactly what was typed, in the reader's own decimal separator,\n * rather than a native `type=\"number\"` that rejects `64,99` in a Spanish\n * locale and spins on a scroll wheel. Tabular figures. Server-safe.\n */\nexport function NumberInput({\n className,\n inputMode = 'decimal',\n ...props\n}: NumberInputProps) {\n return (\n <TextInput\n type=\"text\"\n inputMode={inputMode}\n className={cn('tabular-nums', className)}\n {...props}\n />\n );\n}\n"],"names":["cn","TextInput","NumberInput","className","inputMode","props","type"],"mappings":";;;AAEA,SAASA,EAAE,QAAQ,oBAAoB;AACvC,SAASC,SAAS,QAAQ,oBAAoB;AAI9C;;;;;CAKC,GACD,OAAO,SAASC,YAAY,EAIT;QAJS,EAC1BC,SAAS,EACTC,YAAY,SAAS,EAEJ,OADdC;;;;IAEH,qBACE,KAACJ;QACCK,MAAK;QACLF,WAAWA;QACXD,WAAWH,GAAG,gBAAgBG;OAC1BE;AAGV"}
@@ -0,0 +1,22 @@
1
+ export interface QuantityInputProps {
2
+ /** What is being counted; names the spinbutton and both of its buttons. */
3
+ label: string;
4
+ value: number;
5
+ onChange: (value: number) => void;
6
+ min?: number;
7
+ max?: number;
8
+ step?: number;
9
+ disabled?: boolean;
10
+ id?: string;
11
+ className?: string;
12
+ }
13
+ /**
14
+ * A count, on the WAI-ARIA spinbutton pattern: Up and Down step it, Home and
15
+ * End jump to its bounds, and what is typed is committed on Enter or on
16
+ * leaving the field, clamped to the bounds. The − and + beside it are named
17
+ * "Decrease {label}" and "Increase {label}" and sit at `--target-min`; they are
18
+ * out of the Tab order, as the pattern has them, because the arrow keys
19
+ * already do what they do.
20
+ */
21
+ export declare function QuantityInput({ label, value, onChange, min, max, step, disabled, id, className, }: QuantityInputProps): import("react").JSX.Element;
22
+ //# sourceMappingURL=quantity-input.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"quantity-input.d.ts","sourceRoot":"","sources":["../../../../src/ui/atoms/number-input/quantity-input.tsx"],"names":[],"mappings":"AAOA,MAAM,WAAW,kBAAkB;IACjC,2EAA2E;IAC3E,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAKD;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,EAC5B,KAAK,EACL,KAAK,EACL,QAAQ,EACR,GAAO,EACP,GAAG,EACH,IAAQ,EACR,QAAgB,EAChB,EAAE,EACF,SAAS,GACV,EAAE,kBAAkB,+BA6EpB"}
@@ -0,0 +1,99 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { useEffect, useState } from 'react';
4
+ import { useT } from '../../../i18n/index.js';
5
+ import { cn } from '../../utils/cn.js';
6
+ const STEP_BUTTON = 'flex min-h-(--target-min) min-w-(--target-min) shrink-0 items-center justify-center rounded-md border border-border-control bg-surface-elevated text-content hover:bg-surface disabled:cursor-not-allowed disabled:opacity-50';
7
+ /**
8
+ * A count, on the WAI-ARIA spinbutton pattern: Up and Down step it, Home and
9
+ * End jump to its bounds, and what is typed is committed on Enter or on
10
+ * leaving the field, clamped to the bounds. The − and + beside it are named
11
+ * "Decrease {label}" and "Increase {label}" and sit at `--target-min`; they are
12
+ * out of the Tab order, as the pattern has them, because the arrow keys
13
+ * already do what they do.
14
+ */ export function QuantityInput({ label, value, onChange, min = 0, max, step = 1, disabled = false, id, className }) {
15
+ const t = useT();
16
+ const [text, setText] = useState(String(value));
17
+ useEffect(()=>{
18
+ // eslint-disable-next-line react-hooks/set-state-in-effect -- the value moved from outside (a step, a reset)
19
+ setText(String(value));
20
+ }, [
21
+ value
22
+ ]);
23
+ const clamp = (next)=>Math.min(max != null ? max : Number.POSITIVE_INFINITY, Math.max(min, next));
24
+ const set = (next)=>{
25
+ const clamped = clamp(next);
26
+ setText(String(clamped));
27
+ if (clamped !== value) onChange(clamped);
28
+ };
29
+ const commit = ()=>{
30
+ const typed = Number.parseInt(text, 10);
31
+ set(Number.isNaN(typed) ? value : typed);
32
+ };
33
+ const onKeyDown = (event)=>{
34
+ const next = {
35
+ ArrowUp: value + step,
36
+ ArrowDown: value - step,
37
+ Home: min,
38
+ End: max
39
+ }[event.key];
40
+ if (event.key === 'Enter') {
41
+ commit();
42
+ return;
43
+ }
44
+ if (next === undefined) return;
45
+ event.preventDefault();
46
+ set(next);
47
+ };
48
+ return /*#__PURE__*/ _jsxs("span", {
49
+ className: cn('inline-flex items-center gap-3xs', className),
50
+ children: [
51
+ /*#__PURE__*/ _jsx("button", {
52
+ type: "button",
53
+ tabIndex: -1,
54
+ "aria-label": t('quantity.decrease', {
55
+ label
56
+ }),
57
+ disabled: disabled || value <= min,
58
+ onClick: ()=>set(value - step),
59
+ className: STEP_BUTTON,
60
+ children: /*#__PURE__*/ _jsx("span", {
61
+ "aria-hidden": "true",
62
+ children: "−"
63
+ })
64
+ }),
65
+ /*#__PURE__*/ _jsx("input", {
66
+ id: id,
67
+ type: "text",
68
+ role: "spinbutton",
69
+ inputMode: "numeric",
70
+ "aria-label": label,
71
+ "aria-valuenow": value,
72
+ "aria-valuemin": min,
73
+ "aria-valuemax": max,
74
+ disabled: disabled,
75
+ value: text,
76
+ onChange: (event)=>setText(event.currentTarget.value),
77
+ onBlur: commit,
78
+ onKeyDown: onKeyDown,
79
+ className: "w-16 min-h-(--target-min) rounded-lg border border-border-control bg-surface-elevated px-2xs py-3xs text-center text-step-sm text-content tabular-nums focus-ring disabled:cursor-not-allowed disabled:opacity-50"
80
+ }),
81
+ /*#__PURE__*/ _jsx("button", {
82
+ type: "button",
83
+ tabIndex: -1,
84
+ "aria-label": t('quantity.increase', {
85
+ label
86
+ }),
87
+ disabled: disabled || max !== undefined && value >= max,
88
+ onClick: ()=>set(value + step),
89
+ className: STEP_BUTTON,
90
+ children: /*#__PURE__*/ _jsx("span", {
91
+ "aria-hidden": "true",
92
+ children: "+"
93
+ })
94
+ })
95
+ ]
96
+ });
97
+ }
98
+
99
+ //# sourceMappingURL=quantity-input.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/ui/atoms/number-input/quantity-input.tsx"],"sourcesContent":["'use client';\n\nimport { type KeyboardEvent, useEffect, useState } from 'react';\n\nimport { useT } from '../../../i18n/index.js';\nimport { cn } from '../../utils/cn.js';\n\nexport interface QuantityInputProps {\n /** What is being counted; names the spinbutton and both of its buttons. */\n label: string;\n value: number;\n onChange: (value: number) => void;\n min?: number;\n max?: number;\n step?: number;\n disabled?: boolean;\n id?: string;\n className?: string;\n}\n\nconst STEP_BUTTON =\n 'flex min-h-(--target-min) min-w-(--target-min) shrink-0 items-center justify-center rounded-md border border-border-control bg-surface-elevated text-content hover:bg-surface disabled:cursor-not-allowed disabled:opacity-50';\n\n/**\n * A count, on the WAI-ARIA spinbutton pattern: Up and Down step it, Home and\n * End jump to its bounds, and what is typed is committed on Enter or on\n * leaving the field, clamped to the bounds. The − and + beside it are named\n * \"Decrease {label}\" and \"Increase {label}\" and sit at `--target-min`; they are\n * out of the Tab order, as the pattern has them, because the arrow keys\n * already do what they do.\n */\nexport function QuantityInput({\n label,\n value,\n onChange,\n min = 0,\n max,\n step = 1,\n disabled = false,\n id,\n className,\n}: QuantityInputProps) {\n const t = useT();\n const [text, setText] = useState(String(value));\n\n useEffect(() => {\n // eslint-disable-next-line react-hooks/set-state-in-effect -- the value moved from outside (a step, a reset)\n setText(String(value));\n }, [value]);\n\n const clamp = (next: number) =>\n Math.min(max ?? Number.POSITIVE_INFINITY, Math.max(min, next));\n const set = (next: number) => {\n const clamped = clamp(next);\n setText(String(clamped));\n if (clamped !== value) onChange(clamped);\n };\n const commit = () => {\n const typed = Number.parseInt(text, 10);\n set(Number.isNaN(typed) ? value : typed);\n };\n\n const onKeyDown = (event: KeyboardEvent<HTMLInputElement>) => {\n const next = {\n ArrowUp: value + step,\n ArrowDown: value - step,\n Home: min,\n End: max,\n }[event.key];\n if (event.key === 'Enter') {\n commit();\n return;\n }\n if (next === undefined) return;\n event.preventDefault();\n set(next);\n };\n\n return (\n <span className={cn('inline-flex items-center gap-3xs', className)}>\n <button\n type=\"button\"\n tabIndex={-1}\n aria-label={t('quantity.decrease', { label })}\n disabled={disabled || value <= min}\n onClick={() => set(value - step)}\n className={STEP_BUTTON}\n >\n <span aria-hidden=\"true\">−</span>\n </button>\n <input\n id={id}\n type=\"text\"\n role=\"spinbutton\"\n inputMode=\"numeric\"\n aria-label={label}\n aria-valuenow={value}\n aria-valuemin={min}\n aria-valuemax={max}\n disabled={disabled}\n value={text}\n onChange={event => setText(event.currentTarget.value)}\n onBlur={commit}\n onKeyDown={onKeyDown}\n className=\"w-16 min-h-(--target-min) rounded-lg border border-border-control bg-surface-elevated px-2xs py-3xs text-center text-step-sm text-content tabular-nums focus-ring disabled:cursor-not-allowed disabled:opacity-50\"\n />\n <button\n type=\"button\"\n tabIndex={-1}\n aria-label={t('quantity.increase', { label })}\n disabled={disabled || (max !== undefined && value >= max)}\n onClick={() => set(value + step)}\n className={STEP_BUTTON}\n >\n <span aria-hidden=\"true\">+</span>\n </button>\n </span>\n );\n}\n"],"names":["useEffect","useState","useT","cn","STEP_BUTTON","QuantityInput","label","value","onChange","min","max","step","disabled","id","className","t","text","setText","String","clamp","next","Math","Number","POSITIVE_INFINITY","set","clamped","commit","typed","parseInt","isNaN","onKeyDown","event","ArrowUp","ArrowDown","Home","End","key","undefined","preventDefault","span","button","type","tabIndex","aria-label","onClick","aria-hidden","input","role","inputMode","aria-valuenow","aria-valuemin","aria-valuemax","currentTarget","onBlur"],"mappings":"AAAA;;AAEA,SAA6BA,SAAS,EAAEC,QAAQ,QAAQ,QAAQ;AAEhE,SAASC,IAAI,QAAQ,yBAAyB;AAC9C,SAASC,EAAE,QAAQ,oBAAoB;AAevC,MAAMC,cACJ;AAEF;;;;;;;CAOC,GACD,OAAO,SAASC,cAAc,EAC5BC,KAAK,EACLC,KAAK,EACLC,QAAQ,EACRC,MAAM,CAAC,EACPC,GAAG,EACHC,OAAO,CAAC,EACRC,WAAW,KAAK,EAChBC,EAAE,EACFC,SAAS,EACU;IACnB,MAAMC,IAAIb;IACV,MAAM,CAACc,MAAMC,QAAQ,GAAGhB,SAASiB,OAAOX;IAExCP,UAAU;QACR,6GAA6G;QAC7GiB,QAAQC,OAAOX;IACjB,GAAG;QAACA;KAAM;IAEV,MAAMY,QAAQ,CAACC,OACbC,KAAKZ,GAAG,CAACC,cAAAA,MAAOY,OAAOC,iBAAiB,EAAEF,KAAKX,GAAG,CAACD,KAAKW;IAC1D,MAAMI,MAAM,CAACJ;QACX,MAAMK,UAAUN,MAAMC;QACtBH,QAAQC,OAAOO;QACf,IAAIA,YAAYlB,OAAOC,SAASiB;IAClC;IACA,MAAMC,SAAS;QACb,MAAMC,QAAQL,OAAOM,QAAQ,CAACZ,MAAM;QACpCQ,IAAIF,OAAOO,KAAK,CAACF,SAASpB,QAAQoB;IACpC;IAEA,MAAMG,YAAY,CAACC;QACjB,MAAMX,OAAO;YACXY,SAASzB,QAAQI;YACjBsB,WAAW1B,QAAQI;YACnBuB,MAAMzB;YACN0B,KAAKzB;QACP,CAAC,CAACqB,MAAMK,GAAG,CAAC;QACZ,IAAIL,MAAMK,GAAG,KAAK,SAAS;YACzBV;YACA;QACF;QACA,IAAIN,SAASiB,WAAW;QACxBN,MAAMO,cAAc;QACpBd,IAAIJ;IACN;IAEA,qBACE,MAACmB;QAAKzB,WAAWX,GAAG,oCAAoCW;;0BACtD,KAAC0B;gBACCC,MAAK;gBACLC,UAAU,CAAC;gBACXC,cAAY5B,EAAE,qBAAqB;oBAAET;gBAAM;gBAC3CM,UAAUA,YAAYL,SAASE;gBAC/BmC,SAAS,IAAMpB,IAAIjB,QAAQI;gBAC3BG,WAAWV;0BAEX,cAAA,KAACmC;oBAAKM,eAAY;8BAAO;;;0BAE3B,KAACC;gBACCjC,IAAIA;gBACJ4B,MAAK;gBACLM,MAAK;gBACLC,WAAU;gBACVL,cAAYrC;gBACZ2C,iBAAe1C;gBACf2C,iBAAezC;gBACf0C,iBAAezC;gBACfE,UAAUA;gBACVL,OAAOS;gBACPR,UAAUuB,CAAAA,QAASd,QAAQc,MAAMqB,aAAa,CAAC7C,KAAK;gBACpD8C,QAAQ3B;gBACRI,WAAWA;gBACXhB,WAAU;;0BAEZ,KAAC0B;gBACCC,MAAK;gBACLC,UAAU,CAAC;gBACXC,cAAY5B,EAAE,qBAAqB;oBAAET;gBAAM;gBAC3CM,UAAUA,YAAaF,QAAQ2B,aAAa9B,SAASG;gBACrDkC,SAAS,IAAMpB,IAAIjB,QAAQI;gBAC3BG,WAAWV;0BAEX,cAAA,KAACmC;oBAAKM,eAAY;8BAAO;;;;;AAIjC"}
@@ -15,7 +15,7 @@ import { cn } from '../../utils/cn.js';
15
15
  return /*#__PURE__*/ _jsx("div", _extends({
16
16
  "aria-hidden": "true",
17
17
  "data-testid": "skeleton",
18
- className: cn('animate-pulse bg-border/60 motion-reduce:animate-none', shape === 'line' && 'h-[1em] rounded-full', shape === 'block' && 'rounded-md', shape === 'circle' && 'aspect-square rounded-full', className)
18
+ className: cn('animate-pulse bg-border/60 motion-reduce:animate-none', shape === 'line' && 'h-(--glyph-block) rounded-full', shape === 'block' && 'rounded-md', shape === 'circle' && 'aspect-square rounded-full', className)
19
19
  }, props));
20
20
  }
21
21
  /** A stack of line skeletons standing in for a block of text. */ export function SkeletonText({ lines = 3, className }) {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/ui/atoms/skeleton/skeleton.tsx"],"sourcesContent":["import type { ComponentPropsWithoutRef } from 'react';\n\nimport { cn } from '../../utils/cn.js';\n\nexport type SkeletonShape = 'line' | 'block' | 'circle';\n\nexport interface SkeletonProps extends ComponentPropsWithoutRef<'div'> {\n /** `line` for text, `block` for panels, `circle` for avatars. */\n shape?: SkeletonShape;\n}\n\n/**\n * A loading placeholder. Pulses to read as \"content is coming\", holds still for\n * `prefers-reduced-motion`, and is `aria-hidden` so assistive tech skips it. Its\n * dimensions come from the caller (`className` / `style`) so it matches the real\n * content's geometry and the swap causes no layout shift.\n */\nexport function Skeleton({\n shape = 'block',\n className,\n ...props\n}: SkeletonProps) {\n return (\n <div\n aria-hidden=\"true\"\n data-testid=\"skeleton\"\n className={cn(\n 'animate-pulse bg-border/60 motion-reduce:animate-none',\n shape === 'line' && 'h-[1em] rounded-full',\n shape === 'block' && 'rounded-md',\n shape === 'circle' && 'aspect-square rounded-full',\n className,\n )}\n {...props}\n />\n );\n}\n\nexport interface SkeletonTextProps {\n /** Number of shimmer lines; the last is shortened like a paragraph end. */\n lines?: number;\n className?: string;\n}\n\n/** A stack of line skeletons standing in for a block of text. */\nexport function SkeletonText({ lines = 3, className }: SkeletonTextProps) {\n return (\n <div className={cn('flex flex-col gap-2xs', className)}>\n {Array.from({ length: lines }, (_, index) => (\n <Skeleton\n key={index}\n shape=\"line\"\n className={index === lines - 1 ? 'w-2/3' : 'w-full'}\n />\n ))}\n </div>\n );\n}\n"],"names":["cn","Skeleton","shape","className","props","div","aria-hidden","data-testid","SkeletonText","lines","Array","from","length","_","index"],"mappings":";;;AAEA,SAASA,EAAE,QAAQ,oBAAoB;AASvC;;;;;CAKC,GACD,OAAO,SAASC,SAAS,EAIT;QAJS,EACvBC,QAAQ,OAAO,EACfC,SAAS,EAEK,OADXC;;;;IAEH,qBACE,KAACC;QACCC,eAAY;QACZC,eAAY;QACZJ,WAAWH,GACT,yDACAE,UAAU,UAAU,wBACpBA,UAAU,WAAW,cACrBA,UAAU,YAAY,8BACtBC;OAEEC;AAGV;AAQA,+DAA+D,GAC/D,OAAO,SAASI,aAAa,EAAEC,QAAQ,CAAC,EAAEN,SAAS,EAAqB;IACtE,qBACE,KAACE;QAAIF,WAAWH,GAAG,yBAAyBG;kBACzCO,MAAMC,IAAI,CAAC;YAAEC,QAAQH;QAAM,GAAG,CAACI,GAAGC,sBACjC,KAACb;gBAECC,OAAM;gBACNC,WAAWW,UAAUL,QAAQ,IAAI,UAAU;eAFtCK;;AAOf"}
1
+ {"version":3,"sources":["../../../../src/ui/atoms/skeleton/skeleton.tsx"],"sourcesContent":["import type { ComponentPropsWithoutRef } from 'react';\n\nimport { cn } from '../../utils/cn.js';\n\nexport type SkeletonShape = 'line' | 'block' | 'circle';\n\nexport interface SkeletonProps extends ComponentPropsWithoutRef<'div'> {\n /** `line` for text, `block` for panels, `circle` for avatars. */\n shape?: SkeletonShape;\n}\n\n/**\n * A loading placeholder. Pulses to read as \"content is coming\", holds still for\n * `prefers-reduced-motion`, and is `aria-hidden` so assistive tech skips it. Its\n * dimensions come from the caller (`className` / `style`) so it matches the real\n * content's geometry and the swap causes no layout shift.\n */\nexport function Skeleton({\n shape = 'block',\n className,\n ...props\n}: SkeletonProps) {\n return (\n <div\n aria-hidden=\"true\"\n data-testid=\"skeleton\"\n className={cn(\n 'animate-pulse bg-border/60 motion-reduce:animate-none',\n shape === 'line' && 'h-(--glyph-block) rounded-full',\n shape === 'block' && 'rounded-md',\n shape === 'circle' && 'aspect-square rounded-full',\n className,\n )}\n {...props}\n />\n );\n}\n\nexport interface SkeletonTextProps {\n /** Number of shimmer lines; the last is shortened like a paragraph end. */\n lines?: number;\n className?: string;\n}\n\n/** A stack of line skeletons standing in for a block of text. */\nexport function SkeletonText({ lines = 3, className }: SkeletonTextProps) {\n return (\n <div className={cn('flex flex-col gap-2xs', className)}>\n {Array.from({ length: lines }, (_, index) => (\n <Skeleton\n key={index}\n shape=\"line\"\n className={index === lines - 1 ? 'w-2/3' : 'w-full'}\n />\n ))}\n </div>\n );\n}\n"],"names":["cn","Skeleton","shape","className","props","div","aria-hidden","data-testid","SkeletonText","lines","Array","from","length","_","index"],"mappings":";;;AAEA,SAASA,EAAE,QAAQ,oBAAoB;AASvC;;;;;CAKC,GACD,OAAO,SAASC,SAAS,EAIT;QAJS,EACvBC,QAAQ,OAAO,EACfC,SAAS,EAEK,OADXC;;;;IAEH,qBACE,KAACC;QACCC,eAAY;QACZC,eAAY;QACZJ,WAAWH,GACT,yDACAE,UAAU,UAAU,kCACpBA,UAAU,WAAW,cACrBA,UAAU,YAAY,8BACtBC;OAEEC;AAGV;AAQA,+DAA+D,GAC/D,OAAO,SAASI,aAAa,EAAEC,QAAQ,CAAC,EAAEN,SAAS,EAAqB;IACtE,qBACE,KAACE;QAAIF,WAAWH,GAAG,yBAAyBG;kBACzCO,MAAMC,IAAI,CAAC;YAAEC,QAAQH;QAAM,GAAG,CAACI,GAAGC,sBACjC,KAACb;gBAECC,OAAM;gBACNC,WAAWW,UAAUL,QAAQ,IAAI,UAAU;eAFtCK;;AAOf"}
@@ -0,0 +1,2 @@
1
+ export * from './status-tag.js';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/ui/atoms/status-tag/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC"}
@@ -0,0 +1,3 @@
1
+ export * from './status-tag.js';
2
+
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/ui/atoms/status-tag/index.ts"],"sourcesContent":["export * from './status-tag.js';\n"],"names":[],"mappings":"AAAA,cAAc,kBAAkB"}
@@ -0,0 +1,17 @@
1
+ import type { ComponentPropsWithoutRef, ReactNode } from 'react';
2
+ import { type Tone } from '../alert/tone.js';
3
+ export type StatusTagTone = Tone | 'neutral';
4
+ export interface StatusTagProps extends Omit<ComponentPropsWithoutRef<'span'>, 'children'> {
5
+ tone: StatusTagTone;
6
+ /** The status in words. Required and non-empty: colour is never the only carrier (WCAG 1.4.1). */
7
+ children: string;
8
+ /** A glyph before the words; decorative, so hidden from assistive technology. */
9
+ icon?: ReactNode;
10
+ }
11
+ /**
12
+ * A record's status as a small tag: a tone and the words for it. The words are
13
+ * mandatory, and an empty string throws rather than rendering a coloured dot
14
+ * that means something only to people who can see the colour. Server-safe.
15
+ */
16
+ export declare function StatusTag({ tone, icon, className, children, ...props }: StatusTagProps): import("react").JSX.Element;
17
+ //# sourceMappingURL=status-tag.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status-tag.d.ts","sourceRoot":"","sources":["../../../../src/ui/atoms/status-tag/status-tag.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,wBAAwB,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAGjE,OAAO,EAAE,KAAK,IAAI,EAAgB,MAAM,kBAAkB,CAAC;AAE3D,MAAM,MAAM,aAAa,GAAG,IAAI,GAAG,SAAS,CAAC;AAO7C,MAAM,WAAW,cAAe,SAAQ,IAAI,CAC1C,wBAAwB,CAAC,MAAM,CAAC,EAChC,UAAU,CACX;IACC,IAAI,EAAE,aAAa,CAAC;IACpB,kGAAkG;IAClG,QAAQ,EAAE,MAAM,CAAC;IACjB,iFAAiF;IACjF,IAAI,CAAC,EAAE,SAAS,CAAC;CAClB;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,EACxB,IAAI,EACJ,IAAI,EACJ,SAAS,EACT,QAAQ,EACR,GAAG,KAAK,EACT,EAAE,cAAc,+BAoBhB"}
@@ -0,0 +1,37 @@
1
+ import { _ as _extends } from "@swc/helpers/_/_extends";
2
+ import { _ as _object_without_properties_loose } from "@swc/helpers/_/_object_without_properties_loose";
3
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
4
+ import { cn } from '../../utils/cn.js';
5
+ import { TONE_SURFACE } from '../alert/tone.js';
6
+ const TONE_CLASS = _extends({}, TONE_SURFACE, {
7
+ neutral: 'border-border bg-surface text-content-muted'
8
+ });
9
+ /**
10
+ * A record's status as a small tag: a tone and the words for it. The words are
11
+ * mandatory, and an empty string throws rather than rendering a coloured dot
12
+ * that means something only to people who can see the colour. Server-safe.
13
+ */ export function StatusTag(_0) {
14
+ let { tone, icon, className, children } = _0, props = _object_without_properties_loose(_0, [
15
+ "tone",
16
+ "icon",
17
+ "className",
18
+ "children"
19
+ ]);
20
+ if (children.trim() === '') {
21
+ throw new Error('StatusTag needs its status in words: colour alone carries nothing for someone who cannot see it.');
22
+ }
23
+ return /*#__PURE__*/ _jsxs("span", _extends({
24
+ "data-tone": tone,
25
+ className: cn('inline-flex items-center gap-3xs rounded-full border px-2xs text-step-xs font-medium whitespace-nowrap', TONE_CLASS[tone], className)
26
+ }, props, {
27
+ children: [
28
+ icon !== undefined && /*#__PURE__*/ _jsx("span", {
29
+ "aria-hidden": "true",
30
+ children: icon
31
+ }),
32
+ children
33
+ ]
34
+ }));
35
+ }
36
+
37
+ //# sourceMappingURL=status-tag.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/ui/atoms/status-tag/status-tag.tsx"],"sourcesContent":["import type { ComponentPropsWithoutRef, ReactNode } from 'react';\n\nimport { cn } from '../../utils/cn.js';\nimport { type Tone, TONE_SURFACE } from '../alert/tone.js';\n\nexport type StatusTagTone = Tone | 'neutral';\n\nconst TONE_CLASS: Record<StatusTagTone, string> = {\n ...TONE_SURFACE,\n neutral: 'border-border bg-surface text-content-muted',\n};\n\nexport interface StatusTagProps extends Omit<\n ComponentPropsWithoutRef<'span'>,\n 'children'\n> {\n tone: StatusTagTone;\n /** The status in words. Required and non-empty: colour is never the only carrier (WCAG 1.4.1). */\n children: string;\n /** A glyph before the words; decorative, so hidden from assistive technology. */\n icon?: ReactNode;\n}\n\n/**\n * A record's status as a small tag: a tone and the words for it. The words are\n * mandatory, and an empty string throws rather than rendering a coloured dot\n * that means something only to people who can see the colour. Server-safe.\n */\nexport function StatusTag({\n tone,\n icon,\n className,\n children,\n ...props\n}: StatusTagProps) {\n if (children.trim() === '') {\n throw new Error(\n 'StatusTag needs its status in words: colour alone carries nothing for someone who cannot see it.',\n );\n }\n return (\n <span\n data-tone={tone}\n className={cn(\n 'inline-flex items-center gap-3xs rounded-full border px-2xs text-step-xs font-medium whitespace-nowrap',\n TONE_CLASS[tone],\n className,\n )}\n {...props}\n >\n {icon !== undefined && <span aria-hidden=\"true\">{icon}</span>}\n {children}\n </span>\n );\n}\n"],"names":["cn","TONE_SURFACE","TONE_CLASS","neutral","StatusTag","tone","icon","className","children","props","trim","Error","span","data-tone","undefined","aria-hidden"],"mappings":";;;AAEA,SAASA,EAAE,QAAQ,oBAAoB;AACvC,SAAoBC,YAAY,QAAQ,mBAAmB;AAI3D,MAAMC,aAA4C,aAC7CD;IACHE,SAAS;;AAcX;;;;CAIC,GACD,OAAO,SAASC,UAAU,EAMT;QANS,EACxBC,IAAI,EACJC,IAAI,EACJC,SAAS,EACTC,QAAQ,EAEO,OADZC;;;;;;IAEH,IAAID,SAASE,IAAI,OAAO,IAAI;QAC1B,MAAM,IAAIC,MACR;IAEJ;IACA,qBACE,MAACC;QACCC,aAAWR;QACXE,WAAWP,GACT,0GACAE,UAAU,CAACG,KAAK,EAChBE;OAEEE;;YAEHH,SAASQ,2BAAa,KAACF;gBAAKG,eAAY;0BAAQT;;YAChDE;;;AAGP"}
@@ -1 +1 @@
1
- {"version":3,"file":"switch.d.ts","sourceRoot":"","sources":["../../../../src/ui/atoms/switch/switch.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,wBAAwB,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAejE;;;;GAIG;AACH,wBAAgB,MAAM,CAAC,EACrB,QAAQ,EACR,SAAS,EACT,GAAG,KAAK,EACT,EAAE,IAAI,CAAC,wBAAwB,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,UAAU,CAAC,GAAG;IACzE,QAAQ,EAAE,SAAS,CAAC;CACrB,+BAgBA"}
1
+ {"version":3,"file":"switch.d.ts","sourceRoot":"","sources":["../../../../src/ui/atoms/switch/switch.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,wBAAwB,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAmBjE;;;;GAIG;AACH,wBAAgB,MAAM,CAAC,EACrB,QAAQ,EACR,SAAS,EACT,GAAG,KAAK,EACT,EAAE,IAAI,CAAC,wBAAwB,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,UAAU,CAAC,GAAG;IACzE,QAAQ,EAAE,SAAS,CAAC;CACrB,+BAgBA"}
@@ -1,12 +1,15 @@
1
1
  import { _ as _extends } from "@swc/helpers/_/_extends";
2
2
  import { _ as _object_without_properties_loose } from "@swc/helpers/_/_object_without_properties_loose";
3
3
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
4
- /** The label: the switch, then its text, on one line. */ const LABEL = 'inline-flex cursor-pointer items-center gap-3xs';
4
+ /** The label: the switch, then its text, on one line. */ const LABEL = 'inline-flex min-h-(--target-min) cursor-pointer items-center gap-3xs';
5
5
  /**
6
6
  * Off: an outlined track, its thumb muted at the start. On: filled with the
7
7
  * primary colour, its thumb the surface's, at the end.
8
- */ const TRACK = 'relative inline-flex h-[1.125rem] w-8 shrink-0 items-center rounded-full border border-content-muted bg-transparent transition-colors motion-reduce:transition-none peer-checked:border-primary peer-checked:bg-primary peer-focus-visible:outline-2 peer-focus-visible:outline-offset-2 peer-focus-visible:outline-focus-ring peer-disabled:cursor-not-allowed peer-disabled:opacity-50 peer-checked:[&>span]:translate-x-[0.875rem] peer-checked:[&>span]:bg-surface';
9
- const THUMB = 'ml-[0.125rem] size-3 rounded-full bg-content-muted transition-[translate,background-color] motion-reduce:transition-none';
8
+ */ const TRACK = 'relative inline-flex h-4.5 w-8 shrink-0 items-center rounded-full border border-border-control bg-transparent transition-colors motion-reduce:transition-none peer-checked:border-primary peer-checked:bg-primary peer-focus-visible:outline-2 peer-focus-visible:outline-offset-2 peer-focus-visible:outline-focus-ring peer-disabled:cursor-not-allowed peer-disabled:opacity-50 peer-checked:[&>span]:translate-x-3.5 peer-checked:[&>span]:bg-surface';
9
+ // Forced colours paint every background as Canvas, which would erase the
10
+ // thumb — the only thing that shows the switch's state there — so it takes
11
+ // the system's text colour instead.
12
+ const THUMB = 'ml-0.5 size-3 rounded-full bg-content-muted transition-[translate,background-color] motion-reduce:transition-none forced-colors:bg-[CanvasText]';
10
13
  /**
11
14
  * An on/off choice: a native checkbox announced as a switch, drawn as a track
12
15
  * and a thumb. The checkbox keeps the keyboard, the form and `onChange`; the
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/ui/atoms/switch/switch.tsx"],"sourcesContent":["import type { ComponentPropsWithoutRef, ReactNode } from 'react';\n\n/** The label: the switch, then its text, on one line. */\nconst LABEL = 'inline-flex cursor-pointer items-center gap-3xs';\n\n/**\n * Off: an outlined track, its thumb muted at the start. On: filled with the\n * primary colour, its thumb the surface's, at the end.\n */\nconst TRACK =\n 'relative inline-flex h-[1.125rem] w-8 shrink-0 items-center rounded-full border border-content-muted bg-transparent transition-colors motion-reduce:transition-none peer-checked:border-primary peer-checked:bg-primary peer-focus-visible:outline-2 peer-focus-visible:outline-offset-2 peer-focus-visible:outline-focus-ring peer-disabled:cursor-not-allowed peer-disabled:opacity-50 peer-checked:[&>span]:translate-x-[0.875rem] peer-checked:[&>span]:bg-surface';\n\nconst THUMB =\n 'ml-[0.125rem] size-3 rounded-full bg-content-muted transition-[translate,background-color] motion-reduce:transition-none';\n\n/**\n * An on/off choice: a native checkbox announced as a switch, drawn as a track\n * and a thumb. The checkbox keeps the keyboard, the form and `onChange`; the\n * track only shows its state.\n */\nexport function Switch({\n children,\n className,\n ...input\n}: Omit<ComponentPropsWithoutRef<'input'>, 'type' | 'role' | 'children'> & {\n children: ReactNode;\n}) {\n return (\n <label data-slot=\"switch\" className={className ?? LABEL}>\n <input\n {...input}\n type=\"checkbox\"\n role=\"switch\"\n data-slot=\"switch-input\"\n className=\"peer sr-only\"\n />\n <span data-slot=\"switch-track\" aria-hidden=\"true\" className={TRACK}>\n <span data-slot=\"switch-thumb\" className={THUMB} />\n </span>\n {children}\n </label>\n );\n}\n"],"names":["LABEL","TRACK","THUMB","Switch","children","className","input","label","data-slot","type","role","span","aria-hidden"],"mappings":";;;AAEA,uDAAuD,GACvD,MAAMA,QAAQ;AAEd;;;CAGC,GACD,MAAMC,QACJ;AAEF,MAAMC,QACJ;AAEF;;;;CAIC,GACD,OAAO,SAASC,OAAO,EAMtB;QANsB,EACrBC,QAAQ,EACRC,SAAS,EAIV,OAHIC;;;;IAIH,qBACE,MAACC;QAAMC,aAAU;QAASH,SAAS,EAAEA,oBAAAA,YAAaL;;0BAChD,KAACM,sBACKA;gBACJG,MAAK;gBACLC,MAAK;gBACLF,aAAU;gBACVH,WAAU;;0BAEZ,KAACM;gBAAKH,aAAU;gBAAeI,eAAY;gBAAOP,WAAWJ;0BAC3D,cAAA,KAACU;oBAAKH,aAAU;oBAAeH,WAAWH;;;YAE3CE;;;AAGP"}
1
+ {"version":3,"sources":["../../../../src/ui/atoms/switch/switch.tsx"],"sourcesContent":["import type { ComponentPropsWithoutRef, ReactNode } from 'react';\n\n/** The label: the switch, then its text, on one line. */\nconst LABEL =\n 'inline-flex min-h-(--target-min) cursor-pointer items-center gap-3xs';\n\n/**\n * Off: an outlined track, its thumb muted at the start. On: filled with the\n * primary colour, its thumb the surface's, at the end.\n */\nconst TRACK =\n 'relative inline-flex h-4.5 w-8 shrink-0 items-center rounded-full border border-border-control bg-transparent transition-colors motion-reduce:transition-none peer-checked:border-primary peer-checked:bg-primary peer-focus-visible:outline-2 peer-focus-visible:outline-offset-2 peer-focus-visible:outline-focus-ring peer-disabled:cursor-not-allowed peer-disabled:opacity-50 peer-checked:[&>span]:translate-x-3.5 peer-checked:[&>span]:bg-surface';\n\n// Forced colours paint every background as Canvas, which would erase the\n// thumb — the only thing that shows the switch's state there — so it takes\n// the system's text colour instead.\nconst THUMB =\n 'ml-0.5 size-3 rounded-full bg-content-muted transition-[translate,background-color] motion-reduce:transition-none forced-colors:bg-[CanvasText]';\n\n/**\n * An on/off choice: a native checkbox announced as a switch, drawn as a track\n * and a thumb. The checkbox keeps the keyboard, the form and `onChange`; the\n * track only shows its state.\n */\nexport function Switch({\n children,\n className,\n ...input\n}: Omit<ComponentPropsWithoutRef<'input'>, 'type' | 'role' | 'children'> & {\n children: ReactNode;\n}) {\n return (\n <label data-slot=\"switch\" className={className ?? LABEL}>\n <input\n {...input}\n type=\"checkbox\"\n role=\"switch\"\n data-slot=\"switch-input\"\n className=\"peer sr-only\"\n />\n <span data-slot=\"switch-track\" aria-hidden=\"true\" className={TRACK}>\n <span data-slot=\"switch-thumb\" className={THUMB} />\n </span>\n {children}\n </label>\n );\n}\n"],"names":["LABEL","TRACK","THUMB","Switch","children","className","input","label","data-slot","type","role","span","aria-hidden"],"mappings":";;;AAEA,uDAAuD,GACvD,MAAMA,QACJ;AAEF;;;CAGC,GACD,MAAMC,QACJ;AAEF,yEAAyE;AACzE,2EAA2E;AAC3E,oCAAoC;AACpC,MAAMC,QACJ;AAEF;;;;CAIC,GACD,OAAO,SAASC,OAAO,EAMtB;QANsB,EACrBC,QAAQ,EACRC,SAAS,EAIV,OAHIC;;;;IAIH,qBACE,MAACC;QAAMC,aAAU;QAASH,SAAS,EAAEA,oBAAAA,YAAaL;;0BAChD,KAACM,sBACKA;gBACJG,MAAK;gBACLC,MAAK;gBACLF,aAAU;gBACVH,WAAU;;0BAEZ,KAACM;gBAAKH,aAAU;gBAAeI,eAAY;gBAAOP,WAAWJ;0BAC3D,cAAA,KAACU;oBAAKH,aAAU;oBAAeH,WAAWH;;;YAE3CE;;;AAGP"}
@@ -5,6 +5,11 @@ export interface BreadcrumbItem {
5
5
  }
6
6
  export interface BreadcrumbsProps extends Omit<ComponentPropsWithoutRef<'nav'>, 'children'> {
7
7
  items: BreadcrumbItem[];
8
+ /**
9
+ * The trail's accessible name. English when omitted; a host with a catalog
10
+ * passes its own (the controls catalog's `breadcrumbs.label`).
11
+ */
12
+ label?: string;
8
13
  /** Glyph between crumbs. */
9
14
  separator?: ReactNode;
10
15
  /**
@@ -22,6 +27,10 @@ export interface BreadcrumbsProps extends Omit<ComponentPropsWithoutRef<'nav'>,
22
27
  className: string;
23
28
  }) => ReactNode;
24
29
  }
25
- /** Accessible breadcrumb trail. Presentational only — no routing knowledge. */
26
- export declare function Breadcrumbs({ items, separator, renderLink, className, ...props }: BreadcrumbsProps): import("react").JSX.Element;
30
+ /**
31
+ * Accessible breadcrumb trail. Presentational only — no routing knowledge, and
32
+ * no hooks: every label arrives as a prop, so a server component renders it
33
+ * and a storefront never pays a client boundary for its trail.
34
+ */
35
+ export declare function Breadcrumbs({ items, label, separator, renderLink, className, ...props }: BreadcrumbsProps): import("react").JSX.Element;
27
36
  //# sourceMappingURL=breadcrumbs.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"breadcrumbs.d.ts","sourceRoot":"","sources":["../../../../src/ui/molecules/breadcrumbs/breadcrumbs.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,wBAAwB,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAKjE,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,gBAAiB,SAAQ,IAAI,CAC5C,wBAAwB,CAAC,KAAK,CAAC,EAC/B,UAAU,CACX;IACC,KAAK,EAAE,cAAc,EAAE,CAAC;IACxB,4BAA4B;IAC5B,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB;;;;OAIG;IACH;;;;;OAKG;IACH,UAAU,CAAC,EAAE,CACX,IAAI,EAAE,QAAQ,CAAC,cAAc,CAAC,GAAG;QAAE,SAAS,EAAE,MAAM,CAAA;KAAE,KACnD,SAAS,CAAC;CAChB;AAKD,+EAA+E;AAC/E,wBAAgB,WAAW,CAAC,EAC1B,KAAK,EACL,SAAe,EACf,UAAU,EACV,SAAS,EACT,GAAG,KAAK,EACT,EAAE,gBAAgB,+BA4ClB"}
1
+ {"version":3,"file":"breadcrumbs.d.ts","sourceRoot":"","sources":["../../../../src/ui/molecules/breadcrumbs/breadcrumbs.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,wBAAwB,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAIjE,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,gBAAiB,SAAQ,IAAI,CAC5C,wBAAwB,CAAC,KAAK,CAAC,EAC/B,UAAU,CACX;IACC,KAAK,EAAE,cAAc,EAAE,CAAC;IACxB;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,4BAA4B;IAC5B,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB;;;;OAIG;IACH;;;;;OAKG;IACH,UAAU,CAAC,EAAE,CACX,IAAI,EAAE,QAAQ,CAAC,cAAc,CAAC,GAAG;QAAE,SAAS,EAAE,MAAM,CAAA;KAAE,KACnD,SAAS,CAAC;CAChB;AAMD;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,EAC1B,KAAK,EACL,KAAoB,EACpB,SAAe,EACf,UAAU,EACV,SAAS,EACT,GAAG,KAAK,EACT,EAAE,gBAAgB,+BA0ClB"}
@@ -1,20 +1,22 @@
1
- 'use client';
2
1
  import { _ as _extends } from "@swc/helpers/_/_extends";
3
2
  import { _ as _object_without_properties_loose } from "@swc/helpers/_/_object_without_properties_loose";
4
3
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
5
- import { useT } from '../../../i18n/index.js';
6
4
  import { cn } from '../../utils/cn.js';
7
- /** How a breadcrumb link looks, wherever it is rendered from. */ const LINK_CLASS = 'focus-ring rounded-sm hover:text-content hover:underline';
8
- /** Accessible breadcrumb trail. Presentational only — no routing knowledge. */ export function Breadcrumbs(_0) {
9
- let { items, separator = '/', renderLink, className } = _0, props = _object_without_properties_loose(_0, [
5
+ /** How a breadcrumb link looks, wherever it is rendered from. */ const LINK_CLASS = 'focus-ring inline-flex min-h-(--target-min) min-w-(--target-min) items-center justify-center rounded-sm hover:text-content hover:underline';
6
+ /**
7
+ * Accessible breadcrumb trail. Presentational only — no routing knowledge, and
8
+ * no hooks: every label arrives as a prop, so a server component renders it
9
+ * and a storefront never pays a client boundary for its trail.
10
+ */ export function Breadcrumbs(_0) {
11
+ let { items, label = 'Breadcrumb', separator = '/', renderLink, className } = _0, props = _object_without_properties_loose(_0, [
10
12
  "items",
13
+ "label",
11
14
  "separator",
12
15
  "renderLink",
13
16
  "className"
14
17
  ]);
15
- const t = useT();
16
18
  return /*#__PURE__*/ _jsx("nav", _extends({
17
- "aria-label": t('breadcrumbs.label'),
19
+ "aria-label": label,
18
20
  className: cn('text-step-sm text-content-muted', className)
19
21
  }, props, {
20
22
  children: /*#__PURE__*/ _jsx("ol", {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/ui/molecules/breadcrumbs/breadcrumbs.tsx"],"sourcesContent":["'use client';\n\nimport type { ComponentPropsWithoutRef, ReactNode } from 'react';\n\nimport { useT } from '../../../i18n/index.js';\nimport { cn } from '../../utils/cn.js';\n\nexport interface BreadcrumbItem {\n label: string;\n href?: string;\n}\n\nexport interface BreadcrumbsProps extends Omit<\n ComponentPropsWithoutRef<'nav'>,\n 'children'\n> {\n items: BreadcrumbItem[];\n /** Glyph between crumbs. */\n separator?: ReactNode;\n /**\n * Optional custom link renderer for a crumb that has an `href` and is not the\n * last one — lets a Next shell inject `<Link>` for client-side navigation.\n * Falls back to a plain `<a>`.\n */\n /**\n * Routing escape hatch. It receives `className` alongside the item and must\n * spread it onto whatever it renders — the design system owns how a\n * breadcrumb link looks, including its focus ring, and a host that supplied\n * only an href silently lost both.\n */\n renderLink?: (\n item: Required<BreadcrumbItem> & { className: string },\n ) => ReactNode;\n}\n\n/** How a breadcrumb link looks, wherever it is rendered from. */\nconst LINK_CLASS = 'focus-ring rounded-sm hover:text-content hover:underline';\n\n/** Accessible breadcrumb trail. Presentational only — no routing knowledge. */\nexport function Breadcrumbs({\n items,\n separator = '/',\n renderLink,\n className,\n ...props\n}: BreadcrumbsProps) {\n const t = useT();\n\n return (\n <nav\n aria-label={t('breadcrumbs.label')}\n className={cn('text-step-sm text-content-muted', className)}\n {...props}\n >\n <ol className=\"flex flex-wrap items-center gap-2xs\">\n {items.map((item, index) => {\n const isLast = index === items.length - 1;\n const linkable = item.href !== undefined && !isLast;\n return (\n <li\n key={`${item.label}-${index}`}\n className=\"flex items-center gap-2xs\"\n >\n {linkable ? (\n renderLink ? (\n renderLink({\n ...(item as Required<BreadcrumbItem>),\n className: LINK_CLASS,\n })\n ) : (\n <a href={item.href} className={LINK_CLASS}>\n {item.label}\n </a>\n )\n ) : (\n <span\n aria-current={isLast ? 'page' : undefined}\n className={cn(isLast && 'font-medium text-content')}\n >\n {item.label}\n </span>\n )}\n {!isLast && <span aria-hidden=\"true\">{separator}</span>}\n </li>\n );\n })}\n </ol>\n </nav>\n );\n}\n"],"names":["useT","cn","LINK_CLASS","Breadcrumbs","items","separator","renderLink","className","props","t","nav","aria-label","ol","map","item","index","isLast","length","linkable","href","undefined","li","a","label","span","aria-current","aria-hidden"],"mappings":"AAAA;;;;AAIA,SAASA,IAAI,QAAQ,yBAAyB;AAC9C,SAASC,EAAE,QAAQ,oBAAoB;AA8BvC,+DAA+D,GAC/D,MAAMC,aAAa;AAEnB,6EAA6E,GAC7E,OAAO,SAASC,YAAY,EAMT;QANS,EAC1BC,KAAK,EACLC,YAAY,GAAG,EACfC,UAAU,EACVC,SAAS,EAEQ,OADdC;;;;;;IAEH,MAAMC,IAAIT;IAEV,qBACE,KAACU;QACCC,cAAYF,EAAE;QACdF,WAAWN,GAAG,mCAAmCM;OAC7CC;kBAEJ,cAAA,KAACI;YAAGL,WAAU;sBACXH,MAAMS,GAAG,CAAC,CAACC,MAAMC;gBAChB,MAAMC,SAASD,UAAUX,MAAMa,MAAM,GAAG;gBACxC,MAAMC,WAAWJ,KAAKK,IAAI,KAAKC,aAAa,CAACJ;gBAC7C,qBACE,MAACK;oBAECd,WAAU;;wBAETW,WACCZ,aACEA,WAAW,aACLQ;4BACJP,WAAWL;4CAGb,KAACoB;4BAAEH,MAAML,KAAKK,IAAI;4BAAEZ,WAAWL;sCAC5BY,KAAKS,KAAK;2CAIf,KAACC;4BACCC,gBAAcT,SAAS,SAASI;4BAChCb,WAAWN,GAAGe,UAAU;sCAEvBF,KAAKS,KAAK;;wBAGd,CAACP,wBAAU,KAACQ;4BAAKE,eAAY;sCAAQrB;;;mBAtBjC,GAAGS,KAAKS,KAAK,CAAC,CAAC,EAAER,OAAO;YAyBnC;;;AAIR"}
1
+ {"version":3,"sources":["../../../../src/ui/molecules/breadcrumbs/breadcrumbs.tsx"],"sourcesContent":["import type { ComponentPropsWithoutRef, ReactNode } from 'react';\n\nimport { cn } from '../../utils/cn.js';\n\nexport interface BreadcrumbItem {\n label: string;\n href?: string;\n}\n\nexport interface BreadcrumbsProps extends Omit<\n ComponentPropsWithoutRef<'nav'>,\n 'children'\n> {\n items: BreadcrumbItem[];\n /**\n * The trail's accessible name. English when omitted; a host with a catalog\n * passes its own (the controls catalog's `breadcrumbs.label`).\n */\n label?: string;\n /** Glyph between crumbs. */\n separator?: ReactNode;\n /**\n * Optional custom link renderer for a crumb that has an `href` and is not the\n * last one — lets a Next shell inject `<Link>` for client-side navigation.\n * Falls back to a plain `<a>`.\n */\n /**\n * Routing escape hatch. It receives `className` alongside the item and must\n * spread it onto whatever it renders — the design system owns how a\n * breadcrumb link looks, including its focus ring, and a host that supplied\n * only an href silently lost both.\n */\n renderLink?: (\n item: Required<BreadcrumbItem> & { className: string },\n ) => ReactNode;\n}\n\n/** How a breadcrumb link looks, wherever it is rendered from. */\nconst LINK_CLASS =\n 'focus-ring inline-flex min-h-(--target-min) min-w-(--target-min) items-center justify-center rounded-sm hover:text-content hover:underline';\n\n/**\n * Accessible breadcrumb trail. Presentational only — no routing knowledge, and\n * no hooks: every label arrives as a prop, so a server component renders it\n * and a storefront never pays a client boundary for its trail.\n */\nexport function Breadcrumbs({\n items,\n label = 'Breadcrumb',\n separator = '/',\n renderLink,\n className,\n ...props\n}: BreadcrumbsProps) {\n return (\n <nav\n aria-label={label}\n className={cn('text-step-sm text-content-muted', className)}\n {...props}\n >\n <ol className=\"flex flex-wrap items-center gap-2xs\">\n {items.map((item, index) => {\n const isLast = index === items.length - 1;\n const linkable = item.href !== undefined && !isLast;\n return (\n <li\n key={`${item.label}-${index}`}\n className=\"flex items-center gap-2xs\"\n >\n {linkable ? (\n renderLink ? (\n renderLink({\n ...(item as Required<BreadcrumbItem>),\n className: LINK_CLASS,\n })\n ) : (\n <a href={item.href} className={LINK_CLASS}>\n {item.label}\n </a>\n )\n ) : (\n <span\n aria-current={isLast ? 'page' : undefined}\n className={cn(isLast && 'font-medium text-content')}\n >\n {item.label}\n </span>\n )}\n {!isLast && <span aria-hidden=\"true\">{separator}</span>}\n </li>\n );\n })}\n </ol>\n </nav>\n );\n}\n"],"names":["cn","LINK_CLASS","Breadcrumbs","items","label","separator","renderLink","className","props","nav","aria-label","ol","map","item","index","isLast","length","linkable","href","undefined","li","a","span","aria-current","aria-hidden"],"mappings":";;;AAEA,SAASA,EAAE,QAAQ,oBAAoB;AAmCvC,+DAA+D,GAC/D,MAAMC,aACJ;AAEF;;;;CAIC,GACD,OAAO,SAASC,YAAY,EAOT;QAPS,EAC1BC,KAAK,EACLC,QAAQ,YAAY,EACpBC,YAAY,GAAG,EACfC,UAAU,EACVC,SAAS,EAEQ,OADdC;;;;;;;IAEH,qBACE,KAACC;QACCC,cAAYN;QACZG,WAAWP,GAAG,mCAAmCO;OAC7CC;kBAEJ,cAAA,KAACG;YAAGJ,WAAU;sBACXJ,MAAMS,GAAG,CAAC,CAACC,MAAMC;gBAChB,MAAMC,SAASD,UAAUX,MAAMa,MAAM,GAAG;gBACxC,MAAMC,WAAWJ,KAAKK,IAAI,KAAKC,aAAa,CAACJ;gBAC7C,qBACE,MAACK;oBAECb,WAAU;;wBAETU,WACCX,aACEA,WAAW,aACLO;4BACJN,WAAWN;4CAGb,KAACoB;4BAAEH,MAAML,KAAKK,IAAI;4BAAEX,WAAWN;sCAC5BY,KAAKT,KAAK;2CAIf,KAACkB;4BACCC,gBAAcR,SAAS,SAASI;4BAChCZ,WAAWP,GAAGe,UAAU;sCAEvBF,KAAKT,KAAK;;wBAGd,CAACW,wBAAU,KAACO;4BAAKE,eAAY;sCAAQnB;;;mBAtBjC,GAAGQ,KAAKT,KAAK,CAAC,CAAC,EAAEU,OAAO;YAyBnC;;;AAIR"}
@@ -52,7 +52,7 @@ function move(names, from, to) {
52
52
  }),
53
53
  /*#__PURE__*/ _jsxs(PopoverPanel, {
54
54
  anchor: "bottom end",
55
- className: "w-64 z-10 mt-3xs rounded-xl border border-border bg-surface-elevated p-2xs shadow-card",
55
+ className: "w-64 z-(--z-dropdown) mt-3xs rounded-xl border border-border bg-surface-elevated p-2xs shadow-card",
56
56
  children: [
57
57
  /*#__PURE__*/ _jsx(Text, {
58
58
  step: -2,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/ui/molecules/column-settings/column-settings.tsx"],"sourcesContent":["'use client';\n\nimport { Popover, PopoverButton, PopoverPanel } from '@headlessui/react';\n\nimport { useT } from '../../../i18n/index.js';\nimport { Button } from '../../atoms/button/index.js';\nimport { Checkbox } from '../../atoms/field/index.js';\nimport { Text } from '../../atoms/text/index.js';\n\n/**\n * The user's column layout for one table. Stored through the UI-preferences\n * port, so it is deliberately plain JSON: names only, no descriptors — a column\n * that disappears from the entity simply stops matching.\n */\nexport interface ColumnPersonalization {\n /** Column names, most-significant first. Unlisted columns keep their default\n * position at the end, so a new entity member never breaks a saved layout. */\n order?: string[];\n /** Column names the user hid. */\n hidden?: string[];\n}\n\nexport interface ColumnSettingsColumn {\n name: string;\n label: string;\n}\n\nexport interface ColumnSettingsProps {\n /** Columns in their currently resolved order. */\n columns: readonly ColumnSettingsColumn[];\n hidden: readonly string[];\n onChange: (next: ColumnPersonalization) => void;\n}\n\nfunction move(names: readonly string[], from: number, to: number): string[] {\n const next = [...names];\n const [moved] = next.splice(from, 1);\n next.splice(to, 0, moved);\n return next;\n}\n\n/**\n * Popover for reordering and hiding columns. Reordering uses explicit up/down\n * buttons rather than drag-and-drop: it needs no dependency, works on touch, and\n * is keyboard-operable for free.\n */\nexport function ColumnSettings({\n columns,\n hidden,\n onChange,\n}: ColumnSettingsProps) {\n const order = columns.map(column => column.name);\n\n const toggle = (name: string) =>\n onChange({\n order,\n hidden: hidden.includes(name)\n ? hidden.filter(entry => entry !== name)\n : [...hidden, name],\n });\n\n const t = useT();\n\n const shift = (index: number, delta: number) => {\n const target = index + delta;\n // Defence in depth: the buttons are already disabled at both ends, so this\n // is unreachable through the UI — but an out-of-range splice would silently\n // corrupt the order rather than no-op.\n /* v8 ignore next */\n if (target < 0 || target >= order.length) return;\n onChange({ order: move(order, index, target), hidden: [...hidden] });\n };\n\n return (\n <Popover className=\"relative\">\n <PopoverButton as={Button} type=\"button\" variant=\"secondary\" size=\"sm\">\n {t('columns.title')}\n </PopoverButton>\n <PopoverPanel\n anchor=\"bottom end\"\n className=\"w-64 z-10 mt-3xs rounded-xl border border-border bg-surface-elevated p-2xs shadow-card\"\n >\n <Text step={-2} tone=\"muted\" className=\"px-3xs pb-3xs\">\n {t('columns.subtitle')}\n </Text>\n <ul className=\"flex flex-col gap-3xs\">\n {columns.map((column, index) => (\n <li\n key={column.name}\n className=\"flex items-center justify-between gap-2xs px-3xs\"\n >\n <Checkbox\n label={column.label}\n checked={!hidden.includes(column.name)}\n onChange={() => toggle(column.name)}\n />\n <span className=\"flex gap-3xs\">\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n aria-label={t('columns.moveUp', { column: column.label })}\n disabled={index === 0}\n onClick={() => shift(index, -1)}\n >\n ↑\n </Button>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n aria-label={t('columns.moveDown', { column: column.label })}\n disabled={index === columns.length - 1}\n onClick={() => shift(index, 1)}\n >\n ↓\n </Button>\n </span>\n </li>\n ))}\n </ul>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n className=\"mt-2xs w-full\"\n onClick={() => onChange({})}\n >\n {t('columns.reset')}\n </Button>\n </PopoverPanel>\n </Popover>\n );\n}\n"],"names":["Popover","PopoverButton","PopoverPanel","useT","Button","Checkbox","Text","move","names","from","to","next","moved","splice","ColumnSettings","columns","hidden","onChange","order","map","column","name","toggle","includes","filter","entry","t","shift","index","delta","target","length","className","as","type","variant","size","anchor","step","tone","ul","li","label","checked","span","aria-label","disabled","onClick"],"mappings":"AAAA;;AAEA,SAASA,OAAO,EAAEC,aAAa,EAAEC,YAAY,QAAQ,oBAAoB;AAEzE,SAASC,IAAI,QAAQ,yBAAyB;AAC9C,SAASC,MAAM,QAAQ,8BAA8B;AACrD,SAASC,QAAQ,QAAQ,6BAA6B;AACtD,SAASC,IAAI,QAAQ,4BAA4B;AA2BjD,SAASC,KAAKC,KAAwB,EAAEC,IAAY,EAAEC,EAAU;IAC9D,MAAMC,OAAO;WAAIH;KAAM;IACvB,MAAM,CAACI,MAAM,GAAGD,KAAKE,MAAM,CAACJ,MAAM;IAClCE,KAAKE,MAAM,CAACH,IAAI,GAAGE;IACnB,OAAOD;AACT;AAEA;;;;CAIC,GACD,OAAO,SAASG,eAAe,EAC7BC,OAAO,EACPC,MAAM,EACNC,QAAQ,EACY;IACpB,MAAMC,QAAQH,QAAQI,GAAG,CAACC,CAAAA,SAAUA,OAAOC,IAAI;IAE/C,MAAMC,SAAS,CAACD,OACdJ,SAAS;YACPC;YACAF,QAAQA,OAAOO,QAAQ,CAACF,QACpBL,OAAOQ,MAAM,CAACC,CAAAA,QAASA,UAAUJ,QACjC;mBAAIL;gBAAQK;aAAK;QACvB;IAEF,MAAMK,IAAIvB;IAEV,MAAMwB,QAAQ,CAACC,OAAeC;QAC5B,MAAMC,SAASF,QAAQC;QACvB,2EAA2E;QAC3E,4EAA4E;QAC5E,uCAAuC;QACvC,kBAAkB,GAClB,IAAIC,SAAS,KAAKA,UAAUZ,MAAMa,MAAM,EAAE;QAC1Cd,SAAS;YAAEC,OAAOX,KAAKW,OAAOU,OAAOE;YAASd,QAAQ;mBAAIA;aAAO;QAAC;IACpE;IAEA,qBACE,MAAChB;QAAQgC,WAAU;;0BACjB,KAAC/B;gBAAcgC,IAAI7B;gBAAQ8B,MAAK;gBAASC,SAAQ;gBAAYC,MAAK;0BAC/DV,EAAE;;0BAEL,MAACxB;gBACCmC,QAAO;gBACPL,WAAU;;kCAEV,KAAC1B;wBAAKgC,MAAM,CAAC;wBAAGC,MAAK;wBAAQP,WAAU;kCACpCN,EAAE;;kCAEL,KAACc;wBAAGR,WAAU;kCACXjB,QAAQI,GAAG,CAAC,CAACC,QAAQQ,sBACpB,MAACa;gCAECT,WAAU;;kDAEV,KAAC3B;wCACCqC,OAAOtB,OAAOsB,KAAK;wCACnBC,SAAS,CAAC3B,OAAOO,QAAQ,CAACH,OAAOC,IAAI;wCACrCJ,UAAU,IAAMK,OAAOF,OAAOC,IAAI;;kDAEpC,MAACuB;wCAAKZ,WAAU;;0DACd,KAAC5B;gDACC8B,MAAK;gDACLC,SAAQ;gDACRC,MAAK;gDACLS,cAAYnB,EAAE,kBAAkB;oDAAEN,QAAQA,OAAOsB,KAAK;gDAAC;gDACvDI,UAAUlB,UAAU;gDACpBmB,SAAS,IAAMpB,MAAMC,OAAO,CAAC;0DAC9B;;0DAGD,KAACxB;gDACC8B,MAAK;gDACLC,SAAQ;gDACRC,MAAK;gDACLS,cAAYnB,EAAE,oBAAoB;oDAAEN,QAAQA,OAAOsB,KAAK;gDAAC;gDACzDI,UAAUlB,UAAUb,QAAQgB,MAAM,GAAG;gDACrCgB,SAAS,IAAMpB,MAAMC,OAAO;0DAC7B;;;;;+BA1BER,OAAOC,IAAI;;kCAiCtB,KAACjB;wBACC8B,MAAK;wBACLC,SAAQ;wBACRC,MAAK;wBACLJ,WAAU;wBACVe,SAAS,IAAM9B,SAAS,CAAC;kCAExBS,EAAE;;;;;;AAKb"}
1
+ {"version":3,"sources":["../../../../src/ui/molecules/column-settings/column-settings.tsx"],"sourcesContent":["'use client';\n\nimport { Popover, PopoverButton, PopoverPanel } from '@headlessui/react';\n\nimport { useT } from '../../../i18n/index.js';\nimport { Button } from '../../atoms/button/index.js';\nimport { Checkbox } from '../../atoms/field/index.js';\nimport { Text } from '../../atoms/text/index.js';\n\n/**\n * The user's column layout for one table. Stored through the UI-preferences\n * port, so it is deliberately plain JSON: names only, no descriptors — a column\n * that disappears from the entity simply stops matching.\n */\nexport interface ColumnPersonalization {\n /** Column names, most-significant first. Unlisted columns keep their default\n * position at the end, so a new entity member never breaks a saved layout. */\n order?: string[];\n /** Column names the user hid. */\n hidden?: string[];\n}\n\nexport interface ColumnSettingsColumn {\n name: string;\n label: string;\n}\n\nexport interface ColumnSettingsProps {\n /** Columns in their currently resolved order. */\n columns: readonly ColumnSettingsColumn[];\n hidden: readonly string[];\n onChange: (next: ColumnPersonalization) => void;\n}\n\nfunction move(names: readonly string[], from: number, to: number): string[] {\n const next = [...names];\n const [moved] = next.splice(from, 1);\n next.splice(to, 0, moved);\n return next;\n}\n\n/**\n * Popover for reordering and hiding columns. Reordering uses explicit up/down\n * buttons rather than drag-and-drop: it needs no dependency, works on touch, and\n * is keyboard-operable for free.\n */\nexport function ColumnSettings({\n columns,\n hidden,\n onChange,\n}: ColumnSettingsProps) {\n const order = columns.map(column => column.name);\n\n const toggle = (name: string) =>\n onChange({\n order,\n hidden: hidden.includes(name)\n ? hidden.filter(entry => entry !== name)\n : [...hidden, name],\n });\n\n const t = useT();\n\n const shift = (index: number, delta: number) => {\n const target = index + delta;\n // Defence in depth: the buttons are already disabled at both ends, so this\n // is unreachable through the UI — but an out-of-range splice would silently\n // corrupt the order rather than no-op.\n /* v8 ignore next */\n if (target < 0 || target >= order.length) return;\n onChange({ order: move(order, index, target), hidden: [...hidden] });\n };\n\n return (\n <Popover className=\"relative\">\n <PopoverButton as={Button} type=\"button\" variant=\"secondary\" size=\"sm\">\n {t('columns.title')}\n </PopoverButton>\n <PopoverPanel\n anchor=\"bottom end\"\n className=\"w-64 z-(--z-dropdown) mt-3xs rounded-xl border border-border bg-surface-elevated p-2xs shadow-card\"\n >\n <Text step={-2} tone=\"muted\" className=\"px-3xs pb-3xs\">\n {t('columns.subtitle')}\n </Text>\n <ul className=\"flex flex-col gap-3xs\">\n {columns.map((column, index) => (\n <li\n key={column.name}\n className=\"flex items-center justify-between gap-2xs px-3xs\"\n >\n <Checkbox\n label={column.label}\n checked={!hidden.includes(column.name)}\n onChange={() => toggle(column.name)}\n />\n <span className=\"flex gap-3xs\">\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n aria-label={t('columns.moveUp', { column: column.label })}\n disabled={index === 0}\n onClick={() => shift(index, -1)}\n >\n ↑\n </Button>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n aria-label={t('columns.moveDown', { column: column.label })}\n disabled={index === columns.length - 1}\n onClick={() => shift(index, 1)}\n >\n ↓\n </Button>\n </span>\n </li>\n ))}\n </ul>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n className=\"mt-2xs w-full\"\n onClick={() => onChange({})}\n >\n {t('columns.reset')}\n </Button>\n </PopoverPanel>\n </Popover>\n );\n}\n"],"names":["Popover","PopoverButton","PopoverPanel","useT","Button","Checkbox","Text","move","names","from","to","next","moved","splice","ColumnSettings","columns","hidden","onChange","order","map","column","name","toggle","includes","filter","entry","t","shift","index","delta","target","length","className","as","type","variant","size","anchor","step","tone","ul","li","label","checked","span","aria-label","disabled","onClick"],"mappings":"AAAA;;AAEA,SAASA,OAAO,EAAEC,aAAa,EAAEC,YAAY,QAAQ,oBAAoB;AAEzE,SAASC,IAAI,QAAQ,yBAAyB;AAC9C,SAASC,MAAM,QAAQ,8BAA8B;AACrD,SAASC,QAAQ,QAAQ,6BAA6B;AACtD,SAASC,IAAI,QAAQ,4BAA4B;AA2BjD,SAASC,KAAKC,KAAwB,EAAEC,IAAY,EAAEC,EAAU;IAC9D,MAAMC,OAAO;WAAIH;KAAM;IACvB,MAAM,CAACI,MAAM,GAAGD,KAAKE,MAAM,CAACJ,MAAM;IAClCE,KAAKE,MAAM,CAACH,IAAI,GAAGE;IACnB,OAAOD;AACT;AAEA;;;;CAIC,GACD,OAAO,SAASG,eAAe,EAC7BC,OAAO,EACPC,MAAM,EACNC,QAAQ,EACY;IACpB,MAAMC,QAAQH,QAAQI,GAAG,CAACC,CAAAA,SAAUA,OAAOC,IAAI;IAE/C,MAAMC,SAAS,CAACD,OACdJ,SAAS;YACPC;YACAF,QAAQA,OAAOO,QAAQ,CAACF,QACpBL,OAAOQ,MAAM,CAACC,CAAAA,QAASA,UAAUJ,QACjC;mBAAIL;gBAAQK;aAAK;QACvB;IAEF,MAAMK,IAAIvB;IAEV,MAAMwB,QAAQ,CAACC,OAAeC;QAC5B,MAAMC,SAASF,QAAQC;QACvB,2EAA2E;QAC3E,4EAA4E;QAC5E,uCAAuC;QACvC,kBAAkB,GAClB,IAAIC,SAAS,KAAKA,UAAUZ,MAAMa,MAAM,EAAE;QAC1Cd,SAAS;YAAEC,OAAOX,KAAKW,OAAOU,OAAOE;YAASd,QAAQ;mBAAIA;aAAO;QAAC;IACpE;IAEA,qBACE,MAAChB;QAAQgC,WAAU;;0BACjB,KAAC/B;gBAAcgC,IAAI7B;gBAAQ8B,MAAK;gBAASC,SAAQ;gBAAYC,MAAK;0BAC/DV,EAAE;;0BAEL,MAACxB;gBACCmC,QAAO;gBACPL,WAAU;;kCAEV,KAAC1B;wBAAKgC,MAAM,CAAC;wBAAGC,MAAK;wBAAQP,WAAU;kCACpCN,EAAE;;kCAEL,KAACc;wBAAGR,WAAU;kCACXjB,QAAQI,GAAG,CAAC,CAACC,QAAQQ,sBACpB,MAACa;gCAECT,WAAU;;kDAEV,KAAC3B;wCACCqC,OAAOtB,OAAOsB,KAAK;wCACnBC,SAAS,CAAC3B,OAAOO,QAAQ,CAACH,OAAOC,IAAI;wCACrCJ,UAAU,IAAMK,OAAOF,OAAOC,IAAI;;kDAEpC,MAACuB;wCAAKZ,WAAU;;0DACd,KAAC5B;gDACC8B,MAAK;gDACLC,SAAQ;gDACRC,MAAK;gDACLS,cAAYnB,EAAE,kBAAkB;oDAAEN,QAAQA,OAAOsB,KAAK;gDAAC;gDACvDI,UAAUlB,UAAU;gDACpBmB,SAAS,IAAMpB,MAAMC,OAAO,CAAC;0DAC9B;;0DAGD,KAACxB;gDACC8B,MAAK;gDACLC,SAAQ;gDACRC,MAAK;gDACLS,cAAYnB,EAAE,oBAAoB;oDAAEN,QAAQA,OAAOsB,KAAK;gDAAC;gDACzDI,UAAUlB,UAAUb,QAAQgB,MAAM,GAAG;gDACrCgB,SAAS,IAAMpB,MAAMC,OAAO;0DAC7B;;;;;+BA1BER,OAAOC,IAAI;;kCAiCtB,KAACjB;wBACC8B,MAAK;wBACLC,SAAQ;wBACRC,MAAK;wBACLJ,WAAU;wBACVe,SAAS,IAAM9B,SAAS,CAAC;kCAExBS,EAAE;;;;;;AAKb"}
@@ -22,11 +22,11 @@ import { Button } from '../../atoms/button/index.js';
22
22
  return /*#__PURE__*/ _jsxs(Dialog, {
23
23
  open: open,
24
24
  onClose: onCancel,
25
- className: "inset-0 fixed z-50 flex items-center justify-center overflow-y-auto p-s",
25
+ className: "inset-0 fixed z-(--z-overlay) flex items-center justify-center overflow-y-auto p-s",
26
26
  children: [
27
27
  /*#__PURE__*/ _jsx("div", {
28
28
  "aria-hidden": true,
29
- className: "inset-0 bg-black/40 fixed"
29
+ className: "inset-0 fixed bg-scrim"
30
30
  }),
31
31
  /*#__PURE__*/ _jsxs(DialogPanel, {
32
32
  "data-testid": "confirm-dialog",
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/ui/molecules/confirm-dialog/confirm-dialog.tsx"],"sourcesContent":["'use client';\n\nimport { Dialog, DialogPanel, DialogTitle } from '@headlessui/react';\n\nimport { useT } from '../../../i18n/index.js';\nimport { Button } from '../../atoms/button/index.js';\n\nexport type ConfirmTone = 'destructive' | 'neutral';\n\nexport interface ConfirmDialogProps {\n open: boolean;\n /** Already-resolved copy — this control renders text, it does not translate. */\n title: string;\n message: string;\n /** `destructive` paints the confirm button in the danger tokens. */\n tone?: ConfirmTone;\n confirmLabel?: string;\n cancelLabel?: string;\n busy?: boolean;\n onConfirm: () => void;\n onCancel: () => void;\n}\n\n/**\n * Asks before an irreversible act.\n *\n * It exists because a use-case descriptor may carry\n * `confirm: { tone, messageKey }`, and a surface that renders such a descriptor\n * without asking would fire the act on the first click — `revoke-sessions` ends\n * every session a user holds. The descriptor names the tone and the message key;\n * resolving that key is the caller's job, so this control stays copy-free apart\n * from its own two buttons.\n *\n * The dialog element fills the viewport rather than wrapping a `fixed` child in\n * a `relative` box, for the reason `EntityLinkPicker` records: a zero-sized\n * dialog is invisible to anything that measures it — assistive tech and\n * Playwright alike — even with a painted panel inside.\n */\nexport function ConfirmDialog({\n open,\n title,\n message,\n tone = 'neutral',\n confirmLabel,\n cancelLabel,\n busy = false,\n onConfirm,\n onCancel,\n}: ConfirmDialogProps) {\n const t = useT();\n\n return (\n <Dialog\n open={open}\n onClose={onCancel}\n className=\"inset-0 fixed z-50 flex items-center justify-center overflow-y-auto p-s\"\n >\n <div aria-hidden className=\"inset-0 bg-black/40 fixed\" />\n <DialogPanel\n data-testid=\"confirm-dialog\"\n className=\"max-w-md relative w-full rounded-lg border border-border bg-surface p-s shadow-overlay\"\n >\n <DialogTitle className=\"text-step-1 font-semibold text-content\">\n {title}\n </DialogTitle>\n <p className=\"mt-2xs text-step-sm text-content-muted\">{message}</p>\n <div className=\"mt-s flex justify-end gap-xs\">\n <Button\n type=\"button\"\n variant=\"ghost\"\n onClick={onCancel}\n disabled={busy}\n >\n {cancelLabel ?? t('confirm.cancel')}\n </Button>\n <Button\n type=\"button\"\n variant={tone === 'destructive' ? 'destructive' : 'primary'}\n onClick={onConfirm}\n disabled={busy}\n >\n {confirmLabel ?? t('confirm.confirm')}\n </Button>\n </div>\n </DialogPanel>\n </Dialog>\n );\n}\n"],"names":["Dialog","DialogPanel","DialogTitle","useT","Button","ConfirmDialog","open","title","message","tone","confirmLabel","cancelLabel","busy","onConfirm","onCancel","t","onClose","className","div","aria-hidden","data-testid","p","type","variant","onClick","disabled"],"mappings":"AAAA;;AAEA,SAASA,MAAM,EAAEC,WAAW,EAAEC,WAAW,QAAQ,oBAAoB;AAErE,SAASC,IAAI,QAAQ,yBAAyB;AAC9C,SAASC,MAAM,QAAQ,8BAA8B;AAkBrD;;;;;;;;;;;;;;CAcC,GACD,OAAO,SAASC,cAAc,EAC5BC,IAAI,EACJC,KAAK,EACLC,OAAO,EACPC,OAAO,SAAS,EAChBC,YAAY,EACZC,WAAW,EACXC,OAAO,KAAK,EACZC,SAAS,EACTC,QAAQ,EACW;IACnB,MAAMC,IAAIZ;IAEV,qBACE,MAACH;QACCM,MAAMA;QACNU,SAASF;QACTG,WAAU;;0BAEV,KAACC;gBAAIC,aAAW;gBAACF,WAAU;;0BAC3B,MAAChB;gBACCmB,eAAY;gBACZH,WAAU;;kCAEV,KAACf;wBAAYe,WAAU;kCACpBV;;kCAEH,KAACc;wBAAEJ,WAAU;kCAA0CT;;kCACvD,MAACU;wBAAID,WAAU;;0CACb,KAACb;gCACCkB,MAAK;gCACLC,SAAQ;gCACRC,SAASV;gCACTW,UAAUb;0CAETD,sBAAAA,cAAeI,EAAE;;0CAEpB,KAACX;gCACCkB,MAAK;gCACLC,SAASd,SAAS,gBAAgB,gBAAgB;gCAClDe,SAASX;gCACTY,UAAUb;0CAETF,uBAAAA,eAAgBK,EAAE;;;;;;;;AAM/B"}
1
+ {"version":3,"sources":["../../../../src/ui/molecules/confirm-dialog/confirm-dialog.tsx"],"sourcesContent":["'use client';\n\nimport { Dialog, DialogPanel, DialogTitle } from '@headlessui/react';\n\nimport { useT } from '../../../i18n/index.js';\nimport { Button } from '../../atoms/button/index.js';\n\nexport type ConfirmTone = 'destructive' | 'neutral';\n\nexport interface ConfirmDialogProps {\n open: boolean;\n /** Already-resolved copy — this control renders text, it does not translate. */\n title: string;\n message: string;\n /** `destructive` paints the confirm button in the danger tokens. */\n tone?: ConfirmTone;\n confirmLabel?: string;\n cancelLabel?: string;\n busy?: boolean;\n onConfirm: () => void;\n onCancel: () => void;\n}\n\n/**\n * Asks before an irreversible act.\n *\n * It exists because a use-case descriptor may carry\n * `confirm: { tone, messageKey }`, and a surface that renders such a descriptor\n * without asking would fire the act on the first click — `revoke-sessions` ends\n * every session a user holds. The descriptor names the tone and the message key;\n * resolving that key is the caller's job, so this control stays copy-free apart\n * from its own two buttons.\n *\n * The dialog element fills the viewport rather than wrapping a `fixed` child in\n * a `relative` box, for the reason `EntityLinkPicker` records: a zero-sized\n * dialog is invisible to anything that measures it — assistive tech and\n * Playwright alike — even with a painted panel inside.\n */\nexport function ConfirmDialog({\n open,\n title,\n message,\n tone = 'neutral',\n confirmLabel,\n cancelLabel,\n busy = false,\n onConfirm,\n onCancel,\n}: ConfirmDialogProps) {\n const t = useT();\n\n return (\n <Dialog\n open={open}\n onClose={onCancel}\n className=\"inset-0 fixed z-(--z-overlay) flex items-center justify-center overflow-y-auto p-s\"\n >\n <div aria-hidden className=\"inset-0 fixed bg-scrim\" />\n <DialogPanel\n data-testid=\"confirm-dialog\"\n className=\"max-w-md relative w-full rounded-lg border border-border bg-surface p-s shadow-overlay\"\n >\n <DialogTitle className=\"text-step-1 font-semibold text-content\">\n {title}\n </DialogTitle>\n <p className=\"mt-2xs text-step-sm text-content-muted\">{message}</p>\n <div className=\"mt-s flex justify-end gap-xs\">\n <Button\n type=\"button\"\n variant=\"ghost\"\n onClick={onCancel}\n disabled={busy}\n >\n {cancelLabel ?? t('confirm.cancel')}\n </Button>\n <Button\n type=\"button\"\n variant={tone === 'destructive' ? 'destructive' : 'primary'}\n onClick={onConfirm}\n disabled={busy}\n >\n {confirmLabel ?? t('confirm.confirm')}\n </Button>\n </div>\n </DialogPanel>\n </Dialog>\n );\n}\n"],"names":["Dialog","DialogPanel","DialogTitle","useT","Button","ConfirmDialog","open","title","message","tone","confirmLabel","cancelLabel","busy","onConfirm","onCancel","t","onClose","className","div","aria-hidden","data-testid","p","type","variant","onClick","disabled"],"mappings":"AAAA;;AAEA,SAASA,MAAM,EAAEC,WAAW,EAAEC,WAAW,QAAQ,oBAAoB;AAErE,SAASC,IAAI,QAAQ,yBAAyB;AAC9C,SAASC,MAAM,QAAQ,8BAA8B;AAkBrD;;;;;;;;;;;;;;CAcC,GACD,OAAO,SAASC,cAAc,EAC5BC,IAAI,EACJC,KAAK,EACLC,OAAO,EACPC,OAAO,SAAS,EAChBC,YAAY,EACZC,WAAW,EACXC,OAAO,KAAK,EACZC,SAAS,EACTC,QAAQ,EACW;IACnB,MAAMC,IAAIZ;IAEV,qBACE,MAACH;QACCM,MAAMA;QACNU,SAASF;QACTG,WAAU;;0BAEV,KAACC;gBAAIC,aAAW;gBAACF,WAAU;;0BAC3B,MAAChB;gBACCmB,eAAY;gBACZH,WAAU;;kCAEV,KAACf;wBAAYe,WAAU;kCACpBV;;kCAEH,KAACc;wBAAEJ,WAAU;kCAA0CT;;kCACvD,MAACU;wBAAID,WAAU;;0CACb,KAACb;gCACCkB,MAAK;gCACLC,SAAQ;gCACRC,SAASV;gCACTW,UAAUb;0CAETD,sBAAAA,cAAeI,EAAE;;0CAEpB,KAACX;gCACCkB,MAAK;gCACLC,SAASd,SAAS,gBAAgB,gBAAgB;gCAClDe,SAASX;gCACTY,UAAUb;0CAETF,uBAAAA,eAAgBK,EAAE;;;;;;;;AAM/B"}
@@ -0,0 +1,17 @@
1
+ import type { ComponentPropsWithoutRef, ReactNode } from 'react';
2
+ export interface DescriptionListItem {
3
+ /** A stable key; the term itself when it is unique. */
4
+ readonly key?: string;
5
+ readonly term: ReactNode;
6
+ readonly description: ReactNode;
7
+ }
8
+ export interface DescriptionListProps extends Omit<ComponentPropsWithoutRef<'dl'>, 'children'> {
9
+ items: readonly DescriptionListItem[];
10
+ }
11
+ /**
12
+ * Terms and what they are — a record's facts, a product's specifications —
13
+ * as a real `<dl>`, so each value is announced with the term it belongs to.
14
+ * Two columns where there is room, stacked where there is not. Server-safe.
15
+ */
16
+ export declare function DescriptionList({ items, className, ...props }: DescriptionListProps): import("react").JSX.Element;
17
+ //# sourceMappingURL=description-list.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"description-list.d.ts","sourceRoot":"","sources":["../../../../src/ui/molecules/description-list/description-list.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,wBAAwB,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAIjE,MAAM,WAAW,mBAAmB;IAClC,uDAAuD;IACvD,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IACzB,QAAQ,CAAC,WAAW,EAAE,SAAS,CAAC;CACjC;AAED,MAAM,WAAW,oBAAqB,SAAQ,IAAI,CAChD,wBAAwB,CAAC,IAAI,CAAC,EAC9B,UAAU,CACX;IACC,KAAK,EAAE,SAAS,mBAAmB,EAAE,CAAC;CACvC;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,EAC9B,KAAK,EACL,SAAS,EACT,GAAG,KAAK,EACT,EAAE,oBAAoB,+BAiBtB"}
@@ -0,0 +1,36 @@
1
+ import { _ as _extends } from "@swc/helpers/_/_extends";
2
+ import { _ as _object_without_properties_loose } from "@swc/helpers/_/_object_without_properties_loose";
3
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
4
+ import { cn } from '../../utils/cn.js';
5
+ /**
6
+ * Terms and what they are — a record's facts, a product's specifications —
7
+ * as a real `<dl>`, so each value is announced with the term it belongs to.
8
+ * Two columns where there is room, stacked where there is not. Server-safe.
9
+ */ export function DescriptionList(_0) {
10
+ let { items, className } = _0, props = _object_without_properties_loose(_0, [
11
+ "items",
12
+ "className"
13
+ ]);
14
+ return /*#__PURE__*/ _jsx("dl", _extends({
15
+ className: cn('m-0 sm:grid-cols-[minmax(0,1fr)_minmax(0,2fr)] grid grid-cols-1 gap-x-m gap-y-2xs text-step-sm', className)
16
+ }, props, {
17
+ children: items.map((item, index)=>{
18
+ var _item_key;
19
+ return /*#__PURE__*/ _jsxs("div", {
20
+ className: "contents",
21
+ children: [
22
+ /*#__PURE__*/ _jsx("dt", {
23
+ className: "font-medium text-content-muted",
24
+ children: item.term
25
+ }),
26
+ /*#__PURE__*/ _jsx("dd", {
27
+ className: "m-0 text-content",
28
+ children: item.description
29
+ })
30
+ ]
31
+ }, (_item_key = item.key) != null ? _item_key : index);
32
+ })
33
+ }));
34
+ }
35
+
36
+ //# sourceMappingURL=description-list.js.map