@simplysm/solid 13.0.32 → 13.0.33
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 +39 -14
- package/dist/hooks/useLogger.js +4 -4
- package/dist/hooks/useLogger.js.map +1 -1
- package/dist/hooks/useSyncConfig.d.ts +1 -1
- package/dist/hooks/useSyncConfig.d.ts.map +1 -1
- package/dist/hooks/useSyncConfig.js +6 -4
- package/dist/hooks/useSyncConfig.js.map +1 -1
- package/dist/index.d.ts +6 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -4
- package/dist/index.js.map +1 -1
- package/dist/{hooks/useClipboardValueCopy.d.ts → providers/ClipboardProvider.d.ts} +4 -3
- package/dist/providers/ClipboardProvider.d.ts.map +1 -0
- package/dist/{hooks/useClipboardValueCopy.js → providers/ClipboardProvider.js} +11 -8
- package/dist/providers/ClipboardProvider.js.map +6 -0
- package/dist/providers/ConfigContext.d.ts +15 -47
- package/dist/providers/ConfigContext.d.ts.map +1 -1
- package/dist/providers/ConfigContext.js +18 -1
- package/dist/providers/ConfigContext.js.map +3 -3
- package/dist/providers/ErrorLoggerProvider.d.ts +10 -0
- package/dist/providers/ErrorLoggerProvider.d.ts.map +1 -0
- package/dist/providers/ErrorLoggerProvider.js +23 -0
- package/dist/providers/ErrorLoggerProvider.js.map +6 -0
- package/dist/providers/LoggerContext.d.ts +38 -0
- package/dist/providers/LoggerContext.d.ts.map +1 -0
- package/dist/providers/LoggerContext.js +25 -0
- package/dist/providers/LoggerContext.js.map +6 -0
- package/dist/providers/PwaUpdateProvider.d.ts +12 -0
- package/dist/providers/PwaUpdateProvider.d.ts.map +1 -0
- package/dist/providers/PwaUpdateProvider.js +56 -0
- package/dist/providers/PwaUpdateProvider.js.map +6 -0
- package/dist/providers/ServiceClientContext.d.ts.map +1 -1
- package/dist/providers/ServiceClientContext.js +1 -3
- package/dist/providers/ServiceClientContext.js.map +1 -1
- package/dist/providers/SyncStorageContext.d.ts +42 -0
- package/dist/providers/SyncStorageContext.d.ts.map +1 -0
- package/dist/providers/SyncStorageContext.js +25 -0
- package/dist/providers/SyncStorageContext.js.map +6 -0
- package/dist/providers/ThemeContext.d.ts.map +1 -1
- package/dist/providers/ThemeContext.js +1 -1
- package/dist/providers/ThemeContext.js.map +1 -1
- package/docs/disclosure.md +1 -1
- package/docs/feedback.md +4 -4
- package/docs/form-controls.md +1 -1
- package/docs/hooks.md +8 -42
- package/docs/providers.md +116 -3
- package/docs/styling.md +1 -1
- package/package.json +16 -16
- package/src/hooks/useLogger.ts +4 -4
- package/src/hooks/useSyncConfig.ts +7 -5
- package/src/index.ts +6 -3
- package/src/{hooks/useClipboardValueCopy.ts → providers/ClipboardProvider.tsx} +6 -4
- package/src/providers/ConfigContext.tsx +48 -0
- package/src/providers/ErrorLoggerProvider.tsx +31 -0
- package/src/providers/LoggerContext.tsx +46 -0
- package/src/providers/PwaUpdateProvider.tsx +68 -0
- package/src/providers/ServiceClientContext.ts +1 -3
- package/src/providers/SyncStorageContext.tsx +52 -0
- package/src/providers/ThemeContext.tsx +1 -3
- package/dist/hooks/useClipboardValueCopy.d.ts.map +0 -1
- package/dist/hooks/useClipboardValueCopy.js.map +0 -6
- package/dist/hooks/usePwaUpdate.d.ts +0 -14
- package/dist/hooks/usePwaUpdate.d.ts.map +0 -1
- package/dist/hooks/usePwaUpdate.js +0 -50
- package/dist/hooks/usePwaUpdate.js.map +0 -6
- package/dist/providers/InitializeProvider.d.ts +0 -25
- package/dist/providers/InitializeProvider.d.ts.map +0 -1
- package/dist/providers/InitializeProvider.js +0 -60
- package/dist/providers/InitializeProvider.js.map +0 -6
- package/src/hooks/usePwaUpdate.ts +0 -73
- package/src/providers/ConfigContext.ts +0 -80
- package/src/providers/InitializeProvider.tsx +0 -79
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { memo as _$memo } from "solid-js/web";
|
|
2
|
+
import { onCleanup } from "solid-js";
|
|
3
|
+
import { useNotification } from "../components/feedback/notification/NotificationContext.js";
|
|
4
|
+
const UPDATE_INTERVAL = 5 * 60 * 1e3;
|
|
5
|
+
const PwaUpdateProvider = (props) => {
|
|
6
|
+
if (typeof navigator !== "undefined" && "serviceWorker" in navigator) {
|
|
7
|
+
let promptUpdate2 = function(waitingSW) {
|
|
8
|
+
notification.info("\uC571\uC774 \uC5C5\uB370\uC774\uD2B8\uB418\uC5C8\uC2B5\uB2C8\uB2E4", "\uC0C8\uB85C\uACE0\uCE68\uD558\uBA74 \uCD5C\uC2E0 \uBC84\uC804\uC744 \uC0AC\uC6A9\uD560 \uC218 \uC788\uC2B5\uB2C8\uB2E4", {
|
|
9
|
+
action: {
|
|
10
|
+
label: "\uC0C8\uB85C\uACE0\uCE68",
|
|
11
|
+
onClick: () => {
|
|
12
|
+
waitingSW.postMessage({
|
|
13
|
+
type: "SKIP_WAITING"
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
};
|
|
19
|
+
var promptUpdate = promptUpdate2;
|
|
20
|
+
const notification = useNotification();
|
|
21
|
+
let intervalId;
|
|
22
|
+
void navigator.serviceWorker.getRegistration().then((registration) => {
|
|
23
|
+
if (registration == null) return;
|
|
24
|
+
intervalId = setInterval(() => {
|
|
25
|
+
void registration.update();
|
|
26
|
+
}, UPDATE_INTERVAL);
|
|
27
|
+
if (registration.waiting != null) {
|
|
28
|
+
promptUpdate2(registration.waiting);
|
|
29
|
+
}
|
|
30
|
+
registration.addEventListener("updatefound", () => {
|
|
31
|
+
const newSW = registration.installing;
|
|
32
|
+
if (newSW == null) return;
|
|
33
|
+
newSW.addEventListener("statechange", () => {
|
|
34
|
+
if (newSW.state === "installed" && navigator.serviceWorker.controller != null) {
|
|
35
|
+
promptUpdate2(newSW);
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
});
|
|
40
|
+
const onControllerChange = () => {
|
|
41
|
+
window.location.reload();
|
|
42
|
+
};
|
|
43
|
+
navigator.serviceWorker.addEventListener("controllerchange", onControllerChange);
|
|
44
|
+
onCleanup(() => {
|
|
45
|
+
if (intervalId != null) {
|
|
46
|
+
clearInterval(intervalId);
|
|
47
|
+
}
|
|
48
|
+
navigator.serviceWorker.removeEventListener("controllerchange", onControllerChange);
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
return _$memo(() => props.children);
|
|
52
|
+
};
|
|
53
|
+
export {
|
|
54
|
+
PwaUpdateProvider
|
|
55
|
+
};
|
|
56
|
+
//# sourceMappingURL=PwaUpdateProvider.js.map
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/providers/PwaUpdateProvider.tsx"],
|
|
4
|
+
"mappings": ";AAAA,SAASA,iBAAuC;AAChD,SAASC,uBAAuB;AAEhC,MAAMC,kBAAkB,IAAI,KAAK;AAW1B,MAAMC,oBAAsCC,WAAU;AAC3D,MAAI,OAAOC,cAAc,eAAe,mBAAmBA,WAAW;AAuCpE,QAASC,gBAAT,SAAsBC,WAAgC;AACpDC,mBAAaC,KAAK,uEAAgB,2HAA4B;QAC5DC,QAAQ;UACNC,OAAO;UACPC,SAASA,MAAM;AACbL,sBAAUM,YAAY;cAAEC,MAAM;YAAe,CAAC;UAChD;QACF;MACF,CAAC;IACH;AATSR,uBAAAA;AAtCT,UAAME,eAAeP,gBAAgB;AACrC,QAAIc;AAEJ,SAAKV,UAAUW,cAAcC,gBAAgB,EAAEC,KAAMC,kBAAiB;AACpE,UAAIA,gBAAgB,KAAM;AAE1BJ,mBAAaK,YAAY,MAAM;AAC7B,aAAKD,aAAaE,OAAO;MAC3B,GAAGnB,eAAe;AAElB,UAAIiB,aAAaG,WAAW,MAAM;AAChChB,QAAAA,cAAaa,aAAaG,OAAO;MACnC;AAEAH,mBAAaI,iBAAiB,eAAe,MAAM;AACjD,cAAMC,QAAQL,aAAaM;AAC3B,YAAID,SAAS,KAAM;AAEnBA,cAAMD,iBAAiB,eAAe,MAAM;AAC1C,cAAIC,MAAME,UAAU,eAAerB,UAAUW,cAAcW,cAAc,MAAM;AAC7ErB,YAAAA,cAAakB,KAAK;UACpB;QACF,CAAC;MACH,CAAC;IACH,CAAC;AAED,UAAMI,qBAAqBA,MAAM;AAC/BC,aAAOC,SAASC,OAAO;IACzB;AACA1B,cAAUW,cAAcO,iBAAiB,oBAAoBK,kBAAkB;AAE/E5B,cAAU,MAAM;AACd,UAAIe,cAAc,MAAM;AACtBiB,sBAAcjB,UAAU;MAC1B;AACAV,gBAAUW,cAAciB,oBAAoB,oBAAoBL,kBAAkB;IACpF,CAAC;EAYH;AAEA,SAAAM,OAAA,MAAU9B,MAAM+B,QAAQ;AAC1B;",
|
|
5
|
+
"names": ["onCleanup", "useNotification", "UPDATE_INTERVAL", "PwaUpdateProvider", "props", "navigator", "promptUpdate", "waitingSW", "notification", "info", "action", "label", "onClick", "postMessage", "type", "intervalId", "serviceWorker", "getRegistration", "then", "registration", "setInterval", "update", "waiting", "addEventListener", "newSW", "installing", "state", "controller", "onControllerChange", "window", "location", "reload", "clearInterval", "removeEventListener", "_$memo", "children"]
|
|
6
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ServiceClientContext.d.ts","sourceRoot":"","sources":["../../src/providers/ServiceClientContext.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAC;AAEvF,MAAM,WAAW,yBAAyB;IACxC,OAAO,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,CAAC,uBAAuB,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACpF,KAAK,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACtC,GAAG,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,aAAa,CAAC;IACpC,WAAW,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC;CACvC;AAED,eAAO,MAAM,oBAAoB,mEAA6C,CAAC;AAE/E,wBAAgB,gBAAgB,IAAI,yBAAyB,
|
|
1
|
+
{"version":3,"file":"ServiceClientContext.d.ts","sourceRoot":"","sources":["../../src/providers/ServiceClientContext.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAC;AAEvF,MAAM,WAAW,yBAAyB;IACxC,OAAO,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,CAAC,uBAAuB,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACpF,KAAK,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACtC,GAAG,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,aAAa,CAAC;IACpC,WAAW,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC;CACvC;AAED,eAAO,MAAM,oBAAoB,mEAA6C,CAAC;AAE/E,wBAAgB,gBAAgB,IAAI,yBAAyB,CAM5D"}
|
|
@@ -3,9 +3,7 @@ const ServiceClientContext = createContext();
|
|
|
3
3
|
function useServiceClient() {
|
|
4
4
|
const context = useContext(ServiceClientContext);
|
|
5
5
|
if (!context) {
|
|
6
|
-
throw new Error(
|
|
7
|
-
"useServiceClient\uB294 ServiceClientProvider \uB0B4\uBD80\uC5D0\uC11C\uB9CC \uC0AC\uC6A9\uD560 \uC218 \uC788\uC2B5\uB2C8\uB2E4. ServiceClientProvider\uB294 InitializeProvider\uC640 NotificationProvider \uC544\uB798\uC5D0 \uC704\uCE58\uD574\uC57C \uD569\uB2C8\uB2E4"
|
|
8
|
-
);
|
|
6
|
+
throw new Error("useServiceClient\uB294 ServiceClientProvider \uB0B4\uBD80\uC5D0\uC11C\uB9CC \uC0AC\uC6A9\uD560 \uC218 \uC788\uC2B5\uB2C8\uB2E4");
|
|
9
7
|
}
|
|
10
8
|
return context;
|
|
11
9
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/providers/ServiceClientContext.ts"],
|
|
4
|
-
"mappings": "AAAA,SAAS,eAAe,kBAAkB;AAUnC,MAAM,uBAAuB,cAAyC;AAEtE,SAAS,mBAA8C;AAC5D,QAAM,UAAU,WAAW,oBAAoB;AAC/C,MAAI,CAAC,SAAS;AACZ,UAAM,IAAI
|
|
4
|
+
"mappings": "AAAA,SAAS,eAAe,kBAAkB;AAUnC,MAAM,uBAAuB,cAAyC;AAEtE,SAAS,mBAA8C;AAC5D,QAAM,UAAU,WAAW,oBAAoB;AAC/C,MAAI,CAAC,SAAS;AACZ,UAAM,IAAI,MAAM,gIAA0D;AAAA,EAC5E;AACA,SAAO;AACT;",
|
|
5
5
|
"names": []
|
|
6
6
|
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { type ParentComponent } from "solid-js";
|
|
2
|
+
/**
|
|
3
|
+
* 커스텀 동기화 저장소 어댑터 인터페이스
|
|
4
|
+
*
|
|
5
|
+
* @remarks
|
|
6
|
+
* - 동기 저장소: `localStorage`, `sessionStorage` 등 그대로 전달 가능
|
|
7
|
+
* - 비동기 저장소: `getItem`이 `Promise`를 반환하는 구현체 전달
|
|
8
|
+
*/
|
|
9
|
+
export interface StorageAdapter {
|
|
10
|
+
getItem(key: string): string | null | Promise<string | null>;
|
|
11
|
+
setItem(key: string, value: string): void | Promise<unknown>;
|
|
12
|
+
removeItem(key: string): void | Promise<void>;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* 동기화 저장소 Context
|
|
16
|
+
*
|
|
17
|
+
* @remarks
|
|
18
|
+
* Provider가 없으면 `undefined` (useSyncConfig에서 localStorage로 fallback)
|
|
19
|
+
*/
|
|
20
|
+
export declare const SyncStorageContext: import("solid-js").Context<StorageAdapter | undefined>;
|
|
21
|
+
/**
|
|
22
|
+
* 동기화 저장소 Context에 접근하는 훅
|
|
23
|
+
*
|
|
24
|
+
* @returns StorageAdapter 또는 undefined (Provider가 없으면)
|
|
25
|
+
*/
|
|
26
|
+
export declare function useSyncStorage(): StorageAdapter | undefined;
|
|
27
|
+
/**
|
|
28
|
+
* 동기화 저장소 Provider
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* ```tsx
|
|
32
|
+
* <SyncStorageProvider storage={myStorageAdapter}>
|
|
33
|
+
* <ThemeProvider>
|
|
34
|
+
* <App />
|
|
35
|
+
* </ThemeProvider>
|
|
36
|
+
* </SyncStorageProvider>
|
|
37
|
+
* ```
|
|
38
|
+
*/
|
|
39
|
+
export declare const SyncStorageProvider: ParentComponent<{
|
|
40
|
+
storage: StorageAdapter;
|
|
41
|
+
}>;
|
|
42
|
+
//# sourceMappingURL=SyncStorageContext.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SyncStorageContext.d.ts","sourceRoot":"","sources":["../../src/providers/SyncStorageContext.tsx"],"names":[],"mappings":"AAAA,OAAO,EAA6B,KAAK,eAAe,EAAE,MAAM,UAAU,CAAC;AAE3E;;;;;;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;;;;;GAKG;AACH,eAAO,MAAM,kBAAkB,wDAAuD,CAAC;AAEvF;;;;GAIG;AACH,wBAAgB,cAAc,IAAI,cAAc,GAAG,SAAS,CAE3D;AAED;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,mBAAmB,EAAE,eAAe,CAAC;IAAE,OAAO,EAAE,cAAc,CAAA;CAAE,CAO5E,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { createComponent as _$createComponent } from "solid-js/web";
|
|
2
|
+
import { createContext, useContext } from "solid-js";
|
|
3
|
+
const SyncStorageContext = createContext(void 0);
|
|
4
|
+
function useSyncStorage() {
|
|
5
|
+
return useContext(SyncStorageContext);
|
|
6
|
+
}
|
|
7
|
+
const SyncStorageProvider = (props) => {
|
|
8
|
+
return (
|
|
9
|
+
// eslint-disable-next-line solid/reactivity -- storage는 초기 설정값으로 변경되지 않음
|
|
10
|
+
_$createComponent(SyncStorageContext.Provider, {
|
|
11
|
+
get value() {
|
|
12
|
+
return props.storage;
|
|
13
|
+
},
|
|
14
|
+
get children() {
|
|
15
|
+
return props.children;
|
|
16
|
+
}
|
|
17
|
+
})
|
|
18
|
+
);
|
|
19
|
+
};
|
|
20
|
+
export {
|
|
21
|
+
SyncStorageContext,
|
|
22
|
+
SyncStorageProvider,
|
|
23
|
+
useSyncStorage
|
|
24
|
+
};
|
|
25
|
+
//# sourceMappingURL=SyncStorageContext.js.map
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/providers/SyncStorageContext.tsx"],
|
|
4
|
+
"mappings": ";AAAA,SAASA,eAAeC,kBAAwC;AAqBzD,MAAMC,qBAAqBF,cAA0CG,MAAS;AAO9E,SAASC,iBAA6C;AAC3D,SAAOH,WAAWC,kBAAkB;AACtC;AAcO,MAAMG,sBAAqEC,WAAU;AAC1F;;IACEC,kBACCL,mBAAmBM,UAAQ;MAAA,IAACC,QAAK;AAAA,eAAEH,MAAMI;MAAO;MAAA,IAAAC,WAAA;AAAA,eAC9CL,MAAMK;MAAQ;IAAA,CAAA;;AAGrB;",
|
|
5
|
+
"names": ["createContext", "useContext", "SyncStorageContext", "undefined", "useSyncStorage", "SyncStorageProvider", "props", "_$createComponent", "Provider", "value", "storage", "children"]
|
|
6
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ThemeContext.d.ts","sourceRoot":"","sources":["../../src/providers/ThemeContext.tsx"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,eAAe,EAIrB,MAAM,UAAU,CAAC;AAIlB;;;;;GAKG;AACH,MAAM,MAAM,SAAS,GAAG,OAAO,GAAG,MAAM,GAAG,QAAQ,CAAC;AAEpD;;GAEG;AACH,MAAM,MAAM,aAAa,GAAG,OAAO,GAAG,MAAM,CAAC;AAE7C,UAAU,iBAAiB;IACzB,yBAAyB;IACzB,IAAI,EAAE,MAAM,SAAS,CAAC;IACtB,eAAe;IACf,OAAO,EAAE,CAAC,IAAI,EAAE,SAAS,KAAK,IAAI,CAAC;IACnC,sCAAsC;IACtC,aAAa,EAAE,MAAM,aAAa,CAAC;IACnC,gDAAgD;IAChD,SAAS,EAAE,MAAM,IAAI,CAAC;CACvB;AAID;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,QAAQ,IAAI,iBAAiB,
|
|
1
|
+
{"version":3,"file":"ThemeContext.d.ts","sourceRoot":"","sources":["../../src/providers/ThemeContext.tsx"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,eAAe,EAIrB,MAAM,UAAU,CAAC;AAIlB;;;;;GAKG;AACH,MAAM,MAAM,SAAS,GAAG,OAAO,GAAG,MAAM,GAAG,QAAQ,CAAC;AAEpD;;GAEG;AACH,MAAM,MAAM,aAAa,GAAG,OAAO,GAAG,MAAM,CAAC;AAE7C,UAAU,iBAAiB;IACzB,yBAAyB;IACzB,IAAI,EAAE,MAAM,SAAS,CAAC;IACtB,eAAe;IACf,OAAO,EAAE,CAAC,IAAI,EAAE,SAAS,KAAK,IAAI,CAAC;IACnC,sCAAsC;IACtC,aAAa,EAAE,MAAM,aAAa,CAAC;IACnC,gDAAgD;IAChD,SAAS,EAAE,MAAM,IAAI,CAAC;CACvB;AAID;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,QAAQ,IAAI,iBAAiB,CAM5C;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,aAAa,EAAE,eA2C3B,CAAC"}
|
|
@@ -6,7 +6,7 @@ const ThemeContext = createContext();
|
|
|
6
6
|
function useTheme() {
|
|
7
7
|
const context = useContext(ThemeContext);
|
|
8
8
|
if (!context) {
|
|
9
|
-
throw new Error("useTheme\uB294 ThemeProvider \uB0B4\uBD80\uC5D0\uC11C\uB9CC \uC0AC\uC6A9\uD560 \uC218 \uC788\uC2B5\uB2C8\uB2E4
|
|
9
|
+
throw new Error("useTheme\uB294 ThemeProvider \uB0B4\uBD80\uC5D0\uC11C\uB9CC \uC0AC\uC6A9\uD560 \uC218 \uC788\uC2B5\uB2C8\uB2E4");
|
|
10
10
|
}
|
|
11
11
|
return context;
|
|
12
12
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/providers/ThemeContext.tsx"],
|
|
4
|
-
"mappings": ";AAAA,SACEA,eACAC,YAEAC,YACAC,cACAC,iBACK;AACP,SAASC,wBAAwB;AACjC,SAASC,qBAAqB;AA0B9B,MAAMC,eAAeP,cAAiC;AAwB/C,SAASQ,WAA8B;AAC5C,QAAMC,UAAUR,WAAWM,YAAY;AACvC,MAAI,CAACE,SAAS;AACZ,UAAM,IAAIC,
|
|
4
|
+
"mappings": ";AAAA,SACEA,eACAC,YAEAC,YACAC,cACAC,iBACK;AACP,SAASC,wBAAwB;AACjC,SAASC,qBAAqB;AA0B9B,MAAMC,eAAeP,cAAiC;AAwB/C,SAASQ,WAA8B;AAC5C,QAAMC,UAAUR,WAAWM,YAAY;AACvC,MAAI,CAACE,SAAS;AACZ,UAAM,IAAIC,MAAM,gHAA0C;EAC5D;AACA,SAAOD;AACT;AAmBO,MAAME,gBAAkCC,WAAU;AACvD,QAAM,CAACC,MAAMC,SAASC,KAAK,IAAIT,cAAyB,SAAS,QAAQ;AAGzE,QAAMU,cAAcX,iBAAiB,8BAA8B;AAGnE,QAAMY,gBAAgBf,WAA0B,MAAM;AACpD,UAAMgB,cAAcL,KAAK;AACzB,QAAIK,gBAAgB,UAAU;AAC5B,aAAOF,YAAY,IAAI,SAAS;IAClC;AACA,WAAOE;EACT,CAAC;AAGD,QAAMC,YAAYA,MAAM;AACtB,UAAMC,UAAUP,KAAK;AACrB,UAAMQ,OACJD,YAAY,UAAU,WAAWA,YAAY,WAAW,SAAS;AACnEN,YAAQO,IAAI;EACd;AAGAlB,eAAa,MAAM;AACjB,QAAI,CAACY,MAAM,EAAG;AACd,UAAMO,SAASL,cAAc,MAAM;AACnCM,aAASC,gBAAgBC,UAAUC,OAAO,QAAQJ,MAAM;EAC1D,CAAC;AAGDlB,YAAU,MAAM;AACdmB,aAASC,gBAAgBC,UAAUE,OAAO,MAAM;EAClD,CAAC;AAED,QAAMC,eAAkC;IACtCf;IACAC;IACAG;IACAE;EACF;AAEA,SAAAU,kBAAQtB,aAAauB,UAAQ;IAACC,OAAOH;IAAY,IAAAI,WAAA;AAAA,aAAGpB,MAAMoB;IAAQ;EAAA,CAAA;AACpE;",
|
|
5
5
|
"names": ["createContext", "useContext", "createMemo", "createEffect", "onCleanup", "createMediaQuery", "useSyncConfig", "ThemeContext", "useTheme", "context", "Error", "ThemeProvider", "props", "mode", "setMode", "ready", "prefersDark", "resolvedTheme", "currentMode", "cycleMode", "current", "next", "isDark", "document", "documentElement", "classList", "toggle", "remove", "contextValue", "_$createComponent", "Provider", "value", "children"]
|
|
6
6
|
}
|
package/docs/disclosure.md
CHANGED
|
@@ -212,7 +212,7 @@ function MyPage() {
|
|
|
212
212
|
|
|
213
213
|
**DialogProvider:**
|
|
214
214
|
|
|
215
|
-
`DialogProvider` is the provider component that enables `useDialog`.
|
|
215
|
+
`DialogProvider` is the provider component that enables `useDialog`. Use it in your provider tree to enable programmatic dialogs.
|
|
216
216
|
|
|
217
217
|
```tsx
|
|
218
218
|
import { DialogProvider } from "@simplysm/solid";
|
package/docs/feedback.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
## Notification
|
|
4
4
|
|
|
5
|
-
Notification system.
|
|
5
|
+
Notification system. Set up `NotificationProvider` and `NotificationBanner` in your provider tree. Use the `useNotification` hook to show notifications and optionally add `NotificationBell` in your layout.
|
|
6
6
|
|
|
7
7
|
```tsx
|
|
8
8
|
import {
|
|
@@ -58,14 +58,14 @@ function MyComponent() {
|
|
|
58
58
|
| `clear` | `() => void` | Clear all |
|
|
59
59
|
|
|
60
60
|
**Components:**
|
|
61
|
-
- `NotificationBanner` -- Top-of-screen notification banner (
|
|
61
|
+
- `NotificationBanner` -- Top-of-screen notification banner (add inside `NotificationProvider`)
|
|
62
62
|
- `NotificationBell` -- Notification bell icon (shows unread count, add to your layout as needed)
|
|
63
63
|
|
|
64
64
|
---
|
|
65
65
|
|
|
66
66
|
## Busy
|
|
67
67
|
|
|
68
|
-
Busy overlay system.
|
|
68
|
+
Busy overlay system. Set up `BusyProvider` in your provider tree. Pass `variant` prop to choose between `"spinner"` (default) and `"bar"` variants. Control the busy state using the `useBusy` hook.
|
|
69
69
|
|
|
70
70
|
```tsx
|
|
71
71
|
import { useBusy } from "@simplysm/solid";
|
|
@@ -119,7 +119,7 @@ import { BusyContainer } from "@simplysm/solid";
|
|
|
119
119
|
|
|
120
120
|
## Print / usePrint
|
|
121
121
|
|
|
122
|
-
Browser printing and PDF generation.
|
|
122
|
+
Browser printing and PDF generation.
|
|
123
123
|
|
|
124
124
|
```tsx
|
|
125
125
|
import { Print, usePrint } from "@simplysm/solid";
|
package/docs/form-controls.md
CHANGED
|
@@ -589,7 +589,7 @@ import { ColorPicker } from "@simplysm/solid";
|
|
|
589
589
|
|
|
590
590
|
## ThemeToggle
|
|
591
591
|
|
|
592
|
-
Dark/light/system theme cycle toggle button. Must be used inside `
|
|
592
|
+
Dark/light/system theme cycle toggle button. Must be used inside `ThemeProvider`.
|
|
593
593
|
|
|
594
594
|
```tsx
|
|
595
595
|
import { ThemeToggle } from "@simplysm/solid";
|
package/docs/hooks.md
CHANGED
|
@@ -1,42 +1,8 @@
|
|
|
1
1
|
# Hooks
|
|
2
2
|
|
|
3
|
-
## usePwaUpdate
|
|
4
|
-
|
|
5
|
-
PWA Service Worker update detection hook. Automatically polls for Service Worker updates every 5 minutes. When a new version is detected, shows a notification with a reload action button.
|
|
6
|
-
|
|
7
|
-
**Automatic Integration:** Already integrated into `InitializeProvider` -- no manual setup required for most applications. The hook runs automatically inside the notification system.
|
|
8
|
-
|
|
9
|
-
**Manual Usage (Custom Provider Tree):**
|
|
10
|
-
|
|
11
|
-
```tsx
|
|
12
|
-
import { usePwaUpdate } from "@simplysm/solid";
|
|
13
|
-
|
|
14
|
-
function MyProvider(props) {
|
|
15
|
-
// Must be called inside NotificationProvider
|
|
16
|
-
usePwaUpdate();
|
|
17
|
-
|
|
18
|
-
return (
|
|
19
|
-
<NotificationProvider>
|
|
20
|
-
{props.children}
|
|
21
|
-
</NotificationProvider>
|
|
22
|
-
);
|
|
23
|
-
}
|
|
24
|
-
```
|
|
25
|
-
|
|
26
|
-
**Graceful No-ops:** Works safely in the following scenarios where Service Workers are unavailable:
|
|
27
|
-
- HTTP protocol (non-HTTPS dev servers)
|
|
28
|
-
- Browsers that don't support Service Workers
|
|
29
|
-
- Development/test environments without SW registration
|
|
30
|
-
|
|
31
|
-
**Requirements:**
|
|
32
|
-
- Must be called inside `NotificationProvider` (to display the update notification)
|
|
33
|
-
- `InitializeProvider` already includes both, so manual setup only needed for custom provider trees
|
|
34
|
-
|
|
35
|
-
---
|
|
36
|
-
|
|
37
3
|
## useTheme
|
|
38
4
|
|
|
39
|
-
Hook to access theme (dark/light/system) state. Must be used inside `
|
|
5
|
+
Hook to access theme (dark/light/system) state. Must be used inside `ThemeProvider`.
|
|
40
6
|
|
|
41
7
|
```tsx
|
|
42
8
|
import { useTheme } from "@simplysm/solid";
|
|
@@ -76,7 +42,7 @@ const [token, setToken] = useLocalStorage<string | undefined>("auth-token", unde
|
|
|
76
42
|
|
|
77
43
|
## useSyncConfig
|
|
78
44
|
|
|
79
|
-
Syncable config hook. Uses `
|
|
45
|
+
Syncable config hook. Uses `SyncStorageProvider` storage if present, 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).
|
|
80
46
|
|
|
81
47
|
```tsx
|
|
82
48
|
import { useSyncConfig } from "@simplysm/solid";
|
|
@@ -97,7 +63,7 @@ const [theme, setTheme, ready] = useSyncConfig("theme", "light");
|
|
|
97
63
|
|
|
98
64
|
## useLogger
|
|
99
65
|
|
|
100
|
-
Logging hook. If `
|
|
66
|
+
Logging hook. If `LoggerProvider` is present, logs are sent to the adapter only. Otherwise, logs fall back to `consola`.
|
|
101
67
|
|
|
102
68
|
```tsx
|
|
103
69
|
import { useLogger } from "@simplysm/solid";
|
|
@@ -116,31 +82,31 @@ logger.warn("deprecation notice");
|
|
|
116
82
|
| `warn` | `(...args: unknown[]) => void` | Log message (warning) |
|
|
117
83
|
| `error` | `(...args: unknown[]) => void` | Log message (error) |
|
|
118
84
|
|
|
119
|
-
**Global error capturing:** `
|
|
85
|
+
**Global error capturing:** `ErrorLoggerProvider` captures uncaught errors (`window.onerror`) and unhandled promise rejections (`unhandledrejection`) and logs them via `useLogger`.
|
|
120
86
|
|
|
121
87
|
---
|
|
122
88
|
|
|
123
89
|
## useNotification
|
|
124
90
|
|
|
125
|
-
Hook to access notification system. Must be used inside `
|
|
91
|
+
Hook to access notification system. Must be used inside `NotificationProvider`. See [Notification](feedback.md#notification) for detailed API.
|
|
126
92
|
|
|
127
93
|
---
|
|
128
94
|
|
|
129
95
|
## useBusy
|
|
130
96
|
|
|
131
|
-
Hook to access busy overlay. Must be used inside `
|
|
97
|
+
Hook to access busy overlay. Must be used inside `BusyProvider`. See [Busy](feedback.md#busy) for detailed API.
|
|
132
98
|
|
|
133
99
|
---
|
|
134
100
|
|
|
135
101
|
## usePrint
|
|
136
102
|
|
|
137
|
-
Hook for printing and PDF generation.
|
|
103
|
+
Hook for printing and PDF generation. See [Print / usePrint](feedback.md#print--useprint) for detailed API.
|
|
138
104
|
|
|
139
105
|
---
|
|
140
106
|
|
|
141
107
|
## useConfig
|
|
142
108
|
|
|
143
|
-
Hook to access app-wide configuration. Must be used inside `
|
|
109
|
+
Hook to access app-wide configuration. Must be used inside `ConfigProvider`.
|
|
144
110
|
|
|
145
111
|
```tsx
|
|
146
112
|
import { useConfig } from "@simplysm/solid";
|
package/docs/providers.md
CHANGED
|
@@ -1,10 +1,123 @@
|
|
|
1
1
|
# Providers
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Providers are composable and independent. Compose them at your app root in the recommended order:
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
```tsx
|
|
6
|
+
<ConfigProvider clientName="my-app">
|
|
7
|
+
<SyncStorageProvider storage={...}> {/* optional */}
|
|
8
|
+
<LoggerProvider adapter={...}> {/* optional */}
|
|
9
|
+
<NotificationProvider>
|
|
10
|
+
<NotificationBanner />
|
|
11
|
+
<ErrorLoggerProvider>
|
|
12
|
+
<PwaUpdateProvider>
|
|
13
|
+
<ClipboardProvider>
|
|
14
|
+
<ThemeProvider>
|
|
15
|
+
<BusyProvider>{/* app content */}</BusyProvider>
|
|
16
|
+
</ThemeProvider>
|
|
17
|
+
</ClipboardProvider>
|
|
18
|
+
</PwaUpdateProvider>
|
|
19
|
+
</ErrorLoggerProvider>
|
|
20
|
+
</NotificationProvider>
|
|
21
|
+
</LoggerProvider>
|
|
22
|
+
</SyncStorageProvider>
|
|
23
|
+
</ConfigProvider>
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## ConfigProvider
|
|
27
|
+
|
|
28
|
+
Required root provider. Provides `clientName` used as storage key prefix.
|
|
29
|
+
|
|
30
|
+
```tsx
|
|
31
|
+
<ConfigProvider clientName="my-app">
|
|
32
|
+
{/* app content */}
|
|
33
|
+
</ConfigProvider>
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
| Prop | Type | Description |
|
|
37
|
+
|------|------|-------------|
|
|
38
|
+
| `clientName` | `string` | Client identifier (used as storage key prefix) |
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## SyncStorageProvider
|
|
43
|
+
|
|
44
|
+
Optional provider for custom sync storage (cross-device sync). When present, `useSyncConfig` uses this storage instead of `localStorage`.
|
|
45
|
+
|
|
46
|
+
```tsx
|
|
47
|
+
<SyncStorageProvider storage={myStorageAdapter}>
|
|
48
|
+
{/* children */}
|
|
49
|
+
</SyncStorageProvider>
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
| Prop | Type | Description |
|
|
53
|
+
|------|------|-------------|
|
|
54
|
+
| `storage` | `StorageAdapter` | Storage adapter implementation |
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## LoggerProvider
|
|
59
|
+
|
|
60
|
+
Optional provider for remote logging. When present, `useLogger` sends logs to the adapter instead of `consola`.
|
|
61
|
+
|
|
62
|
+
```tsx
|
|
63
|
+
<LoggerProvider adapter={myLogAdapter}>
|
|
64
|
+
{/* children */}
|
|
65
|
+
</LoggerProvider>
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
| Prop | Type | Description |
|
|
69
|
+
|------|------|-------------|
|
|
70
|
+
| `adapter` | `LogAdapter` | Log adapter implementation |
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
74
|
+
## ErrorLoggerProvider
|
|
75
|
+
|
|
76
|
+
Captures uncaught errors (`window.onerror`) and unhandled promise rejections (`unhandledrejection`) and logs them via `useLogger`.
|
|
77
|
+
|
|
78
|
+
```tsx
|
|
79
|
+
<ErrorLoggerProvider>
|
|
80
|
+
{/* children */}
|
|
81
|
+
</ErrorLoggerProvider>
|
|
82
|
+
```
|
|
6
83
|
|
|
7
|
-
|
|
84
|
+
---
|
|
85
|
+
|
|
86
|
+
## PwaUpdateProvider
|
|
87
|
+
|
|
88
|
+
PWA Service Worker update detection. Polls for SW updates every 5 minutes. When a new version is detected, shows a notification with a reload action. Must be inside `NotificationProvider`.
|
|
89
|
+
|
|
90
|
+
Graceful no-op when `navigator.serviceWorker` is unavailable (HTTP, unsupported browser, dev mode).
|
|
91
|
+
|
|
92
|
+
```tsx
|
|
93
|
+
<PwaUpdateProvider>
|
|
94
|
+
{/* children */}
|
|
95
|
+
</PwaUpdateProvider>
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
---
|
|
99
|
+
|
|
100
|
+
## ClipboardProvider
|
|
101
|
+
|
|
102
|
+
Intercepts `Ctrl+C` to copy form control values (input, textarea, select, checkbox) as plain text. Handles table structures as TSV format.
|
|
103
|
+
|
|
104
|
+
```tsx
|
|
105
|
+
<ClipboardProvider>
|
|
106
|
+
{/* children */}
|
|
107
|
+
</ClipboardProvider>
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
---
|
|
111
|
+
|
|
112
|
+
## ThemeProvider
|
|
113
|
+
|
|
114
|
+
Dark/light/system theme provider. Toggles the `dark` class on `<html>` and manages theme persistence via `useSyncConfig`.
|
|
115
|
+
|
|
116
|
+
```tsx
|
|
117
|
+
<ThemeProvider>
|
|
118
|
+
{/* children */}
|
|
119
|
+
</ThemeProvider>
|
|
120
|
+
```
|
|
8
121
|
|
|
9
122
|
---
|
|
10
123
|
|
package/docs/styling.md
CHANGED
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
|
|
42
42
|
## Dark Mode
|
|
43
43
|
|
|
44
|
-
Uses Tailwind's `class` strategy. `
|
|
44
|
+
Uses Tailwind's `class` strategy. `ThemeProvider` automatically toggles the `dark` class on the `<html>` element.
|
|
45
45
|
|
|
46
46
|
```html
|
|
47
47
|
<!-- Light mode -->
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@simplysm/solid",
|
|
3
|
-
"version": "13.0.
|
|
3
|
+
"version": "13.0.33",
|
|
4
4
|
"description": "심플리즘 패키지 - SolidJS 라이브러리",
|
|
5
5
|
"author": "김석래",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -28,18 +28,18 @@
|
|
|
28
28
|
"@solid-primitives/storage": "^4.3.3",
|
|
29
29
|
"@solidjs/router": "^0.15.4",
|
|
30
30
|
"@tabler/icons-solidjs": "^3.36.1",
|
|
31
|
-
"@tiptap/core": "^3.
|
|
32
|
-
"@tiptap/extension-color": "^3.
|
|
33
|
-
"@tiptap/extension-highlight": "^3.
|
|
34
|
-
"@tiptap/extension-image": "^3.
|
|
35
|
-
"@tiptap/extension-table": "^3.
|
|
36
|
-
"@tiptap/extension-table-cell": "^3.
|
|
37
|
-
"@tiptap/extension-table-header": "^3.
|
|
38
|
-
"@tiptap/extension-table-row": "^3.
|
|
39
|
-
"@tiptap/extension-text-align": "^3.
|
|
40
|
-
"@tiptap/extension-text-style": "^3.
|
|
41
|
-
"@tiptap/pm": "^3.
|
|
42
|
-
"@tiptap/starter-kit": "^3.
|
|
31
|
+
"@tiptap/core": "^3.20.0",
|
|
32
|
+
"@tiptap/extension-color": "^3.20.0",
|
|
33
|
+
"@tiptap/extension-highlight": "^3.20.0",
|
|
34
|
+
"@tiptap/extension-image": "^3.20.0",
|
|
35
|
+
"@tiptap/extension-table": "^3.20.0",
|
|
36
|
+
"@tiptap/extension-table-cell": "^3.20.0",
|
|
37
|
+
"@tiptap/extension-table-header": "^3.20.0",
|
|
38
|
+
"@tiptap/extension-table-row": "^3.20.0",
|
|
39
|
+
"@tiptap/extension-text-align": "^3.20.0",
|
|
40
|
+
"@tiptap/extension-text-style": "^3.20.0",
|
|
41
|
+
"@tiptap/pm": "^3.20.0",
|
|
42
|
+
"@tiptap/starter-kit": "^3.20.0",
|
|
43
43
|
"bwip-js": "^4.8.0",
|
|
44
44
|
"clsx": "^2.1.1",
|
|
45
45
|
"consola": "^3.4.2",
|
|
@@ -47,10 +47,10 @@
|
|
|
47
47
|
"jspdf": "^4.1.0",
|
|
48
48
|
"solid-js": "^1.9.11",
|
|
49
49
|
"solid-tiptap": "^0.8.0",
|
|
50
|
-
"tailwind-merge": "^3.
|
|
50
|
+
"tailwind-merge": "^3.5.0",
|
|
51
51
|
"tailwindcss": "^3.4.19",
|
|
52
|
-
"@simplysm/core-browser": "13.0.
|
|
53
|
-
"@simplysm/core-common": "13.0.
|
|
52
|
+
"@simplysm/core-browser": "13.0.33",
|
|
53
|
+
"@simplysm/core-common": "13.0.33"
|
|
54
54
|
},
|
|
55
55
|
"devDependencies": {
|
|
56
56
|
"@solidjs/testing-library": "^0.8.10"
|
package/src/hooks/useLogger.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { consola } from "consola";
|
|
2
|
-
import {
|
|
2
|
+
import { useLogAdapter, type LogAdapter } from "../providers/LoggerContext";
|
|
3
3
|
|
|
4
4
|
type LogLevel = Parameters<LogAdapter["write"]>[0];
|
|
5
5
|
|
|
@@ -11,12 +11,12 @@ interface Logger {
|
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
export function useLogger(): Logger {
|
|
14
|
-
const
|
|
14
|
+
const logAdapter = useLogAdapter();
|
|
15
15
|
|
|
16
16
|
const createLogFunction = (level: LogLevel) => {
|
|
17
17
|
return (...args: unknown[]) => {
|
|
18
|
-
if (
|
|
19
|
-
void
|
|
18
|
+
if (logAdapter) {
|
|
19
|
+
void logAdapter.write(level, ...args);
|
|
20
20
|
} else {
|
|
21
21
|
(consola as any)[level](...args);
|
|
22
22
|
}
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { type Accessor, type Setter, createEffect, createSignal } from "solid-js";
|
|
2
2
|
import { useConfig } from "../providers/ConfigContext";
|
|
3
|
+
import { useSyncStorage } from "../providers/SyncStorageContext";
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
6
|
* Creates a reactive signal that syncs configuration data to storage.
|
|
6
7
|
*
|
|
7
|
-
* Uses `
|
|
8
|
+
* Uses `SyncStorageProvider` storage if available, otherwise falls back to `localStorage`.
|
|
8
9
|
* Designed for data that should persist and sync across devices (e.g., theme, user preferences, DataSheet configs).
|
|
9
10
|
*
|
|
10
11
|
* @param key - Storage key for the config value
|
|
@@ -27,13 +28,14 @@ export function useSyncConfig<TValue>(
|
|
|
27
28
|
defaultValue: TValue,
|
|
28
29
|
): [Accessor<TValue>, Setter<TValue>, Accessor<boolean>] {
|
|
29
30
|
const config = useConfig();
|
|
31
|
+
const syncStorage = useSyncStorage();
|
|
30
32
|
const prefixedKey = `${config.clientName}.${key}`;
|
|
31
33
|
const [value, setValue] = createSignal<TValue>(defaultValue);
|
|
32
34
|
const [ready, setReady] = createSignal(false);
|
|
33
35
|
|
|
34
36
|
// Initialize from storage
|
|
35
37
|
const initializeFromStorage = async () => {
|
|
36
|
-
if (!
|
|
38
|
+
if (!syncStorage) {
|
|
37
39
|
// Use localStorage synchronously
|
|
38
40
|
try {
|
|
39
41
|
const stored = localStorage.getItem(prefixedKey);
|
|
@@ -49,7 +51,7 @@ export function useSyncConfig<TValue>(
|
|
|
49
51
|
|
|
50
52
|
// Use syncStorage asynchronously
|
|
51
53
|
try {
|
|
52
|
-
const stored = await
|
|
54
|
+
const stored = await syncStorage.getItem(prefixedKey);
|
|
53
55
|
if (stored !== null) {
|
|
54
56
|
setValue(() => JSON.parse(stored) as TValue);
|
|
55
57
|
}
|
|
@@ -77,7 +79,7 @@ export function useSyncConfig<TValue>(
|
|
|
77
79
|
const currentValue = value();
|
|
78
80
|
const serialized = JSON.stringify(currentValue);
|
|
79
81
|
|
|
80
|
-
if (!
|
|
82
|
+
if (!syncStorage) {
|
|
81
83
|
// Use localStorage synchronously
|
|
82
84
|
localStorage.setItem(prefixedKey, serialized);
|
|
83
85
|
return;
|
|
@@ -86,7 +88,7 @@ export function useSyncConfig<TValue>(
|
|
|
86
88
|
// Use syncStorage asynchronously
|
|
87
89
|
void (async () => {
|
|
88
90
|
try {
|
|
89
|
-
await
|
|
91
|
+
await syncStorage.setItem(prefixedKey, serialized);
|
|
90
92
|
} catch {
|
|
91
93
|
// Fall back to localStorage on error
|
|
92
94
|
localStorage.setItem(prefixedKey, serialized);
|
package/src/index.ts
CHANGED
|
@@ -110,8 +110,12 @@ export * from "./components/feedback/Progress";
|
|
|
110
110
|
//#region ========== Providers ==========
|
|
111
111
|
|
|
112
112
|
export * from "./providers/ConfigContext";
|
|
113
|
-
export * from "./providers/
|
|
114
|
-
export
|
|
113
|
+
export * from "./providers/SyncStorageContext";
|
|
114
|
+
export * from "./providers/LoggerContext";
|
|
115
|
+
export * from "./providers/ErrorLoggerProvider";
|
|
116
|
+
export * from "./providers/PwaUpdateProvider";
|
|
117
|
+
export * from "./providers/ClipboardProvider";
|
|
118
|
+
export { useTheme, ThemeProvider } from "./providers/ThemeContext";
|
|
115
119
|
export type { ThemeMode, ResolvedTheme } from "./providers/ThemeContext";
|
|
116
120
|
export * from "./providers/ServiceClientContext";
|
|
117
121
|
export * from "./providers/ServiceClientProvider";
|
|
@@ -130,7 +134,6 @@ export * from "./hooks/usePrint";
|
|
|
130
134
|
export { createControllableSignal } from "./hooks/createControllableSignal";
|
|
131
135
|
export { createIMEHandler } from "./hooks/createIMEHandler";
|
|
132
136
|
export { createMountTransition } from "./hooks/createMountTransition";
|
|
133
|
-
export { usePwaUpdate } from "./hooks/usePwaUpdate";
|
|
134
137
|
export { useRouterLink } from "./hooks/useRouterLink";
|
|
135
138
|
|
|
136
139
|
//#endregion
|