@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.
Files changed (57) hide show
  1. package/dist/fragments/fragment.js +1 -1
  2. package/dist/fragments/fragment.js.map +1 -1
  3. package/dist/index.d.ts +3 -3
  4. package/dist/index.js +3 -3
  5. package/dist/inertia-navigation.d.ts +10 -0
  6. package/dist/inertia-navigation.js +18 -1
  7. package/dist/inertia-navigation.js.map +1 -1
  8. package/dist/layout/components/menu-item.js +3 -3
  9. package/dist/layout/components/menu-item.js.map +1 -1
  10. package/dist/layout/components/outlet.js +3 -4
  11. package/dist/layout/components/outlet.js.map +1 -1
  12. package/dist/layout/components/popover.js +4 -4
  13. package/dist/layout/components/popover.js.map +1 -1
  14. package/dist/layout/components/schema-layout.js +3 -3
  15. package/dist/layout/components/schema-layout.js.map +1 -1
  16. package/dist/layout/components/sidebar.js +4 -4
  17. package/dist/layout/components/sidebar.js.map +1 -1
  18. package/dist/layout/hooks/context.d.ts +5 -3
  19. package/dist/layout/hooks/context.js +13 -4
  20. package/dist/layout/hooks/context.js.map +1 -1
  21. package/dist/layout/index.d.ts +1 -1
  22. package/dist/layout/index.js +2 -2
  23. package/dist/notifications/components/notification-list.js +1 -1
  24. package/dist/notifications/components/notification-list.js.map +1 -1
  25. package/dist/notifications/components/notifications-sheet.d.ts +3 -0
  26. package/dist/notifications/components/notifications-sheet.js +59 -0
  27. package/dist/notifications/components/notifications-sheet.js.map +1 -0
  28. package/dist/notifications/components/notifications.js +23 -19
  29. package/dist/notifications/components/notifications.js.map +1 -1
  30. package/dist/notifications/context.d.ts +17 -0
  31. package/dist/notifications/context.js +36 -0
  32. package/dist/notifications/context.js.map +1 -0
  33. package/dist/notifications/store.d.ts +1 -1
  34. package/dist/notifications/store.js.map +1 -1
  35. package/dist/provider-base.js +9 -7
  36. package/dist/provider-base.js.map +1 -1
  37. package/dist/runtime.d.ts +7 -3
  38. package/dist/runtime.js +8 -5
  39. package/dist/types/generated.d.ts +4 -3
  40. package/dist-standalone/chunks/{chart-view-QdsrTt3D.js → chart-view-eWW-pC-B.js} +6 -6
  41. package/dist-standalone/chunks/{date-picker-field-D_QaDI9c.js → date-picker-field-FY2OOgtu.js} +1 -1
  42. package/dist-standalone/chunks/{field-DE3_bVGA.js → field-DMXnzaJF.js} +1 -1
  43. package/dist-standalone/chunks/floating-ui.dom-CAMzcZKV.js +1 -0
  44. package/dist-standalone/chunks/{input-C-Wm1w0g.js → input-0lNoXsuO.js} +1 -1
  45. package/dist-standalone/chunks/registry-context-gXwNT8GJ.js +1 -0
  46. package/dist-standalone/chunks/{rich-editor-field-B8gIiZoQ.js → rich-editor-field-B0XwZGpp.js} +4 -4
  47. package/dist-standalone/chunks/runtime-BjRIrbqh.js +162 -0
  48. package/dist-standalone/chunks/{subscriptions-C_vxf4VT.js → subscriptions-CSh5RtT7.js} +1 -1
  49. package/dist-standalone/lattice.css +1 -1
  50. package/dist-standalone/lattice.js +1 -1
  51. package/dist-standalone/manifest.json +1 -1
  52. package/dist-standalone/runtime.js +1 -1
  53. package/dist-standalone/sprite.svg +1 -1
  54. package/package.json +6 -6
  55. package/dist-standalone/chunks/floating-ui.dom-DRSJZ5ii.js +0 -1
  56. package/dist-standalone/chunks/registry-context-Q5KtSmdi.js +0 -1
  57. package/dist-standalone/chunks/runtime-uNS3QbQU.js +0 -162
@@ -1,11 +1,13 @@
1
1
  import { useNotifications } from "../store.js";
2
+ import { NotificationsBridgeProvider, createNotificationsBridge } from "../context.js";
2
3
  import { NotificationList } from "./notification-list.js";
3
- import { Component, Suspense, lazy } from "react";
4
+ import { NotificationsSheet } from "./notifications-sheet.js";
5
+ import { Component, Suspense, lazy, useCallback, useEffect, useRef, useState } from "react";
4
6
  import { Icon } from "@lattice-php/ui/icons";
5
7
  import { useT } from "@lattice-php/ui/i18n";
6
8
  import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
7
- import { Popover, PopoverContent, PopoverTrigger } from "@lattice-php/ui/popover";
8
- import { Dialog, DialogContent, DialogTitle } from "@lattice-php/ui/dialog";
9
+ import { Popover, PopoverContent, PopoverTrigger } from "@lattice-php/ui/primitives/popover";
10
+ import { useModal } from "@lattice-php/ui/modal";
9
11
  //#region resources/js/notifications/components/notifications.tsx
10
12
  var NotificationsEcho = lazy(() => import("./notifications-echo.js").then((m) => ({ default: m.NotificationsEcho })));
11
13
  var EchoBoundary = class extends Component {
@@ -26,7 +28,22 @@ var NotificationsComponent = ({ node }) => {
26
28
  endpoint: node.props.endpoint,
27
29
  pollingInterval: node.props.pollingInterval
28
30
  });
31
+ const host = useModal();
32
+ const handleRef = useRef(null);
33
+ const [bridge] = useState(() => createNotificationsBridge(store));
34
+ useEffect(() => {
35
+ bridge.publish(store);
36
+ }, [bridge, store]);
29
37
  const label = t("notifications.label", "Notifications");
38
+ const openSheet = useCallback(() => {
39
+ if (handleRef.current) return;
40
+ handleRef.current = host.open(/* @__PURE__ */ jsx(NotificationsBridgeProvider, {
41
+ value: bridge,
42
+ children: /* @__PURE__ */ jsx(NotificationsSheet, { onClosed: () => {
43
+ handleRef.current = null;
44
+ } })
45
+ }));
46
+ }, [bridge, host]);
30
47
  const trigger = /* @__PURE__ */ jsxs("span", {
31
48
  className: "relative inline-flex items-center justify-center rounded-lt-sm p-2 hover:bg-lt-muted",
32
49
  children: [/* @__PURE__ */ jsx(Icon, {
@@ -67,26 +84,13 @@ var NotificationsComponent = ({ node }) => {
67
84
  channel: node.props.channel,
68
85
  onReceive: (item) => store.receive(item)
69
86
  })
70
- }) }) : null, node.props.slideOut ? /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("button", {
87
+ }) }) : null, node.props.slideOut ? /* @__PURE__ */ jsx("button", {
71
88
  type: "button",
72
89
  "aria-label": label,
73
90
  "data-test": "notifications-trigger",
74
- onClick: () => store.setOpen(true),
91
+ onClick: openSheet,
75
92
  children: trigger
76
- }), /* @__PURE__ */ jsx(Dialog, {
77
- open: store.open,
78
- onOpenChange: store.setOpen,
79
- children: /* @__PURE__ */ jsxs(DialogContent, {
80
- "aria-describedby": void 0,
81
- className: "p-0",
82
- placement: "end",
83
- width: "sm",
84
- children: [/* @__PURE__ */ jsx(DialogTitle, {
85
- className: "sr-only",
86
- children: label
87
- }), panel]
88
- })
89
- })] }) : /* @__PURE__ */ jsxs(Popover, {
93
+ }) : /* @__PURE__ */ jsxs(Popover, {
90
94
  open: store.open,
91
95
  onOpenChange: store.setOpen,
92
96
  children: [/* @__PURE__ */ jsx(PopoverTrigger, {
@@ -1 +1 @@
1
- {"version":3,"file":"notifications.js","names":[],"sources":["../../../resources/js/notifications/components/notifications.tsx"],"sourcesContent":["import { Component, lazy, Suspense, type ReactNode } from \"react\";\nimport { Dialog, DialogContent, DialogTitle } from \"@lattice-php/ui/dialog\";\nimport { Popover as PopoverRoot, PopoverContent, PopoverTrigger } from \"@lattice-php/ui/popover\";\nimport { Icon } from \"@lattice-php/ui/icons\";\nimport { useT } from \"@lattice-php/ui/i18n\";\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 { NotificationList } from \"./notification-list\";\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\n const label = t(\"notifications.label\", \"Notifications\");\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 <>\n <button\n type=\"button\"\n aria-label={label}\n data-test=\"notifications-trigger\"\n onClick={() => store.setOpen(true)}\n >\n {trigger}\n </button>\n <Dialog open={store.open} onOpenChange={store.setOpen}>\n <DialogContent aria-describedby={undefined} className=\"p-0\" placement=\"end\" width=\"sm\">\n <DialogTitle className=\"sr-only\">{label}</DialogTitle>\n {panel}\n </DialogContent>\n </Dialog>\n </>\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":";;;;;;;;;AAUA,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;CAED,MAAM,QAAQ,EAAE,uBAAuB,eAAe;CAEtD,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,qBAAA,YAAA,EAAA,UAAA,CACE,oBAAC,UAAD;EACE,MAAK;EACL,cAAY;EACZ,aAAU;EACV,eAAe,MAAM,QAAQ,IAAI;EAEhC,UAAA;CACK,CAAA,GACR,oBAAC,QAAD;EAAQ,MAAM,MAAM;EAAM,cAAc,MAAM;EAC5C,UAAA,qBAAC,eAAD;GAAe,oBAAkB,KAAA;GAAW,WAAU;GAAM,WAAU;GAAM,OAAM;GAAlF,UAAA,CACE,oBAAC,aAAD;IAAa,WAAU;IAAW,UAAA;GAAmB,CAAA,GACpD,KACY;;CACT,CAAA,CACR,EAAA,CAAA,IAEF,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/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"}
@@ -0,0 +1,17 @@
1
+ import { UseNotificationsReturn } from './store.js';
2
+ export type NotificationsBridge = {
3
+ publish: (next: UseNotificationsReturn) => void;
4
+ subscribe: (listener: () => void) => () => void;
5
+ getSnapshot: () => UseNotificationsReturn;
6
+ };
7
+ export declare function createNotificationsBridge(initial: UseNotificationsReturn): NotificationsBridge;
8
+ export declare const NotificationsBridgeProvider: import('react').Provider<NotificationsBridge | null>;
9
+ /**
10
+ * Returns the notifications store, kept live for a component mounted outside
11
+ * the tree that owns the `useNotifications` call (the modal host renders
12
+ * host-opened content as a sibling of the page, not a descendant) — the
13
+ * bridge is a stable object the owner publishes fresh snapshots into, so
14
+ * subscribers here re-render on every publish rather than reading whatever
15
+ * props were frozen when the element was handed to `host.open()`.
16
+ */
17
+ export declare function useLiveNotifications(): UseNotificationsReturn;
@@ -0,0 +1,36 @@
1
+ import { createContext, useContext, useSyncExternalStore } from "react";
2
+ //#region resources/js/notifications/context.tsx
3
+ function createNotificationsBridge(initial) {
4
+ let snapshot = initial;
5
+ const listeners = /* @__PURE__ */ new Set();
6
+ return {
7
+ publish(next) {
8
+ snapshot = next;
9
+ listeners.forEach((listener) => listener());
10
+ },
11
+ subscribe(listener) {
12
+ listeners.add(listener);
13
+ return () => listeners.delete(listener);
14
+ },
15
+ getSnapshot: () => snapshot
16
+ };
17
+ }
18
+ var NotificationsContext = createContext(null);
19
+ var NotificationsBridgeProvider = NotificationsContext.Provider;
20
+ /**
21
+ * Returns the notifications store, kept live for a component mounted outside
22
+ * the tree that owns the `useNotifications` call (the modal host renders
23
+ * host-opened content as a sibling of the page, not a descendant) — the
24
+ * bridge is a stable object the owner publishes fresh snapshots into, so
25
+ * subscribers here re-render on every publish rather than reading whatever
26
+ * props were frozen when the element was handed to `host.open()`.
27
+ */
28
+ function useLiveNotifications() {
29
+ const bridge = useContext(NotificationsContext);
30
+ if (!bridge) throw new Error("useLiveNotifications must be used within a NotificationsBridgeProvider.");
31
+ return useSyncExternalStore(bridge.subscribe, bridge.getSnapshot);
32
+ }
33
+ //#endregion
34
+ export { NotificationsBridgeProvider, createNotificationsBridge, useLiveNotifications };
35
+
36
+ //# sourceMappingURL=context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.js","names":[],"sources":["../../resources/js/notifications/context.tsx"],"sourcesContent":["import { createContext, useContext, useSyncExternalStore } from \"react\";\nimport type { UseNotificationsReturn } from \"./store\";\n\nexport type NotificationsBridge = {\n publish: (next: UseNotificationsReturn) => void;\n subscribe: (listener: () => void) => () => void;\n getSnapshot: () => UseNotificationsReturn;\n};\n\nexport function createNotificationsBridge(initial: UseNotificationsReturn): NotificationsBridge {\n let snapshot = initial;\n const listeners = new Set<() => void>();\n\n return {\n publish(next) {\n snapshot = next;\n listeners.forEach((listener) => listener());\n },\n subscribe(listener) {\n listeners.add(listener);\n return () => listeners.delete(listener);\n },\n getSnapshot: () => snapshot,\n };\n}\n\nconst NotificationsContext = createContext<NotificationsBridge | null>(null);\n\nexport const NotificationsBridgeProvider = NotificationsContext.Provider;\n\n/**\n * Returns the notifications store, kept live for a component mounted outside\n * the tree that owns the `useNotifications` call (the modal host renders\n * host-opened content as a sibling of the page, not a descendant) — the\n * bridge is a stable object the owner publishes fresh snapshots into, so\n * subscribers here re-render on every publish rather than reading whatever\n * props were frozen when the element was handed to `host.open()`.\n */\nexport function useLiveNotifications(): UseNotificationsReturn {\n const bridge = useContext(NotificationsContext);\n\n if (!bridge) {\n throw new Error(\"useLiveNotifications must be used within a NotificationsBridgeProvider.\");\n }\n\n return useSyncExternalStore(bridge.subscribe, bridge.getSnapshot);\n}\n"],"mappings":";;AASA,SAAgB,0BAA0B,SAAsD;CAC9F,IAAI,WAAW;CACf,MAAM,4BAAY,IAAI,IAAgB;CAEtC,OAAO;EACL,QAAQ,MAAM;GACZ,WAAW;GACX,UAAU,SAAS,aAAa,SAAS,CAAC;EAC5C;EACA,UAAU,UAAU;GAClB,UAAU,IAAI,QAAQ;GACtB,aAAa,UAAU,OAAO,QAAQ;EACxC;EACA,mBAAmB;CACrB;AACF;AAEA,IAAM,uBAAuB,cAA0C,IAAI;AAE3E,IAAa,8BAA8B,qBAAqB;;;;;;;;;AAUhE,SAAgB,uBAA+C;CAC7D,MAAM,SAAS,WAAW,oBAAoB;CAE9C,IAAI,CAAC,QACH,MAAM,IAAI,MAAM,yEAAyE;CAG3F,OAAO,qBAAqB,OAAO,WAAW,OAAO,WAAW;AAClE"}
@@ -7,7 +7,7 @@ type UseNotificationsOptions = {
7
7
  endpoint: string;
8
8
  pollingInterval?: number | null;
9
9
  };
10
- type UseNotificationsReturn = {
10
+ export type UseNotificationsReturn = {
11
11
  notifications: NotificationItem[];
12
12
  unreadCount: number;
13
13
  status: NotificationsStatus;
@@ -1 +1 @@
1
- {"version":3,"file":"store.js","names":[],"sources":["../../resources/js/notifications/store.ts"],"sourcesContent":["import { useCallback, useEffect, useRef, useState } from \"react\";\nimport {\n clearAll as apiClearAll,\n dismiss as apiDismiss,\n fetchNotifications,\n markAllRead as apiMarkAllRead,\n markRead as apiMarkRead,\n} from \"./api\";\nimport type { NotificationItem } from \"./types\";\n\nexport function prependIncoming(\n list: NotificationItem[],\n item: NotificationItem,\n): NotificationItem[] {\n if (list.some((n) => n.id === item.id)) {\n return list;\n }\n\n return [item, ...list];\n}\n\nexport function markReadIn(list: NotificationItem[], id: string): NotificationItem[] {\n return list.map((n) => (n.id === id ? { ...n, isRead: true } : n));\n}\n\nexport function removeIn(list: NotificationItem[], id: string): NotificationItem[] {\n return list.filter((n) => n.id !== id);\n}\n\nexport type NotificationsStatus = \"loading\" | \"idle\" | \"error\";\n\ntype UseNotificationsOptions = {\n endpoint: string;\n pollingInterval?: number | null;\n};\n\ntype UseNotificationsReturn = {\n notifications: NotificationItem[];\n unreadCount: number;\n status: NotificationsStatus;\n hasMore: boolean;\n open: boolean;\n setOpen: (open: boolean) => void;\n loadMore: () => void;\n markRead: (id: string) => void;\n markAllRead: () => void;\n dismiss: (id: string) => void;\n clearAll: () => void;\n receive: (item: NotificationItem) => void;\n};\n\nexport function useNotifications({\n endpoint,\n pollingInterval,\n}: UseNotificationsOptions): UseNotificationsReturn {\n const [notifications, setNotifications] = useState<NotificationItem[]>([]);\n const [unreadCount, setUnreadCount] = useState(0);\n const [status, setStatus] = useState<NotificationsStatus>(\"loading\");\n const [hasMore, setHasMore] = useState(false);\n const [open, setOpen] = useState(false);\n const pageRef = useRef(1);\n const hasMoreRef = useRef(hasMore);\n hasMoreRef.current = hasMore;\n const loadingMoreRef = useRef(false);\n\n const hydrate = useCallback(async (): Promise<void> => {\n try {\n const result = await fetchNotifications(endpoint, 1);\n pageRef.current = 1;\n setNotifications(result.notifications);\n setUnreadCount(result.unreadCount);\n setHasMore(result.hasMore);\n setStatus(\"idle\");\n } catch {\n setStatus(\"error\");\n }\n }, [endpoint]);\n\n useEffect(() => {\n void hydrate();\n }, [hydrate]);\n\n useEffect(() => {\n if (!pollingInterval || pollingInterval <= 0) {\n return;\n }\n\n const timer = setInterval(() => void hydrate(), pollingInterval * 1000);\n\n return () => clearInterval(timer);\n }, [hydrate, pollingInterval]);\n\n const loadMore = useCallback((): void => {\n if (loadingMoreRef.current || !hasMoreRef.current) {\n return;\n }\n\n loadingMoreRef.current = true;\n const next = pageRef.current + 1;\n void fetchNotifications(endpoint, next)\n .then((result) => {\n pageRef.current = next;\n setNotifications((current) => [...current, ...result.notifications]);\n setHasMore(result.hasMore);\n })\n .catch(() => void hydrate())\n .finally(() => {\n loadingMoreRef.current = false;\n });\n }, [endpoint, hydrate]);\n\n const markRead = useCallback(\n (id: string): void => {\n setNotifications((current) => markReadIn(current, id));\n setUnreadCount((count) => Math.max(0, count - 1));\n void apiMarkRead(endpoint, id)\n .then((r) => setUnreadCount(r.unreadCount))\n .catch(() => void hydrate());\n },\n [endpoint, hydrate],\n );\n\n const markAllRead = useCallback((): void => {\n setNotifications((current) => current.map((n) => ({ ...n, isRead: true })));\n setUnreadCount(0);\n void apiMarkAllRead(endpoint)\n .then((r) => setUnreadCount(r.unreadCount))\n .catch(() => void hydrate());\n }, [endpoint, hydrate]);\n\n const dismiss = useCallback(\n (id: string): void => {\n setNotifications((current) => removeIn(current, id));\n void apiDismiss(endpoint, id)\n .then((r) => setUnreadCount(r.unreadCount))\n .catch(() => void hydrate());\n },\n [endpoint, hydrate],\n );\n\n const clearAll = useCallback((): void => {\n setNotifications([]);\n setUnreadCount(0);\n void apiClearAll(endpoint)\n .then((r) => setUnreadCount(r.unreadCount))\n .catch(() => void hydrate());\n }, [endpoint, hydrate]);\n\n const receive = useCallback((item: NotificationItem): void => {\n setNotifications((current) => {\n const next = prependIncoming(current, item);\n if (next !== current) {\n setUnreadCount((count) => count + 1);\n }\n return next;\n });\n }, []);\n\n return {\n notifications,\n unreadCount,\n status,\n hasMore,\n open,\n setOpen,\n loadMore,\n markRead,\n markAllRead,\n dismiss,\n clearAll,\n receive,\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"store.js","names":[],"sources":["../../resources/js/notifications/store.ts"],"sourcesContent":["import { useCallback, useEffect, useRef, useState } from \"react\";\nimport {\n clearAll as apiClearAll,\n dismiss as apiDismiss,\n fetchNotifications,\n markAllRead as apiMarkAllRead,\n markRead as apiMarkRead,\n} from \"./api\";\nimport type { NotificationItem } from \"./types\";\n\nexport function prependIncoming(\n list: NotificationItem[],\n item: NotificationItem,\n): NotificationItem[] {\n if (list.some((n) => n.id === item.id)) {\n return list;\n }\n\n return [item, ...list];\n}\n\nexport function markReadIn(list: NotificationItem[], id: string): NotificationItem[] {\n return list.map((n) => (n.id === id ? { ...n, isRead: true } : n));\n}\n\nexport function removeIn(list: NotificationItem[], id: string): NotificationItem[] {\n return list.filter((n) => n.id !== id);\n}\n\nexport type NotificationsStatus = \"loading\" | \"idle\" | \"error\";\n\ntype UseNotificationsOptions = {\n endpoint: string;\n pollingInterval?: number | null;\n};\n\nexport type UseNotificationsReturn = {\n notifications: NotificationItem[];\n unreadCount: number;\n status: NotificationsStatus;\n hasMore: boolean;\n open: boolean;\n setOpen: (open: boolean) => void;\n loadMore: () => void;\n markRead: (id: string) => void;\n markAllRead: () => void;\n dismiss: (id: string) => void;\n clearAll: () => void;\n receive: (item: NotificationItem) => void;\n};\n\nexport function useNotifications({\n endpoint,\n pollingInterval,\n}: UseNotificationsOptions): UseNotificationsReturn {\n const [notifications, setNotifications] = useState<NotificationItem[]>([]);\n const [unreadCount, setUnreadCount] = useState(0);\n const [status, setStatus] = useState<NotificationsStatus>(\"loading\");\n const [hasMore, setHasMore] = useState(false);\n const [open, setOpen] = useState(false);\n const pageRef = useRef(1);\n const hasMoreRef = useRef(hasMore);\n hasMoreRef.current = hasMore;\n const loadingMoreRef = useRef(false);\n\n const hydrate = useCallback(async (): Promise<void> => {\n try {\n const result = await fetchNotifications(endpoint, 1);\n pageRef.current = 1;\n setNotifications(result.notifications);\n setUnreadCount(result.unreadCount);\n setHasMore(result.hasMore);\n setStatus(\"idle\");\n } catch {\n setStatus(\"error\");\n }\n }, [endpoint]);\n\n useEffect(() => {\n void hydrate();\n }, [hydrate]);\n\n useEffect(() => {\n if (!pollingInterval || pollingInterval <= 0) {\n return;\n }\n\n const timer = setInterval(() => void hydrate(), pollingInterval * 1000);\n\n return () => clearInterval(timer);\n }, [hydrate, pollingInterval]);\n\n const loadMore = useCallback((): void => {\n if (loadingMoreRef.current || !hasMoreRef.current) {\n return;\n }\n\n loadingMoreRef.current = true;\n const next = pageRef.current + 1;\n void fetchNotifications(endpoint, next)\n .then((result) => {\n pageRef.current = next;\n setNotifications((current) => [...current, ...result.notifications]);\n setHasMore(result.hasMore);\n })\n .catch(() => void hydrate())\n .finally(() => {\n loadingMoreRef.current = false;\n });\n }, [endpoint, hydrate]);\n\n const markRead = useCallback(\n (id: string): void => {\n setNotifications((current) => markReadIn(current, id));\n setUnreadCount((count) => Math.max(0, count - 1));\n void apiMarkRead(endpoint, id)\n .then((r) => setUnreadCount(r.unreadCount))\n .catch(() => void hydrate());\n },\n [endpoint, hydrate],\n );\n\n const markAllRead = useCallback((): void => {\n setNotifications((current) => current.map((n) => ({ ...n, isRead: true })));\n setUnreadCount(0);\n void apiMarkAllRead(endpoint)\n .then((r) => setUnreadCount(r.unreadCount))\n .catch(() => void hydrate());\n }, [endpoint, hydrate]);\n\n const dismiss = useCallback(\n (id: string): void => {\n setNotifications((current) => removeIn(current, id));\n void apiDismiss(endpoint, id)\n .then((r) => setUnreadCount(r.unreadCount))\n .catch(() => void hydrate());\n },\n [endpoint, hydrate],\n );\n\n const clearAll = useCallback((): void => {\n setNotifications([]);\n setUnreadCount(0);\n void apiClearAll(endpoint)\n .then((r) => setUnreadCount(r.unreadCount))\n .catch(() => void hydrate());\n }, [endpoint, hydrate]);\n\n const receive = useCallback((item: NotificationItem): void => {\n setNotifications((current) => {\n const next = prependIncoming(current, item);\n if (next !== current) {\n setUnreadCount((count) => count + 1);\n }\n return next;\n });\n }, []);\n\n return {\n notifications,\n unreadCount,\n status,\n hasMore,\n open,\n setOpen,\n loadMore,\n markRead,\n markAllRead,\n dismiss,\n clearAll,\n receive,\n };\n}\n"],"mappings":"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"}
@@ -2,27 +2,29 @@ import { updateAppearance } from "./appearance/index.js";
2
2
  import { Toaster } from "./toast/toaster.js";
3
3
  import { useFlashEffects } from "./effects/use-flash-effects.js";
4
4
  import { EventBridge } from "./event-bridge.js";
5
- import { inertiaNavigation } from "./inertia-navigation.js";
6
- import { RegistryContext } from "@lattice-php/core/registry-context";
5
+ import { inertiaNavigation, useCloseModalsOnNavigate } from "./inertia-navigation.js";
6
+ import { RegistryProvider } from "@lattice-php/core/registry-context";
7
7
  import { jsx, jsxs } from "react/jsx-runtime";
8
8
  import { ActionInteractionProvider } from "@lattice-php/action/components/action-trigger-provider";
9
9
  import { NavigationProvider } from "@lattice-php/ui/navigation";
10
+ import { ModalProvider } from "@lattice-php/ui/modal";
10
11
  import { SpriteProvider } from "@lattice-php/ui/icons/sprite";
11
12
  //#region resources/js/provider-base.tsx
12
13
  var defaultSprite = { href: "" };
13
14
  function ProviderBase({ children, registry, sprite = defaultSprite, toaster = true }) {
14
15
  useFlashEffects();
15
- return /* @__PURE__ */ jsx(RegistryContext.Provider, {
16
- value: registry,
16
+ useCloseModalsOnNavigate();
17
+ return /* @__PURE__ */ jsx(RegistryProvider, {
18
+ registry,
17
19
  children: /* @__PURE__ */ jsx(NavigationProvider, {
18
20
  adapter: inertiaNavigation,
19
- children: /* @__PURE__ */ jsx(ActionInteractionProvider, { children: /* @__PURE__ */ jsxs(SpriteProvider, {
21
+ children: /* @__PURE__ */ jsx(ActionInteractionProvider, { children: /* @__PURE__ */ jsx(SpriteProvider, {
20
22
  sprite,
21
- children: [
23
+ children: /* @__PURE__ */ jsxs(ModalProvider, { children: [
22
24
  children,
23
25
  /* @__PURE__ */ jsx(EventBridge, { onAppearanceChange: updateAppearance }),
24
26
  toaster ? /* @__PURE__ */ jsx(Toaster, {}) : null
25
- ]
27
+ ] })
26
28
  }) })
27
29
  })
28
30
  });
@@ -1 +1 @@
1
- {"version":3,"file":"provider-base.js","names":[],"sources":["../resources/js/provider-base.tsx"],"sourcesContent":["import type { ReactNode } from \"react\";\nimport { ActionInteractionProvider } from \"@lattice-php/action/components/action-trigger-provider\";\nimport type { Registry } from \"@lattice-php/core/registry\";\nimport { RegistryContext } from \"@lattice-php/core/registry-context\";\nimport { useFlashEffects } from \"./effects/use-flash-effects\";\nimport { NavigationProvider } from \"@lattice-php/ui/navigation\";\nimport { EventBridge } from \"./event-bridge\";\nimport { inertiaNavigation } from \"./inertia-navigation\";\nimport type { SpriteValue } from \"@lattice-php/ui/icons/sprite\";\nimport { SpriteProvider } from \"@lattice-php/ui/icons/sprite\";\nimport { Toaster } from \"./toast\";\nimport { updateAppearance } from \"./appearance\";\n\nconst defaultSprite: SpriteValue = { href: \"\" };\n\nexport type ProviderBaseProps = {\n children: ReactNode;\n registry: Registry;\n sprite?: SpriteValue;\n toaster?: boolean;\n};\n\nexport function ProviderBase({\n children,\n registry,\n sprite = defaultSprite,\n toaster = true,\n}: ProviderBaseProps) {\n useFlashEffects();\n\n return (\n <RegistryContext.Provider value={registry}>\n <NavigationProvider adapter={inertiaNavigation}>\n <ActionInteractionProvider>\n <SpriteProvider sprite={sprite}>\n {children}\n <EventBridge onAppearanceChange={updateAppearance} />\n {toaster ? <Toaster /> : null}\n </SpriteProvider>\n </ActionInteractionProvider>\n </NavigationProvider>\n </RegistryContext.Provider>\n );\n}\n"],"mappings":";;;;;;;;;;;AAaA,IAAM,gBAA6B,EAAE,MAAM,GAAG;AAS9C,SAAgB,aAAa,EAC3B,UACA,UACA,SAAS,eACT,UAAU,QACU;CACpB,gBAAgB;CAEhB,OACE,oBAAC,gBAAgB,UAAjB;EAA0B,OAAO;EAC/B,UAAA,oBAAC,oBAAD;GAAoB,SAAS;GAC3B,UAAA,oBAAC,2BAAD,EAAA,UACE,qBAAC,gBAAD;IAAwB;IAAxB,UAAA;KACG;KACD,oBAAC,aAAD,EAAa,oBAAoB,iBAAmB,CAAA;KACnD,UAAU,oBAAC,SAAD,CAAU,CAAA,IAAI;IACX;GACS,CAAA,EAAA,CAAA;EACT,CAAA;CACI,CAAA;AAE9B"}
1
+ {"version":3,"file":"provider-base.js","names":[],"sources":["../resources/js/provider-base.tsx"],"sourcesContent":["import type { ReactNode } from \"react\";\nimport { ActionInteractionProvider } from \"@lattice-php/action/components/action-trigger-provider\";\nimport type { Registry } from \"@lattice-php/core/registry\";\nimport { RegistryProvider } from \"@lattice-php/core/registry-context\";\nimport { useFlashEffects } from \"./effects/use-flash-effects\";\nimport { NavigationProvider } from \"@lattice-php/ui/navigation\";\nimport { ModalProvider } from \"@lattice-php/ui/modal\";\nimport { EventBridge } from \"./event-bridge\";\nimport { inertiaNavigation, useCloseModalsOnNavigate } from \"./inertia-navigation\";\nimport type { SpriteValue } from \"@lattice-php/ui/icons/sprite\";\nimport { SpriteProvider } from \"@lattice-php/ui/icons/sprite\";\nimport { Toaster } from \"./toast\";\nimport { updateAppearance } from \"./appearance\";\n\nconst defaultSprite: SpriteValue = { href: \"\" };\n\nexport type ProviderBaseProps = {\n children: ReactNode;\n registry: Registry;\n sprite?: SpriteValue;\n toaster?: boolean;\n};\n\nexport function ProviderBase({\n children,\n registry,\n sprite = defaultSprite,\n toaster = true,\n}: ProviderBaseProps) {\n useFlashEffects();\n useCloseModalsOnNavigate();\n\n return (\n <RegistryProvider registry={registry}>\n <NavigationProvider adapter={inertiaNavigation}>\n <ActionInteractionProvider>\n <SpriteProvider sprite={sprite}>\n <ModalProvider>\n {children}\n <EventBridge onAppearanceChange={updateAppearance} />\n {toaster ? <Toaster /> : null}\n </ModalProvider>\n </SpriteProvider>\n </ActionInteractionProvider>\n </NavigationProvider>\n </RegistryProvider>\n );\n}\n"],"mappings":";;;;;;;;;;;;AAcA,IAAM,gBAA6B,EAAE,MAAM,GAAG;AAS9C,SAAgB,aAAa,EAC3B,UACA,UACA,SAAS,eACT,UAAU,QACU;CACpB,gBAAgB;CAChB,yBAAyB;CAEzB,OACE,oBAAC,kBAAD;EAA4B;EAC1B,UAAA,oBAAC,oBAAD;GAAoB,SAAS;GAC3B,UAAA,oBAAC,2BAAD,EAAA,UACE,oBAAC,gBAAD;IAAwB;IACtB,UAAA,qBAAC,eAAD,EAAA,UAAA;KACG;KACD,oBAAC,aAAD,EAAa,oBAAoB,iBAAmB,CAAA;KACnD,UAAU,oBAAC,SAAD,CAAU,CAAA,IAAI;IACZ,EAAA,CAAA;GACD,CAAA,EACS,CAAA;EACT,CAAA;CACJ,CAAA;AAEtB"}
package/dist/runtime.d.ts CHANGED
@@ -2,7 +2,9 @@ export * from './index.js';
2
2
  export { router } from '@inertiajs/react';
3
3
  export { inertiaNavigation, navigationPlugin } from './inertia-navigation.js';
4
4
  export { defaultNavigation, NavigationProvider, useNavigation } from '@lattice-php/ui/navigation';
5
- export { runAction } from '@lattice-php/action';
5
+ export { callAction, runAction, useCallAction } from '@lattice-php/action';
6
+ export type { CallActionResult } from '@lattice-php/action';
7
+ export { ActionConfirmOverlay } from '@lattice-php/action/components/action-confirm-overlay';
6
8
  export { apiFetch, apiJson, setRefRefreshEndpoint, xsrfToken } from '@lattice-php/core/api';
7
9
  export { useExtensionRegistry } from '@lattice-php/core/registry-context';
8
10
  export { RenderNode } from '@lattice-php/core/renderer';
@@ -14,8 +16,10 @@ export { RICH_EDITOR_EXTENSION, ToolbarIconButton } from '@lattice-php/form/rich
14
16
  export * from '@lattice-php/form/toolkit';
15
17
  export { useTable } from '@lattice-php/table/hooks/use-table';
16
18
  export { useTableSelection } from '@lattice-php/table/hooks/use-table-selection';
17
- export { getBulkActions } from '@lattice-php/table/lib/bulk';
18
- export { Badge, Button, Checkbox, cn, CodeBlock, Combobox, ConfirmDialog, CopyButton, Dialog, DialogContent, DialogHeader, formatDateValue, IconButton, InfoTooltip, Input, Label, NativeSelect, PreviewableImage, SegmentedPills, Spinner, Textarea, useDebouncedCallback, useFormatContext, usePersistentState, } from '@lattice-php/ui';
19
+ export { getBulkActionNodes } from '@lattice-php/table/lib/bulk';
20
+ export { useAction } from '@lattice-php/action/hooks/use-action';
21
+ export { MODAL_MISSING_ERROR, useEmbeddedModal, useModal } from '@lattice-php/ui/modal';
22
+ export { Badge, Button, Checkbox, cn, CodeBlock, Combobox, ConfirmDialog, CopyButton, Dialog, DialogContent, DialogHeader, DialogTitle, formatDateValue, IconButton, InfoTooltip, Input, Label, NativeSelect, PreviewableImage, SegmentedControl, Spinner, Textarea, useDebouncedCallback, useFormatContext, usePersistentState, } from '@lattice-php/ui';
19
23
  export * from '@lattice-php/ui/i18n';
20
24
  export { announce, attachTreeItemInstruction, combine, draggable, dropTargetForElements, extractTreeItemInstruction, } from './dnd/index.js';
21
25
  export type { Variant } from './toast/index.js';
package/dist/runtime.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 { OutletContext, SidebarCollapsedContext, useSidebarCollapsed } from "./layout/hooks/context.js";
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,15 +21,18 @@ import { useExtensionRegistry } from "@lattice-php/core/registry-context";
21
21
  import { RenderNode } from "@lattice-php/core/renderer";
22
22
  import { nodeIdentity } from "@lattice-php/core/test-id";
23
23
  import { NavigationProvider, defaultNavigation, useNavigation } from "@lattice-php/ui/navigation";
24
- import { Badge, Button, Checkbox, CodeBlock, Combobox, ConfirmDialog, CopyButton, Dialog, DialogContent, DialogHeader, IconButton, InfoTooltip, Input, Label, NativeSelect, PreviewableImage, SegmentedPills, Spinner, Textarea, cn, formatDateValue, useDebouncedCallback, useFormatContext, usePersistentState } from "@lattice-php/ui";
25
- import { runAction } from "@lattice-php/action";
24
+ import { MODAL_MISSING_ERROR, useEmbeddedModal, useModal } from "@lattice-php/ui/modal";
25
+ import { Badge, Button, Checkbox, CodeBlock, Combobox, ConfirmDialog, CopyButton, Dialog, DialogContent, DialogHeader, DialogTitle, IconButton, InfoTooltip, Input, Label, NativeSelect, PreviewableImage, SegmentedControl, Spinner, Textarea, cn, formatDateValue, useDebouncedCallback, useFormatContext, usePersistentState } from "@lattice-php/ui";
26
+ import { callAction, runAction, useCallAction } from "@lattice-php/action";
27
+ import { ActionConfirmOverlay } from "@lattice-php/action/components/action-confirm-overlay";
26
28
  import { coerceColor, toneProps } from "@lattice-php/ui/lib/color";
27
29
  import { requestSignedUpload, xhrTransfer } from "@lattice-php/core/upload";
28
30
  import { SimpleField } from "@lattice-php/form/components/fields/simple-field";
29
31
  import { RICH_EDITOR_EXTENSION, ToolbarIconButton } from "@lattice-php/form/rich-editor";
30
32
  import { useTable } from "@lattice-php/table/hooks/use-table";
31
33
  import { useTableSelection } from "@lattice-php/table/hooks/use-table-selection";
32
- import { getBulkActions } from "@lattice-php/table/lib/bulk";
34
+ import { getBulkActionNodes } from "@lattice-php/table/lib/bulk";
35
+ import { useAction } from "@lattice-php/action/hooks/use-action";
33
36
  export * from "@lattice-php/ui/i18n";
34
37
  export * from "@lattice-php/form/toolkit";
35
- export { Badge, Button, Callouts, Checkbox, CodeBlock, Combobox, ConfirmDialog, CopyButton, Dialog, DialogContent, DialogHeader, EventBridge, Icon, IconButton, IconRenderer, IconRendererProvider, InfoTooltip, Input, LATTICE_EVENT, LATTICE_REF_HEADER, Label, NativeSelect, NavigationProvider, OutletContext, PreviewableImage, Provider, RICH_EDITOR_EXTENSION, RealtimeListeners, RenderNode, Renderer, SchemaLayout, SegmentedPills, SidebarCollapsedContext, SimpleField, Spinner, SpriteProvider, Textarea, Toaster, ToolbarIconButton, announce, apiFetch, apiJson, attachTreeItemInstruction, builtinEffectHandlers, cn, coerceColor, columnCell, combine, copyToClipboard, createLatticeApp, createLayoutResolver, createPageResolver, createRegistry, defaultNavigation, dispatchActionError, dispatchEffects, draggable, dropTargetForElements, eagerComponent, effectHandler, extendRegistry, extractTreeItemInstruction, formatDateValue, getActionEffects, getBulkActions, inertiaNavigation, initializeAppearance, isActionEffect, layoutComponents, lazyComponent, loadPluginModules, mergeEffectHandlers, navigationPlugin, nodeIdentity, onCallout, onToast, pageComponentName, registry, requestSignedUpload, router, runAction, setRefRefreshEndpoint, toneProps, updateAppearance, useAppearance, useColumnRegistry, useComponentRegistry, useDebouncedCallback, useEffectDispatcher, useExtensionRegistry, useFormatContext, useNavigation, usePersistentState, useSidebarCollapsed, useTable, useTableSelection, withHeaders, withRefHeader, withVisitHeaders, xhrTransfer, xsrfToken };
38
+ export { ActionConfirmOverlay, Badge, Button, Callouts, Checkbox, CodeBlock, Combobox, ConfirmDialog, CopyButton, Dialog, DialogContent, DialogHeader, DialogTitle, EventBridge, Icon, IconButton, IconRenderer, IconRendererProvider, InfoTooltip, Input, LATTICE_EVENT, LATTICE_REF_HEADER, Label, MODAL_MISSING_ERROR, NativeSelect, NavigationProvider, OutletProvider, PreviewableImage, Provider, RICH_EDITOR_EXTENSION, RealtimeListeners, RenderNode, Renderer, SchemaLayout, SegmentedControl, SimpleField, Spinner, SpriteProvider, Textarea, Toaster, ToolbarIconButton, announce, apiFetch, apiJson, attachTreeItemInstruction, builtinEffectHandlers, callAction, cn, coerceColor, columnCell, combine, copyToClipboard, createLatticeApp, createLayoutResolver, createPageResolver, createRegistry, defaultNavigation, dispatchActionError, dispatchEffects, draggable, dropTargetForElements, eagerComponent, effectHandler, extendRegistry, extractTreeItemInstruction, formatDateValue, getActionEffects, getBulkActionNodes, inertiaNavigation, initializeAppearance, isActionEffect, layoutComponents, lazyComponent, loadPluginModules, mergeEffectHandlers, navigationPlugin, nodeIdentity, onCallout, onToast, pageComponentName, registry, requestSignedUpload, router, runAction, setRefRefreshEndpoint, toneProps, updateAppearance, useAction, useAppearance, useCallAction, useColumnRegistry, useComponentRegistry, useDebouncedCallback, useEffectDispatcher, useEmbeddedModal, useExtensionRegistry, useFormatContext, useModal, useNavigation, useOutlet, usePersistentState, useTable, useTableSelection, withHeaders, withRefHeader, withVisitHeaders, xhrTransfer, xsrfToken };
@@ -32,8 +32,8 @@ export type Dropdown = {
32
32
  trigger: Node[];
33
33
  };
34
34
  export type FilterNodeType = "filter.date-range" | "filter.media-type" | "filter.select" | "filter.ternary" | "filter.toggle";
35
- export type FormFieldNodeType = "field.builder" | "field.checkbox" | "field.choice" | "field.color-picker" | "field.date-input" | "field.date-time-input" | "field.file-upload" | "field.hidden-input" | "field.media-picker" | "field.number-input" | "field.otp" | "field.password-input" | "field.pattern-input" | "field.repeater" | "field.rich-editor" | "field.select" | "field.text-input" | "field.textarea" | "field.time-input" | "field.toggle" | "wizard" | "wizard-step";
36
- export type FormNodeType = "field.builder" | "field.checkbox" | "field.choice" | "field.color-picker" | "field.date-input" | "field.date-time-input" | "field.file-upload" | "field.hidden-input" | "field.media-picker" | "field.number-input" | "field.otp" | "field.password-input" | "field.pattern-input" | "field.repeater" | "field.rich-editor" | "field.select" | "field.text-input" | "field.textarea" | "field.time-input" | "field.toggle" | "form" | "wizard" | "wizard-step";
35
+ export type FormFieldNodeType = "field.builder" | "field.checkbox" | "field.choice" | "field.color-picker" | "field.date-input" | "field.date-time-input" | "field.file-upload" | "field.hidden-input" | "field.media-picker" | "field.number-input" | "field.otp" | "field.password-input" | "field.pattern-input" | "field.repeater" | "field.rich-editor" | "field.select" | "field.text-input" | "field.textarea" | "field.time-input" | "field.toggle" | "field.tree" | "wizard" | "wizard-step";
36
+ export type FormNodeType = "field.builder" | "field.checkbox" | "field.choice" | "field.color-picker" | "field.date-input" | "field.date-time-input" | "field.file-upload" | "field.hidden-input" | "field.media-picker" | "field.number-input" | "field.otp" | "field.password-input" | "field.pattern-input" | "field.repeater" | "field.rich-editor" | "field.select" | "field.text-input" | "field.textarea" | "field.time-input" | "field.toggle" | "field.tree" | "form" | "wizard" | "wizard-step";
37
37
  export type Fragment = {
38
38
  endpoint: string | null;
39
39
  lazy: boolean;
@@ -68,10 +68,11 @@ export type MenuItem = {
68
68
  icon: string | null;
69
69
  label: string | null;
70
70
  method: HttpMethod | null;
71
+ modal: Node<"modal"> | null;
71
72
  prefix: Affix | null;
72
73
  suffix: Affix | null;
73
74
  };
74
- export type NodeType = "action" | "action.bulk" | "action.group" | "api-reference" | "avatar" | "badge" | "breadcrumbs" | "button" | "calendar" | "callouts" | "card" | "chart" | "chat.box" | "chat.part.text" | "chat.part.tool-call" | "code-block" | "collapsible" | "description-list" | "dropdown" | "entry.badge" | "entry.boolean" | "entry.component" | "entry.date" | "entry.text" | "field.builder" | "field.checkbox" | "field.choice" | "field.color-picker" | "field.date-input" | "field.date-time-input" | "field.file-upload" | "field.hidden-input" | "field.media-picker" | "field.number-input" | "field.otp" | "field.password-input" | "field.pattern-input" | "field.repeater" | "field.rich-editor" | "field.select" | "field.text-input" | "field.textarea" | "field.time-input" | "field.toggle" | "floating-panel" | "form" | "fragment" | "grid" | "heading" | "icon" | "image" | "link" | "map" | "media.library" | "menu" | "menu-item" | "modal" | "notifications" | "outlet" | "pdf" | "progress" | "raw-block" | "remote.data-list" | "search.box" | "search.categories" | "search.input" | "search.preview" | "search.recent" | "search.results" | "section" | "segmented-control" | "separator" | "sidebar" | "sidebar.footer" | "signature" | "stack" | "tab" | "table" | "tabs" | "text" | "tooltip" | "topbar" | "tree" | "wizard" | "wizard-step";
75
+ export type NodeType = "action" | "action.bulk" | "action.group" | "api-reference" | "avatar" | "badge" | "breadcrumbs" | "button" | "calendar" | "callouts" | "card" | "chart" | "chat.box" | "chat.part.text" | "chat.part.tool-call" | "code-block" | "collapsible" | "description-list" | "dropdown" | "entry.badge" | "entry.boolean" | "entry.component" | "entry.date" | "entry.text" | "field.builder" | "field.checkbox" | "field.choice" | "field.color-picker" | "field.date-input" | "field.date-time-input" | "field.file-upload" | "field.hidden-input" | "field.media-picker" | "field.number-input" | "field.otp" | "field.password-input" | "field.pattern-input" | "field.repeater" | "field.rich-editor" | "field.select" | "field.text-input" | "field.textarea" | "field.time-input" | "field.toggle" | "field.tree" | "floating-panel" | "form" | "fragment" | "grid" | "heading" | "icon" | "image" | "link" | "map" | "media.library" | "menu" | "menu-item" | "modal" | "notifications" | "outlet" | "pdf" | "progress" | "raw-block" | "remote.data-list" | "search.box" | "search.categories" | "search.input" | "search.preview" | "search.recent" | "search.results" | "section" | "segmented-control" | "separator" | "sidebar" | "sidebar.footer" | "signature" | "stack" | "tab" | "table" | "tabs" | "text" | "tooltip" | "topbar" | "tree" | "wizard" | "wizard-step";
75
76
  export type NotificationItem = {
76
77
  readonly actions: Node[];
77
78
  readonly body: Translatable | string | null;