UNPKG

@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
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