@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.
Files changed (82) hide show
  1. package/dist/esm/common/floorPlan/floorPlan.faces.mjs +2 -0
  2. package/dist/esm/common/floorPlan/floorPlan.faces.mjs.map +1 -0
  3. package/dist/esm/common/floorPlan/floorPlan.geometry.mjs +2 -0
  4. package/dist/esm/common/floorPlan/floorPlan.geometry.mjs.map +1 -0
  5. package/dist/esm/common/floorPlan/floorPlan.graph.mjs +2 -0
  6. package/dist/esm/common/floorPlan/floorPlan.graph.mjs.map +1 -0
  7. package/dist/esm/common/floorPlan/floorPlan.hit.mjs +2 -0
  8. package/dist/esm/common/floorPlan/floorPlan.hit.mjs.map +1 -0
  9. package/dist/esm/common/floorPlan/floorPlan.json.mjs +2 -0
  10. package/dist/esm/common/floorPlan/floorPlan.json.mjs.map +1 -0
  11. package/dist/esm/common/floorPlan/floorPlan.path.mjs +2 -0
  12. package/dist/esm/common/floorPlan/floorPlan.path.mjs.map +1 -0
  13. package/dist/esm/common/floorPlan/floorPlan.plan.mjs +2 -0
  14. package/dist/esm/common/floorPlan/floorPlan.plan.mjs.map +1 -0
  15. package/dist/esm/common/floorPlan/floorPlan.rooms.mjs +2 -0
  16. package/dist/esm/common/floorPlan/floorPlan.rooms.mjs.map +1 -0
  17. package/dist/esm/common/floorPlan/floorPlan.snap.mjs +2 -0
  18. package/dist/esm/common/floorPlan/floorPlan.snap.mjs.map +1 -0
  19. package/dist/esm/common/floorPlan/floorPlan.types.mjs +2 -0
  20. package/dist/esm/common/floorPlan/floorPlan.types.mjs.map +1 -0
  21. package/dist/esm/common/floorPlan/legacySvg.mjs +2 -0
  22. package/dist/esm/common/floorPlan/legacySvg.mjs.map +1 -0
  23. package/dist/esm/common/hooks/useSheet.mjs +1 -1
  24. package/dist/esm/common/hooks/useSheet.mjs.map +1 -1
  25. package/dist/esm/common/planCanvas/planCanvas.mjs +2 -0
  26. package/dist/esm/common/planCanvas/planCanvas.mjs.map +1 -0
  27. package/dist/esm/common/planCanvas/planCanvas.module.mjs +2 -0
  28. package/dist/esm/common/planCanvas/planCanvas.module.mjs.map +1 -0
  29. package/dist/esm/common/roomDrawer/roomDrawer.mjs +1 -1
  30. package/dist/esm/common/roomDrawer/roomDrawer.mjs.map +1 -1
  31. package/dist/esm/common/roomDrawer/roomDrawer.module.mjs +1 -1
  32. package/dist/esm/common/roomDrawer/roomDrawer.module.mjs.map +1 -1
  33. package/dist/esm/common/roomDrawer/usePlanHistory.mjs +2 -0
  34. package/dist/esm/common/roomDrawer/usePlanHistory.mjs.map +1 -0
  35. package/dist/esm/common/roomViewer/roomViewer.mjs +1 -1
  36. package/dist/esm/common/roomViewer/roomViewer.mjs.map +1 -1
  37. package/dist/esm/common/roomViewer/roomViewer.module.mjs +1 -1
  38. package/dist/esm/common/roomViewer/roomViewer.module.mjs.map +1 -1
  39. package/dist/esm/common/styles/sheet.module.mjs.map +1 -1
  40. package/dist/esm/index.mjs +1 -1
  41. package/dist/index.cjs +3 -7
  42. package/dist/index.cjs.map +1 -1
  43. package/dist/style.css +1 -1
  44. package/dist/types/package/common/configProvider/configProvider.types.d.ts +4 -0
  45. package/dist/types/package/common/floorPlan/floorPlan.faces.d.ts +33 -0
  46. package/dist/types/package/common/floorPlan/floorPlan.fixtures.d.ts +35 -0
  47. package/dist/types/package/common/floorPlan/floorPlan.geometry.d.ts +111 -0
  48. package/dist/types/package/common/floorPlan/floorPlan.graph.d.ts +139 -0
  49. package/dist/types/package/common/floorPlan/floorPlan.hit.d.ts +26 -0
  50. package/dist/types/package/common/floorPlan/floorPlan.json.d.ts +23 -0
  51. package/dist/types/package/common/floorPlan/floorPlan.path.d.ts +59 -0
  52. package/dist/types/package/common/floorPlan/floorPlan.plan.d.ts +98 -0
  53. package/dist/types/package/common/floorPlan/floorPlan.rooms.d.ts +47 -0
  54. package/dist/types/package/common/floorPlan/floorPlan.snap.d.ts +101 -0
  55. package/dist/types/package/common/floorPlan/floorPlan.types.d.ts +276 -0
  56. package/dist/types/package/common/floorPlan/index.d.ts +28 -0
  57. package/dist/types/package/common/floorPlan/legacySvg.d.ts +27 -0
  58. package/dist/types/package/common/hooks/useSheet.d.ts +4 -1
  59. package/dist/types/package/common/planCanvas/index.d.ts +2 -0
  60. package/dist/types/package/common/planCanvas/planCanvas.d.ts +7 -0
  61. package/dist/types/package/common/planCanvas/planCanvas.types.d.ts +62 -0
  62. package/dist/types/package/common/roomDrawer/roomDrawer.d.ts +3 -3
  63. package/dist/types/package/common/roomDrawer/roomDrawer.types.d.ts +295 -15
  64. package/dist/types/package/common/roomDrawer/usePlanHistory.d.ts +24 -0
  65. package/dist/types/package/common/roomViewer/index.d.ts +1 -0
  66. package/dist/types/package/common/roomViewer/roomViewer.d.ts +9 -2
  67. package/dist/types/package/common/roomViewer/roomViewer.types.d.ts +88 -9
  68. package/dist/types/package/index.d.ts +1 -0
  69. package/docs/CLAUDE.md +1 -0
  70. package/docs/ConfigProvider.md +1 -0
  71. package/docs/Dropdown.md +1 -1
  72. package/docs/FloatingMenu.md +1 -1
  73. package/docs/FloorPlan.md +214 -0
  74. package/docs/Modal.md +2 -2
  75. package/docs/Popover.md +1 -1
  76. package/docs/RoomDrawer.md +330 -30
  77. package/docs/RoomViewer.md +80 -27
  78. package/package.json +1 -1
  79. package/dist/esm/common/roomDrawer/roomDrawer.utils.mjs +0 -6
  80. package/dist/esm/common/roomDrawer/roomDrawer.utils.mjs.map +0 -1
  81. package/dist/types/package/common/roomDrawer/roomDrawer.utils.d.ts +0 -32
  82. 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).