UNPKG

@esri/calcite-components

Version:

Web Components for Esri's Calcite Design System.

669 lines (668 loc) • 34.6 kB
/*! 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 @click=${this.onInputWrapperClick} @pointerdown=${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} @calciteInputTextInput=${this.calciteInternalInputInputHandler} @calciteInternalInputTextBlur=${this.calciteInternalInputBlurHandler} @calciteInternalInputTextFocus=${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} @calciteDatePickerChange=${this.handleDateChange} @calciteDatePickerRangeChange=${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 @click=${this.onInputWrapperClick} @pointerdown=${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} @calciteInputTextInput=${this.calciteInternalInputInputHandler} @calciteInternalInputTextBlur=${this.calciteInternalInputBlurHandler} @calciteInternalInputTextFocus=${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 };