diff --git a/build/index.d.ts b/build/index.d.ts index 8861999..23b2294 100644 --- a/build/index.d.ts +++ b/build/index.d.ts @@ -7,6 +7,7 @@ import { JSXInternal } from './jsx'; export * from './jsx'; declare global { export import JSX = JSXInternal; + const FRAGMENT = "FRAGMENT"; } export * from './types'; export { cleanUp, createEffect, createSignal, render, createPromise, createRef, computed, createElement, lazy, ArraySignal, BaseSignal, ObjectSignal, PrimitiveSignal, PublicArraySignal, PublicObjectSignal, PublicSignal, Ref, }; diff --git a/build/jsx.d.ts b/build/jsx.d.ts index 9245ad3..91e1988 100644 --- a/build/jsx.d.ts +++ b/build/jsx.d.ts @@ -1,13 +1,8 @@ import { Ref } from './index'; -import { Fiber } from './types'; -type Defaultize = Props extends any ? Partial>> & // Include the remaining properties from Props -Pick> : never; +type Defaultize = Props extends any ? Partial>> & Pick> : never; type Booleanish = boolean | "true" | "false"; -/** [MDN Reference](https://developer.mozilla.org/docs/Web/API/ToggleEvent) */ interface ToggleEvent extends Event { - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/ToggleEvent/newState) */ readonly newState: string; - /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/ToggleEvent/oldState) */ readonly oldState: string; } declare var ToggleEvent: { @@ -35,11 +30,8 @@ export interface RefractDOMAttributes extends Attributes { __html: string; }; } -/** [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/API/CommandEvent) */ interface CommandEvent extends Event { - /** [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/API/CommandEvent/source) */ readonly source: Element | null; - /** [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/API/CommandEvent/command) */ readonly command: string; } declare var CommandEvent: { @@ -64,7 +56,7 @@ export declare namespace JSXInternal { export type ElementType

= { [K in keyof IntrinsicElements]: P extends IntrinsicElements[K] ? K : never; }[keyof IntrinsicElements] | ComponentType

; - export type Element = Fiber; + export type Element = ComponentChild; export type ElementClass = ComponentType; export interface ElementAttributesProperty { props: any; @@ -81,13 +73,7 @@ export declare namespace JSXInternal { export interface CSSProperties extends AllCSSProperties, DOMCSSProperties { cssText?: string | null; } - export interface SignalLike { - value: T; - peek(): T; - subscribe(fn: (value: T) => void): () => void; - } - export type Signalish = T | SignalLike; - export type UnpackSignal = T extends SignalLike ? V : T; + export type Signalish = T | (() => T); export interface SVGAttributes extends HTMLAttributes { accentHeight?: Signalish; accumulate?: Signalish<"none" | "sum" | undefined>; @@ -98,9 +84,7 @@ export declare namespace JSXInternal { "allow-reorder"?: Signalish<"no" | "yes" | undefined>; alphabetic?: Signalish; amplitude?: Signalish; - /** @deprecated See https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/arabic-form */ arabicForm?: Signalish<"initial" | "medial" | "terminal" | "isolated" | undefined>; - /** @deprecated See https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/arabic-form */ "arabic-form"?: Signalish<"initial" | "medial" | "terminal" | "isolated" | undefined>; ascent?: Signalish; attributeName?: Signalish; @@ -658,223 +642,58 @@ export declare namespace JSXInternal { onCommand?: CommandEventHandler; } export interface AriaAttributes { - /** Identifies the currently active element when DOM focus is on a composite widget, textbox, group, or application. */ "aria-activedescendant"?: Signalish; - /** Indicates whether assistive technologies will present all, or only parts of, the changed region based on the change notifications defined by the aria-relevant attribute. */ "aria-atomic"?: Signalish; - /** - * Indicates whether inputting text could trigger display of one or more predictions of the user's intended value for an input and specifies how predictions would be - * presented if they are made. - */ "aria-autocomplete"?: Signalish<"none" | "inline" | "list" | "both" | undefined>; - /** - * Defines a string value that labels the current element, which is intended to be converted into Braille. - * @see aria-label. - */ "aria-braillelabel"?: Signalish; - /** - * Defines a human-readable, author-localized abbreviated description for the role of an element, which is intended to be converted into Braille. - * @see aria-roledescription. - */ "aria-brailleroledescription"?: Signalish; - /** Indicates an element is being modified and that assistive technologies MAY want to wait until the modifications are complete before exposing them to the user. */ "aria-busy"?: Signalish; - /** - * Indicates the current "checked" state of checkboxes, radio buttons, and other widgets. - * @see aria-pressed - * @see aria-selected. - */ "aria-checked"?: Signalish; - /** - * Defines the total number of columns in a table, grid, or treegrid. - * @see aria-colindex. - */ "aria-colcount"?: Signalish; - /** - * Defines an element's column index or position with respect to the total number of columns within a table, grid, or treegrid. - * @see aria-colcount - * @see aria-colspan. - */ "aria-colindex"?: Signalish; - /** - * Defines a human readable text alternative of aria-colindex. - * @see aria-rowindextext. - */ "aria-colindextext"?: Signalish; - /** - * Defines the number of columns spanned by a cell or gridcell within a table, grid, or treegrid. - * @see aria-colindex - * @see aria-rowspan. - */ "aria-colspan"?: Signalish; - /** - * Identifies the element (or elements) whose contents or presence are controlled by the current element. - * @see aria-owns. - */ "aria-controls"?: Signalish; - /** Indicates the element that represents the current item within a container or set of related elements. */ "aria-current"?: Signalish; - /** - * Identifies the element (or elements) that describes the object. - * @see aria-labelledby - */ "aria-describedby"?: Signalish; - /** - * Defines a string value that describes or annotates the current element. - * @see related aria-describedby. - */ "aria-description"?: Signalish; - /** - * Identifies the element that provides a detailed, extended description for the object. - * @see aria-describedby. - */ "aria-details"?: Signalish; - /** - * Indicates that the element is perceivable but disabled, so it is not editable or otherwise operable. - * @see aria-hidden - * @see aria-readonly. - */ "aria-disabled"?: Signalish; - /** - * Indicates what functions can be performed when a dragged object is released on the drop target. - * @deprecated in ARIA 1.1 - */ "aria-dropeffect"?: Signalish<"none" | "copy" | "execute" | "link" | "move" | "popup" | undefined>; - /** - * Identifies the element that provides an error message for the object. - * @see aria-invalid - * @see aria-describedby. - */ "aria-errormessage"?: Signalish; - /** Indicates whether the element, or another grouping element it controls, is currently expanded or collapsed. */ "aria-expanded"?: Signalish; - /** - * Identifies the next element (or elements) in an alternate reading order of content which, at the user's discretion, - * allows assistive technology to override the general default of reading in document source order. - */ "aria-flowto"?: Signalish; - /** - * Indicates an element's "grabbed" state in a drag-and-drop operation. - * @deprecated in ARIA 1.1 - */ "aria-grabbed"?: Signalish; - /** Indicates the availability and type of interactive popup element, such as menu or dialog, that can be triggered by an element. */ "aria-haspopup"?: Signalish; - /** - * Indicates whether the element is exposed to an accessibility API. - * @see aria-disabled. - */ "aria-hidden"?: Signalish; - /** - * Indicates the entered value does not conform to the format expected by the application. - * @see aria-errormessage. - */ "aria-invalid"?: Signalish; - /** Indicates keyboard shortcuts that an author has implemented to activate or give focus to an element. */ "aria-keyshortcuts"?: Signalish; - /** - * Defines a string value that labels the current element. - * @see aria-labelledby. - */ "aria-label"?: Signalish; - /** - * Identifies the element (or elements) that labels the current element. - * @see aria-describedby. - */ "aria-labelledby"?: Signalish; - /** Defines the hierarchical level of an element within a structure. */ "aria-level"?: Signalish; - /** Indicates that an element will be updated, and describes the types of updates the user agents, assistive technologies, and user can expect from the live region. */ "aria-live"?: Signalish<"off" | "assertive" | "polite" | undefined>; - /** Indicates whether an element is modal when displayed. */ "aria-modal"?: Signalish; - /** Indicates whether a text box accepts multiple lines of input or only a single line. */ "aria-multiline"?: Signalish; - /** Indicates that the user may select more than one item from the current selectable descendants. */ "aria-multiselectable"?: Signalish; - /** Indicates whether the element's orientation is horizontal, vertical, or unknown/ambiguous. */ "aria-orientation"?: Signalish<"horizontal" | "vertical" | undefined>; - /** - * Identifies an element (or elements) in order to define a visual, functional, or contextual parent/child relationship - * between DOM elements where the DOM hierarchy cannot be used to represent the relationship. - * @see aria-controls. - */ "aria-owns"?: Signalish; - /** - * Defines a short hint (a word or short phrase) intended to aid the user with data entry when the control has no value. - * A hint could be a sample value or a brief description of the expected format. - */ "aria-placeholder"?: Signalish; - /** - * Defines an element's number or position in the current set of listitems or treeitems. Not required if all elements in the set are present in the DOM. - * @see aria-setsize. - */ "aria-posinset"?: Signalish; - /** - * Indicates the current "pressed" state of toggle buttons. - * @see aria-checked - * @see aria-selected. - */ "aria-pressed"?: Signalish; - /** - * Indicates that the element is not editable, but is otherwise operable. - * @see aria-disabled. - */ "aria-readonly"?: Signalish; - /** - * Indicates what notifications the user agent will trigger when the accessibility tree within a live region is modified. - * @see aria-atomic. - */ "aria-relevant"?: Signalish<"additions" | "additions removals" | "additions text" | "all" | "removals" | "removals additions" | "removals text" | "text" | "text additions" | "text removals" | undefined>; - /** Indicates that user input is required on the element before a form may be submitted. */ "aria-required"?: Signalish; - /** Defines a human-readable, author-localized description for the role of an element. */ "aria-roledescription"?: Signalish; - /** - * Defines the total number of rows in a table, grid, or treegrid. - * @see aria-rowindex. - */ "aria-rowcount"?: Signalish; - /** - * Defines an element's row index or position with respect to the total number of rows within a table, grid, or treegrid. - * @see aria-rowcount - * @see aria-rowspan. - */ "aria-rowindex"?: Signalish; - /** - * Defines a human readable text alternative of aria-rowindex. - * @see aria-colindextext. - */ "aria-rowindextext"?: Signalish; - /** - * Defines the number of rows spanned by a cell or gridcell within a table, grid, or treegrid. - * @see aria-rowindex - * @see aria-colspan. - */ "aria-rowspan"?: Signalish; - /** - * Indicates the current "selected" state of various widgets. - * @see aria-checked - * @see aria-pressed. - */ "aria-selected"?: Signalish; - /** - * Defines the number of items in the current set of listitems or treeitems. Not required if all elements in the set are present in the DOM. - * @see aria-posinset. - */ "aria-setsize"?: Signalish; - /** Indicates if items in a table or grid are sorted in ascending or descending order. */ "aria-sort"?: Signalish<"none" | "ascending" | "descending" | "other" | undefined>; - /** Defines the maximum allowed value for a range widget. */ "aria-valuemax"?: Signalish; - /** Defines the minimum allowed value for a range widget. */ "aria-valuemin"?: Signalish; - /** - * Defines the current value for a range widget. - * @see aria-valuetext. - */ "aria-valuenow"?: Signalish; - /** Defines the human readable text alternative of aria-valuenow for a range widget. */ "aria-valuetext"?: Signalish; } export type WAIAriaRole = "alert" | "alertdialog" | "application" | "article" | "banner" | "blockquote" | "button" | "caption" | "cell" | "checkbox" | "code" | "columnheader" | "combobox" | "command" | "complementary" | "composite" | "contentinfo" | "definition" | "deletion" | "dialog" | "directory" | "document" | "emphasis" | "feed" | "figure" | "form" | "grid" | "gridcell" | "group" | "heading" | "img" | "input" | "insertion" | "landmark" | "link" | "list" | "listbox" | "listitem" | "log" | "main" | "marquee" | "math" | "meter" | "menu" | "menubar" | "menuitem" | "menuitemcheckbox" | "menuitemradio" | "navigation" | "none" | "note" | "option" | "paragraph" | "presentation" | "progressbar" | "radio" | "radiogroup" | "range" | "region" | "roletype" | "row" | "rowgroup" | "rowheader" | "scrollbar" | "search" | "searchbox" | "section" | "sectionhead" | "select" | "separator" | "slider" | "spinbutton" | "status" | "strong" | "structure" | "subscript" | "superscript" | "switch" | "tab" | "table" | "tablist" | "tabpanel" | "term" | "textbox" | "time" | "timer" | "toolbar" | "tooltip" | "tree" | "treegrid" | "treeitem" | "widget" | "window" | "none presentation"; @@ -1066,21 +885,16 @@ export declare namespace JSXInternal { allow?: Signalish; allowFullScreen?: Signalish; allowTransparency?: Signalish; - /** @deprecated */ frameborder?: Signalish; - /** @deprecated */ frameBorder?: Signalish; height?: Signalish; loading?: Signalish<"eager" | "lazy" | undefined>; - /** @deprecated */ marginHeight?: Signalish; - /** @deprecated */ marginWidth?: Signalish; name?: Signalish; referrerpolicy?: Signalish; referrerPolicy?: Signalish; sandbox?: Signalish; - /** @deprecated */ scrolling?: Signalish; seamless?: Signalish; src?: Signalish; @@ -1302,9 +1116,7 @@ export declare namespace JSXInternal { } interface ScriptHTMLAttributes extends HTMLAttributes { async?: Signalish; - /** @deprecated */ charset?: Signalish; - /** @deprecated */ charSet?: Signalish; crossorigin?: Signalish; crossOrigin?: Signalish; @@ -1421,31 +1233,23 @@ export declare namespace JSXInternal { export interface MathMLAttributes extends HTMLAttributes { dir?: Signalish<"ltr" | "rtl" | undefined>; displaystyle?: Signalish; - /** @deprecated This feature is non-standard. See https://developer.mozilla.org/en-US/docs/Web/MathML/Global_attributes/href */ href?: Signalish; - /** @deprecated See https://developer.mozilla.org/en-US/docs/Web/MathML/Global_attributes/mathbackground */ mathbackground?: Signalish; - /** @deprecated See https://developer.mozilla.org/en-US/docs/Web/MathML/Global_attributes/mathcolor */ mathcolor?: Signalish; - /** @deprecated See https://developer.mozilla.org/en-US/docs/Web/MathML/Global_attributes/mathsize */ mathsize?: Signalish; nonce?: Signalish; scriptlevel?: Signalish; } export interface AnnotationMathMLAttributes extends MathMLAttributes { encoding?: Signalish; - /** @deprecated See https://developer.mozilla.org/en-US/docs/Web/MathML/Element/semantics#src */ src?: Signalish; } export interface AnnotationXmlMathMLAttributes extends MathMLAttributes { encoding?: Signalish; - /** @deprecated See https://developer.mozilla.org/en-US/docs/Web/MathML/Element/semantics#src */ src?: Signalish; } export interface MActionMathMLAttributes extends MathMLAttributes { - /** @deprecated See https://developer.mozilla.org/en-US/docs/Web/MathML/Element/maction#actiontype */ actiontype?: Signalish<"statusline" | "toggle" | undefined>; - /** @deprecated See https://developer.mozilla.org/en-US/docs/Web/MathML/Element/maction#selection */ selection?: Signalish; } export interface MathMathMLAttributes extends MathMLAttributes { @@ -1462,27 +1266,20 @@ export declare namespace JSXInternal { separators?: Signalish; } export interface MFracMathMLAttributes extends MathMLAttributes { - /** @deprecated See https://developer.mozilla.org/en-US/docs/Web/MathML/Element/mfrac#denomalign */ denomalign?: Signalish<"center" | "left" | "right" | undefined>; linethickness?: Signalish; - /** @deprecated See https://developer.mozilla.org/en-US/docs/Web/MathML/Element/mfrac#numalign */ numalign?: Signalish<"center" | "left" | "right" | undefined>; } export interface MiMathMLAttributes extends MathMLAttributes { - /** The only value allowed in the current specification is normal (case insensitive) - * See https://developer.mozilla.org/en-US/docs/Web/MathML/Element/mi#mathvariant */ mathvariant?: Signalish<"normal" | "bold" | "italic" | "bold-italic" | "double-struck" | "bold-fraktur" | "script" | "bold-script" | "fraktur" | "sans-serif" | "bold-sans-serif" | "sans-serif-italic" | "sans-serif-bold-italic" | "monospace" | "initial" | "tailed" | "looped" | "stretched" | undefined>; } export interface MmultiScriptsMathMLAttributes extends MathMLAttributes { - /** @deprecated See https://developer.mozilla.org/en-US/docs/Web/MathML/Element/mmultiscripts#subscriptshift */ subscriptshift?: Signalish; - /** @deprecated See https://developer.mozilla.org/en-US/docs/Web/MathML/Element/mmultiscripts#superscriptshift */ superscriptshift?: Signalish; } export interface MNMathMLAttributes extends MathMLAttributes { } export interface MOMathMLAttributes extends MathMLAttributes { - /** Non-standard attribute See https://developer.mozilla.org/en-US/docs/Web/MathML/Element/mo#accent */ accent?: Signalish; fence?: Signalish; largeop?: Signalish; @@ -1514,9 +1311,7 @@ export declare namespace JSXInternal { export interface MRowMathMLAttributes extends MathMLAttributes { } export interface MSMathMLAttributes extends MathMLAttributes { - /** @deprecated See https://developer.mozilla.org/en-US/docs/Web/MathML/Element/ms#browser_compatibility */ lquote?: Signalish; - /** @deprecated See https://developer.mozilla.org/en-US/docs/Web/MathML/Element/ms#browser_compatibility */ rquote?: Signalish; } export interface MSpaceMathMLAttributes extends MathMLAttributes { @@ -1527,71 +1322,46 @@ export declare namespace JSXInternal { export interface MSqrtMathMLAttributes extends MathMLAttributes { } export interface MStyleMathMLAttributes extends MathMLAttributes { - /** @deprecated See https://developer.mozilla.org/en-US/docs/Web/MathML/Element/mstyle#background */ background?: Signalish; - /** @deprecated See https://developer.mozilla.org/en-US/docs/Web/MathML/Element/mstyle#color */ color?: Signalish; - /** @deprecated See https://developer.mozilla.org/en-US/docs/Web/MathML/Element/mstyle#fontsize */ fontsize?: Signalish; - /** @deprecated See https://developer.mozilla.org/en-US/docs/Web/MathML/Element/mstyle#fontstyle */ fontstyle?: Signalish; - /** @deprecated See https://developer.mozilla.org/en-US/docs/Web/MathML/Element/mstyle#fontweight */ fontweight?: Signalish; - /** @deprecated See https://developer.mozilla.org/en-US/docs/Web/MathML/Element/mstyle#scriptminsize */ scriptminsize?: Signalish; - /** @deprecated See https://developer.mozilla.org/en-US/docs/Web/MathML/Element/mstyle#scriptsizemultiplier */ scriptsizemultiplier?: Signalish; } export interface MSubMathMLAttributes extends MathMLAttributes { - /** @deprecated See https://developer.mozilla.org/en-US/docs/Web/MathML/Element/msub#subscriptshift */ subscriptshift?: Signalish; } export interface MSubsupMathMLAttributes extends MathMLAttributes { - /** @deprecated See https://developer.mozilla.org/en-US/docs/Web/MathML/Element/msubsup#subscriptshift */ subscriptshift?: Signalish; - /** @deprecated See https://developer.mozilla.org/en-US/docs/Web/MathML/Element/msubsup#superscriptshift */ superscriptshift?: Signalish; } export interface MSupMathMLAttributes extends MathMLAttributes { - /** @deprecated See https://developer.mozilla.org/en-US/docs/Web/MathML/Element/msup#superscriptshift */ superscriptshift?: Signalish; } export interface MTableMathMLAttributes extends MathMLAttributes { - /** Non-standard attribute See https://developer.mozilla.org/en-US/docs/Web/MathML/Element/mtable#align */ align?: Signalish<"axis" | "baseline" | "bottom" | "center" | "top" | undefined>; - /** Non-standard attribute See https://developer.mozilla.org/en-US/docs/Web/MathML/Element/mtable#columnalign */ columnalign?: Signalish<"center" | "left" | "right" | undefined>; - /** Non-standard attribute See https://developer.mozilla.org/en-US/docs/Web/MathML/Element/mtable#columnlines */ columnlines?: Signalish<"dashed" | "none" | "solid" | undefined>; - /** Non-standard attribute See https://developer.mozilla.org/en-US/docs/Web/MathML/Element/mtable#columnspacing */ columnspacing?: Signalish; - /** Non-standard attribute See https://developer.mozilla.org/en-US/docs/Web/MathML/Element/mtable#frame */ frame?: Signalish<"dashed" | "none" | "solid" | undefined>; - /** Non-standard attribute See https://developer.mozilla.org/en-US/docs/Web/MathML/Element/mtable#framespacing */ framespacing?: Signalish; - /** Non-standard attribute See https://developer.mozilla.org/en-US/docs/Web/MathML/Element/mtable#rowalign */ rowalign?: Signalish<"axis" | "baseline" | "bottom" | "center" | "top" | undefined>; - /** Non-standard attribute See https://developer.mozilla.org/en-US/docs/Web/MathML/Element/mtable#rowlines */ rowlines?: Signalish<"dashed" | "none" | "solid" | undefined>; - /** Non-standard attribute See https://developer.mozilla.org/en-US/docs/Web/MathML/Element/mtable#rowspacing */ rowspacing?: Signalish; - /** Non-standard attribute See https://developer.mozilla.org/en-US/docs/Web/MathML/Element/mtable#width */ width?: Signalish; } export interface MTdMathMLAttributes extends MathMLAttributes { columnspan?: Signalish; rowspan?: Signalish; - /** Non-standard attribute See https://developer.mozilla.org/en-US/docs/Web/MathML/Element/mtd#columnalign */ columnalign?: Signalish<"center" | "left" | "right" | undefined>; - /** Non-standard attribute See https://developer.mozilla.org/en-US/docs/Web/MathML/Element/mtd#rowalign */ rowalign?: Signalish<"axis" | "baseline" | "bottom" | "center" | "top" | undefined>; } export interface MTextMathMLAttributes extends MathMLAttributes { } export interface MTrMathMLAttributes extends MathMLAttributes { - /** Non-standard attribute See https://developer.mozilla.org/en-US/docs/Web/MathML/Element/mtr#columnalign */ columnalign?: Signalish<"center" | "left" | "right" | undefined>; - /** Non-standard attribute See https://developer.mozilla.org/en-US/docs/Web/MathML/Element/mtr#rowalign */ rowalign?: Signalish<"axis" | "baseline" | "bottom" | "center" | "top" | undefined>; } export interface MUnderMathMLAttributes extends MathMLAttributes { @@ -1667,13 +1437,10 @@ export declare namespace JSXInternal { export interface IntrinsicMathMLElements { annotation: AnnotationMathMLAttributes; "annotation-xml": AnnotationXmlMathMLAttributes; - /** @deprecated See https://developer.mozilla.org/en-US/docs/Web/MathML/Element/maction */ maction: MActionMathMLAttributes; math: MathMathMLAttributes; - /** This feature is non-standard. See https://developer.mozilla.org/en-US/docs/Web/MathML/Element/menclose */ menclose: MEncloseMathMLAttributes; merror: MErrorMathMLAttributes; - /** @deprecated See https://developer.mozilla.org/en-US/docs/Web/MathML/Element/mfenced */ mfenced: MFencedMathMLAttributes; mfrac: MFracMathMLAttributes; mi: MiMathMLAttributes; diff --git a/build/lazy/Lazyloading.d.ts b/build/lazy/Lazyloading.d.ts index 0179d6b..5211f9e 100644 --- a/build/lazy/Lazyloading.d.ts +++ b/build/lazy/Lazyloading.d.ts @@ -1,8 +1,9 @@ +import { ComponentChild } from '../index'; type PropsOf any> = Parameters extends [] ? {} : Parameters[0]; export declare function lazy any>(importFn: () => Promise<{ default: T; }>): (props: PropsOf & { - fallback?: string | Node; - errorFallback?: string | Node | ((error: Error) => Node); + fallback?: ComponentChild; + errorFallback?: ComponentChild | ((error: Error) => ComponentChild); }) => ReturnType; export {}; diff --git a/build/lib.d.ts b/build/lib.d.ts index 34ec79d..fd7737f 100644 --- a/build/lib.d.ts +++ b/build/lib.d.ts @@ -6,11 +6,4 @@ export declare function applyMoves(arr: T[], moves: Record): T[]; -/** - * Computes the indices of the longest increasing subsequence in the given array. - * @param arr - An array of numbers. - * @returns An array of indices representing the longest increasing subsequence. - * - * Time Complexity: O(n log n) - */ export declare function longestIncreasingSubsequenceIndices(arr: number[]): number[]; diff --git a/build/refract.cjs.js b/build/refract.cjs.js index 3e5cdc3..9c12cfb 100644 --- a/build/refract.cjs.js +++ b/build/refract.cjs.js @@ -1 +1 @@ -"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});function T(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)&&Object.prototype.toString.call(e)==="[object Object]"}function _(e){return["boolean","string","number","undefined"].includes(typeof e)||e===null||e instanceof Error}const ce="http://www.w3.org/2000/svg",Fe=new Set(["svg","a","circle","clipPath","defs","desc","ellipse","feBlend","feColorMatrix","feComponentTransfer","feComposite","feConvolveMatrix","feDiffuseLighting","feDisplacementMap","feDistantLight","feDropShadow","feFlood","feFuncA","feFuncB","feFuncG","feFuncR","feGaussianBlur","feImage","feMerge","feMergeNode","feMorphology","feOffset","fePointLight","feSpecularLighting","feSpotLight","feTile","feTurbulence","filter","foreignObject","g","image","line","linearGradient","marker","mask","metadata","path","pattern","polygon","polyline","radialGradient","rect","script","set","stop","style","switch","symbol","text","textPath","title","tspan","use","view"]),Ce=new Set(["math","maction","maligngroup","malignmark","menclose","merror","mfenced","mfrac","mglyph","mi","mlabeledtr","mlongdiv","mmultiscripts","mn","mo","mover","mpadded","mphantom","mroot","mrow","ms","mscarries","mscarry","msgroup","msline","mspace","msqrt","msrow","mstack","mstyle","msub","msup","msubsup","mtable","mtd","mtext","mtr","munder","munderover"]),ke="http://www.w3.org/1998/Math/MathML",Z=/(PointerCapture)$|Capture$/i,Ae=/acit|ex(?:s|g|n|p|$)|rph|grid|ows|mnc|ntw|ine[ch]|zoo|^ord|itera/i;function Me(e){const t=[];for(const n in e){const r=e[n],o=n.replace(/([A-Z])/g,"-$1").toLowerCase();typeof r!="number"||Ae.test(o)?t.push(`${o}: ${r};`):t.push(`${o}: ${r}px;`)}return t.join(" ")}function Pe(e){const t={};for(const n in e){const r=e[n];if(typeof r=="object"&&r!==null){console.warn(`Nested styles not allowed for ${n}`);continue}r==null||r===!1||r===""||(t[n]=r)}return t}function Te(e){return T(e)||typeof e=="string"}function Le(e,t){if(!Te(e))throw new Error("Style attribute must be a plain object or a string");if(typeof e=="string")t.setAttribute("style",e);else{const n=Pe(e);t.setAttribute("style",Me(n))}}function Ne(e,t,n,r){e.__propName=t;const o=Ve(e);o==null||o===!1||(ee(t,o,n,r),e.__signals&&Ke(e,n))}const Re=/(PointerCapture)$|Capture$/i;function ee(e,t,n,r){if(e=="style"){Le(t,n);return}if(e[0]==="o"&&e[1]==="n"&&typeof t=="function"){const o=e!=(e=e.replace(Re,"$1"));e.toLowerCase()in n||e=="onFocusOut"||e=="onFocusIn"||e==="onGotPointerCapture"||e==="onLostPointerCapture"?e=e.toLowerCase().slice(2):e=e.slice(2),n.addEventListener(e,t,o);return}if(r===ce)e=e.replace(/xlink(H|:h)/,"h").replace(/sName$/,"s");else if(e!=="width"&&e!=="height"&&e!=="href"&&e!=="list"&&e!=="form"&&e!=="tabIndex"&&e!=="download"&&e!=="rowSpan"&&e!=="colSpan"&&e!=="role"&&e!=="popover"&&e in n)try{e==="value"&&n.tagName==="SELECT"?setTimeout(()=>{n[e]=t??""}):n[e]=t??"";return}catch{}t!=null&&(t!==!1||e[4]==="-")&&n.setAttribute(e,e==="popover"&&t===!0?"":t)}const w=Symbol("FRAGMENT");function B(e,t,...n){if(e==="FRAGMENT"){const r=L(n);return r[w]=!0,r}return{type:e,props:{...t,children:L(n)}}}function L(e){return e.map(t=>{if(typeof t=="object"){if(Array.isArray(t))return L(t);if(t===null)return v("");if(!t.type||!t.props)throw new Error("Invalid type for a dom node, found "+t);return t}else if(typeof t=="function"){const n=Ye(t);if(_(n))return j("TEXT_CHILD",{nodeValue:n!=null&&n!==!1?String(n):"",children:[]},t);if(Array.isArray(n)){const r=n[w];return j("FRAGMENT",{children:r?n:L(n)},t)}else if(!n.type||!n.props)throw new Error("Invalid type for a dom node, found "+n);return j(n.type,n.props,t)}else return v(t)}).flat()}function v(e){return{type:"TEXT_CHILD",props:{nodeValue:e!=null&&e!==!1?String(e):"",children:[]}}}function j(e,t,n){return{type:e,renderFunction:n,props:t}}function De(e){return e!=="children"&&e!=="key"&&e!=="ref"}function ue(e){let t=null;Fe.has(e.type)?t=ce:Ce.has(e.type)&&(t=ke);const n=e.type==="TEXT_CHILD"?document.createTextNode(""):t?document.createElementNS(t,e.type,e.props.is&&e.props):document.createElement(e.type);if(!e.props)return n;e.props.ref&&e.props.ref instanceof oe&&n instanceof HTMLElement&&(e.props.ref.current=n);for(const r in e.props){if(!De(r))continue;const o=e.props[r];typeof o=="function"&&r[0]!=="o"&&r[1]!=="n"?Ne(o,r,n,t):ee(r,o,n,t)}return n}function Ie(e,t,n){n==null||e==="key"||ee(e,n,t)}function Ge(e,t){x=t;const n=document.createDocumentFragment();b=n;const r={type:"div",props:{children:[e]},dom:n};e.parent=r,F.push(e),requestIdleCallback(fe)}function Oe(){b&&x&&x.appendChild(b)}let F=[],x=null,b=null,O=[];function ie(){for(let e=0;e0&&!t;){const n=F.pop();$e(n),t=e.timeRemaining()<1}if(F.length==0){Oe(),ie();return}requestIdleCallback(fe)}function $e(e){var t;if(e.type==="FRAGMENT"){const n=!e.props.children[w];let r=!1;for(let o=e.props.children.length-1;o>=0;o--)e.props.children[o].parent=e,n&&e.props.children[o].props.key===void 0&&e.renderFunction&&(r=!0),F.push(e.props.children[o]);r&&console.error("Array children must have a key attribute")}else if(typeof e.type=="function"){ge(e);const n=e.type(e.props);if(me(),Array.isArray(n)){for(let r=n.length-1;r>=0;r--)n[r].parent=e,F.push(n[r]);e.props.children=n}else n.parent=e,e.props.children.push(n),F.push(n);O.push(e)}else{e.dom||(e.dom=ue(e));let n=e.parent;for(;n&&!n.dom;)n=n.parent;n&&((t=n.dom)==null||t.appendChild(e.dom));for(let r=e.props.children.length-1;r>=0;r--)e.props.children[r].parent=e,F.push(e.props.children[r])}z(e)}function C(e){if(e.type==="FRAGMENT")if(e.props.children[w])for(const n of e.props.children)n.parent=e,C(n);else{let n=!1;for(const r of e.props.children)r.parent=e,r.props.key===void 0&&(n=!0),C(r);n&&console.error("Array children must have a key attribute")}else if(typeof e.type!="function")for(const t of e.props.children)t.parent=e,C(t);z(e)}function h(e,t,n,r,o){var l,i;if(e.type==="FRAGMENT")for(const s of e.props.children)r&&(s.parent=e),h(s,t,n,r,o);else if(typeof e.type=="function"){ge(e);const s=e.type(e.props);if(me(),Array.isArray(s)){for(const a of s)a.parent=e,h(a,t,n,!0,o);e.props.children=s}else s.parent=e,e.props.children.push(s),h(s,t,n,!0,o);queueMicrotask(()=>{Ee(e)})}else{if(e.dom||(e.dom=ue(e)),t)n?(l=t.parentElement)==null||l.replaceChild(e.dom,t):(i=t.parentElement)==null||i.insertBefore(e.dom,t);else{let s;if(o)s=o;else{let a=e.parent;for(;a&&!a.dom;)a=a.parent;s=a==null?void 0:a.dom}s==null||s.appendChild(e.dom)}for(const s of e.props.children)r&&(s.parent=e),h(s,void 0,void 0,r,e.dom)}r&&z(e)}let $=!0;function g(e,t){if(!(!e||!$)){if(e.renderFunction&&(t&&Qe(e.renderFunction),delete e.renderFunction),e.dom){for(const n in e.props)if(H(n)){let r=n.toLowerCase().substring(2);const o=r!=(r=r.replace(Z,"$1"));e.dom.removeEventListener(r,e.props[n],o),delete e.props[n]}else typeof e.props[n]=="function"?Je(e.props[n]):n==="ref"&&e.props[n]instanceof oe&&(e.props[n].current=null);e.dom.remove()}typeof e.type=="function"&&(rt(e,e.props),delete e.type),e.props.children.forEach(n=>g(n,!0))}}function z(e){e.renderFunction&&qe(e.renderFunction,e)}function pe(e,t){if(_(t)){const n={...v(t),parent:e.parent};C(n),E(e,n)}else if(Array.isArray(t)){const r={type:"FRAGMENT",props:{children:t[w]?t:L(t)},parent:e.parent};C(r),E(e,r)}else{const n={...t,parent:e.parent};C(n),E(e,n)}}function I(e,t){e.renderFunction&&(t.renderFunction=e.renderFunction,z(t))}function G(e,t,n){var r;if(n!==void 0){e.parent.props.children[n]=t;return}(r=e.parent)==null||r.props.children.forEach((o,l)=>{o===e&&(e.parent.props.children[l]=t)})}const H=e=>e.startsWith("on")||e=="onFocusOut"||e=="onFocusIn",se=e=>e!=="children"&&!H(e)&&e!=="key"&&e!=="ref",q=(e,t,n)=>e[n]!==t[n],He=(e,t,n)=>!(n in t);function de(e,t){var n,r;return e===t?!0:e.type!==t.type||((n=e.props)==null?void 0:n.key)!==((r=t.props)==null?void 0:r.key)?!1:P(e.props,t.props)}function P(e,t){if(e===t){if(e instanceof N&&t instanceof N)return P(e.value,t.value);if(Array.isArray(e)&&Array.isArray(t)){if(e.length!==t.length)return!1;for(let o=0;o=0;t--){const n=e.props.children[t],r=te(n);if(r)return r}}}function We(e){if(e)for(let t=e.props.children.length-1;t>=0;t--){const n=e.props.children[t],r=te(n);if(r)return r}}function Ue(e){if(!e)return;let t=e.parent;for(;t&&!t.dom;)t=t.parent;return t}function Xe(e){if(!e)return;if(e.dom)return e;let t=e.parent;for(;t&&!t.dom;)t=t.parent;return t}function E(e,t,n){if(!(!e&&!t)){if(e&&!t)g(e,!0),e.parent.props.children=e.parent.props.children.filter(r=>r!==e);else if(e&&t){const r=e.props,o=t.props;if(e.type==="FRAGMENT"||typeof e.type=="function")if(t.type==="FRAGMENT"||typeof t.type=="function")typeof e.type==typeof t.type&&typeof e.type=="function"?de(e,t)||(h(t,he(e),void 0,!0),I(e,t),g(e),G(e,t,n)):le(e,t);else{t.parent=e.parent;let l=e.props.children[0];for(;l&&!l.dom;)l=l.props.children[0];h(t,l==null?void 0:l.dom),I(e,t),g(e),G(e,t,n)}else{const l=e.dom;if(e.type==="TEXT_CHILD"&&t.type==="TEXT_CHILD"&&!t.dom&&(t.dom=e.dom),l===void 0)return;if(t.type==="FRAGMENT"||typeof t.type=="function")t.parent=e.parent,I(e,t),h(t,l),g(e),G(e,t,n);else{for(const i in r)if(se(i)&&He(r,o,i))l[i]="";else if(H(i)&&(!(i in o)||q(r,o,i))){let s=i.toLowerCase().substring(2);const a=s!=(s=s.replace(Z,"$1"));l.removeEventListener(s,r[i],a)}if(e.type!==t.type)t.parent=e.parent,I(e,t),h(t,l,!0),g(e),G(e,t,n);else{for(const i in o)if(se(i)&&q(r,o,i))l[i]=o[i],r[i]=o[i];else if(H(i)&&q(r,o,i)){let s=i.toLowerCase().substring(2);const a=s!=(s=s.replace(Z,"$1"));l.addEventListener(s,o[i],a),r[i]=o[i]}le(e,t)}}}}}}function ze(e,t){var a;const n=e.props.children,r=t.props.children,o={};for(let c=0;cc?e.props.children[c]=k:e.props.children.push(k),delete o[m];const A=t.props.children[c];A&&(A.parent=e),E(k,A,c),M(e.props.children[c],i==null?void 0:i.dom,l)}else s>c?e.props.children[c]=u:e.props.children.push(u),u.parent=e,h(u,l,!1,!1,i==null?void 0:i.dom)}for(const c in o)if(o.hasOwnProperty(c)){const u=o[c];g(u,!0)}for(;e.props.children.length>t.props.children.length;)e.props.children.pop()}function M(e,t,n){if(e.dom){if(e.dom===t||e.dom===n)return;n?t.insertBefore(e.dom,n):t.appendChild(e.dom)}else for(const r of e.props.children)M(r,t,n)}function le(e,t){const n=t.type==="FRAGMENT"&&!t.props.children[w],r=e.type==="FRAGMENT"&&!e.props.children[w];n&&r?ze(e,t)===!1&&ae(e,t):ae(e,t),t.type==="FRAGMENT"&&t.props.children[w]?e.props.children[w]=!0:e.props.children[w]=!1,e.type=t.type}function K(e,t){var r;let n=Math.max(e.props.children.length,t.props.children.length);for(let o=0;os,A=l.hasOwnProperty(m)&&l[m].newIndex{Q.forEach(t=>{const n=t();if(Y.has(n))return;Y.add(n),n.__cleanup&&typeof n.__cleanup=="function"&&(n.__cleanup(),n.__cleanup=null);const r=n();if(typeof r=="function"&&(n.__cleanup=r),W.has(n)){const o=W.get(n);o&&pe(o,r)}if(U.has(n)){const o=U.get(n);o&&n.__propName&&Ie(n.__propName,o,r)}}),Y.clear(),Q.clear(),J=!1}))}function qe(e,t){W.set(e,t)}function Ke(e,t){U.set(e,t)}function Je(e){U.delete(e);const t=e.__signals;if(t){for(const n of t)n.removeDep(e);e.__signals=null}}function Qe(e){W.delete(e);const t=e.__signals;if(t){for(const n of t)n.removeDep(e);e.__signals=null}}let y=null,f=null;function ne(e){y.__signals||(y.__signals=new Set),y.__signals.add(e)}function re(e){f.__signals||(f.__signals=new Set),f.__signals.add(e)}function Ye(e){var n;if(typeof e!="function")throw new Error("reactive takes a render function as the argument");y=e;const t=e();if(y=null,!_(t)&&T(t)&&!t.type&&!t.props&&!((n=t.props)!=null&&n.children))throw new Error("Reactive value must be primitive or functional component, got: "+typeof t);return t}function Ve(e){if(typeof e!="function")throw new Error("reactive takes a render function as the argument");y=e;const t=e();return y=null,t}function Ze(e){if(typeof e!="function")throw new Error("createEffect takes a effect function as the argument");Se(e),we()||ye(e)}function ye(e,t){if(typeof e!="function")return;f=e;const n=e();f.__signals&&typeof n=="function"&&(f.__cleanup=n),!f.__signals&&n&&typeof n=="function"&&(t?nt(n,t):_e(n)),f=null}function Be(e){if(typeof e!="function")throw new Error("computed takes a function as the argument");let t=we()!==null;f=()=>{if(t){t=!1;return}r.update(e())},Se(f);const n=e(),r=R(n);return f=null,{get value(){return r.value}}}function ve(e){if(typeof e!="function")throw new Error("createPromise takes a function as the argument");const t=e();if(!(t instanceof Promise))throw new Error("createPromise takes a function that returns a promise");const n=R({status:"pending",data:null,error:null});return t.then(r=>{n.update(o=>{o.data=r,o.status="resolved"})}).catch(r=>{n.update(o=>{o.error=r,o.status="rejected"})}),{get value(){return n.value}}}class oe{constructor(t){this.current=t}}function xe(){return new oe(null)}const X=["push","pop","unshift","shift","splice","fill","copyWithin","sort","reverse"];class N{constructor(t){this.isNotified=!1,this._val=t,this.deps=new Set}notify(){this.isNotified||(this.deps.size!==0&&(this.isNotified=!0),this.deps.forEach(t=>{je(()=>(this.isNotified=!1,t))}))}removeDep(t){this.deps.delete(t)}clearDeps(){this.deps.clear()}}class be extends N{constructor(t){if(!_(t))throw new Error("Invalid type for PrimitiveSignal. Valid types: [boolean, string, number, undefined, null]");super(t)}get value(){return f&&(this.deps.add(f),re(this)),y&&(this.deps.add(y),ne(this)),this._val}update(t){if(typeof t=="function"){const n=t(this._val);if(!_(n))throw new Error("Invalid type for PrimitiveSignal. Valid types: [boolean, string, number, undefined, null]");if(n===this._val)return;this._val=n,this.notify()}else{if(!_(t))throw new Error("Invalid type for PrimitiveSignal. Valid types: [boolean, string, number, undefined, null]");if(t===this._val)return;this._val=t,this.notify()}}}class et extends N{constructor(t){if(!Array.isArray(t))throw new Error("Invalid type for ArraySignal; value must be an array");super(t),this.updateCalled=!1,this._val=this.createProxy(t)}createProxy(t){return new Proxy(t,{get:(n,r)=>{const o=n[r];if(typeof o=="function"){if(X.includes(String(r))&&!this.updateCalled)throw new Error("Cannot set a value on an array signal, use the update method for updating the array.");return(...l)=>{const i=o.apply(n,l);return X.includes(String(r))&&this.notify(),i}}return o},set:(n,r,o)=>{if(!this.updateCalled)throw new Error("Cannot set a value on an array signal, use the update method for updating the array.");return n[r]=o,this.notify(),!0}})}get value(){return f&&(this.deps.add(f),re(this)),y&&(this.deps.add(y),ne(this)),this._val}update(t){if(this.updateCalled=!0,typeof t=="function")t(this._val);else{if(!Array.isArray(t))throw new Error("Invalid type for ArraySignal; value must be an array");if(t===this._val)return;this._val=this.createProxy(t),this.notify()}this.updateCalled=!1}}class tt extends N{constructor(t){if(!T(t))throw new Error("Invalid type for ObjectSignal; value must be a plain object");super(t),this.updateCalled=!1,this._val=this.createProxy(t)}createInternalArrayProxy(t){return new Proxy(t,{get:(n,r)=>{const o=n[r];if(typeof o=="function"){if(!this.updateCalled&&X.includes(String(r)))throw new Error("Cannot set a value on an object signal, use the update method for updating the object.");return(...l)=>{const i=o.apply(n,l);return X.includes(String(r))&&this.notify(),i}}return o},set:(n,r,o)=>{if(!this.updateCalled)throw new Error("Cannot set a value on an object signal, use the update method for updating the object.");return n[r]=o,this.notify(),!0}})}createProxy(t){return new Proxy(t,{get:(n,r)=>{const o=n[r];return Array.isArray(o)?(n[r]=this.createInternalArrayProxy(o),n[r]):o},set:(n,r,o)=>{if(!this.updateCalled)throw new Error("Cannot set a value on an object signal, use the update method for updating the object.");return typeof o=="function"?!1:(typeof o=="object"&&o!==null&&(o=this.createProxy(o)),o===n[r]||(n[r]=o,this.notify()),!0)},deleteProperty:(n,r)=>{const o=delete n[r];return this.notify(),o}})}get value(){return f&&(this.deps.add(f),re(this)),y&&(this.deps.add(y),ne(this)),this._val}update(t){if(this.updateCalled=!0,typeof t=="function")t(this._val);else{if(!T(t))throw new Error("Invalid type for ObjectSignal; value must be a plain object");if(t===this._val)return;this._val=this.createProxy(t),this.notify()}this.updateCalled=!1}}function R(e){if(typeof e=="function")throw new Error("Functions cannot be used as signal value");if(typeof e=="object"&&e!==null)if(Array.isArray(e)){const t=new et(e);return V(t),{get value(){return t.value},update:t.update.bind(t)}}else if(T(e)){const t=new tt(e);return V(t),{get value(){return t.value},update:t.update.bind(t)}}else throw new Error("Invalid type for signal initialization: "+typeof e);else if(_(e)){const t=new be(e);return V(t),{get value(){return t.value},update:t.update.bind(t)}}else throw new Error("Invalid type for signal initialization: "+typeof e)}let d=null,p=new WeakMap;function ge(e){d=e}function me(){d=null}function we(){return d}function Ee(e){if(p.has(e)){const t=p.get(e);for(const n of t.effects)ye(n,e)}}function _e(e){d&&(p.has(d)?p.get(d).cleanup.push(e):p.set(d,{signals:new Set,cleanup:[e],effects:new Set}))}function nt(e,t){t&&(p.has(t)?p.get(t).cleanup.push(e):p.set(t,{signals:new Set,cleanup:[e],effects:new Set}))}function Se(e){if(d)if(p.has(d))p.get(d).effects.add(e);else{const t=new Set;t.add(e),p.set(d,{signals:new Set,cleanup:[],effects:t})}}function V(e){if(d)if(p.has(d))p.get(d).signals.add(e);else{const t=new Set;t.add(e),p.set(d,{signals:t,cleanup:[],effects:new Set})}}function rt(e,t){const n=p.get(e);if(n){if(n.cleanup)for(const r of n.cleanup)r();n.cleanup=[];for(const r of n.effects){if(r.__cleanup&&typeof r.__cleanup=="function"&&r.__cleanup(),r.__signals)for(const o of r.__signals)o.removeDep(r);delete r.__signals,delete r.__cleanup}n.signals.forEach(r=>r.clearDeps()),n.signals.clear()}p.delete(e)}function ot(e){let t=null;const n=(r,o)=>{t?(r.update(!1),o.update(null)):e().then(l=>{if(l.default){if(typeof l.default!="function")throw new Error("Lazy-loaded component must be a functional component");t=l.default,r.update(!1),o.update(null)}else o.update(new Error("No default export found from lazy-loaded module"))}).catch(l=>{o.update(l),r.update(!1)})};return r=>{const o=R(!0),l=R(null);n(o,l);const i=s=>typeof s=="string"||s&&typeof s=="object"&&"props"in s&&"type"in s;if(r.fallback!==void 0&&!i(r.fallback))throw new Error("Invalid fallback: Expected a string or a valid JSX node.");if(r.errorFallback!==void 0&&!(typeof r.errorFallback=="function"||i(r.errorFallback)))throw new Error("Invalid errorFallback: Expected a string, a valid JSX node, or a function returning a JSX node.");return B("FRAGMENT",null,()=>o.value?r.fallback:l.value!==null?r.errorFallback?typeof r.errorFallback=="function"?r.errorFallback(l.value):r.errorFallback:"Unknown error occurred while lazy loading component, use errorFallback prop to override":t&&B(t,{...r}))}}exports.cleanUp=_e;exports.computed=Be;exports.createEffect=Ze;exports.createElement=B;exports.createPromise=ve;exports.createRef=xe;exports.createSignal=R;exports.lazy=ot;exports.render=Ge; +"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});function N(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)&&Object.prototype.toString.call(e)==="[object Object]"}function A(e){return["boolean","string","number","undefined"].includes(typeof e)||e===null||e instanceof Error}const ce="http://www.w3.org/2000/svg",ke=new Set(["svg","a","circle","clipPath","defs","desc","ellipse","feBlend","feColorMatrix","feComponentTransfer","feComposite","feConvolveMatrix","feDiffuseLighting","feDisplacementMap","feDistantLight","feDropShadow","feFlood","feFuncA","feFuncB","feFuncG","feFuncR","feGaussianBlur","feImage","feMerge","feMergeNode","feMorphology","feOffset","fePointLight","feSpecularLighting","feSpotLight","feTile","feTurbulence","filter","foreignObject","g","image","line","linearGradient","marker","mask","metadata","path","pattern","polygon","polyline","radialGradient","rect","script","set","stop","style","switch","symbol","text","textPath","title","tspan","use","view"]),Ae=new Set(["math","maction","maligngroup","malignmark","menclose","merror","mfenced","mfrac","mglyph","mi","mlabeledtr","mlongdiv","mmultiscripts","mn","mo","mover","mpadded","mphantom","mroot","mrow","ms","mscarries","mscarry","msgroup","msline","mspace","msqrt","msrow","mstack","mstyle","msub","msup","msubsup","mtable","mtd","mtext","mtr","munder","munderover"]),Te="http://www.w3.org/1998/Math/MathML",j=/(PointerCapture)$|Capture$/i,Ne=/acit|ex(?:s|g|n|p|$)|rph|grid|ows|mnc|ntw|ine[ch]|zoo|^ord|itera/i;function Pe(e){const t=[];for(const n in e){const r=e[n],o=n.replace(/([A-Z])/g,"-$1").toLowerCase();typeof r!="number"||Ne.test(o)?t.push(`${o}: ${r};`):t.push(`${o}: ${r}px;`)}return t.join(" ")}function Re(e){const t={};for(const n in e){const r=e[n];if(typeof r=="object"&&r!==null){console.warn(`Nested styles not allowed for ${n}`);continue}r==null||r===!1||r===""||(t[n]=r)}return t}function Le(e){return N(e)||typeof e=="string"}function De(e,t){if(!Le(e))throw new Error("Style attribute must be a plain object or a string");if(typeof e=="string")t.setAttribute("style",e);else{const n=Re(e);t.setAttribute("style",Pe(n))}}function Ge(e,t,n,r){e.__propName=t;const o=et(e);o==null||o===!1||(te(t,o,n,r),e.__signals&&Je(e,n))}const Ie=/(PointerCapture)$|Capture$/i;function te(e,t,n,r){if(e=="style"){De(t,n);return}if(e[0]==="o"&&e[1]==="n"&&typeof t=="function"){const o=e!=(e=e.replace(Ie,"$1"));e.toLowerCase()in n||e=="onFocusOut"||e=="onFocusIn"||e==="onGotPointerCapture"||e==="onLostPointerCapture"?e=e.toLowerCase().slice(2):e=e.slice(2),n.addEventListener(e,t,o);return}if(r===ce)e=e.replace(/xlink(H|:h)/,"h").replace(/sName$/,"s");else if(e!=="width"&&e!=="height"&&e!=="href"&&e!=="list"&&e!=="form"&&e!=="tabIndex"&&e!=="download"&&e!=="rowSpan"&&e!=="colSpan"&&e!=="role"&&e!=="popover"&&e in n)try{e==="value"&&n.tagName==="SELECT"?setTimeout(()=>{n[e]=t??""}):n[e]=t??"";return}catch{}t!=null&&(t!==!1||e[4]==="-")&&n.setAttribute(e,e==="popover"&&t===!0?"":t)}const h=Symbol("FRAGMENT");function B(e,t,...n){if(e==="FRAGMENT"){const r=P(n);return r[h]=!0,r}return{type:e,props:{...t,children:P(n)}}}function P(e){return e.map(t=>{if(typeof t=="object"){if(Array.isArray(t))return P(t);if(t===null)return x("");if(!t.type||!t.props)throw new Error("Invalid type for a dom node, found "+t);return t}else if(typeof t=="function"){const n=be(t);if(A(n))return X("TEXT_CHILD",{nodeValue:n!=null&&n!==!1?String(n):"",children:[]},t);if(Array.isArray(n)){const r=n[h];return X("FRAGMENT",{children:r?n:P(n)},t)}else if(!n.type||!n.props)throw new Error("Invalid type for a dom node, found "+n);return X(n.type,n.props,t)}else return x(t)}).flat()}function x(e){return{type:"TEXT_CHILD",props:{nodeValue:e!=null&&e!==!1?String(e):"",children:[]}}}function X(e,t,n){return{type:e,renderFunction:n,props:t}}function $e(e){return e!=="children"&&e!=="key"&&e!=="ref"}function ae(e){let t=null;ke.has(e.type)?t=ce:Ae.has(e.type)&&(t=Te);const n=e.type==="TEXT_CHILD"?document.createTextNode(""):t?document.createElementNS(t,e.type,e.props.is&&e.props):document.createElement(e.type);if(!e.props)return n;e.props.ref&&e.props.ref instanceof ne&&n instanceof HTMLElement&&(e.props.ref.current=n);for(const r in e.props){if(!$e(r))continue;const o=e.props[r];typeof o=="function"&&r[0]!=="o"&&r[1]!=="n"?Ge(o,r,n,t):te(r,o,n,t)}return n}function Oe(e,t,n){n==null||e==="key"||te(e,n,t)}function ue(e,t){return e===t?!0:e.type!==t.type||e.props?.key!==t.props?.key?!1:T(e.props,t.props)}function T(e,t){if(e===t){if(e instanceof R&&t instanceof R)return T(e.value,t.value);if(Array.isArray(e)&&Array.isArray(t)){if(e.length!==t.length)return!1;for(let n=0;n0&&!t;){const n=w.pop();ze(n),t=e.timeRemaining()<1}if(w.length==0){Ue(),re();return}requestIdleCallback(fe)}function ze(e){if(e.type==="FRAGMENT"){const t=!e.props.children[h];let n=!1;for(let r=e.props.children.length-1;r>=0;r--)e.props.children[r].parent=e,t&&e.props.children[r].props.key===void 0&&e.renderFunction&&(n=!0),w.push(e.props.children[r]);n&&console.error("Array children must have a key attribute")}else if(typeof e.type=="function"){_e(e);const t=e.type(e.props);if(Ee(),Array.isArray(t)){for(let n=t.length-1;n>=0;n--)t[n].parent=e,w.push(t[n]);e.props.children=t}else t.parent=e,e.props.children.push(t),w.push(t);G.push(e)}else{e.dom||(e.dom=ae(e));let t=W(e);t&&t.dom?.appendChild(e.dom);for(let n=e.props.children.length-1;n>=0;n--)e.props.children[n].parent=e,w.push(e.props.children[n])}U(e)}function F(e){if(e.type==="FRAGMENT")if(e.props.children[h])for(const n of e.props.children)n.parent=e,F(n);else{let n=!1;for(const r of e.props.children)r.parent=e,r.props.key===void 0&&(n=!0),F(r);n&&console.error("Array children must have a key attribute")}else if(typeof e.type!="function")for(const t of e.props.children)t.parent=e,F(t);U(e)}function p(e,t,n,r,o){if(e.type==="FRAGMENT")for(const i of e.props.children)r&&(i.parent=e),p(i,t,n,r,o);else if(typeof e.type=="function"){_e(e);const i=e.type(e.props);if(Ee(),Array.isArray(i)){for(const s of i)s.parent=e,p(s,t,n,!0,o);e.props.children=i}else i.parent=e,e.props.children.push(i),p(i,t,n,!0,o);queueMicrotask(()=>{Ce(e)})}else{if(e.dom||(e.dom=ae(e)),t)n?t.parentElement?.replaceChild(e.dom,t):t.parentElement?.insertBefore(e.dom,t);else{let i;o?i=o:i=W(e)?.dom,i?.appendChild(e.dom)}for(const i of e.props.children)r&&(i.parent=e),p(i,void 0,void 0,r,e.dom)}r&&U(e)}let I=!0;function _(e,t){if(!(!e||!I)){if(e.renderFunction&&(t&&je(e.renderFunction),delete e.renderFunction),e.dom){for(const n in e.props)if($(n)){let r=n.toLowerCase().substring(2);const o=r!=(r=r.replace(j,"$1"));e.dom.removeEventListener(r,e.props[n],o),delete e.props[n]}else typeof e.props[n]=="function"?Ve(e.props[n]):n==="ref"&&e.props[n]instanceof ne&&(e.props[n].current=null);e.dom.remove()}typeof e.type=="function"&&(at(e,e.props),delete e.type),e.props.children.forEach(n=>_(n,!0))}}function U(e){e.renderFunction&&Ze(e.renderFunction,e)}function pe(e,t){if(A(t)){const n={...x(t),parent:e.parent};F(n),y(e,n)}else if(Array.isArray(t)){const r={type:"FRAGMENT",props:{children:t[h]?t:P(t)},parent:e.parent};F(r),y(e,r)}else{const n={...t,parent:e.parent};F(n),y(e,n)}}function Xe(e,t){e.renderFunction&&(t.renderFunction=e.renderFunction,U(t))}function qe(e,t,n){if(n!==void 0){e.parent.props.children[n]=t;return}for(let r=0;re.startsWith("on")||e=="onFocusOut"||e=="onFocusIn",oe=e=>e!=="children"&&!$(e)&&e!=="key"&&e!=="ref",q=(e,t,n)=>e[n]!==t[n],Ke=(e,t,n)=>!(n in t);function y(e,t,n){if(!(!e&&!t)){if(e&&!t)_(e,!0),e.parent.props.children=e.parent.props.children.filter(r=>r!==e);else if(e&&t){const r=e.props,o=t.props;if(e.type==="FRAGMENT"||typeof e.type=="function")if(t.type==="FRAGMENT"||typeof t.type=="function")typeof e.type==typeof t.type&&typeof e.type=="function"?ue(e,t)||(p(t,v(e),void 0,!0),D(e,t,n)):ie(e,t);else{t.parent=e.parent;let i=v(e.props.children[0]);p(t,i),D(e,t,n)}else{const i=e.dom;if(e.type==="TEXT_CHILD"&&t.type==="TEXT_CHILD"&&!t.dom&&(t.dom=e.dom),i===void 0)return;if(t.type==="FRAGMENT"||typeof t.type=="function")t.parent=e.parent,p(t,i),D(e,t,n);else{for(const s in r)if(oe(s)&&Ke(r,o,s))i[s]="";else if($(s)&&(!(s in o)||q(r,o,s))){let c=s.toLowerCase().substring(2);const l=c!=(c=c.replace(j,"$1"));i.removeEventListener(c,r[s],l)}if(e.type!==t.type)t.parent=e.parent,p(t,i,!0),D(e,t,n);else{for(const s in o)if(oe(s)&&q(r,o,s))i[s]=o[s],r[s]=o[s];else if($(s)&&q(r,o,s)){let c=s.toLowerCase().substring(2);const l=c!=(c=c.replace(j,"$1"));i.addEventListener(c,o[s],l),r[s]=o[s]}ie(e,t)}}}}}}function Qe(e,t){const n=e.props.children,r=t.props.children,o={};for(let l=0;ll?e.props.children[l]=g:e.props.children.push(g),delete o[S];const M=t.props.children[l];M&&(M.parent=e),y(g,M,l),k(e.props.children[l],s)}else c>l?e.props.children[l]=a:e.props.children.push(a),a.parent=e,p(a,void 0,!1,!1,s)}for(const l in o){const a=o[l];_(a,!0)}for(;e.props.children.length>t.props.children.length;)e.props.children.pop();i?.dom?.appendChild(s)}function k(e,t,n){if(e.dom){if(e.dom===t||e.dom===n)return;t.appendChild(e.dom)}else for(const r of e.props.children)k(r,t,n)}function ie(e,t){const n=t.type==="FRAGMENT"&&!t.props.children[h],r=e.type==="FRAGMENT"&&!e.props.children[h];n&&r?Qe(e,t)===!1&&se(e,t):se(e,t),t.type==="FRAGMENT"&&t.props.children[h]?e.props.children[h]=!0:e.props.children[h]=!1,e.type=t.type}function K(e,t){let n=Math.max(e.props.children.length,t.props.children.length);for(let r=0;r{Y.forEach(t=>{const n=t();if(Z.has(n))return;Z.add(n),n.__cleanup&&typeof n.__cleanup=="function"&&(n.__cleanup(),n.__cleanup=null);const r=n();if(typeof r=="function"&&(n.__cleanup=r),O.has(n)){const o=O.get(n);o&&pe(o,r)}if(H.has(n)){const o=H.get(n);o&&n.__propName&&Oe(n.__propName,o,r)}}),Z.clear(),Y.clear(),Q=!1}))}function Ze(e,t){O.set(e,t)}function Je(e,t){H.set(e,t)}function Ve(e){H.delete(e);const t=e.__signals;if(t){for(const n of t)n.removeDep(e);e.__signals=null}}function je(e){O.delete(e);const t=e.__signals;if(t){for(const n of t)n.removeDep(e);e.__signals=null}}const Be=["push","pop","unshift","shift","splice","fill","copyWithin","sort","reverse"];function le(e){return Be.includes(String(e))}process.env.NODE_ENV;function J(e){return{get value(){return e.value},update:e.update.bind(e)}}const de=(e,t)=>new Proxy(e,{get:(n,r)=>{const o=n[r];if(typeof o=="function"){if(le(r)&&!t.updateCalled)throw new Error("Cannot set a value on an array signal, use the update method for updating the array.");return(...i)=>{const s=o.apply(n,i);return le(r)&&t.notify(),s}}return o},set:(n,r,o)=>{if(!t.updateCalled)throw new Error("Cannot set a value on an array signal, use the update method for updating the array.");return n[r]=o,t.notify(),!0}});let C=null,d=null;function he(e){d=e}function ye(){d=null}function ge(e){C=e}function me(){C=null}function xe(e){C.__signals||(C.__signals=new Set),C.__signals.add(e)}function ve(e){d.__signals||(d.__signals=new Set),d.__signals.add(e)}function be(e){if(typeof e!="function")throw new Error("reactive takes a render function as the argument");ge(e);const t=e();if(me(),!A(t)&&N(t)&&!t.type&&!t.props&&!t.props?.children)throw new Error("Reactive value must be primitive or functional component, got: "+typeof t);return t}function et(e){if(typeof e!="function")throw new Error("reactive takes a render function as the argument");ge(e);const t=e();return me(),t}function tt(e){if(typeof e!="function")throw new Error("createEffect takes a effect function as the argument");Me(e),Fe()||we(e)}function we(e,t){if(typeof e!="function")return;he(e);const n=e();d.__signals&&typeof n=="function"&&(d.__cleanup=n),!d.__signals&&n&&typeof n=="function"&&(t?ct(n,t):Se(n)),ye()}function nt(e){if(typeof e!="function")throw new Error("computed takes a function as the argument");let t=Fe()!==null;he(()=>{if(t){t=!1;return}r.update(e())}),Me(d);const n=e(),r=L(n);return ye(),{get value(){return r.value}}}function rt(e){if(typeof e!="function")throw new Error("createPromise takes a function as the argument");const t=e();if(!(t instanceof Promise))throw new Error("createPromise takes a function that returns a promise");const n=L({status:"pending",data:null,error:null});return t.then(r=>{n.update(o=>{o.data=r,o.status="resolved"})}).catch(r=>{n.update(o=>{o.error=r,o.status="rejected"})}),{get value(){return n.value}}}class ne{constructor(t){this.current=t}}function ot(){return new ne(null)}class R{constructor(t){this.isNotified=!1,this._val=t,this.deps=new Set}notify(){this.isNotified||(this.deps.size!==0&&(this.isNotified=!0),this.deps.forEach(t=>{Ye(()=>(this.isNotified=!1,t))}))}removeDep(t){this.deps.delete(t)}clearDeps(){this.deps.clear()}get value(){return d&&(this.deps.add(d),ve(this)),C&&(this.deps.add(C),xe(this)),this._val}}class it extends R{constructor(t){super(t)}update(t){if(typeof t=="function"){const n=t(this._val);if(n===this._val)return;this._val=n,this.notify()}else{if(t===this._val)return;this._val=t,this.notify()}}}class st extends R{constructor(t){super(t),this.updateCalled=!1,this._val=this.createProxy(t)}createProxy(t){return de(t,this)}update(t){if(this.updateCalled=!0,typeof t=="function")t(this._val);else{if(t===this._val)return;this._val=this.createProxy(t),this.notify()}this.updateCalled=!1}}class lt extends R{constructor(t){N(t),super(t),this.updateCalled=!1,this._val=this.createProxy(t)}createInternalArrayProxy(t){return de(t,this)}createProxy(t){return new Proxy(t,{get:(n,r)=>{const o=n[r];return Array.isArray(o)?(n[r]=this.createInternalArrayProxy(o),n[r]):o},set:(n,r,o)=>(this.updateCalled,typeof o=="function"?!1:(typeof o=="object"&&o!==null&&(o=this.createProxy(o)),o===n[r]||(n[r]=o,this.notify()),!0)),deleteProperty:(n,r)=>{const o=delete n[r];return this.notify(),o}})}update(t){if(this.updateCalled=!0,typeof t=="function")t(this._val);else{if(N(t),t===this._val)return;this._val=this.createProxy(t),this.notify()}this.updateCalled=!1}}function L(e){if(typeof e=="object"&&e!==null){if(Array.isArray(e)){const t=new st(e);return V(t),J(t)}else if(N(e)){const t=new lt(e);return V(t),J(t)}}else if(A(e)){const t=new it(e);return V(t),J(t)}}let f=null,u=new WeakMap;function _e(e){f=e}function Ee(){f=null}function Fe(){return f}function z(){return{signals:new Set,cleanup:[],effects:new Set}}function Ce(e){if(u.has(e)){const t=u.get(e);for(const n of t.effects)we(n,e)}}function Se(e){if(f)if(u.has(f))u.get(f).cleanup.push(e);else{let t=z();t.cleanup.push(e),u.set(f,t)}}function ct(e,t){if(t)if(u.has(t))u.get(t).cleanup.push(e);else{let n=z();n.cleanup.push(e),u.set(t,n)}}function Me(e){if(f)if(u.has(f))u.get(f).effects.add(e);else{let t=z();t.effects.add(e),u.set(f,t)}}function V(e){if(f)if(u.has(f))u.get(f).signals.add(e);else{let t=z();t.signals.add(e),u.set(f,t)}}function at(e,t){const n=u.get(e);if(n){if(n.cleanup)for(const r of n.cleanup)r();n.cleanup=[];for(const r of n.effects){if(r.__cleanup&&r.__cleanup(),r.__signals)for(const o of r.__signals)o.removeDep(r);delete r.__signals,delete r.__cleanup}n.signals.forEach(r=>r.clearDeps()),n.signals.clear()}u.delete(e)}function ut(e){let t=null;const n=(r,o)=>{t?(r.update(!1),o.update(null)):e().then(i=>{if(i.default){if(typeof i.default!="function")throw new Error("Lazy-loaded component must be a functional component");t=i.default,r.update(!1),o.update(null)}else o.update(new Error("No default export found from lazy-loaded module"))}).catch(i=>{o.update(i),r.update(!1)})};return r=>{const o=L(!0),i=L(null);return n(o,i),B("FRAGMENT",null,()=>o.value?r.fallback:i.value!==null?r.errorFallback?typeof r.errorFallback=="function"?r.errorFallback(i.value):r.errorFallback:"Unknown error occurred while lazy loading component, use errorFallback prop to override":t&&B(t,{...r}))}}exports.cleanUp=Se;exports.computed=nt;exports.createEffect=tt;exports.createElement=B;exports.createPromise=rt;exports.createRef=ot;exports.createSignal=L;exports.lazy=ut;exports.render=We; diff --git a/build/refract.es.js b/build/refract.es.js index 45b769a..c9d689b 100644 --- a/build/refract.es.js +++ b/build/refract.es.js @@ -1,13 +1,13 @@ -function T(e) { +function N(e) { return typeof e == "object" && // Must be an object e !== null && // Cannot be null !Array.isArray(e) && // Cannot be an array Object.prototype.toString.call(e) === "[object Object]"; } -function _(e) { +function M(e) { return ["boolean", "string", "number", "undefined"].includes(typeof e) || e === null || e instanceof Error; } -const ce = "http://www.w3.org/2000/svg", Se = /* @__PURE__ */ new Set([ +const ce = "http://www.w3.org/2000/svg", ke = /* @__PURE__ */ new Set([ "svg", "a", "circle", @@ -67,7 +67,7 @@ const ce = "http://www.w3.org/2000/svg", Se = /* @__PURE__ */ new Set([ "tspan", "use", "view" -]), Fe = /* @__PURE__ */ new Set([ +]), Ae = /* @__PURE__ */ new Set([ "math", "maction", "maligngroup", @@ -107,16 +107,16 @@ const ce = "http://www.w3.org/2000/svg", Se = /* @__PURE__ */ new Set([ "mtr", "munder", "munderover" -]), Ce = "http://www.w3.org/1998/Math/MathML", Z = /(PointerCapture)$|Capture$/i, ke = /acit|ex(?:s|g|n|p|$)|rph|grid|ows|mnc|ntw|ine[ch]|zoo|^ord|itera/i; -function Ae(e) { +]), Me = "http://www.w3.org/1998/Math/MathML", j = /(PointerCapture)$|Capture$/i, Te = /acit|ex(?:s|g|n|p|$)|rph|grid|ows|mnc|ntw|ine[ch]|zoo|^ord|itera/i; +function Ne(e) { const t = []; for (const n in e) { const r = e[n], o = n.replace(/([A-Z])/g, "-$1").toLowerCase(); - typeof r != "number" || ke.test(o) ? t.push(`${o}: ${r};`) : t.push(`${o}: ${r}px;`); + typeof r != "number" || Te.test(o) ? t.push(`${o}: ${r};`) : t.push(`${o}: ${r}px;`); } return t.join(" "); } -function Me(e) { +function Pe(e) { const t = {}; for (const n in e) { const r = e[n]; @@ -128,32 +128,32 @@ function Me(e) { } return t; } -function Pe(e) { - return T(e) || typeof e == "string"; +function Le(e) { + return N(e) || typeof e == "string"; } -function Te(e, t) { - if (!Pe(e)) +function Re(e, t) { + if (!Le(e)) throw new Error("Style attribute must be a plain object or a string"); if (typeof e == "string") t.setAttribute("style", e); else { - const n = Me(e); - t.setAttribute("style", Ae(n)); + const n = Pe(e); + t.setAttribute("style", Ne(n)); } } -function Le(e, t, n, r) { +function De(e, t, n, r) { e.__propName = t; - const o = Qe(e); - o == null || o === !1 || (b(t, o, n, r), e.__signals && je(e, n)); + const o = ve(e); + o == null || o === !1 || (ee(t, o, n, r), e.__signals && Ye(e, n)); } -const Ne = /(PointerCapture)$|Capture$/i; -function b(e, t, n, r) { +const Ge = /(PointerCapture)$|Capture$/i; +function ee(e, t, n, r) { if (e == "style") { - Te(t, n); + Re(t, n); return; } if (e[0] === "o" && e[1] === "n" && typeof t == "function") { - const o = e != (e = e.replace(Ne, "$1")); + const o = e != (e = e.replace(Ge, "$1")); e.toLowerCase() in n || e == "onFocusOut" || e == "onFocusIn" || e === "onGotPointerCapture" || e === "onLostPointerCapture" ? e = e.toLowerCase().slice(2) : e = e.slice(2), n.addEventListener(e, t, o); return; } @@ -172,25 +172,25 @@ function b(e, t, n, r) { e === "popover" && t === !0 ? "" : t ); } -const w = Symbol("FRAGMENT"); -function oe(e, t, ...n) { +const h = Symbol("FRAGMENT"); +function ne(e, t, ...n) { if (e === "FRAGMENT") { - const r = L(n); - return r[w] = !0, r; + const r = P(n); + return r[h] = !0, r; } return { type: e, props: { ...t, - children: L(n) + children: P(n) } }; } -function L(e) { +function P(e) { return e.map((t) => { if (typeof t == "object") { if (Array.isArray(t)) - return L(t); + return P(t); if (t === null) return B(""); if (!t.type || !t.props) @@ -199,9 +199,9 @@ function L(e) { ); return t; } else if (typeof t == "function") { - const n = Je(t); - if (_(n)) - return j( + const n = xe(t); + if (M(n)) + return q( "TEXT_CHILD", { nodeValue: n != null && n !== !1 ? String(n) : "", @@ -210,17 +210,17 @@ function L(e) { t ); if (Array.isArray(n)) { - const r = n[w]; - return j( + const r = n[h]; + return q( "FRAGMENT", - { children: r ? n : L(n) }, + { children: r ? n : P(n) }, t ); } else if (!n.type || !n.props) throw new Error( "Invalid type for a dom node, found " + n ); - return j(n.type, n.props, t); + return q(n.type, n.props, t); } else return B(t); }).flat(); @@ -234,19 +234,19 @@ function B(e) { } }; } -function j(e, t, n) { +function q(e, t, n) { return { type: e, renderFunction: n, props: t }; } -function Re(e) { +function Ie(e) { return e !== "children" && e !== "key" && e !== "ref"; } function ue(e) { let t = null; - Se.has(e.type) ? t = ce : Fe.has(e.type) && (t = Ce); + ke.has(e.type) ? t = ce : Ae.has(e.type) && (t = Me); const n = e.type === "TEXT_CHILD" ? document.createTextNode("") : t ? document.createElementNS( t, // @ts-expect-error @@ -257,22 +257,67 @@ function ue(e) { document.createElement(e.type) ); if (!e.props) return n; - e.props.ref && e.props.ref instanceof re && n instanceof HTMLElement && (e.props.ref.current = n); + e.props.ref && e.props.ref instanceof te && n instanceof HTMLElement && (e.props.ref.current = n); for (const r in e.props) { - if (!Re(r)) + if (!Ie(r)) continue; const o = e.props[r]; - typeof o == "function" && r[0] !== "o" && r[1] !== "n" ? Le(o, r, n, t) : b(r, o, n, t); + typeof o == "function" && r[0] !== "o" && r[1] !== "n" ? De(o, r, n, t) : ee(r, o, n, t); } return n; } -function De(e, t, n) { - n == null || e === "key" || b(e, n, t); +function $e(e, t, n) { + n == null || e === "key" || ee(e, n, t); +} +function ae(e, t) { + return e === t ? !0 : e.type !== t.type || e.props?.key !== t.props?.key ? !1 : T(e.props, t.props); +} +function T(e, t) { + if (e === t) { + if (e instanceof L && t instanceof L) + return T(e.value, t.value); + if (Array.isArray(e) && Array.isArray(t)) { + if (e.length !== t.length) return !1; + for (let n = 0; n < e.length; n++) + if (!T(e[n], t[n])) return !1; + } + return !0; + } + if (M(e) && M(t)) + return e === t; + if (typeof e != typeof t) return !1; + for (let n in e) + if (n !== "children" && (!(n in t) || !T(e[n], t[n]))) + return !1; + for (let n in t) + if (n !== "children" && !(n in e)) + return !1; + return !0; +} +function x(e) { + if (e) { + if (e.dom) return e.dom; + for (const t of e.props.children) { + const n = x(t); + if (n) return n; + } + } +} +function W(e) { + if (!e) return; + let t = e.parent; + for (; t && !t.dom; ) + t = t.parent; + return t; } -function be(e, t) { - x = t; +function Oe(e) { + if (e) + return e.dom ? e : W(e); +} +function it(e, t) { + v = t; const n = document.createDocumentFragment(); - v = n; + b = n; const r = { type: "div", props: { @@ -281,508 +326,414 @@ function be(e, t) { // @ts-expect-error dom: n }; - e.parent = r, F.push(e), requestIdleCallback(fe); + e.parent = r, w.push(e), requestIdleCallback(fe); } -function Ie() { - v && x && x.appendChild(v); +function He() { + b && v && v.appendChild(b); } -let F = [], x = null, v = null, G = []; -function ie() { - for (let e = 0; e < G.length; e++) { - const t = G[e]; - Ee(t); +let w = [], v = null, b = null, D = []; +function re() { + for (let e = 0; e < D.length; e++) { + const t = D[e]; + Ce(t); } - G.length = 0; + D.length = 0; } function fe(e) { - ie(); + re(); let t = !1; - for (; F.length > 0 && !t; ) { - const n = F.pop(); - Ge(n), t = e.timeRemaining() < 1; + for (; w.length > 0 && !t; ) { + const n = w.pop(); + We(n), t = e.timeRemaining() < 1; } - if (F.length == 0) { - Ie(), ie(); + if (w.length == 0) { + He(), re(); return; } requestIdleCallback(fe); } -function Ge(e) { - var t; +function We(e) { if (e.type === "FRAGMENT") { - const n = !e.props.children[w]; - let r = !1; - for (let o = e.props.children.length - 1; o >= 0; o--) - e.props.children[o].parent = e, n && e.props.children[o].props.key === void 0 && e.renderFunction && (r = !0), F.push(e.props.children[o]); - r && console.error("Array children must have a key attribute"); + const t = !e.props.children[h]; + let n = !1; + for (let r = e.props.children.length - 1; r >= 0; r--) + e.props.children[r].parent = e, t && e.props.children[r].props.key === void 0 && e.renderFunction && (n = !0), w.push(e.props.children[r]); + n && console.error("Array children must have a key attribute"); } else if (typeof e.type == "function") { - ge(e); - const n = e.type(e.props); - if (me(), Array.isArray(n)) { - for (let r = n.length - 1; r >= 0; r--) - n[r].parent = e, F.push(n[r]); - e.props.children = n; + _e(e); + const t = e.type(e.props); + if (Ee(), Array.isArray(t)) { + for (let n = t.length - 1; n >= 0; n--) + t[n].parent = e, w.push(t[n]); + e.props.children = t; } else - n.parent = e, e.props.children.push(n), F.push(n); - G.push(e); + t.parent = e, e.props.children.push(t), w.push(t); + D.push(e); } else { e.dom || (e.dom = ue(e)); - let n = e.parent; - for (; n && !n.dom; ) - n = n.parent; - n && ((t = n.dom) == null || t.appendChild(e.dom)); - for (let r = e.props.children.length - 1; r >= 0; r--) - e.props.children[r].parent = e, F.push(e.props.children[r]); + let t = W(e); + t && t.dom?.appendChild(e.dom); + for (let n = e.props.children.length - 1; n >= 0; n--) + e.props.children[n].parent = e, w.push(e.props.children[n]); } - z(e); + U(e); } -function C(e) { +function F(e) { if (e.type === "FRAGMENT") - if (e.props.children[w]) + if (e.props.children[h]) for (const n of e.props.children) - n.parent = e, C(n); + n.parent = e, F(n); else { let n = !1; for (const r of e.props.children) - r.parent = e, r.props.key === void 0 && (n = !0), C(r); + r.parent = e, r.props.key === void 0 && (n = !0), F(r); n && console.error("Array children must have a key attribute"); } else if (typeof e.type != "function") for (const t of e.props.children) - t.parent = e, C(t); - z(e); + t.parent = e, F(t); + U(e); } -function h(e, t, n, r, o) { - var l, i; +function p(e, t, n, r, o) { if (e.type === "FRAGMENT") - for (const s of e.props.children) - r && (s.parent = e), h( - s, + for (const i of e.props.children) + r && (i.parent = e), p( + i, t, n, r, o ); else if (typeof e.type == "function") { - ge(e); - const s = e.type(e.props); - if (me(), Array.isArray(s)) { - for (const a of s) - a.parent = e, h(a, t, n, !0, o); - e.props.children = s; + _e(e); + const i = e.type(e.props); + if (Ee(), Array.isArray(i)) { + for (const s of i) + s.parent = e, p(s, t, n, !0, o); + e.props.children = i; } else - s.parent = e, e.props.children.push(s), h(s, t, n, !0, o); + i.parent = e, e.props.children.push(i), p(i, t, n, !0, o); queueMicrotask(() => { - Ee(e); + Ce(e); }); } else { if (e.dom || (e.dom = ue(e)), t) - n ? (l = t.parentElement) == null || l.replaceChild( + n ? t.parentElement?.replaceChild( e.dom, t - ) : (i = t.parentElement) == null || i.insertBefore( + ) : t.parentElement?.insertBefore( e.dom, t ); else { - let s; - if (o) - s = o; - else { - let a = e.parent; - for (; a && !a.dom; ) - a = a.parent; - s = a == null ? void 0 : a.dom; - } - s == null || s.appendChild(e.dom); + let i; + o ? i = o : i = W(e)?.dom, i?.appendChild(e.dom); } - for (const s of e.props.children) - r && (s.parent = e), h(s, void 0, void 0, r, e.dom); + for (const i of e.props.children) + r && (i.parent = e), p(i, void 0, void 0, r, e.dom); } - r && z(e); + r && U(e); } -let O = !0; -function g(e, t) { - if (!(!e || !O)) { - if (e.renderFunction && (t && Ke(e.renderFunction), delete e.renderFunction), e.dom) { +let G = !0; +function _(e, t) { + if (!(!e || !G)) { + if (e.renderFunction && (t && Je(e.renderFunction), delete e.renderFunction), e.dom) { for (const n in e.props) - if ($(n)) { + if (I(n)) { let r = n.toLowerCase().substring(2); - const o = r != (r = r.replace(Z, "$1")); + const o = r != (r = r.replace(j, "$1")); e.dom.removeEventListener( r, e.props[n], o ), delete e.props[n]; - } else typeof e.props[n] == "function" ? qe(e.props[n]) : n === "ref" && e.props[n] instanceof re && (e.props[n].current = null); + } else typeof e.props[n] == "function" ? Ze(e.props[n]) : n === "ref" && e.props[n] instanceof te && (e.props[n].current = null); e.dom.remove(); } - typeof e.type == "function" && (ve(e, e.props), delete e.type), e.props.children.forEach((n) => g(n, !0)); + typeof e.type == "function" && (ot(e, e.props), delete e.type), e.props.children.forEach((n) => _(n, !0)); } } -function z(e) { - e.renderFunction && ze(e.renderFunction, e); +function U(e) { + e.renderFunction && Qe(e.renderFunction, e); } function pe(e, t) { - if (_(t)) { + if (M(t)) { const n = { ...B(t), parent: e.parent }; - C(n), E(e, n); + F(n), y(e, n); } else if (Array.isArray(t)) { const r = { type: "FRAGMENT", props: { - children: t[w] ? t : L(t) + children: t[h] ? t : P(t) }, parent: e.parent }; - C(r), E(e, r); + F(r), y(e, r); } else { const n = { ...t, parent: e.parent }; - C(n), E(e, n); + F(n), y(e, n); } } -function D(e, t) { - e.renderFunction && (t.renderFunction = e.renderFunction, z(t)); +function Ue(e, t) { + e.renderFunction && (t.renderFunction = e.renderFunction, U(t)); } -function I(e, t, n) { - var r; +function Xe(e, t, n) { if (n !== void 0) { e.parent.props.children[n] = t; return; } - (r = e.parent) == null || r.props.children.forEach((o, l) => { - o === e && (e.parent.props.children[l] = t); - }); -} -const $ = (e) => e.startsWith("on") || e == "onFocusOut" || e == "onFocusIn", se = (e) => e !== "children" && !$(e) && e !== "key" && e !== "ref", q = (e, t, n) => e[n] !== t[n], Oe = (e, t, n) => !(n in t); -function de(e, t) { - var n, r; - return e === t ? !0 : e.type !== t.type || ((n = e.props) == null ? void 0 : n.key) !== ((r = t.props) == null ? void 0 : r.key) ? !1 : P(e.props, t.props); -} -function P(e, t) { - if (e === t) { - if (e instanceof N && t instanceof N) - return P(e.value, t.value); - if (Array.isArray(e) && Array.isArray(t)) { - if (e.length !== t.length) return !1; - for (let o = 0; o < e.length; o++) - if (!P(e[o], t[o])) return !1; - } - return !0; - } - if (_(e) && _(t)) - return e === t; - if (typeof e != typeof t) return !1; - const n = Object.keys(e), r = Object.keys(t); - if (n.length !== r.length) return !1; - for (let o of n) - if (o !== "children" && (!t.hasOwnProperty(o) || !P(e[o], t[o]))) - return !1; - return !0; -} -function he(e) { - if (e) { - if (e.dom) return e.dom; - for (const t of e.props.children) { - const n = he(t); - if (n) return n; - } - } -} -function ee(e) { - if (e) { - if (e.dom) return e.dom; - for (let t = e.props.children.length - 1; t >= 0; t--) { - const n = e.props.children[t], r = ee(n); - if (r) return r; - } - } + for (let r = 0; r < e.parent.props.children.length; r++) + e.parent.props.children[r] === e && (e.parent.props.children[r] = t); } -function $e(e) { - if (e) - for (let t = e.props.children.length - 1; t >= 0; t--) { - const n = e.props.children[t], r = ee(n); - if (r) return r; - } -} -function He(e) { - if (!e) return; - let t = e.parent; - for (; t && !t.dom; ) - t = t.parent; - return t; +function R(e, t, n) { + Ue(e, t), _(e), Xe(e, t, n); } -function We(e) { - if (!e) return; - if (e.dom) return e; - let t = e.parent; - for (; t && !t.dom; ) - t = t.parent; - return t; -} -function E(e, t, n) { +const I = (e) => e.startsWith("on") || e == "onFocusOut" || e == "onFocusIn", oe = (e) => e !== "children" && !I(e) && e !== "key" && e !== "ref", z = (e, t, n) => e[n] !== t[n], qe = (e, t, n) => !(n in t); +function y(e, t, n) { if (!(!e && !t)) { if (e && !t) - g(e, !0), e.parent.props.children = e.parent.props.children.filter( + _(e, !0), e.parent.props.children = e.parent.props.children.filter( (r) => r !== e ); else if (e && t) { const r = e.props, o = t.props; if (e.type === "FRAGMENT" || typeof e.type == "function") if (t.type === "FRAGMENT" || typeof t.type == "function") - typeof e.type == typeof t.type && typeof e.type == "function" ? de(e, t) || (h(t, he(e), void 0, !0), D(e, t), g(e), I(e, t, n)) : le(e, t); + typeof e.type == typeof t.type && typeof e.type == "function" ? ae(e, t) || (p(t, x(e), void 0, !0), R(e, t, n)) : ie(e, t); else { t.parent = e.parent; - let l = e.props.children[0]; - for (; l && !l.dom; ) - l = l.props.children[0]; - h(t, l == null ? void 0 : l.dom), D(e, t), g(e), I(e, t, n); + let i = x(e.props.children[0]); + p(t, i), R(e, t, n); } else { - const l = e.dom; - if (e.type === "TEXT_CHILD" && t.type === "TEXT_CHILD" && !t.dom && (t.dom = e.dom), l === void 0) + const i = e.dom; + if (e.type === "TEXT_CHILD" && t.type === "TEXT_CHILD" && !t.dom && (t.dom = e.dom), i === void 0) return; if (t.type === "FRAGMENT" || typeof t.type == "function") - t.parent = e.parent, D(e, t), h(t, l), g(e), I(e, t, n); + t.parent = e.parent, p(t, i), R(e, t, n); else { - for (const i in r) - if (se(i) && Oe(r, o, i)) - l[i] = ""; - else if ($(i) && (!(i in o) || q(r, o, i))) { - let s = i.toLowerCase().substring(2); - const a = s != (s = s.replace( - Z, + for (const s in r) + if (oe(s) && qe(r, o, s)) + i[s] = ""; + else if (I(s) && (!(s in o) || z(r, o, s))) { + let c = s.toLowerCase().substring(2); + const l = c != (c = c.replace( + j, "$1" )); - l.removeEventListener( - s, - r[i], - a + i.removeEventListener( + c, + r[s], + l ); } if (e.type !== t.type) - t.parent = e.parent, D(e, t), h(t, l, !0), g(e), I(e, t, n); + t.parent = e.parent, p(t, i, !0), R(e, t, n); else { - for (const i in o) - if (se(i) && q(r, o, i)) - l[i] = o[i], r[i] = o[i]; - else if ($(i) && q(r, o, i)) { - let s = i.toLowerCase().substring(2); - const a = s != (s = s.replace( - Z, + for (const s in o) + if (oe(s) && z(r, o, s)) + i[s] = o[s], r[s] = o[s]; + else if (I(s) && z(r, o, s)) { + let c = s.toLowerCase().substring(2); + const l = c != (c = c.replace( + j, "$1" )); - l.addEventListener( - s, - o[i], - a - ), r[i] = o[i]; + i.addEventListener( + c, + o[s], + l + ), r[s] = o[s]; } - le(e, t); + ie(e, t); } } } } } } -function Xe(e, t) { - var a; +function ze(e, t) { const n = e.props.children, r = t.props.children, o = {}; - for (let c = 0; c < n.length; c++) { - const u = n[c].props.key; - if (u == null || o.hasOwnProperty(String(u))) + for (let l = 0; l < n.length; l++) { + const u = n[l].props.key; + if (u == null || String(u) in o) return !1; - o[String(u)] = n[c]; + o[String(u)] = n[l]; } - const l = (a = $e(e)) == null ? void 0 : a.nextSibling, i = He(e); + const i = W(e); if (r.length === 0) { - e.props.children.length = 0, (i == null ? void 0 : i.dom) instanceof HTMLElement && (i.dom.innerHTML = ""); + e.props.children.length = 0, i?.dom instanceof HTMLElement && (i.dom.innerHTML = ""); return; } - const s = e.props.children.length; - for (let c = 0; c < r.length; c++) { - const u = r[c], R = u.props.key, m = String(R); - if (o.hasOwnProperty(m)) { - const k = o[m]; - s > c ? e.props.children[c] = k : e.props.children.push(k), delete o[m]; - const A = t.props.children[c]; - A && (A.parent = e), E(k, A, c), M( - e.props.children[c], - i == null ? void 0 : i.dom, - l - ); + const s = document.createDocumentFragment(), c = e.props.children.length; + for (let l = 0; l < r.length; l++) { + const u = r[l], E = u.props.key, S = String(E); + if (S in o) { + const g = o[S]; + c > l ? e.props.children[l] = g : e.props.children.push(g), delete o[S]; + const k = t.props.children[l]; + k && (k.parent = e), y(g, k, l), A(e.props.children[l], s); } else - s > c ? e.props.children[c] = u : e.props.children.push(u), u.parent = e, h( - u, - l, - !1, - !1, - i == null ? void 0 : i.dom - ); + c > l ? e.props.children[l] = u : e.props.children.push(u), u.parent = e, p(u, void 0, !1, !1, s); + } + for (const l in o) { + const u = o[l]; + _(u, !0); } - for (const c in o) - if (o.hasOwnProperty(c)) { - const u = o[c]; - g(u, !0); - } for (; e.props.children.length > t.props.children.length; ) e.props.children.pop(); + i?.dom?.appendChild(s); } -function M(e, t, n) { +function A(e, t, n) { if (e.dom) { if (e.dom === t || e.dom === n) return; - n ? t.insertBefore(e.dom, n) : t.appendChild(e.dom); + t.appendChild(e.dom); } else for (const r of e.props.children) - M(r, t, n); + A(r, t, n); } -function le(e, t) { - const n = t.type === "FRAGMENT" && !t.props.children[w], r = e.type === "FRAGMENT" && !e.props.children[w]; - n && r ? Xe(e, t) === !1 && ae(e, t) : ae(e, t), t.type === "FRAGMENT" && t.props.children[w] ? e.props.children[w] = !0 : e.props.children[w] = !1, e.type = t.type; +function ie(e, t) { + const n = t.type === "FRAGMENT" && !t.props.children[h], r = e.type === "FRAGMENT" && !e.props.children[h]; + n && r ? ze(e, t) === !1 && se(e, t) : se(e, t), t.type === "FRAGMENT" && t.props.children[h] ? e.props.children[h] = !0 : e.props.children[h] = !1, e.type = t.type; } function K(e, t) { - var r; let n = Math.max(e.props.children.length, t.props.children.length); - for (let o = 0; o < n; o++) { - let l = e.props.children[o], i = t.props.children[o]; - if (i && (i.parent = e), !l && i) - h( - i, - // @ts-expect-error - (r = ee(e.props.children.at(-1))) == null ? void 0 : r.nextSibling - ), e.props.children.push(i); - else if (!i && l) - g(l, !0), e.props.children.splice(o, 1), n = e.props.children.length, o--; + for (let r = 0; r < n; r++) { + let o = e.props.children[r], i = t.props.children[r]; + if (i && (i.parent = e), !o && i) + p(i), e.props.children.push(i); + else if (!i && o) + _(o, !0), e.props.children.splice(r, 1), n = e.props.children.length, r--; else { - E(l, i, o); + y(o, i, r); const s = Math.max( e.props.children.length, t.props.children.length ); - s < n && (n = s, o--); + s < n && (n = s, r--); } } } -function ae(e, t) { +function se(e, t) { let n = Math.max(e.props.children.length, t.props.children.length); const r = {}; let o = 0; - for (let s = 0; s < e.props.children.length; s++) { - const a = e.props.children[s].props.key; - if (a != null) { - if (o++, r.hasOwnProperty(String(a))) { - console.warn("Found two children with the same key", a), console.warn( + for (let c = 0; c < e.props.children.length; c++) { + const l = e.props.children[c].props.key; + if (l != null) { + if (o++, String(l) in r) { + console.warn("Found two children with the same key", l), console.warn( "When two fibers are found having same key the whole children will default to manual updates, which can be slower than with key based reconciliation" ), K(e, t); return; } - r[String(a)] = { fiber: e.props.children[s], index: s }; + r[String(l)] = { fiber: e.props.children[c], index: c }; } } if (o == 0) { K(e, t); return; } - const l = {}; - for (let s = 0; s < t.props.children.length; s++) { - const a = t.props.children[s].props.key; - if (a == null) + const i = {}; + for (let c = 0; c < t.props.children.length; c++) { + const l = t.props.children[c].props.key; + if (l == null) continue; - const c = r[String(a)]; - if (c) { - if (l.hasOwnProperty(String(a))) { - console.warn("Found two children with the same key", a), console.warn( + const u = r[String(l)]; + if (u) { + if (String(l) in i) { + console.warn("Found two children with the same key", l), console.warn( "When two fibers are found having same key the whole children will default to manual updates, which can be slower than with key based reconciliation" ), K(e, t); return; } - l[String(a)] = { - fiber: c.fiber, - newIndex: s, - oldIndex: c.index + i[String(l)] = { + fiber: u.fiber, + newIndex: c, + oldIndex: u.index }; } } - const i = We(e); - for (let s = 0; s < n; s++) { - let a = e.props.children[s], c = t.props.children[s]; - const u = c != null && c.props.key ? String(c.props.key) : "", R = l.hasOwnProperty(u); - let m = a != null && a.props.key ? String(a.props.key) : ""; - if (m && u && m === u) { - E(a, c, s), i != null && i.dom && M(e.props.children[s], i.dom); + const s = Oe(e); + for (let c = 0; c < n; c++) { + let l = e.props.children[c], u = t.props.children[c]; + const E = u?.props.key ? String(u.props.key) : "", S = E in i; + let g = l?.props.key ? String(l.props.key) : ""; + if (g && E && g === E) { + y(l, u, c), s?.dom && A(e.props.children[c], s.dom); continue; } - const k = l.hasOwnProperty(m) && l[m].newIndex > s, A = l.hasOwnProperty(m) && l[m].newIndex < s; - if ((k || A) && (O = !1), c && (c.parent = e), !a && c) - if (R) { - const { fiber: S } = l[u]; - e.props.children.push(S), E(S, c, s), i != null && i.dom && M(e.props.children[s], i.dom); + const k = g in i && i[g].newIndex !== c; + if (k && (G = !1), u && (u.parent = e), !l && u) + if (S) { + const { fiber: m } = i[E]; + e.props.children.push(m), y(m, u, c), s?.dom && A(e.props.children[c], s.dom); } else - i != null && i.dom && h(c, void 0, !1, !1, i.dom), e.props.children.push(c); - else if (!c && a) - g(a, !0), e.props.children.splice(s, 1), n = e.props.children.length, s--; - else if (R) { - const { fiber: S } = l[u]; - g(a, !0), O = !0, e.props.children[s] = S, E(S, c, s), i != null && i.dom && M(e.props.children[s], i.dom); - } else if (k || A) - i != null && i.dom && h( - c, + s?.dom && p(u, void 0, !1, !1, s.dom), e.props.children.push(u); + else if (!u && l) + _(l, !0), e.props.children.splice(c, 1), n = e.props.children.length, c--; + else if (S) { + const { fiber: m } = i[E]; + _(l, !0), G = !0, e.props.children[c] = m, y(m, u, c), s?.dom && A(e.props.children[c], s.dom); + } else if (k) + s?.dom && p( + u, void 0, !1, !1, - i.dom - ), e.props.children[s] = c; + s.dom + ), e.props.children[c] = u; else { - E(a, c, s), i != null && i.dom && M(e.props.children[s], i.dom); - const S = Math.max( + y(l, u, c), s?.dom && A(e.props.children[c], s.dom); + const m = Math.max( e.props.children.length, t.props.children.length ); - S < n && (n = S, s--); + m < n && (n = m, c--); } - O = !0; + G = !0; } } typeof process < "u" && process.env.NODE_ENV === "test" && (module.exports = { - createFiber: C, - commitDeletion: g, - commitFiber: h, + createFiber: F, + commitDeletion: _, + commitFiber: p, updateFiber: pe, - deepCompareFibers: de, - deepEqual: P + deepCompareFibers: ae, + deepEqual: T }); -let J = !1; -const Q = /* @__PURE__ */ new Set(), Y = /* @__PURE__ */ new Set(), H = /* @__PURE__ */ new WeakMap(), W = /* @__PURE__ */ new WeakMap(); -function Ue(e) { - Q.add(e), J || (J = !0, queueMicrotask(() => { - Q.forEach((t) => { +let Q = !1; +const Y = /* @__PURE__ */ new Set(), Z = /* @__PURE__ */ new Set(), $ = /* @__PURE__ */ new WeakMap(), O = /* @__PURE__ */ new WeakMap(); +function Ke(e) { + Y.add(e), Q || (Q = !0, queueMicrotask(() => { + Y.forEach((t) => { const n = t(); - if (Y.has(n)) + if (Z.has(n)) return; - Y.add(n), n.__cleanup && typeof n.__cleanup == "function" && (n.__cleanup(), n.__cleanup = null); + Z.add(n), n.__cleanup && typeof n.__cleanup == "function" && (n.__cleanup(), n.__cleanup = null); const r = n(); - if (typeof r == "function" && (n.__cleanup = r), H.has(n)) { - const o = H.get(n); + if (typeof r == "function" && (n.__cleanup = r), $.has(n)) { + const o = $.get(n); o && pe(o, r); } - if (W.has(n)) { - const o = W.get(n); - o && n.__propName && De(n.__propName, o, r); + if (O.has(n)) { + const o = O.get(n); + o && n.__propName && $e(n.__propName, o, r); } - }), Y.clear(), Q.clear(), J = !1; + }), Z.clear(), Y.clear(), Q = !1; })); } -function ze(e, t) { - H.set(e, t); +function Qe(e, t) { + $.set(e, t); } -function je(e, t) { - W.set(e, t); +function Ye(e, t) { + O.set(e, t); } -function qe(e) { - W.delete(e); +function Ze(e) { + O.delete(e); const t = e.__signals; if (t) { for (const n of t) @@ -790,8 +741,8 @@ function qe(e) { e.__signals = null; } } -function Ke(e) { - H.delete(e); +function Je(e) { + $.delete(e); const t = e.__signals; if (t) { for (const n of t) @@ -799,62 +750,120 @@ function Ke(e) { e.__signals = null; } } -let y = null, f = null; -function te(e) { - y.__signals || (y.__signals = /* @__PURE__ */ new Set()), y.__signals.add(e); +const Ve = [ + "push", + "pop", + "unshift", + "shift", + "splice", + "fill", + "copyWithin", + "sort", + "reverse" +]; +function le(e) { + return Ve.includes(String(e)); } -function ne(e) { - f.__signals || (f.__signals = /* @__PURE__ */ new Set()), f.__signals.add(e); +// @ts-expect-error +process.env.NODE_ENV; +function J(e) { + return { + get value() { + return e.value; + }, + update: e.update.bind(e) + }; } -function Je(e) { - var n; +const de = (e, t) => new Proxy(e, { + get: (n, r) => { + const o = n[r]; + if (typeof o == "function") { + if (le(r) && !t.updateCalled) + throw new Error( + "Cannot set a value on an array signal, use the update method for updating the array." + ); + return (...i) => { + const s = o.apply(n, i); + return le(r) && t.notify(), s; + }; + } + return o; + }, + set: (n, r, o) => { + if (!t.updateCalled) + throw new Error( + "Cannot set a value on an array signal, use the update method for updating the array." + ); + return n[r] = o, t.notify(), !0; + } +}); +let C = null, d = null; +function he(e) { + d = e; +} +function ye() { + d = null; +} +function ge(e) { + C = e; +} +function me() { + C = null; +} +function je(e) { + C.__signals || (C.__signals = /* @__PURE__ */ new Set()), C.__signals.add(e); +} +function Be(e) { + d.__signals || (d.__signals = /* @__PURE__ */ new Set()), d.__signals.add(e); +} +function xe(e) { if (typeof e != "function") throw new Error("reactive takes a render function as the argument"); - y = e; + ge(e); const t = e(); - if (y = null, !_(t) && T(t) && !t.type && !t.props && !((n = t.props) != null && n.children)) + if (me(), !M(t) && N(t) && !t.type && !t.props && !t.props?.children) throw new Error( "Reactive value must be primitive or functional component, got: " + typeof t ); return t; } -function Qe(e) { +function ve(e) { if (typeof e != "function") throw new Error("reactive takes a render function as the argument"); - y = e; + ge(e); const t = e(); - return y = null, t; + return me(), t; } -function et(e) { +function st(e) { if (typeof e != "function") throw new Error("createEffect takes a effect function as the argument"); - _e(e), we() || ye(e); + Se(e), Fe() || we(e); } -function ye(e, t) { +function we(e, t) { if (typeof e != "function") return; - f = e; + he(e); const n = e(); - f.__signals && typeof n == "function" && (f.__cleanup = n), !f.__signals && n && typeof n == "function" && (t ? xe(n, t) : Be(n)), f = null; + d.__signals && typeof n == "function" && (d.__cleanup = n), !d.__signals && n && typeof n == "function" && (t ? rt(n, t) : nt(n)), ye(); } -function tt(e) { +function lt(e) { if (typeof e != "function") throw new Error("computed takes a function as the argument"); - let t = we() !== null; - f = () => { + let t = Fe() !== null; + he(() => { if (t) { t = !1; return; } r.update(e()); - }, _e(f); - const n = e(), r = U(n); - return f = null, { + }), Se(d); + const n = e(), r = H(n); + return ye(), { get value() { return r.value; } }; } -function nt(e) { +function ct(e) { if (typeof e != "function") throw new Error("createPromise takes a function as the argument"); const t = e(); @@ -862,7 +871,7 @@ function nt(e) { throw new Error( "createPromise takes a function that returns a promise" ); - const n = U({ + const n = H({ status: "pending", data: null, error: null @@ -881,32 +890,21 @@ function nt(e) { } }; } -class re { +class te { constructor(t) { this.current = t; } } -function rt() { - return new re(null); +function ut() { + return new te(null); } -const X = [ - "push", - "pop", - "unshift", - "shift", - "splice", - "fill", - "copyWithin", - "sort", - "reverse" -]; -class N { +class L { constructor(t) { this.isNotified = !1, this._val = t, this.deps = /* @__PURE__ */ new Set(); } notify() { this.isNotified || (this.deps.size !== 0 && (this.isNotified = !0), this.deps.forEach((t) => { - Ue(() => (this.isNotified = !1, t)); + Ke(() => (this.isNotified = !1, t)); })); } removeDep(t) { @@ -915,119 +913,48 @@ class N { clearDeps() { this.deps.clear(); } + get value() { + return d && (this.deps.add(d), Be(this)), C && (this.deps.add(C), je(this)), this._val; + } } -class Ye extends N { +class be extends L { constructor(t) { - if (!_(t)) - throw new Error( - "Invalid type for PrimitiveSignal. Valid types: [boolean, string, number, undefined, null]" - ); super(t); } - get value() { - return f && (this.deps.add(f), ne(this)), y && (this.deps.add(y), te(this)), this._val; - } update(t) { if (typeof t == "function") { const n = t(this._val); - if (!_(n)) - throw new Error( - "Invalid type for PrimitiveSignal. Valid types: [boolean, string, number, undefined, null]" - ); if (n === this._val) return; this._val = n, this.notify(); } else { - if (!_(t)) - throw new Error( - "Invalid type for PrimitiveSignal. Valid types: [boolean, string, number, undefined, null]" - ); if (t === this._val) return; this._val = t, this.notify(); } } } -class Ve extends N { +class et extends L { constructor(t) { - if (!Array.isArray(t)) - throw new Error( - "Invalid type for ArraySignal; value must be an array" - ); super(t), this.updateCalled = !1, this._val = this.createProxy(t); } createProxy(t) { - return new Proxy(t, { - get: (n, r) => { - const o = n[r]; - if (typeof o == "function") { - if (X.includes(String(r)) && !this.updateCalled) - throw new Error( - "Cannot set a value on an array signal, use the update method for updating the array." - ); - return (...l) => { - const i = o.apply(n, l); - return X.includes(String(r)) && this.notify(), i; - }; - } - return o; - }, - set: (n, r, o) => { - if (!this.updateCalled) - throw new Error( - "Cannot set a value on an array signal, use the update method for updating the array." - ); - return n[r] = o, this.notify(), !0; - } - }); - } - get value() { - return f && (this.deps.add(f), ne(this)), y && (this.deps.add(y), te(this)), this._val; + return de(t, this); } update(t) { if (this.updateCalled = !0, typeof t == "function") t(this._val); else { - if (!Array.isArray(t)) - throw new Error( - "Invalid type for ArraySignal; value must be an array" - ); if (t === this._val) return; this._val = this.createProxy(t), this.notify(); } this.updateCalled = !1; } } -class Ze extends N { +class tt extends L { constructor(t) { - if (!T(t)) - throw new Error( - "Invalid type for ObjectSignal; value must be a plain object" - ); - super(t), this.updateCalled = !1, this._val = this.createProxy(t); + N(t), super(t), this.updateCalled = !1, this._val = this.createProxy(t); } createInternalArrayProxy(t) { - return new Proxy(t, { - get: (n, r) => { - const o = n[r]; - if (typeof o == "function") { - if (!this.updateCalled && X.includes(String(r))) - throw new Error( - "Cannot set a value on an object signal, use the update method for updating the object." - ); - return (...l) => { - const i = o.apply(n, l); - return X.includes(String(r)) && this.notify(), i; - }; - } - return o; - }, - set: (n, r, o) => { - if (!this.updateCalled) - throw new Error( - "Cannot set a value on an object signal, use the update method for updating the object." - ); - return n[r] = o, this.notify(), !0; - } - }); + return de(t, this); } createProxy(t) { return new Proxy(t, { @@ -1035,190 +962,150 @@ class Ze extends N { const o = n[r]; return Array.isArray(o) ? (n[r] = this.createInternalArrayProxy(o), n[r]) : o; }, - set: (n, r, o) => { - if (!this.updateCalled) - throw new Error( - "Cannot set a value on an object signal, use the update method for updating the object." - ); - return typeof o == "function" ? !1 : (typeof o == "object" && o !== null && (o = this.createProxy(o)), o === n[r] || (n[r] = o, this.notify()), !0); - }, + set: (n, r, o) => (this.updateCalled, typeof o == "function" ? !1 : (typeof o == "object" && o !== null && (o = this.createProxy(o)), o === n[r] || (n[r] = o, this.notify()), !0)), deleteProperty: (n, r) => { const o = delete n[r]; return this.notify(), o; } }); } - get value() { - return f && (this.deps.add(f), ne(this)), y && (this.deps.add(y), te(this)), this._val; - } update(t) { if (this.updateCalled = !0, typeof t == "function") t(this._val); else { - if (!T(t)) - throw new Error( - "Invalid type for ObjectSignal; value must be a plain object" - ); - if (t === this._val) return; + if (N(t), t === this._val) return; this._val = this.createProxy(t), this.notify(); } this.updateCalled = !1; } } -function U(e) { - if (typeof e == "function") - throw new Error("Functions cannot be used as signal value"); - if (typeof e == "object" && e !== null) +function H(e) { + if (typeof e == "object" && e !== null) { if (Array.isArray(e)) { - const t = new Ve(e); - return V(t), { - get value() { - return t.value; - }, - update: t.update.bind(t) - }; - } else if (T(e)) { - const t = new Ze(e); - return V(t), { - get value() { - return t.value; - }, - update: t.update.bind(t) - }; - } else - throw new Error( - "Invalid type for signal initialization: " + typeof e - ); - else if (_(e)) { - const t = new Ye(e); - return V(t), { - get value() { - return t.value; - }, - update: t.update.bind(t) - }; - } else - throw new Error( - "Invalid type for signal initialization: " + typeof e - ); + const t = new et(e); + return V(t), J(t); + } else if (N(e)) { + const t = new tt(e); + return V(t), J(t); + } + } else if (M(e)) { + const t = new be(e); + return V(t), J(t); + } } -let d = null, p = /* @__PURE__ */ new WeakMap(); -function ge(e) { - d = e; +let f = null, a = /* @__PURE__ */ new WeakMap(); +function _e(e) { + f = e; } -function me() { - d = null; +function Ee() { + f = null; +} +function Fe() { + return f; } -function we() { - return d; +function X() { + return { + signals: /* @__PURE__ */ new Set(), + cleanup: [], + effects: /* @__PURE__ */ new Set() + }; } -function Ee(e) { - if (p.has(e)) { - const t = p.get(e); +function Ce(e) { + if (a.has(e)) { + const t = a.get(e); for (const n of t.effects) - ye(n, e); + we(n, e); } } -function Be(e) { - d && (p.has(d) ? p.get(d).cleanup.push(e) : p.set(d, { - signals: /* @__PURE__ */ new Set(), - cleanup: [e], - effects: /* @__PURE__ */ new Set() - })); +function nt(e) { + if (f) + if (a.has(f)) + a.get(f).cleanup.push(e); + else { + let t = X(); + t.cleanup.push(e), a.set(f, t); + } } -function xe(e, t) { - t && (p.has(t) ? p.get(t).cleanup.push(e) : p.set(t, { - signals: /* @__PURE__ */ new Set(), - cleanup: [e], - effects: /* @__PURE__ */ new Set() - })); +function rt(e, t) { + if (t) + if (a.has(t)) + a.get(t).cleanup.push(e); + else { + let n = X(); + n.cleanup.push(e), a.set(t, n); + } } -function _e(e) { - if (d) - if (p.has(d)) - p.get(d).effects.add(e); +function Se(e) { + if (f) + if (a.has(f)) + a.get(f).effects.add(e); else { - const t = /* @__PURE__ */ new Set(); - t.add(e), p.set(d, { - signals: /* @__PURE__ */ new Set(), - cleanup: [], - effects: t - }); + let t = X(); + t.effects.add(e), a.set(f, t); } } function V(e) { - if (d) - if (p.has(d)) - p.get(d).signals.add(e); + if (f) + if (a.has(f)) + a.get(f).signals.add(e); else { - const t = /* @__PURE__ */ new Set(); - t.add(e), p.set(d, { - signals: t, - cleanup: [], - effects: /* @__PURE__ */ new Set() - }); + let t = X(); + t.signals.add(e), a.set(f, t); } } -function ve(e, t) { - const n = p.get(e); +function ot(e, t) { + const n = a.get(e); if (n) { if (n.cleanup) for (const r of n.cleanup) r(); n.cleanup = []; for (const r of n.effects) { - if (r.__cleanup && typeof r.__cleanup == "function" && r.__cleanup(), r.__signals) + if (r.__cleanup && r.__cleanup(), r.__signals) for (const o of r.__signals) o.removeDep(r); delete r.__signals, delete r.__cleanup; } n.signals.forEach((r) => r.clearDeps()), n.signals.clear(); } - p.delete(e); + a.delete(e); } -function ot(e) { +function at(e) { let t = null; const n = (r, o) => { - t ? (r.update(!1), o.update(null)) : e().then((l) => { - if (l.default) { - if (typeof l.default != "function") + t ? (r.update(!1), o.update(null)) : e().then((i) => { + if (i.default) { + if (typeof i.default != "function") throw new Error( "Lazy-loaded component must be a functional component" ); - t = l.default, r.update(!1), o.update(null); + t = i.default, r.update(!1), o.update(null); } else o.update( new Error( "No default export found from lazy-loaded module" ) ); - }).catch((l) => { - o.update(l), r.update(!1); + }).catch((i) => { + o.update(i), r.update(!1); }); }; return (r) => { - const o = U(!0), l = U(null); - n(o, l); - const i = (s) => typeof s == "string" || s && typeof s == "object" && "props" in s && "type" in s; - if (r.fallback !== void 0 && !i(r.fallback)) - throw new Error( - "Invalid fallback: Expected a string or a valid JSX node." - ); - if (r.errorFallback !== void 0 && !(typeof r.errorFallback == "function" || i(r.errorFallback))) - throw new Error( - "Invalid errorFallback: Expected a string, a valid JSX node, or a function returning a JSX node." - ); - return /* @__PURE__ */ oe("FRAGMENT", null, () => o.value ? r.fallback : l.value !== null ? r.errorFallback ? typeof r.errorFallback == "function" ? r.errorFallback(l.value) : r.errorFallback : "Unknown error occurred while lazy loading component, use errorFallback prop to override" : t && /* @__PURE__ */ oe(t, { ...r })); + const o = H(!0), i = H(null); + return n(o, i), /* @__PURE__ */ ne("FRAGMENT", null, () => o.value ? r.fallback : i.value !== null ? r.errorFallback ? typeof r.errorFallback == "function" ? r.errorFallback(i.value) : r.errorFallback : "Unknown error occurred while lazy loading component, use errorFallback prop to override" : ( + // @ts-expect-error + t && /* @__PURE__ */ ne(t, { ...r }) + )); }; } export { - Be as cleanUp, - tt as computed, - et as createEffect, - oe as createElement, - nt as createPromise, - rt as createRef, - U as createSignal, - ot as lazy, - be as render + nt as cleanUp, + lt as computed, + st as createEffect, + ne as createElement, + ct as createPromise, + ut as createRef, + H as createSignal, + at as lazy, + it as render }; diff --git a/build/refract.umd.js b/build/refract.umd.js deleted file mode 100644 index ee0e0bd..0000000 --- a/build/refract.umd.js +++ /dev/null @@ -1 +0,0 @@ -(function(h,_){typeof exports=="object"&&typeof module<"u"?_(exports):typeof define=="function"&&define.amd?define(["exports"],_):(h=typeof globalThis<"u"?globalThis:h||self,_(h.Refract={}))})(this,function(h){"use strict";function _(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)&&Object.prototype.toString.call(e)==="[object Object]"}function S(e){return["boolean","string","number","undefined"].includes(typeof e)||e===null||e instanceof Error}const se="http://www.w3.org/2000/svg",Ce=new Set(["svg","a","circle","clipPath","defs","desc","ellipse","feBlend","feColorMatrix","feComponentTransfer","feComposite","feConvolveMatrix","feDiffuseLighting","feDisplacementMap","feDistantLight","feDropShadow","feFlood","feFuncA","feFuncB","feFuncG","feFuncR","feGaussianBlur","feImage","feMerge","feMergeNode","feMorphology","feOffset","fePointLight","feSpecularLighting","feSpotLight","feTile","feTurbulence","filter","foreignObject","g","image","line","linearGradient","marker","mask","metadata","path","pattern","polygon","polyline","radialGradient","rect","script","set","stop","style","switch","symbol","text","textPath","title","tspan","use","view"]),ke=new Set(["math","maction","maligngroup","malignmark","menclose","merror","mfenced","mfrac","mglyph","mi","mlabeledtr","mlongdiv","mmultiscripts","mn","mo","mover","mpadded","mphantom","mroot","mrow","ms","mscarries","mscarry","msgroup","msline","mspace","msqrt","msrow","mstack","mstyle","msub","msup","msubsup","mtable","mtd","mtext","mtr","munder","munderover"]),Ae="http://www.w3.org/1998/Math/MathML",q=/(PointerCapture)$|Capture$/i,Me=/acit|ex(?:s|g|n|p|$)|rph|grid|ows|mnc|ntw|ine[ch]|zoo|^ord|itera/i;function Te(e){const t=[];for(const n in e){const r=e[n],o=n.replace(/([A-Z])/g,"-$1").toLowerCase();typeof r!="number"||Me.test(o)?t.push(`${o}: ${r};`):t.push(`${o}: ${r}px;`)}return t.join(" ")}function Pe(e){const t={};for(const n in e){const r=e[n];if(typeof r=="object"&&r!==null){console.warn(`Nested styles not allowed for ${n}`);continue}r==null||r===!1||r===""||(t[n]=r)}return t}function Le(e){return _(e)||typeof e=="string"}function Ne(e,t){if(!Le(e))throw new Error("Style attribute must be a plain object or a string");if(typeof e=="string")t.setAttribute("style",e);else{const n=Pe(e);t.setAttribute("style",Te(n))}}function Re(e,t,n,r){e.__propName=t;const o=Ze(e);o==null||o===!1||(K(t,o,n,r),e.__signals&&Je(e,n))}const De=/(PointerCapture)$|Capture$/i;function K(e,t,n,r){if(e=="style"){Ne(t,n);return}if(e[0]==="o"&&e[1]==="n"&&typeof t=="function"){const o=e!=(e=e.replace(De,"$1"));e.toLowerCase()in n||e=="onFocusOut"||e=="onFocusIn"||e==="onGotPointerCapture"||e==="onLostPointerCapture"?e=e.toLowerCase().slice(2):e=e.slice(2),n.addEventListener(e,t,o);return}if(r===se)e=e.replace(/xlink(H|:h)/,"h").replace(/sName$/,"s");else if(e!=="width"&&e!=="height"&&e!=="href"&&e!=="list"&&e!=="form"&&e!=="tabIndex"&&e!=="download"&&e!=="rowSpan"&&e!=="colSpan"&&e!=="role"&&e!=="popover"&&e in n)try{e==="value"&&n.tagName==="SELECT"?setTimeout(()=>{n[e]=t??""}):n[e]=t??"";return}catch{}t!=null&&(t!==!1||e[4]==="-")&&n.setAttribute(e,e==="popover"&&t===!0?"":t)}const w=Symbol("FRAGMENT");function J(e,t,...n){if(e==="FRAGMENT"){const r=L(n);return r[w]=!0,r}return{type:e,props:{...t,children:L(n)}}}function L(e){return e.map(t=>{if(typeof t=="object"){if(Array.isArray(t))return L(t);if(t===null)return Q("");if(!t.type||!t.props)throw new Error("Invalid type for a dom node, found "+t);return t}else if(typeof t=="function"){const n=Ve(t);if(S(n))return Y("TEXT_CHILD",{nodeValue:n!=null&&n!==!1?String(n):"",children:[]},t);if(Array.isArray(n)){const r=n[w];return Y("FRAGMENT",{children:r?n:L(n)},t)}else if(!n.type||!n.props)throw new Error("Invalid type for a dom node, found "+n);return Y(n.type,n.props,t)}else return Q(t)}).flat()}function Q(e){return{type:"TEXT_CHILD",props:{nodeValue:e!=null&&e!==!1?String(e):"",children:[]}}}function Y(e,t,n){return{type:e,renderFunction:n,props:t}}function Ie(e){return e!=="children"&&e!=="key"&&e!=="ref"}function le(e){let t=null;Ce.has(e.type)?t=se:ke.has(e.type)&&(t=Ae);const n=e.type==="TEXT_CHILD"?document.createTextNode(""):t?document.createElementNS(t,e.type,e.props.is&&e.props):document.createElement(e.type);if(!e.props)return n;e.props.ref&&e.props.ref instanceof oe&&n instanceof HTMLElement&&(e.props.ref.current=n);for(const r in e.props){if(!Ie(r))continue;const o=e.props[r];typeof o=="function"&&r[0]!=="o"&&r[1]!=="n"?Re(o,r,n,t):K(r,o,n,t)}return n}function Ge(e,t,n){n==null||e==="key"||K(e,n,t)}function Oe(e,t){V=t;const n=document.createDocumentFragment();Z=n;const r={type:"div",props:{children:[e]},dom:n};e.parent=r,C.push(e),requestIdleCallback(ce)}function $e(){Z&&V&&V.appendChild(Z)}let C=[],V=null,Z=null,I=[];function ae(){for(let e=0;e0&&!t;){const n=C.pop();He(n),t=e.timeRemaining()<1}if(C.length==0){$e(),ae();return}requestIdleCallback(ce)}function He(e){var t;if(e.type==="FRAGMENT"){const n=!e.props.children[w];let r=!1;for(let o=e.props.children.length-1;o>=0;o--)e.props.children[o].parent=e,n&&e.props.children[o].props.key===void 0&&e.renderFunction&&(r=!0),C.push(e.props.children[o]);r&&console.error("Array children must have a key attribute")}else if(typeof e.type=="function"){me(e);const n=e.type(e.props);if(we(),Array.isArray(n)){for(let r=n.length-1;r>=0;r--)n[r].parent=e,C.push(n[r]);e.props.children=n}else n.parent=e,e.props.children.push(n),C.push(n);I.push(e)}else{e.dom||(e.dom=le(e));let n=e.parent;for(;n&&!n.dom;)n=n.parent;n&&((t=n.dom)==null||t.appendChild(e.dom));for(let r=e.props.children.length-1;r>=0;r--)e.props.children[r].parent=e,C.push(e.props.children[r])}O(e)}function A(e){if(e.type==="FRAGMENT")if(e.props.children[w])for(const n of e.props.children)n.parent=e,A(n);else{let n=!1;for(const r of e.props.children)r.parent=e,r.props.key===void 0&&(n=!0),A(r);n&&console.error("Array children must have a key attribute")}else if(typeof e.type!="function")for(const t of e.props.children)t.parent=e,A(t);O(e)}function y(e,t,n,r,o){var l,i;if(e.type==="FRAGMENT")for(const s of e.props.children)r&&(s.parent=e),y(s,t,n,r,o);else if(typeof e.type=="function"){me(e);const s=e.type(e.props);if(we(),Array.isArray(s)){for(const a of s)a.parent=e,y(a,t,n,!0,o);e.props.children=s}else s.parent=e,e.props.children.push(s),y(s,t,n,!0,o);queueMicrotask(()=>{_e(e)})}else{if(e.dom||(e.dom=le(e)),t)n?(l=t.parentElement)==null||l.replaceChild(e.dom,t):(i=t.parentElement)==null||i.insertBefore(e.dom,t);else{let s;if(o)s=o;else{let a=e.parent;for(;a&&!a.dom;)a=a.parent;s=a==null?void 0:a.dom}s==null||s.appendChild(e.dom)}for(const s of e.props.children)r&&(s.parent=e),y(s,void 0,void 0,r,e.dom)}r&&O(e)}let G=!0;function m(e,t){if(!(!e||!G)){if(e.renderFunction&&(t&&Ye(e.renderFunction),delete e.renderFunction),e.dom){for(const n in e.props)if(W(n)){let r=n.toLowerCase().substring(2);const o=r!=(r=r.replace(q,"$1"));e.dom.removeEventListener(r,e.props[n],o),delete e.props[n]}else typeof e.props[n]=="function"?Qe(e.props[n]):n==="ref"&&e.props[n]instanceof oe&&(e.props[n].current=null);e.dom.remove()}typeof e.type=="function"&&(ot(e,e.props),delete e.type),e.props.children.forEach(n=>m(n,!0))}}function O(e){e.renderFunction&&Ke(e.renderFunction,e)}function ue(e,t){if(S(t)){const n={...Q(t),parent:e.parent};A(n),F(e,n)}else if(Array.isArray(t)){const r={type:"FRAGMENT",props:{children:t[w]?t:L(t)},parent:e.parent};A(r),F(e,r)}else{const n={...t,parent:e.parent};A(n),F(e,n)}}function $(e,t){e.renderFunction&&(t.renderFunction=e.renderFunction,O(t))}function H(e,t,n){var r;if(n!==void 0){e.parent.props.children[n]=t;return}(r=e.parent)==null||r.props.children.forEach((o,l)=>{o===e&&(e.parent.props.children[l]=t)})}const W=e=>e.startsWith("on")||e=="onFocusOut"||e=="onFocusIn",fe=e=>e!=="children"&&!W(e)&&e!=="key"&&e!=="ref",B=(e,t,n)=>e[n]!==t[n],We=(e,t,n)=>!(n in t);function pe(e,t){var n,r;return e===t?!0:e.type!==t.type||((n=e.props)==null?void 0:n.key)!==((r=t.props)==null?void 0:r.key)?!1:N(e.props,t.props)}function N(e,t){if(e===t){if(e instanceof R&&t instanceof R)return N(e.value,t.value);if(Array.isArray(e)&&Array.isArray(t)){if(e.length!==t.length)return!1;for(let o=0;o=0;t--){const n=e.props.children[t],r=v(n);if(r)return r}}}function Ue(e){if(e)for(let t=e.props.children.length-1;t>=0;t--){const n=e.props.children[t],r=v(n);if(r)return r}}function Xe(e){if(!e)return;let t=e.parent;for(;t&&!t.dom;)t=t.parent;return t}function ze(e){if(!e)return;if(e.dom)return e;let t=e.parent;for(;t&&!t.dom;)t=t.parent;return t}function F(e,t,n){if(!(!e&&!t)){if(e&&!t)m(e,!0),e.parent.props.children=e.parent.props.children.filter(r=>r!==e);else if(e&&t){const r=e.props,o=t.props;if(e.type==="FRAGMENT"||typeof e.type=="function")if(t.type==="FRAGMENT"||typeof t.type=="function")typeof e.type==typeof t.type&&typeof e.type=="function"?pe(e,t)||(y(t,de(e),void 0,!0),$(e,t),m(e),H(e,t,n)):he(e,t);else{t.parent=e.parent;let l=e.props.children[0];for(;l&&!l.dom;)l=l.props.children[0];y(t,l==null?void 0:l.dom),$(e,t),m(e),H(e,t,n)}else{const l=e.dom;if(e.type==="TEXT_CHILD"&&t.type==="TEXT_CHILD"&&!t.dom&&(t.dom=e.dom),l===void 0)return;if(t.type==="FRAGMENT"||typeof t.type=="function")t.parent=e.parent,$(e,t),y(t,l),m(e),H(e,t,n);else{for(const i in r)if(fe(i)&&We(r,o,i))l[i]="";else if(W(i)&&(!(i in o)||B(r,o,i))){let s=i.toLowerCase().substring(2);const a=s!=(s=s.replace(q,"$1"));l.removeEventListener(s,r[i],a)}if(e.type!==t.type)t.parent=e.parent,$(e,t),y(t,l,!0),m(e),H(e,t,n);else{for(const i in o)if(fe(i)&&B(r,o,i))l[i]=o[i],r[i]=o[i];else if(W(i)&&B(r,o,i)){let s=i.toLowerCase().substring(2);const a=s!=(s=s.replace(q,"$1"));l.addEventListener(s,o[i],a),r[i]=o[i]}he(e,t)}}}}}}function je(e,t){var a;const n=e.props.children,r=t.props.children,o={};for(let c=0;cc?e.props.children[c]=T:e.props.children.push(T),delete o[E];const P=t.props.children[c];P&&(P.parent=e),F(T,P,c),M(e.props.children[c],i==null?void 0:i.dom,l)}else s>c?e.props.children[c]=u:e.props.children.push(u),u.parent=e,y(u,l,!1,!1,i==null?void 0:i.dom)}for(const c in o)if(o.hasOwnProperty(c)){const u=o[c];m(u,!0)}for(;e.props.children.length>t.props.children.length;)e.props.children.pop()}function M(e,t,n){if(e.dom){if(e.dom===t||e.dom===n)return;n?t.insertBefore(e.dom,n):t.appendChild(e.dom)}else for(const r of e.props.children)M(r,t,n)}function he(e,t){const n=t.type==="FRAGMENT"&&!t.props.children[w],r=e.type==="FRAGMENT"&&!e.props.children[w];n&&r?je(e,t)===!1&&ye(e,t):ye(e,t),t.type==="FRAGMENT"&&t.props.children[w]?e.props.children[w]=!0:e.props.children[w]=!1,e.type=t.type}function b(e,t){var r;let n=Math.max(e.props.children.length,t.props.children.length);for(let o=0;os,P=l.hasOwnProperty(E)&&l[E].newIndex{ee.forEach(t=>{const n=t();if(te.has(n))return;te.add(n),n.__cleanup&&typeof n.__cleanup=="function"&&(n.__cleanup(),n.__cleanup=null);const r=n();if(typeof r=="function"&&(n.__cleanup=r),U.has(n)){const o=U.get(n);o&&ue(o,r)}if(X.has(n)){const o=X.get(n);o&&n.__propName&&Ge(n.__propName,o,r)}}),te.clear(),ee.clear(),x=!1}))}function Ke(e,t){U.set(e,t)}function Je(e,t){X.set(e,t)}function Qe(e){X.delete(e);const t=e.__signals;if(t){for(const n of t)n.removeDep(e);e.__signals=null}}function Ye(e){U.delete(e);const t=e.__signals;if(t){for(const n of t)n.removeDep(e);e.__signals=null}}let g=null,f=null;function ne(e){g.__signals||(g.__signals=new Set),g.__signals.add(e)}function re(e){f.__signals||(f.__signals=new Set),f.__signals.add(e)}function Ve(e){var n;if(typeof e!="function")throw new Error("reactive takes a render function as the argument");g=e;const t=e();if(g=null,!S(t)&&_(t)&&!t.type&&!t.props&&!((n=t.props)!=null&&n.children))throw new Error("Reactive value must be primitive or functional component, got: "+typeof t);return t}function Ze(e){if(typeof e!="function")throw new Error("reactive takes a render function as the argument");g=e;const t=e();return g=null,t}function Be(e){if(typeof e!="function")throw new Error("createEffect takes a effect function as the argument");Fe(e),Ee()||ge(e)}function ge(e,t){if(typeof e!="function")return;f=e;const n=e();f.__signals&&typeof n=="function"&&(f.__cleanup=n),!f.__signals&&n&&typeof n=="function"&&(t?rt(n,t):Se(n)),f=null}function ve(e){if(typeof e!="function")throw new Error("computed takes a function as the argument");let t=Ee()!==null;f=()=>{if(t){t=!1;return}r.update(e())},Fe(f);const n=e(),r=D(n);return f=null,{get value(){return r.value}}}function be(e){if(typeof e!="function")throw new Error("createPromise takes a function as the argument");const t=e();if(!(t instanceof Promise))throw new Error("createPromise takes a function that returns a promise");const n=D({status:"pending",data:null,error:null});return t.then(r=>{n.update(o=>{o.data=r,o.status="resolved"})}).catch(r=>{n.update(o=>{o.error=r,o.status="rejected"})}),{get value(){return n.value}}}class oe{constructor(t){this.current=t}}function xe(){return new oe(null)}const z=["push","pop","unshift","shift","splice","fill","copyWithin","sort","reverse"];class R{constructor(t){this.isNotified=!1,this._val=t,this.deps=new Set}notify(){this.isNotified||(this.deps.size!==0&&(this.isNotified=!0),this.deps.forEach(t=>{qe(()=>(this.isNotified=!1,t))}))}removeDep(t){this.deps.delete(t)}clearDeps(){this.deps.clear()}}class et extends R{constructor(t){if(!S(t))throw new Error("Invalid type for PrimitiveSignal. Valid types: [boolean, string, number, undefined, null]");super(t)}get value(){return f&&(this.deps.add(f),re(this)),g&&(this.deps.add(g),ne(this)),this._val}update(t){if(typeof t=="function"){const n=t(this._val);if(!S(n))throw new Error("Invalid type for PrimitiveSignal. Valid types: [boolean, string, number, undefined, null]");if(n===this._val)return;this._val=n,this.notify()}else{if(!S(t))throw new Error("Invalid type for PrimitiveSignal. Valid types: [boolean, string, number, undefined, null]");if(t===this._val)return;this._val=t,this.notify()}}}class tt extends R{constructor(t){if(!Array.isArray(t))throw new Error("Invalid type for ArraySignal; value must be an array");super(t),this.updateCalled=!1,this._val=this.createProxy(t)}createProxy(t){return new Proxy(t,{get:(n,r)=>{const o=n[r];if(typeof o=="function"){if(z.includes(String(r))&&!this.updateCalled)throw new Error("Cannot set a value on an array signal, use the update method for updating the array.");return(...l)=>{const i=o.apply(n,l);return z.includes(String(r))&&this.notify(),i}}return o},set:(n,r,o)=>{if(!this.updateCalled)throw new Error("Cannot set a value on an array signal, use the update method for updating the array.");return n[r]=o,this.notify(),!0}})}get value(){return f&&(this.deps.add(f),re(this)),g&&(this.deps.add(g),ne(this)),this._val}update(t){if(this.updateCalled=!0,typeof t=="function")t(this._val);else{if(!Array.isArray(t))throw new Error("Invalid type for ArraySignal; value must be an array");if(t===this._val)return;this._val=this.createProxy(t),this.notify()}this.updateCalled=!1}}class nt extends R{constructor(t){if(!_(t))throw new Error("Invalid type for ObjectSignal; value must be a plain object");super(t),this.updateCalled=!1,this._val=this.createProxy(t)}createInternalArrayProxy(t){return new Proxy(t,{get:(n,r)=>{const o=n[r];if(typeof o=="function"){if(!this.updateCalled&&z.includes(String(r)))throw new Error("Cannot set a value on an object signal, use the update method for updating the object.");return(...l)=>{const i=o.apply(n,l);return z.includes(String(r))&&this.notify(),i}}return o},set:(n,r,o)=>{if(!this.updateCalled)throw new Error("Cannot set a value on an object signal, use the update method for updating the object.");return n[r]=o,this.notify(),!0}})}createProxy(t){return new Proxy(t,{get:(n,r)=>{const o=n[r];return Array.isArray(o)?(n[r]=this.createInternalArrayProxy(o),n[r]):o},set:(n,r,o)=>{if(!this.updateCalled)throw new Error("Cannot set a value on an object signal, use the update method for updating the object.");return typeof o=="function"?!1:(typeof o=="object"&&o!==null&&(o=this.createProxy(o)),o===n[r]||(n[r]=o,this.notify()),!0)},deleteProperty:(n,r)=>{const o=delete n[r];return this.notify(),o}})}get value(){return f&&(this.deps.add(f),re(this)),g&&(this.deps.add(g),ne(this)),this._val}update(t){if(this.updateCalled=!0,typeof t=="function")t(this._val);else{if(!_(t))throw new Error("Invalid type for ObjectSignal; value must be a plain object");if(t===this._val)return;this._val=this.createProxy(t),this.notify()}this.updateCalled=!1}}function D(e){if(typeof e=="function")throw new Error("Functions cannot be used as signal value");if(typeof e=="object"&&e!==null)if(Array.isArray(e)){const t=new tt(e);return ie(t),{get value(){return t.value},update:t.update.bind(t)}}else if(_(e)){const t=new nt(e);return ie(t),{get value(){return t.value},update:t.update.bind(t)}}else throw new Error("Invalid type for signal initialization: "+typeof e);else if(S(e)){const t=new et(e);return ie(t),{get value(){return t.value},update:t.update.bind(t)}}else throw new Error("Invalid type for signal initialization: "+typeof e)}let d=null,p=new WeakMap;function me(e){d=e}function we(){d=null}function Ee(){return d}function _e(e){if(p.has(e)){const t=p.get(e);for(const n of t.effects)ge(n,e)}}function Se(e){d&&(p.has(d)?p.get(d).cleanup.push(e):p.set(d,{signals:new Set,cleanup:[e],effects:new Set}))}function rt(e,t){t&&(p.has(t)?p.get(t).cleanup.push(e):p.set(t,{signals:new Set,cleanup:[e],effects:new Set}))}function Fe(e){if(d)if(p.has(d))p.get(d).effects.add(e);else{const t=new Set;t.add(e),p.set(d,{signals:new Set,cleanup:[],effects:t})}}function ie(e){if(d)if(p.has(d))p.get(d).signals.add(e);else{const t=new Set;t.add(e),p.set(d,{signals:t,cleanup:[],effects:new Set})}}function ot(e,t){const n=p.get(e);if(n){if(n.cleanup)for(const r of n.cleanup)r();n.cleanup=[];for(const r of n.effects){if(r.__cleanup&&typeof r.__cleanup=="function"&&r.__cleanup(),r.__signals)for(const o of r.__signals)o.removeDep(r);delete r.__signals,delete r.__cleanup}n.signals.forEach(r=>r.clearDeps()),n.signals.clear()}p.delete(e)}function it(e){let t=null;const n=(r,o)=>{t?(r.update(!1),o.update(null)):e().then(l=>{if(l.default){if(typeof l.default!="function")throw new Error("Lazy-loaded component must be a functional component");t=l.default,r.update(!1),o.update(null)}else o.update(new Error("No default export found from lazy-loaded module"))}).catch(l=>{o.update(l),r.update(!1)})};return r=>{const o=D(!0),l=D(null);n(o,l);const i=s=>typeof s=="string"||s&&typeof s=="object"&&"props"in s&&"type"in s;if(r.fallback!==void 0&&!i(r.fallback))throw new Error("Invalid fallback: Expected a string or a valid JSX node.");if(r.errorFallback!==void 0&&!(typeof r.errorFallback=="function"||i(r.errorFallback)))throw new Error("Invalid errorFallback: Expected a string, a valid JSX node, or a function returning a JSX node.");return J("FRAGMENT",null,()=>o.value?r.fallback:l.value!==null?r.errorFallback?typeof r.errorFallback=="function"?r.errorFallback(l.value):r.errorFallback:"Unknown error occurred while lazy loading component, use errorFallback prop to override":t&&J(t,{...r}))}}h.cleanUp=Se,h.computed=ve,h.createEffect=Be,h.createElement=J,h.createPromise=be,h.createRef=xe,h.createSignal=D,h.lazy=it,h.render=Oe,Object.defineProperty(h,Symbol.toStringTag,{value:"Module"})}); diff --git a/build/rendering/utils.d.ts b/build/rendering/utils.d.ts new file mode 100644 index 0000000..34dc5e7 --- /dev/null +++ b/build/rendering/utils.d.ts @@ -0,0 +1,6 @@ +import { Fiber } from '../types'; +export declare function deepCompareFibers(fiberA: any, fiberB: any): boolean; +export declare function deepEqual(objA: any, objB: any): boolean; +export declare function findFirstDom(fiber: Fiber): HTMLElement | Text | undefined; +export declare function findParentFiberWithDom(fiber: Fiber): Fiber | undefined; +export declare function findNearestParentWithDom(fiber: Fiber): Fiber | undefined; diff --git a/build/signals/signal.d.ts b/build/signals/signal.d.ts index 7fc5cf7..c63d330 100644 --- a/build/signals/signal.d.ts +++ b/build/signals/signal.d.ts @@ -30,11 +30,7 @@ export declare function createRef(): Ref; type DeepReadonly = { readonly [K in keyof T]: T[K] extends object ? DeepReadonly : T[K]; }; -/** - * - * Base class for signals. - */ -export declare abstract class BaseSignal { +export declare abstract class BaseSignal { protected _val: T; protected deps: Set; protected isNotified: boolean; @@ -42,37 +38,25 @@ export declare abstract class BaseSignal { protected notify(): void; removeDep(fn: Function): void; clearDeps(): void; - abstract get value(): T | DeepReadonly; + get value(): DeepReadonly; abstract update(val: T | ((prev: T) => T)): void; } type NormalSignal = boolean | string | number | undefined | null | Error; -/** - * Signal for primitive types. - */ export declare class PrimitiveSignal extends BaseSignal { constructor(val: T); - get value(): T; update(val: T | ((prev: T) => T)): void; } -/** - * Signal for arrays. - */ export declare class ArraySignal extends BaseSignal { private updateCalled; constructor(val: T); private createProxy; - get value(): DeepReadonly; update(val: T | ((prev: T) => void)): void; } -/** - * Signal for plain objects. - */ export declare class ObjectSignal> extends BaseSignal { private updateCalled; constructor(val: T); private createInternalArrayProxy; private createProxy; - get value(): DeepReadonly; update(val: T | ((prev: T) => void)): void; } export interface PublicSignal { @@ -85,9 +69,6 @@ export interface PublicArraySignal extends PublicSignal { export interface PublicObjectSignal> extends PublicSignal { update(val: T | ((prev: T) => void)): void; } -/** - * Overloaded factory function to create a signal. - */ declare function createSignal(val: T): PublicSignal; declare function createSignal(val: T): PublicArraySignal; declare function createSignal>(val: T): PublicObjectSignal; diff --git a/build/signals/utils.d.ts b/build/signals/utils.d.ts new file mode 100644 index 0000000..ce6fbb8 --- /dev/null +++ b/build/signals/utils.d.ts @@ -0,0 +1,14 @@ +import { BaseSignal } from './signal'; +export declare const MutatingMethods: string[]; +export declare function throwNonPrimitiveError(): void; +export declare function throwNotUpdateCalled(): void; +export declare function throwNotArray(): void; +export declare function throwNotObject(): void; +export declare function throwInvalidSignalType(val: any): void; +export declare function publicSignal(signal: BaseSignal): { + readonly value: { + readonly [x: string]: any; + }; + update: typeof signal.update; +}; +export declare const createArrayProxy: (arr: any[], signal: any) => any[]; diff --git a/build/utils/general.d.ts b/build/utils/general.d.ts index 345de41..82a873f 100644 --- a/build/utils/general.d.ts +++ b/build/utils/general.d.ts @@ -1,3 +1,2 @@ export declare function isPlainObject(variable: any): boolean; export declare function isPrimitive(val: any): boolean; -export declare function swap(arr: any[], i: number, j: number): void; diff --git a/package-lock.json b/package-lock.json index a997200..62137d2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,16 +1,17 @@ { - "name": "refract", - "version": "1.1.1", + "name": "refract-js", + "version": "1.1.3", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "refract", - "version": "1.1.1", + "name": "refract-js", + "version": "1.1.3", "license": "ISC", "devDependencies": { "@testing-library/dom": "^10.4.0", "jsdom": "^26.0.0", + "terser": "^5.39.0", "vite": "^6.2.0", "vite-plugin-dts": "^4.5.0", "vitest": "^3.0.1" @@ -611,12 +612,64 @@ "node": ">=18" } }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz", + "integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==", + "dev": true, + "dependencies": { + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/source-map": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz", + "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==", + "dev": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25" + } + }, "node_modules/@jridgewell/sourcemap-codec": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", "dev": true }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, "node_modules/@microsoft/api-extractor": { "version": "7.51.0", "resolved": "https://registry.npmjs.org/@microsoft/api-extractor/-/api-extractor-7.51.0.tgz", @@ -1483,6 +1536,12 @@ "concat-map": "0.0.1" } }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true + }, "node_modules/cac": { "version": "6.7.14", "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", @@ -1566,6 +1625,12 @@ "node": ">= 0.8" } }, + "node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, "node_modules/compare-versions": { "version": "6.1.1", "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-6.1.1.tgz", @@ -2421,6 +2486,16 @@ "node": ">=0.10.0" } }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, "node_modules/sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", @@ -2490,6 +2565,24 @@ "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", "dev": true }, + "node_modules/terser": { + "version": "5.39.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.39.0.tgz", + "integrity": "sha512-LBAhFyLho16harJoWMg/nZsQYgTrg5jXOn2nCYjRUcZZEdE3qa2zb8QEDRUGVZBW4rlazf2fxkg8tztybTaqWw==", + "dev": true, + "dependencies": { + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.8.2", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/tinybench": { "version": "2.9.0", "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", diff --git a/package.json b/package.json index e5f2769..9841ecf 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "refract-js", "type": "module", - "version": "1.1.3", + "version": "1.1.4", "description": "Simpler, Faster and Lighter JSX based rendering for Single-Page Applications", "main": "build/refract.cjs.js", "module": "build/refract.es.js", @@ -9,6 +9,7 @@ "files": [ "build" ], + "sideEffects": false, "exports": { ".": { "types": "./build/index.d.ts", @@ -37,6 +38,7 @@ "devDependencies": { "@testing-library/dom": "^10.4.0", "jsdom": "^26.0.0", + "terser": "^5.39.0", "vite": "^6.2.0", "vite-plugin-dts": "^4.5.0", "vitest": "^3.0.1" diff --git a/src/components/App.tsx b/src/components/App.tsx index 18eae3e..18f846a 100644 --- a/src/components/App.tsx +++ b/src/components/App.tsx @@ -12,20 +12,20 @@ const App = (props: any) => { // return ; // return ; // return ; - return ( - <> - - {() => (visible.value ? : "Hidden")} - - ); + // return ( + // <> + // + // {() => (visible.value ? : "Hidden")} + // + // ); // return ; // return ; - // return ; + return ; // return ; // return ; }; diff --git a/src/components/FC1.tsx b/src/components/FC1.tsx index 73701b5..8634824 100644 --- a/src/components/FC1.tsx +++ b/src/components/FC1.tsx @@ -21,19 +21,19 @@ const FC1 = () => { }); // const compText = computed(() => "FC1" + str.value); return ( - <> +

This is FC1 {() => textSignal.value + str.value}

This is {() => str.value}

- +
); }; export default FC1; diff --git a/src/components/IntellisenseTest.tsx b/src/components/IntellisenseTest.tsx new file mode 100644 index 0000000..192345c --- /dev/null +++ b/src/components/IntellisenseTest.tsx @@ -0,0 +1,63 @@ +import { + createSignal, + createPromise, + createRef, + createEffect, + cleanUp, + computed, + lazy, +} from "../index"; + +const LazyFC = lazy(() => import("./FC1")); + +const IntellisenseTest = () => { + const count = createSignal(0); + const arr = createSignal([1, 2]); + const obj = createSignal({ a: 1, b: 2 }); + + createEffect(() => { + count.update((prev) => prev + 1); + arr.update((prev) => prev.push(1)); + obj.update((prev) => prev.a++); + }); + const comp = computed(() => arr.value[0]); + const promise = createPromise(async () => { + return await fetch("fakeapi"); + }); + const ref = createRef(); + + cleanUp(() => { + console.log("cleanup"); + }); + return ( +
+ IntellisenseTest + + "hello" + err.message} + /> + hello
} /> + } /> + } /> + {() => { + promise.value.status === "resolved" + ? promise.value.data + : promise.value.error; + }} +
count.value.toString()} + data-test="test" + >
+ <>Fragment + + ); +}; + +const Test = () => { + return
test
; +}; +export default IntellisenseTest; diff --git a/src/components/Test.tsx b/src/components/Test.tsx index 136dfaa..736ad7a 100644 --- a/src/components/Test.tsx +++ b/src/components/Test.tsx @@ -23,7 +23,7 @@ const Test = () => { setTimeout(() => { showTextSignal.update((prev) => !prev); }, 2000); - const h1ref = createRef(); + const h1ref = createRef(); // console.log("hello"); return (
diff --git a/src/index.ts b/src/index.ts index b60eaaa..814c818 100644 --- a/src/index.ts +++ b/src/index.ts @@ -21,10 +21,12 @@ import type { } from "./signals/signal"; export * from "./jsx"; -import { JSXInternal } from "./jsx"; +import { JSXInternal, FRAGMENT as Fragment } from "./jsx"; declare global { // @ts-expect-error export import JSX = JSXInternal; + // @ts-expect-error + const FRAGMENT = "FRAGMENT"; } export * from "./types"; export { diff --git a/src/jsx.ts b/src/jsx.ts index f6267c7..a2a58c9 100644 --- a/src/jsx.ts +++ b/src/jsx.ts @@ -130,7 +130,7 @@ export namespace JSXInternal { : never; }[keyof IntrinsicElements] | ComponentType

; - export type Element = Fiber; + export type Element = ComponentChild; export type ElementClass = ComponentType; export interface ElementAttributesProperty { @@ -158,15 +158,7 @@ export namespace JSXInternal { cssText?: string | null; } - export interface SignalLike { - value: T; - peek(): T; - subscribe(fn: (value: T) => void): () => void; - } - - export type Signalish = T | SignalLike; - - export type UnpackSignal = T extends SignalLike ? V : T; + export type Signalish = T | (() => T); export interface SVGAttributes extends HTMLAttributes { diff --git a/src/lazy/Lazyloading.tsx b/src/lazy/Lazyloading.tsx index e4afb2a..1ef1854 100644 --- a/src/lazy/Lazyloading.tsx +++ b/src/lazy/Lazyloading.tsx @@ -1,4 +1,4 @@ -import { createSignal, PublicSignal } from "../index"; +import { ComponentChild, createSignal, PublicSignal } from "../index"; declare const FRAGMENT = "FRAGMENT"; @@ -11,8 +11,8 @@ export function lazy any>( importFn: () => Promise<{ default: T }> ): ( props: PropsOf & { - fallback?: string | Node; - errorFallback?: string | Node | ((error: Error) => Node); + fallback?: ComponentChild; + errorFallback?: ComponentChild | ((error: Error) => ComponentChild); } ) => ReturnType { let Component: T | null = null; @@ -62,27 +62,6 @@ export function lazy any>( const error = createSignal(null); load(loading, error); - // Validate fallback and errorFallback types - const isValidNode = (val: any) => - typeof val === "string" || - (val && typeof val === "object" && "props" in val && "type" in val); - - if (props.fallback !== undefined && !isValidNode(props.fallback)) { - throw new Error( - "Invalid fallback: Expected a string or a valid JSX node." - ); - } - if ( - props.errorFallback !== undefined && - !( - typeof props.errorFallback === "function" || - isValidNode(props.errorFallback) - ) - ) { - throw new Error( - "Invalid errorFallback: Expected a string, a valid JSX node, or a function returning a JSX node." - ); - } return ( <> @@ -95,7 +74,8 @@ export function lazy any>( ? props.errorFallback(error.value) : props.errorFallback : "Unknown error occurred while lazy loading component, use errorFallback prop to override" - : Component && + : // @ts-expect-error + Component && } ) as unknown as ReturnType; diff --git a/src/rendering/createElements.ts b/src/rendering/createElements.ts index 7798d19..28e8426 100644 --- a/src/rendering/createElements.ts +++ b/src/rendering/createElements.ts @@ -1,6 +1,4 @@ -import { isValidStyle, preprocessStyle, styleObjectToString } from "../lib"; -import { setReactiveAttributes } from "../signals/batch"; -import { reactive, reactiveAttribute, Ref } from "../signals/signal"; +import { reactive, Ref } from "../signals/signal"; import { Fiber, FiberChildren, diff --git a/src/rendering/functionalComponents.ts b/src/rendering/functionalComponents.ts index 46661cd..6af0721 100644 --- a/src/rendering/functionalComponents.ts +++ b/src/rendering/functionalComponents.ts @@ -22,6 +22,14 @@ export function getCurrentFC() { return currentFC; } +function getNewFC(): any { + return { + signals: new Set(), + cleanup: [], + effects: new Set(), + }; +} + export function runAllEffects(FC: Fiber) { if (fcMap.has(FC)) { const fcData = fcMap.get(FC)!; @@ -36,15 +44,11 @@ export function cleanUp(fn: Function) { if (currentFC) { // console.log(currentFC, fcMap.has(currentFC)); if (fcMap.has(currentFC)) { - const fcData = fcMap.get(currentFC)!; - - fcData.cleanup.push(fn); + fcMap.get(currentFC)!.cleanup.push(fn); } else { - fcMap.set(currentFC, { - signals: new Set(), - cleanup: [fn], - effects: new Set(), - }); + let newFC = getNewFC(); + newFC.cleanup.push(fn); + fcMap.set(currentFC, newFC); } } } @@ -52,15 +56,11 @@ export function cleanUpWFiber(fn: Function, fiber: Fiber) { if (fiber) { // console.log(currentFC, fcMap.has(currentFC)); if (fcMap.has(fiber)) { - const fcData = fcMap.get(fiber)!; - - fcData.cleanup.push(fn); + fcMap.get(fiber)!.cleanup.push(fn); } else { - fcMap.set(fiber, { - signals: new Set(), - cleanup: [fn], - effects: new Set(), - }); + let newFC = getNewFC(); + newFC.cleanup.push(fn); + fcMap.set(fiber, newFC); } } } @@ -68,32 +68,22 @@ export function cleanUpWFiber(fn: Function, fiber: Fiber) { export function addEffect(fn: Function) { if (currentFC) { if (fcMap.has(currentFC)) { - const fcData = fcMap.get(currentFC)!; - fcData.effects.add(fn); + fcMap.get(currentFC)!.effects.add(fn); } else { - const effects = new Set(); - effects.add(fn); - fcMap.set(currentFC, { - signals: new Set(), - cleanup: [], - effects: effects, - }); + let newFC = getNewFC(); + newFC.effects.add(fn); + fcMap.set(currentFC, newFC); } } } export function addSignal(signal: BaseSignal) { if (currentFC) { if (fcMap.has(currentFC)) { - const fcData = fcMap.get(currentFC)!; - fcData.signals.add(signal); + fcMap.get(currentFC)!.signals.add(signal); } else { - const signals = new Set>(); - signals.add(signal); - fcMap.set(currentFC, { - signals: signals, - cleanup: [], - effects: new Set(), - }); + let newFC = getNewFC(); + newFC.signals.add(signal); + fcMap.set(currentFC, newFC); } } } @@ -112,7 +102,7 @@ export function cleanUpFC(currentFC, props) { for (const effect of fcData.effects) { // @ts-expect-error - if (effect.__cleanup && typeof effect.__cleanup === "function") { + if (effect.__cleanup) { // @ts-expect-error effect.__cleanup(); } diff --git a/src/rendering/render.ts b/src/rendering/render.ts index 4f5d725..c8af2ae 100644 --- a/src/rendering/render.ts +++ b/src/rendering/render.ts @@ -3,8 +3,8 @@ import { clearReactiveFunction, setReactiveFunction, } from "../signals/batch"; -import { BaseSignal, Ref } from "../signals/signal"; -import { Fiber, FiberChildren } from "../types"; +import { Ref } from "../signals/signal"; +import { Fiber } from "../types"; import { isPrimitive } from "../utils/general"; import { CAPTURE_REGEX } from "./constants"; import { @@ -19,6 +19,13 @@ import { runAllEffects, setCurrentFC, } from "./functionalComponents"; +import { + deepCompareFibers, + deepEqual, + findFirstDom, + findNearestParentWithDom, + findParentFiberWithDom, +} from "./utils"; export function render(element: Fiber, container: HTMLElement) { rootContainer = container; @@ -102,7 +109,6 @@ function renderNode(fiber: Fiber) { if (noKey) { console.error("Array children must have a key attribute"); } - // console.log(fiber.props.children); } else if (typeof fiber.type === "function") { setCurrentFC(fiber); @@ -111,7 +117,6 @@ function renderNode(fiber: Fiber) { if (Array.isArray(children)) { // which means that the FC returned a fragment - // console.log(children); for (let i = children.length - 1; i >= 0; i--) { children[i].parent = fiber; elements.push(children[i]); @@ -126,10 +131,7 @@ function renderNode(fiber: Fiber) { effectQueue.push(fiber); } else { if (!fiber.dom) fiber.dom = createNode(fiber); - let fiberParent: Fiber | undefined = fiber.parent; - while (fiberParent && !fiberParent.dom) { - fiberParent = fiberParent.parent; - } + let fiberParent = findParentFiberWithDom(fiber); if (fiberParent) { fiberParent.dom?.appendChild(fiber.dom); } @@ -234,11 +236,7 @@ function commitFiber( if (customParent) { parentDom = customParent; } else { - let fiberParent: Fiber | undefined = fiber.parent; - - while (fiberParent && !fiberParent.dom) { - fiberParent = fiberParent.parent; - } + let fiberParent = findParentFiberWithDom(fiber); parentDom = fiberParent?.dom; } parentDom?.appendChild(fiber.dom); @@ -338,8 +336,6 @@ export function updateFiber(prevFiber: Fiber, newValue) { function replaceRenderFunction(prev: Fiber, next: Fiber) { if (prev.renderFunction) { next.renderFunction = prev.renderFunction; - // console.log("Replace render function", prev, next); - // deleteReactiveFunction(prev.renderFunction); setRenderFunction(next); } } @@ -349,11 +345,17 @@ function replaceChildFromParent(prev: Fiber, next: Fiber, index?: number) { prev.parent.props.children[index] = next; return; } - prev.parent?.props.children.forEach((child, i) => { - if (child === prev) { + for (let i = 0; i < prev.parent.props.children.length; i++) { + if (prev.parent.props.children[i] === prev) { prev.parent.props.children[i] = next; } - }); + } +} + +function replaceDeleteFiber(prev: Fiber, next: Fiber, index?: number) { + replaceRenderFunction(prev, next); + commitDeletion(prev); + replaceChildFromParent(prev, next, index); } export const isEvent = (key: string) => @@ -363,116 +365,6 @@ export const isProperty = (key: string) => const isNew = (prev: any, next: any, key: string) => prev[key] !== next[key]; const isGone = (prev: any, next: any, key: string) => !(key in next); -function deepCompareFibers(fiberA: any, fiberB: any): boolean { - // Fast path: identical references - if (fiberA === fiberB) { - return true; - } - - // Compare the fiber types (e.g., function for FCs, string for DOM nodes) - if (fiberA.type !== fiberB.type) { - return false; - } - - // Compare keys if they exist - if (fiberA.props?.key !== fiberB.props?.key) { - return false; - } - return deepEqual(fiberA.props, fiberB.props); -} - -function deepEqual(objA: any, objB: any): boolean { - if (objA === objB) { - // console.log("Signal prop"); - - if (objA instanceof BaseSignal && objB instanceof BaseSignal) - return deepEqual(objA.value, objB.value); - if (Array.isArray(objA) && Array.isArray(objB)) { - if (objA.length !== objB.length) return false; - for (let i = 0; i < objA.length; i++) { - if (!deepEqual(objA[i], objB[i])) return false; - } - } - return true; - } // Same reference or primitive value - - if (isPrimitive(objA) && isPrimitive(objB)) { - return objA === objB; // One is not an object or is null - } - - if (typeof objA !== typeof objB) return false; - - const keysA = Object.keys(objA); - const keysB = Object.keys(objB); - - if (keysA.length !== keysB.length) return false; // Different number of keys - - for (let key of keysA) { - if (key === "children") continue; - if (!objB.hasOwnProperty(key)) return false; // Missing key in one of them - if (!deepEqual(objA[key], objB[key])) return false; // Recurse for nested objects/arrays - } - - return true; -} - -function findFirstDom(fiber: Fiber): HTMLElement | Text | undefined { - if (!fiber) return; - - if (fiber.dom) return fiber.dom; - - for (const child of fiber.props.children) { - const dom = findFirstDom(child); - if (dom) return dom; - } -} -// function findFirstChildDom(fiber: Fiber): HTMLElement | Text | undefined { -// if (!fiber) return; - -// for (const child of fiber.props.children) { -// const dom = findFirstDom(child); -// if (dom) return dom; -// } -// } -function findLastDom(fiber: Fiber): HTMLElement | Text | undefined { - if (!fiber) return; - - if (fiber.dom) return fiber.dom; - - for (let i = fiber.props.children.length - 1; i >= 0; i--) { - const child = fiber.props.children[i]; - const dom = findLastDom(child); - if (dom) return dom; - } -} -function findLastChildDom(fiber: Fiber): HTMLElement | Text | undefined { - if (!fiber) return; - - for (let i = fiber.props.children.length - 1; i >= 0; i--) { - const child = fiber.props.children[i]; - const dom = findLastDom(child); - if (dom) return dom; - } -} -function findParentFiberWithDom(fiber: Fiber): Fiber | undefined { - if (!fiber) return; - let fiberParent = fiber.parent; - while (fiberParent && !fiberParent.dom) { - fiberParent = fiberParent.parent; - } - return fiberParent; -} -function findNearestParentWithDom(fiber: Fiber): Fiber | undefined { - if (!fiber) return; - if (fiber.dom) return fiber; - - let fiberParent = fiber.parent; - while (fiberParent && !fiberParent.dom) { - fiberParent = fiberParent.parent; - } - return fiberParent; -} - function updateNode( prev: Fiber | undefined, next: Fiber | undefined, @@ -482,7 +374,6 @@ function updateNode( if (prev && !next) { commitDeletion(prev, true); - // console.log("to remove", prev); prev.parent.props.children = prev.parent.props.children.filter( (child) => child !== prev ); @@ -492,7 +383,6 @@ function updateNode( if (prev.type === "FRAGMENT" || typeof prev.type === "function") { // PREV IS FRAGMENT if (next.type === "FRAGMENT" || typeof next.type === "function") { - // console.log("Fragment-Fragment", prev, next); if ( typeof prev.type === typeof next.type && typeof prev.type === "function" @@ -501,27 +391,16 @@ function updateNode( if (!areSame) { commitFiber(next, findFirstDom(prev), undefined, true); - replaceRenderFunction(prev, next); - commitDeletion(prev); - replaceChildFromParent(prev, next, index); + replaceDeleteFiber(prev, next, index); } } else { - // console.log("fragment-fragment", { ...prev }, next); - updateChildren(prev, next); } - // replaceChildFromParent(prev, next); } else { next.parent = prev.parent; - let firstChild: Fiber | undefined = prev.props.children[0]; - while (firstChild && !firstChild.dom) - firstChild = firstChild.props.children[0]; - commitFiber(next, firstChild?.dom); - - replaceRenderFunction(prev, next); - // removing all nodes of previous fragment - commitDeletion(prev); - replaceChildFromParent(prev, next, index); + let firstDom = findFirstDom(prev.props.children[0]); + commitFiber(next, firstDom); + replaceDeleteFiber(prev, next, index); } } else { // PREV IS NODE @@ -541,13 +420,10 @@ function updateNode( if (next.type === "FRAGMENT" || typeof next.type === "function") { // console.log("Node-Fragment"); next.parent = prev.parent; - replaceRenderFunction(prev, next); commitFiber(next, node); - commitDeletion(prev); - replaceChildFromParent(prev, next, index); + replaceDeleteFiber(prev, next, index); } else { - // console.log("Node-Node"); // remove old properties and event listeners from NODE for (const prop in prevProps) { if ( @@ -581,28 +457,15 @@ function updateNode( // console.log("Different type", prev, next); next.parent = prev.parent; - replaceRenderFunction(prev, next); - commitFiber(next, node, true); - commitDeletion(prev); - replaceChildFromParent(prev, next, index); - - // console.log(prev.parent); + replaceDeleteFiber(prev, next, index); } else { - // add new properties - // console.log("same type", prev, next); - for (const prop in nextProps) { if ( isProperty(prop) && isNew(prevProps, nextProps, prop) ) { node[prop] = nextProps[prop]; - // console.log( - // "property added", - // prop, - // nextProps[prop] - // ); prevProps[prop] = nextProps[prop]; } else if ( isEvent(prop) && @@ -638,23 +501,15 @@ function reconcileList(prev: Fiber, next: Fiber) { const oldMap: Record = {}; for (let i = 0; i < oldFibers.length; i++) { const key = oldFibers[i].props.key; - if ( - key === null || - key === undefined || - oldMap.hasOwnProperty(String(key)) - ) { + if (key === null || key === undefined || String(key) in oldMap) { // If any fiber is missing a key, we cannot reconcile. - // oldFibers[i].props.key = return false; } oldMap[String(key)] = oldFibers[i]; } - const referenceNode = findLastChildDom(prev)?.nextSibling as - | Node - | undefined; + // Create newChildren array based on newFibers order. const fiberParent = findParentFiberWithDom(prev); - // const fragment = document.createDocumentFragment(); if (newFibers.length === 0) { prev.props.children.length = 0; @@ -662,6 +517,7 @@ function reconcileList(prev: Fiber, next: Fiber) { fiberParent.dom.innerHTML = ""; return; } + const fragment = document.createDocumentFragment(); const prevLen = prev.props.children.length; // const newChildren = new Array(newFibers.length); @@ -670,7 +526,7 @@ function reconcileList(prev: Fiber, next: Fiber) { const key = newFiber.props.key; const keyStr = String(key); // If the fiber exists in the old list, reuse it. - if (oldMap.hasOwnProperty(keyStr)) { + if (keyStr in oldMap) { const oldFiber = oldMap[keyStr]; if (prevLen > i) prev.props.children[i] = oldFiber; @@ -683,11 +539,7 @@ function reconcileList(prev: Fiber, next: Fiber) { if (newFiber) newFiber.parent = prev; updateNode(oldFiber, newFiber, i); - applyFiber( - prev.props.children[i], - fiberParent?.dom!, - referenceNode - ); + applyFiber(prev.props.children[i], fragment); } else { // Otherwise, use the new fiber. // console.log(first) @@ -695,26 +547,18 @@ function reconcileList(prev: Fiber, next: Fiber) { else prev.props.children.push(newFiber); newFiber.parent = prev; - commitFiber( - newFiber, - referenceNode, - false, - false, - fiberParent?.dom - ); + commitFiber(newFiber, undefined, false, false, fragment); } } for (const key in oldMap) { - if (oldMap.hasOwnProperty(key)) { - const fiber = oldMap[key]; - commitDeletion(fiber, true); - } + const fiber = oldMap[key]; + commitDeletion(fiber, true); } while (prev.props.children.length > next.props.children.length) { prev.props.children.pop(); } - // fiberParent?.dom?.appendChild(fragment); + fiberParent?.dom?.appendChild(fragment); } function applyFiber(fiber: Fiber, parent: Node, referenceNode?: Node) { @@ -765,11 +609,7 @@ function updateNonListChildren(prev: Fiber, next: Fiber) { if (nextChild) nextChild.parent = prev; if (!prevChild && nextChild) { - commitFiber( - nextChild, - // @ts-expect-error - findLastDom(prev.props.children.at(-1))?.nextSibling - ); + commitFiber(nextChild); prev.props.children.push(nextChild); } else if (!nextChild && prevChild) { commitDeletion(prevChild, true); @@ -800,7 +640,7 @@ function updateNonListChildrenWithKeys(prev: Fiber, next: Fiber) { continue; } count++; - if (oldMap.hasOwnProperty(String(key))) { + if (String(key) in oldMap) { console.warn("Found two children with the same key", key); console.warn( "When two fibers are found having same key the whole children will default to manual updates, which can be slower than with key based reconciliation" @@ -826,7 +666,7 @@ function updateNonListChildrenWithKeys(prev: Fiber, next: Fiber) { } const oldFiber = oldMap[String(key)]; if (oldFiber) { - if (newMap.hasOwnProperty(String(key))) { + if (String(key) in newMap) { console.warn("Found two children with the same key", key); console.warn( "When two fibers are found having same key the whole children will default to manual updates, which can be slower than with key based reconciliation" @@ -850,7 +690,7 @@ function updateNonListChildrenWithKeys(prev: Fiber, next: Fiber) { // console.log(prevChild, nextChild); const nextKey = nextChild?.props.key ? String(nextChild.props.key) : ""; - const isReused = newMap.hasOwnProperty(nextKey); + const isReused = nextKey in newMap; let prevKey = prevChild?.props.key ? String(prevChild.props.key) : ""; @@ -862,12 +702,9 @@ function updateNonListChildrenWithKeys(prev: Fiber, next: Fiber) { continue; } - const isUsedLater = - newMap.hasOwnProperty(prevKey) && newMap[prevKey].newIndex > i; - const isUsedPreviously = - newMap.hasOwnProperty(prevKey) && newMap[prevKey].newIndex < i; + const isUsedAgain = prevKey in newMap && newMap[prevKey].newIndex !== i; - if (isUsedLater || isUsedPreviously) { + if (isUsedAgain) { ToCommitDeletion = false; } @@ -908,7 +745,7 @@ function updateNonListChildrenWithKeys(prev: Fiber, next: Fiber) { if (parent?.dom) applyFiber(prev.props.children[i], parent.dom); } else { // console.log(ToCommitDeletion); - if (isUsedLater || isUsedPreviously) { + if (isUsedAgain) { if (parent?.dom) commitFiber( nextChild, @@ -936,7 +773,6 @@ function updateNonListChildrenWithKeys(prev: Fiber, next: Fiber) { } ToCommitDeletion = true; } - // console.log(prev.props.children, next.props.children); } // @ts-expect-error diff --git a/src/rendering/utils.ts b/src/rendering/utils.ts new file mode 100644 index 0000000..96635ac --- /dev/null +++ b/src/rendering/utils.ts @@ -0,0 +1,79 @@ +import { BaseSignal } from "../signals/signal"; +import { Fiber } from "../types"; +import { isPrimitive } from "../utils/general"; + +export function deepCompareFibers(fiberA: any, fiberB: any): boolean { + // Fast path: identical references + if (fiberA === fiberB) { + return true; + } + + // Compare the fiber types (e.g., function for FCs, string for DOM nodes) + if (fiberA.type !== fiberB.type) { + return false; + } + + // Compare keys if they exist + if (fiberA.props?.key !== fiberB.props?.key) { + return false; + } + return deepEqual(fiberA.props, fiberB.props); +} + +export function deepEqual(objA: any, objB: any): boolean { + if (objA === objB) { + if (objA instanceof BaseSignal && objB instanceof BaseSignal) + return deepEqual(objA.value, objB.value); + if (Array.isArray(objA) && Array.isArray(objB)) { + if (objA.length !== objB.length) return false; + for (let i = 0; i < objA.length; i++) { + if (!deepEqual(objA[i], objB[i])) return false; + } + } + return true; + } // Same reference or primitive value + + if (isPrimitive(objA) && isPrimitive(objB)) { + return objA === objB; // One is not an object or is null + } + + if (typeof objA !== typeof objB) return false; + const vis = {}; + for (let key in objA) { + if (key === "children") continue; + if (!(key in objB)) return false; // Missing key in one of them + if (!deepEqual(objA[key], objB[key])) return false; // Recurse for nested objects/arrays + vis[key] = true; + } + + for (let key in objB) { + if (key === "children") continue; + if (!(key in objA)) return false; // Missing key in one of them + } + + return true; +} + +export function findFirstDom(fiber: Fiber): HTMLElement | Text | undefined { + if (!fiber) return; + + if (fiber.dom) return fiber.dom; + + for (const child of fiber.props.children) { + const dom = findFirstDom(child); + if (dom) return dom; + } +} +export function findParentFiberWithDom(fiber: Fiber): Fiber | undefined { + if (!fiber) return; + let fiberParent = fiber.parent; + while (fiberParent && !fiberParent.dom) { + fiberParent = fiberParent.parent; + } + return fiberParent; +} +export function findNearestParentWithDom(fiber: Fiber): Fiber | undefined { + if (!fiber) return; + if (fiber.dom) return fiber; + return findParentFiberWithDom(fiber); +} diff --git a/src/signals/signal.ts b/src/signals/signal.ts index c8b3333..89832d9 100644 --- a/src/signals/signal.ts +++ b/src/signals/signal.ts @@ -8,10 +8,32 @@ import { import { Fiber } from "../types"; import { isPlainObject, isPrimitive } from "../utils/general"; import { batchUpdate } from "./batch"; +import { + createArrayProxy, + publicSignal, + throwInvalidSignalType, + throwNonPrimitiveError, + throwNotArray, + throwNotObject, + throwNotUpdateCalled, +} from "./utils"; let currentReactiveFunction: any = null; let currentEffect: any = null; +function setCurrentEffect(effect: any) { + currentEffect = effect; +} +function clearCurrentEffect() { + currentEffect = null; +} +function setCurrentReactiveFunction(effect: any) { + currentReactiveFunction = effect; +} +function clearCurrentReactiveFunction() { + currentReactiveFunction = null; +} + function addSignalToReactiveFunction(signal: any) { if (!currentReactiveFunction.__signals) { currentReactiveFunction.__signals = new Set(); @@ -27,9 +49,9 @@ export function reactive(fn: Function) { if (typeof fn !== "function") throw new Error("reactive takes a render function as the argument"); - currentReactiveFunction = fn; + setCurrentReactiveFunction(fn); const retVal = fn(); - currentReactiveFunction = null; + clearCurrentReactiveFunction(); if ( !isPrimitive(retVal) && isPlainObject(retVal) && @@ -47,9 +69,10 @@ export function reactiveAttribute(fn: Function) { if (typeof fn !== "function") throw new Error("reactive takes a render function as the argument"); - currentReactiveFunction = fn; + setCurrentReactiveFunction(fn); + const retVal = fn(); - currentReactiveFunction = null; + clearCurrentReactiveFunction(); return retVal; } @@ -64,7 +87,7 @@ export function createEffect(fn: Function) { export function runEffect(effect: Function, fiber?: Fiber) { if (typeof effect !== "function") return; - currentEffect = effect; + setCurrentEffect(effect); const effectCleanup = effect(); @@ -85,7 +108,7 @@ export function runEffect(effect: Function, fiber?: Fiber) { } } - currentEffect = null; + clearCurrentEffect(); } function computed>( @@ -95,13 +118,13 @@ function computed>( throw new Error("computed takes a function as the argument"); let firstRun = getCurrentFC() !== null; - currentEffect = () => { + setCurrentEffect(() => { if (firstRun) { firstRun = false; return; } signal.update(fn()); - }; + }); addEffect(currentEffect); @@ -110,7 +133,7 @@ function computed>( // @ts-expect-error - Type assertion for signal const signal = createSignal(val); - currentEffect = null; + clearCurrentEffect(); return { get value() { return signal.value; @@ -172,39 +195,6 @@ export function createRef() { return ref; } -// const NonMutatingArrayMethods = [ -// "constructor", -// "concat", -// "every", -// "filter", -// "find", -// "findIndex", -// "flat", -// "flatMap", -// "forEach", -// "includes", -// "indexOf", -// "join", -// "map", -// "reduce", -// "reduceRight", -// "slice", -// "some", -// "toLocaleString", -// "toString", -// ]; -const MutatingMethods = [ - "push", - "pop", - "unshift", - "shift", - "splice", - "fill", - "copyWithin", - "sort", - "reverse", -]; - type DeepReadonly = { readonly [K in keyof T]: T[K] extends object ? DeepReadonly : T[K]; }; @@ -213,7 +203,7 @@ type DeepReadonly = { * * Base class for signals. */ -export abstract class BaseSignal { +export abstract class BaseSignal { protected _val: T; protected deps: Set; protected isNotified: boolean = false; @@ -245,7 +235,18 @@ export abstract class BaseSignal { this.deps.clear(); } - abstract get value(): T | DeepReadonly; + get value(): DeepReadonly { + if (currentEffect) { + this.deps.add(currentEffect); + addSignalToEffect(this); + } + if (currentReactiveFunction) { + this.deps.add(currentReactiveFunction); + + addSignalToReactiveFunction(this); + } + return this._val; + } abstract update(val: T | ((prev: T) => T)): void; } @@ -256,45 +257,21 @@ type NormalSignal = boolean | string | number | undefined | null | Error; */ export class PrimitiveSignal extends BaseSignal { constructor(val: T) { - if (!isPrimitive(val)) { - throw new Error( - "Invalid type for PrimitiveSignal. Valid types: [boolean, string, number, undefined, null]" - ); - } super(val); } - get value(): T { - if (currentEffect) { - this.deps.add(currentEffect); - addSignalToEffect(this); - } - if (currentReactiveFunction) { - this.deps.add(currentReactiveFunction); - - addSignalToReactiveFunction(this); - } - // (Optional) debug logging: - // console.log(this.deps); - return this._val; - } - public update(val: T | ((prev: T) => T)) { if (typeof val === "function") { const newVal = val(this._val); if (!isPrimitive(newVal)) { - throw new Error( - "Invalid type for PrimitiveSignal. Valid types: [boolean, string, number, undefined, null]" - ); + throwNonPrimitiveError(); } if (newVal === this._val) return; this._val = newVal; this.notify(); } else { if (!isPrimitive(val)) { - throw new Error( - "Invalid type for PrimitiveSignal. Valid types: [boolean, string, number, undefined, null]" - ); + throwNonPrimitiveError(); } if (val === this._val) return; @@ -313,9 +290,7 @@ export class ArraySignal extends BaseSignal { constructor(val: T) { if (!Array.isArray(val)) { - throw new Error( - "Invalid type for ArraySignal; value must be an array" - ); + throwNotArray(); } // Call the base constructor with a proxy-wrapped array. super(val); @@ -323,56 +298,7 @@ export class ArraySignal extends BaseSignal { } private createProxy(val: T): T { - return new Proxy(val, { - get: (target, prop) => { - const value = target[prop as any]; - // If a function is accessed, wrap it to trigger notifications on mutation. - - if (typeof value === "function") { - if ( - MutatingMethods.includes(String(prop)) && - !this.updateCalled - ) { - throw new Error( - "Cannot set a value on an array signal, use the update method for updating the array." - ); - } - - return (...args: any[]) => { - const result = value.apply(target, args); - // Notify if the method is mutating. - if (MutatingMethods.includes(String(prop))) { - this.notify(); - } - return result; - }; - } - return value; - }, - set: (target, prop, newValue) => { - if (!this.updateCalled) { - throw new Error( - "Cannot set a value on an array signal, use the update method for updating the array." - ); - } - target[prop as any] = newValue; - this.notify(); - return true; - }, - }); - } - - get value(): DeepReadonly { - if (currentEffect) { - this.deps.add(currentEffect); - addSignalToEffect(this); - } - if (currentReactiveFunction) { - this.deps.add(currentReactiveFunction); - addSignalToReactiveFunction(this); - } - - return this._val; + return createArrayProxy(val, this) as T; } public update(val: T | ((prev: T) => void)) { @@ -381,9 +307,7 @@ export class ArraySignal extends BaseSignal { val(this._val); } else { if (!Array.isArray(val)) { - throw new Error( - "Invalid type for ArraySignal; value must be an array" - ); + throwNotArray(); } if (val === this._val) return; @@ -402,50 +326,13 @@ export class ObjectSignal> extends BaseSignal { private updateCalled: boolean = false; constructor(val: T) { if (!isPlainObject(val)) { - throw new Error( - "Invalid type for ObjectSignal; value must be a plain object" - ); + throwNotArray(); } super(val); this._val = this.createProxy(val); } private createInternalArrayProxy(val: A): A { - return new Proxy(val, { - get: (target, prop) => { - const value = target[prop as any]; - // If a function is accessed, wrap it to trigger notifications on mutation. - if (typeof value === "function") { - if ( - !this.updateCalled && - MutatingMethods.includes(String(prop)) - ) { - throw new Error( - "Cannot set a value on an object signal, use the update method for updating the object." - ); - } - - return (...args: any[]) => { - const result = value.apply(target, args); - // Notify if the method is mutating. - if (MutatingMethods.includes(String(prop))) { - this.notify(); - } - return result; - }; - } - return value; - }, - set: (target, prop, newValue) => { - if (!this.updateCalled) { - throw new Error( - "Cannot set a value on an object signal, use the update method for updating the object." - ); - } - target[prop as any] = newValue; - this.notify(); - return true; - }, - }); + return createArrayProxy(val, this) as A; } private createProxy(val: T): T { return new Proxy(val, { @@ -463,9 +350,7 @@ export class ObjectSignal> extends BaseSignal { }, set: (target, prop, newValue) => { if (!this.updateCalled) { - throw new Error( - "Cannot set a value on an object signal, use the update method for updating the object." - ); + throwNotUpdateCalled(); } // Do not allow functions to be set as values. if (typeof newValue === "function") return false; @@ -489,28 +374,13 @@ export class ObjectSignal> extends BaseSignal { }, }); } - - get value(): DeepReadonly { - if (currentEffect) { - this.deps.add(currentEffect); - addSignalToEffect(this); - } - if (currentReactiveFunction) { - this.deps.add(currentReactiveFunction); - addSignalToReactiveFunction(this); - } - return this._val; - } - public update(val: T | ((prev: T) => void)) { this.updateCalled = true; if (typeof val === "function") { val(this._val); } else { if (!isPlainObject(val)) { - throw new Error( - "Invalid type for ObjectSignal; value must be a plain object" - ); + throwNotObject(); } if (val === this._val) return; this._val = this.createProxy(val); @@ -545,47 +415,26 @@ function createSignal>( function createSignal>( val: T ) { - if (typeof val === "function") { - throw new Error("Functions cannot be used as signal value"); - } - if (typeof val === "object" && val !== null) { if (Array.isArray(val)) { const signal = new ArraySignal(val); addSignal(signal); - return { - get value() { - return signal.value; - }, - update: signal.update.bind(signal) as typeof signal.update, - }; + return publicSignal(signal); } else if (isPlainObject(val)) { const signal = new ObjectSignal(val); addSignal(signal); - return { - get value() { - return signal.value; - }, - update: signal.update.bind(signal) as typeof signal.update, - }; + return publicSignal(signal); } else { - throw new Error( - "Invalid type for signal initialization: " + typeof val - ); + throwInvalidSignalType(val); } } else if (isPrimitive(val)) { const signal = new PrimitiveSignal(val); + // @ts-expect-error addSignal(signal); - return { - get value() { - return signal.value; - }, - update: signal.update.bind(signal) as typeof signal.update, - }; + // @ts-expect-error + return publicSignal(signal); } else { - throw new Error( - "Invalid type for signal initialization: " + typeof val - ); + throwInvalidSignalType(val); } } diff --git a/src/signals/utils.ts b/src/signals/utils.ts new file mode 100644 index 0000000..11d3317 --- /dev/null +++ b/src/signals/utils.ts @@ -0,0 +1,95 @@ +import { BaseSignal } from "./signal"; + +export const MutatingMethods = [ + "push", + "pop", + "unshift", + "shift", + "splice", + "fill", + "copyWithin", + "sort", + "reverse", +]; + +function isMutating(prop: any) { + return MutatingMethods.includes(String(prop)); +} + +const isProd = + // @ts-expect-error + process.env.NODE_ENV === "production" || + // @ts-expect-error + import.meta.env.MODE === "production"; + +export function throwNonPrimitiveError() { + if (isProd) return; + throw new Error( + "Invalid type for PrimitiveSignal. Valid types: [boolean, string, number, undefined, null]" + ); +} +export function throwNotUpdateCalled() { + if (isProd) return; + throw new Error( + "Cannot set a value on a signal, use the update method instead." + ); +} +export function throwNotArray() { + if (isProd) return; + throw new Error("Invalid type for ArraySignal; value must be an array"); +} +export function throwNotObject() { + if (isProd) return; + throw new Error("Invalid type for ObjectSignal; value must be an object"); +} +export function throwInvalidSignalType(val: any) { + if (isProd) return; + throw new Error("Invalid type for signal initialization: " + typeof val); +} + +export function publicSignal(signal: BaseSignal) { + return { + get value() { + return signal.value; + }, + update: signal.update.bind(signal) as typeof signal.update, + }; +} + +export const createArrayProxy = (arr: any[], signal: any) => { + return new Proxy(arr, { + get: (target, prop) => { + const value = target[prop as any]; + // If a function is accessed, wrap it to trigger notifications on mutation. + + if (typeof value === "function") { + if (isMutating(prop) && !signal.updateCalled) { + throw new Error( + "Cannot set a value on an array signal, use the update method for updating the array." + ); + } + + return (...args: any[]) => { + const result = value.apply(target, args); + // Notify if the method is mutating. + if (isMutating(prop)) { + signal.notify(); + } + return result; + }; + } + return value; + }, + set: (target, prop, newValue) => { + if (!signal.updateCalled) { + throw new Error( + "Cannot set a value on an array signal, use the update method for updating the array." + ); + } + target[prop as any] = newValue; + + signal.notify(); + return true; + }, + }); +}; diff --git a/src/tests/signals/signal.test.ts b/src/tests/signals/signal.test.ts index 6abbc1e..3880c8d 100644 --- a/src/tests/signals/signal.test.ts +++ b/src/tests/signals/signal.test.ts @@ -25,7 +25,7 @@ describe("Signal", () => { it("should not create a signal with function", () => { expect(() => { createSignal(() => 0); - }).toThrow("Functions cannot be used as signal value"); + }).toThrow(); }); it("should should create Normal Signal for primitive and null values", () => { const values = [0, "", false, null, undefined]; @@ -55,9 +55,7 @@ describe("Signal", () => { objectSignal.update(2); objectSignal.update([1, 2]); }; - expect(assignWrongValue).toThrow( - "Invalid type for ObjectSignal; value must be a plain object" - ); + expect(assignWrongValue).toThrow(); }); it("should throw when creating effect without function", () => { const wrongEffect = () => createEffect(1); diff --git a/src/utils/general.ts b/src/utils/general.ts index f1ddd68..506659f 100644 --- a/src/utils/general.ts +++ b/src/utils/general.ts @@ -13,9 +13,3 @@ export function isPrimitive(val: any) { val instanceof Error ); } - -export function swap(arr: any[], i: number, j: number) { - const temp = arr[i]; - arr[i] = arr[j]; - arr[j] = temp; -} diff --git a/tsconfig.json b/tsconfig.json index 21412ec..03b631a 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -9,7 +9,11 @@ "jsxFactory": "createElement", // Match your jsxFactory in esbuild "jsxFragmentFactory": "FRAGMENT", "moduleResolution": "bundler", - "strictNullChecks": true + "strictNullChecks": true, + "declaration": true, + "declarationMap": false, + "emitDeclarationOnly": true, + "removeComments": true }, "exclude": ["node_modules", "dist"] // Exclude generated and third-party files } diff --git a/vite.config.ts b/vite.config.ts index eb2bc1c..0528535 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -7,19 +7,21 @@ const isProd = process.env.NODE_ENV === "production"; export default defineConfig({ build: { outDir: isProd ? "build" : "dist", - minify: true, - sourcemap: !isProd, + minify: "esbuild", + sourcemap: false, lib: { entry: "src/index.ts", name: "Refract", fileName: (format) => `refract.${format}.js`, - formats: ["es", "cjs", "umd"], // Supports multiple module formats + formats: ["es", "cjs"], // Supports multiple module formats }, rollupOptions: { output: { preserveModules: false, }, + treeshake: true, }, + target: "esnext", }, esbuild: { jsxFactory: "createElement", // Your custom JSX factory function