@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.
- package/README.md +7 -0
- package/dist/floorplan-annotation-obstacles.d.ts +4 -0
- package/dist/floorplan-annotation-obstacles.d.ts.map +1 -0
- package/dist/floorplan-annotation-obstacles.js +25 -0
- package/dist/floorplan-camera-sync.d.ts +24 -0
- package/dist/floorplan-camera-sync.d.ts.map +1 -0
- package/dist/floorplan-camera-sync.js +187 -0
- package/dist/floorplan-coordinates.d.ts +10 -0
- package/dist/floorplan-coordinates.d.ts.map +1 -0
- package/dist/floorplan-coordinates.js +25 -0
- package/dist/floorplan-dimension-renderer.d.ts +42 -0
- package/dist/floorplan-dimension-renderer.d.ts.map +1 -0
- package/dist/floorplan-dimension-renderer.js +245 -0
- package/dist/floorplan-geometry-renderer.d.ts +56 -0
- package/dist/floorplan-geometry-renderer.d.ts.map +1 -0
- package/dist/floorplan-geometry-renderer.js +319 -0
- package/dist/floorplan-initial-view.d.ts +29 -0
- package/dist/floorplan-initial-view.d.ts.map +1 -0
- package/dist/floorplan-initial-view.js +30 -0
- package/dist/floorplan-label-angle.d.ts +24 -0
- package/dist/floorplan-label-angle.d.ts.map +1 -0
- package/dist/floorplan-label-angle.js +60 -0
- package/dist/floorplan-navigation-presentation.d.ts +57 -0
- package/dist/floorplan-navigation-presentation.d.ts.map +1 -0
- package/dist/floorplan-navigation-presentation.js +81 -0
- package/dist/floorplan-navigation-shell.d.ts +87 -0
- package/dist/floorplan-navigation-shell.d.ts.map +1 -0
- package/dist/floorplan-navigation-shell.js +1212 -0
- package/dist/floorplan-navigation-types.d.ts +10 -0
- package/dist/floorplan-navigation-types.d.ts.map +1 -0
- package/dist/floorplan-navigation-types.js +1 -0
- package/dist/floorplan-registry-projection.d.ts +84 -0
- package/dist/floorplan-registry-projection.d.ts.map +1 -0
- package/dist/floorplan-registry-projection.js +260 -0
- package/dist/floorplan-render-context.d.ts +56 -0
- package/dist/floorplan-render-context.d.ts.map +1 -0
- package/dist/floorplan-render-context.js +75 -0
- package/dist/index.d.ts +21 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +19 -0
- package/dist/marquee-geometry.d.ts +22 -0
- package/dist/marquee-geometry.d.ts.map +1 -0
- package/dist/marquee-geometry.js +151 -0
- package/dist/spatial-workspace-camera-action-control.d.ts +18 -0
- package/dist/spatial-workspace-camera-action-control.d.ts.map +1 -0
- package/dist/spatial-workspace-camera-action-control.js +13 -0
- package/dist/spatial-workspace-display-control.d.ts +64 -0
- package/dist/spatial-workspace-display-control.d.ts.map +1 -0
- package/dist/spatial-workspace-display-control.js +81 -0
- package/dist/spatial-workspace-gis-control.d.ts +58 -0
- package/dist/spatial-workspace-gis-control.d.ts.map +1 -0
- package/dist/spatial-workspace-gis-control.js +38 -0
- package/dist/spatial-workspace-instance.d.ts +2 -0
- package/dist/spatial-workspace-instance.d.ts.map +1 -0
- package/dist/spatial-workspace-instance.js +14 -0
- package/dist/spatial-workspace-level-selector.d.ts +25 -0
- package/dist/spatial-workspace-level-selector.d.ts.map +1 -0
- package/dist/spatial-workspace-level-selector.js +18 -0
- package/dist/spatial-workspace-level-wall-control.d.ts +38 -0
- package/dist/spatial-workspace-level-wall-control.d.ts.map +1 -0
- package/dist/spatial-workspace-level-wall-control.js +43 -0
- package/dist/spatial-workspace-mode.d.ts +11 -0
- package/dist/spatial-workspace-mode.d.ts.map +1 -0
- package/dist/spatial-workspace-mode.js +29 -0
- package/dist/spatial-workspace-styles.d.ts +3 -0
- package/dist/spatial-workspace-styles.d.ts.map +1 -0
- package/dist/spatial-workspace-styles.js +72 -0
- package/dist/spatial-workspace-view-mode-control.d.ts +19 -0
- package/dist/spatial-workspace-view-mode-control.d.ts.map +1 -0
- package/dist/spatial-workspace-view-mode-control.js +14 -0
- package/dist/spatial-workspace-viewport.d.ts +25 -0
- package/dist/spatial-workspace-viewport.d.ts.map +1 -0
- package/dist/spatial-workspace-viewport.js +106 -0
- package/package.json +47 -0
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export type FloorplanNavigationSource = '2d' | '3d';
|
|
2
|
+
export type FloorplanNavigationPose = {
|
|
3
|
+
source: FloorplanNavigationSource;
|
|
4
|
+
revision: number;
|
|
5
|
+
target: [number, number, number];
|
|
6
|
+
azimuth: number;
|
|
7
|
+
viewWidth: number;
|
|
8
|
+
};
|
|
9
|
+
export type FloorplanNavigationPoseInput = Omit<FloorplanNavigationPose, 'revision'>;
|
|
10
|
+
//# sourceMappingURL=floorplan-navigation-types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"floorplan-navigation-types.d.ts","sourceRoot":"","sources":["../src/floorplan-navigation-types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,yBAAyB,GAAG,IAAI,GAAG,IAAI,CAAA;AAEnD,MAAM,MAAM,uBAAuB,GAAG;IACpC,MAAM,EAAE,yBAAyB,CAAA;IACjC,QAAQ,EAAE,MAAM,CAAA;IAChB,MAAM,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;IAChC,OAAO,EAAE,MAAM,CAAA;IACf,SAAS,EAAE,MAAM,CAAA;CAClB,CAAA;AAED,MAAM,MAAM,4BAA4B,GAAG,IAAI,CAAC,uBAAuB,EAAE,UAAU,CAAC,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import type { AnyNode, AnyNodeDefinition, AnyNodeId, FloorplanGeometry, FloorplanPalette, GeometryContext } from '@ubuilder-ai/core';
|
|
2
|
+
import { type FloorplanMetricNotation, type FloorplanRenderPurpose, type FloorplanWallDimensionReference } from '@ubuilder-ai/floorplan-contract';
|
|
3
|
+
export type FloorplanDefinitionResolver = (kind: string) => AnyNodeDefinition | undefined;
|
|
4
|
+
export type FloorplanProjectionContext = {
|
|
5
|
+
children: AnyNode[];
|
|
6
|
+
siblings: AnyNode[];
|
|
7
|
+
parent: AnyNode | null;
|
|
8
|
+
};
|
|
9
|
+
export type FloorplanRegistryProjectionEntry = {
|
|
10
|
+
id: AnyNodeId;
|
|
11
|
+
node: AnyNode;
|
|
12
|
+
context?: FloorplanProjectionContext;
|
|
13
|
+
};
|
|
14
|
+
export type FloorplanRegistryProjection = {
|
|
15
|
+
entries: readonly FloorplanRegistryProjectionEntry[];
|
|
16
|
+
levelNodeIdsByType: ReadonlyMap<string, readonly AnyNodeId[]>;
|
|
17
|
+
};
|
|
18
|
+
export type ProjectFloorplanRegistryOptions = {
|
|
19
|
+
nodes: Readonly<Record<string, AnyNode>>;
|
|
20
|
+
activeLevelId: AnyNodeId;
|
|
21
|
+
getDefinition: FloorplanDefinitionResolver;
|
|
22
|
+
isKindEnabled: (kind: string) => boolean;
|
|
23
|
+
includeBuildingScoped: boolean;
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* Stable z-order sort. SVG renders in document order — later siblings
|
|
27
|
+
* paint on top of earlier ones — so anything that should sit under other
|
|
28
|
+
* floor-plan geometry has to declare a lower `floorplanOrder`. Within a
|
|
29
|
+
* layer bucket the original projection order remains stable.
|
|
30
|
+
*/
|
|
31
|
+
export declare function orderFloorplanProjectionEntries<T extends {
|
|
32
|
+
node: AnyNode;
|
|
33
|
+
}>(entries: readonly T[], getDefinition: FloorplanDefinitionResolver): T[];
|
|
34
|
+
export declare function projectFloorplanRegistry({ nodes, activeLevelId, getDefinition, isKindEnabled, includeBuildingScoped, }: ProjectFloorplanRegistryOptions): FloorplanRegistryProjection;
|
|
35
|
+
export type FloorplanGeometryContextViewState = {
|
|
36
|
+
selected: boolean;
|
|
37
|
+
unit: 'metric' | 'imperial';
|
|
38
|
+
metricNotation: FloorplanMetricNotation;
|
|
39
|
+
purpose?: FloorplanRenderPurpose;
|
|
40
|
+
wallDimensionReference?: FloorplanWallDimensionReference;
|
|
41
|
+
highlighted: boolean;
|
|
42
|
+
hovered: boolean;
|
|
43
|
+
moving: boolean;
|
|
44
|
+
palette: FloorplanPalette | undefined;
|
|
45
|
+
};
|
|
46
|
+
export type CreateFloorplanGeometryContextOptions = {
|
|
47
|
+
node: AnyNode;
|
|
48
|
+
nodes: Readonly<Record<string, AnyNode>>;
|
|
49
|
+
viewState: FloorplanGeometryContextViewState;
|
|
50
|
+
context?: FloorplanProjectionContext;
|
|
51
|
+
levelData?: unknown;
|
|
52
|
+
runtimeState?: unknown;
|
|
53
|
+
resolve?: GeometryContext['resolve'];
|
|
54
|
+
};
|
|
55
|
+
export declare function createFloorplanGeometryContext({ node, nodes, viewState, context, levelData, runtimeState, resolve: resolveOverride, }: CreateFloorplanGeometryContextOptions): GeometryContext;
|
|
56
|
+
export declare function computeFloorplanLevelData({ definition, nodeIds, nodes, }: {
|
|
57
|
+
definition: AnyNodeDefinition | undefined;
|
|
58
|
+
nodeIds: readonly AnyNodeId[] | undefined;
|
|
59
|
+
nodes: Readonly<Record<string, AnyNode>>;
|
|
60
|
+
}): unknown;
|
|
61
|
+
/**
|
|
62
|
+
* Walk a `FloorplanGeometry` tree and split it into two trees: one with
|
|
63
|
+
* only "base" primitives (polygons, paths, fills, strokes) and one with
|
|
64
|
+
* only "overlay" primitives (handles, labels — see `OVERLAY_KINDS`).
|
|
65
|
+
*
|
|
66
|
+
* Groups recurse: a `kind: 'group'` is split into a base group and an
|
|
67
|
+
* overlay group, both carrying the same `transform` so nested rotations
|
|
68
|
+
* / translations apply in both passes. Empty groups collapse to `null`
|
|
69
|
+
* so the caller can skip emitting an `<g>` when there's nothing to draw.
|
|
70
|
+
*/
|
|
71
|
+
export declare function splitFloorplanOverlay(geometry: FloorplanGeometry): {
|
|
72
|
+
base: FloorplanGeometry | null;
|
|
73
|
+
overlay: FloorplanGeometry | null;
|
|
74
|
+
};
|
|
75
|
+
export declare function buildFloorplanGeometryPartition({ definition, node, context, transformGeometry, }: {
|
|
76
|
+
definition: AnyNodeDefinition | undefined;
|
|
77
|
+
node: AnyNode;
|
|
78
|
+
context: GeometryContext;
|
|
79
|
+
transformGeometry?: (geometry: FloorplanGeometry) => FloorplanGeometry | null;
|
|
80
|
+
}): {
|
|
81
|
+
base: FloorplanGeometry | null;
|
|
82
|
+
overlay: FloorplanGeometry | null;
|
|
83
|
+
};
|
|
84
|
+
//# sourceMappingURL=floorplan-registry-projection.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"floorplan-registry-projection.d.ts","sourceRoot":"","sources":["../src/floorplan-registry-projection.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
import { createFloorplanContextExtensions, } from '@ubuilder-ai/floorplan-contract';
|
|
2
|
+
import { isFloorplanAnnotationObstacleGeometry } from './floorplan-annotation-obstacles';
|
|
3
|
+
/**
|
|
4
|
+
* Stable z-order sort. SVG renders in document order — later siblings
|
|
5
|
+
* paint on top of earlier ones — so anything that should sit under other
|
|
6
|
+
* floor-plan geometry has to declare a lower `floorplanOrder`. Within a
|
|
7
|
+
* layer bucket the original projection order remains stable.
|
|
8
|
+
*/
|
|
9
|
+
export function orderFloorplanProjectionEntries(entries, getDefinition) {
|
|
10
|
+
return entries
|
|
11
|
+
.map((entry, index) => ({ entry, index }))
|
|
12
|
+
.sort((left, right) => {
|
|
13
|
+
const leftOrder = getDefinition(left.entry.node.type)?.floorplanOrder ?? 2;
|
|
14
|
+
const rightOrder = getDefinition(right.entry.node.type)?.floorplanOrder ?? 2;
|
|
15
|
+
return leftOrder - rightOrder || left.index - right.index;
|
|
16
|
+
})
|
|
17
|
+
.map(({ entry }) => entry);
|
|
18
|
+
}
|
|
19
|
+
function childIdsOf(node) {
|
|
20
|
+
const children = node.children;
|
|
21
|
+
return Array.isArray(children) ? children : [];
|
|
22
|
+
}
|
|
23
|
+
function resolveLevelContainerId(activeLevelId, nodes, getDefinition) {
|
|
24
|
+
const level = nodes[activeLevelId];
|
|
25
|
+
if (!level)
|
|
26
|
+
return null;
|
|
27
|
+
const parentId = level.parentId;
|
|
28
|
+
if (parentId) {
|
|
29
|
+
const parent = nodes[parentId];
|
|
30
|
+
if (parent && getDefinition(parent.type)?.capabilities.floorplanLevelContainer) {
|
|
31
|
+
return parentId;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
for (const candidate of Object.values(nodes)) {
|
|
35
|
+
if (!getDefinition(candidate.type)?.capabilities.floorplanLevelContainer)
|
|
36
|
+
continue;
|
|
37
|
+
if (childIdsOf(candidate).includes(activeLevelId))
|
|
38
|
+
return candidate.id;
|
|
39
|
+
}
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
export function projectFloorplanRegistry({ nodes, activeLevelId, getDefinition, isKindEnabled, includeBuildingScoped, }) {
|
|
43
|
+
if (!nodes[activeLevelId]) {
|
|
44
|
+
return { entries: [], levelNodeIdsByType: new Map() };
|
|
45
|
+
}
|
|
46
|
+
const levelNodeIdsByType = new Map();
|
|
47
|
+
const levelDataVisited = new Set();
|
|
48
|
+
const collectLevelDataIds = (id) => {
|
|
49
|
+
if (levelDataVisited.has(id))
|
|
50
|
+
return;
|
|
51
|
+
levelDataVisited.add(id);
|
|
52
|
+
const node = nodes[id];
|
|
53
|
+
if (!node || !isKindEnabled(node.type))
|
|
54
|
+
return;
|
|
55
|
+
const definition = getDefinition(node.type);
|
|
56
|
+
if (definition?.computeFloorplanLevelData) {
|
|
57
|
+
const ids = levelNodeIdsByType.get(node.type);
|
|
58
|
+
if (ids)
|
|
59
|
+
ids.push(id);
|
|
60
|
+
else
|
|
61
|
+
levelNodeIdsByType.set(node.type, [id]);
|
|
62
|
+
}
|
|
63
|
+
for (const childId of childIdsOf(node))
|
|
64
|
+
collectLevelDataIds(childId);
|
|
65
|
+
};
|
|
66
|
+
collectLevelDataIds(activeLevelId);
|
|
67
|
+
const entries = [];
|
|
68
|
+
const pushEntry = (id, node, context) => {
|
|
69
|
+
if (!isKindEnabled(node.type))
|
|
70
|
+
return;
|
|
71
|
+
entries.push(context ? { id, node, context } : { id, node });
|
|
72
|
+
};
|
|
73
|
+
const entryVisited = new Set();
|
|
74
|
+
const visit = (id) => {
|
|
75
|
+
if (entryVisited.has(id))
|
|
76
|
+
return;
|
|
77
|
+
entryVisited.add(id);
|
|
78
|
+
const node = nodes[id];
|
|
79
|
+
if (!node)
|
|
80
|
+
return;
|
|
81
|
+
pushEntry(id, node);
|
|
82
|
+
for (const childId of childIdsOf(node))
|
|
83
|
+
visit(childId);
|
|
84
|
+
};
|
|
85
|
+
visit(activeLevelId);
|
|
86
|
+
const activeLevel = nodes[activeLevelId];
|
|
87
|
+
const collectedIds = new Set(entries.map((entry) => entry.id));
|
|
88
|
+
for (const node of Object.values(nodes)) {
|
|
89
|
+
const id = node.id;
|
|
90
|
+
if (collectedIds.has(id) || !isKindEnabled(node.type))
|
|
91
|
+
continue;
|
|
92
|
+
const definition = getDefinition(node.type);
|
|
93
|
+
const linkedLevelIds = definition?.floorplanLinkedLevelIds;
|
|
94
|
+
if (!definition?.floorplan || !linkedLevelIds?.(node).includes(activeLevelId))
|
|
95
|
+
continue;
|
|
96
|
+
pushEntry(id, node, {
|
|
97
|
+
children: childIdsOf(node)
|
|
98
|
+
.map((childId) => nodes[childId])
|
|
99
|
+
.filter((child) => child !== undefined),
|
|
100
|
+
siblings: [],
|
|
101
|
+
parent: activeLevel,
|
|
102
|
+
});
|
|
103
|
+
collectedIds.add(id);
|
|
104
|
+
}
|
|
105
|
+
if (includeBuildingScoped) {
|
|
106
|
+
const levelContainerId = resolveLevelContainerId(activeLevelId, nodes, getDefinition);
|
|
107
|
+
if (levelContainerId) {
|
|
108
|
+
for (const node of Object.values(nodes)) {
|
|
109
|
+
const id = node.id;
|
|
110
|
+
if (collectedIds.has(id) || !isKindEnabled(node.type))
|
|
111
|
+
continue;
|
|
112
|
+
const definition = getDefinition(node.type);
|
|
113
|
+
if (definition?.floorplanScope !== 'building')
|
|
114
|
+
continue;
|
|
115
|
+
if (node.parentId !== levelContainerId)
|
|
116
|
+
continue;
|
|
117
|
+
pushEntry(id, node, { children: [], siblings: [], parent: activeLevel });
|
|
118
|
+
collectedIds.add(id);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
return {
|
|
123
|
+
entries,
|
|
124
|
+
levelNodeIdsByType,
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
export function createFloorplanGeometryContext({ node, nodes, viewState, context, levelData, runtimeState, resolve: resolveOverride, }) {
|
|
128
|
+
const resolve = resolveOverride ?? ((id) => nodes[id]);
|
|
129
|
+
let children;
|
|
130
|
+
let siblings;
|
|
131
|
+
let parent;
|
|
132
|
+
if (context) {
|
|
133
|
+
children = context.children;
|
|
134
|
+
siblings = context.siblings;
|
|
135
|
+
parent = context.parent;
|
|
136
|
+
}
|
|
137
|
+
else {
|
|
138
|
+
children = childIdsOf(node)
|
|
139
|
+
.map((childId) => nodes[childId])
|
|
140
|
+
.filter((child) => child !== undefined);
|
|
141
|
+
const parentId = node.parentId;
|
|
142
|
+
parent = parentId ? (nodes[parentId] ?? null) : null;
|
|
143
|
+
siblings = [];
|
|
144
|
+
if (parent) {
|
|
145
|
+
const parentChildren = parent.children;
|
|
146
|
+
if (Array.isArray(parentChildren)) {
|
|
147
|
+
const parentChildIds = parentChildren;
|
|
148
|
+
for (const siblingId of parentChildIds) {
|
|
149
|
+
if (siblingId === node.id)
|
|
150
|
+
continue;
|
|
151
|
+
const sibling = nodes[siblingId];
|
|
152
|
+
if (sibling?.type === node.type)
|
|
153
|
+
siblings.push(sibling);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
else {
|
|
157
|
+
siblings = Object.values(nodes).filter((sibling) => sibling !== node && sibling.type === node.type && sibling.parentId === parentId);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
return {
|
|
162
|
+
resolve,
|
|
163
|
+
children,
|
|
164
|
+
siblings,
|
|
165
|
+
parent,
|
|
166
|
+
levelData,
|
|
167
|
+
extensions: createFloorplanContextExtensions({
|
|
168
|
+
metricNotation: viewState.metricNotation,
|
|
169
|
+
purpose: viewState.purpose ?? 'edit',
|
|
170
|
+
runtimeState,
|
|
171
|
+
wallDimensionReference: viewState.wallDimensionReference,
|
|
172
|
+
}),
|
|
173
|
+
viewState: viewState.palette
|
|
174
|
+
? {
|
|
175
|
+
selected: viewState.selected,
|
|
176
|
+
unit: viewState.unit,
|
|
177
|
+
highlighted: viewState.highlighted,
|
|
178
|
+
hovered: viewState.hovered,
|
|
179
|
+
moving: viewState.moving,
|
|
180
|
+
palette: viewState.palette,
|
|
181
|
+
}
|
|
182
|
+
: undefined,
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
export function computeFloorplanLevelData({ definition, nodeIds, nodes, }) {
|
|
186
|
+
const compute = definition?.computeFloorplanLevelData;
|
|
187
|
+
const kind = definition?.kind;
|
|
188
|
+
if (!compute || !kind || !nodeIds?.length)
|
|
189
|
+
return undefined;
|
|
190
|
+
const siblings = nodeIds
|
|
191
|
+
.map((id) => nodes[id])
|
|
192
|
+
.filter((node) => node?.type === kind);
|
|
193
|
+
return compute({ siblings, nodes: nodes });
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Geometry kinds that always render in the overlay pass — interactive
|
|
197
|
+
* handles and node labels. These need to sit above every kind's base
|
|
198
|
+
* geometry regardless of the owning node's z-bucket so that:
|
|
199
|
+
* - polygon edit handles on a selected slab don't get hidden by the
|
|
200
|
+
* walls / items resting on top of the slab,
|
|
201
|
+
* - a zone's name stays legible above the slab covering the zone, and
|
|
202
|
+
* - measurement labels never get clipped by structural fills.
|
|
203
|
+
*/
|
|
204
|
+
const OVERLAY_KINDS = new Set([
|
|
205
|
+
'text',
|
|
206
|
+
'endpoint-handle',
|
|
207
|
+
'midpoint-handle',
|
|
208
|
+
'edge-handle',
|
|
209
|
+
'move-handle',
|
|
210
|
+
'move-arrow',
|
|
211
|
+
'rotate-arrow',
|
|
212
|
+
'dimension',
|
|
213
|
+
'dimension-string',
|
|
214
|
+
'dimension-label',
|
|
215
|
+
'equal-spacing-badge',
|
|
216
|
+
]);
|
|
217
|
+
/**
|
|
218
|
+
* Walk a `FloorplanGeometry` tree and split it into two trees: one with
|
|
219
|
+
* only "base" primitives (polygons, paths, fills, strokes) and one with
|
|
220
|
+
* only "overlay" primitives (handles, labels — see `OVERLAY_KINDS`).
|
|
221
|
+
*
|
|
222
|
+
* Groups recurse: a `kind: 'group'` is split into a base group and an
|
|
223
|
+
* overlay group, both carrying the same `transform` so nested rotations
|
|
224
|
+
* / translations apply in both passes. Empty groups collapse to `null`
|
|
225
|
+
* so the caller can skip emitting an `<g>` when there's nothing to draw.
|
|
226
|
+
*/
|
|
227
|
+
export function splitFloorplanOverlay(geometry) {
|
|
228
|
+
if (isFloorplanAnnotationObstacleGeometry(geometry)) {
|
|
229
|
+
return { base: null, overlay: geometry };
|
|
230
|
+
}
|
|
231
|
+
if (OVERLAY_KINDS.has(geometry.kind)) {
|
|
232
|
+
return { base: null, overlay: geometry };
|
|
233
|
+
}
|
|
234
|
+
if (geometry.kind === 'group') {
|
|
235
|
+
const baseChildren = [];
|
|
236
|
+
const overlayChildren = [];
|
|
237
|
+
for (const child of geometry.children) {
|
|
238
|
+
const split = splitFloorplanOverlay(child);
|
|
239
|
+
if (split.base)
|
|
240
|
+
baseChildren.push(split.base);
|
|
241
|
+
if (split.overlay)
|
|
242
|
+
overlayChildren.push(split.overlay);
|
|
243
|
+
}
|
|
244
|
+
return {
|
|
245
|
+
base: baseChildren.length > 0
|
|
246
|
+
? { kind: 'group', children: baseChildren, transform: geometry.transform }
|
|
247
|
+
: null,
|
|
248
|
+
overlay: overlayChildren.length > 0
|
|
249
|
+
? { kind: 'group', children: overlayChildren, transform: geometry.transform }
|
|
250
|
+
: null,
|
|
251
|
+
};
|
|
252
|
+
}
|
|
253
|
+
return { base: geometry, overlay: null };
|
|
254
|
+
}
|
|
255
|
+
export function buildFloorplanGeometryPartition({ definition, node, context, transformGeometry, }) {
|
|
256
|
+
const builder = definition?.floorplan;
|
|
257
|
+
const geometry = builder?.(node, context) ?? null;
|
|
258
|
+
const transformed = geometry && transformGeometry ? transformGeometry(geometry) : geometry;
|
|
259
|
+
return transformed ? splitFloorplanOverlay(transformed) : { base: null, overlay: null };
|
|
260
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import type { FloorplanPalette } from '@ubuilder-ai/core';
|
|
2
|
+
import { type ReactNode } from 'react';
|
|
3
|
+
/**
|
|
4
|
+
* Per-frame render context shared between a host floorplan surface
|
|
5
|
+
* and its registry-driven scene renderer.
|
|
6
|
+
*
|
|
7
|
+
* The host is the authoritative owner of the floor-plan SVG —
|
|
8
|
+
* it computes `unitsPerPixel` from the viewBox / surface size, mounts the
|
|
9
|
+
* pan/zoom `<g>`, and knows the active theme. The scene renderer is mounted
|
|
10
|
+
* inside the same `<g>`, so anything it draws shares the same coordinate
|
|
11
|
+
* system; this context plumbs through the bits it can't recompute on its
|
|
12
|
+
* own without re-implementing the legacy's resize / theme logic.
|
|
13
|
+
*
|
|
14
|
+
*/
|
|
15
|
+
export type FloorplanRenderContextValue = {
|
|
16
|
+
/** SVG units per screen pixel — used to keep handle radii consistent at any zoom. */
|
|
17
|
+
unitsPerPixel: number;
|
|
18
|
+
/** Themed palette mirroring the host `FloorplanPalette` accent slots. */
|
|
19
|
+
palette: FloorplanPalette;
|
|
20
|
+
/** SVG `<pattern>` id mounted in `<defs>` by the host for hatch fills. */
|
|
21
|
+
hatchPatternId: string;
|
|
22
|
+
/**
|
|
23
|
+
* Rotation (degrees) applied to the registry layer's parent `<g>` by the
|
|
24
|
+
* host surface — 90° by default, adjusted by building rotation. Renderers
|
|
25
|
+
* that emit text labels use this to keep their final on-screen orientation
|
|
26
|
+
* readable instead of mirroring whatever the parent rotation is.
|
|
27
|
+
*/
|
|
28
|
+
sceneRotationDeg: number;
|
|
29
|
+
};
|
|
30
|
+
export type FloorplanStaticRenderContextValue = Omit<FloorplanRenderContextValue, 'sceneRotationDeg' | 'unitsPerPixel'> & {
|
|
31
|
+
getSceneRotationDeg: () => number;
|
|
32
|
+
getUnitsPerPixel: () => number;
|
|
33
|
+
subscribeUnitsPerPixel: (listener: () => void) => () => void;
|
|
34
|
+
};
|
|
35
|
+
export type FloorplanRenderScaleReference = {
|
|
36
|
+
read: () => number;
|
|
37
|
+
subscribe: (listener: () => void) => () => void;
|
|
38
|
+
update: (unitsPerPixel: number) => void;
|
|
39
|
+
};
|
|
40
|
+
export declare function createFloorplanRenderScaleReference(initialUnitsPerPixel: number): FloorplanRenderScaleReference;
|
|
41
|
+
export declare function FloorplanRenderProvider({ children, unitsPerPixel, palette, hatchPatternId, sceneRotationDeg, getSceneRotationDeg, }: FloorplanRenderContextValue & {
|
|
42
|
+
children: ReactNode;
|
|
43
|
+
getSceneRotationDeg: () => number;
|
|
44
|
+
}): import("react").JSX.Element;
|
|
45
|
+
/**
|
|
46
|
+
* Read the active render context. Returns `null` when called outside a
|
|
47
|
+
* provider — consumers treat this as "render statically, skip
|
|
48
|
+
* theme-aware chrome and interactive handles". This makes the layer
|
|
49
|
+
* usable in isolation tests + future editor shells without bringing the
|
|
50
|
+
* whole host surface along.
|
|
51
|
+
*/
|
|
52
|
+
export declare function useFloorplanRender(): FloorplanRenderContextValue | null;
|
|
53
|
+
export declare function useFloorplanStaticRender(): FloorplanStaticRenderContextValue | null;
|
|
54
|
+
export declare function useFloorplanStaticUnitsPerPixel(): number;
|
|
55
|
+
export declare function useFloorplanSceneRotation(): number;
|
|
56
|
+
//# sourceMappingURL=floorplan-render-context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"floorplan-render-context.d.ts","sourceRoot":"","sources":["../src/floorplan-render-context.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAA;AACzD,OAAO,EAEL,KAAK,SAAS,EAMf,MAAM,OAAO,CAAA;AAEd;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,2BAA2B,GAAG;IACxC,qFAAqF;IACrF,aAAa,EAAE,MAAM,CAAA;IACrB,yEAAyE;IACzE,OAAO,EAAE,gBAAgB,CAAA;IACzB,0EAA0E;IAC1E,cAAc,EAAE,MAAM,CAAA;IACtB;;;;;OAKG;IACH,gBAAgB,EAAE,MAAM,CAAA;CACzB,CAAA;AAED,MAAM,MAAM,iCAAiC,GAAG,IAAI,CAClD,2BAA2B,EAC3B,kBAAkB,GAAG,eAAe,CACrC,GAAG;IACF,mBAAmB,EAAE,MAAM,MAAM,CAAA;IACjC,gBAAgB,EAAE,MAAM,MAAM,CAAA;IAC9B,sBAAsB,EAAE,CAAC,QAAQ,EAAE,MAAM,IAAI,KAAK,MAAM,IAAI,CAAA;CAC7D,CAAA;AAMD,MAAM,MAAM,6BAA6B,GAAG;IAC1C,IAAI,EAAE,MAAM,MAAM,CAAA;IAClB,SAAS,EAAE,CAAC,QAAQ,EAAE,MAAM,IAAI,KAAK,MAAM,IAAI,CAAA;IAC/C,MAAM,EAAE,CAAC,aAAa,EAAE,MAAM,KAAK,IAAI,CAAA;CACxC,CAAA;AAED,wBAAgB,mCAAmC,CACjD,oBAAoB,EAAE,MAAM,GAC3B,6BAA6B,CAe/B;AAED,wBAAgB,uBAAuB,CAAC,EACtC,QAAQ,EACR,aAAa,EACb,OAAO,EACP,cAAc,EACd,gBAAgB,EAChB,mBAAmB,GACpB,EAAE,2BAA2B,GAAG;IAC/B,QAAQ,EAAE,SAAS,CAAA;IACnB,mBAAmB,EAAE,MAAM,MAAM,CAAA;CAClC,+BA6BA;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,IAAI,2BAA2B,GAAG,IAAI,CAgBvE;AAED,wBAAgB,wBAAwB,IAAI,iCAAiC,GAAG,IAAI,CAEnF;AAKD,wBAAgB,+BAA+B,IAAI,MAAM,CAOxD;AAED,wBAAgB,yBAAyB,IAAI,MAAM,CAElD"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
import { createContext, useContext, useLayoutEffect, useMemo, useRef, useSyncExternalStore, } from 'react';
|
|
4
|
+
const FloorplanStaticRenderContext = createContext(null);
|
|
5
|
+
const FloorplanSceneRotationContext = createContext(0);
|
|
6
|
+
const FloorplanUnitsPerPixelContext = createContext(1);
|
|
7
|
+
export function createFloorplanRenderScaleReference(initialUnitsPerPixel) {
|
|
8
|
+
let unitsPerPixel = initialUnitsPerPixel;
|
|
9
|
+
const listeners = new Set();
|
|
10
|
+
return {
|
|
11
|
+
read: () => unitsPerPixel,
|
|
12
|
+
subscribe: (listener) => {
|
|
13
|
+
listeners.add(listener);
|
|
14
|
+
return () => listeners.delete(listener);
|
|
15
|
+
},
|
|
16
|
+
update: (nextUnitsPerPixel) => {
|
|
17
|
+
if (Object.is(unitsPerPixel, nextUnitsPerPixel))
|
|
18
|
+
return;
|
|
19
|
+
unitsPerPixel = nextUnitsPerPixel;
|
|
20
|
+
for (const listener of listeners)
|
|
21
|
+
listener();
|
|
22
|
+
},
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
export function FloorplanRenderProvider({ children, unitsPerPixel, palette, hatchPatternId, sceneRotationDeg, getSceneRotationDeg, }) {
|
|
26
|
+
const renderScaleReference = useRef(null);
|
|
27
|
+
if (!renderScaleReference.current) {
|
|
28
|
+
renderScaleReference.current = createFloorplanRenderScaleReference(unitsPerPixel);
|
|
29
|
+
}
|
|
30
|
+
const getUnitsPerPixel = renderScaleReference.current.read;
|
|
31
|
+
const subscribeUnitsPerPixel = renderScaleReference.current.subscribe;
|
|
32
|
+
useLayoutEffect(() => {
|
|
33
|
+
renderScaleReference.current?.update(unitsPerPixel);
|
|
34
|
+
}, [unitsPerPixel]);
|
|
35
|
+
const staticValue = useMemo(() => ({
|
|
36
|
+
palette,
|
|
37
|
+
hatchPatternId,
|
|
38
|
+
getSceneRotationDeg,
|
|
39
|
+
getUnitsPerPixel,
|
|
40
|
+
subscribeUnitsPerPixel,
|
|
41
|
+
}), [palette, hatchPatternId, getSceneRotationDeg, getUnitsPerPixel, subscribeUnitsPerPixel]);
|
|
42
|
+
return (_jsx(FloorplanStaticRenderContext.Provider, { value: staticValue, children: _jsx(FloorplanUnitsPerPixelContext.Provider, { value: unitsPerPixel, children: _jsx(FloorplanSceneRotationContext.Provider, { value: sceneRotationDeg, children: children }) }) }));
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Read the active render context. Returns `null` when called outside a
|
|
46
|
+
* provider — consumers treat this as "render statically, skip
|
|
47
|
+
* theme-aware chrome and interactive handles". This makes the layer
|
|
48
|
+
* usable in isolation tests + future editor shells without bringing the
|
|
49
|
+
* whole host surface along.
|
|
50
|
+
*/
|
|
51
|
+
export function useFloorplanRender() {
|
|
52
|
+
const staticValue = useContext(FloorplanStaticRenderContext);
|
|
53
|
+
const sceneRotationDeg = useContext(FloorplanSceneRotationContext);
|
|
54
|
+
const unitsPerPixel = useContext(FloorplanUnitsPerPixelContext);
|
|
55
|
+
return useMemo(() => staticValue
|
|
56
|
+
? {
|
|
57
|
+
unitsPerPixel,
|
|
58
|
+
palette: staticValue.palette,
|
|
59
|
+
hatchPatternId: staticValue.hatchPatternId,
|
|
60
|
+
sceneRotationDeg,
|
|
61
|
+
}
|
|
62
|
+
: null, [sceneRotationDeg, staticValue, unitsPerPixel]);
|
|
63
|
+
}
|
|
64
|
+
export function useFloorplanStaticRender() {
|
|
65
|
+
return useContext(FloorplanStaticRenderContext);
|
|
66
|
+
}
|
|
67
|
+
const subscribeToNoFloorplanScale = () => () => { };
|
|
68
|
+
const readDefaultFloorplanScale = () => 1;
|
|
69
|
+
export function useFloorplanStaticUnitsPerPixel() {
|
|
70
|
+
const staticValue = useContext(FloorplanStaticRenderContext);
|
|
71
|
+
return useSyncExternalStore(staticValue?.subscribeUnitsPerPixel ?? subscribeToNoFloorplanScale, staticValue?.getUnitsPerPixel ?? readDefaultFloorplanScale, staticValue?.getUnitsPerPixel ?? readDefaultFloorplanScale);
|
|
72
|
+
}
|
|
73
|
+
export function useFloorplanSceneRotation() {
|
|
74
|
+
return useContext(FloorplanSceneRotationContext);
|
|
75
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export * from './floorplan-annotation-obstacles';
|
|
2
|
+
export { cameraPoseToFloorplanNavigationPose, createFloorplanCameraNavigationChannel, createFloorplanCameraSyncBridge, type FloorplanCameraNavigationChannel, type FloorplanCameraSyncBridge, floorplanNavigationPoseToCameraPose, floorplanNavigationPoseToInspectionCameraPose, } from './floorplan-camera-sync';
|
|
3
|
+
export { type FloorplanPoint, floorplanLocalToWorldPoint, worldToFloorplanLocalPoint, } from './floorplan-coordinates';
|
|
4
|
+
export * from './floorplan-dimension-renderer';
|
|
5
|
+
export * from './floorplan-geometry-renderer';
|
|
6
|
+
export * from './floorplan-label-angle';
|
|
7
|
+
export { type FloorplanNavigationController, FloorplanNavigationShell, type FloorplanNavigationShellProps, type FloorplanViewport, rotateFloorplanPoint, type UseFloorplanNavigationOptions, useFloorplanNavigation, } from './floorplan-navigation-shell';
|
|
8
|
+
export type { FloorplanNavigationPose, FloorplanNavigationPoseInput, FloorplanNavigationSource, } from './floorplan-navigation-types';
|
|
9
|
+
export * from './floorplan-registry-projection';
|
|
10
|
+
export * from './floorplan-render-context';
|
|
11
|
+
export * from './marquee-geometry';
|
|
12
|
+
export * from './spatial-workspace-camera-action-control';
|
|
13
|
+
export * from './spatial-workspace-display-control';
|
|
14
|
+
export * from './spatial-workspace-gis-control';
|
|
15
|
+
export * from './spatial-workspace-level-selector';
|
|
16
|
+
export * from './spatial-workspace-level-wall-control';
|
|
17
|
+
export * from './spatial-workspace-mode';
|
|
18
|
+
export * from './spatial-workspace-styles';
|
|
19
|
+
export * from './spatial-workspace-view-mode-control';
|
|
20
|
+
export { type SpatialWorkspaceRenderContext, type SpatialWorkspaceViewMode, SpatialWorkspaceViewport, type SpatialWorkspaceViewportProps, } from './spatial-workspace-viewport';
|
|
21
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,kCAAkC,CAAA;AAChD,OAAO,EACL,mCAAmC,EACnC,sCAAsC,EACtC,+BAA+B,EAC/B,KAAK,gCAAgC,EACrC,KAAK,yBAAyB,EAC9B,mCAAmC,EACnC,6CAA6C,GAC9C,MAAM,yBAAyB,CAAA;AAChC,OAAO,EACL,KAAK,cAAc,EACnB,0BAA0B,EAC1B,0BAA0B,GAC3B,MAAM,yBAAyB,CAAA;AAChC,cAAc,gCAAgC,CAAA;AAC9C,cAAc,+BAA+B,CAAA;AAC7C,cAAc,yBAAyB,CAAA;AACvC,OAAO,EACL,KAAK,6BAA6B,EAClC,wBAAwB,EACxB,KAAK,6BAA6B,EAClC,KAAK,iBAAiB,EACtB,oBAAoB,EACpB,KAAK,6BAA6B,EAClC,sBAAsB,GACvB,MAAM,8BAA8B,CAAA;AACrC,YAAY,EACV,uBAAuB,EACvB,4BAA4B,EAC5B,yBAAyB,GAC1B,MAAM,8BAA8B,CAAA;AACrC,cAAc,iCAAiC,CAAA;AAC/C,cAAc,4BAA4B,CAAA;AAC1C,cAAc,oBAAoB,CAAA;AAClC,cAAc,2CAA2C,CAAA;AACzD,cAAc,qCAAqC,CAAA;AACnD,cAAc,iCAAiC,CAAA;AAC/C,cAAc,oCAAoC,CAAA;AAClD,cAAc,wCAAwC,CAAA;AACtD,cAAc,0BAA0B,CAAA;AACxC,cAAc,4BAA4B,CAAA;AAC1C,cAAc,uCAAuC,CAAA;AACrD,OAAO,EACL,KAAK,6BAA6B,EAClC,KAAK,wBAAwB,EAC7B,wBAAwB,EACxB,KAAK,6BAA6B,GACnC,MAAM,8BAA8B,CAAA"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export * from './floorplan-annotation-obstacles';
|
|
2
|
+
export { cameraPoseToFloorplanNavigationPose, createFloorplanCameraNavigationChannel, createFloorplanCameraSyncBridge, floorplanNavigationPoseToCameraPose, floorplanNavigationPoseToInspectionCameraPose, } from './floorplan-camera-sync';
|
|
3
|
+
export { floorplanLocalToWorldPoint, worldToFloorplanLocalPoint, } from './floorplan-coordinates';
|
|
4
|
+
export * from './floorplan-dimension-renderer';
|
|
5
|
+
export * from './floorplan-geometry-renderer';
|
|
6
|
+
export * from './floorplan-label-angle';
|
|
7
|
+
export { FloorplanNavigationShell, rotateFloorplanPoint, useFloorplanNavigation, } from './floorplan-navigation-shell';
|
|
8
|
+
export * from './floorplan-registry-projection';
|
|
9
|
+
export * from './floorplan-render-context';
|
|
10
|
+
export * from './marquee-geometry';
|
|
11
|
+
export * from './spatial-workspace-camera-action-control';
|
|
12
|
+
export * from './spatial-workspace-display-control';
|
|
13
|
+
export * from './spatial-workspace-gis-control';
|
|
14
|
+
export * from './spatial-workspace-level-selector';
|
|
15
|
+
export * from './spatial-workspace-level-wall-control';
|
|
16
|
+
export * from './spatial-workspace-mode';
|
|
17
|
+
export * from './spatial-workspace-styles';
|
|
18
|
+
export * from './spatial-workspace-view-mode-control';
|
|
19
|
+
export { SpatialWorkspaceViewport, } from './spatial-workspace-viewport';
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export type ScreenRect = {
|
|
2
|
+
minX: number;
|
|
3
|
+
minY: number;
|
|
4
|
+
maxX: number;
|
|
5
|
+
maxY: number;
|
|
6
|
+
};
|
|
7
|
+
export type Point2 = [number, number];
|
|
8
|
+
/** Andrew monotone-chain convex hull. Returns CCW hull without the closing
|
|
9
|
+
* point; degenerate inputs (0–2 points, collinear sets) pass through. */
|
|
10
|
+
export declare function convexHull2D(points: readonly Point2[]): Point2[];
|
|
11
|
+
/** Segment vs polygon (general, possibly concave): endpoint containment or
|
|
12
|
+
* any edge crossing. */
|
|
13
|
+
export declare function segmentIntersectsPolygon(a: Point2, b: Point2, polygon: readonly Point2[]): boolean;
|
|
14
|
+
/** Polygon vs polygon (general): containment either way or any edge crossing. */
|
|
15
|
+
export declare function polygonsIntersect(a: readonly Point2[], b: readonly Point2[]): boolean;
|
|
16
|
+
/**
|
|
17
|
+
* Does the axis-aligned marquee rect intersect the (convex) hull polygon?
|
|
18
|
+
* Covers all cases: hull vertex inside the rect, rect fully inside the hull,
|
|
19
|
+
* and pure edge crossings.
|
|
20
|
+
*/
|
|
21
|
+
export declare function rectIntersectsHull(rect: ScreenRect, hull: readonly Point2[]): boolean;
|
|
22
|
+
//# sourceMappingURL=marquee-geometry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"marquee-geometry.d.ts","sourceRoot":"","sources":["../src/marquee-geometry.ts"],"names":[],"mappings":"AAMA,MAAM,MAAM,UAAU,GAAG;IACvB,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;CACb,CAAA;AAED,MAAM,MAAM,MAAM,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;AAMrC;0EAC0E;AAC1E,wBAAgB,YAAY,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,EAAE,CAsBhE;AAgDD;yBACyB;AACzB,wBAAgB,wBAAwB,CACtC,CAAC,EAAE,MAAM,EACT,CAAC,EAAE,MAAM,EACT,OAAO,EAAE,SAAS,MAAM,EAAE,GACzB,OAAO,CAQT;AAED,iFAAiF;AACjF,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,SAAS,MAAM,EAAE,EAAE,CAAC,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAYrF;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CA2BrF"}
|