@lattice-php/lattice 0.23.0 → 0.25.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.
Files changed (60) hide show
  1. package/dist/action/components/action-form.js +36 -4
  2. package/dist/action/components/action-form.js.map +1 -1
  3. package/dist/form/components/form.js +8 -2
  4. package/dist/form/components/form.js.map +1 -1
  5. package/dist/form/components/index.d.ts +1 -0
  6. package/dist/form/components/index.js +2 -1
  7. package/dist/form/components/wizard.d.ts +3 -0
  8. package/dist/form/components/wizard.js +148 -0
  9. package/dist/form/components/wizard.js.map +1 -0
  10. package/dist/form/embed.d.ts +1 -1
  11. package/dist/form/embed.js +2 -2
  12. package/dist/form/hooks/context.d.ts +7 -2
  13. package/dist/form/hooks/context.js +4 -1
  14. package/dist/form/hooks/context.js.map +1 -1
  15. package/dist/form/index.js +2 -1
  16. package/dist/form/lib/field-errors.d.ts +2 -0
  17. package/dist/form/lib/field-errors.js +5 -1
  18. package/dist/form/lib/field-errors.js.map +1 -1
  19. package/dist/form/lib/field-props.d.ts +6 -0
  20. package/dist/form/lib/field-props.js +7 -1
  21. package/dist/form/lib/field-props.js.map +1 -1
  22. package/dist/form/lib/prefill-targets.js +2 -3
  23. package/dist/form/lib/prefill-targets.js.map +1 -1
  24. package/dist/form/lib/wizard-steps.d.ts +5 -0
  25. package/dist/form/lib/wizard-steps.js +44 -0
  26. package/dist/form/lib/wizard-steps.js.map +1 -0
  27. package/dist/form/plugin.js +4 -1
  28. package/dist/form/plugin.js.map +1 -1
  29. package/dist/i18n/translatable.d.ts +1 -0
  30. package/dist/i18n/translatable.js +4 -1
  31. package/dist/i18n/translatable.js.map +1 -1
  32. package/dist/layout/components/callouts.js +3 -2
  33. package/dist/layout/components/callouts.js.map +1 -1
  34. package/dist/notifications/components/notification-item.js +7 -4
  35. package/dist/notifications/components/notification-item.js.map +1 -1
  36. package/dist/table/components/filter-controls.js +4 -1
  37. package/dist/table/components/filter-controls.js.map +1 -1
  38. package/dist/toast/callout.js +6 -3
  39. package/dist/toast/callout.js.map +1 -1
  40. package/dist/toast/toaster.js +2 -2
  41. package/dist/toast/toaster.js.map +1 -1
  42. package/dist/types/generated.d.ts +18 -25
  43. package/dist/ui/plugin.js +1 -3
  44. package/dist/ui/plugin.js.map +1 -1
  45. package/dist/vite-typescript-refresh.d.ts +9 -0
  46. package/dist/vite-typescript-refresh.js +47 -0
  47. package/dist/vite-typescript-refresh.js.map +1 -0
  48. package/dist/vite.d.ts +22 -1
  49. package/dist/vite.js +62 -8
  50. package/dist/vite.js.map +1 -1
  51. package/dist-standalone/lattice.css +1 -1
  52. package/dist-standalone/lattice.js +14 -14
  53. package/dist-standalone/manifest.json +2 -2
  54. package/package.json +1 -1
  55. package/dist/ui/tree-context.d.ts +0 -33
  56. package/dist/ui/tree-context.js +0 -135
  57. package/dist/ui/tree-context.js.map +0 -1
  58. package/dist/ui/tree.d.ts +0 -19
  59. package/dist/ui/tree.js +0 -187
  60. package/dist/ui/tree.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"prefill-targets.js","names":[],"sources":["../../../resources/js/form/lib/prefill-targets.ts"],"sourcesContent":["import type { Node } from \"@lattice-php/lattice/core/types\";\nimport { fieldProps } from \"./field-props\";\nimport { rowSchemaFor } from \"@lattice-php/lattice/form/components/fields/row-templates\";\nimport { appendPath, getPath } from \"./form-path\";\nimport { buildOverrideKey, rowIdFrom } from \"./override-keys\";\n\ntype PrefillTarget = {\n path: string;\n overrideKey: string;\n resetOn: string[];\n refreshOn: string[];\n};\n\ntype PrefillSnapshot = {\n targets: PrefillTarget[];\n values: Record<string, unknown>;\n};\n\nconst ROW_COLLECTION_TYPES = new Set([\"field.builder\", \"field.repeater\"]);\n\nexport { getPath } from \"./form-path\";\n\nfunction mapDep(dep: string, rowPath: string | null): string {\n if (dep.startsWith(\"@\")) {\n return dep.slice(1);\n }\n\n return rowPath === null ? dep : appendPath(rowPath, dep);\n}\n\nfunction targetFor(\n node: Node,\n rowPath: string | null,\n identityCollectionPath: string | null,\n index = 0,\n row: Record<string, unknown> = {},\n): PrefillTarget | null {\n const props = fieldProps(node);\n\n if (!props.editablePrefill || !props.name) {\n return null;\n }\n\n const rowId = rowIdFrom(row);\n\n return {\n path: rowPath === null ? props.name : appendPath(rowPath, props.name),\n overrideKey:\n identityCollectionPath === null\n ? props.name\n : buildOverrideKey(identityCollectionPath, rowId, index, props.name),\n resetOn: (props.prefillResetOn ?? []).map((dep) => mapDep(dep, rowPath)),\n refreshOn: (props.prefillRefreshOn ?? []).map((dep) => mapDep(dep, rowPath)),\n };\n}\n\nexport function collectPrefillTargets(\n nodes: Node[] | undefined,\n values: Record<string, unknown>,\n): PrefillTarget[] {\n const targets: PrefillTarget[] = [];\n\n const walk = (\n list: Node[] | undefined,\n rowPath: string | null = null,\n identityRowPath: string | null = null,\n identityCollectionPath: string | null = null,\n index = 0,\n row: Record<string, unknown> = {},\n ): void => {\n for (const node of list ?? []) {\n if (ROW_COLLECTION_TYPES.has(node.type)) {\n const name = fieldProps(node).name;\n if (name) {\n const childCollectionPath = appendPath(rowPath, name);\n const childIdentityCollectionPath = appendPath(identityRowPath, name);\n const storedRows = getPath(values, childCollectionPath);\n const rows = Array.isArray(storedRows)\n ? (storedRows as Array<Record<string, unknown>>)\n : [];\n rows.forEach((childRow, childIndex) => {\n walk(\n rowSchemaFor(node, childRow),\n appendPath(childCollectionPath, childIndex),\n appendPath(childIdentityCollectionPath, rowIdFrom(childRow) ?? childIndex),\n childIdentityCollectionPath,\n childIndex,\n childRow,\n );\n });\n }\n\n continue;\n }\n\n const target = targetFor(node, rowPath, identityCollectionPath, index, row);\n if (target) {\n targets.push(target);\n }\n\n walk(node.schema, rowPath, identityRowPath, identityCollectionPath, index, row);\n }\n };\n\n walk(nodes);\n\n return targets;\n}\n\nexport function pathsToClear(previous: PrefillSnapshot, next: PrefillSnapshot): string[] {\n const previousByKey = new Map(\n previous.targets.map((target) => [target.overrideKey, target] as const),\n );\n\n return next.targets\n .filter((target) => {\n const previousTarget = previousByKey.get(target.overrideKey);\n\n return target.resetOn.some((dep, index) => {\n const previousDep = previousTarget?.resetOn[index] ?? dep;\n\n return !Object.is(getPath(previous.values, previousDep), getPath(next.values, dep));\n });\n })\n .map((target) => target.overrideKey);\n}\n\nexport function seededOverrides(\n targets: PrefillTarget[],\n values: Record<string, unknown>,\n): string[] {\n return targets\n .filter((target) => {\n const value = getPath(values, target.path);\n\n return value !== undefined && value !== null && value !== \"\";\n })\n .map((target) => target.overrideKey);\n}\n\nexport function pruneOverrides(overrides: Set<string>, targets: PrefillTarget[]): Set<string> {\n const liveKeys = new Set(targets.map((target) => target.overrideKey));\n\n return new Set([...overrides].filter((key) => liveKeys.has(key)));\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"prefill-targets.js","names":[],"sources":["../../../resources/js/form/lib/prefill-targets.ts"],"sourcesContent":["import type { Node } from \"@lattice-php/lattice/core/types\";\nimport { fieldProps, ROW_FIELD_TYPES } from \"./field-props\";\nimport { rowSchemaFor } from \"@lattice-php/lattice/form/components/fields/row-templates\";\nimport { appendPath, getPath } from \"./form-path\";\nimport { buildOverrideKey, rowIdFrom } from \"./override-keys\";\n\ntype PrefillTarget = {\n path: string;\n overrideKey: string;\n resetOn: string[];\n refreshOn: string[];\n};\n\ntype PrefillSnapshot = {\n targets: PrefillTarget[];\n values: Record<string, unknown>;\n};\n\nexport { getPath } from \"./form-path\";\n\nfunction mapDep(dep: string, rowPath: string | null): string {\n if (dep.startsWith(\"@\")) {\n return dep.slice(1);\n }\n\n return rowPath === null ? dep : appendPath(rowPath, dep);\n}\n\nfunction targetFor(\n node: Node,\n rowPath: string | null,\n identityCollectionPath: string | null,\n index = 0,\n row: Record<string, unknown> = {},\n): PrefillTarget | null {\n const props = fieldProps(node);\n\n if (!props.editablePrefill || !props.name) {\n return null;\n }\n\n const rowId = rowIdFrom(row);\n\n return {\n path: rowPath === null ? props.name : appendPath(rowPath, props.name),\n overrideKey:\n identityCollectionPath === null\n ? props.name\n : buildOverrideKey(identityCollectionPath, rowId, index, props.name),\n resetOn: (props.prefillResetOn ?? []).map((dep) => mapDep(dep, rowPath)),\n refreshOn: (props.prefillRefreshOn ?? []).map((dep) => mapDep(dep, rowPath)),\n };\n}\n\nexport function collectPrefillTargets(\n nodes: Node[] | undefined,\n values: Record<string, unknown>,\n): PrefillTarget[] {\n const targets: PrefillTarget[] = [];\n\n const walk = (\n list: Node[] | undefined,\n rowPath: string | null = null,\n identityRowPath: string | null = null,\n identityCollectionPath: string | null = null,\n index = 0,\n row: Record<string, unknown> = {},\n ): void => {\n for (const node of list ?? []) {\n if (ROW_FIELD_TYPES.has(node.type)) {\n const name = fieldProps(node).name;\n if (name) {\n const childCollectionPath = appendPath(rowPath, name);\n const childIdentityCollectionPath = appendPath(identityRowPath, name);\n const storedRows = getPath(values, childCollectionPath);\n const rows = Array.isArray(storedRows)\n ? (storedRows as Array<Record<string, unknown>>)\n : [];\n rows.forEach((childRow, childIndex) => {\n walk(\n rowSchemaFor(node, childRow),\n appendPath(childCollectionPath, childIndex),\n appendPath(childIdentityCollectionPath, rowIdFrom(childRow) ?? childIndex),\n childIdentityCollectionPath,\n childIndex,\n childRow,\n );\n });\n }\n\n continue;\n }\n\n const target = targetFor(node, rowPath, identityCollectionPath, index, row);\n if (target) {\n targets.push(target);\n }\n\n walk(node.schema, rowPath, identityRowPath, identityCollectionPath, index, row);\n }\n };\n\n walk(nodes);\n\n return targets;\n}\n\nexport function pathsToClear(previous: PrefillSnapshot, next: PrefillSnapshot): string[] {\n const previousByKey = new Map(\n previous.targets.map((target) => [target.overrideKey, target] as const),\n );\n\n return next.targets\n .filter((target) => {\n const previousTarget = previousByKey.get(target.overrideKey);\n\n return target.resetOn.some((dep, index) => {\n const previousDep = previousTarget?.resetOn[index] ?? dep;\n\n return !Object.is(getPath(previous.values, previousDep), getPath(next.values, dep));\n });\n })\n .map((target) => target.overrideKey);\n}\n\nexport function seededOverrides(\n targets: PrefillTarget[],\n values: Record<string, unknown>,\n): string[] {\n return targets\n .filter((target) => {\n const value = getPath(values, target.path);\n\n return value !== undefined && value !== null && value !== \"\";\n })\n .map((target) => target.overrideKey);\n}\n\nexport function pruneOverrides(overrides: Set<string>, targets: PrefillTarget[]): Set<string> {\n const liveKeys = new Set(targets.map((target) => target.overrideKey));\n\n return new Set([...overrides].filter((key) => liveKeys.has(key)));\n}\n"],"mappings":";;;;;AAoBA,SAAS,OAAO,KAAa,SAAgC;CAC3D,IAAI,IAAI,WAAW,GAAG,GACpB,OAAO,IAAI,MAAM,CAAC;CAGpB,OAAO,YAAY,OAAO,MAAM,WAAW,SAAS,GAAG;AACzD;AAEA,SAAS,UACP,MACA,SACA,wBACA,QAAQ,GACR,MAA+B,CAAC,GACV;CACtB,MAAM,QAAQ,WAAW,IAAI;CAE7B,IAAI,CAAC,MAAM,mBAAmB,CAAC,MAAM,MACnC,OAAO;CAGT,MAAM,QAAQ,UAAU,GAAG;CAE3B,OAAO;EACL,MAAM,YAAY,OAAO,MAAM,OAAO,WAAW,SAAS,MAAM,IAAI;EACpE,aACE,2BAA2B,OACvB,MAAM,OACN,iBAAiB,wBAAwB,OAAO,OAAO,MAAM,IAAI;EACvE,UAAU,MAAM,kBAAkB,CAAC,GAAG,KAAK,QAAQ,OAAO,KAAK,OAAO,CAAC;EACvE,YAAY,MAAM,oBAAoB,CAAC,GAAG,KAAK,QAAQ,OAAO,KAAK,OAAO,CAAC;CAC7E;AACF;AAEA,SAAgB,sBACd,OACA,QACiB;CACjB,MAAM,UAA2B,CAAC;CAElC,MAAM,QACJ,MACA,UAAyB,MACzB,kBAAiC,MACjC,yBAAwC,MACxC,QAAQ,GACR,MAA+B,CAAC,MACvB;EACT,KAAK,MAAM,QAAQ,QAAQ,CAAC,GAAG;GAC7B,IAAI,gBAAgB,IAAI,KAAK,IAAI,GAAG;IAClC,MAAM,OAAO,WAAW,IAAI,EAAE;IAC9B,IAAI,MAAM;KACR,MAAM,sBAAsB,WAAW,SAAS,IAAI;KACpD,MAAM,8BAA8B,WAAW,iBAAiB,IAAI;KACpE,MAAM,aAAa,QAAQ,QAAQ,mBAAmB;KAItD,CAHa,MAAM,QAAQ,UAAU,IAChC,aACD,CAAC,GACA,SAAS,UAAU,eAAe;MACrC,KACE,aAAa,MAAM,QAAQ,GAC3B,WAAW,qBAAqB,UAAU,GAC1C,WAAW,6BAA6B,UAAU,QAAQ,KAAK,UAAU,GACzE,6BACA,YACA,QACF;KACF,CAAC;IACH;IAEA;GACF;GAEA,MAAM,SAAS,UAAU,MAAM,SAAS,wBAAwB,OAAO,GAAG;GAC1E,IAAI,QACF,QAAQ,KAAK,MAAM;GAGrB,KAAK,KAAK,QAAQ,SAAS,iBAAiB,wBAAwB,OAAO,GAAG;EAChF;CACF;CAEA,KAAK,KAAK;CAEV,OAAO;AACT;AAEA,SAAgB,aAAa,UAA2B,MAAiC;CACvF,MAAM,gBAAgB,IAAI,IACxB,SAAS,QAAQ,KAAK,WAAW,CAAC,OAAO,aAAa,MAAM,CAAU,CACxE;CAEA,OAAO,KAAK,QACT,QAAQ,WAAW;EAClB,MAAM,iBAAiB,cAAc,IAAI,OAAO,WAAW;EAE3D,OAAO,OAAO,QAAQ,MAAM,KAAK,UAAU;GACzC,MAAM,cAAc,gBAAgB,QAAQ,UAAU;GAEtD,OAAO,CAAC,OAAO,GAAG,QAAQ,SAAS,QAAQ,WAAW,GAAG,QAAQ,KAAK,QAAQ,GAAG,CAAC;EACpF,CAAC;CACH,CAAC,EACA,KAAK,WAAW,OAAO,WAAW;AACvC;AAEA,SAAgB,gBACd,SACA,QACU;CACV,OAAO,QACJ,QAAQ,WAAW;EAClB,MAAM,QAAQ,QAAQ,QAAQ,OAAO,IAAI;EAEzC,OAAO,UAAU,KAAA,KAAa,UAAU,QAAQ,UAAU;CAC5D,CAAC,EACA,KAAK,WAAW,OAAO,WAAW;AACvC;AAEA,SAAgB,eAAe,WAAwB,SAAuC;CAC5F,MAAM,WAAW,IAAI,IAAI,QAAQ,KAAK,WAAW,OAAO,WAAW,CAAC;CAEpE,OAAO,IAAI,IAAI,CAAC,GAAG,SAAS,EAAE,QAAQ,QAAQ,SAAS,IAAI,GAAG,CAAC,CAAC;AAClE"}
@@ -0,0 +1,5 @@
1
+ import { Node } from '../../core/types.js';
2
+ export declare function stepFieldNames(step: Node): string[];
3
+ export declare function stepValidationPaths(step: Node): string[];
4
+ export declare function stepsWithErrors(stepNames: string[][], errors: Record<string, string | undefined>): Set<number>;
5
+ export declare function firstErroredStep(stepNames: string[][], errors: Record<string, string | undefined>): number | null;
@@ -0,0 +1,44 @@
1
+ import { ROW_FIELD_TYPES, fieldProps } from "./field-props.js";
2
+ import { errorKeyBelongsTo } from "./field-errors.js";
3
+ //#region resources/js/form/lib/wizard-steps.ts
4
+ function stepFieldNames(step) {
5
+ const names = [];
6
+ const collect = (node) => {
7
+ const name = fieldProps(node).name;
8
+ if (name) names.push(name);
9
+ if (name && ROW_FIELD_TYPES.has(node.type)) return;
10
+ for (const child of node.schema ?? []) collect(child);
11
+ };
12
+ for (const child of step.schema ?? []) collect(child);
13
+ return names;
14
+ }
15
+ function stepValidationPaths(step) {
16
+ const paths = [];
17
+ const expand = (node) => {
18
+ const name = fieldProps(node).name;
19
+ if (name) paths.push(name, `${name}.*`);
20
+ if (name && ROW_FIELD_TYPES.has(node.type)) {
21
+ for (const child of stepFieldNames(node)) paths.push(`${name}.*.${child}`);
22
+ return;
23
+ }
24
+ for (const child of node.schema ?? []) expand(child);
25
+ };
26
+ for (const child of step.schema ?? []) expand(child);
27
+ return paths;
28
+ }
29
+ function stepsWithErrors(stepNames, errors) {
30
+ const keys = Object.keys(errors).filter((key) => Boolean(errors[key]));
31
+ const owners = /* @__PURE__ */ new Set();
32
+ stepNames.forEach((names, index) => {
33
+ if (keys.some((key) => names.some((name) => errorKeyBelongsTo(key, name)))) owners.add(index);
34
+ });
35
+ return owners;
36
+ }
37
+ function firstErroredStep(stepNames, errors) {
38
+ const owners = stepsWithErrors(stepNames, errors);
39
+ return owners.size > 0 ? Math.min(...owners) : null;
40
+ }
41
+ //#endregion
42
+ export { firstErroredStep, stepFieldNames, stepValidationPaths, stepsWithErrors };
43
+
44
+ //# sourceMappingURL=wizard-steps.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wizard-steps.js","names":[],"sources":["../../../resources/js/form/lib/wizard-steps.ts"],"sourcesContent":["import type { Node } from \"@lattice-php/lattice/core/types\";\nimport { errorKeyBelongsTo } from \"./field-errors\";\nimport { fieldProps, ROW_FIELD_TYPES } from \"./field-props\";\n\nexport function stepFieldNames(step: Node): string[] {\n const names: string[] = [];\n\n const collect = (node: Node): void => {\n const name = fieldProps(node).name;\n\n if (name) {\n names.push(name);\n }\n if (name && ROW_FIELD_TYPES.has(node.type)) {\n return;\n }\n for (const child of node.schema ?? []) {\n collect(child);\n }\n };\n\n for (const child of step.schema ?? []) {\n collect(child);\n }\n\n return names;\n}\n\nexport function stepValidationPaths(step: Node): string[] {\n const paths: string[] = [];\n\n const expand = (node: Node): void => {\n const name = fieldProps(node).name;\n\n if (name) {\n paths.push(name, `${name}.*`);\n }\n\n if (name && ROW_FIELD_TYPES.has(node.type)) {\n for (const child of stepFieldNames(node)) {\n paths.push(`${name}.*.${child}`);\n }\n\n return;\n }\n\n for (const child of node.schema ?? []) {\n expand(child);\n }\n };\n\n for (const child of step.schema ?? []) {\n expand(child);\n }\n\n return paths;\n}\n\nexport function stepsWithErrors(\n stepNames: string[][],\n errors: Record<string, string | undefined>,\n): Set<number> {\n const keys = Object.keys(errors).filter((key) => Boolean(errors[key]));\n const owners = new Set<number>();\n\n stepNames.forEach((names, index) => {\n const owns = keys.some((key) => names.some((name) => errorKeyBelongsTo(key, name)));\n\n if (owns) {\n owners.add(index);\n }\n });\n\n return owners;\n}\n\nexport function firstErroredStep(\n stepNames: string[][],\n errors: Record<string, string | undefined>,\n): number | null {\n const owners = stepsWithErrors(stepNames, errors);\n\n return owners.size > 0 ? Math.min(...owners) : null;\n}\n"],"mappings":";;;AAIA,SAAgB,eAAe,MAAsB;CACnD,MAAM,QAAkB,CAAC;CAEzB,MAAM,WAAW,SAAqB;EACpC,MAAM,OAAO,WAAW,IAAI,EAAE;EAE9B,IAAI,MACF,MAAM,KAAK,IAAI;EAEjB,IAAI,QAAQ,gBAAgB,IAAI,KAAK,IAAI,GACvC;EAEF,KAAK,MAAM,SAAS,KAAK,UAAU,CAAC,GAClC,QAAQ,KAAK;CAEjB;CAEA,KAAK,MAAM,SAAS,KAAK,UAAU,CAAC,GAClC,QAAQ,KAAK;CAGf,OAAO;AACT;AAEA,SAAgB,oBAAoB,MAAsB;CACxD,MAAM,QAAkB,CAAC;CAEzB,MAAM,UAAU,SAAqB;EACnC,MAAM,OAAO,WAAW,IAAI,EAAE;EAE9B,IAAI,MACF,MAAM,KAAK,MAAM,GAAG,KAAK,GAAG;EAG9B,IAAI,QAAQ,gBAAgB,IAAI,KAAK,IAAI,GAAG;GAC1C,KAAK,MAAM,SAAS,eAAe,IAAI,GACrC,MAAM,KAAK,GAAG,KAAK,KAAK,OAAO;GAGjC;EACF;EAEA,KAAK,MAAM,SAAS,KAAK,UAAU,CAAC,GAClC,OAAO,KAAK;CAEhB;CAEA,KAAK,MAAM,SAAS,KAAK,UAAU,CAAC,GAClC,OAAO,KAAK;CAGd,OAAO;AACT;AAEA,SAAgB,gBACd,WACA,QACa;CACb,MAAM,OAAO,OAAO,KAAK,MAAM,EAAE,QAAQ,QAAQ,QAAQ,OAAO,IAAI,CAAC;CACrE,MAAM,yBAAS,IAAI,IAAY;CAE/B,UAAU,SAAS,OAAO,UAAU;EAGlC,IAFa,KAAK,MAAM,QAAQ,MAAM,MAAM,SAAS,kBAAkB,KAAK,IAAI,CAAC,CAE7E,GACF,OAAO,IAAI,KAAK;CAEpB,CAAC;CAED,OAAO;AACT;AAEA,SAAgB,iBACd,WACA,QACe;CACf,MAAM,SAAS,gBAAgB,WAAW,MAAM;CAEhD,OAAO,OAAO,OAAO,IAAI,KAAK,IAAI,GAAG,MAAM,IAAI;AACjD"}
@@ -17,6 +17,7 @@ import { TextareaComponent } from "./components/fields/textarea.js";
17
17
  import { TextInputComponent } from "./components/fields/text-input.js";
18
18
  import { TimeInputComponent } from "./components/fields/time-input.js";
19
19
  import { ToggleComponent } from "./components/fields/toggle.js";
20
+ import { WizardComponent, WizardStepComponent } from "./components/wizard.js";
20
21
  import { RichEditorComponent } from "./components/fields/rich-editor.js";
21
22
  //#region resources/js/form/plugin.ts
22
23
  var formComponents = createPlugin({
@@ -39,7 +40,9 @@ var formComponents = createPlugin({
39
40
  "field.textarea": eagerComponent(TextareaComponent),
40
41
  "field.text-input": eagerComponent(TextInputComponent),
41
42
  "field.time-input": eagerComponent(TimeInputComponent),
42
- "field.toggle": eagerComponent(ToggleComponent)
43
+ "field.toggle": eagerComponent(ToggleComponent),
44
+ wizard: eagerComponent(WizardComponent),
45
+ "wizard-step": eagerComponent(WizardStepComponent)
43
46
  },
44
47
  name: "lattice/form"
45
48
  });
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.js","names":[],"sources":["../../resources/js/form/plugin.ts"],"sourcesContent":["import {\n createPlugin,\n eagerComponent,\n type ComponentRegistryFor,\n} from \"@lattice-php/lattice/core/registry\";\nimport type { FormNodeType } from \"@lattice-php/lattice/types/generated\";\nimport {\n BuilderComponent,\n CheckboxComponent,\n ChoiceComponent,\n ColorPickerFieldComponent,\n DateInputComponent,\n DateTimeInputComponent,\n FileUploadComponent,\n FormComponent,\n HiddenInputComponent,\n NumberInputComponent,\n OtpInputComponent,\n PasswordInputComponent,\n RepeaterComponent,\n SelectComponent,\n TextareaComponent,\n TextInputComponent,\n TimeInputComponent,\n ToggleComponent,\n} from \"./components\";\nimport { RichEditorComponent } from \"./components/fields/rich-editor\";\n\nexport const formComponents = createPlugin({\n components: {\n form: eagerComponent(FormComponent),\n \"field.builder\": eagerComponent(BuilderComponent),\n \"field.checkbox\": eagerComponent(CheckboxComponent),\n \"field.choice\": eagerComponent(ChoiceComponent),\n \"field.color-picker\": eagerComponent(ColorPickerFieldComponent),\n \"field.date-input\": eagerComponent(DateInputComponent),\n \"field.date-time-input\": eagerComponent(DateTimeInputComponent),\n \"field.file-upload\": eagerComponent(FileUploadComponent),\n \"field.hidden-input\": eagerComponent(HiddenInputComponent),\n \"field.number-input\": eagerComponent(NumberInputComponent),\n \"field.otp\": eagerComponent(OtpInputComponent),\n \"field.password-input\": eagerComponent(PasswordInputComponent),\n \"field.repeater\": eagerComponent(RepeaterComponent),\n \"field.rich-editor\": eagerComponent(RichEditorComponent),\n \"field.select\": eagerComponent(SelectComponent),\n \"field.textarea\": eagerComponent(TextareaComponent),\n \"field.text-input\": eagerComponent(TextInputComponent),\n \"field.time-input\": eagerComponent(TimeInputComponent),\n \"field.toggle\": eagerComponent(ToggleComponent),\n } satisfies ComponentRegistryFor<FormNodeType>,\n name: \"lattice/form\",\n});\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AA4BA,IAAa,iBAAiB,aAAa;CACzC,YAAY;EACV,MAAM,eAAe,aAAa;EAClC,iBAAiB,eAAe,gBAAgB;EAChD,kBAAkB,eAAe,iBAAiB;EAClD,gBAAgB,eAAe,eAAe;EAC9C,sBAAsB,eAAe,yBAAyB;EAC9D,oBAAoB,eAAe,kBAAkB;EACrD,yBAAyB,eAAe,sBAAsB;EAC9D,qBAAqB,eAAe,mBAAmB;EACvD,sBAAsB,eAAe,oBAAoB;EACzD,sBAAsB,eAAe,oBAAoB;EACzD,aAAa,eAAe,iBAAiB;EAC7C,wBAAwB,eAAe,sBAAsB;EAC7D,kBAAkB,eAAe,iBAAiB;EAClD,qBAAqB,eAAe,mBAAmB;EACvD,gBAAgB,eAAe,eAAe;EAC9C,kBAAkB,eAAe,iBAAiB;EAClD,oBAAoB,eAAe,kBAAkB;EACrD,oBAAoB,eAAe,kBAAkB;EACrD,gBAAgB,eAAe,eAAe;CAChD;CACA,MAAM;AACR,CAAC"}
1
+ {"version":3,"file":"plugin.js","names":[],"sources":["../../resources/js/form/plugin.ts"],"sourcesContent":["import {\n createPlugin,\n eagerComponent,\n type ComponentRegistryFor,\n} from \"@lattice-php/lattice/core/registry\";\nimport type { FormNodeType } from \"@lattice-php/lattice/types/generated\";\nimport {\n BuilderComponent,\n CheckboxComponent,\n ChoiceComponent,\n ColorPickerFieldComponent,\n DateInputComponent,\n DateTimeInputComponent,\n FileUploadComponent,\n FormComponent,\n HiddenInputComponent,\n NumberInputComponent,\n OtpInputComponent,\n PasswordInputComponent,\n RepeaterComponent,\n SelectComponent,\n TextareaComponent,\n TextInputComponent,\n TimeInputComponent,\n ToggleComponent,\n WizardComponent,\n WizardStepComponent,\n} from \"./components\";\nimport { RichEditorComponent } from \"./components/fields/rich-editor\";\n\nexport const formComponents = createPlugin({\n components: {\n form: eagerComponent(FormComponent),\n \"field.builder\": eagerComponent(BuilderComponent),\n \"field.checkbox\": eagerComponent(CheckboxComponent),\n \"field.choice\": eagerComponent(ChoiceComponent),\n \"field.color-picker\": eagerComponent(ColorPickerFieldComponent),\n \"field.date-input\": eagerComponent(DateInputComponent),\n \"field.date-time-input\": eagerComponent(DateTimeInputComponent),\n \"field.file-upload\": eagerComponent(FileUploadComponent),\n \"field.hidden-input\": eagerComponent(HiddenInputComponent),\n \"field.number-input\": eagerComponent(NumberInputComponent),\n \"field.otp\": eagerComponent(OtpInputComponent),\n \"field.password-input\": eagerComponent(PasswordInputComponent),\n \"field.repeater\": eagerComponent(RepeaterComponent),\n \"field.rich-editor\": eagerComponent(RichEditorComponent),\n \"field.select\": eagerComponent(SelectComponent),\n \"field.textarea\": eagerComponent(TextareaComponent),\n \"field.text-input\": eagerComponent(TextInputComponent),\n \"field.time-input\": eagerComponent(TimeInputComponent),\n \"field.toggle\": eagerComponent(ToggleComponent),\n wizard: eagerComponent(WizardComponent),\n \"wizard-step\": eagerComponent(WizardStepComponent),\n } satisfies ComponentRegistryFor<FormNodeType>,\n name: \"lattice/form\",\n});\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AA8BA,IAAa,iBAAiB,aAAa;CACzC,YAAY;EACV,MAAM,eAAe,aAAa;EAClC,iBAAiB,eAAe,gBAAgB;EAChD,kBAAkB,eAAe,iBAAiB;EAClD,gBAAgB,eAAe,eAAe;EAC9C,sBAAsB,eAAe,yBAAyB;EAC9D,oBAAoB,eAAe,kBAAkB;EACrD,yBAAyB,eAAe,sBAAsB;EAC9D,qBAAqB,eAAe,mBAAmB;EACvD,sBAAsB,eAAe,oBAAoB;EACzD,sBAAsB,eAAe,oBAAoB;EACzD,aAAa,eAAe,iBAAiB;EAC7C,wBAAwB,eAAe,sBAAsB;EAC7D,kBAAkB,eAAe,iBAAiB;EAClD,qBAAqB,eAAe,mBAAmB;EACvD,gBAAgB,eAAe,eAAe;EAC9C,kBAAkB,eAAe,iBAAiB;EAClD,oBAAoB,eAAe,kBAAkB;EACrD,oBAAoB,eAAe,kBAAkB;EACrD,gBAAgB,eAAe,eAAe;EAC9C,QAAQ,eAAe,eAAe;EACtC,eAAe,eAAe,mBAAmB;CACnD;CACA,MAAM;AACR,CAAC"}
@@ -1,4 +1,5 @@
1
1
  import { Translatable } from '../types/generated.js';
2
2
  export type Translate = (key: string, defaultValue?: string, options?: Record<string, unknown>) => string;
3
3
  export declare function isTranslatable(value: unknown): value is Translatable;
4
+ export declare function resolveText(value: string | Translatable | null, t: Translate): string | null;
4
5
  export declare function resolveTranslatable(value: Translatable, payload: Record<string, unknown>, t: Translate): string;
@@ -7,6 +7,9 @@ function readPath(payload, path) {
7
7
  if (typeof node === "object" && node !== null) return node[segment];
8
8
  }, payload);
9
9
  }
10
+ function resolveText(value, t) {
11
+ return isTranslatable(value) ? resolveTranslatable(value, {}, t) : value;
12
+ }
10
13
  function resolveTranslatable(value, payload, t) {
11
14
  const fromPayload = {};
12
15
  for (const [name, path] of Object.entries(value.payload)) {
@@ -19,6 +22,6 @@ function resolveTranslatable(value, payload, t) {
19
22
  });
20
23
  }
21
24
  //#endregion
22
- export { isTranslatable, resolveTranslatable };
25
+ export { isTranslatable, resolveText, resolveTranslatable };
23
26
 
24
27
  //# sourceMappingURL=translatable.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"translatable.js","names":[],"sources":["../../resources/js/i18n/translatable.ts"],"sourcesContent":["import type { Translatable } from \"@lattice-php/lattice/types/generated\";\n\nexport type Translate = (\n key: string,\n defaultValue?: string,\n options?: Record<string, unknown>,\n) => string;\n\nexport function isTranslatable(value: unknown): value is Translatable {\n return (\n typeof value === \"object\" &&\n value !== null &&\n typeof (value as { key?: unknown }).key === \"string\"\n );\n}\n\nfunction readPath(payload: Record<string, unknown>, path: string): unknown {\n return path.split(\".\").reduce<unknown>((node, segment) => {\n if (typeof node === \"object\" && node !== null) {\n return (node as Record<string, unknown>)[segment];\n }\n\n return undefined;\n }, payload);\n}\n\nexport function resolveTranslatable(\n value: Translatable,\n payload: Record<string, unknown>,\n t: Translate,\n): string {\n const fromPayload: Record<string, unknown> = {};\n\n for (const [name, path] of Object.entries(value.payload)) {\n const read = readPath(payload, path);\n fromPayload[name] = read === undefined ? \"\" : read;\n }\n\n return t(value.key, value.key, { ...value.replacements, ...fromPayload });\n}\n"],"mappings":";AAQA,SAAgB,eAAe,OAAuC;CACpE,OACE,OAAO,UAAU,YACjB,UAAU,QACV,OAAQ,MAA4B,QAAQ;AAEhD;AAEA,SAAS,SAAS,SAAkC,MAAuB;CACzE,OAAO,KAAK,MAAM,GAAG,EAAE,QAAiB,MAAM,YAAY;EACxD,IAAI,OAAO,SAAS,YAAY,SAAS,MACvC,OAAQ,KAAiC;CAI7C,GAAG,OAAO;AACZ;AAEA,SAAgB,oBACd,OACA,SACA,GACQ;CACR,MAAM,cAAuC,CAAC;CAE9C,KAAK,MAAM,CAAC,MAAM,SAAS,OAAO,QAAQ,MAAM,OAAO,GAAG;EACxD,MAAM,OAAO,SAAS,SAAS,IAAI;EACnC,YAAY,QAAQ,SAAS,KAAA,IAAY,KAAK;CAChD;CAEA,OAAO,EAAE,MAAM,KAAK,MAAM,KAAK;EAAE,GAAG,MAAM;EAAc,GAAG;CAAY,CAAC;AAC1E"}
1
+ {"version":3,"file":"translatable.js","names":[],"sources":["../../resources/js/i18n/translatable.ts"],"sourcesContent":["import type { Translatable } from \"@lattice-php/lattice/types/generated\";\n\nexport type Translate = (\n key: string,\n defaultValue?: string,\n options?: Record<string, unknown>,\n) => string;\n\nexport function isTranslatable(value: unknown): value is Translatable {\n return (\n typeof value === \"object\" &&\n value !== null &&\n typeof (value as { key?: unknown }).key === \"string\"\n );\n}\n\nfunction readPath(payload: Record<string, unknown>, path: string): unknown {\n return path.split(\".\").reduce<unknown>((node, segment) => {\n if (typeof node === \"object\" && node !== null) {\n return (node as Record<string, unknown>)[segment];\n }\n\n return undefined;\n }, payload);\n}\n\nexport function resolveText(value: string | Translatable | null, t: Translate): string | null {\n return isTranslatable(value) ? resolveTranslatable(value, {}, t) : value;\n}\n\nexport function resolveTranslatable(\n value: Translatable,\n payload: Record<string, unknown>,\n t: Translate,\n): string {\n const fromPayload: Record<string, unknown> = {};\n\n for (const [name, path] of Object.entries(value.payload)) {\n const read = readPath(payload, path);\n fromPayload[name] = read === undefined ? \"\" : read;\n }\n\n return t(value.key, value.key, { ...value.replacements, ...fromPayload });\n}\n"],"mappings":";AAQA,SAAgB,eAAe,OAAuC;CACpE,OACE,OAAO,UAAU,YACjB,UAAU,QACV,OAAQ,MAA4B,QAAQ;AAEhD;AAEA,SAAS,SAAS,SAAkC,MAAuB;CACzE,OAAO,KAAK,MAAM,GAAG,EAAE,QAAiB,MAAM,YAAY;EACxD,IAAI,OAAO,SAAS,YAAY,SAAS,MACvC,OAAQ,KAAiC;CAI7C,GAAG,OAAO;AACZ;AAEA,SAAgB,YAAY,OAAqC,GAA6B;CAC5F,OAAO,eAAe,KAAK,IAAI,oBAAoB,OAAO,CAAC,GAAG,CAAC,IAAI;AACrE;AAEA,SAAgB,oBACd,OACA,SACA,GACQ;CACR,MAAM,cAAuC,CAAC;CAE9C,KAAK,MAAM,CAAC,MAAM,SAAS,OAAO,QAAQ,MAAM,OAAO,GAAG;EACxD,MAAM,OAAO,SAAS,SAAS,IAAI;EACnC,YAAY,QAAQ,SAAS,KAAA,IAAY,KAAK;CAChD;CAEA,OAAO,EAAE,MAAM,KAAK,MAAM,KAAK;EAAE,GAAG,MAAM;EAAc,GAAG;CAAY,CAAC;AAC1E"}
@@ -2,6 +2,7 @@ import { useT } from "../../i18n/instance.js";
2
2
  import { cn } from "../../lib/utils.js";
3
3
  import { Icon } from "../../icons/sprite.js";
4
4
  import { RenderNode } from "../../core/renderer.js";
5
+ import { resolveText } from "../../i18n/translatable.js";
5
6
  import { onCallout } from "../../toast/callout.js";
6
7
  import { variantStyles } from "../../toast/variant-styles.js";
7
8
  import { useEffect, useState } from "react";
@@ -34,11 +35,11 @@ var Callouts = () => {
34
35
  children: [
35
36
  callout.title ? /* @__PURE__ */ jsx("p", {
36
37
  className: "text-sm font-medium text-lt-fg",
37
- children: callout.title
38
+ children: resolveText(callout.title, t)
38
39
  }) : null,
39
40
  /* @__PURE__ */ jsx("p", {
40
41
  className: "text-sm text-lt-fg",
41
- children: callout.message
42
+ children: resolveText(callout.message, t)
42
43
  }),
43
44
  callout.action ? /* @__PURE__ */ jsx("div", {
44
45
  className: "flex flex-wrap gap-2",
@@ -1 +1 @@
1
- {"version":3,"file":"callouts.js","names":[],"sources":["../../../resources/js/layout/components/callouts.tsx"],"sourcesContent":["import { Icon } from \"@lattice-php/lattice/icons\";\nimport { useEffect, useState } from \"react\";\nimport { RenderNode } from \"@lattice-php/lattice/core/renderer\";\nimport type { Callout } from \"@lattice-php/lattice/types/generated\";\nimport type { RendererComponent } from \"@lattice-php/lattice/core/types\";\nimport { onCallout } from \"@lattice-php/lattice/toast\";\nimport { cn } from \"@lattice-php/lattice/lib/utils\";\nimport { useT } from \"@lattice-php/lattice/i18n\";\nimport { variantStyles } from \"@lattice-php/lattice/toast\";\n\ntype CalloutItem = Callout & { id: number };\n\nlet nextId = 0;\n\nconst Callouts: RendererComponent<\"callouts\"> = () => {\n const { t } = useT(\"lattice\");\n const [callouts, setCallouts] = useState<CalloutItem[]>([]);\n\n useEffect(\n () =>\n onCallout((callout) => {\n setCallouts((current) => [...current, { ...callout, id: nextId++ }]);\n }),\n [],\n );\n\n function dismiss(id: number): void {\n setCallouts((current) => current.filter((callout) => callout.id !== id));\n }\n\n if (callouts.length === 0) {\n return null;\n }\n\n return (\n <div className=\"flex w-full flex-col gap-2\">\n {callouts.map((callout) => (\n <div\n key={callout.id}\n role=\"status\"\n data-test={`callout-${callout.variant}`}\n className={cn(\n \"flex items-start gap-3 rounded-lt border border-l-4 border-lt-border bg-lt-popover p-4 text-lt-popover-fg\",\n variantStyles[callout.variant].accent,\n )}\n >\n {variantStyles[callout.variant].icon}\n <div className=\"flex min-w-0 flex-1 flex-col gap-2\">\n {callout.title ? (\n <p className=\"text-sm font-medium text-lt-fg\">{callout.title}</p>\n ) : null}\n <p className=\"text-sm text-lt-fg\">{callout.message}</p>\n {callout.action ? (\n <div className=\"flex flex-wrap gap-2\">\n <RenderNode node={callout.action} />\n </div>\n ) : null}\n </div>\n {callout.dismissible ? (\n <button\n type=\"button\"\n aria-label={t(\"common.dismiss\", \"Dismiss\")}\n data-test=\"callout-dismiss\"\n className=\"shrink-0 rounded-lt-sm p-1 text-lt-muted-fg transition-colors hover:bg-lt-muted hover:text-lt-fg\"\n onClick={() => dismiss(callout.id)}\n >\n <Icon name=\"x\" className=\"size-lt-icon-md\" />\n </button>\n ) : null}\n </div>\n ))}\n </div>\n );\n};\n\nexport default Callouts;\n"],"mappings":";;;;;;;;;AAYA,IAAI,SAAS;AAEb,IAAM,iBAAgD;CACpD,MAAM,EAAE,MAAM,KAAK,SAAS;CAC5B,MAAM,CAAC,UAAU,eAAe,SAAwB,CAAC,CAAC;CAE1D,gBAEI,WAAW,YAAY;EACrB,aAAa,YAAY,CAAC,GAAG,SAAS;GAAE,GAAG;GAAS,IAAI;EAAS,CAAC,CAAC;CACrE,CAAC,GACH,CAAC,CACH;CAEA,SAAS,QAAQ,IAAkB;EACjC,aAAa,YAAY,QAAQ,QAAQ,YAAY,QAAQ,OAAO,EAAE,CAAC;CACzE;CAEA,IAAI,SAAS,WAAW,GACtB,OAAO;CAGT,OACE,oBAAC,OAAD;EAAK,WAAU;YACZ,SAAS,KAAK,YACb,qBAAC,OAAD;GAEE,MAAK;GACL,aAAW,WAAW,QAAQ;GAC9B,WAAW,GACT,6GACA,cAAc,QAAQ,SAAS,MACjC;aAPF;IASG,cAAc,QAAQ,SAAS;IAChC,qBAAC,OAAD;KAAK,WAAU;eAAf;MACG,QAAQ,QACP,oBAAC,KAAD;OAAG,WAAU;iBAAkC,QAAQ;MAAS,CAAA,IAC9D;MACJ,oBAAC,KAAD;OAAG,WAAU;iBAAsB,QAAQ;MAAW,CAAA;MACrD,QAAQ,SACP,oBAAC,OAAD;OAAK,WAAU;iBACb,oBAAC,YAAD,EAAY,MAAM,QAAQ,OAAS,CAAA;MAChC,CAAA,IACH;KACD;;IACJ,QAAQ,cACP,oBAAC,UAAD;KACE,MAAK;KACL,cAAY,EAAE,kBAAkB,SAAS;KACzC,aAAU;KACV,WAAU;KACV,eAAe,QAAQ,QAAQ,EAAE;eAEjC,oBAAC,MAAD;MAAM,MAAK;MAAI,WAAU;KAAmB,CAAA;IACtC,CAAA,IACN;GACD;KA/BE,QAAQ,EA+BV,CACN;CACE,CAAA;AAET"}
1
+ {"version":3,"file":"callouts.js","names":[],"sources":["../../../resources/js/layout/components/callouts.tsx"],"sourcesContent":["import { Icon } from \"@lattice-php/lattice/icons\";\nimport { useEffect, useState } from \"react\";\nimport { RenderNode } from \"@lattice-php/lattice/core/renderer\";\nimport type { Callout } from \"@lattice-php/lattice/types/generated\";\nimport type { RendererComponent } from \"@lattice-php/lattice/core/types\";\nimport { onCallout } from \"@lattice-php/lattice/toast\";\nimport { cn } from \"@lattice-php/lattice/lib/utils\";\nimport { useT } from \"@lattice-php/lattice/i18n\";\nimport { resolveText } from \"@lattice-php/lattice/i18n/translatable\";\nimport { variantStyles } from \"@lattice-php/lattice/toast\";\n\ntype CalloutItem = Callout & { id: number };\n\nlet nextId = 0;\n\nconst Callouts: RendererComponent<\"callouts\"> = () => {\n const { t } = useT(\"lattice\");\n const [callouts, setCallouts] = useState<CalloutItem[]>([]);\n\n useEffect(\n () =>\n onCallout((callout) => {\n setCallouts((current) => [...current, { ...callout, id: nextId++ }]);\n }),\n [],\n );\n\n function dismiss(id: number): void {\n setCallouts((current) => current.filter((callout) => callout.id !== id));\n }\n\n if (callouts.length === 0) {\n return null;\n }\n\n return (\n <div className=\"flex w-full flex-col gap-2\">\n {callouts.map((callout) => (\n <div\n key={callout.id}\n role=\"status\"\n data-test={`callout-${callout.variant}`}\n className={cn(\n \"flex items-start gap-3 rounded-lt border border-l-4 border-lt-border bg-lt-popover p-4 text-lt-popover-fg\",\n variantStyles[callout.variant].accent,\n )}\n >\n {variantStyles[callout.variant].icon}\n <div className=\"flex min-w-0 flex-1 flex-col gap-2\">\n {callout.title ? (\n <p className=\"text-sm font-medium text-lt-fg\">{resolveText(callout.title, t)}</p>\n ) : null}\n <p className=\"text-sm text-lt-fg\">{resolveText(callout.message, t)}</p>\n {callout.action ? (\n <div className=\"flex flex-wrap gap-2\">\n <RenderNode node={callout.action} />\n </div>\n ) : null}\n </div>\n {callout.dismissible ? (\n <button\n type=\"button\"\n aria-label={t(\"common.dismiss\", \"Dismiss\")}\n data-test=\"callout-dismiss\"\n className=\"shrink-0 rounded-lt-sm p-1 text-lt-muted-fg transition-colors hover:bg-lt-muted hover:text-lt-fg\"\n onClick={() => dismiss(callout.id)}\n >\n <Icon name=\"x\" className=\"size-lt-icon-md\" />\n </button>\n ) : null}\n </div>\n ))}\n </div>\n );\n};\n\nexport default Callouts;\n"],"mappings":";;;;;;;;;;AAaA,IAAI,SAAS;AAEb,IAAM,iBAAgD;CACpD,MAAM,EAAE,MAAM,KAAK,SAAS;CAC5B,MAAM,CAAC,UAAU,eAAe,SAAwB,CAAC,CAAC;CAE1D,gBAEI,WAAW,YAAY;EACrB,aAAa,YAAY,CAAC,GAAG,SAAS;GAAE,GAAG;GAAS,IAAI;EAAS,CAAC,CAAC;CACrE,CAAC,GACH,CAAC,CACH;CAEA,SAAS,QAAQ,IAAkB;EACjC,aAAa,YAAY,QAAQ,QAAQ,YAAY,QAAQ,OAAO,EAAE,CAAC;CACzE;CAEA,IAAI,SAAS,WAAW,GACtB,OAAO;CAGT,OACE,oBAAC,OAAD;EAAK,WAAU;YACZ,SAAS,KAAK,YACb,qBAAC,OAAD;GAEE,MAAK;GACL,aAAW,WAAW,QAAQ;GAC9B,WAAW,GACT,6GACA,cAAc,QAAQ,SAAS,MACjC;aAPF;IASG,cAAc,QAAQ,SAAS;IAChC,qBAAC,OAAD;KAAK,WAAU;eAAf;MACG,QAAQ,QACP,oBAAC,KAAD;OAAG,WAAU;iBAAkC,YAAY,QAAQ,OAAO,CAAC;MAAK,CAAA,IAC9E;MACJ,oBAAC,KAAD;OAAG,WAAU;iBAAsB,YAAY,QAAQ,SAAS,CAAC;MAAK,CAAA;MACrE,QAAQ,SACP,oBAAC,OAAD;OAAK,WAAU;iBACb,oBAAC,YAAD,EAAY,MAAM,QAAQ,OAAS,CAAA;MAChC,CAAA,IACH;KACD;;IACJ,QAAQ,cACP,oBAAC,UAAD;KACE,MAAK;KACL,cAAY,EAAE,kBAAkB,SAAS;KACzC,aAAU;KACV,WAAU;KACV,eAAe,QAAQ,QAAQ,EAAE;eAEjC,oBAAC,MAAD;MAAM,MAAK;MAAI,WAAU;KAAmB,CAAA;IACtC,CAAA,IACN;GACD;KA/BE,QAAQ,EA+BV,CACN;CACE,CAAA;AAET"}
@@ -2,6 +2,7 @@ import { useT } from "../../i18n/instance.js";
2
2
  import { cn } from "../../lib/utils.js";
3
3
  import { IconRenderer } from "../../icons/icon-renderer.js";
4
4
  import { RenderNode } from "../../core/renderer.js";
5
+ import { resolveText } from "../../i18n/translatable.js";
5
6
  import { Link } from "@inertiajs/react";
6
7
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
7
8
  //#region resources/js/notifications/components/notification-item.tsx
@@ -13,12 +14,14 @@ var variantIconClass = {
13
14
  };
14
15
  function NotificationItemRow({ notification, onMarkRead, onDismiss }) {
15
16
  const { t } = useT("lattice");
16
- const content = /* @__PURE__ */ jsxs(Fragment, { children: [notification.title ? /* @__PURE__ */ jsx("p", {
17
+ const title = resolveText(notification.title, t);
18
+ const body = resolveText(notification.body, t);
19
+ const content = /* @__PURE__ */ jsxs(Fragment, { children: [title ? /* @__PURE__ */ jsx("p", {
17
20
  className: "truncate text-sm font-medium text-lt-fg",
18
- children: notification.title
19
- }) : null, notification.body ? /* @__PURE__ */ jsx("p", {
21
+ children: title
22
+ }) : null, body ? /* @__PURE__ */ jsx("p", {
20
23
  className: "text-sm text-lt-muted-fg",
21
- children: notification.body
24
+ children: body
22
25
  }) : null] });
23
26
  return /* @__PURE__ */ jsxs("li", {
24
27
  className: cn("flex gap-3 px-3 py-3", !notification.isRead && "bg-lt-muted/40"),
@@ -1 +1 @@
1
- {"version":3,"file":"notification-item.js","names":[],"sources":["../../../resources/js/notifications/components/notification-item.tsx"],"sourcesContent":["import { Link } from \"@inertiajs/react\";\nimport { RenderNode } from \"@lattice-php/lattice/core/renderer\";\nimport { IconRenderer } from \"@lattice-php/lattice/icons\";\nimport { useT } from \"@lattice-php/lattice/i18n\";\nimport { cn } from \"@lattice-php/lattice/lib/utils\";\nimport type { NotificationItem } from \"@lattice-php/lattice/notifications/types\";\n\nconst variantIconClass: Record<NonNullable<NotificationItem[\"variant\"]>, string> = {\n success: \"text-lt-success\",\n info: \"text-lt-info\",\n warning: \"text-lt-warning\",\n error: \"text-lt-danger\",\n};\n\nexport function NotificationItemRow({\n notification,\n onMarkRead,\n onDismiss,\n}: {\n notification: NotificationItem;\n onMarkRead: (id: string) => void;\n onDismiss: (id: string) => void;\n}) {\n const { t } = useT(\"lattice\");\n\n const content = (\n <>\n {notification.title ? (\n <p className=\"truncate text-sm font-medium text-lt-fg\">{notification.title}</p>\n ) : null}\n {notification.body ? <p className=\"text-sm text-lt-muted-fg\">{notification.body}</p> : null}\n </>\n );\n\n return (\n <li\n className={cn(\"flex gap-3 px-3 py-3\", !notification.isRead && \"bg-lt-muted/40\")}\n data-test=\"notification\"\n >\n {notification.icon ? (\n <IconRenderer\n icon={notification.icon}\n className={cn(\n \"mt-0.5 size-lt-icon-md\",\n notification.variant ? variantIconClass[notification.variant] : undefined,\n )}\n />\n ) : null}\n <div className=\"min-w-0 flex-1\">\n {notification.href ? (\n <Link\n href={notification.href}\n className=\"block\"\n data-test=\"notification-link\"\n onClick={() => onMarkRead(notification.id)}\n >\n {content}\n </Link>\n ) : (\n content\n )}\n {notification.actions.length > 0 ? (\n <div className=\"mt-2 flex flex-wrap gap-2\">\n {notification.actions.map((node, index) => (\n <RenderNode key={node.key ?? node.id ?? `action-${index}`} node={node} />\n ))}\n </div>\n ) : null}\n </div>\n <div className=\"flex shrink-0 flex-col gap-1\">\n {!notification.isRead ? (\n <button\n type=\"button\"\n className=\"text-xs text-lt-muted-fg hover:text-lt-fg\"\n onClick={() => onMarkRead(notification.id)}\n >\n {t(\"notifications.mark-read\", \"Mark read\")}\n </button>\n ) : null}\n <button\n type=\"button\"\n aria-label={t(\"notifications.dismiss\", \"Dismiss\")}\n className=\"text-xs text-lt-muted-fg hover:text-lt-fg\"\n onClick={() => onDismiss(notification.id)}\n >\n {t(\"notifications.dismiss\", \"Dismiss\")}\n </button>\n </div>\n </li>\n );\n}\n"],"mappings":";;;;;;;AAOA,IAAM,mBAA6E;CACjF,SAAS;CACT,MAAM;CACN,SAAS;CACT,OAAO;AACT;AAEA,SAAgB,oBAAoB,EAClC,cACA,YACA,aAKC;CACD,MAAM,EAAE,MAAM,KAAK,SAAS;CAE5B,MAAM,UACJ,qBAAA,UAAA,EAAA,UAAA,CACG,aAAa,QACZ,oBAAC,KAAD;EAAG,WAAU;YAA2C,aAAa;CAAS,CAAA,IAC5E,MACH,aAAa,OAAO,oBAAC,KAAD;EAAG,WAAU;YAA4B,aAAa;CAAQ,CAAA,IAAI,IACvF,EAAA,CAAA;CAGJ,OACE,qBAAC,MAAD;EACE,WAAW,GAAG,wBAAwB,CAAC,aAAa,UAAU,gBAAgB;EAC9E,aAAU;YAFZ;GAIG,aAAa,OACZ,oBAAC,cAAD;IACE,MAAM,aAAa;IACnB,WAAW,GACT,0BACA,aAAa,UAAU,iBAAiB,aAAa,WAAW,KAAA,CAClE;GACD,CAAA,IACC;GACJ,qBAAC,OAAD;IAAK,WAAU;cAAf,CACG,aAAa,OACZ,oBAAC,MAAD;KACE,MAAM,aAAa;KACnB,WAAU;KACV,aAAU;KACV,eAAe,WAAW,aAAa,EAAE;eAExC;IACG,CAAA,IAEN,SAED,aAAa,QAAQ,SAAS,IAC7B,oBAAC,OAAD;KAAK,WAAU;eACZ,aAAa,QAAQ,KAAK,MAAM,UAC/B,oBAAC,YAAD,EAAiE,KAAO,GAAvD,KAAK,OAAO,KAAK,MAAM,UAAU,OAAsB,CACzE;IACE,CAAA,IACH,IACD;;GACL,qBAAC,OAAD;IAAK,WAAU;cAAf,CACG,CAAC,aAAa,SACb,oBAAC,UAAD;KACE,MAAK;KACL,WAAU;KACV,eAAe,WAAW,aAAa,EAAE;eAExC,EAAE,2BAA2B,WAAW;IACnC,CAAA,IACN,MACJ,oBAAC,UAAD;KACE,MAAK;KACL,cAAY,EAAE,yBAAyB,SAAS;KAChD,WAAU;KACV,eAAe,UAAU,aAAa,EAAE;eAEvC,EAAE,yBAAyB,SAAS;IAC/B,CAAA,CACL;;EACH;;AAER"}
1
+ {"version":3,"file":"notification-item.js","names":[],"sources":["../../../resources/js/notifications/components/notification-item.tsx"],"sourcesContent":["import { Link } from \"@inertiajs/react\";\nimport { RenderNode } from \"@lattice-php/lattice/core/renderer\";\nimport { IconRenderer } from \"@lattice-php/lattice/icons\";\nimport { useT } from \"@lattice-php/lattice/i18n\";\nimport { resolveText } from \"@lattice-php/lattice/i18n/translatable\";\nimport { cn } from \"@lattice-php/lattice/lib/utils\";\nimport type { NotificationItem } from \"@lattice-php/lattice/notifications/types\";\n\nconst variantIconClass: Record<NonNullable<NotificationItem[\"variant\"]>, string> = {\n success: \"text-lt-success\",\n info: \"text-lt-info\",\n warning: \"text-lt-warning\",\n error: \"text-lt-danger\",\n};\n\nexport function NotificationItemRow({\n notification,\n onMarkRead,\n onDismiss,\n}: {\n notification: NotificationItem;\n onMarkRead: (id: string) => void;\n onDismiss: (id: string) => void;\n}) {\n const { t } = useT(\"lattice\");\n\n const title = resolveText(notification.title, t);\n const body = resolveText(notification.body, t);\n\n const content = (\n <>\n {title ? <p className=\"truncate text-sm font-medium text-lt-fg\">{title}</p> : null}\n {body ? <p className=\"text-sm text-lt-muted-fg\">{body}</p> : null}\n </>\n );\n\n return (\n <li\n className={cn(\"flex gap-3 px-3 py-3\", !notification.isRead && \"bg-lt-muted/40\")}\n data-test=\"notification\"\n >\n {notification.icon ? (\n <IconRenderer\n icon={notification.icon}\n className={cn(\n \"mt-0.5 size-lt-icon-md\",\n notification.variant ? variantIconClass[notification.variant] : undefined,\n )}\n />\n ) : null}\n <div className=\"min-w-0 flex-1\">\n {notification.href ? (\n <Link\n href={notification.href}\n className=\"block\"\n data-test=\"notification-link\"\n onClick={() => onMarkRead(notification.id)}\n >\n {content}\n </Link>\n ) : (\n content\n )}\n {notification.actions.length > 0 ? (\n <div className=\"mt-2 flex flex-wrap gap-2\">\n {notification.actions.map((node, index) => (\n <RenderNode key={node.key ?? node.id ?? `action-${index}`} node={node} />\n ))}\n </div>\n ) : null}\n </div>\n <div className=\"flex shrink-0 flex-col gap-1\">\n {!notification.isRead ? (\n <button\n type=\"button\"\n className=\"text-xs text-lt-muted-fg hover:text-lt-fg\"\n onClick={() => onMarkRead(notification.id)}\n >\n {t(\"notifications.mark-read\", \"Mark read\")}\n </button>\n ) : null}\n <button\n type=\"button\"\n aria-label={t(\"notifications.dismiss\", \"Dismiss\")}\n className=\"text-xs text-lt-muted-fg hover:text-lt-fg\"\n onClick={() => onDismiss(notification.id)}\n >\n {t(\"notifications.dismiss\", \"Dismiss\")}\n </button>\n </div>\n </li>\n );\n}\n"],"mappings":";;;;;;;;AAQA,IAAM,mBAA6E;CACjF,SAAS;CACT,MAAM;CACN,SAAS;CACT,OAAO;AACT;AAEA,SAAgB,oBAAoB,EAClC,cACA,YACA,aAKC;CACD,MAAM,EAAE,MAAM,KAAK,SAAS;CAE5B,MAAM,QAAQ,YAAY,aAAa,OAAO,CAAC;CAC/C,MAAM,OAAO,YAAY,aAAa,MAAM,CAAC;CAE7C,MAAM,UACJ,qBAAA,UAAA,EAAA,UAAA,CACG,QAAQ,oBAAC,KAAD;EAAG,WAAU;YAA2C;CAAS,CAAA,IAAI,MAC7E,OAAO,oBAAC,KAAD;EAAG,WAAU;YAA4B;CAAQ,CAAA,IAAI,IAC7D,EAAA,CAAA;CAGJ,OACE,qBAAC,MAAD;EACE,WAAW,GAAG,wBAAwB,CAAC,aAAa,UAAU,gBAAgB;EAC9E,aAAU;YAFZ;GAIG,aAAa,OACZ,oBAAC,cAAD;IACE,MAAM,aAAa;IACnB,WAAW,GACT,0BACA,aAAa,UAAU,iBAAiB,aAAa,WAAW,KAAA,CAClE;GACD,CAAA,IACC;GACJ,qBAAC,OAAD;IAAK,WAAU;cAAf,CACG,aAAa,OACZ,oBAAC,MAAD;KACE,MAAM,aAAa;KACnB,WAAU;KACV,aAAU;KACV,eAAe,WAAW,aAAa,EAAE;eAExC;IACG,CAAA,IAEN,SAED,aAAa,QAAQ,SAAS,IAC7B,oBAAC,OAAD;KAAK,WAAU;eACZ,aAAa,QAAQ,KAAK,MAAM,UAC/B,oBAAC,YAAD,EAAiE,KAAO,GAAvD,KAAK,OAAO,KAAK,MAAM,UAAU,OAAsB,CACzE;IACE,CAAA,IACH,IACD;;GACL,qBAAC,OAAD;IAAK,WAAU;cAAf,CACG,CAAC,aAAa,SACb,oBAAC,UAAD;KACE,MAAK;KACL,WAAU;KACV,eAAe,WAAW,aAAa,EAAE;eAExC,EAAE,2BAA2B,WAAW;IACnC,CAAA,IACN,MACJ,oBAAC,UAAD;KACE,MAAK;KACL,cAAY,EAAE,yBAAyB,SAAS;KAChD,WAAU;KACV,eAAe,UAAU,aAAa,EAAE;eAEvC,EAAE,yBAAyB,SAAS;IAC/B,CAAA,CACL;;EACH;;AAER"}
@@ -59,7 +59,10 @@ function SchemaControl({ filter, schema, value, processing, bare, onChange, onSe
59
59
  precognitive: false,
60
60
  processing,
61
61
  searchOptions: (field, query, _values, signal) => onSearch ? onSearch(field, query, signal) : Promise.resolve([]),
62
- validate: () => {}
62
+ touch: () => {},
63
+ validate: () => {},
64
+ validateFields: () => {},
65
+ validating: false
63
66
  }), [
64
67
  filter.key,
65
68
  onSearch,
@@ -1 +1 @@
1
- {"version":3,"file":"filter-controls.js","names":[],"sources":["../../../resources/js/table/components/filter-controls.tsx"],"sourcesContent":["import { useCallback, useMemo, useRef } from \"react\";\nimport type { ReactNode } from \"react\";\nimport { Checkbox } from \"@lattice-php/lattice/ui/checkbox\";\nimport { Renderer } from \"@lattice-php/lattice/core/renderer\";\nimport type { Node, Option } from \"@lattice-php/lattice/core/types\";\nimport {\n FieldCommitOverrideProvider,\n FormProvider,\n FormValuesProvider,\n getPath,\n PrefillProvider,\n ResolvedNodesProvider,\n setPath,\n TableCellProvider,\n useFormValues,\n useSetFormValue,\n} from \"@lattice-php/lattice/form/embed\";\nimport { IconButton } from \"@lattice-php/lattice/ui/icon-button\";\nimport { useT } from \"@lattice-php/lattice/i18n\";\nimport { cn } from \"@lattice-php/lattice/lib/utils\";\nimport { isTruthy } from \"@lattice-php/lattice/lib/is-truthy\";\nimport { filterValue, isActiveFilterValue } from \"@lattice-php/lattice/table/lib/filter-values\";\nimport type { FilterNode } from \"@lattice-php/lattice/table/types\";\n\nexport type FilterOptionSearch = (\n field: string,\n query: string,\n signal: AbortSignal,\n) => Promise<Option[]>;\n\ntype FilterValue = Record<string, unknown>;\n\nexport function TableFilterControl({\n filter,\n value,\n processing,\n bare = false,\n onChange,\n onSearch,\n}: {\n filter: FilterNode;\n value: unknown;\n processing: boolean;\n bare?: boolean;\n onChange: (value: unknown) => void;\n onSearch?: FilterOptionSearch;\n}) {\n const { t } = useT(\"lattice\");\n const schema = filter.schema ?? [];\n\n if (schema.length === 0) {\n return (\n <ToggleControl filter={filter} value={value} processing={processing} onChange={onChange} />\n );\n }\n\n return (\n <div className=\"flex items-end gap-2\">\n <div className=\"min-w-0 flex-1\">\n <SchemaControl\n filter={filter}\n schema={schema}\n value={value}\n processing={processing}\n bare={bare}\n onChange={onChange}\n onSearch={onSearch}\n />\n </div>\n {isActiveFilterValue(value) && (\n <IconButton\n size=\"md\"\n icon=\"x\"\n label={t(\"table.filter.clear\", \"Clear {{label}} filter\", {\n label: filter.props.label ?? \"\",\n })}\n disabled={processing}\n onClick={() => onChange(undefined)}\n />\n )}\n </div>\n );\n}\n\nfunction SchemaControl({\n filter,\n schema,\n value,\n processing,\n bare,\n onChange,\n onSearch,\n}: {\n filter: FilterNode;\n schema: Node[];\n value: unknown;\n processing: boolean;\n bare: boolean;\n onChange: (value: unknown) => void;\n onSearch?: FilterOptionSearch;\n}) {\n const initial = useMemo(() => filterValue(value), [value]);\n const form = useMemo(\n () => ({\n action: \"#\",\n clearErrors: () => {},\n componentId: `table-filter-${filter.key}`,\n componentRef: \"\",\n errors: {},\n fieldIdPrefix: `table-filter-${filter.key}`,\n fieldLabels: {},\n precognitive: false,\n processing,\n searchOptions: (\n field: string,\n query: string,\n _values: Record<string, unknown>,\n signal: AbortSignal,\n ) => (onSearch ? onSearch(field, query, signal) : Promise.resolve([])),\n validate: () => {},\n }),\n [filter.key, onSearch, processing],\n );\n\n const content = (\n <div\n aria-disabled={processing}\n className={cn(\"grid gap-3\", processing && \"pointer-events-none opacity-60\")}\n >\n <Renderer nodes={schema} />\n </div>\n );\n\n return (\n <FormProvider value={form}>\n <PrefillProvider value={{ markUserEdit: () => {} }}>\n <ResolvedNodesProvider nodes={{}}>\n <FormValuesProvider initial={initial}>\n <TableFilterCommitBridge onChange={onChange}>\n {bare ? <TableCellProvider>{content}</TableCellProvider> : content}\n </TableFilterCommitBridge>\n </FormValuesProvider>\n </ResolvedNodesProvider>\n </PrefillProvider>\n </FormProvider>\n );\n}\n\nfunction TableFilterCommitBridge({\n children,\n onChange,\n}: {\n children: ReactNode;\n onChange: (value: FilterValue) => void;\n}) {\n const values = useFormValues();\n const setValue = useSetFormValue();\n const valuesRef = useRef(values);\n valuesRef.current = values;\n\n const write = useCallback(\n (name: string, value: unknown) => {\n const nextValue =\n typeof value === \"function\"\n ? (value as (previous: unknown) => unknown)(getPath(valuesRef.current, name))\n : value;\n const next = setPath(valuesRef.current, name, nextValue);\n\n valuesRef.current = next;\n setValue(name, nextValue);\n onChange(next);\n },\n [onChange, setValue],\n );\n\n const commit = useMemo(\n () => ({\n blur: () => {},\n change: write,\n commit: write,\n }),\n [write],\n );\n\n return <FieldCommitOverrideProvider value={commit}>{children}</FieldCommitOverrideProvider>;\n}\n\nfunction ToggleControl({\n filter,\n value,\n processing,\n onChange,\n}: {\n filter: FilterNode;\n value: unknown;\n processing: boolean;\n onChange: (value: unknown) => void;\n}) {\n const checked = isTruthy(filterValue(value).value);\n\n return (\n <label className=\"flex h-lt-control-md cursor-pointer items-center gap-2 text-sm\">\n <Checkbox\n aria-label={filter.props.label ?? undefined}\n data-test={`table-filter-${filter.key}`}\n checked={checked}\n disabled={processing}\n onCheckedChange={(next) => onChange(next === true ? { value: \"1\" } : undefined)}\n />\n <span>{filter.props.label}</span>\n </label>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"filter-controls.js","names":[],"sources":["../../../resources/js/table/components/filter-controls.tsx"],"sourcesContent":["import { useCallback, useMemo, useRef } from \"react\";\nimport type { ReactNode } from \"react\";\nimport { Checkbox } from \"@lattice-php/lattice/ui/checkbox\";\nimport { Renderer } from \"@lattice-php/lattice/core/renderer\";\nimport type { Node, Option } from \"@lattice-php/lattice/core/types\";\nimport {\n FieldCommitOverrideProvider,\n FormProvider,\n FormValuesProvider,\n getPath,\n PrefillProvider,\n ResolvedNodesProvider,\n setPath,\n TableCellProvider,\n useFormValues,\n useSetFormValue,\n} from \"@lattice-php/lattice/form/embed\";\nimport { IconButton } from \"@lattice-php/lattice/ui/icon-button\";\nimport { useT } from \"@lattice-php/lattice/i18n\";\nimport { cn } from \"@lattice-php/lattice/lib/utils\";\nimport { isTruthy } from \"@lattice-php/lattice/lib/is-truthy\";\nimport { filterValue, isActiveFilterValue } from \"@lattice-php/lattice/table/lib/filter-values\";\nimport type { FilterNode } from \"@lattice-php/lattice/table/types\";\n\nexport type FilterOptionSearch = (\n field: string,\n query: string,\n signal: AbortSignal,\n) => Promise<Option[]>;\n\ntype FilterValue = Record<string, unknown>;\n\nexport function TableFilterControl({\n filter,\n value,\n processing,\n bare = false,\n onChange,\n onSearch,\n}: {\n filter: FilterNode;\n value: unknown;\n processing: boolean;\n bare?: boolean;\n onChange: (value: unknown) => void;\n onSearch?: FilterOptionSearch;\n}) {\n const { t } = useT(\"lattice\");\n const schema = filter.schema ?? [];\n\n if (schema.length === 0) {\n return (\n <ToggleControl filter={filter} value={value} processing={processing} onChange={onChange} />\n );\n }\n\n return (\n <div className=\"flex items-end gap-2\">\n <div className=\"min-w-0 flex-1\">\n <SchemaControl\n filter={filter}\n schema={schema}\n value={value}\n processing={processing}\n bare={bare}\n onChange={onChange}\n onSearch={onSearch}\n />\n </div>\n {isActiveFilterValue(value) && (\n <IconButton\n size=\"md\"\n icon=\"x\"\n label={t(\"table.filter.clear\", \"Clear {{label}} filter\", {\n label: filter.props.label ?? \"\",\n })}\n disabled={processing}\n onClick={() => onChange(undefined)}\n />\n )}\n </div>\n );\n}\n\nfunction SchemaControl({\n filter,\n schema,\n value,\n processing,\n bare,\n onChange,\n onSearch,\n}: {\n filter: FilterNode;\n schema: Node[];\n value: unknown;\n processing: boolean;\n bare: boolean;\n onChange: (value: unknown) => void;\n onSearch?: FilterOptionSearch;\n}) {\n const initial = useMemo(() => filterValue(value), [value]);\n const form = useMemo(\n () => ({\n action: \"#\",\n clearErrors: () => {},\n componentId: `table-filter-${filter.key}`,\n componentRef: \"\",\n errors: {},\n fieldIdPrefix: `table-filter-${filter.key}`,\n fieldLabels: {},\n precognitive: false,\n processing,\n searchOptions: (\n field: string,\n query: string,\n _values: Record<string, unknown>,\n signal: AbortSignal,\n ) => (onSearch ? onSearch(field, query, signal) : Promise.resolve([])),\n touch: () => {},\n validate: () => {},\n validateFields: () => {},\n validating: false,\n }),\n [filter.key, onSearch, processing],\n );\n\n const content = (\n <div\n aria-disabled={processing}\n className={cn(\"grid gap-3\", processing && \"pointer-events-none opacity-60\")}\n >\n <Renderer nodes={schema} />\n </div>\n );\n\n return (\n <FormProvider value={form}>\n <PrefillProvider value={{ markUserEdit: () => {} }}>\n <ResolvedNodesProvider nodes={{}}>\n <FormValuesProvider initial={initial}>\n <TableFilterCommitBridge onChange={onChange}>\n {bare ? <TableCellProvider>{content}</TableCellProvider> : content}\n </TableFilterCommitBridge>\n </FormValuesProvider>\n </ResolvedNodesProvider>\n </PrefillProvider>\n </FormProvider>\n );\n}\n\nfunction TableFilterCommitBridge({\n children,\n onChange,\n}: {\n children: ReactNode;\n onChange: (value: FilterValue) => void;\n}) {\n const values = useFormValues();\n const setValue = useSetFormValue();\n const valuesRef = useRef(values);\n valuesRef.current = values;\n\n const write = useCallback(\n (name: string, value: unknown) => {\n const nextValue =\n typeof value === \"function\"\n ? (value as (previous: unknown) => unknown)(getPath(valuesRef.current, name))\n : value;\n const next = setPath(valuesRef.current, name, nextValue);\n\n valuesRef.current = next;\n setValue(name, nextValue);\n onChange(next);\n },\n [onChange, setValue],\n );\n\n const commit = useMemo(\n () => ({\n blur: () => {},\n change: write,\n commit: write,\n }),\n [write],\n );\n\n return <FieldCommitOverrideProvider value={commit}>{children}</FieldCommitOverrideProvider>;\n}\n\nfunction ToggleControl({\n filter,\n value,\n processing,\n onChange,\n}: {\n filter: FilterNode;\n value: unknown;\n processing: boolean;\n onChange: (value: unknown) => void;\n}) {\n const checked = isTruthy(filterValue(value).value);\n\n return (\n <label className=\"flex h-lt-control-md cursor-pointer items-center gap-2 text-sm\">\n <Checkbox\n aria-label={filter.props.label ?? undefined}\n data-test={`table-filter-${filter.key}`}\n checked={checked}\n disabled={processing}\n onCheckedChange={(next) => onChange(next === true ? { value: \"1\" } : undefined)}\n />\n <span>{filter.props.label}</span>\n </label>\n );\n}\n"],"mappings":"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"}
@@ -1,15 +1,18 @@
1
1
  import { LATTICE_EVENT } from "../core/event-names.js";
2
+ import { isTranslatable } from "../i18n/translatable.js";
2
3
  import { isVariant } from "./toast.js";
3
4
  //#region resources/js/toast/callout.ts
4
5
  function normalizeCallout(detail) {
5
6
  if (typeof detail !== "object" || detail === null) return null;
6
7
  const callout = detail;
7
- if (typeof callout.message !== "string" || callout.message === "") return null;
8
+ const rawMessage = callout.message;
9
+ const message = typeof rawMessage === "string" ? rawMessage : isTranslatable(rawMessage) ? rawMessage : null;
10
+ if (message === null || message === "") return null;
8
11
  return {
9
12
  action: callout.action ?? null,
10
13
  dismissible: callout.dismissible !== false,
11
- message: callout.message,
12
- title: typeof callout.title === "string" ? callout.title : null,
14
+ message,
15
+ title: typeof callout.title === "string" || isTranslatable(callout.title) ? callout.title : null,
13
16
  variant: isVariant(callout.variant) ? callout.variant : "info"
14
17
  };
15
18
  }
@@ -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/core/event-names\";\nimport { isVariant } from \"./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 callout = detail 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,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"}
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/core/event-names\";\nimport { isTranslatable } from \"@lattice-php/lattice/i18n/translatable\";\nimport { isVariant } from \"./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 callout = detail as Record<string, unknown>;\n\n const rawMessage = callout.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: (callout.action as Callout[\"action\"]) ?? null,\n dismissible: callout.dismissible !== false,\n message,\n title:\n typeof callout.title === \"string\" || isTranslatable(callout.title) ? 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":";;;;AAOA,SAAgB,iBAAiB,QAAiC;CAChE,IAAI,OAAO,WAAW,YAAY,WAAW,MAC3C,OAAO;CAGT,MAAM,UAAU;CAEhB,MAAM,aAAa,QAAQ;CAC3B,MAAM,UACJ,OAAO,eAAe,WAAW,aAAa,eAAe,UAAU,IAAI,aAAa;CAE1F,IAAI,YAAY,QAAQ,YAAY,IAClC,OAAO;CAGT,OAAO;EACL,QAAS,QAAQ,UAAgC;EACjD,aAAa,QAAQ,gBAAgB;EACrC;EACA,OACE,OAAO,QAAQ,UAAU,YAAY,eAAe,QAAQ,KAAK,IAAI,QAAQ,QAAQ;EACvF,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"}
@@ -2,7 +2,7 @@ import { useT } from "../i18n/instance.js";
2
2
  import { cn } from "../lib/utils.js";
3
3
  import { Icon } from "../icons/sprite.js";
4
4
  import { RenderNode } from "../core/renderer.js";
5
- import { resolveTranslatable } from "../i18n/translatable.js";
5
+ import { resolveText } from "../i18n/translatable.js";
6
6
  import { onToast } from "./toast.js";
7
7
  import { variantStyles } from "./variant-styles.js";
8
8
  import { useEffect, useState } from "react";
@@ -38,7 +38,7 @@ function Toaster({ duration = 4e3 }) {
38
38
  className: "flex min-w-0 flex-1 flex-col gap-2",
39
39
  children: [/* @__PURE__ */ jsx(Toast.Title, {
40
40
  className: "text-sm text-lt-fg",
41
- children: typeof toast.message === "string" ? toast.message : resolveTranslatable(toast.message, {}, t)
41
+ children: resolveText(toast.message, t)
42
42
  }), toast.action ? /* @__PURE__ */ jsx("div", {
43
43
  className: "flex flex-wrap gap-2",
44
44
  children: /* @__PURE__ */ jsx(RenderNode, { node: toast.action })
@@ -1 +1 @@
1
- {"version":3,"file":"toaster.js","names":[],"sources":["../../resources/js/toast/toaster.tsx"],"sourcesContent":["import { Icon } from \"@lattice-php/lattice/icons\";\nimport * as Toast from \"@radix-ui/react-toast\";\nimport { useEffect, useState } from \"react\";\nimport { RenderNode } from \"@lattice-php/lattice/core/renderer\";\nimport type { Toast as ToastMessage } from \"@lattice-php/lattice/types/generated\";\nimport { onToast } from \"./toast\";\nimport { cn } from \"@lattice-php/lattice/lib/utils\";\nimport { useT } from \"@lattice-php/lattice/i18n\";\nimport { variantStyles } from \"./variant-styles\";\nimport { resolveTranslatable } from \"@lattice-php/lattice/i18n/translatable\";\n\ntype ToastItem = ToastMessage & { id: number };\n\nlet nextId = 0;\n\nexport function Toaster({ duration = 4000 }: { duration?: number }) {\n const { t } = useT(\"lattice\");\n const [toasts, setToasts] = useState<ToastItem[]>([]);\n\n function dismiss(id: number): void {\n setToasts((current) => current.filter((toast) => toast.id !== id));\n }\n\n useEffect(\n () =>\n onToast((toast) => {\n setToasts((current) => [...current, { ...toast, id: nextId++ }]);\n }),\n [],\n );\n\n return (\n <Toast.Provider duration={duration} swipeDirection=\"down\">\n {toasts.map((toast) => (\n <Toast.Root\n key={toast.id}\n className={cn(\n \"flex items-start gap-3 rounded-lt border border-l-4 border-lt-border bg-lt-popover p-4 text-lt-popover-fg shadow-lt-lg\",\n variantStyles[toast.variant].accent,\n \"data-[state=open]:animate-lt-toast-in data-[state=closed]:animate-lt-toast-out\",\n \"data-[swipe=move]:translate-y-[var(--radix-toast-swipe-move-y)] data-[swipe=cancel]:translate-y-0 data-[swipe=cancel]:transition-transform\",\n )}\n data-test={`toast-${toast.variant}`}\n duration={toast.persistent ? Infinity : (toast.duration ?? duration)}\n onOpenChange={(open) => {\n if (!open) {\n dismiss(toast.id);\n }\n }}\n >\n {variantStyles[toast.variant].icon}\n <div className=\"flex min-w-0 flex-1 flex-col gap-2\">\n <Toast.Title className=\"text-sm text-lt-fg\">\n {typeof toast.message === \"string\"\n ? toast.message\n : resolveTranslatable(toast.message, {}, t)}\n </Toast.Title>\n {toast.action ? (\n <div className=\"flex flex-wrap gap-2\">\n <RenderNode node={toast.action} />\n </div>\n ) : null}\n </div>\n {toast.dismissible ? (\n <Toast.Close\n aria-label={t(\"common.dismiss\", \"Dismiss\")}\n className=\"shrink-0 rounded-lt-sm p-1 text-lt-muted-fg transition-colors hover:bg-lt-muted hover:text-lt-fg\"\n data-test=\"toast-dismiss\"\n >\n <Icon name=\"x\" className=\"size-lt-icon-md\" />\n </Toast.Close>\n ) : null}\n </Toast.Root>\n ))}\n <Toast.Viewport className=\"fixed inset-x-0 bottom-0 z-lt-toast mx-auto flex w-full max-w-sm flex-col gap-2 p-4 outline-none\" />\n </Toast.Provider>\n );\n}\n"],"mappings":";;;;;;;;;;;AAaA,IAAI,SAAS;AAEb,SAAgB,QAAQ,EAAE,WAAW,OAA+B;CAClE,MAAM,EAAE,MAAM,KAAK,SAAS;CAC5B,MAAM,CAAC,QAAQ,aAAa,SAAsB,CAAC,CAAC;CAEpD,SAAS,QAAQ,IAAkB;EACjC,WAAW,YAAY,QAAQ,QAAQ,UAAU,MAAM,OAAO,EAAE,CAAC;CACnE;CAEA,gBAEI,SAAS,UAAU;EACjB,WAAW,YAAY,CAAC,GAAG,SAAS;GAAE,GAAG;GAAO,IAAI;EAAS,CAAC,CAAC;CACjE,CAAC,GACH,CAAC,CACH;CAEA,OACE,qBAAC,MAAM,UAAP;EAA0B;EAAU,gBAAe;YAAnD,CACG,OAAO,KAAK,UACX,qBAAC,MAAM,MAAP;GAEE,WAAW,GACT,0HACA,cAAc,MAAM,SAAS,QAC7B,kFACA,4IACF;GACA,aAAW,SAAS,MAAM;GAC1B,UAAU,MAAM,aAAa,WAAY,MAAM,YAAY;GAC3D,eAAe,SAAS;IACtB,IAAI,CAAC,MACH,QAAQ,MAAM,EAAE;GAEpB;aAdF;IAgBG,cAAc,MAAM,SAAS;IAC9B,qBAAC,OAAD;KAAK,WAAU;eAAf,CACE,oBAAC,MAAM,OAAP;MAAa,WAAU;gBACpB,OAAO,MAAM,YAAY,WACtB,MAAM,UACN,oBAAoB,MAAM,SAAS,CAAC,GAAG,CAAC;KACjC,CAAA,GACZ,MAAM,SACL,oBAAC,OAAD;MAAK,WAAU;gBACb,oBAAC,YAAD,EAAY,MAAM,MAAM,OAAS,CAAA;KAC9B,CAAA,IACH,IACD;;IACJ,MAAM,cACL,oBAAC,MAAM,OAAP;KACE,cAAY,EAAE,kBAAkB,SAAS;KACzC,WAAU;KACV,aAAU;eAEV,oBAAC,MAAD;MAAM,MAAK;MAAI,WAAU;KAAmB,CAAA;IACjC,CAAA,IACX;GACM;KArCL,MAAM,EAqCD,CACb,GACD,oBAAC,MAAM,UAAP,EAAgB,WAAU,mGAAoG,CAAA,CAChH;;AAEpB"}
1
+ {"version":3,"file":"toaster.js","names":[],"sources":["../../resources/js/toast/toaster.tsx"],"sourcesContent":["import { Icon } from \"@lattice-php/lattice/icons\";\nimport * as Toast from \"@radix-ui/react-toast\";\nimport { useEffect, useState } from \"react\";\nimport { RenderNode } from \"@lattice-php/lattice/core/renderer\";\nimport type { Toast as ToastMessage } from \"@lattice-php/lattice/types/generated\";\nimport { onToast } from \"./toast\";\nimport { cn } from \"@lattice-php/lattice/lib/utils\";\nimport { useT } from \"@lattice-php/lattice/i18n\";\nimport { variantStyles } from \"./variant-styles\";\nimport { resolveText } from \"@lattice-php/lattice/i18n/translatable\";\n\ntype ToastItem = ToastMessage & { id: number };\n\nlet nextId = 0;\n\nexport function Toaster({ duration = 4000 }: { duration?: number }) {\n const { t } = useT(\"lattice\");\n const [toasts, setToasts] = useState<ToastItem[]>([]);\n\n function dismiss(id: number): void {\n setToasts((current) => current.filter((toast) => toast.id !== id));\n }\n\n useEffect(\n () =>\n onToast((toast) => {\n setToasts((current) => [...current, { ...toast, id: nextId++ }]);\n }),\n [],\n );\n\n return (\n <Toast.Provider duration={duration} swipeDirection=\"down\">\n {toasts.map((toast) => (\n <Toast.Root\n key={toast.id}\n className={cn(\n \"flex items-start gap-3 rounded-lt border border-l-4 border-lt-border bg-lt-popover p-4 text-lt-popover-fg shadow-lt-lg\",\n variantStyles[toast.variant].accent,\n \"data-[state=open]:animate-lt-toast-in data-[state=closed]:animate-lt-toast-out\",\n \"data-[swipe=move]:translate-y-[var(--radix-toast-swipe-move-y)] data-[swipe=cancel]:translate-y-0 data-[swipe=cancel]:transition-transform\",\n )}\n data-test={`toast-${toast.variant}`}\n duration={toast.persistent ? Infinity : (toast.duration ?? duration)}\n onOpenChange={(open) => {\n if (!open) {\n dismiss(toast.id);\n }\n }}\n >\n {variantStyles[toast.variant].icon}\n <div className=\"flex min-w-0 flex-1 flex-col gap-2\">\n <Toast.Title className=\"text-sm text-lt-fg\">\n {resolveText(toast.message, t)}\n </Toast.Title>\n {toast.action ? (\n <div className=\"flex flex-wrap gap-2\">\n <RenderNode node={toast.action} />\n </div>\n ) : null}\n </div>\n {toast.dismissible ? (\n <Toast.Close\n aria-label={t(\"common.dismiss\", \"Dismiss\")}\n className=\"shrink-0 rounded-lt-sm p-1 text-lt-muted-fg transition-colors hover:bg-lt-muted hover:text-lt-fg\"\n data-test=\"toast-dismiss\"\n >\n <Icon name=\"x\" className=\"size-lt-icon-md\" />\n </Toast.Close>\n ) : null}\n </Toast.Root>\n ))}\n <Toast.Viewport className=\"fixed inset-x-0 bottom-0 z-lt-toast mx-auto flex w-full max-w-sm flex-col gap-2 p-4 outline-none\" />\n </Toast.Provider>\n );\n}\n"],"mappings":";;;;;;;;;;;AAaA,IAAI,SAAS;AAEb,SAAgB,QAAQ,EAAE,WAAW,OAA+B;CAClE,MAAM,EAAE,MAAM,KAAK,SAAS;CAC5B,MAAM,CAAC,QAAQ,aAAa,SAAsB,CAAC,CAAC;CAEpD,SAAS,QAAQ,IAAkB;EACjC,WAAW,YAAY,QAAQ,QAAQ,UAAU,MAAM,OAAO,EAAE,CAAC;CACnE;CAEA,gBAEI,SAAS,UAAU;EACjB,WAAW,YAAY,CAAC,GAAG,SAAS;GAAE,GAAG;GAAO,IAAI;EAAS,CAAC,CAAC;CACjE,CAAC,GACH,CAAC,CACH;CAEA,OACE,qBAAC,MAAM,UAAP;EAA0B;EAAU,gBAAe;YAAnD,CACG,OAAO,KAAK,UACX,qBAAC,MAAM,MAAP;GAEE,WAAW,GACT,0HACA,cAAc,MAAM,SAAS,QAC7B,kFACA,4IACF;GACA,aAAW,SAAS,MAAM;GAC1B,UAAU,MAAM,aAAa,WAAY,MAAM,YAAY;GAC3D,eAAe,SAAS;IACtB,IAAI,CAAC,MACH,QAAQ,MAAM,EAAE;GAEpB;aAdF;IAgBG,cAAc,MAAM,SAAS;IAC9B,qBAAC,OAAD;KAAK,WAAU;eAAf,CACE,oBAAC,MAAM,OAAP;MAAa,WAAU;gBACpB,YAAY,MAAM,SAAS,CAAC;KAClB,CAAA,GACZ,MAAM,SACL,oBAAC,OAAD;MAAK,WAAU;gBACb,oBAAC,YAAD,EAAY,MAAM,MAAM,OAAS,CAAA;KAC9B,CAAA,IACH,IACD;;IACJ,MAAM,cACL,oBAAC,MAAM,OAAP;KACE,cAAY,EAAE,kBAAkB,SAAS;KACzC,WAAU;KACV,aAAU;eAEV,oBAAC,MAAD;MAAM,MAAK;MAAI,WAAU;KAAmB,CAAA;IACjC,CAAA,IACX;GACM;KAnCL,MAAM,EAmCD,CACb,GACD,oBAAC,MAAM,UAAP,EAAgB,WAAU,mGAAoG,CAAA,CAChH;;AAEpB"}
@@ -222,8 +222,8 @@ export type ButtonVariant = "default" | "destructive" | "ghost" | "info" | "link
222
222
  export type Callout = {
223
223
  action: Node | null;
224
224
  dismissible: boolean;
225
- message: string;
226
- title: string | null;
225
+ message: Translatable | string;
226
+ title: Translatable | string | null;
227
227
  variant: Variant;
228
228
  };
229
229
  export type Callouts = Record<string, never>;
@@ -450,7 +450,8 @@ export type ComponentPropsMap = {
450
450
  text: Text;
451
451
  tooltip: Tooltip;
452
452
  topbar: Topbar;
453
- tree: Tree;
453
+ wizard: Wizard;
454
+ "wizard-step": WizardStep;
454
455
  };
455
456
  export type Condition = {
456
457
  readonly field: string;
@@ -684,8 +685,8 @@ export type Form = {
684
685
  validationSummaryLabel: string;
685
686
  validationTimeout: number | null;
686
687
  };
687
- export type FormFieldNodeType = "field.builder" | "field.checkbox" | "field.choice" | "field.color-picker" | "field.date-input" | "field.date-time-input" | "field.file-upload" | "field.hidden-input" | "field.number-input" | "field.otp" | "field.password-input" | "field.repeater" | "field.rich-editor" | "field.select" | "field.text-input" | "field.textarea" | "field.time-input" | "field.toggle";
688
- export type FormNodeType = "field.builder" | "field.checkbox" | "field.choice" | "field.color-picker" | "field.date-input" | "field.date-time-input" | "field.file-upload" | "field.hidden-input" | "field.number-input" | "field.otp" | "field.password-input" | "field.repeater" | "field.rich-editor" | "field.select" | "field.text-input" | "field.textarea" | "field.time-input" | "field.toggle" | "form";
688
+ export type FormFieldNodeType = "field.builder" | "field.checkbox" | "field.choice" | "field.color-picker" | "field.date-input" | "field.date-time-input" | "field.file-upload" | "field.hidden-input" | "field.number-input" | "field.otp" | "field.password-input" | "field.repeater" | "field.rich-editor" | "field.select" | "field.text-input" | "field.textarea" | "field.time-input" | "field.toggle" | "wizard" | "wizard-step";
689
+ export type FormNodeType = "field.builder" | "field.checkbox" | "field.choice" | "field.color-picker" | "field.date-input" | "field.date-time-input" | "field.file-upload" | "field.hidden-input" | "field.number-input" | "field.otp" | "field.password-input" | "field.repeater" | "field.rich-editor" | "field.select" | "field.text-input" | "field.textarea" | "field.time-input" | "field.toggle" | "form" | "wizard" | "wizard-step";
689
690
  export type Fragment = {
690
691
  endpoint: string | null;
691
692
  lazy: boolean;
@@ -831,16 +832,16 @@ export type MoneyColumn = {
831
832
  toggleable: boolean;
832
833
  width: ColumnWidth;
833
834
  };
834
- export type NodeType = "action" | "action.bulk" | "action.group" | "avatar" | "badge" | "breadcrumbs" | "button" | "callouts" | "card" | "chart" | "chat.box" | "chat.part.text" | "chat.part.tool-call" | "collapsible" | "dropdown" | "field.builder" | "field.checkbox" | "field.choice" | "field.color-picker" | "field.date-input" | "field.date-time-input" | "field.file-upload" | "field.hidden-input" | "field.number-input" | "field.otp" | "field.password-input" | "field.repeater" | "field.rich-editor" | "field.select" | "field.text-input" | "field.textarea" | "field.time-input" | "field.toggle" | "floating-panel" | "form" | "fragment" | "grid" | "heading" | "icon" | "image" | "link" | "menu" | "menu-item" | "modal" | "notifications" | "outlet" | "progress" | "raw-block" | "remote.data-list" | "section" | "segmented-control" | "separator" | "sidebar" | "stack" | "tab" | "table" | "tabs" | "text" | "tooltip" | "topbar" | "tree";
835
+ export type NodeType = "action" | "action.bulk" | "action.group" | "avatar" | "badge" | "breadcrumbs" | "button" | "callouts" | "card" | "chart" | "chat.box" | "chat.part.text" | "chat.part.tool-call" | "collapsible" | "dropdown" | "field.builder" | "field.checkbox" | "field.choice" | "field.color-picker" | "field.date-input" | "field.date-time-input" | "field.file-upload" | "field.hidden-input" | "field.number-input" | "field.otp" | "field.password-input" | "field.repeater" | "field.rich-editor" | "field.select" | "field.text-input" | "field.textarea" | "field.time-input" | "field.toggle" | "floating-panel" | "form" | "fragment" | "grid" | "heading" | "icon" | "image" | "link" | "menu" | "menu-item" | "modal" | "notifications" | "outlet" | "progress" | "raw-block" | "remote.data-list" | "section" | "segmented-control" | "separator" | "sidebar" | "stack" | "tab" | "table" | "tabs" | "text" | "tooltip" | "topbar" | "wizard" | "wizard-step";
835
836
  export type NotificationItem = {
836
837
  readonly actions: Node[];
837
- readonly body: string | null;
838
+ readonly body: Translatable | string | null;
838
839
  readonly createdAt: string | null;
839
840
  readonly href: string | null;
840
841
  readonly icon: string | null;
841
842
  readonly id: string;
842
843
  readonly isRead: boolean;
843
- readonly title: string | null;
844
+ readonly title: Translatable | string | null;
844
845
  readonly variant: Variant | null;
845
846
  };
846
847
  export type NotificationList = {
@@ -1373,26 +1374,18 @@ export type Translatable = {
1373
1374
  payload: Record<string, string>;
1374
1375
  replacements: Record<string, string | number | boolean>;
1375
1376
  };
1376
- export type Tree = {
1377
- activeId: string | null;
1378
- defaultExpanded: string[];
1379
- rememberState: boolean;
1380
- };
1381
- export type TreeNode = {
1382
- actions: Node<"action"> | Node<"action.bulk"> | Node<"action.group"> | null;
1383
- badge: string | null;
1384
- children: TreeNode[];
1385
- disabled: boolean;
1386
- hasChildren: boolean;
1387
- href: string | null;
1388
- icon: string | null;
1389
- readonly id: string;
1390
- readonly label: string;
1391
- };
1392
- export type UiNodeType = "avatar" | "badge" | "button" | "card" | "chart" | "collapsible" | "floating-panel" | "grid" | "heading" | "icon" | "image" | "link" | "modal" | "progress" | "raw-block" | "section" | "segmented-control" | "separator" | "stack" | "tab" | "tabs" | "text" | "tooltip" | "tree";
1377
+ export type UiNodeType = "avatar" | "badge" | "button" | "card" | "chart" | "collapsible" | "floating-panel" | "grid" | "heading" | "icon" | "image" | "link" | "modal" | "progress" | "raw-block" | "section" | "segmented-control" | "separator" | "stack" | "tab" | "tabs" | "text" | "tooltip";
1393
1378
  export type UnreadCount = {
1394
1379
  readonly unreadCount: number;
1395
1380
  };
1396
1381
  export type Variant = "success" | "info" | "warning" | "error";
1397
1382
  export type Width = "full" | "auto" | "sm" | "md" | "lg" | "fill";
1383
+ export type Wizard = {
1384
+ orientation: Orientation;
1385
+ };
1386
+ export type WizardStep = {
1387
+ description: string | null;
1388
+ label: string;
1389
+ name: string;
1390
+ };
1398
1391
  export {};
package/dist/ui/plugin.js CHANGED
@@ -22,7 +22,6 @@ import StackComponent from "./stack.js";
22
22
  import TabComponent, { TabsComponent } from "./tabs.js";
23
23
  import TextComponent from "./text.js";
24
24
  import TooltipComponent from "./tooltip.js";
25
- import TreeComponent from "./tree.js";
26
25
  //#region resources/js/ui/plugin.ts
27
26
  var uiComponents = createPlugin({
28
27
  components: {
@@ -49,8 +48,7 @@ var uiComponents = createPlugin({
49
48
  tab: eagerComponent(TabComponent),
50
49
  tabs: eagerComponent(TabsComponent),
51
50
  text: eagerComponent(TextComponent),
52
- tooltip: eagerComponent(TooltipComponent),
53
- tree: eagerComponent(TreeComponent)
51
+ tooltip: eagerComponent(TooltipComponent)
54
52
  },
55
53
  name: "lattice/ui"
56
54
  });
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.js","names":[],"sources":["../../resources/js/ui/plugin.ts"],"sourcesContent":["import {\n createPlugin,\n eagerComponent,\n type ComponentRegistryFor,\n} from \"@lattice-php/lattice/core/registry\";\nimport type { FragmentNodeType, UiNodeType } from \"@lattice-php/lattice/types/generated\";\nimport AvatarComponent from \"./avatar\";\nimport BadgeComponent from \"./badge\";\nimport ButtonComponent from \"./button\";\nimport CardComponent from \"./card\";\nimport ChartComponent from \"./chart\";\nimport CollapsibleComponent from \"./collapsible\";\nimport FloatingPanelComponent from \"./floating-panel\";\nimport FragmentComponent from \"./fragment\";\nimport GridComponent from \"./grid\";\nimport HeadingComponent from \"./heading\";\nimport IconComponent from \"./icon\";\nimport ImageComponent from \"./image\";\nimport LinkComponent from \"./link\";\nimport ModalComponent from \"./modal\";\nimport ProgressComponent from \"./progress\";\nimport RawBlockComponent from \"./raw-block\";\nimport SectionComponent from \"./section\";\nimport SegmentedControlComponent from \"./segmented-control\";\nimport SeparatorComponent from \"./separator\";\nimport StackComponent from \"./stack\";\nimport TabComponent, { TabsComponent } from \"./tabs\";\nimport TextComponent from \"./text\";\nimport TooltipComponent from \"./tooltip\";\nimport TreeComponent from \"./tree\";\n\ntype UiComponentType = UiNodeType | FragmentNodeType;\n\nexport const uiComponents = createPlugin({\n components: {\n avatar: eagerComponent(AvatarComponent),\n badge: eagerComponent(BadgeComponent),\n button: eagerComponent(ButtonComponent),\n card: eagerComponent(CardComponent),\n chart: eagerComponent(ChartComponent),\n collapsible: eagerComponent(CollapsibleComponent),\n \"floating-panel\": eagerComponent(FloatingPanelComponent),\n fragment: eagerComponent(FragmentComponent),\n grid: eagerComponent(GridComponent),\n heading: eagerComponent(HeadingComponent),\n icon: eagerComponent(IconComponent),\n image: eagerComponent(ImageComponent),\n link: eagerComponent(LinkComponent),\n modal: eagerComponent(ModalComponent),\n progress: eagerComponent(ProgressComponent),\n \"raw-block\": eagerComponent(RawBlockComponent),\n section: eagerComponent(SectionComponent),\n \"segmented-control\": eagerComponent(SegmentedControlComponent),\n separator: eagerComponent(SeparatorComponent),\n stack: eagerComponent(StackComponent),\n tab: eagerComponent(TabComponent),\n tabs: eagerComponent(TabsComponent),\n text: eagerComponent(TextComponent),\n tooltip: eagerComponent(TooltipComponent),\n tree: eagerComponent(TreeComponent),\n } satisfies ComponentRegistryFor<UiComponentType>,\n name: \"lattice/ui\",\n});\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAiCA,IAAa,eAAe,aAAa;CACvC,YAAY;EACV,QAAQ,eAAe,eAAe;EACtC,OAAO,eAAe,cAAc;EACpC,QAAQ,eAAe,eAAe;EACtC,MAAM,eAAe,aAAa;EAClC,OAAO,eAAe,cAAc;EACpC,aAAa,eAAe,oBAAoB;EAChD,kBAAkB,eAAe,sBAAsB;EACvD,UAAU,eAAe,iBAAiB;EAC1C,MAAM,eAAe,aAAa;EAClC,SAAS,eAAe,gBAAgB;EACxC,MAAM,eAAe,aAAa;EAClC,OAAO,eAAe,cAAc;EACpC,MAAM,eAAe,aAAa;EAClC,OAAO,eAAe,cAAc;EACpC,UAAU,eAAe,iBAAiB;EAC1C,aAAa,eAAe,iBAAiB;EAC7C,SAAS,eAAe,gBAAgB;EACxC,qBAAqB,eAAe,yBAAyB;EAC7D,WAAW,eAAe,kBAAkB;EAC5C,OAAO,eAAe,cAAc;EACpC,KAAK,eAAe,YAAY;EAChC,MAAM,eAAe,aAAa;EAClC,MAAM,eAAe,aAAa;EAClC,SAAS,eAAe,gBAAgB;EACxC,MAAM,eAAe,aAAa;CACpC;CACA,MAAM;AACR,CAAC"}
1
+ {"version":3,"file":"plugin.js","names":[],"sources":["../../resources/js/ui/plugin.ts"],"sourcesContent":["import {\n createPlugin,\n eagerComponent,\n type ComponentRegistryFor,\n} from \"@lattice-php/lattice/core/registry\";\nimport type { FragmentNodeType, UiNodeType } from \"@lattice-php/lattice/types/generated\";\nimport AvatarComponent from \"./avatar\";\nimport BadgeComponent from \"./badge\";\nimport ButtonComponent from \"./button\";\nimport CardComponent from \"./card\";\nimport ChartComponent from \"./chart\";\nimport CollapsibleComponent from \"./collapsible\";\nimport FloatingPanelComponent from \"./floating-panel\";\nimport FragmentComponent from \"./fragment\";\nimport GridComponent from \"./grid\";\nimport HeadingComponent from \"./heading\";\nimport IconComponent from \"./icon\";\nimport ImageComponent from \"./image\";\nimport LinkComponent from \"./link\";\nimport ModalComponent from \"./modal\";\nimport ProgressComponent from \"./progress\";\nimport RawBlockComponent from \"./raw-block\";\nimport SectionComponent from \"./section\";\nimport SegmentedControlComponent from \"./segmented-control\";\nimport SeparatorComponent from \"./separator\";\nimport StackComponent from \"./stack\";\nimport TabComponent, { TabsComponent } from \"./tabs\";\nimport TextComponent from \"./text\";\nimport TooltipComponent from \"./tooltip\";\n\ntype UiComponentType = UiNodeType | FragmentNodeType;\n\nexport const uiComponents = createPlugin({\n components: {\n avatar: eagerComponent(AvatarComponent),\n badge: eagerComponent(BadgeComponent),\n button: eagerComponent(ButtonComponent),\n card: eagerComponent(CardComponent),\n chart: eagerComponent(ChartComponent),\n collapsible: eagerComponent(CollapsibleComponent),\n \"floating-panel\": eagerComponent(FloatingPanelComponent),\n fragment: eagerComponent(FragmentComponent),\n grid: eagerComponent(GridComponent),\n heading: eagerComponent(HeadingComponent),\n icon: eagerComponent(IconComponent),\n image: eagerComponent(ImageComponent),\n link: eagerComponent(LinkComponent),\n modal: eagerComponent(ModalComponent),\n progress: eagerComponent(ProgressComponent),\n \"raw-block\": eagerComponent(RawBlockComponent),\n section: eagerComponent(SectionComponent),\n \"segmented-control\": eagerComponent(SegmentedControlComponent),\n separator: eagerComponent(SeparatorComponent),\n stack: eagerComponent(StackComponent),\n tab: eagerComponent(TabComponent),\n tabs: eagerComponent(TabsComponent),\n text: eagerComponent(TextComponent),\n tooltip: eagerComponent(TooltipComponent),\n } satisfies ComponentRegistryFor<UiComponentType>,\n name: \"lattice/ui\",\n});\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AAgCA,IAAa,eAAe,aAAa;CACvC,YAAY;EACV,QAAQ,eAAe,eAAe;EACtC,OAAO,eAAe,cAAc;EACpC,QAAQ,eAAe,eAAe;EACtC,MAAM,eAAe,aAAa;EAClC,OAAO,eAAe,cAAc;EACpC,aAAa,eAAe,oBAAoB;EAChD,kBAAkB,eAAe,sBAAsB;EACvD,UAAU,eAAe,iBAAiB;EAC1C,MAAM,eAAe,aAAa;EAClC,SAAS,eAAe,gBAAgB;EACxC,MAAM,eAAe,aAAa;EAClC,OAAO,eAAe,cAAc;EACpC,MAAM,eAAe,aAAa;EAClC,OAAO,eAAe,cAAc;EACpC,UAAU,eAAe,iBAAiB;EAC1C,aAAa,eAAe,iBAAiB;EAC7C,SAAS,eAAe,gBAAgB;EACxC,qBAAqB,eAAe,yBAAyB;EAC7D,WAAW,eAAe,kBAAkB;EAC5C,OAAO,eAAe,cAAc;EACpC,KAAK,eAAe,YAAY;EAChC,MAAM,eAAe,aAAa;EAClC,MAAM,eAAe,aAAa;EAClC,SAAS,eAAe,gBAAgB;CAC1C;CACA,MAAM;AACR,CAAC"}
@@ -0,0 +1,9 @@
1
+ import { spawn } from 'node:child_process';
2
+ import { existsSync } from 'node:fs';
3
+ import { Logger } from 'vite';
4
+ /**
5
+ * Deliberately absent from `package.json#exports`: unreachable from outside
6
+ * the package even though it compiles into `dist/`. `spawnProcess`/`fileExists`
7
+ * are test seams — the only real caller uses the defaults.
8
+ */
9
+ export declare function refreshTypeScriptTypes(appRoot: string, logger: Pick<Logger, "info" | "warn">, spawnProcess?: typeof spawn, fileExists?: typeof existsSync): void;
@@ -0,0 +1,47 @@
1
+ import { spawn } from "node:child_process";
2
+ import { existsSync } from "node:fs";
3
+ import path from "node:path";
4
+ //#region resources/js/vite-typescript-refresh.ts
5
+ var MAX_STDERR_CHARS = 500;
6
+ /**
7
+ * Deliberately absent from `package.json#exports`: unreachable from outside
8
+ * the package even though it compiles into `dist/`. `spawnProcess`/`fileExists`
9
+ * are test seams — the only real caller uses the defaults.
10
+ */
11
+ function refreshTypeScriptTypes(appRoot, logger, spawnProcess = spawn, fileExists = existsSync) {
12
+ if (!fileExists(path.join(appRoot, "artisan"))) return;
13
+ const child = spawnProcess("php", ["artisan", "lattice:typescript"], {
14
+ cwd: appRoot,
15
+ stdio: [
16
+ "ignore",
17
+ "ignore",
18
+ "pipe"
19
+ ]
20
+ });
21
+ let stderr = "";
22
+ let warned = false;
23
+ const warnOnce = (message) => {
24
+ if (warned) return;
25
+ warned = true;
26
+ logger.warn(message);
27
+ };
28
+ child.stderr?.on("data", (chunk) => {
29
+ if (stderr.length < MAX_STDERR_CHARS) stderr += chunk.toString();
30
+ });
31
+ child.stderr?.on("error", () => {});
32
+ child.on("error", (error) => {
33
+ warnOnce(`[lattice] could not refresh TypeScript types: ${error.message}`);
34
+ });
35
+ child.on("exit", (code) => {
36
+ if (code === 0) logger.info("[lattice] refreshed TypeScript types");
37
+ });
38
+ child.on("close", (code) => {
39
+ if (code === 0) return;
40
+ const detail = stderr.trim().slice(0, MAX_STDERR_CHARS);
41
+ warnOnce(`[lattice] php artisan lattice:typescript exited with code ${code}${detail ? `: ${detail}` : ""}`);
42
+ });
43
+ }
44
+ //#endregion
45
+ export { refreshTypeScriptTypes };
46
+
47
+ //# sourceMappingURL=vite-typescript-refresh.js.map