@toyz/loom 0.13.1 → 0.13.2

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.
@@ -3,6 +3,10 @@
3
3
  *
4
4
  * Stackable class decorator that defers module loading until first mount.
5
5
  *
6
+ * The shell element hosts a real instance inside its shadow DOM.
7
+ * This is necessary because TC39 private fields (#private) are
8
+ * per-class-identity — prototype-copying can't transfer private slots.
9
+ *
6
10
  * ```ts
7
11
  * @component("settings-page")
8
12
  * @route("/settings")
@@ -10,9 +14,10 @@
10
14
  * class SettingsPage extends LoomElement {}
11
15
  * ```
12
16
  */
13
- declare const LAZY_LOADER: unique symbol;
14
- declare const LAZY_OPTS: unique symbol;
15
- declare const LAZY_LOADED: unique symbol;
17
+ declare const LAZY_LOADER: import("..").LoomSymbol<unknown>;
18
+ declare const LAZY_OPTS: import("..").LoomSymbol<LazyOptions>;
19
+ declare const LAZY_LOADED: import("..").LoomSymbol<boolean>;
20
+ declare const LAZY_IMPL: import("..").LoomSymbol<unknown>;
16
21
  export interface LazyOptions {
17
22
  /** Tag name of a loading component to show while the chunk loads */
18
23
  loading?: string;
@@ -27,5 +32,5 @@ export interface LazyOptions {
27
32
  export declare function lazy(loader: () => Promise<{
28
33
  default: unknown;
29
34
  } | unknown>, opts?: LazyOptions): (value: Function, _context: ClassDecoratorContext) => void;
30
- export { LAZY_LOADER, LAZY_OPTS, LAZY_LOADED };
35
+ export { LAZY_LOADER, LAZY_OPTS, LAZY_LOADED, LAZY_IMPL };
31
36
  //# sourceMappingURL=lazy.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"lazy.d.ts","sourceRoot":"","sources":["../../src/element/lazy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,QAAA,MAAM,WAAW,eAA6B,CAAC;AAC/C,QAAA,MAAM,SAAS,eAA2B,CAAC;AAC3C,QAAA,MAAM,WAAW,eAA6B,CAAC;AAE/C,MAAM,WAAW,WAAW;IAC1B,oEAAoE;IACpE,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;GAMG;AACH,wBAAgB,IAAI,CAClB,MAAM,EAAE,MAAM,OAAO,CAAC;IAAE,OAAO,EAAE,OAAO,CAAA;CAAE,GAAG,OAAO,CAAC,EACrD,IAAI,CAAC,EAAE,WAAW,IAED,OAAO,QAAQ,EAAE,UAAU,qBAAqB,UAkDlE;AAED,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,WAAW,EAAE,CAAC"}
1
+ {"version":3,"file":"lazy.d.ts","sourceRoot":"","sources":["../../src/element/lazy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAIH,QAAA,MAAM,WAAW,kCAA8B,CAAC;AAChD,QAAA,MAAM,SAAS,sCAA2C,CAAC;AAC3D,QAAA,MAAM,WAAW,kCAAuC,CAAC;AACzD,QAAA,MAAM,SAAS,kCAA8B,CAAC;AAE9C,MAAM,WAAW,WAAW;IAC1B,oEAAoE;IACpE,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;GAMG;AACH,wBAAgB,IAAI,CAClB,MAAM,EAAE,MAAM,OAAO,CAAC;IAAE,OAAO,EAAE,OAAO,CAAA;CAAE,GAAG,OAAO,CAAC,EACrD,IAAI,CAAC,EAAE,WAAW,IAED,OAAO,QAAQ,EAAE,UAAU,qBAAqB,UAsElE;AAED,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,WAAW,EAAE,SAAS,EAAE,CAAC"}
@@ -3,6 +3,10 @@
3
3
  *
4
4
  * Stackable class decorator that defers module loading until first mount.
5
5
  *
6
+ * The shell element hosts a real instance inside its shadow DOM.
7
+ * This is necessary because TC39 private fields (#private) are
8
+ * per-class-identity — prototype-copying can't transfer private slots.
9
+ *
6
10
  * ```ts
7
11
  * @component("settings-page")
8
12
  * @route("/settings")
@@ -10,9 +14,11 @@
10
14
  * class SettingsPage extends LoomElement {}
11
15
  * ```
12
16
  */
13
- const LAZY_LOADER = Symbol("loom:lazy:loader");
14
- const LAZY_OPTS = Symbol("loom:lazy:opts");
15
- const LAZY_LOADED = Symbol("loom:lazy:loaded");
17
+ import { ROUTE_PROPS, createSymbol } from "../decorators/symbols";
18
+ const LAZY_LOADER = createSymbol("lazy:loader");
19
+ const LAZY_OPTS = createSymbol("lazy:opts");
20
+ const LAZY_LOADED = createSymbol("lazy:loaded");
21
+ const LAZY_IMPL = createSymbol("lazy:impl");
16
22
  /**
17
23
  * @lazy(loader, opts?) — Stackable class decorator
18
24
  *
@@ -23,14 +29,20 @@ const LAZY_LOADED = Symbol("loom:lazy:loaded");
23
29
  export function lazy(loader, opts) {
24
30
  return function (value, _context) {
25
31
  const ctor = value;
26
- ctor[LAZY_LOADER] = loader;
27
- ctor[LAZY_OPTS] = opts;
32
+ ctor[LAZY_LOADER.key] = loader;
33
+ ctor[LAZY_OPTS.key] = opts;
28
34
  const origConnected = ctor.prototype.connectedCallback;
29
35
  ctor.prototype.connectedCallback = async function () {
30
- if (ctor[LAZY_LOADED]) {
36
+ // Already loaded — if we have a hosted impl, just call its connected
37
+ if (ctor[LAZY_LOADED.key]) {
31
38
  origConnected?.call(this);
39
+ // Re-mount the impl if disconnected/reconnected
40
+ if (!this[LAZY_IMPL.key] || !this[LAZY_IMPL.key].isConnected) {
41
+ this._mountLazyImpl?.();
42
+ }
32
43
  return;
33
44
  }
45
+ // Show loading indicator
34
46
  if (opts?.loading) {
35
47
  const loadingEl = document.createElement(opts.loading);
36
48
  this.shadow.appendChild(loadingEl);
@@ -38,27 +50,35 @@ export function lazy(loader, opts) {
38
50
  try {
39
51
  const mod = await loader();
40
52
  const RealClass = mod.default ?? mod;
41
- const realProto = RealClass.prototype;
42
- const descriptors = Object.getOwnPropertyDescriptors(realProto);
43
- for (const [key, desc] of Object.entries(descriptors)) {
44
- if (key === "constructor")
45
- continue;
46
- Object.defineProperty(ctor.prototype, key, desc);
47
- }
48
- const staticDescs = Object.getOwnPropertyDescriptors(RealClass);
49
- for (const [key, desc] of Object.entries(staticDescs)) {
50
- if (["prototype", "length", "name"].includes(key))
51
- continue;
52
- Object.defineProperty(ctor, key, desc);
53
+ // Register the real class under an internal impl tag
54
+ const baseTag = ctor.__loom_tag ?? this.tagName.toLowerCase();
55
+ const implTag = `${baseTag}-impl`;
56
+ if (!customElements.get(implTag)) {
57
+ customElements.define(implTag, RealClass);
53
58
  }
54
- ctor[LAZY_LOADED] = true;
59
+ // Store the impl tag for future mounts
60
+ ctor[LAZY_LOADED.key] = true;
61
+ ctor.__lazy_impl_tag = implTag;
62
+ // Clear loading indicator and mount
55
63
  this.shadow.innerHTML = "";
56
- if (ctor.prototype.connectedCallback !== origConnected) {
57
- ctor.prototype.connectedCallback.call(this);
58
- }
59
- else {
60
- origConnected?.call(this);
61
- }
64
+ this._mountLazyImpl = () => {
65
+ const realEl = document.createElement(ctor.__lazy_impl_tag);
66
+ // Forward all attributes from shell → real instance
67
+ for (const attr of this.attributes) {
68
+ realEl.setAttribute(attr.name, attr.value);
69
+ }
70
+ // Forward route data via ROUTE_PROPS metadata
71
+ const routeBindings = ctor[ROUTE_PROPS.key] ?? [];
72
+ for (const binding of routeBindings) {
73
+ const val = this[binding.propKey];
74
+ if (val !== undefined) {
75
+ realEl[binding.propKey] = val;
76
+ }
77
+ }
78
+ this.shadow.appendChild(realEl);
79
+ this[LAZY_IMPL.key] = realEl;
80
+ };
81
+ this._mountLazyImpl();
62
82
  }
63
83
  catch (err) {
64
84
  console.error("[Loom @lazy] Failed to load module:", err);
@@ -67,5 +87,5 @@ export function lazy(loader, opts) {
67
87
  };
68
88
  };
69
89
  }
70
- export { LAZY_LOADER, LAZY_OPTS, LAZY_LOADED };
90
+ export { LAZY_LOADER, LAZY_OPTS, LAZY_LOADED, LAZY_IMPL };
71
91
  //# sourceMappingURL=lazy.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"lazy.js","sourceRoot":"","sources":["../../src/element/lazy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,MAAM,WAAW,GAAG,MAAM,CAAC,kBAAkB,CAAC,CAAC;AAC/C,MAAM,SAAS,GAAG,MAAM,CAAC,gBAAgB,CAAC,CAAC;AAC3C,MAAM,WAAW,GAAG,MAAM,CAAC,kBAAkB,CAAC,CAAC;AAO/C;;;;;;GAMG;AACH,MAAM,UAAU,IAAI,CAClB,MAAqD,EACrD,IAAkB;IAElB,OAAO,UAAU,KAAe,EAAE,QAA+B;QAC/D,MAAM,IAAI,GAAG,KAAY,CAAC;QAC1B,IAAI,CAAC,WAAW,CAAC,GAAG,MAAM,CAAC;QAC3B,IAAI,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC;QAEvB,MAAM,aAAa,GAAG,IAAI,CAAC,SAAS,CAAC,iBAAiB,CAAC;QAEvD,IAAI,CAAC,SAAS,CAAC,iBAAiB,GAAG,KAAK;YACtC,IAAI,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC;gBACtB,aAAa,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;gBAC1B,OAAO;YACT,CAAC;YAED,IAAI,IAAI,EAAE,OAAO,EAAE,CAAC;gBAClB,MAAM,SAAS,GAAG,QAAQ,CAAC,aAAa,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;gBACvD,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC;YACrC,CAAC;YAED,IAAI,CAAC;gBACH,MAAM,GAAG,GAAG,MAAM,MAAM,EAAE,CAAC;gBAC3B,MAAM,SAAS,GAAI,GAA8B,CAAC,OAAO,IAAI,GAAG,CAAC;gBAEjE,MAAM,SAAS,GAAI,SAAsB,CAAC,SAAS,CAAC;gBACpD,MAAM,WAAW,GAAG,MAAM,CAAC,yBAAyB,CAAC,SAAS,CAAC,CAAC;gBAEhE,KAAK,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC,EAAE,CAAC;oBACtD,IAAI,GAAG,KAAK,aAAa;wBAAE,SAAS;oBACpC,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,SAAS,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;gBACnD,CAAC;gBAED,MAAM,WAAW,GAAG,MAAM,CAAC,yBAAyB,CAAC,SAAmB,CAAC,CAAC;gBAC1E,KAAK,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC,EAAE,CAAC;oBACtD,IAAI,CAAC,WAAW,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC;wBAAE,SAAS;oBAC5D,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;gBACzC,CAAC;gBAED,IAAI,CAAC,WAAW,CAAC,GAAG,IAAI,CAAC;gBACzB,IAAI,CAAC,MAAM,CAAC,SAAS,GAAG,EAAE,CAAC;gBAE3B,IAAI,IAAI,CAAC,SAAS,CAAC,iBAAiB,KAAK,aAAa,EAAE,CAAC;oBACvD,IAAI,CAAC,SAAS,CAAC,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBAC9C,CAAC;qBAAM,CAAC;oBACN,aAAa,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;gBAC5B,CAAC;YACH,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,OAAO,CAAC,KAAK,CAAC,qCAAqC,EAAE,GAAG,CAAC,CAAC;gBAC1D,IAAI,CAAC,MAAM,CAAC,SAAS,GAAG,mDAAmD,CAAC;YAC9E,CAAC;QACH,CAAC,CAAC;IACJ,CAAC,CAAC;AACJ,CAAC;AAED,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,WAAW,EAAE,CAAC"}
1
+ {"version":3,"file":"lazy.js","sourceRoot":"","sources":["../../src/element/lazy.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@toyz/loom",
3
- "version": "0.13.1",
3
+ "version": "0.13.2",
4
4
  "type": "module",
5
5
  "description": "Decorator-driven web component framework with reactive state, DOM morphing, DI, and JSX",
6
6
  "license": "MIT",