@lattice-php/lattice 0.22.0 → 0.24.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 (65) hide show
  1. package/dist/action/components/action-form.js +1 -1
  2. package/dist/action/components/action-group.js +1 -1
  3. package/dist/action/hooks/use-action.js +1 -1
  4. package/dist/chat/components/chat-box.js +1 -1
  5. package/dist/chat/components/prompt-input.js +1 -1
  6. package/dist/core/index.d.ts +4 -0
  7. package/dist/core/index.js +4 -1
  8. package/dist/core/registry.d.ts +5 -0
  9. package/dist/core/registry.js.map +1 -1
  10. package/dist/create-app.d.ts +6 -2
  11. package/dist/create-app.js +12 -1
  12. package/dist/create-app.js.map +1 -1
  13. package/dist/form/components/fields/rich-editor-field.js +1 -1
  14. package/dist/form/components/fields/row-actions.js +1 -1
  15. package/dist/form/components/fields/row-item.js +1 -1
  16. package/dist/form/components/fields/select.js +1 -1
  17. package/dist/form/components/fields/table-rows.js +1 -1
  18. package/dist/form/components/form.js +26 -5
  19. package/dist/form/components/form.js.map +1 -1
  20. package/dist/form/rich-editor/builtins.js +1 -1
  21. package/dist/i18n/backend.js +1 -1
  22. package/dist/i18n/index.js +2 -2
  23. package/dist/i18n/instance.d.ts +1 -0
  24. package/dist/i18n/instance.js +5 -5
  25. package/dist/i18n/instance.js.map +1 -1
  26. package/dist/i18n/timezone.js +1 -1
  27. package/dist/layout/components/callouts.js +1 -1
  28. package/dist/notifications/components/empty-state.js +1 -1
  29. package/dist/notifications/components/notification-item.js +1 -1
  30. package/dist/notifications/components/notifications.js +1 -1
  31. package/dist/remote/components/data-list.js +1 -1
  32. package/dist/table/components/cells/boolean-cell.js +1 -1
  33. package/dist/table/components/column-header.js +1 -1
  34. package/dist/table/components/filter-controls.js +1 -1
  35. package/dist/table/components/filter-value-input.js +1 -1
  36. package/dist/table/components/sort-bar.js +1 -1
  37. package/dist/table/components/table-search.js +1 -1
  38. package/dist/table/components/table.js +1 -1
  39. package/dist/toast/toaster.js +1 -1
  40. package/dist/types/generated.d.ts +5 -19
  41. package/dist/ui/combobox.js +1 -1
  42. package/dist/ui/copyable-text.js +1 -1
  43. package/dist/ui/info-tooltip.js +1 -1
  44. package/dist/ui/plugin.js +1 -3
  45. package/dist/ui/plugin.js.map +1 -1
  46. package/dist/ui/spinner.js +1 -1
  47. package/dist/ui/tabs.js +1 -1
  48. package/dist/vite.d.ts +3 -2
  49. package/dist/vite.js +7 -3
  50. package/dist/vite.js.map +1 -1
  51. package/dist-standalone/chunks/{chart-view-C6R5iPra.js → chart-view-DEwGTt9d.js} +2 -2
  52. package/dist-standalone/chunks/{date-picker-field-DhhEB-Mh.js → date-picker-field-CCQ9nWx0.js} +1 -1
  53. package/dist-standalone/chunks/{page-props-DOfg30l5.js → page-props-D3FnL614.js} +1 -1
  54. package/dist-standalone/chunks/{rich-editor-field-DORXTHPw.js → rich-editor-field-B9Nv1qia.js} +2 -2
  55. package/dist-standalone/chunks/{subscriptions-DK_s_F2g.js → subscriptions-C-0lSr7X.js} +1 -1
  56. package/dist-standalone/lattice.css +1 -1
  57. package/dist-standalone/lattice.js +6 -6
  58. package/dist-standalone/manifest.json +7 -7
  59. package/package.json +2 -2
  60. package/dist/ui/tree-context.d.ts +0 -33
  61. package/dist/ui/tree-context.js +0 -135
  62. package/dist/ui/tree-context.js.map +0 -1
  63. package/dist/ui/tree.d.ts +0 -19
  64. package/dist/ui/tree.js +0 -187
  65. package/dist/ui/tree.js.map +0 -1
@@ -1,5 +1,5 @@
1
- import { Renderer } from "../../core/renderer.js";
2
1
  import { useT } from "../../i18n/instance.js";
2
+ import { Renderer } from "../../core/renderer.js";
3
3
  import { dispatchActionError, getActionEffects } from "../../effects/dispatch.js";
4
4
  import { useEffectDispatcher } from "../../effects/use-effect-dispatcher.js";
5
5
  import { Button } from "../../ui/button.js";
@@ -1,6 +1,6 @@
1
+ import { useT } from "../../i18n/instance.js";
1
2
  import { cn } from "../../lib/utils.js";
2
3
  import { Icon } from "../../icons/sprite.js";
3
- import { useT } from "../../i18n/instance.js";
4
4
  import { nodeIdentity } from "../../core/test-id.js";
5
5
  import { Button } from "../../ui/button.js";
6
6
  import { ActionMenuProvider } from "../../ui/action-menu-context.js";
@@ -1,5 +1,5 @@
1
- import { withHeaders } from "../../core/headers.js";
2
1
  import { translate } from "../../i18n/instance.js";
2
+ import { withHeaders } from "../../core/headers.js";
3
3
  import { useEffectDispatcher } from "../../effects/use-effect-dispatcher.js";
4
4
  import { ConfirmDialog } from "../../ui/confirm-dialog.js";
5
5
  import { apiFetch } from "../../core/api.js";
@@ -1,5 +1,5 @@
1
- import { cn } from "../../lib/utils.js";
2
1
  import { useT } from "../../i18n/instance.js";
2
+ import { cn } from "../../lib/utils.js";
3
3
  import { testIdentity } from "../../core/test-id.js";
4
4
  import { apiFetch, remoteJson } from "../../core/api.js";
5
5
  import { createRemoteNdjsonChatTransport, ndjsonChatTransport } from "../lib/transport.js";
@@ -1,5 +1,5 @@
1
- import { cn } from "../../lib/utils.js";
2
1
  import { useT } from "../../i18n/instance.js";
2
+ import { cn } from "../../lib/utils.js";
3
3
  import { testIdentity } from "../../core/test-id.js";
4
4
  import { Button } from "../../ui/button.js";
5
5
  import { useState } from "react";
@@ -10,4 +10,8 @@ export { createPlugin, createRegistry, eagerComponent, extendRegistry, lazyCompo
10
10
  export type { Plugin, Registry } from './registry.js';
11
11
  export { RegistryContext, setDefaultRegistry, useColumnRegistry, useComponentRegistry, useEffectHandlerRegistry, } from './registry-context.js';
12
12
  export { Renderer, RenderNode } from './renderer.js';
13
+ export { nodeIdentity } from './test-id.js';
14
+ export { usePersistentState } from '../lib/use-persistent-state.js';
15
+ export type { PersistentStateOptions } from '../lib/use-persistent-state.js';
16
+ export { cn } from '../lib/utils.js';
13
17
  export type * from './types.js';
@@ -3,8 +3,11 @@ import { RegistryContext, setDefaultRegistry, useColumnRegistry, useComponentReg
3
3
  import { dataBindings, isRecord, materializeNode, materializeProps, materializeSchema, rowValue } from "./materialize.js";
4
4
  import { LATTICE_REF_HEADER, withRefHeader } from "./component-ref.js";
5
5
  import { withHeaders } from "./headers.js";
6
+ import { cn } from "../lib/utils.js";
6
7
  import { toNodes } from "./nodes.js";
7
8
  import { CollapsedContext, useCollapsed } from "./collapsed-context.js";
8
9
  import { RenderNode, Renderer } from "./renderer.js";
10
+ import { nodeIdentity } from "./test-id.js";
11
+ import { usePersistentState } from "../lib/use-persistent-state.js";
9
12
  import { ApiError, apiFetch, apiJson, clearRemoteTokenCache, invalidateRemoteToken, remoteFetch, remoteJson, remoteToken } from "./api.js";
10
- export { ApiError, CollapsedContext, LATTICE_REF_HEADER, RegistryContext, RenderNode, Renderer, apiFetch, apiJson, clearRemoteTokenCache, createPlugin, createRegistry, dataBindings, eagerComponent, extendRegistry, invalidateRemoteToken, isRecord, lazyComponent, materializeNode, materializeProps, materializeSchema, remoteFetch, remoteJson, remoteToken, rowValue, setDefaultRegistry, toNodes, useCollapsed, useColumnRegistry, useComponentRegistry, useEffectHandlerRegistry, withHeaders, withRefHeader };
13
+ export { ApiError, CollapsedContext, LATTICE_REF_HEADER, RegistryContext, RenderNode, Renderer, apiFetch, apiJson, clearRemoteTokenCache, cn, createPlugin, createRegistry, dataBindings, eagerComponent, extendRegistry, invalidateRemoteToken, isRecord, lazyComponent, materializeNode, materializeProps, materializeSchema, nodeIdentity, remoteFetch, remoteJson, remoteToken, rowValue, setDefaultRegistry, toNodes, useCollapsed, useColumnRegistry, useComponentRegistry, useEffectHandlerRegistry, usePersistentState, withHeaders, withRefHeader };
@@ -16,11 +16,16 @@ export type LazyComponentRegistration = {
16
16
  export type ComponentRegistration = EagerComponentRegistration | LazyComponentRegistration;
17
17
  export type ComponentRegistry = Record<string, ComponentRegistration>;
18
18
  export type ComponentRegistryFor<TTypes extends keyof ComponentPropsMap & string> = Record<TTypes, ComponentRegistration>;
19
+ export type PluginI18n = {
20
+ /** i18next namespace the plugin's components translate under. */
21
+ namespace: string;
22
+ };
19
23
  export type Plugin = {
20
24
  name: string;
21
25
  components?: ComponentRegistry;
22
26
  columns?: ColumnRegistry;
23
27
  effects?: EffectHandlerRegistry;
28
+ i18n?: PluginI18n;
24
29
  };
25
30
  export type Registry = {
26
31
  components: ComponentRegistry;
@@ -1 +1 @@
1
- {"version":3,"file":"registry.js","names":[],"sources":["../../resources/js/core/registry.ts"],"sourcesContent":["import { lazy } from \"react\";\nimport type { LazyExoticComponent } from \"react\";\nimport type { RendererComponent, RendererComponentModule } from \"./types\";\nimport type { EffectHandlerRegistry } from \"@lattice-php/lattice/effects/registry\";\nimport type { ColumnRegistry } from \"@lattice-php/lattice/table/registry\";\nimport type { ComponentPropsMap } from \"@lattice-php/lattice/types/generated\";\n\nexport type EagerComponentRegistration = {\n component: RendererComponent;\n mode: \"eager\";\n};\n\nexport type LazyComponentRegistration = {\n component: LazyExoticComponent<RendererComponent>;\n fallback?: RendererComponent;\n load: () => Promise<RendererComponentModule>;\n mode: \"lazy\";\n};\n\nexport type ComponentRegistration = EagerComponentRegistration | LazyComponentRegistration;\n\nexport type ComponentRegistry = Record<string, ComponentRegistration>;\n\nexport type ComponentRegistryFor<TTypes extends keyof ComponentPropsMap & string> = Record<\n TTypes,\n ComponentRegistration\n>;\n\nexport type Plugin = {\n name: string;\n components?: ComponentRegistry;\n columns?: ColumnRegistry;\n effects?: EffectHandlerRegistry;\n};\n\nexport type Registry = {\n components: ComponentRegistry;\n columns: ColumnRegistry;\n effects: EffectHandlerRegistry;\n};\n\nexport type LazyComponentOptions<TType extends string> = {\n fallback?: RendererComponent<TType>;\n};\n\nexport function eagerComponent<TType extends string>(\n component: RendererComponent<TType>,\n): EagerComponentRegistration {\n return {\n component: component as unknown as RendererComponent,\n mode: \"eager\",\n };\n}\n\nexport function lazyComponent<TType extends string>(\n load: () => Promise<RendererComponentModule<TType>>,\n options: LazyComponentOptions<TType> = {},\n): LazyComponentRegistration {\n const erasedLoader = load as unknown as () => Promise<RendererComponentModule>;\n\n return {\n component: lazy(erasedLoader),\n fallback: options.fallback as RendererComponent | undefined,\n load: erasedLoader,\n mode: \"lazy\",\n };\n}\n\nexport function createPlugin(plugin: Plugin): Plugin {\n return plugin;\n}\n\nexport function createRegistry(...plugins: Plugin[]): Registry {\n return plugins.reduce<Registry>(\n (registry, plugin) => ({\n components: { ...registry.components, ...plugin.components },\n columns: { ...registry.columns, ...plugin.columns },\n effects: { ...registry.effects, ...plugin.effects },\n }),\n { components: {}, columns: {}, effects: {} },\n );\n}\n\nexport function extendRegistry(registry: Registry, ...plugins: Plugin[]): Registry {\n const merged = createRegistry(...plugins);\n\n return {\n components: { ...registry.components, ...merged.components },\n columns: { ...registry.columns, ...merged.columns },\n effects: { ...registry.effects, ...merged.effects },\n };\n}\n"],"mappings":";;AA6CA,SAAgB,eACd,WAC4B;CAC5B,OAAO;EACM;EACX,MAAM;CACR;AACF;AAEA,SAAgB,cACd,MACA,UAAuC,CAAC,GACb;CAC3B,MAAM,eAAe;CAErB,OAAO;EACL,WAAW,KAAK,YAAY;EAC5B,UAAU,QAAQ;EAClB,MAAM;EACN,MAAM;CACR;AACF;AAEA,SAAgB,aAAa,QAAwB;CACnD,OAAO;AACT;AAEA,SAAgB,eAAe,GAAG,SAA6B;CAC7D,OAAO,QAAQ,QACZ,UAAU,YAAY;EACrB,YAAY;GAAE,GAAG,SAAS;GAAY,GAAG,OAAO;EAAW;EAC3D,SAAS;GAAE,GAAG,SAAS;GAAS,GAAG,OAAO;EAAQ;EAClD,SAAS;GAAE,GAAG,SAAS;GAAS,GAAG,OAAO;EAAQ;CACpD,IACA;EAAE,YAAY,CAAC;EAAG,SAAS,CAAC;EAAG,SAAS,CAAC;CAAE,CAC7C;AACF;AAEA,SAAgB,eAAe,UAAoB,GAAG,SAA6B;CACjF,MAAM,SAAS,eAAe,GAAG,OAAO;CAExC,OAAO;EACL,YAAY;GAAE,GAAG,SAAS;GAAY,GAAG,OAAO;EAAW;EAC3D,SAAS;GAAE,GAAG,SAAS;GAAS,GAAG,OAAO;EAAQ;EAClD,SAAS;GAAE,GAAG,SAAS;GAAS,GAAG,OAAO;EAAQ;CACpD;AACF"}
1
+ {"version":3,"file":"registry.js","names":[],"sources":["../../resources/js/core/registry.ts"],"sourcesContent":["import { lazy } from \"react\";\nimport type { LazyExoticComponent } from \"react\";\nimport type { RendererComponent, RendererComponentModule } from \"./types\";\nimport type { EffectHandlerRegistry } from \"@lattice-php/lattice/effects/registry\";\nimport type { ColumnRegistry } from \"@lattice-php/lattice/table/registry\";\nimport type { ComponentPropsMap } from \"@lattice-php/lattice/types/generated\";\n\nexport type EagerComponentRegistration = {\n component: RendererComponent;\n mode: \"eager\";\n};\n\nexport type LazyComponentRegistration = {\n component: LazyExoticComponent<RendererComponent>;\n fallback?: RendererComponent;\n load: () => Promise<RendererComponentModule>;\n mode: \"lazy\";\n};\n\nexport type ComponentRegistration = EagerComponentRegistration | LazyComponentRegistration;\n\nexport type ComponentRegistry = Record<string, ComponentRegistration>;\n\nexport type ComponentRegistryFor<TTypes extends keyof ComponentPropsMap & string> = Record<\n TTypes,\n ComponentRegistration\n>;\n\nexport type PluginI18n = {\n /** i18next namespace the plugin's components translate under. */\n namespace: string;\n};\n\nexport type Plugin = {\n name: string;\n components?: ComponentRegistry;\n columns?: ColumnRegistry;\n effects?: EffectHandlerRegistry;\n i18n?: PluginI18n;\n};\n\nexport type Registry = {\n components: ComponentRegistry;\n columns: ColumnRegistry;\n effects: EffectHandlerRegistry;\n};\n\nexport type LazyComponentOptions<TType extends string> = {\n fallback?: RendererComponent<TType>;\n};\n\nexport function eagerComponent<TType extends string>(\n component: RendererComponent<TType>,\n): EagerComponentRegistration {\n return {\n component: component as unknown as RendererComponent,\n mode: \"eager\",\n };\n}\n\nexport function lazyComponent<TType extends string>(\n load: () => Promise<RendererComponentModule<TType>>,\n options: LazyComponentOptions<TType> = {},\n): LazyComponentRegistration {\n const erasedLoader = load as unknown as () => Promise<RendererComponentModule>;\n\n return {\n component: lazy(erasedLoader),\n fallback: options.fallback as RendererComponent | undefined,\n load: erasedLoader,\n mode: \"lazy\",\n };\n}\n\nexport function createPlugin(plugin: Plugin): Plugin {\n return plugin;\n}\n\nexport function createRegistry(...plugins: Plugin[]): Registry {\n return plugins.reduce<Registry>(\n (registry, plugin) => ({\n components: { ...registry.components, ...plugin.components },\n columns: { ...registry.columns, ...plugin.columns },\n effects: { ...registry.effects, ...plugin.effects },\n }),\n { components: {}, columns: {}, effects: {} },\n );\n}\n\nexport function extendRegistry(registry: Registry, ...plugins: Plugin[]): Registry {\n const merged = createRegistry(...plugins);\n\n return {\n components: { ...registry.components, ...merged.components },\n columns: { ...registry.columns, ...merged.columns },\n effects: { ...registry.effects, ...merged.effects },\n };\n}\n"],"mappings":";;AAmDA,SAAgB,eACd,WAC4B;CAC5B,OAAO;EACM;EACX,MAAM;CACR;AACF;AAEA,SAAgB,cACd,MACA,UAAuC,CAAC,GACb;CAC3B,MAAM,eAAe;CAErB,OAAO;EACL,WAAW,KAAK,YAAY;EAC5B,UAAU,QAAQ;EAClB,MAAM;EACN,MAAM;CACR;AACF;AAEA,SAAgB,aAAa,QAAwB;CACnD,OAAO;AACT;AAEA,SAAgB,eAAe,GAAG,SAA6B;CAC7D,OAAO,QAAQ,QACZ,UAAU,YAAY;EACrB,YAAY;GAAE,GAAG,SAAS;GAAY,GAAG,OAAO;EAAW;EAC3D,SAAS;GAAE,GAAG,SAAS;GAAS,GAAG,OAAO;EAAQ;EAClD,SAAS;GAAE,GAAG,SAAS;GAAS,GAAG,OAAO;EAAQ;CACpD,IACA;EAAE,YAAY,CAAC;EAAG,SAAS,CAAC;EAAG,SAAS,CAAC;CAAE,CAC7C;AACF;AAEA,SAAgB,eAAe,UAAoB,GAAG,SAA6B;CACjF,MAAM,SAAS,eAAe,GAAG,OAAO;CAExC,OAAO;EACL,YAAY;GAAE,GAAG,SAAS;GAAY,GAAG,OAAO;EAAW;EAC3D,SAAS;GAAE,GAAG,SAAS;GAAS,GAAG,OAAO;EAAQ;EAClD,SAAS;GAAE,GAAG,SAAS;GAAS,GAAG,OAAO;EAAQ;CACpD;AACF"}
@@ -6,7 +6,10 @@ import { SpriteValue } from './icons/sprite.js';
6
6
  import { CreateLayoutResolverOptions, PageModules } from './inertia.js';
7
7
  type InertiaAppOptions = NonNullable<Parameters<typeof createInertiaApp>[0]>;
8
8
  export type CreateLatticeAppI18nOptions = {
9
- /** i18next namespaces to load, e.g. `["lattice", "app"]`. Defaults to the package's own. */
9
+ /**
10
+ * i18next namespaces to load, e.g. `["lattice", "app"]`. Defaults to the
11
+ * package's own. Namespaces declared by plugins are merged in on top.
12
+ */
10
13
  namespaces?: string[];
11
14
  };
12
15
  export type CreateLatticeAppOptions = Omit<InertiaAppOptions, "resolve" | "layout" | "setup" | "withApp" | "pages"> & {
@@ -14,7 +17,8 @@ export type CreateLatticeAppOptions = Omit<InertiaAppOptions, "resolve" | "layou
14
17
  /**
15
18
  * Component-package plugins to merge onto the registry — pass the
16
19
  * Composer-discovered `virtual:lattice/plugins` here to register vendor
17
- * components with no manual `extendRegistry` call.
20
+ * components with no manual `extendRegistry` call. A plugin's declared
21
+ * i18n namespace joins the i18n bootstrap automatically.
18
22
  */
19
23
  plugins?: Plugin[];
20
24
  sprite?: SpriteValue;
@@ -1,6 +1,7 @@
1
1
  import { initializeTheme } from "./appearance/index.js";
2
2
  import { extendRegistry } from "./core/registry.js";
3
3
  import { setDefaultRegistry } from "./core/registry-context.js";
4
+ import "./i18n/instance.js";
4
5
  import { LocaleReload } from "./i18n/locale-reload.js";
5
6
  import { i18nConfigFromPageProps } from "./i18n/shared-props.js";
6
7
  import { createLayoutResolver, createPageResolver, withVisitHeaders } from "./inertia.js";
@@ -10,6 +11,14 @@ import { createInertiaApp } from "@inertiajs/react";
10
11
  import { useEffect, useState } from "react";
11
12
  import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
12
13
  //#region resources/js/create-app.tsx
14
+ function withPluginNamespaces(options, entries) {
15
+ if (entries.length === 0) return options;
16
+ const namespaces = new Set([...options.namespaces ?? ["lattice"], ...entries.map((entry) => entry.namespace)]);
17
+ return {
18
+ ...options,
19
+ namespaces: [...namespaces]
20
+ };
21
+ }
13
22
  function AwaitReady({ ready, children }) {
14
23
  const [isReady, setReady] = useState(false);
15
24
  useEffect(() => {
@@ -36,6 +45,8 @@ function createLatticeApp({ registry: registry$1, plugins, sprite, pages = {}, d
36
45
  const activeRegistry = plugins && plugins.length > 0 ? extendRegistry(baseRegistry, ...plugins) : baseRegistry;
37
46
  setDefaultRegistry(activeRegistry);
38
47
  const i18nEnabled = i18n !== false;
48
+ const pluginI18n = plugins?.flatMap((plugin) => plugin.i18n ? [plugin.i18n] : []) ?? [];
49
+ const i18nOptions = i18nEnabled ? withPluginNamespaces(i18n ?? {}, pluginI18n) : {};
39
50
  const userVisitOptions = inertiaOptions.defaults?.visitOptions;
40
51
  const defaults = i18nEnabled ? {
41
52
  ...inertiaOptions.defaults,
@@ -50,7 +61,7 @@ function createLatticeApp({ registry: registry$1, plugins, sprite, pages = {}, d
50
61
  withApp: (node, { ssr, page }) => {
51
62
  const pending = [];
52
63
  if (!ssr) {
53
- if (i18nEnabled && i18nConfigFromPageProps(page.props) !== void 0) pending.push(import("./i18n/page-props.js").then((module) => module.configureI18nFromPageProps(page.props, i18n ?? {})));
64
+ if (i18nEnabled && i18nConfigFromPageProps(page.props) !== void 0) pending.push(import("./i18n/page-props.js").then((module) => module.configureI18nFromPageProps(page.props, i18nOptions)));
54
65
  const booted = boot?.({ page });
55
66
  if (booted) pending.push(booted);
56
67
  }
@@ -1 +1 @@
1
- {"version":3,"file":"create-app.js","names":[],"sources":["../resources/js/create-app.tsx"],"sourcesContent":["import type { Page as InertiaPage, VisitOptions } from \"@inertiajs/core\";\nimport { createInertiaApp } from \"@inertiajs/react\";\nimport { useEffect, useState, type ReactElement, type ReactNode } from \"react\";\nimport { initializeTheme } from \"./appearance\";\nimport { extendRegistry, type Plugin, type Registry } from \"./core/registry\";\nimport { setDefaultRegistry } from \"./core/registry-context\";\nimport type { SpriteValue } from \"./icons/sprite\";\nimport { LocaleReload } from \"./i18n/locale-reload\";\nimport { i18nConfigFromPageProps } from \"./i18n/shared-props\";\nimport {\n createLayoutResolver,\n createPageResolver,\n withVisitHeaders,\n type CreateLayoutResolverOptions,\n type PageModules,\n} from \"./inertia\";\nimport { ProviderBase } from \"./provider-base\";\nimport { registry as defaultRegistry } from \"./registry\";\n\ntype InertiaAppOptions = NonNullable<Parameters<typeof createInertiaApp>[0]>;\n\nexport type CreateLatticeAppI18nOptions = {\n /** i18next namespaces to load, e.g. `[\"lattice\", \"app\"]`. Defaults to the package's own. */\n namespaces?: string[];\n};\n\nexport type CreateLatticeAppOptions = Omit<\n InertiaAppOptions,\n \"resolve\" | \"layout\" | \"setup\" | \"withApp\" | \"pages\"\n> & {\n registry?: Registry;\n /**\n * Component-package plugins to merge onto the registry — pass the\n * Composer-discovered `virtual:lattice/plugins` here to register vendor\n * components with no manual `extendRegistry` call.\n */\n plugins?: Plugin[];\n sprite?: SpriteValue;\n /** Normal Inertia page modules, e.g. `import.meta.glob('./pages/**\\/*.tsx')`. */\n pages?: PageModules;\n defaultLayout?: CreateLayoutResolverOptions[\"defaultLayout\"];\n /**\n * Lattice's i18n bootstrap, on by default: when the backend shares the\n * `lattice.i18n` prop, the first render waits for the translation setup (no\n * flash of untranslated fallbacks), `LocaleReload` re-fetches the page after\n * a locale switch, and every visit carries the locale/timezone headers. The\n * i18next chunk only loads when the backend actually shares the prop. Pass\n * `false` to opt out entirely.\n */\n i18n?: CreateLatticeAppI18nOptions | false;\n /**\n * App bootstrap that needs the initial page — e.g. `configureEcho` from a\n * shared connection prop. Runs on the client before the first render; a\n * returned promise delays that render until it resolves.\n */\n boot?: (context: { page: InertiaPage }) => void | Promise<void>;\n /**\n * Compose providers or siblings around the app. Applied inside the Lattice\n * Provider, so the registry, sprite, and toaster contexts are available.\n */\n wrap?: (app: ReactElement) => ReactElement;\n};\n\n// Fail-open: a failed bootstrap renders the app anyway (with fallback strings)\n// rather than a blank page.\nfunction AwaitReady({ ready, children }: { ready: Promise<unknown>; children: ReactNode }) {\n const [isReady, setReady] = useState(false);\n\n useEffect(() => {\n let active = true;\n const reveal = (): void => {\n if (active) {\n setReady(true);\n }\n };\n\n void ready.then(reveal, reveal);\n\n return () => {\n active = false;\n };\n }, [ready]);\n\n return isReady ? children : null;\n}\n\n/**\n * Bootstrap an Inertia app with the Lattice shell: the page/layout resolvers\n * (server-driven Lattice pages and normal Inertia pages alike), the Provider —\n * registry, sprite, flash toasts via Lattice's own Toaster — theme\n * initialization, and the i18n bootstrap. Forwards any other createInertiaApp\n * option.\n */\nexport function createLatticeApp({\n registry,\n plugins,\n sprite,\n pages = {},\n defaultLayout,\n strictMode = true,\n i18n,\n boot,\n wrap,\n ...inertiaOptions\n}: CreateLatticeAppOptions = {}) {\n const baseRegistry = registry ?? defaultRegistry;\n const activeRegistry =\n plugins && plugins.length > 0 ? extendRegistry(baseRegistry, ...plugins) : baseRegistry;\n\n setDefaultRegistry(activeRegistry);\n\n const i18nEnabled = i18n !== false;\n const userVisitOptions = inertiaOptions.defaults?.visitOptions;\n const defaults = i18nEnabled\n ? {\n ...inertiaOptions.defaults,\n visitOptions: (href: string, options: VisitOptions): VisitOptions =>\n withVisitHeaders(href, userVisitOptions?.(href, options) ?? options),\n }\n : inertiaOptions.defaults;\n\n const app = createInertiaApp({\n ...inertiaOptions,\n defaults,\n strictMode,\n resolve: createPageResolver(pages),\n layout: createLayoutResolver({ defaultLayout }),\n withApp: (node: ReactElement, { ssr, page }: { ssr: boolean; page: InertiaPage }) => {\n const pending: Promise<unknown>[] = [];\n\n if (!ssr) {\n // Loaded on demand so apps without the shared i18n prop never ship the\n // i18next backend; the disabled-config call still stores the timezone.\n if (i18nEnabled && i18nConfigFromPageProps(page.props) !== undefined) {\n pending.push(\n import(\"./i18n/page-props\").then((module) =>\n module.configureI18nFromPageProps(page.props, i18n ?? {}),\n ),\n );\n }\n\n const booted = boot?.({ page });\n\n if (booted) {\n pending.push(booted);\n }\n }\n\n const inner = (\n <>\n {node}\n {i18nEnabled ? <LocaleReload /> : null}\n </>\n );\n\n // The whole shell waits, not just the page: anything rendering a\n // translated string (the Toaster included) would otherwise initialize\n // i18next before the backend can register — init runs exactly once,\n // first caller wins.\n const shell = (\n <ProviderBase registry={activeRegistry} sprite={sprite}>\n {wrap ? wrap(inner) : inner}\n </ProviderBase>\n );\n\n return pending.length > 0 ? (\n <AwaitReady ready={Promise.all(pending)}>{shell}</AwaitReady>\n ) : (\n shell\n );\n },\n });\n\n initializeTheme();\n\n return app;\n}\n"],"mappings":";;;;;;;;;;;;AAiEA,SAAS,WAAW,EAAE,OAAO,YAA8D;CACzF,MAAM,CAAC,SAAS,YAAY,SAAS,KAAK;CAE1C,gBAAgB;EACd,IAAI,SAAS;EACb,MAAM,eAAqB;GACzB,IAAI,QACF,SAAS,IAAI;EAEjB;EAEA,MAAW,KAAK,QAAQ,MAAM;EAE9B,aAAa;GACX,SAAS;EACX;CACF,GAAG,CAAC,KAAK,CAAC;CAEV,OAAO,UAAU,WAAW;AAC9B;;;;;;;;AASA,SAAgB,iBAAiB,EAC/B,UAAA,YACA,SACA,QACA,QAAQ,CAAC,GACT,eACA,aAAa,MACb,MACA,MACA,MACA,GAAG,mBACwB,CAAC,GAAG;CAC/B,MAAM,eAAe,cAAY;CACjC,MAAM,iBACJ,WAAW,QAAQ,SAAS,IAAI,eAAe,cAAc,GAAG,OAAO,IAAI;CAE7E,mBAAmB,cAAc;CAEjC,MAAM,cAAc,SAAS;CAC7B,MAAM,mBAAmB,eAAe,UAAU;CAClD,MAAM,WAAW,cACb;EACE,GAAG,eAAe;EAClB,eAAe,MAAc,YAC3B,iBAAiB,MAAM,mBAAmB,MAAM,OAAO,KAAK,OAAO;CACvE,IACA,eAAe;CAEnB,MAAM,MAAM,iBAAiB;EAC3B,GAAG;EACH;EACA;EACA,SAAS,mBAAmB,KAAK;EACjC,QAAQ,qBAAqB,EAAE,cAAc,CAAC;EAC9C,UAAU,MAAoB,EAAE,KAAK,WAAgD;GACnF,MAAM,UAA8B,CAAC;GAErC,IAAI,CAAC,KAAK;IAGR,IAAI,eAAe,wBAAwB,KAAK,KAAK,MAAM,KAAA,GACzD,QAAQ,KACN,OAAO,wBAAqB,MAAM,WAChC,OAAO,2BAA2B,KAAK,OAAO,QAAQ,CAAC,CAAC,CAC1D,CACF;IAGF,MAAM,SAAS,OAAO,EAAE,KAAK,CAAC;IAE9B,IAAI,QACF,QAAQ,KAAK,MAAM;GAEvB;GAEA,MAAM,QACJ,qBAAA,YAAA,EAAA,UAAA,CACG,MACA,cAAc,oBAAC,cAAD,CAAe,CAAA,IAAI,IAClC,EAAA,CAAA;GAOJ,MAAM,QACJ,oBAAC,cAAD;IAAc,UAAU;IAAwB;cAC7C,OAAO,KAAK,KAAK,IAAI;GACV,CAAA;GAGhB,OAAO,QAAQ,SAAS,IACtB,oBAAC,YAAD;IAAY,OAAO,QAAQ,IAAI,OAAO;cAAI;GAAkB,CAAA,IAE5D;EAEJ;CACF,CAAC;CAED,gBAAgB;CAEhB,OAAO;AACT"}
1
+ {"version":3,"file":"create-app.js","names":[],"sources":["../resources/js/create-app.tsx"],"sourcesContent":["import type { Page as InertiaPage, VisitOptions } from \"@inertiajs/core\";\nimport { createInertiaApp } from \"@inertiajs/react\";\nimport { useEffect, useState, type ReactElement, type ReactNode } from \"react\";\nimport { initializeTheme } from \"./appearance\";\nimport { extendRegistry, type Plugin, type PluginI18n, type Registry } from \"./core/registry\";\nimport { setDefaultRegistry } from \"./core/registry-context\";\nimport type { SpriteValue } from \"./icons/sprite\";\nimport { DEFAULT_NAMESPACE } from \"./i18n/instance\";\nimport { LocaleReload } from \"./i18n/locale-reload\";\nimport { i18nConfigFromPageProps } from \"./i18n/shared-props\";\nimport {\n createLayoutResolver,\n createPageResolver,\n withVisitHeaders,\n type CreateLayoutResolverOptions,\n type PageModules,\n} from \"./inertia\";\nimport { ProviderBase } from \"./provider-base\";\nimport { registry as defaultRegistry } from \"./registry\";\n\ntype InertiaAppOptions = NonNullable<Parameters<typeof createInertiaApp>[0]>;\n\nexport type CreateLatticeAppI18nOptions = {\n /**\n * i18next namespaces to load, e.g. `[\"lattice\", \"app\"]`. Defaults to the\n * package's own. Namespaces declared by plugins are merged in on top.\n */\n namespaces?: string[];\n};\n\nexport type CreateLatticeAppOptions = Omit<\n InertiaAppOptions,\n \"resolve\" | \"layout\" | \"setup\" | \"withApp\" | \"pages\"\n> & {\n registry?: Registry;\n /**\n * Component-package plugins to merge onto the registry — pass the\n * Composer-discovered `virtual:lattice/plugins` here to register vendor\n * components with no manual `extendRegistry` call. A plugin's declared\n * i18n namespace joins the i18n bootstrap automatically.\n */\n plugins?: Plugin[];\n sprite?: SpriteValue;\n /** Normal Inertia page modules, e.g. `import.meta.glob('./pages/**\\/*.tsx')`. */\n pages?: PageModules;\n defaultLayout?: CreateLayoutResolverOptions[\"defaultLayout\"];\n /**\n * Lattice's i18n bootstrap, on by default: when the backend shares the\n * `lattice.i18n` prop, the first render waits for the translation setup (no\n * flash of untranslated fallbacks), `LocaleReload` re-fetches the page after\n * a locale switch, and every visit carries the locale/timezone headers. The\n * i18next chunk only loads when the backend actually shares the prop. Pass\n * `false` to opt out entirely.\n */\n i18n?: CreateLatticeAppI18nOptions | false;\n /**\n * App bootstrap that needs the initial page — e.g. `configureEcho` from a\n * shared connection prop. Runs on the client before the first render; a\n * returned promise delays that render until it resolves.\n */\n boot?: (context: { page: InertiaPage }) => void | Promise<void>;\n /**\n * Compose providers or siblings around the app. Applied inside the Lattice\n * Provider, so the registry, sprite, and toaster contexts are available.\n */\n wrap?: (app: ReactElement) => ReactElement;\n};\n\nfunction withPluginNamespaces(\n options: CreateLatticeAppI18nOptions,\n entries: PluginI18n[],\n): CreateLatticeAppI18nOptions {\n if (entries.length === 0) {\n return options;\n }\n\n const namespaces = new Set([\n ...(options.namespaces ?? [DEFAULT_NAMESPACE]),\n ...entries.map((entry) => entry.namespace),\n ]);\n\n return { ...options, namespaces: [...namespaces] };\n}\n\n// Fail-open: a failed bootstrap renders the app anyway (with fallback strings)\n// rather than a blank page.\nfunction AwaitReady({ ready, children }: { ready: Promise<unknown>; children: ReactNode }) {\n const [isReady, setReady] = useState(false);\n\n useEffect(() => {\n let active = true;\n const reveal = (): void => {\n if (active) {\n setReady(true);\n }\n };\n\n void ready.then(reveal, reveal);\n\n return () => {\n active = false;\n };\n }, [ready]);\n\n return isReady ? children : null;\n}\n\n/**\n * Bootstrap an Inertia app with the Lattice shell: the page/layout resolvers\n * (server-driven Lattice pages and normal Inertia pages alike), the Provider —\n * registry, sprite, flash toasts via Lattice's own Toaster — theme\n * initialization, and the i18n bootstrap. Forwards any other createInertiaApp\n * option.\n */\nexport function createLatticeApp({\n registry,\n plugins,\n sprite,\n pages = {},\n defaultLayout,\n strictMode = true,\n i18n,\n boot,\n wrap,\n ...inertiaOptions\n}: CreateLatticeAppOptions = {}) {\n const baseRegistry = registry ?? defaultRegistry;\n const activeRegistry =\n plugins && plugins.length > 0 ? extendRegistry(baseRegistry, ...plugins) : baseRegistry;\n\n setDefaultRegistry(activeRegistry);\n\n const i18nEnabled = i18n !== false;\n const pluginI18n = plugins?.flatMap((plugin) => (plugin.i18n ? [plugin.i18n] : [])) ?? [];\n const i18nOptions = i18nEnabled ? withPluginNamespaces(i18n ?? {}, pluginI18n) : {};\n const userVisitOptions = inertiaOptions.defaults?.visitOptions;\n const defaults = i18nEnabled\n ? {\n ...inertiaOptions.defaults,\n visitOptions: (href: string, options: VisitOptions): VisitOptions =>\n withVisitHeaders(href, userVisitOptions?.(href, options) ?? options),\n }\n : inertiaOptions.defaults;\n\n const app = createInertiaApp({\n ...inertiaOptions,\n defaults,\n strictMode,\n resolve: createPageResolver(pages),\n layout: createLayoutResolver({ defaultLayout }),\n withApp: (node: ReactElement, { ssr, page }: { ssr: boolean; page: InertiaPage }) => {\n const pending: Promise<unknown>[] = [];\n\n if (!ssr) {\n // Loaded on demand so apps without the shared i18n prop never ship the\n // i18next backend; the disabled-config call still stores the timezone.\n if (i18nEnabled && i18nConfigFromPageProps(page.props) !== undefined) {\n pending.push(\n import(\"./i18n/page-props\").then((module) =>\n module.configureI18nFromPageProps(page.props, i18nOptions),\n ),\n );\n }\n\n const booted = boot?.({ page });\n\n if (booted) {\n pending.push(booted);\n }\n }\n\n const inner = (\n <>\n {node}\n {i18nEnabled ? <LocaleReload /> : null}\n </>\n );\n\n // The whole shell waits, not just the page: anything rendering a\n // translated string (the Toaster included) would otherwise initialize\n // i18next before the backend can register — init runs exactly once,\n // first caller wins.\n const shell = (\n <ProviderBase registry={activeRegistry} sprite={sprite}>\n {wrap ? wrap(inner) : inner}\n </ProviderBase>\n );\n\n return pending.length > 0 ? (\n <AwaitReady ready={Promise.all(pending)}>{shell}</AwaitReady>\n ) : (\n shell\n );\n },\n });\n\n initializeTheme();\n\n return app;\n}\n"],"mappings":";;;;;;;;;;;;;AAoEA,SAAS,qBACP,SACA,SAC6B;CAC7B,IAAI,QAAQ,WAAW,GACrB,OAAO;CAGT,MAAM,aAAa,IAAI,IAAI,CACzB,GAAI,QAAQ,cAAc,CAAA,SAAkB,GAC5C,GAAG,QAAQ,KAAK,UAAU,MAAM,SAAS,CAC3C,CAAC;CAED,OAAO;EAAE,GAAG;EAAS,YAAY,CAAC,GAAG,UAAU;CAAE;AACnD;AAIA,SAAS,WAAW,EAAE,OAAO,YAA8D;CACzF,MAAM,CAAC,SAAS,YAAY,SAAS,KAAK;CAE1C,gBAAgB;EACd,IAAI,SAAS;EACb,MAAM,eAAqB;GACzB,IAAI,QACF,SAAS,IAAI;EAEjB;EAEA,MAAW,KAAK,QAAQ,MAAM;EAE9B,aAAa;GACX,SAAS;EACX;CACF,GAAG,CAAC,KAAK,CAAC;CAEV,OAAO,UAAU,WAAW;AAC9B;;;;;;;;AASA,SAAgB,iBAAiB,EAC/B,UAAA,YACA,SACA,QACA,QAAQ,CAAC,GACT,eACA,aAAa,MACb,MACA,MACA,MACA,GAAG,mBACwB,CAAC,GAAG;CAC/B,MAAM,eAAe,cAAY;CACjC,MAAM,iBACJ,WAAW,QAAQ,SAAS,IAAI,eAAe,cAAc,GAAG,OAAO,IAAI;CAE7E,mBAAmB,cAAc;CAEjC,MAAM,cAAc,SAAS;CAC7B,MAAM,aAAa,SAAS,SAAS,WAAY,OAAO,OAAO,CAAC,OAAO,IAAI,IAAI,CAAC,CAAE,KAAK,CAAC;CACxF,MAAM,cAAc,cAAc,qBAAqB,QAAQ,CAAC,GAAG,UAAU,IAAI,CAAC;CAClF,MAAM,mBAAmB,eAAe,UAAU;CAClD,MAAM,WAAW,cACb;EACE,GAAG,eAAe;EAClB,eAAe,MAAc,YAC3B,iBAAiB,MAAM,mBAAmB,MAAM,OAAO,KAAK,OAAO;CACvE,IACA,eAAe;CAEnB,MAAM,MAAM,iBAAiB;EAC3B,GAAG;EACH;EACA;EACA,SAAS,mBAAmB,KAAK;EACjC,QAAQ,qBAAqB,EAAE,cAAc,CAAC;EAC9C,UAAU,MAAoB,EAAE,KAAK,WAAgD;GACnF,MAAM,UAA8B,CAAC;GAErC,IAAI,CAAC,KAAK;IAGR,IAAI,eAAe,wBAAwB,KAAK,KAAK,MAAM,KAAA,GACzD,QAAQ,KACN,OAAO,wBAAqB,MAAM,WAChC,OAAO,2BAA2B,KAAK,OAAO,WAAW,CAC3D,CACF;IAGF,MAAM,SAAS,OAAO,EAAE,KAAK,CAAC;IAE9B,IAAI,QACF,QAAQ,KAAK,MAAM;GAEvB;GAEA,MAAM,QACJ,qBAAA,YAAA,EAAA,UAAA,CACG,MACA,cAAc,oBAAC,cAAD,CAAe,CAAA,IAAI,IAClC,EAAA,CAAA;GAOJ,MAAM,QACJ,oBAAC,cAAD;IAAc,UAAU;IAAwB;cAC7C,OAAO,KAAK,KAAK,IAAI;GACV,CAAA;GAGhB,OAAO,QAAQ,SAAS,IACtB,oBAAC,YAAD;IAAY,OAAO,QAAQ,IAAI,OAAO;cAAI;GAAkB,CAAA,IAE5D;EAEJ;CACF,CAAC;CAED,gBAAgB;CAEhB,OAAO;AACT"}
@@ -1,5 +1,5 @@
1
- import { cn } from "../../../lib/utils.js";
2
1
  import { useT } from "../../../i18n/instance.js";
2
+ import { cn } from "../../../lib/utils.js";
3
3
  import { useFormContext } from "../../hooks/context.js";
4
4
  import { useFieldScope } from "../../hooks/field-scope.js";
5
5
  import { useFormValue } from "../../hooks/values.js";
@@ -1,5 +1,5 @@
1
- import { Icon } from "../../../icons/sprite.js";
2
1
  import { useT } from "../../../i18n/instance.js";
2
+ import { Icon } from "../../../icons/sprite.js";
3
3
  import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from "../../../ui/dropdown-menu.js";
4
4
  import { jsx, jsxs } from "react/jsx-runtime";
5
5
  //#region resources/js/form/components/fields/row-actions.tsx
@@ -1,7 +1,7 @@
1
+ import { useT } from "../../../i18n/instance.js";
1
2
  import { Icon } from "../../../icons/sprite.js";
2
3
  import { nodeKey } from "../../../core/nodes.js";
3
4
  import { RenderNode } from "../../../core/renderer.js";
4
- import { useT } from "../../../i18n/instance.js";
5
5
  import { FieldScopeProvider } from "../../hooks/field-scope.js";
6
6
  import { buildRowActions } from "./row-action-menu.js";
7
7
  import { RowActions } from "./row-actions.js";
@@ -1,8 +1,8 @@
1
+ import { useT } from "../../../i18n/instance.js";
1
2
  import { materializeSchema } from "../../../core/materialize.js";
2
3
  import { cn } from "../../../lib/utils.js";
3
4
  import { Icon } from "../../../icons/sprite.js";
4
5
  import { Renderer } from "../../../core/renderer.js";
5
- import { useT } from "../../../i18n/instance.js";
6
6
  import { useFormContext } from "../../hooks/context.js";
7
7
  import { useFieldScope } from "../../hooks/field-scope.js";
8
8
  import { useResolvedNode } from "../../hooks/resolved-nodes.js";
@@ -1,7 +1,7 @@
1
+ import { useT } from "../../../i18n/instance.js";
1
2
  import { Icon } from "../../../icons/sprite.js";
2
3
  import { nodeKey } from "../../../core/nodes.js";
3
4
  import { RenderNode } from "../../../core/renderer.js";
4
- import { useT } from "../../../i18n/instance.js";
5
5
  import { useMediaQuery } from "../../../lib/use-media-query.js";
6
6
  import { FieldScopeProvider } from "../../hooks/field-scope.js";
7
7
  import { TableCellProvider } from "../../hooks/row-layout-context.js";
@@ -1,7 +1,9 @@
1
1
  import { LATTICE_EVENT } from "../../core/event-names.js";
2
+ import { useT } from "../../i18n/instance.js";
2
3
  import { useWindowEvent } from "../../core/hooks/use-window-event.js";
3
4
  import { withHeaders } from "../../core/headers.js";
4
- import { useT } from "../../i18n/instance.js";
5
+ import { nodeKey } from "../../core/nodes.js";
6
+ import { RenderNode } from "../../core/renderer.js";
5
7
  import { FormProvider } from "../hooks/context.js";
6
8
  import { PrefillProvider } from "../hooks/prefill-context.js";
7
9
  import { ResolvedNodesProvider } from "../hooks/resolved-nodes.js";
@@ -13,6 +15,14 @@ import { Form } from "@inertiajs/react";
13
15
  import { useMemo } from "react";
14
16
  import { jsx, jsxs } from "react/jsx-runtime";
15
17
  //#region resources/js/form/components/form.tsx
18
+ var JUSTIFY_CLASS = {
19
+ start: "justify-start",
20
+ center: "justify-center",
21
+ end: "justify-end",
22
+ between: "justify-between",
23
+ around: "justify-around",
24
+ evenly: "justify-evenly"
25
+ };
16
26
  function FormResetListener({ componentId, reset }) {
17
27
  useWindowEvent(LATTICE_EVENT.resetForm, (event) => {
18
28
  const detail = event.detail;
@@ -20,7 +30,7 @@ function FormResetListener({ componentId, reset }) {
20
30
  });
21
31
  return null;
22
32
  }
23
- function FormBody({ action, children, componentRef, nodes, shouldRenderSubmitButton, submitLabel, summaryLabel }) {
33
+ function FormBody({ action, children, componentRef, nodes, shouldRenderSubmitButton, submitButtons, submitJustify, submitLabel, submitVariant, summaryLabel }) {
24
34
  const { nodes: resolvedNodes, markUserEdit } = useFormResolver(action, componentRef, nodes);
25
35
  return /* @__PURE__ */ jsx(PrefillProvider, {
26
36
  value: { markUserEdit },
@@ -29,10 +39,15 @@ function FormBody({ action, children, componentRef, nodes, shouldRenderSubmitBut
29
39
  children: /* @__PURE__ */ jsxs("div", {
30
40
  className: "flex flex-col gap-6",
31
41
  children: [children, shouldRenderSubmitButton && /* @__PURE__ */ jsx("div", {
32
- className: "flex justify-end rounded-lt border border-lt-border bg-lt-surface px-lt-gutter py-4 shadow-lt-sm",
33
- children: /* @__PURE__ */ jsx(FormSubmitButton, {
42
+ className: `flex gap-3 ${JUSTIFY_CLASS[submitJustify ?? "end"]}`,
43
+ children: submitButtons?.length ? submitButtons.map((button, index) => button.props.buttonType === "submit" ? /* @__PURE__ */ jsx(FormSubmitButton, {
44
+ label: button.props.label ?? submitLabel,
45
+ summaryLabel,
46
+ variant: button.props.variant ?? submitVariant ?? "default"
47
+ }, nodeKey(button, index)) : /* @__PURE__ */ jsx(RenderNode, { node: button }, nodeKey(button, index))) : /* @__PURE__ */ jsx(FormSubmitButton, {
34
48
  label: submitLabel,
35
- summaryLabel
49
+ summaryLabel,
50
+ variant: submitVariant ?? "default"
36
51
  })
37
52
  })]
38
53
  })
@@ -56,7 +71,10 @@ var FormComponent = ({ children, node }) => {
56
71
  ...state
57
72
  }), [fieldValues, state]);
58
73
  const shouldRenderSubmitButton = props.submitButton;
74
+ const submitButtons = props.submitButtons ?? void 0;
75
+ const submitJustify = props.submitJustify ?? void 0;
59
76
  const submitLabel = props.submitLabel ?? t("form.submit", "Submit");
77
+ const submitVariant = props.submitVariant ?? void 0;
60
78
  const summaryLabel = props.validationSummaryLabel;
61
79
  const validationTimeout = props.validationTimeout ?? void 0;
62
80
  return /* @__PURE__ */ jsx(Form, {
@@ -98,7 +116,10 @@ var FormComponent = ({ children, node }) => {
98
116
  componentRef,
99
117
  nodes: node.schema,
100
118
  shouldRenderSubmitButton,
119
+ submitButtons,
120
+ submitJustify,
101
121
  submitLabel,
122
+ submitVariant,
102
123
  summaryLabel,
103
124
  children
104
125
  })
@@ -1 +1 @@
1
- {"version":3,"file":"form.js","names":[],"sources":["../../../resources/js/form/components/form.tsx"],"sourcesContent":["import { Form as InertiaForm } from \"@inertiajs/react\";\nimport { withHeaders } from \"@lattice-php/lattice/core/headers\";\nimport { LATTICE_EVENT } from \"@lattice-php/lattice/core/event-names\";\nimport { useWindowEvent } from \"@lattice-php/lattice/core/hooks/use-window-event\";\nimport type { Node, RendererComponent } from \"@lattice-php/lattice/core/types\";\nimport { useT } from \"@lattice-php/lattice/i18n\";\nimport { useMemo } from \"react\";\nimport { FormSubmitButton } from \"./base/submit-button\";\nimport { FormProvider } from \"@lattice-php/lattice/form/hooks/context\";\nimport { collectFields } from \"@lattice-php/lattice/form/lib/collect-fields\";\nimport { PrefillProvider } from \"@lattice-php/lattice/form/hooks/prefill-context\";\nimport { ResolvedNodesProvider } from \"@lattice-php/lattice/form/hooks/resolved-nodes\";\nimport { useFormResolver } from \"@lattice-php/lattice/form/hooks/use-form-resolver\";\nimport { FormValuesProvider } from \"@lattice-php/lattice/form/hooks/values\";\n\nfunction FormResetListener({\n componentId,\n reset,\n}: {\n componentId?: string;\n reset: (...fields: string[]) => void;\n}) {\n useWindowEvent(LATTICE_EVENT.resetForm, (event) => {\n const detail = (event as CustomEvent<{ form: string | null }>).detail;\n\n if (!detail?.form || detail.form === componentId) {\n reset();\n }\n });\n\n return null;\n}\n\nfunction FormBody({\n action,\n children,\n componentRef,\n nodes,\n shouldRenderSubmitButton,\n submitLabel,\n summaryLabel,\n}: {\n action: string;\n children: React.ReactNode;\n componentRef: string;\n nodes: Node[] | undefined;\n shouldRenderSubmitButton: boolean;\n submitLabel: string;\n summaryLabel: string;\n}) {\n const { nodes: resolvedNodes, markUserEdit } = useFormResolver(action, componentRef, nodes);\n\n return (\n <PrefillProvider value={{ markUserEdit }}>\n <ResolvedNodesProvider nodes={resolvedNodes}>\n <div className=\"flex flex-col gap-6\">\n {children}\n\n {shouldRenderSubmitButton && (\n <div className=\"flex justify-end rounded-lt border border-lt-border bg-lt-surface px-lt-gutter py-4 shadow-lt-sm\">\n <FormSubmitButton label={submitLabel} summaryLabel={summaryLabel} />\n </div>\n )}\n </div>\n </ResolvedNodesProvider>\n </PrefillProvider>\n );\n}\n\nexport const FormComponent: RendererComponent<\"form\"> = ({ children, node }) => {\n const { t } = useT(\"lattice\");\n const props = node.props;\n const action = props.action ?? \"#\";\n const errorBag = props.errorBag;\n const componentRef = props.ref ?? \"\";\n const method = props.method ?? \"post\";\n const precognitive = props.precognitive;\n const resetOnError = props.resetOnError ?? false;\n const resetOnSuccess = props.resetOnSuccess ?? [];\n const state = props.state;\n const { labels: fieldLabels, values: fieldValues } = useMemo(\n () => collectFields(node.schema),\n [node.schema],\n );\n const initialValues = useMemo(() => ({ ...fieldValues, ...state }), [fieldValues, state]);\n const shouldRenderSubmitButton = props.submitButton;\n const submitLabel = props.submitLabel ?? t(\"form.submit\", \"Submit\");\n const summaryLabel = props.validationSummaryLabel;\n const validationTimeout = props.validationTimeout ?? undefined;\n\n return (\n <InertiaForm\n action={action}\n data-slot=\"form\"\n data-lattice-component={node.id}\n errorBag={errorBag}\n method={method}\n resetOnError={resetOnError}\n resetOnSuccess={resetOnSuccess}\n validationTimeout={precognitive ? validationTimeout : undefined}\n headers={withHeaders(componentRef)}\n className=\"mx-auto flex w-full max-w-2xl flex-col gap-6\"\n >\n {({ clearErrors, errors, processing, reset, validate }) => (\n <FormProvider\n value={{\n action,\n clearErrors: (field) => clearErrors(field),\n componentId: node.id,\n componentRef,\n errors: errors as Record<string, string | undefined>,\n fieldLabels,\n precognitive,\n processing,\n validate: (field) => validate(field),\n }}\n >\n <FormResetListener componentId={node.id} reset={reset} />\n\n {props.status && (\n <div className=\"text-center text-sm font-medium text-lt-success\">{props.status}</div>\n )}\n\n <FormValuesProvider initial={initialValues}>\n <FormBody\n action={action}\n componentRef={componentRef}\n nodes={node.schema}\n shouldRenderSubmitButton={shouldRenderSubmitButton}\n submitLabel={submitLabel}\n summaryLabel={summaryLabel}\n >\n {children}\n </FormBody>\n </FormValuesProvider>\n </FormProvider>\n )}\n </InertiaForm>\n );\n};\n"],"mappings":";;;;;;;;;;;;;;;AAeA,SAAS,kBAAkB,EACzB,aACA,SAIC;CACD,eAAe,cAAc,YAAY,UAAU;EACjD,MAAM,SAAU,MAA+C;EAE/D,IAAI,CAAC,QAAQ,QAAQ,OAAO,SAAS,aACnC,MAAM;CAEV,CAAC;CAED,OAAO;AACT;AAEA,SAAS,SAAS,EAChB,QACA,UACA,cACA,OACA,0BACA,aACA,gBASC;CACD,MAAM,EAAE,OAAO,eAAe,iBAAiB,gBAAgB,QAAQ,cAAc,KAAK;CAE1F,OACE,oBAAC,iBAAD;EAAiB,OAAO,EAAE,aAAa;YACrC,oBAAC,uBAAD;GAAuB,OAAO;aAC5B,qBAAC,OAAD;IAAK,WAAU;cAAf,CACG,UAEA,4BACC,oBAAC,OAAD;KAAK,WAAU;eACb,oBAAC,kBAAD;MAAkB,OAAO;MAA2B;KAAe,CAAA;IAChE,CAAA,CAEJ;;EACgB,CAAA;CACR,CAAA;AAErB;AAEA,IAAa,iBAA4C,EAAE,UAAU,WAAW;CAC9E,MAAM,EAAE,MAAM,KAAK,SAAS;CAC5B,MAAM,QAAQ,KAAK;CACnB,MAAM,SAAS,MAAM,UAAU;CAC/B,MAAM,WAAW,MAAM;CACvB,MAAM,eAAe,MAAM,OAAO;CAClC,MAAM,SAAS,MAAM,UAAU;CAC/B,MAAM,eAAe,MAAM;CAC3B,MAAM,eAAe,MAAM,gBAAgB;CAC3C,MAAM,iBAAiB,MAAM,kBAAkB,CAAC;CAChD,MAAM,QAAQ,MAAM;CACpB,MAAM,EAAE,QAAQ,aAAa,QAAQ,gBAAgB,cAC7C,cAAc,KAAK,MAAM,GAC/B,CAAC,KAAK,MAAM,CACd;CACA,MAAM,gBAAgB,eAAe;EAAE,GAAG;EAAa,GAAG;CAAM,IAAI,CAAC,aAAa,KAAK,CAAC;CACxF,MAAM,2BAA2B,MAAM;CACvC,MAAM,cAAc,MAAM,eAAe,EAAE,eAAe,QAAQ;CAClE,MAAM,eAAe,MAAM;CAC3B,MAAM,oBAAoB,MAAM,qBAAqB,KAAA;CAErD,OACE,oBAAC,MAAD;EACU;EACR,aAAU;EACV,0BAAwB,KAAK;EACnB;EACF;EACM;EACE;EAChB,mBAAmB,eAAe,oBAAoB,KAAA;EACtD,SAAS,YAAY,YAAY;EACjC,WAAU;aAER,EAAE,aAAa,QAAQ,YAAY,OAAO,eAC1C,qBAAC,cAAD;GACE,OAAO;IACL;IACA,cAAc,UAAU,YAAY,KAAK;IACzC,aAAa,KAAK;IAClB;IACQ;IACR;IACA;IACA;IACA,WAAW,UAAU,SAAS,KAAK;GACrC;aAXF;IAaE,oBAAC,mBAAD;KAAmB,aAAa,KAAK;KAAW;IAAQ,CAAA;IAEvD,MAAM,UACL,oBAAC,OAAD;KAAK,WAAU;eAAmD,MAAM;IAAY,CAAA;IAGtF,oBAAC,oBAAD;KAAoB,SAAS;eAC3B,oBAAC,UAAD;MACU;MACM;MACd,OAAO,KAAK;MACc;MACb;MACC;MAEb;KACO,CAAA;IACQ,CAAA;GACR;;CAEL,CAAA;AAEjB"}
1
+ {"version":3,"file":"form.js","names":[],"sources":["../../../resources/js/form/components/form.tsx"],"sourcesContent":["import { Form as InertiaForm } from \"@inertiajs/react\";\nimport { withHeaders } from \"@lattice-php/lattice/core/headers\";\nimport { LATTICE_EVENT } from \"@lattice-php/lattice/core/event-names\";\nimport { useWindowEvent } from \"@lattice-php/lattice/core/hooks/use-window-event\";\nimport { nodeKey } from \"@lattice-php/lattice/core/nodes\";\nimport { RenderNode } from \"@lattice-php/lattice/core/renderer\";\nimport type { Node, RendererComponent } from \"@lattice-php/lattice/core/types\";\nimport { useT } from \"@lattice-php/lattice/i18n\";\nimport type { ButtonVariant, Justify } from \"@lattice-php/lattice/types/generated\";\nimport { useMemo } from \"react\";\nimport { FormSubmitButton } from \"./base/submit-button\";\nimport { FormProvider } from \"@lattice-php/lattice/form/hooks/context\";\nimport { collectFields } from \"@lattice-php/lattice/form/lib/collect-fields\";\nimport { PrefillProvider } from \"@lattice-php/lattice/form/hooks/prefill-context\";\nimport { ResolvedNodesProvider } from \"@lattice-php/lattice/form/hooks/resolved-nodes\";\nimport { useFormResolver } from \"@lattice-php/lattice/form/hooks/use-form-resolver\";\nimport { FormValuesProvider } from \"@lattice-php/lattice/form/hooks/values\";\n\nconst JUSTIFY_CLASS: Record<Justify, string> = {\n start: \"justify-start\",\n center: \"justify-center\",\n end: \"justify-end\",\n between: \"justify-between\",\n around: \"justify-around\",\n evenly: \"justify-evenly\",\n};\n\nfunction FormResetListener({\n componentId,\n reset,\n}: {\n componentId?: string;\n reset: (...fields: string[]) => void;\n}) {\n useWindowEvent(LATTICE_EVENT.resetForm, (event) => {\n const detail = (event as CustomEvent<{ form: string | null }>).detail;\n\n if (!detail?.form || detail.form === componentId) {\n reset();\n }\n });\n\n return null;\n}\n\nfunction FormBody({\n action,\n children,\n componentRef,\n nodes,\n shouldRenderSubmitButton,\n submitButtons,\n submitJustify,\n submitLabel,\n submitVariant,\n summaryLabel,\n}: {\n action: string;\n children: React.ReactNode;\n componentRef: string;\n nodes: Node[] | undefined;\n shouldRenderSubmitButton: boolean;\n submitButtons: Node<\"button\">[] | undefined;\n submitJustify: Justify | undefined;\n submitLabel: string;\n submitVariant: ButtonVariant | undefined;\n summaryLabel: string;\n}) {\n const { nodes: resolvedNodes, markUserEdit } = useFormResolver(action, componentRef, nodes);\n\n return (\n <PrefillProvider value={{ markUserEdit }}>\n <ResolvedNodesProvider nodes={resolvedNodes}>\n <div className=\"flex flex-col gap-6\">\n {children}\n\n {shouldRenderSubmitButton && (\n <div className={`flex gap-3 ${JUSTIFY_CLASS[submitJustify ?? \"end\"]}`}>\n {submitButtons?.length ? (\n submitButtons.map((button, index) =>\n button.props.buttonType === \"submit\" ? (\n <FormSubmitButton\n key={nodeKey(button, index)}\n label={button.props.label ?? submitLabel}\n summaryLabel={summaryLabel}\n variant={button.props.variant ?? submitVariant ?? \"default\"}\n />\n ) : (\n <RenderNode key={nodeKey(button, index)} node={button} />\n ),\n )\n ) : (\n <FormSubmitButton\n label={submitLabel}\n summaryLabel={summaryLabel}\n variant={submitVariant ?? \"default\"}\n />\n )}\n </div>\n )}\n </div>\n </ResolvedNodesProvider>\n </PrefillProvider>\n );\n}\n\nexport const FormComponent: RendererComponent<\"form\"> = ({ children, node }) => {\n const { t } = useT(\"lattice\");\n const props = node.props;\n const action = props.action ?? \"#\";\n const errorBag = props.errorBag;\n const componentRef = props.ref ?? \"\";\n const method = props.method ?? \"post\";\n const precognitive = props.precognitive;\n const resetOnError = props.resetOnError ?? false;\n const resetOnSuccess = props.resetOnSuccess ?? [];\n const state = props.state;\n const { labels: fieldLabels, values: fieldValues } = useMemo(\n () => collectFields(node.schema),\n [node.schema],\n );\n const initialValues = useMemo(() => ({ ...fieldValues, ...state }), [fieldValues, state]);\n const shouldRenderSubmitButton = props.submitButton;\n const submitButtons = props.submitButtons ?? undefined;\n const submitJustify = props.submitJustify ?? undefined;\n const submitLabel = props.submitLabel ?? t(\"form.submit\", \"Submit\");\n const submitVariant = props.submitVariant ?? undefined;\n const summaryLabel = props.validationSummaryLabel;\n const validationTimeout = props.validationTimeout ?? undefined;\n\n return (\n <InertiaForm\n action={action}\n data-slot=\"form\"\n data-lattice-component={node.id}\n errorBag={errorBag}\n method={method}\n resetOnError={resetOnError}\n resetOnSuccess={resetOnSuccess}\n validationTimeout={precognitive ? validationTimeout : undefined}\n headers={withHeaders(componentRef)}\n className=\"mx-auto flex w-full max-w-2xl flex-col gap-6\"\n >\n {({ clearErrors, errors, processing, reset, validate }) => (\n <FormProvider\n value={{\n action,\n clearErrors: (field) => clearErrors(field),\n componentId: node.id,\n componentRef,\n errors: errors as Record<string, string | undefined>,\n fieldLabels,\n precognitive,\n processing,\n validate: (field) => validate(field),\n }}\n >\n <FormResetListener componentId={node.id} reset={reset} />\n\n {props.status && (\n <div className=\"text-center text-sm font-medium text-lt-success\">{props.status}</div>\n )}\n\n <FormValuesProvider initial={initialValues}>\n <FormBody\n action={action}\n componentRef={componentRef}\n nodes={node.schema}\n shouldRenderSubmitButton={shouldRenderSubmitButton}\n submitButtons={submitButtons}\n submitJustify={submitJustify}\n submitLabel={submitLabel}\n submitVariant={submitVariant}\n summaryLabel={summaryLabel}\n >\n {children}\n </FormBody>\n </FormValuesProvider>\n </FormProvider>\n )}\n </InertiaForm>\n );\n};\n"],"mappings":";;;;;;;;;;;;;;;;;AAkBA,IAAM,gBAAyC;CAC7C,OAAO;CACP,QAAQ;CACR,KAAK;CACL,SAAS;CACT,QAAQ;CACR,QAAQ;AACV;AAEA,SAAS,kBAAkB,EACzB,aACA,SAIC;CACD,eAAe,cAAc,YAAY,UAAU;EACjD,MAAM,SAAU,MAA+C;EAE/D,IAAI,CAAC,QAAQ,QAAQ,OAAO,SAAS,aACnC,MAAM;CAEV,CAAC;CAED,OAAO;AACT;AAEA,SAAS,SAAS,EAChB,QACA,UACA,cACA,OACA,0BACA,eACA,eACA,aACA,eACA,gBAYC;CACD,MAAM,EAAE,OAAO,eAAe,iBAAiB,gBAAgB,QAAQ,cAAc,KAAK;CAE1F,OACE,oBAAC,iBAAD;EAAiB,OAAO,EAAE,aAAa;YACrC,oBAAC,uBAAD;GAAuB,OAAO;aAC5B,qBAAC,OAAD;IAAK,WAAU;cAAf,CACG,UAEA,4BACC,oBAAC,OAAD;KAAK,WAAW,cAAc,cAAc,iBAAiB;eAC1D,eAAe,SACd,cAAc,KAAK,QAAQ,UACzB,OAAO,MAAM,eAAe,WAC1B,oBAAC,kBAAD;MAEE,OAAO,OAAO,MAAM,SAAS;MACf;MACd,SAAS,OAAO,MAAM,WAAW,iBAAiB;KACnD,GAJM,QAAQ,QAAQ,KAAK,CAI3B,IAED,oBAAC,YAAD,EAAyC,MAAM,OAAS,GAAvC,QAAQ,QAAQ,KAAK,CAAkB,CAE5D,IAEA,oBAAC,kBAAD;MACE,OAAO;MACO;MACd,SAAS,iBAAiB;KAC3B,CAAA;IAEA,CAAA,CAEJ;;EACgB,CAAA;CACR,CAAA;AAErB;AAEA,IAAa,iBAA4C,EAAE,UAAU,WAAW;CAC9E,MAAM,EAAE,MAAM,KAAK,SAAS;CAC5B,MAAM,QAAQ,KAAK;CACnB,MAAM,SAAS,MAAM,UAAU;CAC/B,MAAM,WAAW,MAAM;CACvB,MAAM,eAAe,MAAM,OAAO;CAClC,MAAM,SAAS,MAAM,UAAU;CAC/B,MAAM,eAAe,MAAM;CAC3B,MAAM,eAAe,MAAM,gBAAgB;CAC3C,MAAM,iBAAiB,MAAM,kBAAkB,CAAC;CAChD,MAAM,QAAQ,MAAM;CACpB,MAAM,EAAE,QAAQ,aAAa,QAAQ,gBAAgB,cAC7C,cAAc,KAAK,MAAM,GAC/B,CAAC,KAAK,MAAM,CACd;CACA,MAAM,gBAAgB,eAAe;EAAE,GAAG;EAAa,GAAG;CAAM,IAAI,CAAC,aAAa,KAAK,CAAC;CACxF,MAAM,2BAA2B,MAAM;CACvC,MAAM,gBAAgB,MAAM,iBAAiB,KAAA;CAC7C,MAAM,gBAAgB,MAAM,iBAAiB,KAAA;CAC7C,MAAM,cAAc,MAAM,eAAe,EAAE,eAAe,QAAQ;CAClE,MAAM,gBAAgB,MAAM,iBAAiB,KAAA;CAC7C,MAAM,eAAe,MAAM;CAC3B,MAAM,oBAAoB,MAAM,qBAAqB,KAAA;CAErD,OACE,oBAAC,MAAD;EACU;EACR,aAAU;EACV,0BAAwB,KAAK;EACnB;EACF;EACM;EACE;EAChB,mBAAmB,eAAe,oBAAoB,KAAA;EACtD,SAAS,YAAY,YAAY;EACjC,WAAU;aAER,EAAE,aAAa,QAAQ,YAAY,OAAO,eAC1C,qBAAC,cAAD;GACE,OAAO;IACL;IACA,cAAc,UAAU,YAAY,KAAK;IACzC,aAAa,KAAK;IAClB;IACQ;IACR;IACA;IACA;IACA,WAAW,UAAU,SAAS,KAAK;GACrC;aAXF;IAaE,oBAAC,mBAAD;KAAmB,aAAa,KAAK;KAAW;IAAQ,CAAA;IAEvD,MAAM,UACL,oBAAC,OAAD;KAAK,WAAU;eAAmD,MAAM;IAAY,CAAA;IAGtF,oBAAC,oBAAD;KAAoB,SAAS;eAC3B,oBAAC,UAAD;MACU;MACM;MACd,OAAO,KAAK;MACc;MACX;MACA;MACF;MACE;MACD;MAEb;KACO,CAAA;IACQ,CAAA;GACR;;CAEL,CAAA;AAEjB"}
@@ -1,5 +1,5 @@
1
- import { cn } from "../../lib/utils.js";
2
1
  import { useT } from "../../i18n/instance.js";
2
+ import { cn } from "../../lib/utils.js";
3
3
  import { Popover, PopoverContent, PopoverTrigger } from "../../ui/popover.js";
4
4
  import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from "../../ui/dropdown-menu.js";
5
5
  import { seedRichEditorExtension } from "./registry.js";
@@ -1,5 +1,5 @@
1
- import { localeHeader } from "./locale.js";
2
1
  import { setConfig } from "./config.js";
2
+ import { localeHeader } from "./locale.js";
3
3
  import { ensureI18n, i18n, preloadLanguages } from "./instance.js";
4
4
  import HttpBackend from "i18next-http-backend";
5
5
  //#region resources/js/i18n/backend.ts
@@ -1,7 +1,7 @@
1
- import { LocaleReload } from "./locale-reload.js";
2
- import { i18nConfigFromPageProps } from "./shared-props.js";
3
1
  import { currentLocale, localeHeader, setLocale, useLocale } from "./locale.js";
4
2
  import { i18n, translate, useT } from "./instance.js";
3
+ import { LocaleReload } from "./locale-reload.js";
4
+ import { i18nConfigFromPageProps } from "./shared-props.js";
5
5
  import { configureI18n, enableBackend } from "./backend.js";
6
6
  import { LocaleSwitcher, useLocaleOptions } from "./locale-switcher.js";
7
7
  import { configureI18nFromPageProps } from "./page-props.js";
@@ -1,4 +1,5 @@
1
1
  import { i18n as I18nInstance, InitOptions } from 'i18next';
2
+ export declare const DEFAULT_NAMESPACE = "lattice";
2
3
  type TranslationFunction = (key: string, defaultValue?: string, options?: Record<string, unknown>) => string;
3
4
  type TranslationResult = {
4
5
  t: TranslationFunction;
@@ -1,9 +1,9 @@
1
- import { currentLocale, subscribeLocale, useLocale } from "./locale.js";
2
1
  import { useConfig } from "./config.js";
2
+ import { currentLocale, subscribeLocale, useLocale } from "./locale.js";
3
3
  import { useCallback, useSyncExternalStore } from "react";
4
4
  import i18next from "i18next";
5
5
  //#region resources/js/i18n/instance.ts
6
- var NAMESPACE = "lattice";
6
+ var DEFAULT_NAMESPACE = "lattice";
7
7
  var i18n = i18next.createInstance();
8
8
  var initialization;
9
9
  var revision = 0;
@@ -38,8 +38,8 @@ function ensureI18n(extend) {
38
38
  const base = {
39
39
  lng: currentLocale(),
40
40
  fallbackLng: "en",
41
- ns: [NAMESPACE],
42
- defaultNS: NAMESPACE,
41
+ ns: [DEFAULT_NAMESPACE],
42
+ defaultNS: DEFAULT_NAMESPACE,
43
43
  interpolation: { escapeValue: false }
44
44
  };
45
45
  initialization = i18n.init(extend ? extend(base) : base);
@@ -90,6 +90,6 @@ function translate(namespace, key, defaultValue, options) {
90
90
  });
91
91
  }
92
92
  //#endregion
93
- export { ensureI18n, i18n, preloadLanguages, translate, useT };
93
+ export { DEFAULT_NAMESPACE, ensureI18n, i18n, preloadLanguages, translate, useT };
94
94
 
95
95
  //# 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 { currentLocale, subscribeLocale, useLocale } from \"./locale\";\n\nconst 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: [NAMESPACE],\n defaultNS: NAMESPACE,\n interpolation: { escapeValue: false },\n };\n\n initialization = i18n.init(extend ? extend(base) : base);\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":";;;;;AAKA,IAAM,YAAY;AAiBlB,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,SAAS;GACd,WAAW;GACX,eAAe,EAAE,aAAa,MAAM;EACtC;EAEA,iBAAiB,KAAK,KAAK,SAAS,OAAO,IAAI,IAAI,IAAI;CACzD;CAEA,OAAO;AACT;AAEA,iBAAiB,WAAW;CAC1B,WAAgB,EAAE,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 { 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 }\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":";;;;;AAKA,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;CACzD;CAEA,OAAO;AACT;AAEA,iBAAiB,WAAW;CAC1B,WAAgB,EAAE,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,5 +1,5 @@
1
- import { LATTICE_EVENT } from "../core/event-names.js";
2
1
  import { configTimezone, subscribeConfig } from "./config.js";
2
+ import { LATTICE_EVENT } from "../core/event-names.js";
3
3
  import { useSyncExternalStore } from "react";
4
4
  //#region resources/js/i18n/timezone.ts
5
5
  var fallback = "UTC";
@@ -1,8 +1,8 @@
1
+ import { useT } from "../../i18n/instance.js";
1
2
  import { cn } from "../../lib/utils.js";
2
3
  import { Icon } from "../../icons/sprite.js";
3
4
  import { RenderNode } from "../../core/renderer.js";
4
5
  import { onCallout } from "../../toast/callout.js";
5
- import { useT } from "../../i18n/instance.js";
6
6
  import { variantStyles } from "../../toast/variant-styles.js";
7
7
  import { useEffect, useState } from "react";
8
8
  import { jsx, jsxs } from "react/jsx-runtime";
@@ -1,5 +1,5 @@
1
- import { Icon } from "../../icons/sprite.js";
2
1
  import { useT } from "../../i18n/instance.js";
2
+ import { Icon } from "../../icons/sprite.js";
3
3
  import { jsx, jsxs } from "react/jsx-runtime";
4
4
  //#region resources/js/notifications/components/empty-state.tsx
5
5
  function EmptyState() {
@@ -1,7 +1,7 @@
1
+ import { useT } from "../../i18n/instance.js";
1
2
  import { cn } from "../../lib/utils.js";
2
3
  import { IconRenderer } from "../../icons/icon-renderer.js";
3
4
  import { RenderNode } from "../../core/renderer.js";
4
- import { useT } from "../../i18n/instance.js";
5
5
  import { Link } from "@inertiajs/react";
6
6
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
7
7
  //#region resources/js/notifications/components/notification-item.tsx
@@ -1,5 +1,5 @@
1
- import { Icon } from "../../icons/sprite.js";
2
1
  import { useT } from "../../i18n/instance.js";
2
+ import { Icon } from "../../icons/sprite.js";
3
3
  import { Popover, PopoverContent, PopoverTrigger } from "../../ui/popover.js";
4
4
  import { Dialog, DialogContent, DialogTitle } from "../../ui/dialog.js";
5
5
  import { Badge } from "../../ui/badge.js";
@@ -1,6 +1,6 @@
1
+ import { useT } from "../../i18n/instance.js";
1
2
  import { materializeSchema } from "../../core/materialize.js";
2
3
  import { Renderer } from "../../core/renderer.js";
3
- import { useT } from "../../i18n/instance.js";
4
4
  import { remoteJson } from "../../core/api.js";
5
5
  import { useEffect, useState } from "react";
6
6
  import { jsx, jsxs } from "react/jsx-runtime";
@@ -1,6 +1,6 @@
1
+ import { useT } from "../../../i18n/instance.js";
1
2
  import { cn } from "../../../lib/utils.js";
2
3
  import { Icon } from "../../../icons/sprite.js";
3
- import { useT } from "../../../i18n/instance.js";
4
4
  import { isTruthy } from "../../../lib/is-truthy.js";
5
5
  import { jsx } from "react/jsx-runtime";
6
6
  //#region resources/js/table/components/cells/boolean-cell.tsx
@@ -1,6 +1,6 @@
1
+ import { useT } from "../../i18n/instance.js";
1
2
  import { cn } from "../../lib/utils.js";
2
3
  import { Icon } from "../../icons/sprite.js";
3
- import { useT } from "../../i18n/instance.js";
4
4
  import { alignJustify, alignText } from "../lib/align.js";
5
5
  import { getColumnAriaSort, getColumnSort } from "../lib/query.js";
6
6
  import { jsx, jsxs } from "react/jsx-runtime";
@@ -1,6 +1,6 @@
1
+ import { useT } from "../../i18n/instance.js";
1
2
  import { cn } from "../../lib/utils.js";
2
3
  import { Renderer } from "../../core/renderer.js";
3
- import { useT } from "../../i18n/instance.js";
4
4
  import { FormProvider } from "../../form/hooks/context.js";
5
5
  import { PrefillProvider } from "../../form/hooks/prefill-context.js";
6
6
  import { getPath, setPath } from "../../form/lib/form-path.js";
@@ -1,6 +1,6 @@
1
+ import { useT } from "../../i18n/instance.js";
1
2
  import { cn } from "../../lib/utils.js";
2
3
  import { Icon } from "../../icons/sprite.js";
3
- import { useT } from "../../i18n/instance.js";
4
4
  import { Input } from "../../ui/input.js";
5
5
  import { IconButton } from "../../ui/icon-button.js";
6
6
  import { NativeSelect } from "../../ui/native-select.js";
@@ -1,5 +1,5 @@
1
- import { Icon } from "../../icons/sprite.js";
2
1
  import { useT } from "../../i18n/instance.js";
2
+ import { Icon } from "../../icons/sprite.js";
3
3
  import { IconButton } from "../../ui/icon-button.js";
4
4
  import { getSortDirectionLabel } from "../lib/query.js";
5
5
  import { jsx, jsxs } from "react/jsx-runtime";
@@ -1,6 +1,6 @@
1
+ import { useT } from "../../i18n/instance.js";
1
2
  import { cn } from "../../lib/utils.js";
2
3
  import { Icon } from "../../icons/sprite.js";
3
- import { useT } from "../../i18n/instance.js";
4
4
  import { useDebouncedCallback } from "../../lib/use-debounced-callback.js";
5
5
  import { Input } from "../../ui/input.js";
6
6
  import { IconButton } from "../../ui/icon-button.js";
@@ -1,7 +1,7 @@
1
+ import { useT } from "../../i18n/instance.js";
1
2
  import { cn } from "../../lib/utils.js";
2
3
  import { Icon } from "../../icons/sprite.js";
3
4
  import { RenderNode, Renderer } from "../../core/renderer.js";
4
- import { useT } from "../../i18n/instance.js";
5
5
  import { nodeIdentity } from "../../core/test-id.js";
6
6
  import { useColumnResizing } from "../../core/hooks/use-column-resizing.js";
7
7
  import { Checkbox } from "../../ui/checkbox.js";