@lattice-php/lattice 0.16.0 → 0.17.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/action/components/action-form.js +1 -1
- package/dist/action/use-action.js +1 -1
- package/dist/chat/types.d.ts +2 -10
- package/dist/core/components/button.js +34 -18
- package/dist/core/components/button.js.map +1 -1
- package/dist/core/components/control.d.ts +0 -2
- package/dist/core/components/control.js.map +1 -1
- package/dist/core/components/link.js +25 -29
- package/dist/core/components/link.js.map +1 -1
- package/dist/core/types.d.ts +22 -42
- package/dist/core/use-click-behavior.d.ts +42 -0
- package/dist/core/use-click-behavior.js +46 -0
- package/dist/core/use-click-behavior.js.map +1 -0
- package/dist/create-app.d.ts +8 -2
- package/dist/create-app.js +4 -2
- package/dist/create-app.js.map +1 -1
- package/dist/effects/registry.d.ts +9 -20
- package/dist/effects/registry.js +4 -6
- package/dist/effects/registry.js.map +1 -1
- package/dist/events/event-bridge.d.ts +1 -1
- package/dist/events/event-bridge.js +1 -1
- package/dist/events/event-bridge.js.map +1 -1
- package/dist/form/components/base/input-otp.d.ts +2 -1
- package/dist/form/components/base/input-otp.js.map +1 -1
- package/dist/form/components/conditions.d.ts +1 -1
- package/dist/form/components/conditions.js.map +1 -1
- package/dist/form/components/field-props.d.ts +2 -1
- package/dist/form/components/field-props.js.map +1 -1
- package/dist/form/components/field-scope.d.ts +2 -1
- package/dist/form/components/field-scope.js.map +1 -1
- package/dist/form/components/fields/row-action-menu.d.ts +2 -1
- package/dist/form/components/fields/row-action-menu.js.map +1 -1
- package/dist/form/components/fields/row-item.d.ts +2 -1
- package/dist/form/components/fields/row-item.js.map +1 -1
- package/dist/form/components/fields/table-rows.d.ts +2 -1
- package/dist/form/components/fields/table-rows.js.map +1 -1
- package/dist/form/components/fields/time-picker-columns.d.ts +2 -1
- package/dist/form/components/fields/time-picker-columns.js.map +1 -1
- package/dist/form/components/fields/time-picker.d.ts +2 -1
- package/dist/form/components/fields/time-picker.js.map +1 -1
- package/dist/form/components/fields/use-row-collection.d.ts +2 -1
- package/dist/form/components/fields/use-row-collection.js.map +1 -1
- package/dist/form/components/form-path.d.ts +0 -1
- package/dist/form/components/form-path.js +1 -1
- package/dist/form/components/form-path.js.map +1 -1
- package/dist/form/components/prefill-targets.d.ts +1 -1
- package/dist/form/components/prefill-targets.js.map +1 -1
- package/dist/form/components/types.d.ts +5 -1
- package/dist/form/components/use-field-commit.d.ts +2 -1
- package/dist/form/components/use-field-commit.js.map +1 -1
- package/dist/form/components/use-form-resolver.d.ts +2 -1
- package/dist/form/components/use-form-resolver.js.map +1 -1
- package/dist/format/date-time.d.ts +12 -0
- package/dist/format/date-time.js +30 -0
- package/dist/format/date-time.js.map +1 -0
- package/dist/format/value.js +1 -1
- package/dist/format/value.js.map +1 -1
- package/dist/i18n/config.d.ts +2 -1
- package/dist/i18n/config.js.map +1 -1
- package/dist/i18n/date-time.js +1 -1
- package/dist/i18n/date-time.js.map +1 -1
- package/dist/i18n/instance.d.ts +1 -1
- package/dist/i18n/instance.js.map +1 -1
- package/dist/i18n/locale-reload.d.ts +2 -1
- package/dist/i18n/locale-reload.js.map +1 -1
- package/dist/index.js +1 -1
- package/dist/layout/components.js +1 -1
- package/dist/layout/menu-item.js +43 -49
- package/dist/layout/menu-item.js.map +1 -1
- package/dist/notifications/api.d.ts +6 -0
- package/dist/notifications/api.js +21 -0
- package/dist/notifications/api.js.map +1 -0
- package/dist/notifications/components/empty-state.d.ts +1 -0
- package/dist/notifications/components/empty-state.js +21 -0
- package/dist/notifications/components/empty-state.js.map +1 -0
- package/dist/notifications/components/notification-item.d.ts +6 -0
- package/dist/notifications/components/notification-item.js +65 -0
- package/dist/notifications/components/notification-item.js.map +1 -0
- package/dist/notifications/components/notification-list.d.ts +10 -0
- package/dist/notifications/components/notification-list.js +38 -0
- package/dist/notifications/components/notification-list.js.map +1 -0
- package/dist/notifications/components/notifications-echo.d.ts +5 -0
- package/dist/notifications/components/notifications-echo.js +22 -0
- package/dist/notifications/components/notifications-echo.js.map +1 -0
- package/dist/notifications/components/notifications.d.ts +3 -0
- package/dist/notifications/components/notifications.js +109 -0
- package/dist/notifications/components/notifications.js.map +1 -0
- package/dist/notifications/index.d.ts +1 -0
- package/dist/notifications/index.js +11 -0
- package/dist/notifications/index.js.map +1 -0
- package/dist/notifications/store.d.ts +25 -0
- package/dist/notifications/store.js +100 -0
- package/dist/notifications/store.js.map +1 -0
- package/dist/notifications/types.d.ts +10 -0
- package/dist/notifications/types.js +0 -0
- package/dist/realtime/build-effects.d.ts +2 -1
- package/dist/realtime/build-effects.js.map +1 -1
- package/dist/realtime/subscriptions.js.map +1 -1
- package/dist/registry/eager.js +2 -1
- package/dist/registry/eager.js.map +1 -1
- package/dist/registry/lazy.js +2 -1
- package/dist/registry/lazy.js.map +1 -1
- package/dist/table/bulk.d.ts +2 -1
- package/dist/table/bulk.js.map +1 -1
- package/dist/table/components/bulk-bar.js +2 -2
- package/dist/table/components/cells/money-cell.js +1 -1
- package/dist/table/components/cells/number-cell.js +1 -1
- package/dist/table/components/cells/text-cell.js +1 -1
- package/dist/table/components/filter-controls.d.ts +0 -4
- package/dist/table/components/filter-controls.js.map +1 -1
- package/dist/table/components/table-cell.js.map +1 -1
- package/dist/table/format.d.ts +1 -12
- package/dist/table/format.js +2 -26
- package/dist/table/format.js.map +1 -1
- package/dist/table/types.d.ts +7 -17
- package/dist/types/generated.d.ts +119 -290
- package/dist/vite-client.d.ts +8 -0
- package/dist/vite.d.ts +35 -1
- package/dist/vite.js +60 -2
- package/dist/vite.js.map +1 -1
- package/package.json +13 -2
- package/resources/icons/bell.svg +16 -0
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { cn } from "../../lib/utils.js";
|
|
2
|
+
import { IconRenderer } from "../../icons/icon-renderer.js";
|
|
3
|
+
import { RenderNode } from "../../core/renderer.js";
|
|
4
|
+
import { useT } from "../../i18n/instance.js";
|
|
5
|
+
import { Link } from "@inertiajs/react";
|
|
6
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
7
|
+
//#region resources/js/notifications/components/notification-item.tsx
|
|
8
|
+
var variantIconClass = {
|
|
9
|
+
success: "text-lt-success",
|
|
10
|
+
info: "text-lt-info",
|
|
11
|
+
warning: "text-lt-warning",
|
|
12
|
+
error: "text-lt-danger"
|
|
13
|
+
};
|
|
14
|
+
function NotificationItemRow({ notification, onMarkRead, onDismiss }) {
|
|
15
|
+
const { t } = useT("lattice");
|
|
16
|
+
const content = /* @__PURE__ */ jsxs(Fragment, { children: [notification.title ? /* @__PURE__ */ jsx("p", {
|
|
17
|
+
className: "truncate text-sm font-medium text-lt-fg",
|
|
18
|
+
children: notification.title
|
|
19
|
+
}) : null, notification.body ? /* @__PURE__ */ jsx("p", {
|
|
20
|
+
className: "text-sm text-lt-muted-fg",
|
|
21
|
+
children: notification.body
|
|
22
|
+
}) : null] });
|
|
23
|
+
return /* @__PURE__ */ jsxs("li", {
|
|
24
|
+
className: cn("flex gap-3 px-3 py-3", !notification.isRead && "bg-lt-muted/40"),
|
|
25
|
+
"data-test": "notification",
|
|
26
|
+
children: [
|
|
27
|
+
notification.icon ? /* @__PURE__ */ jsx(IconRenderer, {
|
|
28
|
+
icon: notification.icon,
|
|
29
|
+
className: cn("mt-0.5 size-lt-icon-md", notification.variant ? variantIconClass[notification.variant] : void 0)
|
|
30
|
+
}) : null,
|
|
31
|
+
/* @__PURE__ */ jsxs("div", {
|
|
32
|
+
className: "min-w-0 flex-1",
|
|
33
|
+
children: [notification.href ? /* @__PURE__ */ jsx(Link, {
|
|
34
|
+
href: notification.href,
|
|
35
|
+
className: "block",
|
|
36
|
+
"data-test": "notification-link",
|
|
37
|
+
onClick: () => onMarkRead(notification.id),
|
|
38
|
+
children: content
|
|
39
|
+
}) : content, notification.actions.length > 0 ? /* @__PURE__ */ jsx("div", {
|
|
40
|
+
className: "mt-2 flex flex-wrap gap-2",
|
|
41
|
+
children: notification.actions.map((node, index) => /* @__PURE__ */ jsx(RenderNode, { node }, node.key ?? node.id ?? `action-${index}`))
|
|
42
|
+
}) : null]
|
|
43
|
+
}),
|
|
44
|
+
/* @__PURE__ */ jsxs("div", {
|
|
45
|
+
className: "flex shrink-0 flex-col gap-1",
|
|
46
|
+
children: [!notification.isRead ? /* @__PURE__ */ jsx("button", {
|
|
47
|
+
type: "button",
|
|
48
|
+
className: "text-xs text-lt-muted-fg hover:text-lt-fg",
|
|
49
|
+
onClick: () => onMarkRead(notification.id),
|
|
50
|
+
children: t("notifications.mark-read", "Mark read")
|
|
51
|
+
}) : null, /* @__PURE__ */ jsx("button", {
|
|
52
|
+
type: "button",
|
|
53
|
+
"aria-label": t("notifications.dismiss", "Dismiss"),
|
|
54
|
+
className: "text-xs text-lt-muted-fg hover:text-lt-fg",
|
|
55
|
+
onClick: () => onDismiss(notification.id),
|
|
56
|
+
children: t("notifications.dismiss", "Dismiss")
|
|
57
|
+
})]
|
|
58
|
+
})
|
|
59
|
+
]
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
//#endregion
|
|
63
|
+
export { NotificationItemRow };
|
|
64
|
+
|
|
65
|
+
//# sourceMappingURL=notification-item.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"notification-item.js","names":[],"sources":["../../../resources/js/notifications/components/notification-item.tsx"],"sourcesContent":["import { Link } from \"@inertiajs/react\";\nimport { RenderNode } from \"@lattice-php/lattice/core/renderer\";\nimport { IconRenderer } from \"@lattice-php/lattice/icons\";\nimport { useT } from \"@lattice-php/lattice/i18n\";\nimport { cn } from \"@lattice-php/lattice/lib/utils\";\nimport type { NotificationItem } from \"../types\";\n\nconst variantIconClass: Record<NonNullable<NotificationItem[\"variant\"]>, string> = {\n success: \"text-lt-success\",\n info: \"text-lt-info\",\n warning: \"text-lt-warning\",\n error: \"text-lt-danger\",\n};\n\nexport function NotificationItemRow({\n notification,\n onMarkRead,\n onDismiss,\n}: {\n notification: NotificationItem;\n onMarkRead: (id: string) => void;\n onDismiss: (id: string) => void;\n}) {\n const { t } = useT(\"lattice\");\n\n const content = (\n <>\n {notification.title ? (\n <p className=\"truncate text-sm font-medium text-lt-fg\">{notification.title}</p>\n ) : null}\n {notification.body ? <p className=\"text-sm text-lt-muted-fg\">{notification.body}</p> : null}\n </>\n );\n\n return (\n <li\n className={cn(\"flex gap-3 px-3 py-3\", !notification.isRead && \"bg-lt-muted/40\")}\n data-test=\"notification\"\n >\n {notification.icon ? (\n <IconRenderer\n icon={notification.icon}\n className={cn(\n \"mt-0.5 size-lt-icon-md\",\n notification.variant ? variantIconClass[notification.variant] : undefined,\n )}\n />\n ) : null}\n <div className=\"min-w-0 flex-1\">\n {notification.href ? (\n <Link\n href={notification.href}\n className=\"block\"\n data-test=\"notification-link\"\n onClick={() => onMarkRead(notification.id)}\n >\n {content}\n </Link>\n ) : (\n content\n )}\n {notification.actions.length > 0 ? (\n <div className=\"mt-2 flex flex-wrap gap-2\">\n {notification.actions.map((node, index) => (\n <RenderNode key={node.key ?? node.id ?? `action-${index}`} node={node} />\n ))}\n </div>\n ) : null}\n </div>\n <div className=\"flex shrink-0 flex-col gap-1\">\n {!notification.isRead ? (\n <button\n type=\"button\"\n className=\"text-xs text-lt-muted-fg hover:text-lt-fg\"\n onClick={() => onMarkRead(notification.id)}\n >\n {t(\"notifications.mark-read\", \"Mark read\")}\n </button>\n ) : null}\n <button\n type=\"button\"\n aria-label={t(\"notifications.dismiss\", \"Dismiss\")}\n className=\"text-xs text-lt-muted-fg hover:text-lt-fg\"\n onClick={() => onDismiss(notification.id)}\n >\n {t(\"notifications.dismiss\", \"Dismiss\")}\n </button>\n </div>\n </li>\n );\n}\n"],"mappings":";;;;;;;AAOA,IAAM,mBAA6E;CACjF,SAAS;CACT,MAAM;CACN,SAAS;CACT,OAAO;AACT;AAEA,SAAgB,oBAAoB,EAClC,cACA,YACA,aAKC;CACD,MAAM,EAAE,MAAM,KAAK,SAAS;CAE5B,MAAM,UACJ,qBAAA,UAAA,EAAA,UAAA,CACG,aAAa,QACZ,oBAAC,KAAD;EAAG,WAAU;YAA2C,aAAa;CAAS,CAAA,IAC5E,MACH,aAAa,OAAO,oBAAC,KAAD;EAAG,WAAU;YAA4B,aAAa;CAAQ,CAAA,IAAI,IACvF,EAAA,CAAA;CAGJ,OACE,qBAAC,MAAD;EACE,WAAW,GAAG,wBAAwB,CAAC,aAAa,UAAU,gBAAgB;EAC9E,aAAU;YAFZ;GAIG,aAAa,OACZ,oBAAC,cAAD;IACE,MAAM,aAAa;IACnB,WAAW,GACT,0BACA,aAAa,UAAU,iBAAiB,aAAa,WAAW,KAAA,CAClE;GACD,CAAA,IACC;GACJ,qBAAC,OAAD;IAAK,WAAU;cAAf,CACG,aAAa,OACZ,oBAAC,MAAD;KACE,MAAM,aAAa;KACnB,WAAU;KACV,aAAU;KACV,eAAe,WAAW,aAAa,EAAE;eAExC;IACG,CAAA,IAEN,SAED,aAAa,QAAQ,SAAS,IAC7B,oBAAC,OAAD;KAAK,WAAU;eACZ,aAAa,QAAQ,KAAK,MAAM,UAC/B,oBAAC,YAAD,EAAiE,KAAO,GAAvD,KAAK,OAAO,KAAK,MAAM,UAAU,OAAsB,CACzE;IACE,CAAA,IACH,IACD;;GACL,qBAAC,OAAD;IAAK,WAAU;cAAf,CACG,CAAC,aAAa,SACb,oBAAC,UAAD;KACE,MAAK;KACL,WAAU;KACV,eAAe,WAAW,aAAa,EAAE;eAExC,EAAE,2BAA2B,WAAW;IACnC,CAAA,IACN,MACJ,oBAAC,UAAD;KACE,MAAK;KACL,cAAY,EAAE,yBAAyB,SAAS;KAChD,WAAU;KACV,eAAe,UAAU,aAAa,EAAE;eAEvC,EAAE,yBAAyB,SAAS;IAC/B,CAAA,CACL;;EACH;;AAER"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { NotificationItem } from '../types';
|
|
2
|
+
import { NotificationsStatus } from '../store';
|
|
3
|
+
export declare function NotificationList({ notifications, status, hasMore, onMarkRead, onDismiss, onLoadMore, }: {
|
|
4
|
+
notifications: NotificationItem[];
|
|
5
|
+
status: NotificationsStatus;
|
|
6
|
+
hasMore: boolean;
|
|
7
|
+
onMarkRead: (id: string) => void;
|
|
8
|
+
onDismiss: (id: string) => void;
|
|
9
|
+
onLoadMore: () => void;
|
|
10
|
+
}): import("react").JSX.Element;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { useT } from "../../i18n/instance.js";
|
|
2
|
+
import { Skeleton } from "../../core/components/skeleton.js";
|
|
3
|
+
import { EmptyState } from "./empty-state.js";
|
|
4
|
+
import { NotificationItemRow } from "./notification-item.js";
|
|
5
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
6
|
+
//#region resources/js/notifications/components/notification-list.tsx
|
|
7
|
+
function NotificationList({ notifications, status, hasMore, onMarkRead, onDismiss, onLoadMore }) {
|
|
8
|
+
const { t } = useT("lattice");
|
|
9
|
+
if (status === "loading" && notifications.length === 0) return /* @__PURE__ */ jsxs("div", {
|
|
10
|
+
className: "space-y-2 p-3",
|
|
11
|
+
children: [
|
|
12
|
+
/* @__PURE__ */ jsx(Skeleton, { className: "h-12 w-full" }),
|
|
13
|
+
/* @__PURE__ */ jsx(Skeleton, { className: "h-12 w-full" }),
|
|
14
|
+
/* @__PURE__ */ jsx(Skeleton, { className: "h-12 w-full" })
|
|
15
|
+
]
|
|
16
|
+
});
|
|
17
|
+
if (notifications.length === 0) return /* @__PURE__ */ jsx(EmptyState, {});
|
|
18
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
19
|
+
className: "max-h-96 overflow-y-auto",
|
|
20
|
+
children: [/* @__PURE__ */ jsx("ul", {
|
|
21
|
+
className: "divide-y divide-lt-border",
|
|
22
|
+
children: notifications.map((notification) => /* @__PURE__ */ jsx(NotificationItemRow, {
|
|
23
|
+
notification,
|
|
24
|
+
onMarkRead,
|
|
25
|
+
onDismiss
|
|
26
|
+
}, notification.id))
|
|
27
|
+
}), hasMore ? /* @__PURE__ */ jsx("button", {
|
|
28
|
+
type: "button",
|
|
29
|
+
className: "w-full py-2 text-sm text-lt-muted-fg hover:text-lt-fg",
|
|
30
|
+
onClick: onLoadMore,
|
|
31
|
+
children: t("notifications.load-more", "Load more")
|
|
32
|
+
}) : null]
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
//#endregion
|
|
36
|
+
export { NotificationList };
|
|
37
|
+
|
|
38
|
+
//# sourceMappingURL=notification-list.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"notification-list.js","names":[],"sources":["../../../resources/js/notifications/components/notification-list.tsx"],"sourcesContent":["import { Skeleton } from \"@lattice-php/lattice/core/components/skeleton\";\nimport { useT } from \"@lattice-php/lattice/i18n\";\nimport type { NotificationItem } from \"../types\";\nimport type { NotificationsStatus } from \"../store\";\nimport { EmptyState } from \"./empty-state\";\nimport { NotificationItemRow } from \"./notification-item\";\n\nexport function NotificationList({\n notifications,\n status,\n hasMore,\n onMarkRead,\n onDismiss,\n onLoadMore,\n}: {\n notifications: NotificationItem[];\n status: NotificationsStatus;\n hasMore: boolean;\n onMarkRead: (id: string) => void;\n onDismiss: (id: string) => void;\n onLoadMore: () => void;\n}) {\n const { t } = useT(\"lattice\");\n\n if (status === \"loading\" && notifications.length === 0) {\n return (\n <div className=\"space-y-2 p-3\">\n <Skeleton className=\"h-12 w-full\" />\n <Skeleton className=\"h-12 w-full\" />\n <Skeleton className=\"h-12 w-full\" />\n </div>\n );\n }\n\n if (notifications.length === 0) {\n return <EmptyState />;\n }\n\n return (\n <div className=\"max-h-96 overflow-y-auto\">\n <ul className=\"divide-y divide-lt-border\">\n {notifications.map((notification) => (\n <NotificationItemRow\n key={notification.id}\n notification={notification}\n onMarkRead={onMarkRead}\n onDismiss={onDismiss}\n />\n ))}\n </ul>\n {hasMore ? (\n <button\n type=\"button\"\n className=\"w-full py-2 text-sm text-lt-muted-fg hover:text-lt-fg\"\n onClick={onLoadMore}\n >\n {t(\"notifications.load-more\", \"Load more\")}\n </button>\n ) : null}\n </div>\n );\n}\n"],"mappings":";;;;;;AAOA,SAAgB,iBAAiB,EAC/B,eACA,QACA,SACA,YACA,WACA,cAQC;CACD,MAAM,EAAE,MAAM,KAAK,SAAS;CAE5B,IAAI,WAAW,aAAa,cAAc,WAAW,GACnD,OACE,qBAAC,OAAD;EAAK,WAAU;YAAf;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;YAAf,CACE,oBAAC,MAAD;GAAI,WAAU;aACX,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;aAER,EAAE,2BAA2B,WAAW;EACnC,CAAA,IACN,IACD;;AAET"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { useEchoNotification } from "@laravel/echo-react";
|
|
2
|
+
//#region resources/js/notifications/components/notifications-echo.tsx
|
|
3
|
+
function NotificationsEcho({ channel, onReceive }) {
|
|
4
|
+
useEchoNotification(channel, (payload) => {
|
|
5
|
+
onReceive({
|
|
6
|
+
id: payload.id,
|
|
7
|
+
title: payload.title ?? null,
|
|
8
|
+
body: payload.body ?? null,
|
|
9
|
+
icon: payload.icon ?? null,
|
|
10
|
+
variant: payload.variant ?? null,
|
|
11
|
+
href: payload.href ?? null,
|
|
12
|
+
isRead: false,
|
|
13
|
+
createdAt: null,
|
|
14
|
+
actions: []
|
|
15
|
+
});
|
|
16
|
+
});
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
19
|
+
//#endregion
|
|
20
|
+
export { NotificationsEcho };
|
|
21
|
+
|
|
22
|
+
//# sourceMappingURL=notifications-echo.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"notifications-echo.js","names":[],"sources":["../../../resources/js/notifications/components/notifications-echo.tsx"],"sourcesContent":["import { useEchoNotification } from \"@laravel/echo-react\";\nimport type { NotificationItem } from \"../types\";\n\nexport function NotificationsEcho({\n channel,\n onReceive,\n}: {\n channel: string;\n onReceive: (item: NotificationItem) => void;\n}) {\n useEchoNotification<Partial<NotificationItem>>(channel, (payload) => {\n onReceive({\n id: payload.id,\n title: payload.title ?? null,\n body: payload.body ?? null,\n icon: payload.icon ?? null,\n variant: payload.variant ?? null,\n href: payload.href ?? null,\n isRead: false,\n createdAt: null,\n actions: [],\n });\n });\n\n return null;\n}\n"],"mappings":";;AAGA,SAAgB,kBAAkB,EAChC,SACA,aAIC;CACD,oBAA+C,UAAU,YAAY;EACnE,UAAU;GACR,IAAI,QAAQ;GACZ,OAAO,QAAQ,SAAS;GACxB,MAAM,QAAQ,QAAQ;GACtB,MAAM,QAAQ,QAAQ;GACtB,SAAS,QAAQ,WAAW;GAC5B,MAAM,QAAQ,QAAQ;GACtB,QAAQ;GACR,WAAW;GACX,SAAS,CAAC;EACZ,CAAC;CACH,CAAC;CAED,OAAO;AACT"}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { Icon } from "../../icons/sprite.js";
|
|
2
|
+
import { useT } from "../../i18n/instance.js";
|
|
3
|
+
import { Popover, PopoverContent, PopoverTrigger } from "../../core/components/popover.js";
|
|
4
|
+
import { Dialog, DialogContent, DialogTitle } from "../../core/components/dialog.js";
|
|
5
|
+
import { Badge } from "../../core/components/badge.js";
|
|
6
|
+
import { useNotifications } from "../store.js";
|
|
7
|
+
import { NotificationList } from "./notification-list.js";
|
|
8
|
+
import { Component, Suspense, lazy } from "react";
|
|
9
|
+
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
10
|
+
//#region resources/js/notifications/components/notifications.tsx
|
|
11
|
+
var NotificationsEcho = lazy(() => import("./notifications-echo.js").then((m) => ({ default: m.NotificationsEcho })));
|
|
12
|
+
var EchoBoundary = class extends Component {
|
|
13
|
+
state = { failed: false };
|
|
14
|
+
static getDerivedStateFromError() {
|
|
15
|
+
return { failed: true };
|
|
16
|
+
}
|
|
17
|
+
componentDidCatch() {
|
|
18
|
+
console.warn("[lattice] The notifications bell declares a realtime channel but Echo is unavailable. Install @laravel/echo-react and call configureEcho().");
|
|
19
|
+
}
|
|
20
|
+
render() {
|
|
21
|
+
return this.state.failed ? null : this.props.children;
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
var NotificationsComponent = ({ node }) => {
|
|
25
|
+
const { t } = useT("lattice");
|
|
26
|
+
const store = useNotifications({
|
|
27
|
+
endpoint: node.props.endpoint,
|
|
28
|
+
pollingInterval: node.props.pollingInterval
|
|
29
|
+
});
|
|
30
|
+
const label = t("notifications.label", "Notifications");
|
|
31
|
+
const trigger = /* @__PURE__ */ jsxs("span", {
|
|
32
|
+
className: "relative inline-flex items-center justify-center rounded-lt-sm p-2 hover:bg-lt-muted",
|
|
33
|
+
children: [/* @__PURE__ */ jsx(Icon, {
|
|
34
|
+
name: "bell",
|
|
35
|
+
className: "size-lt-icon-md"
|
|
36
|
+
}), store.unreadCount > 0 ? /* @__PURE__ */ jsx(Badge, {
|
|
37
|
+
variant: "destructive",
|
|
38
|
+
"data-test": "notifications-badge",
|
|
39
|
+
className: "absolute -right-0.5 -top-0.5 min-w-4 px-1 py-0 text-[10px]",
|
|
40
|
+
children: store.unreadCount
|
|
41
|
+
}) : null]
|
|
42
|
+
});
|
|
43
|
+
const panel = /* @__PURE__ */ jsxs("div", {
|
|
44
|
+
className: "w-80",
|
|
45
|
+
"data-test": "notifications-panel",
|
|
46
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
47
|
+
className: "flex items-center justify-between border-b border-lt-border px-3 py-2",
|
|
48
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
49
|
+
className: "text-sm font-medium",
|
|
50
|
+
children: t("notifications.heading", "Notifications")
|
|
51
|
+
}), store.unreadCount > 0 ? /* @__PURE__ */ jsx("button", {
|
|
52
|
+
type: "button",
|
|
53
|
+
className: "text-xs text-lt-muted-fg hover:text-lt-fg",
|
|
54
|
+
onClick: store.markAllRead,
|
|
55
|
+
children: t("notifications.mark-all-read", "Mark all read")
|
|
56
|
+
}) : null]
|
|
57
|
+
}), /* @__PURE__ */ jsx(NotificationList, {
|
|
58
|
+
notifications: store.notifications,
|
|
59
|
+
status: store.status,
|
|
60
|
+
hasMore: store.hasMore,
|
|
61
|
+
onMarkRead: store.markRead,
|
|
62
|
+
onDismiss: store.dismiss,
|
|
63
|
+
onLoadMore: store.loadMore
|
|
64
|
+
})]
|
|
65
|
+
});
|
|
66
|
+
return /* @__PURE__ */ jsxs(Fragment$1, { children: [node.props.channel ? /* @__PURE__ */ jsx(EchoBoundary, { children: /* @__PURE__ */ jsx(Suspense, {
|
|
67
|
+
fallback: null,
|
|
68
|
+
children: /* @__PURE__ */ jsx(NotificationsEcho, {
|
|
69
|
+
channel: node.props.channel,
|
|
70
|
+
onReceive: (item) => store.receive(item)
|
|
71
|
+
})
|
|
72
|
+
}) }) : null, node.props.slideOut ? /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("button", {
|
|
73
|
+
type: "button",
|
|
74
|
+
"aria-label": label,
|
|
75
|
+
"data-test": "notifications-trigger",
|
|
76
|
+
onClick: () => store.setOpen(true),
|
|
77
|
+
children: trigger
|
|
78
|
+
}), /* @__PURE__ */ jsx(Dialog, {
|
|
79
|
+
open: store.open,
|
|
80
|
+
onOpenChange: store.setOpen,
|
|
81
|
+
children: /* @__PURE__ */ jsxs(DialogContent, {
|
|
82
|
+
className: "fixed left-auto right-0 top-0 h-full w-96 max-w-full translate-x-0 translate-y-0 overflow-y-auto p-0",
|
|
83
|
+
children: [/* @__PURE__ */ jsx(DialogTitle, {
|
|
84
|
+
className: "sr-only",
|
|
85
|
+
children: label
|
|
86
|
+
}), panel]
|
|
87
|
+
})
|
|
88
|
+
})] }) : /* @__PURE__ */ jsxs(Popover, {
|
|
89
|
+
open: store.open,
|
|
90
|
+
onOpenChange: store.setOpen,
|
|
91
|
+
children: [/* @__PURE__ */ jsx(PopoverTrigger, {
|
|
92
|
+
asChild: true,
|
|
93
|
+
children: /* @__PURE__ */ jsx("button", {
|
|
94
|
+
type: "button",
|
|
95
|
+
"aria-label": label,
|
|
96
|
+
"data-test": "notifications-trigger",
|
|
97
|
+
children: trigger
|
|
98
|
+
})
|
|
99
|
+
}), /* @__PURE__ */ jsx(PopoverContent, {
|
|
100
|
+
align: "end",
|
|
101
|
+
className: "p-0",
|
|
102
|
+
children: panel
|
|
103
|
+
})]
|
|
104
|
+
})] });
|
|
105
|
+
};
|
|
106
|
+
//#endregion
|
|
107
|
+
export { NotificationsComponent as default };
|
|
108
|
+
|
|
109
|
+
//# sourceMappingURL=notifications.js.map
|
|
@@ -0,0 +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 { Badge } from \"@lattice-php/lattice/core/components/badge\";\nimport { Dialog, DialogContent, DialogTitle } from \"@lattice-php/lattice/core/components/dialog\";\nimport {\n Popover as PopoverRoot,\n PopoverContent,\n PopoverTrigger,\n} from \"@lattice-php/lattice/core/components/popover\";\nimport { Icon } from \"@lattice-php/lattice/icons\";\nimport { useT } from \"@lattice-php/lattice/i18n\";\nimport type { RendererComponent } from \"@lattice-php/lattice/core/types\";\nimport { useNotifications } from \"../store\";\nimport type { NotificationItem } from \"../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 <Badge\n variant=\"destructive\"\n data-test=\"notifications-badge\"\n className=\"absolute -right-0.5 -top-0.5 min-w-4 px-1 py-0 text-[10px]\"\n >\n {store.unreadCount}\n </Badge>\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 className=\"fixed left-auto right-0 top-0 h-full w-96 max-w-full translate-x-0 translate-y-0 overflow-y-auto p-0\">\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":";;;;;;;;;;AAeA,IAAM,oBAAoB,WACxB,OAAO,2BAAwB,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;YAAhB,CACE,oBAAC,MAAD;GAAM,MAAK;GAAO,WAAU;EAAmB,CAAA,GAC9C,MAAM,cAAc,IACnB,oBAAC,OAAD;GACE,SAAQ;GACR,aAAU;GACV,WAAU;aAET,MAAM;EACF,CAAA,IACL,IACA;;CAGR,MAAM,QACJ,qBAAC,OAAD;EAAK,WAAU;EAAO,aAAU;YAAhC,CACE,qBAAC,OAAD;GAAK,WAAU;aAAf,CACE,oBAAC,QAAD;IAAM,WAAU;cAAuB,EAAE,yBAAyB,eAAe;GAAQ,CAAA,GACxF,MAAM,cAAc,IACnB,oBAAC,UAAD;IACE,MAAK;IACL,WAAU;IACV,SAAS,MAAM;cAEd,EAAE,+BAA+B,eAAe;GAC3C,CAAA,IACN,IACD;MACL,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;YAClB,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;YAEhC;CACK,CAAA,GACR,oBAAC,QAAD;EAAQ,MAAM,MAAM;EAAM,cAAc,MAAM;YAC5C,qBAAC,eAAD;GAAe,WAAU;aAAzB,CACE,oBAAC,aAAD;IAAa,WAAU;cAAW;GAAmB,CAAA,GACpD,KACY;;CACT,CAAA,CACR,EAAA,CAAA,IAEF,qBAAC,SAAD;EAAa,MAAM,MAAM;EAAM,cAAc,MAAM;YAAnD,CACE,oBAAC,gBAAD;GAAgB,SAAA;aACd,oBAAC,UAAD;IAAQ,MAAK;IAAS,cAAY;IAAO,aAAU;cAChD;GACK,CAAA;EACM,CAAA,GAChB,oBAAC,gBAAD;GAAgB,OAAM;GAAM,WAAU;aACnC;EACa,CAAA,CACL;GAEf,EAAA,CAAA;AAEN"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const notificationsPlugin: import('../core/registry').Plugin;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { createPlugin, eagerComponent } from "../core/registry.js";
|
|
2
|
+
import NotificationsComponent from "./components/notifications.js";
|
|
3
|
+
//#region resources/js/notifications/index.ts
|
|
4
|
+
var notificationsPlugin = createPlugin({
|
|
5
|
+
name: "lattice/notifications",
|
|
6
|
+
components: { notifications: eagerComponent(NotificationsComponent) }
|
|
7
|
+
});
|
|
8
|
+
//#endregion
|
|
9
|
+
export { notificationsPlugin };
|
|
10
|
+
|
|
11
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../resources/js/notifications/index.ts"],"sourcesContent":["import { createPlugin, eagerComponent } from \"@lattice-php/lattice/core/registry\";\nimport NotificationsComponent from \"./components/notifications\";\n\nexport const notificationsPlugin = createPlugin({\n name: \"lattice/notifications\",\n components: {\n notifications: eagerComponent(NotificationsComponent),\n },\n});\n"],"mappings":";;;AAGA,IAAa,sBAAsB,aAAa;CAC9C,MAAM;CACN,YAAY,EACV,eAAe,eAAe,sBAAsB,EACtD;AACF,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { NotificationItem } from './types';
|
|
2
|
+
export declare function prependIncoming(list: NotificationItem[], item: NotificationItem): NotificationItem[];
|
|
3
|
+
export declare function markReadIn(list: NotificationItem[], id: string): NotificationItem[];
|
|
4
|
+
export declare function removeIn(list: NotificationItem[], id: string): NotificationItem[];
|
|
5
|
+
export type NotificationsStatus = "loading" | "idle" | "error";
|
|
6
|
+
type UseNotificationsOptions = {
|
|
7
|
+
endpoint: string;
|
|
8
|
+
pollingInterval?: number | null;
|
|
9
|
+
};
|
|
10
|
+
type UseNotificationsReturn = {
|
|
11
|
+
notifications: NotificationItem[];
|
|
12
|
+
unreadCount: number;
|
|
13
|
+
status: NotificationsStatus;
|
|
14
|
+
hasMore: boolean;
|
|
15
|
+
open: boolean;
|
|
16
|
+
setOpen: (open: boolean) => void;
|
|
17
|
+
loadMore: () => void;
|
|
18
|
+
markRead: (id: string) => void;
|
|
19
|
+
markAllRead: () => void;
|
|
20
|
+
dismiss: (id: string) => void;
|
|
21
|
+
clearAll: () => void;
|
|
22
|
+
receive: (item: NotificationItem) => void;
|
|
23
|
+
};
|
|
24
|
+
export declare function useNotifications({ endpoint, pollingInterval, }: UseNotificationsOptions): UseNotificationsReturn;
|
|
25
|
+
export {};
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { clearAll, dismiss, fetchNotifications, markAllRead, markRead } from "./api.js";
|
|
2
|
+
import { useCallback, useEffect, useRef, useState } from "react";
|
|
3
|
+
//#region resources/js/notifications/store.ts
|
|
4
|
+
function prependIncoming(list, item) {
|
|
5
|
+
if (list.some((n) => n.id === item.id)) return list;
|
|
6
|
+
return [item, ...list];
|
|
7
|
+
}
|
|
8
|
+
function markReadIn(list, id) {
|
|
9
|
+
return list.map((n) => n.id === id ? {
|
|
10
|
+
...n,
|
|
11
|
+
isRead: true
|
|
12
|
+
} : n);
|
|
13
|
+
}
|
|
14
|
+
function removeIn(list, id) {
|
|
15
|
+
return list.filter((n) => n.id !== id);
|
|
16
|
+
}
|
|
17
|
+
function useNotifications({ endpoint, pollingInterval }) {
|
|
18
|
+
const [notifications, setNotifications] = useState([]);
|
|
19
|
+
const [unreadCount, setUnreadCount] = useState(0);
|
|
20
|
+
const [status, setStatus] = useState("loading");
|
|
21
|
+
const [hasMore, setHasMore] = useState(false);
|
|
22
|
+
const [open, setOpen] = useState(false);
|
|
23
|
+
const pageRef = useRef(1);
|
|
24
|
+
const hasMoreRef = useRef(hasMore);
|
|
25
|
+
hasMoreRef.current = hasMore;
|
|
26
|
+
const loadingMoreRef = useRef(false);
|
|
27
|
+
const hydrate = useCallback(async () => {
|
|
28
|
+
try {
|
|
29
|
+
const result = await fetchNotifications(endpoint, 1);
|
|
30
|
+
pageRef.current = 1;
|
|
31
|
+
setNotifications(result.notifications);
|
|
32
|
+
setUnreadCount(result.unreadCount);
|
|
33
|
+
setHasMore(result.hasMore);
|
|
34
|
+
setStatus("idle");
|
|
35
|
+
} catch {
|
|
36
|
+
setStatus("error");
|
|
37
|
+
}
|
|
38
|
+
}, [endpoint]);
|
|
39
|
+
useEffect(() => {
|
|
40
|
+
hydrate();
|
|
41
|
+
}, [hydrate]);
|
|
42
|
+
useEffect(() => {
|
|
43
|
+
if (!pollingInterval || pollingInterval <= 0) return;
|
|
44
|
+
const timer = setInterval(() => void hydrate(), pollingInterval * 1e3);
|
|
45
|
+
return () => clearInterval(timer);
|
|
46
|
+
}, [hydrate, pollingInterval]);
|
|
47
|
+
return {
|
|
48
|
+
notifications,
|
|
49
|
+
unreadCount,
|
|
50
|
+
status,
|
|
51
|
+
hasMore,
|
|
52
|
+
open,
|
|
53
|
+
setOpen,
|
|
54
|
+
loadMore: useCallback(() => {
|
|
55
|
+
if (loadingMoreRef.current || !hasMoreRef.current) return;
|
|
56
|
+
loadingMoreRef.current = true;
|
|
57
|
+
const next = pageRef.current + 1;
|
|
58
|
+
fetchNotifications(endpoint, next).then((result) => {
|
|
59
|
+
pageRef.current = next;
|
|
60
|
+
setNotifications((current) => [...current, ...result.notifications]);
|
|
61
|
+
setHasMore(result.hasMore);
|
|
62
|
+
}).catch(() => void hydrate()).finally(() => {
|
|
63
|
+
loadingMoreRef.current = false;
|
|
64
|
+
});
|
|
65
|
+
}, [endpoint, hydrate]),
|
|
66
|
+
markRead: useCallback((id) => {
|
|
67
|
+
setNotifications((current) => markReadIn(current, id));
|
|
68
|
+
setUnreadCount((count) => Math.max(0, count - 1));
|
|
69
|
+
markRead(endpoint, id).then((r) => setUnreadCount(r.unreadCount)).catch(() => void hydrate());
|
|
70
|
+
}, [endpoint, hydrate]),
|
|
71
|
+
markAllRead: useCallback(() => {
|
|
72
|
+
setNotifications((current) => current.map((n) => ({
|
|
73
|
+
...n,
|
|
74
|
+
isRead: true
|
|
75
|
+
})));
|
|
76
|
+
setUnreadCount(0);
|
|
77
|
+
markAllRead(endpoint).then((r) => setUnreadCount(r.unreadCount)).catch(() => void hydrate());
|
|
78
|
+
}, [endpoint, hydrate]),
|
|
79
|
+
dismiss: useCallback((id) => {
|
|
80
|
+
setNotifications((current) => removeIn(current, id));
|
|
81
|
+
dismiss(endpoint, id).then((r) => setUnreadCount(r.unreadCount)).catch(() => void hydrate());
|
|
82
|
+
}, [endpoint, hydrate]),
|
|
83
|
+
clearAll: useCallback(() => {
|
|
84
|
+
setNotifications([]);
|
|
85
|
+
setUnreadCount(0);
|
|
86
|
+
clearAll(endpoint).then((r) => setUnreadCount(r.unreadCount)).catch(() => void hydrate());
|
|
87
|
+
}, [endpoint, hydrate]),
|
|
88
|
+
receive: useCallback((item) => {
|
|
89
|
+
setNotifications((current) => {
|
|
90
|
+
const next = prependIncoming(current, item);
|
|
91
|
+
if (next !== current) setUnreadCount((count) => count + 1);
|
|
92
|
+
return next;
|
|
93
|
+
});
|
|
94
|
+
}, [])
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
//#endregion
|
|
98
|
+
export { markReadIn, prependIncoming, removeIn, useNotifications };
|
|
99
|
+
|
|
100
|
+
//# sourceMappingURL=store.js.map
|
|
@@ -0,0 +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":";;;AAUA,SAAgB,gBACd,MACA,MACoB;CACpB,IAAI,KAAK,MAAM,MAAM,EAAE,OAAO,KAAK,EAAE,GACnC,OAAO;CAGT,OAAO,CAAC,MAAM,GAAG,IAAI;AACvB;AAEA,SAAgB,WAAW,MAA0B,IAAgC;CACnF,OAAO,KAAK,KAAK,MAAO,EAAE,OAAO,KAAK;EAAE,GAAG;EAAG,QAAQ;CAAK,IAAI,CAAE;AACnE;AAEA,SAAgB,SAAS,MAA0B,IAAgC;CACjF,OAAO,KAAK,QAAQ,MAAM,EAAE,OAAO,EAAE;AACvC;AAwBA,SAAgB,iBAAiB,EAC/B,UACA,mBACkD;CAClD,MAAM,CAAC,eAAe,oBAAoB,SAA6B,CAAC,CAAC;CACzE,MAAM,CAAC,aAAa,kBAAkB,SAAS,CAAC;CAChD,MAAM,CAAC,QAAQ,aAAa,SAA8B,SAAS;CACnE,MAAM,CAAC,SAAS,cAAc,SAAS,KAAK;CAC5C,MAAM,CAAC,MAAM,WAAW,SAAS,KAAK;CACtC,MAAM,UAAU,OAAO,CAAC;CACxB,MAAM,aAAa,OAAO,OAAO;CACjC,WAAW,UAAU;CACrB,MAAM,iBAAiB,OAAO,KAAK;CAEnC,MAAM,UAAU,YAAY,YAA2B;EACrD,IAAI;GACF,MAAM,SAAS,MAAM,mBAAmB,UAAU,CAAC;GACnD,QAAQ,UAAU;GAClB,iBAAiB,OAAO,aAAa;GACrC,eAAe,OAAO,WAAW;GACjC,WAAW,OAAO,OAAO;GACzB,UAAU,MAAM;EAClB,QAAQ;GACN,UAAU,OAAO;EACnB;CACF,GAAG,CAAC,QAAQ,CAAC;CAEb,gBAAgB;EACd,QAAa;CACf,GAAG,CAAC,OAAO,CAAC;CAEZ,gBAAgB;EACd,IAAI,CAAC,mBAAmB,mBAAmB,GACzC;EAGF,MAAM,QAAQ,kBAAkB,KAAK,QAAQ,GAAG,kBAAkB,GAAI;EAEtE,aAAa,cAAc,KAAK;CAClC,GAAG,CAAC,SAAS,eAAe,CAAC;CAoE7B,OAAO;EACL;EACA;EACA;EACA;EACA;EACA;EACA,UAzEe,kBAAwB;GACvC,IAAI,eAAe,WAAW,CAAC,WAAW,SACxC;GAGF,eAAe,UAAU;GACzB,MAAM,OAAO,QAAQ,UAAU;GAC/B,mBAAwB,UAAU,IAAI,EACnC,MAAM,WAAW;IAChB,QAAQ,UAAU;IAClB,kBAAkB,YAAY,CAAC,GAAG,SAAS,GAAG,OAAO,aAAa,CAAC;IACnE,WAAW,OAAO,OAAO;GAC3B,CAAC,EACA,YAAY,KAAK,QAAQ,CAAC,EAC1B,cAAc;IACb,eAAe,UAAU;GAC3B,CAAC;EACL,GAAG,CAAC,UAAU,OAAO,CAwDnB;EACA,UAvDe,aACd,OAAqB;GACpB,kBAAkB,YAAY,WAAW,SAAS,EAAE,CAAC;GACrD,gBAAgB,UAAU,KAAK,IAAI,GAAG,QAAQ,CAAC,CAAC;GAChD,SAAiB,UAAU,EAAE,EAC1B,MAAM,MAAM,eAAe,EAAE,WAAW,CAAC,EACzC,YAAY,KAAK,QAAQ,CAAC;EAC/B,GACA,CAAC,UAAU,OAAO,CA+ClB;EACA,aA7CkB,kBAAwB;GAC1C,kBAAkB,YAAY,QAAQ,KAAK,OAAO;IAAE,GAAG;IAAG,QAAQ;GAAK,EAAE,CAAC;GAC1E,eAAe,CAAC;GAChB,YAAoB,QAAQ,EACzB,MAAM,MAAM,eAAe,EAAE,WAAW,CAAC,EACzC,YAAY,KAAK,QAAQ,CAAC;EAC/B,GAAG,CAAC,UAAU,OAAO,CAuCnB;EACA,SAtCc,aACb,OAAqB;GACpB,kBAAkB,YAAY,SAAS,SAAS,EAAE,CAAC;GACnD,QAAgB,UAAU,EAAE,EACzB,MAAM,MAAM,eAAe,EAAE,WAAW,CAAC,EACzC,YAAY,KAAK,QAAQ,CAAC;EAC/B,GACA,CAAC,UAAU,OAAO,CA+BlB;EACA,UA7Be,kBAAwB;GACvC,iBAAiB,CAAC,CAAC;GACnB,eAAe,CAAC;GAChB,SAAiB,QAAQ,EACtB,MAAM,MAAM,eAAe,EAAE,WAAW,CAAC,EACzC,YAAY,KAAK,QAAQ,CAAC;EAC/B,GAAG,CAAC,UAAU,OAAO,CAuBnB;EACA,SAtBc,aAAa,SAAiC;GAC5D,kBAAkB,YAAY;IAC5B,MAAM,OAAO,gBAAgB,SAAS,IAAI;IAC1C,IAAI,SAAS,SACX,gBAAgB,UAAU,QAAQ,CAAC;IAErC,OAAO;GACT,CAAC;EACH,GAAG,CAAC,CAcF;CACF;AACF"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { NotificationItem } from '../types/generated';
|
|
2
|
+
export type { NotificationItem };
|
|
3
|
+
export type NotificationsResponse = {
|
|
4
|
+
notifications: NotificationItem[];
|
|
5
|
+
unreadCount: number;
|
|
6
|
+
hasMore: boolean;
|
|
7
|
+
};
|
|
8
|
+
export type UnreadCountResponse = {
|
|
9
|
+
unreadCount: number;
|
|
10
|
+
};
|
|
File without changes
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Effect } from '../types/generated';
|
|
2
2
|
import { Translate } from '../i18n/translatable';
|
|
3
|
-
|
|
3
|
+
type RawEffect = Record<string, unknown>;
|
|
4
4
|
export declare function buildEffects(effects: readonly RawEffect[], payload: Record<string, unknown>, t: Translate): Effect[];
|
|
5
|
+
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build-effects.js","names":[],"sources":["../../resources/js/realtime/build-effects.ts"],"sourcesContent":["import type { Effect } from \"@lattice-php/lattice/types/generated\";\nimport { isTranslatable, resolveTranslatable } from \"@lattice-php/lattice/i18n/translatable\";\nimport type { Translate } from \"@lattice-php/lattice/i18n/translatable\";\n\
|
|
1
|
+
{"version":3,"file":"build-effects.js","names":[],"sources":["../../resources/js/realtime/build-effects.ts"],"sourcesContent":["import type { Effect } from \"@lattice-php/lattice/types/generated\";\nimport { isTranslatable, resolveTranslatable } from \"@lattice-php/lattice/i18n/translatable\";\nimport type { Translate } from \"@lattice-php/lattice/i18n/translatable\";\n\ntype RawEffect = Record<string, unknown>;\n\nexport function buildEffects(\n effects: readonly RawEffect[],\n payload: Record<string, unknown>,\n t: Translate,\n): Effect[] {\n return effects.map((effect) => resolveEffect(effect, payload, t)) as Effect[];\n}\n\nfunction resolveEffect(\n effect: RawEffect,\n payload: Record<string, unknown>,\n t: Translate,\n): RawEffect {\n if (effect.type !== \"toast\") {\n return effect;\n }\n\n const toast = effect.toast;\n\n if (typeof toast !== \"object\" || toast === null) {\n return effect;\n }\n\n const message = (toast as Record<string, unknown>).message;\n\n if (!isTranslatable(message)) {\n return effect;\n }\n\n return {\n ...effect,\n toast: {\n ...(toast as Record<string, unknown>),\n message: resolveTranslatable(message, payload, t),\n },\n };\n}\n"],"mappings":";;AAMA,SAAgB,aACd,SACA,SACA,GACU;CACV,OAAO,QAAQ,KAAK,WAAW,cAAc,QAAQ,SAAS,CAAC,CAAC;AAClE;AAEA,SAAS,cACP,QACA,SACA,GACW;CACX,IAAI,OAAO,SAAS,SAClB,OAAO;CAGT,MAAM,QAAQ,OAAO;CAErB,IAAI,OAAO,UAAU,YAAY,UAAU,MACzC,OAAO;CAGT,MAAM,UAAW,MAAkC;CAEnD,IAAI,CAAC,eAAe,OAAO,GACzB,OAAO;CAGT,OAAO;EACL,GAAG;EACH,OAAO;GACL,GAAI;GACJ,SAAS,oBAAoB,SAAS,SAAS,CAAC;EAClD;CACF;AACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"subscriptions.js","names":[],"sources":["../../resources/js/realtime/subscriptions.tsx"],"sourcesContent":["import { useEcho, useEchoPresence, useEchoPublic } from \"@laravel/echo-react\";\nimport { useCallback } from \"react\";\nimport { useEffectDispatcher } from \"@lattice-php/lattice/effects/use-effect-dispatcher\";\nimport { useT } from \"@lattice-php/lattice/i18n\";\nimport { buildEffects } from \"./build-effects\";\nimport type {
|
|
1
|
+
{"version":3,"file":"subscriptions.js","names":[],"sources":["../../resources/js/realtime/subscriptions.tsx"],"sourcesContent":["import { useEcho, useEchoPresence, useEchoPublic } from \"@laravel/echo-react\";\nimport { useCallback } from \"react\";\nimport { useEffectDispatcher } from \"@lattice-php/lattice/effects/use-effect-dispatcher\";\nimport { useT } from \"@lattice-php/lattice/i18n\";\nimport { buildEffects } from \"./build-effects\";\nimport type { ListenerPayload } from \"@lattice-php/lattice/types/generated\";\n\nfunction useListenerHandler(listener: ListenerPayload): (payload: unknown) => void {\n const { t } = useT(\"lattice\");\n const dispatch = useEffectDispatcher();\n\n return useCallback(\n (payload: unknown) => {\n const data = (typeof payload === \"object\" && payload !== null ? payload : {}) as Record<\n string,\n unknown\n >;\n dispatch(buildEffects(listener.effects, data, t));\n },\n [dispatch, listener, t],\n );\n}\n\nfunction PublicListener({ listener }: { listener: ListenerPayload }) {\n useEchoPublic(listener.channel, listener.events, useListenerHandler(listener));\n return null;\n}\n\nfunction PrivateListener({ listener }: { listener: ListenerPayload }) {\n useEcho(listener.channel, listener.events, useListenerHandler(listener));\n return null;\n}\n\nfunction PresenceListener({ listener }: { listener: ListenerPayload }) {\n useEchoPresence(listener.channel, listener.events, useListenerHandler(listener));\n return null;\n}\n\nfunction Listener({ listener }: { listener: ListenerPayload }) {\n switch (listener.visibility) {\n case \"private\":\n return <PrivateListener listener={listener} />;\n case \"presence\":\n return <PresenceListener listener={listener} />;\n default:\n return <PublicListener listener={listener} />;\n }\n}\n\nexport default function Subscriptions({ listeners }: { listeners: ListenerPayload[] }) {\n return (\n <>\n {listeners.map((listener, index) => (\n <Listener key={`${listener.visibility}:${listener.channel}:${index}`} listener={listener} />\n ))}\n </>\n );\n}\n"],"mappings":";;;;;;;AAOA,SAAS,mBAAmB,UAAuD;CACjF,MAAM,EAAE,MAAM,KAAK,SAAS;CAC5B,MAAM,WAAW,oBAAoB;CAErC,OAAO,aACJ,YAAqB;EACpB,MAAM,OAAQ,OAAO,YAAY,YAAY,YAAY,OAAO,UAAU,CAAC;EAI3E,SAAS,aAAa,SAAS,SAAS,MAAM,CAAC,CAAC;CAClD,GACA;EAAC;EAAU;EAAU;CAAC,CACxB;AACF;AAEA,SAAS,eAAe,EAAE,YAA2C;CACnE,cAAc,SAAS,SAAS,SAAS,QAAQ,mBAAmB,QAAQ,CAAC;CAC7E,OAAO;AACT;AAEA,SAAS,gBAAgB,EAAE,YAA2C;CACpE,QAAQ,SAAS,SAAS,SAAS,QAAQ,mBAAmB,QAAQ,CAAC;CACvE,OAAO;AACT;AAEA,SAAS,iBAAiB,EAAE,YAA2C;CACrE,gBAAgB,SAAS,SAAS,SAAS,QAAQ,mBAAmB,QAAQ,CAAC;CAC/E,OAAO;AACT;AAEA,SAAS,SAAS,EAAE,YAA2C;CAC7D,QAAQ,SAAS,YAAjB;EACE,KAAK,WACH,OAAO,oBAAC,iBAAD,EAA2B,SAAW,CAAA;EAC/C,KAAK,YACH,OAAO,oBAAC,kBAAD,EAA4B,SAAW,CAAA;EAChD,SACE,OAAO,oBAAC,gBAAD,EAA0B,SAAW,CAAA;CAChD;AACF;AAEA,SAAwB,cAAc,EAAE,aAA+C;CACrF,OACE,oBAAA,YAAA,EAAA,UACG,UAAU,KAAK,UAAU,UACxB,oBAAC,UAAD,EAAgF,SAAW,GAA5E,GAAG,SAAS,WAAW,GAAG,SAAS,QAAQ,GAAG,OAA8B,CAC5F,EACD,CAAA;AAEN"}
|
package/dist/registry/eager.js
CHANGED
|
@@ -2,12 +2,13 @@ import { createRegistry } from "../core/registry.js";
|
|
|
2
2
|
import { layoutComponents } from "../layout/components.js";
|
|
3
3
|
import { actionComponents } from "../action/index.js";
|
|
4
4
|
import { chatPlugin } from "../chat/index.js";
|
|
5
|
+
import { notificationsPlugin } from "../notifications/index.js";
|
|
5
6
|
import { remoteComponents } from "../remote/index.js";
|
|
6
7
|
import { eagerFormComponents } from "../form/eager.js";
|
|
7
8
|
import { eagerCoreComponents } from "../core/components/eager.js";
|
|
8
9
|
import { eagerTableComponents } from "../table/eager.js";
|
|
9
10
|
//#region resources/js/registry/eager.ts
|
|
10
|
-
var eagerRegistry = createRegistry(eagerCoreComponents, actionComponents, eagerFormComponents, layoutComponents, eagerTableComponents, chatPlugin, remoteComponents);
|
|
11
|
+
var eagerRegistry = createRegistry(eagerCoreComponents, actionComponents, eagerFormComponents, layoutComponents, eagerTableComponents, chatPlugin, notificationsPlugin, remoteComponents);
|
|
11
12
|
//#endregion
|
|
12
13
|
export { eagerRegistry };
|
|
13
14
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"eager.js","names":[],"sources":["../../resources/js/registry/eager.ts"],"sourcesContent":["import { createRegistry } from \"@lattice-php/lattice/core/registry\";\nimport { actionComponents } from \"../action\";\nimport { chatPlugin } from \"../chat\";\nimport { eagerCoreComponents } from \"../core/components/eager\";\nimport { eagerFormComponents } from \"../form/eager\";\nimport { layoutComponents } from \"../layout/components\";\nimport { remoteComponents } from \"../remote\";\nimport { eagerTableComponents } from \"../table/eager\";\n\nexport const eagerRegistry = createRegistry(\n eagerCoreComponents,\n actionComponents,\n eagerFormComponents,\n layoutComponents,\n eagerTableComponents,\n chatPlugin,\n remoteComponents,\n);\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"eager.js","names":[],"sources":["../../resources/js/registry/eager.ts"],"sourcesContent":["import { createRegistry } from \"@lattice-php/lattice/core/registry\";\nimport { actionComponents } from \"../action\";\nimport { chatPlugin } from \"../chat\";\nimport { eagerCoreComponents } from \"../core/components/eager\";\nimport { eagerFormComponents } from \"../form/eager\";\nimport { layoutComponents } from \"../layout/components\";\nimport { notificationsPlugin } from \"../notifications\";\nimport { remoteComponents } from \"../remote\";\nimport { eagerTableComponents } from \"../table/eager\";\n\nexport const eagerRegistry = createRegistry(\n eagerCoreComponents,\n actionComponents,\n eagerFormComponents,\n layoutComponents,\n eagerTableComponents,\n chatPlugin,\n notificationsPlugin,\n remoteComponents,\n);\n"],"mappings":";;;;;;;;;;AAUA,IAAa,gBAAgB,eAC3B,qBACA,kBACA,qBACA,kBACA,sBACA,YACA,qBACA,gBACF"}
|
package/dist/registry/lazy.js
CHANGED
|
@@ -4,10 +4,11 @@ import { actionComponents } from "../action/index.js";
|
|
|
4
4
|
import { chatPlugin } from "../chat/index.js";
|
|
5
5
|
import { coreComponents } from "../core/components/index.js";
|
|
6
6
|
import { formComponents } from "../form/index.js";
|
|
7
|
+
import { notificationsPlugin } from "../notifications/index.js";
|
|
7
8
|
import { remoteComponents } from "../remote/index.js";
|
|
8
9
|
import { tableComponents } from "../table/index.js";
|
|
9
10
|
//#region resources/js/registry/lazy.ts
|
|
10
|
-
var lazyRegistry = createRegistry(coreComponents, actionComponents, formComponents, layoutComponents, tableComponents, chatPlugin, remoteComponents);
|
|
11
|
+
var lazyRegistry = createRegistry(coreComponents, actionComponents, formComponents, layoutComponents, tableComponents, chatPlugin, notificationsPlugin, remoteComponents);
|
|
11
12
|
//#endregion
|
|
12
13
|
export { lazyRegistry };
|
|
13
14
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lazy.js","names":[],"sources":["../../resources/js/registry/lazy.ts"],"sourcesContent":["import { createRegistry } from \"@lattice-php/lattice/core/registry\";\nimport { actionComponents } from \"../action\";\nimport { chatPlugin } from \"../chat\";\nimport { coreComponents } from \"../core/components\";\nimport { formComponents } from \"../form\";\nimport { layoutComponents } from \"../layout/components\";\nimport { remoteComponents } from \"../remote\";\nimport { tableComponents } from \"../table\";\n\nexport const lazyRegistry = createRegistry(\n coreComponents,\n actionComponents,\n formComponents,\n layoutComponents,\n tableComponents,\n chatPlugin,\n remoteComponents,\n);\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"lazy.js","names":[],"sources":["../../resources/js/registry/lazy.ts"],"sourcesContent":["import { createRegistry } from \"@lattice-php/lattice/core/registry\";\nimport { actionComponents } from \"../action\";\nimport { chatPlugin } from \"../chat\";\nimport { coreComponents } from \"../core/components\";\nimport { formComponents } from \"../form\";\nimport { layoutComponents } from \"../layout/components\";\nimport { notificationsPlugin } from \"../notifications\";\nimport { remoteComponents } from \"../remote\";\nimport { tableComponents } from \"../table\";\n\nexport const lazyRegistry = createRegistry(\n coreComponents,\n actionComponents,\n formComponents,\n layoutComponents,\n tableComponents,\n chatPlugin,\n notificationsPlugin,\n remoteComponents,\n);\n"],"mappings":";;;;;;;;;;AAUA,IAAa,eAAe,eAC1B,gBACA,kBACA,gBACA,kBACA,iBACA,YACA,qBACA,gBACF"}
|
package/dist/table/bulk.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Method } from '@inertiajs/core';
|
|
2
2
|
import { Node } from '../core/types';
|
|
3
|
-
import { Action,
|
|
3
|
+
import { Action, ButtonVariant } from '../types/generated';
|
|
4
|
+
import { ActionNode } from './types';
|
|
4
5
|
export type BulkAction = {
|
|
5
6
|
id: string;
|
|
6
7
|
label: string;
|
package/dist/table/bulk.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bulk.js","names":[],"sources":["../../resources/js/table/bulk.ts"],"sourcesContent":["import type { Method } from \"@inertiajs/core\";\nimport type { Node } from \"@lattice-php/lattice/core/types\";\nimport type { Action,
|
|
1
|
+
{"version":3,"file":"bulk.js","names":[],"sources":["../../resources/js/table/bulk.ts"],"sourcesContent":["import type { Method } from \"@inertiajs/core\";\nimport type { Node } from \"@lattice-php/lattice/core/types\";\nimport type { Action, ButtonVariant } from \"@lattice-php/lattice/types/generated\";\nimport type { ActionNode } from \"./types\";\n\nexport type BulkAction = {\n id: string;\n label: string;\n method: Method;\n endpoint: string;\n ref: string;\n variant: ButtonVariant;\n confirmation: Action[\"confirmation\"];\n form: Node | null;\n};\n\nexport function getBulkActions(actions: ActionNode[] | undefined): BulkAction[] {\n return (actions ?? []).flatMap((node): BulkAction[] => {\n if (node.type === \"action.group\") {\n return [];\n }\n\n const props = node.props;\n\n if (!props.endpoint) {\n return [];\n }\n\n return [\n {\n id: node.id ?? \"\",\n label: props.label ?? \"Run action\",\n method: props.method ?? \"post\",\n endpoint: props.endpoint,\n ref: props.ref ?? \"\",\n variant: props.variant ?? \"default\",\n confirmation: props.confirmation,\n form: props.form,\n },\n ];\n });\n}\n"],"mappings":";AAgBA,SAAgB,eAAe,SAAiD;CAC9E,QAAQ,WAAW,CAAC,GAAG,SAAS,SAAuB;EACrD,IAAI,KAAK,SAAS,gBAChB,OAAO,CAAC;EAGV,MAAM,QAAQ,KAAK;EAEnB,IAAI,CAAC,MAAM,UACT,OAAO,CAAC;EAGV,OAAO,CACL;GACE,IAAI,KAAK,MAAM;GACf,OAAO,MAAM,SAAS;GACtB,QAAQ,MAAM,UAAU;GACxB,UAAU,MAAM;GAChB,KAAK,MAAM,OAAO;GAClB,SAAS,MAAM,WAAW;GAC1B,cAAc,MAAM;GACpB,MAAM,MAAM;EACd,CACF;CACF,CAAC;AACH"}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { withHeaders } from "../../core/headers.js";
|
|
2
2
|
import { useT } from "../../i18n/instance.js";
|
|
3
3
|
import { prefixedTestId } from "../../core/test-id.js";
|
|
4
|
-
import { getActionEffects } from "../../effects/dispatch.js";
|
|
5
|
-
import { useEffectDispatcher } from "../../effects/use-effect-dispatcher.js";
|
|
6
4
|
import { Button } from "../../core/components/button.js";
|
|
7
5
|
import { Spinner } from "../../core/components/spinner.js";
|
|
8
6
|
import { ConfirmDialog } from "../../core/components/confirm-dialog.js";
|
|
7
|
+
import { getActionEffects } from "../../effects/dispatch.js";
|
|
8
|
+
import { useEffectDispatcher } from "../../effects/use-effect-dispatcher.js";
|
|
9
9
|
import { runAction } from "../../action/run-action.js";
|
|
10
10
|
import { ActionForm } from "../../action/components/action-form.js";
|
|
11
11
|
import { useHttp } from "@inertiajs/react";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { useLocale } from "../../../i18n/locale.js";
|
|
2
|
-
import { formatCell } from "../../format.js";
|
|
3
2
|
import { numericValue } from "../../../format/numeric.js";
|
|
4
3
|
import { formatNumber } from "../../../format/number.js";
|
|
4
|
+
import { formatCell } from "../../format.js";
|
|
5
5
|
import { jsx } from "react/jsx-runtime";
|
|
6
6
|
//#region resources/js/table/components/cells/money-cell.tsx
|
|
7
7
|
var MoneyCell = ({ column, props, row, value }) => {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { useLocale } from "../../../i18n/locale.js";
|
|
2
|
-
import { formatCell } from "../../format.js";
|
|
3
2
|
import { numericValue } from "../../../format/numeric.js";
|
|
4
3
|
import { formatNumber } from "../../../format/number.js";
|
|
4
|
+
import { formatCell } from "../../format.js";
|
|
5
5
|
import { jsx } from "react/jsx-runtime";
|
|
6
6
|
//#region resources/js/table/components/cells/number-cell.tsx
|
|
7
7
|
var NumberCell = ({ column, props, value }) => {
|