@esportsplus/template 0.16.1 → 0.18.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 +29 -24
- package/build/constants.d.ts +13 -3
- package/build/constants.js +14 -4
- package/build/event.js +48 -46
- package/build/html/hydrate.d.ts +2 -8
- package/build/html/hydrate.js +28 -79
- package/build/html/index.d.ts +2106 -5
- package/build/html/index.js +12 -4
- package/build/html/{cache.d.ts → parser.d.ts} +1 -1
- package/build/html/{cache.js → parser.js} +6 -4
- package/build/render.d.ts +1 -2
- package/build/render.js +7 -10
- package/build/slot/cleanup.d.ts +4 -0
- package/build/slot/cleanup.js +52 -0
- package/build/slot/effect.d.ts +3 -0
- package/build/slot/effect.js +56 -0
- package/build/slot/index.d.ts +3 -0
- package/build/slot/index.js +8 -0
- package/build/slot/reactive.d.ts +3 -0
- package/build/slot/reactive.js +125 -0
- package/build/slot/render.d.ts +2 -0
- package/build/slot/render.js +81 -0
- package/build/svg.d.ts +1 -2
- package/build/types.d.ts +21 -17
- package/build/utilities/element.d.ts +11 -0
- package/build/utilities/element.js +9 -0
- package/build/utilities/fragment.d.ts +3 -0
- package/build/utilities/fragment.js +11 -0
- package/build/utilities/node.d.ts +8 -0
- package/build/utilities/node.js +9 -0
- package/build/utilities/queue.d.ts +3 -0
- package/build/utilities/queue.js +4 -0
- package/build/utilities/text.d.ts +3 -0
- package/build/utilities/text.js +9 -0
- package/package.json +2 -2
- package/src/attributes.ts +32 -29
- package/src/constants.ts +32 -5
- package/src/event.ts +55 -52
- package/src/html/hydrate.ts +36 -108
- package/src/html/index.ts +16 -8
- package/src/html/{cache.ts → parser.ts} +5 -3
- package/src/render.ts +8 -12
- package/src/slot/cleanup.ts +74 -0
- package/src/slot/effect.ts +74 -0
- package/src/slot/index.ts +12 -0
- package/src/slot/reactive.ts +177 -0
- package/src/slot/render.ts +117 -0
- package/src/svg.ts +1 -2
- package/src/types.ts +25 -18
- package/src/utilities/element.ts +28 -0
- package/src/utilities/fragment.ts +22 -0
- package/src/utilities/node.ts +26 -0
- package/src/utilities/queue.ts +9 -0
- package/src/utilities/text.ts +16 -0
- package/build/slot.d.ts +0 -21
- package/build/slot.js +0 -204
- package/build/utilities.d.ts +0 -28
- package/build/utilities.js +0 -37
- package/src/slot.ts +0 -277
- package/src/utilities.ts +0 -87
package/build/slot.js
DELETED
|
@@ -1,204 +0,0 @@
|
|
|
1
|
-
import { effect } from '@esportsplus/reactivity';
|
|
2
|
-
import { isArray, isInstanceOf } from '@esportsplus/utilities';
|
|
3
|
-
import { EMPTY_FRAGMENT, RENDERABLE, RENDERABLE_REACTIVE } from './constants.js';
|
|
4
|
-
import { hydrate } from './html/index.js';
|
|
5
|
-
import { append, cloneNode, microtask, nodeValue, raf, text } from './utilities.js';
|
|
6
|
-
import queue from '@esportsplus/queue';
|
|
7
|
-
const CLEANUP_KEY = Symbol();
|
|
8
|
-
const CONNECTED = 0;
|
|
9
|
-
const HYDRATING = 1;
|
|
10
|
-
let cleanup = queue(64), scheduled = false;
|
|
11
|
-
function remove(groups) {
|
|
12
|
-
let group, item;
|
|
13
|
-
while (group = groups.pop()) {
|
|
14
|
-
while (item = group.pop()) {
|
|
15
|
-
if (CLEANUP_KEY in item) {
|
|
16
|
-
cleanup.add(item[CLEANUP_KEY]);
|
|
17
|
-
item[CLEANUP_KEY] = null;
|
|
18
|
-
}
|
|
19
|
-
item.remove();
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
if (!scheduled && cleanup.length) {
|
|
23
|
-
schedule();
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
function render(anchor, elements, fragment, input, slot) {
|
|
27
|
-
if (input === false || input == null || input === '') {
|
|
28
|
-
return;
|
|
29
|
-
}
|
|
30
|
-
let type = typeof input;
|
|
31
|
-
if (type === 'object' && RENDERABLE in input) {
|
|
32
|
-
if (input[RENDERABLE] === RENDERABLE_REACTIVE) {
|
|
33
|
-
slot ??= new Slot(anchor);
|
|
34
|
-
hydrate.reactive(slot.nodes, fragment, input, slot);
|
|
35
|
-
}
|
|
36
|
-
else {
|
|
37
|
-
hydrate.static(elements, fragment, input);
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
else if (type === 'string' || type === 'number') {
|
|
41
|
-
let element = text(type === 'string' ? input : String(input));
|
|
42
|
-
if (slot) {
|
|
43
|
-
slot.text = element;
|
|
44
|
-
}
|
|
45
|
-
append.call(fragment, element);
|
|
46
|
-
if (elements) {
|
|
47
|
-
elements.push([element]);
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
else if (isArray(input)) {
|
|
51
|
-
for (let i = 0, n = input.length; i < n; i++) {
|
|
52
|
-
render(anchor, elements, fragment, input[i], slot);
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
else if (isInstanceOf(input, NodeList)) {
|
|
56
|
-
append.call(fragment, ...input);
|
|
57
|
-
if (elements) {
|
|
58
|
-
elements.push([...input]);
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
else if (isInstanceOf(input, Node)) {
|
|
62
|
-
append.call(fragment, input);
|
|
63
|
-
if (elements) {
|
|
64
|
-
elements.push([input]);
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
function schedule() {
|
|
69
|
-
if (scheduled) {
|
|
70
|
-
return;
|
|
71
|
-
}
|
|
72
|
-
scheduled = true;
|
|
73
|
-
microtask.add(task);
|
|
74
|
-
}
|
|
75
|
-
function task() {
|
|
76
|
-
let fn, fns;
|
|
77
|
-
while (fns = cleanup.next()) {
|
|
78
|
-
try {
|
|
79
|
-
while (fn = fns.pop()) {
|
|
80
|
-
fn();
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
catch { }
|
|
84
|
-
}
|
|
85
|
-
scheduled = false;
|
|
86
|
-
if (cleanup.length) {
|
|
87
|
-
schedule();
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
class Slot {
|
|
91
|
-
marker;
|
|
92
|
-
nodes;
|
|
93
|
-
text = null;
|
|
94
|
-
constructor(marker) {
|
|
95
|
-
ondisconnect(marker, () => this.clear());
|
|
96
|
-
this.marker = marker;
|
|
97
|
-
this.nodes = [];
|
|
98
|
-
}
|
|
99
|
-
get length() {
|
|
100
|
-
return this.nodes.length;
|
|
101
|
-
}
|
|
102
|
-
set length(n) {
|
|
103
|
-
if (n >= this.nodes.length) {
|
|
104
|
-
return;
|
|
105
|
-
}
|
|
106
|
-
else if (n === 0) {
|
|
107
|
-
this.clear();
|
|
108
|
-
}
|
|
109
|
-
else {
|
|
110
|
-
this.splice(n);
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
anchor(index = this.nodes.length - 1) {
|
|
114
|
-
let nodes = this.nodes[index];
|
|
115
|
-
return nodes ? nodes[nodes.length - 1] : this.marker;
|
|
116
|
-
}
|
|
117
|
-
clear() {
|
|
118
|
-
if (this.text) {
|
|
119
|
-
this.nodes.push([this.text]);
|
|
120
|
-
this.text = null;
|
|
121
|
-
}
|
|
122
|
-
remove(this.nodes);
|
|
123
|
-
return this;
|
|
124
|
-
}
|
|
125
|
-
pop() {
|
|
126
|
-
let group = this.nodes.pop();
|
|
127
|
-
if (group) {
|
|
128
|
-
remove([group]);
|
|
129
|
-
}
|
|
130
|
-
return this;
|
|
131
|
-
}
|
|
132
|
-
push(fragment, ...nodes) {
|
|
133
|
-
this.anchor().after(fragment);
|
|
134
|
-
this.nodes.push(...nodes);
|
|
135
|
-
return this;
|
|
136
|
-
}
|
|
137
|
-
render(input, state = HYDRATING) {
|
|
138
|
-
let type = typeof input;
|
|
139
|
-
if (type === 'function') {
|
|
140
|
-
ondisconnect(this.marker, effect(() => {
|
|
141
|
-
let v = input();
|
|
142
|
-
if (state === HYDRATING) {
|
|
143
|
-
this.render(v, state);
|
|
144
|
-
state = CONNECTED;
|
|
145
|
-
}
|
|
146
|
-
else if (state === CONNECTED) {
|
|
147
|
-
raf.add(() => {
|
|
148
|
-
this.render(v, state);
|
|
149
|
-
});
|
|
150
|
-
}
|
|
151
|
-
}));
|
|
152
|
-
return this;
|
|
153
|
-
}
|
|
154
|
-
let text = this.text;
|
|
155
|
-
if (text && text.isConnected && (input == null || type !== 'object')) {
|
|
156
|
-
nodeValue.call(text, (type === 'number' || type === 'string') ? input : '');
|
|
157
|
-
}
|
|
158
|
-
else {
|
|
159
|
-
this.clear();
|
|
160
|
-
let fragment = cloneNode.call(EMPTY_FRAGMENT);
|
|
161
|
-
render(this.marker, this.nodes, fragment, input, this);
|
|
162
|
-
this.marker.after(fragment);
|
|
163
|
-
}
|
|
164
|
-
return this;
|
|
165
|
-
}
|
|
166
|
-
shift() {
|
|
167
|
-
let group = this.nodes.shift();
|
|
168
|
-
if (group) {
|
|
169
|
-
remove([group]);
|
|
170
|
-
}
|
|
171
|
-
return this;
|
|
172
|
-
}
|
|
173
|
-
splice(start, stop = this.nodes.length, fragment, ...nodes) {
|
|
174
|
-
if (!fragment) {
|
|
175
|
-
remove(this.nodes.splice(start, stop));
|
|
176
|
-
}
|
|
177
|
-
else {
|
|
178
|
-
this.anchor(start).after(fragment);
|
|
179
|
-
remove(this.nodes.splice(start, stop, ...nodes));
|
|
180
|
-
}
|
|
181
|
-
return this;
|
|
182
|
-
}
|
|
183
|
-
unshift(fragment, ...nodes) {
|
|
184
|
-
this.marker.after(fragment);
|
|
185
|
-
this.nodes.unshift(...nodes);
|
|
186
|
-
return this;
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
const ondisconnect = (element, fn) => {
|
|
190
|
-
(element[CLEANUP_KEY] ??= []).push(fn);
|
|
191
|
-
};
|
|
192
|
-
export default (marker, value) => {
|
|
193
|
-
let type = typeof value;
|
|
194
|
-
if (type === 'function') {
|
|
195
|
-
new Slot(marker).render(value);
|
|
196
|
-
}
|
|
197
|
-
else {
|
|
198
|
-
let fragment = cloneNode.call(EMPTY_FRAGMENT);
|
|
199
|
-
render(marker, null, fragment, value);
|
|
200
|
-
marker.after(fragment);
|
|
201
|
-
}
|
|
202
|
-
;
|
|
203
|
-
};
|
|
204
|
-
export { ondisconnect, Slot };
|
package/build/utilities.d.ts
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import { Element as E } from './types.js';
|
|
2
|
-
declare const append: (...nodes: (Node | string)[]) => void;
|
|
3
|
-
declare const addEventListener: {
|
|
4
|
-
<K extends keyof ElementEventMap>(type: K, listener: (this: Element, ev: ElementEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void;
|
|
5
|
-
(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void;
|
|
6
|
-
};
|
|
7
|
-
declare const removeEventListener: {
|
|
8
|
-
<K extends keyof ElementEventMap>(type: K, listener: (this: Element, ev: ElementEventMap[K]) => any, options?: boolean | EventListenerOptions): void;
|
|
9
|
-
(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | EventListenerOptions): void;
|
|
10
|
-
};
|
|
11
|
-
declare const className: (v: any) => void;
|
|
12
|
-
declare const innerHTML: (v: any) => void;
|
|
13
|
-
declare const firstElementChild: () => any;
|
|
14
|
-
declare const nextElementSibling: () => any;
|
|
15
|
-
declare const prepend: (...nodes: (Node | string)[]) => void;
|
|
16
|
-
declare const removeAttribute: (qualifiedName: string) => void;
|
|
17
|
-
declare const setAttribute: (qualifiedName: string, value: string) => void;
|
|
18
|
-
declare const cloneNode: (subtree?: boolean) => Node;
|
|
19
|
-
declare const firstChild: () => any;
|
|
20
|
-
declare const nextSibling: () => any;
|
|
21
|
-
declare const nodeValue: (v: any) => void;
|
|
22
|
-
declare const parentElement: () => any;
|
|
23
|
-
declare const parentNode: () => any;
|
|
24
|
-
declare const fragment: (html: string) => DocumentFragment;
|
|
25
|
-
declare const microtask: import("@esportsplus/tasks/build/factory").Scheduler;
|
|
26
|
-
declare const raf: import("@esportsplus/tasks/build/factory").Scheduler;
|
|
27
|
-
declare const text: (value: string) => E;
|
|
28
|
-
export { addEventListener, append, className, cloneNode, firstChild, firstElementChild, fragment, innerHTML, microtask, nextElementSibling, nextSibling, nodeValue, parentElement, parentNode, prepend, raf, removeAttribute, removeEventListener, setAttribute, text };
|
package/build/utilities.js
DELETED
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import { micro as m, raf as r } from '@esportsplus/tasks';
|
|
2
|
-
let prototype, template = document.createElement('template'), t = document.createTextNode('');
|
|
3
|
-
prototype = DocumentFragment.prototype;
|
|
4
|
-
const append = prototype.append;
|
|
5
|
-
prototype = Element.prototype;
|
|
6
|
-
const addEventListener = prototype.addEventListener;
|
|
7
|
-
const removeEventListener = prototype.removeEventListener;
|
|
8
|
-
const className = Object.getOwnPropertyDescriptor(prototype, 'className').set;
|
|
9
|
-
const innerHTML = Object.getOwnPropertyDescriptor(prototype, 'innerHTML').set;
|
|
10
|
-
const firstElementChild = Object.getOwnPropertyDescriptor(prototype, 'firstElementChild').get;
|
|
11
|
-
const nextElementSibling = Object.getOwnPropertyDescriptor(prototype, 'nextElementSibling').get;
|
|
12
|
-
const prepend = prototype.prepend;
|
|
13
|
-
const removeAttribute = prototype.removeAttribute;
|
|
14
|
-
const setAttribute = prototype.setAttribute;
|
|
15
|
-
prototype = Node.prototype;
|
|
16
|
-
const cloneNode = prototype.cloneNode;
|
|
17
|
-
const firstChild = Object.getOwnPropertyDescriptor(prototype, 'firstChild').get;
|
|
18
|
-
const nextSibling = Object.getOwnPropertyDescriptor(prototype, 'nextSibling').get;
|
|
19
|
-
const nodeValue = Object.getOwnPropertyDescriptor(prototype, 'nodeValue').set;
|
|
20
|
-
const parentElement = Object.getOwnPropertyDescriptor(prototype, 'parentElement').get;
|
|
21
|
-
const parentNode = Object.getOwnPropertyDescriptor(prototype, 'parentNode').get;
|
|
22
|
-
const fragment = (html) => {
|
|
23
|
-
innerHTML.call(template, html);
|
|
24
|
-
let { content } = template;
|
|
25
|
-
template = cloneNode.call(template);
|
|
26
|
-
return content;
|
|
27
|
-
};
|
|
28
|
-
const microtask = m();
|
|
29
|
-
const raf = r();
|
|
30
|
-
const text = (value) => {
|
|
31
|
-
let element = cloneNode.call(t);
|
|
32
|
-
if (value !== '') {
|
|
33
|
-
nodeValue.call(element, value);
|
|
34
|
-
}
|
|
35
|
-
return element;
|
|
36
|
-
};
|
|
37
|
-
export { addEventListener, append, className, cloneNode, firstChild, firstElementChild, fragment, innerHTML, microtask, nextElementSibling, nextSibling, nodeValue, parentElement, parentNode, prepend, raf, removeAttribute, removeEventListener, setAttribute, text };
|
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 };
|
package/src/utilities.ts
DELETED
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
import { micro as m, raf as r } from '@esportsplus/tasks';
|
|
2
|
-
import { Element as E } from './types';
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
let prototype,
|
|
6
|
-
template = document.createElement('template'),
|
|
7
|
-
t = document.createTextNode('');
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
prototype = DocumentFragment.prototype;
|
|
11
|
-
|
|
12
|
-
const append = prototype.append
|
|
13
|
-
|
|
14
|
-
// https://github.com/localvoid/ivi/blob/master/packages/ivi/src/client/core.ts#L38
|
|
15
|
-
prototype = Element.prototype;
|
|
16
|
-
|
|
17
|
-
const addEventListener = prototype.addEventListener;
|
|
18
|
-
|
|
19
|
-
const removeEventListener = prototype.removeEventListener;
|
|
20
|
-
|
|
21
|
-
const className = Object.getOwnPropertyDescriptor(prototype, 'className')!.set!;
|
|
22
|
-
|
|
23
|
-
const innerHTML = Object.getOwnPropertyDescriptor(prototype, 'innerHTML')!.set!;
|
|
24
|
-
|
|
25
|
-
const firstElementChild = Object.getOwnPropertyDescriptor(prototype, 'firstElementChild')!.get!;
|
|
26
|
-
|
|
27
|
-
const nextElementSibling = Object.getOwnPropertyDescriptor(prototype, 'nextElementSibling')!.get!;
|
|
28
|
-
|
|
29
|
-
const prepend = prototype.prepend;
|
|
30
|
-
|
|
31
|
-
const removeAttribute = prototype.removeAttribute;
|
|
32
|
-
|
|
33
|
-
const setAttribute = prototype.setAttribute;
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
prototype = Node.prototype;
|
|
37
|
-
|
|
38
|
-
const cloneNode = prototype.cloneNode;
|
|
39
|
-
|
|
40
|
-
const firstChild = Object.getOwnPropertyDescriptor(prototype, 'firstChild')!.get!;
|
|
41
|
-
|
|
42
|
-
const nextSibling = Object.getOwnPropertyDescriptor(prototype, 'nextSibling')!.get!;
|
|
43
|
-
|
|
44
|
-
const nodeValue = Object.getOwnPropertyDescriptor(prototype, 'nodeValue')!.set!;
|
|
45
|
-
|
|
46
|
-
const parentElement = Object.getOwnPropertyDescriptor(prototype, 'parentElement')!.get!;
|
|
47
|
-
|
|
48
|
-
const parentNode = Object.getOwnPropertyDescriptor(prototype, 'parentNode')!.get!;
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
const fragment = (html: string) => {
|
|
52
|
-
innerHTML.call(template, html);
|
|
53
|
-
|
|
54
|
-
let { content } = template;
|
|
55
|
-
|
|
56
|
-
template = cloneNode.call(template) as HTMLTemplateElement;
|
|
57
|
-
|
|
58
|
-
return content;
|
|
59
|
-
};
|
|
60
|
-
|
|
61
|
-
const microtask = m();
|
|
62
|
-
|
|
63
|
-
const raf = r();
|
|
64
|
-
|
|
65
|
-
const text = (value: string) => {
|
|
66
|
-
let element = cloneNode.call(t);
|
|
67
|
-
|
|
68
|
-
if (value !== '') {
|
|
69
|
-
nodeValue.call(element, value);
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
return element as E;
|
|
73
|
-
};
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
export {
|
|
77
|
-
addEventListener, append,
|
|
78
|
-
className, cloneNode,
|
|
79
|
-
firstChild, firstElementChild, fragment,
|
|
80
|
-
innerHTML,
|
|
81
|
-
microtask,
|
|
82
|
-
nextElementSibling, nextSibling, nodeValue,
|
|
83
|
-
parentElement, parentNode, prepend,
|
|
84
|
-
raf, removeAttribute, removeEventListener,
|
|
85
|
-
setAttribute,
|
|
86
|
-
text
|
|
87
|
-
};
|