UNPKG

@hanamura/rcgen

Version:

Generate optimized React container components from configuration

214 lines (192 loc) 5.63 kB
"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 */ [key: string]: 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> ) } `; }