UNPKG

koval-ui

Version:

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

1 lines 9.23 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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"}