@simplysm/solid 13.0.0-beta.28 → 13.0.0-beta.29
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 +18 -12
- package/dist/hooks/{useLocalConfig.d.ts → useLocalStorage.d.ts} +6 -4
- package/dist/hooks/useLocalStorage.d.ts.map +1 -0
- package/dist/hooks/{useLocalConfig.js → useLocalStorage.js} +9 -6
- package/dist/hooks/useLocalStorage.js.map +7 -0
- package/dist/hooks/useLogger.d.ts.map +1 -1
- package/dist/hooks/useLogger.js +6 -25
- package/dist/hooks/useLogger.js.map +2 -2
- package/dist/hooks/useSyncConfig.d.ts.map +1 -1
- package/dist/hooks/useSyncConfig.js +7 -6
- package/dist/hooks/useSyncConfig.js.map +2 -2
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/providers/ConfigContext.d.ts +4 -3
- package/dist/providers/ConfigContext.d.ts.map +1 -1
- package/dist/providers/ConfigContext.js.map +2 -2
- package/dist/providers/InitializeProvider.d.ts +1 -0
- package/dist/providers/InitializeProvider.d.ts.map +1 -1
- package/dist/providers/InitializeProvider.js +19 -1
- package/dist/providers/InitializeProvider.js.map +2 -2
- package/dist/providers/shared-data/SharedDataProvider.d.ts.map +1 -1
- package/dist/providers/shared-data/SharedDataProvider.js +3 -0
- package/dist/providers/shared-data/SharedDataProvider.js.map +2 -2
- package/package.json +3 -3
- package/dist/configs/LogConfig.d.ts +0 -9
- package/dist/configs/LogConfig.d.ts.map +0 -1
- package/dist/configs/LogConfig.js +0 -5
- package/dist/configs/LogConfig.js.map +0 -7
- package/dist/hooks/useLocalConfig.d.ts.map +0 -1
- package/dist/hooks/useLocalConfig.js.map +0 -7
package/README.md
CHANGED
|
@@ -37,7 +37,7 @@ export default {
|
|
|
37
37
|
|
|
38
38
|
### Provider Setup
|
|
39
39
|
|
|
40
|
-
Wrap your app root with `InitializeProvider`. It automatically sets up all required providers internally: configuration context, theme (dark/light/system), notification system with banner, loading overlay, and programmatic dialog support.
|
|
40
|
+
Wrap your app root with `InitializeProvider`. It automatically sets up all required providers internally: configuration context, theme (dark/light/system), notification system with banner, global error capturing (window.onerror, unhandledrejection), loading overlay, and programmatic dialog support.
|
|
41
41
|
|
|
42
42
|
```tsx
|
|
43
43
|
import { InitializeProvider } from "@simplysm/solid";
|
|
@@ -74,7 +74,7 @@ interface StorageAdapter {
|
|
|
74
74
|
|
|
75
75
|
```typescript
|
|
76
76
|
interface LogAdapter {
|
|
77
|
-
write(severity: "error" | "warn" | "log", ...data: any[]): Promise<void> | void;
|
|
77
|
+
write(severity: "error" | "warn" | "info" | "log", ...data: any[]): Promise<void> | void;
|
|
78
78
|
}
|
|
79
79
|
```
|
|
80
80
|
|
|
@@ -1780,14 +1780,14 @@ theme.cycleMode(); // light -> system -> dark -> light
|
|
|
1780
1780
|
|
|
1781
1781
|
---
|
|
1782
1782
|
|
|
1783
|
-
###
|
|
1783
|
+
### useLocalStorage
|
|
1784
1784
|
|
|
1785
|
-
Local-only persistent
|
|
1785
|
+
Local-only persistent storage hook. Always uses `localStorage` regardless of `syncStorage` setting. Keys are automatically prefixed as `{clientName}.{key}`. Use for data that should never leave the device (auth tokens, device-specific state).
|
|
1786
1786
|
|
|
1787
1787
|
```tsx
|
|
1788
|
-
import {
|
|
1788
|
+
import { useLocalStorage } from "@simplysm/solid";
|
|
1789
1789
|
|
|
1790
|
-
const [token, setToken] =
|
|
1790
|
+
const [token, setToken] = useLocalStorage<string | undefined>("auth-token", undefined);
|
|
1791
1791
|
```
|
|
1792
1792
|
|
|
1793
1793
|
| Return value | Type | Description |
|
|
@@ -1799,7 +1799,7 @@ const [token, setToken] = useLocalConfig<string | undefined>("auth-token", undef
|
|
|
1799
1799
|
|
|
1800
1800
|
### useSyncConfig
|
|
1801
1801
|
|
|
1802
|
-
Syncable config hook. Uses `syncStorage` if configured, falls back to `localStorage` otherwise. Keys are automatically
|
|
1802
|
+
Syncable config hook. Uses `syncStorage` if configured, falls back to `localStorage` otherwise. Keys are automatically prefixed as `{clientName}.{key}`. Use for user preferences that should sync across devices (theme, DataSheet column configs, filter presets).
|
|
1803
1803
|
|
|
1804
1804
|
```tsx
|
|
1805
1805
|
import { useSyncConfig } from "@simplysm/solid";
|
|
@@ -1820,20 +1820,26 @@ const [theme, setTheme, loading] = useSyncConfig("theme", "light");
|
|
|
1820
1820
|
|
|
1821
1821
|
### useLogger
|
|
1822
1822
|
|
|
1823
|
-
Logging hook.
|
|
1823
|
+
Logging hook. If `logger` adapter is configured in `AppConfig`, logs are sent to the adapter only. Otherwise, logs fall back to `consola`. Must be used inside `InitializeProvider`.
|
|
1824
1824
|
|
|
1825
1825
|
```tsx
|
|
1826
1826
|
import { useLogger } from "@simplysm/solid";
|
|
1827
1827
|
|
|
1828
1828
|
const logger = useLogger();
|
|
1829
|
-
logger.
|
|
1830
|
-
logger.
|
|
1831
|
-
logger.
|
|
1829
|
+
logger.log("user action", { userId: 123 });
|
|
1830
|
+
logger.info("app started");
|
|
1831
|
+
logger.error("something failed", errorObj);
|
|
1832
|
+
logger.warn("deprecation notice");
|
|
1832
1833
|
```
|
|
1833
1834
|
|
|
1834
1835
|
| Method | Signature | Description |
|
|
1835
1836
|
|--------|-----------|-------------|
|
|
1836
|
-
| `
|
|
1837
|
+
| `log` | `(...args: unknown[]) => void` | Log message (general) |
|
|
1838
|
+
| `info` | `(...args: unknown[]) => void` | Log message (informational) |
|
|
1839
|
+
| `warn` | `(...args: unknown[]) => void` | Log message (warning) |
|
|
1840
|
+
| `error` | `(...args: unknown[]) => void` | Log message (error) |
|
|
1841
|
+
|
|
1842
|
+
**Global error capturing:** `InitializeProvider` automatically captures uncaught errors (`window.onerror`) and unhandled promise rejections (`unhandledrejection`) and logs them via `useLogger`. No additional setup required.
|
|
1837
1843
|
|
|
1838
1844
|
---
|
|
1839
1845
|
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { type Accessor, type Setter } from "solid-js";
|
|
2
2
|
/**
|
|
3
|
-
* localStorage 기반
|
|
3
|
+
* localStorage 기반 저장소 훅.
|
|
4
4
|
* syncStorage 설정과 무관하게 항상 localStorage를 사용한다.
|
|
5
5
|
* 기기별로 독립적으로 유지되어야 하는 데이터(인증 토큰, 기기별 상태 등)에 사용한다.
|
|
6
6
|
*
|
|
7
|
+
* 키는 ConfigContext의 `clientName`으로 자동 prefix된다. (`${clientName}.${key}`)
|
|
8
|
+
*
|
|
7
9
|
* @template T - 저장할 값의 타입
|
|
8
10
|
* @param key - localStorage 키
|
|
9
11
|
* @param initialValue - 초기값 (옵셔널)
|
|
@@ -11,7 +13,7 @@ import { type Accessor, type Setter } from "solid-js";
|
|
|
11
13
|
*
|
|
12
14
|
* @example
|
|
13
15
|
* ```tsx
|
|
14
|
-
* const [token, setToken] =
|
|
16
|
+
* const [token, setToken] = useLocalStorage<string>("auth-token");
|
|
15
17
|
*
|
|
16
18
|
* // 값 설정
|
|
17
19
|
* setToken("abc123");
|
|
@@ -23,5 +25,5 @@ import { type Accessor, type Setter } from "solid-js";
|
|
|
23
25
|
* setToken(undefined);
|
|
24
26
|
* ```
|
|
25
27
|
*/
|
|
26
|
-
export declare function
|
|
27
|
-
//# sourceMappingURL=
|
|
28
|
+
export declare function useLocalStorage<T>(key: string, initialValue?: T): [Accessor<T | undefined>, Setter<T | undefined>];
|
|
29
|
+
//# sourceMappingURL=useLocalStorage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useLocalStorage.d.ts","sourceRoot":"","sources":["../../src/hooks/useLocalStorage.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,QAAQ,EAAE,KAAK,MAAM,EAAgB,MAAM,UAAU,CAAC;AAGpE;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,eAAe,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,GAAG,SAAS,CAAC,EAAE,MAAM,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC,CAsClH"}
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import { createSignal } from "solid-js";
|
|
2
|
-
|
|
2
|
+
import { useConfig } from "../providers/ConfigContext.js";
|
|
3
|
+
function useLocalStorage(key, initialValue) {
|
|
4
|
+
const config = useConfig();
|
|
5
|
+
const prefixedKey = `${config.clientName}.${key}`;
|
|
3
6
|
let storedValue = initialValue;
|
|
4
7
|
try {
|
|
5
|
-
const item = localStorage.getItem(
|
|
8
|
+
const item = localStorage.getItem(prefixedKey);
|
|
6
9
|
if (item !== null) {
|
|
7
10
|
storedValue = JSON.parse(item);
|
|
8
11
|
}
|
|
@@ -19,15 +22,15 @@ function useLocalConfig(key, initialValue) {
|
|
|
19
22
|
setValue(() => newValue);
|
|
20
23
|
}
|
|
21
24
|
if (resolved === void 0) {
|
|
22
|
-
localStorage.removeItem(
|
|
25
|
+
localStorage.removeItem(prefixedKey);
|
|
23
26
|
} else {
|
|
24
|
-
localStorage.setItem(
|
|
27
|
+
localStorage.setItem(prefixedKey, JSON.stringify(resolved));
|
|
25
28
|
}
|
|
26
29
|
return resolved;
|
|
27
30
|
};
|
|
28
31
|
return [value, setAndStore];
|
|
29
32
|
}
|
|
30
33
|
export {
|
|
31
|
-
|
|
34
|
+
useLocalStorage
|
|
32
35
|
};
|
|
33
|
-
//# sourceMappingURL=
|
|
36
|
+
//# sourceMappingURL=useLocalStorage.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/hooks/useLocalStorage.ts"],
|
|
4
|
+
"sourcesContent": ["import { type Accessor, type Setter, createSignal } from \"solid-js\";\nimport { useConfig } from \"../providers/ConfigContext\";\n\n/**\n * localStorage \uAE30\uBC18 \uC800\uC7A5\uC18C \uD6C5.\n * syncStorage \uC124\uC815\uACFC \uBB34\uAD00\uD558\uAC8C \uD56D\uC0C1 localStorage\uB97C \uC0AC\uC6A9\uD55C\uB2E4.\n * \uAE30\uAE30\uBCC4\uB85C \uB3C5\uB9BD\uC801\uC73C\uB85C \uC720\uC9C0\uB418\uC5B4\uC57C \uD558\uB294 \uB370\uC774\uD130(\uC778\uC99D \uD1A0\uD070, \uAE30\uAE30\uBCC4 \uC0C1\uD0DC \uB4F1)\uC5D0 \uC0AC\uC6A9\uD55C\uB2E4.\n *\n * \uD0A4\uB294 ConfigContext\uC758 `clientName`\uC73C\uB85C \uC790\uB3D9 prefix\uB41C\uB2E4. (`${clientName}.${key}`)\n *\n * @template T - \uC800\uC7A5\uD560 \uAC12\uC758 \uD0C0\uC785\n * @param key - localStorage \uD0A4\n * @param initialValue - \uCD08\uAE30\uAC12 (\uC635\uC154\uB110)\n * @returns [Accessor<T | undefined>, Setter<T | undefined>] \uD29C\uD50C\n *\n * @example\n * ```tsx\n * const [token, setToken] = useLocalStorage<string>(\"auth-token\");\n *\n * // \uAC12 \uC124\uC815\n * setToken(\"abc123\");\n *\n * // \uAC12 \uC77D\uAE30\n * console.log(token()); // \"abc123\"\n *\n * // \uAC12 \uC81C\uAC70\n * setToken(undefined);\n * ```\n */\nexport function useLocalStorage<T>(key: string, initialValue?: T): [Accessor<T | undefined>, Setter<T | undefined>] {\n const config = useConfig();\n const prefixedKey = `${config.clientName}.${key}`;\n\n // localStorage\uC5D0\uC11C \uCD08\uAE30\uAC12 \uC77D\uAE30\n let storedValue: T | undefined = initialValue;\n try {\n const item = localStorage.getItem(prefixedKey);\n if (item !== null) {\n storedValue = JSON.parse(item) as T;\n }\n } catch {\n // JSON \uD30C\uC2F1 \uC2E4\uD328 \uC2DC \uCD08\uAE30\uAC12 \uC0AC\uC6A9\n }\n\n const [value, setValue] = createSignal<T | undefined>(storedValue);\n\n const setAndStore = (newValue: T | undefined | ((prev: T | undefined) => T | undefined)) => {\n let resolved: T | undefined;\n\n if (typeof newValue === \"function\") {\n resolved = (newValue as (prev: T | undefined) => T | undefined)(value());\n setValue(() => resolved);\n } else {\n resolved = newValue;\n setValue(() => newValue);\n }\n\n if (resolved === undefined) {\n localStorage.removeItem(prefixedKey);\n } else {\n localStorage.setItem(prefixedKey, JSON.stringify(resolved));\n }\n\n return resolved;\n };\n\n return [value, setAndStore as Setter<T | undefined>];\n}\n"],
|
|
5
|
+
"mappings": "AAAA,SAAqC,oBAAoB;AACzD,SAAS,iBAAiB;AA4BnB,SAAS,gBAAmB,KAAa,cAAoE;AAClH,QAAM,SAAS,UAAU;AACzB,QAAM,cAAc,GAAG,OAAO,UAAU,IAAI,GAAG;AAG/C,MAAI,cAA6B;AACjC,MAAI;AACF,UAAM,OAAO,aAAa,QAAQ,WAAW;AAC7C,QAAI,SAAS,MAAM;AACjB,oBAAc,KAAK,MAAM,IAAI;AAAA,IAC/B;AAAA,EACF,QAAQ;AAAA,EAER;AAEA,QAAM,CAAC,OAAO,QAAQ,IAAI,aAA4B,WAAW;AAEjE,QAAM,cAAc,CAAC,aAAuE;AAC1F,QAAI;AAEJ,QAAI,OAAO,aAAa,YAAY;AAClC,iBAAY,SAAoD,MAAM,CAAC;AACvE,eAAS,MAAM,QAAQ;AAAA,IACzB,OAAO;AACL,iBAAW;AACX,eAAS,MAAM,QAAQ;AAAA,IACzB;AAEA,QAAI,aAAa,QAAW;AAC1B,mBAAa,WAAW,WAAW;AAAA,IACrC,OAAO;AACL,mBAAa,QAAQ,aAAa,KAAK,UAAU,QAAQ,CAAC;AAAA,IAC5D;AAEA,WAAO;AAAA,EACT;AAEA,SAAO,CAAC,OAAO,WAAoC;AACrD;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useLogger.d.ts","sourceRoot":"","sources":["../../src/hooks/useLogger.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"useLogger.d.ts","sourceRoot":"","sources":["../../src/hooks/useLogger.ts"],"names":[],"mappings":"AAKA,UAAU,MAAM;IACd,GAAG,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;IAClC,IAAI,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;IACnC,IAAI,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;IACnC,KAAK,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;CACrC;AAED,wBAAgB,SAAS,IAAI,MAAM,CAmBlC"}
|
package/dist/hooks/useLogger.js
CHANGED
|
@@ -1,32 +1,13 @@
|
|
|
1
1
|
import { consola } from "consola";
|
|
2
|
-
import {
|
|
2
|
+
import { useConfig } from "../providers/ConfigContext.js";
|
|
3
3
|
function useLogger() {
|
|
4
|
+
const config = useConfig();
|
|
4
5
|
const createLogFunction = (level) => {
|
|
5
6
|
return (...args) => {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
if (typeof arg === "string") {
|
|
11
|
-
return arg;
|
|
12
|
-
}
|
|
13
|
-
if (arg == null) {
|
|
14
|
-
return String(arg);
|
|
15
|
-
}
|
|
16
|
-
try {
|
|
17
|
-
return JSON.stringify(arg);
|
|
18
|
-
} catch {
|
|
19
|
-
return String(arg);
|
|
20
|
-
}
|
|
21
|
-
}).join(" ");
|
|
22
|
-
LogAdapter.write({
|
|
23
|
-
level,
|
|
24
|
-
message,
|
|
25
|
-
timestamp: Date.now()
|
|
26
|
-
});
|
|
27
|
-
} catch (err) {
|
|
28
|
-
consola.error("Failed to write log to adapter:", err);
|
|
29
|
-
}
|
|
7
|
+
if (config.logger) {
|
|
8
|
+
void config.logger.write(level, ...args);
|
|
9
|
+
} else {
|
|
10
|
+
consola[level](...args);
|
|
30
11
|
}
|
|
31
12
|
};
|
|
32
13
|
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/hooks/useLogger.ts"],
|
|
4
|
-
"sourcesContent": ["import { consola } from \"consola\";\nimport {
|
|
5
|
-
"mappings": "AAAA,SAAS,eAAe;AACxB,SAAS,
|
|
4
|
+
"sourcesContent": ["import { consola } from \"consola\";\nimport { useConfig, type LogAdapter } from \"../providers/ConfigContext\";\n\ntype LogLevel = Parameters<LogAdapter[\"write\"]>[0];\n\ninterface Logger {\n log: (...args: unknown[]) => void;\n info: (...args: unknown[]) => void;\n warn: (...args: unknown[]) => void;\n error: (...args: unknown[]) => void;\n}\n\nexport function useLogger(): Logger {\n const config = useConfig();\n\n const createLogFunction = (level: LogLevel) => {\n return (...args: unknown[]) => {\n if (config.logger) {\n void config.logger.write(level, ...args);\n } else {\n (consola as any)[level](...args);\n }\n };\n };\n\n return {\n log: createLogFunction(\"log\"),\n info: createLogFunction(\"info\"),\n warn: createLogFunction(\"warn\"),\n error: createLogFunction(\"error\"),\n };\n}\n"],
|
|
5
|
+
"mappings": "AAAA,SAAS,eAAe;AACxB,SAAS,iBAAkC;AAWpC,SAAS,YAAoB;AAClC,QAAM,SAAS,UAAU;AAEzB,QAAM,oBAAoB,CAAC,UAAoB;AAC7C,WAAO,IAAI,SAAoB;AAC7B,UAAI,OAAO,QAAQ;AACjB,aAAK,OAAO,OAAO,MAAM,OAAO,GAAG,IAAI;AAAA,MACzC,OAAO;AACL,QAAC,QAAgB,KAAK,EAAE,GAAG,IAAI;AAAA,MACjC;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AAAA,IACL,KAAK,kBAAkB,KAAK;AAAA,IAC5B,MAAM,kBAAkB,MAAM;AAAA,IAC9B,MAAM,kBAAkB,MAAM;AAAA,IAC9B,OAAO,kBAAkB,OAAO;AAAA,EAClC;AACF;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useSyncConfig.d.ts","sourceRoot":"","sources":["../../src/hooks/useSyncConfig.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,QAAQ,EAAE,KAAK,MAAM,EAAyC,MAAM,UAAU,CAAC;AAG7F;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,YAAY,EAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAC,
|
|
1
|
+
{"version":3,"file":"useSyncConfig.d.ts","sourceRoot":"","sources":["../../src/hooks/useSyncConfig.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,QAAQ,EAAE,KAAK,MAAM,EAAyC,MAAM,UAAU,CAAC;AAG7F;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,YAAY,EAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAC,CA0E1G"}
|
|
@@ -2,12 +2,13 @@ import { createEffect, createSignal, onCleanup } from "solid-js";
|
|
|
2
2
|
import { useConfig } from "../providers/ConfigContext.js";
|
|
3
3
|
function useSyncConfig(key, defaultValue) {
|
|
4
4
|
const config = useConfig();
|
|
5
|
+
const prefixedKey = `${config.clientName}.${key}`;
|
|
5
6
|
const [value, setValue] = createSignal(defaultValue);
|
|
6
7
|
const [loading, setLoading] = createSignal(false);
|
|
7
8
|
const initializeFromStorage = async () => {
|
|
8
9
|
if (!config.syncStorage) {
|
|
9
10
|
try {
|
|
10
|
-
const stored = localStorage.getItem(
|
|
11
|
+
const stored = localStorage.getItem(prefixedKey);
|
|
11
12
|
if (stored !== null) {
|
|
12
13
|
setValue(() => JSON.parse(stored));
|
|
13
14
|
}
|
|
@@ -17,13 +18,13 @@ function useSyncConfig(key, defaultValue) {
|
|
|
17
18
|
}
|
|
18
19
|
setLoading(true);
|
|
19
20
|
try {
|
|
20
|
-
const stored = await config.syncStorage.getItem(
|
|
21
|
+
const stored = await config.syncStorage.getItem(prefixedKey);
|
|
21
22
|
if (stored !== null) {
|
|
22
23
|
setValue(() => JSON.parse(stored));
|
|
23
24
|
}
|
|
24
25
|
} catch {
|
|
25
26
|
try {
|
|
26
|
-
const stored = localStorage.getItem(
|
|
27
|
+
const stored = localStorage.getItem(prefixedKey);
|
|
27
28
|
if (stored !== null) {
|
|
28
29
|
setValue(() => JSON.parse(stored));
|
|
29
30
|
}
|
|
@@ -38,14 +39,14 @@ function useSyncConfig(key, defaultValue) {
|
|
|
38
39
|
const currentValue = value();
|
|
39
40
|
const serialized = JSON.stringify(currentValue);
|
|
40
41
|
if (!config.syncStorage) {
|
|
41
|
-
localStorage.setItem(
|
|
42
|
+
localStorage.setItem(prefixedKey, serialized);
|
|
42
43
|
return;
|
|
43
44
|
}
|
|
44
45
|
void (async () => {
|
|
45
46
|
try {
|
|
46
|
-
await config.syncStorage.setItem(
|
|
47
|
+
await config.syncStorage.setItem(prefixedKey, serialized);
|
|
47
48
|
} catch {
|
|
48
|
-
localStorage.setItem(
|
|
49
|
+
localStorage.setItem(prefixedKey, serialized);
|
|
49
50
|
}
|
|
50
51
|
})();
|
|
51
52
|
});
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/hooks/useSyncConfig.ts"],
|
|
4
|
-
"sourcesContent": ["import { type Accessor, type Setter, createEffect, createSignal, onCleanup } from \"solid-js\";\nimport { useConfig } from \"../providers/ConfigContext\";\n\n/**\n * Creates a reactive signal that syncs configuration data to storage.\n *\n * Uses `syncStorage` from ConfigProvider if available, otherwise falls back to `localStorage`.\n * Designed for data that should persist and sync across devices (e.g., theme, user preferences, DataSheet configs).\n *\n * @param key - Storage key for the config value\n * @param defaultValue - Default value if no stored value exists\n * @returns Tuple of [value accessor, value setter, loading state accessor]\n *\n * @example\n * ```tsx\n * const [theme, setTheme, loading] = useSyncConfig(\"user-theme\", \"light\");\n *\n * <Show when={!loading()}>\n * <button onClick={() => setTheme(theme() === \"light\" ? \"dark\" : \"light\")}>\n * Toggle theme\n * </button>\n * </Show>\n * ```\n */\nexport function useSyncConfig<T>(key: string, defaultValue: T): [Accessor<T>, Setter<T>, Accessor<boolean>] {\n const config = useConfig();\n const [value, setValue] = createSignal<T>(defaultValue);\n const [loading, setLoading] = createSignal(false);\n\n // Initialize from storage\n const initializeFromStorage = async () => {\n if (!config.syncStorage) {\n // Use localStorage synchronously\n try {\n const stored = localStorage.getItem(
|
|
5
|
-
"mappings": "AAAA,SAAqC,cAAc,cAAc,iBAAiB;AAClF,SAAS,iBAAiB;AAuBnB,SAAS,cAAiB,KAAa,cAA8D;AAC1G,QAAM,SAAS,UAAU;AACzB,QAAM,CAAC,OAAO,QAAQ,IAAI,aAAgB,YAAY;AACtD,QAAM,CAAC,SAAS,UAAU,IAAI,aAAa,KAAK;AAGhD,QAAM,wBAAwB,YAAY;AACxC,QAAI,CAAC,OAAO,aAAa;AAEvB,UAAI;AACF,cAAM,SAAS,aAAa,QAAQ,
|
|
4
|
+
"sourcesContent": ["import { type Accessor, type Setter, createEffect, createSignal, onCleanup } from \"solid-js\";\nimport { useConfig } from \"../providers/ConfigContext\";\n\n/**\n * Creates a reactive signal that syncs configuration data to storage.\n *\n * Uses `syncStorage` from ConfigProvider if available, otherwise falls back to `localStorage`.\n * Designed for data that should persist and sync across devices (e.g., theme, user preferences, DataSheet configs).\n *\n * @param key - Storage key for the config value\n * @param defaultValue - Default value if no stored value exists\n * @returns Tuple of [value accessor, value setter, loading state accessor]\n *\n * @example\n * ```tsx\n * const [theme, setTheme, loading] = useSyncConfig(\"user-theme\", \"light\");\n *\n * <Show when={!loading()}>\n * <button onClick={() => setTheme(theme() === \"light\" ? \"dark\" : \"light\")}>\n * Toggle theme\n * </button>\n * </Show>\n * ```\n */\nexport function useSyncConfig<T>(key: string, defaultValue: T): [Accessor<T>, Setter<T>, Accessor<boolean>] {\n const config = useConfig();\n const prefixedKey = `${config.clientName}.${key}`;\n const [value, setValue] = createSignal<T>(defaultValue);\n const [loading, setLoading] = createSignal(false);\n\n // Initialize from storage\n const initializeFromStorage = async () => {\n if (!config.syncStorage) {\n // Use localStorage synchronously\n try {\n const stored = localStorage.getItem(prefixedKey);\n if (stored !== null) {\n setValue(() => JSON.parse(stored) as T);\n }\n } catch {\n // Ignore parse errors, keep default value\n }\n return;\n }\n\n // Use syncStorage asynchronously\n setLoading(true);\n try {\n const stored = await config.syncStorage.getItem(prefixedKey);\n if (stored !== null) {\n setValue(() => JSON.parse(stored) as T);\n }\n } catch {\n // Fall back to localStorage on error\n try {\n const stored = localStorage.getItem(prefixedKey);\n if (stored !== null) {\n setValue(() => JSON.parse(stored) as T);\n }\n } catch {\n // Ignore parse errors\n }\n } finally {\n setLoading(false);\n }\n };\n\n // Initialize on mount\n void initializeFromStorage();\n\n // Save to storage whenever value changes\n createEffect(() => {\n const currentValue = value();\n const serialized = JSON.stringify(currentValue);\n\n if (!config.syncStorage) {\n // Use localStorage synchronously\n localStorage.setItem(prefixedKey, serialized);\n return;\n }\n\n // Use syncStorage asynchronously\n void (async () => {\n try {\n await config.syncStorage!.setItem(prefixedKey, serialized);\n } catch {\n // Fall back to localStorage on error\n localStorage.setItem(prefixedKey, serialized);\n }\n })();\n });\n\n // Clean up (optional, for consistency)\n onCleanup(() => {\n // No cleanup needed for storage operations\n });\n\n return [value, setValue, loading];\n}\n"],
|
|
5
|
+
"mappings": "AAAA,SAAqC,cAAc,cAAc,iBAAiB;AAClF,SAAS,iBAAiB;AAuBnB,SAAS,cAAiB,KAAa,cAA8D;AAC1G,QAAM,SAAS,UAAU;AACzB,QAAM,cAAc,GAAG,OAAO,UAAU,IAAI,GAAG;AAC/C,QAAM,CAAC,OAAO,QAAQ,IAAI,aAAgB,YAAY;AACtD,QAAM,CAAC,SAAS,UAAU,IAAI,aAAa,KAAK;AAGhD,QAAM,wBAAwB,YAAY;AACxC,QAAI,CAAC,OAAO,aAAa;AAEvB,UAAI;AACF,cAAM,SAAS,aAAa,QAAQ,WAAW;AAC/C,YAAI,WAAW,MAAM;AACnB,mBAAS,MAAM,KAAK,MAAM,MAAM,CAAM;AAAA,QACxC;AAAA,MACF,QAAQ;AAAA,MAER;AACA;AAAA,IACF;AAGA,eAAW,IAAI;AACf,QAAI;AACF,YAAM,SAAS,MAAM,OAAO,YAAY,QAAQ,WAAW;AAC3D,UAAI,WAAW,MAAM;AACnB,iBAAS,MAAM,KAAK,MAAM,MAAM,CAAM;AAAA,MACxC;AAAA,IACF,QAAQ;AAEN,UAAI;AACF,cAAM,SAAS,aAAa,QAAQ,WAAW;AAC/C,YAAI,WAAW,MAAM;AACnB,mBAAS,MAAM,KAAK,MAAM,MAAM,CAAM;AAAA,QACxC;AAAA,MACF,QAAQ;AAAA,MAER;AAAA,IACF,UAAE;AACA,iBAAW,KAAK;AAAA,IAClB;AAAA,EACF;AAGA,OAAK,sBAAsB;AAG3B,eAAa,MAAM;AACjB,UAAM,eAAe,MAAM;AAC3B,UAAM,aAAa,KAAK,UAAU,YAAY;AAE9C,QAAI,CAAC,OAAO,aAAa;AAEvB,mBAAa,QAAQ,aAAa,UAAU;AAC5C;AAAA,IACF;AAGA,UAAM,YAAY;AAChB,UAAI;AACF,cAAM,OAAO,YAAa,QAAQ,aAAa,UAAU;AAAA,MAC3D,QAAQ;AAEN,qBAAa,QAAQ,aAAa,UAAU;AAAA,MAC9C;AAAA,IACF,GAAG;AAAA,EACL,CAAC;AAGD,YAAU,MAAM;AAAA,EAEhB,CAAC;AAED,SAAO,CAAC,OAAO,UAAU,OAAO;AAClC;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -70,7 +70,7 @@ export * from "./providers/ServiceClientProvider";
|
|
|
70
70
|
export * from "./providers/shared-data/SharedDataContext";
|
|
71
71
|
export * from "./providers/shared-data/SharedDataProvider";
|
|
72
72
|
export * from "./providers/shared-data/SharedDataChangeEvent";
|
|
73
|
-
export * from "./hooks/
|
|
73
|
+
export * from "./hooks/useLocalStorage";
|
|
74
74
|
export * from "./hooks/useSyncConfig";
|
|
75
75
|
export * from "./hooks/useLogger";
|
|
76
76
|
export * from "./hooks/usePrint";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,kCAAkC,CAAC;AACjD,cAAc,yCAAyC,CAAC;AACxD,cAAc,gDAAgD,CAAC;AAC/D,cAAc,6CAA6C,CAAC;AAC5D,cAAc,oDAAoD,CAAC;AACnE,cAAc,2CAA2C,CAAC;AAC1D,cAAc,6CAA6C,CAAC;AAC5D,cAAc,4CAA4C,CAAC;AAC3D,cAAc,gDAAgD,CAAC;AAC/D,cAAc,4CAA4C,CAAC;AAC3D,cAAc,0CAA0C,CAAC;AACzD,cAAc,8CAA8C,CAAC;AAC7D,cAAc,6CAA6C,CAAC;AAC5D,cAAc,oDAAoD,CAAC;AACnE,cAAc,0CAA0C,CAAC;AACzD,cAAc,kDAAkD,CAAC;AACjE,cAAc,+CAA+C,CAAC;AAC9D,cAAc,oDAAoD,CAAC;AACnE,cAAc,6DAA6D,CAAC;AAC5E,cAAc,iDAAiD,CAAC;AAChE,cAAc,yCAAyC,CAAC;AACxD,cAAc,oDAAoD,CAAC;AACnE,cAAc,uCAAuC,CAAC;AAGtD,cAAc,+BAA+B,CAAC;AAC9C,cAAc,+BAA+B,CAAC;AAC9C,cAAc,qCAAqC,CAAC;AACpD,cAAc,4CAA4C,CAAC;AAC3D,cAAc,mCAAmC,CAAC;AAGlD,cAAc,yBAAyB,CAAC;AACxC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,oCAAoC,CAAC;AACnD,cAAc,wCAAwC,CAAC;AACvD,cAAc,8BAA8B,CAAC;AAC7C,cAAc,mCAAmC,CAAC;AAClD,cAAc,0CAA0C,CAAC;AACzD,cAAc,+BAA+B,CAAC;AAC9C,cAAc,qCAAqC,CAAC;AACpD,cAAc,oDAAoD,CAAC;AACnE,cAAc,iCAAiC,CAAC;AAChD,cAAc,wCAAwC,CAAC;AAGvD,cAAc,8BAA8B,CAAC;AAC7C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,0BAA0B,CAAC;AACzC,cAAc,4BAA4B,CAAC;AAG3C,cAAc,kCAAkC,CAAC;AACjD,cAAc,kCAAkC,CAAC;AACjD,cAAc,gCAAgC,CAAC;AAC/C,cAAc,uCAAuC,CAAC;AACtD,cAAc,+CAA+C,CAAC;AAC9D,cAAc,wCAAwC,CAAC;AACvD,cAAc,8BAA8B,CAAC;AAG7C,cAAc,wDAAwD,CAAC;AACvE,cAAc,qDAAqD,CAAC;AACpE,cAAc,yDAAyD,CAAC;AACxE,cAAc,uDAAuD,CAAC;AAGtE,cAAc,8CAA8C,CAAC;AAC7D,cAAc,gDAAgD,CAAC;AAC/D,cAAc,+CAA+C,CAAC;AAG9D,cAAc,mCAAmC,CAAC;AAClD,cAAc,kDAAkD,CAAC;AACjE,cAAc,gCAAgC,CAAC;AAG/C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,gCAAgC,CAAC;AAC/C,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACpD,YAAY,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AACzE,cAAc,kCAAkC,CAAC;AACjD,cAAc,mCAAmC,CAAC;AAClD,cAAc,2CAA2C,CAAC;AAC1D,cAAc,4CAA4C,CAAC;AAC3D,cAAc,+CAA+C,CAAC;AAG9D,cAAc,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -69,7 +69,7 @@ export * from "./providers/ServiceClientProvider.js";
|
|
|
69
69
|
export * from "./providers/shared-data/SharedDataContext.js";
|
|
70
70
|
export * from "./providers/shared-data/SharedDataProvider.js";
|
|
71
71
|
export * from "./providers/shared-data/SharedDataChangeEvent.js";
|
|
72
|
-
export * from "./hooks/
|
|
72
|
+
export * from "./hooks/useLocalStorage.js";
|
|
73
73
|
export * from "./hooks/useSyncConfig.js";
|
|
74
74
|
export * from "./hooks/useLogger.js";
|
|
75
75
|
export * from "./hooks/usePrint.js";
|
package/dist/index.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/index.ts"],
|
|
4
|
-
"sourcesContent": ["// form-control\nexport * from \"./components/form-control/Button\";\nexport * from \"./components/form-control/select/Select\";\nexport * from \"./components/form-control/select/SelectContext\";\nexport * from \"./components/form-control/combobox/Combobox\";\nexport * from \"./components/form-control/combobox/ComboboxContext\";\nexport * from \"./components/form-control/field/TextInput\";\nexport * from \"./components/form-control/field/NumberInput\";\nexport * from \"./components/form-control/field/DatePicker\";\nexport * from \"./components/form-control/field/DateTimePicker\";\nexport * from \"./components/form-control/field/TimePicker\";\nexport * from \"./components/form-control/field/Textarea\";\nexport * from \"./components/form-control/field/Field.styles\";\nexport * from \"./components/form-control/checkbox/Checkbox\";\nexport * from \"./components/form-control/checkbox/Checkbox.styles\";\nexport * from \"./components/form-control/checkbox/Radio\";\nexport * from \"./components/form-control/checkbox/CheckboxGroup\";\nexport * from \"./components/form-control/checkbox/RadioGroup\";\nexport * from \"./components/form-control/color-picker/ColorPicker\";\nexport * from \"./components/form-control/date-range-picker/DateRangePicker\";\nexport * from \"./components/form-control/editor/RichTextEditor\";\nexport * from \"./components/form-control/numpad/Numpad\";\nexport * from \"./components/form-control/state-preset/StatePreset\";\nexport * from \"./components/form-control/ThemeToggle\";\n\n// layout\nexport * from \"./components/layout/FormGroup\";\nexport * from \"./components/layout/FormTable\";\nexport * from \"./components/layout/sidebar/Sidebar\";\nexport * from \"./components/layout/sidebar/SidebarContext\";\nexport * from \"./components/layout/topbar/Topbar\";\n\n// data\nexport * from \"./components/data/Table\";\nexport * from \"./components/data/list/List\";\nexport * from \"./components/data/list/ListContext\";\nexport * from \"./components/data/list/ListItem.styles\";\nexport * from \"./components/data/Pagination\";\nexport * from \"./components/data/sheet/DataSheet\";\nexport * from \"./components/data/sheet/DataSheet.styles\";\nexport * from \"./components/data/sheet/types\";\nexport * from \"./components/data/calendar/Calendar\";\nexport * from \"./components/data/permission-table/PermissionTable\";\nexport * from \"./components/data/kanban/Kanban\";\nexport * from \"./components/data/kanban/KanbanContext\";\n\n// display\nexport * from \"./components/display/Barcode\";\nexport * from \"./components/display/Card\";\nexport * from \"./components/display/Echarts\";\nexport * from \"./components/display/Icon\";\nexport * from \"./components/display/Tag\";\nexport * from \"./components/display/Alert\";\n\n// disclosure\nexport * from \"./components/disclosure/Collapse\";\nexport * from \"./components/disclosure/Dropdown\";\nexport * from \"./components/disclosure/Dialog\";\nexport * from \"./components/disclosure/DialogContext\";\nexport * from \"./components/disclosure/DialogInstanceContext\";\nexport * from \"./components/disclosure/DialogProvider\";\nexport * from \"./components/disclosure/Tabs\";\n\n// feedback\nexport * from \"./components/feedback/notification/NotificationContext\";\nexport * from \"./components/feedback/notification/NotificationBell\";\nexport * from \"./components/feedback/notification/NotificationProvider\";\nexport * from \"./components/feedback/notification/NotificationBanner\";\n\n// feedback - loading\nexport * from \"./components/feedback/loading/LoadingContext\";\nexport * from \"./components/feedback/loading/LoadingContainer\";\nexport * from \"./components/feedback/loading/LoadingProvider\";\n\n// feedback - print\nexport * from \"./components/feedback/print/Print\";\nexport * from \"./components/feedback/print/PrintInstanceContext\";\nexport * from \"./components/feedback/Progress\";\n\n// providers\nexport * from \"./providers/ConfigContext\";\nexport * from \"./providers/InitializeProvider\";\nexport { useTheme } from \"./providers/ThemeContext\";\nexport type { ThemeMode, ResolvedTheme } from \"./providers/ThemeContext\";\nexport * from \"./providers/ServiceClientContext\";\nexport * from \"./providers/ServiceClientProvider\";\nexport * from \"./providers/shared-data/SharedDataContext\";\nexport * from \"./providers/shared-data/SharedDataProvider\";\nexport * from \"./providers/shared-data/SharedDataChangeEvent\";\n\n// hooks\nexport * from \"./hooks/
|
|
4
|
+
"sourcesContent": ["// form-control\nexport * from \"./components/form-control/Button\";\nexport * from \"./components/form-control/select/Select\";\nexport * from \"./components/form-control/select/SelectContext\";\nexport * from \"./components/form-control/combobox/Combobox\";\nexport * from \"./components/form-control/combobox/ComboboxContext\";\nexport * from \"./components/form-control/field/TextInput\";\nexport * from \"./components/form-control/field/NumberInput\";\nexport * from \"./components/form-control/field/DatePicker\";\nexport * from \"./components/form-control/field/DateTimePicker\";\nexport * from \"./components/form-control/field/TimePicker\";\nexport * from \"./components/form-control/field/Textarea\";\nexport * from \"./components/form-control/field/Field.styles\";\nexport * from \"./components/form-control/checkbox/Checkbox\";\nexport * from \"./components/form-control/checkbox/Checkbox.styles\";\nexport * from \"./components/form-control/checkbox/Radio\";\nexport * from \"./components/form-control/checkbox/CheckboxGroup\";\nexport * from \"./components/form-control/checkbox/RadioGroup\";\nexport * from \"./components/form-control/color-picker/ColorPicker\";\nexport * from \"./components/form-control/date-range-picker/DateRangePicker\";\nexport * from \"./components/form-control/editor/RichTextEditor\";\nexport * from \"./components/form-control/numpad/Numpad\";\nexport * from \"./components/form-control/state-preset/StatePreset\";\nexport * from \"./components/form-control/ThemeToggle\";\n\n// layout\nexport * from \"./components/layout/FormGroup\";\nexport * from \"./components/layout/FormTable\";\nexport * from \"./components/layout/sidebar/Sidebar\";\nexport * from \"./components/layout/sidebar/SidebarContext\";\nexport * from \"./components/layout/topbar/Topbar\";\n\n// data\nexport * from \"./components/data/Table\";\nexport * from \"./components/data/list/List\";\nexport * from \"./components/data/list/ListContext\";\nexport * from \"./components/data/list/ListItem.styles\";\nexport * from \"./components/data/Pagination\";\nexport * from \"./components/data/sheet/DataSheet\";\nexport * from \"./components/data/sheet/DataSheet.styles\";\nexport * from \"./components/data/sheet/types\";\nexport * from \"./components/data/calendar/Calendar\";\nexport * from \"./components/data/permission-table/PermissionTable\";\nexport * from \"./components/data/kanban/Kanban\";\nexport * from \"./components/data/kanban/KanbanContext\";\n\n// display\nexport * from \"./components/display/Barcode\";\nexport * from \"./components/display/Card\";\nexport * from \"./components/display/Echarts\";\nexport * from \"./components/display/Icon\";\nexport * from \"./components/display/Tag\";\nexport * from \"./components/display/Alert\";\n\n// disclosure\nexport * from \"./components/disclosure/Collapse\";\nexport * from \"./components/disclosure/Dropdown\";\nexport * from \"./components/disclosure/Dialog\";\nexport * from \"./components/disclosure/DialogContext\";\nexport * from \"./components/disclosure/DialogInstanceContext\";\nexport * from \"./components/disclosure/DialogProvider\";\nexport * from \"./components/disclosure/Tabs\";\n\n// feedback\nexport * from \"./components/feedback/notification/NotificationContext\";\nexport * from \"./components/feedback/notification/NotificationBell\";\nexport * from \"./components/feedback/notification/NotificationProvider\";\nexport * from \"./components/feedback/notification/NotificationBanner\";\n\n// feedback - loading\nexport * from \"./components/feedback/loading/LoadingContext\";\nexport * from \"./components/feedback/loading/LoadingContainer\";\nexport * from \"./components/feedback/loading/LoadingProvider\";\n\n// feedback - print\nexport * from \"./components/feedback/print/Print\";\nexport * from \"./components/feedback/print/PrintInstanceContext\";\nexport * from \"./components/feedback/Progress\";\n\n// providers\nexport * from \"./providers/ConfigContext\";\nexport * from \"./providers/InitializeProvider\";\nexport { useTheme } from \"./providers/ThemeContext\";\nexport type { ThemeMode, ResolvedTheme } from \"./providers/ThemeContext\";\nexport * from \"./providers/ServiceClientContext\";\nexport * from \"./providers/ServiceClientProvider\";\nexport * from \"./providers/shared-data/SharedDataContext\";\nexport * from \"./providers/shared-data/SharedDataProvider\";\nexport * from \"./providers/shared-data/SharedDataChangeEvent\";\n\n// hooks\nexport * from \"./hooks/useLocalStorage\";\nexport * from \"./hooks/useSyncConfig\";\nexport * from \"./hooks/useLogger\";\nexport * from \"./hooks/usePrint\";\nexport { createControllableSignal } from \"./hooks/createControllableSignal\";\nexport { createIMEHandler } from \"./hooks/createIMEHandler\";\nexport { createMountTransition } from \"./hooks/createMountTransition\";\nexport { createPwaUpdate } from \"./hooks/createPwaUpdate\";\nexport { useRouterLink } from \"./hooks/useRouterLink\";\n\n// styles\nexport * from \"./styles/tokens.styles\";\nexport * from \"./styles/patterns.styles\";\n\n// directives\nexport { ripple } from \"./directives/ripple\";\n\n// helpers\nexport { mergeStyles } from \"./helpers/mergeStyles\";\nexport { splitSlots } from \"./helpers/splitSlots\";\nexport { createAppStructure } from \"./helpers/createAppStructure\";\nexport type {\n AppStructureItem,\n AppStructureGroupItem,\n AppStructureLeafItem,\n AppStructureSubPerm,\n AppRoute,\n AppFlatMenu,\n AppStructure,\n} from \"./helpers/createAppStructure\";\n"],
|
|
5
5
|
"mappings": "AACA,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AAGd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AAGd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AAGd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AAGd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AAGd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AAGd,cAAc;AACd,cAAc;AACd,cAAc;AAGd,cAAc;AACd,cAAc;AACd,cAAc;AAGd,cAAc;AACd,cAAc;AACd,SAAS,gBAAgB;AAEzB,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AAGd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,SAAS,gCAAgC;AACzC,SAAS,wBAAwB;AACjC,SAAS,6BAA6B;AACtC,SAAS,uBAAuB;AAChC,SAAS,qBAAqB;AAG9B,cAAc;AACd,cAAc;AAGd,SAAS,cAAc;AAGvB,SAAS,mBAAmB;AAC5B,SAAS,kBAAkB;AAC3B,SAAS,0BAA0B;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -14,10 +14,11 @@ export interface StorageAdapter {
|
|
|
14
14
|
* 로그 어댑터 인터페이스
|
|
15
15
|
*
|
|
16
16
|
* @remarks
|
|
17
|
-
* - `useLogger`에서
|
|
17
|
+
* - `useLogger`에서 사용하는 로그 전송 어댑터 (DB, 서버 등)
|
|
18
|
+
* - adapter가 설정되면 consola 대신 adapter만 사용됨
|
|
18
19
|
*/
|
|
19
20
|
export interface LogAdapter {
|
|
20
|
-
write(severity: "error" | "warn" | "log", ...data: any[]): Promise<void> | void;
|
|
21
|
+
write(severity: "error" | "warn" | "info" | "log", ...data: any[]): Promise<void> | void;
|
|
21
22
|
}
|
|
22
23
|
/**
|
|
23
24
|
* 앱 전역 설정
|
|
@@ -28,7 +29,7 @@ export interface AppConfig {
|
|
|
28
29
|
*/
|
|
29
30
|
clientName: string;
|
|
30
31
|
/**
|
|
31
|
-
* 동기화 가능 저장소 (useSyncConfig에서 사용,
|
|
32
|
+
* 동기화 가능 저장소 (useSyncConfig에서 사용, 없으면 localStorage로 fallback)
|
|
32
33
|
*/
|
|
33
34
|
syncStorage?: StorageAdapter;
|
|
34
35
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ConfigContext.d.ts","sourceRoot":"","sources":["../../src/providers/ConfigContext.ts"],"names":[],"mappings":"AAEA;;;;;;GAMG;AACH,MAAM,WAAW,cAAc;IAC7B,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAC7D,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC7D,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC/C;AAED
|
|
1
|
+
{"version":3,"file":"ConfigContext.d.ts","sourceRoot":"","sources":["../../src/providers/ConfigContext.ts"],"names":[],"mappings":"AAEA;;;;;;GAMG;AACH,MAAM,WAAW,cAAc;IAC7B,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAC7D,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC7D,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC/C;AAED;;;;;;GAMG;AACH,MAAM,WAAW,UAAU;IACzB,KAAK,CAAC,QAAQ,EAAE,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,KAAK,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;CAC1F;AAED;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB;;OAEG;IACH,UAAU,EAAE,MAAM,CAAC;IAEnB;;OAEG;IACH,WAAW,CAAC,EAAE,cAAc,CAAC;IAE7B;;OAEG;IACH,MAAM,CAAC,EAAE,UAAU,CAAC;IAEpB;;OAEG;IACH,cAAc,CAAC,EAAE,SAAS,GAAG,KAAK,CAAC;CACpC;AAED;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,aAAa,mDAA6B,CAAC;AAExD;;;;GAIG;AACH,wBAAgB,SAAS,IAAI,SAAS,CAMrC"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/providers/ConfigContext.ts"],
|
|
4
|
-
"sourcesContent": ["import { createContext, useContext } from \"solid-js\";\n\n/**\n * \uCEE4\uC2A4\uD140 \uC800\uC7A5\uC18C \uC5B4\uB311\uD130 \uC778\uD130\uD398\uC774\uC2A4\n *\n * @remarks\n * - \uB3D9\uAE30 \uC800\uC7A5\uC18C: `localStorage`, `sessionStorage` \uB4F1 \uADF8\uB300\uB85C \uC804\uB2EC \uAC00\uB2A5\n * - \uBE44\uB3D9\uAE30 \uC800\uC7A5\uC18C: `getItem`\uC774 `Promise`\uB97C \uBC18\uD658\uD558\uB294 \uAD6C\uD604\uCCB4 \uC804\uB2EC\n */\nexport interface StorageAdapter {\n getItem(key: string): string | null | Promise<string | null>;\n setItem(key: string, value: string): void | Promise<unknown>;\n removeItem(key: string): void | Promise<void>;\n}\n\n/**\n * \uB85C\uADF8 \uC5B4\uB311\uD130 \uC778\uD130\uD398\uC774\uC2A4\n *\n * @remarks\n * - `useLogger`\uC5D0\uC11C
|
|
5
|
-
"mappings": "AAAA,SAAS,eAAe,kBAAkB;
|
|
4
|
+
"sourcesContent": ["import { createContext, useContext } from \"solid-js\";\n\n/**\n * \uCEE4\uC2A4\uD140 \uC800\uC7A5\uC18C \uC5B4\uB311\uD130 \uC778\uD130\uD398\uC774\uC2A4\n *\n * @remarks\n * - \uB3D9\uAE30 \uC800\uC7A5\uC18C: `localStorage`, `sessionStorage` \uB4F1 \uADF8\uB300\uB85C \uC804\uB2EC \uAC00\uB2A5\n * - \uBE44\uB3D9\uAE30 \uC800\uC7A5\uC18C: `getItem`\uC774 `Promise`\uB97C \uBC18\uD658\uD558\uB294 \uAD6C\uD604\uCCB4 \uC804\uB2EC\n */\nexport interface StorageAdapter {\n getItem(key: string): string | null | Promise<string | null>;\n setItem(key: string, value: string): void | Promise<unknown>;\n removeItem(key: string): void | Promise<void>;\n}\n\n/**\n * \uB85C\uADF8 \uC5B4\uB311\uD130 \uC778\uD130\uD398\uC774\uC2A4\n *\n * @remarks\n * - `useLogger`\uC5D0\uC11C \uC0AC\uC6A9\uD558\uB294 \uB85C\uADF8 \uC804\uC1A1 \uC5B4\uB311\uD130 (DB, \uC11C\uBC84 \uB4F1)\n * - adapter\uAC00 \uC124\uC815\uB418\uBA74 consola \uB300\uC2E0 adapter\uB9CC \uC0AC\uC6A9\uB428\n */\nexport interface LogAdapter {\n write(severity: \"error\" | \"warn\" | \"info\" | \"log\", ...data: any[]): Promise<void> | void;\n}\n\n/**\n * \uC571 \uC804\uC5ED \uC124\uC815\n */\nexport interface AppConfig {\n /**\n * \uD074\uB77C\uC774\uC5B8\uD2B8 \uC2DD\uBCC4\uC790 (\uC800\uC7A5\uC18C key prefix\uB85C \uC0AC\uC6A9)\n */\n clientName: string;\n\n /**\n * \uB3D9\uAE30\uD654 \uAC00\uB2A5 \uC800\uC7A5\uC18C (useSyncConfig\uC5D0\uC11C \uC0AC\uC6A9, \uC5C6\uC73C\uBA74 localStorage\uB85C fallback)\n */\n syncStorage?: StorageAdapter;\n\n /**\n * \uB85C\uADF8 \uC5B4\uB311\uD130 (useLogger\uC5D0\uC11C consola \uC678 \uCD94\uAC00 \uC804\uC1A1\uC5D0 \uC0AC\uC6A9)\n */\n logger?: LogAdapter;\n\n /**\n * \uB8E8\uD2B8 \uB85C\uB529 \uC624\uBC84\uB808\uC774 \uBCC0\uD615 (\uAE30\uBCF8\uAC12: \"spinner\")\n */\n loadingVariant?: \"spinner\" | \"bar\";\n}\n\n/**\n * \uC571 \uC804\uC5ED \uC124\uC815 Context\n *\n * @example\n * ```tsx\n * // \uC571 \uB8E8\uD2B8\uC5D0\uC11C Provider \uC124\uC815\n * <ConfigContext.Provider value={{ clientName: \"myApp\" }}>\n * <App />\n * </ConfigContext.Provider>\n *\n * // \uCEF4\uD3EC\uB10C\uD2B8\uC5D0\uC11C \uC0AC\uC6A9\n * const config = useConfig();\n * console.log(config.clientName); // \"myApp\"\n * ```\n */\nexport const ConfigContext = createContext<AppConfig>();\n\n/**\n * \uC571 \uC804\uC5ED \uC124\uC815\uC5D0 \uC811\uADFC\uD558\uB294 \uD6C5\n *\n * @throws ConfigContext.Provider\uAC00 \uC5C6\uC73C\uBA74 \uC5D0\uB7EC \uBC1C\uC0DD\n */\nexport function useConfig(): AppConfig {\n const context = useContext(ConfigContext);\n if (!context) {\n throw new Error(\"useConfig\uB294 ConfigContext.Provider \uB0B4\uBD80\uC5D0\uC11C\uB9CC \uC0AC\uC6A9\uD560 \uC218 \uC788\uC2B5\uB2C8\uB2E4\");\n }\n return context;\n}\n"],
|
|
5
|
+
"mappings": "AAAA,SAAS,eAAe,kBAAkB;AAkEnC,MAAM,gBAAgB,cAAyB;AAO/C,SAAS,YAAuB;AACrC,QAAM,UAAU,WAAW,aAAa;AACxC,MAAI,CAAC,SAAS;AACZ,UAAM,IAAI,MAAM,0HAAoD;AAAA,EACtE;AACA,SAAO;AACT;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InitializeProvider.d.ts","sourceRoot":"","sources":["../../src/providers/InitializeProvider.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"InitializeProvider.d.ts","sourceRoot":"","sources":["../../src/providers/InitializeProvider.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAEhD,OAAO,EAAE,KAAK,SAAS,EAAiB,MAAM,iBAAiB,CAAC;AAuChE;;;;;;;;;;;;;;;;;;;GAmBG;AACH,eAAO,MAAM,kBAAkB,EAAE,eAAe,CAAC;IAAE,MAAM,EAAE,SAAS,CAAA;CAAE,CAoBrE,CAAC"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { onCleanup } from "solid-js";
|
|
1
2
|
import { ConfigContext } from "./ConfigContext.js";
|
|
2
3
|
import { useClipboardValueCopy } from "../hooks/useClipboardValueCopy.js";
|
|
3
4
|
import { ThemeProvider } from "./ThemeContext.js";
|
|
@@ -6,13 +7,30 @@ import { NotificationBanner } from "../components/feedback/notification/Notifica
|
|
|
6
7
|
import { LoadingProvider } from "../components/feedback/loading/LoadingProvider.js";
|
|
7
8
|
import { DialogProvider } from "../components/disclosure/DialogProvider.js";
|
|
8
9
|
import { createPwaUpdate } from "../hooks/createPwaUpdate.js";
|
|
10
|
+
import { useLogger } from "../hooks/useLogger.js";
|
|
9
11
|
function PwaUpdater() {
|
|
10
12
|
createPwaUpdate();
|
|
11
13
|
return null;
|
|
12
14
|
}
|
|
15
|
+
function GlobalErrorLogger() {
|
|
16
|
+
const logger = useLogger();
|
|
17
|
+
const onError = (event) => {
|
|
18
|
+
logger.error("Uncaught error:", event.error ?? event.message);
|
|
19
|
+
};
|
|
20
|
+
const onUnhandledRejection = (event) => {
|
|
21
|
+
logger.error("Unhandled rejection:", event.reason);
|
|
22
|
+
};
|
|
23
|
+
window.addEventListener("error", onError);
|
|
24
|
+
window.addEventListener("unhandledrejection", onUnhandledRejection);
|
|
25
|
+
onCleanup(() => {
|
|
26
|
+
window.removeEventListener("error", onError);
|
|
27
|
+
window.removeEventListener("unhandledrejection", onUnhandledRejection);
|
|
28
|
+
});
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
13
31
|
const InitializeProvider = (props) => {
|
|
14
32
|
useClipboardValueCopy();
|
|
15
|
-
return /* @__PURE__ */ React.createElement(ConfigContext.Provider, { value: props.config }, /* @__PURE__ */ React.createElement(ThemeProvider, null, /* @__PURE__ */ React.createElement(NotificationProvider, null, /* @__PURE__ */ React.createElement(NotificationBanner, null), /* @__PURE__ */ React.createElement(PwaUpdater, null), /* @__PURE__ */ React.createElement(LoadingProvider, { variant: props.config.loadingVariant }, /* @__PURE__ */ React.createElement(DialogProvider, null, props.children)))));
|
|
33
|
+
return /* @__PURE__ */ React.createElement(ConfigContext.Provider, { value: props.config }, /* @__PURE__ */ React.createElement(ThemeProvider, null, /* @__PURE__ */ React.createElement(NotificationProvider, null, /* @__PURE__ */ React.createElement(NotificationBanner, null), /* @__PURE__ */ React.createElement(GlobalErrorLogger, null), /* @__PURE__ */ React.createElement(PwaUpdater, null), /* @__PURE__ */ React.createElement(LoadingProvider, { variant: props.config.loadingVariant }, /* @__PURE__ */ React.createElement(DialogProvider, null, props.children)))));
|
|
16
34
|
};
|
|
17
35
|
export {
|
|
18
36
|
InitializeProvider
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/providers/InitializeProvider.tsx"],
|
|
4
|
-
"sourcesContent": ["import type { ParentComponent } from \"solid-js\";\nimport { type AppConfig, ConfigContext } from \"./ConfigContext\";\nimport { useClipboardValueCopy } from \"../hooks/useClipboardValueCopy\";\nimport { ThemeProvider } from \"./ThemeContext\";\nimport { NotificationProvider } from \"../components/feedback/notification/NotificationProvider\";\nimport { NotificationBanner } from \"../components/feedback/notification/NotificationBanner\";\nimport { LoadingProvider } from \"../components/feedback/loading/LoadingProvider\";\nimport { DialogProvider } from \"../components/disclosure/DialogProvider\";\nimport { createPwaUpdate } from \"../hooks/createPwaUpdate\";\n\n/** Runs PWA update detection inside NotificationProvider context */\nfunction PwaUpdater() {\n createPwaUpdate();\n return null;\n}\n\n/**\n * @simplysm/solid \uCD08\uAE30\uD654 Provider\n *\n * @remarks\n * \uC571 \uB8E8\uD2B8\uC5D0\uC11C \uD55C \uBC88 \uAC10\uC2F8\uBA70, \uB2E4\uC74C\uC744 \uCD08\uAE30\uD654\uD55C\uB2E4:\n * - \uC571 \uC804\uC5ED \uC124\uC815 (config) Context \uC81C\uACF5\n * - \uD3FC \uCEE8\uD2B8\uB864 value \uD074\uB9BD\uBCF4\uB4DC \uBCF5\uC0AC \uC9C0\uC6D0\n * - \uD14C\uB9C8 (\uB77C\uC774\uD2B8/\uB2E4\uD06C/\uC2DC\uC2A4\uD15C)\n * - \uC54C\uB9BC \uC2DC\uC2A4\uD15C + \uBC30\uB108\n * - \uB8E8\uD2B8 \uB85C\uB529 \uC624\uBC84\uB808\uC774\n * - \uD504\uB85C\uADF8\uB798\uB9E4\uD2F1 \uB2E4\uC774\uC5BC\uB85C\uADF8\n *\n * @example\n * ```tsx\n * <InitializeProvider config={{ clientName: \"myApp\" }}>\n * <App />\n * </InitializeProvider>\n * ```\n */\nexport const InitializeProvider: ParentComponent<{ config: AppConfig }> = (props) => {\n // \uD3FC \uCEE8\uD2B8\uB864 value \uD074\uB9BD\uBCF4\uB4DC \uBCF5\uC0AC\n useClipboardValueCopy();\n\n /* eslint-disable solid/reactivity -- config\uB294 \uCD08\uAE30 \uC124\uC815\uAC12\uC73C\uB85C \uBCC0\uACBD\uB418\uC9C0 \uC54A\uC74C */\n return (\n <ConfigContext.Provider value={props.config}>\n <ThemeProvider>\n <NotificationProvider>\n <NotificationBanner />\n <PwaUpdater />\n <LoadingProvider variant={props.config.loadingVariant}>\n <DialogProvider>{props.children}</DialogProvider>\n </LoadingProvider>\n </NotificationProvider>\n </ThemeProvider>\n </ConfigContext.Provider>\n );\n /* eslint-enable solid/reactivity */\n};\n"],
|
|
5
|
-
"mappings": "AACA,SAAyB,qBAAqB;AAC9C,SAAS,6BAA6B;AACtC,SAAS,qBAAqB;AAC9B,SAAS,4BAA4B;AACrC,SAAS,0BAA0B;AACnC,SAAS,uBAAuB;AAChC,SAAS,sBAAsB;AAC/B,SAAS,uBAAuB;
|
|
4
|
+
"sourcesContent": ["import type { ParentComponent } from \"solid-js\";\nimport { onCleanup } from \"solid-js\";\nimport { type AppConfig, ConfigContext } from \"./ConfigContext\";\nimport { useClipboardValueCopy } from \"../hooks/useClipboardValueCopy\";\nimport { ThemeProvider } from \"./ThemeContext\";\nimport { NotificationProvider } from \"../components/feedback/notification/NotificationProvider\";\nimport { NotificationBanner } from \"../components/feedback/notification/NotificationBanner\";\nimport { LoadingProvider } from \"../components/feedback/loading/LoadingProvider\";\nimport { DialogProvider } from \"../components/disclosure/DialogProvider\";\nimport { createPwaUpdate } from \"../hooks/createPwaUpdate\";\nimport { useLogger } from \"../hooks/useLogger\";\n\n/** Runs PWA update detection inside NotificationProvider context */\nfunction PwaUpdater() {\n createPwaUpdate();\n return null;\n}\n\n/** Captures uncaught errors and unhandled rejections via useLogger */\nfunction GlobalErrorLogger() {\n const logger = useLogger();\n\n const onError = (event: ErrorEvent) => {\n logger.error(\"Uncaught error:\", event.error ?? event.message);\n };\n\n const onUnhandledRejection = (event: PromiseRejectionEvent) => {\n logger.error(\"Unhandled rejection:\", event.reason);\n };\n\n window.addEventListener(\"error\", onError);\n window.addEventListener(\"unhandledrejection\", onUnhandledRejection);\n\n onCleanup(() => {\n window.removeEventListener(\"error\", onError);\n window.removeEventListener(\"unhandledrejection\", onUnhandledRejection);\n });\n\n return null;\n}\n\n/**\n * @simplysm/solid \uCD08\uAE30\uD654 Provider\n *\n * @remarks\n * \uC571 \uB8E8\uD2B8\uC5D0\uC11C \uD55C \uBC88 \uAC10\uC2F8\uBA70, \uB2E4\uC74C\uC744 \uCD08\uAE30\uD654\uD55C\uB2E4:\n * - \uC571 \uC804\uC5ED \uC124\uC815 (config) Context \uC81C\uACF5\n * - \uD3FC \uCEE8\uD2B8\uB864 value \uD074\uB9BD\uBCF4\uB4DC \uBCF5\uC0AC \uC9C0\uC6D0\n * - \uD14C\uB9C8 (\uB77C\uC774\uD2B8/\uB2E4\uD06C/\uC2DC\uC2A4\uD15C)\n * - \uC54C\uB9BC \uC2DC\uC2A4\uD15C + \uBC30\uB108\n * - \uC804\uC5ED \uC5D0\uB7EC \uCEA1\uCC98 (window.onerror, unhandledrejection)\n * - \uB8E8\uD2B8 \uB85C\uB529 \uC624\uBC84\uB808\uC774\n * - \uD504\uB85C\uADF8\uB798\uB9E4\uD2F1 \uB2E4\uC774\uC5BC\uB85C\uADF8\n *\n * @example\n * ```tsx\n * <InitializeProvider config={{ clientName: \"myApp\" }}>\n * <App />\n * </InitializeProvider>\n * ```\n */\nexport const InitializeProvider: ParentComponent<{ config: AppConfig }> = (props) => {\n // \uD3FC \uCEE8\uD2B8\uB864 value \uD074\uB9BD\uBCF4\uB4DC \uBCF5\uC0AC\n useClipboardValueCopy();\n\n /* eslint-disable solid/reactivity -- config\uB294 \uCD08\uAE30 \uC124\uC815\uAC12\uC73C\uB85C \uBCC0\uACBD\uB418\uC9C0 \uC54A\uC74C */\n return (\n <ConfigContext.Provider value={props.config}>\n <ThemeProvider>\n <NotificationProvider>\n <NotificationBanner />\n <GlobalErrorLogger />\n <PwaUpdater />\n <LoadingProvider variant={props.config.loadingVariant}>\n <DialogProvider>{props.children}</DialogProvider>\n </LoadingProvider>\n </NotificationProvider>\n </ThemeProvider>\n </ConfigContext.Provider>\n );\n /* eslint-enable solid/reactivity */\n};\n"],
|
|
5
|
+
"mappings": "AACA,SAAS,iBAAiB;AAC1B,SAAyB,qBAAqB;AAC9C,SAAS,6BAA6B;AACtC,SAAS,qBAAqB;AAC9B,SAAS,4BAA4B;AACrC,SAAS,0BAA0B;AACnC,SAAS,uBAAuB;AAChC,SAAS,sBAAsB;AAC/B,SAAS,uBAAuB;AAChC,SAAS,iBAAiB;AAG1B,SAAS,aAAa;AACpB,kBAAgB;AAChB,SAAO;AACT;AAGA,SAAS,oBAAoB;AAC3B,QAAM,SAAS,UAAU;AAEzB,QAAM,UAAU,CAAC,UAAsB;AACrC,WAAO,MAAM,mBAAmB,MAAM,SAAS,MAAM,OAAO;AAAA,EAC9D;AAEA,QAAM,uBAAuB,CAAC,UAAiC;AAC7D,WAAO,MAAM,wBAAwB,MAAM,MAAM;AAAA,EACnD;AAEA,SAAO,iBAAiB,SAAS,OAAO;AACxC,SAAO,iBAAiB,sBAAsB,oBAAoB;AAElE,YAAU,MAAM;AACd,WAAO,oBAAoB,SAAS,OAAO;AAC3C,WAAO,oBAAoB,sBAAsB,oBAAoB;AAAA,EACvE,CAAC;AAED,SAAO;AACT;AAsBO,MAAM,qBAA6D,CAAC,UAAU;AAEnF,wBAAsB;AAGtB,SACE,oCAAC,cAAc,UAAd,EAAuB,OAAO,MAAM,UACnC,oCAAC,qBACC,oCAAC,4BACC,oCAAC,wBAAmB,GACpB,oCAAC,uBAAkB,GACnB,oCAAC,gBAAW,GACZ,oCAAC,mBAAgB,SAAS,MAAM,OAAO,kBACrC,oCAAC,sBAAgB,MAAM,QAAS,CAClC,CACF,CACF,CACF;AAGJ;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SharedDataProvider.d.ts","sourceRoot":"","sources":["../../../src/providers/shared-data/SharedDataProvider.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAiB,KAAK,GAAG,EAAuC,MAAM,UAAU,CAAC;AAExF,OAAO,EAGL,KAAK,oBAAoB,EAE1B,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"SharedDataProvider.d.ts","sourceRoot":"","sources":["../../../src/providers/shared-data/SharedDataProvider.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAiB,KAAK,GAAG,EAAuC,MAAM,UAAU,CAAC;AAExF,OAAO,EAGL,KAAK,oBAAoB,EAE1B,MAAM,qBAAqB,CAAC;AAM7B,wBAAgB,kBAAkB,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,KAAK,EAAE;IAC3E,WAAW,EAAE;SAAG,CAAC,IAAI,MAAM,CAAC,GAAG,oBAAoB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;KAAE,CAAC;IAC5D,QAAQ,EAAE,GAAG,CAAC,OAAO,CAAC;CACvB,GAAG,GAAG,CAAC,OAAO,CAuId"}
|
|
@@ -6,9 +6,11 @@ import {
|
|
|
6
6
|
import { SharedDataChangeEvent } from "./SharedDataChangeEvent.js";
|
|
7
7
|
import { useServiceClient } from "../ServiceClientContext.js";
|
|
8
8
|
import { useNotification } from "../../components/feedback/notification/NotificationContext.js";
|
|
9
|
+
import { useLogger } from "../../hooks/useLogger.js";
|
|
9
10
|
function SharedDataProvider(props) {
|
|
10
11
|
const serviceClient = useServiceClient();
|
|
11
12
|
const notification = useNotification();
|
|
13
|
+
const logger = useLogger();
|
|
12
14
|
const [loadingCount, setLoadingCount] = createSignal(0);
|
|
13
15
|
const loading = () => loadingCount() > 0;
|
|
14
16
|
const signalMap = /* @__PURE__ */ new Map();
|
|
@@ -47,6 +49,7 @@ function SharedDataProvider(props) {
|
|
|
47
49
|
});
|
|
48
50
|
}
|
|
49
51
|
} catch (err) {
|
|
52
|
+
logger.error(`SharedData '${name}' fetch failed:`, err);
|
|
50
53
|
notification.danger(
|
|
51
54
|
"\uACF5\uC720 \uB370\uC774\uD130 \uB85C\uB4DC \uC2E4\uD328",
|
|
52
55
|
err instanceof Error ? err.message : `'${name}' \uB370\uC774\uD130\uB97C \uBD88\uB7EC\uC624\uB294 \uC911 \uC624\uB958\uAC00 \uBC1C\uC0DD\uD588\uC2B5\uB2C8\uB2E4.`
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/providers/shared-data/SharedDataProvider.tsx"],
|
|
4
|
-
"sourcesContent": ["import { type Accessor, type JSX, createMemo, createSignal, onCleanup } from \"solid-js\";\nimport { objEqual, waitUntil } from \"@simplysm/core-common\";\nimport {\n SharedDataContext,\n type SharedDataAccessor,\n type SharedDataDefinition,\n type SharedDataValue,\n} from \"./SharedDataContext\";\nimport { SharedDataChangeEvent } from \"./SharedDataChangeEvent\";\nimport { useServiceClient } from \"../ServiceClientContext\";\nimport { useNotification } from \"../../components/feedback/notification/NotificationContext\";\n\nexport function SharedDataProvider<T extends Record<string, unknown>>(props: {\n definitions: { [K in keyof T]: SharedDataDefinition<T[K]> };\n children: JSX.Element;\n}): JSX.Element {\n const serviceClient = useServiceClient();\n const notification = useNotification();\n\n const [loadingCount, setLoadingCount] = createSignal(0);\n const loading: Accessor<boolean> = () => loadingCount() > 0;\n\n const signalMap = new Map<string, ReturnType<typeof createSignal<unknown[]>>>();\n const memoMap = new Map<string, Accessor<Map<string | number, unknown>>>();\n const listenerKeyMap = new Map<string, string>();\n const versionMap = new Map<string, number>();\n\n function ordering<TT>(data: TT[], orderByList: [(item: TT) => unknown, \"asc\" | \"desc\"][]): TT[] {\n let result = [...data];\n for (const orderBy of [...orderByList].reverse()) {\n const selector = (item: TT) => orderBy[0](item) as string | number | undefined;\n if (orderBy[1] === \"desc\") {\n result = result.orderByDesc(selector);\n } else {\n result = result.orderBy(selector);\n }\n }\n return result;\n }\n\n async function loadData(\n name: string,\n def: SharedDataDefinition<unknown>,\n changeKeys?: Array<string | number>,\n ): Promise<void> {\n // CR-1: version counter\uB85C \uB3D9\uC2DC \uD638\uCD9C \uC2DC \uB370\uC774\uD130 \uC5ED\uC804 \uBC29\uC9C0\n const currentVersion = (versionMap.get(name) ?? 0) + 1;\n versionMap.set(name, currentVersion);\n\n setLoadingCount((c) => c + 1);\n try {\n const signal = signalMap.get(name);\n if (!signal) throw new Error(`'${name}'\uC5D0 \uB300\uD55C \uACF5\uC720\uB370\uC774\uD130 \uC800\uC7A5\uC18C\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4.`);\n\n const [, setItems] = signal;\n const resData = await def.fetch(changeKeys);\n\n // CR-1: \uC624\uB798\uB41C \uC751\uB2F5\uC740 \uBB34\uC2DC\n if (versionMap.get(name) !== currentVersion) return;\n\n if (!changeKeys) {\n setItems(ordering(resData, def.orderBy));\n } else {\n setItems((prev) => {\n const filtered = prev.filter((item) => !changeKeys.includes(def.getKey(item as never)));\n filtered.push(...resData);\n return ordering(filtered, def.orderBy);\n });\n }\n } catch (err) {\n // CR-2: fetch \uC2E4\uD328 \uC2DC \uC0AC\uC6A9\uC790\uC5D0\uAC8C \uC54C\uB9BC\n notification.danger(\n \"\uACF5\uC720 \uB370\uC774\uD130 \uB85C\uB4DC \uC2E4\uD328\",\n err instanceof Error ? err.message : `'${name}' \uB370\uC774\uD130\uB97C \uBD88\uB7EC\uC624\uB294 \uC911 \uC624\uB958\uAC00 \uBC1C\uC0DD\uD588\uC2B5\uB2C8\uB2E4.`,\n );\n } finally {\n setLoadingCount((c) => c - 1);\n }\n }\n\n async function wait(): Promise<void> {\n // eslint-disable-next-line solid/reactivity -- waitUntil\uC740 \uD3F4\uB9C1 \uAE30\uBC18\uC774\uBBC0\uB85C tracked scope \uBD88\uD544\uC694\n await waitUntil(() => loadingCount() <= 0);\n }\n\n const accessors: Record<string, SharedDataAccessor<unknown>> = {};\n\n // eslint-disable-next-line solid/reactivity -- definitions\uB294 \uCD08\uAE30 \uC124\uC815\uC6A9\uC73C\uB85C \uB9C8\uC6B4\uD2B8 \uC2DC 1\uD68C\uB9CC \uC77D\uC74C\n for (const [name, def] of Object.entries(props.definitions) as [string, SharedDataDefinition<unknown>][]) {\n const [items, setItems] = createSignal<unknown[]>([]);\n // eslint-disable-next-line solid/reactivity -- signal \uCC38\uC870\uB97C Map\uC5D0 \uC800\uC7A5\uD558\uB294 \uAC83\uC740 \uBC18\uC751\uC131 \uC811\uADFC\uC774 \uC544\uB2D8\n signalMap.set(name, [items, setItems]);\n\n const itemMap = createMemo(() => {\n const map = new Map<string | number, unknown>();\n for (const item of items()) {\n map.set(def.getKey(item as never), item);\n }\n return map;\n });\n // eslint-disable-next-line solid/reactivity -- memo \uCC38\uC870\uB97C Map\uC5D0 \uC800\uC7A5\uD558\uB294 \uAC83\uC740 \uBC18\uC751\uC131 \uC811\uADFC\uC774 \uC544\uB2D8\n memoMap.set(name, itemMap);\n\n const client = serviceClient.get(def.serviceKey);\n void client\n .addEventListener(SharedDataChangeEvent, { name, filter: def.filter }, async (changeKeys) => {\n await loadData(name, def, changeKeys);\n })\n .then((key) => {\n listenerKeyMap.set(name, key);\n });\n\n void loadData(name, def);\n\n accessors[name] = {\n items,\n get: (key: string | number | undefined) => {\n if (key === undefined) return undefined;\n return itemMap().get(key);\n },\n emit: async (changeKeys?: Array<string | number>) => {\n await client.emitToServer(\n SharedDataChangeEvent,\n (info) => info.name === name && objEqual(info.filter, def.filter),\n changeKeys,\n );\n },\n };\n }\n\n onCleanup(() => {\n for (const [name] of Object.entries(props.definitions)) {\n const listenerKey = listenerKeyMap.get(name);\n if (listenerKey != null) {\n const def = (props.definitions as Record<string, SharedDataDefinition<unknown>>)[name];\n const client = serviceClient.get(def.serviceKey);\n void client.removeEventListener(listenerKey);\n }\n }\n });\n\n const contextValue = {\n ...accessors,\n wait,\n loading,\n } as SharedDataValue<Record<string, unknown>>;\n\n return <SharedDataContext.Provider value={contextValue}>{props.children}</SharedDataContext.Provider>;\n}\n"],
|
|
5
|
-
"mappings": "AAAA,SAAkC,YAAY,cAAc,iBAAiB;AAC7E,SAAS,UAAU,iBAAiB;AACpC;AAAA,EACE;AAAA,OAIK;AACP,SAAS,6BAA6B;AACtC,SAAS,wBAAwB;AACjC,SAAS,uBAAuB;
|
|
4
|
+
"sourcesContent": ["import { type Accessor, type JSX, createMemo, createSignal, onCleanup } from \"solid-js\";\nimport { objEqual, waitUntil } from \"@simplysm/core-common\";\nimport {\n SharedDataContext,\n type SharedDataAccessor,\n type SharedDataDefinition,\n type SharedDataValue,\n} from \"./SharedDataContext\";\nimport { SharedDataChangeEvent } from \"./SharedDataChangeEvent\";\nimport { useServiceClient } from \"../ServiceClientContext\";\nimport { useNotification } from \"../../components/feedback/notification/NotificationContext\";\nimport { useLogger } from \"../../hooks/useLogger\";\n\nexport function SharedDataProvider<T extends Record<string, unknown>>(props: {\n definitions: { [K in keyof T]: SharedDataDefinition<T[K]> };\n children: JSX.Element;\n}): JSX.Element {\n const serviceClient = useServiceClient();\n const notification = useNotification();\n const logger = useLogger();\n\n const [loadingCount, setLoadingCount] = createSignal(0);\n const loading: Accessor<boolean> = () => loadingCount() > 0;\n\n const signalMap = new Map<string, ReturnType<typeof createSignal<unknown[]>>>();\n const memoMap = new Map<string, Accessor<Map<string | number, unknown>>>();\n const listenerKeyMap = new Map<string, string>();\n const versionMap = new Map<string, number>();\n\n function ordering<TT>(data: TT[], orderByList: [(item: TT) => unknown, \"asc\" | \"desc\"][]): TT[] {\n let result = [...data];\n for (const orderBy of [...orderByList].reverse()) {\n const selector = (item: TT) => orderBy[0](item) as string | number | undefined;\n if (orderBy[1] === \"desc\") {\n result = result.orderByDesc(selector);\n } else {\n result = result.orderBy(selector);\n }\n }\n return result;\n }\n\n async function loadData(\n name: string,\n def: SharedDataDefinition<unknown>,\n changeKeys?: Array<string | number>,\n ): Promise<void> {\n // CR-1: version counter\uB85C \uB3D9\uC2DC \uD638\uCD9C \uC2DC \uB370\uC774\uD130 \uC5ED\uC804 \uBC29\uC9C0\n const currentVersion = (versionMap.get(name) ?? 0) + 1;\n versionMap.set(name, currentVersion);\n\n setLoadingCount((c) => c + 1);\n try {\n const signal = signalMap.get(name);\n if (!signal) throw new Error(`'${name}'\uC5D0 \uB300\uD55C \uACF5\uC720\uB370\uC774\uD130 \uC800\uC7A5\uC18C\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4.`);\n\n const [, setItems] = signal;\n const resData = await def.fetch(changeKeys);\n\n // CR-1: \uC624\uB798\uB41C \uC751\uB2F5\uC740 \uBB34\uC2DC\n if (versionMap.get(name) !== currentVersion) return;\n\n if (!changeKeys) {\n setItems(ordering(resData, def.orderBy));\n } else {\n setItems((prev) => {\n const filtered = prev.filter((item) => !changeKeys.includes(def.getKey(item as never)));\n filtered.push(...resData);\n return ordering(filtered, def.orderBy);\n });\n }\n } catch (err) {\n // CR-2: fetch \uC2E4\uD328 \uC2DC \uC0AC\uC6A9\uC790\uC5D0\uAC8C \uC54C\uB9BC\n logger.error(`SharedData '${name}' fetch failed:`, err);\n notification.danger(\n \"\uACF5\uC720 \uB370\uC774\uD130 \uB85C\uB4DC \uC2E4\uD328\",\n err instanceof Error ? err.message : `'${name}' \uB370\uC774\uD130\uB97C \uBD88\uB7EC\uC624\uB294 \uC911 \uC624\uB958\uAC00 \uBC1C\uC0DD\uD588\uC2B5\uB2C8\uB2E4.`,\n );\n } finally {\n setLoadingCount((c) => c - 1);\n }\n }\n\n async function wait(): Promise<void> {\n // eslint-disable-next-line solid/reactivity -- waitUntil\uC740 \uD3F4\uB9C1 \uAE30\uBC18\uC774\uBBC0\uB85C tracked scope \uBD88\uD544\uC694\n await waitUntil(() => loadingCount() <= 0);\n }\n\n const accessors: Record<string, SharedDataAccessor<unknown>> = {};\n\n // eslint-disable-next-line solid/reactivity -- definitions\uB294 \uCD08\uAE30 \uC124\uC815\uC6A9\uC73C\uB85C \uB9C8\uC6B4\uD2B8 \uC2DC 1\uD68C\uB9CC \uC77D\uC74C\n for (const [name, def] of Object.entries(props.definitions) as [string, SharedDataDefinition<unknown>][]) {\n const [items, setItems] = createSignal<unknown[]>([]);\n // eslint-disable-next-line solid/reactivity -- signal \uCC38\uC870\uB97C Map\uC5D0 \uC800\uC7A5\uD558\uB294 \uAC83\uC740 \uBC18\uC751\uC131 \uC811\uADFC\uC774 \uC544\uB2D8\n signalMap.set(name, [items, setItems]);\n\n const itemMap = createMemo(() => {\n const map = new Map<string | number, unknown>();\n for (const item of items()) {\n map.set(def.getKey(item as never), item);\n }\n return map;\n });\n // eslint-disable-next-line solid/reactivity -- memo \uCC38\uC870\uB97C Map\uC5D0 \uC800\uC7A5\uD558\uB294 \uAC83\uC740 \uBC18\uC751\uC131 \uC811\uADFC\uC774 \uC544\uB2D8\n memoMap.set(name, itemMap);\n\n const client = serviceClient.get(def.serviceKey);\n void client\n .addEventListener(SharedDataChangeEvent, { name, filter: def.filter }, async (changeKeys) => {\n await loadData(name, def, changeKeys);\n })\n .then((key) => {\n listenerKeyMap.set(name, key);\n });\n\n void loadData(name, def);\n\n accessors[name] = {\n items,\n get: (key: string | number | undefined) => {\n if (key === undefined) return undefined;\n return itemMap().get(key);\n },\n emit: async (changeKeys?: Array<string | number>) => {\n await client.emitToServer(\n SharedDataChangeEvent,\n (info) => info.name === name && objEqual(info.filter, def.filter),\n changeKeys,\n );\n },\n };\n }\n\n onCleanup(() => {\n for (const [name] of Object.entries(props.definitions)) {\n const listenerKey = listenerKeyMap.get(name);\n if (listenerKey != null) {\n const def = (props.definitions as Record<string, SharedDataDefinition<unknown>>)[name];\n const client = serviceClient.get(def.serviceKey);\n void client.removeEventListener(listenerKey);\n }\n }\n });\n\n const contextValue = {\n ...accessors,\n wait,\n loading,\n } as SharedDataValue<Record<string, unknown>>;\n\n return <SharedDataContext.Provider value={contextValue}>{props.children}</SharedDataContext.Provider>;\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@simplysm/solid",
|
|
3
|
-
"version": "13.0.0-beta.
|
|
3
|
+
"version": "13.0.0-beta.29",
|
|
4
4
|
"description": "심플리즘 패키지 - SolidJS 라이브러리",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -44,8 +44,8 @@
|
|
|
44
44
|
"solid-tiptap": "^0.8.0",
|
|
45
45
|
"tailwind-merge": "^3.4.0",
|
|
46
46
|
"tailwindcss": "^3.4.19",
|
|
47
|
-
"@simplysm/core-browser": "13.0.0-beta.
|
|
48
|
-
"@simplysm/core-common": "13.0.0-beta.
|
|
47
|
+
"@simplysm/core-browser": "13.0.0-beta.29",
|
|
48
|
+
"@simplysm/core-common": "13.0.0-beta.29"
|
|
49
49
|
},
|
|
50
50
|
"devDependencies": {
|
|
51
51
|
"@solidjs/testing-library": "^0.8.10"
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"LogConfig.d.ts","sourceRoot":"","sources":["../../src/configs/LogConfig.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,KAAK,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;IACzC,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,eAAO,MAAM,UAAU,EAAE;IACvB,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,QAAQ,KAAK,IAAI,CAAC;CAC9B,CAAC"}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../src/configs/LogConfig.ts"],
|
|
4
|
-
"sourcesContent": ["export interface LogEntry {\n level: \"log\" | \"info\" | \"warn\" | \"error\";\n message: string;\n timestamp: number;\n}\n\nexport const LogAdapter: {\n write?: (entry: LogEntry) => void;\n} = {};\n"],
|
|
5
|
-
"mappings": "AAMO,MAAM,aAET,CAAC;",
|
|
6
|
-
"names": []
|
|
7
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"useLocalConfig.d.ts","sourceRoot":"","sources":["../../src/hooks/useLocalConfig.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,QAAQ,EAAE,KAAK,MAAM,EAAgB,MAAM,UAAU,CAAC;AAEpE;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,GAAG,SAAS,CAAC,EAAE,MAAM,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC,CAmCjH"}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../src/hooks/useLocalConfig.ts"],
|
|
4
|
-
"sourcesContent": ["import { type Accessor, type Setter, createSignal } from \"solid-js\";\n\n/**\n * localStorage \uAE30\uBC18 \uC124\uC815 \uAD00\uB9AC \uD6C5.\n * syncStorage \uC124\uC815\uACFC \uBB34\uAD00\uD558\uAC8C \uD56D\uC0C1 localStorage\uB97C \uC0AC\uC6A9\uD55C\uB2E4.\n * \uAE30\uAE30\uBCC4\uB85C \uB3C5\uB9BD\uC801\uC73C\uB85C \uC720\uC9C0\uB418\uC5B4\uC57C \uD558\uB294 \uB370\uC774\uD130(\uC778\uC99D \uD1A0\uD070, \uAE30\uAE30\uBCC4 \uC0C1\uD0DC \uB4F1)\uC5D0 \uC0AC\uC6A9\uD55C\uB2E4.\n *\n * @template T - \uC800\uC7A5\uD560 \uAC12\uC758 \uD0C0\uC785\n * @param key - localStorage \uD0A4\n * @param initialValue - \uCD08\uAE30\uAC12 (\uC635\uC154\uB110)\n * @returns [Accessor<T | undefined>, Setter<T | undefined>] \uD29C\uD50C\n *\n * @example\n * ```tsx\n * const [token, setToken] = useLocalConfig<string>(\"auth-token\");\n *\n * // \uAC12 \uC124\uC815\n * setToken(\"abc123\");\n *\n * // \uAC12 \uC77D\uAE30\n * console.log(token()); // \"abc123\"\n *\n * // \uAC12 \uC81C\uAC70\n * setToken(undefined);\n * ```\n */\nexport function useLocalConfig<T>(key: string, initialValue?: T): [Accessor<T | undefined>, Setter<T | undefined>] {\n // localStorage\uC5D0\uC11C \uCD08\uAE30\uAC12 \uC77D\uAE30\n let storedValue: T | undefined = initialValue;\n try {\n const item = localStorage.getItem(key);\n if (item !== null) {\n storedValue = JSON.parse(item) as T;\n }\n } catch {\n // JSON \uD30C\uC2F1 \uC2E4\uD328 \uC2DC \uCD08\uAE30\uAC12 \uC0AC\uC6A9\n }\n\n const [value, setValue] = createSignal<T | undefined>(storedValue);\n\n const setAndStore = (newValue: T | undefined | ((prev: T | undefined) => T | undefined)) => {\n let resolved: T | undefined;\n\n if (typeof newValue === \"function\") {\n resolved = (newValue as (prev: T | undefined) => T | undefined)(value());\n setValue(() => resolved);\n } else {\n resolved = newValue;\n setValue(() => newValue);\n }\n\n if (resolved === undefined) {\n localStorage.removeItem(key);\n } else {\n localStorage.setItem(key, JSON.stringify(resolved));\n }\n\n return resolved;\n };\n\n return [value, setAndStore as Setter<T | undefined>];\n}\n"],
|
|
5
|
-
"mappings": "AAAA,SAAqC,oBAAoB;AA0BlD,SAAS,eAAkB,KAAa,cAAoE;AAEjH,MAAI,cAA6B;AACjC,MAAI;AACF,UAAM,OAAO,aAAa,QAAQ,GAAG;AACrC,QAAI,SAAS,MAAM;AACjB,oBAAc,KAAK,MAAM,IAAI;AAAA,IAC/B;AAAA,EACF,QAAQ;AAAA,EAER;AAEA,QAAM,CAAC,OAAO,QAAQ,IAAI,aAA4B,WAAW;AAEjE,QAAM,cAAc,CAAC,aAAuE;AAC1F,QAAI;AAEJ,QAAI,OAAO,aAAa,YAAY;AAClC,iBAAY,SAAoD,MAAM,CAAC;AACvE,eAAS,MAAM,QAAQ;AAAA,IACzB,OAAO;AACL,iBAAW;AACX,eAAS,MAAM,QAAQ;AAAA,IACzB;AAEA,QAAI,aAAa,QAAW;AAC1B,mBAAa,WAAW,GAAG;AAAA,IAC7B,OAAO;AACL,mBAAa,QAAQ,KAAK,KAAK,UAAU,QAAQ,CAAC;AAAA,IACpD;AAEA,WAAO;AAAA,EACT;AAEA,SAAO,CAAC,OAAO,WAAoC;AACrD;",
|
|
6
|
-
"names": []
|
|
7
|
-
}
|