const _s0 = {
m: 'margin',
p: 'padding',
w: 'width',
h: 'height',
minw: 'min-width',
maxw: 'max-width',
minh: 'min-height',
maxh: 'max-height',
r: '-right',
l: '-left',
b: '-bottom',
t: '-top'
}
const sizeRules = [
[/^(w|h|minw|maxw|minh|maxh)(\d+)$/, ([, attr, num]) => ({ [`${_s0[attr]}`]: `${num}px` })],
[/^(w|h)p(\d+\.?\d*)$/, ([, attr, num]) => ({ [`${_s0[attr]}`]: `${num}%` })],
[/^([mp])([rlbt]?)(-?\d+)$/, ([, attr, pos, num]) => ({ [`${_s0[attr]}${pos ? _s0[pos] : ''}`]: `${num}px` })],
[/^([mp])([rlbt]?)-auto$/, ([, attr, pos]) => ({ [`${_s0[attr]}${pos ? _s0[pos] : ''}`]: 'auto' })],
[/^(left|top|right|bottom)(-?\d+)$/, ([, pos, num]) => ({ [`${pos}`]: `${num}px` })],
[/^(left|top|right|bottom)-(auto|unset)$/, ([, pos, val]) => ({ [`${pos}`]: val })]
]
const _s1 = {
none: 'none',
block: 'block',
inline: 'inline',
flex: 'flex',
grid: 'grid',
ib: 'inline-block',
if: 'inline-flex',
ig: 'inline-grid',
abs: 'absolute',
rel: 'relative',
fixed: 'fixed',
sticky: 'sticky',
static: 'static',
r: 'row',
c: 'column',
center: 'center',
start: 'flex-start',
end: 'flex-end',
around: 'space-around',
between: 'space-between',
evenly: 'space-evenly',
stretch: 'stretch'
}
const layoutRules = [
[/^d-(none|block|flex|inline|grid|ib|if|ig)$/, ([, pos]) => ({ display: `${_s1[pos]}` })],
[/^(rel|abs|fixed|sticky|static)$/, ([, pos]) => ({ position: `${_s1[pos]}` })],
['abs-0', { position: 'absolute', left: 0, right: 0, top: 0, bottom: 0 }],
['fixed-0', { position: 'fixed', left: 0, right: 0, top: 0, bottom: 0 }],
['border-box', { 'box-sizing': 'border-box' }],
['content-box', { 'box-sizing': 'content-box' }],
[/^f-([rc])$/, ([, dir]) => ({ display: 'flex', 'flex-direction': `${_s1[dir]}` })],
[/^f-pos-(start|center|end|around|between|evenly|stretch)$/, ([, dir]) => ({ 'justify-content': `${_s1[dir]}` })],
[/^f-box-(start|center|end|stretch)$/, ([, dir]) => ({ 'align-items': `${_s1[dir]}` })],
[/^f-(wrap|nowrap)$/, ([, dir]) => ({ 'flex-wrap': dir })],
[/^fi-(\d+)$/, ([, num]) => ({ flex: `${num}` })]
]
const _s2 = {
f: 'font-size',
lh: 'line-height',
bold: 'bolder',
thin: 'lighter',
normal: 'normal',
under: 'underline',
over: 'overline',
through: 'line-through',
del: 'line-through',
none: 'none'
}
const fontRules = [
[/^(f|lh)(\d+)$/, ([, attr, num]) => ({ [`${_s2[attr]}`]: `${num}px` })],
[/^fw-(bold|thin|normal)$/, ([, dir]) => ({ 'font-weight': `${_s2[dir]}` })],
[/^fw-(\d+)$/, ([, val]) => ({ 'font-weight': val })],
[/^(text|ta)-(right|left|center)$/, ([, abbr, dir]) => ({ 'text-align': dir })],
[
/^td-(under|over|through|del|none)(-solid|-double|-dotted|-dashed|-wavy)?$/,
([, dir, style = '']) => ({ 'text-decoration': `${_s2[dir]} ${style.slice(1)}` })
],
['ts-sm', { 'text-shadow': 'var(--text-shadow-sm)' }],
['ts-lg', { 'text-shadow': 'var(--text-shadow-lg)' }]
]
const _s3 = {
a: '',
r: '-right',
l: '-left',
b: '-bottom',
t: '-top',
ws: 'var(--border-width) var(--border-style) '
}
const borderRules = [
[/^b-([arlbt])$/, ([, pos]) => ({ [`border${_s3[pos]}`]: _s3.ws + 'var(--border-color)' })],
[/^b-([arlbt])-([\w|-]+)$/, ([, pos, color]) => ({ [`border${_s3[pos]}`]: _s3.ws + `var(--${color})` })],
[/^b-([arlbt])#(\w+)$/, ([, pos, color]) => ({ [`border${_s3[pos]}`]: _s3.ws + `#${color}` })],
[/^bs-(none|dotted|dashed|solid|double|groove|ridge|inset|outset)$/, ([, style]) => ({ 'border-style': style })],
[/^br-(\d+)$/, ([, val]) => ({ 'border-radius': `${val}px` })],
[/^nb-([arlbt])$/, ([, pos]) => ({ [`border${_s3[pos]}`]: 'none' })],
['br-sm', { 'border-radius': 'var(--box-radius-sm)' }],
['br-lg', { 'border-radius': 'var(--box-radius-lg)' }],
['br-circle', { 'border-radius': '50%' }],
['bs-sm', { 'box-shadow': 'var(--box-shadow-sm)' }],
['bs-lg', { 'box-shadow': 'var(--box-shadow-lg)' }]
]
const _s4 = {
def: 'default',
hand: 'pointer',
disable: 'not-allowed'
}
const clamp = (v, min, max) => Math.min(Math.max(v, min), max)
const utilRules = [
['ellipsis', { overflow: 'hidden', ' text-overflow': 'ellipsis', 'white-space': 'nowrap' }],
[
/^ellipsis(\d+)$/,
([, num]) => ({
display: '-webkit-box',
overflow: 'hidden',
'-webkit-line-clamp': num,
' -webkit-box-orient': 'vertical',
'overflow-wrap': 'anywhere'
})
],
[/^cur-(def|hand|disable)$/, ([, shape]) => ({ cursor: `${_s4[shape]}` })],
[/^of(\w?)-(auto|scroll|hidden|visible)$/, ([, axis, mode]) => ({ [`overflow${axis ? '-' + axis : ''}`]: mode })],
[/^img-(cover|contain|fill)$/, ([, mode]) => ({ 'object-fit': mode })],
[/^z(-?\d+)$/, ([, num]) => ({ 'z-index': num })],
['noselect', { 'user-select': 'none' }],
['allselect', { 'user-select': 'all' }],
['noevent', { 'pointer-events': 'none' }],
['hide', { visibility: 'hidden' }],
['show', { visibility: 'visible' }],
[/^op(\d+)$/, ([, val]) => ({ opacity: clamp(val / 100, 0, 1) })],
['op-hover', { opacity: 'var(--hover-op)' }],
['op-disabled', { opacity: 'var(--disabled-op)' }],
[/^break(word|all)$/, ([, type]) => ({ 'word-break': `break-${type}` })]
]
const _s5 = { c: 'color', bg: 'background-color' }
const colorRules = [
[
/^(c|bg)-rand(\d+)$/,
([, attr, seed]) => ({ [`${_s5[attr]}`]: `#${Math.floor(Math.random() * 255 * 255 * 255).toString(16)}` })
],
[/^(c|bg)-([\w|-]+)$/, ([, attr, color]) => ({ [`${_s5[attr]}`]: `var(--${color})` })],
[/^(c|bg)#(\w+)$/, ([, attr, color]) => ({ [`${_s5[attr]}`]: `#${color}` })]
]
export const rules: any[] = [...sizeRules, ...layoutRules, ...fontRules, ...borderRules, ...utilRules, ...colorRules]
export const shortcuts: any[] = [
[/^(m|p)x(-?\d+)$/, ([, t, c]) => `${t}l${c} ${t}r${c}`],
[/^(m|p)y(-?\d+)$/, ([, t, c]) => `${t}t${c} ${t}b${c}`],
[/^(m|p)x-auto$/, ([, t, c]) => `${t}l-auto ${t}r-auto`],
[/^(m|p)y-auto$/, ([, t, c]) => `${t}t-auto ${t}b-auto`],
[/^box(\d+)$/, ([, w]) => `w${w} h${w}`],
[/^link-(\w+)$/, ([, c]) => `c-${c} h:c-${c}less cur-hand `],
[/^link#(\w+)$/, ([, c]) => `c#${c} cur-hand `],
['f-center', 'd-flex f-pos-center f-box-center']
]
export const variants = [
(matcher) => {
if (!matcher.startsWith('!')) return matcher
return {
matcher: matcher.slice(1),
body: (body) => {
body.forEach((e) => e[1] && (e[1] += ' !important'))
return body
}
}
},
(matcher) => {
if (!matcher.startsWith('h:')) return matcher
return {
matcher: matcher.slice(2),
selector: (s) => `${s}:hover`,
body: (body) => {
body.push(['transition', 'all var(--trans-time)'])
return body
}
}
},
(matcher) => {
if (!matcher.startsWith('child:')) return matcher
return {
matcher: matcher.slice(6),
selector: (s) => `${s}>*`,
body: (s) => s
}
},
(matcher) => {
const matchResult = matcher.match(/^child<(\w+)>/)
if (!matchResult) return matcher
const [matchStr, selector] = matchResult
return {
matcher: matcher.slice(matchStr.length),
selector: (s) => `${s} ${selector}`,
body: (s) => s
}
}
]