@lattice-php/lattice 0.33.0 → 0.34.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 (73) hide show
  1. package/dist/appearance/index.js +2 -6
  2. package/dist/appearance/index.js.map +1 -1
  3. package/dist/chat/lib/transport.d.ts +2 -2
  4. package/dist/chat/lib/transport.js +22 -23
  5. package/dist/chat/lib/transport.js.map +1 -1
  6. package/dist/core/api.d.ts +0 -1
  7. package/dist/core/api.js +2 -2
  8. package/dist/core/api.js.map +1 -1
  9. package/dist/core/hooks/column-sizing.d.ts +1 -1
  10. package/dist/core/hooks/column-sizing.js +7 -14
  11. package/dist/core/hooks/column-sizing.js.map +1 -1
  12. package/dist/core/hooks/use-column-resizing.js +22 -54
  13. package/dist/core/hooks/use-column-resizing.js.map +1 -1
  14. package/dist/core/index.d.ts +1 -1
  15. package/dist/core/index.js +2 -2
  16. package/dist/core/registry.d.ts +1 -5
  17. package/dist/core/registry.js +1 -2
  18. package/dist/core/registry.js.map +1 -1
  19. package/dist/core/renderer.js +4 -10
  20. package/dist/core/renderer.js.map +1 -1
  21. package/dist/effects/registry.js +1 -4
  22. package/dist/effects/registry.js.map +1 -1
  23. package/dist/event-bridge.d.ts +1 -4
  24. package/dist/event-bridge.js +1 -11
  25. package/dist/event-bridge.js.map +1 -1
  26. package/dist/form/components/fields/choice.js +1 -1
  27. package/dist/form/components/fields/choice.js.map +1 -1
  28. package/dist/form/types.d.ts +1 -4
  29. package/dist/i18n/config.d.ts +1 -1
  30. package/dist/i18n/config.js +5 -21
  31. package/dist/i18n/config.js.map +1 -1
  32. package/dist/i18n/index.d.ts +2 -2
  33. package/dist/i18n/index.js +2 -2
  34. package/dist/i18n/locale-switcher.d.ts +0 -5
  35. package/dist/i18n/locale-switcher.js +1 -5
  36. package/dist/i18n/locale-switcher.js.map +1 -1
  37. package/dist/i18n/locale.js +2 -10
  38. package/dist/i18n/locale.js.map +1 -1
  39. package/dist/i18n/timezone.js +2 -10
  40. package/dist/i18n/timezone.js.map +1 -1
  41. package/dist/icons/icon-renderer.d.ts +1 -2
  42. package/dist/icons/icon-renderer.js +2 -6
  43. package/dist/icons/icon-renderer.js.map +1 -1
  44. package/dist/lib/listeners.d.ts +5 -0
  45. package/dist/lib/listeners.js +19 -0
  46. package/dist/lib/listeners.js.map +1 -0
  47. package/dist/table/hooks/use-column-visibility.js +4 -12
  48. package/dist/table/hooks/use-column-visibility.js.map +1 -1
  49. package/dist/toast/callout.js +8 -16
  50. package/dist/toast/callout.js.map +1 -1
  51. package/dist/toast/toast.d.ts +2 -0
  52. package/dist/toast/toast.js +16 -10
  53. package/dist/toast/toast.js.map +1 -1
  54. package/dist/ui/segmented-pills.d.ts +1 -1
  55. package/dist/ui/segmented-pills.js +1 -1
  56. package/dist/ui/segmented-pills.js.map +1 -1
  57. package/dist-standalone/chunks/{chart-view-WqyMTZiX.js → chart-view-CR1X2aGE.js} +1 -1
  58. package/dist-standalone/chunks/{date-picker-field-CCnkf4SC.js → date-picker-field-B4Xzow-A.js} +1 -1
  59. package/dist-standalone/chunks/{dist-CK9gk4iB.js → dist-ci5ng714.js} +1 -1
  60. package/dist-standalone/chunks/{icon-button-D4DKcnhp.js → icon-button-D3AltHNz.js} +1 -1
  61. package/dist-standalone/chunks/{instance-BQeVkUpw.js → instance-C4O1XWa6.js} +1 -1
  62. package/dist-standalone/chunks/locale-GyqtaX1O.js +1 -0
  63. package/dist-standalone/chunks/{page-props-BA5zqTIT.js → page-props-BHNNVkgJ.js} +1 -1
  64. package/dist-standalone/chunks/{rich-editor-field-BeeSr2Zx.js → rich-editor-field-JM3jBEV1.js} +1 -1
  65. package/dist-standalone/chunks/{subscriptions-Cwd1jFs5.js → subscriptions-BV4g0s0U.js} +1 -1
  66. package/dist-standalone/chunks/{time-picker-DSs9fDWe.js → time-picker-kbhOHEPd.js} +1 -1
  67. package/dist-standalone/chunks/timezone-CyoBch3a.js +1 -0
  68. package/dist-standalone/chunks/{use-effect-dispatcher-CiWYRvsF.js → use-effect-dispatcher-CJXFkAv1.js} +2 -2
  69. package/dist-standalone/lattice.js +4 -4
  70. package/dist-standalone/manifest.json +1 -27
  71. package/package.json +2 -2
  72. package/dist-standalone/chunks/locale-CgtcxthU.js +0 -1
  73. package/dist-standalone/chunks/timezone-BORzyZp2.js +0 -1
@@ -64,16 +64,10 @@ var NodeRenderer = memo(function NodeRenderer({ node }) {
64
64
  node,
65
65
  children
66
66
  });
67
- if (registration.mode === "lazy") {
68
- const FallbackComponent = registration.fallback;
69
- return /* @__PURE__ */ jsx(Suspense, {
70
- fallback: FallbackComponent ? /* @__PURE__ */ jsx(FallbackComponent, {
71
- node,
72
- children: null
73
- }) : null,
74
- children: renderedComponent
75
- });
76
- }
67
+ if (registration.mode === "lazy") return /* @__PURE__ */ jsx(Suspense, {
68
+ fallback: null,
69
+ children: renderedComponent
70
+ });
77
71
  return renderedComponent;
78
72
  });
79
73
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"renderer.js","names":[],"sources":["../../resources/js/core/renderer.tsx"],"sourcesContent":["import { memo, Suspense } from \"react\";\nimport type { ReactNode } from \"react\";\nimport type { Node } from \"./types\";\nimport { nodeKey } from \"./nodes\";\nimport { useCollapsed } from \"./collapsed-context\";\nimport { useComponentRegistry } from \"./registry-context\";\n\nconst warnedMissingTypes = new Set<string>();\n\nfunction warnMissingComponent(type: string): void {\n if (!import.meta.env.DEV || warnedMissingTypes.has(type)) {\n return;\n }\n\n warnedMissingTypes.add(type);\n console.warn(\n `[lattice] No component registered for node type \"${type}\" — Lattice rendered a fallback ` +\n \"placeholder. Likely causes: your app registry was not passed to \" +\n \"createLatticeApp({ registry }), or the registry key does not match the PHP \" +\n \"#[AsComponent]/AsField type.\",\n );\n}\n\nfunction MissingComponentIcon() {\n return (\n <svg\n aria-hidden=\"true\"\n className=\"size-lt-icon-md shrink-0\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth=\"2\"\n viewBox=\"0 0 24 24\"\n >\n <rect height=\"18\" rx=\"2\" strokeDasharray=\"4 3\" width=\"18\" x=\"3\" y=\"3\" />\n <path d=\"M12 8v4\" />\n <path d=\"M12 16h.01\" />\n </svg>\n );\n}\n\n/**\n * Fallback for a node whose type has no registered renderer. Always renders a\n * visible, muted marker — icon-only survives tight spots like table cells — so\n * the gap is never invisible. Shows the type inline in development; keeps it\n * screen-reader-only (plus a hover tooltip) in production.\n */\nfunction MissingComponent({ node }: { node: Node }) {\n warnMissingComponent(node.type);\n\n const label = `Missing component: ${node.type}`;\n\n return (\n <span\n className=\"inline-flex items-center gap-1.5 align-middle text-lt-muted-fg\"\n data-lattice-missing-component={node.type}\n title={label}\n >\n <MissingComponentIcon />\n <span className={import.meta.env.DEV ? \"text-sm\" : \"sr-only\"}>{label}</span>\n </span>\n );\n}\n\nexport function Renderer({ nodes }: { nodes: Node[] }): ReactNode {\n return nodes.map((node, index) => <NodeRenderer key={nodeKey(node, index)} node={node} />);\n}\n\nexport function RenderNode({ node }: { node: Node }): ReactNode {\n return <NodeRenderer node={node} />;\n}\n\nconst NodeRenderer = memo(function NodeRenderer({ node }: { node: Node }) {\n const collapsed = useCollapsed();\n const registry = useComponentRegistry();\n const registration = registry[node.type];\n\n if (collapsed && node.props?.hideWhenCollapsed === true) {\n return null;\n }\n\n if (!registration) {\n return <MissingComponent node={node} />;\n }\n\n const Component = registration.component;\n const children = node.schema?.length ? <Renderer nodes={node.schema} /> : null;\n const renderedComponent = <Component node={node}>{children}</Component>;\n\n if (registration.mode === \"lazy\") {\n const FallbackComponent = registration.fallback;\n const fallback = FallbackComponent ? (\n <FallbackComponent node={node}>{null}</FallbackComponent>\n ) : null;\n\n return <Suspense fallback={fallback}>{renderedComponent}</Suspense>;\n }\n\n return renderedComponent;\n});\n"],"mappings":";;;;;;AAuBA,SAAS,uBAAuB;CAC9B,OACE,qBAAC,OAAD;EACE,eAAY;EACZ,WAAU;EACV,MAAK;EACL,QAAO;EACP,eAAc;EACd,gBAAe;EACf,aAAY;EACZ,SAAQ;EARV,UAAA;GAUE,oBAAC,QAAD;IAAM,QAAO;IAAK,IAAG;IAAI,iBAAgB;IAAM,OAAM;IAAK,GAAE;IAAI,GAAE;GAAK,CAAA;GACvE,oBAAC,QAAD,EAAM,GAAE,UAAW,CAAA;GACnB,oBAAC,QAAD,EAAM,GAAE,aAAc,CAAA;EACnB;;AAET;;;;;;;AAQA,SAAS,iBAAiB,EAAE,QAAwB;CAClD,KAA0B;CAE1B,MAAM,QAAQ,sBAAsB,KAAK;CAEzC,OACE,qBAAC,QAAD;EACE,WAAU;EACV,kCAAgC,KAAK;EACrC,OAAO;EAHT,UAAA,CAKE,oBAAC,sBAAD,CAAuB,CAAA,GACvB,oBAAC,QAAD;GAAM,WAA6C;GAAY,UAAA;EAAY,CAAA,CACvE;;AAEV;AAEA,SAAgB,SAAS,EAAE,SAAuC;CAChE,OAAO,MAAM,KAAK,MAAM,UAAU,oBAAC,cAAD,EAA+C,KAAO,GAAnC,QAAQ,MAAM,KAAK,CAAgB,CAAC;AAC3F;AAEA,SAAgB,WAAW,EAAE,QAAmC;CAC9D,OAAO,oBAAC,cAAD,EAAoB,KAAO,CAAA;AACpC;AAEA,IAAM,eAAe,KAAK,SAAS,aAAa,EAAE,QAAwB;CACxE,MAAM,YAAY,aAAa;CAE/B,MAAM,eADW,qBACI,CAAA,CAAS,KAAK;CAEnC,IAAI,aAAa,KAAK,OAAO,sBAAsB,MACjD,OAAO;CAGT,IAAI,CAAC,cACH,OAAO,oBAAC,kBAAD,EAAwB,KAAO,CAAA;CAGxC,MAAM,YAAY,aAAa;CAC/B,MAAM,WAAW,KAAK,QAAQ,SAAS,oBAAC,UAAD,EAAU,OAAO,KAAK,OAAS,CAAA,IAAI;CAC1E,MAAM,oBAAoB,oBAAC,WAAD;EAAiB;EAAO;CAAoB,CAAA;CAEtE,IAAI,aAAa,SAAS,QAAQ;EAChC,MAAM,oBAAoB,aAAa;EAKvC,OAAO,oBAAC,UAAD;GAAoB,UAJV,oBACf,oBAAC,mBAAD;IAAyB;IAAO,UAAA;GAAwB,CAAA,IACtD;GAEkC,UAAA;EAA4B,CAAA;CACpE;CAEA,OAAO;AACT,CAAC"}
1
+ {"version":3,"file":"renderer.js","names":[],"sources":["../../resources/js/core/renderer.tsx"],"sourcesContent":["import { memo, Suspense } from \"react\";\nimport type { ReactNode } from \"react\";\nimport type { Node } from \"./types\";\nimport { nodeKey } from \"./nodes\";\nimport { useCollapsed } from \"./collapsed-context\";\nimport { useComponentRegistry } from \"./registry-context\";\n\nconst warnedMissingTypes = new Set<string>();\n\nfunction warnMissingComponent(type: string): void {\n if (!import.meta.env.DEV || warnedMissingTypes.has(type)) {\n return;\n }\n\n warnedMissingTypes.add(type);\n console.warn(\n `[lattice] No component registered for node type \"${type}\" — Lattice rendered a fallback ` +\n \"placeholder. Likely causes: your app registry was not passed to \" +\n \"createLatticeApp({ registry }), or the registry key does not match the PHP \" +\n \"#[AsComponent]/AsField type.\",\n );\n}\n\nfunction MissingComponentIcon() {\n return (\n <svg\n aria-hidden=\"true\"\n className=\"size-lt-icon-md shrink-0\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth=\"2\"\n viewBox=\"0 0 24 24\"\n >\n <rect height=\"18\" rx=\"2\" strokeDasharray=\"4 3\" width=\"18\" x=\"3\" y=\"3\" />\n <path d=\"M12 8v4\" />\n <path d=\"M12 16h.01\" />\n </svg>\n );\n}\n\n/**\n * Fallback for a node whose type has no registered renderer. Always renders a\n * visible, muted marker — icon-only survives tight spots like table cells — so\n * the gap is never invisible. Shows the type inline in development; keeps it\n * screen-reader-only (plus a hover tooltip) in production.\n */\nfunction MissingComponent({ node }: { node: Node }) {\n warnMissingComponent(node.type);\n\n const label = `Missing component: ${node.type}`;\n\n return (\n <span\n className=\"inline-flex items-center gap-1.5 align-middle text-lt-muted-fg\"\n data-lattice-missing-component={node.type}\n title={label}\n >\n <MissingComponentIcon />\n <span className={import.meta.env.DEV ? \"text-sm\" : \"sr-only\"}>{label}</span>\n </span>\n );\n}\n\nexport function Renderer({ nodes }: { nodes: Node[] }): ReactNode {\n return nodes.map((node, index) => <NodeRenderer key={nodeKey(node, index)} node={node} />);\n}\n\nexport function RenderNode({ node }: { node: Node }): ReactNode {\n return <NodeRenderer node={node} />;\n}\n\nconst NodeRenderer = memo(function NodeRenderer({ node }: { node: Node }) {\n const collapsed = useCollapsed();\n const registry = useComponentRegistry();\n const registration = registry[node.type];\n\n if (collapsed && node.props?.hideWhenCollapsed === true) {\n return null;\n }\n\n if (!registration) {\n return <MissingComponent node={node} />;\n }\n\n const Component = registration.component;\n const children = node.schema?.length ? <Renderer nodes={node.schema} /> : null;\n const renderedComponent = <Component node={node}>{children}</Component>;\n\n if (registration.mode === \"lazy\") {\n return <Suspense fallback={null}>{renderedComponent}</Suspense>;\n }\n\n return renderedComponent;\n});\n"],"mappings":";;;;;;AAuBA,SAAS,uBAAuB;CAC9B,OACE,qBAAC,OAAD;EACE,eAAY;EACZ,WAAU;EACV,MAAK;EACL,QAAO;EACP,eAAc;EACd,gBAAe;EACf,aAAY;EACZ,SAAQ;EARV,UAAA;GAUE,oBAAC,QAAD;IAAM,QAAO;IAAK,IAAG;IAAI,iBAAgB;IAAM,OAAM;IAAK,GAAE;IAAI,GAAE;GAAK,CAAA;GACvE,oBAAC,QAAD,EAAM,GAAE,UAAW,CAAA;GACnB,oBAAC,QAAD,EAAM,GAAE,aAAc,CAAA;EACnB;;AAET;;;;;;;AAQA,SAAS,iBAAiB,EAAE,QAAwB;CAClD,KAA0B;CAE1B,MAAM,QAAQ,sBAAsB,KAAK;CAEzC,OACE,qBAAC,QAAD;EACE,WAAU;EACV,kCAAgC,KAAK;EACrC,OAAO;EAHT,UAAA,CAKE,oBAAC,sBAAD,CAAuB,CAAA,GACvB,oBAAC,QAAD;GAAM,WAA6C;GAAY,UAAA;EAAY,CAAA,CACvE;;AAEV;AAEA,SAAgB,SAAS,EAAE,SAAuC;CAChE,OAAO,MAAM,KAAK,MAAM,UAAU,oBAAC,cAAD,EAA+C,KAAO,GAAnC,QAAQ,MAAM,KAAK,CAAgB,CAAC;AAC3F;AAEA,SAAgB,WAAW,EAAE,QAAmC;CAC9D,OAAO,oBAAC,cAAD,EAAoB,KAAO,CAAA;AACpC;AAEA,IAAM,eAAe,KAAK,SAAS,aAAa,EAAE,QAAwB;CACxE,MAAM,YAAY,aAAa;CAE/B,MAAM,eADW,qBACI,CAAA,CAAS,KAAK;CAEnC,IAAI,aAAa,KAAK,OAAO,sBAAsB,MACjD,OAAO;CAGT,IAAI,CAAC,cACH,OAAO,oBAAC,kBAAD,EAAwB,KAAO,CAAA;CAGxC,MAAM,YAAY,aAAa;CAC/B,MAAM,WAAW,KAAK,QAAQ,SAAS,oBAAC,UAAD,EAAU,OAAO,KAAK,OAAS,CAAA,IAAI;CAC1E,MAAM,oBAAoB,oBAAC,WAAD;EAAiB;EAAO;CAAoB,CAAA;CAEtE,IAAI,aAAa,SAAS,QACxB,OAAO,oBAAC,UAAD;EAAU,UAAU;EAAO,UAAA;CAA4B,CAAA;CAGhE,OAAO;AACT,CAAC"}
@@ -35,10 +35,7 @@ var builtinEffectHandlers = {
35
35
  "toggle-sidebar": bridge(LATTICE_EVENT.toggleSidebar)
36
36
  };
37
37
  function mergeEffectHandlers(...registries) {
38
- return registries.reduce((merged, registry) => ({
39
- ...merged,
40
- ...registry
41
- }), {});
38
+ return Object.assign({}, ...registries);
42
39
  }
43
40
  //#endregion
44
41
  export { builtinEffectHandlers, effectHandler, mergeEffectHandlers };
@@ -1 +1 @@
1
- {"version":3,"file":"registry.js","names":[],"sources":["../../resources/js/effects/registry.ts"],"sourcesContent":["import { router } from \"@inertiajs/react\";\nimport type {\n EffectOf,\n EffectProps,\n EffectPropsMap,\n EffectPropsOf,\n} from \"@lattice-php/lattice/types/generated\";\nimport { LATTICE_EVENT } from \"@lattice-php/lattice/core/event-names\";\nimport { setLocale } from \"@lattice-php/lattice/i18n/locale\";\n\nexport type { EffectOf, EffectProps, EffectPropsOf };\n\nexport type EffectHandler<TType extends string = string> = (effect: EffectOf<TType>) => void;\n\nexport type EffectHandlerRegistry = Record<string, EffectHandler>;\n\nexport type EffectHandlerRegistryFor<TTypes extends keyof EffectPropsMap & string> = Record<\n TTypes,\n EffectHandler\n>;\n\n/**\n * Author a handler against `EffectHandler<\"my.type\">` for a typed payload, then\n * register it through this — it erases the type parameter for the loose registry.\n */\nexport function effectHandler<TType extends string>(\n _type: TType,\n fn: EffectHandler<TType>,\n): EffectHandler {\n return fn as unknown as EffectHandler;\n}\n\nfunction triggerDownload(url: string): void {\n const link = document.createElement(\"a\");\n link.href = url;\n link.rel = \"noopener\";\n document.body.appendChild(link);\n link.click();\n link.remove();\n}\n\nfunction bridge<TType extends keyof EffectPropsMap & string>(event: string): EffectHandler<TType> {\n return (effect) => window.dispatchEvent(new CustomEvent(event, { detail: effect.props }));\n}\n\n/**\n * Imperative effects act directly; the rest bridge to the `lattice:*` DOM events\n * that toast/callout/modal/fragment/form subscribe to. The export cast erases\n * the mapped type to the loose registry shape — the same variance erasure\n * effectHandler performs.\n */\nconst typedBuiltinHandlers: { [K in keyof EffectPropsMap]: EffectHandler<K> } = {\n \"reload-page\": (effect) => (effect.props.full ? window.location.reload() : router.reload()),\n redirect: (effect) => router.visit(effect.props.url),\n download: (effect) => triggerDownload(effect.props.url),\n \"locale-change\": (effect) => setLocale(effect.props.locale),\n toast: bridge<\"toast\">(LATTICE_EVENT.toast),\n callout: bridge<\"callout\">(LATTICE_EVENT.callout),\n \"retract-callout\": bridge<\"retract-callout\">(LATTICE_EVENT.retractCallout),\n \"reload-component\": bridge<\"reload-component\">(LATTICE_EVENT.reloadComponent),\n \"open-modal\": bridge<\"open-modal\">(LATTICE_EVENT.openModal),\n \"close-modal\": bridge<\"close-modal\">(LATTICE_EVENT.closeModal),\n \"reset-form\": bridge<\"reset-form\">(LATTICE_EVENT.resetForm),\n \"toggle-sidebar\": bridge<\"toggle-sidebar\">(LATTICE_EVENT.toggleSidebar),\n};\n\nexport const builtinEffectHandlers: EffectHandlerRegistryFor<keyof EffectPropsMap & string> =\n typedBuiltinHandlers as EffectHandlerRegistryFor<keyof EffectPropsMap & string>;\n\nexport function mergeEffectHandlers(\n ...registries: Array<EffectHandlerRegistry | undefined>\n): EffectHandlerRegistry {\n return registries.reduce<EffectHandlerRegistry>(\n (merged, registry) => ({ ...merged, ...registry }),\n {},\n );\n}\n"],"mappings":";;;;;;;;AAyBA,SAAgB,cACd,OACA,IACe;CACf,OAAO;AACT;AAEA,SAAS,gBAAgB,KAAmB;CAC1C,MAAM,OAAO,SAAS,cAAc,GAAG;CACvC,KAAK,OAAO;CACZ,KAAK,MAAM;CACX,SAAS,KAAK,YAAY,IAAI;CAC9B,KAAK,MAAM;CACX,KAAK,OAAO;AACd;AAEA,SAAS,OAAoD,OAAqC;CAChG,QAAQ,WAAW,OAAO,cAAc,IAAI,YAAY,OAAO,EAAE,QAAQ,OAAO,MAAM,CAAC,CAAC;AAC1F;AAuBA,IAAa,wBACX;CAfA,gBAAgB,WAAY,OAAO,MAAM,OAAO,OAAO,SAAS,OAAO,IAAI,OAAO,OAAO;CACzF,WAAW,WAAW,OAAO,MAAM,OAAO,MAAM,GAAG;CACnD,WAAW,WAAW,gBAAgB,OAAO,MAAM,GAAG;CACtD,kBAAkB,WAAW,UAAU,OAAO,MAAM,MAAM;CAC1D,OAAO,OAAgB,cAAc,KAAK;CAC1C,SAAS,OAAkB,cAAc,OAAO;CAChD,mBAAmB,OAA0B,cAAc,cAAc;CACzE,oBAAoB,OAA2B,cAAc,eAAe;CAC5E,cAAc,OAAqB,cAAc,SAAS;CAC1D,eAAe,OAAsB,cAAc,UAAU;CAC7D,cAAc,OAAqB,cAAc,SAAS;CAC1D,kBAAkB,OAAyB,cAAc,aAAa;AAItE;AAEF,SAAgB,oBACd,GAAG,YACoB;CACvB,OAAO,WAAW,QACf,QAAQ,cAAc;EAAE,GAAG;EAAQ,GAAG;CAAS,IAChD,CAAC,CACH;AACF"}
1
+ {"version":3,"file":"registry.js","names":[],"sources":["../../resources/js/effects/registry.ts"],"sourcesContent":["import { router } from \"@inertiajs/react\";\nimport type {\n EffectOf,\n EffectProps,\n EffectPropsMap,\n EffectPropsOf,\n} from \"@lattice-php/lattice/types/generated\";\nimport { LATTICE_EVENT } from \"@lattice-php/lattice/core/event-names\";\nimport { setLocale } from \"@lattice-php/lattice/i18n/locale\";\n\nexport type { EffectOf, EffectProps, EffectPropsOf };\n\nexport type EffectHandler<TType extends string = string> = (effect: EffectOf<TType>) => void;\n\nexport type EffectHandlerRegistry = Record<string, EffectHandler>;\n\nexport type EffectHandlerRegistryFor<TTypes extends keyof EffectPropsMap & string> = Record<\n TTypes,\n EffectHandler\n>;\n\n/**\n * Author a handler against `EffectHandler<\"my.type\">` for a typed payload, then\n * register it through this — it erases the type parameter for the loose registry.\n */\nexport function effectHandler<TType extends string>(\n _type: TType,\n fn: EffectHandler<TType>,\n): EffectHandler {\n return fn as unknown as EffectHandler;\n}\n\nfunction triggerDownload(url: string): void {\n const link = document.createElement(\"a\");\n link.href = url;\n link.rel = \"noopener\";\n document.body.appendChild(link);\n link.click();\n link.remove();\n}\n\nfunction bridge<TType extends keyof EffectPropsMap & string>(event: string): EffectHandler<TType> {\n return (effect) => window.dispatchEvent(new CustomEvent(event, { detail: effect.props }));\n}\n\n/**\n * Imperative effects act directly; the rest bridge to the `lattice:*` DOM events\n * that toast/callout/modal/fragment/form subscribe to. The export cast erases\n * the mapped type to the loose registry shape — the same variance erasure\n * effectHandler performs.\n */\nconst typedBuiltinHandlers: { [K in keyof EffectPropsMap]: EffectHandler<K> } = {\n \"reload-page\": (effect) => (effect.props.full ? window.location.reload() : router.reload()),\n redirect: (effect) => router.visit(effect.props.url),\n download: (effect) => triggerDownload(effect.props.url),\n \"locale-change\": (effect) => setLocale(effect.props.locale),\n toast: bridge<\"toast\">(LATTICE_EVENT.toast),\n callout: bridge<\"callout\">(LATTICE_EVENT.callout),\n \"retract-callout\": bridge<\"retract-callout\">(LATTICE_EVENT.retractCallout),\n \"reload-component\": bridge<\"reload-component\">(LATTICE_EVENT.reloadComponent),\n \"open-modal\": bridge<\"open-modal\">(LATTICE_EVENT.openModal),\n \"close-modal\": bridge<\"close-modal\">(LATTICE_EVENT.closeModal),\n \"reset-form\": bridge<\"reset-form\">(LATTICE_EVENT.resetForm),\n \"toggle-sidebar\": bridge<\"toggle-sidebar\">(LATTICE_EVENT.toggleSidebar),\n};\n\nexport const builtinEffectHandlers: EffectHandlerRegistryFor<keyof EffectPropsMap & string> =\n typedBuiltinHandlers as EffectHandlerRegistryFor<keyof EffectPropsMap & string>;\n\nexport function mergeEffectHandlers(\n ...registries: Array<EffectHandlerRegistry | undefined>\n): EffectHandlerRegistry {\n return Object.assign({}, ...registries);\n}\n"],"mappings":";;;;;;;;AAyBA,SAAgB,cACd,OACA,IACe;CACf,OAAO;AACT;AAEA,SAAS,gBAAgB,KAAmB;CAC1C,MAAM,OAAO,SAAS,cAAc,GAAG;CACvC,KAAK,OAAO;CACZ,KAAK,MAAM;CACX,SAAS,KAAK,YAAY,IAAI;CAC9B,KAAK,MAAM;CACX,KAAK,OAAO;AACd;AAEA,SAAS,OAAoD,OAAqC;CAChG,QAAQ,WAAW,OAAO,cAAc,IAAI,YAAY,OAAO,EAAE,QAAQ,OAAO,MAAM,CAAC,CAAC;AAC1F;AAuBA,IAAa,wBACX;CAfA,gBAAgB,WAAY,OAAO,MAAM,OAAO,OAAO,SAAS,OAAO,IAAI,OAAO,OAAO;CACzF,WAAW,WAAW,OAAO,MAAM,OAAO,MAAM,GAAG;CACnD,WAAW,WAAW,gBAAgB,OAAO,MAAM,GAAG;CACtD,kBAAkB,WAAW,UAAU,OAAO,MAAM,MAAM;CAC1D,OAAO,OAAgB,cAAc,KAAK;CAC1C,SAAS,OAAkB,cAAc,OAAO;CAChD,mBAAmB,OAA0B,cAAc,cAAc;CACzE,oBAAoB,OAA2B,cAAc,eAAe;CAC5E,cAAc,OAAqB,cAAc,SAAS;CAC1D,eAAe,OAAsB,cAAc,UAAU;CAC7D,cAAc,OAAqB,cAAc,SAAS;CAC1D,kBAAkB,OAAyB,cAAc,aAAa;AAItE;AAEF,SAAgB,oBACd,GAAG,YACoB;CACvB,OAAO,OAAO,OAAO,CAAC,GAAG,GAAG,UAAU;AACxC"}
@@ -1,9 +1,6 @@
1
- import { ToastMessage } from './toast/index.js';
2
1
  import { Appearance } from './appearance/index.js';
3
2
  type EventBridgeProps = {
4
3
  onAppearanceChange?: (appearance: Appearance) => void;
5
- onLocaleChange?: (locale: string) => void;
6
- onToast?: (toast: ToastMessage) => void;
7
4
  };
8
- export declare function EventBridge({ onAppearanceChange, onLocaleChange, onToast }: EventBridgeProps): null;
5
+ export declare function EventBridge({ onAppearanceChange }: EventBridgeProps): null;
9
6
  export {};
@@ -1,22 +1,12 @@
1
1
  import { isAppearance } from "./appearance/index.js";
2
2
  import { LATTICE_EVENT } from "./core/event-names.js";
3
3
  import { useWindowEvent } from "./core/hooks/use-window-event.js";
4
- import { onToast } from "./toast/toast.js";
5
- import { useEffect } from "react";
6
4
  //#region resources/js/event-bridge.tsx
7
- function EventBridge({ onAppearanceChange, onLocaleChange, onToast: onToast$1 }) {
8
- useEffect(() => {
9
- if (!onToast$1) return;
10
- return onToast(onToast$1);
11
- }, [onToast$1]);
5
+ function EventBridge({ onAppearanceChange }) {
12
6
  useWindowEvent(LATTICE_EVENT.appearanceChange, (event) => {
13
7
  const value = event.detail?.value;
14
8
  if (isAppearance(value)) onAppearanceChange?.(value);
15
9
  }, { enabled: Boolean(onAppearanceChange) });
16
- useWindowEvent(LATTICE_EVENT.localeChange, (event) => {
17
- const locale = event.detail?.locale;
18
- if (typeof locale === "string" && locale !== "") onLocaleChange?.(locale);
19
- }, { enabled: Boolean(onLocaleChange) });
20
10
  return null;
21
11
  }
22
12
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"event-bridge.js","names":[],"sources":["../resources/js/event-bridge.tsx"],"sourcesContent":["import { useEffect } from \"react\";\nimport { onToast as subscribeToToasts } from \"@lattice-php/lattice/toast\";\nimport type { ToastMessage } from \"@lattice-php/lattice/toast\";\nimport { useWindowEvent } from \"@lattice-php/lattice/core/hooks/use-window-event\";\nimport { isAppearance, type Appearance } from \"./appearance\";\nimport { LATTICE_EVENT } from \"./core/event-names\";\n\ntype EventBridgeProps = {\n onAppearanceChange?: (appearance: Appearance) => void;\n onLocaleChange?: (locale: string) => void;\n onToast?: (toast: ToastMessage) => void;\n};\n\ntype AppearanceEvent = CustomEvent<{\n value?: unknown;\n}>;\n\ntype LocaleEvent = CustomEvent<{\n locale?: unknown;\n}>;\n\nexport function EventBridge({ onAppearanceChange, onLocaleChange, onToast }: EventBridgeProps) {\n useEffect(() => {\n if (!onToast) {\n return;\n }\n\n return subscribeToToasts(onToast);\n }, [onToast]);\n\n useWindowEvent(\n LATTICE_EVENT.appearanceChange,\n (event) => {\n const value = (event as AppearanceEvent).detail?.value;\n\n if (isAppearance(value)) {\n onAppearanceChange?.(value);\n }\n },\n { enabled: Boolean(onAppearanceChange) },\n );\n\n useWindowEvent(\n LATTICE_EVENT.localeChange,\n (event) => {\n const locale = (event as LocaleEvent).detail?.locale;\n\n if (typeof locale === \"string\" && locale !== \"\") {\n onLocaleChange?.(locale);\n }\n },\n { enabled: Boolean(onLocaleChange) },\n );\n\n return null;\n}\n"],"mappings":";;;;;;AAqBA,SAAgB,YAAY,EAAE,oBAAoB,gBAAgB,SAAA,aAA6B;CAC7F,gBAAgB;EACd,IAAI,CAAC,WACH;EAGF,OAAO,QAAkB,SAAO;CAClC,GAAG,CAAC,SAAO,CAAC;CAEZ,eACE,cAAc,mBACb,UAAU;EACT,MAAM,QAAS,MAA0B,QAAQ;EAEjD,IAAI,aAAa,KAAK,GACpB,qBAAqB,KAAK;CAE9B,GACA,EAAE,SAAS,QAAQ,kBAAkB,EAAE,CACzC;CAEA,eACE,cAAc,eACb,UAAU;EACT,MAAM,SAAU,MAAsB,QAAQ;EAE9C,IAAI,OAAO,WAAW,YAAY,WAAW,IAC3C,iBAAiB,MAAM;CAE3B,GACA,EAAE,SAAS,QAAQ,cAAc,EAAE,CACrC;CAEA,OAAO;AACT"}
1
+ {"version":3,"file":"event-bridge.js","names":[],"sources":["../resources/js/event-bridge.tsx"],"sourcesContent":["import { useWindowEvent } from \"@lattice-php/lattice/core/hooks/use-window-event\";\nimport { isAppearance, type Appearance } from \"./appearance\";\nimport { LATTICE_EVENT } from \"./core/event-names\";\n\ntype EventBridgeProps = {\n onAppearanceChange?: (appearance: Appearance) => void;\n};\n\ntype AppearanceEvent = CustomEvent<{\n value?: unknown;\n}>;\n\nexport function EventBridge({ onAppearanceChange }: EventBridgeProps) {\n useWindowEvent(\n LATTICE_EVENT.appearanceChange,\n (event) => {\n const value = (event as AppearanceEvent).detail?.value;\n\n if (isAppearance(value)) {\n onAppearanceChange?.(value);\n }\n },\n { enabled: Boolean(onAppearanceChange) },\n );\n\n return null;\n}\n"],"mappings":";;;;AAYA,SAAgB,YAAY,EAAE,sBAAwC;CACpE,eACE,cAAc,mBACb,UAAU;EACT,MAAM,QAAS,MAA0B,QAAQ;EAEjD,IAAI,aAAa,KAAK,GACpB,qBAAqB,KAAK;CAE9B,GACA,EAAE,SAAS,QAAQ,kBAAkB,EAAE,CACzC;CAEA,OAAO;AACT"}
@@ -29,7 +29,7 @@ var ChoiceComponent = ({ node }) => {
29
29
  ariaLabel: node.props.label ?? void 0,
30
30
  autoFocus: node.props.autoFocus ?? void 0,
31
31
  disabled: readOnly || disabled,
32
- name: testId,
32
+ name: testId ?? "segment",
33
33
  onSelect: commit,
34
34
  options,
35
35
  tabIndex: node.props.tabIndex ?? void 0,
@@ -1 +1 @@
1
- {"version":3,"file":"choice.js","names":[],"sources":["../../../../resources/js/form/components/fields/choice.tsx"],"sourcesContent":["import { useMemo } from \"react\";\nimport type { Option, RendererComponent } from \"@lattice-php/lattice/core/types\";\nimport { SegmentedPills } from \"@lattice-php/lattice/ui/segmented-pills\";\nimport { FormFieldFrame } from \"@lattice-php/lattice/form/components/base/field\";\nimport { useControlledField } from \"@lattice-php/lattice/form/hooks/use-controlled-field\";\nimport { useResolvedNode } from \"@lattice-php/lattice/form/hooks/resolved-nodes\";\nimport { useSeedDefault } from \"@lattice-php/lattice/form/hooks/use-seed-default\";\n\nexport const ChoiceComponent: RendererComponent<\"field.choice\"> = ({ node }) => {\n const resolvedNode = useResolvedNode(node);\n const { localName, name, testId, value, error, hidden, required, readOnly, disabled, commit } =\n useControlledField(node);\n const options = useMemo(\n () => (resolvedNode.props as { options?: Option[] }).options ?? [],\n [resolvedNode.props],\n );\n const fallbackValue = options[0]?.value ?? \"\";\n const selected = value || fallbackValue;\n\n useSeedDefault(localName, selected || undefined);\n\n if (hidden || options.length === 0) {\n return null;\n }\n\n return (\n <FormFieldFrame\n error={error}\n helperText={node.props.helperText ?? undefined}\n tooltip={node.props.tooltip ?? undefined}\n label={node.props.label ?? \"\"}\n name={name}\n required={required}\n >\n <input name={name} type=\"hidden\" value={selected} />\n <SegmentedPills\n ariaLabel={node.props.label ?? undefined}\n autoFocus={node.props.autoFocus ?? undefined}\n disabled={readOnly || disabled}\n name={testId}\n onSelect={commit}\n options={options}\n tabIndex={node.props.tabIndex ?? undefined}\n value={selected}\n />\n </FormFieldFrame>\n );\n};\n"],"mappings":";;;;;;;;AAQA,IAAa,mBAAsD,EAAE,WAAW;CAC9E,MAAM,eAAe,gBAAgB,IAAI;CACzC,MAAM,EAAE,WAAW,MAAM,QAAQ,OAAO,OAAO,QAAQ,UAAU,UAAU,UAAU,WACnF,mBAAmB,IAAI;CACzB,MAAM,UAAU,cACP,aAAa,MAAiC,WAAW,CAAC,GACjE,CAAC,aAAa,KAAK,CACrB;CACA,MAAM,gBAAgB,QAAQ,EAAE,EAAE,SAAS;CAC3C,MAAM,WAAW,SAAS;CAE1B,eAAe,WAAW,YAAY,KAAA,CAAS;CAE/C,IAAI,UAAU,QAAQ,WAAW,GAC/B,OAAO;CAGT,OACE,qBAAC,gBAAD;EACS;EACP,YAAY,KAAK,MAAM,cAAc,KAAA;EACrC,SAAS,KAAK,MAAM,WAAW,KAAA;EAC/B,OAAO,KAAK,MAAM,SAAS;EACrB;EACI;EANZ,UAAA,CAQE,oBAAC,SAAD;GAAa;GAAM,MAAK;GAAS,OAAO;EAAW,CAAA,GACnD,oBAAC,gBAAD;GACE,WAAW,KAAK,MAAM,SAAS,KAAA;GAC/B,WAAW,KAAK,MAAM,aAAa,KAAA;GACnC,UAAU,YAAY;GACtB,MAAM;GACN,UAAU;GACD;GACT,UAAU,KAAK,MAAM,YAAY,KAAA;GACjC,OAAO;EACR,CAAA,CACa;;AAEpB"}
1
+ {"version":3,"file":"choice.js","names":[],"sources":["../../../../resources/js/form/components/fields/choice.tsx"],"sourcesContent":["import { useMemo } from \"react\";\nimport type { Option, RendererComponent } from \"@lattice-php/lattice/core/types\";\nimport { SegmentedPills } from \"@lattice-php/lattice/ui/segmented-pills\";\nimport { FormFieldFrame } from \"@lattice-php/lattice/form/components/base/field\";\nimport { useControlledField } from \"@lattice-php/lattice/form/hooks/use-controlled-field\";\nimport { useResolvedNode } from \"@lattice-php/lattice/form/hooks/resolved-nodes\";\nimport { useSeedDefault } from \"@lattice-php/lattice/form/hooks/use-seed-default\";\n\nexport const ChoiceComponent: RendererComponent<\"field.choice\"> = ({ node }) => {\n const resolvedNode = useResolvedNode(node);\n const { localName, name, testId, value, error, hidden, required, readOnly, disabled, commit } =\n useControlledField(node);\n const options = useMemo(\n () => (resolvedNode.props as { options?: Option[] }).options ?? [],\n [resolvedNode.props],\n );\n const fallbackValue = options[0]?.value ?? \"\";\n const selected = value || fallbackValue;\n\n useSeedDefault(localName, selected || undefined);\n\n if (hidden || options.length === 0) {\n return null;\n }\n\n return (\n <FormFieldFrame\n error={error}\n helperText={node.props.helperText ?? undefined}\n tooltip={node.props.tooltip ?? undefined}\n label={node.props.label ?? \"\"}\n name={name}\n required={required}\n >\n <input name={name} type=\"hidden\" value={selected} />\n <SegmentedPills\n ariaLabel={node.props.label ?? undefined}\n autoFocus={node.props.autoFocus ?? undefined}\n disabled={readOnly || disabled}\n name={testId ?? \"segment\"}\n onSelect={commit}\n options={options}\n tabIndex={node.props.tabIndex ?? undefined}\n value={selected}\n />\n </FormFieldFrame>\n );\n};\n"],"mappings":";;;;;;;;AAQA,IAAa,mBAAsD,EAAE,WAAW;CAC9E,MAAM,eAAe,gBAAgB,IAAI;CACzC,MAAM,EAAE,WAAW,MAAM,QAAQ,OAAO,OAAO,QAAQ,UAAU,UAAU,UAAU,WACnF,mBAAmB,IAAI;CACzB,MAAM,UAAU,cACP,aAAa,MAAiC,WAAW,CAAC,GACjE,CAAC,aAAa,KAAK,CACrB;CACA,MAAM,gBAAgB,QAAQ,EAAE,EAAE,SAAS;CAC3C,MAAM,WAAW,SAAS;CAE1B,eAAe,WAAW,YAAY,KAAA,CAAS;CAE/C,IAAI,UAAU,QAAQ,WAAW,GAC/B,OAAO;CAGT,OACE,qBAAC,gBAAD;EACS;EACP,YAAY,KAAK,MAAM,cAAc,KAAA;EACrC,SAAS,KAAK,MAAM,WAAW,KAAA;EAC/B,OAAO,KAAK,MAAM,SAAS;EACrB;EACI;EANZ,UAAA,CAQE,oBAAC,SAAD;GAAa;GAAM,MAAK;GAAS,OAAO;EAAW,CAAA,GACnD,oBAAC,gBAAD;GACE,WAAW,KAAK,MAAM,SAAS,KAAA;GAC/B,WAAW,KAAK,MAAM,aAAa,KAAA;GACnC,UAAU,YAAY;GACtB,MAAM,UAAU;GAChB,UAAU;GACD;GACT,UAAU,KAAK,MAAM,YAAY,KAAA;GACjC,OAAO;EACR,CAAA,CACa;;AAEpB"}
@@ -1,7 +1,4 @@
1
- import { Method } from '@inertiajs/core';
2
1
  import { NodeUnionOf } from '../core/types.js';
3
- import { FormFieldNodeType, FormNodeType } from '../types/generated.js';
2
+ import { FormNodeType } from '../types/generated.js';
4
3
  export type { Checkbox, Choice, DateInput, DateTimeInput, Form, FormNodeType, HiddenInput, LabelAction, NumberInput, PasswordInput, RichEditor, Select, Textarea, TextInput, TimeInput, } from '../types/generated.js';
5
- export type FormFieldNode = NodeUnionOf<FormFieldNodeType>;
6
4
  export type FormNode = NodeUnionOf<FormNodeType>;
7
- export type FormMethod = Method;
@@ -3,8 +3,8 @@ type Config = {
3
3
  readonly locales: readonly string[];
4
4
  readonly timezone: string | null;
5
5
  };
6
+ export declare const subscribeConfig: (callback: () => void) => () => void;
6
7
  export declare function setConfig(config: I18nConfig | undefined): void;
7
8
  export declare function configTimezone(): string | null;
8
- export declare function subscribeConfig(callback: () => void): () => void;
9
9
  export declare function useConfig(): Config;
10
10
  export {};
@@ -1,33 +1,23 @@
1
+ import { createListeners } from "../lib/listeners.js";
1
2
  import { useSyncExternalStore } from "react";
2
3
  //#region resources/js/i18n/config.ts
3
4
  var fallback = {
4
5
  locales: [],
5
6
  timezone: null
6
7
  };
7
- var listeners = /* @__PURE__ */ new Set();
8
+ var { subscribe, notify } = createListeners();
8
9
  var active = fallback;
9
10
  function normalizeLocales(locales) {
10
11
  return Array.from(new Set((locales ?? []).map((locale) => locale.trim()).filter(Boolean)));
11
12
  }
12
- function sameLocales(left, right) {
13
- return left.length === right.length && left.every((locale, index) => locale === right[index]);
14
- }
15
13
  function snapshot() {
16
14
  return active;
17
15
  }
18
- function subscribe(callback) {
19
- listeners.add(callback);
20
- return () => {
21
- listeners.delete(callback);
22
- };
23
- }
24
- function notify() {
25
- listeners.forEach((listener) => listener());
26
- }
16
+ var subscribeConfig = subscribe;
27
17
  function setConfig(config) {
28
18
  const locales = normalizeLocales(config?.locales);
29
19
  const timezone = config?.timezone ?? null;
30
- if (sameLocales(active.locales, locales) && active.timezone === timezone) return;
20
+ if (active.locales.join("") === locales.join("") && active.timezone === timezone) return;
31
21
  active = {
32
22
  locales,
33
23
  timezone
@@ -37,14 +27,8 @@ function setConfig(config) {
37
27
  function configTimezone() {
38
28
  return active.timezone;
39
29
  }
40
- function subscribeConfig(callback) {
41
- listeners.add(callback);
42
- return () => {
43
- listeners.delete(callback);
44
- };
45
- }
46
30
  function useConfig() {
47
- return useSyncExternalStore(subscribe, snapshot, () => fallback);
31
+ return useSyncExternalStore(subscribeConfig, snapshot, () => fallback);
48
32
  }
49
33
  //#endregion
50
34
  export { configTimezone, setConfig, subscribeConfig, useConfig };
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","names":[],"sources":["../../resources/js/i18n/config.ts"],"sourcesContent":["import type { I18nConfig } from \"@lattice-php/lattice/types/generated\";\nimport { useSyncExternalStore } from \"react\";\n\ntype Config = {\n readonly locales: readonly string[];\n readonly timezone: string | null;\n};\n\nconst fallback: Config = { locales: [], timezone: null };\nconst listeners = new Set<() => void>();\n\nlet active: Config = fallback;\n\nfunction normalizeLocales(locales: readonly string[] | undefined): string[] {\n return Array.from(new Set((locales ?? []).map((locale) => locale.trim()).filter(Boolean)));\n}\n\nfunction sameLocales(left: readonly string[], right: readonly string[]): boolean {\n return left.length === right.length && left.every((locale, index) => locale === right[index]);\n}\n\nfunction snapshot(): Config {\n return active;\n}\n\nfunction subscribe(callback: () => void): () => void {\n listeners.add(callback);\n\n return () => {\n listeners.delete(callback);\n };\n}\n\nfunction notify(): void {\n listeners.forEach((listener) => listener());\n}\n\nexport function setConfig(config: I18nConfig | undefined): void {\n const locales = normalizeLocales(config?.locales);\n const timezone = config?.timezone ?? null;\n\n if (sameLocales(active.locales, locales) && active.timezone === timezone) {\n return;\n }\n\n active = { locales, timezone };\n notify();\n}\n\nexport function configTimezone(): string | null {\n return active.timezone;\n}\n\nexport function subscribeConfig(callback: () => void): () => void {\n listeners.add(callback);\n\n return () => {\n listeners.delete(callback);\n };\n}\n\nexport function useConfig(): Config {\n return useSyncExternalStore(subscribe, snapshot, () => fallback);\n}\n"],"mappings":";;AAQA,IAAM,WAAmB;CAAE,SAAS,CAAC;CAAG,UAAU;AAAK;AACvD,IAAM,4BAAY,IAAI,IAAgB;AAEtC,IAAI,SAAiB;AAErB,SAAS,iBAAiB,SAAkD;CAC1E,OAAO,MAAM,KAAK,IAAI,KAAK,WAAW,CAAC,EAAA,CAAG,KAAK,WAAW,OAAO,KAAK,CAAC,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC;AAC3F;AAEA,SAAS,YAAY,MAAyB,OAAmC;CAC/E,OAAO,KAAK,WAAW,MAAM,UAAU,KAAK,OAAO,QAAQ,UAAU,WAAW,MAAM,MAAM;AAC9F;AAEA,SAAS,WAAmB;CAC1B,OAAO;AACT;AAEA,SAAS,UAAU,UAAkC;CACnD,UAAU,IAAI,QAAQ;CAEtB,aAAa;EACX,UAAU,OAAO,QAAQ;CAC3B;AACF;AAEA,SAAS,SAAe;CACtB,UAAU,SAAS,aAAa,SAAS,CAAC;AAC5C;AAEA,SAAgB,UAAU,QAAsC;CAC9D,MAAM,UAAU,iBAAiB,QAAQ,OAAO;CAChD,MAAM,WAAW,QAAQ,YAAY;CAErC,IAAI,YAAY,OAAO,SAAS,OAAO,KAAK,OAAO,aAAa,UAC9D;CAGF,SAAS;EAAE;EAAS;CAAS;CAC7B,OAAO;AACT;AAEA,SAAgB,iBAAgC;CAC9C,OAAO,OAAO;AAChB;AAEA,SAAgB,gBAAgB,UAAkC;CAChE,UAAU,IAAI,QAAQ;CAEtB,aAAa;EACX,UAAU,OAAO,QAAQ;CAC3B;AACF;AAEA,SAAgB,YAAoB;CAClC,OAAO,qBAAqB,WAAW,gBAAgB,QAAQ;AACjE"}
1
+ {"version":3,"file":"config.js","names":[],"sources":["../../resources/js/i18n/config.ts"],"sourcesContent":["import type { I18nConfig } from \"@lattice-php/lattice/types/generated\";\nimport { useSyncExternalStore } from \"react\";\nimport { createListeners } from \"@lattice-php/lattice/lib/listeners\";\n\ntype Config = {\n readonly locales: readonly string[];\n readonly timezone: string | null;\n};\n\nconst fallback: Config = { locales: [], timezone: null };\nconst { subscribe, notify } = createListeners();\n\nlet active: Config = fallback;\n\nfunction normalizeLocales(locales: readonly string[] | undefined): string[] {\n return Array.from(new Set((locales ?? []).map((locale) => locale.trim()).filter(Boolean)));\n}\n\nfunction snapshot(): Config {\n return active;\n}\n\nexport const subscribeConfig = subscribe;\n\nexport function setConfig(config: I18nConfig | undefined): void {\n const locales = normalizeLocales(config?.locales);\n const timezone = config?.timezone ?? null;\n\n if (active.locales.join(\"\u001f\") === locales.join(\"\u001f\") && active.timezone === timezone) {\n return;\n }\n\n active = { locales, timezone };\n notify();\n}\n\nexport function configTimezone(): string | null {\n return active.timezone;\n}\n\nexport function useConfig(): Config {\n return useSyncExternalStore(subscribeConfig, snapshot, () => fallback);\n}\n"],"mappings":";;;AASA,IAAM,WAAmB;CAAE,SAAS,CAAC;CAAG,UAAU;AAAK;AACvD,IAAM,EAAE,WAAW,WAAW,gBAAgB;AAE9C,IAAI,SAAiB;AAErB,SAAS,iBAAiB,SAAkD;CAC1E,OAAO,MAAM,KAAK,IAAI,KAAK,WAAW,CAAC,EAAA,CAAG,KAAK,WAAW,OAAO,KAAK,CAAC,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC;AAC3F;AAEA,SAAS,WAAmB;CAC1B,OAAO;AACT;AAEA,IAAa,kBAAkB;AAE/B,SAAgB,UAAU,QAAsC;CAC9D,MAAM,UAAU,iBAAiB,QAAQ,OAAO;CAChD,MAAM,WAAW,QAAQ,YAAY;CAErC,IAAI,OAAO,QAAQ,KAAK,GAAG,MAAM,QAAQ,KAAK,GAAG,KAAK,OAAO,aAAa,UACxE;CAGF,SAAS;EAAE;EAAS;CAAS;CAC7B,OAAO;AACT;AAEA,SAAgB,iBAAgC;CAC9C,OAAO,OAAO;AAChB;AAEA,SAAgB,YAAoB;CAClC,OAAO,qBAAqB,iBAAiB,gBAAgB,QAAQ;AACvE"}
@@ -2,10 +2,10 @@ export { i18n, useT, translate } from './instance.js';
2
2
  export { configureI18n, enableBackend } from './backend.js';
3
3
  export { currentLocale, localeHeader, setLocale, useLocale } from './locale.js';
4
4
  export { LocaleReload } from './locale-reload.js';
5
- export { LocaleSwitcher, useLocaleOptions } from './locale-switcher.js';
5
+ export { useLocaleOptions } from './locale-switcher.js';
6
6
  export { configureI18nFromPageProps, i18nConfigFromPageProps } from './page-props.js';
7
7
  export type { BackendOptions, ConfigureI18nOptions, I18nConfig } from './backend.js';
8
- export type { LocaleOption, LocaleSwitcherProps, UseLocaleOptionsOptions, UseLocaleOptionsReturn, } from './locale-switcher.js';
8
+ export type { LocaleOption, UseLocaleOptionsOptions, UseLocaleOptionsReturn, } from './locale-switcher.js';
9
9
  export type { UseLocaleReturn } from './locale.js';
10
10
  export { currentTimezone, setTimezone, useTimezone } from './timezone.js';
11
11
  export type { UseTimezoneReturn } from './timezone.js';
@@ -4,7 +4,7 @@ import { i18n, translate, useT } from "./instance.js";
4
4
  import { LocaleReload } from "./locale-reload.js";
5
5
  import { i18nConfigFromPageProps } from "./shared-props.js";
6
6
  import { configureI18n, enableBackend } from "./backend.js";
7
- import { LocaleSwitcher, useLocaleOptions } from "./locale-switcher.js";
7
+ import { useLocaleOptions } from "./locale-switcher.js";
8
8
  import { configureI18nFromPageProps } from "./page-props.js";
9
9
  import { DateTime } from "./date-time.js";
10
- export { DateTime, LocaleReload, LocaleSwitcher, configureI18n, configureI18nFromPageProps, currentLocale, currentTimezone, enableBackend, i18n, i18nConfigFromPageProps, localeHeader, setLocale, setTimezone, translate, useLocale, useLocaleOptions, useT, useTimezone };
10
+ export { DateTime, LocaleReload, configureI18n, configureI18nFromPageProps, currentLocale, currentTimezone, enableBackend, i18n, i18nConfigFromPageProps, localeHeader, setLocale, setTimezone, translate, useLocale, useLocaleOptions, useT, useTimezone };
@@ -1,4 +1,3 @@
1
- import { ReactNode } from 'react';
2
1
  export type LocaleOption = {
3
2
  readonly value: string;
4
3
  readonly label: string;
@@ -14,8 +13,4 @@ export type UseLocaleOptionsReturn = {
14
13
  readonly options: readonly LocaleOption[];
15
14
  readonly setLocale: (locale: string) => void;
16
15
  };
17
- export type LocaleSwitcherProps = UseLocaleOptionsOptions & {
18
- readonly children: (state: UseLocaleOptionsReturn) => ReactNode;
19
- };
20
16
  export declare function useLocaleOptions({ namespace, label, }?: UseLocaleOptionsOptions): UseLocaleOptionsReturn;
21
- export declare function LocaleSwitcher({ children, ...options }: LocaleSwitcherProps): import("react").JSX.Element;
@@ -1,5 +1,4 @@
1
1
  import { useT } from "./instance.js";
2
- import { Fragment, jsx } from "react/jsx-runtime";
3
2
  //#region resources/js/i18n/locale-switcher.tsx
4
3
  function useLocaleOptions({ namespace = "lattice", label } = {}) {
5
4
  const { t, locale, locales, setLocale } = useT(namespace);
@@ -16,10 +15,7 @@ function useLocaleOptions({ namespace = "lattice", label } = {}) {
16
15
  setLocale
17
16
  };
18
17
  }
19
- function LocaleSwitcher({ children, ...options }) {
20
- return /* @__PURE__ */ jsx(Fragment, { children: children(useLocaleOptions(options)) });
21
- }
22
18
  //#endregion
23
- export { LocaleSwitcher, useLocaleOptions };
19
+ export { useLocaleOptions };
24
20
 
25
21
  //# sourceMappingURL=locale-switcher.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"locale-switcher.js","names":[],"sources":["../../resources/js/i18n/locale-switcher.tsx"],"sourcesContent":["import type { ReactNode } from \"react\";\nimport { useT } from \"./instance\";\n\nexport type LocaleOption = {\n readonly value: string;\n readonly label: string;\n readonly active: boolean;\n};\n\nexport type UseLocaleOptionsOptions = {\n readonly namespace?: string;\n readonly label?: (locale: string) => string;\n};\n\nexport type UseLocaleOptionsReturn = {\n readonly locale: string;\n readonly locales: readonly string[];\n readonly options: readonly LocaleOption[];\n readonly setLocale: (locale: string) => void;\n};\n\nexport type LocaleSwitcherProps = UseLocaleOptionsOptions & {\n readonly children: (state: UseLocaleOptionsReturn) => ReactNode;\n};\n\nexport function useLocaleOptions({\n namespace = \"lattice\",\n label,\n}: UseLocaleOptionsOptions = {}): UseLocaleOptionsReturn {\n const { t, locale, locales, setLocale } = useT(namespace);\n const values = locales.length > 0 ? locales : [locale];\n const labelFor = label ?? ((value: string): string => t(`language.${value}`, value));\n\n return {\n locale,\n locales: values,\n options: values.map((value) => ({\n value,\n label: labelFor(value),\n active: value === locale,\n })),\n setLocale,\n };\n}\n\nexport function LocaleSwitcher({ children, ...options }: LocaleSwitcherProps) {\n return <>{children(useLocaleOptions(options))}</>;\n}\n"],"mappings":";;;AAyBA,SAAgB,iBAAiB,EAC/B,YAAY,WACZ,UAC2B,CAAC,GAA2B;CACvD,MAAM,EAAE,GAAG,QAAQ,SAAS,cAAc,KAAK,SAAS;CACxD,MAAM,SAAS,QAAQ,SAAS,IAAI,UAAU,CAAC,MAAM;CACrD,MAAM,WAAW,WAAW,UAA0B,EAAE,YAAY,SAAS,KAAK;CAElF,OAAO;EACL;EACA,SAAS;EACT,SAAS,OAAO,KAAK,WAAW;GAC9B;GACA,OAAO,SAAS,KAAK;GACrB,QAAQ,UAAU;EACpB,EAAE;EACF;CACF;AACF;AAEA,SAAgB,eAAe,EAAE,UAAU,GAAG,WAAgC;CAC5E,OAAO,oBAAA,UAAA,EAAA,UAAG,SAAS,iBAAiB,OAAO,CAAC,EAAI,CAAA;AAClD"}
1
+ {"version":3,"file":"locale-switcher.js","names":[],"sources":["../../resources/js/i18n/locale-switcher.tsx"],"sourcesContent":["import { useT } from \"./instance\";\n\nexport type LocaleOption = {\n readonly value: string;\n readonly label: string;\n readonly active: boolean;\n};\n\nexport type UseLocaleOptionsOptions = {\n readonly namespace?: string;\n readonly label?: (locale: string) => string;\n};\n\nexport type UseLocaleOptionsReturn = {\n readonly locale: string;\n readonly locales: readonly string[];\n readonly options: readonly LocaleOption[];\n readonly setLocale: (locale: string) => void;\n};\n\nexport function useLocaleOptions({\n namespace = \"lattice\",\n label,\n}: UseLocaleOptionsOptions = {}): UseLocaleOptionsReturn {\n const { t, locale, locales, setLocale } = useT(namespace);\n const values = locales.length > 0 ? locales : [locale];\n const labelFor = label ?? ((value: string): string => t(`language.${value}`, value));\n\n return {\n locale,\n locales: values,\n options: values.map((value) => ({\n value,\n label: labelFor(value),\n active: value === locale,\n })),\n setLocale,\n };\n}\n"],"mappings":";;AAoBA,SAAgB,iBAAiB,EAC/B,YAAY,WACZ,UAC2B,CAAC,GAA2B;CACvD,MAAM,EAAE,GAAG,QAAQ,SAAS,cAAc,KAAK,SAAS;CACxD,MAAM,SAAS,QAAQ,SAAS,IAAI,UAAU,CAAC,MAAM;CACrD,MAAM,WAAW,WAAW,UAA0B,EAAE,YAAY,SAAS,KAAK;CAElF,OAAO;EACL;EACA,SAAS;EACT,SAAS,OAAO,KAAK,WAAW;GAC9B;GACA,OAAO,SAAS,KAAK;GACrB,QAAQ,UAAU;EACpB,EAAE;EACF;CACF;AACF"}
@@ -1,10 +1,11 @@
1
+ import { createListeners } from "../lib/listeners.js";
1
2
  import { LATTICE_EVENT } from "../core/event-names.js";
2
3
  import { useSyncExternalStore } from "react";
3
4
  //#region resources/js/i18n/locale.ts
4
5
  var key = "locale";
5
6
  var fallback = "en";
6
7
  var maxAge = 31536e3;
7
- var listeners = /* @__PURE__ */ new Set();
8
+ var { subscribe, notify } = createListeners();
8
9
  var active;
9
10
  function normalize(value) {
10
11
  const next = value.trim();
@@ -50,15 +51,6 @@ function snapshot() {
50
51
  active ??= detectedLocale();
51
52
  return active;
52
53
  }
53
- function subscribe(callback) {
54
- listeners.add(callback);
55
- return () => {
56
- listeners.delete(callback);
57
- };
58
- }
59
- function notify() {
60
- listeners.forEach((listener) => listener());
61
- }
62
54
  function dispatch(locale) {
63
55
  if (typeof window === "undefined") return;
64
56
  window.dispatchEvent(new CustomEvent(LATTICE_EVENT.localeChange, { detail: { locale } }));
@@ -1 +1 @@
1
- {"version":3,"file":"locale.js","names":[],"sources":["../../resources/js/i18n/locale.ts"],"sourcesContent":["import { useSyncExternalStore } from \"react\";\nimport { LATTICE_EVENT } from \"@lattice-php/lattice/core/event-names\";\n\nexport type UseLocaleReturn = {\n readonly locale: string;\n readonly setLocale: (locale: string) => void;\n};\n\nconst key = \"locale\";\nconst fallback = \"en\";\nconst maxAge = 365 * 24 * 60 * 60;\nconst listeners = new Set<() => void>();\n\nlet active: string | undefined;\n\nfunction normalize(value: string): string {\n const next = value.trim();\n\n return next === \"\" ? fallback : next;\n}\n\nfunction storedValue(): string | null {\n if (typeof window === \"undefined\") {\n return null;\n }\n\n try {\n return localStorage.getItem(key);\n } catch {\n return null;\n }\n}\n\nfunction cookieValue(): string | null {\n if (typeof document === \"undefined\") {\n return null;\n }\n\n const item = document.cookie\n .split(\";\")\n .map((cookie) => cookie.trim())\n .find((cookie) => cookie.startsWith(`${key}=`));\n\n if (!item) {\n return null;\n }\n\n try {\n return decodeURIComponent(item.slice(key.length + 1));\n } catch {\n return null;\n }\n}\n\nfunction documentValue(): string | null {\n if (typeof document === \"undefined\") {\n return null;\n }\n\n return document.documentElement.lang || null;\n}\n\nfunction detectedLocale(): string {\n return normalize(storedValue() ?? cookieValue() ?? documentValue() ?? fallback);\n}\n\nfunction persist(locale: string): void {\n if (typeof document !== \"undefined\") {\n document.cookie = `${key}=${encodeURIComponent(locale)};path=/;max-age=${maxAge};SameSite=Lax`;\n document.documentElement.lang = locale;\n }\n\n if (typeof window !== \"undefined\") {\n try {\n localStorage.setItem(key, locale);\n } catch {\n return;\n }\n }\n}\n\nfunction snapshot(): string {\n active ??= detectedLocale();\n\n return active;\n}\n\nfunction subscribe(callback: () => void): () => void {\n listeners.add(callback);\n\n return () => {\n listeners.delete(callback);\n };\n}\n\nfunction notify(): void {\n listeners.forEach((listener) => listener());\n}\n\nfunction dispatch(locale: string): void {\n if (typeof window === \"undefined\") {\n return;\n }\n\n window.dispatchEvent(new CustomEvent(LATTICE_EVENT.localeChange, { detail: { locale } }));\n}\n\nexport function currentLocale(): string {\n return snapshot();\n}\n\nexport function localeHeader(): Record<string, string> {\n return { \"Accept-Language\": currentLocale() };\n}\n\nexport function subscribeLocale(callback: (locale: string) => void): () => void {\n return subscribe(() => callback(currentLocale()));\n}\n\nexport function setLocale(locale: string): void {\n const previous = currentLocale();\n const next = normalize(locale);\n\n active = next;\n persist(next);\n\n if (next === previous) {\n return;\n }\n\n notify();\n dispatch(next);\n}\n\nexport function useLocale(): UseLocaleReturn {\n const locale = useSyncExternalStore(subscribe, snapshot, () => fallback);\n\n return { locale, setLocale } as const;\n}\n"],"mappings":";;;AAQA,IAAM,MAAM;AACZ,IAAM,WAAW;AACjB,IAAM,SAAS;AACf,IAAM,4BAAY,IAAI,IAAgB;AAEtC,IAAI;AAEJ,SAAS,UAAU,OAAuB;CACxC,MAAM,OAAO,MAAM,KAAK;CAExB,OAAO,SAAS,KAAK,WAAW;AAClC;AAEA,SAAS,cAA6B;CACpC,IAAI,OAAO,WAAW,aACpB,OAAO;CAGT,IAAI;EACF,OAAO,aAAa,QAAQ,GAAG;CACjC,QAAQ;EACN,OAAO;CACT;AACF;AAEA,SAAS,cAA6B;CACpC,IAAI,OAAO,aAAa,aACtB,OAAO;CAGT,MAAM,OAAO,SAAS,OACnB,MAAM,GAAG,CAAC,CACV,KAAK,WAAW,OAAO,KAAK,CAAC,CAAC,CAC9B,MAAM,WAAW,OAAO,WAAW,GAAG,IAAI,EAAE,CAAC;CAEhD,IAAI,CAAC,MACH,OAAO;CAGT,IAAI;EACF,OAAO,mBAAmB,KAAK,MAAM,CAAc,CAAC;CACtD,QAAQ;EACN,OAAO;CACT;AACF;AAEA,SAAS,gBAA+B;CACtC,IAAI,OAAO,aAAa,aACtB,OAAO;CAGT,OAAO,SAAS,gBAAgB,QAAQ;AAC1C;AAEA,SAAS,iBAAyB;CAChC,OAAO,UAAU,YAAY,KAAK,YAAY,KAAK,cAAc,KAAK,QAAQ;AAChF;AAEA,SAAS,QAAQ,QAAsB;CACrC,IAAI,OAAO,aAAa,aAAa;EACnC,SAAS,SAAS,GAAG,IAAI,GAAG,mBAAmB,MAAM,EAAE,kBAAkB,OAAO;EAChF,SAAS,gBAAgB,OAAO;CAClC;CAEA,IAAI,OAAO,WAAW,aACpB,IAAI;EACF,aAAa,QAAQ,KAAK,MAAM;CAClC,QAAQ;EACN;CACF;AAEJ;AAEA,SAAS,WAAmB;CAC1B,WAAW,eAAe;CAE1B,OAAO;AACT;AAEA,SAAS,UAAU,UAAkC;CACnD,UAAU,IAAI,QAAQ;CAEtB,aAAa;EACX,UAAU,OAAO,QAAQ;CAC3B;AACF;AAEA,SAAS,SAAe;CACtB,UAAU,SAAS,aAAa,SAAS,CAAC;AAC5C;AAEA,SAAS,SAAS,QAAsB;CACtC,IAAI,OAAO,WAAW,aACpB;CAGF,OAAO,cAAc,IAAI,YAAY,cAAc,cAAc,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC;AAC1F;AAEA,SAAgB,gBAAwB;CACtC,OAAO,SAAS;AAClB;AAEA,SAAgB,eAAuC;CACrD,OAAO,EAAE,mBAAmB,cAAc,EAAE;AAC9C;AAEA,SAAgB,gBAAgB,UAAgD;CAC9E,OAAO,gBAAgB,SAAS,cAAc,CAAC,CAAC;AAClD;AAEA,SAAgB,UAAU,QAAsB;CAC9C,MAAM,WAAW,cAAc;CAC/B,MAAM,OAAO,UAAU,MAAM;CAE7B,SAAS;CACT,QAAQ,IAAI;CAEZ,IAAI,SAAS,UACX;CAGF,OAAO;CACP,SAAS,IAAI;AACf;AAEA,SAAgB,YAA6B;CAG3C,OAAO;EAAE,QAFM,qBAAqB,WAAW,gBAAgB,QAEtD;EAAQ;CAAU;AAC7B"}
1
+ {"version":3,"file":"locale.js","names":[],"sources":["../../resources/js/i18n/locale.ts"],"sourcesContent":["import { useSyncExternalStore } from \"react\";\nimport { LATTICE_EVENT } from \"@lattice-php/lattice/core/event-names\";\nimport { createListeners } from \"@lattice-php/lattice/lib/listeners\";\n\nexport type UseLocaleReturn = {\n readonly locale: string;\n readonly setLocale: (locale: string) => void;\n};\n\nconst key = \"locale\";\nconst fallback = \"en\";\nconst maxAge = 365 * 24 * 60 * 60;\nconst { subscribe, notify } = createListeners();\n\nlet active: string | undefined;\n\nfunction normalize(value: string): string {\n const next = value.trim();\n\n return next === \"\" ? fallback : next;\n}\n\nfunction storedValue(): string | null {\n if (typeof window === \"undefined\") {\n return null;\n }\n\n try {\n return localStorage.getItem(key);\n } catch {\n return null;\n }\n}\n\nfunction cookieValue(): string | null {\n if (typeof document === \"undefined\") {\n return null;\n }\n\n const item = document.cookie\n .split(\";\")\n .map((cookie) => cookie.trim())\n .find((cookie) => cookie.startsWith(`${key}=`));\n\n if (!item) {\n return null;\n }\n\n try {\n return decodeURIComponent(item.slice(key.length + 1));\n } catch {\n return null;\n }\n}\n\nfunction documentValue(): string | null {\n if (typeof document === \"undefined\") {\n return null;\n }\n\n return document.documentElement.lang || null;\n}\n\nfunction detectedLocale(): string {\n return normalize(storedValue() ?? cookieValue() ?? documentValue() ?? fallback);\n}\n\nfunction persist(locale: string): void {\n if (typeof document !== \"undefined\") {\n document.cookie = `${key}=${encodeURIComponent(locale)};path=/;max-age=${maxAge};SameSite=Lax`;\n document.documentElement.lang = locale;\n }\n\n if (typeof window !== \"undefined\") {\n try {\n localStorage.setItem(key, locale);\n } catch {\n return;\n }\n }\n}\n\nfunction snapshot(): string {\n active ??= detectedLocale();\n\n return active;\n}\n\nfunction dispatch(locale: string): void {\n if (typeof window === \"undefined\") {\n return;\n }\n\n window.dispatchEvent(new CustomEvent(LATTICE_EVENT.localeChange, { detail: { locale } }));\n}\n\nexport function currentLocale(): string {\n return snapshot();\n}\n\nexport function localeHeader(): Record<string, string> {\n return { \"Accept-Language\": currentLocale() };\n}\n\nexport function subscribeLocale(callback: (locale: string) => void): () => void {\n return subscribe(() => callback(currentLocale()));\n}\n\nexport function setLocale(locale: string): void {\n const previous = currentLocale();\n const next = normalize(locale);\n\n active = next;\n persist(next);\n\n if (next === previous) {\n return;\n }\n\n notify();\n dispatch(next);\n}\n\nexport function useLocale(): UseLocaleReturn {\n const locale = useSyncExternalStore(subscribe, snapshot, () => fallback);\n\n return { locale, setLocale } as const;\n}\n"],"mappings":";;;;AASA,IAAM,MAAM;AACZ,IAAM,WAAW;AACjB,IAAM,SAAS;AACf,IAAM,EAAE,WAAW,WAAW,gBAAgB;AAE9C,IAAI;AAEJ,SAAS,UAAU,OAAuB;CACxC,MAAM,OAAO,MAAM,KAAK;CAExB,OAAO,SAAS,KAAK,WAAW;AAClC;AAEA,SAAS,cAA6B;CACpC,IAAI,OAAO,WAAW,aACpB,OAAO;CAGT,IAAI;EACF,OAAO,aAAa,QAAQ,GAAG;CACjC,QAAQ;EACN,OAAO;CACT;AACF;AAEA,SAAS,cAA6B;CACpC,IAAI,OAAO,aAAa,aACtB,OAAO;CAGT,MAAM,OAAO,SAAS,OACnB,MAAM,GAAG,CAAC,CACV,KAAK,WAAW,OAAO,KAAK,CAAC,CAAC,CAC9B,MAAM,WAAW,OAAO,WAAW,GAAG,IAAI,EAAE,CAAC;CAEhD,IAAI,CAAC,MACH,OAAO;CAGT,IAAI;EACF,OAAO,mBAAmB,KAAK,MAAM,CAAc,CAAC;CACtD,QAAQ;EACN,OAAO;CACT;AACF;AAEA,SAAS,gBAA+B;CACtC,IAAI,OAAO,aAAa,aACtB,OAAO;CAGT,OAAO,SAAS,gBAAgB,QAAQ;AAC1C;AAEA,SAAS,iBAAyB;CAChC,OAAO,UAAU,YAAY,KAAK,YAAY,KAAK,cAAc,KAAK,QAAQ;AAChF;AAEA,SAAS,QAAQ,QAAsB;CACrC,IAAI,OAAO,aAAa,aAAa;EACnC,SAAS,SAAS,GAAG,IAAI,GAAG,mBAAmB,MAAM,EAAE,kBAAkB,OAAO;EAChF,SAAS,gBAAgB,OAAO;CAClC;CAEA,IAAI,OAAO,WAAW,aACpB,IAAI;EACF,aAAa,QAAQ,KAAK,MAAM;CAClC,QAAQ;EACN;CACF;AAEJ;AAEA,SAAS,WAAmB;CAC1B,WAAW,eAAe;CAE1B,OAAO;AACT;AAEA,SAAS,SAAS,QAAsB;CACtC,IAAI,OAAO,WAAW,aACpB;CAGF,OAAO,cAAc,IAAI,YAAY,cAAc,cAAc,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC;AAC1F;AAEA,SAAgB,gBAAwB;CACtC,OAAO,SAAS;AAClB;AAEA,SAAgB,eAAuC;CACrD,OAAO,EAAE,mBAAmB,cAAc,EAAE;AAC9C;AAEA,SAAgB,gBAAgB,UAAgD;CAC9E,OAAO,gBAAgB,SAAS,cAAc,CAAC,CAAC;AAClD;AAEA,SAAgB,UAAU,QAAsB;CAC9C,MAAM,WAAW,cAAc;CAC/B,MAAM,OAAO,UAAU,MAAM;CAE7B,SAAS;CACT,QAAQ,IAAI;CAEZ,IAAI,SAAS,UACX;CAGF,OAAO;CACP,SAAS,IAAI;AACf;AAEA,SAAgB,YAA6B;CAG3C,OAAO;EAAE,QAFM,qBAAqB,WAAW,gBAAgB,QAEtD;EAAQ;CAAU;AAC7B"}
@@ -1,9 +1,10 @@
1
+ import { createListeners } from "../lib/listeners.js";
1
2
  import { LATTICE_EVENT } from "../core/event-names.js";
2
3
  import { configTimezone, subscribeConfig } from "./config.js";
3
4
  import { useSyncExternalStore } from "react";
4
5
  //#region resources/js/i18n/timezone.ts
5
6
  var fallback = "UTC";
6
- var listeners = /* @__PURE__ */ new Set();
7
+ var { subscribe, notify } = createListeners();
7
8
  var override;
8
9
  function detectedTimezone() {
9
10
  if (typeof Intl === "undefined") return fallback;
@@ -16,15 +17,6 @@ function detectedTimezone() {
16
17
  function snapshot() {
17
18
  return override ?? configTimezone() ?? detectedTimezone();
18
19
  }
19
- function subscribe(callback) {
20
- listeners.add(callback);
21
- return () => {
22
- listeners.delete(callback);
23
- };
24
- }
25
- function notify() {
26
- listeners.forEach((listener) => listener());
27
- }
28
20
  subscribeConfig(() => notify());
29
21
  function dispatch(timezone) {
30
22
  if (typeof window === "undefined") return;
@@ -1 +1 @@
1
- {"version":3,"file":"timezone.js","names":[],"sources":["../../resources/js/i18n/timezone.ts"],"sourcesContent":["import { useSyncExternalStore } from \"react\";\nimport { LATTICE_EVENT } from \"@lattice-php/lattice/core/event-names\";\nimport { configTimezone, subscribeConfig } from \"./config\";\n\nexport type UseTimezoneReturn = {\n readonly timezone: string;\n readonly setTimezone: (timezone: string) => void;\n};\n\nconst fallback = \"UTC\";\nconst listeners = new Set<() => void>();\n\nlet override: string | undefined;\n\nfunction detectedTimezone(): string {\n if (typeof Intl === \"undefined\") {\n return fallback;\n }\n\n try {\n return Intl.DateTimeFormat().resolvedOptions().timeZone || fallback;\n } catch {\n return fallback;\n }\n}\n\nfunction snapshot(): string {\n return override ?? configTimezone() ?? detectedTimezone();\n}\n\nfunction subscribe(callback: () => void): () => void {\n listeners.add(callback);\n\n return () => {\n listeners.delete(callback);\n };\n}\n\nfunction notify(): void {\n listeners.forEach((listener) => listener());\n}\n\nsubscribeConfig(() => notify());\n\nfunction dispatch(timezone: string): void {\n if (typeof window === \"undefined\") {\n return;\n }\n\n window.dispatchEvent(new CustomEvent(LATTICE_EVENT.timezoneChange, { detail: { timezone } }));\n}\n\nexport function currentTimezone(): string {\n return snapshot();\n}\n\nexport function setTimezone(timezone: string): void {\n const previous = currentTimezone();\n const next = timezone.trim();\n\n override = next === \"\" ? undefined : next;\n\n if (currentTimezone() === previous) {\n return;\n }\n\n notify();\n dispatch(currentTimezone());\n}\n\nexport function useTimezone(): UseTimezoneReturn {\n const timezone = useSyncExternalStore(subscribe, snapshot, () => fallback);\n\n return { timezone, setTimezone } as const;\n}\n"],"mappings":";;;;AASA,IAAM,WAAW;AACjB,IAAM,4BAAY,IAAI,IAAgB;AAEtC,IAAI;AAEJ,SAAS,mBAA2B;CAClC,IAAI,OAAO,SAAS,aAClB,OAAO;CAGT,IAAI;EACF,OAAO,KAAK,eAAe,CAAC,CAAC,gBAAgB,CAAC,CAAC,YAAY;CAC7D,QAAQ;EACN,OAAO;CACT;AACF;AAEA,SAAS,WAAmB;CAC1B,OAAO,YAAY,eAAe,KAAK,iBAAiB;AAC1D;AAEA,SAAS,UAAU,UAAkC;CACnD,UAAU,IAAI,QAAQ;CAEtB,aAAa;EACX,UAAU,OAAO,QAAQ;CAC3B;AACF;AAEA,SAAS,SAAe;CACtB,UAAU,SAAS,aAAa,SAAS,CAAC;AAC5C;AAEA,sBAAsB,OAAO,CAAC;AAE9B,SAAS,SAAS,UAAwB;CACxC,IAAI,OAAO,WAAW,aACpB;CAGF,OAAO,cAAc,IAAI,YAAY,cAAc,gBAAgB,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC,CAAC;AAC9F;AAEA,SAAgB,kBAA0B;CACxC,OAAO,SAAS;AAClB;AAEA,SAAgB,YAAY,UAAwB;CAClD,MAAM,WAAW,gBAAgB;CACjC,MAAM,OAAO,SAAS,KAAK;CAE3B,WAAW,SAAS,KAAK,KAAA,IAAY;CAErC,IAAI,gBAAgB,MAAM,UACxB;CAGF,OAAO;CACP,SAAS,gBAAgB,CAAC;AAC5B;AAEA,SAAgB,cAAiC;CAG/C,OAAO;EAAE,UAFQ,qBAAqB,WAAW,gBAAgB,QAExD;EAAU;CAAY;AACjC"}
1
+ {"version":3,"file":"timezone.js","names":[],"sources":["../../resources/js/i18n/timezone.ts"],"sourcesContent":["import { useSyncExternalStore } from \"react\";\nimport { LATTICE_EVENT } from \"@lattice-php/lattice/core/event-names\";\nimport { createListeners } from \"@lattice-php/lattice/lib/listeners\";\nimport { configTimezone, subscribeConfig } from \"./config\";\n\nexport type UseTimezoneReturn = {\n readonly timezone: string;\n readonly setTimezone: (timezone: string) => void;\n};\n\nconst fallback = \"UTC\";\nconst { subscribe, notify } = createListeners();\n\nlet override: string | undefined;\n\nfunction detectedTimezone(): string {\n if (typeof Intl === \"undefined\") {\n return fallback;\n }\n\n try {\n return Intl.DateTimeFormat().resolvedOptions().timeZone || fallback;\n } catch {\n return fallback;\n }\n}\n\nfunction snapshot(): string {\n return override ?? configTimezone() ?? detectedTimezone();\n}\n\nsubscribeConfig(() => notify());\n\nfunction dispatch(timezone: string): void {\n if (typeof window === \"undefined\") {\n return;\n }\n\n window.dispatchEvent(new CustomEvent(LATTICE_EVENT.timezoneChange, { detail: { timezone } }));\n}\n\nexport function currentTimezone(): string {\n return snapshot();\n}\n\nexport function setTimezone(timezone: string): void {\n const previous = currentTimezone();\n const next = timezone.trim();\n\n override = next === \"\" ? undefined : next;\n\n if (currentTimezone() === previous) {\n return;\n }\n\n notify();\n dispatch(currentTimezone());\n}\n\nexport function useTimezone(): UseTimezoneReturn {\n const timezone = useSyncExternalStore(subscribe, snapshot, () => fallback);\n\n return { timezone, setTimezone } as const;\n}\n"],"mappings":";;;;;AAUA,IAAM,WAAW;AACjB,IAAM,EAAE,WAAW,WAAW,gBAAgB;AAE9C,IAAI;AAEJ,SAAS,mBAA2B;CAClC,IAAI,OAAO,SAAS,aAClB,OAAO;CAGT,IAAI;EACF,OAAO,KAAK,eAAe,CAAC,CAAC,gBAAgB,CAAC,CAAC,YAAY;CAC7D,QAAQ;EACN,OAAO;CACT;AACF;AAEA,SAAS,WAAmB;CAC1B,OAAO,YAAY,eAAe,KAAK,iBAAiB;AAC1D;AAEA,sBAAsB,OAAO,CAAC;AAE9B,SAAS,SAAS,UAAwB;CACxC,IAAI,OAAO,WAAW,aACpB;CAGF,OAAO,cAAc,IAAI,YAAY,cAAc,gBAAgB,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC,CAAC;AAC9F;AAEA,SAAgB,kBAA0B;CACxC,OAAO,SAAS;AAClB;AAEA,SAAgB,YAAY,UAAwB;CAClD,MAAM,WAAW,gBAAgB;CACjC,MAAM,OAAO,SAAS,KAAK;CAE3B,WAAW,SAAS,KAAK,KAAA,IAAY;CAErC,IAAI,gBAAgB,MAAM,UACxB;CAGF,OAAO;CACP,SAAS,gBAAgB,CAAC;AAC5B;AAEA,SAAgB,cAAiC;CAG/C,OAAO;EAAE,UAFQ,qBAAqB,WAAW,gBAAgB,QAExD;EAAU;CAAY;AACjC"}
@@ -6,9 +6,8 @@ export type IconRendererProps = {
6
6
  export type IconRendererFunction = (props: IconRendererProps) => ReactNode;
7
7
  type IconRendererProviderProps = {
8
8
  children: ReactNode;
9
- mode?: "replace" | "stack";
10
9
  renderer: IconRendererFunction;
11
10
  };
12
- export declare function IconRendererProvider({ children, mode, renderer, }: IconRendererProviderProps): import("react").JSX.Element;
11
+ export declare function IconRendererProvider({ children, renderer }: IconRendererProviderProps): import("react").JSX.Element;
13
12
  export declare function IconRenderer({ className, icon }: IconRendererProps): string | number | bigint | true | Iterable<ReactNode> | Promise<string | number | bigint | boolean | import('react').ReactPortal | import('react').ReactElement<unknown, string | import('react').JSXElementConstructor<any>> | Iterable<ReactNode> | null | undefined> | import("react").JSX.Element;
14
13
  export {};
@@ -4,13 +4,9 @@ import { createContext, useContext, useMemo } from "react";
4
4
  import { jsx, jsxs } from "react/jsx-runtime";
5
5
  //#region resources/js/icons/icon-renderer.tsx
6
6
  var IconRenderersContext = createContext([]);
7
- function IconRendererProvider({ children, mode = "stack", renderer }) {
7
+ function IconRendererProvider({ children, renderer }) {
8
8
  const parentRenderers = useContext(IconRenderersContext);
9
- const renderers = useMemo(() => mode === "replace" ? [renderer] : [renderer, ...parentRenderers], [
10
- mode,
11
- parentRenderers,
12
- renderer
13
- ]);
9
+ const renderers = useMemo(() => [renderer, ...parentRenderers], [parentRenderers, renderer]);
14
10
  return /* @__PURE__ */ jsx(IconRenderersContext.Provider, {
15
11
  value: renderers,
16
12
  children
@@ -1 +1 @@
1
- {"version":3,"file":"icon-renderer.js","names":[],"sources":["../../resources/js/icons/icon-renderer.tsx"],"sourcesContent":["import { createContext, useContext, useMemo } from \"react\";\nimport type { ReactNode } from \"react\";\nimport { cn } from \"@lattice-php/lattice/lib/utils\";\nimport { Icon, useSprite } from \"./sprite\";\n\nexport type IconRendererProps = {\n className?: string;\n icon: string;\n};\n\nexport type IconRendererFunction = (props: IconRendererProps) => ReactNode;\n\ntype IconRendererProviderProps = {\n children: ReactNode;\n mode?: \"replace\" | \"stack\";\n renderer: IconRendererFunction;\n};\n\nconst IconRenderersContext = createContext<IconRendererFunction[]>([]);\nconst loggedMissingIcons = new Set<string>();\n\nexport function IconRendererProvider({\n children,\n mode = \"stack\",\n renderer,\n}: IconRendererProviderProps) {\n const parentRenderers = useContext(IconRenderersContext);\n const renderers = useMemo(\n () => (mode === \"replace\" ? [renderer] : [renderer, ...parentRenderers]),\n [mode, parentRenderers, renderer],\n );\n\n return (\n <IconRenderersContext.Provider value={renderers}>{children}</IconRenderersContext.Provider>\n );\n}\n\nexport function IconRenderer({ className, icon }: IconRendererProps) {\n const renderers = useContext(IconRenderersContext);\n const { ids } = useSprite();\n\n for (const renderer of renderers) {\n const rendered = renderer({ className, icon });\n\n if (rendered !== null && rendered !== undefined && rendered !== false) {\n return rendered;\n }\n }\n\n // When the sprite is wired and the icon is genuinely absent, show a visible\n // marker. When `ids` is unknown (not yet wired), optimistically emit the\n // sprite reference rather than crying wolf.\n if (ids && !ids.includes(icon)) {\n logMissingIcon(icon);\n return <MissingIcon className={className} />;\n }\n\n return <Icon className={className} name={icon} />;\n}\n\nfunction MissingIcon({ className }: { className?: string }) {\n return (\n <svg\n aria-hidden=\"true\"\n className={cn(\"size-lt-icon-md text-lt-muted-fg\", className)}\n data-lattice-missing-icon=\"\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth=\"2\"\n viewBox=\"0 0 24 24\"\n >\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n <path d=\"M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3\" />\n <path d=\"M12 17h.01\" />\n </svg>\n );\n}\n\nfunction logMissingIcon(icon: string): void {\n if (!import.meta.env.DEV || loggedMissingIcons.has(icon)) {\n return;\n }\n\n loggedMissingIcons.add(icon);\n console.log(`[Lattice] Missing icon renderer for \"${icon}\".`);\n}\n"],"mappings":";;;;;AAkBA,IAAM,uBAAuB,cAAsC,CAAC,CAAC;AAGrE,SAAgB,qBAAqB,EACnC,UACA,OAAO,SACP,YAC4B;CAC5B,MAAM,kBAAkB,WAAW,oBAAoB;CACvD,MAAM,YAAY,cACT,SAAS,YAAY,CAAC,QAAQ,IAAI,CAAC,UAAU,GAAG,eAAe,GACtE;EAAC;EAAM;EAAiB;CAAQ,CAClC;CAEA,OACE,oBAAC,qBAAqB,UAAtB;EAA+B,OAAO;EAAY;CAAwC,CAAA;AAE9F;AAEA,SAAgB,aAAa,EAAE,WAAW,QAA2B;CACnE,MAAM,YAAY,WAAW,oBAAoB;CACjD,MAAM,EAAE,QAAQ,UAAU;CAE1B,KAAK,MAAM,YAAY,WAAW;EAChC,MAAM,WAAW,SAAS;GAAE;GAAW;EAAK,CAAC;EAE7C,IAAI,aAAa,QAAQ,aAAa,KAAA,KAAa,aAAa,OAC9D,OAAO;CAEX;CAKA,IAAI,OAAO,CAAC,IAAI,SAAS,IAAI,GAE3B,OAAO,oBAAC,aAAD,EAAwB,UAAY,CAAA;CAG7C,OAAO,oBAAC,MAAD;EAAiB;EAAW,MAAM;CAAO,CAAA;AAClD;AAEA,SAAS,YAAY,EAAE,aAAqC;CAC1D,OACE,qBAAC,OAAD;EACE,eAAY;EACZ,WAAW,GAAG,oCAAoC,SAAS;EAC3D,6BAA0B;EAC1B,MAAK;EACL,QAAO;EACP,eAAc;EACd,gBAAe;EACf,aAAY;EACZ,SAAQ;EATV,UAAA;GAWE,oBAAC,UAAD;IAAQ,IAAG;IAAK,IAAG;IAAK,GAAE;GAAM,CAAA;GAChC,oBAAC,QAAD,EAAM,GAAE,uCAAwC,CAAA;GAChD,oBAAC,QAAD,EAAM,GAAE,aAAc,CAAA;EACnB;;AAET"}
1
+ {"version":3,"file":"icon-renderer.js","names":[],"sources":["../../resources/js/icons/icon-renderer.tsx"],"sourcesContent":["import { createContext, useContext, useMemo } from \"react\";\nimport type { ReactNode } from \"react\";\nimport { cn } from \"@lattice-php/lattice/lib/utils\";\nimport { Icon, useSprite } from \"./sprite\";\n\nexport type IconRendererProps = {\n className?: string;\n icon: string;\n};\n\nexport type IconRendererFunction = (props: IconRendererProps) => ReactNode;\n\ntype IconRendererProviderProps = {\n children: ReactNode;\n renderer: IconRendererFunction;\n};\n\nconst IconRenderersContext = createContext<IconRendererFunction[]>([]);\nconst loggedMissingIcons = new Set<string>();\n\nexport function IconRendererProvider({ children, renderer }: IconRendererProviderProps) {\n const parentRenderers = useContext(IconRenderersContext);\n const renderers = useMemo(() => [renderer, ...parentRenderers], [parentRenderers, renderer]);\n\n return (\n <IconRenderersContext.Provider value={renderers}>{children}</IconRenderersContext.Provider>\n );\n}\n\nexport function IconRenderer({ className, icon }: IconRendererProps) {\n const renderers = useContext(IconRenderersContext);\n const { ids } = useSprite();\n\n for (const renderer of renderers) {\n const rendered = renderer({ className, icon });\n\n if (rendered !== null && rendered !== undefined && rendered !== false) {\n return rendered;\n }\n }\n\n // When the sprite is wired and the icon is genuinely absent, show a visible\n // marker. When `ids` is unknown (not yet wired), optimistically emit the\n // sprite reference rather than crying wolf.\n if (ids && !ids.includes(icon)) {\n logMissingIcon(icon);\n return <MissingIcon className={className} />;\n }\n\n return <Icon className={className} name={icon} />;\n}\n\nfunction MissingIcon({ className }: { className?: string }) {\n return (\n <svg\n aria-hidden=\"true\"\n className={cn(\"size-lt-icon-md text-lt-muted-fg\", className)}\n data-lattice-missing-icon=\"\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth=\"2\"\n viewBox=\"0 0 24 24\"\n >\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n <path d=\"M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3\" />\n <path d=\"M12 17h.01\" />\n </svg>\n );\n}\n\nfunction logMissingIcon(icon: string): void {\n if (!import.meta.env.DEV || loggedMissingIcons.has(icon)) {\n return;\n }\n\n loggedMissingIcons.add(icon);\n console.log(`[Lattice] Missing icon renderer for \"${icon}\".`);\n}\n"],"mappings":";;;;;AAiBA,IAAM,uBAAuB,cAAsC,CAAC,CAAC;AAGrE,SAAgB,qBAAqB,EAAE,UAAU,YAAuC;CACtF,MAAM,kBAAkB,WAAW,oBAAoB;CACvD,MAAM,YAAY,cAAc,CAAC,UAAU,GAAG,eAAe,GAAG,CAAC,iBAAiB,QAAQ,CAAC;CAE3F,OACE,oBAAC,qBAAqB,UAAtB;EAA+B,OAAO;EAAY;CAAwC,CAAA;AAE9F;AAEA,SAAgB,aAAa,EAAE,WAAW,QAA2B;CACnE,MAAM,YAAY,WAAW,oBAAoB;CACjD,MAAM,EAAE,QAAQ,UAAU;CAE1B,KAAK,MAAM,YAAY,WAAW;EAChC,MAAM,WAAW,SAAS;GAAE;GAAW;EAAK,CAAC;EAE7C,IAAI,aAAa,QAAQ,aAAa,KAAA,KAAa,aAAa,OAC9D,OAAO;CAEX;CAKA,IAAI,OAAO,CAAC,IAAI,SAAS,IAAI,GAE3B,OAAO,oBAAC,aAAD,EAAwB,UAAY,CAAA;CAG7C,OAAO,oBAAC,MAAD;EAAiB;EAAW,MAAM;CAAO,CAAA;AAClD;AAEA,SAAS,YAAY,EAAE,aAAqC;CAC1D,OACE,qBAAC,OAAD;EACE,eAAY;EACZ,WAAW,GAAG,oCAAoC,SAAS;EAC3D,6BAA0B;EAC1B,MAAK;EACL,QAAO;EACP,eAAc;EACd,gBAAe;EACf,aAAY;EACZ,SAAQ;EATV,UAAA;GAWE,oBAAC,UAAD;IAAQ,IAAG;IAAK,IAAG;IAAK,GAAE;GAAM,CAAA;GAChC,oBAAC,QAAD,EAAM,GAAE,uCAAwC,CAAA;GAChD,oBAAC,QAAD,EAAM,GAAE,aAAc,CAAA;EACnB;;AAET"}
@@ -0,0 +1,5 @@
1
+ export type Listeners = {
2
+ subscribe: (callback: () => void) => () => void;
3
+ notify: () => void;
4
+ };
5
+ export declare function createListeners(): Listeners;
@@ -0,0 +1,19 @@
1
+ //#region resources/js/lib/listeners.ts
2
+ function createListeners() {
3
+ const listeners = /* @__PURE__ */ new Set();
4
+ return {
5
+ subscribe(callback) {
6
+ listeners.add(callback);
7
+ return () => {
8
+ listeners.delete(callback);
9
+ };
10
+ },
11
+ notify() {
12
+ listeners.forEach((listener) => listener());
13
+ }
14
+ };
15
+ }
16
+ //#endregion
17
+ export { createListeners };
18
+
19
+ //# sourceMappingURL=listeners.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"listeners.js","names":[],"sources":["../../resources/js/lib/listeners.ts"],"sourcesContent":["export type Listeners = {\n subscribe: (callback: () => void) => () => void;\n notify: () => void;\n};\n\nexport function createListeners(): Listeners {\n const listeners = new Set<() => void>();\n\n return {\n subscribe(callback) {\n listeners.add(callback);\n\n return () => {\n listeners.delete(callback);\n };\n },\n notify() {\n listeners.forEach((listener) => listener());\n },\n };\n}\n"],"mappings":";AAKA,SAAgB,kBAA6B;CAC3C,MAAM,4BAAY,IAAI,IAAgB;CAEtC,OAAO;EACL,UAAU,UAAU;GAClB,UAAU,IAAI,QAAQ;GAEtB,aAAa;IACX,UAAU,OAAO,QAAQ;GAC3B;EACF;EACA,SAAS;GACP,UAAU,SAAS,aAAa,SAAS,CAAC;EAC5C;CACF;AACF"}
@@ -39,22 +39,14 @@ function pickKnownBooleans(source, toggleableKeys) {
39
39
  return result;
40
40
  }
41
41
  function parseStoredVisibility(raw, toggleableKeys) {
42
- const stored = JSON.parse(raw);
43
- if (!isStoredColumnVisibility(stored)) throw new Error("unexpected stored column visibility shape");
44
- return pickKnownBooleans(stored.overrides, toggleableKeys);
42
+ const overrides = JSON.parse(raw)?.overrides;
43
+ if (typeof overrides !== "object" || overrides === null || Array.isArray(overrides)) throw new Error("unexpected stored column visibility shape");
44
+ return pickKnownBooleans(overrides, toggleableKeys);
45
45
  }
46
46
  function serializeVisibility(overrides, toggleableKeys) {
47
47
  const stored = pickKnownBooleans(overrides, toggleableKeys);
48
48
  if (Object.keys(stored).length === 0) return null;
49
- return JSON.stringify({
50
- columns: toggleableKeys,
51
- overrides: stored
52
- });
53
- }
54
- function isStoredColumnVisibility(value) {
55
- if (typeof value !== "object" || value === null) return false;
56
- const record = value;
57
- return Array.isArray(record.columns) && record.columns.every((column) => typeof column === "string") && typeof record.overrides === "object" && record.overrides !== null && !Array.isArray(record.overrides);
49
+ return JSON.stringify({ overrides: stored });
58
50
  }
59
51
  //#endregion
60
52
  export { useColumnVisibility };
@@ -1 +1 @@
1
- {"version":3,"file":"use-column-visibility.js","names":[],"sources":["../../../resources/js/table/hooks/use-column-visibility.ts"],"sourcesContent":["import { useCallback, useMemo } from \"react\";\nimport { usePersistentState } from \"@lattice-php/lattice/lib/use-persistent-state\";\n\nexport type ToggleableColumn = {\n key: string;\n props: {\n label?: string | null;\n toggleable?: boolean;\n hiddenByDefault?: boolean;\n };\n};\n\ntype StoredColumnVisibility = {\n columns: string[];\n overrides: Record<string, boolean>;\n};\n\nexport function useColumnVisibility<TColumn extends ToggleableColumn>({\n columns,\n storageKey,\n}: {\n columns: TColumn[];\n storageKey?: string;\n}) {\n const toggleableColumns = useMemo(\n () => columns.filter((column) => column.props.toggleable),\n [columns],\n );\n const toggleableKeys = useMemo(\n () => toggleableColumns.map((column) => column.key),\n [toggleableColumns],\n );\n\n const [overrides, setOverrides] = usePersistentState<Record<string, boolean>>(\n storageKey ?? \"\",\n {},\n {\n enabled: Boolean(storageKey),\n parse: (raw) => parseStoredVisibility(raw, toggleableKeys),\n serialize: (value) => serializeVisibility(value, toggleableKeys),\n },\n );\n\n const isVisible = useCallback(\n (column: ToggleableColumn): boolean => {\n if (!column.props.toggleable) {\n return true;\n }\n\n return overrides[column.key] ?? !column.props.hiddenByDefault;\n },\n [overrides],\n );\n\n const visibleColumns = useMemo(\n () => columns.filter((column) => isVisible(column)),\n [columns, isVisible],\n );\n\n const setColumnVisible = useCallback(\n (key: string, visible: boolean) => {\n setOverrides((current) => ({ ...current, [key]: visible }));\n },\n [setOverrides],\n );\n\n const resetVisibility = useCallback(() => setOverrides({}), [setOverrides]);\n\n const hasToggleableColumns = toggleableColumns.length > 0;\n const hasHidden = toggleableColumns.some((column) => !isVisible(column));\n\n return {\n hasHidden,\n hasToggleableColumns,\n isVisible,\n resetVisibility,\n setColumnVisible,\n toggleableColumns,\n visibleColumns,\n };\n}\n\nfunction pickKnownBooleans(\n source: Record<string, unknown>,\n toggleableKeys: string[],\n): Record<string, boolean> {\n const known = new Set(toggleableKeys);\n const result: Record<string, boolean> = {};\n\n for (const [key, value] of Object.entries(source)) {\n if (known.has(key) && typeof value === \"boolean\") {\n result[key] = value;\n }\n }\n\n return result;\n}\n\nfunction parseStoredVisibility(raw: string, toggleableKeys: string[]): Record<string, boolean> {\n const stored = JSON.parse(raw) as unknown;\n\n if (!isStoredColumnVisibility(stored)) {\n throw new Error(\"unexpected stored column visibility shape\");\n }\n\n return pickKnownBooleans(stored.overrides, toggleableKeys);\n}\n\nfunction serializeVisibility(\n overrides: Record<string, boolean>,\n toggleableKeys: string[],\n): string | null {\n const stored = pickKnownBooleans(overrides, toggleableKeys);\n\n if (Object.keys(stored).length === 0) {\n return null;\n }\n\n return JSON.stringify({ columns: toggleableKeys, overrides: stored });\n}\n\nfunction isStoredColumnVisibility(value: unknown): value is StoredColumnVisibility {\n if (typeof value !== \"object\" || value === null) {\n return false;\n }\n\n const record = value as Record<string, unknown>;\n\n return (\n Array.isArray(record.columns) &&\n record.columns.every((column) => typeof column === \"string\") &&\n typeof record.overrides === \"object\" &&\n record.overrides !== null &&\n !Array.isArray(record.overrides)\n );\n}\n"],"mappings":";;;AAiBA,SAAgB,oBAAsD,EACpE,SACA,cAIC;CACD,MAAM,oBAAoB,cAClB,QAAQ,QAAQ,WAAW,OAAO,MAAM,UAAU,GACxD,CAAC,OAAO,CACV;CACA,MAAM,iBAAiB,cACf,kBAAkB,KAAK,WAAW,OAAO,GAAG,GAClD,CAAC,iBAAiB,CACpB;CAEA,MAAM,CAAC,WAAW,gBAAgB,mBAChC,cAAc,IACd,CAAC,GACD;EACE,SAAS,QAAQ,UAAU;EAC3B,QAAQ,QAAQ,sBAAsB,KAAK,cAAc;EACzD,YAAY,UAAU,oBAAoB,OAAO,cAAc;CACjE,CACF;CAEA,MAAM,YAAY,aACf,WAAsC;EACrC,IAAI,CAAC,OAAO,MAAM,YAChB,OAAO;EAGT,OAAO,UAAU,OAAO,QAAQ,CAAC,OAAO,MAAM;CAChD,GACA,CAAC,SAAS,CACZ;CAEA,MAAM,iBAAiB,cACf,QAAQ,QAAQ,WAAW,UAAU,MAAM,CAAC,GAClD,CAAC,SAAS,SAAS,CACrB;CAEA,MAAM,mBAAmB,aACtB,KAAa,YAAqB;EACjC,cAAc,aAAa;GAAE,GAAG;IAAU,MAAM;EAAQ,EAAE;CAC5D,GACA,CAAC,YAAY,CACf;CAEA,MAAM,kBAAkB,kBAAkB,aAAa,CAAC,CAAC,GAAG,CAAC,YAAY,CAAC;CAE1E,MAAM,uBAAuB,kBAAkB,SAAS;CAGxD,OAAO;EACL,WAHgB,kBAAkB,MAAM,WAAW,CAAC,UAAU,MAAM,CAGpE;EACA;EACA;EACA;EACA;EACA;EACA;CACF;AACF;AAEA,SAAS,kBACP,QACA,gBACyB;CACzB,MAAM,QAAQ,IAAI,IAAI,cAAc;CACpC,MAAM,SAAkC,CAAC;CAEzC,KAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,MAAM,GAC9C,IAAI,MAAM,IAAI,GAAG,KAAK,OAAO,UAAU,WACrC,OAAO,OAAO;CAIlB,OAAO;AACT;AAEA,SAAS,sBAAsB,KAAa,gBAAmD;CAC7F,MAAM,SAAS,KAAK,MAAM,GAAG;CAE7B,IAAI,CAAC,yBAAyB,MAAM,GAClC,MAAM,IAAI,MAAM,2CAA2C;CAG7D,OAAO,kBAAkB,OAAO,WAAW,cAAc;AAC3D;AAEA,SAAS,oBACP,WACA,gBACe;CACf,MAAM,SAAS,kBAAkB,WAAW,cAAc;CAE1D,IAAI,OAAO,KAAK,MAAM,CAAC,CAAC,WAAW,GACjC,OAAO;CAGT,OAAO,KAAK,UAAU;EAAE,SAAS;EAAgB,WAAW;CAAO,CAAC;AACtE;AAEA,SAAS,yBAAyB,OAAiD;CACjF,IAAI,OAAO,UAAU,YAAY,UAAU,MACzC,OAAO;CAGT,MAAM,SAAS;CAEf,OACE,MAAM,QAAQ,OAAO,OAAO,KAC5B,OAAO,QAAQ,OAAO,WAAW,OAAO,WAAW,QAAQ,KAC3D,OAAO,OAAO,cAAc,YAC5B,OAAO,cAAc,QACrB,CAAC,MAAM,QAAQ,OAAO,SAAS;AAEnC"}
1
+ {"version":3,"file":"use-column-visibility.js","names":[],"sources":["../../../resources/js/table/hooks/use-column-visibility.ts"],"sourcesContent":["import { useCallback, useMemo } from \"react\";\nimport { usePersistentState } from \"@lattice-php/lattice/lib/use-persistent-state\";\n\nexport type ToggleableColumn = {\n key: string;\n props: {\n label?: string | null;\n toggleable?: boolean;\n hiddenByDefault?: boolean;\n };\n};\n\nexport function useColumnVisibility<TColumn extends ToggleableColumn>({\n columns,\n storageKey,\n}: {\n columns: TColumn[];\n storageKey?: string;\n}) {\n const toggleableColumns = useMemo(\n () => columns.filter((column) => column.props.toggleable),\n [columns],\n );\n const toggleableKeys = useMemo(\n () => toggleableColumns.map((column) => column.key),\n [toggleableColumns],\n );\n\n const [overrides, setOverrides] = usePersistentState<Record<string, boolean>>(\n storageKey ?? \"\",\n {},\n {\n enabled: Boolean(storageKey),\n parse: (raw) => parseStoredVisibility(raw, toggleableKeys),\n serialize: (value) => serializeVisibility(value, toggleableKeys),\n },\n );\n\n const isVisible = useCallback(\n (column: ToggleableColumn): boolean => {\n if (!column.props.toggleable) {\n return true;\n }\n\n return overrides[column.key] ?? !column.props.hiddenByDefault;\n },\n [overrides],\n );\n\n const visibleColumns = useMemo(\n () => columns.filter((column) => isVisible(column)),\n [columns, isVisible],\n );\n\n const setColumnVisible = useCallback(\n (key: string, visible: boolean) => {\n setOverrides((current) => ({ ...current, [key]: visible }));\n },\n [setOverrides],\n );\n\n const resetVisibility = useCallback(() => setOverrides({}), [setOverrides]);\n\n const hasToggleableColumns = toggleableColumns.length > 0;\n const hasHidden = toggleableColumns.some((column) => !isVisible(column));\n\n return {\n hasHidden,\n hasToggleableColumns,\n isVisible,\n resetVisibility,\n setColumnVisible,\n toggleableColumns,\n visibleColumns,\n };\n}\n\nfunction pickKnownBooleans(\n source: Record<string, unknown>,\n toggleableKeys: string[],\n): Record<string, boolean> {\n const known = new Set(toggleableKeys);\n const result: Record<string, boolean> = {};\n\n for (const [key, value] of Object.entries(source)) {\n if (known.has(key) && typeof value === \"boolean\") {\n result[key] = value;\n }\n }\n\n return result;\n}\n\nfunction parseStoredVisibility(raw: string, toggleableKeys: string[]): Record<string, boolean> {\n const stored = JSON.parse(raw) as { overrides?: unknown };\n const overrides = stored?.overrides;\n\n if (typeof overrides !== \"object\" || overrides === null || Array.isArray(overrides)) {\n throw new Error(\"unexpected stored column visibility shape\");\n }\n\n return pickKnownBooleans(overrides as Record<string, unknown>, toggleableKeys);\n}\n\nfunction serializeVisibility(\n overrides: Record<string, boolean>,\n toggleableKeys: string[],\n): string | null {\n const stored = pickKnownBooleans(overrides, toggleableKeys);\n\n if (Object.keys(stored).length === 0) {\n return null;\n }\n\n return JSON.stringify({ overrides: stored });\n}\n"],"mappings":";;;AAYA,SAAgB,oBAAsD,EACpE,SACA,cAIC;CACD,MAAM,oBAAoB,cAClB,QAAQ,QAAQ,WAAW,OAAO,MAAM,UAAU,GACxD,CAAC,OAAO,CACV;CACA,MAAM,iBAAiB,cACf,kBAAkB,KAAK,WAAW,OAAO,GAAG,GAClD,CAAC,iBAAiB,CACpB;CAEA,MAAM,CAAC,WAAW,gBAAgB,mBAChC,cAAc,IACd,CAAC,GACD;EACE,SAAS,QAAQ,UAAU;EAC3B,QAAQ,QAAQ,sBAAsB,KAAK,cAAc;EACzD,YAAY,UAAU,oBAAoB,OAAO,cAAc;CACjE,CACF;CAEA,MAAM,YAAY,aACf,WAAsC;EACrC,IAAI,CAAC,OAAO,MAAM,YAChB,OAAO;EAGT,OAAO,UAAU,OAAO,QAAQ,CAAC,OAAO,MAAM;CAChD,GACA,CAAC,SAAS,CACZ;CAEA,MAAM,iBAAiB,cACf,QAAQ,QAAQ,WAAW,UAAU,MAAM,CAAC,GAClD,CAAC,SAAS,SAAS,CACrB;CAEA,MAAM,mBAAmB,aACtB,KAAa,YAAqB;EACjC,cAAc,aAAa;GAAE,GAAG;IAAU,MAAM;EAAQ,EAAE;CAC5D,GACA,CAAC,YAAY,CACf;CAEA,MAAM,kBAAkB,kBAAkB,aAAa,CAAC,CAAC,GAAG,CAAC,YAAY,CAAC;CAE1E,MAAM,uBAAuB,kBAAkB,SAAS;CAGxD,OAAO;EACL,WAHgB,kBAAkB,MAAM,WAAW,CAAC,UAAU,MAAM,CAGpE;EACA;EACA;EACA;EACA;EACA;EACA;CACF;AACF;AAEA,SAAS,kBACP,QACA,gBACyB;CACzB,MAAM,QAAQ,IAAI,IAAI,cAAc;CACpC,MAAM,SAAkC,CAAC;CAEzC,KAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,MAAM,GAC9C,IAAI,MAAM,IAAI,GAAG,KAAK,OAAO,UAAU,WACrC,OAAO,OAAO;CAIlB,OAAO;AACT;AAEA,SAAS,sBAAsB,KAAa,gBAAmD;CAE7F,MAAM,YADS,KAAK,MAAM,GACR,CAAA,EAAQ;CAE1B,IAAI,OAAO,cAAc,YAAY,cAAc,QAAQ,MAAM,QAAQ,SAAS,GAChF,MAAM,IAAI,MAAM,2CAA2C;CAG7D,OAAO,kBAAkB,WAAsC,cAAc;AAC/E;AAEA,SAAS,oBACP,WACA,gBACe;CACf,MAAM,SAAS,kBAAkB,WAAW,cAAc;CAE1D,IAAI,OAAO,KAAK,MAAM,CAAC,CAAC,WAAW,GACjC,OAAO;CAGT,OAAO,KAAK,UAAU,EAAE,WAAW,OAAO,CAAC;AAC7C"}
@@ -1,13 +1,12 @@
1
1
  import { LATTICE_EVENT } from "../core/event-names.js";
2
2
  import { isTranslatable } from "../i18n/translatable.js";
3
- import { isVariant } from "./toast.js";
3
+ import { coerceMessage, isVariant, subscribeWindowEvent } from "./toast.js";
4
4
  //#region resources/js/toast/callout.ts
5
5
  function normalizeCallout(detail) {
6
6
  if (typeof detail !== "object" || detail === null) return null;
7
7
  const callout = detail;
8
- const rawMessage = callout.message;
9
- const message = typeof rawMessage === "string" ? rawMessage : isTranslatable(rawMessage) ? rawMessage : null;
10
- if (message === null || message === "") return null;
8
+ const message = coerceMessage(callout.message);
9
+ if (message === null) return null;
11
10
  return {
12
11
  action: callout.action ?? null,
13
12
  dismissible: callout.dismissible !== false,
@@ -18,20 +17,13 @@ function normalizeCallout(detail) {
18
17
  };
19
18
  }
20
19
  function onCallout(callback) {
21
- const listener = (event) => {
22
- const callout = normalizeCallout(event.detail);
23
- if (callout) callback(callout);
24
- };
25
- window.addEventListener(LATTICE_EVENT.callout, listener);
26
- return () => window.removeEventListener(LATTICE_EVENT.callout, listener);
20
+ return subscribeWindowEvent(LATTICE_EVENT.callout, normalizeCallout, callback);
27
21
  }
28
22
  function onRetractCallout(callback) {
29
- const listener = (event) => {
30
- const unique = event.detail?.unique;
31
- if (typeof unique === "string") callback(unique);
32
- };
33
- window.addEventListener(LATTICE_EVENT.retractCallout, listener);
34
- return () => window.removeEventListener(LATTICE_EVENT.retractCallout, listener);
23
+ return subscribeWindowEvent(LATTICE_EVENT.retractCallout, (detail) => {
24
+ const unique = detail?.unique;
25
+ return typeof unique === "string" ? unique : null;
26
+ }, callback);
35
27
  }
36
28
  //#endregion
37
29
  export { normalizeCallout, onCallout, onRetractCallout };