@vxrn/color-scheme 1.19.4 → 1.19.5
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/dist/cjs/index.cjs +8 -6
- package/dist/cjs/index.native.js +4 -2
- package/dist/cjs/index.native.js.map +1 -1
- package/dist/cjs/safeStorage.cjs +40 -0
- package/dist/cjs/safeStorage.native.js +43 -0
- package/dist/cjs/safeStorage.native.js.map +1 -0
- package/dist/cjs/safeStorage.test.cjs +49 -0
- package/dist/cjs/safeStorage.test.native.js +66 -0
- package/dist/cjs/safeStorage.test.native.js.map +1 -0
- package/dist/cjs/userScheme.cjs +9 -12
- package/dist/cjs/userScheme.native.js +11 -16
- package/dist/cjs/userScheme.native.js.map +1 -1
- package/dist/esm/index.js +8 -6
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/index.mjs +8 -6
- package/dist/esm/index.mjs.map +1 -1
- package/dist/esm/index.native.js +3 -2
- package/dist/esm/index.native.js.map +1 -1
- package/dist/esm/safeStorage.mjs +14 -0
- package/dist/esm/safeStorage.mjs.map +1 -0
- package/dist/esm/safeStorage.native.js +14 -0
- package/dist/esm/safeStorage.native.js.map +1 -0
- package/dist/esm/safeStorage.test.mjs +50 -0
- package/dist/esm/safeStorage.test.mjs.map +1 -0
- package/dist/esm/safeStorage.test.native.js +64 -0
- package/dist/esm/safeStorage.test.native.js.map +1 -0
- package/dist/esm/userScheme.mjs +9 -12
- package/dist/esm/userScheme.mjs.map +1 -1
- package/dist/esm/userScheme.native.js +11 -16
- package/dist/esm/userScheme.native.js.map +1 -1
- package/package.json +5 -3
- package/src/index.tsx +10 -6
- package/src/safeStorage.test.ts +63 -0
- package/src/safeStorage.ts +20 -0
- package/src/userScheme.ts +13 -20
- package/types/index.d.ts.map +1 -1
- package/types/safeStorage.d.ts +3 -0
- package/types/safeStorage.d.ts.map +1 -0
- package/types/safeStorage.test.d.ts +2 -0
- package/types/safeStorage.test.d.ts.map +1 -0
- package/types/userScheme.d.ts.map +1 -1
package/dist/esm/index.native.js
CHANGED
|
@@ -17,7 +17,7 @@ function SchemeProvider(param) {
|
|
|
17
17
|
} = useUserScheme();
|
|
18
18
|
if (forceScheme) `${getClassName("light")}${getClassName("dark")}${getClassName(forceScheme)}`;else {
|
|
19
19
|
var fallback = defaultScheme ? `'${defaultScheme}' === 'dark'` : `window.matchMedia('(prefers-color-scheme: dark)').matches`;
|
|
20
|
-
var seedStorage = defaultScheme ?
|
|
20
|
+
var seedStorage = defaultScheme ? `;if(!e){localStorage.setItem('${storageKey}','${defaultScheme}')}` : "";
|
|
21
21
|
`${getClassName("light")}${getClassName("dark")}${storageKey}${seedStorage}${fallback}${getClassName("dark")}${getClassName("light")}`;
|
|
22
22
|
}
|
|
23
23
|
return /* @__PURE__ */jsxs(Fragment, {
|
|
@@ -35,7 +35,8 @@ function MetaTheme(param) {
|
|
|
35
35
|
} = useUserScheme();
|
|
36
36
|
var forced = getForceScheme();
|
|
37
37
|
var scriptContent = forced ? `document.getElementById('vxrn-theme-color').setAttribute('content','${forced === "dark" ? darkColor : lightColor}')` : `let dc = document.getElementById('vxrn-theme-color')
|
|
38
|
-
let e1 =
|
|
38
|
+
let e1 = null
|
|
39
|
+
try { e1 = localStorage.getItem('${storageKey}') } catch (_e) {}
|
|
39
40
|
let isD = 'system' === e1 || !e1 ? window.matchMedia('(prefers-color-scheme: dark)').matches : e1 === 'dark'
|
|
40
41
|
dc.setAttribute('content', isD ? '${darkColor}' : '${lightColor}')`;
|
|
41
42
|
return /* @__PURE__ */jsxs(Fragment, {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["Fragment","jsx","jsxs","getForceScheme","getUserScheme","onUserSchemeChange","setForceScheme","setUserScheme","setUserScheme2","useUserScheme","useUserScheme2","getSystemScheme","useSystemScheme","storageKey","SchemeProvider","param","children","getClassName","name","defaultScheme","forceScheme","value","fallback","seedStorage","MetaTheme","color","darkColor","lightColor","forced","scriptContent","suppressHydrationWarning","id","content","dangerouslySetInnerHTML","__html"],"sources":["index.native.js"],"sourcesContent":["import { Fragment, jsx, jsxs } from \"react/jsx-runtime\";\nimport { getForceScheme, getUserScheme, onUserSchemeChange, setForceScheme, setUserScheme as setUserScheme2, useUserScheme, useUserScheme as useUserScheme2 } from \"./userScheme\";\nimport { getSystemScheme, useSystemScheme } from \"./systemScheme\";\n\nvar storageKey = \"vxrn-scheme\";\nfunction SchemeProvider(param) {\n\tvar { children, getClassName = function(name) {\n\t\treturn `t_${name}`;\n\t}, defaultScheme, forceScheme } = param;\n\tsetForceScheme(forceScheme !== null && forceScheme !== void 0 ? forceScheme : null);\n\tvar { value } = useUserScheme();\n\tif (forceScheme) `${getClassName(\"light\")}${getClassName(\"dark\")}${getClassName(forceScheme)}`;\n\telse {\n\t\tvar fallback = defaultScheme ? `'${defaultScheme}' === 'dark'` : `window.matchMedia('(prefers-color-scheme: dark)').matches`;\n\t\tvar seedStorage = defaultScheme ?
|
|
1
|
+
{"version":3,"names":["Fragment","jsx","jsxs","getForceScheme","getUserScheme","onUserSchemeChange","setForceScheme","setUserScheme","setUserScheme2","useUserScheme","useUserScheme2","getSystemScheme","useSystemScheme","storageKey","SchemeProvider","param","children","getClassName","name","defaultScheme","forceScheme","value","fallback","seedStorage","MetaTheme","color","darkColor","lightColor","forced","scriptContent","suppressHydrationWarning","id","content","dangerouslySetInnerHTML","__html"],"sources":["index.native.js"],"sourcesContent":["import { Fragment, jsx, jsxs } from \"react/jsx-runtime\";\nimport { getForceScheme, getUserScheme, onUserSchemeChange, setForceScheme, setUserScheme as setUserScheme2, useUserScheme, useUserScheme as useUserScheme2 } from \"./userScheme\";\nimport { getSystemScheme, useSystemScheme } from \"./systemScheme\";\n\nvar storageKey = \"vxrn-scheme\";\nfunction SchemeProvider(param) {\n\tvar { children, getClassName = function(name) {\n\t\treturn `t_${name}`;\n\t}, defaultScheme, forceScheme } = param;\n\tsetForceScheme(forceScheme !== null && forceScheme !== void 0 ? forceScheme : null);\n\tvar { value } = useUserScheme();\n\tif (forceScheme) `${getClassName(\"light\")}${getClassName(\"dark\")}${getClassName(forceScheme)}`;\n\telse {\n\t\tvar fallback = defaultScheme ? `'${defaultScheme}' === 'dark'` : `window.matchMedia('(prefers-color-scheme: dark)').matches`;\n\t\tvar seedStorage = defaultScheme ? `;if(!e){localStorage.setItem('${storageKey}','${defaultScheme}')}` : \"\";\n\t\t`${getClassName(\"light\")}${getClassName(\"dark\")}${storageKey}${seedStorage}${fallback}${getClassName(\"dark\")}${getClassName(\"light\")}`;\n\t}\n\treturn /* @__PURE__ */ jsxs(Fragment, { children: [null, children] });\n}\nfunction MetaTheme(param) {\n\tvar { color, darkColor, lightColor } = param;\n\tvar { value } = useUserScheme();\n\tvar forced = getForceScheme();\n\tvar scriptContent = forced ? `document.getElementById('vxrn-theme-color').setAttribute('content','${forced === \"dark\" ? darkColor : lightColor}')` : `let dc = document.getElementById('vxrn-theme-color')\nlet e1 = null\ntry { e1 = localStorage.getItem('${storageKey}') } catch (_e) {}\nlet isD = 'system' === e1 || !e1 ? window.matchMedia('(prefers-color-scheme: dark)').matches : e1 === 'dark'\ndc.setAttribute('content', isD ? '${darkColor}' : '${lightColor}')`;\n\treturn /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(\"meta\", {\n\t\tsuppressHydrationWarning: true,\n\t\tid: \"vxrn-theme-color\",\n\t\tname: \"theme-color\",\n\t\tcontent: color !== null && color !== void 0 ? color : value === \"dark\" ? darkColor : lightColor\n\t}), /* @__PURE__ */ jsx(\"script\", {\n\t\tsuppressHydrationWarning: true,\n\t\tid: \"meta-theme-hydrate\",\n\t\tdangerouslySetInnerHTML: { __html: scriptContent }\n\t})] });\n}\n\nexport { MetaTheme, SchemeProvider, getSystemScheme, getUserScheme, onUserSchemeChange, setUserScheme2 as setUserScheme, useSystemScheme, useUserScheme2 as useUserScheme };"],"mappings":"AAAA,SAASA,QAAQ,EAAEC,GAAG,EAAEC,IAAI,QAAQ,mBAAmB;AACvD,SAASC,cAAc,EAAEC,aAAa,EAAEC,kBAAkB,EAAEC,cAAc,EAAEC,aAAa,IAAIC,cAAc,EAAEC,aAAa,EAAEA,aAAa,IAAIC,cAAc,QAAQ,wBAAc;AACjL,SAASC,eAAe,EAAEC,eAAe,QAAQ,0BAAgB;AAEjE,IAAIC,UAAU,GAAG,aAAa;AAC9B,SAASC,cAAcA,CAACC,KAAK,EAAE;EAC9B,IAAI;IAAEC,QAAQ;IAAEC,YAAY,GAAG,SAAAA,CAASC,IAAI,EAAE;MAC7C,OAAO,KAAKA,IAAI,EAAE;IACnB,CAAC;IAAEC,aAAa;IAAEC;EAAY,CAAC,GAAGL,KAAK;EACvCT,cAAc,CAACc,WAAW,KAAK,IAAI,IAAIA,WAAW,KAAK,KAAK,CAAC,GAAGA,WAAW,GAAG,IAAI,CAAC;EACnF,IAAI;IAAEC;EAAM,CAAC,GAAGZ,aAAa,CAAC,CAAC;EAC/B,IAAIW,WAAW,EAAE,GAAGH,YAAY,CAAC,OAAO,CAAC,GAAGA,YAAY,CAAC,MAAM,CAAC,GAAGA,YAAY,CAACG,WAAW,CAAC,EAAE,CAAC,KAC1F;IACJ,IAAIE,QAAQ,GAAGH,aAAa,GAAG,IAAIA,aAAa,cAAc,GAAG,2DAA2D;IAC5H,IAAII,WAAW,GAAGJ,aAAa,GAAG,iCAAiCN,UAAU,MAAMM,aAAa,KAAK,GAAG,EAAE;IAC1G,GAAGF,YAAY,CAAC,OAAO,CAAC,GAAGA,YAAY,CAAC,MAAM,CAAC,GAAGJ,UAAU,GAAGU,WAAW,GAAGD,QAAQ,GAAGL,YAAY,CAAC,MAAM,CAAC,GAAGA,YAAY,CAAC,OAAO,CAAC,EAAE;EACvI;EACA,OAAO,eAAgBf,IAAI,CAACF,QAAQ,EAAE;IAAEgB,QAAQ,EAAE,CAAC,IAAI,EAAEA,QAAQ;EAAE,CAAC,CAAC;AACtE;AACA,SAASQ,SAASA,CAACT,KAAK,EAAE;EACzB,IAAI;IAAEU,KAAK;IAAEC,SAAS;IAAEC;EAAW,CAAC,GAAGZ,KAAK;EAC5C,IAAI;IAAEM;EAAM,CAAC,GAAGZ,aAAa,CAAC,CAAC;EAC/B,IAAImB,MAAM,GAAGzB,cAAc,CAAC,CAAC;EAC7B,IAAI0B,aAAa,GAAGD,MAAM,GAAG,uEAAuEA,MAAM,KAAK,MAAM,GAAGF,SAAS,GAAGC,UAAU,IAAI,GAAG;AACtJ;AACA,mCAAmCd,UAAU;AAC7C;AACA,oCAAoCa,SAAS,QAAQC,UAAU,IAAI;EAClE,OAAO,eAAgBzB,IAAI,CAACF,QAAQ,EAAE;IAAEgB,QAAQ,EAAE,CAAC,eAAgBf,GAAG,CAAC,MAAM,EAAE;MAC9E6B,wBAAwB,EAAE,IAAI;MAC9BC,EAAE,EAAE,kBAAkB;MACtBb,IAAI,EAAE,aAAa;MACnBc,OAAO,EAAEP,KAAK,KAAK,IAAI,IAAIA,KAAK,KAAK,KAAK,CAAC,GAAGA,KAAK,GAAGJ,KAAK,KAAK,MAAM,GAAGK,SAAS,GAAGC;IACtF,CAAC,CAAC,EAAE,eAAgB1B,GAAG,CAAC,QAAQ,EAAE;MACjC6B,wBAAwB,EAAE,IAAI;MAC9BC,EAAE,EAAE,oBAAoB;MACxBE,uBAAuB,EAAE;QAAEC,MAAM,EAAEL;MAAc;IAClD,CAAC,CAAC;EAAE,CAAC,CAAC;AACP;AAEA,SAASL,SAAS,EAAEV,cAAc,EAAEH,eAAe,EAAEP,aAAa,EAAEC,kBAAkB,EAAEG,cAAc,IAAID,aAAa,EAAEK,eAAe,EAAEF,cAAc,IAAID,aAAa","ignoreList":[]}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
function getStorageItem(key) {
|
|
2
|
+
try {
|
|
3
|
+
return localStorage.getItem(key);
|
|
4
|
+
} catch {
|
|
5
|
+
return null;
|
|
6
|
+
}
|
|
7
|
+
}
|
|
8
|
+
function setStorageItem(key, value) {
|
|
9
|
+
try {
|
|
10
|
+
localStorage.setItem(key, value);
|
|
11
|
+
} catch {}
|
|
12
|
+
}
|
|
13
|
+
export { getStorageItem, setStorageItem };
|
|
14
|
+
//# sourceMappingURL=safeStorage.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["getStorageItem","key","localStorage","getItem","setStorageItem","value","setItem"],"sources":["../../src/safeStorage.ts"],"sourcesContent":[null],"mappings":"AAOO,SAASA,eAAeC,GAAA,EAA4B;EACzD,IAAI;IACF,OAAOC,YAAA,CAAaC,OAAA,CAAQF,GAAG;EACjC,QAAQ;IACN,OAAO;EACT;AACF;AAEO,SAASG,eAAeH,GAAA,EAAaI,KAAA,EAAqB;EAC/D,IAAI;IACFH,YAAA,CAAaI,OAAA,CAAQL,GAAA,EAAKI,KAAK;EACjC,QAAQ,CAAC;AACX","ignoreList":[]}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
function getStorageItem(key) {
|
|
2
|
+
try {
|
|
3
|
+
return localStorage.getItem(key);
|
|
4
|
+
} catch (unused) {
|
|
5
|
+
return null;
|
|
6
|
+
}
|
|
7
|
+
}
|
|
8
|
+
function setStorageItem(key, value) {
|
|
9
|
+
try {
|
|
10
|
+
localStorage.setItem(key, value);
|
|
11
|
+
} catch (unused) {}
|
|
12
|
+
}
|
|
13
|
+
export { getStorageItem, setStorageItem };
|
|
14
|
+
//# sourceMappingURL=safeStorage.native.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["getStorageItem","key","localStorage","getItem","unused","setStorageItem","value","setItem"],"sources":["../../src/safeStorage.ts"],"sourcesContent":[null],"mappings":"AAOO,SAASA,eAAeC,GAAA,EAA4B;EACzD,IAAI;IACF,OAAOC,YAAA,CAAaC,OAAA,CAAQF,GAAG;EACjC,SAAQG,MAAA;IACN,OAAO;EACT;AACF;AAEO,SAASC,eAAeJ,GAAA,EAAaK,KAAA,EAAqB;EAC/D,IAAI;IACFJ,YAAA,CAAaK,OAAA,CAAQN,GAAA,EAAKK,KAAK;EACjC,SAAQF,MAAA,GAAC;AACX","ignoreList":[]}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { afterEach, describe, expect, it } from "vitest";
|
|
2
|
+
import { getStorageItem, setStorageItem } from "./safeStorage.mjs";
|
|
3
|
+
afterEach(() => {
|
|
4
|
+
delete globalThis.localStorage;
|
|
5
|
+
});
|
|
6
|
+
function defineLocalStorage(descriptor) {
|
|
7
|
+
Object.defineProperty(globalThis, "localStorage", {
|
|
8
|
+
configurable: true,
|
|
9
|
+
...descriptor
|
|
10
|
+
});
|
|
11
|
+
}
|
|
12
|
+
describe("safeStorage", () => {
|
|
13
|
+
it("reads and writes through to a working localStorage", () => {
|
|
14
|
+
const store = /* @__PURE__ */new Map();
|
|
15
|
+
defineLocalStorage({
|
|
16
|
+
value: {
|
|
17
|
+
getItem: k => store.has(k) ? store.get(k) : null,
|
|
18
|
+
setItem: (k, v) => void store.set(k, v)
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
setStorageItem("vxrn-scheme", "dark");
|
|
22
|
+
expect(getStorageItem("vxrn-scheme")).toBe("dark");
|
|
23
|
+
});
|
|
24
|
+
it("returns null instead of throwing when the localStorage getter throws", () => {
|
|
25
|
+
defineLocalStorage({
|
|
26
|
+
get() {
|
|
27
|
+
throw new Error('Failed to read the "localStorage" property: Access is denied.');
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
expect(() => getStorageItem("vxrn-scheme")).not.toThrow();
|
|
31
|
+
expect(getStorageItem("vxrn-scheme")).toBeNull();
|
|
32
|
+
expect(() => setStorageItem("vxrn-scheme", "dark")).not.toThrow();
|
|
33
|
+
});
|
|
34
|
+
it("swallows errors when setItem throws (quota / blocked)", () => {
|
|
35
|
+
defineLocalStorage({
|
|
36
|
+
value: {
|
|
37
|
+
getItem: () => null,
|
|
38
|
+
setItem: () => {
|
|
39
|
+
throw new Error("QuotaExceededError");
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
expect(() => setStorageItem("vxrn-scheme", "dark")).not.toThrow();
|
|
44
|
+
});
|
|
45
|
+
it("returns null when localStorage is undefined (native)", () => {
|
|
46
|
+
expect(getStorageItem("vxrn-scheme")).toBeNull();
|
|
47
|
+
expect(() => setStorageItem("vxrn-scheme", "dark")).not.toThrow();
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
//# sourceMappingURL=safeStorage.test.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["afterEach","describe","expect","it","getStorageItem","setStorageItem","globalThis","localStorage","defineLocalStorage","descriptor","Object","defineProperty","configurable","store","Map","value","getItem","k","has","get","setItem","v","set","toBe","Error","not","toThrow","toBeNull"],"sources":["../../src/safeStorage.test.ts"],"sourcesContent":[null],"mappings":"AAAA,SAASA,SAAA,EAAWC,QAAA,EAAUC,MAAA,EAAQC,EAAA,QAAU;AAChD,SAASC,cAAA,EAAgBC,cAAA,QAAsB;AAI/CL,SAAA,CAAU,MAAM;EACd,OAAQM,UAAA,CAAmBC,YAAA;AAC7B,CAAC;AAED,SAASC,mBAAmBC,UAAA,EAAgC;EAC1DC,MAAA,CAAOC,cAAA,CAAeL,UAAA,EAAY,gBAAgB;IAChDM,YAAA,EAAc;IACd,GAAGH;EACL,CAAC;AACH;AAEAR,QAAA,CAAS,eAAe,MAAM;EAC5BE,EAAA,CAAG,sDAAsD,MAAM;IAC7D,MAAMU,KAAA,GAAQ,mBAAIC,GAAA,CAAoB;IACtCN,kBAAA,CAAmB;MACjBO,KAAA,EAAO;QACLC,OAAA,EAAUC,CAAA,IAAeJ,KAAA,CAAMK,GAAA,CAAID,CAAC,IAAIJ,KAAA,CAAMM,GAAA,CAAIF,CAAC,IAAK;QACxDG,OAAA,EAASA,CAACH,CAAA,EAAWI,CAAA,KAAc,KAAKR,KAAA,CAAMS,GAAA,CAAIL,CAAA,EAAGI,CAAC;MACxD;IACF,CAAC;IAEDhB,cAAA,CAAe,eAAe,MAAM;IACpCH,MAAA,CAAOE,cAAA,CAAe,aAAa,CAAC,EAAEmB,IAAA,CAAK,MAAM;EACnD,CAAC;EAKDpB,EAAA,CAAG,wEAAwE,MAAM;IAC/EK,kBAAA,CAAmB;MACjBW,IAAA,EAAM;QACJ,MAAM,IAAIK,KAAA,CAAM,+DAA+D;MACjF;IACF,CAAC;IAEDtB,MAAA,CAAO,MAAME,cAAA,CAAe,aAAa,CAAC,EAAEqB,GAAA,CAAIC,OAAA,CAAQ;IACxDxB,MAAA,CAAOE,cAAA,CAAe,aAAa,CAAC,EAAEuB,QAAA,CAAS;IAC/CzB,MAAA,CAAO,MAAMG,cAAA,CAAe,eAAe,MAAM,CAAC,EAAEoB,GAAA,CAAIC,OAAA,CAAQ;EAClE,CAAC;EAEDvB,EAAA,CAAG,yDAAyD,MAAM;IAChEK,kBAAA,CAAmB;MACjBO,KAAA,EAAO;QACLC,OAAA,EAASA,CAAA,KAAM;QACfI,OAAA,EAASA,CAAA,KAAM;UACb,MAAM,IAAII,KAAA,CAAM,oBAAoB;QACtC;MACF;IACF,CAAC;IAEDtB,MAAA,CAAO,MAAMG,cAAA,CAAe,eAAe,MAAM,CAAC,EAAEoB,GAAA,CAAIC,OAAA,CAAQ;EAClE,CAAC;EAEDvB,EAAA,CAAG,wDAAwD,MAAM;IAC/DD,MAAA,CAAOE,cAAA,CAAe,aAAa,CAAC,EAAEuB,QAAA,CAAS;IAC/CzB,MAAA,CAAO,MAAMG,cAAA,CAAe,eAAe,MAAM,CAAC,EAAEoB,GAAA,CAAIC,OAAA,CAAQ;EAClE,CAAC;AACH,CAAC","ignoreList":[]}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { afterEach, describe, expect, it } from "vitest";
|
|
2
|
+
import { getStorageItem, setStorageItem } from "./safeStorage.native.js";
|
|
3
|
+
afterEach(function () {
|
|
4
|
+
delete globalThis.localStorage;
|
|
5
|
+
});
|
|
6
|
+
function defineLocalStorage(descriptor) {
|
|
7
|
+
Object.defineProperty(globalThis, "localStorage", {
|
|
8
|
+
configurable: true,
|
|
9
|
+
...descriptor
|
|
10
|
+
});
|
|
11
|
+
}
|
|
12
|
+
describe("safeStorage", function () {
|
|
13
|
+
it("reads and writes through to a working localStorage", function () {
|
|
14
|
+
var store = /* @__PURE__ */new Map();
|
|
15
|
+
defineLocalStorage({
|
|
16
|
+
value: {
|
|
17
|
+
getItem: function getItem(k) {
|
|
18
|
+
return store.has(k) ? store.get(k) : null;
|
|
19
|
+
},
|
|
20
|
+
setItem: function setItem(k, v) {
|
|
21
|
+
return void store.set(k, v);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
setStorageItem("vxrn-scheme", "dark");
|
|
26
|
+
expect(getStorageItem("vxrn-scheme")).toBe("dark");
|
|
27
|
+
});
|
|
28
|
+
it("returns null instead of throwing when the localStorage getter throws", function () {
|
|
29
|
+
defineLocalStorage({
|
|
30
|
+
get() {
|
|
31
|
+
throw new Error('Failed to read the "localStorage" property: Access is denied.');
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
expect(function () {
|
|
35
|
+
return getStorageItem("vxrn-scheme");
|
|
36
|
+
}).not.toThrow();
|
|
37
|
+
expect(getStorageItem("vxrn-scheme")).toBeNull();
|
|
38
|
+
expect(function () {
|
|
39
|
+
return setStorageItem("vxrn-scheme", "dark");
|
|
40
|
+
}).not.toThrow();
|
|
41
|
+
});
|
|
42
|
+
it("swallows errors when setItem throws (quota / blocked)", function () {
|
|
43
|
+
defineLocalStorage({
|
|
44
|
+
value: {
|
|
45
|
+
getItem: function getItem() {
|
|
46
|
+
return null;
|
|
47
|
+
},
|
|
48
|
+
setItem: function setItem() {
|
|
49
|
+
throw new Error("QuotaExceededError");
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
expect(function () {
|
|
54
|
+
return setStorageItem("vxrn-scheme", "dark");
|
|
55
|
+
}).not.toThrow();
|
|
56
|
+
});
|
|
57
|
+
it("returns null when localStorage is undefined (native)", function () {
|
|
58
|
+
expect(getStorageItem("vxrn-scheme")).toBeNull();
|
|
59
|
+
expect(function () {
|
|
60
|
+
return setStorageItem("vxrn-scheme", "dark");
|
|
61
|
+
}).not.toThrow();
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
//# sourceMappingURL=safeStorage.test.native.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["afterEach","describe","expect","it","getStorageItem","setStorageItem","globalThis","localStorage","defineLocalStorage","descriptor","Object","defineProperty","configurable","store","Map","value","getItem","k","has","get","setItem","v","set","toBe","Error","not","toThrow","toBeNull"],"sources":["../../src/safeStorage.test.ts"],"sourcesContent":[null],"mappings":"AAAA,SAASA,SAAA,EAAWC,QAAA,EAAUC,MAAA,EAAQC,EAAA,QAAU;AAChD,SAASC,cAAA,EAAgBC,cAAA,QAAsB;AAI/CL,SAAA,CAAU,YAAM;EACd,OAAQM,UAAA,CAAmBC,YAAA;AAC7B,CAAC;AAED,SAASC,mBAAmBC,UAAA,EAAgC;EAC1DC,MAAA,CAAOC,cAAA,CAAeL,UAAA,EAAY,gBAAgB;IAChDM,YAAA,EAAc;IACd,GAAGH;EACL,CAAC;AACH;AAEAR,QAAA,CAAS,eAAe,YAAM;EAC5BE,EAAA,CAAG,sDAAsD,YAAM;IAC7D,IAAAU,KAAM,kBAAQ,IAAAC,GAAI;IAClBN,kBAAA,CAAmB;MACjBO,KAAA,EAAO;QACLC,OAAA,EAAS,SAAgBA,OAAMA,CAAIC,CAAC;UACpC,OAASJ,KAAY,CAAAK,GAAA,CAAcD,CAAA,IAAKJ,KAAA,CAAMM,GAAA,CAAIF,CAAA,IAAI;QACxD;QACDG,OAAA,WAAAA,QAAAH,CAAA,EAAAI,CAAA;UAED,YAAeR,KAAA,CAAAS,GAAA,CAAAL,CAAA,EAAeI,CAAA;QAC9B;MACD;IAKD,CAAG;IACDhB,cAAA,cAAmB;IAAAH,MACjB,CAAAE,cAAM,iBAAAmB,IAAA;EACJ;EAA+EpB,EAAA,uEACjF;IACFK,kBAAC;MAEDW,IAAA,EAAO;QACP,MAAO,IAAAK,KAAA,gEAAwC;MAC/C;IACD;IAEDtB,MAAG;MACD,OAAAE,cAAmB;IAAA,EACjB,CAAAqB,GAAA,CAAAC,OAAO;IAAAxB,MACL,CAAAE,cAAe,iBAAAuB,QAAA;IAAAzB,MACf,aAAS;MACP,OAAAG,cAAgB,sBAAoB;IAAA,GAAAoB,GACtC,CAAAC,OAAA;EAAA;EACFvB,EACF,CAAC;IAEDK,kBAAa;MACdO,KAAA;QAEEC,OAAA,WAAAA,QAAA;UACD,OAAO;QACP;QACDI,OAAA,WAAAA,QAAA;UACF,UAAAI,KAAA","ignoreList":[]}
|
package/dist/esm/userScheme.mjs
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { useIsomorphicLayoutEffect } from "@vxrn/use-isomorphic-layout-effect";
|
|
2
2
|
import { useMemo, useState } from "react";
|
|
3
|
+
import { getStorageItem, setStorageItem } from "./safeStorage.mjs";
|
|
3
4
|
import { getSystemScheme } from "./systemScheme.mjs";
|
|
4
5
|
const listeners = /* @__PURE__ */new Set();
|
|
5
6
|
const storageKey = "vxrn-scheme";
|
|
@@ -10,13 +11,11 @@ function notifyListeners() {
|
|
|
10
11
|
});
|
|
11
12
|
}
|
|
12
13
|
function restoreUnforcedScheme() {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
return;
|
|
19
|
-
}
|
|
14
|
+
const stored = getStorageItem(storageKey);
|
|
15
|
+
if (stored) {
|
|
16
|
+
currentSetting = stored;
|
|
17
|
+
currentValue = stored === "system" ? resolveValue("system") : stored;
|
|
18
|
+
return;
|
|
20
19
|
}
|
|
21
20
|
currentSetting = "system";
|
|
22
21
|
currentValue = resolveValue("system");
|
|
@@ -79,7 +78,7 @@ function updateScheme(setting) {
|
|
|
79
78
|
}
|
|
80
79
|
function setUserScheme(setting) {
|
|
81
80
|
if (_forceScheme) return;
|
|
82
|
-
|
|
81
|
+
setStorageItem(storageKey, setting);
|
|
83
82
|
updateScheme(setting);
|
|
84
83
|
}
|
|
85
84
|
function getUserScheme() {
|
|
@@ -105,10 +104,8 @@ function useUserScheme() {
|
|
|
105
104
|
const resolvedState = state.setting === snapshot.setting && state.value === snapshot.value ? state : snapshot;
|
|
106
105
|
useIsomorphicLayoutEffect(() => {
|
|
107
106
|
if (!_forceScheme) {
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
if (stored) updateScheme(stored);
|
|
111
|
-
}
|
|
107
|
+
const stored = getStorageItem(storageKey);
|
|
108
|
+
if (stored) updateScheme(stored);
|
|
112
109
|
startWebListener();
|
|
113
110
|
}
|
|
114
111
|
return onUserSchemeChange((setting, value) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["useIsomorphicLayoutEffect","useMemo","useState","getSystemScheme","listeners","Set","storageKey","_forceScheme","notifyListeners","forEach","listener","currentSetting","currentValue","restoreUnforcedScheme","
|
|
1
|
+
{"version":3,"names":["useIsomorphicLayoutEffect","useMemo","useState","getStorageItem","setStorageItem","getSystemScheme","listeners","Set","storageKey","_forceScheme","notifyListeners","forEach","listener","currentSetting","currentValue","restoreUnforcedScheme","stored","resolveValue","setForceScheme","scheme","wasForced","startWebListener","getForceScheme","getInitialSetting","getInitialValue","setting","initialSetting","isWebListening","matcher","window","matchMedia","onSystemChange","updateValueFromSystem","addEventListener","value","updateScheme","setUserScheme","getUserScheme","onUserSchemeChange","add","delete","useUserScheme","state","setState","snapshot","resolvedState","set"],"sources":["userScheme.mjs"],"sourcesContent":["import { useIsomorphicLayoutEffect } from \"@vxrn/use-isomorphic-layout-effect\";\nimport { useMemo, useState } from \"react\";\nimport { getStorageItem, setStorageItem } from \"./safeStorage\";\nimport { getSystemScheme } from \"./systemScheme\";\n\nconst listeners = /* @__PURE__ */ new Set();\nconst storageKey = \"vxrn-scheme\";\nlet _forceScheme = null;\nfunction notifyListeners() {\n\tlisteners.forEach((listener) => {\n\t\tlistener(currentSetting, currentValue);\n\t});\n}\nfunction restoreUnforcedScheme() {\n\tconst stored = getStorageItem(storageKey);\n\tif (stored) {\n\t\tcurrentSetting = stored;\n\t\tcurrentValue = stored === \"system\" ? resolveValue(\"system\") : stored;\n\t\treturn;\n\t}\n\tcurrentSetting = \"system\";\n\tcurrentValue = resolveValue(\"system\");\n}\nfunction setForceScheme(scheme) {\n\tconst wasForced = _forceScheme;\n\tif (wasForced === scheme) return;\n\t_forceScheme = scheme;\n\tif (scheme) {\n\t\tcurrentSetting = scheme;\n\t\tcurrentValue = scheme;\n\t} else if (wasForced) {\n\t\trestoreUnforcedScheme();\n\t\tstartWebListener();\n\t}\n}\nfunction getForceScheme() {\n\treturn _forceScheme;\n}\nfunction getInitialSetting() {\n\treturn \"system\";\n}\nfunction getInitialValue(setting) {\n\treturn \"light\";\n}\nconst initialSetting = getInitialSetting();\nlet currentSetting = initialSetting;\nlet currentValue = getInitialValue(initialSetting);\nlet isWebListening = false;\nfunction startWebListener() {\n\tif (isWebListening) return;\n\tisWebListening = true;\n\tconst matcher = typeof window !== \"undefined\" ? window.matchMedia?.(\"(prefers-color-scheme: dark)\") : null;\n\tconst onSystemChange = () => {\n\t\tif (currentSetting === \"system\") updateValueFromSystem();\n\t};\n\tonSystemChange();\n\tmatcher?.addEventListener?.(\"change\", onSystemChange);\n}\nfunction resolveValue(setting) {\n\tif (setting === \"system\") return getSystemScheme();\n\treturn setting;\n}\nfunction updateValueFromSystem() {\n\tif (_forceScheme) return;\n\tconst value = resolveValue(\"system\");\n\tif (value !== currentValue) {\n\t\tcurrentValue = value;\n\t\tnotifyListeners();\n\t}\n}\nfunction updateScheme(setting) {\n\tif (_forceScheme) return;\n\tconst value = setting === \"system\" ? resolveValue(\"system\") : setting;\n\tif (value !== currentValue || currentSetting !== setting) {\n\t\tcurrentSetting = setting;\n\t\tcurrentValue = value;\n\t\tnotifyListeners();\n\t}\n}\nfunction setUserScheme(setting) {\n\tif (_forceScheme) return;\n\tsetStorageItem(storageKey, setting);\n\tupdateScheme(setting);\n}\nfunction getUserScheme() {\n\tif (_forceScheme) return {\n\t\tsetting: _forceScheme,\n\t\tvalue: _forceScheme\n\t};\n\treturn {\n\t\tsetting: currentSetting,\n\t\tvalue: currentValue\n\t};\n}\nfunction onUserSchemeChange(listener) {\n\tlisteners.add(listener);\n\tlistener(currentSetting, currentValue);\n\treturn () => {\n\t\tlisteners.delete(listener);\n\t};\n}\nfunction useUserScheme() {\n\tconst [state, setState] = useState(() => getUserScheme());\n\tconst snapshot = getUserScheme();\n\tconst resolvedState = state.setting === snapshot.setting && state.value === snapshot.value ? state : snapshot;\n\tuseIsomorphicLayoutEffect(() => {\n\t\tif (!_forceScheme) {\n\t\t\tconst stored = getStorageItem(storageKey);\n\t\t\tif (stored) updateScheme(stored);\n\t\t\tstartWebListener();\n\t\t}\n\t\treturn onUserSchemeChange((setting, value) => {\n\t\t\tsetState({\n\t\t\t\tsetting,\n\t\t\t\tvalue\n\t\t\t});\n\t\t});\n\t}, []);\n\treturn useMemo(() => ({\n\t\tsetting: resolvedState.setting,\n\t\tvalue: resolvedState.value,\n\t\tset: setUserScheme\n\t}), [resolvedState.setting, resolvedState.value]);\n}\n\nexport { getForceScheme, getUserScheme, onUserSchemeChange, setForceScheme, setUserScheme, useUserScheme };"],"mappings":"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","ignoreList":[]}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { useIsomorphicLayoutEffect } from "@vxrn/use-isomorphic-layout-effect";
|
|
2
2
|
import { useMemo, useState } from "react";
|
|
3
3
|
import { Appearance } from "react-native";
|
|
4
|
+
import { getStorageItem, setStorageItem } from "./safeStorage.native.js";
|
|
4
5
|
var listeners = /* @__PURE__ */new Set();
|
|
5
6
|
var storageKey = "vxrn-scheme";
|
|
6
7
|
var _forceScheme = null;
|
|
@@ -10,13 +11,11 @@ function notifyListeners() {
|
|
|
10
11
|
});
|
|
11
12
|
}
|
|
12
13
|
function restoreUnforcedScheme() {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
return;
|
|
19
|
-
}
|
|
14
|
+
var stored = getStorageItem(storageKey);
|
|
15
|
+
if (stored) {
|
|
16
|
+
currentSetting = stored;
|
|
17
|
+
currentValue = stored === "system" ? resolveValue("system") : stored;
|
|
18
|
+
return;
|
|
20
19
|
}
|
|
21
20
|
currentSetting = "system";
|
|
22
21
|
currentValue = resolveValue("system");
|
|
@@ -37,10 +36,8 @@ function getForceScheme() {
|
|
|
37
36
|
return _forceScheme;
|
|
38
37
|
}
|
|
39
38
|
function getInitialSetting() {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
if (stored === "light" || stored === "dark" || stored === "system") return stored;
|
|
43
|
-
}
|
|
39
|
+
var stored = getStorageItem(storageKey);
|
|
40
|
+
if (stored === "light" || stored === "dark" || stored === "system") return stored;
|
|
44
41
|
return "system";
|
|
45
42
|
}
|
|
46
43
|
function getInitialValue(setting) {
|
|
@@ -89,7 +86,7 @@ function updateScheme(setting) {
|
|
|
89
86
|
}
|
|
90
87
|
function setUserScheme(setting) {
|
|
91
88
|
if (_forceScheme) return;
|
|
92
|
-
|
|
89
|
+
setStorageItem(storageKey, setting);
|
|
93
90
|
updateScheme(setting);
|
|
94
91
|
}
|
|
95
92
|
function getUserScheme() {
|
|
@@ -117,10 +114,8 @@ function useUserScheme() {
|
|
|
117
114
|
var resolvedState = state.setting === snapshot.setting && state.value === snapshot.value ? state : snapshot;
|
|
118
115
|
useIsomorphicLayoutEffect(function () {
|
|
119
116
|
if (!_forceScheme) {
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
if (stored) updateScheme(stored);
|
|
123
|
-
}
|
|
117
|
+
var stored = getStorageItem(storageKey);
|
|
118
|
+
if (stored) updateScheme(stored);
|
|
124
119
|
startWebListener();
|
|
125
120
|
}
|
|
126
121
|
return onUserSchemeChange(function (setting, value) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["useIsomorphicLayoutEffect","useMemo","useState","Appearance","listeners","Set","storageKey","_forceScheme","notifyListeners","forEach","listener","currentSetting","currentValue","restoreUnforcedScheme","localStorage","stored","getItem","resolveValue","setForceScheme","scheme","wasForced","startWebListener","getForceScheme","getInitialSetting","getInitialValue","setting","getColorScheme","initialSetting","addChangeListener","next","colorScheme","updateValueFromSystem","isWebListening","_window_matchMedia","_window","_matcher_addEventListener","matcher","window","matchMedia","call","onSystemChange","onSystemChange2","addEventListener","value","updateScheme","setColorScheme","setUserScheme","setItem","getUserScheme","onUserSchemeChange","add","delete","useUserScheme","state","setState","snapshot","resolvedState","set"],"sources":["userScheme.native.js"],"sourcesContent":["import { useIsomorphicLayoutEffect } from \"@vxrn/use-isomorphic-layout-effect\";\nimport { useMemo, useState } from \"react\";\nimport { Appearance } from \"react-native\";\n\nvar listeners = /* @__PURE__ */ new Set();\nvar storageKey = \"vxrn-scheme\";\nvar _forceScheme = null;\nfunction notifyListeners() {\n\tlisteners.forEach(function(listener) {\n\t\tlistener(currentSetting, currentValue);\n\t});\n}\nfunction restoreUnforcedScheme() {\n\tif (typeof localStorage !== \"undefined\") {\n\t\tvar stored = localStorage.getItem(storageKey);\n\t\tif (stored) {\n\t\t\tcurrentSetting = stored;\n\t\t\tcurrentValue = stored === \"system\" ? resolveValue(\"system\") : stored;\n\t\t\treturn;\n\t\t}\n\t}\n\tcurrentSetting = \"system\";\n\tcurrentValue = resolveValue(\"system\");\n}\nfunction setForceScheme(scheme) {\n\tvar wasForced = _forceScheme;\n\tif (wasForced === scheme) return;\n\t_forceScheme = scheme;\n\tif (scheme) {\n\t\tcurrentSetting = scheme;\n\t\tcurrentValue = scheme;\n\t} else if (wasForced) {\n\t\trestoreUnforcedScheme();\n\t\tstartWebListener();\n\t}\n}\nfunction getForceScheme() {\n\treturn _forceScheme;\n}\nfunction getInitialSetting() {\n\tif (typeof localStorage !== \"undefined\") {\n\t\tvar stored = localStorage.getItem(storageKey);\n\t\tif (stored === \"light\" || stored === \"dark\" || stored === \"system\") return stored;\n\t}\n\treturn \"system\";\n}\nfunction getInitialValue(setting) {\n\tif (setting === \"system\") return Appearance.getColorScheme() === \"dark\" ? \"dark\" : \"light\";\n\treturn setting;\n}\nvar initialSetting = getInitialSetting();\nvar currentSetting = initialSetting;\nvar currentValue = getInitialValue(initialSetting);\nAppearance.addChangeListener(function(next) {\n\tif (currentSetting === \"system\" && next.colorScheme) updateValueFromSystem();\n});\nvar isWebListening = false;\nfunction startWebListener() {\n\tvar _window_matchMedia, _window, _matcher_addEventListener;\n\tif (isWebListening) return;\n\tisWebListening = true;\n\tvar matcher = typeof window !== \"undefined\" ? (_window_matchMedia = (_window = window).matchMedia) === null || _window_matchMedia === void 0 ? void 0 : _window_matchMedia.call(_window, \"(prefers-color-scheme: dark)\") : null;\n\tvar onSystemChange = function onSystemChange2() {\n\t\tif (currentSetting === \"system\") updateValueFromSystem();\n\t};\n\tonSystemChange();\n\tmatcher === null || matcher === void 0 || (_matcher_addEventListener = matcher.addEventListener) == null || _matcher_addEventListener.call(matcher, \"change\", onSystemChange);\n}\nfunction resolveValue(setting) {\n\tif (setting === \"system\") return Appearance.getColorScheme() === \"dark\" ? \"dark\" : \"light\";\n\treturn setting;\n}\nfunction updateValueFromSystem() {\n\tif (_forceScheme) return;\n\tvar value = resolveValue(\"system\");\n\tif (value !== currentValue) {\n\t\tcurrentValue = value;\n\t\tnotifyListeners();\n\t}\n}\nfunction updateScheme(setting) {\n\tif (_forceScheme) return;\n\tvar value = setting === \"system\" ? resolveValue(\"system\") : setting;\n\tif (value !== currentValue || currentSetting !== setting) {\n\t\tcurrentSetting = setting;\n\t\tcurrentValue = value;\n\t\tif (setting !== \"system\") Appearance.setColorScheme(value);\n\t\telse Appearance.setColorScheme(\"unspecified\");\n\t\tnotifyListeners();\n\t}\n}\nfunction setUserScheme(setting) {\n\tif (_forceScheme) return;\n\tif (typeof localStorage !== \"undefined\") localStorage.setItem(storageKey, setting);\n\tupdateScheme(setting);\n}\nfunction getUserScheme() {\n\tif (_forceScheme) return {\n\t\tsetting: _forceScheme,\n\t\tvalue: _forceScheme\n\t};\n\treturn {\n\t\tsetting: currentSetting,\n\t\tvalue: currentValue\n\t};\n}\nfunction onUserSchemeChange(listener) {\n\tlisteners.add(listener);\n\tlistener(currentSetting, currentValue);\n\treturn function() {\n\t\tlisteners.delete(listener);\n\t};\n}\nfunction useUserScheme() {\n\tvar [state, setState] = useState(function() {\n\t\treturn getUserScheme();\n\t});\n\tvar snapshot = getUserScheme();\n\tvar resolvedState = state.setting === snapshot.setting && state.value === snapshot.value ? state : snapshot;\n\tuseIsomorphicLayoutEffect(function() {\n\t\tif (!_forceScheme) {\n\t\t\tif (typeof localStorage !== \"undefined\") {\n\t\t\t\tvar stored = localStorage.getItem(storageKey);\n\t\t\t\tif (stored) updateScheme(stored);\n\t\t\t}\n\t\t\tstartWebListener();\n\t\t}\n\t\treturn onUserSchemeChange(function(setting, value) {\n\t\t\tsetState({\n\t\t\t\tsetting,\n\t\t\t\tvalue\n\t\t\t});\n\t\t});\n\t}, []);\n\treturn useMemo(function() {\n\t\treturn {\n\t\t\tsetting: resolvedState.setting,\n\t\t\tvalue: resolvedState.value,\n\t\t\tset: setUserScheme\n\t\t};\n\t}, [resolvedState.setting, resolvedState.value]);\n}\n\nexport { getForceScheme, getUserScheme, onUserSchemeChange, setForceScheme, setUserScheme, useUserScheme };"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"names":["useIsomorphicLayoutEffect","useMemo","useState","Appearance","getStorageItem","setStorageItem","listeners","Set","storageKey","_forceScheme","notifyListeners","forEach","listener","currentSetting","currentValue","restoreUnforcedScheme","stored","resolveValue","setForceScheme","scheme","wasForced","startWebListener","getForceScheme","getInitialSetting","getInitialValue","setting","getColorScheme","initialSetting","addChangeListener","next","colorScheme","updateValueFromSystem","isWebListening","_window_matchMedia","_window","_matcher_addEventListener","matcher","window","matchMedia","call","onSystemChange","onSystemChange2","addEventListener","value","updateScheme","setColorScheme","setUserScheme","getUserScheme","onUserSchemeChange","add","delete","useUserScheme","state","setState","snapshot","resolvedState","set"],"sources":["userScheme.native.js"],"sourcesContent":["import { useIsomorphicLayoutEffect } from \"@vxrn/use-isomorphic-layout-effect\";\nimport { useMemo, useState } from \"react\";\nimport { Appearance } from \"react-native\";\nimport { getStorageItem, setStorageItem } from \"./safeStorage\";\n\nvar listeners = /* @__PURE__ */ new Set();\nvar storageKey = \"vxrn-scheme\";\nvar _forceScheme = null;\nfunction notifyListeners() {\n\tlisteners.forEach(function(listener) {\n\t\tlistener(currentSetting, currentValue);\n\t});\n}\nfunction restoreUnforcedScheme() {\n\tvar stored = getStorageItem(storageKey);\n\tif (stored) {\n\t\tcurrentSetting = stored;\n\t\tcurrentValue = stored === \"system\" ? resolveValue(\"system\") : stored;\n\t\treturn;\n\t}\n\tcurrentSetting = \"system\";\n\tcurrentValue = resolveValue(\"system\");\n}\nfunction setForceScheme(scheme) {\n\tvar wasForced = _forceScheme;\n\tif (wasForced === scheme) return;\n\t_forceScheme = scheme;\n\tif (scheme) {\n\t\tcurrentSetting = scheme;\n\t\tcurrentValue = scheme;\n\t} else if (wasForced) {\n\t\trestoreUnforcedScheme();\n\t\tstartWebListener();\n\t}\n}\nfunction getForceScheme() {\n\treturn _forceScheme;\n}\nfunction getInitialSetting() {\n\tvar stored = getStorageItem(storageKey);\n\tif (stored === \"light\" || stored === \"dark\" || stored === \"system\") return stored;\n\treturn \"system\";\n}\nfunction getInitialValue(setting) {\n\tif (setting === \"system\") return Appearance.getColorScheme() === \"dark\" ? \"dark\" : \"light\";\n\treturn setting;\n}\nvar initialSetting = getInitialSetting();\nvar currentSetting = initialSetting;\nvar currentValue = getInitialValue(initialSetting);\nAppearance.addChangeListener(function(next) {\n\tif (currentSetting === \"system\" && next.colorScheme) updateValueFromSystem();\n});\nvar isWebListening = false;\nfunction startWebListener() {\n\tvar _window_matchMedia, _window, _matcher_addEventListener;\n\tif (isWebListening) return;\n\tisWebListening = true;\n\tvar matcher = typeof window !== \"undefined\" ? (_window_matchMedia = (_window = window).matchMedia) === null || _window_matchMedia === void 0 ? void 0 : _window_matchMedia.call(_window, \"(prefers-color-scheme: dark)\") : null;\n\tvar onSystemChange = function onSystemChange2() {\n\t\tif (currentSetting === \"system\") updateValueFromSystem();\n\t};\n\tonSystemChange();\n\tmatcher === null || matcher === void 0 || (_matcher_addEventListener = matcher.addEventListener) == null || _matcher_addEventListener.call(matcher, \"change\", onSystemChange);\n}\nfunction resolveValue(setting) {\n\tif (setting === \"system\") return Appearance.getColorScheme() === \"dark\" ? \"dark\" : \"light\";\n\treturn setting;\n}\nfunction updateValueFromSystem() {\n\tif (_forceScheme) return;\n\tvar value = resolveValue(\"system\");\n\tif (value !== currentValue) {\n\t\tcurrentValue = value;\n\t\tnotifyListeners();\n\t}\n}\nfunction updateScheme(setting) {\n\tif (_forceScheme) return;\n\tvar value = setting === \"system\" ? resolveValue(\"system\") : setting;\n\tif (value !== currentValue || currentSetting !== setting) {\n\t\tcurrentSetting = setting;\n\t\tcurrentValue = value;\n\t\tif (setting !== \"system\") Appearance.setColorScheme(value);\n\t\telse Appearance.setColorScheme(\"unspecified\");\n\t\tnotifyListeners();\n\t}\n}\nfunction setUserScheme(setting) {\n\tif (_forceScheme) return;\n\tsetStorageItem(storageKey, setting);\n\tupdateScheme(setting);\n}\nfunction getUserScheme() {\n\tif (_forceScheme) return {\n\t\tsetting: _forceScheme,\n\t\tvalue: _forceScheme\n\t};\n\treturn {\n\t\tsetting: currentSetting,\n\t\tvalue: currentValue\n\t};\n}\nfunction onUserSchemeChange(listener) {\n\tlisteners.add(listener);\n\tlistener(currentSetting, currentValue);\n\treturn function() {\n\t\tlisteners.delete(listener);\n\t};\n}\nfunction useUserScheme() {\n\tvar [state, setState] = useState(function() {\n\t\treturn getUserScheme();\n\t});\n\tvar snapshot = getUserScheme();\n\tvar resolvedState = state.setting === snapshot.setting && state.value === snapshot.value ? state : snapshot;\n\tuseIsomorphicLayoutEffect(function() {\n\t\tif (!_forceScheme) {\n\t\t\tvar stored = getStorageItem(storageKey);\n\t\t\tif (stored) updateScheme(stored);\n\t\t\tstartWebListener();\n\t\t}\n\t\treturn onUserSchemeChange(function(setting, value) {\n\t\t\tsetState({\n\t\t\t\tsetting,\n\t\t\t\tvalue\n\t\t\t});\n\t\t});\n\t}, []);\n\treturn useMemo(function() {\n\t\treturn {\n\t\t\tsetting: resolvedState.setting,\n\t\t\tvalue: resolvedState.value,\n\t\t\tset: setUserScheme\n\t\t};\n\t}, [resolvedState.setting, resolvedState.value]);\n}\n\nexport { getForceScheme, getUserScheme, onUserSchemeChange, setForceScheme, setUserScheme, useUserScheme };"],"mappings":"AAAA,SAASA,yBAAyB,QAAQ,oCAAoC;AAC9E,SAASC,OAAO,EAAEC,QAAQ,QAAQ,OAAO;AACzC,SAASC,UAAU,QAAQ,cAAc;AACzC,SAASC,cAAc,EAAEC,cAAc,QAAQ,yBAAe;AAE9D,IAAIC,SAAS,GAAG,eAAgB,IAAIC,GAAG,CAAC,CAAC;AACzC,IAAIC,UAAU,GAAG,aAAa;AAC9B,IAAIC,YAAY,GAAG,IAAI;AACvB,SAASC,eAAeA,CAAA,EAAG;EAC1BJ,SAAS,CAACK,OAAO,CAAC,UAASC,QAAQ,EAAE;IACpCA,QAAQ,CAACC,cAAc,EAAEC,YAAY,CAAC;EACvC,CAAC,CAAC;AACH;AACA,SAASC,qBAAqBA,CAAA,EAAG;EAChC,IAAIC,MAAM,GAAGZ,cAAc,CAACI,UAAU,CAAC;EACvC,IAAIQ,MAAM,EAAE;IACXH,cAAc,GAAGG,MAAM;IACvBF,YAAY,GAAGE,MAAM,KAAK,QAAQ,GAAGC,YAAY,CAAC,QAAQ,CAAC,GAAGD,MAAM;IACpE;EACD;EACAH,cAAc,GAAG,QAAQ;EACzBC,YAAY,GAAGG,YAAY,CAAC,QAAQ,CAAC;AACtC;AACA,SAASC,cAAcA,CAACC,MAAM,EAAE;EAC/B,IAAIC,SAAS,GAAGX,YAAY;EAC5B,IAAIW,SAAS,KAAKD,MAAM,EAAE;EAC1BV,YAAY,GAAGU,MAAM;EACrB,IAAIA,MAAM,EAAE;IACXN,cAAc,GAAGM,MAAM;IACvBL,YAAY,GAAGK,MAAM;EACtB,CAAC,MAAM,IAAIC,SAAS,EAAE;IACrBL,qBAAqB,CAAC,CAAC;IACvBM,gBAAgB,CAAC,CAAC;EACnB;AACD;AACA,SAASC,cAAcA,CAAA,EAAG;EACzB,OAAOb,YAAY;AACpB;AACA,SAASc,iBAAiBA,CAAA,EAAG;EAC5B,IAAIP,MAAM,GAAGZ,cAAc,CAACI,UAAU,CAAC;EACvC,IAAIQ,MAAM,KAAK,OAAO,IAAIA,MAAM,KAAK,MAAM,IAAIA,MAAM,KAAK,QAAQ,EAAE,OAAOA,MAAM;EACjF,OAAO,QAAQ;AAChB;AACA,SAASQ,eAAeA,CAACC,OAAO,EAAE;EACjC,IAAIA,OAAO,KAAK,QAAQ,EAAE,OAAOtB,UAAU,CAACuB,cAAc,CAAC,CAAC,KAAK,MAAM,GAAG,MAAM,GAAG,OAAO;EAC1F,OAAOD,OAAO;AACf;AACA,IAAIE,cAAc,GAAGJ,iBAAiB,CAAC,CAAC;AACxC,IAAIV,cAAc,GAAGc,cAAc;AACnC,IAAIb,YAAY,GAAGU,eAAe,CAACG,cAAc,CAAC;AAClDxB,UAAU,CAACyB,iBAAiB,CAAC,UAASC,IAAI,EAAE;EAC3C,IAAIhB,cAAc,KAAK,QAAQ,IAAIgB,IAAI,CAACC,WAAW,EAAEC,qBAAqB,CAAC,CAAC;AAC7E,CAAC,CAAC;AACF,IAAIC,cAAc,GAAG,KAAK;AAC1B,SAASX,gBAAgBA,CAAA,EAAG;EAC3B,IAAIY,kBAAkB,EAAEC,OAAO,EAAEC,yBAAyB;EAC1D,IAAIH,cAAc,EAAE;EACpBA,cAAc,GAAG,IAAI;EACrB,IAAII,OAAO,GAAG,OAAOC,MAAM,KAAK,WAAW,GAAG,CAACJ,kBAAkB,GAAG,CAACC,OAAO,GAAGG,MAAM,EAAEC,UAAU,MAAM,IAAI,IAAIL,kBAAkB,KAAK,KAAK,CAAC,GAAG,KAAK,CAAC,GAAGA,kBAAkB,CAACM,IAAI,CAACL,OAAO,EAAE,8BAA8B,CAAC,GAAG,IAAI;EAC/N,IAAIM,cAAc,GAAG,SAASC,eAAeA,CAAA,EAAG;IAC/C,IAAI5B,cAAc,KAAK,QAAQ,EAAEkB,qBAAqB,CAAC,CAAC;EACzD,CAAC;EACDS,cAAc,CAAC,CAAC;EAChBJ,OAAO,KAAK,IAAI,IAAIA,OAAO,KAAK,KAAK,CAAC,IAAI,CAACD,yBAAyB,GAAGC,OAAO,CAACM,gBAAgB,KAAK,IAAI,IAAIP,yBAAyB,CAACI,IAAI,CAACH,OAAO,EAAE,QAAQ,EAAEI,cAAc,CAAC;AAC9K;AACA,SAASvB,YAAYA,CAACQ,OAAO,EAAE;EAC9B,IAAIA,OAAO,KAAK,QAAQ,EAAE,OAAOtB,UAAU,CAACuB,cAAc,CAAC,CAAC,KAAK,MAAM,GAAG,MAAM,GAAG,OAAO;EAC1F,OAAOD,OAAO;AACf;AACA,SAASM,qBAAqBA,CAAA,EAAG;EAChC,IAAItB,YAAY,EAAE;EAClB,IAAIkC,KAAK,GAAG1B,YAAY,CAAC,QAAQ,CAAC;EAClC,IAAI0B,KAAK,KAAK7B,YAAY,EAAE;IAC3BA,YAAY,GAAG6B,KAAK;IACpBjC,eAAe,CAAC,CAAC;EAClB;AACD;AACA,SAASkC,YAAYA,CAACnB,OAAO,EAAE;EAC9B,IAAIhB,YAAY,EAAE;EAClB,IAAIkC,KAAK,GAAGlB,OAAO,KAAK,QAAQ,GAAGR,YAAY,CAAC,QAAQ,CAAC,GAAGQ,OAAO;EACnE,IAAIkB,KAAK,KAAK7B,YAAY,IAAID,cAAc,KAAKY,OAAO,EAAE;IACzDZ,cAAc,GAAGY,OAAO;IACxBX,YAAY,GAAG6B,KAAK;IACpB,IAAIlB,OAAO,KAAK,QAAQ,EAAEtB,UAAU,CAAC0C,cAAc,CAACF,KAAK,CAAC,CAAC,KACtDxC,UAAU,CAAC0C,cAAc,CAAC,aAAa,CAAC;IAC7CnC,eAAe,CAAC,CAAC;EAClB;AACD;AACA,SAASoC,aAAaA,CAACrB,OAAO,EAAE;EAC/B,IAAIhB,YAAY,EAAE;EAClBJ,cAAc,CAACG,UAAU,EAAEiB,OAAO,CAAC;EACnCmB,YAAY,CAACnB,OAAO,CAAC;AACtB;AACA,SAASsB,aAAaA,CAAA,EAAG;EACxB,IAAItC,YAAY,EAAE,OAAO;IACxBgB,OAAO,EAAEhB,YAAY;IACrBkC,KAAK,EAAElC;EACR,CAAC;EACD,OAAO;IACNgB,OAAO,EAAEZ,cAAc;IACvB8B,KAAK,EAAE7B;EACR,CAAC;AACF;AACA,SAASkC,kBAAkBA,CAACpC,QAAQ,EAAE;EACrCN,SAAS,CAAC2C,GAAG,CAACrC,QAAQ,CAAC;EACvBA,QAAQ,CAACC,cAAc,EAAEC,YAAY,CAAC;EACtC,OAAO,YAAW;IACjBR,SAAS,CAAC4C,MAAM,CAACtC,QAAQ,CAAC;EAC3B,CAAC;AACF;AACA,SAASuC,aAAaA,CAAA,EAAG;EACxB,IAAI,CAACC,KAAK,EAAEC,QAAQ,CAAC,GAAGnD,QAAQ,CAAC,YAAW;IAC3C,OAAO6C,aAAa,CAAC,CAAC;EACvB,CAAC,CAAC;EACF,IAAIO,QAAQ,GAAGP,aAAa,CAAC,CAAC;EAC9B,IAAIQ,aAAa,GAAGH,KAAK,CAAC3B,OAAO,KAAK6B,QAAQ,CAAC7B,OAAO,IAAI2B,KAAK,CAACT,KAAK,KAAKW,QAAQ,CAACX,KAAK,GAAGS,KAAK,GAAGE,QAAQ;EAC3GtD,yBAAyB,CAAC,YAAW;IACpC,IAAI,CAACS,YAAY,EAAE;MAClB,IAAIO,MAAM,GAAGZ,cAAc,CAACI,UAAU,CAAC;MACvC,IAAIQ,MAAM,EAAE4B,YAAY,CAAC5B,MAAM,CAAC;MAChCK,gBAAgB,CAAC,CAAC;IACnB;IACA,OAAO2B,kBAAkB,CAAC,UAASvB,OAAO,EAAEkB,KAAK,EAAE;MAClDU,QAAQ,CAAC;QACR5B,OAAO;QACPkB;MACD,CAAC,CAAC;IACH,CAAC,CAAC;EACH,CAAC,EAAE,EAAE,CAAC;EACN,OAAO1C,OAAO,CAAC,YAAW;IACzB,OAAO;MACNwB,OAAO,EAAE8B,aAAa,CAAC9B,OAAO;MAC9BkB,KAAK,EAAEY,aAAa,CAACZ,KAAK;MAC1Ba,GAAG,EAAEV;IACN,CAAC;EACF,CAAC,EAAE,CAACS,aAAa,CAAC9B,OAAO,EAAE8B,aAAa,CAACZ,KAAK,CAAC,CAAC;AACjD;AAEA,SAASrB,cAAc,EAAEyB,aAAa,EAAEC,kBAAkB,EAAE9B,cAAc,EAAE4B,aAAa,EAAEK,aAAa","ignoreList":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vxrn/color-scheme",
|
|
3
|
-
"version": "1.19.
|
|
3
|
+
"version": "1.19.5",
|
|
4
4
|
"sideEffects": false,
|
|
5
5
|
"exports": {
|
|
6
6
|
"./package.json": "./package.json",
|
|
@@ -26,16 +26,18 @@
|
|
|
26
26
|
"clean:build": "tamagui-build clean:build",
|
|
27
27
|
"lint": "npx biome check src",
|
|
28
28
|
"lint:fix": "npx biome check --write --unsafe src",
|
|
29
|
+
"test": "vitest run --dir src",
|
|
29
30
|
"typecheck": "tsc --noEmit",
|
|
30
31
|
"watch": "tamagui-build --watch"
|
|
31
32
|
},
|
|
32
33
|
"dependencies": {
|
|
33
|
-
"@vxrn/use-isomorphic-layout-effect": "1.19.
|
|
34
|
+
"@vxrn/use-isomorphic-layout-effect": "1.19.5"
|
|
34
35
|
},
|
|
35
36
|
"devDependencies": {
|
|
36
37
|
"@tamagui/build": "2.3.0",
|
|
37
38
|
"react": "19.2.0",
|
|
38
|
-
"react-native": "0.83.2"
|
|
39
|
+
"react-native": "0.83.2",
|
|
40
|
+
"vitest": "^4.1.0"
|
|
39
41
|
},
|
|
40
42
|
"peerDependencies": {
|
|
41
43
|
"react": "19.2.0",
|
package/src/index.tsx
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { useIsomorphicLayoutEffect } from '@vxrn/use-isomorphic-layout-effect'
|
|
2
|
+
import { getStorageItem } from './safeStorage'
|
|
2
3
|
import type { Scheme } from './systemScheme'
|
|
3
4
|
import {
|
|
4
5
|
getForceScheme,
|
|
@@ -44,8 +45,8 @@ export function SchemeProvider({
|
|
|
44
45
|
if (process.env.TAMAGUI_TARGET !== 'native') {
|
|
45
46
|
// when defaultScheme is set and no stored preference, apply it on mount
|
|
46
47
|
useIsomorphicLayoutEffect(() => {
|
|
47
|
-
if (!forceScheme && defaultScheme
|
|
48
|
-
if (!
|
|
48
|
+
if (!forceScheme && defaultScheme) {
|
|
49
|
+
if (!getStorageItem(storageKey)) {
|
|
49
50
|
setUserScheme(defaultScheme)
|
|
50
51
|
}
|
|
51
52
|
}
|
|
@@ -76,14 +77,16 @@ d.add('${getClassName(forceScheme)}')`
|
|
|
76
77
|
: `window.matchMedia('(prefers-color-scheme: dark)').matches`
|
|
77
78
|
|
|
78
79
|
const seedStorage = defaultScheme
|
|
79
|
-
?
|
|
80
|
+
? `;if(!e){localStorage.setItem('${storageKey}','${defaultScheme}')}`
|
|
80
81
|
: ''
|
|
81
82
|
|
|
83
|
+
// localStorage access throws when storage is blocked - guard so the theme
|
|
84
|
+
// still applies (falling back to system/default) instead of erroring
|
|
82
85
|
scriptContent = `let d = document.documentElement.classList
|
|
83
86
|
d.remove('${getClassName('light')}')
|
|
84
87
|
d.remove('${getClassName('dark')}')
|
|
85
|
-
let e =
|
|
86
|
-
${seedStorage}
|
|
88
|
+
let e = null
|
|
89
|
+
try { e = localStorage.getItem('${storageKey}')${seedStorage} } catch (_e) {}
|
|
87
90
|
let t = 'system' === e || !e
|
|
88
91
|
? ${fallback}
|
|
89
92
|
: e === 'dark'
|
|
@@ -118,7 +121,8 @@ export function MetaTheme({
|
|
|
118
121
|
const scriptContent = forced
|
|
119
122
|
? `document.getElementById('vxrn-theme-color').setAttribute('content','${forced === 'dark' ? darkColor : lightColor}')`
|
|
120
123
|
: `let dc = document.getElementById('vxrn-theme-color')
|
|
121
|
-
let e1 =
|
|
124
|
+
let e1 = null
|
|
125
|
+
try { e1 = localStorage.getItem('${storageKey}') } catch (_e) {}
|
|
122
126
|
let isD = 'system' === e1 || !e1 ? window.matchMedia('(prefers-color-scheme: dark)').matches : e1 === 'dark'
|
|
123
127
|
dc.setAttribute('content', isD ? '${darkColor}' : '${lightColor}')`
|
|
124
128
|
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { afterEach, describe, expect, it } from 'vitest'
|
|
2
|
+
import { getStorageItem, setStorageItem } from './safeStorage'
|
|
3
|
+
|
|
4
|
+
// localStorage isn't a real global in the node test env, so each test installs
|
|
5
|
+
// its own descriptor and we clear it afterwards.
|
|
6
|
+
afterEach(() => {
|
|
7
|
+
delete (globalThis as any).localStorage
|
|
8
|
+
})
|
|
9
|
+
|
|
10
|
+
function defineLocalStorage(descriptor: PropertyDescriptor) {
|
|
11
|
+
Object.defineProperty(globalThis, 'localStorage', {
|
|
12
|
+
configurable: true,
|
|
13
|
+
...descriptor,
|
|
14
|
+
})
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
describe('safeStorage', () => {
|
|
18
|
+
it('reads and writes through to a working localStorage', () => {
|
|
19
|
+
const store = new Map<string, string>()
|
|
20
|
+
defineLocalStorage({
|
|
21
|
+
value: {
|
|
22
|
+
getItem: (k: string) => (store.has(k) ? store.get(k)! : null),
|
|
23
|
+
setItem: (k: string, v: string) => void store.set(k, v),
|
|
24
|
+
},
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
setStorageItem('vxrn-scheme', 'dark')
|
|
28
|
+
expect(getStorageItem('vxrn-scheme')).toBe('dark')
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
// the actual prod bug: Chrome with storage blocked makes the localStorage
|
|
32
|
+
// getter throw SecurityError, so even `typeof localStorage` throws. accessing
|
|
33
|
+
// it must degrade to null, not crash hydration.
|
|
34
|
+
it('returns null instead of throwing when the localStorage getter throws', () => {
|
|
35
|
+
defineLocalStorage({
|
|
36
|
+
get() {
|
|
37
|
+
throw new Error('Failed to read the "localStorage" property: Access is denied.')
|
|
38
|
+
},
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
expect(() => getStorageItem('vxrn-scheme')).not.toThrow()
|
|
42
|
+
expect(getStorageItem('vxrn-scheme')).toBeNull()
|
|
43
|
+
expect(() => setStorageItem('vxrn-scheme', 'dark')).not.toThrow()
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
it('swallows errors when setItem throws (quota / blocked)', () => {
|
|
47
|
+
defineLocalStorage({
|
|
48
|
+
value: {
|
|
49
|
+
getItem: () => null,
|
|
50
|
+
setItem: () => {
|
|
51
|
+
throw new Error('QuotaExceededError')
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
})
|
|
55
|
+
|
|
56
|
+
expect(() => setStorageItem('vxrn-scheme', 'dark')).not.toThrow()
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
it('returns null when localStorage is undefined (native)', () => {
|
|
60
|
+
expect(getStorageItem('vxrn-scheme')).toBeNull()
|
|
61
|
+
expect(() => setStorageItem('vxrn-scheme', 'dark')).not.toThrow()
|
|
62
|
+
})
|
|
63
|
+
})
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
// accessing localStorage can THROW, not just be undefined: Chrome with
|
|
2
|
+
// cookies/site-data blocked, sandboxed iframes, and some private-mode browsers
|
|
3
|
+
// make `window.localStorage` a getter that throws SecurityError. `typeof
|
|
4
|
+
// localStorage` evaluates that getter, so it throws too and is useless as a
|
|
5
|
+
// guard. on native it's simply not defined. wrap every access in try/catch so a
|
|
6
|
+
// blocked-storage user degrades gracefully instead of crashing hydration.
|
|
7
|
+
|
|
8
|
+
export function getStorageItem(key: string): string | null {
|
|
9
|
+
try {
|
|
10
|
+
return localStorage.getItem(key)
|
|
11
|
+
} catch {
|
|
12
|
+
return null
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function setStorageItem(key: string, value: string): void {
|
|
17
|
+
try {
|
|
18
|
+
localStorage.setItem(key, value)
|
|
19
|
+
} catch {}
|
|
20
|
+
}
|