Skip to content

Yamada UIのfactoryをみていく

factory.ts

ネイティブのHTML要素やその集合体をYamada UIのコンポーネントとして昇格させるための処理がfactory.tsに書かれている。

packages/core/src/factory.ts
import type {
UIFactory,
DOMElements,
StyledOptions,
HTMLUIComponents,
UIComponent
} from './components'
import { styled } from './styled'
const factory = () => {
const cache = new Map<DOMElements, UIComponent<DOMElements>>()
return new Proxy(styled, {
apply: (_target, _thisArg, [el, options]: [DOMElements, StyledOptions]) => {
return styled(el, options)
},
get: (_target, el: DOMElements) => {
if (!cache.has(el)) cache.set(el, styled(el))
return cache.get(el)
}
}) as UIFactory & HTMLUIComponents
}
/**
* `ui` is an object of JSX elements enabled with Yamada UI's style system,
* and can also be used as a function for custom components to receive Yamada UI's style system.
*
* @see Docs https://yamada-ui.com/styled-system/ui
*/
export const ui = factory()

このソースコードがあるとこう言うことができる。

packages/components/badge/src/badge.tsx
import type { HTMLUIProps, ThemeProps, CSSUIObject } from "@yamada-ui/core"
import {
ui,
forwardRef,
useComponentStyle,
omitThemeProps,
} from "@yamada-ui/core"
import { cx } from "@yamada-ui/utils"
export type BadgeProps = HTMLUIProps<"span"> & ThemeProps<"Badge">
/**
* `Badge` is a component that emphasizes the status of an item to make it immediately recognizable.
*
* @see Docs https://yamada-ui.com/components/data-display/badge
*/
export const Badge = forwardRef<BadgeProps, "span">((props, ref) => {
const [styles, mergedProps] = useComponentStyle("Badge", props)
const { className, ...rest } = omitThemeProps(mergedProps)
const css: CSSUIObject = {
display: "inline-block",
whiteSpace: "nowrap",
verticalAlign: "middle",
...styles,
}
return (
<ui.span
ref={ref}
className={cx("ui-badge", className)}
__css={css}
{...rest}
/>
)
})

このソースのここの部分。

packages/components/badge/src/badge.tsx
<ui.span
ref={ref}
className={cx("ui-badge", className)}
__css={css}
{...rest}
/>

これを実行すると、factory.tsのここの部分が実行される。

packages/core/src/factory.ts
get: (_target, el: DOMElements) => {
if (!cache.has(el)) cache.set(el, styled(el))
return cache.get(el)
},

その結果、ただの<span>要素が、Yamada UIの機能(Styleとか)を追加した<span>要素・改になる。

参考

Proxyの基本的な使い方を復習すべき