@hypertools/sdk 0.2.1 → 0.3.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.
@@ -0,0 +1,118 @@
1
+ /**
2
+ * ExperienceController - Control exported HyperTools experiences programmatically
3
+ *
4
+ * Use this to connect to and control exported web components from the SDK.
5
+ * The exported experience has its initial state packaged, but you can
6
+ * override params, listen to events, and control it via this API.
7
+ *
8
+ * @example
9
+ * ```typescript
10
+ * import { ExperienceController } from '@hypertools/sdk';
11
+ *
12
+ * // Get the exported web component
13
+ * const element = document.querySelector('my-experience');
14
+ *
15
+ * // Connect SDK controller
16
+ * const controller = new ExperienceController(element);
17
+ *
18
+ * // Control programmatically
19
+ * controller.setParam('speed', 5);
20
+ * controller.on('paramchange', (e) => console.log(e.detail));
21
+ *
22
+ * // Later, disconnect
23
+ * controller.destroy();
24
+ * ```
25
+ */
26
+ import { type ExperienceEvent, type EventHandler } from './EventEmitter';
27
+ /**
28
+ * Interface for exported HyperTools web components
29
+ */
30
+ export interface ExportedExperienceElement extends HTMLElement {
31
+ setParam(key: string, value: unknown): void;
32
+ setParams(params: Record<string, unknown>): void;
33
+ getParams(): Record<string, unknown>;
34
+ getParamDefs(): Record<string, {
35
+ type: string;
36
+ value: unknown;
37
+ [key: string]: unknown;
38
+ }>;
39
+ }
40
+ export interface ExperienceControllerConfig {
41
+ /** The exported web component element */
42
+ element: ExportedExperienceElement;
43
+ /** Initial param overrides (applied on connect) */
44
+ initialParams?: Record<string, unknown>;
45
+ /** Auto-connect on creation (default: true) */
46
+ autoConnect?: boolean;
47
+ }
48
+ export declare class ExperienceController {
49
+ private _element;
50
+ private _events;
51
+ private _isConnected;
52
+ private _isDestroyed;
53
+ private _boundReadyHandler;
54
+ private _boundParamChangeHandler;
55
+ constructor(elementOrConfig: ExportedExperienceElement | ExperienceControllerConfig);
56
+ /**
57
+ * Connect to the web component and start listening to events
58
+ */
59
+ connect(): void;
60
+ /**
61
+ * Disconnect from the web component
62
+ */
63
+ disconnect(): void;
64
+ get element(): ExportedExperienceElement;
65
+ get isConnected(): boolean;
66
+ get isDestroyed(): boolean;
67
+ /**
68
+ * Set a single parameter
69
+ */
70
+ setParam(key: string, value: unknown): void;
71
+ /**
72
+ * Set multiple parameters at once
73
+ */
74
+ setParams(params: Record<string, unknown>): void;
75
+ /**
76
+ * Get current parameter values
77
+ */
78
+ getParams(): Record<string, unknown>;
79
+ /**
80
+ * Get parameter definitions (types, ranges, etc.)
81
+ */
82
+ getParamDefs(): Record<string, {
83
+ type: string;
84
+ value: unknown;
85
+ [key: string]: unknown;
86
+ }>;
87
+ /**
88
+ * Reset parameters to their default values
89
+ */
90
+ resetParams(): void;
91
+ /**
92
+ * Subscribe to an event
93
+ */
94
+ on<T extends ExperienceEvent>(type: T['type'], handler: EventHandler<T>): () => void;
95
+ /**
96
+ * Subscribe to an event once
97
+ */
98
+ once<T extends ExperienceEvent>(type: T['type'], handler: EventHandler<T>): () => void;
99
+ /**
100
+ * Unsubscribe from an event
101
+ */
102
+ off<T extends ExperienceEvent>(type: T['type'], handler: EventHandler<T>): void;
103
+ /**
104
+ * Destroy the controller and disconnect from the element
105
+ */
106
+ destroy(): void;
107
+ private _handleReady;
108
+ private _handleParamChange;
109
+ /**
110
+ * Connect to an experience by CSS selector
111
+ */
112
+ static fromSelector(selector: string, initialParams?: Record<string, unknown>): ExperienceController;
113
+ /**
114
+ * Wait for element to be defined, then connect
115
+ */
116
+ static whenDefined(tagName: string, initialParams?: Record<string, unknown>): Promise<ExperienceController>;
117
+ }
118
+ //# sourceMappingURL=ExperienceController.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ExperienceController.d.ts","sourceRoot":"","sources":["../../src/core/ExperienceController.ts"],"names":[],"mappings":"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"}
@@ -3,6 +3,8 @@
3
3
  */
4
4
  export { Experience } from './Experience';
5
5
  export type { ExperienceConfig, ExperienceContext, ExportsApi, EnvironmentApi, SetupFunction, CleanupFunction, CaptureHandler, } from './Experience';
6
+ export { ExperienceController } from './ExperienceController';
7
+ export type { ExportedExperienceElement, ExperienceControllerConfig, } from './ExperienceController';
6
8
  export { ParamStore } from './ParamStore';
7
9
  export type { ParamType, ParamDefinition, ParamDefinitions, ParamValues, ParamChangeCallback, SelectOption, } from './ParamStore';
8
10
  export { EventEmitter } from './EventEmitter';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,YAAY,EACV,gBAAgB,EAChB,iBAAiB,EACjB,UAAU,EACV,cAAc,EACd,aAAa,EACb,eAAe,EACf,cAAc,GACf,MAAM,cAAc,CAAC;AAEtB,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,YAAY,EACV,SAAS,EACT,eAAe,EACf,gBAAgB,EAChB,WAAW,EACX,mBAAmB,EACnB,YAAY,GACb,MAAM,cAAc,CAAC;AAEtB,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,YAAY,EACV,mBAAmB,EACnB,eAAe,EACf,UAAU,EACV,UAAU,EACV,UAAU,EACV,WAAW,EACX,gBAAgB,EAChB,SAAS,EACT,UAAU,EACV,qBAAqB,EACrB,uBAAuB,EACvB,YAAY,GACb,MAAM,gBAAgB,CAAC;AAExB,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,YAAY,EACV,gBAAgB,EAChB,wBAAwB,EACxB,0BAA0B,GAC3B,MAAM,kBAAkB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,YAAY,EACV,gBAAgB,EAChB,iBAAiB,EACjB,UAAU,EACV,cAAc,EACd,aAAa,EACb,eAAe,EACf,cAAc,GACf,MAAM,cAAc,CAAC;AAEtB,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAC9D,YAAY,EACV,yBAAyB,EACzB,0BAA0B,GAC3B,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,YAAY,EACV,SAAS,EACT,eAAe,EACf,gBAAgB,EAChB,WAAW,EACX,mBAAmB,EACnB,YAAY,GACb,MAAM,cAAc,CAAC;AAEtB,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,YAAY,EACV,mBAAmB,EACnB,eAAe,EACf,UAAU,EACV,UAAU,EACV,UAAU,EACV,WAAW,EACX,gBAAgB,EAChB,SAAS,EACT,UAAU,EACV,qBAAqB,EACrB,uBAAuB,EACvB,YAAY,GACb,MAAM,gBAAgB,CAAC;AAExB,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,YAAY,EACV,gBAAgB,EAChB,wBAAwB,EACxB,0BAA0B,GAC3B,MAAM,kBAAkB,CAAC"}
@@ -8,8 +8,8 @@
8
8
  * @license MIT
9
9
  * @see https://github.com/hypertools/sdk
10
10
  */
11
- class H{_handlers=new Map;on(E,x){if(!this._handlers.has(E))this._handlers.set(E,new Set);return this._handlers.get(E).add(x),()=>this.off(E,x)}once(E,x){let C=(P)=>{this.off(E,C),x(P)};return this.on(E,C)}off(E,x){let C=this._handlers.get(E);if(C)C.delete(x)}emit(E){let x=this._handlers.get(E.type);if(!x)return;for(let C of x)try{C(E)}catch(P){console.error(`[EventEmitter] Handler error for ${E.type}:`,P)}}removeAllListeners(E){if(E)this._handlers.delete(E);else this._handlers.clear()}listenerCount(E){return this._handlers.get(E)?.size??0}}class O{_definitions;_values;_listeners;_proxy;constructor(E,x){this._definitions=E,this._listeners=new Set,this._values={};for(let[C,P]of Object.entries(E))this._values[C]=P.value;if(x){for(let[C,P]of Object.entries(x))if(C in this._definitions)this._values[C]=this._validate(C,P)}this._proxy=this._createProxy()}_createProxy(){let E=this;return new Proxy(this._values,{get(x,C){return x[C]},set(x,C,P){if(!(C in E._definitions))return console.warn(`[ParamStore] Unknown parameter: ${C}`),!1;let R=E._validate(C,P),D=x[C];if(R!==D)x[C]=R,E._notify(C,R,D);return!0},has(x,C){return C in x},ownKeys(x){return Object.keys(x)},getOwnPropertyDescriptor(x,C){if(C in x)return{enumerable:!0,configurable:!0,value:x[C]};return}})}_validate(E,x){let C=this._definitions[E];if(!C)return x;switch(C.type){case"number":{let P=typeof x==="number"?x:parseFloat(String(x));if(isNaN(P))P=C.value;if(C.min!==void 0)P=Math.max(C.min,P);if(C.max!==void 0)P=Math.min(C.max,P);if(C.step!==void 0)P=Math.round(P/C.step)*C.step;return P}case"color":{let P=String(x);if(/^#[0-9A-Fa-f]{6}$/.test(P))return P;if(/^#[0-9A-Fa-f]{3}$/.test(P))return P;if(/^#[0-9A-Fa-f]{8}$/.test(P))return P;if(/^rgb\(/.test(P))return P;if(/^rgba\(/.test(P))return P;if(/^hsl\(/.test(P))return P;if(/^hsla\(/.test(P))return P;return C.value}case"boolean":if(typeof x==="boolean")return x;if(x==="true"||x==="1")return!0;if(x==="false"||x==="0")return!1;return Boolean(x);case"string":return String(x);case"select":{let P=String(x);return(C.options||[]).some((F)=>typeof F==="object"?F.value===P:F===P)?P:C.value}case"point2d":{if(typeof x==="object"&&x!==null&&"x"in x&&"y"in x)return{x:Number(x.x),y:Number(x.y)};return C.value}case"point3d":{if(typeof x==="object"&&x!==null&&"x"in x&&"y"in x&&"z"in x)return{x:Number(x.x),y:Number(x.y),z:Number(x.z)};return C.value}default:return x}}_notify(E,x,C){for(let P of this._listeners)try{P(E,x,C)}catch(R){console.error("[ParamStore] Listener error:",R)}}getProxy(){return this._proxy}getSnapshot(){return{...this._values}}getDefinitions(){return{...this._definitions}}set(E,x){this._proxy[E]=x}setMultiple(E){for(let[x,C]of Object.entries(E))this._proxy[x]=C}reset(){for(let[E,x]of Object.entries(this._definitions))this._proxy[E]=x.value}subscribe(E){return this._listeners.add(E),()=>this._listeners.delete(E)}addDefinition(E,x){this._definitions[E]=x,this._values[E]=x.value}}class S{_byName=new Map;_byId=new Map;_onRegister=new Set;_onUnregister=new Set;register(E,x,C){if(this._byName.has(E))this.unregister(E);let P=this._generateId(),R={name:E,id:P,object:x,metadata:C};this._byName.set(E,R),this._byId.set(P,R);for(let D of this._onRegister)try{D(E,P,x)}catch(F){console.error("[ObjectRegistry] onRegister callback error:",F)}return P}unregister(E){let x=this._byName.get(E);if(!x)return!1;this._byName.delete(E),this._byId.delete(x.id);for(let C of this._onUnregister)try{C(E)}catch(P){console.error("[ObjectRegistry] onUnregister callback error:",P)}return!0}findByName(E){return this._byName.get(E)?.object}findById(E){return this._byId.get(E)?.object}getInfo(E){return this._byName.get(E)}has(E){return this._byName.has(E)}getNames(){return Array.from(this._byName.keys())}getAll(){let E=new Map;for(let[x,C]of this._byName)E.set(x,C.object);return E}query(E){let x=[];for(let C of this._byName.values())if(E(C))x.push(C);return x}findByType(E){return this.query((x)=>x.metadata?.type===E).map((x)=>x.object)}clear(){let E=Array.from(this._byName.keys());for(let x of E)this.unregister(x)}onRegister(E){return this._onRegister.add(E),()=>this._onRegister.delete(E)}onUnregister(E){return this._onUnregister.add(E),()=>this._onUnregister.delete(E)}get size(){return this._byName.size}_generateId(){return`obj_${Date.now()}_${Math.random().toString(36).slice(2,9)}`}}class U{_isReady=!1;_isPlaying=!1;_isDestroyed=!1;_currentFrame=0;_paramStore;_events;_objects;_mount;_frameRate;_filename="capture";_cleanups=[];_userCleanup;_animationFrameId;_lastFrameTime=0;_resizeObserver;_captureHandler;constructor(E){if(this._mount=E.mount,this._frameRate=E.frameRate??60,E.background)this._mount.style.background=E.background;this._paramStore=new O(E.paramDefs??{},E.initialParams),this._events=new H,this._objects=new S,this._paramStore.subscribe((x,C,P)=>{this._events.emit({type:"paramChange",timestamp:Date.now(),key:x,value:C,previousValue:P})}),this._setupResizeObserver(),this._runSetup(E.setup,E.autoplay??!0)}get isReady(){return this._isReady}get isPlaying(){return this._isPlaying}get isDestroyed(){return this._isDestroyed}get currentFrame(){return this._currentFrame}get mount(){return this._mount}get params(){return this._paramStore.getProxy()}get events(){return this._events}get objects(){return this._objects}setParam(E,x){this._paramStore.set(E,x)}setParams(E){this._paramStore.setMultiple(E)}getParams(){return this._paramStore.getSnapshot()}getParamDefs(){return this._paramStore.getDefinitions()}resetParams(){this._paramStore.reset()}registerObject(E,x,C){return this._objects.register(E,x,C)}findObjectByName(E){return this._objects.findByName(E)}findObjectById(E){return this._objects.findById(E)}getAllObjects(){return this._objects.getAll()}play(){if(this._isPlaying||this._isDestroyed)return;this._isPlaying=!0,this._lastFrameTime=performance.now(),this._tick(),this._events.emit({type:"play",timestamp:Date.now()})}pause(){if(!this._isPlaying)return;if(this._isPlaying=!1,this._animationFrameId)cancelAnimationFrame(this._animationFrameId),this._animationFrameId=void 0;this._events.emit({type:"pause",timestamp:Date.now()})}toggle(){if(this._isPlaying)this.pause();else this.play()}on(E,x){return this._events.on(E,x)}once(E,x){return this._events.once(E,x)}off(E,x){this._events.off(E,x)}async captureImage(E="png"){if(this._captureHandler)return this._captureHandler(E);let x=this._mount.querySelector("canvas");if(!x)return console.warn("[Experience] No canvas found for capture"),null;return new Promise((C)=>{let P=`image/${E}`,R=E==="jpeg"?0.92:void 0;x.toBlob((D)=>C(D),P,R)})}getFilename(){return this._filename}addCleanup(E){if(typeof E==="function")this._cleanups.push(E)}destroy(){if(this._isDestroyed)return;if(this._isDestroyed=!0,this.pause(),this._userCleanup)try{this._userCleanup()}catch(E){console.error("[Experience] User cleanup error:",E)}while(this._cleanups.length>0){let E=this._cleanups.pop();if(E)try{E()}catch(x){console.error("[Experience] Cleanup error:",x)}}this._resizeObserver?.disconnect(),this._objects.clear(),this._events.removeAllListeners(),this._events.emit({type:"destroyed",timestamp:Date.now()})}async _runSetup(E,x){try{let C=this._createContext(),P=await E(C);if(typeof P==="function")this._userCleanup=P;if(this._isReady=!0,this._events.emit({type:"ready",timestamp:Date.now()}),x)this.play()}catch(C){console.error("[Experience] Setup error:",C),this._events.emit({type:"error",timestamp:Date.now(),error:C instanceof Error?C:Error(String(C))})}}_createContext(){return{mount:this._mount,params:this._paramStore.getProxy(),exports:this._createExportsApi(),environment:this._createEnvironmentApi(),registerObject:(E,x,C)=>this._objects.register(E,x,C),findObjectByName:(E)=>this._objects.findByName(E),experience:this}}_createExportsApi(){return{captureImage:(E)=>this.captureImage(E),setFilename:(E)=>{this._filename=E},registerCaptureHandler:(E)=>{this._captureHandler=E}}}_createEnvironmentApi(){return{window,document,onResize:(E)=>{let x=()=>{E(this._mount.clientWidth,this._mount.clientHeight)};x();let C=new ResizeObserver(x);C.observe(this._mount);let P=()=>C.disconnect();return this._cleanups.push(P),P},addCleanup:(E)=>this.addCleanup(E)}}_setupResizeObserver(){this._resizeObserver=new ResizeObserver((E)=>{for(let x of E){let{width:C,height:P}=x.contentRect;this._events.emit({type:"resize",timestamp:Date.now(),width:C,height:P})}}),this._resizeObserver.observe(this._mount)}_tick(){if(!this._isPlaying)return;let E=performance.now(),x=E-this._lastFrameTime,C=1000/this._frameRate;if(x>=C)this._currentFrame++,this._lastFrameTime=E-x%C,this._events.emit({type:"frame",timestamp:Date.now(),frame:this._currentFrame,deltaTime:x});this._animationFrameId=requestAnimationFrame(()=>this._tick())}}export{O as ParamStore,S as ObjectRegistry,U as Experience,H as EventEmitter};
11
+ class F{_handlers=new Map;on(x,E){if(!this._handlers.has(x))this._handlers.set(x,new Set);return this._handlers.get(x).add(E),()=>this.off(x,E)}once(x,E){let R=(P)=>{this.off(x,R),E(P)};return this.on(x,R)}off(x,E){let R=this._handlers.get(x);if(R)R.delete(E)}emit(x){let E=this._handlers.get(x.type);if(!E)return;for(let R of E)try{R(x)}catch(P){console.error(`[EventEmitter] Handler error for ${x.type}:`,P)}}removeAllListeners(x){if(x)this._handlers.delete(x);else this._handlers.clear()}listenerCount(x){return this._handlers.get(x)?.size??0}}class S{_definitions;_values;_listeners;_proxy;constructor(x,E){this._definitions=x,this._listeners=new Set,this._values={};for(let[R,P]of Object.entries(x))this._values[R]=P.value;if(E){for(let[R,P]of Object.entries(E))if(R in this._definitions)this._values[R]=this._validate(R,P)}this._proxy=this._createProxy()}_createProxy(){let x=this;return new Proxy(this._values,{get(E,R){return E[R]},set(E,R,P){if(!(R in x._definitions))return console.warn(`[ParamStore] Unknown parameter: ${R}`),!1;let C=x._validate(R,P),D=E[R];if(C!==D)E[R]=C,x._notify(R,C,D);return!0},has(E,R){return R in E},ownKeys(E){return Object.keys(E)},getOwnPropertyDescriptor(E,R){if(R in E)return{enumerable:!0,configurable:!0,value:E[R]};return}})}_validate(x,E){let R=this._definitions[x];if(!R)return E;switch(R.type){case"number":{let P=typeof E==="number"?E:parseFloat(String(E));if(isNaN(P))P=R.value;if(R.min!==void 0)P=Math.max(R.min,P);if(R.max!==void 0)P=Math.min(R.max,P);if(R.step!==void 0)P=Math.round(P/R.step)*R.step;return P}case"color":{let P=String(E);if(/^#[0-9A-Fa-f]{6}$/.test(P))return P;if(/^#[0-9A-Fa-f]{3}$/.test(P))return P;if(/^#[0-9A-Fa-f]{8}$/.test(P))return P;if(/^rgb\(/.test(P))return P;if(/^rgba\(/.test(P))return P;if(/^hsl\(/.test(P))return P;if(/^hsla\(/.test(P))return P;return R.value}case"boolean":if(typeof E==="boolean")return E;if(E==="true"||E==="1")return!0;if(E==="false"||E==="0")return!1;return Boolean(E);case"string":return String(E);case"select":{let P=String(E);return(R.options||[]).some((H)=>typeof H==="object"?H.value===P:H===P)?P:R.value}case"point2d":{if(typeof E==="object"&&E!==null&&"x"in E&&"y"in E)return{x:Number(E.x),y:Number(E.y)};return R.value}case"point3d":{if(typeof E==="object"&&E!==null&&"x"in E&&"y"in E&&"z"in E)return{x:Number(E.x),y:Number(E.y),z:Number(E.z)};return R.value}default:return E}}_notify(x,E,R){for(let P of this._listeners)try{P(x,E,R)}catch(C){console.error("[ParamStore] Listener error:",C)}}getProxy(){return this._proxy}getSnapshot(){return{...this._values}}getDefinitions(){return{...this._definitions}}set(x,E){this._proxy[x]=E}setMultiple(x){for(let[E,R]of Object.entries(x))this._proxy[E]=R}reset(){for(let[x,E]of Object.entries(this._definitions))this._proxy[x]=E.value}subscribe(x){return this._listeners.add(x),()=>this._listeners.delete(x)}addDefinition(x,E){this._definitions[x]=E,this._values[x]=E.value}}class U{_byName=new Map;_byId=new Map;_onRegister=new Set;_onUnregister=new Set;register(x,E,R){if(this._byName.has(x))this.unregister(x);let P=this._generateId(),C={name:x,id:P,object:E,metadata:R};this._byName.set(x,C),this._byId.set(P,C);for(let D of this._onRegister)try{D(x,P,E)}catch(H){console.error("[ObjectRegistry] onRegister callback error:",H)}return P}unregister(x){let E=this._byName.get(x);if(!E)return!1;this._byName.delete(x),this._byId.delete(E.id);for(let R of this._onUnregister)try{R(x)}catch(P){console.error("[ObjectRegistry] onUnregister callback error:",P)}return!0}findByName(x){return this._byName.get(x)?.object}findById(x){return this._byId.get(x)?.object}getInfo(x){return this._byName.get(x)}has(x){return this._byName.has(x)}getNames(){return Array.from(this._byName.keys())}getAll(){let x=new Map;for(let[E,R]of this._byName)x.set(E,R.object);return x}query(x){let E=[];for(let R of this._byName.values())if(x(R))E.push(R);return E}findByType(x){return this.query((E)=>E.metadata?.type===x).map((E)=>E.object)}clear(){let x=Array.from(this._byName.keys());for(let E of x)this.unregister(E)}onRegister(x){return this._onRegister.add(x),()=>this._onRegister.delete(x)}onUnregister(x){return this._onUnregister.add(x),()=>this._onUnregister.delete(x)}get size(){return this._byName.size}_generateId(){return`obj_${Date.now()}_${Math.random().toString(36).slice(2,9)}`}}class K{_isReady=!1;_isPlaying=!1;_isDestroyed=!1;_currentFrame=0;_paramStore;_events;_objects;_mount;_frameRate;_filename="capture";_cleanups=[];_userCleanup;_animationFrameId;_lastFrameTime=0;_resizeObserver;_captureHandler;constructor(x){if(this._mount=x.mount,this._frameRate=x.frameRate??60,x.background)this._mount.style.background=x.background;this._paramStore=new S(x.paramDefs??{},x.initialParams),this._events=new F,this._objects=new U,this._paramStore.subscribe((E,R,P)=>{this._events.emit({type:"paramChange",timestamp:Date.now(),key:E,value:R,previousValue:P})}),this._setupResizeObserver(),this._runSetup(x.setup,x.autoplay??!0)}get isReady(){return this._isReady}get isPlaying(){return this._isPlaying}get isDestroyed(){return this._isDestroyed}get currentFrame(){return this._currentFrame}get mount(){return this._mount}get params(){return this._paramStore.getProxy()}get events(){return this._events}get objects(){return this._objects}setParam(x,E){this._paramStore.set(x,E)}setParams(x){this._paramStore.setMultiple(x)}getParams(){return this._paramStore.getSnapshot()}getParamDefs(){return this._paramStore.getDefinitions()}resetParams(){this._paramStore.reset()}registerObject(x,E,R){return this._objects.register(x,E,R)}findObjectByName(x){return this._objects.findByName(x)}findObjectById(x){return this._objects.findById(x)}getAllObjects(){return this._objects.getAll()}play(){if(this._isPlaying||this._isDestroyed)return;this._isPlaying=!0,this._lastFrameTime=performance.now(),this._tick(),this._events.emit({type:"play",timestamp:Date.now()})}pause(){if(!this._isPlaying)return;if(this._isPlaying=!1,this._animationFrameId)cancelAnimationFrame(this._animationFrameId),this._animationFrameId=void 0;this._events.emit({type:"pause",timestamp:Date.now()})}toggle(){if(this._isPlaying)this.pause();else this.play()}on(x,E){return this._events.on(x,E)}once(x,E){return this._events.once(x,E)}off(x,E){this._events.off(x,E)}async captureImage(x="png"){if(this._captureHandler)return this._captureHandler(x);let E=this._mount.querySelector("canvas");if(!E)return console.warn("[Experience] No canvas found for capture"),null;return new Promise((R)=>{let P=`image/${x}`,C=x==="jpeg"?0.92:void 0;E.toBlob((D)=>R(D),P,C)})}getFilename(){return this._filename}addCleanup(x){if(typeof x==="function")this._cleanups.push(x)}destroy(){if(this._isDestroyed)return;if(this._isDestroyed=!0,this.pause(),this._userCleanup)try{this._userCleanup()}catch(x){console.error("[Experience] User cleanup error:",x)}while(this._cleanups.length>0){let x=this._cleanups.pop();if(x)try{x()}catch(E){console.error("[Experience] Cleanup error:",E)}}this._resizeObserver?.disconnect(),this._objects.clear(),this._events.removeAllListeners(),this._events.emit({type:"destroyed",timestamp:Date.now()})}async _runSetup(x,E){try{let R=this._createContext(),P=await x(R);if(typeof P==="function")this._userCleanup=P;if(this._isReady=!0,this._events.emit({type:"ready",timestamp:Date.now()}),E)this.play()}catch(R){console.error("[Experience] Setup error:",R),this._events.emit({type:"error",timestamp:Date.now(),error:R instanceof Error?R:Error(String(R))})}}_createContext(){return{mount:this._mount,params:this._paramStore.getProxy(),exports:this._createExportsApi(),environment:this._createEnvironmentApi(),registerObject:(x,E,R)=>this._objects.register(x,E,R),findObjectByName:(x)=>this._objects.findByName(x),experience:this}}_createExportsApi(){return{captureImage:(x)=>this.captureImage(x),setFilename:(x)=>{this._filename=x},registerCaptureHandler:(x)=>{this._captureHandler=x}}}_createEnvironmentApi(){return{window,document,onResize:(x)=>{let E=()=>{x(this._mount.clientWidth,this._mount.clientHeight)};E();let R=new ResizeObserver(E);R.observe(this._mount);let P=()=>R.disconnect();return this._cleanups.push(P),P},addCleanup:(x)=>this.addCleanup(x)}}_setupResizeObserver(){this._resizeObserver=new ResizeObserver((x)=>{for(let E of x){let{width:R,height:P}=E.contentRect;this._events.emit({type:"resize",timestamp:Date.now(),width:R,height:P})}}),this._resizeObserver.observe(this._mount)}_tick(){if(!this._isPlaying)return;let x=performance.now(),E=x-this._lastFrameTime,R=1000/this._frameRate;if(E>=R)this._currentFrame++,this._lastFrameTime=x-E%R,this._events.emit({type:"frame",timestamp:Date.now(),frame:this._currentFrame,deltaTime:E});this._animationFrameId=requestAnimationFrame(()=>this._tick())}}class A{_element;_events;_isConnected=!1;_isDestroyed=!1;_boundReadyHandler;_boundParamChangeHandler;constructor(x){let E=x instanceof HTMLElement?{element:x}:x;if(this._element=E.element,this._events=new F,this._boundReadyHandler=this._handleReady.bind(this),this._boundParamChangeHandler=this._handleParamChange.bind(this),E.autoConnect!==!1){if(this.connect(),E.initialParams)this.setParams(E.initialParams)}}connect(){if(this._isConnected||this._isDestroyed)return;this._element.addEventListener("ready",this._boundReadyHandler),this._element.addEventListener("paramchange",this._boundParamChangeHandler),this._isConnected=!0,this._events.emit({type:"connected",timestamp:Date.now()})}disconnect(){if(!this._isConnected)return;this._element.removeEventListener("ready",this._boundReadyHandler),this._element.removeEventListener("paramchange",this._boundParamChangeHandler),this._isConnected=!1,this._events.emit({type:"disconnected",timestamp:Date.now()})}get element(){return this._element}get isConnected(){return this._isConnected}get isDestroyed(){return this._isDestroyed}setParam(x,E){this._element.setParam(x,E)}setParams(x){this._element.setParams(x)}getParams(){return this._element.getParams()}getParamDefs(){return this._element.getParamDefs()}resetParams(){let x=this.getParamDefs(),E={};for(let[R,P]of Object.entries(x))E[R]=P.value;this.setParams(E)}on(x,E){return this._events.on(x,E)}once(x,E){return this._events.once(x,E)}off(x,E){this._events.off(x,E)}destroy(){if(this._isDestroyed)return;this.disconnect(),this._events.removeAllListeners(),this._isDestroyed=!0,this._events.emit({type:"destroyed",timestamp:Date.now()})}_handleReady(x){this._events.emit({type:"ready",timestamp:Date.now()})}_handleParamChange(x){let E=x;this._events.emit({type:"paramChange",timestamp:Date.now(),key:E.detail.key,value:E.detail.value,previousValue:E.detail.previousValue})}static fromSelector(x,E){let R=document.querySelector(x);if(!R)throw Error(`[ExperienceController] Element not found: ${x}`);return new A({element:R,initialParams:E})}static async whenDefined(x,E){await customElements.whenDefined(x);let R=document.querySelector(x);if(!R)R=document.createElement(x);return new A({element:R,initialParams:E})}}export{S as ParamStore,U as ObjectRegistry,A as ExperienceController,K as Experience,F as EventEmitter};
12
12
 
13
13
  /* @hypertools/sdk - MIT License - https://hypertools.dev */
14
14
 
15
- //# debugId=BE20C8AEA123CFE964756E2164756E21
15
+ //# debugId=9F2CC592AD55E80264756E2164756E21
@@ -1,13 +1,14 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../../src/core/EventEmitter.ts", "../../src/core/ParamStore.ts", "../../src/core/ObjectRegistry.ts", "../../src/core/Experience.ts"],
3
+ "sources": ["../../src/core/EventEmitter.ts", "../../src/core/ParamStore.ts", "../../src/core/ObjectRegistry.ts", "../../src/core/Experience.ts", "../../src/core/ExperienceController.ts"],
4
4
  "sourcesContent": [
5
5
  "/**\n * Typed event system for Experience\n */\n\nexport type ExperienceEventType =\n | 'ready'\n | 'error'\n | 'frame'\n | 'resize'\n | 'paramChange'\n | 'play'\n | 'pause'\n | 'objectRegistered'\n | 'objectUnregistered'\n | string; // Allow custom events\n\nexport interface ExperienceEvent {\n type: ExperienceEventType;\n timestamp: number;\n}\n\nexport interface ReadyEvent extends ExperienceEvent {\n type: 'ready';\n}\n\nexport interface ErrorEvent extends ExperienceEvent {\n type: 'error';\n error: Error;\n}\n\nexport interface FrameEvent extends ExperienceEvent {\n type: 'frame';\n frame: number;\n deltaTime: number;\n}\n\nexport interface ResizeEvent extends ExperienceEvent {\n type: 'resize';\n width: number;\n height: number;\n}\n\nexport interface ParamChangeEvent extends ExperienceEvent {\n type: 'paramChange';\n key: string;\n value: unknown;\n previousValue: unknown;\n}\n\nexport interface PlayEvent extends ExperienceEvent {\n type: 'play';\n}\n\nexport interface PauseEvent extends ExperienceEvent {\n type: 'pause';\n}\n\nexport interface ObjectRegisteredEvent extends ExperienceEvent {\n type: 'objectRegistered';\n name: string;\n id: string;\n}\n\nexport interface ObjectUnregisteredEvent extends ExperienceEvent {\n type: 'objectUnregistered';\n name: string;\n}\n\nexport type EventHandler<T extends ExperienceEvent = ExperienceEvent> = (\n event: T\n) => void;\n\nexport class EventEmitter {\n private _handlers = new Map<ExperienceEventType, Set<EventHandler>>();\n\n /**\n * Subscribe to event\n * @returns Unsubscribe function\n */\n on<T extends ExperienceEvent>(\n type: T['type'],\n handler: EventHandler<T>\n ): () => void {\n if (!this._handlers.has(type)) {\n this._handlers.set(type, new Set());\n }\n this._handlers.get(type)!.add(handler as EventHandler);\n\n // Return unsubscribe function\n return () => this.off(type, handler);\n }\n\n /**\n * Subscribe once - auto-unsubscribes after first call\n */\n once<T extends ExperienceEvent>(\n type: T['type'],\n handler: EventHandler<T>\n ): () => void {\n const wrapper: EventHandler<T> = (event) => {\n this.off(type, wrapper);\n handler(event);\n };\n return this.on(type, wrapper);\n }\n\n /**\n * Unsubscribe from event\n */\n off<T extends ExperienceEvent>(\n type: T['type'],\n handler: EventHandler<T>\n ): void {\n const handlers = this._handlers.get(type);\n if (handlers) {\n handlers.delete(handler as EventHandler);\n }\n }\n\n /**\n * Emit event to all handlers\n */\n emit<T extends ExperienceEvent>(event: T): void {\n const handlers = this._handlers.get(event.type);\n if (!handlers) return;\n\n for (const handler of handlers) {\n try {\n handler(event);\n } catch (error) {\n console.error(`[EventEmitter] Handler error for ${event.type}:`, error);\n }\n }\n }\n\n /**\n * Remove all listeners for a type (or all if no type specified)\n */\n removeAllListeners(type?: ExperienceEventType): void {\n if (type) {\n this._handlers.delete(type);\n } else {\n this._handlers.clear();\n }\n }\n\n /**\n * Get listener count for a type\n */\n listenerCount(type: ExperienceEventType): number {\n return this._handlers.get(type)?.size ?? 0;\n }\n}\n",
6
6
  "/**\n * Reactive parameter store with Proxy-based reactivity\n */\n\nexport type ParamType =\n | 'number'\n | 'color'\n | 'boolean'\n | 'string'\n | 'select'\n | 'file'\n | 'point2d'\n | 'point3d';\n\nexport interface SelectOption {\n label: string;\n value: string;\n}\n\nexport interface ParamDefinition {\n type: ParamType;\n value: unknown;\n label?: string;\n\n // Number constraints\n min?: number;\n max?: number;\n step?: number;\n\n // Select options\n options?: (string | SelectOption)[];\n\n // File constraints\n accept?: string;\n maxSize?: number;\n}\n\nexport type ParamDefinitions = Record<string, ParamDefinition>;\nexport type ParamValues = Record<string, unknown>;\n\nexport type ParamChangeCallback = (\n key: string,\n value: unknown,\n previousValue: unknown\n) => void;\n\nexport class ParamStore {\n private _definitions: ParamDefinitions;\n private _values: ParamValues;\n private _listeners: Set<ParamChangeCallback>;\n private _proxy: ParamValues;\n\n constructor(definitions: ParamDefinitions, initialOverrides?: ParamValues) {\n this._definitions = definitions;\n this._listeners = new Set();\n\n // Initialize from definitions\n this._values = {};\n for (const [key, def] of Object.entries(definitions)) {\n this._values[key] = def.value;\n }\n\n // Apply overrides\n if (initialOverrides) {\n for (const [key, value] of Object.entries(initialOverrides)) {\n if (key in this._definitions) {\n this._values[key] = this._validate(key, value);\n }\n }\n }\n\n // Create reactive proxy\n this._proxy = this._createProxy();\n }\n\n private _createProxy(): ParamValues {\n const self = this;\n return new Proxy(this._values, {\n get(target, prop: string) {\n return target[prop];\n },\n set(target, prop: string, value: unknown) {\n if (!(prop in self._definitions)) {\n console.warn(`[ParamStore] Unknown parameter: ${prop}`);\n return false;\n }\n\n const validated = self._validate(prop, value);\n const previous = target[prop];\n\n if (validated !== previous) {\n target[prop] = validated;\n self._notify(prop, validated, previous);\n }\n\n return true;\n },\n has(target, prop: string) {\n return prop in target;\n },\n ownKeys(target) {\n return Object.keys(target);\n },\n getOwnPropertyDescriptor(target, prop: string) {\n if (prop in target) {\n return {\n enumerable: true,\n configurable: true,\n value: target[prop],\n };\n }\n return undefined;\n },\n });\n }\n\n private _validate(key: string, value: unknown): unknown {\n const def = this._definitions[key];\n if (!def) return value;\n\n switch (def.type) {\n case 'number': {\n let num = typeof value === 'number' ? value : parseFloat(String(value));\n if (isNaN(num)) num = def.value as number;\n if (def.min !== undefined) num = Math.max(def.min, num);\n if (def.max !== undefined) num = Math.min(def.max, num);\n if (def.step !== undefined) {\n num = Math.round(num / def.step) * def.step;\n }\n return num;\n }\n\n case 'color': {\n const str = String(value);\n // Accept various color formats\n if (/^#[0-9A-Fa-f]{6}$/.test(str)) return str;\n if (/^#[0-9A-Fa-f]{3}$/.test(str)) return str;\n if (/^#[0-9A-Fa-f]{8}$/.test(str)) return str; // RGBA\n if (/^rgb\\(/.test(str)) return str;\n if (/^rgba\\(/.test(str)) return str;\n if (/^hsl\\(/.test(str)) return str;\n if (/^hsla\\(/.test(str)) return str;\n return def.value;\n }\n\n case 'boolean':\n if (typeof value === 'boolean') return value;\n if (value === 'true' || value === '1') return true;\n if (value === 'false' || value === '0') return false;\n return Boolean(value);\n\n case 'string':\n return String(value);\n\n case 'select': {\n const str = String(value);\n const options = def.options || [];\n const valid = options.some((opt) =>\n typeof opt === 'object' ? opt.value === str : opt === str\n );\n return valid ? str : def.value;\n }\n\n case 'point2d': {\n if (\n typeof value === 'object' &&\n value !== null &&\n 'x' in value &&\n 'y' in value\n ) {\n return { x: Number((value as any).x), y: Number((value as any).y) };\n }\n return def.value;\n }\n\n case 'point3d': {\n if (\n typeof value === 'object' &&\n value !== null &&\n 'x' in value &&\n 'y' in value &&\n 'z' in value\n ) {\n return {\n x: Number((value as any).x),\n y: Number((value as any).y),\n z: Number((value as any).z),\n };\n }\n return def.value;\n }\n\n default:\n return value;\n }\n }\n\n private _notify(key: string, value: unknown, previous: unknown): void {\n for (const listener of this._listeners) {\n try {\n listener(key, value, previous);\n } catch (error) {\n console.error('[ParamStore] Listener error:', error);\n }\n }\n }\n\n /**\n * Get reactive params proxy\n */\n getProxy(): ParamValues {\n return this._proxy;\n }\n\n /**\n * Get snapshot of current values (non-reactive copy)\n */\n getSnapshot(): ParamValues {\n return { ...this._values };\n }\n\n /**\n * Get definitions\n */\n getDefinitions(): ParamDefinitions {\n return { ...this._definitions };\n }\n\n /**\n * Set single value\n */\n set(key: string, value: unknown): void {\n this._proxy[key] = value;\n }\n\n /**\n * Set multiple values\n */\n setMultiple(params: ParamValues): void {\n for (const [key, value] of Object.entries(params)) {\n this._proxy[key] = value;\n }\n }\n\n /**\n * Reset to defaults\n */\n reset(): void {\n for (const [key, def] of Object.entries(this._definitions)) {\n this._proxy[key] = def.value;\n }\n }\n\n /**\n * Subscribe to changes\n * @returns Unsubscribe function\n */\n subscribe(callback: ParamChangeCallback): () => void {\n this._listeners.add(callback);\n return () => this._listeners.delete(callback);\n }\n\n /**\n * Add a new param definition dynamically\n */\n addDefinition(key: string, definition: ParamDefinition): void {\n this._definitions[key] = definition;\n this._values[key] = definition.value;\n }\n}\n",
7
7
  "/**\n * Spline-like object registry for querying objects by name/id\n */\n\nexport interface RegisteredObject<T = unknown> {\n name: string;\n id: string;\n object: T;\n metadata?: Record<string, unknown>;\n}\n\nexport type ObjectRegisteredCallback = (name: string, id: string, object: unknown) => void;\nexport type ObjectUnregisteredCallback = (name: string) => void;\n\nexport class ObjectRegistry {\n private _byName = new Map<string, RegisteredObject>();\n private _byId = new Map<string, RegisteredObject>();\n private _onRegister: Set<ObjectRegisteredCallback> = new Set();\n private _onUnregister: Set<ObjectUnregisteredCallback> = new Set();\n\n /**\n * Register an object for external access\n * @returns Generated ID for the object\n */\n register<T>(\n name: string,\n object: T,\n metadata?: Record<string, unknown>\n ): string {\n // If name already exists, unregister first\n if (this._byName.has(name)) {\n this.unregister(name);\n }\n\n const id = this._generateId();\n\n const registered: RegisteredObject<T> = {\n name,\n id,\n object,\n metadata,\n };\n\n this._byName.set(name, registered);\n this._byId.set(id, registered);\n\n // Notify listeners\n for (const callback of this._onRegister) {\n try {\n callback(name, id, object);\n } catch (e) {\n console.error('[ObjectRegistry] onRegister callback error:', e);\n }\n }\n\n return id;\n }\n\n /**\n * Unregister an object by name\n */\n unregister(name: string): boolean {\n const obj = this._byName.get(name);\n if (!obj) return false;\n\n this._byName.delete(name);\n this._byId.delete(obj.id);\n\n // Notify listeners\n for (const callback of this._onUnregister) {\n try {\n callback(name);\n } catch (e) {\n console.error('[ObjectRegistry] onUnregister callback error:', e);\n }\n }\n\n return true;\n }\n\n /**\n * Find object by name (Spline-like API)\n */\n findByName<T = unknown>(name: string): T | undefined {\n return this._byName.get(name)?.object as T | undefined;\n }\n\n /**\n * Find object by ID\n */\n findById<T = unknown>(id: string): T | undefined {\n return this._byId.get(id)?.object as T | undefined;\n }\n\n /**\n * Get registered object info by name\n */\n getInfo(name: string): RegisteredObject | undefined {\n return this._byName.get(name);\n }\n\n /**\n * Check if an object exists\n */\n has(name: string): boolean {\n return this._byName.has(name);\n }\n\n /**\n * Get all registered object names\n */\n getNames(): string[] {\n return Array.from(this._byName.keys());\n }\n\n /**\n * Get all registered objects as a Map\n */\n getAll(): Map<string, unknown> {\n const result = new Map<string, unknown>();\n for (const [name, registered] of this._byName) {\n result.set(name, registered.object);\n }\n return result;\n }\n\n /**\n * Query objects by metadata\n */\n query(predicate: (obj: RegisteredObject) => boolean): RegisteredObject[] {\n const results: RegisteredObject[] = [];\n for (const obj of this._byName.values()) {\n if (predicate(obj)) {\n results.push(obj);\n }\n }\n return results;\n }\n\n /**\n * Query objects by type (requires metadata.type to be set)\n */\n findByType<T = unknown>(type: string): T[] {\n return this.query((obj) => obj.metadata?.type === type).map(\n (obj) => obj.object as T\n );\n }\n\n /**\n * Clear all registered objects\n */\n clear(): void {\n const names = Array.from(this._byName.keys());\n for (const name of names) {\n this.unregister(name);\n }\n }\n\n /**\n * Subscribe to object registration events\n */\n onRegister(callback: ObjectRegisteredCallback): () => void {\n this._onRegister.add(callback);\n return () => this._onRegister.delete(callback);\n }\n\n /**\n * Subscribe to object unregistration events\n */\n onUnregister(callback: ObjectUnregisteredCallback): () => void {\n this._onUnregister.add(callback);\n return () => this._onUnregister.delete(callback);\n }\n\n /**\n * Get the number of registered objects\n */\n get size(): number {\n return this._byName.size;\n }\n\n private _generateId(): string {\n return `obj_${Date.now()}_${Math.random().toString(36).slice(2, 9)}`;\n }\n}\n",
8
- "/**\n * Core Experience class - THE shared logic for all runtimes\n *\n * This is the brain. All adapters (Frame, Export, HostedPreview) use this.\n * Adapters are thin wiring layers - Experience contains ALL the logic.\n */\n\nimport {\n EventEmitter,\n type ExperienceEvent,\n type EventHandler,\n type ParamChangeEvent,\n type FrameEvent,\n type ResizeEvent,\n type ErrorEvent,\n} from './EventEmitter';\nimport { ParamStore, type ParamDefinitions, type ParamValues } from './ParamStore';\nimport { ObjectRegistry } from './ObjectRegistry';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface ExperienceConfig {\n /** Mount element where content is rendered */\n mount: HTMLElement;\n\n /** Parameter definitions schema */\n paramDefs?: ParamDefinitions;\n\n /** Initial parameter values (overrides defaults from paramDefs) */\n initialParams?: Record<string, unknown>;\n\n /** User's setup function */\n setup: SetupFunction;\n\n /** Auto-start on init (default: true) */\n autoplay?: boolean;\n\n /** Target frame rate for frame events (default: 60) */\n frameRate?: number;\n\n /** Background color/style */\n background?: string;\n}\n\n/**\n * Context passed to user's setup function\n * This is the API users interact with in their code\n */\nexport interface ExperienceContext {\n /** DOM element to render into */\n mount: HTMLElement;\n\n /** Reactive params object (Proxy) - changes trigger events */\n params: ParamValues;\n\n /** Export/capture utilities */\n exports: ExportsApi;\n\n /** Environment utilities (window, document, resize) */\n environment: EnvironmentApi;\n\n /** Register an object for Spline-like queries */\n registerObject: <T = unknown>(\n name: string,\n object: T,\n metadata?: Record<string, unknown>\n ) => string;\n\n /** Find registered object by name */\n findObjectByName: <T = unknown>(name: string) => T | undefined;\n\n /** Experience instance (for advanced use) */\n experience: Experience;\n}\n\nexport interface ExportsApi {\n /** Capture canvas as image */\n captureImage: (format?: 'png' | 'jpeg' | 'webp') => Promise<Blob | null>;\n\n /** Set filename for exports */\n setFilename: (filename: string) => void;\n\n /** Register custom capture handler */\n registerCaptureHandler: (handler: CaptureHandler) => void;\n}\n\nexport type CaptureHandler = (format: string) => Promise<Blob | null>;\n\nexport interface EnvironmentApi {\n /** Window reference */\n window: Window;\n\n /** Document reference */\n document: Document;\n\n /** Subscribe to resize events, returns cleanup */\n onResize: (callback: (width: number, height: number) => void) => () => void;\n\n /** Add cleanup function to be called on destroy */\n addCleanup: (cleanup: () => void) => void;\n}\n\nexport type SetupFunction = (\n context: ExperienceContext\n) => CleanupFunction | void | Promise<CleanupFunction | void>;\n\nexport type CleanupFunction = () => void;\n\n// ============================================================================\n// Experience Class\n// ============================================================================\n\nexport class Experience {\n // State\n private _isReady = false;\n private _isPlaying = false;\n private _isDestroyed = false;\n private _currentFrame = 0;\n\n // Core systems\n private _paramStore: ParamStore;\n private _events: EventEmitter;\n private _objects: ObjectRegistry;\n\n // Config\n private _mount: HTMLElement;\n private _frameRate: number;\n private _filename = 'capture';\n\n // Lifecycle\n private _cleanups: CleanupFunction[] = [];\n private _userCleanup?: CleanupFunction;\n private _animationFrameId?: number;\n private _lastFrameTime = 0;\n private _resizeObserver?: ResizeObserver;\n private _captureHandler?: CaptureHandler;\n\n constructor(config: ExperienceConfig) {\n this._mount = config.mount;\n this._frameRate = config.frameRate ?? 60;\n\n // Apply background if provided\n if (config.background) {\n this._mount.style.background = config.background;\n }\n\n // Initialize core systems\n this._paramStore = new ParamStore(\n config.paramDefs ?? {},\n config.initialParams\n );\n this._events = new EventEmitter();\n this._objects = new ObjectRegistry();\n\n // Subscribe to param changes -> emit events\n this._paramStore.subscribe((key, value, previousValue) => {\n this._events.emit<ParamChangeEvent>({\n type: 'paramChange',\n timestamp: Date.now(),\n key,\n value,\n previousValue,\n });\n });\n\n // Setup resize observer\n this._setupResizeObserver();\n\n // Run user setup\n this._runSetup(config.setup, config.autoplay ?? true);\n }\n\n // ===== Public Getters =====\n\n get isReady(): boolean {\n return this._isReady;\n }\n\n get isPlaying(): boolean {\n return this._isPlaying;\n }\n\n get isDestroyed(): boolean {\n return this._isDestroyed;\n }\n\n get currentFrame(): number {\n return this._currentFrame;\n }\n\n get mount(): HTMLElement {\n return this._mount;\n }\n\n /** Reactive params proxy */\n get params(): ParamValues {\n return this._paramStore.getProxy();\n }\n\n /** EventEmitter for external subscriptions */\n get events(): EventEmitter {\n return this._events;\n }\n\n /** ObjectRegistry for external access */\n get objects(): ObjectRegistry {\n return this._objects;\n }\n\n // ===== Parameter Methods =====\n\n setParam(key: string, value: unknown): void {\n this._paramStore.set(key, value);\n }\n\n setParams(params: Record<string, unknown>): void {\n this._paramStore.setMultiple(params);\n }\n\n getParams(): Record<string, unknown> {\n return this._paramStore.getSnapshot();\n }\n\n getParamDefs(): ParamDefinitions {\n return this._paramStore.getDefinitions();\n }\n\n resetParams(): void {\n this._paramStore.reset();\n }\n\n // ===== Object Registry (Spline-like) =====\n\n registerObject<T = unknown>(\n name: string,\n object: T,\n metadata?: Record<string, unknown>\n ): string {\n return this._objects.register(name, object, metadata);\n }\n\n findObjectByName<T = unknown>(name: string): T | undefined {\n return this._objects.findByName<T>(name);\n }\n\n findObjectById<T = unknown>(id: string): T | undefined {\n return this._objects.findById<T>(id);\n }\n\n getAllObjects(): Map<string, unknown> {\n return this._objects.getAll();\n }\n\n // ===== Playback =====\n\n play(): void {\n if (this._isPlaying || this._isDestroyed) return;\n this._isPlaying = true;\n this._lastFrameTime = performance.now();\n this._tick();\n this._events.emit({ type: 'play', timestamp: Date.now() });\n }\n\n pause(): void {\n if (!this._isPlaying) return;\n this._isPlaying = false;\n if (this._animationFrameId) {\n cancelAnimationFrame(this._animationFrameId);\n this._animationFrameId = undefined;\n }\n this._events.emit({ type: 'pause', timestamp: Date.now() });\n }\n\n toggle(): void {\n if (this._isPlaying) {\n this.pause();\n } else {\n this.play();\n }\n }\n\n // ===== Events =====\n\n on<T extends ExperienceEvent>(\n type: T['type'],\n handler: EventHandler<T>\n ): () => void {\n return this._events.on(type, handler);\n }\n\n once<T extends ExperienceEvent>(\n type: T['type'],\n handler: EventHandler<T>\n ): () => void {\n return this._events.once(type, handler);\n }\n\n off<T extends ExperienceEvent>(\n type: T['type'],\n handler: EventHandler<T>\n ): void {\n this._events.off(type, handler);\n }\n\n // ===== Capture =====\n\n async captureImage(format: 'png' | 'jpeg' | 'webp' = 'png'): Promise<Blob | null> {\n // Use custom handler if registered\n if (this._captureHandler) {\n return this._captureHandler(format);\n }\n\n // Default: find canvas and capture\n const canvas = this._mount.querySelector('canvas');\n if (!canvas) {\n console.warn('[Experience] No canvas found for capture');\n return null;\n }\n\n return new Promise((resolve) => {\n const mimeType = `image/${format}`;\n const quality = format === 'jpeg' ? 0.92 : undefined;\n canvas.toBlob((blob) => resolve(blob), mimeType, quality);\n });\n }\n\n getFilename(): string {\n return this._filename;\n }\n\n // ===== Lifecycle =====\n\n /**\n * Add a cleanup function to be called on destroy\n */\n addCleanup(cleanup: CleanupFunction): void {\n if (typeof cleanup === 'function') {\n this._cleanups.push(cleanup);\n }\n }\n\n /**\n * Destroy the experience and run all cleanups\n */\n destroy(): void {\n if (this._isDestroyed) return;\n this._isDestroyed = true;\n\n // Stop animation\n this.pause();\n\n // Run user cleanup first\n if (this._userCleanup) {\n try {\n this._userCleanup();\n } catch (e) {\n console.error('[Experience] User cleanup error:', e);\n }\n }\n\n // Run registered cleanups (reverse order)\n while (this._cleanups.length > 0) {\n const cleanup = this._cleanups.pop();\n if (cleanup) {\n try {\n cleanup();\n } catch (e) {\n console.error('[Experience] Cleanup error:', e);\n }\n }\n }\n\n // Disconnect observers\n this._resizeObserver?.disconnect();\n\n // Clear registry\n this._objects.clear();\n\n // Remove all event listeners\n this._events.removeAllListeners();\n\n // Emit destroyed event before clearing\n this._events.emit({ type: 'destroyed', timestamp: Date.now() });\n }\n\n // ===== Private Methods =====\n\n private async _runSetup(setup: SetupFunction, autoplay: boolean): Promise<void> {\n try {\n // Create context for user's setup\n const context = this._createContext();\n\n // Run user's setup\n const cleanup = await setup(context);\n if (typeof cleanup === 'function') {\n this._userCleanup = cleanup;\n }\n\n this._isReady = true;\n this._events.emit({ type: 'ready', timestamp: Date.now() });\n\n // Autoplay if enabled\n if (autoplay) {\n this.play();\n }\n } catch (error) {\n console.error('[Experience] Setup error:', error);\n this._events.emit<ErrorEvent>({\n type: 'error',\n timestamp: Date.now(),\n error: error instanceof Error ? error : new Error(String(error)),\n });\n }\n }\n\n private _createContext(): ExperienceContext {\n return {\n mount: this._mount,\n params: this._paramStore.getProxy(),\n exports: this._createExportsApi(),\n environment: this._createEnvironmentApi(),\n registerObject: (name, object, metadata) =>\n this._objects.register(name, object, metadata),\n findObjectByName: (name) => this._objects.findByName(name),\n experience: this,\n };\n }\n\n private _createExportsApi(): ExportsApi {\n return {\n captureImage: (format) => this.captureImage(format),\n setFilename: (filename) => {\n this._filename = filename;\n },\n registerCaptureHandler: (handler) => {\n this._captureHandler = handler;\n },\n };\n }\n\n private _createEnvironmentApi(): EnvironmentApi {\n return {\n window,\n document,\n onResize: (callback) => {\n const handler = () => {\n callback(this._mount.clientWidth, this._mount.clientHeight);\n };\n\n // Call immediately with current size\n handler();\n\n // Setup observer\n const ro = new ResizeObserver(handler);\n ro.observe(this._mount);\n\n const cleanup = () => ro.disconnect();\n this._cleanups.push(cleanup);\n return cleanup;\n },\n addCleanup: (cleanup) => this.addCleanup(cleanup),\n };\n }\n\n private _setupResizeObserver(): void {\n this._resizeObserver = new ResizeObserver((entries) => {\n for (const entry of entries) {\n const { width, height } = entry.contentRect;\n this._events.emit<ResizeEvent>({\n type: 'resize',\n timestamp: Date.now(),\n width,\n height,\n });\n }\n });\n this._resizeObserver.observe(this._mount);\n }\n\n private _tick(): void {\n if (!this._isPlaying) return;\n\n const now = performance.now();\n const deltaTime = now - this._lastFrameTime;\n const targetInterval = 1000 / this._frameRate;\n\n if (deltaTime >= targetInterval) {\n this._currentFrame++;\n this._lastFrameTime = now - (deltaTime % targetInterval);\n\n this._events.emit<FrameEvent>({\n type: 'frame',\n timestamp: Date.now(),\n frame: this._currentFrame,\n deltaTime,\n });\n }\n\n this._animationFrameId = requestAnimationFrame(() => this._tick());\n }\n}\n"
8
+ "/**\n * Core Experience class - THE shared logic for all runtimes\n *\n * This is the brain. All adapters (Frame, Export, HostedPreview) use this.\n * Adapters are thin wiring layers - Experience contains ALL the logic.\n */\n\nimport {\n EventEmitter,\n type ExperienceEvent,\n type EventHandler,\n type ParamChangeEvent,\n type FrameEvent,\n type ResizeEvent,\n type ErrorEvent,\n} from './EventEmitter';\nimport { ParamStore, type ParamDefinitions, type ParamValues } from './ParamStore';\nimport { ObjectRegistry } from './ObjectRegistry';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface ExperienceConfig {\n /** Mount element where content is rendered */\n mount: HTMLElement;\n\n /** Parameter definitions schema */\n paramDefs?: ParamDefinitions;\n\n /** Initial parameter values (overrides defaults from paramDefs) */\n initialParams?: Record<string, unknown>;\n\n /** User's setup function */\n setup: SetupFunction;\n\n /** Auto-start on init (default: true) */\n autoplay?: boolean;\n\n /** Target frame rate for frame events (default: 60) */\n frameRate?: number;\n\n /** Background color/style */\n background?: string;\n}\n\n/**\n * Context passed to user's setup function\n * This is the API users interact with in their code\n */\nexport interface ExperienceContext {\n /** DOM element to render into */\n mount: HTMLElement;\n\n /** Reactive params object (Proxy) - changes trigger events */\n params: ParamValues;\n\n /** Export/capture utilities */\n exports: ExportsApi;\n\n /** Environment utilities (window, document, resize) */\n environment: EnvironmentApi;\n\n /** Register an object for Spline-like queries */\n registerObject: <T = unknown>(\n name: string,\n object: T,\n metadata?: Record<string, unknown>\n ) => string;\n\n /** Find registered object by name */\n findObjectByName: <T = unknown>(name: string) => T | undefined;\n\n /** Experience instance (for advanced use) */\n experience: Experience;\n}\n\nexport interface ExportsApi {\n /** Capture canvas as image */\n captureImage: (format?: 'png' | 'jpeg' | 'webp') => Promise<Blob | null>;\n\n /** Set filename for exports */\n setFilename: (filename: string) => void;\n\n /** Register custom capture handler */\n registerCaptureHandler: (handler: CaptureHandler) => void;\n}\n\nexport type CaptureHandler = (format: string) => Promise<Blob | null>;\n\nexport interface EnvironmentApi {\n /** Window reference */\n window: Window;\n\n /** Document reference */\n document: Document;\n\n /** Subscribe to resize events, returns cleanup */\n onResize: (callback: (width: number, height: number) => void) => () => void;\n\n /** Add cleanup function to be called on destroy */\n addCleanup: (cleanup: () => void) => void;\n}\n\nexport type SetupFunction = (\n context: ExperienceContext\n) => CleanupFunction | void | Promise<CleanupFunction | void>;\n\nexport type CleanupFunction = () => void;\n\n// ============================================================================\n// Experience Class\n// ============================================================================\n\nexport class Experience {\n // State\n private _isReady = false;\n private _isPlaying = false;\n private _isDestroyed = false;\n private _currentFrame = 0;\n\n // Core systems\n private _paramStore: ParamStore;\n private _events: EventEmitter;\n private _objects: ObjectRegistry;\n\n // Config\n private _mount: HTMLElement;\n private _frameRate: number;\n private _filename = 'capture';\n\n // Lifecycle\n private _cleanups: CleanupFunction[] = [];\n private _userCleanup?: CleanupFunction;\n private _animationFrameId?: number;\n private _lastFrameTime = 0;\n private _resizeObserver?: ResizeObserver;\n private _captureHandler?: CaptureHandler;\n\n constructor(config: ExperienceConfig) {\n this._mount = config.mount;\n this._frameRate = config.frameRate ?? 60;\n\n // Apply background if provided\n if (config.background) {\n this._mount.style.background = config.background;\n }\n\n // Initialize core systems\n this._paramStore = new ParamStore(\n config.paramDefs ?? {},\n config.initialParams\n );\n this._events = new EventEmitter();\n this._objects = new ObjectRegistry();\n\n // Subscribe to param changes -> emit events\n this._paramStore.subscribe((key, value, previousValue) => {\n this._events.emit<ParamChangeEvent>({\n type: 'paramChange',\n timestamp: Date.now(),\n key,\n value,\n previousValue,\n });\n });\n\n // Setup resize observer\n this._setupResizeObserver();\n\n // Run user setup\n this._runSetup(config.setup, config.autoplay ?? true);\n }\n\n // ===== Public Getters =====\n\n get isReady(): boolean {\n return this._isReady;\n }\n\n get isPlaying(): boolean {\n return this._isPlaying;\n }\n\n get isDestroyed(): boolean {\n return this._isDestroyed;\n }\n\n get currentFrame(): number {\n return this._currentFrame;\n }\n\n get mount(): HTMLElement {\n return this._mount;\n }\n\n /** Reactive params proxy */\n get params(): ParamValues {\n return this._paramStore.getProxy();\n }\n\n /** EventEmitter for external subscriptions */\n get events(): EventEmitter {\n return this._events;\n }\n\n /** ObjectRegistry for external access */\n get objects(): ObjectRegistry {\n return this._objects;\n }\n\n // ===== Parameter Methods =====\n\n setParam(key: string, value: unknown): void {\n this._paramStore.set(key, value);\n }\n\n setParams(params: Record<string, unknown>): void {\n this._paramStore.setMultiple(params);\n }\n\n getParams(): Record<string, unknown> {\n return this._paramStore.getSnapshot();\n }\n\n getParamDefs(): ParamDefinitions {\n return this._paramStore.getDefinitions();\n }\n\n resetParams(): void {\n this._paramStore.reset();\n }\n\n // ===== Object Registry (Spline-like) =====\n\n registerObject<T = unknown>(\n name: string,\n object: T,\n metadata?: Record<string, unknown>\n ): string {\n return this._objects.register(name, object, metadata);\n }\n\n findObjectByName<T = unknown>(name: string): T | undefined {\n return this._objects.findByName<T>(name);\n }\n\n findObjectById<T = unknown>(id: string): T | undefined {\n return this._objects.findById<T>(id);\n }\n\n getAllObjects(): Map<string, unknown> {\n return this._objects.getAll();\n }\n\n // ===== Playback =====\n\n play(): void {\n if (this._isPlaying || this._isDestroyed) return;\n this._isPlaying = true;\n this._lastFrameTime = performance.now();\n this._tick();\n this._events.emit({ type: 'play', timestamp: Date.now() });\n }\n\n pause(): void {\n if (!this._isPlaying) return;\n this._isPlaying = false;\n if (this._animationFrameId) {\n cancelAnimationFrame(this._animationFrameId);\n this._animationFrameId = undefined;\n }\n this._events.emit({ type: 'pause', timestamp: Date.now() });\n }\n\n toggle(): void {\n if (this._isPlaying) {\n this.pause();\n } else {\n this.play();\n }\n }\n\n // ===== Events =====\n\n on<T extends ExperienceEvent>(\n type: T['type'],\n handler: EventHandler<T>\n ): () => void {\n return this._events.on(type, handler);\n }\n\n once<T extends ExperienceEvent>(\n type: T['type'],\n handler: EventHandler<T>\n ): () => void {\n return this._events.once(type, handler);\n }\n\n off<T extends ExperienceEvent>(\n type: T['type'],\n handler: EventHandler<T>\n ): void {\n this._events.off(type, handler);\n }\n\n // ===== Capture =====\n\n async captureImage(format: 'png' | 'jpeg' | 'webp' = 'png'): Promise<Blob | null> {\n // Use custom handler if registered\n if (this._captureHandler) {\n return this._captureHandler(format);\n }\n\n // Default: find canvas and capture\n const canvas = this._mount.querySelector('canvas');\n if (!canvas) {\n console.warn('[Experience] No canvas found for capture');\n return null;\n }\n\n return new Promise((resolve) => {\n const mimeType = `image/${format}`;\n const quality = format === 'jpeg' ? 0.92 : undefined;\n canvas.toBlob((blob) => resolve(blob), mimeType, quality);\n });\n }\n\n getFilename(): string {\n return this._filename;\n }\n\n // ===== Lifecycle =====\n\n /**\n * Add a cleanup function to be called on destroy\n */\n addCleanup(cleanup: CleanupFunction): void {\n if (typeof cleanup === 'function') {\n this._cleanups.push(cleanup);\n }\n }\n\n /**\n * Destroy the experience and run all cleanups\n */\n destroy(): void {\n if (this._isDestroyed) return;\n this._isDestroyed = true;\n\n // Stop animation\n this.pause();\n\n // Run user cleanup first\n if (this._userCleanup) {\n try {\n this._userCleanup();\n } catch (e) {\n console.error('[Experience] User cleanup error:', e);\n }\n }\n\n // Run registered cleanups (reverse order)\n while (this._cleanups.length > 0) {\n const cleanup = this._cleanups.pop();\n if (cleanup) {\n try {\n cleanup();\n } catch (e) {\n console.error('[Experience] Cleanup error:', e);\n }\n }\n }\n\n // Disconnect observers\n this._resizeObserver?.disconnect();\n\n // Clear registry\n this._objects.clear();\n\n // Remove all event listeners\n this._events.removeAllListeners();\n\n // Emit destroyed event before clearing\n this._events.emit({ type: 'destroyed', timestamp: Date.now() });\n }\n\n // ===== Private Methods =====\n\n private async _runSetup(setup: SetupFunction, autoplay: boolean): Promise<void> {\n try {\n // Create context for user's setup\n const context = this._createContext();\n\n // Run user's setup\n const cleanup = await setup(context);\n if (typeof cleanup === 'function') {\n this._userCleanup = cleanup;\n }\n\n this._isReady = true;\n this._events.emit({ type: 'ready', timestamp: Date.now() });\n\n // Autoplay if enabled\n if (autoplay) {\n this.play();\n }\n } catch (error) {\n console.error('[Experience] Setup error:', error);\n this._events.emit<ErrorEvent>({\n type: 'error',\n timestamp: Date.now(),\n error: error instanceof Error ? error : new Error(String(error)),\n });\n }\n }\n\n private _createContext(): ExperienceContext {\n return {\n mount: this._mount,\n params: this._paramStore.getProxy(),\n exports: this._createExportsApi(),\n environment: this._createEnvironmentApi(),\n registerObject: (name, object, metadata) =>\n this._objects.register(name, object, metadata),\n findObjectByName: (name) => this._objects.findByName(name),\n experience: this,\n };\n }\n\n private _createExportsApi(): ExportsApi {\n return {\n captureImage: (format) => this.captureImage(format),\n setFilename: (filename) => {\n this._filename = filename;\n },\n registerCaptureHandler: (handler) => {\n this._captureHandler = handler;\n },\n };\n }\n\n private _createEnvironmentApi(): EnvironmentApi {\n return {\n window,\n document,\n onResize: (callback) => {\n const handler = () => {\n callback(this._mount.clientWidth, this._mount.clientHeight);\n };\n\n // Call immediately with current size\n handler();\n\n // Setup observer\n const ro = new ResizeObserver(handler);\n ro.observe(this._mount);\n\n const cleanup = () => ro.disconnect();\n this._cleanups.push(cleanup);\n return cleanup;\n },\n addCleanup: (cleanup) => this.addCleanup(cleanup),\n };\n }\n\n private _setupResizeObserver(): void {\n this._resizeObserver = new ResizeObserver((entries) => {\n for (const entry of entries) {\n const { width, height } = entry.contentRect;\n this._events.emit<ResizeEvent>({\n type: 'resize',\n timestamp: Date.now(),\n width,\n height,\n });\n }\n });\n this._resizeObserver.observe(this._mount);\n }\n\n private _tick(): void {\n if (!this._isPlaying) return;\n\n const now = performance.now();\n const deltaTime = now - this._lastFrameTime;\n const targetInterval = 1000 / this._frameRate;\n\n if (deltaTime >= targetInterval) {\n this._currentFrame++;\n this._lastFrameTime = now - (deltaTime % targetInterval);\n\n this._events.emit<FrameEvent>({\n type: 'frame',\n timestamp: Date.now(),\n frame: this._currentFrame,\n deltaTime,\n });\n }\n\n this._animationFrameId = requestAnimationFrame(() => this._tick());\n }\n}\n",
9
+ "/**\n * ExperienceController - Control exported HyperTools experiences programmatically\n *\n * Use this to connect to and control exported web components from the SDK.\n * The exported experience has its initial state packaged, but you can\n * override params, listen to events, and control it via this API.\n *\n * @example\n * ```typescript\n * import { ExperienceController } from '@hypertools/sdk';\n *\n * // Get the exported web component\n * const element = document.querySelector('my-experience');\n *\n * // Connect SDK controller\n * const controller = new ExperienceController(element);\n *\n * // Control programmatically\n * controller.setParam('speed', 5);\n * controller.on('paramchange', (e) => console.log(e.detail));\n *\n * // Later, disconnect\n * controller.destroy();\n * ```\n */\n\nimport { EventEmitter, type ExperienceEvent, type EventHandler, type ParamChangeEvent } from './EventEmitter';\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Interface for exported HyperTools web components\n */\nexport interface ExportedExperienceElement extends HTMLElement {\n setParam(key: string, value: unknown): void;\n setParams(params: Record<string, unknown>): void;\n getParams(): Record<string, unknown>;\n getParamDefs(): Record<string, { type: string; value: unknown; [key: string]: unknown }>;\n}\n\nexport interface ExperienceControllerConfig {\n /** The exported web component element */\n element: ExportedExperienceElement;\n\n /** Initial param overrides (applied on connect) */\n initialParams?: Record<string, unknown>;\n\n /** Auto-connect on creation (default: true) */\n autoConnect?: boolean;\n}\n\n// ============================================================================\n// ExperienceController Class\n// ============================================================================\n\nexport class ExperienceController {\n private _element: ExportedExperienceElement;\n private _events: EventEmitter;\n private _isConnected = false;\n private _isDestroyed = false;\n\n // Event listeners we attach to the element\n private _boundReadyHandler: (e: Event) => void;\n private _boundParamChangeHandler: (e: Event) => void;\n\n constructor(elementOrConfig: ExportedExperienceElement | ExperienceControllerConfig) {\n // Handle both direct element and config object\n const config: ExperienceControllerConfig =\n elementOrConfig instanceof HTMLElement\n ? { element: elementOrConfig }\n : elementOrConfig;\n\n this._element = config.element;\n this._events = new EventEmitter();\n\n // Bind event handlers\n this._boundReadyHandler = this._handleReady.bind(this);\n this._boundParamChangeHandler = this._handleParamChange.bind(this);\n\n // Auto-connect unless disabled\n if (config.autoConnect !== false) {\n this.connect();\n\n // Apply initial params if provided\n if (config.initialParams) {\n this.setParams(config.initialParams);\n }\n }\n }\n\n // ===== Connection =====\n\n /**\n * Connect to the web component and start listening to events\n */\n connect(): void {\n if (this._isConnected || this._isDestroyed) return;\n\n this._element.addEventListener('ready', this._boundReadyHandler);\n this._element.addEventListener('paramchange', this._boundParamChangeHandler);\n\n this._isConnected = true;\n\n // Emit connected event\n this._events.emit({ type: 'connected', timestamp: Date.now() });\n }\n\n /**\n * Disconnect from the web component\n */\n disconnect(): void {\n if (!this._isConnected) return;\n\n this._element.removeEventListener('ready', this._boundReadyHandler);\n this._element.removeEventListener('paramchange', this._boundParamChangeHandler);\n\n this._isConnected = false;\n\n this._events.emit({ type: 'disconnected', timestamp: Date.now() });\n }\n\n // ===== Getters =====\n\n get element(): ExportedExperienceElement {\n return this._element;\n }\n\n get isConnected(): boolean {\n return this._isConnected;\n }\n\n get isDestroyed(): boolean {\n return this._isDestroyed;\n }\n\n // ===== Parameter Methods =====\n\n /**\n * Set a single parameter\n */\n setParam(key: string, value: unknown): void {\n this._element.setParam(key, value);\n }\n\n /**\n * Set multiple parameters at once\n */\n setParams(params: Record<string, unknown>): void {\n this._element.setParams(params);\n }\n\n /**\n * Get current parameter values\n */\n getParams(): Record<string, unknown> {\n return this._element.getParams();\n }\n\n /**\n * Get parameter definitions (types, ranges, etc.)\n */\n getParamDefs(): Record<string, { type: string; value: unknown; [key: string]: unknown }> {\n return this._element.getParamDefs();\n }\n\n /**\n * Reset parameters to their default values\n */\n resetParams(): void {\n const defs = this.getParamDefs();\n const defaults: Record<string, unknown> = {};\n\n for (const [key, def] of Object.entries(defs)) {\n defaults[key] = def.value;\n }\n\n this.setParams(defaults);\n }\n\n // ===== Events =====\n\n /**\n * Subscribe to an event\n */\n on<T extends ExperienceEvent>(\n type: T['type'],\n handler: EventHandler<T>\n ): () => void {\n return this._events.on(type, handler);\n }\n\n /**\n * Subscribe to an event once\n */\n once<T extends ExperienceEvent>(\n type: T['type'],\n handler: EventHandler<T>\n ): () => void {\n return this._events.once(type, handler);\n }\n\n /**\n * Unsubscribe from an event\n */\n off<T extends ExperienceEvent>(\n type: T['type'],\n handler: EventHandler<T>\n ): void {\n this._events.off(type, handler);\n }\n\n // ===== Lifecycle =====\n\n /**\n * Destroy the controller and disconnect from the element\n */\n destroy(): void {\n if (this._isDestroyed) return;\n\n this.disconnect();\n this._events.removeAllListeners();\n this._isDestroyed = true;\n\n this._events.emit({ type: 'destroyed', timestamp: Date.now() });\n }\n\n // ===== Private Event Handlers =====\n\n private _handleReady(_e: Event): void {\n this._events.emit({ type: 'ready', timestamp: Date.now() });\n }\n\n private _handleParamChange(e: Event): void {\n const customEvent = e as CustomEvent<{\n key: string;\n value: unknown;\n previousValue: unknown;\n }>;\n\n this._events.emit<ParamChangeEvent>({\n type: 'paramChange',\n timestamp: Date.now(),\n key: customEvent.detail.key,\n value: customEvent.detail.value,\n previousValue: customEvent.detail.previousValue,\n });\n }\n\n // ===== Static Factory Methods =====\n\n /**\n * Connect to an experience by CSS selector\n */\n static fromSelector(selector: string, initialParams?: Record<string, unknown>): ExperienceController {\n const element = document.querySelector(selector) as ExportedExperienceElement;\n if (!element) {\n throw new Error(`[ExperienceController] Element not found: ${selector}`);\n }\n return new ExperienceController({ element, initialParams });\n }\n\n /**\n * Wait for element to be defined, then connect\n */\n static async whenDefined(\n tagName: string,\n initialParams?: Record<string, unknown>\n ): Promise<ExperienceController> {\n // Wait for custom element to be defined\n await customElements.whenDefined(tagName);\n\n // Find or create the element\n let element = document.querySelector(tagName) as ExportedExperienceElement;\n if (!element) {\n element = document.createElement(tagName) as ExportedExperienceElement;\n }\n\n return new ExperienceController({ element, initialParams });\n }\n}\n"
9
10
  ],
10
- "mappings": ";;;;;;;;;;AAwEO,MAAM,CAAa,CAChB,UAAY,IAAI,IAMxB,EAA6B,CAC3B,EACA,EACY,CACZ,GAAI,CAAC,KAAK,UAAU,IAAI,CAAI,EAC1B,KAAK,UAAU,IAAI,EAAM,IAAI,GAAK,EAKpC,OAHA,KAAK,UAAU,IAAI,CAAI,EAAG,IAAI,CAAuB,EAG9C,IAAM,KAAK,IAAI,EAAM,CAAO,EAMrC,IAA+B,CAC7B,EACA,EACY,CACZ,IAAM,EAA2B,CAAC,IAAU,CAC1C,KAAK,IAAI,EAAM,CAAO,EACtB,EAAQ,CAAK,GAEf,OAAO,KAAK,GAAG,EAAM,CAAO,EAM9B,GAA8B,CAC5B,EACA,EACM,CACN,IAAM,EAAW,KAAK,UAAU,IAAI,CAAI,EACxC,GAAI,EACF,EAAS,OAAO,CAAuB,EAO3C,IAA+B,CAAC,EAAgB,CAC9C,IAAM,EAAW,KAAK,UAAU,IAAI,EAAM,IAAI,EAC9C,GAAI,CAAC,EAAU,OAEf,QAAW,KAAW,EACpB,GAAI,CACF,EAAQ,CAAK,EACb,MAAO,EAAO,CACd,QAAQ,MAAM,oCAAoC,EAAM,QAAS,CAAK,GAQ5E,kBAAkB,CAAC,EAAkC,CACnD,GAAI,EACF,KAAK,UAAU,OAAO,CAAI,EAE1B,UAAK,UAAU,MAAM,EAOzB,aAAa,CAAC,EAAmC,CAC/C,OAAO,KAAK,UAAU,IAAI,CAAI,GAAG,MAAQ,EAE7C,CC1GO,MAAM,CAAW,CACd,aACA,QACA,WACA,OAER,WAAW,CAAC,EAA+B,EAAgC,CACzE,KAAK,aAAe,EACpB,KAAK,WAAa,IAAI,IAGtB,KAAK,QAAU,CAAC,EAChB,QAAY,EAAK,KAAQ,OAAO,QAAQ,CAAW,EACjD,KAAK,QAAQ,GAAO,EAAI,MAI1B,GAAI,GACF,QAAY,EAAK,KAAU,OAAO,QAAQ,CAAgB,EACxD,GAAI,KAAO,KAAK,aACd,KAAK,QAAQ,GAAO,KAAK,UAAU,EAAK,CAAK,EAMnD,KAAK,OAAS,KAAK,aAAa,EAG1B,YAAY,EAAgB,CAClC,IAAM,EAAO,KACb,OAAO,IAAI,MAAM,KAAK,QAAS,CAC7B,GAAG,CAAC,EAAQ,EAAc,CACxB,OAAO,EAAO,IAEhB,GAAG,CAAC,EAAQ,EAAc,EAAgB,CACxC,GAAI,EAAE,KAAQ,EAAK,cAEjB,OADA,QAAQ,KAAK,mCAAmC,GAAM,EAC/C,GAGT,IAAM,EAAY,EAAK,UAAU,EAAM,CAAK,EACtC,EAAW,EAAO,GAExB,GAAI,IAAc,EAChB,EAAO,GAAQ,EACf,EAAK,QAAQ,EAAM,EAAW,CAAQ,EAGxC,MAAO,IAET,GAAG,CAAC,EAAQ,EAAc,CACxB,OAAO,KAAQ,GAEjB,OAAO,CAAC,EAAQ,CACd,OAAO,OAAO,KAAK,CAAM,GAE3B,wBAAwB,CAAC,EAAQ,EAAc,CAC7C,GAAI,KAAQ,EACV,MAAO,CACL,WAAY,GACZ,aAAc,GACd,MAAO,EAAO,EAChB,EAEF,OAEJ,CAAC,EAGK,SAAS,CAAC,EAAa,EAAyB,CACtD,IAAM,EAAM,KAAK,aAAa,GAC9B,GAAI,CAAC,EAAK,OAAO,EAEjB,OAAQ,EAAI,UACL,SAAU,CACb,IAAI,EAAM,OAAO,IAAU,SAAW,EAAQ,WAAW,OAAO,CAAK,CAAC,EACtE,GAAI,MAAM,CAAG,EAAG,EAAM,EAAI,MAC1B,GAAI,EAAI,MAAQ,OAAW,EAAM,KAAK,IAAI,EAAI,IAAK,CAAG,EACtD,GAAI,EAAI,MAAQ,OAAW,EAAM,KAAK,IAAI,EAAI,IAAK,CAAG,EACtD,GAAI,EAAI,OAAS,OACf,EAAM,KAAK,MAAM,EAAM,EAAI,IAAI,EAAI,EAAI,KAEzC,OAAO,CACT,KAEK,QAAS,CACZ,IAAM,EAAM,OAAO,CAAK,EAExB,GAAI,oBAAoB,KAAK,CAAG,EAAG,OAAO,EAC1C,GAAI,oBAAoB,KAAK,CAAG,EAAG,OAAO,EAC1C,GAAI,oBAAoB,KAAK,CAAG,EAAG,OAAO,EAC1C,GAAI,SAAS,KAAK,CAAG,EAAG,OAAO,EAC/B,GAAI,UAAU,KAAK,CAAG,EAAG,OAAO,EAChC,GAAI,SAAS,KAAK,CAAG,EAAG,OAAO,EAC/B,GAAI,UAAU,KAAK,CAAG,EAAG,OAAO,EAChC,OAAO,EAAI,KACb,KAEK,UACH,GAAI,OAAO,IAAU,UAAW,OAAO,EACvC,GAAI,IAAU,QAAU,IAAU,IAAK,MAAO,GAC9C,GAAI,IAAU,SAAW,IAAU,IAAK,MAAO,GAC/C,OAAO,QAAQ,CAAK,MAEjB,SACH,OAAO,OAAO,CAAK,MAEhB,SAAU,CACb,IAAM,EAAM,OAAO,CAAK,EAKxB,OAJgB,EAAI,SAAW,CAAC,GACV,KAAK,CAAC,IAC1B,OAAO,IAAQ,SAAW,EAAI,QAAU,EAAM,IAAQ,CACxD,EACe,EAAM,EAAI,KAC3B,KAEK,UAAW,CACd,GACE,OAAO,IAAU,UACjB,IAAU,MACV,MAAO,GACP,MAAO,EAEP,MAAO,CAAE,EAAG,OAAQ,EAAc,CAAC,EAAG,EAAG,OAAQ,EAAc,CAAC,CAAE,EAEpE,OAAO,EAAI,KACb,KAEK,UAAW,CACd,GACE,OAAO,IAAU,UACjB,IAAU,MACV,MAAO,GACP,MAAO,GACP,MAAO,EAEP,MAAO,CACL,EAAG,OAAQ,EAAc,CAAC,EAC1B,EAAG,OAAQ,EAAc,CAAC,EAC1B,EAAG,OAAQ,EAAc,CAAC,CAC5B,EAEF,OAAO,EAAI,KACb,SAGE,OAAO,GAIL,OAAO,CAAC,EAAa,EAAgB,EAAyB,CACpE,QAAW,KAAY,KAAK,WAC1B,GAAI,CACF,EAAS,EAAK,EAAO,CAAQ,EAC7B,MAAO,EAAO,CACd,QAAQ,MAAM,+BAAgC,CAAK,GAQzD,QAAQ,EAAgB,CACtB,OAAO,KAAK,OAMd,WAAW,EAAgB,CACzB,MAAO,IAAK,KAAK,OAAQ,EAM3B,cAAc,EAAqB,CACjC,MAAO,IAAK,KAAK,YAAa,EAMhC,GAAG,CAAC,EAAa,EAAsB,CACrC,KAAK,OAAO,GAAO,EAMrB,WAAW,CAAC,EAA2B,CACrC,QAAY,EAAK,KAAU,OAAO,QAAQ,CAAM,EAC9C,KAAK,OAAO,GAAO,EAOvB,KAAK,EAAS,CACZ,QAAY,EAAK,KAAQ,OAAO,QAAQ,KAAK,YAAY,EACvD,KAAK,OAAO,GAAO,EAAI,MAQ3B,SAAS,CAAC,EAA2C,CAEnD,OADA,KAAK,WAAW,IAAI,CAAQ,EACrB,IAAM,KAAK,WAAW,OAAO,CAAQ,EAM9C,aAAa,CAAC,EAAa,EAAmC,CAC5D,KAAK,aAAa,GAAO,EACzB,KAAK,QAAQ,GAAO,EAAW,MAEnC,CC/PO,MAAM,CAAe,CAClB,QAAU,IAAI,IACd,MAAQ,IAAI,IACZ,YAA6C,IAAI,IACjD,cAAiD,IAAI,IAM7D,QAAW,CACT,EACA,EACA,EACQ,CAER,GAAI,KAAK,QAAQ,IAAI,CAAI,EACvB,KAAK,WAAW,CAAI,EAGtB,IAAM,EAAK,KAAK,YAAY,EAEtB,EAAkC,CACtC,OACA,KACA,SACA,UACF,EAEA,KAAK,QAAQ,IAAI,EAAM,CAAU,EACjC,KAAK,MAAM,IAAI,EAAI,CAAU,EAG7B,QAAW,KAAY,KAAK,YAC1B,GAAI,CACF,EAAS,EAAM,EAAI,CAAM,EACzB,MAAO,EAAG,CACV,QAAQ,MAAM,8CAA+C,CAAC,EAIlE,OAAO,EAMT,UAAU,CAAC,EAAuB,CAChC,IAAM,EAAM,KAAK,QAAQ,IAAI,CAAI,EACjC,GAAI,CAAC,EAAK,MAAO,GAEjB,KAAK,QAAQ,OAAO,CAAI,EACxB,KAAK,MAAM,OAAO,EAAI,EAAE,EAGxB,QAAW,KAAY,KAAK,cAC1B,GAAI,CACF,EAAS,CAAI,EACb,MAAO,EAAG,CACV,QAAQ,MAAM,gDAAiD,CAAC,EAIpE,MAAO,GAMT,UAAuB,CAAC,EAA6B,CACnD,OAAO,KAAK,QAAQ,IAAI,CAAI,GAAG,OAMjC,QAAqB,CAAC,EAA2B,CAC/C,OAAO,KAAK,MAAM,IAAI,CAAE,GAAG,OAM7B,OAAO,CAAC,EAA4C,CAClD,OAAO,KAAK,QAAQ,IAAI,CAAI,EAM9B,GAAG,CAAC,EAAuB,CACzB,OAAO,KAAK,QAAQ,IAAI,CAAI,EAM9B,QAAQ,EAAa,CACnB,OAAO,MAAM,KAAK,KAAK,QAAQ,KAAK,CAAC,EAMvC,MAAM,EAAyB,CAC7B,IAAM,EAAS,IAAI,IACnB,QAAY,EAAM,KAAe,KAAK,QACpC,EAAO,IAAI,EAAM,EAAW,MAAM,EAEpC,OAAO,EAMT,KAAK,CAAC,EAAmE,CACvE,IAAM,EAA8B,CAAC,EACrC,QAAW,KAAO,KAAK,QAAQ,OAAO,EACpC,GAAI,EAAU,CAAG,EACf,EAAQ,KAAK,CAAG,EAGpB,OAAO,EAMT,UAAuB,CAAC,EAAmB,CACzC,OAAO,KAAK,MAAM,CAAC,IAAQ,EAAI,UAAU,OAAS,CAAI,EAAE,IACtD,CAAC,IAAQ,EAAI,MACf,EAMF,KAAK,EAAS,CACZ,IAAM,EAAQ,MAAM,KAAK,KAAK,QAAQ,KAAK,CAAC,EAC5C,QAAW,KAAQ,EACjB,KAAK,WAAW,CAAI,EAOxB,UAAU,CAAC,EAAgD,CAEzD,OADA,KAAK,YAAY,IAAI,CAAQ,EACtB,IAAM,KAAK,YAAY,OAAO,CAAQ,EAM/C,YAAY,CAAC,EAAkD,CAE7D,OADA,KAAK,cAAc,IAAI,CAAQ,EACxB,IAAM,KAAK,cAAc,OAAO,CAAQ,KAM7C,KAAI,EAAW,CACjB,OAAO,KAAK,QAAQ,KAGd,WAAW,EAAW,CAC5B,MAAO,OAAO,KAAK,IAAI,KAAK,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,MAAM,EAAG,CAAC,IAErE,CCtEO,MAAM,CAAW,CAEd,SAAW,GACX,WAAa,GACb,aAAe,GACf,cAAgB,EAGhB,YACA,QACA,SAGA,OACA,WACA,UAAY,UAGZ,UAA+B,CAAC,EAChC,aACA,kBACA,eAAiB,EACjB,gBACA,gBAER,WAAW,CAAC,EAA0B,CAKpC,GAJA,KAAK,OAAS,EAAO,MACrB,KAAK,WAAa,EAAO,WAAa,GAGlC,EAAO,WACT,KAAK,OAAO,MAAM,WAAa,EAAO,WAIxC,KAAK,YAAc,IAAI,EACrB,EAAO,WAAa,CAAC,EACrB,EAAO,aACT,EACA,KAAK,QAAU,IAAI,EACnB,KAAK,SAAW,IAAI,EAGpB,KAAK,YAAY,UAAU,CAAC,EAAK,EAAO,IAAkB,CACxD,KAAK,QAAQ,KAAuB,CAClC,KAAM,cACN,UAAW,KAAK,IAAI,EACpB,MACA,QACA,eACF,CAAC,EACF,EAGD,KAAK,qBAAqB,EAG1B,KAAK,UAAU,EAAO,MAAO,EAAO,UAAY,EAAI,KAKlD,QAAO,EAAY,CACrB,OAAO,KAAK,YAGV,UAAS,EAAY,CACvB,OAAO,KAAK,cAGV,YAAW,EAAY,CACzB,OAAO,KAAK,gBAGV,aAAY,EAAW,CACzB,OAAO,KAAK,iBAGV,MAAK,EAAgB,CACvB,OAAO,KAAK,UAIV,OAAM,EAAgB,CACxB,OAAO,KAAK,YAAY,SAAS,KAI/B,OAAM,EAAiB,CACzB,OAAO,KAAK,WAIV,QAAO,EAAmB,CAC5B,OAAO,KAAK,SAKd,QAAQ,CAAC,EAAa,EAAsB,CAC1C,KAAK,YAAY,IAAI,EAAK,CAAK,EAGjC,SAAS,CAAC,EAAuC,CAC/C,KAAK,YAAY,YAAY,CAAM,EAGrC,SAAS,EAA4B,CACnC,OAAO,KAAK,YAAY,YAAY,EAGtC,YAAY,EAAqB,CAC/B,OAAO,KAAK,YAAY,eAAe,EAGzC,WAAW,EAAS,CAClB,KAAK,YAAY,MAAM,EAKzB,cAA2B,CACzB,EACA,EACA,EACQ,CACR,OAAO,KAAK,SAAS,SAAS,EAAM,EAAQ,CAAQ,EAGtD,gBAA6B,CAAC,EAA6B,CACzD,OAAO,KAAK,SAAS,WAAc,CAAI,EAGzC,cAA2B,CAAC,EAA2B,CACrD,OAAO,KAAK,SAAS,SAAY,CAAE,EAGrC,aAAa,EAAyB,CACpC,OAAO,KAAK,SAAS,OAAO,EAK9B,IAAI,EAAS,CACX,GAAI,KAAK,YAAc,KAAK,aAAc,OAC1C,KAAK,WAAa,GAClB,KAAK,eAAiB,YAAY,IAAI,EACtC,KAAK,MAAM,EACX,KAAK,QAAQ,KAAK,CAAE,KAAM,OAAQ,UAAW,KAAK,IAAI,CAAE,CAAC,EAG3D,KAAK,EAAS,CACZ,GAAI,CAAC,KAAK,WAAY,OAEtB,GADA,KAAK,WAAa,GACd,KAAK,kBACP,qBAAqB,KAAK,iBAAiB,EAC3C,KAAK,kBAAoB,OAE3B,KAAK,QAAQ,KAAK,CAAE,KAAM,QAAS,UAAW,KAAK,IAAI,CAAE,CAAC,EAG5D,MAAM,EAAS,CACb,GAAI,KAAK,WACP,KAAK,MAAM,EAEX,UAAK,KAAK,EAMd,EAA6B,CAC3B,EACA,EACY,CACZ,OAAO,KAAK,QAAQ,GAAG,EAAM,CAAO,EAGtC,IAA+B,CAC7B,EACA,EACY,CACZ,OAAO,KAAK,QAAQ,KAAK,EAAM,CAAO,EAGxC,GAA8B,CAC5B,EACA,EACM,CACN,KAAK,QAAQ,IAAI,EAAM,CAAO,OAK1B,aAAY,CAAC,EAAkC,MAA6B,CAEhF,GAAI,KAAK,gBACP,OAAO,KAAK,gBAAgB,CAAM,EAIpC,IAAM,EAAS,KAAK,OAAO,cAAc,QAAQ,EACjD,GAAI,CAAC,EAEH,OADA,QAAQ,KAAK,0CAA0C,EAChD,KAGT,OAAO,IAAI,QAAQ,CAAC,IAAY,CAC9B,IAAM,EAAW,SAAS,IACpB,EAAU,IAAW,OAAS,KAAO,OAC3C,EAAO,OAAO,CAAC,IAAS,EAAQ,CAAI,EAAG,EAAU,CAAO,EACzD,EAGH,WAAW,EAAW,CACpB,OAAO,KAAK,UAQd,UAAU,CAAC,EAAgC,CACzC,GAAI,OAAO,IAAY,WACrB,KAAK,UAAU,KAAK,CAAO,EAO/B,OAAO,EAAS,CACd,GAAI,KAAK,aAAc,OAOvB,GANA,KAAK,aAAe,GAGpB,KAAK,MAAM,EAGP,KAAK,aACP,GAAI,CACF,KAAK,aAAa,EAClB,MAAO,EAAG,CACV,QAAQ,MAAM,mCAAoC,CAAC,EAKvD,MAAO,KAAK,UAAU,OAAS,EAAG,CAChC,IAAM,EAAU,KAAK,UAAU,IAAI,EACnC,GAAI,EACF,GAAI,CACF,EAAQ,EACR,MAAO,EAAG,CACV,QAAQ,MAAM,8BAA+B,CAAC,GAMpD,KAAK,iBAAiB,WAAW,EAGjC,KAAK,SAAS,MAAM,EAGpB,KAAK,QAAQ,mBAAmB,EAGhC,KAAK,QAAQ,KAAK,CAAE,KAAM,YAAa,UAAW,KAAK,IAAI,CAAE,CAAC,OAKlD,UAAS,CAAC,EAAsB,EAAkC,CAC9E,GAAI,CAEF,IAAM,EAAU,KAAK,eAAe,EAG9B,EAAU,MAAM,EAAM,CAAO,EACnC,GAAI,OAAO,IAAY,WACrB,KAAK,aAAe,EAOtB,GAJA,KAAK,SAAW,GAChB,KAAK,QAAQ,KAAK,CAAE,KAAM,QAAS,UAAW,KAAK,IAAI,CAAE,CAAC,EAGtD,EACF,KAAK,KAAK,EAEZ,MAAO,EAAO,CACd,QAAQ,MAAM,4BAA6B,CAAK,EAChD,KAAK,QAAQ,KAAiB,CAC5B,KAAM,QACN,UAAW,KAAK,IAAI,EACpB,MAAO,aAAiB,MAAQ,EAAY,MAAM,OAAO,CAAK,CAAC,CACjE,CAAC,GAIG,cAAc,EAAsB,CAC1C,MAAO,CACL,MAAO,KAAK,OACZ,OAAQ,KAAK,YAAY,SAAS,EAClC,QAAS,KAAK,kBAAkB,EAChC,YAAa,KAAK,sBAAsB,EACxC,eAAgB,CAAC,EAAM,EAAQ,IAC7B,KAAK,SAAS,SAAS,EAAM,EAAQ,CAAQ,EAC/C,iBAAkB,CAAC,IAAS,KAAK,SAAS,WAAW,CAAI,EACzD,WAAY,IACd,EAGM,iBAAiB,EAAe,CACtC,MAAO,CACL,aAAc,CAAC,IAAW,KAAK,aAAa,CAAM,EAClD,YAAa,CAAC,IAAa,CACzB,KAAK,UAAY,GAEnB,uBAAwB,CAAC,IAAY,CACnC,KAAK,gBAAkB,EAE3B,EAGM,qBAAqB,EAAmB,CAC9C,MAAO,CACL,OACA,SACA,SAAU,CAAC,IAAa,CACtB,IAAM,EAAU,IAAM,CACpB,EAAS,KAAK,OAAO,YAAa,KAAK,OAAO,YAAY,GAI5D,EAAQ,EAGR,IAAM,EAAK,IAAI,eAAe,CAAO,EACrC,EAAG,QAAQ,KAAK,MAAM,EAEtB,IAAM,EAAU,IAAM,EAAG,WAAW,EAEpC,OADA,KAAK,UAAU,KAAK,CAAO,EACpB,GAET,WAAY,CAAC,IAAY,KAAK,WAAW,CAAO,CAClD,EAGM,oBAAoB,EAAS,CACnC,KAAK,gBAAkB,IAAI,eAAe,CAAC,IAAY,CACrD,QAAW,KAAS,EAAS,CAC3B,IAAQ,QAAO,UAAW,EAAM,YAChC,KAAK,QAAQ,KAAkB,CAC7B,KAAM,SACN,UAAW,KAAK,IAAI,EACpB,QACA,QACF,CAAC,GAEJ,EACD,KAAK,gBAAgB,QAAQ,KAAK,MAAM,EAGlC,KAAK,EAAS,CACpB,GAAI,CAAC,KAAK,WAAY,OAEtB,IAAM,EAAM,YAAY,IAAI,EACtB,EAAY,EAAM,KAAK,eACvB,EAAiB,KAAO,KAAK,WAEnC,GAAI,GAAa,EACf,KAAK,gBACL,KAAK,eAAiB,EAAO,EAAY,EAEzC,KAAK,QAAQ,KAAiB,CAC5B,KAAM,QACN,UAAW,KAAK,IAAI,EACpB,MAAO,KAAK,cACZ,WACF,CAAC,EAGH,KAAK,kBAAoB,sBAAsB,IAAM,KAAK,MAAM,CAAC,EAErE",
11
- "debugId": "BE20C8AEA123CFE964756E2164756E21",
11
+ "mappings": "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",
12
+ "debugId": "9F2CC592AD55E80264756E2164756E21",
12
13
  "names": []
13
14
  }
package/dist/index.d.ts CHANGED
@@ -13,6 +13,8 @@
13
13
  */
14
14
  export { Experience } from "./core/Experience";
15
15
  export type { ExperienceConfig, ExperienceContext, ExportsApi, EnvironmentApi, } from "./core/Experience";
16
+ export { ExperienceController } from "./core/ExperienceController";
17
+ export type { ExportedExperienceElement, ExperienceControllerConfig, } from "./core/ExperienceController";
16
18
  export { ParamStore } from "./core/ParamStore";
17
19
  export type { ParamType, ParamDefinition, ParamDefinitions, ParamValues, ParamChangeCallback, SelectOption, } from "./core/ParamStore";
18
20
  export { EventEmitter } from "./core/EventEmitter";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAMH,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,YAAY,EACV,gBAAgB,EAChB,iBAAiB,EACjB,UAAU,EACV,cAAc,GACf,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,YAAY,EACV,SAAS,EACT,eAAe,EACf,gBAAgB,EAChB,WAAW,EACX,mBAAmB,EACnB,YAAY,GACb,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,YAAY,EACV,mBAAmB,EACnB,eAAe,EACf,UAAU,EACV,UAAU,EACV,UAAU,EACV,WAAW,EACX,gBAAgB,EAChB,SAAS,EACT,UAAU,EACV,YAAY,GACb,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,YAAY,EACV,gBAAgB,GACjB,MAAM,uBAAuB,CAAC;AAO/B,OAAO,EACL,iBAAiB,EACjB,kBAAkB,EAClB,cAAc,EACd,oBAAoB,EACpB,WAAW,EACZ,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EACL,OAAO,EACP,SAAS,EACT,aAAa,EACb,gBAAgB,EACjB,MAAM,eAAe,CAAC;AAGvB,OAAO,EACL,iBAAiB,EACjB,kBAAkB,EAClB,cAAc,EACd,oBAAoB,EACpB,WAAW,GACZ,CAAC;AAEF,YAAY,EAEV,WAAW,EACX,qBAAqB,EACrB,iBAAiB,EACjB,kBAAkB,EAClB,uBAAuB,EACvB,sBAAsB,EACtB,wBAAwB,EACxB,uBAAuB,EACvB,uBAAuB,EAGvB,wBAAwB,EACxB,eAAe,EAGf,eAAe,EACf,oBAAoB,GACrB,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EACL,OAAO,EACP,SAAS,EACT,aAAa,EACb,gBAAgB,GACjB,CAAC;AAEF,YAAY,EAEV,uBAAuB,EACvB,oBAAoB,EACpB,wBAAwB,EACxB,uBAAuB,EAGvB,cAAc,EACd,kBAAkB,EAClB,qBAAqB,EACrB,iBAAiB,EACjB,gBAAgB,EAChB,oBAAoB,EACpB,0BAA0B,EAC1B,0BAA0B,EAC1B,2BAA2B,EAG3B,oBAAoB,EACpB,mBAAmB,EAGnB,YAAY,EACZ,WAAW,GACZ,MAAM,eAAe,CAAC;AAmCvB,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,QAEpE;AAGD,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,iBAAiB,GAAG,IAAI,QAE1E"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAMH,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,YAAY,EACV,gBAAgB,EAChB,iBAAiB,EACjB,UAAU,EACV,cAAc,GACf,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AACnE,YAAY,EACV,yBAAyB,EACzB,0BAA0B,GAC3B,MAAM,6BAA6B,CAAC;AAErC,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,YAAY,EACV,SAAS,EACT,eAAe,EACf,gBAAgB,EAChB,WAAW,EACX,mBAAmB,EACnB,YAAY,GACb,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,YAAY,EACV,mBAAmB,EACnB,eAAe,EACf,UAAU,EACV,UAAU,EACV,UAAU,EACV,WAAW,EACX,gBAAgB,EAChB,SAAS,EACT,UAAU,EACV,YAAY,GACb,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,YAAY,EACV,gBAAgB,GACjB,MAAM,uBAAuB,CAAC;AAO/B,OAAO,EACL,iBAAiB,EACjB,kBAAkB,EAClB,cAAc,EACd,oBAAoB,EACpB,WAAW,EACZ,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EACL,OAAO,EACP,SAAS,EACT,aAAa,EACb,gBAAgB,EACjB,MAAM,eAAe,CAAC;AAGvB,OAAO,EACL,iBAAiB,EACjB,kBAAkB,EAClB,cAAc,EACd,oBAAoB,EACpB,WAAW,GACZ,CAAC;AAEF,YAAY,EAEV,WAAW,EACX,qBAAqB,EACrB,iBAAiB,EACjB,kBAAkB,EAClB,uBAAuB,EACvB,sBAAsB,EACtB,wBAAwB,EACxB,uBAAuB,EACvB,uBAAuB,EAGvB,wBAAwB,EACxB,eAAe,EAGf,eAAe,EACf,oBAAoB,GACrB,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EACL,OAAO,EACP,SAAS,EACT,aAAa,EACb,gBAAgB,GACjB,CAAC;AAEF,YAAY,EAEV,uBAAuB,EACvB,oBAAoB,EACpB,wBAAwB,EACxB,uBAAuB,EAGvB,cAAc,EACd,kBAAkB,EAClB,qBAAqB,EACrB,iBAAiB,EACjB,gBAAgB,EAChB,oBAAoB,EACpB,0BAA0B,EAC1B,0BAA0B,EAC1B,2BAA2B,EAG3B,oBAAoB,EACpB,mBAAmB,EAGnB,YAAY,EACZ,WAAW,GACZ,MAAM,eAAe,CAAC;AAmCvB,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,QAEpE;AAGD,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,iBAAiB,GAAG,IAAI,QAE1E"}