123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383 |
- /*!
- * (C) Ionic http://ionicframework.com - MIT License
- */
- import { proxyCustomElement, HTMLElement, h, Host } from '@stencil/core/internal/client';
- import { a as addEventListener, c as componentOnReady } from './helpers.js';
- import { p as printIonError } from './index4.js';
- import { c as createColorClasses } from './theme.js';
- import { b as getIonMode } from './ionic-global.js';
- import { s as parseDate, x as getToday, L as getHourCycle, N as getLocalizedDateTime, M as getLocalizedTime } from './data.js';
- import { d as defineCustomElement$2 } from './ripple-effect.js';
- const datetimeButtonIosCss = ":host{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-ms-flex-align:center;align-items:center;-ms-flex-pack:center;justify-content:center}:host button{border-radius:8px;-webkit-margin-start:2px;margin-inline-start:2px;-webkit-margin-end:2px;margin-inline-end:2px;margin-top:0px;margin-bottom:0px;position:relative;-webkit-transition:150ms color ease-in-out;transition:150ms color ease-in-out;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:1rem;cursor:pointer;overflow:hidden;-webkit-appearance:none;-moz-appearance:none;appearance:none}:host(.time-active) #time-button,:host(.date-active) #date-button{color:var(--ion-color-base)}:host(.datetime-button-disabled){pointer-events:none}:host(.datetime-button-disabled) button{opacity:0.4}:host button{-webkit-padding-start:13px;padding-inline-start:13px;-webkit-padding-end:13px;padding-inline-end:13px;padding-top:7px;padding-bottom:7px}:host button.ion-activated{color:var(--ion-color-step-600, var(--ion-text-color-step-400, #666666))}";
- const IonDatetimeButtonIosStyle0 = datetimeButtonIosCss;
- const datetimeButtonMdCss = ":host{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-ms-flex-align:center;align-items:center;-ms-flex-pack:center;justify-content:center}:host button{border-radius:8px;-webkit-margin-start:2px;margin-inline-start:2px;-webkit-margin-end:2px;margin-inline-end:2px;margin-top:0px;margin-bottom:0px;position:relative;-webkit-transition:150ms color ease-in-out;transition:150ms color ease-in-out;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:1rem;cursor:pointer;overflow:hidden;-webkit-appearance:none;-moz-appearance:none;appearance:none}:host(.time-active) #time-button,:host(.date-active) #date-button{color:var(--ion-color-base)}:host(.datetime-button-disabled){pointer-events:none}:host(.datetime-button-disabled) button{opacity:0.4}:host button{-webkit-padding-start:12px;padding-inline-start:12px;-webkit-padding-end:12px;padding-inline-end:12px;padding-top:6px;padding-bottom:6px}";
- const IonDatetimeButtonMdStyle0 = datetimeButtonMdCss;
- const DatetimeButton = /*@__PURE__*/ proxyCustomElement(class DatetimeButton extends HTMLElement {
- constructor() {
- super();
- this.__registerHost();
- this.__attachShadow();
- this.datetimeEl = null;
- this.overlayEl = null;
- /**
- * Accepts one or more string values and converts
- * them to DatetimeParts. This is done so datetime-button
- * can work with an array internally and not need
- * to keep checking if the datetime value is `string` or `string[]`.
- */
- this.getParsedDateValues = (value) => {
- if (value === undefined || value === null) {
- return [];
- }
- if (Array.isArray(value)) {
- return value;
- }
- return [value];
- };
- /**
- * Check the value property on the linked
- * ion-datetime and then format it according
- * to the locale specified on ion-datetime.
- */
- this.setDateTimeText = () => {
- var _a, _b, _c, _d, _e;
- const { datetimeEl, datetimePresentation } = this;
- if (!datetimeEl) {
- return;
- }
- const { value, locale, formatOptions, hourCycle, preferWheel, multiple, titleSelectedDatesFormatter } = datetimeEl;
- const parsedValues = this.getParsedDateValues(value);
- /**
- * Both ion-datetime and ion-datetime-button default
- * to today's date and time if no value is set.
- */
- const parsedDatetimes = parseDate(parsedValues.length > 0 ? parsedValues : [getToday()]);
- if (!parsedDatetimes) {
- return;
- }
- /**
- * If developers incorrectly use multiple="true"
- * with non "date" datetimes, then just select
- * the first value so the interface does
- * not appear broken. Datetime will provide a
- * warning in the console.
- */
- const firstParsedDatetime = parsedDatetimes[0];
- const computedHourCycle = getHourCycle(locale, hourCycle);
- this.dateText = this.timeText = undefined;
- switch (datetimePresentation) {
- case 'date-time':
- case 'time-date':
- const dateText = getLocalizedDateTime(locale, firstParsedDatetime, (_a = formatOptions === null || formatOptions === void 0 ? void 0 : formatOptions.date) !== null && _a !== void 0 ? _a : { month: 'short', day: 'numeric', year: 'numeric' });
- const timeText = getLocalizedTime(locale, firstParsedDatetime, computedHourCycle, formatOptions === null || formatOptions === void 0 ? void 0 : formatOptions.time);
- if (preferWheel) {
- this.dateText = `${dateText} ${timeText}`;
- }
- else {
- this.dateText = dateText;
- this.timeText = timeText;
- }
- break;
- case 'date':
- if (multiple && parsedValues.length !== 1) {
- let headerText = `${parsedValues.length} days`; // default/fallback for multiple selection
- if (titleSelectedDatesFormatter !== undefined) {
- try {
- headerText = titleSelectedDatesFormatter(parsedValues);
- }
- catch (e) {
- printIonError('[ion-datetime-button] - Exception in provided `titleSelectedDatesFormatter`:', e);
- }
- }
- this.dateText = headerText;
- }
- else {
- this.dateText = getLocalizedDateTime(locale, firstParsedDatetime, (_b = formatOptions === null || formatOptions === void 0 ? void 0 : formatOptions.date) !== null && _b !== void 0 ? _b : { month: 'short', day: 'numeric', year: 'numeric' });
- }
- break;
- case 'time':
- this.timeText = getLocalizedTime(locale, firstParsedDatetime, computedHourCycle, formatOptions === null || formatOptions === void 0 ? void 0 : formatOptions.time);
- break;
- case 'month-year':
- this.dateText = getLocalizedDateTime(locale, firstParsedDatetime, (_c = formatOptions === null || formatOptions === void 0 ? void 0 : formatOptions.date) !== null && _c !== void 0 ? _c : { month: 'long', year: 'numeric' });
- break;
- case 'month':
- this.dateText = getLocalizedDateTime(locale, firstParsedDatetime, (_d = formatOptions === null || formatOptions === void 0 ? void 0 : formatOptions.time) !== null && _d !== void 0 ? _d : { month: 'long' });
- break;
- case 'year':
- this.dateText = getLocalizedDateTime(locale, firstParsedDatetime, (_e = formatOptions === null || formatOptions === void 0 ? void 0 : formatOptions.time) !== null && _e !== void 0 ? _e : { year: 'numeric' });
- break;
- }
- };
- /**
- * Waits for the ion-datetime to re-render.
- * This is needed in order to correctly position
- * a popover relative to the trigger element.
- */
- this.waitForDatetimeChanges = async () => {
- const { datetimeEl } = this;
- if (!datetimeEl) {
- return Promise.resolve();
- }
- return new Promise((resolve) => {
- addEventListener(datetimeEl, 'ionRender', resolve, { once: true });
- });
- };
- this.handleDateClick = async (ev) => {
- const { datetimeEl, datetimePresentation } = this;
- if (!datetimeEl) {
- return;
- }
- let needsPresentationChange = false;
- /**
- * When clicking the date button,
- * we need to make sure that only a date
- * picker is displayed. For presentation styles
- * that display content other than a date picker,
- * we need to update the presentation style.
- */
- switch (datetimePresentation) {
- case 'date-time':
- case 'time-date':
- const needsChange = datetimeEl.presentation !== 'date';
- /**
- * The date+time wheel picker
- * shows date and time together,
- * so do not adjust the presentation
- * in that case.
- */
- if (!datetimeEl.preferWheel && needsChange) {
- datetimeEl.presentation = 'date';
- needsPresentationChange = true;
- }
- break;
- }
- /**
- * Track which button was clicked
- * so that it can have the correct
- * activated styles applied when
- * the modal/popover containing
- * the datetime is opened.
- */
- this.selectedButton = 'date';
- this.presentOverlay(ev, needsPresentationChange, this.dateTargetEl);
- };
- this.handleTimeClick = (ev) => {
- const { datetimeEl, datetimePresentation } = this;
- if (!datetimeEl) {
- return;
- }
- let needsPresentationChange = false;
- /**
- * When clicking the time button,
- * we need to make sure that only a time
- * picker is displayed. For presentation styles
- * that display content other than a time picker,
- * we need to update the presentation style.
- */
- switch (datetimePresentation) {
- case 'date-time':
- case 'time-date':
- const needsChange = datetimeEl.presentation !== 'time';
- if (needsChange) {
- datetimeEl.presentation = 'time';
- needsPresentationChange = true;
- }
- break;
- }
- /**
- * Track which button was clicked
- * so that it can have the correct
- * activated styles applied when
- * the modal/popover containing
- * the datetime is opened.
- */
- this.selectedButton = 'time';
- this.presentOverlay(ev, needsPresentationChange, this.timeTargetEl);
- };
- /**
- * If the datetime is presented in an
- * overlay, the datetime and overlay
- * should be appropriately sized.
- * These classes provide default sizing values
- * that developers can customize.
- * The goal is to provide an overlay that is
- * reasonably sized with a datetime that
- * fills the entire container.
- */
- this.presentOverlay = async (ev, needsPresentationChange, triggerEl) => {
- const { overlayEl } = this;
- if (!overlayEl) {
- return;
- }
- if (overlayEl.tagName === 'ION-POPOVER') {
- /**
- * When the presentation on datetime changes,
- * we need to wait for the component to re-render
- * otherwise the computed width/height of the
- * popover content will be wrong, causing
- * the popover to not align with the trigger element.
- */
- if (needsPresentationChange) {
- await this.waitForDatetimeChanges();
- }
- /**
- * We pass the trigger button element
- * so that the popover aligns with the individual
- * button that was clicked, not the component container.
- */
- overlayEl.present(Object.assign(Object.assign({}, ev), { detail: {
- ionShadowTarget: triggerEl,
- } }));
- }
- else {
- overlayEl.present();
- }
- };
- this.datetimePresentation = 'date-time';
- this.dateText = undefined;
- this.timeText = undefined;
- this.datetimeActive = false;
- this.selectedButton = undefined;
- this.color = 'primary';
- this.disabled = false;
- this.datetime = undefined;
- }
- async componentWillLoad() {
- const { datetime } = this;
- if (!datetime) {
- printIonError('[ion-datetime-button] - An ID associated with an ion-datetime instance is required to function properly.', this.el);
- return;
- }
- const datetimeEl = (this.datetimeEl = document.getElementById(datetime));
- if (!datetimeEl) {
- printIonError(`[ion-datetime-button] - No ion-datetime instance found for ID '${datetime}'.`, this.el);
- return;
- }
- /**
- * The element reference must be an ion-datetime. Print an error
- * if a non-datetime element was provided.
- */
- if (datetimeEl.tagName !== 'ION-DATETIME') {
- printIonError(`[ion-datetime-button] - Expected an ion-datetime instance for ID '${datetime}' but received '${datetimeEl.tagName.toLowerCase()}' instead.`, datetimeEl);
- return;
- }
- /**
- * Since the datetime can be used in any context (overlays, accordion, etc)
- * we track when it is visible to determine when it is active.
- * This informs which button is highlighted as well as the
- * aria-expanded state.
- */
- const io = new IntersectionObserver((entries) => {
- const ev = entries[0];
- this.datetimeActive = ev.isIntersecting;
- }, {
- threshold: 0.01,
- });
- io.observe(datetimeEl);
- /**
- * Get a reference to any modal/popover
- * the datetime is being used in so we can
- * correctly size it when it is presented.
- */
- const overlayEl = (this.overlayEl = datetimeEl.closest('ion-modal, ion-popover'));
- /**
- * The .ion-datetime-button-overlay class contains
- * styles that allow any modal/popover to be
- * sized according to the dimensions of the datetime.
- * If developers want a smaller/larger overlay all they need
- * to do is change the width/height of the datetime.
- * Additionally, this lets us avoid having to set
- * explicit widths on each variant of datetime.
- */
- if (overlayEl) {
- overlayEl.classList.add('ion-datetime-button-overlay');
- }
- componentOnReady(datetimeEl, () => {
- const datetimePresentation = (this.datetimePresentation = datetimeEl.presentation || 'date-time');
- /**
- * Set the initial display
- * in the rendered buttons.
- *
- * From there, we need to listen
- * for ionChange to be emitted
- * from datetime so we know when
- * to re-render the displayed
- * text in the buttons.
- */
- this.setDateTimeText();
- addEventListener(datetimeEl, 'ionValueChange', this.setDateTimeText);
- /**
- * Configure the initial selected button
- * in the event that the datetime is displayed
- * without clicking one of the datetime buttons.
- * For example, a datetime could be expanded
- * in an accordion. In this case users only
- * need to click the accordion header to show
- * the datetime.
- */
- switch (datetimePresentation) {
- case 'date-time':
- case 'date':
- case 'month-year':
- case 'month':
- case 'year':
- this.selectedButton = 'date';
- break;
- case 'time-date':
- case 'time':
- this.selectedButton = 'time';
- break;
- }
- });
- }
- render() {
- const { color, dateText, timeText, selectedButton, datetimeActive, disabled } = this;
- const mode = getIonMode(this);
- return (h(Host, { key: '11d037e6ab061e5116842970760b04850b42f2c7', class: createColorClasses(color, {
- [mode]: true,
- [`${selectedButton}-active`]: datetimeActive,
- ['datetime-button-disabled']: disabled,
- }) }, dateText && (h("button", { key: '08ecb62da0fcbf7466a1f2403276712a3ff17fbc', class: "ion-activatable", id: "date-button", "aria-expanded": datetimeActive ? 'true' : 'false', onClick: this.handleDateClick, disabled: disabled, part: "native", ref: (el) => (this.dateTargetEl = el) }, h("slot", { key: '1c04853d4d23c0f1a594602bde44511c98355644', name: "date-target" }, dateText), mode === 'md' && h("ion-ripple-effect", { key: '5fc566cd4bc885bcf983ce99e3dc65d7f485bf9b' }))), timeText && (h("button", { key: 'c9c5c34ac338badf8659da22bea5829d62c51169', class: "ion-activatable", id: "time-button", "aria-expanded": datetimeActive ? 'true' : 'false', onClick: this.handleTimeClick, disabled: disabled, part: "native", ref: (el) => (this.timeTargetEl = el) }, h("slot", { key: '147a9d2069dbf737f6fc64787823d6d5af5aa653', name: "time-target" }, timeText), mode === 'md' && h("ion-ripple-effect", { key: '70a5e25b75ed90ac6bba003468435f67aa9d8f0a' })))));
- }
- get el() { return this; }
- static get style() { return {
- ios: IonDatetimeButtonIosStyle0,
- md: IonDatetimeButtonMdStyle0
- }; }
- }, [33, "ion-datetime-button", {
- "color": [513],
- "disabled": [516],
- "datetime": [1],
- "datetimePresentation": [32],
- "dateText": [32],
- "timeText": [32],
- "datetimeActive": [32],
- "selectedButton": [32]
- }]);
- function defineCustomElement$1() {
- if (typeof customElements === "undefined") {
- return;
- }
- const components = ["ion-datetime-button", "ion-ripple-effect"];
- components.forEach(tagName => { switch (tagName) {
- case "ion-datetime-button":
- if (!customElements.get(tagName)) {
- customElements.define(tagName, DatetimeButton);
- }
- break;
- case "ion-ripple-effect":
- if (!customElements.get(tagName)) {
- defineCustomElement$2();
- }
- break;
- } });
- }
- const IonDatetimeButton = DatetimeButton;
- const defineCustomElement = defineCustomElement$1;
- export { IonDatetimeButton, defineCustomElement };
|