UNPKG

koval-ui

Version:

React components collection with minimalistic design. Supports theming, layout, and input validation.

1 lines 9.27 kB
{"version":3,"file":"InputRange.cjs","sources":["../../../../src/lib/InputRange/InputRange.tsx"],"sourcesContent":["import type {ChangeEvent, FC, SVGProps} from 'react';\nimport {useMemo} from 'react';\nimport {forwardRef, useCallback} from 'react';\nimport classNames from 'classnames';\nimport {useLocalTheme} from 'css-vars-hook';\n\nimport type {DataAttributes, LibraryProps} from '@/internal/LibraryAPI';\nimport type {NativePropsNumeric, CallbackPropsTextual, ValidationProps} from '@/internal/inputs';\nimport {useExternalValidation} from '@/internal/inputs';\nimport {useRevalidateOnFormChange} from '@/internal/inputs';\nimport {ValidationState, useValidationIcon, useValidation} from '@/internal/inputs';\nimport {useControllableState} from '@/internal/hooks/useControllableState.ts';\nimport {useInternalId} from '@/internal/hooks/useInternalId.ts';\nimport {useInternalRef} from '@/internal/hooks/useInternalRef.ts';\n\nimport classes from './InputRange.module.css';\n\nexport type Props = DataAttributes &\n LibraryProps &\n Omit<NativePropsNumeric, 'size'> &\n CallbackPropsTextual &\n ValidationProps & {\n prefix?: FC<{className?: string} & SVGProps<SVGSVGElement> & unknown>;\n bars?: number;\n scaleUnit?: string;\n /**\n * Enable to display scale below input\n */\n displayScale?: boolean;\n };\n\nconst createOptions = ({\n min,\n max,\n bars,\n scaleUnit,\n}: {\n min: number;\n max: number;\n bars: number;\n scaleUnit?: string;\n}) => {\n const total = max - min;\n const singleBar = total / bars;\n const scale = new Array(bars + 1).fill('');\n return scale.map((_, i) => {\n const value = Math.floor(min + singleBar * i);\n return (\n <option\n value={value}\n label={`- ${value}${scaleUnit}`}\n className={classes.mark}\n key={i}></option>\n );\n });\n};\n\nexport const InputRange = forwardRef<HTMLInputElement, Props>(\n (\n {\n prefix: Prefix,\n id,\n className,\n disabled,\n value,\n onChange = () => {},\n onFocus = () => {},\n onBlur = () => {},\n onKeyDown = () => {},\n onKeyUp = () => {},\n defaultValue,\n min = 0,\n max = 100,\n bars = 5,\n scaleUnit = '',\n revalidateOnFormChange,\n validation,\n errorMessage,\n displayScale,\n displayIcon = true,\n ...nativeProps\n },\n ref\n ) => {\n const hasValidators = Boolean(validation) || Boolean(nativeProps.required);\n\n const {validateTextual, validity, setValidity} = useValidation({validation, hasValidators});\n\n const inputRef = useInternalRef(ref);\n useRevalidateOnFormChange(inputRef, validateTextual, revalidateOnFormChange);\n useExternalValidation({errorMessage, inputRef, setValidity, validation});\n\n const ValidationIcon = useValidationIcon(validity);\n\n const [displayValue, setDisplayValue] = useControllableState({\n value,\n defaultValue,\n });\n\n const handleChange = useCallback(\n (event: ChangeEvent<HTMLInputElement>) => {\n setDisplayValue(event.target.value);\n onChange(event);\n },\n [onChange, setDisplayValue]\n );\n\n const handleInvalid = useCallback(() => {\n setValidity(ValidationState.error);\n }, [setValidity]);\n\n const inputId = useInternalId(id);\n const scaleId = `${inputId}-scale`;\n\n const {LocalRoot} = useLocalTheme();\n\n const theme = useMemo(\n () => ({\n 'output-length': max.toString().length + scaleUnit.length,\n }),\n [max, scaleUnit]\n );\n\n return (\n <div\n className={classNames(\n classes['input-range'],\n {[classes.withValidationIcon]: displayIcon},\n className\n )}>\n {Prefix && (\n <label className={classes.prefix} htmlFor={inputId}>\n <Prefix />\n </label>\n )}\n <div className={classes['scale-wrapper']}>\n <input\n {...nativeProps}\n id={inputId}\n type=\"range\"\n className={classes.input}\n ref={inputRef}\n disabled={disabled}\n value={value}\n defaultValue={defaultValue}\n onChange={handleChange}\n onBlur={onBlur}\n onFocus={onFocus}\n onKeyUp={onKeyUp}\n onKeyDown={onKeyDown}\n onInvalid={handleInvalid}\n onInput={validateTextual}\n list={scaleId}\n min={min}\n max={max}\n />\n {displayScale && (\n <datalist id={scaleId} className={classes.scale}>\n {createOptions({min: Number(min), max: Number(max), bars, scaleUnit})}\n </datalist>\n )}\n </div>\n {/* TODO: add htmlFor when CSS vars hook supports it */}\n <LocalRoot as=\"output\" theme={theme} className={classes.output}>\n {displayValue || Number(max) / 2} {scaleUnit}\n </LocalRoot>\n {displayIcon && validity && <ValidationIcon className={classes.validation} />}\n </div>\n );\n }\n);\n\nInputRange.displayName = 'InputRange';\n"],"names":["createOptions","min","max","bars","scaleUnit","singleBar","_","i","value","jsx","classes","InputRange","forwardRef","Prefix","id","className","disabled","onChange","onFocus","onBlur","onKeyDown","onKeyUp","defaultValue","revalidateOnFormChange","validation","errorMessage","displayScale","displayIcon","nativeProps","ref","hasValidators","validateTextual","validity","setValidity","useValidation","inputRef","useInternalRef","useRevalidateOnFormChange","useExternalValidation","ValidationIcon","useValidationIcon","displayValue","setDisplayValue","useControllableState","handleChange","useCallback","event","handleInvalid","ValidationState","inputId","useInternalId","scaleId","LocalRoot","useLocalTheme","theme","useMemo","jsxs","classNames"],"mappings":"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"}