UNPKG

duoyun-ui

Version:

A lightweight desktop UI component library, implemented using Gem

240 lines 7.92 kB
import { render, TemplateResult } from '@mantou/gem/lib/element'; import { connect, createStore } from '@mantou/gem/lib/store'; import { cleanObject } from '@mantou/gem/lib/utils'; import { isNullish } from '../lib/types'; export function convertToMap(list, key, value, fallback) { const argLength = arguments.length; const isSelf = argLength === 2; const hasFallback = argLength === 4; const result = {}; list.forEach((item) => { if (item) { // missing `value` is self result[item[key]] = value ? item[value] : item; } }); return new Proxy(result, { get: (target, prop) => { return prop in target || isSelf ? target[prop] : hasFallback ? fallback : prop; }, }); } /**Get Cascader/Tree max deep*/ export function getCascaderDeep(list, cascaderKey) { const getChildren = (t) => { const children = t[cascaderKey]; if (Array.isArray(children)) { let l = 0; children.forEach((e) => { const ll = getChildren(e); if (ll > l) l = ll; }); return 1 + l; } return 0; }; let l = 0; list.forEach((e) => { const ll = getChildren(e); if (ll > l) l = ll; }); return 1 + l; } /** * Get the value from the bottom layer, * compare the new value of the upper layer to choose a new value, bubbling to the top layer */ export function getCascaderBubbleWeakMap(list, cascaderKey, getValue, comparerFn = (a) => a, setValueCallback) { const map = new WeakMap(); const getItemValue = (e) => { const v = map.get(e) ?? getValue(e); if (isNullish(v)) return; return v; }; const check = (l) => l?.forEach((e) => { check(e[cascaderKey]); let value = getItemValue(e); e[cascaderKey]?.forEach((i) => { const v = getItemValue(i); value = isNullish(value) ? v : comparerFn(v, value); }); if (!isNullish(value)) { map.set(e, value); setValueCallback?.(e, value); } }); check(list); return map; } /**Simple proxy object, use prop name as a fallback when reading prop */ export function proxyObject(object) { return new Proxy(object, { get: (target, prop) => { return prop in target ? target[prop] : prop; }, }); } /**Deep read prop */ export function readProp(obj, paths, options = {}) { if (!Array.isArray(paths)) return obj[paths]; const len = paths.length; return paths.reduce((p, c, i) => { if (!options.fill) return p?.[c]; if (options.onlyFillIntermediate && i === len - 1) return p[c]; return (p[c] ||= {}); }, obj); } /**Only let the last add Promise take effect, don’t care about the order of Resolve */ export class OrderlyPromisePool { pool = []; add(promise, callback) { const newIndex = this.pool.length; const removeCallback = () => this.pool.splice(newIndex, 1, null); this.pool.push(callback); promise .then((r) => { if (this.pool[this.pool.length - 1] === callback) { callback(r); this.pool.length = 0; } else { removeCallback(); } }) .catch((err) => { removeCallback(); throw err; }); } } export var ComparerType; (function (ComparerType) { ComparerType["Eq"] = "eq"; ComparerType["Gte"] = "gte"; ComparerType["Lte"] = "lte"; ComparerType["Lt"] = "lt"; ComparerType["Gt"] = "gt"; ComparerType["Ne"] = "ne"; ComparerType["Miss"] = "miss"; ComparerType["Have"] = "have"; })(ComparerType || (ComparerType = {})); /**Serialize comparer */ export function comparer(a, comparerType, b) { const aNum = Number(a); const bNum = Number(b); const isNumber = !Number.isNaN(aNum) && !Number.isNaN(aNum); switch (comparerType) { case ComparerType.Eq: // biome-ignore lint/suspicious/noDoubleEquals: <explanation> return a == b; case ComparerType.Ne: // biome-ignore lint/suspicious/noDoubleEquals: <explanation> return a != b; case ComparerType.Gt: return isNumber ? aNum > bNum : a > b; case ComparerType.Gte: return isNumber ? aNum >= bNum : a >= b; case ComparerType.Lt: return isNumber ? aNum < bNum : a < b; case ComparerType.Lte: return isNumber ? aNum <= bNum : a <= b; case ComparerType.Have: return a?.includes?.(b); case ComparerType.Miss: return !a?.includes?.(b); default: return false; } } /**Serialized `TemplateResult` */ const div = document.createElement('div'); export function getStringFromTemplate(input) { if (input instanceof TemplateResult) { render(input, div); return div.textContent || ''; } return String(input); } /**Segmentation search word */ export function splitString(s) { return s.split(/(?:\s|\/)+/); } /**Search */ export function isIncludesString(origin, search, caseSensitive = false) { const getStr = (s) => (caseSensitive ? s : s.toLowerCase()).trim(); const oString = getStr(getStringFromTemplate(origin)); const sString = getStr(search); return splitString(sString).some((s) => oString.includes(s)); } /**Create auto cache(localStorage) Store */ export function createCacheStore(storageKey, initStore, options) { const getKey = () => { const prefix = typeof options?.prefix === 'function' ? options.prefix() : options?.prefix; return prefix ? `${prefix}@${storageKey}` : storageKey; }; const getStoreStore = (key) => { let storeCache = undefined; try { storeCache = JSON.parse(localStorage.getItem(key) || '{}'); } catch { // } return storeCache ? { ...initStore, ...storeCache } : initStore; }; const cacheExcludeKeys = new Set(options?.cacheExcludeKeys || []); let key = getKey(); const store = createStore(getStoreStore(key)); if (options?.depStore) { connect(options.depStore, () => { const newKey = getKey(); if (newKey !== key) { key = newKey; cleanObject(store)(getStoreStore(newKey)); } }); } const saveStore = () => { localStorage.setItem(key, JSON.stringify(Object.fromEntries(Object.entries(store).filter(([k]) => !cacheExcludeKeys.has(k))))); }; addEventListener('pagehide', saveStore); return { store, saveStore }; } // 是链接需要使用 img 渲染 export function isRemoteIcon(icon) { return typeof icon === 'string' && !!icon.trim().match(/^(http|[./])/); } /** * Pass additional fields * * not support async function */ export class DyPromise extends Promise { static new(executor, props) { const instance = new DyPromise(executor); return Object.assign(instance, props); } // biome-ignore lint/suspicious/noThenProperty: extends then(onfulfilled, onrejected) { const result = super.then(onfulfilled, onrejected); return Object.assign(result, this); } catch(onrejected) { const result = super.catch(onrejected); return Object.assign(result, this); } finally(onfinally) { const result = super.finally(onfinally); return Object.assign(result, this); } } // 不应该以发生错误的方式来处理拒绝的 Promise // 缺点:同时有个相同原因的 Promise 需要用错误处理时会被忽略 export const ignoredPromiseReasonSet = new WeakSet(); //# sourceMappingURL=utils.js.map