@nnao45/figma-use 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json ADDED
@@ -0,0 +1,87 @@
1
+ {
2
+ "name": "@nnao45/figma-use",
3
+ "version": "0.1.0",
4
+ "description": "Control Figma from the command line. Full read/write access for AI agents.",
5
+ "keywords": [
6
+ "ai",
7
+ "ai-agents",
8
+ "automation",
9
+ "cli",
10
+ "design",
11
+ "figma",
12
+ "plugin"
13
+ ],
14
+ "homepage": "https://github.com/nnao45/figma-use#readme",
15
+ "bugs": {
16
+ "url": "https://github.com/nnao45/figma-use/issues"
17
+ },
18
+ "license": "MIT",
19
+ "author": "nnao45",
20
+ "repository": {
21
+ "type": "git",
22
+ "url": "git+https://github.com/nnao45/figma-use.git"
23
+ },
24
+ "publishConfig": {
25
+ "access": "public"
26
+ },
27
+ "bin": {
28
+ "figma-fast": "bin/figma-fast.js",
29
+ "figma-use": "bin/figma-use.js"
30
+ },
31
+ "files": [
32
+ "bin",
33
+ "CHANGELOG.md",
34
+ "README.md",
35
+ "SKILL.md",
36
+ "dist/cli",
37
+ "packages/plugin/src",
38
+ "packages/cli/src/color.ts",
39
+ "packages/cli/src/render"
40
+ ],
41
+ "type": "module",
42
+ "sideEffects": false,
43
+ "exports": {
44
+ ".": "./dist/cli/index.js",
45
+ "./render": "./packages/cli/src/render/index.ts",
46
+ "./components": "./packages/cli/src/render/components.tsx"
47
+ },
48
+ "scripts": {
49
+ "build": "bun run build:cli",
50
+ "build:cli": "bun build packages/cli/src/index.ts --outdir dist/cli --target node --minify --external esbuild --external typescript --external @modelcontextprotocol/sdk --external oxfmt --external whaticon --external pngjs --external pixelmatch",
51
+ "test": "cd packages/cli && bun test",
52
+ "lint": "oxlint packages/",
53
+ "format": "oxfmt --write packages/",
54
+ "prepublishOnly": "bun run build",
55
+ "build:fast": "bun build packages/cli/src/fast.ts --outfile dist/fast.mjs --target node --minify"
56
+ },
57
+ "dependencies": {
58
+ "agentfmt": "^0.1.3",
59
+ "citty": "^0.1.6",
60
+ "consola": "^3.4.2",
61
+ "diff": "^8.0.3",
62
+ "esbuild": "^0.25.4",
63
+ "fontoxpath": "^3.34.0",
64
+ "postcss": "^8.5.6",
65
+ "svgpath": "^2.6.0",
66
+ "typescript": "^5.8.3",
67
+ "whaticon": "0.1.2",
68
+ "zod": "^4.3.6"
69
+ },
70
+ "devDependencies": {
71
+ "@figma/plugin-typings": "^1.122.0",
72
+ "@iconify/core": "^4.1.0",
73
+ "@iconify/types": "^2.0.0",
74
+ "@iconify/utils": "^3.1.0",
75
+ "@types/bun": "^1.3.6",
76
+ "@types/pngjs": "^6.0.5",
77
+ "@types/react": "^19.2.9",
78
+ "@types/ws": "^8.18.1",
79
+ "ajv": "^8.17.1",
80
+ "ajv-formats": "^3.0.1",
81
+ "oxfmt": "^0.26.0",
82
+ "oxlint": "^1.39.0",
83
+ "pixelmatch": "^7.1.0",
84
+ "pngjs": "^7.0.0",
85
+ "react": "19"
86
+ }
87
+ }
@@ -0,0 +1,157 @@
1
+ /**
2
+ * ComponentSet (variants) support
3
+ *
4
+ * ## How ComponentSet works in Figma's multiplayer protocol
5
+ *
6
+ * ComponentSet is NOT a separate node type - it's a FRAME with special fields:
7
+ * - type = FRAME (4)
8
+ * - isStateGroup = true (field 225)
9
+ * - stateGroupPropertyValueOrders (field 238) = [{property: "variant", values: ["A", "B"]}]
10
+ *
11
+ * Children are SYMBOL (Component) nodes with names like "variant=Primary, size=Large".
12
+ * Figma auto-generates componentPropertyDefinitions from these names.
13
+ *
14
+ * ## Why Instances are created via Plugin API
15
+ *
16
+ * IMPORTANT: Instance nodes with symbolData.symbolID CANNOT be created via multiplayer
17
+ * when linking to components in the same batch. Figma reassigns GUIDs on receive,
18
+ * breaking the symbolID references.
19
+ *
20
+ * Example: We send SYMBOL with localID=100, Instance with symbolData.symbolID=100.
21
+ * Figma receives and assigns new IDs: SYMBOL becomes 200, but Instance still
22
+ * references 100 → broken link.
23
+ *
24
+ * This works for defineComponent() because Component and first Instance are adjacent
25
+ * in the node tree, but fails for ComponentSet where variant components are created
26
+ * first, then instances are created as siblings of the ComponentSet.
27
+ *
28
+ * Solution: Create the ComponentSet and variant Components via multiplayer (fast),
29
+ * then create Instances via Plugin API in trigger-layout (correct linking).
30
+ * The pendingComponentSetInstances array passes instance specs to the plugin.
31
+ *
32
+ * Discovered through protocol sniffing - see scripts/sniff-ws.ts
33
+ */
34
+
35
+ import * as React from './mini-react.ts'
36
+
37
+ import type { FC, ReactElement } from './mini-react.ts'
38
+
39
+ type VariantDef = Record<string, readonly string[]>
40
+ type VariantProps<V extends VariantDef> = { [K in keyof V]: V[K][number] }
41
+
42
+ interface ComponentSetDef<V extends VariantDef> {
43
+ name: string
44
+ variants: V
45
+ render: (props: VariantProps<V>) => ReactElement
46
+ symbol: symbol
47
+ }
48
+
49
+ // Use global registry to avoid module duplication issues between bundled CLI and source imports
50
+ const REGISTRY_KEY = '__figma_use_component_set_registry__'
51
+ const componentSetRegistry: Map<symbol, ComponentSetDef<VariantDef>> = ((
52
+ globalThis as Record<string, unknown>
53
+ )[REGISTRY_KEY] as Map<symbol, ComponentSetDef<VariantDef>>) ||
54
+ ((globalThis as Record<string, unknown>)[REGISTRY_KEY] = new Map<
55
+ symbol,
56
+ ComponentSetDef<VariantDef>
57
+ >())
58
+
59
+ export function resetComponentSetRegistry() {
60
+ componentSetRegistry.clear()
61
+ }
62
+
63
+ export function getComponentSetRegistry() {
64
+ return componentSetRegistry
65
+ }
66
+
67
+ /**
68
+ * Define a component with variants (ComponentSet)
69
+ *
70
+ * @example
71
+ * const Button = defineComponentSet('Button', {
72
+ * variant: ['Primary', 'Secondary'] as const,
73
+ * size: ['Small', 'Large'] as const,
74
+ * }, ({ variant, size }) => (
75
+ * <Frame style={{ padding: size === 'Large' ? 16 : 8 }}>
76
+ * <Text>{variant}</Text>
77
+ * </Frame>
78
+ * ))
79
+ *
80
+ * <Button variant="Primary" size="Large" />
81
+ */
82
+ export function defineComponentSet<V extends VariantDef>(
83
+ name: string,
84
+ variants: V,
85
+ render: (props: VariantProps<V>) => ReactElement
86
+ ): FC<Partial<VariantProps<V>> & { style?: Record<string, unknown> }> {
87
+ const sym = Symbol(name)
88
+ componentSetRegistry.set(sym, {
89
+ name,
90
+ variants,
91
+ render,
92
+ symbol: sym
93
+ } as ComponentSetDef<VariantDef>)
94
+
95
+ const VariantInstance: FC<Partial<VariantProps<V>> & { style?: Record<string, unknown> }> = (
96
+ props
97
+ ) => {
98
+ const { style, ...variantProps } = props
99
+ return React.createElement('__component_set_instance__', {
100
+ __componentSetSymbol: sym,
101
+ __componentSetName: name,
102
+ __variantProps: variantProps,
103
+ style
104
+ })
105
+ }
106
+ ;(VariantInstance as unknown as { displayName: string }).displayName = name
107
+
108
+ return VariantInstance
109
+ }
110
+
111
+ /**
112
+ * Generate all variant combinations
113
+ */
114
+ export function generateVariantCombinations<V extends VariantDef>(
115
+ variants: V
116
+ ): Array<VariantProps<V>> {
117
+ const keys = Object.keys(variants) as (keyof V)[]
118
+ if (keys.length === 0) return [{}] as Array<VariantProps<V>>
119
+
120
+ const result: Array<VariantProps<V>> = []
121
+
122
+ function combine(index: number, current: Partial<VariantProps<V>>) {
123
+ if (index === keys.length) {
124
+ result.push(current as VariantProps<V>)
125
+ return
126
+ }
127
+
128
+ const key = keys[index]!
129
+ for (const value of variants[key]!) {
130
+ combine(index + 1, { ...current, [key]: value })
131
+ }
132
+ }
133
+
134
+ combine(0, {})
135
+ return result
136
+ }
137
+
138
+ /**
139
+ * Build variant name string for Figma component (e.g., "variant=Primary, size=Large")
140
+ */
141
+ export function buildVariantName(props: Record<string, string>): string {
142
+ return Object.entries(props)
143
+ .map(([k, v]) => `${k}=${v}`)
144
+ .join(', ')
145
+ }
146
+
147
+ /**
148
+ * Build stateGroupPropertyValueOrders for ComponentSet
149
+ */
150
+ export function buildStateGroupPropertyValueOrders(
151
+ variants: VariantDef
152
+ ): Array<{ property: string; values: string[] }> {
153
+ return Object.entries(variants).map(([property, values]) => ({
154
+ property,
155
+ values: [...values]
156
+ }))
157
+ }
@@ -0,0 +1,115 @@
1
+ /**
2
+ * Figma JSX Components
3
+ *
4
+ * Returns TreeNode objects for Figma Widget API rendering.
5
+ * Use @ts-expect-error in .figma.tsx files if TypeScript complains about JSX types.
6
+ */
7
+
8
+ import { node, type BaseProps, type TextProps, type TreeNode } from './tree.ts'
9
+
10
+ // Core components
11
+ export function Frame(props: BaseProps): TreeNode {
12
+ return node('frame', props)
13
+ }
14
+
15
+ export function Text(props: TextProps): TreeNode {
16
+ return node('text', props)
17
+ }
18
+
19
+ export function Rectangle(props: BaseProps): TreeNode {
20
+ return node('rectangle', props)
21
+ }
22
+
23
+ export function Ellipse(props: BaseProps): TreeNode {
24
+ return node('ellipse', props)
25
+ }
26
+
27
+ export function Line(props: BaseProps): TreeNode {
28
+ return node('line', props)
29
+ }
30
+
31
+ export function Image(props: BaseProps & { src: string }): TreeNode {
32
+ return node('image', props)
33
+ }
34
+
35
+ export function SVG(props: BaseProps & { src: string }): TreeNode {
36
+ return node('svg', props)
37
+ }
38
+
39
+ export function Star(props: BaseProps & { points?: number; innerRadius?: number }): TreeNode {
40
+ return node('star', props)
41
+ }
42
+
43
+ export function Polygon(props: BaseProps & { pointCount?: number }): TreeNode {
44
+ return node('polygon', props)
45
+ }
46
+
47
+ export function Vector(props: BaseProps): TreeNode {
48
+ return node('vector', props)
49
+ }
50
+
51
+ export function Group(props: BaseProps): TreeNode {
52
+ return node('group', props)
53
+ }
54
+
55
+ export function Section(props: BaseProps): TreeNode {
56
+ return node('section', props)
57
+ }
58
+
59
+ // Aliases
60
+ export const View = Frame
61
+ export const Rect = Rectangle
62
+ export const Component = Frame
63
+ export const Instance = Frame
64
+ export const Page = Frame
65
+
66
+ // Intrinsic elements
67
+ export const INTRINSIC_ELEMENTS = [
68
+ 'frame',
69
+ 'text',
70
+ 'rectangle',
71
+ 'ellipse',
72
+ 'line',
73
+ 'image',
74
+ 'svg',
75
+ 'star',
76
+ 'polygon',
77
+ 'vector',
78
+ 'group',
79
+ 'section'
80
+ ]
81
+
82
+ // Variables
83
+ export {
84
+ defineVars,
85
+ figmaVar,
86
+ isVariable,
87
+ loadVariablesIntoRegistry,
88
+ isRegistryLoaded,
89
+ type FigmaVariable
90
+ } from './vars.ts'
91
+
92
+ // Legacy component registry
93
+ const componentRegistry = new Map<symbol, { name: string; element: unknown }>()
94
+ export const resetComponentRegistry = () => componentRegistry.clear()
95
+ export const getComponentRegistry = () => componentRegistry
96
+
97
+ export function defineComponent(name: string, element: unknown) {
98
+ const sym = Symbol(name)
99
+ componentRegistry.set(sym, { name, element })
100
+ return () => element
101
+ }
102
+
103
+ // Icon
104
+ export interface IconProps {
105
+ icon: string
106
+ size?: number
107
+ color?: string
108
+ }
109
+
110
+ export function Icon(props: IconProps) {
111
+ return { __icon: true, ...props }
112
+ }
113
+
114
+ // Re-export types
115
+ export type { BaseProps, TextProps, StyleProps, TreeNode } from './tree.ts'
@@ -0,0 +1,166 @@
1
+ import { loadIcon } from '@iconify/core/lib/api/icons'
2
+ import { setAPIModule } from '@iconify/core/lib/api/modules'
3
+ import { fetchAPIModule } from '@iconify/core/lib/api/modules/fetch'
4
+ import { iconToSVG } from '@iconify/utils'
5
+
6
+ import type { ReactNode } from './mini-react.ts'
7
+ import type { Props, ReactElement } from './tree.ts'
8
+ import type { IconifyIcon } from '@iconify/types'
9
+
10
+ // Initialize API module
11
+ setAPIModule('', fetchAPIModule)
12
+
13
+ export interface IconData {
14
+ svg: string
15
+ width: number
16
+ height: number
17
+ body: string
18
+ viewBox: { left: number; top: number; width: number; height: number }
19
+ }
20
+
21
+ const iconCache = new Map<string, IconData>()
22
+
23
+ // Raw icon data cache (before size transformation)
24
+ const rawIconCache = new Map<string, IconifyIcon>()
25
+
26
+ /**
27
+ * Load raw icon data (without size transformation)
28
+ */
29
+ async function loadRawIcon(name: string): Promise<IconifyIcon | null> {
30
+ if (rawIconCache.has(name)) {
31
+ return rawIconCache.get(name)!
32
+ }
33
+
34
+ const icon = await loadIcon(name)
35
+ if (!icon) {
36
+ return null
37
+ }
38
+
39
+ rawIconCache.set(name, icon)
40
+ return icon
41
+ }
42
+
43
+ /**
44
+ * Load icon from Iconify and return SVG string
45
+ * @param name Icon name in format "prefix:name" (e.g., "mdi:home", "lucide:star")
46
+ * @param size Optional size (default: 24)
47
+ */
48
+ export async function loadIconSvg(name: string, size: number = 24): Promise<IconData | null> {
49
+ const cacheKey = `${name}@${size}`
50
+
51
+ if (iconCache.has(cacheKey)) {
52
+ return iconCache.get(cacheKey)!
53
+ }
54
+
55
+ const icon = await loadRawIcon(name)
56
+ if (!icon) {
57
+ return null
58
+ }
59
+
60
+ const result = iconToSVG(icon, { height: size, width: size })
61
+ const svg = `<svg xmlns="http://www.w3.org/2000/svg" ${Object.entries(result.attributes)
62
+ .map(([k, v]) => `${k}="${v}"`)
63
+ .join(' ')}>${result.body}</svg>`
64
+
65
+ const data: IconData = {
66
+ svg,
67
+ width: size,
68
+ height: size,
69
+ body: result.body,
70
+ viewBox: {
71
+ left: result.viewBox[0],
72
+ top: result.viewBox[1],
73
+ width: result.viewBox[2],
74
+ height: result.viewBox[3]
75
+ }
76
+ }
77
+
78
+ iconCache.set(cacheKey, data)
79
+ return data
80
+ }
81
+
82
+ /**
83
+ * Get cached icon data (synchronous, for use in React components)
84
+ * Returns null if icon not preloaded
85
+ */
86
+ export function getIconData(name: string, size: number = 24): IconData | null {
87
+ return iconCache.get(`${name}@${size}`) || null
88
+ }
89
+
90
+ /**
91
+ * Preload icons for use in JSX render
92
+ * Call before rendering to ensure icons are available synchronously
93
+ */
94
+ export async function preloadIcons(icons: Array<{ name: string; size?: number }>): Promise<void> {
95
+ await Promise.all(icons.map(({ name, size }) => loadIconSvg(name, size || 24)))
96
+ }
97
+
98
+ /**
99
+ * Get list of popular icon sets
100
+ */
101
+ export const iconSets = {
102
+ mdi: 'Material Design Icons',
103
+ lucide: 'Lucide',
104
+ heroicons: 'Heroicons',
105
+ 'heroicons-outline': 'Heroicons Outline',
106
+ 'heroicons-solid': 'Heroicons Solid',
107
+ tabler: 'Tabler Icons',
108
+ 'fa-solid': 'Font Awesome Solid',
109
+ 'fa-regular': 'Font Awesome Regular',
110
+ 'fa-brands': 'Font Awesome Brands',
111
+ ri: 'Remix Icon',
112
+ ph: 'Phosphor',
113
+ 'ph-bold': 'Phosphor Bold',
114
+ 'ph-fill': 'Phosphor Fill',
115
+ carbon: 'Carbon',
116
+ fluent: 'Fluent UI',
117
+ ion: 'Ionicons',
118
+ bi: 'Bootstrap Icons'
119
+ }
120
+
121
+ /**
122
+ * Recursively collect Icon primitives from React element tree
123
+ */
124
+ export function collectIcons(element: ReactNode): Array<{ name: string; size?: number }> {
125
+ const icons: Array<{ name: string; size?: number }> = []
126
+
127
+ function traverse(node: ReactNode): void {
128
+ if (!node || typeof node !== 'object') return
129
+
130
+ if (Array.isArray(node)) {
131
+ node.forEach(traverse)
132
+ return
133
+ }
134
+
135
+ const el = node as ReactElement
136
+ if (!el.type) return
137
+
138
+ if (el.type === 'icon') {
139
+ const props = el.props as { icon?: string; size?: number }
140
+ if (props.icon) {
141
+ icons.push({ name: props.icon, size: props.size })
142
+ }
143
+ }
144
+
145
+ if (typeof el.type === 'function') {
146
+ try {
147
+ const rendered = (el.type as (p: Props) => ReactNode)(el.props as Props)
148
+ if (rendered) traverse(rendered)
149
+ } catch {
150
+ // Ignore render errors during collection
151
+ }
152
+ }
153
+
154
+ const props = el.props as { children?: ReactNode }
155
+ if (props.children) {
156
+ if (Array.isArray(props.children)) {
157
+ props.children.forEach(traverse)
158
+ } else {
159
+ traverse(props.children)
160
+ }
161
+ }
162
+ }
163
+
164
+ traverse(element)
165
+ return icons
166
+ }
@@ -0,0 +1,47 @@
1
+ /**
2
+ * React → Figma Renderer
3
+ */
4
+
5
+ export { renderWithWidgetApi } from './widget-renderer.ts'
6
+
7
+ export {
8
+ Frame,
9
+ Text,
10
+ Rectangle,
11
+ Ellipse,
12
+ Line,
13
+ Image,
14
+ SVG,
15
+ View,
16
+ Rect,
17
+ Star,
18
+ Polygon,
19
+ Vector,
20
+ Component,
21
+ Instance,
22
+ Group,
23
+ Page,
24
+ Icon,
25
+ INTRINSIC_ELEMENTS,
26
+ defineVars,
27
+ figmaVar,
28
+ isVariable,
29
+ loadVariablesIntoRegistry,
30
+ isRegistryLoaded,
31
+ type FigmaVariable,
32
+ defineComponent,
33
+ resetComponentRegistry,
34
+ getComponentRegistry
35
+ } from './components.tsx'
36
+
37
+ export { preloadIcons, loadIconSvg, getIconData, collectIcons } from './icon.ts'
38
+
39
+ export { renderJsx } from './render-jsx.ts'
40
+
41
+ export {
42
+ defineComponentSet,
43
+ resetComponentSetRegistry,
44
+ getComponentSetRegistry
45
+ } from './component-set.tsx'
46
+
47
+ export { buildComponent, readStdin, renderFromString } from './render-from-string.ts'
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Development JSX Runtime - re-exports production runtime
3
+ */
4
+
5
+ export { jsx, jsxs, jsxDEV, Fragment } from './jsx-runtime.ts'
6
+ export type { JSX } from './jsx-runtime.ts'
@@ -0,0 +1,90 @@
1
+ /**
2
+ * Custom JSX Runtime for Figma components
3
+ *
4
+ * This module provides jsx/jsxs functions that produce TreeNode objects
5
+ * instead of React elements.
6
+ */
7
+
8
+ import { node, type BaseProps, type TreeNode, type TextProps } from './tree.ts'
9
+
10
+ export function jsx(type: string | ((props: BaseProps) => TreeNode), props: BaseProps): TreeNode {
11
+ if (typeof type === 'function') {
12
+ return type(props)
13
+ }
14
+ return node(type, props)
15
+ }
16
+
17
+ export const jsxs = jsx
18
+ export const jsxDEV = jsx
19
+
20
+ // Fragment just returns children
21
+ export function Fragment({ children }: { children?: unknown }): TreeNode {
22
+ return node('fragment', { children } as BaseProps)
23
+ }
24
+
25
+ // SVG element props
26
+ interface SvgProps {
27
+ width?: string | number
28
+ height?: string | number
29
+ viewBox?: string
30
+ fill?: string
31
+ children?: unknown
32
+ }
33
+
34
+ interface PathProps {
35
+ d: string
36
+ fill?: string
37
+ stroke?: string
38
+ strokeWidth?: string | number
39
+ fillRule?: string
40
+ clipRule?: string
41
+ }
42
+
43
+ interface RectProps {
44
+ x?: string | number
45
+ y?: string | number
46
+ width?: string | number
47
+ height?: string | number
48
+ rx?: string | number
49
+ ry?: string | number
50
+ fill?: string
51
+ stroke?: string
52
+ }
53
+
54
+ interface CircleProps {
55
+ cx?: string | number
56
+ cy?: string | number
57
+ r?: string | number
58
+ fill?: string
59
+ stroke?: string
60
+ }
61
+
62
+ // JSX namespace for TypeScript
63
+ export namespace JSX {
64
+ export type Element = TreeNode
65
+
66
+ export interface IntrinsicElements {
67
+ frame: BaseProps
68
+ text: TextProps
69
+ rectangle: BaseProps
70
+ ellipse: BaseProps
71
+ line: BaseProps
72
+ star: BaseProps & { points?: number; innerRadius?: number }
73
+ polygon: BaseProps & { pointCount?: number }
74
+ vector: BaseProps
75
+ group: BaseProps
76
+ image: BaseProps & { src: string }
77
+ // Figma SVG component with src string
78
+ SVG: BaseProps & { src: string }
79
+ // Native SVG elements (inline)
80
+ svg: SvgProps
81
+ path: PathProps
82
+ rect: RectProps
83
+ circle: CircleProps
84
+ g: { children?: unknown; fill?: string; stroke?: string }
85
+ }
86
+
87
+ export interface ElementChildrenAttribute {
88
+ children: {}
89
+ }
90
+ }
@@ -0,0 +1,33 @@
1
+ // Minimal React-compatible createElement for JSX rendering
2
+ // Replaces 86KB react package with ~200 bytes
3
+
4
+ export type ReactElement = {
5
+ type: string | Function
6
+ props: Record<string, unknown> & { children?: ReactNode[] }
7
+ }
8
+
9
+ export type ReactNode = ReactElement | string | number | null | undefined | ReactNode[]
10
+
11
+ export type FC<P = Record<string, unknown>> = (props: P) => ReactElement
12
+
13
+ export function createElement(
14
+ type: string | Function,
15
+ props: Record<string, unknown> | null,
16
+ ...children: ReactNode[]
17
+ ): ReactElement {
18
+ const flatChildren = children.flat()
19
+ return {
20
+ type,
21
+ props: {
22
+ ...props,
23
+ children:
24
+ flatChildren.length === 1
25
+ ? (flatChildren as ReactNode[])
26
+ : flatChildren.length > 0
27
+ ? flatChildren
28
+ : undefined
29
+ }
30
+ }
31
+ }
32
+
33
+ export default { createElement }