@qumra/jisr 1.0.1 → 1.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +10 -10
- package/dist/hooks/context.d.ts +16 -9
- package/dist/hooks/context.d.ts.map +1 -1
- package/dist/hooks/context.js +35 -12
- package/dist/hooks/context.js.map +1 -1
- package/dist/hooks/useModal.d.ts +24 -25
- package/dist/hooks/useModal.d.ts.map +1 -1
- package/dist/hooks/useModal.js +35 -28
- package/dist/hooks/useModal.js.map +1 -1
- package/dist/hooks/useNavigationMenu.d.ts +55 -0
- package/dist/hooks/useNavigationMenu.d.ts.map +1 -0
- package/dist/hooks/useNavigationMenu.js +81 -0
- package/dist/hooks/useNavigationMenu.js.map +1 -0
- package/dist/hooks/useSaveBar.d.ts +48 -24
- package/dist/hooks/useSaveBar.d.ts.map +1 -1
- package/dist/hooks/useSaveBar.js +73 -25
- package/dist/hooks/useSaveBar.js.map +1 -1
- package/dist/hooks/useToast.js +1 -1
- package/dist/index.d.ts +5 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/jisr.global.js +2 -0
- package/dist/jisr.global.js.map +1 -0
- package/dist/utils/actions.d.ts +47 -14
- package/dist/utils/actions.d.ts.map +1 -1
- package/dist/utils/actions.js +26 -17
- package/dist/utils/actions.js.map +1 -1
- package/dist/utils/app-bridge.d.ts +19 -2
- package/dist/utils/app-bridge.d.ts.map +1 -1
- package/dist/utils/app-bridge.js +56 -4
- package/dist/utils/app-bridge.js.map +1 -1
- package/package.json +2 -10
package/README.md
CHANGED
|
@@ -347,18 +347,18 @@ const myAction: AppBridgeAction = {
|
|
|
347
347
|
|
|
348
348
|
| Package | Description |
|
|
349
349
|
|---------|-------------|
|
|
350
|
-
| [@qumra/
|
|
351
|
-
| [@qumra/
|
|
352
|
-
| [@qumra/
|
|
353
|
-
| [@qumra/
|
|
354
|
-
| [@qumra/
|
|
355
|
-
| [@qumra/
|
|
356
|
-
| [@qumra/
|
|
350
|
+
| [@qumra/app-sdk](https://www.npmjs.com/package/@qumra/app-sdk) | Core SDK — sessions, security, errors |
|
|
351
|
+
| [@qumra/app-react-router](https://www.npmjs.com/package/@qumra/app-react-router) | React Router 7 integration |
|
|
352
|
+
| [@qumra/app-session-storage-prisma](https://www.npmjs.com/package/@qumra/app-session-storage-prisma) | Prisma session storage |
|
|
353
|
+
| [@qumra/app-session-storage-mongodb](https://www.npmjs.com/package/@qumra/app-session-storage-mongodb) | MongoDB session storage |
|
|
354
|
+
| [@qumra/jisr](https://www.npmjs.com/package/@qumra/jisr) | App Bridge for iframe communication |
|
|
355
|
+
| [@qumra/manara](https://www.npmjs.com/package/@qumra/manara) | Design system & components |
|
|
356
|
+
| [@qumra/riwaq](https://www.npmjs.com/package/@qumra/riwaq) | UI Extensions SDK |
|
|
357
357
|
|
|
358
358
|
## License
|
|
359
359
|
|
|
360
|
-
ISC ©
|
|
360
|
+
ISC © Qumra
|
|
361
361
|
|
|
362
|
-
##
|
|
362
|
+
## Documentation
|
|
363
363
|
|
|
364
|
-
|
|
364
|
+
https://docs.qumra.cloud
|
package/dist/hooks/context.d.ts
CHANGED
|
@@ -12,6 +12,8 @@ export interface QumraAppBridgeProviderProps {
|
|
|
12
12
|
children: React.ReactNode;
|
|
13
13
|
/** Configuration for the AppBridge instance */
|
|
14
14
|
config: AppBridgeConfig;
|
|
15
|
+
/** Custom navigate handler. If not provided, uses built-in SPA navigation (pushState + popstate). */
|
|
16
|
+
navigate?: (url: string) => void;
|
|
15
17
|
}
|
|
16
18
|
/**
|
|
17
19
|
* Provider component for AppBridge
|
|
@@ -19,18 +21,18 @@ export interface QumraAppBridgeProviderProps {
|
|
|
19
21
|
*
|
|
20
22
|
* @example
|
|
21
23
|
* ```tsx
|
|
22
|
-
*
|
|
24
|
+
* // Works out of the box — built-in navigation
|
|
25
|
+
* <QumraAppBridgeProvider config={{ apiKey: 'your-api-key' }}>
|
|
26
|
+
* <YourApp />
|
|
27
|
+
* </QumraAppBridgeProvider>
|
|
23
28
|
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
* </QumraAppBridgeProvider>
|
|
29
|
-
* );
|
|
30
|
-
* }
|
|
29
|
+
* // Or with a custom navigate handler
|
|
30
|
+
* <QumraAppBridgeProvider config={{ apiKey }} navigate={(url) => navigate(url)}>
|
|
31
|
+
* <YourApp />
|
|
32
|
+
* </QumraAppBridgeProvider>
|
|
31
33
|
* ```
|
|
32
34
|
*/
|
|
33
|
-
export declare function QumraAppBridgeProvider({ children, config, }: QumraAppBridgeProviderProps): JSX.Element;
|
|
35
|
+
export declare function QumraAppBridgeProvider({ children, config, navigate, }: QumraAppBridgeProviderProps): JSX.Element;
|
|
34
36
|
/**
|
|
35
37
|
* Internal hook to get the AppBridge context
|
|
36
38
|
* @internal
|
|
@@ -38,4 +40,9 @@ export declare function QumraAppBridgeProvider({ children, config, }: QumraAppBr
|
|
|
38
40
|
* @throws Error if used outside of QumraAppBridgeProvider
|
|
39
41
|
*/
|
|
40
42
|
export declare function useAppBridgeContext(): AppBridge;
|
|
43
|
+
/**
|
|
44
|
+
* Internal hook to get the app-level navigate handler
|
|
45
|
+
* @internal
|
|
46
|
+
*/
|
|
47
|
+
export declare function useAppNavigate(): (url: string) => void;
|
|
41
48
|
//# sourceMappingURL=context.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/hooks/context.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,SAAS,EAAE,KAAK,eAAe,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/hooks/context.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,SAAS,EAAE,KAAK,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAoBzE;;GAEG;AACH,MAAM,WAAW,2BAA2B;IAC1C,8DAA8D;IAC9D,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,+CAA+C;IAC/C,MAAM,EAAE,eAAe,CAAC;IACxB,qGAAqG;IACrG,QAAQ,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;CAClC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,sBAAsB,CAAC,EACrC,QAAQ,EACR,MAAM,EACN,QAAQ,GACT,EAAE,2BAA2B,GAAG,GAAG,CAAC,OAAO,CAwB3C;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,IAAI,SAAS,CAU/C;AAED;;;GAGG;AACH,wBAAgB,cAAc,IAAI,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAGtD"}
|
package/dist/hooks/context.js
CHANGED
|
@@ -7,34 +7,49 @@ import React from 'react';
|
|
|
7
7
|
import { AppBridge } from '../utils/app-bridge.js';
|
|
8
8
|
/** React Context for AppBridge instance */
|
|
9
9
|
const AppBridgeContext = React.createContext(null);
|
|
10
|
+
/** App-level navigate handler */
|
|
11
|
+
const NavigateContext = React.createContext(null);
|
|
12
|
+
/**
|
|
13
|
+
* Built-in navigate that works with React Router and most SPA routers.
|
|
14
|
+
* Uses pushState + popstate event which routers listen to.
|
|
15
|
+
*/
|
|
16
|
+
function defaultNavigate(url) {
|
|
17
|
+
if (typeof window === 'undefined')
|
|
18
|
+
return;
|
|
19
|
+
window.history.pushState(null, '', url);
|
|
20
|
+
window.dispatchEvent(new PopStateEvent('popstate'));
|
|
21
|
+
}
|
|
10
22
|
/**
|
|
11
23
|
* Provider component for AppBridge
|
|
12
24
|
* Must wrap your application to provide the AppBridge to all hooks
|
|
13
25
|
*
|
|
14
26
|
* @example
|
|
15
27
|
* ```tsx
|
|
16
|
-
*
|
|
28
|
+
* // Works out of the box — built-in navigation
|
|
29
|
+
* <QumraAppBridgeProvider config={{ apiKey: 'your-api-key' }}>
|
|
30
|
+
* <YourApp />
|
|
31
|
+
* </QumraAppBridgeProvider>
|
|
17
32
|
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
* </QumraAppBridgeProvider>
|
|
23
|
-
* );
|
|
24
|
-
* }
|
|
33
|
+
* // Or with a custom navigate handler
|
|
34
|
+
* <QumraAppBridgeProvider config={{ apiKey }} navigate={(url) => navigate(url)}>
|
|
35
|
+
* <YourApp />
|
|
36
|
+
* </QumraAppBridgeProvider>
|
|
25
37
|
* ```
|
|
26
38
|
*/
|
|
27
|
-
export function QumraAppBridgeProvider({ children, config, }) {
|
|
39
|
+
export function QumraAppBridgeProvider({ children, config, navigate, }) {
|
|
28
40
|
const [bridge] = React.useState(() => new AppBridge(config));
|
|
41
|
+
const navigateRef = React.useRef(navigate ?? defaultNavigate);
|
|
42
|
+
navigateRef.current = navigate ?? defaultNavigate;
|
|
29
43
|
React.useEffect(() => {
|
|
30
|
-
|
|
44
|
+
bridge.setNavigateHandler((path) => {
|
|
45
|
+
navigateRef.current(path);
|
|
46
|
+
});
|
|
31
47
|
bridge.ready();
|
|
32
|
-
// Cleanup on unmount
|
|
33
48
|
return () => {
|
|
34
49
|
bridge.destroy();
|
|
35
50
|
};
|
|
36
51
|
}, [bridge]);
|
|
37
|
-
return (_jsx(AppBridgeContext.Provider, { value: bridge, children: children }));
|
|
52
|
+
return (_jsx(AppBridgeContext.Provider, { value: bridge, children: _jsx(NavigateContext.Provider, { value: navigateRef, children: children }) }));
|
|
38
53
|
}
|
|
39
54
|
/**
|
|
40
55
|
* Internal hook to get the AppBridge context
|
|
@@ -49,4 +64,12 @@ export function useAppBridgeContext() {
|
|
|
49
64
|
}
|
|
50
65
|
return context;
|
|
51
66
|
}
|
|
67
|
+
/**
|
|
68
|
+
* Internal hook to get the app-level navigate handler
|
|
69
|
+
* @internal
|
|
70
|
+
*/
|
|
71
|
+
export function useAppNavigate() {
|
|
72
|
+
const ref = React.useContext(NavigateContext);
|
|
73
|
+
return ref?.current ?? defaultNavigate;
|
|
74
|
+
}
|
|
52
75
|
//# sourceMappingURL=context.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context.js","sourceRoot":"","sources":["../../src/hooks/context.tsx"],"names":[],"mappings":";AAAA;;;GAGG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,SAAS,EAAwB,MAAM,wBAAwB,CAAC;AAEzE,2CAA2C;AAC3C,MAAM,gBAAgB,GAAG,KAAK,CAAC,aAAa,CAAmB,IAAI,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"context.js","sourceRoot":"","sources":["../../src/hooks/context.tsx"],"names":[],"mappings":";AAAA;;;GAGG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,SAAS,EAAwB,MAAM,wBAAwB,CAAC;AAEzE,2CAA2C;AAC3C,MAAM,gBAAgB,GAAG,KAAK,CAAC,aAAa,CAAmB,IAAI,CAAC,CAAC;AAErE,iCAAiC;AACjC,MAAM,eAAe,GAAG,KAAK,CAAC,aAAa,CAEzC,IAAI,CAAC,CAAC;AAER;;;GAGG;AACH,SAAS,eAAe,CAAC,GAAW;IAClC,IAAI,OAAO,MAAM,KAAK,WAAW;QAAE,OAAO;IAC1C,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,IAAI,EAAE,EAAE,EAAE,GAAG,CAAC,CAAC;IACxC,MAAM,CAAC,aAAa,CAAC,IAAI,aAAa,CAAC,UAAU,CAAC,CAAC,CAAC;AACtD,CAAC;AAcD;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,sBAAsB,CAAC,EACrC,QAAQ,EACR,MAAM,EACN,QAAQ,GACoB;IAC5B,MAAM,CAAC,MAAM,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAC,GAAG,EAAE,CAAC,IAAI,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC;IAC7D,MAAM,WAAW,GAAG,KAAK,CAAC,MAAM,CAAC,QAAQ,IAAI,eAAe,CAAC,CAAC;IAC9D,WAAW,CAAC,OAAO,GAAG,QAAQ,IAAI,eAAe,CAAC;IAElD,KAAK,CAAC,SAAS,CAAC,GAAG,EAAE;QACnB,MAAM,CAAC,kBAAkB,CAAC,CAAC,IAAI,EAAE,EAAE;YACjC,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QAC5B,CAAC,CAAC,CAAC;QAEH,MAAM,CAAC,KAAK,EAAE,CAAC;QAEf,OAAO,GAAG,EAAE;YACV,MAAM,CAAC,OAAO,EAAE,CAAC;QACnB,CAAC,CAAC;IACJ,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC;IAEb,OAAO,CACL,KAAC,gBAAgB,CAAC,QAAQ,IAAC,KAAK,EAAE,MAAM,YACtC,KAAC,eAAe,CAAC,QAAQ,IAAC,KAAK,EAAE,WAAW,YACzC,QAAQ,GACgB,GACD,CAC7B,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,mBAAmB;IACjC,MAAM,OAAO,GAAG,KAAK,CAAC,UAAU,CAAC,gBAAgB,CAAC,CAAC;IAEnD,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CACb,2DAA2D,CAC5D,CAAC;IACJ,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,cAAc;IAC5B,MAAM,GAAG,GAAG,KAAK,CAAC,UAAU,CAAC,eAAe,CAAC,CAAC;IAC9C,OAAO,GAAG,EAAE,OAAO,IAAI,eAAe,CAAC;AACzC,CAAC"}
|
package/dist/hooks/useModal.d.ts
CHANGED
|
@@ -2,45 +2,44 @@
|
|
|
2
2
|
* Hook for managing modal dialogs
|
|
3
3
|
*/
|
|
4
4
|
import type { ModalOptions } from '../utils/actions.js';
|
|
5
|
+
/**
|
|
6
|
+
* Options for modal.show() — modal config + event callbacks
|
|
7
|
+
*/
|
|
8
|
+
export interface ModalShowOptions extends ModalOptions {
|
|
9
|
+
/** Called when the user clicks the primary action */
|
|
10
|
+
onConfirm?: () => void | Promise<void>;
|
|
11
|
+
/** Called when the user clicks the secondary action or dismisses the modal */
|
|
12
|
+
onCancel?: () => void;
|
|
13
|
+
}
|
|
5
14
|
/**
|
|
6
15
|
* Modal utility functions
|
|
7
16
|
*/
|
|
8
17
|
export interface UseModalResult {
|
|
9
|
-
/**
|
|
10
|
-
|
|
18
|
+
/** Show a modal dialog */
|
|
19
|
+
show: (options: ModalShowOptions) => void;
|
|
11
20
|
/** Close the current modal */
|
|
12
|
-
|
|
21
|
+
hide: () => void;
|
|
13
22
|
}
|
|
14
23
|
/**
|
|
15
24
|
* Hook to manage modal dialogs
|
|
16
25
|
*
|
|
17
26
|
* @example
|
|
18
27
|
* ```tsx
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
* export function MyComponent() {
|
|
22
|
-
* const modal = useModal();
|
|
23
|
-
*
|
|
24
|
-
* const handleOpenSettings = () => {
|
|
25
|
-
* modal.open({
|
|
26
|
-
* title: 'Settings',
|
|
27
|
-
* url: '/settings',
|
|
28
|
-
* size: 'large',
|
|
29
|
-
* primaryAction: {
|
|
30
|
-
* content: 'Save',
|
|
31
|
-
* onAction: () => {
|
|
32
|
-
* // Handle save
|
|
33
|
-
* modal.close();
|
|
34
|
-
* }
|
|
35
|
-
* }
|
|
36
|
-
* });
|
|
37
|
-
* };
|
|
28
|
+
* const modal = useModal();
|
|
38
29
|
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
30
|
+
* modal.show({
|
|
31
|
+
* title: 'حذف المنتج؟',
|
|
32
|
+
* message: 'هذا الإجراء لا يمكن التراجع عنه',
|
|
33
|
+
* primaryAction: { label: 'حذف', variant: 'destructive' },
|
|
34
|
+
* secondaryAction: { label: 'إلغاء' },
|
|
35
|
+
* onConfirm: async () => {
|
|
36
|
+
* await deleteProduct();
|
|
37
|
+
* modal.hide();
|
|
38
|
+
* },
|
|
39
|
+
* });
|
|
41
40
|
* ```
|
|
42
41
|
*
|
|
43
|
-
* @returns Object with
|
|
42
|
+
* @returns Object with show and hide methods
|
|
44
43
|
*/
|
|
45
44
|
export declare function useModal(): UseModalResult;
|
|
46
45
|
//# sourceMappingURL=useModal.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useModal.d.ts","sourceRoot":"","sources":["../../src/hooks/useModal.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAExD;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,0BAA0B;IAC1B,IAAI,EAAE,CAAC,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"useModal.d.ts","sourceRoot":"","sources":["../../src/hooks/useModal.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAExD;;GAEG;AACH,MAAM,WAAW,gBAAiB,SAAQ,YAAY;IACpD,qDAAqD;IACrD,SAAS,CAAC,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACvC,8EAA8E;IAC9E,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;CACvB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,0BAA0B;IAC1B,IAAI,EAAE,CAAC,OAAO,EAAE,gBAAgB,KAAK,IAAI,CAAC;IAC1C,8BAA8B;IAC9B,IAAI,EAAE,MAAM,IAAI,CAAC;CAClB;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,QAAQ,IAAI,cAAc,CAyCzC"}
|
package/dist/hooks/useModal.js
CHANGED
|
@@ -1,48 +1,55 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Hook for managing modal dialogs
|
|
3
3
|
*/
|
|
4
|
-
import { useCallback } from 'react';
|
|
4
|
+
import { useCallback, useEffect, useRef } from 'react';
|
|
5
5
|
import { useAppBridge } from './useAppBridge.js';
|
|
6
|
-
import { openModal, closeModal } from '../utils/actions.js';
|
|
6
|
+
import { ActionType, openModal, closeModal } from '../utils/actions.js';
|
|
7
7
|
/**
|
|
8
8
|
* Hook to manage modal dialogs
|
|
9
9
|
*
|
|
10
10
|
* @example
|
|
11
11
|
* ```tsx
|
|
12
|
-
*
|
|
12
|
+
* const modal = useModal();
|
|
13
13
|
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
* onAction: () => {
|
|
25
|
-
* // Handle save
|
|
26
|
-
* modal.close();
|
|
27
|
-
* }
|
|
28
|
-
* }
|
|
29
|
-
* });
|
|
30
|
-
* };
|
|
31
|
-
*
|
|
32
|
-
* return <button onClick={handleOpenSettings}>Open Settings</button>;
|
|
33
|
-
* }
|
|
14
|
+
* modal.show({
|
|
15
|
+
* title: 'حذف المنتج؟',
|
|
16
|
+
* message: 'هذا الإجراء لا يمكن التراجع عنه',
|
|
17
|
+
* primaryAction: { label: 'حذف', variant: 'destructive' },
|
|
18
|
+
* secondaryAction: { label: 'إلغاء' },
|
|
19
|
+
* onConfirm: async () => {
|
|
20
|
+
* await deleteProduct();
|
|
21
|
+
* modal.hide();
|
|
22
|
+
* },
|
|
23
|
+
* });
|
|
34
24
|
* ```
|
|
35
25
|
*
|
|
36
|
-
* @returns Object with
|
|
26
|
+
* @returns Object with show and hide methods
|
|
37
27
|
*/
|
|
38
28
|
export function useModal() {
|
|
39
29
|
const bridge = useAppBridge();
|
|
40
|
-
const
|
|
41
|
-
|
|
30
|
+
const optionsRef = useRef();
|
|
31
|
+
useEffect(() => {
|
|
32
|
+
const unsubConfirm = bridge.subscribe(ActionType.MODAL_CONFIRM, () => {
|
|
33
|
+
optionsRef.current?.onConfirm?.();
|
|
34
|
+
});
|
|
35
|
+
const unsubCancel = bridge.subscribe(ActionType.MODAL_CANCEL, () => {
|
|
36
|
+
optionsRef.current?.onCancel?.();
|
|
37
|
+
optionsRef.current = undefined;
|
|
38
|
+
});
|
|
39
|
+
return () => {
|
|
40
|
+
unsubConfirm();
|
|
41
|
+
unsubCancel();
|
|
42
|
+
};
|
|
43
|
+
}, [bridge]);
|
|
44
|
+
const show = useCallback((options) => {
|
|
45
|
+
optionsRef.current = options;
|
|
46
|
+
const { onConfirm, onCancel, ...modalOptions } = options;
|
|
47
|
+
bridge.dispatch(openModal(modalOptions));
|
|
42
48
|
}, [bridge]);
|
|
43
|
-
const
|
|
49
|
+
const hide = useCallback(() => {
|
|
50
|
+
optionsRef.current = undefined;
|
|
44
51
|
bridge.dispatch(closeModal());
|
|
45
52
|
}, [bridge]);
|
|
46
|
-
return {
|
|
53
|
+
return { show, hide };
|
|
47
54
|
}
|
|
48
55
|
//# sourceMappingURL=useModal.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useModal.js","sourceRoot":"","sources":["../../src/hooks/useModal.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"useModal.js","sourceRoot":"","sources":["../../src/hooks/useModal.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC;AACvD,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAuBxE;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,UAAU,QAAQ;IACtB,MAAM,MAAM,GAAG,YAAY,EAAE,CAAC;IAC9B,MAAM,UAAU,GAAG,MAAM,EAAoB,CAAC;IAE9C,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,YAAY,GAAG,MAAM,CAAC,SAAS,CACnC,UAAU,CAAC,aAAa,EACxB,GAAG,EAAE;YACH,UAAU,CAAC,OAAO,EAAE,SAAS,EAAE,EAAE,CAAC;QACpC,CAAC,CACF,CAAC;QAEF,MAAM,WAAW,GAAG,MAAM,CAAC,SAAS,CAClC,UAAU,CAAC,YAAY,EACvB,GAAG,EAAE;YACH,UAAU,CAAC,OAAO,EAAE,QAAQ,EAAE,EAAE,CAAC;YACjC,UAAU,CAAC,OAAO,GAAG,SAAS,CAAC;QACjC,CAAC,CACF,CAAC;QAEF,OAAO,GAAG,EAAE;YACV,YAAY,EAAE,CAAC;YACf,WAAW,EAAE,CAAC;QAChB,CAAC,CAAC;IACJ,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC;IAEb,MAAM,IAAI,GAAG,WAAW,CACtB,CAAC,OAAyB,EAAE,EAAE;QAC5B,UAAU,CAAC,OAAO,GAAG,OAAO,CAAC;QAC7B,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,GAAG,YAAY,EAAE,GAAG,OAAO,CAAC;QACzD,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC,CAAC;IAC3C,CAAC,EACD,CAAC,MAAM,CAAC,CACT,CAAC;IAEF,MAAM,IAAI,GAAG,WAAW,CAAC,GAAG,EAAE;QAC5B,UAAU,CAAC,OAAO,GAAG,SAAS,CAAC;QAC/B,MAAM,CAAC,QAAQ,CAAC,UAAU,EAAE,CAAC,CAAC;IAChC,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC;IAEb,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;AACxB,CAAC"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hook for managing the navigation menu in the Qumra Admin host.
|
|
3
|
+
*/
|
|
4
|
+
import type { NavigationMenuItem } from '../utils/actions.js';
|
|
5
|
+
/**
|
|
6
|
+
* Partial update for a navigation menu item (url cannot be changed)
|
|
7
|
+
*/
|
|
8
|
+
export type NavigationMenuItemUpdate = Partial<Omit<NavigationMenuItem, 'url'>>;
|
|
9
|
+
/**
|
|
10
|
+
* Navigation menu utility functions
|
|
11
|
+
*/
|
|
12
|
+
export interface UseNavigationMenuResult {
|
|
13
|
+
/** Current navigation pages */
|
|
14
|
+
readonly pages: NavigationMenuItem[];
|
|
15
|
+
/** Replace all navigation pages */
|
|
16
|
+
set: (pages: NavigationMenuItem[]) => void;
|
|
17
|
+
/** Add a navigation item. If an item with the same url exists, it will be updated */
|
|
18
|
+
add: (item: NavigationMenuItem) => void;
|
|
19
|
+
/** Remove a navigation item by url */
|
|
20
|
+
remove: (url: string) => void;
|
|
21
|
+
/** Update properties of a single item by url */
|
|
22
|
+
update: (url: string, partial: NavigationMenuItemUpdate) => void;
|
|
23
|
+
/** Tell the host which page is currently active */
|
|
24
|
+
setActive: (path: string) => void;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Hook to manage the navigation menu shown in the Qumra Admin host.
|
|
28
|
+
*
|
|
29
|
+
* The returned object is **stable** — safe to use in useEffect dependencies
|
|
30
|
+
* without causing infinite loops.
|
|
31
|
+
*
|
|
32
|
+
* Navigation events from the host (HOST::NAVIGATION::NAVIGATE) are handled
|
|
33
|
+
* at the Provider level, so they work even when components unmount/remount.
|
|
34
|
+
*
|
|
35
|
+
* @example
|
|
36
|
+
* ```tsx
|
|
37
|
+
* function App() {
|
|
38
|
+
* const navigation = useNavigationMenu();
|
|
39
|
+
*
|
|
40
|
+
* useEffect(() => {
|
|
41
|
+
* navigation.set([
|
|
42
|
+
* { label: 'الرئيسية', url: '/', icon: 'home' },
|
|
43
|
+
* { label: 'الطلبات', url: '/orders', icon: 'orders', badge: 3 },
|
|
44
|
+
* ]);
|
|
45
|
+
* }, [navigation]); // safe — navigation is stable
|
|
46
|
+
*
|
|
47
|
+
* // Update badge dynamically
|
|
48
|
+
* navigation.update('/orders', { badge: 5 });
|
|
49
|
+
* }
|
|
50
|
+
* ```
|
|
51
|
+
*
|
|
52
|
+
* @returns Stable object with navigation management methods
|
|
53
|
+
*/
|
|
54
|
+
export declare function useNavigationMenu(): UseNavigationMenuResult;
|
|
55
|
+
//# sourceMappingURL=useNavigationMenu.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useNavigationMenu.d.ts","sourceRoot":"","sources":["../../src/hooks/useNavigationMenu.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAE9D;;GAEG;AACH,MAAM,MAAM,wBAAwB,GAAG,OAAO,CAAC,IAAI,CAAC,kBAAkB,EAAE,KAAK,CAAC,CAAC,CAAC;AAEhF;;GAEG;AACH,MAAM,WAAW,uBAAuB;IACtC,+BAA+B;IAC/B,QAAQ,CAAC,KAAK,EAAE,kBAAkB,EAAE,CAAC;IACrC,mCAAmC;IACnC,GAAG,EAAE,CAAC,KAAK,EAAE,kBAAkB,EAAE,KAAK,IAAI,CAAC;IAC3C,qFAAqF;IACrF,GAAG,EAAE,CAAC,IAAI,EAAE,kBAAkB,KAAK,IAAI,CAAC;IACxC,sCAAsC;IACtC,MAAM,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IAC9B,gDAAgD;IAChD,MAAM,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,wBAAwB,KAAK,IAAI,CAAC;IACjE,mDAAmD;IACnD,SAAS,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CACnC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAgB,iBAAiB,IAAI,uBAAuB,CA+E3D"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hook for managing the navigation menu in the Qumra Admin host.
|
|
3
|
+
*/
|
|
4
|
+
import { useCallback, useMemo, useRef } from 'react';
|
|
5
|
+
import { useAppBridge } from './useAppBridge.js';
|
|
6
|
+
import { ActionType } from '../utils/actions.js';
|
|
7
|
+
/**
|
|
8
|
+
* Hook to manage the navigation menu shown in the Qumra Admin host.
|
|
9
|
+
*
|
|
10
|
+
* The returned object is **stable** — safe to use in useEffect dependencies
|
|
11
|
+
* without causing infinite loops.
|
|
12
|
+
*
|
|
13
|
+
* Navigation events from the host (HOST::NAVIGATION::NAVIGATE) are handled
|
|
14
|
+
* at the Provider level, so they work even when components unmount/remount.
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```tsx
|
|
18
|
+
* function App() {
|
|
19
|
+
* const navigation = useNavigationMenu();
|
|
20
|
+
*
|
|
21
|
+
* useEffect(() => {
|
|
22
|
+
* navigation.set([
|
|
23
|
+
* { label: 'الرئيسية', url: '/', icon: 'home' },
|
|
24
|
+
* { label: 'الطلبات', url: '/orders', icon: 'orders', badge: 3 },
|
|
25
|
+
* ]);
|
|
26
|
+
* }, [navigation]); // safe — navigation is stable
|
|
27
|
+
*
|
|
28
|
+
* // Update badge dynamically
|
|
29
|
+
* navigation.update('/orders', { badge: 5 });
|
|
30
|
+
* }
|
|
31
|
+
* ```
|
|
32
|
+
*
|
|
33
|
+
* @returns Stable object with navigation management methods
|
|
34
|
+
*/
|
|
35
|
+
export function useNavigationMenu() {
|
|
36
|
+
const bridge = useAppBridge();
|
|
37
|
+
const pagesRef = useRef([]);
|
|
38
|
+
// Dispatch the full pages list to the host and update the ref
|
|
39
|
+
const dispatchPages = useCallback((nextPages) => {
|
|
40
|
+
pagesRef.current = nextPages;
|
|
41
|
+
bridge.dispatch({
|
|
42
|
+
type: ActionType.NAVIGATION_UPDATE,
|
|
43
|
+
payload: { pages: nextPages },
|
|
44
|
+
});
|
|
45
|
+
}, [bridge]);
|
|
46
|
+
const set = useCallback((nextPages) => {
|
|
47
|
+
dispatchPages(nextPages);
|
|
48
|
+
}, [dispatchPages]);
|
|
49
|
+
const add = useCallback((item) => {
|
|
50
|
+
const current = pagesRef.current;
|
|
51
|
+
const index = current.findIndex((i) => i.url === item.url);
|
|
52
|
+
const nextPages = index >= 0
|
|
53
|
+
? current.map((i) => (i.url === item.url ? { ...i, ...item } : i))
|
|
54
|
+
: [...current, item];
|
|
55
|
+
dispatchPages(nextPages);
|
|
56
|
+
}, [dispatchPages]);
|
|
57
|
+
const remove = useCallback((url) => {
|
|
58
|
+
dispatchPages(pagesRef.current.filter((i) => i.url !== url));
|
|
59
|
+
}, [dispatchPages]);
|
|
60
|
+
const update = useCallback((url, partial) => {
|
|
61
|
+
dispatchPages(pagesRef.current.map((i) => i.url === url ? { ...i, ...partial } : i));
|
|
62
|
+
}, [dispatchPages]);
|
|
63
|
+
const setActive = useCallback((path) => {
|
|
64
|
+
bridge.dispatch({
|
|
65
|
+
type: ActionType.NAVIGATION_SET_ACTIVE,
|
|
66
|
+
payload: { path },
|
|
67
|
+
});
|
|
68
|
+
}, [bridge]);
|
|
69
|
+
// Stable object — all deps are stable (bridge never changes)
|
|
70
|
+
return useMemo(() => ({
|
|
71
|
+
get pages() {
|
|
72
|
+
return pagesRef.current;
|
|
73
|
+
},
|
|
74
|
+
set,
|
|
75
|
+
add,
|
|
76
|
+
remove,
|
|
77
|
+
update,
|
|
78
|
+
setActive,
|
|
79
|
+
}), [set, add, remove, update, setActive]);
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=useNavigationMenu.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useNavigationMenu.js","sourceRoot":"","sources":["../../src/hooks/useNavigationMenu.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,13 +1,37 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Hook for managing the save bar (unsaved changes indicator)
|
|
3
3
|
*/
|
|
4
|
-
|
|
4
|
+
/**
|
|
5
|
+
* Helpers passed to onSave for manual control over save result
|
|
6
|
+
*/
|
|
7
|
+
export interface SaveBarHelpers {
|
|
8
|
+
/** Signal that the save completed successfully */
|
|
9
|
+
complete: () => void;
|
|
10
|
+
/** Signal that the save failed */
|
|
11
|
+
error: (message?: string) => void;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Options passed to saveBar.show()
|
|
15
|
+
*/
|
|
16
|
+
export interface SaveBarShowOptions {
|
|
17
|
+
/**
|
|
18
|
+
* Callback when the save button is clicked.
|
|
19
|
+
*
|
|
20
|
+
* Receives `{ complete, error }` helpers for manual control.
|
|
21
|
+
* - If you call `complete()` or `error()`, you control the result.
|
|
22
|
+
* - If you don't call either, the hook auto-dispatches based on the promise:
|
|
23
|
+
* resolves → SAVE_COMPLETE, throws → SAVE_ERROR.
|
|
24
|
+
*/
|
|
25
|
+
onSave?: (helpers: SaveBarHelpers) => void | Promise<void>;
|
|
26
|
+
/** Callback when the discard button is clicked */
|
|
27
|
+
onDiscard?: () => void;
|
|
28
|
+
}
|
|
5
29
|
/**
|
|
6
30
|
* Save bar utility functions
|
|
7
31
|
*/
|
|
8
32
|
export interface UseSaveBarResult {
|
|
9
33
|
/** Show the save bar */
|
|
10
|
-
show: (options?:
|
|
34
|
+
show: (options?: SaveBarShowOptions) => void;
|
|
11
35
|
/** Hide the save bar */
|
|
12
36
|
hide: () => void;
|
|
13
37
|
}
|
|
@@ -15,31 +39,31 @@ export interface UseSaveBarResult {
|
|
|
15
39
|
* Hook to manage the save bar for indicating unsaved changes
|
|
16
40
|
*
|
|
17
41
|
* @example
|
|
42
|
+
* Simple (auto mode):
|
|
18
43
|
* ```tsx
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
* export function MyComponent() {
|
|
22
|
-
* const saveBar = useSaveBar();
|
|
23
|
-
* const [hasChanges, setHasChanges] = React.useState(false);
|
|
24
|
-
*
|
|
25
|
-
* const handleChange = () => {
|
|
26
|
-
* setHasChanges(true);
|
|
27
|
-
* saveBar.show();
|
|
28
|
-
* };
|
|
29
|
-
*
|
|
30
|
-
* const handleSave = async () => {
|
|
44
|
+
* saveBar.show({
|
|
45
|
+
* onSave: async () => {
|
|
31
46
|
* await saveData();
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
47
|
+
* // resolves → SAVE_COMPLETE, throws → SAVE_ERROR
|
|
48
|
+
* },
|
|
49
|
+
* onDiscard: () => resetForm(),
|
|
50
|
+
* });
|
|
51
|
+
* ```
|
|
35
52
|
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
53
|
+
* @example
|
|
54
|
+
* Dynamic (manual control):
|
|
55
|
+
* ```tsx
|
|
56
|
+
* saveBar.show({
|
|
57
|
+
* onSave: async ({ complete, error }) => {
|
|
58
|
+
* const res = await fetch('/api/save', { method: 'POST' });
|
|
59
|
+
* if (res.ok) {
|
|
60
|
+
* complete();
|
|
61
|
+
* } else {
|
|
62
|
+
* error('فشل الحفظ');
|
|
63
|
+
* }
|
|
64
|
+
* },
|
|
65
|
+
* onDiscard: () => resetForm(),
|
|
66
|
+
* });
|
|
43
67
|
* ```
|
|
44
68
|
*
|
|
45
69
|
* @returns Object with show and hide methods
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useSaveBar.d.ts","sourceRoot":"","sources":["../../src/hooks/useSaveBar.ts"],"names":[],"mappings":"AAAA;;GAEG;
|
|
1
|
+
{"version":3,"file":"useSaveBar.d.ts","sourceRoot":"","sources":["../../src/hooks/useSaveBar.ts"],"names":[],"mappings":"AAAA;;GAEG;AAMH;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,kDAAkD;IAClD,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,kCAAkC;IAClC,KAAK,EAAE,CAAC,OAAO,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;CACnC;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC;;;;;;;OAOG;IACH,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,cAAc,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3D,kDAAkD;IAClD,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;CACxB;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,wBAAwB;IACxB,IAAI,EAAE,CAAC,OAAO,CAAC,EAAE,kBAAkB,KAAK,IAAI,CAAC;IAC7C,wBAAwB;IACxB,IAAI,EAAE,MAAM,IAAI,CAAC;CAClB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,wBAAgB,UAAU,IAAI,gBAAgB,CAqE7C"}
|