diff --git a/system/core/scripts/generateComponents.ts b/system/core/scripts/generateComponents.ts index ae4587a2..0c35e758 100644 --- a/system/core/scripts/generateComponents.ts +++ b/system/core/scripts/generateComponents.ts @@ -259,7 +259,6 @@ class CssComponentBuilder extends ComponentBuilder { } hasValidSelectors() { - if (this.pascalImportKey === 'Spinner') return true; if (this.className) return true; if (!this.element) return false; return !!this.defaultProps.find(([key]) => key === 'type'); @@ -293,9 +292,10 @@ class CssComponentBuilder extends ComponentBuilder { '${this.element}' >({ variants: ${JSON.stringify(this.getVariants())}, - className: '${this.className}', - element: '${this.element}', - displayName: '${this.pascalImportKey}' + ${this.buildWithComponentProps({ + elementName: this.element, + displayName: this.pascalImportKey + })}, });` ); } @@ -306,17 +306,37 @@ class CssComponentBuilder extends ComponentBuilder { writeForwardRefComponent({ varName, elementName, - omitVariants = false, displayName = '', + omitVariants = false, fixedProps: fixedPropsArg = this.fixedProps || [], shouldExport = false }) { - const propsType = omitVariants ? 'Omit' : 'Props'; + const propsType = `${ + omitVariants ? 'Omit' : 'Props' + } & ${this.reactHtmlAttributesType}`; + return `${ + shouldExport ? 'export ' : '' + }const ${varName} = buildWithComponent<${ + this.elementType + }, ${propsType}>({ ${this.buildWithComponentProps({ + elementName, + displayName: displayName || varName, + fixedProps: fixedPropsArg + })}});`; + } + + // eslint-disable-next-line @typescript-eslint/naming-convention + private buildWithComponentProps({ + elementName, + displayName = '', + fixedProps: fixedPropsArg = this.fixedProps || [] + }) { const props = this.buildProps(fixedPropsArg); const classNameProp = props.find(({ key }) => key === 'className'); - const append: string[] = [ - `className: ${classNameProp ? `'${classNameProp.value}'` : 'undefined'}` - ]; + if (!classNameProp) { + throw new Error(`Missing className prop for ${displayName}`); + } + const append: string[] = [`className: '${classNameProp.value}'`]; const additionalProps = props.filter(({ key }) => key !== 'className'); if (additionalProps.length) { append.push( @@ -328,15 +348,9 @@ class CssComponentBuilder extends ComponentBuilder { .join(', ')} }` ); } - return `${ - shouldExport ? 'export ' : '' - }const ${varName} = buildWithComponent<${ - this.elementType - }, ${propsType} & ${ - this.reactHtmlAttributesType - }>({ tag: '${elementName}', displayName: '${ - displayName || varName - }', ${append.join(', ')}});`; + return `tag: '${elementName}', displayName: '${displayName}', ${append.join( + ', ' + )}`; } protected formatDefaultProp(key: string) { diff --git a/system/core/src/components/Checkbox.ts b/system/core/src/components/Checkbox.ts index c8ef1f6f..a7ef5856 100644 --- a/system/core/src/components/Checkbox.ts +++ b/system/core/src/components/Checkbox.ts @@ -2,6 +2,7 @@ import { OptionalKeys, css } from '../utils'; export const element = 'input'; export const selectors = ['input[type="checkbox"]:not(.toggle)']; +export const className = 'checkbox'; export interface Props { type: 'checkbox'; diff --git a/system/core/src/components/InputWithIcons.ts b/system/core/src/components/InputWithIcons.ts index 4a200166..cc00536f 100644 --- a/system/core/src/components/InputWithIcons.ts +++ b/system/core/src/components/InputWithIcons.ts @@ -78,7 +78,7 @@ export const fullStyles = css` & > [data-mode='input-append'] { height: calc(var(--tk-input-height) - var(--tk-input-border-width) * 2); width: calc( - var(--tk-input-icon-size)+ var(--tk-input-icon-gap)+ + var(--tk-input-icon-size) + var(--tk-input-icon-gap) + var(--tk-input-icon-end-padding) ); --tk-icon-button-padding: 8px !important; diff --git a/system/core/src/components/InputWithPrefix.ts b/system/core/src/components/InputWithPrefix.ts index 96230f56..e3ffb985 100644 --- a/system/core/src/components/InputWithPrefix.ts +++ b/system/core/src/components/InputWithPrefix.ts @@ -86,7 +86,7 @@ export const fullStyles = css` grid-area: 1/4/1/5; height: calc(var(--tk-input-height) - var(--tk-input-border-width) * 2); width: calc( - var(--tk-input-icon-size)+ var(--tk-input-icon-gap)+ + var(--tk-input-icon-size) + var(--tk-input-icon-gap) + var(--tk-input-icon-end-padding) ); --tk-icon-button-padding: 8px !important; diff --git a/system/core/src/components/Radio.ts b/system/core/src/components/Radio.ts index 9e2ef7d7..d5b989b9 100644 --- a/system/core/src/components/Radio.ts +++ b/system/core/src/components/Radio.ts @@ -2,6 +2,7 @@ import { OptionalKeys, css } from '../utils'; export const element = 'input'; export const selectors = ['input[type="radio"]:not(.toggle)']; +export const className = 'radio'; export interface Props { type: 'radio'; diff --git a/system/core/src/components/TextAreaWithIcons.ts b/system/core/src/components/TextAreaWithIcons.ts index 0a0515db..1a8b83ae 100644 --- a/system/core/src/components/TextAreaWithIcons.ts +++ b/system/core/src/components/TextAreaWithIcons.ts @@ -97,7 +97,7 @@ export const fullStyles = css` & > [data-mode='input-append'] { height: calc(var(--tk-input-height) - var(--tk-input-border-width) * 2); width: calc( - var(--tk-input-icon-size)+ var(--tk-input-icon-gap)+ + var(--tk-input-icon-size) + var(--tk-input-icon-gap) + var(--tk-input-icon-end-padding) ); --tk-icon-button-padding: 8px !important; diff --git a/system/core/src/components/TextAreaWithPrefix.ts b/system/core/src/components/TextAreaWithPrefix.ts index b6723976..6eec7d35 100644 --- a/system/core/src/components/TextAreaWithPrefix.ts +++ b/system/core/src/components/TextAreaWithPrefix.ts @@ -102,7 +102,7 @@ export const fullStyles = css` grid-area: 1/4/1/5; height: calc(var(--tk-input-height) - var(--tk-input-border-width) * 2); width: calc( - var(--tk-input-icon-size)+ var(--tk-input-icon-gap)+ + var(--tk-input-icon-size) + var(--tk-input-icon-gap) + var(--tk-input-icon-end-padding) ); --tk-icon-button-padding: 8px !important; diff --git a/system/css/src/buildFile.ts b/system/css/src/buildFile.ts index b07776dc..4204be90 100644 --- a/system/css/src/buildFile.ts +++ b/system/css/src/buildFile.ts @@ -140,7 +140,12 @@ export class ComponentBuilder extends CssFileBuilder { getClassySelectors() { const { element, className, selectors = [] } = this.fileContent; - if (!className) return selectors; + if (!className) { + console.warn( + `className is missing in ${this.folderName}/${this.fileName}` + ); + return selectors; + } if (element === 'input') return [`input.${className}`]; return [`.${className}`]; } diff --git a/system/react-css/src/components/Badge.tsx b/system/react-css/src/components/Badge.tsx index ced8ca86..43596350 100644 --- a/system/react-css/src/components/Badge.tsx +++ b/system/react-css/src/components/Badge.tsx @@ -40,7 +40,7 @@ export const VariantBadge = buildVariantComponents< 'orange', 'disabled' ], - className: 'badge', - element: 'span', - displayName: 'Badge' + tag: 'span', + displayName: 'Badge', + className: 'badge' }); diff --git a/system/react-css/src/components/Banner.tsx b/system/react-css/src/components/Banner.tsx index 4ede4f6f..a7e77f01 100644 --- a/system/react-css/src/components/Banner.tsx +++ b/system/react-css/src/components/Banner.tsx @@ -20,7 +20,7 @@ export const VariantBanner = buildVariantComponents< 'div' >({ variants: ['tertiary', 'ghost', 'success', 'warning', 'info', 'neutral'], - className: 'banner', - element: 'div', - displayName: 'Banner' + tag: 'div', + displayName: 'Banner', + className: 'banner' }); diff --git a/system/react-css/src/components/Button.tsx b/system/react-css/src/components/Button.tsx index a917d01f..6d88899a 100644 --- a/system/react-css/src/components/Button.tsx +++ b/system/react-css/src/components/Button.tsx @@ -44,7 +44,11 @@ export const VariantButton = buildVariantComponents< 'bare', 'danger' ], + tag: 'button', + displayName: 'Button', className: 'btn', - element: 'button', - displayName: 'Button' + additionalProps: { + type: button.defaultProps.type as never, + 'data-size': { toString: () => getConfigDefault('controlSize') } + } }); diff --git a/system/react-css/src/components/Checkbox.tsx b/system/react-css/src/components/Checkbox.tsx index 8b58ad39..c89bd502 100644 --- a/system/react-css/src/components/Checkbox.tsx +++ b/system/react-css/src/components/Checkbox.tsx @@ -16,6 +16,6 @@ export const Checkbox = buildWithComponent< >({ tag: 'input', displayName: 'Checkbox', - className: undefined, + className: 'checkbox', additionalProps: { type: checkbox.defaultProps.type as never } }); diff --git a/system/react-css/src/components/IconButton.tsx b/system/react-css/src/components/IconButton.tsx index e031bd0a..34009c9b 100644 --- a/system/react-css/src/components/IconButton.tsx +++ b/system/react-css/src/components/IconButton.tsx @@ -46,7 +46,11 @@ export const VariantIconButton = buildVariantComponents< 'danger', 'danger-bare' ], + tag: 'button', + displayName: 'IconButton', className: 'icon-button', - element: 'button', - displayName: 'IconButton' + additionalProps: { + type: 'button', + 'data-size': { toString: () => getConfigDefault('controlSize') } + } }); diff --git a/system/react-css/src/components/Radio.tsx b/system/react-css/src/components/Radio.tsx index 1daab105..9c2dfd4d 100644 --- a/system/react-css/src/components/Radio.tsx +++ b/system/react-css/src/components/Radio.tsx @@ -16,6 +16,6 @@ export const Radio = buildWithComponent< >({ tag: 'input', displayName: 'Radio', - className: undefined, + className: 'radio', additionalProps: { type: radio.defaultProps.type as never } }); diff --git a/system/react-css/src/utils.tsx b/system/react-css/src/utils.tsx index 29e89f93..d6b6a2ad 100644 --- a/system/react-css/src/utils.tsx +++ b/system/react-css/src/utils.tsx @@ -140,14 +140,13 @@ export function buildVariantComponents< >({ variants, className, - element, - displayName + tag, + displayName, + additionalProps, + style }: { variants: TVariant[]; - className: string; - displayName: string; - element: TElement; -}): Record< +} & DecorateOptions): Record< Capitalize, React.ForwardRefExoticComponent & WithComponentType > { @@ -161,10 +160,13 @@ export function buildVariantComponents< HTMLElementTagNameMap[TElement], Omit >({ - tag: element, + tag, className, + style, displayName: `${displayName}_${variantKey}`, - additionalProps: { 'data-variant': key } + additionalProps: additionalProps + ? { ...additionalProps, 'data-variant': key } + : { 'data-variant': key } }) }; }, {} as Record, React.ForwardRefExoticComponent & WithComponentType>);