@lmb-it/kitsconcerto-native 0.1.294 → 0.1.296

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.
@@ -12,34 +12,90 @@ var index_native$3 = require('../components/overlay/ConfirmPopup/index.cjs');
12
12
  const PopupContext = React.createContext(null);
13
13
  const PopupProvider = ({ children }) => {
14
14
  const toastRef = React.useRef(null);
15
- const [confirmState, setConfirmState] = React.useState({ visible: false });
15
+ const [confirmState, setConfirmState] = React.useState({ visible: false, owner: 0 });
16
16
  const confirmPromiseRef = React.useRef({});
17
- const hideConfirm = React.useCallback(() => setConfirmState((s) => ({ ...s, visible: false })), []);
18
- const doAccept = React.useCallback(() => {
19
- confirmPromiseRef.current.resolve?.(true);
20
- confirmPromiseRef.current = {};
21
- hideConfirm();
22
- }, [hideConfirm]);
23
- const doReject = React.useCallback(() => {
24
- confirmPromiseRef.current.resolve?.(false);
17
+ const confirmOwnerRef = React.useRef(0);
18
+ const notifiedConfirmOwnerRef = React.useRef(0);
19
+ const activeConfirmActionsRef = React.useRef(/* @__PURE__ */ new Map());
20
+ const promptPromiseRef = React.useRef({});
21
+ const mountedRef = React.useRef(true);
22
+ const openConfirmation = React.useCallback((props, pending = {}) => {
23
+ if (!mountedRef.current) {
24
+ pending.resolve?.(false);
25
+ return;
26
+ }
27
+ const previous = confirmPromiseRef.current;
28
+ if (previous.owner !== void 0) previous.resolve?.(false);
29
+ const owner2 = ++confirmOwnerRef.current;
30
+ confirmPromiseRef.current = { ...pending, owner: owner2 };
31
+ setConfirmState({ ...props, owner: owner2 });
32
+ }, []);
33
+ const hideConfirm = React.useCallback((owner2) => {
34
+ if (!mountedRef.current || owner2 !== confirmOwnerRef.current || activeConfirmActionsRef.current.has(owner2)) return;
35
+ const pending = confirmPromiseRef.current;
36
+ setConfirmState((s) => s.owner === owner2 ? { ...s, visible: false } : s);
37
+ Promise.resolve().then(() => {
38
+ if (pending.owner !== owner2) return;
39
+ pending.resolve?.(false);
40
+ if (confirmPromiseRef.current === pending) confirmPromiseRef.current = {};
41
+ });
42
+ }, []);
43
+ const runConfirmAction = React.useCallback((owner2, accepted, callback, wait = false) => {
44
+ if (!mountedRef.current || owner2 !== confirmOwnerRef.current || confirmPromiseRef.current.owner !== owner2) return;
45
+ const pending = confirmPromiseRef.current;
25
46
  confirmPromiseRef.current = {};
26
- hideConfirm();
47
+ if (!wait) {
48
+ pending.resolve?.(accepted);
49
+ try {
50
+ return callback?.();
51
+ } finally {
52
+ hideConfirm(owner2);
53
+ }
54
+ }
55
+ activeConfirmActionsRef.current.set(owner2, pending);
56
+ const failed = (error) => {
57
+ activeConfirmActionsRef.current.delete(owner2);
58
+ if (owner2 !== confirmOwnerRef.current || !mountedRef.current) {
59
+ pending.resolve?.(false);
60
+ return;
61
+ }
62
+ confirmPromiseRef.current = pending;
63
+ return Promise.reject(error);
64
+ };
65
+ try {
66
+ return Promise.resolve(callback?.()).then(() => {
67
+ activeConfirmActionsRef.current.delete(owner2);
68
+ pending.resolve?.(accepted);
69
+ hideConfirm(owner2);
70
+ }, failed);
71
+ } catch (error) {
72
+ return failed(error);
73
+ }
27
74
  }, [hideConfirm]);
28
75
  const [confirmPopupState, setConfirmPopupState] = React.useState({ visible: false });
29
- const hideConfirmPopup = React.useCallback((result) => setConfirmPopupState((s) => ({ ...s, visible: false })), []);
76
+ const hideConfirmPopup = React.useCallback((_result) => setConfirmPopupState((s) => ({ ...s, visible: false })), []);
30
77
  const [dialogState, setDialogState] = React.useState({ visible: false });
31
78
  const onCloseRef = React.useRef();
32
79
  React.useEffect(() => {
33
80
  onCloseRef.current = dialogState.onClose;
34
81
  }, [dialogState.onClose]);
35
82
  const hideDialog = React.useCallback(() => {
83
+ promptPromiseRef.current.reject?.();
84
+ promptPromiseRef.current = {};
36
85
  setDialogState((s) => ({ ...s, visible: false }));
37
86
  onCloseRef.current?.();
38
87
  }, []);
39
- React.useEffect(() => {
88
+ React.useLayoutEffect(() => {
89
+ mountedRef.current = true;
90
+ const activeActions = activeConfirmActionsRef.current;
40
91
  return () => {
92
+ mountedRef.current = false;
41
93
  confirmPromiseRef.current.reject?.();
42
94
  confirmPromiseRef.current = {};
95
+ activeActions.forEach((pending) => pending.reject?.());
96
+ activeActions.clear();
97
+ promptPromiseRef.current.reject?.();
98
+ promptPromiseRef.current = {};
43
99
  };
44
100
  }, []);
45
101
  const toast = React.useCallback((...a) => {
@@ -52,8 +108,8 @@ const PopupProvider = ({ children }) => {
52
108
  toastRef.current?.dismissAll?.();
53
109
  }, []);
54
110
  const confirm = React.useCallback((props) => {
55
- setConfirmState({ visible: true, acceptLabel: "Accept", rejectLabel: "Reject", ...props });
56
- }, []);
111
+ openConfirmation({ visible: true, acceptLabel: "Accept", rejectLabel: "Reject", ...props });
112
+ }, [openConfirmation]);
57
113
  const confirmPopup = React.useCallback((props) => {
58
114
  setConfirmPopupState({ visible: true, ...props });
59
115
  }, []);
@@ -61,8 +117,7 @@ const PopupProvider = ({ children }) => {
61
117
  setDialogState({ visible, ...props });
62
118
  }, []);
63
119
  const alert = React.useCallback((message, opts = {}) => new Promise((resolve) => {
64
- confirmPromiseRef.current = { resolve: () => resolve() };
65
- setConfirmState({
120
+ openConfirmation({
66
121
  visible: true,
67
122
  header: opts.header ?? "Alert",
68
123
  message,
@@ -71,23 +126,25 @@ const PopupProvider = ({ children }) => {
71
126
  type: opts.type,
72
127
  icon: opts.icon,
73
128
  headless: opts.headless
74
- });
75
- }), []);
129
+ }, { resolve: () => resolve(), reject: () => resolve() });
130
+ }), [openConfirmation]);
76
131
  const confirmAsync = React.useCallback((opts) => new Promise((resolve) => {
77
- confirmPromiseRef.current = { resolve };
78
- setConfirmState({
132
+ openConfirmation({
79
133
  visible: true,
80
134
  defaultUI: true,
81
135
  acceptLabel: opts.acceptLabel ?? "Yes",
82
136
  rejectLabel: opts.rejectLabel ?? "No",
83
137
  ...opts
84
- });
85
- }), []);
138
+ }, { resolve, reject: () => resolve(false) });
139
+ }), [openConfirmation]);
86
140
  const prompt = React.useCallback((render, opts = {}) => new Promise((resolve, reject) => {
87
- confirmPromiseRef.current = { resolve, reject };
141
+ const pending = { resolve, reject };
142
+ promptPromiseRef.current.reject?.();
143
+ promptPromiseRef.current = pending;
88
144
  const hide = () => {
145
+ if (promptPromiseRef.current !== pending) return;
89
146
  setDialogState((s) => ({ ...s, visible: false }));
90
- confirmPromiseRef.current = {};
147
+ promptPromiseRef.current = {};
91
148
  };
92
149
  setDialogState({
93
150
  visible: true,
@@ -116,10 +173,25 @@ const PopupProvider = ({ children }) => {
116
173
  confirmAsync,
117
174
  prompt
118
175
  }), [confirm, confirmPopup, dialog, toast, toastDismiss, toastDismissAll, alert, confirmAsync, prompt]);
176
+ const { owner, ...confirmationProps } = confirmState;
119
177
  return /* @__PURE__ */ jsxRuntime.jsxs(PopupContext.Provider, { value, children: [
120
178
  children,
121
179
  /* @__PURE__ */ jsxRuntime.jsx(index_native.default, { ref: toastRef }),
122
- /* @__PURE__ */ jsxRuntime.jsx(index_native$1.default, { onHide: hideConfirm, accept: doAccept, reject: doReject, ...confirmState }),
180
+ /* @__PURE__ */ jsxRuntime.jsx(
181
+ index_native$1.default,
182
+ {
183
+ ...confirmationProps,
184
+ onHide: (result) => {
185
+ if (!mountedRef.current || owner !== confirmOwnerRef.current || activeConfirmActionsRef.current.has(owner) || notifiedConfirmOwnerRef.current === owner) return;
186
+ notifiedConfirmOwnerRef.current = owner;
187
+ hideConfirm(owner);
188
+ confirmationProps.onHide?.(result);
189
+ },
190
+ accept: () => runConfirmAction(owner, true, confirmationProps.accept, confirmationProps.async),
191
+ reject: () => runConfirmAction(owner, false, confirmationProps.reject, confirmationProps.async)
192
+ },
193
+ owner
194
+ ),
123
195
  /* @__PURE__ */ jsxRuntime.jsx(index_native$2.default, { state: dialogState, onHide: hideDialog }),
124
196
  /* @__PURE__ */ jsxRuntime.jsx(index_native$3.default, { onHide: hideConfirmPopup, ...confirmPopupState })
125
197
  ] });
@@ -1 +1 @@
1
- {"version":3,"file":"DialogContext.cjs","sources":["../../../src/contexts/DialogContext.tsx"],"sourcesContent":["import React, {createContext, useCallback, useContext, useEffect, useMemo, useRef, useState} from \"react\";\nimport KitsToast from \"../components/overlay/Toast\";\nimport KitsConfirm from \"../components/overlay/ConfirmDialog\";\nimport KitsDialog from \"../components/overlay/Dialog\";\nimport KitsConfirmPopup from \"../components/overlay/ConfirmPopup\";\nimport type {\n IConfirmDialogProps,\n IConfirmPopupProps,\n IDialogState,\n IKitsToastRef,\n IToastFunction,\n IToastParams,\n ToastPosition,\n} from \"@lmb-it/kitsconcerto-types\";\n\ninterface Ctx {\n confirm: (props: IConfirmDialogProps) => void;\n confirmPopup: (props: IConfirmPopupProps) => void;\n dialog: (props: IDialogState) => void;\n toast: IToastFunction;\n toastDismiss: (position?: ToastPosition) => void;\n toastDismissAll: () => void;\n alert: (message: React.ReactNode, opts?: IConfirmDialogProps) => Promise<void>;\n confirmAsync: (opts: IConfirmDialogProps) => Promise<boolean>;\n prompt: (\n render: (api: { resolve: (v: any) => void; reject: () => void; hide: () => void }) => React.ReactNode,\n opts?: IConfirmDialogProps\n ) => Promise<any>;\n}\n\nconst PopupContext = createContext<Ctx>(null as any);\n\nconst PopupProvider: React.FC<React.PropsWithChildren> = ({children}) => {\n const toastRef = useRef<IKitsToastRef>(null);\n\n // --- Confirm ---\n const [confirmState, setConfirmState] = useState<IConfirmDialogProps>({visible: false});\n const confirmPromiseRef = useRef<{ resolve?: (v: any) => void; reject?: (r?: any) => void }>({});\n\n const hideConfirm = useCallback(() => setConfirmState(s => ({...s, visible: false})), []);\n const doAccept = useCallback(() => {\n confirmPromiseRef.current.resolve?.(true);\n confirmPromiseRef.current = {};\n hideConfirm();\n }, [hideConfirm]);\n const doReject = useCallback(() => {\n confirmPromiseRef.current.resolve?.(false);\n confirmPromiseRef.current = {};\n hideConfirm();\n }, [hideConfirm]);\n\n // --- ConfirmPopup ---\n const [confirmPopupState, setConfirmPopupState] = useState<IConfirmPopupProps>({visible: false});\n const hideConfirmPopup = useCallback((result) => setConfirmPopupState(s => ({...s, visible: false})), []);\n\n // --- Dialog ---\n const [dialogState, setDialogState] = useState<IDialogState>({visible: false});\n // @ts-ignore\n const onCloseRef = useRef<(() => void) | undefined>();\n\n useEffect(() => {\n onCloseRef.current = dialogState.onClose;\n }, [dialogState.onClose]);\n\n const hideDialog = useCallback(() => {\n setDialogState(s => ({...s, visible: false}));\n onCloseRef.current?.();\n }, []);\n\n // --- Cleanup pending promises on unmount ---\n useEffect(() => {\n return () => {\n confirmPromiseRef.current.reject?.();\n confirmPromiseRef.current = {};\n };\n }, []);\n\n // --- Toast API ---\n const toast = useCallback<IToastFunction>((...a) => {\n toastRef.current?.toast(...(a as IToastParams));\n }, []);\n\n const toastDismiss = useCallback((position?: ToastPosition) => {\n toastRef.current?.dismiss?.(position);\n }, []);\n\n const toastDismissAll = useCallback(() => {\n toastRef.current?.dismissAll?.();\n }, []);\n\n // --- Confirm API ---\n const confirm = useCallback((props: IConfirmDialogProps) => {\n setConfirmState({visible: true, acceptLabel: \"Accept\", rejectLabel: \"Reject\", ...props});\n }, []);\n\n const confirmPopup = useCallback((props: IConfirmPopupProps) => {\n setConfirmPopupState({visible: true, ...props});\n }, []);\n\n const dialog = useCallback(({visible = true, ...props}: IDialogState) => {\n setDialogState({visible, ...props});\n }, []);\n\n const alert = useCallback((message: React.ReactNode, opts: IConfirmDialogProps = {}) =>\n new Promise<void>(resolve => {\n confirmPromiseRef.current = {resolve: () => resolve()};\n setConfirmState({\n visible: true,\n header: opts.header ?? \"Alert\",\n message,\n defaultUI: true,\n acceptLabel: opts.acceptLabel ?? \"OK\",\n type: opts.type,\n icon: opts.icon,\n headless: opts.headless,\n });\n }), []);\n\n const confirmAsync = useCallback((opts: IConfirmDialogProps) =>\n new Promise<boolean>(resolve => {\n confirmPromiseRef.current = {resolve};\n setConfirmState({\n visible: true,\n defaultUI: true,\n acceptLabel: opts.acceptLabel ?? \"Yes\",\n rejectLabel: opts.rejectLabel ?? \"No\",\n ...opts,\n });\n }), []);\n\n const prompt = useCallback((\n render: (api: { resolve: (v: any) => void; reject: () => void; hide: () => void }) => React.ReactNode,\n opts: IConfirmDialogProps = {}\n ) =>\n new Promise<any>((resolve, reject) => {\n confirmPromiseRef.current = {resolve, reject};\n const hide = () => {\n setDialogState(s => ({...s, visible: false}));\n confirmPromiseRef.current = {};\n };\n setDialogState({\n visible: true,\n header: opts.header,\n children: render({\n resolve: (v) => {\n resolve(v);\n hide();\n },\n reject: () => {\n reject();\n hide();\n },\n hide,\n }),\n });\n }), []);\n\n // --- Stable context value ---\n const value = useMemo<Ctx>(() => ({\n confirm, confirmPopup, dialog, toast, toastDismiss, toastDismissAll, alert, confirmAsync, prompt,\n }), [confirm, confirmPopup, dialog, toast, toastDismiss, toastDismissAll, alert, confirmAsync, prompt]);\n\n return (\n <PopupContext.Provider value={value}>\n {children}\n <KitsToast ref={toastRef}/>\n <KitsConfirm onHide={hideConfirm} accept={doAccept} reject={doReject} {...confirmState} />\n <KitsDialog state={dialogState} onHide={hideDialog}/>\n {/*@ts-ignore*/}\n <KitsConfirmPopup onHide={hideConfirmPopup} {...confirmPopupState} />\n </PopupContext.Provider>\n );\n};\n\nexport const usePopup = () => useContext(PopupContext);\nexport const useDialog = usePopup; // alias\n\nexport default PopupProvider;\n"],"names":["createContext","useRef","useState","useCallback","useEffect","useMemo","jsxs","jsx","KitsToast","KitsConfirm","KitsDialog","KitsConfirmPopup","useContext"],"mappings":"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"}
1
+ {"version":3,"file":"DialogContext.cjs","sources":["../../../src/contexts/DialogContext.tsx"],"sourcesContent":["import React, {createContext, useCallback, useContext, useEffect, useLayoutEffect, useMemo, useRef, useState} from \"react\";\nimport KitsToast from \"../components/overlay/Toast\";\nimport KitsConfirm from \"../components/overlay/ConfirmDialog\";\nimport KitsDialog from \"../components/overlay/Dialog\";\nimport KitsConfirmPopup from \"../components/overlay/ConfirmPopup\";\nimport type {\n IConfirmDialogProps,\n IConfirmPopupProps,\n IDialogState,\n IKitsToastRef,\n IToastFunction,\n IToastParams,\n ToastPosition,\n} from \"@lmb-it/kitsconcerto-types\";\n\ninterface Ctx {\n confirm: (props: IConfirmDialogProps) => void;\n confirmPopup: (props: IConfirmPopupProps) => void;\n dialog: (props: IDialogState) => void;\n toast: IToastFunction;\n toastDismiss: (position?: ToastPosition) => void;\n toastDismissAll: () => void;\n alert: (message: React.ReactNode, opts?: IConfirmDialogProps) => Promise<void>;\n confirmAsync: (opts: IConfirmDialogProps) => Promise<boolean>;\n prompt: (\n render: (api: { resolve: (v: any) => void; reject: () => void; hide: () => void }) => React.ReactNode,\n opts?: IConfirmDialogProps\n ) => Promise<any>;\n}\n\nconst PopupContext = createContext<Ctx>(null as any);\ntype PendingDialog = {resolve?: (v: any) => void; reject?: (r?: any) => void; owner?: number};\ntype OwnedConfirmation = IConfirmDialogProps & {owner: number};\n\nconst PopupProvider: React.FC<React.PropsWithChildren> = ({children}) => {\n const toastRef = useRef<IKitsToastRef>(null);\n\n // --- Confirm ---\n const [confirmState, setConfirmState] = useState<OwnedConfirmation>({visible: false, owner: 0});\n const confirmPromiseRef = useRef<PendingDialog>({});\n const confirmOwnerRef = useRef(0);\n const notifiedConfirmOwnerRef = useRef(0);\n const activeConfirmActionsRef = useRef(new Map<number, PendingDialog>());\n const promptPromiseRef = useRef<PendingDialog>({});\n const mountedRef = useRef(true);\n\n const openConfirmation = useCallback((props: IConfirmDialogProps, pending: PendingDialog = {}) => {\n if (!mountedRef.current) {pending.resolve?.(false); return;}\n const previous = confirmPromiseRef.current;\n if (previous.owner !== undefined) previous.resolve?.(false);\n const owner = ++confirmOwnerRef.current;\n confirmPromiseRef.current = {...pending, owner};\n setConfirmState({...props, owner});\n }, []);\n\n const hideConfirm = useCallback((owner: number) => {\n if (!mountedRef.current || owner !== confirmOwnerRef.current || activeConfirmActionsRef.current.has(owner)) return;\n const pending = confirmPromiseRef.current;\n setConfirmState(s => s.owner === owner ? {...s, visible: false} : s);\n // Some renderers close before invoking their explicit action. Settle\n // dismissal at the end of that synchronous action, without a timer.\n // A newer confirmation owns a different promise and is never cleared.\n Promise.resolve().then(() => {\n if (pending.owner !== owner) return;\n pending.resolve?.(false);\n if (confirmPromiseRef.current === pending) confirmPromiseRef.current = {};\n });\n }, []);\n const runConfirmAction = useCallback((owner: number, accepted: boolean, callback?: () => unknown, wait = false) => {\n if (!mountedRef.current || owner !== confirmOwnerRef.current || confirmPromiseRef.current.owner !== owner) return;\n const pending = confirmPromiseRef.current;\n confirmPromiseRef.current = {};\n if (!wait) {\n pending.resolve?.(accepted);\n try {return callback?.();} finally {hideConfirm(owner);}\n }\n activeConfirmActionsRef.current.set(owner, pending);\n const failed = (error: unknown) => {\n activeConfirmActionsRef.current.delete(owner);\n if (owner !== confirmOwnerRef.current || !mountedRef.current) {\n pending.resolve?.(false);\n return;\n }\n confirmPromiseRef.current = pending;\n return Promise.reject(error);\n };\n try {\n return Promise.resolve(callback?.()).then(() => {\n activeConfirmActionsRef.current.delete(owner);\n pending.resolve?.(accepted);\n hideConfirm(owner);\n }, failed);\n } catch (error) {\n return failed(error);\n }\n }, [hideConfirm]);\n\n // --- ConfirmPopup ---\n const [confirmPopupState, setConfirmPopupState] = useState<IConfirmPopupProps>({visible: false});\n const hideConfirmPopup = useCallback((_result: unknown) => setConfirmPopupState(s => ({...s, visible: false})), []);\n\n // --- Dialog ---\n const [dialogState, setDialogState] = useState<IDialogState>({visible: false});\n // @ts-ignore\n const onCloseRef = useRef<(() => void) | undefined>();\n\n useEffect(() => {\n onCloseRef.current = dialogState.onClose;\n }, [dialogState.onClose]);\n\n const hideDialog = useCallback(() => {\n promptPromiseRef.current.reject?.();\n promptPromiseRef.current = {};\n setDialogState(s => ({...s, visible: false}));\n onCloseRef.current?.();\n }, []);\n\n // --- Cleanup pending promises on unmount ---\n useLayoutEffect(() => {\n mountedRef.current = true;\n const activeActions = activeConfirmActionsRef.current;\n return () => {\n mountedRef.current = false;\n confirmPromiseRef.current.reject?.();\n confirmPromiseRef.current = {};\n activeActions.forEach(pending => pending.reject?.());\n activeActions.clear();\n promptPromiseRef.current.reject?.();\n promptPromiseRef.current = {};\n };\n }, []);\n\n // --- Toast API ---\n const toast = useCallback<IToastFunction>((...a) => {\n toastRef.current?.toast(...(a as IToastParams));\n }, []);\n\n const toastDismiss = useCallback((position?: ToastPosition) => {\n toastRef.current?.dismiss?.(position);\n }, []);\n\n const toastDismissAll = useCallback(() => {\n toastRef.current?.dismissAll?.();\n }, []);\n\n // --- Confirm API ---\n const confirm = useCallback((props: IConfirmDialogProps) => {\n openConfirmation({visible: true, acceptLabel: \"Accept\", rejectLabel: \"Reject\", ...props});\n }, [openConfirmation]);\n\n const confirmPopup = useCallback((props: IConfirmPopupProps) => {\n setConfirmPopupState({visible: true, ...props});\n }, []);\n\n const dialog = useCallback(({visible = true, ...props}: IDialogState) => {\n setDialogState({visible, ...props});\n }, []);\n\n const alert = useCallback((message: React.ReactNode, opts: IConfirmDialogProps = {}) =>\n new Promise<void>(resolve => {\n openConfirmation({\n visible: true,\n header: opts.header ?? \"Alert\",\n message,\n defaultUI: true,\n acceptLabel: opts.acceptLabel ?? \"OK\",\n type: opts.type,\n icon: opts.icon,\n headless: opts.headless,\n }, {resolve: () => resolve(), reject: () => resolve()});\n }), [openConfirmation]);\n\n const confirmAsync = useCallback((opts: IConfirmDialogProps) =>\n new Promise<boolean>(resolve => {\n openConfirmation({\n visible: true,\n defaultUI: true,\n acceptLabel: opts.acceptLabel ?? \"Yes\",\n rejectLabel: opts.rejectLabel ?? \"No\",\n ...opts,\n }, {resolve, reject: () => resolve(false)});\n }), [openConfirmation]);\n\n const prompt = useCallback((\n render: (api: { resolve: (v: any) => void; reject: () => void; hide: () => void }) => React.ReactNode,\n opts: IConfirmDialogProps = {}\n ) =>\n new Promise<any>((resolve, reject) => {\n const pending = {resolve, reject};\n promptPromiseRef.current.reject?.();\n promptPromiseRef.current = pending;\n const hide = () => {\n if (promptPromiseRef.current !== pending) return;\n setDialogState(s => ({...s, visible: false}));\n promptPromiseRef.current = {};\n };\n setDialogState({\n visible: true,\n header: opts.header,\n children: render({\n resolve: (v) => {\n resolve(v);\n hide();\n },\n reject: () => {\n reject();\n hide();\n },\n hide,\n }),\n });\n }), []);\n\n // --- Stable context value ---\n const value = useMemo<Ctx>(() => ({\n confirm, confirmPopup, dialog, toast, toastDismiss, toastDismissAll, alert, confirmAsync, prompt,\n }), [confirm, confirmPopup, dialog, toast, toastDismiss, toastDismissAll, alert, confirmAsync, prompt]);\n const {owner, ...confirmationProps} = confirmState;\n\n return (\n <PopupContext.Provider value={value}>\n {children}\n <KitsToast ref={toastRef}/>\n <KitsConfirm\n key={owner}\n {...confirmationProps}\n onHide={result => {\n if (!mountedRef.current || owner !== confirmOwnerRef.current || activeConfirmActionsRef.current.has(owner) || notifiedConfirmOwnerRef.current === owner) return;\n notifiedConfirmOwnerRef.current = owner;\n hideConfirm(owner);\n confirmationProps.onHide?.(result);\n }}\n accept={() => runConfirmAction(owner, true, confirmationProps.accept, confirmationProps.async)}\n reject={() => runConfirmAction(owner, false, confirmationProps.reject, confirmationProps.async)}\n />\n <KitsDialog state={dialogState} onHide={hideDialog}/>\n {/*@ts-ignore*/}\n <KitsConfirmPopup onHide={hideConfirmPopup} {...confirmPopupState} />\n </PopupContext.Provider>\n );\n};\n\nexport const usePopup = () => useContext(PopupContext);\nexport const useDialog = usePopup; // alias\n\nexport default PopupProvider;\n"],"names":["createContext","useRef","useState","useCallback","owner","useEffect","useLayoutEffect","useMemo","jsxs","jsx","KitsToast","KitsConfirm","KitsDialog","KitsConfirmPopup","useContext"],"mappings":";;;;;;;;;;;AA8BA,MAAM,YAAA,GAAeA,oBAAmB,IAAW,CAAA;AAInD,MAAM,aAAA,GAAmD,CAAC,EAAC,QAAA,EAAQ,KAAM;AACrE,EAAA,MAAM,QAAA,GAAWC,aAAsB,IAAI,CAAA;AAG3C,EAAA,MAAM,CAAC,YAAA,EAAc,eAAe,CAAA,GAAIC,cAAA,CAA4B,EAAC,OAAA,EAAS,KAAA,EAAO,KAAA,EAAO,CAAA,EAAE,CAAA;AAC9F,EAAA,MAAM,iBAAA,GAAoBD,YAAA,CAAsB,EAAE,CAAA;AAClD,EAAA,MAAM,eAAA,GAAkBA,aAAO,CAAC,CAAA;AAChC,EAAA,MAAM,uBAAA,GAA0BA,aAAO,CAAC,CAAA;AACxC,EAAA,MAAM,uBAAA,GAA0BA,YAAA,iBAAO,IAAI,GAAA,EAA4B,CAAA;AACvE,EAAA,MAAM,gBAAA,GAAmBA,YAAA,CAAsB,EAAE,CAAA;AACjD,EAAA,MAAM,UAAA,GAAaA,aAAO,IAAI,CAAA;AAE9B,EAAA,MAAM,mBAAmBE,iBAAA,CAAY,CAAC,KAAA,EAA4B,OAAA,GAAyB,EAAC,KAAM;AAC9F,IAAA,IAAI,CAAC,WAAW,OAAA,EAAS;AAAC,MAAA,OAAA,CAAQ,UAAU,KAAK,CAAA;AAAG,MAAA;AAAA,IAAO;AAC3D,IAAA,MAAM,WAAW,iBAAA,CAAkB,OAAA;AACnC,IAAA,IAAI,QAAA,CAAS,KAAA,KAAU,MAAA,EAAW,QAAA,CAAS,UAAU,KAAK,CAAA;AAC1D,IAAA,MAAMC,MAAAA,GAAQ,EAAE,eAAA,CAAgB,OAAA;AAChC,IAAA,iBAAA,CAAkB,OAAA,GAAU,EAAC,GAAG,OAAA,EAAS,OAAAA,MAAAA,EAAK;AAC9C,IAAA,eAAA,CAAgB,EAAC,GAAG,KAAA,EAAO,KAAA,EAAAA,QAAM,CAAA;AAAA,EACrC,CAAA,EAAG,EAAE,CAAA;AAEL,EAAA,MAAM,WAAA,GAAcD,iBAAA,CAAY,CAACC,MAAAA,KAAkB;AAC/C,IAAA,IAAI,CAAC,UAAA,CAAW,OAAA,IAAWA,MAAAA,KAAU,eAAA,CAAgB,WAAW,uBAAA,CAAwB,OAAA,CAAQ,GAAA,CAAIA,MAAK,CAAA,EAAG;AAC5G,IAAA,MAAM,UAAU,iBAAA,CAAkB,OAAA;AAClC,IAAA,eAAA,CAAgB,CAAA,CAAA,KAAK,CAAA,CAAE,KAAA,KAAUA,MAAAA,GAAQ,EAAC,GAAG,CAAA,EAAG,OAAA,EAAS,KAAA,EAAK,GAAI,CAAC,CAAA;AAInE,IAAA,OAAA,CAAQ,OAAA,EAAQ,CAAE,IAAA,CAAK,MAAM;AACzB,MAAA,IAAI,OAAA,CAAQ,UAAUA,MAAAA,EAAO;AAC7B,MAAA,OAAA,CAAQ,UAAU,KAAK,CAAA;AACvB,MAAA,IAAI,iBAAA,CAAkB,OAAA,KAAY,OAAA,EAAS,iBAAA,CAAkB,UAAU,EAAC;AAAA,IAC5E,CAAC,CAAA;AAAA,EACL,CAAA,EAAG,EAAE,CAAA;AACL,EAAA,MAAM,mBAAmBD,iBAAA,CAAY,CAACC,QAAe,QAAA,EAAmB,QAAA,EAA0B,OAAO,KAAA,KAAU;AAC/G,IAAA,IAAI,CAAC,WAAW,OAAA,IAAWA,MAAAA,KAAU,gBAAgB,OAAA,IAAW,iBAAA,CAAkB,OAAA,CAAQ,KAAA,KAAUA,MAAAA,EAAO;AAC3G,IAAA,MAAM,UAAU,iBAAA,CAAkB,OAAA;AAClC,IAAA,iBAAA,CAAkB,UAAU,EAAC;AAC7B,IAAA,IAAI,CAAC,IAAA,EAAM;AACP,MAAA,OAAA,CAAQ,UAAU,QAAQ,CAAA;AAC1B,MAAA,IAAI;AAAC,QAAA,OAAO,QAAA,IAAW;AAAA,MAAE,CAAA,SAAE;AAAS,QAAA,WAAA,CAAYA,MAAK,CAAA;AAAA,MAAE;AAAA,IAC3D;AACA,IAAA,uBAAA,CAAwB,OAAA,CAAQ,GAAA,CAAIA,MAAAA,EAAO,OAAO,CAAA;AAClD,IAAA,MAAM,MAAA,GAAS,CAAC,KAAA,KAAmB;AAC/B,MAAA,uBAAA,CAAwB,OAAA,CAAQ,OAAOA,MAAK,CAAA;AAC5C,MAAA,IAAIA,MAAAA,KAAU,eAAA,CAAgB,OAAA,IAAW,CAAC,WAAW,OAAA,EAAS;AAC1D,QAAA,OAAA,CAAQ,UAAU,KAAK,CAAA;AACvB,QAAA;AAAA,MACJ;AACA,MAAA,iBAAA,CAAkB,OAAA,GAAU,OAAA;AAC5B,MAAA,OAAO,OAAA,CAAQ,OAAO,KAAK,CAAA;AAAA,IAC/B,CAAA;AACA,IAAA,IAAI;AACA,MAAA,OAAO,QAAQ,OAAA,CAAQ,QAAA,IAAY,CAAA,CAAE,KAAK,MAAM;AAC5C,QAAA,uBAAA,CAAwB,OAAA,CAAQ,OAAOA,MAAK,CAAA;AAC5C,QAAA,OAAA,CAAQ,UAAU,QAAQ,CAAA;AAC1B,QAAA,WAAA,CAAYA,MAAK,CAAA;AAAA,MACrB,GAAG,MAAM,CAAA;AAAA,IACb,SAAS,KAAA,EAAO;AACZ,MAAA,OAAO,OAAO,KAAK,CAAA;AAAA,IACvB;AAAA,EACJ,CAAA,EAAG,CAAC,WAAW,CAAC,CAAA;AAGhB,EAAA,MAAM,CAAC,mBAAmB,oBAAoB,CAAA,GAAIF,eAA6B,EAAC,OAAA,EAAS,OAAM,CAAA;AAC/F,EAAA,MAAM,gBAAA,GAAmBC,iBAAA,CAAY,CAAC,OAAA,KAAqB,qBAAqB,CAAA,CAAA,MAAM,EAAC,GAAG,CAAA,EAAG,OAAA,EAAS,KAAA,EAAK,CAAE,CAAA,EAAG,EAAE,CAAA;AAGlH,EAAA,MAAM,CAAC,aAAa,cAAc,CAAA,GAAID,eAAuB,EAAC,OAAA,EAAS,OAAM,CAAA;AAE7E,EAAA,MAAM,aAAaD,YAAA,EAAiC;AAEpD,EAAAI,eAAA,CAAU,MAAM;AACZ,IAAA,UAAA,CAAW,UAAU,WAAA,CAAY,OAAA;AAAA,EACrC,CAAA,EAAG,CAAC,WAAA,CAAY,OAAO,CAAC,CAAA;AAExB,EAAA,MAAM,UAAA,GAAaF,kBAAY,MAAM;AACjC,IAAA,gBAAA,CAAiB,QAAQ,MAAA,IAAS;AAClC,IAAA,gBAAA,CAAiB,UAAU,EAAC;AAC5B,IAAA,cAAA,CAAe,QAAM,EAAC,GAAG,CAAA,EAAG,OAAA,EAAS,OAAK,CAAE,CAAA;AAC5C,IAAA,UAAA,CAAW,OAAA,IAAU;AAAA,EACzB,CAAA,EAAG,EAAE,CAAA;AAGL,EAAAG,qBAAA,CAAgB,MAAM;AAClB,IAAA,UAAA,CAAW,OAAA,GAAU,IAAA;AACrB,IAAA,MAAM,gBAAgB,uBAAA,CAAwB,OAAA;AAC9C,IAAA,OAAO,MAAM;AACT,MAAA,UAAA,CAAW,OAAA,GAAU,KAAA;AACrB,MAAA,iBAAA,CAAkB,QAAQ,MAAA,IAAS;AACnC,MAAA,iBAAA,CAAkB,UAAU,EAAC;AAC7B,MAAA,aAAA,CAAc,OAAA,CAAQ,CAAA,OAAA,KAAW,OAAA,CAAQ,MAAA,IAAU,CAAA;AACnD,MAAA,aAAA,CAAc,KAAA,EAAM;AACpB,MAAA,gBAAA,CAAiB,QAAQ,MAAA,IAAS;AAClC,MAAA,gBAAA,CAAiB,UAAU,EAAC;AAAA,IAChC,CAAA;AAAA,EACJ,CAAA,EAAG,EAAE,CAAA;AAGL,EAAA,MAAM,KAAA,GAAQH,iBAAA,CAA4B,CAAA,GAAI,CAAA,KAAM;AAChD,IAAA,QAAA,CAAS,OAAA,EAAS,KAAA,CAAM,GAAI,CAAkB,CAAA;AAAA,EAClD,CAAA,EAAG,EAAE,CAAA;AAEL,EAAA,MAAM,YAAA,GAAeA,iBAAA,CAAY,CAAC,QAAA,KAA6B;AAC3D,IAAA,QAAA,CAAS,OAAA,EAAS,UAAU,QAAQ,CAAA;AAAA,EACxC,CAAA,EAAG,EAAE,CAAA;AAEL,EAAA,MAAM,eAAA,GAAkBA,kBAAY,MAAM;AACtC,IAAA,QAAA,CAAS,SAAS,UAAA,IAAa;AAAA,EACnC,CAAA,EAAG,EAAE,CAAA;AAGL,EAAA,MAAM,OAAA,GAAUA,iBAAA,CAAY,CAAC,KAAA,KAA+B;AACxD,IAAA,gBAAA,CAAiB,EAAC,SAAS,IAAA,EAAM,WAAA,EAAa,UAAU,WAAA,EAAa,QAAA,EAAU,GAAG,KAAA,EAAM,CAAA;AAAA,EAC5F,CAAA,EAAG,CAAC,gBAAgB,CAAC,CAAA;AAErB,EAAA,MAAM,YAAA,GAAeA,iBAAA,CAAY,CAAC,KAAA,KAA8B;AAC5D,IAAA,oBAAA,CAAqB,EAAC,OAAA,EAAS,IAAA,EAAM,GAAG,OAAM,CAAA;AAAA,EAClD,CAAA,EAAG,EAAE,CAAA;AAEL,EAAA,MAAM,MAAA,GAASA,kBAAY,CAAC,EAAC,UAAU,IAAA,EAAM,GAAG,OAAK,KAAoB;AACrE,IAAA,cAAA,CAAe,EAAC,OAAA,EAAS,GAAG,KAAA,EAAM,CAAA;AAAA,EACtC,CAAA,EAAG,EAAE,CAAA;AAEL,EAAA,MAAM,KAAA,GAAQA,kBAAY,CAAC,OAAA,EAA0B,OAA4B,EAAC,KAC9E,IAAI,OAAA,CAAc,CAAA,OAAA,KAAW;AACzB,IAAA,gBAAA,CAAiB;AAAA,MACb,OAAA,EAAS,IAAA;AAAA,MACT,MAAA,EAAQ,KAAK,MAAA,IAAU,OAAA;AAAA,MACvB,OAAA;AAAA,MACA,SAAA,EAAW,IAAA;AAAA,MACX,WAAA,EAAa,KAAK,WAAA,IAAe,IAAA;AAAA,MACjC,MAAM,IAAA,CAAK,IAAA;AAAA,MACX,MAAM,IAAA,CAAK,IAAA;AAAA,MACX,UAAU,IAAA,CAAK;AAAA,KACnB,EAAG,EAAC,OAAA,EAAS,MAAM,OAAA,IAAW,MAAA,EAAQ,MAAM,OAAA,EAAQ,EAAE,CAAA;AAAA,EAC1D,CAAC,CAAA,EAAG,CAAC,gBAAgB,CAAC,CAAA;AAE1B,EAAA,MAAM,eAAeA,iBAAA,CAAY,CAAC,IAAA,KAC9B,IAAI,QAAiB,CAAA,OAAA,KAAW;AAC5B,IAAA,gBAAA,CAAiB;AAAA,MACb,OAAA,EAAS,IAAA;AAAA,MACT,SAAA,EAAW,IAAA;AAAA,MACX,WAAA,EAAa,KAAK,WAAA,IAAe,KAAA;AAAA,MACjC,WAAA,EAAa,KAAK,WAAA,IAAe,IAAA;AAAA,MACjC,GAAG;AAAA,KACP,EAAG,EAAC,OAAA,EAAS,MAAA,EAAQ,MAAM,OAAA,CAAQ,KAAK,GAAE,CAAA;AAAA,EAC9C,CAAC,CAAA,EAAG,CAAC,gBAAgB,CAAC,CAAA;AAE1B,EAAA,MAAM,MAAA,GAASA,iBAAA,CAAY,CACvB,MAAA,EACA,IAAA,GAA4B,EAAC,KAE7B,IAAI,OAAA,CAAa,CAAC,OAAA,EAAS,MAAA,KAAW;AAClC,IAAA,MAAM,OAAA,GAAU,EAAC,OAAA,EAAS,MAAA,EAAM;AAChC,IAAA,gBAAA,CAAiB,QAAQ,MAAA,IAAS;AAClC,IAAA,gBAAA,CAAiB,OAAA,GAAU,OAAA;AAC3B,IAAA,MAAM,OAAO,MAAM;AACf,MAAA,IAAI,gBAAA,CAAiB,YAAY,OAAA,EAAS;AAC1C,MAAA,cAAA,CAAe,QAAM,EAAC,GAAG,CAAA,EAAG,OAAA,EAAS,OAAK,CAAE,CAAA;AAC5C,MAAA,gBAAA,CAAiB,UAAU,EAAC;AAAA,IAChC,CAAA;AACA,IAAA,cAAA,CAAe;AAAA,MACX,OAAA,EAAS,IAAA;AAAA,MACT,QAAQ,IAAA,CAAK,MAAA;AAAA,MACb,UAAU,MAAA,CAAO;AAAA,QACb,OAAA,EAAS,CAAC,CAAA,KAAM;AACZ,UAAA,OAAA,CAAQ,CAAC,CAAA;AACT,UAAA,IAAA,EAAK;AAAA,QACT,CAAA;AAAA,QACA,QAAQ,MAAM;AACV,UAAA,MAAA,EAAO;AACP,UAAA,IAAA,EAAK;AAAA,QACT,CAAA;AAAA,QACA;AAAA,OACH;AAAA,KACJ,CAAA;AAAA,EACL,CAAC,CAAA,EAAG,EAAE,CAAA;AAGV,EAAA,MAAM,KAAA,GAAQI,cAAa,OAAO;AAAA,IAC9B,OAAA;AAAA,IAAS,YAAA;AAAA,IAAc,MAAA;AAAA,IAAQ,KAAA;AAAA,IAAO,YAAA;AAAA,IAAc,eAAA;AAAA,IAAiB,KAAA;AAAA,IAAO,YAAA;AAAA,IAAc;AAAA,GAC9F,CAAA,EAAI,CAAC,OAAA,EAAS,YAAA,EAAc,MAAA,EAAQ,KAAA,EAAO,YAAA,EAAc,eAAA,EAAiB,KAAA,EAAO,YAAA,EAAc,MAAM,CAAC,CAAA;AACtG,EAAA,MAAM,EAAC,KAAA,EAAO,GAAG,iBAAA,EAAiB,GAAI,YAAA;AAEtC,EAAA,uBACIC,eAAA,CAAC,YAAA,CAAa,QAAA,EAAb,EAAsB,KAAA,EAClB,QAAA,EAAA;AAAA,IAAA,QAAA;AAAA,oBACDC,cAAA,CAACC,oBAAA,EAAA,EAAU,GAAA,EAAK,QAAA,EAAS,CAAA;AAAA,oBACzBD,cAAA;AAAA,MAACE,sBAAA;AAAA,MAAA;AAAA,QAEI,GAAG,iBAAA;AAAA,QACJ,QAAQ,CAAA,MAAA,KAAU;AACd,UAAA,IAAI,CAAC,UAAA,CAAW,OAAA,IAAW,KAAA,KAAU,eAAA,CAAgB,OAAA,IAAW,uBAAA,CAAwB,OAAA,CAAQ,GAAA,CAAI,KAAK,CAAA,IAAK,uBAAA,CAAwB,YAAY,KAAA,EAAO;AACzJ,UAAA,uBAAA,CAAwB,OAAA,GAAU,KAAA;AAClC,UAAA,WAAA,CAAY,KAAK,CAAA;AACjB,UAAA,iBAAA,CAAkB,SAAS,MAAM,CAAA;AAAA,QACrC,CAAA;AAAA,QACA,MAAA,EAAQ,MAAM,gBAAA,CAAiB,KAAA,EAAO,MAAM,iBAAA,CAAkB,MAAA,EAAQ,kBAAkB,KAAK,CAAA;AAAA,QAC7F,MAAA,EAAQ,MAAM,gBAAA,CAAiB,KAAA,EAAO,OAAO,iBAAA,CAAkB,MAAA,EAAQ,kBAAkB,KAAK;AAAA,OAAA;AAAA,MATzF;AAAA,KAUT;AAAA,oBACAF,cAAA,CAACG,sBAAA,EAAA,EAAW,KAAA,EAAO,WAAA,EAAa,QAAQ,UAAA,EAAW,CAAA;AAAA,oBAEnDH,cAAA,CAACI,sBAAA,EAAA,EAAiB,MAAA,EAAQ,gBAAA,EAAmB,GAAG,iBAAA,EAAmB;AAAA,GAAA,EACvE,CAAA;AAER;AAEO,MAAM,QAAA,GAAW,MAAMC,gBAAA,CAAW,YAAY;AAC9C,MAAM,SAAA,GAAY;;;;;;"}
@@ -1,5 +1,5 @@
1
1
  import { jsxs, jsx } from 'react/jsx-runtime';
2
- import { createContext, useRef, useState, useCallback, useEffect, useMemo, useContext } from 'react';
2
+ import { createContext, useRef, useState, useCallback, useEffect, useLayoutEffect, useMemo, useContext } from 'react';
3
3
  import KitsToast from '../components/overlay/Toast/index.js';
4
4
  import KitsConfirm from '../components/overlay/ConfirmDialog/index.js';
5
5
  import KitsDialogControlled from '../components/overlay/Dialog/index.js';
@@ -8,34 +8,90 @@ import KitsConfirmPopup from '../components/overlay/ConfirmPopup/index.js';
8
8
  const PopupContext = createContext(null);
9
9
  const PopupProvider = ({ children }) => {
10
10
  const toastRef = useRef(null);
11
- const [confirmState, setConfirmState] = useState({ visible: false });
11
+ const [confirmState, setConfirmState] = useState({ visible: false, owner: 0 });
12
12
  const confirmPromiseRef = useRef({});
13
- const hideConfirm = useCallback(() => setConfirmState((s) => ({ ...s, visible: false })), []);
14
- const doAccept = useCallback(() => {
15
- confirmPromiseRef.current.resolve?.(true);
16
- confirmPromiseRef.current = {};
17
- hideConfirm();
18
- }, [hideConfirm]);
19
- const doReject = useCallback(() => {
20
- confirmPromiseRef.current.resolve?.(false);
13
+ const confirmOwnerRef = useRef(0);
14
+ const notifiedConfirmOwnerRef = useRef(0);
15
+ const activeConfirmActionsRef = useRef(/* @__PURE__ */ new Map());
16
+ const promptPromiseRef = useRef({});
17
+ const mountedRef = useRef(true);
18
+ const openConfirmation = useCallback((props, pending = {}) => {
19
+ if (!mountedRef.current) {
20
+ pending.resolve?.(false);
21
+ return;
22
+ }
23
+ const previous = confirmPromiseRef.current;
24
+ if (previous.owner !== void 0) previous.resolve?.(false);
25
+ const owner2 = ++confirmOwnerRef.current;
26
+ confirmPromiseRef.current = { ...pending, owner: owner2 };
27
+ setConfirmState({ ...props, owner: owner2 });
28
+ }, []);
29
+ const hideConfirm = useCallback((owner2) => {
30
+ if (!mountedRef.current || owner2 !== confirmOwnerRef.current || activeConfirmActionsRef.current.has(owner2)) return;
31
+ const pending = confirmPromiseRef.current;
32
+ setConfirmState((s) => s.owner === owner2 ? { ...s, visible: false } : s);
33
+ Promise.resolve().then(() => {
34
+ if (pending.owner !== owner2) return;
35
+ pending.resolve?.(false);
36
+ if (confirmPromiseRef.current === pending) confirmPromiseRef.current = {};
37
+ });
38
+ }, []);
39
+ const runConfirmAction = useCallback((owner2, accepted, callback, wait = false) => {
40
+ if (!mountedRef.current || owner2 !== confirmOwnerRef.current || confirmPromiseRef.current.owner !== owner2) return;
41
+ const pending = confirmPromiseRef.current;
21
42
  confirmPromiseRef.current = {};
22
- hideConfirm();
43
+ if (!wait) {
44
+ pending.resolve?.(accepted);
45
+ try {
46
+ return callback?.();
47
+ } finally {
48
+ hideConfirm(owner2);
49
+ }
50
+ }
51
+ activeConfirmActionsRef.current.set(owner2, pending);
52
+ const failed = (error) => {
53
+ activeConfirmActionsRef.current.delete(owner2);
54
+ if (owner2 !== confirmOwnerRef.current || !mountedRef.current) {
55
+ pending.resolve?.(false);
56
+ return;
57
+ }
58
+ confirmPromiseRef.current = pending;
59
+ return Promise.reject(error);
60
+ };
61
+ try {
62
+ return Promise.resolve(callback?.()).then(() => {
63
+ activeConfirmActionsRef.current.delete(owner2);
64
+ pending.resolve?.(accepted);
65
+ hideConfirm(owner2);
66
+ }, failed);
67
+ } catch (error) {
68
+ return failed(error);
69
+ }
23
70
  }, [hideConfirm]);
24
71
  const [confirmPopupState, setConfirmPopupState] = useState({ visible: false });
25
- const hideConfirmPopup = useCallback((result) => setConfirmPopupState((s) => ({ ...s, visible: false })), []);
72
+ const hideConfirmPopup = useCallback((_result) => setConfirmPopupState((s) => ({ ...s, visible: false })), []);
26
73
  const [dialogState, setDialogState] = useState({ visible: false });
27
74
  const onCloseRef = useRef();
28
75
  useEffect(() => {
29
76
  onCloseRef.current = dialogState.onClose;
30
77
  }, [dialogState.onClose]);
31
78
  const hideDialog = useCallback(() => {
79
+ promptPromiseRef.current.reject?.();
80
+ promptPromiseRef.current = {};
32
81
  setDialogState((s) => ({ ...s, visible: false }));
33
82
  onCloseRef.current?.();
34
83
  }, []);
35
- useEffect(() => {
84
+ useLayoutEffect(() => {
85
+ mountedRef.current = true;
86
+ const activeActions = activeConfirmActionsRef.current;
36
87
  return () => {
88
+ mountedRef.current = false;
37
89
  confirmPromiseRef.current.reject?.();
38
90
  confirmPromiseRef.current = {};
91
+ activeActions.forEach((pending) => pending.reject?.());
92
+ activeActions.clear();
93
+ promptPromiseRef.current.reject?.();
94
+ promptPromiseRef.current = {};
39
95
  };
40
96
  }, []);
41
97
  const toast = useCallback((...a) => {
@@ -48,8 +104,8 @@ const PopupProvider = ({ children }) => {
48
104
  toastRef.current?.dismissAll?.();
49
105
  }, []);
50
106
  const confirm = useCallback((props) => {
51
- setConfirmState({ visible: true, acceptLabel: "Accept", rejectLabel: "Reject", ...props });
52
- }, []);
107
+ openConfirmation({ visible: true, acceptLabel: "Accept", rejectLabel: "Reject", ...props });
108
+ }, [openConfirmation]);
53
109
  const confirmPopup = useCallback((props) => {
54
110
  setConfirmPopupState({ visible: true, ...props });
55
111
  }, []);
@@ -57,8 +113,7 @@ const PopupProvider = ({ children }) => {
57
113
  setDialogState({ visible, ...props });
58
114
  }, []);
59
115
  const alert = useCallback((message, opts = {}) => new Promise((resolve) => {
60
- confirmPromiseRef.current = { resolve: () => resolve() };
61
- setConfirmState({
116
+ openConfirmation({
62
117
  visible: true,
63
118
  header: opts.header ?? "Alert",
64
119
  message,
@@ -67,23 +122,25 @@ const PopupProvider = ({ children }) => {
67
122
  type: opts.type,
68
123
  icon: opts.icon,
69
124
  headless: opts.headless
70
- });
71
- }), []);
125
+ }, { resolve: () => resolve(), reject: () => resolve() });
126
+ }), [openConfirmation]);
72
127
  const confirmAsync = useCallback((opts) => new Promise((resolve) => {
73
- confirmPromiseRef.current = { resolve };
74
- setConfirmState({
128
+ openConfirmation({
75
129
  visible: true,
76
130
  defaultUI: true,
77
131
  acceptLabel: opts.acceptLabel ?? "Yes",
78
132
  rejectLabel: opts.rejectLabel ?? "No",
79
133
  ...opts
80
- });
81
- }), []);
134
+ }, { resolve, reject: () => resolve(false) });
135
+ }), [openConfirmation]);
82
136
  const prompt = useCallback((render, opts = {}) => new Promise((resolve, reject) => {
83
- confirmPromiseRef.current = { resolve, reject };
137
+ const pending = { resolve, reject };
138
+ promptPromiseRef.current.reject?.();
139
+ promptPromiseRef.current = pending;
84
140
  const hide = () => {
141
+ if (promptPromiseRef.current !== pending) return;
85
142
  setDialogState((s) => ({ ...s, visible: false }));
86
- confirmPromiseRef.current = {};
143
+ promptPromiseRef.current = {};
87
144
  };
88
145
  setDialogState({
89
146
  visible: true,
@@ -112,10 +169,25 @@ const PopupProvider = ({ children }) => {
112
169
  confirmAsync,
113
170
  prompt
114
171
  }), [confirm, confirmPopup, dialog, toast, toastDismiss, toastDismissAll, alert, confirmAsync, prompt]);
172
+ const { owner, ...confirmationProps } = confirmState;
115
173
  return /* @__PURE__ */ jsxs(PopupContext.Provider, { value, children: [
116
174
  children,
117
175
  /* @__PURE__ */ jsx(KitsToast, { ref: toastRef }),
118
- /* @__PURE__ */ jsx(KitsConfirm, { onHide: hideConfirm, accept: doAccept, reject: doReject, ...confirmState }),
176
+ /* @__PURE__ */ jsx(
177
+ KitsConfirm,
178
+ {
179
+ ...confirmationProps,
180
+ onHide: (result) => {
181
+ if (!mountedRef.current || owner !== confirmOwnerRef.current || activeConfirmActionsRef.current.has(owner) || notifiedConfirmOwnerRef.current === owner) return;
182
+ notifiedConfirmOwnerRef.current = owner;
183
+ hideConfirm(owner);
184
+ confirmationProps.onHide?.(result);
185
+ },
186
+ accept: () => runConfirmAction(owner, true, confirmationProps.accept, confirmationProps.async),
187
+ reject: () => runConfirmAction(owner, false, confirmationProps.reject, confirmationProps.async)
188
+ },
189
+ owner
190
+ ),
119
191
  /* @__PURE__ */ jsx(KitsDialogControlled, { state: dialogState, onHide: hideDialog }),
120
192
  /* @__PURE__ */ jsx(KitsConfirmPopup, { onHide: hideConfirmPopup, ...confirmPopupState })
121
193
  ] });
@@ -1 +1 @@
1
- {"version":3,"file":"DialogContext.js","sources":["../../../src/contexts/DialogContext.tsx"],"sourcesContent":["import React, {createContext, useCallback, useContext, useEffect, useMemo, useRef, useState} from \"react\";\nimport KitsToast from \"../components/overlay/Toast\";\nimport KitsConfirm from \"../components/overlay/ConfirmDialog\";\nimport KitsDialog from \"../components/overlay/Dialog\";\nimport KitsConfirmPopup from \"../components/overlay/ConfirmPopup\";\nimport type {\n IConfirmDialogProps,\n IConfirmPopupProps,\n IDialogState,\n IKitsToastRef,\n IToastFunction,\n IToastParams,\n ToastPosition,\n} from \"@lmb-it/kitsconcerto-types\";\n\ninterface Ctx {\n confirm: (props: IConfirmDialogProps) => void;\n confirmPopup: (props: IConfirmPopupProps) => void;\n dialog: (props: IDialogState) => void;\n toast: IToastFunction;\n toastDismiss: (position?: ToastPosition) => void;\n toastDismissAll: () => void;\n alert: (message: React.ReactNode, opts?: IConfirmDialogProps) => Promise<void>;\n confirmAsync: (opts: IConfirmDialogProps) => Promise<boolean>;\n prompt: (\n render: (api: { resolve: (v: any) => void; reject: () => void; hide: () => void }) => React.ReactNode,\n opts?: IConfirmDialogProps\n ) => Promise<any>;\n}\n\nconst PopupContext = createContext<Ctx>(null as any);\n\nconst PopupProvider: React.FC<React.PropsWithChildren> = ({children}) => {\n const toastRef = useRef<IKitsToastRef>(null);\n\n // --- Confirm ---\n const [confirmState, setConfirmState] = useState<IConfirmDialogProps>({visible: false});\n const confirmPromiseRef = useRef<{ resolve?: (v: any) => void; reject?: (r?: any) => void }>({});\n\n const hideConfirm = useCallback(() => setConfirmState(s => ({...s, visible: false})), []);\n const doAccept = useCallback(() => {\n confirmPromiseRef.current.resolve?.(true);\n confirmPromiseRef.current = {};\n hideConfirm();\n }, [hideConfirm]);\n const doReject = useCallback(() => {\n confirmPromiseRef.current.resolve?.(false);\n confirmPromiseRef.current = {};\n hideConfirm();\n }, [hideConfirm]);\n\n // --- ConfirmPopup ---\n const [confirmPopupState, setConfirmPopupState] = useState<IConfirmPopupProps>({visible: false});\n const hideConfirmPopup = useCallback((result) => setConfirmPopupState(s => ({...s, visible: false})), []);\n\n // --- Dialog ---\n const [dialogState, setDialogState] = useState<IDialogState>({visible: false});\n // @ts-ignore\n const onCloseRef = useRef<(() => void) | undefined>();\n\n useEffect(() => {\n onCloseRef.current = dialogState.onClose;\n }, [dialogState.onClose]);\n\n const hideDialog = useCallback(() => {\n setDialogState(s => ({...s, visible: false}));\n onCloseRef.current?.();\n }, []);\n\n // --- Cleanup pending promises on unmount ---\n useEffect(() => {\n return () => {\n confirmPromiseRef.current.reject?.();\n confirmPromiseRef.current = {};\n };\n }, []);\n\n // --- Toast API ---\n const toast = useCallback<IToastFunction>((...a) => {\n toastRef.current?.toast(...(a as IToastParams));\n }, []);\n\n const toastDismiss = useCallback((position?: ToastPosition) => {\n toastRef.current?.dismiss?.(position);\n }, []);\n\n const toastDismissAll = useCallback(() => {\n toastRef.current?.dismissAll?.();\n }, []);\n\n // --- Confirm API ---\n const confirm = useCallback((props: IConfirmDialogProps) => {\n setConfirmState({visible: true, acceptLabel: \"Accept\", rejectLabel: \"Reject\", ...props});\n }, []);\n\n const confirmPopup = useCallback((props: IConfirmPopupProps) => {\n setConfirmPopupState({visible: true, ...props});\n }, []);\n\n const dialog = useCallback(({visible = true, ...props}: IDialogState) => {\n setDialogState({visible, ...props});\n }, []);\n\n const alert = useCallback((message: React.ReactNode, opts: IConfirmDialogProps = {}) =>\n new Promise<void>(resolve => {\n confirmPromiseRef.current = {resolve: () => resolve()};\n setConfirmState({\n visible: true,\n header: opts.header ?? \"Alert\",\n message,\n defaultUI: true,\n acceptLabel: opts.acceptLabel ?? \"OK\",\n type: opts.type,\n icon: opts.icon,\n headless: opts.headless,\n });\n }), []);\n\n const confirmAsync = useCallback((opts: IConfirmDialogProps) =>\n new Promise<boolean>(resolve => {\n confirmPromiseRef.current = {resolve};\n setConfirmState({\n visible: true,\n defaultUI: true,\n acceptLabel: opts.acceptLabel ?? \"Yes\",\n rejectLabel: opts.rejectLabel ?? \"No\",\n ...opts,\n });\n }), []);\n\n const prompt = useCallback((\n render: (api: { resolve: (v: any) => void; reject: () => void; hide: () => void }) => React.ReactNode,\n opts: IConfirmDialogProps = {}\n ) =>\n new Promise<any>((resolve, reject) => {\n confirmPromiseRef.current = {resolve, reject};\n const hide = () => {\n setDialogState(s => ({...s, visible: false}));\n confirmPromiseRef.current = {};\n };\n setDialogState({\n visible: true,\n header: opts.header,\n children: render({\n resolve: (v) => {\n resolve(v);\n hide();\n },\n reject: () => {\n reject();\n hide();\n },\n hide,\n }),\n });\n }), []);\n\n // --- Stable context value ---\n const value = useMemo<Ctx>(() => ({\n confirm, confirmPopup, dialog, toast, toastDismiss, toastDismissAll, alert, confirmAsync, prompt,\n }), [confirm, confirmPopup, dialog, toast, toastDismiss, toastDismissAll, alert, confirmAsync, prompt]);\n\n return (\n <PopupContext.Provider value={value}>\n {children}\n <KitsToast ref={toastRef}/>\n <KitsConfirm onHide={hideConfirm} accept={doAccept} reject={doReject} {...confirmState} />\n <KitsDialog state={dialogState} onHide={hideDialog}/>\n {/*@ts-ignore*/}\n <KitsConfirmPopup onHide={hideConfirmPopup} {...confirmPopupState} />\n </PopupContext.Provider>\n );\n};\n\nexport const usePopup = () => useContext(PopupContext);\nexport const useDialog = usePopup; // alias\n\nexport default PopupProvider;\n"],"names":["KitsDialog"],"mappings":"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"}
1
+ {"version":3,"file":"DialogContext.js","sources":["../../../src/contexts/DialogContext.tsx"],"sourcesContent":["import React, {createContext, useCallback, useContext, useEffect, useLayoutEffect, useMemo, useRef, useState} from \"react\";\nimport KitsToast from \"../components/overlay/Toast\";\nimport KitsConfirm from \"../components/overlay/ConfirmDialog\";\nimport KitsDialog from \"../components/overlay/Dialog\";\nimport KitsConfirmPopup from \"../components/overlay/ConfirmPopup\";\nimport type {\n IConfirmDialogProps,\n IConfirmPopupProps,\n IDialogState,\n IKitsToastRef,\n IToastFunction,\n IToastParams,\n ToastPosition,\n} from \"@lmb-it/kitsconcerto-types\";\n\ninterface Ctx {\n confirm: (props: IConfirmDialogProps) => void;\n confirmPopup: (props: IConfirmPopupProps) => void;\n dialog: (props: IDialogState) => void;\n toast: IToastFunction;\n toastDismiss: (position?: ToastPosition) => void;\n toastDismissAll: () => void;\n alert: (message: React.ReactNode, opts?: IConfirmDialogProps) => Promise<void>;\n confirmAsync: (opts: IConfirmDialogProps) => Promise<boolean>;\n prompt: (\n render: (api: { resolve: (v: any) => void; reject: () => void; hide: () => void }) => React.ReactNode,\n opts?: IConfirmDialogProps\n ) => Promise<any>;\n}\n\nconst PopupContext = createContext<Ctx>(null as any);\ntype PendingDialog = {resolve?: (v: any) => void; reject?: (r?: any) => void; owner?: number};\ntype OwnedConfirmation = IConfirmDialogProps & {owner: number};\n\nconst PopupProvider: React.FC<React.PropsWithChildren> = ({children}) => {\n const toastRef = useRef<IKitsToastRef>(null);\n\n // --- Confirm ---\n const [confirmState, setConfirmState] = useState<OwnedConfirmation>({visible: false, owner: 0});\n const confirmPromiseRef = useRef<PendingDialog>({});\n const confirmOwnerRef = useRef(0);\n const notifiedConfirmOwnerRef = useRef(0);\n const activeConfirmActionsRef = useRef(new Map<number, PendingDialog>());\n const promptPromiseRef = useRef<PendingDialog>({});\n const mountedRef = useRef(true);\n\n const openConfirmation = useCallback((props: IConfirmDialogProps, pending: PendingDialog = {}) => {\n if (!mountedRef.current) {pending.resolve?.(false); return;}\n const previous = confirmPromiseRef.current;\n if (previous.owner !== undefined) previous.resolve?.(false);\n const owner = ++confirmOwnerRef.current;\n confirmPromiseRef.current = {...pending, owner};\n setConfirmState({...props, owner});\n }, []);\n\n const hideConfirm = useCallback((owner: number) => {\n if (!mountedRef.current || owner !== confirmOwnerRef.current || activeConfirmActionsRef.current.has(owner)) return;\n const pending = confirmPromiseRef.current;\n setConfirmState(s => s.owner === owner ? {...s, visible: false} : s);\n // Some renderers close before invoking their explicit action. Settle\n // dismissal at the end of that synchronous action, without a timer.\n // A newer confirmation owns a different promise and is never cleared.\n Promise.resolve().then(() => {\n if (pending.owner !== owner) return;\n pending.resolve?.(false);\n if (confirmPromiseRef.current === pending) confirmPromiseRef.current = {};\n });\n }, []);\n const runConfirmAction = useCallback((owner: number, accepted: boolean, callback?: () => unknown, wait = false) => {\n if (!mountedRef.current || owner !== confirmOwnerRef.current || confirmPromiseRef.current.owner !== owner) return;\n const pending = confirmPromiseRef.current;\n confirmPromiseRef.current = {};\n if (!wait) {\n pending.resolve?.(accepted);\n try {return callback?.();} finally {hideConfirm(owner);}\n }\n activeConfirmActionsRef.current.set(owner, pending);\n const failed = (error: unknown) => {\n activeConfirmActionsRef.current.delete(owner);\n if (owner !== confirmOwnerRef.current || !mountedRef.current) {\n pending.resolve?.(false);\n return;\n }\n confirmPromiseRef.current = pending;\n return Promise.reject(error);\n };\n try {\n return Promise.resolve(callback?.()).then(() => {\n activeConfirmActionsRef.current.delete(owner);\n pending.resolve?.(accepted);\n hideConfirm(owner);\n }, failed);\n } catch (error) {\n return failed(error);\n }\n }, [hideConfirm]);\n\n // --- ConfirmPopup ---\n const [confirmPopupState, setConfirmPopupState] = useState<IConfirmPopupProps>({visible: false});\n const hideConfirmPopup = useCallback((_result: unknown) => setConfirmPopupState(s => ({...s, visible: false})), []);\n\n // --- Dialog ---\n const [dialogState, setDialogState] = useState<IDialogState>({visible: false});\n // @ts-ignore\n const onCloseRef = useRef<(() => void) | undefined>();\n\n useEffect(() => {\n onCloseRef.current = dialogState.onClose;\n }, [dialogState.onClose]);\n\n const hideDialog = useCallback(() => {\n promptPromiseRef.current.reject?.();\n promptPromiseRef.current = {};\n setDialogState(s => ({...s, visible: false}));\n onCloseRef.current?.();\n }, []);\n\n // --- Cleanup pending promises on unmount ---\n useLayoutEffect(() => {\n mountedRef.current = true;\n const activeActions = activeConfirmActionsRef.current;\n return () => {\n mountedRef.current = false;\n confirmPromiseRef.current.reject?.();\n confirmPromiseRef.current = {};\n activeActions.forEach(pending => pending.reject?.());\n activeActions.clear();\n promptPromiseRef.current.reject?.();\n promptPromiseRef.current = {};\n };\n }, []);\n\n // --- Toast API ---\n const toast = useCallback<IToastFunction>((...a) => {\n toastRef.current?.toast(...(a as IToastParams));\n }, []);\n\n const toastDismiss = useCallback((position?: ToastPosition) => {\n toastRef.current?.dismiss?.(position);\n }, []);\n\n const toastDismissAll = useCallback(() => {\n toastRef.current?.dismissAll?.();\n }, []);\n\n // --- Confirm API ---\n const confirm = useCallback((props: IConfirmDialogProps) => {\n openConfirmation({visible: true, acceptLabel: \"Accept\", rejectLabel: \"Reject\", ...props});\n }, [openConfirmation]);\n\n const confirmPopup = useCallback((props: IConfirmPopupProps) => {\n setConfirmPopupState({visible: true, ...props});\n }, []);\n\n const dialog = useCallback(({visible = true, ...props}: IDialogState) => {\n setDialogState({visible, ...props});\n }, []);\n\n const alert = useCallback((message: React.ReactNode, opts: IConfirmDialogProps = {}) =>\n new Promise<void>(resolve => {\n openConfirmation({\n visible: true,\n header: opts.header ?? \"Alert\",\n message,\n defaultUI: true,\n acceptLabel: opts.acceptLabel ?? \"OK\",\n type: opts.type,\n icon: opts.icon,\n headless: opts.headless,\n }, {resolve: () => resolve(), reject: () => resolve()});\n }), [openConfirmation]);\n\n const confirmAsync = useCallback((opts: IConfirmDialogProps) =>\n new Promise<boolean>(resolve => {\n openConfirmation({\n visible: true,\n defaultUI: true,\n acceptLabel: opts.acceptLabel ?? \"Yes\",\n rejectLabel: opts.rejectLabel ?? \"No\",\n ...opts,\n }, {resolve, reject: () => resolve(false)});\n }), [openConfirmation]);\n\n const prompt = useCallback((\n render: (api: { resolve: (v: any) => void; reject: () => void; hide: () => void }) => React.ReactNode,\n opts: IConfirmDialogProps = {}\n ) =>\n new Promise<any>((resolve, reject) => {\n const pending = {resolve, reject};\n promptPromiseRef.current.reject?.();\n promptPromiseRef.current = pending;\n const hide = () => {\n if (promptPromiseRef.current !== pending) return;\n setDialogState(s => ({...s, visible: false}));\n promptPromiseRef.current = {};\n };\n setDialogState({\n visible: true,\n header: opts.header,\n children: render({\n resolve: (v) => {\n resolve(v);\n hide();\n },\n reject: () => {\n reject();\n hide();\n },\n hide,\n }),\n });\n }), []);\n\n // --- Stable context value ---\n const value = useMemo<Ctx>(() => ({\n confirm, confirmPopup, dialog, toast, toastDismiss, toastDismissAll, alert, confirmAsync, prompt,\n }), [confirm, confirmPopup, dialog, toast, toastDismiss, toastDismissAll, alert, confirmAsync, prompt]);\n const {owner, ...confirmationProps} = confirmState;\n\n return (\n <PopupContext.Provider value={value}>\n {children}\n <KitsToast ref={toastRef}/>\n <KitsConfirm\n key={owner}\n {...confirmationProps}\n onHide={result => {\n if (!mountedRef.current || owner !== confirmOwnerRef.current || activeConfirmActionsRef.current.has(owner) || notifiedConfirmOwnerRef.current === owner) return;\n notifiedConfirmOwnerRef.current = owner;\n hideConfirm(owner);\n confirmationProps.onHide?.(result);\n }}\n accept={() => runConfirmAction(owner, true, confirmationProps.accept, confirmationProps.async)}\n reject={() => runConfirmAction(owner, false, confirmationProps.reject, confirmationProps.async)}\n />\n <KitsDialog state={dialogState} onHide={hideDialog}/>\n {/*@ts-ignore*/}\n <KitsConfirmPopup onHide={hideConfirmPopup} {...confirmPopupState} />\n </PopupContext.Provider>\n );\n};\n\nexport const usePopup = () => useContext(PopupContext);\nexport const useDialog = usePopup; // alias\n\nexport default PopupProvider;\n"],"names":["owner","KitsDialog"],"mappings":"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"}
@@ -24,7 +24,7 @@ const useFormManager = ({
24
24
  }
25
25
  }, [elements]);
26
26
  const defaultValues = React.useMemo(() => helpers.getDefaultValues(elements), [elements]);
27
- const schema = React.useMemo(() => schemaBuilder.schemaBuilder(elements), [elements]);
27
+ const schema = React.useMemo(() => schemaBuilder.schemaBuilder(elements), [elements, id]);
28
28
  const combinedChildIds = React.useMemo(() => helpers.getCombinedChildIds(elements), [elements]);
29
29
  const stripCombinedChildren = React.useCallback((data) => {
30
30
  if (combinedChildIds.size === 0) return data;
@@ -82,7 +82,7 @@ const useFormManager = ({
82
82
  [outputFormat, onSubmit, setIsSubmitting, formMethods, stripCombinedChildren]
83
83
  );
84
84
  const handleSubmitWrapper = React.useCallback(() => {
85
- formMethods.handleSubmit(onValidSubmit, (errors) => {
85
+ return formMethods.handleSubmit(onValidSubmit, (errors) => {
86
86
  setIsSubmitting(false);
87
87
  onInvalidSubmit?.(errors);
88
88
  })();
@@ -93,8 +93,9 @@ const useFormManager = ({
93
93
  return acc[key];
94
94
  }, obj);
95
95
  }
96
+ const { watch } = formMethods;
96
97
  React.useEffect(() => {
97
- const subscription = formMethods.watch((currentValues, { name, type }) => {
98
+ const subscription = watch((currentValues, { name, type }) => {
98
99
  onChange?.(stripCombinedChildren(currentValues));
99
100
  if (onChangeSingleValue && name && type === "change") {
100
101
  if (!combinedChildIds.has(name)) {
@@ -104,7 +105,7 @@ const useFormManager = ({
104
105
  }
105
106
  });
106
107
  return () => subscription.unsubscribe();
107
- }, [formMethods.watch, onChange, onChangeSingleValue, stripCombinedChildren, combinedChildIds]);
108
+ }, [watch, onChange, onChangeSingleValue, stripCombinedChildren, combinedChildIds]);
108
109
  return {
109
110
  formMethods,
110
111
  // The original object for FormProvider
@@ -1 +1 @@
1
- {"version":3,"file":"useFormManager.cjs","sources":["../../../../src/form-renderer/hooks/useFormManager.ts"],"sourcesContent":["// hooks/useFormManager.ts\n\nimport {type Dispatch, type SetStateAction, useCallback, useEffect, useMemo} from 'react';\nimport {type FieldValues, type SubmitHandler, useForm, type UseFormReturn, type DefaultValues} from 'react-hook-form';\nimport {yupResolver} from '@hookform/resolvers/yup';\nimport {checkNameDuplication, getCombinedChildIds, getDefaultValues, schemaBuilder} from '../utils';\nimport type {IFormComponent} from '@lmb-it/kitsconcerto-types';\n\n// --- Using Your Provided Type Definitions ---\n\n\n// --- CORRECTED RETURN TYPE ---\nexport interface UseFormManagerReturn<T extends FieldValues> {\n /**\n * The original, unmodified methods returned from react-hook-form's useForm hook.\n * This is what gets passed to the FormProvider.\n */\n formMethods: UseFormReturn<T>;\n /**\n * Our custom loading state for the submit button.\n */\n isSubmitting: boolean;\n /**\n * Our wrapped submit handler that manages the isSubmitting state.\n * This is what the <form> element's onSubmit will call.\n */\n handleSubmit: () => void;\n\n setIsSubmitting: Dispatch<SetStateAction<boolean>>\n}\n\n// A helper utility to check for valid URLs, as used in your original getDefaultValues.\nconst isValidURL = (urlString: string): boolean => {\n try {\n const url = new URL(urlString);\n return ['http:', 'https:'].includes(url.protocol);\n } catch (_) {\n return false;\n }\n};\n\nexport const useFormManager = <T extends FieldValues>({\n elements,\n onSubmit,\n onInvalidSubmit, id,\n onChange,\n onChangeSingleValue, // <-- Add this\n outputFormat = 'Json'\n }: IFormComponent<T>, isSubmitting: boolean, setIsSubmitting: Dispatch<SetStateAction<boolean>>): UseFormManagerReturn<T> => {\n\n\n // 1. Check for duplicate names on mount and when elements change.\n useEffect(() => {\n try {\n checkNameDuplication(elements);\n } catch (error) {\n console.error(\"Form Configuration Error:\", error);\n }\n }, [elements]);\n\n // 2. Generate the default values object, memoized for performance.\n const defaultValues = useMemo(() => getDefaultValues(elements), [elements]);\n\n const schema = useMemo(() => schemaBuilder(elements, id!), [elements]);\n\n // 2b. Collect Combined children IDs to exclude from output data.\n const combinedChildIds = useMemo(() => getCombinedChildIds(elements), [elements]);\n\n const stripCombinedChildren = useCallback((data: Record<string, any>) => {\n if (combinedChildIds.size === 0) return data;\n const filtered: Record<string, any> = {};\n for (const [key, value] of Object.entries(data)) {\n if (!combinedChildIds.has(key)) {\n filtered[key] = value;\n }\n }\n return filtered;\n }, [combinedChildIds]);\n\n // console.log(id, elements, schema)\n\n // console.log(schema.describe())\n // This is the original, unmodified object from react-hook-form\n const formMethods = useForm<T>({\n resolver: yupResolver(schema),\n defaultValues: defaultValues as DefaultValues<T>,\n shouldUnregister: false,\n mode: \"onSubmit\",\n reValidateMode: \"onChange\",\n // ... (defaultValues logic remains the same)\n });\n\n\n const onValidSubmit: SubmitHandler<any> = useCallback(\n (rawData) => {\n const data = stripCombinedChildren(rawData);\n if (outputFormat === \"FormData\") {\n const formData = new FormData();\n for (const [key, value] of Object.entries(data)) {\n if (Array.isArray(value)) {\n if (value.length === 1 && value[0] instanceof File) {\n formData.append(key, value[0]);\n } else {\n value.forEach((item) => {\n if (item instanceof File) {\n formData.append(`${key}[]`, item);\n } else if (\n typeof item === \"number\" ||\n typeof item === \"string\"\n ) {\n formData.append(`${key}[]`, item.toString());\n } else {\n formData.append(`${key}[]`, JSON.stringify(item));\n }\n });\n }\n } else {\n if (value instanceof File) {\n formData.append(key, value);\n } else if (\n typeof value === \"number\" ||\n typeof value === \"string\"\n ) {\n formData.append(key, value.toString());\n } else {\n formData.append(key, JSON.stringify(value));\n }\n }\n }\n\n onSubmit && onSubmit(formData, setIsSubmitting, formMethods);\n } else {\n onSubmit && onSubmit(data, setIsSubmitting, formMethods);\n }\n },\n [outputFormat, onSubmit, setIsSubmitting, formMethods, stripCombinedChildren],\n );\n\n\n // Our custom wrapper function\n const handleSubmitWrapper = useCallback(() => {\n // We call the ORIGINAL handleSubmit from formMethods here\n formMethods.handleSubmit(onValidSubmit, (errors) => {\n setIsSubmitting(false);\n onInvalidSubmit?.(errors);\n })();\n }, [formMethods, onValidSubmit, setIsSubmitting, onInvalidSubmit]);\n\n function getValueByPath(obj: any, path: string) {\n return path.split(\".\").reduce((acc, key) => {\n if (acc === undefined || acc === null) return undefined;\n return acc[key];\n }, obj);\n }\n\n // This useEffect hook handles both global and single-value change events.\n useEffect(() => {\n const subscription = formMethods.watch((currentValues, {name, type}) => {\n // 1. Trigger the global onChange callback with all values (excluding Combined children).\n onChange?.(stripCombinedChildren(currentValues as { [s: string]: any }));\n\n // 2. Trigger the single value change callback (skip Combined child fields).\n if (onChangeSingleValue && name && type === 'change') {\n if (!combinedChildIds.has(name)) {\n const value = getValueByPath(currentValues, name);\n onChangeSingleValue(name, value);\n }\n }\n });\n return () => subscription.unsubscribe();\n }, [formMethods.watch, onChange, onChangeSingleValue, stripCombinedChildren, combinedChildIds]);\n\n // Return the two concerns separately\n return {\n formMethods, // The original object for FormProvider\n isSubmitting,\n setIsSubmitting,\n handleSubmit: handleSubmitWrapper, // The wrapped function for our UI\n };\n};\n"],"names":["useEffect","checkNameDuplication","useMemo","getDefaultValues","schemaBuilder","getCombinedChildIds","useCallback","useForm","yupResolver"],"mappings":"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"}
1
+ {"version":3,"file":"useFormManager.cjs","sources":["../../../../src/form-renderer/hooks/useFormManager.ts"],"sourcesContent":["// hooks/useFormManager.ts\n\nimport {type Dispatch, type SetStateAction, useCallback, useEffect, useMemo} from 'react';\nimport {type FieldValues, type SubmitHandler, useForm, type UseFormReturn, type DefaultValues} from 'react-hook-form';\nimport {yupResolver} from '@hookform/resolvers/yup';\nimport {checkNameDuplication, getCombinedChildIds, getDefaultValues, schemaBuilder} from '../utils';\nimport type {IFormComponent} from '@lmb-it/kitsconcerto-types';\n\n// --- Using Your Provided Type Definitions ---\n\n\n// --- CORRECTED RETURN TYPE ---\nexport interface UseFormManagerReturn<T extends FieldValues> {\n /**\n * The original, unmodified methods returned from react-hook-form's useForm hook.\n * This is what gets passed to the FormProvider.\n */\n formMethods: UseFormReturn<T>;\n /**\n * Our custom loading state for the submit button.\n */\n isSubmitting: boolean;\n /**\n * Our wrapped submit handler that manages the isSubmitting state.\n * This is what the <form> element's onSubmit will call.\n */\n handleSubmit: () => Promise<void>;\n\n setIsSubmitting: Dispatch<SetStateAction<boolean>>\n}\n\nexport const useFormManager = <T extends FieldValues>({\n elements,\n onSubmit,\n onInvalidSubmit, id,\n onChange,\n onChangeSingleValue, // <-- Add this\n outputFormat = 'Json'\n }: IFormComponent<T>, isSubmitting: boolean, setIsSubmitting: Dispatch<SetStateAction<boolean>>): UseFormManagerReturn<T> => {\n\n\n // 1. Check for duplicate names on mount and when elements change.\n useEffect(() => {\n try {\n checkNameDuplication(elements);\n } catch (error) {\n console.error(\"Form Configuration Error:\", error);\n }\n }, [elements]);\n\n // 2. Generate the default values object, memoized for performance.\n const defaultValues = useMemo(() => getDefaultValues(elements), [elements]);\n\n const schema = useMemo(() => schemaBuilder(elements, id!), [elements, id]);\n\n // 2b. Collect Combined children IDs to exclude from output data.\n const combinedChildIds = useMemo(() => getCombinedChildIds(elements), [elements]);\n\n const stripCombinedChildren = useCallback((data: Record<string, any>) => {\n if (combinedChildIds.size === 0) return data;\n const filtered: Record<string, any> = {};\n for (const [key, value] of Object.entries(data)) {\n if (!combinedChildIds.has(key)) {\n filtered[key] = value;\n }\n }\n return filtered;\n }, [combinedChildIds]);\n\n // console.log(id, elements, schema)\n\n // console.log(schema.describe())\n // This is the original, unmodified object from react-hook-form\n const formMethods = useForm<T>({\n resolver: yupResolver(schema),\n defaultValues: defaultValues as DefaultValues<T>,\n shouldUnregister: false,\n mode: \"onSubmit\",\n reValidateMode: \"onChange\",\n // ... (defaultValues logic remains the same)\n });\n\n\n const onValidSubmit: SubmitHandler<any> = useCallback(\n (rawData) => {\n const data = stripCombinedChildren(rawData);\n if (outputFormat === \"FormData\") {\n const formData = new FormData();\n for (const [key, value] of Object.entries(data)) {\n if (Array.isArray(value)) {\n if (value.length === 1 && value[0] instanceof File) {\n formData.append(key, value[0]);\n } else {\n value.forEach((item) => {\n if (item instanceof File) {\n formData.append(`${key}[]`, item);\n } else if (\n typeof item === \"number\" ||\n typeof item === \"string\"\n ) {\n formData.append(`${key}[]`, item.toString());\n } else {\n formData.append(`${key}[]`, JSON.stringify(item));\n }\n });\n }\n } else {\n if (value instanceof File) {\n formData.append(key, value);\n } else if (\n typeof value === \"number\" ||\n typeof value === \"string\"\n ) {\n formData.append(key, value.toString());\n } else {\n formData.append(key, JSON.stringify(value));\n }\n }\n }\n\n onSubmit && onSubmit(formData, setIsSubmitting, formMethods);\n } else {\n onSubmit && onSubmit(data, setIsSubmitting, formMethods);\n }\n },\n [outputFormat, onSubmit, setIsSubmitting, formMethods, stripCombinedChildren],\n );\n\n\n // Our custom wrapper function\n const handleSubmitWrapper = useCallback(() => {\n // We call the ORIGINAL handleSubmit from formMethods here\n return formMethods.handleSubmit(onValidSubmit, (errors) => {\n setIsSubmitting(false);\n onInvalidSubmit?.(errors);\n })();\n }, [formMethods, onValidSubmit, setIsSubmitting, onInvalidSubmit]);\n\n function getValueByPath(obj: any, path: string) {\n return path.split(\".\").reduce((acc, key) => {\n if (acc === undefined || acc === null) return undefined;\n return acc[key];\n }, obj);\n }\n\n // This useEffect hook handles both global and single-value change events.\n const {watch} = formMethods;\n useEffect(() => {\n const subscription = watch((currentValues, {name, type}) => {\n // 1. Trigger the global onChange callback with all values (excluding Combined children).\n onChange?.(stripCombinedChildren(currentValues as { [s: string]: any }));\n\n // 2. Trigger the single value change callback (skip Combined child fields).\n if (onChangeSingleValue && name && type === 'change') {\n if (!combinedChildIds.has(name)) {\n const value = getValueByPath(currentValues, name);\n onChangeSingleValue(name, value);\n }\n }\n });\n return () => subscription.unsubscribe();\n }, [watch, onChange, onChangeSingleValue, stripCombinedChildren, combinedChildIds]);\n\n // Return the two concerns separately\n return {\n formMethods, // The original object for FormProvider\n isSubmitting,\n setIsSubmitting,\n handleSubmit: handleSubmitWrapper, // The wrapped function for our UI\n };\n};\n"],"names":["useEffect","checkNameDuplication","useMemo","getDefaultValues","schemaBuilder","getCombinedChildIds","useCallback","useForm","yupResolver"],"mappings":";;;;;;;;AA+BO,MAAM,iBAAiB,CAAwB;AAAA,EACI,QAAA;AAAA,EACA,QAAA;AAAA,EACA,eAAA;AAAA,EAAiB,EAAA;AAAA,EACjB,QAAA;AAAA,EACA,mBAAA;AAAA;AAAA,EACA,YAAA,GAAe;AACnB,CAAA,EAAsB,cAAuB,eAAA,KAAgF;AAI/K,EAAAA,eAAA,CAAU,MAAM;AACZ,IAAA,IAAI;AACA,MAAAC,4BAAA,CAAqB,QAAQ,CAAA;AAAA,IACjC,SAAS,KAAA,EAAO;AACZ,MAAA,OAAA,CAAQ,KAAA,CAAM,6BAA6B,KAAK,CAAA;AAAA,IACpD;AAAA,EACJ,CAAA,EAAG,CAAC,QAAQ,CAAC,CAAA;AAGb,EAAA,MAAM,aAAA,GAAgBC,cAAQ,MAAMC,wBAAA,CAAiB,QAAQ,CAAA,EAAG,CAAC,QAAQ,CAAC,CAAA;AAE1E,EAAA,MAAM,MAAA,GAASD,aAAA,CAAQ,MAAME,2BAAA,CAAc,QAAa,CAAA,EAAG,CAAC,QAAA,EAAU,EAAE,CAAC,CAAA;AAGzE,EAAA,MAAM,gBAAA,GAAmBF,cAAQ,MAAMG,2BAAA,CAAoB,QAAQ,CAAA,EAAG,CAAC,QAAQ,CAAC,CAAA;AAEhF,EAAA,MAAM,qBAAA,GAAwBC,iBAAA,CAAY,CAAC,IAAA,KAA8B;AACrE,IAAA,IAAI,gBAAA,CAAiB,IAAA,KAAS,CAAA,EAAG,OAAO,IAAA;AACxC,IAAA,MAAM,WAAgC,EAAC;AACvC,IAAA,KAAA,MAAW,CAAC,GAAA,EAAK,KAAK,KAAK,MAAA,CAAO,OAAA,CAAQ,IAAI,CAAA,EAAG;AAC7C,MAAA,IAAI,CAAC,gBAAA,CAAiB,GAAA,CAAI,GAAG,CAAA,EAAG;AAC5B,QAAA,QAAA,CAAS,GAAG,CAAA,GAAI,KAAA;AAAA,MACpB;AAAA,IACJ;AACA,IAAA,OAAO,QAAA;AAAA,EACX,CAAA,EAAG,CAAC,gBAAgB,CAAC,CAAA;AAMrB,EAAA,MAAM,cAAcC,qBAAA,CAAW;AAAA,IAC3B,QAAA,EAAUC,gBAAY,MAAM,CAAA;AAAA,IAC5B,aAAA;AAAA,IACA,gBAAA,EAAkB,KAAA;AAAA,IAClB,IAAA,EAAM,UAAA;AAAA,IACN,cAAA,EAAgB;AAAA;AAAA,GAEnB,CAAA;AAGD,EAAA,MAAM,aAAA,GAAoCF,iBAAA;AAAA,IACtC,CAAC,OAAA,KAAY;AACT,MAAA,MAAM,IAAA,GAAO,sBAAsB,OAAO,CAAA;AAC1C,MAAA,IAAI,iBAAiB,UAAA,EAAY;AAC7B,QAAA,MAAM,QAAA,GAAW,IAAI,QAAA,EAAS;AAC9B,QAAA,KAAA,MAAW,CAAC,GAAA,EAAK,KAAK,KAAK,MAAA,CAAO,OAAA,CAAQ,IAAI,CAAA,EAAG;AAC7C,UAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,KAAK,CAAA,EAAG;AACtB,YAAA,IAAI,MAAM,MAAA,KAAW,CAAA,IAAK,KAAA,CAAM,CAAC,aAAa,IAAA,EAAM;AAChD,cAAA,QAAA,CAAS,MAAA,CAAO,GAAA,EAAK,KAAA,CAAM,CAAC,CAAC,CAAA;AAAA,YACjC,CAAA,MAAO;AACH,cAAA,KAAA,CAAM,OAAA,CAAQ,CAAC,IAAA,KAAS;AACpB,gBAAA,IAAI,gBAAgB,IAAA,EAAM;AACtB,kBAAA,QAAA,CAAS,MAAA,CAAO,CAAA,EAAG,GAAG,CAAA,EAAA,CAAA,EAAM,IAAI,CAAA;AAAA,gBACpC,WACI,OAAO,IAAA,KAAS,QAAA,IAChB,OAAO,SAAS,QAAA,EAClB;AACE,kBAAA,QAAA,CAAS,OAAO,CAAA,EAAG,GAAG,CAAA,EAAA,CAAA,EAAM,IAAA,CAAK,UAAU,CAAA;AAAA,gBAC/C,CAAA,MAAO;AACH,kBAAA,QAAA,CAAS,OAAO,CAAA,EAAG,GAAG,MAAM,IAAA,CAAK,SAAA,CAAU,IAAI,CAAC,CAAA;AAAA,gBACpD;AAAA,cACJ,CAAC,CAAA;AAAA,YACL;AAAA,UACJ,CAAA,MAAO;AACH,YAAA,IAAI,iBAAiB,IAAA,EAAM;AACvB,cAAA,QAAA,CAAS,MAAA,CAAO,KAAK,KAAK,CAAA;AAAA,YAC9B,WACI,OAAO,KAAA,KAAU,QAAA,IACjB,OAAO,UAAU,QAAA,EACnB;AACE,cAAA,QAAA,CAAS,MAAA,CAAO,GAAA,EAAK,KAAA,CAAM,QAAA,EAAU,CAAA;AAAA,YACzC,CAAA,MAAO;AACH,cAAA,QAAA,CAAS,MAAA,CAAO,GAAA,EAAK,IAAA,CAAK,SAAA,CAAU,KAAK,CAAC,CAAA;AAAA,YAC9C;AAAA,UACJ;AAAA,QACJ;AAEA,QAAA,QAAA,IAAY,QAAA,CAAS,QAAA,EAAU,eAAA,EAAiB,WAAW,CAAA;AAAA,MAC/D,CAAA,MAAO;AACH,QAAA,QAAA,IAAY,QAAA,CAAS,IAAA,EAAM,eAAA,EAAiB,WAAW,CAAA;AAAA,MAC3D;AAAA,IACJ,CAAA;AAAA,IACA,CAAC,YAAA,EAAc,QAAA,EAAU,eAAA,EAAiB,aAAa,qBAAqB;AAAA,GAChF;AAIA,EAAA,MAAM,mBAAA,GAAsBA,kBAAY,MAAM;AAE1C,IAAA,OAAO,WAAA,CAAY,YAAA,CAAa,aAAA,EAAe,CAAC,MAAA,KAAW;AACvD,MAAA,eAAA,CAAgB,KAAK,CAAA;AACrB,MAAA,eAAA,GAAkB,MAAM,CAAA;AAAA,IAC5B,CAAC,CAAA,EAAE;AAAA,EACP,GAAG,CAAC,WAAA,EAAa,aAAA,EAAe,eAAA,EAAiB,eAAe,CAAC,CAAA;AAEjE,EAAA,SAAS,cAAA,CAAe,KAAU,IAAA,EAAc;AAC5C,IAAA,OAAO,KAAK,KAAA,CAAM,GAAG,EAAE,MAAA,CAAO,CAAC,KAAK,GAAA,KAAQ;AACxC,MAAA,IAAI,GAAA,KAAQ,MAAA,IAAa,GAAA,KAAQ,IAAA,EAAM,OAAO,MAAA;AAC9C,MAAA,OAAO,IAAI,GAAG,CAAA;AAAA,IAClB,GAAG,GAAG,CAAA;AAAA,EACV;AAGA,EAAA,MAAM,EAAC,OAAK,GAAI,WAAA;AAChB,EAAAN,eAAA,CAAU,MAAM;AACZ,IAAA,MAAM,eAAe,KAAA,CAAM,CAAC,eAAe,EAAC,IAAA,EAAM,MAAI,KAAM;AAExD,MAAA,QAAA,GAAW,qBAAA,CAAsB,aAAqC,CAAC,CAAA;AAGvE,MAAA,IAAI,mBAAA,IAAuB,IAAA,IAAQ,IAAA,KAAS,QAAA,EAAU;AAClD,QAAA,IAAI,CAAC,gBAAA,CAAiB,GAAA,CAAI,IAAI,CAAA,EAAG;AAC7B,UAAA,MAAM,KAAA,GAAQ,cAAA,CAAe,aAAA,EAAe,IAAI,CAAA;AAChD,UAAA,mBAAA,CAAoB,MAAM,KAAK,CAAA;AAAA,QACnC;AAAA,MACJ;AAAA,IACJ,CAAC,CAAA;AACD,IAAA,OAAO,MAAM,aAAa,WAAA,EAAY;AAAA,EAC1C,GAAG,CAAC,KAAA,EAAO,UAAU,mBAAA,EAAqB,qBAAA,EAAuB,gBAAgB,CAAC,CAAA;AAGlF,EAAA,OAAO;AAAA,IACH,WAAA;AAAA;AAAA,IACA,YAAA;AAAA,IACA,eAAA;AAAA,IACA,YAAA,EAAc;AAAA;AAAA,GAClB;AACJ;;;;"}