-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathstyle.ts
57 lines (52 loc) · 1.69 KB
/
style.ts
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
import { ei } from 'epic-inline'
import type { CSSProperties, Styles } from './types'
export const mergeStyles = (styles: CSSProperties[]) => styles.reduce((result, current) => Object.assign(result, current), {})
// TODO manually maintained, same as epic-jsx.
const sizeStyleProperties = [
'width',
'height',
'border',
'margin',
'padding',
'top',
'right',
'bottom',
'left',
'gap',
'rowGap',
'columnGap',
]
function startsWithSizeProperty(propertyName: string) {
return sizeStyleProperties.some((prop) => propertyName.startsWith(prop))
}
function convertStylesToPixels(styleObject: CSSStyleDeclaration) {
const convertedStyles: CSSProperties = {}
for (const key in styleObject) {
if (Object.hasOwn(styleObject, key)) {
const value = styleObject[key]
if (typeof value === 'number' && startsWithSizeProperty(key)) {
convertedStyles[key] = `${value}px`
} else {
convertedStyles[key] = value
}
}
}
return convertedStyles
}
export const toInline = (styles?: string | number | Styles | Styles[]) => {
if (!styles) {
return undefined
}
if (typeof styles === 'string') {
const convertedStyles = ei(styles)
return typeof convertedStyles === 'object' ? convertStylesToPixels(convertedStyles as any) : convertedStyles
}
if (Array.isArray(styles)) {
// This will convert all string based styles if possible, later filters out non-objects for safety.
const mappedStyles = styles.map(toInline) as object[]
// Type inference fail without intermediate variable ;(
const objectStyles = mappedStyles.filter((style) => typeof style === 'object' && style !== null)
return mergeStyles(objectStyles)
}
return styles
}