-
Notifications
You must be signed in to change notification settings - Fork 299
Expand file tree
/
Copy pathconfigprovider.tsx
More file actions
95 lines (83 loc) · 2.39 KB
/
Copy pathconfigprovider.tsx
File metadata and controls
95 lines (83 loc) · 2.39 KB
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
83
84
85
86
87
88
89
90
91
92
93
94
95
import React, { FunctionComponent, createContext, useContext } from 'react'
import classNames from 'classnames'
import kebabCase from 'lodash.kebabcase'
import isEqual from 'react-fast-compare'
import { useMemo } from '@/hooks/use-memo'
import zhCN from '@/locales/zh-CN'
import { inBrowser } from '@/utils'
import { WebConfigProviderProps, Locales as LocalesType } from '@/types'
type Locales = Partial<LocalesType>
export const defaultConfigRef: {
current: WebConfigProviderProps<Locales>
} = {
current: {
locale: zhCN,
direction: 'ltr',
},
}
export const setDefaultConfig = (config: WebConfigProviderProps<Locales>) => {
defaultConfigRef.current = config
}
export const getDefaultConfig = () => {
return defaultConfigRef.current
}
const ConfigContext = createContext<WebConfigProviderProps<Locales> | null>(
null
)
export const useConfig = () => {
return useContext(ConfigContext) ?? getDefaultConfig()
}
function convertThemeVarsToCSSVars(themeVars: Record<string, string | number>) {
const cssVars: Record<string, string | number> = {}
Object.keys(themeVars).forEach((key) => {
cssVars[`--${kebabCase(key)}`] = themeVars[key]
})
return cssVars
}
export const useRtl = () => {
const { direction } = useConfig()
if (direction) {
return direction === 'rtl'
}
return inBrowser && document.dir === 'rtl'
}
export const ConfigProvider: FunctionComponent<
Partial<WebConfigProviderProps<Locales>>
> = (props) => {
const { style, className, children, direction, ...config } = props
const classPrefix = 'nut-configprovider'
const mergedConfig = useMemo(
() => {
return {
...getDefaultConfig(),
...config,
direction,
}
},
[config, direction],
(prev, next) =>
prev.some((prevTheme, index) => {
const nextTheme = next[index]
return !isEqual(prevTheme, nextTheme)
})
) as WebConfigProviderProps<Locales>
const cssVarStyle = React.useMemo(() => {
return convertThemeVarsToCSSVars(mergedConfig.theme || {})
}, [mergedConfig.theme])
return (
<ConfigContext.Provider value={mergedConfig}>
<div
className={classNames(classPrefix, className)}
style={{
...cssVarStyle,
...style,
direction,
}}
dir={direction}
>
{children}
</div>
</ConfigContext.Provider>
)
}
ConfigProvider.displayName = 'NutConfigProvider'