@lattice-php/lattice 0.32.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 (97) hide show
  1. package/dist/appearance/index.d.ts +6 -0
  2. package/dist/appearance/index.js +13 -8
  3. package/dist/appearance/index.js.map +1 -1
  4. package/dist/chat/lib/transport.d.ts +2 -2
  5. package/dist/chat/lib/transport.js +22 -23
  6. package/dist/chat/lib/transport.js.map +1 -1
  7. package/dist/core/api.d.ts +0 -1
  8. package/dist/core/api.js +2 -2
  9. package/dist/core/api.js.map +1 -1
  10. package/dist/core/hooks/column-sizing.d.ts +1 -1
  11. package/dist/core/hooks/column-sizing.js +7 -14
  12. package/dist/core/hooks/column-sizing.js.map +1 -1
  13. package/dist/core/hooks/use-column-resizing.js +22 -54
  14. package/dist/core/hooks/use-column-resizing.js.map +1 -1
  15. package/dist/core/index.d.ts +1 -1
  16. package/dist/core/index.js +2 -2
  17. package/dist/core/registry.d.ts +1 -5
  18. package/dist/core/registry.js +1 -2
  19. package/dist/core/registry.js.map +1 -1
  20. package/dist/core/renderer.js +4 -10
  21. package/dist/core/renderer.js.map +1 -1
  22. package/dist/create-app.d.ts +6 -3
  23. package/dist/create-app.js +13 -5
  24. package/dist/create-app.js.map +1 -1
  25. package/dist/effects/registry.js +1 -4
  26. package/dist/effects/registry.js.map +1 -1
  27. package/dist/event-bridge.d.ts +1 -4
  28. package/dist/event-bridge.js +1 -11
  29. package/dist/event-bridge.js.map +1 -1
  30. package/dist/form/components/fields/choice.js +1 -1
  31. package/dist/form/components/fields/choice.js.map +1 -1
  32. package/dist/form/components/fields/use-flip-reorder.js +3 -2
  33. package/dist/form/components/fields/use-flip-reorder.js.map +1 -1
  34. package/dist/form/components/fields/use-row-collection.js +3 -2
  35. package/dist/form/components/fields/use-row-collection.js.map +1 -1
  36. package/dist/form/hooks/use-form-resolver.js +3 -2
  37. package/dist/form/hooks/use-form-resolver.js.map +1 -1
  38. package/dist/form/types.d.ts +1 -4
  39. package/dist/i18n/config.d.ts +1 -1
  40. package/dist/i18n/config.js +5 -21
  41. package/dist/i18n/config.js.map +1 -1
  42. package/dist/i18n/index.d.ts +2 -2
  43. package/dist/i18n/index.js +2 -2
  44. package/dist/i18n/instance.d.ts +8 -0
  45. package/dist/i18n/instance.js +17 -1
  46. package/dist/i18n/instance.js.map +1 -1
  47. package/dist/i18n/locale-switcher.d.ts +0 -5
  48. package/dist/i18n/locale-switcher.js +1 -5
  49. package/dist/i18n/locale-switcher.js.map +1 -1
  50. package/dist/i18n/locale.js +2 -10
  51. package/dist/i18n/locale.js.map +1 -1
  52. package/dist/i18n/timezone.js +2 -10
  53. package/dist/i18n/timezone.js.map +1 -1
  54. package/dist/icons/icon-renderer.d.ts +1 -2
  55. package/dist/icons/icon-renderer.js +2 -6
  56. package/dist/icons/icon-renderer.js.map +1 -1
  57. package/dist/lib/listeners.d.ts +5 -0
  58. package/dist/lib/listeners.js +19 -0
  59. package/dist/lib/listeners.js.map +1 -0
  60. package/dist/lib/use-layout-effect.d.ts +6 -0
  61. package/dist/lib/use-layout-effect.js +11 -0
  62. package/dist/lib/use-layout-effect.js.map +1 -0
  63. package/dist/ssr.d.ts +20 -0
  64. package/dist/ssr.js +32 -0
  65. package/dist/ssr.js.map +1 -0
  66. package/dist/table/hooks/use-column-visibility.js +4 -12
  67. package/dist/table/hooks/use-column-visibility.js.map +1 -1
  68. package/dist/toast/callout.js +8 -16
  69. package/dist/toast/callout.js.map +1 -1
  70. package/dist/toast/toast.d.ts +2 -0
  71. package/dist/toast/toast.js +16 -10
  72. package/dist/toast/toast.js.map +1 -1
  73. package/dist/ui/segmented-pills.d.ts +1 -1
  74. package/dist/ui/segmented-pills.js +1 -1
  75. package/dist/ui/segmented-pills.js.map +1 -1
  76. package/dist/vite.js +2 -5
  77. package/dist/vite.js.map +1 -1
  78. package/dist-standalone/chunks/{chart-view-WqyMTZiX.js → chart-view-CR1X2aGE.js} +1 -1
  79. package/dist-standalone/chunks/{date-picker-field-CCnkf4SC.js → date-picker-field-B4Xzow-A.js} +1 -1
  80. package/dist-standalone/chunks/{dist-CK9gk4iB.js → dist-ci5ng714.js} +1 -1
  81. package/dist-standalone/chunks/{icon-button-CEwL9uXW.js → icon-button-D3AltHNz.js} +1 -1
  82. package/dist-standalone/chunks/instance-C4O1XWa6.js +1 -0
  83. package/dist-standalone/chunks/locale-GyqtaX1O.js +1 -0
  84. package/dist-standalone/chunks/page-props-BHNNVkgJ.js +1 -0
  85. package/dist-standalone/chunks/{rich-editor-field-DVvEzA3W.js → rich-editor-field-JM3jBEV1.js} +1 -1
  86. package/dist-standalone/chunks/{subscriptions-HzwKFUPT.js → subscriptions-BV4g0s0U.js} +1 -1
  87. package/dist-standalone/chunks/{time-picker-DSs9fDWe.js → time-picker-kbhOHEPd.js} +1 -1
  88. package/dist-standalone/chunks/timezone-CyoBch3a.js +1 -0
  89. package/dist-standalone/chunks/{use-effect-dispatcher-CiWYRvsF.js → use-effect-dispatcher-CJXFkAv1.js} +2 -2
  90. package/dist-standalone/lattice.css +1 -1
  91. package/dist-standalone/lattice.js +4 -4
  92. package/dist-standalone/manifest.json +1 -27
  93. package/package.json +10 -2
  94. package/dist-standalone/chunks/instance-B-C4sgf4.js +0 -1
  95. package/dist-standalone/chunks/locale-CgtcxthU.js +0 -1
  96. package/dist-standalone/chunks/page-props-nxR5n6k4.js +0 -1
  97. package/dist-standalone/chunks/timezone-BORzyZp2.js +0 -1
@@ -7,6 +7,7 @@ import i18next from "i18next";
7
7
  var DEFAULT_NAMESPACE = "lattice";
8
8
  var i18n = i18next.createInstance();
9
9
  var initialization;
10
+ var hold;
10
11
  var revision = 0;
11
12
  function subscribe(onStoreChange) {
12
13
  const listener = () => {
@@ -30,11 +31,26 @@ function snapshot() {
30
31
  return revision;
31
32
  }
32
33
  /**
34
+ * Defer component-driven initialization until `until` settles — for shells
35
+ * that render before the i18n bootstrap has loaded (SSR hydration), where the
36
+ * first rendered `useT` would otherwise win the init race and lock the HTTP
37
+ * backend out. Configuring callers (those passing `extend` to {@link ensureI18n})
38
+ * bypass the hold; a failed bootstrap releases it, so init stays fail-open.
39
+ */
40
+ function holdI18nInit(until) {
41
+ const release = () => {
42
+ hold = void 0;
43
+ };
44
+ const released = until.then(release, release);
45
+ if (!initialization) hold = released;
46
+ }
47
+ /**
33
48
  * Initialize the instance exactly once. The first caller wins — a rendered
34
49
  * component (inline English, zero config) or `enableBackend()`, which registers
35
50
  * its backend first because i18next can only wire a backend during `init`.
36
51
  */
37
52
  function ensureI18n(extend) {
53
+ if (!initialization && hold && !extend) return hold.then(() => ensureI18n());
38
54
  if (!initialization) {
39
55
  const base = {
40
56
  lng: currentLocale(),
@@ -92,6 +108,6 @@ function translate(namespace, key, defaultValue, options) {
92
108
  });
93
109
  }
94
110
  //#endregion
95
- export { DEFAULT_NAMESPACE, ensureI18n, i18n, preloadLanguages, translate, useT };
111
+ export { DEFAULT_NAMESPACE, ensureI18n, holdI18nInit, i18n, preloadLanguages, translate, useT };
96
112
 
97
113
  //# sourceMappingURL=instance.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"instance.js","names":[],"sources":["../../resources/js/i18n/instance.ts"],"sourcesContent":["import i18next, { type i18n as I18nInstance, type InitOptions } from \"i18next\";\nimport { useCallback, useSyncExternalStore } from \"react\";\nimport { useConfig } from \"./config\";\nimport { registerDateTimeFormatter } from \"./date-time-formatter\";\nimport { currentLocale, subscribeLocale, useLocale } from \"./locale\";\n\nexport const DEFAULT_NAMESPACE = \"lattice\";\n\ntype TranslationFunction = (\n key: string,\n defaultValue?: string,\n options?: Record<string, unknown>,\n) => string;\n\ntype TranslationResult = {\n t: TranslationFunction;\n i18n: I18nInstance;\n locale: string;\n locales: readonly string[];\n ready: boolean;\n setLocale: (locale: string) => void;\n};\n\nexport const i18n: I18nInstance = i18next.createInstance();\n\nlet initialization: Promise<unknown> | undefined;\nlet revision = 0;\n\nfunction subscribe(onStoreChange: () => void): () => void {\n const listener = () => {\n revision += 1;\n onStoreChange();\n };\n\n i18n.on(\"initialized\", listener);\n i18n.on(\"loaded\", listener);\n i18n.on(\"languageChanged\", listener);\n i18n.store?.on(\"added\", listener);\n i18n.store?.on(\"removed\", listener);\n\n return () => {\n i18n.off(\"initialized\", listener);\n i18n.off(\"loaded\", listener);\n i18n.off(\"languageChanged\", listener);\n i18n.store?.off(\"added\", listener);\n i18n.store?.off(\"removed\", listener);\n };\n}\n\nfunction snapshot(): number {\n return revision;\n}\n\n/**\n * Initialize the instance exactly once. The first caller wins — a rendered\n * component (inline English, zero config) or `enableBackend()`, which registers\n * its backend first because i18next can only wire a backend during `init`.\n */\nexport function ensureI18n(extend?: (base: InitOptions) => InitOptions): Promise<unknown> {\n if (!initialization) {\n const base: InitOptions = {\n lng: currentLocale(),\n fallbackLng: \"en\",\n ns: [DEFAULT_NAMESPACE],\n defaultNS: DEFAULT_NAMESPACE,\n interpolation: { escapeValue: false },\n };\n\n initialization = i18n.init(extend ? extend(base) : base);\n // `services.formatter` only exists once `init()` has run, so this must follow it.\n registerDateTimeFormatter(i18n);\n }\n\n return initialization;\n}\n\nsubscribeLocale((locale) => {\n void ensureI18n().then(() => {\n if (i18n.language !== locale) {\n void i18n.changeLanguage(locale);\n }\n });\n});\n\n/**\n * Eagerly load the namespaces for the given locales so a later\n * `changeLanguage` resolves them from the store instead of an HTTP round-trip,\n * which would otherwise flash the fallback language on switch. The active\n * locale is already loaded by {@link ensureI18n}, so it is skipped.\n */\nexport async function preloadLanguages(locales: readonly string[]): Promise<void> {\n const pending = locales.filter((locale) => locale !== currentLocale());\n\n if (pending.length === 0) {\n return;\n }\n\n await ensureI18n();\n await i18n.loadLanguages([...pending]);\n}\n\nexport function useT(namespace: string): TranslationResult {\n ensureI18n();\n useSyncExternalStore(subscribe, snapshot, snapshot);\n const { locales } = useConfig();\n const { locale, setLocale } = useLocale();\n\n const t = useCallback<TranslationFunction>(\n (key, defaultValue = key, options = {}) => translate(namespace, key, defaultValue, options),\n [namespace],\n );\n\n return { t, i18n, locale, locales, ready: i18n.isInitialized, setLocale };\n}\n\nexport function translate(\n namespace: string,\n key: string,\n defaultValue: string,\n options?: Record<string, unknown>,\n): string {\n ensureI18n();\n\n if (!i18n.isInitialized || !i18n.hasLoadedNamespace(namespace)) {\n return i18n.t(key, defaultValue, { ns: namespace, ...options, saveMissing: false });\n }\n\n return i18n.t(key, defaultValue, { ns: namespace, ...options });\n}\n"],"mappings":";;;;;;AAMA,IAAa,oBAAoB;AAiBjC,IAAa,OAAqB,QAAQ,eAAe;AAEzD,IAAI;AACJ,IAAI,WAAW;AAEf,SAAS,UAAU,eAAuC;CACxD,MAAM,iBAAiB;EACrB,YAAY;EACZ,cAAc;CAChB;CAEA,KAAK,GAAG,eAAe,QAAQ;CAC/B,KAAK,GAAG,UAAU,QAAQ;CAC1B,KAAK,GAAG,mBAAmB,QAAQ;CACnC,KAAK,OAAO,GAAG,SAAS,QAAQ;CAChC,KAAK,OAAO,GAAG,WAAW,QAAQ;CAElC,aAAa;EACX,KAAK,IAAI,eAAe,QAAQ;EAChC,KAAK,IAAI,UAAU,QAAQ;EAC3B,KAAK,IAAI,mBAAmB,QAAQ;EACpC,KAAK,OAAO,IAAI,SAAS,QAAQ;EACjC,KAAK,OAAO,IAAI,WAAW,QAAQ;CACrC;AACF;AAEA,SAAS,WAAmB;CAC1B,OAAO;AACT;;;;;;AAOA,SAAgB,WAAW,QAA+D;CACxF,IAAI,CAAC,gBAAgB;EACnB,MAAM,OAAoB;GACxB,KAAK,cAAc;GACnB,aAAa;GACb,IAAI,CAAC,iBAAiB;GACtB,WAAW;GACX,eAAe,EAAE,aAAa,MAAM;EACtC;EAEA,iBAAiB,KAAK,KAAK,SAAS,OAAO,IAAI,IAAI,IAAI;EAEvD,0BAA0B,IAAI;CAChC;CAEA,OAAO;AACT;AAEA,iBAAiB,WAAW;CAC1B,WAAgB,CAAC,CAAC,WAAW;EAC3B,IAAI,KAAK,aAAa,QACpB,KAAU,eAAe,MAAM;CAEnC,CAAC;AACH,CAAC;;;;;;;AAQD,eAAsB,iBAAiB,SAA2C;CAChF,MAAM,UAAU,QAAQ,QAAQ,WAAW,WAAW,cAAc,CAAC;CAErE,IAAI,QAAQ,WAAW,GACrB;CAGF,MAAM,WAAW;CACjB,MAAM,KAAK,cAAc,CAAC,GAAG,OAAO,CAAC;AACvC;AAEA,SAAgB,KAAK,WAAsC;CACzD,WAAW;CACX,qBAAqB,WAAW,UAAU,QAAQ;CAClD,MAAM,EAAE,YAAY,UAAU;CAC9B,MAAM,EAAE,QAAQ,cAAc,UAAU;CAOxC,OAAO;EAAE,GALC,aACP,KAAK,eAAe,KAAK,UAAU,CAAC,MAAM,UAAU,WAAW,KAAK,cAAc,OAAO,GAC1F,CAAC,SAAS,CAGH;EAAG;EAAM;EAAQ;EAAS,OAAO,KAAK;EAAe;CAAU;AAC1E;AAEA,SAAgB,UACd,WACA,KACA,cACA,SACQ;CACR,WAAW;CAEX,IAAI,CAAC,KAAK,iBAAiB,CAAC,KAAK,mBAAmB,SAAS,GAC3D,OAAO,KAAK,EAAE,KAAK,cAAc;EAAE,IAAI;EAAW,GAAG;EAAS,aAAa;CAAM,CAAC;CAGpF,OAAO,KAAK,EAAE,KAAK,cAAc;EAAE,IAAI;EAAW,GAAG;CAAQ,CAAC;AAChE"}
1
+ {"version":3,"file":"instance.js","names":[],"sources":["../../resources/js/i18n/instance.ts"],"sourcesContent":["import i18next, { type i18n as I18nInstance, type InitOptions } from \"i18next\";\nimport { useCallback, useSyncExternalStore } from \"react\";\nimport { useConfig } from \"./config\";\nimport { registerDateTimeFormatter } from \"./date-time-formatter\";\nimport { currentLocale, subscribeLocale, useLocale } from \"./locale\";\n\nexport const DEFAULT_NAMESPACE = \"lattice\";\n\ntype TranslationFunction = (\n key: string,\n defaultValue?: string,\n options?: Record<string, unknown>,\n) => string;\n\ntype TranslationResult = {\n t: TranslationFunction;\n i18n: I18nInstance;\n locale: string;\n locales: readonly string[];\n ready: boolean;\n setLocale: (locale: string) => void;\n};\n\nexport const i18n: I18nInstance = i18next.createInstance();\n\nlet initialization: Promise<unknown> | undefined;\nlet hold: Promise<unknown> | undefined;\nlet revision = 0;\n\nfunction subscribe(onStoreChange: () => void): () => void {\n const listener = () => {\n revision += 1;\n onStoreChange();\n };\n\n i18n.on(\"initialized\", listener);\n i18n.on(\"loaded\", listener);\n i18n.on(\"languageChanged\", listener);\n i18n.store?.on(\"added\", listener);\n i18n.store?.on(\"removed\", listener);\n\n return () => {\n i18n.off(\"initialized\", listener);\n i18n.off(\"loaded\", listener);\n i18n.off(\"languageChanged\", listener);\n i18n.store?.off(\"added\", listener);\n i18n.store?.off(\"removed\", listener);\n };\n}\n\nfunction snapshot(): number {\n return revision;\n}\n\n/**\n * Defer component-driven initialization until `until` settles — for shells\n * that render before the i18n bootstrap has loaded (SSR hydration), where the\n * first rendered `useT` would otherwise win the init race and lock the HTTP\n * backend out. Configuring callers (those passing `extend` to {@link ensureI18n})\n * bypass the hold; a failed bootstrap releases it, so init stays fail-open.\n */\nexport function holdI18nInit(until: Promise<unknown>): void {\n const release = (): void => {\n hold = undefined;\n };\n const released = until.then(release, release);\n\n if (!initialization) {\n hold = released;\n }\n}\n\n/**\n * Initialize the instance exactly once. The first caller wins — a rendered\n * component (inline English, zero config) or `enableBackend()`, which registers\n * its backend first because i18next can only wire a backend during `init`.\n */\nexport function ensureI18n(extend?: (base: InitOptions) => InitOptions): Promise<unknown> {\n if (!initialization && hold && !extend) {\n return hold.then(() => ensureI18n());\n }\n\n if (!initialization) {\n const base: InitOptions = {\n lng: currentLocale(),\n fallbackLng: \"en\",\n ns: [DEFAULT_NAMESPACE],\n defaultNS: DEFAULT_NAMESPACE,\n interpolation: { escapeValue: false },\n };\n\n initialization = i18n.init(extend ? extend(base) : base);\n // `services.formatter` only exists once `init()` has run, so this must follow it.\n registerDateTimeFormatter(i18n);\n }\n\n return initialization;\n}\n\nsubscribeLocale((locale) => {\n void ensureI18n().then(() => {\n if (i18n.language !== locale) {\n void i18n.changeLanguage(locale);\n }\n });\n});\n\n/**\n * Eagerly load the namespaces for the given locales so a later\n * `changeLanguage` resolves them from the store instead of an HTTP round-trip,\n * which would otherwise flash the fallback language on switch. The active\n * locale is already loaded by {@link ensureI18n}, so it is skipped.\n */\nexport async function preloadLanguages(locales: readonly string[]): Promise<void> {\n const pending = locales.filter((locale) => locale !== currentLocale());\n\n if (pending.length === 0) {\n return;\n }\n\n await ensureI18n();\n await i18n.loadLanguages([...pending]);\n}\n\nexport function useT(namespace: string): TranslationResult {\n ensureI18n();\n useSyncExternalStore(subscribe, snapshot, snapshot);\n const { locales } = useConfig();\n const { locale, setLocale } = useLocale();\n\n const t = useCallback<TranslationFunction>(\n (key, defaultValue = key, options = {}) => translate(namespace, key, defaultValue, options),\n [namespace],\n );\n\n return { t, i18n, locale, locales, ready: i18n.isInitialized, setLocale };\n}\n\nexport function translate(\n namespace: string,\n key: string,\n defaultValue: string,\n options?: Record<string, unknown>,\n): string {\n ensureI18n();\n\n if (!i18n.isInitialized || !i18n.hasLoadedNamespace(namespace)) {\n return i18n.t(key, defaultValue, { ns: namespace, ...options, saveMissing: false });\n }\n\n return i18n.t(key, defaultValue, { ns: namespace, ...options });\n}\n"],"mappings":";;;;;;AAMA,IAAa,oBAAoB;AAiBjC,IAAa,OAAqB,QAAQ,eAAe;AAEzD,IAAI;AACJ,IAAI;AACJ,IAAI,WAAW;AAEf,SAAS,UAAU,eAAuC;CACxD,MAAM,iBAAiB;EACrB,YAAY;EACZ,cAAc;CAChB;CAEA,KAAK,GAAG,eAAe,QAAQ;CAC/B,KAAK,GAAG,UAAU,QAAQ;CAC1B,KAAK,GAAG,mBAAmB,QAAQ;CACnC,KAAK,OAAO,GAAG,SAAS,QAAQ;CAChC,KAAK,OAAO,GAAG,WAAW,QAAQ;CAElC,aAAa;EACX,KAAK,IAAI,eAAe,QAAQ;EAChC,KAAK,IAAI,UAAU,QAAQ;EAC3B,KAAK,IAAI,mBAAmB,QAAQ;EACpC,KAAK,OAAO,IAAI,SAAS,QAAQ;EACjC,KAAK,OAAO,IAAI,WAAW,QAAQ;CACrC;AACF;AAEA,SAAS,WAAmB;CAC1B,OAAO;AACT;;;;;;;;AASA,SAAgB,aAAa,OAA+B;CAC1D,MAAM,gBAAsB;EAC1B,OAAO,KAAA;CACT;CACA,MAAM,WAAW,MAAM,KAAK,SAAS,OAAO;CAE5C,IAAI,CAAC,gBACH,OAAO;AAEX;;;;;;AAOA,SAAgB,WAAW,QAA+D;CACxF,IAAI,CAAC,kBAAkB,QAAQ,CAAC,QAC9B,OAAO,KAAK,WAAW,WAAW,CAAC;CAGrC,IAAI,CAAC,gBAAgB;EACnB,MAAM,OAAoB;GACxB,KAAK,cAAc;GACnB,aAAa;GACb,IAAI,CAAC,iBAAiB;GACtB,WAAW;GACX,eAAe,EAAE,aAAa,MAAM;EACtC;EAEA,iBAAiB,KAAK,KAAK,SAAS,OAAO,IAAI,IAAI,IAAI;EAEvD,0BAA0B,IAAI;CAChC;CAEA,OAAO;AACT;AAEA,iBAAiB,WAAW;CAC1B,WAAgB,CAAC,CAAC,WAAW;EAC3B,IAAI,KAAK,aAAa,QACpB,KAAU,eAAe,MAAM;CAEnC,CAAC;AACH,CAAC;;;;;;;AAQD,eAAsB,iBAAiB,SAA2C;CAChF,MAAM,UAAU,QAAQ,QAAQ,WAAW,WAAW,cAAc,CAAC;CAErE,IAAI,QAAQ,WAAW,GACrB;CAGF,MAAM,WAAW;CACjB,MAAM,KAAK,cAAc,CAAC,GAAG,OAAO,CAAC;AACvC;AAEA,SAAgB,KAAK,WAAsC;CACzD,WAAW;CACX,qBAAqB,WAAW,UAAU,QAAQ;CAClD,MAAM,EAAE,YAAY,UAAU;CAC9B,MAAM,EAAE,QAAQ,cAAc,UAAU;CAOxC,OAAO;EAAE,GALC,aACP,KAAK,eAAe,KAAK,UAAU,CAAC,MAAM,UAAU,WAAW,KAAK,cAAc,OAAO,GAC1F,CAAC,SAAS,CAGH;EAAG;EAAM;EAAQ;EAAS,OAAO,KAAK;EAAe;CAAU;AAC1E;AAEA,SAAgB,UACd,WACA,KACA,cACA,SACQ;CACR,WAAW;CAEX,IAAI,CAAC,KAAK,iBAAiB,CAAC,KAAK,mBAAmB,SAAS,GAC3D,OAAO,KAAK,EAAE,KAAK,cAAc;EAAE,IAAI;EAAW,GAAG;EAAS,aAAa;CAAM,CAAC;CAGpF,OAAO,KAAK,EAAE,KAAK,cAAc;EAAE,IAAI;EAAW,GAAG;CAAQ,CAAC;AAChE"}
@@ -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"}
@@ -0,0 +1,6 @@
1
+ import { useEffect } from 'react';
2
+ /**
3
+ * Drop-in for React's `useLayoutEffect`, which warns under `renderToString`;
4
+ * effects never run there, so the server-side substitution is free.
5
+ */
6
+ export declare const useLayoutEffect: typeof useEffect;
@@ -0,0 +1,11 @@
1
+ import { useEffect, useLayoutEffect as useLayoutEffect$1 } from "react";
2
+ //#region resources/js/lib/use-layout-effect.ts
3
+ /**
4
+ * Drop-in for React's `useLayoutEffect`, which warns under `renderToString`;
5
+ * effects never run there, so the server-side substitution is free.
6
+ */
7
+ var useLayoutEffect = typeof window === "undefined" ? useEffect : useLayoutEffect$1;
8
+ //#endregion
9
+ export { useLayoutEffect };
10
+
11
+ //# sourceMappingURL=use-layout-effect.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-layout-effect.js","names":[],"sources":["../../resources/js/lib/use-layout-effect.ts"],"sourcesContent":["// oxlint-disable-next-line no-restricted-imports -- the one place the real hook may be imported\nimport { useEffect, useLayoutEffect as reactUseLayoutEffect } from \"react\";\n\n/**\n * Drop-in for React's `useLayoutEffect`, which warns under `renderToString`;\n * effects never run there, so the server-side substitution is free.\n */\nexport const useLayoutEffect = typeof window === \"undefined\" ? useEffect : reactUseLayoutEffect;\n"],"mappings":";;;;;;AAOA,IAAa,kBAAkB,OAAO,WAAW,cAAc,YAAY"}
package/dist/ssr.d.ts ADDED
@@ -0,0 +1,20 @@
1
+ import { InertiaAppSSRResponse, Page } from '@inertiajs/core';
2
+ import { CreateLatticeAppOptions } from './create-app.js';
3
+ /**
4
+ * Build an SSR entry's render function from the same options as `createLatticeApp`.
5
+ * `@inertiajs/vite` only auto-wraps literal `createInertiaApp` calls, so a Lattice
6
+ * app declares its own `resources/js/ssr.tsx`:
7
+ *
8
+ * import createServer from "@inertiajs/react/server";
9
+ * import { createLatticeSsr } from "@lattice-php/lattice/ssr";
10
+ *
11
+ * createServer(createLatticeSsr({ ...same options as app.tsx }));
12
+ *
13
+ * The plugin rewrites that `createServer` call into the dev-server default
14
+ * export plus the production HTTP bootstrap; where the bootstrap is unwanted,
15
+ * `export default createLatticeSsr(...)` works as-is.
16
+ *
17
+ * Own subpath on purpose: importing react-dom/server from the client bundle
18
+ * would drag the server renderer into the app.
19
+ */
20
+ export declare function createLatticeSsr(options?: CreateLatticeAppOptions): (page: Page) => Promise<InertiaAppSSRResponse>;
package/dist/ssr.js ADDED
@@ -0,0 +1,32 @@
1
+ import { createLatticeApp } from "./create-app.js";
2
+ import { renderToString } from "react-dom/server";
3
+ //#region resources/js/ssr.ts
4
+ /**
5
+ * Build an SSR entry's render function from the same options as `createLatticeApp`.
6
+ * `@inertiajs/vite` only auto-wraps literal `createInertiaApp` calls, so a Lattice
7
+ * app declares its own `resources/js/ssr.tsx`:
8
+ *
9
+ * import createServer from "@inertiajs/react/server";
10
+ * import { createLatticeSsr } from "@lattice-php/lattice/ssr";
11
+ *
12
+ * createServer(createLatticeSsr({ ...same options as app.tsx }));
13
+ *
14
+ * The plugin rewrites that `createServer` call into the dev-server default
15
+ * export plus the production HTTP bootstrap; where the bootstrap is unwanted,
16
+ * `export default createLatticeSsr(...)` works as-is.
17
+ *
18
+ * Own subpath on purpose: importing react-dom/server from the client bundle
19
+ * would drag the server renderer into the app.
20
+ */
21
+ function createLatticeSsr(options = {}) {
22
+ const app = createLatticeApp(options);
23
+ return async (page) => {
24
+ const render = await app;
25
+ if (typeof render !== "function") throw new Error("[lattice] createLatticeSsr requires a server environment without a DOM.");
26
+ return render(page, renderToString);
27
+ };
28
+ }
29
+ //#endregion
30
+ export { createLatticeSsr };
31
+
32
+ //# sourceMappingURL=ssr.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ssr.js","names":[],"sources":["../resources/js/ssr.ts"],"sourcesContent":["import type { InertiaAppSSRResponse, Page } from \"@inertiajs/core\";\nimport { renderToString } from \"react-dom/server\";\nimport { createLatticeApp, type CreateLatticeAppOptions } from \"./create-app\";\n\n/**\n * Build an SSR entry's render function from the same options as `createLatticeApp`.\n * `@inertiajs/vite` only auto-wraps literal `createInertiaApp` calls, so a Lattice\n * app declares its own `resources/js/ssr.tsx`:\n *\n * import createServer from \"@inertiajs/react/server\";\n * import { createLatticeSsr } from \"@lattice-php/lattice/ssr\";\n *\n * createServer(createLatticeSsr({ ...same options as app.tsx }));\n *\n * The plugin rewrites that `createServer` call into the dev-server default\n * export plus the production HTTP bootstrap; where the bootstrap is unwanted,\n * `export default createLatticeSsr(...)` works as-is.\n *\n * Own subpath on purpose: importing react-dom/server from the client bundle\n * would drag the server renderer into the app.\n */\nexport function createLatticeSsr(\n options: CreateLatticeAppOptions = {},\n): (page: Page) => Promise<InertiaAppSSRResponse> {\n const app = createLatticeApp(options);\n\n return async (page: Page): Promise<InertiaAppSSRResponse> => {\n const render = await app;\n\n if (typeof render !== \"function\") {\n throw new Error(\"[lattice] createLatticeSsr requires a server environment without a DOM.\");\n }\n\n return render(page, renderToString);\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAqBA,SAAgB,iBACd,UAAmC,CAAC,GACY;CAChD,MAAM,MAAM,iBAAiB,OAAO;CAEpC,OAAO,OAAO,SAA+C;EAC3D,MAAM,SAAS,MAAM;EAErB,IAAI,OAAO,WAAW,YACpB,MAAM,IAAI,MAAM,yEAAyE;EAG3F,OAAO,OAAO,MAAM,cAAc;CACpC;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 };
@@ -1 +1 @@
1
- {"version":3,"file":"callout.js","names":[],"sources":["../../resources/js/toast/callout.ts"],"sourcesContent":["import type { Callout, RetractCallout } 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 unique: typeof callout.unique === \"string\" ? callout.unique : 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\nexport function onRetractCallout(callback: (unique: string) => void): () => void {\n const listener = (event: Event): void => {\n const unique = (event as CustomEvent<RetractCallout>).detail?.unique;\n\n if (typeof unique === \"string\") {\n callback(unique);\n }\n };\n\n window.addEventListener(LATTICE_EVENT.retractCallout, listener);\n\n return () => window.removeEventListener(LATTICE_EVENT.retractCallout, 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,QAAQ,OAAO,QAAQ,WAAW,WAAW,QAAQ,SAAS;EAC9D,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;AAEA,SAAgB,iBAAiB,UAAgD;CAC/E,MAAM,YAAY,UAAuB;EACvC,MAAM,SAAU,MAAsC,QAAQ;EAE9D,IAAI,OAAO,WAAW,UACpB,SAAS,MAAM;CAEnB;CAEA,OAAO,iBAAiB,cAAc,gBAAgB,QAAQ;CAE9D,aAAa,OAAO,oBAAoB,cAAc,gBAAgB,QAAQ;AAChF"}
1
+ {"version":3,"file":"callout.js","names":[],"sources":["../../resources/js/toast/callout.ts"],"sourcesContent":["import type { Callout, RetractCallout } 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 { coerceMessage, isVariant, subscribeWindowEvent } 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 const message = coerceMessage(callout.message);\n\n if (message === null) {\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 unique: typeof callout.unique === \"string\" ? callout.unique : null,\n variant: isVariant(callout.variant) ? callout.variant : \"info\",\n };\n}\n\nexport function onCallout(callback: (callout: Callout) => void): () => void {\n return subscribeWindowEvent(LATTICE_EVENT.callout, normalizeCallout, callback);\n}\n\nexport function onRetractCallout(callback: (unique: string) => void): () => void {\n return subscribeWindowEvent(\n LATTICE_EVENT.retractCallout,\n (detail) => {\n const unique = (detail as RetractCallout | undefined)?.unique;\n\n return typeof unique === \"string\" ? unique : null;\n },\n callback,\n );\n}\n"],"mappings":";;;;AAOA,SAAgB,iBAAiB,QAAiC;CAChE,IAAI,OAAO,WAAW,YAAY,WAAW,MAC3C,OAAO;CAGT,MAAM,UAAU;CAChB,MAAM,UAAU,cAAc,QAAQ,OAAO;CAE7C,IAAI,YAAY,MACd,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,QAAQ,OAAO,QAAQ,WAAW,WAAW,QAAQ,SAAS;EAC9D,SAAS,UAAU,QAAQ,OAAO,IAAI,QAAQ,UAAU;CAC1D;AACF;AAEA,SAAgB,UAAU,UAAkD;CAC1E,OAAO,qBAAqB,cAAc,SAAS,kBAAkB,QAAQ;AAC/E;AAEA,SAAgB,iBAAiB,UAAgD;CAC/E,OAAO,qBACL,cAAc,iBACb,WAAW;EACV,MAAM,SAAU,QAAuC;EAEvD,OAAO,OAAO,WAAW,WAAW,SAAS;CAC/C,GACA,QACF;AACF"}
@@ -1,5 +1,7 @@
1
1
  import { Toast as ToastMessage, Variant } from '../types/generated.js';
2
2
  export type { ToastMessage, Variant };
3
3
  export declare function isVariant(value: unknown): value is Variant;
4
+ export declare function coerceMessage(value: unknown): ToastMessage["message"] | null;
5
+ export declare function subscribeWindowEvent<T>(event: string, normalize: (detail: unknown) => T | null, callback: (value: T) => void): () => void;
4
6
  export declare function normalizeToastMessage(value: unknown): ToastMessage | null;
5
7
  export declare function onToast(callback: (toast: ToastMessage) => void): () => void;
@@ -12,12 +12,23 @@ var variants = [
12
12
  function isVariant(value) {
13
13
  return variants.some((variant) => variant === value);
14
14
  }
15
+ function coerceMessage(value) {
16
+ const message = typeof value === "string" ? value : isTranslatable(value) ? value : null;
17
+ return message === "" ? null : message;
18
+ }
19
+ function subscribeWindowEvent(event, normalize, callback) {
20
+ const listener = (windowEvent) => {
21
+ const value = normalize(windowEvent.detail);
22
+ if (value !== null) callback(value);
23
+ };
24
+ window.addEventListener(event, listener);
25
+ return () => window.removeEventListener(event, listener);
26
+ }
15
27
  function normalizeToastMessage(value) {
16
28
  if (typeof value !== "object" || value === null) return null;
17
29
  const toast = value;
18
- const rawMessage = toast.message;
19
- const message = typeof rawMessage === "string" ? rawMessage : isTranslatable(rawMessage) ? rawMessage : null;
20
- if (message === null || message === "") return null;
30
+ const message = coerceMessage(toast.message);
31
+ if (message === null) return null;
21
32
  return {
22
33
  action: toast.action ?? null,
23
34
  dismissible: toast.dismissible !== false,
@@ -28,14 +39,9 @@ function normalizeToastMessage(value) {
28
39
  };
29
40
  }
30
41
  function onToast(callback) {
31
- const listener = (event) => {
32
- const toast = normalizeToastMessage(event.detail);
33
- if (toast) callback(toast);
34
- };
35
- window.addEventListener(LATTICE_EVENT.toast, listener);
36
- return () => window.removeEventListener(LATTICE_EVENT.toast, listener);
42
+ return subscribeWindowEvent(LATTICE_EVENT.toast, normalizeToastMessage, callback);
37
43
  }
38
44
  //#endregion
39
- export { isVariant, normalizeToastMessage, onToast };
45
+ export { coerceMessage, isVariant, normalizeToastMessage, onToast, subscribeWindowEvent };
40
46
 
41
47
  //# sourceMappingURL=toast.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"toast.js","names":[],"sources":["../../resources/js/toast/toast.ts"],"sourcesContent":["import type { Toast as ToastMessage, Variant } from \"@lattice-php/lattice/types/generated\";\nimport { LATTICE_EVENT } from \"@lattice-php/lattice/core/event-names\";\nimport { isTranslatable } from \"@lattice-php/lattice/i18n/translatable\";\n\nexport type { ToastMessage, Variant };\n\nconst variants = [\n \"primary\",\n \"secondary\",\n \"success\",\n \"info\",\n \"warning\",\n \"danger\",\n] as const satisfies readonly Variant[];\n\nexport function isVariant(value: unknown): value is Variant {\n return variants.some((variant) => variant === value);\n}\n\nexport function normalizeToastMessage(value: unknown): ToastMessage | null {\n if (typeof value !== \"object\" || value === null) {\n return null;\n }\n\n const toast = value as Record<string, unknown>;\n\n const rawMessage = toast.message;\n const message =\n typeof rawMessage === \"string\" ? rawMessage : isTranslatable(rawMessage) ? rawMessage : null;\n\n if (message === null || message === \"\") {\n return null;\n }\n\n return {\n action: (toast.action as ToastMessage[\"action\"]) ?? null,\n dismissible: toast.dismissible !== false,\n duration: typeof toast.duration === \"number\" ? toast.duration : null,\n message,\n persistent: toast.persistent === true,\n variant: isVariant(toast.variant) ? toast.variant : \"success\",\n };\n}\n\nexport function onToast(callback: (toast: ToastMessage) => void): () => void {\n const listener = (event: Event): void => {\n const toast = normalizeToastMessage((event as CustomEvent).detail);\n\n if (toast) {\n callback(toast);\n }\n };\n\n window.addEventListener(LATTICE_EVENT.toast, listener);\n\n return () => window.removeEventListener(LATTICE_EVENT.toast, listener);\n}\n"],"mappings":";;;AAMA,IAAM,WAAW;CACf;CACA;CACA;CACA;CACA;CACA;AACF;AAEA,SAAgB,UAAU,OAAkC;CAC1D,OAAO,SAAS,MAAM,YAAY,YAAY,KAAK;AACrD;AAEA,SAAgB,sBAAsB,OAAqC;CACzE,IAAI,OAAO,UAAU,YAAY,UAAU,MACzC,OAAO;CAGT,MAAM,QAAQ;CAEd,MAAM,aAAa,MAAM;CACzB,MAAM,UACJ,OAAO,eAAe,WAAW,aAAa,eAAe,UAAU,IAAI,aAAa;CAE1F,IAAI,YAAY,QAAQ,YAAY,IAClC,OAAO;CAGT,OAAO;EACL,QAAS,MAAM,UAAqC;EACpD,aAAa,MAAM,gBAAgB;EACnC,UAAU,OAAO,MAAM,aAAa,WAAW,MAAM,WAAW;EAChE;EACA,YAAY,MAAM,eAAe;EACjC,SAAS,UAAU,MAAM,OAAO,IAAI,MAAM,UAAU;CACtD;AACF;AAEA,SAAgB,QAAQ,UAAqD;CAC3E,MAAM,YAAY,UAAuB;EACvC,MAAM,QAAQ,sBAAuB,MAAsB,MAAM;EAEjE,IAAI,OACF,SAAS,KAAK;CAElB;CAEA,OAAO,iBAAiB,cAAc,OAAO,QAAQ;CAErD,aAAa,OAAO,oBAAoB,cAAc,OAAO,QAAQ;AACvE"}
1
+ {"version":3,"file":"toast.js","names":[],"sources":["../../resources/js/toast/toast.ts"],"sourcesContent":["import type { Toast as ToastMessage, Variant } from \"@lattice-php/lattice/types/generated\";\nimport { LATTICE_EVENT } from \"@lattice-php/lattice/core/event-names\";\nimport { isTranslatable } from \"@lattice-php/lattice/i18n/translatable\";\n\nexport type { ToastMessage, Variant };\n\nconst variants = [\n \"primary\",\n \"secondary\",\n \"success\",\n \"info\",\n \"warning\",\n \"danger\",\n] as const satisfies readonly Variant[];\n\nexport function isVariant(value: unknown): value is Variant {\n return variants.some((variant) => variant === value);\n}\n\nexport function coerceMessage(value: unknown): ToastMessage[\"message\"] | null {\n const message = typeof value === \"string\" ? value : isTranslatable(value) ? value : null;\n\n return message === \"\" ? null : message;\n}\n\nexport function subscribeWindowEvent<T>(\n event: string,\n normalize: (detail: unknown) => T | null,\n callback: (value: T) => void,\n): () => void {\n const listener = (windowEvent: Event): void => {\n const value = normalize((windowEvent as CustomEvent).detail);\n\n if (value !== null) {\n callback(value);\n }\n };\n\n window.addEventListener(event, listener);\n\n return () => window.removeEventListener(event, listener);\n}\n\nexport function normalizeToastMessage(value: unknown): ToastMessage | null {\n if (typeof value !== \"object\" || value === null) {\n return null;\n }\n\n const toast = value as Record<string, unknown>;\n const message = coerceMessage(toast.message);\n\n if (message === null) {\n return null;\n }\n\n return {\n action: (toast.action as ToastMessage[\"action\"]) ?? null,\n dismissible: toast.dismissible !== false,\n duration: typeof toast.duration === \"number\" ? toast.duration : null,\n message,\n persistent: toast.persistent === true,\n variant: isVariant(toast.variant) ? toast.variant : \"success\",\n };\n}\n\nexport function onToast(callback: (toast: ToastMessage) => void): () => void {\n return subscribeWindowEvent(LATTICE_EVENT.toast, normalizeToastMessage, callback);\n}\n"],"mappings":";;;AAMA,IAAM,WAAW;CACf;CACA;CACA;CACA;CACA;CACA;AACF;AAEA,SAAgB,UAAU,OAAkC;CAC1D,OAAO,SAAS,MAAM,YAAY,YAAY,KAAK;AACrD;AAEA,SAAgB,cAAc,OAAgD;CAC5E,MAAM,UAAU,OAAO,UAAU,WAAW,QAAQ,eAAe,KAAK,IAAI,QAAQ;CAEpF,OAAO,YAAY,KAAK,OAAO;AACjC;AAEA,SAAgB,qBACd,OACA,WACA,UACY;CACZ,MAAM,YAAY,gBAA6B;EAC7C,MAAM,QAAQ,UAAW,YAA4B,MAAM;EAE3D,IAAI,UAAU,MACZ,SAAS,KAAK;CAElB;CAEA,OAAO,iBAAiB,OAAO,QAAQ;CAEvC,aAAa,OAAO,oBAAoB,OAAO,QAAQ;AACzD;AAEA,SAAgB,sBAAsB,OAAqC;CACzE,IAAI,OAAO,UAAU,YAAY,UAAU,MACzC,OAAO;CAGT,MAAM,QAAQ;CACd,MAAM,UAAU,cAAc,MAAM,OAAO;CAE3C,IAAI,YAAY,MACd,OAAO;CAGT,OAAO;EACL,QAAS,MAAM,UAAqC;EACpD,aAAa,MAAM,gBAAgB;EACnC,UAAU,OAAO,MAAM,aAAa,WAAW,MAAM,WAAW;EAChE;EACA,YAAY,MAAM,eAAe;EACjC,SAAS,UAAU,MAAM,OAAO,IAAI,MAAM,UAAU;CACtD;AACF;AAEA,SAAgB,QAAQ,UAAqD;CAC3E,OAAO,qBAAqB,cAAc,OAAO,uBAAuB,QAAQ;AAClF"}
@@ -7,7 +7,7 @@ export declare function SegmentedPills({ ariaLabel, autoFocus, disabled, name, o
7
7
  ariaLabel?: string;
8
8
  autoFocus?: boolean;
9
9
  disabled?: boolean;
10
- name?: string;
10
+ name: string;
11
11
  onSelect: (value: string) => void;
12
12
  options: Option[];
13
13
  tabIndex?: number;
@@ -23,7 +23,7 @@ function SegmentedPills({ ariaLabel, autoFocus = false, disabled = false, name,
23
23
  const isSelected = value === option.value;
24
24
  return /* @__PURE__ */ jsx("button", {
25
25
  "aria-checked": isSelected,
26
- "data-test": `${name ?? "segment"}-${option.value}`,
26
+ "data-test": `${name}-${option.value}`,
27
27
  className: cn(pillClassName(isSelected), disabled && "cursor-not-allowed opacity-60"),
28
28
  disabled,
29
29
  onClick: () => onSelect(option.value),