UNPKG

@carbon/react

Version:

React components for the Carbon Design System

199 lines (197 loc) 7.4 kB
/** * Copyright IBM Corp. 2016, 2026 * * This source code is licensed under the Apache-2.0 license found in the * LICENSE file in the root directory of this source tree. */ import { usePrefix } from "../../internal/usePrefix.js"; import { Text } from "../Text/Text.js"; import { useId } from "../../internal/useId.js"; import { warning } from "../../internal/warning.js"; import { deprecate } from "../../prop-types/deprecate.js"; import { isComponentElement } from "../../internal/utils.js"; import { useNormalizedInputProps } from "../../internal/useNormalizedInputProps.js"; import { AILabel } from "../AILabel/index.js"; import { FormContext } from "../FluidForm/FormContext.js"; import classNames from "classnames"; import { cloneElement, forwardRef, useContext } from "react"; import PropTypes from "prop-types"; import { jsx, jsxs } from "react/jsx-runtime"; import { Calendar, WarningAltFilled, WarningFilled } from "@carbon/icons-react"; //#region src/components/DatePickerInput/DatePickerInput.tsx /** * Copyright IBM Corp. 2016, 2026 * * This source code is licensed under the Apache-2.0 license found in the * LICENSE file in the root directory of this source tree. */ let didWarnAboutDatePickerInputValue = false; const DatePickerInput = forwardRef((props, ref) => { const { datePickerType, decorator, disabled = false, helperText, hideLabel, id, invalid = false, invalidText, labelText, onClick = () => {}, onChange = () => {}, pattern = "\\d{1,2}\\/\\d{1,2}\\/\\d{4}", placeholder, size = "md", slug, type = "text", warn = false, warnText, readOnly, ...rest } = props; const prefix = usePrefix(); const { isFluid } = useContext(FormContext); const datePickerInputInstanceId = useId(); const normalizedProps = useNormalizedInputProps({ id, readOnly, disabled, invalid, invalidText, warn, warnText }); const datePickerInputProps = { id, onChange: (event) => { if (!disabled) onChange(event); }, onClick: (event) => { if (!disabled) onClick(event); }, pattern, placeholder, type }; if ("value" in rest && !didWarnAboutDatePickerInputValue) { warning(false, "The 'value' prop is not supported on the DatePickerInput component. For DatePicker components with 'datePickerType=\"range\"', please pass the 'value' prop (as an array of dates) to the parent DatePicker component instead."); didWarnAboutDatePickerInputValue = true; } const wrapperClasses = classNames(`${prefix}--date-picker-input__wrapper`, { [`${prefix}--date-picker-input__wrapper--invalid`]: normalizedProps.invalid, [`${prefix}--date-picker-input__wrapper--warn`]: normalizedProps.warn, [`${prefix}--date-picker-input__wrapper--slug`]: slug, [`${prefix}--date-picker-input__wrapper--decorator`]: decorator }); const labelClasses = classNames(`${prefix}--label`, { [`${prefix}--visually-hidden`]: hideLabel, [`${prefix}--label--disabled`]: normalizedProps.disabled, [`${prefix}--label--readonly`]: readOnly }); const helperTextClasses = classNames(`${prefix}--form__helper-text`, { [`${prefix}--form__helper-text--disabled`]: normalizedProps.disabled }); const inputClasses = classNames(`${prefix}--date-picker__input`, { [`${prefix}--date-picker__input--${size}`]: size, [`${prefix}--date-picker__input--invalid`]: normalizedProps.invalid, [`${prefix}--date-picker__input--warn`]: normalizedProps.warn }); const containerClasses = classNames(`${prefix}--date-picker-container`, { [`${prefix}--date-picker--nolabel`]: !labelText, [`${prefix}--date-picker--fluid--invalid`]: isFluid && normalizedProps.invalid, [`${prefix}--date-picker--fluid--warn`]: isFluid && normalizedProps.warn }); const datePickerInputHelperId = !helperText ? void 0 : `datepicker-input-helper-text-${datePickerInputInstanceId}`; let ariaDescribedBy; if (normalizedProps.invalid) ariaDescribedBy = normalizedProps.invalidId; else if (normalizedProps.warn) ariaDescribedBy = normalizedProps.warnId; else ariaDescribedBy = helperText ? datePickerInputHelperId : void 0; const inputProps = { ...rest, ...datePickerInputProps, className: inputClasses, disabled: normalizedProps.disabled, ref, ["aria-describedby"]: ariaDescribedBy }; if (normalizedProps.invalid) { inputProps["data-invalid"] = true; inputProps["aria-invalid"] = true; } const input = /* @__PURE__ */ jsx("input", { ...inputProps }); const candidate = slug ?? decorator; const normalizedDecorator = isComponentElement(candidate, AILabel) ? cloneElement(candidate, { size: "mini" }) : candidate; return /* @__PURE__ */ jsxs("div", { className: containerClasses, children: [ labelText && /* @__PURE__ */ jsx(Text, { as: "label", htmlFor: id, className: labelClasses, children: labelText }), /* @__PURE__ */ jsx("div", { className: wrapperClasses, children: /* @__PURE__ */ jsxs("span", { children: [ input, slug ? normalizedDecorator : decorator ? /* @__PURE__ */ jsx("div", { className: `${prefix}--date-picker-input-inner-wrapper--decorator`, children: normalizedDecorator }) : "", /* @__PURE__ */ jsx(DatePickerIcon, { datePickerType, invalid: normalizedProps.invalid, warn: normalizedProps.warn, disabled: normalizedProps.disabled, readOnly }) ] }) }), normalizedProps.validation, helperText && !normalizedProps.invalid && !normalizedProps.warn && /* @__PURE__ */ jsx(Text, { as: "div", id: datePickerInputHelperId, className: helperTextClasses, children: helperText }) ] }); }); DatePickerInput.propTypes = { datePickerType: PropTypes.oneOf([ "simple", "single", "range" ]), decorator: PropTypes.node, disabled: PropTypes.bool, helperText: PropTypes.node, hideLabel: PropTypes.bool, id: PropTypes.string.isRequired, invalid: PropTypes.bool, invalidText: PropTypes.node, labelText: PropTypes.node.isRequired, onChange: PropTypes.func, onClick: PropTypes.func, pattern: PropTypes.string, placeholder: PropTypes.string, readOnly: PropTypes.bool, size: PropTypes.oneOf([ "sm", "md", "lg" ]), slug: deprecate(PropTypes.node, "The `slug` prop has been deprecated and will be removed in the next major version. Use the decorator prop instead."), type: PropTypes.string, warn: PropTypes.bool, warnText: PropTypes.node }; function DatePickerIcon({ datePickerType, invalid, warn, disabled, readOnly }) { const prefix = usePrefix(); const { isFluid } = useContext(FormContext); if (datePickerType === "simple" && !invalid && !warn) { if (!isFluid) return null; } if (disabled || readOnly) return /* @__PURE__ */ jsx(Calendar, { className: `${prefix}--date-picker__icon`, role: "img", "aria-hidden": "true" }); if (invalid) return /* @__PURE__ */ jsx(WarningFilled, { className: `${prefix}--date-picker__icon ${prefix}--date-picker__icon--invalid` }); if (!invalid && warn) return /* @__PURE__ */ jsx(WarningAltFilled, { className: `${prefix}--date-picker__icon ${prefix}--date-picker__icon--warn` }); return /* @__PURE__ */ jsx(Calendar, { className: `${prefix}--date-picker__icon`, role: "img", "aria-hidden": "true" }); } DatePickerIcon.propTypes = { datePickerType: PropTypes.oneOf([ "simple", "single", "range" ]), invalid: PropTypes.bool, warn: PropTypes.bool, disabled: PropTypes.bool, readOnly: PropTypes.bool }; //#endregion export { DatePickerInput as default };