@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,206 @@
1
+
2
+ import * as React from "react";
3
+
4
+ //#region src/composites/Wizard/Wizard.d.ts
5
+ type WizardSlotComposition = 'step' | 'summary' | 'navigation';
6
+ type WizardSlotComponent<P, K extends WizardSlotComposition> = React.ComponentType<P> & {
7
+ composition: K;
8
+ };
9
+ /**
10
+ * Public state surface shared by the {@link Wizard} host with its
11
+ * sub-parts. Consumed by {@link WizardNavigationProps.children} as a
12
+ * render-prop signature so authors can compose custom navigation while
13
+ * still observing the same state machine the default row uses.
14
+ */
15
+ interface WizardState {
16
+ currentStep: number;
17
+ totalSteps: number;
18
+ isFirst: boolean;
19
+ isLast: boolean;
20
+ isComplete: boolean;
21
+ goNext: () => void;
22
+ goPrev: () => void;
23
+ goTo: (step: number) => void;
24
+ }
25
+ /**
26
+ * Formal semantic identity — Wizard root (Structure entity, root part).
27
+ */
28
+ declare const wizardMeta: {
29
+ readonly displayName: "Wizard";
30
+ readonly entity: "Structure";
31
+ readonly structure: "root";
32
+ };
33
+ /**
34
+ * Props for {@link Wizard}.
35
+ *
36
+ * The Wizard root carries no `evaluation` prop: under the evidence rule
37
+ * (CONTRIBUTING §2.3) a dimension only appears on a component if a runtime
38
+ * dispatches on it. The Wizard root renders a transparent `<section>` —
39
+ * no color tokens are read here — so adding `evaluation` would reserve API
40
+ * surface for a speculative future consumer. Re-introduce it the day a
41
+ * real consumer (e.g. wizard frame chrome) needs it.
42
+ *
43
+ * The composite owns its layout; the root does not accept `style` or
44
+ * `className`. Pass them on a wrapping element instead. See CONTRIBUTING
45
+ * §4.
46
+ */
47
+ interface WizardProps {
48
+ /**
49
+ * Controlled current step index (0-based). When the user has advanced
50
+ * past the last step, `currentStep === numberOfSteps` — this is the
51
+ * terminal state that renders the {@link WizardSummary} sub-part (if
52
+ * provided). Pair with {@link WizardProps.onStepChange}.
53
+ */
54
+ currentStep?: number;
55
+ /**
56
+ * Initial step index when rendering uncontrolled.
57
+ * @default 0
58
+ */
59
+ defaultStep?: number;
60
+ /**
61
+ * Fires whenever the active step changes — controlled or uncontrolled.
62
+ */
63
+ onStepChange?: (step: number) => void;
64
+ /**
65
+ * Accessible name for the wizard region (rendered as `aria-label`).
66
+ * Always provide one (or `aria-labelledby`) — the wizard renders a
67
+ * `<section>` landmark and screen-reader users navigate by its name.
68
+ */
69
+ 'aria-label'?: string;
70
+ /**
71
+ * Builds the text announced by the wizard's visually-hidden
72
+ * `aria-live=polite` region whenever the active step changes.
73
+ * The default is an English fallback (`"Step 2 of 3"` / `"Complete"`) —
74
+ * localized hosts supply their own copy here (CONTRIBUTING §6).
75
+ */
76
+ announceStep?: (state: {
77
+ currentStep: number;
78
+ totalSteps: number;
79
+ isComplete: boolean;
80
+ }) => string;
81
+ /**
82
+ * Expected children: any number of {@link WizardStep} (in order), an
83
+ * optional {@link WizardSummary}, and an optional {@link WizardNavigation}.
84
+ * Children are dispatched on their fixed `composition` identity.
85
+ */
86
+ children?: React.ReactNode;
87
+ }
88
+ /**
89
+ * A step-at-a-time Structure composite. The host reads each child's
90
+ * fixed `composition` identity at runtime to decide which single step
91
+ * to render, whether to swap in the summary view, and whether to render
92
+ * the navigation row. This is the canonical evidence that FSL
93
+ * `Composition` drives behavior from *fixed-identity sub-parts*
94
+ * (complementing `DialogActions`, which drives behavior from *runtime
95
+ * values on leaves*).
96
+ *
97
+ * @example
98
+ * ```tsx
99
+ * const [step, setStep] = React.useState(0);
100
+ * return (
101
+ * <Wizard currentStep={step} onStepChange={setStep} aria-label="Onboarding">
102
+ * <WizardStep>First step content</WizardStep>
103
+ * <WizardStep>Second step content</WizardStep>
104
+ * <WizardStep>Third step content</WizardStep>
105
+ * <WizardSummary>All done!</WizardSummary>
106
+ * <WizardNavigation prevLabel="Back" nextLabel="Next" finishLabel="Finish" />
107
+ * </Wizard>
108
+ * );
109
+ * ```
110
+ */
111
+ declare const Wizard: {
112
+ ({
113
+ currentStep,
114
+ defaultStep,
115
+ onStepChange,
116
+ announceStep,
117
+ children,
118
+ ...props
119
+ }: WizardProps): import("react/jsx-runtime").JSX.Element;
120
+ displayName: "Wizard";
121
+ };
122
+ /**
123
+ * Formal semantic identity — a step body inside a {@link Wizard}.
124
+ */
125
+ declare const wizardStepMeta: {
126
+ readonly displayName: "WizardStep";
127
+ readonly entity: "Structure";
128
+ readonly structure: "content";
129
+ readonly composition: "step";
130
+ };
131
+ /**
132
+ * Props for {@link WizardStep}.
133
+ */
134
+ interface WizardStepProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'style' | 'className'> {
135
+ /**
136
+ * Optional accessible label for this step (rendered as `aria-label`).
137
+ */
138
+ 'aria-label'?: string;
139
+ /** Step body — freeform content (fields, descriptions, media). */
140
+ children?: React.ReactNode;
141
+ }
142
+ declare const WizardStep: WizardSlotComponent<WizardStepProps, "step">;
143
+ /**
144
+ * Formal semantic identity — summary view shown after the last step.
145
+ */
146
+ declare const wizardSummaryMeta: {
147
+ readonly displayName: "WizardSummary";
148
+ readonly entity: "Structure";
149
+ readonly structure: "content";
150
+ readonly composition: "summary";
151
+ };
152
+ /**
153
+ * Props for {@link WizardSummary}.
154
+ */
155
+ type WizardSummaryProps = Omit<React.HTMLAttributes<HTMLDivElement>, 'style' | 'className'>;
156
+ declare const WizardSummary: WizardSlotComponent<WizardSummaryProps, "summary">;
157
+ /**
158
+ * Formal semantic identity — the navigation slot inside a {@link Wizard}.
159
+ */
160
+ declare const wizardNavigationMeta: {
161
+ readonly displayName: "WizardNavigation";
162
+ readonly entity: "Structure";
163
+ readonly structure: "actions";
164
+ readonly composition: "navigation";
165
+ };
166
+ interface WizardNavigationCommonProps {
167
+ /**
168
+ * Fires when the user advances past the last step (first click of
169
+ * `Finish`). The Wizard host transitions to the `isComplete` state
170
+ * and renders the {@link WizardSummary} if one is provided.
171
+ */
172
+ onFinish?: () => void;
173
+ }
174
+ interface WizardNavigationLabelProps extends WizardNavigationCommonProps {
175
+ /**
176
+ * Label for the "previous step" button. **Required** — flow-critical
177
+ * labels have no English default (CONTRIBUTING §6 / ADR-001); the
178
+ * caller supplies localized copy.
179
+ */
180
+ prevLabel: React.ReactNode;
181
+ /** Label for the "next step" button. **Required** — see `prevLabel`. */
182
+ nextLabel: React.ReactNode;
183
+ /** Label for the final-step button. **Required** — see `prevLabel`. */
184
+ finishLabel: React.ReactNode;
185
+ children?: never;
186
+ }
187
+ interface WizardNavigationRenderProps extends WizardNavigationCommonProps {
188
+ /**
189
+ * Replace the default button row with a render-prop so the host can
190
+ * compose custom controls while still reading wizard state from the
191
+ * same context (validation gating, async next, etc.). When provided,
192
+ * the label props do not apply — the render-prop owns all copy.
193
+ */
194
+ children: (state: WizardState) => React.ReactNode;
195
+ prevLabel?: never;
196
+ nextLabel?: never;
197
+ finishLabel?: never;
198
+ }
199
+ /**
200
+ * Props for {@link WizardNavigation} — either the default row with
201
+ * caller-supplied labels, or a render-prop that owns the whole row.
202
+ */
203
+ type WizardNavigationProps = WizardNavigationLabelProps | WizardNavigationRenderProps;
204
+ declare const WizardNavigation: WizardSlotComponent<WizardNavigationProps, "navigation">;
205
+ //#endregion
206
+ export { Wizard, WizardNavigation, WizardNavigationProps, WizardProps, WizardStep, WizardStepProps, WizardSummary, WizardSummaryProps, wizardMeta, wizardNavigationMeta, wizardStepMeta, wizardSummaryMeta };
@@ -0,0 +1,324 @@
1
+ /** Powered by @ttoss/config. https://ttoss.dev/docs/modules/packages/config/ */
2
+ import { Button } from "../../components/Button/Button.mjs";
3
+ import { createCompositeScope } from "../scope.mjs";
4
+ import { vars } from "@ttoss/fsl-theme/vars";
5
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
6
+ import * as React from "react";
7
+
8
+ //#region src/composites/Wizard/Wizard.tsx
9
+ /**
10
+ * Tag a component as a Wizard slot. Returns the same component augmented
11
+ * with a typed `.composition` literal — no cast, no post-declaration
12
+ * mutation in the caller.
13
+ */
14
+ var defineWizardSlot = (Component, composition) => {
15
+ return Object.assign(Component, {
16
+ composition
17
+ });
18
+ };
19
+ var REACT_MEMO_TYPE = Symbol.for("react.memo");
20
+ var REACT_FORWARD_REF_TYPE = Symbol.for("react.forward_ref");
21
+ var readComposition = type => {
22
+ if (type === null || typeof type !== "object" && typeof type !== "function") return;
23
+ const candidate = type.composition;
24
+ if (candidate === "step" || candidate === "summary" || candidate === "navigation") return candidate;
25
+ };
26
+ var getChildComposition = child => {
27
+ if (!React.isValidElement(child)) return void 0;
28
+ let type = child.type;
29
+ for (let depth = 0; depth < 8; depth++) {
30
+ const direct = readComposition(type);
31
+ if (direct !== void 0) return direct;
32
+ if (typeof type !== "object" || type === null) return void 0;
33
+ const wrapped = type;
34
+ if (wrapped.$$typeof === REACT_MEMO_TYPE) {
35
+ type = wrapped.type;
36
+ continue;
37
+ }
38
+ if (wrapped.$$typeof === REACT_FORWARD_REF_TYPE) {
39
+ type = wrapped.render;
40
+ continue;
41
+ }
42
+ return;
43
+ }
44
+ };
45
+ var wizardScope = createCompositeScope("Wizard");
46
+ var VISUALLY_HIDDEN_STYLE = {
47
+ position: "absolute",
48
+ width: "1px",
49
+ height: "1px",
50
+ padding: 0,
51
+ margin: "-1px",
52
+ overflow: "hidden",
53
+ clipPath: "inset(50%)",
54
+ whiteSpace: "nowrap",
55
+ border: 0
56
+ };
57
+ /**
58
+ * Default step announcement — an English fallback, documented per the
59
+ * package i18n rule (CONTRIBUTING §6 / ADR-001): supplementary AT feedback
60
+ * may ship a default; localized hosts override via
61
+ * {@link WizardProps.announceStep}.
62
+ */
63
+ var defaultAnnounceStep = ({
64
+ currentStep,
65
+ totalSteps,
66
+ isComplete
67
+ }) => {
68
+ if (isComplete) return "Complete";
69
+ return `Step ${currentStep + 1} of ${totalSteps}`;
70
+ };
71
+ /**
72
+ * Formal semantic identity — Wizard root (Structure entity, root part).
73
+ */
74
+ var wizardMeta = {
75
+ displayName: "Wizard",
76
+ entity: "Structure",
77
+ structure: "root"
78
+ };
79
+ /**
80
+ * A step-at-a-time Structure composite. The host reads each child's
81
+ * fixed `composition` identity at runtime to decide which single step
82
+ * to render, whether to swap in the summary view, and whether to render
83
+ * the navigation row. This is the canonical evidence that FSL
84
+ * `Composition` drives behavior from *fixed-identity sub-parts*
85
+ * (complementing `DialogActions`, which drives behavior from *runtime
86
+ * values on leaves*).
87
+ *
88
+ * @example
89
+ * ```tsx
90
+ * const [step, setStep] = React.useState(0);
91
+ * return (
92
+ * <Wizard currentStep={step} onStepChange={setStep} aria-label="Onboarding">
93
+ * <WizardStep>First step content</WizardStep>
94
+ * <WizardStep>Second step content</WizardStep>
95
+ * <WizardStep>Third step content</WizardStep>
96
+ * <WizardSummary>All done!</WizardSummary>
97
+ * <WizardNavigation prevLabel="Back" nextLabel="Next" finishLabel="Finish" />
98
+ * </Wizard>
99
+ * );
100
+ * ```
101
+ */
102
+ var Wizard = ({
103
+ currentStep,
104
+ defaultStep = 0,
105
+ onStepChange,
106
+ announceStep = defaultAnnounceStep,
107
+ children,
108
+ ...props
109
+ }) => {
110
+ const [internalStep, setInternalStep] = React.useState(defaultStep);
111
+ const step = currentStep ?? internalStep;
112
+ const rootRef = React.useRef(null);
113
+ const setStep = React.useCallback(next => {
114
+ if (currentStep === void 0) setInternalStep(next);
115
+ onStepChange?.(next);
116
+ }, [currentStep, onStepChange]);
117
+ const classified = React.useMemo(() => {
118
+ const steps = [];
119
+ let summary = null;
120
+ let navigation = null;
121
+ const unknown = [];
122
+ React.Children.forEach(children, child => {
123
+ const composition = getChildComposition(child);
124
+ if (composition === "step" && React.isValidElement(child)) steps.push(child);else if (composition === "summary" && React.isValidElement(child)) summary = child;else if (composition === "navigation" && React.isValidElement(child)) navigation = child;else unknown.push(child);
125
+ });
126
+ return {
127
+ steps,
128
+ summary,
129
+ navigation,
130
+ unknown
131
+ };
132
+ }, [children]);
133
+ const totalSteps = classified.steps.length;
134
+ const safeStep = Math.max(0, Math.min(step, totalSteps));
135
+ const isComplete = safeStep >= totalSteps && totalSteps > 0;
136
+ const goTo = React.useCallback(next => {
137
+ setStep(Math.max(0, Math.min(next, totalSteps)));
138
+ }, [setStep, totalSteps]);
139
+ const goNext = React.useCallback(() => {
140
+ return goTo(safeStep + 1);
141
+ }, [goTo, safeStep]);
142
+ const goPrev = React.useCallback(() => {
143
+ return goTo(safeStep - 1);
144
+ }, [goTo, safeStep]);
145
+ const contextValue = React.useMemo(() => {
146
+ return {
147
+ currentStep: safeStep,
148
+ totalSteps,
149
+ isFirst: safeStep === 0,
150
+ isLast: totalSteps > 0 && safeStep === totalSteps - 1,
151
+ isComplete,
152
+ goNext,
153
+ goPrev,
154
+ goTo
155
+ };
156
+ }, [safeStep, totalSteps, isComplete, goNext, goPrev, goTo]);
157
+ const activeStep = isComplete ? classified.summary : classified.steps[safeStep] ?? null;
158
+ const prevStepRef = React.useRef(safeStep);
159
+ React.useEffect(() => {
160
+ if (prevStepRef.current === safeStep) return;
161
+ prevStepRef.current = safeStep;
162
+ rootRef.current?.querySelector("[data-part=\"content\"]")?.focus();
163
+ }, [safeStep]);
164
+ return /* @__PURE__ */jsx(wizardScope.Provider, {
165
+ value: contextValue,
166
+ children: /* @__PURE__ */jsxs("section", {
167
+ ...props,
168
+ ref: rootRef,
169
+ "data-scope": "wizard",
170
+ "data-part": "root",
171
+ "data-current-step": safeStep,
172
+ "data-total-steps": totalSteps,
173
+ "data-complete": isComplete ? "true" : void 0,
174
+ style: {
175
+ boxSizing: "border-box",
176
+ display: "flex",
177
+ flexDirection: "column",
178
+ gap: vars.spacing.gap.stack.md,
179
+ ...vars.text.body.md
180
+ },
181
+ children: [/* @__PURE__ */jsx("div", {
182
+ "data-scope": "wizard",
183
+ "data-part": "status",
184
+ "aria-live": "polite",
185
+ style: VISUALLY_HIDDEN_STYLE,
186
+ children: totalSteps > 0 ? announceStep({
187
+ currentStep: safeStep,
188
+ totalSteps,
189
+ isComplete
190
+ }) : null
191
+ }), activeStep, classified.navigation, classified.unknown]
192
+ })
193
+ });
194
+ };
195
+ Wizard.displayName = wizardMeta.displayName;
196
+ /**
197
+ * Formal semantic identity — a step body inside a {@link Wizard}.
198
+ */
199
+ var wizardStepMeta = {
200
+ displayName: "WizardStep",
201
+ entity: "Structure",
202
+ structure: "content",
203
+ composition: "step"
204
+ };
205
+ /**
206
+ * A single step's body inside a Wizard. Only the step at the current
207
+ * index is rendered — selection is the Wizard host's runtime dispatch
208
+ * on this component's fixed `composition` identity.
209
+ */
210
+ var WizardStepBase = props => {
211
+ wizardScope.use(wizardStepMeta.displayName);
212
+ return /* @__PURE__ */jsx("div", {
213
+ tabIndex: -1,
214
+ ...props,
215
+ "data-scope": "wizard",
216
+ "data-part": "content",
217
+ "data-composition": "step",
218
+ style: {
219
+ boxSizing: "border-box",
220
+ display: "flex",
221
+ flexDirection: "column",
222
+ gap: vars.spacing.gap.stack.sm
223
+ }
224
+ });
225
+ };
226
+ WizardStepBase.displayName = wizardStepMeta.displayName;
227
+ var WizardStep = defineWizardSlot(WizardStepBase, "step");
228
+ /**
229
+ * Formal semantic identity — summary view shown after the last step.
230
+ */
231
+ var wizardSummaryMeta = {
232
+ displayName: "WizardSummary",
233
+ entity: "Structure",
234
+ structure: "content",
235
+ composition: "summary"
236
+ };
237
+ /**
238
+ * A summary view shown once the user has advanced past the last
239
+ * {@link WizardStep}. Selection is the Wizard host's runtime dispatch on
240
+ * this component's fixed `composition` identity — rendered if and only if
241
+ * `currentStep === totalSteps`.
242
+ */
243
+ var WizardSummaryBase = props => {
244
+ wizardScope.use(wizardSummaryMeta.displayName);
245
+ return /* @__PURE__ */jsx("div", {
246
+ tabIndex: -1,
247
+ ...props,
248
+ "data-scope": "wizard",
249
+ "data-part": "content",
250
+ "data-composition": "summary",
251
+ style: {
252
+ boxSizing: "border-box",
253
+ display: "flex",
254
+ flexDirection: "column",
255
+ gap: vars.spacing.gap.stack.sm
256
+ }
257
+ });
258
+ };
259
+ WizardSummaryBase.displayName = wizardSummaryMeta.displayName;
260
+ var WizardSummary = defineWizardSlot(WizardSummaryBase, "summary");
261
+ /**
262
+ * Formal semantic identity — the navigation slot inside a {@link Wizard}.
263
+ */
264
+ var wizardNavigationMeta = {
265
+ displayName: "WizardNavigation",
266
+ entity: "Structure",
267
+ structure: "actions",
268
+ composition: "navigation"
269
+ };
270
+ /**
271
+ * Default navigation row for a {@link Wizard}. Reads wizard state from
272
+ * React context — rendering is otherwise deterministic: `Back` is
273
+ * disabled on the first step; the primary button switches label from
274
+ * the next label to the finish label on the last step and fires
275
+ * `onFinish` before advancing. All labels are caller-supplied — the
276
+ * package ships no user-facing copy (CONTRIBUTING §6 / ADR-001).
277
+ */
278
+ var WizardNavigationBase = ({
279
+ prevLabel,
280
+ nextLabel,
281
+ finishLabel,
282
+ onFinish,
283
+ children
284
+ }) => {
285
+ const ctx = wizardScope.use(wizardNavigationMeta.displayName);
286
+ const content = children ? children(ctx) : /* @__PURE__ */jsxs(Fragment, {
287
+ children: [/* @__PURE__ */jsx(Button, {
288
+ evaluation: "muted",
289
+ onPress: ctx.goPrev,
290
+ isDisabled: ctx.isFirst || ctx.isComplete,
291
+ children: prevLabel
292
+ }), /* @__PURE__ */jsx(Button, {
293
+ evaluation: "primary",
294
+ composition: "primaryAction",
295
+ consequence: ctx.isLast ? "committing" : "neutral",
296
+ isDisabled: ctx.isComplete,
297
+ onPress: () => {
298
+ if (ctx.isLast) onFinish?.();
299
+ ctx.goNext();
300
+ },
301
+ children: ctx.isLast ? finishLabel : nextLabel
302
+ })]
303
+ });
304
+ return /* @__PURE__ */jsx("div", {
305
+ "data-scope": "wizard",
306
+ "data-part": "actions",
307
+ "data-composition": "navigation",
308
+ style: {
309
+ boxSizing: "border-box",
310
+ display: "flex",
311
+ flexDirection: "row",
312
+ alignItems: "center",
313
+ justifyContent: "flex-end",
314
+ gap: vars.spacing.gap.inline.md,
315
+ marginBlockStart: vars.spacing.gap.stack.sm
316
+ },
317
+ children: content
318
+ });
319
+ };
320
+ WizardNavigationBase.displayName = wizardNavigationMeta.displayName;
321
+ var WizardNavigation = defineWizardSlot(WizardNavigationBase, "navigation");
322
+
323
+ //#endregion
324
+ export { Wizard, WizardNavigation, WizardStep, WizardSummary, wizardMeta, wizardNavigationMeta, wizardStepMeta, wizardSummaryMeta };
@@ -0,0 +1,124 @@
1
+ /** Powered by @ttoss/config. https://ttoss.dev/docs/modules/packages/config/ */
2
+ const require_runtime = require('../_virtual/_rolldown/runtime.cjs');
3
+ let react = require("react");
4
+ react = require_runtime.__toESM(react, 1);
5
+
6
+ //#region src/composites/scope.ts
7
+ /**
8
+ * Composite Scope — runtime host-presence guard.
9
+ *
10
+ * The Component Semantics Projection treats Composition as a flat vocabulary
11
+ * (see `docs/.../component-model.md` §"Parent disambiguation"): a slot role
12
+ * like `'heading'` is legal on its declared Entity regardless of which host
13
+ * renders it. The data model intentionally has no `host` field, and the FSL
14
+ * Structural Language §10 lists no Host × Role legality matrix.
15
+ *
16
+ * What is *not* covered by that flatness is the runtime invariant that some
17
+ * sub-parts only make sense inside their host (e.g. `<DialogHeading>` solto
18
+ * is not a meaningful element). This module closes that gap with two tiny
19
+ * builders — chosen by *name*, not by a `<true>` type sentinel — so the
20
+ * author's intent is self-evident at the call site:
21
+ *
22
+ * 1. `createPresenceScope(host)` — pure host-presence guard. No state is
23
+ * shared; sub-parts only need to assert "I am inside <Host>". Provider
24
+ * takes no `value` prop. Used by Dialog, Form, TextField, Menu.
25
+ *
26
+ * 2. `createCompositeScope<T>(host)` — host shares typed state with its
27
+ * sub-parts (evaluation, controlled step, validation, …). Provider
28
+ * requires a `value` of type `T`. Used by Accordion, Wizard.
29
+ *
30
+ * Both builders share the same error contract: `use('<SubPart>')` outside
31
+ * the host throws an `Error` whose message names both the sub-part and the
32
+ * expected host. Both set `Context.displayName = '<Host>Scope'` for nice
33
+ * DevTools output.
34
+ *
35
+ * Authoring rule (mirrored in CONTRIBUTING §2.3): if the host has no value
36
+ * to share with sub-parts, use `createPresenceScope`. If TypeScript tempts
37
+ * you to write `createCompositeScope<true>('X')`, you wanted
38
+ * `createPresenceScope('X')`.
39
+ *
40
+ * @example Presence guard
41
+ * ```tsx
42
+ * const formScope = createPresenceScope('Form');
43
+ *
44
+ * export const Form = ({ children }) => (
45
+ * <formScope.Provider>{children}</formScope.Provider>
46
+ * );
47
+ *
48
+ * export const FormSubmit = (props) => {
49
+ * formScope.use('FormSubmit');
50
+ * return <button type="submit" {...props} />;
51
+ * };
52
+ * ```
53
+ *
54
+ * @example Stateful scope
55
+ * ```tsx
56
+ * const wizardScope = createCompositeScope<WizardContextValue>('Wizard');
57
+ *
58
+ * export const Wizard = ({ children }) => {
59
+ * const ctx = useWizardState(...);
60
+ * return <wizardScope.Provider value={ctx}>{children}</wizardScope.Provider>;
61
+ * };
62
+ *
63
+ * export const WizardNavigation = () => {
64
+ * const ctx = wizardScope.use('WizardNavigation');
65
+ * return <button onClick={ctx.goNext}>Next</button>;
66
+ * };
67
+ * ```
68
+ */
69
+ var PRESENT = Symbol("composite-scope.present");
70
+ /** Throws the canonical out-of-host error for a sub-part. */
71
+ var throwOutOfHost = (consumerDisplayName, hostDisplayName) => {
72
+ throw new Error(`<${consumerDisplayName}> must be rendered inside <${hostDisplayName}>.`);
73
+ };
74
+ /**
75
+ * Creates a scope where the host shares typed state with its sub-parts.
76
+ *
77
+ * @param hostDisplayName - Display name of the host component, used in the
78
+ * error message thrown by `use()` when a sub-part is rendered outside.
79
+ * Must match the host's `*Meta.displayName`.
80
+ */
81
+ var createCompositeScope = hostDisplayName => {
82
+ const Context = react.createContext(null);
83
+ Context.displayName = `${hostDisplayName}Scope`;
84
+ return {
85
+ Provider: Context.Provider,
86
+ use: consumerDisplayName => {
87
+ const value = react.useContext(Context);
88
+ if (value === null) return throwOutOfHost(consumerDisplayName, hostDisplayName);
89
+ return value;
90
+ }
91
+ };
92
+ };
93
+ /**
94
+ * Creates a presence-only scope. Sub-parts use `scope.use('<Name>')` to
95
+ * assert they are rendered inside `<Host>` — no value is shared.
96
+ *
97
+ * Use this when the host has nothing to publish to sub-parts. If you find
98
+ * yourself reaching for `createCompositeScope<true>('X')`, use this
99
+ * instead — it is the same contract with a clearer name and zero
100
+ * boilerplate at the call site (`<Provider>` instead of
101
+ * `<Provider value={true}>`).
102
+ */
103
+ var createPresenceScope = hostDisplayName => {
104
+ const Context = react.createContext(null);
105
+ Context.displayName = `${hostDisplayName}Scope`;
106
+ const Provider = ({
107
+ children
108
+ }) => {
109
+ return react.createElement(Context.Provider, {
110
+ value: PRESENT
111
+ }, children);
112
+ };
113
+ Provider.displayName = `${hostDisplayName}ScopeProvider`;
114
+ return {
115
+ Provider,
116
+ use: consumerDisplayName => {
117
+ if (react.useContext(Context) !== PRESENT) throwOutOfHost(consumerDisplayName, hostDisplayName);
118
+ }
119
+ };
120
+ };
121
+
122
+ //#endregion
123
+ exports.createCompositeScope = createCompositeScope;
124
+ exports.createPresenceScope = createPresenceScope;