@ahrowe/ui 0.25.1 → 0.26.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/esm/common/floorPlan/floorPlan.faces.mjs +2 -0
- package/dist/esm/common/floorPlan/floorPlan.faces.mjs.map +1 -0
- package/dist/esm/common/floorPlan/floorPlan.geometry.mjs +2 -0
- package/dist/esm/common/floorPlan/floorPlan.geometry.mjs.map +1 -0
- package/dist/esm/common/floorPlan/floorPlan.graph.mjs +2 -0
- package/dist/esm/common/floorPlan/floorPlan.graph.mjs.map +1 -0
- package/dist/esm/common/floorPlan/floorPlan.hit.mjs +2 -0
- package/dist/esm/common/floorPlan/floorPlan.hit.mjs.map +1 -0
- package/dist/esm/common/floorPlan/floorPlan.json.mjs +2 -0
- package/dist/esm/common/floorPlan/floorPlan.json.mjs.map +1 -0
- package/dist/esm/common/floorPlan/floorPlan.path.mjs +2 -0
- package/dist/esm/common/floorPlan/floorPlan.path.mjs.map +1 -0
- package/dist/esm/common/floorPlan/floorPlan.plan.mjs +2 -0
- package/dist/esm/common/floorPlan/floorPlan.plan.mjs.map +1 -0
- package/dist/esm/common/floorPlan/floorPlan.rooms.mjs +2 -0
- package/dist/esm/common/floorPlan/floorPlan.rooms.mjs.map +1 -0
- package/dist/esm/common/floorPlan/floorPlan.snap.mjs +2 -0
- package/dist/esm/common/floorPlan/floorPlan.snap.mjs.map +1 -0
- package/dist/esm/common/floorPlan/floorPlan.types.mjs +2 -0
- package/dist/esm/common/floorPlan/floorPlan.types.mjs.map +1 -0
- package/dist/esm/common/floorPlan/legacySvg.mjs +2 -0
- package/dist/esm/common/floorPlan/legacySvg.mjs.map +1 -0
- package/dist/esm/common/hooks/useSheet.mjs +1 -1
- package/dist/esm/common/hooks/useSheet.mjs.map +1 -1
- package/dist/esm/common/planCanvas/planCanvas.mjs +2 -0
- package/dist/esm/common/planCanvas/planCanvas.mjs.map +1 -0
- package/dist/esm/common/planCanvas/planCanvas.module.mjs +2 -0
- package/dist/esm/common/planCanvas/planCanvas.module.mjs.map +1 -0
- package/dist/esm/common/roomDrawer/roomDrawer.mjs +1 -1
- package/dist/esm/common/roomDrawer/roomDrawer.mjs.map +1 -1
- package/dist/esm/common/roomDrawer/roomDrawer.module.mjs +1 -1
- package/dist/esm/common/roomDrawer/roomDrawer.module.mjs.map +1 -1
- package/dist/esm/common/roomDrawer/usePlanHistory.mjs +2 -0
- package/dist/esm/common/roomDrawer/usePlanHistory.mjs.map +1 -0
- package/dist/esm/common/roomViewer/roomViewer.mjs +1 -1
- package/dist/esm/common/roomViewer/roomViewer.mjs.map +1 -1
- package/dist/esm/common/roomViewer/roomViewer.module.mjs +1 -1
- package/dist/esm/common/roomViewer/roomViewer.module.mjs.map +1 -1
- package/dist/esm/common/styles/sheet.module.mjs.map +1 -1
- package/dist/esm/index.mjs +1 -1
- package/dist/index.cjs +3 -7
- package/dist/index.cjs.map +1 -1
- package/dist/style.css +1 -1
- package/dist/types/package/common/configProvider/configProvider.types.d.ts +4 -0
- package/dist/types/package/common/floorPlan/floorPlan.faces.d.ts +33 -0
- package/dist/types/package/common/floorPlan/floorPlan.fixtures.d.ts +35 -0
- package/dist/types/package/common/floorPlan/floorPlan.geometry.d.ts +111 -0
- package/dist/types/package/common/floorPlan/floorPlan.graph.d.ts +139 -0
- package/dist/types/package/common/floorPlan/floorPlan.hit.d.ts +26 -0
- package/dist/types/package/common/floorPlan/floorPlan.json.d.ts +23 -0
- package/dist/types/package/common/floorPlan/floorPlan.path.d.ts +59 -0
- package/dist/types/package/common/floorPlan/floorPlan.plan.d.ts +98 -0
- package/dist/types/package/common/floorPlan/floorPlan.rooms.d.ts +47 -0
- package/dist/types/package/common/floorPlan/floorPlan.snap.d.ts +101 -0
- package/dist/types/package/common/floorPlan/floorPlan.types.d.ts +276 -0
- package/dist/types/package/common/floorPlan/index.d.ts +28 -0
- package/dist/types/package/common/floorPlan/legacySvg.d.ts +27 -0
- package/dist/types/package/common/hooks/useSheet.d.ts +4 -1
- package/dist/types/package/common/planCanvas/index.d.ts +2 -0
- package/dist/types/package/common/planCanvas/planCanvas.d.ts +7 -0
- package/dist/types/package/common/planCanvas/planCanvas.types.d.ts +62 -0
- package/dist/types/package/common/roomDrawer/roomDrawer.d.ts +3 -3
- package/dist/types/package/common/roomDrawer/roomDrawer.types.d.ts +295 -15
- package/dist/types/package/common/roomDrawer/usePlanHistory.d.ts +24 -0
- package/dist/types/package/common/roomViewer/index.d.ts +1 -0
- package/dist/types/package/common/roomViewer/roomViewer.d.ts +9 -2
- package/dist/types/package/common/roomViewer/roomViewer.types.d.ts +88 -9
- package/dist/types/package/index.d.ts +1 -0
- package/docs/CLAUDE.md +1 -0
- package/docs/ConfigProvider.md +1 -0
- package/docs/Dropdown.md +1 -1
- package/docs/FloatingMenu.md +1 -1
- package/docs/FloorPlan.md +214 -0
- package/docs/Modal.md +2 -2
- package/docs/Popover.md +1 -1
- package/docs/RoomDrawer.md +330 -30
- package/docs/RoomViewer.md +80 -27
- package/package.json +1 -1
- package/dist/esm/common/roomDrawer/roomDrawer.utils.mjs +0 -6
- package/dist/esm/common/roomDrawer/roomDrawer.utils.mjs.map +0 -1
- package/dist/types/package/common/roomDrawer/roomDrawer.utils.d.ts +0 -32
- package/docs/room-drawing-analysis.md +0 -337
|
@@ -1,337 +0,0 @@
|
|
|
1
|
-
# RoomViewer — Deep Analysis
|
|
2
|
-
|
|
3
|
-
This document reverse-engineers every convention in the existing SVG room data so we can build a room-drawing tool that produces fully compatible output.
|
|
4
|
-
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
## 1. The Data Model
|
|
8
|
-
|
|
9
|
-
Each floor is an object `{ id: string, label: string, data: ReactElement }`.
|
|
10
|
-
`data` is a JSX SVG element. The component renders it inside a `<div>` wrapper and queries the DOM after render to attach click handlers.
|
|
11
|
-
|
|
12
|
-
```ts
|
|
13
|
-
interface FloorData {
|
|
14
|
-
id: string;
|
|
15
|
-
label: string; // shown as the floor heading
|
|
16
|
-
data: ReactElement; // the <svg> JSX element
|
|
17
|
-
}
|
|
18
|
-
```
|
|
19
|
-
|
|
20
|
-
The array can hold 1..N floors. When length > 1 the component renders chevron navigation.
|
|
21
|
-
|
|
22
|
-
---
|
|
23
|
-
|
|
24
|
-
## 2. SVG Coordinate System
|
|
25
|
-
|
|
26
|
-
### ViewBox
|
|
27
|
-
|
|
28
|
-
```
|
|
29
|
-
viewBox="minX minY width height"
|
|
30
|
-
```
|
|
31
|
-
|
|
32
|
-
| Floor | viewBox | x-range | y-range |
|
|
33
|
-
|-------|---------|---------|---------|
|
|
34
|
-
| Ground (floor 1) | `0.9 0.9 165.1 103.8` | 0.9 → 166.0 | 0.9 → 104.7 |
|
|
35
|
-
| Upper (floor 2) | `22 46 167 105` | 22 → 189 | 46 → 151 |
|
|
36
|
-
|
|
37
|
-
**Key observation**: the viewBox does NOT need to start at origin. Floor 2 starts at `(22, 46)` because the actual room coordinates in that SVG happen to begin around those values. The SVG renderer maps the viewBox onto the container's display size automatically.
|
|
38
|
-
|
|
39
|
-
The SVG itself has no `width` or `height` attributes — it fills whatever container it is placed in (the component styles it with CSS).
|
|
40
|
-
|
|
41
|
-
### Y-axis direction
|
|
42
|
-
|
|
43
|
-
SVG uses a **top-left origin** with Y increasing downward (opposite to Cartesian). This affects how you think about "up" and "down" in path commands: `V 1` is near the top edge, `V 103` is near the bottom.
|
|
44
|
-
|
|
45
|
-
### Stroke width
|
|
46
|
-
|
|
47
|
-
All paths are rendered with `stroke-width: 1px` (set in CSS, not SVG). This means wall thickness is purely visual — the coordinate defines the centre-line of the wall.
|
|
48
|
-
|
|
49
|
-
---
|
|
50
|
-
|
|
51
|
-
## 3. Room Definition — Two Formats
|
|
52
|
-
|
|
53
|
-
### Format A: Group with background path
|
|
54
|
-
|
|
55
|
-
```xml
|
|
56
|
-
<g id="roomKitchen">
|
|
57
|
-
<path id="path923" d="..." /> <!-- decorative outline segment(s) -->
|
|
58
|
-
<path id="path925" d="..." /> <!-- more outline -->
|
|
59
|
-
<path id="background" d="..." /> <!-- closed filled polygon -->
|
|
60
|
-
</g>
|
|
61
|
-
```
|
|
62
|
-
|
|
63
|
-
- The `<g>` gets the `id="roomXxx"` that makes it interactive.
|
|
64
|
-
- The `background` path is a **closed polygon** (`Z` at end) covering the room's entire floor area. CSS sets it `fill: transparent` by default and the highlight classes colour it.
|
|
65
|
-
- The other paths are partial outlines (wall segments). They do **not** need to form a closed shape together — they are supplementary wall lines for visual completeness.
|
|
66
|
-
- The group can also contain `<text>` for room label rendering (floor 2 only).
|
|
67
|
-
|
|
68
|
-
### Format B: Bare path
|
|
69
|
-
|
|
70
|
-
```xml
|
|
71
|
-
<path id="roomToilet" d="..." />
|
|
72
|
-
```
|
|
73
|
-
|
|
74
|
-
- A single `<path>` element whose `id` starts with `room`.
|
|
75
|
-
- The path itself is the room outline. It is typically **open** (no `Z`) — just the visible wall segments.
|
|
76
|
-
- There is no separate background path. When highlighted, the path element itself gets both the `selected` (stroke colour) and `tint` (fill) classes directly.
|
|
77
|
-
- This format has no text label support.
|
|
78
|
-
|
|
79
|
-
### Comparison
|
|
80
|
-
|
|
81
|
-
| | Format A (group) | Format B (bare path) |
|
|
82
|
-
|--|--|--|
|
|
83
|
-
| Hit area | `path[id="background"]` | the path element itself |
|
|
84
|
-
| Outline | multiple partial paths | single path |
|
|
85
|
-
| Text label | supported (`<text>` inside `<g>`) | not supported |
|
|
86
|
-
| CSS tint target | `background` child | the path itself |
|
|
87
|
-
| CSS stroke target | the `<g>` and its `path` children | the path itself |
|
|
88
|
-
|
|
89
|
-
---
|
|
90
|
-
|
|
91
|
-
## 4. The `id="background"` Convention
|
|
92
|
-
|
|
93
|
-
Inside a Format A group, the background path:
|
|
94
|
-
|
|
95
|
-
- Must have `id="background"` (exact string, queried with `querySelector('[id="background"]')`).
|
|
96
|
-
- Must be a **closed polygon** (path ends with `Z`) covering the whole room area.
|
|
97
|
-
- Is the actual clickable surface when the group is a `<g>` — CSS sets `cursor: pointer` on it.
|
|
98
|
-
- Gets the tint class on selection.
|
|
99
|
-
- Multiple rooms can each have their own `id="background"` child (duplicate IDs in different subtrees — technically invalid HTML but SVG renders it fine and querySelector on a parent scoped to the group returns the right one).
|
|
100
|
-
|
|
101
|
-
---
|
|
102
|
-
|
|
103
|
-
## 5. Path Anatomy — How Rooms Are Drawn
|
|
104
|
-
|
|
105
|
-
SVG path `d` attributes use these commands in the sample data:
|
|
106
|
-
|
|
107
|
-
| Command | Meaning |
|
|
108
|
-
|---------|---------|
|
|
109
|
-
| `M x,y` | Move to absolute point — starts a new sub-path |
|
|
110
|
-
| `m dx,dy` | Move to relative point |
|
|
111
|
-
| `H x` | Horizontal line to absolute x |
|
|
112
|
-
| `h dx` | Horizontal line by relative dx |
|
|
113
|
-
| `V y` | Vertical line to absolute y |
|
|
114
|
-
| `v dy` | Vertical line by relative dy |
|
|
115
|
-
| `L x,y` | Line to absolute point |
|
|
116
|
-
| `l dx,dy` | Line to relative point |
|
|
117
|
-
| `Z` | Close path (line back to start of sub-path) |
|
|
118
|
-
|
|
119
|
-
All rooms in the sample data use **only axis-aligned segments** (H, V) with the exception of `L` / `l` for diagonal closes on the background polygons where the start and end points aren't perfectly aligned. In practice all rooms are **rectilinear polygons** (right-angle corners only).
|
|
120
|
-
|
|
121
|
-
### Example: roomKitchen background (Format A)
|
|
122
|
-
|
|
123
|
-
```
|
|
124
|
-
m 70.283619,51.634041 → start at (70.28, 51.63)
|
|
125
|
-
h 95.082671 → right to (165.37, 51.63)
|
|
126
|
-
l 0.0972,52.109689 → slightly right+down to (165.46, 103.74) ← border-align correction
|
|
127
|
-
H 69.930275 → left to (69.93, 103.74)
|
|
128
|
-
Z → close back to (70.28, 51.63)
|
|
129
|
-
```
|
|
130
|
-
|
|
131
|
-
This is a near-perfect rectangle at x: 70–165, y: 52–104.
|
|
132
|
-
The tiny `l 0.0972,52.11` instead of a pure `V` is because the border path itself has a slight diagonal — the background traces the outer border exactly.
|
|
133
|
-
|
|
134
|
-
### Example: roomToilet (Format B, open path)
|
|
135
|
-
|
|
136
|
-
```
|
|
137
|
-
M 41.312537,31.672271 → start at (41.31, 31.67)
|
|
138
|
-
V 27.96255 → up to (41.31, 27.96) top-left corner
|
|
139
|
-
H 1.5913974 → left to (1.59, 27.96) top-right corner (at left wall)
|
|
140
|
-
V 48.100984 → down to (1.59, 48.10) bottom-right corner
|
|
141
|
-
H 41.135885 → right to (41.14, 48.10) bottom-left corner
|
|
142
|
-
v -6.53616 → up to (41.14, 41.56) partial right wall
|
|
143
|
-
```
|
|
144
|
-
|
|
145
|
-
No `Z` — the path is open. It draws three walls (top, left outer wall, bottom) and part of the right wall, leaving the door gap open. The room outline is **not** self-contained; it shares walls with the outer border and adjacent rooms.
|
|
146
|
-
|
|
147
|
-
### Example: roomEntryHall (Format B, staircase shape)
|
|
148
|
-
|
|
149
|
-
```
|
|
150
|
-
M 47.848693,81.841692 → (47.85, 81.84)
|
|
151
|
-
V 73.715669 → up to (47.85, 73.72)
|
|
152
|
-
H 25.774869 → left to (25.77, 73.72)
|
|
153
|
-
V 68.698633 → up to (25.77, 68.70) ← step in wall
|
|
154
|
-
H 1.6667594 → left to (1.67, 68.70)
|
|
155
|
-
l -0.07538,35.045097 → down to (1.59, 103.75) outer bottom-left
|
|
156
|
-
H 48.201992 → right to (48.20, 103.75)
|
|
157
|
-
v -9.094696 → up to (48.20, 94.65)
|
|
158
|
-
```
|
|
159
|
-
|
|
160
|
-
This L-shaped room has a **step** in its top-right corner at `(25.77, 73.72)→(25.77, 68.70)` — a 5-unit indentation where the wall jogs inward. This is the staircase landing or hallway notch.
|
|
161
|
-
|
|
162
|
-
### The `nope` path
|
|
163
|
-
|
|
164
|
-
```
|
|
165
|
-
id="nope" — NOT prefixed with "room", therefore not interactive
|
|
166
|
-
M 47.848693,73.715669
|
|
167
|
-
H 25.774869
|
|
168
|
-
V 57.331599 → up to y=57.33
|
|
169
|
-
68.698633 → implicit V 68.70 (continuation) — BACK DOWN to y=68.70
|
|
170
|
-
H 1.6667594 → left
|
|
171
|
-
L 1.5913794,48.100984 → up
|
|
172
|
-
H 47.848679 → right
|
|
173
|
-
Z
|
|
174
|
-
```
|
|
175
|
-
|
|
176
|
-
This is the hallway/corridor space between Toilet, Office, and EntryHall. It is drawn but not selectable. The double V value (`V 57.33 68.70`) creates a zigzag that draws the staircase step outline that is shared with the EntryHall.
|
|
177
|
-
|
|
178
|
-
---
|
|
179
|
-
|
|
180
|
-
## 6. Wall Sharing
|
|
181
|
-
|
|
182
|
-
Rooms do **not** each define their complete closed boundary. They only draw the wall segments that are their "own" walls — the walls they share with other rooms or the outer border are not repeated.
|
|
183
|
-
|
|
184
|
-
Examples from floor 1:
|
|
185
|
-
|
|
186
|
-
- The left outer wall (`x ≈ 1.59`) is drawn by the `border` path, not by individual rooms.
|
|
187
|
-
- The wall at `x ≈ 70` separating Toilet/Office/EntryHall from Kitchen/Livingroom is partially drawn by each room on that side.
|
|
188
|
-
- The horizontal wall at `y ≈ 27.96` separating Toilet and Office is drawn by both their paths, but only the outer edge is stroked.
|
|
189
|
-
|
|
190
|
-
This means the SVG viewer relies on **overlapping strokes** to form complete wall appearances — you don't get gaps because each side draws at least one stroke along the shared wall.
|
|
191
|
-
|
|
192
|
-
**Implication for a drawing tool**: rooms should be stored as complete closed polygons internally, and at render time the tool can either:
|
|
193
|
-
1. Render each room as a complete closed shape (simpler), or
|
|
194
|
-
2. Compute shared edges and only render each wall segment once (more authentic to the existing format, matches the component's CSS expectations).
|
|
195
|
-
|
|
196
|
-
---
|
|
197
|
-
|
|
198
|
-
## 7. The `<use>` Highlight Mechanism
|
|
199
|
-
|
|
200
|
-
Every SVG must contain exactly one `<use id="use" href="">` element, placed **after** all room elements (so it renders on top in SVG painter's order):
|
|
201
|
-
|
|
202
|
-
```xml
|
|
203
|
-
<use id="use" href="" />
|
|
204
|
-
```
|
|
205
|
-
|
|
206
|
-
When a room is clicked, `onRoomClicked` does:
|
|
207
|
-
```js
|
|
208
|
-
use.setAttribute('href', `#${roomId}`);
|
|
209
|
-
```
|
|
210
|
-
|
|
211
|
-
This makes `<use>` render a visual copy of the selected room's element at the same position. Because `<use>` is last in the DOM, its copy renders on top of everything else.
|
|
212
|
-
|
|
213
|
-
The `<use>` element inherits the CSS classes of the element it references (via SVG shadow DOM), so the green stroke/tint applied to the original group also shows on the `<use>` copy. The effect is a highlighted outline drawn over all other overlapping paths — this is why the selection visually "pops" even when rooms share wall lines.
|
|
214
|
-
|
|
215
|
-
**Critical**: without `<use id="use">` in the SVG the component will throw when trying to `setAttribute` on `undefined`.
|
|
216
|
-
|
|
217
|
-
---
|
|
218
|
-
|
|
219
|
-
## 8. CSS Highlight Classes
|
|
220
|
-
|
|
221
|
-
The component applies classes from the CSS module to DOM elements directly via `classList`. Three classes are involved:
|
|
222
|
-
|
|
223
|
-
### `.roomViewerSelected`
|
|
224
|
-
Applied to: the room's top element (`<g>` or `<path>`)
|
|
225
|
-
Effect:
|
|
226
|
-
```css
|
|
227
|
-
stroke: #18f810 !important; /* green stroke on the group/path */
|
|
228
|
-
path { stroke: #18f810 !important; fill: none !important; }
|
|
229
|
-
path[id="background"] { stroke: none !important; fill: #20f81013 !important; }
|
|
230
|
-
```
|
|
231
|
-
|
|
232
|
-
### `.roomViewerTint`
|
|
233
|
-
Applied to: the `path[id="background"]` child, or the room element itself if no background exists
|
|
234
|
-
Effect:
|
|
235
|
-
```css
|
|
236
|
-
fill: #20f81013 !important; /* translucent green fill */
|
|
237
|
-
path { fill: #20f81013 !important; }
|
|
238
|
-
text { stroke: none; fill: none; } /* hide text when tinted */
|
|
239
|
-
```
|
|
240
|
-
|
|
241
|
-
### Deselection
|
|
242
|
-
Both classes are removed from the previously selected room before applying to the new one. The `<use href>` is updated too.
|
|
243
|
-
|
|
244
|
-
### Note on `.roomViewerActive`
|
|
245
|
-
The CSS defines an `-active` class with identical styling to `-selected` but it is **never set by the component code**. It appears to be dead CSS, possibly from an older version.
|
|
246
|
-
|
|
247
|
-
---
|
|
248
|
-
|
|
249
|
-
## 9. Non-Interactive Elements
|
|
250
|
-
|
|
251
|
-
These elements appear in the SVG but are deliberately not rooms:
|
|
252
|
-
|
|
253
|
-
| `id` | Role |
|
|
254
|
-
|------|------|
|
|
255
|
-
| `border` | outer building outline — pure decoration |
|
|
256
|
-
| `layer1` | top-level `<g>` grouping all content |
|
|
257
|
-
| `background` | fill area inside a Format A room — selectable but not a room itself |
|
|
258
|
-
| `nope` | corridor/void area explicitly excluded from interaction |
|
|
259
|
-
| `path923`, `path925`, etc. | decorative wall segments inside Format A groups |
|
|
260
|
-
| `use` | the highlight overlay — must exist but is not a room |
|
|
261
|
-
|
|
262
|
-
The selector `[id^="room"]` in both the JavaScript (`querySelectorAll`) and CSS (`*[id^="room"]`) correctly targets only room elements.
|
|
263
|
-
|
|
264
|
-
---
|
|
265
|
-
|
|
266
|
-
## 10. Transform Attribute
|
|
267
|
-
|
|
268
|
-
Floor 1's `roomLivingroom` has:
|
|
269
|
-
```xml
|
|
270
|
-
<g id="roomLivingroom" transform="translate(-0.41843424,-0.03740732)">
|
|
271
|
-
```
|
|
272
|
-
|
|
273
|
-
This tiny sub-pixel shift aligns the Livingroom paths with the outer border precisely (the border has very slight diagonal lines rather than perfect axis-aligned coordinates). The drawing tool should either:
|
|
274
|
-
- Support a `transform` per room for micro-alignment corrections, or
|
|
275
|
-
- Guarantee perfectly aligned coordinates so no correction is needed.
|
|
276
|
-
|
|
277
|
-
---
|
|
278
|
-
|
|
279
|
-
## 11. Summary: What a Drawing Tool Needs to Produce
|
|
280
|
-
|
|
281
|
-
To produce SVG data compatible with RoomViewer, every exported SVG must satisfy these rules:
|
|
282
|
-
|
|
283
|
-
### Required structure
|
|
284
|
-
```xml
|
|
285
|
-
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="minX minY width height">
|
|
286
|
-
<g id="layer1">
|
|
287
|
-
<!-- outer border (optional but conventional) -->
|
|
288
|
-
<path id="border" d="..." />
|
|
289
|
-
|
|
290
|
-
<!-- zero or more room elements -->
|
|
291
|
-
<g id="roomXxx"> <!-- Format A -->
|
|
292
|
-
<path d="..." /> <!-- wall segment(s) -->
|
|
293
|
-
<path id="background" d="..." /> <!-- closed polygon, must end with Z -->
|
|
294
|
-
<text ...>Label</text> <!-- optional -->
|
|
295
|
-
</g>
|
|
296
|
-
|
|
297
|
-
<path id="roomYyy" d="..." /> <!-- Format B, for simple rooms -->
|
|
298
|
-
</g>
|
|
299
|
-
|
|
300
|
-
<use id="use" href="" /> <!-- REQUIRED, must be last -->
|
|
301
|
-
</svg>
|
|
302
|
-
```
|
|
303
|
-
|
|
304
|
-
### Room ID convention
|
|
305
|
-
- Must start with `room` (case-sensitive)
|
|
306
|
-
- Remainder is the "pure room ID" — stored in state without the `room` prefix
|
|
307
|
-
- Examples: `roomLivingroom`, `roomBath`, `roomBedroomOne`
|
|
308
|
-
|
|
309
|
-
### Background path rules
|
|
310
|
-
- Must be a **closed polygon** — path `d` must end with `Z`
|
|
311
|
-
- Must have exactly `id="background"` (the querySelector targets this exact string)
|
|
312
|
-
- Should cover the entire floor area of the room
|
|
313
|
-
- For rectilinear rooms: trace all four (or more) corners and close
|
|
314
|
-
|
|
315
|
-
### `<use>` element rules
|
|
316
|
-
- Must have `id="use"`
|
|
317
|
-
- Must be the last element in the SVG (so it renders on top)
|
|
318
|
-
- `href=""` initially empty
|
|
319
|
-
|
|
320
|
-
### Coordinate system for a drawing tool
|
|
321
|
-
- Use a fixed grid (e.g. 200×150 units) as the design canvas
|
|
322
|
-
- Store rooms as arrays of `{x, y}` corner points (all axis-aligned → only right-angle corners)
|
|
323
|
-
- Generate path `d` for wall outlines: open path tracing the room's perimeter segments
|
|
324
|
-
- Generate path `d` for background: closed polygon — `M x0,y0 H x1 V y1 H x0 Z` (for a rectangle)
|
|
325
|
-
- viewBox should be computed from the bounding box of all content with a small margin
|
|
326
|
-
- Keep coordinates as floating-point with 2–6 decimal places (the existing SVGs use 6)
|
|
327
|
-
|
|
328
|
-
### Data format to emit
|
|
329
|
-
```ts
|
|
330
|
-
{
|
|
331
|
-
id: string, // e.g. 'floorOne'
|
|
332
|
-
label: string, // e.g. 'First floor'
|
|
333
|
-
data: ReactElement // the <svg> JSX
|
|
334
|
-
}
|
|
335
|
-
```
|
|
336
|
-
|
|
337
|
-
The drawing tool should render rooms as JSX (using `React.createElement` or a JSX template string evaluated at export time).
|