@lattice-php/lattice 0.60.0 → 0.62.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 (96) hide show
  1. package/dist/create-app.js +3 -2
  2. package/dist/create-app.js.map +1 -1
  3. package/dist/event-bridge.js +1 -1
  4. package/dist/fragments/fragment.js +1 -1
  5. package/dist/index.d.ts +1 -3
  6. package/dist/index.js +3 -7
  7. package/dist/inertia-navigation.d.ts +6 -0
  8. package/dist/inertia-navigation.js +28 -4
  9. package/dist/inertia-navigation.js.map +1 -1
  10. package/dist/lattice.css +16 -0
  11. package/dist/layout/components/outlet.js.map +1 -1
  12. package/dist/layout/components/schema-layout.js +1 -1
  13. package/dist/layout/components/schema-layout.js.map +1 -1
  14. package/dist/layout/index.d.ts +0 -1
  15. package/dist/layout/index.js +1 -2
  16. package/dist/layout/plugin.js +1 -19
  17. package/dist/layout/plugin.js.map +1 -1
  18. package/dist/notifications/components/empty-state.js +1 -1
  19. package/dist/notifications/components/notification-item.js +3 -3
  20. package/dist/notifications/components/notification-item.js.map +1 -1
  21. package/dist/notifications/components/notification-list.js +1 -1
  22. package/dist/notifications/components/notification-list.js.map +1 -1
  23. package/dist/notifications/components/notifications-echo.js.map +1 -1
  24. package/dist/notifications/components/notifications-sheet.js +2 -2
  25. package/dist/notifications/components/notifications-sheet.js.map +1 -1
  26. package/dist/notifications/components/notifications.js +4 -4
  27. package/dist/notifications/components/notifications.js.map +1 -1
  28. package/dist/page.js +2 -1
  29. package/dist/page.js.map +1 -1
  30. package/dist/provider-base.d.ts +3 -1
  31. package/dist/provider-base.js +6 -5
  32. package/dist/provider-base.js.map +1 -1
  33. package/dist/realtime/subscriptions.js +3 -3
  34. package/dist/realtime/subscriptions.js.map +1 -1
  35. package/dist/remote/components/data-list.js +1 -1
  36. package/dist/runtime.d.ts +4 -4
  37. package/dist/runtime.js +6 -9
  38. package/dist/types/generated.d.ts +5 -39
  39. package/dist-standalone/chunks/chart-view-CJZkJAHB.js +59 -0
  40. package/dist-standalone/chunks/{date-picker-field-D_73rR_m.js → date-picker-view-p9mSMvwV.js} +1 -1
  41. package/dist-standalone/chunks/dist-Dd8dg4q5.js +106 -0
  42. package/dist-standalone/chunks/{field-CGZayHGR.js → pattern-input-view-CCPpYThT.js} +1 -1
  43. package/dist-standalone/chunks/rich-editor-view-CBCDtSzk.js +53 -0
  44. package/dist-standalone/chunks/runtime-DI3n1MuN.js +162 -0
  45. package/dist-standalone/chunks/{subscriptions-CJ3H8KiC.js → subscriptions-C1LRT5gZ.js} +1 -1
  46. package/dist-standalone/lattice.css +1 -1
  47. package/dist-standalone/lattice.js +1 -1
  48. package/dist-standalone/manifest.json +1 -1
  49. package/dist-standalone/runtime.js +1 -1
  50. package/dist-standalone/sprite.svg +1 -1
  51. package/package.json +7 -12
  52. package/dist/layout/components/breadcrumbs.d.ts +0 -3
  53. package/dist/layout/components/breadcrumbs.js +0 -41
  54. package/dist/layout/components/breadcrumbs.js.map +0 -1
  55. package/dist/layout/components/callouts.d.ts +0 -15
  56. package/dist/layout/components/callouts.js +0 -89
  57. package/dist/layout/components/callouts.js.map +0 -1
  58. package/dist/layout/components/dropdown.d.ts +0 -3
  59. package/dist/layout/components/dropdown.js +0 -24
  60. package/dist/layout/components/dropdown.js.map +0 -1
  61. package/dist/layout/components/menu-item.d.ts +0 -3
  62. package/dist/layout/components/menu-item.js +0 -137
  63. package/dist/layout/components/menu-item.js.map +0 -1
  64. package/dist/layout/components/menu.d.ts +0 -3
  65. package/dist/layout/components/menu.js +0 -14
  66. package/dist/layout/components/menu.js.map +0 -1
  67. package/dist/layout/components/popover.d.ts +0 -17
  68. package/dist/layout/components/popover.js +0 -46
  69. package/dist/layout/components/popover.js.map +0 -1
  70. package/dist/layout/components/sidebar-footer.d.ts +0 -3
  71. package/dist/layout/components/sidebar-footer.js +0 -12
  72. package/dist/layout/components/sidebar-footer.js.map +0 -1
  73. package/dist/layout/components/sidebar.d.ts +0 -3
  74. package/dist/layout/components/sidebar.js +0 -55
  75. package/dist/layout/components/sidebar.js.map +0 -1
  76. package/dist/layout/components/topbar.d.ts +0 -3
  77. package/dist/layout/components/topbar.js +0 -16
  78. package/dist/layout/components/topbar.js.map +0 -1
  79. package/dist/toast/callout.d.ts +0 -5
  80. package/dist/toast/callout.js +0 -31
  81. package/dist/toast/callout.js.map +0 -1
  82. package/dist/toast/index.d.ts +0 -6
  83. package/dist/toast/index.js +0 -5
  84. package/dist/toast/toast.d.ts +0 -7
  85. package/dist/toast/toast.js +0 -47
  86. package/dist/toast/toast.js.map +0 -1
  87. package/dist/toast/toaster.d.ts +0 -3
  88. package/dist/toast/toaster.js +0 -63
  89. package/dist/toast/toaster.js.map +0 -1
  90. package/dist/toast/variant-styles.d.ts +0 -6
  91. package/dist/toast/variant-styles.js +0 -51
  92. package/dist/toast/variant-styles.js.map +0 -1
  93. package/dist-standalone/chunks/chart-view-BxNPMybJ.js +0 -59
  94. package/dist-standalone/chunks/dist-DAHNiLp2.js +0 -106
  95. package/dist-standalone/chunks/rich-editor-field-Cp8zPFKl.js +0 -53
  96. package/dist-standalone/chunks/runtime-DGQM7tBp.js +0 -162
@@ -13,7 +13,7 @@ import { DEFAULT_NAMESPACE, UI_NAMESPACE, holdI18nInit } from "@lattice-php/ui/i
13
13
  import { LocaleReload } from "@lattice-php/ui/i18n/locale-reload";
14
14
  import { localeHeader } from "@lattice-php/ui/i18n/locale";
15
15
  import { i18nConfigFromPageProps } from "@lattice-php/ui/i18n/shared-props";
16
- import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
16
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
17
17
  //#region resources/js/create-app.tsx
18
18
  function withPluginNamespaces(options, entries) {
19
19
  const namespaces = /* @__PURE__ */ new Set([...options.namespaces ?? [DEFAULT_NAMESPACE, UI_NAMESPACE], ...entries.map((entry) => entry.namespace)]);
@@ -75,8 +75,9 @@ function createLatticeApp({ registry: registry$1, plugins, sprite, pages = {}, d
75
75
  const booted = boot?.({ page });
76
76
  if (booted) pending.push(booted);
77
77
  }
78
- const inner = /* @__PURE__ */ jsxs(Fragment$1, { children: [node, i18nEnabled ? /* @__PURE__ */ jsx(LocaleReload, {}) : null] });
78
+ const inner = /* @__PURE__ */ jsxs(Fragment, { children: [node, i18nEnabled ? /* @__PURE__ */ jsx(LocaleReload, {}) : null] });
79
79
  const shell = /* @__PURE__ */ jsx(ProviderBase, {
80
+ initialUrl: page.url,
80
81
  registry: activeRegistry,
81
82
  sprite,
82
83
  children: wrap ? wrap(inner) : inner
@@ -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 { initializeAppearance, seedAppearance } from \"./appearance\";\nimport { setRefRefreshEndpoint } from \"@lattice-php/core/api\";\nimport { setRequestHeaderProvider } from \"@lattice-php/core/headers\";\nimport { isRecord } from \"@lattice-php/core/materialize\";\nimport {\n extendRegistry,\n type Plugin,\n type PluginI18n,\n type Registry,\n} from \"@lattice-php/core/registry\";\nimport { setDefaultRegistry } from \"@lattice-php/core/registry-context\";\nimport type { SpriteValue } from \"@lattice-php/ui/icons/sprite\";\nimport { DEFAULT_NAMESPACE, holdI18nInit, UI_NAMESPACE } from \"@lattice-php/ui/i18n/instance\";\nimport { LocaleReload } from \"@lattice-php/ui/i18n/locale-reload\";\nimport { localeHeader } from \"@lattice-php/ui/i18n/locale\";\nimport { i18nConfigFromPageProps } from \"@lattice-php/ui/i18n/shared-props\";\nimport {\n createLayoutResolver,\n createPageResolver,\n registerRefRenewal,\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; a server-rendered page instead hydrates\n * immediately and swaps strings in once ready), `LocaleReload` re-fetches the\n * page after a locale switch, and every visit carries the locale/timezone\n * 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, except when\n * hydrating a server-rendered page (hydration must match the SSR'd HTML).\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 const namespaces = new Set([\n ...(options.namespaces ?? [DEFAULT_NAMESPACE, UI_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 setRequestHeaderProvider(localeHeader);\n registerRefRenewal();\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 const shared = page.props.lattice;\n let hydrating = false;\n\n if (isRecord(shared)) {\n seedAppearance(shared.appearance);\n }\n\n if (!ssr) {\n hydrating =\n document\n .getElementById(inertiaOptions.id ?? \"app\")\n ?.hasAttribute(\"data-server-rendered\") === true;\n\n if (\n isRecord(shared) &&\n isRecord(shared.urls) &&\n typeof shared.urls.refreshRef === \"string\"\n ) {\n setRefRefreshEndpoint(shared.urls.refreshRef);\n }\n\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(\"@lattice-php/ui/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 if (pending.length === 0) {\n return shell;\n }\n\n // A hydration pass must render what the server rendered — gating on the\n // bootstrap would hydrate null against the SSR'd markup. The hold still\n // lets the i18n backend win the init race; strings swap in once it resolves.\n if (hydrating) {\n holdI18nInit(Promise.all(pending));\n\n return shell;\n }\n\n return <AwaitReady ready={Promise.all(pending)}>{shell}</AwaitReady>;\n },\n });\n\n initializeAppearance();\n\n return app;\n}\n"],"mappings":"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"}
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 { initializeAppearance, seedAppearance } from \"./appearance\";\nimport { setRefRefreshEndpoint } from \"@lattice-php/core/api\";\nimport { setRequestHeaderProvider } from \"@lattice-php/core/headers\";\nimport { isRecord } from \"@lattice-php/core/materialize\";\nimport {\n extendRegistry,\n type Plugin,\n type PluginI18n,\n type Registry,\n} from \"@lattice-php/core/registry\";\nimport { setDefaultRegistry } from \"@lattice-php/core/registry-context\";\nimport type { SpriteValue } from \"@lattice-php/ui/icons/sprite\";\nimport { DEFAULT_NAMESPACE, holdI18nInit, UI_NAMESPACE } from \"@lattice-php/ui/i18n/instance\";\nimport { LocaleReload } from \"@lattice-php/ui/i18n/locale-reload\";\nimport { localeHeader } from \"@lattice-php/ui/i18n/locale\";\nimport { i18nConfigFromPageProps } from \"@lattice-php/ui/i18n/shared-props\";\nimport {\n createLayoutResolver,\n createPageResolver,\n registerRefRenewal,\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; a server-rendered page instead hydrates\n * immediately and swaps strings in once ready), `LocaleReload` re-fetches the\n * page after a locale switch, and every visit carries the locale/timezone\n * 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, except when\n * hydrating a server-rendered page (hydration must match the SSR'd HTML).\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 const namespaces = new Set([\n ...(options.namespaces ?? [DEFAULT_NAMESPACE, UI_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 setRequestHeaderProvider(localeHeader);\n registerRefRenewal();\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 const shared = page.props.lattice;\n let hydrating = false;\n\n if (isRecord(shared)) {\n seedAppearance(shared.appearance);\n }\n\n if (!ssr) {\n hydrating =\n document\n .getElementById(inertiaOptions.id ?? \"app\")\n ?.hasAttribute(\"data-server-rendered\") === true;\n\n if (\n isRecord(shared) &&\n isRecord(shared.urls) &&\n typeof shared.urls.refreshRef === \"string\"\n ) {\n setRefRefreshEndpoint(shared.urls.refreshRef);\n }\n\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(\"@lattice-php/ui/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 initialUrl={page.url} registry={activeRegistry} sprite={sprite}>\n {wrap ? wrap(inner) : inner}\n </ProviderBase>\n );\n\n if (pending.length === 0) {\n return shell;\n }\n\n // A hydration pass must render what the server rendered — gating on the\n // bootstrap would hydrate null against the SSR'd markup. The hold still\n // lets the i18n backend win the init race; strings swap in once it resolves.\n if (hydrating) {\n holdI18nInit(Promise.all(pending));\n\n return shell;\n }\n\n return <AwaitReady ready={Promise.all(pending)}>{shell}</AwaitReady>;\n },\n });\n\n initializeAppearance();\n\n return app;\n}\n"],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  import { isAppearance } from "./appearance/index.js";
2
- import { LATTICE_EVENT } from "@lattice-php/core/event-names";
3
2
  import { useWindowEvent } from "@lattice-php/core/hooks/use-window-event";
3
+ import { LATTICE_EVENT } from "@lattice-php/core/event-names";
4
4
  //#region resources/js/event-bridge.tsx
5
5
  function EventBridge({ onAppearanceChange }) {
6
6
  useWindowEvent(LATTICE_EVENT.appearanceChange, (event) => {
@@ -1,8 +1,8 @@
1
1
  import { useCallback, useEffect, useState } from "react";
2
2
  import { apiJson } from "@lattice-php/core/api";
3
+ import { jsx } from "react/jsx-runtime";
3
4
  import { Renderer } from "@lattice-php/core/renderer";
4
5
  import { LATTICE_EVENT } from "@lattice-php/core/event-names";
5
- import { jsx } from "react/jsx-runtime";
6
6
  import { Skeleton } from "@lattice-php/ui/primitives/skeleton";
7
7
  import { toNodes } from "@lattice-php/core/nodes";
8
8
  //#region resources/js/fragments/fragment.tsx
package/dist/index.d.ts CHANGED
@@ -9,9 +9,8 @@ export { createLatticeApp, type CreateLatticeAppI18nOptions, type CreateLatticeA
9
9
  export { EventBridge } from './event-bridge.js';
10
10
  export { Icon, IconRenderer, IconRendererProvider, SpriteProvider } from '@lattice-php/ui/icons';
11
11
  export { createLayoutResolver, createPageResolver, pageComponentName, withVisitHeaders, } from './inertia.js';
12
- export { Callouts, layoutComponents, OutletProvider, SchemaLayout, useOutlet } from './layout/index.js';
12
+ export { layoutComponents, OutletProvider, SchemaLayout, useOutlet } from './layout/index.js';
13
13
  export { Provider, useColumnRegistry, useComponentRegistry } from './provider.js';
14
- export { onCallout, onToast, Toaster } from './toast/index.js';
15
14
  export { createRegistry, eagerComponent, extendRegistry, lazyComponent, loadPluginModules, } from '@lattice-php/core/registry';
16
15
  export type { Plugin, Registry } from '@lattice-php/core/registry';
17
16
  export { Renderer } from '@lattice-php/core/renderer';
@@ -32,5 +31,4 @@ export type { ActionEffect, ActionResponse } from '@lattice-php/ui/effects/dispa
32
31
  export type { EffectHandler, EffectHandlerRegistry, EffectOf, EffectProps, EffectPropsOf, } from '@lattice-php/ui/effects/registry';
33
32
  export type { EditorExtensionPayloadOf, EditorExtensionProps, RichEditorExtensionDefinition, ToolbarButton, ToolbarControl, ToolbarItem, } from '@lattice-php/form/rich-editor/registry';
34
33
  export type { Appearance, ResolvedAppearance, UseAppearanceReturn } from './appearance/index.js';
35
- export type { Callout, ToastMessage, Variant } from './toast/index.js';
36
34
  export type { IconName, IconRendererFunction, IconRendererProps, KnownIcons, SpriteValue, } from '@lattice-php/ui/icons';
package/dist/index.js CHANGED
@@ -1,8 +1,4 @@
1
1
  import { initializeAppearance, updateAppearance, useAppearance } from "./appearance/index.js";
2
- import { onToast } from "./toast/toast.js";
3
- import { onCallout } from "./toast/callout.js";
4
- import { Toaster } from "./toast/toaster.js";
5
- import Callouts from "./layout/components/callouts.js";
6
2
  import { OutletProvider, useOutlet } from "./layout/hooks/context.js";
7
3
  import { layoutComponents } from "./layout/plugin.js";
8
4
  import SchemaLayout from "./layout/components/schema-layout.js";
@@ -15,12 +11,12 @@ import { Provider, useColumnRegistry, useComponentRegistry } from "./provider.js
15
11
  import { withHeaders } from "@lattice-php/core/headers";
16
12
  import { createRegistry, eagerComponent, extendRegistry, lazyComponent, loadPluginModules } from "@lattice-php/core/registry";
17
13
  import { LATTICE_REF_HEADER, withRefHeader } from "@lattice-php/core/component-ref";
18
- import { Icon, IconRenderer, IconRendererProvider, SpriteProvider } from "@lattice-php/ui/icons";
19
14
  import { Renderer } from "@lattice-php/core/renderer";
20
- import { LATTICE_EVENT } from "@lattice-php/core/event-names";
21
15
  import { dispatchActionError, dispatchEffects, getActionEffects, isActionEffect } from "@lattice-php/ui/effects/dispatch";
22
16
  import { useEffectDispatcher } from "@lattice-php/ui/effects/use-effect-dispatcher";
17
+ import { LATTICE_EVENT } from "@lattice-php/core/event-names";
23
18
  import { builtinEffectHandlers, effectHandler, mergeEffectHandlers } from "@lattice-php/ui/effects/registry";
19
+ import { Icon, IconRenderer, IconRendererProvider, SpriteProvider } from "@lattice-php/ui/icons";
24
20
  import { copyToClipboard } from "@lattice-php/ui/primitives/copyable-text";
25
21
  import { columnCell } from "@lattice-php/table/registry";
26
- export { Callouts, EventBridge, Icon, IconRenderer, IconRendererProvider, LATTICE_EVENT, LATTICE_REF_HEADER, OutletProvider, Provider, RealtimeListeners, Renderer, SchemaLayout, SpriteProvider, Toaster, builtinEffectHandlers, columnCell, copyToClipboard, createLatticeApp, createLayoutResolver, createPageResolver, createRegistry, dispatchActionError, dispatchEffects, eagerComponent, effectHandler, extendRegistry, getActionEffects, initializeAppearance, isActionEffect, layoutComponents, lazyComponent, loadPluginModules, mergeEffectHandlers, onCallout, onToast, pageComponentName, registry, updateAppearance, useAppearance, useColumnRegistry, useComponentRegistry, useEffectDispatcher, useOutlet, withHeaders, withRefHeader, withVisitHeaders };
22
+ export { EventBridge, Icon, IconRenderer, IconRendererProvider, LATTICE_EVENT, LATTICE_REF_HEADER, OutletProvider, Provider, RealtimeListeners, Renderer, SchemaLayout, SpriteProvider, builtinEffectHandlers, columnCell, copyToClipboard, createLatticeApp, createLayoutResolver, createPageResolver, createRegistry, dispatchActionError, dispatchEffects, eagerComponent, effectHandler, extendRegistry, getActionEffects, initializeAppearance, isActionEffect, layoutComponents, lazyComponent, loadPluginModules, mergeEffectHandlers, pageComponentName, registry, updateAppearance, useAppearance, useColumnRegistry, useComponentRegistry, useEffectDispatcher, useOutlet, withHeaders, withRefHeader, withVisitHeaders };
@@ -1,6 +1,12 @@
1
1
  import { Plugin } from '@lattice-php/core/registry';
2
2
  import { NavigationAdapter } from '@lattice-php/ui/navigation';
3
3
  export declare const inertiaNavigation: NavigationAdapter;
4
+ /**
5
+ * The Inertia-backed navigation adapter with a live `currentUrl`. The provider
6
+ * mounts outside Inertia's page context, so the url is seeded from the initial
7
+ * page and then tracked through the router's `navigate` event.
8
+ */
9
+ export declare function useInertiaNavigation(initialUrl?: string): NavigationAdapter;
4
10
  /**
5
11
  * An open modal must not survive the page it was opened on — its content can
6
12
  * hold stale props once the visit swaps in a new page. Inertia's `navigate`
@@ -1,7 +1,7 @@
1
1
  import { Link, router } from "@inertiajs/react";
2
- import { useEffect } from "react";
3
- import { LATTICE_EVENT } from "@lattice-php/core/event-names";
2
+ import { useEffect, useMemo, useState } from "react";
4
3
  import { jsx } from "react/jsx-runtime";
4
+ import { LATTICE_EVENT } from "@lattice-php/core/event-names";
5
5
  import { effectHandler } from "@lattice-php/ui/effects/registry";
6
6
  //#region resources/js/inertia-navigation.tsx
7
7
  function InertiaLink({ href, method = "get", children, ...props }) {
@@ -12,11 +12,35 @@ function InertiaLink({ href, method = "get", children, ...props }) {
12
12
  children
13
13
  });
14
14
  }
15
+ function onNavigate(listener) {
16
+ return router.on("navigate", listener);
17
+ }
15
18
  var inertiaNavigation = {
16
19
  Link: InertiaLink,
17
20
  visit: (url, options) => router.visit(url, options),
18
- reload: () => router.reload()
21
+ reload: () => router.reload(),
22
+ onNavigate
19
23
  };
24
+ function pathOf(url) {
25
+ return url.split(/[?#]/, 1)[0] ?? url;
26
+ }
27
+ function initialPath(initialUrl) {
28
+ if (initialUrl !== void 0) return pathOf(initialUrl);
29
+ return typeof window === "undefined" ? void 0 : window.location.pathname;
30
+ }
31
+ /**
32
+ * The Inertia-backed navigation adapter with a live `currentUrl`. The provider
33
+ * mounts outside Inertia's page context, so the url is seeded from the initial
34
+ * page and then tracked through the router's `navigate` event.
35
+ */
36
+ function useInertiaNavigation(initialUrl) {
37
+ const [currentUrl, setCurrentUrl] = useState(() => initialPath(initialUrl));
38
+ useEffect(() => router.on("navigate", (event) => setCurrentUrl(pathOf(event.detail.page.url))), []);
39
+ return useMemo(() => ({
40
+ ...inertiaNavigation,
41
+ currentUrl
42
+ }), [currentUrl]);
43
+ }
20
44
  function closeAllModals() {
21
45
  window.dispatchEvent(new CustomEvent(LATTICE_EVENT.closeModal, { detail: { modal: null } }));
22
46
  }
@@ -45,6 +69,6 @@ var navigationPlugin = {
45
69
  } }
46
70
  };
47
71
  //#endregion
48
- export { inertiaNavigation, navigationPlugin, useCloseModalsOnNavigate };
72
+ export { inertiaNavigation, navigationPlugin, useCloseModalsOnNavigate, useInertiaNavigation };
49
73
 
50
74
  //# sourceMappingURL=inertia-navigation.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"inertia-navigation.js","names":[],"sources":["../resources/js/inertia-navigation.tsx"],"sourcesContent":["import { Link, router } from \"@inertiajs/react\";\nimport { useEffect } from \"react\";\nimport type { Plugin } from \"@lattice-php/core/registry\";\nimport { LATTICE_EVENT } from \"@lattice-php/core/event-names\";\nimport { effectHandler } from \"@lattice-php/ui/effects/registry\";\nimport type { NavigationAdapter, NavLinkProps } from \"@lattice-php/ui/navigation\";\nimport type { ComponentProps } from \"react\";\n\nfunction InertiaLink({ href, method = \"get\", children, ...props }: NavLinkProps) {\n // NavLinkProps types handlers against HTMLAnchorElement; Inertia's Link\n // types them against Element. Same events at runtime, so the cast only\n // bridges React's generic variance.\n return (\n <Link href={href} method={method} {...(props as ComponentProps<typeof Link>)}>\n {children}\n </Link>\n );\n}\n\nexport const inertiaNavigation: NavigationAdapter = {\n Link: InertiaLink,\n visit: (url, options) => router.visit(url, options),\n reload: () => router.reload(),\n};\n\nfunction closeAllModals(): void {\n window.dispatchEvent(new CustomEvent(LATTICE_EVENT.closeModal, { detail: { modal: null } }));\n}\n\n/**\n * An open modal must not survive the page it was opened on — its content can\n * hold stale props once the visit swaps in a new page. Inertia's `navigate`\n * event only fires for a visit that actually swaps in a different page\n * (a new URL, or history back/forward); a same-URL visit — `router.reload()`,\n * partial reloads, polling — is internally marked as a `replace` and never\n * fires it. Subscribing to `navigate` alone is therefore already the correct\n * discriminator: a modal open during a same-page refresh is left untouched.\n */\nexport function useCloseModalsOnNavigate(): void {\n useEffect(() => router.on(\"navigate\", closeAllModals), []);\n}\n\n/**\n * SPA-grade redirect/reload effect handlers. Registered as an effects\n * extension so they override ui's window-based built-ins wherever the\n * framework registry is active.\n */\nexport const navigationPlugin: Plugin = {\n name: \"lattice/navigation\",\n extensions: {\n effects: {\n redirect: effectHandler(\"redirect\", (effect) => router.visit(effect.props.url)),\n \"reload-page\": effectHandler(\"reload-page\", (effect) =>\n effect.props.full ? window.location.reload() : router.reload(),\n ),\n },\n },\n};\n"],"mappings":";;;;;;AAQA,SAAS,YAAY,EAAE,MAAM,SAAS,OAAO,UAAU,GAAG,SAAuB;CAI/E,OACE,oBAAC,MAAD;EAAY;EAAc;EAAQ,GAAK;EACpC;CACG,CAAA;AAEV;AAEA,IAAa,oBAAuC;CAClD,MAAM;CACN,QAAQ,KAAK,YAAY,OAAO,MAAM,KAAK,OAAO;CAClD,cAAc,OAAO,OAAO;AAC9B;AAEA,SAAS,iBAAuB;CAC9B,OAAO,cAAc,IAAI,YAAY,cAAc,YAAY,EAAE,QAAQ,EAAE,OAAO,KAAK,EAAE,CAAC,CAAC;AAC7F;;;;;;;;;;AAWA,SAAgB,2BAAiC;CAC/C,gBAAgB,OAAO,GAAG,YAAY,cAAc,GAAG,CAAC,CAAC;AAC3D;;;;;;AAOA,IAAa,mBAA2B;CACtC,MAAM;CACN,YAAY,EACV,SAAS;EACP,UAAU,cAAc,aAAa,WAAW,OAAO,MAAM,OAAO,MAAM,GAAG,CAAC;EAC9E,eAAe,cAAc,gBAAgB,WAC3C,OAAO,MAAM,OAAO,OAAO,SAAS,OAAO,IAAI,OAAO,OAAO,CAC/D;CACF,EACF;AACF"}
1
+ {"version":3,"file":"inertia-navigation.js","names":[],"sources":["../resources/js/inertia-navigation.tsx"],"sourcesContent":["import { Link, router } from \"@inertiajs/react\";\nimport { useEffect, useMemo, useState } from \"react\";\nimport type { Plugin } from \"@lattice-php/core/registry\";\nimport { LATTICE_EVENT } from \"@lattice-php/core/event-names\";\nimport { effectHandler } from \"@lattice-php/ui/effects/registry\";\nimport type { NavigationAdapter, NavLinkProps } from \"@lattice-php/ui/navigation\";\nimport type { ComponentProps } from \"react\";\n\nfunction InertiaLink({ href, method = \"get\", children, ...props }: NavLinkProps) {\n // NavLinkProps types handlers against HTMLAnchorElement; Inertia's Link\n // types them against Element. Same events at runtime, so the cast only\n // bridges React's generic variance.\n return (\n <Link href={href} method={method} {...(props as ComponentProps<typeof Link>)}>\n {children}\n </Link>\n );\n}\n\nfunction onNavigate(listener: () => void): () => void {\n return router.on(\"navigate\", listener);\n}\n\nexport const inertiaNavigation: NavigationAdapter = {\n Link: InertiaLink,\n visit: (url, options) => router.visit(url, options),\n reload: () => router.reload(),\n onNavigate,\n};\n\nfunction pathOf(url: string): string {\n return url.split(/[?#]/, 1)[0] ?? url;\n}\n\nfunction initialPath(initialUrl: string | undefined): string | undefined {\n if (initialUrl !== undefined) {\n return pathOf(initialUrl);\n }\n\n return typeof window === \"undefined\" ? undefined : window.location.pathname;\n}\n\n/**\n * The Inertia-backed navigation adapter with a live `currentUrl`. The provider\n * mounts outside Inertia's page context, so the url is seeded from the initial\n * page and then tracked through the router's `navigate` event.\n */\nexport function useInertiaNavigation(initialUrl?: string): NavigationAdapter {\n const [currentUrl, setCurrentUrl] = useState(() => initialPath(initialUrl));\n\n useEffect(\n () => router.on(\"navigate\", (event) => setCurrentUrl(pathOf(event.detail.page.url))),\n [],\n );\n\n return useMemo(() => ({ ...inertiaNavigation, currentUrl }), [currentUrl]);\n}\n\nfunction closeAllModals(): void {\n window.dispatchEvent(new CustomEvent(LATTICE_EVENT.closeModal, { detail: { modal: null } }));\n}\n\n/**\n * An open modal must not survive the page it was opened on — its content can\n * hold stale props once the visit swaps in a new page. Inertia's `navigate`\n * event only fires for a visit that actually swaps in a different page\n * (a new URL, or history back/forward); a same-URL visit — `router.reload()`,\n * partial reloads, polling — is internally marked as a `replace` and never\n * fires it. Subscribing to `navigate` alone is therefore already the correct\n * discriminator: a modal open during a same-page refresh is left untouched.\n */\nexport function useCloseModalsOnNavigate(): void {\n useEffect(() => router.on(\"navigate\", closeAllModals), []);\n}\n\n/**\n * SPA-grade redirect/reload effect handlers. Registered as an effects\n * extension so they override ui's window-based built-ins wherever the\n * framework registry is active.\n */\nexport const navigationPlugin: Plugin = {\n name: \"lattice/navigation\",\n extensions: {\n effects: {\n redirect: effectHandler(\"redirect\", (effect) => router.visit(effect.props.url)),\n \"reload-page\": effectHandler(\"reload-page\", (effect) =>\n effect.props.full ? window.location.reload() : router.reload(),\n ),\n },\n },\n};\n"],"mappings":";;;;;;AAQA,SAAS,YAAY,EAAE,MAAM,SAAS,OAAO,UAAU,GAAG,SAAuB;CAI/E,OACE,oBAAC,MAAD;EAAY;EAAc;EAAQ,GAAK;EACpC;CACG,CAAA;AAEV;AAEA,SAAS,WAAW,UAAkC;CACpD,OAAO,OAAO,GAAG,YAAY,QAAQ;AACvC;AAEA,IAAa,oBAAuC;CAClD,MAAM;CACN,QAAQ,KAAK,YAAY,OAAO,MAAM,KAAK,OAAO;CAClD,cAAc,OAAO,OAAO;CAC5B;AACF;AAEA,SAAS,OAAO,KAAqB;CACnC,OAAO,IAAI,MAAM,QAAQ,CAAC,CAAC,CAAC,MAAM;AACpC;AAEA,SAAS,YAAY,YAAoD;CACvE,IAAI,eAAe,KAAA,GACjB,OAAO,OAAO,UAAU;CAG1B,OAAO,OAAO,WAAW,cAAc,KAAA,IAAY,OAAO,SAAS;AACrE;;;;;;AAOA,SAAgB,qBAAqB,YAAwC;CAC3E,MAAM,CAAC,YAAY,iBAAiB,eAAe,YAAY,UAAU,CAAC;CAE1E,gBACQ,OAAO,GAAG,aAAa,UAAU,cAAc,OAAO,MAAM,OAAO,KAAK,GAAG,CAAC,CAAC,GACnF,CAAC,CACH;CAEA,OAAO,eAAe;EAAE,GAAG;EAAmB;CAAW,IAAI,CAAC,UAAU,CAAC;AAC3E;AAEA,SAAS,iBAAuB;CAC9B,OAAO,cAAc,IAAI,YAAY,cAAc,YAAY,EAAE,QAAQ,EAAE,OAAO,KAAK,EAAE,CAAC,CAAC;AAC7F;;;;;;;;;;AAWA,SAAgB,2BAAiC;CAC/C,gBAAgB,OAAO,GAAG,YAAY,cAAc,GAAG,CAAC,CAAC;AAC3D;;;;;;AAOA,IAAa,mBAA2B;CACtC,MAAM;CACN,YAAY,EACV,SAAS;EACP,UAAU,cAAc,aAAa,WAAW,OAAO,MAAM,OAAO,MAAM,GAAG,CAAC;EAC9E,eAAe,cAAc,gBAAgB,WAC3C,OAAO,MAAM,OAAO,OAAO,SAAS,OAAO,IAAI,OAAO,OAAO,CAC/D;CACF,EACF;AACF"}
package/dist/lattice.css CHANGED
@@ -130,12 +130,28 @@
130
130
  --lt-sidebar-w: 16rem;
131
131
  --lt-sidebar-w-collapsed: 4rem;
132
132
  --lt-container-max: 80rem;
133
+ --lt-topbar-h: 3.5rem;
134
+
135
+ /* Viewport-top clearance for sticky content; a sticky topbar claims it below */
136
+ --lt-sticky-offset: 0px;
133
137
 
134
138
  /* Card / section content inset — the gutter apps can break out of */
135
139
  --lt-gutter: calc(var(--spacing) * 6);
136
140
 
141
+ /* Pinned table cells need an opaque background so scrolled content behind
142
+ them doesn't show through; these derive from --lt-bg/--lt-muted, so one
143
+ definition covers both themes. */
144
+ --lt-table-pinned-bg: var(--lt-bg);
145
+ --lt-table-pinned-muted-bg: color-mix(in oklab, var(--lt-muted) 50%, var(--lt-bg));
146
+ --lt-table-pinned-stripe-bg: color-mix(in oklab, var(--lt-muted) 30%, var(--lt-bg));
147
+ --lt-table-pinned-hover-bg: color-mix(in oklab, var(--lt-muted) 50%, var(--lt-bg));
148
+
137
149
  color-scheme: light;
138
150
  }
151
+
152
+ :root:has([data-lattice-topbar][data-sticky]) {
153
+ --lt-sticky-offset: var(--lt-topbar-h);
154
+ }
139
155
  }
140
156
 
141
157
  /*
@@ -1 +1 @@
1
- {"version":3,"file":"outlet.js","names":[],"sources":["../../../resources/js/layout/components/outlet.tsx"],"sourcesContent":["import type { RendererComponent } from \"@lattice-php/core/types\";\nimport { useOutlet } from \"@lattice-php/lattice/layout/hooks/context\";\n\n/**\n * Renders the active page at the position the layout schema places it.\n */\nconst OutletComponent: RendererComponent<\"outlet\"> = () => {\n return <>{useOutlet()}</>;\n};\n\nexport default OutletComponent;\n"],"mappings":";;;;;;AAMA,IAAM,wBAAqD;CACzD,OAAO,oBAAA,UAAA,EAAA,UAAG,UAAU,EAAI,CAAA;AAC1B"}
1
+ {"version":3,"file":"outlet.js","names":[],"sources":["../../../resources/js/layout/components/outlet.tsx"],"sourcesContent":["import type { RendererComponent } from \"@lattice-php/core/types\";\nimport { useOutlet } from \"../hooks/context\";\n\n/**\n * Renders the active page at the position the layout schema places it.\n */\nconst OutletComponent: RendererComponent<\"outlet\"> = () => {\n return <>{useOutlet()}</>;\n};\n\nexport default OutletComponent;\n"],"mappings":";;;;;;AAMA,IAAM,wBAAqD;CACzD,OAAO,oBAAA,UAAA,EAAA,UAAG,UAAU,EAAI,CAAA;AAC1B"}
@@ -1,7 +1,7 @@
1
1
  import { OutletProvider } from "../hooks/context.js";
2
2
  import { usePage } from "@inertiajs/react";
3
- import { Renderer } from "@lattice-php/core/renderer";
4
3
  import { Fragment, jsx } from "react/jsx-runtime";
4
+ import { Renderer } from "@lattice-php/core/renderer";
5
5
  //#region resources/js/layout/components/schema-layout.tsx
6
6
  /**
7
7
  * Persistent Inertia layout that renders a server-composed layout schema and
@@ -1 +1 @@
1
- {"version":3,"file":"schema-layout.js","names":[],"sources":["../../../resources/js/layout/components/schema-layout.tsx"],"sourcesContent":["import { usePage } from \"@inertiajs/react\";\nimport type { ReactNode } from \"react\";\nimport { Renderer } from \"@lattice-php/core/renderer\";\nimport type { PagePayload } from \"@lattice-php/lattice/types\";\nimport { OutletProvider } from \"@lattice-php/lattice/layout/hooks/context\";\n\n/**\n * Persistent Inertia layout that renders a server-composed layout schema and\n * exposes the active page (`children`) to the Outlet via context. The same\n * component instance is reused across navigations that share a layout, so\n * shell state (open sidebar, scroll position) survives page visits.\n */\nexport default function SchemaLayout({ children }: { children: ReactNode }) {\n const lattice = usePage().props.lattice as PagePayload;\n const layout = lattice.layout;\n\n if (!layout) {\n return <>{children}</>;\n }\n\n return (\n <OutletProvider outlet={children}>\n <Renderer nodes={layout.schema} />\n </OutletProvider>\n );\n}\n"],"mappings":";;;;;;;;;;;AAYA,SAAwB,aAAa,EAAE,YAAqC;CAE1E,MAAM,SADU,QAAQ,CAAC,CAAC,MAAM,QACT;CAEvB,IAAI,CAAC,QACH,OAAO,oBAAA,UAAA,EAAG,SAAW,CAAA;CAGvB,OACE,oBAAC,gBAAD;EAAgB,QAAQ;EACtB,UAAA,oBAAC,UAAD,EAAU,OAAO,OAAO,OAAS,CAAA;CACnB,CAAA;AAEpB"}
1
+ {"version":3,"file":"schema-layout.js","names":[],"sources":["../../../resources/js/layout/components/schema-layout.tsx"],"sourcesContent":["import { usePage } from \"@inertiajs/react\";\nimport type { ReactNode } from \"react\";\nimport { Renderer } from \"@lattice-php/core/renderer\";\nimport type { PagePayload } from \"@lattice-php/lattice/types\";\nimport { OutletProvider } from \"../hooks/context\";\n\n/**\n * Persistent Inertia layout that renders a server-composed layout schema and\n * exposes the active page (`children`) to the Outlet via context. The same\n * component instance is reused across navigations that share a layout, so\n * shell state (open sidebar, scroll position) survives page visits.\n */\nexport default function SchemaLayout({ children }: { children: ReactNode }) {\n const lattice = usePage().props.lattice as PagePayload;\n const layout = lattice.layout;\n\n if (!layout) {\n return <>{children}</>;\n }\n\n return (\n <OutletProvider outlet={children}>\n <Renderer nodes={layout.schema} />\n </OutletProvider>\n );\n}\n"],"mappings":";;;;;;;;;;;AAYA,SAAwB,aAAa,EAAE,YAAqC;CAE1E,MAAM,SADU,QAAQ,CAAC,CAAC,MAAM,QACT;CAEvB,IAAI,CAAC,QACH,OAAO,oBAAA,UAAA,EAAG,SAAW,CAAA;CAGvB,OACE,oBAAC,gBAAD;EAAgB,QAAQ;EACtB,UAAA,oBAAC,UAAD,EAAU,OAAO,OAAO,OAAS,CAAA;CACnB,CAAA;AAEpB"}
@@ -1,4 +1,3 @@
1
- export { default as Callouts } from './components/callouts.js';
2
1
  export { layoutComponents } from './plugin.js';
3
2
  export { OutletProvider, useOutlet } from './hooks/context.js';
4
3
  export { default as SchemaLayout } from './components/schema-layout.js';
@@ -1,5 +1,4 @@
1
- import Callouts from "./components/callouts.js";
2
1
  import { OutletProvider, useOutlet } from "./hooks/context.js";
3
2
  import { layoutComponents } from "./plugin.js";
4
3
  import SchemaLayout from "./components/schema-layout.js";
5
- export { Callouts, OutletProvider, SchemaLayout, layoutComponents, useOutlet };
4
+ export { OutletProvider, SchemaLayout, layoutComponents, useOutlet };
@@ -1,26 +1,8 @@
1
- import Callouts from "./components/callouts.js";
2
- import BreadcrumbsComponent from "./components/breadcrumbs.js";
3
- import DropdownComponent from "./components/dropdown.js";
4
- import MenuComponent from "./components/menu.js";
5
- import MenuItemComponent from "./components/menu-item.js";
6
1
  import OutletComponent from "./components/outlet.js";
7
- import SidebarComponent from "./components/sidebar.js";
8
- import SidebarFooterComponent from "./components/sidebar-footer.js";
9
- import TopbarComponent from "./components/topbar.js";
10
2
  import { eagerComponent } from "@lattice-php/core/registry";
11
3
  //#region resources/js/layout/plugin.ts
12
4
  var layoutComponents = {
13
- components: {
14
- breadcrumbs: eagerComponent(BreadcrumbsComponent),
15
- callouts: eagerComponent(Callouts),
16
- dropdown: eagerComponent(DropdownComponent),
17
- menu: eagerComponent(MenuComponent),
18
- "menu-item": eagerComponent(MenuItemComponent),
19
- outlet: eagerComponent(OutletComponent),
20
- sidebar: eagerComponent(SidebarComponent),
21
- "sidebar.footer": eagerComponent(SidebarFooterComponent),
22
- topbar: eagerComponent(TopbarComponent)
23
- },
5
+ components: { outlet: eagerComponent(OutletComponent) },
24
6
  name: "lattice/layout"
25
7
  };
26
8
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.js","names":[],"sources":["../../resources/js/layout/plugin.ts"],"sourcesContent":["import { eagerComponent, type ComponentRegistryFor, type Plugin } from \"@lattice-php/core/registry\";\nimport type { LayoutNodeType } from \"@lattice-php/lattice/types/generated\";\nimport BreadcrumbsComponent from \"./components/breadcrumbs\";\nimport CalloutsComponent from \"./components/callouts\";\nimport DropdownComponent from \"./components/dropdown\";\nimport MenuComponent from \"./components/menu\";\nimport MenuItemComponent from \"./components/menu-item\";\nimport OutletComponent from \"./components/outlet\";\nimport SidebarComponent from \"./components/sidebar\";\nimport SidebarFooterComponent from \"./components/sidebar-footer\";\nimport TopbarComponent from \"./components/topbar\";\n\nexport const layoutComponents: Plugin = {\n components: {\n breadcrumbs: eagerComponent(BreadcrumbsComponent),\n callouts: eagerComponent(CalloutsComponent),\n dropdown: eagerComponent(DropdownComponent),\n menu: eagerComponent(MenuComponent),\n \"menu-item\": eagerComponent(MenuItemComponent),\n outlet: eagerComponent(OutletComponent),\n sidebar: eagerComponent(SidebarComponent),\n \"sidebar.footer\": eagerComponent(SidebarFooterComponent),\n topbar: eagerComponent(TopbarComponent),\n } satisfies ComponentRegistryFor<LayoutNodeType>,\n name: \"lattice/layout\",\n};\n"],"mappings":";;;;;;;;;;;AAYA,IAAa,mBAA2B;CACtC,YAAY;EACV,aAAa,eAAe,oBAAoB;EAChD,UAAU,eAAe,QAAiB;EAC1C,UAAU,eAAe,iBAAiB;EAC1C,MAAM,eAAe,aAAa;EAClC,aAAa,eAAe,iBAAiB;EAC7C,QAAQ,eAAe,eAAe;EACtC,SAAS,eAAe,gBAAgB;EACxC,kBAAkB,eAAe,sBAAsB;EACvD,QAAQ,eAAe,eAAe;CACxC;CACA,MAAM;AACR"}
1
+ {"version":3,"file":"plugin.js","names":[],"sources":["../../resources/js/layout/plugin.ts"],"sourcesContent":["import { eagerComponent, type ComponentRegistryFor, type Plugin } from \"@lattice-php/core/registry\";\nimport type { LayoutNodeType } from \"@lattice-php/lattice/types/generated\";\nimport OutletComponent from \"./components/outlet\";\n\nexport const layoutComponents: Plugin = {\n components: {\n outlet: eagerComponent(OutletComponent),\n } satisfies ComponentRegistryFor<LayoutNodeType>,\n name: \"lattice/layout\",\n};\n"],"mappings":";;;AAIA,IAAa,mBAA2B;CACtC,YAAY,EACV,QAAQ,eAAe,eAAe,EACxC;CACA,MAAM;AACR"}
@@ -1,6 +1,6 @@
1
+ import { jsx, jsxs } from "react/jsx-runtime";
1
2
  import { Icon } from "@lattice-php/ui/icons";
2
3
  import { useT } from "@lattice-php/ui/i18n";
3
- import { jsx, jsxs } from "react/jsx-runtime";
4
4
  //#region resources/js/notifications/components/empty-state.tsx
5
5
  function EmptyState() {
6
6
  const { t } = useT("lattice");
@@ -1,10 +1,10 @@
1
1
  import { Link } from "@inertiajs/react";
2
- import { IconRenderer } from "@lattice-php/ui/icons";
2
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
3
3
  import { RenderNode } from "@lattice-php/core/renderer";
4
- import { resolveText } from "@lattice-php/ui/i18n/translatable";
5
4
  import { cn } from "@lattice-php/ui/lib/utils";
5
+ import { IconRenderer } from "@lattice-php/ui/icons";
6
6
  import { useT } from "@lattice-php/ui/i18n";
7
- import { Fragment, jsx, jsxs } from "react/jsx-runtime";
7
+ import { resolveText } from "@lattice-php/ui/i18n/translatable";
8
8
  //#region resources/js/notifications/components/notification-item.tsx
9
9
  var variantIconClass = {
10
10
  primary: "text-lt-primary",
@@ -1 +1 @@
1
- {"version":3,"file":"notification-item.js","names":[],"sources":["../../../resources/js/notifications/components/notification-item.tsx"],"sourcesContent":["import { Link } from \"@inertiajs/react\";\nimport { RenderNode } from \"@lattice-php/core/renderer\";\nimport { IconRenderer } from \"@lattice-php/ui/icons\";\nimport { useT } from \"@lattice-php/ui/i18n\";\nimport { resolveText } from \"@lattice-php/ui/i18n/translatable\";\nimport { cn } from \"@lattice-php/ui/lib/utils\";\nimport type { NotificationItem } from \"@lattice-php/lattice/notifications/types\";\n\nconst variantIconClass: Record<NonNullable<NotificationItem[\"variant\"]>, string> = {\n primary: \"text-lt-primary\",\n secondary: \"text-lt-muted-fg\",\n success: \"text-lt-success\",\n info: \"text-lt-info\",\n warning: \"text-lt-warning\",\n danger: \"text-lt-danger\",\n};\n\nexport function NotificationItemRow({\n notification,\n onMarkRead,\n onDismiss,\n}: {\n notification: NotificationItem;\n onMarkRead: (id: string) => void;\n onDismiss: (id: string) => void;\n}) {\n const { t } = useT(\"lattice\");\n\n const title = resolveText(notification.title, t);\n const body = resolveText(notification.body, t);\n\n const content = (\n <>\n {title ? <p className=\"truncate text-sm font-medium text-lt-fg\">{title}</p> : null}\n {body ? <p className=\"text-sm text-lt-muted-fg\">{body}</p> : null}\n </>\n );\n\n return (\n <li\n className={cn(\"flex gap-3 px-3 py-3\", !notification.isRead && \"bg-lt-muted/40\")}\n data-test=\"notification\"\n >\n {notification.icon ? (\n <IconRenderer\n icon={notification.icon}\n className={cn(\n \"mt-0.5 size-lt-icon-md\",\n notification.variant ? variantIconClass[notification.variant] : undefined,\n )}\n />\n ) : null}\n <div className=\"min-w-0 flex-1\">\n {notification.href ? (\n <Link\n href={notification.href}\n className=\"block\"\n data-test=\"notification-link\"\n onClick={() => onMarkRead(notification.id)}\n >\n {content}\n </Link>\n ) : (\n content\n )}\n {notification.actions.length > 0 ? (\n <div className=\"mt-2 flex flex-wrap gap-2\">\n {notification.actions.map((node, index) => (\n <RenderNode key={node.key ?? node.id ?? `action-${index}`} node={node} />\n ))}\n </div>\n ) : null}\n </div>\n <div className=\"flex shrink-0 flex-col gap-1\">\n {!notification.isRead ? (\n <button\n type=\"button\"\n className=\"text-xs text-lt-muted-fg hover:text-lt-fg\"\n onClick={() => onMarkRead(notification.id)}\n >\n {t(\"notifications.mark-read\", \"Mark read\")}\n </button>\n ) : null}\n <button\n type=\"button\"\n aria-label={t(\"notifications.dismiss\", \"Dismiss\")}\n className=\"text-xs text-lt-muted-fg hover:text-lt-fg\"\n onClick={() => onDismiss(notification.id)}\n >\n {t(\"notifications.dismiss\", \"Dismiss\")}\n </button>\n </div>\n </li>\n );\n}\n"],"mappings":";;;;;;;;AAQA,IAAM,mBAA6E;CACjF,SAAS;CACT,WAAW;CACX,SAAS;CACT,MAAM;CACN,SAAS;CACT,QAAQ;AACV;AAEA,SAAgB,oBAAoB,EAClC,cACA,YACA,aAKC;CACD,MAAM,EAAE,MAAM,KAAK,SAAS;CAE5B,MAAM,QAAQ,YAAY,aAAa,OAAO,CAAC;CAC/C,MAAM,OAAO,YAAY,aAAa,MAAM,CAAC;CAE7C,MAAM,UACJ,qBAAA,UAAA,EAAA,UAAA,CACG,QAAQ,oBAAC,KAAD;EAAG,WAAU;EAA2C,UAAA;CAAS,CAAA,IAAI,MAC7E,OAAO,oBAAC,KAAD;EAAG,WAAU;EAA4B,UAAA;CAAQ,CAAA,IAAI,IAC7D,EAAA,CAAA;CAGJ,OACE,qBAAC,MAAD;EACE,WAAW,GAAG,wBAAwB,CAAC,aAAa,UAAU,gBAAgB;EAC9E,aAAU;EAFZ,UAAA;GAIG,aAAa,OACZ,oBAAC,cAAD;IACE,MAAM,aAAa;IACnB,WAAW,GACT,0BACA,aAAa,UAAU,iBAAiB,aAAa,WAAW,KAAA,CAClE;GACD,CAAA,IACC;GACJ,qBAAC,OAAD;IAAK,WAAU;IAAf,UAAA,CACG,aAAa,OACZ,oBAAC,MAAD;KACE,MAAM,aAAa;KACnB,WAAU;KACV,aAAU;KACV,eAAe,WAAW,aAAa,EAAE;KAExC,UAAA;IACG,CAAA,IAEN,SAED,aAAa,QAAQ,SAAS,IAC7B,oBAAC,OAAD;KAAK,WAAU;KACZ,UAAA,aAAa,QAAQ,KAAK,MAAM,UAC/B,oBAAC,YAAD,EAAiE,KAAO,GAAvD,KAAK,OAAO,KAAK,MAAM,UAAU,OAAsB,CACzE;IACE,CAAA,IACH,IACD;;GACL,qBAAC,OAAD;IAAK,WAAU;IAAf,UAAA,CACG,CAAC,aAAa,SACb,oBAAC,UAAD;KACE,MAAK;KACL,WAAU;KACV,eAAe,WAAW,aAAa,EAAE;KAExC,UAAA,EAAE,2BAA2B,WAAW;IACnC,CAAA,IACN,MACJ,oBAAC,UAAD;KACE,MAAK;KACL,cAAY,EAAE,yBAAyB,SAAS;KAChD,WAAU;KACV,eAAe,UAAU,aAAa,EAAE;KAEvC,UAAA,EAAE,yBAAyB,SAAS;IAC/B,CAAA,CACL;;EACH;;AAER"}
1
+ {"version":3,"file":"notification-item.js","names":[],"sources":["../../../resources/js/notifications/components/notification-item.tsx"],"sourcesContent":["import { Link } from \"@inertiajs/react\";\nimport { RenderNode } from \"@lattice-php/core/renderer\";\nimport { IconRenderer } from \"@lattice-php/ui/icons\";\nimport { useT } from \"@lattice-php/ui/i18n\";\nimport { resolveText } from \"@lattice-php/ui/i18n/translatable\";\nimport { cn } from \"@lattice-php/ui/lib/utils\";\nimport type { NotificationItem } from \"../types\";\n\nconst variantIconClass: Record<NonNullable<NotificationItem[\"variant\"]>, string> = {\n primary: \"text-lt-primary\",\n secondary: \"text-lt-muted-fg\",\n success: \"text-lt-success\",\n info: \"text-lt-info\",\n warning: \"text-lt-warning\",\n danger: \"text-lt-danger\",\n};\n\nexport function NotificationItemRow({\n notification,\n onMarkRead,\n onDismiss,\n}: {\n notification: NotificationItem;\n onMarkRead: (id: string) => void;\n onDismiss: (id: string) => void;\n}) {\n const { t } = useT(\"lattice\");\n\n const title = resolveText(notification.title, t);\n const body = resolveText(notification.body, t);\n\n const content = (\n <>\n {title ? <p className=\"truncate text-sm font-medium text-lt-fg\">{title}</p> : null}\n {body ? <p className=\"text-sm text-lt-muted-fg\">{body}</p> : null}\n </>\n );\n\n return (\n <li\n className={cn(\"flex gap-3 px-3 py-3\", !notification.isRead && \"bg-lt-muted/40\")}\n data-test=\"notification\"\n >\n {notification.icon ? (\n <IconRenderer\n icon={notification.icon}\n className={cn(\n \"mt-0.5 size-lt-icon-md\",\n notification.variant ? variantIconClass[notification.variant] : undefined,\n )}\n />\n ) : null}\n <div className=\"min-w-0 flex-1\">\n {notification.href ? (\n <Link\n href={notification.href}\n className=\"block\"\n data-test=\"notification-link\"\n onClick={() => onMarkRead(notification.id)}\n >\n {content}\n </Link>\n ) : (\n content\n )}\n {notification.actions.length > 0 ? (\n <div className=\"mt-2 flex flex-wrap gap-2\">\n {notification.actions.map((node, index) => (\n <RenderNode key={node.key ?? node.id ?? `action-${index}`} node={node} />\n ))}\n </div>\n ) : null}\n </div>\n <div className=\"flex shrink-0 flex-col gap-1\">\n {!notification.isRead ? (\n <button\n type=\"button\"\n className=\"text-xs text-lt-muted-fg hover:text-lt-fg\"\n onClick={() => onMarkRead(notification.id)}\n >\n {t(\"notifications.mark-read\", \"Mark read\")}\n </button>\n ) : null}\n <button\n type=\"button\"\n aria-label={t(\"notifications.dismiss\", \"Dismiss\")}\n className=\"text-xs text-lt-muted-fg hover:text-lt-fg\"\n onClick={() => onDismiss(notification.id)}\n >\n {t(\"notifications.dismiss\", \"Dismiss\")}\n </button>\n </div>\n </li>\n );\n}\n"],"mappings":";;;;;;;;AAQA,IAAM,mBAA6E;CACjF,SAAS;CACT,WAAW;CACX,SAAS;CACT,MAAM;CACN,SAAS;CACT,QAAQ;AACV;AAEA,SAAgB,oBAAoB,EAClC,cACA,YACA,aAKC;CACD,MAAM,EAAE,MAAM,KAAK,SAAS;CAE5B,MAAM,QAAQ,YAAY,aAAa,OAAO,CAAC;CAC/C,MAAM,OAAO,YAAY,aAAa,MAAM,CAAC;CAE7C,MAAM,UACJ,qBAAA,UAAA,EAAA,UAAA,CACG,QAAQ,oBAAC,KAAD;EAAG,WAAU;EAA2C,UAAA;CAAS,CAAA,IAAI,MAC7E,OAAO,oBAAC,KAAD;EAAG,WAAU;EAA4B,UAAA;CAAQ,CAAA,IAAI,IAC7D,EAAA,CAAA;CAGJ,OACE,qBAAC,MAAD;EACE,WAAW,GAAG,wBAAwB,CAAC,aAAa,UAAU,gBAAgB;EAC9E,aAAU;EAFZ,UAAA;GAIG,aAAa,OACZ,oBAAC,cAAD;IACE,MAAM,aAAa;IACnB,WAAW,GACT,0BACA,aAAa,UAAU,iBAAiB,aAAa,WAAW,KAAA,CAClE;GACD,CAAA,IACC;GACJ,qBAAC,OAAD;IAAK,WAAU;IAAf,UAAA,CACG,aAAa,OACZ,oBAAC,MAAD;KACE,MAAM,aAAa;KACnB,WAAU;KACV,aAAU;KACV,eAAe,WAAW,aAAa,EAAE;KAExC,UAAA;IACG,CAAA,IAEN,SAED,aAAa,QAAQ,SAAS,IAC7B,oBAAC,OAAD;KAAK,WAAU;KACZ,UAAA,aAAa,QAAQ,KAAK,MAAM,UAC/B,oBAAC,YAAD,EAAiE,KAAO,GAAvD,KAAK,OAAO,KAAK,MAAM,UAAU,OAAsB,CACzE;IACE,CAAA,IACH,IACD;;GACL,qBAAC,OAAD;IAAK,WAAU;IAAf,UAAA,CACG,CAAC,aAAa,SACb,oBAAC,UAAD;KACE,MAAK;KACL,WAAU;KACV,eAAe,WAAW,aAAa,EAAE;KAExC,UAAA,EAAE,2BAA2B,WAAW;IACnC,CAAA,IACN,MACJ,oBAAC,UAAD;KACE,MAAK;KACL,cAAY,EAAE,yBAAyB,SAAS;KAChD,WAAU;KACV,eAAe,UAAU,aAAa,EAAE;KAEvC,UAAA,EAAE,yBAAyB,SAAS;IAC/B,CAAA,CACL;;EACH;;AAER"}
@@ -1,8 +1,8 @@
1
1
  import { EmptyState } from "./empty-state.js";
2
2
  import { NotificationItemRow } from "./notification-item.js";
3
- import { useT } from "@lattice-php/ui/i18n";
4
3
  import { jsx, jsxs } from "react/jsx-runtime";
5
4
  import { Skeleton } from "@lattice-php/ui/primitives/skeleton";
5
+ import { useT } from "@lattice-php/ui/i18n";
6
6
  //#region resources/js/notifications/components/notification-list.tsx
7
7
  function NotificationList({ notifications, status, hasMore, onMarkRead, onDismiss, onLoadMore }) {
8
8
  const { t } = useT("lattice");
@@ -1 +1 @@
1
- {"version":3,"file":"notification-list.js","names":[],"sources":["../../../resources/js/notifications/components/notification-list.tsx"],"sourcesContent":["import { Skeleton } from \"@lattice-php/ui/primitives/skeleton\";\nimport { useT } from \"@lattice-php/ui/i18n\";\nimport type { NotificationItem } from \"@lattice-php/lattice/notifications/types\";\nimport type { NotificationsStatus } from \"@lattice-php/lattice/notifications/store\";\nimport { EmptyState } from \"./empty-state\";\nimport { NotificationItemRow } from \"./notification-item\";\n\nexport function NotificationList({\n notifications,\n status,\n hasMore,\n onMarkRead,\n onDismiss,\n onLoadMore,\n}: {\n notifications: NotificationItem[];\n status: NotificationsStatus;\n hasMore: boolean;\n onMarkRead: (id: string) => void;\n onDismiss: (id: string) => void;\n onLoadMore: () => void;\n}) {\n const { t } = useT(\"lattice\");\n\n if (status === \"loading\" && notifications.length === 0) {\n return (\n <div className=\"space-y-2 p-3\">\n <Skeleton className=\"h-12 w-full\" />\n <Skeleton className=\"h-12 w-full\" />\n <Skeleton className=\"h-12 w-full\" />\n </div>\n );\n }\n\n if (notifications.length === 0) {\n return <EmptyState />;\n }\n\n return (\n <div className=\"max-h-96 overflow-y-auto\">\n <ul className=\"divide-y divide-lt-border\">\n {notifications.map((notification) => (\n <NotificationItemRow\n key={notification.id}\n notification={notification}\n onMarkRead={onMarkRead}\n onDismiss={onDismiss}\n />\n ))}\n </ul>\n {hasMore ? (\n <button\n type=\"button\"\n className=\"w-full py-2 text-sm text-lt-muted-fg hover:text-lt-fg\"\n onClick={onLoadMore}\n >\n {t(\"notifications.load-more\", \"Load more\")}\n </button>\n ) : null}\n </div>\n );\n}\n"],"mappings":";;;;;;AAOA,SAAgB,iBAAiB,EAC/B,eACA,QACA,SACA,YACA,WACA,cAQC;CACD,MAAM,EAAE,MAAM,KAAK,SAAS;CAE5B,IAAI,WAAW,aAAa,cAAc,WAAW,GACnD,OACE,qBAAC,OAAD;EAAK,WAAU;EAAf,UAAA;GACE,oBAAC,UAAD,EAAU,WAAU,cAAe,CAAA;GACnC,oBAAC,UAAD,EAAU,WAAU,cAAe,CAAA;GACnC,oBAAC,UAAD,EAAU,WAAU,cAAe,CAAA;EAChC;;CAIT,IAAI,cAAc,WAAW,GAC3B,OAAO,oBAAC,YAAD,CAAa,CAAA;CAGtB,OACE,qBAAC,OAAD;EAAK,WAAU;EAAf,UAAA,CACE,oBAAC,MAAD;GAAI,WAAU;GACX,UAAA,cAAc,KAAK,iBAClB,oBAAC,qBAAD;IAEgB;IACF;IACD;GACZ,GAJM,aAAa,EAInB,CACF;EACC,CAAA,GACH,UACC,oBAAC,UAAD;GACE,MAAK;GACL,WAAU;GACV,SAAS;GAER,UAAA,EAAE,2BAA2B,WAAW;EACnC,CAAA,IACN,IACD;;AAET"}
1
+ {"version":3,"file":"notification-list.js","names":[],"sources":["../../../resources/js/notifications/components/notification-list.tsx"],"sourcesContent":["import { Skeleton } from \"@lattice-php/ui/primitives/skeleton\";\nimport { useT } from \"@lattice-php/ui/i18n\";\nimport type { NotificationItem } from \"../types\";\nimport type { NotificationsStatus } from \"../store\";\nimport { EmptyState } from \"./empty-state\";\nimport { NotificationItemRow } from \"./notification-item\";\n\nexport function NotificationList({\n notifications,\n status,\n hasMore,\n onMarkRead,\n onDismiss,\n onLoadMore,\n}: {\n notifications: NotificationItem[];\n status: NotificationsStatus;\n hasMore: boolean;\n onMarkRead: (id: string) => void;\n onDismiss: (id: string) => void;\n onLoadMore: () => void;\n}) {\n const { t } = useT(\"lattice\");\n\n if (status === \"loading\" && notifications.length === 0) {\n return (\n <div className=\"space-y-2 p-3\">\n <Skeleton className=\"h-12 w-full\" />\n <Skeleton className=\"h-12 w-full\" />\n <Skeleton className=\"h-12 w-full\" />\n </div>\n );\n }\n\n if (notifications.length === 0) {\n return <EmptyState />;\n }\n\n return (\n <div className=\"max-h-96 overflow-y-auto\">\n <ul className=\"divide-y divide-lt-border\">\n {notifications.map((notification) => (\n <NotificationItemRow\n key={notification.id}\n notification={notification}\n onMarkRead={onMarkRead}\n onDismiss={onDismiss}\n />\n ))}\n </ul>\n {hasMore ? (\n <button\n type=\"button\"\n className=\"w-full py-2 text-sm text-lt-muted-fg hover:text-lt-fg\"\n onClick={onLoadMore}\n >\n {t(\"notifications.load-more\", \"Load more\")}\n </button>\n ) : null}\n </div>\n );\n}\n"],"mappings":";;;;;;AAOA,SAAgB,iBAAiB,EAC/B,eACA,QACA,SACA,YACA,WACA,cAQC;CACD,MAAM,EAAE,MAAM,KAAK,SAAS;CAE5B,IAAI,WAAW,aAAa,cAAc,WAAW,GACnD,OACE,qBAAC,OAAD;EAAK,WAAU;EAAf,UAAA;GACE,oBAAC,UAAD,EAAU,WAAU,cAAe,CAAA;GACnC,oBAAC,UAAD,EAAU,WAAU,cAAe,CAAA;GACnC,oBAAC,UAAD,EAAU,WAAU,cAAe,CAAA;EAChC;;CAIT,IAAI,cAAc,WAAW,GAC3B,OAAO,oBAAC,YAAD,CAAa,CAAA;CAGtB,OACE,qBAAC,OAAD;EAAK,WAAU;EAAf,UAAA,CACE,oBAAC,MAAD;GAAI,WAAU;GACX,UAAA,cAAc,KAAK,iBAClB,oBAAC,qBAAD;IAEgB;IACF;IACD;GACZ,GAJM,aAAa,EAInB,CACF;EACC,CAAA,GACH,UACC,oBAAC,UAAD;GACE,MAAK;GACL,WAAU;GACV,SAAS;GAER,UAAA,EAAE,2BAA2B,WAAW;EACnC,CAAA,IACN,IACD;;AAET"}
@@ -1 +1 @@
1
- {"version":3,"file":"notifications-echo.js","names":[],"sources":["../../../resources/js/notifications/components/notifications-echo.tsx"],"sourcesContent":["import { useEchoNotification } from \"@laravel/echo-react\";\nimport type { NotificationItem } from \"@lattice-php/lattice/notifications/types\";\n\nexport function NotificationsEcho({\n channel,\n onReceive,\n}: {\n channel: string;\n onReceive: (item: NotificationItem) => void;\n}) {\n useEchoNotification<Partial<NotificationItem>>(channel, (payload) => {\n onReceive({\n id: payload.id,\n title: payload.title ?? null,\n body: payload.body ?? null,\n icon: payload.icon ?? null,\n variant: payload.variant ?? null,\n href: payload.href ?? null,\n isRead: false,\n createdAt: null,\n actions: [],\n });\n });\n\n return null;\n}\n"],"mappings":";;AAGA,SAAgB,kBAAkB,EAChC,SACA,aAIC;CACD,oBAA+C,UAAU,YAAY;EACnE,UAAU;GACR,IAAI,QAAQ;GACZ,OAAO,QAAQ,SAAS;GACxB,MAAM,QAAQ,QAAQ;GACtB,MAAM,QAAQ,QAAQ;GACtB,SAAS,QAAQ,WAAW;GAC5B,MAAM,QAAQ,QAAQ;GACtB,QAAQ;GACR,WAAW;GACX,SAAS,CAAC;EACZ,CAAC;CACH,CAAC;CAED,OAAO;AACT"}
1
+ {"version":3,"file":"notifications-echo.js","names":[],"sources":["../../../resources/js/notifications/components/notifications-echo.tsx"],"sourcesContent":["import { useEchoNotification } from \"@laravel/echo-react\";\nimport type { NotificationItem } from \"../types\";\n\nexport function NotificationsEcho({\n channel,\n onReceive,\n}: {\n channel: string;\n onReceive: (item: NotificationItem) => void;\n}) {\n useEchoNotification<Partial<NotificationItem>>(channel, (payload) => {\n onReceive({\n id: payload.id,\n title: payload.title ?? null,\n body: payload.body ?? null,\n icon: payload.icon ?? null,\n variant: payload.variant ?? null,\n href: payload.href ?? null,\n isRead: false,\n createdAt: null,\n actions: [],\n });\n });\n\n return null;\n}\n"],"mappings":";;AAGA,SAAgB,kBAAkB,EAChC,SACA,aAIC;CACD,oBAA+C,UAAU,YAAY;EACnE,UAAU;GACR,IAAI,QAAQ;GACZ,OAAO,QAAQ,SAAS;GACxB,MAAM,QAAQ,QAAQ;GACtB,MAAM,QAAQ,QAAQ;GACtB,SAAS,QAAQ,WAAW;GAC5B,MAAM,QAAQ,QAAQ;GACtB,QAAQ;GACR,WAAW;GACX,SAAS,CAAC;EACZ,CAAC;CACH,CAAC;CAED,OAAO;AACT"}
@@ -1,8 +1,8 @@
1
1
  import { useLiveNotifications } from "../context.js";
2
2
  import { NotificationList } from "./notification-list.js";
3
- import { useT } from "@lattice-php/ui/i18n";
4
3
  import { jsx, jsxs } from "react/jsx-runtime";
5
- import { MODAL_MISSING_ERROR, useEmbeddedModal } from "@lattice-php/ui/modal";
4
+ import { MODAL_MISSING_ERROR, useEmbeddedModal } from "@lattice-php/ui/components/modal/modal-host";
5
+ import { useT } from "@lattice-php/ui/i18n";
6
6
  import { Dialog, DialogContent, DialogTitle } from "@lattice-php/ui/primitives/dialog";
7
7
  //#region resources/js/notifications/components/notifications-sheet.tsx
8
8
  function NotificationsSheet({ onClosed }) {
@@ -1 +1 @@
1
- {"version":3,"file":"notifications-sheet.js","names":[],"sources":["../../../resources/js/notifications/components/notifications-sheet.tsx"],"sourcesContent":["import { Dialog, DialogContent, DialogTitle } from \"@lattice-php/ui/primitives/dialog\";\nimport { useT } from \"@lattice-php/ui/i18n\";\nimport { MODAL_MISSING_ERROR, useEmbeddedModal } from \"@lattice-php/ui/modal\";\nimport { useLiveNotifications } from \"../context\";\nimport { NotificationList } from \"./notification-list\";\n\nexport function NotificationsSheet({ onClosed }: { onClosed: () => void }) {\n const context = useEmbeddedModal();\n\n if (!context) {\n throw new Error(MODAL_MISSING_ERROR);\n }\n\n const store = useLiveNotifications();\n const { t } = useT(\"lattice\");\n const label = t(\"notifications.label\", \"Notifications\");\n const heading = t(\"notifications.heading\", \"Notifications\");\n\n return (\n <Dialog open={context.open} onOpenChange={context.onOpenChange}>\n <DialogContent\n aria-describedby={undefined}\n className=\"p-0\"\n onCloseAutoFocus={(event) => {\n context.onExited(event);\n onClosed();\n }}\n placement=\"end\"\n width=\"sm\"\n >\n <DialogTitle className=\"sr-only\">{label}</DialogTitle>\n <div className=\"w-full\" data-test=\"notifications-panel\">\n <div className=\"flex items-center justify-between border-b border-lt-border px-3 py-2\">\n <span className=\"text-sm font-medium\">{heading}</span>\n {store.unreadCount > 0 ? (\n <button\n type=\"button\"\n className=\"text-xs text-lt-muted-fg hover:text-lt-fg\"\n onClick={store.markAllRead}\n >\n {t(\"notifications.mark-all-read\", \"Mark all read\")}\n </button>\n ) : null}\n </div>\n <NotificationList\n notifications={store.notifications}\n status={store.status}\n hasMore={store.hasMore}\n onMarkRead={store.markRead}\n onDismiss={store.dismiss}\n onLoadMore={store.loadMore}\n />\n </div>\n </DialogContent>\n </Dialog>\n );\n}\n"],"mappings":";;;;;;;AAMA,SAAgB,mBAAmB,EAAE,YAAsC;CACzE,MAAM,UAAU,iBAAiB;CAEjC,IAAI,CAAC,SACH,MAAM,IAAI,MAAM,mBAAmB;CAGrC,MAAM,QAAQ,qBAAqB;CACnC,MAAM,EAAE,MAAM,KAAK,SAAS;CAC5B,MAAM,QAAQ,EAAE,uBAAuB,eAAe;CACtD,MAAM,UAAU,EAAE,yBAAyB,eAAe;CAE1D,OACE,oBAAC,QAAD;EAAQ,MAAM,QAAQ;EAAM,cAAc,QAAQ;EAChD,UAAA,qBAAC,eAAD;GACE,oBAAkB,KAAA;GAClB,WAAU;GACV,mBAAmB,UAAU;IAC3B,QAAQ,SAAS,KAAK;IACtB,SAAS;GACX;GACA,WAAU;GACV,OAAM;GARR,UAAA,CAUE,oBAAC,aAAD;IAAa,WAAU;IAAW,UAAA;GAAmB,CAAA,GACrD,qBAAC,OAAD;IAAK,WAAU;IAAS,aAAU;IAAlC,UAAA,CACE,qBAAC,OAAD;KAAK,WAAU;KAAf,UAAA,CACE,oBAAC,QAAD;MAAM,WAAU;MAAuB,UAAA;KAAc,CAAA,GACpD,MAAM,cAAc,IACnB,oBAAC,UAAD;MACE,MAAK;MACL,WAAU;MACV,SAAS,MAAM;MAEd,UAAA,EAAE,+BAA+B,eAAe;KAC3C,CAAA,IACN,IACD;IACL,CAAA,GAAA,oBAAC,kBAAD;KACE,eAAe,MAAM;KACrB,QAAQ,MAAM;KACd,SAAS,MAAM;KACf,YAAY,MAAM;KAClB,WAAW,MAAM;KACjB,YAAY,MAAM;IACnB,CAAA,CACE;GACQ,CAAA,CAAA;;CACT,CAAA;AAEZ"}
1
+ {"version":3,"file":"notifications-sheet.js","names":[],"sources":["../../../resources/js/notifications/components/notifications-sheet.tsx"],"sourcesContent":["import { Dialog, DialogContent, DialogTitle } from \"@lattice-php/ui/primitives/dialog\";\nimport { useT } from \"@lattice-php/ui/i18n\";\nimport { MODAL_MISSING_ERROR, useEmbeddedModal } from \"@lattice-php/ui/components/modal/modal-host\";\nimport { useLiveNotifications } from \"../context\";\nimport { NotificationList } from \"./notification-list\";\n\nexport function NotificationsSheet({ onClosed }: { onClosed: () => void }) {\n const context = useEmbeddedModal();\n\n if (!context) {\n throw new Error(MODAL_MISSING_ERROR);\n }\n\n const store = useLiveNotifications();\n const { t } = useT(\"lattice\");\n const label = t(\"notifications.label\", \"Notifications\");\n const heading = t(\"notifications.heading\", \"Notifications\");\n\n return (\n <Dialog open={context.open} onOpenChange={context.onOpenChange}>\n <DialogContent\n aria-describedby={undefined}\n className=\"p-0\"\n onCloseAutoFocus={(event) => {\n context.onExited(event);\n onClosed();\n }}\n placement=\"end\"\n width=\"sm\"\n >\n <DialogTitle className=\"sr-only\">{label}</DialogTitle>\n <div className=\"w-full\" data-test=\"notifications-panel\">\n <div className=\"flex items-center justify-between border-b border-lt-border px-3 py-2\">\n <span className=\"text-sm font-medium\">{heading}</span>\n {store.unreadCount > 0 ? (\n <button\n type=\"button\"\n className=\"text-xs text-lt-muted-fg hover:text-lt-fg\"\n onClick={store.markAllRead}\n >\n {t(\"notifications.mark-all-read\", \"Mark all read\")}\n </button>\n ) : null}\n </div>\n <NotificationList\n notifications={store.notifications}\n status={store.status}\n hasMore={store.hasMore}\n onMarkRead={store.markRead}\n onDismiss={store.dismiss}\n onLoadMore={store.loadMore}\n />\n </div>\n </DialogContent>\n </Dialog>\n );\n}\n"],"mappings":";;;;;;;AAMA,SAAgB,mBAAmB,EAAE,YAAsC;CACzE,MAAM,UAAU,iBAAiB;CAEjC,IAAI,CAAC,SACH,MAAM,IAAI,MAAM,mBAAmB;CAGrC,MAAM,QAAQ,qBAAqB;CACnC,MAAM,EAAE,MAAM,KAAK,SAAS;CAC5B,MAAM,QAAQ,EAAE,uBAAuB,eAAe;CACtD,MAAM,UAAU,EAAE,yBAAyB,eAAe;CAE1D,OACE,oBAAC,QAAD;EAAQ,MAAM,QAAQ;EAAM,cAAc,QAAQ;EAChD,UAAA,qBAAC,eAAD;GACE,oBAAkB,KAAA;GAClB,WAAU;GACV,mBAAmB,UAAU;IAC3B,QAAQ,SAAS,KAAK;IACtB,SAAS;GACX;GACA,WAAU;GACV,OAAM;GARR,UAAA,CAUE,oBAAC,aAAD;IAAa,WAAU;IAAW,UAAA;GAAmB,CAAA,GACrD,qBAAC,OAAD;IAAK,WAAU;IAAS,aAAU;IAAlC,UAAA,CACE,qBAAC,OAAD;KAAK,WAAU;KAAf,UAAA,CACE,oBAAC,QAAD;MAAM,WAAU;MAAuB,UAAA;KAAc,CAAA,GACpD,MAAM,cAAc,IACnB,oBAAC,UAAD;MACE,MAAK;MACL,WAAU;MACV,SAAS,MAAM;MAEd,UAAA,EAAE,+BAA+B,eAAe;KAC3C,CAAA,IACN,IACD;IACL,CAAA,GAAA,oBAAC,kBAAD;KACE,eAAe,MAAM;KACrB,QAAQ,MAAM;KACd,SAAS,MAAM;KACf,YAAY,MAAM;KAClB,WAAW,MAAM;KACjB,YAAY,MAAM;IACnB,CAAA,CACE;GACQ,CAAA,CAAA;;CACT,CAAA;AAEZ"}
@@ -3,11 +3,11 @@ import { NotificationsBridgeProvider, createNotificationsBridge } from "../conte
3
3
  import { NotificationList } from "./notification-list.js";
4
4
  import { NotificationsSheet } from "./notifications-sheet.js";
5
5
  import { Component, Suspense, lazy, useCallback, useEffect, useRef, useState } from "react";
6
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
7
+ import { useModal } from "@lattice-php/ui/components/modal/modal-host";
8
+ import { Popover, PopoverContent, PopoverTrigger } from "@lattice-php/ui/components/popover/popover";
6
9
  import { Icon } from "@lattice-php/ui/icons";
7
10
  import { useT } from "@lattice-php/ui/i18n";
8
- import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
9
- import { Popover, PopoverContent, PopoverTrigger } from "@lattice-php/ui/primitives/popover";
10
- import { useModal } from "@lattice-php/ui/modal";
11
11
  //#region resources/js/notifications/components/notifications.tsx
12
12
  var NotificationsEcho = lazy(() => import("./notifications-echo.js").then((m) => ({ default: m.NotificationsEcho })));
13
13
  var EchoBoundary = class extends Component {
@@ -78,7 +78,7 @@ var NotificationsComponent = ({ node }) => {
78
78
  onLoadMore: store.loadMore
79
79
  })]
80
80
  });
81
- return /* @__PURE__ */ jsxs(Fragment$1, { children: [node.props.channel ? /* @__PURE__ */ jsx(EchoBoundary, { children: /* @__PURE__ */ jsx(Suspense, {
81
+ return /* @__PURE__ */ jsxs(Fragment, { children: [node.props.channel ? /* @__PURE__ */ jsx(EchoBoundary, { children: /* @__PURE__ */ jsx(Suspense, {
82
82
  fallback: null,
83
83
  children: /* @__PURE__ */ jsx(NotificationsEcho, {
84
84
  channel: node.props.channel,
@@ -1 +1 @@
1
- {"version":3,"file":"notifications.js","names":[],"sources":["../../../resources/js/notifications/components/notifications.tsx"],"sourcesContent":["import {\n Component,\n lazy,\n Suspense,\n useCallback,\n useEffect,\n useRef,\n useState,\n type ReactNode,\n} from \"react\";\nimport {\n Popover as PopoverRoot,\n PopoverContent,\n PopoverTrigger,\n} from \"@lattice-php/ui/primitives/popover\";\nimport { Icon } from \"@lattice-php/ui/icons\";\nimport { useT } from \"@lattice-php/ui/i18n\";\nimport { type ModalHandle, useModal } from \"@lattice-php/ui/modal\";\nimport type { RendererComponent } from \"@lattice-php/core/types\";\nimport { useNotifications } from \"@lattice-php/lattice/notifications/store\";\nimport type { NotificationItem } from \"@lattice-php/lattice/notifications/types\";\nimport { createNotificationsBridge, NotificationsBridgeProvider } from \"../context\";\nimport { NotificationList } from \"./notification-list\";\nimport { NotificationsSheet } from \"./notifications-sheet\";\n\nconst NotificationsEcho = lazy(() =>\n import(\"./notifications-echo\").then((m) => ({ default: m.NotificationsEcho })),\n);\n\nclass EchoBoundary extends Component<{ children: ReactNode }, { failed: boolean }> {\n state = { failed: false };\n\n static getDerivedStateFromError(): { failed: boolean } {\n return { failed: true };\n }\n\n componentDidCatch(): void {\n console.warn(\n \"[lattice] The notifications bell declares a realtime channel but Echo is unavailable. Install @laravel/echo-react and call configureEcho().\",\n );\n }\n\n render(): ReactNode {\n return this.state.failed ? null : this.props.children;\n }\n}\n\nconst NotificationsComponent: RendererComponent<\"notifications\"> = ({ node }) => {\n const { t } = useT(\"lattice\");\n const store = useNotifications({\n endpoint: node.props.endpoint,\n pollingInterval: node.props.pollingInterval,\n });\n const host = useModal();\n const handleRef = useRef<ModalHandle | null>(null);\n const [bridge] = useState(() => createNotificationsBridge(store));\n\n useEffect(() => {\n bridge.publish(store);\n }, [bridge, store]);\n\n const label = t(\"notifications.label\", \"Notifications\");\n\n const openSheet = useCallback((): void => {\n if (handleRef.current) {\n return;\n }\n\n handleRef.current = host.open(\n <NotificationsBridgeProvider value={bridge}>\n <NotificationsSheet\n onClosed={() => {\n handleRef.current = null;\n }}\n />\n </NotificationsBridgeProvider>,\n );\n }, [bridge, host]);\n\n const trigger = (\n <span className=\"relative inline-flex items-center justify-center rounded-lt-sm p-2 hover:bg-lt-muted\">\n <Icon name=\"bell\" className=\"size-lt-icon-md\" />\n {store.unreadCount > 0 ? (\n <span\n data-test=\"notifications-badge\"\n className=\"absolute -right-0.5 -top-0.5 inline-flex min-w-4 items-center justify-center rounded-lt-full bg-lt-danger px-1 py-0 text-[10px] font-medium text-lt-danger-fg\"\n >\n {store.unreadCount}\n </span>\n ) : null}\n </span>\n );\n\n const panel = (\n <div className=\"w-80\" data-test=\"notifications-panel\">\n <div className=\"flex items-center justify-between border-b border-lt-border px-3 py-2\">\n <span className=\"text-sm font-medium\">{t(\"notifications.heading\", \"Notifications\")}</span>\n {store.unreadCount > 0 ? (\n <button\n type=\"button\"\n className=\"text-xs text-lt-muted-fg hover:text-lt-fg\"\n onClick={store.markAllRead}\n >\n {t(\"notifications.mark-all-read\", \"Mark all read\")}\n </button>\n ) : null}\n </div>\n <NotificationList\n notifications={store.notifications}\n status={store.status}\n hasMore={store.hasMore}\n onMarkRead={store.markRead}\n onDismiss={store.dismiss}\n onLoadMore={store.loadMore}\n />\n </div>\n );\n\n return (\n <>\n {node.props.channel ? (\n <EchoBoundary>\n <Suspense fallback={null}>\n <NotificationsEcho\n channel={node.props.channel}\n onReceive={(item: NotificationItem) => store.receive(item)}\n />\n </Suspense>\n </EchoBoundary>\n ) : null}\n\n {node.props.slideOut ? (\n <button\n type=\"button\"\n aria-label={label}\n data-test=\"notifications-trigger\"\n onClick={openSheet}\n >\n {trigger}\n </button>\n ) : (\n <PopoverRoot open={store.open} onOpenChange={store.setOpen}>\n <PopoverTrigger asChild>\n <button type=\"button\" aria-label={label} data-test=\"notifications-trigger\">\n {trigger}\n </button>\n </PopoverTrigger>\n <PopoverContent align=\"end\" className=\"p-0\">\n {panel}\n </PopoverContent>\n </PopoverRoot>\n )}\n </>\n );\n};\n\nexport default NotificationsComponent;\n"],"mappings":";;;;;;;;;;;AAyBA,IAAM,oBAAoB,WACxB,OAAO,0BAAuB,CAAC,MAAM,OAAO,EAAE,SAAS,EAAE,kBAAkB,EAAE,CAC/E;AAEA,IAAM,eAAN,cAA2B,UAAwD;CACjF,QAAQ,EAAE,QAAQ,MAAM;CAExB,OAAO,2BAAgD;EACrD,OAAO,EAAE,QAAQ,KAAK;CACxB;CAEA,oBAA0B;EACxB,QAAQ,KACN,6IACF;CACF;CAEA,SAAoB;EAClB,OAAO,KAAK,MAAM,SAAS,OAAO,KAAK,MAAM;CAC/C;AACF;AAEA,IAAM,0BAA8D,EAAE,WAAW;CAC/E,MAAM,EAAE,MAAM,KAAK,SAAS;CAC5B,MAAM,QAAQ,iBAAiB;EAC7B,UAAU,KAAK,MAAM;EACrB,iBAAiB,KAAK,MAAM;CAC9B,CAAC;CACD,MAAM,OAAO,SAAS;CACtB,MAAM,YAAY,OAA2B,IAAI;CACjD,MAAM,CAAC,UAAU,eAAe,0BAA0B,KAAK,CAAC;CAEhE,gBAAgB;EACd,OAAO,QAAQ,KAAK;CACtB,GAAG,CAAC,QAAQ,KAAK,CAAC;CAElB,MAAM,QAAQ,EAAE,uBAAuB,eAAe;CAEtD,MAAM,YAAY,kBAAwB;EACxC,IAAI,UAAU,SACZ;EAGF,UAAU,UAAU,KAAK,KACvB,oBAAC,6BAAD;GAA6B,OAAO;GAClC,UAAA,oBAAC,oBAAD,EACE,gBAAgB;IACd,UAAU,UAAU;GACtB,EACD,CAAA;EAC0B,CAAA,CAC/B;CACF,GAAG,CAAC,QAAQ,IAAI,CAAC;CAEjB,MAAM,UACJ,qBAAC,QAAD;EAAM,WAAU;EAAhB,UAAA,CACE,oBAAC,MAAD;GAAM,MAAK;GAAO,WAAU;EAAmB,CAAA,GAC9C,MAAM,cAAc,IACnB,oBAAC,QAAD;GACE,aAAU;GACV,WAAU;GAET,UAAA,MAAM;EACH,CAAA,IACJ,IACA;;CAGR,MAAM,QACJ,qBAAC,OAAD;EAAK,WAAU;EAAO,aAAU;EAAhC,UAAA,CACE,qBAAC,OAAD;GAAK,WAAU;GAAf,UAAA,CACE,oBAAC,QAAD;IAAM,WAAU;IAAuB,UAAA,EAAE,yBAAyB,eAAe;GAAQ,CAAA,GACxF,MAAM,cAAc,IACnB,oBAAC,UAAD;IACE,MAAK;IACL,WAAU;IACV,SAAS,MAAM;IAEd,UAAA,EAAE,+BAA+B,eAAe;GAC3C,CAAA,IACN,IACD;EACL,CAAA,GAAA,oBAAC,kBAAD;GACE,eAAe,MAAM;GACrB,QAAQ,MAAM;GACd,SAAS,MAAM;GACf,YAAY,MAAM;GAClB,WAAW,MAAM;GACjB,YAAY,MAAM;EACnB,CAAA,CACE;;CAGP,OACE,qBAAA,YAAA,EAAA,UAAA,CACG,KAAK,MAAM,UACV,oBAAC,cAAD,EAAA,UACE,oBAAC,UAAD;EAAU,UAAU;EAClB,UAAA,oBAAC,mBAAD;GACE,SAAS,KAAK,MAAM;GACpB,YAAY,SAA2B,MAAM,QAAQ,IAAI;EAC1D,CAAA;CACO,CAAA,EACE,CAAA,IACZ,MAEH,KAAK,MAAM,WACV,oBAAC,UAAD;EACE,MAAK;EACL,cAAY;EACZ,aAAU;EACV,SAAS;EAER,UAAA;CACK,CAAA,IAER,qBAAC,SAAD;EAAa,MAAM,MAAM;EAAM,cAAc,MAAM;EAAnD,UAAA,CACE,oBAAC,gBAAD;GAAgB,SAAA;GACd,UAAA,oBAAC,UAAD;IAAQ,MAAK;IAAS,cAAY;IAAO,aAAU;IAChD,UAAA;GACK,CAAA;EACM,CAAA,GAChB,oBAAC,gBAAD;GAAgB,OAAM;GAAM,WAAU;GACnC,UAAA;EACa,CAAA,CACL;CAEf,CAAA,CAAA,EAAA,CAAA;AAEN"}
1
+ {"version":3,"file":"notifications.js","names":[],"sources":["../../../resources/js/notifications/components/notifications.tsx"],"sourcesContent":["import {\n Component,\n lazy,\n Suspense,\n useCallback,\n useEffect,\n useRef,\n useState,\n type ReactNode,\n} from \"react\";\nimport {\n Popover as PopoverRoot,\n PopoverContent,\n PopoverTrigger,\n} from \"@lattice-php/ui/components/popover/popover\";\nimport { Icon } from \"@lattice-php/ui/icons\";\nimport { useT } from \"@lattice-php/ui/i18n\";\nimport { type ModalHandle, useModal } from \"@lattice-php/ui/components/modal/modal-host\";\nimport type { RendererComponent } from \"@lattice-php/core/types\";\nimport { useNotifications } from \"../store\";\nimport type { NotificationItem } from \"../types\";\nimport { createNotificationsBridge, NotificationsBridgeProvider } from \"../context\";\nimport { NotificationList } from \"./notification-list\";\nimport { NotificationsSheet } from \"./notifications-sheet\";\n\nconst NotificationsEcho = lazy(() =>\n import(\"./notifications-echo\").then((m) => ({ default: m.NotificationsEcho })),\n);\n\nclass EchoBoundary extends Component<{ children: ReactNode }, { failed: boolean }> {\n state = { failed: false };\n\n static getDerivedStateFromError(): { failed: boolean } {\n return { failed: true };\n }\n\n componentDidCatch(): void {\n console.warn(\n \"[lattice] The notifications bell declares a realtime channel but Echo is unavailable. Install @laravel/echo-react and call configureEcho().\",\n );\n }\n\n render(): ReactNode {\n return this.state.failed ? null : this.props.children;\n }\n}\n\nconst NotificationsComponent: RendererComponent<\"notifications\"> = ({ node }) => {\n const { t } = useT(\"lattice\");\n const store = useNotifications({\n endpoint: node.props.endpoint,\n pollingInterval: node.props.pollingInterval,\n });\n const host = useModal();\n const handleRef = useRef<ModalHandle | null>(null);\n const [bridge] = useState(() => createNotificationsBridge(store));\n\n useEffect(() => {\n bridge.publish(store);\n }, [bridge, store]);\n\n const label = t(\"notifications.label\", \"Notifications\");\n\n const openSheet = useCallback((): void => {\n if (handleRef.current) {\n return;\n }\n\n handleRef.current = host.open(\n <NotificationsBridgeProvider value={bridge}>\n <NotificationsSheet\n onClosed={() => {\n handleRef.current = null;\n }}\n />\n </NotificationsBridgeProvider>,\n );\n }, [bridge, host]);\n\n const trigger = (\n <span className=\"relative inline-flex items-center justify-center rounded-lt-sm p-2 hover:bg-lt-muted\">\n <Icon name=\"bell\" className=\"size-lt-icon-md\" />\n {store.unreadCount > 0 ? (\n <span\n data-test=\"notifications-badge\"\n className=\"absolute -right-0.5 -top-0.5 inline-flex min-w-4 items-center justify-center rounded-lt-full bg-lt-danger px-1 py-0 text-[10px] font-medium text-lt-danger-fg\"\n >\n {store.unreadCount}\n </span>\n ) : null}\n </span>\n );\n\n const panel = (\n <div className=\"w-80\" data-test=\"notifications-panel\">\n <div className=\"flex items-center justify-between border-b border-lt-border px-3 py-2\">\n <span className=\"text-sm font-medium\">{t(\"notifications.heading\", \"Notifications\")}</span>\n {store.unreadCount > 0 ? (\n <button\n type=\"button\"\n className=\"text-xs text-lt-muted-fg hover:text-lt-fg\"\n onClick={store.markAllRead}\n >\n {t(\"notifications.mark-all-read\", \"Mark all read\")}\n </button>\n ) : null}\n </div>\n <NotificationList\n notifications={store.notifications}\n status={store.status}\n hasMore={store.hasMore}\n onMarkRead={store.markRead}\n onDismiss={store.dismiss}\n onLoadMore={store.loadMore}\n />\n </div>\n );\n\n return (\n <>\n {node.props.channel ? (\n <EchoBoundary>\n <Suspense fallback={null}>\n <NotificationsEcho\n channel={node.props.channel}\n onReceive={(item: NotificationItem) => store.receive(item)}\n />\n </Suspense>\n </EchoBoundary>\n ) : null}\n\n {node.props.slideOut ? (\n <button\n type=\"button\"\n aria-label={label}\n data-test=\"notifications-trigger\"\n onClick={openSheet}\n >\n {trigger}\n </button>\n ) : (\n <PopoverRoot open={store.open} onOpenChange={store.setOpen}>\n <PopoverTrigger asChild>\n <button type=\"button\" aria-label={label} data-test=\"notifications-trigger\">\n {trigger}\n </button>\n </PopoverTrigger>\n <PopoverContent align=\"end\" className=\"p-0\">\n {panel}\n </PopoverContent>\n </PopoverRoot>\n )}\n </>\n );\n};\n\nexport default NotificationsComponent;\n"],"mappings":";;;;;;;;;;;AAyBA,IAAM,oBAAoB,WACxB,OAAO,0BAAuB,CAAC,MAAM,OAAO,EAAE,SAAS,EAAE,kBAAkB,EAAE,CAC/E;AAEA,IAAM,eAAN,cAA2B,UAAwD;CACjF,QAAQ,EAAE,QAAQ,MAAM;CAExB,OAAO,2BAAgD;EACrD,OAAO,EAAE,QAAQ,KAAK;CACxB;CAEA,oBAA0B;EACxB,QAAQ,KACN,6IACF;CACF;CAEA,SAAoB;EAClB,OAAO,KAAK,MAAM,SAAS,OAAO,KAAK,MAAM;CAC/C;AACF;AAEA,IAAM,0BAA8D,EAAE,WAAW;CAC/E,MAAM,EAAE,MAAM,KAAK,SAAS;CAC5B,MAAM,QAAQ,iBAAiB;EAC7B,UAAU,KAAK,MAAM;EACrB,iBAAiB,KAAK,MAAM;CAC9B,CAAC;CACD,MAAM,OAAO,SAAS;CACtB,MAAM,YAAY,OAA2B,IAAI;CACjD,MAAM,CAAC,UAAU,eAAe,0BAA0B,KAAK,CAAC;CAEhE,gBAAgB;EACd,OAAO,QAAQ,KAAK;CACtB,GAAG,CAAC,QAAQ,KAAK,CAAC;CAElB,MAAM,QAAQ,EAAE,uBAAuB,eAAe;CAEtD,MAAM,YAAY,kBAAwB;EACxC,IAAI,UAAU,SACZ;EAGF,UAAU,UAAU,KAAK,KACvB,oBAAC,6BAAD;GAA6B,OAAO;GAClC,UAAA,oBAAC,oBAAD,EACE,gBAAgB;IACd,UAAU,UAAU;GACtB,EACD,CAAA;EAC0B,CAAA,CAC/B;CACF,GAAG,CAAC,QAAQ,IAAI,CAAC;CAEjB,MAAM,UACJ,qBAAC,QAAD;EAAM,WAAU;EAAhB,UAAA,CACE,oBAAC,MAAD;GAAM,MAAK;GAAO,WAAU;EAAmB,CAAA,GAC9C,MAAM,cAAc,IACnB,oBAAC,QAAD;GACE,aAAU;GACV,WAAU;GAET,UAAA,MAAM;EACH,CAAA,IACJ,IACA;;CAGR,MAAM,QACJ,qBAAC,OAAD;EAAK,WAAU;EAAO,aAAU;EAAhC,UAAA,CACE,qBAAC,OAAD;GAAK,WAAU;GAAf,UAAA,CACE,oBAAC,QAAD;IAAM,WAAU;IAAuB,UAAA,EAAE,yBAAyB,eAAe;GAAQ,CAAA,GACxF,MAAM,cAAc,IACnB,oBAAC,UAAD;IACE,MAAK;IACL,WAAU;IACV,SAAS,MAAM;IAEd,UAAA,EAAE,+BAA+B,eAAe;GAC3C,CAAA,IACN,IACD;EACL,CAAA,GAAA,oBAAC,kBAAD;GACE,eAAe,MAAM;GACrB,QAAQ,MAAM;GACd,SAAS,MAAM;GACf,YAAY,MAAM;GAClB,WAAW,MAAM;GACjB,YAAY,MAAM;EACnB,CAAA,CACE;;CAGP,OACE,qBAAA,UAAA,EAAA,UAAA,CACG,KAAK,MAAM,UACV,oBAAC,cAAD,EAAA,UACE,oBAAC,UAAD;EAAU,UAAU;EAClB,UAAA,oBAAC,mBAAD;GACE,SAAS,KAAK,MAAM;GACpB,YAAY,SAA2B,MAAM,QAAQ,IAAI;EAC1D,CAAA;CACO,CAAA,EACE,CAAA,IACZ,MAEH,KAAK,MAAM,WACV,oBAAC,UAAD;EACE,MAAK;EACL,cAAY;EACZ,aAAU;EACV,SAAS;EAER,UAAA;CACK,CAAA,IAER,qBAAC,SAAD;EAAa,MAAM,MAAM;EAAM,cAAc,MAAM;EAAnD,UAAA,CACE,oBAAC,gBAAD;GAAgB,SAAA;GACd,UAAA,oBAAC,UAAD;IAAQ,MAAK;IAAS,cAAY;IAAO,aAAU;IAChD,UAAA;GACK,CAAA;EACM,CAAA,GAChB,oBAAC,gBAAD;GAAgB,OAAM;GAAM,WAAU;GACnC,UAAA;EACa,CAAA,CACL;CAEf,CAAA,CAAA,EAAA,CAAA;AAEN"}
package/dist/page.js CHANGED
@@ -1,11 +1,12 @@
1
1
  import { RealtimeListeners } from "./realtime/listeners.js";
2
2
  import { Head } from "@inertiajs/react";
3
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
3
4
  import { Renderer } from "@lattice-php/core/renderer";
4
5
  import { cn } from "@lattice-php/ui/lib/utils";
5
- import { Fragment, jsx, jsxs } from "react/jsx-runtime";
6
6
  //#region resources/js/page.tsx
7
7
  var pageWidths = {
8
8
  full: "max-w-none",
9
+ xl: "max-w-6xl",
9
10
  lg: "max-w-4xl",
10
11
  md: "max-w-2xl",
11
12
  sm: "max-w-md"
package/dist/page.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"page.js","names":[],"sources":["../resources/js/page.tsx"],"sourcesContent":["import { Head } from \"@inertiajs/react\";\nimport { Renderer } from \"@lattice-php/core/renderer\";\nimport type { PagePayload } from \"@lattice-php/lattice\";\nimport { cn } from \"@lattice-php/ui/lib/utils\";\nimport { RealtimeListeners } from \"@lattice-php/lattice/realtime/listeners\";\n\ntype Props = {\n lattice: PagePayload;\n};\n\nconst pageWidths: Record<string, string> = {\n full: \"max-w-none\",\n lg: \"max-w-4xl\",\n md: \"max-w-2xl\",\n sm: \"max-w-md\",\n};\n\nexport default function Page({ lattice }: Props) {\n return (\n <>\n <Head title={lattice.title ?? undefined} />\n\n <RealtimeListeners listeners={lattice.listeners} />\n\n <div\n data-test=\"lattice-page-container\"\n data-page-width={lattice.width}\n className={cn(\n \"mx-auto w-full px-4 py-6 sm:px-6 lg:px-8\",\n pageWidths[lattice.width] ?? pageWidths.full,\n )}\n >\n <Renderer nodes={lattice.schema} />\n </div>\n </>\n );\n}\n"],"mappings":";;;;;;AAUA,IAAM,aAAqC;CACzC,MAAM;CACN,IAAI;CACJ,IAAI;CACJ,IAAI;AACN;AAEA,SAAwB,KAAK,EAAE,WAAkB;CAC/C,OACE,qBAAA,UAAA,EAAA,UAAA;EACE,oBAAC,MAAD,EAAM,OAAO,QAAQ,SAAS,KAAA,EAAY,CAAA;EAE1C,oBAAC,mBAAD,EAAmB,WAAW,QAAQ,UAAY,CAAA;EAElD,oBAAC,OAAD;GACE,aAAU;GACV,mBAAiB,QAAQ;GACzB,WAAW,GACT,4CACA,WAAW,QAAQ,UAAU,WAAW,IAC1C;GAEA,UAAA,oBAAC,UAAD,EAAU,OAAO,QAAQ,OAAS,CAAA;EAC/B,CAAA;CACL,EAAA,CAAA;AAEN"}
1
+ {"version":3,"file":"page.js","names":[],"sources":["../resources/js/page.tsx"],"sourcesContent":["import { Head } from \"@inertiajs/react\";\nimport { Renderer } from \"@lattice-php/core/renderer\";\nimport type { PagePayload } from \"@lattice-php/lattice\";\nimport { cn } from \"@lattice-php/ui/lib/utils\";\nimport { RealtimeListeners } from \"./realtime/listeners\";\n\ntype Props = {\n lattice: PagePayload;\n};\n\nconst pageWidths: Record<string, string> = {\n full: \"max-w-none\",\n xl: \"max-w-6xl\",\n lg: \"max-w-4xl\",\n md: \"max-w-2xl\",\n sm: \"max-w-md\",\n};\n\nexport default function Page({ lattice }: Props) {\n return (\n <>\n <Head title={lattice.title ?? undefined} />\n\n <RealtimeListeners listeners={lattice.listeners} />\n\n <div\n data-test=\"lattice-page-container\"\n data-page-width={lattice.width}\n className={cn(\n \"mx-auto w-full px-4 py-6 sm:px-6 lg:px-8\",\n pageWidths[lattice.width] ?? pageWidths.full,\n )}\n >\n <Renderer nodes={lattice.schema} />\n </div>\n </>\n );\n}\n"],"mappings":";;;;;;AAUA,IAAM,aAAqC;CACzC,MAAM;CACN,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;AACN;AAEA,SAAwB,KAAK,EAAE,WAAkB;CAC/C,OACE,qBAAA,UAAA,EAAA,UAAA;EACE,oBAAC,MAAD,EAAM,OAAO,QAAQ,SAAS,KAAA,EAAY,CAAA;EAE1C,oBAAC,mBAAD,EAAmB,WAAW,QAAQ,UAAY,CAAA;EAElD,oBAAC,OAAD;GACE,aAAU;GACV,mBAAiB,QAAQ;GACzB,WAAW,GACT,4CACA,WAAW,QAAQ,UAAU,WAAW,IAC1C;GAEA,UAAA,oBAAC,UAAD,EAAU,OAAO,QAAQ,OAAS,CAAA;EAC/B,CAAA;CACL,EAAA,CAAA;AAEN"}
@@ -3,8 +3,10 @@ import { Registry } from '@lattice-php/core/registry';
3
3
  import { SpriteValue } from '@lattice-php/ui/icons/sprite';
4
4
  export type ProviderBaseProps = {
5
5
  children: ReactNode;
6
+ /** The url of the page being rendered, so the first render already knows it (SSR included). */
7
+ initialUrl?: string;
6
8
  registry: Registry;
7
9
  sprite?: SpriteValue;
8
10
  toaster?: boolean;
9
11
  };
10
- export declare function ProviderBase({ children, registry, sprite, toaster, }: ProviderBaseProps): import("react").JSX.Element;
12
+ export declare function ProviderBase({ children, initialUrl, registry, sprite, toaster, }: ProviderBaseProps): import("react").JSX.Element;