UNPKG

@nex-ui/react

Version:

🎉 A beautiful, modern, and reliable React component library.

245 lines (241 loc) • 7.98 kB
"use client"; 'use strict'; var jsxRuntime = require('react/jsx-runtime'); var react = require('react'); var styled = require('@nex-ui/styled'); var utils = require('@nex-ui/utils'); var hooks = require('@nex-ui/hooks'); var icons = require('@nex-ui/icons'); var Context = require('../provider/Context.cjs'); var useDefaultProps = require('../utils/useDefaultProps.cjs'); var useStyles = require('../utils/useStyles.cjs'); var useSlotProps = require('../utils/useSlotProps.cjs'); var Button = require('../button/Button.cjs'); var composeClasses = require('../utils/composeClasses.cjs'); var input = require('../../theme/recipes/input.cjs'); var getUtilityClass = require('../utils/getUtilityClass.cjs'); const useSlotClasses = (ownerState)=>{ const { prefix } = Context.useNexUI(); const inputRoot = `${prefix}-input`; const { variant, clearable, radius, size, color, disabled, fullWidth, invaild, classes, labelPlacement } = ownerState; const slots = { root: [ 'root', `variant-${variant}`, `radius-${radius}`, `size-${size}`, `color-${color}`, disabled && 'disabled', fullWidth && 'full-width', invaild && 'invaild', clearable && 'clearable', labelPlacement && `label-placement-${labelPlacement}` ], input: [ 'input' ], clearBtn: [ 'clear-btn' ], prefix: [ 'prefix' ], suffix: [ 'suffix' ], label: [ 'label' ] }; const composedClasses = composeClasses.composeClasses(slots, getUtilityClass.getUtilityClass(inputRoot), classes); return composedClasses; }; const useSlotAriaProps = (ownerState)=>{ const { tabIndex, disabled, invaild, label } = ownerState; const labelString = utils.isString(label); const id = react.useId(); const inputId = `input-${id}`; const labelId = `label-${id}`; const inputProps = { tabIndex: disabled ? -1 : tabIndex, 'aria-invalid': invaild, id: labelString ? inputId : undefined, 'aria-labelledby': labelString ? labelId : undefined, 'aria-label': labelString ? label : undefined }; const labelProps = { id: labelString ? labelId : undefined, htmlFor: labelString ? inputId : undefined }; const clearBtnProps = { 'aria-label': 'Clear input', tabIndex: -1 }; return { input: inputProps, label: labelProps, clearBtn: clearBtnProps }; }; const Input = (inProps)=>{ const { primaryThemeColor } = Context.useNexUI(); const props = useDefaultProps.useDefaultProps({ name: 'Input', props: inProps }); const { sx, ref, label, className, prefix, suffix, onClear, slotProps, onValueChange, placeholder, tabIndex = 0, as = 'input', defaultValue = '', value: valueProp, color = primaryThemeColor, type = 'text', disabled = false, variant = 'outlined', fullWidth = false, invaild = false, size = 'md', radius = size, clearable = false, labelPlacement: labelPlacementProp = 'float-outside', ...remainingProps } = props; const [value, setValue] = hooks.useControlledState(valueProp, defaultValue, onValueChange); const inputRef = react.useRef(null); const mergedRefs = utils.mergeRefs(ref, inputRef); const hasLabel = !!label; const hasValue = !!value; const hasPlaceholder = !!placeholder; const hasPrefix = !!prefix; let labelPlacement = labelPlacementProp; const floatLabel = labelPlacement === 'float-outside' || labelPlacement === 'float-inside'; const hasDefaultPlaceholder = [ 'date', 'datetime-local', 'time', 'week', 'month', 'range' ].includes(type); if (!hasLabel) { labelPlacement = undefined; } else if (floatLabel && (hasPlaceholder || hasValue || hasDefaultPlaceholder || hasPrefix)) { if (labelPlacementProp === 'float-outside') { labelPlacement = 'outside'; } else if (labelPlacementProp === 'float-inside') { labelPlacement = 'inside'; } } const ownerState = { ...props, as, tabIndex, color, disabled, variant, fullWidth, size, radius, invaild, type, clearable, value, labelPlacement }; const styles = useStyles.useStyles({ ownerState, name: 'Input', recipe: input.inputRecipe }); const classes = useSlotClasses(ownerState); const slotAriaProps = useSlotAriaProps(ownerState); const onClearValue = hooks.useEvent(()=>{ setValue(''); onClear?.(); inputRef.current?.focus(); }); const handleChange = hooks.useEvent((e)=>{ setValue(e.target.value); }); const rootProps = useSlotProps.useSlotProps({ ownerState, externalSlotProps: slotProps?.root, externalForwardedProps: { className, sx }, sx: styles.root, classNames: classes.root, additionalProps: { onClick: (e)=>{ if (inputRef.current && e.target === e.currentTarget) { inputRef.current.focus(); } } } }); const labelProps = useSlotProps.useSlotProps({ ownerState, externalSlotProps: slotProps?.label, sx: styles.label, classNames: classes.label, additionalProps: slotAriaProps.label }); const inputProps = useSlotProps.useSlotProps({ ownerState, externalForwardedProps: remainingProps, sx: styles.input, classNames: classes.input, additionalProps: { as, type, value, disabled, placeholder, ref: mergedRefs, onChange: handleChange, ...slotAriaProps.input } }); const clearBtnProps = useSlotProps.useSlotProps({ ownerState, externalSlotProps: slotProps?.clearBtn, sx: styles.clearBtn, classNames: classes.clearBtn, additionalProps: { onClick: onClearValue, iconOnly: true, disableRipple: true, size: 'sm', color: variant === 'filled' ? color : 'gray', variant: 'text', disabled: disabled, sx: { visibility: value ? 'visible' : 'hidden' }, ...slotAriaProps.clearBtn } }); const prefixProps = useSlotProps.useSlotProps({ ownerState, externalSlotProps: slotProps?.prefix, sx: styles.prefix, classNames: classes.prefix }); const suffixProps = useSlotProps.useSlotProps({ ownerState, externalSlotProps: slotProps?.suffix, sx: styles.suffix, classNames: classes.suffix }); return /*#__PURE__*/ jsxRuntime.jsxs(styled.nex.div, { ...rootProps, children: [ prefix && /*#__PURE__*/ jsxRuntime.jsx(styled.nex.span, { ...prefixProps, children: prefix }), label && /*#__PURE__*/ jsxRuntime.jsx(styled.nex.label, { ...labelProps, children: label }), /*#__PURE__*/ jsxRuntime.jsx(styled.nex.input, { ...inputProps }), clearable && /*#__PURE__*/ jsxRuntime.jsx(Button.Button, { ...clearBtnProps, children: /*#__PURE__*/ jsxRuntime.jsx(icons.CloseCircleFilled, {}) }), suffix && /*#__PURE__*/ jsxRuntime.jsx(styled.nex.span, { ...suffixProps, children: suffix }) ] }); }; Input.displayName = 'Input'; exports.Input = Input;