UNPKG

@ionic/core

Version:
656 lines (649 loc) • 118 kB
/*! * (C) Ionic http://ionicframework.com - MIT License */ import { proxyCustomElement, HTMLElement, createEvent, writeTask, h, Host } from '@stencil/core/internal/client'; import { startFocusVisible } from './focus-visible.js'; import { r as raf, g as getElementRoot, e as renderHiddenInput } from './helpers.js'; import { a as printIonError, p as printIonWarning } from './index4.js'; import { i as isRTL } from './dir.js'; import { c as createColorClasses } from './theme.js'; import { c as chevronDown, f as caretUpSharp, g as chevronForward, h as caretDownSharp, a as chevronBack } from './index6.js'; import { b as getIonMode } from './ionic-global.js'; import { i as isBefore, a as isAfter, g as getPreviousMonth, b as getNextMonth, c as isSameDay, d as getDay, e as generateDayAriaLabel, v as validateParts, f as getPartsFromCalendarDay, h as getNextYear, j as getPreviousYear, k as getEndOfWeek, l as getStartOfWeek, m as getPreviousDay, n as getNextDay, o as getPreviousWeek, p as getNextWeek, q as parseMinParts, r as parseMaxParts, s as parseDate, w as warnIfValueOutOfBounds, t as parseAmPm, u as clampDate, x as convertToArrayOfNumbers, y as convertDataToISO, z as getToday, A as getClosestValidDate, B as generateMonths, C as getNumDaysInMonth, D as getCombinedDateColumnData, E as getMonthColumnData, F as getDayColumnData, G as getYearColumnData, H as isMonthFirstLocale, I as getTimeColumnsData, J as isLocaleDayPeriodRTL, K as calculateHourFromAMPM, L as getMonthAndYear, M as getDaysOfWeek, N as getDaysOfMonth, O as getHourCycle, P as getLocalizedTime, Q as getLocalizedDateTime, R as formatValue } from './data.js'; import { d as defineCustomElement$a } from './backdrop.js'; import { d as defineCustomElement$9 } from './button.js'; import { d as defineCustomElement$8 } from './buttons.js'; import { d as defineCustomElement$7 } from './icon.js'; import { d as defineCustomElement$6 } from './picker.js'; import { d as defineCustomElement$5 } from './picker-column.js'; import { d as defineCustomElement$4 } from './picker-column-option.js'; import { d as defineCustomElement$3 } from './popover.js'; import { d as defineCustomElement$2 } from './ripple-effect.js'; const isYearDisabled = (refYear, minParts, maxParts) => { if (minParts && minParts.year > refYear) { return true; } if (maxParts && maxParts.year < refYear) { return true; } return false; }; /** * Returns true if a given day should * not be interactive according to its value, * or the max/min dates. */ const isDayDisabled = (refParts, minParts, maxParts, dayValues) => { /** * If this is a filler date (i.e. padding) * then the date is disabled. */ if (refParts.day === null) { return true; } /** * If user passed in a list of acceptable day values * check to make sure that the date we are looking * at is in this array. */ if (dayValues !== undefined && !dayValues.includes(refParts.day)) { return true; } /** * Given a min date, perform the following * checks. If any of them are true, then the * day should be disabled: * 1. Is the current year < the min allowed year? * 2. Is the current year === min allowed year, * but the current month < the min allowed month? * 3. Is the current year === min allowed year, the * current month === min allow month, but the current * day < the min allowed day? */ if (minParts && isBefore(refParts, minParts)) { return true; } /** * Given a max date, perform the following * checks. If any of them are true, then the * day should be disabled: * 1. Is the current year > the max allowed year? * 2. Is the current year === max allowed year, * but the current month > the max allowed month? * 3. Is the current year === max allowed year, the * current month === max allow month, but the current * day > the max allowed day? */ if (maxParts && isAfter(refParts, maxParts)) { return true; } /** * If none of these checks * passed then the date should * be interactive. */ return false; }; /** * Given a locale, a date, the selected date(s), and today's date, * generate the state for a given calendar day button. */ const getCalendarDayState = (locale, refParts, activeParts, todayParts, minParts, maxParts, dayValues) => { /** * activeParts signals what day(s) are currently selected in the datetime. * If multiple="true", this will be an array, but the logic in this util * is the same whether we have one selected day or many because we're only * calculating the state for one button. So, we treat a single activeParts value * the same as an array of length one. */ const activePartsArray = Array.isArray(activeParts) ? activeParts : [activeParts]; /** * The day button is active if it is selected, or in other words, if refParts * matches at least one selected date. */ const isActive = activePartsArray.find((parts) => isSameDay(refParts, parts)) !== undefined; const isToday = isSameDay(refParts, todayParts); const disabled = isDayDisabled(refParts, minParts, maxParts, dayValues); /** * Note that we always return one object regardless of whether activeParts * was an array, since we pare down to one value for isActive. */ return { disabled, isActive, isToday, ariaSelected: isActive ? 'true' : null, ariaLabel: generateDayAriaLabel(locale, isToday, refParts), text: refParts.day != null ? getDay(locale, refParts) : null, }; }; /** * Returns `true` if the month is disabled given the * current date value and min/max date constraints. */ const isMonthDisabled = (refParts, { minParts, maxParts, }) => { // If the year is disabled then the month is disabled. if (isYearDisabled(refParts.year, minParts, maxParts)) { return true; } // If the date value is before the min date, then the month is disabled. // If the date value is after the max date, then the month is disabled. if ((minParts && isBefore(refParts, minParts)) || (maxParts && isAfter(refParts, maxParts))) { return true; } return false; }; /** * Given a working date, an optional minimum date range, * and an optional maximum date range; determine if the * previous navigation button is disabled. */ const isPrevMonthDisabled = (refParts, minParts, maxParts) => { const prevMonth = Object.assign(Object.assign({}, getPreviousMonth(refParts)), { day: null }); return isMonthDisabled(prevMonth, { minParts, maxParts, }); }; /** * Given a working date and a maximum date range, * determine if the next navigation button is disabled. */ const isNextMonthDisabled = (refParts, maxParts) => { const nextMonth = Object.assign(Object.assign({}, getNextMonth(refParts)), { day: null }); return isMonthDisabled(nextMonth, { maxParts, }); }; /** * Given the value of the highlightedDates property * and an ISO string, return the styles to use for * that date, or undefined if none are found. */ const getHighlightStyles = (highlightedDates, dateIsoString, el) => { if (Array.isArray(highlightedDates)) { const dateStringWithoutTime = dateIsoString.split('T')[0]; const matchingHighlight = highlightedDates.find((hd) => hd.date === dateStringWithoutTime); if (matchingHighlight) { return { textColor: matchingHighlight.textColor, backgroundColor: matchingHighlight.backgroundColor, }; } } else { /** * Wrap in a try-catch to prevent exceptions in the user's function * from interrupting the calendar's rendering. */ try { return highlightedDates(dateIsoString); } catch (e) { printIonError('[ion-datetime] - Exception thrown from provided `highlightedDates` callback. Please check your function and try again.', el, e); } } return undefined; }; /** * If a time zone is provided in the format options, the rendered text could * differ from what was selected in the Datetime, which could cause * confusion. */ const warnIfTimeZoneProvided = (el, formatOptions) => { var _a, _b, _c, _d; if (((_a = formatOptions === null || formatOptions === void 0 ? void 0 : formatOptions.date) === null || _a === void 0 ? void 0 : _a.timeZone) || ((_b = formatOptions === null || formatOptions === void 0 ? void 0 : formatOptions.date) === null || _b === void 0 ? void 0 : _b.timeZoneName) || ((_c = formatOptions === null || formatOptions === void 0 ? void 0 : formatOptions.time) === null || _c === void 0 ? void 0 : _c.timeZone) || ((_d = formatOptions === null || formatOptions === void 0 ? void 0 : formatOptions.time) === null || _d === void 0 ? void 0 : _d.timeZoneName)) { printIonWarning('[ion-datetime] - "timeZone" and "timeZoneName" are not supported in "formatOptions".', el); } }; const checkForPresentationFormatMismatch = (el, presentation, formatOptions) => { // formatOptions is not required if (!formatOptions) return; // If formatOptions is provided, the date and/or time objects are required, depending on the presentation switch (presentation) { case 'date': case 'month-year': case 'month': case 'year': if (formatOptions.date === undefined) { printIonWarning(`[ion-datetime] - The '${presentation}' presentation requires a date object in formatOptions.`, el); } break; case 'time': if (formatOptions.time === undefined) { printIonWarning(`[ion-datetime] - The 'time' presentation requires a time object in formatOptions.`, el); } break; case 'date-time': case 'time-date': if (formatOptions.date === undefined && formatOptions.time === undefined) { printIonWarning(`[ion-datetime] - The '${presentation}' presentation requires either a date or time object (or both) in formatOptions.`, el); } break; } }; const datetimeIosCss = ":host{display:-ms-flexbox;display:flex;-ms-flex-flow:column;flex-flow:column;background:var(--background);overflow:hidden}:host(.datetime-size-fixed){width:auto;height:auto}:host(.datetime-size-fixed:not(.datetime-prefer-wheel)){max-width:350px}:host(.datetime-size-fixed.datetime-prefer-wheel){min-width:350px;max-width:-webkit-max-content;max-width:-moz-max-content;max-width:max-content}:host(.datetime-size-cover){width:100%}:host .calendar-body,:host .datetime-year{opacity:0}:host(:not(.datetime-ready)) .datetime-year{position:absolute;pointer-events:none}:host(.datetime-ready) .calendar-body{opacity:1}:host(.datetime-ready) .datetime-year{display:none;opacity:1}:host .wheel-order-year-first .day-column{-ms-flex-order:3;order:3;text-align:end}:host .wheel-order-year-first .month-column{-ms-flex-order:2;order:2;text-align:end}:host .wheel-order-year-first .year-column{-ms-flex-order:1;order:1;text-align:start}:host .datetime-calendar,:host .datetime-year{display:-ms-flexbox;display:flex;-ms-flex:1 1 auto;flex:1 1 auto;-ms-flex-flow:column;flex-flow:column}:host(.show-month-and-year) .datetime-year{display:-ms-flexbox;display:flex}:host(.show-month-and-year) .calendar-next-prev,:host(.show-month-and-year) .calendar-days-of-week,:host(.show-month-and-year) .calendar-body,:host(.show-month-and-year) .datetime-time{display:none}:host(.month-year-picker-open) .datetime-footer{display:none}:host(.datetime-disabled){pointer-events:none}:host(.datetime-disabled) .calendar-days-of-week,:host(.datetime-disabled) .datetime-time{opacity:0.4}:host(.datetime-readonly){pointer-events:none;}:host(.datetime-readonly) .calendar-action-buttons,:host(.datetime-readonly) .calendar-body,:host(.datetime-readonly) .datetime-year{pointer-events:initial}:host(.datetime-readonly) .calendar-day[disabled]:not(.calendar-day-constrained),:host(.datetime-readonly) .datetime-action-buttons ion-button[disabled]{opacity:1}:host .datetime-header .datetime-title{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}:host .datetime-action-buttons.has-clear-button{width:100%}:host .datetime-action-buttons ion-buttons{display:-ms-flexbox;display:flex;-ms-flex-pack:justify;justify-content:space-between}.datetime-action-buttons .datetime-action-buttons-container{display:-ms-flexbox;display:flex}:host .calendar-action-buttons{display:-ms-flexbox;display:flex;-ms-flex-pack:justify;justify-content:space-between}:host .calendar-action-buttons ion-button{--background:transparent}:host .calendar-days-of-week{display:grid;grid-template-columns:repeat(7, 1fr);text-align:center}.calendar-days-of-week .day-of-week{-webkit-margin-start:auto;margin-inline-start:auto;-webkit-margin-end:auto;margin-inline-end:auto;margin-top:0;margin-bottom:0}:host .calendar-body{display:-ms-flexbox;display:flex;-ms-flex-positive:1;flex-grow:1;-webkit-scroll-snap-type:x mandatory;-ms-scroll-snap-type:x mandatory;scroll-snap-type:x mandatory;overflow-x:scroll;overflow-y:hidden;scrollbar-width:none;outline:none}:host .calendar-body .calendar-month{display:-ms-flexbox;display:flex;-ms-flex-flow:column;flex-flow:column;scroll-snap-align:start;scroll-snap-stop:always;-ms-flex-negative:0;flex-shrink:0;width:100%}:host .calendar-body .calendar-month-disabled{scroll-snap-align:none}:host .calendar-body::-webkit-scrollbar{display:none}:host .calendar-body .calendar-month-grid{display:grid;grid-template-columns:repeat(7, 1fr)}:host .calendar-day-wrapper{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;-ms-flex-pack:center;justify-content:center;min-width:0;min-height:0;overflow:visible}.calendar-day{border-radius:50%;-webkit-padding-start:0px;padding-inline-start:0px;-webkit-padding-end:0px;padding-inline-end:0px;padding-top:0px;padding-bottom:0px;-webkit-margin-start:0px;margin-inline-start:0px;-webkit-margin-end:0px;margin-inline-end:0px;margin-top:0px;margin-bottom:0px;display:-ms-flexbox;display:flex;position:relative;-ms-flex-align:center;align-items:center;-ms-flex-pack:center;justify-content:center;border:none;outline:none;background:none;color:currentColor;font-family:var(--ion-font-family, inherit);cursor:pointer;-webkit-appearance:none;-moz-appearance:none;appearance:none;z-index:0}:host .calendar-day[disabled]{pointer-events:none;opacity:0.4}.calendar-day:not(.calendar-day-adjacent-day):focus{background:rgba(var(--ion-color-base-rgb), 0.2);-webkit-box-shadow:0px 0px 0px 4px rgba(var(--ion-color-base-rgb), 0.2);box-shadow:0px 0px 0px 4px rgba(var(--ion-color-base-rgb), 0.2)}:host .datetime-time{display:-ms-flexbox;display:flex;-ms-flex-pack:justify;justify-content:space-between}:host(.datetime-presentation-time) .datetime-time{padding-left:0;padding-right:0;padding-top:0;padding-bottom:0}:host ion-popover{--height:200px}:host .time-header{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center}:host .time-body{border-radius:8px;-webkit-padding-start:12px;padding-inline-start:12px;-webkit-padding-end:12px;padding-inline-end:12px;padding-top:6px;padding-bottom:6px;display:-ms-flexbox;display:flex;border:none;background:var(--ion-color-step-300, var(--ion-background-color-step-300, #edeef0));color:var(--ion-text-color, #000);font-family:inherit;font-size:inherit;cursor:pointer;-webkit-appearance:none;-moz-appearance:none;appearance:none}:host .time-body-active{color:var(--ion-color-base)}:host(.in-item){position:static}:host(.show-month-and-year) .calendar-action-buttons .calendar-month-year-toggle{color:var(--ion-color-base)}.calendar-month-year{min-width:0}.calendar-month-year-toggle{font-family:inherit;font-size:inherit;font-style:inherit;font-weight:inherit;letter-spacing:inherit;text-decoration:inherit;text-indent:inherit;text-overflow:inherit;text-transform:inherit;text-align:inherit;white-space:inherit;color:inherit;position:relative;border:0;outline:none;background:transparent;cursor:pointer;z-index:1}.calendar-month-year-toggle::after{left:0;right:0;top:0;bottom:0;position:absolute;content:\"\";opacity:0;-webkit-transition:opacity 15ms linear, background-color 15ms linear;transition:opacity 15ms linear, background-color 15ms linear;z-index:-1}.calendar-month-year-toggle.ion-focused::after{background:currentColor}.calendar-month-year-toggle:disabled{opacity:0.3;pointer-events:none}.calendar-month-year-toggle ion-icon{-webkit-padding-start:4px;padding-inline-start:4px;-webkit-padding-end:0;padding-inline-end:0;padding-top:0;padding-bottom:0;-ms-flex-negative:0;flex-shrink:0}.calendar-month-year-toggle #toggle-wrapper{display:-ms-inline-flexbox;display:inline-flex;-ms-flex-align:center;align-items:center}ion-picker{--highlight-background:var(--wheel-highlight-background);--highlight-border-radius:var(--wheel-highlight-border-radius);--fade-background-rgb:var(--wheel-fade-background-rgb)}:host{--background:var(--ion-color-light, #f4f5f8);--background-rgb:var(--ion-color-light-rgb, 244, 245, 248);--title-color:var(--ion-color-step-600, var(--ion-text-color-step-400, #666666))}:host(.datetime-presentation-date-time:not(.datetime-prefer-wheel)),:host(.datetime-presentation-time-date:not(.datetime-prefer-wheel)),:host(.datetime-presentation-date:not(.datetime-prefer-wheel)){min-height:350px}:host .datetime-header{-webkit-padding-start:16px;padding-inline-start:16px;-webkit-padding-end:16px;padding-inline-end:16px;padding-top:16px;padding-bottom:16px;border-bottom:0.55px solid var(--ion-color-step-200, var(--ion-background-color-step-200, #cccccc));font-size:min(0.875rem, 22.4px)}:host .datetime-header .datetime-title{color:var(--title-color)}:host .datetime-header .datetime-selected-date{margin-top:10px}.calendar-month-year-toggle{-webkit-padding-start:16px;padding-inline-start:16px;-webkit-padding-end:16px;padding-inline-end:16px;padding-top:0px;padding-bottom:0px;min-height:44px;font-size:min(1rem, 25.6px);font-weight:600}.calendar-month-year-toggle.ion-focused::after{opacity:0.15}.calendar-month-year-toggle #toggle-wrapper{-webkit-margin-start:0;margin-inline-start:0;-webkit-margin-end:8px;margin-inline-end:8px;margin-top:10px;margin-bottom:10px}:host .calendar-action-buttons .calendar-month-year-toggle ion-icon,:host .calendar-action-buttons ion-buttons ion-button{color:var(--ion-color-base)}:host .calendar-action-buttons ion-buttons{padding-left:0;padding-right:0;padding-top:8px;padding-bottom:0}:host .calendar-action-buttons ion-buttons ion-button{margin-left:0;margin-right:0;margin-top:0;margin-bottom:0}:host .calendar-days-of-week{-webkit-padding-start:8px;padding-inline-start:8px;-webkit-padding-end:8px;padding-inline-end:8px;padding-top:0;padding-bottom:0;color:var(--ion-color-step-300, var(--ion-text-color-step-700, #b3b3b3));font-size:min(0.75rem, 19.2px);font-weight:600;line-height:24px;text-transform:uppercase}@supports (border-radius: mod(1px, 1px)){.calendar-days-of-week .day-of-week{width:clamp(20px, calc(mod(min(1rem, 24px), 24px) * 10), 100%);height:24px;overflow:hidden}.calendar-day{border-radius:max(8px, mod(min(1rem, 24px), 24px) * 10)}}@supports ((border-radius: mod(1px, 1px)) and (background: -webkit-named-image(apple-pay-logo-black)) and (not (contain-intrinsic-size: none))) or (not (border-radius: mod(1px, 1px))){.calendar-days-of-week .day-of-week{width:auto;height:auto;overflow:initial}.calendar-day{border-radius:32px}}:host .calendar-body .calendar-month .calendar-month-grid{-webkit-padding-start:8px;padding-inline-start:8px;-webkit-padding-end:8px;padding-inline-end:8px;padding-top:8px;padding-bottom:8px;-ms-flex-align:center;align-items:center;height:calc(100% - 16px)}:host .calendar-day-wrapper{-webkit-padding-start:4px;padding-inline-start:4px;-webkit-padding-end:4px;padding-inline-end:4px;padding-top:4px;padding-bottom:4px;height:0;min-height:1rem}:host .calendar-day{width:40px;min-width:40px;height:40px;font-size:min(1.25rem, 32px)}.calendar-day.calendar-day-active{background:rgba(var(--ion-color-base-rgb), 0.2);font-size:min(1.375rem, 35.2px)}:host .calendar-day.calendar-day-today{color:var(--ion-color-base)}:host .calendar-day.calendar-day-active,:host .calendar-day.calendar-day-adjacent-day.calendar-day-active{color:var(--ion-color-base);font-weight:600}:host .calendar-day.calendar-day-today.calendar-day-active{background:var(--ion-color-base);color:var(--ion-color-contrast)}:host .calendar-day.calendar-day-adjacent-day{color:var(--ion-color-step-300, var(--ion-text-color-step-700, #b3b3b3))}:host .datetime-time{-webkit-padding-start:16px;padding-inline-start:16px;-webkit-padding-end:16px;padding-inline-end:16px;padding-top:8px;padding-bottom:16px;font-size:min(1rem, 25.6px)}:host .datetime-time .time-header{font-weight:600}:host .datetime-buttons{-webkit-padding-start:8px;padding-inline-start:8px;-webkit-padding-end:8px;padding-inline-end:8px;padding-top:8px;padding-bottom:8px;border-top:0.55px solid var(--ion-color-step-200, var(--ion-background-color-step-200, #cccccc))}:host .datetime-buttons ::slotted(ion-buttons),:host .datetime-buttons ion-buttons{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;-ms-flex-pack:justify;justify-content:space-between}:host .datetime-action-buttons{width:100%}"; const datetimeMdCss = ":host{display:-ms-flexbox;display:flex;-ms-flex-flow:column;flex-flow:column;background:var(--background);overflow:hidden}:host(.datetime-size-fixed){width:auto;height:auto}:host(.datetime-size-fixed:not(.datetime-prefer-wheel)){max-width:350px}:host(.datetime-size-fixed.datetime-prefer-wheel){min-width:350px;max-width:-webkit-max-content;max-width:-moz-max-content;max-width:max-content}:host(.datetime-size-cover){width:100%}:host .calendar-body,:host .datetime-year{opacity:0}:host(:not(.datetime-ready)) .datetime-year{position:absolute;pointer-events:none}:host(.datetime-ready) .calendar-body{opacity:1}:host(.datetime-ready) .datetime-year{display:none;opacity:1}:host .wheel-order-year-first .day-column{-ms-flex-order:3;order:3;text-align:end}:host .wheel-order-year-first .month-column{-ms-flex-order:2;order:2;text-align:end}:host .wheel-order-year-first .year-column{-ms-flex-order:1;order:1;text-align:start}:host .datetime-calendar,:host .datetime-year{display:-ms-flexbox;display:flex;-ms-flex:1 1 auto;flex:1 1 auto;-ms-flex-flow:column;flex-flow:column}:host(.show-month-and-year) .datetime-year{display:-ms-flexbox;display:flex}:host(.show-month-and-year) .calendar-next-prev,:host(.show-month-and-year) .calendar-days-of-week,:host(.show-month-and-year) .calendar-body,:host(.show-month-and-year) .datetime-time{display:none}:host(.month-year-picker-open) .datetime-footer{display:none}:host(.datetime-disabled){pointer-events:none}:host(.datetime-disabled) .calendar-days-of-week,:host(.datetime-disabled) .datetime-time{opacity:0.4}:host(.datetime-readonly){pointer-events:none;}:host(.datetime-readonly) .calendar-action-buttons,:host(.datetime-readonly) .calendar-body,:host(.datetime-readonly) .datetime-year{pointer-events:initial}:host(.datetime-readonly) .calendar-day[disabled]:not(.calendar-day-constrained),:host(.datetime-readonly) .datetime-action-buttons ion-button[disabled]{opacity:1}:host .datetime-header .datetime-title{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}:host .datetime-action-buttons.has-clear-button{width:100%}:host .datetime-action-buttons ion-buttons{display:-ms-flexbox;display:flex;-ms-flex-pack:justify;justify-content:space-between}.datetime-action-buttons .datetime-action-buttons-container{display:-ms-flexbox;display:flex}:host .calendar-action-buttons{display:-ms-flexbox;display:flex;-ms-flex-pack:justify;justify-content:space-between}:host .calendar-action-buttons ion-button{--background:transparent}:host .calendar-days-of-week{display:grid;grid-template-columns:repeat(7, 1fr);text-align:center}.calendar-days-of-week .day-of-week{-webkit-margin-start:auto;margin-inline-start:auto;-webkit-margin-end:auto;margin-inline-end:auto;margin-top:0;margin-bottom:0}:host .calendar-body{display:-ms-flexbox;display:flex;-ms-flex-positive:1;flex-grow:1;-webkit-scroll-snap-type:x mandatory;-ms-scroll-snap-type:x mandatory;scroll-snap-type:x mandatory;overflow-x:scroll;overflow-y:hidden;scrollbar-width:none;outline:none}:host .calendar-body .calendar-month{display:-ms-flexbox;display:flex;-ms-flex-flow:column;flex-flow:column;scroll-snap-align:start;scroll-snap-stop:always;-ms-flex-negative:0;flex-shrink:0;width:100%}:host .calendar-body .calendar-month-disabled{scroll-snap-align:none}:host .calendar-body::-webkit-scrollbar{display:none}:host .calendar-body .calendar-month-grid{display:grid;grid-template-columns:repeat(7, 1fr)}:host .calendar-day-wrapper{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;-ms-flex-pack:center;justify-content:center;min-width:0;min-height:0;overflow:visible}.calendar-day{border-radius:50%;-webkit-padding-start:0px;padding-inline-start:0px;-webkit-padding-end:0px;padding-inline-end:0px;padding-top:0px;padding-bottom:0px;-webkit-margin-start:0px;margin-inline-start:0px;-webkit-margin-end:0px;margin-inline-end:0px;margin-top:0px;margin-bottom:0px;display:-ms-flexbox;display:flex;position:relative;-ms-flex-align:center;align-items:center;-ms-flex-pack:center;justify-content:center;border:none;outline:none;background:none;color:currentColor;font-family:var(--ion-font-family, inherit);cursor:pointer;-webkit-appearance:none;-moz-appearance:none;appearance:none;z-index:0}:host .calendar-day[disabled]{pointer-events:none;opacity:0.4}.calendar-day:not(.calendar-day-adjacent-day):focus{background:rgba(var(--ion-color-base-rgb), 0.2);-webkit-box-shadow:0px 0px 0px 4px rgba(var(--ion-color-base-rgb), 0.2);box-shadow:0px 0px 0px 4px rgba(var(--ion-color-base-rgb), 0.2)}:host .datetime-time{display:-ms-flexbox;display:flex;-ms-flex-pack:justify;justify-content:space-between}:host(.datetime-presentation-time) .datetime-time{padding-left:0;padding-right:0;padding-top:0;padding-bottom:0}:host ion-popover{--height:200px}:host .time-header{display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center}:host .time-body{border-radius:8px;-webkit-padding-start:12px;padding-inline-start:12px;-webkit-padding-end:12px;padding-inline-end:12px;padding-top:6px;padding-bottom:6px;display:-ms-flexbox;display:flex;border:none;background:var(--ion-color-step-300, var(--ion-background-color-step-300, #edeef0));color:var(--ion-text-color, #000);font-family:inherit;font-size:inherit;cursor:pointer;-webkit-appearance:none;-moz-appearance:none;appearance:none}:host .time-body-active{color:var(--ion-color-base)}:host(.in-item){position:static}:host(.show-month-and-year) .calendar-action-buttons .calendar-month-year-toggle{color:var(--ion-color-base)}.calendar-month-year{min-width:0}.calendar-month-year-toggle{font-family:inherit;font-size:inherit;font-style:inherit;font-weight:inherit;letter-spacing:inherit;text-decoration:inherit;text-indent:inherit;text-overflow:inherit;text-transform:inherit;text-align:inherit;white-space:inherit;color:inherit;position:relative;border:0;outline:none;background:transparent;cursor:pointer;z-index:1}.calendar-month-year-toggle::after{left:0;right:0;top:0;bottom:0;position:absolute;content:\"\";opacity:0;-webkit-transition:opacity 15ms linear, background-color 15ms linear;transition:opacity 15ms linear, background-color 15ms linear;z-index:-1}.calendar-month-year-toggle.ion-focused::after{background:currentColor}.calendar-month-year-toggle:disabled{opacity:0.3;pointer-events:none}.calendar-month-year-toggle ion-icon{-webkit-padding-start:4px;padding-inline-start:4px;-webkit-padding-end:0;padding-inline-end:0;padding-top:0;padding-bottom:0;-ms-flex-negative:0;flex-shrink:0}.calendar-month-year-toggle #toggle-wrapper{display:-ms-inline-flexbox;display:inline-flex;-ms-flex-align:center;align-items:center}ion-picker{--highlight-background:var(--wheel-highlight-background);--highlight-border-radius:var(--wheel-highlight-border-radius);--fade-background-rgb:var(--wheel-fade-background-rgb)}:host{--background:var(--ion-color-step-100, var(--ion-background-color-step-100, #ffffff));--title-color:var(--ion-color-contrast)}:host .datetime-header{-webkit-padding-start:20px;padding-inline-start:20px;-webkit-padding-end:20px;padding-inline-end:20px;padding-top:20px;padding-bottom:20px;background:var(--ion-color-base);color:var(--title-color)}:host .datetime-header .datetime-title{font-size:0.75rem;text-transform:uppercase}:host .datetime-header .datetime-selected-date{margin-top:30px;font-size:2.125rem}:host .calendar-action-buttons ion-button{--color:var(--ion-color-step-650, var(--ion-text-color-step-350, #595959))}.calendar-month-year-toggle{-webkit-padding-start:20px;padding-inline-start:20px;-webkit-padding-end:16px;padding-inline-end:16px;padding-top:12px;padding-bottom:12px;min-height:48px;background:transparent;color:var(--ion-color-step-650, var(--ion-text-color-step-350, #595959));z-index:1}.calendar-month-year-toggle.ion-focused::after{opacity:0.04}.calendar-month-year-toggle ion-ripple-effect{color:currentColor}@media (any-hover: hover){.calendar-month-year-toggle.ion-activatable:not(.ion-focused):hover::after{background:currentColor;opacity:0.04}}:host .calendar-days-of-week{-webkit-padding-start:10px;padding-inline-start:10px;-webkit-padding-end:10px;padding-inline-end:10px;padding-top:0px;padding-bottom:0px;color:var(--ion-color-step-500, var(--ion-text-color-step-500, gray));font-size:0.875rem;line-height:36px}:host .calendar-body .calendar-month .calendar-month-grid{-webkit-padding-start:10px;padding-inline-start:10px;-webkit-padding-end:10px;padding-inline-end:10px;padding-top:4px;padding-bottom:4px;grid-template-rows:repeat(6, 1fr)}:host .calendar-day{width:42px;min-width:42px;height:42px;font-size:0.875rem}:host .calendar-day.calendar-day-today{border:1px solid var(--ion-color-base);color:var(--ion-color-base)}:host .calendar-day.calendar-day-active,:host .calendar-day.calendar-day-adjacent-day.calendar-day-active{color:var(--ion-color-contrast)}.calendar-day.calendar-day-active,.calendar-day.calendar-day-active:focus{border:1px solid var(--ion-color-base);background:var(--ion-color-base)}:host .calendar-day.calendar-day-adjacent-day{color:var(--ion-color-step-500, var(--ion-text-color-step-500, gray))}:host .datetime-time{-webkit-padding-start:16px;padding-inline-start:16px;-webkit-padding-end:16px;padding-inline-end:16px;padding-top:8px;padding-bottom:8px}:host .time-header{color:var(--ion-color-step-650, var(--ion-text-color-step-350, #595959))}:host(.datetime-presentation-month) .datetime-year,:host(.datetime-presentation-year) .datetime-year,:host(.datetime-presentation-month-year) .datetime-year{margin-top:20px;margin-bottom:20px}:host .datetime-buttons{-webkit-padding-start:10px;padding-inline-start:10px;-webkit-padding-end:10px;padding-inline-end:10px;padding-top:10px;padding-bottom:10px;display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;-ms-flex-pack:end;justify-content:flex-end}"; const Datetime = /*@__PURE__*/ proxyCustomElement(class Datetime extends HTMLElement { constructor() { super(); this.__registerHost(); this.__attachShadow(); this.ionCancel = createEvent(this, "ionCancel", 7); this.ionChange = createEvent(this, "ionChange", 7); this.ionValueChange = createEvent(this, "ionValueChange", 7); this.ionFocus = createEvent(this, "ionFocus", 7); this.ionBlur = createEvent(this, "ionBlur", 7); this.ionStyle = createEvent(this, "ionStyle", 7); this.ionRender = createEvent(this, "ionRender", 7); this.inputId = `ion-dt-${datetimeIds++}`; this.prevPresentation = null; this.showMonthAndYear = false; this.activeParts = []; this.workingParts = { month: 5, day: 28, year: 2021, hour: 13, minute: 52, ampm: 'pm', isAdjacentDay: false, }; this.isTimePopoverOpen = false; /** * The color to use from your application's color palette. * Default options are: `"primary"`, `"secondary"`, `"tertiary"`, `"success"`, `"warning"`, `"danger"`, `"light"`, `"medium"`, and `"dark"`. * For more information on colors, see [theming](/docs/theming/basics). */ this.color = 'primary'; /** * The name of the control, which is submitted with the form data. */ this.name = this.inputId; /** * If `true`, the user cannot interact with the datetime. */ this.disabled = false; /** * If `true`, the datetime appears normal but the selected date cannot be changed. */ this.readonly = false; /** * If `true`, the datetime calendar displays a six-week (42-day) layout, * including days from the previous and next months to fill the grid. * These adjacent days are selectable unless disabled. */ this.showAdjacentDays = false; /** * Which values you want to select. `"date"` will show * a calendar picker to select the month, day, and year. `"time"` * will show a time picker to select the hour, minute, and (optionally) * AM/PM. `"date-time"` will show the date picker first and time picker second. * `"time-date"` will show the time picker first and date picker second. */ this.presentation = 'date-time'; /** * The text to display on the picker's cancel button. */ this.cancelText = 'Cancel'; /** * The text to display on the picker's "Done" button. */ this.doneText = 'Done'; /** * The text to display on the picker's "Clear" button. */ this.clearText = 'Clear'; /** * The locale to use for `ion-datetime`. This * impacts month and day name formatting. * The `"default"` value refers to the default * locale set by your device. */ this.locale = 'default'; /** * The first day of the week to use for `ion-datetime`. The * default value is `0` and represents Sunday. */ this.firstDayOfWeek = 0; /** * If `true`, multiple dates can be selected at once. Only * applies to `presentation="date"` and `preferWheel="false"`. */ this.multiple = false; /** * If `true`, a header will be shown above the calendar * picker. This will include both the slotted title, and * the selected date. */ this.showDefaultTitle = false; /** * If `true`, the default "Cancel" and "OK" buttons * will be rendered at the bottom of the `ion-datetime` * component. Developers can also use the `button` slot * if they want to customize these buttons. If custom * buttons are set in the `button` slot then the * default buttons will not be rendered. */ this.showDefaultButtons = false; /** * If `true`, a "Clear" button will be rendered alongside * the default "Cancel" and "OK" buttons at the bottom of the `ion-datetime` * component. Developers can also use the `button` slot * if they want to customize these buttons. If custom * buttons are set in the `button` slot then the * default buttons will not be rendered. */ this.showClearButton = false; /** * If `true`, the default "Time" label will be rendered * for the time selector of the `ion-datetime` component. * Developers can also use the `time-label` slot * if they want to customize this label. If a custom * label is set in the `time-label` slot then the * default label will not be rendered. */ this.showDefaultTimeLabel = true; /** * If `cover`, the `ion-datetime` will expand to cover the full width of its container. * If `fixed`, the `ion-datetime` will have a fixed width. */ this.size = 'fixed'; /** * If `true`, a wheel picker will be rendered instead of a calendar grid * where possible. If `false`, a calendar grid will be rendered instead of * a wheel picker where possible. * * A wheel picker can be rendered instead of a grid when `presentation` is * one of the following values: `"date"`, `"date-time"`, or `"time-date"`. * * A wheel picker will always be rendered regardless of * the `preferWheel` value when `presentation` is one of the following values: * `"time"`, `"month"`, `"month-year"`, or `"year"`. */ this.preferWheel = false; this.warnIfIncorrectValueUsage = () => { const { multiple, value } = this; if (!multiple && Array.isArray(value)) { /** * We do some processing on the `value` array so * that it looks more like an array when logged to * the console. * Example given ['a', 'b'] * Default toString() behavior: a,b * Custom behavior: ['a', 'b'] */ printIonWarning(`[ion-datetime] - An array of values was passed, but multiple is "false". This is incorrect usage and may result in unexpected behaviors. To dismiss this warning, pass a string to the "value" property when multiple="false". Value Passed: [${value.map((v) => `'${v}'`).join(', ')}] `, this.el); } }; this.setValue = (value) => { this.value = value; this.ionChange.emit({ value }); }; /** * Returns the DatetimePart interface * to use when rendering an initial set of * data. This should be used when rendering an * interface in an environment where the `value` * may not be set. This function works * by returning the first selected date and then * falling back to defaultParts if no active date * is selected. */ this.getActivePartsWithFallback = () => { var _a; const { defaultParts } = this; return (_a = this.getActivePart()) !== null && _a !== void 0 ? _a : defaultParts; }; this.getActivePart = () => { const { activeParts } = this; return Array.isArray(activeParts) ? activeParts[0] : activeParts; }; this.closeParentOverlay = (role) => { const popoverOrModal = this.el.closest('ion-modal, ion-popover'); if (popoverOrModal) { popoverOrModal.dismiss(undefined, role); } }; this.setWorkingParts = (parts) => { this.workingParts = Object.assign({}, parts); }; this.setActiveParts = (parts, removeDate = false) => { /** if the datetime component is in readonly mode, * allow browsing of the calendar without changing * the set value */ if (this.readonly) { return; } const { multiple, minParts, maxParts, activeParts } = this; /** * When setting the active parts, it is possible * to set invalid data. For example, * when updating January 31 to February, * February 31 does not exist. As a result * we need to validate the active parts and * ensure that we are only setting valid dates. * Additionally, we need to update the working parts * too in the event that the validated parts are different. */ const validatedParts = validateParts(parts, minParts, maxParts); this.setWorkingParts(validatedParts); if (multiple) { const activePartsArray = Array.isArray(activeParts) ? activeParts : [activeParts]; if (removeDate) { this.activeParts = activePartsArray.filter((p) => !isSameDay(p, validatedParts)); } else { this.activeParts = [...activePartsArray, validatedParts]; } } else { this.activeParts = Object.assign({}, validatedParts); } const hasSlottedButtons = this.el.querySelector('[slot="buttons"]') !== null; if (hasSlottedButtons || this.showDefaultButtons) { return; } this.confirm(); }; this.initializeKeyboardListeners = () => { const calendarBodyRef = this.calendarBodyRef; if (!calendarBodyRef) { return; } const root = this.el.shadowRoot; /** * Get a reference to the month * element we are currently viewing. */ const currentMonth = calendarBodyRef.querySelector('.calendar-month:nth-of-type(2)'); /** * When focusing the calendar body, we want to pass focus * to the working day, but other days should * only be accessible using the arrow keys. Pressing * Tab should jump between bodies of selectable content. */ const checkCalendarBodyFocus = (ev) => { var _a; const record = ev[0]; /** * If calendar body was already focused * when this fired or if the calendar body * if not currently focused, we should not re-focus * the inner day. */ if (((_a = record.oldValue) === null || _a === void 0 ? void 0 : _a.includes('ion-focused')) || !calendarBodyRef.classList.contains('ion-focused')) { return; } this.focusWorkingDay(currentMonth); }; const mo = new MutationObserver(checkCalendarBodyFocus); mo.observe(calendarBodyRef, { attributeFilter: ['class'], attributeOldValue: true }); this.destroyKeyboardMO = () => { mo === null || mo === void 0 ? void 0 : mo.disconnect(); }; /** * We must use keydown not keyup as we want * to prevent scrolling when using the arrow keys. */ calendarBodyRef.addEventListener('keydown', (ev) => { const activeElement = root.activeElement; if (!activeElement || !activeElement.classList.contains('calendar-day')) { return; } const parts = getPartsFromCalendarDay(activeElement); let partsToFocus; switch (ev.key) { case 'ArrowDown': ev.preventDefault(); partsToFocus = getNextWeek(parts); break; case 'ArrowUp': ev.preventDefault(); partsToFocus = getPreviousWeek(parts); break; case 'ArrowRight': ev.preventDefault(); partsToFocus = getNextDay(parts); break; case 'ArrowLeft': ev.preventDefault(); partsToFocus = getPreviousDay(parts); break; case 'Home': ev.preventDefault(); partsToFocus = getStartOfWeek(parts); break; case 'End': ev.preventDefault(); partsToFocus = getEndOfWeek(parts); break; case 'PageUp': ev.preventDefault(); partsToFocus = ev.shiftKey ? getPreviousYear(parts) : getPreviousMonth(parts); break; case 'PageDown': ev.preventDefault(); partsToFocus = ev.shiftKey ? getNextYear(parts) : getNextMonth(parts); break; /** * Do not preventDefault here * as we do not want to override other * browser defaults such as pressing Enter/Space * to select a day. */ default: return; } /** * If the day we want to move focus to is * disabled, do not do anything. */ if (isDayDisabled(partsToFocus, this.minParts, this.maxParts)) { return; } this.setWorkingParts(Object.assign(Object.assign({}, this.workingParts), partsToFocus)); /** * Give view a chance to re-render * then move focus to the new working day */ requestAnimationFrame(() => this.focusWorkingDay(currentMonth)); }); }; this.focusWorkingDay = (currentMonth) => { /** * Get the number of offset days so * we know how much to offset our next selector by * to grab the correct calendar-day element. */ const { day, month, year } = this.workingParts; const firstOfMonth = new Date(`${month}/1/${year}`).getDay(); const offset = firstOfMonth >= this.firstDayOfWeek ? firstOfMonth - this.firstDayOfWeek : 7 - (this.firstDayOfWeek - firstOfMonth); if (day === null) { return; } /** * Get the calendar day element * and focus it. */ const dayEl = currentMonth.querySelector(`.calendar-day-wrapper:nth-of-type(${offset + day}) .calendar-day`); if (dayEl) { dayEl.focus(); } }; this.processMinParts = () => { const { min, defaultParts } = this; if (min === undefined) { this.minParts = undefined; return; } this.minParts = parseMinParts(min, defaultParts); }; this.processMaxParts = () => { const { max, defaultParts } = this; if (max === undefined) { this.maxParts = undefined; return; } this.maxParts = parseMaxParts(max, defaultParts); }; this.initializeCalendarListener = () => { const calendarBodyRef = this.calendarBodyRef; if (!calendarBodyRef) { return; } /** * For performance reasons, we only render 3 * months at a time: The current month, the previous * month, and the next month. We have a scroll listener * on the calendar body to append/prepend new months. * * We can do this because Stencil is smart enough to not * re-create the .calendar-month containers, but rather * update the content within those containers. * * As an added bonus, WebKit has some troubles with * scroll-snap-stop: always, so not rendering all of * the months in a row allows us to mostly sidestep * that issue. */ const months = calendarBodyRef.querySelectorAll('.calendar-month'); const startMonth = months[0]; const workingMonth = months[1]; const endMonth = months[2]; const mode = getIonMode(this); const needsiOSRubberBandFix = mode === 'ios' && typeof navigator !== 'undefined' && navigator.maxTouchPoints > 1; /** * Before setting up the scroll listener, * scroll the middle month into view. * scrollIntoView() will scroll entire page * if element is not in viewport. Use scrollLeft instead. */ writeTask(() => { calendarBodyRef.scrollLeft = startMonth.clientWidth * (isRTL(this.el) ? -1 : 1); const getChangedMonth = (parts) => { const box = calendarBodyRef.getBoundingClientRect(); /** * If the current scroll position is all the way to the left * then we have scrolled to the previous month. * Otherwise, assume that we have scrolled to the next * month. We have a tolerance of 2px to account for * sub pixel rendering. * * Check below the next line ensures that we did not * swipe and abort (i.e. we swiped but we are still on the current month). */ const condition = isRTL(this.el) ? calendarBodyRef.scrollLeft >= -2 : calendarBodyRef.scrollLeft <= 2; const month = condition ? startMonth : endMonth; /** * The edge of the month must be lined up with * the edge of the calendar body in order for