@ubuilder-ai/workspace 0.1.0-alpha.1

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 (71) hide show
  1. package/README.md +7 -0
  2. package/dist/floorplan-annotation-obstacles.d.ts +4 -0
  3. package/dist/floorplan-annotation-obstacles.d.ts.map +1 -0
  4. package/dist/floorplan-annotation-obstacles.js +25 -0
  5. package/dist/floorplan-camera-sync.d.ts +24 -0
  6. package/dist/floorplan-camera-sync.d.ts.map +1 -0
  7. package/dist/floorplan-camera-sync.js +187 -0
  8. package/dist/floorplan-coordinates.d.ts +10 -0
  9. package/dist/floorplan-coordinates.d.ts.map +1 -0
  10. package/dist/floorplan-coordinates.js +25 -0
  11. package/dist/floorplan-dimension-renderer.d.ts +42 -0
  12. package/dist/floorplan-dimension-renderer.d.ts.map +1 -0
  13. package/dist/floorplan-dimension-renderer.js +245 -0
  14. package/dist/floorplan-geometry-renderer.d.ts +56 -0
  15. package/dist/floorplan-geometry-renderer.d.ts.map +1 -0
  16. package/dist/floorplan-geometry-renderer.js +319 -0
  17. package/dist/floorplan-initial-view.d.ts +29 -0
  18. package/dist/floorplan-initial-view.d.ts.map +1 -0
  19. package/dist/floorplan-initial-view.js +30 -0
  20. package/dist/floorplan-label-angle.d.ts +24 -0
  21. package/dist/floorplan-label-angle.d.ts.map +1 -0
  22. package/dist/floorplan-label-angle.js +60 -0
  23. package/dist/floorplan-navigation-presentation.d.ts +57 -0
  24. package/dist/floorplan-navigation-presentation.d.ts.map +1 -0
  25. package/dist/floorplan-navigation-presentation.js +81 -0
  26. package/dist/floorplan-navigation-shell.d.ts +87 -0
  27. package/dist/floorplan-navigation-shell.d.ts.map +1 -0
  28. package/dist/floorplan-navigation-shell.js +1178 -0
  29. package/dist/floorplan-navigation-types.d.ts +10 -0
  30. package/dist/floorplan-navigation-types.d.ts.map +1 -0
  31. package/dist/floorplan-navigation-types.js +1 -0
  32. package/dist/floorplan-registry-projection.d.ts +84 -0
  33. package/dist/floorplan-registry-projection.d.ts.map +1 -0
  34. package/dist/floorplan-registry-projection.js +260 -0
  35. package/dist/floorplan-render-context.d.ts +56 -0
  36. package/dist/floorplan-render-context.d.ts.map +1 -0
  37. package/dist/floorplan-render-context.js +75 -0
  38. package/dist/index.d.ts +20 -0
  39. package/dist/index.d.ts.map +1 -0
  40. package/dist/index.js +18 -0
  41. package/dist/spatial-workspace-camera-action-control.d.ts +18 -0
  42. package/dist/spatial-workspace-camera-action-control.d.ts.map +1 -0
  43. package/dist/spatial-workspace-camera-action-control.js +13 -0
  44. package/dist/spatial-workspace-display-control.d.ts +64 -0
  45. package/dist/spatial-workspace-display-control.d.ts.map +1 -0
  46. package/dist/spatial-workspace-display-control.js +81 -0
  47. package/dist/spatial-workspace-gis-control.d.ts +58 -0
  48. package/dist/spatial-workspace-gis-control.d.ts.map +1 -0
  49. package/dist/spatial-workspace-gis-control.js +38 -0
  50. package/dist/spatial-workspace-instance.d.ts +2 -0
  51. package/dist/spatial-workspace-instance.d.ts.map +1 -0
  52. package/dist/spatial-workspace-instance.js +14 -0
  53. package/dist/spatial-workspace-level-selector.d.ts +21 -0
  54. package/dist/spatial-workspace-level-selector.d.ts.map +1 -0
  55. package/dist/spatial-workspace-level-selector.js +11 -0
  56. package/dist/spatial-workspace-level-wall-control.d.ts +38 -0
  57. package/dist/spatial-workspace-level-wall-control.d.ts.map +1 -0
  58. package/dist/spatial-workspace-level-wall-control.js +41 -0
  59. package/dist/spatial-workspace-mode.d.ts +11 -0
  60. package/dist/spatial-workspace-mode.d.ts.map +1 -0
  61. package/dist/spatial-workspace-mode.js +29 -0
  62. package/dist/spatial-workspace-styles.d.ts +3 -0
  63. package/dist/spatial-workspace-styles.d.ts.map +1 -0
  64. package/dist/spatial-workspace-styles.js +72 -0
  65. package/dist/spatial-workspace-view-mode-control.d.ts +19 -0
  66. package/dist/spatial-workspace-view-mode-control.d.ts.map +1 -0
  67. package/dist/spatial-workspace-view-mode-control.js +14 -0
  68. package/dist/spatial-workspace-viewport.d.ts +25 -0
  69. package/dist/spatial-workspace-viewport.d.ts.map +1 -0
  70. package/dist/spatial-workspace-viewport.js +75 -0
  71. package/package.json +47 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spatial-workspace-display-control.d.ts","sourceRoot":"","sources":["../src/spatial-workspace-display-control.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,81 @@
1
+ 'use client';
2
+ import { jsx as _jsx } from "react/jsx-runtime";
3
+ import { createElement as _createElement } from "react";
4
+ import { Fragment } from 'react';
5
+ const SHADING_ACTIONS = [
6
+ { kind: 'set-shading', value: 'solid' },
7
+ { kind: 'set-shading', value: 'rendered' },
8
+ ];
9
+ const EDGE_ACTIONS = [
10
+ { kind: 'set-edges', value: 'off' },
11
+ { kind: 'set-edges', value: 'soft' },
12
+ { kind: 'set-edges', value: 'strong' },
13
+ ];
14
+ export function createSpatialWorkspaceDisplayActionGroups(sceneThemeIds) {
15
+ return {
16
+ edges: EDGE_ACTIONS,
17
+ primary: [
18
+ { kind: 'toggle-shadows' },
19
+ { kind: 'toggle-projection' },
20
+ { kind: 'toggle-textures' },
21
+ ],
22
+ sceneThemes: sceneThemeIds.map((value) => ({
23
+ kind: 'set-scene-theme',
24
+ value,
25
+ })),
26
+ shading: SHADING_ACTIONS,
27
+ };
28
+ }
29
+ export function createSpatialWorkspaceDisplayActions(sceneThemeIds) {
30
+ const groups = createSpatialWorkspaceDisplayActionGroups(sceneThemeIds);
31
+ return [...groups.primary, ...groups.shading, ...groups.sceneThemes, ...groups.edges];
32
+ }
33
+ export function isSpatialWorkspaceDisplayActionActive(state, action) {
34
+ switch (action.kind) {
35
+ case 'toggle-shadows':
36
+ return state.shadows;
37
+ case 'toggle-projection':
38
+ return state.projection === 'orthographic';
39
+ case 'toggle-textures':
40
+ return state.textures;
41
+ case 'set-shading':
42
+ return state.shading === action.value;
43
+ case 'set-scene-theme':
44
+ return state.sceneTheme === action.value;
45
+ case 'set-edges':
46
+ return state.edges === action.value;
47
+ }
48
+ }
49
+ export function applySpatialWorkspaceDisplayAction(state, controller, action) {
50
+ switch (action.kind) {
51
+ case 'toggle-shadows':
52
+ controller.setShadows(!state.shadows);
53
+ return;
54
+ case 'toggle-projection':
55
+ controller.setProjection(state.projection === 'perspective' ? 'orthographic' : 'perspective');
56
+ return;
57
+ case 'toggle-textures':
58
+ controller.setTextures(!state.textures);
59
+ return;
60
+ case 'set-shading':
61
+ controller.setShading(action.value);
62
+ return;
63
+ case 'set-scene-theme':
64
+ controller.setSceneTheme(action.value);
65
+ return;
66
+ case 'set-edges':
67
+ controller.setEdges(action.value);
68
+ }
69
+ }
70
+ function displayActionKey(action) {
71
+ return 'value' in action ? `${action.kind}:${action.value}` : action.kind;
72
+ }
73
+ export function SpatialWorkspaceDisplayControl({ actions, buttonProps, controller, renderButton, renderContent, sceneThemeIds, state, ...rootProps }) {
74
+ const resolvedActions = actions ?? createSpatialWorkspaceDisplayActions(sceneThemeIds);
75
+ return (_jsx("div", { ...rootProps, "data-pascal-spatial-workspace-display-control": "", role: "group", children: resolvedActions.map((action) => {
76
+ const active = isSpatialWorkspaceDisplayActionActive(state, action);
77
+ const key = displayActionKey(action);
78
+ const button = (_createElement("button", { ...buttonProps?.(action, active), "aria-pressed": active, "data-pascal-spatial-workspace-display-action": key, key: key, onClick: () => applySpatialWorkspaceDisplayAction(state, controller, action), type: "button" }, renderContent(action, active)));
79
+ return renderButton ? (_jsx(Fragment, { children: renderButton(button, action, active) }, key)) : (button);
80
+ }) }));
81
+ }
@@ -0,0 +1,58 @@
1
+ import { type ComponentPropsWithoutRef, type ReactElement, type ReactNode } from 'react';
2
+ export type SpatialWorkspaceGisMeasurementKind = 'distance' | 'area' | 'perimeter';
3
+ export type SpatialWorkspaceGisAction = {
4
+ kind: 'toggle-world';
5
+ } | {
6
+ kind: 'toggle-surface';
7
+ } | {
8
+ kind: 'toggle-buildings';
9
+ } | {
10
+ kind: 'toggle-road-network';
11
+ } | {
12
+ kind: 'start-measurement';
13
+ value: SpatialWorkspaceGisMeasurementKind;
14
+ } | {
15
+ kind: 'cancel-measurement';
16
+ };
17
+ export type SpatialWorkspaceGisState = {
18
+ buildings: boolean;
19
+ measurement: SpatialWorkspaceGisMeasurementKind | null;
20
+ roadNetwork: boolean;
21
+ surface: boolean;
22
+ world: boolean;
23
+ };
24
+ export type SpatialWorkspaceGisButtonProps = Omit<ComponentPropsWithoutRef<'button'>, 'aria-pressed' | 'children' | 'disabled' | 'onClick' | 'type'> & {
25
+ 'data-pascal-spatial-workspace-gis-action'?: never;
26
+ };
27
+ export type SpatialWorkspaceGisControlProps = Omit<ComponentPropsWithoutRef<'div'>, 'children' | 'role'> & {
28
+ actions?: readonly SpatialWorkspaceGisAction[];
29
+ buttonProps?: (action: SpatialWorkspaceGisAction, active: boolean) => SpatialWorkspaceGisButtonProps | undefined;
30
+ onActionRequest: (action: SpatialWorkspaceGisAction) => void;
31
+ renderButton?: (button: ReactElement, action: SpatialWorkspaceGisAction, active: boolean) => ReactNode;
32
+ renderContent: (action: SpatialWorkspaceGisAction, active: boolean) => ReactNode;
33
+ state: SpatialWorkspaceGisState;
34
+ };
35
+ export declare const SPATIAL_WORKSPACE_GIS_ACTIONS: readonly [{
36
+ readonly kind: "toggle-world";
37
+ }, {
38
+ readonly kind: "toggle-surface";
39
+ }, {
40
+ readonly kind: "toggle-buildings";
41
+ }, {
42
+ readonly kind: "toggle-road-network";
43
+ }, {
44
+ readonly kind: "start-measurement";
45
+ readonly value: "distance";
46
+ }, {
47
+ readonly kind: "start-measurement";
48
+ readonly value: "area";
49
+ }, {
50
+ readonly kind: "start-measurement";
51
+ readonly value: "perimeter";
52
+ }, {
53
+ readonly kind: "cancel-measurement";
54
+ }];
55
+ export declare function spatialWorkspaceGisActionKey(action: SpatialWorkspaceGisAction): string;
56
+ export declare function isSpatialWorkspaceGisActionActive(state: SpatialWorkspaceGisState, action: SpatialWorkspaceGisAction): boolean;
57
+ export declare function SpatialWorkspaceGisControl({ actions, buttonProps, onActionRequest, renderButton, renderContent, state, ...rootProps }: SpatialWorkspaceGisControlProps): import("react").JSX.Element;
58
+ //# sourceMappingURL=spatial-workspace-gis-control.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spatial-workspace-gis-control.d.ts","sourceRoot":"","sources":["../src/spatial-workspace-gis-control.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,wBAAwB,EAAY,KAAK,YAAY,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAElG,MAAM,MAAM,kCAAkC,GAAG,UAAU,GAAG,MAAM,GAAG,WAAW,CAAA;AAElF,MAAM,MAAM,yBAAyB,GACjC;IAAE,IAAI,EAAE,cAAc,CAAA;CAAE,GACxB;IAAE,IAAI,EAAE,gBAAgB,CAAA;CAAE,GAC1B;IAAE,IAAI,EAAE,kBAAkB,CAAA;CAAE,GAC5B;IAAE,IAAI,EAAE,qBAAqB,CAAA;CAAE,GAC/B;IAAE,IAAI,EAAE,mBAAmB,CAAC;IAAC,KAAK,EAAE,kCAAkC,CAAA;CAAE,GACxE;IAAE,IAAI,EAAE,oBAAoB,CAAA;CAAE,CAAA;AAElC,MAAM,MAAM,wBAAwB,GAAG;IACrC,SAAS,EAAE,OAAO,CAAA;IAClB,WAAW,EAAE,kCAAkC,GAAG,IAAI,CAAA;IACtD,WAAW,EAAE,OAAO,CAAA;IACpB,OAAO,EAAE,OAAO,CAAA;IAChB,KAAK,EAAE,OAAO,CAAA;CACf,CAAA;AAED,MAAM,MAAM,8BAA8B,GAAG,IAAI,CAC/C,wBAAwB,CAAC,QAAQ,CAAC,EAClC,cAAc,GAAG,UAAU,GAAG,UAAU,GAAG,SAAS,GAAG,MAAM,CAC9D,GAAG;IACF,0CAA0C,CAAC,EAAE,KAAK,CAAA;CACnD,CAAA;AAED,MAAM,MAAM,+BAA+B,GAAG,IAAI,CAChD,wBAAwB,CAAC,KAAK,CAAC,EAC/B,UAAU,GAAG,MAAM,CACpB,GAAG;IACF,OAAO,CAAC,EAAE,SAAS,yBAAyB,EAAE,CAAA;IAC9C,WAAW,CAAC,EAAE,CACZ,MAAM,EAAE,yBAAyB,EACjC,MAAM,EAAE,OAAO,KACZ,8BAA8B,GAAG,SAAS,CAAA;IAC/C,eAAe,EAAE,CAAC,MAAM,EAAE,yBAAyB,KAAK,IAAI,CAAA;IAC5D,YAAY,CAAC,EAAE,CACb,MAAM,EAAE,YAAY,EACpB,MAAM,EAAE,yBAAyB,EACjC,MAAM,EAAE,OAAO,KACZ,SAAS,CAAA;IACd,aAAa,EAAE,CAAC,MAAM,EAAE,yBAAyB,EAAE,MAAM,EAAE,OAAO,KAAK,SAAS,CAAA;IAChF,KAAK,EAAE,wBAAwB,CAAA;CAChC,CAAA;AAED,eAAO,MAAM,6BAA6B;;;;;;;;;;;;;;;;;;;EASe,CAAA;AAEzD,wBAAgB,4BAA4B,CAAC,MAAM,EAAE,yBAAyB,GAAG,MAAM,CAEtF;AAED,wBAAgB,iCAAiC,CAC/C,KAAK,EAAE,wBAAwB,EAC/B,MAAM,EAAE,yBAAyB,GAChC,OAAO,CAOT;AAED,wBAAgB,0BAA0B,CAAC,EACzC,OAAuC,EACvC,WAAW,EACX,eAAe,EACf,YAAY,EACZ,aAAa,EACb,KAAK,EACL,GAAG,SAAS,EACb,EAAE,+BAA+B,+BA0BjC"}
@@ -0,0 +1,38 @@
1
+ 'use client';
2
+ import { jsx as _jsx } from "react/jsx-runtime";
3
+ import { createElement as _createElement } from "react";
4
+ import { Fragment } from 'react';
5
+ export const SPATIAL_WORKSPACE_GIS_ACTIONS = [
6
+ { kind: 'toggle-world' },
7
+ { kind: 'toggle-surface' },
8
+ { kind: 'toggle-buildings' },
9
+ { kind: 'toggle-road-network' },
10
+ { kind: 'start-measurement', value: 'distance' },
11
+ { kind: 'start-measurement', value: 'area' },
12
+ { kind: 'start-measurement', value: 'perimeter' },
13
+ { kind: 'cancel-measurement' },
14
+ ];
15
+ export function spatialWorkspaceGisActionKey(action) {
16
+ return 'value' in action ? `${action.kind}:${action.value}` : action.kind;
17
+ }
18
+ export function isSpatialWorkspaceGisActionActive(state, action) {
19
+ if (action.kind === 'toggle-world')
20
+ return state.world;
21
+ if (action.kind === 'toggle-surface')
22
+ return state.surface;
23
+ if (action.kind === 'toggle-buildings')
24
+ return state.buildings;
25
+ if (action.kind === 'toggle-road-network')
26
+ return state.roadNetwork;
27
+ if (action.kind === 'start-measurement')
28
+ return state.measurement === action.value;
29
+ return state.measurement !== null;
30
+ }
31
+ export function SpatialWorkspaceGisControl({ actions = SPATIAL_WORKSPACE_GIS_ACTIONS, buttonProps, onActionRequest, renderButton, renderContent, state, ...rootProps }) {
32
+ return (_jsx("div", { ...rootProps, "data-pascal-spatial-workspace-gis-control": "", role: "group", children: actions.map((action) => {
33
+ const active = isSpatialWorkspaceGisActionActive(state, action);
34
+ const key = spatialWorkspaceGisActionKey(action);
35
+ const button = (_createElement("button", { ...buttonProps?.(action, active), "aria-pressed": active, "data-pascal-spatial-workspace-gis-action": key, key: key, onClick: () => onActionRequest(action), type: "button" }, renderContent(action, active)));
36
+ return renderButton ? (_jsx(Fragment, { children: renderButton(button, action, active) }, key)) : (button);
37
+ }) }));
38
+ }
@@ -0,0 +1,2 @@
1
+ export declare function acquireSpatialWorkspaceInstance(): () => void;
2
+ //# sourceMappingURL=spatial-workspace-instance.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spatial-workspace-instance.d.ts","sourceRoot":"","sources":["../src/spatial-workspace-instance.ts"],"names":[],"mappings":"AAEA,wBAAgB,+BAA+B,IAAI,MAAM,IAAI,CAc5D"}
@@ -0,0 +1,14 @@
1
+ let activeSpatialWorkspaceInstances = 0;
2
+ export function acquireSpatialWorkspaceInstance() {
3
+ if (activeSpatialWorkspaceInstances > 0) {
4
+ throw new Error('Only one @ubuilder-ai/workspace instance may be mounted on a page in workspace v1.');
5
+ }
6
+ activeSpatialWorkspaceInstances += 1;
7
+ let released = false;
8
+ return () => {
9
+ if (released)
10
+ return;
11
+ released = true;
12
+ activeSpatialWorkspaceInstances -= 1;
13
+ };
14
+ }
@@ -0,0 +1,21 @@
1
+ import { type ComponentPropsWithoutRef, type MouseEvent, type ReactElement, type ReactNode } from 'react';
2
+ type SpatialWorkspaceDataAttributes = {
3
+ [attribute: `data-${string}`]: boolean | number | string | undefined;
4
+ };
5
+ export type SpatialWorkspaceLevelSelectorButtonProps = Omit<ComponentPropsWithoutRef<'button'>, 'aria-selected' | 'children' | 'disabled' | 'onClick' | 'type'> & SpatialWorkspaceDataAttributes & {
6
+ 'data-pascal-spatial-workspace-level-id'?: never;
7
+ };
8
+ export type SpatialWorkspaceLevelSelectorItem = {
9
+ buttonProps?: SpatialWorkspaceLevelSelectorButtonProps;
10
+ content: ReactNode;
11
+ id: string;
12
+ renderButton?: (button: ReactElement, item: SpatialWorkspaceLevelSelectorItem, active: boolean) => ReactNode;
13
+ };
14
+ export type SpatialWorkspaceLevelSelectorProps = Omit<ComponentPropsWithoutRef<'div'>, 'children' | 'role'> & {
15
+ activeLevelId?: string | null;
16
+ items: readonly SpatialWorkspaceLevelSelectorItem[];
17
+ onLevelRequest: (levelId: string, event: MouseEvent<HTMLButtonElement>) => void;
18
+ };
19
+ export declare function SpatialWorkspaceLevelSelector({ activeLevelId, items, onLevelRequest, ...rootProps }: SpatialWorkspaceLevelSelectorProps): import("react").JSX.Element;
20
+ export {};
21
+ //# sourceMappingURL=spatial-workspace-level-selector.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spatial-workspace-level-selector.d.ts","sourceRoot":"","sources":["../src/spatial-workspace-level-selector.tsx"],"names":[],"mappings":"AAEA,OAAO,EACL,KAAK,wBAAwB,EAE7B,KAAK,UAAU,EACf,KAAK,YAAY,EACjB,KAAK,SAAS,EACf,MAAM,OAAO,CAAA;AAEd,KAAK,8BAA8B,GAAG;IACpC,CAAC,SAAS,EAAE,QAAQ,MAAM,EAAE,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,SAAS,CAAA;CACrE,CAAA;AAED,MAAM,MAAM,wCAAwC,GAAG,IAAI,CACzD,wBAAwB,CAAC,QAAQ,CAAC,EAClC,eAAe,GAAG,UAAU,GAAG,UAAU,GAAG,SAAS,GAAG,MAAM,CAC/D,GACC,8BAA8B,GAAG;IAC/B,wCAAwC,CAAC,EAAE,KAAK,CAAA;CACjD,CAAA;AAEH,MAAM,MAAM,iCAAiC,GAAG;IAC9C,WAAW,CAAC,EAAE,wCAAwC,CAAA;IACtD,OAAO,EAAE,SAAS,CAAA;IAClB,EAAE,EAAE,MAAM,CAAA;IACV,YAAY,CAAC,EAAE,CACb,MAAM,EAAE,YAAY,EACpB,IAAI,EAAE,iCAAiC,EACvC,MAAM,EAAE,OAAO,KACZ,SAAS,CAAA;CACf,CAAA;AAED,MAAM,MAAM,kCAAkC,GAAG,IAAI,CACnD,wBAAwB,CAAC,KAAK,CAAC,EAC/B,UAAU,GAAG,MAAM,CACpB,GAAG;IACF,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC7B,KAAK,EAAE,SAAS,iCAAiC,EAAE,CAAA;IACnD,cAAc,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,CAAC,iBAAiB,CAAC,KAAK,IAAI,CAAA;CAChF,CAAA;AAED,wBAAgB,6BAA6B,CAAC,EAC5C,aAAa,EACb,KAAK,EACL,cAAc,EACd,GAAG,SAAS,EACb,EAAE,kCAAkC,+BA2BpC"}
@@ -0,0 +1,11 @@
1
+ 'use client';
2
+ import { jsx as _jsx } from "react/jsx-runtime";
3
+ import { createElement as _createElement } from "react";
4
+ import { Fragment, } from 'react';
5
+ export function SpatialWorkspaceLevelSelector({ activeLevelId, items, onLevelRequest, ...rootProps }) {
6
+ return (_jsx("div", { ...rootProps, "data-pascal-spatial-workspace-level-selector": "", role: "listbox", children: items.map((item) => {
7
+ const active = item.id === activeLevelId;
8
+ const button = (_createElement("button", { ...item.buttonProps, "aria-selected": active, "data-pascal-spatial-workspace-level-id": item.id, key: item.id, onClick: (event) => onLevelRequest(item.id, event), role: "option", type: "button" }, item.content));
9
+ return item.renderButton ? (_jsx(Fragment, { children: item.renderButton(button, item, active) }, item.id)) : (button);
10
+ }) }));
11
+ }
@@ -0,0 +1,38 @@
1
+ import type { ComponentPropsWithoutRef, MouseEvent, ReactElement, ReactNode } from 'react';
2
+ export type SpatialWorkspaceLevelMode = 'stacked' | 'exploded' | 'solo' | 'manual';
3
+ export type SpatialWorkspaceWallMode = 'cutaway' | 'up' | 'down' | 'translucent';
4
+ export type SpatialWorkspaceCanonicalWallMode = Exclude<SpatialWorkspaceWallMode, 'translucent'>;
5
+ type SpatialWorkspaceDataAttributes = {
6
+ [attribute: `data-${string}`]: boolean | number | string | undefined;
7
+ };
8
+ export type SpatialWorkspaceLevelModeButtonProps = Omit<ComponentPropsWithoutRef<'button'>, 'aria-disabled' | 'children' | 'disabled' | 'onClick' | 'type'> & SpatialWorkspaceDataAttributes & {
9
+ 'data-pascal-spatial-workspace-level-mode'?: never;
10
+ 'data-pascal-spatial-workspace-level-mode-control'?: never;
11
+ };
12
+ export type SpatialWorkspaceWallModeButtonProps = Omit<ComponentPropsWithoutRef<'button'>, 'aria-disabled' | 'children' | 'disabled' | 'onClick' | 'type'> & SpatialWorkspaceDataAttributes & {
13
+ 'data-pascal-spatial-workspace-wall-mode'?: never;
14
+ 'data-pascal-spatial-workspace-wall-mode-control'?: never;
15
+ };
16
+ export type SpatialWorkspaceLevelModeControlProps = {
17
+ buttonProps?: SpatialWorkspaceLevelModeButtonProps;
18
+ content: ReactNode;
19
+ disabled?: boolean;
20
+ mode: SpatialWorkspaceLevelMode;
21
+ onModeRequest: (mode: SpatialWorkspaceLevelMode, event: MouseEvent<HTMLButtonElement>) => void;
22
+ renderButton?: (button: ReactElement, mode: SpatialWorkspaceLevelMode) => ReactNode;
23
+ };
24
+ export type SpatialWorkspaceWallModeControlProps = {
25
+ buttonProps?: SpatialWorkspaceWallModeButtonProps;
26
+ content: ReactNode;
27
+ disabled?: boolean;
28
+ mode: SpatialWorkspaceWallMode;
29
+ onModeRequest: (mode: SpatialWorkspaceCanonicalWallMode, event: MouseEvent<HTMLButtonElement>) => void;
30
+ renderButton?: (button: ReactElement, mode: SpatialWorkspaceCanonicalWallMode) => ReactNode;
31
+ };
32
+ export declare function resolveNextSpatialWorkspaceLevelMode(mode: SpatialWorkspaceLevelMode): SpatialWorkspaceLevelMode;
33
+ export declare function normalizeSpatialWorkspaceWallMode(mode: SpatialWorkspaceWallMode): SpatialWorkspaceCanonicalWallMode;
34
+ export declare function resolveNextSpatialWorkspaceWallMode(mode: SpatialWorkspaceWallMode): SpatialWorkspaceCanonicalWallMode;
35
+ export declare function SpatialWorkspaceLevelModeControl({ buttonProps, content, disabled, mode, onModeRequest, renderButton, }: SpatialWorkspaceLevelModeControlProps): string | number | bigint | boolean | import("react").JSX.Element | Iterable<ReactNode> | Promise<string | number | bigint | boolean | import("react").ReactPortal | ReactElement<unknown, string | import("react").JSXElementConstructor<any>> | Iterable<ReactNode> | null | undefined> | null | undefined;
36
+ export declare function SpatialWorkspaceWallModeControl({ buttonProps, content, disabled, mode, onModeRequest, renderButton, }: SpatialWorkspaceWallModeControlProps): string | number | bigint | boolean | import("react").JSX.Element | Iterable<ReactNode> | Promise<string | number | bigint | boolean | import("react").ReactPortal | ReactElement<unknown, string | import("react").JSXElementConstructor<any>> | Iterable<ReactNode> | null | undefined> | null | undefined;
37
+ export {};
38
+ //# sourceMappingURL=spatial-workspace-level-wall-control.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spatial-workspace-level-wall-control.d.ts","sourceRoot":"","sources":["../src/spatial-workspace-level-wall-control.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,wBAAwB,EAAE,UAAU,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAE1F,MAAM,MAAM,yBAAyB,GAAG,SAAS,GAAG,UAAU,GAAG,MAAM,GAAG,QAAQ,CAAA;AAClF,MAAM,MAAM,wBAAwB,GAAG,SAAS,GAAG,IAAI,GAAG,MAAM,GAAG,aAAa,CAAA;AAChF,MAAM,MAAM,iCAAiC,GAAG,OAAO,CAAC,wBAAwB,EAAE,aAAa,CAAC,CAAA;AAEhG,KAAK,8BAA8B,GAAG;IACpC,CAAC,SAAS,EAAE,QAAQ,MAAM,EAAE,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,SAAS,CAAA;CACrE,CAAA;AAED,MAAM,MAAM,oCAAoC,GAAG,IAAI,CACrD,wBAAwB,CAAC,QAAQ,CAAC,EAClC,eAAe,GAAG,UAAU,GAAG,UAAU,GAAG,SAAS,GAAG,MAAM,CAC/D,GACC,8BAA8B,GAAG;IAC/B,0CAA0C,CAAC,EAAE,KAAK,CAAA;IAClD,kDAAkD,CAAC,EAAE,KAAK,CAAA;CAC3D,CAAA;AAEH,MAAM,MAAM,mCAAmC,GAAG,IAAI,CACpD,wBAAwB,CAAC,QAAQ,CAAC,EAClC,eAAe,GAAG,UAAU,GAAG,UAAU,GAAG,SAAS,GAAG,MAAM,CAC/D,GACC,8BAA8B,GAAG;IAC/B,yCAAyC,CAAC,EAAE,KAAK,CAAA;IACjD,iDAAiD,CAAC,EAAE,KAAK,CAAA;CAC1D,CAAA;AAEH,MAAM,MAAM,qCAAqC,GAAG;IAClD,WAAW,CAAC,EAAE,oCAAoC,CAAA;IAClD,OAAO,EAAE,SAAS,CAAA;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,IAAI,EAAE,yBAAyB,CAAA;IAC/B,aAAa,EAAE,CAAC,IAAI,EAAE,yBAAyB,EAAE,KAAK,EAAE,UAAU,CAAC,iBAAiB,CAAC,KAAK,IAAI,CAAA;IAC9F,YAAY,CAAC,EAAE,CAAC,MAAM,EAAE,YAAY,EAAE,IAAI,EAAE,yBAAyB,KAAK,SAAS,CAAA;CACpF,CAAA;AAED,MAAM,MAAM,oCAAoC,GAAG;IACjD,WAAW,CAAC,EAAE,mCAAmC,CAAA;IACjD,OAAO,EAAE,SAAS,CAAA;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,IAAI,EAAE,wBAAwB,CAAA;IAC9B,aAAa,EAAE,CACb,IAAI,EAAE,iCAAiC,EACvC,KAAK,EAAE,UAAU,CAAC,iBAAiB,CAAC,KACjC,IAAI,CAAA;IACT,YAAY,CAAC,EAAE,CAAC,MAAM,EAAE,YAAY,EAAE,IAAI,EAAE,iCAAiC,KAAK,SAAS,CAAA;CAC5F,CAAA;AAED,wBAAgB,oCAAoC,CAClD,IAAI,EAAE,yBAAyB,GAC9B,yBAAyB,CAK3B;AAED,wBAAgB,iCAAiC,CAC/C,IAAI,EAAE,wBAAwB,GAC7B,iCAAiC,CAEnC;AAED,wBAAgB,mCAAmC,CACjD,IAAI,EAAE,wBAAwB,GAC7B,iCAAiC,CAMnC;AAED,wBAAgB,gCAAgC,CAAC,EAC/C,WAAW,EACX,OAAO,EACP,QAAgB,EAChB,IAAI,EACJ,aAAa,EACb,YAAY,GACb,EAAE,qCAAqC,+SAkBvC;AAED,wBAAgB,+BAA+B,CAAC,EAC9C,WAAW,EACX,OAAO,EACP,QAAgB,EAChB,IAAI,EACJ,aAAa,EACb,YAAY,GACb,EAAE,oCAAoC,+SAmBtC"}
@@ -0,0 +1,41 @@
1
+ 'use client';
2
+ import { jsx as _jsx } from "react/jsx-runtime";
3
+ export function resolveNextSpatialWorkspaceLevelMode(mode) {
4
+ if (mode === 'manual')
5
+ return 'stacked';
6
+ if (mode === 'stacked')
7
+ return 'exploded';
8
+ if (mode === 'exploded')
9
+ return 'solo';
10
+ return 'stacked';
11
+ }
12
+ export function normalizeSpatialWorkspaceWallMode(mode) {
13
+ return mode === 'translucent' ? 'cutaway' : mode;
14
+ }
15
+ export function resolveNextSpatialWorkspaceWallMode(mode) {
16
+ if (mode === 'translucent')
17
+ return 'cutaway';
18
+ const canonicalMode = normalizeSpatialWorkspaceWallMode(mode);
19
+ if (canonicalMode === 'cutaway')
20
+ return 'up';
21
+ if (canonicalMode === 'up')
22
+ return 'down';
23
+ return 'cutaway';
24
+ }
25
+ export function SpatialWorkspaceLevelModeControl({ buttonProps, content, disabled = false, mode, onModeRequest, renderButton, }) {
26
+ const button = (_jsx("button", { ...buttonProps, "aria-disabled": disabled, "data-pascal-spatial-workspace-level-mode": mode, "data-pascal-spatial-workspace-level-mode-control": "", onClick: (event) => {
27
+ if (disabled)
28
+ return;
29
+ onModeRequest(resolveNextSpatialWorkspaceLevelMode(mode), event);
30
+ }, type: "button", children: content }));
31
+ return renderButton ? renderButton(button, mode) : button;
32
+ }
33
+ export function SpatialWorkspaceWallModeControl({ buttonProps, content, disabled = false, mode, onModeRequest, renderButton, }) {
34
+ const canonicalMode = normalizeSpatialWorkspaceWallMode(mode);
35
+ const button = (_jsx("button", { ...buttonProps, "aria-disabled": disabled, "data-pascal-spatial-workspace-wall-mode": canonicalMode, "data-pascal-spatial-workspace-wall-mode-control": "", onClick: (event) => {
36
+ if (disabled)
37
+ return;
38
+ onModeRequest(resolveNextSpatialWorkspaceWallMode(mode), event);
39
+ }, type: "button", children: content }));
40
+ return renderButton ? renderButton(button, canonicalMode) : button;
41
+ }
@@ -0,0 +1,11 @@
1
+ import type { SpatialWorkspaceViewMode } from './spatial-workspace-viewport';
2
+ export type SpatialWorkspaceKind = 'building' | 'site';
3
+ export type SpatialWorkspaceViewPlan = {
4
+ cameraAction: 'set-top-view' | null;
5
+ disabled: boolean;
6
+ nextSiteTopViewActive: boolean;
7
+ viewMode: SpatialWorkspaceViewMode;
8
+ };
9
+ export declare function isBuildingSpatialWorkspace(workspaceKind: SpatialWorkspaceKind): workspaceKind is 'building';
10
+ export declare function resolveSpatialWorkspaceViewPlan(requestedMode: SpatialWorkspaceViewMode, workspaceKind: SpatialWorkspaceKind, siteTopViewActive: boolean): SpatialWorkspaceViewPlan;
11
+ //# sourceMappingURL=spatial-workspace-mode.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spatial-workspace-mode.d.ts","sourceRoot":"","sources":["../src/spatial-workspace-mode.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,8BAA8B,CAAA;AAE5E,MAAM,MAAM,oBAAoB,GAAG,UAAU,GAAG,MAAM,CAAA;AAEtD,MAAM,MAAM,wBAAwB,GAAG;IACrC,YAAY,EAAE,cAAc,GAAG,IAAI,CAAA;IACnC,QAAQ,EAAE,OAAO,CAAA;IACjB,qBAAqB,EAAE,OAAO,CAAA;IAC9B,QAAQ,EAAE,wBAAwB,CAAA;CACnC,CAAA;AAED,wBAAgB,0BAA0B,CACxC,aAAa,EAAE,oBAAoB,GAClC,aAAa,IAAI,UAAU,CAE7B;AAED,wBAAgB,+BAA+B,CAC7C,aAAa,EAAE,wBAAwB,EACvC,aAAa,EAAE,oBAAoB,EACnC,iBAAiB,EAAE,OAAO,GACzB,wBAAwB,CA2B1B"}
@@ -0,0 +1,29 @@
1
+ export function isBuildingSpatialWorkspace(workspaceKind) {
2
+ return workspaceKind === 'building';
3
+ }
4
+ export function resolveSpatialWorkspaceViewPlan(requestedMode, workspaceKind, siteTopViewActive) {
5
+ if (isBuildingSpatialWorkspace(workspaceKind)) {
6
+ return {
7
+ cameraAction: null,
8
+ disabled: false,
9
+ nextSiteTopViewActive: false,
10
+ viewMode: requestedMode,
11
+ };
12
+ }
13
+ if (requestedMode === 'split') {
14
+ return {
15
+ cameraAction: null,
16
+ disabled: true,
17
+ nextSiteTopViewActive: siteTopViewActive,
18
+ viewMode: '3d',
19
+ };
20
+ }
21
+ return {
22
+ // Site plan presentation stays on the GIS canvas, so each request carries
23
+ // an idempotent camera target rather than toggling the current state.
24
+ cameraAction: 'set-top-view',
25
+ disabled: false,
26
+ nextSiteTopViewActive: requestedMode === '2d',
27
+ viewMode: '3d',
28
+ };
29
+ }
@@ -0,0 +1,3 @@
1
+ export declare const SPATIAL_WORKSPACE_STYLE_TEXT = "\n:where(\n [data-pascal-spatial-workspace-view-mode-control],\n [data-pascal-spatial-workspace-level-selector],\n [data-pascal-spatial-workspace-display-control],\n [data-pascal-spatial-workspace-camera-action-control],\n [data-pascal-spatial-workspace-gis-control]\n) {\n --pascal-workspace-accent: #2563eb;\n --pascal-workspace-accent-contrast: #ffffff;\n --pascal-workspace-border: color-mix(in srgb, currentColor 22%, transparent);\n --pascal-workspace-focus: color-mix(in srgb, var(--pascal-workspace-accent) 72%, white);\n display: flex;\n align-items: center;\n gap: 0.375rem;\n}\n\n:where(\n [data-pascal-spatial-workspace-view-mode-control],\n [data-pascal-spatial-workspace-level-selector],\n [data-pascal-spatial-workspace-display-control],\n [data-pascal-spatial-workspace-camera-action-control],\n [data-pascal-spatial-workspace-gis-control]\n) > button,\n:where(\n [data-pascal-spatial-workspace-level-mode-control],\n [data-pascal-spatial-workspace-wall-mode-control]\n) {\n border-color: var(--pascal-workspace-border, currentColor);\n border-radius: 0.5rem;\n font: inherit;\n}\n\n:where(\n [data-pascal-spatial-workspace-view-mode-control],\n [data-pascal-spatial-workspace-level-selector],\n [data-pascal-spatial-workspace-display-control],\n [data-pascal-spatial-workspace-camera-action-control],\n [data-pascal-spatial-workspace-gis-control]\n) > button[aria-pressed='true'],\n:where([data-pascal-spatial-workspace-level-selector]) > button[aria-selected='true'] {\n box-shadow: inset 0 0 0 1px var(--pascal-workspace-accent, #2563eb);\n}\n\n:where(\n [data-pascal-spatial-workspace-view-mode-control],\n [data-pascal-spatial-workspace-level-selector],\n [data-pascal-spatial-workspace-display-control],\n [data-pascal-spatial-workspace-camera-action-control],\n [data-pascal-spatial-workspace-gis-control]\n) > button:focus-visible,\n:where(\n [data-pascal-spatial-workspace-level-mode-control],\n [data-pascal-spatial-workspace-wall-mode-control]\n):focus-visible {\n outline: 2px solid var(--pascal-workspace-focus, #60a5fa);\n outline-offset: 2px;\n}\n\n:where([data-pascal-spatial-workspace]) {\n isolation: isolate;\n}\n\n:where([data-pascal-workspace-divider]) {\n touch-action: none;\n}\n";
2
+ export declare function SpatialWorkspaceStyles(): import("react").JSX.Element;
3
+ //# sourceMappingURL=spatial-workspace-styles.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spatial-workspace-styles.d.ts","sourceRoot":"","sources":["../src/spatial-workspace-styles.tsx"],"names":[],"mappings":"AAEA,eAAO,MAAM,4BAA4B,stEAkExC,CAAA;AAED,wBAAgB,sBAAsB,gCAErC"}
@@ -0,0 +1,72 @@
1
+ 'use client';
2
+ import { jsx as _jsx } from "react/jsx-runtime";
3
+ export const SPATIAL_WORKSPACE_STYLE_TEXT = `
4
+ :where(
5
+ [data-pascal-spatial-workspace-view-mode-control],
6
+ [data-pascal-spatial-workspace-level-selector],
7
+ [data-pascal-spatial-workspace-display-control],
8
+ [data-pascal-spatial-workspace-camera-action-control],
9
+ [data-pascal-spatial-workspace-gis-control]
10
+ ) {
11
+ --pascal-workspace-accent: #2563eb;
12
+ --pascal-workspace-accent-contrast: #ffffff;
13
+ --pascal-workspace-border: color-mix(in srgb, currentColor 22%, transparent);
14
+ --pascal-workspace-focus: color-mix(in srgb, var(--pascal-workspace-accent) 72%, white);
15
+ display: flex;
16
+ align-items: center;
17
+ gap: 0.375rem;
18
+ }
19
+
20
+ :where(
21
+ [data-pascal-spatial-workspace-view-mode-control],
22
+ [data-pascal-spatial-workspace-level-selector],
23
+ [data-pascal-spatial-workspace-display-control],
24
+ [data-pascal-spatial-workspace-camera-action-control],
25
+ [data-pascal-spatial-workspace-gis-control]
26
+ ) > button,
27
+ :where(
28
+ [data-pascal-spatial-workspace-level-mode-control],
29
+ [data-pascal-spatial-workspace-wall-mode-control]
30
+ ) {
31
+ border-color: var(--pascal-workspace-border, currentColor);
32
+ border-radius: 0.5rem;
33
+ font: inherit;
34
+ }
35
+
36
+ :where(
37
+ [data-pascal-spatial-workspace-view-mode-control],
38
+ [data-pascal-spatial-workspace-level-selector],
39
+ [data-pascal-spatial-workspace-display-control],
40
+ [data-pascal-spatial-workspace-camera-action-control],
41
+ [data-pascal-spatial-workspace-gis-control]
42
+ ) > button[aria-pressed='true'],
43
+ :where([data-pascal-spatial-workspace-level-selector]) > button[aria-selected='true'] {
44
+ box-shadow: inset 0 0 0 1px var(--pascal-workspace-accent, #2563eb);
45
+ }
46
+
47
+ :where(
48
+ [data-pascal-spatial-workspace-view-mode-control],
49
+ [data-pascal-spatial-workspace-level-selector],
50
+ [data-pascal-spatial-workspace-display-control],
51
+ [data-pascal-spatial-workspace-camera-action-control],
52
+ [data-pascal-spatial-workspace-gis-control]
53
+ ) > button:focus-visible,
54
+ :where(
55
+ [data-pascal-spatial-workspace-level-mode-control],
56
+ [data-pascal-spatial-workspace-wall-mode-control]
57
+ ):focus-visible {
58
+ outline: 2px solid var(--pascal-workspace-focus, #60a5fa);
59
+ outline-offset: 2px;
60
+ }
61
+
62
+ :where([data-pascal-spatial-workspace]) {
63
+ isolation: isolate;
64
+ }
65
+
66
+ :where([data-pascal-workspace-divider]) {
67
+ touch-action: none;
68
+ }
69
+ `;
70
+ export function SpatialWorkspaceStyles() {
71
+ return _jsx("style", { "data-pascal-spatial-workspace-styles": "", children: SPATIAL_WORKSPACE_STYLE_TEXT });
72
+ }
@@ -0,0 +1,19 @@
1
+ import { type ComponentPropsWithoutRef, type MouseEvent, type ReactElement, type ReactNode } from 'react';
2
+ import type { SpatialWorkspaceViewMode } from './spatial-workspace-viewport';
3
+ export type SpatialWorkspaceViewModeButtonProps = Omit<ComponentPropsWithoutRef<'button'>, 'aria-disabled' | 'aria-pressed' | 'children' | 'disabled' | 'onClick' | 'type'> & {
4
+ 'data-pascal-spatial-workspace-view-mode'?: never;
5
+ };
6
+ export type SpatialWorkspaceViewModeControlItem = {
7
+ buttonProps?: SpatialWorkspaceViewModeButtonProps;
8
+ content: ReactNode;
9
+ disabled?: boolean;
10
+ mode: SpatialWorkspaceViewMode;
11
+ renderButton?: (button: ReactElement, item: SpatialWorkspaceViewModeControlItem) => ReactNode;
12
+ };
13
+ export interface SpatialWorkspaceViewModeControlProps extends Omit<ComponentPropsWithoutRef<'div'>, 'children' | 'role'> {
14
+ activeMode: SpatialWorkspaceViewMode;
15
+ items: readonly SpatialWorkspaceViewModeControlItem[];
16
+ onModeRequest: (mode: SpatialWorkspaceViewMode, event: MouseEvent<HTMLButtonElement>) => void;
17
+ }
18
+ export declare function SpatialWorkspaceViewModeControl({ activeMode, items, onModeRequest, ...rootProps }: SpatialWorkspaceViewModeControlProps): import("react").JSX.Element;
19
+ //# sourceMappingURL=spatial-workspace-view-mode-control.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spatial-workspace-view-mode-control.d.ts","sourceRoot":"","sources":["../src/spatial-workspace-view-mode-control.tsx"],"names":[],"mappings":"AAEA,OAAO,EACL,KAAK,wBAAwB,EAE7B,KAAK,UAAU,EACf,KAAK,YAAY,EACjB,KAAK,SAAS,EACf,MAAM,OAAO,CAAA;AACd,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,8BAA8B,CAAA;AAE5E,MAAM,MAAM,mCAAmC,GAAG,IAAI,CACpD,wBAAwB,CAAC,QAAQ,CAAC,EAClC,eAAe,GAAG,cAAc,GAAG,UAAU,GAAG,UAAU,GAAG,SAAS,GAAG,MAAM,CAChF,GAAG;IACF,yCAAyC,CAAC,EAAE,KAAK,CAAA;CAClD,CAAA;AAED,MAAM,MAAM,mCAAmC,GAAG;IAChD,WAAW,CAAC,EAAE,mCAAmC,CAAA;IACjD,OAAO,EAAE,SAAS,CAAA;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,IAAI,EAAE,wBAAwB,CAAA;IAC9B,YAAY,CAAC,EAAE,CAAC,MAAM,EAAE,YAAY,EAAE,IAAI,EAAE,mCAAmC,KAAK,SAAS,CAAA;CAC9F,CAAA;AAED,MAAM,WAAW,oCACf,SAAQ,IAAI,CAAC,wBAAwB,CAAC,KAAK,CAAC,EAAE,UAAU,GAAG,MAAM,CAAC;IAClE,UAAU,EAAE,wBAAwB,CAAA;IACpC,KAAK,EAAE,SAAS,mCAAmC,EAAE,CAAA;IACrD,aAAa,EAAE,CAAC,IAAI,EAAE,wBAAwB,EAAE,KAAK,EAAE,UAAU,CAAC,iBAAiB,CAAC,KAAK,IAAI,CAAA;CAC9F;AAED,wBAAgB,+BAA+B,CAAC,EAC9C,UAAU,EACV,KAAK,EACL,aAAa,EACb,GAAG,SAAS,EACb,EAAE,oCAAoC,+BA6BtC"}
@@ -0,0 +1,14 @@
1
+ 'use client';
2
+ import { jsx as _jsx } from "react/jsx-runtime";
3
+ import { createElement as _createElement } from "react";
4
+ import { Fragment, } from 'react';
5
+ export function SpatialWorkspaceViewModeControl({ activeMode, items, onModeRequest, ...rootProps }) {
6
+ return (_jsx("div", { ...rootProps, "data-pascal-spatial-workspace-view-mode-control": "", role: "group", children: items.map((item) => {
7
+ const button = (_createElement("button", { ...item.buttonProps, "aria-disabled": item.disabled ?? false, "aria-pressed": activeMode === item.mode, "data-pascal-spatial-workspace-view-mode": item.mode, key: item.mode, onClick: (event) => {
8
+ if (item.disabled)
9
+ return;
10
+ onModeRequest(item.mode, event);
11
+ }, type: "button" }, item.content));
12
+ return item.renderButton ? (_jsx(Fragment, { children: item.renderButton(button, item) }, item.mode)) : (button);
13
+ }) }));
14
+ }
@@ -0,0 +1,25 @@
1
+ import { type ComponentPropsWithoutRef, type ReactNode, type RefObject } from 'react';
2
+ export type SpatialWorkspaceViewMode = '3d' | '2d' | 'split';
3
+ export type SpatialWorkspaceRenderContext = {
4
+ show2d: boolean;
5
+ show3d: boolean;
6
+ viewerPaneRef: RefObject<HTMLDivElement | null>;
7
+ workspaceElement: HTMLDivElement | null;
8
+ };
9
+ type SpatialWorkspaceSurface = ReactNode | ((context: SpatialWorkspaceRenderContext) => ReactNode);
10
+ export interface SpatialWorkspaceViewportProps extends Omit<ComponentPropsWithoutRef<'div'>, 'children'> {
11
+ children?: ReactNode;
12
+ floorplan: SpatialWorkspaceSurface;
13
+ floorplanPaneRatio: number;
14
+ onFloorplanPaneRatioChange: (ratio: number) => void;
15
+ viewMode: SpatialWorkspaceViewMode;
16
+ viewer: SpatialWorkspaceSurface;
17
+ }
18
+ export declare function clampSpatialWorkspacePaneRatio(ratio: number): number;
19
+ export declare function resolveSpatialWorkspacePaneVisibility(viewMode: SpatialWorkspaceViewMode): {
20
+ show2d: boolean;
21
+ show3d: boolean;
22
+ };
23
+ export declare function SpatialWorkspaceViewport({ children, className, floorplan, floorplanPaneRatio, onFloorplanPaneRatioChange, viewMode, viewer, ...rootProps }: SpatialWorkspaceViewportProps): import("react").JSX.Element;
24
+ export {};
25
+ //# sourceMappingURL=spatial-workspace-viewport.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spatial-workspace-viewport.d.ts","sourceRoot":"","sources":["../src/spatial-workspace-viewport.tsx"],"names":[],"mappings":"AAEA,OAAO,EACL,KAAK,wBAAwB,EAC7B,KAAK,SAAS,EACd,KAAK,SAAS,EAKf,MAAM,OAAO,CAAA;AAId,MAAM,MAAM,wBAAwB,GAAG,IAAI,GAAG,IAAI,GAAG,OAAO,CAAA;AAE5D,MAAM,MAAM,6BAA6B,GAAG;IAC1C,MAAM,EAAE,OAAO,CAAA;IACf,MAAM,EAAE,OAAO,CAAA;IACf,aAAa,EAAE,SAAS,CAAC,cAAc,GAAG,IAAI,CAAC,CAAA;IAC/C,gBAAgB,EAAE,cAAc,GAAG,IAAI,CAAA;CACxC,CAAA;AAED,KAAK,uBAAuB,GAAG,SAAS,GAAG,CAAC,CAAC,OAAO,EAAE,6BAA6B,KAAK,SAAS,CAAC,CAAA;AAElG,MAAM,WAAW,6BACf,SAAQ,IAAI,CAAC,wBAAwB,CAAC,KAAK,CAAC,EAAE,UAAU,CAAC;IACzD,QAAQ,CAAC,EAAE,SAAS,CAAA;IACpB,SAAS,EAAE,uBAAuB,CAAA;IAClC,kBAAkB,EAAE,MAAM,CAAA;IAC1B,0BAA0B,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IACnD,QAAQ,EAAE,wBAAwB,CAAA;IAClC,MAAM,EAAE,uBAAuB,CAAA;CAChC;AAKD,wBAAgB,8BAA8B,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEpE;AAED,wBAAgB,qCAAqC,CAAC,QAAQ,EAAE,wBAAwB;;;EAKvF;AASD,wBAAgB,wBAAwB,CAAC,EACvC,QAAQ,EACR,SAAS,EACT,SAAS,EACT,kBAAkB,EAClB,0BAA0B,EAC1B,QAAQ,EACR,MAAM,EACN,GAAG,SAAS,EACb,EAAE,6BAA6B,+BAoG/B"}
@@ -0,0 +1,75 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { useCallback, useEffect, useRef, useState, } from 'react';
4
+ import { acquireSpatialWorkspaceInstance } from './spatial-workspace-instance';
5
+ import { SpatialWorkspaceStyles } from './spatial-workspace-styles';
6
+ const MIN_FLOORPLAN_PANE_RATIO = 0.15;
7
+ const MAX_FLOORPLAN_PANE_RATIO = 0.85;
8
+ export function clampSpatialWorkspacePaneRatio(ratio) {
9
+ return Math.max(MIN_FLOORPLAN_PANE_RATIO, Math.min(MAX_FLOORPLAN_PANE_RATIO, ratio));
10
+ }
11
+ export function resolveSpatialWorkspacePaneVisibility(viewMode) {
12
+ return {
13
+ show2d: viewMode === '2d' || viewMode === 'split',
14
+ show3d: viewMode === '3d' || viewMode === 'split',
15
+ };
16
+ }
17
+ function renderSurface(surface, context) {
18
+ return typeof surface === 'function' ? surface(context) : surface;
19
+ }
20
+ export function SpatialWorkspaceViewport({ children, className, floorplan, floorplanPaneRatio, onFloorplanPaneRatioChange, viewMode, viewer, ...rootProps }) {
21
+ const workspaceRef = useRef(null);
22
+ const viewerPaneRef = useRef(null);
23
+ const [workspaceElement, setWorkspaceElement] = useState(null);
24
+ const isResizingFloorplan = useRef(false);
25
+ const setWorkspaceNode = useCallback((element) => {
26
+ workspaceRef.current = element;
27
+ setWorkspaceElement(element);
28
+ }, []);
29
+ const stopFloorplanResize = useCallback(() => {
30
+ isResizingFloorplan.current = false;
31
+ document.body.style.cursor = '';
32
+ document.body.style.userSelect = '';
33
+ }, []);
34
+ const handleFloorplanDividerDown = useCallback((event) => {
35
+ event.preventDefault();
36
+ isResizingFloorplan.current = true;
37
+ document.body.style.cursor = 'col-resize';
38
+ document.body.style.userSelect = 'none';
39
+ }, []);
40
+ useEffect(() => acquireSpatialWorkspaceInstance(), []);
41
+ useEffect(() => {
42
+ const handlePointerMove = (event) => {
43
+ if (!isResizingFloorplan.current)
44
+ return;
45
+ const workspace = workspaceRef.current;
46
+ if (!workspace)
47
+ return;
48
+ const rect = workspace.getBoundingClientRect();
49
+ if (rect.width <= 0)
50
+ return;
51
+ const ratio = (event.clientX - rect.left) / rect.width;
52
+ onFloorplanPaneRatioChange(clampSpatialWorkspacePaneRatio(ratio));
53
+ };
54
+ window.addEventListener('pointermove', handlePointerMove);
55
+ window.addEventListener('pointerup', stopFloorplanResize);
56
+ return () => {
57
+ window.removeEventListener('pointermove', handlePointerMove);
58
+ window.removeEventListener('pointerup', stopFloorplanResize);
59
+ stopFloorplanResize();
60
+ };
61
+ }, [onFloorplanPaneRatioChange, stopFloorplanResize]);
62
+ const { show2d, show3d } = resolveSpatialWorkspacePaneVisibility(viewMode);
63
+ const renderContext = { show2d, show3d, viewerPaneRef, workspaceElement };
64
+ return (_jsxs("div", { ...rootProps, className: `relative flex h-full${className ? ` ${className}` : ''}`, "data-pascal-spatial-workspace": "", ref: setWorkspaceNode, children: [_jsx(SpatialWorkspaceStyles, {}), children, _jsxs("div", { className: "relative h-full flex-shrink-0", "data-pascal-workspace-pane": "2d", style: {
65
+ width: viewMode === '2d' ? '100%' : `${floorplanPaneRatio * 100}%`,
66
+ display: show2d ? undefined : 'none',
67
+ }, children: [_jsx("div", { className: "h-full w-full overflow-hidden", children: renderSurface(floorplan, renderContext) }), viewMode === 'split' ? (_jsx("div", { className: "absolute inset-y-0 -right-3 z-10 flex w-6 cursor-col-resize items-center justify-center", "data-pascal-workspace-divider": "", onPointerDown: handleFloorplanDividerDown, children: _jsx("div", { className: "h-8 w-1 rounded-full bg-neutral-400" }) })) : null] }), _jsx("div", { "aria-hidden": !show3d || undefined, className: "relative min-w-0 flex-1 overflow-hidden", "data-pascal-workspace-pane": "3d", "data-viewer-3d-pane": "", ref: viewerPaneRef, style: show3d
68
+ ? undefined
69
+ : {
70
+ inset: 0,
71
+ pointerEvents: 'none',
72
+ position: 'absolute',
73
+ visibility: 'hidden',
74
+ }, children: renderSurface(viewer, renderContext) })] }));
75
+ }