@szum-tech/design-system 2.5.1 → 2.7.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.
- package/dist/{chunk-75T7KAAY.js → chunk-36YD6ICC.js} +2 -2
- package/dist/chunk-3WSQRFUY.cjs +11 -0
- package/dist/{chunk-V5OVQTDR.js → chunk-5BTQ6BQA.js} +2 -2
- package/dist/chunk-7EYMOUWG.cjs +51 -0
- package/dist/{chunk-MOOWZNA6.js → chunk-7V34QHYR.js} +3 -3
- package/dist/chunk-D3MOZUNH.cjs +1043 -0
- package/dist/chunk-DFD2WUOU.js +27 -0
- package/dist/{chunk-Q2IKZZ3U.cjs → chunk-EIXSMEDP.cjs} +1 -0
- package/dist/chunk-EW6TE3N5.cjs +38 -0
- package/dist/{chunk-3DSBDIFJ.cjs → chunk-FPFRA5Q6.cjs} +2 -2
- package/dist/{chunk-BJ553XYM.cjs → chunk-G6VXQ7DJ.cjs} +3 -3
- package/dist/{chunk-RXYZURP4.js → chunk-GEACYHTU.js} +1 -0
- package/dist/chunk-H5O5L6XT.js +14 -0
- package/dist/chunk-I5P2HH5Z.js +136 -0
- package/dist/{chunk-3PV6NLP5.js → chunk-IAI7BIAG.js} +3 -3
- package/dist/{chunk-XKXP3W3H.cjs → chunk-K4TRAPRN.cjs} +3 -3
- package/dist/{chunk-4C7M4HBP.js → chunk-MI3CQBHC.js} +3 -3
- package/dist/{chunk-KXTNZ4UO.cjs → chunk-NHFHKMX2.cjs} +3 -3
- package/dist/{chunk-6L3QPLRR.cjs → chunk-OIWEXHFE.cjs} +3 -3
- package/dist/chunk-P5IUC7HJ.js +9 -0
- package/dist/chunk-S5BN23O7.cjs +147 -0
- package/dist/chunk-XIPREW2R.js +996 -0
- package/dist/{chunk-WMMJEZ7Y.js → chunk-YJFJLF7Y.js} +3 -3
- package/dist/{chunk-FPK72OV4.cjs → chunk-ZZ3EBGSD.cjs} +2 -2
- package/dist/components/badge/index.cjs +2 -2
- package/dist/components/badge/index.js +1 -1
- package/dist/components/button/index.cjs +2 -2
- package/dist/components/button/index.js +1 -1
- package/dist/components/card/index.cjs +7 -7
- package/dist/components/card/index.js +1 -1
- package/dist/components/form/index.cjs +21 -17
- package/dist/components/form/index.js +14 -10
- package/dist/components/index.cjs +194 -70
- package/dist/components/index.d.cts +4 -0
- package/dist/components/index.d.ts +4 -0
- package/dist/components/index.js +14 -10
- package/dist/components/input/index.cjs +2 -2
- package/dist/components/input/index.js +1 -1
- package/dist/components/item/index.cjs +48 -0
- package/dist/components/item/index.d.cts +60 -0
- package/dist/components/item/index.d.ts +60 -0
- package/dist/components/item/index.js +3 -0
- package/dist/components/select/index.cjs +3 -3
- package/dist/components/select/index.js +1 -1
- package/dist/components/separator/index.cjs +2 -2
- package/dist/components/separator/index.js +1 -1
- package/dist/components/spinner/index.cjs +11 -0
- package/dist/components/spinner/index.d.cts +7 -0
- package/dist/components/spinner/index.d.ts +7 -0
- package/dist/components/spinner/index.js +2 -0
- package/dist/components/stepper/index.cjs +103 -0
- package/dist/components/stepper/index.d.cts +162 -0
- package/dist/components/stepper/index.d.ts +162 -0
- package/dist/components/stepper/index.js +22 -0
- package/dist/components/textarea/index.cjs +2 -2
- package/dist/components/textarea/index.js +1 -1
- package/dist/contexts/index.cjs +18 -0
- package/dist/contexts/index.d.cts +11 -0
- package/dist/contexts/index.d.ts +11 -0
- package/dist/contexts/index.js +1 -0
- package/dist/hooks/index.cjs +18 -0
- package/dist/hooks/index.d.cts +14 -0
- package/dist/hooks/index.d.ts +14 -0
- package/dist/hooks/index.js +1 -0
- package/dist/icons/index.d.cts +3 -0
- package/dist/icons/index.d.ts +3 -0
- package/package.json +22 -1
- package/dist/chunk-DH5YKYXV.cjs +0 -116
- package/dist/chunk-SPCZ3GVM.js +0 -88
|
@@ -0,0 +1,996 @@
|
|
|
1
|
+
import { HelperText } from './chunk-5PBHBOXI.js';
|
|
2
|
+
import { Label } from './chunk-VZKTT6CG.js';
|
|
3
|
+
import { useDirection, Direction } from './chunk-H5O5L6XT.js';
|
|
4
|
+
import { useLazyRef, useIsomorphicLayoutEffect } from './chunk-DFD2WUOU.js';
|
|
5
|
+
import { cn } from './chunk-ZD2QRAOX.js';
|
|
6
|
+
import { useFormContext, FormProvider, Controller } from 'react-hook-form';
|
|
7
|
+
import * as React12 from 'react';
|
|
8
|
+
import { twMerge } from 'tailwind-merge';
|
|
9
|
+
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
10
|
+
import { Slot } from '@radix-ui/react-slot';
|
|
11
|
+
|
|
12
|
+
var Form = FormProvider;
|
|
13
|
+
var FormItemContext = React12.createContext({});
|
|
14
|
+
var FormItem = React12.forwardRef(function({ className, ...props }, ref) {
|
|
15
|
+
const id = React12.useId();
|
|
16
|
+
return /* @__PURE__ */ jsx(FormItemContext.Provider, { value: { id }, children: /* @__PURE__ */ jsx("div", { ref, className: twMerge("space-y-2", className), ...props }) });
|
|
17
|
+
});
|
|
18
|
+
FormItem.displayName = "FormItem";
|
|
19
|
+
var FormFieldContext = React12.createContext({});
|
|
20
|
+
var FormField = ({
|
|
21
|
+
...props
|
|
22
|
+
}) => {
|
|
23
|
+
return /* @__PURE__ */ jsx(FormFieldContext.Provider, { value: { name: props.name }, children: /* @__PURE__ */ jsx(Controller, { ...props }) });
|
|
24
|
+
};
|
|
25
|
+
var useFormField = () => {
|
|
26
|
+
const fieldContext = React12.useContext(FormFieldContext);
|
|
27
|
+
const itemContext = React12.useContext(FormItemContext);
|
|
28
|
+
const { getFieldState, formState } = useFormContext();
|
|
29
|
+
const fieldState = getFieldState(fieldContext.name, formState);
|
|
30
|
+
if (!fieldContext) {
|
|
31
|
+
throw new Error("useFormField should be used within <FormField>");
|
|
32
|
+
}
|
|
33
|
+
const { id } = itemContext;
|
|
34
|
+
return {
|
|
35
|
+
id,
|
|
36
|
+
name: fieldContext.name,
|
|
37
|
+
formItemId: `${id}-form-item`,
|
|
38
|
+
formDescriptionId: `${id}-form-item-description`,
|
|
39
|
+
formMessageId: `${id}-form-item-message`,
|
|
40
|
+
...fieldState
|
|
41
|
+
};
|
|
42
|
+
};
|
|
43
|
+
var FormLabel = React12.forwardRef(
|
|
44
|
+
({ className, caption, ...props }, ref) => {
|
|
45
|
+
const { error, formItemId } = useFormField();
|
|
46
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex flex-row items-end justify-between", children: [
|
|
47
|
+
/* @__PURE__ */ jsx(
|
|
48
|
+
Label,
|
|
49
|
+
{
|
|
50
|
+
ref,
|
|
51
|
+
className: twMerge(error ? "text-error-500" : null, className),
|
|
52
|
+
htmlFor: formItemId,
|
|
53
|
+
...props
|
|
54
|
+
}
|
|
55
|
+
),
|
|
56
|
+
caption ? /* @__PURE__ */ jsx("div", { className: "typography-caption text-gray-200", children: caption }) : null
|
|
57
|
+
] });
|
|
58
|
+
}
|
|
59
|
+
);
|
|
60
|
+
FormLabel.displayName = "FormLabel";
|
|
61
|
+
var FormControl = React12.forwardRef(function(props, ref) {
|
|
62
|
+
const { error, formItemId, formDescriptionId, formMessageId } = useFormField();
|
|
63
|
+
const newProps = { ...props, invalid: !!error };
|
|
64
|
+
return /* @__PURE__ */ jsx(
|
|
65
|
+
Slot,
|
|
66
|
+
{
|
|
67
|
+
ref,
|
|
68
|
+
id: formItemId,
|
|
69
|
+
"aria-describedby": !error ? `${formDescriptionId}` : `${formDescriptionId} ${formMessageId}`,
|
|
70
|
+
"aria-invalid": !!error,
|
|
71
|
+
...newProps
|
|
72
|
+
}
|
|
73
|
+
);
|
|
74
|
+
});
|
|
75
|
+
FormControl.displayName = "FormControl";
|
|
76
|
+
|
|
77
|
+
// src/components/stepper/stepper.constants.ts
|
|
78
|
+
var STEPPER_ROOT_NAME = "Stepper";
|
|
79
|
+
var STEPPER_NAV_NAME = "StepperNav";
|
|
80
|
+
var STEPPER_ITEM_NAME = "StepperItem";
|
|
81
|
+
var STEPPER_TRIGGER_NAME = "StepperTrigger";
|
|
82
|
+
var STEPPER_INDICATOR_NAME = "StepperIndicator";
|
|
83
|
+
var STEPPER_TITLE_NAME = "StepperTitle";
|
|
84
|
+
var STEPPER_DESCRIPTION_NAME = "StepperDescription";
|
|
85
|
+
var STEPPER_CONTENT_NAME = "StepperContent";
|
|
86
|
+
var STEPPER_PREV_TRIGGER_NAME = "StepperPrevTrigger";
|
|
87
|
+
var STEPPER_NEXT_TRIGGER_NAME = "StepperNextTrigger";
|
|
88
|
+
var STEPPER_ENTRY_FOCUS = "stepperFocusGroup.onEntryFocus";
|
|
89
|
+
var STEPPER_EVENT_OPTIONS = { bubbles: false, cancelable: true };
|
|
90
|
+
var STEPPER_ARROW_KEYS = ["ArrowUp", "ArrowDown", "ArrowLeft", "ArrowRight"];
|
|
91
|
+
var STEPPER_MAP_KEY_TO_FOCUS_INTENT = {
|
|
92
|
+
ArrowLeft: "prev",
|
|
93
|
+
ArrowUp: "prev",
|
|
94
|
+
ArrowRight: "next",
|
|
95
|
+
ArrowDown: "next",
|
|
96
|
+
PageUp: "first",
|
|
97
|
+
Home: "first",
|
|
98
|
+
PageDown: "last",
|
|
99
|
+
End: "last"
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
// src/components/stepper/stepper.context.tsx
|
|
103
|
+
var StepperContext = React12.createContext(null);
|
|
104
|
+
function useStepperContext(consumerName) {
|
|
105
|
+
const context = React12.useContext(StepperContext);
|
|
106
|
+
if (!context) {
|
|
107
|
+
throw new Error(`\`${consumerName}\` must be used within \`${STEPPER_ROOT_NAME}\``);
|
|
108
|
+
}
|
|
109
|
+
return context;
|
|
110
|
+
}
|
|
111
|
+
function createStepperStore(listenersRef, stateRef, onValueChange, onValueComplete, onValueAdd, onValueRemove, onValidate) {
|
|
112
|
+
const store = {
|
|
113
|
+
subscribe: (cb) => {
|
|
114
|
+
if (listenersRef.current) {
|
|
115
|
+
listenersRef.current.add(cb);
|
|
116
|
+
return () => listenersRef.current?.delete(cb);
|
|
117
|
+
}
|
|
118
|
+
return () => {
|
|
119
|
+
};
|
|
120
|
+
},
|
|
121
|
+
getState: () => stateRef.current ?? {
|
|
122
|
+
steps: /* @__PURE__ */ new Map(),
|
|
123
|
+
value: void 0
|
|
124
|
+
},
|
|
125
|
+
setState: (key, value) => {
|
|
126
|
+
const state = stateRef.current;
|
|
127
|
+
if (!state || Object.is(state[key], value)) return;
|
|
128
|
+
if (key === "value" && typeof value === "string") {
|
|
129
|
+
state.value = value;
|
|
130
|
+
onValueChange?.(value);
|
|
131
|
+
} else {
|
|
132
|
+
state[key] = value;
|
|
133
|
+
}
|
|
134
|
+
store.notify();
|
|
135
|
+
},
|
|
136
|
+
setStateWithValidation: async (value, direction) => {
|
|
137
|
+
if (!onValidate) {
|
|
138
|
+
store.setState("value", value);
|
|
139
|
+
return true;
|
|
140
|
+
}
|
|
141
|
+
try {
|
|
142
|
+
const isValid = await onValidate(value, direction);
|
|
143
|
+
if (isValid) {
|
|
144
|
+
store.setState("value", value);
|
|
145
|
+
}
|
|
146
|
+
return isValid;
|
|
147
|
+
} catch {
|
|
148
|
+
return false;
|
|
149
|
+
}
|
|
150
|
+
},
|
|
151
|
+
hasValidation: () => !!onValidate,
|
|
152
|
+
addStep: (newStep) => {
|
|
153
|
+
const state = stateRef.current;
|
|
154
|
+
if (state) {
|
|
155
|
+
state.steps = new Map(state.steps);
|
|
156
|
+
state.steps.set(newStep.value, newStep);
|
|
157
|
+
onValueAdd?.(newStep.value);
|
|
158
|
+
store.notify();
|
|
159
|
+
}
|
|
160
|
+
},
|
|
161
|
+
removeStep: (value) => {
|
|
162
|
+
const state = stateRef.current;
|
|
163
|
+
if (state) {
|
|
164
|
+
state.steps = new Map(state.steps);
|
|
165
|
+
state.steps.delete(value);
|
|
166
|
+
onValueRemove?.(value);
|
|
167
|
+
store.notify();
|
|
168
|
+
}
|
|
169
|
+
},
|
|
170
|
+
setStep: ({ value, disabled, loading, completed }) => {
|
|
171
|
+
const state = stateRef.current;
|
|
172
|
+
if (state) {
|
|
173
|
+
const step = state.steps.get(value);
|
|
174
|
+
if (step) {
|
|
175
|
+
const updatedStep = { ...step, completed, disabled, loading };
|
|
176
|
+
state.steps = new Map(state.steps);
|
|
177
|
+
state.steps.set(value, updatedStep);
|
|
178
|
+
if (completed !== step.completed) {
|
|
179
|
+
onValueComplete?.(value, completed);
|
|
180
|
+
}
|
|
181
|
+
store.notify();
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
},
|
|
185
|
+
notify: () => {
|
|
186
|
+
if (listenersRef.current) {
|
|
187
|
+
for (const cb of listenersRef.current) {
|
|
188
|
+
cb();
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
};
|
|
193
|
+
return store;
|
|
194
|
+
}
|
|
195
|
+
var StepperStoreContext = React12.createContext(null);
|
|
196
|
+
function useStepperStoreContext(consumerName) {
|
|
197
|
+
const context = React12.useContext(StepperStoreContext);
|
|
198
|
+
if (!context) {
|
|
199
|
+
throw new Error(`\`${consumerName}\` must be used within \`${STEPPER_ROOT_NAME}\``);
|
|
200
|
+
}
|
|
201
|
+
return context;
|
|
202
|
+
}
|
|
203
|
+
function useStepperStore(selector) {
|
|
204
|
+
const store = useStepperStoreContext("useStore");
|
|
205
|
+
const getSnapshot = React12.useCallback(() => selector(store.getState()), [selector, store]);
|
|
206
|
+
return React12.useSyncExternalStore(store.subscribe, getSnapshot, getSnapshot);
|
|
207
|
+
}
|
|
208
|
+
function Stepper({
|
|
209
|
+
value,
|
|
210
|
+
defaultValue,
|
|
211
|
+
onValueChange,
|
|
212
|
+
onValueComplete,
|
|
213
|
+
onValueAdd,
|
|
214
|
+
onValueRemove,
|
|
215
|
+
onValidate,
|
|
216
|
+
id: idProp,
|
|
217
|
+
dir: dirProp,
|
|
218
|
+
orientation = "horizontal",
|
|
219
|
+
activationMode = "automatic",
|
|
220
|
+
asChild,
|
|
221
|
+
disabled = false,
|
|
222
|
+
nonInteractive = false,
|
|
223
|
+
loop = false,
|
|
224
|
+
className,
|
|
225
|
+
indicators = {},
|
|
226
|
+
...rootProps
|
|
227
|
+
}) {
|
|
228
|
+
const id = React12.useId();
|
|
229
|
+
const rootId = idProp ?? id;
|
|
230
|
+
const listenersRef = useLazyRef(() => /* @__PURE__ */ new Set());
|
|
231
|
+
const stateRef = useLazyRef(() => ({
|
|
232
|
+
steps: /* @__PURE__ */ new Map(),
|
|
233
|
+
value: value ?? defaultValue
|
|
234
|
+
}));
|
|
235
|
+
const store = React12.useMemo(
|
|
236
|
+
() => createStepperStore(listenersRef, stateRef, onValueChange, onValueComplete, onValueAdd, onValueRemove, onValidate),
|
|
237
|
+
[listenersRef, stateRef, onValueChange, onValueComplete, onValueAdd, onValueRemove, onValidate]
|
|
238
|
+
);
|
|
239
|
+
useIsomorphicLayoutEffect(() => {
|
|
240
|
+
if (value !== void 0) {
|
|
241
|
+
store.setState("value", value);
|
|
242
|
+
}
|
|
243
|
+
}, [value]);
|
|
244
|
+
const dir = useDirection(dirProp);
|
|
245
|
+
const contextValue = React12.useMemo(
|
|
246
|
+
() => ({
|
|
247
|
+
id: rootId,
|
|
248
|
+
dir,
|
|
249
|
+
orientation,
|
|
250
|
+
activationMode,
|
|
251
|
+
disabled,
|
|
252
|
+
nonInteractive,
|
|
253
|
+
loop,
|
|
254
|
+
indicators
|
|
255
|
+
}),
|
|
256
|
+
[rootId, dir, orientation, activationMode, disabled, nonInteractive, loop, indicators]
|
|
257
|
+
);
|
|
258
|
+
const RootPrimitive = asChild ? Slot : "div";
|
|
259
|
+
return /* @__PURE__ */ jsx(StepperStoreContext.Provider, { value: store, children: /* @__PURE__ */ jsx(StepperContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx(
|
|
260
|
+
RootPrimitive,
|
|
261
|
+
{
|
|
262
|
+
id: rootId,
|
|
263
|
+
"data-disabled": disabled ? "" : void 0,
|
|
264
|
+
"data-orientation": orientation,
|
|
265
|
+
"data-slot": "stepper",
|
|
266
|
+
dir,
|
|
267
|
+
...rootProps,
|
|
268
|
+
className: cn("flex w-full flex-col gap-4 data-[orientation=vertical]:flex-row", className)
|
|
269
|
+
}
|
|
270
|
+
) }) });
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
// src/components/stepper/stepper.types.ts
|
|
274
|
+
var StepperFocusIntent = {
|
|
275
|
+
FIRST: "first",
|
|
276
|
+
LAST: "last",
|
|
277
|
+
PREV: "prev",
|
|
278
|
+
NEXT: "next"
|
|
279
|
+
};
|
|
280
|
+
var StepperOrientation = {
|
|
281
|
+
HORIZONTAL: "horizontal",
|
|
282
|
+
VERTICAL: "vertical"
|
|
283
|
+
};
|
|
284
|
+
var StepperNavigationDirection = {
|
|
285
|
+
NEXT: "next",
|
|
286
|
+
PREV: "prev"
|
|
287
|
+
};
|
|
288
|
+
var StepperActivationMode = {
|
|
289
|
+
AUTOMATIC: "automatic",
|
|
290
|
+
MANUAL: "manual"
|
|
291
|
+
};
|
|
292
|
+
var StepperDataState = {
|
|
293
|
+
INACTIVE: "inactive",
|
|
294
|
+
ACTIVE: "active",
|
|
295
|
+
COMPLETED: "completed"
|
|
296
|
+
};
|
|
297
|
+
var StepperFocusContext = React12.createContext(null);
|
|
298
|
+
function useStepperFocusContext(consumerName) {
|
|
299
|
+
const context = React12.useContext(StepperFocusContext);
|
|
300
|
+
if (!context) {
|
|
301
|
+
throw new Error(`\`${consumerName}\` must be used within \`FocusProvider\``);
|
|
302
|
+
}
|
|
303
|
+
return context;
|
|
304
|
+
}
|
|
305
|
+
function setRef(ref, value) {
|
|
306
|
+
if (typeof ref === "function") {
|
|
307
|
+
return ref(value);
|
|
308
|
+
} else if (ref !== null && ref !== void 0) {
|
|
309
|
+
ref.current = value;
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
function composeRefs(...refs) {
|
|
313
|
+
return (node) => {
|
|
314
|
+
let hasCleanup = false;
|
|
315
|
+
const cleanups = refs.map((ref) => {
|
|
316
|
+
const cleanup = setRef(ref, node);
|
|
317
|
+
if (!hasCleanup && typeof cleanup == "function") {
|
|
318
|
+
hasCleanup = true;
|
|
319
|
+
}
|
|
320
|
+
return cleanup;
|
|
321
|
+
});
|
|
322
|
+
if (hasCleanup) {
|
|
323
|
+
return () => {
|
|
324
|
+
for (let i = 0; i < cleanups.length; i++) {
|
|
325
|
+
const cleanup = cleanups[i];
|
|
326
|
+
if (typeof cleanup == "function") {
|
|
327
|
+
cleanup();
|
|
328
|
+
} else {
|
|
329
|
+
setRef(refs[i], null);
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
};
|
|
333
|
+
}
|
|
334
|
+
};
|
|
335
|
+
}
|
|
336
|
+
function useComposedRefs(...refs) {
|
|
337
|
+
return React12.useCallback(composeRefs(...refs), refs);
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
// src/components/stepper/stepper.utils.tsx
|
|
341
|
+
function focusFirst(candidates, preventScroll = false) {
|
|
342
|
+
const PREVIOUSLY_FOCUSED_ELEMENT = document.activeElement;
|
|
343
|
+
for (const candidateRef of candidates) {
|
|
344
|
+
const candidate = candidateRef.current;
|
|
345
|
+
if (!candidate) continue;
|
|
346
|
+
if (candidate === PREVIOUSLY_FOCUSED_ELEMENT) return;
|
|
347
|
+
candidate.focus({ preventScroll });
|
|
348
|
+
if (document.activeElement !== PREVIOUSLY_FOCUSED_ELEMENT) return;
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
function getDataState(value, itemValue, stepState, steps, variant = "item") {
|
|
352
|
+
const stepKeys = Array.from(steps.keys());
|
|
353
|
+
const currentIndex = stepKeys.indexOf(itemValue);
|
|
354
|
+
if (stepState?.completed) {
|
|
355
|
+
return StepperDataState.COMPLETED;
|
|
356
|
+
}
|
|
357
|
+
if (value === itemValue) {
|
|
358
|
+
return variant === "separator" ? StepperDataState.INACTIVE : StepperDataState.ACTIVE;
|
|
359
|
+
}
|
|
360
|
+
if (value) {
|
|
361
|
+
const activeIndex = stepKeys.indexOf(value);
|
|
362
|
+
if (activeIndex > currentIndex) {
|
|
363
|
+
return StepperDataState.COMPLETED;
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
return StepperDataState.INACTIVE;
|
|
367
|
+
}
|
|
368
|
+
function getId(id, variant, value) {
|
|
369
|
+
return `${id}-${variant}-${value}`;
|
|
370
|
+
}
|
|
371
|
+
function wrapArray(array, startIndex) {
|
|
372
|
+
return array.map((_, index) => array[(startIndex + index) % array.length]);
|
|
373
|
+
}
|
|
374
|
+
function getDirectionAwareKey(key, dir) {
|
|
375
|
+
if (dir !== Direction.RTL) return key;
|
|
376
|
+
return key === "ArrowLeft" ? "ArrowRight" : key === "ArrowRight" ? "ArrowLeft" : key;
|
|
377
|
+
}
|
|
378
|
+
function getFocusIntent(event, dir, orientation) {
|
|
379
|
+
const key = getDirectionAwareKey(event.key, dir);
|
|
380
|
+
if (orientation === "horizontal" && ["ArrowUp", "ArrowDown"].includes(key)) return void 0;
|
|
381
|
+
if (orientation === "vertical" && ["ArrowLeft", "ArrowRight"].includes(key)) return void 0;
|
|
382
|
+
return STEPPER_MAP_KEY_TO_FOCUS_INTENT[key];
|
|
383
|
+
}
|
|
384
|
+
function StepperNav({ className, children, asChild, ref, ...listProps }) {
|
|
385
|
+
const context = useStepperContext(STEPPER_NAV_NAME);
|
|
386
|
+
const orientation = context.orientation;
|
|
387
|
+
const currentValue = useStepperStore((state) => state.value);
|
|
388
|
+
const [tabStopId, setTabStopId] = React12.useState(null);
|
|
389
|
+
const [isTabbingBackOut, setIsTabbingBackOut] = React12.useState(false);
|
|
390
|
+
const [focusableItemCount, setFocusableItemCount] = React12.useState(0);
|
|
391
|
+
const isClickFocusRef = React12.useRef(false);
|
|
392
|
+
const itemsRef = React12.useRef(/* @__PURE__ */ new Map());
|
|
393
|
+
const listRef = React12.useRef(null);
|
|
394
|
+
const composedRef = useComposedRefs(ref, listRef);
|
|
395
|
+
const onItemFocus = React12.useCallback((tabStopId2) => {
|
|
396
|
+
setTabStopId(tabStopId2);
|
|
397
|
+
}, []);
|
|
398
|
+
const onItemShiftTab = React12.useCallback(() => {
|
|
399
|
+
setIsTabbingBackOut(true);
|
|
400
|
+
}, []);
|
|
401
|
+
const onFocusableItemAdd = React12.useCallback(() => {
|
|
402
|
+
setFocusableItemCount((prevCount) => prevCount + 1);
|
|
403
|
+
}, []);
|
|
404
|
+
const onFocusableItemRemove = React12.useCallback(() => {
|
|
405
|
+
setFocusableItemCount((prevCount) => prevCount - 1);
|
|
406
|
+
}, []);
|
|
407
|
+
const onItemRegister = React12.useCallback((item) => {
|
|
408
|
+
itemsRef.current.set(item.id, item);
|
|
409
|
+
}, []);
|
|
410
|
+
const onItemUnregister = React12.useCallback((id) => {
|
|
411
|
+
itemsRef.current.delete(id);
|
|
412
|
+
}, []);
|
|
413
|
+
const getItems = React12.useCallback(() => {
|
|
414
|
+
return Array.from(itemsRef.current.values()).filter((item) => item.ref.current).sort((a, b) => {
|
|
415
|
+
const elementA = a.ref.current;
|
|
416
|
+
const elementB = b.ref.current;
|
|
417
|
+
if (!elementA || !elementB) return 0;
|
|
418
|
+
const position = elementA.compareDocumentPosition(elementB);
|
|
419
|
+
if (position & Node.DOCUMENT_POSITION_FOLLOWING) {
|
|
420
|
+
return -1;
|
|
421
|
+
}
|
|
422
|
+
if (position & Node.DOCUMENT_POSITION_PRECEDING) {
|
|
423
|
+
return 1;
|
|
424
|
+
}
|
|
425
|
+
return 0;
|
|
426
|
+
});
|
|
427
|
+
}, []);
|
|
428
|
+
const onBlur = React12.useCallback(
|
|
429
|
+
(event) => {
|
|
430
|
+
listProps.onBlur?.(event);
|
|
431
|
+
if (event.defaultPrevented) return;
|
|
432
|
+
setIsTabbingBackOut(false);
|
|
433
|
+
},
|
|
434
|
+
[listProps.onBlur]
|
|
435
|
+
);
|
|
436
|
+
const onFocus = React12.useCallback(
|
|
437
|
+
(event) => {
|
|
438
|
+
listProps.onFocus?.(event);
|
|
439
|
+
if (event.defaultPrevented) return;
|
|
440
|
+
const isKeyboardFocus = !isClickFocusRef.current;
|
|
441
|
+
if (event.target === event.currentTarget && isKeyboardFocus && !isTabbingBackOut) {
|
|
442
|
+
const entryFocusEvent = new CustomEvent(STEPPER_ENTRY_FOCUS, STEPPER_EVENT_OPTIONS);
|
|
443
|
+
event.currentTarget.dispatchEvent(entryFocusEvent);
|
|
444
|
+
if (!entryFocusEvent.defaultPrevented) {
|
|
445
|
+
const items = Array.from(itemsRef.current.values()).filter((item) => !item.disabled);
|
|
446
|
+
const selectedItem = currentValue ? items.find((item) => item.value === currentValue) : void 0;
|
|
447
|
+
const activeItem = items.find((item) => item.active);
|
|
448
|
+
const currentItem = items.find((item) => item.id === tabStopId);
|
|
449
|
+
const candidateItems = [selectedItem, activeItem, currentItem, ...items].filter(
|
|
450
|
+
Boolean
|
|
451
|
+
);
|
|
452
|
+
const candidateRefs = candidateItems.map((item) => item.ref);
|
|
453
|
+
focusFirst(candidateRefs, false);
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
isClickFocusRef.current = false;
|
|
457
|
+
},
|
|
458
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
459
|
+
[listProps.onFocus, isTabbingBackOut, currentValue, tabStopId]
|
|
460
|
+
);
|
|
461
|
+
const onMouseDown = React12.useCallback(
|
|
462
|
+
(event) => {
|
|
463
|
+
listProps.onMouseDown?.(event);
|
|
464
|
+
if (event.defaultPrevented) return;
|
|
465
|
+
isClickFocusRef.current = true;
|
|
466
|
+
},
|
|
467
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
468
|
+
[listProps.onMouseDown]
|
|
469
|
+
);
|
|
470
|
+
const focusContextValue = React12.useMemo(
|
|
471
|
+
() => ({
|
|
472
|
+
tabStopId,
|
|
473
|
+
onItemFocus,
|
|
474
|
+
onItemShiftTab,
|
|
475
|
+
onFocusableItemAdd,
|
|
476
|
+
onFocusableItemRemove,
|
|
477
|
+
onItemRegister,
|
|
478
|
+
onItemUnregister,
|
|
479
|
+
getItems
|
|
480
|
+
}),
|
|
481
|
+
[
|
|
482
|
+
tabStopId,
|
|
483
|
+
onItemFocus,
|
|
484
|
+
onItemShiftTab,
|
|
485
|
+
onFocusableItemAdd,
|
|
486
|
+
onFocusableItemRemove,
|
|
487
|
+
onItemRegister,
|
|
488
|
+
onItemUnregister,
|
|
489
|
+
getItems
|
|
490
|
+
]
|
|
491
|
+
);
|
|
492
|
+
const StepperNavPrimitive = asChild ? Slot : "nav";
|
|
493
|
+
return /* @__PURE__ */ jsx(StepperFocusContext.Provider, { value: focusContextValue, children: /* @__PURE__ */ jsx(
|
|
494
|
+
StepperNavPrimitive,
|
|
495
|
+
{
|
|
496
|
+
role: "tablist",
|
|
497
|
+
"data-slot": "stepper-nav",
|
|
498
|
+
"aria-orientation": orientation,
|
|
499
|
+
"data-orientation": orientation,
|
|
500
|
+
dir: context.dir,
|
|
501
|
+
tabIndex: isTabbingBackOut || focusableItemCount === 0 ? -1 : 0,
|
|
502
|
+
ref: composedRef,
|
|
503
|
+
onBlur,
|
|
504
|
+
onFocus,
|
|
505
|
+
onMouseDown,
|
|
506
|
+
className: cn(
|
|
507
|
+
"group/stepper-nav inline-flex gap-4",
|
|
508
|
+
"data-[orientation=horizontal]:w-full data-[orientation=horizontal]:flex-row data-[orientation=vertical]:flex-col",
|
|
509
|
+
className
|
|
510
|
+
),
|
|
511
|
+
...listProps,
|
|
512
|
+
children
|
|
513
|
+
}
|
|
514
|
+
) });
|
|
515
|
+
}
|
|
516
|
+
var StepperItemContext = React12.createContext(null);
|
|
517
|
+
function useStepperItemContext(consumerName) {
|
|
518
|
+
const context = React12.useContext(StepperItemContext);
|
|
519
|
+
if (!context) {
|
|
520
|
+
throw new Error(`\`${consumerName}\` must be used within \`${STEPPER_ITEM_NAME}\``);
|
|
521
|
+
}
|
|
522
|
+
return context;
|
|
523
|
+
}
|
|
524
|
+
function StepperItem({
|
|
525
|
+
value: itemValue,
|
|
526
|
+
completed = false,
|
|
527
|
+
disabled = false,
|
|
528
|
+
loading = false,
|
|
529
|
+
asChild,
|
|
530
|
+
className,
|
|
531
|
+
children,
|
|
532
|
+
...props
|
|
533
|
+
}) {
|
|
534
|
+
const { orientation, dir } = useStepperContext(STEPPER_ITEM_NAME);
|
|
535
|
+
const store = useStepperStoreContext(STEPPER_ITEM_NAME);
|
|
536
|
+
const value = useStepperStore((state) => state.value);
|
|
537
|
+
useIsomorphicLayoutEffect(() => {
|
|
538
|
+
store.addStep({ value: itemValue, completed, disabled, loading });
|
|
539
|
+
return () => {
|
|
540
|
+
store.removeStep(itemValue);
|
|
541
|
+
};
|
|
542
|
+
}, [itemValue, completed, disabled, loading]);
|
|
543
|
+
useIsomorphicLayoutEffect(() => {
|
|
544
|
+
store.setStep({ value: itemValue, completed, disabled, loading });
|
|
545
|
+
}, [itemValue, completed, disabled, loading]);
|
|
546
|
+
const stepState = useStepperStore((state) => state.steps.get(itemValue));
|
|
547
|
+
const steps = useStepperStore((state) => state.steps);
|
|
548
|
+
const dataState = getDataState(value, itemValue, stepState, steps);
|
|
549
|
+
const itemContextValue = React12.useMemo(
|
|
550
|
+
() => ({
|
|
551
|
+
value: itemValue,
|
|
552
|
+
stepState
|
|
553
|
+
}),
|
|
554
|
+
[itemValue, stepState]
|
|
555
|
+
);
|
|
556
|
+
const StepperItemPrimitive = asChild ? Slot : "div";
|
|
557
|
+
return /* @__PURE__ */ jsx(StepperItemContext.Provider, { value: itemContextValue, children: /* @__PURE__ */ jsxs(
|
|
558
|
+
StepperItemPrimitive,
|
|
559
|
+
{
|
|
560
|
+
"data-disabled": stepState?.disabled ? "" : void 0,
|
|
561
|
+
"data-orientation": orientation,
|
|
562
|
+
"data-state": dataState,
|
|
563
|
+
"data-slot": "stepper-item",
|
|
564
|
+
dir,
|
|
565
|
+
className: cn(
|
|
566
|
+
"group/step flex flex-1 flex-col justify-end",
|
|
567
|
+
"",
|
|
568
|
+
// "group-data-[orientation=horizontal]/stepper-nav:flex-row group-data-[orientation=vertical]/stepper-nav:flex-col",
|
|
569
|
+
className
|
|
570
|
+
),
|
|
571
|
+
...props,
|
|
572
|
+
children: [
|
|
573
|
+
children,
|
|
574
|
+
/* @__PURE__ */ jsx(
|
|
575
|
+
"div",
|
|
576
|
+
{
|
|
577
|
+
"data-state": dataState,
|
|
578
|
+
className: cn(
|
|
579
|
+
"h-1 w-full bg-gray-800 transition-colors duration-500",
|
|
580
|
+
"data-[state=active]:bg-primary-500 data-[state=completed]:bg-success-500"
|
|
581
|
+
)
|
|
582
|
+
}
|
|
583
|
+
)
|
|
584
|
+
]
|
|
585
|
+
}
|
|
586
|
+
) });
|
|
587
|
+
}
|
|
588
|
+
function StepperTrigger({ asChild, disabled, className, ref, ...triggerProps }) {
|
|
589
|
+
const context = useStepperContext(STEPPER_TRIGGER_NAME);
|
|
590
|
+
const itemContext = useStepperItemContext(STEPPER_TRIGGER_NAME);
|
|
591
|
+
const store = useStepperStoreContext(STEPPER_TRIGGER_NAME);
|
|
592
|
+
const focusContext = useStepperFocusContext(STEPPER_TRIGGER_NAME);
|
|
593
|
+
const value = useStepperStore((state) => state.value);
|
|
594
|
+
const itemValue = itemContext.value;
|
|
595
|
+
const stepState = useStepperStore((state) => state.steps.get(itemValue));
|
|
596
|
+
const activationMode = context.activationMode;
|
|
597
|
+
const orientation = context.orientation;
|
|
598
|
+
const loop = context.loop;
|
|
599
|
+
const steps = useStepperStore((state) => state.steps);
|
|
600
|
+
const stepIndex = Array.from(steps.keys()).indexOf(itemValue);
|
|
601
|
+
const stepPosition = stepIndex + 1;
|
|
602
|
+
const stepCount = steps.size;
|
|
603
|
+
const triggerId = getId(context.id, "trigger", itemValue);
|
|
604
|
+
const contentId = getId(context.id, "content", itemValue);
|
|
605
|
+
const titleId = getId(context.id, "title", itemValue);
|
|
606
|
+
const descriptionId = getId(context.id, "description", itemValue);
|
|
607
|
+
const isDisabled = context.disabled || stepState?.disabled || disabled;
|
|
608
|
+
const isActive = value === itemValue;
|
|
609
|
+
const isTabStop = focusContext.tabStopId === triggerId;
|
|
610
|
+
const dataState = getDataState(value, itemValue, stepState, steps);
|
|
611
|
+
const triggerRef = React12.useRef(null);
|
|
612
|
+
const composedRef = useComposedRefs(ref, triggerRef);
|
|
613
|
+
const isArrowKeyPressedRef = React12.useRef(false);
|
|
614
|
+
const isMouseClickRef = React12.useRef(false);
|
|
615
|
+
React12.useEffect(() => {
|
|
616
|
+
function onKeyDown2(event) {
|
|
617
|
+
if (STEPPER_ARROW_KEYS.includes(event.key)) {
|
|
618
|
+
isArrowKeyPressedRef.current = true;
|
|
619
|
+
}
|
|
620
|
+
}
|
|
621
|
+
function onKeyUp() {
|
|
622
|
+
isArrowKeyPressedRef.current = false;
|
|
623
|
+
}
|
|
624
|
+
document.addEventListener("keydown", onKeyDown2);
|
|
625
|
+
document.addEventListener("keyup", onKeyUp);
|
|
626
|
+
return () => {
|
|
627
|
+
document.removeEventListener("keydown", onKeyDown2);
|
|
628
|
+
document.removeEventListener("keyup", onKeyUp);
|
|
629
|
+
};
|
|
630
|
+
}, []);
|
|
631
|
+
useIsomorphicLayoutEffect(() => {
|
|
632
|
+
focusContext.onItemRegister({
|
|
633
|
+
id: triggerId,
|
|
634
|
+
ref: triggerRef,
|
|
635
|
+
value: itemValue,
|
|
636
|
+
active: isTabStop,
|
|
637
|
+
disabled: !!isDisabled
|
|
638
|
+
});
|
|
639
|
+
if (!isDisabled) {
|
|
640
|
+
focusContext.onFocusableItemAdd();
|
|
641
|
+
}
|
|
642
|
+
return () => {
|
|
643
|
+
focusContext.onItemUnregister(triggerId);
|
|
644
|
+
if (!isDisabled) {
|
|
645
|
+
focusContext.onFocusableItemRemove();
|
|
646
|
+
}
|
|
647
|
+
};
|
|
648
|
+
}, [focusContext, triggerId, itemValue, isTabStop, isDisabled]);
|
|
649
|
+
const onClick = React12.useCallback(
|
|
650
|
+
async (event) => {
|
|
651
|
+
triggerProps.onClick?.(event);
|
|
652
|
+
if (event.defaultPrevented) return;
|
|
653
|
+
if (!isDisabled && !context.nonInteractive) {
|
|
654
|
+
const currentStepIndex = Array.from(steps.keys()).indexOf(value ?? "");
|
|
655
|
+
const targetStepIndex = Array.from(steps.keys()).indexOf(itemValue);
|
|
656
|
+
const direction = targetStepIndex > currentStepIndex ? "next" : "prev";
|
|
657
|
+
await store.setStateWithValidation(itemValue, direction);
|
|
658
|
+
}
|
|
659
|
+
},
|
|
660
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
661
|
+
[isDisabled, context.nonInteractive, store, itemValue, value, steps, triggerProps.onClick]
|
|
662
|
+
);
|
|
663
|
+
const onFocus = React12.useCallback(
|
|
664
|
+
async (event) => {
|
|
665
|
+
triggerProps.onFocus?.(event);
|
|
666
|
+
if (event.defaultPrevented) return;
|
|
667
|
+
focusContext.onItemFocus(triggerId);
|
|
668
|
+
const isKeyboardFocus = !isMouseClickRef.current;
|
|
669
|
+
if (!isActive && !isDisabled && activationMode !== "manual" && !context.nonInteractive && isKeyboardFocus) {
|
|
670
|
+
const currentStepIndex = Array.from(steps.keys()).indexOf(value || "");
|
|
671
|
+
const targetStepIndex = Array.from(steps.keys()).indexOf(itemValue);
|
|
672
|
+
const direction = targetStepIndex > currentStepIndex ? "next" : "prev";
|
|
673
|
+
await store.setStateWithValidation(itemValue, direction);
|
|
674
|
+
}
|
|
675
|
+
isMouseClickRef.current = false;
|
|
676
|
+
},
|
|
677
|
+
[
|
|
678
|
+
focusContext,
|
|
679
|
+
triggerId,
|
|
680
|
+
activationMode,
|
|
681
|
+
isActive,
|
|
682
|
+
isDisabled,
|
|
683
|
+
context.nonInteractive,
|
|
684
|
+
store,
|
|
685
|
+
itemValue,
|
|
686
|
+
value,
|
|
687
|
+
steps,
|
|
688
|
+
triggerProps.onFocus
|
|
689
|
+
]
|
|
690
|
+
);
|
|
691
|
+
const onKeyDown = React12.useCallback(
|
|
692
|
+
async (event) => {
|
|
693
|
+
triggerProps.onKeyDown?.(event);
|
|
694
|
+
if (event.defaultPrevented) return;
|
|
695
|
+
if (event.key === "Enter" && context.nonInteractive) {
|
|
696
|
+
event.preventDefault();
|
|
697
|
+
return;
|
|
698
|
+
}
|
|
699
|
+
if ((event.key === "Enter" || event.key === " ") && activationMode === "manual" && !context.nonInteractive) {
|
|
700
|
+
event.preventDefault();
|
|
701
|
+
if (!isDisabled && triggerRef.current) {
|
|
702
|
+
triggerRef.current.click();
|
|
703
|
+
}
|
|
704
|
+
return;
|
|
705
|
+
}
|
|
706
|
+
if (event.key === "Tab" && event.shiftKey) {
|
|
707
|
+
focusContext.onItemShiftTab();
|
|
708
|
+
return;
|
|
709
|
+
}
|
|
710
|
+
if (event.target !== event.currentTarget) return;
|
|
711
|
+
const focusIntent = getFocusIntent(event, context.dir, orientation);
|
|
712
|
+
if (focusIntent !== void 0) {
|
|
713
|
+
if (event.metaKey || event.ctrlKey || event.altKey || event.shiftKey) return;
|
|
714
|
+
event.preventDefault();
|
|
715
|
+
const items = focusContext.getItems().filter((item) => !item.disabled);
|
|
716
|
+
let candidateRefs = items.map((item) => item.ref);
|
|
717
|
+
if (focusIntent === "last") {
|
|
718
|
+
candidateRefs.reverse();
|
|
719
|
+
} else if (focusIntent === "prev" || focusIntent === "next") {
|
|
720
|
+
if (focusIntent === "prev") candidateRefs.reverse();
|
|
721
|
+
const currentIndex = candidateRefs.findIndex((ref2) => ref2.current === event.currentTarget);
|
|
722
|
+
candidateRefs = loop ? wrapArray(candidateRefs, currentIndex + 1) : candidateRefs.slice(currentIndex + 1);
|
|
723
|
+
}
|
|
724
|
+
if (store.hasValidation() && candidateRefs.length > 0) {
|
|
725
|
+
const nextRef = candidateRefs[0];
|
|
726
|
+
const nextElement = nextRef?.current;
|
|
727
|
+
const nextItem = items.find((item) => item.ref.current === nextElement);
|
|
728
|
+
if (nextItem && nextItem.value !== itemValue) {
|
|
729
|
+
const currentStepIndex = Array.from(steps.keys()).indexOf(value || "");
|
|
730
|
+
const targetStepIndex = Array.from(steps.keys()).indexOf(nextItem.value);
|
|
731
|
+
const direction = targetStepIndex > currentStepIndex ? "next" : "prev";
|
|
732
|
+
if (direction === "next") {
|
|
733
|
+
const isValid = await store.setStateWithValidation(nextItem.value, direction);
|
|
734
|
+
if (!isValid) return;
|
|
735
|
+
} else {
|
|
736
|
+
store.setState("value", nextItem.value);
|
|
737
|
+
}
|
|
738
|
+
queueMicrotask(() => nextElement?.focus());
|
|
739
|
+
return;
|
|
740
|
+
}
|
|
741
|
+
}
|
|
742
|
+
queueMicrotask(() => focusFirst(candidateRefs));
|
|
743
|
+
}
|
|
744
|
+
},
|
|
745
|
+
[
|
|
746
|
+
focusContext,
|
|
747
|
+
context.nonInteractive,
|
|
748
|
+
context.dir,
|
|
749
|
+
activationMode,
|
|
750
|
+
orientation,
|
|
751
|
+
loop,
|
|
752
|
+
isDisabled,
|
|
753
|
+
triggerProps.onKeyDown,
|
|
754
|
+
store,
|
|
755
|
+
itemValue,
|
|
756
|
+
value,
|
|
757
|
+
steps
|
|
758
|
+
]
|
|
759
|
+
);
|
|
760
|
+
const onMouseDown = React12.useCallback(
|
|
761
|
+
(event) => {
|
|
762
|
+
triggerProps.onMouseDown?.(event);
|
|
763
|
+
if (event.defaultPrevented) {
|
|
764
|
+
return;
|
|
765
|
+
}
|
|
766
|
+
isMouseClickRef.current = true;
|
|
767
|
+
if (isDisabled) {
|
|
768
|
+
event.preventDefault();
|
|
769
|
+
} else {
|
|
770
|
+
focusContext.onItemFocus(triggerId);
|
|
771
|
+
}
|
|
772
|
+
},
|
|
773
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
774
|
+
[focusContext, triggerId, isDisabled, triggerProps.onMouseDown]
|
|
775
|
+
);
|
|
776
|
+
const TriggerPrimitive = asChild ? Slot : "button";
|
|
777
|
+
return /* @__PURE__ */ jsx(
|
|
778
|
+
TriggerPrimitive,
|
|
779
|
+
{
|
|
780
|
+
id: triggerId,
|
|
781
|
+
role: "tab",
|
|
782
|
+
type: "button",
|
|
783
|
+
disabled: isDisabled,
|
|
784
|
+
tabIndex: isTabStop ? 0 : -1,
|
|
785
|
+
ref: composedRef,
|
|
786
|
+
"data-slot": "stepper-trigger",
|
|
787
|
+
"data-disabled": isDisabled ? "" : void 0,
|
|
788
|
+
"data-state": dataState,
|
|
789
|
+
"aria-controls": contentId,
|
|
790
|
+
"aria-current": isActive ? "step" : void 0,
|
|
791
|
+
"aria-describedby": `${titleId} ${descriptionId}`,
|
|
792
|
+
"aria-posinset": stepPosition,
|
|
793
|
+
"aria-selected": isActive,
|
|
794
|
+
"aria-setsize": stepCount,
|
|
795
|
+
className: cn(
|
|
796
|
+
"inline-flex w-full cursor-pointer items-center gap-3 rounded text-left transition-colors duration-300 outline-none",
|
|
797
|
+
"text-gray-500 data-[state=active]:text-gray-100 data-[state=completed]:text-gray-100 data-[state=loading]:text-gray-100",
|
|
798
|
+
"disabled:pointer-events-none disabled:opacity-60",
|
|
799
|
+
"focus-visible:ring-primary-500/50 focus-visible:z-10 focus-visible:ring-[3px]",
|
|
800
|
+
className
|
|
801
|
+
),
|
|
802
|
+
onClick,
|
|
803
|
+
onFocus,
|
|
804
|
+
onKeyDown,
|
|
805
|
+
onMouseDown,
|
|
806
|
+
...triggerProps
|
|
807
|
+
}
|
|
808
|
+
);
|
|
809
|
+
}
|
|
810
|
+
function StepperIndicator({ className, children, asChild, ref, ...props }) {
|
|
811
|
+
const { indicators, dir } = useStepperContext(STEPPER_INDICATOR_NAME);
|
|
812
|
+
const itemContext = useStepperItemContext(STEPPER_INDICATOR_NAME);
|
|
813
|
+
const value = useStepperStore((state) => state.value);
|
|
814
|
+
const itemValue = itemContext.value;
|
|
815
|
+
const stepState = useStepperStore((state) => state.steps.get(itemValue));
|
|
816
|
+
const steps = useStepperStore((state) => state.steps);
|
|
817
|
+
const stepPosition = Array.from(steps.keys()).indexOf(itemValue) + 1;
|
|
818
|
+
const dataState = getDataState(value, itemValue, stepState, steps);
|
|
819
|
+
const StepperIndicatorPrimitive = asChild ? Slot : "div";
|
|
820
|
+
return /* @__PURE__ */ jsx(
|
|
821
|
+
StepperIndicatorPrimitive,
|
|
822
|
+
{
|
|
823
|
+
"data-slot": "stepper-indicator",
|
|
824
|
+
"data-state": dataState,
|
|
825
|
+
dir,
|
|
826
|
+
ref,
|
|
827
|
+
className: cn(
|
|
828
|
+
"bg-app-foreground relative flex size-6 shrink-0 items-center justify-center self-end overflow-hidden rounded-t border-x border-t border-gray-800 text-xs transition-colors duration-500",
|
|
829
|
+
"data-[state=completed]:bg-success-500/50 data-[state=completed]:border-success-500",
|
|
830
|
+
"data-[state=active]:bg-primary-500/50 data-[state=active]:border-primary-500",
|
|
831
|
+
className
|
|
832
|
+
),
|
|
833
|
+
...props,
|
|
834
|
+
children: /* @__PURE__ */ jsx("div", { className: "absolute", children: typeof children === "function" ? children(dataState) : indicators && (itemContext.stepState?.loading && indicators.loading || dataState === "completed" && indicators.completed || dataState === "active" && indicators.active || dataState === "inactive" && indicators.inactive) ? itemContext.stepState?.loading && indicators.loading || dataState === "completed" && indicators.completed || dataState === "active" && indicators.active || dataState === "inactive" && indicators.inactive : children ? children : stepPosition })
|
|
835
|
+
}
|
|
836
|
+
);
|
|
837
|
+
}
|
|
838
|
+
function StepperTitle({ className, asChild = false, ...props }) {
|
|
839
|
+
const context = useStepperContext(STEPPER_TITLE_NAME);
|
|
840
|
+
const itemContext = useStepperItemContext(STEPPER_TITLE_NAME);
|
|
841
|
+
const titleId = getId(context.id, "title", itemContext.value);
|
|
842
|
+
const TitlePrimitive = asChild ? Slot : "h3";
|
|
843
|
+
return /* @__PURE__ */ jsx(
|
|
844
|
+
TitlePrimitive,
|
|
845
|
+
{
|
|
846
|
+
id: titleId,
|
|
847
|
+
"data-slot": "stepper-title",
|
|
848
|
+
dir: context.dir,
|
|
849
|
+
className: cn("text-sm leading-none font-medium", className),
|
|
850
|
+
...props
|
|
851
|
+
}
|
|
852
|
+
);
|
|
853
|
+
}
|
|
854
|
+
function StepperDescription({ className, asChild, ...props }) {
|
|
855
|
+
const context = useStepperContext(STEPPER_DESCRIPTION_NAME);
|
|
856
|
+
const itemContext = useStepperItemContext(STEPPER_DESCRIPTION_NAME);
|
|
857
|
+
const descriptionId = getId(context.id, "description", itemContext.value);
|
|
858
|
+
const StepperDescriptionPrimitive = asChild ? Slot : "span";
|
|
859
|
+
return /* @__PURE__ */ jsx(
|
|
860
|
+
StepperDescriptionPrimitive,
|
|
861
|
+
{
|
|
862
|
+
id: descriptionId,
|
|
863
|
+
"data-slot": "stepper-description",
|
|
864
|
+
dir: context.dir,
|
|
865
|
+
className: cn("text-sm text-gray-700", className),
|
|
866
|
+
...props
|
|
867
|
+
}
|
|
868
|
+
);
|
|
869
|
+
}
|
|
870
|
+
function StepperPanel({ children, asChild = false, className, ...props }) {
|
|
871
|
+
const currentValue = useStepperStore((state) => state.value);
|
|
872
|
+
const StepperPanelPrimitive = asChild ? Slot : "div";
|
|
873
|
+
return /* @__PURE__ */ jsx(
|
|
874
|
+
StepperPanelPrimitive,
|
|
875
|
+
{
|
|
876
|
+
"data-slot": "stepper-panel",
|
|
877
|
+
"data-state": currentValue,
|
|
878
|
+
className: cn("w-full", className),
|
|
879
|
+
...props,
|
|
880
|
+
children
|
|
881
|
+
}
|
|
882
|
+
);
|
|
883
|
+
}
|
|
884
|
+
function StepperContent({
|
|
885
|
+
value: valueProp,
|
|
886
|
+
asChild = false,
|
|
887
|
+
forceMount = false,
|
|
888
|
+
className,
|
|
889
|
+
...props
|
|
890
|
+
}) {
|
|
891
|
+
const context = useStepperContext(STEPPER_CONTENT_NAME);
|
|
892
|
+
const value = useStepperStore((state) => state.value);
|
|
893
|
+
const contentId = getId(context.id, "content", valueProp);
|
|
894
|
+
const triggerId = getId(context.id, "trigger", valueProp);
|
|
895
|
+
const isActive = value === valueProp;
|
|
896
|
+
if (!isActive && !forceMount) {
|
|
897
|
+
return null;
|
|
898
|
+
}
|
|
899
|
+
const ContentPrimitive = asChild ? Slot : "div";
|
|
900
|
+
return /* @__PURE__ */ jsx(
|
|
901
|
+
ContentPrimitive,
|
|
902
|
+
{
|
|
903
|
+
id: contentId,
|
|
904
|
+
role: "tabpanel",
|
|
905
|
+
"data-state": value,
|
|
906
|
+
"aria-labelledby": triggerId,
|
|
907
|
+
"data-slot": "stepper-content",
|
|
908
|
+
dir: context.dir,
|
|
909
|
+
className: cn("w-full", className, !isActive && forceMount && "hidden"),
|
|
910
|
+
hidden: !isActive && forceMount,
|
|
911
|
+
...props
|
|
912
|
+
}
|
|
913
|
+
);
|
|
914
|
+
}
|
|
915
|
+
function StepperNextTrigger({ asChild = false, onClick, disabled, ...props }) {
|
|
916
|
+
const store = useStepperStoreContext(STEPPER_NEXT_TRIGGER_NAME);
|
|
917
|
+
const value = useStepperStore((state) => state.value);
|
|
918
|
+
const steps = useStepperStore((state) => state.steps);
|
|
919
|
+
const stepKeys = Array.from(steps.keys());
|
|
920
|
+
const currentIndex = value ? stepKeys.indexOf(value) : -1;
|
|
921
|
+
const isDisabled = disabled || currentIndex >= stepKeys.length - 1;
|
|
922
|
+
const handleClick = React12.useCallback(
|
|
923
|
+
async (event) => {
|
|
924
|
+
onClick?.(event);
|
|
925
|
+
if (event.defaultPrevented || isDisabled) {
|
|
926
|
+
return;
|
|
927
|
+
}
|
|
928
|
+
const nextIndex = Math.min(currentIndex + 1, stepKeys.length - 1);
|
|
929
|
+
const nextStepValue = stepKeys[nextIndex];
|
|
930
|
+
if (nextStepValue) {
|
|
931
|
+
await store.setStateWithValidation(nextStepValue, "next");
|
|
932
|
+
}
|
|
933
|
+
},
|
|
934
|
+
[onClick, isDisabled, currentIndex, stepKeys, store]
|
|
935
|
+
);
|
|
936
|
+
const StepperNextTriggerPrimitive = asChild ? Slot : "button";
|
|
937
|
+
return /* @__PURE__ */ jsx(
|
|
938
|
+
StepperNextTriggerPrimitive,
|
|
939
|
+
{
|
|
940
|
+
type: "button",
|
|
941
|
+
"data-slot": "stepper-next-trigger",
|
|
942
|
+
disabled: isDisabled,
|
|
943
|
+
onClick: handleClick,
|
|
944
|
+
...props
|
|
945
|
+
}
|
|
946
|
+
);
|
|
947
|
+
}
|
|
948
|
+
function StepperPrevTrigger({ asChild = false, disabled, onClick, ...props }) {
|
|
949
|
+
const store = useStepperStoreContext(STEPPER_PREV_TRIGGER_NAME);
|
|
950
|
+
const value = useStepperStore((state) => state.value);
|
|
951
|
+
const steps = useStepperStore((state) => state.steps);
|
|
952
|
+
const stepKeys = Array.from(steps.keys());
|
|
953
|
+
const currentIndex = value ? stepKeys.indexOf(value) : -1;
|
|
954
|
+
const isDisabled = disabled || currentIndex <= 0;
|
|
955
|
+
const handleClick = React12.useCallback(
|
|
956
|
+
async (event) => {
|
|
957
|
+
onClick?.(event);
|
|
958
|
+
if (event.defaultPrevented || isDisabled) {
|
|
959
|
+
return;
|
|
960
|
+
}
|
|
961
|
+
const prevIndex = Math.max(currentIndex - 1, 0);
|
|
962
|
+
const prevStepValue = stepKeys[prevIndex];
|
|
963
|
+
if (prevStepValue) {
|
|
964
|
+
store.setState("value", prevStepValue);
|
|
965
|
+
}
|
|
966
|
+
},
|
|
967
|
+
[currentIndex, isDisabled, onClick, stepKeys, store]
|
|
968
|
+
);
|
|
969
|
+
const StepperPrevTriggerPrimitive = asChild ? Slot : "button";
|
|
970
|
+
return /* @__PURE__ */ jsx(
|
|
971
|
+
StepperPrevTriggerPrimitive,
|
|
972
|
+
{
|
|
973
|
+
type: "button",
|
|
974
|
+
"data-slot": "stepper-prev-trigger",
|
|
975
|
+
disabled: isDisabled,
|
|
976
|
+
onClick: handleClick,
|
|
977
|
+
...props
|
|
978
|
+
}
|
|
979
|
+
);
|
|
980
|
+
}
|
|
981
|
+
var FormMessage = React12.forwardRef(function({ children, ...props }, ref) {
|
|
982
|
+
const { error, formMessageId } = useFormField();
|
|
983
|
+
const body = error ? String(error?.message) : children;
|
|
984
|
+
if (!body) {
|
|
985
|
+
return null;
|
|
986
|
+
}
|
|
987
|
+
return /* @__PURE__ */ jsx(HelperText, { ref, type: "error", id: formMessageId, ...props, children: body });
|
|
988
|
+
});
|
|
989
|
+
FormMessage.displayName = "FormMessage";
|
|
990
|
+
var FormDescription = React12.forwardRef(function(props, ref) {
|
|
991
|
+
const { formDescriptionId } = useFormField();
|
|
992
|
+
return /* @__PURE__ */ jsx(HelperText, { ref, id: formDescriptionId, ...props });
|
|
993
|
+
});
|
|
994
|
+
FormDescription.displayName = "FormDescription";
|
|
995
|
+
|
|
996
|
+
export { Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage, Stepper, StepperActivationMode, StepperContent, StepperDataState, StepperDescription, StepperFocusIntent, StepperIndicator, StepperItem, StepperNav, StepperNavigationDirection, StepperNextTrigger, StepperOrientation, StepperPanel, StepperPrevTrigger, StepperTitle, StepperTrigger, useStepperContext, useStepperFocusContext, useStepperItemContext };
|