@lattice-php/lattice 0.25.0 → 0.26.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/action/components/action-form.js +1 -1
- package/dist/action/components/action-form.js.map +1 -1
- package/dist/action/components/action-group.js +1 -1
- package/dist/action/components/action-group.js.map +1 -1
- package/dist/action/components/action.js +3 -2
- package/dist/action/components/action.js.map +1 -1
- package/dist/action/hooks/use-action.js +2 -1
- package/dist/action/hooks/use-action.js.map +1 -1
- package/dist/appearance/index.d.ts +1 -1
- package/dist/appearance/index.js +8 -8
- package/dist/appearance/index.js.map +1 -1
- package/dist/chat/components/prompt-input.js +1 -2
- package/dist/chat/components/prompt-input.js.map +1 -1
- package/dist/create-app.js +2 -2
- package/dist/create-app.js.map +1 -1
- package/dist/form/components/base/submit-button.d.ts +4 -3
- package/dist/form/components/base/submit-button.js +2 -1
- package/dist/form/components/base/submit-button.js.map +1 -1
- package/dist/form/components/fields/date-picker-field.js +3 -3
- package/dist/form/components/fields/date-picker-field.js.map +1 -1
- package/dist/form/components/fields/number-input.js +1 -1
- package/dist/form/components/fields/number-input.js.map +1 -1
- package/dist/form/components/fields/rich-editor-field.js +1 -1
- package/dist/form/components/fields/rich-editor-field.js.map +1 -1
- package/dist/form/components/fields/row-action-menu.js +3 -3
- package/dist/form/components/fields/row-action-menu.js.map +1 -1
- package/dist/form/components/fields/row-actions.d.ts +1 -1
- package/dist/form/components/fields/row-actions.js +4 -4
- package/dist/form/components/fields/row-actions.js.map +1 -1
- package/dist/form/components/fields/toggle.js +1 -1
- package/dist/form/components/fields/toggle.js.map +1 -1
- package/dist/form/components/form.js +7 -3
- package/dist/form/components/form.js.map +1 -1
- package/dist/form/components/wizard.js +1 -1
- package/dist/form/components/wizard.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/lattice.css +183 -115
- package/dist/notifications/components/notification-item.js +3 -1
- package/dist/notifications/components/notification-item.js.map +1 -1
- package/dist/notifications/components/notifications.js +2 -4
- package/dist/notifications/components/notifications.js.map +1 -1
- package/dist/table/components/bulk-bar.js +2 -0
- package/dist/table/components/bulk-bar.js.map +1 -1
- package/dist/table/components/cells/badge-cell.js +3 -6
- package/dist/table/components/cells/badge-cell.js.map +1 -1
- package/dist/table/components/cells/text-cell.js +6 -9
- package/dist/table/components/cells/text-cell.js.map +1 -1
- package/dist/table/components/column-filter-control.js +2 -2
- package/dist/table/components/column-filter-control.js.map +1 -1
- package/dist/table/components/filter-bar.js +1 -1
- package/dist/table/components/filter-bar.js.map +1 -1
- package/dist/table/components/pagination.js +6 -6
- package/dist/table/components/pagination.js.map +1 -1
- package/dist/table/lib/bulk.d.ts +3 -2
- package/dist/table/lib/bulk.js +2 -1
- package/dist/table/lib/bulk.js.map +1 -1
- package/dist/toast/toast.js +3 -1
- package/dist/toast/toast.js.map +1 -1
- package/dist/toast/variant-styles.js +15 -1
- package/dist/toast/variant-styles.js.map +1 -1
- package/dist/types/generated.d.ts +14 -9
- package/dist/ui/action-menu-context.d.ts +1 -1
- package/dist/ui/action-menu-context.js +1 -1
- package/dist/ui/action-menu-context.js.map +1 -1
- package/dist/ui/affix-group.js +1 -1
- package/dist/ui/affix-group.js.map +1 -1
- package/dist/ui/badge.d.ts +4 -7
- package/dist/ui/badge.js +11 -17
- package/dist/ui/badge.js.map +1 -1
- package/dist/ui/button.d.ts +6 -5
- package/dist/ui/button.js +154 -15
- package/dist/ui/button.js.map +1 -1
- package/dist/ui/chart-view.js +9 -7
- package/dist/ui/chart-view.js.map +1 -1
- package/dist/ui/checkbox.js +1 -1
- package/dist/ui/checkbox.js.map +1 -1
- package/dist/ui/confirm-dialog.d.ts +4 -3
- package/dist/ui/confirm-dialog.js +3 -2
- package/dist/ui/confirm-dialog.js.map +1 -1
- package/dist/ui/control.d.ts +1 -1
- package/dist/ui/control.js +1 -1
- package/dist/ui/control.js.map +1 -1
- package/dist/ui/dialog.js +1 -1
- package/dist/ui/dialog.js.map +1 -1
- package/dist/ui/dropdown-menu.d.ts +2 -2
- package/dist/ui/dropdown-menu.js +2 -2
- package/dist/ui/dropdown-menu.js.map +1 -1
- package/dist/ui/icon-button.d.ts +3 -3
- package/dist/ui/icon-button.js +6 -6
- package/dist/ui/icon-button.js.map +1 -1
- package/dist/ui/image-preview.js +1 -1
- package/dist/ui/image-preview.js.map +1 -1
- package/dist/ui/index.d.ts +2 -2
- package/dist/ui/index.js +2 -2
- package/dist/ui/info-tooltip.js +1 -1
- package/dist/ui/info-tooltip.js.map +1 -1
- package/dist/ui/input-otp.js +1 -1
- package/dist/ui/input-otp.js.map +1 -1
- package/dist/ui/label.js +1 -1
- package/dist/ui/label.js.map +1 -1
- package/dist/ui/password-input.js +1 -1
- package/dist/ui/password-input.js.map +1 -1
- package/dist/ui/progress.js +2 -2
- package/dist/ui/progress.js.map +1 -1
- package/dist/ui/text.js +1 -1
- package/dist/ui/tooltip.js +1 -1
- package/dist/ui/tooltip.js.map +1 -1
- package/dist-standalone/chunks/{chart-view-DEwGTt9d.js → chart-view-8xEKTUJV.js} +1 -1
- package/dist-standalone/chunks/{date-picker-field-CCQ9nWx0.js → date-picker-field-cdhxtVSG.js} +1 -1
- package/dist-standalone/chunks/{rich-editor-field-B9Nv1qia.js → rich-editor-field-47ov3Bny.js} +1 -1
- package/dist-standalone/lattice.css +1 -1
- package/dist-standalone/lattice.js +6 -6
- package/dist-standalone/manifest.json +5 -5
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rich-editor-field.js","names":[],"sources":["../../../../resources/js/form/components/fields/rich-editor-field.tsx"],"sourcesContent":["import { Placeholder } from \"@tiptap/extensions\";\nimport { type Editor, EditorContent, useEditor } from \"@tiptap/react\";\nimport { StarterKit } from \"@tiptap/starter-kit\";\nimport { useEffect, useMemo } from \"react\";\nimport { cn } from \"@lattice-php/lattice/lib/utils\";\nimport { useT } from \"@lattice-php/lattice/i18n\";\nimport type { RendererComponent } from \"@lattice-php/lattice/core/types\";\nimport { FormFieldFrame } from \"@lattice-php/lattice/form/components/base/field\";\nimport { useFormContext } from \"@lattice-php/lattice/form/hooks/context\";\nimport { useFieldScope } from \"@lattice-php/lattice/form/hooks/field-scope\";\nimport { useDependentField } from \"@lattice-php/lattice/form/hooks/use-dependent-field\";\nimport { useFieldCommit } from \"@lattice-php/lattice/form/hooks/use-field-commit\";\nimport { useFormValue } from \"@lattice-php/lattice/form/hooks/values\";\nimport { registerBuiltinRichEditorExtensions } from \"@lattice-php/lattice/form/rich-editor/builtins\";\nimport {\n assembleStarterKitOptions,\n assembleTiptapExtensions,\n assembleToolbar,\n resolveRichEditorExtensions,\n type ToolbarEntry,\n} from \"@lattice-php/lattice/form/rich-editor/registry\";\nimport { ToolbarIconButton } from \"@lattice-php/lattice/form/rich-editor/toolbar-button\";\n\nregisterBuiltinRichEditorExtensions();\n\nfunction Toolbar({ editor, items }: { editor: Editor; items: ToolbarEntry[] }) {\n const { t } = useT(\"lattice\");\n\n return (\n <div className=\"flex flex-wrap items-center gap-0.5 border-b border-lt-border p-1\">\n {items.map((item, index) => {\n if (item === \"separator\") {\n // eslint-disable-next-line react/no-array-index-key\n return <span key={`sep-${index}`} className=\"mx-1 h-5 w-px bg-lt-border\" />;\n }\n\n if (\"component\" in item) {\n const Control = item.component;\n\n return <Control editor={editor} key={item.key} />;\n }\n\n const label = t(`form.editor.${item.key}`, item.label);\n\n return (\n <ToolbarIconButton\n active={item.isActive(editor)}\n disabled={item.isDisabled?.(editor) ?? false}\n icon={item.icon}\n key={item.key}\n label={label}\n onClick={() => item.run(editor)}\n testId={`editor-${item.key}`}\n />\n );\n })}\n </div>\n );\n}\n\nconst RichEditorField: RendererComponent<\"field.rich-editor\"> = ({ node }) => {\n const { errors } = useFormContext();\n const { hidden, required, readOnly, disabled } = useDependentField(node);\n const { change, blur } = useFieldCommit();\n const name = node.props.name;\n const scope = useFieldScope();\n const globalValue = useFormValue(name);\n const storedValue = scope ? scope.getValue(name) : globalValue;\n const domName = scope ? scope.scopedName(name) : name;\n const errorKey = scope ? scope.errorKey(name) : name;\n const locked = readOnly || disabled;\n const initialContent =\n typeof storedValue === \"object\" && storedValue !== null\n ? (storedValue as object)\n : ((node.props.value as object | undefined) ?? \"\");\n\n const resolved = useMemo(\n () => resolveRichEditorExtensions(node.props.extensions),\n [node.props.extensions],\n );\n const toolbar = useMemo(() => assembleToolbar(resolved), [resolved]);\n const extensions = useMemo(\n () => [\n StarterKit.configure(assembleStarterKitOptions(resolved)),\n Placeholder.configure({ placeholder: node.props.placeholder ?? \"\" }),\n ...assembleTiptapExtensions(resolved),\n ],\n [resolved, node.props.placeholder],\n );\n\n const editor = useEditor({\n extensions,\n content: initialContent,\n editable: !locked,\n immediatelyRender: false,\n // Tiptap v3 stops re-rendering per transaction by default, but the toolbar\n // reads isActive/isDisabled during render — without this, selection-only\n // transactions leave those states stale.\n shouldRerenderOnTransaction: true,\n editorProps: {\n attributes: {\n class: \"lattice-prose min-h-32 px-3 py-2 outline-none\",\n },\n },\n onUpdate: ({ editor: instance }) => {\n change(name, instance.isEmpty ? null : instance.getJSON());\n },\n onBlur: () => {\n blur(name);\n },\n });\n\n useEffect(() => {\n editor?.setEditable(!locked);\n }, [editor, locked]);\n\n if (hidden) {\n return null;\n }\n\n const submittedValue = storedValue ? JSON.stringify(storedValue) : \"\";\n\n return (\n <FormFieldFrame\n error={errors[errorKey]}\n helperText={node.props.helperText ?? undefined}\n tooltip={node.props.tooltip ?? undefined}\n label={node.props.label ?? \"\"}\n name={domName}\n required={required}\n >\n <div\n className={cn(\n \"overflow-hidden rounded-lt-sm border border-lt-input bg-transparent shadow-lt-xs focus-within:border-lt-ring focus-within:ring-[
|
|
1
|
+
{"version":3,"file":"rich-editor-field.js","names":[],"sources":["../../../../resources/js/form/components/fields/rich-editor-field.tsx"],"sourcesContent":["import { Placeholder } from \"@tiptap/extensions\";\nimport { type Editor, EditorContent, useEditor } from \"@tiptap/react\";\nimport { StarterKit } from \"@tiptap/starter-kit\";\nimport { useEffect, useMemo } from \"react\";\nimport { cn } from \"@lattice-php/lattice/lib/utils\";\nimport { useT } from \"@lattice-php/lattice/i18n\";\nimport type { RendererComponent } from \"@lattice-php/lattice/core/types\";\nimport { FormFieldFrame } from \"@lattice-php/lattice/form/components/base/field\";\nimport { useFormContext } from \"@lattice-php/lattice/form/hooks/context\";\nimport { useFieldScope } from \"@lattice-php/lattice/form/hooks/field-scope\";\nimport { useDependentField } from \"@lattice-php/lattice/form/hooks/use-dependent-field\";\nimport { useFieldCommit } from \"@lattice-php/lattice/form/hooks/use-field-commit\";\nimport { useFormValue } from \"@lattice-php/lattice/form/hooks/values\";\nimport { registerBuiltinRichEditorExtensions } from \"@lattice-php/lattice/form/rich-editor/builtins\";\nimport {\n assembleStarterKitOptions,\n assembleTiptapExtensions,\n assembleToolbar,\n resolveRichEditorExtensions,\n type ToolbarEntry,\n} from \"@lattice-php/lattice/form/rich-editor/registry\";\nimport { ToolbarIconButton } from \"@lattice-php/lattice/form/rich-editor/toolbar-button\";\n\nregisterBuiltinRichEditorExtensions();\n\nfunction Toolbar({ editor, items }: { editor: Editor; items: ToolbarEntry[] }) {\n const { t } = useT(\"lattice\");\n\n return (\n <div className=\"flex flex-wrap items-center gap-0.5 border-b border-lt-border p-1\">\n {items.map((item, index) => {\n if (item === \"separator\") {\n // eslint-disable-next-line react/no-array-index-key\n return <span key={`sep-${index}`} className=\"mx-1 h-5 w-px bg-lt-border\" />;\n }\n\n if (\"component\" in item) {\n const Control = item.component;\n\n return <Control editor={editor} key={item.key} />;\n }\n\n const label = t(`form.editor.${item.key}`, item.label);\n\n return (\n <ToolbarIconButton\n active={item.isActive(editor)}\n disabled={item.isDisabled?.(editor) ?? false}\n icon={item.icon}\n key={item.key}\n label={label}\n onClick={() => item.run(editor)}\n testId={`editor-${item.key}`}\n />\n );\n })}\n </div>\n );\n}\n\nconst RichEditorField: RendererComponent<\"field.rich-editor\"> = ({ node }) => {\n const { errors } = useFormContext();\n const { hidden, required, readOnly, disabled } = useDependentField(node);\n const { change, blur } = useFieldCommit();\n const name = node.props.name;\n const scope = useFieldScope();\n const globalValue = useFormValue(name);\n const storedValue = scope ? scope.getValue(name) : globalValue;\n const domName = scope ? scope.scopedName(name) : name;\n const errorKey = scope ? scope.errorKey(name) : name;\n const locked = readOnly || disabled;\n const initialContent =\n typeof storedValue === \"object\" && storedValue !== null\n ? (storedValue as object)\n : ((node.props.value as object | undefined) ?? \"\");\n\n const resolved = useMemo(\n () => resolveRichEditorExtensions(node.props.extensions),\n [node.props.extensions],\n );\n const toolbar = useMemo(() => assembleToolbar(resolved), [resolved]);\n const extensions = useMemo(\n () => [\n StarterKit.configure(assembleStarterKitOptions(resolved)),\n Placeholder.configure({ placeholder: node.props.placeholder ?? \"\" }),\n ...assembleTiptapExtensions(resolved),\n ],\n [resolved, node.props.placeholder],\n );\n\n const editor = useEditor({\n extensions,\n content: initialContent,\n editable: !locked,\n immediatelyRender: false,\n // Tiptap v3 stops re-rendering per transaction by default, but the toolbar\n // reads isActive/isDisabled during render — without this, selection-only\n // transactions leave those states stale.\n shouldRerenderOnTransaction: true,\n editorProps: {\n attributes: {\n class: \"lattice-prose min-h-32 px-3 py-2 outline-none\",\n },\n },\n onUpdate: ({ editor: instance }) => {\n change(name, instance.isEmpty ? null : instance.getJSON());\n },\n onBlur: () => {\n blur(name);\n },\n });\n\n useEffect(() => {\n editor?.setEditable(!locked);\n }, [editor, locked]);\n\n if (hidden) {\n return null;\n }\n\n const submittedValue = storedValue ? JSON.stringify(storedValue) : \"\";\n\n return (\n <FormFieldFrame\n error={errors[errorKey]}\n helperText={node.props.helperText ?? undefined}\n tooltip={node.props.tooltip ?? undefined}\n label={node.props.label ?? \"\"}\n name={domName}\n required={required}\n >\n <div\n className={cn(\n \"overflow-hidden rounded-lt-sm border border-lt-input bg-transparent shadow-lt-xs focus-within:border-lt-ring focus-within:ring-[length:var(--lt-ring-width)] focus-within:ring-lt-ring/50\",\n locked && \"opacity-60\",\n )}\n >\n {editor && !locked && toolbar.length > 0 && <Toolbar editor={editor} items={toolbar} />}\n <EditorContent editor={editor} />\n </div>\n <input name={domName} type=\"hidden\" value={submittedValue} />\n </FormFieldFrame>\n );\n};\n\nexport default RichEditorField;\n"],"mappings":"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"}
|
|
@@ -28,7 +28,7 @@ function defaultActions(removable) {
|
|
|
28
28
|
key: "remove",
|
|
29
29
|
label: null,
|
|
30
30
|
icon: null,
|
|
31
|
-
|
|
31
|
+
danger: true
|
|
32
32
|
}];
|
|
33
33
|
}
|
|
34
34
|
function toClientAction(action, ctx) {
|
|
@@ -38,7 +38,7 @@ function toClientAction(action, ctx) {
|
|
|
38
38
|
key: action.key,
|
|
39
39
|
label: action.label ?? ctx.t(builtIn.key, builtIn.fallback),
|
|
40
40
|
icon: action.icon ?? builtIn.icon,
|
|
41
|
-
|
|
41
|
+
danger: action.danger,
|
|
42
42
|
onClick: () => ctx.onDuplicate(ctx.index)
|
|
43
43
|
};
|
|
44
44
|
}
|
|
@@ -49,7 +49,7 @@ function toClientAction(action, ctx) {
|
|
|
49
49
|
key: action.key,
|
|
50
50
|
label: action.label ?? ctx.t(builtIn.key, builtIn.fallback),
|
|
51
51
|
icon: action.icon ?? builtIn.icon,
|
|
52
|
-
|
|
52
|
+
danger: action.danger,
|
|
53
53
|
onClick: () => ctx.onRemove(ctx.index)
|
|
54
54
|
};
|
|
55
55
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"row-action-menu.js","names":[],"sources":["../../../../resources/js/form/components/fields/row-action-menu.ts"],"sourcesContent":["import type { RowAction as WireRowAction } from \"@lattice-php/lattice/types/generated\";\nimport type { RowAction } from \"./row-actions\";\n\ntype RowActionTranslate = (key: string, fallback: string) => string;\n\n/** Translation key + fallback and icon for each built-in; the server sends null labels. */\nconst BUILT_IN: Record<\"duplicate\" | \"remove\", { key: string; fallback: string; icon: string }> = {\n duplicate: { key: \"table.row-actions.duplicate\", fallback: \"Duplicate\", icon: \"copy\" },\n remove: { key: \"table.row-actions.remove\", fallback: \"Remove\", icon: \"trash-2\" },\n};\n\nexport type RowActionContext = {\n index: number;\n removable: boolean;\n onRemove: (index: number) => void;\n onDuplicate: (index: number) => void;\n t: RowActionTranslate;\n};\n\n/**\n * Resolves the declared wire row actions into the click-wired client actions the\n * kebab renders. `null` (undeclared) falls back to the built-in remove; an empty\n * array disables row actions entirely. Remove is dropped while the row is at its\n * minimum, and built-in labels resolve through i18n when the server sends none.\n */\nexport function buildRowActions(\n declared: WireRowAction[] | null,\n ctx: RowActionContext,\n): RowAction[] {\n const source = declared ?? defaultActions(ctx.removable);\n\n return source\n .map((action) => toClientAction(action, ctx))\n .filter((action): action is RowAction => action !== null);\n}\n\nfunction defaultActions(removable: boolean): WireRowAction[] {\n if (!removable) {\n return [];\n }\n\n return [{ type: \"remove\", key: \"remove\", label: null, icon: null,
|
|
1
|
+
{"version":3,"file":"row-action-menu.js","names":[],"sources":["../../../../resources/js/form/components/fields/row-action-menu.ts"],"sourcesContent":["import type { RowAction as WireRowAction } from \"@lattice-php/lattice/types/generated\";\nimport type { RowAction } from \"./row-actions\";\n\ntype RowActionTranslate = (key: string, fallback: string) => string;\n\n/** Translation key + fallback and icon for each built-in; the server sends null labels. */\nconst BUILT_IN: Record<\"duplicate\" | \"remove\", { key: string; fallback: string; icon: string }> = {\n duplicate: { key: \"table.row-actions.duplicate\", fallback: \"Duplicate\", icon: \"copy\" },\n remove: { key: \"table.row-actions.remove\", fallback: \"Remove\", icon: \"trash-2\" },\n};\n\nexport type RowActionContext = {\n index: number;\n removable: boolean;\n onRemove: (index: number) => void;\n onDuplicate: (index: number) => void;\n t: RowActionTranslate;\n};\n\n/**\n * Resolves the declared wire row actions into the click-wired client actions the\n * kebab renders. `null` (undeclared) falls back to the built-in remove; an empty\n * array disables row actions entirely. Remove is dropped while the row is at its\n * minimum, and built-in labels resolve through i18n when the server sends none.\n */\nexport function buildRowActions(\n declared: WireRowAction[] | null,\n ctx: RowActionContext,\n): RowAction[] {\n const source = declared ?? defaultActions(ctx.removable);\n\n return source\n .map((action) => toClientAction(action, ctx))\n .filter((action): action is RowAction => action !== null);\n}\n\nfunction defaultActions(removable: boolean): WireRowAction[] {\n if (!removable) {\n return [];\n }\n\n return [{ type: \"remove\", key: \"remove\", label: null, icon: null, danger: true }];\n}\n\nfunction toClientAction(action: WireRowAction, ctx: RowActionContext): RowAction | null {\n if (action.type === \"duplicate\") {\n const builtIn = BUILT_IN.duplicate;\n\n return {\n key: action.key,\n label: action.label ?? ctx.t(builtIn.key, builtIn.fallback),\n icon: action.icon ?? builtIn.icon,\n danger: action.danger,\n onClick: () => ctx.onDuplicate(ctx.index),\n };\n }\n\n if (action.type === \"remove\") {\n if (!ctx.removable) {\n return null;\n }\n\n const builtIn = BUILT_IN.remove;\n\n return {\n key: action.key,\n label: action.label ?? ctx.t(builtIn.key, builtIn.fallback),\n icon: action.icon ?? builtIn.icon,\n danger: action.danger,\n onClick: () => ctx.onRemove(ctx.index),\n };\n }\n\n return null;\n}\n"],"mappings":";;AAMA,IAAM,WAA4F;CAChG,WAAW;EAAE,KAAK;EAA+B,UAAU;EAAa,MAAM;CAAO;CACrF,QAAQ;EAAE,KAAK;EAA4B,UAAU;EAAU,MAAM;CAAU;AACjF;;;;;;;AAgBA,SAAgB,gBACd,UACA,KACa;CAGb,QAFe,YAAY,eAAe,IAAI,SAAS,GAGpD,KAAK,WAAW,eAAe,QAAQ,GAAG,CAAC,EAC3C,QAAQ,WAAgC,WAAW,IAAI;AAC5D;AAEA,SAAS,eAAe,WAAqC;CAC3D,IAAI,CAAC,WACH,OAAO,CAAC;CAGV,OAAO,CAAC;EAAE,MAAM;EAAU,KAAK;EAAU,OAAO;EAAM,MAAM;EAAM,QAAQ;CAAK,CAAC;AAClF;AAEA,SAAS,eAAe,QAAuB,KAAyC;CACtF,IAAI,OAAO,SAAS,aAAa;EAC/B,MAAM,UAAU,SAAS;EAEzB,OAAO;GACL,KAAK,OAAO;GACZ,OAAO,OAAO,SAAS,IAAI,EAAE,QAAQ,KAAK,QAAQ,QAAQ;GAC1D,MAAM,OAAO,QAAQ,QAAQ;GAC7B,QAAQ,OAAO;GACf,eAAe,IAAI,YAAY,IAAI,KAAK;EAC1C;CACF;CAEA,IAAI,OAAO,SAAS,UAAU;EAC5B,IAAI,CAAC,IAAI,WACP,OAAO;EAGT,MAAM,UAAU,SAAS;EAEzB,OAAO;GACL,KAAK,OAAO;GACZ,OAAO,OAAO,SAAS,IAAI,EAAE,QAAQ,KAAK,QAAQ,QAAQ;GAC1D,MAAM,OAAO,QAAQ,QAAQ;GAC7B,QAAQ,OAAO;GACf,eAAe,IAAI,SAAS,IAAI,KAAK;EACvC;CACF;CAEA,OAAO;AACT"}
|
|
@@ -3,8 +3,8 @@ import { Icon } from "../../../icons/sprite.js";
|
|
|
3
3
|
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from "../../../ui/dropdown-menu.js";
|
|
4
4
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
5
5
|
//#region resources/js/form/components/fields/row-actions.tsx
|
|
6
|
-
function inlineClass(
|
|
7
|
-
return
|
|
6
|
+
function inlineClass(danger) {
|
|
7
|
+
return danger ? "text-lt-danger hover:text-lt-danger [&_svg]:size-lt-icon-sm" : "text-lt-muted-fg hover:text-lt-fg [&_svg]:size-lt-icon-sm";
|
|
8
8
|
}
|
|
9
9
|
function RowActions({ actions }) {
|
|
10
10
|
const { t } = useT("lattice");
|
|
@@ -15,7 +15,7 @@ function RowActions({ actions }) {
|
|
|
15
15
|
type: "button",
|
|
16
16
|
"aria-label": action.label,
|
|
17
17
|
"data-test": `row-action-${action.key}`,
|
|
18
|
-
className: inlineClass(action.
|
|
18
|
+
className: inlineClass(action.danger),
|
|
19
19
|
onClick: action.onClick,
|
|
20
20
|
children: /* @__PURE__ */ jsx(Icon, { name: action.icon })
|
|
21
21
|
});
|
|
@@ -34,7 +34,7 @@ function RowActions({ actions }) {
|
|
|
34
34
|
className: "min-w-[10rem]",
|
|
35
35
|
children: actions.map((action) => /* @__PURE__ */ jsx(DropdownMenuItem, {
|
|
36
36
|
"data-test": `row-action-${action.key}`,
|
|
37
|
-
|
|
37
|
+
danger: action.danger,
|
|
38
38
|
icon: action.icon,
|
|
39
39
|
onClick: action.onClick,
|
|
40
40
|
children: action.label
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"row-actions.js","names":[],"sources":["../../../../resources/js/form/components/fields/row-actions.tsx"],"sourcesContent":["import { Icon } from \"@lattice-php/lattice/icons\";\nimport { useT } from \"@lattice-php/lattice/i18n\";\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuTrigger,\n} from \"@lattice-php/lattice/ui/dropdown-menu\";\n\nexport type RowAction = {\n key: string;\n label: string;\n icon: string;\n onClick: () => void;\n
|
|
1
|
+
{"version":3,"file":"row-actions.js","names":[],"sources":["../../../../resources/js/form/components/fields/row-actions.tsx"],"sourcesContent":["import { Icon } from \"@lattice-php/lattice/icons\";\nimport { useT } from \"@lattice-php/lattice/i18n\";\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuTrigger,\n} from \"@lattice-php/lattice/ui/dropdown-menu\";\n\nexport type RowAction = {\n key: string;\n label: string;\n icon: string;\n onClick: () => void;\n danger?: boolean;\n};\n\nfunction inlineClass(danger?: boolean): string {\n return danger\n ? \"text-lt-danger hover:text-lt-danger [&_svg]:size-lt-icon-sm\"\n : \"text-lt-muted-fg hover:text-lt-fg [&_svg]:size-lt-icon-sm\";\n}\n\nexport function RowActions({ actions }: { actions: RowAction[] }) {\n const { t } = useT(\"lattice\");\n if (actions.length === 0) {\n return null;\n }\n\n if (actions.length === 1) {\n const action = actions[0];\n return (\n <button\n type=\"button\"\n aria-label={action.label}\n data-test={`row-action-${action.key}`}\n className={inlineClass(action.danger)}\n onClick={action.onClick}\n >\n <Icon name={action.icon} />\n </button>\n );\n }\n\n return (\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <button\n type=\"button\"\n aria-label={t(\"common.action-group.label\", \"Actions\")}\n data-test=\"row-actions-menu\"\n className=\"text-lt-muted-fg hover:text-lt-fg [&_svg]:size-lt-icon-sm\"\n >\n <Icon name=\"more-horizontal\" />\n </button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\" className=\"min-w-[10rem]\">\n {actions.map((action) => (\n <DropdownMenuItem\n key={action.key}\n data-test={`row-action-${action.key}`}\n danger={action.danger}\n icon={action.icon}\n onClick={action.onClick}\n >\n {action.label}\n </DropdownMenuItem>\n ))}\n </DropdownMenuContent>\n </DropdownMenu>\n );\n}\n"],"mappings":";;;;;AAiBA,SAAS,YAAY,QAA0B;CAC7C,OAAO,SACH,gEACA;AACN;AAEA,SAAgB,WAAW,EAAE,WAAqC;CAChE,MAAM,EAAE,MAAM,KAAK,SAAS;CAC5B,IAAI,QAAQ,WAAW,GACrB,OAAO;CAGT,IAAI,QAAQ,WAAW,GAAG;EACxB,MAAM,SAAS,QAAQ;EACvB,OACE,oBAAC,UAAD;GACE,MAAK;GACL,cAAY,OAAO;GACnB,aAAW,cAAc,OAAO;GAChC,WAAW,YAAY,OAAO,MAAM;GACpC,SAAS,OAAO;aAEhB,oBAAC,MAAD,EAAM,MAAM,OAAO,KAAO,CAAA;EACpB,CAAA;CAEZ;CAEA,OACE,qBAAC,cAAD,EAAA,UAAA,CACE,oBAAC,qBAAD;EAAqB,SAAA;YACnB,oBAAC,UAAD;GACE,MAAK;GACL,cAAY,EAAE,6BAA6B,SAAS;GACpD,aAAU;GACV,WAAU;aAEV,oBAAC,MAAD,EAAM,MAAK,kBAAmB,CAAA;EACxB,CAAA;CACW,CAAA,GACrB,oBAAC,qBAAD;EAAqB,OAAM;EAAM,WAAU;YACxC,QAAQ,KAAK,WACZ,oBAAC,kBAAD;GAEE,aAAW,cAAc,OAAO;GAChC,QAAQ,OAAO;GACf,MAAM,OAAO;GACb,SAAS,OAAO;aAEf,OAAO;EACQ,GAPX,OAAO,GAOI,CACnB;CACkB,CAAA,CACT,EAAA,CAAA;AAElB"}
|
|
@@ -43,7 +43,7 @@ var ToggleComponent = ({ node }) => {
|
|
|
43
43
|
"aria-checked": checked,
|
|
44
44
|
"aria-label": props.label ?? localName,
|
|
45
45
|
autoFocus: props.autoFocus ?? false,
|
|
46
|
-
className: cn("inline-flex h-6 w-11 shrink-0 cursor-pointer items-center rounded-full border border-transparent bg-lt-muted p-0.5 shadow-lt-xs transition-colors outline-none focus-visible:border-lt-ring focus-visible:ring-[
|
|
46
|
+
className: cn("inline-flex h-6 w-11 shrink-0 cursor-pointer items-center rounded-full border border-transparent bg-lt-muted p-0.5 shadow-lt-xs transition-colors outline-none focus-visible:border-lt-ring focus-visible:ring-[length:var(--lt-ring-width)] focus-visible:ring-lt-ring/50 disabled:cursor-not-allowed disabled:bg-lt-disabled data-[state=checked]:bg-lt-primary disabled:data-[state=checked]:bg-lt-disabled"),
|
|
47
47
|
"data-state": checked ? "checked" : "unchecked",
|
|
48
48
|
"data-test": testIdentity(localName),
|
|
49
49
|
disabled: locked,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"toggle.js","names":[],"sources":["../../../../resources/js/form/components/fields/toggle.tsx"],"sourcesContent":["import type { RendererComponent } from \"@lattice-php/lattice/core/types\";\nimport { testIdentity } from \"@lattice-php/lattice/core/test-id\";\nimport { cn } from \"@lattice-php/lattice/lib/utils\";\nimport { FormFieldFrame } from \"@lattice-php/lattice/form/components/base/field\";\nimport { toBoolean } from \"@lattice-php/lattice/form/lib/conditions\";\nimport { useFormContext } from \"@lattice-php/lattice/form/hooks/context\";\nimport { fieldDomName } from \"@lattice-php/lattice/form/lib/field-dom-name\";\nimport { useFieldScope } from \"@lattice-php/lattice/form/hooks/field-scope\";\nimport { useDependentField } from \"@lattice-php/lattice/form/hooks/use-dependent-field\";\nimport { useFieldCommit } from \"@lattice-php/lattice/form/hooks/use-field-commit\";\nimport { useSeedDefault } from \"@lattice-php/lattice/form/hooks/use-seed-default\";\nimport { useFormValue } from \"@lattice-php/lattice/form/hooks/values\";\n\nexport const ToggleComponent: RendererComponent<\"field.toggle\"> = ({ node }) => {\n const { hidden, required, readOnly, disabled } = useDependentField(node);\n const props = node.props;\n const localName = props.name;\n const scope = useFieldScope();\n const { errors, fieldIdPrefix } = useFormContext();\n const name = fieldDomName(scope ? scope.scopedName(localName) : localName, fieldIdPrefix);\n const errorKey = scope ? scope.errorKey(localName) : localName;\n const globalValue = useFormValue(localName);\n const storedValue = scope ? scope.getValue(localName) : globalValue;\n const defaultChecked = toBoolean(props.value);\n const checked = storedValue !== undefined ? toBoolean(storedValue) : defaultChecked;\n const locked = readOnly || disabled;\n const { commit } = useFieldCommit();\n\n useSeedDefault(localName, defaultChecked);\n\n if (hidden) {\n return null;\n }\n\n return (\n <FormFieldFrame\n error={errors[errorKey]}\n helperText={props.helperText ?? undefined}\n tooltip={props.tooltip ?? undefined}\n label={props.label ?? \"\"}\n name={name}\n required={required}\n >\n <input disabled={locked} name={name} type=\"hidden\" value={checked ? \"1\" : \"0\"} />\n <button\n aria-checked={checked}\n aria-label={props.label ?? localName}\n autoFocus={props.autoFocus ?? false}\n className={cn(\n \"inline-flex h-6 w-11 shrink-0 cursor-pointer items-center rounded-full border border-transparent bg-lt-muted p-0.5 shadow-lt-xs transition-colors outline-none focus-visible:border-lt-ring focus-visible:ring-[
|
|
1
|
+
{"version":3,"file":"toggle.js","names":[],"sources":["../../../../resources/js/form/components/fields/toggle.tsx"],"sourcesContent":["import type { RendererComponent } from \"@lattice-php/lattice/core/types\";\nimport { testIdentity } from \"@lattice-php/lattice/core/test-id\";\nimport { cn } from \"@lattice-php/lattice/lib/utils\";\nimport { FormFieldFrame } from \"@lattice-php/lattice/form/components/base/field\";\nimport { toBoolean } from \"@lattice-php/lattice/form/lib/conditions\";\nimport { useFormContext } from \"@lattice-php/lattice/form/hooks/context\";\nimport { fieldDomName } from \"@lattice-php/lattice/form/lib/field-dom-name\";\nimport { useFieldScope } from \"@lattice-php/lattice/form/hooks/field-scope\";\nimport { useDependentField } from \"@lattice-php/lattice/form/hooks/use-dependent-field\";\nimport { useFieldCommit } from \"@lattice-php/lattice/form/hooks/use-field-commit\";\nimport { useSeedDefault } from \"@lattice-php/lattice/form/hooks/use-seed-default\";\nimport { useFormValue } from \"@lattice-php/lattice/form/hooks/values\";\n\nexport const ToggleComponent: RendererComponent<\"field.toggle\"> = ({ node }) => {\n const { hidden, required, readOnly, disabled } = useDependentField(node);\n const props = node.props;\n const localName = props.name;\n const scope = useFieldScope();\n const { errors, fieldIdPrefix } = useFormContext();\n const name = fieldDomName(scope ? scope.scopedName(localName) : localName, fieldIdPrefix);\n const errorKey = scope ? scope.errorKey(localName) : localName;\n const globalValue = useFormValue(localName);\n const storedValue = scope ? scope.getValue(localName) : globalValue;\n const defaultChecked = toBoolean(props.value);\n const checked = storedValue !== undefined ? toBoolean(storedValue) : defaultChecked;\n const locked = readOnly || disabled;\n const { commit } = useFieldCommit();\n\n useSeedDefault(localName, defaultChecked);\n\n if (hidden) {\n return null;\n }\n\n return (\n <FormFieldFrame\n error={errors[errorKey]}\n helperText={props.helperText ?? undefined}\n tooltip={props.tooltip ?? undefined}\n label={props.label ?? \"\"}\n name={name}\n required={required}\n >\n <input disabled={locked} name={name} type=\"hidden\" value={checked ? \"1\" : \"0\"} />\n <button\n aria-checked={checked}\n aria-label={props.label ?? localName}\n autoFocus={props.autoFocus ?? false}\n className={cn(\n \"inline-flex h-6 w-11 shrink-0 cursor-pointer items-center rounded-full border border-transparent bg-lt-muted p-0.5 shadow-lt-xs transition-colors outline-none focus-visible:border-lt-ring focus-visible:ring-[length:var(--lt-ring-width)] focus-visible:ring-lt-ring/50 disabled:cursor-not-allowed disabled:bg-lt-disabled data-[state=checked]:bg-lt-primary disabled:data-[state=checked]:bg-lt-disabled\",\n )}\n data-state={checked ? \"checked\" : \"unchecked\"}\n data-test={testIdentity(localName)}\n disabled={locked}\n id={name}\n name={name}\n onClick={() => commit(localName, !checked)}\n role=\"switch\"\n tabIndex={props.tabIndex ?? undefined}\n type=\"button\"\n >\n <span\n className=\"size-5 rounded-full bg-lt-bg shadow-lt-sm transition-transform data-[state=checked]:translate-x-5 data-[state=unchecked]:translate-x-0\"\n data-state={checked ? \"checked\" : \"unchecked\"}\n />\n </button>\n </FormFieldFrame>\n );\n};\n"],"mappings":";;;;;;;;;;;;;AAaA,IAAa,mBAAsD,EAAE,WAAW;CAC9E,MAAM,EAAE,QAAQ,UAAU,UAAU,aAAa,kBAAkB,IAAI;CACvE,MAAM,QAAQ,KAAK;CACnB,MAAM,YAAY,MAAM;CACxB,MAAM,QAAQ,cAAc;CAC5B,MAAM,EAAE,QAAQ,kBAAkB,eAAe;CACjD,MAAM,OAAO,aAAa,QAAQ,MAAM,WAAW,SAAS,IAAI,WAAW,aAAa;CACxF,MAAM,WAAW,QAAQ,MAAM,SAAS,SAAS,IAAI;CACrD,MAAM,cAAc,aAAa,SAAS;CAC1C,MAAM,cAAc,QAAQ,MAAM,SAAS,SAAS,IAAI;CACxD,MAAM,iBAAiB,UAAU,MAAM,KAAK;CAC5C,MAAM,UAAU,gBAAgB,KAAA,IAAY,UAAU,WAAW,IAAI;CACrE,MAAM,SAAS,YAAY;CAC3B,MAAM,EAAE,WAAW,eAAe;CAElC,eAAe,WAAW,cAAc;CAExC,IAAI,QACF,OAAO;CAGT,OACE,qBAAC,gBAAD;EACE,OAAO,OAAO;EACd,YAAY,MAAM,cAAc,KAAA;EAChC,SAAS,MAAM,WAAW,KAAA;EAC1B,OAAO,MAAM,SAAS;EAChB;EACI;YANZ,CAQE,oBAAC,SAAD;GAAO,UAAU;GAAc;GAAM,MAAK;GAAS,OAAO,UAAU,MAAM;EAAM,CAAA,GAChF,oBAAC,UAAD;GACE,gBAAc;GACd,cAAY,MAAM,SAAS;GAC3B,WAAW,MAAM,aAAa;GAC9B,WAAW,GACT,gZACF;GACA,cAAY,UAAU,YAAY;GAClC,aAAW,aAAa,SAAS;GACjC,UAAU;GACV,IAAI;GACE;GACN,eAAe,OAAO,WAAW,CAAC,OAAO;GACzC,MAAK;GACL,UAAU,MAAM,YAAY,KAAA;GAC5B,MAAK;aAEL,oBAAC,QAAD;IACE,WAAU;IACV,cAAY,UAAU,YAAY;GACnC,CAAA;EACK,CAAA,CACM;;AAEpB"}
|
|
@@ -30,7 +30,7 @@ function FormResetListener({ componentId, reset }) {
|
|
|
30
30
|
});
|
|
31
31
|
return null;
|
|
32
32
|
}
|
|
33
|
-
function FormBody({ action, children, componentRef, nodes, shouldRenderSubmitButton, submitButtons, submitJustify, submitLabel, submitVariant, summaryLabel }) {
|
|
33
|
+
function FormBody({ action, children, componentRef, nodes, shouldRenderSubmitButton, submitButtons, submitEmphasis, submitJustify, submitLabel, submitVariant, summaryLabel }) {
|
|
34
34
|
const { nodes: resolvedNodes, markUserEdit } = useFormResolver(action, componentRef, nodes);
|
|
35
35
|
return /* @__PURE__ */ jsx(PrefillProvider, {
|
|
36
36
|
value: { markUserEdit },
|
|
@@ -41,13 +41,15 @@ function FormBody({ action, children, componentRef, nodes, shouldRenderSubmitBut
|
|
|
41
41
|
children: [children, shouldRenderSubmitButton && /* @__PURE__ */ jsx("div", {
|
|
42
42
|
className: `flex gap-3 ${JUSTIFY_CLASS[submitJustify ?? "end"]}`,
|
|
43
43
|
children: submitButtons?.length ? submitButtons.map((button, index) => button.props.buttonType === "submit" ? /* @__PURE__ */ jsx(FormSubmitButton, {
|
|
44
|
+
emphasis: button.props.emphasis ?? submitEmphasis,
|
|
44
45
|
label: button.props.label ?? submitLabel,
|
|
45
46
|
summaryLabel,
|
|
46
|
-
variant: button.props.variant ?? submitVariant
|
|
47
|
+
variant: button.props.variant ?? submitVariant
|
|
47
48
|
}, nodeKey(button, index)) : /* @__PURE__ */ jsx(RenderNode, { node: button }, nodeKey(button, index))) : /* @__PURE__ */ jsx(FormSubmitButton, {
|
|
49
|
+
emphasis: submitEmphasis,
|
|
48
50
|
label: submitLabel,
|
|
49
51
|
summaryLabel,
|
|
50
|
-
variant: submitVariant
|
|
52
|
+
variant: submitVariant
|
|
51
53
|
})
|
|
52
54
|
})]
|
|
53
55
|
})
|
|
@@ -75,6 +77,7 @@ var FormComponent = ({ children, node }) => {
|
|
|
75
77
|
const submitJustify = props.submitJustify ?? void 0;
|
|
76
78
|
const submitLabel = props.submitLabel ?? t("form.submit", "Submit");
|
|
77
79
|
const submitVariant = props.submitVariant ?? void 0;
|
|
80
|
+
const submitEmphasis = props.submitEmphasis ?? void 0;
|
|
78
81
|
const summaryLabel = props.validationSummaryLabel;
|
|
79
82
|
const validationTimeout = props.validationTimeout ?? void 0;
|
|
80
83
|
return /* @__PURE__ */ jsx(Form, {
|
|
@@ -123,6 +126,7 @@ var FormComponent = ({ children, node }) => {
|
|
|
123
126
|
nodes: node.schema,
|
|
124
127
|
shouldRenderSubmitButton,
|
|
125
128
|
submitButtons,
|
|
129
|
+
submitEmphasis,
|
|
126
130
|
submitJustify,
|
|
127
131
|
submitLabel,
|
|
128
132
|
submitVariant,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"form.js","names":[],"sources":["../../../resources/js/form/components/form.tsx"],"sourcesContent":["import { Form as InertiaForm } from \"@inertiajs/react\";\nimport { withHeaders } from \"@lattice-php/lattice/core/headers\";\nimport { LATTICE_EVENT } from \"@lattice-php/lattice/core/event-names\";\nimport { useWindowEvent } from \"@lattice-php/lattice/core/hooks/use-window-event\";\nimport { nodeKey } from \"@lattice-php/lattice/core/nodes\";\nimport { RenderNode } from \"@lattice-php/lattice/core/renderer\";\nimport type { Node, RendererComponent } from \"@lattice-php/lattice/core/types\";\nimport { useT } from \"@lattice-php/lattice/i18n\";\nimport type {
|
|
1
|
+
{"version":3,"file":"form.js","names":[],"sources":["../../../resources/js/form/components/form.tsx"],"sourcesContent":["import { Form as InertiaForm } from \"@inertiajs/react\";\nimport { withHeaders } from \"@lattice-php/lattice/core/headers\";\nimport { LATTICE_EVENT } from \"@lattice-php/lattice/core/event-names\";\nimport { useWindowEvent } from \"@lattice-php/lattice/core/hooks/use-window-event\";\nimport { nodeKey } from \"@lattice-php/lattice/core/nodes\";\nimport { RenderNode } from \"@lattice-php/lattice/core/renderer\";\nimport type { Node, RendererComponent } from \"@lattice-php/lattice/core/types\";\nimport { useT } from \"@lattice-php/lattice/i18n\";\nimport type { Emphasis, Justify, Variant } from \"@lattice-php/lattice/types/generated\";\nimport { useMemo } from \"react\";\nimport { FormSubmitButton } from \"./base/submit-button\";\nimport { FormProvider } from \"@lattice-php/lattice/form/hooks/context\";\nimport { collectFields } from \"@lattice-php/lattice/form/lib/collect-fields\";\nimport { PrefillProvider } from \"@lattice-php/lattice/form/hooks/prefill-context\";\nimport { ResolvedNodesProvider } from \"@lattice-php/lattice/form/hooks/resolved-nodes\";\nimport { useFormResolver } from \"@lattice-php/lattice/form/hooks/use-form-resolver\";\nimport { FormValuesProvider } from \"@lattice-php/lattice/form/hooks/values\";\n\nconst JUSTIFY_CLASS: Record<Justify, string> = {\n start: \"justify-start\",\n center: \"justify-center\",\n end: \"justify-end\",\n between: \"justify-between\",\n around: \"justify-around\",\n evenly: \"justify-evenly\",\n};\n\nfunction FormResetListener({\n componentId,\n reset,\n}: {\n componentId?: string;\n reset: (...fields: string[]) => void;\n}) {\n useWindowEvent(LATTICE_EVENT.resetForm, (event) => {\n const detail = (event as CustomEvent<{ form: string | null }>).detail;\n\n if (!detail?.form || detail.form === componentId) {\n reset();\n }\n });\n\n return null;\n}\n\nfunction FormBody({\n action,\n children,\n componentRef,\n nodes,\n shouldRenderSubmitButton,\n submitButtons,\n submitEmphasis,\n submitJustify,\n submitLabel,\n submitVariant,\n summaryLabel,\n}: {\n action: string;\n children: React.ReactNode;\n componentRef: string;\n nodes: Node[] | undefined;\n shouldRenderSubmitButton: boolean;\n submitButtons: Node<\"button\">[] | undefined;\n submitEmphasis: Emphasis | undefined;\n submitJustify: Justify | undefined;\n submitLabel: string;\n submitVariant: Variant | undefined;\n summaryLabel: string;\n}) {\n const { nodes: resolvedNodes, markUserEdit } = useFormResolver(action, componentRef, nodes);\n\n return (\n <PrefillProvider value={{ markUserEdit }}>\n <ResolvedNodesProvider nodes={resolvedNodes}>\n <div className=\"flex flex-col gap-6\">\n {children}\n\n {shouldRenderSubmitButton && (\n <div className={`flex gap-3 ${JUSTIFY_CLASS[submitJustify ?? \"end\"]}`}>\n {submitButtons?.length ? (\n submitButtons.map((button, index) =>\n button.props.buttonType === \"submit\" ? (\n <FormSubmitButton\n key={nodeKey(button, index)}\n emphasis={button.props.emphasis ?? submitEmphasis}\n label={button.props.label ?? submitLabel}\n summaryLabel={summaryLabel}\n variant={button.props.variant ?? submitVariant}\n />\n ) : (\n <RenderNode key={nodeKey(button, index)} node={button} />\n ),\n )\n ) : (\n <FormSubmitButton\n emphasis={submitEmphasis}\n label={submitLabel}\n summaryLabel={summaryLabel}\n variant={submitVariant}\n />\n )}\n </div>\n )}\n </div>\n </ResolvedNodesProvider>\n </PrefillProvider>\n );\n}\n\nexport const FormComponent: RendererComponent<\"form\"> = ({ children, node }) => {\n const { t } = useT(\"lattice\");\n const props = node.props;\n const action = props.action ?? \"#\";\n const errorBag = props.errorBag;\n const componentRef = props.ref ?? \"\";\n const method = props.method ?? \"post\";\n const precognitive = props.precognitive;\n const resetOnError = props.resetOnError ?? false;\n const resetOnSuccess = props.resetOnSuccess ?? [];\n const state = props.state;\n const { labels: fieldLabels, values: fieldValues } = useMemo(\n () => collectFields(node.schema),\n [node.schema],\n );\n const initialValues = useMemo(() => ({ ...fieldValues, ...state }), [fieldValues, state]);\n const shouldRenderSubmitButton = props.submitButton;\n const submitButtons = props.submitButtons ?? undefined;\n const submitJustify = props.submitJustify ?? undefined;\n const submitLabel = props.submitLabel ?? t(\"form.submit\", \"Submit\");\n const submitVariant = props.submitVariant ?? undefined;\n const submitEmphasis = props.submitEmphasis ?? undefined;\n const summaryLabel = props.validationSummaryLabel;\n const validationTimeout = props.validationTimeout ?? undefined;\n\n return (\n <InertiaForm\n action={action}\n data-slot=\"form\"\n data-lattice-component={node.id}\n errorBag={errorBag}\n method={method}\n resetOnError={resetOnError}\n resetOnSuccess={resetOnSuccess}\n validationTimeout={precognitive ? validationTimeout : undefined}\n headers={withHeaders(componentRef)}\n className=\"mx-auto flex w-full max-w-2xl flex-col gap-6\"\n >\n {({ clearErrors, errors, processing, reset, touch, validate, validating }) => (\n <FormProvider\n value={{\n action,\n clearErrors: (field) => clearErrors(field),\n componentId: node.id,\n componentRef,\n errors: errors as Record<string, string | undefined>,\n fieldLabels,\n precognitive,\n processing,\n touch: (fields) => touch(...fields),\n validate: (field) => validate(field),\n validateFields: (fields, options) => validate({ only: fields, ...options }),\n validating,\n }}\n >\n <FormResetListener componentId={node.id} reset={reset} />\n\n {props.status && (\n <div className=\"text-center text-sm font-medium text-lt-success\">{props.status}</div>\n )}\n\n <FormValuesProvider initial={initialValues}>\n <FormBody\n action={action}\n componentRef={componentRef}\n nodes={node.schema}\n shouldRenderSubmitButton={shouldRenderSubmitButton}\n submitButtons={submitButtons}\n submitEmphasis={submitEmphasis}\n submitJustify={submitJustify}\n submitLabel={submitLabel}\n submitVariant={submitVariant}\n summaryLabel={summaryLabel}\n >\n {children}\n </FormBody>\n </FormValuesProvider>\n </FormProvider>\n )}\n </InertiaForm>\n );\n};\n"],"mappings":"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"}
|
|
@@ -107,7 +107,7 @@ var WizardComponent = ({ children, node }) => {
|
|
|
107
107
|
disabled: activeIndex === 0 || processing,
|
|
108
108
|
onClick: () => goTo(activeIndex - 1),
|
|
109
109
|
type: "button",
|
|
110
|
-
|
|
110
|
+
emphasis: "outline",
|
|
111
111
|
children: t("form.wizard.back", "Back")
|
|
112
112
|
}), isLast ? /* @__PURE__ */ jsxs(Button, {
|
|
113
113
|
"data-test": "wizard-finish",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wizard.js","names":[],"sources":["../../../resources/js/form/components/wizard.tsx"],"sourcesContent":["import { createContext, useContext, useEffect, useMemo, useRef, useState } from \"react\";\nimport type { ReactNode } from \"react\";\nimport type { Node, RendererComponent } from \"@lattice-php/lattice/core/types\";\nimport type { WizardStep } from \"@lattice-php/lattice/types/generated\";\nimport { cn } from \"@lattice-php/lattice/lib/utils\";\nimport { useT } from \"@lattice-php/lattice/i18n\";\nimport { Icon } from \"@lattice-php/lattice/icons\";\nimport { Button } from \"@lattice-php/lattice/ui/button\";\nimport { Spinner } from \"@lattice-php/lattice/ui/spinner\";\nimport { useFormContext } from \"@lattice-php/lattice/form/hooks/context\";\nimport {\n firstErroredStep,\n stepFieldNames,\n stepsWithErrors,\n stepValidationPaths,\n} from \"@lattice-php/lattice/form/lib/wizard-steps\";\n\ntype WizardContextValue = { activeName: string };\n\nconst WizardContext = createContext<WizardContextValue>({ activeName: \"\" });\n\nfunction getSteps(node: Node<\"wizard\">): { items: WizardStep[]; nodes: Node[] } {\n const nodes = (node.schema ?? []).filter((child) => child.type === \"wizard-step\");\n const items = nodes.map((child) => child.props as unknown as WizardStep);\n\n return { items, nodes };\n}\n\nexport const WizardComponent: RendererComponent<\"wizard\"> = ({ children, node }) => {\n const { t } = useT(\"lattice\");\n const { errors, processing, touch, validateFields, validating } = useFormContext();\n const { items, nodes } = useMemo(() => getSteps(node), [node]);\n const stepNames = useMemo(() => nodes.map((step) => stepFieldNames(step)), [nodes]);\n const isVertical = node.props.orientation === \"vertical\";\n\n const [activeIndex, setActiveIndex] = useState(0);\n const [visited, setVisited] = useState<Set<number>>(() => new Set([0]));\n const [completed, setCompleted] = useState<Set<number>>(() => new Set());\n const erroredSteps = useMemo(() => stepsWithErrors(stepNames, errors), [stepNames, errors]);\n const isLast = activeIndex === items.length - 1;\n\n const goTo = (index: number): void => {\n setActiveIndex(index);\n setVisited((previous) => new Set(previous).add(index));\n };\n\n const advance = (): void => {\n setCompleted((previous) => new Set(previous).add(activeIndex));\n\n if (!isLast) {\n goTo(activeIndex + 1);\n }\n };\n\n const onNext = (): void => {\n const step = nodes[activeIndex];\n const paths = step ? stepValidationPaths(step) : [];\n\n if (paths.length === 0) {\n advance();\n\n return;\n }\n\n touch(paths);\n validateFields(paths, { onSuccess: advance });\n };\n\n const wasProcessing = useRef(false);\n useEffect(() => {\n if (wasProcessing.current && !processing) {\n const target = firstErroredStep(stepNames, errors);\n\n if (target !== null && target !== activeIndex) {\n goTo(target);\n }\n }\n\n wasProcessing.current = processing;\n }, [processing, errors, stepNames, activeIndex]);\n\n const contextValue = useMemo(\n () => ({ activeName: items[activeIndex]?.name ?? \"\" }),\n [items, activeIndex],\n );\n\n return (\n <WizardContext.Provider value={contextValue}>\n <div className={cn(\"gap-6\", isVertical ? \"flex\" : \"grid\")} data-slot=\"wizard\">\n <ol\n aria-label={t(\"form.wizard.steps\", \"Steps\")}\n className={cn(\"gap-1\", isVertical ? \"flex w-56 shrink-0 flex-col\" : \"flex flex-wrap\")}\n >\n {items.map((step, index) => {\n const isActive = index === activeIndex;\n const isDone = completed.has(index);\n const hasError = erroredSteps.has(index);\n\n return (\n <li key={step.name}>\n <button\n aria-current={isActive ? \"step\" : undefined}\n className={cn(\n \"flex w-full items-center gap-2 rounded-lt px-3 py-2 text-left text-sm\",\n isActive ? \"bg-lt-muted font-medium text-lt-fg\" : \"text-lt-muted-fg\",\n !visited.has(index) && \"cursor-not-allowed opacity-60\",\n )}\n data-error={hasError || undefined}\n data-test={`wizard-rail-${step.name}`}\n disabled={!visited.has(index)}\n id={`wizard-step-${step.name}-trigger`}\n onClick={() => goTo(index)}\n type=\"button\"\n >\n <span\n className={cn(\n \"flex size-5 shrink-0 items-center justify-center rounded-full border text-xs\",\n hasError\n ? \"border-lt-danger text-lt-danger\"\n : isDone\n ? \"border-lt-primary bg-lt-primary text-lt-primary-fg\"\n : \"border-lt-border\",\n )}\n >\n {isDone && !hasError ? (\n <Icon className=\"size-lt-icon-sm\" name=\"check\" />\n ) : (\n index + 1\n )}\n </span>\n <span className=\"min-w-0\">\n <span className=\"block truncate\">{step.label}</span>\n {isVertical && step.description && (\n <span className=\"block truncate text-xs text-lt-muted-fg\">\n {step.description}\n </span>\n )}\n </span>\n </button>\n </li>\n );\n })}\n </ol>\n\n <div className=\"min-w-0 flex-1 space-y-6\">\n {children}\n\n <div className=\"flex items-center justify-between gap-3\">\n <Button\n data-test=\"wizard-back\"\n disabled={activeIndex === 0 || processing}\n onClick={() => goTo(activeIndex - 1)}\n type=\"button\"\n variant=\"outline\"\n >\n {t(\"form.wizard.back\", \"Back\")}\n </Button>\n\n {isLast ? (\n <Button data-test=\"wizard-finish\" disabled={processing} type=\"submit\">\n {processing && <Spinner />}\n {t(\"form.wizard.finish\", \"Finish\")}\n </Button>\n ) : (\n <Button\n data-test=\"wizard-next\"\n disabled={processing || validating}\n onClick={onNext}\n type=\"button\"\n >\n {validating && <Spinner />}\n {t(\"form.wizard.next\", \"Next\")}\n </Button>\n )}\n </div>\n </div>\n </div>\n </WizardContext.Provider>\n );\n};\n\nexport const WizardStepComponent: RendererComponent<\"wizard-step\"> = ({ children, node }) => {\n const { activeName } = useContext(WizardContext);\n const name = node.props.name;\n const isActive = activeName === name;\n const [hasOpened, setHasOpened] = useState(isActive);\n\n useEffect(() => {\n if (isActive) {\n setHasOpened(true);\n }\n }, [isActive]);\n\n return (\n <section\n aria-labelledby={`wizard-step-${name}-trigger`}\n className={cn(\"space-y-8\", !isActive && \"hidden\")}\n hidden={!isActive}\n id={`wizard-step-${name}-panel`}\n >\n {hasOpened ? (children as ReactNode) : null}\n </section>\n );\n};\n"],"mappings":";;;;;;;;;;AAmBA,IAAM,gBAAgB,cAAkC,EAAE,YAAY,GAAG,CAAC;AAE1E,SAAS,SAAS,MAA8D;CAC9E,MAAM,SAAS,KAAK,UAAU,CAAC,GAAG,QAAQ,UAAU,MAAM,SAAS,aAAa;CAGhF,OAAO;EAAE,OAFK,MAAM,KAAK,UAAU,MAAM,KAEhC;EAAO;CAAM;AACxB;AAEA,IAAa,mBAAgD,EAAE,UAAU,WAAW;CAClF,MAAM,EAAE,MAAM,KAAK,SAAS;CAC5B,MAAM,EAAE,QAAQ,YAAY,OAAO,gBAAgB,eAAe,eAAe;CACjF,MAAM,EAAE,OAAO,UAAU,cAAc,SAAS,IAAI,GAAG,CAAC,IAAI,CAAC;CAC7D,MAAM,YAAY,cAAc,MAAM,KAAK,SAAS,eAAe,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC;CAClF,MAAM,aAAa,KAAK,MAAM,gBAAgB;CAE9C,MAAM,CAAC,aAAa,kBAAkB,SAAS,CAAC;CAChD,MAAM,CAAC,SAAS,cAAc,eAA4B,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC;CACtE,MAAM,CAAC,WAAW,gBAAgB,+BAA4B,IAAI,IAAI,CAAC;CACvE,MAAM,eAAe,cAAc,gBAAgB,WAAW,MAAM,GAAG,CAAC,WAAW,MAAM,CAAC;CAC1F,MAAM,SAAS,gBAAgB,MAAM,SAAS;CAE9C,MAAM,QAAQ,UAAwB;EACpC,eAAe,KAAK;EACpB,YAAY,aAAa,IAAI,IAAI,QAAQ,EAAE,IAAI,KAAK,CAAC;CACvD;CAEA,MAAM,gBAAsB;EAC1B,cAAc,aAAa,IAAI,IAAI,QAAQ,EAAE,IAAI,WAAW,CAAC;EAE7D,IAAI,CAAC,QACH,KAAK,cAAc,CAAC;CAExB;CAEA,MAAM,eAAqB;EACzB,MAAM,OAAO,MAAM;EACnB,MAAM,QAAQ,OAAO,oBAAoB,IAAI,IAAI,CAAC;EAElD,IAAI,MAAM,WAAW,GAAG;GACtB,QAAQ;GAER;EACF;EAEA,MAAM,KAAK;EACX,eAAe,OAAO,EAAE,WAAW,QAAQ,CAAC;CAC9C;CAEA,MAAM,gBAAgB,OAAO,KAAK;CAClC,gBAAgB;EACd,IAAI,cAAc,WAAW,CAAC,YAAY;GACxC,MAAM,SAAS,iBAAiB,WAAW,MAAM;GAEjD,IAAI,WAAW,QAAQ,WAAW,aAChC,KAAK,MAAM;EAEf;EAEA,cAAc,UAAU;CAC1B,GAAG;EAAC;EAAY;EAAQ;EAAW;CAAW,CAAC;CAE/C,MAAM,eAAe,eACZ,EAAE,YAAY,MAAM,cAAc,QAAQ,GAAG,IACpD,CAAC,OAAO,WAAW,CACrB;CAEA,OACE,oBAAC,cAAc,UAAf;EAAwB,OAAO;YAC7B,qBAAC,OAAD;GAAK,WAAW,GAAG,SAAS,aAAa,SAAS,MAAM;GAAG,aAAU;aAArE,CACE,oBAAC,MAAD;IACE,cAAY,EAAE,qBAAqB,OAAO;IAC1C,WAAW,GAAG,SAAS,aAAa,gCAAgC,gBAAgB;cAEnF,MAAM,KAAK,MAAM,UAAU;KAC1B,MAAM,WAAW,UAAU;KAC3B,MAAM,SAAS,UAAU,IAAI,KAAK;KAClC,MAAM,WAAW,aAAa,IAAI,KAAK;KAEvC,OACE,oBAAC,MAAD,EAAA,UACE,qBAAC,UAAD;MACE,gBAAc,WAAW,SAAS,KAAA;MAClC,WAAW,GACT,yEACA,WAAW,uCAAuC,oBAClD,CAAC,QAAQ,IAAI,KAAK,KAAK,+BACzB;MACA,cAAY,YAAY,KAAA;MACxB,aAAW,eAAe,KAAK;MAC/B,UAAU,CAAC,QAAQ,IAAI,KAAK;MAC5B,IAAI,eAAe,KAAK,KAAK;MAC7B,eAAe,KAAK,KAAK;MACzB,MAAK;gBAZP,CAcE,oBAAC,QAAD;OACE,WAAW,GACT,gFACA,WACI,oCACA,SACE,uDACA,kBACR;iBAEC,UAAU,CAAC,WACV,oBAAC,MAAD;QAAM,WAAU;QAAkB,MAAK;OAAS,CAAA,IAEhD,QAAQ;MAEN,CAAA,GACN,qBAAC,QAAD;OAAM,WAAU;iBAAhB,CACE,oBAAC,QAAD;QAAM,WAAU;kBAAkB,KAAK;OAAY,CAAA,GAClD,cAAc,KAAK,eAClB,oBAAC,QAAD;QAAM,WAAU;kBACb,KAAK;OACF,CAAA,CAEJ;QACA;QACN,GAxCK,KAAK,IAwCV;IAER,CAAC;GACC,CAAA,GAEJ,qBAAC,OAAD;IAAK,WAAU;cAAf,CACG,UAED,qBAAC,OAAD;KAAK,WAAU;eAAf,CACE,oBAAC,QAAD;MACE,aAAU;MACV,UAAU,gBAAgB,KAAK;MAC/B,eAAe,KAAK,cAAc,CAAC;MACnC,MAAK;MACL,SAAQ;gBAEP,EAAE,oBAAoB,MAAM;KACvB,CAAA,GAEP,SACC,qBAAC,QAAD;MAAQ,aAAU;MAAgB,UAAU;MAAY,MAAK;gBAA7D,CACG,cAAc,oBAAC,SAAD,CAAU,CAAA,GACxB,EAAE,sBAAsB,QAAQ,CAC3B;UAER,qBAAC,QAAD;MACE,aAAU;MACV,UAAU,cAAc;MACxB,SAAS;MACT,MAAK;gBAJP,CAMG,cAAc,oBAAC,SAAD,CAAU,CAAA,GACxB,EAAE,oBAAoB,MAAM,CACvB;OAEP;MACF;KACF;;CACiB,CAAA;AAE5B;AAEA,IAAa,uBAAyD,EAAE,UAAU,WAAW;CAC3F,MAAM,EAAE,eAAe,WAAW,aAAa;CAC/C,MAAM,OAAO,KAAK,MAAM;CACxB,MAAM,WAAW,eAAe;CAChC,MAAM,CAAC,WAAW,gBAAgB,SAAS,QAAQ;CAEnD,gBAAgB;EACd,IAAI,UACF,aAAa,IAAI;CAErB,GAAG,CAAC,QAAQ,CAAC;CAEb,OACE,oBAAC,WAAD;EACE,mBAAiB,eAAe,KAAK;EACrC,WAAW,GAAG,aAAa,CAAC,YAAY,QAAQ;EAChD,QAAQ,CAAC;EACT,IAAI,eAAe,KAAK;YAEvB,YAAa,WAAyB;CAChC,CAAA;AAEb"}
|
|
1
|
+
{"version":3,"file":"wizard.js","names":[],"sources":["../../../resources/js/form/components/wizard.tsx"],"sourcesContent":["import { createContext, useContext, useEffect, useMemo, useRef, useState } from \"react\";\nimport type { ReactNode } from \"react\";\nimport type { Node, RendererComponent } from \"@lattice-php/lattice/core/types\";\nimport type { WizardStep } from \"@lattice-php/lattice/types/generated\";\nimport { cn } from \"@lattice-php/lattice/lib/utils\";\nimport { useT } from \"@lattice-php/lattice/i18n\";\nimport { Icon } from \"@lattice-php/lattice/icons\";\nimport { Button } from \"@lattice-php/lattice/ui/button\";\nimport { Spinner } from \"@lattice-php/lattice/ui/spinner\";\nimport { useFormContext } from \"@lattice-php/lattice/form/hooks/context\";\nimport {\n firstErroredStep,\n stepFieldNames,\n stepsWithErrors,\n stepValidationPaths,\n} from \"@lattice-php/lattice/form/lib/wizard-steps\";\n\ntype WizardContextValue = { activeName: string };\n\nconst WizardContext = createContext<WizardContextValue>({ activeName: \"\" });\n\nfunction getSteps(node: Node<\"wizard\">): { items: WizardStep[]; nodes: Node[] } {\n const nodes = (node.schema ?? []).filter((child) => child.type === \"wizard-step\");\n const items = nodes.map((child) => child.props as unknown as WizardStep);\n\n return { items, nodes };\n}\n\nexport const WizardComponent: RendererComponent<\"wizard\"> = ({ children, node }) => {\n const { t } = useT(\"lattice\");\n const { errors, processing, touch, validateFields, validating } = useFormContext();\n const { items, nodes } = useMemo(() => getSteps(node), [node]);\n const stepNames = useMemo(() => nodes.map((step) => stepFieldNames(step)), [nodes]);\n const isVertical = node.props.orientation === \"vertical\";\n\n const [activeIndex, setActiveIndex] = useState(0);\n const [visited, setVisited] = useState<Set<number>>(() => new Set([0]));\n const [completed, setCompleted] = useState<Set<number>>(() => new Set());\n const erroredSteps = useMemo(() => stepsWithErrors(stepNames, errors), [stepNames, errors]);\n const isLast = activeIndex === items.length - 1;\n\n const goTo = (index: number): void => {\n setActiveIndex(index);\n setVisited((previous) => new Set(previous).add(index));\n };\n\n const advance = (): void => {\n setCompleted((previous) => new Set(previous).add(activeIndex));\n\n if (!isLast) {\n goTo(activeIndex + 1);\n }\n };\n\n const onNext = (): void => {\n const step = nodes[activeIndex];\n const paths = step ? stepValidationPaths(step) : [];\n\n if (paths.length === 0) {\n advance();\n\n return;\n }\n\n touch(paths);\n validateFields(paths, { onSuccess: advance });\n };\n\n const wasProcessing = useRef(false);\n useEffect(() => {\n if (wasProcessing.current && !processing) {\n const target = firstErroredStep(stepNames, errors);\n\n if (target !== null && target !== activeIndex) {\n goTo(target);\n }\n }\n\n wasProcessing.current = processing;\n }, [processing, errors, stepNames, activeIndex]);\n\n const contextValue = useMemo(\n () => ({ activeName: items[activeIndex]?.name ?? \"\" }),\n [items, activeIndex],\n );\n\n return (\n <WizardContext.Provider value={contextValue}>\n <div className={cn(\"gap-6\", isVertical ? \"flex\" : \"grid\")} data-slot=\"wizard\">\n <ol\n aria-label={t(\"form.wizard.steps\", \"Steps\")}\n className={cn(\"gap-1\", isVertical ? \"flex w-56 shrink-0 flex-col\" : \"flex flex-wrap\")}\n >\n {items.map((step, index) => {\n const isActive = index === activeIndex;\n const isDone = completed.has(index);\n const hasError = erroredSteps.has(index);\n\n return (\n <li key={step.name}>\n <button\n aria-current={isActive ? \"step\" : undefined}\n className={cn(\n \"flex w-full items-center gap-2 rounded-lt px-3 py-2 text-left text-sm\",\n isActive ? \"bg-lt-muted font-medium text-lt-fg\" : \"text-lt-muted-fg\",\n !visited.has(index) && \"cursor-not-allowed opacity-60\",\n )}\n data-error={hasError || undefined}\n data-test={`wizard-rail-${step.name}`}\n disabled={!visited.has(index)}\n id={`wizard-step-${step.name}-trigger`}\n onClick={() => goTo(index)}\n type=\"button\"\n >\n <span\n className={cn(\n \"flex size-5 shrink-0 items-center justify-center rounded-full border text-xs\",\n hasError\n ? \"border-lt-danger text-lt-danger\"\n : isDone\n ? \"border-lt-primary bg-lt-primary text-lt-primary-fg\"\n : \"border-lt-border\",\n )}\n >\n {isDone && !hasError ? (\n <Icon className=\"size-lt-icon-sm\" name=\"check\" />\n ) : (\n index + 1\n )}\n </span>\n <span className=\"min-w-0\">\n <span className=\"block truncate\">{step.label}</span>\n {isVertical && step.description && (\n <span className=\"block truncate text-xs text-lt-muted-fg\">\n {step.description}\n </span>\n )}\n </span>\n </button>\n </li>\n );\n })}\n </ol>\n\n <div className=\"min-w-0 flex-1 space-y-6\">\n {children}\n\n <div className=\"flex items-center justify-between gap-3\">\n <Button\n data-test=\"wizard-back\"\n disabled={activeIndex === 0 || processing}\n onClick={() => goTo(activeIndex - 1)}\n type=\"button\"\n emphasis=\"outline\"\n >\n {t(\"form.wizard.back\", \"Back\")}\n </Button>\n\n {isLast ? (\n <Button data-test=\"wizard-finish\" disabled={processing} type=\"submit\">\n {processing && <Spinner />}\n {t(\"form.wizard.finish\", \"Finish\")}\n </Button>\n ) : (\n <Button\n data-test=\"wizard-next\"\n disabled={processing || validating}\n onClick={onNext}\n type=\"button\"\n >\n {validating && <Spinner />}\n {t(\"form.wizard.next\", \"Next\")}\n </Button>\n )}\n </div>\n </div>\n </div>\n </WizardContext.Provider>\n );\n};\n\nexport const WizardStepComponent: RendererComponent<\"wizard-step\"> = ({ children, node }) => {\n const { activeName } = useContext(WizardContext);\n const name = node.props.name;\n const isActive = activeName === name;\n const [hasOpened, setHasOpened] = useState(isActive);\n\n useEffect(() => {\n if (isActive) {\n setHasOpened(true);\n }\n }, [isActive]);\n\n return (\n <section\n aria-labelledby={`wizard-step-${name}-trigger`}\n className={cn(\"space-y-8\", !isActive && \"hidden\")}\n hidden={!isActive}\n id={`wizard-step-${name}-panel`}\n >\n {hasOpened ? (children as ReactNode) : null}\n </section>\n );\n};\n"],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ export { getActionEffects, isActionEffect, dispatchEffects, dispatchActionError,
|
|
|
5
5
|
export { useEffectDispatcher } from './effects/use-effect-dispatcher.js';
|
|
6
6
|
export { builtinEffectHandlers, effectHandler, mergeEffectHandlers } from './effects/registry.js';
|
|
7
7
|
export { registerRichEditorExtension } from './form/rich-editor/registry.js';
|
|
8
|
-
export {
|
|
8
|
+
export { initializeAppearance, updateAppearance, useAppearance } from './appearance/index.js';
|
|
9
9
|
export { copyToClipboard } from './clipboard/index.js';
|
|
10
10
|
export { createLatticeApp, type CreateLatticeAppI18nOptions, type CreateLatticeAppOptions, } from './create-app.js';
|
|
11
11
|
export { EventBridge } from './event-bridge.js';
|
|
@@ -22,7 +22,7 @@ export { Renderer } from './core/renderer.js';
|
|
|
22
22
|
export { LATTICE_REF_HEADER, withRefHeader } from './core/component-ref.js';
|
|
23
23
|
export { withHeaders } from './core/headers.js';
|
|
24
24
|
export { LATTICE_EVENT } from './core/event-names.js';
|
|
25
|
-
export type {
|
|
25
|
+
export type { Emphasis } from './ui/button.js';
|
|
26
26
|
export type { ReloadComponentEvent } from './core/event-names.js';
|
|
27
27
|
export type { ComponentProps, KnownPageContainer, LayoutPayload, Node, NodeProps, NodeType, PageContainer, PageBreadcrumb, PagePayload, ComponentPropsOf, RendererComponent, RendererComponentModule, RendererComponentProps, Schema, UnknownComponent, } from './core/types.js';
|
|
28
28
|
export { RealtimeListeners } from './realtime/listeners.js';
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { initializeAppearance, updateAppearance, useAppearance } from "./appearance/index.js";
|
|
2
2
|
import { createPlugin, createRegistry, eagerComponent, extendRegistry, lazyComponent } from "./core/registry.js";
|
|
3
3
|
import { useColumnRegistry, useComponentRegistry } from "./core/registry-context.js";
|
|
4
4
|
import { LATTICE_EVENT } from "./core/event-names.js";
|
|
@@ -29,4 +29,4 @@ import { registry } from "./registry.js";
|
|
|
29
29
|
import { createLatticeApp } from "./create-app.js";
|
|
30
30
|
import { registerRichEditorExtension } from "./form/rich-editor/registry.js";
|
|
31
31
|
import { Provider } from "./provider.js";
|
|
32
|
-
export { Callouts, EventBridge, Icon, IconRenderer, IconRendererProvider, LATTICE_EVENT, LATTICE_REF_HEADER, OutletContext, Provider, RealtimeListeners, Renderer, SchemaLayout, CollapsedContext as SidebarCollapsedContext, SpriteProvider, Toaster, builtinEffectHandlers, chatComponents, columnCell, copyToClipboard, createLatticeApp, createLayoutResolver, createPageResolver, createPlugin, createRegistry, dispatchActionError, dispatchEffects, eagerComponent, effectHandler, extendRegistry, getActionEffects,
|
|
32
|
+
export { Callouts, EventBridge, Icon, IconRenderer, IconRendererProvider, LATTICE_EVENT, LATTICE_REF_HEADER, OutletContext, Provider, RealtimeListeners, Renderer, SchemaLayout, CollapsedContext as SidebarCollapsedContext, SpriteProvider, Toaster, builtinEffectHandlers, chatComponents, columnCell, copyToClipboard, createLatticeApp, createLayoutResolver, createPageResolver, createPlugin, createRegistry, dispatchActionError, dispatchEffects, eagerComponent, effectHandler, extendRegistry, getActionEffects, initializeAppearance, isActionEffect, layoutComponents, lazyComponent, mergeEffectHandlers, onCallout, onToast, pageComponentName, registerRichEditorExtension, registry, updateAppearance, useAppearance, useChat, useColumnRegistry, useComponentRegistry, useEffectDispatcher, useCollapsed as useSidebarCollapsed, withHeaders, withRefHeader, withVisitHeaders };
|