@realitycollective/iwsdk-uiextensions 0.1.0-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.
Files changed (46) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/Examples/README.md +13 -0
  3. package/Examples/basic-window/main.ts +31 -0
  4. package/Examples/basic-window/window.uikitml +59 -0
  5. package/Examples/controls/controls.uikitml +50 -0
  6. package/Examples/controls/main.ts +44 -0
  7. package/Examples/dock-regions/main.ts +55 -0
  8. package/LICENSE +21 -0
  9. package/README.md +117 -0
  10. package/dist/components.d.ts +189 -0
  11. package/dist/components.js +97 -0
  12. package/dist/components.js.map +1 -0
  13. package/dist/factory.d.ts +55 -0
  14. package/dist/factory.js +63 -0
  15. package/dist/factory.js.map +1 -0
  16. package/dist/index.d.ts +24 -0
  17. package/dist/index.js +27 -0
  18. package/dist/index.js.map +1 -0
  19. package/dist/manager-registry.d.ts +8 -0
  20. package/dist/manager-registry.js +11 -0
  21. package/dist/manager-registry.js.map +1 -0
  22. package/dist/region-registry-store.d.ts +7 -0
  23. package/dist/region-registry-store.js +11 -0
  24. package/dist/region-registry-store.js.map +1 -0
  25. package/dist/register.d.ts +19 -0
  26. package/dist/register.js +20 -0
  27. package/dist/register.js.map +1 -0
  28. package/dist/scene-host.d.ts +23 -0
  29. package/dist/scene-host.js +145 -0
  30. package/dist/scene-host.js.map +1 -0
  31. package/dist/systems/controls-system.d.ts +24 -0
  32. package/dist/systems/controls-system.js +24 -0
  33. package/dist/systems/controls-system.js.map +1 -0
  34. package/dist/systems/dock-region-system.d.ts +230 -0
  35. package/dist/systems/dock-region-system.js +102 -0
  36. package/dist/systems/dock-region-system.js.map +1 -0
  37. package/dist/systems/dock-system.d.ts +205 -0
  38. package/dist/systems/dock-system.js +135 -0
  39. package/dist/systems/dock-system.js.map +1 -0
  40. package/dist/systems/drag-system.d.ts +280 -0
  41. package/dist/systems/drag-system.js +167 -0
  42. package/dist/systems/drag-system.js.map +1 -0
  43. package/dist/systems/window-system.d.ts +455 -0
  44. package/dist/systems/window-system.js +244 -0
  45. package/dist/systems/window-system.js.map +1 -0
  46. package/package.json +65 -0
@@ -0,0 +1,97 @@
1
+ /**
2
+ * ECS components for UI Extensions.
3
+ *
4
+ * These compose with the IWSDK's own components - a window entity typically
5
+ * carries `PanelUI` (the IWSDK loads/renders the panel), `UIWindow` (ours),
6
+ * and the IWSDK interaction tags (`RayInteractable`, `PokeInteractable`).
7
+ * The systems in this package add/remove the IWSDK `Follower` / `ScreenSpace`
8
+ * components to realise dock modes rather than re-implementing them.
9
+ */
10
+ import { Types, createComponent } from '@iwsdk/core';
11
+ import { DockMode } from '@realitycollective/webxr-uiextensions';
12
+ /** Region flow options mirrored as an enum object for the component schema. */
13
+ export const RegionFlowType = {
14
+ Row: 'row',
15
+ Column: 'column',
16
+ Grid: 'grid',
17
+ };
18
+ /**
19
+ * Marks a panel entity as a managed window with chrome, focus, docking and
20
+ * drag behaviour. Pair with `PanelUI` whose markup contains the window chrome
21
+ * elements (see `WINDOW_CHROME_IDS` / the Examples folder).
22
+ */
23
+ export const UIWindow = createComponent('UIWindow', {
24
+ /** Stable id; auto-generated when empty. */
25
+ windowId: { type: Types.String, default: '' },
26
+ /** Title text written into the `uix-title` element. */
27
+ title: { type: Types.String, default: '' },
28
+ /** Current dock state. */
29
+ dockMode: { type: Types.Enum, enum: DockMode, default: DockMode.WorldLocked },
30
+ /** Whether the title bar drags the window. */
31
+ movable: { type: Types.Boolean, default: true },
32
+ /** Show/enable the close affordance. */
33
+ closable: { type: Types.Boolean, default: true },
34
+ /** Show/enable the minimize affordance. */
35
+ minimizable: { type: Types.Boolean, default: true },
36
+ /** Show/enable the pin (body-follow ⇄ world-locked) affordance. */
37
+ pinnable: { type: Types.Boolean, default: true },
38
+ /** Keep the window yawed toward the viewer while it is being dragged. */
39
+ billboardWhileDragging: { type: Types.Boolean, default: true },
40
+ /**
41
+ * Seconds a title-bar press must be held before it becomes a drag.
42
+ * Shorter presses stay clicks, so title-bar buttons don't fight the drag.
43
+ */
44
+ dragDelay: { type: Types.Float32, default: 0.3 },
45
+ /** Head-relative offset used in `body-follow` mode (meters). */
46
+ followOffset: { type: Types.Vec3, default: [0, -0.15, -1.2] },
47
+ /** `Follower` lerp speed for body-follow. */
48
+ followSpeed: { type: Types.Float32, default: 3 },
49
+ /** `Follower` positional deadzone for body-follow (meters). */
50
+ followTolerance: { type: Types.Float32, default: 0.35 },
51
+ /** Meters the focused window is nudged toward the viewer per focus depth. */
52
+ focusBias: { type: Types.Float32, default: 0.02 },
53
+ /**
54
+ * World size box in meters, applied via `UIKitDocument.setTargetDimensions`
55
+ * once the document loads. IWSDK 0.5 removed `PanelUI.maxWidth/maxHeight`;
56
+ * this is the supported replacement. `0` leaves the document at its
57
+ * intrinsic markup size, scaled only by the entity transform.
58
+ */
59
+ targetWidth: { type: Types.Float32, default: 0 },
60
+ targetHeight: { type: Types.Float32, default: 0 },
61
+ }, 'UI Extensions managed window (chrome, focus, docking, drag)');
62
+ /**
63
+ * Internal bookkeeping the systems keep on window entities - which dock mode
64
+ * has actually been applied to engine components, and whether chrome wiring
65
+ * has run for the current PanelDocument.
66
+ */
67
+ export const UIWindowState = createComponent('UIWindowState', {
68
+ appliedDockMode: { type: Types.String, default: '' },
69
+ chromeWired: { type: Types.Boolean, default: false },
70
+ /** "Home" snapshot captured on adoption - the DOCK button returns here. */
71
+ homeDockMode: { type: Types.String, default: '' },
72
+ homeRegion: { type: Types.String, default: '' },
73
+ homePosition: { type: Types.Vec3, default: [0, 0, 0] },
74
+ homeYaw: { type: Types.Float32, default: 0 },
75
+ }, 'Internal UI Extensions window bookkeeping');
76
+ /**
77
+ * A named layout region that docked windows snap to and are laid out within.
78
+ * Place the entity where the region should live (it can itself carry a
79
+ * `Follower` to make a body-locked region).
80
+ */
81
+ export const UIDockRegion = createComponent('UIDockRegion', {
82
+ regionId: { type: Types.String, default: '' },
83
+ flow: { type: Types.Enum, enum: RegionFlowType, default: RegionFlowType.Column },
84
+ /** Distance between slot origins (meters). */
85
+ pitch: { type: Types.Float32, default: 0.35 },
86
+ /** Columns per row (grid flow only). */
87
+ columns: { type: Types.Float32, default: 2 },
88
+ /** Max docked windows (0 = unlimited). */
89
+ capacity: { type: Types.Float32, default: 0 },
90
+ /** Drop-capture radius (meters). */
91
+ snapRadius: { type: Types.Float32, default: 0.5 },
92
+ }, 'UI Extensions layout region for docking windows');
93
+ /** Present on a window entity while it is docked into a region. */
94
+ export const UIDockedTo = createComponent('UIDockedTo', {
95
+ regionId: { type: Types.String, default: '' },
96
+ }, 'Marks a UI Extensions window as docked into a region');
97
+ //# sourceMappingURL=components.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"components.js","sourceRoot":"","sources":["../src/components.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * ECS components for UI Extensions.\n *\n * These compose with the IWSDK's own components - a window entity typically\n * carries `PanelUI` (the IWSDK loads/renders the panel), `UIWindow` (ours),\n * and the IWSDK interaction tags (`RayInteractable`, `PokeInteractable`).\n * The systems in this package add/remove the IWSDK `Follower` / `ScreenSpace`\n * components to realise dock modes rather than re-implementing them.\n */\nimport { Types, createComponent } from '@iwsdk/core';\nimport { DockMode } from '@realitycollective/webxr-uiextensions';\n\n/** Region flow options mirrored as an enum object for the component schema. */\nexport const RegionFlowType = {\n Row: 'row',\n Column: 'column',\n Grid: 'grid',\n} as const;\n\n/**\n * Marks a panel entity as a managed window with chrome, focus, docking and\n * drag behaviour. Pair with `PanelUI` whose markup contains the window chrome\n * elements (see `WINDOW_CHROME_IDS` / the Examples folder).\n */\nexport const UIWindow = createComponent(\n 'UIWindow',\n {\n /** Stable id; auto-generated when empty. */\n windowId: { type: Types.String, default: '' },\n /** Title text written into the `uix-title` element. */\n title: { type: Types.String, default: '' },\n /** Current dock state. */\n dockMode: { type: Types.Enum, enum: DockMode, default: DockMode.WorldLocked },\n /** Whether the title bar drags the window. */\n movable: { type: Types.Boolean, default: true },\n /** Show/enable the close affordance. */\n closable: { type: Types.Boolean, default: true },\n /** Show/enable the minimize affordance. */\n minimizable: { type: Types.Boolean, default: true },\n /** Show/enable the pin (body-follow ⇄ world-locked) affordance. */\n pinnable: { type: Types.Boolean, default: true },\n /** Keep the window yawed toward the viewer while it is being dragged. */\n billboardWhileDragging: { type: Types.Boolean, default: true },\n /**\n * Seconds a title-bar press must be held before it becomes a drag.\n * Shorter presses stay clicks, so title-bar buttons don't fight the drag.\n */\n dragDelay: { type: Types.Float32, default: 0.3 },\n /** Head-relative offset used in `body-follow` mode (meters). */\n followOffset: { type: Types.Vec3, default: [0, -0.15, -1.2] },\n /** `Follower` lerp speed for body-follow. */\n followSpeed: { type: Types.Float32, default: 3 },\n /** `Follower` positional deadzone for body-follow (meters). */\n followTolerance: { type: Types.Float32, default: 0.35 },\n /** Meters the focused window is nudged toward the viewer per focus depth. */\n focusBias: { type: Types.Float32, default: 0.02 },\n /**\n * World size box in meters, applied via `UIKitDocument.setTargetDimensions`\n * once the document loads. IWSDK 0.5 removed `PanelUI.maxWidth/maxHeight`;\n * this is the supported replacement. `0` leaves the document at its\n * intrinsic markup size, scaled only by the entity transform.\n */\n targetWidth: { type: Types.Float32, default: 0 },\n targetHeight: { type: Types.Float32, default: 0 },\n },\n 'UI Extensions managed window (chrome, focus, docking, drag)',\n);\n\n/**\n * Internal bookkeeping the systems keep on window entities - which dock mode\n * has actually been applied to engine components, and whether chrome wiring\n * has run for the current PanelDocument.\n */\nexport const UIWindowState = createComponent(\n 'UIWindowState',\n {\n appliedDockMode: { type: Types.String, default: '' },\n chromeWired: { type: Types.Boolean, default: false },\n /** \"Home\" snapshot captured on adoption - the DOCK button returns here. */\n homeDockMode: { type: Types.String, default: '' },\n homeRegion: { type: Types.String, default: '' },\n homePosition: { type: Types.Vec3, default: [0, 0, 0] },\n homeYaw: { type: Types.Float32, default: 0 },\n },\n 'Internal UI Extensions window bookkeeping',\n);\n\n/**\n * A named layout region that docked windows snap to and are laid out within.\n * Place the entity where the region should live (it can itself carry a\n * `Follower` to make a body-locked region).\n */\nexport const UIDockRegion = createComponent(\n 'UIDockRegion',\n {\n regionId: { type: Types.String, default: '' },\n flow: { type: Types.Enum, enum: RegionFlowType, default: RegionFlowType.Column },\n /** Distance between slot origins (meters). */\n pitch: { type: Types.Float32, default: 0.35 },\n /** Columns per row (grid flow only). */\n columns: { type: Types.Float32, default: 2 },\n /** Max docked windows (0 = unlimited). */\n capacity: { type: Types.Float32, default: 0 },\n /** Drop-capture radius (meters). */\n snapRadius: { type: Types.Float32, default: 0.5 },\n },\n 'UI Extensions layout region for docking windows',\n);\n\n/** Present on a window entity while it is docked into a region. */\nexport const UIDockedTo = createComponent(\n 'UIDockedTo',\n {\n regionId: { type: Types.String, default: '' },\n },\n 'Marks a UI Extensions window as docked into a region',\n);\n"]}
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Convenience factories - one call to spawn a managed window or dock region.
3
+ * Thin sugar over `createTransformEntity().addComponent(...)`; everything
4
+ * they do can be done manually with the components.
5
+ */
6
+ import { type Entity, type World } from '@iwsdk/core';
7
+ import { RegionFlowType } from './components.js';
8
+ import { type DockModeValue } from '@realitycollective/webxr-uiextensions';
9
+ export interface CreateWindowOptions {
10
+ /**
11
+ * URL of the UIKitML source (e.g. "/ui/my-window.uikitml"). IWSDK 0.5 parses
12
+ * UIKitML at runtime - the build-time plugin and its generated JSON are gone.
13
+ */
14
+ config: string;
15
+ id?: string;
16
+ title?: string;
17
+ dockMode?: DockModeValue;
18
+ /** World position for world-locked windows. */
19
+ position?: [number, number, number];
20
+ /**
21
+ * Fit the panel into this world-space box (meters), preserving aspect ratio.
22
+ * Replaces the `PanelUI.maxWidth/maxHeight` fields removed in IWSDK 0.5.
23
+ * Omit to keep the markup's intrinsic size and scale via the entity transform.
24
+ */
25
+ maxWidth?: number;
26
+ maxHeight?: number;
27
+ movable?: boolean;
28
+ closable?: boolean;
29
+ minimizable?: boolean;
30
+ pinnable?: boolean;
31
+ billboardWhileDragging?: boolean;
32
+ followOffset?: [number, number, number];
33
+ followSpeed?: number;
34
+ followTolerance?: number;
35
+ /** Dock straight into this region on spawn. */
36
+ region?: string;
37
+ }
38
+ export declare function createUIWindow(world: World, options: CreateWindowOptions): Entity;
39
+ export interface CreateDockRegionOptions {
40
+ id: string;
41
+ flow?: (typeof RegionFlowType)[keyof typeof RegionFlowType];
42
+ pitch?: number;
43
+ columns?: number;
44
+ capacity?: number;
45
+ snapRadius?: number;
46
+ /** World position of the region origin. */
47
+ position?: [number, number, number];
48
+ /**
49
+ * Body-lock the region itself: it follows the player's head at
50
+ * `followOffset`, and every window docked into it comes along.
51
+ */
52
+ follow?: boolean;
53
+ followOffset?: [number, number, number];
54
+ }
55
+ export declare function createDockRegion(world: World, options: CreateDockRegionOptions): Entity;
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Convenience factories - one call to spawn a managed window or dock region.
3
+ * Thin sugar over `createTransformEntity().addComponent(...)`; everything
4
+ * they do can be done manually with the components.
5
+ */
6
+ import { Follower, FollowBehavior, PanelUI, PokeInteractable, RayInteractable, } from '@iwsdk/core';
7
+ import { UIDockRegion, UIDockedTo, UIWindow, RegionFlowType } from './components.js';
8
+ import { DockMode } from '@realitycollective/webxr-uiextensions';
9
+ export function createUIWindow(world, options) {
10
+ const entity = world
11
+ .createTransformEntity()
12
+ .addComponent(PanelUI, {
13
+ config: options.config,
14
+ })
15
+ .addComponent(UIWindow, {
16
+ // Applied by UIWindowSystem once the document loads - see components.ts.
17
+ targetWidth: options.maxWidth ?? 0,
18
+ targetHeight: options.maxHeight ?? 0,
19
+ windowId: options.id ?? '',
20
+ title: options.title ?? '',
21
+ dockMode: options.dockMode ?? DockMode.WorldLocked,
22
+ movable: options.movable ?? true,
23
+ closable: options.closable ?? true,
24
+ minimizable: options.minimizable ?? true,
25
+ pinnable: options.pinnable ?? true,
26
+ billboardWhileDragging: options.billboardWhileDragging ?? true,
27
+ followOffset: options.followOffset ?? [0, -0.15, -1.2],
28
+ followSpeed: options.followSpeed ?? 3,
29
+ followTolerance: options.followTolerance ?? 0.35,
30
+ })
31
+ .addComponent(RayInteractable)
32
+ .addComponent(PokeInteractable);
33
+ if (options.position) {
34
+ entity.object3D?.position.set(...options.position);
35
+ }
36
+ if (options.region) {
37
+ entity.addComponent(UIDockedTo, { regionId: options.region });
38
+ }
39
+ return entity;
40
+ }
41
+ export function createDockRegion(world, options) {
42
+ const entity = world.createTransformEntity().addComponent(UIDockRegion, {
43
+ regionId: options.id,
44
+ flow: options.flow ?? RegionFlowType.Column,
45
+ pitch: options.pitch ?? 0.35,
46
+ columns: options.columns ?? 2,
47
+ capacity: options.capacity ?? 0,
48
+ snapRadius: options.snapRadius ?? 0.5,
49
+ });
50
+ if (options.position) {
51
+ entity.object3D?.position.set(...options.position);
52
+ }
53
+ if (options.follow) {
54
+ entity.addComponent(Follower, {
55
+ // Camera, not player.head - the head rig is origin-locked outside XR.
56
+ target: world.camera,
57
+ offsetPosition: options.followOffset ?? [0, -0.2, -1.4],
58
+ behavior: FollowBehavior.PivotY,
59
+ });
60
+ }
61
+ return entity;
62
+ }
63
+ //# sourceMappingURL=factory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"factory.js","sourceRoot":"","sources":["../src/factory.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Convenience factories - one call to spawn a managed window or dock region.\n * Thin sugar over `createTransformEntity().addComponent(...)`; everything\n * they do can be done manually with the components.\n */\nimport {\n Follower,\n FollowBehavior,\n PanelUI,\n PokeInteractable,\n RayInteractable,\n type Entity,\n type World,\n} from '@iwsdk/core';\nimport { UIDockRegion, UIDockedTo, UIWindow, RegionFlowType } from './components.js';\nimport { DockMode, type DockModeValue } from '@realitycollective/webxr-uiextensions';\n\nexport interface CreateWindowOptions {\n /**\n * URL of the UIKitML source (e.g. \"/ui/my-window.uikitml\"). IWSDK 0.5 parses\n * UIKitML at runtime - the build-time plugin and its generated JSON are gone.\n */\n config: string;\n id?: string;\n title?: string;\n dockMode?: DockModeValue;\n /** World position for world-locked windows. */\n position?: [number, number, number];\n /**\n * Fit the panel into this world-space box (meters), preserving aspect ratio.\n * Replaces the `PanelUI.maxWidth/maxHeight` fields removed in IWSDK 0.5.\n * Omit to keep the markup's intrinsic size and scale via the entity transform.\n */\n maxWidth?: number;\n maxHeight?: number;\n movable?: boolean;\n closable?: boolean;\n minimizable?: boolean;\n pinnable?: boolean;\n billboardWhileDragging?: boolean;\n followOffset?: [number, number, number];\n followSpeed?: number;\n followTolerance?: number;\n /** Dock straight into this region on spawn. */\n region?: string;\n}\n\nexport function createUIWindow(world: World, options: CreateWindowOptions): Entity {\n const entity = world\n .createTransformEntity()\n .addComponent(PanelUI, {\n config: options.config,\n })\n .addComponent(UIWindow, {\n // Applied by UIWindowSystem once the document loads - see components.ts.\n targetWidth: options.maxWidth ?? 0,\n targetHeight: options.maxHeight ?? 0,\n windowId: options.id ?? '',\n title: options.title ?? '',\n dockMode: options.dockMode ?? DockMode.WorldLocked,\n movable: options.movable ?? true,\n closable: options.closable ?? true,\n minimizable: options.minimizable ?? true,\n pinnable: options.pinnable ?? true,\n billboardWhileDragging: options.billboardWhileDragging ?? true,\n followOffset: options.followOffset ?? [0, -0.15, -1.2],\n followSpeed: options.followSpeed ?? 3,\n followTolerance: options.followTolerance ?? 0.35,\n })\n .addComponent(RayInteractable)\n .addComponent(PokeInteractable);\n\n if (options.position) {\n entity.object3D?.position.set(...options.position);\n }\n if (options.region) {\n entity.addComponent(UIDockedTo, { regionId: options.region });\n }\n return entity;\n}\n\nexport interface CreateDockRegionOptions {\n id: string;\n flow?: (typeof RegionFlowType)[keyof typeof RegionFlowType];\n pitch?: number;\n columns?: number;\n capacity?: number;\n snapRadius?: number;\n /** World position of the region origin. */\n position?: [number, number, number];\n /**\n * Body-lock the region itself: it follows the player's head at\n * `followOffset`, and every window docked into it comes along.\n */\n follow?: boolean;\n followOffset?: [number, number, number];\n}\n\nexport function createDockRegion(world: World, options: CreateDockRegionOptions): Entity {\n const entity = world.createTransformEntity().addComponent(UIDockRegion, {\n regionId: options.id,\n flow: options.flow ?? RegionFlowType.Column,\n pitch: options.pitch ?? 0.35,\n columns: options.columns ?? 2,\n capacity: options.capacity ?? 0,\n snapRadius: options.snapRadius ?? 0.5,\n });\n if (options.position) {\n entity.object3D?.position.set(...options.position);\n }\n if (options.follow) {\n entity.addComponent(Follower, {\n // Camera, not player.head - the head rig is origin-locked outside XR.\n target: world.camera,\n offsetPosition: options.followOffset ?? [0, -0.2, -1.4],\n behavior: FollowBehavior.PivotY,\n });\n }\n return entity;\n}\n"]}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * @realitycollective/iwsdk-uiextensions - the Meta IWSDK adapter.
3
+ *
4
+ * The engine-free UX core (window manager, dock state, region math, drag
5
+ * math, control models, markup upgraders, adapter interfaces) lives in
6
+ * `@realitycollective/webxr-uiextensions` and is re-exported here in full,
7
+ * so this package remains a drop-in single dependency for IWSDK apps.
8
+ *
9
+ * What this package adds is the IWSDK binding: ECS components + systems
10
+ * that apply the core onto `@iwsdk/core` entities, plus the one-call
11
+ * factories and `registerUIExtensions`.
12
+ */
13
+ export * from '@realitycollective/webxr-uiextensions';
14
+ export * from './components.js';
15
+ export * from './manager-registry.js';
16
+ export * from './region-registry-store.js';
17
+ export * from './factory.js';
18
+ export * from './scene-host.js';
19
+ export * from './register.js';
20
+ export * from './systems/window-system.js';
21
+ export * from './systems/dock-system.js';
22
+ export * from './systems/drag-system.js';
23
+ export * from './systems/dock-region-system.js';
24
+ export * from './systems/controls-system.js';
package/dist/index.js ADDED
@@ -0,0 +1,27 @@
1
+ /**
2
+ * @realitycollective/iwsdk-uiextensions - the Meta IWSDK adapter.
3
+ *
4
+ * The engine-free UX core (window manager, dock state, region math, drag
5
+ * math, control models, markup upgraders, adapter interfaces) lives in
6
+ * `@realitycollective/webxr-uiextensions` and is re-exported here in full,
7
+ * so this package remains a drop-in single dependency for IWSDK apps.
8
+ *
9
+ * What this package adds is the IWSDK binding: ECS components + systems
10
+ * that apply the core onto `@iwsdk/core` entities, plus the one-call
11
+ * factories and `registerUIExtensions`.
12
+ */
13
+ // The portable core - re-exported for a single-dependency experience.
14
+ export * from '@realitycollective/webxr-uiextensions';
15
+ // IWSDK ECS binding
16
+ export * from './components.js';
17
+ export * from './manager-registry.js';
18
+ export * from './region-registry-store.js';
19
+ export * from './factory.js';
20
+ export * from './scene-host.js';
21
+ export * from './register.js';
22
+ export * from './systems/window-system.js';
23
+ export * from './systems/dock-system.js';
24
+ export * from './systems/drag-system.js';
25
+ export * from './systems/dock-region-system.js';
26
+ export * from './systems/controls-system.js';
27
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,sEAAsE;AACtE,cAAc,uCAAuC,CAAC;AAEtD,oBAAoB;AACpB,cAAc,iBAAiB,CAAC;AAChC,cAAc,uBAAuB,CAAC;AACtC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,cAAc,CAAC;AAC7B,cAAc,iBAAiB,CAAC;AAChC,cAAc,eAAe,CAAC;AAC9B,cAAc,4BAA4B,CAAC;AAC3C,cAAc,0BAA0B,CAAC;AACzC,cAAc,0BAA0B,CAAC;AACzC,cAAc,iCAAiC,CAAC;AAChD,cAAc,8BAA8B,CAAC","sourcesContent":["/**\n * @realitycollective/iwsdk-uiextensions - the Meta IWSDK adapter.\n *\n * The engine-free UX core (window manager, dock state, region math, drag\n * math, control models, markup upgraders, adapter interfaces) lives in\n * `@realitycollective/webxr-uiextensions` and is re-exported here in full,\n * so this package remains a drop-in single dependency for IWSDK apps.\n *\n * What this package adds is the IWSDK binding: ECS components + systems\n * that apply the core onto `@iwsdk/core` entities, plus the one-call\n * factories and `registerUIExtensions`.\n */\n// The portable core - re-exported for a single-dependency experience.\nexport * from '@realitycollective/webxr-uiextensions';\n\n// IWSDK ECS binding\nexport * from './components.js';\nexport * from './manager-registry.js';\nexport * from './region-registry-store.js';\nexport * from './factory.js';\nexport * from './scene-host.js';\nexport * from './register.js';\nexport * from './systems/window-system.js';\nexport * from './systems/dock-system.js';\nexport * from './systems/drag-system.js';\nexport * from './systems/dock-region-system.js';\nexport * from './systems/controls-system.js';\n"]}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * One `WindowManager` per IWSDK `World`, lazily created. App code and the
3
+ * systems in this package resolve the same instance through this registry,
4
+ * so window state has a single home without a global singleton.
5
+ */
6
+ import type { World } from '@iwsdk/core';
7
+ import { WindowManager } from '@realitycollective/webxr-uiextensions';
8
+ export declare function windowManagerFor(world: World): WindowManager;
@@ -0,0 +1,11 @@
1
+ import { WindowManager } from '@realitycollective/webxr-uiextensions';
2
+ const managers = new WeakMap();
3
+ export function windowManagerFor(world) {
4
+ let manager = managers.get(world);
5
+ if (!manager) {
6
+ manager = new WindowManager();
7
+ managers.set(world, manager);
8
+ }
9
+ return manager;
10
+ }
11
+ //# sourceMappingURL=manager-registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manager-registry.js","sourceRoot":"","sources":["../src/manager-registry.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,aAAa,EAAE,MAAM,uCAAuC,CAAC;AAEtE,MAAM,QAAQ,GAAG,IAAI,OAAO,EAAwB,CAAC;AAErD,MAAM,UAAU,gBAAgB,CAAC,KAAY;IAC3C,IAAI,OAAO,GAAG,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IAClC,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,GAAG,IAAI,aAAa,EAAE,CAAC;QAC9B,QAAQ,CAAC,GAAG,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;IAC/B,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC","sourcesContent":["/**\n * One `WindowManager` per IWSDK `World`, lazily created. App code and the\n * systems in this package resolve the same instance through this registry,\n * so window state has a single home without a global singleton.\n */\nimport type { World } from '@iwsdk/core';\nimport { WindowManager } from '@realitycollective/webxr-uiextensions';\n\nconst managers = new WeakMap<World, WindowManager>();\n\nexport function windowManagerFor(world: World): WindowManager {\n let manager = managers.get(world);\n if (!manager) {\n manager = new WindowManager();\n managers.set(world, manager);\n }\n return manager;\n}\n"]}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * One `RegionRegistry` per IWSDK `World` (same pattern as the window
3
+ * manager) so the drag and region systems share region state.
4
+ */
5
+ import type { World } from '@iwsdk/core';
6
+ import { RegionRegistry } from '@realitycollective/webxr-uiextensions';
7
+ export declare function regionRegistryFor(world: World): RegionRegistry;
@@ -0,0 +1,11 @@
1
+ import { RegionRegistry } from '@realitycollective/webxr-uiextensions';
2
+ const registries = new WeakMap();
3
+ export function regionRegistryFor(world) {
4
+ let registry = registries.get(world);
5
+ if (!registry) {
6
+ registry = new RegionRegistry();
7
+ registries.set(world, registry);
8
+ }
9
+ return registry;
10
+ }
11
+ //# sourceMappingURL=region-registry-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"region-registry-store.js","sourceRoot":"","sources":["../src/region-registry-store.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,cAAc,EAAE,MAAM,uCAAuC,CAAC;AAEvE,MAAM,UAAU,GAAG,IAAI,OAAO,EAAyB,CAAC;AAExD,MAAM,UAAU,iBAAiB,CAAC,KAAY;IAC5C,IAAI,QAAQ,GAAG,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IACrC,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,QAAQ,GAAG,IAAI,cAAc,EAAE,CAAC;QAChC,UAAU,CAAC,GAAG,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;IAClC,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC","sourcesContent":["/**\n * One `RegionRegistry` per IWSDK `World` (same pattern as the window\n * manager) so the drag and region systems share region state.\n */\nimport type { World } from '@iwsdk/core';\nimport { RegionRegistry } from '@realitycollective/webxr-uiextensions';\n\nconst registries = new WeakMap<World, RegionRegistry>();\n\nexport function regionRegistryFor(world: World): RegionRegistry {\n let registry = registries.get(world);\n if (!registry) {\n registry = new RegionRegistry();\n registries.set(world, registry);\n }\n return registry;\n}\n"]}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * One-call setup: register every UI Extensions system on a world.
3
+ *
4
+ * ```ts
5
+ * const world = await World.create(container, { features: { spatialUI: true } });
6
+ * registerUIExtensions(world);
7
+ * ```
8
+ */
9
+ import type { World } from '@iwsdk/core';
10
+ import type { WindowManager } from '@realitycollective/webxr-uiextensions';
11
+ export interface RegisterOptions {
12
+ /** Disable the title-bar drag system. */
13
+ drag?: boolean;
14
+ /** Disable dock regions. */
15
+ regions?: boolean;
16
+ /** Disable the `data-uix` control upgrades. */
17
+ controls?: boolean;
18
+ }
19
+ export declare function registerUIExtensions(world: World, options?: RegisterOptions): WindowManager;
@@ -0,0 +1,20 @@
1
+ import { UIWindowSystem } from './systems/window-system.js';
2
+ import { UIDockSystem } from './systems/dock-system.js';
3
+ import { UIDragSystem } from './systems/drag-system.js';
4
+ import { UIDockRegionSystem } from './systems/dock-region-system.js';
5
+ import { UIControlsSystem } from './systems/controls-system.js';
6
+ import { windowManagerFor } from './manager-registry.js';
7
+ export function registerUIExtensions(world, options = {}) {
8
+ world.registerSystem(UIWindowSystem).registerSystem(UIDockSystem);
9
+ if (options.drag !== false) {
10
+ world.registerSystem(UIDragSystem);
11
+ }
12
+ if (options.regions !== false) {
13
+ world.registerSystem(UIDockRegionSystem);
14
+ }
15
+ if (options.controls !== false) {
16
+ world.registerSystem(UIControlsSystem);
17
+ }
18
+ return windowManagerFor(world);
19
+ }
20
+ //# sourceMappingURL=register.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"register.js","sourceRoot":"","sources":["../src/register.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAC5D,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AACxD,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AACxD,OAAO,EAAE,kBAAkB,EAAE,MAAM,iCAAiC,CAAC;AACrE,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAChE,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAYzD,MAAM,UAAU,oBAAoB,CAClC,KAAY,EACZ,UAA2B,EAAE;IAE7B,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC,CAAC,cAAc,CAAC,YAAY,CAAC,CAAC;IAClE,IAAI,OAAO,CAAC,IAAI,KAAK,KAAK,EAAE,CAAC;QAC3B,KAAK,CAAC,cAAc,CAAC,YAAY,CAAC,CAAC;IACrC,CAAC;IACD,IAAI,OAAO,CAAC,OAAO,KAAK,KAAK,EAAE,CAAC;QAC9B,KAAK,CAAC,cAAc,CAAC,kBAAkB,CAAC,CAAC;IAC3C,CAAC;IACD,IAAI,OAAO,CAAC,QAAQ,KAAK,KAAK,EAAE,CAAC;QAC/B,KAAK,CAAC,cAAc,CAAC,gBAAgB,CAAC,CAAC;IACzC,CAAC;IACD,OAAO,gBAAgB,CAAC,KAAK,CAAC,CAAC;AACjC,CAAC","sourcesContent":["/**\n * One-call setup: register every UI Extensions system on a world.\n *\n * ```ts\n * const world = await World.create(container, { features: { spatialUI: true } });\n * registerUIExtensions(world);\n * ```\n */\nimport type { World } from '@iwsdk/core';\nimport { UIWindowSystem } from './systems/window-system.js';\nimport { UIDockSystem } from './systems/dock-system.js';\nimport { UIDragSystem } from './systems/drag-system.js';\nimport { UIDockRegionSystem } from './systems/dock-region-system.js';\nimport { UIControlsSystem } from './systems/controls-system.js';\nimport { windowManagerFor } from './manager-registry.js';\nimport type { WindowManager } from '@realitycollective/webxr-uiextensions';\n\nexport interface RegisterOptions {\n /** Disable the title-bar drag system. */\n drag?: boolean;\n /** Disable dock regions. */\n regions?: boolean;\n /** Disable the `data-uix` control upgrades. */\n controls?: boolean;\n}\n\nexport function registerUIExtensions(\n world: World,\n options: RegisterOptions = {},\n): WindowManager {\n world.registerSystem(UIWindowSystem).registerSystem(UIDockSystem);\n if (options.drag !== false) {\n world.registerSystem(UIDragSystem);\n }\n if (options.regions !== false) {\n world.registerSystem(UIDockRegionSystem);\n }\n if (options.controls !== false) {\n world.registerSystem(UIControlsSystem);\n }\n return windowManagerFor(world);\n}\n"]}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * IWSDK implementation of the core's `WindowHost` + `SceneTarget`.
3
+ *
4
+ * This is what makes a portable `SceneDescriptor` build the SAME playground
5
+ * on IWSDK as on plain three.js, and lets app behaviour be wired through
6
+ * `onPanelReady` instead of hand-written ECS queries:
7
+ *
8
+ * const host = createSceneHost(world);
9
+ * applyScene(host, PLAYGROUND);
10
+ * host.onPanelReady(({ id, panel }) => wireMyPanel(id, panel));
11
+ *
12
+ * Readiness is detected with a single ECS query on `PanelUI + PanelDocument`
13
+ * - the engine-specific mechanism stays here, behind the portable interface.
14
+ */
15
+ import { type World } from '@iwsdk/core';
16
+ import { type SceneTarget, type WindowHost } from '@realitycollective/webxr-uiextensions';
17
+ export interface IwsdkSceneHost extends WindowHost, SceneTarget {
18
+ readonly world: World;
19
+ }
20
+ /**
21
+ * Create the host for a world. Call AFTER `registerUIExtensions(world)`.
22
+ */
23
+ export declare function createSceneHost(world: World): IwsdkSceneHost;
@@ -0,0 +1,145 @@
1
+ /**
2
+ * IWSDK implementation of the core's `WindowHost` + `SceneTarget`.
3
+ *
4
+ * This is what makes a portable `SceneDescriptor` build the SAME playground
5
+ * on IWSDK as on plain three.js, and lets app behaviour be wired through
6
+ * `onPanelReady` instead of hand-written ECS queries:
7
+ *
8
+ * const host = createSceneHost(world);
9
+ * applyScene(host, PLAYGROUND);
10
+ * host.onPanelReady(({ id, panel }) => wireMyPanel(id, panel));
11
+ *
12
+ * Readiness is detected with a single ECS query on `PanelUI + PanelDocument`
13
+ * - the engine-specific mechanism stays here, behind the portable interface.
14
+ */
15
+ import { PanelDocument, PanelUI, createSystem, } from '@iwsdk/core';
16
+ import { upgradePanel, } from '@realitycollective/webxr-uiextensions';
17
+ import { createDockRegion, createUIWindow } from './factory.js';
18
+ import { UIWindow } from './components.js';
19
+ /** Panel handle over an IWSDK `UIKitDocument`. */
20
+ function panelHandleFor(document) {
21
+ return {
22
+ get root() {
23
+ return document.rootElement;
24
+ },
25
+ getElementById: (id) => document.getElementById(id) ?? undefined,
26
+ setTargetDimensions: (width, height) => document.setTargetDimensions(width, height),
27
+ dispose: () => {
28
+ /* IWSDK owns the document lifecycle via the entity. */
29
+ },
30
+ };
31
+ }
32
+ /**
33
+ * Bridges panel loading into `onPanelReady`. Registered once per host; the
34
+ * query fires as each panel's document is attached by IWSDK's UI system.
35
+ */
36
+ function createReadySystem(onReady) {
37
+ return class UixPanelReadySystem extends createSystem({
38
+ panels: { required: [PanelUI, PanelDocument] },
39
+ }) {
40
+ init() {
41
+ this.cleanupFuncs.push(this.queries.panels.subscribe('qualify', (entity) => onReady(entity)));
42
+ this.queries.panels.entities.forEach((entity) => onReady(entity));
43
+ }
44
+ };
45
+ }
46
+ /**
47
+ * Create the host for a world. Call AFTER `registerUIExtensions(world)`.
48
+ */
49
+ export function createSceneHost(world) {
50
+ const readyListeners = new Set();
51
+ const ready = new Map();
52
+ const seen = new WeakSet();
53
+ const announce = (entity) => {
54
+ const document = PanelDocument.data.document[entity.index];
55
+ if (!document || seen.has(document)) {
56
+ return;
57
+ }
58
+ seen.add(document);
59
+ // Window id comes from the UIWindow component the factory attached.
60
+ const id = entity.hasComponent(UIWindow)
61
+ ? UIWindow.data.windowId[entity.index]
62
+ : '';
63
+ if (!id) {
64
+ return; // a bare panel, not a managed window - nothing to wire by id
65
+ }
66
+ const panel = panelHandleFor(document);
67
+ // Upgrade `data-uix` controls exactly as the ECS controls system does,
68
+ // so wiring code sees the same handles on every adapter (idempotent).
69
+ upgradePanel(document, document.rootElement);
70
+ const event = { id, panel };
71
+ ready.set(id, event);
72
+ for (const listener of readyListeners) {
73
+ try {
74
+ listener(event);
75
+ }
76
+ catch (error) {
77
+ console.error(`[uix] panel-ready listener failed for "${id}":`, error);
78
+ }
79
+ }
80
+ };
81
+ world.registerSystem(createReadySystem(announce));
82
+ return {
83
+ world,
84
+ createPanel() {
85
+ throw new Error('[uix] createPanel() is not supported on the IWSDK host - spawn a window ' +
86
+ '(spawnWindow/createUIWindow) so IWSDK owns the panel lifecycle.');
87
+ },
88
+ onPanelReady(listener) {
89
+ readyListeners.add(listener);
90
+ for (const event of ready.values()) {
91
+ listener(event);
92
+ }
93
+ return () => void readyListeners.delete(listener);
94
+ },
95
+ spawnRegion(region) {
96
+ createDockRegion(world, {
97
+ id: region.id,
98
+ ...(region.flow !== undefined ? { flow: region.flow } : {}),
99
+ ...(region.pitch !== undefined ? { pitch: region.pitch } : {}),
100
+ ...(region.columns !== undefined ? { columns: region.columns } : {}),
101
+ ...(region.capacity !== undefined ? { capacity: region.capacity } : {}),
102
+ ...(region.snapRadius !== undefined
103
+ ? { snapRadius: region.snapRadius }
104
+ : {}),
105
+ ...(region.position !== undefined
106
+ ? { position: [...region.position] }
107
+ : {}),
108
+ ...(region.follow !== undefined ? { follow: region.follow } : {}),
109
+ ...(region.followOffset !== undefined
110
+ ? { followOffset: [...region.followOffset] }
111
+ : {}),
112
+ });
113
+ },
114
+ spawnWindow(window) {
115
+ createUIWindow(world, {
116
+ id: window.id,
117
+ title: window.title,
118
+ config: window.config,
119
+ ...(window.position !== undefined
120
+ ? { position: [...window.position] }
121
+ : {}),
122
+ ...(window.maxWidth !== undefined ? { maxWidth: window.maxWidth } : {}),
123
+ ...(window.maxHeight !== undefined ? { maxHeight: window.maxHeight } : {}),
124
+ ...(window.dockMode !== undefined ? { dockMode: window.dockMode } : {}),
125
+ ...(window.region !== undefined ? { region: window.region } : {}),
126
+ ...(window.followOffset !== undefined
127
+ ? { followOffset: [...window.followOffset] }
128
+ : {}),
129
+ ...(window.followSpeed !== undefined
130
+ ? { followSpeed: window.followSpeed }
131
+ : {}),
132
+ ...(window.followTolerance !== undefined
133
+ ? { followTolerance: window.followTolerance }
134
+ : {}),
135
+ ...(window.movable !== undefined ? { movable: window.movable } : {}),
136
+ ...(window.closable !== undefined ? { closable: window.closable } : {}),
137
+ ...(window.minimizable !== undefined
138
+ ? { minimizable: window.minimizable }
139
+ : {}),
140
+ ...(window.pinnable !== undefined ? { pinnable: window.pinnable } : {}),
141
+ });
142
+ },
143
+ };
144
+ }
145
+ //# sourceMappingURL=scene-host.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scene-host.js","sourceRoot":"","sources":["../src/scene-host.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * IWSDK implementation of the core's `WindowHost` + `SceneTarget`.\n *\n * This is what makes a portable `SceneDescriptor` build the SAME playground\n * on IWSDK as on plain three.js, and lets app behaviour be wired through\n * `onPanelReady` instead of hand-written ECS queries:\n *\n * const host = createSceneHost(world);\n * applyScene(host, PLAYGROUND);\n * host.onPanelReady(({ id, panel }) => wireMyPanel(id, panel));\n *\n * Readiness is detected with a single ECS query on `PanelUI + PanelDocument`\n * - the engine-specific mechanism stays here, behind the portable interface.\n */\nimport {\n PanelDocument,\n PanelUI,\n UIKitDocument,\n createSystem,\n type Entity,\n type World,\n} from '@iwsdk/core';\nimport {\n upgradePanel,\n type PanelHandle,\n type PanelReadyEvent,\n type SceneRegion,\n type SceneTarget,\n type SceneWindow,\n type UixElement,\n type WindowHost,\n} from '@realitycollective/webxr-uiextensions';\nimport { createDockRegion, createUIWindow } from './factory.js';\nimport { UIWindow } from './components.js';\n\n/** Panel handle over an IWSDK `UIKitDocument`. */\nfunction panelHandleFor(document: UIKitDocument): PanelHandle {\n return {\n get root(): UixElement {\n return document.rootElement as unknown as UixElement;\n },\n getElementById: (id) =>\n (document.getElementById(id) as UixElement | null) ?? undefined,\n setTargetDimensions: (width, height) =>\n document.setTargetDimensions(width, height),\n dispose: () => {\n /* IWSDK owns the document lifecycle via the entity. */\n },\n };\n}\n\n/**\n * Bridges panel loading into `onPanelReady`. Registered once per host; the\n * query fires as each panel's document is attached by IWSDK's UI system.\n */\nfunction createReadySystem(onReady: (entity: Entity) => void) {\n return class UixPanelReadySystem extends createSystem({\n panels: { required: [PanelUI, PanelDocument] },\n }) {\n override init(): void {\n this.cleanupFuncs.push(\n this.queries.panels.subscribe('qualify', (entity) => onReady(entity)),\n );\n this.queries.panels.entities.forEach((entity) => onReady(entity));\n }\n };\n}\n\nexport interface IwsdkSceneHost extends WindowHost, SceneTarget {\n readonly world: World;\n}\n\n/**\n * Create the host for a world. Call AFTER `registerUIExtensions(world)`.\n */\nexport function createSceneHost(world: World): IwsdkSceneHost {\n const readyListeners = new Set<(event: PanelReadyEvent) => void>();\n const ready = new Map<string, PanelReadyEvent>();\n const seen = new WeakSet<object>();\n\n const announce = (entity: Entity): void => {\n const document = PanelDocument.data.document[entity.index] as\n | UIKitDocument\n | undefined;\n if (!document || seen.has(document)) {\n return;\n }\n seen.add(document);\n // Window id comes from the UIWindow component the factory attached.\n const id = entity.hasComponent(UIWindow)\n ? (UIWindow.data.windowId[entity.index] as string)\n : '';\n if (!id) {\n return; // a bare panel, not a managed window - nothing to wire by id\n }\n const panel = panelHandleFor(document);\n // Upgrade `data-uix` controls exactly as the ECS controls system does,\n // so wiring code sees the same handles on every adapter (idempotent).\n upgradePanel(document, document.rootElement as unknown as UixElement);\n const event: PanelReadyEvent = { id, panel };\n ready.set(id, event);\n for (const listener of readyListeners) {\n try {\n listener(event);\n } catch (error) {\n console.error(`[uix] panel-ready listener failed for \"${id}\":`, error);\n }\n }\n };\n\n world.registerSystem(createReadySystem(announce));\n\n return {\n world,\n\n createPanel(): PanelHandle {\n throw new Error(\n '[uix] createPanel() is not supported on the IWSDK host - spawn a window ' +\n '(spawnWindow/createUIWindow) so IWSDK owns the panel lifecycle.',\n );\n },\n\n onPanelReady(listener) {\n readyListeners.add(listener);\n for (const event of ready.values()) {\n listener(event);\n }\n return () => void readyListeners.delete(listener);\n },\n\n spawnRegion(region: SceneRegion): void {\n createDockRegion(world, {\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\n ? { snapRadius: region.snapRadius }\n : {}),\n ...(region.position !== undefined\n ? { position: [...region.position] as [number, number, number] }\n : {}),\n ...(region.follow !== undefined ? { follow: region.follow } : {}),\n ...(region.followOffset !== undefined\n ? { followOffset: [...region.followOffset] as [number, number, number] }\n : {}),\n });\n },\n\n spawnWindow(window: SceneWindow): void {\n createUIWindow(world, {\n id: window.id,\n title: window.title,\n config: window.config,\n ...(window.position !== undefined\n ? { position: [...window.position] as [number, number, number] }\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 [number, number, number] }\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 });\n },\n };\n}\n"]}
@@ -0,0 +1,24 @@
1
+ declare const UIControlsSystem_base: import("elics").SystemConstructor<import("elics").SystemSchema, {
2
+ panels: {
3
+ required: import("elics").Component<{
4
+ document: {
5
+ type: import("@iwsdk/core").Types.Object;
6
+ default: undefined;
7
+ };
8
+ }>[];
9
+ };
10
+ }, World, import("@iwsdk/core").System<import("elics").SystemSchema, {
11
+ panels: {
12
+ required: import("elics").Component<{
13
+ document: {
14
+ type: import("@iwsdk/core").Types.Object;
15
+ default: undefined;
16
+ };
17
+ }>[];
18
+ };
19
+ }>>;
20
+ export declare class UIControlsSystem extends UIControlsSystem_base {
21
+ init(): void;
22
+ private upgrade;
23
+ }
24
+ export {};