UNPKG

@jay-js/system

Version:

A powerful and flexible TypeScript library for UI, state management, lazy loading, routing and managing draggable elements in modern web applications.

129 lines 4.58 kB
import { state } from "../core/state.js"; import { subscriberManager } from "../core/subscriber.js"; export const REACTIVE_MARKER = Symbol("reactive"); export const SETVALUE_MARKER = Symbol("setValue"); export const SETCHILD_MARKER = Symbol("setChildren"); export const DERIVED_MARKER = Symbol("derived"); let derivedIdCounter = 0; /** * Creates a derived state that automatically recalculates whenever states * accessed within the function change * * @template T Type of derived value * @param fn Function that calculates the derived value * @returns A state that updates when any dependency changes */ export function derived(fn) { const derivedState = state(fn()); const derivedId = ++derivedIdCounter; const effectFn = () => { derivedState.set(fn()); }; // Adiciona metadados à função para gerar hash único effectFn[DERIVED_MARKER] = true; effectFn._derivedId = derivedId; effect(effectFn); return derivedState; } /** * Executes a function and automatically monitors any state access * to create a reactive effect. The function will be executed again when * any accessed state changes. * * @param fn Function to be executed as an effect */ export function effect(fn) { subscriberManager.setSubscriber(fn); fn(); subscriberManager.clearSubscriber(); } /** * Creates a helper for setting values in objects reactively. * When a state is accessed within the function, a subscription is automatically * created to update the value when the state changes. * * @param fn Function that returns the value to be set * @param element Optional HTMLElement to track subscriptions for automatic cleanup * @returns Function for setting values in objects */ export function values(fn, element) { const _set_value = Object.assign(() => { if (_set_value._path.length > 0) { let target = _set_value._object_ref; for (let i = 0; i < _set_value._path.length - 1; i++) { if (!target[_set_value._path[i]]) { target[_set_value._path[i]] = {}; } target = target[_set_value._path[i]]; } const lastKey = _set_value._path[_set_value._path.length - 1]; target[lastKey] = _set_value._fn(); return; } _set_value._object_ref = _set_value._fn(); // Isso aqui é para o caso de setar o objeto todo, Mas talvez não faça sentido }, { _object_ref: undefined, _path: [], _fn: fn, _element: element, [SETVALUE_MARKER]: true, }); return Object.assign((object, ...path) => { _set_value._object_ref = object; _set_value._path = path; effect(_set_value); }, { [REACTIVE_MARKER]: true, }); } /** * Creates a reactive effect for updating children of a DOM node. * Automatically monitors state changes and triggers child updates. * * @param fn Function that generates the child elements * @param nodeRefId Reference identifier for the target node * @param setChild Callback function to execute when children need to be updated * @param element Optional HTMLElement to track subscriptions for automatic cleanup */ export function childs(fn, nodeRefId, setChild, element) { const _set_child = Object.assign(setChild, { _fn: fn, _ref: nodeRefId, _element: element, [SETCHILD_MARKER]: true, }); effect(_set_child); } /** * Generates a unique hash identifier for a function. * Takes into account special markers (SETVALUE_MARKER, SETCHILD_MARKER) to create * unique identifiers for reactive functions with additional metadata. * * @param fn Function to generate hash for * @returns Hexadecimal hash string with optional suffix based on function markers */ export function generateFunctionHash(fn, path) { let suffix = ""; let _fn = fn; if (fn[SETVALUE_MARKER]) { suffix = `__prop:${fn._path.join(".")}`; _fn = fn._fn; } if (fn[SETCHILD_MARKER]) { suffix = `__childref:${fn._ref}`; _fn = fn._fn; } if (fn[DERIVED_MARKER]) { suffix = `${suffix}__derived:${fn._derivedId}`; } suffix = path ? `${suffix}__target:${path}` : suffix; const _fn_string = _fn.toString(); let hash = 0; for (let i = 0; i < _fn_string.length; i++) { const char = _fn_string.charCodeAt(i); hash = (hash << 5) - hash + char; hash |= 0; } return `${Math.abs(hash).toString(16)}${suffix ? suffix : ""}`; } //# sourceMappingURL=helpers.js.map