parts can have a custom render()
This commit is contained in:
parent
e772e0e711
commit
9b6e1e91ec
|
|
@ -196,7 +196,11 @@ 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(' ')} {...baseAttrs} {...props}>{children}</Tag>
|
const finalProps = { class: classNames.join(' '), ...baseAttrs, ...props, children }
|
||||||
|
|
||||||
|
const content = (partName && def.render) ? def.render(finalProps) : children
|
||||||
|
|
||||||
|
return <Tag {...finalProps}>{content}</Tag>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -315,4 +319,4 @@ function tagName(base: string): string {
|
||||||
}
|
}
|
||||||
|
|
||||||
// shortcut so you only have to import one thing, if you want
|
// shortcut so you only have to import one thing, if you want
|
||||||
define.Styles = Styles
|
define.Styles = Styles
|
||||||
|
|
|
||||||
|
|
@ -558,6 +558,82 @@ describe('custom render function', () => {
|
||||||
expect(html).toContain('<footer')
|
expect(html).toContain('<footer')
|
||||||
expect(html).toContain('Main Content')
|
expect(html).toContain('Main Content')
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test('part can have its own render function', () => {
|
||||||
|
const Component = define('PartRender', {
|
||||||
|
parts: {
|
||||||
|
Icon: {
|
||||||
|
base: 'span',
|
||||||
|
color: 'blue',
|
||||||
|
render: (props) => <>★ {props.children}</>
|
||||||
|
}
|
||||||
|
},
|
||||||
|
render: ({ props, parts }) => (
|
||||||
|
<parts.Root>
|
||||||
|
<parts.Icon>star</parts.Icon>
|
||||||
|
</parts.Root>
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
const html = renderToString(Component({}))
|
||||||
|
expect(html).toContain('★ star')
|
||||||
|
expect(html).toContain('class="PartRender_Icon"')
|
||||||
|
expect(html).toContain('<span') // base tag is preserved
|
||||||
|
})
|
||||||
|
|
||||||
|
test('part render receives props including children', () => {
|
||||||
|
let receivedProps: any
|
||||||
|
|
||||||
|
const Component = define('PartRenderProps', {
|
||||||
|
parts: {
|
||||||
|
Item: {
|
||||||
|
base: 'li',
|
||||||
|
render: (props) => {
|
||||||
|
receivedProps = props
|
||||||
|
return <>item: {props.children}</>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
render: ({ props, parts }) => (
|
||||||
|
<parts.Root>
|
||||||
|
<parts.Item data-test="value">content</parts.Item>
|
||||||
|
</parts.Root>
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
const html = renderToString(Component({}))
|
||||||
|
expect(receivedProps.class).toBe('PartRenderProps_Item')
|
||||||
|
expect(receivedProps['data-test']).toBe('value')
|
||||||
|
expect(receivedProps.children).toBe('content')
|
||||||
|
expect(html).toContain('<li') // base tag preserved
|
||||||
|
expect(html).toContain('item: content')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('part render works with variants', () => {
|
||||||
|
const Component = define('PartRenderVariant', {
|
||||||
|
variants: {
|
||||||
|
size: {
|
||||||
|
small: { fontSize: 12 },
|
||||||
|
large: { fontSize: 24 }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
parts: {
|
||||||
|
Label: {
|
||||||
|
fontWeight: 'bold',
|
||||||
|
render: (props) => <>Label: {props.children}</>
|
||||||
|
}
|
||||||
|
},
|
||||||
|
render: ({ props, parts }) => (
|
||||||
|
<parts.Root>
|
||||||
|
<parts.Label>text</parts.Label>
|
||||||
|
</parts.Root>
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
const html = renderToString(Component({ size: 'large' }))
|
||||||
|
expect(html).toContain('Label: text')
|
||||||
|
expect(html).toContain('PartRenderVariant_Label')
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('Styles component', () => {
|
describe('Styles component', () => {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user