@esportsplus/template 0.12.12 → 0.14.0
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.
Potentially problematic release.
This version of @esportsplus/template might be problematic. Click here for more details.
- package/build/attributes.d.ts +3 -1
- package/build/attributes.js +37 -40
- package/build/constants.d.ts +3 -5
- package/build/constants.js +3 -5
- package/build/event.d.ts +1 -1
- package/build/event.js +53 -28
- package/build/html/cache.js +14 -70
- package/build/html/hydrate.js +6 -4
- package/build/slot.d.ts +2 -2
- package/build/slot.js +31 -34
- package/build/types.d.ts +7 -4
- package/build/types.js +1 -1
- package/package.json +2 -2
- package/src/attributes.ts +45 -44
- package/src/constants.ts +7 -14
- package/src/event.ts +76 -37
- package/src/html/cache.ts +16 -88
- package/src/html/hydrate.ts +6 -4
- package/src/slot.ts +38 -44
- package/src/types.ts +9 -4
package/build/attributes.d.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { Attributes, Element } from './types.js';
|
|
2
|
+
declare const apply: (element: Element) => void;
|
|
3
|
+
declare const spread: (element: Element, attributes: Attributes | Attributes[]) => void;
|
|
2
4
|
declare const _default: {
|
|
3
5
|
apply: (element: Element) => void;
|
|
4
|
-
set: (element: Element, value: unknown, name: string) => void;
|
|
5
6
|
spread: (element: Element, attributes: Attributes | Attributes[]) => void;
|
|
6
7
|
};
|
|
7
8
|
export default _default;
|
|
9
|
+
export { apply, spread };
|
package/build/attributes.js
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import { effect, root } from '@esportsplus/reactivity';
|
|
2
|
-
import { ATTRIBUTES } from './constants.js';
|
|
3
2
|
import { className, isArray, isObject, raf, removeAttribute, setAttribute } from './utilities.js';
|
|
4
3
|
import event from './event.js';
|
|
5
4
|
let attributes = {}, delimiters = {
|
|
6
5
|
class: ' ',
|
|
7
6
|
style: ';'
|
|
8
|
-
};
|
|
7
|
+
}, key = Symbol();
|
|
9
8
|
function attribute(element, name, value) {
|
|
10
9
|
if (value === false || value == null) {
|
|
11
10
|
value = '';
|
|
@@ -45,12 +44,22 @@ function reactive(element, id, name, value, wait = false) {
|
|
|
45
44
|
}
|
|
46
45
|
}
|
|
47
46
|
function set(element, value, name) {
|
|
48
|
-
if (
|
|
47
|
+
if (name === 'style' && isObject(value)) {
|
|
48
|
+
for (let key in value) {
|
|
49
|
+
set(element, value[key], name);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
else if (isArray(value)) {
|
|
53
|
+
for (let i = 0, n = value.length; i < n; i++) {
|
|
54
|
+
set(element, value[i], name);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
else if (typeof value === 'function') {
|
|
49
58
|
if (name.startsWith('on')) {
|
|
50
59
|
event(element, name, value);
|
|
51
60
|
}
|
|
52
61
|
else {
|
|
53
|
-
reactive(element, ('e' + store(element)[
|
|
62
|
+
reactive(element, ('e' + store(element)[key]++), name, value, true);
|
|
54
63
|
}
|
|
55
64
|
}
|
|
56
65
|
else {
|
|
@@ -58,7 +67,7 @@ function set(element, value, name) {
|
|
|
58
67
|
}
|
|
59
68
|
}
|
|
60
69
|
function store(element) {
|
|
61
|
-
return (element[
|
|
70
|
+
return (element[key] || (element[key] = { [key]: 0 }));
|
|
62
71
|
}
|
|
63
72
|
function update(element, id, name, value, wait = false) {
|
|
64
73
|
if (value === false || value == null) {
|
|
@@ -119,44 +128,32 @@ function update(element, id, name, value, wait = false) {
|
|
|
119
128
|
attribute(element, name, value);
|
|
120
129
|
}
|
|
121
130
|
}
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
set(element, value[key], name);
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
else if (isArray(value)) {
|
|
136
|
-
for (let i = 0, n = value.length; i < n; i++) {
|
|
137
|
-
set(element, value[i], name);
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
else {
|
|
141
|
-
set(element, value, name);
|
|
131
|
+
const apply = (element) => {
|
|
132
|
+
for (let key in attributes) {
|
|
133
|
+
attribute(element, key, attributes[key]);
|
|
134
|
+
}
|
|
135
|
+
attributes = {};
|
|
136
|
+
};
|
|
137
|
+
const spread = function (element, attributes) {
|
|
138
|
+
if (isObject(attributes)) {
|
|
139
|
+
for (let name in attributes) {
|
|
140
|
+
set(element, attributes[name], name);
|
|
142
141
|
}
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
142
|
+
}
|
|
143
|
+
else if (isArray(attributes)) {
|
|
144
|
+
for (let i = 0, n = attributes.length; i < n; i++) {
|
|
145
|
+
let attrs = attributes[i];
|
|
146
|
+
if (!isObject(attrs)) {
|
|
147
|
+
continue;
|
|
148
148
|
}
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
for (let i = 0, n = attributes.length; i < n; i++) {
|
|
152
|
-
let attrs = attributes[i];
|
|
153
|
-
if (!isObject(attrs)) {
|
|
154
|
-
continue;
|
|
155
|
-
}
|
|
156
|
-
for (let name in attrs) {
|
|
157
|
-
this.set(element, attrs[name], name);
|
|
158
|
-
}
|
|
149
|
+
for (let name in attrs) {
|
|
150
|
+
set(element, attrs[name], name);
|
|
159
151
|
}
|
|
160
152
|
}
|
|
161
153
|
}
|
|
154
|
+
else {
|
|
155
|
+
throw new Error('@esportsplus/template: attributes must be of type `Attributes` or `Attributes[]`; Received ' + JSON.stringify(attributes));
|
|
156
|
+
}
|
|
162
157
|
};
|
|
158
|
+
export default { apply, spread };
|
|
159
|
+
export { apply, spread };
|
package/build/constants.d.ts
CHANGED
|
@@ -1,18 +1,16 @@
|
|
|
1
|
-
declare const ATTRIBUTES: unique symbol;
|
|
2
1
|
declare const NODE_CLOSING = 1;
|
|
3
2
|
declare const NODE_ELEMENT = 3;
|
|
4
3
|
declare const NODE_SLOT = 4;
|
|
5
4
|
declare const NODE_VOID = 5;
|
|
6
5
|
declare const NODE_WHITELIST: Record<string, number>;
|
|
7
6
|
declare const REGEX_EMPTY_TEXT_NODES: RegExp;
|
|
8
|
-
declare const REGEX_EVENTS: RegExp;
|
|
9
|
-
declare const REGEX_EXTRA_WHITESPACE: RegExp;
|
|
10
|
-
declare const REGEX_SLOT_ATTRIBUTES: RegExp;
|
|
11
7
|
declare const REGEX_SLOT_NODES: RegExp;
|
|
12
8
|
declare const RENDERABLE: unique symbol;
|
|
13
9
|
declare const RENDERABLE_REACTIVE: unique symbol;
|
|
14
10
|
declare const RENDERABLE_TEMPLATE: unique symbol;
|
|
15
11
|
declare const SLOT: unique symbol;
|
|
12
|
+
declare const SLOT_CLEANUP: unique symbol;
|
|
16
13
|
declare const SLOT_HTML = "<!--$-->";
|
|
17
14
|
declare const SLOT_MARKER = "{{$}}";
|
|
18
|
-
|
|
15
|
+
declare const SLOT_MARKER_LENGTH: number;
|
|
16
|
+
export { NODE_CLOSING, NODE_ELEMENT, NODE_SLOT, NODE_VOID, NODE_WHITELIST, REGEX_EMPTY_TEXT_NODES, REGEX_SLOT_NODES, RENDERABLE, RENDERABLE_REACTIVE, RENDERABLE_TEMPLATE, SLOT, SLOT_CLEANUP, SLOT_HTML, SLOT_MARKER, SLOT_MARKER_LENGTH };
|
package/build/constants.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
const ATTRIBUTES = Symbol();
|
|
2
1
|
const NODE_CLOSING = 1;
|
|
3
2
|
const NODE_COMMENT = 2;
|
|
4
3
|
const NODE_ELEMENT = 3;
|
|
@@ -25,14 +24,13 @@ const NODE_WHITELIST = {
|
|
|
25
24
|
'wbr': NODE_VOID
|
|
26
25
|
};
|
|
27
26
|
const REGEX_EMPTY_TEXT_NODES = /(>|})\s+(<|{)/g;
|
|
28
|
-
const REGEX_EVENTS = /(?:\s*on[\w-:]+\s*=\s*["'][^"']*["'])/g;
|
|
29
|
-
const REGEX_EXTRA_WHITESPACE = /\s\s+/g;
|
|
30
|
-
const REGEX_SLOT_ATTRIBUTES = /<[\w-]+([^><]*{{\$}}[^><]*)>/g;
|
|
31
27
|
const REGEX_SLOT_NODES = /<([\w-]+|[\/!])(?:([^><]*{{\$}}[^><]*)|(?:[^><]*))?>|{{\$}}/g;
|
|
32
28
|
const RENDERABLE = Symbol();
|
|
33
29
|
const RENDERABLE_REACTIVE = Symbol();
|
|
34
30
|
const RENDERABLE_TEMPLATE = Symbol();
|
|
35
31
|
const SLOT = Symbol();
|
|
32
|
+
const SLOT_CLEANUP = Symbol();
|
|
36
33
|
const SLOT_HTML = '<!--$-->';
|
|
37
34
|
const SLOT_MARKER = '{{$}}';
|
|
38
|
-
|
|
35
|
+
const SLOT_MARKER_LENGTH = SLOT_MARKER.length;
|
|
36
|
+
export { NODE_CLOSING, NODE_ELEMENT, NODE_SLOT, NODE_VOID, NODE_WHITELIST, REGEX_EMPTY_TEXT_NODES, REGEX_SLOT_NODES, RENDERABLE, RENDERABLE_REACTIVE, RENDERABLE_TEMPLATE, SLOT, SLOT_CLEANUP, SLOT_HTML, SLOT_MARKER, SLOT_MARKER_LENGTH };
|
package/build/event.d.ts
CHANGED
package/build/event.js
CHANGED
|
@@ -1,33 +1,15 @@
|
|
|
1
1
|
import { root } from '@esportsplus/reactivity';
|
|
2
|
+
import { SLOT_CLEANUP } from './constants.js';
|
|
2
3
|
import { addEventListener, defineProperty, parentElement } from './utilities.js';
|
|
3
|
-
let capture = new Set(['
|
|
4
|
-
'
|
|
5
|
-
'
|
|
6
|
-
'
|
|
7
|
-
'
|
|
4
|
+
let capture = new Set(['onblur', 'onfocus', 'onscroll']), controllers = new Map(), keys = {}, passive = new Set([
|
|
5
|
+
'onmousedown', 'onmouseenter', 'onmouseleave', 'onmousemove', 'onmouseout', 'onmouseover', 'onmouseup', 'onmousewheel',
|
|
6
|
+
'onscroll',
|
|
7
|
+
'ontouchcancel', 'ontouchend', 'ontouchleave', 'ontouchmove', 'ontouchstart',
|
|
8
|
+
'onwheel'
|
|
8
9
|
]);
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
let node = e.target;
|
|
13
|
-
defineProperty(e, 'currentTarget', {
|
|
14
|
-
configurable: true,
|
|
15
|
-
get() {
|
|
16
|
-
return node || window.document;
|
|
17
|
-
}
|
|
18
|
-
});
|
|
19
|
-
while (node) {
|
|
20
|
-
if (key in node) {
|
|
21
|
-
return node[key].call(node, e);
|
|
22
|
-
}
|
|
23
|
-
node = parentElement.call(node);
|
|
24
|
-
}
|
|
25
|
-
}, {
|
|
26
|
-
capture: capture.has(type),
|
|
27
|
-
passive: passive.has(type)
|
|
28
|
-
});
|
|
29
|
-
return key;
|
|
30
|
-
}
|
|
10
|
+
['onmousemove', 'onmousewheel', 'onscroll', 'ontouchend', 'ontouchmove', 'ontouchstart', 'onwheel'].map(event => {
|
|
11
|
+
controllers.set(event, null);
|
|
12
|
+
});
|
|
31
13
|
export default (element, event, listener) => {
|
|
32
14
|
if (event === 'onmount') {
|
|
33
15
|
let interval = setInterval(() => {
|
|
@@ -45,5 +27,48 @@ export default (element, event, listener) => {
|
|
|
45
27
|
else if (event === 'onrender') {
|
|
46
28
|
return root(() => listener(element));
|
|
47
29
|
}
|
|
48
|
-
|
|
30
|
+
let controller = controllers.get(event), signal;
|
|
31
|
+
if (controller === null) {
|
|
32
|
+
let { abort, signal } = new AbortController();
|
|
33
|
+
controllers.set(event, controller = {
|
|
34
|
+
abort,
|
|
35
|
+
signal,
|
|
36
|
+
listeners: 0,
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
if (controller) {
|
|
40
|
+
controller.listeners++;
|
|
41
|
+
(element[SLOT_CLEANUP] ??= []).push(() => {
|
|
42
|
+
if (--controller.listeners) {
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
controller.abort();
|
|
46
|
+
controllers.set(event, null);
|
|
47
|
+
});
|
|
48
|
+
signal = controller.signal;
|
|
49
|
+
}
|
|
50
|
+
let key = keys[event];
|
|
51
|
+
if (!key) {
|
|
52
|
+
key = keys[event] = Symbol();
|
|
53
|
+
addEventListener.call(window.document, event.slice(2), (e) => {
|
|
54
|
+
let node = e.target;
|
|
55
|
+
defineProperty(e, 'currentTarget', {
|
|
56
|
+
configurable: true,
|
|
57
|
+
get() {
|
|
58
|
+
return node || window.document;
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
while (node) {
|
|
62
|
+
if (key in node) {
|
|
63
|
+
return node[key].call(node, e);
|
|
64
|
+
}
|
|
65
|
+
node = parentElement.call(node);
|
|
66
|
+
}
|
|
67
|
+
}, {
|
|
68
|
+
capture: capture.has(event),
|
|
69
|
+
passive: passive.has(event),
|
|
70
|
+
signal
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
element[key] = listener;
|
|
49
74
|
};
|
package/build/html/cache.js
CHANGED
|
@@ -1,67 +1,19 @@
|
|
|
1
|
-
import { NODE_CLOSING, NODE_ELEMENT, NODE_SLOT, NODE_VOID, NODE_WHITELIST, REGEX_EMPTY_TEXT_NODES,
|
|
1
|
+
import { NODE_CLOSING, NODE_ELEMENT, NODE_SLOT, NODE_VOID, NODE_WHITELIST, REGEX_EMPTY_TEXT_NODES, REGEX_SLOT_NODES, SLOT_HTML, SLOT_MARKER, SLOT_MARKER_LENGTH } from '../constants.js';
|
|
2
2
|
import { firstChild, firstElementChild, fragment, nextElementSibling, nextSibling } from '../utilities.js';
|
|
3
|
-
import
|
|
3
|
+
import { spread } from '../attributes.js';
|
|
4
4
|
import s from '../slot.js';
|
|
5
5
|
let cache = new WeakMap();
|
|
6
6
|
function build(literals, values) {
|
|
7
7
|
if (values.length === 0) {
|
|
8
8
|
return set(literals, literals[0]);
|
|
9
9
|
}
|
|
10
|
-
let
|
|
10
|
+
let buffer = '', html = literals.join(SLOT_MARKER)
|
|
11
|
+
.replace(REGEX_EMPTY_TEXT_NODES, '$1$2')
|
|
12
|
+
.trim(), index = 0, level = 0, levels = [{
|
|
11
13
|
children: 0,
|
|
12
14
|
elements: 0,
|
|
13
15
|
path: []
|
|
14
|
-
}], slot = 0, slots = [], total = values.length;
|
|
15
|
-
{
|
|
16
|
-
let attribute = '', buffer = '', char = '', quote = '';
|
|
17
|
-
for (let match of html.matchAll(REGEX_SLOT_ATTRIBUTES)) {
|
|
18
|
-
let found = match[1], metadata = attributes[found];
|
|
19
|
-
if (metadata) {
|
|
20
|
-
continue;
|
|
21
|
-
}
|
|
22
|
-
metadata = attributes[found] = [];
|
|
23
|
-
for (let i = 0, n = found.length; i < n; i++) {
|
|
24
|
-
char = found[i];
|
|
25
|
-
if (char === ' ') {
|
|
26
|
-
buffer = '';
|
|
27
|
-
}
|
|
28
|
-
else if (char === '=') {
|
|
29
|
-
attribute = buffer;
|
|
30
|
-
buffer = '';
|
|
31
|
-
}
|
|
32
|
-
else if (char === '"' || char === "'") {
|
|
33
|
-
if (!attribute) {
|
|
34
|
-
}
|
|
35
|
-
else if (!quote) {
|
|
36
|
-
quote = char;
|
|
37
|
-
}
|
|
38
|
-
else if (quote === char) {
|
|
39
|
-
attribute = '';
|
|
40
|
-
buffer = '';
|
|
41
|
-
quote = '';
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
else if (char === '{' && char !== buffer) {
|
|
45
|
-
buffer = char;
|
|
46
|
-
}
|
|
47
|
-
else {
|
|
48
|
-
buffer += char;
|
|
49
|
-
if (buffer === SLOT_MARKER) {
|
|
50
|
-
buffer = '';
|
|
51
|
-
if (attribute) {
|
|
52
|
-
metadata.push(attribute);
|
|
53
|
-
if (!quote) {
|
|
54
|
-
attribute = '';
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
else {
|
|
58
|
-
metadata.push(null);
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
}
|
|
16
|
+
}], parsed = html.split(SLOT_MARKER), slot = 0, slots = [], total = values.length;
|
|
65
17
|
for (let match of html.matchAll(REGEX_SLOT_NODES)) {
|
|
66
18
|
let parent = levels[level], type = match[1] === undefined ? NODE_SLOT : (NODE_WHITELIST[match[1].toLowerCase()] || NODE_ELEMENT);
|
|
67
19
|
if ((match.index || 1) - 1 > index) {
|
|
@@ -70,19 +22,15 @@ function build(literals, values) {
|
|
|
70
22
|
if (type === NODE_ELEMENT || type === NODE_VOID) {
|
|
71
23
|
let attr = match[2];
|
|
72
24
|
if (attr) {
|
|
73
|
-
let
|
|
74
|
-
|
|
75
|
-
throw new Error(`Template: attribute metadata could not be found for '${attr}'`);
|
|
76
|
-
}
|
|
77
|
-
for (let i = 0, n = metadata.length; i < n; i++) {
|
|
78
|
-
let name = metadata[i];
|
|
25
|
+
let i = attr.indexOf(SLOT_MARKER), path = methods(parent.children, parent.path, firstChild, nextSibling);
|
|
26
|
+
while (i !== -1) {
|
|
79
27
|
slots.push({
|
|
80
|
-
fn:
|
|
81
|
-
name,
|
|
28
|
+
fn: spread,
|
|
82
29
|
path,
|
|
83
30
|
slot
|
|
84
31
|
});
|
|
85
|
-
buffer +=
|
|
32
|
+
buffer += parsed[slot++];
|
|
33
|
+
i = attr.indexOf(SLOT_MARKER, i + SLOT_MARKER_LENGTH);
|
|
86
34
|
}
|
|
87
35
|
}
|
|
88
36
|
if (type === NODE_ELEMENT) {
|
|
@@ -97,16 +45,15 @@ function build(literals, values) {
|
|
|
97
45
|
parent.elements++;
|
|
98
46
|
}
|
|
99
47
|
else if (type === NODE_SLOT) {
|
|
100
|
-
buffer +=
|
|
48
|
+
buffer += parsed[slot] + SLOT_HTML;
|
|
101
49
|
slots.push({
|
|
102
50
|
fn: s,
|
|
103
|
-
name: null,
|
|
104
51
|
path: methods(parent.children, parent.path, firstChild, nextSibling),
|
|
105
52
|
slot: slot++
|
|
106
53
|
});
|
|
107
54
|
}
|
|
108
55
|
if (slot === total) {
|
|
109
|
-
buffer +=
|
|
56
|
+
buffer += parsed[slot];
|
|
110
57
|
break;
|
|
111
58
|
}
|
|
112
59
|
if (type === NODE_CLOSING) {
|
|
@@ -117,7 +64,7 @@ function build(literals, values) {
|
|
|
117
64
|
}
|
|
118
65
|
index = (match.index || 0) + match[0].length;
|
|
119
66
|
}
|
|
120
|
-
return set(literals,
|
|
67
|
+
return set(literals, buffer, slots);
|
|
121
68
|
}
|
|
122
69
|
function methods(children, copy, first, next) {
|
|
123
70
|
let methods = copy.slice();
|
|
@@ -127,9 +74,6 @@ function methods(children, copy, first, next) {
|
|
|
127
74
|
}
|
|
128
75
|
return methods;
|
|
129
76
|
}
|
|
130
|
-
function minify(html) {
|
|
131
|
-
return html.replace(REGEX_EMPTY_TEXT_NODES, '$1$2').replace(REGEX_EXTRA_WHITESPACE, ' ').trim();
|
|
132
|
-
}
|
|
133
77
|
function set(literals, html, slots = null) {
|
|
134
78
|
let template = {
|
|
135
79
|
fragment: fragment(html),
|
package/build/html/hydrate.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { root } from '@esportsplus/reactivity';
|
|
2
2
|
import { cloneNode, firstChild, nextSibling } from '../utilities.js';
|
|
3
|
-
import
|
|
3
|
+
import { apply } from '../attributes.js';
|
|
4
4
|
import cache from './cache.js';
|
|
5
5
|
function reactive(renderable, slot) {
|
|
6
6
|
let array = renderable.values, factory = renderable.template, refresh = () => {
|
|
@@ -23,10 +23,10 @@ function render(renderable, template) {
|
|
|
23
23
|
if (slots !== null) {
|
|
24
24
|
let node, previous, values = renderable.values;
|
|
25
25
|
for (let i = slots.length - 1; i >= 0; i--) {
|
|
26
|
-
let { fn,
|
|
26
|
+
let { fn, path, slot } = slots[i];
|
|
27
27
|
if (path === previous) { }
|
|
28
28
|
else {
|
|
29
|
-
|
|
29
|
+
apply(node);
|
|
30
30
|
node = fragment;
|
|
31
31
|
previous = path;
|
|
32
32
|
for (let o = 0, j = path.length; o < j; o++) {
|
|
@@ -35,7 +35,9 @@ function render(renderable, template) {
|
|
|
35
35
|
}
|
|
36
36
|
fn(node, values[slot], name);
|
|
37
37
|
}
|
|
38
|
-
|
|
38
|
+
if (node) {
|
|
39
|
+
apply(node);
|
|
40
|
+
}
|
|
39
41
|
}
|
|
40
42
|
for (let element = firstChild.call(fragment); element; element = nextSibling.call(element)) {
|
|
41
43
|
elements.push(element);
|
package/build/slot.d.ts
CHANGED
|
@@ -10,10 +10,10 @@ declare class Slot {
|
|
|
10
10
|
set length(n: number);
|
|
11
11
|
anchor(index?: number): Element;
|
|
12
12
|
clear(): void;
|
|
13
|
-
pop(): Elements | undefined;
|
|
13
|
+
pop(): Elements[] | undefined;
|
|
14
14
|
push(...groups: Elements[]): number;
|
|
15
15
|
render(input: unknown): this;
|
|
16
|
-
shift(): Elements | undefined;
|
|
16
|
+
shift(): Elements[] | undefined;
|
|
17
17
|
splice(start: number, stop?: number, ...groups: Elements[]): Elements[];
|
|
18
18
|
unshift(...groups: Elements[]): number;
|
|
19
19
|
}
|
package/build/slot.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { effect, root, DIRTY } from '@esportsplus/reactivity';
|
|
2
|
-
import { RENDERABLE, RENDERABLE_REACTIVE, SLOT } from './constants.js';
|
|
2
|
+
import { RENDERABLE, RENDERABLE_REACTIVE, SLOT, SLOT_CLEANUP } from './constants.js';
|
|
3
3
|
import { hydrate } from './html/index.js';
|
|
4
4
|
import { firstChild, isArray, isObject, nextSibling, nodeValue, raf, text } from './utilities.js';
|
|
5
|
-
let cleanup = [],
|
|
6
|
-
function
|
|
5
|
+
let cleanup = [], scheduled = false;
|
|
6
|
+
function after(anchor, groups) {
|
|
7
7
|
for (let i = 0, n = groups.length; i < n; i++) {
|
|
8
8
|
let group = groups[i];
|
|
9
9
|
if (group.length) {
|
|
@@ -13,29 +13,13 @@ function afterGroups(anchor, groups) {
|
|
|
13
13
|
}
|
|
14
14
|
return groups;
|
|
15
15
|
}
|
|
16
|
-
function
|
|
17
|
-
if (group === undefined) {
|
|
18
|
-
return group;
|
|
19
|
-
}
|
|
20
|
-
for (let i = 0, n = group.length; i < n; i++) {
|
|
21
|
-
let item = group[i];
|
|
22
|
-
if (key in item) {
|
|
23
|
-
cleanup.push(item[key]);
|
|
24
|
-
}
|
|
25
|
-
item.remove();
|
|
26
|
-
}
|
|
27
|
-
if (!scheduled && cleanup.length) {
|
|
28
|
-
schedule();
|
|
29
|
-
}
|
|
30
|
-
return group;
|
|
31
|
-
}
|
|
32
|
-
function removeGroups(groups) {
|
|
16
|
+
function remove(...groups) {
|
|
33
17
|
for (let i = 0, n = groups.length; i < n; i++) {
|
|
34
18
|
let group = groups[i];
|
|
35
19
|
for (let j = 0, o = group.length; j < o; j++) {
|
|
36
20
|
let item = group[j];
|
|
37
|
-
if (
|
|
38
|
-
cleanup.push(item[
|
|
21
|
+
if (item[SLOT_CLEANUP]) {
|
|
22
|
+
cleanup.push(...item[SLOT_CLEANUP]);
|
|
39
23
|
}
|
|
40
24
|
item.remove();
|
|
41
25
|
}
|
|
@@ -55,12 +39,12 @@ function render(anchor, input, slot) {
|
|
|
55
39
|
for (let i = 0, n = input.length; i < n; i++) {
|
|
56
40
|
groups.push(render(null, input[i]));
|
|
57
41
|
}
|
|
58
|
-
return anchor ?
|
|
42
|
+
return anchor ? after(anchor, groups) : groups;
|
|
59
43
|
}
|
|
60
44
|
let nodes = [];
|
|
61
45
|
if (RENDERABLE in input) {
|
|
62
46
|
if (input[RENDERABLE] === RENDERABLE_REACTIVE) {
|
|
63
|
-
return
|
|
47
|
+
return after(anchor, hydrate.reactive(input, slot));
|
|
64
48
|
}
|
|
65
49
|
else {
|
|
66
50
|
nodes = hydrate.static(input);
|
|
@@ -98,13 +82,16 @@ function schedule() {
|
|
|
98
82
|
scheduled = true;
|
|
99
83
|
raf.add(() => {
|
|
100
84
|
try {
|
|
101
|
-
let
|
|
102
|
-
while (
|
|
103
|
-
|
|
85
|
+
let fn;
|
|
86
|
+
while (fn = cleanup.pop()) {
|
|
87
|
+
fn();
|
|
104
88
|
}
|
|
105
89
|
}
|
|
106
90
|
catch (e) { }
|
|
107
91
|
scheduled = false;
|
|
92
|
+
if (cleanup.length) {
|
|
93
|
+
schedule();
|
|
94
|
+
}
|
|
108
95
|
});
|
|
109
96
|
}
|
|
110
97
|
class Slot {
|
|
@@ -113,7 +100,9 @@ class Slot {
|
|
|
113
100
|
nodes;
|
|
114
101
|
text = null;
|
|
115
102
|
constructor(marker) {
|
|
116
|
-
marker[
|
|
103
|
+
(marker[SLOT_CLEANUP] ??= []).push(() => {
|
|
104
|
+
this.clear();
|
|
105
|
+
});
|
|
117
106
|
this.marker = marker;
|
|
118
107
|
this.nodes = [];
|
|
119
108
|
}
|
|
@@ -131,14 +120,18 @@ class Slot {
|
|
|
131
120
|
return node || this.marker;
|
|
132
121
|
}
|
|
133
122
|
clear() {
|
|
134
|
-
|
|
123
|
+
remove(...this.nodes);
|
|
135
124
|
this.text = null;
|
|
136
125
|
}
|
|
137
126
|
pop() {
|
|
138
|
-
|
|
127
|
+
let group = this.nodes.pop();
|
|
128
|
+
if (!group) {
|
|
129
|
+
return undefined;
|
|
130
|
+
}
|
|
131
|
+
return remove(group);
|
|
139
132
|
}
|
|
140
133
|
push(...groups) {
|
|
141
|
-
|
|
134
|
+
after(this.anchor(), groups);
|
|
142
135
|
for (let i = 0, n = groups.length; i < n; i++) {
|
|
143
136
|
this.nodes.push(groups[i]);
|
|
144
137
|
}
|
|
@@ -182,13 +175,17 @@ class Slot {
|
|
|
182
175
|
return this;
|
|
183
176
|
}
|
|
184
177
|
shift() {
|
|
185
|
-
|
|
178
|
+
let group = this.nodes.shift();
|
|
179
|
+
if (!group) {
|
|
180
|
+
return undefined;
|
|
181
|
+
}
|
|
182
|
+
return remove(group);
|
|
186
183
|
}
|
|
187
184
|
splice(start, stop = this.nodes.length, ...groups) {
|
|
188
|
-
return
|
|
185
|
+
return remove(...this.nodes.splice(start, stop, ...after(this.anchor(start), groups)));
|
|
189
186
|
}
|
|
190
187
|
unshift(...groups) {
|
|
191
|
-
return this.nodes.unshift(...
|
|
188
|
+
return this.nodes.unshift(...after(this.marker, groups));
|
|
192
189
|
}
|
|
193
190
|
}
|
|
194
191
|
export default (marker, value) => {
|
package/build/types.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ReactiveArray } from '@esportsplus/reactivity';
|
|
2
|
-
import { RENDERABLE, RENDERABLE_REACTIVE, RENDERABLE_TEMPLATE } from './constants.js';
|
|
2
|
+
import { RENDERABLE, RENDERABLE_REACTIVE, RENDERABLE_TEMPLATE, SLOT_CLEANUP } from './constants.js';
|
|
3
3
|
import { firstChild } from './utilities.js';
|
|
4
4
|
import attributes from './attributes.js';
|
|
5
5
|
import event from './event.js';
|
|
@@ -12,10 +12,14 @@ type Attributes = {
|
|
|
12
12
|
} & {
|
|
13
13
|
[key: `aria-${string}`]: string | number | boolean | undefined;
|
|
14
14
|
[key: `data-${string}`]: string | undefined;
|
|
15
|
+
onmount?: (element: Element) => void;
|
|
16
|
+
onrender?: (element: Element) => void;
|
|
15
17
|
} & Record<PropertyKey, unknown>;
|
|
16
18
|
type Effect<T> = () => EffectResponse<T>;
|
|
17
19
|
type EffectResponse<T> = T extends [] ? EffectResponse<T[number]>[] : Primitive | Renderable<T>;
|
|
18
|
-
type Element = HTMLElement & Attributes &
|
|
20
|
+
type Element = HTMLElement & Attributes & {
|
|
21
|
+
[SLOT_CLEANUP]?: VoidFunction[];
|
|
22
|
+
} & Record<PropertyKey, unknown>;
|
|
19
23
|
type Elements = Element[];
|
|
20
24
|
type Primitive = bigint | boolean | null | number | string | undefined;
|
|
21
25
|
type Renderable<T = unknown> = RenderableReactive<T> | RenderableTemplate<T>;
|
|
@@ -37,8 +41,7 @@ type Template = {
|
|
|
37
41
|
html: string;
|
|
38
42
|
literals: TemplateStringsArray;
|
|
39
43
|
slots: {
|
|
40
|
-
fn: typeof attributes.
|
|
41
|
-
name: PropertyKey | null;
|
|
44
|
+
fn: typeof attributes.spread | typeof event | typeof slot;
|
|
42
45
|
path: typeof firstChild[];
|
|
43
46
|
slot: number;
|
|
44
47
|
}[] | null;
|
package/build/types.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import { RENDERABLE } from './constants.js';
|
|
1
|
+
import { RENDERABLE, SLOT_CLEANUP } from './constants.js';
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"dependencies": {
|
|
4
4
|
"@esportsplus/reactivity": "^0.4.6",
|
|
5
5
|
"@esportsplus/tasks": "^0.1.9",
|
|
6
|
-
"@esportsplus/utilities": "^0.
|
|
6
|
+
"@esportsplus/utilities": "^0.19.0"
|
|
7
7
|
},
|
|
8
8
|
"devDependencies": {
|
|
9
9
|
"@esportsplus/typescript": "^0.9.1"
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"private": false,
|
|
14
14
|
"type": "module",
|
|
15
15
|
"types": "./build/index.d.ts",
|
|
16
|
-
"version": "0.
|
|
16
|
+
"version": "0.14.0",
|
|
17
17
|
"scripts": {
|
|
18
18
|
"build": "tsc && tsc-alias",
|
|
19
19
|
"-": "-"
|