From 7b7e930c0ee7a913b4117c1807e63141329261aa Mon Sep 17 00:00:00 2001 From: Slizhevsky Vladislav Date: Wed, 25 Mar 2026 18:17:25 +0100 Subject: [PATCH 1/2] [UIK-5011][checkbox] rewrite component to ts --- semcore/checkbox/package.json | 2 +- .../checkbox/src/Checkbox.internal.type.ts | 24 +++++++ .../src/{Checkbox.jsx => Checkbox.tsx} | 63 +++++++++++-------- .../src/{index.d.ts => Checkbox.type.ts} | 14 ++--- semcore/checkbox/src/{index.js => index.ts} | 2 +- semcore/checkbox/vite.config.ts | 2 +- semcore/core/src/core-types/Component.ts | 9 ++- 7 files changed, 79 insertions(+), 37 deletions(-) create mode 100644 semcore/checkbox/src/Checkbox.internal.type.ts rename semcore/checkbox/src/{Checkbox.jsx => Checkbox.tsx} (76%) rename semcore/checkbox/src/{index.d.ts => Checkbox.type.ts} (78%) rename semcore/checkbox/src/{index.js => index.ts} (53%) 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.internal.type.ts b/semcore/checkbox/src/Checkbox.internal.type.ts new file mode 100644 index 0000000000..9fa94ec45e --- /dev/null +++ b/semcore/checkbox/src/Checkbox.internal.type.ts @@ -0,0 +1,24 @@ +import type { IRootComponentProps } from '@semcore/core/src'; + +import type { CheckboxProps } from './Checkbox.type'; + +export type CheckboxValueControlPropsInternal = IRootComponentProps & { + indeterminate: CheckboxProps['indeterminate']; + state: CheckboxProps['state']; +}; + +export type CheckboxValueCheckMarkPropsInternal = IRootComponentProps & { + indeterminate: CheckboxProps['indeterminate']; + state: CheckboxProps['state']; + checked: CheckboxProps['checked']; +}; + +export type CheckboxTextPropsInternal = { + disabled: CheckboxProps['disabled']; + hoistDisabled: (value: boolean) => void; + rootDisabled?: boolean; +}; + +export type CheckboxValuePropsInternal = { + checked?: boolean; +}; diff --git a/semcore/checkbox/src/Checkbox.jsx b/semcore/checkbox/src/Checkbox.tsx similarity index 76% rename from semcore/checkbox/src/Checkbox.jsx rename to semcore/checkbox/src/Checkbox.tsx index f8a8cc07f4..0f86fc450a 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,15 @@ import { useColorResolver } from '@semcore/core/lib/utils/use/useColorResolver'; import { Text as TypographyText } from '@semcore/typography'; import React from 'react'; +import type { CheckboxTextPropsInternal, CheckboxValueCheckMarkPropsInternal, CheckboxValueControlPropsInternal, CheckboxValuePropsInternal } from './Checkbox.internal.type'; +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 +31,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 +107,29 @@ class CheckboxRoot extends Component { } } -class ValueRoot extends Component { - static defaultProps = (props) => { +class ValueRoot extends Component< + CheckboxValueProps & CheckboxValuePropsInternal, + 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,15 @@ class ValueRoot extends Component { } } -function Control(props) { +function Control(props: CheckboxValueControlProps & CheckboxValueControlPropsInternal) { 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 +227,26 @@ function Control(props) { } Control.displayName = 'Control'; -function CheckMark(props) { +function CheckMark(props: CheckboxValueCheckMarkProps & CheckboxValueCheckMarkPropsInternal) { 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) { +function Text(props: CheckboxTextProps & CheckboxTextPropsInternal) { 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 +262,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 { From cebfe6dd067b18b019638355f4cb1ae04499b5d7 Mon Sep 17 00:00:00 2001 From: Slizhevsky Vladislav Date: Thu, 26 Mar 2026 16:14:11 +0100 Subject: [PATCH 2/2] [UIK-5011][checkbox] update types --- .../checkbox/src/Checkbox.internal.type.ts | 24 ------------------- semcore/checkbox/src/Checkbox.tsx | 13 ++++++---- 2 files changed, 8 insertions(+), 29 deletions(-) delete mode 100644 semcore/checkbox/src/Checkbox.internal.type.ts diff --git a/semcore/checkbox/src/Checkbox.internal.type.ts b/semcore/checkbox/src/Checkbox.internal.type.ts deleted file mode 100644 index 9fa94ec45e..0000000000 --- a/semcore/checkbox/src/Checkbox.internal.type.ts +++ /dev/null @@ -1,24 +0,0 @@ -import type { IRootComponentProps } from '@semcore/core/src'; - -import type { CheckboxProps } from './Checkbox.type'; - -export type CheckboxValueControlPropsInternal = IRootComponentProps & { - indeterminate: CheckboxProps['indeterminate']; - state: CheckboxProps['state']; -}; - -export type CheckboxValueCheckMarkPropsInternal = IRootComponentProps & { - indeterminate: CheckboxProps['indeterminate']; - state: CheckboxProps['state']; - checked: CheckboxProps['checked']; -}; - -export type CheckboxTextPropsInternal = { - disabled: CheckboxProps['disabled']; - hoistDisabled: (value: boolean) => void; - rootDisabled?: boolean; -}; - -export type CheckboxValuePropsInternal = { - checked?: boolean; -}; diff --git a/semcore/checkbox/src/Checkbox.tsx b/semcore/checkbox/src/Checkbox.tsx index 0f86fc450a..ff9cb80197 100644 --- a/semcore/checkbox/src/Checkbox.tsx +++ b/semcore/checkbox/src/Checkbox.tsx @@ -9,7 +9,6 @@ import { useColorResolver } from '@semcore/core/lib/utils/use/useColorResolver'; import { Text as TypographyText } from '@semcore/typography'; import React from 'react'; -import type { CheckboxTextPropsInternal, CheckboxValueCheckMarkPropsInternal, CheckboxValueControlPropsInternal, CheckboxValuePropsInternal } from './Checkbox.internal.type'; import type { CheckboxComponent, CheckboxProps, CheckboxTextProps, CheckboxValueCheckMarkProps, CheckboxValueComponent, CheckboxValueControlProps, CheckboxValueProps } from './Checkbox.type'; import style from './style/checkbox.shadow.css'; @@ -107,8 +106,9 @@ class CheckboxRoot extends Component { } } +type ValuePropsFromRoot = ReturnType['getValueProps']>; class ValueRoot extends Component< - CheckboxValueProps & CheckboxValuePropsInternal, + ValuePropsFromRoot & CheckboxValueProps, typeof ValueRoot.enhance, { checked: (e: React.ChangeEvent) => boolean } > { @@ -202,7 +202,8 @@ class ValueRoot extends Component< } } -function Control(props: CheckboxValueControlProps & CheckboxValueControlPropsInternal) { +type ControlPropsFromRoot = ReturnType['getControlProps']>; +function Control(props: IRootComponentProps & ControlPropsFromRoot & CheckboxValueControlProps) { const SControl = Root; const { indeterminate, styles, state } = props; const checkboxRef = React.useRef(null); @@ -227,7 +228,8 @@ function Control(props: CheckboxValueControlProps & CheckboxValueControlPropsInt } Control.displayName = 'Control'; -function CheckMark(props: CheckboxValueCheckMarkProps & CheckboxValueCheckMarkPropsInternal) { +type CheckMarkPropsFromRoot = ReturnType['getCheckMarkProps']>; +function CheckMark(props: IRootComponentProps & CheckMarkPropsFromRoot & CheckboxValueCheckMarkProps) { const SCheckbox = Root; const SInvalidPattern = InvalidStateBox; const { styles, state, checked, indeterminate } = props; @@ -239,7 +241,8 @@ function CheckMark(props: CheckboxValueCheckMarkProps & CheckboxValueCheckMarkPr } CheckMark.displayName = 'CheckMark'; -function Text(props: CheckboxTextProps & CheckboxTextPropsInternal) { +type TextPropsFromRoot = ReturnType['getTextProps']>; +function Text(props: IRootComponentProps & TextPropsFromRoot & CheckboxTextProps) { const SText = Root; const { styles, color } = props;