@esportsplus/template 0.15.20 → 0.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/build/attributes.js +27 -23
  2. package/build/constants.d.ts +14 -3
  3. package/build/constants.js +15 -3
  4. package/build/event.js +7 -7
  5. package/build/html/cache.d.ts +2 -2
  6. package/build/html/cache.js +24 -16
  7. package/build/html/hydrate.d.ts +2 -6
  8. package/build/html/hydrate.js +29 -53
  9. package/build/html/index.d.ts +2106 -5
  10. package/build/html/index.js +12 -4
  11. package/build/render.d.ts +1 -2
  12. package/build/render.js +6 -10
  13. package/build/slot/cleanup.d.ts +4 -0
  14. package/build/slot/cleanup.js +51 -0
  15. package/build/slot/effect.d.ts +3 -0
  16. package/build/slot/effect.js +51 -0
  17. package/build/slot/index.d.ts +3 -0
  18. package/build/slot/index.js +15 -0
  19. package/build/slot/reactive.d.ts +3 -0
  20. package/build/slot/reactive.js +117 -0
  21. package/build/slot/render.d.ts +2 -0
  22. package/build/slot/render.js +58 -0
  23. package/build/svg.d.ts +1 -2
  24. package/build/types.d.ts +25 -21
  25. package/build/utilities.d.ts +3 -3
  26. package/build/utilities.js +12 -12
  27. package/package.json +2 -2
  28. package/src/attributes.ts +30 -28
  29. package/src/constants.ts +38 -4
  30. package/src/event.ts +8 -8
  31. package/src/html/cache.ts +28 -18
  32. package/src/html/hydrate.ts +38 -68
  33. package/src/html/index.ts +16 -8
  34. package/src/render.ts +8 -12
  35. package/src/slot/cleanup.ts +74 -0
  36. package/src/slot/effect.ts +73 -0
  37. package/src/slot/index.ts +23 -0
  38. package/src/slot/reactive.ts +167 -0
  39. package/src/slot/render.ts +81 -0
  40. package/src/svg.ts +1 -2
  41. package/src/types.ts +30 -20
  42. package/src/utilities.ts +15 -13
  43. package/build/slot.d.ts +0 -21
  44. package/build/slot.js +0 -200
  45. package/src/slot.ts +0 -287
@@ -0,0 +1,167 @@
1
+ import { root, ReactiveArray } from '@esportsplus/reactivity';
2
+ import { EMPTY_FRAGMENT } from '~/constants';
3
+ import { Fragment, RenderableReactive, SlotGroup } from '~/types';
4
+ import { append, cloneNode, firstChild, lastChild } from '~/utilities';
5
+ import { remove } from './cleanup';
6
+
7
+
8
+ class ReactiveArraySlot<T> {
9
+ array: ReactiveArray<T[]>;
10
+ fragment = cloneNode.call(EMPTY_FRAGMENT) as Fragment;
11
+ marker: Element;
12
+ nodes: SlotGroup[] = [];
13
+ template: (
14
+ this: ReactiveArray<T[]>,
15
+ ...args: Parameters< Parameters<ReactiveArray<T[]>['map']>[0] >
16
+ ) => SlotGroup;
17
+
18
+
19
+ constructor(anchor: Element, array: ReactiveArray<T[]>, template: RenderableReactive['template']) {
20
+ let fragment = this.fragment;
21
+
22
+ this.array = array;
23
+ this.marker = anchor;
24
+ this.template = function (data, i) {
25
+ let frag = template.call(this, data, i).fragment,
26
+ group = {
27
+ head: firstChild.call(frag),
28
+ tail: lastChild.call(frag)
29
+ };
30
+
31
+ append.call(fragment, frag);
32
+
33
+ return group;
34
+ };
35
+
36
+
37
+ let render = () => {
38
+ root(() => this.render());
39
+ };
40
+
41
+ array.on('clear', () => this.clear());
42
+ array.on('reverse', render);
43
+ array.on('pop', () => this.pop());
44
+ array.on('push', ({ items }) => {
45
+ root(() => this.push(items));
46
+ });
47
+ array.on('shift', () => this.shift());
48
+ array.on('sort', render);
49
+ array.on('splice', ({ deleteCount, items, start }) => {
50
+ root(() => this.splice(start, deleteCount, ...items));
51
+ });
52
+ array.on('unshift', ({ items }) => {
53
+ root(() => this.unshift(items));
54
+ });
55
+
56
+ if (array.length) {
57
+ render();
58
+ }
59
+ }
60
+
61
+
62
+ get length() {
63
+ return this.nodes.length;
64
+ }
65
+
66
+ set length(n: number) {
67
+ if (n >= this.nodes.length) {
68
+ return;
69
+ }
70
+ else if (n === 0) {
71
+ this.clear();
72
+ }
73
+ else {
74
+ this.splice(n);
75
+ }
76
+ }
77
+
78
+
79
+ anchor(index: number = this.nodes.length - 1) {
80
+ let node = this.nodes[index];
81
+
82
+ if (node) {
83
+ return node.tail || node.head;
84
+ }
85
+
86
+ return this.marker;
87
+ }
88
+
89
+ clear() {
90
+ remove(this.nodes);
91
+ }
92
+
93
+ pop() {
94
+ let group = this.nodes.pop();
95
+
96
+ if (group) {
97
+ remove([group]);
98
+ }
99
+ }
100
+
101
+ push(items: T[]) {
102
+ let anchor = this.anchor(),
103
+ array = this.array;
104
+
105
+ for (let i = 0, n = items.length; i < n; i++) {
106
+ this.nodes.push(
107
+ this.template.call(array, items[i], i)
108
+ );
109
+ }
110
+
111
+ anchor.after(this.fragment);
112
+ }
113
+
114
+ render() {
115
+ let nodes = this.nodes;
116
+
117
+ if (nodes.length) {
118
+ remove(nodes);
119
+ }
120
+
121
+ nodes = this.array.map(this.template);
122
+ this.marker.after(this.fragment);
123
+ }
124
+
125
+ shift() {
126
+ let group = this.nodes.shift();
127
+
128
+ if (group) {
129
+ remove([group]);
130
+ }
131
+ }
132
+
133
+ splice(start: number, stop: number = this.nodes.length, ...items: T[]) {
134
+ if (!items.length) {
135
+ return remove(this.nodes.splice(start, stop));
136
+ }
137
+
138
+ let array = this.array,
139
+ n = items.length,
140
+ nodes = new Array(n);
141
+
142
+ for (let i = 0; i < n; i++) {
143
+ nodes[i] = this.template.call(array, items[i], i);
144
+ }
145
+
146
+ remove(this.nodes.splice(start, stop, ...nodes));
147
+ this.anchor(start - 1).after(this.fragment);
148
+ }
149
+
150
+ unshift(items: T[]) {
151
+ let array = this.array,
152
+ n = items.length,
153
+ nodes = new Array(n);
154
+
155
+ for (let i = 0; i < n; i++) {
156
+ nodes[i] = this.template.call(array, items[i], i);
157
+ }
158
+
159
+ this.nodes.unshift(...nodes);
160
+ this.marker.after(this.fragment);
161
+ }
162
+ }
163
+
164
+
165
+ export default (anchor: Element, renderable: RenderableReactive) => {
166
+ new ReactiveArraySlot(anchor, renderable.array, renderable.template);
167
+ };
@@ -0,0 +1,81 @@
1
+ import { isArray } from '@esportsplus/utilities';
2
+ import {
3
+ RENDERABLE,
4
+ RENDERABLE_ARRAY, RENDERABLE_FRAGMENT, RENDERABLE_HTML_FRAGMENT, RENDERABLE_HTML_REACTIVE_ARRAY,
5
+ RENDERABLE_NODE, RENDERABLE_NODE_LIST, RENDERABLE_TEXT, RENDERABLE_VOID
6
+ } from '~/constants';
7
+ import { Element, Fragment, RenderableReactive, RenderableTemplate } from '~/types';
8
+ import { append, text } from '~/utilities';
9
+ import reactive from './reactive';
10
+
11
+
12
+ function type(input: unknown) {
13
+ if (input === false || input == null || input === '') {
14
+ return RENDERABLE_VOID;
15
+ }
16
+
17
+ if (typeof input !== 'object') {
18
+ return RENDERABLE_TEXT;
19
+ }
20
+
21
+ if (RENDERABLE in input) {
22
+ return input[RENDERABLE];
23
+ }
24
+
25
+ if (isArray(input)) {
26
+ return RENDERABLE_ARRAY;
27
+ }
28
+
29
+ let nodeType = (input as any).nodeType;
30
+
31
+ if (nodeType === 11) {
32
+ return RENDERABLE_FRAGMENT;
33
+ }
34
+
35
+ if (nodeType !== undefined) {
36
+ return RENDERABLE_NODE;
37
+ }
38
+
39
+ if (input instanceof NodeList) {
40
+ return RENDERABLE_NODE_LIST;
41
+ }
42
+ }
43
+
44
+
45
+ export default function render(anchor: Element, fragment: Fragment, input: unknown) {
46
+ let t = type(input);
47
+
48
+ switch (t) {
49
+ case RENDERABLE_VOID:
50
+ return;
51
+
52
+ case RENDERABLE_TEXT:
53
+ append.call(fragment, text(String(input)));
54
+ return;
55
+
56
+ case RENDERABLE_HTML_FRAGMENT:
57
+ append.call(fragment, (input as RenderableTemplate).fragment);
58
+ return;
59
+
60
+ case RENDERABLE_HTML_REACTIVE_ARRAY:
61
+ return reactive(anchor, input as RenderableReactive);
62
+
63
+ case RENDERABLE_ARRAY:
64
+ for (let i = 0, n = (input as unknown[]).length; i < n; i++) {
65
+ render(anchor, fragment, (input as unknown[])[i]);
66
+ }
67
+ return;
68
+
69
+ case RENDERABLE_FRAGMENT:
70
+ append.call(fragment, input as Fragment);
71
+ return;
72
+
73
+ case RENDERABLE_NODE:
74
+ append.call(fragment, input as Node);
75
+ return;
76
+
77
+ case RENDERABLE_NODE_LIST:
78
+ append.call(fragment, ...(input as NodeList));
79
+ return;
80
+ }
81
+ };
package/src/svg.ts CHANGED
@@ -1,9 +1,8 @@
1
1
  import html from './html';
2
- import { RenderableTemplate } from './types';
3
2
 
4
3
 
5
4
  const svg = html.bind(null) as typeof html & {
6
- sprite: <T>(symbol: string) => RenderableTemplate<T>
5
+ sprite: (symbol: string) => ReturnType<typeof html>
7
6
  };
8
7
 
9
8
  svg.sprite = (symbol: string) => {
package/src/types.ts CHANGED
@@ -1,8 +1,9 @@
1
1
  import { ReactiveArray } from '@esportsplus/reactivity';
2
- import { RENDERABLE, RENDERABLE_REACTIVE, RENDERABLE_TEMPLATE } from './constants';
2
+ import { RENDERABLE, RENDERABLE_HTML_FRAGMENT, RENDERABLE_HTML_REACTIVE_ARRAY } from './constants';
3
3
  import { firstChild } from './utilities';
4
4
  import attributes from './attributes';
5
5
  import slot from './slot';
6
+ import html from './html';
6
7
 
7
8
 
8
9
  type Attribute = Primitive | Effect<Primitive | Primitive[]>;
@@ -24,38 +25,43 @@ type Attributes = {
24
25
 
25
26
  type Effect<T> = () => EffectResponse<T>;
26
27
 
27
- type EffectResponse<T> = T extends [] ? EffectResponse<T[number]>[] : Primitive | Renderable<T>;
28
+ type EffectResponse<T> = T extends [] ? (Primitive | Renderable)[] : Primitive | Renderable;
28
29
 
29
30
  type Element = HTMLElement & Attributes & Record<PropertyKey, unknown>;
30
31
 
31
32
  type Elements = Element[];
32
33
 
33
- type HydrateResult = { elements: Elements, fragment: DocumentFragment | Node };
34
+ type Fragment = (DocumentFragment | Node) & Record<PropertyKey, unknown>;
34
35
 
35
36
  // Copied from '@esportsplus/utilities'
36
37
  // - Importing from ^ causes 'cannot be named without a reference to...' error
37
38
  type Primitive = bigint | boolean | null | number | string | undefined;
38
39
 
39
- type Renderable<T = unknown> = RenderableReactive<T> | RenderableTemplate<T>;
40
+ type Renderable = Fragment | RenderableReactive;
40
41
 
41
- type RenderableReactive<T = unknown> = Readonly<{
42
- [RENDERABLE]: typeof RENDERABLE_REACTIVE;
43
- literals: null;
42
+ type RenderableReactive = Readonly<{
43
+ [RENDERABLE]: typeof RENDERABLE_HTML_REACTIVE_ARRAY;
44
+ array: ReactiveArray<unknown[]>;
44
45
  template: (
45
- this: ThisParameterType< Parameters<ReactiveArray<T>['map']>[0] >,
46
- ...args: Parameters< Parameters<ReactiveArray<T>['map']>[0] >
47
- ) => RenderableTemplate<T>;
48
- values: ReactiveArray<T>;
46
+ this: ReactiveArray<unknown[]>,
47
+ ...args: Parameters< Parameters<ReactiveArray<unknown[]>['map']>[0] >
48
+ ) => ReturnType<typeof html>;
49
49
  }>;
50
50
 
51
- type RenderableTemplate<T> = {
52
- [RENDERABLE]: typeof RENDERABLE_TEMPLATE;
51
+ type RenderableTemplate = {
52
+ [RENDERABLE]: typeof RENDERABLE_HTML_FRAGMENT;
53
+ fragment: Fragment;
53
54
  literals: TemplateStringsArray;
54
- template: Template | null;
55
- values: (RenderableValue<T> | RenderableValue<T>[])[];
56
55
  };
57
56
 
58
- type RenderableValue<T = unknown> = Attributes | Readonly<Attributes> | Readonly<Attributes[]> | Effect<T> | Primitive | Renderable;
57
+ type RenderableValue<T = unknown> = Attributes | Readonly<Attributes> | Readonly<Attributes[]> | Effect<T> | Fragment | Primitive | RenderableReactive;
58
+
59
+ type RenderableValues = RenderableValue | RenderableValue[];
60
+
61
+ type SlotGroup = {
62
+ head: Element;
63
+ tail: Element;
64
+ };
59
65
 
60
66
  type Template = {
61
67
  fragment: DocumentFragment;
@@ -63,8 +69,11 @@ type Template = {
63
69
  literals: TemplateStringsArray;
64
70
  slots: {
65
71
  fn: typeof attributes.spread | typeof slot;
66
- parent: typeof firstChild[];
67
- path: typeof firstChild[];
72
+ path: {
73
+ absolute: typeof firstChild[],
74
+ parent: typeof firstChild[],
75
+ relative: typeof firstChild[]
76
+ };
68
77
  slot: number;
69
78
  }[] | null;
70
79
  };
@@ -73,7 +82,8 @@ type Template = {
73
82
  export type {
74
83
  Attributes,
75
84
  Effect, Element, Elements,
76
- HydrateResult,
77
- Renderable, RenderableReactive, RenderableTemplate, RenderableValue,
85
+ Fragment,
86
+ Renderable, RenderableReactive, RenderableTemplate, RenderableValue, RenderableValues,
87
+ SlotGroup,
78
88
  Template
79
89
  };
package/src/utilities.ts CHANGED
@@ -2,7 +2,8 @@ import { micro as m, raf as r } from '@esportsplus/tasks';
2
2
  import { Element as E } from './types';
3
3
 
4
4
 
5
- let prototype,
5
+ let getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor,
6
+ prototype,
6
7
  template = document.createElement('template'),
7
8
  t = document.createTextNode('');
8
9
 
@@ -18,15 +19,13 @@ const addEventListener = prototype.addEventListener;
18
19
 
19
20
  const removeEventListener = prototype.removeEventListener;
20
21
 
21
- const className = Object.getOwnPropertyDescriptor(prototype, 'className')!.set!;
22
+ const className = getOwnPropertyDescriptor(prototype, 'className')!.set!;
22
23
 
23
- const innerHTML = Object.getOwnPropertyDescriptor(prototype, 'innerHTML')!.set!;
24
+ const innerHTML = getOwnPropertyDescriptor(prototype, 'innerHTML')!.set!;
24
25
 
25
- const firstElementChild = Object.getOwnPropertyDescriptor(prototype, 'firstElementChild')!.get!;
26
+ const firstElementChild = getOwnPropertyDescriptor(prototype, 'firstElementChild')!.get!;
26
27
 
27
- const nextElementSibling = Object.getOwnPropertyDescriptor(prototype, 'nextElementSibling')!.get!;
28
-
29
- const prepend = prototype.prepend;
28
+ const nextElementSibling = getOwnPropertyDescriptor(prototype, 'nextElementSibling')!.get!;
30
29
 
31
30
  const removeAttribute = prototype.removeAttribute;
32
31
 
@@ -37,15 +36,17 @@ prototype = Node.prototype;
37
36
 
38
37
  const cloneNode = prototype.cloneNode;
39
38
 
40
- const firstChild = Object.getOwnPropertyDescriptor(prototype, 'firstChild')!.get!;
39
+ const firstChild = getOwnPropertyDescriptor(prototype, 'firstChild')!.get!;
40
+
41
+ const lastChild = getOwnPropertyDescriptor(prototype, 'lastChild')!.get!;
41
42
 
42
- const nextSibling = Object.getOwnPropertyDescriptor(prototype, 'nextSibling')!.get!;
43
+ const nextSibling = getOwnPropertyDescriptor(prototype, 'nextSibling')!.get!;
43
44
 
44
- const nodeValue = Object.getOwnPropertyDescriptor(prototype, 'nodeValue')!.set!;
45
+ const nodeValue = getOwnPropertyDescriptor(prototype, 'nodeValue')!.set!;
45
46
 
46
- const parentElement = Object.getOwnPropertyDescriptor(prototype, 'parentElement')!.get!;
47
+ const parentElement = getOwnPropertyDescriptor(prototype, 'parentElement')!.get!;
47
48
 
48
- const parentNode = Object.getOwnPropertyDescriptor(prototype, 'parentNode')!.get!;
49
+ const previousSibling = getOwnPropertyDescriptor(prototype, 'previousSibling')!.get!;
49
50
 
50
51
 
51
52
  const fragment = (html: string) => {
@@ -78,9 +79,10 @@ export {
78
79
  className, cloneNode,
79
80
  firstChild, firstElementChild, fragment,
80
81
  innerHTML,
82
+ lastChild,
81
83
  microtask,
82
84
  nextElementSibling, nextSibling, nodeValue,
83
- parentElement, parentNode, prepend,
85
+ parentElement, previousSibling,
84
86
  raf, removeAttribute, removeEventListener,
85
87
  setAttribute,
86
88
  text
package/build/slot.d.ts DELETED
@@ -1,21 +0,0 @@
1
- import { Element, Elements, HydrateResult } from './types.js';
2
- declare class Slot {
3
- marker: Element;
4
- nodes: Elements[];
5
- text: Element | null;
6
- constructor(marker: Element);
7
- get length(): number;
8
- set length(n: number);
9
- anchor(index?: number): Element;
10
- clear(): void;
11
- pop(): Elements[] | undefined;
12
- push(...groups: HydrateResult[]): number;
13
- render(input: unknown, state?: number): this;
14
- shift(): Elements[] | undefined;
15
- splice(start: number, stop?: number, ...groups: HydrateResult[]): Elements[];
16
- unshift(...groups: HydrateResult[]): number;
17
- }
18
- declare const ondisconnect: (element: Element, fn: VoidFunction) => void;
19
- declare const _default: (marker: Element, value: unknown) => Slot;
20
- export default _default;
21
- export { ondisconnect, Slot };
package/build/slot.js DELETED
@@ -1,200 +0,0 @@
1
- import { effect, root } from '@esportsplus/reactivity';
2
- import { isArray, isFunction, isInstanceOf, isObject } from '@esportsplus/utilities';
3
- import { RENDERABLE, RENDERABLE_REACTIVE } from './constants.js';
4
- import { hydrate } from './html/index.js';
5
- import { append, cloneNode, firstChild, fragment, microtask, nextSibling, 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, template = fragment('');
11
- function after(anchor, groups) {
12
- let n = groups.length;
13
- if (n === 0) {
14
- return [];
15
- }
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;
21
- }
22
- anchor.after(fragment);
23
- return elements;
24
- }
25
- function remove(groups) {
26
- for (let i = 0, n = groups.length; i < n; i++) {
27
- let group = groups[i];
28
- for (let j = 0, o = group.length; j < o; j++) {
29
- let item = group[j];
30
- if (CLEANUP_KEY in item) {
31
- cleanup.add(item[CLEANUP_KEY]);
32
- }
33
- item.remove();
34
- }
35
- }
36
- if (!scheduled && cleanup.length) {
37
- schedule();
38
- }
39
- return groups;
40
- }
41
- function render(elements, fragment, input, slot) {
42
- if (input === false || input == null || input === '') {
43
- return;
44
- }
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)) {
55
- for (let i = 0, n = input.length; i < n; i++) {
56
- render(elements, fragment, input[i]);
57
- }
58
- }
59
- else if (isObject(input) && RENDERABLE in input) {
60
- if (input[RENDERABLE] === RENDERABLE_REACTIVE) {
61
- let response = hydrate.reactive(input, slot);
62
- for (let i = 0, n = response.length; i < n; i++) {
63
- let { elements: e, fragment: f } = response[i];
64
- append.call(fragment, f);
65
- elements.push(e);
66
- }
67
- }
68
- else {
69
- let { elements: e, fragment: f } = hydrate.static(input);
70
- append.call(fragment, f);
71
- elements.push(e);
72
- }
73
- }
74
- else if (isInstanceOf(input, NodeList)) {
75
- let e = new Array(input.length), i = 0;
76
- for (let node = firstChild.call(input); node; node = nextSibling.call(node)) {
77
- e[i++] = node;
78
- }
79
- append.call(fragment, ...e);
80
- elements.push(e);
81
- }
82
- else if (isInstanceOf(input, Node)) {
83
- append.call(fragment, input);
84
- elements.push([input]);
85
- }
86
- }
87
- function schedule() {
88
- if (scheduled) {
89
- return;
90
- }
91
- scheduled = true;
92
- microtask.add(task);
93
- }
94
- function task() {
95
- let fn, fns;
96
- while (fns = cleanup.next()) {
97
- try {
98
- while (fn = fns.pop()) {
99
- fn();
100
- }
101
- }
102
- catch { }
103
- }
104
- scheduled = false;
105
- if (cleanup.length) {
106
- schedule();
107
- }
108
- }
109
- class Slot {
110
- marker;
111
- nodes;
112
- text = null;
113
- constructor(marker) {
114
- ondisconnect(marker, () => this.clear());
115
- this.marker = marker;
116
- this.nodes = [];
117
- }
118
- get length() {
119
- return this.nodes.length;
120
- }
121
- set length(n) {
122
- this.splice(n);
123
- }
124
- anchor(index = this.nodes.length - 1) {
125
- let nodes = this.nodes[index];
126
- return nodes ? nodes[nodes.length - 1] : this.marker;
127
- }
128
- clear() {
129
- remove(this.nodes);
130
- this.nodes.length = 0;
131
- this.text = null;
132
- }
133
- pop() {
134
- let group = this.nodes.pop();
135
- if (!group) {
136
- return undefined;
137
- }
138
- return remove([group]);
139
- }
140
- push(...groups) {
141
- return this.nodes.push(...after(this.anchor(), groups));
142
- }
143
- render(input, state = HYDRATING) {
144
- if (isFunction(input)) {
145
- ondisconnect(this.marker, effect(() => {
146
- let v = input();
147
- if (isFunction(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
- }
155
- else if (state === CONNECTED) {
156
- raf.add(() => {
157
- this.render(v, state);
158
- });
159
- }
160
- }));
161
- return this;
162
- }
163
- if (this.text && this.text.isConnected) {
164
- let type = typeof input;
165
- if (input == null || type !== 'object') {
166
- nodeValue.call(this.text, (type === 'number' || type === 'string') ? input : '');
167
- return this;
168
- }
169
- }
170
- this.clear();
171
- let fragment = cloneNode.call(template), nodes = [];
172
- render(nodes, fragment, input, this);
173
- this.marker.after(fragment);
174
- this.nodes = nodes;
175
- return this;
176
- }
177
- shift() {
178
- let group = this.nodes.shift();
179
- if (!group) {
180
- return undefined;
181
- }
182
- return remove([group]);
183
- }
184
- splice(start, stop = this.nodes.length, ...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)));
189
- }
190
- unshift(...groups) {
191
- return this.nodes.unshift(...after(this.marker, groups));
192
- }
193
- }
194
- const ondisconnect = (element, fn) => {
195
- (element[CLEANUP_KEY] ??= []).push(fn);
196
- };
197
- export default (marker, value) => {
198
- return new Slot(marker).render(value);
199
- };
200
- export { ondisconnect, Slot };