@salla.sa/twilight-components
Version:
Salla Web Component
748 lines (736 loc) • 134 kB
JavaScript
/*!
* Crafted with ❤ by Salla
*/
'use strict';
var index = require('./index-C7gO-zm5.js');
var calendar = require('./calendar-D-PUoCDH.js');
var keyboard_arrow_down = require('./keyboard_arrow_down-DHJ3FFZq.js');
var minus = require('./minus-CCryh1qf.js');
var Helper = require('./Helper-CU4Xuiki.js');
require('./anime.es-BqW8JHZi.js');
function _interopNamespace(e) {
if (e && e.__esModule) return e;
var n = Object.create(null);
if (e) {
Object.keys(e).forEach(function (k) {
if (k !== 'default') {
var d = Object.getOwnPropertyDescriptor(e, k);
Object.defineProperty(n, k, d.get ? d : {
enumerable: true,
get: function () { return e[k]; }
});
}
});
}
n.default = e;
return Object.freeze(n);
}
var BookingTime = `<!-- Generated by IcoMoon.io -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
<title>calendar-time</title>
<path d="M22.667 17.333c-0.737 0-1.333 0.596-1.333 1.333v2.667h-2.667c-0.737 0-1.333 0.596-1.333 1.333s0.596 1.333 1.333 1.333h4c0.737 0 1.333-0.596 1.333-1.333v-4c0-0.737-0.596-1.333-1.333-1.333zM28 2.667h-2.667v-1.333c0-0.736-0.596-1.333-1.333-1.333s-1.333 0.597-1.333 1.333v1.333h-13.333v-1.333c0-0.736-0.596-1.333-1.333-1.333s-1.333 0.597-1.333 1.333v1.333h-2.667c-2.205 0-4 1.795-4 4v21.333c0 2.205 1.795 4 4 4h5.363c0.737 0 1.333-0.596 1.333-1.333s-0.596-1.333-1.333-1.333h-5.363c-0.736 0-1.333-0.597-1.333-1.333v-21.333c0-0.736 0.597-1.333 1.333-1.333h2.667v2.667c0 0.736 0.596 1.333 1.333 1.333s1.333-0.597 1.333-1.333v-2.667h13.333v2.667c0 0.736 0.596 1.333 1.333 1.333s1.333-0.597 1.333-1.333v-2.667h2.667c0.736 0 1.333 0.599 1.333 1.333v2.696c0 0.736 0.596 1.333 1.333 1.333s1.333-0.597 1.333-1.333v-2.696c0-2.205-1.795-4-4-4zM22 12c-5.515 0-10 4.485-10 10s4.485 10 10 10 10-4.485 10-10-4.485-10-10-10zM22 29.333c-4.043 0-7.333-3.291-7.333-7.333s3.291-7.333 7.333-7.333 7.333 3.291 7.333 7.333-3.291 7.333-7.333 7.333z"></path>
</svg>
`;
var TimeIcon = `<!-- Generated by IcoMoon.io -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
<title>time</title>
<path d="M16 0c-8.823 0-16 7.177-16 16s7.177 16 16 16 16-7.177 16-16-7.177-16-16-16zM16 29.333c-7.352 0-13.333-5.981-13.333-13.333s5.981-13.333 13.333-13.333 13.333 5.981 13.333 13.333-5.981 13.333-13.333 13.333zM16 8c-0.736 0-1.333 0.596-1.333 1.333v6.667h-4c-0.736 0-1.333 0.596-1.333 1.333s0.597 1.333 1.333 1.333h5.333c0.736 0 1.333-0.596 1.333-1.333v-8c0-0.737-0.597-1.333-1.333-1.333z"></path>
</svg>
`;
const sallaBookingFieldCss = ":host{display:block}";
const SallaBookingField = class {
constructor(hostRef) {
index.registerInstance(this, hostRef);
this.invalidInput = index.createEvent(this, "invalidInput");
this.bookNowLabel = salla.lang.get('pages.cart.book_an_appointment', 'حجز موعد');
this.editLabel = salla.lang.get('pages.cart.edit_an_appointment', 'تعديل الموعد');
this.bookedLabel = salla.lang.get('pages.cart.booked_successfully', 'تمت اضافة الموعد بنجاح');
this.selectDate = salla.lang.get('pages.cart.select_appointment_date', 'حدد تاريخ الموعد');
this.bookingUrl = '';
this.iframeReady = false;
this.reservations = [];
// Load translations
salla.lang.onLoaded(() => this.setTranslations());
// Register event listeners
Salla.event.on('booking::open', (data) => this.handleBookingOpen(data));
}
async setTranslations() {
const setNestedAsync = (lang, key, value) => {
return new Promise((resolve) => {
salla.helpers.setNested(salla.lang.messages[lang], key, value);
resolve(true);
});
};
await setNestedAsync('ar.trans', 'pages.cart.book_an_appointment', 'حجز موعد');
await setNestedAsync('en.trans', 'pages.cart.book_an_appointment', 'Book an Appointment');
await setNestedAsync('ar.trans', 'pages.cart.edit_an_appointment', 'تعديل الموعد');
await setNestedAsync('en.trans', 'pages.cart.edit_an_appointment', 'Edit an Appointment');
await setNestedAsync('ar.trans', 'pages.cart.booked_successfully', 'تمت اضافة الموعد بنجاح');
await setNestedAsync('en.trans', 'pages.cart.booked_successfully', 'Booked Successfully');
await setNestedAsync('ar.trans', 'pages.cart.select_appointment_date', 'حدد تاريخ الموعد');
await setNestedAsync('en.trans', 'pages.cart.select_appointment_date', 'Select appointment date');
this.bookNowLabel = salla.lang.get('pages.cart.book_an_appointment');
this.editLabel = salla.lang.get('pages.cart.edit_an_appointment');
this.bookedLabel = salla.lang.get('pages.cart.booked_successfully');
this.selectDate = salla.lang.get('pages.cart.select_appointment_date');
}
openBookingModal(event, afterReload = false) {
if (afterReload && (!event.detail || typeof event.detail !== 'number' || event.detail !== this.productId)) {
return;
}
if (salla.config.isGuest()) {
this.setAfterReloadEvent('booking::open-after-reload', this.productId);
salla.event.dispatch('login::open');
return;
}
salla.booking.add(this.productId, false)
.then((resp) => {
if (resp.data.redirect.to !== 'booking') {
throw new Error('Unexpected redirect!');
}
salla.event.dispatch('booking::open', { url: resp.data.redirect.url, id: this.productId });
})
.catch((error) => {
salla.error(salla.lang.get('common.errors.error_occurred'));
salla.logger.error(error.response || error);
});
}
handleBookingOpen(data) {
if (data.id !== this.productId)
return;
this.bookingUrl = salla.url.addParamToUrl('product_id', data.id, data.url);
this.iframeReady = true;
setTimeout(() => {
this.modal.setTitle(this.selectDate);
this.modal.open();
}, 100);
}
setAfterReloadEvent(event, payload) {
salla.storage.set('afterReloadEvent', { event, payload });
}
emitAfterReloadEvent() {
const eventDetails = salla.storage.get('afterReloadEvent');
if (eventDetails && eventDetails.event) {
const customEvent = new CustomEvent(eventDetails.event, {
detail: eventDetails.payload
});
window.dispatchEvent(customEvent);
salla.storage.remove('afterReloadEvent');
}
}
componentWillLoad() {
if (this.option && this.option.details.length) {
this.reservations = this.option.details;
}
}
componentDidLoad() {
window.addEventListener('booking::open-after-reload', (event) => this.openBookingModal(event, true));
this.emitAfterReloadEvent();
window.addEventListener('message', this.handleMessageEvent.bind(this));
this.reservationsInput.addEventListener('invalid', e => this.invalidInput.emit(e));
this.reservationsInput.addEventListener('input', () => {
this.reservationsInput.setCustomValidity('');
this.reservationsInput.reportValidity();
});
}
handleMessageEvent(event) {
if (event.data.source !== 'booking')
return;
const action = event.data.type;
const value = event.data.message;
if (localStorage.getItem('debug'))
console.log(`Received an action:${action}`, event.data);
if (action === 'error') {
if (value.fields?.reservation) {
salla.notify.error(value.fields.reservation[0]);
return;
}
const errorList = Object.values(value.fields || [value.message]).flat().map(error => `<li>${error}</li>`).join('');
salla.notify.error(`<ul>${errorList}</ul>`);
}
if (action === 'success') {
if (Number(value.productId) !== Number(this.productId))
return;
this.reservations = value.data.reservations.map(schedule => {
if (schedule.time && schedule.time.length > 0) {
const timeSlot = schedule.time[0];
return {
date: schedule.date,
day: schedule.day,
from_timestamp: timeSlot.from,
to_timestamp: timeSlot.to,
};
}
return null;
}).filter(item => item !== null);
salla.notify.success(this.bookedLabel);
this.modal?.close();
setTimeout(() => window.location.reload());
}
if (action === 'height') {
this.iframe.height = value?.height + 'px';
}
}
bookingModal() {
return (index.h("salla-modal", { class: "s-booking-field-modal", ref: modal => (this.modal = modal), width: "md", position: "middle", noPadding: true }, index.h("iframe", { ref: iframe => (this.iframe = iframe), src: this.bookingUrl, frameborder: "0" })));
}
renderReservationDate(reservation) {
return (index.h("span", { class: reservation.from_timestamp ? 's-booking-field-reservations-has-time' : '' }, index.h("i", { class: "s-booking-field-reservations-icon", innerHTML: calendar.SICalendar }), reservation.date));
}
renderReservationTime(reservation) {
if (!reservation.from_timestamp)
return '';
return (index.h("span", { class: "s-booking-field-reservations-time" }, index.h("i", { class: "s-booking-field-reservations-icon", innerHTML: TimeIcon }), index.h("span", null, reservation.from_timestamp, " - ", reservation.to_timestamp)));
}
render() {
return (index.h(index.Host, { key: '9a65e86d8c731ea7538ae930d73c63a0fba342d6' }, index.h("div", { key: 'fbac1a9dfdf76f36405db4dff611fd9baa47870b', class: "s-booking-field-main" }, this.option.required || this.reservations.length > 0 ? index.h("div", { class: "s-booking-field-price" }, index.h("span", { innerHTML: salla.money(this.option.price) })) : '', index.h("salla-button", { key: '190495f3a42496aa9d14da129363e6ff83e788ac', class: "s-booking-field-book-now", size: "small", loaderPosition: "center", fill: "outline", onClick: event => this.openBookingModal(event, false) }, index.h("span", { key: '7db20f2888bc865d87545804a2f609f7d07e4dc2', class: "s-booking-field-book-now-content" }, index.h("span", { key: '05f6f331e311f79e5a61a7b6e197e24334bdb5d4', innerHTML: BookingTime }), this.reservations.length ? this.editLabel : this.bookNowLabel))), this.reservations.length > 0 && (index.h("div", { key: 'f54c13f40c3109f5d3249361ac299451151909cf', class: "s-booking-field-reservations" }, this.reservations.map((reservation, index$1) => (index.h("div", { key: index$1, class: "s-booking-field-reservations-item" }, this.renderReservationDate(reservation), this.renderReservationTime(reservation)))))), index.h("input", { key: '5d147e4832a2b14ed614152efefa35769e0c52ba', class: "s-hidden", name: this.option.name, required: this.option.required, value: JSON.stringify(this.reservations) === '[]' ? '' : JSON.stringify(this.reservations), ref: reservations => this.reservationsInput = reservations }), this.iframeReady && this.bookingModal()));
}
get host() { return index.getElement(this); }
};
SallaBookingField.style = sallaBookingFieldCss;
const sallaColorPickerCss = "";
const SallaColorPicker = class {
constructor(hostRef) {
index.registerInstance(this, hostRef);
this.colorChanged = index.createEvent(this, "colorChanged");
this.invalidInput = index.createEvent(this, "invalidInput");
this.submitted = index.createEvent(this, "submitted");
this.popupOpened = index.createEvent(this, "popupOpened");
this.popupClosed = index.createEvent(this, "popupClosed");
/** Lazy-loaded to avoid bundling vanilla-picker (Babel polyfills) into main/hydrate bundle. */
this.picker = null;
this.pickerReady = null;
/**
* File input name for the native formData
*/
this.name = 'color';
/**
* Set if the color picker input is required or not
*/
this.required = false;
/**
* How to display the selected color in the text field
* (the text field still supports input in any format).
*/
this.format = 'hex';
/**
* Whether to have a "Cancel" button which closes the popup.
*/
this.showCancelButton = false;
/**
* Whether to show a text field for color value editing.
*/
this.showTextField = true;
/**
* Whether to enable adjusting the alpha channel.
*/
this.enableAlpha = false;
this.updateViewportCache = () => {
this.cachedViewportWidth = this.getViewportWidthFromBreakpoints();
};
this.cachedViewportWidth = 0; // Will be populated in componentDidLoad via requestAnimationFrame
}
colorChangeHandler(color) {
if (this.colorInput)
this.colorInput.value = color.hex;
this.colorChanged.emit(color);
}
async submittedHandler(color) {
await this.setColorValue(color.rgbaString, true);
if (this.canvas)
this.canvas.style.backgroundColor = color.rgbString;
if (this.colorInput) {
this.colorInput.value = color.hex;
this.colorInput.dispatchEvent(new window.Event('change', { bubbles: true }));
}
this.submitted.emit(color);
}
popupOpenedHandler(color) {
// Double rAF: defer setPopInPosition (getBoundingClientRect) until after paint to avoid forced reflow
requestAnimationFrame(() => {
requestAnimationFrame(() => this.setPopInPosition());
});
this.popupOpened.emit(color);
}
popupClosedHandler(color) {
this.popupClosed.emit(color);
}
/** Methods */
async ensurePicker() {
if (this.picker)
return this.picker;
if (this.pickerReady)
return await this.pickerReady;
throw new Error('Color picker not initialized');
}
/**
* Set the picker options.
*
* (Usually a new .parent and .color).
* @param {Object} options
*/
async setPickerOption(options) {
const picker = await this.ensurePicker();
picker.setOptions(options);
}
/**
* Move the popup to a different parent, optionally opening it at the same time.
*
* (Usually a new .parent and .color).
* @param {Options} option
*
* Whether to open the popup immediately.
* @param {boolean} openImmediately
*/
async movePopUp(options, openImmediately) {
const picker = await this.ensurePicker();
picker.movePopup(options, openImmediately);
}
/**
* Set/initialize the picker's color.
*
* Color name, RGBA/HSLA/HEX string, or RGBA array.
* @param {string} color
*
* If true, won't trigger onChange.
* @param {boolean} triggerEvent
*/
async setColorValue(color, triggerEvent) {
const picker = await this.ensurePicker();
picker.setColor(color, triggerEvent);
}
/**
* Show/open the picker.
*/
async openPicker() {
const picker = await this.ensurePicker();
picker.show();
}
/**
* Close/Hide the picker.
*/
async closePicker() {
const picker = await this.ensurePicker();
picker.hide();
}
/**
* Release all resources used by this picker instance.
*/
async destroyPicker() {
const picker = await this.ensurePicker();
picker.destroy();
this.picker = null;
this.pickerReady = null;
}
disconnectedCallback() {
window.removeEventListener('resize', this.updateViewportCache);
}
componentWillLoad() {
salla.onReady(() => {
this.color = this.color ? this.color : salla.config.get('theme.color.primary', '#5dd5c4');
});
}
/**
* Returns viewport width from matchMedia breakpoints (no layout read).
* Must match updateViewportCache breakpoints for consistency.
*/
getViewportWidthFromBreakpoints() {
if (typeof window === 'undefined')
return 1024;
if (window.matchMedia('(min-width: 1200px)').matches)
return 1200;
if (window.matchMedia('(min-width: 992px)').matches)
return 992;
if (window.matchMedia('(min-width: 768px)').matches)
return 768;
return 375;
}
setPopInPosition() {
// Use cached viewport width – reading innerWidth at popup open causes forced reflow.
// Fallback: matchMedia-based value when cache is 0 (e.g. SSR before hydration). Same breakpoints as updateViewportCache.
const viewportWidth = this.cachedViewportWidth || this.getViewportWidthFromBreakpoints();
const popup = this.host.querySelector('.picker_wrapper');
const widgetEl = this.host.querySelector('.s-color-picker-widget');
if (!popup || !widgetEl)
return;
const widgetPosition = widgetEl.getBoundingClientRect();
const widgetToWindowEq = viewportWidth / 2 - widgetPosition.width / 2;
const widgetInLeft = widgetToWindowEq > widgetPosition.x;
const widgetInRight = widgetToWindowEq < widgetPosition.x;
const widgetInCenter = widgetToWindowEq === widgetPosition.x;
const isMobile = !window.matchMedia('(min-width: 768px)').matches;
if (isMobile && widgetInLeft) {
popup.style.left = '0';
}
if (isMobile && widgetInRight) {
popup.style.left = 'auto';
}
if (!isMobile || (isMobile && ((!widgetInRight && !widgetInLeft) || widgetInCenter))) {
popup.style.left = `-95px`;
}
}
initColorPicker() {
this.pickerReady = Promise.resolve().then(function () { return require('./vanilla-picker-BEliYBNM.js'); }).then(function (n) { return n.vanillaPicker; }).then(mod => {
const Picker = mod.default;
const picker = new Picker({
parent: this.host,
color: this.color,
popup: 'bottom',
alpha: this.enableAlpha,
editor: this.showTextField,
editorFormat: this.format,
cancelButton: this.showCancelButton,
onChange: (color) => this.colorChangeHandler(color),
onDone: (color) => this.submittedHandler(color),
onOpen: (color) => this.popupOpenedHandler(color),
onClose: (color) => this.popupClosedHandler(color),
});
this.picker = picker;
return this.picker;
});
}
render() {
return (index.h(index.Host, { key: '2f142fd64afd5571574a7e1c40de3be16ede62e6', class: "s-color-picker-main" }, index.h("slot", { key: '92acdf14b2f42ac52d0a632ba6840a5dcebfa4d4', name: "widget" }, index.h("div", { key: '7ba074040299a91802109d0e1d2e78604e39d3a8', class: "s-color-picker-widget" }, index.h("div", { key: 'a6272207f79fd28e33b66e415a3e05b969ace983', class: "s-color-picker-widget-canvas", ref: dv => (this.canvas = dv) }), index.h("span", { key: 'e6fed242bb84fae6221cdec525658b68f7514ce7', innerHTML: keyboard_arrow_down.ArrowDown }))), index.h("input", { key: '9eb1673f44e663f939124da45fec79c401736203', class: "s-hidden", name: this.name, required: this.required, value: this.color, ref: color => (this.colorInput = color) })));
}
componentDidLoad() {
if (this.canvas)
this.canvas.style.backgroundColor = this.color;
this.initColorPicker();
// Populate viewport cache in next frame (avoids forced reflow during initial render)
requestAnimationFrame(() => this.updateViewportCache());
window.addEventListener('resize', this.updateViewportCache);
if (this.colorInput) {
this.colorInput.addEventListener('invalid', e => {
this.invalidInput.emit(e);
});
this.colorInput.addEventListener('input', () => {
this.colorInput.setCustomValidity('');
this.colorInput.reportValidity();
});
}
}
get host() { return index.getElement(this); }
};
SallaColorPicker.style = sallaColorPickerCss;
const SallaConditionalFields = class {
constructor(hostRef) {
index.registerInstance(this, hostRef);
}
hideAllOptions(optionId) {
this.host.querySelectorAll(`[data-show-when^="options[${optionId}"]`).forEach((field) => {
field.classList.add('hidden');
this.hideAllOptions(field.dataset.optionId);
this.disableInputs(field);
});
}
disableInputs(field) {
field.querySelectorAll('[name]').forEach((node) => {
const input = node;
input.setAttribute('disabled', '');
input.removeAttribute('required');
if (input instanceof HTMLSelectElement) {
input.value = '';
return;
}
if (input instanceof HTMLTextAreaElement) {
input.value = '';
return;
}
if (input instanceof HTMLInputElement) {
const t = (input.type || 'text').toLowerCase();
if (t === 'checkbox' || t === 'radio') {
input.checked = false;
return;
}
if (['text', 'search', 'number', 'tel', 'url', 'email'].includes(t)) {
input.value = '';
}
}
});
}
changeHandler(event) {
salla.event.emit('salla-onditional-fields::change', event);
salla.log('Received the change/input event: ', event);
if (!event.target ||
(!['SELECT', 'INPUT', 'TEXTAREA'].includes(event.target.tagName) &&
!['checkbox', 'radio', 'text'].includes(event.target.getAttribute('type')))) {
salla.log('Ignore the event because is not a supported input: ' + (event?.target?.tagName || 'N/A'));
return;
}
// For text inputs, debounce the handling to improve performance on mobile
const isTextInput = ['INPUT', 'TEXTAREA'].includes(event.target.tagName) &&
(!event.target.getAttribute('type') || event.target.getAttribute('type') === 'text');
if (isTextInput && event.type === 'input') {
clearTimeout(this.debounceTimeout);
this.debounceTimeout = setTimeout(() => {
this.processConditionalFields(event);
}, 300); // 300ms debounce for text inputs
return;
}
// Process immediately for change events and non-text inputs
this.processConditionalFields(event);
}
processConditionalFields(event) {
let optionId = event.target.name.replace('[]', '');
let isMultiple = event.target.getAttribute('type') === 'checkbox';
let isRadio = event.target.getAttribute('type') === 'radio';
let isTextInput = ['INPUT', 'TEXTAREA'].includes(event.target.tagName) &&
(!event.target.getAttribute('type') || event.target.getAttribute('type') === 'text');
salla.log('Trying to find all elements with condition:', `[data-show-when^="${optionId}"]`);
this.host.querySelectorAll(`[data-show-when^="${optionId}"]`)
.forEach((field) => {
let isEqual = !field?.dataset.showWhen.includes('!=');
let value = field?.dataset.showWhen.replace(/(.*)(=|!=)(.*)/gm, '$3').trim();
let isSelected;
if (isMultiple) {
let selectedValues = Array.from(this.host.querySelectorAll(`input[name="${event.target.name}"]:checked`), e => e?.value);
isSelected = selectedValues.includes(value.toString());
}
else if (isRadio) {
// Handle radio inputs.
isSelected = event.target.checked && event.target.value === value;
}
else if (isTextInput) {
// Handle text inputs and textareas - check if value matches or is not empty for boolean conditions
isSelected = value === event.target.value || (value.toLowerCase() === 'true' && event.target.value.trim() !== '');
}
else {
isSelected = value === event.target.value;
}
salla.log('The input is ', isMultiple ? 'Multiple' : isRadio ? 'Radio' : isTextInput ? 'Text' : 'Single', ' value:', isSelected);
let showTheInput = (isEqual && isSelected) || (!isEqual && !isSelected);
if (showTheInput) {
field.classList.remove('hidden');
field.querySelectorAll('[name]').forEach((input) => {
input.removeAttribute('disabled');
const closestProductOption = input.closest('.s-product-options-option');
if (closestProductOption.dataset.optionRequired === 'true') {
input.setAttribute('required', '');
}
if (input.getAttribute('type') === 'checkbox') {
const checkboxes = Array.from(document.querySelectorAll(`input[type="checkbox"][name="${input.getAttribute('name')}"]`));
const isAnyChecked = checkboxes.some((checkbox) => checkbox.checked);
if (isAnyChecked) {
checkboxes.forEach((checkbox) => {
checkbox.removeAttribute('required');
});
}
}
});
}
else {
this.hideAllOptions(field.dataset.optionId);
field.classList.add('hidden');
this.disableInputs(field);
}
});
}
componentDidRender() {
this.host.querySelectorAll(`[data-show-when]`).forEach((field) => {
// @ts-ignore
let optionName = field?.dataset?.showWhen.replace(/(.*)(=|!=)(.*)/gm, '$1').trim();
if (!optionName) {
return;
}
this.changeHandler({
target: this.host.querySelector('[name^="' + optionName + '"]')
});
});
}
render() {
return (index.h(index.Host, { key: '9931740a40a239483408056ae458769a0ab3997d' }, index.h("slot", { key: '6db0aa3b6db44f3811d1ed456672218891018d6f' })));
}
get host() { return index.getElement(this); }
};
const sallaDatetimePickerCss = ".flatpickr-calendar{background:transparent;opacity:0;display:none;text-align:center;visibility:hidden;padding:0;-webkit-animation:none;animation:none;direction:ltr;border:0;font-size:14px;line-height:24px;border-radius:5px;position:absolute;width:307.875px;-webkit-box-sizing:border-box;box-sizing:border-box;-ms-touch-action:manipulation;touch-action:manipulation;background:#fff;-webkit-box-shadow:1px 0 0 #e6e6e6,-1px 0 0 #e6e6e6,0 1px 0 #e6e6e6,0 -1px 0 #e6e6e6,0 3px 13px rgba(0,0,0,0.08);box-shadow:1px 0 0 #e6e6e6,-1px 0 0 #e6e6e6,0 1px 0 #e6e6e6,0 -1px 0 #e6e6e6,0 3px 13px rgba(0,0,0,0.08)}.flatpickr-calendar.open,.flatpickr-calendar.inline{opacity:1;max-height:640px;visibility:visible}.flatpickr-calendar.open{display:inline-block;z-index:99999}.flatpickr-calendar.animate.open{-webkit-animation:fpFadeInDown 300ms cubic-bezier(.23,1,.32,1);animation:fpFadeInDown 300ms cubic-bezier(.23,1,.32,1)}.flatpickr-calendar.inline{display:block;position:relative;top:2px}.flatpickr-calendar.static{position:absolute;top:calc(100% + 2px)}.flatpickr-calendar.static.open{z-index:999;display:block}.flatpickr-calendar.multiMonth .flatpickr-days .dayContainer:nth-child(n+1) .flatpickr-day.inRange:nth-child(7n+7){-webkit-box-shadow:none !important;box-shadow:none !important}.flatpickr-calendar.multiMonth .flatpickr-days .dayContainer:nth-child(n+2) .flatpickr-day.inRange:nth-child(7n+1){-webkit-box-shadow:-2px 0 0 #e6e6e6,5px 0 0 #e6e6e6;box-shadow:-2px 0 0 #e6e6e6,5px 0 0 #e6e6e6}.flatpickr-calendar .hasWeeks .dayContainer,.flatpickr-calendar .hasTime .dayContainer{border-bottom:0;border-bottom-right-radius:0;border-bottom-left-radius:0}.flatpickr-calendar .hasWeeks .dayContainer{border-left:0}.flatpickr-calendar.hasTime .flatpickr-time{height:40px;border-top:1px solid #e6e6e6}.flatpickr-calendar.noCalendar.hasTime .flatpickr-time{height:auto}.flatpickr-calendar:before,.flatpickr-calendar:after{position:absolute;display:block;pointer-events:none;border:solid transparent;content:'';height:0;width:0;left:22px}.flatpickr-calendar.rightMost:before,.flatpickr-calendar.arrowRight:before,.flatpickr-calendar.rightMost:after,.flatpickr-calendar.arrowRight:after{left:auto;right:22px}.flatpickr-calendar.arrowCenter:before,.flatpickr-calendar.arrowCenter:after{left:50%;right:50%}.flatpickr-calendar:before{border-width:5px;margin:0 -5px}.flatpickr-calendar:after{border-width:4px;margin:0 -4px}.flatpickr-calendar.arrowTop:before,.flatpickr-calendar.arrowTop:after{bottom:100%}.flatpickr-calendar.arrowTop:before{border-bottom-color:#e6e6e6}.flatpickr-calendar.arrowTop:after{border-bottom-color:#fff}.flatpickr-calendar.arrowBottom:before,.flatpickr-calendar.arrowBottom:after{top:100%}.flatpickr-calendar.arrowBottom:before{border-top-color:#e6e6e6}.flatpickr-calendar.arrowBottom:after{border-top-color:#fff}.flatpickr-calendar:focus{outline:0}.flatpickr-wrapper{position:relative;display:inline-block}.flatpickr-months{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex}.flatpickr-months .flatpickr-month{background:transparent;color:rgba(0,0,0,0.9);fill:rgba(0,0,0,0.9);height:34px;line-height:1;text-align:center;position:relative;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;overflow:hidden;-webkit-box-flex:1;-webkit-flex:1;-ms-flex:1;flex:1}.flatpickr-months .flatpickr-prev-month,.flatpickr-months .flatpickr-next-month{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;text-decoration:none;cursor:pointer;position:absolute;top:0;height:34px;padding:10px;z-index:3;color:rgba(0,0,0,0.9);fill:rgba(0,0,0,0.9)}.flatpickr-months .flatpickr-prev-month.flatpickr-disabled,.flatpickr-months .flatpickr-next-month.flatpickr-disabled{display:none}.flatpickr-months .flatpickr-prev-month i,.flatpickr-months .flatpickr-next-month i{position:relative}.flatpickr-months .flatpickr-prev-month.flatpickr-prev-month,.flatpickr-months .flatpickr-next-month.flatpickr-prev-month{left:0}.flatpickr-months .flatpickr-prev-month.flatpickr-next-month,.flatpickr-months .flatpickr-next-month.flatpickr-next-month{right:0}.flatpickr-months .flatpickr-prev-month:hover,.flatpickr-months .flatpickr-next-month:hover{color:#959ea9}.flatpickr-months .flatpickr-prev-month:hover svg,.flatpickr-months .flatpickr-next-month:hover svg{fill:#f64747}.flatpickr-months .flatpickr-prev-month svg,.flatpickr-months .flatpickr-next-month svg{width:14px;height:14px}.flatpickr-months .flatpickr-prev-month svg path,.flatpickr-months .flatpickr-next-month svg path{-webkit-transition:fill .1s;transition:fill .1s;fill:inherit}.numInputWrapper{position:relative;height:auto}.numInputWrapper input,.numInputWrapper span{display:inline-block}.numInputWrapper input{width:100%}.numInputWrapper input::-ms-clear{display:none}.numInputWrapper input::-webkit-outer-spin-button,.numInputWrapper input::-webkit-inner-spin-button{margin:0;-webkit-appearance:none}.numInputWrapper span{position:absolute;right:0;width:14px;padding:0 4px 0 2px;height:50%;line-height:50%;opacity:0;cursor:pointer;border:1px solid rgba(57,57,57,0.15);-webkit-box-sizing:border-box;box-sizing:border-box}.numInputWrapper span:hover{background:rgba(0,0,0,0.1)}.numInputWrapper span:active{background:rgba(0,0,0,0.2)}.numInputWrapper span:after{display:block;content:\"\";position:absolute}.numInputWrapper span.arrowUp{top:0;border-bottom:0}.numInputWrapper span.arrowUp:after{border-left:4px solid transparent;border-right:4px solid transparent;border-bottom:4px solid rgba(57,57,57,0.6);top:26%}.numInputWrapper span.arrowDown{top:50%}.numInputWrapper span.arrowDown:after{border-left:4px solid transparent;border-right:4px solid transparent;border-top:4px solid rgba(57,57,57,0.6);top:40%}.numInputWrapper span svg{width:inherit;height:auto}.numInputWrapper span svg path{fill:rgba(0,0,0,0.5)}.numInputWrapper:hover{background:rgba(0,0,0,0.05)}.numInputWrapper:hover span{opacity:1}.flatpickr-current-month{font-size:135%;line-height:inherit;font-weight:300;color:inherit;position:absolute;width:75%;left:12.5%;padding:7.48px 0 0 0;line-height:1;height:34px;display:inline-block;text-align:center;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}.flatpickr-current-month span.cur-month{font-family:inherit;font-weight:700;color:inherit;display:inline-block;margin-left:.5ch;padding:0}.flatpickr-current-month span.cur-month:hover{background:rgba(0,0,0,0.05)}.flatpickr-current-month .numInputWrapper{width:6ch;width:7ch\\0;display:inline-block}.flatpickr-current-month .numInputWrapper span.arrowUp:after{border-bottom-color:rgba(0,0,0,0.9)}.flatpickr-current-month .numInputWrapper span.arrowDown:after{border-top-color:rgba(0,0,0,0.9)}.flatpickr-current-month input.cur-year{background:transparent;-webkit-box-sizing:border-box;box-sizing:border-box;color:inherit;cursor:text;padding:0 0 0 .5ch;margin:0;display:inline-block;font-size:inherit;font-family:inherit;font-weight:300;line-height:inherit;height:auto;border:0;border-radius:0;vertical-align:initial;-webkit-appearance:textfield;-moz-appearance:textfield;appearance:textfield}.flatpickr-current-month input.cur-year:focus{outline:0}.flatpickr-current-month input.cur-year[disabled],.flatpickr-current-month input.cur-year[disabled]:hover{font-size:100%;color:rgba(0,0,0,0.5);background:transparent;pointer-events:none}.flatpickr-current-month .flatpickr-monthDropdown-months{appearance:menulist;background:transparent;border:none;border-radius:0;box-sizing:border-box;color:inherit;cursor:pointer;font-size:inherit;font-family:inherit;font-weight:300;height:auto;line-height:inherit;margin:-1px 0 0 0;outline:none;padding:0 0 0 .5ch;position:relative;vertical-align:initial;-webkit-box-sizing:border-box;-webkit-appearance:menulist;-moz-appearance:menulist;width:auto}.flatpickr-current-month .flatpickr-monthDropdown-months:focus,.flatpickr-current-month .flatpickr-monthDropdown-months:active{outline:none}.flatpickr-current-month .flatpickr-monthDropdown-months:hover{background:rgba(0,0,0,0.05)}.flatpickr-current-month .flatpickr-monthDropdown-months .flatpickr-monthDropdown-month{background-color:transparent;outline:none;padding:0}.flatpickr-weekdays{background:transparent;text-align:center;overflow:hidden;width:100%;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;height:28px}.flatpickr-weekdays .flatpickr-weekdaycontainer{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-flex:1;-webkit-flex:1;-ms-flex:1;flex:1}span.flatpickr-weekday{cursor:default;font-size:90%;background:transparent;color:rgba(0,0,0,0.54);line-height:1;margin:0;text-align:center;display:block;-webkit-box-flex:1;-webkit-flex:1;-ms-flex:1;flex:1;font-weight:bolder}.dayContainer,.flatpickr-weeks{padding:1px 0 0 0}.flatpickr-days{position:relative;overflow:hidden;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-align:start;-webkit-align-items:flex-start;-ms-flex-align:start;align-items:flex-start;width:307.875px}.flatpickr-days:focus{outline:0}.dayContainer{padding:0;outline:0;text-align:left;width:307.875px;min-width:307.875px;max-width:307.875px;-webkit-box-sizing:border-box;box-sizing:border-box;display:inline-block;display:-ms-flexbox;display:-webkit-box;display:-webkit-flex;display:flex;-webkit-flex-wrap:wrap;flex-wrap:wrap;-ms-flex-wrap:wrap;-ms-flex-pack:justify;-webkit-justify-content:space-around;justify-content:space-around;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);opacity:1}.dayContainer+.dayContainer{-webkit-box-shadow:-1px 0 0 #e6e6e6;box-shadow:-1px 0 0 #e6e6e6}.flatpickr-day{background:none;border:1px solid transparent;border-radius:150px;-webkit-box-sizing:border-box;box-sizing:border-box;color:#393939;cursor:pointer;font-weight:400;width:14.2857143%;-webkit-flex-basis:14.2857143%;-ms-flex-preferred-size:14.2857143%;flex-basis:14.2857143%;max-width:39px;height:39px;line-height:39px;margin:0;display:inline-block;position:relative;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;text-align:center}.flatpickr-day.inRange,.flatpickr-day.prevMonthDay.inRange,.flatpickr-day.nextMonthDay.inRange,.flatpickr-day.today.inRange,.flatpickr-day.prevMonthDay.today.inRange,.flatpickr-day.nextMonthDay.today.inRange,.flatpickr-day:hover,.flatpickr-day.prevMonthDay:hover,.flatpickr-day.nextMonthDay:hover,.flatpickr-day:focus,.flatpickr-day.prevMonthDay:focus,.flatpickr-day.nextMonthDay:focus{cursor:pointer;outline:0;background:#e6e6e6;border-color:#e6e6e6}.flatpickr-day.today{border-color:#959ea9}.flatpickr-day.today:hover,.flatpickr-day.today:focus{border-color:#959ea9;background:#959ea9;color:#fff}.flatpickr-day.selected,.flatpickr-day.startRange,.flatpickr-day.endRange,.flatpickr-day.selected.inRange,.flatpickr-day.startRange.inRange,.flatpickr-day.endRange.inRange,.flatpickr-day.selected:focus,.flatpickr-day.startRange:focus,.flatpickr-day.endRange:focus,.flatpickr-day.selected:hover,.flatpickr-day.startRange:hover,.flatpickr-day.endRange:hover,.flatpickr-day.selected.prevMonthDay,.flatpickr-day.startRange.prevMonthDay,.flatpickr-day.endRange.prevMonthDay,.flatpickr-day.selected.nextMonthDay,.flatpickr-day.startRange.nextMonthDay,.flatpickr-day.endRange.nextMonthDay{background:#569ff7;-webkit-box-shadow:none;box-shadow:none;color:#fff;border-color:#569ff7}.flatpickr-day.selected.startRange,.flatpickr-day.startRange.startRange,.flatpickr-day.endRange.startRange{border-radius:50px 0 0 50px}.flatpickr-day.selected.endRange,.flatpickr-day.startRange.endRange,.flatpickr-day.endRange.endRange{border-radius:0 50px 50px 0}.flatpickr-day.selected.startRange+.endRange:not(:nth-child(7n+1)),.flatpickr-day.startRange.startRange+.endRange:not(:nth-child(7n+1)),.flatpickr-day.endRange.startRange+.endRange:not(:nth-child(7n+1)){-webkit-box-shadow:-10px 0 0 #569ff7;box-shadow:-10px 0 0 #569ff7}.flatpickr-day.selected.startRange.endRange,.flatpickr-day.startRange.startRange.endRange,.flatpickr-day.endRange.startRange.endRange{border-radius:50px}.flatpickr-day.inRange{border-radius:0;-webkit-box-shadow:-5px 0 0 #e6e6e6,5px 0 0 #e6e6e6;box-shadow:-5px 0 0 #e6e6e6,5px 0 0 #e6e6e6}.flatpickr-day.flatpickr-disabled,.flatpickr-day.flatpickr-disabled:hover,.flatpickr-day.prevMonthDay,.flatpickr-day.nextMonthDay,.flatpickr-day.notAllowed,.flatpickr-day.notAllowed.prevMonthDay,.flatpickr-day.notAllowed.nextMonthDay{color:rgba(57,57,57,0.3);background:transparent;border-color:transparent;cursor:default}.flatpickr-day.flatpickr-disabled,.flatpickr-day.flatpickr-disabled:hover{cursor:not-allowed;color:rgba(57,57,57,0.1)}.flatpickr-day.week.selected{border-radius:0;-webkit-box-shadow:-5px 0 0 #569ff7,5px 0 0 #569ff7;box-shadow:-5px 0 0 #569ff7,5px 0 0 #569ff7}.flatpickr-day.hidden{visibility:hidden}.rangeMode .flatpickr-day{margin-top:1px}.flatpickr-weekwrapper{float:left}.flatpickr-weekwrapper .flatpickr-weeks{padding:0 12px;-webkit-box-shadow:1px 0 0 #e6e6e6;box-shadow:1px 0 0 #e6e6e6}.flatpickr-weekwrapper .flatpickr-weekday{float:none;width:100%;line-height:28px}.flatpickr-weekwrapper span.flatpickr-day,.flatpickr-weekwrapper span.flatpickr-day:hover{display:block;width:100%;max-width:none;color:rgba(57,57,57,0.3);background:transparent;cursor:default;border:none}.flatpickr-innerContainer{display:block;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-sizing:border-box;box-sizing:border-box;overflow:hidden}.flatpickr-rContainer{display:inline-block;padding:0;-webkit-box-sizing:border-box;box-sizing:border-box}.flatpickr-time{text-align:center;outline:0;display:block;height:0;line-height:40px;max-height:40px;-webkit-box-sizing:border-box;box-sizing:border-box;overflow:hidden;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex}.flatpickr-time:after{content:\"\";display:table;clear:both}.flatpickr-time .numInputWrapper{-webkit-box-flex:1;-webkit-flex:1;-ms-flex:1;flex:1;width:40%;height:40px;float:left}.flatpickr-time .numInputWrapper span.arrowUp:after{border-bottom-color:#393939}.flatpickr-time .numInputWrapper span.arrowDown:after{border-top-color:#393939}.flatpickr-time.hasSeconds .numInputWrapper{width:26%}.flatpickr-time.time24hr .numInputWrapper{width:49%}.flatpickr-time input{background:transparent;-webkit-box-shadow:none;box-shadow:none;border:0;border-radius:0;text-align:center;margin:0;padding:0;height:inherit;line-height:inherit;color:#393939;font-size:14px;position:relative;-webkit-box-sizing:border-box;box-sizing:border-box;-webkit-appearance:textfield;-moz-appearance:textfield;appearance:textfield}.flatpickr-time input.flatpickr-hour{font-weight:bold}.flatpickr-time input.flatpickr-minute,.flatpickr-time input.flatpickr-second{font-weight:400}.flatpickr-time input:focus{outline:0;border:0}.flatpickr-time .flatpickr-time-separator,.flatpickr-time .flatpickr-am-pm{height:inherit;float:left;line-height:inherit;color:#393939;font-weight:bold;width:2%;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-align-self:center;-ms-flex-item-align:center;align-self:center}.flatpickr-time .flatpickr-am-pm{outline:0;width:18%;cursor:pointer;text-align:center;font-weight:400}.flatpickr-time input:hover,.flatpickr-time .flatpickr-am-pm:hover,.flatpickr-time input:focus,.flatpickr-time .flatpickr-am-pm:focus{background:#eee}.flatpickr-input[readonly]{cursor:pointer}@-webkit-keyframes fpFadeInDown{from{opacity:0;-webkit-transform:translate3d(0,-20px,0);transform:translate3d(0,-20px,0)}to{opacity:1;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}@keyframes fpFadeInDown{from{opacity:0;-webkit-transform:translate3d(0,-20px,0);transform:translate3d(0,-20px,0)}to{opacity:1;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}";
const SallaDatetimePicker = class {
constructor(hostRef) {
index.registerInstance(this, hostRef);
this.picked = index.createEvent(this, "picked");
this.invalidInput = index.createEvent(this, "invalidInput");
/**
* Two way data binding to retrieve the selected date[time] value
*/
this.value = null;
/**
* Placeholder text to show on the input element
*/
this.placeholder = salla.lang.get('blocks.buy_as_gift.select_send_date_and_time');
/**
* Allows the user to enter a date directly into the input field. By default, direct entry is disabled.
*/
this.allowInput = true;
/**
* Allows the preloading of an invalid date. When disabled, the field will be cleared if the provided date is invalid
*/
this.allowInvalidPreload = false;
/**
* Exactly the same as date format, but for the altInput field.
*/
this.altFormat = "F j, Y";
/**
* Show the user a readable date (as per altFormat), but return something totally different to the server.
*/
this.altInput = false;
/**
* Instead of body, appends the calendar to the specified node instead.
*/
this.appendTo = undefined;
/**
* Defines how the date will be formatted in the aria-label for calendar days,
* using the same tokens as dateFormat. If you change this, you should choose a
* value that will make sense if a screen reader reads it out loud.
*/
this.ariaDateFormat = "F j, Y";
/**
* Whether the default time should be auto-filled when the input is empty and gains or loses focus.
*/
this.autoFillDefaultTime = true;
/**
* Whether clicking on the input should open the picker.
* Set it to false if you only want to open the calendar programmatically with [open()]
*/
this.clickOpens = true;
/**
* Whether calendar should close after date selection or not
*/
this.closeOnSelect = true;
/**
* A string of characters which are used to define how the date will be displayed in the input box.
* The supported characters are defined in the table below.
*/
this.dateFormat = "Y-m-d";
/**
* Initial value of the hour element, when no date is selected
*/
this.defaultHour = 12;
/**
* Initial value of the minute element, when no date is selected
*/
this.defaultMinute = 0;
/**
* Initial value of the seconds element, when no date is selected
*/
this.defaultSeconds = 0;
/**
* Disables certain dates, preventing them from being selected.
* See https://chmln.github.io/flatpickr/examples/#disabling-specific-dates
*/
this.disable = [];
/**
* Set this to true to always use the non-native picker on mobile devices.
* By default, Flatpickr utilizes native datetime widgets unless certain options (e.g. disable) are used.
*/
this.disableMobile = false;
/**
* Disables all dates except these specified. See https://chmln.github.io/flatpickr/examples/#disabling-all-dates-except-select-few
*/
this.enable = [(_) => true];
/**
* Enables seconds selection in the time picker.
*/
this.enableSeconds = false;
/**
* Enables the time picker
*/
this.enableTime = false;
/**
* Adjusts the step for the hour input (incl. scrolling)
*/
this.hourIncrement = 1;
/**
* Displays the calendar inline
*/
this.inline = false;
/**
* The locale, either as a string (e.g. "ar", "en") or as an object.
* See https://chmln.github.io/flatpickr/localization/
*/
this.locale = "en";
/**
* The maximum date that a user can pick to (inclusive).
*/
this.maxDate = null;
/**
* The minimum date that a user can start picking from (inclusive).
*/
this.maxTime = null;
/**
* The minimum date that a user can start picking from (inclusive).
*/
this.minDate = null;
/**
* The minimum time that a user can start picking from (inclusive).
*/
this.minTime = null;
/**
* Adjusts the step for the minute input (incl. scrolling) Defaults to 5
*/
this.minuteIncrement = 5;
/**
* Date selection mode, defaults to "single"
*/
this.mode = "single";
/**
* How the month should be displayed in the header of the calendar.
* If showMonths has a value greater than 1, the month is always shown as static.
*/
this.monthSelectorType = "dropdown";
/**
* HTML for the arrow icon, used to switch months.
*/
this.nextArrow = '<span class="sicon-keyboard_arrow_right"></span>';
/**
* Hides the day selection in calendar. Use it along with enableTime to create a time picker.
*/
this.noCalendar = false;
/**
* How the calendar should be positioned with regards to the input. Defaults to "auto"
*/
this.position = "auto";
/**
* HTML for the left arrow icon, used to switch months.
*/
this.prevArrow = '<span class="sicon-keyboard_arrow_left"></span>';
/**
* Whether to display the current month name in shorthand mode, e.g. "Sep" instead "September"
*/
this.shorthandCurrentMonth = false;
/**
* Position the calendar inside the wrapper and next to the input element*.
*/
this.static = false;
/**
* The number of months to be shown at the same time when displaying the calendar.
*/
this.showMonths = 1;
/**
* Displays time picker in 24 hour mode without AM/PM selection when enabled.
*/
this.time_24hr = false;
/**
* Enables display of week numbers in calendar.
*/
this.weekNumbers = false;
/**
* See https://chmln.github.io/flatpickr/examples/#flatpickr-external-elements
*/
this.wrap = false;
/**
* Whether the input is disabled
*/
this.disabled = false;
}
/**
* Lazy load flatpickr library
* This reduces initial bundle size by ~35-40KB
*/
async loadFlatpickr() {
if (this.flatpickr)
return;
try {
const flatpickrModule = await Promise.resolve().then(function () { return require('./index-D-dRbHuJ.js'); });
this.flatpickr = flatpickrModule.default;
// Load locale if not English
if (this.locale && this.locale !== 'en') {
try {