@esportsplus/template 0.28.1 → 0.29.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/.github/workflows/bump.yml +2 -2
- package/.github/workflows/dependabot.yml +1 -1
- package/.github/workflows/publish.yml +2 -2
- package/build/attributes.d.ts +7 -1
- package/build/attributes.js +86 -33
- package/build/constants.d.ts +3 -11
- package/build/constants.js +4 -32
- package/build/event/constants.d.ts +3 -0
- package/build/event/constants.js +13 -0
- package/build/event/index.d.ts +9 -1
- package/build/event/index.js +29 -35
- package/build/event/ontick.js +6 -9
- package/build/html.d.ts +9 -0
- package/build/html.js +7 -0
- package/build/index.d.ts +8 -2
- package/build/index.js +8 -1
- package/build/render.d.ts +2 -2
- package/build/render.js +2 -3
- package/build/runtime.d.ts +1 -0
- package/build/runtime.js +5 -0
- package/build/slot/array.d.ts +3 -3
- package/build/slot/array.js +11 -14
- package/build/slot/cleanup.d.ts +1 -1
- package/build/slot/cleanup.js +1 -2
- package/build/slot/effect.js +5 -7
- package/build/slot/index.js +1 -7
- package/build/slot/render.js +6 -8
- package/build/svg.d.ts +1 -1
- package/build/svg.js +1 -1
- package/build/transformer/codegen.d.ts +18 -0
- package/build/transformer/codegen.js +316 -0
- package/build/transformer/index.d.ts +12 -0
- package/build/transformer/index.js +62 -0
- package/build/transformer/parser.d.ts +18 -0
- package/build/transformer/parser.js +166 -0
- package/build/transformer/plugins/esbuild.d.ts +5 -0
- package/build/transformer/plugins/esbuild.js +35 -0
- package/build/transformer/plugins/tsc.d.ts +3 -0
- package/build/transformer/plugins/tsc.js +4 -0
- package/build/transformer/plugins/vite.d.ts +5 -0
- package/build/transformer/plugins/vite.js +37 -0
- package/build/transformer/ts-parser.d.ts +21 -0
- package/build/transformer/ts-parser.js +72 -0
- package/build/transformer/type-analyzer.d.ts +7 -0
- package/build/transformer/type-analyzer.js +230 -0
- package/build/types.d.ts +2 -3
- package/build/utilities.d.ts +7 -0
- package/build/utilities.js +31 -0
- package/package.json +11 -4
- package/src/attributes.ts +115 -51
- package/src/constants.ts +6 -53
- package/src/event/constants.ts +16 -0
- package/src/event/index.ts +36 -42
- package/src/event/onconnect.ts +1 -1
- package/src/event/onresize.ts +1 -1
- package/src/event/ontick.ts +7 -11
- package/src/html.ts +18 -0
- package/src/index.ts +8 -2
- package/src/render.ts +6 -7
- package/src/runtime.ts +8 -0
- package/src/slot/array.ts +18 -24
- package/src/slot/cleanup.ts +3 -4
- package/src/slot/effect.ts +6 -8
- package/src/slot/index.ts +2 -8
- package/src/slot/render.ts +7 -9
- package/src/svg.ts +1 -1
- package/src/transformer/codegen.ts +518 -0
- package/src/transformer/index.ts +98 -0
- package/src/transformer/parser.ts +239 -0
- package/src/transformer/plugins/esbuild.ts +46 -0
- package/src/transformer/plugins/tsc.ts +7 -0
- package/src/transformer/plugins/vite.ts +49 -0
- package/src/transformer/ts-parser.ts +123 -0
- package/src/transformer/type-analyzer.ts +334 -0
- package/src/types.ts +3 -4
- package/src/utilities.ts +52 -0
- package/storage/rewrite-analysis-2026-01-04.md +439 -0
- package/test/constants.ts +69 -0
- package/test/effects.ts +237 -0
- package/test/events.ts +318 -0
- package/test/imported-values.ts +253 -0
- package/test/nested.ts +298 -0
- package/test/slots.ts +259 -0
- package/test/spread.ts +290 -0
- package/test/static.ts +118 -0
- package/test/templates.ts +473 -0
- package/test/tsconfig.json +17 -0
- package/test/vite.config.ts +50 -0
- package/build/html/index.d.ts +0 -9
- package/build/html/index.js +0 -29
- package/build/html/parser.d.ts +0 -5
- package/build/html/parser.js +0 -165
- package/build/utilities/element.d.ts +0 -11
- package/build/utilities/element.js +0 -9
- package/build/utilities/fragment.d.ts +0 -3
- package/build/utilities/fragment.js +0 -10
- package/build/utilities/marker.d.ts +0 -2
- package/build/utilities/marker.js +0 -4
- package/build/utilities/node.d.ts +0 -9
- package/build/utilities/node.js +0 -10
- package/build/utilities/raf.d.ts +0 -2
- package/build/utilities/raf.js +0 -1
- package/build/utilities/text.d.ts +0 -2
- package/build/utilities/text.js +0 -9
- package/src/html/index.ts +0 -48
- package/src/html/parser.ts +0 -235
- package/src/utilities/element.ts +0 -28
- package/src/utilities/fragment.ts +0 -19
- package/src/utilities/marker.ts +0 -6
- package/src/utilities/node.ts +0 -29
- package/src/utilities/raf.ts +0 -1
- package/src/utilities/text.ts +0 -15
package/package.json
CHANGED
|
@@ -2,11 +2,17 @@
|
|
|
2
2
|
"author": "ICJR",
|
|
3
3
|
"dependencies": {
|
|
4
4
|
"@esportsplus/queue": "^0.2.0",
|
|
5
|
-
"@esportsplus/reactivity": "^0.
|
|
6
|
-
"@esportsplus/utilities": "^0.
|
|
5
|
+
"@esportsplus/reactivity": "^0.23.2",
|
|
6
|
+
"@esportsplus/utilities": "^0.27.2",
|
|
7
|
+
"serve": "^14.2.5"
|
|
7
8
|
},
|
|
8
9
|
"devDependencies": {
|
|
9
|
-
"@esportsplus/typescript": "^0.
|
|
10
|
+
"@esportsplus/typescript": "^0.13.0",
|
|
11
|
+
"@types/node": "^25.0.3",
|
|
12
|
+
"esbuild": "^0.27.2",
|
|
13
|
+
"typescript": "^5.9.3",
|
|
14
|
+
"vite": "^7.3.0",
|
|
15
|
+
"vite-tsconfig-paths": "^6.0.3"
|
|
10
16
|
},
|
|
11
17
|
"main": "./build/index.js",
|
|
12
18
|
"name": "@esportsplus/template",
|
|
@@ -17,9 +23,10 @@
|
|
|
17
23
|
},
|
|
18
24
|
"type": "module",
|
|
19
25
|
"types": "./build/index.d.ts",
|
|
20
|
-
"version": "0.
|
|
26
|
+
"version": "0.29.1",
|
|
21
27
|
"scripts": {
|
|
22
28
|
"build": "tsc && tsc-alias",
|
|
29
|
+
"compile:test": "vite build --config test/vite.config.ts",
|
|
23
30
|
"-": "-"
|
|
24
31
|
}
|
|
25
32
|
}
|
package/src/attributes.ts
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import { effect } from '@esportsplus/reactivity';
|
|
2
2
|
import { isArray, isObject } from '@esportsplus/utilities';
|
|
3
|
-
import { STATE_HYDRATING, STATE_NONE, STATE_WAITING } from './constants';
|
|
3
|
+
import { DIRECT_ATTACH_EVENTS, LIFECYCLE_EVENTS, STATE_HYDRATING, STATE_NONE, STATE_WAITING } from './constants';
|
|
4
4
|
import { Attributes, Element } from './types';
|
|
5
|
-
import {
|
|
5
|
+
import { raf } from './utilities';
|
|
6
6
|
import q from '@esportsplus/queue';
|
|
7
|
-
import raf from './utilities/raf';
|
|
8
7
|
import event from './event';
|
|
9
8
|
|
|
10
9
|
|
|
@@ -32,13 +31,13 @@ let delimiters: Record<string, string> = {
|
|
|
32
31
|
|
|
33
32
|
function apply(element: Element, name: string, value: unknown) {
|
|
34
33
|
if (value == null || value === false || value === '') {
|
|
35
|
-
removeAttribute
|
|
34
|
+
element.removeAttribute(name);
|
|
36
35
|
}
|
|
37
36
|
else if (name === 'class') {
|
|
38
|
-
className
|
|
37
|
+
element.className = value as string;
|
|
39
38
|
}
|
|
40
39
|
else if (name === 'style' || (name[0] === 'd' && name.startsWith('data-')) || element['ownerSVGElement']) {
|
|
41
|
-
setAttribute
|
|
40
|
+
element.setAttribute(name, value as string);
|
|
42
41
|
}
|
|
43
42
|
else {
|
|
44
43
|
element[name] = value;
|
|
@@ -62,6 +61,7 @@ function list(
|
|
|
62
61
|
}
|
|
63
62
|
|
|
64
63
|
let base = name + '.static',
|
|
64
|
+
changed = false,
|
|
65
65
|
delimiter = delimiters[name],
|
|
66
66
|
store = (ctx ??= context(element)).store ??= {},
|
|
67
67
|
dynamic = store[name] as Set<string> | undefined;
|
|
@@ -75,10 +75,17 @@ function list(
|
|
|
75
75
|
|
|
76
76
|
if (id === null) {
|
|
77
77
|
if (value && typeof value === 'string') {
|
|
78
|
+
changed = true;
|
|
78
79
|
store[base] += (store[base] ? delimiter : '') + value;
|
|
79
80
|
}
|
|
80
81
|
}
|
|
81
82
|
else {
|
|
83
|
+
if (store[id + '.raw'] === value) {
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
store[id + '.raw'] = value;
|
|
88
|
+
|
|
82
89
|
let hot: Record<PropertyKey, true> = {};
|
|
83
90
|
|
|
84
91
|
if (value && typeof value === 'string') {
|
|
@@ -92,7 +99,11 @@ function list(
|
|
|
92
99
|
continue;
|
|
93
100
|
}
|
|
94
101
|
|
|
95
|
-
dynamic.
|
|
102
|
+
if (!dynamic.has(part)) {
|
|
103
|
+
changed = true;
|
|
104
|
+
dynamic.add(part);
|
|
105
|
+
}
|
|
106
|
+
|
|
96
107
|
hot[part] = true;
|
|
97
108
|
}
|
|
98
109
|
}
|
|
@@ -105,6 +116,7 @@ function list(
|
|
|
105
116
|
continue;
|
|
106
117
|
}
|
|
107
118
|
|
|
119
|
+
changed = true;
|
|
108
120
|
dynamic.delete(part);
|
|
109
121
|
}
|
|
110
122
|
}
|
|
@@ -112,6 +124,10 @@ function list(
|
|
|
112
124
|
store[id] = hot;
|
|
113
125
|
}
|
|
114
126
|
|
|
127
|
+
if (!changed) {
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
|
|
115
131
|
value = store[base];
|
|
116
132
|
|
|
117
133
|
for (let key of dynamic) {
|
|
@@ -156,6 +172,41 @@ function property(
|
|
|
156
172
|
}
|
|
157
173
|
}
|
|
158
174
|
|
|
175
|
+
function reactive(element: Element, name: string, state: State, value: unknown) {
|
|
176
|
+
let ctx = context(element),
|
|
177
|
+
fn = name === 'class' || name === 'style' ? list : property;
|
|
178
|
+
|
|
179
|
+
ctx.effect ??= 0;
|
|
180
|
+
|
|
181
|
+
let id = (ctx.effect as number)++;
|
|
182
|
+
|
|
183
|
+
effect(() => {
|
|
184
|
+
let v = (value as Function)(element);
|
|
185
|
+
|
|
186
|
+
if (v == null || typeof v !== 'object') {
|
|
187
|
+
fn(ctx, element, id, name, state, v);
|
|
188
|
+
}
|
|
189
|
+
else if (isArray(v)) {
|
|
190
|
+
let last = v.length - 1;
|
|
191
|
+
|
|
192
|
+
for (let i = 0, n = v.length; i < n; i++) {
|
|
193
|
+
fn(
|
|
194
|
+
ctx,
|
|
195
|
+
element,
|
|
196
|
+
id,
|
|
197
|
+
name,
|
|
198
|
+
state === STATE_HYDRATING
|
|
199
|
+
? state
|
|
200
|
+
: i !== last ? STATE_WAITING : state,
|
|
201
|
+
v[i],
|
|
202
|
+
);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
state = STATE_NONE;
|
|
208
|
+
}
|
|
209
|
+
|
|
159
210
|
function schedule(ctx: Context | null, element: Element, name: string, state: State, value: unknown) {
|
|
160
211
|
ctx ??= context(element);
|
|
161
212
|
(ctx.updates ??= {})[name] = value;
|
|
@@ -198,50 +249,27 @@ function task() {
|
|
|
198
249
|
|
|
199
250
|
|
|
200
251
|
const set = (element: Element, name: string, value: unknown) => {
|
|
201
|
-
let fn = name === 'class' || name === 'style' ? list : property,
|
|
202
|
-
state: State = STATE_HYDRATING;
|
|
203
|
-
|
|
204
252
|
if (typeof value === 'function') {
|
|
205
253
|
if (name[0] === 'o' && name[1] === 'n') {
|
|
206
|
-
|
|
207
|
-
|
|
254
|
+
let e = name.slice(2).toLowerCase(),
|
|
255
|
+
key = name.toLowerCase();
|
|
208
256
|
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
ctx.effect ??= 0;
|
|
212
|
-
|
|
213
|
-
let id = (ctx.effect as number)++;
|
|
214
|
-
|
|
215
|
-
effect(() => {
|
|
216
|
-
let v = (value as Function)(element);
|
|
217
|
-
|
|
218
|
-
if (v == null || typeof v !== 'object') {
|
|
219
|
-
fn(ctx, element, id, name, state, v);
|
|
257
|
+
if (LIFECYCLE_EVENTS.has(key)) {
|
|
258
|
+
(event as any)[key](element, value as Function);
|
|
220
259
|
}
|
|
221
|
-
else if (
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
for (let i = 0, n = v.length; i < n; i++) {
|
|
225
|
-
fn(
|
|
226
|
-
ctx,
|
|
227
|
-
element,
|
|
228
|
-
id,
|
|
229
|
-
name,
|
|
230
|
-
state === STATE_HYDRATING
|
|
231
|
-
? state
|
|
232
|
-
: i !== last ? STATE_WAITING : state,
|
|
233
|
-
v[i],
|
|
234
|
-
);
|
|
235
|
-
}
|
|
260
|
+
else if (DIRECT_ATTACH_EVENTS.has(key)) {
|
|
261
|
+
event.direct(element, e, value as Function);
|
|
236
262
|
}
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
263
|
+
else {
|
|
264
|
+
event.delegate(element, e, value as Function);
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
else {
|
|
268
|
+
reactive(element, name, STATE_HYDRATING, value);
|
|
269
|
+
}
|
|
241
270
|
return;
|
|
242
271
|
}
|
|
243
|
-
|
|
244
|
-
if (typeof value !== 'object') {
|
|
272
|
+
else if (typeof value !== 'object') {
|
|
245
273
|
// Skip isArray when possible
|
|
246
274
|
}
|
|
247
275
|
else if (isArray(value)) {
|
|
@@ -257,15 +285,51 @@ const set = (element: Element, name: string, value: unknown) => {
|
|
|
257
285
|
return;
|
|
258
286
|
}
|
|
259
287
|
|
|
260
|
-
|
|
288
|
+
(name === 'class' || name === 'style' ? list : property)(null, element, null, name, STATE_HYDRATING, value);
|
|
289
|
+
};
|
|
290
|
+
|
|
291
|
+
const setClass = (element: Element, classlist: false | string | undefined, value: unknown) => {
|
|
292
|
+
let ctx = context(element),
|
|
293
|
+
store = ctx.store ??= {};
|
|
294
|
+
|
|
295
|
+
store['class.static'] = classlist || '';
|
|
296
|
+
store['class'] ??= new Set<string>();
|
|
297
|
+
|
|
298
|
+
if (typeof value === 'function') {
|
|
299
|
+
reactive(element, 'class', STATE_HYDRATING, value);
|
|
300
|
+
}
|
|
301
|
+
else {
|
|
302
|
+
list(ctx, element, null, 'class', STATE_HYDRATING, value);
|
|
303
|
+
}
|
|
304
|
+
};
|
|
305
|
+
|
|
306
|
+
const setProperty = (element: Element, name: string, value: unknown) => {
|
|
307
|
+
if (typeof value === 'function') {
|
|
308
|
+
reactive(element, name, STATE_HYDRATING, value);
|
|
309
|
+
}
|
|
310
|
+
else {
|
|
311
|
+
property(null, element, null, name, STATE_HYDRATING, value);
|
|
312
|
+
}
|
|
313
|
+
};
|
|
314
|
+
|
|
315
|
+
const setStyle = (element: Element, styles: false | string | undefined, value: unknown) => {
|
|
316
|
+
let ctx = context(element),
|
|
317
|
+
store = ctx.store ??= {};
|
|
318
|
+
|
|
319
|
+
store['style.static'] = styles || '';
|
|
320
|
+
store['style'] ??= new Set<string>();
|
|
321
|
+
|
|
322
|
+
if (typeof value === 'function') {
|
|
323
|
+
reactive(element, 'style', STATE_HYDRATING, value);
|
|
324
|
+
}
|
|
325
|
+
else {
|
|
326
|
+
list(ctx, element, null, 'style', STATE_HYDRATING, value);
|
|
327
|
+
}
|
|
261
328
|
};
|
|
262
329
|
|
|
263
330
|
const spread = function (element: Element, value: Attributes | Attributes[]) {
|
|
264
331
|
if (isObject(value)) {
|
|
265
|
-
let
|
|
266
|
-
name;
|
|
267
|
-
|
|
268
|
-
while (name = names.pop()) {
|
|
332
|
+
for (let name in value) {
|
|
269
333
|
let v = value[name];
|
|
270
334
|
|
|
271
335
|
if (v == null || v === false || v === '') {
|
|
@@ -283,5 +347,5 @@ const spread = function (element: Element, value: Attributes | Attributes[]) {
|
|
|
283
347
|
};
|
|
284
348
|
|
|
285
349
|
|
|
286
|
-
export default { set, spread };
|
|
287
|
-
export { set, spread };
|
|
350
|
+
export default { set, setClass, setProperty, setStyle, spread };
|
|
351
|
+
export { set, setClass, setProperty, setStyle, spread };
|
package/src/constants.ts
CHANGED
|
@@ -1,74 +1,27 @@
|
|
|
1
|
-
import { fragment } from './utilities
|
|
1
|
+
import { fragment } from './utilities';
|
|
2
2
|
|
|
3
3
|
|
|
4
4
|
const ARRAY_SLOT = Symbol('template.array.slot');
|
|
5
5
|
|
|
6
|
-
|
|
7
6
|
const CLEANUP = Symbol('template.cleanup');
|
|
8
7
|
|
|
9
|
-
|
|
10
8
|
const EMPTY_FRAGMENT = fragment('');
|
|
11
9
|
|
|
12
|
-
|
|
13
|
-
const NODE_CLOSING = 1;
|
|
14
|
-
|
|
15
|
-
const NODE_COMMENT = 2;
|
|
16
|
-
|
|
17
|
-
const NODE_ELEMENT = 3;
|
|
18
|
-
|
|
19
|
-
const NODE_SLOT = 4;
|
|
20
|
-
|
|
21
|
-
const NODE_VOID = 5;
|
|
22
|
-
|
|
23
|
-
const NODE_WHITELIST: Record<string, number> = {
|
|
24
|
-
'/': NODE_CLOSING,
|
|
25
|
-
'!': NODE_COMMENT,
|
|
26
|
-
|
|
27
|
-
'area': NODE_VOID,
|
|
28
|
-
'base': NODE_VOID,
|
|
29
|
-
'br': NODE_VOID,
|
|
30
|
-
'col': NODE_VOID,
|
|
31
|
-
'embed': NODE_VOID,
|
|
32
|
-
'hr': NODE_VOID,
|
|
33
|
-
'img': NODE_VOID,
|
|
34
|
-
'input': NODE_VOID,
|
|
35
|
-
'keygen': NODE_VOID,
|
|
36
|
-
'link': NODE_VOID,
|
|
37
|
-
'menuitem': NODE_VOID,
|
|
38
|
-
'meta': NODE_VOID,
|
|
39
|
-
'param': NODE_VOID,
|
|
40
|
-
'source': NODE_VOID,
|
|
41
|
-
'track': NODE_VOID,
|
|
42
|
-
'wbr': NODE_VOID
|
|
43
|
-
};
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
const REGEX_EMPTY_TEXT_NODES = /(>|}|\s)\s+(<|{|\s)/g;
|
|
47
|
-
|
|
48
|
-
const REGEX_EVENTS = /(?:\s*on[\w-:]+\s*=(?:\s*["'][^"']*["'])*)/g;
|
|
49
|
-
|
|
50
|
-
const REGEX_SLOT_ATTRIBUTES = /<[\w-]+([^><]*{{\$}}[^><]*)>/g;
|
|
51
|
-
|
|
52
|
-
const REGEX_SLOT_NODES = /<([\w-]+|[\/!])(?:([^><]*{{\$}}[^><]*)|(?:[^><]*))?>|{{\$}}/g;
|
|
53
|
-
|
|
54
|
-
|
|
55
10
|
const SLOT_HTML = '<!--$-->';
|
|
56
11
|
|
|
57
|
-
const SLOT_MARKER = '{{$}}';
|
|
58
|
-
|
|
59
|
-
|
|
60
12
|
const STATE_HYDRATING = 0;
|
|
61
13
|
|
|
62
14
|
const STATE_NONE = 1;
|
|
63
15
|
|
|
64
16
|
const STATE_WAITING = 2;
|
|
65
17
|
|
|
18
|
+
const STORE = Symbol('template.store');
|
|
19
|
+
|
|
66
20
|
|
|
67
21
|
export {
|
|
68
22
|
ARRAY_SLOT,
|
|
69
23
|
CLEANUP,
|
|
70
24
|
EMPTY_FRAGMENT,
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
};
|
|
25
|
+
SLOT_HTML, STATE_HYDRATING, STATE_NONE, STATE_WAITING, STORE
|
|
26
|
+
};
|
|
27
|
+
export * from './event/constants';
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
const DIRECT_ATTACH_EVENTS = new Set<string>([
|
|
2
|
+
'onblur',
|
|
3
|
+
'onerror',
|
|
4
|
+
'onfocus', 'onfocusin', 'onfocusout',
|
|
5
|
+
'onload',
|
|
6
|
+
'onplay', 'onpause', 'onended', 'ontimeupdate',
|
|
7
|
+
'onreset',
|
|
8
|
+
'onscroll', 'onsubmit'
|
|
9
|
+
]);
|
|
10
|
+
|
|
11
|
+
const LIFECYCLE_EVENTS = new Set<string>([
|
|
12
|
+
'onconnect', 'ondisconnect', 'onrender', 'onresize', 'ontick'
|
|
13
|
+
]);
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
export { DIRECT_ATTACH_EVENTS, LIFECYCLE_EVENTS };
|
package/src/event/index.ts
CHANGED
|
@@ -1,36 +1,31 @@
|
|
|
1
1
|
import { root } from '@esportsplus/reactivity';
|
|
2
2
|
import { defineProperty } from '@esportsplus/utilities';
|
|
3
3
|
import { Element } from '~/types';
|
|
4
|
-
import {
|
|
5
|
-
import { parentElement } from '~/utilities/node';
|
|
6
|
-
import { ondisconnect } from '~/slot/cleanup';
|
|
4
|
+
import { ondisconnect as disconnect } from '~/slot/cleanup';
|
|
7
5
|
import onconnect from './onconnect';
|
|
8
6
|
import onresize from './onresize';
|
|
9
7
|
import ontick from './ontick';
|
|
10
8
|
|
|
11
9
|
|
|
12
|
-
let
|
|
13
|
-
|
|
14
|
-
`on${string}`,
|
|
15
|
-
(AbortController & { listeners: number }) | null
|
|
16
|
-
>(),
|
|
10
|
+
let controllers = new Map<string, (AbortController & { listeners: number }) | null>(),
|
|
11
|
+
host = window.document,
|
|
17
12
|
keys: Record<string, symbol> = {},
|
|
18
|
-
passive = new Set
|
|
19
|
-
'
|
|
20
|
-
'
|
|
21
|
-
'
|
|
22
|
-
'
|
|
23
|
-
'
|
|
24
|
-
'
|
|
13
|
+
passive = new Set<string>([
|
|
14
|
+
'animationend', 'animationiteration', 'animationstart',
|
|
15
|
+
'mousedown', 'mouseenter', 'mouseleave', 'mousemove', 'mouseout', 'mouseover', 'mouseup', 'mousewheel',
|
|
16
|
+
'pointerenter', 'pointerleave', 'pointermove', 'pointerout', 'pointerover',
|
|
17
|
+
'scroll',
|
|
18
|
+
'touchcancel', 'touchend', 'touchleave', 'touchmove', 'touchstart', 'transitionend',
|
|
19
|
+
'wheel'
|
|
25
20
|
]);
|
|
26
21
|
|
|
27
22
|
|
|
28
|
-
(['
|
|
23
|
+
(['mousemove', 'mousewheel', 'scroll', 'touchend', 'touchmove', 'touchstart', 'wheel'] as string[]).map(event => {
|
|
29
24
|
controllers.set(event, null);
|
|
30
25
|
});
|
|
31
26
|
|
|
32
27
|
|
|
33
|
-
function register(element: Element, event:
|
|
28
|
+
function register(element: Element, event: string) {
|
|
34
29
|
let controller = controllers.get(event),
|
|
35
30
|
signal: AbortController['signal'] | undefined;
|
|
36
31
|
|
|
@@ -63,7 +58,7 @@ function register(element: Element, event: `on${string}`) {
|
|
|
63
58
|
|
|
64
59
|
let key = keys[event] = Symbol();
|
|
65
60
|
|
|
66
|
-
addEventListener
|
|
61
|
+
host.addEventListener(event.slice(2), (e) => {
|
|
67
62
|
let fn,
|
|
68
63
|
node = e.target as Element | null;
|
|
69
64
|
|
|
@@ -81,10 +76,9 @@ function register(element: Element, event: `on${string}`) {
|
|
|
81
76
|
return fn.call(node, e);
|
|
82
77
|
}
|
|
83
78
|
|
|
84
|
-
node = parentElement
|
|
79
|
+
node = node.parentElement as Element | null;
|
|
85
80
|
}
|
|
86
81
|
}, {
|
|
87
|
-
capture: capture.has(event),
|
|
88
82
|
passive: passive.has(event),
|
|
89
83
|
signal
|
|
90
84
|
});
|
|
@@ -93,30 +87,30 @@ function register(element: Element, event: `on${string}`) {
|
|
|
93
87
|
}
|
|
94
88
|
|
|
95
89
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
onconnect(element, listener);
|
|
100
|
-
return;
|
|
90
|
+
const delegate = (element: Element, event: string, listener: Function): void => {
|
|
91
|
+
element[ keys[event] || register(element, event) ] = listener;
|
|
92
|
+
};
|
|
101
93
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
94
|
+
// DIRECT_ATTACH_EVENTS in ./constants.ts tells compiler to use this function
|
|
95
|
+
const direct = (element: Element, event: string, listener: Function): void => {
|
|
96
|
+
let handler = (e: Event) => listener.call(element, e);
|
|
105
97
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
98
|
+
element.addEventListener(event, handler, {
|
|
99
|
+
passive: passive.has(event)
|
|
100
|
+
});
|
|
109
101
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
102
|
+
ondisconnect(element, () => {
|
|
103
|
+
element.removeEventListener(event, handler);
|
|
104
|
+
});
|
|
105
|
+
};
|
|
113
106
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
107
|
+
const ondisconnect = (element: Element, listener: Function) => {
|
|
108
|
+
disconnect(element, () => listener(element));
|
|
109
|
+
};
|
|
117
110
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
111
|
+
const onrender = (element: Element, listener: Function) => {
|
|
112
|
+
root(() => listener(element));
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
export default { delegate, direct, onconnect, ondisconnect, onrender, onresize, ontick };
|
package/src/event/onconnect.ts
CHANGED
package/src/event/onresize.ts
CHANGED
package/src/event/ontick.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import raf from '~/utilities/raf';
|
|
1
|
+
import { raf } from '~/utilities';
|
|
3
2
|
|
|
4
3
|
|
|
5
4
|
let tasks = Object.assign(new Set<VoidFunction>(), { running: false });
|
|
@@ -34,13 +33,11 @@ const remove = (task: VoidFunction) => {
|
|
|
34
33
|
|
|
35
34
|
|
|
36
35
|
export default (element: Element, listener: Function) => {
|
|
37
|
-
let
|
|
38
|
-
remove(fn);
|
|
39
|
-
},
|
|
36
|
+
let connected = false,
|
|
40
37
|
fn = () => {
|
|
41
|
-
if (
|
|
38
|
+
if (connected === false) {
|
|
42
39
|
if (element.isConnected) {
|
|
43
|
-
|
|
40
|
+
connected = true;
|
|
44
41
|
}
|
|
45
42
|
else if (retry--) {
|
|
46
43
|
return;
|
|
@@ -52,11 +49,10 @@ export default (element: Element, listener: Function) => {
|
|
|
52
49
|
return;
|
|
53
50
|
}
|
|
54
51
|
|
|
55
|
-
listener(
|
|
52
|
+
listener(() => remove(fn), element);
|
|
56
53
|
},
|
|
57
|
-
retry = 60
|
|
58
|
-
state = STATE_HYDRATING;
|
|
54
|
+
retry = 60;
|
|
59
55
|
|
|
60
56
|
add(fn);
|
|
61
57
|
};
|
|
62
|
-
export { add, remove };
|
|
58
|
+
export { add, remove };
|
package/src/html.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { ReactiveArray } from '@esportsplus/reactivity';
|
|
2
|
+
import { Attribute, Attributes, Renderable } from '~/types';
|
|
3
|
+
import { ArraySlot } from '~/slot/array';
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
type Values<T> = Attribute | Attributes<any> | ArraySlot<T> | Renderable<T>;
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
const html = <T>(_literals: TemplateStringsArray, ..._values: (Values<T> | Values<T>[])[]): DocumentFragment => {
|
|
10
|
+
throw new Error('html`` templates must be compiled. Ensure vite-plugin is configured.');
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
html.reactive = <T>(_arr: ReactiveArray<T>, _template: (value: T) => DocumentFragment): ArraySlot<T> => {
|
|
14
|
+
throw new Error('html.reactive() must be compiled. Ensure vite-plugin is configured.');
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
export default html;
|
package/src/index.ts
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
|
+
import './runtime';
|
|
2
|
+
export { default as attributes } from './attributes';
|
|
3
|
+
export { default as event } from './event';
|
|
1
4
|
export { default as html } from './html';
|
|
2
5
|
export { default as render } from './render';
|
|
6
|
+
export { default as slot } from './slot';
|
|
3
7
|
export { default as svg } from './svg';
|
|
4
|
-
export
|
|
5
|
-
export
|
|
8
|
+
export { ArraySlot } from './slot/array';
|
|
9
|
+
export { EffectSlot } from './slot/effect';
|
|
10
|
+
export type { Attributes, Element, Renderable } from './types';
|
|
11
|
+
export * from './utilities';
|
package/src/render.ts
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
|
-
import { Renderable } from './types';
|
|
2
|
-
import {
|
|
3
|
-
import marker from './utilities/marker';
|
|
1
|
+
import { Effect, Element, Renderable } from './types';
|
|
2
|
+
import { marker } from './utilities';
|
|
4
3
|
import slot from './slot';
|
|
5
4
|
|
|
6
5
|
|
|
7
|
-
export default <T>(parent: HTMLElement, renderable: Renderable<T
|
|
8
|
-
let anchor = marker.cloneNode();
|
|
6
|
+
export default <T>(parent: HTMLElement, renderable: Exclude<Renderable<T>, Effect<T>>) => {
|
|
7
|
+
let anchor = marker.cloneNode() as unknown as Element;
|
|
9
8
|
|
|
10
|
-
nodeValue
|
|
9
|
+
parent.nodeValue = '';
|
|
11
10
|
parent.append(anchor);
|
|
12
11
|
|
|
13
12
|
slot(anchor, renderable);
|
|
14
|
-
};
|
|
13
|
+
};
|
package/src/runtime.ts
ADDED