@symbiotejs/symbiote 3.4.3 → 3.4.5

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/AI_REFERENCE.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # Symbiote.js — AI Context Reference (v3.x)
2
2
 
3
3
  > **Purpose**: Authoritative reference for AI code assistants. All information is derived from source code analysis of [symbiote.js](https://github.com/symbiotejs/symbiote.js).
4
- > Current version: **3.2.0**. Zero dependencies. ~6 KB gzip.
4
+ > Current version: **3.4.3**. Zero dependencies. ~6.3 KB brotli / ~7 KB gzip.
5
5
 
6
6
  ---
7
7
 
package/CHANGELOG.md CHANGED
@@ -1,5 +1,19 @@
1
1
  # Changelog
2
2
 
3
+ ## 3.4.5
4
+
5
+ ### Fixed
6
+
7
+ - **PubSub: computed properties with cross-context deps no longer depend on import order.** When a computed property declared `deps: ['CTX/prop']` and the target context wasn't registered yet, the subscription was silently skipped. Now deferred deps are stored in `PubSub.pendingDeps` and automatically resolved when `registerCtx()` is called.
8
+
9
+ ## 3.4.4
10
+
11
+ ### Fixed
12
+
13
+ - **SSR: `isVirtual` components.** `renderToString` and `renderToStream` now detect `isVirtual` elements and serialize the replacement template nodes instead of the detached custom element wrapper. Previously, virtual components produced an empty `<tag-name></tag-name>` in SSR output.
14
+
15
+ - **SSR: `allowCustomTemplate` with `use-template` attribute.** `DocumentFragment` detection in `render()` used `constructor === DocumentFragment`, which fails in linkedom where `template.content.cloneNode()` returns a fragment with a different internal constructor. Changed to `nodeType === 11` — spec-correct and works in both browser and linkedom. Previously, custom templates were silently ignored during SSR.
16
+
3
17
  ## 3.4.3
4
18
 
5
19
  ### Fixed
package/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  [![Tests](https://github.com/symbiotejs/symbiote.js/actions/workflows/tests.yml/badge.svg)](https://github.com/symbiotejs/symbiote.js/actions/workflows/tests.yml)
2
2
  [![npm version](https://img.shields.io/npm/v/@symbiotejs/symbiote)](https://www.npmjs.com/package/@symbiotejs/symbiote)
3
3
  [![npm downloads](https://img.shields.io/npm/dm/@symbiotejs/symbiote)](https://www.npmjs.com/package/@symbiotejs/symbiote)
4
- ![bundle size](https://img.shields.io/badge/minzip-6.5_kb-blue)
4
+ ![bundle size](https://img.shields.io/badge/brotli-6.3_kb-blue)
5
5
  ![types](https://img.shields.io/badge/types-JSDoc+d.ts-blue)
6
6
  ![license](https://img.shields.io/badge/license-MIT-green)
7
7
 
@@ -9,7 +9,7 @@
9
9
 
10
10
  <img src="https://rnd-pro.com/svg/symbiote/index.svg" width="200" alt="Symbiote.js">
11
11
 
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.
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. **~6.3kb** brotli / **~7kb** gzip.
13
13
 
14
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
 
@@ -344,11 +344,12 @@ CSS values are parsed automatically — quoted strings become strings, numbers b
344
344
 
345
345
  | Library | Minified | Gzip | Brotli |
346
346
  |---------|----------|------|--------|
347
- | **Symbiote.js** (full) | 18.4 kb | 6.6 kb | **5.9 kb** |
348
- | **Lit** (LitElement + html + css) | 15.1 kb | 5.8 kb | **5.3 kb** |
349
- | **React + ReactDOM** | 188.8 kb | 58.8 kb | **50.6 kb** |
347
+ | **Symbiote.js** (core) | 19.8 kb | 6.9 kb | **6.3 kb** |
348
+ | **Symbiote.js** (full, with AppRouter) | 24.0 kb | 8.3 kb | **7.5 kb** |
349
+ | **Lit** 3.3 | 15.5 kb | 6.0 kb | **~5.1 kb** |
350
+ | **React 19 + ReactDOM** | ~186 kb | ~59 kb | **~50 kb** |
350
351
 
351
- Symbiote and Lit have similar base sizes, but Symbiote's **5.9 kb** includes more powerful features: global state management, lists (itemize API), exit animations, computed properties etc. Lit needs additional packages for comparable features. React is **~10× larger** before adding a router, state manager, or SSR framework.
352
+ Symbiote and Lit have similar base sizes, but Symbiote's **6.3 kb** core includes more built-in features: global state management, lists (itemize API), exit animations, computed properties etc. Lit needs additional packages for comparable features. React is **~8× larger** before adding a router, state manager, or SSR framework.
352
353
 
353
354
  ## Browser support
354
355
 
package/core/PubSub.js CHANGED
@@ -120,10 +120,24 @@ export class PubSub {
120
120
  let extCtx = PubSub.getCtx(ctxName, false);
121
121
 
122
122
  if (!extCtx) {
123
- console.warn(
124
- `[Symbiote] PubSub: external dep context "${ctxName}" not found for computed "${compProp}".\n`
125
- + `Available contexts: [${[...PubSub.globalStore.keys()].map(String).join(', ')}]`
126
- );
123
+ // Defer: will resolve when the context is registered
124
+ if (!PubSub.pendingDeps.has(ctxName)) {
125
+ PubSub.pendingDeps.set(ctxName, []);
126
+ }
127
+ PubSub.pendingDeps.get(ctxName).push(() => {
128
+ let resolvedCtx = PubSub.getCtx(ctxName, false);
129
+ if (!resolvedCtx) return;
130
+ let sub = resolvedCtx.sub(propName, () => {
131
+ this.#recalcComputed(compProp);
132
+ }, false);
133
+ if (sub) {
134
+ if (!this.#externalSubs[compProp]) {
135
+ this.#externalSubs[compProp] = [];
136
+ }
137
+ this.#externalSubs[compProp].push(sub);
138
+ }
139
+ this.#recalcComputed(compProp);
140
+ });
127
141
  continue;
128
142
  }
129
143
 
@@ -366,6 +380,15 @@ export class PubSub {
366
380
  data = new PubSub(schema);
367
381
  data.uid = uid;
368
382
  PubSub.globalStore.set(uid, data);
383
+
384
+ // Resolve deferred external deps waiting for this context:
385
+ let pending = PubSub.pendingDeps.get(uid);
386
+ if (pending) {
387
+ PubSub.pendingDeps.delete(uid);
388
+ for (let resolve of pending) {
389
+ resolve();
390
+ }
391
+ }
369
392
  }
370
393
  return data;
371
394
  }
@@ -391,6 +414,9 @@ export class PubSub {
391
414
  /** @type {Map<String | Symbol, PubSub>} */
392
415
  PubSub.globalStore = globalThis.__SYMBIOTE_PUBSUB_STORE || (globalThis.__SYMBIOTE_PUBSUB_STORE = new Map());
393
416
 
417
+ /** @type {Map<String | Symbol, Array<Function>>} */
418
+ PubSub.pendingDeps = new Map();
419
+
394
420
  /** @type {Boolean} */
395
421
  PubSub.devMode = false;
396
422
 
package/core/Symbiote.js CHANGED
@@ -120,8 +120,9 @@ export class Symbiote extends HTMLElement {
120
120
  this.#super.__tpl = document.createElement('template');
121
121
  this.#super.__tpl.innerHTML = trustedHTML.createHTML(this.#super.template);
122
122
  }
123
- if (template?.constructor === DocumentFragment) {
124
- fr = template;
123
+ // @ts-expect-error - nodeType works for both DOM nodes and linkedom fragments
124
+ if (template?.nodeType === 11) {
125
+ fr = /** @type {DocumentFragment} */ (template);
125
126
  } else if (template?.constructor === String) {
126
127
  let tpl = document.createElement('template');
127
128
  tpl.innerHTML = trustedHTML.createHTML(template);
package/node/SSR.js CHANGED
@@ -410,8 +410,19 @@ export class SSR {
410
410
  el.setAttribute(key, String(val));
411
411
  }
412
412
  SSR.#doc.body.appendChild(el);
413
- let html = serializeElement(el, new Set(), options.nonce);
414
- el.remove();
413
+ let html;
414
+ // isVirtual replaces the element with its template fragment:
415
+ if (/** @type {any} */ (el).isVirtual) {
416
+ let emittedStyles = new Set();
417
+ html = '';
418
+ for (let child of SSR.#doc.body.childNodes) {
419
+ html += serializeNode(child, emittedStyles, options.nonce);
420
+ }
421
+ } else {
422
+ html = serializeElement(el, new Set(), options.nonce);
423
+ el.remove();
424
+ }
425
+ SSR.#doc.body.innerHTML = '';
415
426
  return html;
416
427
  }
417
428
 
@@ -433,8 +444,17 @@ export class SSR {
433
444
  el.setAttribute(key, String(val));
434
445
  }
435
446
  SSR.#doc.body.appendChild(el);
436
- yield* streamElement(el, new Set(), options.nonce);
437
- el.remove();
447
+ // isVirtual replaces the element with its template fragment:
448
+ if (/** @type {any} */ (el).isVirtual) {
449
+ let emittedStyles = new Set();
450
+ for (let child of SSR.#doc.body.childNodes) {
451
+ yield* streamNode(child, emittedStyles, options.nonce);
452
+ }
453
+ } else {
454
+ yield* streamElement(el, new Set(), options.nonce);
455
+ el.remove();
456
+ }
457
+ SSR.#doc.body.innerHTML = '';
438
458
  }
439
459
  }
440
460
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "@symbiotejs/symbiote",
4
- "version": "3.4.3",
4
+ "version": "3.4.5",
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",
@@ -23,6 +23,7 @@ export class PubSub<T extends Record<string, unknown>> {
23
23
  }
24
24
  export namespace PubSub {
25
25
  let globalStore: Map<string | Symbol, PubSub<any>>;
26
+ let pendingDeps: Map<string | Symbol, Array<Function>>;
26
27
  let devMode: boolean;
27
28
  }
28
29
  export default PubSub;
@@ -1 +1 @@
1
- {"version":3,"file":"PubSub.d.ts","sourceRoot":"","sources":["../../core/PubSub.js"],"names":[],"mappings":"AAgBA,oBADwC,CAAC,SAA1B,MAAM,CAAC,MAAM,EAAE,OAAO,CAAE;IA2DrC,oDAFW,GAAC,kBAKX;IA0RD,mBALuC,CAAC,SAA1B,MAAM,CAAC,MAAM,EAAE,OAAO,CAAE,UAC3B,CAAC,QACD,SAAS,MAAM,GACb,MAAM,CAAC,CAAC,CAAC,CAarB;IAGD,sBADY,SAAS,MAAM,QAG1B;IAOD,mBAJW,SAAS,MAAM,iCASzB;IAzUD,oBADY,CAAC,EAWZ;IARG,WAA6B;IAO/B,aADW,MAAM,CAAC,MAAM,CAAC,EAAE,GAAG,CAAC,CAAC,GAAG,EAAC,OAAO,KAAK,IAAI,CAAC,CAAC,CAChB;IAwHxC,WADY,MAAM,CAAC,OAqClB;IAzBK,sBAAuB;IA4B7B,uBAEC;IAOD,uBAHW,OAAO,2BASjB;IAMD,UAHW,MAAM,CAAC,OACP,OAAO,QAqBjB;IAGD,aADc,CAAC,CAed;IAGD,iBADY,CAAC,QAKZ;IAGD,aADY,MAAM,CAAC,kBAoBlB;IAOD,UAJW,MAAM,CAAC,YACP,CAAC,GAAG,EAAE,OAAO,KAAK,IAAI;;wBAAhB,OAAO,KAAK,IAAI;MAwBhC;IAKD,aAFW,SAAS,MAAM,EAIzB;IAED,WANW,SAAS,MAAM,CAQzB;;CAqCF;;qBAEU,GAAG,CAAC,SAAS,MAAM,cAAS"}
1
+ {"version":3,"file":"PubSub.d.ts","sourceRoot":"","sources":["../../core/PubSub.js"],"names":[],"mappings":"AAgBA,oBADwC,CAAC,SAA1B,MAAM,CAAC,MAAM,EAAE,OAAO,CAAE;IA2DrC,oDAFW,GAAC,kBAKX;IAwSD,mBALuC,CAAC,SAA1B,MAAM,CAAC,MAAM,EAAE,OAAO,CAAE,UAC3B,CAAC,QACD,SAAS,MAAM,GACb,MAAM,CAAC,CAAC,CAAC,CAsBrB;IAGD,sBADY,SAAS,MAAM,QAG1B;IAOD,mBAJW,SAAS,MAAM,iCASzB;IAhWD,oBADY,CAAC,EAWZ;IARG,WAA6B;IAO/B,aADW,MAAM,CAAC,MAAM,CAAC,EAAE,GAAG,CAAC,CAAC,GAAG,EAAC,OAAO,KAAK,IAAI,CAAC,CAAC,CAChB;IAsIxC,WADY,MAAM,CAAC,OAqClB;IAzBK,sBAAuB;IA4B7B,uBAEC;IAOD,uBAHW,OAAO,2BASjB;IAMD,UAHW,MAAM,CAAC,OACP,OAAO,QAqBjB;IAGD,aADc,CAAC,CAed;IAGD,iBADY,CAAC,QAKZ;IAGD,aADY,MAAM,CAAC,kBAoBlB;IAOD,UAJW,MAAM,CAAC,YACP,CAAC,GAAG,EAAE,OAAO,KAAK,IAAI;;wBAAhB,OAAO,KAAK,IAAI;MAwBhC;IAKD,aAFW,SAAS,MAAM,EAIzB;IAED,WANW,SAAS,MAAM,CAQzB;;CA8CF;;qBAEU,GAAG,CAAC,SAAS,MAAM,cAAS;qBAG5B,GAAG,CAAC,SAAS,MAAM,EAAE,KAAK,UAAU,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"Symbiote.d.ts","sourceRoot":"","sources":["../../core/Symbiote.js"],"names":[],"mappings":";;AAmBA,sBADc,CAAC;IAuBb,cADW,mBAAmB,CACjB;IAGb,sCAAwB;IAExB,iCAGC;IAED,8BAEC;IAkBD,wBAAgB;IAyJhB,+BAJwB,CAAC,SAAZ,aAAU,uBAEZ,CAAC;;;MAuCX;IAmPD,qCAA+B;IAoC/B,iDAFa,OAAO,QAAQ,CAqB3B;IAED,wBAKC;IAGD;;aAOC;IAsHD,6BADY,SAAS,aAAa,QAOjC;IAGD,+BADY,SAAS,aAAa,QAOjC;IAGD,8BADY,SAAS,aAAa,EAIjC;IAGD,gCADY,SAAS,aAAa,EAIjC;IAnjBD,cA6BC;IApID,gCAEC;IAED,qBAAiB;IACjB,uBAAmB;IAiBnB,kBAHW,SAAS,gBAAgB,0BAkFnC;IAnDG,aAAiD;IAwDnD,OADW,CAAC,CACoB;IAEhC;;MAAmC;IAEnC,oBADW,GAAG,CAAC,CAAC,EAAE,EAAE,gBAAgB,gBAAW,EAAE,KAAK,eAAU,KAAK,IAAI,CAAC,CACvC;IAEnC;;MAA8B;IAC9B,kBAAwB;IAExB,qBAAwB;IAExB,sBAAyB;IAEzB,wBAA0B;IAE1B,0BAA6B;IAI7B,iBAAoB;IAEpB,6BAAgC;IAEhC,mBAAsB;IAEtB,4BAA8B;IAIhC,yBAEC;IAGD,sBASC;IAGD,4BAKC;IAGD,6BAEC;IAoDD,IALuB,CAAC,SAAX,MAAO,CAAE,QACX,CAAC,WACD,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,IAAI,wBAmB/B;IAGD,2BAGC;IAGD,uBAGC;IAQD,IALuB,CAAC,SAAX,MAAO,CAAE,qBAEX,CAAC,CAAC,CAAC,CAAC,2BAMd;IAMD,UAHW,OAAO,CAAC,CAAC,CAAC,2BAOpB;IAGD,SADc,CAAC,CA2Bd;IAMD,YAHW,OAAO,CAAC,CAAC,CAAC,mCAcpB;IAED,8BAgBC;IAdG,4CASE;IAwFF,0BAAwC;IAwB1C,uBAAyB;IAG3B,0BAEC;IAED,wBAAoB;IAUpB,yBAAuB;IACvB,6BA0BC;IA6CD,oEAeC;IAMD,yDAoBC;IAYD,0BAME;IAMF,0CAFW,GAAG,QAmBb;IAED,yBAGC;IAOD,8EAmBC;;CA+BF;;mBAltBkB,aAAa;qBACX,iBAAiB;2BACX,iBAAiB"}
1
+ {"version":3,"file":"Symbiote.d.ts","sourceRoot":"","sources":["../../core/Symbiote.js"],"names":[],"mappings":";;AAmBA,sBADc,CAAC;IAuBb,cADW,mBAAmB,CACjB;IAGb,sCAAwB;IAExB,iCAGC;IAED,8BAEC;IAkBD,wBAAgB;IA0JhB,+BAJwB,CAAC,SAAZ,aAAU,uBAEZ,CAAC;;;MAuCX;IAmPD,qCAA+B;IAoC/B,iDAFa,OAAO,QAAQ,CAqB3B;IAED,wBAKC;IAGD;;aAOC;IAsHD,6BADY,SAAS,aAAa,QAOjC;IAGD,+BADY,SAAS,aAAa,QAOjC;IAGD,8BADY,SAAS,aAAa,EAIjC;IAGD,gCADY,SAAS,aAAa,EAIjC;IAnjBD,cA6BC;IArID,gCAEC;IAED,qBAAiB;IACjB,uBAAmB;IAiBnB,kBAHW,SAAS,gBAAgB,0BAmFnC;IApDG,aAAiD;IAyDnD,OADW,CAAC,CACoB;IAEhC;;MAAmC;IAEnC,oBADW,GAAG,CAAC,CAAC,EAAE,EAAE,gBAAgB,gBAAW,EAAE,KAAK,eAAU,KAAK,IAAI,CAAC,CACvC;IAEnC;;MAA8B;IAC9B,kBAAwB;IAExB,qBAAwB;IAExB,sBAAyB;IAEzB,wBAA0B;IAE1B,0BAA6B;IAI7B,iBAAoB;IAEpB,6BAAgC;IAEhC,mBAAsB;IAEtB,4BAA8B;IAIhC,yBAEC;IAGD,sBASC;IAGD,4BAKC;IAGD,6BAEC;IAoDD,IALuB,CAAC,SAAX,MAAO,CAAE,QACX,CAAC,WACD,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,IAAI,wBAmB/B;IAGD,2BAGC;IAGD,uBAGC;IAQD,IALuB,CAAC,SAAX,MAAO,CAAE,qBAEX,CAAC,CAAC,CAAC,CAAC,2BAMd;IAMD,UAHW,OAAO,CAAC,CAAC,CAAC,2BAOpB;IAGD,SADc,CAAC,CA2Bd;IAMD,YAHW,OAAO,CAAC,CAAC,CAAC,mCAcpB;IAED,8BAgBC;IAdG,4CASE;IAwFF,0BAAwC;IAwB1C,uBAAyB;IAG3B,0BAEC;IAED,wBAAoB;IAUpB,yBAAuB;IACvB,6BA0BC;IA6CD,oEAeC;IAMD,yDAoBC;IAYD,0BAME;IAMF,0CAFW,GAAG,QAmBb;IAED,yBAGC;IAOD,8EAmBC;;CA+BF;;mBAntBkB,aAAa;qBACX,iBAAiB;2BACX,iBAAiB"}
@@ -1 +1 @@
1
- {"version":3,"file":"SSR.d.ts","sourceRoot":"","sources":["../../node/SSR.js"],"names":[],"mappings":"AAsQA;IAEE,8BAAmB;IACnB,8BAAmB;IAMnB;;;OAkEC;IAMD,uBAeC;IAkBD,yBAZW,MAAM,YACN;QAAE,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,GAChB,OAAO,CAAC,MAAM,CAAC,CA0B3B;IAWD,+BALW,MAAM;;iBAEN;QAAE,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,GAChB,MAAM,CAclB;IAWD,+BALW,MAAM;;iBAEN;QAAE,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,GAChB,cAAc,CAAC,MAAM,CAAC,CAalC;CACF"}
1
+ {"version":3,"file":"SSR.d.ts","sourceRoot":"","sources":["../../node/SSR.js"],"names":[],"mappings":"AAsQA;IAEE,8BAAmB;IACnB,8BAAmB;IAMnB;;;OAkEC;IAMD,uBAeC;IAkBD,yBAZW,MAAM,YACN;QAAE,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,GAChB,OAAO,CAAC,MAAM,CAAC,CA0B3B;IAWD,+BALW,MAAM;;iBAEN;QAAE,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,GAChB,MAAM,CAyBlB;IAWD,+BALW,MAAM;;iBAEN;QAAE,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,GAChB,cAAc,CAAC,MAAM,CAAC,CAsBlC;CACF"}