@esportsplus/template 0.15.18 → 0.15.20

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.

Potentially problematic release.


This version of @esportsplus/template might be problematic. Click here for more details.

@@ -1,9 +1,7 @@
1
1
  import { Attributes, Element } from './types.js';
2
- declare const apply: (element: Element) => void;
3
2
  declare const spread: (element: Element, value: Attributes | Attributes[]) => void;
4
3
  declare const _default: {
5
- apply: (element: Element) => void;
6
4
  spread: (element: Element, value: Attributes | Attributes[]) => void;
7
5
  };
8
6
  export default _default;
9
- export { apply, spread };
7
+ export { spread };
@@ -5,7 +5,6 @@ import { className, raf, removeAttribute, setAttribute } from './utilities.js';
5
5
  import q from '@esportsplus/queue';
6
6
  import event from './event.js';
7
7
  const EFFECT_KEY = Symbol();
8
- const HYDRATE_KEY = Symbol();
9
8
  const STORE_KEY = Symbol();
10
9
  const UPDATES_KEY = Symbol();
11
10
  const STATE_HYDRATING = 0;
@@ -140,7 +139,7 @@ function update(context, id, name, value, state) {
140
139
  store[name] = value;
141
140
  }
142
141
  if (state === STATE_HYDRATING) {
143
- (context.element[HYDRATE_KEY] ??= {})[name] = value;
142
+ attribute(context.element, name, value);
144
143
  }
145
144
  else {
146
145
  context.updates[name] = value;
@@ -153,16 +152,6 @@ function update(context, id, name, value, state) {
153
152
  }
154
153
  }
155
154
  }
156
- const apply = (element) => {
157
- let attributes = element[HYDRATE_KEY];
158
- if (!attributes) {
159
- return;
160
- }
161
- for (let key in attributes) {
162
- attribute(element, key, attributes[key]);
163
- }
164
- delete element[HYDRATE_KEY];
165
- };
166
155
  const spread = function (element, value) {
167
156
  let cache = (element[STORE_KEY] ??= { [UPDATES_KEY]: {} }), context = {
168
157
  element,
@@ -184,5 +173,5 @@ const spread = function (element, value) {
184
173
  }
185
174
  }
186
175
  };
187
- export default { apply, spread };
188
- export { apply, spread };
176
+ export default { spread };
177
+ export { spread };
@@ -26,6 +26,7 @@ function build(literals, values) {
26
26
  while (i !== -1) {
27
27
  slots.push({
28
28
  fn: spread,
29
+ parent: parent.path,
29
30
  path,
30
31
  slot
31
32
  });
@@ -48,7 +49,8 @@ function build(literals, values) {
48
49
  buffer += parsed[slot] + SLOT_HTML;
49
50
  slots.push({
50
51
  fn: s,
51
- path: methods(parent.children, parent.path, firstChild, nextSibling),
52
+ parent: parent.path,
53
+ path: methods(parent.children, [], firstChild, nextSibling),
52
54
  slot: slot++
53
55
  });
54
56
  }
@@ -1,6 +1,5 @@
1
1
  import { root } from '@esportsplus/reactivity';
2
2
  import { cloneNode, firstChild, nextSibling } from '../utilities.js';
3
- import { apply } from '../attributes.js';
4
3
  import cache from './cache.js';
5
4
  function reactive(renderable, slot) {
6
5
  let array = renderable.values, factory = renderable.template, refresh = () => {
@@ -35,7 +34,6 @@ function hydrate(renderable, template) {
35
34
  for (let i = slots.length - 1; i >= 0; i--) {
36
35
  let { fn, path, slot } = slots[i];
37
36
  if (path !== previous) {
38
- apply(node);
39
37
  node = fragment;
40
38
  previous = path;
41
39
  for (let o = 0, j = path.length; o < j; o++) {
@@ -44,7 +42,6 @@ function hydrate(renderable, template) {
44
42
  }
45
43
  fn(node, values[slot]);
46
44
  }
47
- apply(node);
48
45
  }
49
46
  for (let element = firstChild.call(fragment); element; element = nextSibling.call(element)) {
50
47
  elements.push(element);
package/build/slot.d.ts CHANGED
@@ -10,7 +10,7 @@ declare class Slot {
10
10
  clear(): void;
11
11
  pop(): Elements[] | undefined;
12
12
  push(...groups: HydrateResult[]): number;
13
- render(input: unknown): this;
13
+ render(input: unknown, state?: number): this;
14
14
  shift(): Elements[] | undefined;
15
15
  splice(start: number, stop?: number, ...groups: HydrateResult[]): Elements[];
16
16
  unshift(...groups: HydrateResult[]): number;
package/build/slot.js CHANGED
@@ -5,27 +5,24 @@ import { hydrate } from './html/index.js';
5
5
  import { append, cloneNode, firstChild, fragment, microtask, nextSibling, nodeValue, raf, text } from './utilities.js';
6
6
  import queue from '@esportsplus/queue';
7
7
  const CLEANUP_KEY = Symbol();
8
+ const CONNECTED = 0;
9
+ const HYDRATING = 1;
8
10
  let cleanup = queue(64), scheduled = false, template = fragment('');
9
11
  function after(anchor, groups) {
10
12
  let n = groups.length;
11
13
  if (n === 0) {
12
14
  return [];
13
15
  }
14
- let elements = [], fragment = groups[0].fragment || cloneNode.call(template);
15
- if (n === 1) {
16
- elements.push(groups[0].elements);
17
- }
18
- else {
19
- for (let i = 1; i < n; i++) {
20
- let { elements: e, fragment: f } = groups[i];
21
- append.call(fragment, f);
22
- elements.push(e);
23
- }
16
+ let fragment = cloneNode.call(template), elements = new Array(n);
17
+ for (let i = 0; i < n; i++) {
18
+ let { elements: e, fragment: f } = groups[i];
19
+ append.call(fragment, f);
20
+ elements[i] = e;
24
21
  }
25
22
  anchor.after(fragment);
26
23
  return elements;
27
24
  }
28
- function remove(...groups) {
25
+ function remove(groups) {
29
26
  for (let i = 0, n = groups.length; i < n; i++) {
30
27
  let group = groups[i];
31
28
  for (let j = 0, o = group.length; j < o; j++) {
@@ -45,7 +42,16 @@ function render(elements, fragment, input, slot) {
45
42
  if (input === false || input == null || input === '') {
46
43
  return;
47
44
  }
48
- if (isArray(input)) {
45
+ let type = typeof input;
46
+ if (type === 'string' || type === 'number') {
47
+ let element = text(type === 'string' ? input : String(input));
48
+ if (slot) {
49
+ slot.text = element;
50
+ }
51
+ append.call(fragment, element);
52
+ elements.push([element]);
53
+ }
54
+ else if (isArray(input)) {
49
55
  for (let i = 0, n = input.length; i < n; i++) {
50
56
  render(elements, fragment, input[i]);
51
57
  }
@@ -66,9 +72,9 @@ function render(elements, fragment, input, slot) {
66
72
  }
67
73
  }
68
74
  else if (isInstanceOf(input, NodeList)) {
69
- let e = [];
75
+ let e = new Array(input.length), i = 0;
70
76
  for (let node = firstChild.call(input); node; node = nextSibling.call(node)) {
71
- e.push(node);
77
+ e[i++] = node;
72
78
  }
73
79
  append.call(fragment, ...e);
74
80
  elements.push(e);
@@ -77,14 +83,6 @@ function render(elements, fragment, input, slot) {
77
83
  append.call(fragment, input);
78
84
  elements.push([input]);
79
85
  }
80
- else {
81
- let element = text(typeof input === 'string' ? input : String(input));
82
- if (slot) {
83
- slot.text = element;
84
- }
85
- append.call(fragment, element);
86
- elements.push([element]);
87
- }
88
86
  }
89
87
  function schedule() {
90
88
  if (scheduled) {
@@ -124,14 +122,11 @@ class Slot {
124
122
  this.splice(n);
125
123
  }
126
124
  anchor(index = this.nodes.length - 1) {
127
- let node, nodes = this.nodes[index];
128
- if (nodes) {
129
- node = nodes[nodes.length - 1];
130
- }
131
- return node || this.marker;
125
+ let nodes = this.nodes[index];
126
+ return nodes ? nodes[nodes.length - 1] : this.marker;
132
127
  }
133
128
  clear() {
134
- remove(...this.nodes);
129
+ remove(this.nodes);
135
130
  this.nodes.length = 0;
136
131
  this.text = null;
137
132
  }
@@ -140,32 +135,35 @@ class Slot {
140
135
  if (!group) {
141
136
  return undefined;
142
137
  }
143
- return remove(group);
138
+ return remove([group]);
144
139
  }
145
140
  push(...groups) {
146
141
  return this.nodes.push(...after(this.anchor(), groups));
147
142
  }
148
- render(input) {
143
+ render(input, state = HYDRATING) {
149
144
  if (isFunction(input)) {
150
145
  ondisconnect(this.marker, effect(() => {
151
146
  let v = input();
152
147
  if (isFunction(v)) {
153
- root(() => this.render(v()));
148
+ root(() => this.render(v(), state));
149
+ state = CONNECTED;
150
+ }
151
+ else if (state === HYDRATING) {
152
+ this.render(v, state);
153
+ state = CONNECTED;
154
154
  }
155
- else {
155
+ else if (state === CONNECTED) {
156
156
  raf.add(() => {
157
- this.render(v);
157
+ this.render(v, state);
158
158
  });
159
159
  }
160
160
  }));
161
161
  return this;
162
162
  }
163
- if (this.text) {
163
+ if (this.text && this.text.isConnected) {
164
164
  let type = typeof input;
165
- if (type === 'object' && input !== null) {
166
- }
167
- else if (this.text.isConnected) {
168
- nodeValue.call(this.text, (type === 'string' || type === 'number') ? input : '');
165
+ if (input == null || type !== 'object') {
166
+ nodeValue.call(this.text, (type === 'number' || type === 'string') ? input : '');
169
167
  return this;
170
168
  }
171
169
  }
@@ -181,10 +179,13 @@ class Slot {
181
179
  if (!group) {
182
180
  return undefined;
183
181
  }
184
- return remove(group);
182
+ return remove([group]);
185
183
  }
186
184
  splice(start, stop = this.nodes.length, ...groups) {
187
- return remove(...this.nodes.splice(start, stop, ...after(this.anchor(start), groups)));
185
+ if (!groups.length) {
186
+ return remove(this.nodes.splice(start, stop));
187
+ }
188
+ return remove(this.nodes.splice(start, stop, ...after(this.anchor(start), groups)));
188
189
  }
189
190
  unshift(...groups) {
190
191
  return this.nodes.unshift(...after(this.marker, groups));
package/build/types.d.ts CHANGED
@@ -45,6 +45,7 @@ type Template = {
45
45
  literals: TemplateStringsArray;
46
46
  slots: {
47
47
  fn: typeof attributes.spread | typeof slot;
48
+ parent: typeof firstChild[];
48
49
  path: typeof firstChild[];
49
50
  slot: number;
50
51
  }[] | null;
@@ -1,9 +1,9 @@
1
1
  import { Element as E } from './types.js';
2
+ declare const append: (...nodes: (Node | string)[]) => void;
2
3
  declare const addEventListener: {
3
4
  <K extends keyof ElementEventMap>(type: K, listener: (this: Element, ev: ElementEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void;
4
5
  (type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void;
5
6
  };
6
- declare const append: (...nodes: (Node | string)[]) => void;
7
7
  declare const removeEventListener: {
8
8
  <K extends keyof ElementEventMap>(type: K, listener: (this: Element, ev: ElementEventMap[K]) => any, options?: boolean | EventListenerOptions): void;
9
9
  (type: string, listener: EventListenerOrEventListenerObject, options?: boolean | EventListenerOptions): void;
@@ -1,8 +1,9 @@
1
1
  import { micro as m, raf as r } from '@esportsplus/tasks';
2
2
  let prototype, template = document.createElement('template'), t = document.createTextNode('');
3
+ prototype = DocumentFragment.prototype;
4
+ const append = prototype.append;
3
5
  prototype = Element.prototype;
4
6
  const addEventListener = prototype.addEventListener;
5
- const append = prototype.append;
6
7
  const removeEventListener = prototype.removeEventListener;
7
8
  const className = Object.getOwnPropertyDescriptor(prototype, 'className').set;
8
9
  const innerHTML = Object.getOwnPropertyDescriptor(prototype, 'innerHTML').set;
package/package.json CHANGED
@@ -14,7 +14,7 @@
14
14
  "private": false,
15
15
  "type": "module",
16
16
  "types": "./build/index.d.ts",
17
- "version": "0.15.18",
17
+ "version": "0.15.20",
18
18
  "scripts": {
19
19
  "build": "tsc && tsc-alias",
20
20
  "-": "-"
package/src/attributes.ts CHANGED
@@ -9,8 +9,6 @@ import event from './event';
9
9
 
10
10
  const EFFECT_KEY = Symbol();
11
11
 
12
- const HYDRATE_KEY = Symbol();
13
-
14
12
  const STORE_KEY = Symbol();
15
13
 
16
14
  const UPDATES_KEY = Symbol();
@@ -216,7 +214,7 @@ function update(
216
214
  }
217
215
 
218
216
  if (state === STATE_HYDRATING) {
219
- ((context.element[HYDRATE_KEY] ??= {}) as Record<PropertyKey, unknown>)[name] = value;
217
+ attribute(context.element, name, value);
220
218
  }
221
219
  else {
222
220
  context.updates[name] = value;
@@ -233,20 +231,6 @@ function update(
233
231
  }
234
232
 
235
233
 
236
- const apply = (element: Element) => {
237
- let attributes = element[HYDRATE_KEY] as Record<PropertyKey, unknown> | undefined;
238
-
239
- if (!attributes) {
240
- return;
241
- }
242
-
243
- for (let key in attributes) {
244
- attribute(element, key, attributes[key]);
245
- }
246
-
247
- delete element[HYDRATE_KEY];
248
- };
249
-
250
234
  const spread = function (element: Element, value: Attributes | Attributes[]) {
251
235
  let cache = (element[STORE_KEY] ??= { [UPDATES_KEY]: {} }) as Record<PropertyKey, unknown>,
252
236
  context = {
@@ -273,5 +257,5 @@ const spread = function (element: Element, value: Attributes | Attributes[]) {
273
257
  };
274
258
 
275
259
 
276
- export default { apply, spread };
277
- export { apply, spread };
260
+ export default { spread };
261
+ export { spread };
package/src/html/cache.ts CHANGED
@@ -51,6 +51,7 @@ function build(literals: TemplateStringsArray, values: unknown[]) {
51
51
  while (i !== -1) {
52
52
  slots.push({
53
53
  fn: spread,
54
+ parent: parent.path,
54
55
  path,
55
56
  slot
56
57
  });
@@ -76,7 +77,8 @@ function build(literals: TemplateStringsArray, values: unknown[]) {
76
77
  buffer += parsed[slot] + SLOT_HTML;
77
78
  slots.push({
78
79
  fn: s,
79
- path: methods(parent.children, parent.path, firstChild, nextSibling),
80
+ parent: parent.path,
81
+ path: methods(parent.children, [], firstChild, nextSibling),
80
82
  slot: slot++
81
83
  });
82
84
  }
@@ -2,7 +2,6 @@ import { root } from '@esportsplus/reactivity';
2
2
  import { Element, Elements, HydrateResult, Renderable, RenderableReactive, RenderableTemplate, Template } from '~/types';
3
3
  import { Slot } from '~/slot';
4
4
  import { cloneNode, firstChild, nextSibling } from '~/utilities';
5
- import { apply } from '~/attributes';
6
5
  import cache from './cache';
7
6
 
8
7
 
@@ -53,8 +52,6 @@ function hydrate<T>(renderable: Renderable<T>, template: Template): HydrateResul
53
52
  let { fn, path, slot } = slots[i];
54
53
 
55
54
  if (path !== previous) {
56
- apply(node);
57
-
58
55
  node = fragment;
59
56
  previous = path;
60
57
 
@@ -66,8 +63,6 @@ function hydrate<T>(renderable: Renderable<T>, template: Template): HydrateResul
66
63
  // @ts-ignore
67
64
  fn(node, values[slot]);
68
65
  }
69
-
70
- apply(node);
71
66
  }
72
67
 
73
68
  for (let element = firstChild.call(fragment as Element); element; element = nextSibling.call(element)) {
package/src/slot.ts CHANGED
@@ -9,6 +9,10 @@ import queue from '@esportsplus/queue';
9
9
 
10
10
  const CLEANUP_KEY = Symbol();
11
11
 
12
+ const CONNECTED = 0;
13
+
14
+ const HYDRATING = 1;
15
+
12
16
 
13
17
  let cleanup = queue<VoidFunction[]>(64),
14
18
  scheduled = false,
@@ -22,19 +26,14 @@ function after(anchor: Element, groups: HydrateResult[]) {
22
26
  return [];
23
27
  }
24
28
 
25
- let elements: Elements[] = [],
26
- fragment = groups[0].fragment || cloneNode.call(template);
29
+ let fragment = cloneNode.call(template),
30
+ elements = new Array(n);
27
31
 
28
- if (n === 1) {
29
- elements.push( groups[0].elements );
30
- }
31
- else {
32
- for (let i = 1; i < n; i++) {
33
- let { elements: e, fragment: f } = groups[i];
32
+ for (let i = 0; i < n; i++) {
33
+ let { elements: e, fragment: f } = groups[i];
34
34
 
35
- append.call(fragment, f);
36
- elements.push(e);
37
- }
35
+ append.call(fragment, f);
36
+ elements[i] = e;
38
37
  }
39
38
 
40
39
  anchor.after(fragment);
@@ -42,7 +41,7 @@ function after(anchor: Element, groups: HydrateResult[]) {
42
41
  return elements;
43
42
  }
44
43
 
45
- function remove(...groups: Elements[]) {
44
+ function remove(groups: Elements[]) {
46
45
  for (let i = 0, n = groups.length; i < n; i++) {
47
46
  let group = groups[i];
48
47
 
@@ -69,7 +68,19 @@ function render(elements: Elements[], fragment: DocumentFragment | Node, input:
69
68
  return;
70
69
  }
71
70
 
72
- if (isArray(input)) {
71
+ let type = typeof input;
72
+
73
+ if (type === 'string' || type === 'number') {
74
+ let element = text(type === 'string' ? input as string : String(input));
75
+
76
+ if (slot) {
77
+ slot.text = element;
78
+ }
79
+
80
+ append.call(fragment, element);
81
+ elements.push([element]);
82
+ }
83
+ else if (isArray(input)) {
73
84
  for (let i = 0, n = input.length; i < n; i++) {
74
85
  render(elements, fragment, input[i]);
75
86
  }
@@ -93,10 +104,11 @@ function render(elements: Elements[], fragment: DocumentFragment | Node, input:
93
104
  }
94
105
  }
95
106
  else if (isInstanceOf(input, NodeList)) {
96
- let e: Elements = [];
107
+ let e: Elements = new Array(input.length),
108
+ i = 0;
97
109
 
98
110
  for (let node = firstChild.call(input); node; node = nextSibling.call(node)) {
99
- e.push(node);
111
+ e[i++] = node;
100
112
  }
101
113
 
102
114
  append.call(fragment, ...e);
@@ -106,16 +118,6 @@ function render(elements: Elements[], fragment: DocumentFragment | Node, input:
106
118
  append.call(fragment, input);
107
119
  elements.push([ input as Element ]);
108
120
  }
109
- else {
110
- let element = text( typeof input === 'string' ? input : String(input) );
111
-
112
- if (slot) {
113
- slot.text = element;
114
- }
115
-
116
- append.call(fragment, element);
117
- elements.push([ element ]);
118
- }
119
121
  }
120
122
 
121
123
  function schedule() {
@@ -171,18 +173,13 @@ class Slot {
171
173
 
172
174
 
173
175
  anchor(index: number = this.nodes.length - 1) {
174
- let node,
175
- nodes = this.nodes[index];
176
+ let nodes = this.nodes[index];
176
177
 
177
- if (nodes) {
178
- node = nodes[nodes.length - 1];
179
- }
180
-
181
- return node || this.marker;
178
+ return nodes ? nodes[nodes.length - 1] : this.marker;
182
179
  }
183
180
 
184
181
  clear() {
185
- remove(...this.nodes);
182
+ remove(this.nodes);
186
183
  this.nodes.length = 0;
187
184
  this.text = null;
188
185
  }
@@ -194,14 +191,14 @@ class Slot {
194
191
  return undefined;
195
192
  }
196
193
 
197
- return remove(group);
194
+ return remove([group]);
198
195
  }
199
196
 
200
197
  push(...groups: HydrateResult[]) {
201
198
  return this.nodes.push( ...after(this.anchor(), groups) );
202
199
  }
203
200
 
204
- render(input: unknown) {
201
+ render(input: unknown, state = HYDRATING) {
205
202
  if (isFunction(input)) {
206
203
  ondisconnect(
207
204
  this.marker,
@@ -209,11 +206,16 @@ class Slot {
209
206
  let v = input();
210
207
 
211
208
  if (isFunction(v)) {
212
- root(() => this.render(v()));
209
+ root(() => this.render(v(), state));
210
+ state = CONNECTED;
211
+ }
212
+ else if (state === HYDRATING) {
213
+ this.render(v, state);
214
+ state = CONNECTED;
213
215
  }
214
- else {
216
+ else if (state === CONNECTED) {
215
217
  raf.add(() => {
216
- this.render(v);
218
+ this.render(v, state);
217
219
  });
218
220
  }
219
221
  })
@@ -222,16 +224,11 @@ class Slot {
222
224
  return this;
223
225
  }
224
226
 
225
- if (this.text) {
227
+ if (this.text && this.text.isConnected) {
226
228
  let type = typeof input;
227
229
 
228
- if (type === 'object' && input !== null) {
229
- }
230
- else if (this.text.isConnected) {
231
- nodeValue.call(
232
- this.text,
233
- (type === 'string' || type === 'number') ? input : ''
234
- );
230
+ if (input == null || type !== 'object') {
231
+ nodeValue.call(this.text, (type === 'number' || type === 'string') ? input : '');
235
232
  return this;
236
233
  }
237
234
  }
@@ -256,12 +253,16 @@ class Slot {
256
253
  return undefined;
257
254
  }
258
255
 
259
- return remove(group);
256
+ return remove([group]);
260
257
  }
261
258
 
262
259
  splice(start: number, stop: number = this.nodes.length, ...groups: HydrateResult[]) {
260
+ if (!groups.length) {
261
+ return remove(this.nodes.splice(start, stop));
262
+ }
263
+
263
264
  return remove(
264
- ...this.nodes.splice(
265
+ this.nodes.splice(
265
266
  start,
266
267
  stop,
267
268
  ...after(this.anchor(start), groups)
package/src/types.ts CHANGED
@@ -63,6 +63,7 @@ type Template = {
63
63
  literals: TemplateStringsArray;
64
64
  slots: {
65
65
  fn: typeof attributes.spread | typeof slot;
66
+ parent: typeof firstChild[];
66
67
  path: typeof firstChild[];
67
68
  slot: number;
68
69
  }[] | null;
package/src/utilities.ts CHANGED
@@ -7,13 +7,15 @@ let prototype,
7
7
  t = document.createTextNode('');
8
8
 
9
9
 
10
+ prototype = DocumentFragment.prototype;
11
+
12
+ const append = prototype.append
13
+
10
14
  // https://github.com/localvoid/ivi/blob/master/packages/ivi/src/client/core.ts#L38
11
15
  prototype = Element.prototype;
12
16
 
13
17
  const addEventListener = prototype.addEventListener;
14
18
 
15
- const append = prototype.append;
16
-
17
19
  const removeEventListener = prototype.removeEventListener;
18
20
 
19
21
  const className = Object.getOwnPropertyDescriptor(prototype, 'className')!.set!;