@lattice-php/lattice 0.56.3 → 0.58.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.
- package/dist/fragments/fragment.js +1 -1
- package/dist/fragments/fragment.js.map +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.js +3 -3
- package/dist/inertia-navigation.d.ts +10 -0
- package/dist/inertia-navigation.js +18 -1
- package/dist/inertia-navigation.js.map +1 -1
- package/dist/layout/components/menu-item.js +3 -3
- package/dist/layout/components/menu-item.js.map +1 -1
- package/dist/layout/components/outlet.js +3 -4
- package/dist/layout/components/outlet.js.map +1 -1
- package/dist/layout/components/popover.js +4 -4
- package/dist/layout/components/popover.js.map +1 -1
- package/dist/layout/components/schema-layout.js +3 -3
- package/dist/layout/components/schema-layout.js.map +1 -1
- package/dist/layout/components/sidebar.js +4 -4
- package/dist/layout/components/sidebar.js.map +1 -1
- package/dist/layout/hooks/context.d.ts +5 -3
- package/dist/layout/hooks/context.js +13 -4
- package/dist/layout/hooks/context.js.map +1 -1
- package/dist/layout/index.d.ts +1 -1
- package/dist/layout/index.js +2 -2
- package/dist/notifications/components/notification-list.js +1 -1
- package/dist/notifications/components/notification-list.js.map +1 -1
- package/dist/notifications/components/notifications-sheet.d.ts +3 -0
- package/dist/notifications/components/notifications-sheet.js +59 -0
- package/dist/notifications/components/notifications-sheet.js.map +1 -0
- package/dist/notifications/components/notifications.js +23 -19
- package/dist/notifications/components/notifications.js.map +1 -1
- package/dist/notifications/context.d.ts +17 -0
- package/dist/notifications/context.js +36 -0
- package/dist/notifications/context.js.map +1 -0
- package/dist/notifications/store.d.ts +1 -1
- package/dist/notifications/store.js.map +1 -1
- package/dist/provider-base.js +9 -7
- package/dist/provider-base.js.map +1 -1
- package/dist/runtime.d.ts +7 -3
- package/dist/runtime.js +8 -5
- package/dist/types/generated.d.ts +4 -3
- package/dist-standalone/chunks/{chart-view-QdsrTt3D.js → chart-view-eWW-pC-B.js} +6 -6
- package/dist-standalone/chunks/{date-picker-field-D_QaDI9c.js → date-picker-field-FY2OOgtu.js} +1 -1
- package/dist-standalone/chunks/{field-DE3_bVGA.js → field-DMXnzaJF.js} +1 -1
- package/dist-standalone/chunks/floating-ui.dom-CAMzcZKV.js +1 -0
- package/dist-standalone/chunks/{input-C-Wm1w0g.js → input-0lNoXsuO.js} +1 -1
- package/dist-standalone/chunks/registry-context-gXwNT8GJ.js +1 -0
- package/dist-standalone/chunks/{rich-editor-field-B8gIiZoQ.js → rich-editor-field-B0XwZGpp.js} +4 -4
- package/dist-standalone/chunks/runtime-BjRIrbqh.js +162 -0
- package/dist-standalone/chunks/{subscriptions-C_vxf4VT.js → subscriptions-CSh5RtT7.js} +1 -1
- package/dist-standalone/lattice.css +1 -1
- package/dist-standalone/lattice.js +1 -1
- package/dist-standalone/manifest.json +1 -1
- package/dist-standalone/runtime.js +1 -1
- package/dist-standalone/sprite.svg +1 -1
- package/package.json +6 -6
- package/dist-standalone/chunks/floating-ui.dom-DRSJZ5ii.js +0 -1
- package/dist-standalone/chunks/registry-context-Q5KtSmdi.js +0 -1
- package/dist-standalone/chunks/runtime-uNS3QbQU.js +0 -162
|
@@ -3,7 +3,7 @@ import { apiJson } from "@lattice-php/core/api";
|
|
|
3
3
|
import { Renderer } from "@lattice-php/core/renderer";
|
|
4
4
|
import { LATTICE_EVENT } from "@lattice-php/core/event-names";
|
|
5
5
|
import { jsx } from "react/jsx-runtime";
|
|
6
|
-
import { Skeleton } from "@lattice-php/ui/skeleton";
|
|
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
|
|
9
9
|
var fragmentSizeHeights = {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fragment.js","names":[],"sources":["../../resources/js/fragments/fragment.tsx"],"sourcesContent":["import { useCallback, useEffect, useState } from \"react\";\nimport { apiJson } from \"@lattice-php/core/api\";\nimport { Skeleton } from \"@lattice-php/ui/skeleton\";\nimport { Renderer } from \"@lattice-php/core/renderer\";\nimport type { RendererComponent } from \"@lattice-php/core/types\";\nimport type { FragmentResponse } from \"@lattice-php/lattice/types/generated\";\nimport { toNodes } from \"@lattice-php/core/nodes\";\nimport { LATTICE_EVENT, type ReloadComponentEvent } from \"@lattice-php/core/event-names\";\n\nconst fragmentSizeHeights = {\n lg: 320,\n md: 64,\n sm: 40,\n xl: 384,\n xs: 32,\n \"2xl\": 448,\n \"3xl\": 512,\n \"4xl\": 576,\n} as const;\n\nconst FragmentComponent: RendererComponent<\"fragment\"> = ({ node }) => {\n const endpoint = node.props.endpoint ?? \"\";\n const isLazy = node.props.lazy === true;\n const componentRef = node.props.ref ?? \"\";\n const placeholderHeight = fragmentSizeHeights[node.props.size];\n const [components, setComponents] = useState(() => node.schema ?? []);\n const [hasLoaded, setHasLoaded] = useState(!isLazy);\n const [processing, setProcessing] = useState(isLazy && endpoint !== \"\");\n\n const load = useCallback(async (): Promise<void> => {\n if (!endpoint) {\n return;\n }\n\n setProcessing(true);\n\n try {\n const result = await apiJson<FragmentResponse>(endpoint, { ref: componentRef });\n\n setComponents(toNodes(result.schema));\n setHasLoaded(true);\n } finally {\n setProcessing(false);\n }\n }, [endpoint, componentRef]);\n\n useEffect(() => {\n if (!isLazy || hasLoaded) {\n return;\n }\n\n void load();\n }, [hasLoaded, isLazy, load]);\n\n useEffect(() => {\n function reload(event: Event): void {\n const detail = (event as ReloadComponentEvent).detail;\n\n if (detail?.component !== node.id) {\n return;\n }\n\n void load();\n }\n\n window.addEventListener(LATTICE_EVENT.reloadComponent, reload);\n\n return () => window.removeEventListener(LATTICE_EVENT.reloadComponent, reload);\n }, [load, node.id]);\n\n useEffect(() => {\n function reloadOnLocaleChange(): void {\n if (!hasLoaded) {\n return;\n }\n\n void load();\n }\n\n window.addEventListener(LATTICE_EVENT.localeChange, reloadOnLocaleChange);\n\n return () => window.removeEventListener(LATTICE_EVENT.localeChange, reloadOnLocaleChange);\n }, [hasLoaded, load]);\n\n return (\n <div\n data-lattice-fragment={node.id}\n style={processing && components.length === 0 ? { minHeight: placeholderHeight } : undefined}\n >\n {processing && components.length === 0 ? (\n <Skeleton className=\"w-full\" style={{ height: placeholderHeight }} />\n ) : (\n <Renderer nodes={components} />\n )}\n </div>\n );\n};\n\nexport default FragmentComponent;\n"],"mappings":";;;;;;;;AASA,IAAM,sBAAsB;CAC1B,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,OAAO;CACP,OAAO;CACP,OAAO;AACT;AAEA,IAAM,qBAAoD,EAAE,WAAW;CACrE,MAAM,WAAW,KAAK,MAAM,YAAY;CACxC,MAAM,SAAS,KAAK,MAAM,SAAS;CACnC,MAAM,eAAe,KAAK,MAAM,OAAO;CACvC,MAAM,oBAAoB,oBAAoB,KAAK,MAAM;CACzD,MAAM,CAAC,YAAY,iBAAiB,eAAe,KAAK,UAAU,CAAC,CAAC;CACpE,MAAM,CAAC,WAAW,gBAAgB,SAAS,CAAC,MAAM;CAClD,MAAM,CAAC,YAAY,iBAAiB,SAAS,UAAU,aAAa,EAAE;CAEtE,MAAM,OAAO,YAAY,YAA2B;EAClD,IAAI,CAAC,UACH;EAGF,cAAc,IAAI;EAElB,IAAI;GACF,MAAM,SAAS,MAAM,QAA0B,UAAU,EAAE,KAAK,aAAa,CAAC;GAE9E,cAAc,QAAQ,OAAO,MAAM,CAAC;GACpC,aAAa,IAAI;EACnB,UAAU;GACR,cAAc,KAAK;EACrB;CACF,GAAG,CAAC,UAAU,YAAY,CAAC;CAE3B,gBAAgB;EACd,IAAI,CAAC,UAAU,WACb;EAGF,KAAU;CACZ,GAAG;EAAC;EAAW;EAAQ;CAAI,CAAC;CAE5B,gBAAgB;EACd,SAAS,OAAO,OAAoB;GAGlC,IAFgB,MAA+B,QAEnC,cAAc,KAAK,IAC7B;GAGF,KAAU;EACZ;EAEA,OAAO,iBAAiB,cAAc,iBAAiB,MAAM;EAE7D,aAAa,OAAO,oBAAoB,cAAc,iBAAiB,MAAM;CAC/E,GAAG,CAAC,MAAM,KAAK,EAAE,CAAC;CAElB,gBAAgB;EACd,SAAS,uBAA6B;GACpC,IAAI,CAAC,WACH;GAGF,KAAU;EACZ;EAEA,OAAO,iBAAiB,cAAc,cAAc,oBAAoB;EAExE,aAAa,OAAO,oBAAoB,cAAc,cAAc,oBAAoB;CAC1F,GAAG,CAAC,WAAW,IAAI,CAAC;CAEpB,OACE,oBAAC,OAAD;EACE,yBAAuB,KAAK;EAC5B,OAAO,cAAc,WAAW,WAAW,IAAI,EAAE,WAAW,kBAAkB,IAAI,KAAA;EAEjF,UAAA,cAAc,WAAW,WAAW,IACnC,oBAAC,UAAD;GAAU,WAAU;GAAS,OAAO,EAAE,QAAQ,kBAAkB;EAAI,CAAA,IAEpE,oBAAC,UAAD,EAAU,OAAO,WAAa,CAAA;CAE7B,CAAA;AAET"}
|
|
1
|
+
{"version":3,"file":"fragment.js","names":[],"sources":["../../resources/js/fragments/fragment.tsx"],"sourcesContent":["import { useCallback, useEffect, useState } from \"react\";\nimport { apiJson } from \"@lattice-php/core/api\";\nimport { Skeleton } from \"@lattice-php/ui/primitives/skeleton\";\nimport { Renderer } from \"@lattice-php/core/renderer\";\nimport type { RendererComponent } from \"@lattice-php/core/types\";\nimport type { FragmentResponse } from \"@lattice-php/lattice/types/generated\";\nimport { toNodes } from \"@lattice-php/core/nodes\";\nimport { LATTICE_EVENT, type ReloadComponentEvent } from \"@lattice-php/core/event-names\";\n\nconst fragmentSizeHeights = {\n lg: 320,\n md: 64,\n sm: 40,\n xl: 384,\n xs: 32,\n \"2xl\": 448,\n \"3xl\": 512,\n \"4xl\": 576,\n} as const;\n\nconst FragmentComponent: RendererComponent<\"fragment\"> = ({ node }) => {\n const endpoint = node.props.endpoint ?? \"\";\n const isLazy = node.props.lazy === true;\n const componentRef = node.props.ref ?? \"\";\n const placeholderHeight = fragmentSizeHeights[node.props.size];\n const [components, setComponents] = useState(() => node.schema ?? []);\n const [hasLoaded, setHasLoaded] = useState(!isLazy);\n const [processing, setProcessing] = useState(isLazy && endpoint !== \"\");\n\n const load = useCallback(async (): Promise<void> => {\n if (!endpoint) {\n return;\n }\n\n setProcessing(true);\n\n try {\n const result = await apiJson<FragmentResponse>(endpoint, { ref: componentRef });\n\n setComponents(toNodes(result.schema));\n setHasLoaded(true);\n } finally {\n setProcessing(false);\n }\n }, [endpoint, componentRef]);\n\n useEffect(() => {\n if (!isLazy || hasLoaded) {\n return;\n }\n\n void load();\n }, [hasLoaded, isLazy, load]);\n\n useEffect(() => {\n function reload(event: Event): void {\n const detail = (event as ReloadComponentEvent).detail;\n\n if (detail?.component !== node.id) {\n return;\n }\n\n void load();\n }\n\n window.addEventListener(LATTICE_EVENT.reloadComponent, reload);\n\n return () => window.removeEventListener(LATTICE_EVENT.reloadComponent, reload);\n }, [load, node.id]);\n\n useEffect(() => {\n function reloadOnLocaleChange(): void {\n if (!hasLoaded) {\n return;\n }\n\n void load();\n }\n\n window.addEventListener(LATTICE_EVENT.localeChange, reloadOnLocaleChange);\n\n return () => window.removeEventListener(LATTICE_EVENT.localeChange, reloadOnLocaleChange);\n }, [hasLoaded, load]);\n\n return (\n <div\n data-lattice-fragment={node.id}\n style={processing && components.length === 0 ? { minHeight: placeholderHeight } : undefined}\n >\n {processing && components.length === 0 ? (\n <Skeleton className=\"w-full\" style={{ height: placeholderHeight }} />\n ) : (\n <Renderer nodes={components} />\n )}\n </div>\n );\n};\n\nexport default FragmentComponent;\n"],"mappings":";;;;;;;;AASA,IAAM,sBAAsB;CAC1B,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,OAAO;CACP,OAAO;CACP,OAAO;AACT;AAEA,IAAM,qBAAoD,EAAE,WAAW;CACrE,MAAM,WAAW,KAAK,MAAM,YAAY;CACxC,MAAM,SAAS,KAAK,MAAM,SAAS;CACnC,MAAM,eAAe,KAAK,MAAM,OAAO;CACvC,MAAM,oBAAoB,oBAAoB,KAAK,MAAM;CACzD,MAAM,CAAC,YAAY,iBAAiB,eAAe,KAAK,UAAU,CAAC,CAAC;CACpE,MAAM,CAAC,WAAW,gBAAgB,SAAS,CAAC,MAAM;CAClD,MAAM,CAAC,YAAY,iBAAiB,SAAS,UAAU,aAAa,EAAE;CAEtE,MAAM,OAAO,YAAY,YAA2B;EAClD,IAAI,CAAC,UACH;EAGF,cAAc,IAAI;EAElB,IAAI;GACF,MAAM,SAAS,MAAM,QAA0B,UAAU,EAAE,KAAK,aAAa,CAAC;GAE9E,cAAc,QAAQ,OAAO,MAAM,CAAC;GACpC,aAAa,IAAI;EACnB,UAAU;GACR,cAAc,KAAK;EACrB;CACF,GAAG,CAAC,UAAU,YAAY,CAAC;CAE3B,gBAAgB;EACd,IAAI,CAAC,UAAU,WACb;EAGF,KAAU;CACZ,GAAG;EAAC;EAAW;EAAQ;CAAI,CAAC;CAE5B,gBAAgB;EACd,SAAS,OAAO,OAAoB;GAGlC,IAFgB,MAA+B,QAEnC,cAAc,KAAK,IAC7B;GAGF,KAAU;EACZ;EAEA,OAAO,iBAAiB,cAAc,iBAAiB,MAAM;EAE7D,aAAa,OAAO,oBAAoB,cAAc,iBAAiB,MAAM;CAC/E,GAAG,CAAC,MAAM,KAAK,EAAE,CAAC;CAElB,gBAAgB;EACd,SAAS,uBAA6B;GACpC,IAAI,CAAC,WACH;GAGF,KAAU;EACZ;EAEA,OAAO,iBAAiB,cAAc,cAAc,oBAAoB;EAExE,aAAa,OAAO,oBAAoB,cAAc,cAAc,oBAAoB;CAC1F,GAAG,CAAC,WAAW,IAAI,CAAC;CAEpB,OACE,oBAAC,OAAD;EACE,yBAAuB,KAAK;EAC5B,OAAO,cAAc,WAAW,WAAW,IAAI,EAAE,WAAW,kBAAkB,IAAI,KAAA;EAEjF,UAAA,cAAc,WAAW,WAAW,IACnC,oBAAC,UAAD;GAAU,WAAU;GAAS,OAAO,EAAE,QAAQ,kBAAkB;EAAI,CAAA,IAEpE,oBAAC,UAAD,EAAU,OAAO,WAAa,CAAA;CAE7B,CAAA;AAET"}
|
package/dist/index.d.ts
CHANGED
|
@@ -4,12 +4,12 @@ export { getActionEffects, isActionEffect, dispatchEffects, dispatchActionError,
|
|
|
4
4
|
export { useEffectDispatcher } from '@lattice-php/ui/effects/use-effect-dispatcher';
|
|
5
5
|
export { builtinEffectHandlers, effectHandler, mergeEffectHandlers, } from '@lattice-php/ui/effects/registry';
|
|
6
6
|
export { initializeAppearance, updateAppearance, useAppearance } from './appearance/index.js';
|
|
7
|
-
export { copyToClipboard } from '@lattice-php/ui/copyable-text';
|
|
7
|
+
export { copyToClipboard } from '@lattice-php/ui/primitives/copyable-text';
|
|
8
8
|
export { createLatticeApp, type CreateLatticeAppI18nOptions, type CreateLatticeAppOptions, } from './create-app.js';
|
|
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,
|
|
12
|
+
export { Callouts, layoutComponents, OutletProvider, SchemaLayout, useOutlet } from './layout/index.js';
|
|
13
13
|
export { Provider, useColumnRegistry, useComponentRegistry } from './provider.js';
|
|
14
14
|
export { onCallout, onToast, Toaster } from './toast/index.js';
|
|
15
15
|
export { createRegistry, eagerComponent, extendRegistry, lazyComponent, loadPluginModules, } from '@lattice-php/core/registry';
|
|
@@ -18,7 +18,7 @@ export { Renderer } from '@lattice-php/core/renderer';
|
|
|
18
18
|
export { LATTICE_REF_HEADER, withRefHeader } from '@lattice-php/core/component-ref';
|
|
19
19
|
export { withHeaders } from '@lattice-php/core/headers';
|
|
20
20
|
export { LATTICE_EVENT } from '@lattice-php/core/event-names';
|
|
21
|
-
export type { Emphasis } from '@lattice-php/ui/button';
|
|
21
|
+
export type { Emphasis } from '@lattice-php/ui/components/button/button';
|
|
22
22
|
export type { ReloadComponentEvent } from '@lattice-php/core/event-names';
|
|
23
23
|
export type { ComponentProps, KnownPageWidth, LayoutPayload, Node, NodeProps, NodeType, PageBreadcrumb, PagePayload, PageWidth, ComponentPropsOf, RendererComponent, RendererComponentModule, RendererComponentProps, Schema, UnknownComponent, } from './types/index.js';
|
|
24
24
|
export { RealtimeListeners } from './realtime/listeners.js';
|
package/dist/index.js
CHANGED
|
@@ -3,7 +3,7 @@ import { onToast } from "./toast/toast.js";
|
|
|
3
3
|
import { onCallout } from "./toast/callout.js";
|
|
4
4
|
import { Toaster } from "./toast/toaster.js";
|
|
5
5
|
import Callouts from "./layout/components/callouts.js";
|
|
6
|
-
import {
|
|
6
|
+
import { OutletProvider, useOutlet } from "./layout/hooks/context.js";
|
|
7
7
|
import { layoutComponents } from "./layout/plugin.js";
|
|
8
8
|
import SchemaLayout from "./layout/components/schema-layout.js";
|
|
9
9
|
import { RealtimeListeners } from "./realtime/listeners.js";
|
|
@@ -21,6 +21,6 @@ import { LATTICE_EVENT } from "@lattice-php/core/event-names";
|
|
|
21
21
|
import { dispatchActionError, dispatchEffects, getActionEffects, isActionEffect } from "@lattice-php/ui/effects/dispatch";
|
|
22
22
|
import { useEffectDispatcher } from "@lattice-php/ui/effects/use-effect-dispatcher";
|
|
23
23
|
import { builtinEffectHandlers, effectHandler, mergeEffectHandlers } from "@lattice-php/ui/effects/registry";
|
|
24
|
-
import { copyToClipboard } from "@lattice-php/ui/copyable-text";
|
|
24
|
+
import { copyToClipboard } from "@lattice-php/ui/primitives/copyable-text";
|
|
25
25
|
import { columnCell } from "@lattice-php/table/registry";
|
|
26
|
-
export { Callouts, EventBridge, Icon, IconRenderer, IconRendererProvider, LATTICE_EVENT, LATTICE_REF_HEADER,
|
|
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 };
|
|
@@ -1,6 +1,16 @@
|
|
|
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
|
+
* An open modal must not survive the page it was opened on — its content can
|
|
6
|
+
* hold stale props once the visit swaps in a new page. Inertia's `navigate`
|
|
7
|
+
* event only fires for a visit that actually swaps in a different page
|
|
8
|
+
* (a new URL, or history back/forward); a same-URL visit — `router.reload()`,
|
|
9
|
+
* partial reloads, polling — is internally marked as a `replace` and never
|
|
10
|
+
* fires it. Subscribing to `navigate` alone is therefore already the correct
|
|
11
|
+
* discriminator: a modal open during a same-page refresh is left untouched.
|
|
12
|
+
*/
|
|
13
|
+
export declare function useCloseModalsOnNavigate(): void;
|
|
4
14
|
/**
|
|
5
15
|
* SPA-grade redirect/reload effect handlers. Registered as an effects
|
|
6
16
|
* extension so they override ui's window-based built-ins wherever the
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { Link, router } from "@inertiajs/react";
|
|
2
|
+
import { useEffect } from "react";
|
|
3
|
+
import { LATTICE_EVENT } from "@lattice-php/core/event-names";
|
|
2
4
|
import { jsx } from "react/jsx-runtime";
|
|
3
5
|
import { effectHandler } from "@lattice-php/ui/effects/registry";
|
|
4
6
|
//#region resources/js/inertia-navigation.tsx
|
|
@@ -15,6 +17,21 @@ var inertiaNavigation = {
|
|
|
15
17
|
visit: (url, options) => router.visit(url, options),
|
|
16
18
|
reload: () => router.reload()
|
|
17
19
|
};
|
|
20
|
+
function closeAllModals() {
|
|
21
|
+
window.dispatchEvent(new CustomEvent(LATTICE_EVENT.closeModal, { detail: { modal: null } }));
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* An open modal must not survive the page it was opened on — its content can
|
|
25
|
+
* hold stale props once the visit swaps in a new page. Inertia's `navigate`
|
|
26
|
+
* event only fires for a visit that actually swaps in a different page
|
|
27
|
+
* (a new URL, or history back/forward); a same-URL visit — `router.reload()`,
|
|
28
|
+
* partial reloads, polling — is internally marked as a `replace` and never
|
|
29
|
+
* fires it. Subscribing to `navigate` alone is therefore already the correct
|
|
30
|
+
* discriminator: a modal open during a same-page refresh is left untouched.
|
|
31
|
+
*/
|
|
32
|
+
function useCloseModalsOnNavigate() {
|
|
33
|
+
useEffect(() => router.on("navigate", closeAllModals), []);
|
|
34
|
+
}
|
|
18
35
|
/**
|
|
19
36
|
* SPA-grade redirect/reload effect handlers. Registered as an effects
|
|
20
37
|
* extension so they override ui's window-based built-ins wherever the
|
|
@@ -28,6 +45,6 @@ var navigationPlugin = {
|
|
|
28
45
|
} }
|
|
29
46
|
};
|
|
30
47
|
//#endregion
|
|
31
|
-
export { inertiaNavigation, navigationPlugin };
|
|
48
|
+
export { inertiaNavigation, navigationPlugin, useCloseModalsOnNavigate };
|
|
32
49
|
|
|
33
50
|
//# 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 type { Plugin } from \"@lattice-php/core/registry\";\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\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":"
|
|
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,11 +1,11 @@
|
|
|
1
1
|
import { Popover } from "./popover.js";
|
|
2
|
-
import { useSidebarCollapsed } from "../hooks/context.js";
|
|
3
2
|
import { Link, usePage } from "@inertiajs/react";
|
|
4
3
|
import { useState } from "react";
|
|
5
4
|
import { Icon, IconRenderer } from "@lattice-php/ui/icons";
|
|
6
5
|
import { cn } from "@lattice-php/ui/lib/utils";
|
|
7
6
|
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
8
7
|
import { prefixedNodeTestId } from "@lattice-php/core/test-id";
|
|
8
|
+
import { useCollapsed } from "@lattice-php/core/collapsed-context";
|
|
9
9
|
import { ActionTrigger, useClickBehavior } from "@lattice-php/ui/click-behavior";
|
|
10
10
|
//#region resources/js/layout/components/menu-item.tsx
|
|
11
11
|
var rowClass = "flex items-center gap-2 rounded-lt-sm px-3 py-2 text-base font-medium text-lt-fg transition-colors hover:bg-lt-muted";
|
|
@@ -23,7 +23,7 @@ function schemaContainsPath(schema, path) {
|
|
|
23
23
|
return (schema ?? []).some((child) => child.props?.href === path || schemaContainsPath(child.schema, path));
|
|
24
24
|
}
|
|
25
25
|
var MenuItemComponent = ({ children, node }) => {
|
|
26
|
-
const collapsed =
|
|
26
|
+
const collapsed = useCollapsed();
|
|
27
27
|
const { icon, label: rawLabel, prefix, suffix } = node.props;
|
|
28
28
|
const label = rawLabel ?? "";
|
|
29
29
|
const iconOnly = Boolean(icon);
|
|
@@ -60,7 +60,7 @@ var MenuItemComponent = ({ children, node }) => {
|
|
|
60
60
|
action: behavior.action,
|
|
61
61
|
children: triggerButton
|
|
62
62
|
}) });
|
|
63
|
-
if (behavior.kind === "effects") return /* @__PURE__ */ jsx("li", { children: triggerButton({
|
|
63
|
+
if (behavior.kind === "effects" || behavior.kind === "modal") return /* @__PURE__ */ jsx("li", { children: triggerButton({
|
|
64
64
|
onClick: behavior.onClick,
|
|
65
65
|
processing: false
|
|
66
66
|
}) });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"menu-item.js","names":[],"sources":["../../../resources/js/layout/components/menu-item.tsx"],"sourcesContent":["import { Link, usePage } from \"@inertiajs/react\";\nimport { useState } from \"react\";\nimport type { ReactNode } from \"react\";\nimport { prefixedNodeTestId } from \"@lattice-php/core/test-id\";\nimport type { RendererComponent, Schema } from \"@lattice-php/core/types\";\nimport { Icon, IconRenderer } from \"@lattice-php/ui/icons\";\nimport { cn } from \"@lattice-php/ui/lib/utils\";\nimport type { Affix } from \"@lattice-php/core\";\nimport { ActionTrigger, type TriggerState, useClickBehavior } from \"@lattice-php/ui/click-behavior\";\nimport {
|
|
1
|
+
{"version":3,"file":"menu-item.js","names":[],"sources":["../../../resources/js/layout/components/menu-item.tsx"],"sourcesContent":["import { Link, usePage } from \"@inertiajs/react\";\nimport { useState } from \"react\";\nimport type { ReactNode } from \"react\";\nimport { prefixedNodeTestId } from \"@lattice-php/core/test-id\";\nimport type { RendererComponent, Schema } from \"@lattice-php/core/types\";\nimport { Icon, IconRenderer } from \"@lattice-php/ui/icons\";\nimport { cn } from \"@lattice-php/ui/lib/utils\";\nimport type { Affix } from \"@lattice-php/core\";\nimport { ActionTrigger, type TriggerState, useClickBehavior } from \"@lattice-php/ui/click-behavior\";\nimport { useCollapsed } from \"@lattice-php/core/collapsed-context\";\nimport { Popover } from \"./popover\";\n\nconst rowClass =\n \"flex items-center gap-2 rounded-lt-sm px-3 py-2 text-base font-medium text-lt-fg transition-colors hover:bg-lt-muted\";\n\nfunction MenuAffix({ affix, className }: { affix: Affix; className?: string }) {\n if (affix.icon) {\n return <IconRenderer className={cn(\"size-lt-icon-md shrink-0\", className)} icon={affix.icon} />;\n }\n\n return <span className={cn(\"shrink-0 text-sm text-lt-muted-fg\", className)}>{affix.text}</span>;\n}\n\nfunction schemaContainsPath(schema: Schema | undefined, path: string): boolean {\n return (schema ?? []).some(\n (child) => child.props?.href === path || schemaContainsPath(child.schema, path),\n );\n}\n\nconst MenuItemComponent: RendererComponent<\"menu-item\"> = ({ children, node }) => {\n const collapsed = useCollapsed();\n const { icon, label: rawLabel, prefix, suffix } = node.props;\n const label = rawLabel ?? \"\";\n const iconOnly = Boolean(icon);\n const flyoutIcon = icon ?? prefix?.icon ?? null;\n const currentPath = usePage().url.split(\"?\")[0];\n const testId = prefixedNodeTestId(\"menu\", node);\n const behavior = useClickBehavior(node.props);\n\n const content = icon ? (\n <IconRenderer className=\"size-lt-icon-md shrink-0\" icon={icon} />\n ) : (\n <>\n {prefix ? <MenuAffix affix={prefix} /> : null}\n {collapsed ? (\n <span\n className=\"pointer-events-none absolute top-1/2 left-full z-lt-popover ml-2 hidden -translate-y-1/2 rounded-lt-sm border border-lt-border bg-lt-popover px-2 py-1 text-sm whitespace-nowrap text-lt-popover-fg shadow-lt-md group-hover:block\"\n role=\"tooltip\"\n >\n {label}\n </span>\n ) : (\n <span>{label}</span>\n )}\n {suffix ? <MenuAffix affix={suffix} className=\"ml-auto\" /> : null}\n </>\n );\n\n const rowClassName = cn(\n rowClass,\n \"w-full\",\n collapsed && \"group relative justify-center\",\n iconOnly && \"justify-center\",\n );\n\n const triggerButton = ({ onClick, processing }: TriggerState) => (\n <button\n aria-label={collapsed || iconOnly ? label : undefined}\n className={rowClassName}\n data-test={testId}\n disabled={processing}\n onClick={onClick}\n type=\"button\"\n >\n {content}\n </button>\n );\n\n if (behavior.kind === \"action\") {\n return (\n <li>\n <ActionTrigger action={behavior.action}>{triggerButton}</ActionTrigger>\n </li>\n );\n }\n\n if (behavior.kind === \"effects\" || behavior.kind === \"modal\") {\n return <li>{triggerButton({ onClick: behavior.onClick, processing: false })}</li>;\n }\n\n if (behavior.kind === \"navigate\") {\n const active = currentPath === behavior.href;\n\n return (\n <li>\n <Link\n aria-current={active ? \"page\" : undefined}\n aria-label={collapsed || iconOnly ? label : undefined}\n as={behavior.method === \"get\" ? undefined : \"button\"}\n className={cn(rowClassName, active && \"bg-lt-muted font-medium\")}\n data-test={testId}\n href={behavior.href}\n method={behavior.method}\n >\n {content}\n </Link>\n </li>\n );\n }\n\n if (!children) {\n return collapsed ? null : (\n <li>\n <span className=\"flex items-center gap-2 px-3 py-2 text-xs font-semibold tracking-wide text-lt-muted-fg uppercase\">\n {content}\n </span>\n </li>\n );\n }\n\n if (collapsed) {\n return (\n <FlyoutGroup icon={flyoutIcon} label={label} testId={testId}>\n {children}\n </FlyoutGroup>\n );\n }\n\n return (\n <CollapsibleItem\n content={content}\n defaultOpen={schemaContainsPath(node.schema, currentPath)}\n testId={testId}\n >\n {children}\n </CollapsibleItem>\n );\n};\n\nfunction CollapsibleItem({\n children,\n content,\n defaultOpen,\n testId,\n}: {\n children: ReactNode;\n content: ReactNode;\n defaultOpen: boolean;\n testId?: string;\n}) {\n const [open, setOpen] = useState(defaultOpen);\n\n return (\n <li>\n <button\n aria-expanded={open}\n className={cn(rowClass, \"w-full\")}\n data-test={testId}\n onClick={() => setOpen((value) => !value)}\n type=\"button\"\n >\n {content}\n <Icon\n name=\"chevron-right\"\n className={cn(\n \"ml-auto size-lt-icon-md shrink-0 transition-transform\",\n open && \"rotate-90\",\n )}\n />\n </button>\n {open ? <ul className=\"mt-1 flex flex-col gap-1 pl-3\">{children}</ul> : null}\n </li>\n );\n}\n\nfunction FlyoutGroup({\n children,\n icon,\n label,\n testId,\n}: {\n children: ReactNode;\n icon?: string | null;\n label: string;\n testId?: string;\n}) {\n return (\n <li>\n <Popover\n className=\"min-w-48\"\n placement=\"right\"\n testId={testId}\n trigger={\n icon ? (\n <IconRenderer className=\"size-lt-icon-md shrink-0\" icon={icon} />\n ) : (\n <span>{label}</span>\n )\n }\n triggerClassName={cn(rowClass, \"justify-center\")}\n triggerLabel={label}\n >\n <ul className=\"flex flex-col gap-1\">\n <li className=\"px-3 py-1.5 text-xs font-semibold tracking-wide text-lt-muted-fg uppercase\">\n {label}\n </li>\n {children}\n </ul>\n </Popover>\n </li>\n );\n}\n\nexport default MenuItemComponent;\n"],"mappings":"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"}
|
|
@@ -1,12 +1,11 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { Fragment as Fragment$1, jsx } from "react/jsx-runtime";
|
|
1
|
+
import { useOutlet } from "../hooks/context.js";
|
|
2
|
+
import { Fragment, jsx } from "react/jsx-runtime";
|
|
4
3
|
//#region resources/js/layout/components/outlet.tsx
|
|
5
4
|
/**
|
|
6
5
|
* Renders the active page at the position the layout schema places it.
|
|
7
6
|
*/
|
|
8
7
|
var OutletComponent = () => {
|
|
9
|
-
return /* @__PURE__ */ jsx(Fragment
|
|
8
|
+
return /* @__PURE__ */ jsx(Fragment, { children: useOutlet() });
|
|
10
9
|
};
|
|
11
10
|
//#endregion
|
|
12
11
|
export { OutletComponent as default };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"outlet.js","names":[],"sources":["../../../resources/js/layout/components/outlet.tsx"],"sourcesContent":["import
|
|
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"}
|
|
@@ -2,8 +2,8 @@ import { usePage } from "@inertiajs/react";
|
|
|
2
2
|
import { useEffect, useState } from "react";
|
|
3
3
|
import { cn } from "@lattice-php/ui/lib/utils";
|
|
4
4
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
5
|
-
import { Popover as Popover$1, PopoverContent, PopoverTrigger } from "@lattice-php/ui/popover";
|
|
6
|
-
import {
|
|
5
|
+
import { Popover as Popover$1, PopoverContent, PopoverTrigger } from "@lattice-php/ui/primitives/popover";
|
|
6
|
+
import { CollapsedProvider } from "@lattice-php/core/collapsed-context";
|
|
7
7
|
//#region resources/js/layout/components/popover.tsx
|
|
8
8
|
/**
|
|
9
9
|
* A navigation-aware popover for the sidebar: it wraps the shared popover
|
|
@@ -33,8 +33,8 @@ function Popover({ align = "start", children, className, placement = "bottom", t
|
|
|
33
33
|
className: cn("min-w-56 p-1", className),
|
|
34
34
|
role: "menu",
|
|
35
35
|
side: placement,
|
|
36
|
-
children: /* @__PURE__ */ jsx(
|
|
37
|
-
|
|
36
|
+
children: /* @__PURE__ */ jsx(CollapsedProvider, {
|
|
37
|
+
collapsed: false,
|
|
38
38
|
children
|
|
39
39
|
})
|
|
40
40
|
})]
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"popover.js","names":[],"sources":["../../../resources/js/layout/components/popover.tsx"],"sourcesContent":["import { usePage } from \"@inertiajs/react\";\nimport { useEffect, useState } from \"react\";\nimport type { ReactNode } from \"react\";\nimport {
|
|
1
|
+
{"version":3,"file":"popover.js","names":[],"sources":["../../../resources/js/layout/components/popover.tsx"],"sourcesContent":["import { usePage } from \"@inertiajs/react\";\nimport { useEffect, useState } from \"react\";\nimport type { ReactNode } from \"react\";\nimport {\n Popover as PopoverRoot,\n PopoverContent,\n PopoverTrigger,\n} from \"@lattice-php/ui/primitives/popover\";\nimport { cn } from \"@lattice-php/ui/lib/utils\";\nimport { CollapsedProvider } from \"@lattice-php/core/collapsed-context\";\n\n/**\n * A navigation-aware popover for the sidebar: it wraps the shared popover\n * primitive (so positioning and dismissal stay consistent with the rest of the\n * app) and closes itself on every Inertia navigation. Items render expanded\n * regardless of the sidebar's collapsed state.\n */\nexport function Popover({\n align = \"start\",\n children,\n className,\n placement = \"bottom\",\n testId,\n trigger,\n triggerClassName,\n triggerLabel,\n}: {\n align?: \"start\" | \"end\";\n children: ReactNode;\n className?: string;\n placement?: \"bottom\" | \"right\" | \"top\";\n testId?: string;\n trigger: ReactNode;\n triggerClassName?: string;\n triggerLabel?: string;\n}) {\n const [open, setOpen] = useState(false);\n const url = usePage().url;\n\n useEffect(() => setOpen(false), [url]);\n\n return (\n <PopoverRoot open={open} onOpenChange={setOpen}>\n <PopoverTrigger asChild>\n <button\n aria-label={triggerLabel}\n className={cn(\"w-full\", triggerClassName)}\n data-test={testId}\n title={triggerLabel}\n type=\"button\"\n >\n {trigger}\n </button>\n </PopoverTrigger>\n <PopoverContent\n align={align}\n className={cn(\"min-w-56 p-1\", className)}\n role=\"menu\"\n side={placement}\n >\n <CollapsedProvider collapsed={false}>{children}</CollapsedProvider>\n </PopoverContent>\n </PopoverRoot>\n );\n}\n"],"mappings":";;;;;;;;;;;;;AAiBA,SAAgB,QAAQ,EACtB,QAAQ,SACR,UACA,WACA,YAAY,UACZ,QACA,SACA,kBACA,gBAUC;CACD,MAAM,CAAC,MAAM,WAAW,SAAS,KAAK;CACtC,MAAM,MAAM,QAAQ,CAAC,CAAC;CAEtB,gBAAgB,QAAQ,KAAK,GAAG,CAAC,GAAG,CAAC;CAErC,OACE,qBAAC,WAAD;EAAmB;EAAM,cAAc;EAAvC,UAAA,CACE,oBAAC,gBAAD;GAAgB,SAAA;GACd,UAAA,oBAAC,UAAD;IACE,cAAY;IACZ,WAAW,GAAG,UAAU,gBAAgB;IACxC,aAAW;IACX,OAAO;IACP,MAAK;IAEJ,UAAA;GACK,CAAA;EACM,CAAA,GAChB,oBAAC,gBAAD;GACS;GACP,WAAW,GAAG,gBAAgB,SAAS;GACvC,MAAK;GACL,MAAM;GAEN,UAAA,oBAAC,mBAAD;IAAmB,WAAW;IAAQ;GAA4B,CAAA;EACpD,CAAA,CACL;;AAEjB"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { OutletProvider } from "../hooks/context.js";
|
|
2
2
|
import { usePage } from "@inertiajs/react";
|
|
3
3
|
import { Renderer } from "@lattice-php/core/renderer";
|
|
4
4
|
import { Fragment, jsx } from "react/jsx-runtime";
|
|
@@ -12,8 +12,8 @@ import { Fragment, jsx } from "react/jsx-runtime";
|
|
|
12
12
|
function SchemaLayout({ children }) {
|
|
13
13
|
const layout = usePage().props.lattice.layout;
|
|
14
14
|
if (!layout) return /* @__PURE__ */ jsx(Fragment, { children });
|
|
15
|
-
return /* @__PURE__ */ jsx(
|
|
16
|
-
|
|
15
|
+
return /* @__PURE__ */ jsx(OutletProvider, {
|
|
16
|
+
outlet: children,
|
|
17
17
|
children: /* @__PURE__ */ jsx(Renderer, { nodes: layout.schema })
|
|
18
18
|
});
|
|
19
19
|
}
|
|
@@ -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 {
|
|
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"}
|
|
@@ -4,10 +4,10 @@ import { LATTICE_EVENT } from "@lattice-php/core/event-names";
|
|
|
4
4
|
import { cn } from "@lattice-php/ui/lib/utils";
|
|
5
5
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
6
6
|
import { nodeIdentity } from "@lattice-php/core/test-id";
|
|
7
|
-
import {
|
|
7
|
+
import { CollapsedProvider } from "@lattice-php/core/collapsed-context";
|
|
8
8
|
import { useWindowEvent } from "@lattice-php/core/hooks/use-window-event";
|
|
9
9
|
import { useMediaQuery } from "@lattice-php/ui/lib/use-media-query";
|
|
10
|
-
import { useCollapsibleState } from "@lattice-php/ui/use-collapsible-state";
|
|
10
|
+
import { useCollapsibleState } from "@lattice-php/ui/lib/use-collapsible-state";
|
|
11
11
|
//#region resources/js/layout/components/sidebar.tsx
|
|
12
12
|
var DESKTOP_QUERY = "(min-width: 768px)";
|
|
13
13
|
function matchesTarget(event, identity) {
|
|
@@ -33,8 +33,8 @@ var SidebarComponent = ({ children, node }) => {
|
|
|
33
33
|
if (event.key === "Escape") setMobileOpen(false);
|
|
34
34
|
}, { enabled: mobileOpen });
|
|
35
35
|
const isCollapsed = collapsible && collapsed && isDesktop;
|
|
36
|
-
return /* @__PURE__ */ jsxs(
|
|
37
|
-
|
|
36
|
+
return /* @__PURE__ */ jsxs(CollapsedProvider, {
|
|
37
|
+
collapsed: isCollapsed,
|
|
38
38
|
children: [mobileOpen ? /* @__PURE__ */ jsx("div", {
|
|
39
39
|
"aria-hidden": "true",
|
|
40
40
|
className: "fixed inset-0 z-lt-overlay bg-lt-overlay md:hidden",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sidebar.js","names":[],"sources":["../../../resources/js/layout/components/sidebar.tsx"],"sourcesContent":["import { router } from \"@inertiajs/react\";\nimport { useEffect, useState } from \"react\";\nimport type { RendererComponent } from \"@lattice-php/core/types\";\nimport {
|
|
1
|
+
{"version":3,"file":"sidebar.js","names":[],"sources":["../../../resources/js/layout/components/sidebar.tsx"],"sourcesContent":["import { router } from \"@inertiajs/react\";\nimport { useEffect, useState } from \"react\";\nimport type { RendererComponent } from \"@lattice-php/core/types\";\nimport { CollapsedProvider } from \"@lattice-php/core/collapsed-context\";\nimport { LATTICE_EVENT } from \"@lattice-php/core/event-names\";\nimport { useWindowEvent } from \"@lattice-php/core/hooks/use-window-event\";\nimport { nodeIdentity } from \"@lattice-php/core/test-id\";\nimport { cn } from \"@lattice-php/ui/lib/utils\";\nimport { useMediaQuery } from \"@lattice-php/ui/lib/use-media-query\";\nimport { useCollapsibleState } from \"@lattice-php/ui/lib/use-collapsible-state\";\n\nconst DESKTOP_QUERY = \"(min-width: 768px)\";\n\nfunction matchesTarget(event: Event, identity: string | undefined): boolean {\n const target = (event as CustomEvent<{ target?: string }>).detail?.target;\n\n return target == null || target === identity;\n}\n\nconst SidebarComponent: RendererComponent<\"sidebar\"> = ({ children, node }) => {\n const collapsible = node.props.collapsible;\n const rememberState = node.props.rememberState;\n const identity = nodeIdentity(node);\n const storageKey = `lattice:sidebar:${identity ?? \"default\"}`;\n const isDesktop = useMediaQuery(DESKTOP_QUERY, true);\n\n const [collapsed, toggleCollapsed] = useCollapsibleState(\n storageKey,\n false,\n collapsible && rememberState,\n );\n const [mobileOpen, setMobileOpen] = useState(false);\n\n useWindowEvent(LATTICE_EVENT.toggleSidebar, (event) => {\n if (!matchesTarget(event, identity)) {\n return;\n }\n\n if (window.matchMedia?.(DESKTOP_QUERY).matches ?? true) {\n if (collapsible) {\n toggleCollapsed();\n }\n } else {\n setMobileOpen((open) => !open);\n }\n });\n\n useEffect(() => router.on(\"navigate\", () => setMobileOpen(false)), []);\n\n useWindowEvent(\n \"keydown\",\n (event) => {\n if ((event as KeyboardEvent).key === \"Escape\") {\n setMobileOpen(false);\n }\n },\n { enabled: mobileOpen },\n );\n\n const isCollapsed = collapsible && collapsed && isDesktop;\n\n return (\n <CollapsedProvider collapsed={isCollapsed}>\n {mobileOpen ? (\n <div\n aria-hidden=\"true\"\n className=\"fixed inset-0 z-lt-overlay bg-lt-overlay md:hidden\"\n data-test=\"sidebar-backdrop\"\n onClick={() => setMobileOpen(false)}\n />\n ) : null}\n <aside\n className={cn(\n \"fixed inset-y-0 left-0 z-lt-modal flex h-svh w-72 max-w-[80vw] shrink-0 flex-col gap-4 border-r border-lt-border bg-lt-bg p-4 transition-transform\",\n \"md:sticky md:top-0 md:z-auto md:max-w-none md:translate-x-0 md:transition-[width]\",\n mobileOpen ? \"translate-x-0\" : \"-translate-x-full\",\n isCollapsed\n ? \"md:w-16 md:overflow-visible\"\n : \"md:w-64 md:overflow-x-hidden md:overflow-y-auto\",\n )}\n data-collapsed={isCollapsed ? \"true\" : \"false\"}\n data-lattice-component={identity}\n data-test=\"sidebar\"\n >\n {children}\n </aside>\n </CollapsedProvider>\n );\n};\n\nexport default SidebarComponent;\n"],"mappings":";;;;;;;;;;;AAWA,IAAM,gBAAgB;AAEtB,SAAS,cAAc,OAAc,UAAuC;CAC1E,MAAM,SAAU,MAA2C,QAAQ;CAEnE,OAAO,UAAU,QAAQ,WAAW;AACtC;AAEA,IAAM,oBAAkD,EAAE,UAAU,WAAW;CAC7E,MAAM,cAAc,KAAK,MAAM;CAC/B,MAAM,gBAAgB,KAAK,MAAM;CACjC,MAAM,WAAW,aAAa,IAAI;CAClC,MAAM,aAAa,mBAAmB,YAAY;CAClD,MAAM,YAAY,cAAc,eAAe,IAAI;CAEnD,MAAM,CAAC,WAAW,mBAAmB,oBACnC,YACA,OACA,eAAe,aACjB;CACA,MAAM,CAAC,YAAY,iBAAiB,SAAS,KAAK;CAElD,eAAe,cAAc,gBAAgB,UAAU;EACrD,IAAI,CAAC,cAAc,OAAO,QAAQ,GAChC;EAGF,IAAI,OAAO,aAAa,aAAa,CAAC,CAAC,WAAW,MAC5C;OAAA,aACF,gBAAgB;EAAA,OAGlB,eAAe,SAAS,CAAC,IAAI;CAEjC,CAAC;CAED,gBAAgB,OAAO,GAAG,kBAAkB,cAAc,KAAK,CAAC,GAAG,CAAC,CAAC;CAErE,eACE,YACC,UAAU;EACT,IAAK,MAAwB,QAAQ,UACnC,cAAc,KAAK;CAEvB,GACA,EAAE,SAAS,WAAW,CACxB;CAEA,MAAM,cAAc,eAAe,aAAa;CAEhD,OACE,qBAAC,mBAAD;EAAmB,WAAW;EAA9B,UAAA,CACG,aACC,oBAAC,OAAD;GACE,eAAY;GACZ,WAAU;GACV,aAAU;GACV,eAAe,cAAc,KAAK;EACnC,CAAA,IACC,MACJ,oBAAC,SAAD;GACE,WAAW,GACT,sJACA,qFACA,aAAa,kBAAkB,qBAC/B,cACI,gCACA,iDACN;GACA,kBAAgB,cAAc,SAAS;GACvC,0BAAwB;GACxB,aAAU;GAET;EACI,CAAA,CACU;;AAEvB"}
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { ReactNode } from 'react';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
export declare function OutletProvider({ outlet, children }: {
|
|
3
|
+
outlet: ReactNode;
|
|
4
|
+
children: ReactNode;
|
|
5
|
+
}): import("react").JSX.Element;
|
|
6
|
+
export declare function useOutlet(): ReactNode;
|
|
@@ -1,8 +1,17 @@
|
|
|
1
|
-
import { createContext } from "react";
|
|
2
|
-
import {
|
|
3
|
-
//#region resources/js/layout/hooks/context.
|
|
1
|
+
import { createContext, useContext } from "react";
|
|
2
|
+
import { jsx } from "react/jsx-runtime";
|
|
3
|
+
//#region resources/js/layout/hooks/context.tsx
|
|
4
4
|
var OutletContext = createContext(null);
|
|
5
|
+
function OutletProvider({ outlet, children }) {
|
|
6
|
+
return /* @__PURE__ */ jsx(OutletContext.Provider, {
|
|
7
|
+
value: outlet,
|
|
8
|
+
children
|
|
9
|
+
});
|
|
10
|
+
}
|
|
11
|
+
function useOutlet() {
|
|
12
|
+
return useContext(OutletContext);
|
|
13
|
+
}
|
|
5
14
|
//#endregion
|
|
6
|
-
export {
|
|
15
|
+
export { OutletProvider, useOutlet };
|
|
7
16
|
|
|
8
17
|
//# sourceMappingURL=context.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context.js","names":[],"sources":["../../../resources/js/layout/hooks/context.
|
|
1
|
+
{"version":3,"file":"context.js","names":[],"sources":["../../../resources/js/layout/hooks/context.tsx"],"sourcesContent":["import { createContext, useContext } from \"react\";\nimport type { ReactNode } from \"react\";\n\nconst OutletContext = createContext<ReactNode>(null);\n\nexport function OutletProvider({ outlet, children }: { outlet: ReactNode; children: ReactNode }) {\n return <OutletContext.Provider value={outlet}>{children}</OutletContext.Provider>;\n}\n\nexport function useOutlet(): ReactNode {\n return useContext(OutletContext);\n}\n"],"mappings":";;;AAGA,IAAM,gBAAgB,cAAyB,IAAI;AAEnD,SAAgB,eAAe,EAAE,QAAQ,YAAwD;CAC/F,OAAO,oBAAC,cAAc,UAAf;EAAwB,OAAO;EAAS;CAAiC,CAAA;AAClF;AAEA,SAAgB,YAAuB;CACrC,OAAO,WAAW,aAAa;AACjC"}
|
package/dist/layout/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export { default as Callouts } from './components/callouts.js';
|
|
2
2
|
export { layoutComponents } from './plugin.js';
|
|
3
|
-
export {
|
|
3
|
+
export { OutletProvider, useOutlet } from './hooks/context.js';
|
|
4
4
|
export { default as SchemaLayout } from './components/schema-layout.js';
|
package/dist/layout/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import Callouts from "./components/callouts.js";
|
|
2
|
-
import {
|
|
2
|
+
import { OutletProvider, useOutlet } from "./hooks/context.js";
|
|
3
3
|
import { layoutComponents } from "./plugin.js";
|
|
4
4
|
import SchemaLayout from "./components/schema-layout.js";
|
|
5
|
-
export { Callouts,
|
|
5
|
+
export { Callouts, OutletProvider, SchemaLayout, layoutComponents, useOutlet };
|
|
@@ -2,7 +2,7 @@ import { EmptyState } from "./empty-state.js";
|
|
|
2
2
|
import { NotificationItemRow } from "./notification-item.js";
|
|
3
3
|
import { useT } from "@lattice-php/ui/i18n";
|
|
4
4
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
5
|
-
import { Skeleton } from "@lattice-php/ui/skeleton";
|
|
5
|
+
import { Skeleton } from "@lattice-php/ui/primitives/skeleton";
|
|
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/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 \"@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"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { useLiveNotifications } from "../context.js";
|
|
2
|
+
import { NotificationList } from "./notification-list.js";
|
|
3
|
+
import { useT } from "@lattice-php/ui/i18n";
|
|
4
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
5
|
+
import { MODAL_MISSING_ERROR, useEmbeddedModal } from "@lattice-php/ui/modal";
|
|
6
|
+
import { Dialog, DialogContent, DialogTitle } from "@lattice-php/ui/primitives/dialog";
|
|
7
|
+
//#region resources/js/notifications/components/notifications-sheet.tsx
|
|
8
|
+
function NotificationsSheet({ onClosed }) {
|
|
9
|
+
const context = useEmbeddedModal();
|
|
10
|
+
if (!context) throw new Error(MODAL_MISSING_ERROR);
|
|
11
|
+
const store = useLiveNotifications();
|
|
12
|
+
const { t } = useT("lattice");
|
|
13
|
+
const label = t("notifications.label", "Notifications");
|
|
14
|
+
const heading = t("notifications.heading", "Notifications");
|
|
15
|
+
return /* @__PURE__ */ jsx(Dialog, {
|
|
16
|
+
open: context.open,
|
|
17
|
+
onOpenChange: context.onOpenChange,
|
|
18
|
+
children: /* @__PURE__ */ jsxs(DialogContent, {
|
|
19
|
+
"aria-describedby": void 0,
|
|
20
|
+
className: "p-0",
|
|
21
|
+
onCloseAutoFocus: (event) => {
|
|
22
|
+
context.onExited(event);
|
|
23
|
+
onClosed();
|
|
24
|
+
},
|
|
25
|
+
placement: "end",
|
|
26
|
+
width: "sm",
|
|
27
|
+
children: [/* @__PURE__ */ jsx(DialogTitle, {
|
|
28
|
+
className: "sr-only",
|
|
29
|
+
children: label
|
|
30
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
31
|
+
className: "w-full",
|
|
32
|
+
"data-test": "notifications-panel",
|
|
33
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
34
|
+
className: "flex items-center justify-between border-b border-lt-border px-3 py-2",
|
|
35
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
36
|
+
className: "text-sm font-medium",
|
|
37
|
+
children: heading
|
|
38
|
+
}), store.unreadCount > 0 ? /* @__PURE__ */ jsx("button", {
|
|
39
|
+
type: "button",
|
|
40
|
+
className: "text-xs text-lt-muted-fg hover:text-lt-fg",
|
|
41
|
+
onClick: store.markAllRead,
|
|
42
|
+
children: t("notifications.mark-all-read", "Mark all read")
|
|
43
|
+
}) : null]
|
|
44
|
+
}), /* @__PURE__ */ jsx(NotificationList, {
|
|
45
|
+
notifications: store.notifications,
|
|
46
|
+
status: store.status,
|
|
47
|
+
hasMore: store.hasMore,
|
|
48
|
+
onMarkRead: store.markRead,
|
|
49
|
+
onDismiss: store.dismiss,
|
|
50
|
+
onLoadMore: store.loadMore
|
|
51
|
+
})]
|
|
52
|
+
})]
|
|
53
|
+
})
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
//#endregion
|
|
57
|
+
export { NotificationsSheet };
|
|
58
|
+
|
|
59
|
+
//# sourceMappingURL=notifications-sheet.js.map
|
|
@@ -0,0 +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"}
|