hooo boy
This commit is contained in:
parent
4cf3e0e832
commit
3c3ad71296
|
|
@ -4,8 +4,8 @@ import { ExampleSection } from './ssr/helpers'
|
||||||
const TabSwitcher = define('TabSwitcher', {
|
const TabSwitcher = define('TabSwitcher', {
|
||||||
parts: {
|
parts: {
|
||||||
Input: {
|
Input: {
|
||||||
base: 'input',
|
base: 'input[type=radio]',
|
||||||
display: 'none', // Hide radio inputs
|
display: 'none',
|
||||||
},
|
},
|
||||||
TabBar: {
|
TabBar: {
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
|
|
@ -31,6 +31,13 @@ const TabSwitcher = define('TabSwitcher', {
|
||||||
':hover': {
|
':hover': {
|
||||||
color: '#111827',
|
color: '#111827',
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
selectors: {
|
||||||
|
'.TabSwitcher_Input:checked + &': {
|
||||||
|
color: '#3b82f6',
|
||||||
|
borderBottom: '2px solid #3b82f6'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Content: {
|
Content: {
|
||||||
|
|
@ -38,52 +45,39 @@ const TabSwitcher = define('TabSwitcher', {
|
||||||
padding: 20,
|
padding: 20,
|
||||||
background: '#f9fafb',
|
background: '#f9fafb',
|
||||||
borderRadius: 8,
|
borderRadius: 8,
|
||||||
|
|
||||||
|
selectors: {
|
||||||
|
'.TabSwitcher_Input:checked ~ &': {
|
||||||
|
display: 'block'
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
render({ props, parts: { Root, Input, TabBar, TabLabel, Content } }) {
|
render({ props, parts: { Root, Input, TabBar, TabLabel, Content } }) {
|
||||||
return (
|
return (
|
||||||
<Root>
|
<Root>
|
||||||
{/* Hidden radio inputs */}
|
<TabBar>
|
||||||
{props.tabs?.map((tab: any, index: number) => (
|
{props.tabs?.map((tab: any, index: number) => (
|
||||||
|
<>
|
||||||
<Input
|
<Input
|
||||||
key={`input-${tab.id}`}
|
key={`input-${tab.id}`}
|
||||||
type="radio"
|
id={`${props.name}-${tab.id}`}
|
||||||
id={`tab-${props.name}-${tab.id}`}
|
|
||||||
name={props.name || 'tabs'}
|
name={props.name || 'tabs'}
|
||||||
checked={index === 0}
|
checked={index === 0}
|
||||||
/>
|
/>
|
||||||
))}
|
<TabLabel key={`label-${tab.id}`} for={`${props.name}-${tab.id}`}>
|
||||||
|
|
||||||
{/* Tab labels */}
|
|
||||||
<TabBar>
|
|
||||||
{props.tabs?.map((tab: any) => (
|
|
||||||
<TabLabel key={`label-${tab.id}`} for={`tab-${props.name}-${tab.id}`}>
|
|
||||||
{tab.label}
|
{tab.label}
|
||||||
</TabLabel>
|
</TabLabel>
|
||||||
|
</>
|
||||||
))}
|
))}
|
||||||
</TabBar>
|
</TabBar>
|
||||||
|
|
||||||
{/* Tab content panels */}
|
|
||||||
{props.tabs?.map((tab: any) => (
|
{props.tabs?.map((tab: any) => (
|
||||||
<Content key={`content-${tab.id}`} class={`content-${props.name}-${tab.id}`}>
|
<Content key={`content-${tab.id}`}>
|
||||||
{tab.content}
|
{tab.content}
|
||||||
</Content>
|
</Content>
|
||||||
))}
|
))}
|
||||||
|
|
||||||
{/* CSS to show active tab and content */}
|
|
||||||
<style dangerouslySetInnerHTML={{
|
|
||||||
__html: props.tabs?.map((tab: any) => `
|
|
||||||
input#tab-${props.name}-${tab.id}:checked + .TabBar label[for="tab-${props.name}-${tab.id}"],
|
|
||||||
input#tab-${props.name}-${tab.id}:checked ~ .TabBar label[for="tab-${props.name}-${tab.id}"] {
|
|
||||||
color: #3b82f6 !important;
|
|
||||||
border-bottom: 2px solid #3b82f6 !important;
|
|
||||||
}
|
|
||||||
input#tab-${props.name}-${tab.id}:checked ~ .content-${props.name}-${tab.id} {
|
|
||||||
display: block !important;
|
|
||||||
}
|
|
||||||
`).join('\n')
|
|
||||||
}} />
|
|
||||||
</Root>
|
</Root>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -92,7 +86,7 @@ const TabSwitcher = define('TabSwitcher', {
|
||||||
const Pills = define('Pills', {
|
const Pills = define('Pills', {
|
||||||
parts: {
|
parts: {
|
||||||
Input: {
|
Input: {
|
||||||
base: 'input',
|
base: 'input[type=radio]',
|
||||||
display: 'none',
|
display: 'none',
|
||||||
},
|
},
|
||||||
PillBar: {
|
PillBar: {
|
||||||
|
|
@ -118,6 +112,16 @@ const Pills = define('Pills', {
|
||||||
background: '#e5e7eb',
|
background: '#e5e7eb',
|
||||||
color: '#111827',
|
color: '#111827',
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
selectors: {
|
||||||
|
'.Pills_Input:checked + &': {
|
||||||
|
background: '#3b82f6',
|
||||||
|
color: 'white'
|
||||||
|
},
|
||||||
|
'.Pills_Input:checked + &:hover': {
|
||||||
|
background: '#2563eb'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -125,33 +129,21 @@ const Pills = define('Pills', {
|
||||||
render({ props, parts: { Root, Input, PillBar, PillLabel } }) {
|
render({ props, parts: { Root, Input, PillBar, PillLabel } }) {
|
||||||
return (
|
return (
|
||||||
<Root>
|
<Root>
|
||||||
|
<PillBar>
|
||||||
{props.items?.map((item: any, index: number) => (
|
{props.items?.map((item: any, index: number) => (
|
||||||
|
<>
|
||||||
<Input
|
<Input
|
||||||
key={`input-${item.id}`}
|
key={`input-${item.id}`}
|
||||||
type="radio"
|
id={`${props.name}-${item.id}`}
|
||||||
id={`pill-${props.name}-${item.id}`}
|
|
||||||
name={props.name || 'pills'}
|
name={props.name || 'pills'}
|
||||||
checked={index === 0}
|
checked={index === 0}
|
||||||
/>
|
/>
|
||||||
))}
|
<PillLabel key={`label-${item.id}`} for={`${props.name}-${item.id}`}>
|
||||||
|
|
||||||
<PillBar>
|
|
||||||
{props.items?.map((item: any) => (
|
|
||||||
<PillLabel key={`label-${item.id}`} for={`pill-${props.name}-${item.id}`}>
|
|
||||||
{item.label}
|
{item.label}
|
||||||
</PillLabel>
|
</PillLabel>
|
||||||
|
</>
|
||||||
))}
|
))}
|
||||||
</PillBar>
|
</PillBar>
|
||||||
|
|
||||||
<style dangerouslySetInnerHTML={{
|
|
||||||
__html: props.items?.map((item: any) => `
|
|
||||||
input#pill-${props.name}-${item.id}:checked + .PillBar label[for="pill-${props.name}-${item.id}"],
|
|
||||||
input#pill-${props.name}-${item.id}:checked ~ .PillBar label[for="pill-${props.name}-${item.id}"] {
|
|
||||||
background: #3b82f6 !important;
|
|
||||||
color: white !important;
|
|
||||||
}
|
|
||||||
`).join('\n')
|
|
||||||
}} />
|
|
||||||
</Root>
|
</Root>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -160,7 +152,7 @@ const Pills = define('Pills', {
|
||||||
const VerticalNav = define('VerticalNav', {
|
const VerticalNav = define('VerticalNav', {
|
||||||
parts: {
|
parts: {
|
||||||
Input: {
|
Input: {
|
||||||
base: 'input',
|
base: 'input[type=radio]',
|
||||||
display: 'none',
|
display: 'none',
|
||||||
},
|
},
|
||||||
NavBar: {
|
NavBar: {
|
||||||
|
|
@ -190,6 +182,17 @@ const VerticalNav = define('VerticalNav', {
|
||||||
background: '#f3f4f6',
|
background: '#f3f4f6',
|
||||||
color: '#111827',
|
color: '#111827',
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
selectors: {
|
||||||
|
'.VerticalNav_Input:checked + &': {
|
||||||
|
background: '#eff6ff',
|
||||||
|
color: '#3b82f6',
|
||||||
|
},
|
||||||
|
'.VerticalNav_Input:checked + &:hover': {
|
||||||
|
background: '#dbeafe',
|
||||||
|
color: '#2563eb'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Icon: {
|
Icon: {
|
||||||
|
|
@ -205,34 +208,22 @@ const VerticalNav = define('VerticalNav', {
|
||||||
render({ props, parts: { Root, Input, NavBar, NavLabel, Icon } }) {
|
render({ props, parts: { Root, Input, NavBar, NavLabel, Icon } }) {
|
||||||
return (
|
return (
|
||||||
<Root>
|
<Root>
|
||||||
|
<NavBar>
|
||||||
{props.items?.map((item: any, index: number) => (
|
{props.items?.map((item: any, index: number) => (
|
||||||
|
<>
|
||||||
<Input
|
<Input
|
||||||
key={`input-${item.id}`}
|
key={`input-${item.id}`}
|
||||||
type="radio"
|
id={`${props.name}-${item.id}`}
|
||||||
id={`nav-${props.name}-${item.id}`}
|
|
||||||
name={props.name || 'nav'}
|
name={props.name || 'nav'}
|
||||||
checked={index === 0}
|
checked={index === 0}
|
||||||
/>
|
/>
|
||||||
))}
|
<NavLabel key={`label-${item.id}`} for={`${props.name}-${item.id}`}>
|
||||||
|
|
||||||
<NavBar>
|
|
||||||
{props.items?.map((item: any) => (
|
|
||||||
<NavLabel key={`label-${item.id}`} for={`nav-${props.name}-${item.id}`}>
|
|
||||||
{item.icon && <Icon>{item.icon}</Icon>}
|
{item.icon && <Icon>{item.icon}</Icon>}
|
||||||
{item.label}
|
{item.label}
|
||||||
</NavLabel>
|
</NavLabel>
|
||||||
|
</>
|
||||||
))}
|
))}
|
||||||
</NavBar>
|
</NavBar>
|
||||||
|
|
||||||
<style dangerouslySetInnerHTML={{
|
|
||||||
__html: props.items?.map((item: any) => `
|
|
||||||
input#nav-${props.name}-${item.id}:checked + .NavBar label[for="nav-${props.name}-${item.id}"],
|
|
||||||
input#nav-${props.name}-${item.id}:checked ~ .NavBar label[for="nav-${props.name}-${item.id}"] {
|
|
||||||
background: #eff6ff !important;
|
|
||||||
color: #3b82f6 !important;
|
|
||||||
}
|
|
||||||
`).join('\n')
|
|
||||||
}} />
|
|
||||||
</Root>
|
</Root>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -476,32 +467,41 @@ const SimpleVerticalNav = define('SimpleVerticalNav', {
|
||||||
export const NavigationExamplesContent = () => (
|
export const NavigationExamplesContent = () => (
|
||||||
<>
|
<>
|
||||||
<ExampleSection title="Tabs">
|
<ExampleSection title="Tabs">
|
||||||
<Tabs items={[
|
<TabSwitcher
|
||||||
{ id: 1, label: 'Overview', active: true },
|
name="demo-tabs"
|
||||||
{ id: 2, label: 'Analytics', active: false },
|
tabs={[
|
||||||
{ id: 3, label: 'Reports', active: false },
|
{ id: 'overview', label: 'Overview', content: <p>Overview content</p> },
|
||||||
{ id: 4, label: 'Settings', active: false },
|
{ id: 'analytics', label: 'Analytics', content: <p>Analytics content</p> },
|
||||||
]} />
|
{ id: 'reports', label: 'Reports', content: <p>Reports content</p> },
|
||||||
|
{ id: 'settings', label: 'Settings', content: <p>Settings content</p> },
|
||||||
|
]}
|
||||||
|
/>
|
||||||
</ExampleSection>
|
</ExampleSection>
|
||||||
|
|
||||||
<ExampleSection title="Pills">
|
<ExampleSection title="Pills">
|
||||||
<SimplePills items={[
|
<Pills
|
||||||
{ id: 1, label: 'All', active: true },
|
name="demo-pills"
|
||||||
{ id: 2, label: 'Active', active: false },
|
items={[
|
||||||
{ id: 3, label: 'Pending', active: false },
|
{ id: 'all', label: 'All' },
|
||||||
{ id: 4, label: 'Archived', active: false },
|
{ id: 'active', label: 'Active' },
|
||||||
]} />
|
{ id: 'pending', label: 'Pending' },
|
||||||
|
{ id: 'archived', label: 'Archived' },
|
||||||
|
]}
|
||||||
|
/>
|
||||||
</ExampleSection>
|
</ExampleSection>
|
||||||
|
|
||||||
<ExampleSection title="Vertical Navigation">
|
<ExampleSection title="Vertical Navigation">
|
||||||
<SimpleVerticalNav items={[
|
<VerticalNav
|
||||||
{ id: 1, label: 'Dashboard', icon: '📊', active: true },
|
name="demo-nav"
|
||||||
{ id: 2, label: 'Projects', icon: '📁', active: false },
|
items={[
|
||||||
{ id: 3, label: 'Team', icon: '👥', active: false },
|
{ id: 'dashboard', label: 'Dashboard', icon: '📊' },
|
||||||
{ id: 4, label: 'Calendar', icon: '📅', active: false },
|
{ id: 'projects', label: 'Projects', icon: '📁' },
|
||||||
{ id: 5, label: 'Documents', icon: '📄', active: false },
|
{ id: 'team', label: 'Team', icon: '👥' },
|
||||||
{ id: 6, label: 'Settings', icon: '⚙️', active: false },
|
{ id: 'calendar', label: 'Calendar', icon: '📅' },
|
||||||
]} />
|
{ id: 'documents', label: 'Documents', icon: '📄' },
|
||||||
|
{ id: 'settings', label: 'Settings', icon: '⚙️' },
|
||||||
|
]}
|
||||||
|
/>
|
||||||
</ExampleSection>
|
</ExampleSection>
|
||||||
|
|
||||||
<ExampleSection title="Breadcrumbs">
|
<ExampleSection title="Breadcrumbs">
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ export const Styles = () => <style dangerouslySetInnerHTML={{ __html: stylesToCS
|
||||||
const isBrowser = typeof document !== 'undefined'
|
const isBrowser = typeof document !== 'undefined'
|
||||||
let styleElement: HTMLStyleElement | null = null
|
let styleElement: HTMLStyleElement | null = null
|
||||||
|
|
||||||
// automatically inject <style> tag into browser for SPA
|
// automatically inject <style> tag into browser for SPA
|
||||||
function injectStylesInBrowser() {
|
function injectStylesInBrowser() {
|
||||||
if (!isBrowser) return
|
if (!isBrowser) return
|
||||||
|
|
||||||
|
|
@ -30,7 +30,7 @@ export function stylesToCSS(styles: Record<string, Record<string, string>>): str
|
||||||
for (const [selector, style] of Object.entries(styles)) {
|
for (const [selector, style] of Object.entries(styles)) {
|
||||||
if (Object.keys(style).length === 0) continue
|
if (Object.keys(style).length === 0) continue
|
||||||
|
|
||||||
out.push(`.${selector} {`)
|
out.push(`${expandSelector(selector)} { `)
|
||||||
for (const [name, value] of Object.entries(style).sort(([a], [b]) => a.localeCompare(b)))
|
for (const [name, value] of Object.entries(style).sort(([a], [b]) => a.localeCompare(b)))
|
||||||
out.push(` ${name}: ${value};`)
|
out.push(` ${name}: ${value};`)
|
||||||
out.push(`}\n`)
|
out.push(`}\n`)
|
||||||
|
|
@ -39,6 +39,10 @@ export function stylesToCSS(styles: Record<string, Record<string, string>>): str
|
||||||
return out.join('\n')
|
return out.join('\n')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function expandSelector(selector: string): string {
|
||||||
|
return selector.startsWith('.') ? selector : `.${selector}`
|
||||||
|
}
|
||||||
|
|
||||||
// creates a CSS class name
|
// creates a CSS class name
|
||||||
function makeClassName(baseName: string, partName?: string, variantName?: string, variantKey?: string): string {
|
function makeClassName(baseName: string, partName?: string, variantName?: string, variantKey?: string): string {
|
||||||
const cls = partName ? `${baseName}_${partName}` : baseName
|
const cls = partName ? `${baseName}_${partName}` : baseName
|
||||||
|
|
@ -76,7 +80,21 @@ function makeStyle(def: TagDef) {
|
||||||
function makeComponent(baseName: string, rootDef: TagDef, rootProps: Record<string, any>, partName?: string) {
|
function makeComponent(baseName: string, rootDef: TagDef, rootProps: Record<string, any>, partName?: string) {
|
||||||
const def = partName ? rootDef.parts?.[partName]! : rootDef
|
const def = partName ? rootDef.parts?.[partName]! : rootDef
|
||||||
const base = def.base ?? 'div'
|
const base = def.base ?? 'div'
|
||||||
const Tag = (base) as keyof JSX.IntrinsicElements
|
|
||||||
|
// Extract element name from base (e.g., 'input[type=radio]' -> 'input')
|
||||||
|
const tagName = base.split('[')[0]
|
||||||
|
const Tag = (tagName) as keyof JSX.IntrinsicElements
|
||||||
|
|
||||||
|
// Extract attributes from base (e.g., 'input[type=radio]' -> { type: 'radio' })
|
||||||
|
const baseAttrs: Record<string, string> = {}
|
||||||
|
const attrMatch = base.match(/\[([^\]]+)\]/)
|
||||||
|
if (attrMatch && attrMatch[1]) {
|
||||||
|
const attrStr = attrMatch[1]
|
||||||
|
const [attrName, attrValue] = attrStr.split('=')
|
||||||
|
if (attrName && attrValue) {
|
||||||
|
baseAttrs[attrName] = attrValue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return ({ children, ...props }: { children: any, [key: string]: any }) => {
|
return ({ children, ...props }: { children: any, [key: string]: any }) => {
|
||||||
const classNames = [makeClassName(baseName, partName)]
|
const classNames = [makeClassName(baseName, partName)]
|
||||||
|
|
@ -107,7 +125,7 @@ function makeComponent(baseName: string, rootDef: TagDef, rootProps: Record<stri
|
||||||
classNames.push(variantKey === true ? variantName : `${variantName}-${variantKey}`)
|
classNames.push(variantKey === true ? variantName : `${variantName}-${variantKey}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
return <Tag class={classNames.join(' ')} {...props}>{children}</Tag>
|
return <Tag class={classNames.join(' ')} {...baseAttrs} {...props}>{children}</Tag>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -121,15 +139,25 @@ function registerStyles(name: string, def: TagDef) {
|
||||||
const rootClassName = makeClassName(name)
|
const rootClassName = makeClassName(name)
|
||||||
styles[rootClassName] ??= makeStyle(def)
|
styles[rootClassName] ??= makeStyle(def)
|
||||||
|
|
||||||
|
for (let [selector, selectorDef] of Object.entries(def.selectors ?? {})) {
|
||||||
|
selector = selector.replace('&', `.${rootClassName}`)
|
||||||
|
if (styles[selector]) throw `${selector} already defined!`
|
||||||
|
styles[selector] = makeStyle(selectorDef)
|
||||||
|
}
|
||||||
|
|
||||||
for (const [state, style] of Object.entries(def.states ?? {}))
|
for (const [state, style] of Object.entries(def.states ?? {}))
|
||||||
styles[`${rootClassName}${stateName(state)}`] = makeStyle(style)
|
styles[`${rootClassName}${stateName(state)}`] = makeStyle(style)
|
||||||
|
|
||||||
for (const [partName, partDef] of Object.entries(def.parts ?? {})) {
|
for (const [partName, partDef] of Object.entries(def.parts ?? {})) {
|
||||||
const partClassName = makeClassName(name, partName)
|
const partClassName = makeClassName(name, partName)
|
||||||
styles[partClassName] ??= makeStyle(partDef)
|
styles[partClassName] ??= makeStyle(partDef)
|
||||||
|
for (let [selector, selectorDef] of Object.entries(partDef.selectors ?? {})) {
|
||||||
|
selector = selector.replace('&', `.${partClassName}`)
|
||||||
|
if (styles[selector]) throw `${selector} already defined!`
|
||||||
|
styles[selector] = makeStyle(selectorDef)
|
||||||
|
}
|
||||||
for (const [state, style] of Object.entries(partDef.states ?? {}))
|
for (const [state, style] of Object.entries(partDef.states ?? {}))
|
||||||
styles[`${partClassName}${stateName(state)}`] = makeStyle(style)
|
styles[`${partClassName}${stateName(state)}`] = makeStyle(style)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const [variantName, variantConfig] of Object.entries(def.variants ?? {})) {
|
for (const [variantName, variantConfig] of Object.entries(def.variants ?? {})) {
|
||||||
|
|
@ -144,6 +172,11 @@ function registerStyles(name: string, def: TagDef) {
|
||||||
const baseClassName = makeClassName(name)
|
const baseClassName = makeClassName(name)
|
||||||
const className = `${baseClassName}.${variantName}`
|
const className = `${baseClassName}.${variantName}`
|
||||||
styles[className] ??= makeStyle(variantDef)
|
styles[className] ??= makeStyle(variantDef)
|
||||||
|
for (let [selector, selectorDef] of Object.entries(variantDef.selectors ?? {})) {
|
||||||
|
selector = selector.replace('&', `.${className}`)
|
||||||
|
if (styles[selector]) throw `${selector} already defined!`
|
||||||
|
styles[selector] = makeStyle(selectorDef)
|
||||||
|
}
|
||||||
for (const [state, style] of Object.entries(variantDef.states ?? {}))
|
for (const [state, style] of Object.entries(variantDef.states ?? {}))
|
||||||
styles[`${className}${stateName(state)}`] = makeStyle(style)
|
styles[`${className}${stateName(state)}`] = makeStyle(style)
|
||||||
|
|
||||||
|
|
@ -151,6 +184,11 @@ function registerStyles(name: string, def: TagDef) {
|
||||||
const basePartClassName = makeClassName(name, partName)
|
const basePartClassName = makeClassName(name, partName)
|
||||||
const partClassName = `${basePartClassName}.${variantName}`
|
const partClassName = `${basePartClassName}.${variantName}`
|
||||||
styles[partClassName] ??= makeStyle(partDef)
|
styles[partClassName] ??= makeStyle(partDef)
|
||||||
|
for (let [selector, selectorDef] of Object.entries(partDef.selectors ?? {})) {
|
||||||
|
selector = selector.replace('&', `.${partClassName}`)
|
||||||
|
if (styles[selector]) throw `${selector} already defined!`
|
||||||
|
styles[selector] = makeStyle(selectorDef)
|
||||||
|
}
|
||||||
for (const [state, style] of Object.entries(partDef.states ?? {}))
|
for (const [state, style] of Object.entries(partDef.states ?? {}))
|
||||||
styles[`${partClassName}${stateName(state)}`] = makeStyle(style)
|
styles[`${partClassName}${stateName(state)}`] = makeStyle(style)
|
||||||
}
|
}
|
||||||
|
|
@ -159,12 +197,22 @@ function registerStyles(name: string, def: TagDef) {
|
||||||
for (const [variantKey, variantDef] of Object.entries(variantConfig as Record<string, TagDef>)) {
|
for (const [variantKey, variantDef] of Object.entries(variantConfig as Record<string, TagDef>)) {
|
||||||
const className = makeClassName(name, undefined, variantName, variantKey)
|
const className = makeClassName(name, undefined, variantName, variantKey)
|
||||||
styles[className] ??= makeStyle(variantDef)
|
styles[className] ??= makeStyle(variantDef)
|
||||||
|
for (let [selector, selectorDef] of Object.entries(variantDef.selectors ?? {})) {
|
||||||
|
selector = selector.replace('&', `.${className}`)
|
||||||
|
if (styles[selector]) throw `${selector} already defined!`
|
||||||
|
styles[selector] = makeStyle(selectorDef)
|
||||||
|
}
|
||||||
for (const [state, style] of Object.entries(variantDef.states ?? {}))
|
for (const [state, style] of Object.entries(variantDef.states ?? {}))
|
||||||
styles[`${className}${stateName(state)}`] = makeStyle(style)
|
styles[`${className}${stateName(state)}`] = makeStyle(style)
|
||||||
|
|
||||||
for (const [partName, partDef] of Object.entries(variantDef.parts ?? {})) {
|
for (const [partName, partDef] of Object.entries(variantDef.parts ?? {})) {
|
||||||
const partClassName = makeClassName(name, partName, variantName, variantKey)
|
const partClassName = makeClassName(name, partName, variantName, variantKey)
|
||||||
styles[partClassName] ??= makeStyle(partDef)
|
styles[partClassName] ??= makeStyle(partDef)
|
||||||
|
for (let [selector, selectorDef] of Object.entries(partDef.selectors ?? {})) {
|
||||||
|
selector = selector.replace('&', `.${partClassName}`)
|
||||||
|
if (styles[selector]) throw `${selector} already defined!`
|
||||||
|
styles[selector] = makeStyle(selectorDef)
|
||||||
|
}
|
||||||
for (const [state, style] of Object.entries(partDef.states ?? {}))
|
for (const [state, style] of Object.entries(partDef.states ?? {}))
|
||||||
styles[`${partClassName}${stateName(state)}`] = makeStyle(style)
|
styles[`${partClassName}${stateName(state)}`] = makeStyle(style)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ export type TagDef = {
|
||||||
className?: string
|
className?: string
|
||||||
base?: string
|
base?: string
|
||||||
states?: Record<string, TagDef>,
|
states?: Record<string, TagDef>,
|
||||||
|
selectors?: Record<string, TagDef>,
|
||||||
parts?: Record<string, TagDef>
|
parts?: Record<string, TagDef>
|
||||||
variants?: Record<string, TagDef | Record<string, TagDef>>
|
variants?: Record<string, TagDef | Record<string, TagDef>>
|
||||||
render?: (obj: any) => any
|
render?: (obj: any) => any
|
||||||
|
|
@ -155,10 +156,12 @@ export const NonStyleKeys = new Set([
|
||||||
'className',
|
'className',
|
||||||
'base',
|
'base',
|
||||||
'states',
|
'states',
|
||||||
|
'css',
|
||||||
'parts',
|
'parts',
|
||||||
'variants',
|
'variants',
|
||||||
'render',
|
'render',
|
||||||
'styles',
|
'styles',
|
||||||
|
'selectors',
|
||||||
])
|
])
|
||||||
|
|
||||||
export const UnitlessProps = new Set([
|
export const UnitlessProps = new Set([
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user