@nucleux/md3-structured-input 0.0.0-stage → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js ADDED
@@ -0,0 +1,534 @@
1
+ "use client";
2
+ import * as React from 'react';
3
+ import { cn } from '@nucleux/utils';
4
+ import { Md3Button } from '@nucleux/md3-button';
5
+ import { Md3Card } from '@nucleux/md3-card';
6
+ import { Md3Chip } from '@nucleux/md3-chip';
7
+ import { structuredPartsToText } from '@nucleux/structured-input';
8
+ export { structuredPartsToText } from '@nucleux/structured-input';
9
+ import { Check, Sparkles, UserPen, X } from 'lucide-react';
10
+ import { jsxs, jsx } from 'react/jsx-runtime';
11
+
12
+ // src/index.tsx
13
+ var stateLayer = "before:absolute before:inset-0 before:bg-current before:opacity-0 before:transition-opacity before:content-[''] hover:before:opacity-[0.08] focus-visible:before:opacity-[0.12] active:before:opacity-[0.12]";
14
+ var fieldClass = cn(
15
+ "w-full rounded-md-xs border border-md-outline bg-transparent px-4 text-base text-md-on-surface outline-none transition-colors",
16
+ "placeholder:text-md-on-surface-variant hover:border-md-on-surface",
17
+ "focus:border-md-primary focus:ring-1 focus:ring-inset focus:ring-md-primary",
18
+ "disabled:cursor-not-allowed disabled:opacity-[0.38]"
19
+ );
20
+ var Md3StructuredInput = React.forwardRef(
21
+ ({
22
+ question,
23
+ options,
24
+ multiple = false,
25
+ value,
26
+ defaultValue = [],
27
+ onValueChange,
28
+ allowOther = false,
29
+ otherPlaceholder = "Something else\u2026",
30
+ onSubmit,
31
+ onSkip,
32
+ submitLabel = "Continue",
33
+ skipLabel = "Skip",
34
+ className,
35
+ ...props
36
+ }, ref) => {
37
+ const [internal, setInternal] = React.useState(defaultValue);
38
+ const [other, setOther] = React.useState("");
39
+ const questionId = React.useId();
40
+ const groupRef = React.useRef(null);
41
+ const selected = value !== void 0 ? value : internal;
42
+ const setSelected = (next) => {
43
+ if (value === void 0) setInternal(next);
44
+ onValueChange?.(next);
45
+ };
46
+ const toggle = (val) => {
47
+ if (multiple) {
48
+ setSelected(selected.includes(val) ? selected.filter((v) => v !== val) : [...selected, val]);
49
+ } else {
50
+ setSelected([val]);
51
+ }
52
+ };
53
+ return /* @__PURE__ */ jsxs(
54
+ Md3Card,
55
+ {
56
+ ref,
57
+ variant: "outlined",
58
+ className: cn("flex flex-col gap-4 rounded-md-lg p-5 animate-nx-fade-in motion-reduce:animate-none", className),
59
+ ...props,
60
+ children: [
61
+ /* @__PURE__ */ jsx("p", { id: questionId, className: "text-base font-medium tracking-[0.15px] text-md-on-surface", children: question }),
62
+ /* @__PURE__ */ jsx(
63
+ "div",
64
+ {
65
+ ref: groupRef,
66
+ role: multiple ? "group" : "radiogroup",
67
+ "aria-labelledby": questionId,
68
+ className: "flex flex-col gap-1",
69
+ onKeyDown: (e) => {
70
+ if (multiple || !["ArrowDown", "ArrowUp", "ArrowRight", "ArrowLeft"].includes(e.key)) return;
71
+ const radios = Array.from(groupRef.current?.querySelectorAll('[role="radio"]') ?? []);
72
+ const i = radios.indexOf(document.activeElement);
73
+ if (i < 0) return;
74
+ e.preventDefault();
75
+ const step = e.key === "ArrowDown" || e.key === "ArrowRight" ? 1 : -1;
76
+ const next = (i + step + radios.length) % radios.length;
77
+ radios[next].focus();
78
+ setSelected([options[next].value]);
79
+ },
80
+ children: options.map((option, index) => {
81
+ const active = selected.includes(option.value);
82
+ const tabbable = multiple || index === Math.max(0, options.findIndex((o) => selected.includes(o.value)));
83
+ return /* @__PURE__ */ jsxs(
84
+ "button",
85
+ {
86
+ type: "button",
87
+ role: multiple ? "checkbox" : "radio",
88
+ "aria-checked": active,
89
+ tabIndex: tabbable ? 0 : -1,
90
+ onClick: () => toggle(option.value),
91
+ className: cn(
92
+ "relative flex min-h-12 items-center gap-4 overflow-hidden rounded-md-md px-3 py-2 text-left text-sm transition-colors duration-200 motion-reduce:transition-none",
93
+ stateLayer,
94
+ "outline-none focus-visible:ring-2 focus-visible:ring-md-primary",
95
+ active ? "bg-md-secondary-container text-md-on-secondary-container" : "text-md-on-surface"
96
+ ),
97
+ children: [
98
+ multiple ? /* @__PURE__ */ jsx(
99
+ "span",
100
+ {
101
+ className: cn(
102
+ "relative inline-flex size-[18px] shrink-0 items-center justify-center rounded-[2px] border-2 transition-colors [&_svg]:size-3.5",
103
+ active ? "border-md-primary bg-md-primary text-md-on-primary" : "border-md-on-surface-variant"
104
+ ),
105
+ children: active && /* @__PURE__ */ jsx(Check, { strokeWidth: 3, "aria-hidden": "true" })
106
+ }
107
+ ) : /* @__PURE__ */ jsx(
108
+ "span",
109
+ {
110
+ className: cn(
111
+ "relative inline-flex size-5 shrink-0 items-center justify-center rounded-full border-2 transition-colors",
112
+ active ? "border-md-primary" : "border-md-on-surface-variant"
113
+ ),
114
+ children: /* @__PURE__ */ jsx(
115
+ "span",
116
+ {
117
+ className: cn(
118
+ "size-2.5 rounded-full bg-md-primary transition-transform duration-200 motion-reduce:transition-none",
119
+ active ? "scale-100" : "scale-0"
120
+ )
121
+ }
122
+ )
123
+ }
124
+ ),
125
+ /* @__PURE__ */ jsx("span", { className: "relative flex-1", children: option.label })
126
+ ]
127
+ },
128
+ option.value
129
+ );
130
+ })
131
+ }
132
+ ),
133
+ allowOther && /* @__PURE__ */ jsx(
134
+ "input",
135
+ {
136
+ type: "text",
137
+ value: other,
138
+ onChange: (e) => setOther(e.target.value),
139
+ placeholder: otherPlaceholder,
140
+ "aria-label": otherPlaceholder,
141
+ className: cn(fieldClass, "h-12")
142
+ }
143
+ ),
144
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-end gap-2", children: [
145
+ onSkip && /* @__PURE__ */ jsx(Md3Button, { variant: "text", onClick: onSkip, children: skipLabel }),
146
+ onSubmit && /* @__PURE__ */ jsx(
147
+ Md3Button,
148
+ {
149
+ variant: "filled",
150
+ onClick: () => onSubmit(selected, allowOther ? other : void 0),
151
+ disabled: selected.length === 0 && !(allowOther && other.trim()),
152
+ children: submitLabel
153
+ }
154
+ )
155
+ ] })
156
+ ]
157
+ }
158
+ );
159
+ }
160
+ );
161
+ Md3StructuredInput.displayName = "Md3StructuredInput";
162
+ var Md3StructuredInputSlots = React.forwardRef(
163
+ ({
164
+ slots,
165
+ values: valuesProp,
166
+ defaultValues,
167
+ onValuesChange,
168
+ freeform = false,
169
+ onSubmit,
170
+ submitLabel = "Generate",
171
+ label = "Structured prompt builder",
172
+ className,
173
+ ...props
174
+ }, ref) => {
175
+ const [internal, setInternal] = React.useState(defaultValues ?? {});
176
+ const values = valuesProp ?? internal;
177
+ const [edited, setEdited] = React.useState({});
178
+ const [extra, setExtra] = React.useState("");
179
+ const baseId = React.useId();
180
+ const setValue = (name, value) => {
181
+ const next = { ...values, [name]: value };
182
+ if (valuesProp === void 0) setInternal(next);
183
+ setEdited((e) => ({ ...e, [name]: true }));
184
+ onValuesChange?.(next);
185
+ };
186
+ const hasAny = Object.values(values).some((v) => v && v.trim()) || extra.trim().length > 0;
187
+ const freeformLabel = typeof freeform === "string" ? freeform : "Anything else?";
188
+ return /* @__PURE__ */ jsxs(
189
+ "form",
190
+ {
191
+ ref,
192
+ "aria-label": label,
193
+ className: cn("grid grid-cols-1 gap-4 text-md-on-surface sm:grid-cols-2", className),
194
+ onSubmit: (e) => {
195
+ e.preventDefault();
196
+ if (hasAny) onSubmit?.(values, extra);
197
+ },
198
+ ...props,
199
+ children: [
200
+ slots.map((slot) => {
201
+ const id = `${baseId}-${slot.name}`;
202
+ const helperId = `${id}-helper`;
203
+ const isEdited = !!edited[slot.name];
204
+ const mark = slot.suggested ? isEdited ? "edited" : "suggested" : null;
205
+ const describedBy = slot.helper || mark === "suggested" ? helperId : void 0;
206
+ return /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col gap-1.5", slot.wide && "sm:col-span-2"), children: [
207
+ /* @__PURE__ */ jsxs("div", { className: "flex min-h-6 items-center gap-2", children: [
208
+ /* @__PURE__ */ jsx("label", { htmlFor: id, className: "text-xs font-medium tracking-[0.5px] text-md-on-surface-variant", children: slot.label }),
209
+ mark && /* @__PURE__ */ jsxs(
210
+ "span",
211
+ {
212
+ className: cn(
213
+ "inline-flex h-6 items-center gap-1 rounded-md-sm px-2 text-[11px] font-medium tracking-[0.5px] [&_svg]:size-3.5",
214
+ mark === "suggested" ? "bg-md-primary-container text-md-on-primary-container" : "bg-md-surface-container-high text-md-on-surface-variant"
215
+ ),
216
+ children: [
217
+ mark === "suggested" ? /* @__PURE__ */ jsx(Sparkles, { "aria-hidden": "true" }) : /* @__PURE__ */ jsx(UserPen, { "aria-hidden": "true" }),
218
+ mark === "suggested" ? "Suggested" : "Edited by you"
219
+ ]
220
+ }
221
+ )
222
+ ] }),
223
+ slot.options ? /* @__PURE__ */ jsxs(
224
+ "select",
225
+ {
226
+ id,
227
+ value: values[slot.name] ?? "",
228
+ "aria-describedby": describedBy,
229
+ onChange: (e) => setValue(slot.name, e.target.value),
230
+ className: cn(fieldClass, "h-14 cursor-pointer", !values[slot.name] && "text-md-on-surface-variant"),
231
+ children: [
232
+ /* @__PURE__ */ jsx("option", { value: "", disabled: true, children: slot.placeholder ?? "Choose\u2026" }),
233
+ slot.options.map((o) => /* @__PURE__ */ jsx("option", { value: o.value, children: typeof o.label === "string" || typeof o.label === "number" ? o.label : o.value }, o.value))
234
+ ]
235
+ }
236
+ ) : /* @__PURE__ */ jsx(
237
+ "input",
238
+ {
239
+ id,
240
+ type: "text",
241
+ value: values[slot.name] ?? "",
242
+ placeholder: slot.placeholder,
243
+ "aria-describedby": describedBy,
244
+ onChange: (e) => setValue(slot.name, e.target.value),
245
+ className: cn(fieldClass, "h-14")
246
+ }
247
+ ),
248
+ describedBy && /* @__PURE__ */ jsxs("p", { id: helperId, className: "px-4 text-xs text-md-on-surface-variant", children: [
249
+ mark === "suggested" ? `Suggested ${slot.suggested}. ` : "",
250
+ slot.helper
251
+ ] })
252
+ ] }, slot.name);
253
+ }),
254
+ freeform && /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1.5 sm:col-span-2", children: [
255
+ /* @__PURE__ */ jsx(
256
+ "label",
257
+ {
258
+ htmlFor: `${baseId}-freeform`,
259
+ className: "text-xs font-medium tracking-[0.5px] text-md-on-surface-variant",
260
+ children: freeformLabel
261
+ }
262
+ ),
263
+ /* @__PURE__ */ jsx(
264
+ "textarea",
265
+ {
266
+ id: `${baseId}-freeform`,
267
+ rows: 2,
268
+ value: extra,
269
+ placeholder: "Say it in your own words \u2014 this overrides the fields above",
270
+ onChange: (e) => setExtra(e.target.value),
271
+ className: cn(fieldClass, "resize-none py-3")
272
+ }
273
+ )
274
+ ] }),
275
+ onSubmit && /* @__PURE__ */ jsx("div", { className: "flex justify-end sm:col-span-2", children: /* @__PURE__ */ jsx(Md3Button, { type: "submit", variant: "filled", disabled: !hasAny, children: submitLabel }) })
276
+ ]
277
+ }
278
+ );
279
+ }
280
+ );
281
+ Md3StructuredInputSlots.displayName = "Md3StructuredInputSlots";
282
+ var DEFAULT_TRIGGERS = [
283
+ { trigger: "@", label: "Person" },
284
+ { trigger: "p:", label: "Project" },
285
+ { trigger: "/", label: "File" }
286
+ ];
287
+ var TAG_TONES = [
288
+ "bg-md-primary-container text-md-on-primary-container",
289
+ "bg-md-secondary-container text-md-on-secondary-container",
290
+ "bg-md-tertiary-container text-md-on-tertiary-container",
291
+ "bg-md-surface-container-high text-md-on-surface"
292
+ ];
293
+ var Md3StructuredInputTags = React.forwardRef(
294
+ ({
295
+ triggers = DEFAULT_TRIGGERS,
296
+ value: valueProp,
297
+ defaultValue,
298
+ onValueChange,
299
+ onSubmit,
300
+ placeholder = "Type @ for people, p: for projects, / for files",
301
+ submitLabel = "Send",
302
+ className,
303
+ ...props
304
+ }, ref) => {
305
+ const [internal, setInternal] = React.useState(defaultValue ?? []);
306
+ const parts = valueProp ?? internal;
307
+ const [draft, setDraft] = React.useState("");
308
+ const inputRef = React.useRef(null);
309
+ const hintId = React.useId();
310
+ const commit = (next) => {
311
+ if (valueProp === void 0) setInternal(next);
312
+ onValueChange?.(next);
313
+ };
314
+ const ordered = [...triggers].sort((a, b) => b.trigger.length - a.trigger.length);
315
+ const matchTag = (word) => {
316
+ const t = ordered.find((tr) => word.startsWith(tr.trigger) && word.length > tr.trigger.length);
317
+ return t ? { trigger: t.trigger, value: word.slice(t.trigger.length) } : null;
318
+ };
319
+ const lastWord = draft.split(" ").pop() ?? "";
320
+ const activeTrigger = ordered.find((tr) => lastWord.startsWith(tr.trigger));
321
+ const query = activeTrigger ? lastWord.slice(activeTrigger.trigger.length).toLowerCase() : "";
322
+ const suggestions = activeTrigger?.suggestions?.filter((s) => s.toLowerCase().startsWith(query)).slice(0, 5) ?? [];
323
+ const flush = (source = draft, forceTag) => {
324
+ const words = source.split(" ");
325
+ const last = words.pop() ?? "";
326
+ const tag = forceTag ?? matchTag(last);
327
+ const textBefore = (tag ? words.join(" ") : source).trim();
328
+ const next = [...parts];
329
+ if (textBefore) next.push({ type: "text", text: textBefore });
330
+ if (tag) next.push({ type: "tag", ...tag });
331
+ if (next.length !== parts.length) commit(next);
332
+ setDraft("");
333
+ return next;
334
+ };
335
+ const toneFor = (trigger) => {
336
+ const i = triggers.findIndex((t) => t.trigger === trigger);
337
+ return TAG_TONES[(i < 0 ? 0 : i) % TAG_TONES.length];
338
+ };
339
+ const labelFor = (trigger) => triggers.find((t) => t.trigger === trigger)?.label ?? "Tag";
340
+ const submit = () => {
341
+ const next = flush();
342
+ const text = structuredPartsToText(next);
343
+ if (text) onSubmit?.(next, text);
344
+ };
345
+ return /* @__PURE__ */ jsxs("div", { ref, className: cn("flex flex-col gap-2 text-md-on-surface", className), ...props, children: [
346
+ /* @__PURE__ */ jsxs(
347
+ "div",
348
+ {
349
+ className: cn(
350
+ "flex min-h-14 flex-wrap items-center gap-1.5 rounded-md-xs border border-md-outline bg-transparent px-3 py-2 text-base text-md-on-surface transition-colors",
351
+ "hover:border-md-on-surface focus-within:border-md-primary focus-within:ring-1 focus-within:ring-inset focus-within:ring-md-primary"
352
+ ),
353
+ onClick: () => inputRef.current?.focus(),
354
+ children: [
355
+ parts.map(
356
+ (part, i) => part.type === "text" ? /* @__PURE__ */ jsx("span", { children: part.text }, i) : /* @__PURE__ */ jsxs(
357
+ "span",
358
+ {
359
+ className: cn(
360
+ "inline-flex h-7 items-center gap-0.5 rounded-md-sm pl-2 pr-0.5 text-sm font-medium animate-nx-fade-in motion-reduce:animate-none",
361
+ toneFor(part.trigger)
362
+ ),
363
+ children: [
364
+ part.trigger,
365
+ part.value,
366
+ /* @__PURE__ */ jsx(
367
+ "button",
368
+ {
369
+ type: "button",
370
+ "aria-label": `Remove ${labelFor(part.trigger).toLowerCase()} ${part.trigger}${part.value}`,
371
+ onClick: (e) => {
372
+ e.stopPropagation();
373
+ commit(parts.filter((_, j) => j !== i));
374
+ inputRef.current?.focus();
375
+ },
376
+ className: cn(
377
+ "relative inline-flex size-6 items-center justify-center overflow-hidden rounded-full [&_svg]:size-3.5",
378
+ stateLayer,
379
+ "outline-none focus-visible:ring-2 focus-visible:ring-md-primary"
380
+ ),
381
+ children: /* @__PURE__ */ jsx(X, { className: "relative", "aria-hidden": "true" })
382
+ }
383
+ )
384
+ ]
385
+ },
386
+ i
387
+ )
388
+ ),
389
+ /* @__PURE__ */ jsx(
390
+ "input",
391
+ {
392
+ ref: inputRef,
393
+ type: "text",
394
+ value: draft,
395
+ "aria-label": placeholder,
396
+ "aria-describedby": hintId,
397
+ placeholder: parts.length ? void 0 : placeholder,
398
+ onChange: (e) => {
399
+ const v = e.target.value;
400
+ if (v.endsWith(" ") && matchTag(v.trimEnd().split(" ").pop() ?? "")) flush(v.trimEnd());
401
+ else setDraft(v);
402
+ },
403
+ onKeyDown: (e) => {
404
+ if (e.key === " " && matchTag(lastWord)) {
405
+ e.preventDefault();
406
+ flush();
407
+ } else if (e.key === "Enter") {
408
+ e.preventDefault();
409
+ submit();
410
+ } else if (e.key === "Backspace" && draft === "" && parts.length) {
411
+ e.preventDefault();
412
+ const last = parts[parts.length - 1];
413
+ commit(parts.slice(0, -1));
414
+ if (last.type === "text") setDraft(last.text);
415
+ }
416
+ },
417
+ className: "h-8 min-w-[8rem] flex-1 bg-transparent text-base text-md-on-surface outline-none placeholder:text-md-on-surface-variant"
418
+ }
419
+ )
420
+ ]
421
+ }
422
+ ),
423
+ /* @__PURE__ */ jsxs("p", { id: hintId, className: "sr-only", children: [
424
+ triggers.map((t) => `${t.trigger} for ${t.label.toLowerCase()}`).join(", "),
425
+ ". Space turns a tag into a chip; Backspace removes the last one; Enter sends."
426
+ ] }),
427
+ activeTrigger && suggestions.length > 0 && /* @__PURE__ */ jsx("div", { role: "group", "aria-label": `${activeTrigger.label} suggestions`, className: "flex flex-wrap gap-2", children: suggestions.map((s) => /* @__PURE__ */ jsxs(
428
+ Md3Chip,
429
+ {
430
+ variant: "suggestion",
431
+ onClick: () => {
432
+ flush(draft, { trigger: activeTrigger.trigger, value: s });
433
+ inputRef.current?.focus();
434
+ },
435
+ children: [
436
+ activeTrigger.trigger,
437
+ s
438
+ ]
439
+ },
440
+ s
441
+ )) }),
442
+ onSubmit && /* @__PURE__ */ jsx("div", { className: "flex justify-end", children: /* @__PURE__ */ jsx(Md3Button, { variant: "filled", onClick: submit, disabled: parts.length === 0 && draft.trim() === "", children: submitLabel }) })
443
+ ] });
444
+ }
445
+ );
446
+ Md3StructuredInputTags.displayName = "Md3StructuredInputTags";
447
+ var Md3StructuredInputWizard = React.forwardRef(
448
+ ({
449
+ steps,
450
+ step: stepProp,
451
+ defaultStep = 0,
452
+ onStepChange,
453
+ description,
454
+ onSubmit,
455
+ submitLabel = "Generate",
456
+ allowEarlySubmit = true,
457
+ className,
458
+ children,
459
+ ...props
460
+ }, ref) => {
461
+ const [internal, setInternal] = React.useState(defaultStep);
462
+ const step = Math.min(Math.max(stepProp ?? internal, 0), Math.max(steps.length - 1, 0));
463
+ const headingRef = React.useRef(null);
464
+ const headingId = React.useId();
465
+ const moved = React.useRef(false);
466
+ React.useEffect(() => {
467
+ if (moved.current) headingRef.current?.focus();
468
+ }, [step]);
469
+ const go = (next) => {
470
+ moved.current = true;
471
+ if (stepProp === void 0) setInternal(next);
472
+ onStepChange?.(next);
473
+ };
474
+ const last = step === steps.length - 1;
475
+ return /* @__PURE__ */ jsxs(
476
+ Md3Card,
477
+ {
478
+ ref,
479
+ variant: "outlined",
480
+ role: "group",
481
+ "aria-labelledby": headingId,
482
+ className: cn("flex flex-col gap-3 rounded-md-lg p-4", className),
483
+ ...props,
484
+ children: [
485
+ /* @__PURE__ */ jsx("div", { className: "flex gap-1", "aria-hidden": "true", children: steps.map((_, i) => /* @__PURE__ */ jsx(
486
+ "span",
487
+ {
488
+ className: cn(
489
+ "h-1 flex-1 rounded-full transition-colors duration-300 motion-reduce:transition-none",
490
+ i <= step ? "bg-md-primary" : "bg-md-secondary-container"
491
+ )
492
+ },
493
+ i
494
+ )) }),
495
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
496
+ /* @__PURE__ */ jsxs(
497
+ "p",
498
+ {
499
+ ref: headingRef,
500
+ id: headingId,
501
+ tabIndex: -1,
502
+ className: "rounded-md-xs text-sm font-medium tracking-[0.1px] text-md-on-surface outline-none focus-visible:ring-2 focus-visible:ring-md-primary",
503
+ children: [
504
+ "Step ",
505
+ step + 1,
506
+ " of ",
507
+ steps.length,
508
+ " \xB7 ",
509
+ steps[step]
510
+ ]
511
+ }
512
+ ),
513
+ description && /* @__PURE__ */ jsx("p", { className: "text-sm text-md-on-surface-variant", children: description })
514
+ ] }),
515
+ children,
516
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
517
+ step > 0 && /* @__PURE__ */ jsx(Md3Button, { variant: "text", onClick: () => go(step - 1), children: "Back" }),
518
+ /* @__PURE__ */ jsx("span", { className: "flex-1" }),
519
+ !last && allowEarlySubmit && onSubmit && /* @__PURE__ */ jsxs(Md3Button, { variant: "text", onClick: onSubmit, children: [
520
+ submitLabel,
521
+ " now"
522
+ ] }),
523
+ last ? onSubmit && /* @__PURE__ */ jsx(Md3Button, { variant: "filled", onClick: onSubmit, children: submitLabel }) : /* @__PURE__ */ jsx(Md3Button, { variant: "filled", onClick: () => go(step + 1), children: "Next" })
524
+ ] })
525
+ ]
526
+ }
527
+ );
528
+ }
529
+ );
530
+ Md3StructuredInputWizard.displayName = "Md3StructuredInputWizard";
531
+
532
+ export { Md3StructuredInput, Md3StructuredInputSlots, Md3StructuredInputTags, Md3StructuredInputWizard };
533
+ //# sourceMappingURL=index.js.map
534
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.tsx"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import * as React from \"react\";\nimport { cn } from \"@nucleux/utils\";\nimport { Md3Button } from \"@nucleux/md3-button\";\nimport { Md3Card } from \"@nucleux/md3-card\";\nimport { Md3Chip } from \"@nucleux/md3-chip\";\nimport {\n structuredPartsToText,\n type StructuredInputPart,\n type StructuredInputProps,\n type StructuredInputSlotsProps,\n type StructuredInputTagsProps,\n type StructuredInputTagTrigger,\n type StructuredInputValues,\n type StructuredInputWizardProps,\n} from \"@nucleux/structured-input\";\nimport { Check, Sparkles, UserPen, X } from \"lucide-react\";\n\n// Same API as the shadcn twin: the props and data shapes are the twin's own types.\nexport type Md3StructuredInputProps = StructuredInputProps;\nexport type Md3StructuredInputSlotsProps = StructuredInputSlotsProps;\nexport type Md3StructuredInputTagsProps = StructuredInputTagsProps;\nexport type Md3StructuredInputWizardProps = StructuredInputWizardProps;\nexport type {\n StructuredOption,\n StructuredInputSlot,\n StructuredInputValues,\n StructuredInputTagTrigger,\n StructuredInputPart,\n} from \"@nucleux/structured-input\";\n/** Serialise parts into the plain prompt text — shared with `@nucleux/structured-input`. */\nexport { structuredPartsToText };\n\nconst stateLayer =\n \"before:absolute before:inset-0 before:bg-current before:opacity-0 before:transition-opacity before:content-[''] hover:before:opacity-[0.08] focus-visible:before:opacity-[0.12] active:before:opacity-[0.12]\";\n\n/** MD3 outlined field chrome, shared by text inputs, selects and textareas. */\nconst fieldClass = cn(\n \"w-full rounded-md-xs border border-md-outline bg-transparent px-4 text-base text-md-on-surface outline-none transition-colors\",\n \"placeholder:text-md-on-surface-variant hover:border-md-on-surface\",\n \"focus:border-md-primary focus:ring-1 focus:ring-inset focus:ring-md-primary\",\n \"disabled:cursor-not-allowed disabled:opacity-[0.38]\",\n);\n\n/**\n * Material 3 structured input: an agent-generated clarifying question as a\n * compact MD3 card — single or multi-select options drawn as MD3 radio and\n * checkbox rows with a state layer, a free-text escape, and a skip. Arrow keys\n * move and select in single mode, exactly as in the twin. The other variants\n * are composable siblings: {@link Md3StructuredInputSlots},\n * {@link Md3StructuredInputTags} and {@link Md3StructuredInputWizard}. Shares\n * its API with `StructuredInput` from `@nucleux/structured-input`.\n */\nexport const Md3StructuredInput = React.forwardRef<HTMLDivElement, Md3StructuredInputProps>(\n (\n {\n question,\n options,\n multiple = false,\n value,\n defaultValue = [],\n onValueChange,\n allowOther = false,\n otherPlaceholder = \"Something else…\",\n onSubmit,\n onSkip,\n submitLabel = \"Continue\",\n skipLabel = \"Skip\",\n className,\n ...props\n },\n ref,\n ) => {\n const [internal, setInternal] = React.useState<string[]>(defaultValue);\n const [other, setOther] = React.useState(\"\");\n const questionId = React.useId();\n const groupRef = React.useRef<HTMLDivElement>(null);\n const selected = value !== undefined ? value : internal;\n\n const setSelected = (next: string[]) => {\n if (value === undefined) setInternal(next);\n onValueChange?.(next);\n };\n const toggle = (val: string) => {\n if (multiple) {\n setSelected(selected.includes(val) ? selected.filter((v) => v !== val) : [...selected, val]);\n } else {\n setSelected([val]);\n }\n };\n\n return (\n <Md3Card\n ref={ref}\n variant=\"outlined\"\n className={cn(\"flex flex-col gap-4 rounded-md-lg p-5 animate-nx-fade-in motion-reduce:animate-none\", className)}\n {...props}\n >\n <p id={questionId} className=\"text-base font-medium tracking-[0.15px] text-md-on-surface\">\n {question}\n </p>\n <div\n ref={groupRef}\n role={multiple ? \"group\" : \"radiogroup\"}\n aria-labelledby={questionId}\n className=\"flex flex-col gap-1\"\n onKeyDown={(e) => {\n // Radio-group keyboard pattern: arrows move and select.\n if (multiple || ![\"ArrowDown\", \"ArrowUp\", \"ArrowRight\", \"ArrowLeft\"].includes(e.key)) return;\n const radios = Array.from(groupRef.current?.querySelectorAll<HTMLButtonElement>('[role=\"radio\"]') ?? []);\n const i = radios.indexOf(document.activeElement as HTMLButtonElement);\n if (i < 0) return;\n e.preventDefault();\n const step = e.key === \"ArrowDown\" || e.key === \"ArrowRight\" ? 1 : -1;\n const next = (i + step + radios.length) % radios.length;\n radios[next].focus();\n setSelected([options[next].value]);\n }}\n >\n {options.map((option, index) => {\n const active = selected.includes(option.value);\n const tabbable = multiple || index === Math.max(0, options.findIndex((o) => selected.includes(o.value)));\n return (\n <button\n key={option.value}\n type=\"button\"\n role={multiple ? \"checkbox\" : \"radio\"}\n aria-checked={active}\n tabIndex={tabbable ? 0 : -1}\n onClick={() => toggle(option.value)}\n className={cn(\n \"relative flex min-h-12 items-center gap-4 overflow-hidden rounded-md-md px-3 py-2 text-left text-sm transition-colors duration-200 motion-reduce:transition-none\",\n stateLayer,\n \"outline-none focus-visible:ring-2 focus-visible:ring-md-primary\",\n active\n ? \"bg-md-secondary-container text-md-on-secondary-container\"\n : \"text-md-on-surface\",\n )}\n >\n {multiple ? (\n <span\n className={cn(\n \"relative inline-flex size-[18px] shrink-0 items-center justify-center rounded-[2px] border-2 transition-colors [&_svg]:size-3.5\",\n active ? \"border-md-primary bg-md-primary text-md-on-primary\" : \"border-md-on-surface-variant\",\n )}\n >\n {active && <Check strokeWidth={3} aria-hidden=\"true\" />}\n </span>\n ) : (\n <span\n className={cn(\n \"relative inline-flex size-5 shrink-0 items-center justify-center rounded-full border-2 transition-colors\",\n active ? \"border-md-primary\" : \"border-md-on-surface-variant\",\n )}\n >\n <span\n className={cn(\n \"size-2.5 rounded-full bg-md-primary transition-transform duration-200 motion-reduce:transition-none\",\n active ? \"scale-100\" : \"scale-0\",\n )}\n />\n </span>\n )}\n <span className=\"relative flex-1\">{option.label}</span>\n </button>\n );\n })}\n </div>\n {allowOther && (\n <input\n type=\"text\"\n value={other}\n onChange={(e) => setOther(e.target.value)}\n placeholder={otherPlaceholder}\n aria-label={otherPlaceholder}\n className={cn(fieldClass, \"h-12\")}\n />\n )}\n <div className=\"flex items-center justify-end gap-2\">\n {onSkip && (\n <Md3Button variant=\"text\" onClick={onSkip}>\n {skipLabel}\n </Md3Button>\n )}\n {onSubmit && (\n <Md3Button\n variant=\"filled\"\n onClick={() => onSubmit(selected, allowOther ? other : undefined)}\n disabled={selected.length === 0 && !(allowOther && other.trim())}\n >\n {submitLabel}\n </Md3Button>\n )}\n </div>\n </Md3Card>\n );\n },\n);\nMd3StructuredInput.displayName = \"Md3StructuredInput\";\n\n/* -------------------------------------------------------------------------- */\n/* Named slots */\n/* -------------------------------------------------------------------------- */\n\n/**\n * Material 3 named slots: a short set of plain-language MD3 outlined fields\n * (2–4) that fill a prompt template — text fields or native selects with\n * visible labels and helper text, an optional freeform override, and a submit\n * that never requires every field. Agent-suggested values carry a\n * primary-container “Suggested” mark with their reason and turn into a neutral\n * “Edited by you” once changed; the component never changes a value the person\n * set. Shares its API with `StructuredInputSlots`.\n */\nexport const Md3StructuredInputSlots = React.forwardRef<HTMLFormElement, Md3StructuredInputSlotsProps>(\n (\n {\n slots,\n values: valuesProp,\n defaultValues,\n onValuesChange,\n freeform = false,\n onSubmit,\n submitLabel = \"Generate\",\n label = \"Structured prompt builder\",\n className,\n ...props\n },\n ref,\n ) => {\n const [internal, setInternal] = React.useState<StructuredInputValues>(defaultValues ?? {});\n const values = valuesProp ?? internal;\n const [edited, setEdited] = React.useState<Record<string, boolean>>({});\n const [extra, setExtra] = React.useState(\"\");\n const baseId = React.useId();\n\n const setValue = (name: string, value: string) => {\n const next = { ...values, [name]: value };\n if (valuesProp === undefined) setInternal(next);\n setEdited((e) => ({ ...e, [name]: true }));\n onValuesChange?.(next);\n };\n\n const hasAny = Object.values(values).some((v) => v && v.trim()) || extra.trim().length > 0;\n const freeformLabel = typeof freeform === \"string\" ? freeform : \"Anything else?\";\n\n return (\n <form\n ref={ref}\n aria-label={label}\n className={cn(\"grid grid-cols-1 gap-4 text-md-on-surface sm:grid-cols-2\", className)}\n onSubmit={(e) => {\n e.preventDefault();\n if (hasAny) onSubmit?.(values, extra);\n }}\n {...props}\n >\n {slots.map((slot) => {\n const id = `${baseId}-${slot.name}`;\n const helperId = `${id}-helper`;\n const isEdited = !!edited[slot.name];\n const mark = slot.suggested ? (isEdited ? \"edited\" : \"suggested\") : null;\n const describedBy = slot.helper || mark === \"suggested\" ? helperId : undefined;\n return (\n <div key={slot.name} className={cn(\"flex flex-col gap-1.5\", slot.wide && \"sm:col-span-2\")}>\n <div className=\"flex min-h-6 items-center gap-2\">\n <label htmlFor={id} className=\"text-xs font-medium tracking-[0.5px] text-md-on-surface-variant\">\n {slot.label}\n </label>\n {mark && (\n <span\n className={cn(\n \"inline-flex h-6 items-center gap-1 rounded-md-sm px-2 text-[11px] font-medium tracking-[0.5px] [&_svg]:size-3.5\",\n mark === \"suggested\"\n ? \"bg-md-primary-container text-md-on-primary-container\"\n : \"bg-md-surface-container-high text-md-on-surface-variant\",\n )}\n >\n {mark === \"suggested\" ? <Sparkles aria-hidden=\"true\" /> : <UserPen aria-hidden=\"true\" />}\n {mark === \"suggested\" ? \"Suggested\" : \"Edited by you\"}\n </span>\n )}\n </div>\n {slot.options ? (\n <select\n id={id}\n value={values[slot.name] ?? \"\"}\n aria-describedby={describedBy}\n onChange={(e) => setValue(slot.name, e.target.value)}\n className={cn(fieldClass, \"h-14 cursor-pointer\", !values[slot.name] && \"text-md-on-surface-variant\")}\n >\n <option value=\"\" disabled>\n {slot.placeholder ?? \"Choose…\"}\n </option>\n {slot.options.map((o) => (\n <option key={o.value} value={o.value}>\n {typeof o.label === \"string\" || typeof o.label === \"number\" ? o.label : o.value}\n </option>\n ))}\n </select>\n ) : (\n <input\n id={id}\n type=\"text\"\n value={values[slot.name] ?? \"\"}\n placeholder={slot.placeholder}\n aria-describedby={describedBy}\n onChange={(e) => setValue(slot.name, e.target.value)}\n className={cn(fieldClass, \"h-14\")}\n />\n )}\n {describedBy && (\n <p id={helperId} className=\"px-4 text-xs text-md-on-surface-variant\">\n {mark === \"suggested\" ? `Suggested ${slot.suggested}. ` : \"\"}\n {slot.helper}\n </p>\n )}\n </div>\n );\n })}\n {freeform && (\n <div className=\"flex flex-col gap-1.5 sm:col-span-2\">\n <label\n htmlFor={`${baseId}-freeform`}\n className=\"text-xs font-medium tracking-[0.5px] text-md-on-surface-variant\"\n >\n {freeformLabel}\n </label>\n <textarea\n id={`${baseId}-freeform`}\n rows={2}\n value={extra}\n placeholder=\"Say it in your own words — this overrides the fields above\"\n onChange={(e) => setExtra(e.target.value)}\n className={cn(fieldClass, \"resize-none py-3\")}\n />\n </div>\n )}\n {onSubmit && (\n <div className=\"flex justify-end sm:col-span-2\">\n <Md3Button type=\"submit\" variant=\"filled\" disabled={!hasAny}>\n {submitLabel}\n </Md3Button>\n </div>\n )}\n </form>\n );\n },\n);\nMd3StructuredInputSlots.displayName = \"Md3StructuredInputSlots\";\n\n/* -------------------------------------------------------------------------- */\n/* Tagged input */\n/* -------------------------------------------------------------------------- */\n\n// Same defaults as the twin (internal there).\nconst DEFAULT_TRIGGERS: StructuredInputTagTrigger[] = [\n { trigger: \"@\", label: \"Person\" },\n { trigger: \"p:\", label: \"Project\" },\n { trigger: \"/\", label: \"File\" },\n];\n\n/** MD3 tonal roles for tag chips, cycled per trigger. */\nconst TAG_TONES = [\n \"bg-md-primary-container text-md-on-primary-container\",\n \"bg-md-secondary-container text-md-on-secondary-container\",\n \"bg-md-tertiary-container text-md-on-tertiary-container\",\n \"bg-md-surface-container-high text-md-on-surface\",\n];\n\n/**\n * Material 3 tagged input: a prompt field (MD3 outlined) where typed prefixes\n * (`@` person, `p:` project, `/` file — configurable) become removable input\n * chips in tonal containers, with type-ahead suggestions as MD3 suggestion\n * chips. Backspace on an empty field removes the last tag; Enter sends. Tags\n * are optional — plain text always works. Shares its API (and\n * `structuredPartsToText`) with `StructuredInputTags`.\n */\nexport const Md3StructuredInputTags = React.forwardRef<HTMLDivElement, Md3StructuredInputTagsProps>(\n (\n {\n triggers = DEFAULT_TRIGGERS,\n value: valueProp,\n defaultValue,\n onValueChange,\n onSubmit,\n placeholder = \"Type @ for people, p: for projects, / for files\",\n submitLabel = \"Send\",\n className,\n ...props\n },\n ref,\n ) => {\n const [internal, setInternal] = React.useState<StructuredInputPart[]>(defaultValue ?? []);\n const parts = valueProp ?? internal;\n const [draft, setDraft] = React.useState(\"\");\n const inputRef = React.useRef<HTMLInputElement>(null);\n const hintId = React.useId();\n\n const commit = (next: StructuredInputPart[]) => {\n if (valueProp === undefined) setInternal(next);\n onValueChange?.(next);\n };\n\n // Longest trigger first so \"p:\" wins over \"p\".\n const ordered = [...triggers].sort((a, b) => b.trigger.length - a.trigger.length);\n const matchTag = (word: string) => {\n const t = ordered.find((tr) => word.startsWith(tr.trigger) && word.length > tr.trigger.length);\n return t ? { trigger: t.trigger, value: word.slice(t.trigger.length) } : null;\n };\n\n const lastWord = draft.split(\" \").pop() ?? \"\";\n const activeTrigger = ordered.find((tr) => lastWord.startsWith(tr.trigger));\n const query = activeTrigger ? lastWord.slice(activeTrigger.trigger.length).toLowerCase() : \"\";\n const suggestions =\n activeTrigger?.suggestions?.filter((s) => s.toLowerCase().startsWith(query)).slice(0, 5) ?? [];\n\n /** Split the draft into text + a trailing tag (if any) and commit them. */\n const flush = (source = draft, forceTag?: { trigger: string; value: string }): StructuredInputPart[] => {\n const words = source.split(\" \");\n const last = words.pop() ?? \"\";\n const tag = forceTag ?? matchTag(last);\n const textBefore = (tag ? words.join(\" \") : source).trim();\n const next = [...parts];\n if (textBefore) next.push({ type: \"text\", text: textBefore });\n if (tag) next.push({ type: \"tag\", ...tag });\n if (next.length !== parts.length) commit(next);\n setDraft(\"\");\n return next;\n };\n\n const toneFor = (trigger: string) => {\n const i = triggers.findIndex((t) => t.trigger === trigger);\n return TAG_TONES[(i < 0 ? 0 : i) % TAG_TONES.length];\n };\n const labelFor = (trigger: string) => triggers.find((t) => t.trigger === trigger)?.label ?? \"Tag\";\n\n const submit = () => {\n const next = flush();\n const text = structuredPartsToText(next);\n if (text) onSubmit?.(next, text);\n };\n\n return (\n <div ref={ref} className={cn(\"flex flex-col gap-2 text-md-on-surface\", className)} {...props}>\n <div\n className={cn(\n \"flex min-h-14 flex-wrap items-center gap-1.5 rounded-md-xs border border-md-outline bg-transparent px-3 py-2 text-base text-md-on-surface transition-colors\",\n \"hover:border-md-on-surface focus-within:border-md-primary focus-within:ring-1 focus-within:ring-inset focus-within:ring-md-primary\",\n )}\n onClick={() => inputRef.current?.focus()}\n >\n {parts.map((part, i) =>\n part.type === \"text\" ? (\n <span key={i}>{part.text}</span>\n ) : (\n <span\n key={i}\n className={cn(\n \"inline-flex h-7 items-center gap-0.5 rounded-md-sm pl-2 pr-0.5 text-sm font-medium animate-nx-fade-in motion-reduce:animate-none\",\n toneFor(part.trigger),\n )}\n >\n {part.trigger}\n {part.value}\n <button\n type=\"button\"\n aria-label={`Remove ${labelFor(part.trigger).toLowerCase()} ${part.trigger}${part.value}`}\n onClick={(e) => {\n e.stopPropagation();\n commit(parts.filter((_, j) => j !== i));\n inputRef.current?.focus();\n }}\n className={cn(\n \"relative inline-flex size-6 items-center justify-center overflow-hidden rounded-full [&_svg]:size-3.5\",\n stateLayer,\n \"outline-none focus-visible:ring-2 focus-visible:ring-md-primary\",\n )}\n >\n <X className=\"relative\" aria-hidden=\"true\" />\n </button>\n </span>\n ),\n )}\n <input\n ref={inputRef}\n type=\"text\"\n value={draft}\n aria-label={placeholder}\n aria-describedby={hintId}\n placeholder={parts.length ? undefined : placeholder}\n onChange={(e) => {\n const v = e.target.value;\n // A space after a tag word (incl. mobile keyboards that skip keydown) makes it a chip.\n if (v.endsWith(\" \") && matchTag(v.trimEnd().split(\" \").pop() ?? \"\")) flush(v.trimEnd());\n else setDraft(v);\n }}\n onKeyDown={(e) => {\n if (e.key === \" \" && matchTag(lastWord)) {\n e.preventDefault();\n flush();\n } else if (e.key === \"Enter\") {\n e.preventDefault();\n submit();\n } else if (e.key === \"Backspace\" && draft === \"\" && parts.length) {\n e.preventDefault();\n const last = parts[parts.length - 1];\n commit(parts.slice(0, -1));\n if (last.type === \"text\") setDraft(last.text);\n }\n }}\n className=\"h-8 min-w-[8rem] flex-1 bg-transparent text-base text-md-on-surface outline-none placeholder:text-md-on-surface-variant\"\n />\n </div>\n <p id={hintId} className=\"sr-only\">\n {triggers.map((t) => `${t.trigger} for ${t.label.toLowerCase()}`).join(\", \")}. Space turns a tag into a\n chip; Backspace removes the last one; Enter sends.\n </p>\n {activeTrigger && suggestions.length > 0 && (\n <div role=\"group\" aria-label={`${activeTrigger.label} suggestions`} className=\"flex flex-wrap gap-2\">\n {suggestions.map((s) => (\n <Md3Chip\n key={s}\n variant=\"suggestion\"\n onClick={() => {\n flush(draft, { trigger: activeTrigger.trigger, value: s });\n inputRef.current?.focus();\n }}\n >\n {activeTrigger.trigger}\n {s}\n </Md3Chip>\n ))}\n </div>\n )}\n {onSubmit && (\n <div className=\"flex justify-end\">\n <Md3Button variant=\"filled\" onClick={submit} disabled={parts.length === 0 && draft.trim() === \"\"}>\n {submitLabel}\n </Md3Button>\n </div>\n )}\n </div>\n );\n },\n);\nMd3StructuredInputTags.displayName = \"Md3StructuredInputTags\";\n\n/* -------------------------------------------------------------------------- */\n/* Wizard step */\n/* -------------------------------------------------------------------------- */\n\n/**\n * Material 3 wizard step: a multi-step MD3 card for high-stakes prompts\n * (legal, HR, medical) — a segmented progress track in the primary colour,\n * “Step 2 of 3 · Audience”, the step's question and fields (children), and\n * Back / Next / Generate as MD3 text and filled buttons. Focus moves to the\n * step heading when the step changes; nothing forces every step to be filled\n * before generating. Shares its API with `StructuredInputWizard`.\n */\nexport const Md3StructuredInputWizard = React.forwardRef<HTMLDivElement, Md3StructuredInputWizardProps>(\n (\n {\n steps,\n step: stepProp,\n defaultStep = 0,\n onStepChange,\n description,\n onSubmit,\n submitLabel = \"Generate\",\n allowEarlySubmit = true,\n className,\n children,\n ...props\n },\n ref,\n ) => {\n const [internal, setInternal] = React.useState(defaultStep);\n const step = Math.min(Math.max(stepProp ?? internal, 0), Math.max(steps.length - 1, 0));\n const headingRef = React.useRef<HTMLParagraphElement>(null);\n const headingId = React.useId();\n const moved = React.useRef(false);\n\n React.useEffect(() => {\n if (moved.current) headingRef.current?.focus();\n }, [step]);\n\n const go = (next: number) => {\n moved.current = true;\n if (stepProp === undefined) setInternal(next);\n onStepChange?.(next);\n };\n\n const last = step === steps.length - 1;\n\n return (\n <Md3Card\n ref={ref}\n variant=\"outlined\"\n role=\"group\"\n aria-labelledby={headingId}\n className={cn(\"flex flex-col gap-3 rounded-md-lg p-4\", className)}\n {...props}\n >\n <div className=\"flex gap-1\" aria-hidden=\"true\">\n {steps.map((_, i) => (\n <span\n key={i}\n className={cn(\n \"h-1 flex-1 rounded-full transition-colors duration-300 motion-reduce:transition-none\",\n i <= step ? \"bg-md-primary\" : \"bg-md-secondary-container\",\n )}\n />\n ))}\n </div>\n <div className=\"flex flex-col gap-1\">\n <p\n ref={headingRef}\n id={headingId}\n tabIndex={-1}\n className=\"rounded-md-xs text-sm font-medium tracking-[0.1px] text-md-on-surface outline-none focus-visible:ring-2 focus-visible:ring-md-primary\"\n >\n Step {step + 1} of {steps.length} · {steps[step]}\n </p>\n {description && <p className=\"text-sm text-md-on-surface-variant\">{description}</p>}\n </div>\n {children}\n <div className=\"flex items-center gap-2\">\n {step > 0 && (\n <Md3Button variant=\"text\" onClick={() => go(step - 1)}>\n Back\n </Md3Button>\n )}\n <span className=\"flex-1\" />\n {!last && allowEarlySubmit && onSubmit && (\n <Md3Button variant=\"text\" onClick={onSubmit}>\n {submitLabel} now\n </Md3Button>\n )}\n {last ? (\n onSubmit && (\n <Md3Button variant=\"filled\" onClick={onSubmit}>\n {submitLabel}\n </Md3Button>\n )\n ) : (\n <Md3Button variant=\"filled\" onClick={() => go(step + 1)}>\n Next\n </Md3Button>\n )}\n </div>\n </Md3Card>\n );\n },\n);\nMd3StructuredInputWizard.displayName = \"Md3StructuredInputWizard\";\n"]}