@toyz/loom 0.1.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 (127) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +108 -0
  3. package/dist/app.d.ts +70 -0
  4. package/dist/app.d.ts.map +1 -0
  5. package/dist/app.js +152 -0
  6. package/dist/app.js.map +1 -0
  7. package/dist/bus.d.ts +27 -0
  8. package/dist/bus.d.ts.map +1 -0
  9. package/dist/bus.js +41 -0
  10. package/dist/bus.js.map +1 -0
  11. package/dist/css.d.ts +25 -0
  12. package/dist/css.d.ts.map +1 -0
  13. package/dist/css.js +48 -0
  14. package/dist/css.js.map +1 -0
  15. package/dist/decorators/component.d.ts +11 -0
  16. package/dist/decorators/component.d.ts.map +1 -0
  17. package/dist/decorators/component.js +38 -0
  18. package/dist/decorators/component.js.map +1 -0
  19. package/dist/decorators/di.d.ts +37 -0
  20. package/dist/decorators/di.d.ts.map +1 -0
  21. package/dist/decorators/di.js +65 -0
  22. package/dist/decorators/di.js.map +1 -0
  23. package/dist/decorators/dom.d.ts +15 -0
  24. package/dist/decorators/dom.d.ts.map +1 -0
  25. package/dist/decorators/dom.js +33 -0
  26. package/dist/decorators/dom.js.map +1 -0
  27. package/dist/decorators/events.d.ts +46 -0
  28. package/dist/decorators/events.d.ts.map +1 -0
  29. package/dist/decorators/events.js +69 -0
  30. package/dist/decorators/events.js.map +1 -0
  31. package/dist/decorators/index.d.ts +18 -0
  32. package/dist/decorators/index.d.ts.map +1 -0
  33. package/dist/decorators/index.js +27 -0
  34. package/dist/decorators/index.js.map +1 -0
  35. package/dist/decorators/lifecycle.d.ts +49 -0
  36. package/dist/decorators/lifecycle.d.ts.map +1 -0
  37. package/dist/decorators/lifecycle.js +105 -0
  38. package/dist/decorators/lifecycle.js.map +1 -0
  39. package/dist/decorators/state.d.ts +41 -0
  40. package/dist/decorators/state.d.ts.map +1 -0
  41. package/dist/decorators/state.js +125 -0
  42. package/dist/decorators/state.js.map +1 -0
  43. package/dist/decorators/symbols.d.ts +13 -0
  44. package/dist/decorators/symbols.d.ts.map +1 -0
  45. package/dist/decorators/symbols.js +15 -0
  46. package/dist/decorators/symbols.js.map +1 -0
  47. package/dist/decorators/timing.d.ts +35 -0
  48. package/dist/decorators/timing.d.ts.map +1 -0
  49. package/dist/decorators/timing.js +57 -0
  50. package/dist/decorators/timing.js.map +1 -0
  51. package/dist/decorators/transform.d.ts +45 -0
  52. package/dist/decorators/transform.d.ts.map +1 -0
  53. package/dist/decorators/transform.js +48 -0
  54. package/dist/decorators/transform.js.map +1 -0
  55. package/dist/element.d.ts +62 -0
  56. package/dist/element.d.ts.map +1 -0
  57. package/dist/element.js +150 -0
  58. package/dist/element.js.map +1 -0
  59. package/dist/event.d.ts +24 -0
  60. package/dist/event.d.ts.map +1 -0
  61. package/dist/event.js +35 -0
  62. package/dist/event.js.map +1 -0
  63. package/dist/icon.d.ts +35 -0
  64. package/dist/icon.d.ts.map +1 -0
  65. package/dist/icon.js +119 -0
  66. package/dist/icon.js.map +1 -0
  67. package/dist/index.d.ts +29 -0
  68. package/dist/index.d.ts.map +1 -0
  69. package/dist/index.js +34 -0
  70. package/dist/index.js.map +1 -0
  71. package/dist/jsx-dev-runtime.d.ts +8 -0
  72. package/dist/jsx-dev-runtime.d.ts.map +1 -0
  73. package/dist/jsx-dev-runtime.js +8 -0
  74. package/dist/jsx-dev-runtime.js.map +1 -0
  75. package/dist/jsx-runtime.d.ts +13 -0
  76. package/dist/jsx-runtime.d.ts.map +1 -0
  77. package/dist/jsx-runtime.js +101 -0
  78. package/dist/jsx-runtime.js.map +1 -0
  79. package/dist/morph.d.ts +23 -0
  80. package/dist/morph.d.ts.map +1 -0
  81. package/dist/morph.js +212 -0
  82. package/dist/morph.js.map +1 -0
  83. package/dist/reactive.d.ts +75 -0
  84. package/dist/reactive.d.ts.map +1 -0
  85. package/dist/reactive.js +133 -0
  86. package/dist/reactive.js.map +1 -0
  87. package/dist/render-loop.d.ts +34 -0
  88. package/dist/render-loop.d.ts.map +1 -0
  89. package/dist/render-loop.js +70 -0
  90. package/dist/render-loop.js.map +1 -0
  91. package/dist/router/events.d.ts +12 -0
  92. package/dist/router/events.d.ts.map +1 -0
  93. package/dist/router/events.js +17 -0
  94. package/dist/router/events.js.map +1 -0
  95. package/dist/router/index.d.ts +14 -0
  96. package/dist/router/index.d.ts.map +1 -0
  97. package/dist/router/index.js +18 -0
  98. package/dist/router/index.js.map +1 -0
  99. package/dist/router/link.d.ts +18 -0
  100. package/dist/router/link.d.ts.map +1 -0
  101. package/dist/router/link.js +75 -0
  102. package/dist/router/link.js.map +1 -0
  103. package/dist/router/mode.d.ts +33 -0
  104. package/dist/router/mode.d.ts.map +1 -0
  105. package/dist/router/mode.js +48 -0
  106. package/dist/router/mode.js.map +1 -0
  107. package/dist/router/outlet.d.ts +40 -0
  108. package/dist/router/outlet.d.ts.map +1 -0
  109. package/dist/router/outlet.js +171 -0
  110. package/dist/router/outlet.js.map +1 -0
  111. package/dist/router/route.d.ts +76 -0
  112. package/dist/router/route.d.ts.map +1 -0
  113. package/dist/router/route.js +147 -0
  114. package/dist/router/route.js.map +1 -0
  115. package/dist/router/router.d.ts +50 -0
  116. package/dist/router/router.d.ts.map +1 -0
  117. package/dist/router/router.js +140 -0
  118. package/dist/router/router.js.map +1 -0
  119. package/dist/storage.d.ts +55 -0
  120. package/dist/storage.d.ts.map +1 -0
  121. package/dist/storage.js +90 -0
  122. package/dist/storage.js.map +1 -0
  123. package/dist/virtual.d.ts +69 -0
  124. package/dist/virtual.d.ts.map +1 -0
  125. package/dist/virtual.js +247 -0
  126. package/dist/virtual.js.map +1 -0
  127. package/package.json +58 -0
package/dist/icon.js ADDED
@@ -0,0 +1,119 @@
1
+ /**
2
+ * Loom — Icon Component
3
+ *
4
+ * Reusable SVG icon wrapper with a static registry.
5
+ * Ships with zero built-in icons — register your own.
6
+ *
7
+ * Usage:
8
+ * // Register icons (once, at boot)
9
+ * LoomIcon.register("bolt", '<path d="M13 2 3 14h9l-1 8 10-12h-9l1-8z" />');
10
+ *
11
+ * // Use anywhere in JSX
12
+ * <loom-icon name="bolt" size={20} color="var(--accent)" />
13
+ */
14
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
15
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
16
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
17
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
18
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
19
+ };
20
+ import { LoomElement } from "./element";
21
+ import { component, prop } from "./decorators";
22
+ import { css } from "./css";
23
+ const baseStyles = css `
24
+ :host {
25
+ display: inline-flex;
26
+ align-items: center;
27
+ justify-content: center;
28
+ vertical-align: middle;
29
+ line-height: 0;
30
+ width: var(--_s);
31
+ height: var(--_s);
32
+ }
33
+ svg {
34
+ width: 100%;
35
+ height: 100%;
36
+ fill: none;
37
+ stroke: var(--_c, currentColor);
38
+ stroke-width: 1.75;
39
+ stroke-linecap: round;
40
+ stroke-linejoin: round;
41
+ }
42
+ `;
43
+ /** Icon path data registry (name → SVG inner content) */
44
+ const registry = new Map();
45
+ let LoomIcon = class LoomIcon extends LoomElement {
46
+ /** Icon name (must be registered via LoomIcon.register) */
47
+ name = "";
48
+ /** Size in pixels */
49
+ size = 24;
50
+ /** Stroke color (CSS value) */
51
+ color = "currentColor";
52
+ /** Register an icon. `svgInner` is the SVG inner content (paths, circles, etc). */
53
+ static register(name, svgInner) {
54
+ registry.set(name, svgInner);
55
+ }
56
+ /** Register multiple icons at once. */
57
+ static registerAll(icons) {
58
+ for (const [name, svg] of Object.entries(icons)) {
59
+ registry.set(name, svg);
60
+ }
61
+ }
62
+ /** Check if an icon is registered. */
63
+ static has(name) {
64
+ return registry.has(name);
65
+ }
66
+ /** List all registered icon names. */
67
+ static get names() {
68
+ return Array.from(registry.keys());
69
+ }
70
+ /** Immediately apply size/color from attributes — runs before connectedCallback */
71
+ attributeChangedCallback(name, _old, val) {
72
+ // Note: @component decorator wraps this method and parses @prop values
73
+ // before calling us. We just sync the CSS custom properties immediately.
74
+ if (name === "size" && val !== null) {
75
+ this.style.setProperty("--_s", `${val}px`);
76
+ }
77
+ else if (name === "color" && val !== null) {
78
+ this.style.setProperty("--_c", val);
79
+ }
80
+ }
81
+ connectedCallback() {
82
+ // Set CSS vars from current attributes before first paint
83
+ const s = this.getAttribute("size");
84
+ const c = this.getAttribute("color");
85
+ this.style.setProperty("--_s", `${s ?? this.size}px`);
86
+ if (c)
87
+ this.style.setProperty("--_c", c);
88
+ super.connectedCallback();
89
+ }
90
+ update() {
91
+ this.shadow.adoptedStyleSheets = [baseStyles];
92
+ this.style.setProperty("--_s", `${this.size}px`);
93
+ this.style.setProperty("--_c", this.color);
94
+ const inner = registry.get(this.name);
95
+ if (!inner) {
96
+ const placeholder = document.createElement("span");
97
+ return placeholder;
98
+ }
99
+ const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
100
+ svg.setAttribute("viewBox", "0 0 24 24");
101
+ svg.setAttribute("aria-hidden", "true");
102
+ svg.innerHTML = inner;
103
+ return svg;
104
+ }
105
+ };
106
+ __decorate([
107
+ prop
108
+ ], LoomIcon.prototype, "name", void 0);
109
+ __decorate([
110
+ prop
111
+ ], LoomIcon.prototype, "size", void 0);
112
+ __decorate([
113
+ prop
114
+ ], LoomIcon.prototype, "color", void 0);
115
+ LoomIcon = __decorate([
116
+ component("loom-icon")
117
+ ], LoomIcon);
118
+ export { LoomIcon };
119
+ //# sourceMappingURL=icon.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"icon.js","sourceRoot":"","sources":["../src/icon.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Loom — Barrel exports
3
+ *
4
+ * Import everything from "loom":
5
+ * import { EventBus, LoomEvent, Reactive, LoomElement, component, ... } from "loom";
6
+ */
7
+ export { app } from "./app";
8
+ export type { LoomApp } from "./app";
9
+ export { LoomEvent } from "./event";
10
+ export { EventBus, bus, useBus } from "./bus";
11
+ export type { Constructor, Handler } from "./bus";
12
+ export { Reactive, CollectionStore } from "./reactive";
13
+ export type { Subscriber, Updater, Identifiable } from "./reactive";
14
+ export { MemoryStorage, LocalMedium, SessionMedium } from "./storage";
15
+ export type { StorageMedium, PersistOptions } from "./storage";
16
+ export { css } from "./css";
17
+ export type { CSSValue } from "./css";
18
+ export { LoomElement } from "./element";
19
+ export { morph } from "./morph";
20
+ export { component, prop, reactive, computed, on, watch, emit, query, queryAll, catch_, suspend, mount, unmount, interval, timeout, animationFrame, service, inject, factory, params, routeQuery, transform, typed, } from "./decorators";
21
+ export { jsx, jsxs, Fragment } from "./jsx-runtime";
22
+ export { renderLoop } from "./render-loop";
23
+ export type { RenderLoop } from "./render-loop";
24
+ export { LoomIcon } from "./icon";
25
+ export { LoomVirtual } from "./virtual";
26
+ export type { VirtualListOptions } from "./virtual";
27
+ export { LoomRouter, RouteChanged, route, guard, matchRoute, routes, LoomOutlet, LoomLink, HashMode, HistoryMode, } from "./router";
28
+ export type { RouterMode, RouterOptions, RouteInfo, RouteEntry } from "./router";
29
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AAC5B,YAAY,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AAErC,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACpC,OAAO,EAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC;AAC9C,YAAY,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AAGlD,OAAO,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AACvD,YAAY,EAAE,UAAU,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAGpE,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AACtE,YAAY,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAG/D,OAAO,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AAC5B,YAAY,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAGtC,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAGxC,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAGhC,OAAO,EACL,SAAS,EACT,IAAI,EACJ,QAAQ,EACR,QAAQ,EACR,EAAE,EACF,KAAK,EACL,IAAI,EACJ,KAAK,EACL,QAAQ,EACR,MAAM,EACN,OAAO,EACP,KAAK,EACL,OAAO,EACP,QAAQ,EACR,OAAO,EACP,cAAc,EACd,OAAO,EACP,MAAM,EACN,OAAO,EACP,MAAM,EACN,UAAU,EACV,SAAS,EACT,KAAK,GACN,MAAM,cAAc,CAAC;AAGtB,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAGpD,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3C,YAAY,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAGhD,OAAO,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAGlC,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACxC,YAAY,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;AAGpD,OAAO,EACL,UAAU,EACV,YAAY,EACZ,KAAK,EACL,KAAK,EACL,UAAU,EACV,MAAM,EACN,UAAU,EACV,QAAQ,EACR,QAAQ,EACR,WAAW,GACZ,MAAM,UAAU,CAAC;AAClB,YAAY,EAAE,UAAU,EAAE,aAAa,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Loom — Barrel exports
3
+ *
4
+ * Import everything from "loom":
5
+ * import { EventBus, LoomEvent, Reactive, LoomElement, component, ... } from "loom";
6
+ */
7
+ // App entry point
8
+ export { app } from "./app";
9
+ // Event system
10
+ export { LoomEvent } from "./event";
11
+ export { EventBus, bus, useBus } from "./bus";
12
+ // Reactive stores
13
+ export { Reactive, CollectionStore } from "./reactive";
14
+ // Storage mediums
15
+ export { MemoryStorage, LocalMedium, SessionMedium } from "./storage";
16
+ // CSS
17
+ export { css } from "./css";
18
+ // Element base
19
+ export { LoomElement } from "./element";
20
+ // DOM morphing
21
+ export { morph } from "./morph";
22
+ // Decorators
23
+ export { component, prop, reactive, computed, on, watch, emit, query, queryAll, catch_, suspend, mount, unmount, interval, timeout, animationFrame, service, inject, factory, params, routeQuery, transform, typed, } from "./decorators";
24
+ // JSX runtime (re-exported so jsxImportSource resolves)
25
+ export { jsx, jsxs, Fragment } from "./jsx-runtime";
26
+ // Render loop
27
+ export { renderLoop } from "./render-loop";
28
+ // Icon
29
+ export { LoomIcon } from "./icon";
30
+ // Virtual list
31
+ export { LoomVirtual } from "./virtual";
32
+ // Router
33
+ export { LoomRouter, RouteChanged, route, guard, matchRoute, routes, LoomOutlet, LoomLink, HashMode, HistoryMode, } from "./router";
34
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,kBAAkB;AAClB,OAAO,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AAE5B,eAAe;AACf,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACpC,OAAO,EAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC;AAG9C,kBAAkB;AAClB,OAAO,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAGvD,kBAAkB;AAClB,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAGtE,MAAM;AACN,OAAO,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AAG5B,eAAe;AACf,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAExC,eAAe;AACf,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAEhC,aAAa;AACb,OAAO,EACL,SAAS,EACT,IAAI,EACJ,QAAQ,EACR,QAAQ,EACR,EAAE,EACF,KAAK,EACL,IAAI,EACJ,KAAK,EACL,QAAQ,EACR,MAAM,EACN,OAAO,EACP,KAAK,EACL,OAAO,EACP,QAAQ,EACR,OAAO,EACP,cAAc,EACd,OAAO,EACP,MAAM,EACN,OAAO,EACP,MAAM,EACN,UAAU,EACV,SAAS,EACT,KAAK,GACN,MAAM,cAAc,CAAC;AAEtB,wDAAwD;AACxD,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAEpD,cAAc;AACd,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAG3C,OAAO;AACP,OAAO,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAElC,eAAe;AACf,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAGxC,SAAS;AACT,OAAO,EACL,UAAU,EACV,YAAY,EACZ,KAAK,EACL,KAAK,EACL,UAAU,EACV,MAAM,EACN,UAAU,EACV,QAAQ,EACR,QAAQ,EACR,WAAW,GACZ,MAAM,UAAU,CAAC"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Loom — JSX Dev Runtime
3
+ *
4
+ * In development, React-style JSX transform imports from jsx-dev-runtime.
5
+ * We just re-export the production runtime since we don't need dev-specific features.
6
+ */
7
+ export { jsx as jsxDEV, Fragment } from "./jsx-runtime";
8
+ //# sourceMappingURL=jsx-dev-runtime.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jsx-dev-runtime.d.ts","sourceRoot":"","sources":["../src/jsx-dev-runtime.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,GAAG,IAAI,MAAM,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Loom — JSX Dev Runtime
3
+ *
4
+ * In development, React-style JSX transform imports from jsx-dev-runtime.
5
+ * We just re-export the production runtime since we don't need dev-specific features.
6
+ */
7
+ export { jsx as jsxDEV, Fragment } from "./jsx-runtime";
8
+ //# sourceMappingURL=jsx-dev-runtime.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jsx-dev-runtime.js","sourceRoot":"","sources":["../src/jsx-dev-runtime.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,GAAG,IAAI,MAAM,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Loom — JSX Runtime (automatic mode)
3
+ *
4
+ * Zero vDOM. JSX compiles directly to DOM elements.
5
+ * Configure via tsconfig: "jsxImportSource": "loom"
6
+ */
7
+ export declare function jsx(tag: string | Function, props: Record<string, any>): HTMLElement | SVGElement | DocumentFragment;
8
+ /** jsxs is the same as jsx — we don't do vDOM diffing */
9
+ export declare const jsxs: typeof jsx;
10
+ export declare function Fragment(props: {
11
+ children?: any;
12
+ }): DocumentFragment;
13
+ //# sourceMappingURL=jsx-runtime.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jsx-runtime.d.ts","sourceRoot":"","sources":["../src/jsx-runtime.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAeH,wBAAgB,GAAG,CACjB,GAAG,EAAE,MAAM,GAAG,QAAQ,EACtB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GACzB,WAAW,GAAG,UAAU,GAAG,gBAAgB,CAkD7C;AAED,yDAAyD;AACzD,eAAO,MAAM,IAAI,YAAM,CAAC;AAExB,wBAAgB,QAAQ,CAAC,KAAK,EAAE;IAAE,QAAQ,CAAC,EAAE,GAAG,CAAA;CAAE,GAAG,gBAAgB,CAIpE"}
@@ -0,0 +1,101 @@
1
+ /**
2
+ * Loom — JSX Runtime (automatic mode)
3
+ *
4
+ * Zero vDOM. JSX compiles directly to DOM elements.
5
+ * Configure via tsconfig: "jsxImportSource": "loom"
6
+ */
7
+ import { LOOM_EVENTS } from "./morph";
8
+ const SVG_NS = "http://www.w3.org/2000/svg";
9
+ const SVG_TAGS = new Set([
10
+ "svg", "path", "circle", "rect", "line", "polyline", "polygon",
11
+ "text", "g", "defs", "use", "clipPath", "mask", "filter",
12
+ "linearGradient", "radialGradient", "stop", "foreignObject",
13
+ "marker", "symbol", "pattern", "ellipse", "image", "tspan",
14
+ ]);
15
+ /** Properties that must be set as JS properties, not HTML attributes */
16
+ const PROP_KEYS = new Set(["value", "checked", "selected", "indeterminate"]);
17
+ export function jsx(tag, props) {
18
+ if (typeof tag === "function")
19
+ return tag(props);
20
+ const isSVG = SVG_TAGS.has(tag);
21
+ const el = isSVG
22
+ ? document.createElementNS(SVG_NS, tag)
23
+ : document.createElement(tag);
24
+ for (const [key, val] of Object.entries(props ?? {})) {
25
+ if (key === "children")
26
+ continue;
27
+ if (key.startsWith("on") && typeof val === "function") {
28
+ const eventType = key.slice(2).toLowerCase();
29
+ el.addEventListener(eventType, val);
30
+ // Track for morph diffing
31
+ let events = el[LOOM_EVENTS];
32
+ if (!events) {
33
+ events = new Map();
34
+ el[LOOM_EVENTS] = events;
35
+ }
36
+ events.set(eventType, val);
37
+ }
38
+ else if (key === "ref" && typeof val === "function") {
39
+ val(el);
40
+ }
41
+ else if (key === "style" && typeof val === "object") {
42
+ Object.assign(el.style, val);
43
+ }
44
+ else if (key === "className" || key === "class") {
45
+ if (isSVG) {
46
+ el.setAttribute("class", val);
47
+ }
48
+ else {
49
+ el.className = val;
50
+ }
51
+ }
52
+ else if (key === "htmlFor") {
53
+ el.setAttribute("for", val);
54
+ }
55
+ else if (key === "rawHTML" || key === "innerHTML") {
56
+ el.innerHTML = val;
57
+ el.__loomRawHTML = true;
58
+ }
59
+ else if (PROP_KEYS.has(key)) {
60
+ el[key] = val;
61
+ }
62
+ else if (typeof val === "boolean") {
63
+ val ? el.setAttribute(key, "") : el.removeAttribute(key);
64
+ }
65
+ else if (typeof val === "object" || typeof val === "function") {
66
+ // Non-primitive values (arrays, objects) — set as JS property
67
+ el[key] = val;
68
+ }
69
+ else {
70
+ if (isSVG) {
71
+ el.setAttribute(key, String(val));
72
+ }
73
+ else {
74
+ el.setAttribute(key, String(val));
75
+ }
76
+ }
77
+ }
78
+ appendChildren(el, props?.children);
79
+ return el;
80
+ }
81
+ /** jsxs is the same as jsx — we don't do vDOM diffing */
82
+ export const jsxs = jsx;
83
+ export function Fragment(props) {
84
+ const frag = document.createDocumentFragment();
85
+ appendChildren(frag, props?.children);
86
+ return frag;
87
+ }
88
+ function appendChildren(parent, children) {
89
+ if (children == null || children === false)
90
+ return;
91
+ if (Array.isArray(children)) {
92
+ children.forEach((c) => appendChildren(parent, c));
93
+ }
94
+ else if (children instanceof Node) {
95
+ parent.appendChild(children);
96
+ }
97
+ else {
98
+ parent.appendChild(document.createTextNode(String(children)));
99
+ }
100
+ }
101
+ //# sourceMappingURL=jsx-runtime.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jsx-runtime.js","sourceRoot":"","sources":["../src/jsx-runtime.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Loom — DOM Morph
3
+ *
4
+ * Patches an existing DOM tree to match a new tree, in-place.
5
+ * Only touches what actually changed — text, attributes, structure.
6
+ * Event listeners are tracked via __loomEvents expando for diffing.
7
+ *
8
+ * Key features:
9
+ * - Keyed reconciliation via `data-loom-key`
10
+ * - `loom-keep` skips nodes entirely (escape hatch for imperative DOM)
11
+ * - Preserves focus, selection, scroll position
12
+ * - Concurrent-safe: void update() = no morph, returned Node = auto-morph
13
+ */
14
+ /** Expando key for tracked event listeners */
15
+ export declare const LOOM_EVENTS = "__loomEvents";
16
+ /** Type for tracked events on an element */
17
+ export type LoomEventMap = Map<string, EventListener>;
18
+ /**
19
+ * Morph the children of `root` (typically a ShadowRoot) to match `newTree`.
20
+ * `newTree` can be a single Node or an array of Nodes (from Fragment).
21
+ */
22
+ export declare function morph(root: ShadowRoot | HTMLElement, newTree: Node | Node[]): void;
23
+ //# sourceMappingURL=morph.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"morph.d.ts","sourceRoot":"","sources":["../src/morph.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,8CAA8C;AAC9C,eAAO,MAAM,WAAW,iBAAiB,CAAC;AAE1C,4CAA4C;AAC5C,MAAM,MAAM,YAAY,GAAG,GAAG,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;AAItD;;;GAGG;AACH,wBAAgB,KAAK,CAAC,IAAI,EAAE,UAAU,GAAG,WAAW,EAAE,OAAO,EAAE,IAAI,GAAG,IAAI,EAAE,GAAG,IAAI,CAGlF"}
package/dist/morph.js ADDED
@@ -0,0 +1,212 @@
1
+ /**
2
+ * Loom — DOM Morph
3
+ *
4
+ * Patches an existing DOM tree to match a new tree, in-place.
5
+ * Only touches what actually changed — text, attributes, structure.
6
+ * Event listeners are tracked via __loomEvents expando for diffing.
7
+ *
8
+ * Key features:
9
+ * - Keyed reconciliation via `data-loom-key`
10
+ * - `loom-keep` skips nodes entirely (escape hatch for imperative DOM)
11
+ * - Preserves focus, selection, scroll position
12
+ * - Concurrent-safe: void update() = no morph, returned Node = auto-morph
13
+ */
14
+ /** Expando key for tracked event listeners */
15
+ export const LOOM_EVENTS = "__loomEvents";
16
+ // ── Public API ──
17
+ /**
18
+ * Morph the children of `root` (typically a ShadowRoot) to match `newTree`.
19
+ * `newTree` can be a single Node or an array of Nodes (from Fragment).
20
+ */
21
+ export function morph(root, newTree) {
22
+ const newChildren = normalizeChildren(newTree);
23
+ morphChildren(root, newChildren);
24
+ }
25
+ // ── Core algorithm ──
26
+ function morphChildren(parent, newChildren) {
27
+ const oldChildren = Array.from(parent.childNodes);
28
+ // Build keyed index from old children
29
+ const oldKeyed = new Map();
30
+ for (const old of oldChildren) {
31
+ const key = getKey(old);
32
+ if (key)
33
+ oldKeyed.set(key, old);
34
+ }
35
+ // Track which old nodes we've consumed
36
+ const consumed = new Set();
37
+ let oldIdx = 0;
38
+ for (let i = 0; i < newChildren.length; i++) {
39
+ const newChild = newChildren[i];
40
+ const newKey = getKey(newChild);
41
+ // Keyed match — pull from map regardless of position
42
+ if (newKey && oldKeyed.has(newKey)) {
43
+ const oldChild = oldKeyed.get(newKey);
44
+ consumed.add(oldChild);
45
+ morphNode(oldChild, newChild);
46
+ // Move into position if needed
47
+ const ref = parent.childNodes[i] ?? null;
48
+ if (oldChild !== ref) {
49
+ parent.insertBefore(oldChild, ref);
50
+ }
51
+ continue;
52
+ }
53
+ // Unkeyed — try to match by position (skip consumed)
54
+ while (oldIdx < oldChildren.length && consumed.has(oldChildren[oldIdx])) {
55
+ oldIdx++;
56
+ }
57
+ const oldChild = oldChildren[oldIdx];
58
+ if (!oldChild) {
59
+ // No more old children — append
60
+ parent.appendChild(newChild);
61
+ continue;
62
+ }
63
+ // Skip loom-keep nodes — don't touch them
64
+ if (isKeep(oldChild)) {
65
+ consumed.add(oldChild);
66
+ oldIdx++;
67
+ i--; // re-process this new child against the next old
68
+ continue;
69
+ }
70
+ if (canMorph(oldChild, newChild)) {
71
+ consumed.add(oldChild);
72
+ morphNode(oldChild, newChild);
73
+ oldIdx++;
74
+ }
75
+ else {
76
+ // Can't morph — insert new before old
77
+ parent.insertBefore(newChild, oldChild);
78
+ }
79
+ }
80
+ // Remove unconsumed old children (except loom-keep)
81
+ for (const old of oldChildren) {
82
+ if (!consumed.has(old) && !isKeep(old) && old.parentNode === parent) {
83
+ parent.removeChild(old);
84
+ }
85
+ }
86
+ }
87
+ /** Morph a single node in-place. */
88
+ function morphNode(old, next) {
89
+ // Text nodes
90
+ if (old.nodeType === Node.TEXT_NODE && next.nodeType === Node.TEXT_NODE) {
91
+ if (old.textContent !== next.textContent) {
92
+ old.textContent = next.textContent;
93
+ }
94
+ return;
95
+ }
96
+ // Comment nodes
97
+ if (old.nodeType === Node.COMMENT_NODE && next.nodeType === Node.COMMENT_NODE) {
98
+ if (old.textContent !== next.textContent) {
99
+ old.textContent = next.textContent;
100
+ }
101
+ return;
102
+ }
103
+ // Element nodes
104
+ if (old.nodeType === Node.ELEMENT_NODE && next.nodeType === Node.ELEMENT_NODE) {
105
+ const oldEl = old;
106
+ const nextEl = next;
107
+ // Patch attributes
108
+ patchAttributes(oldEl, nextEl);
109
+ // Patch event listeners
110
+ patchEvents(oldEl, nextEl);
111
+ // Patch special DOM properties
112
+ patchProperties(oldEl, nextEl);
113
+ // innerHTML / rawHTML — if the new element used rawHTML, just slam it
114
+ // The JSX runtime sets a __loomRawHTML marker
115
+ if (nextEl.__loomRawHTML) {
116
+ if (oldEl.innerHTML !== nextEl.innerHTML) {
117
+ oldEl.innerHTML = nextEl.innerHTML;
118
+ }
119
+ return; // Don't recurse into rawHTML children
120
+ }
121
+ // Recurse children
122
+ morphChildren(oldEl, Array.from(nextEl.childNodes));
123
+ }
124
+ }
125
+ // ── Attribute diffing ──
126
+ function patchAttributes(old, next) {
127
+ // Add/update attributes from next
128
+ const nextAttrs = next.attributes;
129
+ for (let i = 0; i < nextAttrs.length; i++) {
130
+ const { name, value } = nextAttrs[i];
131
+ if (old.getAttribute(name) !== value) {
132
+ old.setAttribute(name, value);
133
+ }
134
+ }
135
+ // Remove attributes not in next
136
+ const oldAttrs = old.attributes;
137
+ for (let i = oldAttrs.length - 1; i >= 0; i--) {
138
+ const { name } = oldAttrs[i];
139
+ if (!next.hasAttribute(name)) {
140
+ old.removeAttribute(name);
141
+ }
142
+ }
143
+ }
144
+ // ── Event listener diffing ──
145
+ function patchEvents(old, next) {
146
+ const oldEvents = old[LOOM_EVENTS] ?? new Map();
147
+ const newEvents = next[LOOM_EVENTS] ?? new Map();
148
+ // Remove old listeners not in new
149
+ for (const [type, listener] of oldEvents) {
150
+ if (!newEvents.has(type)) {
151
+ old.removeEventListener(type, listener);
152
+ oldEvents.delete(type);
153
+ }
154
+ }
155
+ // Add/replace listeners from new
156
+ for (const [type, listener] of newEvents) {
157
+ const existing = oldEvents.get(type);
158
+ if (existing !== listener) {
159
+ if (existing)
160
+ old.removeEventListener(type, existing);
161
+ old.addEventListener(type, listener);
162
+ oldEvents.set(type, listener);
163
+ }
164
+ }
165
+ // Transfer the map to old element
166
+ if (newEvents.size > 0) {
167
+ old[LOOM_EVENTS] = oldEvents;
168
+ }
169
+ }
170
+ // ── DOM property patching ──
171
+ const PROP_KEYS = ["value", "checked", "selected", "indeterminate"];
172
+ function patchProperties(old, next) {
173
+ for (const key of PROP_KEYS) {
174
+ if (key in next && old[key] !== next[key]) {
175
+ old[key] = next[key];
176
+ }
177
+ }
178
+ }
179
+ // ── Helpers ──
180
+ function getKey(node) {
181
+ if (node.nodeType !== Node.ELEMENT_NODE)
182
+ return null;
183
+ return node.getAttribute("data-loom-key");
184
+ }
185
+ function isKeep(node) {
186
+ if (node.nodeType !== Node.ELEMENT_NODE)
187
+ return false;
188
+ return node.hasAttribute("loom-keep");
189
+ }
190
+ function canMorph(old, next) {
191
+ // Same node type
192
+ if (old.nodeType !== next.nodeType)
193
+ return false;
194
+ // Text/comment nodes always morphable
195
+ if (old.nodeType === Node.TEXT_NODE || old.nodeType === Node.COMMENT_NODE)
196
+ return true;
197
+ // Elements must share tag name
198
+ if (old.nodeType === Node.ELEMENT_NODE) {
199
+ return old.tagName === next.tagName;
200
+ }
201
+ return false;
202
+ }
203
+ function normalizeChildren(tree) {
204
+ if (Array.isArray(tree))
205
+ return tree;
206
+ // DocumentFragment — extract children
207
+ if (tree.nodeType === Node.DOCUMENT_FRAGMENT_NODE) {
208
+ return Array.from(tree.childNodes);
209
+ }
210
+ return [tree];
211
+ }
212
+ //# sourceMappingURL=morph.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"morph.js","sourceRoot":"","sources":["../src/morph.ts"],"names":[],"mappings":"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"}