@awsui/components-react
Version:
On July 19th, 2022, we launched [Cloudscape Design System](https://cloudscape.design). Cloudscape is an evolution of AWS-UI. It consists of user interface guidelines, front-end components, design resources, and development tools for building intuitive, en
100 lines • 7.57 kB
JavaScript
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
'use client';
import React, { useCallback, useRef, useState } from 'react';
import clsx from 'clsx';
import { useMergeRefs, useUniqueId } from '@awsui/component-toolkit/internal';
import { InternalButton } from '../button/internal';
import InternalCalendar from '../calendar/internal';
import { useFormFieldContext } from '../contexts/form-field.js';
import InternalDateInput from '../date-input/internal';
import { useLocale } from '../i18n/context.js';
import { getBaseProps } from '../internal/base-component';
import Dropdown from '../internal/components/dropdown';
import FocusLock from '../internal/components/focus-lock';
import { fireNonCancelableEvent } from '../internal/events';
import checkControlled from '../internal/hooks/check-controlled';
import useForwardFocus from '../internal/hooks/forward-focus';
import useBaseComponent from '../internal/hooks/use-base-component';
import { useFocusTracker } from '../internal/hooks/use-focus-tracker.js';
import { KeyCode } from '../internal/keycode';
import { applyDisplayName } from '../internal/utils/apply-display-name.js';
import { parseDate } from '../internal/utils/date-time';
import { normalizeLocale } from '../internal/utils/locale';
import InternalLiveRegion from '../live-region/internal';
import { getBaseDateLabel, getSelectedDateLabel, isValidFullDate } from './utils';
import styles from './styles.css.js';
const DatePicker = React.forwardRef(({ locale, startOfWeek, isDateEnabled, dateDisabledReason, nextMonthAriaLabel, previousMonthAriaLabel, todayAriaLabel, i18nStrings, placeholder = '', value = '', readOnly = false, disabled = false, onBlur, autoFocus = false, onChange, onFocus, name, ariaLabel, ariaRequired, controlId, invalid, warning, openCalendarAriaLabel, expandToViewport, granularity = 'day', format = 'slashed', inputFormat = 'slashed', ...restProps }, ref) => {
var _a, _b, _c;
const { __internalRootRef } = useBaseComponent('DatePicker', {
props: { autoFocus, expandToViewport, granularity, readOnly },
metadata: { hasDisabledReasons: Boolean(dateDisabledReason) },
});
checkControlled('DatePicker', 'value', value, 'onChange', onChange);
const contextLocale = useLocale();
const normalizedLocale = normalizeLocale('DatePicker', locale || contextLocale);
const baseProps = getBaseProps(restProps);
const [isDropDownOpen, setIsDropDownOpen] = useState(false);
const { ariaLabelledby, ariaDescribedby } = useFormFieldContext(restProps);
const internalInputRef = useRef(null);
const buttonRef = useRef(null);
useForwardFocus(ref, internalInputRef);
const rootRef = useRef(null);
const dropdownId = useUniqueId('calender');
const calendarDescriptionId = useUniqueId('calendar-description-');
const mergedRef = useMergeRefs(rootRef, __internalRootRef);
useFocusTracker({ rootRef, onBlur, onFocus });
const onDropdownCloseHandler = useCallback(() => setIsDropDownOpen(false), [setIsDropDownOpen]);
const onButtonClickHandler = () => {
if (!isDropDownOpen) {
setIsDropDownOpen(true);
}
};
const onWrapperKeyDownHandler = (event) => {
var _a;
if (event.keyCode === KeyCode.escape && isDropDownOpen) {
event.stopPropagation();
(_a = buttonRef.current) === null || _a === void 0 ? void 0 : _a.focus();
setIsDropDownOpen(false);
}
};
const onInputChangeHandler = event => {
fireNonCancelableEvent(onChange, { value: event.detail.value });
};
const onInputBlurHandler = () => {
if (!isDropDownOpen) {
setIsDropDownOpen(false);
}
};
// Set displayed date to value if defined or to current date otherwise.
const parsedValue = value && value.length >= 4 ? parseDate(value) : null;
const baseDate = parsedValue || new Date();
const hasFullValue = isValidFullDate({ date: value, granularity });
const buttonAriaLabel = openCalendarAriaLabel &&
openCalendarAriaLabel(hasFullValue && parsedValue
? getSelectedDateLabel({ date: parsedValue, granularity, locale: normalizedLocale })
: null);
const trigger = (React.createElement("div", { className: styles['date-picker-trigger'] },
React.createElement("div", { className: styles['date-picker-input'] },
React.createElement(InternalDateInput, { name: name, invalid: invalid, warning: warning, controlId: controlId, ariaLabelledby: ariaLabelledby, ariaDescribedby: ariaDescribedby, ariaLabel: ariaLabel, ariaRequired: ariaRequired, value: value, disabled: disabled, readOnly: readOnly, onChange: onInputChangeHandler, onBlur: onInputBlurHandler, placeholder: placeholder, ref: internalInputRef, autoFocus: autoFocus, onFocus: onDropdownCloseHandler, granularity: granularity, locale: locale, format: format, inputFormat: inputFormat })),
React.createElement("div", null,
React.createElement(InternalButton, { iconName: "calendar", className: styles['open-calendar-button'], onClick: onButtonClickHandler, ref: buttonRef, ariaLabel: buttonAriaLabel, disabled: disabled || readOnly, formAction: "none" }))));
baseProps.className = clsx(baseProps.className, styles.root, styles['date-picker-container']);
return (React.createElement("div", { ...baseProps, ref: mergedRef, onKeyDown: !disabled && !readOnly ? onWrapperKeyDownHandler : undefined }, disabled || readOnly ? (trigger) : (React.createElement(Dropdown, { stretchWidth: true, stretchHeight: true, open: isDropDownOpen, onDropdownClose: onDropdownCloseHandler, trigger: trigger, expandToViewport: expandToViewport, scrollable: false, dropdownId: dropdownId }, isDropDownOpen && (React.createElement(FocusLock, { className: styles['focus-lock'], autoFocus: true },
React.createElement("div", { tabIndex: 0, className: styles.calendar, role: "dialog" },
React.createElement(InternalCalendar, { value: value, onChange: e => {
var _a;
fireNonCancelableEvent(onChange, e.detail);
(_a = buttonRef === null || buttonRef === void 0 ? void 0 : buttonRef.current) === null || _a === void 0 ? void 0 : _a.focus();
setIsDropDownOpen(false);
}, locale: normalizedLocale, startOfWeek: startOfWeek, ariaDescribedby: calendarDescriptionId, ariaLabel: ariaLabel, ariaLabelledby: ariaLabelledby, granularity: granularity, isDateEnabled: isDateEnabled, dateDisabledReason: dateDisabledReason, i18nStrings: {
...i18nStrings,
todayAriaLabel: (_a = i18nStrings === null || i18nStrings === void 0 ? void 0 : i18nStrings.todayAriaLabel) !== null && _a !== void 0 ? _a : todayAriaLabel,
nextMonthAriaLabel: (_b = i18nStrings === null || i18nStrings === void 0 ? void 0 : i18nStrings.nextMonthAriaLabel) !== null && _b !== void 0 ? _b : nextMonthAriaLabel,
previousMonthAriaLabel: (_c = i18nStrings === null || i18nStrings === void 0 ? void 0 : i18nStrings.previousMonthAriaLabel) !== null && _c !== void 0 ? _c : previousMonthAriaLabel,
} }),
React.createElement(InternalLiveRegion, { id: calendarDescriptionId, hidden: true, tagName: "span" }, getBaseDateLabel({ date: baseDate, granularity, locale: normalizedLocale })))))))));
});
applyDisplayName(DatePicker, 'DatePicker');
export default DatePicker;
//# sourceMappingURL=index.js.map