UNPKG

igniteui-webcomponents

Version:

Ignite UI for Web Components is a complete library of UI components, giving you the ability to build modern web applications using encapsulation and the concept of reusable components in a dependency-free approach.

399 lines 14.9 kB
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; import { getDateFormatter } from 'igniteui-i18n-core'; import { html } from 'lit'; import { eventOptions, property } from 'lit/decorators.js'; import { ifDefined } from 'lit/directives/if-defined.js'; import { live } from 'lit/directives/live.js'; import { addThemingController } from '../../theming/theming-controller.js'; import { convertToDate, isValidDate } from '../calendar/helpers.js'; import { addKeybindings, arrowDown, arrowLeft, arrowRight, arrowUp, ctrlKey, } from '../common/controllers/key-bindings.js'; import { addSlotController, setSlots } from '../common/controllers/slot.js'; import { registerComponent } from '../common/definitions/register.js'; import { addI18nController, formatDisplayDate, getDefaultDateTimeFormat, } from '../common/i18n/i18n-controller.js'; import { EventEmitterMixin } from '../common/mixins/event-emitter.js'; import { FormValueDateTimeTransformers } from '../common/mixins/forms/form-transformers.js'; import { createFormValueState } from '../common/mixins/forms/form-value.js'; import { partMap } from '../common/part-map.js'; import { styles } from '../input/themes/input.base.css.js'; import { styles as shared } from '../input/themes/shared/input.common.css.js'; import { all } from '../input/themes/themes.js'; import { IgcMaskInputBaseComponent, } from '../mask-input/mask-input-base.js'; import IgcValidationContainerComponent from '../validation-container/validation-container.js'; import { DatePart, DEFAULT_DATE_PARTS_SPIN_DELTAS, } from './date-part.js'; import { createDatePart, DateParts, DateTimeMaskParser, } from './datetime-mask-parser.js'; import { dateTimeInputValidators } from './validators.js'; const Slots = setSlots('prefix', 'suffix', 'helper-text', 'value-missing', 'range-overflow', 'range-underflow', 'custom-error', 'invalid'); export default class IgcDateTimeInputComponent extends EventEmitterMixin(IgcMaskInputBaseComponent) { static { this.tagName = 'igc-date-time-input'; } static { this.styles = [styles, shared]; } static register() { registerComponent(IgcDateTimeInputComponent, IgcValidationContainerComponent); } get __validators() { return dateTimeInputValidators; } get _targetDatePart() { return this._focused ? this._getDatePartAtCursor() : this._getDefaultDatePart(); } get _datePartDeltas() { return { ...DEFAULT_DATE_PARTS_SPIN_DELTAS, ...this.spinDelta }; } set inputFormat(val) { if (val) { this._applyMask(val); this._inputFormat = val; this._updateMaskDisplay(); } } get inputFormat() { return this._inputFormat || this._parser.mask; } set value(value) { this._formValue.setValueAndFormState(value); this._updateMaskDisplay(); } get value() { return this._formValue.value; } set min(value) { this._min = convertToDate(value); this._validate(); } get min() { return this._min; } set max(value) { this._max = convertToDate(value); this._validate(); } get max() { return this._max; } set displayFormat(value) { this._displayFormat = value; } get displayFormat() { return (this._displayFormat ?? this._inputFormat ?? this._defaultDisplayFormat); } set locale(value) { this._i18nController.locale = value; } get locale() { return this._i18nController.locale; } constructor() { super(); this._parser = new DateTimeMaskParser(); this._defaultDisplayFormat = ''; this._oldValue = null; this._min = null; this._max = null; this._i18nController = addI18nController(this, { defaultEN: {}, onResourceChange: this._handleResourceChange, }); this._themes = addThemingController(this, all); this._slots = addSlotController(this, { slots: Slots, }); this._formValue = createFormValueState(this, { initialValue: null, transformers: FormValueDateTimeTransformers, }); this.spinLoop = true; addKeybindings(this, { skip: () => this.readOnly, bindingDefaults: { triggers: ['keydownRepeat'] }, }) .set([ctrlKey, ';'], this._setCurrentDateTime) .set(arrowUp, this._keyboardSpin.bind(this, 'up')) .set(arrowDown, this._keyboardSpin.bind(this, 'down')) .set([ctrlKey, arrowLeft], this._navigateParts.bind(this, 0)) .set([ctrlKey, arrowRight], this._navigateParts.bind(this, 1)); } update(props) { if (props.has('displayFormat')) { this._updateDefaultDisplayFormat(); } if (props.has('locale')) { this._initializeDefaultMask(); } if (props.has('displayFormat') || props.has('locale')) { this._updateMaskDisplay(); } super.update(props); } _resolvePartNames(base) { const result = super._resolvePartNames(base); result.filled = result.filled || !this._isEmptyMask; return result; } _updateSetRangeTextValue() { this._updateValueFromMask(); } _emitInputEvent() { this._setTouchedState(); this.emitEvent('igcInput', { detail: this.value?.toString() }); } _handleResourceChange() { this._initializeDefaultMask(); this._updateMaskDisplay(); } _handleDragLeave() { if (!this._focused) { this._updateMaskDisplay(); } } _handleDragEnter() { if (!this._focused) { this._maskedValue = this._buildMaskedValue(); } } async _handleWheel(event) { if (!this._focused || this.readOnly) { return; } event.preventDefault(); event.stopPropagation(); const { start, end } = this._inputSelection; event.deltaY > 0 ? this.stepDown() : this.stepUp(); this._emitInputEvent(); await this.updateComplete; this.setSelectionRange(start, end); } async _handleFocus() { this._focused = true; if (this.readOnly) { return; } this._oldValue = this.value; if (!this.value) { this._maskedValue = this._parser.emptyMask; await this.updateComplete; this.select(); } else if (this.displayFormat !== this.inputFormat) { this._updateMaskDisplay(); } } _handleBlur() { this._focused = false; if (!(this._isMaskComplete() || this._isEmptyMask)) { const parsedDate = this._parser.parseDate(this._maskedValue); if (parsedDate) { this.value = parsedDate; } else { this.clear(); } } else { this._updateMaskDisplay(); } if (!this.readOnly && this._oldValue !== this.value) { this.emitEvent('igcChange', { detail: this.value }); } super._handleBlur(); } _setCurrentDateTime() { this.value = new Date(); this._emitInputEvent(); } _navigateParts(direction) { const position = this._calculatePartNavigationPosition(this._input?.value ?? '', direction); this.setSelectionRange(position, position); } _calculatePartNavigationPosition(inputValue, direction) { const cursorPos = this._maskSelection.start; const dateParts = this._parser.dateParts; if (direction === 0) { const part = dateParts.findLast((part) => part.type === DateParts.Literal && part.end < cursorPos); return part?.end ?? 0; } const part = dateParts.find((part) => part.type === DateParts.Literal && part.start > cursorPos); return part?.start ?? inputValue.length; } async _keyboardSpin(direction) { direction === 'up' ? this.stepUp() : this.stepDown(); this._emitInputEvent(); await this.updateComplete; this.setSelectionRange(this._maskSelection.start, this._maskSelection.end); } _updateMaskDisplay() { if (this._focused) { this._maskedValue = this._buildMaskedValue(); return; } if (!isValidDate(this.value)) { this._maskedValue = ''; return; } this._maskedValue = formatDisplayDate(this.value, this.locale, this.displayFormat); } async _updateInput(text, { start, end }) { const result = this._parser.replace(this._maskedValue, text, start, end); this._maskedValue = result.value; this._updateValueFromMask(); this.requestUpdate(); if (start !== this.inputFormat.length) { this._emitInputEvent(); } await this.updateComplete; this._input?.setSelectionRange(result.end, result.end); } _performStep(datePart, delta, isDecrement) { const part = datePart || this._targetDatePart; const { start, end } = this._inputSelection; this.value = this._calculateSpunValue(part, delta, isDecrement); this.updateComplete.then(() => this._input?.setSelectionRange(start, end)); } _calculateSpunValue(datePart, delta, isDecrement) { const effectiveDelta = delta || this._datePartDeltas[datePart] || 1; const spinAmount = isDecrement ? -Math.abs(effectiveDelta) : Math.abs(effectiveDelta); return this._spinDatePart(datePart, spinAmount); } _spinDatePart(datePart, delta) { if (!isValidDate(this.value)) { return new Date(); } const newDate = new Date(this.value.getTime()); const partType = datePart; let part = this._parser.getPartByType(partType); if (!part) { part = createDatePart(partType, { start: 0, end: 0, format: '' }); } let amPmValue; if (datePart === DatePart.AmPm) { const formatPart = this._parser.getPartByType(DateParts.AmPm); if (formatPart) { amPmValue = this._maskedValue.substring(formatPart.start, formatPart.end); } } part.spin(delta, { date: newDate, spinLoop: this.spinLoop, amPmValue, originalDate: this.value, }); return newDate; } _updateDefaultDisplayFormat() { this._defaultDisplayFormat = getDateFormatter().getLocaleDateTimeFormat(this.locale); } _applyMask(formatString) { const previous = this._parser.mask; this._parser.mask = formatString; if (!this.placeholder || previous === this.placeholder) { this.placeholder = this._parser.mask; } } _buildMaskedValue() { return isValidDate(this.value) ? this._parser.formatDate(this.value) : this._maskedValue || this._parser.emptyMask; } _initializeDefaultMask() { this._updateDefaultDisplayFormat(); if (!this._inputFormat) { this._applyMask(getDefaultDateTimeFormat(this.locale)); } } _getDatePartAtCursor() { return this._parser.getDatePartForCursor(this._inputSelection.start) ?.type; } _getDefaultDatePart() { return (this._parser.getPartByType(DateParts.Date)?.type ?? this._parser.getPartByType(DateParts.Hours)?.type ?? this._parser.getFirstDatePart()?.type); } _isMaskComplete() { return !this._maskedValue.includes(this.prompt); } _updateValueFromMask() { if (!this._isMaskComplete()) { this.value = null; return; } const parsedDate = this._parser.parseDate(this._maskedValue); this.value = isValidDate(parsedDate) ? parsedDate : null; } stepUp(datePart, delta) { this._performStep(datePart, delta, false); } stepDown(datePart, delta) { this._performStep(datePart, delta, true); } clear() { this._maskedValue = ''; this.value = null; } hasDateParts() { return this._parser.hasDateParts(); } hasTimeParts() { return this._parser.hasTimeParts(); } _renderInput() { return html ` <input type="text" part=${partMap(this._resolvePartNames('input'))} name=${ifDefined(this.name)} .value=${live(this._maskedValue)} .placeholder=${this.placeholder || this._parser.emptyMask} ?readonly=${this.readOnly} ?disabled=${this.disabled} @blur=${this._handleBlur} @focus=${this._handleFocus} @input=${this._handleInput} @wheel=${this._handleWheel} @keydown=${this._setMaskSelection} @click=${this._handleClick} @cut=${this._setMaskSelection} @compositionstart=${this._handleCompositionStart} @compositionend=${this._handleCompositionEnd} @dragenter=${this._handleDragEnter} @dragleave=${this._handleDragLeave} @dragstart=${this._setMaskSelection} /> `; } } __decorate([ property({ attribute: 'input-format' }) ], IgcDateTimeInputComponent.prototype, "inputFormat", null); __decorate([ property({ converter: convertToDate }) ], IgcDateTimeInputComponent.prototype, "value", null); __decorate([ property({ converter: convertToDate }) ], IgcDateTimeInputComponent.prototype, "min", null); __decorate([ property({ converter: convertToDate }) ], IgcDateTimeInputComponent.prototype, "max", null); __decorate([ property({ attribute: 'display-format' }) ], IgcDateTimeInputComponent.prototype, "displayFormat", null); __decorate([ property({ attribute: false }) ], IgcDateTimeInputComponent.prototype, "spinDelta", void 0); __decorate([ property({ type: Boolean, attribute: 'spin-loop' }) ], IgcDateTimeInputComponent.prototype, "spinLoop", void 0); __decorate([ property() ], IgcDateTimeInputComponent.prototype, "locale", null); __decorate([ eventOptions({ passive: false }) ], IgcDateTimeInputComponent.prototype, "_handleWheel", null); //# sourceMappingURL=date-time-input.js.map