@skenora/babylon-editor 0.1.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.
Files changed (34) hide show
  1. package/README.md +34 -0
  2. package/dist/bridge/editor-runtime-bridge.d.ts +47 -0
  3. package/dist/bridge/editor-runtime-bridge.d.ts.map +1 -0
  4. package/dist/bridge/editor-runtime-bridge.js +548 -0
  5. package/dist/bridge/editor-runtime-bridge.js.map +1 -0
  6. package/dist/bridge/projection-operation.d.ts +50 -0
  7. package/dist/bridge/projection-operation.d.ts.map +1 -0
  8. package/dist/bridge/projection-operation.js +12 -0
  9. package/dist/bridge/projection-operation.js.map +1 -0
  10. package/dist/controllers/keyboard-controller.d.ts +17 -0
  11. package/dist/controllers/keyboard-controller.d.ts.map +1 -0
  12. package/dist/controllers/keyboard-controller.js +78 -0
  13. package/dist/controllers/keyboard-controller.js.map +1 -0
  14. package/dist/flow/editor-flow-bridge.d.ts +16 -0
  15. package/dist/flow/editor-flow-bridge.d.ts.map +1 -0
  16. package/dist/flow/editor-flow-bridge.js +46 -0
  17. package/dist/flow/editor-flow-bridge.js.map +1 -0
  18. package/dist/flow/flow-host.d.ts +12 -0
  19. package/dist/flow/flow-host.d.ts.map +1 -0
  20. package/dist/flow/flow-host.js +172 -0
  21. package/dist/flow/flow-host.js.map +1 -0
  22. package/dist/flow/runtime-flow-controller.d.ts +25 -0
  23. package/dist/flow/runtime-flow-controller.d.ts.map +1 -0
  24. package/dist/flow/runtime-flow-controller.js +143 -0
  25. package/dist/flow/runtime-flow-controller.js.map +1 -0
  26. package/dist/index.d.ts +7 -0
  27. package/dist/index.d.ts.map +1 -0
  28. package/dist/index.js +7 -0
  29. package/dist/index.js.map +1 -0
  30. package/dist/runtime-flow.d.ts +3 -0
  31. package/dist/runtime-flow.d.ts.map +1 -0
  32. package/dist/runtime-flow.js +3 -0
  33. package/dist/runtime-flow.js.map +1 -0
  34. package/package.json +42 -0
@@ -0,0 +1,50 @@
1
+ export type EditorRuntimeProjectionPolicy = "strict" | "best-effort";
2
+ export type EditorRuntimeProjectionStatus = "queued" | "loading" | "ready" | "partial" | "failed" | "cancelled";
3
+ export type EditorRuntimeProjectionTerminalStatus = Extract<EditorRuntimeProjectionStatus, "ready" | "partial" | "failed" | "cancelled">;
4
+ export interface EditorRuntimeProjectionModelFailure {
5
+ readonly entityId: string;
6
+ readonly error: unknown;
7
+ }
8
+ /** Identifies the document change that caused one runtime projection request. */
9
+ export interface EditorRuntimeProjectionRequest {
10
+ /** Host-owned operation identifier. Generated by the bridge when omitted. */
11
+ readonly operationId?: string;
12
+ /** Runtime projection identifier. Generated by the bridge when omitted. */
13
+ readonly projectionId?: string;
14
+ /** Expected editor revision for the associated document change. */
15
+ readonly sourceRevision?: number;
16
+ /** Expected editor change identifier. `null` represents an initial load. */
17
+ readonly changeId?: string | null;
18
+ /** Model loading policy for this projection operation. */
19
+ readonly modelLoadPolicy?: EditorRuntimeProjectionPolicy;
20
+ }
21
+ export interface EditorRuntimeProjectionOperation {
22
+ readonly operationId: string;
23
+ readonly projectionId: string;
24
+ readonly documentId: string;
25
+ readonly sourceRevision: number;
26
+ readonly changeId: string | null;
27
+ readonly operation: string;
28
+ readonly modelLoadPolicy: EditorRuntimeProjectionPolicy;
29
+ readonly status: EditorRuntimeProjectionStatus;
30
+ readonly startedAt: number | null;
31
+ readonly completedAt: number | null;
32
+ readonly modelFailures: readonly EditorRuntimeProjectionModelFailure[];
33
+ readonly error?: unknown;
34
+ }
35
+ export interface EditorRuntimeProjectionResult extends EditorRuntimeProjectionOperation {
36
+ readonly status: EditorRuntimeProjectionTerminalStatus;
37
+ }
38
+ /** Local bridge events avoid widening the shared RuntimeEventMap prematurely. */
39
+ export interface EditorRuntimeProjectionEventMap {
40
+ "projection.queued": EditorRuntimeProjectionOperation;
41
+ "projection.started": EditorRuntimeProjectionOperation;
42
+ "projection.completed": EditorRuntimeProjectionResult;
43
+ }
44
+ /** Thrown by the legacy `flush()` API when its projection did not complete. */
45
+ export declare class EditorRuntimeProjectionError extends Error {
46
+ readonly result: EditorRuntimeProjectionResult;
47
+ readonly error: unknown;
48
+ constructor(result: EditorRuntimeProjectionResult);
49
+ }
50
+ //# sourceMappingURL=projection-operation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"projection-operation.d.ts","sourceRoot":"","sources":["../../src/bridge/projection-operation.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,6BAA6B,GAAG,QAAQ,GAAG,aAAa,CAAC;AAErE,MAAM,MAAM,6BAA6B,GACvC,QAAQ,GAAG,SAAS,GAAG,OAAO,GAAG,SAAS,GAAG,QAAQ,GAAG,WAAW,CAAC;AAEtE,MAAM,MAAM,qCAAqC,GAAG,OAAO,CACzD,6BAA6B,EAC7B,OAAO,GAAG,SAAS,GAAG,QAAQ,GAAG,WAAW,CAC7C,CAAC;AAEF,MAAM,WAAW,mCAAmC;IAClD,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;CACzB;AAED,iFAAiF;AACjF,MAAM,WAAW,8BAA8B;IAC7C,6EAA6E;IAC7E,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,2EAA2E;IAC3E,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B,mEAAmE;IACnE,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IACjC,4EAA4E;IAC5E,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,0DAA0D;IAC1D,QAAQ,CAAC,eAAe,CAAC,EAAE,6BAA6B,CAAC;CAC1D;AAED,MAAM,WAAW,gCAAgC;IAC/C,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,eAAe,EAAE,6BAA6B,CAAC;IACxD,QAAQ,CAAC,MAAM,EAAE,6BAA6B,CAAC;IAC/C,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IACpC,QAAQ,CAAC,aAAa,EAAE,SAAS,mCAAmC,EAAE,CAAC;IACvE,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,MAAM,WAAW,6BAA8B,SAAQ,gCAAgC;IACrF,QAAQ,CAAC,MAAM,EAAE,qCAAqC,CAAC;CACxD;AAED,iFAAiF;AACjF,MAAM,WAAW,+BAA+B;IAC9C,mBAAmB,EAAE,gCAAgC,CAAC;IACtD,oBAAoB,EAAE,gCAAgC,CAAC;IACvD,sBAAsB,EAAE,6BAA6B,CAAC;CACvD;AAED,+EAA+E;AAC/E,qBAAa,4BAA6B,SAAQ,KAAK;IACrD,QAAQ,CAAC,MAAM,EAAE,6BAA6B,CAAC;IAC/C,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;gBAEZ,MAAM,EAAE,6BAA6B;CAQlD"}
@@ -0,0 +1,12 @@
1
+ /** Thrown by the legacy `flush()` API when its projection did not complete. */
2
+ export class EditorRuntimeProjectionError extends Error {
3
+ result;
4
+ error;
5
+ constructor(result) {
6
+ super(`Runtime projection ${result.status} for operation ${result.operationId}`);
7
+ this.name = "EditorRuntimeProjectionError";
8
+ this.result = result;
9
+ this.error = result.error;
10
+ }
11
+ }
12
+ //# sourceMappingURL=projection-operation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"projection-operation.js","sourceRoot":"","sources":["../../src/bridge/projection-operation.ts"],"names":[],"mappings":"AAuDA,+EAA+E;AAC/E,MAAM,OAAO,4BAA6B,SAAQ,KAAK;IAC5C,MAAM,CAAgC;IACtC,KAAK,CAAU;IAExB,YAAY,MAAqC;QAC/C,KAAK,CACH,sBAAsB,MAAM,CAAC,MAAM,kBAAkB,MAAM,CAAC,WAAW,EAAE,CAC1E,CAAC;QACF,IAAI,CAAC,IAAI,GAAG,8BAA8B,CAAC;QAC3C,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC;IAC5B,CAAC;CACF"}
@@ -0,0 +1,17 @@
1
+ import { type EditorSession } from "@skenora/editor";
2
+ import type { RuntimeSelectionController } from "@skenora/runtime/editor";
3
+ import { type RuntimeSession } from "@skenora/runtime/projection";
4
+ export interface KeyboardControllerOptions {
5
+ target: EventTarget;
6
+ editor: EditorSession;
7
+ runtime: RuntimeSession;
8
+ selection?: RuntimeSelectionController | null;
9
+ enabled?: () => boolean;
10
+ }
11
+ /** Host-installed shortcuts; no listener is attached until this class is created. */
12
+ export declare class EditorKeyboardController {
13
+ #private;
14
+ constructor(options: KeyboardControllerOptions);
15
+ dispose(): void;
16
+ }
17
+ //# sourceMappingURL=keyboard-controller.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"keyboard-controller.d.ts","sourceRoot":"","sources":["../../src/controllers/keyboard-controller.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,aAAa,EACnB,MAAM,iBAAiB,CAAC;AACzB,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,yBAAyB,CAAC;AAC1E,OAAO,EAEL,KAAK,cAAc,EACpB,MAAM,6BAA6B,CAAC;AAErC,MAAM,WAAW,yBAAyB;IACxC,MAAM,EAAE,WAAW,CAAC;IACpB,MAAM,EAAE,aAAa,CAAC;IACtB,OAAO,EAAE,cAAc,CAAC;IACxB,SAAS,CAAC,EAAE,0BAA0B,GAAG,IAAI,CAAC;IAC9C,OAAO,CAAC,EAAE,MAAM,OAAO,CAAC;CACzB;AAED,qFAAqF;AACrF,qBAAa,wBAAwB;;gBAIvB,OAAO,EAAE,yBAAyB;IAQ9C,OAAO,IAAI,IAAI;CA4DhB"}
@@ -0,0 +1,78 @@
1
+ import { duplicateEntityTreeCommand, removeEntityCommand, } from "@skenora/editor";
2
+ import { RUNTIME_CAMERA_CAPABILITY, } from "@skenora/runtime/projection";
3
+ /** Host-installed shortcuts; no listener is attached until this class is created. */
4
+ export class EditorKeyboardController {
5
+ #options;
6
+ #disposed = false;
7
+ constructor(options) {
8
+ this.#options = options;
9
+ options.target.addEventListener("keydown", this.#onKeyDown);
10
+ }
11
+ dispose() {
12
+ if (this.#disposed)
13
+ return;
14
+ this.#disposed = true;
15
+ this.#options.target.removeEventListener("keydown", this.#onKeyDown);
16
+ }
17
+ #onKeyDown = (event) => {
18
+ if (this.#options.enabled?.() === false || isTextInput(event.target))
19
+ return;
20
+ const { editor, runtime, selection } = this.#options;
21
+ const modifier = event.metaKey || event.ctrlKey;
22
+ const key = event.key.toLowerCase();
23
+ if (modifier && key === "z") {
24
+ event.preventDefault();
25
+ if (event.shiftKey)
26
+ editor.redo();
27
+ else
28
+ editor.undo();
29
+ return;
30
+ }
31
+ if (modifier && key === "y") {
32
+ event.preventDefault();
33
+ editor.redo();
34
+ return;
35
+ }
36
+ if (modifier && key === "d") {
37
+ event.preventDefault();
38
+ const commands = editor.selection.map((id) => duplicateEntityTreeCommand(id));
39
+ editor.transaction("Duplicate selection", commands);
40
+ return;
41
+ }
42
+ if (key === "delete" || key === "backspace") {
43
+ if (editor.selection.length === 0)
44
+ return;
45
+ event.preventDefault();
46
+ editor.transaction("Delete selection", editor.selection.map((id) => removeEntityCommand(id)));
47
+ editor.select([]);
48
+ return;
49
+ }
50
+ if (key === "escape") {
51
+ editor.select([]);
52
+ return;
53
+ }
54
+ if (key === "f") {
55
+ runtime.capabilities
56
+ .require(RUNTIME_CAMERA_CAPABILITY)
57
+ .frame(editor.selection);
58
+ return;
59
+ }
60
+ if (key === "w")
61
+ selection?.setMode("position");
62
+ if (key === "e")
63
+ selection?.setMode("rotation");
64
+ if (key === "r")
65
+ selection?.setMode("scale");
66
+ if (key === "q")
67
+ selection?.setMode("none");
68
+ };
69
+ }
70
+ function isTextInput(target) {
71
+ if (!(target instanceof HTMLElement))
72
+ return false;
73
+ return (target.isContentEditable ||
74
+ target instanceof HTMLInputElement ||
75
+ target instanceof HTMLTextAreaElement ||
76
+ target instanceof HTMLSelectElement);
77
+ }
78
+ //# sourceMappingURL=keyboard-controller.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"keyboard-controller.js","sourceRoot":"","sources":["../../src/controllers/keyboard-controller.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ import type { EditorSession } from "@skenora/editor";
2
+ import type { RuntimeSession } from "@skenora/runtime/projection";
3
+ import { RuntimeFlowController, type RuntimeFlowControllerOptions } from "./runtime-flow-controller.js";
4
+ export interface EditorFlowBridgeOptions extends RuntimeFlowControllerOptions {
5
+ startOnFlowChange?: boolean;
6
+ }
7
+ /** Keeps editor-owned Flow documents projected into an optional runtime. */
8
+ export declare class EditorFlowBridge {
9
+ #private;
10
+ readonly editor: EditorSession;
11
+ readonly runtime: RuntimeSession;
12
+ readonly controller: RuntimeFlowController;
13
+ constructor(editor: EditorSession, runtime: RuntimeSession, options?: EditorFlowBridgeOptions);
14
+ dispose(): void;
15
+ }
16
+ //# sourceMappingURL=editor-flow-bridge.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"editor-flow-bridge.d.ts","sourceRoot":"","sources":["../../src/flow/editor-flow-bridge.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAErD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAClE,OAAO,EACL,qBAAqB,EACrB,KAAK,4BAA4B,EAClC,MAAM,2BAA2B,CAAC;AAEnC,MAAM,WAAW,uBAAwB,SAAQ,4BAA4B;IAC3E,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED,4EAA4E;AAC5E,qBAAa,gBAAgB;;IAC3B,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC;IAC/B,QAAQ,CAAC,OAAO,EAAE,cAAc,CAAC;IACjC,QAAQ,CAAC,UAAU,EAAE,qBAAqB,CAAC;gBAMzC,MAAM,EAAE,aAAa,EACrB,OAAO,EAAE,cAAc,EACvB,OAAO,GAAE,uBAA4B;IAcvC,OAAO,IAAI,IAAI;CAqChB"}
@@ -0,0 +1,46 @@
1
+ import { createCausationMetadata } from "@skenora/events";
2
+ import { RuntimeFlowController, } from "./runtime-flow-controller.js";
3
+ /** Keeps editor-owned Flow documents projected into an optional runtime. */
4
+ export class EditorFlowBridge {
5
+ editor;
6
+ runtime;
7
+ controller;
8
+ #lifetime = new AbortController();
9
+ #startOnFlowChange;
10
+ #disposed = false;
11
+ constructor(editor, runtime, options = {}) {
12
+ this.editor = editor;
13
+ this.runtime = runtime;
14
+ this.#startOnFlowChange = options.startOnFlowChange ?? false;
15
+ this.controller = new RuntimeFlowController(runtime, options);
16
+ this.controller.setDocument(editor.snapshot);
17
+ editor.subscribe("document.changed", (change, event) => this.#syncChange(change, event), this.#lifetime.signal);
18
+ }
19
+ dispose() {
20
+ if (this.#disposed)
21
+ return;
22
+ this.#disposed = true;
23
+ this.#lifetime.abort();
24
+ this.controller.dispose();
25
+ }
26
+ #syncChange(change, cause) {
27
+ if (!change.patches.some((patch) => patch.path.length === 0 ||
28
+ patch.path[0] === "flows" ||
29
+ patch.path[0] === "variables")) {
30
+ return;
31
+ }
32
+ try {
33
+ this.controller.setDocument(this.editor.snapshot);
34
+ }
35
+ catch (error) {
36
+ this.runtime.events.publish("runtime.error", { error, operation: "syncFlows" }, createCausationMetadata(cause, "flow"));
37
+ return;
38
+ }
39
+ if (!this.#startOnFlowChange)
40
+ return;
41
+ void this.controller.start().catch((error) => {
42
+ this.runtime.events.publish("runtime.error", { error, operation: "restartFlows" }, createCausationMetadata(cause, "flow"));
43
+ });
44
+ }
45
+ }
46
+ //# sourceMappingURL=editor-flow-bridge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"editor-flow-bridge.js","sourceRoot":"","sources":["../../src/flow/editor-flow-bridge.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,uBAAuB,EAAsB,MAAM,iBAAiB,CAAC;AAE9E,OAAO,EACL,qBAAqB,GAEtB,MAAM,2BAA2B,CAAC;AAMnC,4EAA4E;AAC5E,MAAM,OAAO,gBAAgB;IAClB,MAAM,CAAgB;IACtB,OAAO,CAAiB;IACxB,UAAU,CAAwB;IAClC,SAAS,GAAG,IAAI,eAAe,EAAE,CAAC;IAClC,kBAAkB,CAAU;IACrC,SAAS,GAAG,KAAK,CAAC;IAElB,YACE,MAAqB,EACrB,OAAuB,EACvB,UAAmC,EAAE;QAErC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,kBAAkB,GAAG,OAAO,CAAC,iBAAiB,IAAI,KAAK,CAAC;QAC7D,IAAI,CAAC,UAAU,GAAG,IAAI,qBAAqB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAC9D,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QAC7C,MAAM,CAAC,SAAS,CACd,kBAAkB,EAClB,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,WAAW,CAAC,MAAM,EAAE,KAAK,CAAC,EAClD,IAAI,CAAC,SAAS,CAAC,MAAM,CACtB,CAAC;IACJ,CAAC;IAED,OAAO;QACL,IAAI,IAAI,CAAC,SAAS;YAAE,OAAO;QAC3B,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;QACtB,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC;QACvB,IAAI,CAAC,UAAU,CAAC,OAAO,EAAE,CAAC;IAC5B,CAAC;IAED,WAAW,CAAC,MAAsB,EAAE,KAA8B;QAChE,IACE,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAClB,CAAC,KAAK,EAAE,EAAE,CACR,KAAK,CAAC,IAAI,CAAC,MAAM,KAAK,CAAC;YACvB,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,OAAO;YACzB,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,WAAW,CAChC,EACD,CAAC;YACD,OAAO;QACT,CAAC;QACD,IAAI,CAAC;YACH,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QACpD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,CACzB,eAAe,EACf,EAAE,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,EACjC,uBAAuB,CAAC,KAAK,EAAE,MAAM,CAAC,CACvC,CAAC;YACF,OAAO;QACT,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,kBAAkB;YAAE,OAAO;QACrC,KAAK,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;YAC3C,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,CACzB,eAAe,EACf,EAAE,KAAK,EAAE,SAAS,EAAE,cAAc,EAAE,EACpC,uBAAuB,CAAC,KAAK,EAAE,MAAM,CAAC,CACvC,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC;CACF"}
@@ -0,0 +1,12 @@
1
+ import { type EventChannel } from "@skenora/events";
2
+ import type { FlowHost } from "@skenora/flow";
3
+ import { type RuntimeSession } from "@skenora/runtime/projection";
4
+ export interface RuntimeFlowHostOptions {
5
+ events?: EventChannel<Record<string, unknown>>;
6
+ variables?: Readonly<Record<string, unknown>>;
7
+ }
8
+ export interface RuntimeFlowHost extends FlowHost {
9
+ dispose(): void;
10
+ }
11
+ export declare function createRuntimeFlowHost(runtime: RuntimeSession, options?: RuntimeFlowHostOptions): RuntimeFlowHost;
12
+ //# sourceMappingURL=flow-host.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flow-host.d.ts","sourceRoot":"","sources":["../../src/flow/flow-host.ts"],"names":[],"mappings":"AAEA,OAAO,EAAY,KAAK,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC9D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAE9C,OAAO,EAQL,KAAK,cAAc,EACpB,MAAM,6BAA6B,CAAC;AAErC,MAAM,WAAW,sBAAsB;IACrC,MAAM,CAAC,EAAE,YAAY,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IAC/C,SAAS,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;CAC/C;AAED,MAAM,WAAW,eAAgB,SAAQ,QAAQ;IAC/C,OAAO,IAAI,IAAI,CAAC;CACjB;AAED,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,cAAc,EACvB,OAAO,GAAE,sBAA2B,GACnC,eAAe,CA0LjB"}
@@ -0,0 +1,172 @@
1
+ import { PointerEventTypes } from "@babylonjs/core/Events/pointerEvents";
2
+ import { EventHub } from "@skenora/events";
3
+ import { MaterialAnimationError } from "@skenora/contracts";
4
+ import { RUNTIME_ANIMATIONS_CAPABILITY, RUNTIME_CAMERA_CAPABILITY, RUNTIME_MATERIALS_CAPABILITY, RUNTIME_MATERIAL_ANIMATIONS_CAPABILITY, RUNTIME_NODES_CAPABILITY, RUNTIME_PARTICLES_CAPABILITY, RUNTIME_TEXTURE_ANIMATIONS_CAPABILITY, } from "@skenora/runtime/projection";
5
+ export function createRuntimeFlowHost(runtime, options = {}) {
6
+ const variables = new Map(Object.entries(options.variables ?? {}));
7
+ const ownedEvents = options.events
8
+ ? null
9
+ : new EventHub();
10
+ const events = options.events ?? ownedEvents;
11
+ const nodes = runtime.capabilities.require(RUNTIME_NODES_CAPABILITY);
12
+ const materials = runtime.capabilities.require(RUNTIME_MATERIALS_CAPABILITY);
13
+ const materialAnimations = () => runtime.capabilities.require(RUNTIME_MATERIAL_ANIMATIONS_CAPABILITY);
14
+ const camera = runtime.capabilities.require(RUNTIME_CAMERA_CAPABILITY);
15
+ const animations = runtime.capabilities.require(RUNTIME_ANIMATIONS_CAPABILITY);
16
+ const particles = runtime.capabilities.require(RUNTIME_PARTICLES_CAPABILITY);
17
+ const textureAnimations = runtime.capabilities.require(RUNTIME_TEXTURE_ANIMATIONS_CAPABILITY);
18
+ let hoveredEntityId = null;
19
+ const pointerObserver = runtime.scene.onPointerObservable.add((pointer) => {
20
+ const mesh = pointer.pickInfo?.pickedMesh ?? null;
21
+ const entityId = getEntityId(mesh);
22
+ const payload = pointerPayload(pointer, entityId);
23
+ if (pointer.type === PointerEventTypes.POINTERMOVE) {
24
+ events.publish("runtime.pointer.move", payload, { source: "runtime" });
25
+ if (hoveredEntityId !== entityId) {
26
+ if (hoveredEntityId) {
27
+ events.publish("runtime.pointer.leave", { ...payload, entityId: hoveredEntityId, nextEntityId: entityId }, { source: "runtime" });
28
+ }
29
+ if (entityId) {
30
+ events.publish("runtime.pointer.enter", payload, {
31
+ source: "runtime",
32
+ });
33
+ }
34
+ hoveredEntityId = entityId;
35
+ }
36
+ }
37
+ else if (pointer.type === PointerEventTypes.POINTERDOWN) {
38
+ events.publish("runtime.pointer.down", payload, { source: "runtime" });
39
+ }
40
+ else if (pointer.type === PointerEventTypes.POINTERUP) {
41
+ events.publish("runtime.pointer.up", payload, { source: "runtime" });
42
+ }
43
+ else if (pointer.type === PointerEventTypes.POINTERPICK) {
44
+ events.publish("runtime.pointer.pick", payload, { source: "runtime" });
45
+ }
46
+ });
47
+ return {
48
+ events: {
49
+ source: events,
50
+ emit: (type, payload, metadata) => {
51
+ events.publish(type, payload, metadata);
52
+ },
53
+ },
54
+ variables: {
55
+ getVariable: (name) => variables.get(name),
56
+ setVariable: (name, value) => {
57
+ variables.set(name, value);
58
+ events.publish("variable.changed", { name, value }, { source: "runtime" });
59
+ },
60
+ },
61
+ entities: {
62
+ getEntityState: (entityId) => nodes.getState(entityId),
63
+ setEntityEnabled: (entityId, enabled) => nodes.setEnabled(entityId, enabled),
64
+ setEntityVisible: (entityId, visible) => nodes.setVisible(entityId, visible),
65
+ setEntityTransform: (entityId, transform) => nodes.setTransform(entityId, transform),
66
+ setEntityTransparent: (entityId, alpha) => nodes.setTransparent(entityId, alpha),
67
+ setEntityOutline: (entityId, color) => nodes.setOutline(entityId, color),
68
+ },
69
+ materials: {
70
+ setMaterialProperty: (materialId, property, value) => materials.setProperty(materialId, property, value),
71
+ },
72
+ materialAnimations: {
73
+ playMaterialAnimation: async (materialId, animationId, playOptions) => {
74
+ const result = await materialAnimations().play(materialId, animationId, playOptions);
75
+ if (result.status === "cancelled")
76
+ throw new MaterialAnimationError("material-animation-cancelled", materialId, animationId);
77
+ },
78
+ pauseMaterialAnimation: (materialId, animationId) => {
79
+ materialAnimations().pause(materialId, animationId);
80
+ },
81
+ resumeMaterialAnimation: (materialId, animationId) => {
82
+ materialAnimations().resume(materialId, animationId);
83
+ },
84
+ stopMaterialAnimation: (materialId, animationId) => materialAnimations().stop(materialId, animationId),
85
+ resetMaterialAnimation: (materialId, animationId) => materialAnimations().reset(materialId, animationId),
86
+ },
87
+ camera: {
88
+ frameEntity: (entityId) => {
89
+ if (entityId)
90
+ nodes.require(entityId);
91
+ camera.frame(entityId ? [entityId] : undefined);
92
+ },
93
+ activateCameraEntity: (entityId, controls) => {
94
+ if (!camera.activateEntity(entityId, controls)) {
95
+ throw new Error(`Camera entity not found: ${entityId}`);
96
+ }
97
+ },
98
+ restoreViewportCamera: () => camera.restoreViewport(),
99
+ playCameraPath: async (pathId) => {
100
+ try {
101
+ await camera.playPath(pathId);
102
+ }
103
+ catch (error) {
104
+ events.publish("runtime.action.error", { action: "camera.playPath", error }, { source: "runtime" });
105
+ throw error;
106
+ }
107
+ },
108
+ pauseCameraPath: () => {
109
+ camera.pausePath();
110
+ },
111
+ resumeCameraPath: () => {
112
+ camera.resumePath();
113
+ },
114
+ stopCameraPath: () => camera.stopPath(),
115
+ },
116
+ animations: {
117
+ playAnimation: (entityId, animation) => {
118
+ animations.play(entityId, animation, {
119
+ started: (name) => events.publish("runtime.animation.started", { entityId, animation: name }, { source: "runtime" }),
120
+ completed: (name) => events.publish("runtime.animation.completed", { entityId, animation: name }, { source: "runtime" }),
121
+ });
122
+ },
123
+ stopAnimation: (entityId, animation) => animations.stop(entityId, animation),
124
+ },
125
+ particles: {
126
+ setParticleRunning: (entityId, running) => {
127
+ if (!particles.setRunning(entityId, running)) {
128
+ throw new Error(`Particle entity not found: ${entityId}`);
129
+ }
130
+ },
131
+ },
132
+ textureAnimations: {
133
+ playTextureAnimation: async (animationId, playOptions) => {
134
+ try {
135
+ await textureAnimations.play(animationId, playOptions);
136
+ }
137
+ catch (error) {
138
+ events.publish("runtime.action.error", { action: "textureAnimation.play", error }, { source: "runtime" });
139
+ throw error;
140
+ }
141
+ },
142
+ stopTextureAnimation: (animationId) => textureAnimations.stop(animationId),
143
+ },
144
+ dispose: () => {
145
+ runtime.scene.onPointerObservable.remove(pointerObserver);
146
+ ownedEvents?.dispose();
147
+ },
148
+ };
149
+ }
150
+ function pointerPayload(pointer, entityId) {
151
+ const event = pointer.event;
152
+ const point = pointer.pickInfo?.pickedPoint;
153
+ return {
154
+ entityId,
155
+ button: typeof event?.button === "number" ? event.button : 0,
156
+ buttons: typeof event?.buttons === "number" ? event.buttons : 0,
157
+ pointerId: typeof event?.pointerId === "number" ? event.pointerId : null,
158
+ point: point ? { x: point.x, y: point.y, z: point.z } : null,
159
+ };
160
+ }
161
+ function getEntityId(node) {
162
+ let current = node;
163
+ while (current) {
164
+ const metadata = current.metadata;
165
+ if (typeof metadata?.skenora?.entityId === "string") {
166
+ return metadata.skenora.entityId;
167
+ }
168
+ current = current.parent;
169
+ }
170
+ return null;
171
+ }
172
+ //# sourceMappingURL=flow-host.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flow-host.js","sourceRoot":"","sources":["../../src/flow/flow-host.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ /** Owns optional Flow playback for an editor/runtime composition. */
2
+ import type { SceneDocumentData } from "@skenora/contracts";
3
+ import { FlowRuntime, type FlowRuntimeOptions } from "@skenora/flow";
4
+ import type { RuntimeSession } from "@skenora/runtime/projection";
5
+ import { type RuntimeFlowHost, type RuntimeFlowHostOptions } from "./flow-host.js";
6
+ export interface RuntimeFlowControllerOptions {
7
+ events?: FlowRuntimeOptions["events"];
8
+ host?: RuntimeFlowHostOptions;
9
+ maxSteps?: FlowRuntimeOptions["maxSteps"];
10
+ nodes?: FlowRuntimeOptions["nodes"];
11
+ }
12
+ /** Owns the optional Flow/runtime composition without coupling either core. */
13
+ export declare class RuntimeFlowController {
14
+ #private;
15
+ readonly runtime: RuntimeSession;
16
+ constructor(runtime: RuntimeSession, options?: RuntimeFlowControllerOptions);
17
+ get host(): RuntimeFlowHost | null;
18
+ get flow(): FlowRuntime | null;
19
+ get running(): boolean;
20
+ setDocument(document: Readonly<SceneDocumentData>): void;
21
+ start(payload?: unknown): Promise<void>;
22
+ stop(): number;
23
+ dispose(): void;
24
+ }
25
+ //# sourceMappingURL=runtime-flow-controller.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime-flow-controller.d.ts","sourceRoot":"","sources":["../../src/flow/runtime-flow-controller.ts"],"names":[],"mappings":"AAAA,qEAAqE;AACrE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAE5D,OAAO,EAEL,WAAW,EAGX,KAAK,kBAAkB,EACxB,MAAM,eAAe,CAAC;AACvB,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAClE,OAAO,EAEL,KAAK,eAAe,EACpB,KAAK,sBAAsB,EAC5B,MAAM,aAAa,CAAC;AAErB,MAAM,WAAW,4BAA4B;IAC3C,MAAM,CAAC,EAAE,kBAAkB,CAAC,QAAQ,CAAC,CAAC;IACtC,IAAI,CAAC,EAAE,sBAAsB,CAAC;IAC9B,QAAQ,CAAC,EAAE,kBAAkB,CAAC,UAAU,CAAC,CAAC;IAC1C,KAAK,CAAC,EAAE,kBAAkB,CAAC,OAAO,CAAC,CAAC;CACrC;AAED,+EAA+E;AAC/E,qBAAa,qBAAqB;;IAChC,QAAQ,CAAC,OAAO,EAAE,cAAc,CAAC;gBAU/B,OAAO,EAAE,cAAc,EACvB,OAAO,GAAE,4BAAiC;IAoB5C,IAAI,IAAI,IAAI,eAAe,GAAG,IAAI,CAEjC;IAED,IAAI,IAAI,IAAI,WAAW,GAAG,IAAI,CAE7B;IAED,IAAI,OAAO,IAAI,OAAO,CAErB;IAED,WAAW,CAAC,QAAQ,EAAE,QAAQ,CAAC,iBAAiB,CAAC,GAAG,IAAI;IAkBlD,KAAK,CAAC,OAAO,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAmB7C,IAAI,IAAI,MAAM;IAYd,OAAO,IAAI,IAAI;CAqDhB"}
@@ -0,0 +1,143 @@
1
+ import { createCausationMetadata } from "@skenora/events";
2
+ import { createBuiltInFlowNodeRegistry, FlowRuntime, FlowValidationError, validateFlowGraph, } from "@skenora/flow";
3
+ import { createRuntimeFlowHost, } from "./flow-host.js";
4
+ /** Owns the optional Flow/runtime composition without coupling either core. */
5
+ export class RuntimeFlowController {
6
+ runtime;
7
+ #options;
8
+ #lifetime = new AbortController();
9
+ #host = null;
10
+ #flow = null;
11
+ #document = null;
12
+ #running = false;
13
+ #disposed = false;
14
+ constructor(runtime, options = {}) {
15
+ this.runtime = runtime;
16
+ this.#options = options;
17
+ runtime.events.subscribe("runtime.document.applied", ({ documentId }, event) => {
18
+ if (!this.#running || this.#document?.id !== documentId)
19
+ return;
20
+ void this.start().catch((error) => {
21
+ runtime.events.publish("runtime.error", { error, operation: "startFlows" }, createCausationMetadata(event, "flow"));
22
+ });
23
+ }, { signal: this.#lifetime.signal });
24
+ }
25
+ get host() {
26
+ return this.#host;
27
+ }
28
+ get flow() {
29
+ return this.#flow;
30
+ }
31
+ get running() {
32
+ return this.#running;
33
+ }
34
+ setDocument(document) {
35
+ this.#assertActive();
36
+ const ownedDocument = structuredClone(document);
37
+ validateFlowDocument(ownedDocument, this.#options);
38
+ if (!this.#running) {
39
+ this.#document = ownedDocument;
40
+ return;
41
+ }
42
+ const next = this.#createActiveFlow(ownedDocument);
43
+ const previousFlow = this.#flow;
44
+ const previousHost = this.#host;
45
+ this.#document = ownedDocument;
46
+ this.#host = next.host;
47
+ this.#flow = next.flow;
48
+ previousFlow?.dispose();
49
+ previousHost?.dispose();
50
+ }
51
+ async start(payload) {
52
+ this.#assertActive();
53
+ const document = this.#document;
54
+ if (!document)
55
+ return;
56
+ if (!this.#running) {
57
+ const next = this.#createActiveFlow(document);
58
+ this.#host = next.host;
59
+ this.#flow = next.flow;
60
+ this.#running = true;
61
+ }
62
+ const flow = this.#flow;
63
+ if (!flow)
64
+ return;
65
+ await Promise.all(Object.values(document.flows)
66
+ .filter((graph) => graph.enabled)
67
+ .map((graph) => flow.start(graph.id, payload)));
68
+ }
69
+ stop() {
70
+ this.#assertActive();
71
+ if (!this.#running)
72
+ return 0;
73
+ const cancelled = this.#flow?.cancelAll() ?? 0;
74
+ this.#flow?.dispose();
75
+ this.#host?.dispose();
76
+ this.#flow = null;
77
+ this.#host = null;
78
+ this.#running = false;
79
+ return cancelled;
80
+ }
81
+ dispose() {
82
+ if (this.#disposed)
83
+ return;
84
+ this.#lifetime.abort();
85
+ this.#flow?.dispose();
86
+ this.#host?.dispose();
87
+ this.#flow = null;
88
+ this.#host = null;
89
+ this.#document = null;
90
+ this.#running = false;
91
+ this.#disposed = true;
92
+ }
93
+ #createActiveFlow(document) {
94
+ const host = createRuntimeFlowHost(this.runtime, {
95
+ ...this.#options.host,
96
+ variables: document.variables,
97
+ });
98
+ let flow = null;
99
+ try {
100
+ flow = new FlowRuntime(host, {
101
+ ...(this.#options.events === undefined
102
+ ? {}
103
+ : { events: this.#options.events }),
104
+ ...(this.#options.maxSteps === undefined
105
+ ? {}
106
+ : { maxSteps: this.#options.maxSteps }),
107
+ ...(this.#options.nodes === undefined
108
+ ? {}
109
+ : { nodes: this.#options.nodes }),
110
+ });
111
+ for (const graph of Object.values(document.flows)) {
112
+ flow.mount(graph);
113
+ }
114
+ }
115
+ catch (error) {
116
+ flow?.dispose();
117
+ host.dispose();
118
+ throw error;
119
+ }
120
+ if (!flow) {
121
+ host.dispose();
122
+ throw new Error("Flow runtime could not be created");
123
+ }
124
+ return { host, flow };
125
+ }
126
+ #assertActive() {
127
+ if (this.#disposed) {
128
+ throw new Error("RuntimeFlowController has been disposed");
129
+ }
130
+ }
131
+ }
132
+ function validateFlowDocument(document, options) {
133
+ const registry = createBuiltInFlowNodeRegistry();
134
+ for (const registration of options.nodes ?? []) {
135
+ registry.register(registration.definition);
136
+ }
137
+ for (const graph of Object.values(document.flows)) {
138
+ const result = validateFlowGraph(graph, registry);
139
+ if (!result.valid)
140
+ throw new FlowValidationError(result.issues);
141
+ }
142
+ }
143
+ //# sourceMappingURL=runtime-flow-controller.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime-flow-controller.js","sourceRoot":"","sources":["../../src/flow/runtime-flow-controller.ts"],"names":[],"mappings":"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"}