@interdead/framework 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 (54) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +86 -0
  3. package/dist/browser/interdead-framework.global.js +319 -0
  4. package/dist/cjs/adapters/hugo-config-source-adapter.js +51 -0
  5. package/dist/cjs/adapters/hugo-config-source-adapter.js.map +1 -0
  6. package/dist/cjs/adapters/js-object-config-source-adapter.js +13 -0
  7. package/dist/cjs/adapters/js-object-config-source-adapter.js.map +1 -0
  8. package/dist/cjs/contracts/framework-config.js +3 -0
  9. package/dist/cjs/contracts/framework-config.js.map +1 -0
  10. package/dist/cjs/contracts/framework-feature.js +3 -0
  11. package/dist/cjs/contracts/framework-feature.js.map +1 -0
  12. package/dist/cjs/core/feature-registry.js +28 -0
  13. package/dist/cjs/core/feature-registry.js.map +1 -0
  14. package/dist/cjs/core/framework-runtime.js +64 -0
  15. package/dist/cjs/core/framework-runtime.js.map +1 -0
  16. package/dist/cjs/features/membrane/membrane-feature.js +87 -0
  17. package/dist/cjs/features/membrane/membrane-feature.js.map +1 -0
  18. package/dist/cjs/features/membrane/membrane-renderer.js +64 -0
  19. package/dist/cjs/features/membrane/membrane-renderer.js.map +1 -0
  20. package/dist/cjs/index.js +25 -0
  21. package/dist/cjs/index.js.map +1 -0
  22. package/dist/cjs/ports/config-source-port.js +3 -0
  23. package/dist/cjs/ports/config-source-port.js.map +1 -0
  24. package/dist/esm/adapters/hugo-config-source-adapter.js +47 -0
  25. package/dist/esm/adapters/hugo-config-source-adapter.js.map +1 -0
  26. package/dist/esm/adapters/js-object-config-source-adapter.js +9 -0
  27. package/dist/esm/adapters/js-object-config-source-adapter.js.map +1 -0
  28. package/dist/esm/contracts/framework-config.js +2 -0
  29. package/dist/esm/contracts/framework-config.js.map +1 -0
  30. package/dist/esm/contracts/framework-feature.js +2 -0
  31. package/dist/esm/contracts/framework-feature.js.map +1 -0
  32. package/dist/esm/core/feature-registry.js +24 -0
  33. package/dist/esm/core/feature-registry.js.map +1 -0
  34. package/dist/esm/core/framework-runtime.js +59 -0
  35. package/dist/esm/core/framework-runtime.js.map +1 -0
  36. package/dist/esm/features/membrane/membrane-feature.js +83 -0
  37. package/dist/esm/features/membrane/membrane-feature.js.map +1 -0
  38. package/dist/esm/features/membrane/membrane-renderer.js +60 -0
  39. package/dist/esm/features/membrane/membrane-renderer.js.map +1 -0
  40. package/dist/esm/index.js +9 -0
  41. package/dist/esm/index.js.map +1 -0
  42. package/dist/esm/ports/config-source-port.js +2 -0
  43. package/dist/esm/ports/config-source-port.js.map +1 -0
  44. package/dist/types/adapters/hugo-config-source-adapter.d.ts +7 -0
  45. package/dist/types/adapters/js-object-config-source-adapter.d.ts +7 -0
  46. package/dist/types/contracts/framework-config.d.ts +21 -0
  47. package/dist/types/contracts/framework-feature.d.ts +7 -0
  48. package/dist/types/core/feature-registry.d.ts +7 -0
  49. package/dist/types/core/framework-runtime.d.ts +18 -0
  50. package/dist/types/features/membrane/membrane-feature.d.ts +21 -0
  51. package/dist/types/features/membrane/membrane-renderer.d.ts +15 -0
  52. package/dist/types/index.d.ts +8 -0
  53. package/dist/types/ports/config-source-port.d.ts +4 -0
  54. package/package.json +51 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) InterDead
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,86 @@
1
+ ## Introduction
2
+
3
+ `@interdead/framework` is the shared UI runtime package for InterDead hosts. It provides a modular feature registry and a stable API for enabling only the needed interactive effects.
4
+
5
+ Current shipped feature set:
6
+
7
+ - `membrane` (interactive horizontal membrane lines with hover/click/touch/focus pulse reaction).
8
+
9
+ ## Installation
10
+
11
+ ```bash
12
+ npm install @interdead/framework
13
+ ```
14
+
15
+ ## Build targets
16
+
17
+ The package builds in three formats:
18
+
19
+ - ESM: `dist/esm`
20
+ - CJS: `dist/cjs`
21
+ - Browser global bundle: `dist/browser/interdead-framework.global.js` (`window.InterdeadFramework`)
22
+
23
+ ## Usage (JavaScript host / InterDeadProto style)
24
+
25
+ ```ts
26
+ import {
27
+ FrameworkRuntime,
28
+ JsObjectConfigSourceAdapter,
29
+ } from '@interdead/framework';
30
+
31
+ const runtime = new FrameworkRuntime(
32
+ new JsObjectConfigSourceAdapter({
33
+ enabledFeatures: { membrane: true },
34
+ featureOptions: {
35
+ membrane: {
36
+ interactionSelectors: ['button', '[data-action]'],
37
+ activeBodyClass: 'proto-membrane-active',
38
+ canvasClassName: 'proto-membrane-canvas',
39
+ reducedMotionMode: 'minimal',
40
+ },
41
+ },
42
+ }),
43
+ );
44
+
45
+ runtime.boot();
46
+ ```
47
+
48
+ ## Usage (Hugo host / InterDeadIT style)
49
+
50
+ ```ts
51
+ import { FrameworkRuntime, HugoConfigSourceAdapter } from '@interdead/framework';
52
+
53
+ const runtime = new FrameworkRuntime(new HugoConfigSourceAdapter(document));
54
+ runtime.boot();
55
+ ```
56
+
57
+ Provide config marker in HTML (recommended on `<body>`):
58
+
59
+ ```html
60
+ <body
61
+ data-interdead-framework="true"
62
+ data-framework-membrane="true"
63
+ data-framework-membrane-selectors="[data-modal-trigger], [data-auth-button], .gm-slider__arrow"
64
+ data-framework-reduced-motion-mode="minimal"
65
+ ></body>
66
+ ```
67
+
68
+ ## Reduced motion
69
+
70
+ - `disable`: do not mount the feature when `prefers-reduced-motion: reduce` is active.
71
+ - `minimal`: mount with reduced membrane profile (lower line count and amplitude).
72
+ - `full`: mount with unchanged profile.
73
+
74
+ ## API
75
+
76
+ - `createInterdeadFramework(config, options)`
77
+ - `FrameworkRuntime` (`boot`, `destroy`)
78
+ - `HugoConfigSourceAdapter`
79
+ - `JsObjectConfigSourceAdapter`
80
+
81
+ ## Release
82
+
83
+ - Tag format: `framework-v0.1.0`
84
+ - Build and tests:
85
+ - `npm run build`
86
+ - `npm test`
@@ -0,0 +1,319 @@
1
+ "use strict";
2
+ var InterdeadFramework = (() => {
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __export = (target, all) => {
8
+ for (var name in all)
9
+ __defProp(target, name, { get: all[name], enumerable: true });
10
+ };
11
+ var __copyProps = (to, from, except, desc) => {
12
+ if (from && typeof from === "object" || typeof from === "function") {
13
+ for (let key of __getOwnPropNames(from))
14
+ if (!__hasOwnProp.call(to, key) && key !== except)
15
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
16
+ }
17
+ return to;
18
+ };
19
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
20
+
21
+ // src/index.ts
22
+ var index_exports = {};
23
+ __export(index_exports, {
24
+ FeatureRegistry: () => FeatureRegistry,
25
+ FrameworkRuntime: () => FrameworkRuntime,
26
+ HugoConfigSourceAdapter: () => HugoConfigSourceAdapter,
27
+ JsObjectConfigSourceAdapter: () => JsObjectConfigSourceAdapter,
28
+ MembraneFeature: () => MembraneFeature,
29
+ createInterdeadFramework: () => createInterdeadFramework
30
+ });
31
+
32
+ // src/adapters/js-object-config-source-adapter.ts
33
+ var JsObjectConfigSourceAdapter = class {
34
+ constructor(config = {}) {
35
+ this.config = config;
36
+ }
37
+ load() {
38
+ return this.config;
39
+ }
40
+ };
41
+
42
+ // src/adapters/hugo-config-source-adapter.ts
43
+ var DEFAULT_SELECTORS = [
44
+ "[data-modal-trigger]",
45
+ "[data-cta-anchor]",
46
+ "[data-auth-button]",
47
+ ".gm-slider__arrow"
48
+ ];
49
+ var HugoConfigSourceAdapter = class {
50
+ constructor(documentRef = document) {
51
+ this.documentRef = documentRef;
52
+ }
53
+ load() {
54
+ const bodyMarker = this.documentRef.body?.hasAttribute(
55
+ "data-interdead-framework"
56
+ ) ? this.documentRef.body : null;
57
+ const marker = bodyMarker || this.documentRef.querySelector("[data-interdead-framework]");
58
+ if (!marker) {
59
+ return {};
60
+ }
61
+ const membraneEnabled = marker.dataset.frameworkMembrane !== "false";
62
+ const selectors = marker.dataset.frameworkMembraneSelectors ? marker.dataset.frameworkMembraneSelectors.split(",").map((item) => item.trim()).filter(Boolean) : DEFAULT_SELECTORS;
63
+ const membraneConfig = {
64
+ canvasClassName: marker.dataset.frameworkMembraneCanvasClass || "gm-membrane-canvas",
65
+ activeBodyClass: marker.dataset.frameworkMembraneActiveClass || "gm-membrane-active",
66
+ interactionSelectors: selectors,
67
+ reducedMotionMode: marker.dataset.frameworkReducedMotionMode === "disable" ? "disable" : marker.dataset.frameworkReducedMotionMode === "full" ? "full" : "minimal"
68
+ };
69
+ return {
70
+ enabledFeatures: {
71
+ membrane: membraneEnabled
72
+ },
73
+ featureOptions: {
74
+ membrane: membraneConfig
75
+ }
76
+ };
77
+ }
78
+ };
79
+
80
+ // src/features/membrane/membrane-renderer.ts
81
+ var DEFAULT_CONFIG = {
82
+ lineCount: 18,
83
+ lineColor: "rgba(138, 229, 144, 0.26)",
84
+ pulseColor: "rgba(198, 110, 72, 0.45)",
85
+ pulseDecay: 0.9,
86
+ amplitude: 5
87
+ };
88
+ var MembraneRenderer = class {
89
+ constructor(canvas, windowRef) {
90
+ this.canvas = canvas;
91
+ this.windowRef = windowRef;
92
+ this.width = 0;
93
+ this.height = 0;
94
+ this.pulse = 0;
95
+ this.pulseX = 0.5;
96
+ this.pulseY = 0.5;
97
+ const context = this.canvas.getContext("2d");
98
+ if (!context) {
99
+ throw new Error("MembraneRenderer requires 2D canvas context.");
100
+ }
101
+ this.ctx = context;
102
+ this.resize();
103
+ }
104
+ resize() {
105
+ this.width = this.windowRef.innerWidth;
106
+ this.height = this.windowRef.innerHeight;
107
+ this.canvas.width = this.width;
108
+ this.canvas.height = this.height;
109
+ }
110
+ triggerPulse(xRatio, yRatio) {
111
+ this.pulse = 1;
112
+ this.pulseX = Math.min(1, Math.max(0, xRatio));
113
+ this.pulseY = Math.min(1, Math.max(0, yRatio));
114
+ }
115
+ draw(time, config = {}) {
116
+ const merged = { ...DEFAULT_CONFIG, ...config };
117
+ const { lineCount, lineColor, pulseColor, pulseDecay, amplitude } = merged;
118
+ this.pulse *= pulseDecay;
119
+ this.ctx.clearRect(0, 0, this.width, this.height);
120
+ const phase = time * 12e-4;
121
+ for (let index = 0; index < lineCount; index += 1) {
122
+ const y = (index + 1) / (lineCount + 1) * this.height;
123
+ const distance = Math.abs(y - this.height * this.pulseY) / this.height;
124
+ const pulseWeight = Math.max(0, 1 - distance * 3) * this.pulse;
125
+ const wobble = Math.sin(phase + index * 0.54) * amplitude * (0.3 + pulseWeight);
126
+ const gradient = this.ctx.createLinearGradient(0, y, this.width, y);
127
+ gradient.addColorStop(0, "rgba(0, 0, 0, 0)");
128
+ gradient.addColorStop(0.5, pulseWeight > 0.01 ? pulseColor : lineColor);
129
+ gradient.addColorStop(1, "rgba(0, 0, 0, 0)");
130
+ this.ctx.strokeStyle = gradient;
131
+ this.ctx.lineWidth = 1 + pulseWeight * 2;
132
+ this.ctx.beginPath();
133
+ this.ctx.moveTo(0, y + wobble);
134
+ this.ctx.lineTo(this.width, y - wobble * 0.2);
135
+ this.ctx.stroke();
136
+ }
137
+ this.ctx.lineWidth = 1;
138
+ }
139
+ };
140
+
141
+ // src/features/membrane/membrane-feature.ts
142
+ var MembraneFeature = class {
143
+ constructor(windowRef = window, documentRef = document) {
144
+ this.windowRef = windowRef;
145
+ this.documentRef = documentRef;
146
+ this.key = "membrane";
147
+ this.animationFrame = 0;
148
+ this.canvas = null;
149
+ this.renderer = null;
150
+ this.boundInteractions = [];
151
+ this.config = {};
152
+ this.appliedBodyClass = null;
153
+ this.handleResize = () => {
154
+ this.renderer?.resize();
155
+ };
156
+ this.tick = () => {
157
+ this.animationFrame = this.windowRef.requestAnimationFrame(this.tick);
158
+ this.renderer?.draw(this.windowRef.performance.now(), this.config);
159
+ };
160
+ }
161
+ mount() {
162
+ if (this.canvas) {
163
+ return;
164
+ }
165
+ this.canvas = this.documentRef.createElement("canvas");
166
+ this.canvas.className = this.config.canvasClassName || "gm-membrane-canvas";
167
+ this.documentRef.body.appendChild(this.canvas);
168
+ this.renderer = new MembraneRenderer(this.canvas, this.windowRef);
169
+ this.windowRef.addEventListener("resize", this.handleResize);
170
+ this.bindInteractions();
171
+ this.appliedBodyClass = this.config.activeBodyClass || "gm-membrane-active";
172
+ this.documentRef.body.classList.add(this.appliedBodyClass);
173
+ this.tick();
174
+ }
175
+ updateConfig(config) {
176
+ this.config = config.featureOptions?.membrane || {};
177
+ }
178
+ destroy() {
179
+ if (this.animationFrame) {
180
+ this.windowRef.cancelAnimationFrame(this.animationFrame);
181
+ this.animationFrame = 0;
182
+ }
183
+ this.windowRef.removeEventListener("resize", this.handleResize);
184
+ this.unbindInteractions();
185
+ this.canvas?.remove();
186
+ this.canvas = null;
187
+ this.renderer = null;
188
+ if (this.appliedBodyClass) {
189
+ this.documentRef.body.classList.remove(this.appliedBodyClass);
190
+ this.appliedBodyClass = null;
191
+ }
192
+ }
193
+ bindInteractions() {
194
+ const selectors = this.config.interactionSelectors || [];
195
+ const uniqueNodes = /* @__PURE__ */ new Set();
196
+ for (const selector of selectors) {
197
+ for (const node of this.documentRef.querySelectorAll(selector)) {
198
+ uniqueNodes.add(node);
199
+ }
200
+ }
201
+ for (const node of uniqueNodes) {
202
+ const handler = () => {
203
+ const rect = node.getBoundingClientRect();
204
+ this.renderer?.triggerPulse(
205
+ (rect.left + rect.width * 0.5) / this.windowRef.innerWidth,
206
+ (rect.top + rect.height * 0.5) / this.windowRef.innerHeight
207
+ );
208
+ };
209
+ node.addEventListener("mouseenter", handler);
210
+ node.addEventListener("focus", handler);
211
+ node.addEventListener("click", handler);
212
+ node.addEventListener("touchstart", handler, { passive: true });
213
+ this.boundInteractions.push({ node, handler });
214
+ }
215
+ }
216
+ unbindInteractions() {
217
+ for (const bound of this.boundInteractions) {
218
+ bound.node.removeEventListener("mouseenter", bound.handler);
219
+ bound.node.removeEventListener("focus", bound.handler);
220
+ bound.node.removeEventListener("click", bound.handler);
221
+ bound.node.removeEventListener("touchstart", bound.handler);
222
+ }
223
+ this.boundInteractions = [];
224
+ }
225
+ };
226
+
227
+ // src/core/feature-registry.ts
228
+ var FeatureRegistry = class {
229
+ constructor() {
230
+ this.factories = /* @__PURE__ */ new Map();
231
+ }
232
+ register(key, factory) {
233
+ this.factories.set(key, factory);
234
+ }
235
+ createEnabled(config = {}) {
236
+ const features = [];
237
+ const keys = Object.keys(config);
238
+ for (const key of keys) {
239
+ if (!config[key]) {
240
+ continue;
241
+ }
242
+ const factory = this.factories.get(key);
243
+ if (!factory) {
244
+ continue;
245
+ }
246
+ features.push(factory());
247
+ }
248
+ return features;
249
+ }
250
+ };
251
+
252
+ // src/core/framework-runtime.ts
253
+ var FrameworkRuntime = class {
254
+ constructor(configSource, options = {}) {
255
+ this.configSource = configSource;
256
+ this.options = options;
257
+ this.registry = new FeatureRegistry();
258
+ this.features = [];
259
+ this.config = {};
260
+ const windowRef = this.options.windowRef || window;
261
+ const documentRef = this.options.documentRef || document;
262
+ this.registry.register(
263
+ "membrane",
264
+ () => new MembraneFeature(windowRef, documentRef)
265
+ );
266
+ }
267
+ boot() {
268
+ this.config = this.configSource.load();
269
+ const windowRef = this.options.windowRef || window;
270
+ const reducedMotionPreferred = windowRef.matchMedia?.(
271
+ "(prefers-reduced-motion: reduce)"
272
+ )?.matches;
273
+ const reducedMode = this.config.featureOptions?.membrane?.reducedMotionMode || "minimal";
274
+ if (reducedMotionPreferred && reducedMode === "disable") {
275
+ return;
276
+ }
277
+ if (reducedMotionPreferred && reducedMode === "minimal") {
278
+ this.applyMinimalMembraneProfile();
279
+ }
280
+ const instances = this.registry.createEnabled(
281
+ this.config.enabledFeatures || {}
282
+ );
283
+ this.features.push(...instances);
284
+ for (const feature of this.features) {
285
+ feature.updateConfig(this.config);
286
+ feature.mount();
287
+ }
288
+ }
289
+ destroy() {
290
+ while (this.features.length > 0) {
291
+ const feature = this.features.pop();
292
+ feature?.destroy();
293
+ }
294
+ }
295
+ applyMinimalMembraneProfile() {
296
+ const membraneConfig = this.config.featureOptions?.membrane || {};
297
+ const reducedConfig = {
298
+ ...membraneConfig,
299
+ lineCount: Math.max(
300
+ 8,
301
+ Math.round((membraneConfig.lineCount || 18) * 0.55)
302
+ ),
303
+ amplitude: (membraneConfig.amplitude || 5) * 0.45,
304
+ pulseDecay: Math.min(0.95, (membraneConfig.pulseDecay || 0.9) + 0.04)
305
+ };
306
+ this.config = {
307
+ ...this.config,
308
+ featureOptions: {
309
+ ...this.config.featureOptions,
310
+ membrane: reducedConfig
311
+ }
312
+ };
313
+ }
314
+ };
315
+ function createInterdeadFramework(config = {}, options = {}) {
316
+ return new FrameworkRuntime(new JsObjectConfigSourceAdapter(config), options);
317
+ }
318
+ return __toCommonJS(index_exports);
319
+ })();
@@ -0,0 +1,51 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.HugoConfigSourceAdapter = void 0;
4
+ const DEFAULT_SELECTORS = [
5
+ "[data-modal-trigger]",
6
+ "[data-cta-anchor]",
7
+ "[data-auth-button]",
8
+ ".gm-slider__arrow",
9
+ ];
10
+ class HugoConfigSourceAdapter {
11
+ constructor(documentRef = document) {
12
+ this.documentRef = documentRef;
13
+ }
14
+ load() {
15
+ const bodyMarker = this.documentRef.body?.hasAttribute("data-interdead-framework")
16
+ ? this.documentRef.body
17
+ : null;
18
+ const marker = bodyMarker ||
19
+ this.documentRef.querySelector("[data-interdead-framework]");
20
+ if (!marker) {
21
+ return {};
22
+ }
23
+ const membraneEnabled = marker.dataset.frameworkMembrane !== "false";
24
+ const selectors = marker.dataset.frameworkMembraneSelectors
25
+ ? marker.dataset.frameworkMembraneSelectors
26
+ .split(",")
27
+ .map((item) => item.trim())
28
+ .filter(Boolean)
29
+ : DEFAULT_SELECTORS;
30
+ const membraneConfig = {
31
+ canvasClassName: marker.dataset.frameworkMembraneCanvasClass || "gm-membrane-canvas",
32
+ activeBodyClass: marker.dataset.frameworkMembraneActiveClass || "gm-membrane-active",
33
+ interactionSelectors: selectors,
34
+ reducedMotionMode: marker.dataset.frameworkReducedMotionMode === "disable"
35
+ ? "disable"
36
+ : marker.dataset.frameworkReducedMotionMode === "full"
37
+ ? "full"
38
+ : "minimal",
39
+ };
40
+ return {
41
+ enabledFeatures: {
42
+ membrane: membraneEnabled,
43
+ },
44
+ featureOptions: {
45
+ membrane: membraneConfig,
46
+ },
47
+ };
48
+ }
49
+ }
50
+ exports.HugoConfigSourceAdapter = HugoConfigSourceAdapter;
51
+ //# sourceMappingURL=hugo-config-source-adapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hugo-config-source-adapter.js","sourceRoot":"","sources":["../../../src/adapters/hugo-config-source-adapter.ts"],"names":[],"mappings":";;;AAMA,MAAM,iBAAiB,GAAG;IACxB,sBAAsB;IACtB,mBAAmB;IACnB,oBAAoB;IACpB,mBAAmB;CACpB,CAAC;AAEF,MAAa,uBAAuB;IAClC,YAA6B,cAAwB,QAAQ;QAAhC,gBAAW,GAAX,WAAW,CAAqB;IAAG,CAAC;IAEjE,IAAI;QACF,MAAM,UAAU,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE,YAAY,CACpD,0BAA0B,CAC3B;YACC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI;YACvB,CAAC,CAAC,IAAI,CAAC;QACT,MAAM,MAAM,GACV,UAAU;YACV,IAAI,CAAC,WAAW,CAAC,aAAa,CAAc,4BAA4B,CAAC,CAAC;QAE5E,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,OAAO,EAAE,CAAC;QACZ,CAAC;QAED,MAAM,eAAe,GAAG,MAAM,CAAC,OAAO,CAAC,iBAAiB,KAAK,OAAO,CAAC;QACrE,MAAM,SAAS,GAAG,MAAM,CAAC,OAAO,CAAC,0BAA0B;YACzD,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,0BAA0B;iBACtC,KAAK,CAAC,GAAG,CAAC;iBACV,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;iBAC1B,MAAM,CAAC,OAAO,CAAC;YACpB,CAAC,CAAC,iBAAiB,CAAC;QAEtB,MAAM,cAAc,GAAmB;YACrC,eAAe,EACb,MAAM,CAAC,OAAO,CAAC,4BAA4B,IAAI,oBAAoB;YACrE,eAAe,EACb,MAAM,CAAC,OAAO,CAAC,4BAA4B,IAAI,oBAAoB;YACrE,oBAAoB,EAAE,SAAS;YAC/B,iBAAiB,EACf,MAAM,CAAC,OAAO,CAAC,0BAA0B,KAAK,SAAS;gBACrD,CAAC,CAAC,SAAS;gBACX,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,0BAA0B,KAAK,MAAM;oBACpD,CAAC,CAAC,MAAM;oBACR,CAAC,CAAC,SAAS;SAClB,CAAC;QAEF,OAAO;YACL,eAAe,EAAE;gBACf,QAAQ,EAAE,eAAe;aAC1B;YACD,cAAc,EAAE;gBACd,QAAQ,EAAE,cAAc;aACzB;SACF,CAAC;IACJ,CAAC;CACF;AAhDD,0DAgDC"}
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.JsObjectConfigSourceAdapter = void 0;
4
+ class JsObjectConfigSourceAdapter {
5
+ constructor(config = {}) {
6
+ this.config = config;
7
+ }
8
+ load() {
9
+ return this.config;
10
+ }
11
+ }
12
+ exports.JsObjectConfigSourceAdapter = JsObjectConfigSourceAdapter;
13
+ //# sourceMappingURL=js-object-config-source-adapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"js-object-config-source-adapter.js","sourceRoot":"","sources":["../../../src/adapters/js-object-config-source-adapter.ts"],"names":[],"mappings":";;;AAGA,MAAa,2BAA2B;IACtC,YAA6B,SAA0B,EAAE;QAA5B,WAAM,GAAN,MAAM,CAAsB;IAAG,CAAC;IAE7D,IAAI;QACF,OAAO,IAAI,CAAC,MAAM,CAAC;IACrB,CAAC;CACF;AAND,kEAMC"}
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=framework-config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"framework-config.js","sourceRoot":"","sources":["../../../src/contracts/framework-config.ts"],"names":[],"mappings":""}
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=framework-feature.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"framework-feature.js","sourceRoot":"","sources":["../../../src/contracts/framework-feature.ts"],"names":[],"mappings":""}
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.FeatureRegistry = void 0;
4
+ class FeatureRegistry {
5
+ constructor() {
6
+ this.factories = new Map();
7
+ }
8
+ register(key, factory) {
9
+ this.factories.set(key, factory);
10
+ }
11
+ createEnabled(config = {}) {
12
+ const features = [];
13
+ const keys = Object.keys(config);
14
+ for (const key of keys) {
15
+ if (!config[key]) {
16
+ continue;
17
+ }
18
+ const factory = this.factories.get(key);
19
+ if (!factory) {
20
+ continue;
21
+ }
22
+ features.push(factory());
23
+ }
24
+ return features;
25
+ }
26
+ }
27
+ exports.FeatureRegistry = FeatureRegistry;
28
+ //# sourceMappingURL=feature-registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"feature-registry.js","sourceRoot":"","sources":["../../../src/core/feature-registry.ts"],"names":[],"mappings":";;;AAMA,MAAa,eAAe;IAA5B;QACmB,cAAS,GAAG,IAAI,GAAG,EAGjC,CAAC;IAyBN,CAAC;IAvBC,QAAQ,CAAC,GAAwB,EAAE,OAA+B;QAChE,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;IACnC,CAAC;IAED,aAAa,CAAC,SAAgC,EAAE;QAC9C,MAAM,QAAQ,GAAuB,EAAE,CAAC;QACxC,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAA0B,CAAC;QAE1D,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;YACvB,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;gBACjB,SAAS;YACX,CAAC;YAED,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YACxC,IAAI,CAAC,OAAO,EAAE,CAAC;gBACb,SAAS;YACX,CAAC;YAED,QAAQ,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;QAC3B,CAAC;QAED,OAAO,QAAQ,CAAC;IAClB,CAAC;CACF;AA7BD,0CA6BC"}
@@ -0,0 +1,64 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.FrameworkRuntime = void 0;
4
+ exports.createInterdeadFramework = createInterdeadFramework;
5
+ const js_object_config_source_adapter_js_1 = require("../adapters/js-object-config-source-adapter.js");
6
+ const membrane_feature_js_1 = require("../features/membrane/membrane-feature.js");
7
+ const feature_registry_js_1 = require("./feature-registry.js");
8
+ class FrameworkRuntime {
9
+ constructor(configSource, options = {}) {
10
+ this.configSource = configSource;
11
+ this.options = options;
12
+ this.registry = new feature_registry_js_1.FeatureRegistry();
13
+ this.features = [];
14
+ this.config = {};
15
+ const windowRef = this.options.windowRef || window;
16
+ const documentRef = this.options.documentRef || document;
17
+ this.registry.register("membrane", () => new membrane_feature_js_1.MembraneFeature(windowRef, documentRef));
18
+ }
19
+ boot() {
20
+ this.config = this.configSource.load();
21
+ const windowRef = this.options.windowRef || window;
22
+ const reducedMotionPreferred = windowRef.matchMedia?.("(prefers-reduced-motion: reduce)")?.matches;
23
+ const reducedMode = this.config.featureOptions?.membrane?.reducedMotionMode || "minimal";
24
+ if (reducedMotionPreferred && reducedMode === "disable") {
25
+ return;
26
+ }
27
+ if (reducedMotionPreferred && reducedMode === "minimal") {
28
+ this.applyMinimalMembraneProfile();
29
+ }
30
+ const instances = this.registry.createEnabled(this.config.enabledFeatures || {});
31
+ this.features.push(...instances);
32
+ for (const feature of this.features) {
33
+ feature.updateConfig(this.config);
34
+ feature.mount();
35
+ }
36
+ }
37
+ destroy() {
38
+ while (this.features.length > 0) {
39
+ const feature = this.features.pop();
40
+ feature?.destroy();
41
+ }
42
+ }
43
+ applyMinimalMembraneProfile() {
44
+ const membraneConfig = this.config.featureOptions?.membrane || {};
45
+ const reducedConfig = {
46
+ ...membraneConfig,
47
+ lineCount: Math.max(8, Math.round((membraneConfig.lineCount || 18) * 0.55)),
48
+ amplitude: (membraneConfig.amplitude || 5) * 0.45,
49
+ pulseDecay: Math.min(0.95, (membraneConfig.pulseDecay || 0.9) + 0.04),
50
+ };
51
+ this.config = {
52
+ ...this.config,
53
+ featureOptions: {
54
+ ...this.config.featureOptions,
55
+ membrane: reducedConfig,
56
+ },
57
+ };
58
+ }
59
+ }
60
+ exports.FrameworkRuntime = FrameworkRuntime;
61
+ function createInterdeadFramework(config = {}, options = {}) {
62
+ return new FrameworkRuntime(new js_object_config_source_adapter_js_1.JsObjectConfigSourceAdapter(config), options);
63
+ }
64
+ //# sourceMappingURL=framework-runtime.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"framework-runtime.js","sourceRoot":"","sources":["../../../src/core/framework-runtime.ts"],"names":[],"mappings":"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"}