@esri/calcite-components
Version:
Web Components for Esri's Calcite Design System.
669 lines (668 loc) • 34.6 kB
JavaScript
/*! All material copyright ESRI, All Rights Reserved, unless otherwise specified.
See https://github.com/Esri/calcite-design-system/blob/dev/LICENSE.md for details.
v3.2.1 */
import { c as customElement } from "../../chunks/runtime.js";
import { ref } from "lit-html/directives/ref.js";
import { isServer, nothing, html } from "lit";
import { LitElement, createEvent, stringOrBoolean, safeClassMap } from "@arcgis/lumina";
import { u as useFocusTrap } from "../../chunks/useFocusTrap.js";
import { d as datePartsFromISO, a as dateFromISO, b as dateFromRange, c as dateToISO, e as datePartsFromLocalizedString, f as dateFromLocalizedString, i as inRange } from "../../chunks/date.js";
import { h as focusFirstTabbable } from "../../chunks/dom.js";
import { b as defaultMenuPlacement, r as reposition, c as connectFloatingUI, a as disconnectFloatingUI, f as filterValidFlipPlacements, h as hideFloatingUI, F as FloatingCSS } from "../../chunks/floating-ui.js";
import { c as connectForm, d as disconnectForm, s as submitForm, H as HiddenFormInputSlot } from "../../chunks/form.js";
import { u as updateHostInteraction, I as InteractiveContainer } from "../../chunks/interactive.js";
import { n as numberKeys } from "../../chunks/key.js";
import { c as connectLabel, d as disconnectLabel } from "../../chunks/label.js";
import { c as componentFocusable, g as getIconScale } from "../../chunks/component.js";
import { n as numberStringFormatter, a as getSupportedNumberingSystem, d as getDateFormatSupportedLocale, b as getSupportedLocale } from "../../chunks/locale.js";
import { o as onToggleOpenCloseComponent } from "../../chunks/openCloseComponent.js";
import { g as getValueAsDateRange, a as getLocaleData } from "../../chunks/utils2.js";
import { g as guid } from "../../chunks/guid.js";
import { V as Validation } from "../../chunks/Validation.js";
import { s as syncHiddenFormInput } from "../../chunks/input.js";
import { u as useT9n } from "../../chunks/useT9n.js";
import { css } from "@lit/reactive-element/css-tag.js";
const styles = css`:host{--calcite-icon-size: 1rem;--calcite-spacing-eighth: .125rem;--calcite-spacing-quarter: .25rem;--calcite-spacing-half: .5rem;--calcite-spacing-three-quarters: .75rem;--calcite-spacing: 1rem;--calcite-spacing-plus-quarter: 1.25rem;--calcite-spacing-plus-half: 1.5rem;--calcite-spacing-double: 2rem;--calcite-menu-min-width: 10rem;--calcite-header-min-height: 3rem;--calcite-footer-min-height: 3rem}:host([disabled]){cursor:default;-webkit-user-select:none;user-select:none;opacity:var(--calcite-opacity-disabled)}:host([disabled]) *,:host([disabled]) ::slotted(*){pointer-events:none}:host{position:relative;display:inline-block;width:100%;overflow:visible;vertical-align:top;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}:host .menu-container .calcite-floating-ui-anim{position:relative;transition:var(--calcite-floating-ui-transition);transition-property:inset,left,opacity;opacity:0;box-shadow:0 0 16px #00000029;z-index:var(--calcite-z-index);border-radius:.25rem}:host .menu-container[data-placement^=bottom] .calcite-floating-ui-anim{inset-block-start:-5px}:host .menu-container[data-placement^=top] .calcite-floating-ui-anim{inset-block-start:5px}:host .menu-container[data-placement^=left] .calcite-floating-ui-anim{left:5px}:host .menu-container[data-placement^=right] .calcite-floating-ui-anim{left:-5px}:host .menu-container[data-placement] .calcite-floating-ui-anim--active{opacity:1;inset-block-start:0;left:0}:host([scale=s]){--calcite-toggle-spacing: .5rem;--calcite-internal-input-text-input-padding-inline-end: calc(var(--calcite-toggle-spacing) + 1rem)}:host([scale=m]){--calcite-toggle-spacing: .75rem;--calcite-internal-input-text-input-padding-inline-end: calc(var(--calcite-toggle-spacing) + 1.5rem)}:host([scale=l]){--calcite-toggle-spacing: 1rem;--calcite-internal-input-text-input-padding-inline-end: calc(var(--calcite-toggle-spacing) + 2rem)}:host([disabled]) ::slotted([calcite-hydrated][disabled]),:host([disabled]) [calcite-hydrated][disabled]{opacity:1}.interaction-container{display:contents}.calendar-wrapper{--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow);transform:translateZ(0)}.input-wrapper{position:relative}.input-wrapper .chevron-icon{color:var(--calcite-color-text-3)}.input-wrapper:focus-within .chevron-icon,.input-wrapper:active .chevron-icon,.input-wrapper:hover .chevron-icon{color:var(--calcite-color-text-1)}.input-wrapper:focus-within~.input-wrapper .chevron-icon,.input-wrapper:active~.input-wrapper .chevron-icon,.input-wrapper:hover~.input-wrapper .chevron-icon{color:var(--calcite-color-text-1)}.toggle-icon{position:absolute;display:flex;cursor:pointer;align-items:center;inset-inline-end:0;inset-block:0;padding-inline:var(--calcite-toggle-spacing)}:host([range]) .container{display:flex}:host([range]) .input-container{display:flex;flex:1 1 auto}:host([range]) .input-wrapper{flex:1 1 auto}.divider-container{display:flex;align-items:stretch;border-width:1px;border-left-width:0px;border-right-width:0px;border-style:solid;border-color:var(--calcite-color-border-input);background-color:var(--calcite-color-foreground-1)}:host([layout=horizontal]) .divider-container{width:1px}.divider{display:inline-block;width:1px;margin-block:var(--calcite-spacing-xxs);background-color:var(--calcite-color-border-2)}:host([layout=vertical]) .divider-container{height:1px;width:100%;border-top-width:0px;border-bottom-width:0px;border-left-width:1px;border-right-width:0px;padding-inline:var(--calcite-spacing-md)}:host([layout=vertical]) .divider-container .divider{margin-top:0;margin-bottom:0;height:1px;width:100%}:host([range][layout=vertical]) .input-wrapper{width:100%}:host([range][layout=vertical]) .input-container{flex-direction:column;align-items:flex-start}.menu-container{--calcite-floating-ui-z-index: var(--calcite-z-index-dropdown);inline-size:max-content;display:none;max-inline-size:100vw;max-block-size:100vh;inset-block-start:0;left:0;z-index:var(--calcite-floating-ui-z-index)}.menu-container .calcite-floating-ui-anim{position:relative;transition:var(--calcite-floating-ui-transition);transition-property:inset,left,opacity;opacity:0;box-shadow:0 0 16px #00000029;z-index:var(--calcite-z-index);border-radius:.25rem}.menu-container[data-placement^=bottom] .calcite-floating-ui-anim{inset-block-start:-5px}.menu-container[data-placement^=top] .calcite-floating-ui-anim{inset-block-start:5px}.menu-container[data-placement^=left] .calcite-floating-ui-anim{left:5px}.menu-container[data-placement^=right] .calcite-floating-ui-anim{left:-5px}.menu-container[data-placement] .calcite-floating-ui-anim--active{opacity:1;inset-block-start:0;left:0}.input .calcite-input__wrapper{margin-top:0}.vertical-chevron-container{display:flex;align-items:center;border-width:1px;border-left-width:0px;border-style:solid;border-color:var(--calcite-color-border-input);padding-inline:var(--calcite-spacing-md);background-color:var(--calcite-color-foreground-1)}.vertical-chevron-container calcite-icon{color:var(--calcite-color-text-3)}.vertical-chevron-container calcite-icon:hover{color:var(--calcite-color-text-1)}:host([range][layout=vertical][scale=s]) .vertical-chevron-container,:host([range][layout=vertical][scale=s]) .divider-container{padding-inline:var(--calcite-spacing-sm)}:host([range][layout=vertical][scale=l]) .vertical-chevron-container,:host([range][layout=vertical][scale=l]) .divider-container{padding-inline:var(--calcite-spacing-lg)}.container:focus-within .vertical-chevron-container calcite-icon,.container:active .vertical-chevron-container calcite-icon,.container:hover .vertical-chevron-container calcite-icon{color:var(--calcite-color-text-1)}.validation-container{display:flex;flex-direction:column;align-items:flex-start;align-self:stretch}:host([scale=m]) .validation-container,:host([scale=l]) .validation-container{padding-block-start:.5rem}:host([scale=s]) .validation-container{padding-block-start:.25rem}::slotted(input[slot=hidden-form-input]){margin:0!important;opacity:0!important;outline:none!important;padding:0!important;position:absolute!important;inset:0!important;transform:none!important;-webkit-appearance:none!important;z-index:-1!important}.assistive-text{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border-width:0}:host([hidden]){display:none}[hidden]{display:none}`;
const CSS = {
assistiveText: "assistive-text",
calendarWrapper: "calendar-wrapper",
container: "container",
dividerContainer: "divider-container",
divider: "divider",
inputContainer: "input-container",
inputNoBottomBorder: "input--no-bottom-border",
inputNoRightBorder: "input--no-right-border",
inputNoTopBorder: "input--no-top-border",
inputNoLeftBorder: "input--no-left-border",
inputWrapper: "input-wrapper",
input: "input",
menu: "menu-container",
toggleIcon: "toggle-icon",
verticalChevronContainer: "vertical-chevron-container",
chevronIcon: "chevron-icon"
};
const IDS = {
validationMessage: "inputDatePickerValidationMessage"
};
function isTwoDigitYear(value) {
if (!value) {
return false;
}
const { year } = datePartsFromISO(value);
return Number(year) < 100;
}
function normalizeToCurrentCentury(twoDigitYear) {
const currentYear = (/* @__PURE__ */ new Date()).getFullYear();
const normalizedYear = Math.floor(currentYear / 100) * 100 + twoDigitYear;
return normalizedYear;
}
class InputDatePicker extends LitElement {
constructor() {
super();
this.commonDateSeparators = [".", "-", "/"];
this.dialogId = `date-picker-dialog--${guid()}`;
this.focusOnOpen = false;
this.focusTrap = useFocusTrap({
triggerProp: "open",
focusTrapOptions: {
onActivate: () => {
if (this.focusOnOpen) {
this.datePickerEl?.setFocus();
this.focusOnOpen = false;
}
},
allowOutsideClick: true,
// Allow outside click and let the popover manager take care of closing the popover.
clickOutsideDeactivates: false,
initialFocus: false,
setReturnFocus: false,
onDeactivate: () => {
this.open = false;
}
}
})(this);
this.transitionProp = "opacity";
this.placeholderTextId = `calcite-input-date-picker-placeholder-${guid()}`;
this.rangeStartValueChangedByUser = false;
this.userChangedValue = false;
this._value = "";
this.valueAsDateChangedExternally = false;
this.messages = useT9n({ blocking: true });
this.focusedInput = "start";
this.disabled = false;
this.focusTrapDisabled = false;
this.layout = "horizontal";
this.monthStyle = "wide";
this.open = false;
this.overlayPositioning = "absolute";
this.placement = defaultMenuPlacement;
this.proximitySelectionDisabled = false;
this.range = false;
this.readOnly = false;
this.required = false;
this.scale = "m";
this.status = "idle";
this.validity = {
valid: false,
badInput: false,
customError: false,
patternMismatch: false,
rangeOverflow: false,
rangeUnderflow: false,
stepMismatch: false,
tooLong: false,
tooShort: false,
typeMismatch: false,
valueMissing: false
};
this.calciteInputDatePickerBeforeClose = createEvent({ cancelable: false });
this.calciteInputDatePickerBeforeOpen = createEvent({ cancelable: false });
this.calciteInputDatePickerChange = createEvent({ cancelable: false });
this.calciteInputDatePickerClose = createEvent({ cancelable: false });
this.calciteInputDatePickerOpen = createEvent({ cancelable: false });
this.listen("blur", this.blurHandler);
this.listen("keydown", this.keyDownHandler);
this.handleDateTimeFormatChange();
}
static {
this.properties = { datePickerActiveDate: [16, {}, { state: true }], focusedInput: [16, {}, { state: true }], localeData: [16, {}, { state: true }], disabled: [7, {}, { reflect: true, type: Boolean }], flipPlacements: [0, {}, { attribute: false }], focusTrapDisabled: [7, {}, { reflect: true, type: Boolean }], form: [3, {}, { reflect: true }], headingLevel: [11, {}, { type: Number, reflect: true }], label: 1, layout: [3, {}, { reflect: true }], max: [3, {}, { reflect: true }], maxAsDate: [0, {}, { attribute: false }], messageOverrides: [0, {}, { attribute: false }], min: [3, {}, { reflect: true }], minAsDate: [0, {}, { attribute: false }], monthStyle: 1, name: [3, {}, { reflect: true }], numberingSystem: [3, {}, { reflect: true }], open: [7, {}, { reflect: true, type: Boolean }], overlayPositioning: [3, {}, { reflect: true }], placement: [3, {}, { reflect: true }], proximitySelectionDisabled: [5, {}, { type: Boolean }], range: [7, {}, { reflect: true, type: Boolean }], readOnly: [7, {}, { reflect: true, type: Boolean }], required: [7, {}, { reflect: true, type: Boolean }], scale: [3, {}, { reflect: true }], status: [3, {}, { reflect: true }], validationIcon: [3, { converter: stringOrBoolean }, { reflect: true }], validationMessage: 1, validity: [0, {}, { attribute: false }], value: 1, valueAsDate: [0, {}, { attribute: false }] };
}
static {
this.shadowRootOptions = { mode: "open", delegatesFocus: true };
}
static {
this.styles = styles;
}
get value() {
return this._value;
}
set value(value) {
const valueChanged = value !== this._value;
const invalidValueCleared = value === "" && (this.startInput?.value !== "" || this.endInput?.value !== "");
if (valueChanged || invalidValueCleared) {
this._value = value;
this.valueWatcher(value);
}
}
async reposition(delayed = false) {
const { floatingEl, referenceEl, placement, overlayPositioning, filteredFlipPlacements } = this;
return reposition(this, {
floatingEl,
referenceEl,
overlayPositioning,
placement,
flipPlacements: filteredFlipPlacements,
type: "menu"
}, delayed);
}
async setFocus() {
await componentFocusable(this);
focusFirstTabbable(this.el);
}
connectedCallback() {
super.connectedCallback();
const { open } = this;
if (open) {
this.openHandler();
}
if (this.min) {
this.minAsDate = dateFromISO(this.min);
}
if (this.max) {
this.maxAsDate = dateFromISO(this.max);
}
if (Array.isArray(this.value)) {
this.valueAsDate = getValueAsDateRange(this.value);
} else if (this.value) {
try {
const date = dateFromISO(this.value);
const dateInRange = dateFromRange(date, this.minAsDate, this.maxAsDate);
this.valueAsDate = dateInRange;
} catch {
this.warnAboutInvalidValue(this.value);
this.value = "";
}
} else if (this.valueAsDate) {
if (this.range && Array.isArray(this.valueAsDate)) {
this.value = [dateToISO(this.valueAsDate[0]), dateToISO(this.valueAsDate[1])];
} else if (!this.range && !Array.isArray(this.valueAsDate)) {
this.value = dateToISO(this.valueAsDate);
}
}
connectLabel(this);
connectForm(this);
this.setFilteredPlacements();
numberStringFormatter.numberFormatOptions = {
numberingSystem: this.numberingSystem,
locale: this.messages._lang,
useGrouping: false
};
connectFloatingUI(this);
}
async load() {
this.handleDateTimeFormatChange();
await this.loadLocaleData();
this.onMinChanged(this.min);
this.onMaxChanged(this.max);
}
willUpdate(changes) {
if (changes.has("disabled") && (this.hasUpdated || this.disabled !== false)) {
this.handleDisabledAndReadOnlyChange(this.disabled);
}
if (changes.has("readOnly") && (this.hasUpdated || this.readOnly !== false)) {
this.handleDisabledAndReadOnlyChange(this.readOnly);
}
if (changes.has("valueAsDate")) {
this.valueAsDateWatcher(this.valueAsDate);
}
if (changes.has("flipPlacements")) {
this.flipPlacementsHandler();
}
if (changes.has("min")) {
this.onMinChanged(this.min);
}
if (changes.has("max")) {
this.onMaxChanged(this.max);
}
if (changes.has("open") && (this.hasUpdated || this.open !== false)) {
this.openHandler();
}
if (changes.has("overlayPositioning") && (this.hasUpdated || this.overlayPositioning !== "absolute")) {
this.reposition(true);
}
if (changes.has("numberingSystem") || changes.has("messages")) {
this.handleDateTimeFormatChange();
}
if (changes.has("layout") && (this.hasUpdated || this.layout !== "horizontal")) {
this.setReferenceEl();
}
if (changes.has("messages")) {
this.loadLocaleData();
}
}
updated() {
updateHostInteraction(this);
}
loaded() {
this.localizeInputValues();
connectFloatingUI(this);
}
disconnectedCallback() {
super.disconnectedCallback();
disconnectLabel(this);
disconnectForm(this);
disconnectFloatingUI(this);
}
handleDisabledAndReadOnlyChange(value) {
if (!value) {
this.open = false;
}
}
valueWatcher(newValue) {
if (!this.userChangedValue) {
let newValueAsDate;
if (Array.isArray(newValue)) {
newValueAsDate = getValueAsDateRange(newValue);
} else if (newValue) {
newValueAsDate = dateFromISO(newValue);
} else {
newValueAsDate = void 0;
}
if (!this.valueAsDateChangedExternally && newValueAsDate !== this.valueAsDate) {
this.valueAsDate = newValueAsDate;
}
this.localizeInputValues();
}
this.userChangedValue = false;
}
valueAsDateWatcher(valueAsDate) {
const newValue = Array.isArray(valueAsDate) ? [dateToISO(valueAsDate[0]), dateToISO(valueAsDate[1])] : dateToISO(valueAsDate);
this.datePickerActiveDate = Array.isArray(valueAsDate) ? valueAsDate[0] : valueAsDate;
if (this.value !== newValue) {
this.valueAsDateChangedExternally = true;
this.value = newValue;
this.valueAsDateChangedExternally = false;
}
}
flipPlacementsHandler() {
this.setFilteredPlacements();
this.reposition(true);
}
onMinChanged(min) {
this.minAsDate = dateFromISO(min);
}
onMaxChanged(max) {
this.maxAsDate = dateFromISO(max);
}
openHandler() {
onToggleOpenCloseComponent(this);
if (this.disabled || this.readOnly) {
return;
}
this.reposition(true);
}
calciteInternalInputInputHandler(event) {
const target = event.target;
const value = target.value;
const parsedValue = this.parseNumerals(value);
const formattedValue = this.formatNumerals(parsedValue);
target.value = formattedValue;
const { year } = datePartsFromLocalizedString(value, this.localeData);
if (year && year.length < 4) {
return;
}
const date = dateFromLocalizedString(value, this.localeData);
if (inRange(date, this.min, this.max)) {
this.datePickerActiveDate = date;
}
}
calciteInternalInputBlurHandler() {
this.commitValue();
}
handleDateTimeFormatChange() {
const formattingOptions = {
// we explicitly set numberingSystem to prevent the browser-inferred value
// @see [Arabic numbering system support context](https://github.com/Esri/calcite-design-system/issues/3079#issuecomment-1168964195) for more info.
numberingSystem: getSupportedNumberingSystem(this.numberingSystem)
};
this.dateTimeFormat = new Intl.DateTimeFormat(getDateFormatSupportedLocale(getSupportedLocale(this.messages._lang)), formattingOptions);
}
setReferenceEl() {
const { focusedInput, layout, endWrapper, startWrapper } = this;
this.referenceEl = focusedInput === "end" || layout === "vertical" ? endWrapper || startWrapper : startWrapper || endWrapper;
requestAnimationFrame(() => connectFloatingUI(this));
}
onInputWrapperPointerDown() {
this.currentOpenInput = this.focusedInput;
}
onInputWrapperClick(event) {
const { range, endInput, startInput, currentOpenInput } = this;
const currentTarget = event.currentTarget;
const position = currentTarget.getAttribute("data-position");
const path = event.composedPath();
const wasToggleClicked = path.find((el) => el.classList?.contains(CSS.toggleIcon));
if (wasToggleClicked) {
const targetInput = position === "start" ? startInput : endInput;
targetInput.setFocus();
}
if (!range || !this.open || currentOpenInput === position) {
this.open = !this.open;
}
}
setFilteredPlacements() {
const { el, flipPlacements } = this;
this.filteredFlipPlacements = flipPlacements ? filterValidFlipPlacements(flipPlacements, el) : null;
}
setTransitionEl(el) {
if (!el) {
return;
}
this.transitionEl = el;
}
onLabelClick() {
this.setFocus();
}
onBeforeOpen() {
this.calciteInputDatePickerBeforeOpen.emit();
}
onOpen() {
this.focusTrap.activate();
this.calciteInputDatePickerOpen.emit();
}
onBeforeClose() {
this.calciteInputDatePickerBeforeClose.emit();
}
onClose() {
this.calciteInputDatePickerClose.emit();
hideFloatingUI(this);
this.focusTrap.deactivate();
this.focusOnOpen = false;
this.datePickerEl?.reset();
}
syncHiddenFormInput(input) {
syncHiddenFormInput("date", this, input);
}
setStartInput(el) {
this.startInput = el;
}
setEndInput(el) {
this.endInput = el;
}
blurHandler() {
this.open = false;
}
commitValue() {
const { focusedInput, value } = this;
const focusedInputName = `${focusedInput}Input`;
const focusedInputValue = this[focusedInputName].value;
const date = dateFromLocalizedString(focusedInputValue, this.localeData);
const dateAsISO = dateToISO(date);
const valueIsArray = Array.isArray(value);
if (this.range) {
const focusedInputValueIndex = focusedInput === "start" ? 0 : 1;
if (valueIsArray) {
if (dateAsISO === value[focusedInputValueIndex]) {
return;
}
if (date) {
this.setRangeValue([
focusedInput === "start" ? date : dateFromISO(value[0]),
focusedInput === "end" ? date : dateFromISO(value[1])
]);
this.localizeInputValues();
} else {
this.setRangeValue([
focusedInput === "end" && dateFromISO(value[0]),
focusedInput === "start" && dateFromISO(value[1])
]);
}
} else {
if (date) {
this.setRangeValue([
focusedInput === "start" ? date : dateFromISO(value[0]),
focusedInput === "end" ? date : dateFromISO(value[1])
]);
this.localizeInputValues();
}
}
} else {
if (dateAsISO === value) {
return;
}
this.setValue(date);
this.localizeInputValues();
}
}
keyDownHandler(event) {
const { defaultPrevented, key } = event;
if (defaultPrevented) {
return;
}
const targetHasSelect = event.composedPath().some((el) => el.tagName === "CALCITE-SELECT");
if (key === "Enter") {
event.preventDefault();
this.commitValue();
if (this.shouldFocusRangeEnd()) {
this.endInput?.setFocus();
} else if (this.shouldFocusRangeStart()) {
this.startInput?.setFocus();
}
if (submitForm(this)) {
this.restoreInputFocus(true);
}
} else if ((key === "ArrowDown" || key === "ArrowUp") && !targetHasSelect) {
this.open = true;
this.focusOnOpen = true;
event.preventDefault();
} else if (this.open && key === "Escape") {
this.open = false;
event.preventDefault();
this.restoreInputFocus(true);
}
}
startInputFocus() {
this.focusedInput = "start";
}
endInputFocus() {
this.focusedInput = "end";
}
setFloatingEl(el) {
this.floatingEl = el;
connectFloatingUI(this);
}
setStartWrapper(el) {
this.startWrapper = el;
this.setReferenceEl();
}
setEndWrapper(el) {
this.endWrapper = el;
this.setReferenceEl();
}
setDatePickerRef(el) {
if (!el) {
return;
}
this.datePickerEl = el;
this.focusTrap.overrideFocusTrapEl(el);
}
async loadLocaleData() {
if (isServer) {
return;
}
numberStringFormatter.numberFormatOptions = {
numberingSystem: this.numberingSystem,
locale: this.messages._lang,
useGrouping: false
};
this.localeData = await getLocaleData(this.messages._lang);
this.localizeInputValues();
}
handleDateChange(event) {
if (this.range) {
return;
}
event.stopPropagation();
this.setValue(event.target.valueAsDate);
this.localizeInputValues();
this.restoreInputFocus();
}
shouldFocusRangeStart() {
const startValue = this.value[0];
const endValue = this.value[1];
return !!(endValue && !startValue && this.focusedInput === "end" && this.startInput);
}
shouldFocusRangeEnd() {
const startValue = this.value[0];
const endValue = this.value[1];
return !!(startValue && !endValue && this.focusedInput === "start" && this.endInput);
}
handleDateRangeChange(event) {
if (!this.range) {
return;
}
event.stopPropagation();
const value = event.target.valueAsDate;
this.setRangeValue(value);
this.localizeInputValues();
this.restoreInputFocus();
}
restoreInputFocus(isDatePickerClosed = false) {
if (!this.range) {
this.startInput.setFocus();
this.open = false;
return;
}
if (isDatePickerClosed) {
this.focusInput();
return;
}
this.rangeStartValueChangedByUser = this.focusedInput === "start";
this.focusedInput = "end";
if (this.shouldFocusRangeStart() || this.rangeStartValueChangedByUser) {
return;
}
this.open = false;
this.focusInput();
}
localizeInputValues() {
const date = dateFromRange(this.range ? Array.isArray(this.valueAsDate) && this.valueAsDate[0] || void 0 : this.valueAsDate, this.minAsDate, this.maxAsDate);
const endDate = this.range ? dateFromRange(Array.isArray(this.valueAsDate) && this.valueAsDate[1] || void 0, this.minAsDate, this.maxAsDate) : null;
this.setInputValue((date && this.dateTimeFormat.format(date)) ?? "", "start");
this.setInputValue((this.range && endDate && this.dateTimeFormat.format(endDate)) ?? "", "end");
}
setInputValue(newValue, input = "start") {
const inputEl = this[`${input}Input`];
if (!inputEl) {
return;
}
inputEl.value = newValue;
}
setRangeValue(valueAsDate) {
if (!this.range) {
return;
}
const { value: oldValue } = this;
const oldValueIsArray = Array.isArray(oldValue);
const valueIsArray = Array.isArray(valueAsDate);
const newStartDate = valueIsArray ? valueAsDate[0] : null;
let newStartDateISO = valueIsArray ? dateToISO(newStartDate) : "";
if (newStartDateISO) {
newStartDateISO = this.getNormalizedDate(newStartDateISO);
}
const newEndDate = valueIsArray ? valueAsDate[1] : null;
let newEndDateISO = valueIsArray ? dateToISO(newEndDate) : "";
if (newEndDateISO) {
newEndDateISO = this.getNormalizedDate(newEndDateISO);
}
const newValue = newStartDateISO || newEndDateISO ? [newStartDateISO, newEndDateISO] : "";
if (newValue === oldValue) {
return;
}
this.userChangedValue = true;
this.value = newValue;
this.valueAsDate = newValue ? getValueAsDateRange(newValue) : void 0;
const changeEvent = this.calciteInputDatePickerChange.emit();
if (changeEvent && changeEvent.defaultPrevented) {
this.value = oldValue;
if (oldValueIsArray) {
this.setInputValue(oldValue[0], "start");
this.setInputValue(oldValue[1], "end");
} else {
this.value = oldValue;
this.setInputValue(oldValue);
}
}
}
setValue(value) {
if (this.range) {
return;
}
const oldValue = this.value;
let newValue = dateToISO(value);
newValue = this.getNormalizedDate(newValue);
if (newValue === oldValue) {
return;
}
this.userChangedValue = true;
this.valueAsDate = newValue ? dateFromISO(newValue) : void 0;
this.value = newValue || "";
const changeEvent = this.calciteInputDatePickerChange.emit();
if (changeEvent.defaultPrevented) {
this.value = oldValue;
this.setInputValue(oldValue);
}
}
warnAboutInvalidValue(value) {
console.warn(`The specified value "${value}" does not conform to the required format, "YYYY-MM-DD".`);
}
formatNumerals(value) {
return value ? value.split("").map((char) => this.commonDateSeparators?.includes(char) ? this.localeData?.separator : numberKeys?.includes(char) ? numberStringFormatter?.numberFormatter?.format(Number(char)) : char).join("") : "";
}
parseNumerals(value) {
return value ? value.split("").map((char) => numberKeys.includes(char) ? numberStringFormatter.delocalize(char) : char).join("") : "";
}
getNormalizedDate(value) {
if (!value) {
return "";
}
if (!isTwoDigitYear(value)) {
return value;
}
const { day, month, year } = datePartsFromISO(value);
const normalizedYear = normalizeToCurrentCentury(Number(year));
return `${normalizedYear}-${month}-${day}`;
}
focusInput() {
const focusedInput = this.focusedInput === "start" ? this.startInput : this.endInput;
focusedInput.setFocus();
}
render() {
const { disabled, messages: { _lang: effectiveLocale }, messages, numberingSystem, readOnly } = this;
numberStringFormatter.numberFormatOptions = {
numberingSystem,
locale: effectiveLocale,
useGrouping: false
};
return InteractiveContainer({ disabled: this.disabled, children: html`${this.localeData && html`<div class=${safeClassMap(CSS.container)}><div class=${safeClassMap(CSS.inputContainer)}><div class=${safeClassMap(CSS.inputWrapper)} data-position=start =${this.onInputWrapperClick} =${this.onInputWrapperPointerDown} ${ref(this.setStartWrapper)}><calcite-input-text aria-controls=${this.dialogId ?? nothing} aria-describedby=${this.placeholderTextId ?? nothing} aria-errormessage=${IDS.validationMessage} aria-autocomplete=none .ariaExpanded=${this.open} aria-haspopup=dialog .ariaInvalid=${this.status === "invalid"} class=${safeClassMap({
[CSS.input]: true,
[CSS.inputNoBottomBorder]: this.layout === "vertical" && this.range,
[CSS.inputNoRightBorder]: this.range
})} .disabled=${disabled} icon=calendar .label=${this.label} =${this.calciteInternalInputInputHandler} =${this.calciteInternalInputBlurHandler} =${this.startInputFocus} .placeholder=${this.localeData?.placeholder} .readOnly=${readOnly} role=combobox .scale=${this.scale} .status=${this.status} ${ref(this.setStartInput)}></calcite-input-text>${!this.readOnly && !this.range && this.renderToggleIcon(this.open && this.focusedInput === "start") || ""}<span aria-hidden=true class=${safeClassMap(CSS.assistiveText)} id=${this.placeholderTextId ?? nothing}>${messages.dateFormat.replace("{format}", this.localeData?.placeholder)}</span></div><div .ariaHidden=${!this.open} .ariaLabel=${messages.chooseDate} aria-live=polite aria-modal=true class=${safeClassMap(CSS.menu)} id=${this.dialogId ?? nothing} role=dialog ${ref(this.setFloatingEl)}><div class=${safeClassMap({
[CSS.calendarWrapper]: true,
[FloatingCSS.animation]: true,
[FloatingCSS.animationActive]: this.open
})} ${ref(this.setTransitionEl)}><calcite-date-picker .activeDate=${this.datePickerActiveDate} .activeRange=${this.focusedInput} .headingLevel=${this.headingLevel} .layout=${this.layout} .max=${this.max} .maxAsDate=${this.maxAsDate} .messageOverrides=${this.messageOverrides} .min=${this.min} .minAsDate=${this.minAsDate} .monthStyle=${this.monthStyle} .numberingSystem=${numberingSystem} =${this.handleDateChange} =${this.handleDateRangeChange} .proximitySelectionDisabled=${this.proximitySelectionDisabled} .range=${this.range} .scale=${this.scale} tabindex=${(this.open ? void 0 : -1) ?? nothing} .valueAsDate=${this.valueAsDate} ${ref(this.setDatePickerRef)}></calcite-date-picker></div></div>${this.range && html`<div class=${safeClassMap(CSS.dividerContainer)}><div class=${safeClassMap(CSS.divider)}></div></div>` || ""}${this.range && html`<div class=${safeClassMap(CSS.inputWrapper)} data-position=end =${this.onInputWrapperClick} =${this.onInputWrapperPointerDown} ${ref(this.setEndWrapper)}><calcite-input-text aria-controls=${this.dialogId ?? nothing} aria-autocomplete=none .ariaExpanded=${this.open} aria-haspopup=dialog class=${safeClassMap({
[CSS.input]: true,
[CSS.inputNoTopBorder]: this.layout === "vertical" && this.range,
[CSS.inputNoLeftBorder]: this.layout === "horizontal" && this.range,
[CSS.inputNoRightBorder]: this.layout === "vertical" && this.range
})} .disabled=${disabled} icon=calendar .label=${this.label} =${this.calciteInternalInputInputHandler} =${this.calciteInternalInputBlurHandler} =${this.endInputFocus} .placeholder=${this.localeData?.placeholder} .readOnly=${readOnly} role=combobox .scale=${this.scale} .status=${this.status} ${ref(this.setEndInput)}></calcite-input-text>${!this.readOnly && this.layout === "horizontal" && this.renderToggleIcon(this.open) || ""}</div>` || ""}</div>${this.range && this.layout === "vertical" && html`<div class=${safeClassMap(CSS.verticalChevronContainer)}><calcite-icon .icon=${this.open ? "chevron-up" : "chevron-down"} .scale=${getIconScale(this.scale)}></calcite-icon></div>` || ""}</div>` || ""}${HiddenFormInputSlot({ component: this })}${this.validationMessage && this.status === "invalid" ? Validation({ icon: this.validationIcon, id: IDS.validationMessage, message: this.validationMessage, scale: this.scale, status: this.status }) : null}` });
}
renderToggleIcon(open) {
return html`<span class=${safeClassMap(CSS.toggleIcon)} tabindex=-1><calcite-icon class=${safeClassMap(CSS.chevronIcon)} .icon=${open ? "chevron-up" : "chevron-down"} .scale=${getIconScale(this.scale)}></calcite-icon></span>`;
}
}
customElement("calcite-input-date-picker", InputDatePicker);
export {
InputDatePicker
};