@solfacil/girassol
Version:
Girassol design system
262 lines (220 loc) • 6.12 kB
text/typescript
type Data = {
colors: Record<string, any>
spacing: Record<string, any>
effects: Record<string, any>
borders: Record<string, any>
}
type Args = {
activeSafeList: boolean
data: Data
}
export function safelist({ activeSafeList = true, data }: Args): string[] {
if (activeSafeList) {
const colors = data.colors
? safelistElementColors(safelistColors(data.colors))
: []
const spacing = data.spacing ? safelistSpacing(data.spacing) : []
const effects = safelistEffects(data.effects)
const gaps = range(20).map((i) => `gap-${i}`)
const gridRows = range(14).map((i) => `grid-rows-${i}`)
const gridCols = range(14).map((i) => `grid-cols-${i}`)
const rowsStart = range(14).map((i) => `row-start-${i}`)
const colsStart = range(14).map((i) => `col-start-${i}`)
const rowsSpan = range(14).map((i) => `row-span-${i}`)
const colsSpan = range(14).map((i) => `col-span-${i}`)
const maxLines = range(10).map((i) => `max-lines-${i}`)
const borders = safelistBorders(data.borders.borderRadius, data.borders.borderWidth)
return [
'debug',
'debug-all',
...colors,
...spacing,
...gaps,
...gridRows,
...gridCols,
...rowsStart,
...colsStart,
...rowsSpan,
...colsSpan,
...effects,
...maxLines,
...borders,
...safelistTypography(),
...safelistIconSizes(),
...safelistIllustrationsSizes(),
]
}
return []
}
export function safelistColors({ colors, backgroundImage }: Data['colors']) {
const colorsNames: string[] = []
for (const category in colors) {
for (const color in colors[category]) {
const current = colors[category][color]
if (typeof current === 'string') {
colorsNames.push(`${category}-${color}`)
}
if (typeof current === 'object') {
for (const insideColor in colors[category][color]) {
colorsNames.push(`${category}-${color}-${insideColor}`)
}
}
}
}
for (const gradientName in backgroundImage) {
colorsNames.push(`${gradientName}`)
}
return colorsNames
}
export function safelistElementColors(colorsNames: string[]) {
const elements = [
'text',
'bg',
'outline',
'fill',
'stroke',
'border',
'shadow',
'text-decoration-color',
'text-stroke-color',
]
const elementColors: string[] = []
elements.forEach((element) => elementColors.push(`${element}-transparent`))
elements.forEach((element: string) => {
colorsNames.forEach((color: string) => {
elementColors.push(`${element}-${color}`)
})
})
return elementColors
}
export function safelistBorders(borderRadius: Data['spacing'], borderWidth: Data['spacing']): string[] {
const borderAxis = [
'border',
'border-a',
'border-x',
'border-y',
'border-l',
'border-r',
'border-t',
'border-b',
]
const borderWidthAxis = [
'rounded',
'rounded-x',
'rounded-y',
'rounded-l',
'rounded-r',
'rounded-t',
'rounded-b',
]
const elementsBorder: string[] = []
Object.keys(borderWidth).forEach((element: string) => {
borderAxis.forEach((axis) => {
elementsBorder.push(`${axis}-${element}`)
})
})
Object.keys(borderRadius).forEach((element: string) => {
borderWidthAxis.forEach((axis) => {
elementsBorder.push(`${axis}-${element}`)
})
})
return elementsBorder
}
export function safelistSpacing(spacing: Data['spacing']): string[] {
const spacingTokenNames = Object.keys(spacing)
const paddings = ['p', 'px', 'py', 'pl', 'pr', 'pt', 'pb']
const margins = ['m', 'mx', 'my', 'ml', 'mr', 'mt', 'mb']
const typos = [
'text',
'tracking',
'decoration',
'underline-offset',
'indent',
'text-stroke',
]
const svg = ['stroke']
const border = [
'border-a',
'border-x',
'border-y',
'border-l',
'border-r',
'border-t',
'border-b',
]
const staticTokens = ['w-full', 'h-full', 'w-fit-content']
const elements = [
...paddings,
...margins,
...typos,
...svg,
...border,
]
const elementSpacing: string[] = staticTokens
elements.forEach((element: string) => {
spacingTokenNames.forEach((space: string) => {
elementSpacing.push(`${element}-${space}`)
})
})
margins.forEach((margin) => elementSpacing.push(`${margin}-auto`))
paddings.forEach((padding) => elementSpacing.push(`${padding}-auto`))
return elementSpacing
}
export function range(size: number, startAt = 1) {
return Array.from(Array(size).keys()).map((i) => i + startAt)
}
export function safelistEffects(effects: Data['effects']) {
const opacitiesPrefix = ['text', 'bg', 'shadow']
const opacities = Object.keys(effects.opacity).flatMap((opacity) =>
opacitiesPrefix.map((prefix) => `${prefix}-${opacity}`),
)
const shadows = Object.keys(effects.boxShadow).flatMap(
(shadow) => `shadow-${shadow}`,
)
return [...opacities, ...shadows]
}
export function safelistIconSizes() {
return [
'icon-size-small',
'icon-size-medium',
'icon-size-large',
'icon-size-x-large',
'icon-size-giga',
]
}
export function safelistIllustrationsSizes() {
return [
'illustration-size-micro',
'illustration-size-xs',
'illustration-size-sm',
'illustration-size-medium',
'illustration-size-large',
'illustration-size-xl',
'illustration-size-2xl',
'illustration-size-mega',
'illustration-size-giga',
]
}
export function safelistTypography() {
return [
'fonts-display-large',
'fonts-display-medium',
'fonts-display-small',
'fonts-heading-h1',
'fonts-heading-h2',
'fonts-heading-h3',
'fonts-heading-h4',
'fonts-body-x-large-regular',
'fonts-body-x-large-bold',
'fonts-body-large-regular',
'fonts-body-large-bold',
'fonts-body-medium-regular',
'fonts-body-medium-bold',
'fonts-body-small-regular',
'fonts-body-small-bold',
'fonts-link-inline-large',
'fonts-link-inline-medium',
'fonts-link-inline-small',
'fonts-overline-small',
]
}