@molecule/app-react 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +115 -0
- package/README.md +2645 -0
- package/dist/agent-identity.d.ts +40 -0
- package/dist/agent-identity.d.ts.map +1 -0
- package/dist/agent-identity.js +31 -0
- package/dist/agent-identity.js.map +1 -0
- package/dist/contexts.d.ts +69 -0
- package/dist/contexts.d.ts.map +1 -0
- package/dist/contexts.js +70 -0
- package/dist/contexts.js.map +1 -0
- package/dist/hooks/index.d.ts +32 -0
- package/dist/hooks/index.d.ts.map +1 -0
- package/dist/hooks/index.js +32 -0
- package/dist/hooks/index.js.map +1 -0
- package/dist/hooks/useAIModels.d.ts +48 -0
- package/dist/hooks/useAIModels.d.ts.map +1 -0
- package/dist/hooks/useAIModels.js +145 -0
- package/dist/hooks/useAIModels.js.map +1 -0
- package/dist/hooks/useAsyncState.d.ts +41 -0
- package/dist/hooks/useAsyncState.d.ts.map +1 -0
- package/dist/hooks/useAsyncState.js +77 -0
- package/dist/hooks/useAsyncState.js.map +1 -0
- package/dist/hooks/useAuth.d.ts +43 -0
- package/dist/hooks/useAuth.d.ts.map +1 -0
- package/dist/hooks/useAuth.js +106 -0
- package/dist/hooks/useAuth.js.map +1 -0
- package/dist/hooks/useCapacitorApp.d.ts +35 -0
- package/dist/hooks/useCapacitorApp.d.ts.map +1 -0
- package/dist/hooks/useCapacitorApp.js +61 -0
- package/dist/hooks/useCapacitorApp.js.map +1 -0
- package/dist/hooks/useChangePassword.d.ts +34 -0
- package/dist/hooks/useChangePassword.d.ts.map +1 -0
- package/dist/hooks/useChangePassword.js +37 -0
- package/dist/hooks/useChangePassword.js.map +1 -0
- package/dist/hooks/useChat.d.ts +30 -0
- package/dist/hooks/useChat.d.ts.map +1 -0
- package/dist/hooks/useChat.js +1510 -0
- package/dist/hooks/useChat.js.map +1 -0
- package/dist/hooks/useDevice.d.ts +39 -0
- package/dist/hooks/useDevice.d.ts.map +1 -0
- package/dist/hooks/useDevice.js +41 -0
- package/dist/hooks/useDevice.js.map +1 -0
- package/dist/hooks/useEditor.d.ts +20 -0
- package/dist/hooks/useEditor.d.ts.map +1 -0
- package/dist/hooks/useEditor.js +98 -0
- package/dist/hooks/useEditor.js.map +1 -0
- package/dist/hooks/useForm.d.ts +87 -0
- package/dist/hooks/useForm.d.ts.map +1 -0
- package/dist/hooks/useForm.js +148 -0
- package/dist/hooks/useForm.js.map +1 -0
- package/dist/hooks/useHttp.d.ts +103 -0
- package/dist/hooks/useHttp.d.ts.map +1 -0
- package/dist/hooks/useHttp.js +161 -0
- package/dist/hooks/useHttp.js.map +1 -0
- package/dist/hooks/useLogger.d.ts +68 -0
- package/dist/hooks/useLogger.d.ts.map +1 -0
- package/dist/hooks/useLogger.js +95 -0
- package/dist/hooks/useLogger.js.map +1 -0
- package/dist/hooks/useLogin.d.ts +35 -0
- package/dist/hooks/useLogin.d.ts.map +1 -0
- package/dist/hooks/useLogin.js +37 -0
- package/dist/hooks/useLogin.js.map +1 -0
- package/dist/hooks/useOAuth.d.ts +83 -0
- package/dist/hooks/useOAuth.d.ts.map +1 -0
- package/dist/hooks/useOAuth.js +348 -0
- package/dist/hooks/useOAuth.js.map +1 -0
- package/dist/hooks/usePasswordReset.d.ts +43 -0
- package/dist/hooks/usePasswordReset.d.ts.map +1 -0
- package/dist/hooks/usePasswordReset.js +50 -0
- package/dist/hooks/usePasswordReset.js.map +1 -0
- package/dist/hooks/usePlatform.d.ts +38 -0
- package/dist/hooks/usePlatform.d.ts.map +1 -0
- package/dist/hooks/usePlatform.js +40 -0
- package/dist/hooks/usePlatform.js.map +1 -0
- package/dist/hooks/usePreview.d.ts +20 -0
- package/dist/hooks/usePreview.d.ts.map +1 -0
- package/dist/hooks/usePreview.js +62 -0
- package/dist/hooks/usePreview.js.map +1 -0
- package/dist/hooks/usePromise.d.ts +39 -0
- package/dist/hooks/usePromise.d.ts.map +1 -0
- package/dist/hooks/usePromise.js +92 -0
- package/dist/hooks/usePromise.js.map +1 -0
- package/dist/hooks/usePush.d.ts +50 -0
- package/dist/hooks/usePush.d.ts.map +1 -0
- package/dist/hooks/usePush.js +89 -0
- package/dist/hooks/usePush.js.map +1 -0
- package/dist/hooks/useRouter.d.ts +65 -0
- package/dist/hooks/useRouter.d.ts.map +1 -0
- package/dist/hooks/useRouter.js +120 -0
- package/dist/hooks/useRouter.js.map +1 -0
- package/dist/hooks/useSignup.d.ts +35 -0
- package/dist/hooks/useSignup.d.ts.map +1 -0
- package/dist/hooks/useSignup.js +37 -0
- package/dist/hooks/useSignup.js.map +1 -0
- package/dist/hooks/useStorage.d.ts +72 -0
- package/dist/hooks/useStorage.d.ts.map +1 -0
- package/dist/hooks/useStorage.js +144 -0
- package/dist/hooks/useStorage.js.map +1 -0
- package/dist/hooks/useStore.d.ts +51 -0
- package/dist/hooks/useStore.d.ts.map +1 -0
- package/dist/hooks/useStore.js +86 -0
- package/dist/hooks/useStore.js.map +1 -0
- package/dist/hooks/useTheme.d.ts +50 -0
- package/dist/hooks/useTheme.d.ts.map +1 -0
- package/dist/hooks/useTheme.js +135 -0
- package/dist/hooks/useTheme.js.map +1 -0
- package/dist/hooks/useTranslation.d.ts +69 -0
- package/dist/hooks/useTranslation.d.ts.map +1 -0
- package/dist/hooks/useTranslation.js +131 -0
- package/dist/hooks/useTranslation.js.map +1 -0
- package/dist/hooks/useVersion.d.ts +41 -0
- package/dist/hooks/useVersion.d.ts.map +1 -0
- package/dist/hooks/useVersion.js +73 -0
- package/dist/hooks/useVersion.js.map +1 -0
- package/dist/hooks/useWorkspace.d.ts +18 -0
- package/dist/hooks/useWorkspace.d.ts.map +1 -0
- package/dist/hooks/useWorkspace.js +67 -0
- package/dist/hooks/useWorkspace.js.map +1 -0
- package/dist/index.d.ts +80 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +80 -0
- package/dist/index.js.map +1 -0
- package/dist/providers.d.ts +189 -0
- package/dist/providers.d.ts.map +1 -0
- package/dist/providers.js +248 -0
- package/dist/providers.js.map +1 -0
- package/dist/types.d.ts +381 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +7 -0
- package/dist/types.js.map +1 -0
- package/package.json +82 -0
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* React hook for storage.
|
|
3
|
+
*
|
|
4
|
+
* @module
|
|
5
|
+
*/
|
|
6
|
+
import { useCallback, useContext, useEffect, useState } from 'react';
|
|
7
|
+
import { t } from '@molecule/app-i18n';
|
|
8
|
+
import { StorageContext } from '../contexts.js';
|
|
9
|
+
/**
|
|
10
|
+
* Hook to access the storage provider from context.
|
|
11
|
+
*
|
|
12
|
+
* @returns The storage provider from context
|
|
13
|
+
* @throws {Error} Error if used outside of StorageProvider
|
|
14
|
+
*/
|
|
15
|
+
export function useStorageProvider() {
|
|
16
|
+
const provider = useContext(StorageContext);
|
|
17
|
+
if (!provider) {
|
|
18
|
+
throw new Error(t('react.error.useStorageOutsideProvider', undefined, {
|
|
19
|
+
defaultValue: 'useStorageProvider must be used within a StorageProvider',
|
|
20
|
+
}));
|
|
21
|
+
}
|
|
22
|
+
return provider;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Hook to manage a single storage value with React state sync.
|
|
26
|
+
*
|
|
27
|
+
* @param key - Storage key
|
|
28
|
+
* @param options - Hook options
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* ```tsx
|
|
32
|
+
* const { value: theme, setValue: setTheme, loading } = useStorageValue<string>('theme', {
|
|
33
|
+
* defaultValue: 'light'
|
|
34
|
+
* })
|
|
35
|
+
*
|
|
36
|
+
* if (loading) return <Spinner />
|
|
37
|
+
* return (
|
|
38
|
+
* <select value={theme} onChange={(e) => setTheme(e.target.value)}>
|
|
39
|
+
* <option value="light">Light</option>
|
|
40
|
+
* <option value="dark">Dark</option>
|
|
41
|
+
* </select>
|
|
42
|
+
* )
|
|
43
|
+
* ```
|
|
44
|
+
* @returns Storage value state (value, loading, error) and mutators (setValue, removeValue).
|
|
45
|
+
*/
|
|
46
|
+
export function useStorageValue(key, options) {
|
|
47
|
+
const storage = useStorageProvider();
|
|
48
|
+
const { defaultValue, sync = false } = options ?? {};
|
|
49
|
+
const [value, setValueState] = useState(defaultValue);
|
|
50
|
+
const [loading, setLoading] = useState(true);
|
|
51
|
+
const [error, setError] = useState(null);
|
|
52
|
+
// Load initial value
|
|
53
|
+
useEffect(() => {
|
|
54
|
+
let mounted = true;
|
|
55
|
+
const loadValue = async () => {
|
|
56
|
+
try {
|
|
57
|
+
const stored = await storage.get(key);
|
|
58
|
+
if (mounted) {
|
|
59
|
+
setValueState(stored ?? defaultValue);
|
|
60
|
+
setLoading(false);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
catch (err) {
|
|
64
|
+
if (mounted) {
|
|
65
|
+
setError(err instanceof Error ? err : new Error(String(err)));
|
|
66
|
+
setLoading(false);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
loadValue();
|
|
71
|
+
return () => {
|
|
72
|
+
mounted = false;
|
|
73
|
+
};
|
|
74
|
+
}, [key, storage, defaultValue]);
|
|
75
|
+
// Sync across tabs if supported
|
|
76
|
+
useEffect(() => {
|
|
77
|
+
if (!sync)
|
|
78
|
+
return;
|
|
79
|
+
const handleStorageChange = (event) => {
|
|
80
|
+
if (event.key === key && event.newValue !== null) {
|
|
81
|
+
try {
|
|
82
|
+
const newValue = JSON.parse(event.newValue);
|
|
83
|
+
setValueState(newValue);
|
|
84
|
+
}
|
|
85
|
+
catch (_error) {
|
|
86
|
+
// JSON.parse failed on newValue — the cross-tab sync is best-effort and the
|
|
87
|
+
// local state already holds the last good value, so ignoring is safe here.
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
window.addEventListener('storage', handleStorageChange);
|
|
92
|
+
return () => window.removeEventListener('storage', handleStorageChange);
|
|
93
|
+
}, [key, sync]);
|
|
94
|
+
const setValue = useCallback(async (newValue) => {
|
|
95
|
+
try {
|
|
96
|
+
await storage.set(key, newValue);
|
|
97
|
+
setValueState(newValue);
|
|
98
|
+
setError(null);
|
|
99
|
+
}
|
|
100
|
+
catch (err) {
|
|
101
|
+
setError(err instanceof Error ? err : new Error(String(err)));
|
|
102
|
+
throw err;
|
|
103
|
+
}
|
|
104
|
+
}, [key, storage]);
|
|
105
|
+
const removeValue = useCallback(async () => {
|
|
106
|
+
try {
|
|
107
|
+
await storage.remove(key);
|
|
108
|
+
setValueState(defaultValue);
|
|
109
|
+
setError(null);
|
|
110
|
+
}
|
|
111
|
+
catch (err) {
|
|
112
|
+
setError(err instanceof Error ? err : new Error(String(err)));
|
|
113
|
+
throw err;
|
|
114
|
+
}
|
|
115
|
+
}, [key, storage, defaultValue]);
|
|
116
|
+
return {
|
|
117
|
+
value,
|
|
118
|
+
setValue,
|
|
119
|
+
removeValue,
|
|
120
|
+
loading,
|
|
121
|
+
error,
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Hook for simple storage operations without React state sync.
|
|
126
|
+
*
|
|
127
|
+
* @returns Storage operation methods
|
|
128
|
+
*/
|
|
129
|
+
export function useStorage() {
|
|
130
|
+
const storage = useStorageProvider();
|
|
131
|
+
const get = useCallback((key) => storage.get(key), [storage]);
|
|
132
|
+
const set = useCallback((key, value) => storage.set(key, value), [storage]);
|
|
133
|
+
const remove = useCallback((key) => storage.remove(key), [storage]);
|
|
134
|
+
const clear = useCallback(() => storage.clear(), [storage]);
|
|
135
|
+
const keys = useCallback(() => storage.keys(), [storage]);
|
|
136
|
+
return {
|
|
137
|
+
get,
|
|
138
|
+
set,
|
|
139
|
+
remove,
|
|
140
|
+
clear,
|
|
141
|
+
keys,
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
//# sourceMappingURL=useStorage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useStorage.js","sourceRoot":"","sources":["../../src/hooks/useStorage.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* React hook for state management.
|
|
3
|
+
*
|
|
4
|
+
* @module
|
|
5
|
+
*/
|
|
6
|
+
import type { StateProvider, Store } from '@molecule/app-state';
|
|
7
|
+
import type { UseStoreOptions } from '../types.js';
|
|
8
|
+
/**
|
|
9
|
+
* Hook to access the state provider from context.
|
|
10
|
+
*
|
|
11
|
+
* @returns The state provider from context
|
|
12
|
+
* @throws {Error} Error if used outside of StateProvider
|
|
13
|
+
*/
|
|
14
|
+
export declare function useStateProvider(): StateProvider;
|
|
15
|
+
/**
|
|
16
|
+
* Hook to subscribe to a store with optional selector and equality function.
|
|
17
|
+
*
|
|
18
|
+
* @param store - The store to subscribe to
|
|
19
|
+
* @param options - Hook options (selector, equalityFn)
|
|
20
|
+
* @returns The selected state
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* ```tsx
|
|
24
|
+
* const count = useStore(counterStore)
|
|
25
|
+
* const doubled = useStore(counterStore, { selector: (s) => s.count * 2 })
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
export declare function useStore<T, S = T>(store: Store<T>, options?: UseStoreOptions<T, S>): S;
|
|
29
|
+
/**
|
|
30
|
+
* Hook to get the store's setState function.
|
|
31
|
+
*
|
|
32
|
+
* @param store - The store to get setState from
|
|
33
|
+
* @returns The setState function
|
|
34
|
+
*/
|
|
35
|
+
export declare function useSetStore<T>(store: Store<T>): Store<T>['setState'];
|
|
36
|
+
/**
|
|
37
|
+
* Hook to create a bound action for a store.
|
|
38
|
+
*
|
|
39
|
+
* @param store - The store to bind to
|
|
40
|
+
* @param action - The action function that receives setState and getState
|
|
41
|
+
* @returns A bound action function
|
|
42
|
+
*
|
|
43
|
+
* @example
|
|
44
|
+
* ```tsx
|
|
45
|
+
* const increment = useStoreAction(counterStore, (setState, getState) => () => {
|
|
46
|
+
* setState({ count: getState().count + 1 })
|
|
47
|
+
* })
|
|
48
|
+
* ```
|
|
49
|
+
*/
|
|
50
|
+
export declare function useStoreAction<T, Args extends unknown[], R>(store: Store<T>, action: (setState: Store<T>['setState'], getState: Store<T>['getState']) => (...args: Args) => R): (...args: Args) => R;
|
|
51
|
+
//# sourceMappingURL=useStore.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useStore.d.ts","sourceRoot":"","sources":["../../src/hooks/useStore.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH,OAAO,KAAK,EAAE,aAAa,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAA;AAG/D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AAElD;;;;;GAKG;AACH,wBAAgB,gBAAgB,IAAI,aAAa,CAUhD;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,QAAQ,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,EAAE,eAAe,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,CAgCtF;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAEpE;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAAE,IAAI,SAAS,OAAO,EAAE,EAAE,CAAC,EACzD,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,EACf,MAAM,EAAE,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,KAAK,CAAC,GAAG,IAAI,EAAE,IAAI,KAAK,CAAC,GAC/F,CAAC,GAAG,IAAI,EAAE,IAAI,KAAK,CAAC,CAKtB"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* React hook for state management.
|
|
3
|
+
*
|
|
4
|
+
* @module
|
|
5
|
+
*/
|
|
6
|
+
import { useCallback, useContext, useRef, useSyncExternalStore } from 'react';
|
|
7
|
+
import { t } from '@molecule/app-i18n';
|
|
8
|
+
import { StateContext } from '../contexts.js';
|
|
9
|
+
/**
|
|
10
|
+
* Hook to access the state provider from context.
|
|
11
|
+
*
|
|
12
|
+
* @returns The state provider from context
|
|
13
|
+
* @throws {Error} Error if used outside of StateProvider
|
|
14
|
+
*/
|
|
15
|
+
export function useStateProvider() {
|
|
16
|
+
const provider = useContext(StateContext);
|
|
17
|
+
if (!provider) {
|
|
18
|
+
throw new Error(t('react.error.useStoreOutsideProvider', undefined, {
|
|
19
|
+
defaultValue: 'useStateProvider must be used within a StateProvider',
|
|
20
|
+
}));
|
|
21
|
+
}
|
|
22
|
+
return provider;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Hook to subscribe to a store with optional selector and equality function.
|
|
26
|
+
*
|
|
27
|
+
* @param store - The store to subscribe to
|
|
28
|
+
* @param options - Hook options (selector, equalityFn)
|
|
29
|
+
* @returns The selected state
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* ```tsx
|
|
33
|
+
* const count = useStore(counterStore)
|
|
34
|
+
* const doubled = useStore(counterStore, { selector: (s) => s.count * 2 })
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
37
|
+
export function useStore(store, options) {
|
|
38
|
+
// Validate that we're within a StateProvider
|
|
39
|
+
useStateProvider();
|
|
40
|
+
const { selector, equalityFn } = options ?? {};
|
|
41
|
+
// Use a ref to track the previous selected value for equality comparison
|
|
42
|
+
const prevSelectedRef = useRef(undefined);
|
|
43
|
+
const getSnapshot = useCallback(() => {
|
|
44
|
+
const state = store.getState();
|
|
45
|
+
const selected = selector ? selector(state) : state;
|
|
46
|
+
// If we have an equality function and a previous value, check equality
|
|
47
|
+
if (equalityFn && prevSelectedRef.current !== undefined) {
|
|
48
|
+
if (equalityFn(prevSelectedRef.current, selected)) {
|
|
49
|
+
return prevSelectedRef.current;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
prevSelectedRef.current = selected;
|
|
53
|
+
return selected;
|
|
54
|
+
}, [store, selector, equalityFn]);
|
|
55
|
+
const subscribe = useCallback((onStoreChange) => {
|
|
56
|
+
return store.subscribe(onStoreChange);
|
|
57
|
+
}, [store]);
|
|
58
|
+
return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Hook to get the store's setState function.
|
|
62
|
+
*
|
|
63
|
+
* @param store - The store to get setState from
|
|
64
|
+
* @returns The setState function
|
|
65
|
+
*/
|
|
66
|
+
export function useSetStore(store) {
|
|
67
|
+
return store.setState;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Hook to create a bound action for a store.
|
|
71
|
+
*
|
|
72
|
+
* @param store - The store to bind to
|
|
73
|
+
* @param action - The action function that receives setState and getState
|
|
74
|
+
* @returns A bound action function
|
|
75
|
+
*
|
|
76
|
+
* @example
|
|
77
|
+
* ```tsx
|
|
78
|
+
* const increment = useStoreAction(counterStore, (setState, getState) => () => {
|
|
79
|
+
* setState({ count: getState().count + 1 })
|
|
80
|
+
* })
|
|
81
|
+
* ```
|
|
82
|
+
*/
|
|
83
|
+
export function useStoreAction(store, action) {
|
|
84
|
+
return useCallback((...args) => action(store.setState, store.getState)(...args), [store, action]);
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=useStore.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useStore.js","sourceRoot":"","sources":["../../src/hooks/useStore.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,EAAE,oBAAoB,EAAE,MAAM,OAAO,CAAA;AAE7E,OAAO,EAAE,CAAC,EAAE,MAAM,oBAAoB,CAAA;AAGtC,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAA;AAG7C;;;;;GAKG;AACH,MAAM,UAAU,gBAAgB;IAC9B,MAAM,QAAQ,GAAG,UAAU,CAAC,YAAY,CAAC,CAAA;IACzC,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,MAAM,IAAI,KAAK,CACb,CAAC,CAAC,qCAAqC,EAAE,SAAS,EAAE;YAClD,YAAY,EAAE,sDAAsD;SACrE,CAAC,CACH,CAAA;IACH,CAAC;IACD,OAAO,QAAQ,CAAA;AACjB,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,QAAQ,CAAW,KAAe,EAAE,OAA+B;IACjF,6CAA6C;IAC7C,gBAAgB,EAAE,CAAA;IAElB,MAAM,EAAE,QAAQ,EAAE,UAAU,EAAE,GAAG,OAAO,IAAI,EAAE,CAAA;IAE9C,yEAAyE;IACzE,MAAM,eAAe,GAAG,MAAM,CAAgB,SAAS,CAAC,CAAA;IAExD,MAAM,WAAW,GAAG,WAAW,CAAC,GAAG,EAAE;QACnC,MAAM,KAAK,GAAG,KAAK,CAAC,QAAQ,EAAE,CAAA;QAC9B,MAAM,QAAQ,GAAG,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAE,KAAsB,CAAA;QAErE,uEAAuE;QACvE,IAAI,UAAU,IAAI,eAAe,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;YACxD,IAAI,UAAU,CAAC,eAAe,CAAC,OAAO,EAAE,QAAQ,CAAC,EAAE,CAAC;gBAClD,OAAO,eAAe,CAAC,OAAO,CAAA;YAChC,CAAC;QACH,CAAC;QAED,eAAe,CAAC,OAAO,GAAG,QAAQ,CAAA;QAClC,OAAO,QAAQ,CAAA;IACjB,CAAC,EAAE,CAAC,KAAK,EAAE,QAAQ,EAAE,UAAU,CAAC,CAAC,CAAA;IAEjC,MAAM,SAAS,GAAG,WAAW,CAC3B,CAAC,aAAyB,EAAE,EAAE;QAC5B,OAAO,KAAK,CAAC,SAAS,CAAC,aAAa,CAAC,CAAA;IACvC,CAAC,EACD,CAAC,KAAK,CAAC,CACR,CAAA;IAED,OAAO,oBAAoB,CAAC,SAAS,EAAE,WAAW,EAAE,WAAW,CAAC,CAAA;AAClE,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,WAAW,CAAI,KAAe;IAC5C,OAAO,KAAK,CAAC,QAAQ,CAAA;AACvB,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,cAAc,CAC5B,KAAe,EACf,MAAgG;IAEhG,OAAO,WAAW,CAChB,CAAC,GAAG,IAAU,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAC,GAAG,IAAI,CAAC,EAClE,CAAC,KAAK,EAAE,MAAM,CAAC,CAChB,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* React hook for theming.
|
|
3
|
+
*
|
|
4
|
+
* @module
|
|
5
|
+
*/
|
|
6
|
+
import type { Theme, ThemeProvider } from '@molecule/app-theme';
|
|
7
|
+
import type { UseThemeResult } from '../types.js';
|
|
8
|
+
/**
|
|
9
|
+
* Hook to access the theme provider from context.
|
|
10
|
+
*
|
|
11
|
+
* @returns The theme provider from context
|
|
12
|
+
* @throws {Error} Error if used outside of ThemeProvider
|
|
13
|
+
*/
|
|
14
|
+
export declare function useThemeProvider(): ThemeProvider;
|
|
15
|
+
/**
|
|
16
|
+
* Hook for theme state and actions.
|
|
17
|
+
*
|
|
18
|
+
* @returns Theme state and actions
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```tsx
|
|
22
|
+
* const { theme, themeName, setTheme, toggleTheme } = useTheme()
|
|
23
|
+
*
|
|
24
|
+
* return (
|
|
25
|
+
* <button onClick={toggleTheme}>
|
|
26
|
+
* Current theme: {themeName}
|
|
27
|
+
* </button>
|
|
28
|
+
* )
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
export declare function useTheme(): UseThemeResult;
|
|
32
|
+
/**
|
|
33
|
+
* Hook to get just the current theme object.
|
|
34
|
+
*
|
|
35
|
+
* @returns The current theme
|
|
36
|
+
*/
|
|
37
|
+
export declare function useCurrentTheme(): Theme;
|
|
38
|
+
/**
|
|
39
|
+
* Hook to get just the theme mode (light/dark).
|
|
40
|
+
*
|
|
41
|
+
* @returns The current theme mode
|
|
42
|
+
*/
|
|
43
|
+
export declare function useThemeMode(): 'light' | 'dark';
|
|
44
|
+
/**
|
|
45
|
+
* Hook to get theme colors.
|
|
46
|
+
*
|
|
47
|
+
* @returns The current theme colors
|
|
48
|
+
*/
|
|
49
|
+
export declare function useThemeColors(): Theme['colors'];
|
|
50
|
+
//# sourceMappingURL=useTheme.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useTheme.d.ts","sourceRoot":"","sources":["../../src/hooks/useTheme.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH,OAAO,KAAK,EAAE,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AAG/D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAEjD;;;;;GAKG;AACH,wBAAgB,gBAAgB,IAAI,aAAa,CAUhD;AAuBD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,QAAQ,IAAI,cAAc,CA4DzC;AAED;;;;GAIG;AACH,wBAAgB,eAAe,IAAI,KAAK,CAGvC;AAED;;;;GAIG;AACH,wBAAgB,YAAY,IAAI,OAAO,GAAG,MAAM,CAG/C;AAED;;;;GAIG;AACH,wBAAgB,cAAc,IAAI,KAAK,CAAC,QAAQ,CAAC,CAGhD"}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* React hook for theming.
|
|
3
|
+
*
|
|
4
|
+
* @module
|
|
5
|
+
*/
|
|
6
|
+
import { useCallback, useContext, useEffect, useState } from 'react';
|
|
7
|
+
import { t } from '@molecule/app-i18n';
|
|
8
|
+
import { ThemeContext } from '../contexts.js';
|
|
9
|
+
/**
|
|
10
|
+
* Hook to access the theme provider from context.
|
|
11
|
+
*
|
|
12
|
+
* @returns The theme provider from context
|
|
13
|
+
* @throws {Error} Error if used outside of ThemeProvider
|
|
14
|
+
*/
|
|
15
|
+
export function useThemeProvider() {
|
|
16
|
+
const provider = useContext(ThemeContext);
|
|
17
|
+
if (!provider) {
|
|
18
|
+
throw new Error(t('react.error.useThemeOutsideProvider', undefined, {
|
|
19
|
+
defaultValue: 'useThemeProvider must be used within a ThemeProvider',
|
|
20
|
+
}));
|
|
21
|
+
}
|
|
22
|
+
return provider;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Subscribe to a theme provider, supporting both `subscribe` and `onThemeChange` methods.
|
|
26
|
+
* @param provider - The ThemeProvider instance to subscribe to.
|
|
27
|
+
* @param callback - Listener invoked whenever the active theme changes.
|
|
28
|
+
* @returns An unsubscribe function that removes the listener.
|
|
29
|
+
*/
|
|
30
|
+
function subscribeToThemeProvider(provider, callback) {
|
|
31
|
+
if (typeof provider.subscribe === 'function') {
|
|
32
|
+
return provider.subscribe(callback);
|
|
33
|
+
}
|
|
34
|
+
if (typeof provider
|
|
35
|
+
.onThemeChange === 'function') {
|
|
36
|
+
return provider.onThemeChange(callback);
|
|
37
|
+
}
|
|
38
|
+
return () => { };
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Hook for theme state and actions.
|
|
42
|
+
*
|
|
43
|
+
* @returns Theme state and actions
|
|
44
|
+
*
|
|
45
|
+
* @example
|
|
46
|
+
* ```tsx
|
|
47
|
+
* const { theme, themeName, setTheme, toggleTheme } = useTheme()
|
|
48
|
+
*
|
|
49
|
+
* return (
|
|
50
|
+
* <button onClick={toggleTheme}>
|
|
51
|
+
* Current theme: {themeName}
|
|
52
|
+
* </button>
|
|
53
|
+
* )
|
|
54
|
+
* ```
|
|
55
|
+
*/
|
|
56
|
+
export function useTheme() {
|
|
57
|
+
const provider = useThemeProvider();
|
|
58
|
+
const [theme, setThemeState] = useState(() => provider.getTheme());
|
|
59
|
+
const [themeName, setThemeName] = useState(() => {
|
|
60
|
+
return typeof provider
|
|
61
|
+
.getThemeName === 'function'
|
|
62
|
+
? provider.getThemeName()
|
|
63
|
+
: provider.getTheme().name;
|
|
64
|
+
});
|
|
65
|
+
useEffect(() => {
|
|
66
|
+
const unsubscribe = subscribeToThemeProvider(provider, () => {
|
|
67
|
+
setThemeState(provider.getTheme());
|
|
68
|
+
setThemeName(typeof provider
|
|
69
|
+
.getThemeName === 'function'
|
|
70
|
+
? provider.getThemeName()
|
|
71
|
+
: provider.getTheme().name);
|
|
72
|
+
});
|
|
73
|
+
return unsubscribe;
|
|
74
|
+
}, [provider]);
|
|
75
|
+
// Memoized action wrappers
|
|
76
|
+
const setTheme = useCallback((name) => provider.setTheme(name), [provider]);
|
|
77
|
+
const toggleTheme = useCallback(() => {
|
|
78
|
+
// Prefer the provider's purpose-built light/dark toggle. `toggleMode`
|
|
79
|
+
// is a required `ThemeProvider` method and the semantically correct
|
|
80
|
+
// action for a light/dark toggle — unlike `getThemes()`, which is
|
|
81
|
+
// optional, so the index-cycle below silently no-ops for providers
|
|
82
|
+
// that don't implement it. The index-cycle is kept only as a fallback
|
|
83
|
+
// for non-conforming providers that predate `toggleMode`.
|
|
84
|
+
if (typeof provider.toggleMode === 'function') {
|
|
85
|
+
provider.toggleMode();
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
const themes = provider.getThemes?.() ?? [];
|
|
89
|
+
if (themes.length === 0)
|
|
90
|
+
return;
|
|
91
|
+
const currentName = typeof provider
|
|
92
|
+
.getThemeName === 'function'
|
|
93
|
+
? provider.getThemeName()
|
|
94
|
+
: provider.getTheme().name;
|
|
95
|
+
const currentIndex = themes.findIndex((t) => typeof t === 'string' ? t === currentName : t.name === currentName);
|
|
96
|
+
const nextIndex = (currentIndex + 1) % themes.length;
|
|
97
|
+
const next = themes[nextIndex];
|
|
98
|
+
provider.setTheme(typeof next === 'string' ? next : next.name);
|
|
99
|
+
}, [provider]);
|
|
100
|
+
return {
|
|
101
|
+
theme,
|
|
102
|
+
themeName,
|
|
103
|
+
setTheme,
|
|
104
|
+
toggleTheme,
|
|
105
|
+
mode: theme.mode,
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Hook to get just the current theme object.
|
|
110
|
+
*
|
|
111
|
+
* @returns The current theme
|
|
112
|
+
*/
|
|
113
|
+
export function useCurrentTheme() {
|
|
114
|
+
const { theme } = useTheme();
|
|
115
|
+
return theme;
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Hook to get just the theme mode (light/dark).
|
|
119
|
+
*
|
|
120
|
+
* @returns The current theme mode
|
|
121
|
+
*/
|
|
122
|
+
export function useThemeMode() {
|
|
123
|
+
const { mode } = useTheme();
|
|
124
|
+
return mode;
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Hook to get theme colors.
|
|
128
|
+
*
|
|
129
|
+
* @returns The current theme colors
|
|
130
|
+
*/
|
|
131
|
+
export function useThemeColors() {
|
|
132
|
+
const { theme } = useTheme();
|
|
133
|
+
return theme.colors;
|
|
134
|
+
}
|
|
135
|
+
//# sourceMappingURL=useTheme.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useTheme.js","sourceRoot":"","sources":["../../src/hooks/useTheme.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* React hook for internationalization.
|
|
3
|
+
*
|
|
4
|
+
* @module
|
|
5
|
+
*/
|
|
6
|
+
import type { I18nProvider } from '@molecule/app-i18n';
|
|
7
|
+
import type { UseTranslationResult } from '../types.js';
|
|
8
|
+
/**
|
|
9
|
+
* Hook to access the i18n provider from context.
|
|
10
|
+
*
|
|
11
|
+
* @returns The i18n provider from context
|
|
12
|
+
* @throws {Error} Error if used outside of I18nProvider
|
|
13
|
+
*/
|
|
14
|
+
export declare function useI18nProvider(): I18nProvider;
|
|
15
|
+
/**
|
|
16
|
+
* Hook for internationalization.
|
|
17
|
+
*
|
|
18
|
+
* @returns Translation function and locale management
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```tsx
|
|
22
|
+
* const { t, locale, setLocale, formatNumber } = useTranslation()
|
|
23
|
+
*
|
|
24
|
+
* return (
|
|
25
|
+
* <div>
|
|
26
|
+
* <h1>{t('welcome.title', { name: 'User' })}</h1>
|
|
27
|
+
* <p>{formatNumber(1234.56, { style: 'currency', currency: 'USD' })}</p>
|
|
28
|
+
* <select value={locale} onChange={(e) => setLocale(e.target.value)}>
|
|
29
|
+
* <option value="en">English</option>
|
|
30
|
+
* <option value="es">Spanish</option>
|
|
31
|
+
* </select>
|
|
32
|
+
* </div>
|
|
33
|
+
* )
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
export declare function useTranslation(): UseTranslationResult;
|
|
37
|
+
/**
|
|
38
|
+
* Hook to get just the translation function.
|
|
39
|
+
*
|
|
40
|
+
* @returns The translation function
|
|
41
|
+
*/
|
|
42
|
+
export declare function useT(): I18nProvider['t'];
|
|
43
|
+
/**
|
|
44
|
+
* Hook to get the current locale.
|
|
45
|
+
*
|
|
46
|
+
* @returns The current locale code
|
|
47
|
+
*/
|
|
48
|
+
export declare function useLocale(): string;
|
|
49
|
+
/**
|
|
50
|
+
* Hook to get the text direction.
|
|
51
|
+
*
|
|
52
|
+
* @returns The text direction ('ltr' or 'rtl')
|
|
53
|
+
*/
|
|
54
|
+
export declare function useDirection(): 'ltr' | 'rtl';
|
|
55
|
+
/**
|
|
56
|
+
* Translates an error at render time so the displayed message updates automatically
|
|
57
|
+
* when the locale changes.
|
|
58
|
+
*
|
|
59
|
+
* **Always use this hook to display errors in React components** — accessing
|
|
60
|
+
* `error.message` directly bypasses re-translation and leaves stale text after a
|
|
61
|
+
* locale switch. If `error` is an `I18nError` (thrown via `throw new I18nError(key)`),
|
|
62
|
+
* its key is translated using the current locale. For plain `Error` instances,
|
|
63
|
+
* `error.message` is returned unchanged.
|
|
64
|
+
*
|
|
65
|
+
* @param error - The error to translate, or `null`/`undefined`.
|
|
66
|
+
* @returns The translated error string, or `null` if no error.
|
|
67
|
+
*/
|
|
68
|
+
export declare function useI18nError(error: Error | null | undefined): string | null;
|
|
69
|
+
//# sourceMappingURL=useTranslation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useTranslation.d.ts","sourceRoot":"","sources":["../../src/hooks/useTranslation.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,KAAK,EAEV,YAAY,EAGb,MAAM,oBAAoB,CAAA;AAI3B,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAA;AAEvD;;;;;GAKG;AACH,wBAAgB,eAAe,IAAI,YAAY,CAU9C;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,cAAc,IAAI,oBAAoB,CAqDrD;AAED;;;;GAIG;AACH,wBAAgB,IAAI,IAAI,YAAY,CAAC,GAAG,CAAC,CAUxC;AAED;;;;GAIG;AACH,wBAAgB,SAAS,IAAI,MAAM,CAGlC;AAED;;;;GAIG;AACH,wBAAgB,YAAY,IAAI,KAAK,GAAG,KAAK,CAG5C;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,GAAG,IAAI,CAW3E"}
|