@judo/feedback 0.1.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 (85) hide show
  1. package/LICENSE +277 -0
  2. package/README.md +172 -0
  3. package/dist/dialogs/components/alert-dialog.d.ts +11 -0
  4. package/dist/dialogs/components/alert-dialog.d.ts.map +1 -0
  5. package/dist/dialogs/components/confirm-dialog.d.ts +12 -0
  6. package/dist/dialogs/components/confirm-dialog.d.ts.map +1 -0
  7. package/dist/dialogs/components/dialog-host.d.ts +10 -0
  8. package/dist/dialogs/components/dialog-host.d.ts.map +1 -0
  9. package/dist/dialogs/components/index.d.ts +4 -0
  10. package/dist/dialogs/components/index.d.ts.map +1 -0
  11. package/dist/dialogs/hooks/index.d.ts +2 -0
  12. package/dist/dialogs/hooks/index.d.ts.map +1 -0
  13. package/dist/dialogs/hooks/use-confirmation.d.ts +9 -0
  14. package/dist/dialogs/hooks/use-confirmation.d.ts.map +1 -0
  15. package/dist/dialogs/index.d.ts +11 -0
  16. package/dist/dialogs/index.d.ts.map +1 -0
  17. package/dist/dialogs/provider/dialog-provider.d.ts +20 -0
  18. package/dist/dialogs/provider/dialog-provider.d.ts.map +1 -0
  19. package/dist/dialogs/provider/index.d.ts +2 -0
  20. package/dist/dialogs/provider/index.d.ts.map +1 -0
  21. package/dist/dialogs/service/dialog-service-impl.d.ts +18 -0
  22. package/dist/dialogs/service/dialog-service-impl.d.ts.map +1 -0
  23. package/dist/dialogs/service/dialog-service.d.ts +71 -0
  24. package/dist/dialogs/service/dialog-service.d.ts.map +1 -0
  25. package/dist/dialogs/service/index.d.ts +3 -0
  26. package/dist/dialogs/service/index.d.ts.map +1 -0
  27. package/dist/index.d.ts +11 -0
  28. package/dist/index.d.ts.map +1 -0
  29. package/dist/index.js +497 -0
  30. package/dist/index.js.map +1 -0
  31. package/dist/loading/components/container-loading.d.ts +13 -0
  32. package/dist/loading/components/container-loading.d.ts.map +1 -0
  33. package/dist/loading/components/global-loading-overlay.d.ts +9 -0
  34. package/dist/loading/components/global-loading-overlay.d.ts.map +1 -0
  35. package/dist/loading/components/index.d.ts +4 -0
  36. package/dist/loading/components/index.d.ts.map +1 -0
  37. package/dist/loading/components/skeletons/card-skeleton.d.ts +5 -0
  38. package/dist/loading/components/skeletons/card-skeleton.d.ts.map +1 -0
  39. package/dist/loading/components/skeletons/form-skeleton.d.ts +9 -0
  40. package/dist/loading/components/skeletons/form-skeleton.d.ts.map +1 -0
  41. package/dist/loading/components/skeletons/index.d.ts +6 -0
  42. package/dist/loading/components/skeletons/index.d.ts.map +1 -0
  43. package/dist/loading/components/skeletons/link-skeleton.d.ts +5 -0
  44. package/dist/loading/components/skeletons/link-skeleton.d.ts.map +1 -0
  45. package/dist/loading/components/skeletons/table-skeleton.d.ts +10 -0
  46. package/dist/loading/components/skeletons/table-skeleton.d.ts.map +1 -0
  47. package/dist/loading/components/skeletons/text-input-skeleton.d.ts +8 -0
  48. package/dist/loading/components/skeletons/text-input-skeleton.d.ts.map +1 -0
  49. package/dist/loading/hooks/index.d.ts +3 -0
  50. package/dist/loading/hooks/index.d.ts.map +1 -0
  51. package/dist/loading/hooks/use-component-loading.d.ts +10 -0
  52. package/dist/loading/hooks/use-component-loading.d.ts.map +1 -0
  53. package/dist/loading/hooks/use-loading-state.d.ts +6 -0
  54. package/dist/loading/hooks/use-loading-state.d.ts.map +1 -0
  55. package/dist/loading/index.d.ts +11 -0
  56. package/dist/loading/index.d.ts.map +1 -0
  57. package/dist/loading/provider/index.d.ts +2 -0
  58. package/dist/loading/provider/index.d.ts.map +1 -0
  59. package/dist/loading/provider/loading-provider.d.ts +22 -0
  60. package/dist/loading/provider/loading-provider.d.ts.map +1 -0
  61. package/dist/loading/service/index.d.ts +3 -0
  62. package/dist/loading/service/index.d.ts.map +1 -0
  63. package/dist/loading/service/loading-service-impl.d.ts +19 -0
  64. package/dist/loading/service/loading-service-impl.d.ts.map +1 -0
  65. package/dist/loading/service/loading-service.d.ts +43 -0
  66. package/dist/loading/service/loading-service.d.ts.map +1 -0
  67. package/dist/notifications/hooks/index.d.ts +2 -0
  68. package/dist/notifications/hooks/index.d.ts.map +1 -0
  69. package/dist/notifications/hooks/use-notifications.d.ts +7 -0
  70. package/dist/notifications/hooks/use-notifications.d.ts.map +1 -0
  71. package/dist/notifications/index.d.ts +10 -0
  72. package/dist/notifications/index.d.ts.map +1 -0
  73. package/dist/notifications/provider/index.d.ts +2 -0
  74. package/dist/notifications/provider/index.d.ts.map +1 -0
  75. package/dist/notifications/provider/notification-provider.d.ts +12 -0
  76. package/dist/notifications/provider/notification-provider.d.ts.map +1 -0
  77. package/dist/notifications/service/index.d.ts +3 -0
  78. package/dist/notifications/service/index.d.ts.map +1 -0
  79. package/dist/notifications/service/notification-service-impl.d.ts +14 -0
  80. package/dist/notifications/service/notification-service-impl.d.ts.map +1 -0
  81. package/dist/notifications/service/notification-service.d.ts +62 -0
  82. package/dist/notifications/service/notification-service.d.ts.map +1 -0
  83. package/dist/provider/index.d.ts +40 -0
  84. package/dist/provider/index.d.ts.map +1 -0
  85. package/package.json +60 -0
@@ -0,0 +1,71 @@
1
+ import { ComponentType } from 'react';
2
+ /**
3
+ * Options for confirmation dialogs.
4
+ */
5
+ export interface ConfirmDialogOptions {
6
+ title?: string;
7
+ message: string;
8
+ confirmText?: string;
9
+ cancelText?: string;
10
+ confirmColor?: "primary" | "secondary" | "error" | "warning";
11
+ /** Show dangerous action styling */
12
+ destructive?: boolean;
13
+ }
14
+ /**
15
+ * Options for alert dialogs.
16
+ */
17
+ export interface AlertDialogOptions {
18
+ title?: string;
19
+ message: string;
20
+ variant?: "info" | "warning" | "error";
21
+ okText?: string;
22
+ }
23
+ /**
24
+ * Props passed to custom dialog components.
25
+ */
26
+ export interface CustomDialogProps<T = unknown> {
27
+ onClose: (result?: T) => void;
28
+ }
29
+ /**
30
+ * Custom dialog configuration.
31
+ */
32
+ export interface CustomDialog<T = unknown, P extends CustomDialogProps<T> = CustomDialogProps<T>> {
33
+ component: ComponentType<P>;
34
+ props?: Omit<P, "onClose">;
35
+ size?: "xs" | "sm" | "md" | "lg" | "xl";
36
+ fullWidth?: boolean;
37
+ disableBackdropClick?: boolean;
38
+ }
39
+ /**
40
+ * Internal dialog state for tracking open dialogs.
41
+ */
42
+ export interface DialogState {
43
+ id: string;
44
+ type: "confirm" | "alert" | "custom";
45
+ options?: ConfirmDialogOptions | AlertDialogOptions;
46
+ dialog?: CustomDialog<unknown>;
47
+ }
48
+ /**
49
+ * DialogService interface for managing dialogs.
50
+ */
51
+ export interface DialogService {
52
+ /** Show confirmation dialog, returns true if confirmed */
53
+ confirm(options: ConfirmDialogOptions): Promise<boolean>;
54
+ /** Show alert dialog */
55
+ alert(options: AlertDialogOptions): Promise<void>;
56
+ /** Show custom dialog */
57
+ open<T, P extends CustomDialogProps<T> = CustomDialogProps<T>>(dialog: CustomDialog<T, P>): Promise<T | undefined>;
58
+ /** Close dialog by ID */
59
+ close(id: string, result?: unknown): void;
60
+ /** Close all dialogs */
61
+ closeAll(): void;
62
+ /** Subscribe to dialog state changes */
63
+ subscribe(callback: () => void): () => void;
64
+ /** Get current dialog states */
65
+ getSnapshot(): DialogState[];
66
+ }
67
+ /**
68
+ * Generate a unique ID for dialogs.
69
+ */
70
+ export declare function generateDialogId(): string;
71
+ //# sourceMappingURL=dialog-service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dialog-service.d.ts","sourceRoot":"","sources":["../../../src/dialogs/service/dialog-service.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAE3C;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACpC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,SAAS,GAAG,WAAW,GAAG,OAAO,GAAG,SAAS,CAAC;IAC7D,oCAAoC;IACpC,WAAW,CAAC,EAAE,OAAO,CAAC;CACtB;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IAClC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC;IACvC,MAAM,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB,CAAC,CAAC,GAAG,OAAO;IAC7C,OAAO,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,KAAK,IAAI,CAAC;CAC9B;AAED;;GAEG;AACH,MAAM,WAAW,YAAY,CAAC,CAAC,GAAG,OAAO,EAAE,CAAC,SAAS,iBAAiB,CAAC,CAAC,CAAC,GAAG,iBAAiB,CAAC,CAAC,CAAC;IAC/F,SAAS,EAAE,aAAa,CAAC,CAAC,CAAC,CAAC;IAC5B,KAAK,CAAC,EAAE,IAAI,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC;IAC3B,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;IACxC,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,oBAAoB,CAAC,EAAE,OAAO,CAAC;CAC/B;AAED;;GAEG;AACH,MAAM,WAAW,WAAW;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,SAAS,GAAG,OAAO,GAAG,QAAQ,CAAC;IACrC,OAAO,CAAC,EAAE,oBAAoB,GAAG,kBAAkB,CAAC;IACpD,MAAM,CAAC,EAAE,YAAY,CAAC,OAAO,CAAC,CAAC;CAC/B;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC7B,0DAA0D;IAC1D,OAAO,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAEzD,wBAAwB;IACxB,KAAK,CAAC,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAElD,yBAAyB;IACzB,IAAI,CAAC,CAAC,EAAE,CAAC,SAAS,iBAAiB,CAAC,CAAC,CAAC,GAAG,iBAAiB,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,YAAY,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC;IAEnH,yBAAyB;IACzB,KAAK,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;IAE1C,wBAAwB;IACxB,QAAQ,IAAI,IAAI,CAAC;IAEjB,wCAAwC;IACxC,SAAS,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC;IAE5C,gCAAgC;IAChC,WAAW,IAAI,WAAW,EAAE,CAAC;CAC7B;AAED;;GAEG;AACH,wBAAgB,gBAAgB,IAAI,MAAM,CAEzC"}
@@ -0,0 +1,3 @@
1
+ export { type DialogService, type DialogState, type ConfirmDialogOptions, type AlertDialogOptions, type CustomDialog, type CustomDialogProps, generateDialogId, } from './dialog-service';
2
+ export { DialogServiceImpl } from './dialog-service-impl';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/dialogs/service/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,KAAK,aAAa,EAClB,KAAK,WAAW,EAChB,KAAK,oBAAoB,EACzB,KAAK,kBAAkB,EACvB,KAAK,YAAY,EACjB,KAAK,iBAAiB,EACtB,gBAAgB,GAChB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * @judo/feedback
3
+ *
4
+ * User feedback system for JUDO UI Runtime.
5
+ * Provides dialogs, notifications, and loading states for better UX.
6
+ */
7
+ export { type DialogService, type DialogState, type ConfirmDialogOptions, type AlertDialogOptions, type CustomDialog, type CustomDialogProps, generateDialogId, DialogServiceImpl, ConfirmDialog, type ConfirmDialogProps, AlertDialog, type AlertDialogProps, DialogHost, type DialogHostProps, DialogProvider, useDialog, useDialogOptional, type DialogProviderProps, useConfirmation, } from './dialogs';
8
+ export { type NotificationService, type Notification, type NotificationOptions, type NotificationAction, type NotificationVariant, type NotificationPosition, mapPositionToAnchorOrigin, NotificationServiceImpl, NotificationProvider, type NotificationProviderProps, useNotifications, } from './notifications';
9
+ export { type LoadingService, type LoadingSnapshot, type LoadingOptions, LoadingServiceImpl, TextInputSkeleton, type TextInputSkeletonProps, TableSkeleton, type TableSkeletonProps, FormSkeleton, type FormSkeletonProps, CardSkeleton, LinkSkeleton, ContainerLoading, type ContainerLoadingProps, GlobalLoadingOverlay, type GlobalLoadingOverlayProps, LoadingProvider, useLoading, useLoadingOptional, type LoadingProviderProps, useLoadingState, useComponentLoading, } from './loading';
10
+ export { FeedbackProvider, type FeedbackProviderProps, useFeedback } from './provider';
11
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,EAEN,KAAK,aAAa,EAClB,KAAK,WAAW,EAChB,KAAK,oBAAoB,EACzB,KAAK,kBAAkB,EACvB,KAAK,YAAY,EACjB,KAAK,iBAAiB,EACtB,gBAAgB,EAChB,iBAAiB,EAEjB,aAAa,EACb,KAAK,kBAAkB,EACvB,WAAW,EACX,KAAK,gBAAgB,EACrB,UAAU,EACV,KAAK,eAAe,EAEpB,cAAc,EACd,SAAS,EACT,iBAAiB,EACjB,KAAK,mBAAmB,EAExB,eAAe,GACf,MAAM,WAAW,CAAC;AAKnB,OAAO,EAEN,KAAK,mBAAmB,EACxB,KAAK,YAAY,EACjB,KAAK,mBAAmB,EACxB,KAAK,kBAAkB,EACvB,KAAK,mBAAmB,EACxB,KAAK,oBAAoB,EACzB,yBAAyB,EACzB,uBAAuB,EAEvB,oBAAoB,EACpB,KAAK,yBAAyB,EAE9B,gBAAgB,GAChB,MAAM,iBAAiB,CAAC;AAKzB,OAAO,EAEN,KAAK,cAAc,EACnB,KAAK,eAAe,EACpB,KAAK,cAAc,EACnB,kBAAkB,EAElB,iBAAiB,EACjB,KAAK,sBAAsB,EAC3B,aAAa,EACb,KAAK,kBAAkB,EACvB,YAAY,EACZ,KAAK,iBAAiB,EACtB,YAAY,EACZ,YAAY,EACZ,gBAAgB,EAChB,KAAK,qBAAqB,EAC1B,oBAAoB,EACpB,KAAK,yBAAyB,EAE9B,eAAe,EACf,UAAU,EACV,kBAAkB,EAClB,KAAK,oBAAoB,EAEzB,eAAe,EACf,mBAAmB,GACnB,MAAM,WAAW,CAAC;AAKnB,OAAO,EAAE,gBAAgB,EAAE,KAAK,qBAAqB,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,497 @@
1
+ import { Alert, Backdrop, Box, Button, Card, CardContent, CircularProgress, Dialog, DialogActions, DialogContent, DialogContentText, DialogTitle, Skeleton, Typography } from "@mui/material";
2
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
3
+ import { createContext, useCallback, useContext, useEffect, useMemo, useRef, useState, useSyncExternalStore } from "react";
4
+ import { SnackbarProvider, closeSnackbar, enqueueSnackbar, useSnackbar } from "notistack";
5
+ function generateDialogId() {
6
+ return `dialog-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;
7
+ }
8
+ var DialogServiceImpl = class {
9
+ dialogs = [];
10
+ resolvers = /* @__PURE__ */ new Map();
11
+ subscribers = /* @__PURE__ */ new Set();
12
+ confirm(v) {
13
+ return new Promise((q) => {
14
+ let J = generateDialogId();
15
+ this.resolvers.set(J, q), this.dialogs = [...this.dialogs, {
16
+ id: J,
17
+ type: "confirm",
18
+ options: v
19
+ }], this.notify();
20
+ });
21
+ }
22
+ alert(v) {
23
+ return new Promise((q) => {
24
+ let J = generateDialogId();
25
+ this.resolvers.set(J, q), this.dialogs = [...this.dialogs, {
26
+ id: J,
27
+ type: "alert",
28
+ options: v
29
+ }], this.notify();
30
+ });
31
+ }
32
+ open(v) {
33
+ return new Promise((q) => {
34
+ let J = generateDialogId();
35
+ this.resolvers.set(J, q), this.dialogs = [...this.dialogs, {
36
+ id: J,
37
+ type: "custom",
38
+ dialog: v
39
+ }], this.notify();
40
+ });
41
+ }
42
+ close(v, q) {
43
+ let J = this.resolvers.get(v);
44
+ J && (J(q), this.resolvers.delete(v)), this.dialogs = this.dialogs.filter((q) => q.id !== v), this.notify();
45
+ }
46
+ closeAll() {
47
+ for (let [v, q] of this.resolvers) q(void 0);
48
+ this.resolvers.clear(), this.dialogs = [], this.notify();
49
+ }
50
+ subscribe(v) {
51
+ return this.subscribers.add(v), () => {
52
+ this.subscribers.delete(v);
53
+ };
54
+ }
55
+ getSnapshot() {
56
+ return this.dialogs;
57
+ }
58
+ notify() {
59
+ for (let v of this.subscribers) v();
60
+ }
61
+ };
62
+ function ConfirmDialog({ open: v, options: q, onConfirm: J, onCancel: X }) {
63
+ return /* @__PURE__ */ jsxs(Dialog, {
64
+ open: v,
65
+ onClose: X,
66
+ "aria-labelledby": "confirm-dialog-title",
67
+ children: [
68
+ /* @__PURE__ */ jsx(DialogTitle, {
69
+ id: "confirm-dialog-title",
70
+ children: q.title ?? "Confirm"
71
+ }),
72
+ /* @__PURE__ */ jsx(DialogContent, { children: /* @__PURE__ */ jsx(DialogContentText, { children: q.message }) }),
73
+ /* @__PURE__ */ jsxs(DialogActions, { children: [/* @__PURE__ */ jsx(Button, {
74
+ onClick: X,
75
+ children: q.cancelText ?? "Cancel"
76
+ }), /* @__PURE__ */ jsx(Button, {
77
+ onClick: J,
78
+ variant: "contained",
79
+ color: q.destructive ? "error" : q.confirmColor ?? "primary",
80
+ children: q.confirmText ?? "Confirm"
81
+ })] })
82
+ ]
83
+ });
84
+ }
85
+ function AlertDialog({ open: q, options: J, onClose: X }) {
86
+ return /* @__PURE__ */ jsxs(Dialog, {
87
+ open: q,
88
+ onClose: X,
89
+ "aria-labelledby": "alert-dialog-title",
90
+ children: [
91
+ /* @__PURE__ */ jsx(DialogTitle, {
92
+ id: "alert-dialog-title",
93
+ children: J.title ?? "Alert"
94
+ }),
95
+ /* @__PURE__ */ jsx(DialogContent, { children: J.variant ? /* @__PURE__ */ jsx(Alert, {
96
+ severity: J.variant,
97
+ sx: { mb: 1 },
98
+ children: J.message
99
+ }) : /* @__PURE__ */ jsx(DialogContentText, { children: J.message }) }),
100
+ /* @__PURE__ */ jsx(DialogActions, { children: /* @__PURE__ */ jsx(Button, {
101
+ onClick: X,
102
+ variant: "contained",
103
+ children: J.okText ?? "OK"
104
+ }) })
105
+ ]
106
+ });
107
+ }
108
+ function DialogHost({ service: v }) {
109
+ return /* @__PURE__ */ jsx(Fragment, { children: useSyncExternalStore(v.subscribe.bind(v), v.getSnapshot.bind(v)).map((q) => /* @__PURE__ */ jsx(DialogRenderer, {
110
+ dialog: q,
111
+ service: v
112
+ }, q.id)) });
113
+ }
114
+ function DialogRenderer({ dialog: v, service: q }) {
115
+ if (v.type === "confirm") return /* @__PURE__ */ jsx(ConfirmDialog, {
116
+ open: !0,
117
+ options: v.options,
118
+ onConfirm: () => q.close(v.id, !0),
119
+ onCancel: () => q.close(v.id, !1)
120
+ });
121
+ if (v.type === "alert") return /* @__PURE__ */ jsx(AlertDialog, {
122
+ open: !0,
123
+ options: v.options,
124
+ onClose: () => q.close(v.id)
125
+ });
126
+ if (v.type === "custom" && v.dialog) {
127
+ let J = v.dialog.component;
128
+ return /* @__PURE__ */ jsx(Dialog, {
129
+ open: !0,
130
+ onClose: v.dialog.disableBackdropClick ? void 0 : () => q.close(v.id),
131
+ maxWidth: v.dialog.size ?? "sm",
132
+ fullWidth: v.dialog.fullWidth ?? !0,
133
+ children: /* @__PURE__ */ jsx(J, {
134
+ onClose: (J) => q.close(v.id, J),
135
+ ...v.dialog.props
136
+ })
137
+ });
138
+ }
139
+ return null;
140
+ }
141
+ var DialogContext = createContext(null);
142
+ function DialogProvider({ children: v, service: q }) {
143
+ let J = useMemo(() => q ?? new DialogServiceImpl(), [q]);
144
+ return /* @__PURE__ */ jsxs(DialogContext.Provider, {
145
+ value: J,
146
+ children: [v, /* @__PURE__ */ jsx(DialogHost, { service: J })]
147
+ });
148
+ }
149
+ function useDialog() {
150
+ let v = useContext(DialogContext);
151
+ if (!v) throw Error("useDialog must be used within a DialogProvider");
152
+ return v;
153
+ }
154
+ function useDialogOptional() {
155
+ return useContext(DialogContext);
156
+ }
157
+ function useConfirmation() {
158
+ let v = useDialog();
159
+ return { confirm: useCallback((q) => v.confirm(q), [v]) };
160
+ }
161
+ function mapPositionToAnchorOrigin(v) {
162
+ return {
163
+ "top-right": {
164
+ vertical: "top",
165
+ horizontal: "right"
166
+ },
167
+ "top-center": {
168
+ vertical: "top",
169
+ horizontal: "center"
170
+ },
171
+ "top-left": {
172
+ vertical: "top",
173
+ horizontal: "left"
174
+ },
175
+ "bottom-right": {
176
+ vertical: "bottom",
177
+ horizontal: "right"
178
+ },
179
+ "bottom-center": {
180
+ vertical: "bottom",
181
+ horizontal: "center"
182
+ },
183
+ "bottom-left": {
184
+ vertical: "bottom",
185
+ horizontal: "left"
186
+ }
187
+ }[v ?? "bottom-right"];
188
+ }
189
+ var NotificationServiceImpl = class {
190
+ success(v, q) {
191
+ return this.show({
192
+ message: v,
193
+ variant: "success",
194
+ ...q
195
+ });
196
+ }
197
+ error(v, q) {
198
+ return this.show({
199
+ message: v,
200
+ variant: "error",
201
+ duration: 0,
202
+ ...q
203
+ });
204
+ }
205
+ warning(v, q) {
206
+ return this.show({
207
+ message: v,
208
+ variant: "warning",
209
+ ...q
210
+ });
211
+ }
212
+ info(v, q) {
213
+ return this.show({
214
+ message: v,
215
+ variant: "info",
216
+ ...q
217
+ });
218
+ }
219
+ show(v) {
220
+ let q = enqueueSnackbar(v.message, {
221
+ variant: v.variant,
222
+ autoHideDuration: v.duration === 0 ? null : v.duration ?? 5e3,
223
+ anchorOrigin: mapPositionToAnchorOrigin(v.position),
224
+ preventDuplicate: v.key !== void 0,
225
+ key: v.key
226
+ });
227
+ return String(q);
228
+ }
229
+ dismiss(v) {
230
+ closeSnackbar(v);
231
+ }
232
+ dismissAll() {
233
+ closeSnackbar();
234
+ }
235
+ };
236
+ function NotificationProvider({ children: v, maxSnack: q = 5 }) {
237
+ return /* @__PURE__ */ jsx(SnackbarProvider, {
238
+ maxSnack: q,
239
+ anchorOrigin: {
240
+ vertical: "bottom",
241
+ horizontal: "right"
242
+ },
243
+ children: v
244
+ });
245
+ }
246
+ function useNotifications() {
247
+ let { enqueueSnackbar: v, closeSnackbar: q } = useSnackbar();
248
+ return useMemo(() => ({
249
+ success(v, q) {
250
+ return this.show({
251
+ message: v,
252
+ variant: "success",
253
+ ...q
254
+ });
255
+ },
256
+ error(v, q) {
257
+ return this.show({
258
+ message: v,
259
+ variant: "error",
260
+ duration: 0,
261
+ ...q
262
+ });
263
+ },
264
+ warning(v, q) {
265
+ return this.show({
266
+ message: v,
267
+ variant: "warning",
268
+ ...q
269
+ });
270
+ },
271
+ info(v, q) {
272
+ return this.show({
273
+ message: v,
274
+ variant: "info",
275
+ ...q
276
+ });
277
+ },
278
+ show(q) {
279
+ let J = v(q.message, {
280
+ variant: q.variant,
281
+ autoHideDuration: q.duration === 0 ? null : q.duration ?? 5e3,
282
+ anchorOrigin: mapPositionToAnchorOrigin(q.position),
283
+ preventDuplicate: q.key !== void 0,
284
+ key: q.key
285
+ });
286
+ return String(J);
287
+ },
288
+ dismiss(v) {
289
+ q(v);
290
+ },
291
+ dismissAll() {
292
+ q();
293
+ }
294
+ }), [v, q]);
295
+ }
296
+ var LoadingServiceImpl = class {
297
+ loadingStates = /* @__PURE__ */ new Map();
298
+ subscribers = /* @__PURE__ */ new Set();
299
+ cachedSnapshot = null;
300
+ start(v, q = {}) {
301
+ this.loadingStates.set(v, q), this.invalidateSnapshot(), this.notify();
302
+ }
303
+ end(v) {
304
+ this.loadingStates.delete(v), this.invalidateSnapshot(), this.notify();
305
+ }
306
+ isLoading() {
307
+ return this.loadingStates.size > 0;
308
+ }
309
+ isLoadingKey(v) {
310
+ return this.loadingStates.has(v);
311
+ }
312
+ getActiveKeys() {
313
+ return Array.from(this.loadingStates.keys());
314
+ }
315
+ subscribe(v) {
316
+ return this.subscribers.add(v), () => {
317
+ this.subscribers.delete(v);
318
+ };
319
+ }
320
+ getSnapshot() {
321
+ if (this.cachedSnapshot) return this.cachedSnapshot;
322
+ let v = Array.from(this.loadingStates.entries()).find(([, v]) => v.global);
323
+ return this.cachedSnapshot = {
324
+ isLoading: this.loadingStates.size > 0,
325
+ activeKeys: this.getActiveKeys(),
326
+ globalLoading: !!v,
327
+ message: v?.[1].message,
328
+ progress: v?.[1].progress
329
+ }, this.cachedSnapshot;
330
+ }
331
+ invalidateSnapshot() {
332
+ this.cachedSnapshot = null;
333
+ }
334
+ notify() {
335
+ for (let v of this.subscribers) v();
336
+ }
337
+ };
338
+ function TextInputSkeleton({ width: v = "100%" }) {
339
+ return /* @__PURE__ */ jsxs(Box, {
340
+ sx: { width: v },
341
+ children: [/* @__PURE__ */ jsx(Skeleton, {
342
+ variant: "text",
343
+ width: 80,
344
+ height: 20,
345
+ sx: { mb: .5 }
346
+ }), /* @__PURE__ */ jsx(Skeleton, {
347
+ variant: "rectangular",
348
+ height: 56
349
+ })]
350
+ });
351
+ }
352
+ function TableSkeleton({ rows: v = 5, columns: q = 4 }) {
353
+ let Y = Array.from({ length: q }, (v, q) => /* @__PURE__ */ jsx(Skeleton, {
354
+ variant: "text",
355
+ sx: { flex: 1 },
356
+ height: 40
357
+ }, q)), X = Array.from({ length: v }, (v, Y) => /* @__PURE__ */ jsx(Box, {
358
+ display: "flex",
359
+ gap: 2,
360
+ mb: 1,
361
+ children: Array.from({ length: q }, (v, q) => /* @__PURE__ */ jsx(Skeleton, {
362
+ variant: "text",
363
+ sx: { flex: 1 },
364
+ height: 32
365
+ }, q))
366
+ }, Y));
367
+ return /* @__PURE__ */ jsxs(Box, { children: [/* @__PURE__ */ jsx(Box, {
368
+ display: "flex",
369
+ gap: 2,
370
+ mb: 1,
371
+ children: Y
372
+ }), X] });
373
+ }
374
+ function FormSkeleton({ fields: v = 4 }) {
375
+ return /* @__PURE__ */ jsx(Box, {
376
+ display: "flex",
377
+ flexDirection: "column",
378
+ gap: 2,
379
+ children: Array.from({ length: v }, (v, q) => /* @__PURE__ */ jsx(TextInputSkeleton, {}, q))
380
+ });
381
+ }
382
+ function CardSkeleton() {
383
+ return /* @__PURE__ */ jsx(Card, { children: /* @__PURE__ */ jsxs(CardContent, { children: [
384
+ /* @__PURE__ */ jsx(Skeleton, {
385
+ variant: "text",
386
+ width: "60%",
387
+ height: 32
388
+ }),
389
+ /* @__PURE__ */ jsx(Skeleton, {
390
+ variant: "text",
391
+ width: "80%"
392
+ }),
393
+ /* @__PURE__ */ jsx(Skeleton, {
394
+ variant: "text",
395
+ width: "40%"
396
+ })
397
+ ] }) });
398
+ }
399
+ function LinkSkeleton() {
400
+ return /* @__PURE__ */ jsxs(Box, { children: [/* @__PURE__ */ jsx(Skeleton, {
401
+ variant: "text",
402
+ width: 80,
403
+ height: 20,
404
+ sx: { mb: .5 }
405
+ }), /* @__PURE__ */ jsx(Skeleton, {
406
+ variant: "rectangular",
407
+ height: 56
408
+ })] });
409
+ }
410
+ function ContainerLoading({ loading: v, skeleton: q, children: Y, minLoadingTime: X = 200 }) {
411
+ let [Z, Q] = useState(v), $ = useRef(null);
412
+ return useEffect(() => {
413
+ if (v) $.current = Date.now(), Q(!0);
414
+ else if ($.current) {
415
+ let v = Date.now() - $.current, q = Math.max(0, X - v);
416
+ if (q > 0) {
417
+ let v = setTimeout(() => Q(!1), q);
418
+ return () => clearTimeout(v);
419
+ }
420
+ Q(!1), $.current = null;
421
+ } else Q(!1);
422
+ }, [v, X]), Z && q ? /* @__PURE__ */ jsx(Fragment, { children: q }) : Z ? /* @__PURE__ */ jsx(Box, {
423
+ display: "flex",
424
+ justifyContent: "center",
425
+ alignItems: "center",
426
+ p: 4,
427
+ children: /* @__PURE__ */ jsx(CircularProgress, {})
428
+ }) : /* @__PURE__ */ jsx(Fragment, { children: Y });
429
+ }
430
+ function GlobalLoadingOverlay({ service: v }) {
431
+ let J = useSyncExternalStore(v.subscribe.bind(v), v.getSnapshot.bind(v));
432
+ return J.globalLoading ? /* @__PURE__ */ jsxs(Backdrop, {
433
+ open: J.globalLoading,
434
+ sx: {
435
+ zIndex: (v) => v.zIndex.modal + 1,
436
+ flexDirection: "column",
437
+ gap: 2,
438
+ color: "#fff"
439
+ },
440
+ children: [J.progress === void 0 ? /* @__PURE__ */ jsx(CircularProgress, {
441
+ size: 60,
442
+ color: "inherit"
443
+ }) : /* @__PURE__ */ jsx(CircularProgress, {
444
+ variant: "determinate",
445
+ value: J.progress,
446
+ size: 60,
447
+ color: "inherit"
448
+ }), J.message && /* @__PURE__ */ jsx(Typography, {
449
+ color: "inherit",
450
+ variant: "h6",
451
+ children: J.message
452
+ })]
453
+ }) : null;
454
+ }
455
+ var LoadingContext = createContext(null);
456
+ function LoadingProvider({ children: v, service: q, showGlobalOverlay: J = !0 }) {
457
+ let Y = useMemo(() => q ?? new LoadingServiceImpl(), [q]);
458
+ return /* @__PURE__ */ jsxs(LoadingContext.Provider, {
459
+ value: Y,
460
+ children: [v, J && /* @__PURE__ */ jsx(GlobalLoadingOverlay, { service: Y })]
461
+ });
462
+ }
463
+ function useLoading() {
464
+ let v = useContext(LoadingContext);
465
+ if (!v) throw Error("useLoading must be used within a LoadingProvider");
466
+ return v;
467
+ }
468
+ function useLoadingOptional() {
469
+ return useContext(LoadingContext);
470
+ }
471
+ function useLoadingState() {
472
+ let v = useLoading();
473
+ return useSyncExternalStore(v.subscribe.bind(v), v.getSnapshot.bind(v));
474
+ }
475
+ function useComponentLoading(v) {
476
+ let q = useLoading();
477
+ return {
478
+ isLoading: useSyncExternalStore(q.subscribe.bind(q), () => q.isLoadingKey(v)),
479
+ startLoading: useCallback((J) => {
480
+ q.start(v, J);
481
+ }, [q, v]),
482
+ endLoading: useCallback(() => {
483
+ q.end(v);
484
+ }, [q, v])
485
+ };
486
+ }
487
+ function FeedbackProvider({ children: v }) {
488
+ return /* @__PURE__ */ jsx(DialogProvider, { children: /* @__PURE__ */ jsx(NotificationProvider, { children: /* @__PURE__ */ jsx(LoadingProvider, { children: v }) }) });
489
+ }
490
+ function useFeedback() {
491
+ return {
492
+ dialogs: useDialog(),
493
+ notifications: useNotifications(),
494
+ loading: useLoading()
495
+ };
496
+ }
497
+ export { AlertDialog, CardSkeleton, ConfirmDialog, ContainerLoading, DialogHost, DialogProvider, DialogServiceImpl, FeedbackProvider, FormSkeleton, GlobalLoadingOverlay, LinkSkeleton, LoadingProvider, LoadingServiceImpl, NotificationProvider, NotificationServiceImpl, TableSkeleton, TextInputSkeleton, generateDialogId, mapPositionToAnchorOrigin, useComponentLoading, useConfirmation, useDialog, useDialogOptional, useFeedback, useLoading, useLoadingOptional, useLoadingState, useNotifications };