UNPKG

reblendjs

Version:

ReblendJs uses Reactjs pradigm to build UI components, with isolated state for each components.

284 lines (253 loc) 10.1 kB
/* eslint-disable @typescript-eslint/no-explicit-any */ import { REBLEND_PRIMITIVE_ELEMENT_NAME } from 'reblend-typing' import * as ReblendTyping from 'reblend-typing' import { type BaseComponent } from './BaseComponent' type SymbolsType = { ReblendNode: symbol ReblendVNode: symbol ReblendLazyNode: symbol ReblendLazyVNode: symbol ReactToReblendNode: symbol ReactToReblendVNode: symbol ReblendNodeStandard: symbol ReblendVNodeStandard: symbol } const Symbols: SymbolsType = { ReblendNode: Symbol('Reblend.Node'), ReblendVNode: Symbol('Reblend.VNode'), ReblendLazyNode: Symbol('Reblend.Lazy.Node'), ReblendLazyVNode: Symbol('Reblend.Lazy.VNode'), ReactToReblendNode: Symbol('React.Reblend.Node'), ReactToReblendVNode: Symbol('React.Reblend.VNode'), ReblendNodeStandard: Symbol('Reblend.Node.Standard'), ReblendVNodeStandard: Symbol('Reblend.VNode.Standard'), } export enum ReblendNodeTypeDict { ReblendNode = 'ReblendNode', ReblendVNode = 'ReblendVNode', ReblendLazyNode = 'ReblendLazyNode', ReblendLazyVNode = 'ReblendLazyVNode', ReactToReblendNode = 'ReactToReblendNode', ReactToReblendVNode = 'ReactToReblendVNode', ReblendNodeStandard = 'ReblendNodeStandard', ReblendVNodeStandard = 'ReblendVNodeStandard', } export function addSymbol(type: ReblendNodeTypeDict, obj: object) { const symb = Symbols[type] if (!obj || !symb) { return false } obj[symb] = true return obj[symb] } /** * Checks if the given element has a name other than 'BaseComponent'. * * @param {typeof BaseComponent} element - The element to check. * @returns {boolean} `true` if the element has a name and it is not 'BaseComponent', otherwise `false`. */ export function hasName(element: typeof BaseComponent): boolean { return !!(element?.ELEMENT_NAME && element.ELEMENT_NAME !== 'BaseComponent') } /** * Checks if the provided node is a rendered Reblend node. * * @param {any} node - The node to check. * @returns {boolean} `true` if the node is a rendered Reblend node, otherwise `false`. */ export function isReblendRenderedNode(node: any): boolean { return node && typeof node === 'object' && node![Symbols.ReblendNode] } /** * Checks if the provided node is a virtual Reblend node. * * @param {any} node - The node to check. * @returns {boolean} `true` if the node is a virtual Reblend node, otherwise `false`. */ export function isReblendVirtualNode(node: any): boolean { return node && typeof node === 'object' && node![Symbols.ReblendVNode] } /** * Checks if the provided node is a rendered Reblend lazy node. * * @param {any} node - The node to check. * @returns {boolean} `true` if the node is a rendered Reblend lazy node, otherwise `false`. */ export function isReblendRenderedLazyNode(node: any): boolean { return node && typeof node === 'object' && node![Symbols.ReblendLazyNode] } /** * Checks if the provided node is a virtual Reblend lazy node. * * @param {any} node - The node to check. * @returns {boolean} `true` if the node is a virtual Reblend lazy node, otherwise `false`. */ export function isReblendLazyVirtualNode(node: any): boolean { return node && typeof node === 'object' && node![Symbols.ReblendLazyVNode] } /** * Checks if the provided node is a standard rendered Reblend node. * * @param {any} node - The node to check. * @returns {boolean} `true` if the node is a standard rendered Reblend node, otherwise `false`. */ export function isReblendRenderedNodeStandard(node: any): boolean { return node && typeof node === 'object' && node![Symbols.ReblendNodeStandard] } /** * Checks if the provided node is a standard virtual Reblend node. * * @param {any} node - The node to check. * @returns {boolean} `true` if the node is a standard virtual Reblend node, otherwise `false`. */ export function isReblendVirtualNodeStandard(node: any): boolean { return node && typeof node === 'object' && node![Symbols.ReblendVNodeStandard] } /** * Checks if the provided node is a React to Reblend rendered node. * * @param {any} node - The node to check. * @returns {boolean} `true` if the node is a React to Reblend rendered node, otherwise `false`. */ export function isReactToReblendRenderedNode(node: any): boolean { return node && typeof node === 'object' && node![Symbols.ReactToReblendNode] } /** * Checks if the provided node is a React to Reblend virtual node. * * @param {any} node - The node to check. * @returns {boolean} `true` if the node is a React to Reblend virtual node, otherwise `false`. */ export function isReactToReblendVirtualNode(node: any): boolean { return node && typeof node === 'object' && node![Symbols.ReactToReblendVNode] } /** * Checks if the provided node is a standard virtual node. * * @param {any} node - The node to check. * @returns {boolean} `true` if the node is a standard virtual node, otherwise `false`. */ export function isStandardVirtualNode(node: any): boolean { return node && typeof node === 'object' && node![Symbols.ReblendVNodeStandard] } /** * Checks if the provided element is a Reblend primitive element. * * @param {any} element - The element to check. * @returns {boolean} `true` if the element is a Reblend primitive element, otherwise `false`. */ export function isReblendPrimitiveElement(element: any): boolean { return !isPrimitive(element) && element.displayName === REBLEND_PRIMITIVE_ELEMENT_NAME } /** * Checks if the provided data is a primitive type. * Primitive types include string, number, boolean, bigint, null, undefined, and symbol. * * @param {any} data - The data to check. * @returns {boolean} `true` if the data is a primitive, otherwise `false`. */ export function isPrimitive(data: any): boolean { const primitves = ['string', 'number', 'boolean', 'bigint', 'null', 'undefined', 'symbol'] const dataType = typeof data return primitves.some((primitve) => primitve === (data === null ? 'null' : dataType)) } /** * Checks if the given object is an array-like structure by verifying that it contains array-specific methods and properties. * * @param {unknown} obj - The object to check. * @returns {boolean} `true` if the object is an array-like structure, otherwise `false`. */ export function isArray(obj: unknown): boolean { const arrayProperties = ['pop', 'push', 'length', 'shift', 'unshift', 'splice', 'slice', 'find', 'includes'] return typeof obj === 'object' && arrayProperties.every((property) => property in obj!) } /** * Checks if the provided display name represents a React node. * * @param {ReblendTyping.IAny} displayName - The display name to check. * @returns {boolean} `true` if the display name represents a React node, otherwise `false`. */ export function isReactNode(displayName: ReblendTyping.IAny): boolean { return ( displayName && (typeof displayName === 'object' || typeof displayName === 'function') && !('construct' in displayName && 'mountOn' in displayName && 'createInnerHtmlElements' in displayName.prototype) && ('$$typeof' in displayName || (displayName.prototype && displayName.prototype.isReactComponent)) ) } /** * Checks if the provided display name represents a Lazy node. * * @param {ReblendTyping.IAny} displayName - The display name to check. * @returns {boolean} `true` if the display name represents a Promise Instance, otherwise `false`. */ export function isLazyNode(displayName: ReblendTyping.IAny): boolean { return displayName && typeof displayName === 'object' && displayName instanceof Promise } /** * Checks if a node is a standard HTML element or a Reblend primitive element. * * @param {ReblendTyping.Component | HTMLElement} node - The node to check. * @returns {boolean} - True if the node is standard or a Reblend primitive element, false otherwise. */ export function isStandard<P, S>(node: ReblendTyping.Component<P, S> | HTMLElement) { if (!node) { return false } return isReblendRenderedNodeStandard(node) || isReblendPrimitiveElement(node) } /** * Checks if a node is a Reblend HTML element or a Reblend React HTML element. * * @param {ReblendTyping.Component | HTMLElement} node - The node to check. * @returns {boolean} - True if the node is Reblend or a Reblend React element, false otherwise. */ export function isNonStandard<P, S>(node: ReblendTyping.Component<P, S> | HTMLElement) { if (!node) { return false } return isReblendRenderedNode(node) || isReactToReblendRenderedNode(node) } /** * Determines if a given node is a text node. * * @param {Node} node - The node to check. * @returns {boolean} - True if the node is a text node, otherwise false. */ export function isTextNode(node: Node): node is Text { return node?.nodeType === Node.TEXT_NODE } /** * Checks whether the given data is empty (undefined or null). * * @param {*} data - The data to check. * @returns {boolean} - True if the data is empty, otherwise false. */ export function isEmpty(data: any) { return data === undefined || data === null } /** * Extends the prototype of the target object with the provided prototype, skipping constructors and existing functions. * * @param {any} target - The target object to extend. * @param {any} prototype - The prototype object to copy properties and methods from. */ export function extendPrototype(target: any, prototype: any): void { // If there's a prototype chain, continue copying from the prototype chain const proto = Object.getPrototypeOf(prototype) if (proto && proto !== Object.prototype) { extendPrototype(target, proto) } const descriptors = Object.getOwnPropertyDescriptors(prototype) for (const key in descriptors) { if (Object.prototype.hasOwnProperty.call(descriptors, key)) { // Skip the constructor if (key === 'constructor') continue const descriptor = descriptors[key] // Avoid replacing existing functions on the target //if (!(key in target) || (typeof descriptor.value !== 'function' && !(key in target))) { Object.defineProperty(target, key, descriptor) //} } } }