rask-ui 0.2.6 → 0.2.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"AbstractVNode.d.ts","sourceRoot":"","sources":["../../src/vdom/AbstractVNode.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAEhC,MAAM,MAAM,cAAc,GACtB;IACE,IAAI,EAAE,KAAK,CAAC;IACZ,GAAG,EAAE,IAAI,GAAG,IAAI,EAAE,CAAC;CACpB,GACD;IACE,IAAI,EAAE,SAAS,CAAC;IAChB,MAAM,EAAE,IAAI,GAAG,IAAI,EAAE,CAAC;IACtB,MAAM,EAAE,IAAI,GAAG,IAAI,EAAE,CAAC;CACvB,GACD;IACE,IAAI,EAAE,QAAQ,CAAC;IACf,GAAG,EAAE,IAAI,GAAG,IAAI,EAAE,CAAC;CACpB,CAAC;AAEN,8BAAsB,aAAa;IACjC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,KAAK,CAAC;IACf,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,GAAG,CAAC,EAAE,IAAI,CAAC;IACX,QAAQ,CAAC,EAAE,KAAK,EAAE,CAAC;IACnB,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,KAAK,GAAG,IAAI,GAAG,IAAI,EAAE;IAC7C,QAAQ,CAAC,KAAK,CAAC,OAAO,EAAE,KAAK,GAAG,IAAI;IACpC,QAAQ,CAAC,OAAO,IAAI,IAAI;IACxB,QAAQ,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,cAAc,EAAE,GAAG,IAAI;IACtD,SAAS,CAAC,cAAc;IAOxB;;OAEG;IACH,WAAW,IAAI,IAAI,EAAE;IAWrB,gBAAgB,IAAI,WAAW;IAiB/B,SAAS,CAAC,QAAQ,CAAC,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,GAAG,OAAO;IAoB3D,aAAa,CAAC,WAAW,EAAE,KAAK,EAAE,GAAG;QACnC,QAAQ,EAAE,KAAK,EAAE,CAAC;QAClB,mBAAmB,EAAE,OAAO,CAAC;QAC7B,UAAU,EAAE,cAAc,EAAE,CAAC;KAC9B;IAkJD,oBAAoB,CAAC,MAAM,EAAE,WAAW,EAAE,UAAU,EAAE,cAAc,EAAE;IAqCtE;;;;OAIG;IACH,SAAS,CAAC,eAAe;CA6B1B"}
1
+ {"version":3,"file":"AbstractVNode.d.ts","sourceRoot":"","sources":["../../src/vdom/AbstractVNode.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAEhC,MAAM,MAAM,cAAc,GACtB;IACE,IAAI,EAAE,KAAK,CAAC;IACZ,GAAG,EAAE,IAAI,GAAG,IAAI,EAAE,CAAC;CACpB,GACD;IACE,IAAI,EAAE,SAAS,CAAC;IAChB,MAAM,EAAE,IAAI,GAAG,IAAI,EAAE,CAAC;IACtB,MAAM,EAAE,IAAI,GAAG,IAAI,EAAE,CAAC;CACvB,GACD;IACE,IAAI,EAAE,QAAQ,CAAC;IACf,GAAG,EAAE,IAAI,GAAG,IAAI,EAAE,CAAC;CACpB,CAAC;AAEN,8BAAsB,aAAa;IACjC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,KAAK,CAAC;IACf,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,GAAG,CAAC,EAAE,IAAI,CAAC;IACX,QAAQ,CAAC,EAAE,KAAK,EAAE,CAAC;IACnB,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,KAAK,GAAG,IAAI,GAAG,IAAI,EAAE;IAC7C,QAAQ,CAAC,KAAK,CAAC,OAAO,EAAE,KAAK,GAAG,IAAI;IACpC,QAAQ,CAAC,OAAO,IAAI,IAAI;IACxB,QAAQ,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,cAAc,EAAE,GAAG,IAAI;IACtD,SAAS,CAAC,cAAc;IAOxB;;OAEG;IACH,WAAW,IAAI,IAAI,EAAE;IAmBrB,gBAAgB,IAAI,WAAW;IAiB/B,SAAS,CAAC,QAAQ,CAAC,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,GAAG,OAAO;IAoB3D,aAAa,CAAC,WAAW,EAAE,KAAK,EAAE,GAAG;QACnC,QAAQ,EAAE,KAAK,EAAE,CAAC;QAClB,mBAAmB,EAAE,OAAO,CAAC;QAC7B,UAAU,EAAE,cAAc,EAAE,CAAC;KAC9B;IAkJD,oBAAoB,CAAC,MAAM,EAAE,WAAW,EAAE,UAAU,EAAE,cAAc,EAAE;IAqCtE;;;;OAIG;IACH,SAAS,CAAC,eAAe;CA6B1B"}
@@ -21,7 +21,15 @@ export class AbstractVNode {
21
21
  if (!this.children) {
22
22
  throw new Error("This VNode has no element or children");
23
23
  }
24
- return this.children.map((child) => child.getElements()).flat();
24
+ // Optimized: avoid intermediate arrays from map+flat
25
+ const result = [];
26
+ for (let i = 0; i < this.children.length; i++) {
27
+ const childElms = this.children[i].getElements();
28
+ for (let j = 0; j < childElms.length; j++) {
29
+ result.push(childElms[j]);
30
+ }
31
+ }
32
+ return result;
25
33
  }
26
34
  getParentElement() {
27
35
  let parent = this.parent;
@@ -1 +1 @@
1
- {"version":3,"file":"ComponentVNode.d.ts","sourceRoot":"","sources":["../../src/vdom/ComponentVNode.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsB,QAAQ,EAAU,MAAM,gBAAgB,CAAC;AACtE,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAGhE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAGvC,MAAM,MAAM,cAAc,GACtB,KAAK,GACL,MAAM,GACN,IAAI,GACJ,MAAM,GACN,SAAS,GACT,OAAO,CAAC;AACZ,MAAM,MAAM,iBAAiB,GAAG,cAAc,GAAG,cAAc,EAAE,CAAC;AAElE;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,MAAM,SAAS,CAAC,CAAC,SAAS,KAAK,IACjC,CAAC,CAAC,KAAK,EAAE,CAAC,KAAK,MAAM,iBAAiB,CAAC,GACvC,CAAC,MAAM,MAAM,iBAAiB,CAAC,CAAC;AAEpC,MAAM,MAAM,iBAAiB,GAAG;IAC9B,MAAM,CAAC,EAAE,KAAK,CAAC;IACf,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IACtC,QAAQ,EAAE,KAAK,CAAC,MAAM,IAAI,CAAC,CAAC;IAC5B,UAAU,EAAE,KAAK,CAAC,MAAM,IAAI,CAAC,CAAC;IAC9B,QAAQ,EAAE,QAAQ,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,OAAO,CAAC;IACf,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAAC;CACnC,CAAC;AAKF,wBAAgB,mBAAmB,sBAYlC;AAED,wBAAgB,OAAO,CAAC,EAAE,EAAE,MAAM,IAAI,QAYrC;AAED,wBAAgB,SAAS,CAAC,EAAE,EAAE,MAAM,IAAI,QAYvC;AAED,qBAAa,cAAe,SAAQ,aAAa;IAC/C,SAAS,EAAE,SAAS,CAAC,GAAG,CAAC,CAAC;IAC1B,KAAK,EAAE,KAAK,CAAC;IAEb,QAAQ,EAAE,KAAK,EAAE,CAAM;IACvB,QAAQ,CAAC,EAAE,iBAAiB,CAAC;gBAE3B,SAAS,EAAE,SAAS,CAAC,GAAG,CAAC,EACzB,KAAK,EAAE,KAAK,EACZ,QAAQ,EAAE,KAAK,EAAE,EACjB,GAAG,CAAC,EAAE,MAAM;IAWd,QAAQ,CAAC,UAAU,CAAC,EAAE,cAAc,EAAE,GAAG,IAAI;IAG7C,KAAK,CAAC,MAAM,CAAC,EAAE,KAAK,GAAG,IAAI,EAAE;IA0I7B,KAAK,CAAC,OAAO,EAAE,cAAc;IAW7B,OAAO;CAcR"}
1
+ {"version":3,"file":"ComponentVNode.d.ts","sourceRoot":"","sources":["../../src/vdom/ComponentVNode.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsB,QAAQ,EAAU,MAAM,gBAAgB,CAAC;AACtE,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAGhE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAIvC,MAAM,MAAM,cAAc,GACtB,KAAK,GACL,MAAM,GACN,IAAI,GACJ,MAAM,GACN,SAAS,GACT,OAAO,CAAC;AACZ,MAAM,MAAM,iBAAiB,GAAG,cAAc,GAAG,cAAc,EAAE,CAAC;AAElE;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,MAAM,SAAS,CAAC,CAAC,SAAS,KAAK,IACjC,CAAC,CAAC,KAAK,EAAE,CAAC,KAAK,MAAM,iBAAiB,CAAC,GACvC,CAAC,MAAM,MAAM,iBAAiB,CAAC,CAAC;AAEpC,MAAM,MAAM,iBAAiB,GAAG;IAC9B,MAAM,CAAC,EAAE,KAAK,CAAC;IACf,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IACtC,QAAQ,EAAE,KAAK,CAAC,MAAM,IAAI,CAAC,CAAC;IAC5B,UAAU,EAAE,KAAK,CAAC,MAAM,IAAI,CAAC,CAAC;IAC9B,QAAQ,EAAE,QAAQ,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,OAAO,CAAC;IACf,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAAC;CACnC,CAAC;AAKF,wBAAgB,mBAAmB,sBAYlC;AAED,wBAAgB,OAAO,CAAC,EAAE,EAAE,MAAM,IAAI,QAYrC;AAED,wBAAgB,SAAS,CAAC,EAAE,EAAE,MAAM,IAAI,QAYvC;AAED,qBAAa,cAAe,SAAQ,aAAa;IAC/C,SAAS,EAAE,SAAS,CAAC,GAAG,CAAC,CAAC;IAC1B,KAAK,EAAE,KAAK,CAAC;IAEb,QAAQ,EAAE,KAAK,EAAE,CAAM;IACvB,QAAQ,CAAC,EAAE,iBAAiB,CAAC;gBAE3B,SAAS,EAAE,SAAS,CAAC,GAAG,CAAC,EACzB,KAAK,EAAE,KAAK,EACZ,QAAQ,EAAE,KAAK,EAAE,EACjB,GAAG,CAAC,EAAE,MAAM;IAWd,QAAQ,CAAC,UAAU,CAAC,EAAE,cAAc,EAAE,GAAG,IAAI;IAG7C,KAAK,CAAC,MAAM,CAAC,EAAE,KAAK,GAAG,IAAI,EAAE;IA6I7B,KAAK,CAAC,OAAO,EAAE,cAAc;IAW7B,OAAO;CAcR"}
@@ -3,6 +3,7 @@ import { AbstractVNode } from "./AbstractVNode";
3
3
  import { FragmentVNode } from "./FragmentVNode";
4
4
  import { RootVNode } from "./RootVNode";
5
5
  import { normalizeChildren } from "./utils";
6
+ import { flattenNodes } from "./dom-utils";
6
7
  import { currentRoot } from "./RootVNode";
7
8
  export function getCurrentComponent() {
8
9
  if (!currentRoot) {
@@ -158,9 +159,12 @@ export class ComponentVNode extends AbstractVNode {
158
159
  this.children = executeRender();
159
160
  this.root?.popComponent();
160
161
  this.root?.clearCurrent();
161
- const childElements = this.children
162
- .map((child) => child.mount(this))
163
- .flat();
162
+ // Optimized: avoid intermediate arrays from map+flat
163
+ const childResults = [];
164
+ for (let i = 0; i < this.children.length; i++) {
165
+ childResults.push(this.children[i].mount(this));
166
+ }
167
+ const childElements = flattenNodes(childResults);
164
168
  // Queue onMount callbacks after children are mounted
165
169
  // This ensures refs and other child lifecycle hooks run before parent onMount
166
170
  instance.onMounts.forEach((cb) => {
@@ -1,13 +1,15 @@
1
1
  import { AbstractVNode, PatchOperation } from "./AbstractVNode";
2
- import { Props, VNode } from "./types";
2
+ import { Props, VNode, VFlags } from "./types";
3
3
  export declare class ElementVNode extends AbstractVNode {
4
4
  tag: string;
5
5
  props: Props;
6
6
  children: VNode[];
7
7
  key?: string;
8
+ flags: VFlags;
8
9
  private ref?;
9
10
  private eventListeners?;
10
11
  constructor(tag: string, { ref, ...props }: Props, children: VNode[], key?: string);
12
+ private computeFlags;
11
13
  rerender(operations?: PatchOperation[]): void;
12
14
  mount(parent?: VNode): Node;
13
15
  /**
@@ -19,6 +21,7 @@ export declare class ElementVNode extends AbstractVNode {
19
21
  unmount(): void;
20
22
  private setProp;
21
23
  private patchProps;
24
+ private patchStyle;
22
25
  private addEventListener;
23
26
  }
24
27
  //# sourceMappingURL=ElementVNode.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ElementVNode.d.ts","sourceRoot":"","sources":["../../src/vdom/ElementVNode.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAGhE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAUvC,qBAAa,YAAa,SAAQ,aAAa;IAC7C,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,KAAK,CAAC;IACb,QAAQ,EAAE,KAAK,EAAE,CAAC;IAClB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,GAAG,CAAC,CAA0D;IACtE,OAAO,CAAC,cAAc,CAAC,CAA6B;gBAElD,GAAG,EAAE,MAAM,EACX,EAAE,GAAG,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,EACxB,QAAQ,EAAE,KAAK,EAAE,EACjB,GAAG,CAAC,EAAE,MAAM;IASd,QAAQ,CAAC,UAAU,CAAC,EAAE,cAAc,EAAE,GAAG,IAAI;IAO7C,KAAK,CAAC,MAAM,CAAC,EAAE,KAAK,GAAG,IAAI;IAkC3B;;;;OAIG;IACH,KAAK,CAAC,OAAO,EAAE,YAAY;IAc3B,OAAO;IAYP,OAAO,CAAC,OAAO,CAoCb;IACF,OAAO,CAAC,UAAU;IAGlB,OAAO,CAAC,gBAAgB;CAgBzB"}
1
+ {"version":3,"file":"ElementVNode.d.ts","sourceRoot":"","sources":["../../src/vdom/ElementVNode.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAGhE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAU/C,qBAAa,YAAa,SAAQ,aAAa;IAC7C,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,KAAK,CAAC;IACb,QAAQ,EAAE,KAAK,EAAE,CAAC;IAClB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,GAAG,CAAC,CAA0D;IACtE,OAAO,CAAC,cAAc,CAAC,CAA6B;gBAElD,GAAG,EAAE,MAAM,EACX,EAAE,GAAG,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,EACxB,QAAQ,EAAE,KAAK,EAAE,EACjB,GAAG,CAAC,EAAE,MAAM;IAad,OAAO,CAAC,YAAY;IAwBpB,QAAQ,CAAC,UAAU,CAAC,EAAE,cAAc,EAAE,GAAG,IAAI;IAO7C,KAAK,CAAC,MAAM,CAAC,EAAE,KAAK,GAAG,IAAI;IAkC3B;;;;OAIG;IACH,KAAK,CAAC,OAAO,EAAE,YAAY;IAwB3B,OAAO;IAYP,OAAO,CAAC,OAAO,CAoCb;IACF,OAAO,CAAC,UAAU;IAsClB,OAAO,CAAC,UAAU;IAoClB,OAAO,CAAC,gBAAgB;CAgBzB"}
@@ -7,6 +7,7 @@ export class ElementVNode extends AbstractVNode {
7
7
  props;
8
8
  children;
9
9
  key;
10
+ flags;
10
11
  ref;
11
12
  eventListeners;
12
13
  constructor(tag, { ref, ...props }, children, key) {
@@ -16,6 +17,31 @@ export class ElementVNode extends AbstractVNode {
16
17
  this.children = children;
17
18
  this.key = key;
18
19
  this.ref = ref;
20
+ // Pre-compute flags for fast-path checks during patching
21
+ this.flags = this.computeFlags(props);
22
+ }
23
+ computeFlags(props) {
24
+ let flags = 0 /* VFlags.None */;
25
+ const propKeys = Object.keys(props);
26
+ if (propKeys.length > 0) {
27
+ flags |= 1 /* VFlags.HasProps */;
28
+ for (let i = 0; i < propKeys.length; i++) {
29
+ const key = propKeys[i];
30
+ if (key === "class" || key === "className") {
31
+ flags |= 2 /* VFlags.HasClass */;
32
+ }
33
+ else if (key === "style") {
34
+ flags |= 4 /* VFlags.HasStyle */;
35
+ }
36
+ else if (isEventProp(key)) {
37
+ flags |= 8 /* VFlags.HasEvents */;
38
+ }
39
+ else if (key.startsWith("data-") || key.startsWith("aria-")) {
40
+ flags |= 16 /* VFlags.HasDataAttrs */;
41
+ }
42
+ }
43
+ }
44
+ return flags;
19
45
  }
20
46
  rerender(operations) {
21
47
  if (operations) {
@@ -60,7 +86,14 @@ export class ElementVNode extends AbstractVNode {
60
86
  * - Patch the children
61
87
  */
62
88
  patch(newNode) {
63
- this.patchProps(newNode.props);
89
+ // Save old flags before updating
90
+ const oldFlags = this.flags;
91
+ // Only patch props if either old or new node has props
92
+ if ((oldFlags | newNode.flags) & 1 /* VFlags.HasProps */) {
93
+ this.patchProps(newNode.props, oldFlags, newNode.flags);
94
+ }
95
+ // Update flags and props after patching
96
+ this.flags = newNode.flags;
64
97
  this.props = newNode.props;
65
98
  const { children, hasChangedStructure, operations } = this.patchChildren(newNode.children);
66
99
  this.children = children;
@@ -110,8 +143,64 @@ export class ElementVNode extends AbstractVNode {
110
143
  }
111
144
  setElementProp(elm, prop, value);
112
145
  };
113
- patchProps(newProps) {
114
- diffObjectKeys(this.props, newProps, this.setProp);
146
+ patchProps(newProps, oldFlags, newFlags) {
147
+ // Early bailout for reference equality
148
+ if (this.props === newProps) {
149
+ return;
150
+ }
151
+ const oldProps = this.props;
152
+ const elm = this.getHTMLElement();
153
+ // Handle class separately for efficiency (check if either old or new has class)
154
+ if ((oldFlags | newFlags) & 2 /* VFlags.HasClass */) {
155
+ const oldClass = oldProps.class ?? oldProps.className;
156
+ const newClass = newProps.class ?? newProps.className;
157
+ if (oldClass !== newClass) {
158
+ setElementClass(elm, newClass);
159
+ }
160
+ }
161
+ // Handle style separately with per-property diffing (check if either old or new has style)
162
+ if ((oldFlags | newFlags) & 4 /* VFlags.HasStyle */) {
163
+ this.patchStyle(oldProps.style, newProps.style);
164
+ }
165
+ // Handle regular props (excluding class, className, style, children)
166
+ diffObjectKeys(oldProps, newProps, (key, value, oldValue) => {
167
+ // Skip props we've already handled
168
+ if (key === "class" ||
169
+ key === "className" ||
170
+ key === "style" ||
171
+ key === "children") {
172
+ return;
173
+ }
174
+ this.setProp(key, value);
175
+ });
176
+ }
177
+ patchStyle(oldStyle, newStyle) {
178
+ // Early bailout for reference equality
179
+ if (oldStyle === newStyle) {
180
+ return;
181
+ }
182
+ const elm = this.getHTMLElement();
183
+ // If either is a string, fall back to full replacement
184
+ if (typeof oldStyle === "string" || typeof newStyle === "string") {
185
+ setElementStyle(elm, newStyle);
186
+ return;
187
+ }
188
+ // Per-property style diffing for objects
189
+ const os = oldStyle || {};
190
+ const ns = newStyle || {};
191
+ // Remove old styles not in new
192
+ for (const key in os) {
193
+ if (!(key in ns)) {
194
+ elm.style[key] = "";
195
+ }
196
+ }
197
+ // Set new/changed styles
198
+ for (const key in ns) {
199
+ const newVal = ns[key];
200
+ if (newVal !== os[key]) {
201
+ elm.style[key] = newVal;
202
+ }
203
+ }
115
204
  }
116
205
  addEventListener(type, cb) {
117
206
  if (!this.eventListeners) {
@@ -1 +1 @@
1
- {"version":3,"file":"FragmentVNode.d.ts","sourceRoot":"","sources":["../../src/vdom/FragmentVNode.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAKhE,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAEhC,eAAO,MAAM,QAAQ,eAAqB,CAAC;AAE3C,qBAAa,aAAc,SAAQ,aAAa;IAC9C,QAAQ,EAAE,KAAK,EAAE,CAAC;IAClB,GAAG,CAAC,EAAE,MAAM,CAAC;gBAED,QAAQ,EAAE,KAAK,EAAE,EAAE,GAAG,CAAC,EAAE,MAAM;IAK3C,KAAK,CAAC,MAAM,CAAC,EAAE,KAAK,GAAG,IAAI,EAAE;IAW7B,QAAQ,CAAC,UAAU,CAAC,EAAE,cAAc,EAAE,GAAG,IAAI;IAG7C,KAAK,CAAC,OAAO,EAAE,aAAa;IAiB5B,OAAO;CAMR"}
1
+ {"version":3,"file":"FragmentVNode.d.ts","sourceRoot":"","sources":["../../src/vdom/FragmentVNode.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAKhE,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAGhC,eAAO,MAAM,QAAQ,eAAqB,CAAC;AAE3C,qBAAa,aAAc,SAAQ,aAAa;IAC9C,QAAQ,EAAE,KAAK,EAAE,CAAC;IAClB,GAAG,CAAC,EAAE,MAAM,CAAC;gBAED,QAAQ,EAAE,KAAK,EAAE,EAAE,GAAG,CAAC,EAAE,MAAM;IAK3C,KAAK,CAAC,MAAM,CAAC,EAAE,KAAK,GAAG,IAAI,EAAE;IAgB7B,QAAQ,CAAC,UAAU,CAAC,EAAE,cAAc,EAAE,GAAG,IAAI;IAG7C,KAAK,CAAC,OAAO,EAAE,aAAa;IAiB5B,OAAO;CAMR"}
@@ -1,5 +1,6 @@
1
1
  import { AbstractVNode } from "./AbstractVNode";
2
2
  import { RootVNode } from "./RootVNode";
3
+ import { flattenNodes } from "./dom-utils";
3
4
  export const Fragment = Symbol("Fragment");
4
5
  export class FragmentVNode extends AbstractVNode {
5
6
  children;
@@ -17,7 +18,12 @@ export class FragmentVNode extends AbstractVNode {
17
18
  else {
18
19
  this.root = parent?.root;
19
20
  }
20
- return this.children.map((child) => child.mount(this)).flat();
21
+ // Optimized: avoid intermediate arrays from map+flat
22
+ const childResults = [];
23
+ for (let i = 0; i < this.children.length; i++) {
24
+ childResults.push(this.children[i].mount(this));
25
+ }
26
+ return flattenNodes(childResults);
21
27
  }
22
28
  rerender(operations) {
23
29
  this.parent?.rerender(operations);
@@ -1 +1 @@
1
- {"version":3,"file":"RootVNode.d.ts","sourceRoot":"","sources":["../../src/vdom/RootVNode.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAChE,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAChC,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAIrD,eAAO,IAAI,WAAW,EAAE,SAAS,GAAG,SAAS,CAAC;AAE9C,qBAAa,SAAU,SAAQ,aAAa;IAC1C,QAAQ,EAAE,KAAK,EAAE,CAAC;IAClB,cAAc,EAAE,iBAAiB,EAAE,CAAM;IACzC,OAAO,CAAC,cAAc,CAGpB;IACF,OAAO,CAAC,mBAAmB,CAAkB;IAC7C,OAAO,CAAC,gBAAgB,CAAyB;gBAErC,QAAQ,EAAE,KAAK,EAAE,SAAS,EAAE,WAAW;IAMnD,UAAU,CAAC,EAAE,EAAE,MAAM,IAAI;IAIzB,YAAY,CAAC,EAAE,EAAE,MAAM,IAAI;IAG3B,aAAa,CAAC,EAAE,EAAE,MAAM,IAAI;IAa5B,cAAc;IAOd,aAAa,CAAC,QAAQ,EAAE,iBAAiB;IAIzC,YAAY;IAIZ,YAAY;IAIZ,YAAY;IAMZ,KAAK,IAAI,IAAI,GAAG,IAAI,EAAE;IAGtB,KAAK,IAAI,IAAI;IACb,QAAQ,CAAC,UAAU,CAAC,EAAE,cAAc,EAAE,GAAG,IAAI;IAS7C,OAAO,IAAI,IAAI;CAChB"}
1
+ {"version":3,"file":"RootVNode.d.ts","sourceRoot":"","sources":["../../src/vdom/RootVNode.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAChE,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAChC,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAKrD,eAAO,IAAI,WAAW,EAAE,SAAS,GAAG,SAAS,CAAC;AAE9C,qBAAa,SAAU,SAAQ,aAAa;IAC1C,QAAQ,EAAE,KAAK,EAAE,CAAC;IAClB,cAAc,EAAE,iBAAiB,EAAE,CAAM;IACzC,OAAO,CAAC,cAAc,CAGpB;IACF,OAAO,CAAC,mBAAmB,CAAkB;IAC7C,OAAO,CAAC,gBAAgB,CAAyB;gBAErC,QAAQ,EAAE,KAAK,EAAE,SAAS,EAAE,WAAW;IAMnD,UAAU,CAAC,EAAE,EAAE,MAAM,IAAI;IAIzB,YAAY,CAAC,EAAE,EAAE,MAAM,IAAI;IAG3B,aAAa,CAAC,EAAE,EAAE,MAAM,IAAI;IAa5B,cAAc;IAOd,aAAa,CAAC,QAAQ,EAAE,iBAAiB;IAIzC,YAAY;IAIZ,YAAY;IAIZ,YAAY;IAMZ,KAAK,IAAI,IAAI,GAAG,IAAI,EAAE;IAStB,KAAK,IAAI,IAAI;IACb,QAAQ,CAAC,UAAU,CAAC,EAAE,cAAc,EAAE,GAAG,IAAI;IAS7C,OAAO,IAAI,IAAI;CAChB"}
@@ -1,4 +1,5 @@
1
1
  import { AbstractVNode } from "./AbstractVNode";
2
+ import { flattenNodes } from "./dom-utils";
2
3
  // Global reference to the currently executing root
3
4
  // Safe because JS is single-threaded - only one render executes at a time
4
5
  export let currentRoot;
@@ -56,7 +57,13 @@ export class RootVNode extends AbstractVNode {
56
57
  }
57
58
  }
58
59
  mount() {
59
- return this.children.map((childNode) => childNode.mount(this)).flat();
60
+ // Optimized: avoid intermediate arrays from map+flat
61
+ const childResults = [];
62
+ for (let i = 0; i < this.children.length; i++) {
63
+ childResults.push(this.children[i].mount(this));
64
+ }
65
+ const result = flattenNodes(childResults);
66
+ return result.length === 1 ? result[0] : result;
60
67
  }
61
68
  patch() { }
62
69
  rerender(operations) {
@@ -1,9 +1,14 @@
1
+ /**
2
+ * Efficiently flatten a Node or Node[] result without creating intermediate arrays.
3
+ * Used to optimize mount operations that return either Node or Node[].
4
+ */
5
+ export declare function flattenNodes(items: (Node | Node[])[]): Node[];
1
6
  export declare function replaceElementsOf(parent: HTMLElement, newChildren: Node | Node[]): void;
2
7
  export declare function elementsToFragment(elm: Node | Node[]): Node;
3
8
  export declare function removeElementRange(parent: Node, start: Node, end: Node): void;
4
9
  export declare function setElementProp(elm: HTMLElement, key: string, value: unknown): void;
5
10
  export declare function setElementAttr(elm: HTMLElement, key: string, value: string | null): void;
6
- export declare function setElementStyle(elm: HTMLElement, value: string | Record<string, unknown> | null): void;
11
+ export declare function setElementStyle(elm: HTMLElement, value?: string | Record<string, unknown> | null): void;
7
12
  export declare function isEventProp(name: string): boolean;
8
13
  export declare function setElementClass(elm: HTMLElement, value: string | Record<string, boolean> | null | undefined): void;
9
14
  //# sourceMappingURL=dom-utils.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"dom-utils.d.ts","sourceRoot":"","sources":["../../src/vdom/dom-utils.ts"],"names":[],"mappings":"AAAA,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,WAAW,EACnB,WAAW,EAAE,IAAI,GAAG,IAAI,EAAE,QAO3B;AAED,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,IAAI,GAAG,IAAI,EAAE,GAAG,IAAI,CAc3D;AAGD,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,QAQtE;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,WAAW,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,QAE3E;AAED,wBAAgB,cAAc,CAC5B,GAAG,EAAE,WAAW,EAChB,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,MAAM,GAAG,IAAI,QAOrB;AAED,wBAAgB,eAAe,CAC7B,GAAG,EAAE,WAAW,EAChB,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,QAe/C;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEjD;AAED,wBAAgB,eAAe,CAC7B,GAAG,EAAE,WAAW,EAChB,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,GAAG,SAAS,QA0B3D"}
1
+ {"version":3,"file":"dom-utils.d.ts","sourceRoot":"","sources":["../../src/vdom/dom-utils.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,CAAC,IAAI,GAAG,IAAI,EAAE,CAAC,EAAE,GAAG,IAAI,EAAE,CAa7D;AAED,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,WAAW,EACnB,WAAW,EAAE,IAAI,GAAG,IAAI,EAAE,QAO3B;AAED,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,IAAI,GAAG,IAAI,EAAE,GAAG,IAAI,CAc3D;AAGD,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,QAQtE;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,WAAW,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,QAE3E;AAED,wBAAgB,cAAc,CAC5B,GAAG,EAAE,WAAW,EAChB,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,MAAM,GAAG,IAAI,QAOrB;AAED,wBAAgB,eAAe,CAC7B,GAAG,EAAE,WAAW,EAChB,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,QAehD;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEjD;AAED,wBAAgB,eAAe,CAC7B,GAAG,EAAE,WAAW,EAChB,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,GAAG,SAAS,QA0B3D"}
@@ -1,3 +1,22 @@
1
+ /**
2
+ * Efficiently flatten a Node or Node[] result without creating intermediate arrays.
3
+ * Used to optimize mount operations that return either Node or Node[].
4
+ */
5
+ export function flattenNodes(items) {
6
+ const result = [];
7
+ for (let i = 0; i < items.length; i++) {
8
+ const item = items[i];
9
+ if (Array.isArray(item)) {
10
+ for (let j = 0; j < item.length; j++) {
11
+ result.push(item[j]);
12
+ }
13
+ }
14
+ else {
15
+ result.push(item);
16
+ }
17
+ }
18
+ return result;
19
+ }
1
20
  export function replaceElementsOf(parent, newChildren) {
2
21
  if (Array.isArray(newChildren)) {
3
22
  parent.replaceChildren(...newChildren);
@@ -42,7 +61,7 @@ export function setElementAttr(elm, key, value) {
42
61
  }
43
62
  }
44
63
  export function setElementStyle(elm, value) {
45
- if (value === null) {
64
+ if (value === null || value === undefined) {
46
65
  elm.removeAttribute("style");
47
66
  return;
48
67
  }
@@ -5,4 +5,16 @@ import { RootVNode } from "./RootVNode";
5
5
  import { TextVNode } from "./TextVNode";
6
6
  export type VNode = ElementVNode | FragmentVNode | ComponentVNode | TextVNode | RootVNode;
7
7
  export type Props = Record<string, unknown>;
8
+ /**
9
+ * Bit flags to optimize VNode property checks.
10
+ * Pre-computed during VNode creation to avoid repeated conditional checks.
11
+ */
12
+ export declare const enum VFlags {
13
+ None = 0,
14
+ HasProps = 1,// Has any props at all
15
+ HasClass = 2,// Has class or className prop
16
+ HasStyle = 4,// Has style prop
17
+ HasEvents = 8,// Has event listeners (onXxx props)
18
+ HasDataAttrs = 16
19
+ }
8
20
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/vdom/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAExC,MAAM,MAAM,KAAK,GACb,YAAY,GACZ,aAAa,GACb,cAAc,GACd,SAAS,GACT,SAAS,CAAC;AAEd,MAAM,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/vdom/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAExC,MAAM,MAAM,KAAK,GACb,YAAY,GACZ,aAAa,GACb,cAAc,GACd,SAAS,GACT,SAAS,CAAC;AAEd,MAAM,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAE5C;;;GAGG;AACH,0BAAkB,MAAM;IACtB,IAAI,IAAI;IACR,QAAQ,IAAS,CAAQ,uBAAuB;IAChD,QAAQ,IAAS,CAAQ,8BAA8B;IACvD,QAAQ,IAAS,CAAQ,iBAAiB;IAC1C,SAAS,IAAS,CAAO,oCAAoC;IAC7D,YAAY,KAAS;CACtB"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rask-ui",
3
- "version": "0.2.6",
3
+ "version": "0.2.7",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",