@hypertools/sdk 0.3.2 → 0.4.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.
- package/README.md +175 -0
- package/dist/core/ExperienceController.d.ts +39 -0
- package/dist/core/ExperienceController.d.ts.map +1 -1
- package/dist/core/index.js +2 -2
- package/dist/core/index.js.map +3 -3
- package/dist/index.js +39 -39
- package/dist/index.js.map +3 -3
- package/examples/README.md +84 -0
- package/examples/p5js/index.html +39 -0
- package/examples/p5js/main.ts +136 -0
- package/examples/react/index.html +22 -0
- package/examples/react/main.tsx +310 -0
- package/examples/react-landing/README.md +64 -0
- package/examples/react-landing/index.html +14 -0
- package/examples/react-landing/package.json +23 -0
- package/examples/react-landing/public/boids-flocking-project.js +12 -0
- package/examples/react-landing/src/App.css +379 -0
- package/examples/react-landing/src/App.tsx +483 -0
- package/examples/react-landing/src/main.tsx +9 -0
- package/examples/react-landing/src/types.d.ts +24 -0
- package/examples/react-landing/tsconfig.json +20 -0
- package/examples/react-landing/vite.config.ts +9 -0
- package/examples/recording/index.html +113 -0
- package/examples/recording/main.ts +256 -0
- package/examples/threejs/index.html +40 -0
- package/examples/threejs/main.ts +196 -0
- package/examples/vanilla-canvas/index.html +77 -0
- package/examples/vanilla-canvas/main.ts +162 -0
- package/package.json +5 -1
package/README.md
CHANGED
|
@@ -402,10 +402,185 @@ controls.refresh();
|
|
|
402
402
|
controls.dispose();
|
|
403
403
|
```
|
|
404
404
|
|
|
405
|
+
## Using Exported HyperTools Experiences
|
|
406
|
+
|
|
407
|
+
When you export a project from [HyperTools](https://hypertools.dev), you get a standalone web component that can be embedded anywhere. Use `ExperienceController` from this SDK to control it programmatically.
|
|
408
|
+
|
|
409
|
+
### Setup
|
|
410
|
+
|
|
411
|
+
1. **Get your exported experience** - Export from HyperTools to get a JS file (e.g., `my-experience.js`)
|
|
412
|
+
|
|
413
|
+
2. **Load the experience** in your HTML:
|
|
414
|
+
```html
|
|
415
|
+
<script src="./my-experience.js"></script>
|
|
416
|
+
<my-experience></my-experience>
|
|
417
|
+
```
|
|
418
|
+
|
|
419
|
+
3. **Install the SDK** to control it:
|
|
420
|
+
```bash
|
|
421
|
+
npm install @hypertools/sdk
|
|
422
|
+
```
|
|
423
|
+
|
|
424
|
+
### Basic Control
|
|
425
|
+
|
|
426
|
+
```typescript
|
|
427
|
+
import { ExperienceController } from '@hypertools/sdk';
|
|
428
|
+
|
|
429
|
+
// Get reference to the web component
|
|
430
|
+
const element = document.querySelector('my-experience');
|
|
431
|
+
|
|
432
|
+
// Connect the controller
|
|
433
|
+
const controller = new ExperienceController({
|
|
434
|
+
element,
|
|
435
|
+
initialParams: {
|
|
436
|
+
speed: 5,
|
|
437
|
+
color: '#ff0000',
|
|
438
|
+
},
|
|
439
|
+
});
|
|
440
|
+
|
|
441
|
+
// Control parameters
|
|
442
|
+
controller.setParam('speed', 10);
|
|
443
|
+
controller.setParams({ speed: 8, color: '#00ff00' });
|
|
444
|
+
|
|
445
|
+
// Get current values
|
|
446
|
+
const params = controller.getParams();
|
|
447
|
+
const paramDefs = controller.getParamDefs();
|
|
448
|
+
|
|
449
|
+
// Reset to defaults
|
|
450
|
+
controller.resetParams();
|
|
451
|
+
|
|
452
|
+
// Listen to changes
|
|
453
|
+
controller.on('paramChange', (event) => {
|
|
454
|
+
console.log(`${event.key} changed to ${event.value}`);
|
|
455
|
+
});
|
|
456
|
+
|
|
457
|
+
// Cleanup when done
|
|
458
|
+
controller.destroy();
|
|
459
|
+
```
|
|
460
|
+
|
|
461
|
+
### Dispatching Events
|
|
462
|
+
|
|
463
|
+
Trigger interactions programmatically by dispatching synthetic events:
|
|
464
|
+
|
|
465
|
+
```typescript
|
|
466
|
+
// Simulate a click
|
|
467
|
+
controller.dispatchToCanvas('click', { clientX: 400, clientY: 300 });
|
|
468
|
+
|
|
469
|
+
// Simulate a long press (e.g., for formation triggers)
|
|
470
|
+
controller.dispatchToCanvas('mousedown', { clientX: 400, clientY: 300 });
|
|
471
|
+
setTimeout(() => {
|
|
472
|
+
controller.dispatchToCanvas('mouseup', { clientX: 400, clientY: 300 });
|
|
473
|
+
}, 600);
|
|
474
|
+
|
|
475
|
+
// Keyboard events
|
|
476
|
+
controller.dispatchToCanvas('keydown', { key: 'Space' });
|
|
477
|
+
|
|
478
|
+
// Custom events
|
|
479
|
+
controller.dispatchCustomEvent('myEvent', { data: 'hello' });
|
|
480
|
+
```
|
|
481
|
+
|
|
482
|
+
### React Integration
|
|
483
|
+
|
|
484
|
+
```tsx
|
|
485
|
+
import { useEffect, useRef, useState } from 'react';
|
|
486
|
+
import { ExperienceController } from '@hypertools/sdk';
|
|
487
|
+
import type { ExportedExperienceElement } from '@hypertools/sdk';
|
|
488
|
+
|
|
489
|
+
function App() {
|
|
490
|
+
const experienceRef = useRef<ExportedExperienceElement>(null);
|
|
491
|
+
const controllerRef = useRef<ExperienceController | null>(null);
|
|
492
|
+
const [isReady, setIsReady] = useState(false);
|
|
493
|
+
|
|
494
|
+
useEffect(() => {
|
|
495
|
+
const element = experienceRef.current;
|
|
496
|
+
if (!element) return;
|
|
497
|
+
|
|
498
|
+
const onReady = () => {
|
|
499
|
+
controllerRef.current = new ExperienceController({ element });
|
|
500
|
+
setIsReady(true);
|
|
501
|
+
};
|
|
502
|
+
|
|
503
|
+
element.addEventListener('ready', onReady, { once: true });
|
|
504
|
+
|
|
505
|
+
return () => {
|
|
506
|
+
element.removeEventListener('ready', onReady);
|
|
507
|
+
controllerRef.current?.destroy();
|
|
508
|
+
};
|
|
509
|
+
}, []);
|
|
510
|
+
|
|
511
|
+
return (
|
|
512
|
+
<div>
|
|
513
|
+
{/* @ts-expect-error - Custom element */}
|
|
514
|
+
<my-experience ref={experienceRef} />
|
|
515
|
+
|
|
516
|
+
{isReady && (
|
|
517
|
+
<button onClick={() => controllerRef.current?.setParam('speed', 10)}>
|
|
518
|
+
Speed Up
|
|
519
|
+
</button>
|
|
520
|
+
)}
|
|
521
|
+
</div>
|
|
522
|
+
);
|
|
523
|
+
}
|
|
524
|
+
```
|
|
525
|
+
|
|
526
|
+
### ExperienceController API
|
|
527
|
+
|
|
528
|
+
```typescript
|
|
529
|
+
// Constructor options
|
|
530
|
+
interface ExperienceControllerConfig {
|
|
531
|
+
element: ExportedExperienceElement; // The web component
|
|
532
|
+
initialParams?: Record<string, unknown>; // Override initial values
|
|
533
|
+
autoConnect?: boolean; // Connect immediately (default: true)
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
// Methods
|
|
537
|
+
controller.connect(); // Connect to element
|
|
538
|
+
controller.disconnect(); // Disconnect from element
|
|
539
|
+
controller.destroy(); // Full cleanup
|
|
540
|
+
|
|
541
|
+
controller.setParam(key, value);
|
|
542
|
+
controller.setParams(params);
|
|
543
|
+
controller.getParams();
|
|
544
|
+
controller.getParamDefs();
|
|
545
|
+
controller.resetParams();
|
|
546
|
+
|
|
547
|
+
controller.on(event, handler); // Subscribe
|
|
548
|
+
controller.once(event, handler); // Subscribe once
|
|
549
|
+
controller.off(event, handler); // Unsubscribe
|
|
550
|
+
|
|
551
|
+
controller.dispatchToCanvas(eventType, eventInit); // Dispatch to canvas
|
|
552
|
+
controller.dispatchToElement(eventType, eventInit); // Dispatch to element
|
|
553
|
+
controller.dispatchCustomEvent(type, detail); // Custom event
|
|
554
|
+
|
|
555
|
+
controller.getCanvas(); // Get canvas element
|
|
556
|
+
controller.getMount(); // Get mount element
|
|
557
|
+
|
|
558
|
+
// Properties
|
|
559
|
+
controller.element; // The web component
|
|
560
|
+
controller.isConnected; // Connection status
|
|
561
|
+
controller.isDestroyed; // Destroyed status
|
|
562
|
+
|
|
563
|
+
// Static factories
|
|
564
|
+
ExperienceController.fromSelector('my-experience');
|
|
565
|
+
await ExperienceController.whenDefined('my-experience');
|
|
566
|
+
```
|
|
567
|
+
|
|
568
|
+
### Building Custom Features
|
|
569
|
+
|
|
570
|
+
See [`examples/react-landing/`](./examples/react-landing/) for a complete example showing how to build custom features on top of exported experiences:
|
|
571
|
+
|
|
572
|
+
- **Preset System** - Pre-configured settings with visual selection
|
|
573
|
+
- **Click-to-Form Mode** - Click anywhere to trigger interactions at that position
|
|
574
|
+
- **Auto-pilot Mode** - Automatically cycle through presets
|
|
575
|
+
- **Idle Screensaver** - Start animations after inactivity
|
|
576
|
+
- **Share Configuration** - Generate shareable URLs with encoded settings
|
|
577
|
+
- **Keyboard Shortcuts** - Custom keyboard controls
|
|
578
|
+
|
|
405
579
|
## Examples
|
|
406
580
|
|
|
407
581
|
See the `/examples` directory for complete working examples:
|
|
408
582
|
|
|
583
|
+
- `examples/react-landing/` - **React app with exported experience as background + custom features**
|
|
409
584
|
- `examples/vanilla-canvas/` - Pure Canvas API
|
|
410
585
|
- `examples/p5js/` - p5.js sketch
|
|
411
586
|
- `examples/threejs/` - Three.js scene
|
|
@@ -100,12 +100,51 @@ export declare class ExperienceController {
|
|
|
100
100
|
* Unsubscribe from an event
|
|
101
101
|
*/
|
|
102
102
|
off<T extends ExperienceEvent>(type: T['type'], handler: EventHandler<T>): void;
|
|
103
|
+
/**
|
|
104
|
+
* Dispatch a synthetic event to the experience's canvas
|
|
105
|
+
* Useful for triggering interactions programmatically (mousedown, click, etc.)
|
|
106
|
+
*
|
|
107
|
+
* @example
|
|
108
|
+
* ```typescript
|
|
109
|
+
* // Simulate a click at center
|
|
110
|
+
* controller.dispatchToCanvas('click', { clientX: 500, clientY: 300 });
|
|
111
|
+
*
|
|
112
|
+
* // Simulate long press for formation
|
|
113
|
+
* controller.dispatchToCanvas('mousedown', { clientX: 400, clientY: 300 });
|
|
114
|
+
* setTimeout(() => controller.dispatchToCanvas('mouseup'), 600);
|
|
115
|
+
* ```
|
|
116
|
+
*/
|
|
117
|
+
dispatchToCanvas(eventType: string, eventInit?: MouseEventInit | KeyboardEventInit | EventInit): boolean;
|
|
118
|
+
/**
|
|
119
|
+
* Dispatch a synthetic event to the experience element itself
|
|
120
|
+
*/
|
|
121
|
+
dispatchToElement(eventType: string, eventInit?: CustomEventInit | EventInit): boolean;
|
|
122
|
+
/**
|
|
123
|
+
* Dispatch a custom event with data to the experience
|
|
124
|
+
*/
|
|
125
|
+
dispatchCustomEvent(eventType: string, detail?: unknown): boolean;
|
|
126
|
+
/**
|
|
127
|
+
* Get the canvas element inside the experience (if any)
|
|
128
|
+
*/
|
|
129
|
+
getCanvas(): HTMLCanvasElement | null;
|
|
130
|
+
/**
|
|
131
|
+
* Get the mount element inside the experience shadow DOM
|
|
132
|
+
*/
|
|
133
|
+
getMount(): HTMLElement | null;
|
|
103
134
|
/**
|
|
104
135
|
* Destroy the controller and disconnect from the element
|
|
105
136
|
*/
|
|
106
137
|
destroy(): void;
|
|
107
138
|
private _handleReady;
|
|
108
139
|
private _handleParamChange;
|
|
140
|
+
/**
|
|
141
|
+
* Find canvas element inside the experience's shadow DOM
|
|
142
|
+
*/
|
|
143
|
+
private _findCanvas;
|
|
144
|
+
/**
|
|
145
|
+
* Create appropriate event based on type
|
|
146
|
+
*/
|
|
147
|
+
private _createEvent;
|
|
109
148
|
/**
|
|
110
149
|
* Connect to an experience by CSS selector
|
|
111
150
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ExperienceController.d.ts","sourceRoot":"","sources":["../../src/core/ExperienceController.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,OAAO,EAAgB,KAAK,eAAe,EAAE,KAAK,YAAY,EAAyB,MAAM,gBAAgB,CAAC;AAM9G;;GAEG;AACH,MAAM,WAAW,yBAA0B,SAAQ,WAAW;IAC5D,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI,CAAC;IAC5C,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IACjD,SAAS,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACrC,YAAY,IAAI,MAAM,CAAC,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,OAAO,CAAC;QAAC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;KAAE,CAAC,CAAC;CAC1F;AAED,MAAM,WAAW,0BAA0B;IACzC,yCAAyC;IACzC,OAAO,EAAE,yBAAyB,CAAC;IAEnC,mDAAmD;IACnD,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAExC,+CAA+C;IAC/C,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAMD,qBAAa,oBAAoB;IAC/B,OAAO,CAAC,QAAQ,CAA4B;IAC5C,OAAO,CAAC,OAAO,CAAe;IAC9B,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,YAAY,CAAS;IAG7B,OAAO,CAAC,kBAAkB,CAAqB;IAC/C,OAAO,CAAC,wBAAwB,CAAqB;gBAEzC,eAAe,EAAE,yBAAyB,GAAG,0BAA0B;IA2BnF;;OAEG;IACH,OAAO,IAAI,IAAI;IAYf;;OAEG;IACH,UAAU,IAAI,IAAI;IAalB,IAAI,OAAO,IAAI,yBAAyB,CAEvC;IAED,IAAI,WAAW,IAAI,OAAO,CAEzB;IAED,IAAI,WAAW,IAAI,OAAO,CAEzB;IAID;;OAEG;IACH,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI;IAI3C;;OAEG;IACH,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAIhD;;OAEG;IACH,SAAS,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAIpC;;OAEG;IACH,YAAY,IAAI,MAAM,CAAC,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,OAAO,CAAC;QAAC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;KAAE,CAAC;IAIxF;;OAEG;IACH,WAAW,IAAI,IAAI;IAanB;;OAEG;IACH,EAAE,CAAC,CAAC,SAAS,eAAe,EAC1B,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,EACf,OAAO,EAAE,YAAY,CAAC,CAAC,CAAC,GACvB,MAAM,IAAI;IAIb;;OAEG;IACH,IAAI,CAAC,CAAC,SAAS,eAAe,EAC5B,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,EACf,OAAO,EAAE,YAAY,CAAC,CAAC,CAAC,GACvB,MAAM,IAAI;IAIb;;OAEG;IACH,GAAG,CAAC,CAAC,SAAS,eAAe,EAC3B,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,EACf,OAAO,EAAE,YAAY,CAAC,CAAC,CAAC,GACvB,IAAI;IAMP;;OAEG;IACH,OAAO,IAAI,IAAI;IAYf,OAAO,CAAC,YAAY;IAIpB,OAAO,CAAC,kBAAkB;
|
|
1
|
+
{"version":3,"file":"ExperienceController.d.ts","sourceRoot":"","sources":["../../src/core/ExperienceController.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,OAAO,EAAgB,KAAK,eAAe,EAAE,KAAK,YAAY,EAAyB,MAAM,gBAAgB,CAAC;AAM9G;;GAEG;AACH,MAAM,WAAW,yBAA0B,SAAQ,WAAW;IAC5D,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI,CAAC;IAC5C,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IACjD,SAAS,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACrC,YAAY,IAAI,MAAM,CAAC,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,OAAO,CAAC;QAAC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;KAAE,CAAC,CAAC;CAC1F;AAED,MAAM,WAAW,0BAA0B;IACzC,yCAAyC;IACzC,OAAO,EAAE,yBAAyB,CAAC;IAEnC,mDAAmD;IACnD,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAExC,+CAA+C;IAC/C,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAMD,qBAAa,oBAAoB;IAC/B,OAAO,CAAC,QAAQ,CAA4B;IAC5C,OAAO,CAAC,OAAO,CAAe;IAC9B,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,YAAY,CAAS;IAG7B,OAAO,CAAC,kBAAkB,CAAqB;IAC/C,OAAO,CAAC,wBAAwB,CAAqB;gBAEzC,eAAe,EAAE,yBAAyB,GAAG,0BAA0B;IA2BnF;;OAEG;IACH,OAAO,IAAI,IAAI;IAYf;;OAEG;IACH,UAAU,IAAI,IAAI;IAalB,IAAI,OAAO,IAAI,yBAAyB,CAEvC;IAED,IAAI,WAAW,IAAI,OAAO,CAEzB;IAED,IAAI,WAAW,IAAI,OAAO,CAEzB;IAID;;OAEG;IACH,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI;IAI3C;;OAEG;IACH,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAIhD;;OAEG;IACH,SAAS,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAIpC;;OAEG;IACH,YAAY,IAAI,MAAM,CAAC,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,OAAO,CAAC;QAAC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;KAAE,CAAC;IAIxF;;OAEG;IACH,WAAW,IAAI,IAAI;IAanB;;OAEG;IACH,EAAE,CAAC,CAAC,SAAS,eAAe,EAC1B,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,EACf,OAAO,EAAE,YAAY,CAAC,CAAC,CAAC,GACvB,MAAM,IAAI;IAIb;;OAEG;IACH,IAAI,CAAC,CAAC,SAAS,eAAe,EAC5B,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,EACf,OAAO,EAAE,YAAY,CAAC,CAAC,CAAC,GACvB,MAAM,IAAI;IAIb;;OAEG;IACH,GAAG,CAAC,CAAC,SAAS,eAAe,EAC3B,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,EACf,OAAO,EAAE,YAAY,CAAC,CAAC,CAAC,GACvB,IAAI;IAMP;;;;;;;;;;;;;OAaG;IACH,gBAAgB,CACd,SAAS,EAAE,MAAM,EACjB,SAAS,CAAC,EAAE,cAAc,GAAG,iBAAiB,GAAG,SAAS,GACzD,OAAO;IAWV;;OAEG;IACH,iBAAiB,CACf,SAAS,EAAE,MAAM,EACjB,SAAS,CAAC,EAAE,eAAe,GAAG,SAAS,GACtC,OAAO;IAKV;;OAEG;IACH,mBAAmB,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,GAAG,OAAO;IASjE;;OAEG;IACH,SAAS,IAAI,iBAAiB,GAAG,IAAI;IAIrC;;OAEG;IACH,QAAQ,IAAI,WAAW,GAAG,IAAI;IAM9B;;OAEG;IACH,OAAO,IAAI,IAAI;IAYf,OAAO,CAAC,YAAY;IAIpB,OAAO,CAAC,kBAAkB;IAgB1B;;OAEG;IACH,OAAO,CAAC,WAAW;IAWnB;;OAEG;IACH,OAAO,CAAC,YAAY;IA0CpB;;OAEG;IACH,MAAM,CAAC,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,oBAAoB;IAQpG;;OAEG;WACU,WAAW,CACtB,OAAO,EAAE,MAAM,EACf,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACtC,OAAO,CAAC,oBAAoB,CAAC;CAYjC"}
|
package/dist/core/index.js
CHANGED
|
@@ -8,8 +8,8 @@
|
|
|
8
8
|
* @license MIT
|
|
9
9
|
* @see https://github.com/hypertools/sdk
|
|
10
10
|
*/
|
|
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};
|
|
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 P=(C)=>{this.off(x,P),E(C)};return this.on(x,P)}off(x,E){let P=this._handlers.get(x);if(P)P.delete(E)}emit(x){let E=this._handlers.get(x.type);if(!E)return;for(let P of E)try{P(x)}catch(C){console.error(`[EventEmitter] Handler error for ${x.type}:`,C)}}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[P,C]of Object.entries(x))this._values[P]=C.value;if(E){for(let[P,C]of Object.entries(E))if(P in this._definitions)this._values[P]=this._validate(P,C)}this._proxy=this._createProxy()}_createProxy(){let x=this;return new Proxy(this._values,{get(E,P){return E[P]},set(E,P,C){if(!(P in x._definitions))return console.warn(`[ParamStore] Unknown parameter: ${P}`),!1;let D=x._validate(P,C),R=E[P];if(D!==R)E[P]=D,x._notify(P,D,R);return!0},has(E,P){return P in E},ownKeys(E){return Object.keys(E)},getOwnPropertyDescriptor(E,P){if(P in E)return{enumerable:!0,configurable:!0,value:E[P]};return}})}_validate(x,E){let P=this._definitions[x];if(!P)return E;switch(P.type){case"number":{let C=typeof E==="number"?E:parseFloat(String(E));if(isNaN(C))C=P.value;if(P.min!==void 0)C=Math.max(P.min,C);if(P.max!==void 0)C=Math.min(P.max,C);if(P.step!==void 0)C=Math.round(C/P.step)*P.step;return C}case"color":{let C=String(E);if(/^#[0-9A-Fa-f]{6}$/.test(C))return C;if(/^#[0-9A-Fa-f]{3}$/.test(C))return C;if(/^#[0-9A-Fa-f]{8}$/.test(C))return C;if(/^rgb\(/.test(C))return C;if(/^rgba\(/.test(C))return C;if(/^hsl\(/.test(C))return C;if(/^hsla\(/.test(C))return C;return P.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 C=String(E);return(P.options||[]).some((H)=>typeof H==="object"?H.value===C:H===C)?C:P.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 P.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 P.value}default:return E}}_notify(x,E,P){for(let C of this._listeners)try{C(x,E,P)}catch(D){console.error("[ParamStore] Listener error:",D)}}getProxy(){return this._proxy}getSnapshot(){return{...this._values}}getDefinitions(){return{...this._definitions}}set(x,E){this._proxy[x]=E}setMultiple(x){for(let[E,P]of Object.entries(x))this._proxy[E]=P}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,P){if(this._byName.has(x))this.unregister(x);let C=this._generateId(),D={name:x,id:C,object:E,metadata:P};this._byName.set(x,D),this._byId.set(C,D);for(let R of this._onRegister)try{R(x,C,E)}catch(H){console.error("[ObjectRegistry] onRegister callback error:",H)}return C}unregister(x){let E=this._byName.get(x);if(!E)return!1;this._byName.delete(x),this._byId.delete(E.id);for(let P of this._onUnregister)try{P(x)}catch(C){console.error("[ObjectRegistry] onUnregister callback error:",C)}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,P]of this._byName)x.set(E,P.object);return x}query(x){let E=[];for(let P of this._byName.values())if(x(P))E.push(P);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,P,C)=>{this._events.emit({type:"paramChange",timestamp:Date.now(),key:E,value:P,previousValue:C})}),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,P){return this._objects.register(x,E,P)}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((P)=>{let C=`image/${x}`,D=x==="jpeg"?0.92:void 0;E.toBlob((R)=>P(R),C,D)})}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 P=this._createContext(),C=await x(P);if(typeof C==="function")this._userCleanup=C;if(this._isReady=!0,this._events.emit({type:"ready",timestamp:Date.now()}),E)this.play()}catch(P){console.error("[Experience] Setup error:",P),this._events.emit({type:"error",timestamp:Date.now(),error:P instanceof Error?P:Error(String(P))})}}_createContext(){return{mount:this._mount,params:this._paramStore.getProxy(),exports:this._createExportsApi(),environment:this._createEnvironmentApi(),registerObject:(x,E,P)=>this._objects.register(x,E,P),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 P=new ResizeObserver(E);P.observe(this._mount);let C=()=>P.disconnect();return this._cleanups.push(C),C},addCleanup:(x)=>this.addCleanup(x)}}_setupResizeObserver(){this._resizeObserver=new ResizeObserver((x)=>{for(let E of x){let{width:P,height:C}=E.contentRect;this._events.emit({type:"resize",timestamp:Date.now(),width:P,height:C})}}),this._resizeObserver.observe(this._mount)}_tick(){if(!this._isPlaying)return;let x=performance.now(),E=x-this._lastFrameTime,P=1000/this._frameRate;if(E>=P)this._currentFrame++,this._lastFrameTime=x-E%P,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[P,C]of Object.entries(x))E[P]=C.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)}dispatchToCanvas(x,E){let P=this._findCanvas();if(!P)return console.warn("[ExperienceController] No canvas found in experience"),!1;let C=this._createEvent(x,E);return P.dispatchEvent(C)}dispatchToElement(x,E){let P=this._createEvent(x,E);return this._element.dispatchEvent(P)}dispatchCustomEvent(x,E){let P=new CustomEvent(x,{detail:E,bubbles:!0,cancelable:!0});return this._element.dispatchEvent(P)}getCanvas(){return this._findCanvas()}getMount(){return this._element.shadowRoot?.querySelector(".mount")}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})}_findCanvas(){let x=this._element.shadowRoot;if(x){let E=x.querySelector("canvas");if(E)return E}return this._element.querySelector("canvas")}_createEvent(x,E){let P={bubbles:!0,cancelable:!0,...E};if(x.startsWith("mouse")||x==="click"||x==="dblclick")return new MouseEvent(x,P);if(x.startsWith("key"))return new KeyboardEvent(x,P);if(x.startsWith("pointer"))return new PointerEvent(x,P);if(x.startsWith("touch"))return new TouchEvent(x,P);if(x==="wheel")return new WheelEvent(x,P);if("detail"in(E||{}))return new CustomEvent(x,P);return new Event(x,P)}static fromSelector(x,E){let P=document.querySelector(x);if(!P)throw Error(`[ExperienceController] Element not found: ${x}`);return new A({element:P,initialParams:E})}static async whenDefined(x,E){await customElements.whenDefined(x);let P=document.querySelector(x);if(!P)P=document.createElement(x);return new A({element:P,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=
|
|
15
|
+
//# debugId=AF04FBCAE7C8AF9064756E2164756E21
|
package/dist/core/index.js.map
CHANGED
|
@@ -6,9 +6,9 @@
|
|
|
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
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
|
+
"/**\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 // ===== Event Dispatching =====\n\n /**\n * Dispatch a synthetic event to the experience's canvas\n * Useful for triggering interactions programmatically (mousedown, click, etc.)\n *\n * @example\n * ```typescript\n * // Simulate a click at center\n * controller.dispatchToCanvas('click', { clientX: 500, clientY: 300 });\n *\n * // Simulate long press for formation\n * controller.dispatchToCanvas('mousedown', { clientX: 400, clientY: 300 });\n * setTimeout(() => controller.dispatchToCanvas('mouseup'), 600);\n * ```\n */\n dispatchToCanvas(\n eventType: string,\n eventInit?: MouseEventInit | KeyboardEventInit | EventInit\n ): boolean {\n const canvas = this._findCanvas();\n if (!canvas) {\n console.warn('[ExperienceController] No canvas found in experience');\n return false;\n }\n\n const event = this._createEvent(eventType, eventInit);\n return canvas.dispatchEvent(event);\n }\n\n /**\n * Dispatch a synthetic event to the experience element itself\n */\n dispatchToElement(\n eventType: string,\n eventInit?: CustomEventInit | EventInit\n ): boolean {\n const event = this._createEvent(eventType, eventInit);\n return this._element.dispatchEvent(event);\n }\n\n /**\n * Dispatch a custom event with data to the experience\n */\n dispatchCustomEvent(eventType: string, detail?: unknown): boolean {\n const event = new CustomEvent(eventType, {\n detail,\n bubbles: true,\n cancelable: true,\n });\n return this._element.dispatchEvent(event);\n }\n\n /**\n * Get the canvas element inside the experience (if any)\n */\n getCanvas(): HTMLCanvasElement | null {\n return this._findCanvas();\n }\n\n /**\n * Get the mount element inside the experience shadow DOM\n */\n getMount(): HTMLElement | null {\n return this._element.shadowRoot?.querySelector('.mount') as HTMLElement | null;\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 /**\n * Find canvas element inside the experience's shadow DOM\n */\n private _findCanvas(): HTMLCanvasElement | null {\n // Try shadow DOM first\n const shadowRoot = this._element.shadowRoot;\n if (shadowRoot) {\n const canvas = shadowRoot.querySelector('canvas');\n if (canvas) return canvas;\n }\n // Fallback to direct child\n return this._element.querySelector('canvas');\n }\n\n /**\n * Create appropriate event based on type\n */\n private _createEvent(\n eventType: string,\n eventInit?: MouseEventInit | KeyboardEventInit | CustomEventInit | EventInit\n ): Event {\n const baseInit = { bubbles: true, cancelable: true, ...eventInit };\n\n // Mouse events\n if (eventType.startsWith('mouse') || eventType === 'click' || eventType === 'dblclick') {\n return new MouseEvent(eventType, baseInit as MouseEventInit);\n }\n\n // Keyboard events\n if (eventType.startsWith('key')) {\n return new KeyboardEvent(eventType, baseInit as KeyboardEventInit);\n }\n\n // Pointer events\n if (eventType.startsWith('pointer')) {\n return new PointerEvent(eventType, baseInit as PointerEventInit);\n }\n\n // Touch events (basic support)\n if (eventType.startsWith('touch')) {\n return new TouchEvent(eventType, baseInit as TouchEventInit);\n }\n\n // Wheel events\n if (eventType === 'wheel') {\n return new WheelEvent(eventType, baseInit as WheelEventInit);\n }\n\n // Custom events (if detail is provided)\n if ('detail' in (eventInit || {})) {\n return new CustomEvent(eventType, baseInit as CustomEventInit);\n }\n\n // Generic event\n return new Event(eventType, baseInit);\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"
|
|
10
10
|
],
|
|
11
|
-
"mappings": "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",
|
|
12
|
-
"debugId": "
|
|
11
|
+
"mappings": "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",
|
|
12
|
+
"debugId": "AF04FBCAE7C8AF9064756E2164756E21",
|
|
13
13
|
"names": []
|
|
14
14
|
}
|