shineout
Version:
Shein 前端组件库
79 lines (66 loc) • 2.15 kB
text/typescript
import cssInject from './vars-inject'
import { capitalize } from './strings'
import { entries } from './objects'
type ObjectProps = { [x: string]: any }
type Accessors = { [U in keyof typeof cssInject]: ObjectProps }
function setOptions(options: any, setter: any) {
if (!options) return
for (const [key, value] of entries(options)) {
if (key === setter) continue
this[key] = value
}
}
function getDOMStyle(dom: HTMLElement) {
document.body.appendChild(dom)
const style = window.getComputedStyle(dom)
Promise.resolve().then(() => {
if (dom.parentElement) dom.parentElement.removeChild(dom)
})
return style
}
function getStyleAttr(className: string, key: keyof CSSStyleDeclaration = 'color') {
const div = document.createElement('div')
div.className = className
return (getDOMStyle as any)(div)[key]
}
let cache: ObjectProps = {}
interface conf {
name: string
attr?: keyof CSSStyleDeclaration
value?: string
parser?: Function
className: string
}
function genAccessors(obj: object, data: ObjectProps) {
data.conf.forEach((item: conf) => {
const { name, className, attr, parser = (v: any) => v } = item
const { info } = data
const cacheKey = `${info.name}-${name}`
Object.defineProperty(obj, name, {
enumerable: true,
get: () => {
if (cache[cacheKey]) return cache[cacheKey]
if (item.value) return item.value
const res = getStyleAttr(className, attr)
cache[cacheKey] = parser(res)
return cache[cacheKey]
},
// eslint-disable-next-line no-return-assign
set: v => {
delete cache[cacheKey]
if (item.value) item.value = v
data[name] = v
},
})
})
}
const accessors = Object.keys(cssInject).reduce((obj, key) => ({ ...obj, [key]: {} }), {}) as Accessors
for (const [key, value] of entries(accessors)) {
const setterName = `set${capitalize(key)}`
value[setterName] = (options: any) => setOptions.call(value, options, setterName)
genAccessors(value, cssInject[key as keyof typeof accessors])
}
export function cleanCache() {
cache = {}
}
export default accessors as Accessors