@realitycollective/webxr-uiextensions 0.1.0-preview.4 → 0.1.0-preview.6
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 +12 -1
- package/dist/adapter.d.ts +6 -0
- package/dist/adapter.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -8,6 +8,7 @@ The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and
|
|
|
8
8
|
|
|
9
9
|
### Added
|
|
10
10
|
|
|
11
|
+
- `verify:pack` now lints the shape of what ships: publint over every package directory, with warnings counted as errors, and attw (Are The Types Wrong) over every packed tarball, resolving the published types under node10, node16 and bundler resolution. `cjs-resolves-to-esm` is ignored by design, because every package is ESM-only and a require() caller is expected to use a dynamic import. Both run offline on the tarballs the script already builds; `publint` and `@arethetypeswrong/cli` are dev dependencies. The script stays identical across the Reality Collective repositories.
|
|
11
12
|
- `@realitycollective/webxr-uiextensions` - engine-free core: window manager, dock state and regions, drag maths, hold-to-drag, control models (stepper/toggle/expandable/log), the `SceneDescriptor` scene format, window chrome conventions and the platform-adapter contract.
|
|
12
13
|
- `@realitycollective/iwsdk-uiextensions` - Meta IWSDK adapter binding the core onto IWSDK's ECS, UIKitML and interaction systems, with shipped examples.
|
|
13
14
|
- `@realitycollective/xrblocks-uiextensions` - EXPERIMENTAL Google XR Blocks / plain three.js adapter: panel document, window host, follow and scale maths, desktop controls and locomotion, pointer forwarding.
|
|
@@ -30,11 +31,21 @@ The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and
|
|
|
30
31
|
- `compilePanelSource` in `@realitycollective/uix-devtools` serves the **source** on its `blob:` URL rather than compiled JSON, matching what 0.5 fetches. `CompiledPanel.json` is now `CompiledPanel.source`, and the `resolveFile` option is gone because the 0.5 parser has no `<link ref>` stylesheet resolution; put shared rules in a `<style>` block, of which several are allowed and merge. Validation now runs on `@drawcall/uikitml`, pinned to the version `@iwsdk/core` depends on, so a source that passes here is one `PanelUISystem` will accept and no second parser enters the tree.
|
|
31
32
|
- Example and demo markup uses `rgba()` or eight-digit hex rather than `background-opacity`, which the 0.5 parser removed. Both parsers accept the replacement, so one stylesheet serves every adapter.
|
|
32
33
|
- The IWSDK component kit is selected by name, `spatialUI: { kit: 'horizon' }`, rather than by passing an imported kit module. The kits now live inside the parser.
|
|
33
|
-
- `@types/three` is pinned to `0.184.0` across the workspace. IWSDK 0.5.3 and xrblocks resolved different copies, and two copies of the three typings make structurally identical `Object3D` types mutually unassignable, which surfaces as spurious errors far from their cause.
|
|
34
|
+
- `@types/three` is pinned to `0.184.0` across the workspace. IWSDK 0.5.3 and xrblocks resolved different copies, and two copies of the three typings make structurally identical `Object3D` types mutually unassignable, which surfaces as spurious errors far from their cause. One copy per workspace is now the rule in every Reality Collective repository that hosts IWSDK. This workspace stays on 0.184.0 rather than the 0.181.0 that matches its super-three: on 0.181.0 the `Object3D` augmentation that `@pmndrs/pointer-events` declares does not merge with three's `Object3D`, and TypeScript reports two incompatible `Object3D` types across the showcase and the XR Blocks adapter. 0.184.0 is the version this workspace is verified against.
|
|
34
35
|
- `onPanelReady` on the IWSDK host announces bare panels as well as managed windows. A `PanelUI` entity with no `UIWindow`, or with an empty `windowId`, used to be dropped silently; it is now announced with `kind: 'panel'` and its config path as the id. Listeners that only want managed windows should check `kind`.
|
|
35
36
|
- `id` is optional in the XR Blocks host's `CreateWindowOptions`; a window created without one is named `uix-window-<n>`, as on IWSDK. The options also accept `movable` for parity, but this host has no title-bar drag of its own yet, so the flag is recorded and not acted on.
|
|
36
37
|
- The XR Blocks window handle gains `panel` - the document, which already implements `PanelHandle` - and `onReady`, which fires synchronously because uikitml interprets the markup during `createWindow`. The interface is now named `XrBlocksWindowHandle`, with `WindowHandle` kept as an alias, because the core exports a `WindowHandle` of its own.
|
|
37
38
|
- Coverage gates `packages/iwsdk-uiextensions/src/factory.ts` and `src/scene-host.ts` at the same 100% as the core. `new World()` from `@iwsdk/core` constructs headlessly - no renderer, no WebGL, no XR session - so the factories, the scene host and its ECS query all run for real in a node test. The per-frame ECS systems still need a live world and stay outside the gate.
|
|
38
39
|
- `@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.
|
|
40
|
+
- `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.
|
|
39
41
|
|
|
40
42
|
[0.1.0]: https://github.com/realitycollective/WebXR-UIExtensions/commits/main
|
|
43
|
+
|
|
44
|
+
### Fixed
|
|
45
|
+
|
|
46
|
+
- `createSceneHost(world)` returns the same host on every call for a world, where it previously built a new one each time. A second host registered a second readiness ECS system on the same world and repeated the panel upgrade pass, so two modules each asking for the host quietly doubled that work. It now memoises per world exactly as the window manager registry does, which also means separate modules can ask for the host without coordinating or passing it around.
|
|
47
|
+
- Documented in `@realitycollective/iwsdk-uiextensions` that `onPanelReady` announces windows spawned by `createUIWindow`, not only by `host.createWindow`, so code holding factory entities has a readiness signal without changing how it spawns them. The readiness section now also warns against polling `getPanelHandle` on a timer, because a poll that gives up early leaves a window that draws and responds to nothing with no error, and records that a factory window created without an `id` is announced as `kind: 'panel'` with its config path, which a listener filtering on `kind === 'window'` will never see.
|
|
48
|
+
- `@realitycollective/uix-devtools/cli` resolved to no types under TypeScript's legacy `node10` module resolution, which ignores the `exports` map; `typesVersions` now maps the subpath to `dist/cli/lib.d.ts`. Found by the attw step `verify:pack` gained in this release.
|
|
49
|
+
- `@realitycollective/iwsdk-uiextensions` imported three.js's `Vector3`, `Quaternion`, `Euler` and `Object3D` through `@iwsdk/core`, which only provides them by `export * from 'three'`. That resolves in node and in every demo, and fails a consumer whose Vite config excludes `three` from dependency optimization, which any app that transforms three's source does: esbuild cannot enumerate a star re-export it is not bundling, and the dev server stops with `No matching export in "@iwsdk/core" for import "Vector3"`, a message that names neither the package nor the cause. The four systems modules now import those classes from `three`, declared as a peer dependency (`>=0.170.0`, the range the XR Blocks adapter carries), which every IWSDK application already has. Reported by the Anatomy Atlas XR client.
|
|
50
|
+
- `@realitycollective/xrblocks-uiextensions` imported `reversePainterSortStable` from `@pmndrs/uikit` without declaring it; it resolved only because another package hoisted it. The package now lists it as a dependency. Found by the new import-surface gate.
|
|
51
|
+
- Two gates, shared with every Reality Collective repository. `packages/webxr-uiextensions/test/import-surface.test.ts` runs `scripts/import-surface.mjs` over every published package and fails an import of a name that a dependency only re-exports from another package, and any bare import of a package the manifest does not declare. `packages/iwsdk-uiextensions/test/prebundle.test.ts` runs the dependency optimizer of every bundler `scripts/release.config.json` names (`scripts/prebundle-check.mjs`) over the adapter next to `@iwsdk/core`, once with defaults and once with every package `@iwsdk/core` re-exports wholesale excluded, so the consumer path is exercised on every `npm test`. It runs on **Vite 7 and Vite 8**, because this fault belongs to a bundler rather than to bundling: Vite 7 optimizes with esbuild, which requires every named import to be statically enumerable and so rejects a name behind an external `export *`, while Vite 8 optimizes with rolldown, which resolves the same import lazily through a namespace object and accepts it. Testing only one of them would say nothing about consumers on the other. The versions under test are ordinary devDependencies installed under npm aliases, `vite-7` and `vite-8`, the same mechanism the workspace already uses for `three`; add an entry to `prebundle.bundlers` to support another. Each run also feeds the optimizer a **deliberately broken copy** of the adapter, carrying one extra module that imports a name the host only re-exports wholesale, and asserts the bundler's verdict matches that bundler's `detectsStarHops` flag. The probed name is discovered from the host's own surface rather than hard-coded, so it stays valid as that surface changes. This is what stops the check becoming decoration: on a permissive bundler a gate that can only pass reports safety it never verified, and the suite now fails if a bundler's strictness moves in either direction, or if no supported bundler can detect the fault at all. Transpiling uses the TypeScript compiler the repository already builds with, so no bundler is a hidden requirement of the harness itself. Both were red before this fix.
|
package/dist/adapter.d.ts
CHANGED
|
@@ -179,6 +179,12 @@ export interface WindowOptionsBase {
|
|
|
179
179
|
* `origin` (ray origin or touch point) and a normalised `direction`. It is
|
|
180
180
|
* the Input package's `RayTuple`, which is what lets a provider written
|
|
181
181
|
* against `@realitycollective/webxr-input` feed this contract unchanged.
|
|
182
|
+
*
|
|
183
|
+
* Once delivered, a sample belongs to the listener: the source never writes
|
|
184
|
+
* to it again, so `hold-to-drag` and `drag-math` may keep a press-time
|
|
185
|
+
* sample without copying it. This is the rule `@realitycollective/webxr-input`
|
|
186
|
+
* states on `InputSourceSnapshot`, so a provider feeding both contracts has
|
|
187
|
+
* one promise to keep.
|
|
182
188
|
*/
|
|
183
189
|
export type PointerSample = RayTuple;
|
|
184
190
|
/**
|
package/dist/adapter.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"adapter.js","sourceRoot":"","sources":["../src/adapter.ts"],"names":[],"mappings":"","sourcesContent":["/**\n * Platform-adapter contract.\n *\n * The core package owns every UX decision - window lifecycle, dock state,\n * region slot math, drag math, control models - and knows nothing about any\n * engine. An engine adapter supplies the three capabilities the core cannot\n * provide for itself, and drives the core from its own frame loop:\n *\n * - {@link PanelHost}: turn compiled UIKitML JSON into a live spatial panel\n * - {@link PointerInputSource}: deliver ray/pointer press-move-release\n * - {@link HeadPoseSource}: the viewer pose, for follow mode & body-lock\n *\n * On top of those, {@link WindowHost} adds the portable window surface:\n * {@link WindowHost.onPanelReady} for readiness, {@link PanelReadyEvent.kind}\n * to tell a managed window from a bare panel, and\n * {@link WindowHost.supportsStandalonePanels} to say whether `createPanel` is\n * usable at all. Each adapter's own `createWindow` returns a\n * {@link WindowHandle} and takes options extending {@link WindowOptionsBase},\n * so window code reads the same on every engine even though the `config`\n * payload does not.\n *\n * Known adapters:\n * - `@realitycollective/iwsdk-uiextensions` - Meta IWSDK (ECS systems bind\n * these capabilities to `@iwsdk/core` components)\n * - `@realitycollective/xrblocks-uiextensions` - Google XR Blocks / plain\n * three.js (experimental)\n *\n * The interfaces use plain tuples/records only - no engine, no three.js. The\n * geometry vocabulary itself comes from `@realitycollective/webxr-input`, the\n * engine-free contracts package both extension families share, so a pose or a\n * ray means the same thing to Interactions and to UI Extensions and one input\n * stack drives both. The names below are re-exported, so importing them from\n * this package keeps working.\n */\nimport type { RayTuple, Vec3Tuple } from '@realitycollective/webxr-input';\nimport type { DockModeValue } from './core/dock-state.js';\nimport type { UixElement } from './controls/element.js';\n\n/**\n * The shared geometry vocabulary, re-exported so this package stays the one\n * import an adapter needs:\n *\n * - `Vec3Tuple` - position as [x, y, z] in meters, world space unless stated\n * - `QuatTuple` - orientation quaternion as [x, y, z, w]\n * - `HeadPose` - a viewer (head) pose sample\n * - `HeadPoseSource` - supplies that pose each frame, camera on desktop and\n * HMD in XR\n */\nexport type {\n HeadPose,\n HeadPoseSource,\n QuatTuple,\n Vec3Tuple,\n} from '@realitycollective/webxr-input';\n\n/**\n * A live spatial panel created from compiled UIKitML JSON.\n * The `root` is traversable with the core's `walk`/`findRole` helpers and\n * the `data-uix` control upgraders - identical markup works on every\n * adapter.\n */\nexport interface PanelHandle {\n /** Root element of the interpreted panel (UixElement-conformant). */\n readonly root: UixElement;\n /** Look up an element by its markup `id`. */\n getElementById(id: string): UixElement | undefined;\n /** Constrain the panel to fit within width × height meters. */\n setTargetDimensions(width: number, height: number): void;\n /** Release panel resources. */\n dispose(): void;\n}\n\n/** Creates spatial panels - the engine-specific half of UIKitML rendering. */\nexport interface PanelHost {\n /**\n * Create a panel from compiled UIKitML JSON (the `{ element, classes }`\n * shape produced by the build plugin or by\n * `@realitycollective/uix-devtools`' `compilePanelSource`).\n */\n createPanel(configJson: unknown): PanelHandle;\n}\n\n/**\n * A window whose panel has finished loading and is ready to be wired.\n * Delivered by {@link WindowHost.onPanelReady}.\n */\nexport interface PanelReadyEvent {\n /** The window's id, as given to the scene descriptor / create call. */\n id: string;\n /** The live panel - traverse it, or look elements up by markup id. */\n panel: PanelHandle;\n /**\n * What became ready.\n *\n * - `window` - created through the adapter's window factory and managed by\n * the window manager, so `id` is the id the caller asked for.\n * - `panel` - a bare panel the adapter noticed. `id` is then the adapter's\n * best stable identifier for it, which on IWSDK is the panel's config\n * path.\n *\n * Left optional so existing listeners keep compiling; adapters set it.\n */\n kind?: 'window' | 'panel';\n}\n\n/**\n * The engine-agnostic surface an app needs to build a UI: spawn windows and\n * regions from portable data, observe when panels become wireable, and reach\n * the shared `WindowManager`.\n *\n * Panels load asynchronously on every adapter (IWSDK fetches the config;\n * uikit lays out over following frames), so app code must never assume a\n * panel exists immediately after creating its window. {@link onPanelReady}\n * is the portable answer - it replaces engine-specific discovery (ECS\n * queries on IWSDK, polling anywhere else) and fires for panels that became\n * ready before the listener was registered, so wiring order never matters.\n */\nexport interface WindowHost extends PanelHost {\n /**\n * Whether {@link PanelHost.createPanel} works on this host. When `false`\n * the method is not available and throws; spawn a window instead, so the\n * engine owns the panel lifecycle. IWSDK is `false`, three.js/XR Blocks is\n * `true`.\n */\n readonly supportsStandalonePanels: boolean;\n /**\n * Subscribe to panel readiness. Late subscribers are replayed the windows\n * that are already live. Returns an unsubscribe function.\n */\n onPanelReady(listener: (event: PanelReadyEvent) => void): () => void;\n}\n\n/**\n * A window an adapter spawned, before its panel necessarily exists.\n *\n * `createWindow` itself stays adapter-specific because the `config` payload\n * differs per engine, but what it hands back is the same everywhere: an id, a\n * panel once there is one, and a one-shot readiness callback.\n */\nexport interface WindowHandle {\n /** The window's id - the one passed in, or one the adapter generated. */\n readonly id: string;\n /**\n * The live panel, or `undefined` until the adapter has attached the\n * document. IWSDK loads and parses the markup over later frames; the\n * three.js host interprets it during `createWindow`, so there it is set\n * straight away.\n */\n readonly panel: PanelHandle | undefined;\n /**\n * Run `listener` once, when the panel is attached. Fires immediately if it\n * already is, so wiring order never matters. Returns an unsubscribe\n * function for the case where the caller gives up first.\n */\n onReady(listener: (panel: PanelHandle) => void): () => void;\n}\n\n/**\n * The window options every adapter understands.\n *\n * An adapter's own `CreateWindowOptions` extends this and adds only what its\n * engine needs - chiefly `config`, whose type differs (IWSDK takes a source\n * path, the three.js host takes parsed markup). Keeping the rest here is what\n * lets one `SceneWindow` map onto every adapter without a translation table.\n */\nexport interface WindowOptionsBase {\n /** Stable window id. Adapters generate one when it is absent. */\n id?: string;\n /** Title text written into the window chrome's title element. */\n title?: string;\n dockMode?: DockModeValue;\n /** World position for world-locked windows. */\n position?: Vec3Tuple;\n /** Fit the panel into this box in meters, preserving aspect ratio. */\n maxWidth?: number;\n maxHeight?: number;\n /** Whether the title bar drags the window. */\n movable?: boolean;\n closable?: boolean;\n minimizable?: boolean;\n pinnable?: boolean;\n /** Head-relative offset used in body-follow mode (meters). */\n followOffset?: Vec3Tuple;\n followSpeed?: number;\n followTolerance?: number;\n /** Dock straight into this region on spawn. */\n region?: string;\n}\n\n/**\n * One pointer/ray interaction stream, engine-normalised: a world-space\n * `origin` (ray origin or touch point) and a normalised `direction`. It is\n * the Input package's `RayTuple`, which is what lets a provider written\n * against `@realitycollective/webxr-input` feed this contract unchanged.\n */\nexport type PointerSample = RayTuple;\n\n/**\n * Delivers press-move-release for one interaction source (a controller ray,\n * a hand pinch, a mouse). The core's `hold-to-drag` and `drag-math` consume\n * these; the adapter decides what constitutes press/release.\n */\nexport interface PointerInputSource {\n onPress(listener: (sample: PointerSample) => void): () => void;\n onMove(listener: (sample: PointerSample) => void): () => void;\n onRelease(listener: (sample: PointerSample) => void): () => void;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"adapter.js","sourceRoot":"","sources":["../src/adapter.ts"],"names":[],"mappings":"","sourcesContent":["/**\n * Platform-adapter contract.\n *\n * The core package owns every UX decision - window lifecycle, dock state,\n * region slot math, drag math, control models - and knows nothing about any\n * engine. An engine adapter supplies the three capabilities the core cannot\n * provide for itself, and drives the core from its own frame loop:\n *\n * - {@link PanelHost}: turn compiled UIKitML JSON into a live spatial panel\n * - {@link PointerInputSource}: deliver ray/pointer press-move-release\n * - {@link HeadPoseSource}: the viewer pose, for follow mode & body-lock\n *\n * On top of those, {@link WindowHost} adds the portable window surface:\n * {@link WindowHost.onPanelReady} for readiness, {@link PanelReadyEvent.kind}\n * to tell a managed window from a bare panel, and\n * {@link WindowHost.supportsStandalonePanels} to say whether `createPanel` is\n * usable at all. Each adapter's own `createWindow` returns a\n * {@link WindowHandle} and takes options extending {@link WindowOptionsBase},\n * so window code reads the same on every engine even though the `config`\n * payload does not.\n *\n * Known adapters:\n * - `@realitycollective/iwsdk-uiextensions` - Meta IWSDK (ECS systems bind\n * these capabilities to `@iwsdk/core` components)\n * - `@realitycollective/xrblocks-uiextensions` - Google XR Blocks / plain\n * three.js (experimental)\n *\n * The interfaces use plain tuples/records only - no engine, no three.js. The\n * geometry vocabulary itself comes from `@realitycollective/webxr-input`, the\n * engine-free contracts package both extension families share, so a pose or a\n * ray means the same thing to Interactions and to UI Extensions and one input\n * stack drives both. The names below are re-exported, so importing them from\n * this package keeps working.\n */\nimport type { RayTuple, Vec3Tuple } from '@realitycollective/webxr-input';\nimport type { DockModeValue } from './core/dock-state.js';\nimport type { UixElement } from './controls/element.js';\n\n/**\n * The shared geometry vocabulary, re-exported so this package stays the one\n * import an adapter needs:\n *\n * - `Vec3Tuple` - position as [x, y, z] in meters, world space unless stated\n * - `QuatTuple` - orientation quaternion as [x, y, z, w]\n * - `HeadPose` - a viewer (head) pose sample\n * - `HeadPoseSource` - supplies that pose each frame, camera on desktop and\n * HMD in XR\n */\nexport type {\n HeadPose,\n HeadPoseSource,\n QuatTuple,\n Vec3Tuple,\n} from '@realitycollective/webxr-input';\n\n/**\n * A live spatial panel created from compiled UIKitML JSON.\n * The `root` is traversable with the core's `walk`/`findRole` helpers and\n * the `data-uix` control upgraders - identical markup works on every\n * adapter.\n */\nexport interface PanelHandle {\n /** Root element of the interpreted panel (UixElement-conformant). */\n readonly root: UixElement;\n /** Look up an element by its markup `id`. */\n getElementById(id: string): UixElement | undefined;\n /** Constrain the panel to fit within width × height meters. */\n setTargetDimensions(width: number, height: number): void;\n /** Release panel resources. */\n dispose(): void;\n}\n\n/** Creates spatial panels - the engine-specific half of UIKitML rendering. */\nexport interface PanelHost {\n /**\n * Create a panel from compiled UIKitML JSON (the `{ element, classes }`\n * shape produced by the build plugin or by\n * `@realitycollective/uix-devtools`' `compilePanelSource`).\n */\n createPanel(configJson: unknown): PanelHandle;\n}\n\n/**\n * A window whose panel has finished loading and is ready to be wired.\n * Delivered by {@link WindowHost.onPanelReady}.\n */\nexport interface PanelReadyEvent {\n /** The window's id, as given to the scene descriptor / create call. */\n id: string;\n /** The live panel - traverse it, or look elements up by markup id. */\n panel: PanelHandle;\n /**\n * What became ready.\n *\n * - `window` - created through the adapter's window factory and managed by\n * the window manager, so `id` is the id the caller asked for.\n * - `panel` - a bare panel the adapter noticed. `id` is then the adapter's\n * best stable identifier for it, which on IWSDK is the panel's config\n * path.\n *\n * Left optional so existing listeners keep compiling; adapters set it.\n */\n kind?: 'window' | 'panel';\n}\n\n/**\n * The engine-agnostic surface an app needs to build a UI: spawn windows and\n * regions from portable data, observe when panels become wireable, and reach\n * the shared `WindowManager`.\n *\n * Panels load asynchronously on every adapter (IWSDK fetches the config;\n * uikit lays out over following frames), so app code must never assume a\n * panel exists immediately after creating its window. {@link onPanelReady}\n * is the portable answer - it replaces engine-specific discovery (ECS\n * queries on IWSDK, polling anywhere else) and fires for panels that became\n * ready before the listener was registered, so wiring order never matters.\n */\nexport interface WindowHost extends PanelHost {\n /**\n * Whether {@link PanelHost.createPanel} works on this host. When `false`\n * the method is not available and throws; spawn a window instead, so the\n * engine owns the panel lifecycle. IWSDK is `false`, three.js/XR Blocks is\n * `true`.\n */\n readonly supportsStandalonePanels: boolean;\n /**\n * Subscribe to panel readiness. Late subscribers are replayed the windows\n * that are already live. Returns an unsubscribe function.\n */\n onPanelReady(listener: (event: PanelReadyEvent) => void): () => void;\n}\n\n/**\n * A window an adapter spawned, before its panel necessarily exists.\n *\n * `createWindow` itself stays adapter-specific because the `config` payload\n * differs per engine, but what it hands back is the same everywhere: an id, a\n * panel once there is one, and a one-shot readiness callback.\n */\nexport interface WindowHandle {\n /** The window's id - the one passed in, or one the adapter generated. */\n readonly id: string;\n /**\n * The live panel, or `undefined` until the adapter has attached the\n * document. IWSDK loads and parses the markup over later frames; the\n * three.js host interprets it during `createWindow`, so there it is set\n * straight away.\n */\n readonly panel: PanelHandle | undefined;\n /**\n * Run `listener` once, when the panel is attached. Fires immediately if it\n * already is, so wiring order never matters. Returns an unsubscribe\n * function for the case where the caller gives up first.\n */\n onReady(listener: (panel: PanelHandle) => void): () => void;\n}\n\n/**\n * The window options every adapter understands.\n *\n * An adapter's own `CreateWindowOptions` extends this and adds only what its\n * engine needs - chiefly `config`, whose type differs (IWSDK takes a source\n * path, the three.js host takes parsed markup). Keeping the rest here is what\n * lets one `SceneWindow` map onto every adapter without a translation table.\n */\nexport interface WindowOptionsBase {\n /** Stable window id. Adapters generate one when it is absent. */\n id?: string;\n /** Title text written into the window chrome's title element. */\n title?: string;\n dockMode?: DockModeValue;\n /** World position for world-locked windows. */\n position?: Vec3Tuple;\n /** Fit the panel into this box in meters, preserving aspect ratio. */\n maxWidth?: number;\n maxHeight?: number;\n /** Whether the title bar drags the window. */\n movable?: boolean;\n closable?: boolean;\n minimizable?: boolean;\n pinnable?: boolean;\n /** Head-relative offset used in body-follow mode (meters). */\n followOffset?: Vec3Tuple;\n followSpeed?: number;\n followTolerance?: number;\n /** Dock straight into this region on spawn. */\n region?: string;\n}\n\n/**\n * One pointer/ray interaction stream, engine-normalised: a world-space\n * `origin` (ray origin or touch point) and a normalised `direction`. It is\n * the Input package's `RayTuple`, which is what lets a provider written\n * against `@realitycollective/webxr-input` feed this contract unchanged.\n *\n * Once delivered, a sample belongs to the listener: the source never writes\n * to it again, so `hold-to-drag` and `drag-math` may keep a press-time\n * sample without copying it. This is the rule `@realitycollective/webxr-input`\n * states on `InputSourceSnapshot`, so a provider feeding both contracts has\n * one promise to keep.\n */\nexport type PointerSample = RayTuple;\n\n/**\n * Delivers press-move-release for one interaction source (a controller ray,\n * a hand pinch, a mouse). The core's `hold-to-drag` and `drag-math` consume\n * these; the adapter decides what constitutes press/release.\n */\nexport interface PointerInputSource {\n onPress(listener: (sample: PointerSample) => void): () => void;\n onMove(listener: (sample: PointerSample) => void): () => void;\n onRelease(listener: (sample: PointerSample) => void): () => void;\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@realitycollective/webxr-uiextensions",
|
|
3
|
-
"version": "0.1.0-preview.
|
|
3
|
+
"version": "0.1.0-preview.6",
|
|
4
4
|
"description": "Engine-free core of the Reality Collective UI Extensions: windowing, docking, layout regions and control models for WebXR spatial UI, driven through platform-adapter interfaces. Pair with an engine adapter - @realitycollective/iwsdk-uiextensions (Meta IWSDK) or @realitycollective/xrblocks-uiextensions (Google XR Blocks).",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"realitycollective",
|