diff --git a/semcore/checkbox/package.json b/semcore/checkbox/package.json index 2ee10dc954..eb8fccc410 100644 --- a/semcore/checkbox/package.json +++ b/semcore/checkbox/package.json @@ -9,7 +9,7 @@ "author": "UI-kit team ", "license": "MIT", "scripts": { - "build": "pnpm semcore-builder --source=js && pnpm vite build" + "build": "pnpm semcore-builder && pnpm vite build" }, "exports": { "require": "./lib/cjs/index.js", diff --git a/semcore/checkbox/src/Checkbox.jsx b/semcore/checkbox/src/Checkbox.tsx similarity index 74% rename from semcore/checkbox/src/Checkbox.jsx rename to semcore/checkbox/src/Checkbox.tsx index f8a8cc07f4..ff9cb80197 100644 --- a/semcore/checkbox/src/Checkbox.jsx +++ b/semcore/checkbox/src/Checkbox.tsx @@ -1,4 +1,5 @@ import { Box, Flex, InvalidStateBox } from '@semcore/base-components'; +import type { IRootComponentProps } from '@semcore/core'; import { createComponent, Component, sstyled, Root } from '@semcore/core'; import { callAllEventHandlers } from '@semcore/core/lib/utils/assignProps'; import resolveColorEnhance from '@semcore/core/lib/utils/enhances/resolveColorEnhance'; @@ -8,9 +9,14 @@ import { useColorResolver } from '@semcore/core/lib/utils/use/useColorResolver'; import { Text as TypographyText } from '@semcore/typography'; import React from 'react'; +import type { CheckboxComponent, CheckboxProps, CheckboxTextProps, CheckboxValueCheckMarkProps, CheckboxValueComponent, CheckboxValueControlProps, CheckboxValueProps } from './Checkbox.type'; import style from './style/checkbox.shadow.css'; -class CheckboxRoot extends Component { +type State = { + hoistedDisabled?: boolean; +}; + +class CheckboxRoot extends Component { static displayName = 'Checkbox'; static style = style; @@ -24,7 +30,7 @@ class CheckboxRoot extends Component { hoistedDisabled: undefined, }; - hoistDisabled = (disabled) => { + hoistDisabled = (disabled: CheckboxProps['disabled']) => { logger.warn( true, `Don't set disabled on Checkbox.Value or Checkbox.Text, set it on Checkbox instead. Otherwise it will produce wrong SSR output.`, @@ -100,31 +106,30 @@ class CheckboxRoot extends Component { } } -class ValueRoot extends Component { - static defaultProps = (props) => { +type ValuePropsFromRoot = ReturnType['getValueProps']>; +class ValueRoot extends Component< + ValuePropsFromRoot & CheckboxValueProps, + typeof ValueRoot.enhance, + { checked: (e: React.ChangeEvent) => boolean } +> { + static defaultProps = () => { return { - includeInputProps: [ - ...inputProps, - ...(props.includeInputProps ?? []), - 'aria-label', - 'aria-labelledby', - 'aria-describedby', - ], + includeInputProps: [...inputProps, 'aria-label', 'aria-labelledby', 'aria-describedby'], }; }; - static enhance = [resolveColorEnhance()]; + static enhance = [resolveColorEnhance()] as const; static displayName = 'Value'; static style = style; - handleClick(e) { + handleClick(e: React.MouseEvent) { // idk for what it exists, leaving just in case it saves us from some bugs e.stopPropagation(); } uncontrolledProps() { return { - checked: (e) => e.target.checked, + checked: (e: React.ChangeEvent) => e.target.checked, }; } @@ -151,19 +156,21 @@ class ValueRoot extends Component { indeterminate, includeInputProps, resolveColor, + children, + Children, ...other } = this.asProps; const [, checkMarkProps] = getInputProps(other, includeInputProps); - const { children: _children, Children: _Children, ...propsWithoutChildren } = checkMarkProps; + return { - theme, + theme: resolveColor(theme), size, state, // keyboardFocused, checked, indeterminate, resolveColor, - ...propsWithoutChildren, + ...checkMarkProps, }; } @@ -195,13 +202,16 @@ class ValueRoot extends Component { } } -function Control(props) { +type ControlPropsFromRoot = ReturnType['getControlProps']>; +function Control(props: IRootComponentProps & ControlPropsFromRoot & CheckboxValueControlProps) { const SControl = Root; const { indeterminate, styles, state } = props; - const checkboxRef = React.useRef(null); + const checkboxRef = React.useRef(null); React.useEffect(() => { if (checkboxRef.current) { + if (indeterminate === undefined) return; + checkboxRef.current.indeterminate = indeterminate; } }, [indeterminate, checkboxRef]); @@ -218,24 +228,28 @@ function Control(props) { } Control.displayName = 'Control'; -function CheckMark(props) { +type CheckMarkPropsFromRoot = ReturnType['getCheckMarkProps']>; +function CheckMark(props: IRootComponentProps & CheckMarkPropsFromRoot & CheckboxValueCheckMarkProps) { const SCheckbox = Root; const SInvalidPattern = InvalidStateBox; - const { theme, styles, resolveColor, state, checked, indeterminate } = props; + const { styles, state, checked, indeterminate } = props; return sstyled(styles)( - + {state === 'invalid' && !checked && !indeterminate && } , ); } CheckMark.displayName = 'CheckMark'; -function Text(props) { +type TextPropsFromRoot = ReturnType['getTextProps']>; +function Text(props: IRootComponentProps & TextPropsFromRoot & CheckboxTextProps) { const SText = Root; const { styles, color } = props; React.useEffect(() => { if (props.rootDisabled !== props.disabled) { + if (props.disabled === undefined) return; + props.hoistDisabled(props.disabled); } }, [props.rootDisabled, props.disabled, props.hoistDisabled]); @@ -251,11 +265,11 @@ Text.displayName = 'Text'; const Value = createComponent(ValueRoot, { Control, CheckMark, -}); +}) as CheckboxValueComponent; const Checkbox = createComponent(CheckboxRoot, { Text, Value, -}); -export { inputProps }; +}) as CheckboxComponent; + export default Checkbox; diff --git a/semcore/checkbox/src/index.d.ts b/semcore/checkbox/src/Checkbox.type.ts similarity index 78% rename from semcore/checkbox/src/index.d.ts rename to semcore/checkbox/src/Checkbox.type.ts index 647e0dab04..771f555267 100644 --- a/semcore/checkbox/src/index.d.ts +++ b/semcore/checkbox/src/Checkbox.type.ts @@ -46,12 +46,12 @@ export type CheckboxContext = { export type CheckboxTextProps = TextProps; -declare const Checkbox: Intergalactic.Component<'label', CheckboxProps, CheckboxContext> & { - Text: Intergalactic.Component<'span', CheckboxTextProps>; - Value: Intergalactic.Component<'input', CheckboxValueProps> & { - Control: Intergalactic.Component<'input', CheckboxValueControlProps>; - CheckMark: Intergalactic.Component; - }; +export type CheckboxValueComponent = Intergalactic.Component<'input', CheckboxValueProps> & { + Control: Intergalactic.Component<'input', CheckboxValueControlProps>; + CheckMark: Intergalactic.Component; }; -export default Checkbox; +export type CheckboxComponent = Intergalactic.Component<'label', CheckboxProps, CheckboxContext> & { + Text: Intergalactic.Component<'span', CheckboxTextProps>; + Value: CheckboxValueComponent; +}; diff --git a/semcore/checkbox/src/index.js b/semcore/checkbox/src/index.ts similarity index 53% rename from semcore/checkbox/src/index.js rename to semcore/checkbox/src/index.ts index b077973e26..7322e1e29c 100644 --- a/semcore/checkbox/src/index.js +++ b/semcore/checkbox/src/index.ts @@ -1,2 +1,2 @@ export { default } from './Checkbox'; -export * from './Checkbox'; +export * from './Checkbox.type'; diff --git a/semcore/checkbox/vite.config.ts b/semcore/checkbox/vite.config.ts index 0991a16528..90f46b4cb2 100644 --- a/semcore/checkbox/vite.config.ts +++ b/semcore/checkbox/vite.config.ts @@ -7,7 +7,7 @@ export default mergeConfig( defineConfig({ build: { lib: { - entry: './src/index.js', + entry: './src/index.ts', }, rollupOptions: { external: ['react', 'react-dom', 'react/jsx-runtime', /@babel\/runtime\/*/, /@semcore\/*/], diff --git a/semcore/core/src/core-types/Component.ts b/semcore/core/src/core-types/Component.ts index b625ae1a7f..e8410ea6a5 100644 --- a/semcore/core/src/core-types/Component.ts +++ b/semcore/core/src/core-types/Component.ts @@ -45,10 +45,17 @@ type BaseAsProps any)[ InnerProps >; +type UncontrolledPropValue = + | V + | null + | ((value: V, e?: any) => void | boolean | V) + | ((value: V, e?: any) => void | boolean | V)[] + | ((e?: any) => void | boolean | V); + export abstract class Component< Props = {}, Enhance extends readonly ((...args: any[]) => any)[] = [], - Uncontrolled extends Readonly<{ [key in keyof Props]?: Props[key] | null | ((value: Props[key], e?: any) => void | boolean | Props[key]) | ((value: Props[key], e?: any) => void | boolean | Props[key])[] }> = never, + Uncontrolled extends Readonly<{ [key in keyof Props]?: UncontrolledPropValue }> = never, InnerProps = {}, State = {}, > extends PureComponent {