@carbon/react
Version:
React components for the Carbon Design System
262 lines (254 loc) • 8.72 kB
JavaScript
/**
* 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 _rollupPluginBabelHelpers = require('../../_virtual/_rollupPluginBabelHelpers.js');
var cx = require('classnames');
var PropTypes = require('prop-types');
var React = require('react');
var usePrefix = require('../../internal/usePrefix.js');
var deprecate = require('../../prop-types/deprecate.js');
var iconsReact = require('@carbon/icons-react');
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
var cx__default = /*#__PURE__*/_interopDefaultLegacy(cx);
var PropTypes__default = /*#__PURE__*/_interopDefaultLegacy(PropTypes);
var React__default = /*#__PURE__*/_interopDefaultLegacy(React);
const frFn = React.forwardRef;
const TimePicker = frFn((props, ref) => {
const {
children,
className,
disabled = false,
hideLabel,
id,
invalidText = 'Invalid time format.',
invalid = false,
warningText = 'Warning message.',
warning = false,
labelText,
light = false,
maxLength = 5,
onChange = () => {},
onClick = () => {},
onBlur = () => {},
pattern = '(1[012]|[1-9]):[0-5][0-9](\\s)?',
placeholder = 'hh:mm',
readOnly,
size = 'md',
type = 'text',
value,
...rest
} = props;
const prefix = usePrefix.usePrefix();
const [isValue, setValue] = React__default["default"].useState(value);
const [prevValue, setPrevValue] = React__default["default"].useState(value);
if (value !== prevValue) {
setValue(value);
setPrevValue(value);
}
function handleOnClick(evt) {
if (!disabled) {
if (!readOnly) {
setValue(isValue);
}
onClick(evt);
}
}
function handleOnChange(evt) {
if (!disabled && !readOnly) {
setValue(isValue);
onChange(evt);
}
}
function handleOnBlur(evt) {
if (!disabled) {
if (!readOnly) {
setValue(isValue);
}
onBlur(evt);
}
}
const timePickerInputClasses = cx__default["default"](`${prefix}--time-picker__input-field`, `${prefix}--text-input`, [className], {
[`${prefix}--text-input--light`]: light,
[`${prefix}--time-picker__input-field-error`]: invalid || warning
});
const timePickerClasses = cx__default["default"]({
[`${prefix}--time-picker`]: true,
[`${prefix}--time-picker--light`]: light,
[`${prefix}--time-picker--invalid`]: invalid,
[`${prefix}--time-picker--warning`]: warning,
[`${prefix}--time-picker--readonly`]: readOnly,
[`${prefix}--time-picker--${size}`]: size,
...(className && {
[className]: true
})
});
const labelClasses = cx__default["default"](`${prefix}--label`, {
[`${prefix}--visually-hidden`]: hideLabel,
[`${prefix}--label--disabled`]: disabled
});
const label = labelText ? /*#__PURE__*/React__default["default"].createElement("label", {
htmlFor: id,
className: labelClasses
}, labelText) : null;
function getInternalPickerSelects() {
const readOnlyEventHandlers = {
onMouseDown: evt => {
// NOTE: does not prevent click
if (readOnly) {
evt.preventDefault();
// focus on the element as per readonly input behavior
evt.target.focus();
}
},
onKeyDown: evt => {
const selectAccessKeys = ['ArrowDown', 'ArrowUp', ' '];
// This prevents the select from opening for the above keys
if (readOnly && selectAccessKeys.includes(evt.key)) {
evt.preventDefault();
}
}
};
const mappedChildren = React__default["default"].Children.map(children, pickerSelect => {
const item = pickerSelect;
if (item) {
return /*#__PURE__*/React__default["default"].cloneElement(item, {
...item.props,
disabled: item.props.disabled ?? disabled,
readOnly: readOnly,
...readOnlyEventHandlers
});
}
});
return mappedChildren;
}
const readOnlyProps = {
readOnly: readOnly
};
return /*#__PURE__*/React__default["default"].createElement("div", {
className: cx__default["default"](`${prefix}--form-item`, className)
}, label, /*#__PURE__*/React__default["default"].createElement("div", {
className: timePickerClasses
}, /*#__PURE__*/React__default["default"].createElement("div", {
className: `${prefix}--time-picker__input`
}, /*#__PURE__*/React__default["default"].createElement("input", _rollupPluginBabelHelpers["extends"]({
className: timePickerInputClasses,
"data-invalid": invalid ? invalid : undefined,
disabled: disabled,
id: id,
maxLength: maxLength,
onClick: handleOnClick,
onChange: handleOnChange,
onBlur: handleOnBlur,
placeholder: placeholder,
pattern: pattern,
ref: ref,
type: type,
value: value
}, rest, readOnlyProps)), (invalid || warning) && /*#__PURE__*/React__default["default"].createElement("div", {
className: `${prefix}--time-picker__error__icon`
}, invalid ? /*#__PURE__*/React__default["default"].createElement(iconsReact.WarningFilled, {
className: `${prefix}--checkbox__invalid-icon`,
size: 16
}) : /*#__PURE__*/React__default["default"].createElement(iconsReact.WarningAltFilled, {
className: `${prefix}--text-input__invalid-icon--warning`,
size: 16
}))), getInternalPickerSelects()), (invalid || warning) && /*#__PURE__*/React__default["default"].createElement("div", {
className: `${prefix}--form-requirement`
}, invalid ? invalidText : warningText));
});
TimePicker.propTypes = {
/**
* Pass in the children that will be rendered next to the form control
*/
children: PropTypes__default["default"].node,
/**
* Specify an optional className to be applied to the container node
*/
className: PropTypes__default["default"].string,
/**
* Specify whether the `<input>` should be disabled
*/
disabled: PropTypes__default["default"].bool,
/**
* Specify whether you want the underlying label to be visually hidden
*/
hideLabel: PropTypes__default["default"].bool,
/**
* Specify a custom `id` for the `<input>`
*/
id: PropTypes__default["default"].string.isRequired,
/**
* Specify whether the control is currently invalid
*/
invalid: PropTypes__default["default"].bool,
/**
* Provide the text that is displayed when the control is in an invalid state
*/
invalidText: PropTypes__default["default"].node,
/**
* Provide the text that will be read by a screen reader when visiting this
* control
*/
labelText: PropTypes__default["default"].node,
/**
* The `light` prop for `TimePicker` has been deprecated. It will be removed in v12. Use the `Layer` component instead.
*/
light: deprecate["default"](PropTypes__default["default"].bool, 'The `light` prop for `TimePicker` is no longer needed and has been deprecated. It will be removed in the next major release. Use the `Layer` component instead.'),
/**
* Specify the maximum length of the time string in `<input>`
*/
maxLength: PropTypes__default["default"].number,
/**
* Optionally provide an `onBlur` handler that is called whenever the
* `<input>` loses focus
*/
onBlur: PropTypes__default["default"].func,
/**
* Optionally provide an `onChange` handler that is called whenever `<input>`
* is updated
*/
onChange: PropTypes__default["default"].func,
/**
* Optionally provide an `onClick` handler that is called whenever the
* `<input>` is clicked
*/
onClick: PropTypes__default["default"].func,
/**
* Specify the regular expression working as the pattern of the time string in `<input>`
*/
pattern: PropTypes__default["default"].string,
/**
* Specify the placeholder attribute for the `<input>`
*/
placeholder: PropTypes__default["default"].string,
/**
* Specify whether the TimePicker should be read-only
*/
readOnly: PropTypes__default["default"].bool,
/**
* Specify the size of the Time Picker.
*/
size: PropTypes__default["default"].oneOf(['sm', 'md', 'lg']),
/**
* Specify the type of the `<input>`
*/
type: PropTypes__default["default"].string,
/**
* Specify the value of the `<input>`
*/
value: PropTypes__default["default"].string,
/**
* Specify a warning message
*/
warning: PropTypes__default["default"].bool,
/**
* Provide the text that is displayed when the control is in an warning state
*/
warningText: PropTypes__default["default"].node
};
exports["default"] = TimePicker;