@ubuilder-ai/workspace 0.0.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 (74) 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 +1212 -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 +21 -0
  39. package/dist/index.d.ts.map +1 -0
  40. package/dist/index.js +19 -0
  41. package/dist/marquee-geometry.d.ts +22 -0
  42. package/dist/marquee-geometry.d.ts.map +1 -0
  43. package/dist/marquee-geometry.js +151 -0
  44. package/dist/spatial-workspace-camera-action-control.d.ts +18 -0
  45. package/dist/spatial-workspace-camera-action-control.d.ts.map +1 -0
  46. package/dist/spatial-workspace-camera-action-control.js +13 -0
  47. package/dist/spatial-workspace-display-control.d.ts +64 -0
  48. package/dist/spatial-workspace-display-control.d.ts.map +1 -0
  49. package/dist/spatial-workspace-display-control.js +81 -0
  50. package/dist/spatial-workspace-gis-control.d.ts +58 -0
  51. package/dist/spatial-workspace-gis-control.d.ts.map +1 -0
  52. package/dist/spatial-workspace-gis-control.js +38 -0
  53. package/dist/spatial-workspace-instance.d.ts +2 -0
  54. package/dist/spatial-workspace-instance.d.ts.map +1 -0
  55. package/dist/spatial-workspace-instance.js +14 -0
  56. package/dist/spatial-workspace-level-selector.d.ts +25 -0
  57. package/dist/spatial-workspace-level-selector.d.ts.map +1 -0
  58. package/dist/spatial-workspace-level-selector.js +18 -0
  59. package/dist/spatial-workspace-level-wall-control.d.ts +38 -0
  60. package/dist/spatial-workspace-level-wall-control.d.ts.map +1 -0
  61. package/dist/spatial-workspace-level-wall-control.js +43 -0
  62. package/dist/spatial-workspace-mode.d.ts +11 -0
  63. package/dist/spatial-workspace-mode.d.ts.map +1 -0
  64. package/dist/spatial-workspace-mode.js +29 -0
  65. package/dist/spatial-workspace-styles.d.ts +3 -0
  66. package/dist/spatial-workspace-styles.d.ts.map +1 -0
  67. package/dist/spatial-workspace-styles.js +72 -0
  68. package/dist/spatial-workspace-view-mode-control.d.ts +19 -0
  69. package/dist/spatial-workspace-view-mode-control.d.ts.map +1 -0
  70. package/dist/spatial-workspace-view-mode-control.js +14 -0
  71. package/dist/spatial-workspace-viewport.d.ts +25 -0
  72. package/dist/spatial-workspace-viewport.d.ts.map +1 -0
  73. package/dist/spatial-workspace-viewport.js +106 -0
  74. package/package.json +47 -0
@@ -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, style, ...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,KAAK,EACL,GAAG,SAAS,EACb,EAAE,6BAA6B,+BAyI/B"}
@@ -0,0 +1,106 @@
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, style, ...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, style: {
65
+ position: 'relative',
66
+ display: 'flex',
67
+ width: '100%',
68
+ height: '100%',
69
+ minWidth: 0,
70
+ minHeight: 0,
71
+ overflow: 'hidden',
72
+ ...style,
73
+ }, 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: {
74
+ position: 'relative',
75
+ flexShrink: 0,
76
+ height: '100%',
77
+ minHeight: 0,
78
+ width: viewMode === '2d' ? '100%' : `${floorplanPaneRatio * 100}%`,
79
+ display: show2d ? undefined : 'none',
80
+ }, children: [_jsx("div", { className: "h-full w-full overflow-hidden", style: { height: '100%', width: '100%', 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": "", style: {
81
+ position: 'absolute',
82
+ top: 0,
83
+ bottom: 0,
84
+ right: -12,
85
+ zIndex: 10,
86
+ width: 24,
87
+ display: 'flex',
88
+ cursor: 'col-resize',
89
+ alignItems: 'center',
90
+ justifyContent: 'center',
91
+ }, onPointerDown: handleFloorplanDividerDown, children: _jsx("div", { className: "h-8 w-1 rounded-full bg-neutral-400", style: { width: 4, height: 32, borderRadius: 4, background: '#a3a3a3' } }) })) : 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: {
92
+ position: 'relative',
93
+ flex: 1,
94
+ minWidth: 0,
95
+ height: '100%',
96
+ overflow: 'hidden',
97
+ ...(!show3d
98
+ ? {
99
+ inset: 0,
100
+ pointerEvents: 'none',
101
+ position: 'absolute',
102
+ visibility: 'hidden',
103
+ }
104
+ : {}),
105
+ }, children: renderSurface(viewer, renderContext) })] }));
106
+ }
package/package.json ADDED
@@ -0,0 +1,47 @@
1
+ {
2
+ "name": "@ubuilder-ai/workspace",
3
+ "version": "0.0.1",
4
+ "description": "Shared read-only spatial workbench for uBuilder-AI Building and Site experiences",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.js",
12
+ "default": "./dist/index.js"
13
+ }
14
+ },
15
+ "files": [
16
+ "dist",
17
+ "README.md"
18
+ ],
19
+ "scripts": {
20
+ "build": "tsc --build",
21
+ "check-types": "tsgo --noEmit",
22
+ "test": "bun test",
23
+ "prepublishOnly": "bun run build && bun test"
24
+ },
25
+ "peerDependencies": {
26
+ "@ubuilder-ai/core": "0.0.1",
27
+ "react": "^18 || ^19",
28
+ "react-dom": "^18 || ^19"
29
+ },
30
+ "dependencies": {
31
+ "@ubuilder-ai/floorplan-contract": "0.0.1"
32
+ },
33
+ "devDependencies": {
34
+ "@ubuilder-ai/core": "0.0.1",
35
+ "@ubuilder-ai/typescript-config": "*",
36
+ "@types/bun": "^1.3.0",
37
+ "@types/react": "19.2.2",
38
+ "@types/react-dom": "19.2.2",
39
+ "typescript": "6.0.3"
40
+ },
41
+ "repository": {
42
+ "type": "git",
43
+ "url": "https://github.com/JimmyZheng-ZJU/uBuilder-AI.git",
44
+ "directory": "packages/workspace"
45
+ },
46
+ "license": "MIT"
47
+ }