@esportsplus/template 0.16.1 → 0.17.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.
- package/build/attributes.js +27 -23
- package/build/constants.d.ts +13 -3
- package/build/constants.js +13 -3
- package/build/event.js +7 -7
- package/build/html/cache.js +1 -1
- package/build/html/hydrate.d.ts +2 -8
- package/build/html/hydrate.js +27 -78
- package/build/html/index.d.ts +2106 -5
- package/build/html/index.js +12 -4
- package/build/render.d.ts +1 -2
- package/build/render.js +6 -10
- package/build/slot/cleanup.d.ts +4 -0
- package/build/slot/cleanup.js +51 -0
- package/build/slot/effect.d.ts +3 -0
- package/build/slot/effect.js +51 -0
- package/build/slot/index.d.ts +3 -0
- package/build/slot/index.js +15 -0
- package/build/slot/reactive.d.ts +3 -0
- package/build/slot/reactive.js +117 -0
- package/build/slot/render.d.ts +2 -0
- package/build/slot/render.js +58 -0
- package/build/svg.d.ts +1 -2
- package/build/types.d.ts +20 -16
- package/build/utilities.d.ts +3 -3
- package/build/utilities.js +12 -12
- package/package.json +2 -2
- package/src/attributes.ts +30 -28
- package/src/constants.ts +31 -4
- package/src/event.ts +8 -8
- package/src/html/hydrate.ts +35 -107
- package/src/html/index.ts +16 -8
- package/src/render.ts +8 -12
- package/src/slot/cleanup.ts +74 -0
- package/src/slot/effect.ts +73 -0
- package/src/slot/index.ts +23 -0
- package/src/slot/reactive.ts +167 -0
- package/src/slot/render.ts +81 -0
- package/src/svg.ts +1 -2
- package/src/types.ts +24 -17
- package/src/utilities.ts +15 -13
- package/build/slot.d.ts +0 -21
- package/build/slot.js +0 -204
- package/src/slot.ts +0 -277
package/src/slot.ts
DELETED
|
@@ -1,277 +0,0 @@
|
|
|
1
|
-
import { effect } from '@esportsplus/reactivity';
|
|
2
|
-
import { isArray, isInstanceOf } from '@esportsplus/utilities';
|
|
3
|
-
import { EMPTY_FRAGMENT, RENDERABLE, RENDERABLE_REACTIVE } from './constants';
|
|
4
|
-
import { hydrate } from './html';
|
|
5
|
-
import { Element, Elements, Fragment, RenderableReactive, RenderableTemplate } from './types';
|
|
6
|
-
import { append, cloneNode, microtask, nodeValue, raf, text } from './utilities'
|
|
7
|
-
import queue from '@esportsplus/queue';
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
const CLEANUP_KEY = Symbol();
|
|
11
|
-
|
|
12
|
-
const CONNECTED = 0;
|
|
13
|
-
|
|
14
|
-
const HYDRATING = 1;
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
let cleanup = queue<VoidFunction[]>(64),
|
|
18
|
-
scheduled = false;
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
function remove(groups: Elements[]) {
|
|
22
|
-
let group,
|
|
23
|
-
item;
|
|
24
|
-
|
|
25
|
-
while (group = groups.pop()) {
|
|
26
|
-
while (item = group.pop()) {
|
|
27
|
-
if (CLEANUP_KEY in item) {
|
|
28
|
-
cleanup.add(item[CLEANUP_KEY] as VoidFunction[]);
|
|
29
|
-
item[CLEANUP_KEY] = null;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
item.remove();
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
if (!scheduled && cleanup.length) {
|
|
37
|
-
schedule();
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
function render(anchor: Element, elements: Elements[] | null, fragment: Fragment, input: unknown, slot?: Slot) {
|
|
42
|
-
if (input === false || input == null || input === '') {
|
|
43
|
-
return;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
let type = typeof input;
|
|
47
|
-
|
|
48
|
-
if (type === 'object' && RENDERABLE in (input as Record<PropertyKey, unknown>)) {
|
|
49
|
-
if ((input as Record<PropertyKey, unknown>)[RENDERABLE] === RENDERABLE_REACTIVE) {
|
|
50
|
-
slot ??= new Slot(anchor);
|
|
51
|
-
hydrate.reactive(slot.nodes, fragment, input as RenderableReactive, slot);
|
|
52
|
-
}
|
|
53
|
-
else {
|
|
54
|
-
hydrate.static(elements, fragment, input as RenderableTemplate);
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
else if (type === 'string' || type === 'number') {
|
|
58
|
-
let element = text( type === 'string' ? input as string : String(input) );
|
|
59
|
-
|
|
60
|
-
if (slot) {
|
|
61
|
-
slot.text = element;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
append.call(fragment, element);
|
|
65
|
-
|
|
66
|
-
if (elements) {
|
|
67
|
-
elements.push([element]);
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
else if (isArray(input)) {
|
|
71
|
-
for (let i = 0, n = input.length; i < n; i++) {
|
|
72
|
-
render(anchor, elements, fragment, input[i], slot);
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
else if (isInstanceOf(input, NodeList)) {
|
|
76
|
-
append.call(fragment, ...input);
|
|
77
|
-
|
|
78
|
-
if (elements) {
|
|
79
|
-
elements.push([...input] as Elements);
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
else if (isInstanceOf(input, Node)) {
|
|
83
|
-
append.call(fragment, input);
|
|
84
|
-
|
|
85
|
-
if (elements) {
|
|
86
|
-
elements.push([ input as Element ]);
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
function schedule() {
|
|
92
|
-
if (scheduled) {
|
|
93
|
-
return;
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
scheduled = true;
|
|
97
|
-
microtask.add(task);
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
function task() {
|
|
101
|
-
let fn, fns;
|
|
102
|
-
|
|
103
|
-
while (fns = cleanup.next()) {
|
|
104
|
-
try {
|
|
105
|
-
while (fn = fns.pop()) {
|
|
106
|
-
fn();
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
catch { }
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
scheduled = false;
|
|
113
|
-
|
|
114
|
-
if (cleanup.length) {
|
|
115
|
-
schedule();
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
class Slot {
|
|
121
|
-
marker: Element;
|
|
122
|
-
nodes: Elements[];
|
|
123
|
-
text: Element | null = null;
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
constructor(marker: Element) {
|
|
127
|
-
ondisconnect(marker, () => this.clear());
|
|
128
|
-
|
|
129
|
-
this.marker = marker;
|
|
130
|
-
this.nodes = [];
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
get length() {
|
|
135
|
-
return this.nodes.length;
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
set length(n: number) {
|
|
139
|
-
if (n >= this.nodes.length) {
|
|
140
|
-
return;
|
|
141
|
-
}
|
|
142
|
-
else if (n === 0) {
|
|
143
|
-
this.clear();
|
|
144
|
-
}
|
|
145
|
-
else {
|
|
146
|
-
this.splice(n);
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
anchor(index: number = this.nodes.length - 1) {
|
|
152
|
-
let nodes = this.nodes[index];
|
|
153
|
-
|
|
154
|
-
return nodes ? nodes[nodes.length - 1] : this.marker;
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
clear() {
|
|
158
|
-
if (this.text) {
|
|
159
|
-
this.nodes.push([this.text]);
|
|
160
|
-
this.text = null;
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
remove(this.nodes);
|
|
164
|
-
|
|
165
|
-
return this;
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
pop() {
|
|
169
|
-
let group = this.nodes.pop();
|
|
170
|
-
|
|
171
|
-
if (group) {
|
|
172
|
-
remove([group]);
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
return this;
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
push(fragment: Fragment, ...nodes: Elements[]) {
|
|
179
|
-
this.anchor().after(fragment);
|
|
180
|
-
this.nodes.push( ...nodes );
|
|
181
|
-
|
|
182
|
-
return this;
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
render(input: unknown, state = HYDRATING) {
|
|
186
|
-
let type = typeof input;
|
|
187
|
-
|
|
188
|
-
if (type === 'function') {
|
|
189
|
-
ondisconnect(
|
|
190
|
-
this.marker,
|
|
191
|
-
effect(() => {
|
|
192
|
-
let v = (input as Function)();
|
|
193
|
-
|
|
194
|
-
if (state === HYDRATING) {
|
|
195
|
-
this.render(v, state);
|
|
196
|
-
state = CONNECTED;
|
|
197
|
-
}
|
|
198
|
-
else if (state === CONNECTED) {
|
|
199
|
-
raf.add(() => {
|
|
200
|
-
this.render(v, state);
|
|
201
|
-
});
|
|
202
|
-
}
|
|
203
|
-
})
|
|
204
|
-
);
|
|
205
|
-
|
|
206
|
-
return this;
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
let text = this.text;
|
|
210
|
-
|
|
211
|
-
if (text && text.isConnected && (input == null || type !== 'object')) {
|
|
212
|
-
nodeValue.call(text, (type === 'number' || type === 'string') ? input : '');
|
|
213
|
-
}
|
|
214
|
-
else {
|
|
215
|
-
this.clear();
|
|
216
|
-
|
|
217
|
-
let fragment = cloneNode.call(EMPTY_FRAGMENT);
|
|
218
|
-
|
|
219
|
-
render(this.marker, this.nodes, fragment, input, this);
|
|
220
|
-
|
|
221
|
-
this.marker.after(fragment);
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
return this;
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
shift() {
|
|
228
|
-
let group = this.nodes.shift();
|
|
229
|
-
|
|
230
|
-
if (group) {
|
|
231
|
-
remove([group]);
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
return this;
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
splice(start: number, stop: number = this.nodes.length, fragment?: Fragment, ...nodes: Elements[]) {
|
|
238
|
-
if (!fragment) {
|
|
239
|
-
remove( this.nodes.splice(start, stop) );
|
|
240
|
-
}
|
|
241
|
-
else {
|
|
242
|
-
this.anchor(start).after(fragment);
|
|
243
|
-
remove( this.nodes.splice(start, stop, ...nodes) )
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
return this;
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
unshift(fragment: Fragment, ...nodes: Elements[]) {
|
|
250
|
-
this.marker.after(fragment);
|
|
251
|
-
this.nodes.unshift( ...nodes );
|
|
252
|
-
|
|
253
|
-
return this;
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
const ondisconnect = (element: Element, fn: VoidFunction) => {
|
|
259
|
-
((element[CLEANUP_KEY] ??= []) as VoidFunction[]).push(fn);
|
|
260
|
-
};
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
export default (marker: Element, value: unknown) => {
|
|
264
|
-
let type = typeof value;
|
|
265
|
-
|
|
266
|
-
if (type === 'function') {
|
|
267
|
-
new Slot(marker).render(value);
|
|
268
|
-
}
|
|
269
|
-
else {
|
|
270
|
-
let fragment = cloneNode.call(EMPTY_FRAGMENT);
|
|
271
|
-
|
|
272
|
-
render(marker, null, fragment, value);
|
|
273
|
-
|
|
274
|
-
marker.after(fragment);
|
|
275
|
-
};
|
|
276
|
-
};
|
|
277
|
-
export { ondisconnect, Slot };
|