@esportsplus/template 0.32.3 → 0.32.4
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 -11
- package/build/attributes.js +36 -46
- package/build/constants.d.ts +9 -9
- package/build/constants.js +9 -9
- package/build/event/index.d.ts +9 -10
- package/build/event/index.js +18 -2
- package/build/index.d.ts +2 -2
- package/build/index.js +2 -2
- package/build/transformer/codegen.js +2 -2
- package/build/transformer/parser.d.ts +2 -2
- package/build/transformer/parser.js +10 -11
- package/build/transformer/type-analyzer.js +9 -9
- package/build/types.d.ts +2 -2
- package/package.json +1 -1
- package/src/attributes.ts +47 -59
- package/src/constants.ts +9 -9
- package/src/event/index.ts +23 -2
- package/src/index.ts +2 -2
- package/src/transformer/codegen.ts +7 -7
- package/src/transformer/parser.ts +12 -19
- package/src/transformer/type-analyzer.ts +9 -9
- package/src/types.ts +2 -2
package/build/attributes.d.ts
CHANGED
|
@@ -1,15 +1,6 @@
|
|
|
1
1
|
import { Attributes, Element } from './types.js';
|
|
2
|
-
declare const set: (element: Element, name: string, value: unknown) => void;
|
|
3
2
|
declare const setClass: (element: Element, classlist: false | string | undefined, value: unknown) => void;
|
|
4
3
|
declare const setProperty: (element: Element, name: string, value: unknown) => void;
|
|
4
|
+
declare const setProperties: (element: Element, value: Attributes | Attributes[]) => void;
|
|
5
5
|
declare const setStyle: (element: Element, styles: false | string | undefined, value: unknown) => void;
|
|
6
|
-
|
|
7
|
-
declare const _default: {
|
|
8
|
-
set: (element: Element, name: string, value: unknown) => void;
|
|
9
|
-
setClass: (element: Element, classlist: false | string | undefined, value: unknown) => void;
|
|
10
|
-
setProperty: (element: Element, name: string, value: unknown) => void;
|
|
11
|
-
setStyle: (element: Element, styles: false | string | undefined, value: unknown) => void;
|
|
12
|
-
spread: (element: Element, value: Attributes | Attributes[]) => void;
|
|
13
|
-
};
|
|
14
|
-
export default _default;
|
|
15
|
-
export { set, setClass, setProperty, setStyle, spread };
|
|
6
|
+
export { setClass, setProperty, setProperties, setStyle };
|
package/build/attributes.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { effect } from '@esportsplus/reactivity';
|
|
2
2
|
import { isArray, isObject } from '@esportsplus/utilities';
|
|
3
|
-
import {
|
|
3
|
+
import { STATE_HYDRATING, STATE_NONE, STATE_WAITING, STORE } from './constants.js';
|
|
4
4
|
import { raf } from './utilities.js';
|
|
5
5
|
import q from '@esportsplus/queue';
|
|
6
|
-
import
|
|
6
|
+
import { runtime } from './event/index.js';
|
|
7
7
|
let delimiters = {
|
|
8
8
|
class: ' ',
|
|
9
9
|
style: ';'
|
|
@@ -138,36 +138,10 @@ function schedule(ctx, element, name, state, value) {
|
|
|
138
138
|
scheduled = true;
|
|
139
139
|
raf(task);
|
|
140
140
|
}
|
|
141
|
-
function
|
|
142
|
-
let context, n = queue.length;
|
|
143
|
-
while ((context = queue.next()) && n--) {
|
|
144
|
-
let { element, updates } = context;
|
|
145
|
-
for (let name in updates) {
|
|
146
|
-
apply(element, name, updates[name]);
|
|
147
|
-
}
|
|
148
|
-
context.updates = {};
|
|
149
|
-
context.updating = false;
|
|
150
|
-
}
|
|
151
|
-
if (queue.length) {
|
|
152
|
-
raf(task);
|
|
153
|
-
}
|
|
154
|
-
else {
|
|
155
|
-
scheduled = false;
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
const set = (element, name, value) => {
|
|
141
|
+
function set(element, name, value) {
|
|
159
142
|
if (typeof value === 'function') {
|
|
160
143
|
if (name[0] === 'o' && name[1] === 'n') {
|
|
161
|
-
|
|
162
|
-
if (LIFECYCLE_EVENTS.has(key)) {
|
|
163
|
-
event[key](element, value);
|
|
164
|
-
}
|
|
165
|
-
else if (DIRECT_ATTACH_EVENTS.has(key)) {
|
|
166
|
-
event.direct(element, e, value);
|
|
167
|
-
}
|
|
168
|
-
else {
|
|
169
|
-
event.delegate(element, e, value);
|
|
170
|
-
}
|
|
144
|
+
runtime(element, name, value);
|
|
171
145
|
}
|
|
172
146
|
else {
|
|
173
147
|
reactive(element, name, STATE_HYDRATING, value);
|
|
@@ -187,7 +161,24 @@ const set = (element, name, value) => {
|
|
|
187
161
|
return;
|
|
188
162
|
}
|
|
189
163
|
(name === 'class' || name === 'style' ? list : property)(null, element, null, name, STATE_HYDRATING, value);
|
|
190
|
-
}
|
|
164
|
+
}
|
|
165
|
+
function task() {
|
|
166
|
+
let context, n = queue.length;
|
|
167
|
+
while ((context = queue.next()) && n--) {
|
|
168
|
+
let { element, updates } = context;
|
|
169
|
+
for (let name in updates) {
|
|
170
|
+
apply(element, name, updates[name]);
|
|
171
|
+
}
|
|
172
|
+
context.updates = {};
|
|
173
|
+
context.updating = false;
|
|
174
|
+
}
|
|
175
|
+
if (queue.length) {
|
|
176
|
+
raf(task);
|
|
177
|
+
}
|
|
178
|
+
else {
|
|
179
|
+
scheduled = false;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
191
182
|
const setClass = (element, classlist, value) => {
|
|
192
183
|
let ctx = context(element), store = ctx.store ??= {};
|
|
193
184
|
store['class.static'] = classlist || '';
|
|
@@ -207,18 +198,7 @@ const setProperty = (element, name, value) => {
|
|
|
207
198
|
property(null, element, null, name, STATE_HYDRATING, value);
|
|
208
199
|
}
|
|
209
200
|
};
|
|
210
|
-
const
|
|
211
|
-
let ctx = context(element), store = ctx.store ??= {};
|
|
212
|
-
store['style.static'] = styles || '';
|
|
213
|
-
store['style'] ??= new Set();
|
|
214
|
-
if (typeof value === 'function') {
|
|
215
|
-
reactive(element, 'style', STATE_HYDRATING, value);
|
|
216
|
-
}
|
|
217
|
-
else {
|
|
218
|
-
list(ctx, element, null, 'style', STATE_HYDRATING, value);
|
|
219
|
-
}
|
|
220
|
-
};
|
|
221
|
-
const spread = function (element, value) {
|
|
201
|
+
const setProperties = function (element, value) {
|
|
222
202
|
if (isObject(value)) {
|
|
223
203
|
for (let name in value) {
|
|
224
204
|
let v = value[name];
|
|
@@ -230,9 +210,19 @@ const spread = function (element, value) {
|
|
|
230
210
|
}
|
|
231
211
|
else if (isArray(value)) {
|
|
232
212
|
for (let i = 0, n = value.length; i < n; i++) {
|
|
233
|
-
|
|
213
|
+
setProperties(element, value[i]);
|
|
234
214
|
}
|
|
235
215
|
}
|
|
236
216
|
};
|
|
237
|
-
|
|
238
|
-
|
|
217
|
+
const setStyle = (element, styles, value) => {
|
|
218
|
+
let ctx = context(element), store = ctx.store ??= {};
|
|
219
|
+
store['style.static'] = styles || '';
|
|
220
|
+
store['style'] ??= new Set();
|
|
221
|
+
if (typeof value === 'function') {
|
|
222
|
+
reactive(element, 'style', STATE_HYDRATING, value);
|
|
223
|
+
}
|
|
224
|
+
else {
|
|
225
|
+
list(ctx, element, null, 'style', STATE_HYDRATING, value);
|
|
226
|
+
}
|
|
227
|
+
};
|
|
228
|
+
export { setClass, setProperty, setProperties, setStyle };
|
package/build/constants.d.ts
CHANGED
|
@@ -4,15 +4,15 @@ declare const COMPILER_ENTRYPOINT = "html";
|
|
|
4
4
|
declare const COMPILER_ENTRYPOINT_REACTIVITY = "reactive";
|
|
5
5
|
declare const COMPILER_NAMESPACE: string;
|
|
6
6
|
declare const enum COMPILER_TYPES {
|
|
7
|
-
ArraySlot =
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
DocumentFragment =
|
|
11
|
-
Effect =
|
|
12
|
-
|
|
13
|
-
Primitive =
|
|
14
|
-
Static =
|
|
15
|
-
Unknown =
|
|
7
|
+
ArraySlot = "array-slot",
|
|
8
|
+
Attributes = "attributes",
|
|
9
|
+
Attribute = "attribute",
|
|
10
|
+
DocumentFragment = "document-fragment",
|
|
11
|
+
Effect = "effect",
|
|
12
|
+
Node = "node",
|
|
13
|
+
Primitive = "primitive",
|
|
14
|
+
Static = "static",
|
|
15
|
+
Unknown = "unknown"
|
|
16
16
|
}
|
|
17
17
|
declare const DIRECT_ATTACH_EVENTS: Set<string>;
|
|
18
18
|
declare const LIFECYCLE_EVENTS: Set<string>;
|
package/build/constants.js
CHANGED
|
@@ -6,15 +6,15 @@ const COMPILER_ENTRYPOINT_REACTIVITY = 'reactive';
|
|
|
6
6
|
const COMPILER_NAMESPACE = uid('template');
|
|
7
7
|
var COMPILER_TYPES;
|
|
8
8
|
(function (COMPILER_TYPES) {
|
|
9
|
-
COMPILER_TYPES[
|
|
10
|
-
COMPILER_TYPES[
|
|
11
|
-
COMPILER_TYPES[
|
|
12
|
-
COMPILER_TYPES[
|
|
13
|
-
COMPILER_TYPES[
|
|
14
|
-
COMPILER_TYPES[
|
|
15
|
-
COMPILER_TYPES[
|
|
16
|
-
COMPILER_TYPES[
|
|
17
|
-
COMPILER_TYPES[
|
|
9
|
+
COMPILER_TYPES["ArraySlot"] = "array-slot";
|
|
10
|
+
COMPILER_TYPES["Attributes"] = "attributes";
|
|
11
|
+
COMPILER_TYPES["Attribute"] = "attribute";
|
|
12
|
+
COMPILER_TYPES["DocumentFragment"] = "document-fragment";
|
|
13
|
+
COMPILER_TYPES["Effect"] = "effect";
|
|
14
|
+
COMPILER_TYPES["Node"] = "node";
|
|
15
|
+
COMPILER_TYPES["Primitive"] = "primitive";
|
|
16
|
+
COMPILER_TYPES["Static"] = "static";
|
|
17
|
+
COMPILER_TYPES["Unknown"] = "unknown";
|
|
18
18
|
})(COMPILER_TYPES || (COMPILER_TYPES = {}));
|
|
19
19
|
;
|
|
20
20
|
const DIRECT_ATTACH_EVENTS = new Set([
|
package/build/event/index.d.ts
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import { Element } from '../types.js';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
};
|
|
11
|
-
export default _default;
|
|
2
|
+
import onconnect from './onconnect.js';
|
|
3
|
+
import onresize from './onresize.js';
|
|
4
|
+
import ontick from './ontick.js';
|
|
5
|
+
declare const delegate: (element: Element, event: string, listener: Function) => void;
|
|
6
|
+
declare const on: (element: Element, event: string, listener: Function) => void;
|
|
7
|
+
declare const ondisconnect: (element: Element, listener: Function) => void;
|
|
8
|
+
declare const onrender: (element: Element, listener: Function) => void;
|
|
9
|
+
declare const runtime: (element: Element, event: `on${string}`, listener: Function) => void;
|
|
10
|
+
export { delegate, on, onconnect, ondisconnect, onrender, onresize, ontick, runtime };
|
package/build/event/index.js
CHANGED
|
@@ -4,6 +4,7 @@ import { ondisconnect as disconnect } from '../slot/cleanup.js';
|
|
|
4
4
|
import onconnect from './onconnect.js';
|
|
5
5
|
import onresize from './onresize.js';
|
|
6
6
|
import ontick from './ontick.js';
|
|
7
|
+
import { DIRECT_ATTACH_EVENTS, LIFECYCLE_EVENTS } from '../constants.js';
|
|
7
8
|
let controllers = new Map(), host = window.document, keys = {}, passive = new Set([
|
|
8
9
|
'animationend', 'animationiteration', 'animationstart',
|
|
9
10
|
'mousedown', 'mouseenter', 'mouseleave', 'mousemove', 'mouseout', 'mouseover', 'mouseup', 'mousewheel',
|
|
@@ -61,7 +62,7 @@ function register(element, event) {
|
|
|
61
62
|
const delegate = (element, event, listener) => {
|
|
62
63
|
element[keys[event] || register(element, event)] = listener;
|
|
63
64
|
};
|
|
64
|
-
const
|
|
65
|
+
const on = (element, event, listener) => {
|
|
65
66
|
let handler = (e) => listener.call(element, e);
|
|
66
67
|
element.addEventListener(event, handler, {
|
|
67
68
|
passive: passive.has(event)
|
|
@@ -76,4 +77,19 @@ const ondisconnect = (element, listener) => {
|
|
|
76
77
|
const onrender = (element, listener) => {
|
|
77
78
|
root(() => listener(element));
|
|
78
79
|
};
|
|
79
|
-
|
|
80
|
+
const lifecycle = { onconnect, ondisconnect, onrender, onresize, ontick };
|
|
81
|
+
const runtime = (element, event, listener) => {
|
|
82
|
+
let key = event.toLowerCase();
|
|
83
|
+
if (LIFECYCLE_EVENTS.has(key)) {
|
|
84
|
+
lifecycle[key](element, listener);
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
let e = event.slice(2).toLowerCase();
|
|
88
|
+
if (DIRECT_ATTACH_EVENTS.has(key)) {
|
|
89
|
+
on(element, e, listener);
|
|
90
|
+
}
|
|
91
|
+
else {
|
|
92
|
+
delegate(element, e, listener);
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
export { delegate, on, onconnect, ondisconnect, onrender, onresize, ontick, runtime };
|
package/build/index.d.ts
CHANGED
|
@@ -2,8 +2,8 @@ import './runtime.js';
|
|
|
2
2
|
export { default as html } from './html.js';
|
|
3
3
|
export { default as render } from './render.js';
|
|
4
4
|
export { default as svg } from './svg.js';
|
|
5
|
-
export
|
|
6
|
-
export
|
|
5
|
+
export * from './attributes.js';
|
|
6
|
+
export * from './event/index.js';
|
|
7
7
|
export { default as slot } from './slot/index.js';
|
|
8
8
|
export { ArraySlot } from './slot/array.js';
|
|
9
9
|
export { EffectSlot } from './slot/effect.js';
|
package/build/index.js
CHANGED
|
@@ -2,8 +2,8 @@ import './runtime.js';
|
|
|
2
2
|
export { default as html } from './html.js';
|
|
3
3
|
export { default as render } from './render.js';
|
|
4
4
|
export { default as svg } from './svg.js';
|
|
5
|
-
export
|
|
6
|
-
export
|
|
5
|
+
export * from './attributes.js';
|
|
6
|
+
export * from './event/index.js';
|
|
7
7
|
export { default as slot } from './slot/index.js';
|
|
8
8
|
export { ArraySlot } from './slot/array.js';
|
|
9
9
|
export { EffectSlot } from './slot/effect.js';
|
|
@@ -88,11 +88,11 @@ function generateTemplateCode(ctx, { html, slots }, exprTexts, exprNodes, isArro
|
|
|
88
88
|
let elementVar = slots[i].path.length === 0
|
|
89
89
|
? root
|
|
90
90
|
: (nodes.get(slots[i].path.join('.')) || root), slot = slots[i];
|
|
91
|
-
if (slot.type === COMPILER_TYPES.
|
|
91
|
+
if (slot.type === COMPILER_TYPES.Attribute) {
|
|
92
92
|
let names = slot.attributes.names;
|
|
93
93
|
for (let j = 0, m = names.length; j < m; j++) {
|
|
94
94
|
let name = names[j];
|
|
95
|
-
if (name ===
|
|
95
|
+
if (name === COMPILER_TYPES.Attributes) {
|
|
96
96
|
let bindings = generateSpreadBindings(exprNodes[index], exprTexts[index] || 'undefined', elementVar, ctx.checker, COMPILER_NAMESPACE);
|
|
97
97
|
for (let k = 0, o = bindings.length; k < o; k++) {
|
|
98
98
|
code.push(bindings[k]);
|
|
@@ -5,14 +5,14 @@ declare const _default: {
|
|
|
5
5
|
html: string;
|
|
6
6
|
slots: ({
|
|
7
7
|
path: NodePath;
|
|
8
|
-
type: COMPILER_TYPES.
|
|
8
|
+
type: COMPILER_TYPES.Node;
|
|
9
9
|
} | {
|
|
10
10
|
attributes: {
|
|
11
11
|
names: string[];
|
|
12
12
|
statics: Record<string, string>;
|
|
13
13
|
};
|
|
14
14
|
path: NodePath;
|
|
15
|
-
type: COMPILER_TYPES.
|
|
15
|
+
type: COMPILER_TYPES.Attribute;
|
|
16
16
|
})[] | null;
|
|
17
17
|
};
|
|
18
18
|
};
|
|
@@ -53,7 +53,7 @@ const parse = (literals) => {
|
|
|
53
53
|
if (n === 0) {
|
|
54
54
|
return { html, slots: null };
|
|
55
55
|
}
|
|
56
|
-
let attributes = {}, buffer = '',
|
|
56
|
+
let attributes = {}, buffer = '', index = 0, level = 0, levels = [{ children: 0, elements: 0, path: [] }], parsed = html.split(SLOT_MARKER), slot = 0, slots = [];
|
|
57
57
|
{
|
|
58
58
|
let attribute = '', buffer = '', char = '', quote = '';
|
|
59
59
|
for (let match of html.matchAll(REGEX_SLOT_ATTRIBUTES)) {
|
|
@@ -102,12 +102,9 @@ const parse = (literals) => {
|
|
|
102
102
|
}
|
|
103
103
|
}
|
|
104
104
|
else {
|
|
105
|
-
names.push(
|
|
105
|
+
names.push(COMPILER_TYPES.Attributes);
|
|
106
106
|
}
|
|
107
107
|
}
|
|
108
|
-
else if (buffer === 'on') {
|
|
109
|
-
events = true;
|
|
110
|
-
}
|
|
111
108
|
}
|
|
112
109
|
}
|
|
113
110
|
}
|
|
@@ -127,7 +124,7 @@ const parse = (literals) => {
|
|
|
127
124
|
if (!attrs) {
|
|
128
125
|
throw new Error(`${PACKAGE}: attribute metadata could not be found for '${attr}'`);
|
|
129
126
|
}
|
|
130
|
-
slots.push({ attributes: attrs, path, type: COMPILER_TYPES.
|
|
127
|
+
slots.push({ attributes: attrs, path, type: COMPILER_TYPES.Attribute });
|
|
131
128
|
for (let i = 0, n = attrs.names.length; i < n; i++) {
|
|
132
129
|
buffer += parsed[slot++];
|
|
133
130
|
}
|
|
@@ -139,7 +136,10 @@ const parse = (literals) => {
|
|
|
139
136
|
}
|
|
140
137
|
else if (type === NODE_SLOT) {
|
|
141
138
|
buffer += parsed[slot++] + SLOT_HTML;
|
|
142
|
-
slots.push({
|
|
139
|
+
slots.push({
|
|
140
|
+
path: methods(parent.children, parent.path, 'firstChild', 'nextSibling'),
|
|
141
|
+
type: COMPILER_TYPES.Node
|
|
142
|
+
});
|
|
143
143
|
}
|
|
144
144
|
if (n === slot) {
|
|
145
145
|
buffer += parsed[slot];
|
|
@@ -154,10 +154,9 @@ const parse = (literals) => {
|
|
|
154
154
|
index = (match.index || 0) + match[0].length;
|
|
155
155
|
}
|
|
156
156
|
}
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
buffer = buffer.replace(REGEX_EMPTY_ATTRIBUTES, '');
|
|
157
|
+
buffer = buffer
|
|
158
|
+
.replace(REGEX_EVENTS, '')
|
|
159
|
+
.replace(REGEX_EMPTY_ATTRIBUTES, '');
|
|
161
160
|
return {
|
|
162
161
|
html: buffer,
|
|
163
162
|
slots: slots.length ? slots : null
|
|
@@ -123,23 +123,23 @@ const generateAttributeBinding = (elementVar, name, expr, staticValue, ns) => {
|
|
|
123
123
|
if (name.startsWith('on') && name.length > 2) {
|
|
124
124
|
let event = name.slice(2).toLowerCase(), key = name.toLowerCase();
|
|
125
125
|
if (LIFECYCLE_EVENTS.has(key)) {
|
|
126
|
-
return `${ns}
|
|
126
|
+
return `${ns}.${key}(${elementVar}, ${expr});`;
|
|
127
127
|
}
|
|
128
128
|
if (DIRECT_ATTACH_EVENTS.has(key)) {
|
|
129
|
-
return `${ns}.
|
|
129
|
+
return `${ns}.on(${elementVar}, '${event}', ${expr});`;
|
|
130
130
|
}
|
|
131
|
-
return `${ns}.
|
|
131
|
+
return `${ns}.delegate(${elementVar}, '${event}', ${expr});`;
|
|
132
132
|
}
|
|
133
133
|
if (name === 'class') {
|
|
134
|
-
return `${ns}.
|
|
134
|
+
return `${ns}.setClass(${elementVar}, '${staticValue}', ${expr});`;
|
|
135
135
|
}
|
|
136
|
-
if (name ===
|
|
137
|
-
return `${ns}.
|
|
136
|
+
if (name === COMPILER_TYPES.Attributes) {
|
|
137
|
+
return `${ns}.setProperties(${elementVar}, ${expr});`;
|
|
138
138
|
}
|
|
139
139
|
if (name === 'style') {
|
|
140
|
-
return `${ns}.
|
|
140
|
+
return `${ns}.setStyle(${elementVar}, '${staticValue}', ${expr});`;
|
|
141
141
|
}
|
|
142
|
-
return `${ns}.
|
|
142
|
+
return `${ns}.setProperty(${elementVar}, '${name}', ${expr});`;
|
|
143
143
|
};
|
|
144
144
|
const generateSpreadBindings = (expr, exprCode, elementVar, checker, ns) => {
|
|
145
145
|
while (ts.isParenthesizedExpression(expr)) {
|
|
@@ -147,7 +147,7 @@ const generateSpreadBindings = (expr, exprCode, elementVar, checker, ns) => {
|
|
|
147
147
|
}
|
|
148
148
|
let analysis = analyzeSpread(expr, checker);
|
|
149
149
|
if (!analysis.canUnpack) {
|
|
150
|
-
return [`${ns}.
|
|
150
|
+
return [`${ns}.setProperties(${elementVar}, ${exprCode});`];
|
|
151
151
|
}
|
|
152
152
|
let lines = [];
|
|
153
153
|
if (ts.isObjectLiteralExpression(expr)) {
|
package/build/types.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ArraySlot } from './slot/array.js';
|
|
2
|
-
import
|
|
2
|
+
import { setProperties } from './attributes.js';
|
|
3
3
|
import slot from './slot/index.js';
|
|
4
4
|
type Attribute = Effect<Primitive | Primitive[]> | ((...args: any[]) => void) | Primitive;
|
|
5
5
|
type Attributes<T extends HTMLElement = Element> = {
|
|
@@ -27,7 +27,7 @@ type Template = {
|
|
|
27
27
|
html: string;
|
|
28
28
|
literals: TemplateStringsArray;
|
|
29
29
|
slots: {
|
|
30
|
-
fn: typeof
|
|
30
|
+
fn: typeof setProperties | typeof slot;
|
|
31
31
|
name: string | null;
|
|
32
32
|
path: (() => ChildNode | null)[];
|
|
33
33
|
}[] | null;
|
package/package.json
CHANGED
package/src/attributes.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { effect } from '@esportsplus/reactivity';
|
|
2
2
|
import { isArray, isObject } from '@esportsplus/utilities';
|
|
3
|
-
import {
|
|
3
|
+
import { STATE_HYDRATING, STATE_NONE, STATE_WAITING, STORE } from './constants';
|
|
4
4
|
import { Attributes, Element } from './types';
|
|
5
5
|
import { raf } from './utilities';
|
|
6
6
|
import q from '@esportsplus/queue';
|
|
7
|
-
import
|
|
7
|
+
import { runtime } from './event';
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
type Context = {
|
|
@@ -221,45 +221,10 @@ function schedule(ctx: Context | null, element: Element, name: string, state: St
|
|
|
221
221
|
raf(task);
|
|
222
222
|
}
|
|
223
223
|
|
|
224
|
-
function
|
|
225
|
-
let context,
|
|
226
|
-
n = queue.length;
|
|
227
|
-
|
|
228
|
-
while ((context = queue.next()) && n--) {
|
|
229
|
-
let { element, updates } = context;
|
|
230
|
-
|
|
231
|
-
for (let name in updates) {
|
|
232
|
-
apply(element, name, updates[name]);
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
context.updates = {};
|
|
236
|
-
context.updating = false;
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
if (queue.length) {
|
|
240
|
-
raf(task);
|
|
241
|
-
}
|
|
242
|
-
else {
|
|
243
|
-
scheduled = false;
|
|
244
|
-
}
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
const set = (element: Element, name: string, value: unknown) => {
|
|
224
|
+
function set(element: Element, name: string, value: unknown) {
|
|
249
225
|
if (typeof value === 'function') {
|
|
250
226
|
if (name[0] === 'o' && name[1] === 'n') {
|
|
251
|
-
|
|
252
|
-
key = name.toLowerCase();
|
|
253
|
-
|
|
254
|
-
if (LIFECYCLE_EVENTS.has(key)) {
|
|
255
|
-
(event as any)[key](element, value as Function);
|
|
256
|
-
}
|
|
257
|
-
else if (DIRECT_ATTACH_EVENTS.has(key)) {
|
|
258
|
-
event.direct(element, e, value as Function);
|
|
259
|
-
}
|
|
260
|
-
else {
|
|
261
|
-
event.delegate(element, e, value as Function);
|
|
262
|
-
}
|
|
227
|
+
runtime(element, name as `on${string}`, value as Function);
|
|
263
228
|
}
|
|
264
229
|
else {
|
|
265
230
|
reactive(element, name, STATE_HYDRATING, value);
|
|
@@ -283,7 +248,31 @@ const set = (element: Element, name: string, value: unknown) => {
|
|
|
283
248
|
}
|
|
284
249
|
|
|
285
250
|
(name === 'class' || name === 'style' ? list : property)(null, element, null, name, STATE_HYDRATING, value);
|
|
286
|
-
}
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
function task() {
|
|
254
|
+
let context,
|
|
255
|
+
n = queue.length;
|
|
256
|
+
|
|
257
|
+
while ((context = queue.next()) && n--) {
|
|
258
|
+
let { element, updates } = context;
|
|
259
|
+
|
|
260
|
+
for (let name in updates) {
|
|
261
|
+
apply(element, name, updates[name]);
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
context.updates = {};
|
|
265
|
+
context.updating = false;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
if (queue.length) {
|
|
269
|
+
raf(task);
|
|
270
|
+
}
|
|
271
|
+
else {
|
|
272
|
+
scheduled = false;
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
|
|
287
276
|
|
|
288
277
|
const setClass = (element: Element, classlist: false | string | undefined, value: unknown) => {
|
|
289
278
|
let ctx = context(element),
|
|
@@ -309,22 +298,7 @@ const setProperty = (element: Element, name: string, value: unknown) => {
|
|
|
309
298
|
}
|
|
310
299
|
};
|
|
311
300
|
|
|
312
|
-
const
|
|
313
|
-
let ctx = context(element),
|
|
314
|
-
store = ctx.store ??= {};
|
|
315
|
-
|
|
316
|
-
store['style.static'] = styles || '';
|
|
317
|
-
store['style'] ??= new Set<string>();
|
|
318
|
-
|
|
319
|
-
if (typeof value === 'function') {
|
|
320
|
-
reactive(element, 'style', STATE_HYDRATING, value);
|
|
321
|
-
}
|
|
322
|
-
else {
|
|
323
|
-
list(ctx, element, null, 'style', STATE_HYDRATING, value);
|
|
324
|
-
}
|
|
325
|
-
};
|
|
326
|
-
|
|
327
|
-
const spread = function (element: Element, value: Attributes | Attributes[]) {
|
|
301
|
+
const setProperties = function (element: Element, value: Attributes | Attributes[]) {
|
|
328
302
|
if (isObject(value)) {
|
|
329
303
|
for (let name in value) {
|
|
330
304
|
let v = value[name];
|
|
@@ -338,11 +312,25 @@ const spread = function (element: Element, value: Attributes | Attributes[]) {
|
|
|
338
312
|
}
|
|
339
313
|
else if (isArray(value)) {
|
|
340
314
|
for (let i = 0, n = value.length; i < n; i++) {
|
|
341
|
-
|
|
315
|
+
setProperties(element, value[i]);
|
|
342
316
|
}
|
|
343
317
|
}
|
|
344
318
|
};
|
|
345
319
|
|
|
320
|
+
const setStyle = (element: Element, styles: false | string | undefined, value: unknown) => {
|
|
321
|
+
let ctx = context(element),
|
|
322
|
+
store = ctx.store ??= {};
|
|
323
|
+
|
|
324
|
+
store['style.static'] = styles || '';
|
|
325
|
+
store['style'] ??= new Set<string>();
|
|
326
|
+
|
|
327
|
+
if (typeof value === 'function') {
|
|
328
|
+
reactive(element, 'style', STATE_HYDRATING, value);
|
|
329
|
+
}
|
|
330
|
+
else {
|
|
331
|
+
list(ctx, element, null, 'style', STATE_HYDRATING, value);
|
|
332
|
+
}
|
|
333
|
+
};
|
|
334
|
+
|
|
346
335
|
|
|
347
|
-
export
|
|
348
|
-
export { set, setClass, setProperty, setStyle, spread };
|
|
336
|
+
export { setClass, setProperty, setProperties, setStyle };
|
package/src/constants.ts
CHANGED
|
@@ -13,15 +13,15 @@ const COMPILER_ENTRYPOINT_REACTIVITY = 'reactive';
|
|
|
13
13
|
const COMPILER_NAMESPACE = uid('template');
|
|
14
14
|
|
|
15
15
|
const enum COMPILER_TYPES {
|
|
16
|
-
ArraySlot,
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
DocumentFragment,
|
|
20
|
-
Effect,
|
|
21
|
-
|
|
22
|
-
Primitive,
|
|
23
|
-
Static,
|
|
24
|
-
Unknown
|
|
16
|
+
ArraySlot = 'array-slot',
|
|
17
|
+
Attributes = 'attributes',
|
|
18
|
+
Attribute = 'attribute',
|
|
19
|
+
DocumentFragment = 'document-fragment',
|
|
20
|
+
Effect = 'effect',
|
|
21
|
+
Node = 'node',
|
|
22
|
+
Primitive = 'primitive',
|
|
23
|
+
Static = 'static',
|
|
24
|
+
Unknown = 'unknown'
|
|
25
25
|
};
|
|
26
26
|
|
|
27
27
|
const DIRECT_ATTACH_EVENTS = new Set<string>([
|
package/src/event/index.ts
CHANGED
|
@@ -5,6 +5,7 @@ import { ondisconnect as disconnect } from '~/slot/cleanup';
|
|
|
5
5
|
import onconnect from './onconnect';
|
|
6
6
|
import onresize from './onresize';
|
|
7
7
|
import ontick from './ontick';
|
|
8
|
+
import { DIRECT_ATTACH_EVENTS, LIFECYCLE_EVENTS } from '~/constants';
|
|
8
9
|
|
|
9
10
|
|
|
10
11
|
let controllers = new Map<string, (AbortController & { listeners: number }) | null>(),
|
|
@@ -92,7 +93,7 @@ const delegate = (element: Element, event: string, listener: Function): void =>
|
|
|
92
93
|
};
|
|
93
94
|
|
|
94
95
|
// DIRECT_ATTACH_EVENTS in ./constants.ts tells compiler to use this function
|
|
95
|
-
const
|
|
96
|
+
const on = (element: Element, event: string, listener: Function): void => {
|
|
96
97
|
let handler = (e: Event) => listener.call(element, e);
|
|
97
98
|
|
|
98
99
|
element.addEventListener(event, handler, {
|
|
@@ -112,5 +113,25 @@ const onrender = (element: Element, listener: Function) => {
|
|
|
112
113
|
root(() => listener(element));
|
|
113
114
|
};
|
|
114
115
|
|
|
116
|
+
const lifecycle = { onconnect, ondisconnect, onrender, onresize, ontick };
|
|
115
117
|
|
|
116
|
-
|
|
118
|
+
const runtime = (element: Element, event: `on${string}`, listener: Function): void => {
|
|
119
|
+
let key = event.toLowerCase();
|
|
120
|
+
|
|
121
|
+
if (LIFECYCLE_EVENTS.has(key)) {
|
|
122
|
+
lifecycle[key as keyof typeof lifecycle](element, listener);
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
let e = event.slice(2).toLowerCase();
|
|
127
|
+
|
|
128
|
+
if (DIRECT_ATTACH_EVENTS.has(key)) {
|
|
129
|
+
on(element, e, listener);
|
|
130
|
+
}
|
|
131
|
+
else {
|
|
132
|
+
delegate(element, e, listener);
|
|
133
|
+
}
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
export { delegate, on, onconnect, ondisconnect, onrender, onresize, ontick, runtime };
|
package/src/index.ts
CHANGED
|
@@ -4,8 +4,8 @@ export { default as render } from './render';
|
|
|
4
4
|
export { default as svg } from './svg';
|
|
5
5
|
|
|
6
6
|
// Must be exported for compilation even if not used directly
|
|
7
|
-
export
|
|
8
|
-
export
|
|
7
|
+
export * from './attributes';
|
|
8
|
+
export * from './event';
|
|
9
9
|
export { default as slot } from './slot';
|
|
10
10
|
export { ArraySlot } from './slot/array';
|
|
11
11
|
export { EffectSlot } from './slot/effect';
|
|
@@ -9,13 +9,13 @@ import {
|
|
|
9
9
|
import parser from './parser';
|
|
10
10
|
|
|
11
11
|
|
|
12
|
-
type
|
|
12
|
+
type Attribute = {
|
|
13
13
|
attributes: {
|
|
14
14
|
names: string[];
|
|
15
15
|
statics: Record<string, string>;
|
|
16
16
|
};
|
|
17
17
|
path: string[];
|
|
18
|
-
type: COMPILER_TYPES.
|
|
18
|
+
type: COMPILER_TYPES.Attribute;
|
|
19
19
|
};
|
|
20
20
|
|
|
21
21
|
type CodegenContext = {
|
|
@@ -31,14 +31,14 @@ type CodegenResult = {
|
|
|
31
31
|
code: string;
|
|
32
32
|
};
|
|
33
33
|
|
|
34
|
-
type
|
|
34
|
+
type Node = {
|
|
35
35
|
path: string[];
|
|
36
|
-
type: COMPILER_TYPES.
|
|
36
|
+
type: COMPILER_TYPES.Node;
|
|
37
37
|
};
|
|
38
38
|
|
|
39
39
|
type ParseResult = {
|
|
40
40
|
html: string;
|
|
41
|
-
slots: (
|
|
41
|
+
slots: (Attribute | Node)[] | null;
|
|
42
42
|
};
|
|
43
43
|
|
|
44
44
|
|
|
@@ -189,13 +189,13 @@ function generateTemplateCode(
|
|
|
189
189
|
: (nodes.get(slots[i].path.join('.')) || root),
|
|
190
190
|
slot = slots[i];
|
|
191
191
|
|
|
192
|
-
if (slot.type === COMPILER_TYPES.
|
|
192
|
+
if (slot.type === COMPILER_TYPES.Attribute) {
|
|
193
193
|
let names = slot.attributes.names;
|
|
194
194
|
|
|
195
195
|
for (let j = 0, m = names.length; j < m; j++) {
|
|
196
196
|
let name = names[j];
|
|
197
197
|
|
|
198
|
-
if (name ===
|
|
198
|
+
if (name === COMPILER_TYPES.Attributes) {
|
|
199
199
|
let bindings = generateSpreadBindings(
|
|
200
200
|
exprNodes[index],
|
|
201
201
|
exprTexts[index] || 'undefined',
|
|
@@ -1,8 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
COMPILER_TYPES,
|
|
3
|
-
PACKAGE,
|
|
4
|
-
SLOT_HTML
|
|
5
|
-
} from '../constants';
|
|
1
|
+
import { COMPILER_TYPES, PACKAGE, SLOT_HTML } from '../constants';
|
|
6
2
|
|
|
7
3
|
|
|
8
4
|
type NodePath = ('firstChild' | 'firstElementChild' | 'nextElementSibling' | 'nextSibling')[];
|
|
@@ -88,15 +84,14 @@ const parse = (literals: string[]) => {
|
|
|
88
84
|
|
|
89
85
|
let attributes: Record<string, { names: string[], statics: Record<string, string> }> = {},
|
|
90
86
|
buffer = '',
|
|
91
|
-
events = false,
|
|
92
87
|
index = 0,
|
|
93
88
|
level = 0,
|
|
94
89
|
levels = [{ children: 0, elements: 0, path: [] as NodePath }],
|
|
95
90
|
parsed = html.split(SLOT_MARKER),
|
|
96
91
|
slot = 0,
|
|
97
92
|
slots: (
|
|
98
|
-
{ path: NodePath; type: COMPILER_TYPES.
|
|
99
|
-
{ attributes: typeof attributes[string]; path: NodePath; type: COMPILER_TYPES.
|
|
93
|
+
{ path: NodePath; type: COMPILER_TYPES.Node } |
|
|
94
|
+
{ attributes: typeof attributes[string]; path: NodePath; type: COMPILER_TYPES.Attribute }
|
|
100
95
|
)[] = [];
|
|
101
96
|
|
|
102
97
|
{
|
|
@@ -159,12 +154,9 @@ const parse = (literals: string[]) => {
|
|
|
159
154
|
}
|
|
160
155
|
}
|
|
161
156
|
else {
|
|
162
|
-
names.push(
|
|
157
|
+
names.push(COMPILER_TYPES.Attributes);
|
|
163
158
|
}
|
|
164
159
|
}
|
|
165
|
-
else if (buffer === 'on') {
|
|
166
|
-
events = true;
|
|
167
|
-
}
|
|
168
160
|
}
|
|
169
161
|
}
|
|
170
162
|
}
|
|
@@ -192,7 +184,7 @@ const parse = (literals: string[]) => {
|
|
|
192
184
|
throw new Error(`${PACKAGE}: attribute metadata could not be found for '${attr}'`);
|
|
193
185
|
}
|
|
194
186
|
|
|
195
|
-
slots.push({ attributes: attrs, path, type: COMPILER_TYPES.
|
|
187
|
+
slots.push({ attributes: attrs, path, type: COMPILER_TYPES.Attribute });
|
|
196
188
|
|
|
197
189
|
for (let i = 0, n = attrs.names.length; i < n; i++) {
|
|
198
190
|
buffer += parsed[slot++];
|
|
@@ -207,7 +199,10 @@ const parse = (literals: string[]) => {
|
|
|
207
199
|
}
|
|
208
200
|
else if (type === NODE_SLOT) {
|
|
209
201
|
buffer += parsed[slot++] + SLOT_HTML;
|
|
210
|
-
slots.push({
|
|
202
|
+
slots.push({
|
|
203
|
+
path: methods(parent.children, parent.path, 'firstChild', 'nextSibling'),
|
|
204
|
+
type: COMPILER_TYPES.Node
|
|
205
|
+
});
|
|
211
206
|
}
|
|
212
207
|
|
|
213
208
|
if (n === slot) {
|
|
@@ -226,11 +221,9 @@ const parse = (literals: string[]) => {
|
|
|
226
221
|
}
|
|
227
222
|
}
|
|
228
223
|
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
buffer = buffer.replace(REGEX_EMPTY_ATTRIBUTES, '');
|
|
224
|
+
buffer = buffer
|
|
225
|
+
.replace(REGEX_EVENTS, '')
|
|
226
|
+
.replace(REGEX_EMPTY_ATTRIBUTES, '');
|
|
234
227
|
|
|
235
228
|
return {
|
|
236
229
|
html: buffer,
|
|
@@ -178,29 +178,29 @@ const generateAttributeBinding = (elementVar: string, name: string, expr: string
|
|
|
178
178
|
key = name.toLowerCase();
|
|
179
179
|
|
|
180
180
|
if (LIFECYCLE_EVENTS.has(key)) {
|
|
181
|
-
return `${ns}
|
|
181
|
+
return `${ns}.${key}(${elementVar}, ${expr});`;
|
|
182
182
|
}
|
|
183
183
|
|
|
184
184
|
if (DIRECT_ATTACH_EVENTS.has(key)) {
|
|
185
|
-
return `${ns}.
|
|
185
|
+
return `${ns}.on(${elementVar}, '${event}', ${expr});`;
|
|
186
186
|
}
|
|
187
187
|
|
|
188
|
-
return `${ns}.
|
|
188
|
+
return `${ns}.delegate(${elementVar}, '${event}', ${expr});`;
|
|
189
189
|
}
|
|
190
190
|
|
|
191
191
|
if (name === 'class') {
|
|
192
|
-
return `${ns}.
|
|
192
|
+
return `${ns}.setClass(${elementVar}, '${staticValue}', ${expr});`;
|
|
193
193
|
}
|
|
194
194
|
|
|
195
|
-
if (name ===
|
|
196
|
-
return `${ns}.
|
|
195
|
+
if (name === COMPILER_TYPES.Attributes) {
|
|
196
|
+
return `${ns}.setProperties(${elementVar}, ${expr});`;
|
|
197
197
|
}
|
|
198
198
|
|
|
199
199
|
if (name === 'style') {
|
|
200
|
-
return `${ns}.
|
|
200
|
+
return `${ns}.setStyle(${elementVar}, '${staticValue}', ${expr});`;
|
|
201
201
|
}
|
|
202
202
|
|
|
203
|
-
return `${ns}.
|
|
203
|
+
return `${ns}.setProperty(${elementVar}, '${name}', ${expr});`;
|
|
204
204
|
};
|
|
205
205
|
|
|
206
206
|
const generateSpreadBindings = (
|
|
@@ -217,7 +217,7 @@ const generateSpreadBindings = (
|
|
|
217
217
|
let analysis = analyzeSpread(expr, checker);
|
|
218
218
|
|
|
219
219
|
if (!analysis.canUnpack) {
|
|
220
|
-
return [`${ns}.
|
|
220
|
+
return [`${ns}.setProperties(${elementVar}, ${exprCode});`];
|
|
221
221
|
}
|
|
222
222
|
|
|
223
223
|
let lines: string[] = [];
|
package/src/types.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ArraySlot } from './slot/array';
|
|
2
|
-
import
|
|
2
|
+
import { setProperties } from './attributes';
|
|
3
3
|
import slot from './slot';
|
|
4
4
|
|
|
5
5
|
|
|
@@ -38,7 +38,7 @@ type Template = {
|
|
|
38
38
|
html: string;
|
|
39
39
|
literals: TemplateStringsArray;
|
|
40
40
|
slots: {
|
|
41
|
-
fn: typeof
|
|
41
|
+
fn: typeof setProperties | typeof slot;
|
|
42
42
|
name: string | null;
|
|
43
43
|
path: (() => ChildNode | null)[];
|
|
44
44
|
}[] | null;
|