@lattice-php/lattice 0.8.0 → 0.10.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.js +16 -85
- package/dist/action/components/action.js.map +1 -1
- package/dist/action/use-action.d.ts +18 -0
- package/dist/action/use-action.js +90 -0
- package/dist/action/use-action.js.map +1 -0
- package/dist/core/components/control.d.ts +0 -1
- package/dist/core/components/control.js +0 -1
- package/dist/core/components/control.js.map +1 -1
- package/dist/core/components/fragment.js +4 -1
- package/dist/core/components/fragment.js.map +1 -1
- package/dist/core/components/icon.js +4 -1
- package/dist/core/components/icon.js.map +1 -1
- package/dist/core/components/link.js +24 -3
- package/dist/core/components/link.js.map +1 -1
- package/dist/core/components/text.js +4 -1
- package/dist/core/components/text.js.map +1 -1
- package/dist/core/renderer.d.ts +0 -2
- package/dist/core/renderer.js +0 -2
- package/dist/core/renderer.js.map +1 -1
- package/dist/effects/dispatch.d.ts +0 -1
- package/dist/effects/dispatch.js.map +1 -1
- package/dist/effects/registry.js +0 -1
- package/dist/effects/registry.js.map +1 -1
- package/dist/form/components/base/input-otp.d.ts +0 -1
- package/dist/form/components/base/input-otp.js +0 -1
- package/dist/form/components/base/input-otp.js.map +1 -1
- package/dist/form/components/field-props.d.ts +0 -1
- package/dist/form/components/field-props.js +0 -1
- package/dist/form/components/field-props.js.map +1 -1
- package/dist/form/components/fields/repeater-rows.d.ts +0 -2
- package/dist/form/components/fields/repeater-rows.js +0 -2
- package/dist/form/components/fields/repeater-rows.js.map +1 -1
- package/dist/form/components/fields/simple-field.d.ts +0 -1
- package/dist/form/components/fields/simple-field.js +0 -1
- package/dist/form/components/fields/simple-field.js.map +1 -1
- package/dist/form/components/fields/toggle.d.ts +2 -0
- package/dist/form/components/fields/toggle.js +65 -0
- package/dist/form/components/fields/toggle.js.map +1 -0
- package/dist/form/components/index.d.ts +1 -0
- package/dist/form/components/index.js +2 -1
- package/dist/form/components/use-controlled-field.d.ts +0 -1
- package/dist/form/components/use-controlled-field.js +0 -1
- package/dist/form/components/use-controlled-field.js.map +1 -1
- package/dist/form/index.js +2 -1
- package/dist/form/index.js.map +1 -1
- package/dist/index.js +3 -3
- package/dist/lattice.css +6 -0
- package/dist/layout/menu-item.js +21 -0
- package/dist/layout/menu-item.js.map +1 -1
- package/dist/lib/utils.js +11 -1
- package/dist/lib/utils.js.map +1 -1
- package/dist/table/components/cells/boolean-cell.d.ts +0 -1
- package/dist/table/components/cells/boolean-cell.js +0 -1
- package/dist/table/components/cells/boolean-cell.js.map +1 -1
- package/dist/table/components/cells/numeric.d.ts +0 -1
- package/dist/table/components/cells/numeric.js +0 -1
- package/dist/table/components/cells/numeric.js.map +1 -1
- package/dist/table/components/cells/stack-cell.d.ts +0 -1
- package/dist/table/components/cells/stack-cell.js +0 -1
- package/dist/table/components/cells/stack-cell.js.map +1 -1
- package/dist/table/registry.d.ts +0 -2
- package/dist/table/registry.js.map +1 -1
- package/dist/toast/callout.d.ts +0 -2
- package/dist/toast/callout.js +0 -2
- package/dist/toast/callout.js.map +1 -1
- package/dist/toast/toast.d.ts +0 -3
- package/dist/toast/toast.js +0 -3
- package/dist/toast/toast.js.map +1 -1
- package/dist/types/generated.d.ts +33 -2
- package/package.json +5 -2
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
export type RepeaterRow = Record<string, unknown>;
|
|
2
2
|
export declare const ROW_ID_KEY = "__rowId";
|
|
3
|
-
/** Stamp a stable client-only id on a row (no-op if it already has one). */
|
|
4
3
|
export declare function withRowId(row: RepeaterRow): RepeaterRow;
|
|
5
4
|
/** Ensure every row has a stable id; returns the SAME array reference if none were missing. */
|
|
6
5
|
export declare function ensureRowIds(rows: RepeaterRow[]): RepeaterRow[];
|
|
7
|
-
/** Seed the row list from a stored value, falling back to `defaultItems` blank rows. */
|
|
8
6
|
export declare function seedRows(value: unknown, defaultItems: number): RepeaterRow[];
|
|
9
7
|
export declare function addRow(rows: RepeaterRow[]): RepeaterRow[];
|
|
10
8
|
export declare function removeRow(rows: RepeaterRow[], index: number): RepeaterRow[];
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
//#region resources/js/form/components/fields/repeater-rows.ts
|
|
2
2
|
var ROW_ID_KEY = "__rowId";
|
|
3
3
|
var rowIdCounter = 0;
|
|
4
|
-
/** Stamp a stable client-only id on a row (no-op if it already has one). */
|
|
5
4
|
function withRowId(row) {
|
|
6
5
|
return row["__rowId"] ? row : {
|
|
7
6
|
...row,
|
|
@@ -13,7 +12,6 @@ function ensureRowIds(rows) {
|
|
|
13
12
|
if (rows.every((row) => Boolean(row["__rowId"]))) return rows;
|
|
14
13
|
return rows.map(withRowId);
|
|
15
14
|
}
|
|
16
|
-
/** Seed the row list from a stored value, falling back to `defaultItems` blank rows. */
|
|
17
15
|
function seedRows(value, defaultItems) {
|
|
18
16
|
if (Array.isArray(value) && value.length > 0) return value.map((row) => row && typeof row === "object" ? { ...row } : {});
|
|
19
17
|
return Array.from({ length: Math.max(0, defaultItems) }, () => ({}));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"repeater-rows.js","names":[],"sources":["../../../../resources/js/form/components/fields/repeater-rows.ts"],"sourcesContent":["export type RepeaterRow = Record<string, unknown>;\n\nexport const ROW_ID_KEY = \"__rowId\";\n\nlet rowIdCounter = 0;\n\
|
|
1
|
+
{"version":3,"file":"repeater-rows.js","names":[],"sources":["../../../../resources/js/form/components/fields/repeater-rows.ts"],"sourcesContent":["export type RepeaterRow = Record<string, unknown>;\n\nexport const ROW_ID_KEY = \"__rowId\";\n\nlet rowIdCounter = 0;\n\nexport function withRowId(row: RepeaterRow): RepeaterRow {\n return row[ROW_ID_KEY] ? row : { ...row, [ROW_ID_KEY]: `r${rowIdCounter++}` };\n}\n\n/** Ensure every row has a stable id; returns the SAME array reference if none were missing. */\nexport function ensureRowIds(rows: RepeaterRow[]): RepeaterRow[] {\n if (rows.every((row) => Boolean(row[ROW_ID_KEY]))) {\n return rows;\n }\n return rows.map(withRowId);\n}\n\nexport function seedRows(value: unknown, defaultItems: number): RepeaterRow[] {\n if (Array.isArray(value) && value.length > 0) {\n return value.map((row) => (row && typeof row === \"object\" ? { ...(row as RepeaterRow) } : {}));\n }\n\n return Array.from({ length: Math.max(0, defaultItems) }, () => ({}));\n}\n\nexport function addRow(rows: RepeaterRow[]): RepeaterRow[] {\n return [...rows, {}];\n}\n\nexport function removeRow(rows: RepeaterRow[], index: number): RepeaterRow[] {\n return rows.filter((_, i) => i !== index);\n}\n\nexport function duplicateRow(rows: RepeaterRow[], index: number): RepeaterRow[] {\n const source = rows[index];\n if (!source) {\n return rows;\n }\n\n const { [ROW_ID_KEY]: _id, ...copy } = source;\n return [...rows.slice(0, index + 1), withRowId(copy), ...rows.slice(index + 1)];\n}\n\nexport function moveRow(rows: RepeaterRow[], from: number, to: number): RepeaterRow[] {\n const next = [...rows];\n const [moved] = next.splice(from, 1);\n next.splice(to, 0, moved);\n return next;\n}\n"],"mappings":";AAEA,IAAa,aAAa;AAE1B,IAAI,eAAe;AAEnB,SAAgB,UAAU,KAA+B;CACvD,OAAO,IAAA,aAAkB,MAAM;EAAE,GAAG;GAAM,aAAa,IAAI;CAAiB;AAC9E;;AAGA,SAAgB,aAAa,MAAoC;CAC/D,IAAI,KAAK,OAAO,QAAQ,QAAQ,IAAA,UAAe,CAAC,GAC9C,OAAO;CAET,OAAO,KAAK,IAAI,SAAS;AAC3B;AAEA,SAAgB,SAAS,OAAgB,cAAqC;CAC5E,IAAI,MAAM,QAAQ,KAAK,KAAK,MAAM,SAAS,GACzC,OAAO,MAAM,KAAK,QAAS,OAAO,OAAO,QAAQ,WAAW,EAAE,GAAI,IAAoB,IAAI,CAAC,CAAE;CAG/F,OAAO,MAAM,KAAK,EAAE,QAAQ,KAAK,IAAI,GAAG,YAAY,EAAE,UAAU,CAAC,EAAE;AACrE;AAEA,SAAgB,OAAO,MAAoC;CACzD,OAAO,CAAC,GAAG,MAAM,CAAC,CAAC;AACrB;AAEA,SAAgB,UAAU,MAAqB,OAA8B;CAC3E,OAAO,KAAK,QAAQ,GAAG,MAAM,MAAM,KAAK;AAC1C;AAEA,SAAgB,aAAa,MAAqB,OAA8B;CAC9E,MAAM,SAAS,KAAK;CACpB,IAAI,CAAC,QACH,OAAO;CAGT,MAAM,GAAG,aAAa,KAAK,GAAG,SAAS;CACvC,OAAO;EAAC,GAAG,KAAK,MAAM,GAAG,QAAQ,CAAC;EAAG,UAAU,IAAI;EAAG,GAAG,KAAK,MAAM,QAAQ,CAAC;CAAC;AAChF;AAEA,SAAgB,QAAQ,MAAqB,MAAc,IAA2B;CACpF,MAAM,OAAO,CAAC,GAAG,IAAI;CACrB,MAAM,CAAC,SAAS,KAAK,OAAO,MAAM,CAAC;CACnC,KAAK,OAAO,IAAI,GAAG,KAAK;CACxB,OAAO;AACT"}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { ReactNode } from 'react';
|
|
2
2
|
import { Node } from '../../../core/types';
|
|
3
3
|
import { ControlledField } from '../use-controlled-field';
|
|
4
|
-
/** The shared shell for single-input fields; the control is a render prop receiving the resolved field state. */
|
|
5
4
|
export declare function SimpleField({ node, label, children, }: {
|
|
6
5
|
node: Node;
|
|
7
6
|
label: string;
|
|
@@ -3,7 +3,6 @@ import { FormFieldFrame } from "../base/field.js";
|
|
|
3
3
|
import { useControlledField } from "../use-controlled-field.js";
|
|
4
4
|
import { jsx } from "react/jsx-runtime";
|
|
5
5
|
//#region resources/js/form/components/fields/simple-field.tsx
|
|
6
|
-
/** The shared shell for single-input fields; the control is a render prop receiving the resolved field state. */
|
|
7
6
|
function SimpleField({ node, label, children }) {
|
|
8
7
|
const field = useControlledField(node);
|
|
9
8
|
if (field.hidden) return null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"simple-field.js","names":[],"sources":["../../../../resources/js/form/components/fields/simple-field.tsx"],"sourcesContent":["import type { ReactNode } from \"react\";\nimport type { Node } from \"@lattice-php/lattice/core/types\";\nimport { FormFieldFrame } from \"../base/field\";\nimport { fieldProps } from \"../field-props\";\nimport { type ControlledField, useControlledField } from \"../use-controlled-field\";\n\
|
|
1
|
+
{"version":3,"file":"simple-field.js","names":[],"sources":["../../../../resources/js/form/components/fields/simple-field.tsx"],"sourcesContent":["import type { ReactNode } from \"react\";\nimport type { Node } from \"@lattice-php/lattice/core/types\";\nimport { FormFieldFrame } from \"../base/field\";\nimport { fieldProps } from \"../field-props\";\nimport { type ControlledField, useControlledField } from \"../use-controlled-field\";\n\nexport function SimpleField({\n node,\n label,\n children,\n}: {\n node: Node;\n label: string;\n children: (field: ControlledField) => ReactNode;\n}) {\n const field = useControlledField(node);\n\n if (field.hidden) {\n return null;\n }\n\n return (\n <FormFieldFrame\n error={field.error}\n helperText={fieldProps(node).helperText ?? undefined}\n tooltip={fieldProps(node).tooltip ?? undefined}\n label={label}\n name={field.name}\n required={field.required}\n >\n {children(field)}\n </FormFieldFrame>\n );\n}\n"],"mappings":";;;;;AAMA,SAAgB,YAAY,EAC1B,MACA,OACA,YAKC;CACD,MAAM,QAAQ,mBAAmB,IAAI;CAErC,IAAI,MAAM,QACR,OAAO;CAGT,OACE,oBAAC,gBAAD;EACE,OAAO,MAAM;EACb,YAAY,WAAW,IAAI,EAAE,cAAc,KAAA;EAC3C,SAAS,WAAW,IAAI,EAAE,WAAW,KAAA;EAC9B;EACP,MAAM,MAAM;EACZ,UAAU,MAAM;YAEf,SAAS,KAAK;CACD,CAAA;AAEpB"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { cn } from "../../../lib/utils.js";
|
|
2
|
+
import { testIdentity } from "../../../core/test-id.js";
|
|
3
|
+
import { useFormContext } from "../context.js";
|
|
4
|
+
import { useFieldScope } from "../field-scope.js";
|
|
5
|
+
import { useFormValue } from "../values.js";
|
|
6
|
+
import { toBoolean } from "../conditions.js";
|
|
7
|
+
import { FormFieldFrame } from "../base/field.js";
|
|
8
|
+
import { useDependentField } from "../use-dependent-field.js";
|
|
9
|
+
import { useFieldCommit } from "../use-field-commit.js";
|
|
10
|
+
import { useSeedDefault } from "../use-seed-default.js";
|
|
11
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
12
|
+
//#region resources/js/form/components/fields/toggle.tsx
|
|
13
|
+
var ToggleComponent = ({ node }) => {
|
|
14
|
+
const { hidden, required, readOnly, disabled } = useDependentField(node);
|
|
15
|
+
const props = node.props;
|
|
16
|
+
const localName = props.name;
|
|
17
|
+
const scope = useFieldScope();
|
|
18
|
+
const name = scope ? scope.scopedName(localName) : localName;
|
|
19
|
+
const errorKey = scope ? scope.errorKey(localName) : localName;
|
|
20
|
+
const globalValue = useFormValue(localName);
|
|
21
|
+
const storedValue = scope ? scope.getValue(localName) : globalValue;
|
|
22
|
+
const defaultChecked = toBoolean(props.value);
|
|
23
|
+
const checked = storedValue !== void 0 ? toBoolean(storedValue) : defaultChecked;
|
|
24
|
+
const locked = readOnly || disabled;
|
|
25
|
+
const { errors } = useFormContext();
|
|
26
|
+
const { commit } = useFieldCommit();
|
|
27
|
+
useSeedDefault(localName, defaultChecked);
|
|
28
|
+
if (hidden) return null;
|
|
29
|
+
return /* @__PURE__ */ jsxs(FormFieldFrame, {
|
|
30
|
+
error: errors[errorKey],
|
|
31
|
+
helperText: props.helperText ?? void 0,
|
|
32
|
+
tooltip: props.tooltip ?? void 0,
|
|
33
|
+
label: props.label ?? "",
|
|
34
|
+
name,
|
|
35
|
+
required,
|
|
36
|
+
children: [/* @__PURE__ */ jsx("input", {
|
|
37
|
+
disabled: locked,
|
|
38
|
+
name,
|
|
39
|
+
type: "hidden",
|
|
40
|
+
value: checked ? "1" : "0"
|
|
41
|
+
}), /* @__PURE__ */ jsx("button", {
|
|
42
|
+
"aria-checked": checked,
|
|
43
|
+
"aria-label": props.label ?? localName,
|
|
44
|
+
autoFocus: props.autoFocus ?? false,
|
|
45
|
+
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-[3px] focus-visible:ring-lt-ring/50 disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-lt-primary"),
|
|
46
|
+
"data-state": checked ? "checked" : "unchecked",
|
|
47
|
+
"data-test": testIdentity(localName),
|
|
48
|
+
disabled: locked,
|
|
49
|
+
id: name,
|
|
50
|
+
name,
|
|
51
|
+
onClick: () => commit(localName, !checked),
|
|
52
|
+
role: "switch",
|
|
53
|
+
tabIndex: props.tabIndex ?? void 0,
|
|
54
|
+
type: "button",
|
|
55
|
+
children: /* @__PURE__ */ jsx("span", {
|
|
56
|
+
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",
|
|
57
|
+
"data-state": checked ? "checked" : "unchecked"
|
|
58
|
+
})
|
|
59
|
+
})]
|
|
60
|
+
});
|
|
61
|
+
};
|
|
62
|
+
//#endregion
|
|
63
|
+
export { ToggleComponent };
|
|
64
|
+
|
|
65
|
+
//# sourceMappingURL=toggle.js.map
|
|
@@ -0,0 +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 \"../base/field\";\nimport { toBoolean } from \"../conditions\";\nimport { useFormContext } from \"../context\";\nimport { useFieldScope } from \"../field-scope\";\nimport { useDependentField } from \"../use-dependent-field\";\nimport { useFieldCommit } from \"../use-field-commit\";\nimport { useSeedDefault } from \"../use-seed-default\";\nimport { useFormValue } from \"../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 name = scope ? scope.scopedName(localName) : localName;\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 { errors } = useFormContext();\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-[3px] focus-visible:ring-lt-ring/50 disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-lt-primary\",\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":";;;;;;;;;;;;AAYA,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,OAAO,QAAQ,MAAM,WAAW,SAAS,IAAI;CACnD,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;CAClC,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,uUACF;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"}
|
|
@@ -12,3 +12,4 @@ export { RepeaterComponent } from './fields/repeater';
|
|
|
12
12
|
export { SelectComponent } from './fields/select';
|
|
13
13
|
export { TextareaComponent } from './fields/textarea';
|
|
14
14
|
export { TextInputComponent } from './fields/text-input';
|
|
15
|
+
export { ToggleComponent } from './fields/toggle';
|
|
@@ -12,4 +12,5 @@ import { RepeaterComponent } from "./fields/repeater.js";
|
|
|
12
12
|
import { SelectComponent } from "./fields/select.js";
|
|
13
13
|
import { TextareaComponent } from "./fields/textarea.js";
|
|
14
14
|
import { TextInputComponent } from "./fields/text-input.js";
|
|
15
|
-
|
|
15
|
+
import { ToggleComponent } from "./fields/toggle.js";
|
|
16
|
+
export { BuilderComponent, CheckboxComponent, ChoiceComponent, DateInputComponent, FileUploadComponent, FormComponent, HiddenInputComponent, NumberInputComponent, OtpInputComponent, PasswordInputComponent, RepeaterComponent, SelectComponent, TextInputComponent, TextareaComponent, ToggleComponent };
|
|
@@ -6,7 +6,6 @@ import { useFormValue } from "./values.js";
|
|
|
6
6
|
import { useDependentField } from "./use-dependent-field.js";
|
|
7
7
|
import { useFieldCommit } from "./use-field-commit.js";
|
|
8
8
|
//#region resources/js/form/components/use-controlled-field.ts
|
|
9
|
-
/** Shared wiring read by every store-controlled, condition-aware field. */
|
|
10
9
|
function useControlledField(node) {
|
|
11
10
|
const { errors } = useFormContext();
|
|
12
11
|
const scope = useFieldScope();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-controlled-field.js","names":[],"sources":["../../../resources/js/form/components/use-controlled-field.ts"],"sourcesContent":["import type { Node } from \"@lattice-php/lattice/core/types\";\nimport { testIdentity } from \"@lattice-php/lattice/core/test-id\";\nimport type { FieldState } from \"./conditions\";\nimport { fieldProps } from \"./field-props\";\nimport { useFieldScope } from \"./field-scope\";\nimport { useFormContext } from \"./context\";\nimport { useDependentField } from \"./use-dependent-field\";\nimport { useFieldCommit } from \"./use-field-commit\";\nimport { useFormValue } from \"./values\";\n\nexport type ControlledField = FieldState & {\n localName: string;\n name: string;\n testId?: string;\n value: string;\n error?: string;\n commit: (value: unknown) => void;\n};\n\
|
|
1
|
+
{"version":3,"file":"use-controlled-field.js","names":[],"sources":["../../../resources/js/form/components/use-controlled-field.ts"],"sourcesContent":["import type { Node } from \"@lattice-php/lattice/core/types\";\nimport { testIdentity } from \"@lattice-php/lattice/core/test-id\";\nimport type { FieldState } from \"./conditions\";\nimport { fieldProps } from \"./field-props\";\nimport { useFieldScope } from \"./field-scope\";\nimport { useFormContext } from \"./context\";\nimport { useDependentField } from \"./use-dependent-field\";\nimport { useFieldCommit } from \"./use-field-commit\";\nimport { useFormValue } from \"./values\";\n\nexport type ControlledField = FieldState & {\n localName: string;\n name: string;\n testId?: string;\n value: string;\n error?: string;\n commit: (value: unknown) => void;\n};\n\nexport function useControlledField(node: Node): ControlledField {\n const { errors } = useFormContext();\n const scope = useFieldScope();\n const state = useDependentField(node);\n const props = fieldProps(node);\n const localName = props.name ?? \"\";\n\n const globalValue = useFormValue(localName);\n const storedValue = scope ? scope.getValue(localName) : globalValue;\n const currentValue = storedValue !== undefined ? storedValue : props.value;\n const value =\n typeof currentValue === \"string\" || typeof currentValue === \"number\"\n ? String(currentValue)\n : \"\";\n\n const domName = scope ? scope.scopedName(localName) : localName;\n const errorKey = scope ? scope.errorKey(localName) : localName;\n\n const { commit: commitField } = useFieldCommit();\n const commit = (next: unknown): void => commitField(localName, next);\n\n return {\n ...state,\n localName,\n name: domName,\n testId: testIdentity(localName),\n value,\n error: errors[errorKey],\n commit,\n };\n}\n"],"mappings":";;;;;;;;AAmBA,SAAgB,mBAAmB,MAA6B;CAC9D,MAAM,EAAE,WAAW,eAAe;CAClC,MAAM,QAAQ,cAAc;CAC5B,MAAM,QAAQ,kBAAkB,IAAI;CACpC,MAAM,QAAQ,WAAW,IAAI;CAC7B,MAAM,YAAY,MAAM,QAAQ;CAEhC,MAAM,cAAc,aAAa,SAAS;CAC1C,MAAM,cAAc,QAAQ,MAAM,SAAS,SAAS,IAAI;CACxD,MAAM,eAAe,gBAAgB,KAAA,IAAY,cAAc,MAAM;CACrE,MAAM,QACJ,OAAO,iBAAiB,YAAY,OAAO,iBAAiB,WACxD,OAAO,YAAY,IACnB;CAEN,MAAM,UAAU,QAAQ,MAAM,WAAW,SAAS,IAAI;CACtD,MAAM,WAAW,QAAQ,MAAM,SAAS,SAAS,IAAI;CAErD,MAAM,EAAE,QAAQ,gBAAgB,eAAe;CAC/C,MAAM,UAAU,SAAwB,YAAY,WAAW,IAAI;CAEnE,OAAO;EACL,GAAG;EACH;EACA,MAAM;EACN,QAAQ,aAAa,SAAS;EAC9B;EACA,OAAO,OAAO;EACd;CACF;AACF"}
|
package/dist/form/index.js
CHANGED
|
@@ -26,7 +26,8 @@ var formComponents = createPlugin({
|
|
|
26
26
|
}),
|
|
27
27
|
"field.select": lazyComponent(loadFormComponent("SelectComponent")),
|
|
28
28
|
"field.textarea": lazyComponent(loadFormComponent("TextareaComponent")),
|
|
29
|
-
"field.text-input": lazyComponent(loadFormComponent("TextInputComponent"))
|
|
29
|
+
"field.text-input": lazyComponent(loadFormComponent("TextInputComponent")),
|
|
30
|
+
"field.toggle": lazyComponent(loadFormComponent("ToggleComponent"))
|
|
30
31
|
},
|
|
31
32
|
name: "lattice/form"
|
|
32
33
|
});
|
package/dist/form/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../resources/js/form/index.ts"],"sourcesContent":["import { createPlugin, lazyComponent } from \"@lattice-php/lattice/core/registry\";\nimport type { RendererComponent, RendererComponentModule } from \"@lattice-php/lattice/core/types\";\nimport { FormSkeletonComponent } from \"./skeleton\";\n\ntype FormComponentName =\n | \"BuilderComponent\"\n | \"CheckboxComponent\"\n | \"ChoiceComponent\"\n | \"DateInputComponent\"\n | \"FileUploadComponent\"\n | \"FormComponent\"\n | \"HiddenInputComponent\"\n | \"NumberInputComponent\"\n | \"OtpInputComponent\"\n | \"PasswordInputComponent\"\n | \"RepeaterComponent\"\n | \"SelectComponent\"\n | \"TextareaComponent\"\n | \"TextInputComponent\";\n\nconst loadFormComponents = () => import(\"./components\");\n\nfunction loadFormComponent<TType extends string>(\n name: FormComponentName,\n): () => Promise<RendererComponentModule<TType>> {\n return async () => {\n const components = await loadFormComponents();\n\n return {\n default: components[name] as unknown as RendererComponent<TType>,\n };\n };\n}\n\nexport const formComponents = createPlugin({\n components: {\n form: lazyComponent(loadFormComponent(\"FormComponent\"), {\n fallback: FormSkeletonComponent,\n }),\n \"field.builder\": lazyComponent(loadFormComponent(\"BuilderComponent\")),\n \"field.checkbox\": lazyComponent(loadFormComponent(\"CheckboxComponent\")),\n \"field.choice\": lazyComponent(loadFormComponent(\"ChoiceComponent\")),\n \"field.date-input\": lazyComponent(loadFormComponent(\"DateInputComponent\")),\n \"field.file-upload\": lazyComponent(loadFormComponent(\"FileUploadComponent\")),\n \"field.hidden-input\": lazyComponent(loadFormComponent(\"HiddenInputComponent\")),\n \"field.number-input\": lazyComponent(loadFormComponent(\"NumberInputComponent\")),\n \"field.otp\": lazyComponent(loadFormComponent(\"OtpInputComponent\")),\n \"field.password-input\": lazyComponent(loadFormComponent(\"PasswordInputComponent\")),\n \"field.repeater\": lazyComponent(loadFormComponent(\"RepeaterComponent\")),\n // Loaded from its own module so TipTap is split into a separate chunk,\n // only fetched on pages that actually render a rich editor.\n \"field.rich-editor\": lazyComponent<\"field.rich-editor\">(async () => {\n const { RichEditorComponent } = await import(\"./components/fields/rich-editor\");\n\n return { default: RichEditorComponent };\n }),\n \"field.select\": lazyComponent(loadFormComponent(\"SelectComponent\")),\n \"field.textarea\": lazyComponent(loadFormComponent(\"TextareaComponent\")),\n \"field.text-input\": lazyComponent(loadFormComponent(\"TextInputComponent\")),\n },\n name: \"lattice/form\",\n});\n"],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../resources/js/form/index.ts"],"sourcesContent":["import { createPlugin, lazyComponent } from \"@lattice-php/lattice/core/registry\";\nimport type { RendererComponent, RendererComponentModule } from \"@lattice-php/lattice/core/types\";\nimport { FormSkeletonComponent } from \"./skeleton\";\n\ntype FormComponentName =\n | \"BuilderComponent\"\n | \"CheckboxComponent\"\n | \"ChoiceComponent\"\n | \"DateInputComponent\"\n | \"FileUploadComponent\"\n | \"FormComponent\"\n | \"HiddenInputComponent\"\n | \"NumberInputComponent\"\n | \"OtpInputComponent\"\n | \"PasswordInputComponent\"\n | \"RepeaterComponent\"\n | \"SelectComponent\"\n | \"TextareaComponent\"\n | \"TextInputComponent\"\n | \"ToggleComponent\";\n\nconst loadFormComponents = () => import(\"./components\");\n\nfunction loadFormComponent<TType extends string>(\n name: FormComponentName,\n): () => Promise<RendererComponentModule<TType>> {\n return async () => {\n const components = await loadFormComponents();\n\n return {\n default: components[name] as unknown as RendererComponent<TType>,\n };\n };\n}\n\nexport const formComponents = createPlugin({\n components: {\n form: lazyComponent(loadFormComponent(\"FormComponent\"), {\n fallback: FormSkeletonComponent,\n }),\n \"field.builder\": lazyComponent(loadFormComponent(\"BuilderComponent\")),\n \"field.checkbox\": lazyComponent(loadFormComponent(\"CheckboxComponent\")),\n \"field.choice\": lazyComponent(loadFormComponent(\"ChoiceComponent\")),\n \"field.date-input\": lazyComponent(loadFormComponent(\"DateInputComponent\")),\n \"field.file-upload\": lazyComponent(loadFormComponent(\"FileUploadComponent\")),\n \"field.hidden-input\": lazyComponent(loadFormComponent(\"HiddenInputComponent\")),\n \"field.number-input\": lazyComponent(loadFormComponent(\"NumberInputComponent\")),\n \"field.otp\": lazyComponent(loadFormComponent(\"OtpInputComponent\")),\n \"field.password-input\": lazyComponent(loadFormComponent(\"PasswordInputComponent\")),\n \"field.repeater\": lazyComponent(loadFormComponent(\"RepeaterComponent\")),\n // Loaded from its own module so TipTap is split into a separate chunk,\n // only fetched on pages that actually render a rich editor.\n \"field.rich-editor\": lazyComponent<\"field.rich-editor\">(async () => {\n const { RichEditorComponent } = await import(\"./components/fields/rich-editor\");\n\n return { default: RichEditorComponent };\n }),\n \"field.select\": lazyComponent(loadFormComponent(\"SelectComponent\")),\n \"field.textarea\": lazyComponent(loadFormComponent(\"TextareaComponent\")),\n \"field.text-input\": lazyComponent(loadFormComponent(\"TextInputComponent\")),\n \"field.toggle\": lazyComponent(loadFormComponent(\"ToggleComponent\")),\n },\n name: \"lattice/form\",\n});\n"],"mappings":";;;AAqBA,IAAM,2BAA2B,OAAO;AAExC,SAAS,kBACP,MAC+C;CAC/C,OAAO,YAAY;EAGjB,OAAO,EACL,UAAS,MAHc,mBAAmB,GAGtB,MACtB;CACF;AACF;AAEA,IAAa,iBAAiB,aAAa;CACzC,YAAY;EACV,MAAM,cAAc,kBAAkB,eAAe,GAAG,EACtD,UAAU,sBACZ,CAAC;EACD,iBAAiB,cAAc,kBAAkB,kBAAkB,CAAC;EACpE,kBAAkB,cAAc,kBAAkB,mBAAmB,CAAC;EACtE,gBAAgB,cAAc,kBAAkB,iBAAiB,CAAC;EAClE,oBAAoB,cAAc,kBAAkB,oBAAoB,CAAC;EACzE,qBAAqB,cAAc,kBAAkB,qBAAqB,CAAC;EAC3E,sBAAsB,cAAc,kBAAkB,sBAAsB,CAAC;EAC7E,sBAAsB,cAAc,kBAAkB,sBAAsB,CAAC;EAC7E,aAAa,cAAc,kBAAkB,mBAAmB,CAAC;EACjE,wBAAwB,cAAc,kBAAkB,wBAAwB,CAAC;EACjF,kBAAkB,cAAc,kBAAkB,mBAAmB,CAAC;EAGtE,qBAAqB,cAAmC,YAAY;GAClE,MAAM,EAAE,wBAAwB,MAAM,OAAO;GAE7C,OAAO,EAAE,SAAS,oBAAoB;EACxC,CAAC;EACD,gBAAgB,cAAc,kBAAkB,iBAAiB,CAAC;EAClE,kBAAkB,cAAc,kBAAkB,mBAAmB,CAAC;EACtE,oBAAoB,cAAc,kBAAkB,oBAAoB,CAAC;EACzE,gBAAgB,cAAc,kBAAkB,iBAAiB,CAAC;CACpE;CACA,MAAM;AACR,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -12,14 +12,14 @@ import { onCallout } from "./toast/callout.js";
|
|
|
12
12
|
import { EventBridge } from "./events/event-bridge.js";
|
|
13
13
|
import Callouts from "./layout/callouts.js";
|
|
14
14
|
import { createPlugin, createRegistry, eagerComponent, extendRegistry, lazyComponent } from "./core/registry.js";
|
|
15
|
+
import { builtinEffectHandlers, effectHandler, mergeEffectHandlers } from "./effects/registry.js";
|
|
16
|
+
import { dispatchActionError, dispatchEffects, getActionEffects, isActionEffect } from "./effects/dispatch.js";
|
|
17
|
+
import { useEffectDispatcher } from "./effects/use-effect-dispatcher.js";
|
|
15
18
|
import { OutletContext } from "./layout/context.js";
|
|
16
19
|
import { layoutComponents } from "./layout/components.js";
|
|
17
20
|
import SchemaLayout from "./layout/schema-layout.js";
|
|
18
21
|
import { RealtimeListeners } from "./realtime/listeners.js";
|
|
19
22
|
import { createLayoutResolver, createPageResolver, pageComponentName, withVisitHeaders } from "./inertia.js";
|
|
20
|
-
import { builtinEffectHandlers, effectHandler, mergeEffectHandlers } from "./effects/registry.js";
|
|
21
|
-
import { dispatchActionError, dispatchEffects, getActionEffects, isActionEffect } from "./effects/dispatch.js";
|
|
22
|
-
import { useEffectDispatcher } from "./effects/use-effect-dispatcher.js";
|
|
23
23
|
import { useChat } from "./chat/use-chat.js";
|
|
24
24
|
import { chatPlugin } from "./chat/index.js";
|
|
25
25
|
import { registry } from "./registry.js";
|
package/dist/lattice.css
CHANGED
|
@@ -51,6 +51,9 @@
|
|
|
51
51
|
--lt-icon-md: 1rem;
|
|
52
52
|
--lt-icon-lg: 1.25rem;
|
|
53
53
|
--lt-icon-xl: 1.5rem;
|
|
54
|
+
--lt-icon-2xl: 2rem;
|
|
55
|
+
--lt-icon-3xl: 2.5rem;
|
|
56
|
+
--lt-icon-4xl: 3rem;
|
|
54
57
|
--lt-icon-stroke: 1.5;
|
|
55
58
|
|
|
56
59
|
/* Control heights — density lever */
|
|
@@ -192,6 +195,9 @@
|
|
|
192
195
|
--spacing-lt-icon-md: var(--lt-icon-md);
|
|
193
196
|
--spacing-lt-icon-lg: var(--lt-icon-lg);
|
|
194
197
|
--spacing-lt-icon-xl: var(--lt-icon-xl);
|
|
198
|
+
--spacing-lt-icon-2xl: var(--lt-icon-2xl);
|
|
199
|
+
--spacing-lt-icon-3xl: var(--lt-icon-3xl);
|
|
200
|
+
--spacing-lt-icon-4xl: var(--lt-icon-4xl);
|
|
195
201
|
--spacing-lt-control-sm: var(--lt-control-h-sm);
|
|
196
202
|
--spacing-lt-control-md: var(--lt-control-h-md);
|
|
197
203
|
--spacing-lt-control-lg: var(--lt-control-h-lg);
|
package/dist/layout/menu-item.js
CHANGED
|
@@ -4,6 +4,7 @@ import { IconRenderer } from "../icons/icon-renderer.js";
|
|
|
4
4
|
import { useCollapsed } from "../core/collapsed-context.js";
|
|
5
5
|
import { prefixedNodeTestId } from "../core/test-id.js";
|
|
6
6
|
import { Popover } from "./popover.js";
|
|
7
|
+
import { useAction } from "../action/use-action.js";
|
|
7
8
|
import { Link, usePage } from "@inertiajs/react";
|
|
8
9
|
import { useState } from "react";
|
|
9
10
|
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
@@ -48,6 +49,14 @@ var MenuItemComponent = ({ children, node }) => {
|
|
|
48
49
|
className: "ml-auto"
|
|
49
50
|
}) : null
|
|
50
51
|
] });
|
|
52
|
+
const action = node.props.action;
|
|
53
|
+
if (action && href === "" && !children) return /* @__PURE__ */ jsx(ActionMenuItem, {
|
|
54
|
+
action,
|
|
55
|
+
className: cn(rowClass, "w-full", collapsed && "group relative justify-center", iconOnly && "justify-center"),
|
|
56
|
+
label: collapsed || iconOnly ? label : void 0,
|
|
57
|
+
testId,
|
|
58
|
+
children: content
|
|
59
|
+
});
|
|
51
60
|
if (href === "") {
|
|
52
61
|
if (!children) return collapsed ? null : /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx("span", {
|
|
53
62
|
className: "flex items-center gap-2 px-3 py-2 text-xs font-semibold tracking-wide text-lt-muted-fg uppercase",
|
|
@@ -116,6 +125,18 @@ function FlyoutGroup({ children, icon, label, testId }) {
|
|
|
116
125
|
})
|
|
117
126
|
}) });
|
|
118
127
|
}
|
|
128
|
+
function ActionMenuItem({ action, children, className, label, testId }) {
|
|
129
|
+
const { processing, requestSubmit, overlays } = useAction(action);
|
|
130
|
+
return /* @__PURE__ */ jsxs("li", { children: [/* @__PURE__ */ jsx("button", {
|
|
131
|
+
"aria-label": label,
|
|
132
|
+
className,
|
|
133
|
+
"data-test": testId,
|
|
134
|
+
disabled: processing,
|
|
135
|
+
onClick: requestSubmit,
|
|
136
|
+
type: "button",
|
|
137
|
+
children
|
|
138
|
+
}), overlays] });
|
|
139
|
+
}
|
|
119
140
|
//#endregion
|
|
120
141
|
export { MenuItemComponent as default };
|
|
121
142
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"menu-item.js","names":[],"sources":["../../resources/js/layout/menu-item.tsx"],"sourcesContent":["import { Link, usePage } from \"@inertiajs/react\";\nimport { useState } from \"react\";\nimport type { ReactNode } from \"react\";\nimport { prefixedNodeTestId } from \"@lattice-php/lattice/core/test-id\";\nimport type { RendererComponent, Schema } from \"@lattice-php/lattice/core/types\";\nimport { Icon, IconRenderer } from \"@lattice-php/lattice/icons\";\nimport { cn } from \"@lattice-php/lattice/lib/utils\";\nimport type { Affix } from \"@lattice-php/lattice/types/generated\";\nimport { useSidebarCollapsed } from \"./context\";\nimport { Popover } from \"./popover\";\n\nconst rowClass =\n \"flex items-center gap-2 rounded-lt-sm px-3 py-2 text-base font-medium text-lt-fg transition-colors hover:bg-lt-muted\";\n\nfunction MenuAffix({ affix, className }: { affix: Affix; className?: string }) {\n if (affix.icon) {\n return <IconRenderer className={cn(\"size-lt-icon-md shrink-0\", className)} icon={affix.icon} />;\n }\n\n return <span className={cn(\"shrink-0 text-sm text-lt-muted-fg\", className)}>{affix.text}</span>;\n}\n\nfunction schemaContainsPath(schema: Schema | undefined, path: string): boolean {\n return (schema ?? []).some(\n (child) => child.props?.href === path || schemaContainsPath(child.schema, path),\n );\n}\n\nconst MenuItemComponent: RendererComponent<\"menu-item\"> = ({ children, node }) => {\n const collapsed = useSidebarCollapsed();\n const icon = node.props.icon;\n const label = node.props.label;\n const prefix = node.props.prefix;\n const suffix = node.props.suffix;\n const iconOnly = Boolean(icon);\n const flyoutIcon = icon ?? prefix?.icon ?? null;\n const href = node.props.href ?? \"\";\n const currentPath = usePage().url.split(\"?\")[0];\n const testId = prefixedNodeTestId(\"menu\", node);\n\n const content = icon ? (\n <IconRenderer className=\"size-lt-icon-md shrink-0\" icon={icon} />\n ) : (\n <>\n {prefix ? <MenuAffix affix={prefix} /> : null}\n {collapsed ? (\n <span\n className=\"pointer-events-none absolute top-1/2 left-full z-50 ml-2 hidden -translate-y-1/2 rounded-lt-sm border border-lt-border bg-lt-popover px-2 py-1 text-sm whitespace-nowrap text-lt-popover-fg shadow-lt-md group-hover:block\"\n role=\"tooltip\"\n >\n {label}\n </span>\n ) : (\n <span>{label}</span>\n )}\n {suffix ? <MenuAffix affix={suffix} className=\"ml-auto\" /> : null}\n </>\n );\n\n if (href === \"\") {\n if (!children) {\n return collapsed ? null : (\n <li>\n <span className=\"flex items-center gap-2 px-3 py-2 text-xs font-semibold tracking-wide text-lt-muted-fg uppercase\">\n {content}\n </span>\n </li>\n );\n }\n\n if (collapsed) {\n return (\n <FlyoutGroup icon={flyoutIcon} label={label} testId={testId}>\n {children}\n </FlyoutGroup>\n );\n }\n\n return (\n <CollapsibleItem\n content={content}\n defaultOpen={schemaContainsPath(node.schema, currentPath)}\n testId={testId}\n >\n {children}\n </CollapsibleItem>\n );\n }\n\n const active = currentPath === href;\n const method = node.props.method ?? \"get\";\n\n return (\n <li>\n <Link\n aria-current={active ? \"page\" : undefined}\n aria-label={collapsed || iconOnly ? label : undefined}\n as={method === \"get\" ? undefined : \"button\"}\n className={cn(\n rowClass,\n \"w-full\",\n collapsed && \"group relative justify-center\",\n iconOnly && \"justify-center\",\n active && \"bg-lt-muted font-medium\",\n )}\n data-test={testId}\n href={href}\n method={method}\n >\n {content}\n </Link>\n </li>\n );\n};\n\nfunction CollapsibleItem({\n children,\n content,\n defaultOpen,\n testId,\n}: {\n children: ReactNode;\n content: ReactNode;\n defaultOpen: boolean;\n testId?: string;\n}) {\n const [open, setOpen] = useState(defaultOpen);\n\n return (\n <li>\n <button\n aria-expanded={open}\n className={cn(rowClass, \"w-full\")}\n data-test={testId}\n onClick={() => setOpen((value) => !value)}\n type=\"button\"\n >\n {content}\n <Icon\n name=\"chevron-right\"\n className={cn(\n \"ml-auto size-lt-icon-md shrink-0 transition-transform\",\n open && \"rotate-90\",\n )}\n />\n </button>\n {open ? <ul className=\"mt-1 flex flex-col gap-1 pl-3\">{children}</ul> : null}\n </li>\n );\n}\n\nfunction FlyoutGroup({\n children,\n icon,\n label,\n testId,\n}: {\n children: ReactNode;\n icon?: string | null;\n label: string;\n testId?: string;\n}) {\n return (\n <li>\n <Popover\n className=\"min-w-48\"\n placement=\"right\"\n testId={testId}\n trigger={\n icon ? (\n <IconRenderer className=\"size-lt-icon-md shrink-0\" icon={icon} />\n ) : (\n <span>{label}</span>\n )\n }\n triggerClassName={cn(rowClass, \"justify-center\")}\n triggerLabel={label}\n >\n <ul className=\"flex flex-col gap-1\">\n <li className=\"px-3 py-1.5 text-xs font-semibold tracking-wide text-lt-muted-fg uppercase\">\n {label}\n </li>\n {children}\n </ul>\n </Popover>\n </li>\n );\n}\n\nexport default MenuItemComponent;\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"menu-item.js","names":[],"sources":["../../resources/js/layout/menu-item.tsx"],"sourcesContent":["import { Link, usePage } from \"@inertiajs/react\";\nimport { useState } from \"react\";\nimport type { ReactNode } from \"react\";\nimport { useAction } from \"@lattice-php/lattice/action/use-action\";\nimport { prefixedNodeTestId } from \"@lattice-php/lattice/core/test-id\";\nimport type { Node, RendererComponent, Schema } from \"@lattice-php/lattice/core/types\";\nimport { Icon, IconRenderer } from \"@lattice-php/lattice/icons\";\nimport { cn } from \"@lattice-php/lattice/lib/utils\";\nimport type { Affix } from \"@lattice-php/lattice/types/generated\";\nimport { useSidebarCollapsed } from \"./context\";\nimport { Popover } from \"./popover\";\n\nconst rowClass =\n \"flex items-center gap-2 rounded-lt-sm px-3 py-2 text-base font-medium text-lt-fg transition-colors hover:bg-lt-muted\";\n\nfunction MenuAffix({ affix, className }: { affix: Affix; className?: string }) {\n if (affix.icon) {\n return <IconRenderer className={cn(\"size-lt-icon-md shrink-0\", className)} icon={affix.icon} />;\n }\n\n return <span className={cn(\"shrink-0 text-sm text-lt-muted-fg\", className)}>{affix.text}</span>;\n}\n\nfunction schemaContainsPath(schema: Schema | undefined, path: string): boolean {\n return (schema ?? []).some(\n (child) => child.props?.href === path || schemaContainsPath(child.schema, path),\n );\n}\n\nconst MenuItemComponent: RendererComponent<\"menu-item\"> = ({ children, node }) => {\n const collapsed = useSidebarCollapsed();\n const icon = node.props.icon;\n const label = node.props.label;\n const prefix = node.props.prefix;\n const suffix = node.props.suffix;\n const iconOnly = Boolean(icon);\n const flyoutIcon = icon ?? prefix?.icon ?? null;\n const href = node.props.href ?? \"\";\n const currentPath = usePage().url.split(\"?\")[0];\n const testId = prefixedNodeTestId(\"menu\", node);\n\n const content = icon ? (\n <IconRenderer className=\"size-lt-icon-md shrink-0\" icon={icon} />\n ) : (\n <>\n {prefix ? <MenuAffix affix={prefix} /> : null}\n {collapsed ? (\n <span\n className=\"pointer-events-none absolute top-1/2 left-full z-50 ml-2 hidden -translate-y-1/2 rounded-lt-sm border border-lt-border bg-lt-popover px-2 py-1 text-sm whitespace-nowrap text-lt-popover-fg shadow-lt-md group-hover:block\"\n role=\"tooltip\"\n >\n {label}\n </span>\n ) : (\n <span>{label}</span>\n )}\n {suffix ? <MenuAffix affix={suffix} className=\"ml-auto\" /> : null}\n </>\n );\n\n const action = node.props.action;\n\n if (action && href === \"\" && !children) {\n return (\n <ActionMenuItem\n action={action as Node<\"action\">}\n className={cn(\n rowClass,\n \"w-full\",\n collapsed && \"group relative justify-center\",\n iconOnly && \"justify-center\",\n )}\n label={collapsed || iconOnly ? label : undefined}\n testId={testId}\n >\n {content}\n </ActionMenuItem>\n );\n }\n\n if (href === \"\") {\n if (!children) {\n return collapsed ? null : (\n <li>\n <span className=\"flex items-center gap-2 px-3 py-2 text-xs font-semibold tracking-wide text-lt-muted-fg uppercase\">\n {content}\n </span>\n </li>\n );\n }\n\n if (collapsed) {\n return (\n <FlyoutGroup icon={flyoutIcon} label={label} testId={testId}>\n {children}\n </FlyoutGroup>\n );\n }\n\n return (\n <CollapsibleItem\n content={content}\n defaultOpen={schemaContainsPath(node.schema, currentPath)}\n testId={testId}\n >\n {children}\n </CollapsibleItem>\n );\n }\n\n const active = currentPath === href;\n const method = node.props.method ?? \"get\";\n\n return (\n <li>\n <Link\n aria-current={active ? \"page\" : undefined}\n aria-label={collapsed || iconOnly ? label : undefined}\n as={method === \"get\" ? undefined : \"button\"}\n className={cn(\n rowClass,\n \"w-full\",\n collapsed && \"group relative justify-center\",\n iconOnly && \"justify-center\",\n active && \"bg-lt-muted font-medium\",\n )}\n data-test={testId}\n href={href}\n method={method}\n >\n {content}\n </Link>\n </li>\n );\n};\n\nfunction CollapsibleItem({\n children,\n content,\n defaultOpen,\n testId,\n}: {\n children: ReactNode;\n content: ReactNode;\n defaultOpen: boolean;\n testId?: string;\n}) {\n const [open, setOpen] = useState(defaultOpen);\n\n return (\n <li>\n <button\n aria-expanded={open}\n className={cn(rowClass, \"w-full\")}\n data-test={testId}\n onClick={() => setOpen((value) => !value)}\n type=\"button\"\n >\n {content}\n <Icon\n name=\"chevron-right\"\n className={cn(\n \"ml-auto size-lt-icon-md shrink-0 transition-transform\",\n open && \"rotate-90\",\n )}\n />\n </button>\n {open ? <ul className=\"mt-1 flex flex-col gap-1 pl-3\">{children}</ul> : null}\n </li>\n );\n}\n\nfunction FlyoutGroup({\n children,\n icon,\n label,\n testId,\n}: {\n children: ReactNode;\n icon?: string | null;\n label: string;\n testId?: string;\n}) {\n return (\n <li>\n <Popover\n className=\"min-w-48\"\n placement=\"right\"\n testId={testId}\n trigger={\n icon ? (\n <IconRenderer className=\"size-lt-icon-md shrink-0\" icon={icon} />\n ) : (\n <span>{label}</span>\n )\n }\n triggerClassName={cn(rowClass, \"justify-center\")}\n triggerLabel={label}\n >\n <ul className=\"flex flex-col gap-1\">\n <li className=\"px-3 py-1.5 text-xs font-semibold tracking-wide text-lt-muted-fg uppercase\">\n {label}\n </li>\n {children}\n </ul>\n </Popover>\n </li>\n );\n}\n\nfunction ActionMenuItem({\n action,\n children,\n className,\n label,\n testId,\n}: {\n action: Node<\"action\">;\n children: ReactNode;\n className: string;\n label?: string;\n testId?: string;\n}) {\n const { processing, requestSubmit, overlays } = useAction(action);\n\n return (\n <li>\n <button\n aria-label={label}\n className={className}\n data-test={testId}\n disabled={processing}\n onClick={requestSubmit}\n type=\"button\"\n >\n {children}\n </button>\n {overlays}\n </li>\n );\n}\n\nexport default MenuItemComponent;\n"],"mappings":";;;;;;;;;;;AAYA,IAAM,WACJ;AAEF,SAAS,UAAU,EAAE,OAAO,aAAmD;CAC7E,IAAI,MAAM,MACR,OAAO,oBAAC,cAAD;EAAc,WAAW,GAAG,4BAA4B,SAAS;EAAG,MAAM,MAAM;CAAO,CAAA;CAGhG,OAAO,oBAAC,QAAD;EAAM,WAAW,GAAG,qCAAqC,SAAS;YAAI,MAAM;CAAW,CAAA;AAChG;AAEA,SAAS,mBAAmB,QAA4B,MAAuB;CAC7E,QAAQ,UAAU,CAAC,GAAG,MACnB,UAAU,MAAM,OAAO,SAAS,QAAQ,mBAAmB,MAAM,QAAQ,IAAI,CAChF;AACF;AAEA,IAAM,qBAAqD,EAAE,UAAU,WAAW;CAChF,MAAM,YAAY,aAAoB;CACtC,MAAM,OAAO,KAAK,MAAM;CACxB,MAAM,QAAQ,KAAK,MAAM;CACzB,MAAM,SAAS,KAAK,MAAM;CAC1B,MAAM,SAAS,KAAK,MAAM;CAC1B,MAAM,WAAW,QAAQ,IAAI;CAC7B,MAAM,aAAa,QAAQ,QAAQ,QAAQ;CAC3C,MAAM,OAAO,KAAK,MAAM,QAAQ;CAChC,MAAM,cAAc,QAAQ,EAAE,IAAI,MAAM,GAAG,EAAE;CAC7C,MAAM,SAAS,mBAAmB,QAAQ,IAAI;CAE9C,MAAM,UAAU,OACd,oBAAC,cAAD;EAAc,WAAU;EAAiC;CAAO,CAAA,IAEhE,qBAAA,YAAA,EAAA,UAAA;EACG,SAAS,oBAAC,WAAD,EAAW,OAAO,OAAS,CAAA,IAAI;EACxC,YACC,oBAAC,QAAD;GACE,WAAU;GACV,MAAK;aAEJ;EACG,CAAA,IAEN,oBAAC,QAAD,EAAA,UAAO,MAAY,CAAA;EAEpB,SAAS,oBAAC,WAAD;GAAW,OAAO;GAAQ,WAAU;EAAW,CAAA,IAAI;CAC7D,EAAA,CAAA;CAGJ,MAAM,SAAS,KAAK,MAAM;CAE1B,IAAI,UAAU,SAAS,MAAM,CAAC,UAC5B,OACE,oBAAC,gBAAD;EACU;EACR,WAAW,GACT,UACA,UACA,aAAa,iCACb,YAAY,gBACd;EACA,OAAO,aAAa,WAAW,QAAQ,KAAA;EAC/B;YAEP;CACa,CAAA;CAIpB,IAAI,SAAS,IAAI;EACf,IAAI,CAAC,UACH,OAAO,YAAY,OACjB,oBAAC,MAAD,EAAA,UACE,oBAAC,QAAD;GAAM,WAAU;aACb;EACG,CAAA,EACJ,CAAA;EAIR,IAAI,WACF,OACE,oBAAC,aAAD;GAAa,MAAM;GAAmB;GAAe;GAClD;EACU,CAAA;EAIjB,OACE,oBAAC,iBAAD;GACW;GACT,aAAa,mBAAmB,KAAK,QAAQ,WAAW;GAChD;GAEP;EACc,CAAA;CAErB;CAEA,MAAM,SAAS,gBAAgB;CAC/B,MAAM,SAAS,KAAK,MAAM,UAAU;CAEpC,OACE,oBAAC,MAAD,EAAA,UACE,oBAAC,MAAD;EACE,gBAAc,SAAS,SAAS,KAAA;EAChC,cAAY,aAAa,WAAW,QAAQ,KAAA;EAC5C,IAAI,WAAW,QAAQ,KAAA,IAAY;EACnC,WAAW,GACT,UACA,UACA,aAAa,iCACb,YAAY,kBACZ,UAAU,yBACZ;EACA,aAAW;EACL;EACE;YAEP;CACG,CAAA,EACJ,CAAA;AAER;AAEA,SAAS,gBAAgB,EACvB,UACA,SACA,aACA,UAMC;CACD,MAAM,CAAC,MAAM,WAAW,SAAS,WAAW;CAE5C,OACE,qBAAC,MAAD,EAAA,UAAA,CACE,qBAAC,UAAD;EACE,iBAAe;EACf,WAAW,GAAG,UAAU,QAAQ;EAChC,aAAW;EACX,eAAe,SAAS,UAAU,CAAC,KAAK;EACxC,MAAK;YALP,CAOG,SACD,oBAAC,MAAD;GACE,MAAK;GACL,WAAW,GACT,yDACA,QAAQ,WACV;EACD,CAAA,CACK;KACP,OAAO,oBAAC,MAAD;EAAI,WAAU;EAAiC;CAAa,CAAA,IAAI,IACtE,EAAA,CAAA;AAER;AAEA,SAAS,YAAY,EACnB,UACA,MACA,OACA,UAMC;CACD,OACE,oBAAC,MAAD,EAAA,UACE,oBAAC,SAAD;EACE,WAAU;EACV,WAAU;EACF;EACR,SACE,OACE,oBAAC,cAAD;GAAc,WAAU;GAAiC;EAAO,CAAA,IAEhE,oBAAC,QAAD,EAAA,UAAO,MAAY,CAAA;EAGvB,kBAAkB,GAAG,UAAU,gBAAgB;EAC/C,cAAc;YAEd,qBAAC,MAAD;GAAI,WAAU;aAAd,CACE,oBAAC,MAAD;IAAI,WAAU;cACX;GACC,CAAA,GACH,QACC;;CACG,CAAA,EACP,CAAA;AAER;AAEA,SAAS,eAAe,EACtB,QACA,UACA,WACA,OACA,UAOC;CACD,MAAM,EAAE,YAAY,eAAe,aAAa,UAAU,MAAM;CAEhE,OACE,qBAAC,MAAD,EAAA,UAAA,CACE,oBAAC,UAAD;EACE,cAAY;EACD;EACX,aAAW;EACX,UAAU;EACV,SAAS;EACT,MAAK;EAEJ;CACK,CAAA,GACP,QACC,EAAA,CAAA;AAER"}
|
package/dist/lib/utils.js
CHANGED
|
@@ -1,6 +1,16 @@
|
|
|
1
1
|
import { clsx } from "clsx";
|
|
2
|
-
import {
|
|
2
|
+
import { extendTailwindMerge } from "tailwind-merge";
|
|
3
3
|
//#region resources/js/lib/utils.ts
|
|
4
|
+
var twMerge = extendTailwindMerge({ extend: { classGroups: { "lt-icon-size": [{ size: [{ lt: [{ icon: [
|
|
5
|
+
"xs",
|
|
6
|
+
"sm",
|
|
7
|
+
"md",
|
|
8
|
+
"lg",
|
|
9
|
+
"xl",
|
|
10
|
+
"2xl",
|
|
11
|
+
"3xl",
|
|
12
|
+
"4xl"
|
|
13
|
+
] }] }] }] } } });
|
|
4
14
|
function cn(...inputs) {
|
|
5
15
|
return twMerge(clsx(inputs));
|
|
6
16
|
}
|
package/dist/lib/utils.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.js","names":[],"sources":["../../resources/js/lib/utils.ts"],"sourcesContent":["import { clsx } from \"clsx\";\nimport type { ClassValue } from \"clsx\";\nimport {
|
|
1
|
+
{"version":3,"file":"utils.js","names":[],"sources":["../../resources/js/lib/utils.ts"],"sourcesContent":["import { clsx } from \"clsx\";\nimport type { ClassValue } from \"clsx\";\nimport { extendTailwindMerge } from \"tailwind-merge\";\n\n// The sprite renderer always applies `size-lt-icon-md` as a baseline, and these\n// custom utilities are invisible to tailwind-merge's stock config, so an explicit\n// `size-lt-icon-*` would otherwise be left to fight the baseline on source order.\n// Registering them as one conflicting group lets the explicit size always win.\nconst twMerge = extendTailwindMerge<\"lt-icon-size\">({\n extend: {\n classGroups: {\n \"lt-icon-size\": [\n { size: [{ lt: [{ icon: [\"xs\", \"sm\", \"md\", \"lg\", \"xl\", \"2xl\", \"3xl\", \"4xl\"] }] }] },\n ],\n },\n },\n});\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n"],"mappings":";;;AAQA,IAAM,UAAU,oBAAoC,EAClD,QAAQ,EACN,aAAa,EACX,gBAAgB,CACd,EAAE,MAAM,CAAC,EAAE,IAAI,CAAC,EAAE,MAAM;CAAC;CAAM;CAAM;CAAM;CAAM;CAAM;CAAO;CAAO;AAAK,EAAE,CAAC,EAAE,CAAC,EAAE,CACpF,EACF,EACF,EACF,CAAC;AAED,SAAgB,GAAG,GAAG,QAAsB;CAC1C,OAAO,QAAQ,KAAK,MAAM,CAAC;AAC7B"}
|
|
@@ -5,7 +5,6 @@ import { jsx } from "react/jsx-runtime";
|
|
|
5
5
|
function isTruthy(value) {
|
|
6
6
|
return value === true || value === 1 || value === "1" || value === "true";
|
|
7
7
|
}
|
|
8
|
-
/** Renders a boolean column as a check (truthy) or cross (falsy) icon. */
|
|
9
8
|
var BooleanCell = ({ value }) => {
|
|
10
9
|
const truthy = isTruthy(value);
|
|
11
10
|
return /* @__PURE__ */ jsx("span", {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"boolean-cell.js","names":[],"sources":["../../../../resources/js/table/components/cells/boolean-cell.tsx"],"sourcesContent":["import { Icon } from \"@lattice-php/lattice/icons\";\nimport { cn } from \"@lattice-php/lattice/lib/utils\";\nimport type { ColumnCellComponent } from \"../../registry\";\n\nfunction isTruthy(value: unknown): boolean {\n return value === true || value === 1 || value === \"1\" || value === \"true\";\n}\n\
|
|
1
|
+
{"version":3,"file":"boolean-cell.js","names":[],"sources":["../../../../resources/js/table/components/cells/boolean-cell.tsx"],"sourcesContent":["import { Icon } from \"@lattice-php/lattice/icons\";\nimport { cn } from \"@lattice-php/lattice/lib/utils\";\nimport type { ColumnCellComponent } from \"../../registry\";\n\nfunction isTruthy(value: unknown): boolean {\n return value === true || value === 1 || value === \"1\" || value === \"true\";\n}\n\nexport const BooleanCell: ColumnCellComponent<\"column.boolean\"> = ({ value }) => {\n const truthy = isTruthy(value);\n\n return (\n <span aria-label={String(truthy)} role=\"img\">\n <Icon\n name={truthy ? \"check\" : \"x\"}\n className={cn(\"size-lt-icon-md\", truthy ? \"text-lt-success\" : \"text-lt-muted-fg\")}\n />\n </span>\n );\n};\n"],"mappings":";;;;AAIA,SAAS,SAAS,OAAyB;CACzC,OAAO,UAAU,QAAQ,UAAU,KAAK,UAAU,OAAO,UAAU;AACrE;AAEA,IAAa,eAAsD,EAAE,YAAY;CAC/E,MAAM,SAAS,SAAS,KAAK;CAE7B,OACE,oBAAC,QAAD;EAAM,cAAY,OAAO,MAAM;EAAG,MAAK;YACrC,oBAAC,MAAD;GACE,MAAM,SAAS,UAAU;GACzB,WAAW,GAAG,mBAAmB,SAAS,oBAAoB,kBAAkB;EACjF,CAAA;CACG,CAAA;AAEV"}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
//#region resources/js/table/components/cells/numeric.ts
|
|
2
|
-
/** Parses a cell value to a finite number, or null when it isn't numeric. */
|
|
3
2
|
function numericValue(value) {
|
|
4
3
|
const number = typeof value === "number" ? value : Number(value);
|
|
5
4
|
return value !== null && value !== void 0 && value !== "" && !Number.isNaN(number) ? number : null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"numeric.js","names":[],"sources":["../../../../resources/js/table/components/cells/numeric.ts"],"sourcesContent":["
|
|
1
|
+
{"version":3,"file":"numeric.js","names":[],"sources":["../../../../resources/js/table/components/cells/numeric.ts"],"sourcesContent":["export function numericValue(value: unknown): number | null {\n const number = typeof value === \"number\" ? value : Number(value);\n\n return value !== null && value !== undefined && value !== \"\" && !Number.isNaN(number)\n ? number\n : null;\n}\n"],"mappings":";AAAA,SAAgB,aAAa,OAA+B;CAC1D,MAAM,SAAS,OAAO,UAAU,WAAW,QAAQ,OAAO,KAAK;CAE/D,OAAO,UAAU,QAAQ,UAAU,KAAA,KAAa,UAAU,MAAM,CAAC,OAAO,MAAM,MAAM,IAChF,SACA;AACN"}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { TextCell } from "./text-cell.js";
|
|
2
2
|
import { jsx } from "react/jsx-runtime";
|
|
3
3
|
//#region resources/js/table/components/cells/stack-cell.tsx
|
|
4
|
-
/** Renders a stack column's nested columns as stacked text rows. */
|
|
5
4
|
var StackCell = ({ column, row }) => /* @__PURE__ */ jsx("div", {
|
|
6
5
|
className: "grid gap-1",
|
|
7
6
|
children: (column.columns ?? []).map((stackedColumn) => /* @__PURE__ */ jsx("span", { children: /* @__PURE__ */ jsx(TextCell, {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stack-cell.js","names":[],"sources":["../../../../resources/js/table/components/cells/stack-cell.tsx"],"sourcesContent":["import type { ColumnCellComponent } from \"../../registry\";\nimport type { ColumnPropsOf } from \"../../types\";\nimport { TextCell } from \"./text-cell\";\n\
|
|
1
|
+
{"version":3,"file":"stack-cell.js","names":[],"sources":["../../../../resources/js/table/components/cells/stack-cell.tsx"],"sourcesContent":["import type { ColumnCellComponent } from \"../../registry\";\nimport type { ColumnPropsOf } from \"../../types\";\nimport { TextCell } from \"./text-cell\";\n\nexport const StackCell: ColumnCellComponent<\"column.stack\"> = ({ column, row }) => (\n <div className=\"grid gap-1\">\n {(column.columns ?? []).map((stackedColumn) => (\n <span key={stackedColumn.key}>\n <TextCell\n column={stackedColumn}\n props={(stackedColumn.props ?? {}) as ColumnPropsOf<\"column.text\">}\n row={row}\n value={row[stackedColumn.key]}\n />\n </span>\n ))}\n </div>\n);\n"],"mappings":";;;AAIA,IAAa,aAAkD,EAAE,QAAQ,UACvE,oBAAC,OAAD;CAAK,WAAU;YACX,OAAO,WAAW,CAAC,GAAG,KAAK,kBAC3B,oBAAC,QAAD,EAAA,UACE,oBAAC,UAAD;EACE,QAAQ;EACR,OAAQ,cAAc,SAAS,CAAC;EAC3B;EACL,OAAO,IAAI,cAAc;CAC1B,CAAA,EACG,GAPK,cAAc,GAOnB,CACP;AACE,CAAA"}
|
package/dist/table/registry.d.ts
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import { ReactNode } from 'react';
|
|
2
2
|
import { ColumnPropsOf, TableColumn, TableRow } from './types';
|
|
3
3
|
export type ColumnCellArgs<TType extends string = string> = {
|
|
4
|
-
/** The full wire column (key, label, type, nested columns). */
|
|
5
4
|
column: TableColumn;
|
|
6
|
-
/** The column's `props`, resolved to the type's shape. */
|
|
7
5
|
props: ColumnPropsOf<TType>;
|
|
8
6
|
row: TableRow;
|
|
9
7
|
value: unknown;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry.js","names":[],"sources":["../../resources/js/table/registry.ts"],"sourcesContent":["import type { ReactNode } from \"react\";\nimport type { ColumnPropsOf, TableColumn, TableRow } from \"./types\";\n\nexport type ColumnCellArgs<TType extends string = string> = {\n
|
|
1
|
+
{"version":3,"file":"registry.js","names":[],"sources":["../../resources/js/table/registry.ts"],"sourcesContent":["import type { ReactNode } from \"react\";\nimport type { ColumnPropsOf, TableColumn, TableRow } from \"./types\";\n\nexport type ColumnCellArgs<TType extends string = string> = {\n column: TableColumn;\n props: ColumnPropsOf<TType>;\n row: TableRow;\n value: unknown;\n};\n\nexport type ColumnCellComponent<TType extends string = string> = (\n args: ColumnCellArgs<TType>,\n) => ReactNode;\n\nexport type ColumnRegistry = Record<string, ColumnCellComponent>;\n\n/**\n * Registers a typed column cell, erasing the type parameter so it fits the\n * registry. Mirrors `eagerComponent`/`lazyComponent` for the component registry:\n * author against `ColumnCellComponent<\"my.type\">` for typed `props`, register\n * through this.\n */\nexport function columnCell<TType extends string>(\n cell: ColumnCellComponent<TType>,\n): ColumnCellComponent {\n return cell as ColumnCellComponent;\n}\n"],"mappings":";;;;;;;AAsBA,SAAgB,WACd,MACqB;CACrB,OAAO;AACT"}
|
package/dist/toast/callout.d.ts
CHANGED
|
@@ -1,6 +1,4 @@
|
|
|
1
1
|
import { Callout } from '../types/generated';
|
|
2
2
|
export type { Callout };
|
|
3
|
-
/** Coerce a raw callout value (effect detail `{ callout: {...} }`) into a Callout. */
|
|
4
3
|
export declare function normalizeCallout(detail: unknown): Callout | null;
|
|
5
|
-
/** Subscribe to the `lattice:callout` bus. Returns an unsubscribe function. */
|
|
6
4
|
export declare function onCallout(callback: (callout: Callout) => void): () => void;
|
package/dist/toast/callout.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { LATTICE_EVENT } from "../events/event-names.js";
|
|
2
2
|
import { isVariant } from "./toast.js";
|
|
3
3
|
//#region resources/js/toast/callout.ts
|
|
4
|
-
/** Coerce a raw callout value (effect detail `{ callout: {...} }`) into a Callout. */
|
|
5
4
|
function normalizeCallout(detail) {
|
|
6
5
|
if (typeof detail !== "object" || detail === null) return null;
|
|
7
6
|
const value = detail.callout;
|
|
@@ -16,7 +15,6 @@ function normalizeCallout(detail) {
|
|
|
16
15
|
variant: isVariant(callout.variant) ? callout.variant : "info"
|
|
17
16
|
};
|
|
18
17
|
}
|
|
19
|
-
/** Subscribe to the `lattice:callout` bus. Returns an unsubscribe function. */
|
|
20
18
|
function onCallout(callback) {
|
|
21
19
|
const listener = (event) => {
|
|
22
20
|
const callout = normalizeCallout(event.detail);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"callout.js","names":[],"sources":["../../resources/js/toast/callout.ts"],"sourcesContent":["import type { Callout } from \"@lattice-php/lattice/types/generated\";\nimport { LATTICE_EVENT } from \"@lattice-php/lattice/events/event-names\";\nimport { isVariant } from \"@lattice-php/lattice/toast/toast\";\n\nexport type { Callout };\n\
|
|
1
|
+
{"version":3,"file":"callout.js","names":[],"sources":["../../resources/js/toast/callout.ts"],"sourcesContent":["import type { Callout } from \"@lattice-php/lattice/types/generated\";\nimport { LATTICE_EVENT } from \"@lattice-php/lattice/events/event-names\";\nimport { isVariant } from \"@lattice-php/lattice/toast/toast\";\n\nexport type { Callout };\n\nexport function normalizeCallout(detail: unknown): Callout | null {\n if (typeof detail !== \"object\" || detail === null) {\n return null;\n }\n\n const value = (detail as { callout?: unknown }).callout;\n\n if (typeof value !== \"object\" || value === null) {\n return null;\n }\n\n const callout = value as Record<string, unknown>;\n\n if (typeof callout.message !== \"string\" || callout.message === \"\") {\n return null;\n }\n\n return {\n action: (callout.action as Callout[\"action\"]) ?? null,\n dismissible: callout.dismissible !== false,\n message: callout.message,\n title: typeof callout.title === \"string\" ? callout.title : null,\n variant: isVariant(callout.variant) ? callout.variant : \"info\",\n };\n}\n\nexport function onCallout(callback: (callout: Callout) => void): () => void {\n const listener = (event: Event): void => {\n const callout = normalizeCallout((event as CustomEvent).detail);\n\n if (callout) {\n callback(callout);\n }\n };\n\n window.addEventListener(LATTICE_EVENT.callout, listener);\n\n return () => window.removeEventListener(LATTICE_EVENT.callout, listener);\n}\n"],"mappings":";;;AAMA,SAAgB,iBAAiB,QAAiC;CAChE,IAAI,OAAO,WAAW,YAAY,WAAW,MAC3C,OAAO;CAGT,MAAM,QAAS,OAAiC;CAEhD,IAAI,OAAO,UAAU,YAAY,UAAU,MACzC,OAAO;CAGT,MAAM,UAAU;CAEhB,IAAI,OAAO,QAAQ,YAAY,YAAY,QAAQ,YAAY,IAC7D,OAAO;CAGT,OAAO;EACL,QAAS,QAAQ,UAAgC;EACjD,aAAa,QAAQ,gBAAgB;EACrC,SAAS,QAAQ;EACjB,OAAO,OAAO,QAAQ,UAAU,WAAW,QAAQ,QAAQ;EAC3D,SAAS,UAAU,QAAQ,OAAO,IAAI,QAAQ,UAAU;CAC1D;AACF;AAEA,SAAgB,UAAU,UAAkD;CAC1E,MAAM,YAAY,UAAuB;EACvC,MAAM,UAAU,iBAAkB,MAAsB,MAAM;EAE9D,IAAI,SACF,SAAS,OAAO;CAEpB;CAEA,OAAO,iBAAiB,cAAc,SAAS,QAAQ;CAEvD,aAAa,OAAO,oBAAoB,cAAc,SAAS,QAAQ;AACzE"}
|
package/dist/toast/toast.d.ts
CHANGED
|
@@ -6,9 +6,6 @@ export declare function isVariant(value: unknown): value is Variant;
|
|
|
6
6
|
* ToastMessage, defaulting optional fields, or null when it is malformed.
|
|
7
7
|
*/
|
|
8
8
|
export declare function normalizeToastMessage(value: unknown): ToastMessage | null;
|
|
9
|
-
/** Coerce a `lattice:toast` event detail (`{ toast: {...} }`) into a ToastMessage. */
|
|
10
9
|
export declare function normalizeToast(detail: unknown): ToastMessage | null;
|
|
11
|
-
/** Emit a toast onto the shared `lattice:toast` bus. */
|
|
12
10
|
export declare function showToast(toast: ToastMessage): void;
|
|
13
|
-
/** Subscribe to the shared toast bus. Returns an unsubscribe function. */
|
|
14
11
|
export declare function onToast(callback: (toast: ToastMessage) => void): () => void;
|
package/dist/toast/toast.js
CHANGED
|
@@ -29,17 +29,14 @@ function normalizeToastMessage(value) {
|
|
|
29
29
|
variant: isVariant(toast.variant) ? toast.variant : "success"
|
|
30
30
|
};
|
|
31
31
|
}
|
|
32
|
-
/** Coerce a `lattice:toast` event detail (`{ toast: {...} }`) into a ToastMessage. */
|
|
33
32
|
function normalizeToast(detail) {
|
|
34
33
|
if (typeof detail !== "object" || detail === null) return null;
|
|
35
34
|
return normalizeToastMessage(detail.toast);
|
|
36
35
|
}
|
|
37
|
-
/** Emit a toast onto the shared `lattice:toast` bus. */
|
|
38
36
|
function showToast(toast) {
|
|
39
37
|
if (typeof window === "undefined") return;
|
|
40
38
|
window.dispatchEvent(new CustomEvent(LATTICE_EVENT.toast, { detail: { toast } }));
|
|
41
39
|
}
|
|
42
|
-
/** Subscribe to the shared toast bus. Returns an unsubscribe function. */
|
|
43
40
|
function onToast(callback) {
|
|
44
41
|
const listener = (event) => {
|
|
45
42
|
const toast = normalizeToast(event.detail);
|
package/dist/toast/toast.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"toast.js","names":[],"sources":["../../resources/js/toast/toast.ts"],"sourcesContent":["import type { ToastMessage, Variant } from \"@lattice-php/lattice/types/generated\";\nimport { LATTICE_EVENT } from \"@lattice-php/lattice/events/event-names\";\nimport { isTranslatable } from \"@lattice-php/lattice/i18n/translatable\";\n\nexport type { ToastMessage, Variant };\n\nconst variants = [\"success\", \"info\", \"warning\", \"error\"] as const satisfies readonly Variant[];\n\nexport function isVariant(value: unknown): value is Variant {\n return variants.some((variant) => variant === value);\n}\n\n/**\n * Coerce a raw toast value (server flash payload or event detail) into a\n * ToastMessage, defaulting optional fields, or null when it is malformed.\n */\nexport function normalizeToastMessage(value: unknown): ToastMessage | null {\n if (typeof value !== \"object\" || value === null) {\n return null;\n }\n\n const toast = value as Record<string, unknown>;\n\n const rawMessage = toast.message;\n const message =\n typeof rawMessage === \"string\" ? rawMessage : isTranslatable(rawMessage) ? rawMessage : null;\n\n if (message === null || message === \"\") {\n return null;\n }\n\n return {\n action: (toast.action as ToastMessage[\"action\"]) ?? null,\n dismissible: toast.dismissible !== false,\n duration: typeof toast.duration === \"number\" ? toast.duration : null,\n message,\n persistent: toast.persistent === true,\n variant: isVariant(toast.variant) ? toast.variant : \"success\",\n };\n}\n\
|
|
1
|
+
{"version":3,"file":"toast.js","names":[],"sources":["../../resources/js/toast/toast.ts"],"sourcesContent":["import type { ToastMessage, Variant } from \"@lattice-php/lattice/types/generated\";\nimport { LATTICE_EVENT } from \"@lattice-php/lattice/events/event-names\";\nimport { isTranslatable } from \"@lattice-php/lattice/i18n/translatable\";\n\nexport type { ToastMessage, Variant };\n\nconst variants = [\"success\", \"info\", \"warning\", \"error\"] as const satisfies readonly Variant[];\n\nexport function isVariant(value: unknown): value is Variant {\n return variants.some((variant) => variant === value);\n}\n\n/**\n * Coerce a raw toast value (server flash payload or event detail) into a\n * ToastMessage, defaulting optional fields, or null when it is malformed.\n */\nexport function normalizeToastMessage(value: unknown): ToastMessage | null {\n if (typeof value !== \"object\" || value === null) {\n return null;\n }\n\n const toast = value as Record<string, unknown>;\n\n const rawMessage = toast.message;\n const message =\n typeof rawMessage === \"string\" ? rawMessage : isTranslatable(rawMessage) ? rawMessage : null;\n\n if (message === null || message === \"\") {\n return null;\n }\n\n return {\n action: (toast.action as ToastMessage[\"action\"]) ?? null,\n dismissible: toast.dismissible !== false,\n duration: typeof toast.duration === \"number\" ? toast.duration : null,\n message,\n persistent: toast.persistent === true,\n variant: isVariant(toast.variant) ? toast.variant : \"success\",\n };\n}\n\nexport function normalizeToast(detail: unknown): ToastMessage | null {\n if (typeof detail !== \"object\" || detail === null) {\n return null;\n }\n\n return normalizeToastMessage((detail as { toast?: unknown }).toast);\n}\n\nexport function showToast(toast: ToastMessage): void {\n if (typeof window === \"undefined\") {\n return;\n }\n\n window.dispatchEvent(new CustomEvent(LATTICE_EVENT.toast, { detail: { toast } }));\n}\n\nexport function onToast(callback: (toast: ToastMessage) => void): () => void {\n const listener = (event: Event): void => {\n const toast = normalizeToast((event as CustomEvent).detail);\n\n if (toast) {\n callback(toast);\n }\n };\n\n window.addEventListener(LATTICE_EVENT.toast, listener);\n\n return () => window.removeEventListener(LATTICE_EVENT.toast, listener);\n}\n"],"mappings":";;;AAMA,IAAM,WAAW;CAAC;CAAW;CAAQ;CAAW;AAAO;AAEvD,SAAgB,UAAU,OAAkC;CAC1D,OAAO,SAAS,MAAM,YAAY,YAAY,KAAK;AACrD;;;;;AAMA,SAAgB,sBAAsB,OAAqC;CACzE,IAAI,OAAO,UAAU,YAAY,UAAU,MACzC,OAAO;CAGT,MAAM,QAAQ;CAEd,MAAM,aAAa,MAAM;CACzB,MAAM,UACJ,OAAO,eAAe,WAAW,aAAa,eAAe,UAAU,IAAI,aAAa;CAE1F,IAAI,YAAY,QAAQ,YAAY,IAClC,OAAO;CAGT,OAAO;EACL,QAAS,MAAM,UAAqC;EACpD,aAAa,MAAM,gBAAgB;EACnC,UAAU,OAAO,MAAM,aAAa,WAAW,MAAM,WAAW;EAChE;EACA,YAAY,MAAM,eAAe;EACjC,SAAS,UAAU,MAAM,OAAO,IAAI,MAAM,UAAU;CACtD;AACF;AAEA,SAAgB,eAAe,QAAsC;CACnE,IAAI,OAAO,WAAW,YAAY,WAAW,MAC3C,OAAO;CAGT,OAAO,sBAAuB,OAA+B,KAAK;AACpE;AAEA,SAAgB,UAAU,OAA2B;CACnD,IAAI,OAAO,WAAW,aACpB;CAGF,OAAO,cAAc,IAAI,YAAY,cAAc,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC;AAClF;AAEA,SAAgB,QAAQ,UAAqD;CAC3E,MAAM,YAAY,UAAuB;EACvC,MAAM,QAAQ,eAAgB,MAAsB,MAAM;EAE1D,IAAI,OACF,SAAS,KAAK;CAElB;CAEA,OAAO,iBAAiB,cAAc,OAAO,QAAQ;CAErD,aAAa,OAAO,oBAAoB,cAAc,OAAO,QAAQ;AACvE"}
|