@carbon/react
Version:
React components for the Carbon Design System
199 lines (197 loc) • 7.4 kB
JavaScript
/**
* 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 };