@veracity/vui
Version:
Veracity UI is a React component library crafted for use within Veracity applications and pages. Based on Styled Components and @xstyled.
231 lines (228 loc) • 7.35 kB
JavaScript
import { isString } from "../utils/assertion.js";
import { filterUndefined } from "../utils/object.js";
import { cs } from "../utils/styles.js";
import { clearIconSize, displayValueOnlyTextSize, helpTextMargin, helpTextSize, inputColors, inputStateMapping } from "./consts.js";
import { useStyleConfig } from "../core/theme.js";
import styled from "../core/styled.js";
import vui from "../core/vui.js";
import { Box } from "../box/box.js";
import { T } from "../t/t.js";
import { IconButton } from "../button/buttons.js";
import { InputProvider } from "./context.js";
import { HelpText } from "./helpText.js";
import { Label } from "../label/label.js";
import autoCompletePopover_default from "./autoCompletePopover.js";
import { getInitialCount } from "./helpers.js";
import { InputIcon } from "./inputIcon.js";
import { InputInput } from "./inputInput.js";
import { useEffect, useId, useMemo, useState } from "react";
import { jsx, jsxs } from "react/jsx-runtime";
//#region src/input/input.tsx
const InputBase = styled.divBox`
align-items: center;
color: sandstone.10;
background-color: white;
border-radius: none;
border-width: 1px;
display: flex;
flex-shrink: 0;
outline: none;
position: relative;
transition-duration: 0s;
transform: translate3d(0, 0, 0);
width: 100%;
&[aria-disabled='true'] {
opacity: 0.5;
cursor: not-allowed;
background-color: sandstone.79;
border-color: sandstone.79;
color: white;
& > .vui-icon {
color: sandstone.50;
}
& > .vui-icon > path {
fill: sandstone.50;
}
}
`;
/**
* Displays an input element wrapped in a div to allow extra content, like counter, side icons or buttons.
* Forwards many relevant props to the inner input. Handles different states, like loading or error.
* Exposes some props to the children via context.
*/
const Input = vui((props, ref) => {
const { allowClear, ariaLabel, autoComplete, autoCompleteMaxHeight, autoCompleteOptions, autoFocus, children, className, defaultValue, disabled, displayValueOnly, errorText, helpText, startIcon, endIcon, iconLeft, iconRight, id: idProp, input, inputProps, inputRef, itemLeft, itemRight, label, labelMarkOptional, labelTooltipText, max, maxLength, min, minLength, name, onBlur, onChange: onChangeProp, onFocus, pattern, placeholder, readOnly, required, showCount, size = "lg", state = "", stateMapping, step, type = "text", value, variant, ...rest } = props;
const resolvedStartIcon = startIcon ?? iconLeft;
const resolvedEndIcon = endIcon ?? iconRight;
const generatedId = useId();
const [count, setCount] = useState(() => getInitialCount(props));
const [valueInternal, setValueInternal] = useState(defaultValue || "");
const states = {
...inputStateMapping,
...stateMapping
};
const id = idProp || generatedId;
const styles = useStyleConfig("Input", props);
const context = useMemo(() => filterUndefined({
disabled,
size,
variant
}), [
disabled,
size,
variant
]);
function onChange(e) {
const inputValue = e.target.value;
const value = maxLength ? inputValue.slice(0, maxLength) : inputValue;
setValueInternal(value);
setCount(value?.length);
onChangeProp?.(e);
}
function onAutoCompleteSelect(value) {
onChange({
target: { value },
type: "autoCompleteSelect"
});
}
function onClear() {
const value = "";
const e = {
target: { value },
type: "onClear"
};
setValueInternal(value);
setCount(0);
onChange(e);
}
const aliasedProps = filterUndefined({
"aria-disabled": disabled,
bg: readOnly ? "sandstone.97" : void 0,
borderColor: readOnly ? "sandstone.55" : void 0
});
useEffect(() => {
if (value === void 0 && defaultValue !== void 0) return;
setValueInternal(value ?? "");
setCount(value?.toString()?.length ? `${value}`.length : 0);
}, [value]);
useEffect(() => {
if (iconLeft !== void 0) console.warn("[Input] `iconLeft` is deprecated. Use `startIcon` instead.");
if (iconRight !== void 0) console.warn("[Input] `iconRight` is deprecated. Use `endIcon` instead.");
}, [iconLeft, iconRight]);
const filterAutoCompleteOptions = (i) => valueInternal === i ? false : !valueInternal || i.toLowerCase().includes(`${valueInternal}`.toLowerCase());
return /* @__PURE__ */ jsx(InputProvider, {
value: context,
children: displayValueOnly ? /* @__PURE__ */ jsx(T, {
className: cs("vui-input-value", className),
size: displayValueOnlyTextSize[size],
children: value || defaultValue
}) : /* @__PURE__ */ jsx(autoCompletePopover_default, {
autoCompleteMaxHeight,
autoCompleteOptions,
filterAutoCompleteOptions,
onAutoCompleteSelect,
children: /* @__PURE__ */ jsxs(Box, {
className: "vui-inputContainer",
column: true,
ref,
...rest,
children: [
isString(label) ? /* @__PURE__ */ jsx(Label, {
"aria-disabled": disabled,
className: "vui-inputLabel",
htmlFor: id,
markAsOptional: labelMarkOptional,
mb: .5,
text: label,
tooltipText: labelTooltipText,
...styles.label
}) : label,
/* @__PURE__ */ jsxs(InputBase, {
className: cs("vui-input", className),
...styles.container,
...aliasedProps,
children: [
itemLeft,
isString(resolvedStartIcon) ? /* @__PURE__ */ jsx(InputIcon, {
ml: 1,
name: resolvedStartIcon
}) : resolvedStartIcon,
children ?? input ?? /* @__PURE__ */ jsx(InputInput, {
ref: inputRef,
autoFocus,
ariaLabel,
disabled,
id,
max,
maxLength,
min,
minLength,
name,
onBlur,
onChange,
onFocus,
pattern,
placeholder,
readOnly,
required,
step,
type,
autoComplete: autoCompleteOptions?.length ? "off" : autoComplete,
value: valueInternal,
...inputProps
}),
isString(resolvedEndIcon) ? /* @__PURE__ */ jsx(InputIcon, {
mr: 1,
name: resolvedEndIcon
}) : resolvedEndIcon,
itemRight,
state && /* @__PURE__ */ jsx(InputIcon, {
mr: 1,
...states[state]?.iconProps
}),
allowClear && !!valueInternal && /* @__PURE__ */ jsx(IconButton, {
icon: "uiTimes",
mr: .5,
onClick: onClear,
size: clearIconSize[size],
title: "Clear",
variant: "tertiary"
}),
showCount && /* @__PURE__ */ jsxs(T, {
className: "vui-inputCount",
color: maxLength && count > maxLength ? inputColors.error : inputColors.helpText,
position: "absolute",
right: 0,
size: "sm",
top: "calc(100% + 1px)",
children: [
count,
" ",
maxLength ? `/ ${maxLength}` : null
]
})
]
}),
!!helpText && /* @__PURE__ */ jsx(HelpText, {
size: helpTextSize[size],
children: helpText
}),
!!errorText && /* @__PURE__ */ jsx(HelpText, {
isError: true,
mr: showCount ? "60px" : void 0,
size: helpTextSize[size],
children: errorText
})
]
})
})
});
});
Input.Icon = InputIcon;
Input.Input = InputInput;
Input.HelpText = HelpText;
Input.displayName = "Input";
//#endregion
export { Input, Input as default, InputBase };
globalThis.__vuiVersion__ = "5.3.1"
//# sourceMappingURL=input.js.map