UNPKG

@limetech/lime-elements

Version:
232 lines (227 loc) • 8.25 kB
import { r as registerInstance, c as createEvent, h, g as getElement } from './index-2714248e.js'; import { c as createRandomString } from './random-string-355331d3.js'; import { i as isIOSDevice, a as isAndroidDevice } from './device-4fdce119.js'; import './sv-d8302491.js'; import { m as moment } from './moment-fbe0e39e.js'; import { M as MDCTextField } from './component-e6eb55fa.js'; import './_commonjsHelpers-9b95d21f.js'; import './ponyfill-9f1f6cd2.js'; import './component-a531729c.js'; import './component-b934161d.js'; class DateFormatter { constructor(language = 'en') { this.language = language; } formatDate(date, dateFormat) { if (date) { return moment(date).locale(this.getLanguage()).format(dateFormat); } return ''; } parseDate(date, dateFormat) { if (date) { return moment(date, dateFormat).toDate(); } return null; } getLanguage() { if (this.language === 'no') { return 'nb'; } return this.language; } getDateFormat(type) { return ({ date: 'L', time: 'LT', week: '[w] W GGGG', month: 'MM/YYYY', quarter: '[Q]Q YYYY', year: 'YYYY', datetime: 'L - LT', }[type] || 'L - LT'); } } const datePickerCss = ":host(limel-date-picker){position:relative}limel-input-field[disabled],limel-input-field[readonly]{pointer-events:none}"; // tslint:disable:no-duplicate-string const nativeTypeForConsumerType = { date: 'date', time: 'time', // Mobile Safari feature detects as capable of input type `week`, // but it just displays a non-interactive input // TODO(ads): remove this when support is decent on iOS! week: isIOSDevice() ? 'date' : 'week', month: 'month', quarter: 'date', year: 'date', datetime: 'datetime-local', default: 'datetime-local', }; const nativeFormatForType = { date: 'Y-MM-DD', time: 'HH:mm', week: 'GGGG-[W]WW', month: 'Y-MM', 'datetime-local': 'Y-MM-DD[T]HH:mm', }; const DatePicker = class { constructor(hostRef) { registerInstance(this, hostRef); this.change = createEvent(this, "change", 7); this.portalId = `date-picker-calendar-${createRandomString()}`; this.documentClickListener = (event) => { if (event.composedPath().includes(this.textField)) { return; } const element = document.querySelector(`#${this.portalId}`); if (!element.contains(event.target)) { this.hideCalendar(); } }; this.formatValue = (value) => this.dateFormatter.formatDate(value, this.internalFormat); this.disabled = false; this.readonly = false; this.invalid = false; this.label = undefined; this.placeholder = undefined; this.helperText = undefined; this.required = false; this.value = undefined; this.type = 'datetime'; this.format = undefined; this.language = 'en'; this.formatter = undefined; this.internalFormat = undefined; this.showPortal = false; this.handleCalendarChange = this.handleCalendarChange.bind(this); this.handleInputElementChange = this.handleInputElementChange.bind(this); this.showCalendar = this.showCalendar.bind(this); this.dateFormatter = new DateFormatter(this.language); this.clearValue = this.clearValue.bind(this); this.hideCalendar = this.hideCalendar.bind(this); this.onInputClick = this.onInputClick.bind(this); this.nativeChangeHandler = this.nativeChangeHandler.bind(this); this.preventBlurFromCalendarContainer = this.preventBlurFromCalendarContainer.bind(this); } componentWillLoad() { this.useNative = !this.readonly && (isIOSDevice() || isAndroidDevice()); this.updateInternalFormatAndType(); } componentWillUpdate() { this.updateInternalFormatAndType(); } disconnectedCallback() { this.hideCalendar(); } render() { const inputProps = { onAction: this.clearValue, }; if (this.value && !this.readonly) { inputProps.trailingIcon = 'clear_symbol'; } if (this.useNative) { return (h("limel-input-field", { disabled: this.disabled, readonly: this.readonly, invalid: this.invalid, label: this.label, helperText: this.helperText, required: this.required, value: this.formatValue(this.value), type: this.nativeType, onChange: this.nativeChangeHandler })); } const dropdownZIndex = getComputedStyle(this.host).getPropertyValue('--dropdown-z-index'); const formatter = this.formatter || this.formatValue; return [ h("limel-input-field", Object.assign({ disabled: this.disabled, readonly: this.readonly, invalid: this.invalid, label: this.label, placeholder: this.placeholder, helperText: this.helperText, required: this.required, value: this.value ? formatter(this.value) : '', onFocus: this.showCalendar, onBlur: this.hideCalendar, onClick: this.onInputClick, onChange: this.handleInputElementChange, ref: (el) => (this.textField = el) }, inputProps)), h("limel-portal", { containerId: this.portalId, visible: this.showPortal, containerStyle: { 'z-index': dropdownZIndex } }, h("limel-flatpickr-adapter", { format: this.internalFormat, language: this.language, type: this.type, value: this.value, ref: (el) => (this.datePickerCalendar = el), isOpen: this.showPortal, formatter: formatter, onChange: this.handleCalendarChange })), ]; } updateInternalFormatAndType() { this.nativeType = nativeTypeForConsumerType[this.type || 'default']; this.nativeFormat = nativeFormatForType[this.nativeType]; if (this.useNative) { this.internalFormat = this.nativeFormat; } else if (this.formatter || this.format) { this.internalFormat = this.format; } else { this.internalFormat = this.dateFormatter.getDateFormat(this.type); } } nativeChangeHandler(event) { event.stopPropagation(); const date = this.dateFormatter.parseDate(event.detail, this.internalFormat); this.change.emit(date); } showCalendar(event) { this.showPortal = true; const inputElement = this.textField.shadowRoot.querySelector('input'); setTimeout(() => { this.datePickerCalendar.inputElement = inputElement; }); event.stopPropagation(); document.addEventListener('mousedown', this.documentClickListener, { passive: true, }); document.addEventListener('blur', this.preventBlurFromCalendarContainer, { capture: true, }); } preventBlurFromCalendarContainer(event) { // We don't want the input element to lose focus when we pick // a date in the calendar container. // This is also required in order to not close the non // automatically closing pickers (type datetime and time) // when you pick a value. if (event.relatedTarget === this.datePickerCalendar) { event.stopPropagation(); } } hideCalendar() { setTimeout(() => { this.showPortal = false; }); document.removeEventListener('mousedown', this.documentClickListener); document.removeEventListener('blur', this.preventBlurFromCalendarContainer); if (!this.pickerIsAutoClosing()) { this.fixFlatpickrFocusBug(); } } fixFlatpickrFocusBug() { // Flatpickr removes the focus from the input field // but the 'visual focus' is still there const mdcTextField = new MDCTextField(this.textField.shadowRoot.querySelector('.mdc-text-field')); mdcTextField.getDefaultFoundation().deactivateFocus(); mdcTextField.valid = !this.invalid; } handleCalendarChange(event) { const date = event.detail; event.stopPropagation(); if (this.pickerIsAutoClosing()) { this.hideCalendar(); } this.change.emit(date); } onInputClick(event) { if (this.disabled || this.readonly) { return; } if (this.showPortal) { return; } this.showCalendar(event); } handleInputElementChange(event) { if (event.detail === '') { this.clearValue(); } event.stopPropagation(); } pickerIsAutoClosing() { return this.type !== 'datetime' && this.type !== 'time'; } clearValue() { this.change.emit(null); } get host() { return getElement(this); } }; DatePicker.style = datePickerCss; export { DatePicker as limel_date_picker }; //# sourceMappingURL=limel-date-picker.entry.js.map