@hanamura/rcgen
Version:
Generate optimized React container components from configuration
214 lines (192 loc) • 5.63 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.default = render;
const utils_1 = require("../../src/utils");
/**
* Render the Stack component
*/
function render(config) {
// If a variable prefix is provided, use it
const prefix = config.variablePrefix ? `${config.variablePrefix}-` : '';
return `// generated by static-generator
import React, { Children, cloneElement, Fragment, isValidElement } from 'react'
import { QueryName, Spacing } from '../types'
import { getSpacingValue } from '../utils'
import styles from './Stack.module.css'
/**
* Options for the Stack component
*/
export type StackOptions = {
/**
* Gap between items
*/
gap?: Spacing | undefined
/**
* Divider position
*/
dividerPosition?: { start?: boolean, between?: boolean, end?: boolean } | undefined
/**
* Padding block
*/
paddingBlock?: Spacing | [padding: Spacing] | [start: Spacing, end: Spacing] | undefined
/**
* Padding inline
*/
paddingInline?: Spacing | [padding: Spacing] | [start: Spacing, end: Spacing] | undefined
}
/**
* Props for the Stack component
*/
export type StackProps = {
/**
* Options for the Stack component
*/
options?: StackOptions | undefined
/**
* Adaptive options for the Stack component
*/
adaptiveOptions?: Record<QueryName, StackOptions> | undefined
/**
* Divider
*/
divider?: React.ReactNode | ((props: { index: number, position: 'start' | 'between' | 'end' }) => React.ReactNode) | undefined
/**
* HTML element for the Stack component
*/
as?: React.ElementType | undefined
/**
* Class name for the Stack component
*/
className?: string | undefined
/**
* Style for the Stack component
*/
style?: React.CSSProperties | undefined
/**
* Children for the Stack component
*/
children?: React.ReactNode | undefined
/**
* Any other props
*/
[]: any
}
/**
* Stack component
*/
export function Stack({
options,
adaptiveOptions,
divider,
as: Component = 'div',
className,
style,
children,
...rest
}: StackProps) {
const renderDivider = (
index: number,
position: 'start' | 'between' | 'end',
) => {
if (!divider) return null
if (typeof divider === 'function') {
return divider({ index, position })
} else if (isValidElement(divider)) {
return cloneElement(divider, { key: \`divider-\${position}-\${index}\` })
} else {
return divider
}
}
const childrenArray = Children.toArray(children)
const childCount = childrenArray.length
return (
<Component
className={\`\${styles['stack']} \${className ?? ''}\`}
style={
{
${config.queries
.map(({ name }) => {
const n = (0, utils_1.normalizeName)(name);
return [
// gap
[
`'--${prefix}stack-${n}-gap':`,
`getSpacingValue(adaptiveOptions?.['${n}']?.gap ?? options?.gap) ?? 0`,
].join(' '),
// padding block
[
`'--${prefix}stack-${n}-padding-block':`,
`getSpacingValue(adaptiveOptions?.['${n}']?.paddingBlock ?? options?.paddingBlock) ?? 0`,
].join(' '),
// padding inline
[
`'--${prefix}stack-${n}-padding-inline':`,
`getSpacingValue(adaptiveOptions?.['${n}']?.paddingInline ?? options?.paddingInline) ?? 0`,
].join(' '),
// divider start
[
`'--${prefix}stack-${n}-divider-start-display':`,
`(adaptiveOptions?.['${n}']?.dividerPosition?.start ?? options?.dividerPosition?.start) ? 'contents' : 'none'`,
].join(' '),
// divider between
[
`'--${prefix}stack-${n}-divider-between-display':`,
`(adaptiveOptions?.['${n}']?.dividerPosition?.between ?? options?.dividerPosition?.between ?? true) ? 'contents' : 'none'`,
].join(' '),
// divider end
[
`'--${prefix}stack-${n}-divider-end-display':`,
`(adaptiveOptions?.['${n}']?.dividerPosition?.end ?? options?.dividerPosition?.end) ? 'contents' : 'none'`,
].join(' '),
].join(',\n');
})
.join(',\n') || '...({})' // If no styles are provided, return an empty object
},
...style,
} as React.CSSProperties
}
{...rest}
>
{(() => {
if (childCount === 0) return null
const divider = renderDivider(0, 'start')
return (
divider && (
<div className={\`\${styles['divider']} \${styles['isStart']}\`}>
{divider}
</div>
)
)
})()}
{childrenArray.map((child, index) => (
<Fragment key={index}>
{child}
{(() => {
if (index === childCount - 1) return null
const divider = renderDivider(index + 1, 'between')
return (
divider && (
<div className={\`\${styles['divider']} \${styles['isBetween']}\`}>
{divider}
</div>
)
)
})()}
</Fragment>
))}
{(() => {
if (childCount === 0) return null
const divider = renderDivider(childCount, 'end')
return (
divider && (
<div className={\`\${styles['divider']} \${styles['isEnd']}\`}>
{divider}
</div>
)
)
})()}
</Component>
)
}
`;
}