UNPKG

@3mo/date-time-fields

Version:

Date time fields let people select dates, date-ranges, and times.

119 lines (114 loc) 3.53 kB
import { __decorate } from "tslib"; import { Component, css, event, eventOptions, html, property, query, queryAll } from '@a11d/lit'; export class DateList extends Component { constructor() { super(...arguments); this._navigateOnScroll = false; } get zero() { return 0; } static get styles() { return css ` :host { position: relative; } mo-scroller { min-width: 50px; scrollbar-width: none; } .selector { position: absolute; transform: translateY(-50%); inset-block-start: 50%; inset-inline: 0; width: 100%; height: 32px; border-block: 2px dashed var(--mo-color-gray-transparent); } .pad { height: 200px; } mo-selectable-list-item { min-height: 32px; padding-block: 8px; scroll-snap-align: center; } `; } connected() { this.scrollIntoItem('navigating', 'instant'); } get template() { return this.navigationDate === undefined ? html.nothing : html ` <div class='selector'></div> <mo-scroller snapType='y mandatory' @scroll=${this.handleScroll} @scrollend=${this.handleScroll} @mouseenter=${() => this.navigateOnScroll = true} @mouseleave=${() => this.navigateOnScroll = false} @touchstart=${() => this.navigateOnScroll = true} @touchend=${() => this.navigateOnScroll = false} > <mo-selectable-list @change=${() => this.scrollIntoItem('selected', 'smooth')}> <div class='pad'></div> ${this.listItemsTemplate} <div class='pad'></div> </mo-selectable-list> </mo-scroller> `; } async scrollIntoItem(key, behavior = 'smooth') { await this.updateComplete; const item = key === 'navigating' ? this.navigatingItem : this.selectedItem; item?.scrollIntoView({ block: 'center', behavior }); } get navigateOnScroll() { return this._navigateOnScroll; } set navigateOnScroll(value) { if (value) { this._navigateOnScroll = value; } else { setTimeout(() => this._navigateOnScroll = value, 100); } } handleScroll(e) { if (e.type === 'scroll' && 'onscrollend' in HTMLElement.prototype) { return; } if (!this.navigateOnScroll) { return; } const middleY = this.selector.getBoundingClientRect().y; const middleItem = this.items.reduce((closest, item) => { const itemY = item.getBoundingClientRect().y; return Math.abs(itemY - middleY) < Math.abs(closest.getBoundingClientRect().y - middleY) ? item : closest; }); middleItem?.dispatchEvent(new CustomEvent('navigate')); } } __decorate([ event() ], DateList.prototype, "change", void 0); __decorate([ event() ], DateList.prototype, "navigate", void 0); __decorate([ property({ type: Object, event: 'navigate' }) ], DateList.prototype, "navigationDate", void 0); __decorate([ property({ type: Object }) ], DateList.prototype, "value", void 0); __decorate([ query('.selector') ], DateList.prototype, "selector", void 0); __decorate([ queryAll('mo-selectable-list-item') ], DateList.prototype, "items", void 0); __decorate([ query('mo-selectable-list-item[data-navigating]') ], DateList.prototype, "navigatingItem", void 0); __decorate([ query('mo-selectable-list-item[selected]') ], DateList.prototype, "selectedItem", void 0); __decorate([ eventOptions({ passive: true }) ], DateList.prototype, "handleScroll", null);