@realitycollective/xrblocks-uiextensions 0.1.0 → 0.1.1-preview.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/CHANGELOG.md +28 -1
- package/dist/host.d.ts +10 -0
- package/dist/host.js +47 -21
- package/dist/host.js.map +1 -1
- package/dist/panel-document.d.ts +5 -3
- package/dist/panel-document.js.map +1 -1
- package/dist/pointer-forward.d.ts +5 -3
- package/dist/pointer-forward.js.map +1 -1
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,9 +1,35 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
Change log for the Reality Collective WebXR UI Extensions packages. All
|
|
3
|
+
Change log for the Reality Collective WebXR UI Extensions packages. All five packages are versioned and released together; the version below is the one carried by the `v<version>` release tag.
|
|
4
4
|
|
|
5
5
|
The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and the project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). Preview builds are not listed separately. The entry for a version accumulates while its previews are published, and is dated when that version is released.
|
|
6
6
|
|
|
7
|
+
## [0.1.1]
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- `uixElementContractCases()`, a shared conformance suite for `UixElement`, the interface the core's controls drive panel elements through, with `CONTRACT_PANEL_MARKUP` and the `UixElementContractSubject`, `UixElementContractDriver` and `UixElementContractCase` types. Every platform builds the same small panel from the markup its own way, and six cases check it: children follow the markup in order, `tagOf` reads a `uix-*` tag and nothing for a built-in one, `data-uix-*` attributes arrive camelCased in `userData`, `setProperties` reaches what the platform shows, one event reaches every listener on its element and no other, and a core stepper upgraded from the markup follows clicks to its maximum. It runs against real uikit elements on IWSDK and on XR Blocks and three.js, built headlessly the way each platform builds them, and against `NativeWindowHost` over the fake native app. It found the native defect under Fixed.
|
|
12
|
+
- `dataAttributeKey()`, the one rule for where a `data-*` attribute lands in `userData`: `data-uix-min` becomes `uixMin`, and an already camelCased `dataUixMin` gives the same key. The IWSDK component set and the native proxy elements both use it; the IWSDK copy was private.
|
|
13
|
+
- `sceneTargetContractCases()`, a shared conformance suite for `SceneTarget`, shipped as data beside `windowHostContractCases()`, with `CONTRACT_SCENE` and the `SceneTargetContractSetup` and `SceneTargetContractCase` types. A client builds its UI with the core's `applyScene()` and never asks which platform draws it, so every host must turn the same descriptor into the same windows. The suite checks that through the host's `WindowManager`: every descriptor window is opened under its id and title, a window named into a region is in that region, a window keeps its dock mode and chrome, and a window given both a region and a dock mode is world-locked in that region. The IWSDK, XR Blocks and native hosts all pass it.
|
|
14
|
+
- `MemoryWindowHost`, `MemoryWindowHandle`, `MemoryPanel` and `createMemoryWindowHostSetup()` in `@realitycollective/webxr-uiextensions`, an in-memory `WindowHost` and the family's mock. The package shipped `windowHostContractCases()` but nothing to run them against without an engine, so every headless consumer and every new adapter had to write a host first. The mock opens windows on a real `WindowManager`. A window's panel attaches when the test calls `attach(id)`, as on IWSDK, and closing a window through the manager disposes its panel and drops it from `onPanelReady` replay. `dispose()` closes every window it opened and forgets its listeners, as every platform host does. `createMemoryWindowHostSetup()` returns a fresh `WindowHostContractSetup`, so the suite runs in one loop. It passes every contract case, which `test/memory-window-host.test.ts` checks, and it is inside the 100% coverage gate. It came from a team building a native host, whose version passed the suite under Node and Hermes.
|
|
15
|
+
- `dispose()` on `WindowHost`, implemented by every platform host: `IwsdkSceneHost`, `UixWindowHost` (XR Blocks and three.js) and `NativeWindowHost`. It means the same thing everywhere: close every window the host opened through its `WindowManager`, so each goes down the normal close path, then release the host's own subscriptions and listeners, so `onPanelReady` replays nothing afterwards. It is safe to call twice. The XR Blocks host also removes the region groups it added to the scene. The IWSDK host silences its readiness system, which stays registered on the world, and forgets itself, so a later `createSceneHost(world)` builds a fresh host. No host could be torn down before, so an app that rebuilt its UI leaked listeners and scene objects on every platform. `windowHostContractCases()` gains a seventh case that holds every host to it. This adds a required member to the `WindowHost` interface, so a host written outside this repository must implement it.
|
|
16
|
+
- `@realitycollective/native-uiextensions` - the native app adapter, for an OpenXR or visionOS app that embeds a JavaScript engine such as Hermes, renders panels itself and installs `globalThis.__rcHost`, per the Reality Collective native host contract shared across the WebXR family repositories. `NativeWindowHost` implements the core `WindowHost` and `SceneTarget`, as the IWSDK and XR Blocks hosts do, so `applyScene` builds the same scene on native; regions go to the host as `createRegion` and are removed on `dispose`. Bare panels and windows build a tree of internal proxy `UixElement`s over the host's `NativeElementNode` tree, so the existing `data-uix` control upgraders work unchanged; `setProperties` forwards to `host.setProperties`, and `addEventListener` is routed from the host's single `onElementEvent` callback by `(panelId, elementHandle)`. Every `WindowManager` state change (open, focus, minimize, hide, dock, chrome, hand menu) mirrors to the host as `applyWindow(record)`; closing a window disposes its panel (once attached) and calls `closeWindow`. No engine dependency - the package reads and writes only plain data across the host boundary. Ships with an in-memory fake of the `ui` slice under `test/helpers` and runs the shared `windowHostContractCases()` against it.
|
|
17
|
+
- `demos/webxr-multiplatform` - `?uix-engine=<engine>&uix-autostart=1` boots that pipeline at once instead of showing the launch screen. It exists for the post-deploy smoke test, which now loads the desktop and IWSDK pipelines of the deployed lab as well as its launch screen; before this a pipeline that failed to start was invisible to CI, because nothing pressed START. The XR Blocks pipeline is not smoked: xrblocks renders into `<body>` rather than the mount point and logs a `console.error` about the three.js revision it wants, both of which the smoke test counts as failures.
|
|
18
|
+
|
|
19
|
+
### Changed
|
|
20
|
+
|
|
21
|
+
- `tagOf()` reads nothing for a built-in element on every platform, as its doc always said. The XR Blocks and three.js parser records a built-in tag such as `span` the same way as a custom one, so `tagOf` read `"span"` there and nothing on IWSDK. A custom element name always holds a hyphen, so `tagOf` now returns a name only when it has one.
|
|
22
|
+
- `WindowManager` holds one rule for regions: a window in a region is always world-locked, because the region places it. Opening a window into a region, or `dockTo`, makes it world-locked whatever dock mode it asked for; `dockTo` emits `regionChanged` and then, if the mode changed, `dockChanged`. Setting a follow mode with `setDockMode` or `togglePin` takes a docked window out of its region first. The hosts disagreed before this: the XR Blocks host forced a docked window to world-locked on its own, while the IWSDK and native hosts left the manager's record in the requested follow mode. The same scene descriptor therefore laid out differently by platform. The XR Blocks host's own copy of the rule is gone. The native host now sends the native app the manager's dock mode for a new window, not the one the options asked for.
|
|
23
|
+
- `@realitycollective/iwsdk-uiextensions` - `TouchPointerLike` (the parameter type of `sampleOf`) is exported, and `UITouchGuardSystem` uses the core's `Hand` type rather than a private duplicate. `@realitycollective/xrblocks-uiextensions` exports `UikitComponentLike` (`UixPanelDocument.rootComponent`) and `InteractiveLike` (the return type of `pickInteractive`); `@realitycollective/uix-devtools` exports `CompileOptions` (the options of `compilePanelSource`). Each was a module-private type that appeared in an exported signature, so a consumer had nothing to name and TypeDoc reported it as referenced but undocumented.
|
|
24
|
+
|
|
25
|
+
### Fixed
|
|
26
|
+
|
|
27
|
+
- `@realitycollective/native-uiextensions` - the `data-uix-*` attributes of a native panel never reached the controls. `NativeElementNode` had no field for them, so on native every control ran on its defaults: a stepper lost its range, step and starting value, a toggle its labels and colours, and every control its `data-uix-id`, so `controls.stepper("count")` found nothing. `NativeElementNode` gains `attributes`, the element's `data-*` attributes as the markup wrote them, and the proxy lifts them into `userData` with `dataAttributeKey()`. The native app must send them.
|
|
28
|
+
|
|
29
|
+
- `demos/webxr-multiplatform` - the IWSDK pipeline failed to start on the deployed lab, for every visitor, with `Failed to resolve module specifier "three-mesh-bvh"`. The Vite config externalised `three-mesh-bvh` alongside the optional integrations xrblocks imports lazily, but `@iwsdk/core` imports it for real, so the IWSDK chunk shipped a bare import the browser cannot resolve. It resolves in the workspace through `@iwsdk/core`'s own dependency and is now bundled like `three-pathfinding`. Found while photographing the live lab for the Reality Collective site.
|
|
30
|
+
- `@realitycollective/iwsdk-uiextensions` - the README and `Examples/controls` still showed the `data-uix="stepper"` / `data-uix-role` attribute form that the core stopped upgrading when controls became custom elements, so the shipped example silently produced no controls. Both now use `<uix-stepper>`, `<uix-toggle>`, `<uix-expandable-label>` and `<uix-log-view>` with their part elements, and both register `uixComponentSet` when creating the world, which IWSDK 0.5 needs before it will parse a panel that uses a control. The README says why.
|
|
31
|
+
- `docs/developer-cycle.md` - the publishing section described GitHub Packages ("no npmjs.com for now"); the packages publish to npmjs.com under the `@realitycollective` scope through `publish-npm.yml`, and the section now describes that workflow, its two dist-tags and the consumer install commands.
|
|
32
|
+
|
|
7
33
|
## [0.1.0] - 2026-09-17
|
|
8
34
|
|
|
9
35
|
### Added
|
|
@@ -52,6 +78,7 @@ The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and
|
|
|
52
78
|
- `@realitycollective/webxr-uiextensions` takes its geometry vocabulary from `@realitycollective/webxr-input` at `^0.1.1` rather than redeclaring it. `Vec3Tuple`, `QuatTuple`, `HeadPose`, `HeadPoseSource` and `PointerSample` are now that package's types, re-exported under the same names, so no import changes for a consumer. `PointerSample` is its `RayTuple`, which is what lets an input provider written against the shared contracts feed this contract unchanged. It is the core's only runtime dependency: the contracts package is engine-free and carries none of its own, and `test/architecture.test.ts` now allows exactly that one name and fails on any other.
|
|
53
79
|
- `PointerSample` states its ownership rule: a delivered sample belongs to the listener and the source never writes to it again, so the core's hold-to-drag and drag maths may keep a press-time sample without copying. It mirrors the rule `@realitycollective/webxr-input` 0.1.3 writes on `InputSourceSnapshot`, so a provider feeding both contracts has one promise to keep.
|
|
54
80
|
|
|
81
|
+
[0.1.1]: https://github.com/realitycollective/WebXR-UIExtensions/compare/v0.1.0...development
|
|
55
82
|
[0.1.0]: https://github.com/realitycollective/WebXR-UIExtensions/releases/tag/v0.1.0
|
|
56
83
|
|
|
57
84
|
### Fixed
|
package/dist/host.d.ts
CHANGED
|
@@ -108,6 +108,9 @@ export declare class UixWindowHost implements WindowHost, SceneTarget {
|
|
|
108
108
|
private readonly ready;
|
|
109
109
|
/** Feeds `uix-window-<n>` ids to windows created without one. */
|
|
110
110
|
private windowSequence;
|
|
111
|
+
/** Every manager subscription, released by {@link dispose}. */
|
|
112
|
+
private readonly subscriptions;
|
|
113
|
+
private disposed;
|
|
111
114
|
constructor(options: UixWindowHostOptions);
|
|
112
115
|
/**
|
|
113
116
|
* PanelHost - bare panel, unmanaged (used by devtools and tests). Always
|
|
@@ -119,6 +122,13 @@ export declare class UixWindowHost implements WindowHost, SceneTarget {
|
|
|
119
122
|
* so wiring code never races window creation.
|
|
120
123
|
*/
|
|
121
124
|
onPanelReady(listener: (event: PanelReadyEvent) => void): () => void;
|
|
125
|
+
/**
|
|
126
|
+
* Leave nothing behind: close every window through the manager, so each
|
|
127
|
+
* goes down the normal close path (its document disposed, its group
|
|
128
|
+
* removed), remove the region groups this host added to the scene, then
|
|
129
|
+
* release every manager subscription. Safe to call twice.
|
|
130
|
+
*/
|
|
131
|
+
dispose(): void;
|
|
122
132
|
spawnRegion(region: SceneRegion): void;
|
|
123
133
|
/**
|
|
124
134
|
* Scene descriptors carry config PATHS; this resolves the path and spawns
|
package/dist/host.js
CHANGED
|
@@ -55,13 +55,16 @@ export class UixWindowHost {
|
|
|
55
55
|
ready = new Map();
|
|
56
56
|
/** Feeds `uix-window-<n>` ids to windows created without one. */
|
|
57
57
|
windowSequence = 0;
|
|
58
|
+
/** Every manager subscription, released by {@link dispose}. */
|
|
59
|
+
subscriptions = [];
|
|
60
|
+
disposed = false;
|
|
58
61
|
constructor(options) {
|
|
59
62
|
this.scene = options.scene;
|
|
60
63
|
this.headPose = options.headPose;
|
|
61
64
|
this.handPose = options.handPose;
|
|
62
65
|
this.kit = options.kit;
|
|
63
66
|
this.loadConfig = options.loadConfig ?? loadUikitmlSource;
|
|
64
|
-
this.manager.events.on('closed', (record) => {
|
|
67
|
+
this.subscriptions.push(this.manager.events.on('closed', (record) => {
|
|
65
68
|
const state = this.states.get(record.id);
|
|
66
69
|
if (state) {
|
|
67
70
|
this.states.delete(record.id);
|
|
@@ -71,14 +74,14 @@ export class UixWindowHost {
|
|
|
71
74
|
state.handle.group.removeFromParent();
|
|
72
75
|
this.layoutRegions();
|
|
73
76
|
}
|
|
74
|
-
});
|
|
75
|
-
this.manager.events.on('hidden', (record) => {
|
|
77
|
+
}));
|
|
78
|
+
this.subscriptions.push(this.manager.events.on('hidden', (record) => {
|
|
76
79
|
this.applyPresentation(record.id);
|
|
77
|
-
});
|
|
78
|
-
this.manager.events.on('shown', (record) => {
|
|
80
|
+
}));
|
|
81
|
+
this.subscriptions.push(this.manager.events.on('shown', (record) => {
|
|
79
82
|
this.applyPresentation(record.id);
|
|
80
|
-
});
|
|
81
|
-
this.manager.events.on('dockChanged', ({ window, previous }) => {
|
|
83
|
+
}));
|
|
84
|
+
this.subscriptions.push(this.manager.events.on('dockChanged', ({ window, previous }) => {
|
|
82
85
|
if (previous === DockMode.HandLocked) {
|
|
83
86
|
// Off the hand: the gate no longer applies.
|
|
84
87
|
const state = this.states.get(window.id);
|
|
@@ -87,27 +90,27 @@ export class UixWindowHost {
|
|
|
87
90
|
this.applyPresentation(window.id);
|
|
88
91
|
}
|
|
89
92
|
}
|
|
90
|
-
});
|
|
91
|
-
this.manager.events.on('regionChanged', ({ window }) => {
|
|
93
|
+
}));
|
|
94
|
+
this.subscriptions.push(this.manager.events.on('regionChanged', ({ window }) => {
|
|
92
95
|
this.applyRegion(window);
|
|
93
|
-
});
|
|
94
|
-
this.manager.events.on('returnHome', (record) => {
|
|
96
|
+
}));
|
|
97
|
+
this.subscriptions.push(this.manager.events.on('returnHome', (record) => {
|
|
95
98
|
this.returnHome(record.id);
|
|
96
|
-
});
|
|
97
|
-
this.manager.events.on('chromeChanged', ({ window }) => {
|
|
99
|
+
}));
|
|
100
|
+
this.subscriptions.push(this.manager.events.on('chromeChanged', ({ window }) => {
|
|
98
101
|
this.applyChrome(window);
|
|
99
|
-
});
|
|
100
|
-
this.manager.events.on('minimized', (record) => {
|
|
102
|
+
}));
|
|
103
|
+
this.subscriptions.push(this.manager.events.on('minimized', (record) => {
|
|
101
104
|
this.setContentCollapsed(record.id, true);
|
|
102
105
|
this.syncMinimizeLabel(record.id);
|
|
103
|
-
});
|
|
104
|
-
this.manager.events.on('restored', (record) => {
|
|
106
|
+
}));
|
|
107
|
+
this.subscriptions.push(this.manager.events.on('restored', (record) => {
|
|
105
108
|
this.setContentCollapsed(record.id, false);
|
|
106
109
|
this.syncMinimizeLabel(record.id);
|
|
107
|
-
});
|
|
108
|
-
this.manager.events.on('dockChanged', ({ window }) => {
|
|
110
|
+
}));
|
|
111
|
+
this.subscriptions.push(this.manager.events.on('dockChanged', ({ window }) => {
|
|
109
112
|
this.syncPinLabel(window.id);
|
|
110
|
-
});
|
|
113
|
+
}));
|
|
111
114
|
}
|
|
112
115
|
// --- WindowHost -----------------------------------------------------------
|
|
113
116
|
/**
|
|
@@ -128,6 +131,30 @@ export class UixWindowHost {
|
|
|
128
131
|
}
|
|
129
132
|
return () => void this.readyListeners.delete(listener);
|
|
130
133
|
}
|
|
134
|
+
/**
|
|
135
|
+
* Leave nothing behind: close every window through the manager, so each
|
|
136
|
+
* goes down the normal close path (its document disposed, its group
|
|
137
|
+
* removed), remove the region groups this host added to the scene, then
|
|
138
|
+
* release every manager subscription. Safe to call twice.
|
|
139
|
+
*/
|
|
140
|
+
dispose() {
|
|
141
|
+
if (this.disposed)
|
|
142
|
+
return;
|
|
143
|
+
this.disposed = true;
|
|
144
|
+
for (const id of [...this.states.keys()]) {
|
|
145
|
+
if (this.manager.has(id))
|
|
146
|
+
this.manager.close(id);
|
|
147
|
+
}
|
|
148
|
+
for (const region of this.regionStates.values()) {
|
|
149
|
+
region.handle.group.removeFromParent();
|
|
150
|
+
}
|
|
151
|
+
this.regionStates.clear();
|
|
152
|
+
this.ready.clear();
|
|
153
|
+
this.readyListeners.clear();
|
|
154
|
+
for (const unsubscribe of this.subscriptions)
|
|
155
|
+
unsubscribe();
|
|
156
|
+
this.subscriptions.length = 0;
|
|
157
|
+
}
|
|
131
158
|
// --- SceneTarget (portable scene descriptors) -----------------------------
|
|
132
159
|
spawnRegion(region) {
|
|
133
160
|
this.createRegion({
|
|
@@ -241,7 +268,6 @@ export class UixWindowHost {
|
|
|
241
268
|
this.manager.undock(record.id);
|
|
242
269
|
throw error;
|
|
243
270
|
}
|
|
244
|
-
this.manager.setDockMode(record.id, DockMode.WorldLocked);
|
|
245
271
|
}
|
|
246
272
|
this.layoutRegions();
|
|
247
273
|
}
|
package/dist/host.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"host.js","sourceRoot":"","sources":["../src/host.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * UixWindowHost - the engine binding for plain three.js / XR Blocks scenes.\n *\n * Owns a core `WindowManager` + `RegionRegistry` and applies their decisions\n * to the scene graph: spawn UIKitML windows and dock regions, wire chrome\n * buttons (focus / PIN / DOCK / MIN / X), collapse content while minimized,\n * hide and show, place docked windows into their region's slots, return a\n * window to where it spawned, ease `body-follow` windows (and body-locked\n * regions) toward the viewer each frame, and ride `hand-locked` windows\n * (hand menus) on a tracked hand behind the palm gate.\n *\n * The manager is the API app code drives; every manager event is applied\n * here, so `host.manager.hide(id)` or `.dockTo(id, region)` from a hand menu\n * is all a caller needs.\n *\n * It implements the core's `WindowHost` (so app code can wire behaviour\n * through `onPanelReady` with no engine knowledge) and `SceneTarget` (so a\n * portable `SceneDescriptor` builds the same playground here as on IWSDK).\n */\nimport { Group, type Object3D } from 'three';\nimport { parse, type Kit } from '@pmndrs/uikitml';\n\n/**\n * Default `config` resolver: fetch UIKitML source and parse it.\n *\n * IWSDK 0.5 dropped the build-time compile step and parses `PanelUI.config`\n * as source at runtime, so descriptors carry `.uikitml` paths. This parses the\n * same file for the three.js and XR Blocks hosts, which interpret an AST.\n */\nasync function loadUikitmlSource(path: string): Promise<unknown> {\n const response = await fetch(path);\n if (!response.ok) {\n throw new Error(`UIKitML source ${path} -> HTTP ${response.status}`);\n }\n return parse(await response.text());\n}\nimport {\n DockMode,\n RegionRegistry,\n WINDOW_CHROME_IDS,\n WindowManager,\n evaluateHandMenu,\n minimizeLabelFor,\n pinLabelFor,\n slotOffset,\n type HandPoseSource,\n type HandPoses,\n type HeadPoseSource,\n type PanelHandle,\n type PanelReadyEvent,\n type RegionDefinition,\n type WindowChrome,\n type WindowRecord,\n type SceneRegion,\n type SceneTarget,\n type SceneWindow,\n type UixElement,\n type Vec3Tuple,\n type WindowHandle as CoreWindowHandle,\n type WindowHost,\n type WindowOptionsBase,\n} from '@realitycollective/webxr-uiextensions';\nimport {\n approach,\n approachAlpha,\n distanceSquared,\n followTarget,\n} from './follow-math.js';\nimport { UixPanelDocument } from './panel-document.js';\n\n/**\n * Options for {@link UixWindowHost.createWindow}.\n *\n * Everything but `config` comes from the portable {@link WindowOptionsBase},\n * so an option means the same thing here as on the IWSDK adapter. `id` is\n * optional: leave it out and the host names the window `uix-window-<n>`.\n *\n * One option is accepted but not acted on: `movable`. This host has no\n * title-bar drag of its own yet - dragging comes from the XR Blocks / desktop\n * input layer above it - so the flag is recorded and otherwise ignored.\n */\nexport interface CreateWindowOptions extends WindowOptionsBase {\n /** Compiled UIKitML JSON (the `{ element, classes }` shape). */\n config: unknown;\n}\n\nexport interface CreateRegionOptions extends Partial<RegionDefinition> {\n id: string;\n position?: Vec3Tuple;\n /** Body-lock the region so it follows the viewer. */\n follow?: boolean;\n followOffset?: Vec3Tuple;\n}\n\n/**\n * A window spawned by {@link UixWindowHost.createWindow}.\n *\n * Satisfies the core {@link CoreWindowHandle} and adds the three.js specifics.\n * `panel` is the document itself, which already implements `PanelHandle`, and\n * is never `undefined` here: uikitml interprets the markup synchronously, so\n * the panel exists the moment `createWindow` returns.\n */\nexport interface XrBlocksWindowHandle extends CoreWindowHandle {\n readonly id: string;\n /** The scene-graph node - position/rotate freely. */\n group: Group;\n document: UixPanelDocument;\n /** Same object as {@link document}, under the portable name. */\n readonly panel: UixPanelDocument;\n onReady(listener: (panel: PanelHandle) => void): () => void;\n}\n\n/** Back-compatible name for {@link XrBlocksWindowHandle}. */\nexport type WindowHandle = XrBlocksWindowHandle;\n\nexport interface RegionHandle {\n id: string;\n group: Group;\n}\n\nexport interface UixWindowHostOptions {\n /** Parent for spawned windows (the scene, or any group inside it). */\n scene: Object3D;\n /** Viewer pose provider - camera on desktop, HMD pose in XR. */\n headPose: HeadPoseSource;\n /**\n * Tracked-hand pose provider, for `hand-locked` windows (hand menus). See\n * `webxrHandPoseSource` for one backed by a WebXR session. Leave it out\n * where there are no hands (a desktop) and hand-locked windows fall back\n * to body-follow placement, so the same scene still shows its menus.\n */\n handPose?: HandPoseSource;\n /** Optional UIKitML component kit(s) (e.g. horizon kit). */\n kit?: Kit;\n /**\n * Resolver for a window's `config` when it arrives as a string path (as\n * portable `SceneDescriptor`s carry it).\n *\n * Defaults to fetching the `.uikitml` source and parsing it, which is the\n * same artefact IWSDK loads - so one markup file serves every adapter and\n * no build step is required. Override only for an unusual transport; you do\n * not need to supply this to load a normal panel.\n */\n loadConfig?: (path: string) => Promise<unknown>;\n}\n\ninterface FollowOptions {\n followOffset: Vec3Tuple;\n followSpeed: number;\n followTolerance: number;\n}\n\ninterface WindowState {\n handle: XrBlocksWindowHandle;\n /** Where the window spawned, for `returnHome`. */\n home: { region: string | undefined; position: Vec3Tuple; dockMode: WindowRecord['dockMode'] };\n /**\n * Recorded from the create options and not acted on - see\n * {@link CreateWindowOptions}. Kept so a future drag path here, or a caller\n * inspecting the host, reads the value the scene descriptor asked for.\n */\n movable: boolean;\n options: FollowOptions;\n content: UixElement | undefined;\n pin: UixElement | undefined;\n minimize: UixElement | undefined;\n /** Every chrome button by its role, for `chromeChanged`. */\n buttons: Record<keyof WindowChrome, UixElement | undefined>;\n /** Hand-menu palm gate this frame; always open in the other dock modes. */\n gateOpen: boolean;\n}\n\ninterface RegionState {\n handle: RegionHandle;\n follow: boolean;\n followOffset: Vec3Tuple;\n}\n\nconst DEFAULT_FOLLOW_OFFSET: Vec3Tuple = [0, -0.15, -1.2];\nconst DEFAULT_REGION_FOLLOW_OFFSET: Vec3Tuple = [0, -0.2, -1.4];\n\nexport class UixWindowHost implements WindowHost, SceneTarget {\n /** Bare panels work here - the host does not own a panel lifecycle. */\n readonly supportsStandalonePanels: boolean = true;\n readonly manager = new WindowManager();\n readonly regions = new RegionRegistry();\n private readonly scene: Object3D;\n private readonly headPose: HeadPoseSource;\n private readonly handPose: HandPoseSource | undefined;\n private readonly kit: Kit | undefined;\n private readonly loadConfig: (path: string) => Promise<unknown>;\n private readonly states = new Map<string, WindowState>();\n private readonly regionStates = new Map<string, RegionState>();\n private readonly readyListeners = new Set<(event: PanelReadyEvent) => void>();\n /** Panels already live - replayed to late `onPanelReady` subscribers. */\n private readonly ready = new Map<string, PanelReadyEvent>();\n /** Feeds `uix-window-<n>` ids to windows created without one. */\n private windowSequence = 0;\n\n constructor(options: UixWindowHostOptions) {\n this.scene = options.scene;\n this.headPose = options.headPose;\n this.handPose = options.handPose;\n this.kit = options.kit;\n this.loadConfig = options.loadConfig ?? loadUikitmlSource;\n\n this.manager.events.on('closed', (record) => {\n const state = this.states.get(record.id);\n if (state) {\n this.states.delete(record.id);\n this.ready.delete(record.id);\n this.regions.undock(record.id);\n state.handle.document.dispose();\n state.handle.group.removeFromParent();\n this.layoutRegions();\n }\n });\n this.manager.events.on('hidden', (record) => {\n this.applyPresentation(record.id);\n });\n this.manager.events.on('shown', (record) => {\n this.applyPresentation(record.id);\n });\n this.manager.events.on('dockChanged', ({ window, previous }) => {\n if (previous === DockMode.HandLocked) {\n // Off the hand: the gate no longer applies.\n const state = this.states.get(window.id);\n if (state) {\n state.gateOpen = true;\n this.applyPresentation(window.id);\n }\n }\n });\n this.manager.events.on('regionChanged', ({ window }) => {\n this.applyRegion(window);\n });\n this.manager.events.on('returnHome', (record) => {\n this.returnHome(record.id);\n });\n this.manager.events.on('chromeChanged', ({ window }) => {\n this.applyChrome(window);\n });\n this.manager.events.on('minimized', (record) => {\n this.setContentCollapsed(record.id, true);\n this.syncMinimizeLabel(record.id);\n });\n this.manager.events.on('restored', (record) => {\n this.setContentCollapsed(record.id, false);\n this.syncMinimizeLabel(record.id);\n });\n this.manager.events.on('dockChanged', ({ window }) => {\n this.syncPinLabel(window.id);\n });\n }\n\n // --- WindowHost -----------------------------------------------------------\n\n /**\n * PanelHost - bare panel, unmanaged (used by devtools and tests). Always\n * available here, which is what `supportsStandalonePanels` reports.\n */\n createPanel(configJson: unknown): UixPanelDocument {\n return new UixPanelDocument(configJson, this.kit);\n }\n\n /**\n * Observe panel readiness. Windows already live are replayed immediately,\n * so wiring code never races window creation.\n */\n onPanelReady(listener: (event: PanelReadyEvent) => void): () => void {\n this.readyListeners.add(listener);\n for (const event of this.ready.values()) {\n listener(event);\n }\n return () => void this.readyListeners.delete(listener);\n }\n\n // --- SceneTarget (portable scene descriptors) -----------------------------\n\n spawnRegion(region: SceneRegion): void {\n this.createRegion({\n id: region.id,\n ...(region.flow !== undefined ? { flow: region.flow } : {}),\n ...(region.pitch !== undefined ? { pitch: region.pitch } : {}),\n ...(region.columns !== undefined ? { columns: region.columns } : {}),\n ...(region.capacity !== undefined ? { capacity: region.capacity } : {}),\n ...(region.snapRadius !== undefined ? { snapRadius: region.snapRadius } : {}),\n ...(region.position !== undefined\n ? { position: [...region.position] as Vec3Tuple }\n : {}),\n ...(region.follow !== undefined ? { follow: region.follow } : {}),\n ...(region.followOffset !== undefined\n ? { followOffset: [...region.followOffset] as Vec3Tuple }\n : {}),\n });\n }\n\n /**\n * Scene descriptors carry config PATHS; this resolves the path and spawns\n * the window when it arrives. Fire-and-forget by design - subscribe with\n * {@link onPanelReady} to wire behaviour once the panel exists.\n */\n spawnWindow(window: SceneWindow): void {\n void this.loadConfig(window.config)\n .then((config) => {\n this.createWindow({\n id: window.id,\n config,\n title: window.title,\n ...(window.position !== undefined\n ? { position: [...window.position] as Vec3Tuple }\n : {}),\n ...(window.maxWidth !== undefined ? { maxWidth: window.maxWidth } : {}),\n ...(window.maxHeight !== undefined ? { maxHeight: window.maxHeight } : {}),\n ...(window.dockMode !== undefined ? { dockMode: window.dockMode } : {}),\n ...(window.region !== undefined ? { region: window.region } : {}),\n ...(window.followOffset !== undefined\n ? { followOffset: [...window.followOffset] as Vec3Tuple }\n : {}),\n ...(window.followSpeed !== undefined\n ? { followSpeed: window.followSpeed }\n : {}),\n ...(window.followTolerance !== undefined\n ? { followTolerance: window.followTolerance }\n : {}),\n ...(window.movable !== undefined ? { movable: window.movable } : {}),\n ...(window.closable !== undefined ? { closable: window.closable } : {}),\n ...(window.minimizable !== undefined\n ? { minimizable: window.minimizable }\n : {}),\n ...(window.pinnable !== undefined ? { pinnable: window.pinnable } : {}),\n ...(window.dockable !== undefined ? { dockable: window.dockable } : {}),\n ...(window.handMenu !== undefined ? { handMenu: window.handMenu } : {}),\n });\n })\n .catch((error) => {\n console.error(`[uix] failed to load panel \"${window.id}\":`, error);\n });\n }\n\n // --- Regions --------------------------------------------------------------\n\n /** Create a dock region anchored in the scene. */\n createRegion(options: CreateRegionOptions): RegionHandle {\n const { id, position, follow, followOffset, ...definition } = options;\n this.regions.register(id, definition);\n\n const group = new Group();\n group.name = `uix-region:${id}`;\n if (position) {\n group.position.set(...position);\n }\n this.scene.add(group);\n\n const handle: RegionHandle = { id, group };\n this.regionStates.set(id, {\n handle,\n follow: follow ?? false,\n followOffset: followOffset ?? DEFAULT_REGION_FOLLOW_OFFSET,\n });\n return handle;\n }\n\n region(id: string): RegionHandle | undefined {\n return this.regionStates.get(id)?.handle;\n }\n\n /**\n * Dock a window into a region (or undock it with `undefined`). A thin\n * forwarder to the manager, kept so existing callers read the same;\n * `manager.dockTo` / `manager.undock` are the portable calls.\n */\n dock(windowId: string, regionId: string | undefined): void {\n if (regionId === undefined) {\n this.manager.undock(windowId);\n } else {\n this.manager.dockTo(windowId, regionId);\n }\n }\n\n /** Make the registry (and the layout) agree with the record's region. */\n private applyRegion(record: Pick<WindowRecord, 'id' | 'region'>): void {\n const current = this.regions.regionOf(record.id);\n if (current === record.region) {\n return;\n }\n if (current !== undefined) {\n this.regions.undock(record.id);\n }\n if (record.region !== undefined) {\n try {\n this.regions.dock(record.id, record.region);\n } catch (error) {\n // Unknown or full region: the record must not claim it.\n this.manager.undock(record.id);\n throw error;\n }\n this.manager.setDockMode(record.id, DockMode.WorldLocked);\n }\n this.layoutRegions();\n }\n\n /** Put a window back where it spawned: its region, or its placement and mode. */\n private returnHome(id: string): void {\n const state = this.states.get(id);\n if (!state) {\n return;\n }\n const { home } = state;\n if (home.region !== undefined) {\n this.manager.dockTo(id, home.region);\n return;\n }\n this.manager.undock(id);\n this.manager.setDockMode(id, home.dockMode);\n if (home.dockMode === DockMode.WorldLocked) {\n state.handle.group.position.set(...home.position);\n }\n // Follow modes ease back to the viewer on their own in update().\n }\n\n // --- Windows --------------------------------------------------------------\n\n /** Spawn a managed window from compiled UIKitML JSON. */\n createWindow(options: CreateWindowOptions): XrBlocksWindowHandle {\n const id = options.id ?? `uix-window-${(this.windowSequence += 1)}`;\n const document = new UixPanelDocument(options.config, this.kit);\n document.setTargetDimensions(options.maxWidth ?? 1, options.maxHeight ?? 1);\n\n const group = new Group();\n group.name = `uix-window:${id}`;\n group.add(document);\n if (options.position) {\n group.position.set(...options.position);\n }\n this.scene.add(group);\n\n const handle: XrBlocksWindowHandle = {\n id,\n group,\n document,\n panel: document,\n // The panel exists already, so readiness is immediate. The unsubscribe\n // is returned anyway, so callers can write one shape of code for both\n // adapters.\n onReady(listener: (panel: PanelHandle) => void): () => void {\n listener(document);\n return () => {};\n },\n };\n const dockMode = options.dockMode ?? DockMode.WorldLocked;\n this.states.set(id, {\n handle,\n home: {\n region: options.region,\n position: options.position ? [...options.position] : [0, 0, 0],\n dockMode,\n },\n movable: options.movable ?? true,\n options: {\n followOffset: options.followOffset ?? DEFAULT_FOLLOW_OFFSET,\n followSpeed: options.followSpeed ?? 3,\n followTolerance: options.followTolerance ?? 0.35,\n },\n content: undefined,\n pin: undefined,\n minimize: undefined,\n buttons: { pin: undefined, dock: undefined, minimize: undefined, close: undefined },\n gateOpen: true,\n });\n\n const record = this.manager.open(id, {\n title: options.title ?? '',\n dockMode,\n // Chrome buttons are opt-in - see WindowOptionsBase.\n chrome: {\n close: options.closable ?? false,\n minimize: options.minimizable ?? false,\n pin: options.pinnable ?? false,\n dock: options.dockable ?? false,\n },\n ...(options.handMenu !== undefined ? { handMenu: options.handMenu } : {}),\n });\n this.wireChrome(options, handle);\n this.applyChrome(record);\n\n if (options.region !== undefined) {\n this.dock(id, options.region);\n }\n\n // The panel's element tree exists synchronously (uikitml interprets on\n // construction); only its LAYOUT is async. Announce readiness now so\n // wiring can attach handlers immediately.\n const event: PanelReadyEvent = { id, panel: document, kind: 'window' };\n this.ready.set(id, event);\n for (const listener of this.readyListeners) {\n try {\n listener(event);\n } catch (error) {\n console.error(`[uix] panel-ready listener failed for \"${id}\":`, error);\n }\n }\n\n return handle;\n }\n\n window(id: string): XrBlocksWindowHandle | undefined {\n return this.states.get(id)?.handle;\n }\n\n /** Drive per-frame from the engine loop (delta in SECONDS). */\n update(deltaSeconds: number): void {\n let hands: HandPoses | undefined;\n for (const [id, state] of this.states) {\n state.handle.document.update(deltaSeconds);\n const record = this.manager.get(id);\n if (!record) {\n continue;\n }\n const docked = this.regions.regionOf(id) !== undefined;\n if (record.dockMode === DockMode.HandLocked && !record.dragging && !docked) {\n if (this.handPose && (this.handPose.hasHands?.() ?? true)) {\n hands ??= this.readHands();\n this.placeOnHand(id, state, hands);\n } else {\n // No hands here (a desktop, or no session yet): the menu follows\n // the body instead, and the gate does not apply.\n state.gateOpen = true;\n this.applyPresentation(id);\n this.applyFollow(state.handle.group, state.options, deltaSeconds, true);\n }\n continue;\n }\n if (record.dockMode === DockMode.BodyFollow && !record.dragging && !docked) {\n this.applyFollow(state.handle.group, state.options, deltaSeconds, true);\n }\n }\n for (const state of this.regionStates.values()) {\n if (state.follow) {\n this.applyFollow(\n state.handle.group,\n {\n followOffset: state.followOffset,\n followSpeed: 3,\n followTolerance: 0.2,\n },\n deltaSeconds,\n false,\n );\n this.layoutRegion(state.handle.id);\n }\n }\n }\n\n /** This frame's tracked hands from the source, absent ones left out. */\n private readHands(): HandPoses {\n const poses: HandPoses = {};\n for (const hand of ['left', 'right'] as const) {\n const pose = this.handPose?.getHandPose(hand);\n if (pose) {\n poses[hand] = pose;\n }\n }\n return poses;\n }\n\n private placeOnHand(id: string, state: WindowState, hands: HandPoses): void {\n const record = this.manager.get(id);\n if (!record) {\n return;\n }\n const placement = evaluateHandMenu(hands, this.headPose.getHeadPose().position, record.handMenu);\n state.gateOpen = placement.visible;\n if (placement.pose) {\n state.handle.group.position.set(...placement.pose.position);\n state.handle.group.quaternion.set(...placement.pose.quaternion);\n }\n this.applyPresentation(id);\n }\n\n private applyFollow(\n group: Group,\n options: FollowOptions,\n deltaSeconds: number,\n faceViewer: boolean,\n ): void {\n const pose = this.headPose.getHeadPose();\n const target = followTarget(pose, options.followOffset);\n const position = group.position;\n const current: Vec3Tuple = [position.x, position.y, position.z];\n const tolerance = options.followTolerance;\n if (distanceSquared(current, target) <= tolerance * tolerance) {\n return;\n }\n const next = approach(\n current,\n target,\n approachAlpha(options.followSpeed, deltaSeconds),\n );\n position.set(...next);\n if (faceViewer) {\n group.lookAt(pose.position[0], position.y, pose.position[2]);\n }\n }\n\n /** Re-place every docked window into its region's slot. */\n private layoutRegions(): void {\n for (const id of this.regionStates.keys()) {\n this.layoutRegion(id);\n }\n }\n\n private layoutRegion(regionId: string): void {\n const regionState = this.regionStates.get(regionId);\n const registered = this.regions.get(regionId);\n if (!regionState || !registered) {\n return;\n }\n const origin = regionState.handle.group.position;\n registered.members.forEach((windowId, index) => {\n const windowState = this.states.get(windowId);\n if (!windowState) {\n return;\n }\n const [dx, dy, dz] = slotOffset(registered.definition, index);\n windowState.handle.group.position.set(\n origin.x + dx,\n origin.y + dy,\n origin.z + dz,\n );\n windowState.handle.group.quaternion.copy(regionState.handle.group.quaternion);\n });\n }\n\n private wireChrome(\n options: CreateWindowOptions,\n handle: XrBlocksWindowHandle,\n ): void {\n const element = (id: string) => handle.document.getElementById(id);\n const id = handle.id;\n\n const title = element(WINDOW_CHROME_IDS.title);\n if (title && options.title) {\n title.setProperties({ text: options.title });\n }\n\n // Chrome presses must not bubble to the window root's focus handler:\n // a press on CLOSE would otherwise focus a window that is about to be\n // destroyed, and `focus()` on a removed window throws. (Same guard the\n // IWSDK adapter applies.)\n const swallowPress = (button: UixElement | undefined): void => {\n button?.addEventListener('pointerdown', (event) => {\n (event as { stopPropagation?: () => void } | undefined)?.stopPropagation?.();\n });\n };\n swallowPress(element(WINDOW_CHROME_IDS.pin));\n swallowPress(element(WINDOW_CHROME_IDS.dock));\n swallowPress(element(WINDOW_CHROME_IDS.minimize));\n swallowPress(element(WINDOW_CHROME_IDS.close));\n\n // Any press anywhere on the window brings it to the front. Guarded:\n // events can still arrive for a window that was just closed.\n element(WINDOW_CHROME_IDS.window)?.addEventListener('pointerdown', () => {\n if (this.manager.has(id)) {\n this.manager.focus(id);\n }\n });\n\n const state = this.states.get(id);\n if (state) {\n state.content = element(WINDOW_CHROME_IDS.content);\n state.pin = element(WINDOW_CHROME_IDS.pin);\n state.minimize = element(WINDOW_CHROME_IDS.minimize);\n state.buttons = {\n close: element(WINDOW_CHROME_IDS.close),\n minimize: element(WINDOW_CHROME_IDS.minimize),\n pin: element(WINDOW_CHROME_IDS.pin),\n dock: element(WINDOW_CHROME_IDS.dock),\n };\n }\n\n // Every button is wired once and gated on the record at click time, so\n // enabling a button later (manager.setChrome) needs no rewiring.\n const enabled = (key: keyof WindowChrome): boolean =>\n this.manager.get(id)?.chrome[key] === true;\n\n element(WINDOW_CHROME_IDS.close)?.addEventListener('click', () => {\n if (enabled('close')) {\n this.manager.close(id);\n }\n });\n element(WINDOW_CHROME_IDS.minimize)?.addEventListener('click', () => {\n if (enabled('minimize')) {\n this.manager.toggleMinimized(id);\n }\n });\n element(WINDOW_CHROME_IDS.pin)?.addEventListener('click', () => {\n if (enabled('pin')) {\n // Pinning a docked window pops it out of its region first.\n this.manager.undock(id);\n this.manager.togglePin(id);\n }\n });\n element(WINDOW_CHROME_IDS.dock)?.addEventListener('click', () => {\n if (enabled('dock')) {\n this.manager.returnHome(id);\n }\n });\n this.syncMinimizeLabel(id);\n this.syncPinLabel(id);\n }\n\n /** Show exactly the enabled buttons. */\n private applyChrome(record: Pick<WindowRecord, 'id' | 'chrome'>): void {\n const buttons = this.states.get(record.id)?.buttons;\n if (!buttons) {\n return;\n }\n for (const key of ['close', 'minimize', 'pin', 'dock'] as const) {\n buttons[key]?.setProperties({ display: record.chrome[key] ? 'flex' : 'none' });\n }\n }\n\n /** Drawn exactly when not hidden and (for a hand menu) the palm gate is open. */\n private applyPresentation(id: string): void {\n const state = this.states.get(id);\n const record = this.manager.get(id);\n if (state && record) {\n state.handle.group.visible = !record.hidden && state.gateOpen;\n }\n }\n\n private setContentCollapsed(id: string, collapsed: boolean): void {\n this.states\n .get(id)\n ?.content?.setProperties({ display: collapsed ? 'none' : 'flex' });\n }\n\n /** MIN when open, MAX when minimized - the label names the next action. */\n private syncMinimizeLabel(id: string): void {\n const record = this.manager.get(id);\n const minimize = this.states.get(id)?.minimize;\n if (record && minimize) {\n minimize.setProperties({ text: minimizeLabelFor(record) });\n }\n }\n\n private syncPinLabel(id: string): void {\n const record = this.manager.get(id);\n const pin = this.states.get(id)?.pin;\n if (record && pin) {\n pin.setProperties({ text: pinLabelFor(record) });\n }\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"host.js","sourceRoot":"","sources":["../src/host.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * UixWindowHost - the engine binding for plain three.js / XR Blocks scenes.\n *\n * Owns a core `WindowManager` + `RegionRegistry` and applies their decisions\n * to the scene graph: spawn UIKitML windows and dock regions, wire chrome\n * buttons (focus / PIN / DOCK / MIN / X), collapse content while minimized,\n * hide and show, place docked windows into their region's slots, return a\n * window to where it spawned, ease `body-follow` windows (and body-locked\n * regions) toward the viewer each frame, and ride `hand-locked` windows\n * (hand menus) on a tracked hand behind the palm gate.\n *\n * The manager is the API app code drives; every manager event is applied\n * here, so `host.manager.hide(id)` or `.dockTo(id, region)` from a hand menu\n * is all a caller needs.\n *\n * It implements the core's `WindowHost` (so app code can wire behaviour\n * through `onPanelReady` with no engine knowledge) and `SceneTarget` (so a\n * portable `SceneDescriptor` builds the same playground here as on IWSDK).\n */\nimport { Group, type Object3D } from 'three';\nimport { parse, type Kit } from '@pmndrs/uikitml';\n\n/**\n * Default `config` resolver: fetch UIKitML source and parse it.\n *\n * IWSDK 0.5 dropped the build-time compile step and parses `PanelUI.config`\n * as source at runtime, so descriptors carry `.uikitml` paths. This parses the\n * same file for the three.js and XR Blocks hosts, which interpret an AST.\n */\nasync function loadUikitmlSource(path: string): Promise<unknown> {\n const response = await fetch(path);\n if (!response.ok) {\n throw new Error(`UIKitML source ${path} -> HTTP ${response.status}`);\n }\n return parse(await response.text());\n}\nimport {\n DockMode,\n RegionRegistry,\n WINDOW_CHROME_IDS,\n WindowManager,\n evaluateHandMenu,\n minimizeLabelFor,\n pinLabelFor,\n slotOffset,\n type HandPoseSource,\n type HandPoses,\n type HeadPoseSource,\n type PanelHandle,\n type PanelReadyEvent,\n type RegionDefinition,\n type WindowChrome,\n type WindowRecord,\n type SceneRegion,\n type SceneTarget,\n type SceneWindow,\n type UixElement,\n type Vec3Tuple,\n type WindowHandle as CoreWindowHandle,\n type WindowHost,\n type WindowOptionsBase,\n} from '@realitycollective/webxr-uiextensions';\nimport {\n approach,\n approachAlpha,\n distanceSquared,\n followTarget,\n} from './follow-math.js';\nimport { UixPanelDocument } from './panel-document.js';\n\n/**\n * Options for {@link UixWindowHost.createWindow}.\n *\n * Everything but `config` comes from the portable {@link WindowOptionsBase},\n * so an option means the same thing here as on the IWSDK adapter. `id` is\n * optional: leave it out and the host names the window `uix-window-<n>`.\n *\n * One option is accepted but not acted on: `movable`. This host has no\n * title-bar drag of its own yet - dragging comes from the XR Blocks / desktop\n * input layer above it - so the flag is recorded and otherwise ignored.\n */\nexport interface CreateWindowOptions extends WindowOptionsBase {\n /** Compiled UIKitML JSON (the `{ element, classes }` shape). */\n config: unknown;\n}\n\nexport interface CreateRegionOptions extends Partial<RegionDefinition> {\n id: string;\n position?: Vec3Tuple;\n /** Body-lock the region so it follows the viewer. */\n follow?: boolean;\n followOffset?: Vec3Tuple;\n}\n\n/**\n * A window spawned by {@link UixWindowHost.createWindow}.\n *\n * Satisfies the core {@link CoreWindowHandle} and adds the three.js specifics.\n * `panel` is the document itself, which already implements `PanelHandle`, and\n * is never `undefined` here: uikitml interprets the markup synchronously, so\n * the panel exists the moment `createWindow` returns.\n */\nexport interface XrBlocksWindowHandle extends CoreWindowHandle {\n readonly id: string;\n /** The scene-graph node - position/rotate freely. */\n group: Group;\n document: UixPanelDocument;\n /** Same object as {@link document}, under the portable name. */\n readonly panel: UixPanelDocument;\n onReady(listener: (panel: PanelHandle) => void): () => void;\n}\n\n/** Back-compatible name for {@link XrBlocksWindowHandle}. */\nexport type WindowHandle = XrBlocksWindowHandle;\n\nexport interface RegionHandle {\n id: string;\n group: Group;\n}\n\nexport interface UixWindowHostOptions {\n /** Parent for spawned windows (the scene, or any group inside it). */\n scene: Object3D;\n /** Viewer pose provider - camera on desktop, HMD pose in XR. */\n headPose: HeadPoseSource;\n /**\n * Tracked-hand pose provider, for `hand-locked` windows (hand menus). See\n * `webxrHandPoseSource` for one backed by a WebXR session. Leave it out\n * where there are no hands (a desktop) and hand-locked windows fall back\n * to body-follow placement, so the same scene still shows its menus.\n */\n handPose?: HandPoseSource;\n /** Optional UIKitML component kit(s) (e.g. horizon kit). */\n kit?: Kit;\n /**\n * Resolver for a window's `config` when it arrives as a string path (as\n * portable `SceneDescriptor`s carry it).\n *\n * Defaults to fetching the `.uikitml` source and parsing it, which is the\n * same artefact IWSDK loads - so one markup file serves every adapter and\n * no build step is required. Override only for an unusual transport; you do\n * not need to supply this to load a normal panel.\n */\n loadConfig?: (path: string) => Promise<unknown>;\n}\n\ninterface FollowOptions {\n followOffset: Vec3Tuple;\n followSpeed: number;\n followTolerance: number;\n}\n\ninterface WindowState {\n handle: XrBlocksWindowHandle;\n /** Where the window spawned, for `returnHome`. */\n home: { region: string | undefined; position: Vec3Tuple; dockMode: WindowRecord['dockMode'] };\n /**\n * Recorded from the create options and not acted on - see\n * {@link CreateWindowOptions}. Kept so a future drag path here, or a caller\n * inspecting the host, reads the value the scene descriptor asked for.\n */\n movable: boolean;\n options: FollowOptions;\n content: UixElement | undefined;\n pin: UixElement | undefined;\n minimize: UixElement | undefined;\n /** Every chrome button by its role, for `chromeChanged`. */\n buttons: Record<keyof WindowChrome, UixElement | undefined>;\n /** Hand-menu palm gate this frame; always open in the other dock modes. */\n gateOpen: boolean;\n}\n\ninterface RegionState {\n handle: RegionHandle;\n follow: boolean;\n followOffset: Vec3Tuple;\n}\n\nconst DEFAULT_FOLLOW_OFFSET: Vec3Tuple = [0, -0.15, -1.2];\nconst DEFAULT_REGION_FOLLOW_OFFSET: Vec3Tuple = [0, -0.2, -1.4];\n\nexport class UixWindowHost implements WindowHost, SceneTarget {\n /** Bare panels work here - the host does not own a panel lifecycle. */\n readonly supportsStandalonePanels: boolean = true;\n readonly manager = new WindowManager();\n readonly regions = new RegionRegistry();\n private readonly scene: Object3D;\n private readonly headPose: HeadPoseSource;\n private readonly handPose: HandPoseSource | undefined;\n private readonly kit: Kit | undefined;\n private readonly loadConfig: (path: string) => Promise<unknown>;\n private readonly states = new Map<string, WindowState>();\n private readonly regionStates = new Map<string, RegionState>();\n private readonly readyListeners = new Set<(event: PanelReadyEvent) => void>();\n /** Panels already live - replayed to late `onPanelReady` subscribers. */\n private readonly ready = new Map<string, PanelReadyEvent>();\n /** Feeds `uix-window-<n>` ids to windows created without one. */\n private windowSequence = 0;\n /** Every manager subscription, released by {@link dispose}. */\n private readonly subscriptions: Array<() => void> = [];\n private disposed = false;\n\n constructor(options: UixWindowHostOptions) {\n this.scene = options.scene;\n this.headPose = options.headPose;\n this.handPose = options.handPose;\n this.kit = options.kit;\n this.loadConfig = options.loadConfig ?? loadUikitmlSource;\n\n this.subscriptions.push(this.manager.events.on('closed', (record) => {\n const state = this.states.get(record.id);\n if (state) {\n this.states.delete(record.id);\n this.ready.delete(record.id);\n this.regions.undock(record.id);\n state.handle.document.dispose();\n state.handle.group.removeFromParent();\n this.layoutRegions();\n }\n }));\n this.subscriptions.push(this.manager.events.on('hidden', (record) => {\n this.applyPresentation(record.id);\n }));\n this.subscriptions.push(this.manager.events.on('shown', (record) => {\n this.applyPresentation(record.id);\n }));\n this.subscriptions.push(this.manager.events.on('dockChanged', ({ window, previous }) => {\n if (previous === DockMode.HandLocked) {\n // Off the hand: the gate no longer applies.\n const state = this.states.get(window.id);\n if (state) {\n state.gateOpen = true;\n this.applyPresentation(window.id);\n }\n }\n }));\n this.subscriptions.push(this.manager.events.on('regionChanged', ({ window }) => {\n this.applyRegion(window);\n }));\n this.subscriptions.push(this.manager.events.on('returnHome', (record) => {\n this.returnHome(record.id);\n }));\n this.subscriptions.push(this.manager.events.on('chromeChanged', ({ window }) => {\n this.applyChrome(window);\n }));\n this.subscriptions.push(this.manager.events.on('minimized', (record) => {\n this.setContentCollapsed(record.id, true);\n this.syncMinimizeLabel(record.id);\n }));\n this.subscriptions.push(this.manager.events.on('restored', (record) => {\n this.setContentCollapsed(record.id, false);\n this.syncMinimizeLabel(record.id);\n }));\n this.subscriptions.push(this.manager.events.on('dockChanged', ({ window }) => {\n this.syncPinLabel(window.id);\n }));\n }\n\n // --- WindowHost -----------------------------------------------------------\n\n /**\n * PanelHost - bare panel, unmanaged (used by devtools and tests). Always\n * available here, which is what `supportsStandalonePanels` reports.\n */\n createPanel(configJson: unknown): UixPanelDocument {\n return new UixPanelDocument(configJson, this.kit);\n }\n\n /**\n * Observe panel readiness. Windows already live are replayed immediately,\n * so wiring code never races window creation.\n */\n onPanelReady(listener: (event: PanelReadyEvent) => void): () => void {\n this.readyListeners.add(listener);\n for (const event of this.ready.values()) {\n listener(event);\n }\n return () => void this.readyListeners.delete(listener);\n }\n\n /**\n * Leave nothing behind: close every window through the manager, so each\n * goes down the normal close path (its document disposed, its group\n * removed), remove the region groups this host added to the scene, then\n * release every manager subscription. Safe to call twice.\n */\n dispose(): void {\n if (this.disposed) return;\n this.disposed = true;\n for (const id of [...this.states.keys()]) {\n if (this.manager.has(id)) this.manager.close(id);\n }\n for (const region of this.regionStates.values()) {\n region.handle.group.removeFromParent();\n }\n this.regionStates.clear();\n this.ready.clear();\n this.readyListeners.clear();\n for (const unsubscribe of this.subscriptions) unsubscribe();\n this.subscriptions.length = 0;\n }\n\n // --- SceneTarget (portable scene descriptors) -----------------------------\n\n spawnRegion(region: SceneRegion): void {\n this.createRegion({\n id: region.id,\n ...(region.flow !== undefined ? { flow: region.flow } : {}),\n ...(region.pitch !== undefined ? { pitch: region.pitch } : {}),\n ...(region.columns !== undefined ? { columns: region.columns } : {}),\n ...(region.capacity !== undefined ? { capacity: region.capacity } : {}),\n ...(region.snapRadius !== undefined ? { snapRadius: region.snapRadius } : {}),\n ...(region.position !== undefined\n ? { position: [...region.position] as Vec3Tuple }\n : {}),\n ...(region.follow !== undefined ? { follow: region.follow } : {}),\n ...(region.followOffset !== undefined\n ? { followOffset: [...region.followOffset] as Vec3Tuple }\n : {}),\n });\n }\n\n /**\n * Scene descriptors carry config PATHS; this resolves the path and spawns\n * the window when it arrives. Fire-and-forget by design - subscribe with\n * {@link onPanelReady} to wire behaviour once the panel exists.\n */\n spawnWindow(window: SceneWindow): void {\n void this.loadConfig(window.config)\n .then((config) => {\n this.createWindow({\n id: window.id,\n config,\n title: window.title,\n ...(window.position !== undefined\n ? { position: [...window.position] as Vec3Tuple }\n : {}),\n ...(window.maxWidth !== undefined ? { maxWidth: window.maxWidth } : {}),\n ...(window.maxHeight !== undefined ? { maxHeight: window.maxHeight } : {}),\n ...(window.dockMode !== undefined ? { dockMode: window.dockMode } : {}),\n ...(window.region !== undefined ? { region: window.region } : {}),\n ...(window.followOffset !== undefined\n ? { followOffset: [...window.followOffset] as Vec3Tuple }\n : {}),\n ...(window.followSpeed !== undefined\n ? { followSpeed: window.followSpeed }\n : {}),\n ...(window.followTolerance !== undefined\n ? { followTolerance: window.followTolerance }\n : {}),\n ...(window.movable !== undefined ? { movable: window.movable } : {}),\n ...(window.closable !== undefined ? { closable: window.closable } : {}),\n ...(window.minimizable !== undefined\n ? { minimizable: window.minimizable }\n : {}),\n ...(window.pinnable !== undefined ? { pinnable: window.pinnable } : {}),\n ...(window.dockable !== undefined ? { dockable: window.dockable } : {}),\n ...(window.handMenu !== undefined ? { handMenu: window.handMenu } : {}),\n });\n })\n .catch((error) => {\n console.error(`[uix] failed to load panel \"${window.id}\":`, error);\n });\n }\n\n // --- Regions --------------------------------------------------------------\n\n /** Create a dock region anchored in the scene. */\n createRegion(options: CreateRegionOptions): RegionHandle {\n const { id, position, follow, followOffset, ...definition } = options;\n this.regions.register(id, definition);\n\n const group = new Group();\n group.name = `uix-region:${id}`;\n if (position) {\n group.position.set(...position);\n }\n this.scene.add(group);\n\n const handle: RegionHandle = { id, group };\n this.regionStates.set(id, {\n handle,\n follow: follow ?? false,\n followOffset: followOffset ?? DEFAULT_REGION_FOLLOW_OFFSET,\n });\n return handle;\n }\n\n region(id: string): RegionHandle | undefined {\n return this.regionStates.get(id)?.handle;\n }\n\n /**\n * Dock a window into a region (or undock it with `undefined`). A thin\n * forwarder to the manager, kept so existing callers read the same;\n * `manager.dockTo` / `manager.undock` are the portable calls.\n */\n dock(windowId: string, regionId: string | undefined): void {\n if (regionId === undefined) {\n this.manager.undock(windowId);\n } else {\n this.manager.dockTo(windowId, regionId);\n }\n }\n\n /** Make the registry (and the layout) agree with the record's region. */\n private applyRegion(record: Pick<WindowRecord, 'id' | 'region'>): void {\n const current = this.regions.regionOf(record.id);\n if (current === record.region) {\n return;\n }\n if (current !== undefined) {\n this.regions.undock(record.id);\n }\n if (record.region !== undefined) {\n try {\n this.regions.dock(record.id, record.region);\n } catch (error) {\n // Unknown or full region: the record must not claim it.\n this.manager.undock(record.id);\n throw error;\n }\n }\n this.layoutRegions();\n }\n\n /** Put a window back where it spawned: its region, or its placement and mode. */\n private returnHome(id: string): void {\n const state = this.states.get(id);\n if (!state) {\n return;\n }\n const { home } = state;\n if (home.region !== undefined) {\n this.manager.dockTo(id, home.region);\n return;\n }\n this.manager.undock(id);\n this.manager.setDockMode(id, home.dockMode);\n if (home.dockMode === DockMode.WorldLocked) {\n state.handle.group.position.set(...home.position);\n }\n // Follow modes ease back to the viewer on their own in update().\n }\n\n // --- Windows --------------------------------------------------------------\n\n /** Spawn a managed window from compiled UIKitML JSON. */\n createWindow(options: CreateWindowOptions): XrBlocksWindowHandle {\n const id = options.id ?? `uix-window-${(this.windowSequence += 1)}`;\n const document = new UixPanelDocument(options.config, this.kit);\n document.setTargetDimensions(options.maxWidth ?? 1, options.maxHeight ?? 1);\n\n const group = new Group();\n group.name = `uix-window:${id}`;\n group.add(document);\n if (options.position) {\n group.position.set(...options.position);\n }\n this.scene.add(group);\n\n const handle: XrBlocksWindowHandle = {\n id,\n group,\n document,\n panel: document,\n // The panel exists already, so readiness is immediate. The unsubscribe\n // is returned anyway, so callers can write one shape of code for both\n // adapters.\n onReady(listener: (panel: PanelHandle) => void): () => void {\n listener(document);\n return () => {};\n },\n };\n const dockMode = options.dockMode ?? DockMode.WorldLocked;\n this.states.set(id, {\n handle,\n home: {\n region: options.region,\n position: options.position ? [...options.position] : [0, 0, 0],\n dockMode,\n },\n movable: options.movable ?? true,\n options: {\n followOffset: options.followOffset ?? DEFAULT_FOLLOW_OFFSET,\n followSpeed: options.followSpeed ?? 3,\n followTolerance: options.followTolerance ?? 0.35,\n },\n content: undefined,\n pin: undefined,\n minimize: undefined,\n buttons: { pin: undefined, dock: undefined, minimize: undefined, close: undefined },\n gateOpen: true,\n });\n\n const record = this.manager.open(id, {\n title: options.title ?? '',\n dockMode,\n // Chrome buttons are opt-in - see WindowOptionsBase.\n chrome: {\n close: options.closable ?? false,\n minimize: options.minimizable ?? false,\n pin: options.pinnable ?? false,\n dock: options.dockable ?? false,\n },\n ...(options.handMenu !== undefined ? { handMenu: options.handMenu } : {}),\n });\n this.wireChrome(options, handle);\n this.applyChrome(record);\n\n if (options.region !== undefined) {\n this.dock(id, options.region);\n }\n\n // The panel's element tree exists synchronously (uikitml interprets on\n // construction); only its LAYOUT is async. Announce readiness now so\n // wiring can attach handlers immediately.\n const event: PanelReadyEvent = { id, panel: document, kind: 'window' };\n this.ready.set(id, event);\n for (const listener of this.readyListeners) {\n try {\n listener(event);\n } catch (error) {\n console.error(`[uix] panel-ready listener failed for \"${id}\":`, error);\n }\n }\n\n return handle;\n }\n\n window(id: string): XrBlocksWindowHandle | undefined {\n return this.states.get(id)?.handle;\n }\n\n /** Drive per-frame from the engine loop (delta in SECONDS). */\n update(deltaSeconds: number): void {\n let hands: HandPoses | undefined;\n for (const [id, state] of this.states) {\n state.handle.document.update(deltaSeconds);\n const record = this.manager.get(id);\n if (!record) {\n continue;\n }\n const docked = this.regions.regionOf(id) !== undefined;\n if (record.dockMode === DockMode.HandLocked && !record.dragging && !docked) {\n if (this.handPose && (this.handPose.hasHands?.() ?? true)) {\n hands ??= this.readHands();\n this.placeOnHand(id, state, hands);\n } else {\n // No hands here (a desktop, or no session yet): the menu follows\n // the body instead, and the gate does not apply.\n state.gateOpen = true;\n this.applyPresentation(id);\n this.applyFollow(state.handle.group, state.options, deltaSeconds, true);\n }\n continue;\n }\n if (record.dockMode === DockMode.BodyFollow && !record.dragging && !docked) {\n this.applyFollow(state.handle.group, state.options, deltaSeconds, true);\n }\n }\n for (const state of this.regionStates.values()) {\n if (state.follow) {\n this.applyFollow(\n state.handle.group,\n {\n followOffset: state.followOffset,\n followSpeed: 3,\n followTolerance: 0.2,\n },\n deltaSeconds,\n false,\n );\n this.layoutRegion(state.handle.id);\n }\n }\n }\n\n /** This frame's tracked hands from the source, absent ones left out. */\n private readHands(): HandPoses {\n const poses: HandPoses = {};\n for (const hand of ['left', 'right'] as const) {\n const pose = this.handPose?.getHandPose(hand);\n if (pose) {\n poses[hand] = pose;\n }\n }\n return poses;\n }\n\n private placeOnHand(id: string, state: WindowState, hands: HandPoses): void {\n const record = this.manager.get(id);\n if (!record) {\n return;\n }\n const placement = evaluateHandMenu(hands, this.headPose.getHeadPose().position, record.handMenu);\n state.gateOpen = placement.visible;\n if (placement.pose) {\n state.handle.group.position.set(...placement.pose.position);\n state.handle.group.quaternion.set(...placement.pose.quaternion);\n }\n this.applyPresentation(id);\n }\n\n private applyFollow(\n group: Group,\n options: FollowOptions,\n deltaSeconds: number,\n faceViewer: boolean,\n ): void {\n const pose = this.headPose.getHeadPose();\n const target = followTarget(pose, options.followOffset);\n const position = group.position;\n const current: Vec3Tuple = [position.x, position.y, position.z];\n const tolerance = options.followTolerance;\n if (distanceSquared(current, target) <= tolerance * tolerance) {\n return;\n }\n const next = approach(\n current,\n target,\n approachAlpha(options.followSpeed, deltaSeconds),\n );\n position.set(...next);\n if (faceViewer) {\n group.lookAt(pose.position[0], position.y, pose.position[2]);\n }\n }\n\n /** Re-place every docked window into its region's slot. */\n private layoutRegions(): void {\n for (const id of this.regionStates.keys()) {\n this.layoutRegion(id);\n }\n }\n\n private layoutRegion(regionId: string): void {\n const regionState = this.regionStates.get(regionId);\n const registered = this.regions.get(regionId);\n if (!regionState || !registered) {\n return;\n }\n const origin = regionState.handle.group.position;\n registered.members.forEach((windowId, index) => {\n const windowState = this.states.get(windowId);\n if (!windowState) {\n return;\n }\n const [dx, dy, dz] = slotOffset(registered.definition, index);\n windowState.handle.group.position.set(\n origin.x + dx,\n origin.y + dy,\n origin.z + dz,\n );\n windowState.handle.group.quaternion.copy(regionState.handle.group.quaternion);\n });\n }\n\n private wireChrome(\n options: CreateWindowOptions,\n handle: XrBlocksWindowHandle,\n ): void {\n const element = (id: string) => handle.document.getElementById(id);\n const id = handle.id;\n\n const title = element(WINDOW_CHROME_IDS.title);\n if (title && options.title) {\n title.setProperties({ text: options.title });\n }\n\n // Chrome presses must not bubble to the window root's focus handler:\n // a press on CLOSE would otherwise focus a window that is about to be\n // destroyed, and `focus()` on a removed window throws. (Same guard the\n // IWSDK adapter applies.)\n const swallowPress = (button: UixElement | undefined): void => {\n button?.addEventListener('pointerdown', (event) => {\n (event as { stopPropagation?: () => void } | undefined)?.stopPropagation?.();\n });\n };\n swallowPress(element(WINDOW_CHROME_IDS.pin));\n swallowPress(element(WINDOW_CHROME_IDS.dock));\n swallowPress(element(WINDOW_CHROME_IDS.minimize));\n swallowPress(element(WINDOW_CHROME_IDS.close));\n\n // Any press anywhere on the window brings it to the front. Guarded:\n // events can still arrive for a window that was just closed.\n element(WINDOW_CHROME_IDS.window)?.addEventListener('pointerdown', () => {\n if (this.manager.has(id)) {\n this.manager.focus(id);\n }\n });\n\n const state = this.states.get(id);\n if (state) {\n state.content = element(WINDOW_CHROME_IDS.content);\n state.pin = element(WINDOW_CHROME_IDS.pin);\n state.minimize = element(WINDOW_CHROME_IDS.minimize);\n state.buttons = {\n close: element(WINDOW_CHROME_IDS.close),\n minimize: element(WINDOW_CHROME_IDS.minimize),\n pin: element(WINDOW_CHROME_IDS.pin),\n dock: element(WINDOW_CHROME_IDS.dock),\n };\n }\n\n // Every button is wired once and gated on the record at click time, so\n // enabling a button later (manager.setChrome) needs no rewiring.\n const enabled = (key: keyof WindowChrome): boolean =>\n this.manager.get(id)?.chrome[key] === true;\n\n element(WINDOW_CHROME_IDS.close)?.addEventListener('click', () => {\n if (enabled('close')) {\n this.manager.close(id);\n }\n });\n element(WINDOW_CHROME_IDS.minimize)?.addEventListener('click', () => {\n if (enabled('minimize')) {\n this.manager.toggleMinimized(id);\n }\n });\n element(WINDOW_CHROME_IDS.pin)?.addEventListener('click', () => {\n if (enabled('pin')) {\n // Pinning a docked window pops it out of its region first.\n this.manager.undock(id);\n this.manager.togglePin(id);\n }\n });\n element(WINDOW_CHROME_IDS.dock)?.addEventListener('click', () => {\n if (enabled('dock')) {\n this.manager.returnHome(id);\n }\n });\n this.syncMinimizeLabel(id);\n this.syncPinLabel(id);\n }\n\n /** Show exactly the enabled buttons. */\n private applyChrome(record: Pick<WindowRecord, 'id' | 'chrome'>): void {\n const buttons = this.states.get(record.id)?.buttons;\n if (!buttons) {\n return;\n }\n for (const key of ['close', 'minimize', 'pin', 'dock'] as const) {\n buttons[key]?.setProperties({ display: record.chrome[key] ? 'flex' : 'none' });\n }\n }\n\n /** Drawn exactly when not hidden and (for a hand menu) the palm gate is open. */\n private applyPresentation(id: string): void {\n const state = this.states.get(id);\n const record = this.manager.get(id);\n if (state && record) {\n state.handle.group.visible = !record.hidden && state.gateOpen;\n }\n }\n\n private setContentCollapsed(id: string, collapsed: boolean): void {\n this.states\n .get(id)\n ?.content?.setProperties({ display: collapsed ? 'none' : 'flex' });\n }\n\n /** MIN when open, MAX when minimized - the label names the next action. */\n private syncMinimizeLabel(id: string): void {\n const record = this.manager.get(id);\n const minimize = this.states.get(id)?.minimize;\n if (record && minimize) {\n minimize.setProperties({ text: minimizeLabelFor(record) });\n }\n }\n\n private syncPinLabel(id: string): void {\n const record = this.manager.get(id);\n const pin = this.states.get(id)?.pin;\n if (record && pin) {\n pin.setProperties({ text: pinLabelFor(record) });\n }\n }\n}\n"]}
|
package/dist/panel-document.d.ts
CHANGED
|
@@ -11,8 +11,11 @@
|
|
|
11
11
|
import { Group, type Object3D } from 'three';
|
|
12
12
|
import { type Kit } from '@pmndrs/uikitml';
|
|
13
13
|
import type { PanelHandle, UixElement } from '@realitycollective/webxr-uiextensions';
|
|
14
|
-
/**
|
|
15
|
-
|
|
14
|
+
/**
|
|
15
|
+
* The slice of a uikit component this adapter relies on. Exported because
|
|
16
|
+
* `UixPanelDocument` exposes it as `rootComponent`.
|
|
17
|
+
*/
|
|
18
|
+
export interface UikitComponentLike extends Object3D {
|
|
16
19
|
update?(deltaMs: number): void;
|
|
17
20
|
size?: {
|
|
18
21
|
value: unknown;
|
|
@@ -34,4 +37,3 @@ export declare class UixPanelDocument extends Group implements PanelHandle {
|
|
|
34
37
|
dispose(): void;
|
|
35
38
|
private applyScale;
|
|
36
39
|
}
|
|
37
|
-
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"panel-document.js","sourceRoot":"","sources":["../src/panel-document.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EAAE,KAAK,EAAiB,MAAM,OAAO,CAAC;AAC7C,OAAO,EAAE,SAAS,EAAY,MAAM,iBAAiB,CAAC;AAEtD,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"panel-document.js","sourceRoot":"","sources":["../src/panel-document.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * UixPanelDocument - minimal spatial hosting for interpreted UIKitML on\n * plain three.js (the XR Blocks scene graph is plain three.js).\n *\n * Mirrors the behaviour of IWSDK's UIKitDocument where it matters to the\n * core: a `Group` wrapping the interpreted component tree, per-frame\n * `update`, scale-to-fit via {@link fitScale}, and `getElementById` backed\n * by the components' `userData.id` (where UIKitML places markup ids -\n * the same `userData` surface the core's `UixElement` contract reads).\n */\nimport { Group, type Object3D } from 'three';\nimport { interpret, type Kit } from '@pmndrs/uikitml';\nimport type { PanelHandle, UixElement } from '@realitycollective/webxr-uiextensions';\nimport { fitScale } from './scale-math.js';\n\n/**\n * The slice of a uikit component this adapter relies on. Exported because\n * `UixPanelDocument` exposes it as `rootComponent`.\n */\nexport interface UikitComponentLike extends Object3D {\n update?(deltaMs: number): void;\n size?: {\n value: unknown;\n subscribe?(listener: () => void): () => void;\n };\n dispose?(): void;\n}\n\nfunction naturalSize(\n component: UikitComponentLike,\n): [number | undefined, number | undefined] {\n const value = component.size?.value;\n if (Array.isArray(value) && value.length >= 2) {\n return [value[0] as number, value[1] as number];\n }\n return [undefined, undefined];\n}\n\nexport class UixPanelDocument extends Group implements PanelHandle {\n readonly rootComponent: UikitComponentLike;\n private targetWidth = 1;\n private targetHeight = 1;\n private unsubscribeSize: (() => void) | undefined;\n\n constructor(configJson: unknown, kit?: Kit) {\n super();\n const component = interpret(\n configJson as Parameters<typeof interpret>[0],\n kit,\n );\n if (!component) {\n throw new Error('UIKitML config produced no interpretable root element.');\n }\n this.rootComponent = component as unknown as UikitComponentLike;\n this.add(this.rootComponent);\n // Re-fit whenever layout measures the panel (size arrives async).\n this.unsubscribeSize = this.rootComponent.size?.subscribe?.(() =>\n this.applyScale(),\n );\n }\n\n get root(): UixElement {\n return this.rootComponent as unknown as UixElement;\n }\n\n getElementById(id: string): UixElement | undefined {\n let found: UixElement | undefined;\n this.rootComponent.traverse((object: Object3D) => {\n if (!found && object.userData?.['id'] === id) {\n found = object as unknown as UixElement;\n }\n });\n return found;\n }\n\n setTargetDimensions(width: number, height: number): void {\n this.targetWidth = width;\n this.targetHeight = height;\n this.applyScale();\n }\n\n /** Drive per-frame - uikit expects milliseconds. */\n update(deltaSeconds: number): void {\n this.rootComponent.update?.(deltaSeconds * 1000);\n }\n\n dispose(): void {\n this.unsubscribeSize?.();\n this.unsubscribeSize = undefined;\n this.removeFromParent();\n this.rootComponent.dispose?.();\n }\n\n private applyScale(): void {\n const [naturalWidth, naturalHeight] = naturalSize(this.rootComponent);\n const scale = fitScale(\n this.targetWidth,\n this.targetHeight,\n naturalWidth,\n naturalHeight,\n );\n if (scale !== undefined) {\n this.scale.setScalar(scale);\n }\n }\n}\n"]}
|
|
@@ -10,8 +10,11 @@
|
|
|
10
10
|
* which is what IWSDK itself builds on.)
|
|
11
11
|
*/
|
|
12
12
|
import type { Object3D } from 'three';
|
|
13
|
-
/**
|
|
14
|
-
|
|
13
|
+
/**
|
|
14
|
+
* The event surface uikit components expose (three.js EventDispatcher).
|
|
15
|
+
* Exported because `pickInteractive` returns it.
|
|
16
|
+
*/
|
|
17
|
+
export interface InteractiveLike {
|
|
15
18
|
dispatchEvent?(event: {
|
|
16
19
|
type: string;
|
|
17
20
|
[key: string]: unknown;
|
|
@@ -33,4 +36,3 @@ export declare function pickInteractive(hit: unknown): InteractiveLike | undefin
|
|
|
33
36
|
export declare function forwardClick(intersections: ReadonlyArray<{
|
|
34
37
|
object: Object3D;
|
|
35
38
|
}>): InteractiveLike | undefined;
|
|
36
|
-
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pointer-forward.js","sourceRoot":"","sources":["../src/pointer-forward.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"pointer-forward.js","sourceRoot":"","sources":["../src/pointer-forward.ts"],"names":[],"mappings":"AAuBA;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAAC,GAAY;IAC1C,IAAI,OAAO,GAAG,GAAkC,CAAC;IACjD,OAAO,OAAO,EAAE,CAAC;QACf,IACE,OAAO,OAAO,CAAC,aAAa,KAAK,UAAU;YAC3C,OAAO,CAAC,QAAQ;YAChB,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,KAAK,SAAS,EACzC,CAAC;YACD,OAAO,OAAO,CAAC;QACjB,CAAC;QACD,OAAO,GAAG,OAAO,CAAC,MAAqC,CAAC;IAC1D,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAC1B,aAAkD;IAElD,MAAM,KAAK,GAAG,aAAa,CAAC,CAAC,CAAC,CAAC;IAC/B,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,MAAM,MAAM,GAAG,eAAe,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAC7C,MAAM,EAAE,aAAa,EAAE,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;IAC3C,OAAO,MAAM,CAAC;AAChB,CAAC","sourcesContent":["/**\n * Minimal pointer forwarding - turns engine raycast hits into uikit events.\n *\n * XR Blocks (and any plain three.js app) raycasts with its own machinery;\n * uikit components are ordinary three.js Meshes, so they appear in those\n * intersections. This module picks the correct interactive element from a\n * hit list and dispatches DOM-ish events to it. v1 forwards clicks and\n * hover enter/leave - enough for window chrome and `data-uix` controls.\n * (Full pointer capture / poke semantics: use `@pmndrs/pointer-events`,\n * which is what IWSDK itself builds on.)\n */\nimport type { Object3D } from 'three';\n\n/**\n * The event surface uikit components expose (three.js EventDispatcher).\n * Exported because `pickInteractive` returns it.\n */\nexport interface InteractiveLike {\n dispatchEvent?(event: { type: string; [key: string]: unknown }): void;\n userData?: Record<string, unknown>;\n parent?: unknown;\n}\n\n/**\n * Walk up from a hit object to the nearest ancestor that can receive\n * events and belongs to a uikit tree (identified by the `dataUid` UIKitML\n * stamps into userData). Pure - testable with stub objects.\n */\nexport function pickInteractive(hit: unknown): InteractiveLike | undefined {\n let current = hit as InteractiveLike | undefined;\n while (current) {\n if (\n typeof current.dispatchEvent === 'function' &&\n current.userData &&\n current.userData['dataUid'] !== undefined\n ) {\n return current;\n }\n current = current.parent as InteractiveLike | undefined;\n }\n return undefined;\n}\n\n/**\n * Dispatch a click to the interactive element (if any) under the first hit\n * of an intersection list (`Raycaster.intersectObject(panel, true)` order).\n * Returns the element that received the event, for host-side bookkeeping.\n */\nexport function forwardClick(\n intersections: ReadonlyArray<{ object: Object3D }>,\n): InteractiveLike | undefined {\n const first = intersections[0];\n if (!first) {\n return undefined;\n }\n const target = pickInteractive(first.object);\n target?.dispatchEvent?.({ type: 'click' });\n return target;\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@realitycollective/xrblocks-uiextensions",
|
|
3
|
-
"version": "0.1.0",
|
|
3
|
+
"version": "0.1.1-preview.0",
|
|
4
4
|
"description": "EXPERIMENTAL Google XR Blocks / plain three.js adapter for the Reality Collective UI Extensions - hosts the engine-free @realitycollective/webxr-uiextensions windowing core (UIKitML panels, window chrome, follow mode) in any three.js WebXR scene, including XR Blocks Scripts.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"realitycollective",
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
"dependencies": {
|
|
38
38
|
"@pmndrs/uikit": "^1.0.76",
|
|
39
39
|
"@pmndrs/uikitml": "^0.1.12",
|
|
40
|
-
"@realitycollective/webxr-uiextensions": "^0.1.0"
|
|
40
|
+
"@realitycollective/webxr-uiextensions": "^0.1.1-preview.0"
|
|
41
41
|
},
|
|
42
42
|
"peerDependencies": {
|
|
43
43
|
"three": ">=0.170.0"
|