12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913 |
- /*!
- * (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, e as renderHiddenInput, g as getElementRoot } from './helpers.js';
- import { p as printIonError, a as printIonWarning } from './index4.js';
- import { i as isRTL } from './dir.js';
- import { c as createColorClasses } from './theme.js';
- import { a as chevronBack, f as chevronForward, c as chevronDown, g as caretUpSharp, h as caretDownSharp } from './index7.js';
- import { b as getIonMode } from './ionic-global.js';
- import { g as generateDayAriaLabel, a as getDay, i as isBefore, b as isAfter, c as isSameDay, d as getPreviousMonth, e as getNextMonth, 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 convertToArrayOfNumbers, u as convertDataToISO, x as getToday, y as getClosestValidDate, z as generateMonths, A as getNumDaysInMonth, B as getCombinedDateColumnData, C as getMonthColumnData, D as getDayColumnData, E as getYearColumnData, F as isMonthFirstLocale, G as getTimeColumnsData, H as isLocaleDayPeriodRTL, I as getMonthAndYear, J as getDaysOfWeek, K as getDaysOfMonth, L as getHourCycle, M as getLocalizedTime, N as getLocalizedDateTime, O as formatValue, P as clampDate, Q as parseAmPm, R as calculateHourFromAMPM } 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: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{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 .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 IonDatetimeIosStyle0 = datetimeIosCss;
- 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: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{color:var(--ion-color-contrast)}.calendar-day.calendar-day-active{border:1px solid var(--ion-color-base);background:var(--ion-color-base)}: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 IonDatetimeMdStyle0 = datetimeMdCss;
- 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.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 padding days so
- * we know how much to offset our next selector by
- * to grab the correct calendar-day element.
- */
- const padding = currentMonth.querySelectorAll('.calendar-day-padding');
- const { day } = this.workingParts;
- if (day === null) {
- return;
- }
- /**
- * Get the calendar day element
- * and focus it.
- */
- const dayEl = currentMonth.querySelector(`.calendar-day-wrapper:nth-of-type(${padding.length + 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
- * the component to update. Otherwise, it
- * may be the case that the user has paused their
- * swipe or the browser has not finished snapping yet.
- * Rather than check if the x values are equal,
- * we give it a tolerance of 2px to account for
- * sub pixel rendering.
- */
- const monthBox = month.getBoundingClientRect();
- if (Math.abs(monthBox.x - box.x) > 2)
- return;
- /**
- * If we're force-rendering a month, assume we've
- * scrolled to that and return it.
- *
- * If forceRenderDate is ever used in a context where the
- * forced month is not immediately auto-scrolled to, this
- * should be updated to also check whether `month` has the
- * same month and year as the forced date.
- */
- const { forceRenderDate } = this;
- if (forceRenderDate !== undefined) {
- return { month: forceRenderDate.month, year: forceRenderDate.year, day: forceRenderDate.day };
- }
- /**
- * From here, we can determine if the start
- * month or the end month was scrolled into view.
- * If no month was changed, then we can return from
- * the scroll callback early.
- */
- if (month === startMonth) {
- return getPreviousMonth(parts);
- }
- else if (month === endMonth) {
- return getNextMonth(parts);
- }
- else {
- return;
- }
- };
- const updateActiveMonth = () => {
- if (needsiOSRubberBandFix) {
- calendarBodyRef.style.removeProperty('pointer-events');
- appliediOSRubberBandFix = false;
- }
- /**
- * If the month did not change
- * then we can return early.
- */
- const newDate = getChangedMonth(this.workingParts);
- if (!newDate)
- return;
- const { month, day, year } = newDate;
- if (isMonthDisabled({ month, year, day: null }, {
- minParts: Object.assign(Object.assign({}, this.minParts), { day: null }),
- maxParts: Object.assign(Object.assign({}, this.maxParts), { day: null }),
- })) {
- return;
- }
- /**
- * Prevent scrolling for other browsers
- * to give the DOM time to update and the container
- * time to properly snap.
- */
- calendarBodyRef.style.setProperty('overflow', 'hidden');
- /**
- * Use a writeTask here to ensure
- * that the state is updated and the
- * correct month is scrolled into view
- * in the same frame. This is not
- * typically a problem on newer devices
- * but older/slower device may have a flicker
- * if we did not do this.
- */
- writeTask(() => {
- this.setWorkingParts(Object.assign(Object.assign({}, this.workingParts), { month, day: day, year }));
- calendarBodyRef.scrollLeft = workingMonth.clientWidth * (isRTL(this.el) ? -1 : 1);
- calendarBodyRef.style.removeProperty('overflow');
- if (this.resolveForceDateScrolling) {
- this.resolveForceDateScrolling();
- }
- });
- };
- /**
- * When the container finishes scrolling we
- * need to update the DOM with the selected month.
- */
- let scrollTimeout;
- /**
- * We do not want to attempt to set pointer-events
- * multiple times within a single swipe gesture as
- * that adds unnecessary work to the main thread.
- */
- let appliediOSRubberBandFix = false;
- const scrollCallback = () => {
- if (scrollTimeout) {
- clearTimeout(scrollTimeout);
- }
- /**
- * On iOS it is possible to quickly rubber band
- * the scroll area before the scroll timeout has fired.
- * This results in users reaching the end of the scrollable
- * container before the DOM has updated.
- * By setting `pointer-events: none` we can ensure that
- * subsequent swipes do not happen while the container
- * is snapping.
- */
- if (!appliediOSRubberBandFix && needsiOSRubberBandFix) {
- calendarBodyRef.style.setProperty('pointer-events', 'none');
- appliediOSRubberBandFix = true;
- }
- // Wait ~3 frames
- scrollTimeout = setTimeout(updateActiveMonth, 50);
- };
- calendarBodyRef.addEventListener('scroll', scrollCallback);
- this.destroyCalendarListener = () => {
- calendarBodyRef.removeEventListener('scroll', scrollCallback);
- };
- });
- };
- /**
- * Clean up all listeners except for the overlay
- * listener. This is so that we can re-create the listeners
- * if the datetime has been hidden/presented by a modal or popover.
- */
- this.destroyInteractionListeners = () => {
- const { destroyCalendarListener, destroyKeyboardMO } = this;
- if (destroyCalendarListener !== undefined) {
- destroyCalendarListener();
- }
- if (destroyKeyboardMO !== undefined) {
- destroyKeyboardMO();
- }
- };
- this.processValue = (value) => {
- const hasValue = value !== null && value !== undefined && value !== '' && (!Array.isArray(value) || value.length > 0);
- const valueToProcess = hasValue ? parseDate(value) : this.defaultParts;
- const { minParts, maxParts, workingParts, el } = this;
- this.warnIfIncorrectValueUsage();
- /**
- * Return early if the value wasn't parsed correctly, such as
- * if an improperly formatted date string was provided.
- */
- if (!valueToProcess) {
- return;
- }
- /**
- * Datetime should only warn of out of bounds values
- * if set by the user. If the `value` is undefined,
- * we will default to today's date which may be out
- * of bounds. In this case, the warning makes it look
- * like the developer did something wrong which is
- * not true.
- */
- if (hasValue) {
- warnIfValueOutOfBounds(valueToProcess, minParts, maxParts);
- }
- /**
- * If there are multiple values, pick an arbitrary one to clamp to. This way,
- * if the values are across months, we always show at least one of them. Note
- * that the values don't necessarily have to be in order.
- */
- const singleValue = Array.isArray(valueToProcess) ? valueToProcess[0] : valueToProcess;
- const targetValue = clampDate(singleValue, minParts, maxParts);
- const { month, day, year, hour, minute } = targetValue;
- const ampm = parseAmPm(hour);
- /**
- * Since `activeParts` indicates a value that
- * been explicitly selected either by the
- * user or the app, only update `activeParts`
- * if the `value` property is set.
- */
- if (hasValue) {
- if (Array.isArray(valueToProcess)) {
- this.activeParts = [...valueToProcess];
- }
- else {
- this.activeParts = {
- month,
- day,
- year,
- hour,
- minute,
- ampm,
- };
- }
- }
- else {
- /**
- * Reset the active parts if the value is not set.
- * This will clear the selected calendar day when
- * performing a clear action or using the reset() method.
- */
- this.activeParts = [];
- }
- /**
- * Only animate if:
- * 1. We're using grid style (wheel style pickers should just jump to new value)
- * 2. The month and/or year actually changed, and both are defined (otherwise there's nothing to animate to)
- * 3. The calendar body is visible (prevents animation when in collapsed datetime-button, for example)
- * 4. The month/year picker is not open (since you wouldn't see the animation anyway)
- */
- const didChangeMonth = (month !== undefined && month !== workingParts.month) || (year !== undefined && year !== workingParts.year);
- const bodyIsVisible = el.classList.contains('datetime-ready');
- const { isGridStyle, showMonthAndYear } = this;
- let areAllSelectedDatesInSameMonth = true;
- if (Array.isArray(valueToProcess)) {
- const firstMonth = valueToProcess[0].month;
- for (const date of valueToProcess) {
- if (date.month !== firstMonth) {
- areAllSelectedDatesInSameMonth = false;
- break;
- }
- }
- }
- /**
- * If there is more than one date selected
- * and the dates aren't all in the same month,
- * then we should neither animate to the date
- * nor update the working parts because we do
- * not know which date the user wants to view.
- */
- if (areAllSelectedDatesInSameMonth) {
- if (isGridStyle && didChangeMonth && bodyIsVisible && !showMonthAndYear) {
- this.animateToDate(targetValue);
- }
- else {
- /**
- * We only need to do this if we didn't just animate to a new month,
- * since that calls prevMonth/nextMonth which calls setWorkingParts for us.
- */
- this.setWorkingParts({
- month,
- day,
- year,
- hour,
- minute,
- ampm,
- });
- }
- }
- };
- this.animateToDate = async (targetValue) => {
- const { workingParts } = this;
- /**
- * Tell other render functions that we need to force the
- * target month to appear in place of the actual next/prev month.
- * Because this is a State variable, a rerender will be triggered
- * automatically, updating the rendered months.
- */
- this.forceRenderDate = targetValue;
- /**
- * Flag that we've started scrolling to the forced date.
- * The resolve function will be called by the datetime's
- * scroll listener when it's done updating everything.
- * This is a replacement for making prev/nextMonth async,
- * since the logic we're waiting on is in a listener.
- */
- const forceDateScrollingPromise = new Promise((resolve) => {
- this.resolveForceDateScrolling = resolve;
- });
- /**
- * Animate smoothly to the forced month. This will also update
- * workingParts and correct the surrounding months for us.
- */
- const targetMonthIsBefore = isBefore(targetValue, workingParts);
- targetMonthIsBefore ? this.prevMonth() : this.nextMonth();
- await forceDateScrollingPromise;
- this.resolveForceDateScrolling = undefined;
- this.forceRenderDate = undefined;
- };
- this.onFocus = () => {
- this.ionFocus.emit();
- };
- this.onBlur = () => {
- this.ionBlur.emit();
- };
- this.hasValue = () => {
- return this.value != null;
- };
- this.nextMonth = () => {
- const calendarBodyRef = this.calendarBodyRef;
- if (!calendarBodyRef) {
- return;
- }
- const nextMonth = calendarBodyRef.querySelector('.calendar-month:last-of-type');
- if (!nextMonth) {
- return;
- }
- const left = nextMonth.offsetWidth * 2;
- calendarBodyRef.scrollTo({
- top: 0,
- left: left * (isRTL(this.el) ? -1 : 1),
- behavior: 'smooth',
- });
- };
- this.prevMonth = () => {
- const calendarBodyRef = this.calendarBodyRef;
- if (!calendarBodyRef) {
- return;
- }
- const prevMonth = calendarBodyRef.querySelector('.calendar-month:first-of-type');
- if (!prevMonth) {
- return;
- }
- calendarBodyRef.scrollTo({
- top: 0,
- left: 0,
- behavior: 'smooth',
- });
- };
- this.toggleMonthAndYearView = () => {
- this.showMonthAndYear = !this.showMonthAndYear;
- };
- this.showMonthAndYear = false;
- this.activeParts = [];
- this.workingParts = {
- month: 5,
- day: 28,
- year: 2021,
- hour: 13,
- minute: 52,
- ampm: 'pm',
- };
- this.isTimePopoverOpen = false;
- this.forceRenderDate = undefined;
- this.color = 'primary';
- this.name = this.inputId;
- this.disabled = false;
- this.formatOptions = undefined;
- this.readonly = false;
- this.isDateEnabled = undefined;
- this.min = undefined;
- this.max = undefined;
- this.presentation = 'date-time';
- this.cancelText = 'Cancel';
- this.doneText = 'Done';
- this.clearText = 'Clear';
- this.yearValues = undefined;
- this.monthValues = undefined;
- this.dayValues = undefined;
- this.hourValues = undefined;
- this.minuteValues = undefined;
- this.locale = 'default';
- this.firstDayOfWeek = 0;
- this.titleSelectedDatesFormatter = undefined;
- this.multiple = false;
- this.highlightedDates = undefined;
- this.value = undefined;
- this.showDefaultTitle = false;
- this.showDefaultButtons = false;
- this.showClearButton = false;
- this.showDefaultTimeLabel = true;
- this.hourCycle = undefined;
- this.size = 'fixed';
- this.preferWheel = false;
- }
- formatOptionsChanged() {
- const { el, formatOptions, presentation } = this;
- checkForPresentationFormatMismatch(el, presentation, formatOptions);
- warnIfTimeZoneProvided(el, formatOptions);
- }
- disabledChanged() {
- this.emitStyle();
- }
- minChanged() {
- this.processMinParts();
- }
- maxChanged() {
- this.processMaxParts();
- }
- presentationChanged() {
- const { el, formatOptions, presentation } = this;
- checkForPresentationFormatMismatch(el, presentation, formatOptions);
- }
- get isGridStyle() {
- const { presentation, preferWheel } = this;
- const hasDatePresentation = presentation === 'date' || presentation === 'date-time' || presentation === 'time-date';
- return hasDatePresentation && !preferWheel;
- }
- yearValuesChanged() {
- this.parsedYearValues = convertToArrayOfNumbers(this.yearValues);
- }
- monthValuesChanged() {
- this.parsedMonthValues = convertToArrayOfNumbers(this.monthValues);
- }
- dayValuesChanged() {
- this.parsedDayValues = convertToArrayOfNumbers(this.dayValues);
- }
- hourValuesChanged() {
- this.parsedHourValues = convertToArrayOfNumbers(this.hourValues);
- }
- minuteValuesChanged() {
- this.parsedMinuteValues = convertToArrayOfNumbers(this.minuteValues);
- }
- /**
- * Update the datetime value when the value changes
- */
- async valueChanged() {
- const { value } = this;
- if (this.hasValue()) {
- this.processValue(value);
- }
- this.emitStyle();
- this.ionValueChange.emit({ value });
- }
- /**
- * Confirms the selected datetime value, updates the
- * `value` property, and optionally closes the popover
- * or modal that the datetime was presented in.
- */
- async confirm(closeOverlay = false) {
- const { isCalendarPicker, activeParts, preferWheel, workingParts } = this;
- /**
- * We only update the value if the presentation is not a calendar picker.
- */
- if (activeParts !== undefined || !isCalendarPicker) {
- const activePartsIsArray = Array.isArray(activeParts);
- if (activePartsIsArray && activeParts.length === 0) {
- if (preferWheel) {
- /**
- * If the datetime is using a wheel picker, but the
- * active parts are empty, then the user has confirmed the
- * initial value (working parts) presented to them.
- */
- this.setValue(convertDataToISO(workingParts));
- }
- else {
- this.setValue(undefined);
- }
- }
- else {
- this.setValue(convertDataToISO(activeParts));
- }
- }
- if (closeOverlay) {
- this.closeParentOverlay(CONFIRM_ROLE);
- }
- }
- /**
- * Resets the internal state of the datetime but does not update the value.
- * Passing a valid ISO-8601 string will reset the state of the component to the provided date.
- * If no value is provided, the internal state will be reset to the clamped value of the min, max and today.
- */
- async reset(startDate) {
- this.processValue(startDate);
- }
- /**
- * Emits the ionCancel event and
- * optionally closes the popover
- * or modal that the datetime was
- * presented in.
- */
- async cancel(closeOverlay = false) {
- this.ionCancel.emit();
- if (closeOverlay) {
- this.closeParentOverlay(CANCEL_ROLE);
- }
- }
- get isCalendarPicker() {
- const { presentation } = this;
- return presentation === 'date' || presentation === 'date-time' || presentation === 'time-date';
- }
- connectedCallback() {
- this.clearFocusVisible = startFocusVisible(this.el).destroy;
- }
- disconnectedCallback() {
- if (this.clearFocusVisible) {
- this.clearFocusVisible();
- this.clearFocusVisible = undefined;
- }
- }
- initializeListeners() {
- this.initializeCalendarListener();
- this.initializeKeyboardListeners();
- }
- componentDidLoad() {
- const { el, intersectionTrackerRef } = this;
- /**
- * If a scrollable element is hidden using `display: none`,
- * it will not have a scroll height meaning we cannot scroll elements
- * into view. As a result, we will need to wait for the datetime to become
- * visible if used inside of a modal or a popover otherwise the scrollable
- * areas will not have the correct values snapped into place.
- */
- const visibleCallback = (entries) => {
- const ev = entries[0];
- if (!ev.isIntersecting) {
- return;
- }
- this.initializeListeners();
- /**
- * TODO FW-2793: Datetime needs a frame to ensure that it
- * can properly scroll contents into view. As a result
- * we hide the scrollable content until after that frame
- * so users do not see the content quickly shifting. The downside
- * is that the content will pop into view a frame after. Maybe there
- * is a better way to handle this?
- */
- writeTask(() => {
- this.el.classList.add('datetime-ready');
- });
- };
- const visibleIO = new IntersectionObserver(visibleCallback, { threshold: 0.01, root: el });
- /**
- * Use raf to avoid a race condition between the component loading and
- * its display animation starting (such as when shown in a modal). This
- * could cause the datetime to start at a visibility of 0, erroneously
- * triggering the `hiddenIO` observer below.
- */
- raf(() => visibleIO === null || visibleIO === void 0 ? void 0 : visibleIO.observe(intersectionTrackerRef));
- /**
- * We need to clean up listeners when the datetime is hidden
- * in a popover/modal so that we can properly scroll containers
- * back into view if they are re-presented. When the datetime is hidden
- * the scroll areas have scroll widths/heights of 0px, so any snapping
- * we did originally has been lost.
- */
- const hiddenCallback = (entries) => {
- const ev = entries[0];
- if (ev.isIntersecting) {
- return;
- }
- this.destroyInteractionListeners();
- /**
- * When datetime is hidden, we need to make sure that
- * the month/year picker is closed. Otherwise,
- * it will be open when the datetime re-appears
- * and the scroll area of the calendar grid will be 0.
- * As a result, the wrong month will be shown.
- */
- this.showMonthAndYear = false;
- writeTask(() => {
- this.el.classList.remove('datetime-ready');
- });
- };
- const hiddenIO = new IntersectionObserver(hiddenCallback, { threshold: 0, root: el });
- raf(() => hiddenIO === null || hiddenIO === void 0 ? void 0 : hiddenIO.observe(intersectionTrackerRef));
- /**
- * Datetime uses Ionic components that emit
- * ionFocus and ionBlur. These events are
- * composed meaning they will cross
- * the shadow dom boundary. We need to
- * stop propagation on these events otherwise
- * developers will see 2 ionFocus or 2 ionBlur
- * events at a time.
- */
- const root = getElementRoot(this.el);
- root.addEventListener('ionFocus', (ev) => ev.stopPropagation());
- root.addEventListener('ionBlur', (ev) => ev.stopPropagation());
- }
- /**
- * When the presentation is changed, all calendar content is recreated,
- * so we need to re-init behavior with the new elements.
- */
- componentDidRender() {
- const { presentation, prevPresentation, calendarBodyRef, minParts, preferWheel, forceRenderDate } = this;
- /**
- * TODO(FW-2165)
- * Remove this when https://bugs.webkit.org/show_bug.cgi?id=235960 is fixed.
- * When using `min`, we add `scroll-snap-align: none`
- * to the disabled month so that users cannot scroll to it.
- * This triggers a bug in WebKit where the scroll position is reset.
- * Since the month change logic is handled by a scroll listener,
- * this causes the month to change leading to `scroll-snap-align`
- * changing again, thus changing the scroll position again and causing
- * an infinite loop.
- * This issue only applies to the calendar grid, so we can disable
- * it if the calendar grid is not being used.
- */
- const hasCalendarGrid = !preferWheel && ['date-time', 'time-date', 'date'].includes(presentation);
- if (minParts !== undefined && hasCalendarGrid && calendarBodyRef) {
- const workingMonth = calendarBodyRef.querySelector('.calendar-month:nth-of-type(1)');
- /**
- * We need to make sure the datetime is not in the process
- * of scrolling to a new datetime value if the value
- * is updated programmatically.
- * Otherwise, the datetime will appear to not scroll at all because
- * we are resetting the scroll position to the center of the view.
- * Prior to the datetime's value being updated programmatically,
- * the calendarBodyRef is scrolled such that the middle month is centered
- * in the view. The below code updates the scroll position so the middle
- * month is also centered in the view. Since the scroll position did not change,
- * the scroll callback in this file does not fire,
- * and the resolveForceDateScrolling promise never resolves.
- */
- if (workingMonth && forceRenderDate === undefined) {
- calendarBodyRef.scrollLeft = workingMonth.clientWidth * (isRTL(this.el) ? -1 : 1);
- }
- }
- if (prevPresentation === null) {
- this.prevPresentation = presentation;
- return;
- }
- if (presentation === prevPresentation) {
- return;
- }
- this.prevPresentation = presentation;
- this.destroyInteractionListeners();
- this.initializeListeners();
- /**
- * The month/year picker from the date interface
- * should be closed as it is not available in non-date
- * interfaces.
- */
- this.showMonthAndYear = false;
- raf(() => {
- this.ionRender.emit();
- });
- }
- componentWillLoad() {
- const { el, formatOptions, highlightedDates, multiple, presentation, preferWheel } = this;
- if (multiple) {
- if (presentation !== 'date') {
- printIonWarning('[ion-datetime] - Multiple date selection is only supported for presentation="date".', el);
- }
- if (preferWheel) {
- printIonWarning('[ion-datetime] - Multiple date selection is not supported with preferWheel="true".', el);
- }
- }
- if (highlightedDates !== undefined) {
- if (presentation !== 'date' && presentation !== 'date-time' && presentation !== 'time-date') {
- printIonWarning('[ion-datetime] - The highlightedDates property is only supported with the date, date-time, and time-date presentations.', el);
- }
- if (preferWheel) {
- printIonWarning('[ion-datetime] - The highlightedDates property is not supported with preferWheel="true".', el);
- }
- }
- if (formatOptions) {
- checkForPresentationFormatMismatch(el, presentation, formatOptions);
- warnIfTimeZoneProvided(el, formatOptions);
- }
- const hourValues = (this.parsedHourValues = convertToArrayOfNumbers(this.hourValues));
- const minuteValues = (this.parsedMinuteValues = convertToArrayOfNumbers(this.minuteValues));
- const monthValues = (this.parsedMonthValues = convertToArrayOfNumbers(this.monthValues));
- const yearValues = (this.parsedYearValues = convertToArrayOfNumbers(this.yearValues));
- const dayValues = (this.parsedDayValues = convertToArrayOfNumbers(this.dayValues));
- const todayParts = (this.todayParts = parseDate(getToday()));
- this.processMinParts();
- this.processMaxParts();
- this.defaultParts = getClosestValidDate({
- refParts: todayParts,
- monthValues,
- dayValues,
- yearValues,
- hourValues,
- minuteValues,
- minParts: this.minParts,
- maxParts: this.maxParts,
- });
- this.processValue(this.value);
- this.emitStyle();
- }
- emitStyle() {
- this.ionStyle.emit({
- interactive: true,
- datetime: true,
- 'interactive-disabled': this.disabled,
- });
- }
- /**
- * Universal render methods
- * These are pieces of datetime that
- * are rendered independently of presentation.
- */
- renderFooter() {
- const { disabled, readonly, showDefaultButtons, showClearButton } = this;
- /**
- * The cancel, clear, and confirm buttons
- * should not be interactive if the datetime
- * is disabled or readonly.
- */
- const isButtonDisabled = disabled || readonly;
- const hasSlottedButtons = this.el.querySelector('[slot="buttons"]') !== null;
- if (!hasSlottedButtons && !showDefaultButtons && !showClearButton) {
- return;
- }
- const clearButtonClick = () => {
- this.reset();
- this.setValue(undefined);
- };
- /**
- * By default we render two buttons:
- * Cancel - Dismisses the datetime and
- * does not update the `value` prop.
- * OK - Dismisses the datetime and
- * updates the `value` prop.
- */
- return (h("div", { class: "datetime-footer" }, h("div", { class: "datetime-buttons" }, h("div", { class: {
- ['datetime-action-buttons']: true,
- ['has-clear-button']: this.showClearButton,
- } }, h("slot", { name: "buttons" }, h("ion-buttons", null, showDefaultButtons && (h("ion-button", { id: "cancel-button", color: this.color, onClick: () => this.cancel(true), disabled: isButtonDisabled }, this.cancelText)), h("div", { class: "datetime-action-buttons-container" }, showClearButton && (h("ion-button", { id: "clear-button", color: this.color, onClick: () => clearButtonClick(), disabled: isButtonDisabled }, this.clearText)), showDefaultButtons && (h("ion-button", { id: "confirm-button", color: this.color, onClick: () => this.confirm(true), disabled: isButtonDisabled }, this.doneText)))))))));
- }
- /**
- * Wheel picker render methods
- */
- renderWheelPicker(forcePresentation = this.presentation) {
- /**
- * If presentation="time-date" we switch the
- * order of the render array here instead of
- * manually reordering each date/time picker
- * column with CSS. This allows for additional
- * flexibility if we need to render subsets
- * of the date/time data or do additional ordering
- * within the child render functions.
- */
- const renderArray = forcePresentation === 'time-date'
- ? [this.renderTimePickerColumns(forcePresentation), this.renderDatePickerColumns(forcePresentation)]
- : [this.renderDatePickerColumns(forcePresentation), this.renderTimePickerColumns(forcePresentation)];
- return h("ion-picker", null, renderArray);
- }
- renderDatePickerColumns(forcePresentation) {
- return forcePresentation === 'date-time' || forcePresentation === 'time-date'
- ? this.renderCombinedDatePickerColumn()
- : this.renderIndividualDatePickerColumns(forcePresentation);
- }
- renderCombinedDatePickerColumn() {
- const { defaultParts, disabled, workingParts, locale, minParts, maxParts, todayParts, isDateEnabled } = this;
- const activePart = this.getActivePartsWithFallback();
- /**
- * By default, generate a range of 3 months:
- * Previous month, current month, and next month
- */
- const monthsToRender = generateMonths(workingParts);
- const lastMonth = monthsToRender[monthsToRender.length - 1];
- /**
- * Ensure that users can select the entire window of dates.
- */
- monthsToRender[0].day = 1;
- lastMonth.day = getNumDaysInMonth(lastMonth.month, lastMonth.year);
- /**
- * Narrow the dates rendered based on min/max dates (if any).
- * The `min` date is used if the min is after the generated min month.
- * The `max` date is used if the max is before the generated max month.
- * This ensures that the sliding window always stays at 3 months
- * but still allows future dates to be lazily rendered based on any min/max
- * constraints.
- */
- const min = minParts !== undefined && isAfter(minParts, monthsToRender[0]) ? minParts : monthsToRender[0];
- const max = maxParts !== undefined && isBefore(maxParts, lastMonth) ? maxParts : lastMonth;
- const result = getCombinedDateColumnData(locale, todayParts, min, max, this.parsedDayValues, this.parsedMonthValues);
- let items = result.items;
- const parts = result.parts;
- if (isDateEnabled) {
- items = items.map((itemObject, index) => {
- const referenceParts = parts[index];
- let disabled;
- try {
- /**
- * The `isDateEnabled` implementation is try-catch wrapped
- * to prevent exceptions in the user's function from
- * interrupting the calendar rendering.
- */
- disabled = !isDateEnabled(convertDataToISO(referenceParts));
- }
- catch (e) {
- printIonError('[ion-datetime] - Exception thrown from provided `isDateEnabled` function. Please check your function and try again.', e);
- }
- return Object.assign(Object.assign({}, itemObject), { disabled });
- });
- }
- /**
- * If we have selected a day already, then default the column
- * to that value. Otherwise, set it to the default date.
- */
- const todayString = workingParts.day !== null
- ? `${workingParts.year}-${workingParts.month}-${workingParts.day}`
- : `${defaultParts.year}-${defaultParts.month}-${defaultParts.day}`;
- return (h("ion-picker-column", { "aria-label": "Select a date", class: "date-column", color: this.color, disabled: disabled, value: todayString, onIonChange: (ev) => {
- const { value } = ev.detail;
- const findPart = parts.find(({ month, day, year }) => value === `${year}-${month}-${day}`);
- this.setWorkingParts(Object.assign(Object.assign({}, workingParts), findPart));
- this.setActiveParts(Object.assign(Object.assign({}, activePart), findPart));
- ev.stopPropagation();
- } }, items.map((item) => (h("ion-picker-column-option", { part: item.value === todayString ? `${WHEEL_ITEM_PART} ${WHEEL_ITEM_ACTIVE_PART}` : WHEEL_ITEM_PART, key: item.value, disabled: item.disabled, value: item.value }, item.text)))));
- }
- renderIndividualDatePickerColumns(forcePresentation) {
- const { workingParts, isDateEnabled } = this;
- const shouldRenderMonths = forcePresentation !== 'year' && forcePresentation !== 'time';
- const months = shouldRenderMonths
- ? getMonthColumnData(this.locale, workingParts, this.minParts, this.maxParts, this.parsedMonthValues)
- : [];
- const shouldRenderDays = forcePresentation === 'date';
- let days = shouldRenderDays
- ? getDayColumnData(this.locale, workingParts, this.minParts, this.maxParts, this.parsedDayValues)
- : [];
- if (isDateEnabled) {
- days = days.map((dayObject) => {
- const { value } = dayObject;
- const valueNum = typeof value === 'string' ? parseInt(value) : value;
- const referenceParts = {
- month: workingParts.month,
- day: valueNum,
- year: workingParts.year,
- };
- let disabled;
- try {
- /**
- * The `isDateEnabled` implementation is try-catch wrapped
- * to prevent exceptions in the user's function from
- * interrupting the calendar rendering.
- */
- disabled = !isDateEnabled(convertDataToISO(referenceParts));
- }
- catch (e) {
- printIonError('[ion-datetime] - Exception thrown from provided `isDateEnabled` function. Please check your function and try again.', e);
- }
- return Object.assign(Object.assign({}, dayObject), { disabled });
- });
- }
- const shouldRenderYears = forcePresentation !== 'month' && forcePresentation !== 'time';
- const years = shouldRenderYears
- ? getYearColumnData(this.locale, this.defaultParts, this.minParts, this.maxParts, this.parsedYearValues)
- : [];
- /**
- * Certain locales show the day before the month.
- */
- const showMonthFirst = isMonthFirstLocale(this.locale, { month: 'numeric', day: 'numeric' });
- let renderArray = [];
- if (showMonthFirst) {
- renderArray = [
- this.renderMonthPickerColumn(months),
- this.renderDayPickerColumn(days),
- this.renderYearPickerColumn(years),
- ];
- }
- else {
- renderArray = [
- this.renderDayPickerColumn(days),
- this.renderMonthPickerColumn(months),
- this.renderYearPickerColumn(years),
- ];
- }
- return renderArray;
- }
- renderDayPickerColumn(days) {
- var _a;
- if (days.length === 0) {
- return [];
- }
- const { disabled, workingParts } = this;
- const activePart = this.getActivePartsWithFallback();
- const pickerColumnValue = (_a = (workingParts.day !== null ? workingParts.day : this.defaultParts.day)) !== null && _a !== void 0 ? _a : undefined;
- return (h("ion-picker-column", { "aria-label": "Select a day", class: "day-column", color: this.color, disabled: disabled, value: pickerColumnValue, onIonChange: (ev) => {
- this.setWorkingParts(Object.assign(Object.assign({}, workingParts), { day: ev.detail.value }));
- this.setActiveParts(Object.assign(Object.assign({}, activePart), { day: ev.detail.value }));
- ev.stopPropagation();
- } }, days.map((day) => (h("ion-picker-column-option", { part: day.value === pickerColumnValue ? `${WHEEL_ITEM_PART} ${WHEEL_ITEM_ACTIVE_PART}` : WHEEL_ITEM_PART, key: day.value, disabled: day.disabled, value: day.value }, day.text)))));
- }
- renderMonthPickerColumn(months) {
- if (months.length === 0) {
- return [];
- }
- const { disabled, workingParts } = this;
- const activePart = this.getActivePartsWithFallback();
- return (h("ion-picker-column", { "aria-label": "Select a month", class: "month-column", color: this.color, disabled: disabled, value: workingParts.month, onIonChange: (ev) => {
- this.setWorkingParts(Object.assign(Object.assign({}, workingParts), { month: ev.detail.value }));
- this.setActiveParts(Object.assign(Object.assign({}, activePart), { month: ev.detail.value }));
- ev.stopPropagation();
- } }, months.map((month) => (h("ion-picker-column-option", { part: month.value === workingParts.month ? `${WHEEL_ITEM_PART} ${WHEEL_ITEM_ACTIVE_PART}` : WHEEL_ITEM_PART, key: month.value, disabled: month.disabled, value: month.value }, month.text)))));
- }
- renderYearPickerColumn(years) {
- if (years.length === 0) {
- return [];
- }
- const { disabled, workingParts } = this;
- const activePart = this.getActivePartsWithFallback();
- return (h("ion-picker-column", { "aria-label": "Select a year", class: "year-column", color: this.color, disabled: disabled, value: workingParts.year, onIonChange: (ev) => {
- this.setWorkingParts(Object.assign(Object.assign({}, workingParts), { year: ev.detail.value }));
- this.setActiveParts(Object.assign(Object.assign({}, activePart), { year: ev.detail.value }));
- ev.stopPropagation();
- } }, years.map((year) => (h("ion-picker-column-option", { part: year.value === workingParts.year ? `${WHEEL_ITEM_PART} ${WHEEL_ITEM_ACTIVE_PART}` : WHEEL_ITEM_PART, key: year.value, disabled: year.disabled, value: year.value }, year.text)))));
- }
- renderTimePickerColumns(forcePresentation) {
- if (['date', 'month', 'month-year', 'year'].includes(forcePresentation)) {
- return [];
- }
- /**
- * If a user has not selected a date,
- * then we should show all times. If the
- * user has selected a date (even if it has
- * not been confirmed yet), we should apply
- * the max and min restrictions so that the
- * time picker shows values that are
- * appropriate for the selected date.
- */
- const activePart = this.getActivePart();
- const userHasSelectedDate = activePart !== undefined;
- const { hoursData, minutesData, dayPeriodData } = getTimeColumnsData(this.locale, this.workingParts, this.hourCycle, userHasSelectedDate ? this.minParts : undefined, userHasSelectedDate ? this.maxParts : undefined, this.parsedHourValues, this.parsedMinuteValues);
- return [
- this.renderHourPickerColumn(hoursData),
- this.renderMinutePickerColumn(minutesData),
- this.renderDayPeriodPickerColumn(dayPeriodData),
- ];
- }
- renderHourPickerColumn(hoursData) {
- const { disabled, workingParts } = this;
- if (hoursData.length === 0)
- return [];
- const activePart = this.getActivePartsWithFallback();
- return (h("ion-picker-column", { "aria-label": "Select an hour", color: this.color, disabled: disabled, value: activePart.hour, numericInput: true, onIonChange: (ev) => {
- this.setWorkingParts(Object.assign(Object.assign({}, workingParts), { hour: ev.detail.value }));
- this.setActiveParts(Object.assign(Object.assign({}, this.getActivePartsWithFallback()), { hour: ev.detail.value }));
- ev.stopPropagation();
- } }, hoursData.map((hour) => (h("ion-picker-column-option", { part: hour.value === activePart.hour ? `${WHEEL_ITEM_PART} ${WHEEL_ITEM_ACTIVE_PART}` : WHEEL_ITEM_PART, key: hour.value, disabled: hour.disabled, value: hour.value }, hour.text)))));
- }
- renderMinutePickerColumn(minutesData) {
- const { disabled, workingParts } = this;
- if (minutesData.length === 0)
- return [];
- const activePart = this.getActivePartsWithFallback();
- return (h("ion-picker-column", { "aria-label": "Select a minute", color: this.color, disabled: disabled, value: activePart.minute, numericInput: true, onIonChange: (ev) => {
- this.setWorkingParts(Object.assign(Object.assign({}, workingParts), { minute: ev.detail.value }));
- this.setActiveParts(Object.assign(Object.assign({}, this.getActivePartsWithFallback()), { minute: ev.detail.value }));
- ev.stopPropagation();
- } }, minutesData.map((minute) => (h("ion-picker-column-option", { part: minute.value === activePart.minute ? `${WHEEL_ITEM_PART} ${WHEEL_ITEM_ACTIVE_PART}` : WHEEL_ITEM_PART, key: minute.value, disabled: minute.disabled, value: minute.value }, minute.text)))));
- }
- renderDayPeriodPickerColumn(dayPeriodData) {
- const { disabled, workingParts } = this;
- if (dayPeriodData.length === 0) {
- return [];
- }
- const activePart = this.getActivePartsWithFallback();
- const isDayPeriodRTL = isLocaleDayPeriodRTL(this.locale);
- return (h("ion-picker-column", { "aria-label": "Select a day period", style: isDayPeriodRTL ? { order: '-1' } : {}, color: this.color, disabled: disabled, value: activePart.ampm, onIonChange: (ev) => {
- const hour = calculateHourFromAMPM(workingParts, ev.detail.value);
- this.setWorkingParts(Object.assign(Object.assign({}, workingParts), { ampm: ev.detail.value, hour }));
- this.setActiveParts(Object.assign(Object.assign({}, this.getActivePartsWithFallback()), { ampm: ev.detail.value, hour }));
- ev.stopPropagation();
- } }, dayPeriodData.map((dayPeriod) => (h("ion-picker-column-option", { part: dayPeriod.value === activePart.ampm ? `${WHEEL_ITEM_PART} ${WHEEL_ITEM_ACTIVE_PART}` : WHEEL_ITEM_PART, key: dayPeriod.value, disabled: dayPeriod.disabled, value: dayPeriod.value }, dayPeriod.text)))));
- }
- renderWheelView(forcePresentation) {
- const { locale } = this;
- const showMonthFirst = isMonthFirstLocale(locale);
- const columnOrder = showMonthFirst ? 'month-first' : 'year-first';
- return (h("div", { class: {
- [`wheel-order-${columnOrder}`]: true,
- } }, this.renderWheelPicker(forcePresentation)));
- }
- /**
- * Grid Render Methods
- */
- renderCalendarHeader(mode) {
- const { disabled } = this;
- const expandedIcon = mode === 'ios' ? chevronDown : caretUpSharp;
- const collapsedIcon = mode === 'ios' ? chevronForward : caretDownSharp;
- const prevMonthDisabled = disabled || isPrevMonthDisabled(this.workingParts, this.minParts, this.maxParts);
- const nextMonthDisabled = disabled || isNextMonthDisabled(this.workingParts, this.maxParts);
- // don't use the inheritAttributes util because it removes dir from the host, and we still need that
- const hostDir = this.el.getAttribute('dir') || undefined;
- return (h("div", { class: "calendar-header" }, h("div", { class: "calendar-action-buttons" }, h("div", { class: "calendar-month-year" }, h("button", { class: {
- 'calendar-month-year-toggle': true,
- 'ion-activatable': true,
- 'ion-focusable': true,
- }, part: "month-year-button", disabled: disabled, "aria-label": this.showMonthAndYear ? 'Hide year picker' : 'Show year picker', onClick: () => this.toggleMonthAndYearView() }, h("span", { id: "toggle-wrapper" }, getMonthAndYear(this.locale, this.workingParts), h("ion-icon", { "aria-hidden": "true", icon: this.showMonthAndYear ? expandedIcon : collapsedIcon, lazy: false, flipRtl: true })), mode === 'md' && h("ion-ripple-effect", null))), h("div", { class: "calendar-next-prev" }, h("ion-buttons", null, h("ion-button", { "aria-label": "Previous month", disabled: prevMonthDisabled, onClick: () => this.prevMonth() }, h("ion-icon", { dir: hostDir, "aria-hidden": "true", slot: "icon-only", icon: chevronBack, lazy: false, flipRtl: true })), h("ion-button", { "aria-label": "Next month", disabled: nextMonthDisabled, onClick: () => this.nextMonth() }, h("ion-icon", { dir: hostDir, "aria-hidden": "true", slot: "icon-only", icon: chevronForward, lazy: false, flipRtl: true }))))), h("div", { class: "calendar-days-of-week", "aria-hidden": "true" }, getDaysOfWeek(this.locale, mode, this.firstDayOfWeek % 7).map((d) => {
- return h("div", { class: "day-of-week" }, d);
- }))));
- }
- renderMonth(month, year) {
- const { disabled, readonly } = this;
- const yearAllowed = this.parsedYearValues === undefined || this.parsedYearValues.includes(year);
- const monthAllowed = this.parsedMonthValues === undefined || this.parsedMonthValues.includes(month);
- const isCalMonthDisabled = !yearAllowed || !monthAllowed;
- const isDatetimeDisabled = disabled || readonly;
- const swipeDisabled = disabled ||
- isMonthDisabled({
- month,
- year,
- day: null,
- }, {
- // The day is not used when checking if a month is disabled.
- // Users should be able to access the min or max month, even if the
- // min/max date is out of bounds (e.g. min is set to Feb 15, Feb should not be disabled).
- minParts: Object.assign(Object.assign({}, this.minParts), { day: null }),
- maxParts: Object.assign(Object.assign({}, this.maxParts), { day: null }),
- });
- // The working month should never have swipe disabled.
- // Otherwise the CSS scroll snap will not work and the user
- // can free-scroll the calendar.
- const isWorkingMonth = this.workingParts.month === month && this.workingParts.year === year;
- const activePart = this.getActivePartsWithFallback();
- return (h("div", { "aria-hidden": !isWorkingMonth ? 'true' : null, class: {
- 'calendar-month': true,
- // Prevents scroll snap swipe gestures for months outside of the min/max bounds
- 'calendar-month-disabled': !isWorkingMonth && swipeDisabled,
- } }, h("div", { class: "calendar-month-grid" }, getDaysOfMonth(month, year, this.firstDayOfWeek % 7).map((dateObject, index) => {
- const { day, dayOfWeek } = dateObject;
- const { el, highlightedDates, isDateEnabled, multiple } = this;
- const referenceParts = { month, day, year };
- const isCalendarPadding = day === null;
- const { isActive, isToday, ariaLabel, ariaSelected, disabled: isDayDisabled, text, } = getCalendarDayState(this.locale, referenceParts, this.activeParts, this.todayParts, this.minParts, this.maxParts, this.parsedDayValues);
- const dateIsoString = convertDataToISO(referenceParts);
- let isCalDayDisabled = isCalMonthDisabled || isDayDisabled;
- if (!isCalDayDisabled && isDateEnabled !== undefined) {
- try {
- /**
- * The `isDateEnabled` implementation is try-catch wrapped
- * to prevent exceptions in the user's function from
- * interrupting the calendar rendering.
- */
- isCalDayDisabled = !isDateEnabled(dateIsoString);
- }
- catch (e) {
- printIonError('[ion-datetime] - Exception thrown from provided `isDateEnabled` function. Please check your function and try again.', el, e);
- }
- }
- /**
- * Some days are constrained through max & min or allowed dates
- * and also disabled because the component is readonly or disabled.
- * These need to be displayed differently.
- */
- const isCalDayConstrained = isCalDayDisabled && isDatetimeDisabled;
- const isButtonDisabled = isCalDayDisabled || isDatetimeDisabled;
- let dateStyle = undefined;
- /**
- * Custom highlight styles should not override the style for selected dates,
- * nor apply to "filler days" at the start of the grid.
- */
- if (highlightedDates !== undefined && !isActive && day !== null) {
- dateStyle = getHighlightStyles(highlightedDates, dateIsoString, el);
- }
- let dateParts = undefined;
- // "Filler days" at the beginning of the grid should not get the calendar day
- // CSS parts added to them
- if (!isCalendarPadding) {
- dateParts = `calendar-day${isActive ? ' active' : ''}${isToday ? ' today' : ''}${isCalDayDisabled ? ' disabled' : ''}`;
- }
- return (h("div", { class: "calendar-day-wrapper" }, h("button", {
- // We need to use !important for the inline styles here because
- // otherwise the CSS shadow parts will override these styles.
- // See https://github.com/WICG/webcomponents/issues/847
- // Both the CSS shadow parts and highlightedDates styles are
- // provided by the developer, but highlightedDates styles should
- // always take priority.
- ref: (el) => {
- if (el) {
- el.style.setProperty('color', `${dateStyle ? dateStyle.textColor : ''}`, 'important');
- el.style.setProperty('background-color', `${dateStyle ? dateStyle.backgroundColor : ''}`, 'important');
- }
- }, tabindex: "-1", "data-day": day, "data-month": month, "data-year": year, "data-index": index, "data-day-of-week": dayOfWeek, disabled: isButtonDisabled, class: {
- 'calendar-day-padding': isCalendarPadding,
- 'calendar-day': true,
- 'calendar-day-active': isActive,
- 'calendar-day-constrained': isCalDayConstrained,
- 'calendar-day-today': isToday,
- }, part: dateParts, "aria-hidden": isCalendarPadding ? 'true' : null, "aria-selected": ariaSelected, "aria-label": ariaLabel, onClick: () => {
- if (isCalendarPadding) {
- return;
- }
- this.setWorkingParts(Object.assign(Object.assign({}, this.workingParts), { month,
- day,
- year }));
- // multiple only needs date info, so we can wipe out other fields like time
- if (multiple) {
- this.setActiveParts({
- month,
- day,
- year,
- }, isActive);
- }
- else {
- this.setActiveParts(Object.assign(Object.assign({}, activePart), { month,
- day,
- year }));
- }
- }
- }, text)));
- }))));
- }
- renderCalendarBody() {
- return (h("div", { class: "calendar-body ion-focusable", ref: (el) => (this.calendarBodyRef = el), tabindex: "0" }, generateMonths(this.workingParts, this.forceRenderDate).map(({ month, year }) => {
- return this.renderMonth(month, year);
- })));
- }
- renderCalendar(mode) {
- return (h("div", { class: "datetime-calendar", key: "datetime-calendar" }, this.renderCalendarHeader(mode), this.renderCalendarBody()));
- }
- renderTimeLabel() {
- const hasSlottedTimeLabel = this.el.querySelector('[slot="time-label"]') !== null;
- if (!hasSlottedTimeLabel && !this.showDefaultTimeLabel) {
- return;
- }
- return h("slot", { name: "time-label" }, "Time");
- }
- renderTimeOverlay() {
- const { disabled, hourCycle, isTimePopoverOpen, locale, formatOptions } = this;
- const computedHourCycle = getHourCycle(locale, hourCycle);
- const activePart = this.getActivePartsWithFallback();
- return [
- h("div", { class: "time-header" }, this.renderTimeLabel()),
- h("button", { class: {
- 'time-body': true,
- 'time-body-active': isTimePopoverOpen,
- }, part: `time-button${isTimePopoverOpen ? ' active' : ''}`, "aria-expanded": "false", "aria-haspopup": "true", disabled: disabled, onClick: async (ev) => {
- const { popoverRef } = this;
- if (popoverRef) {
- this.isTimePopoverOpen = true;
- popoverRef.present(new CustomEvent('ionShadowTarget', {
- detail: {
- ionShadowTarget: ev.target,
- },
- }));
- await popoverRef.onWillDismiss();
- this.isTimePopoverOpen = false;
- }
- } }, getLocalizedTime(locale, activePart, computedHourCycle, formatOptions === null || formatOptions === void 0 ? void 0 : formatOptions.time)),
- h("ion-popover", { alignment: "center", translucent: true, overlayIndex: 1, arrow: false, onWillPresent: (ev) => {
- /**
- * Intersection Observers do not consistently fire between Blink and Webkit
- * when toggling the visibility of the popover and trying to scroll the picker
- * column to the correct time value.
- *
- * This will correctly scroll the element position to the correct time value,
- * before the popover is fully presented.
- */
- const cols = ev.target.querySelectorAll('ion-picker-column');
- // TODO (FW-615): Potentially remove this when intersection observers are fixed in picker column
- cols.forEach((col) => col.scrollActiveItemIntoView());
- }, style: {
- '--offset-y': '-10px',
- '--min-width': 'fit-content',
- },
- // Allow native browser keyboard events to support up/down/home/end key
- // navigation within the time picker.
- keyboardEvents: true, ref: (el) => (this.popoverRef = el) }, this.renderWheelPicker('time')),
- ];
- }
- getHeaderSelectedDateText() {
- var _a;
- const { activeParts, formatOptions, multiple, titleSelectedDatesFormatter } = this;
- const isArray = Array.isArray(activeParts);
- let headerText;
- if (multiple && isArray && activeParts.length !== 1) {
- headerText = `${activeParts.length} days`; // default/fallback for multiple selection
- if (titleSelectedDatesFormatter !== undefined) {
- try {
- headerText = titleSelectedDatesFormatter(convertDataToISO(activeParts));
- }
- catch (e) {
- printIonError('[ion-datetime] - Exception in provided `titleSelectedDatesFormatter`:', e);
- }
- }
- }
- else {
- // for exactly 1 day selected (multiple set or not), show a formatted version of that
- headerText = getLocalizedDateTime(this.locale, this.getActivePartsWithFallback(), (_a = formatOptions === null || formatOptions === void 0 ? void 0 : formatOptions.date) !== null && _a !== void 0 ? _a : { weekday: 'short', month: 'short', day: 'numeric' });
- }
- return headerText;
- }
- renderHeader(showExpandedHeader = true) {
- const hasSlottedTitle = this.el.querySelector('[slot="title"]') !== null;
- if (!hasSlottedTitle && !this.showDefaultTitle) {
- return;
- }
- return (h("div", { class: "datetime-header" }, h("div", { class: "datetime-title" }, h("slot", { name: "title" }, "Select Date")), showExpandedHeader && h("div", { class: "datetime-selected-date" }, this.getHeaderSelectedDateText())));
- }
- /**
- * Render time picker inside of datetime.
- * Do not pass color prop to segment on
- * iOS mode. MD segment has been customized and
- * should take on the color prop, but iOS
- * should just be the default segment.
- */
- renderTime() {
- const { presentation } = this;
- const timeOnlyPresentation = presentation === 'time';
- return (h("div", { class: "datetime-time" }, timeOnlyPresentation ? this.renderWheelPicker() : this.renderTimeOverlay()));
- }
- /**
- * Renders the month/year picker that is
- * displayed on the calendar grid.
- * The .datetime-year class has additional
- * styles that let us show/hide the
- * picker when the user clicks on the
- * toggle in the calendar header.
- */
- renderCalendarViewMonthYearPicker() {
- return h("div", { class: "datetime-year" }, this.renderWheelView('month-year'));
- }
- /**
- * Render entry point
- * All presentation types are rendered from here.
- */
- renderDatetime(mode) {
- const { presentation, preferWheel } = this;
- /**
- * Certain presentation types have separate grid and wheel displays.
- * If preferWheel is true then we should show a wheel picker instead.
- */
- const hasWheelVariant = presentation === 'date' || presentation === 'date-time' || presentation === 'time-date';
- if (preferWheel && hasWheelVariant) {
- return [this.renderHeader(false), this.renderWheelView(), this.renderFooter()];
- }
- switch (presentation) {
- case 'date-time':
- return [
- this.renderHeader(),
- this.renderCalendar(mode),
- this.renderCalendarViewMonthYearPicker(),
- this.renderTime(),
- this.renderFooter(),
- ];
- case 'time-date':
- return [
- this.renderHeader(),
- this.renderTime(),
- this.renderCalendar(mode),
- this.renderCalendarViewMonthYearPicker(),
- this.renderFooter(),
- ];
- case 'time':
- return [this.renderHeader(false), this.renderTime(), this.renderFooter()];
- case 'month':
- case 'month-year':
- case 'year':
- return [this.renderHeader(false), this.renderWheelView(), this.renderFooter()];
- default:
- return [
- this.renderHeader(),
- this.renderCalendar(mode),
- this.renderCalendarViewMonthYearPicker(),
- this.renderFooter(),
- ];
- }
- }
- render() {
- const { name, value, disabled, el, color, readonly, showMonthAndYear, preferWheel, presentation, size, isGridStyle, } = this;
- const mode = getIonMode(this);
- const isMonthAndYearPresentation = presentation === 'year' || presentation === 'month' || presentation === 'month-year';
- const shouldShowMonthAndYear = showMonthAndYear || isMonthAndYearPresentation;
- const monthYearPickerOpen = showMonthAndYear && !isMonthAndYearPresentation;
- const hasDatePresentation = presentation === 'date' || presentation === 'date-time' || presentation === 'time-date';
- const hasWheelVariant = hasDatePresentation && preferWheel;
- renderHiddenInput(true, el, name, formatValue(value), disabled);
- return (h(Host, { key: 'c3dfea8f46fcbcef38eb9e8a69b1b46a4e4b82fd', "aria-disabled": disabled ? 'true' : null, onFocus: this.onFocus, onBlur: this.onBlur, class: Object.assign({}, createColorClasses(color, {
- [mode]: true,
- ['datetime-readonly']: readonly,
- ['datetime-disabled']: disabled,
- 'show-month-and-year': shouldShowMonthAndYear,
- 'month-year-picker-open': monthYearPickerOpen,
- [`datetime-presentation-${presentation}`]: true,
- [`datetime-size-${size}`]: true,
- [`datetime-prefer-wheel`]: hasWheelVariant,
- [`datetime-grid`]: isGridStyle,
- })) }, h("div", { key: '75c91243cf6a51f44b83d7cf7d8c0c96bfd3c83f', class: "intersection-tracker", ref: (el) => (this.intersectionTrackerRef = el) }), this.renderDatetime(mode)));
- }
- get el() { return this; }
- static get watchers() { return {
- "formatOptions": ["formatOptionsChanged"],
- "disabled": ["disabledChanged"],
- "min": ["minChanged"],
- "max": ["maxChanged"],
- "presentation": ["presentationChanged"],
- "yearValues": ["yearValuesChanged"],
- "monthValues": ["monthValuesChanged"],
- "dayValues": ["dayValuesChanged"],
- "hourValues": ["hourValuesChanged"],
- "minuteValues": ["minuteValuesChanged"],
- "value": ["valueChanged"]
- }; }
- static get style() { return {
- ios: IonDatetimeIosStyle0,
- md: IonDatetimeMdStyle0
- }; }
- }, [33, "ion-datetime", {
- "color": [1],
- "name": [1],
- "disabled": [4],
- "formatOptions": [16],
- "readonly": [4],
- "isDateEnabled": [16],
- "min": [1025],
- "max": [1025],
- "presentation": [1],
- "cancelText": [1, "cancel-text"],
- "doneText": [1, "done-text"],
- "clearText": [1, "clear-text"],
- "yearValues": [8, "year-values"],
- "monthValues": [8, "month-values"],
- "dayValues": [8, "day-values"],
- "hourValues": [8, "hour-values"],
- "minuteValues": [8, "minute-values"],
- "locale": [1],
- "firstDayOfWeek": [2, "first-day-of-week"],
- "titleSelectedDatesFormatter": [16],
- "multiple": [4],
- "highlightedDates": [16],
- "value": [1025],
- "showDefaultTitle": [4, "show-default-title"],
- "showDefaultButtons": [4, "show-default-buttons"],
- "showClearButton": [4, "show-clear-button"],
- "showDefaultTimeLabel": [4, "show-default-time-label"],
- "hourCycle": [1, "hour-cycle"],
- "size": [1],
- "preferWheel": [4, "prefer-wheel"],
- "showMonthAndYear": [32],
- "activeParts": [32],
- "workingParts": [32],
- "isTimePopoverOpen": [32],
- "forceRenderDate": [32],
- "confirm": [64],
- "reset": [64],
- "cancel": [64]
- }, undefined, {
- "formatOptions": ["formatOptionsChanged"],
- "disabled": ["disabledChanged"],
- "min": ["minChanged"],
- "max": ["maxChanged"],
- "presentation": ["presentationChanged"],
- "yearValues": ["yearValuesChanged"],
- "monthValues": ["monthValuesChanged"],
- "dayValues": ["dayValuesChanged"],
- "hourValues": ["hourValuesChanged"],
- "minuteValues": ["minuteValuesChanged"],
- "value": ["valueChanged"]
- }]);
- let datetimeIds = 0;
- const CANCEL_ROLE = 'datetime-cancel';
- const CONFIRM_ROLE = 'datetime-confirm';
- const WHEEL_ITEM_PART = 'wheel-item';
- const WHEEL_ITEM_ACTIVE_PART = `active`;
- function defineCustomElement$1() {
- if (typeof customElements === "undefined") {
- return;
- }
- const components = ["ion-datetime", "ion-backdrop", "ion-button", "ion-buttons", "ion-icon", "ion-picker", "ion-picker-column", "ion-picker-column-option", "ion-popover", "ion-ripple-effect"];
- components.forEach(tagName => { switch (tagName) {
- case "ion-datetime":
- if (!customElements.get(tagName)) {
- customElements.define(tagName, Datetime);
- }
- break;
- case "ion-backdrop":
- if (!customElements.get(tagName)) {
- defineCustomElement$a();
- }
- break;
- case "ion-button":
- if (!customElements.get(tagName)) {
- defineCustomElement$9();
- }
- break;
- case "ion-buttons":
- if (!customElements.get(tagName)) {
- defineCustomElement$8();
- }
- break;
- case "ion-icon":
- if (!customElements.get(tagName)) {
- defineCustomElement$7();
- }
- break;
- case "ion-picker":
- if (!customElements.get(tagName)) {
- defineCustomElement$6();
- }
- break;
- case "ion-picker-column":
- if (!customElements.get(tagName)) {
- defineCustomElement$5();
- }
- break;
- case "ion-picker-column-option":
- if (!customElements.get(tagName)) {
- defineCustomElement$4();
- }
- break;
- case "ion-popover":
- if (!customElements.get(tagName)) {
- defineCustomElement$3();
- }
- break;
- case "ion-ripple-effect":
- if (!customElements.get(tagName)) {
- defineCustomElement$2();
- }
- break;
- } });
- }
- const IonDatetime = Datetime;
- const defineCustomElement = defineCustomElement$1;
- export { IonDatetime, defineCustomElement };
|