@symbiotejs/symbiote 3.3.8 → 3.3.9
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/CHANGELOG.md +18 -0
- package/README.md +30 -30
- package/core/itemizeProcessor-keyed.js +6 -34
- package/core/itemizeProcessor.js +45 -107
- package/core/itemizeSetup.js +88 -0
- package/package.json +5 -1
- package/types/core/itemizeProcessor-keyed.d.ts.map +1 -1
- package/types/core/itemizeProcessor.d.ts.map +1 -1
- package/types/core/itemizeSetup.d.ts +8 -0
- package/types/core/itemizeSetup.d.ts.map +1 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,23 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 3.3.9
|
|
4
|
+
|
|
5
|
+
### Improved
|
|
6
|
+
|
|
7
|
+
- **DRY itemize processors.** Extracted shared setup logic (element discovery, SSR hydration, class creation, template derivation, attribute cleanup) into `itemizeSetup.js`. Both `itemizeProcessor.js` and `itemizeProcessor-keyed.js` now use the same setup, eliminating code duplication.
|
|
8
|
+
|
|
9
|
+
- **Keyed processor SSR support.** `itemizeProcessor-keyed.js` now inherits all SSR hydration fixes: `clientSSR` detection, SSR tag adoption, `isoMode` on items, static template derivation, conditional child clearing, and `initPropFallback`.
|
|
10
|
+
|
|
11
|
+
### Fixed
|
|
12
|
+
|
|
13
|
+
- **Keyed processor: live HTMLCollection bug.** Fixed `animateOut` failing when removing multiple items by key — the live `HTMLCollection` shifted indices during removal. Elements are now snapshotted before removal.
|
|
14
|
+
|
|
15
|
+
## 3.3.8
|
|
16
|
+
|
|
17
|
+
### Fixed
|
|
18
|
+
|
|
19
|
+
- **SSR hydration: Itemize template derivation.** Dynamically added itemize items now use the original template (parsed from `fnCtx.constructor.template`) instead of SSR-expanded `innerHTML`. This preserves nested custom elements (e.g. icons) in new items added after hydration.
|
|
20
|
+
|
|
3
21
|
## 3.3.7
|
|
4
22
|
|
|
5
23
|
### Fixed
|
package/README.md
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
|
|
12
12
|
A lightweight, standards-first UI library built on Web Components. No virtual DOM, no compiler, no build step required — works directly in the browser. A bundler is recommended for production performance, but entirely optional. **~6kb** gzipped.
|
|
13
13
|
|
|
14
|
-
Symbiote.js gives you the convenience of a modern framework while staying close to the native platform — HTML, CSS, and DOM APIs. Components are real custom elements that work everywhere: in any framework, in plain HTML, or in a micro-frontend architecture.
|
|
14
|
+
Symbiote.js gives you the convenience of a modern framework while staying close to the native platform — HTML, CSS, and DOM APIs. Components are real custom elements that work everywhere: in any framework, in plain HTML, or in a micro-frontend architecture. And with **isomorphic mode**, the same component code works on the server and the client — server-rendered pages hydrate automatically, no diffing, no mismatch errors.
|
|
15
15
|
|
|
16
16
|
## What's new in 3.x
|
|
17
17
|
|
|
@@ -61,57 +61,57 @@ npm i @symbiotejs/symbiote
|
|
|
61
61
|
import Symbiote, { html, css } from '@symbiotejs/symbiote';
|
|
62
62
|
```
|
|
63
63
|
|
|
64
|
-
##
|
|
64
|
+
## Isomorphic Web Components
|
|
65
65
|
|
|
66
|
-
|
|
66
|
+
One component. Server-rendered or client-rendered — automatically. Set `isoMode = true` and the component figures it out: if server-rendered content exists, it hydrates; otherwise it renders from template. No conditional logic, no separate server/client versions:
|
|
67
67
|
|
|
68
68
|
```js
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
69
|
+
class MyComponent extends Symbiote {
|
|
70
|
+
isoMode = true;
|
|
71
|
+
count = 0;
|
|
72
|
+
increment() {
|
|
73
|
+
this.$.count++;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
73
76
|
|
|
74
|
-
|
|
75
|
-
|
|
77
|
+
MyComponent.template = html`
|
|
78
|
+
<h2>{{count}}</h2>
|
|
79
|
+
<button ${{onclick: 'increment'}}>Click me!</button>
|
|
80
|
+
`;
|
|
81
|
+
MyComponent.reg('my-component');
|
|
76
82
|
```
|
|
77
83
|
|
|
78
|
-
|
|
84
|
+
This exact code runs **everywhere** — SSR on the server, hydration on the client, or pure client rendering. No framework split, no `'use client'` directives, no hydration mismatch errors.
|
|
79
85
|
|
|
80
|
-
###
|
|
86
|
+
### SSR — one class, zero config
|
|
81
87
|
|
|
82
|
-
|
|
88
|
+
Server rendering doesn't need a virtual DOM, a reconciler, or framework-specific packages:
|
|
83
89
|
|
|
84
90
|
```js
|
|
85
91
|
import { SSR } from '@symbiotejs/symbiote/node/SSR.js';
|
|
86
92
|
|
|
87
|
-
await SSR.init();
|
|
88
|
-
await import('./my-app.js');
|
|
93
|
+
await SSR.init(); // patches globals with linkedom
|
|
94
|
+
await import('./my-app.js'); // components register normally
|
|
89
95
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
res.write('<!DOCTYPE html><html><body>');
|
|
93
|
-
for await (let chunk of SSR.renderToStream('my-app')) {
|
|
94
|
-
res.write(chunk);
|
|
95
|
-
}
|
|
96
|
-
res.end('</body></html>');
|
|
97
|
-
}).listen(3000);
|
|
96
|
+
let html = await SSR.processHtml('<my-app></my-app>');
|
|
97
|
+
SSR.destroy();
|
|
98
98
|
```
|
|
99
99
|
|
|
100
|
+
For large pages, stream HTML chunks with `SSR.renderToStream()` for faster TTFB. See [SSR docs](./docs/ssr.md) and [server setup recipes](./docs/ssr-server.md).
|
|
101
|
+
|
|
100
102
|
### How it compares
|
|
101
103
|
|
|
102
104
|
| | **Symbiote.js** | **Next.js (React)** | **Lit** (`@lit-labs/ssr`) |
|
|
103
|
-
|
|
104
|
-
| **
|
|
105
|
-
| **Hydration** |
|
|
106
|
-
| **Packages** | 1 module
|
|
105
|
+
|--|----------------|---------------------|----|
|
|
106
|
+
| **Isomorphic code** | Same code, `isoMode` auto-detects | Server Components vs Client Components split | Same code, but load-order constraints |
|
|
107
|
+
| **Hydration** | Binding-based — attaches to existing DOM, no diffing | `hydrateRoot()` — must produce identical output or errors | Requires `ssr-client` + hydrate support module |
|
|
108
|
+
| **Packages** | 1 module + `linkedom` peer dep | Full framework buy-in | 3 packages: `ssr`, `ssr-client`, `ssr-dom-shim` |
|
|
107
109
|
| **Streaming** | `renderToStream()` async generator | `renderToPipeableStream()` | Iterable `RenderResult` |
|
|
108
|
-
| **Mismatch handling** | Not needed — bindings attach to whatever DOM exists | Hard errors
|
|
109
|
-
| **Component code** | Same code, no changes | Server Components vs Client Components split | Same code, but load-order constraints |
|
|
110
|
+
| **Mismatch handling** | Not needed — bindings attach to whatever DOM exists | Hard errors if server/client output differs | N/A |
|
|
110
111
|
| **Template output** | Clean HTML with `bind=` attributes | HTML with framework markers | HTML with `<!--lit-part-->` comment markers |
|
|
111
|
-
| **Bundle impact** | Zero — SSR module is server-only | React runtime required on client | Zero — SSR packages are server-only |
|
|
112
112
|
| **Lock-in** | None — standard Web Components | Full framework commitment | Lit-specific, but Web Components |
|
|
113
113
|
|
|
114
|
-
**Key insight:**
|
|
114
|
+
**Key insight:** There are no hydration mismatches because there's no diffing. The server produces HTML with binding attributes. The client reads those attributes and adds reactivity. That's it.
|
|
115
115
|
|
|
116
116
|
## Core concepts
|
|
117
117
|
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import { DICT } from './dictionary.js';
|
|
2
1
|
import { animateOut } from './animateOut.js';
|
|
3
|
-
import {
|
|
2
|
+
import { setupItemize } from './itemizeSetup.js';
|
|
4
3
|
|
|
5
4
|
/**
|
|
6
5
|
* Optimized itemize template processor.
|
|
@@ -30,31 +29,7 @@ import { ownElements } from './ownElements.js';
|
|
|
30
29
|
* @param {T} fnCtx
|
|
31
30
|
*/
|
|
32
31
|
export function itemizeProcessor(fr, fnCtx) {
|
|
33
|
-
|
|
34
|
-
return !el.matches(`[${DICT.LIST_ATTR}] [${DICT.LIST_ATTR}]`);
|
|
35
|
-
}).forEach((el) => {
|
|
36
|
-
let itemTag = el.getAttribute(DICT.LIST_ITEM_TAG_ATTR);
|
|
37
|
-
let itemClass;
|
|
38
|
-
if (itemTag) {
|
|
39
|
-
itemClass = window.customElements.get(itemTag);
|
|
40
|
-
}
|
|
41
|
-
if (!itemClass) {
|
|
42
|
-
itemClass = class extends fnCtx.Symbiote {
|
|
43
|
-
constructor() {
|
|
44
|
-
super();
|
|
45
|
-
if (!itemTag) {
|
|
46
|
-
this.style.display = 'contents';
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
};
|
|
50
|
-
itemClass.template = el.querySelector('template')?.innerHTML || el.innerHTML;
|
|
51
|
-
itemClass.reg(itemTag);
|
|
52
|
-
}
|
|
53
|
-
while (el.firstChild) {
|
|
54
|
-
el.firstChild.remove();
|
|
55
|
-
}
|
|
56
|
-
let repeatDataKey = el.getAttribute(DICT.LIST_ATTR);
|
|
57
|
-
|
|
32
|
+
setupItemize(fr, fnCtx, ({ el, itemClass, repeatDataKey, clientSSR }) => {
|
|
58
33
|
/** @type {*[]} */
|
|
59
34
|
let prevData = [];
|
|
60
35
|
|
|
@@ -180,8 +155,9 @@ export function itemizeProcessor(fr, fnCtx) {
|
|
|
180
155
|
}
|
|
181
156
|
}
|
|
182
157
|
|
|
183
|
-
|
|
184
|
-
|
|
158
|
+
let removeEls = [...toRemove].map((key) => children[prevKeyToIdx.get(key)]);
|
|
159
|
+
for (let el of removeEls) {
|
|
160
|
+
animateOut(el);
|
|
185
161
|
}
|
|
186
162
|
|
|
187
163
|
for (let i = 0; i < newChildren.length; i++) {
|
|
@@ -226,10 +202,6 @@ export function itemizeProcessor(fr, fnCtx) {
|
|
|
226
202
|
}
|
|
227
203
|
|
|
228
204
|
prevData = items;
|
|
229
|
-
});
|
|
230
|
-
if (!globalThis.__SYMBIOTE_SSR) {
|
|
231
|
-
el.removeAttribute(DICT.LIST_ATTR);
|
|
232
|
-
el.removeAttribute(DICT.LIST_ITEM_TAG_ATTR);
|
|
233
|
-
}
|
|
205
|
+
}, !clientSSR);
|
|
234
206
|
});
|
|
235
207
|
}
|
package/core/itemizeProcessor.js
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
import { DICT } from './dictionary.js';
|
|
2
1
|
import { animateOut } from './animateOut.js';
|
|
3
|
-
import {
|
|
4
|
-
import { initPropFallback } from './initPropFallback.js';
|
|
2
|
+
import { setupItemize } from './itemizeSetup.js';
|
|
5
3
|
|
|
6
4
|
/**
|
|
7
5
|
* @template {import('./Symbiote.js').Symbiote} T
|
|
@@ -9,118 +7,58 @@ import { initPropFallback } from './initPropFallback.js';
|
|
|
9
7
|
* @param {T} fnCtx
|
|
10
8
|
*/
|
|
11
9
|
export function itemizeProcessor(fr, fnCtx) {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
return !el.matches(`[${DICT.LIST_ATTR}] [${DICT.LIST_ATTR}]`);
|
|
16
|
-
}).forEach((el) => {
|
|
17
|
-
let itemTag = el.getAttribute(DICT.LIST_ITEM_TAG_ATTR);
|
|
18
|
-
let repeatDataKey = el.getAttribute(DICT.LIST_ATTR);
|
|
19
|
-
let itemClass;
|
|
20
|
-
if (itemTag) {
|
|
21
|
-
itemClass = window.customElements.get(itemTag);
|
|
22
|
-
}
|
|
23
|
-
if (!itemClass) {
|
|
24
|
-
// During hydration, adopt existing SSR item tag and derive template
|
|
25
|
-
if (clientSSR && el.children.length > 0) {
|
|
26
|
-
let ssrTag = el.children[0].localName;
|
|
27
|
-
itemClass = window.customElements.get(ssrTag);
|
|
28
|
-
if (!itemClass) {
|
|
29
|
-
itemClass = class extends fnCtx.Symbiote {
|
|
30
|
-
constructor() {
|
|
31
|
-
super();
|
|
32
|
-
this.isoMode = true;
|
|
33
|
-
if (!itemTag) {
|
|
34
|
-
this.style.display = 'contents';
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
};
|
|
38
|
-
let tpl = document.createElement('template');
|
|
39
|
-
// @ts-expect-error
|
|
40
|
-
tpl.innerHTML = fnCtx.constructor.template;
|
|
41
|
-
let staticEl = tpl.content.querySelector(
|
|
42
|
-
`[${DICT.LIST_ATTR}="${repeatDataKey}"]`
|
|
43
|
-
);
|
|
44
|
-
itemClass.template = staticEl?.querySelector('template')?.innerHTML
|
|
45
|
-
|| el.children[0].innerHTML;
|
|
46
|
-
itemClass.reg(ssrTag);
|
|
47
|
-
}
|
|
48
|
-
} else {
|
|
49
|
-
itemClass = class extends fnCtx.Symbiote {
|
|
50
|
-
constructor() {
|
|
51
|
-
super();
|
|
52
|
-
if (!itemTag) {
|
|
53
|
-
this.style.display = 'contents';
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
};
|
|
57
|
-
itemClass.template = el.querySelector('template')?.innerHTML || el.innerHTML;
|
|
58
|
-
itemClass.reg(itemTag);
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
if (!clientSSR) {
|
|
10
|
+
setupItemize(fr, fnCtx, ({ el, itemClass, repeatDataKey, clientSSR }) => {
|
|
11
|
+
fnCtx.sub(repeatDataKey, (data) => {
|
|
12
|
+
if (!data) {
|
|
62
13
|
while (el.firstChild) {
|
|
63
14
|
el.firstChild.remove();
|
|
64
15
|
}
|
|
16
|
+
return;
|
|
65
17
|
}
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
return;
|
|
75
|
-
}
|
|
76
|
-
/** @type {*[]} */
|
|
77
|
-
let currentList = [...el.children];
|
|
78
|
-
let fragment;
|
|
79
|
-
let fillItems = (/** @type {*[]} */ items) => {
|
|
80
|
-
items.forEach((item, idx) => {
|
|
81
|
-
if (currentList[idx]) {
|
|
82
|
-
if (currentList[idx].set$) {
|
|
83
|
-
currentList[idx].set$(item);
|
|
84
|
-
} else {
|
|
85
|
-
for (let k in item) {
|
|
86
|
-
currentList[idx][k] = item[k];
|
|
87
|
-
}
|
|
88
|
-
}
|
|
18
|
+
/** @type {*[]} */
|
|
19
|
+
let currentList = [...el.children];
|
|
20
|
+
let fragment;
|
|
21
|
+
let fillItems = (/** @type {*[]} */ items) => {
|
|
22
|
+
items.forEach((item, idx) => {
|
|
23
|
+
if (currentList[idx]) {
|
|
24
|
+
if (currentList[idx].set$) {
|
|
25
|
+
currentList[idx].set$(item);
|
|
89
26
|
} else {
|
|
90
|
-
|
|
91
|
-
|
|
27
|
+
for (let k in item) {
|
|
28
|
+
currentList[idx][k] = item[k];
|
|
92
29
|
}
|
|
93
|
-
let repeatItem = new itemClass();
|
|
94
|
-
Object.assign((repeatItem?.init$ || repeatItem), item);
|
|
95
|
-
fragment.appendChild(repeatItem);
|
|
96
30
|
}
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
if (data.constructor === Array) {
|
|
105
|
-
fillItems(data);
|
|
106
|
-
} else if (data.constructor === Object) {
|
|
107
|
-
let items = [];
|
|
108
|
-
for (let itemKey in data) {
|
|
109
|
-
let init = data[itemKey];
|
|
110
|
-
Object.defineProperty(init, '_KEY_', {
|
|
111
|
-
value: itemKey,
|
|
112
|
-
enumerable: true,
|
|
113
|
-
});
|
|
114
|
-
items.push(init);
|
|
31
|
+
} else {
|
|
32
|
+
if (!fragment) {
|
|
33
|
+
fragment = document.createDocumentFragment();
|
|
34
|
+
}
|
|
35
|
+
let repeatItem = new itemClass();
|
|
36
|
+
Object.assign((repeatItem?.init$ || repeatItem), item);
|
|
37
|
+
fragment.appendChild(repeatItem);
|
|
115
38
|
}
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
39
|
+
});
|
|
40
|
+
fragment && el.appendChild(fragment);
|
|
41
|
+
let oversize = currentList.slice(items.length, currentList.length);
|
|
42
|
+
for (let exItm of oversize) {
|
|
43
|
+
animateOut(exItm);
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
if (data.constructor === Array) {
|
|
47
|
+
fillItems(data);
|
|
48
|
+
} else if (data.constructor === Object) {
|
|
49
|
+
let items = [];
|
|
50
|
+
for (let itemKey in data) {
|
|
51
|
+
let init = data[itemKey];
|
|
52
|
+
Object.defineProperty(init, '_KEY_', {
|
|
53
|
+
value: itemKey,
|
|
54
|
+
enumerable: true,
|
|
55
|
+
});
|
|
56
|
+
items.push(init);
|
|
119
57
|
}
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
el.removeAttribute(DICT.LIST_ITEM_TAG_ATTR);
|
|
58
|
+
fillItems(items);
|
|
59
|
+
} else {
|
|
60
|
+
console.warn(`[Symbiote] <${fnCtx.localName}>: itemize data must be Array or Object, got ${typeof data}:`, data);
|
|
124
61
|
}
|
|
125
|
-
});
|
|
62
|
+
}, !clientSSR);
|
|
63
|
+
});
|
|
126
64
|
}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { DICT } from './dictionary.js';
|
|
2
|
+
import { ownElements } from './ownElements.js';
|
|
3
|
+
import { initPropFallback } from './initPropFallback.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @typedef {Object} ItemizeDescriptor
|
|
7
|
+
* @property {Element} el
|
|
8
|
+
* @property {*} itemClass
|
|
9
|
+
* @property {string} repeatDataKey
|
|
10
|
+
* @property {boolean} clientSSR
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Shared setup for itemize processors.
|
|
15
|
+
* Handles element discovery, class creation, SSR hydration, template derivation,
|
|
16
|
+
* child clearing, initPropFallback, and attribute cleanup.
|
|
17
|
+
*
|
|
18
|
+
* @template {import('./Symbiote.js').Symbiote} T
|
|
19
|
+
* @param {DocumentFragment} fr
|
|
20
|
+
* @param {T} fnCtx
|
|
21
|
+
* @param {(desc: ItemizeDescriptor) => void} handler
|
|
22
|
+
*/
|
|
23
|
+
export function setupItemize(fr, fnCtx, handler) {
|
|
24
|
+
let clientSSR = fnCtx.ssrMode && !globalThis.__SYMBIOTE_SSR;
|
|
25
|
+
|
|
26
|
+
ownElements(fr, `[${DICT.LIST_ATTR}]`).filter((el) => {
|
|
27
|
+
return !el.matches(`[${DICT.LIST_ATTR}] [${DICT.LIST_ATTR}]`);
|
|
28
|
+
}).forEach((el) => {
|
|
29
|
+
let itemTag = el.getAttribute(DICT.LIST_ITEM_TAG_ATTR);
|
|
30
|
+
let repeatDataKey = el.getAttribute(DICT.LIST_ATTR);
|
|
31
|
+
let itemClass;
|
|
32
|
+
if (itemTag) {
|
|
33
|
+
itemClass = window.customElements.get(itemTag);
|
|
34
|
+
}
|
|
35
|
+
if (!itemClass) {
|
|
36
|
+
if (clientSSR && el.children.length > 0) {
|
|
37
|
+
let ssrTag = el.children[0].localName;
|
|
38
|
+
itemClass = window.customElements.get(ssrTag);
|
|
39
|
+
if (!itemClass) {
|
|
40
|
+
itemClass = class extends fnCtx.Symbiote {
|
|
41
|
+
constructor() {
|
|
42
|
+
super();
|
|
43
|
+
this.isoMode = true;
|
|
44
|
+
if (!itemTag) {
|
|
45
|
+
this.style.display = 'contents';
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
let tpl = document.createElement('template');
|
|
50
|
+
// @ts-expect-error
|
|
51
|
+
tpl.innerHTML = fnCtx.constructor.template;
|
|
52
|
+
let staticEl = tpl.content.querySelector(
|
|
53
|
+
`[${DICT.LIST_ATTR}="${repeatDataKey}"]`
|
|
54
|
+
);
|
|
55
|
+
itemClass.template = staticEl?.querySelector('template')?.innerHTML
|
|
56
|
+
|| el.children[0].innerHTML;
|
|
57
|
+
itemClass.reg(ssrTag);
|
|
58
|
+
}
|
|
59
|
+
} else {
|
|
60
|
+
itemClass = class extends fnCtx.Symbiote {
|
|
61
|
+
constructor() {
|
|
62
|
+
super();
|
|
63
|
+
if (!itemTag) {
|
|
64
|
+
this.style.display = 'contents';
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
itemClass.template = el.querySelector('template')?.innerHTML || el.innerHTML;
|
|
69
|
+
itemClass.reg(itemTag);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
if (!clientSSR) {
|
|
73
|
+
while (el.firstChild) {
|
|
74
|
+
el.firstChild.remove();
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
if (!fnCtx.has(repeatDataKey) && fnCtx.allowTemplateInits) {
|
|
78
|
+
initPropFallback(fnCtx, repeatDataKey);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
handler({ el, itemClass, repeatDataKey, clientSSR });
|
|
82
|
+
|
|
83
|
+
if (!globalThis.__SYMBIOTE_SSR) {
|
|
84
|
+
el.removeAttribute(DICT.LIST_ATTR);
|
|
85
|
+
el.removeAttribute(DICT.LIST_ITEM_TAG_ATTR);
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"type": "module",
|
|
3
3
|
"name": "@symbiotejs/symbiote",
|
|
4
|
-
"version": "3.3.
|
|
4
|
+
"version": "3.3.9",
|
|
5
5
|
"description": "Symbiote.js - zero-dependency close-to-platform frontend library to build super-powered web components",
|
|
6
6
|
"author": "team@rnd-pro.com",
|
|
7
7
|
"license": "MIT",
|
|
@@ -87,6 +87,10 @@
|
|
|
87
87
|
"types": "./types/core/itemizeProcessor.d.ts",
|
|
88
88
|
"default": "./core/itemizeProcessor.js"
|
|
89
89
|
},
|
|
90
|
+
"./core/itemizeSetup.js": {
|
|
91
|
+
"types": "./types/core/itemizeSetup.d.ts",
|
|
92
|
+
"default": "./core/itemizeSetup.js"
|
|
93
|
+
},
|
|
90
94
|
"./core/ownElements.js": {
|
|
91
95
|
"types": "./types/core/ownElements.d.ts",
|
|
92
96
|
"default": "./core/ownElements.js"
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"itemizeProcessor-keyed.d.ts","sourceRoot":"","sources":["../../core/itemizeProcessor-keyed.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"itemizeProcessor-keyed.d.ts","sourceRoot":"","sources":["../../core/itemizeProcessor-keyed.js"],"names":[],"mappings":"AA8BA,iCAJgD,CAAC,SAApC,qCAAkC,MACpC,gBAAgB,SAChB,CAAC,QAkLX"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"itemizeProcessor.d.ts","sourceRoot":"","sources":["../../core/itemizeProcessor.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"itemizeProcessor.d.ts","sourceRoot":"","sources":["../../core/itemizeProcessor.js"],"names":[],"mappings":"AAQA,iCAJgD,CAAC,SAApC,qCAAkC,MACpC,gBAAgB,SAChB,CAAC,QAyDX"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export function setupItemize<T extends import("./Symbiote.js").Symbiote<any>>(fr: DocumentFragment, fnCtx: T, handler: (desc: ItemizeDescriptor) => void): void;
|
|
2
|
+
export type ItemizeDescriptor = {
|
|
3
|
+
el: Element;
|
|
4
|
+
itemClass: any;
|
|
5
|
+
repeatDataKey: string;
|
|
6
|
+
clientSSR: boolean;
|
|
7
|
+
};
|
|
8
|
+
//# sourceMappingURL=itemizeSetup.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"itemizeSetup.d.ts","sourceRoot":"","sources":["../../core/itemizeSetup.js"],"names":[],"mappings":"AAsBA,6BALgD,CAAC,SAApC,qCAAkC,MACpC,gBAAgB,SAChB,CAAC,WACD,CAAC,IAAI,EAAE,iBAAiB,KAAK,IAAI,QAmE3C;;QAjFa,OAAO;eACP,GAAC;mBACD,MAAM;eACN,OAAO"}
|