diff --git a/categories/blob/react/src/components/FileSelectBox/index.tsx b/categories/blob/react/src/components/FileSelectBox/index.tsx index 54317c8..4a3b9c9 100644 --- a/categories/blob/react/src/components/FileSelectBox/index.tsx +++ b/categories/blob/react/src/components/FileSelectBox/index.tsx @@ -31,6 +31,9 @@ export interface FileSelectBoxProps< * Short textual description as guidelines for valid input values. */ hint?: React.ReactNode, + /** + * Should the component be enhanced? + */ enhanced?: boolean, /** * Is the label hidden? diff --git a/categories/color/react/src/components/ColorPicker/index.tsx b/categories/color/react/src/components/ColorPicker/index.tsx index b964c2a..cf6adc7 100644 --- a/categories/color/react/src/components/ColorPicker/index.tsx +++ b/categories/color/react/src/components/ColorPicker/index.tsx @@ -18,6 +18,9 @@ export const colorPickerPlugin = plugin(({ addComponents }) => { '&::-webkit-color-swatch': { 'border': '2px solid black', }, + '&::-moz-color-swatch': { + 'border': '2px solid black', + }, }, }); }); @@ -63,6 +66,7 @@ export const ColorPicker = React.forwardRef< }, )} > + {/* todo add chevron down to picker */} , 'size' | 'type' | 'label' | 'inputMode' | 'pattern'> { +/** + * Props of the {@link EmailInput} component. + */ +export interface EmailInputProps extends Omit, 'size' | 'type' | 'label' | 'inputMode' | 'pattern' | 'autoComplete'> { /** * Short textual description indicating the nature of the component's value. */ @@ -42,6 +48,10 @@ export interface EmailInputProps extends Omit, 'size' | 'type' | 'label' | 'list' | 'inputMode'> { /** * Short textual description indicating the nature of the component's value. diff --git a/categories/formatted/react/src/components/PhoneNumberInput/index.tsx b/categories/formatted/react/src/components/PhoneNumberInput/index.tsx index ac53c86..683d301 100644 --- a/categories/formatted/react/src/components/PhoneNumberInput/index.tsx +++ b/categories/formatted/react/src/components/PhoneNumberInput/index.tsx @@ -4,9 +4,15 @@ import { useClientSide, useFallbackId, useProxyInput } from '@modal-sh/react-uti import PhoneInput, { Country, Value } from 'react-phone-number-input/input'; import clsx from 'clsx'; +/** + * Derived HTML element of the {@link PhoneNumberInput} component. + */ export type PhoneNumberInputDerivedElement = HTMLInputElement; -export interface PhoneNumberInputProps extends Omit, 'size' | 'type' | 'label' | 'inputMode'> { +/** + * Props of the {@link PhoneNumberInput} component. + */ +export interface PhoneNumberInputProps extends Omit, 'autoComplete' | 'size' | 'type' | 'label' | 'inputMode'> { /** * Short textual description indicating the nature of the component's value. */ diff --git a/categories/formatted/react/src/components/UrlInput/index.tsx b/categories/formatted/react/src/components/UrlInput/index.tsx index 1fb913d..5d66c74 100644 --- a/categories/formatted/react/src/components/UrlInput/index.tsx +++ b/categories/formatted/react/src/components/UrlInput/index.tsx @@ -3,8 +3,14 @@ import { TextControl } from '@tesseract-design/web-base'; import clsx from 'clsx'; import { useFallbackId } from '@modal-sh/react-utils'; +/** + * Derived HTML element of the {@link UrlInput} component. + */ export type UrlInputDerivedElement = HTMLInputElement; +/** + * Props of the {@link UrlInput} component. + */ export interface UrlInputProps extends Omit, 'size' | 'type' | 'label' | 'inputMode'> { /** * Short textual description indicating the nature of the component's value. diff --git a/categories/freeform/react/src/components/MaskedTextInput/index.tsx b/categories/freeform/react/src/components/MaskedTextInput/index.tsx index b5dd000..77ebf88 100644 --- a/categories/freeform/react/src/components/MaskedTextInput/index.tsx +++ b/categories/freeform/react/src/components/MaskedTextInput/index.tsx @@ -3,9 +3,15 @@ import { TextControl } from '@tesseract-design/web-base'; import clsx from 'clsx'; import { useClientSide, useFallbackId } from '@modal-sh/react-utils'; +/** + * Derived HTML element of the {@link MaskedTextInput} component. + */ export type MaskedTextInputDerivedElement = HTMLInputElement; -export interface MaskedTextInputProps extends Omit, 'size' | 'type' | 'label' | 'pattern'> { +/** + * Props of the {@link MaskedTextInput} component. + */ +export interface MaskedTextInputProps extends Omit, 'autoComplete' | 'size' | 'type' | 'label' | 'pattern'> { /** * Short textual description indicating the nature of the component's value. */ @@ -38,6 +44,14 @@ export interface MaskedTextInputProps extends Omit { - const { clientSide: indicator } = useClientSide({ clientSide: true, initial: false }); + const { clientSide: enhanced } = useClientSide({ clientSide: enhancedProp }); const labelId = React.useId(); const id = useFallbackId(idProp); const [visible, setVisible] = React.useState(false); + const [visibleViaKey, setVisibleViaKey] = React.useState(false); const defaultRef = React.useRef(null); const ref = forwardedRef ?? defaultRef; + const handleKeyDown: React.KeyboardEventHandler< + MaskedTextInputDerivedElement + > = React.useCallback((e) => { + if (e.ctrlKey && e.code === 'Space') { + setVisibleViaKey(true); + } + onKeyDown?.(e); + }, [onKeyDown]); + const handleKeyUp: React.KeyboardEventHandler< MaskedTextInputDerivedElement > = React.useCallback((e) => { if (e.ctrlKey && e.code === 'Space') { + setVisibleViaKey(false); setVisible((prev) => !prev); } onKeyUp?.(e); @@ -98,6 +126,22 @@ export const MaskedTextInput = React.forwardRef< }); }, [ref, defaultRef]); + // const preserveFocus: React.MouseEventHandler = React.useCallback(() => { + // const { current } = typeof ref === 'object' ? ref : defaultRef; + // setVisibleViaKey(true); + // setTimeout(() => { + // current?.focus(); + // }); + // }, [ref, defaultRef]); + + // const handleToggleMouseUp: React.MouseEventHandler = React.useCallback(() => { + // const { current } = typeof ref === 'object' ? ref : defaultRef; + // setVisibleViaKey(false); + // setTimeout(() => { + // current?.focus(); + // }); + // }, [ref, defaultRef]); + React.useEffect(() => { if (typeof ref === 'function') { const defaultElement = defaultRef.current as MaskedTextInputDerivedElement; @@ -131,12 +175,12 @@ export const MaskedTextInput = React.forwardRef< 'sr-only': hiddenLabel, }, { - 'pr-1': !indicator, + 'pr-1': !enhanced, }, { - 'pr-10': indicator && size === 'small', - 'pr-12': indicator && size === 'medium', - 'pr-16': indicator && size === 'large', + 'pr-10': enhanced && size === 'small', + 'pr-12': enhanced && size === 'medium', + 'pr-16': enhanced && size === 'large', }, )} > @@ -156,7 +200,9 @@ export const MaskedTextInput = React.forwardRef< aria-labelledby={labelId} type={!visible ? 'password' : 'text'} data-testid="input" - onKeyUp={handleKeyUp} + autoComplete={autoComplete ?? 'off'} + onKeyUp={enhanced ? handleKeyUp : undefined} + onKeyDown={enhanced ? handleKeyDown : undefined} className={clsx( 'bg-negative rounded-inherit w-full peer block font-inherit', 'focus:outline-0', @@ -173,13 +219,13 @@ export const MaskedTextInput = React.forwardRef< 'pt-4': variant === 'alternate', }, { - 'pr-4': variant === 'default' && !indicator, - 'pr-1.5': variant === 'alternate' && !indicator, + 'pr-4': variant === 'default' && !enhanced, + 'pr-1.5': variant === 'alternate' && !enhanced, }, { - 'pr-10': indicator && size === 'small', - 'pr-12': indicator && size === 'medium', - 'pr-16': indicator && size === 'large', + 'pr-10': enhanced && size === 'small', + 'pr-12': enhanced && size === 'medium', + 'pr-16': enhanced && size === 'large', }, { 'h-10': size === 'small', @@ -202,13 +248,13 @@ export const MaskedTextInput = React.forwardRef< 'pt-3': variant === 'alternate' && size !== 'small', }, { - 'pr-4': !indicator && variant === 'default', - 'pr-1': !indicator && variant === 'alternate', + 'pr-4': !enhanced && variant === 'default', + 'pr-1': !enhanced && variant === 'alternate', }, { - 'pr-10': indicator && size === 'small', - 'pr-12': indicator && size === 'medium', - 'pr-16': indicator && size === 'large', + 'pr-10': enhanced && size === 'small', + 'pr-12': enhanced && size === 'medium', + 'pr-16': enhanced && size === 'large', }, )} > @@ -219,14 +265,18 @@ export const MaskedTextInput = React.forwardRef< )} - {indicator && ( + {enhanced && ( - - + + Step Down + + + )} {border && ( { * sliders and vv. */ +/** + * Orientation of the {@link Slider} component. + */ export type SliderOrientation = 'horizontal' | 'vertical'; +/** + * Derived HTML element of the {@link Slider} component. + */ export type SliderDerivedElement = HTMLInputElement; +/** + * Props of the {@link Slider} component. + */ export interface SliderProps extends Omit, 'type'> { + /** + * Orientation of the component. + */ orient?: SliderOrientation; + /** + * Options of the component. + */ children?: React.ReactNode; + /** + * Length of the component. + */ length?: React.CSSProperties['width']; } @@ -93,7 +111,7 @@ export const sliderPlugin = plugin(({ addComponents }) => { 'aspect-ratio': '1 / 1', 'z-index': '1', position: 'relative', - 'box-shadow': '-100000.5em 0 0 100000em rgb(var(--color-primary) / 50%)', + 'box-shadow': 'calc(-200001em / 2) 0 0 100000em rgb(var(--color-primary) / 50%)', }, '& > input:focus::-webkit-slider-container': { @@ -105,11 +123,11 @@ export const sliderPlugin = plugin(({ addComponents }) => { }, '& > input:focus::-webkit-slider-thumb': { - 'box-shadow': '-100000.5em 0 0 100000em rgb(var(--color-secondary) / 50%)', + 'box-shadow': 'calc(-200001em / 2) 0 0 100000em rgb(var(--color-secondary) / 50%)', }, '& > input:active::-webkit-slider-thumb': { - 'box-shadow': '-100000.5em 0 0 100000em rgb(var(--color-tertiary) / 50%)', + 'box-shadow': 'calc(-200001em / 2) 0 0 100000em rgb(var(--color-tertiary) / 50%)', }, '&[data-orient="horizontal"]': { @@ -155,15 +173,15 @@ export const sliderPlugin = plugin(({ addComponents }) => { 'aspect-ratio': '1 / 1', 'z-index': '1', position: 'relative', - 'box-shadow': '-100000.5em 0 0 100000em rgb(var(--color-primary) / 50%)', + 'box-shadow': 'calc(-200001em / 2) 0 0 100000em rgb(var(--color-primary) / 50%)', }, '& > input:focus::-moz-range-thumb': { - 'box-shadow': '-100000.5em 0 0 100000em rgb(var(--color-secondary) / 50%)', + 'box-shadow': 'calc(-200001em / 2) 0 0 100000em rgb(var(--color-secondary) / 50%)', }, '& > input:active::-moz-range-thumb': { - 'box-shadow': '-100000.5em 0 0 100000em rgb(var(--color-tertiary) / 50%)', + 'box-shadow': 'calc(-200001em / 2) 0 0 100000em rgb(var(--color-tertiary) / 50%)', }, '& > input[orient="vertical"]': { @@ -179,15 +197,15 @@ export const sliderPlugin = plugin(({ addComponents }) => { '& > input[orient="vertical"]::-moz-range-thumb': { width: '100%', height: '1em', - 'box-shadow': '0 100000.5em 0 100000em rgb(var(--color-primary) / 50%)', + 'box-shadow': '0 calc(200001em / 2) 0 100000em rgb(var(--color-primary) / 50%)', }, '& > input[orient="vertical"]:focus::-moz-range-thumb': { - 'box-shadow': '0 100000.5em 0 100000em rgb(var(--color-secondary) / 50%)', + 'box-shadow': '0 calc(200001em / 2) 0 100000em rgb(var(--color-secondary) / 50%)', }, '& > input[orient="vertical"]:active::-moz-range-thumb': { - 'box-shadow': '0 100000.5em 0 100000em rgb(var(--color-tertiary) / 50%)', + 'box-shadow': '0 calc(200001em / 2) 0 100000em rgb(var(--color-tertiary) / 50%)', }, '&[data-chrome] > input + *': { @@ -208,6 +226,9 @@ export const sliderPlugin = plugin(({ addComponents }) => { }); }); +/** + * Component for inputting continuous numeric values. + */ export const Slider = React.forwardRef(( { className, diff --git a/categories/temporal/react/src/components/DateDropdown/index.tsx b/categories/temporal/react/src/components/DateDropdown/index.tsx index 06b25a4..68522c4 100644 --- a/categories/temporal/react/src/components/DateDropdown/index.tsx +++ b/categories/temporal/react/src/components/DateDropdown/index.tsx @@ -4,8 +4,14 @@ import clsx from 'clsx'; import plugin from 'tailwindcss/plugin'; import { useFallbackId } from '@modal-sh/react-utils'; +/** + * Derived HTML element of the {@link DateDropdown} component. + */ export type DateDropdownDerivedElement = HTMLInputElement; +/** + * Props of the {@link DateDropdown} component. + */ export interface DateDropdownProps extends Omit, 'size' | 'type' | 'label' | 'pattern'> { /** * Short textual description indicating the nature of the component's value. @@ -68,7 +74,7 @@ export const dateDropdownPlugin = plugin(({ addComponents }) => { }); /** - * Component for inputting textual values. + * Component for inputting date values. */ export const DateDropdown = React.forwardRef< DateDropdownDerivedElement, diff --git a/categories/temporal/react/src/components/TimeSpinner/index.tsx b/categories/temporal/react/src/components/TimeSpinner/index.tsx index bc1bb41..c18f195 100644 --- a/categories/temporal/react/src/components/TimeSpinner/index.tsx +++ b/categories/temporal/react/src/components/TimeSpinner/index.tsx @@ -4,6 +4,9 @@ import clsx from 'clsx'; import plugin from 'tailwindcss/plugin'; import { useFallbackId } from '@modal-sh/react-utils'; +/** + * Derived HTML element of the {@link TimeSpinner} component. + */ export type TimeSpinnerDerivedElement = HTMLInputElement; type Digit = (0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9); @@ -16,6 +19,9 @@ type StepHhMmSs = `${StepHhMm}:${Segment}`; type Step = StepHhMm | StepHhMmSs; +/** + * Props of the {@link TimeSpinner} component. + */ export interface TimeSpinnerProps extends Omit, 'size' | 'type' | 'label' | 'step' | 'pattern'> { /** * Short textual description indicating the nature of the component's value. @@ -82,7 +88,7 @@ export const timeSpinnerPlugin = plugin(({ addComponents }) => { }); /** - * Component for inputting textual values. + * Component for inputting time values. */ export const TimeSpinner = React.forwardRef< TimeSpinnerDerivedElement, diff --git a/showcases/web-kitchensink-reactnext/src/pages/examples/registration-form/index.tsx b/showcases/web-kitchensink-reactnext/src/pages/examples/registration-form/index.tsx index 0320508..19977c3 100644 --- a/showcases/web-kitchensink-reactnext/src/pages/examples/registration-form/index.tsx +++ b/showcases/web-kitchensink-reactnext/src/pages/examples/registration-form/index.tsx @@ -102,6 +102,7 @@ const RegistrationFormPage: NextPage = () => { label="Password" name="password" onChange={handleChange} + enhanced />
@@ -111,6 +112,7 @@ const RegistrationFormPage: NextPage = () => { label="Confirm Password" name="confirmPassword" onChange={handleChange} + enhanced />