yandel 1.1.2 → 1.2.1

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.
package/README.md CHANGED
@@ -199,10 +199,10 @@ function AppNotifications() {
199
199
 
200
200
  #### Future node
201
201
 
202
- Future nodes are `templates` (functions) and will be created at render time (as `components` and `text`). This applies for all type of functions that return a `ValidTemplateReturn`; also the generic tags like `div`, `span`, etc. are allowed
202
+ Future nodes are `templates` (functions) used as a child and will be created at render time (as `components` and `text`). This applies for all type of functions that return a `ValidTemplateReturn`; also the generic tags like `div`, `span`, etc. are allowed
203
203
 
204
204
  ```ts
205
- import { div, main, nav } from "yandel"
205
+ import { div, main, nav } from "yandel";
206
206
 
207
207
  function MyGridOfPhotos () {
208
208
  return div(...);
@@ -566,7 +566,7 @@ function UserConsumerWithError() {
566
566
 
567
567
  #### Future nodes
568
568
 
569
- As explained in the section of [future nodes](#future-node), `components`, `text` and `future nodes` are created at render time, and if your consumer is a function, like in the next example:
569
+ As explained in the section of [future nodes](#future-node), `components`, `text` and `future nodes` are created at render time. You have to understand how they are being created:
570
570
 
571
571
  ```ts
572
572
  function UserConsumer() {
@@ -580,7 +580,8 @@ class App extends Component {
580
580
  }
581
581
  ```
582
582
 
583
- `UserConsumer` will be created before the `UserProvider` is rendered and provides, leading to an undefined context.
583
+ When a component is created, its `render` method will be called at render time. In this example, `UserConsumer` will be called before the `UserProvider` `render`
584
+ method at render time, so the context will be undefined.
584
585
 
585
586
  ```ts
586
587
  public render(): ValidTemplateReturn {
@@ -591,11 +592,11 @@ public render(): ValidTemplateReturn {
591
592
  }
592
593
  ```
593
594
 
594
- Now, `UserConsumer` will be able to consume. Don't forget that nodes outside the provider component
595
+ Now, `UserConsumer` will be able to consume, because It will be created at render time right after the `UserProvider` `render` method, so it will be accesible.
595
596
 
596
597
  ### Ref
597
598
 
598
- The `ref` prop allows you to have access to the element's reference:
599
+ The `ref` prop allows you to have access to the tag's reference:
599
600
 
600
601
  ```ts
601
602
  import { Component, ElementRef, Stores, input } from "yandel";
@@ -635,7 +636,7 @@ class WithKey extends Component {
635
636
 
636
637
  ## Usage
637
638
 
638
- Define your own templates and components. Then, use `createRoot.render` to render your UI.
639
+ Define your UI: components, templates, nodes... then, use `createRoot.render` to start rendering and done!
639
640
 
640
641
  ```ts
641
642
  import {
package/dist/index.d.ts CHANGED
@@ -1,2 +1,3 @@
1
- export { Component, createContext, createRoot, EffectHandler, Element, ElementRef, HTMLProps, HTMLTags, Portal, StateHandler, Stores, Styles, ValidNode, ValidNodeChild, ValidTemplateReturn, FutureNode, } from "./node";
1
+ /// <reference path="../types/index.d.ts" preserve="true" />
2
+ export { Component, createContext, createRoot, EffectHandler, Portal, Stores, ValidNode, ValidNodeChild, ValidTemplateReturn, FutureNode, } from "./node";
2
3
  export * from "./tags";
package/dist/index.js CHANGED
@@ -1,2 +1,10 @@
1
- export { Component, createContext, createRoot, Portal, Stores, } from "./node";
1
+ /// <reference path="../types/index.d.ts" preserve="true"/>
2
+ export { Component, createContext, createRoot,
3
+ // Element,
4
+ // ElementRef,
5
+ // HTMLProps,
6
+ // HTMLTags,
7
+ Portal,
8
+ // StateHandler,
9
+ Stores, } from "./node";
2
10
  export * from "./tags";
package/dist/node.d.ts CHANGED
@@ -1,62 +1,12 @@
1
- type HTMLExcludedProperties = `aria${string}` | "tagName" | "shadowRoot" | "slot" | "classList" | "style" | "attributes" | "attributeStyleMap" | "ATTRIBUTE_NODE" | "CDATA_SECTION_NODE" | "COMMENT_NODE" | "childElementCount" | "childNodes" | "children" | "isConnected" | "ownerDocument" | "lastChild" | "lastElement" | "nextElementSibling" | "nextSibling" | "previousElementSibling" | "previousSibling" | "parentElement" | "parent" | "outerContent" | "firstChild" | "firstElementChild" | "lastChild" | "lastElementChild" | "innerHTML" | "outerHTML" | "innerContent" | "textContent" | `DOCUMENT_${string}` | "NOTATION_NODE" | "PROCESSING_INSTRUCTION_NODE" | "CONTENT_NODE" | "ELEMENT_NODE" | "TEXT_NODE" | `ENTITY_${string}`;
2
- type AriaWidgetProperties = "aria-autocomplete" | "aria-checked" | "aria-disabled" | "aria-errormessage" | "aria-expanded" | "aria-haspopup" | "aria-hidden" | "aria-invalid" | "aria-label" | "aria-level" | "aria-modal" | "aria-multiline" | "aria-multiselectable" | "aria-orientation" | "aria-placeholder" | "aria-pressed" | "aria-readonly" | "aria-required" | "aria-selected" | "aria-sort" | "aria-valuemax" | "aria-valuemin" | "aria-valuenow" | "aria-valuetext";
3
- type AriaLiveRegionProperties = "aria-busy" | "aria-live" | "aria-relevant" | "aria-atomic";
4
- type AriaDragAndDropProperties = "aria-dropeffect" | "aria-grabbed";
5
- type AriaRelatonshipProperties = "aria-activedescendant" | "aria-colcount" | "aria-colindex" | "aria-colspan" | "aria-controls" | "aria-describedby" | "aria-description" | "aria-details" | "aria-errormessage" | "aria-flowto" | "aria-labelledby" | "aria-owns" | "aria-posinset" | "aria-rowcount" | "aria-rowindex" | "aria-rowspan" | "aria-setsize";
6
- type AriaGlobalProperties = "aria-atomic" | "aria-busy" | "aria-controls" | "aria-current" | "aria-describedby" | "aria-description" | "aria-details" | "aria-disabled" | "aria-dropeffect" | "aria-errormessage" | "aria-flowto" | "aria-grabbed" | "aria-haspopup" | "aria-hidden" | "aria-invalid" | "aria-keyshortcuts" | "aria-label" | "aria-labelledby" | "aria-live" | "aria-owns" | "aria-relevant" | "aria-roledescription";
7
- type AriaProps = AriaWidgetProperties | AriaDragAndDropProperties | AriaLiveRegionProperties | AriaRelatonshipProperties | AriaGlobalProperties;
8
- type AriaBoolean = "true" | "false";
9
- type AriaValue = Exclude<string, AriaBoolean>;
10
- type AriaValueMap = Partial<Record<AriaProps, AriaBoolean | AriaValue>>;
11
- type KeyedObject = Record<string | symbol | number, any>;
12
- type HTMLTags = keyof HTMLElementTagNameMap;
13
- type HTMLSVGTags = keyof SVGElementTagNameMap;
14
- type Element<K extends HTMLTags = HTMLTags> = HTMLElementTagNameMap[K];
15
- type SVGElement<K extends HTMLSVGTags = HTMLSVGTags> = SVGElementTagNameMap[K];
16
- interface SwitchableNode<T extends Node> {
17
- switch(t: T): boolean;
18
- }
19
- type FutureNode = () => ValidNodeChild;
20
1
  type ValidNode = Node | Component | Component<KeyedObject> | FutureNode;
21
2
  type ValidNodeChild = ValidNode | null | string;
22
3
  type ValidTemplateReturn = ValidNodeChild | ValidNodeChild[];
4
+ type FutureNode = () => ValidNodeChild;
23
5
  type EffectHandler = (() => void) | (() => () => void);
24
- type ExcludeFunctions<T> = {
25
- [K in keyof T as T[K] extends Function ? never : K]: T[K];
26
- };
27
- type Styles = Partial<CSSStyleDeclaration>;
28
- interface ElementOverridedProperties extends AriaValueMap {
29
- style?: Styles;
30
- }
31
- type AnyElement<T extends HTMLTags | HTMLSVGTags = HTMLTags> = T extends HTMLTags ? Element<T> : T extends HTMLSVGTags ? SVGElement<T> : never;
32
- type AnyProps<T extends HTMLTags | HTMLSVGTags = HTMLTags> = T extends HTMLTags ? HTMLProps<T> : T extends HTMLSVGTags ? SVGProps<T> : never;
33
- type ElementRef<T extends HTMLTags | HTMLSVGTags = HTMLTags> = Stores<(T extends HTMLTags ? HTMLElementTagNameMap[T] : T extends HTMLSVGTags ? SVGElementTagNameMap[T] : never) | undefined>;
34
- interface ElementProps<T extends HTMLTags | HTMLSVGTags = HTMLTags> {
35
- ref?: ElementRef<T>;
36
- key?: string | number | symbol;
37
- }
38
- type ExcludeProperties<T> = {
39
- [K in keyof T as K extends HTMLExcludedProperties ? never : K]: T[K];
40
- };
41
- type HTMLProps<T extends HTMLTags> = Partial<ExcludeProperties<ExcludeFunctions<Element<T>>>> & ElementProps<T> & ElementOverridedProperties;
42
- type SVGAttributeValue = string | number;
43
- type NormalizeSVGProp<T> = T extends SVGAnimatedLength ? SVGAttributeValue : T extends SVGAnimatedAngle ? SVGAttributeValue : T extends SVGAnimatedBoolean ? SVGAttributeValue : T extends SVGAnimatedEnumeration ? SVGAttributeValue : T extends SVGAnimatedInteger ? SVGAttributeValue : T extends SVGAnimatedNumber ? SVGAttributeValue : T extends SVGAnimatedPreserveAspectRatio ? SVGAttributeValue : T extends SVGAnimatedRect ? SVGAttributeValue : T extends SVGAnimatedString ? SVGAttributeValue : T extends SVGAnimatedTransformList ? SVGAttributeValue : T extends SVGPointList ? SVGAttributeValue : T;
44
- type SVGRawProps<T extends HTMLSVGTags> = ExcludeProperties<ExcludeFunctions<SVGElementTagNameMap[T]>>;
45
- interface SVGOverridedProperties {
46
- fill?: string;
47
- "fill-opacity"?: string;
48
- stroke?: string;
49
- "stroke-width"?: SVGAttributeValue;
50
- "stroke-linecap"?: "butt" | "round" | "square";
51
- "stroke-linejoin"?: "miter" | "round" | "bevel";
52
- d?: string;
53
- "stroke-dasharray"?: SVGAttributeValue;
6
+ interface SwitchableNode<T extends Node> {
7
+ switch(t: T): boolean;
54
8
  }
55
- type SVGProps<T extends HTMLSVGTags> = Partial<{
56
- [K in keyof SVGRawProps<T>]: NormalizeSVGProp<SVGRawProps<T>[K]>;
57
- }> & ElementProps<T> & ElementOverridedProperties & SVGOverridedProperties;
58
- type StateHandler<S extends KeyedObject | undefined = undefined> = S | ((l: S) => S);
59
- declare const enum NodeType {
9
+ declare enum NodeType {
60
10
  Tag = 0,
61
11
  Content = 1,
62
12
  Parent = 2,
@@ -93,10 +43,7 @@ declare class TagNode<T extends HTMLTags | HTMLSVGTags = HTMLTags> extends Node
93
43
  key: symbol | string | number | undefined;
94
44
  index_length: number;
95
45
  constructor(tag: T, props?: AnyProps<T>, children?: ValidNodeChild[]);
96
- private _apply_dom_props;
97
46
  private _diff_dom_props;
98
- private _clear_dom_props;
99
- private _clear_dom_events;
100
47
  get dom(): AnyElement<T> | undefined;
101
48
  get props(): AnyProps<T> | undefined;
102
49
  get children(): ValidNodeChild[] | undefined;
@@ -105,7 +52,7 @@ declare class TagNode<T extends HTMLTags | HTMLSVGTags = HTMLTags> extends Node
105
52
  clearChildren(): void;
106
53
  clearDom(): void;
107
54
  delete(): void;
108
- switch(t: TagNode<HTMLTags>): boolean;
55
+ switch(t: TagNode): boolean;
109
56
  }
110
57
  declare class ParentNode<T extends HTMLElement = HTMLElement> extends Node implements SwitchableNode<ParentNode> {
111
58
  static is(t: any): t is ParentNode;
@@ -141,4 +88,4 @@ declare function createRoot<T extends HTMLElement>(root: T): {
141
88
  render: (...children: ValidNodeChild[]) => void;
142
89
  };
143
90
  declare function createContext<T extends KeyedObject>(): Context<T>;
144
- export { Component, createContext, createRoot, EffectHandler, Element, ElementRef, HTMLProps, HTMLTags, HTMLSVGTags, SVGProps, Node, Portal, StateHandler, Stores, Styles, TagNode, ValidNode, ValidNodeChild, ValidTemplateReturn, FutureNode, };
91
+ export { Component, createContext, createRoot, EffectHandler, Node, Portal, Stores, TagNode, ValidNode, ValidNodeChild, ValidTemplateReturn, FutureNode, };
package/dist/node.js CHANGED
@@ -64,6 +64,13 @@ const SVG_TAGS = new Set([
64
64
  "use",
65
65
  "view",
66
66
  ]);
67
+ var NodeType;
68
+ (function (NodeType) {
69
+ NodeType[NodeType["Tag"] = 0] = "Tag";
70
+ NodeType[NodeType["Content"] = 1] = "Content";
71
+ NodeType[NodeType["Parent"] = 2] = "Parent";
72
+ NodeType[NodeType["Component"] = 3] = "Component";
73
+ })(NodeType || (NodeType = {}));
67
74
  class Stores {
68
75
  #_stores;
69
76
  constructor(s) {
@@ -76,7 +83,7 @@ class Stores {
76
83
  this.#_stores = s;
77
84
  }
78
85
  }
79
- class ComponentUpdateQueue {
86
+ class UpdateQueue {
80
87
  static _update_scheduled = false;
81
88
  static _queue = new Set();
82
89
  static processNodeQueue() {
@@ -118,16 +125,14 @@ class ComponentUpdateQueue {
118
125
  if (!this._update_scheduled)
119
126
  this.notifyQueue();
120
127
  }
121
- }
122
- function queueNodesDeletion(ns) {
123
- queueMicrotask(() => {
124
- for (const c of ns) {
125
- if (c instanceof Node)
126
- c.delete();
127
- else
128
- console.warn("Unknown child");
129
- }
130
- });
128
+ static queueNodesDeletion(ns) {
129
+ queueMicrotask(() => {
130
+ for (const c of ns) {
131
+ if (c && c instanceof Node)
132
+ c.delete();
133
+ }
134
+ });
135
+ }
131
136
  }
132
137
  const ComponentInternalKey = Symbol("_$ci$_");
133
138
  function _c_el(t) {
@@ -149,16 +154,16 @@ class Node {
149
154
  this.$typeof = t;
150
155
  }
151
156
  get isTag() {
152
- return this.$typeof === 0 /* NodeType.Tag */;
157
+ return this.$typeof === NodeType.Tag;
153
158
  }
154
159
  get isContent() {
155
- return this.$typeof === 1 /* NodeType.Content */;
160
+ return this.$typeof === NodeType.Content;
156
161
  }
157
162
  get isParent() {
158
- return this.$typeof === 2 /* NodeType.Parent */;
163
+ return this.$typeof === NodeType.Parent;
159
164
  }
160
165
  get isComponent() {
161
- return this.$typeof === 3 /* NodeType.Component */;
166
+ return this.$typeof === NodeType.Component;
162
167
  }
163
168
  get deleted() {
164
169
  return this._deleted;
@@ -183,7 +188,7 @@ class ContentNode extends Node {
183
188
  _content;
184
189
  _dom = undefined;
185
190
  constructor(content) {
186
- super(1 /* NodeType.Content */);
191
+ super(NodeType.Content);
187
192
  this._content = content;
188
193
  this.needs_update = true;
189
194
  }
@@ -225,21 +230,10 @@ class ContentNode extends Node {
225
230
  super.delete();
226
231
  }
227
232
  }
228
- function create_template(t) {
229
- try {
230
- return t();
231
- }
232
- catch (error) {
233
- throw new Error(`Template create error: ${error}`);
234
- }
235
- }
236
- function _get_node_from_future(t) {
237
- const n = create_template(t);
238
- if (_is_fn(n))
239
- return _get_node_from_future(n);
240
- return n;
233
+ function _create_html_tag(tag) {
234
+ return SVG_TAGS.has(tag) ? _c_s(tag) : _c_el(tag);
241
235
  }
242
- function _apply_dom_prop(dom, props, prop) {
236
+ function _apply_html_prop(dom, props, prop) {
243
237
  const v = props[prop];
244
238
  if (v == null)
245
239
  return;
@@ -287,7 +281,7 @@ function _apply_dom_prop(dom, props, prop) {
287
281
  else
288
282
  dom.setAttribute(prop, v);
289
283
  }
290
- function _remove_dom_prop(dom, props, prop) {
284
+ function _remove_html_prop(dom, props, prop) {
291
285
  if (/^on[a-z]/.test(prop)) {
292
286
  const ev_name = prop.slice(2);
293
287
  dom.removeEventListener(ev_name, props[prop]);
@@ -295,11 +289,21 @@ function _remove_dom_prop(dom, props, prop) {
295
289
  }
296
290
  if (prop === "ref" && props.ref instanceof Stores) {
297
291
  props.ref.stores = undefined;
298
- return;
299
292
  }
300
293
  const v = props[prop];
301
- if (v == null)
294
+ if (v == null) {
295
+ if (prop === "style")
296
+ return;
297
+ if (prop in dom) {
298
+ try {
299
+ dom[prop] = undefined;
300
+ }
301
+ catch (error) {
302
+ console.error("Remove prop error:", error);
303
+ }
304
+ }
302
305
  return;
306
+ }
303
307
  if (prop === "style" && typeof v === "object") {
304
308
  try {
305
309
  Object.entries(v).forEach(([cssProp]) => {
@@ -323,15 +327,15 @@ function _remove_dom_prop(dom, props, prop) {
323
327
  switch (t) {
324
328
  case "boolean": {
325
329
  dom[prop] = false;
326
- return;
330
+ break;
327
331
  }
328
332
  case "string": {
329
333
  dom[prop] = "";
330
- return;
334
+ break;
331
335
  }
332
336
  case "object": {
333
- dom[prop] = null;
334
- return;
337
+ dom[prop] = undefined;
338
+ break;
335
339
  }
336
340
  }
337
341
  }
@@ -339,6 +343,69 @@ function _remove_dom_prop(dom, props, prop) {
339
343
  }
340
344
  dom.removeAttribute(prop);
341
345
  }
346
+ function _get_props_diff(a, b) {
347
+ const _to_remove = {};
348
+ const _to_apply = {};
349
+ for (const key in a) {
350
+ if (!b.hasOwnProperty(key)) {
351
+ _to_remove[key] = a[key];
352
+ }
353
+ }
354
+ for (const key in b) {
355
+ if (b[key] == null) {
356
+ _to_remove[key] = b[key];
357
+ }
358
+ else {
359
+ if (b[key] === a[key])
360
+ continue;
361
+ _to_apply[key] = b[key];
362
+ }
363
+ }
364
+ return {
365
+ apply: _to_apply,
366
+ remove: _to_remove,
367
+ };
368
+ }
369
+ // function _diff_html_props<T extends HTMLTags | HTMLSVGTags>(
370
+ // dom: AnyElement<T>,
371
+ // a: AnyProps<T>,
372
+ // b: AnyProps<T>
373
+ // ) {
374
+ // for (const prop of Object.keys(a)) {
375
+ // if (prop.startsWith("on")) {
376
+ // _remove_html_prop(dom, a, prop);
377
+ // if (prop in b) _apply_html_prop(dom, b, prop);
378
+ // } else if (!(prop in b)) {
379
+ // _remove_html_prop(dom, a, prop);
380
+ // } else _apply_html_prop(dom, b, prop);
381
+ // }
382
+ // }
383
+ function _clear_events(dom, props) {
384
+ for (const prop of Object.keys(props)) {
385
+ if (prop.startsWith("on")) {
386
+ if (typeof props[prop] !== "function")
387
+ continue;
388
+ const ev_name = prop.slice(2);
389
+ dom.removeEventListener(ev_name, props[prop]);
390
+ delete props[prop];
391
+ }
392
+ }
393
+ }
394
+ function _apply_props(dom, props) {
395
+ for (const prop of Object.keys(props)) {
396
+ _apply_html_prop(dom, props, prop);
397
+ }
398
+ }
399
+ function _clear_props(dom, props) {
400
+ for (const prop of Object.keys(props)) {
401
+ _remove_html_prop(dom, props, prop);
402
+ }
403
+ }
404
+ function _remove_style(dom, styles) {
405
+ for (const style of Object.keys(styles)) {
406
+ dom.style[style] = "";
407
+ }
408
+ }
342
409
  class TagNode extends Node {
343
410
  static is(t) {
344
411
  return t instanceof TagNode;
@@ -350,7 +417,7 @@ class TagNode extends Node {
350
417
  key = undefined;
351
418
  index_length = 0;
352
419
  constructor(tag, props, children) {
353
- super(0 /* NodeType.Tag */);
420
+ super(NodeType.Tag);
354
421
  this.tag = tag;
355
422
  this._props = props;
356
423
  if (this._props && "key" in this._props) {
@@ -359,51 +426,26 @@ class TagNode extends Node {
359
426
  this._children = children;
360
427
  this.needs_update = true;
361
428
  }
362
- _apply_dom_props() {
363
- if (!this._props || !this._dom)
364
- return;
365
- for (const prop in this._props) {
366
- _apply_dom_prop(this._dom, this._props, prop);
367
- }
368
- }
369
429
  _diff_dom_props(nprops) {
370
- if (!this._props) {
371
- this._props = nprops;
372
- this._apply_dom_props();
373
- return;
374
- }
375
- if (this._dom)
376
- for (const prop in this._props) {
377
- if (prop.startsWith("on")) {
378
- _remove_dom_prop(this._dom, this._props, prop);
379
- if (prop in nprops)
380
- _apply_dom_prop(this._dom, nprops, prop);
381
- }
382
- else if (!(prop in nprops)) {
383
- _remove_dom_prop(this._dom, this._props, prop);
430
+ if (this._dom) {
431
+ if (this._props) {
432
+ if (this._props.style) {
433
+ _remove_style(this._dom, this._props.style);
434
+ delete this._props.style;
384
435
  }
385
- else
386
- _apply_dom_prop(this._dom, nprops, prop);
387
- }
388
- this._props = nprops;
389
- }
390
- _clear_dom_props() {
391
- if (this._props && this._dom)
392
- for (const prop in this._props) {
393
- _remove_dom_prop(this._dom, this._props, prop);
436
+ _clear_events(this._dom, this._props);
437
+ const diff = _get_props_diff(this._props, nprops);
438
+ _clear_props(this._dom, diff.remove);
439
+ _apply_props(this._dom, diff.apply);
440
+ this._props = nprops;
394
441
  }
395
- }
396
- _clear_dom_events() {
397
- if (this._props && this._dom)
398
- for (const prop in this._props) {
399
- const v = Reflect.get(this._props, prop);
400
- if (!v)
401
- continue;
402
- if (prop.startsWith("on") && typeof v === "function") {
403
- const ev_name = prop.slice(2);
404
- this._dom.removeEventListener(ev_name, Reflect.get(this._props, prop));
405
- }
442
+ else {
443
+ this._props = nprops;
444
+ _apply_props(this._dom, this._props);
445
+ return;
406
446
  }
447
+ }
448
+ this._props = nprops;
407
449
  }
408
450
  get dom() {
409
451
  return this._dom;
@@ -423,12 +465,16 @@ class TagNode extends Node {
423
465
  if (this._deleted)
424
466
  throw new Error("Attempt to create a deleted node");
425
467
  if (this._dom) {
426
- this._apply_dom_props();
427
- this.needs_update = true;
428
- return true;
468
+ if (this._props) {
469
+ _apply_props(this._dom, this._props);
470
+ this.needs_update = true;
471
+ return true;
472
+ }
473
+ return false;
429
474
  }
430
- this._dom = (SVG_TAGS.has(this.tag) ? _c_s(this.tag) : _c_el(this.tag));
431
- this._apply_dom_props();
475
+ this._dom = _create_html_tag(this.tag);
476
+ if (this._props)
477
+ _apply_props(this._dom, this._props);
432
478
  this.needs_update = false;
433
479
  return true;
434
480
  }
@@ -436,7 +482,7 @@ class TagNode extends Node {
436
482
  if (this._deleted)
437
483
  return;
438
484
  if (this._children?.length) {
439
- queueNodesDeletion(this._children);
485
+ UpdateQueue.queueNodesDeletion(this._children);
440
486
  delete this._children;
441
487
  }
442
488
  }
@@ -446,7 +492,8 @@ class TagNode extends Node {
446
492
  return;
447
493
  }
448
494
  this.needs_update = true;
449
- this._clear_dom_events();
495
+ if (this._props)
496
+ _clear_events(this._dom, this._props);
450
497
  this._dom.remove();
451
498
  delete this._dom;
452
499
  }
@@ -464,10 +511,20 @@ class TagNode extends Node {
464
511
  this.key = t.props?.key ?? t.key;
465
512
  if (this.tag === t.tag) {
466
513
  // Tag is the same
467
- if (t.props)
468
- this._diff_dom_props(t.props);
469
- else if (this._props)
470
- this._clear_dom_props();
514
+ if (this._dom) {
515
+ if (this._props) {
516
+ if (t.props)
517
+ this._diff_dom_props(t.props);
518
+ else
519
+ _clear_props(this._dom, this._props);
520
+ }
521
+ else if (t.props) {
522
+ this._props = t.props;
523
+ _apply_props(this._dom, this._props);
524
+ }
525
+ }
526
+ else if (t.props)
527
+ this._props = t.props;
471
528
  }
472
529
  else {
473
530
  // Tag has changed
@@ -500,7 +557,7 @@ class ParentNode extends Node {
500
557
  _children = undefined;
501
558
  child_length = 0;
502
559
  constructor(root, children) {
503
- super(2 /* NodeType.Parent */);
560
+ super(NodeType.Parent);
504
561
  this.dom = root;
505
562
  this._children = children;
506
563
  }
@@ -515,7 +572,7 @@ class ParentNode extends Node {
515
572
  clearChildren() {
516
573
  this.child_length = 0;
517
574
  if (this._children?.length) {
518
- queueNodesDeletion(this._children);
575
+ UpdateQueue.queueNodesDeletion(this._children);
519
576
  delete this._children;
520
577
  }
521
578
  }
@@ -542,6 +599,20 @@ class ParentNode extends Node {
542
599
  return this.needs_update;
543
600
  }
544
601
  }
602
+ function _create_template(t) {
603
+ try {
604
+ return t();
605
+ }
606
+ catch (error) {
607
+ throw new Error(`Template create error: ${error}`);
608
+ }
609
+ }
610
+ function _get_node_from_future(t) {
611
+ const n = _create_template(t);
612
+ if (_is_fn(n))
613
+ return _get_node_from_future(n);
614
+ return n;
615
+ }
545
616
  class ComponentNode extends Node {
546
617
  static is(t) {
547
618
  return t instanceof ComponentNode;
@@ -551,7 +622,7 @@ class ComponentNode extends Node {
551
622
  _children = undefined;
552
623
  child_length = 0;
553
624
  constructor(template) {
554
- super(3 /* NodeType.Component */);
625
+ super(NodeType.Component);
555
626
  this._template = template;
556
627
  getInternals(this._template).switch(this);
557
628
  this.needs_update = true;
@@ -563,7 +634,7 @@ class ComponentNode extends Node {
563
634
  throw new Error("Template has been deleted");
564
635
  nextInternalTick(this._template);
565
636
  try {
566
- const child = create_template(this._template.render.bind(this._template));
637
+ const child = _create_template(this._template.render.bind(this._template));
567
638
  if (child == null) {
568
639
  if (this.hasChildren) {
569
640
  this.clearChildren();
@@ -603,7 +674,7 @@ class ComponentNode extends Node {
603
674
  return;
604
675
  this.child_length = 0;
605
676
  if (this._children?.length) {
606
- queueNodesDeletion(this._children);
677
+ UpdateQueue.queueNodesDeletion(this._children);
607
678
  delete this._children;
608
679
  }
609
680
  }
@@ -619,10 +690,8 @@ class ComponentNode extends Node {
619
690
  if (t.hasChildren) {
620
691
  this.needs_update = diffChildren(this._children, t.children);
621
692
  }
622
- else {
623
- this.needs_update = true;
624
- this.clearChildren();
625
- }
693
+ this.needs_update = true;
694
+ this.clearChildren();
626
695
  }
627
696
  else if (t.hasChildren)
628
697
  this._children = t.children;
@@ -686,7 +755,7 @@ class ComponentInternals {
686
755
  : s;
687
756
  Promise.resolve().then(() => {
688
757
  if (this.#_n)
689
- ComponentUpdateQueue.queueNodeUpdate(this.#_n);
758
+ UpdateQueue.queueNodeUpdate(this.#_n);
690
759
  });
691
760
  }
692
761
  addEffect(e) {
@@ -1202,4 +1271,15 @@ function createRoot(root) {
1202
1271
  function createContext() {
1203
1272
  return new Context();
1204
1273
  }
1205
- export { Component, createContext, createRoot, Node, Portal, Stores, TagNode, };
1274
+ export { Component, createContext, createRoot,
1275
+ // Element,
1276
+ // ElementRef,
1277
+ // HTMLProps,
1278
+ // HTMLTags,
1279
+ // HTMLSVGTags,
1280
+ // SVGProps,
1281
+ Node, Portal,
1282
+ // StateHandler,
1283
+ Stores,
1284
+ // Styles,
1285
+ TagNode, };
package/dist/tags.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { HTMLProps, SVGProps, TagNode, ValidNodeChild } from "./node";
1
+ import { TagNode, ValidNodeChild } from "./node";
2
2
  export declare function _is_valid_node(n: any): n is ValidNodeChild;
3
3
  /**
4
4
  * h1 - Creates h1 Tag node
package/dist/tags.js CHANGED
@@ -1,4 +1,4 @@
1
- import { Component, Node, TagNode, } from "./node";
1
+ import { Component, Node, TagNode } from "./node";
2
2
  import { _is_string } from "./utils";
3
3
  export function _is_valid_node(n) {
4
4
  return (n == null || _is_string(n) || n instanceof Node || n instanceof Component);
package/package.json CHANGED
@@ -1,11 +1,12 @@
1
1
  {
2
2
  "name": "yandel",
3
3
  "description": "A reactive lightweight TS frontend framework",
4
- "version": "1.1.2",
4
+ "version": "1.2.1",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
7
7
  "files": [
8
- "dist"
8
+ "dist",
9
+ "types"
9
10
  ],
10
11
  "scripts": {
11
12
  "build": "tsc",
@@ -0,0 +1,225 @@
1
+ type HTMLExcludedProperties =
2
+ | `aria${string}`
3
+ | "tagName"
4
+ | "shadowRoot"
5
+ | "slot"
6
+ | "classList"
7
+ | "style"
8
+ | "attributes"
9
+ | "attributeStyleMap"
10
+ | "ATTRIBUTE_NODE"
11
+ | "CDATA_SECTION_NODE"
12
+ | "COMMENT_NODE"
13
+ | "childElementCount"
14
+ | "childNodes"
15
+ | "children"
16
+ | "isConnected"
17
+ | "ownerDocument"
18
+ | "lastChild"
19
+ | "lastElement"
20
+ | "nextElementSibling"
21
+ | "nextSibling"
22
+ | "previousElementSibling"
23
+ | "previousSibling"
24
+ | "parentElement"
25
+ | "parent"
26
+ | "outerContent"
27
+ | "firstChild"
28
+ | "firstElementChild"
29
+ | "lastChild"
30
+ | "lastElementChild"
31
+ | "innerHTML"
32
+ | "outerHTML"
33
+ | "innerContent"
34
+ | "textContent"
35
+ | `DOCUMENT_${string}`
36
+ | "NOTATION_NODE"
37
+ | "PROCESSING_INSTRUCTION_NODE"
38
+ | "CONTENT_NODE"
39
+ | "ELEMENT_NODE"
40
+ | "TEXT_NODE"
41
+ | `ENTITY_${string}`;
42
+ type AriaWidgetProperties =
43
+ | "aria-autocomplete"
44
+ | "aria-checked"
45
+ | "aria-disabled"
46
+ | "aria-errormessage"
47
+ | "aria-expanded"
48
+ | "aria-haspopup"
49
+ | "aria-hidden"
50
+ | "aria-invalid"
51
+ | "aria-label"
52
+ | "aria-level"
53
+ | "aria-modal"
54
+ | "aria-multiline"
55
+ | "aria-multiselectable"
56
+ | "aria-orientation"
57
+ | "aria-placeholder"
58
+ | "aria-pressed"
59
+ | "aria-readonly"
60
+ | "aria-required"
61
+ | "aria-selected"
62
+ | "aria-sort"
63
+ | "aria-valuemax"
64
+ | "aria-valuemin"
65
+ | "aria-valuenow"
66
+ | "aria-valuetext";
67
+ type AriaLiveRegionProperties =
68
+ | "aria-busy"
69
+ | "aria-live"
70
+ | "aria-relevant"
71
+ | "aria-atomic";
72
+ type AriaDragAndDropProperties = "aria-dropeffect" | "aria-grabbed";
73
+ type AriaRelatonshipProperties =
74
+ | "aria-activedescendant"
75
+ | "aria-colcount"
76
+ | "aria-colindex"
77
+ | "aria-colspan"
78
+ | "aria-controls"
79
+ | "aria-describedby"
80
+ | "aria-description"
81
+ | "aria-details"
82
+ | "aria-errormessage"
83
+ | "aria-flowto"
84
+ | "aria-labelledby"
85
+ | "aria-owns"
86
+ | "aria-posinset"
87
+ | "aria-rowcount"
88
+ | "aria-rowindex"
89
+ | "aria-rowspan"
90
+ | "aria-setsize";
91
+ type AriaGlobalProperties =
92
+ | "aria-atomic"
93
+ | "aria-busy"
94
+ | "aria-controls"
95
+ | "aria-current"
96
+ | "aria-describedby"
97
+ | "aria-description"
98
+ | "aria-details"
99
+ | "aria-disabled"
100
+ | "aria-dropeffect"
101
+ | "aria-errormessage"
102
+ | "aria-flowto"
103
+ | "aria-grabbed"
104
+ | "aria-haspopup"
105
+ | "aria-hidden"
106
+ | "aria-invalid"
107
+ | "aria-keyshortcuts"
108
+ | "aria-label"
109
+ | "aria-labelledby"
110
+ | "aria-live"
111
+ | "aria-owns"
112
+ | "aria-relevant"
113
+ | "aria-roledescription";
114
+ type AriaProps =
115
+ | AriaWidgetProperties
116
+ | AriaDragAndDropProperties
117
+ | AriaLiveRegionProperties
118
+ | AriaRelatonshipProperties
119
+ | AriaGlobalProperties;
120
+ type AriaBoolean = "true" | "false";
121
+ type AriaValue = Exclude<string, AriaBoolean>;
122
+ type AriaValueMap = Partial<Record<AriaProps, AriaBoolean | AriaValue>>;
123
+ type KeyedObject = Record<string | symbol | number, any>;
124
+ type HTMLTags = keyof HTMLElementTagNameMap;
125
+ type HTMLSVGTags = keyof SVGElementTagNameMap;
126
+ type YElement<K extends HTMLTags = HTMLTags> = HTMLElementTagNameMap[K];
127
+ type YSVGElement<K extends HTMLSVGTags = HTMLSVGTags> = SVGElementTagNameMap[K];
128
+
129
+ type ExcludeFunctions<T> = {
130
+ [K in keyof T as T[K] extends Function ? never : K]: T[K];
131
+ };
132
+ type Styles = Partial<CSSStyleDeclaration>;
133
+ interface ElementOverridedProperties extends AriaValueMap {
134
+ style?: Styles;
135
+ }
136
+ type AnyElement<T extends HTMLTags | HTMLSVGTags = HTMLTags> =
137
+ T extends HTMLTags
138
+ ? YElement<T>
139
+ : T extends HTMLSVGTags
140
+ ? YSVGElement<T>
141
+ : never;
142
+ type AnyProps<T extends HTMLTags | HTMLSVGTags = HTMLTags> = T extends HTMLTags
143
+ ? HTMLProps<T>
144
+ : T extends HTMLSVGTags
145
+ ? SVGProps<T>
146
+ : never;
147
+ interface Stores<T> {
148
+ get stores(): T;
149
+ }
150
+ type ElementRef<T extends HTMLTags | HTMLSVGTags = HTMLTags> = Stores<
151
+ | (T extends HTMLTags
152
+ ? HTMLElementTagNameMap[T]
153
+ : T extends HTMLSVGTags
154
+ ? SVGElementTagNameMap[T]
155
+ : never)
156
+ | undefined
157
+ >;
158
+ interface ElementProps<T extends HTMLTags | HTMLSVGTags = HTMLTags> {
159
+ ref?: ElementRef<T>;
160
+ key?: string | number | symbol;
161
+ }
162
+ type ExcludeProperties<T> = {
163
+ [K in keyof T as K extends HTMLExcludedProperties ? never : K]: T[K];
164
+ };
165
+ type HTMLProps<T extends HTMLTags> = Partial<
166
+ ExcludeProperties<ExcludeFunctions<YElement<T>>>
167
+ > &
168
+ ElementProps<T> &
169
+ ElementOverridedProperties;
170
+
171
+ type SVGAttributeValue = string | number;
172
+
173
+ type NormalizeSVGProp<T> = T extends SVGAnimatedLength
174
+ ? SVGAttributeValue
175
+ : T extends SVGAnimatedAngle
176
+ ? SVGAttributeValue
177
+ : T extends SVGAnimatedBoolean
178
+ ? SVGAttributeValue
179
+ : T extends SVGAnimatedEnumeration
180
+ ? SVGAttributeValue
181
+ : T extends SVGAnimatedInteger
182
+ ? SVGAttributeValue
183
+ : T extends SVGAnimatedNumber
184
+ ? SVGAttributeValue
185
+ : T extends SVGAnimatedPreserveAspectRatio
186
+ ? SVGAttributeValue
187
+ : T extends SVGAnimatedRect
188
+ ? SVGAttributeValue
189
+ : T extends SVGAnimatedString
190
+ ? SVGAttributeValue
191
+ : T extends SVGAnimatedTransformList
192
+ ? SVGAttributeValue
193
+ : T extends SVGPointList
194
+ ? SVGAttributeValue
195
+ : T;
196
+
197
+ type SVGRawProps<T extends HTMLSVGTags> = ExcludeProperties<
198
+ ExcludeFunctions<SVGElementTagNameMap[T]>
199
+ >;
200
+ interface SVGOverridedProperties {
201
+ fill?: string;
202
+ "fill-opacity"?: string;
203
+ stroke?: string;
204
+ "stroke-width"?: SVGAttributeValue;
205
+ "stroke-linecap"?: "butt" | "round" | "square";
206
+ "stroke-linejoin"?: "miter" | "round" | "bevel";
207
+ d?: string;
208
+ "stroke-dasharray"?: SVGAttributeValue;
209
+ }
210
+ type SVGProps<T extends HTMLSVGTags> = Partial<{
211
+ [K in keyof SVGRawProps<T>]: NormalizeSVGProp<SVGRawProps<T>[K]>;
212
+ }> &
213
+ ElementProps<T> &
214
+ ElementOverridedProperties &
215
+ SVGOverridedProperties;
216
+ type StateHandler<S extends KeyedObject | undefined = undefined> =
217
+ | S
218
+ | ((l: S) => S);
219
+
220
+ // declare abstract class Component<S extends KeyedObject | void = void> {
221
+ // protected get state(): S;
222
+ // protected setState(h: StateHandler<S extends void ? undefined : S>): void;
223
+ // public render(): ValidTemplateReturn;
224
+ // public delete(): void;
225
+ // }