-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathcore.tsx
82 lines (65 loc) · 1.79 KB
/
core.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
import React, { cloneElement, createContext, useCallback, useRef, useState } from 'react'
export const PictoContext = createContext({
optimise: (id: string, node: React.ReactElement) => node,
refresh: () => {},
})
interface Cache {
[id: string]: React.ReactElement
}
interface PictoProviderProps {
children: React.ReactNode
}
export const PictoProvider = ({ children }: PictoProviderProps) => {
const forceUpdate = useForceUpdate()
const cache = useRef<Cache>({})
const isPending = useRef(false)
const value = {
optimise(id: string, node: React.ReactElement) {
if (!(id in cache.current)) {
cache.current = { ...cache.current, [id]: node }
isPending.current = true
}
return cloneElement(
node,
{ fill: null, xmlnsXlink: 'http://www.w3.org/1999/xlink' },
<use xlinkHref={'#' + id} />
)
},
refresh() {
if (!isPending) {
return
}
forceUpdate()
isPending.current = false
},
}
return (
<PictoContext.Provider value={value}>
<>
{children}
<Symbols cache={cache} />
</>
</PictoContext.Provider>
)
}
interface SymbolsProps {
cache: React.MutableRefObject<Cache>
}
const Symbols = ({ cache }: SymbolsProps) => {
const entries = Object.entries(cache.current)
if (entries.length < 1) {
return null
}
return (
<svg style={{ display: 'none' }} xmlns="http://www.w3.org/2000/svg">
{Object.entries(cache.current).map(([id, node]) =>
cloneElement(node, { as: 'symbol', className: null, height: null, id, key: id, width: null, xmlns: null })
)}
</svg>
)
}
const useForceUpdate = () => {
const [, updateState] = useState<object>()
const forceUpdate = useCallback(() => updateState({}), [])
return forceUpdate
}