@ttoss/fsl-ui 0.2.4

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 (174) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +76 -0
  3. package/dist/_virtual/_rolldown/runtime.cjs +30 -0
  4. package/dist/components/Breadcrumbs/Breadcrumbs.cjs +129 -0
  5. package/dist/components/Breadcrumbs/Breadcrumbs.d.cts +61 -0
  6. package/dist/components/Breadcrumbs/Breadcrumbs.d.mts +61 -0
  7. package/dist/components/Breadcrumbs/Breadcrumbs.mjs +126 -0
  8. package/dist/components/Button/Button.cjs +80 -0
  9. package/dist/components/Button/Button.d.cts +68 -0
  10. package/dist/components/Button/Button.d.mts +68 -0
  11. package/dist/components/Button/Button.mjs +79 -0
  12. package/dist/components/Checkbox/Checkbox.cjs +183 -0
  13. package/dist/components/Checkbox/Checkbox.d.cts +45 -0
  14. package/dist/components/Checkbox/Checkbox.d.mts +45 -0
  15. package/dist/components/Checkbox/Checkbox.mjs +182 -0
  16. package/dist/components/CheckboxGroup/CheckboxGroup.cjs +97 -0
  17. package/dist/components/CheckboxGroup/CheckboxGroup.d.cts +56 -0
  18. package/dist/components/CheckboxGroup/CheckboxGroup.d.mts +56 -0
  19. package/dist/components/CheckboxGroup/CheckboxGroup.mjs +96 -0
  20. package/dist/components/FileTrigger/FileTrigger.cjs +51 -0
  21. package/dist/components/FileTrigger/FileTrigger.d.cts +52 -0
  22. package/dist/components/FileTrigger/FileTrigger.d.mts +52 -0
  23. package/dist/components/FileTrigger/FileTrigger.mjs +50 -0
  24. package/dist/components/GridList/GridList.cjs +220 -0
  25. package/dist/components/GridList/GridList.d.cts +72 -0
  26. package/dist/components/GridList/GridList.d.mts +72 -0
  27. package/dist/components/GridList/GridList.mjs +217 -0
  28. package/dist/components/Group/Group.cjs +77 -0
  29. package/dist/components/Group/Group.d.cts +61 -0
  30. package/dist/components/Group/Group.d.mts +61 -0
  31. package/dist/components/Group/Group.mjs +74 -0
  32. package/dist/components/Icon/Icon.cjs +52 -0
  33. package/dist/components/Icon/Icon.mjs +52 -0
  34. package/dist/components/Icon/glyphs.cjs +72 -0
  35. package/dist/components/Icon/glyphs.mjs +63 -0
  36. package/dist/components/Link/Link.cjs +62 -0
  37. package/dist/components/Link/Link.d.cts +38 -0
  38. package/dist/components/Link/Link.d.mts +38 -0
  39. package/dist/components/Link/Link.mjs +61 -0
  40. package/dist/components/ListBox/ListBox.cjs +126 -0
  41. package/dist/components/ListBox/ListBox.d.cts +63 -0
  42. package/dist/components/ListBox/ListBox.d.mts +63 -0
  43. package/dist/components/ListBox/ListBox.mjs +123 -0
  44. package/dist/components/Meter/Meter.cjs +126 -0
  45. package/dist/components/Meter/Meter.d.cts +63 -0
  46. package/dist/components/Meter/Meter.d.mts +63 -0
  47. package/dist/components/Meter/Meter.mjs +125 -0
  48. package/dist/components/NumberField/NumberField.cjs +221 -0
  49. package/dist/components/NumberField/NumberField.d.cts +68 -0
  50. package/dist/components/NumberField/NumberField.d.mts +68 -0
  51. package/dist/components/NumberField/NumberField.mjs +220 -0
  52. package/dist/components/ProgressBar/ProgressBar.cjs +132 -0
  53. package/dist/components/ProgressBar/ProgressBar.d.cts +56 -0
  54. package/dist/components/ProgressBar/ProgressBar.d.mts +56 -0
  55. package/dist/components/ProgressBar/ProgressBar.mjs +129 -0
  56. package/dist/components/RadioGroup/RadioGroup.cjs +218 -0
  57. package/dist/components/RadioGroup/RadioGroup.d.cts +82 -0
  58. package/dist/components/RadioGroup/RadioGroup.d.mts +82 -0
  59. package/dist/components/RadioGroup/RadioGroup.mjs +215 -0
  60. package/dist/components/Select/Select.cjs +253 -0
  61. package/dist/components/Select/Select.d.cts +86 -0
  62. package/dist/components/Select/Select.d.mts +86 -0
  63. package/dist/components/Select/Select.mjs +250 -0
  64. package/dist/components/Separator/Separator.cjs +64 -0
  65. package/dist/components/Separator/Separator.d.cts +44 -0
  66. package/dist/components/Separator/Separator.d.mts +44 -0
  67. package/dist/components/Separator/Separator.mjs +63 -0
  68. package/dist/components/Slider/Slider.cjs +160 -0
  69. package/dist/components/Slider/Slider.d.cts +45 -0
  70. package/dist/components/Slider/Slider.d.mts +45 -0
  71. package/dist/components/Slider/Slider.mjs +159 -0
  72. package/dist/components/Switch/Switch.cjs +176 -0
  73. package/dist/components/Switch/Switch.d.cts +43 -0
  74. package/dist/components/Switch/Switch.d.mts +43 -0
  75. package/dist/components/Switch/Switch.mjs +175 -0
  76. package/dist/components/Tabs/Tabs.cjs +180 -0
  77. package/dist/components/Tabs/Tabs.d.cts +85 -0
  78. package/dist/components/Tabs/Tabs.d.mts +85 -0
  79. package/dist/components/Tabs/Tabs.mjs +173 -0
  80. package/dist/components/Toast/Toast.cjs +218 -0
  81. package/dist/components/Toast/Toast.d.cts +96 -0
  82. package/dist/components/Toast/Toast.d.mts +96 -0
  83. package/dist/components/Toast/Toast.mjs +214 -0
  84. package/dist/components/ToggleButton/ToggleButton.cjs +125 -0
  85. package/dist/components/ToggleButton/ToggleButton.d.cts +43 -0
  86. package/dist/components/ToggleButton/ToggleButton.d.mts +43 -0
  87. package/dist/components/ToggleButton/ToggleButton.mjs +124 -0
  88. package/dist/components/ToggleButtonGroup/ToggleButtonGroup.cjs +48 -0
  89. package/dist/components/ToggleButtonGroup/ToggleButtonGroup.d.cts +41 -0
  90. package/dist/components/ToggleButtonGroup/ToggleButtonGroup.d.mts +41 -0
  91. package/dist/components/ToggleButtonGroup/ToggleButtonGroup.mjs +47 -0
  92. package/dist/components/Toolbar/Toolbar.cjs +67 -0
  93. package/dist/components/Toolbar/Toolbar.d.cts +60 -0
  94. package/dist/components/Toolbar/Toolbar.d.mts +60 -0
  95. package/dist/components/Toolbar/Toolbar.mjs +66 -0
  96. package/dist/composites/Accordion/Accordion.cjs +279 -0
  97. package/dist/composites/Accordion/Accordion.d.cts +176 -0
  98. package/dist/composites/Accordion/Accordion.d.mts +176 -0
  99. package/dist/composites/Accordion/Accordion.mjs +270 -0
  100. package/dist/composites/ConfirmationDialog/ConfirmationDialog.cjs +206 -0
  101. package/dist/composites/ConfirmationDialog/ConfirmationDialog.d.cts +166 -0
  102. package/dist/composites/ConfirmationDialog/ConfirmationDialog.d.mts +166 -0
  103. package/dist/composites/ConfirmationDialog/ConfirmationDialog.mjs +203 -0
  104. package/dist/composites/Dialog/Dialog.cjs +372 -0
  105. package/dist/composites/Dialog/Dialog.d.cts +234 -0
  106. package/dist/composites/Dialog/Dialog.d.mts +234 -0
  107. package/dist/composites/Dialog/Dialog.mjs +360 -0
  108. package/dist/composites/Disclosure/Disclosure.cjs +214 -0
  109. package/dist/composites/Disclosure/Disclosure.d.cts +118 -0
  110. package/dist/composites/Disclosure/Disclosure.d.mts +118 -0
  111. package/dist/composites/Disclosure/Disclosure.mjs +207 -0
  112. package/dist/composites/Form/Form.cjs +161 -0
  113. package/dist/composites/Form/Form.d.cts +176 -0
  114. package/dist/composites/Form/Form.d.mts +176 -0
  115. package/dist/composites/Form/Form.mjs +156 -0
  116. package/dist/composites/Menu/Menu.cjs +190 -0
  117. package/dist/composites/Menu/Menu.d.cts +158 -0
  118. package/dist/composites/Menu/Menu.d.mts +158 -0
  119. package/dist/composites/Menu/Menu.mjs +186 -0
  120. package/dist/composites/Popover/Popover.cjs +80 -0
  121. package/dist/composites/Popover/Popover.d.cts +56 -0
  122. package/dist/composites/Popover/Popover.d.mts +56 -0
  123. package/dist/composites/Popover/Popover.mjs +78 -0
  124. package/dist/composites/SearchField/SearchField.cjs +194 -0
  125. package/dist/composites/SearchField/SearchField.d.cts +81 -0
  126. package/dist/composites/SearchField/SearchField.d.mts +81 -0
  127. package/dist/composites/SearchField/SearchField.mjs +189 -0
  128. package/dist/composites/TagGroup/TagGroup.cjs +212 -0
  129. package/dist/composites/TagGroup/TagGroup.d.cts +84 -0
  130. package/dist/composites/TagGroup/TagGroup.d.mts +84 -0
  131. package/dist/composites/TagGroup/TagGroup.mjs +209 -0
  132. package/dist/composites/TextArea/TextArea.cjs +190 -0
  133. package/dist/composites/TextArea/TextArea.d.cts +95 -0
  134. package/dist/composites/TextArea/TextArea.d.mts +95 -0
  135. package/dist/composites/TextArea/TextArea.mjs +181 -0
  136. package/dist/composites/TextField/TextField.cjs +200 -0
  137. package/dist/composites/TextField/TextField.d.cts +111 -0
  138. package/dist/composites/TextField/TextField.d.mts +111 -0
  139. package/dist/composites/TextField/TextField.mjs +191 -0
  140. package/dist/composites/Tooltip/Tooltip.cjs +79 -0
  141. package/dist/composites/Tooltip/Tooltip.d.cts +53 -0
  142. package/dist/composites/Tooltip/Tooltip.d.mts +53 -0
  143. package/dist/composites/Tooltip/Tooltip.mjs +77 -0
  144. package/dist/composites/Wizard/Wizard.cjs +333 -0
  145. package/dist/composites/Wizard/Wizard.d.cts +206 -0
  146. package/dist/composites/Wizard/Wizard.d.mts +206 -0
  147. package/dist/composites/Wizard/Wizard.mjs +324 -0
  148. package/dist/composites/scope.cjs +124 -0
  149. package/dist/composites/scope.mjs +121 -0
  150. package/dist/index.cjs +186 -0
  151. package/dist/index.d.cts +37 -0
  152. package/dist/index.d.mts +37 -0
  153. package/dist/index.mjs +39 -0
  154. package/dist/semantics/componentMeta.d.cts +37 -0
  155. package/dist/semantics/componentMeta.d.mts +37 -0
  156. package/dist/semantics/index.cjs +16 -0
  157. package/dist/semantics/index.d.cts +4 -0
  158. package/dist/semantics/index.d.mts +4 -0
  159. package/dist/semantics/index.mjs +3 -0
  160. package/dist/semantics/taxonomy.cjs +150 -0
  161. package/dist/semantics/taxonomy.d.cts +153 -0
  162. package/dist/semantics/taxonomy.d.mts +153 -0
  163. package/dist/semantics/taxonomy.mjs +140 -0
  164. package/dist/tokens/escapeHatch.cjs +13 -0
  165. package/dist/tokens/escapeHatch.mjs +13 -0
  166. package/dist/tokens/focusRing.cjs +28 -0
  167. package/dist/tokens/focusRing.mjs +28 -0
  168. package/dist/tokens/keyframes.cjs +76 -0
  169. package/dist/tokens/keyframes.mjs +75 -0
  170. package/dist/tokens/resolveInteractiveStyle.cjs +41 -0
  171. package/dist/tokens/resolveInteractiveStyle.mjs +41 -0
  172. package/llms.txt +142 -0
  173. package/package.json +70 -0
  174. package/src/tokens/CONTRACT.md +505 -0
@@ -0,0 +1,166 @@
1
+
2
+ import { ConsequencesFor, EvaluationsFor } from "../../semantics/taxonomy.cjs";
3
+ import { DialogActionsPlatform } from "../Dialog/Dialog.cjs";
4
+ import * as React from "react";
5
+
6
+ //#region src/composites/ConfirmationDialog/ConfirmationDialog.d.ts
7
+ /**
8
+ * Formal semantic identity — ConfirmationDialog root (Overlay entity).
9
+ */
10
+ declare const confirmationDialogMeta: {
11
+ readonly displayName: "ConfirmationDialog";
12
+ readonly entity: "Overlay";
13
+ readonly structure: "root";
14
+ };
15
+ interface ConfirmationDialogBaseProps {
16
+ /**
17
+ * The element that opens the dialog. Typically a {@link Button}.
18
+ * React Aria's `DialogTrigger` wires open/close state to it.
19
+ */
20
+ trigger: React.ReactElement;
21
+ /** Heading rendered inside the dialog. */
22
+ title: React.ReactNode;
23
+ /** Body content — usually a short explanation of what will happen. */
24
+ children?: React.ReactNode;
25
+ /**
26
+ * Label for the confirm button. **Required** — flow-critical labels
27
+ * have no English default (CONTRIBUTING §6 / ADR-001); the caller
28
+ * supplies localized copy.
29
+ */
30
+ confirmLabel: React.ReactNode;
31
+ /**
32
+ * Label for the cancel / dismiss button. **Required** — see
33
+ * `confirmLabel`.
34
+ */
35
+ cancelLabel: React.ReactNode;
36
+ /**
37
+ * Semantic emphasis for the confirm button (authorial voice, orthogonal
38
+ * to `consequence`). `destructive` consequence does not imply a
39
+ * `negative` evaluation — color is the author's call.
40
+ * @default 'primary'
41
+ */
42
+ evaluation?: EvaluationsFor<'Action'>;
43
+ /** Called only when confirmation is definitive (after arming, if required). */
44
+ onConfirm: () => void;
45
+ /**
46
+ * Time window (ms) during which the *second* click of a destructive
47
+ * confirmation must land. After expiry, arming resets silently.
48
+ * Ignored for non-destructive consequences.
49
+ * @default 2000
50
+ */
51
+ armWindowMs?: number;
52
+ /**
53
+ * Platform convention forwarded to the underlying {@link DialogActions}.
54
+ * @default 'ios'
55
+ */
56
+ platform?: DialogActionsPlatform;
57
+ }
58
+ interface ConfirmationDialogDestructiveProps extends ConfirmationDialogBaseProps {
59
+ /**
60
+ * Effect on state the confirm action produces. **Selects the confirm
61
+ * mechanism** (see component-level comment): `destructive` requires a
62
+ * two-click arming protocol; `neutral` / `committing` confirm on the
63
+ * first click.
64
+ */
65
+ consequence: Extract<ConsequencesFor<'Action'>, 'destructive'>;
66
+ /**
67
+ * Label shown on the confirm button while it is *armed* (first click
68
+ * already received, awaiting second). **Required** for `destructive` —
69
+ * it is flow-critical copy the user must be able to read.
70
+ */
71
+ armedLabel: React.ReactNode;
72
+ }
73
+ interface ConfirmationDialogNonDestructiveProps extends ConfirmationDialogBaseProps {
74
+ /**
75
+ * Effect on state the confirm action produces. `neutral` / `committing`
76
+ * confirm on the first click — no arming protocol.
77
+ * @default 'neutral'
78
+ */
79
+ consequence?: Exclude<ConsequencesFor<'Action'>, 'destructive'>;
80
+ /** Only destructive confirmations have an armed state. */
81
+ armedLabel?: never;
82
+ }
83
+ /**
84
+ * Props for {@link ConfirmationDialog}. A discriminated union on
85
+ * `consequence`: `destructive` requires `armedLabel`; other consequences
86
+ * forbid it. The type system enforces what the arming mechanism needs.
87
+ */
88
+ type ConfirmationDialogProps = ConfirmationDialogDestructiveProps | ConfirmationDialogNonDestructiveProps;
89
+ /**
90
+ * A Dialog composite that demands confirmation before invoking a side effect.
91
+ *
92
+ * Reads its `consequence` prop at runtime to select the confirm mechanism —
93
+ * this is what makes `Consequence` a behavior-driving FSL dimension and not
94
+ * decoration. For `destructive`, the confirm button emits
95
+ * `data-arming="true"` while awaiting the second click. (`data-pending` is
96
+ * reserved by React Aria for `isPending`, which also toggles
97
+ * `aria-disabled` — unsuitable here because the armed button must remain
98
+ * clickable for the second press.)
99
+ *
100
+ * @example Single-click commit
101
+ * ```tsx
102
+ * <ConfirmationDialog
103
+ * trigger={<Button>Publish</Button>}
104
+ * title="Publish post?"
105
+ * confirmLabel="Publish"
106
+ * cancelLabel="Cancel"
107
+ * consequence="committing"
108
+ * onConfirm={publish}
109
+ * >
110
+ * Your post will become visible to everyone.
111
+ * </ConfirmationDialog>
112
+ * ```
113
+ *
114
+ * @example Two-click destructive confirm
115
+ * ```tsx
116
+ * <ConfirmationDialog
117
+ * trigger={<Button evaluation="negative">Delete account</Button>}
118
+ * title="Delete account?"
119
+ * confirmLabel="Delete"
120
+ * armedLabel="Click again to confirm"
121
+ * cancelLabel="Cancel"
122
+ * consequence="destructive"
123
+ * evaluation="negative"
124
+ * onConfirm={deleteAccount}
125
+ * >
126
+ * This action cannot be undone.
127
+ * </ConfirmationDialog>
128
+ * ```
129
+ *
130
+ * @example Visually destructive but single-click (escape-hatch pattern)
131
+ *
132
+ * Use `consequence="committing"` with `evaluation="negative"` when the
133
+ * action is irreversible-looking but does **not** warrant two-click arming
134
+ * (e.g. "Remove from list", "Unsubscribe"). The confirm button renders in
135
+ * the negative color without engaging the arming protocol.
136
+ *
137
+ * ```tsx
138
+ * <ConfirmationDialog
139
+ * trigger={<Button evaluation="negative">Unsubscribe</Button>}
140
+ * title="Unsubscribe?"
141
+ * confirmLabel="Unsubscribe"
142
+ * cancelLabel="Cancel"
143
+ * consequence="committing"
144
+ * evaluation="negative"
145
+ * onConfirm={unsubscribe}
146
+ * />
147
+ * ```
148
+ */
149
+ declare const ConfirmationDialog: {
150
+ ({
151
+ trigger,
152
+ title,
153
+ children,
154
+ confirmLabel,
155
+ armedLabel,
156
+ cancelLabel,
157
+ consequence,
158
+ evaluation,
159
+ onConfirm,
160
+ armWindowMs,
161
+ platform
162
+ }: ConfirmationDialogProps): import("react/jsx-runtime").JSX.Element;
163
+ displayName: "ConfirmationDialog";
164
+ };
165
+ //#endregion
166
+ export { ConfirmationDialog, ConfirmationDialogProps, confirmationDialogMeta };
@@ -0,0 +1,166 @@
1
+
2
+ import { ConsequencesFor, EvaluationsFor } from "../../semantics/taxonomy.mjs";
3
+ import { DialogActionsPlatform } from "../Dialog/Dialog.mjs";
4
+ import * as React from "react";
5
+
6
+ //#region src/composites/ConfirmationDialog/ConfirmationDialog.d.ts
7
+ /**
8
+ * Formal semantic identity — ConfirmationDialog root (Overlay entity).
9
+ */
10
+ declare const confirmationDialogMeta: {
11
+ readonly displayName: "ConfirmationDialog";
12
+ readonly entity: "Overlay";
13
+ readonly structure: "root";
14
+ };
15
+ interface ConfirmationDialogBaseProps {
16
+ /**
17
+ * The element that opens the dialog. Typically a {@link Button}.
18
+ * React Aria's `DialogTrigger` wires open/close state to it.
19
+ */
20
+ trigger: React.ReactElement;
21
+ /** Heading rendered inside the dialog. */
22
+ title: React.ReactNode;
23
+ /** Body content — usually a short explanation of what will happen. */
24
+ children?: React.ReactNode;
25
+ /**
26
+ * Label for the confirm button. **Required** — flow-critical labels
27
+ * have no English default (CONTRIBUTING §6 / ADR-001); the caller
28
+ * supplies localized copy.
29
+ */
30
+ confirmLabel: React.ReactNode;
31
+ /**
32
+ * Label for the cancel / dismiss button. **Required** — see
33
+ * `confirmLabel`.
34
+ */
35
+ cancelLabel: React.ReactNode;
36
+ /**
37
+ * Semantic emphasis for the confirm button (authorial voice, orthogonal
38
+ * to `consequence`). `destructive` consequence does not imply a
39
+ * `negative` evaluation — color is the author's call.
40
+ * @default 'primary'
41
+ */
42
+ evaluation?: EvaluationsFor<'Action'>;
43
+ /** Called only when confirmation is definitive (after arming, if required). */
44
+ onConfirm: () => void;
45
+ /**
46
+ * Time window (ms) during which the *second* click of a destructive
47
+ * confirmation must land. After expiry, arming resets silently.
48
+ * Ignored for non-destructive consequences.
49
+ * @default 2000
50
+ */
51
+ armWindowMs?: number;
52
+ /**
53
+ * Platform convention forwarded to the underlying {@link DialogActions}.
54
+ * @default 'ios'
55
+ */
56
+ platform?: DialogActionsPlatform;
57
+ }
58
+ interface ConfirmationDialogDestructiveProps extends ConfirmationDialogBaseProps {
59
+ /**
60
+ * Effect on state the confirm action produces. **Selects the confirm
61
+ * mechanism** (see component-level comment): `destructive` requires a
62
+ * two-click arming protocol; `neutral` / `committing` confirm on the
63
+ * first click.
64
+ */
65
+ consequence: Extract<ConsequencesFor<'Action'>, 'destructive'>;
66
+ /**
67
+ * Label shown on the confirm button while it is *armed* (first click
68
+ * already received, awaiting second). **Required** for `destructive` —
69
+ * it is flow-critical copy the user must be able to read.
70
+ */
71
+ armedLabel: React.ReactNode;
72
+ }
73
+ interface ConfirmationDialogNonDestructiveProps extends ConfirmationDialogBaseProps {
74
+ /**
75
+ * Effect on state the confirm action produces. `neutral` / `committing`
76
+ * confirm on the first click — no arming protocol.
77
+ * @default 'neutral'
78
+ */
79
+ consequence?: Exclude<ConsequencesFor<'Action'>, 'destructive'>;
80
+ /** Only destructive confirmations have an armed state. */
81
+ armedLabel?: never;
82
+ }
83
+ /**
84
+ * Props for {@link ConfirmationDialog}. A discriminated union on
85
+ * `consequence`: `destructive` requires `armedLabel`; other consequences
86
+ * forbid it. The type system enforces what the arming mechanism needs.
87
+ */
88
+ type ConfirmationDialogProps = ConfirmationDialogDestructiveProps | ConfirmationDialogNonDestructiveProps;
89
+ /**
90
+ * A Dialog composite that demands confirmation before invoking a side effect.
91
+ *
92
+ * Reads its `consequence` prop at runtime to select the confirm mechanism —
93
+ * this is what makes `Consequence` a behavior-driving FSL dimension and not
94
+ * decoration. For `destructive`, the confirm button emits
95
+ * `data-arming="true"` while awaiting the second click. (`data-pending` is
96
+ * reserved by React Aria for `isPending`, which also toggles
97
+ * `aria-disabled` — unsuitable here because the armed button must remain
98
+ * clickable for the second press.)
99
+ *
100
+ * @example Single-click commit
101
+ * ```tsx
102
+ * <ConfirmationDialog
103
+ * trigger={<Button>Publish</Button>}
104
+ * title="Publish post?"
105
+ * confirmLabel="Publish"
106
+ * cancelLabel="Cancel"
107
+ * consequence="committing"
108
+ * onConfirm={publish}
109
+ * >
110
+ * Your post will become visible to everyone.
111
+ * </ConfirmationDialog>
112
+ * ```
113
+ *
114
+ * @example Two-click destructive confirm
115
+ * ```tsx
116
+ * <ConfirmationDialog
117
+ * trigger={<Button evaluation="negative">Delete account</Button>}
118
+ * title="Delete account?"
119
+ * confirmLabel="Delete"
120
+ * armedLabel="Click again to confirm"
121
+ * cancelLabel="Cancel"
122
+ * consequence="destructive"
123
+ * evaluation="negative"
124
+ * onConfirm={deleteAccount}
125
+ * >
126
+ * This action cannot be undone.
127
+ * </ConfirmationDialog>
128
+ * ```
129
+ *
130
+ * @example Visually destructive but single-click (escape-hatch pattern)
131
+ *
132
+ * Use `consequence="committing"` with `evaluation="negative"` when the
133
+ * action is irreversible-looking but does **not** warrant two-click arming
134
+ * (e.g. "Remove from list", "Unsubscribe"). The confirm button renders in
135
+ * the negative color without engaging the arming protocol.
136
+ *
137
+ * ```tsx
138
+ * <ConfirmationDialog
139
+ * trigger={<Button evaluation="negative">Unsubscribe</Button>}
140
+ * title="Unsubscribe?"
141
+ * confirmLabel="Unsubscribe"
142
+ * cancelLabel="Cancel"
143
+ * consequence="committing"
144
+ * evaluation="negative"
145
+ * onConfirm={unsubscribe}
146
+ * />
147
+ * ```
148
+ */
149
+ declare const ConfirmationDialog: {
150
+ ({
151
+ trigger,
152
+ title,
153
+ children,
154
+ confirmLabel,
155
+ armedLabel,
156
+ cancelLabel,
157
+ consequence,
158
+ evaluation,
159
+ onConfirm,
160
+ armWindowMs,
161
+ platform
162
+ }: ConfirmationDialogProps): import("react/jsx-runtime").JSX.Element;
163
+ displayName: "ConfirmationDialog";
164
+ };
165
+ //#endregion
166
+ export { ConfirmationDialog, ConfirmationDialogProps, confirmationDialogMeta };
@@ -0,0 +1,203 @@
1
+ /** Powered by @ttoss/config. https://ttoss.dev/docs/modules/packages/config/ */
2
+ import { Button } from "../../components/Button/Button.mjs";
3
+ import { Dialog, DialogActions, DialogBody, DialogHeading, DialogModal, DialogTrigger } from "../Dialog/Dialog.mjs";
4
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
5
+ import * as React from "react";
6
+
7
+ //#region src/composites/ConfirmationDialog/ConfirmationDialog.tsx
8
+ /**
9
+ * Formal semantic identity — ConfirmationDialog root (Overlay entity).
10
+ */
11
+ var confirmationDialogMeta = {
12
+ displayName: "ConfirmationDialog",
13
+ entity: "Overlay",
14
+ structure: "root"
15
+ };
16
+ /**
17
+ * Owns the consequence-driven confirm mechanism so the component body stays
18
+ * declarative. `destructive` requires a two-click arm→confirm within
19
+ * `armWindowMs`; everything else confirms on the first click. Toggling
20
+ * `consequence` mid-lifetime resets arming via the render-phase adjustment
21
+ * pattern (no extra commit).
22
+ */
23
+ var useArmedConfirm = ({
24
+ consequence,
25
+ onConfirm,
26
+ armWindowMs
27
+ }) => {
28
+ const requiresArming = consequence === "destructive";
29
+ const [isArmed, setIsArmed] = React.useState(false);
30
+ const armTimerRef = React.useRef(null);
31
+ const clearArmTimer = React.useCallback(() => {
32
+ if (armTimerRef.current !== null) {
33
+ clearTimeout(armTimerRef.current);
34
+ armTimerRef.current = null;
35
+ }
36
+ }, []);
37
+ const [prevConsequence, setPrevConsequence] = React.useState(consequence);
38
+ if (prevConsequence !== consequence) {
39
+ setPrevConsequence(consequence);
40
+ setIsArmed(false);
41
+ }
42
+ React.useEffect(() => {
43
+ return () => {
44
+ clearArmTimer();
45
+ };
46
+ }, [clearArmTimer]);
47
+ const reset = React.useCallback(() => {
48
+ clearArmTimer();
49
+ setIsArmed(false);
50
+ }, [clearArmTimer]);
51
+ const arm = React.useCallback(() => {
52
+ setIsArmed(true);
53
+ clearArmTimer();
54
+ armTimerRef.current = setTimeout(() => {
55
+ armTimerRef.current = null;
56
+ setIsArmed(false);
57
+ }, armWindowMs);
58
+ }, [armWindowMs, clearArmTimer]);
59
+ const confirm = close => {
60
+ if (!(!requiresArming || isArmed)) {
61
+ arm();
62
+ return;
63
+ }
64
+ reset();
65
+ onConfirm();
66
+ close();
67
+ };
68
+ return {
69
+ isArmed,
70
+ confirm,
71
+ reset
72
+ };
73
+ };
74
+ /**
75
+ * A Dialog composite that demands confirmation before invoking a side effect.
76
+ *
77
+ * Reads its `consequence` prop at runtime to select the confirm mechanism —
78
+ * this is what makes `Consequence` a behavior-driving FSL dimension and not
79
+ * decoration. For `destructive`, the confirm button emits
80
+ * `data-arming="true"` while awaiting the second click. (`data-pending` is
81
+ * reserved by React Aria for `isPending`, which also toggles
82
+ * `aria-disabled` — unsuitable here because the armed button must remain
83
+ * clickable for the second press.)
84
+ *
85
+ * @example Single-click commit
86
+ * ```tsx
87
+ * <ConfirmationDialog
88
+ * trigger={<Button>Publish</Button>}
89
+ * title="Publish post?"
90
+ * confirmLabel="Publish"
91
+ * cancelLabel="Cancel"
92
+ * consequence="committing"
93
+ * onConfirm={publish}
94
+ * >
95
+ * Your post will become visible to everyone.
96
+ * </ConfirmationDialog>
97
+ * ```
98
+ *
99
+ * @example Two-click destructive confirm
100
+ * ```tsx
101
+ * <ConfirmationDialog
102
+ * trigger={<Button evaluation="negative">Delete account</Button>}
103
+ * title="Delete account?"
104
+ * confirmLabel="Delete"
105
+ * armedLabel="Click again to confirm"
106
+ * cancelLabel="Cancel"
107
+ * consequence="destructive"
108
+ * evaluation="negative"
109
+ * onConfirm={deleteAccount}
110
+ * >
111
+ * This action cannot be undone.
112
+ * </ConfirmationDialog>
113
+ * ```
114
+ *
115
+ * @example Visually destructive but single-click (escape-hatch pattern)
116
+ *
117
+ * Use `consequence="committing"` with `evaluation="negative"` when the
118
+ * action is irreversible-looking but does **not** warrant two-click arming
119
+ * (e.g. "Remove from list", "Unsubscribe"). The confirm button renders in
120
+ * the negative color without engaging the arming protocol.
121
+ *
122
+ * ```tsx
123
+ * <ConfirmationDialog
124
+ * trigger={<Button evaluation="negative">Unsubscribe</Button>}
125
+ * title="Unsubscribe?"
126
+ * confirmLabel="Unsubscribe"
127
+ * cancelLabel="Cancel"
128
+ * consequence="committing"
129
+ * evaluation="negative"
130
+ * onConfirm={unsubscribe}
131
+ * />
132
+ * ```
133
+ */
134
+ var ConfirmationDialog = ({
135
+ trigger,
136
+ title,
137
+ children,
138
+ confirmLabel,
139
+ armedLabel,
140
+ cancelLabel,
141
+ consequence = "neutral",
142
+ evaluation = "primary",
143
+ onConfirm,
144
+ armWindowMs = 2e3,
145
+ platform = "ios"
146
+ }) => {
147
+ const {
148
+ isArmed,
149
+ confirm,
150
+ reset
151
+ } = useArmedConfirm({
152
+ consequence,
153
+ onConfirm,
154
+ armWindowMs
155
+ });
156
+ const currentConfirmLabel = consequence === "destructive" && isArmed ? armedLabel : confirmLabel;
157
+ return /* @__PURE__ */jsxs(DialogTrigger, {
158
+ onOpenChange: open => {
159
+ if (!open) reset();
160
+ },
161
+ children: [trigger, /* @__PURE__ */jsx(DialogModal, {
162
+ children: /* @__PURE__ */jsx(Dialog, {
163
+ "data-scope": "confirmation-dialog",
164
+ "data-consequence": consequence,
165
+ children: ({
166
+ close
167
+ }) => {
168
+ return /* @__PURE__ */jsxs(Fragment, {
169
+ children: [/* @__PURE__ */jsx(DialogHeading, {
170
+ children: title
171
+ }), children !== void 0 && /* @__PURE__ */jsx(DialogBody, {
172
+ children
173
+ }), /* @__PURE__ */jsxs(DialogActions, {
174
+ platform,
175
+ children: [/* @__PURE__ */jsx(Button, {
176
+ slot: "close",
177
+ composition: "dismissAction",
178
+ evaluation: "muted",
179
+ onPress: () => {
180
+ return reset();
181
+ },
182
+ children: cancelLabel
183
+ }), /* @__PURE__ */jsx(Button, {
184
+ composition: "primaryAction",
185
+ consequence,
186
+ evaluation,
187
+ "data-arming": isArmed ? "true" : void 0,
188
+ onPress: () => {
189
+ return confirm(close);
190
+ },
191
+ children: currentConfirmLabel
192
+ })]
193
+ })]
194
+ });
195
+ }
196
+ })
197
+ })]
198
+ });
199
+ };
200
+ ConfirmationDialog.displayName = confirmationDialogMeta.displayName;
201
+
202
+ //#endregion
203
+ export { ConfirmationDialog, confirmationDialogMeta };