UNPKG

@carbon/react

Version:

React components for the Carbon Design System

320 lines (310 loc) 10.7 kB
/** * Copyright IBM Corp. 2016, 2023 * * This source code is licensed under the Apache-2.0 license found in the * LICENSE file in the root directory of this source tree. */ 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var iconsReact = require('@carbon/icons-react'); var warning = require('../../internal/warning.js'); var cx = require('classnames'); var PropTypes = require('prop-types'); var React = require('react'); var usePrefix = require('../../internal/usePrefix.js'); require('../FluidForm/FluidForm.js'); var FormContext = require('../FluidForm/FormContext.js'); var useId = require('../../internal/useId.js'); var Text = require('../Text/Text.js'); require('../Text/TextDirection.js'); var deprecate = require('../../prop-types/deprecate.js'); var index = require('../AILabel/index.js'); var utils = require('../../internal/utils.js'); var useNormalizedInputProps = require('../../internal/useNormalizedInputProps.js'); // eslint-disable-next-line @typescript-eslint/no-explicit-any -- https://github.com/carbon-design-system/carbon/issues/20452 let didWarnAboutDatePickerInputValue = false; const frFn = React.forwardRef; const DatePickerInput = frFn((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.usePrefix(); const { isFluid } = React.useContext(FormContext.FormContext); const datePickerInputInstanceId = useId.useId(); const normalizedProps = useNormalizedInputProps.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 (process.env.NODE_ENV !== 'production' && 'value' in rest && !didWarnAboutDatePickerInputValue) { process.env.NODE_ENV !== "production" ? warning.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.`) : void 0; didWarnAboutDatePickerInputValue = true; } const wrapperClasses = cx(`${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 = cx(`${prefix}--label`, { [`${prefix}--visually-hidden`]: hideLabel, [`${prefix}--label--disabled`]: normalizedProps.disabled, [`${prefix}--label--readonly`]: readOnly }); const helperTextClasses = cx(`${prefix}--form__helper-text`, { [`${prefix}--form__helper-text--disabled`]: normalizedProps.disabled }); const inputClasses = cx(`${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 = cx(`${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 ? undefined : `datepicker-input-helper-text-${datePickerInputInstanceId}`; // eslint-disable-next-line @typescript-eslint/no-explicit-any -- https://github.com/carbon-design-system/carbon/issues/20452 const inputProps = { ...rest, ...datePickerInputProps, className: inputClasses, disabled: normalizedProps.disabled, ref, ['aria-describedby']: helperText ? datePickerInputHelperId : undefined }; if (normalizedProps.invalid) { inputProps['data-invalid'] = true; } const input = /*#__PURE__*/React.createElement("input", inputProps); // AILabel always size `mini` const candidate = slug ?? decorator; const candidateIsAILabel = utils.isComponentElement(candidate, index.AILabel); const normalizedDecorator = candidateIsAILabel ? /*#__PURE__*/React.cloneElement(candidate, { size: 'mini' }) : candidate; return /*#__PURE__*/React.createElement("div", { className: containerClasses }, labelText && /*#__PURE__*/React.createElement(Text.Text, { as: "label", htmlFor: id, className: labelClasses }, labelText), /*#__PURE__*/React.createElement("div", { className: wrapperClasses }, /*#__PURE__*/React.createElement("span", null, input, slug ? normalizedDecorator : decorator ? /*#__PURE__*/React.createElement("div", { className: `${prefix}--date-picker-input-inner-wrapper--decorator` }, normalizedDecorator) : '', isFluid && /*#__PURE__*/React.createElement(DatePickerIcon, { datePickerType: datePickerType }), /*#__PURE__*/React.createElement(DatePickerIcon, { datePickerType: datePickerType, invalid: normalizedProps.invalid, warn: normalizedProps.warn, disabled: normalizedProps.disabled, readOnly: readOnly }))), normalizedProps.validation, helperText && !normalizedProps.invalid && !normalizedProps.warn && /*#__PURE__*/React.createElement(Text.Text, { as: "div", id: datePickerInputHelperId, className: helperTextClasses }, helperText)); }); DatePickerInput.propTypes = { /** * The type of the date picker: * * * `simple` - Without calendar dropdown. * * `single` - With calendar dropdown and single date. * * `range` - With calendar dropdown and a date range. */ datePickerType: PropTypes.oneOf(['simple', 'single', 'range']), /** * **Experimental**: Provide a decorator component to be rendered inside the `RadioButton` component */ decorator: PropTypes.node, /** * Specify whether or not the input should be disabled */ disabled: PropTypes.bool, /** * Provide text that is used alongside the control label for additional help */ helperText: PropTypes.node, /** * Specify if the label should be hidden */ hideLabel: PropTypes.bool, /** * Specify an id that uniquely identifies the `<input>` */ id: PropTypes.string.isRequired, /** * Specify whether or not the input should be invalid */ invalid: PropTypes.bool, /** * Specify the text to be rendered when the input is invalid */ invalidText: PropTypes.node, /** * Provide the text that will be read by a screen reader when visiting this * control */ labelText: PropTypes.node.isRequired, /** * Specify an `onChange` handler that is called whenever a change in the * input field has occurred */ onChange: PropTypes.func, /** * Provide a function to be called when the input field is clicked */ onClick: PropTypes.func, /** * Provide a regular expression that the input value must match */ // eslint-disable-next-line @typescript-eslint/no-explicit-any -- https://github.com/carbon-design-system/carbon/issues/20452 pattern: (props, propName, componentName) => { if (props[propName] === undefined) { return; } try { new RegExp(props[propName]); // eslint-disable-next-line @typescript-eslint/no-unused-vars -- https://github.com/carbon-design-system/carbon/issues/20452 } catch (e) { return new Error(`Invalid value of prop '${propName}' supplied to '${componentName}', it should be a valid regular expression`); } }, /** * Specify the placeholder text */ placeholder: PropTypes.string, /** * whether the DatePicker is to be readOnly */ readOnly: PropTypes.bool, /** * Specify the size of the Date Picker Input. Currently supports either `sm`, `md`, or `lg` as an option. */ size: PropTypes.oneOf(['sm', 'md', 'lg']), slug: deprecate.deprecate(PropTypes.node, 'The `slug` prop has been deprecated and will be removed in the next major version. Use the decorator prop instead.'), /** * Specify the type of the `<input>` */ type: PropTypes.string, /** * Specify whether the control is currently in warning state */ warn: PropTypes.bool, /** * Provide the text that is displayed when the control is in warning state */ warnText: PropTypes.node }; function DatePickerIcon({ datePickerType, invalid, warn, disabled, readOnly }) { const prefix = usePrefix.usePrefix(); const { isFluid } = React.useContext(FormContext.FormContext); if (datePickerType === 'simple' && !invalid && !warn) { if (!isFluid) { return null; } } // Don't show invalid/warn icons when disabled or readonly if (disabled || readOnly) { return /*#__PURE__*/React.createElement(iconsReact.Calendar, { className: `${prefix}--date-picker__icon`, role: "img", "aria-hidden": "true" }); } if (invalid) { return /*#__PURE__*/React.createElement(iconsReact.WarningFilled, { className: `${prefix}--date-picker__icon ${prefix}--date-picker__icon--invalid` }); } if (!invalid && warn) { return /*#__PURE__*/React.createElement(iconsReact.WarningAltFilled, { className: `${prefix}--date-picker__icon ${prefix}--date-picker__icon--warn` }); } return /*#__PURE__*/React.createElement(iconsReact.Calendar, { className: `${prefix}--date-picker__icon`, role: "img", "aria-hidden": "true" }); } DatePickerIcon.propTypes = { /** * The type of the date picker: * * * `simple` - Without calendar dropdown. * * `single` - With calendar dropdown and single date. * * `range` - With calendar dropdown and a date range. */ datePickerType: PropTypes.oneOf(['simple', 'single', 'range']), /** * Specify whether or not the input should be invalid */ invalid: PropTypes.bool, /** * Specify whether the control is currently in warning state */ warn: PropTypes.bool, /** * Specify whether or not the input should be disabled */ disabled: PropTypes.bool, /** * Specify whether the input is readonly */ readOnly: PropTypes.bool }; exports.default = DatePickerInput;