@esportsplus/template 0.15.19 → 0.16.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/build/attributes.d.ts +1 -3
- package/build/attributes.js +3 -14
- package/build/constants.d.ts +2 -1
- package/build/constants.js +3 -1
- package/build/html/cache.d.ts +2 -2
- package/build/html/cache.js +23 -13
- package/build/html/hydrate.d.ts +5 -3
- package/build/html/hydrate.js +62 -40
- package/build/render.d.ts +1 -1
- package/build/slot.d.ts +9 -9
- package/build/slot.js +105 -100
- package/build/types.d.ts +8 -7
- package/package.json +2 -2
- package/src/attributes.ts +3 -19
- package/src/constants.ts +7 -0
- package/src/html/cache.ts +28 -16
- package/src/html/hydrate.ts +80 -45
- package/src/slot.ts +119 -128
- package/src/types.ts +8 -4
package/build/attributes.d.ts
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import { Attributes, Element } from './types.js';
|
|
2
|
-
declare const apply: (element: Element) => void;
|
|
3
2
|
declare const spread: (element: Element, value: Attributes | Attributes[]) => void;
|
|
4
3
|
declare const _default: {
|
|
5
|
-
apply: (element: Element) => void;
|
|
6
4
|
spread: (element: Element, value: Attributes | Attributes[]) => void;
|
|
7
5
|
};
|
|
8
6
|
export default _default;
|
|
9
|
-
export {
|
|
7
|
+
export { spread };
|
package/build/attributes.js
CHANGED
|
@@ -5,7 +5,6 @@ import { className, raf, removeAttribute, setAttribute } from './utilities.js';
|
|
|
5
5
|
import q from '@esportsplus/queue';
|
|
6
6
|
import event from './event.js';
|
|
7
7
|
const EFFECT_KEY = Symbol();
|
|
8
|
-
const HYDRATE_KEY = Symbol();
|
|
9
8
|
const STORE_KEY = Symbol();
|
|
10
9
|
const UPDATES_KEY = Symbol();
|
|
11
10
|
const STATE_HYDRATING = 0;
|
|
@@ -140,7 +139,7 @@ function update(context, id, name, value, state) {
|
|
|
140
139
|
store[name] = value;
|
|
141
140
|
}
|
|
142
141
|
if (state === STATE_HYDRATING) {
|
|
143
|
-
(context.element
|
|
142
|
+
attribute(context.element, name, value);
|
|
144
143
|
}
|
|
145
144
|
else {
|
|
146
145
|
context.updates[name] = value;
|
|
@@ -153,16 +152,6 @@ function update(context, id, name, value, state) {
|
|
|
153
152
|
}
|
|
154
153
|
}
|
|
155
154
|
}
|
|
156
|
-
const apply = (element) => {
|
|
157
|
-
let attributes = element[HYDRATE_KEY];
|
|
158
|
-
if (!attributes) {
|
|
159
|
-
return;
|
|
160
|
-
}
|
|
161
|
-
for (let key in attributes) {
|
|
162
|
-
attribute(element, key, attributes[key]);
|
|
163
|
-
}
|
|
164
|
-
delete element[HYDRATE_KEY];
|
|
165
|
-
};
|
|
166
155
|
const spread = function (element, value) {
|
|
167
156
|
let cache = (element[STORE_KEY] ??= { [UPDATES_KEY]: {} }), context = {
|
|
168
157
|
element,
|
|
@@ -184,5 +173,5 @@ const spread = function (element, value) {
|
|
|
184
173
|
}
|
|
185
174
|
}
|
|
186
175
|
};
|
|
187
|
-
export default {
|
|
188
|
-
export {
|
|
176
|
+
export default { spread };
|
|
177
|
+
export { spread };
|
package/build/constants.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
declare const EMPTY_FRAGMENT: DocumentFragment;
|
|
1
2
|
declare const NODE_CLOSING = 1;
|
|
2
3
|
declare const NODE_ELEMENT = 3;
|
|
3
4
|
declare const NODE_SLOT = 4;
|
|
@@ -11,4 +12,4 @@ declare const RENDERABLE_TEMPLATE: unique symbol;
|
|
|
11
12
|
declare const SLOT_HTML = "<!--$-->";
|
|
12
13
|
declare const SLOT_MARKER = "{{$}}";
|
|
13
14
|
declare const SLOT_MARKER_LENGTH: number;
|
|
14
|
-
export { NODE_CLOSING, NODE_ELEMENT, NODE_SLOT, NODE_VOID, NODE_WHITELIST, REGEX_EMPTY_TEXT_NODES, REGEX_SLOT_NODES, RENDERABLE, RENDERABLE_REACTIVE, RENDERABLE_TEMPLATE, SLOT_HTML, SLOT_MARKER, SLOT_MARKER_LENGTH };
|
|
15
|
+
export { EMPTY_FRAGMENT, NODE_CLOSING, NODE_ELEMENT, NODE_SLOT, NODE_VOID, NODE_WHITELIST, REGEX_EMPTY_TEXT_NODES, REGEX_SLOT_NODES, RENDERABLE, RENDERABLE_REACTIVE, RENDERABLE_TEMPLATE, SLOT_HTML, SLOT_MARKER, SLOT_MARKER_LENGTH };
|
package/build/constants.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { fragment } from './utilities.js';
|
|
2
|
+
const EMPTY_FRAGMENT = fragment('');
|
|
1
3
|
const NODE_CLOSING = 1;
|
|
2
4
|
const NODE_COMMENT = 2;
|
|
3
5
|
const NODE_ELEMENT = 3;
|
|
@@ -31,4 +33,4 @@ const RENDERABLE_TEMPLATE = Symbol();
|
|
|
31
33
|
const SLOT_HTML = '<!--$-->';
|
|
32
34
|
const SLOT_MARKER = '{{$}}';
|
|
33
35
|
const SLOT_MARKER_LENGTH = SLOT_MARKER.length;
|
|
34
|
-
export { NODE_CLOSING, NODE_ELEMENT, NODE_SLOT, NODE_VOID, NODE_WHITELIST, REGEX_EMPTY_TEXT_NODES, REGEX_SLOT_NODES, RENDERABLE, RENDERABLE_REACTIVE, RENDERABLE_TEMPLATE, SLOT_HTML, SLOT_MARKER, SLOT_MARKER_LENGTH };
|
|
36
|
+
export { EMPTY_FRAGMENT, NODE_CLOSING, NODE_ELEMENT, NODE_SLOT, NODE_VOID, NODE_WHITELIST, REGEX_EMPTY_TEXT_NODES, REGEX_SLOT_NODES, RENDERABLE, RENDERABLE_REACTIVE, RENDERABLE_TEMPLATE, SLOT_HTML, SLOT_MARKER, SLOT_MARKER_LENGTH };
|
package/build/html/cache.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Template } from '../types.js';
|
|
2
2
|
declare const _default: {
|
|
3
|
-
get:
|
|
3
|
+
get: (literals: TemplateStringsArray) => Template;
|
|
4
4
|
};
|
|
5
5
|
export default _default;
|
package/build/html/cache.js
CHANGED
|
@@ -3,8 +3,9 @@ import { firstChild, firstElementChild, fragment, nextElementSibling, nextSiblin
|
|
|
3
3
|
import { spread } from '../attributes.js';
|
|
4
4
|
import s from '../slot.js';
|
|
5
5
|
let cache = new WeakMap();
|
|
6
|
-
function build(literals
|
|
7
|
-
|
|
6
|
+
function build(literals) {
|
|
7
|
+
let n = literals.length - 1;
|
|
8
|
+
if (n === 0) {
|
|
8
9
|
return set(literals, literals[0]);
|
|
9
10
|
}
|
|
10
11
|
let buffer = '', html = literals.join(SLOT_MARKER)
|
|
@@ -13,20 +14,26 @@ function build(literals, values) {
|
|
|
13
14
|
children: 0,
|
|
14
15
|
elements: 0,
|
|
15
16
|
path: []
|
|
16
|
-
}], parsed = html.split(SLOT_MARKER), slot = 0, slots = []
|
|
17
|
+
}], parsed = html.split(SLOT_MARKER), slot = 0, slots = [];
|
|
17
18
|
for (let match of html.matchAll(REGEX_SLOT_NODES)) {
|
|
18
19
|
let parent = levels[level], type = match[1] === undefined ? NODE_SLOT : (NODE_WHITELIST[match[1].toLowerCase()] || NODE_ELEMENT);
|
|
19
20
|
if ((match.index || 1) - 1 > index) {
|
|
20
21
|
parent.children++;
|
|
21
22
|
}
|
|
22
23
|
if (type === NODE_ELEMENT || type === NODE_VOID) {
|
|
23
|
-
let attr = match[2]
|
|
24
|
+
let attr = match[2], path = parent.path.length
|
|
25
|
+
? methods(parent.elements, parent.path, firstElementChild, nextElementSibling)
|
|
26
|
+
: methods(parent.children, [], firstChild, nextSibling);
|
|
24
27
|
if (attr) {
|
|
25
|
-
let i = attr.indexOf(SLOT_MARKER),
|
|
28
|
+
let i = attr.indexOf(SLOT_MARKER), p = {
|
|
29
|
+
absolute: path,
|
|
30
|
+
parent: parent.path,
|
|
31
|
+
relative: path.slice(parent.path.length)
|
|
32
|
+
};
|
|
26
33
|
while (i !== -1) {
|
|
27
34
|
slots.push({
|
|
28
35
|
fn: spread,
|
|
29
|
-
path,
|
|
36
|
+
path: p,
|
|
30
37
|
slot
|
|
31
38
|
});
|
|
32
39
|
buffer += parsed[slot++];
|
|
@@ -37,22 +44,25 @@ function build(literals, values) {
|
|
|
37
44
|
levels[++level] = {
|
|
38
45
|
children: 0,
|
|
39
46
|
elements: 0,
|
|
40
|
-
path
|
|
41
|
-
? methods(parent.elements, parent.path, firstElementChild, nextElementSibling)
|
|
42
|
-
: methods(parent.children, [], firstChild, nextSibling)
|
|
47
|
+
path
|
|
43
48
|
};
|
|
44
49
|
}
|
|
45
50
|
parent.elements++;
|
|
46
51
|
}
|
|
47
52
|
else if (type === NODE_SLOT) {
|
|
53
|
+
let relative = methods(parent.children, [], firstChild, nextSibling);
|
|
48
54
|
buffer += parsed[slot] + SLOT_HTML;
|
|
49
55
|
slots.push({
|
|
50
56
|
fn: s,
|
|
51
|
-
path:
|
|
57
|
+
path: {
|
|
58
|
+
absolute: [...parent.path, ...relative],
|
|
59
|
+
parent: parent.path,
|
|
60
|
+
relative
|
|
61
|
+
},
|
|
52
62
|
slot: slot++
|
|
53
63
|
});
|
|
54
64
|
}
|
|
55
|
-
if (slot ===
|
|
65
|
+
if (slot === n) {
|
|
56
66
|
buffer += parsed[slot];
|
|
57
67
|
break;
|
|
58
68
|
}
|
|
@@ -84,7 +94,7 @@ function set(literals, html, slots = null) {
|
|
|
84
94
|
cache.set(literals, template);
|
|
85
95
|
return template;
|
|
86
96
|
}
|
|
87
|
-
const get = (
|
|
88
|
-
return cache.get(literals) || build(literals
|
|
97
|
+
const get = (literals) => {
|
|
98
|
+
return cache.get(literals) || build(literals);
|
|
89
99
|
};
|
|
90
100
|
export default { get };
|
package/build/html/hydrate.d.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Elements, Fragment, RenderableReactive, RenderableTemplate } from '../types.js';
|
|
2
2
|
import { Slot } from '../slot.js';
|
|
3
|
+
declare function reactive<T>(elements: Elements[], fragment: Fragment, renderable: RenderableReactive<T>, slot: Slot): void;
|
|
4
|
+
declare function hydrate<T>(elements: Elements[] | null, fragment: Fragment, renderable: RenderableTemplate<T>): void;
|
|
3
5
|
declare const _default: {
|
|
4
|
-
reactive:
|
|
5
|
-
static:
|
|
6
|
+
reactive: typeof reactive;
|
|
7
|
+
static: typeof hydrate;
|
|
6
8
|
};
|
|
7
9
|
export default _default;
|
package/build/html/hydrate.js
CHANGED
|
@@ -1,63 +1,85 @@
|
|
|
1
1
|
import { root } from '@esportsplus/reactivity';
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import { EMPTY_FRAGMENT } from '../constants.js';
|
|
3
|
+
import { cloneNode } from '../utilities.js';
|
|
4
4
|
import cache from './cache.js';
|
|
5
|
-
function reactive(renderable, slot) {
|
|
5
|
+
function reactive(elements, fragment, renderable, slot) {
|
|
6
6
|
let array = renderable.values, factory = renderable.template, refresh = () => {
|
|
7
|
-
|
|
7
|
+
root(() => array.map(template));
|
|
8
|
+
slot.clear();
|
|
9
|
+
slot.anchor().after(fragment);
|
|
10
|
+
slot.nodes = elements;
|
|
11
|
+
reset();
|
|
12
|
+
}, reset = () => {
|
|
13
|
+
elements = [];
|
|
14
|
+
fragment = cloneNode.call(EMPTY_FRAGMENT);
|
|
8
15
|
}, template = function (data, i) {
|
|
9
|
-
|
|
10
|
-
return hydrate(renderable, cache.get(renderable));
|
|
16
|
+
hydrate(elements, fragment, factory.call(this, data, i));
|
|
11
17
|
};
|
|
12
|
-
array.on('
|
|
13
|
-
|
|
14
|
-
});
|
|
15
|
-
array.on('push', ({ items }) => {
|
|
16
|
-
slot.push(...root(() => array.map(template, array.length - items.length)));
|
|
17
|
-
});
|
|
18
|
+
array.on('clear', () => slot.clear());
|
|
19
|
+
array.on('pop', () => slot.pop());
|
|
18
20
|
array.on('reverse', refresh);
|
|
19
|
-
array.on('shift', () =>
|
|
20
|
-
slot.shift();
|
|
21
|
-
});
|
|
21
|
+
array.on('shift', () => slot.shift());
|
|
22
22
|
array.on('sort', refresh);
|
|
23
|
+
array.on('push', ({ items }) => {
|
|
24
|
+
let anchor = slot.anchor();
|
|
25
|
+
elements = slot.nodes;
|
|
26
|
+
root(() => array.map(template, array.length - items.length));
|
|
27
|
+
anchor.after(fragment);
|
|
28
|
+
reset();
|
|
29
|
+
});
|
|
23
30
|
array.on('splice', ({ deleteCount: d, items: i, start: s }) => {
|
|
24
|
-
|
|
31
|
+
if (array.length === 0) {
|
|
32
|
+
slot.clear();
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
root(() => array.map(template, s, i.length));
|
|
36
|
+
slot.splice(s, d, fragment, ...elements);
|
|
37
|
+
reset();
|
|
25
38
|
});
|
|
26
39
|
array.on('unshift', ({ items }) => {
|
|
27
|
-
|
|
40
|
+
root(() => array.map(template, 0, items.length));
|
|
41
|
+
slot.unshift(fragment, ...elements);
|
|
42
|
+
reset();
|
|
28
43
|
});
|
|
29
|
-
|
|
44
|
+
root(() => array.map(template));
|
|
45
|
+
reset();
|
|
30
46
|
}
|
|
31
|
-
function hydrate(
|
|
32
|
-
let
|
|
47
|
+
function hydrate(elements, fragment, renderable) {
|
|
48
|
+
let { fragment: frag, slots } = cache.get(renderable.literals), clone = cloneNode.call(frag, true);
|
|
33
49
|
if (slots !== null) {
|
|
34
|
-
let node,
|
|
35
|
-
for (let i = slots.length
|
|
36
|
-
let { fn, path, slot } = slots[i];
|
|
37
|
-
if (
|
|
38
|
-
if (
|
|
39
|
-
|
|
50
|
+
let node, nodePath, parent, parentPath, values = renderable.values;
|
|
51
|
+
for (let i = 0, n = slots.length; i < n; i++) {
|
|
52
|
+
let { fn, path, slot } = slots[i], pp = path.parent, pr = path.relative;
|
|
53
|
+
if (pp !== parentPath) {
|
|
54
|
+
if (pp === nodePath) {
|
|
55
|
+
parent = node;
|
|
56
|
+
parentPath = nodePath;
|
|
57
|
+
nodePath = undefined;
|
|
40
58
|
}
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
59
|
+
else {
|
|
60
|
+
parent = clone;
|
|
61
|
+
parentPath = pp;
|
|
62
|
+
for (let o = 0, j = pp.length; o < j; o++) {
|
|
63
|
+
parent = pp[o].call(parent);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
if (pr !== nodePath) {
|
|
68
|
+
node = parent;
|
|
69
|
+
nodePath = path.absolute;
|
|
70
|
+
for (let o = 0, j = pr.length; o < j; o++) {
|
|
71
|
+
node = pr[o].call(node);
|
|
45
72
|
}
|
|
46
73
|
}
|
|
47
74
|
fn(node, values[slot]);
|
|
48
75
|
}
|
|
49
|
-
apply(node);
|
|
50
76
|
}
|
|
51
|
-
|
|
52
|
-
elements.push(
|
|
77
|
+
if (elements) {
|
|
78
|
+
elements.push([...clone.childNodes]);
|
|
53
79
|
}
|
|
54
|
-
|
|
80
|
+
fragment.appendChild(clone);
|
|
55
81
|
}
|
|
56
82
|
export default {
|
|
57
|
-
reactive
|
|
58
|
-
|
|
59
|
-
},
|
|
60
|
-
static: (renderable) => {
|
|
61
|
-
return hydrate(renderable, renderable.template || (renderable.template = cache.get(renderable)));
|
|
62
|
-
}
|
|
83
|
+
reactive,
|
|
84
|
+
static: hydrate
|
|
63
85
|
};
|
package/build/render.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import { Slot } from './slot.js';
|
|
2
2
|
import { Renderable } from './types.js';
|
|
3
|
-
declare const _default: (renderable: Renderable, parent: HTMLElement | Slot) => Slot;
|
|
3
|
+
declare const _default: (renderable: Renderable, parent: HTMLElement | Slot) => void | Slot;
|
|
4
4
|
export default _default;
|
package/build/slot.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Element, Elements,
|
|
1
|
+
import { Element, Elements, Fragment } from './types.js';
|
|
2
2
|
declare class Slot {
|
|
3
3
|
marker: Element;
|
|
4
4
|
nodes: Elements[];
|
|
@@ -7,15 +7,15 @@ declare class Slot {
|
|
|
7
7
|
get length(): number;
|
|
8
8
|
set length(n: number);
|
|
9
9
|
anchor(index?: number): Element;
|
|
10
|
-
clear():
|
|
11
|
-
pop():
|
|
12
|
-
push(...
|
|
13
|
-
render(input: unknown): this;
|
|
14
|
-
shift():
|
|
15
|
-
splice(start: number, stop?: number, ...
|
|
16
|
-
unshift(...
|
|
10
|
+
clear(): this;
|
|
11
|
+
pop(): this;
|
|
12
|
+
push(fragment: Fragment, ...nodes: Elements[]): this;
|
|
13
|
+
render(input: unknown, state?: number): this;
|
|
14
|
+
shift(): this;
|
|
15
|
+
splice(start: number, stop?: number, fragment?: Fragment, ...nodes: Elements[]): this;
|
|
16
|
+
unshift(fragment: Fragment, ...nodes: Elements[]): this;
|
|
17
17
|
}
|
|
18
18
|
declare const ondisconnect: (element: Element, fn: VoidFunction) => void;
|
|
19
|
-
declare const _default: (marker: Element, value: unknown) =>
|
|
19
|
+
declare const _default: (marker: Element, value: unknown) => void;
|
|
20
20
|
export default _default;
|
|
21
21
|
export { ondisconnect, Slot };
|
package/build/slot.js
CHANGED
|
@@ -1,37 +1,20 @@
|
|
|
1
|
-
import { effect
|
|
2
|
-
import { isArray,
|
|
3
|
-
import { RENDERABLE, RENDERABLE_REACTIVE } from './constants.js';
|
|
1
|
+
import { effect } from '@esportsplus/reactivity';
|
|
2
|
+
import { isArray, isInstanceOf } from '@esportsplus/utilities';
|
|
3
|
+
import { EMPTY_FRAGMENT, RENDERABLE, RENDERABLE_REACTIVE } from './constants.js';
|
|
4
4
|
import { hydrate } from './html/index.js';
|
|
5
|
-
import { append, cloneNode,
|
|
5
|
+
import { append, cloneNode, microtask, nodeValue, raf, text } from './utilities.js';
|
|
6
6
|
import queue from '@esportsplus/queue';
|
|
7
7
|
const CLEANUP_KEY = Symbol();
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
if (n === 1) {
|
|
16
|
-
elements.push(groups[0].elements);
|
|
17
|
-
}
|
|
18
|
-
else {
|
|
19
|
-
for (let i = 1; i < n; i++) {
|
|
20
|
-
let { elements: e, fragment: f } = groups[i];
|
|
21
|
-
append.call(fragment, f);
|
|
22
|
-
elements.push(e);
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
anchor.after(fragment);
|
|
26
|
-
return elements;
|
|
27
|
-
}
|
|
28
|
-
function remove(...groups) {
|
|
29
|
-
for (let i = 0, n = groups.length; i < n; i++) {
|
|
30
|
-
let group = groups[i];
|
|
31
|
-
for (let j = 0, o = group.length; j < o; j++) {
|
|
32
|
-
let item = group[j];
|
|
8
|
+
const CONNECTED = 0;
|
|
9
|
+
const HYDRATING = 1;
|
|
10
|
+
let cleanup = queue(64), scheduled = false;
|
|
11
|
+
function remove(groups) {
|
|
12
|
+
let group, item;
|
|
13
|
+
while (group = groups.pop()) {
|
|
14
|
+
while (item = group.pop()) {
|
|
33
15
|
if (CLEANUP_KEY in item) {
|
|
34
16
|
cleanup.add(item[CLEANUP_KEY]);
|
|
17
|
+
item[CLEANUP_KEY] = null;
|
|
35
18
|
}
|
|
36
19
|
item.remove();
|
|
37
20
|
}
|
|
@@ -39,51 +22,47 @@ function remove(...groups) {
|
|
|
39
22
|
if (!scheduled && cleanup.length) {
|
|
40
23
|
schedule();
|
|
41
24
|
}
|
|
42
|
-
return groups;
|
|
43
25
|
}
|
|
44
|
-
function render(elements, fragment, input, slot) {
|
|
26
|
+
function render(anchor, elements, fragment, input, slot) {
|
|
45
27
|
if (input === false || input == null || input === '') {
|
|
46
28
|
return;
|
|
47
29
|
}
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
render(elements, fragment, input[i]);
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
else if (isObject(input) && RENDERABLE in input) {
|
|
30
|
+
let type = typeof input;
|
|
31
|
+
if (type === 'object' && RENDERABLE in input) {
|
|
54
32
|
if (input[RENDERABLE] === RENDERABLE_REACTIVE) {
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
let { elements: e, fragment: f } = response[i];
|
|
58
|
-
append.call(fragment, f);
|
|
59
|
-
elements.push(e);
|
|
60
|
-
}
|
|
33
|
+
slot ??= new Slot(anchor);
|
|
34
|
+
hydrate.reactive(slot.nodes, fragment, input, slot);
|
|
61
35
|
}
|
|
62
36
|
else {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
37
|
+
hydrate.static(elements, fragment, input);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
else if (type === 'string' || type === 'number') {
|
|
41
|
+
let element = text(type === 'string' ? input : String(input));
|
|
42
|
+
if (slot) {
|
|
43
|
+
slot.text = element;
|
|
44
|
+
}
|
|
45
|
+
append.call(fragment, element);
|
|
46
|
+
if (elements) {
|
|
47
|
+
elements.push([element]);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
else if (isArray(input)) {
|
|
51
|
+
for (let i = 0, n = input.length; i < n; i++) {
|
|
52
|
+
render(anchor, elements, fragment, input[i], slot);
|
|
66
53
|
}
|
|
67
54
|
}
|
|
68
55
|
else if (isInstanceOf(input, NodeList)) {
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
56
|
+
append.call(fragment, ...input);
|
|
57
|
+
if (elements) {
|
|
58
|
+
elements.push([...input]);
|
|
72
59
|
}
|
|
73
|
-
append.call(fragment, ...e);
|
|
74
|
-
elements.push(e);
|
|
75
60
|
}
|
|
76
61
|
else if (isInstanceOf(input, Node)) {
|
|
77
62
|
append.call(fragment, input);
|
|
78
|
-
elements
|
|
79
|
-
|
|
80
|
-
else {
|
|
81
|
-
let element = text(typeof input === 'string' ? input : String(input));
|
|
82
|
-
if (slot) {
|
|
83
|
-
slot.text = element;
|
|
63
|
+
if (elements) {
|
|
64
|
+
elements.push([input]);
|
|
84
65
|
}
|
|
85
|
-
append.call(fragment, element);
|
|
86
|
-
elements.push([element]);
|
|
87
66
|
}
|
|
88
67
|
}
|
|
89
68
|
function schedule() {
|
|
@@ -121,79 +100,105 @@ class Slot {
|
|
|
121
100
|
return this.nodes.length;
|
|
122
101
|
}
|
|
123
102
|
set length(n) {
|
|
124
|
-
this.
|
|
103
|
+
if (n >= this.nodes.length) {
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
else if (n === 0) {
|
|
107
|
+
this.clear();
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
this.splice(n);
|
|
111
|
+
}
|
|
125
112
|
}
|
|
126
113
|
anchor(index = this.nodes.length - 1) {
|
|
127
|
-
let
|
|
128
|
-
|
|
129
|
-
node = nodes[nodes.length - 1];
|
|
130
|
-
}
|
|
131
|
-
return node || this.marker;
|
|
114
|
+
let nodes = this.nodes[index];
|
|
115
|
+
return nodes ? nodes[nodes.length - 1] : this.marker;
|
|
132
116
|
}
|
|
133
117
|
clear() {
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
118
|
+
if (this.text) {
|
|
119
|
+
this.nodes.push([this.text]);
|
|
120
|
+
this.text = null;
|
|
121
|
+
}
|
|
122
|
+
remove(this.nodes);
|
|
123
|
+
return this;
|
|
137
124
|
}
|
|
138
125
|
pop() {
|
|
139
126
|
let group = this.nodes.pop();
|
|
140
|
-
if (
|
|
141
|
-
|
|
127
|
+
if (group) {
|
|
128
|
+
remove([group]);
|
|
142
129
|
}
|
|
143
|
-
return
|
|
130
|
+
return this;
|
|
144
131
|
}
|
|
145
|
-
push(...
|
|
146
|
-
|
|
132
|
+
push(fragment, ...nodes) {
|
|
133
|
+
this.anchor().after(fragment);
|
|
134
|
+
this.nodes.push(...nodes);
|
|
135
|
+
return this;
|
|
147
136
|
}
|
|
148
|
-
render(input) {
|
|
149
|
-
|
|
137
|
+
render(input, state = HYDRATING) {
|
|
138
|
+
let type = typeof input;
|
|
139
|
+
if (type === 'function') {
|
|
150
140
|
ondisconnect(this.marker, effect(() => {
|
|
151
141
|
let v = input();
|
|
152
|
-
if (
|
|
153
|
-
|
|
142
|
+
if (state === HYDRATING) {
|
|
143
|
+
this.render(v, state);
|
|
144
|
+
state = CONNECTED;
|
|
154
145
|
}
|
|
155
|
-
else {
|
|
146
|
+
else if (state === CONNECTED) {
|
|
156
147
|
raf.add(() => {
|
|
157
|
-
this.render(v);
|
|
148
|
+
this.render(v, state);
|
|
158
149
|
});
|
|
159
150
|
}
|
|
160
151
|
}));
|
|
161
152
|
return this;
|
|
162
153
|
}
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
154
|
+
let text = this.text;
|
|
155
|
+
if (text && text.isConnected && (input == null || type !== 'object')) {
|
|
156
|
+
nodeValue.call(text, (type === 'number' || type === 'string') ? input : '');
|
|
157
|
+
}
|
|
158
|
+
else {
|
|
159
|
+
this.clear();
|
|
160
|
+
let fragment = cloneNode.call(EMPTY_FRAGMENT);
|
|
161
|
+
render(this.marker, this.nodes, fragment, input, this);
|
|
162
|
+
this.marker.after(fragment);
|
|
171
163
|
}
|
|
172
|
-
this.clear();
|
|
173
|
-
let fragment = cloneNode.call(template), nodes = [];
|
|
174
|
-
render(nodes, fragment, input, this);
|
|
175
|
-
this.marker.after(fragment);
|
|
176
|
-
this.nodes = nodes;
|
|
177
164
|
return this;
|
|
178
165
|
}
|
|
179
166
|
shift() {
|
|
180
167
|
let group = this.nodes.shift();
|
|
181
|
-
if (
|
|
182
|
-
|
|
168
|
+
if (group) {
|
|
169
|
+
remove([group]);
|
|
183
170
|
}
|
|
184
|
-
return
|
|
171
|
+
return this;
|
|
185
172
|
}
|
|
186
|
-
splice(start, stop = this.nodes.length, ...
|
|
187
|
-
|
|
173
|
+
splice(start, stop = this.nodes.length, fragment, ...nodes) {
|
|
174
|
+
if (!fragment) {
|
|
175
|
+
remove(this.nodes.splice(start, stop));
|
|
176
|
+
}
|
|
177
|
+
else {
|
|
178
|
+
this.anchor(start).after(fragment);
|
|
179
|
+
remove(this.nodes.splice(start, stop, ...nodes));
|
|
180
|
+
}
|
|
181
|
+
return this;
|
|
188
182
|
}
|
|
189
|
-
unshift(...
|
|
190
|
-
|
|
183
|
+
unshift(fragment, ...nodes) {
|
|
184
|
+
this.marker.after(fragment);
|
|
185
|
+
this.nodes.unshift(...nodes);
|
|
186
|
+
return this;
|
|
191
187
|
}
|
|
192
188
|
}
|
|
193
189
|
const ondisconnect = (element, fn) => {
|
|
194
190
|
(element[CLEANUP_KEY] ??= []).push(fn);
|
|
195
191
|
};
|
|
196
192
|
export default (marker, value) => {
|
|
197
|
-
|
|
193
|
+
let type = typeof value;
|
|
194
|
+
if (type === 'function') {
|
|
195
|
+
new Slot(marker).render(value);
|
|
196
|
+
}
|
|
197
|
+
else {
|
|
198
|
+
let fragment = cloneNode.call(EMPTY_FRAGMENT);
|
|
199
|
+
render(marker, null, fragment, value);
|
|
200
|
+
marker.after(fragment);
|
|
201
|
+
}
|
|
202
|
+
;
|
|
198
203
|
};
|
|
199
204
|
export { ondisconnect, Slot };
|
package/build/types.d.ts
CHANGED
|
@@ -20,10 +20,7 @@ type Effect<T> = () => EffectResponse<T>;
|
|
|
20
20
|
type EffectResponse<T> = T extends [] ? EffectResponse<T[number]>[] : Primitive | Renderable<T>;
|
|
21
21
|
type Element = HTMLElement & Attributes & Record<PropertyKey, unknown>;
|
|
22
22
|
type Elements = Element[];
|
|
23
|
-
type
|
|
24
|
-
elements: Elements;
|
|
25
|
-
fragment: DocumentFragment | Node;
|
|
26
|
-
};
|
|
23
|
+
type Fragment = DocumentFragment | Node;
|
|
27
24
|
type Primitive = bigint | boolean | null | number | string | undefined;
|
|
28
25
|
type Renderable<T = unknown> = RenderableReactive<T> | RenderableTemplate<T>;
|
|
29
26
|
type RenderableReactive<T = unknown> = Readonly<{
|
|
@@ -32,7 +29,7 @@ type RenderableReactive<T = unknown> = Readonly<{
|
|
|
32
29
|
template: (this: ThisParameterType<Parameters<ReactiveArray<T>['map']>[0]>, ...args: Parameters<Parameters<ReactiveArray<T>['map']>[0]>) => RenderableTemplate<T>;
|
|
33
30
|
values: ReactiveArray<T>;
|
|
34
31
|
}>;
|
|
35
|
-
type RenderableTemplate<T> = {
|
|
32
|
+
type RenderableTemplate<T = unknown> = {
|
|
36
33
|
[RENDERABLE]: typeof RENDERABLE_TEMPLATE;
|
|
37
34
|
literals: TemplateStringsArray;
|
|
38
35
|
template: Template | null;
|
|
@@ -45,8 +42,12 @@ type Template = {
|
|
|
45
42
|
literals: TemplateStringsArray;
|
|
46
43
|
slots: {
|
|
47
44
|
fn: typeof attributes.spread | typeof slot;
|
|
48
|
-
path:
|
|
45
|
+
path: {
|
|
46
|
+
absolute: typeof firstChild[];
|
|
47
|
+
parent: typeof firstChild[];
|
|
48
|
+
relative: typeof firstChild[];
|
|
49
|
+
};
|
|
49
50
|
slot: number;
|
|
50
51
|
}[] | null;
|
|
51
52
|
};
|
|
52
|
-
export type { Attributes, Effect, Element, Elements,
|
|
53
|
+
export type { Attributes, Effect, Element, Elements, Fragment, Renderable, RenderableReactive, RenderableTemplate, RenderableValue, Template };
|