@esportsplus/template 0.15.15 → 0.15.17
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 +2 -2
- package/build/attributes.js +87 -47
- package/build/constants.d.ts +2 -1
- package/build/constants.js +2 -1
- package/build/event.js +6 -5
- package/build/html/hydrate.d.ts +6 -3
- package/build/html/hydrate.js +26 -23
- package/build/slot.d.ts +4 -4
- package/build/slot.js +62 -61
- package/build/types.d.ts +8 -4
- package/build/types.js +1 -1
- package/build/utilities.d.ts +2 -1
- package/build/utilities.js +2 -1
- package/package.json +3 -3
- package/src/attributes.ts +131 -52
- package/src/constants.ts +8 -14
- package/src/event.ts +8 -6
- package/src/html/hydrate.ts +33 -34
- package/src/slot.ts +85 -79
- package/src/types.ts +13 -5
- package/src/utilities.ts +3 -1
package/src/slot.ts
CHANGED
|
@@ -2,26 +2,44 @@ import { effect, root } from '@esportsplus/reactivity';
|
|
|
2
2
|
import { isArray, isFunction, isInstanceOf, isObject } from '@esportsplus/utilities';
|
|
3
3
|
import { RENDERABLE, RENDERABLE_REACTIVE, SLOT_CLEANUP } from './constants';
|
|
4
4
|
import { hydrate } from './html';
|
|
5
|
-
import { Element, Elements, RenderableReactive, RenderableTemplate } from './types';
|
|
6
|
-
import { firstChild, microtask, nextSibling, nodeValue, raf, text } from './utilities'
|
|
5
|
+
import { Element, Elements, RenderableReactive, RenderableTemplate, RenderedGroup } from './types';
|
|
6
|
+
import { append, firstChild, fragment, microtask, nextSibling, nodeValue, raf, text } from './utilities'
|
|
7
7
|
import queue from '@esportsplus/queue';
|
|
8
8
|
|
|
9
9
|
|
|
10
|
-
let cleanup = queue<VoidFunction[]>(
|
|
10
|
+
let cleanup = queue<VoidFunction[]>(64),
|
|
11
|
+
fallback = fragment(''),
|
|
11
12
|
scheduled = false;
|
|
12
13
|
|
|
13
14
|
|
|
14
|
-
function after(anchor: Element, groups:
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
function after(anchor: Element, groups: RenderedGroup[]) {
|
|
16
|
+
let elements: Elements[] = [],
|
|
17
|
+
n = groups.length;
|
|
18
|
+
|
|
19
|
+
if (n) {
|
|
20
|
+
let fragment = groups[0].fragment || fallback;
|
|
21
|
+
|
|
22
|
+
if (n === 1) {
|
|
23
|
+
elements.push( groups[0].elements );
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
for (let i = 1; i < n; i++) {
|
|
27
|
+
let group = groups[i];
|
|
28
|
+
|
|
29
|
+
if (group.fragment) {
|
|
30
|
+
append.call(fragment, group.fragment);
|
|
31
|
+
group.fragment = null;
|
|
32
|
+
}
|
|
17
33
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
anchor = group.at(-1)!;
|
|
34
|
+
elements.push(group.elements);
|
|
35
|
+
}
|
|
21
36
|
}
|
|
37
|
+
|
|
38
|
+
anchor.after(fragment);
|
|
39
|
+
groups[0].fragment = null;
|
|
22
40
|
}
|
|
23
41
|
|
|
24
|
-
return
|
|
42
|
+
return elements;
|
|
25
43
|
}
|
|
26
44
|
|
|
27
45
|
function remove(...groups: Elements[]) {
|
|
@@ -32,7 +50,7 @@ function remove(...groups: Elements[]) {
|
|
|
32
50
|
let item = group[j];
|
|
33
51
|
|
|
34
52
|
if (item[SLOT_CLEANUP]) {
|
|
35
|
-
cleanup.add(
|
|
53
|
+
cleanup.add(item[SLOT_CLEANUP]);
|
|
36
54
|
}
|
|
37
55
|
|
|
38
56
|
item.remove();
|
|
@@ -46,62 +64,57 @@ function remove(...groups: Elements[]) {
|
|
|
46
64
|
return groups;
|
|
47
65
|
}
|
|
48
66
|
|
|
49
|
-
function render(
|
|
50
|
-
if (input === false || input == null) {
|
|
51
|
-
|
|
67
|
+
function render(groups: RenderedGroup[], input: unknown, slot?: Slot) {
|
|
68
|
+
if (input === false || input == null || input === '') {
|
|
69
|
+
return groups;
|
|
52
70
|
}
|
|
53
|
-
else if (isObject(input)) {
|
|
54
|
-
if (isArray(input)) {
|
|
55
|
-
let groups: Elements[] = [];
|
|
56
71
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
return anchor ? after(anchor, groups) : groups;
|
|
72
|
+
if (isArray(input)) {
|
|
73
|
+
for (let i = 0, n = input.length; i < n; i++) {
|
|
74
|
+
render(groups, input[i]);
|
|
62
75
|
}
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
}
|
|
70
|
-
else {
|
|
71
|
-
nodes = hydrate.static(input as RenderableTemplate<unknown>);
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
else if (isInstanceOf(input, NodeList)) {
|
|
75
|
-
for (let node = firstChild.call(input); node; node = nextSibling.call(node)) {
|
|
76
|
-
nodes.push(node);
|
|
77
|
-
}
|
|
76
|
+
}
|
|
77
|
+
else if (isObject(input) && RENDERABLE in input) {
|
|
78
|
+
if (input[RENDERABLE] === RENDERABLE_REACTIVE) {
|
|
79
|
+
groups.push(
|
|
80
|
+
...hydrate.reactive(input as RenderableReactive, slot!)
|
|
81
|
+
);
|
|
78
82
|
}
|
|
79
|
-
else
|
|
80
|
-
|
|
83
|
+
else {
|
|
84
|
+
groups.push(
|
|
85
|
+
hydrate.static(input as RenderableTemplate<unknown>)
|
|
86
|
+
);
|
|
81
87
|
}
|
|
88
|
+
}
|
|
89
|
+
else if (isInstanceOf(input, NodeList)) {
|
|
90
|
+
let elements: Elements = [];
|
|
82
91
|
|
|
83
|
-
|
|
84
|
-
|
|
92
|
+
for (let node = firstChild.call(input); node; node = nextSibling.call(node)) {
|
|
93
|
+
elements.push(node);
|
|
85
94
|
}
|
|
86
95
|
|
|
87
|
-
|
|
96
|
+
groups.push({ elements, fragment: null });
|
|
88
97
|
}
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
98
|
+
else if (isInstanceOf(input, Node)) {
|
|
99
|
+
groups.push({
|
|
100
|
+
elements: [ input as Element ],
|
|
101
|
+
fragment: input as RenderedGroup['fragment']
|
|
102
|
+
});
|
|
92
103
|
}
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
if (anchor) {
|
|
97
|
-
anchor.after(node);
|
|
104
|
+
else {
|
|
105
|
+
let element = text( typeof input === 'string' ? input : String(input) );
|
|
98
106
|
|
|
99
107
|
if (slot) {
|
|
100
|
-
slot.text =
|
|
108
|
+
slot.text = element;
|
|
101
109
|
}
|
|
110
|
+
|
|
111
|
+
groups.push({
|
|
112
|
+
elements: [ element ],
|
|
113
|
+
fragment: element
|
|
114
|
+
});
|
|
102
115
|
}
|
|
103
116
|
|
|
104
|
-
return
|
|
117
|
+
return groups;
|
|
105
118
|
}
|
|
106
119
|
|
|
107
120
|
function schedule() {
|
|
@@ -110,20 +123,19 @@ function schedule() {
|
|
|
110
123
|
}
|
|
111
124
|
|
|
112
125
|
scheduled = true;
|
|
113
|
-
|
|
114
126
|
microtask.add(task);
|
|
115
127
|
}
|
|
116
128
|
|
|
117
129
|
function task() {
|
|
118
|
-
let fns;
|
|
130
|
+
let fn, fns;
|
|
119
131
|
|
|
120
132
|
while (fns = cleanup.next()) {
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
133
|
+
try {
|
|
134
|
+
while (fn = fns.pop()) {
|
|
135
|
+
fn();
|
|
124
136
|
}
|
|
125
|
-
catch { }
|
|
126
137
|
}
|
|
138
|
+
catch { }
|
|
127
139
|
}
|
|
128
140
|
|
|
129
141
|
scheduled = false;
|
|
@@ -170,6 +182,7 @@ class Slot {
|
|
|
170
182
|
|
|
171
183
|
clear() {
|
|
172
184
|
remove(...this.nodes);
|
|
185
|
+
this.nodes.length = 0;
|
|
173
186
|
this.text = null;
|
|
174
187
|
}
|
|
175
188
|
|
|
@@ -183,14 +196,8 @@ class Slot {
|
|
|
183
196
|
return remove(group);
|
|
184
197
|
}
|
|
185
198
|
|
|
186
|
-
push(...groups:
|
|
187
|
-
after(this.anchor(), groups);
|
|
188
|
-
|
|
189
|
-
for (let i = 0, n = groups.length; i < n; i++) {
|
|
190
|
-
this.nodes.push(groups[i]);
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
return this.nodes.length;
|
|
199
|
+
push(...groups: RenderedGroup[]) {
|
|
200
|
+
return this.nodes.push( ...after(this.anchor(), groups) );
|
|
194
201
|
}
|
|
195
202
|
|
|
196
203
|
render(input: unknown) {
|
|
@@ -198,7 +205,7 @@ class Slot {
|
|
|
198
205
|
ondisconnect(
|
|
199
206
|
this.marker,
|
|
200
207
|
effect(() => {
|
|
201
|
-
let v =
|
|
208
|
+
let v = input();
|
|
202
209
|
|
|
203
210
|
if (isFunction(v)) {
|
|
204
211
|
root(() => this.render(v()));
|
|
@@ -217,7 +224,8 @@ class Slot {
|
|
|
217
224
|
if (this.text) {
|
|
218
225
|
let type = typeof input;
|
|
219
226
|
|
|
220
|
-
if (type === 'object' && input !== null) {
|
|
227
|
+
if (type === 'object' && input !== null) {
|
|
228
|
+
}
|
|
221
229
|
else if (this.text.isConnected) {
|
|
222
230
|
nodeValue.call(
|
|
223
231
|
this.text,
|
|
@@ -228,13 +236,7 @@ class Slot {
|
|
|
228
236
|
}
|
|
229
237
|
|
|
230
238
|
this.clear();
|
|
231
|
-
|
|
232
|
-
if (isArray(input) || (isObject(input) && input[RENDERABLE] === RENDERABLE_REACTIVE)) {
|
|
233
|
-
this.nodes = render(this.marker, input, this) as Elements[];
|
|
234
|
-
}
|
|
235
|
-
else {
|
|
236
|
-
this.nodes = [ render(this.marker, input, this) as Elements ];
|
|
237
|
-
}
|
|
239
|
+
this.nodes = after(this.marker, render([], input, this));
|
|
238
240
|
|
|
239
241
|
return this;
|
|
240
242
|
}
|
|
@@ -249,14 +251,18 @@ class Slot {
|
|
|
249
251
|
return remove(group);
|
|
250
252
|
}
|
|
251
253
|
|
|
252
|
-
splice(start: number, stop: number = this.nodes.length, ...groups:
|
|
254
|
+
splice(start: number, stop: number = this.nodes.length, ...groups: RenderedGroup[]) {
|
|
253
255
|
return remove(
|
|
254
|
-
...this.nodes.splice(
|
|
256
|
+
...this.nodes.splice(
|
|
257
|
+
start,
|
|
258
|
+
stop,
|
|
259
|
+
...after(this.anchor(start), groups)
|
|
260
|
+
)
|
|
255
261
|
);
|
|
256
262
|
}
|
|
257
263
|
|
|
258
|
-
unshift(...groups:
|
|
259
|
-
return this.nodes.unshift(...after(this.marker, groups));
|
|
264
|
+
unshift(...groups: RenderedGroup[]) {
|
|
265
|
+
return this.nodes.unshift( ...after(this.marker, groups) );
|
|
260
266
|
}
|
|
261
267
|
}
|
|
262
268
|
|
package/src/types.ts
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import { ReactiveArray } from '@esportsplus/reactivity';
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
ATTRIBUTE_STORE,
|
|
4
|
+
RENDERABLE, RENDERABLE_REACTIVE, RENDERABLE_TEMPLATE,
|
|
5
|
+
SLOT_CLEANUP
|
|
6
|
+
} from './constants';
|
|
3
7
|
import { firstChild } from './utilities';
|
|
4
8
|
import attributes from './attributes';
|
|
5
|
-
import event from './event';
|
|
6
9
|
import slot from './slot';
|
|
7
10
|
|
|
8
11
|
|
|
@@ -27,7 +30,10 @@ type Effect<T> = () => EffectResponse<T>;
|
|
|
27
30
|
|
|
28
31
|
type EffectResponse<T> = T extends [] ? EffectResponse<T[number]>[] : Primitive | Renderable<T>;
|
|
29
32
|
|
|
30
|
-
type Element = HTMLElement & Attributes & {
|
|
33
|
+
type Element = HTMLElement & Attributes & {
|
|
34
|
+
[ATTRIBUTE_STORE]?: Record<PropertyKey, unknown>;
|
|
35
|
+
[SLOT_CLEANUP]?: VoidFunction[]
|
|
36
|
+
} & Record<PropertyKey, unknown>;
|
|
31
37
|
|
|
32
38
|
type Elements = Element[];
|
|
33
39
|
|
|
@@ -56,12 +62,14 @@ type RenderableTemplate<T> = {
|
|
|
56
62
|
|
|
57
63
|
type RenderableValue<T = unknown> = Attributes | Readonly<Attributes> | Readonly<Attributes[]> | Effect<T> | Primitive | Renderable;
|
|
58
64
|
|
|
65
|
+
type RenderedGroup = { elements: Elements, fragment: DocumentFragment | Node | null };
|
|
66
|
+
|
|
59
67
|
type Template = {
|
|
60
68
|
fragment: DocumentFragment;
|
|
61
69
|
html: string;
|
|
62
70
|
literals: TemplateStringsArray;
|
|
63
71
|
slots: {
|
|
64
|
-
fn: typeof attributes.spread | typeof
|
|
72
|
+
fn: typeof attributes.spread | typeof slot;
|
|
65
73
|
path: typeof firstChild[];
|
|
66
74
|
slot: number;
|
|
67
75
|
}[] | null;
|
|
@@ -71,6 +79,6 @@ type Template = {
|
|
|
71
79
|
export type {
|
|
72
80
|
Attributes,
|
|
73
81
|
Effect, Element, Elements,
|
|
74
|
-
Renderable, RenderableReactive, RenderableTemplate, RenderableValue,
|
|
82
|
+
Renderable, RenderableReactive, RenderableTemplate, RenderableValue, RenderedGroup,
|
|
75
83
|
Template
|
|
76
84
|
};
|
package/src/utilities.ts
CHANGED
|
@@ -12,6 +12,8 @@ prototype = Element.prototype;
|
|
|
12
12
|
|
|
13
13
|
const addEventListener = prototype.addEventListener;
|
|
14
14
|
|
|
15
|
+
const append = prototype.append;
|
|
16
|
+
|
|
15
17
|
const removeEventListener = prototype.removeEventListener;
|
|
16
18
|
|
|
17
19
|
const className = Object.getOwnPropertyDescriptor(prototype, 'className')!.set!;
|
|
@@ -70,7 +72,7 @@ const text = (value: string) => {
|
|
|
70
72
|
|
|
71
73
|
|
|
72
74
|
export {
|
|
73
|
-
addEventListener,
|
|
75
|
+
addEventListener, append,
|
|
74
76
|
className, cloneNode,
|
|
75
77
|
firstChild, firstElementChild, fragment,
|
|
76
78
|
innerHTML,
|