@lattice-php/lattice 0.36.1 → 0.38.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/form/components/base/field.d.ts +14 -4
- package/dist/form/components/base/field.js +33 -10
- package/dist/form/components/base/field.js.map +1 -1
- package/dist/form/components/fields/builder.js +4 -2
- package/dist/form/components/fields/builder.js.map +1 -1
- package/dist/form/components/fields/choice.js +6 -5
- package/dist/form/components/fields/choice.js.map +1 -1
- package/dist/form/components/fields/color-picker-field.js +2 -2
- package/dist/form/components/fields/color-picker-field.js.map +1 -1
- package/dist/form/components/fields/date-input.js +2 -1
- package/dist/form/components/fields/date-input.js.map +1 -1
- package/dist/form/components/fields/date-picker-field.d.ts +3 -1
- package/dist/form/components/fields/date-picker-field.js +2 -2
- package/dist/form/components/fields/date-picker-field.js.map +1 -1
- package/dist/form/components/fields/date-time-input.js +2 -1
- package/dist/form/components/fields/date-time-input.js.map +1 -1
- package/dist/form/components/fields/file-upload.js +4 -4
- package/dist/form/components/fields/file-upload.js.map +1 -1
- package/dist/form/components/fields/number-input.js +3 -3
- package/dist/form/components/fields/number-input.js.map +1 -1
- package/dist/form/components/fields/otp-input.js +2 -2
- package/dist/form/components/fields/otp-input.js.map +1 -1
- package/dist/form/components/fields/password-input.js +6 -6
- package/dist/form/components/fields/password-input.js.map +1 -1
- package/dist/form/components/fields/repeater.js +4 -2
- package/dist/form/components/fields/repeater.js.map +1 -1
- package/dist/form/components/fields/rich-editor-field.js +7 -5
- package/dist/form/components/fields/rich-editor-field.js.map +1 -1
- package/dist/form/components/fields/select.js +5 -5
- package/dist/form/components/fields/select.js.map +1 -1
- package/dist/form/components/fields/simple-field.d.ts +2 -1
- package/dist/form/components/fields/simple-field.js +2 -2
- package/dist/form/components/fields/simple-field.js.map +1 -1
- package/dist/form/components/fields/text-input.js +2 -2
- package/dist/form/components/fields/text-input.js.map +1 -1
- package/dist/form/components/fields/textarea.js +2 -2
- package/dist/form/components/fields/textarea.js.map +1 -1
- package/dist/form/components/fields/time-input.js +2 -2
- package/dist/form/components/fields/time-input.js.map +1 -1
- package/dist/form/components/fields/toggle.js +6 -6
- package/dist/form/components/fields/toggle.js.map +1 -1
- package/dist/form/index.d.ts +1 -0
- package/dist/form/index.js +2 -1
- package/dist/form/toolkit.d.ts +1 -1
- package/dist/table/components/column-visibility-menu.js +1 -1
- package/dist/table/components/filter-controls.js +1 -1
- package/dist/table/components/filter-value-input.js +1 -1
- package/dist/table/components/table-search.js +1 -1
- package/dist/types/generated.d.ts +12 -2
- package/dist/ui/code-block-view.d.ts +3 -0
- package/dist/ui/code-block-view.js +135 -0
- package/dist/ui/code-block-view.js.map +1 -0
- package/dist/ui/code-block.d.ts +25 -0
- package/dist/ui/code-block.js +54 -0
- package/dist/ui/code-block.js.map +1 -0
- package/dist/ui/copyable-text.d.ts +3 -1
- package/dist/ui/copyable-text.js +19 -13
- package/dist/ui/copyable-text.js.map +1 -1
- package/dist/ui/index.d.ts +3 -0
- package/dist/ui/index.js +3 -1
- package/dist/ui/plugin.js +2 -0
- package/dist/ui/plugin.js.map +1 -1
- package/dist/ui/segmented-pills.d.ts +2 -1
- package/dist/ui/segmented-pills.js +3 -2
- package/dist/ui/segmented-pills.js.map +1 -1
- package/dist/vite.js.map +1 -1
- package/dist-standalone/chunks/{chart-view-CR1X2aGE.js → chart-view-CFV7BU_D.js} +17 -17
- package/dist-standalone/chunks/code-block-view-fzD5e55N.js +34 -0
- package/dist-standalone/chunks/date-picker-field-DepKtR_m.js +1 -0
- package/dist-standalone/chunks/dist-BtOmkEqQ.js +1 -0
- package/dist-standalone/chunks/jsx-runtime-0vZSBttN.js +1 -0
- package/dist-standalone/chunks/{jsx-runtime-CN5ucv1d.js → react-dom-DJCfT20h.js} +1 -1
- package/dist-standalone/chunks/rich-editor-field-BZQIPOLc.js +158 -0
- package/dist-standalone/chunks/{subscriptions-BV4g0s0U.js → subscriptions-4IpkpPX3.js} +1 -1
- package/dist-standalone/chunks/{time-picker-kbhOHEPd.js → time-picker-DUjYyeeP.js} +1 -1
- package/dist-standalone/chunks/use-dependent-field-DvH7mUyx.js +41 -0
- package/dist-standalone/chunks/use-effect-dispatcher-BMWOfaFE.js +97 -0
- package/dist-standalone/chunks/w3c-keyname-BOAvb0qz.js +1 -0
- package/dist-standalone/lattice.css +1 -1
- package/dist-standalone/lattice.js +5 -4
- package/dist-standalone/manifest.json +1 -1
- package/package.json +9 -1
- package/dist-standalone/chunks/date-picker-field-B4Xzow-A.js +0 -1
- package/dist-standalone/chunks/dist-ci5ng714.js +0 -1
- package/dist-standalone/chunks/icon-button-D3AltHNz.js +0 -41
- package/dist-standalone/chunks/rich-editor-field-JM3jBEV1.js +0 -158
- package/dist-standalone/chunks/use-effect-dispatcher-CJXFkAv1.js +0 -97
|
@@ -1,11 +1,21 @@
|
|
|
1
1
|
import { LabelAction } from '../../types.js';
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
import { ComponentProps, ReactNode } from 'react';
|
|
3
|
+
export type FormFieldControlProps = {
|
|
4
|
+
id: string;
|
|
5
|
+
"aria-describedby"?: string;
|
|
6
|
+
"aria-invalid"?: boolean;
|
|
7
|
+
"aria-labelledby"?: string;
|
|
8
|
+
"aria-required"?: boolean;
|
|
9
|
+
};
|
|
10
|
+
type FormFieldFrameProps = Omit<ComponentProps<"div">, "children" | "id"> & {
|
|
11
|
+
children: (controlProps: FormFieldControlProps) => ReactNode;
|
|
4
12
|
error?: string;
|
|
5
13
|
helperText?: string;
|
|
14
|
+
id: string;
|
|
6
15
|
label: string;
|
|
7
16
|
labelAction?: LabelAction;
|
|
8
|
-
name: string;
|
|
9
17
|
required?: boolean;
|
|
10
18
|
tooltip?: string;
|
|
11
|
-
}
|
|
19
|
+
};
|
|
20
|
+
export declare function FormFieldFrame({ children, className, error, helperText, id, label, labelAction, required, tooltip, ...props }: FormFieldFrameProps): ReactNode;
|
|
21
|
+
export {};
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { cn } from "../../../lib/utils.js";
|
|
1
2
|
import { useInTableCell } from "../../hooks/row-layout-context.js";
|
|
2
3
|
import { InfoTooltip } from "../../../ui/info-tooltip.js";
|
|
3
4
|
import { TextLink } from "../../../ui/link.js";
|
|
@@ -5,27 +6,45 @@ import InputError from "../../../ui/input-error.js";
|
|
|
5
6
|
import { Label } from "../../../ui/label.js";
|
|
6
7
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
7
8
|
//#region resources/js/form/components/base/field.tsx
|
|
8
|
-
function FormFieldFrame({ children, error, helperText, label, labelAction,
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
function FormFieldFrame({ children, className, error, helperText, id, label, labelAction, required, tooltip, ...props }) {
|
|
10
|
+
const bare = useInTableCell();
|
|
11
|
+
const labelId = `${id}-label`;
|
|
12
|
+
const helperTextId = !bare && helperText ? `${id}-helper` : void 0;
|
|
13
|
+
const errorId = error ? `${id}-error` : void 0;
|
|
14
|
+
const control = children({
|
|
15
|
+
id,
|
|
16
|
+
"aria-describedby": [helperTextId, errorId].filter(Boolean).join(" ") || void 0,
|
|
17
|
+
"aria-invalid": error ? true : void 0,
|
|
18
|
+
"aria-labelledby": label ? labelId : void 0,
|
|
19
|
+
"aria-required": required || void 0
|
|
20
|
+
});
|
|
21
|
+
if (bare) return /* @__PURE__ */ jsxs("div", {
|
|
22
|
+
...props,
|
|
23
|
+
className: cn("grid gap-1", className),
|
|
11
24
|
children: [
|
|
12
25
|
/* @__PURE__ */ jsx(Label, {
|
|
13
|
-
|
|
26
|
+
id: labelId,
|
|
27
|
+
htmlFor: id,
|
|
14
28
|
className: "sr-only",
|
|
15
29
|
children: label
|
|
16
30
|
}),
|
|
17
|
-
|
|
18
|
-
/* @__PURE__ */ jsx(InputError, {
|
|
31
|
+
control,
|
|
32
|
+
/* @__PURE__ */ jsx(InputError, {
|
|
33
|
+
id: errorId,
|
|
34
|
+
message: error
|
|
35
|
+
})
|
|
19
36
|
]
|
|
20
37
|
});
|
|
21
38
|
return /* @__PURE__ */ jsxs("div", {
|
|
22
|
-
|
|
39
|
+
...props,
|
|
40
|
+
className: cn("grid gap-2", className),
|
|
23
41
|
children: [
|
|
24
42
|
/* @__PURE__ */ jsxs("div", {
|
|
25
43
|
className: "flex min-h-5 items-center",
|
|
26
44
|
children: [
|
|
27
45
|
/* @__PURE__ */ jsx(Label, {
|
|
28
|
-
|
|
46
|
+
id: labelId,
|
|
47
|
+
htmlFor: id,
|
|
29
48
|
children: label
|
|
30
49
|
}),
|
|
31
50
|
required && /* @__PURE__ */ jsx("span", {
|
|
@@ -42,12 +61,16 @@ function FormFieldFrame({ children, error, helperText, label, labelAction, name,
|
|
|
42
61
|
})
|
|
43
62
|
]
|
|
44
63
|
}),
|
|
45
|
-
|
|
64
|
+
control,
|
|
46
65
|
helperText && /* @__PURE__ */ jsx("p", {
|
|
66
|
+
id: helperTextId,
|
|
47
67
|
className: "text-sm text-lt-muted-fg",
|
|
48
68
|
children: helperText
|
|
49
69
|
}),
|
|
50
|
-
/* @__PURE__ */ jsx(InputError, {
|
|
70
|
+
/* @__PURE__ */ jsx(InputError, {
|
|
71
|
+
id: errorId,
|
|
72
|
+
message: error
|
|
73
|
+
})
|
|
51
74
|
]
|
|
52
75
|
});
|
|
53
76
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"field.js","names":[],"sources":["../../../../resources/js/form/components/base/field.tsx"],"sourcesContent":["import InputError from \"@lattice-php/lattice/ui/input-error\";\nimport { InfoTooltip } from \"@lattice-php/lattice/ui/info-tooltip\";\nimport { TextLink } from \"@lattice-php/lattice/ui/link\";\nimport { Label } from \"@lattice-php/lattice/ui/label\";\nimport { useInTableCell } from \"@lattice-php/lattice/form/hooks/row-layout-context\";\nimport type { LabelAction } from \"@lattice-php/lattice/form/types\";\n\nexport
|
|
1
|
+
{"version":3,"file":"field.js","names":[],"sources":["../../../../resources/js/form/components/base/field.tsx"],"sourcesContent":["import InputError from \"@lattice-php/lattice/ui/input-error\";\nimport { InfoTooltip } from \"@lattice-php/lattice/ui/info-tooltip\";\nimport { TextLink } from \"@lattice-php/lattice/ui/link\";\nimport { Label } from \"@lattice-php/lattice/ui/label\";\nimport { useInTableCell } from \"@lattice-php/lattice/form/hooks/row-layout-context\";\nimport { cn } from \"@lattice-php/lattice/lib/utils\";\nimport type { LabelAction } from \"@lattice-php/lattice/form/types\";\nimport type { ComponentProps, ReactNode } from \"react\";\n\nexport type FormFieldControlProps = {\n id: string;\n \"aria-describedby\"?: string;\n \"aria-invalid\"?: boolean;\n \"aria-labelledby\"?: string;\n \"aria-required\"?: boolean;\n};\n\ntype FormFieldFrameProps = Omit<ComponentProps<\"div\">, \"children\" | \"id\"> & {\n children: (controlProps: FormFieldControlProps) => ReactNode;\n error?: string;\n helperText?: string;\n id: string;\n label: string;\n labelAction?: LabelAction;\n required?: boolean;\n tooltip?: string;\n};\n\nexport function FormFieldFrame({\n children,\n className,\n error,\n helperText,\n id,\n label,\n labelAction,\n required,\n tooltip,\n ...props\n}: FormFieldFrameProps): ReactNode {\n const bare = useInTableCell();\n const labelId = `${id}-label`;\n const helperTextId = !bare && helperText ? `${id}-helper` : undefined;\n const errorId = error ? `${id}-error` : undefined;\n const describedBy = [helperTextId, errorId].filter(Boolean).join(\" \") || undefined;\n const control = children({\n id,\n \"aria-describedby\": describedBy,\n \"aria-invalid\": error ? true : undefined,\n \"aria-labelledby\": label ? labelId : undefined,\n \"aria-required\": required || undefined,\n });\n\n if (bare) {\n return (\n <div {...props} className={cn(\"grid gap-1\", className)}>\n <Label id={labelId} htmlFor={id} className=\"sr-only\">\n {label}\n </Label>\n {control}\n <InputError id={errorId} message={error} />\n </div>\n );\n }\n\n return (\n <div {...props} className={cn(\"grid gap-2\", className)}>\n <div className=\"flex min-h-5 items-center\">\n <Label id={labelId} htmlFor={id}>\n {label}\n </Label>\n {required && (\n <span aria-hidden=\"true\" className=\"ml-0.5 text-lt-danger\">\n *\n </span>\n )}\n <InfoTooltip content={tooltip} />\n {labelAction && (\n <TextLink\n href={labelAction.href}\n tabIndex={labelAction.tabIndex ?? undefined}\n className=\"ml-auto text-sm\"\n >\n {labelAction.label}\n </TextLink>\n )}\n </div>\n\n {control}\n\n {helperText && (\n <p id={helperTextId} className=\"text-sm text-lt-muted-fg\">\n {helperText}\n </p>\n )}\n\n <InputError id={errorId} message={error} />\n </div>\n );\n}\n"],"mappings":";;;;;;;;AA4BA,SAAgB,eAAe,EAC7B,UACA,WACA,OACA,YACA,IACA,OACA,aACA,UACA,SACA,GAAG,SAC8B;CACjC,MAAM,OAAO,eAAe;CAC5B,MAAM,UAAU,GAAG,GAAG;CACtB,MAAM,eAAe,CAAC,QAAQ,aAAa,GAAG,GAAG,WAAW,KAAA;CAC5D,MAAM,UAAU,QAAQ,GAAG,GAAG,UAAU,KAAA;CAExC,MAAM,UAAU,SAAS;EACvB;EACA,oBAHkB,CAAC,cAAc,OAAO,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC,KAAK,GAAG,KAAK,KAAA;EAIvE,gBAAgB,QAAQ,OAAO,KAAA;EAC/B,mBAAmB,QAAQ,UAAU,KAAA;EACrC,iBAAiB,YAAY,KAAA;CAC/B,CAAC;CAED,IAAI,MACF,OACE,qBAAC,OAAD;EAAK,GAAI;EAAO,WAAW,GAAG,cAAc,SAAS;EAArD,UAAA;GACE,oBAAC,OAAD;IAAO,IAAI;IAAS,SAAS;IAAI,WAAU;IACxC,UAAA;GACI,CAAA;GACN;GACD,oBAAC,YAAD;IAAY,IAAI;IAAS,SAAS;GAAQ,CAAA;EACvC;;CAIT,OACE,qBAAC,OAAD;EAAK,GAAI;EAAO,WAAW,GAAG,cAAc,SAAS;EAArD,UAAA;GACE,qBAAC,OAAD;IAAK,WAAU;IAAf,UAAA;KACE,oBAAC,OAAD;MAAO,IAAI;MAAS,SAAS;MAC1B,UAAA;KACI,CAAA;KACN,YACC,oBAAC,QAAD;MAAM,eAAY;MAAO,WAAU;MAAwB,UAAA;KAErD,CAAA;KAER,oBAAC,aAAD,EAAa,SAAS,QAAU,CAAA;KAC/B,eACC,oBAAC,UAAD;MACE,MAAM,YAAY;MAClB,UAAU,YAAY,YAAY,KAAA;MAClC,WAAU;MAET,UAAA,YAAY;KACL,CAAA;IAET;;GAEJ;GAEA,cACC,oBAAC,KAAD;IAAG,IAAI;IAAc,WAAU;IAC5B,UAAA;GACA,CAAA;GAGL,oBAAC,YAAD;IAAY,IAAI;IAAS,SAAS;GAAQ,CAAA;EACvC;;AAET"}
|
|
@@ -52,10 +52,12 @@ var BuilderComponent = ({ node }) => {
|
|
|
52
52
|
helperText: props.helperText ?? void 0,
|
|
53
53
|
tooltip: props.tooltip ?? void 0,
|
|
54
54
|
label: props.label ?? "",
|
|
55
|
-
|
|
55
|
+
id: path,
|
|
56
56
|
required,
|
|
57
|
-
children: /* @__PURE__ */ jsxs("div", {
|
|
57
|
+
children: (controlProps) => /* @__PURE__ */ jsxs("div", {
|
|
58
|
+
...controlProps,
|
|
58
59
|
className: "flex flex-col gap-3",
|
|
60
|
+
role: "group",
|
|
59
61
|
children: [
|
|
60
62
|
/* @__PURE__ */ jsx(RowKeyInputs, {
|
|
61
63
|
path,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"builder.js","names":[],"sources":["../../../../resources/js/form/components/fields/builder.tsx"],"sourcesContent":["import type { Node, RendererComponent } from \"@lattice-php/lattice/core/types\";\nimport { useT } from \"@lattice-php/lattice/i18n\";\nimport { FormFieldFrame } from \"@lattice-php/lattice/form/components/base/field\";\nimport { useFormContext } from \"@lattice-php/lattice/form/hooks/context\";\nimport { useDependentField } from \"@lattice-php/lattice/form/hooks/use-dependent-field\";\nimport { AddRowMenu, type AddRowOption } from \"./add-row-menu\";\nimport { ROW_ID_KEY } from \"./repeater-rows\";\nimport { buildRowActions } from \"./row-action-menu\";\nimport { RowActions } from \"./row-actions\";\nimport { RowKeyInputs } from \"./row-key-inputs\";\nimport { RowItem } from \"./row-item\";\nimport { rowTemplatesOf, type RowTemplate } from \"./row-templates\";\nimport { columnsFromSchema, TableRows } from \"./table-rows\";\nimport { useFlipReorder } from \"./use-flip-reorder\";\nimport { useRowCollection } from \"./use-row-collection\";\n\nconst EMPTY_TEMPLATE: Node[] = [];\n\nexport const BuilderComponent: RendererComponent<\"field.builder\"> = ({ node }) => {\n const props = node.props;\n const name = props.name;\n const templates = rowTemplatesOf(node) ?? [];\n const { errors } = useFormContext();\n const { hidden, required } = useDependentField(node);\n const { path, rows, onField, onRemove, onMove, onDuplicate, append } = useRowCollection(\n name,\n props.defaultItems ?? 0,\n );\n const { t } = useT(\"lattice\");\n const orderSignature = rows.map((r) => String(r[ROW_ID_KEY] ?? \"\")).join(\",\");\n const registerRow = useFlipReorder(orderSignature);\n const atMax = props.maxItems != null && rows.length >= props.maxItems;\n const atMin = props.minItems != null && rows.length <= props.minItems;\n const isTable = props.layout === \"table\";\n\n const templateFor = (type: unknown): RowTemplate | undefined =>\n templates.find((template) => template.type === type);\n const options: AddRowOption[] = templates.map((template) => ({\n type: template.type,\n label: template.label,\n }));\n\n if (hidden) {\n return null;\n }\n\n const primary = templates[0];\n const tableRows = rows.map((row, index) => {\n const template = templateFor(row.type);\n const isPrimary = !!template && !!primary && template.type === primary.type;\n return {\n key: String(row[ROW_ID_KEY] ?? index),\n index,\n row,\n template: template?.schema ?? EMPTY_TEMPLATE,\n span: !isPrimary,\n heading: template?.label ?? `Unknown block: ${String(row.type)}`,\n };\n });\n\n return (\n <FormFieldFrame\n error={errors[path]}\n helperText={props.helperText ?? undefined}\n tooltip={props.tooltip ?? undefined}\n label={props.label ?? \"\"}\n
|
|
1
|
+
{"version":3,"file":"builder.js","names":[],"sources":["../../../../resources/js/form/components/fields/builder.tsx"],"sourcesContent":["import type { Node, RendererComponent } from \"@lattice-php/lattice/core/types\";\nimport { useT } from \"@lattice-php/lattice/i18n\";\nimport { FormFieldFrame } from \"@lattice-php/lattice/form/components/base/field\";\nimport { useFormContext } from \"@lattice-php/lattice/form/hooks/context\";\nimport { useDependentField } from \"@lattice-php/lattice/form/hooks/use-dependent-field\";\nimport { AddRowMenu, type AddRowOption } from \"./add-row-menu\";\nimport { ROW_ID_KEY } from \"./repeater-rows\";\nimport { buildRowActions } from \"./row-action-menu\";\nimport { RowActions } from \"./row-actions\";\nimport { RowKeyInputs } from \"./row-key-inputs\";\nimport { RowItem } from \"./row-item\";\nimport { rowTemplatesOf, type RowTemplate } from \"./row-templates\";\nimport { columnsFromSchema, TableRows } from \"./table-rows\";\nimport { useFlipReorder } from \"./use-flip-reorder\";\nimport { useRowCollection } from \"./use-row-collection\";\n\nconst EMPTY_TEMPLATE: Node[] = [];\n\nexport const BuilderComponent: RendererComponent<\"field.builder\"> = ({ node }) => {\n const props = node.props;\n const name = props.name;\n const templates = rowTemplatesOf(node) ?? [];\n const { errors } = useFormContext();\n const { hidden, required } = useDependentField(node);\n const { path, rows, onField, onRemove, onMove, onDuplicate, append } = useRowCollection(\n name,\n props.defaultItems ?? 0,\n );\n const { t } = useT(\"lattice\");\n const orderSignature = rows.map((r) => String(r[ROW_ID_KEY] ?? \"\")).join(\",\");\n const registerRow = useFlipReorder(orderSignature);\n const atMax = props.maxItems != null && rows.length >= props.maxItems;\n const atMin = props.minItems != null && rows.length <= props.minItems;\n const isTable = props.layout === \"table\";\n\n const templateFor = (type: unknown): RowTemplate | undefined =>\n templates.find((template) => template.type === type);\n const options: AddRowOption[] = templates.map((template) => ({\n type: template.type,\n label: template.label,\n }));\n\n if (hidden) {\n return null;\n }\n\n const primary = templates[0];\n const tableRows = rows.map((row, index) => {\n const template = templateFor(row.type);\n const isPrimary = !!template && !!primary && template.type === primary.type;\n return {\n key: String(row[ROW_ID_KEY] ?? index),\n index,\n row,\n template: template?.schema ?? EMPTY_TEMPLATE,\n span: !isPrimary,\n heading: template?.label ?? `Unknown block: ${String(row.type)}`,\n };\n });\n\n return (\n <FormFieldFrame\n error={errors[path]}\n helperText={props.helperText ?? undefined}\n tooltip={props.tooltip ?? undefined}\n label={props.label ?? \"\"}\n id={path}\n required={required}\n >\n {(controlProps) => (\n <div {...controlProps} className=\"flex flex-col gap-3\" role=\"group\">\n <RowKeyInputs path={path} rows={rows} rowKey={ROW_ID_KEY} />\n <RowKeyInputs path={path} rows={rows} rowKey=\"type\" />\n {isTable ? (\n <>\n <TableRows\n base={path}\n columns={columnsFromSchema(primary?.schema ?? [])}\n rows={tableRows}\n reorderable={props.reorderable ?? false}\n removable={() => !atMin}\n rowActions={props.rowActions}\n onField={onField}\n onMove={onMove}\n onRemove={onRemove}\n onDuplicate={onDuplicate}\n registerRow={registerRow}\n resizableColumns={props.resizableColumns === true}\n resizeIndicator={props.resizeIndicator === true}\n />\n </>\n ) : (\n rows.map((row, index) => {\n const template = templateFor(row.type);\n const key = String(row[ROW_ID_KEY] ?? index);\n\n return (\n <div key={key} ref={(el) => registerRow(key, el)} data-flip-key={key}>\n {template ? (\n <RowItem\n base={path}\n index={index}\n row={row}\n template={template.schema ?? EMPTY_TEMPLATE}\n heading={template.label}\n reorderable={props.reorderable ?? false}\n isFirst={index === 0}\n isLast={index === rows.length - 1}\n removable={!atMin}\n rowActions={props.rowActions}\n onField={onField}\n onRemove={onRemove}\n onMove={onMove}\n onDuplicate={onDuplicate}\n />\n ) : (\n <div\n data-test={`repeater-${name}-row-${index}`}\n className=\"flex items-center justify-between rounded-lt border border-dashed border-lt-border p-4 text-sm text-lt-muted-fg\"\n >\n <span>Unknown block: {String(row.type)}</span>\n <RowActions\n actions={buildRowActions(props.rowActions, {\n index,\n removable: !atMin,\n onRemove,\n onDuplicate,\n t,\n })}\n />\n </div>\n )}\n </div>\n );\n })\n )}\n\n {!atMax && (\n <AddRowMenu\n addLabel={props.addLabel ?? \"Add\"}\n options={options}\n onSelect={(type) => append({ type })}\n />\n )}\n </div>\n )}\n </FormFieldFrame>\n );\n};\n"],"mappings":"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"}
|
|
@@ -4,7 +4,7 @@ import { FormFieldFrame } from "../base/field.js";
|
|
|
4
4
|
import { useSeedDefault } from "../../hooks/use-seed-default.js";
|
|
5
5
|
import { useControlledField } from "../../hooks/use-controlled-field.js";
|
|
6
6
|
import { useMemo } from "react";
|
|
7
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
7
|
+
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
8
8
|
//#region resources/js/form/components/fields/choice.tsx
|
|
9
9
|
var ChoiceComponent = ({ node }) => {
|
|
10
10
|
const resolvedNode = useResolvedNode(node);
|
|
@@ -14,18 +14,19 @@ var ChoiceComponent = ({ node }) => {
|
|
|
14
14
|
const selected = value || fallbackValue;
|
|
15
15
|
useSeedDefault(localName, selected || void 0);
|
|
16
16
|
if (hidden || options.length === 0) return null;
|
|
17
|
-
return /* @__PURE__ */
|
|
17
|
+
return /* @__PURE__ */ jsx(FormFieldFrame, {
|
|
18
18
|
error,
|
|
19
19
|
helperText: node.props.helperText ?? void 0,
|
|
20
20
|
tooltip: node.props.tooltip ?? void 0,
|
|
21
21
|
label: node.props.label ?? "",
|
|
22
|
-
name,
|
|
22
|
+
id: name,
|
|
23
23
|
required,
|
|
24
|
-
children: [/* @__PURE__ */ jsx("input", {
|
|
24
|
+
children: (controlProps) => /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("input", {
|
|
25
25
|
name,
|
|
26
26
|
type: "hidden",
|
|
27
27
|
value: selected
|
|
28
28
|
}), /* @__PURE__ */ jsx(SegmentedPills, {
|
|
29
|
+
...controlProps,
|
|
29
30
|
ariaLabel: node.props.label ?? void 0,
|
|
30
31
|
autoFocus: node.props.autoFocus ?? void 0,
|
|
31
32
|
disabled: readOnly || disabled,
|
|
@@ -34,7 +35,7 @@ var ChoiceComponent = ({ node }) => {
|
|
|
34
35
|
options,
|
|
35
36
|
tabIndex: node.props.tabIndex ?? void 0,
|
|
36
37
|
value: selected
|
|
37
|
-
})]
|
|
38
|
+
})] })
|
|
38
39
|
});
|
|
39
40
|
};
|
|
40
41
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"choice.js","names":[],"sources":["../../../../resources/js/form/components/fields/choice.tsx"],"sourcesContent":["import { useMemo } from \"react\";\nimport type { Option, RendererComponent } from \"@lattice-php/lattice/core/types\";\nimport { SegmentedPills } from \"@lattice-php/lattice/ui/segmented-pills\";\nimport { FormFieldFrame } from \"@lattice-php/lattice/form/components/base/field\";\nimport { useControlledField } from \"@lattice-php/lattice/form/hooks/use-controlled-field\";\nimport { useResolvedNode } from \"@lattice-php/lattice/form/hooks/resolved-nodes\";\nimport { useSeedDefault } from \"@lattice-php/lattice/form/hooks/use-seed-default\";\n\nexport const ChoiceComponent: RendererComponent<\"field.choice\"> = ({ node }) => {\n const resolvedNode = useResolvedNode(node);\n const { localName, name, testId, value, error, hidden, required, readOnly, disabled, commit } =\n useControlledField(node);\n const options = useMemo(\n () => (resolvedNode.props as { options?: Option[] }).options ?? [],\n [resolvedNode.props],\n );\n const fallbackValue = options[0]?.value ?? \"\";\n const selected = value || fallbackValue;\n\n useSeedDefault(localName, selected || undefined);\n\n if (hidden || options.length === 0) {\n return null;\n }\n\n return (\n <FormFieldFrame\n error={error}\n helperText={node.props.helperText ?? undefined}\n tooltip={node.props.tooltip ?? undefined}\n label={node.props.label ?? \"\"}\n
|
|
1
|
+
{"version":3,"file":"choice.js","names":[],"sources":["../../../../resources/js/form/components/fields/choice.tsx"],"sourcesContent":["import { useMemo } from \"react\";\nimport type { Option, RendererComponent } from \"@lattice-php/lattice/core/types\";\nimport { SegmentedPills } from \"@lattice-php/lattice/ui/segmented-pills\";\nimport { FormFieldFrame } from \"@lattice-php/lattice/form/components/base/field\";\nimport { useControlledField } from \"@lattice-php/lattice/form/hooks/use-controlled-field\";\nimport { useResolvedNode } from \"@lattice-php/lattice/form/hooks/resolved-nodes\";\nimport { useSeedDefault } from \"@lattice-php/lattice/form/hooks/use-seed-default\";\n\nexport const ChoiceComponent: RendererComponent<\"field.choice\"> = ({ node }) => {\n const resolvedNode = useResolvedNode(node);\n const { localName, name, testId, value, error, hidden, required, readOnly, disabled, commit } =\n useControlledField(node);\n const options = useMemo(\n () => (resolvedNode.props as { options?: Option[] }).options ?? [],\n [resolvedNode.props],\n );\n const fallbackValue = options[0]?.value ?? \"\";\n const selected = value || fallbackValue;\n\n useSeedDefault(localName, selected || undefined);\n\n if (hidden || options.length === 0) {\n return null;\n }\n\n return (\n <FormFieldFrame\n error={error}\n helperText={node.props.helperText ?? undefined}\n tooltip={node.props.tooltip ?? undefined}\n label={node.props.label ?? \"\"}\n id={name}\n required={required}\n >\n {(controlProps) => (\n <>\n <input name={name} type=\"hidden\" value={selected} />\n <SegmentedPills\n {...controlProps}\n ariaLabel={node.props.label ?? undefined}\n autoFocus={node.props.autoFocus ?? undefined}\n disabled={readOnly || disabled}\n name={testId ?? \"segment\"}\n onSelect={commit}\n options={options}\n tabIndex={node.props.tabIndex ?? undefined}\n value={selected}\n />\n </>\n )}\n </FormFieldFrame>\n );\n};\n"],"mappings":";;;;;;;;AAQA,IAAa,mBAAsD,EAAE,WAAW;CAC9E,MAAM,eAAe,gBAAgB,IAAI;CACzC,MAAM,EAAE,WAAW,MAAM,QAAQ,OAAO,OAAO,QAAQ,UAAU,UAAU,UAAU,WACnF,mBAAmB,IAAI;CACzB,MAAM,UAAU,cACP,aAAa,MAAiC,WAAW,CAAC,GACjE,CAAC,aAAa,KAAK,CACrB;CACA,MAAM,gBAAgB,QAAQ,EAAE,EAAE,SAAS;CAC3C,MAAM,WAAW,SAAS;CAE1B,eAAe,WAAW,YAAY,KAAA,CAAS;CAE/C,IAAI,UAAU,QAAQ,WAAW,GAC/B,OAAO;CAGT,OACE,oBAAC,gBAAD;EACS;EACP,YAAY,KAAK,MAAM,cAAc,KAAA;EACrC,SAAS,KAAK,MAAM,WAAW,KAAA;EAC/B,OAAO,KAAK,MAAM,SAAS;EAC3B,IAAI;EACM;EAER,WAAA,iBACA,qBAAA,YAAA,EAAA,UAAA,CACE,oBAAC,SAAD;GAAa;GAAM,MAAK;GAAS,OAAO;EAAW,CAAA,GACnD,oBAAC,gBAAD;GACE,GAAI;GACJ,WAAW,KAAK,MAAM,SAAS,KAAA;GAC/B,WAAW,KAAK,MAAM,aAAa,KAAA;GACnC,UAAU,YAAY;GACtB,MAAM,UAAU;GAChB,UAAU;GACD;GACT,UAAU,KAAK,MAAM,YAAY,KAAA;GACjC,OAAO;EACR,CAAA,CACD,EAAA,CAAA;CAEU,CAAA;AAEpB"}
|
|
@@ -10,7 +10,7 @@ var ColorPickerFieldComponent = ({ node }) => {
|
|
|
10
10
|
return /* @__PURE__ */ jsx(SimpleField, {
|
|
11
11
|
node,
|
|
12
12
|
label: props.label ?? "",
|
|
13
|
-
children: ({ name, value, readOnly, disabled, commit }) => {
|
|
13
|
+
children: ({ name, value, readOnly, disabled, commit }, controlProps) => {
|
|
14
14
|
const hex = normalizeHex(value);
|
|
15
15
|
return /* @__PURE__ */ jsxs(Popover, { children: [
|
|
16
16
|
/* @__PURE__ */ jsx("input", {
|
|
@@ -21,10 +21,10 @@ var ColorPickerFieldComponent = ({ node }) => {
|
|
|
21
21
|
/* @__PURE__ */ jsx(PopoverTrigger, {
|
|
22
22
|
asChild: true,
|
|
23
23
|
children: /* @__PURE__ */ jsx("button", {
|
|
24
|
+
...controlProps,
|
|
24
25
|
className: cn(controlSurface(), "flex items-center gap-2 text-left"),
|
|
25
26
|
"data-test": `color-picker-${name}`,
|
|
26
27
|
disabled: disabled || readOnly,
|
|
27
|
-
id: name,
|
|
28
28
|
type: "button",
|
|
29
29
|
children: hex ? /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("span", {
|
|
30
30
|
"aria-hidden": "true",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"color-picker-field.js","names":[],"sources":["../../../../resources/js/form/components/fields/color-picker-field.tsx"],"sourcesContent":["import type { RendererComponent } from \"@lattice-php/lattice/core/types\";\nimport { cn } from \"@lattice-php/lattice/lib/utils\";\nimport { ColorPicker, normalizeHex } from \"@lattice-php/lattice/ui/color-picker\";\nimport { controlSurface } from \"@lattice-php/lattice/ui/control\";\nimport { Popover, PopoverContent, PopoverTrigger } from \"@lattice-php/lattice/ui/popover\";\nimport { SimpleField } from \"./simple-field\";\n\nexport const ColorPickerFieldComponent: RendererComponent<\"field.color-picker\"> = ({ node }) => {\n const props = node.props;\n\n return (\n <SimpleField node={node} label={props.label ?? \"\"}>\n {({ name, value, readOnly, disabled, commit }) => {\n const hex = normalizeHex(value);\n\n return (\n <Popover>\n <input name={name} type=\"hidden\" value={hex ?? \"\"} />\n <PopoverTrigger asChild>\n <button\n className={cn(controlSurface(), \"flex items-center gap-2 text-left\")}\n data-test={`color-picker-${name}`}\n disabled={disabled || readOnly}\n
|
|
1
|
+
{"version":3,"file":"color-picker-field.js","names":[],"sources":["../../../../resources/js/form/components/fields/color-picker-field.tsx"],"sourcesContent":["import type { RendererComponent } from \"@lattice-php/lattice/core/types\";\nimport { cn } from \"@lattice-php/lattice/lib/utils\";\nimport { ColorPicker, normalizeHex } from \"@lattice-php/lattice/ui/color-picker\";\nimport { controlSurface } from \"@lattice-php/lattice/ui/control\";\nimport { Popover, PopoverContent, PopoverTrigger } from \"@lattice-php/lattice/ui/popover\";\nimport { SimpleField } from \"./simple-field\";\n\nexport const ColorPickerFieldComponent: RendererComponent<\"field.color-picker\"> = ({ node }) => {\n const props = node.props;\n\n return (\n <SimpleField node={node} label={props.label ?? \"\"}>\n {({ name, value, readOnly, disabled, commit }, controlProps) => {\n const hex = normalizeHex(value);\n\n return (\n <Popover>\n <input name={name} type=\"hidden\" value={hex ?? \"\"} />\n <PopoverTrigger asChild>\n <button\n {...controlProps}\n className={cn(controlSurface(), \"flex items-center gap-2 text-left\")}\n data-test={`color-picker-${name}`}\n disabled={disabled || readOnly}\n type=\"button\"\n >\n {hex ? (\n <>\n <span\n aria-hidden=\"true\"\n className=\"size-4 shrink-0 rounded-full border border-lt-border\"\n style={{ background: hex }}\n />\n <span className=\"tabular-nums\">{hex}</span>\n </>\n ) : (\n <span className=\"text-lt-muted-fg\">{props.placeholder ?? \"\"}</span>\n )}\n </button>\n </PopoverTrigger>\n <PopoverContent className=\"p-3\">\n <ColorPicker\n onChange={(next) => commit(next)}\n palette={props.palette}\n value={hex ?? \"#6b7280\"}\n />\n </PopoverContent>\n </Popover>\n );\n }}\n </SimpleField>\n );\n};\n"],"mappings":";;;;;;;AAOA,IAAa,6BAAsE,EAAE,WAAW;CAC9F,MAAM,QAAQ,KAAK;CAEnB,OACE,oBAAC,aAAD;EAAmB;EAAM,OAAO,MAAM,SAAS;EAC3C,WAAA,EAAE,MAAM,OAAO,UAAU,UAAU,UAAU,iBAAiB;GAC9D,MAAM,MAAM,aAAa,KAAK;GAE9B,OACE,qBAAC,SAAD,EAAA,UAAA;IACE,oBAAC,SAAD;KAAa;KAAM,MAAK;KAAS,OAAO,OAAO;IAAK,CAAA;IACpD,oBAAC,gBAAD;KAAgB,SAAA;KACd,UAAA,oBAAC,UAAD;MACE,GAAI;MACJ,WAAW,GAAG,eAAe,GAAG,mCAAmC;MACnE,aAAW,gBAAgB;MAC3B,UAAU,YAAY;MACtB,MAAK;MAEJ,UAAA,MACC,qBAAA,UAAA,EAAA,UAAA,CACE,oBAAC,QAAD;OACE,eAAY;OACZ,WAAU;OACV,OAAO,EAAE,YAAY,IAAI;MAC1B,CAAA,GACD,oBAAC,QAAD;OAAM,WAAU;OAAgB,UAAA;MAAU,CAAA,CAC1C,EAAA,CAAA,IAEF,oBAAC,QAAD;OAAM,WAAU;OAAoB,UAAA,MAAM,eAAe;MAAS,CAAA;KAE9D,CAAA;IACM,CAAA;IAChB,oBAAC,gBAAD;KAAgB,WAAU;KACxB,UAAA,oBAAC,aAAD;MACE,WAAW,SAAS,OAAO,IAAI;MAC/B,SAAS,MAAM;MACf,OAAO,OAAO;KACf,CAAA;IACa,CAAA;GACT,EAAA,CAAA;EAEb;CACW,CAAA;AAEjB"}
|
|
@@ -7,7 +7,8 @@ var DateInputComponent = ({ node }) => {
|
|
|
7
7
|
return /* @__PURE__ */ jsx(SimpleField, {
|
|
8
8
|
node,
|
|
9
9
|
label: props.label ?? "",
|
|
10
|
-
children: ({ name, testId, value, readOnly, disabled, change, blur }) => /* @__PURE__ */ jsx(DatePicker, {
|
|
10
|
+
children: ({ name, testId, value, readOnly, disabled, change, blur }, controlProps) => /* @__PURE__ */ jsx(DatePicker, {
|
|
11
|
+
controlProps,
|
|
11
12
|
autoFocus: props.autoFocus ?? false,
|
|
12
13
|
disabled,
|
|
13
14
|
label: props.label ?? props.name,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"date-input.js","names":[],"sources":["../../../../resources/js/form/components/fields/date-input.tsx"],"sourcesContent":["import type { RendererComponent } from \"@lattice-php/lattice/core/types\";\nimport { DatePicker } from \"./date-picker\";\nimport { SimpleField } from \"./simple-field\";\n\nexport const DateInputComponent: RendererComponent<\"field.date-input\"> = ({ node }) => {\n const props = node.props;\n\n return (\n <SimpleField node={node} label={props.label ?? \"\"}>\n {({ name, testId, value, readOnly, disabled, change, blur }) => (\n <DatePicker\n autoFocus={props.autoFocus ?? false}\n disabled={disabled}\n label={props.label ?? props.name}\n max={props.max || undefined}\n min={props.min || undefined}\n mode=\"date\"\n name={name}\n onBlur={blur}\n onChange={change}\n readOnly={readOnly}\n tabIndex={props.tabIndex ?? undefined}\n testId={testId ?? props.name}\n value={value}\n />\n )}\n </SimpleField>\n );\n};\n"],"mappings":";;;;AAIA,IAAa,sBAA6D,EAAE,WAAW;CACrF,MAAM,QAAQ,KAAK;CAEnB,OACE,oBAAC,aAAD;EAAmB;EAAM,OAAO,MAAM,SAAS;EAC3C,WAAA,EAAE,MAAM,QAAQ,OAAO,UAAU,UAAU,QAAQ,
|
|
1
|
+
{"version":3,"file":"date-input.js","names":[],"sources":["../../../../resources/js/form/components/fields/date-input.tsx"],"sourcesContent":["import type { RendererComponent } from \"@lattice-php/lattice/core/types\";\nimport { DatePicker } from \"./date-picker\";\nimport { SimpleField } from \"./simple-field\";\n\nexport const DateInputComponent: RendererComponent<\"field.date-input\"> = ({ node }) => {\n const props = node.props;\n\n return (\n <SimpleField node={node} label={props.label ?? \"\"}>\n {({ name, testId, value, readOnly, disabled, change, blur }, controlProps) => (\n <DatePicker\n controlProps={controlProps}\n autoFocus={props.autoFocus ?? false}\n disabled={disabled}\n label={props.label ?? props.name}\n max={props.max || undefined}\n min={props.min || undefined}\n mode=\"date\"\n name={name}\n onBlur={blur}\n onChange={change}\n readOnly={readOnly}\n tabIndex={props.tabIndex ?? undefined}\n testId={testId ?? props.name}\n value={value}\n />\n )}\n </SimpleField>\n );\n};\n"],"mappings":";;;;AAIA,IAAa,sBAA6D,EAAE,WAAW;CACrF,MAAM,QAAQ,KAAK;CAEnB,OACE,oBAAC,aAAD;EAAmB;EAAM,OAAO,MAAM,SAAS;EAC3C,WAAA,EAAE,MAAM,QAAQ,OAAO,UAAU,UAAU,QAAQ,QAAQ,iBAC3D,oBAAC,YAAD;GACgB;GACd,WAAW,MAAM,aAAa;GACpB;GACV,OAAO,MAAM,SAAS,MAAM;GAC5B,KAAK,MAAM,OAAO,KAAA;GAClB,KAAK,MAAM,OAAO,KAAA;GAClB,MAAK;GACC;GACN,QAAQ;GACR,UAAU;GACA;GACV,UAAU,MAAM,YAAY,KAAA;GAC5B,QAAQ,UAAU,MAAM;GACjB;EACR,CAAA;CAEQ,CAAA;AAEjB"}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
import { FormFieldControlProps } from '../base/field.js';
|
|
1
2
|
export type DatePickerFieldProps = {
|
|
2
3
|
mode: "date" | "date-time";
|
|
4
|
+
controlProps: FormFieldControlProps;
|
|
3
5
|
label: string;
|
|
4
6
|
name: string;
|
|
5
7
|
testId: string;
|
|
@@ -15,4 +17,4 @@ export type DatePickerFieldProps = {
|
|
|
15
17
|
onChange: (value: string) => void;
|
|
16
18
|
onBlur?: () => void;
|
|
17
19
|
};
|
|
18
|
-
export declare function DatePickerField({ mode, label, name, testId, value, min, max, step, disabled, readOnly, autoFocus, tabIndex, timezone, onChange, onBlur, }: DatePickerFieldProps): import("react").JSX.Element;
|
|
20
|
+
export declare function DatePickerField({ mode, controlProps, label, name, testId, value, min, max, step, disabled, readOnly, autoFocus, tabIndex, timezone, onChange, onBlur, }: DatePickerFieldProps): import("react").JSX.Element;
|
|
@@ -11,7 +11,7 @@ import { jsx, jsxs } from "react/jsx-runtime";
|
|
|
11
11
|
import * as datePicker from "@zag-js/date-picker";
|
|
12
12
|
import { normalizeProps, useMachine } from "@zag-js/react";
|
|
13
13
|
//#region resources/js/form/components/fields/date-picker-field.tsx
|
|
14
|
-
function DatePickerField({ mode, label, name, testId, value, min, max, step, disabled, readOnly, autoFocus = false, tabIndex, timezone = "UTC", onChange, onBlur }) {
|
|
14
|
+
function DatePickerField({ mode, controlProps, label, name, testId, value, min, max, step, disabled, readOnly, autoFocus = false, tabIndex, timezone = "UTC", onChange, onBlur }) {
|
|
15
15
|
const id = useId();
|
|
16
16
|
const { locale } = useLocale();
|
|
17
17
|
const selected = useMemo(() => [mode === "date" ? parseDateValue(value) : parseDateTimeValue(value, timezone)].filter(Boolean), [
|
|
@@ -63,11 +63,11 @@ function DatePickerField({ mode, label, name, testId, value, min, max, step, dis
|
|
|
63
63
|
className: "flex gap-2",
|
|
64
64
|
children: [/* @__PURE__ */ jsx(Input, {
|
|
65
65
|
...inputProps,
|
|
66
|
+
...controlProps,
|
|
66
67
|
"aria-label": label,
|
|
67
68
|
autoFocus,
|
|
68
69
|
"data-test": testId,
|
|
69
70
|
disabled,
|
|
70
|
-
id: name,
|
|
71
71
|
onInput: (event) => {
|
|
72
72
|
onInput?.(event);
|
|
73
73
|
if (mode !== "date") return;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"date-picker-field.js","names":[],"sources":["../../../../resources/js/form/components/fields/date-picker-field.tsx"],"sourcesContent":["import type { DateValue } from \"@internationalized/date\";\nimport * as datePicker from \"@zag-js/date-picker\";\nimport { normalizeProps, useMachine } from \"@zag-js/react\";\nimport { useId, useMemo } from \"react\";\nimport { Button } from \"@lattice-php/lattice/ui/button\";\nimport { Icon } from \"@lattice-php/lattice/icons\";\nimport { useLocale } from \"@lattice-php/lattice/i18n\";\nimport { cn } from \"@lattice-php/lattice/lib/utils\";\nimport { Input } from \"@lattice-php/lattice/ui/input\";\nimport {\n formatDateDisplayValue,\n formatDateTimeDisplayValue,\n formatDateTimeValue,\n formatDateValue,\n formatTimeInputValue,\n parseDateDisplayValue,\n parseDateTimeDisplayValue,\n parseDateTimeValue,\n parseDateValue,\n} from \"./date-picker-value\";\nimport { TimePicker } from \"./time-picker\";\nimport { parseTimeString } from \"./time-picker-columns\";\n\nexport type DatePickerFieldProps = {\n mode: \"date\" | \"date-time\";\n label: string;\n name: string;\n testId: string;\n value: unknown;\n min?: string | null;\n max?: string | null;\n step?: number | null;\n disabled: boolean;\n readOnly: boolean;\n autoFocus?: boolean;\n tabIndex?: number | null;\n timezone?: string;\n onChange: (value: string) => void;\n onBlur?: () => void;\n};\n\nexport function DatePickerField({\n mode,\n label,\n name,\n testId,\n value,\n min,\n max,\n step,\n disabled,\n readOnly,\n autoFocus = false,\n tabIndex,\n timezone = \"UTC\",\n onChange,\n onBlur,\n}: DatePickerFieldProps) {\n const id = useId();\n const { locale } = useLocale();\n const selected = useMemo(\n () =>\n [mode === \"date\" ? parseDateValue(value) : parseDateTimeValue(value, timezone)].filter(\n Boolean,\n ) as DateValue[],\n [mode, timezone, value],\n );\n const service = useMachine(datePicker.machine, {\n id,\n name,\n value: selected.length > 0 ? selected : undefined,\n min: min ? parseDateValue(min) : undefined,\n max: max ? parseDateValue(max) : undefined,\n disabled,\n readOnly,\n locale,\n selectionMode: \"single\",\n timeZone: timezone,\n closeOnSelect: mode === \"date\",\n format(date) {\n return mode === \"date\"\n ? formatDateDisplayValue(date, locale)\n : formatDateTimeDisplayValue(date, locale, timezone);\n },\n parse(text) {\n return mode === \"date\"\n ? parseDateDisplayValue(text, locale)\n : parseDateTimeDisplayValue(text, locale, timezone);\n },\n onValueChange(details) {\n const next = details.value[0];\n\n onChange(mode === \"date\" ? formatDateValue(next) : formatDateTimeValue(next, timezone));\n },\n onOpenChange(details) {\n if (!details.open) {\n onBlur?.();\n }\n },\n });\n const api = datePicker.connect(service, normalizeProps);\n const { name: _inputName, onInput, ...inputProps } = api.getInputProps();\n const submittedValue =\n mode === \"date\" ? formatDateValue(selected[0]) : formatDateTimeValue(selected[0], timezone);\n\n return (\n <div {...api.getRootProps()} className={cn(\"relative\", api.open && \"z-lt-popover\")}>\n <input type=\"hidden\" name={name} value={submittedValue} data-test={`${testId}-value`} />\n <div {...api.getControlProps()} className=\"flex gap-2\">\n <Input\n {...inputProps}\n aria-label={label}\n autoFocus={autoFocus}\n data-test={testId}\n disabled={disabled}\n id={name}\n onInput={(event) => {\n onInput?.(event);\n\n if (mode !== \"date\") {\n return;\n }\n\n const normalized = normalizeDateInputValue(event.currentTarget.value);\n\n if (!normalized) {\n return;\n }\n\n const next = parseDateValue(normalized);\n\n if (!next) {\n return;\n }\n\n event.currentTarget.value = normalized;\n api.setValue([next]);\n event.currentTarget.value = formatDateDisplayValue(next, locale);\n onChange(formatDateValue(next));\n }}\n readOnly={readOnly}\n tabIndex={tabIndex ?? undefined}\n />\n <Button\n {...api.getTriggerProps()}\n aria-label={`Open ${label || name} calendar`}\n disabled={disabled || readOnly}\n size=\"icon\"\n type=\"button\"\n variant=\"secondary\"\n >\n <Icon name=\"calendar\" className=\"size-lt-icon-md\" aria-hidden=\"true\" />\n </Button>\n </div>\n {api.open ? (\n <div\n {...api.getPositionerProps()}\n className=\"absolute z-lt-popover mt-2 rounded-lt-sm border border-lt-border bg-lt-popover p-3 text-lt-popover-fg shadow-lt-md\"\n >\n <div {...api.getContentProps()} className=\"grid gap-3\">\n <div className=\"flex items-center justify-between gap-2\">\n <Button {...api.getPrevTriggerProps()} emphasis=\"ghost\" size=\"icon\" type=\"button\">\n <Icon name=\"chevron-left\" className=\"size-lt-icon-md\" aria-hidden=\"true\" />\n </Button>\n <div {...api.getRangeTextProps()} className=\"text-sm font-medium text-lt-fg\" />\n <Button {...api.getNextTriggerProps()} emphasis=\"ghost\" size=\"icon\" type=\"button\">\n <Icon name=\"chevron-right\" className=\"size-lt-icon-md\" aria-hidden=\"true\" />\n </Button>\n </div>\n <table {...api.getTableProps()} className=\"w-full border-collapse text-sm\">\n <thead {...api.getTableHeadProps()}>\n <tr {...api.getTableRowProps()}>\n {api.weekDays.map((day) => (\n <th\n {...api.getTableHeaderProps()}\n aria-label={day.long}\n key={day.value.toString()}\n className=\"size-8 text-center text-xs font-medium text-lt-muted-fg\"\n >\n {day.narrow}\n </th>\n ))}\n </tr>\n </thead>\n <tbody {...api.getTableBodyProps()}>\n {api.weeks.map((week, weekIndex) => (\n <tr {...api.getTableRowProps()} key={weekIndex}>\n {week.map((day) => {\n const state = api.getDayTableCellState({ value: day });\n\n return (\n <td\n {...api.getDayTableCellProps({ value: day })}\n key={day.toString()}\n className=\"p-0 text-center\"\n >\n <button\n {...api.getDayTableCellTriggerProps({ value: day })}\n type=\"button\"\n className={cn(\n \"size-8 rounded-lt-sm text-sm text-lt-fg hover:bg-lt-muted\",\n state.selected && \"bg-lt-primary text-lt-primary-fg\",\n state.outsideRange && \"text-lt-muted-fg\",\n state.disabled && \"cursor-not-allowed opacity-40\",\n )}\n >\n {day.day}\n </button>\n </td>\n );\n })}\n </tr>\n ))}\n </tbody>\n </table>\n {mode === \"date-time\" ? (\n <TimePicker\n value={parseTimeString(formatTimeInputValue(selected[0], timezone))}\n onChange={(next) =>\n api.setTime({ hour: next.hour, minute: next.minute, second: next.second })\n }\n step={step}\n disabled={disabled}\n readOnly={readOnly}\n testId={`${testId}-time`}\n />\n ) : null}\n </div>\n </div>\n ) : null}\n </div>\n );\n}\n\nfunction normalizeDateInputValue(value: string): string | undefined {\n const compact = value.replace(/\\D/g, \"\");\n\n if (compact.length !== 8) {\n return undefined;\n }\n\n return `${compact.slice(0, 4)}-${compact.slice(4, 6)}-${compact.slice(6, 8)}`;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"date-picker-field.js","names":[],"sources":["../../../../resources/js/form/components/fields/date-picker-field.tsx"],"sourcesContent":["import type { DateValue } from \"@internationalized/date\";\nimport * as datePicker from \"@zag-js/date-picker\";\nimport { normalizeProps, useMachine } from \"@zag-js/react\";\nimport { useId, useMemo } from \"react\";\nimport { Button } from \"@lattice-php/lattice/ui/button\";\nimport { Icon } from \"@lattice-php/lattice/icons\";\nimport { useLocale } from \"@lattice-php/lattice/i18n\";\nimport { cn } from \"@lattice-php/lattice/lib/utils\";\nimport { Input } from \"@lattice-php/lattice/ui/input\";\nimport type { FormFieldControlProps } from \"@lattice-php/lattice/form/components/base/field\";\nimport {\n formatDateDisplayValue,\n formatDateTimeDisplayValue,\n formatDateTimeValue,\n formatDateValue,\n formatTimeInputValue,\n parseDateDisplayValue,\n parseDateTimeDisplayValue,\n parseDateTimeValue,\n parseDateValue,\n} from \"./date-picker-value\";\nimport { TimePicker } from \"./time-picker\";\nimport { parseTimeString } from \"./time-picker-columns\";\n\nexport type DatePickerFieldProps = {\n mode: \"date\" | \"date-time\";\n controlProps: FormFieldControlProps;\n label: string;\n name: string;\n testId: string;\n value: unknown;\n min?: string | null;\n max?: string | null;\n step?: number | null;\n disabled: boolean;\n readOnly: boolean;\n autoFocus?: boolean;\n tabIndex?: number | null;\n timezone?: string;\n onChange: (value: string) => void;\n onBlur?: () => void;\n};\n\nexport function DatePickerField({\n mode,\n controlProps,\n label,\n name,\n testId,\n value,\n min,\n max,\n step,\n disabled,\n readOnly,\n autoFocus = false,\n tabIndex,\n timezone = \"UTC\",\n onChange,\n onBlur,\n}: DatePickerFieldProps) {\n const id = useId();\n const { locale } = useLocale();\n const selected = useMemo(\n () =>\n [mode === \"date\" ? parseDateValue(value) : parseDateTimeValue(value, timezone)].filter(\n Boolean,\n ) as DateValue[],\n [mode, timezone, value],\n );\n const service = useMachine(datePicker.machine, {\n id,\n name,\n value: selected.length > 0 ? selected : undefined,\n min: min ? parseDateValue(min) : undefined,\n max: max ? parseDateValue(max) : undefined,\n disabled,\n readOnly,\n locale,\n selectionMode: \"single\",\n timeZone: timezone,\n closeOnSelect: mode === \"date\",\n format(date) {\n return mode === \"date\"\n ? formatDateDisplayValue(date, locale)\n : formatDateTimeDisplayValue(date, locale, timezone);\n },\n parse(text) {\n return mode === \"date\"\n ? parseDateDisplayValue(text, locale)\n : parseDateTimeDisplayValue(text, locale, timezone);\n },\n onValueChange(details) {\n const next = details.value[0];\n\n onChange(mode === \"date\" ? formatDateValue(next) : formatDateTimeValue(next, timezone));\n },\n onOpenChange(details) {\n if (!details.open) {\n onBlur?.();\n }\n },\n });\n const api = datePicker.connect(service, normalizeProps);\n const { name: _inputName, onInput, ...inputProps } = api.getInputProps();\n const submittedValue =\n mode === \"date\" ? formatDateValue(selected[0]) : formatDateTimeValue(selected[0], timezone);\n\n return (\n <div {...api.getRootProps()} className={cn(\"relative\", api.open && \"z-lt-popover\")}>\n <input type=\"hidden\" name={name} value={submittedValue} data-test={`${testId}-value`} />\n <div {...api.getControlProps()} className=\"flex gap-2\">\n <Input\n {...inputProps}\n {...controlProps}\n aria-label={label}\n autoFocus={autoFocus}\n data-test={testId}\n disabled={disabled}\n onInput={(event) => {\n onInput?.(event);\n\n if (mode !== \"date\") {\n return;\n }\n\n const normalized = normalizeDateInputValue(event.currentTarget.value);\n\n if (!normalized) {\n return;\n }\n\n const next = parseDateValue(normalized);\n\n if (!next) {\n return;\n }\n\n event.currentTarget.value = normalized;\n api.setValue([next]);\n event.currentTarget.value = formatDateDisplayValue(next, locale);\n onChange(formatDateValue(next));\n }}\n readOnly={readOnly}\n tabIndex={tabIndex ?? undefined}\n />\n <Button\n {...api.getTriggerProps()}\n aria-label={`Open ${label || name} calendar`}\n disabled={disabled || readOnly}\n size=\"icon\"\n type=\"button\"\n variant=\"secondary\"\n >\n <Icon name=\"calendar\" className=\"size-lt-icon-md\" aria-hidden=\"true\" />\n </Button>\n </div>\n {api.open ? (\n <div\n {...api.getPositionerProps()}\n className=\"absolute z-lt-popover mt-2 rounded-lt-sm border border-lt-border bg-lt-popover p-3 text-lt-popover-fg shadow-lt-md\"\n >\n <div {...api.getContentProps()} className=\"grid gap-3\">\n <div className=\"flex items-center justify-between gap-2\">\n <Button {...api.getPrevTriggerProps()} emphasis=\"ghost\" size=\"icon\" type=\"button\">\n <Icon name=\"chevron-left\" className=\"size-lt-icon-md\" aria-hidden=\"true\" />\n </Button>\n <div {...api.getRangeTextProps()} className=\"text-sm font-medium text-lt-fg\" />\n <Button {...api.getNextTriggerProps()} emphasis=\"ghost\" size=\"icon\" type=\"button\">\n <Icon name=\"chevron-right\" className=\"size-lt-icon-md\" aria-hidden=\"true\" />\n </Button>\n </div>\n <table {...api.getTableProps()} className=\"w-full border-collapse text-sm\">\n <thead {...api.getTableHeadProps()}>\n <tr {...api.getTableRowProps()}>\n {api.weekDays.map((day) => (\n <th\n {...api.getTableHeaderProps()}\n aria-label={day.long}\n key={day.value.toString()}\n className=\"size-8 text-center text-xs font-medium text-lt-muted-fg\"\n >\n {day.narrow}\n </th>\n ))}\n </tr>\n </thead>\n <tbody {...api.getTableBodyProps()}>\n {api.weeks.map((week, weekIndex) => (\n <tr {...api.getTableRowProps()} key={weekIndex}>\n {week.map((day) => {\n const state = api.getDayTableCellState({ value: day });\n\n return (\n <td\n {...api.getDayTableCellProps({ value: day })}\n key={day.toString()}\n className=\"p-0 text-center\"\n >\n <button\n {...api.getDayTableCellTriggerProps({ value: day })}\n type=\"button\"\n className={cn(\n \"size-8 rounded-lt-sm text-sm text-lt-fg hover:bg-lt-muted\",\n state.selected && \"bg-lt-primary text-lt-primary-fg\",\n state.outsideRange && \"text-lt-muted-fg\",\n state.disabled && \"cursor-not-allowed opacity-40\",\n )}\n >\n {day.day}\n </button>\n </td>\n );\n })}\n </tr>\n ))}\n </tbody>\n </table>\n {mode === \"date-time\" ? (\n <TimePicker\n value={parseTimeString(formatTimeInputValue(selected[0], timezone))}\n onChange={(next) =>\n api.setTime({ hour: next.hour, minute: next.minute, second: next.second })\n }\n step={step}\n disabled={disabled}\n readOnly={readOnly}\n testId={`${testId}-time`}\n />\n ) : null}\n </div>\n </div>\n ) : null}\n </div>\n );\n}\n\nfunction normalizeDateInputValue(value: string): string | undefined {\n const compact = value.replace(/\\D/g, \"\");\n\n if (compact.length !== 8) {\n return undefined;\n }\n\n return `${compact.slice(0, 4)}-${compact.slice(4, 6)}-${compact.slice(6, 8)}`;\n}\n"],"mappings":"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"}
|
|
@@ -9,7 +9,8 @@ var DateTimeInputComponent = ({ node }) => {
|
|
|
9
9
|
return /* @__PURE__ */ jsx(SimpleField, {
|
|
10
10
|
node,
|
|
11
11
|
label: props.label ?? "",
|
|
12
|
-
children: ({ name, testId, value, readOnly, disabled, change, blur }) => /* @__PURE__ */ jsx(DatePicker, {
|
|
12
|
+
children: ({ name, testId, value, readOnly, disabled, change, blur }, controlProps) => /* @__PURE__ */ jsx(DatePicker, {
|
|
13
|
+
controlProps,
|
|
13
14
|
autoFocus: props.autoFocus ?? false,
|
|
14
15
|
disabled,
|
|
15
16
|
label: props.label ?? props.name,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"date-time-input.js","names":[],"sources":["../../../../resources/js/form/components/fields/date-time-input.tsx"],"sourcesContent":["import type { RendererComponent } from \"@lattice-php/lattice/core/types\";\nimport { useTimezone } from \"@lattice-php/lattice/i18n\";\nimport { DatePicker } from \"./date-picker\";\nimport { SimpleField } from \"./simple-field\";\n\nexport const DateTimeInputComponent: RendererComponent<\"field.date-time-input\"> = ({ node }) => {\n const props = node.props;\n const { timezone } = useTimezone();\n\n return (\n <SimpleField node={node} label={props.label ?? \"\"}>\n {({ name, testId, value, readOnly, disabled, change, blur }) => (\n <DatePicker\n autoFocus={props.autoFocus ?? false}\n disabled={disabled}\n label={props.label ?? props.name}\n max={props.max}\n min={props.min}\n mode=\"date-time\"\n name={name}\n onBlur={blur}\n onChange={change}\n readOnly={readOnly}\n step={props.step}\n tabIndex={props.tabIndex ?? undefined}\n testId={testId ?? props.name}\n timezone={timezone}\n value={value}\n />\n )}\n </SimpleField>\n );\n};\n"],"mappings":";;;;;AAKA,IAAa,0BAAsE,EAAE,WAAW;CAC9F,MAAM,QAAQ,KAAK;CACnB,MAAM,EAAE,aAAa,YAAY;CAEjC,OACE,oBAAC,aAAD;EAAmB;EAAM,OAAO,MAAM,SAAS;EAC3C,WAAA,EAAE,MAAM,QAAQ,OAAO,UAAU,UAAU,QAAQ,
|
|
1
|
+
{"version":3,"file":"date-time-input.js","names":[],"sources":["../../../../resources/js/form/components/fields/date-time-input.tsx"],"sourcesContent":["import type { RendererComponent } from \"@lattice-php/lattice/core/types\";\nimport { useTimezone } from \"@lattice-php/lattice/i18n\";\nimport { DatePicker } from \"./date-picker\";\nimport { SimpleField } from \"./simple-field\";\n\nexport const DateTimeInputComponent: RendererComponent<\"field.date-time-input\"> = ({ node }) => {\n const props = node.props;\n const { timezone } = useTimezone();\n\n return (\n <SimpleField node={node} label={props.label ?? \"\"}>\n {({ name, testId, value, readOnly, disabled, change, blur }, controlProps) => (\n <DatePicker\n controlProps={controlProps}\n autoFocus={props.autoFocus ?? false}\n disabled={disabled}\n label={props.label ?? props.name}\n max={props.max}\n min={props.min}\n mode=\"date-time\"\n name={name}\n onBlur={blur}\n onChange={change}\n readOnly={readOnly}\n step={props.step}\n tabIndex={props.tabIndex ?? undefined}\n testId={testId ?? props.name}\n timezone={timezone}\n value={value}\n />\n )}\n </SimpleField>\n );\n};\n"],"mappings":";;;;;AAKA,IAAa,0BAAsE,EAAE,WAAW;CAC9F,MAAM,QAAQ,KAAK;CACnB,MAAM,EAAE,aAAa,YAAY;CAEjC,OACE,oBAAC,aAAD;EAAmB;EAAM,OAAO,MAAM,SAAS;EAC3C,WAAA,EAAE,MAAM,QAAQ,OAAO,UAAU,UAAU,QAAQ,QAAQ,iBAC3D,oBAAC,YAAD;GACgB;GACd,WAAW,MAAM,aAAa;GACpB;GACV,OAAO,MAAM,SAAS,MAAM;GAC5B,KAAK,MAAM;GACX,KAAK,MAAM;GACX,MAAK;GACC;GACN,QAAQ;GACR,UAAU;GACA;GACV,MAAM,MAAM;GACZ,UAAU,MAAM,YAAY,KAAA;GAC5B,QAAQ,UAAU,MAAM;GACd;GACH;EACR,CAAA;CAEQ,CAAA;AAEjB"}
|
|
@@ -3,10 +3,10 @@ import { testIdentity } from "../../../core/test-id.js";
|
|
|
3
3
|
import { useFormContext } from "../../hooks/context.js";
|
|
4
4
|
import { useFieldScope } from "../../hooks/field-scope.js";
|
|
5
5
|
import { useFormValues, useSetFormValue } from "../../hooks/values.js";
|
|
6
|
+
import { IconButton } from "../../../ui/icon-button.js";
|
|
6
7
|
import { FormFieldFrame } from "../base/field.js";
|
|
7
8
|
import { useDependentField } from "../../hooks/use-dependent-field.js";
|
|
8
9
|
import { requestSignedUpload, xhrTransfer } from "../../../core/upload.js";
|
|
9
|
-
import { IconButton } from "../../../ui/icon-button.js";
|
|
10
10
|
import { useEffect, useId, useMemo, useRef, useState } from "react";
|
|
11
11
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
12
12
|
//#region resources/js/form/components/fields/file-upload.tsx
|
|
@@ -170,9 +170,9 @@ var FileUploadComponent = ({ node }) => {
|
|
|
170
170
|
helperText: props.helperText ?? void 0,
|
|
171
171
|
tooltip: props.tooltip ?? void 0,
|
|
172
172
|
label: props.label ?? "",
|
|
173
|
-
|
|
173
|
+
id: inputId,
|
|
174
174
|
required,
|
|
175
|
-
children: /* @__PURE__ */ jsxs("div", {
|
|
175
|
+
children: (controlProps) => /* @__PURE__ */ jsxs("div", {
|
|
176
176
|
className: "flex flex-col gap-3 rounded-lt-sm border border-dashed border-lt-border bg-lt-surface px-4 py-6",
|
|
177
177
|
"data-test": testIdentity(name),
|
|
178
178
|
onDragOver: (event) => event.preventDefault(),
|
|
@@ -240,11 +240,11 @@ var FileUploadComponent = ({ node }) => {
|
|
|
240
240
|
value: token
|
|
241
241
|
}, token)),
|
|
242
242
|
/* @__PURE__ */ jsx("input", {
|
|
243
|
+
...controlProps,
|
|
243
244
|
accept: props.accept ?? void 0,
|
|
244
245
|
"aria-label": props.label ?? name,
|
|
245
246
|
className: "sr-only",
|
|
246
247
|
"data-test": testIdentity(`${name}-input`),
|
|
247
|
-
id: inputId,
|
|
248
248
|
multiple,
|
|
249
249
|
name: signed ? void 0 : fieldName,
|
|
250
250
|
onChange: (event) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"file-upload.js","names":[],"sources":["../../../../resources/js/form/components/fields/file-upload.tsx"],"sourcesContent":["import { testIdentity } from \"@lattice-php/lattice/core/test-id\";\nimport { requestSignedUpload, xhrTransfer } from \"@lattice-php/lattice/core/upload\";\nimport type { RendererComponent } from \"@lattice-php/lattice/core/types\";\nimport type { SignedUpload } from \"@lattice-php/lattice/types/generated\";\nimport { IconButton } from \"@lattice-php/lattice/ui/icon-button\";\nimport { useT } from \"@lattice-php/lattice/i18n\";\nimport { useEffect, useId, useMemo, useRef, useState } from \"react\";\nimport { FormFieldFrame } from \"@lattice-php/lattice/form/components/base/field\";\nimport { useFormContext } from \"@lattice-php/lattice/form/hooks/context\";\nimport { useDependentField } from \"@lattice-php/lattice/form/hooks/use-dependent-field\";\nimport { useFieldScope } from \"@lattice-php/lattice/form/hooks/field-scope\";\nimport { useFormValues, useSetFormValue } from \"@lattice-php/lattice/form/hooks/values\";\n\ntype Item = {\n id: string;\n name: string;\n size: number | null;\n status: \"ready\" | \"uploading\" | \"error\";\n progress: number;\n file?: File;\n key?: string;\n url?: string | null;\n token?: string;\n existing: boolean;\n};\n\nfunction uploadValueEquals(current: unknown, next: string[] | string): boolean {\n if (Array.isArray(next)) {\n return (\n Array.isArray(current) &&\n current.length === next.length &&\n current.every((value, index) => value === next[index])\n );\n }\n\n return current === next;\n}\n\nexport const FileUploadComponent: RendererComponent<\"field.file-upload\"> = ({ node }) => {\n const { t } = useT(\"lattice\");\n const props = node.props;\n const { hidden, required, readOnly, disabled } = useDependentField(node);\n const { action, componentRef, errors } = useFormContext();\n const name = props.name;\n const scope = useFieldScope();\n const domName = scope ? scope.scopedName(name) : name;\n const errorKey = scope ? scope.errorKey(name) : name;\n const uploadKey = errorKey;\n const values = useFormValues();\n const setValue = useSetFormValue();\n const inputId = useId();\n const fileInputRef = useRef<HTMLInputElement>(null);\n const previewUrlsRef = useRef<Set<string>>(new Set());\n const locked = readOnly || disabled;\n const signed = props.signed;\n const multiple = props.multiple;\n const fieldName = multiple ? `${domName}[]` : domName;\n\n const initial = useMemo<Item[]>(\n () =>\n (props.files ?? []).map((file) => ({\n id: crypto.randomUUID(),\n name: file.name,\n size: file.size,\n status: \"ready\" as const,\n progress: 100,\n key: file.key,\n url: file.url,\n token: file.token,\n existing: true,\n })),\n [props.files],\n );\n const [items, setItems] = useState<Item[]>(initial);\n const [removedTokens, setRemovedTokens] = useState<string[]>([]);\n\n useEffect(() => {\n if (!signed) {\n return;\n }\n\n const keys = items\n .filter((item) => !item.existing && item.key && item.status === \"ready\")\n .map((item) => item.key as string);\n const next = multiple ? keys : (keys[0] ?? \"\");\n\n if (scope) {\n if (!uploadValueEquals(scope.getValue(name), next)) {\n scope.setValue(name, next);\n }\n\n return;\n }\n\n setValue(name, next);\n }, [items, multiple, name, scope, setValue, signed]);\n\n useEffect(() => {\n if (!signed || scope) {\n return;\n }\n\n setValue(`${name}__removed`, removedTokens);\n }, [name, removedTokens, scope, setValue, signed]);\n\n useEffect(\n () => () => {\n previewUrlsRef.current.forEach((url) => URL.revokeObjectURL(url));\n previewUrlsRef.current.clear();\n },\n [],\n );\n\n const multipartFiles = useMemo(\n () => items.filter((item) => item.file && !item.existing).map((item) => item.file as File),\n [items],\n );\n useEffect(() => {\n if (signed || !fileInputRef.current) {\n return;\n }\n\n const transfer = new DataTransfer();\n multipartFiles.forEach((file) => transfer.items.add(file));\n fileInputRef.current.files = transfer.files;\n }, [multipartFiles, signed]);\n\n function createPreviewUrl(file: File): string | undefined {\n if (!props.image) {\n return undefined;\n }\n\n const url = URL.createObjectURL(file);\n previewUrlsRef.current.add(url);\n\n return url;\n }\n\n function revokePreviewUrl(item: Item): void {\n if (!item.url || !previewUrlsRef.current.has(item.url)) {\n return;\n }\n\n URL.revokeObjectURL(item.url);\n previewUrlsRef.current.delete(item.url);\n }\n\n async function signAndUpload(item: Item, file: File): Promise<void> {\n const markFailed = (): void => {\n setItems((prev) =>\n prev.map((entry) => (entry.id === item.id ? { ...entry, status: \"error\" } : entry)),\n );\n };\n\n const response = await requestSignedUpload(action, {\n ref: componentRef,\n target: uploadKey,\n filename: file.name,\n contentType: file.type,\n values,\n });\n\n if (!response.ok) {\n markFailed();\n\n return;\n }\n\n const sign = (await response.json()) as SignedUpload;\n\n try {\n const put = await xhrTransfer({\n url: sign.url,\n method: sign.method.toUpperCase(),\n body: file,\n headers: sign.headers,\n onProgress: (progress) =>\n setItems((prev) =>\n prev.map((entry) => (entry.id === item.id ? { ...entry, progress } : entry)),\n ),\n });\n\n setItems((prev) =>\n prev.map((entry) =>\n entry.id === item.id\n ? {\n ...entry,\n status: put.ok ? \"ready\" : \"error\",\n key: sign.key,\n progress: 100,\n }\n : entry,\n ),\n );\n } catch {\n markFailed();\n }\n }\n\n function addFiles(fileList: FileList | null): void {\n if (!fileList || locked) {\n return;\n }\n\n const incoming = Array.from(fileList);\n const next = incoming.map<Item>((file) => ({\n id: crypto.randomUUID(),\n name: file.name,\n size: file.size,\n status: signed ? \"uploading\" : \"ready\",\n progress: 0,\n file,\n url: createPreviewUrl(file),\n existing: false,\n }));\n\n if (!multiple) {\n items.forEach(revokePreviewUrl);\n\n if (!scope) {\n const replacedTokens = items\n .filter((item) => item.existing && item.token)\n .map((item) => item.token as string);\n\n if (replacedTokens.length > 0) {\n setRemovedTokens((tokens) => [...tokens, ...replacedTokens]);\n }\n }\n }\n\n setItems((prev) => (multiple ? [...prev, ...next] : next));\n\n if (signed) {\n next.forEach((item, index) => void signAndUpload(item, incoming[index]));\n }\n }\n\n function removeItem(id: string): void {\n const target = items.find((item) => item.id === id);\n\n if (target) {\n revokePreviewUrl(target);\n }\n\n if (target?.existing && target.token && !scope) {\n setRemovedTokens((tokens) => [...tokens, target.token as string]);\n }\n\n setItems((prev) => prev.filter((i) => i.id !== id));\n }\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 <div\n className=\"flex flex-col gap-3 rounded-lt-sm border border-dashed border-lt-border bg-lt-surface px-4 py-6\"\n data-test={testIdentity(name)}\n onDragOver={(event) => event.preventDefault()}\n onDrop={(event) => {\n event.preventDefault();\n addFiles(event.dataTransfer.files);\n }}\n >\n <button\n className=\"text-sm text-lt-muted-fg\"\n disabled={locked}\n onClick={() => fileInputRef.current?.click()}\n type=\"button\"\n >\n {t(\"form.file-upload.dropzone\", \"Drop files here or click to browse\")}\n </button>\n\n <ul\n className={props.image ? \"grid grid-cols-1 gap-3 sm:grid-cols-2\" : \"flex flex-col gap-2\"}\n >\n {items.map((item) => (\n <li\n className={\n props.image\n ? \"flex min-w-0 items-center gap-3 rounded-lt-sm border border-lt-border bg-lt-bg p-2 text-sm\"\n : \"flex items-center justify-between gap-3 text-sm\"\n }\n key={item.id}\n >\n {props.image && item.url ? (\n <img\n alt={item.name}\n className=\"size-16 shrink-0 rounded-lt-sm border border-lt-border object-cover\"\n data-test={testIdentity(`${name}-preview`)}\n src={item.url}\n />\n ) : null}\n <div className=\"min-w-0 flex-1\">\n <span className=\"block truncate\" data-test={testIdentity(`${name}-item`)}>\n {item.name}\n </span>\n {item.status === \"uploading\" && (\n <span className=\"text-xs text-lt-muted-fg\">{item.progress}%</span>\n )}\n {item.status === \"error\" && (\n <span className=\"text-xs text-lt-danger\">\n {t(\"form.file-upload.failed\", \"Failed\")}\n </span>\n )}\n </div>\n {(!item.existing || !scope) && (\n <IconButton\n size=\"sm\"\n icon=\"x\"\n label={t(\"form.file-upload.remove\", \"Remove {{name}}\", { name: item.name })}\n data-test={testIdentity(\n item.existing ? `${name}-remove-existing` : `${name}-remove`,\n )}\n disabled={locked}\n onClick={() => removeItem(item.id)}\n />\n )}\n {signed && !item.existing && item.key && item.status === \"ready\" && (\n <input\n data-test={testIdentity(`${name}-uploaded`)}\n name={fieldName}\n type=\"hidden\"\n value={item.key}\n />\n )}\n </li>\n ))}\n </ul>\n\n {!scope &&\n removedTokens.map((token) => (\n <input key={token} name={`${name}__removed[]`} type=\"hidden\" value={token} />\n ))}\n\n <input\n accept={props.accept ?? undefined}\n aria-label={props.label ?? name}\n className=\"sr-only\"\n data-test={testIdentity(`${name}-input`)}\n id={inputId}\n multiple={multiple}\n name={signed ? undefined : fieldName}\n onChange={(event) => {\n addFiles(event.target.files);\n if (signed) {\n event.target.value = \"\";\n }\n }}\n ref={fileInputRef}\n type=\"file\"\n />\n </div>\n </FormFieldFrame>\n );\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"file-upload.js","names":[],"sources":["../../../../resources/js/form/components/fields/file-upload.tsx"],"sourcesContent":["import { testIdentity } from \"@lattice-php/lattice/core/test-id\";\nimport { requestSignedUpload, xhrTransfer } from \"@lattice-php/lattice/core/upload\";\nimport type { RendererComponent } from \"@lattice-php/lattice/core/types\";\nimport type { SignedUpload } from \"@lattice-php/lattice/types/generated\";\nimport { IconButton } from \"@lattice-php/lattice/ui/icon-button\";\nimport { useT } from \"@lattice-php/lattice/i18n\";\nimport { useEffect, useId, useMemo, useRef, useState } from \"react\";\nimport { FormFieldFrame } from \"@lattice-php/lattice/form/components/base/field\";\nimport { useFormContext } from \"@lattice-php/lattice/form/hooks/context\";\nimport { useDependentField } from \"@lattice-php/lattice/form/hooks/use-dependent-field\";\nimport { useFieldScope } from \"@lattice-php/lattice/form/hooks/field-scope\";\nimport { useFormValues, useSetFormValue } from \"@lattice-php/lattice/form/hooks/values\";\n\ntype Item = {\n id: string;\n name: string;\n size: number | null;\n status: \"ready\" | \"uploading\" | \"error\";\n progress: number;\n file?: File;\n key?: string;\n url?: string | null;\n token?: string;\n existing: boolean;\n};\n\nfunction uploadValueEquals(current: unknown, next: string[] | string): boolean {\n if (Array.isArray(next)) {\n return (\n Array.isArray(current) &&\n current.length === next.length &&\n current.every((value, index) => value === next[index])\n );\n }\n\n return current === next;\n}\n\nexport const FileUploadComponent: RendererComponent<\"field.file-upload\"> = ({ node }) => {\n const { t } = useT(\"lattice\");\n const props = node.props;\n const { hidden, required, readOnly, disabled } = useDependentField(node);\n const { action, componentRef, errors } = useFormContext();\n const name = props.name;\n const scope = useFieldScope();\n const domName = scope ? scope.scopedName(name) : name;\n const errorKey = scope ? scope.errorKey(name) : name;\n const uploadKey = errorKey;\n const values = useFormValues();\n const setValue = useSetFormValue();\n const inputId = useId();\n const fileInputRef = useRef<HTMLInputElement>(null);\n const previewUrlsRef = useRef<Set<string>>(new Set());\n const locked = readOnly || disabled;\n const signed = props.signed;\n const multiple = props.multiple;\n const fieldName = multiple ? `${domName}[]` : domName;\n\n const initial = useMemo<Item[]>(\n () =>\n (props.files ?? []).map((file) => ({\n id: crypto.randomUUID(),\n name: file.name,\n size: file.size,\n status: \"ready\" as const,\n progress: 100,\n key: file.key,\n url: file.url,\n token: file.token,\n existing: true,\n })),\n [props.files],\n );\n const [items, setItems] = useState<Item[]>(initial);\n const [removedTokens, setRemovedTokens] = useState<string[]>([]);\n\n useEffect(() => {\n if (!signed) {\n return;\n }\n\n const keys = items\n .filter((item) => !item.existing && item.key && item.status === \"ready\")\n .map((item) => item.key as string);\n const next = multiple ? keys : (keys[0] ?? \"\");\n\n if (scope) {\n if (!uploadValueEquals(scope.getValue(name), next)) {\n scope.setValue(name, next);\n }\n\n return;\n }\n\n setValue(name, next);\n }, [items, multiple, name, scope, setValue, signed]);\n\n useEffect(() => {\n if (!signed || scope) {\n return;\n }\n\n setValue(`${name}__removed`, removedTokens);\n }, [name, removedTokens, scope, setValue, signed]);\n\n useEffect(\n () => () => {\n previewUrlsRef.current.forEach((url) => URL.revokeObjectURL(url));\n previewUrlsRef.current.clear();\n },\n [],\n );\n\n const multipartFiles = useMemo(\n () => items.filter((item) => item.file && !item.existing).map((item) => item.file as File),\n [items],\n );\n useEffect(() => {\n if (signed || !fileInputRef.current) {\n return;\n }\n\n const transfer = new DataTransfer();\n multipartFiles.forEach((file) => transfer.items.add(file));\n fileInputRef.current.files = transfer.files;\n }, [multipartFiles, signed]);\n\n function createPreviewUrl(file: File): string | undefined {\n if (!props.image) {\n return undefined;\n }\n\n const url = URL.createObjectURL(file);\n previewUrlsRef.current.add(url);\n\n return url;\n }\n\n function revokePreviewUrl(item: Item): void {\n if (!item.url || !previewUrlsRef.current.has(item.url)) {\n return;\n }\n\n URL.revokeObjectURL(item.url);\n previewUrlsRef.current.delete(item.url);\n }\n\n async function signAndUpload(item: Item, file: File): Promise<void> {\n const markFailed = (): void => {\n setItems((prev) =>\n prev.map((entry) => (entry.id === item.id ? { ...entry, status: \"error\" } : entry)),\n );\n };\n\n const response = await requestSignedUpload(action, {\n ref: componentRef,\n target: uploadKey,\n filename: file.name,\n contentType: file.type,\n values,\n });\n\n if (!response.ok) {\n markFailed();\n\n return;\n }\n\n const sign = (await response.json()) as SignedUpload;\n\n try {\n const put = await xhrTransfer({\n url: sign.url,\n method: sign.method.toUpperCase(),\n body: file,\n headers: sign.headers,\n onProgress: (progress) =>\n setItems((prev) =>\n prev.map((entry) => (entry.id === item.id ? { ...entry, progress } : entry)),\n ),\n });\n\n setItems((prev) =>\n prev.map((entry) =>\n entry.id === item.id\n ? {\n ...entry,\n status: put.ok ? \"ready\" : \"error\",\n key: sign.key,\n progress: 100,\n }\n : entry,\n ),\n );\n } catch {\n markFailed();\n }\n }\n\n function addFiles(fileList: FileList | null): void {\n if (!fileList || locked) {\n return;\n }\n\n const incoming = Array.from(fileList);\n const next = incoming.map<Item>((file) => ({\n id: crypto.randomUUID(),\n name: file.name,\n size: file.size,\n status: signed ? \"uploading\" : \"ready\",\n progress: 0,\n file,\n url: createPreviewUrl(file),\n existing: false,\n }));\n\n if (!multiple) {\n items.forEach(revokePreviewUrl);\n\n if (!scope) {\n const replacedTokens = items\n .filter((item) => item.existing && item.token)\n .map((item) => item.token as string);\n\n if (replacedTokens.length > 0) {\n setRemovedTokens((tokens) => [...tokens, ...replacedTokens]);\n }\n }\n }\n\n setItems((prev) => (multiple ? [...prev, ...next] : next));\n\n if (signed) {\n next.forEach((item, index) => void signAndUpload(item, incoming[index]));\n }\n }\n\n function removeItem(id: string): void {\n const target = items.find((item) => item.id === id);\n\n if (target) {\n revokePreviewUrl(target);\n }\n\n if (target?.existing && target.token && !scope) {\n setRemovedTokens((tokens) => [...tokens, target.token as string]);\n }\n\n setItems((prev) => prev.filter((i) => i.id !== id));\n }\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 id={inputId}\n required={required}\n >\n {(controlProps) => (\n <div\n className=\"flex flex-col gap-3 rounded-lt-sm border border-dashed border-lt-border bg-lt-surface px-4 py-6\"\n data-test={testIdentity(name)}\n onDragOver={(event) => event.preventDefault()}\n onDrop={(event) => {\n event.preventDefault();\n addFiles(event.dataTransfer.files);\n }}\n >\n <button\n className=\"text-sm text-lt-muted-fg\"\n disabled={locked}\n onClick={() => fileInputRef.current?.click()}\n type=\"button\"\n >\n {t(\"form.file-upload.dropzone\", \"Drop files here or click to browse\")}\n </button>\n\n <ul\n className={\n props.image ? \"grid grid-cols-1 gap-3 sm:grid-cols-2\" : \"flex flex-col gap-2\"\n }\n >\n {items.map((item) => (\n <li\n className={\n props.image\n ? \"flex min-w-0 items-center gap-3 rounded-lt-sm border border-lt-border bg-lt-bg p-2 text-sm\"\n : \"flex items-center justify-between gap-3 text-sm\"\n }\n key={item.id}\n >\n {props.image && item.url ? (\n <img\n alt={item.name}\n className=\"size-16 shrink-0 rounded-lt-sm border border-lt-border object-cover\"\n data-test={testIdentity(`${name}-preview`)}\n src={item.url}\n />\n ) : null}\n <div className=\"min-w-0 flex-1\">\n <span className=\"block truncate\" data-test={testIdentity(`${name}-item`)}>\n {item.name}\n </span>\n {item.status === \"uploading\" && (\n <span className=\"text-xs text-lt-muted-fg\">{item.progress}%</span>\n )}\n {item.status === \"error\" && (\n <span className=\"text-xs text-lt-danger\">\n {t(\"form.file-upload.failed\", \"Failed\")}\n </span>\n )}\n </div>\n {(!item.existing || !scope) && (\n <IconButton\n size=\"sm\"\n icon=\"x\"\n label={t(\"form.file-upload.remove\", \"Remove {{name}}\", { name: item.name })}\n data-test={testIdentity(\n item.existing ? `${name}-remove-existing` : `${name}-remove`,\n )}\n disabled={locked}\n onClick={() => removeItem(item.id)}\n />\n )}\n {signed && !item.existing && item.key && item.status === \"ready\" && (\n <input\n data-test={testIdentity(`${name}-uploaded`)}\n name={fieldName}\n type=\"hidden\"\n value={item.key}\n />\n )}\n </li>\n ))}\n </ul>\n\n {!scope &&\n removedTokens.map((token) => (\n <input key={token} name={`${name}__removed[]`} type=\"hidden\" value={token} />\n ))}\n\n <input\n {...controlProps}\n accept={props.accept ?? undefined}\n aria-label={props.label ?? name}\n className=\"sr-only\"\n data-test={testIdentity(`${name}-input`)}\n multiple={multiple}\n name={signed ? undefined : fieldName}\n onChange={(event) => {\n addFiles(event.target.files);\n if (signed) {\n event.target.value = \"\";\n }\n }}\n ref={fileInputRef}\n type=\"file\"\n />\n </div>\n )}\n </FormFieldFrame>\n );\n};\n"],"mappings":"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"}
|
|
@@ -8,16 +8,16 @@ var NumberInputComponent = ({ node }) => {
|
|
|
8
8
|
return /* @__PURE__ */ jsx(SimpleField, {
|
|
9
9
|
node,
|
|
10
10
|
label: props.label ?? "",
|
|
11
|
-
children: ({ name, testId, value, readOnly, disabled, commit }) => {
|
|
11
|
+
children: ({ name, testId, value, readOnly, disabled, commit }, controlProps) => {
|
|
12
12
|
const onChange = (event) => commit(event.target.value);
|
|
13
13
|
return props.slider ? /* @__PURE__ */ jsxs("div", {
|
|
14
14
|
className: "flex items-center gap-3",
|
|
15
15
|
children: [/* @__PURE__ */ jsx("input", {
|
|
16
|
+
...controlProps,
|
|
16
17
|
"aria-label": props.label ?? "",
|
|
17
18
|
className: "h-2 w-full cursor-pointer appearance-none rounded-lt-sm bg-lt-muted accent-lt-primary disabled:cursor-not-allowed disabled:accent-lt-disabled",
|
|
18
19
|
"data-test": testId,
|
|
19
20
|
disabled: disabled || readOnly,
|
|
20
|
-
id: name,
|
|
21
21
|
max: props.max ?? void 0,
|
|
22
22
|
min: props.min ?? void 0,
|
|
23
23
|
name,
|
|
@@ -34,11 +34,11 @@ var NumberInputComponent = ({ node }) => {
|
|
|
34
34
|
prefix: props.prefix,
|
|
35
35
|
suffix: props.suffix,
|
|
36
36
|
children: (controlClassName) => /* @__PURE__ */ jsx(Input, {
|
|
37
|
+
...controlProps,
|
|
37
38
|
autoFocus: props.autoFocus ?? false,
|
|
38
39
|
className: controlClassName,
|
|
39
40
|
"data-test": testId,
|
|
40
41
|
disabled,
|
|
41
|
-
id: name,
|
|
42
42
|
max: props.max ?? void 0,
|
|
43
43
|
min: props.min ?? void 0,
|
|
44
44
|
name,
|