UNPKG

vueless

Version:

Vue Styleless UI Component Library, powered by Tailwind CSS.

187 lines (156 loc) • 4.75 kB
import type { UnknownObject } from "../types.ts"; import { Comment, Text, Fragment } from "vue"; import type { Slot, VNode } from "vue"; /** * Deeply clone given object (same as lodash.cloneDeep). */ export function cloneDeep(entity: unknown, cache = new WeakMap()): unknown | UnknownObject { // primitives if (Object(entity) !== entity || !entity) { return entity; } // cyclic reference if (cache.has(entity)) { return cache.get(entity); } const result = entity instanceof Set ? new Set(entity) : entity instanceof Map ? new Map(Array.from(entity, ([key, val]) => [key, cloneDeep(val, cache)])) : entity instanceof Date ? new Date(entity) : entity instanceof RegExp ? new RegExp(entity.source, entity.flags) : entity.constructor ? new (entity.constructor as { new (): typeof entity })() : Object.create(null); cache.set(entity, result); return Object.assign( result, ...Object.keys(entity).map((key) => ({ [key]: cloneDeep((entity as Record<string | number, unknown>)[key], cache), })), ); } /** * Creates a debounced function with delay (same as lodash.debounce). */ export function createDebounce<T extends unknown[]>(func: (...args: T) => void, ms: number) { let timeout: ReturnType<typeof setTimeout>; return function (this: unknown, ...args: T) { clearTimeout(timeout); timeout = setTimeout(() => func.apply(this, args), ms); }; } /** * Checks if a Vue slot is defined and contains actual content. * * @param slot - The Vue slot to check. * @param props - Optional props to pass to the slot function. * @returns {boolean} True if the slot exists and contains non-empty content, false otherwise. * * @remarks * A slot is considered empty if it: * - Is undefined or null * - Contains only comments * - Contains only empty text nodes * - Contains only empty fragments */ export function hasSlotContent(slot: Slot | undefined | null, props = {}): boolean { type Args = VNode | VNode[]; const toArray = (arg: Args) => { return Array.isArray(arg) ? arg : [arg]; }; const isVNodeEmpty = (vnode: Args) => { return ( !vnode || toArray(vnode).every((vnode) => { return ( vnode.type === Comment || (vnode.type === Text && !vnode.children?.length) || (vnode.type === Fragment && !vnode.children?.length) ); }) ); }; if (!slot) { return false; } return !isVNodeEmpty(slot(props)); } /** * Change page title in runtime by provided config. */ export function setTitle({ title = "", separator = " / ", suffix = "" }) { if (isCSR) { document.title = title ? title + separator + suffix : suffix; } } /** * Generates simple unique identifier. */ export function getRandomId(length = 15) { const characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; const charactersLength = characters.length; let id = ""; while (id.length < length) { id += characters.charAt(Math.floor(Math.random() * charactersLength)); } return id; } /** * Check is code rendering on the server side. */ export const isSSR: boolean = typeof window === "undefined"; /** * Check is code rendering on the client side. */ export const isCSR: boolean = typeof window !== "undefined"; /** * Set cookie on the client side */ export function setCookie(name: string, value: string, attributes = {} as UnknownObject) { attributes = { path: "/", ...attributes, }; if (attributes.expires instanceof Date) { attributes.expires = attributes.expires.toUTCString(); } let updatedCookie = encodeURIComponent(name) + "=" + encodeURIComponent(value); for (const attributeKey in attributes) { updatedCookie += "; " + attributeKey; const attributeValue = attributes[attributeKey]; if (attributeValue !== true) { updatedCookie += "=" + attributeValue; } } document.cookie = updatedCookie; } /** * Get cookie on the client side */ export function getCookie(name: string) { const matches = document.cookie.match( new RegExp("(?:^|; )" + name.replace(/([\.$?*|{}\(\)\[\]\\\/\+^])/g, "\\$1") + "=([^;]*)"), ); return matches ? decodeURIComponent(matches[1]) : undefined; } /** * Delete cookie on the client side */ export function deleteCookie(name: string) { setCookie(name, "", { "max-age": -1, }); } export function isEmptyValue(value: object | null | undefined | string | unknown) { return ( value === null || value === undefined || value === "" || (Array.isArray(value) && value.length === 0) || (typeof value === "object" && !Object.keys(value).length) ); }