@nex-ui/react
Version:
🎉 A beautiful, modern, and reliable React component library.
245 lines (241 loc) • 7.98 kB
JavaScript
"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;