From 2258466d86589ae8ad634051617c194b159e998c Mon Sep 17 00:00:00 2001 From: TheoryOfNekomata Date: Sun, 3 Sep 2023 10:03:08 +0800 Subject: [PATCH] Update derived element types Use HTMLElementTagNameMap to unify both rendering and typing. --- .../src/components/ActionButton/index.tsx | 10 +- .../src/components/FileSelectBox/index.tsx | 162 ++++++++++-------- .../react/src/components/ComboBox/index.tsx | 8 +- .../src/components/DropdownSelect/index.tsx | 10 +- .../react/src/components/MenuSelect/index.tsx | 8 +- .../src/components/RadioButton/index.tsx | 12 +- .../src/components/RadioTickBox/index.tsx | 8 +- .../src/components/ColorPicker/index.tsx | 8 +- .../react/src/components/Swatch/index.tsx | 8 +- .../react/src/components/EmailInput/index.tsx | 8 +- .../src/components/PatternTextInput/index.tsx | 8 +- .../src/components/PhoneNumberInput/index.tsx | 8 +- .../react/src/components/UrlInput/index.tsx | 8 +- .../src/components/MaskedTextInput/index.tsx | 8 +- .../components/MultilineTextInput/index.tsx | 8 +- .../react/src/components/TextInput/index.tsx | 8 +- .../react/src/components/Badge/index.tsx | 10 +- .../src/components/KeyValueTable/index.tsx | 28 ++- .../src/components/MenuMultiSelect/index.tsx | 8 +- .../react/src/components/TagInput/index.tsx | 18 +- .../src/components/ToggleButton/index.tsx | 8 +- .../src/components/ToggleSwitch/index.tsx | 8 +- .../src/components/ToggleTickBox/index.tsx | 8 +- .../react/src/components/LinkButton/index.tsx | 14 +- .../src/components/NumberSpinner/index.tsx | 20 ++- .../react/src/components/Slider/index.tsx | 12 +- .../src/components/DateDropdown/index.tsx | 8 +- .../src/components/TimeSpinner/index.tsx | 8 +- 28 files changed, 288 insertions(+), 152 deletions(-) diff --git a/categories/web/action/react/src/components/ActionButton/index.tsx b/categories/web/action/react/src/components/ActionButton/index.tsx index f2211cd..b439498 100644 --- a/categories/web/action/react/src/components/ActionButton/index.tsx +++ b/categories/web/action/react/src/components/ActionButton/index.tsx @@ -2,10 +2,14 @@ import * as React from 'react'; import clsx from 'clsx'; import { Button } from '@tesseract-design/web-base'; +const ActionButtonDerivedElementComponent = 'button' as const; + /** * Derived HTML element of the {@link ActionButton} component. */ -export type ActionButtonDerivedElement = HTMLButtonElement; +export type ActionButtonDerivedElement = HTMLElementTagNameMap[ + typeof ActionButtonDerivedElementComponent +]; /** * Props of the {@link ActionButton} component. @@ -76,7 +80,7 @@ export const ActionButton = React.forwardRef ( - + )); ActionButton.displayName = 'ActionButton' as const; diff --git a/categories/web/blob/react/src/components/FileSelectBox/index.tsx b/categories/web/blob/react/src/components/FileSelectBox/index.tsx index e55b031..bc3c7f5 100644 --- a/categories/web/blob/react/src/components/FileSelectBox/index.tsx +++ b/categories/web/blob/react/src/components/FileSelectBox/index.tsx @@ -2,9 +2,7 @@ import * as React from 'react'; import { useClientSide, useFallbackId, useProxyInput } from '@modal-sh/react-utils'; import clsx from 'clsx'; -const DEFAULT_ENHANCED_HEIGHT_PX = 64 as const; - -const DEFAULT_NON_ENHANCED_SIDE_HEIGHT_PX = 256 as const; +const FileSelectBoxDefaultPreviewComponentDerivedElementComponent = 'div' as const; /** * Common props for the {@link FileSelectBoxProps.previewComponent|previewComponent prop} of the @@ -29,57 +27,9 @@ export interface CommonPreviewComponentProps = Partial = Partial, - P extends CommonPreviewComponentProps = CommonPreviewComponentProps -> extends Omit, 'size' | 'type' | 'label' | 'list'> { - /** - * Should the component display a border? - */ - border?: boolean, - /** - * Should the component occupy the whole width of its parent? - */ - block?: boolean, - /** - * Short textual description indicating the nature of the component's value. - */ - label?: React.ReactNode, - /** - * Short textual description as guidelines for valid input values. - */ - hint?: React.ReactNode, - /** - * Should the component be enhanced? - */ - enhanced?: boolean, - /** - * Is the label hidden? - */ - hiddenLabel?: boolean, - /** - * Preview component for the selected file(s). - */ - previewComponent?: React.ElementType

, - /** - * Reselect label. - */ - reselectLabel?: string, - /** - * Clear label. - */ - clearLabel?: string, -} - -export type FileSelectBoxDefaultPreviewComponentDerivedElement = HTMLDivElement; +export type FileSelectBoxDefaultPreviewComponentDerivedElement = HTMLElementTagNameMap[ + typeof FileSelectBoxDefaultPreviewComponentDerivedElementComponent +]; /** * Default component for the {@link FileSelectBoxProps.previewComponent|previewComponent prop} @@ -94,7 +44,7 @@ export const FileSelectBoxDefaultPreviewComponent = React.forwardRef< enhanced, disabled, }, forwardedRef) => ( -

)} -
+ )); -const isButtonElement = (el: HTMLElement): el is HTMLButtonElement => el.tagName === 'BUTTON'; +const DEFAULT_ENHANCED_HEIGHT_PX = 64 as const; + +const DEFAULT_NON_ENHANCED_SIDE_HEIGHT_PX = 256 as const; + +const FileSelectBoxRootElementComponent = 'div' as const; -const isInputElement = (el: HTMLElement): el is HTMLInputElement => el.tagName === 'INPUT'; +type FileSelectBoxRootElement = HTMLElementTagNameMap[typeof FileSelectBoxRootElementComponent]; + +const FileSelectBoxActionElementComponent = 'button' as const; + +type FileSelectBoxActionElement = HTMLElementTagNameMap[typeof FileSelectBoxActionElementComponent]; + +const FileSelectBoxDerivedElementComponent = 'input' as const; + +/** + * Derived HTML element of the {@link FileSelectBox} component. + */ +export type FileSelectBoxDerivedElement = HTMLElementTagNameMap[typeof FileSelectBoxDerivedElementComponent]; + +/** + * Props of the {@link FileSelectBox} component. + */ +export interface FileSelectBoxProps< + F extends Partial = Partial, + P extends CommonPreviewComponentProps = CommonPreviewComponentProps +> extends Omit, 'size' | 'type' | 'label' | 'list'> { + /** + * Should the component display a border? + */ + border?: boolean, + /** + * Should the component occupy the whole width of its parent? + */ + block?: boolean, + /** + * Short textual description indicating the nature of the component's value. + */ + label?: React.ReactNode, + /** + * Short textual description as guidelines for valid input values. + */ + hint?: React.ReactNode, + /** + * Should the component be enhanced? + */ + enhanced?: boolean, + /** + * Is the label hidden? + */ + hiddenLabel?: boolean, + /** + * Preview component for the selected file(s). + */ + previewComponent?: React.ElementType

, + /** + * Reselect label. + */ + reselectLabel?: string, + /** + * Clear label. + */ + clearLabel?: string, +} + +const isButtonElement = (el: HTMLElement): el is FileSelectBoxActionElement => el.tagName === 'BUTTON'; + +const isInputElement = (el: HTMLElement): el is FileSelectBoxDerivedElement => el.tagName === 'INPUT'; const isKeyUpEvent = (e: React.SyntheticEvent): e is React.KeyboardEvent => e.type === 'keyup'; @@ -211,8 +225,8 @@ export const FileSelectBox = React.forwardRef - | React.MouseEvent - | React.DragEvent + | React.MouseEvent + | React.DragEvent | React.KeyboardEvent | React.ClipboardEvent, FileSelectBoxDerivedElement @@ -270,12 +284,12 @@ export const FileSelectBox = React.forwardRef = React.useCallback((e) => { + const cancelEvent: React.DragEventHandler = React.useCallback((e) => { e.stopPropagation(); e.preventDefault(); }, []); - const handleDrop: React.DragEventHandler = React.useCallback((e) => { + const handleDrop: React.DragEventHandler = React.useCallback((e) => { cancelEvent(e); doSetFileList(e); }, [cancelEvent, doSetFileList]); @@ -312,7 +326,7 @@ export const FileSelectBox = React.forwardRef = React.useCallback(() => { setAboutToSelect(true); setTimeout(() => { @@ -322,7 +336,7 @@ export const FileSelectBox = React.forwardRef = React.useCallback(() => { const fileInput = defaultRef.current as FileSelectBoxDerivedElement; if (typeof fileInput.showPicker !== 'function') { @@ -333,7 +347,7 @@ export const FileSelectBox = React.forwardRef = React.useCallback(() => { setAboutToClear(true); setTimeout(() => { @@ -366,7 +380,7 @@ export const FileSelectBox = React.forwardRef )} {clientSide && ( - + )} -

- +
- +
@@ -569,7 +583,7 @@ export const FileSelectBox = React.forwardRef )} - + ); }); diff --git a/categories/web/choice/react/src/components/ComboBox/index.tsx b/categories/web/choice/react/src/components/ComboBox/index.tsx index 770e7dc..ae584d7 100644 --- a/categories/web/choice/react/src/components/ComboBox/index.tsx +++ b/categories/web/choice/react/src/components/ComboBox/index.tsx @@ -3,10 +3,14 @@ import { TextControl } from '@tesseract-design/web-base'; import { useFallbackId } from '@modal-sh/react-utils'; import clsx from 'clsx'; +const ComboBoxDerivedElementComponent = 'input' as const; + /** * Derived HTML element of the {@link ComboBox} component. */ -export type ComboBoxDerivedElement = HTMLInputElement; +export type ComboBoxDerivedElement = HTMLElementTagNameMap[ + typeof ComboBoxDerivedElementComponent +]; /** * Props of the {@link ComboBox} component. @@ -143,7 +147,7 @@ export const ComboBox = React.forwardRef( {' '} )} - )} - + {hint && (
)} - + - - [0]; @@ -56,7 +60,7 @@ export const Swatch = React.forwardRef(({ )} style={style} > - )} - )} - )} - ( {' '} )} - )} - )} -