@flesler/cursor-canvas-web 1.5.1 → 1.5.2
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/package.json
CHANGED
|
@@ -32,4 +32,36 @@ describe('useCanvasState', () => {
|
|
|
32
32
|
|
|
33
33
|
expect(result.current[0]).toBe(true)
|
|
34
34
|
})
|
|
35
|
+
|
|
36
|
+
it('falls back to __canvasJsonState when localStorage throws', () => {
|
|
37
|
+
const storage = Object.getOwnPropertyDescriptor(globalThis, 'localStorage')
|
|
38
|
+
Object.defineProperty(globalThis, 'localStorage', {
|
|
39
|
+
configurable: true,
|
|
40
|
+
get() {
|
|
41
|
+
throw new DOMException('sandboxed', 'SecurityError')
|
|
42
|
+
},
|
|
43
|
+
})
|
|
44
|
+
;(globalThis as { __canvasJsonState?: Record<string, unknown> }).__canvasJsonState = {
|
|
45
|
+
label: 'from-sidecar',
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const { result } = renderHook(() => useCanvasState('label', 'default'))
|
|
49
|
+
|
|
50
|
+
expect(result.current[0]).toBe('from-sidecar')
|
|
51
|
+
delete (globalThis as { __canvasJsonState?: Record<string, unknown> }).__canvasJsonState
|
|
52
|
+
if (storage) {
|
|
53
|
+
Object.defineProperty(globalThis, 'localStorage', storage)
|
|
54
|
+
}
|
|
55
|
+
})
|
|
56
|
+
|
|
57
|
+
it('reads global __canvasJsonState when localStorage has no value', () => {
|
|
58
|
+
;(globalThis as { __canvasJsonState?: Record<string, unknown> }).__canvasJsonState = {
|
|
59
|
+
label: 'from-sidecar',
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const { result } = renderHook(() => useCanvasState('label', 'default'))
|
|
63
|
+
|
|
64
|
+
expect(result.current[0]).toBe('from-sidecar')
|
|
65
|
+
delete (globalThis as { __canvasJsonState?: Record<string, unknown> }).__canvasJsonState
|
|
66
|
+
})
|
|
35
67
|
})
|
|
@@ -8,13 +8,15 @@ export function useCanvasState<T>(
|
|
|
8
8
|
const storageKey = `canvas:${key}`
|
|
9
9
|
|
|
10
10
|
const [state, setState] = useState<T>(() => {
|
|
11
|
-
if (typeof localStorage === 'undefined') return defaultValue
|
|
12
11
|
try {
|
|
13
12
|
const raw = localStorage.getItem(storageKey)
|
|
14
|
-
|
|
13
|
+
if (raw !== null) return JSON.parse(raw) as T
|
|
15
14
|
} catch {
|
|
16
|
-
|
|
15
|
+
// Sandboxed, SSR, or unavailable; fall through to inlined export state.
|
|
17
16
|
}
|
|
17
|
+
const inline = inlineCanvasState<T>(key)
|
|
18
|
+
if (inline !== undefined) return inline
|
|
19
|
+
return defaultValue
|
|
18
20
|
})
|
|
19
21
|
|
|
20
22
|
const set = useCallback<SetCanvasState<T>>(
|
|
@@ -25,7 +27,7 @@ export function useCanvasState<T>(
|
|
|
25
27
|
? (action as (prev: T) => T)(prev)
|
|
26
28
|
: action
|
|
27
29
|
try {
|
|
28
|
-
localStorage
|
|
30
|
+
localStorage.setItem(storageKey, JSON.stringify(next))
|
|
29
31
|
} catch {
|
|
30
32
|
// Ignore quota / unavailable storage; state still updates in memory.
|
|
31
33
|
}
|
|
@@ -55,3 +57,13 @@ export function mergeStyle(
|
|
|
55
57
|
): CSSProperties {
|
|
56
58
|
return { ...base, ...override }
|
|
57
59
|
}
|
|
60
|
+
|
|
61
|
+
function inlineCanvasState<T>(key: string): T | undefined {
|
|
62
|
+
try {
|
|
63
|
+
const bag = (globalThis as { __canvasJsonState?: Record<string, unknown> }).__canvasJsonState
|
|
64
|
+
if (!bag || !Object.hasOwn(bag, key)) return undefined
|
|
65
|
+
return bag[key] as T
|
|
66
|
+
} catch {
|
|
67
|
+
return undefined
|
|
68
|
+
}
|
|
69
|
+
}
|