UNPKG

web-ui-pack

Version:
261 lines (260 loc) 9.4 kB
import dateCompareWithoutTime from "../helpers/dateCompareWithoutTime"; import dateCopyTime from "../helpers/dateCopyTime"; import dateFromString from "../helpers/dateFromString"; import dateToString from "../helpers/dateToString"; import localeInfo from "../objects/localeInfo"; import WUPTimeObject from "../objects/timeObject"; import WUPBaseComboControl from "./baseCombo"; import WUPCalendarControl from "./calendar"; WUPCalendarControl.$use(); const tagName = "wup-date"; export default class WUPDateControl extends WUPBaseComboControl { #ctr = this.constructor; static get $style() { return `${super.$style} :host { --ctrl-icon-img: var(--wup-icon-date); } :host > [menu] { overflow: hidden; } :host > [menu] > wup-calendar { margin: 0; }`; } static get mappedAttributes() { const m = super.mappedAttributes; m.min = { type: 4 }; m.max = { type: 4 }; m.firstweekday = { type: 1 }; m.startwith = { type: 2 }; m.sync = { type: 6 }; return m; } static $defaults = { ...WUPBaseComboControl.$defaults, ...WUPCalendarControl.$defaults, validationRules: { ...WUPBaseComboControl.$defaults.validationRules, min: (v, setV, c) => (v === undefined || dateCompareWithoutTime(v, setV, c._opts.utc) === -1) && __wupln(`Min value is ${c.valueToInput(setV)}`, "validation"), max: (v, setV, c) => (v === undefined || dateCompareWithoutTime(v, setV, c._opts.utc) === 1) && __wupln(`Max value is ${c.valueToInput(setV)}`, "validation"), exclude: (v, setV, c) => (v === undefined || setV.some((d) => dateCompareWithoutTime(v, d, c._opts.utc) === 0)) && __wupln(`This value is disabled`, "validation"), }, format: "", sync: null, }; get $initValue() { return super.$initValue; } set $initValue(v) { super.$initValue = v; this.setTimeValue(this.refTime, v, 5); } constructor() { super(); this.#ctr.$defaults.firstWeekDay ||= localeInfo.firstWeekDay; this._opts.firstWeekDay ||= this.#ctr.$defaults.firstWeekDay; this.#ctr.$defaults.format ||= localeInfo.date.toLowerCase(); this._opts.format ||= this.#ctr.$defaults.format; } parse(text) { if (!text) { return undefined; } return WUPCalendarControl.$parse(text, !!this._opts.utc); } parseInput(text) { const format = `${this._opts.format.toUpperCase()} hh:mm:ss.fff${this._opts.utc ? "Z" : ""}`; const v = dateFromString(text, format, { throwOutOfRange: true }) ?? undefined; return v; } canParseInput(_text) { return !this.refMask || this.refMask.isCompleted; } valueToStorage(v) { return dateToString(v, `yyyy-MM-dd${this._opts.utc ? "Z" : ""}`); } gotChanges(propsChanged) { WUPCalendarControl.prototype.gotChangesSharable.call(this); this._opts.format ||= "YYYY-MM-DD"; if (this._opts.format.toUpperCase().includes("MMM")) { this.throwError(`'MMM' in format isn't supported`); this._opts.format = "YYYY-MM-DD"; } this._opts.mask ||= this._opts.format .replace(/[yY]/g, "0") .replace(/dd|DD/, "00") .replace(/[dD]/, "#0") .replace(/mm|MM/, "00") .replace(/[mM]/, "#0"); this._opts.maskholder ||= this._opts.format.replace(/([mMdD]){1,2}/g, "$1$1"); const el = this.refTime; if (el) { if (this._opts.name && !el.$options.name) { el.$options.name = ""; } this.setTimeValidations(el); } super.gotChanges(propsChanged); } get validations() { const vls = super.validations; if (this._opts.min) vls.min = this._opts.min; if (this._opts.max) vls.max = this._opts.max; if (this._opts.exclude) vls.exclude = this._opts.exclude; return vls; } renderMenu(popup, menuId) { popup.$options.minWidthByTarget = false; const el = document.createElement("wup-calendar"); el.renderInput = () => { el.$refLabel.remove(); return { menuId }; }; el.focusItem = (a) => this.focusMenuItem(a); el.focus = () => true; el.gotFocus.call(el, new FocusEvent("focusin")); el.setInputValue = () => { }; el.gotFormChanges = () => { }; el.$refInput = this.$refInput; el.$options.validations = this.validations.required ? { required: true } : undefined; el.$options.startWith = this._opts.startWith; el.$options.exclude = this._opts.exclude; el.$options.max = this._opts.max; el.$options.min = this._opts.min; el.$options.utc = this._opts.utc; el.$options.name = undefined; el.$options.validationCase = 0; const v = this.$value; el.$initValue = v && !Number.isNaN(v.valueOf()) ? v : undefined; el.setValue = (val, reason) => { const r = WUPCalendarControl.prototype.setValue.call(el, val, reason); if (reason === 4) { this.selectValue(el.$value); } return r; }; el.$onChange = (e) => e.stopPropagation(); popup.appendChild(el); return el; } setValue(v, reason, skipInput = false) { const elTime = this.refTime; if (v) { let isCopied = false; if (skipInput) { const prev = this.$value || this.$initValue; prev && dateCopyTime(v, prev, this._opts.utc); isCopied = !!prev; } if (!isCopied && reason !== 1 && reason !== 5) { const vt = elTime?.$value; if (vt) { v = vt.copyToDate(v, this._opts.utc); } } } const isChanged = super.setValue(v, reason, skipInput); if (isChanged) { const c = this.$refPopup?.firstElementChild; if (c) { c._isStopChanges = true; c.$value = v && !Number.isNaN(v.valueOf()) ? v : undefined; setTimeout(() => (c._isStopChanges = false)); } } if (elTime) { this.setTimeValidations(elTime); if (reason === 1) { this.setTimeValue(elTime, v, reason); } else if (elTime.$value) { !elTime.$isEmpty && elTime.$validate(); } } return isChanged; } valueToInput(v) { if (v === undefined) { return ""; } return dateToString(v, this._opts.format.toUpperCase() + (this._opts.utc ? "Z" : "")); } focusMenuItem(next) { const el = this.$refPopup?.firstElementChild; if (el) { Object.getPrototypeOf(el).focusItem.call(el, next); } else { this.$refInput.removeAttribute("aria-activedescendant"); } this._focusedMenuItem = next; } focusMenuItemByKeydown(e) { const clnd = this.$refPopup?.firstElementChild; clnd.gotKeyDown.call(clnd, e); } get refTime() { const s = this._opts.sync; if (s && typeof s === "string") { this._opts.sync = this.findBySelector(s); } return this._opts.sync; } setTimeValue(elTime, v, reason) { if (!elTime) { return; } delete elTime.setValue; const t = v && new WUPTimeObject(v, this._opts.utc); switch (reason) { case 5: elTime.$initValue = t; break; case 1: elTime.$value = t; break; } const orig = Object.getPrototypeOf(elTime).setValue; elTime.setValue = (...args) => { const isChanged = orig.call(elTime, ...args); const dt = this.$value; if (isChanged && dt) { (elTime.$value || new WUPTimeObject(0, 0)).copyToDate(dt, this._opts.utc); } return isChanged; }; } setTimeValidations(elTime) { const v = this.$value; const obj = {}; const vld = this._opts.validations; if (v) { ["min", "max"].forEach((k) => { const dFrom = this._opts[k] || (vld && vld[k]); if (dFrom) { if (typeof dFrom === "function") { this.throwError("Impossible to sync [min] with time. Expected Date instead of function"); return; } const c = dateCompareWithoutTime(v, dFrom, this._opts.utc); obj[k] = c === 0 ? new WUPTimeObject(dFrom, this._opts.utc) : obj[k]; } }); } const o = elTime.$options; o.min = obj.min; o.max = obj.max; o.validations ||= {}; o.validations.required = !!vld?.required; o.validations.min = undefined; o.validations.max = undefined; } } customElements.define(tagName, WUPDateControl);