@pascal-app/core 1.0.0-beta.5 → 1.0.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 (231) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +23 -0
  3. package/dist/capture/index.d.ts +3 -0
  4. package/dist/capture/index.d.ts.map +1 -0
  5. package/dist/capture/index.js +2 -0
  6. package/dist/capture/schema.d.ts +417 -0
  7. package/dist/capture/schema.d.ts.map +1 -0
  8. package/dist/capture/schema.js +348 -0
  9. package/dist/capture/source.d.ts +60 -0
  10. package/dist/capture/source.d.ts.map +1 -0
  11. package/dist/capture/source.js +254 -0
  12. package/dist/events/bus.d.ts +55 -7
  13. package/dist/events/bus.d.ts.map +1 -1
  14. package/dist/events/hidden-wall-pointer-hold.d.ts +28 -0
  15. package/dist/events/hidden-wall-pointer-hold.d.ts.map +1 -0
  16. package/dist/events/hidden-wall-pointer-hold.js +37 -0
  17. package/dist/hooks/spatial-grid/spatial-grid-sync.d.ts +2785 -1
  18. package/dist/hooks/spatial-grid/spatial-grid-sync.d.ts.map +1 -1
  19. package/dist/hooks/spatial-grid/spatial-grid-sync.js +132 -19
  20. package/dist/hooks/spatial-grid/support-host-patch.d.ts +45 -1
  21. package/dist/hooks/spatial-grid/support-host-patch.d.ts.map +1 -1
  22. package/dist/hooks/spatial-grid/support-host-patch.js +171 -6
  23. package/dist/index.d.ts +14 -6
  24. package/dist/index.d.ts.map +1 -1
  25. package/dist/index.js +16 -5
  26. package/dist/lib/asset-storage.d.ts.map +1 -1
  27. package/dist/lib/asset-storage.js +4 -1
  28. package/dist/lib/polygon-union.d.ts +4 -0
  29. package/dist/lib/polygon-union.d.ts.map +1 -0
  30. package/dist/lib/polygon-union.js +306 -0
  31. package/dist/lib/roof-overlap.d.ts +32 -0
  32. package/dist/lib/roof-overlap.d.ts.map +1 -0
  33. package/dist/lib/roof-overlap.js +72 -0
  34. package/dist/lib/slab-polygon.d.ts +35 -2
  35. package/dist/lib/slab-polygon.d.ts.map +1 -1
  36. package/dist/lib/slab-polygon.js +133 -27
  37. package/dist/lib/space-detection.d.ts +11 -0
  38. package/dist/lib/space-detection.d.ts.map +1 -1
  39. package/dist/lib/space-detection.js +42 -14
  40. package/dist/registry/handles.d.ts +24 -3
  41. package/dist/registry/handles.d.ts.map +1 -1
  42. package/dist/registry/index.d.ts +3 -4
  43. package/dist/registry/index.d.ts.map +1 -1
  44. package/dist/registry/index.js +1 -2
  45. package/dist/registry/registry.d.ts +13 -6
  46. package/dist/registry/registry.d.ts.map +1 -1
  47. package/dist/registry/registry.js +37 -4
  48. package/dist/registry/scene-api.d.ts +16 -0
  49. package/dist/registry/scene-api.d.ts.map +1 -1
  50. package/dist/registry/scene-api.js +49 -1
  51. package/dist/registry/types.d.ts +226 -13
  52. package/dist/registry/types.d.ts.map +1 -1
  53. package/dist/schema/__bench__/node-parsers.bench.d.ts +24 -0
  54. package/dist/schema/__bench__/node-parsers.bench.d.ts.map +1 -0
  55. package/dist/schema/__bench__/node-parsers.bench.js +314 -0
  56. package/dist/schema/__fixtures__/node-fixtures.d.ts +28 -0
  57. package/dist/schema/__fixtures__/node-fixtures.d.ts.map +1 -0
  58. package/dist/schema/__fixtures__/node-fixtures.js +125 -0
  59. package/dist/schema/base.d.ts +1 -1
  60. package/dist/schema/base.d.ts.map +1 -1
  61. package/dist/schema/base.js +8 -1
  62. package/dist/schema/compiled-node-parsers.d.ts +40 -0
  63. package/dist/schema/compiled-node-parsers.d.ts.map +1 -0
  64. package/dist/schema/compiled-node-parsers.js +95 -0
  65. package/dist/schema/index.d.ts +19 -15
  66. package/dist/schema/index.d.ts.map +1 -1
  67. package/dist/schema/index.js +17 -12
  68. package/dist/schema/material.d.ts +2 -1
  69. package/dist/schema/material.d.ts.map +1 -1
  70. package/dist/schema/material.js +1 -0
  71. package/dist/schema/nodes/automatic-downspout.d.ts +17 -0
  72. package/dist/schema/nodes/automatic-downspout.d.ts.map +1 -0
  73. package/dist/schema/nodes/automatic-downspout.js +237 -0
  74. package/dist/schema/nodes/block.d.ts +107 -0
  75. package/dist/schema/nodes/block.d.ts.map +1 -0
  76. package/dist/schema/nodes/block.js +207 -0
  77. package/dist/schema/nodes/box-vent.d.ts +8 -2
  78. package/dist/schema/nodes/box-vent.d.ts.map +1 -1
  79. package/dist/schema/nodes/box-vent.js +2 -0
  80. package/dist/schema/nodes/building.d.ts +1 -1
  81. package/dist/schema/nodes/cabinet.d.ts +25 -3
  82. package/dist/schema/nodes/cabinet.d.ts.map +1 -1
  83. package/dist/schema/nodes/cabinet.js +26 -5
  84. package/dist/schema/nodes/ceiling.d.ts +1 -1
  85. package/dist/schema/nodes/chimney.d.ts +2 -2
  86. package/dist/schema/nodes/column.d.ts +6 -6
  87. package/dist/schema/nodes/construction-dimension.d.ts +4 -4
  88. package/dist/schema/nodes/cupola.d.ts +9 -1
  89. package/dist/schema/nodes/cupola.d.ts.map +1 -1
  90. package/dist/schema/nodes/cupola.js +2 -0
  91. package/dist/schema/nodes/door.d.ts +1 -1
  92. package/dist/schema/nodes/dormer.d.ts +44 -1
  93. package/dist/schema/nodes/dormer.d.ts.map +1 -1
  94. package/dist/schema/nodes/dormer.js +131 -7
  95. package/dist/schema/nodes/downspout.d.ts +11 -1
  96. package/dist/schema/nodes/downspout.d.ts.map +1 -1
  97. package/dist/schema/nodes/downspout.js +24 -0
  98. package/dist/schema/nodes/duct-fitting.d.ts +18 -1
  99. package/dist/schema/nodes/duct-fitting.d.ts.map +1 -1
  100. package/dist/schema/nodes/duct-fitting.js +25 -4
  101. package/dist/schema/nodes/duct-segment.d.ts +23 -1
  102. package/dist/schema/nodes/duct-segment.d.ts.map +1 -1
  103. package/dist/schema/nodes/duct-segment.js +20 -0
  104. package/dist/schema/nodes/duct-terminal.d.ts +1 -1
  105. package/dist/schema/nodes/elevator.d.ts +1 -1
  106. package/dist/schema/nodes/eyebrow-vent.d.ts +8 -2
  107. package/dist/schema/nodes/eyebrow-vent.d.ts.map +1 -1
  108. package/dist/schema/nodes/eyebrow-vent.js +2 -0
  109. package/dist/schema/nodes/fence.d.ts +1 -1
  110. package/dist/schema/nodes/guide.d.ts +1 -1
  111. package/dist/schema/nodes/gutter.d.ts +36 -2
  112. package/dist/schema/nodes/gutter.d.ts.map +1 -1
  113. package/dist/schema/nodes/gutter.js +308 -1
  114. package/dist/schema/nodes/hanger-overrides.d.ts +7 -0
  115. package/dist/schema/nodes/hanger-overrides.d.ts.map +1 -0
  116. package/dist/schema/nodes/hanger-overrides.js +6 -0
  117. package/dist/schema/nodes/hvac-equipment.d.ts +1 -1
  118. package/dist/schema/nodes/item.d.ts +4 -3
  119. package/dist/schema/nodes/item.d.ts.map +1 -1
  120. package/dist/schema/nodes/item.js +5 -0
  121. package/dist/schema/nodes/lean-to-extension.d.ts +212 -0
  122. package/dist/schema/nodes/lean-to-extension.d.ts.map +1 -0
  123. package/dist/schema/nodes/lean-to-extension.js +114 -0
  124. package/dist/schema/nodes/level.d.ts +2 -2
  125. package/dist/schema/nodes/level.d.ts.map +1 -1
  126. package/dist/schema/nodes/lineset.d.ts +1 -1
  127. package/dist/schema/nodes/liquid-line.d.ts +1 -1
  128. package/dist/schema/nodes/measurement.d.ts +1 -1
  129. package/dist/schema/nodes/pipe-fitting.d.ts +9 -1
  130. package/dist/schema/nodes/pipe-fitting.d.ts.map +1 -1
  131. package/dist/schema/nodes/pipe-fitting.js +6 -2
  132. package/dist/schema/nodes/pipe-segment.d.ts +23 -1
  133. package/dist/schema/nodes/pipe-segment.d.ts.map +1 -1
  134. package/dist/schema/nodes/pipe-segment.js +20 -0
  135. package/dist/schema/nodes/pipe-trap.d.ts +1 -1
  136. package/dist/schema/nodes/ridge-vent.d.ts +1 -1
  137. package/dist/schema/nodes/ridge-vent.d.ts.map +1 -1
  138. package/dist/schema/nodes/ridge-vent.js +4 -1
  139. package/dist/schema/nodes/roof-segment-shape.d.ts +4 -0
  140. package/dist/schema/nodes/roof-segment-shape.d.ts.map +1 -1
  141. package/dist/schema/nodes/roof-segment-shape.js +64 -1
  142. package/dist/schema/nodes/roof-segment-walls.d.ts +3 -1
  143. package/dist/schema/nodes/roof-segment-walls.d.ts.map +1 -1
  144. package/dist/schema/nodes/roof-segment-walls.js +1 -1
  145. package/dist/schema/nodes/roof-segment.d.ts +41 -1
  146. package/dist/schema/nodes/roof-segment.d.ts.map +1 -1
  147. package/dist/schema/nodes/roof-segment.js +79 -2
  148. package/dist/schema/nodes/roof.d.ts +22 -1
  149. package/dist/schema/nodes/roof.d.ts.map +1 -1
  150. package/dist/schema/nodes/roof.js +14 -0
  151. package/dist/schema/nodes/scan.d.ts +19 -2
  152. package/dist/schema/nodes/scan.d.ts.map +1 -1
  153. package/dist/schema/nodes/scan.js +11 -1
  154. package/dist/schema/nodes/shelf.d.ts +2 -2
  155. package/dist/schema/nodes/site.d.ts +1 -1
  156. package/dist/schema/nodes/skylight.d.ts +1 -1
  157. package/dist/schema/nodes/slab.d.ts +1 -1
  158. package/dist/schema/nodes/solar-panel.d.ts +1 -1
  159. package/dist/schema/nodes/spawn.d.ts +1 -1
  160. package/dist/schema/nodes/stair-segment.d.ts +1 -1
  161. package/dist/schema/nodes/stair.d.ts +1 -1
  162. package/dist/schema/nodes/structural-grid.d.ts +1 -1
  163. package/dist/schema/nodes/turbine-vent.d.ts +7 -1
  164. package/dist/schema/nodes/turbine-vent.d.ts.map +1 -1
  165. package/dist/schema/nodes/turbine-vent.js +2 -0
  166. package/dist/schema/nodes/wall.d.ts +4 -4
  167. package/dist/schema/nodes/wall.d.ts.map +1 -1
  168. package/dist/schema/nodes/wall.js +7 -1
  169. package/dist/schema/nodes/window.d.ts +10 -3
  170. package/dist/schema/nodes/window.d.ts.map +1 -1
  171. package/dist/schema/nodes/window.js +4 -0
  172. package/dist/schema/nodes/zone.d.ts +2 -2
  173. package/dist/schema/nodes/zone.js +1 -1
  174. package/dist/schema/types.d.ts +484 -109
  175. package/dist/schema/types.d.ts.map +1 -1
  176. package/dist/schema/types.js +27 -1
  177. package/dist/services/hosting.d.ts +2 -2
  178. package/dist/services/hosting.d.ts.map +1 -1
  179. package/dist/services/hosting.js +4 -4
  180. package/dist/services/index.d.ts +1 -1
  181. package/dist/services/index.d.ts.map +1 -1
  182. package/dist/services/index.js +1 -1
  183. package/dist/services/system-graph.d.ts +11 -0
  184. package/dist/services/system-graph.d.ts.map +1 -1
  185. package/dist/services/system-graph.js +35 -5
  186. package/dist/store/actions/node-actions.d.ts +7 -0
  187. package/dist/store/actions/node-actions.d.ts.map +1 -1
  188. package/dist/store/actions/node-actions.js +429 -17
  189. package/dist/store/history-invalidation.d.ts +3 -0
  190. package/dist/store/history-invalidation.d.ts.map +1 -0
  191. package/dist/store/history-invalidation.js +72 -0
  192. package/dist/store/scene-hydration.d.ts +5 -0
  193. package/dist/store/scene-hydration.d.ts.map +1 -0
  194. package/dist/store/scene-hydration.js +57 -0
  195. package/dist/store/use-scene.d.ts +3 -0
  196. package/dist/store/use-scene.d.ts.map +1 -1
  197. package/dist/store/use-scene.js +332 -64
  198. package/dist/systems/roof/roof-elevation-system.d.ts +3 -0
  199. package/dist/systems/roof/roof-elevation-system.d.ts.map +1 -0
  200. package/dist/systems/roof/roof-elevation-system.js +94 -0
  201. package/dist/systems/roof/roof-elevation.d.ts +4 -0
  202. package/dist/systems/roof/roof-elevation.d.ts.map +1 -0
  203. package/dist/systems/roof/roof-elevation.js +95 -0
  204. package/dist/systems/roof/roof-footprint.d.ts +17 -0
  205. package/dist/systems/roof/roof-footprint.d.ts.map +1 -0
  206. package/dist/systems/roof/roof-footprint.js +83 -0
  207. package/dist/systems/stair/stair-flight.d.ts +17 -0
  208. package/dist/systems/stair/stair-flight.d.ts.map +1 -0
  209. package/dist/systems/stair/stair-flight.js +27 -0
  210. package/dist/systems/stair/stair-opening-preview.d.ts +1555 -1328
  211. package/dist/systems/stair/stair-opening-preview.d.ts.map +1 -1
  212. package/dist/systems/stair/stair-opening-system.d.ts +1 -0
  213. package/dist/systems/stair/stair-opening-system.d.ts.map +1 -1
  214. package/dist/systems/stair/stair-opening-system.js +93 -96
  215. package/dist/systems/stair/stair-rise.d.ts.map +1 -1
  216. package/dist/systems/stair/stair-rise.js +20 -21
  217. package/dist/systems/wall/wall-curve.d.ts +1 -0
  218. package/dist/systems/wall/wall-curve.d.ts.map +1 -1
  219. package/dist/systems/wall/wall-curve.js +73 -0
  220. package/dist/systems/wall/wall-footprint.d.ts +1 -0
  221. package/dist/systems/wall/wall-footprint.d.ts.map +1 -1
  222. package/dist/systems/wall/wall-footprint.js +1 -0
  223. package/dist/utils/clone-scene-graph.d.ts.map +1 -1
  224. package/dist/utils/clone-scene-graph.js +26 -0
  225. package/dist/validation/validate-build-json.d.ts +3 -0
  226. package/dist/validation/validate-build-json.d.ts.map +1 -1
  227. package/dist/validation/validate-build-json.js +49 -2
  228. package/package.json +10 -3
  229. package/dist/systems/elevator/elevator-runtime-system.d.ts +0 -2
  230. package/dist/systems/elevator/elevator-runtime-system.d.ts.map +0 -1
  231. package/dist/systems/elevator/elevator-runtime-system.js +0 -8
@@ -2,6 +2,13 @@ import dedent from 'dedent';
2
2
  import { z } from 'zod';
3
3
  import { BaseNode, nodeType, objectId } from '../base';
4
4
  import { MaterialSchema } from '../material';
5
+ import { normalizeRoofSegmentTrim } from './roof-segment';
6
+ import { getRoofShapeEaveSides } from './roof-segment-shape';
7
+ const MIN_DEFAULT_GUTTER_LENGTH_M = 0.2;
8
+ const DEFAULT_GUTTER_GENERATOR = 'default-gutter';
9
+ const AUTO_GUTTER_METADATA_KEY = 'autoGutter';
10
+ export const GUTTER_EAVE_TUCK_INWARD = 0.04;
11
+ export const GUTTER_EAVE_TUCK_UP = 0.04;
5
12
  // A single drop outlet drilled in the gutter floor. A gutter can carry
6
13
  // several so a long run can split between multiple downspouts (each
7
14
  // downspout links to one outlet via its `outletId`).
@@ -15,11 +22,13 @@ export const GutterOutlet = z.object({
15
22
  // Bore diameter of this drop. Default 0.07 m ≈ 3″. The cross-section
16
23
  // SHAPE (round vs rectangular) follows the gutter's profile, not this.
17
24
  diameter: z.number().default(0.07),
25
+ generatedBy: z.literal('default-downspout').optional(),
18
26
  });
19
27
  export const GutterNode = BaseNode.extend({
20
28
  id: objectId('gutter'),
21
29
  type: nodeType('gutter'),
22
30
  material: MaterialSchema.optional(),
31
+ slots: z.record(z.string(), z.string()).optional(),
23
32
  // White preset by default — matches the rest of the roof accessory
24
33
  // family (box-vent / ridge-vent) so the paint inspector reads as
25
34
  // "White" instead of "no material" on a freshly-placed gutter.
@@ -35,8 +44,19 @@ export const GutterNode = BaseNode.extend({
35
44
  // direction (segment-local +X) — but exposed in case the user wants
36
45
  // to tilt for a custom run.
37
46
  rotation: z.number().default(0),
38
- // Length along the eave (gutter-local +X).
47
+ // Length along the eave (gutter-local +X). For a curved eave this is the
48
+ // arc length of the run.
39
49
  length: z.number().default(2.0),
50
+ // Concentric-arc descriptor for a run that follows a curved eave, in
51
+ // gutter-mesh-local coordinates (center + true radius). Absent for a straight
52
+ // gutter.
53
+ arc: z
54
+ .object({
55
+ centerX: z.number(),
56
+ centerZ: z.number(),
57
+ radius: z.number(),
58
+ })
59
+ .optional(),
40
60
  // Profile size — the vertical drop of the U-channel below the eave
41
61
  // line. 5″ (0.127 m) is the most common residential gutter size; 6″
42
62
  // (0.152 m) is the common commercial / heavy-duty size. Default
@@ -74,3 +94,290 @@ export const GutterNode = BaseNode.extend({
74
94
  - hangerStyle / hangerSpacing: visible metal straps across the rim
75
95
  - outlets: drop-tube outlets (id + along-length offset + bore diameter)
76
96
  `);
97
+ function metadataRecord(metadata) {
98
+ if (typeof metadata === 'object' && metadata !== null && !Array.isArray(metadata)) {
99
+ return metadata;
100
+ }
101
+ return {};
102
+ }
103
+ export function computeGutterEaveY(segment) {
104
+ const wallHeight = segment.wallHeight ?? 0;
105
+ if ((segment.roofType ?? 'gable') === 'flat')
106
+ return wallHeight;
107
+ const pitchRad = ((segment.pitch ?? 0) * Math.PI) / 180;
108
+ return wallHeight - (segment.overhang ?? 0) * Math.tan(pitchRad) + GUTTER_EAVE_TUCK_UP;
109
+ }
110
+ function getDefaultGutterSides(segment) {
111
+ return getRoofShapeEaveSides(segment.roofType);
112
+ }
113
+ function getGutterEnvelope(segment) {
114
+ const halfW = Math.max(0, segment.width) / 2;
115
+ const halfD = Math.max(0, segment.depth) / 2;
116
+ const overhang = Math.max(0, segment.overhang ?? 0);
117
+ const outerHalfW = Math.max(halfW, halfW + overhang - GUTTER_EAVE_TUCK_INWARD);
118
+ const outerHalfD = Math.max(halfD, halfD + overhang - GUTTER_EAVE_TUCK_INWARD);
119
+ const trim = normalizeRoofSegmentTrim(segment);
120
+ const minX = trim.left > 0 ? -halfW + trim.left : -outerHalfW;
121
+ const maxX = trim.right > 0 ? halfW - trim.right : outerHalfW;
122
+ const minZ = trim.back > 0 ? -halfD + trim.back : -outerHalfD;
123
+ const maxZ = trim.front > 0 ? halfD - trim.front : outerHalfD;
124
+ return { minX, maxX, minZ, maxZ, outerHalfW, outerHalfD, trim };
125
+ }
126
+ function getGutterEnvelopePolygon(segment) {
127
+ const { minX, maxX, minZ, maxZ, trim } = getGutterEnvelope(segment);
128
+ return [
129
+ [minX + trim.backLeftX, minZ],
130
+ [maxX - trim.backRightX, minZ],
131
+ [maxX, minZ + trim.backRightZ],
132
+ [maxX, maxZ - trim.frontRightZ],
133
+ [maxX - trim.frontRightX, maxZ],
134
+ [minX + trim.frontLeftX, maxZ],
135
+ [minX, maxZ - trim.frontLeftZ],
136
+ [minX, minZ + trim.backLeftZ],
137
+ ];
138
+ }
139
+ function segmentLocalToRoof(segment, point) {
140
+ const rotation = segment.rotation ?? 0;
141
+ const cos = Math.cos(rotation);
142
+ const sin = Math.sin(rotation);
143
+ return [
144
+ (segment.position?.[0] ?? 0) + point[0] * cos + point[1] * sin,
145
+ (segment.position?.[2] ?? 0) - point[0] * sin + point[1] * cos,
146
+ ];
147
+ }
148
+ function pointOnSegment(point, a, b) {
149
+ const lengthSq = (b[0] - a[0]) ** 2 + (b[1] - a[1]) ** 2;
150
+ if (lengthSq <= 1e-14) {
151
+ return (point[0] - a[0]) ** 2 + (point[1] - a[1]) ** 2 <= 1e-14;
152
+ }
153
+ const cross = (point[0] - a[0]) * (b[1] - a[1]) - (point[1] - a[1]) * (b[0] - a[0]);
154
+ if (Math.abs(cross) > 1e-7)
155
+ return false;
156
+ const dot = (point[0] - a[0]) * (b[0] - a[0]) + (point[1] - a[1]) * (b[1] - a[1]);
157
+ if (dot < -1e-7)
158
+ return false;
159
+ return dot <= lengthSq + 1e-7;
160
+ }
161
+ function pointStrictlyInsidePolygon(point, polygon) {
162
+ let inside = false;
163
+ for (let i = 0, j = polygon.length - 1; i < polygon.length; j = i++) {
164
+ const a = polygon[j];
165
+ const b = polygon[i];
166
+ if (pointOnSegment(point, a, b))
167
+ return false;
168
+ if (a[1] > point[1] !== b[1] > point[1] &&
169
+ point[0] < ((b[0] - a[0]) * (point[1] - a[1])) / (b[1] - a[1]) + a[0]) {
170
+ inside = !inside;
171
+ }
172
+ }
173
+ return inside;
174
+ }
175
+ function segmentCrossingT(start, end, a, b) {
176
+ const rx = end[0] - start[0];
177
+ const rz = end[1] - start[1];
178
+ const sx = b[0] - a[0];
179
+ const sz = b[1] - a[1];
180
+ const denominator = rx * sz - rz * sx;
181
+ if (Math.abs(denominator) < 1e-10)
182
+ return null;
183
+ const dx = a[0] - start[0];
184
+ const dz = a[1] - start[1];
185
+ const t = (dx * sz - dz * sx) / denominator;
186
+ const u = (dx * rz - dz * rx) / denominator;
187
+ if (t < -1e-8 || t > 1 + 1e-8 || u < -1e-8 || u > 1 + 1e-8)
188
+ return null;
189
+ return Math.max(0, Math.min(1, t));
190
+ }
191
+ function coveredIntervals(start, end, polygon) {
192
+ const splits = [0, 1];
193
+ for (let i = 0; i < polygon.length; i++) {
194
+ const t = segmentCrossingT(start, end, polygon[i], polygon[(i + 1) % polygon.length]);
195
+ if (t !== null)
196
+ splits.push(t);
197
+ }
198
+ splits.sort((a, b) => a - b);
199
+ const unique = splits.filter((value, index) => index === 0 || value - splits[index - 1] > 1e-7);
200
+ const intervals = [];
201
+ for (let i = 0; i < unique.length - 1; i++) {
202
+ const from = unique[i];
203
+ const to = unique[i + 1];
204
+ if (to - from <= 1e-7)
205
+ continue;
206
+ const middle = (from + to) / 2;
207
+ const point = [
208
+ start[0] + (end[0] - start[0]) * middle,
209
+ start[1] + (end[1] - start[1]) * middle,
210
+ ];
211
+ if (pointStrictlyInsidePolygon(point, polygon))
212
+ intervals.push([from, to]);
213
+ }
214
+ return intervals;
215
+ }
216
+ function subtractInterval(visible, covered) {
217
+ const next = [];
218
+ for (const [from, to] of visible) {
219
+ if (covered[1] <= from + 1e-7 || covered[0] >= to - 1e-7) {
220
+ next.push([from, to]);
221
+ continue;
222
+ }
223
+ if (covered[0] > from + 1e-7)
224
+ next.push([from, Math.min(to, covered[0])]);
225
+ if (covered[1] < to - 1e-7)
226
+ next.push([Math.max(from, covered[1]), to]);
227
+ }
228
+ return next;
229
+ }
230
+ function clipRunAgainstSegments(run, segment, roofSegments) {
231
+ const direction = [Math.cos(run.rotation), -Math.sin(run.rotation)];
232
+ const localStart = [
233
+ run.position[0] - direction[0] * (run.length / 2),
234
+ run.position[2] - direction[1] * (run.length / 2),
235
+ ];
236
+ const localEnd = [
237
+ run.position[0] + direction[0] * (run.length / 2),
238
+ run.position[2] + direction[1] * (run.length / 2),
239
+ ];
240
+ const roofStart = segmentLocalToRoof(segment, localStart);
241
+ const roofEnd = segmentLocalToRoof(segment, localEnd);
242
+ let visible = [[0, 1]];
243
+ for (const sibling of roofSegments) {
244
+ if (sibling.id === segment.id)
245
+ continue;
246
+ const polygon = getGutterEnvelopePolygon(sibling).map((point) => segmentLocalToRoof(sibling, point));
247
+ for (const covered of coveredIntervals(roofStart, roofEnd, polygon)) {
248
+ visible = subtractInterval(visible, covered);
249
+ }
250
+ if (visible.length === 0)
251
+ break;
252
+ }
253
+ return visible
254
+ .map(([from, to]) => {
255
+ const length = run.length * (to - from);
256
+ const middle = (from + to) / 2;
257
+ return {
258
+ ...run,
259
+ position: [
260
+ localStart[0] + (localEnd[0] - localStart[0]) * middle,
261
+ run.position[1],
262
+ localStart[1] + (localEnd[1] - localStart[1]) * middle,
263
+ ],
264
+ length,
265
+ };
266
+ })
267
+ .filter((candidate) => candidate.length >= MIN_DEFAULT_GUTTER_LENGTH_M);
268
+ }
269
+ function clipRunAgainstExclusions(run, exclusions) {
270
+ let visible = [[0, 1]];
271
+ for (const exclusion of exclusions) {
272
+ if (exclusion.side !== run.side)
273
+ continue;
274
+ const from = Math.max(0, Math.min(1, Math.min(exclusion.from, exclusion.to)));
275
+ const to = Math.max(0, Math.min(1, Math.max(exclusion.from, exclusion.to)));
276
+ visible = subtractInterval(visible, [from, to]);
277
+ if (visible.length === 0)
278
+ break;
279
+ }
280
+ const direction = [Math.cos(run.rotation), -Math.sin(run.rotation)];
281
+ const start = [
282
+ run.position[0] - direction[0] * (run.length / 2),
283
+ run.position[2] - direction[1] * (run.length / 2),
284
+ ];
285
+ return visible
286
+ .map(([from, to]) => {
287
+ const length = run.length * (to - from);
288
+ const middle = (from + to) / 2;
289
+ return {
290
+ ...run,
291
+ position: [
292
+ start[0] + direction[0] * run.length * middle,
293
+ run.position[1],
294
+ start[1] + direction[1] * run.length * middle,
295
+ ],
296
+ length,
297
+ };
298
+ })
299
+ .filter((candidate) => candidate.length >= MIN_DEFAULT_GUTTER_LENGTH_M);
300
+ }
301
+ export function getGutterRunsForSegment(segment, roofSegments = [], exclusions = []) {
302
+ const { minX, maxX, minZ, maxZ, outerHalfW, outerHalfD, trim } = getGutterEnvelope(segment);
303
+ const eaveY = computeGutterEaveY(segment);
304
+ const runs = {
305
+ '+Z': trim.front > 0
306
+ ? null
307
+ : {
308
+ side: '+Z',
309
+ position: [(minX + maxX) / 2, eaveY, outerHalfD],
310
+ rotation: 0,
311
+ length: maxX - minX,
312
+ },
313
+ '-Z': trim.back > 0
314
+ ? null
315
+ : {
316
+ side: '-Z',
317
+ position: [(minX + maxX) / 2, eaveY, -outerHalfD],
318
+ rotation: Math.PI,
319
+ length: maxX - minX,
320
+ },
321
+ '+X': trim.right > 0
322
+ ? null
323
+ : {
324
+ side: '+X',
325
+ position: [outerHalfW, eaveY, (minZ + maxZ) / 2],
326
+ rotation: Math.PI / 2,
327
+ length: maxZ - minZ,
328
+ },
329
+ '-X': trim.left > 0
330
+ ? null
331
+ : {
332
+ side: '-X',
333
+ position: [-outerHalfW, eaveY, (minZ + maxZ) / 2],
334
+ rotation: -Math.PI / 2,
335
+ length: maxZ - minZ,
336
+ },
337
+ };
338
+ const candidates = getDefaultGutterSides(segment)
339
+ .map((side) => runs[side])
340
+ .filter((run) => run !== null && run.length >= MIN_DEFAULT_GUTTER_LENGTH_M);
341
+ return candidates
342
+ .flatMap((run) => clipRunAgainstExclusions(run, exclusions))
343
+ .flatMap((run) => clipRunAgainstSegments(run, segment, roofSegments));
344
+ }
345
+ export function createDefaultGuttersForSegment(segment, roofSegments = [], exclusions = []) {
346
+ return getGutterRunsForSegment(segment, roofSegments, exclusions).map((run) => GutterNode.parse({
347
+ name: 'Gutter',
348
+ roofSegmentId: segment.id,
349
+ position: run.position,
350
+ rotation: run.rotation,
351
+ length: run.length,
352
+ metadata: {
353
+ generatedBy: DEFAULT_GUTTER_GENERATOR,
354
+ autoGutterSide: run.side,
355
+ },
356
+ }));
357
+ }
358
+ export function getDefaultGutterSide(node, roofSegmentId) {
359
+ const parsed = GutterNode.safeParse(node);
360
+ if (!parsed.success)
361
+ return null;
362
+ if (roofSegmentId && parsed.data.roofSegmentId !== roofSegmentId)
363
+ return null;
364
+ const metadata = metadataRecord(parsed.data.metadata);
365
+ if (metadata.generatedBy !== DEFAULT_GUTTER_GENERATOR)
366
+ return null;
367
+ const side = metadata.autoGutterSide;
368
+ return side === '+X' || side === '-X' || side === '+Z' || side === '-Z' ? side : null;
369
+ }
370
+ export function isDefaultGutterNode(node, roofSegmentId) {
371
+ return getDefaultGutterSide(node, roofSegmentId) !== null;
372
+ }
373
+ export function hasAutoGutterMetadata(segment) {
374
+ return typeof metadataRecord(segment.metadata)[AUTO_GUTTER_METADATA_KEY] === 'boolean';
375
+ }
376
+ export function isAutoGutterEnabled(segment, nodes) {
377
+ const metadataValue = metadataRecord(segment.metadata)[AUTO_GUTTER_METADATA_KEY];
378
+ if (typeof metadataValue === 'boolean')
379
+ return metadataValue;
380
+ if (!nodes)
381
+ return false;
382
+ return (segment.children ?? []).some((childId) => isDefaultGutterNode(nodes[childId], segment.id));
383
+ }
@@ -0,0 +1,7 @@
1
+ import { z } from 'zod';
2
+ export declare const HangerOverrides: z.ZodRecord<z.ZodString, z.ZodObject<{
3
+ fraction: z.ZodOptional<z.ZodNumber>;
4
+ skipped: z.ZodOptional<z.ZodBoolean>;
5
+ hostId: z.ZodOptional<z.ZodString>;
6
+ }, z.core.$strip>>;
7
+ //# sourceMappingURL=hanger-overrides.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hanger-overrides.d.ts","sourceRoot":"","sources":["../../../src/schema/nodes/hanger-overrides.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB,eAAO,MAAM,eAAe;;;;kBAO3B,CAAA"}
@@ -0,0 +1,6 @@
1
+ import { z } from 'zod';
2
+ export const HangerOverrides = z.record(z.string(), z.object({
3
+ fraction: z.number().finite().min(0).max(1).optional(),
4
+ skipped: z.boolean().optional(),
5
+ hostId: z.string().optional(),
6
+ }));
@@ -28,7 +28,7 @@ export declare const HvacEquipmentNode: z.ZodObject<{
28
28
  fov: z.ZodOptional<z.ZodNumber>;
29
29
  zoom: z.ZodOptional<z.ZodNumber>;
30
30
  }, z.core.$strip>>;
31
- metadata: z.ZodDefault<z.ZodOptional<z.ZodJSONSchema>>;
31
+ metadata: z.ZodDefault<z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
32
32
  id: z.ZodDefault<z.ZodTemplateLiteral<`hvac-equipment_${string}`>>;
33
33
  type: z.ZodDefault<z.ZodLiteral<"hvac-equipment">>;
34
34
  position: z.ZodDefault<z.ZodTuple<[z.ZodNumber, z.ZodNumber, z.ZodNumber], null>>;
@@ -154,8 +154,8 @@ declare const assetSchema: z.ZodObject<{
154
154
  dimensions: z.ZodDefault<z.ZodTuple<[z.ZodNumber, z.ZodNumber, z.ZodNumber], null>>;
155
155
  attachTo: z.ZodOptional<z.ZodEnum<{
156
156
  wall: "wall";
157
- ceiling: "ceiling";
158
157
  "wall-side": "wall-side";
158
+ ceiling: "ceiling";
159
159
  }>>;
160
160
  recessed: z.ZodOptional<z.ZodBoolean>;
161
161
  tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
@@ -228,7 +228,7 @@ export declare const ItemNode: z.ZodObject<{
228
228
  fov: z.ZodOptional<z.ZodNumber>;
229
229
  zoom: z.ZodOptional<z.ZodNumber>;
230
230
  }, z.core.$strip>>;
231
- metadata: z.ZodDefault<z.ZodOptional<z.ZodJSONSchema>>;
231
+ metadata: z.ZodDefault<z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
232
232
  id: z.ZodDefault<z.ZodTemplateLiteral<`item_${string}`>>;
233
233
  type: z.ZodDefault<z.ZodLiteral<"item">>;
234
234
  position: z.ZodDefault<z.ZodTuple<[z.ZodNumber, z.ZodNumber, z.ZodNumber], null>>;
@@ -248,6 +248,7 @@ export declare const ItemNode: z.ZodObject<{
248
248
  right: "right";
249
249
  left: "left";
250
250
  }>>;
251
+ blockFaceId: z.ZodOptional<z.ZodString>;
251
252
  supportSlabId: z.ZodOptional<z.ZodString>;
252
253
  collectionIds: z.ZodOptional<z.ZodArray<z.ZodCustom<`collection_${string}`, `collection_${string}`>>>;
253
254
  slots: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
@@ -267,8 +268,8 @@ export declare const ItemNode: z.ZodObject<{
267
268
  dimensions: z.ZodDefault<z.ZodTuple<[z.ZodNumber, z.ZodNumber, z.ZodNumber], null>>;
268
269
  attachTo: z.ZodOptional<z.ZodEnum<{
269
270
  wall: "wall";
270
- ceiling: "ceiling";
271
271
  "wall-side": "wall-side";
272
+ ceiling: "ceiling";
272
273
  }>>;
273
274
  recessed: z.ZodOptional<z.ZodBoolean>;
274
275
  tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
@@ -1 +1 @@
1
- {"version":3,"file":"item.d.ts","sourceRoot":"","sources":["../../../src/schema/nodes/item.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAOvB,QAAA,MAAM,mBAAmB;;;;iBAIvB,CAAA;AAEF,QAAA,MAAM,mBAAmB;;;;;;;;;;;;;iBASvB,CAAA;AAEF,QAAA,MAAM,wBAAwB;;;;;;;;;;iBAO5B,CAAA;AAEF,QAAA,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;2BAIjB,CAAA;AAIF,QAAA,MAAM,qBAAqB;;;;;;;iBAOzB,CAAA;AAEF,QAAA,MAAM,iBAAiB;;;;;;iBAMrB,CAAA;AAEF,QAAA,MAAM,YAAY;;;;;;;;;;;;;2BAA2E,CAAA;AAI7F,QAAA,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAGrB,CAAA;AAEF,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAA;AAC/D,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAA;AAC/D,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAA;AACzE,MAAM,MAAM,OAAO,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,aAAa,CAAC,CAAA;AACnD,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAA;AACnE,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAA;AAC3D,MAAM,MAAM,MAAM,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,YAAY,CAAC,CAAA;AACjD,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAA;AAE3D,QAAA,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA2Cf,CAAA;AAEF,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC,CAAA;AACpD,MAAM,MAAM,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC,CAAA;AAE/C,eAAO,MAAM,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAuDnB,CAAA;AAEF,MAAM,MAAM,QAAQ,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,QAAQ,CAAC,CAAA;AAE/C,eAAO,MAAM,mCAAmC,MAAM,CAAA;AAEtD;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,QAAQ,GAAG,OAAO,CAM/D;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,QAAQ,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAI5E"}
1
+ {"version":3,"file":"item.d.ts","sourceRoot":"","sources":["../../../src/schema/nodes/item.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAOvB,QAAA,MAAM,mBAAmB;;;;iBAIvB,CAAA;AAEF,QAAA,MAAM,mBAAmB;;;;;;;;;;;;;iBASvB,CAAA;AAEF,QAAA,MAAM,wBAAwB;;;;;;;;;;iBAO5B,CAAA;AAEF,QAAA,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;2BAIjB,CAAA;AAIF,QAAA,MAAM,qBAAqB;;;;;;;iBAOzB,CAAA;AAEF,QAAA,MAAM,iBAAiB;;;;;;iBAMrB,CAAA;AAEF,QAAA,MAAM,YAAY;;;;;;;;;;;;;2BAA2E,CAAA;AAI7F,QAAA,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAGrB,CAAA;AAEF,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAA;AAC/D,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAA;AAC/D,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAA;AACzE,MAAM,MAAM,OAAO,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,aAAa,CAAC,CAAA;AACnD,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAA;AACnE,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAA;AAC3D,MAAM,MAAM,MAAM,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,YAAY,CAAC,CAAA;AACjD,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAA;AAE3D,QAAA,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA2Cf,CAAA;AAEF,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC,CAAA;AACpD,MAAM,MAAM,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC,CAAA;AAE/C,eAAO,MAAM,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA4DnB,CAAA;AAEF,MAAM,MAAM,QAAQ,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,QAAQ,CAAC,CAAA;AAE/C,eAAO,MAAM,mCAAmC,MAAM,CAAA;AAEtD;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,QAAQ,GAAG,OAAO,CAM/D;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,QAAQ,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAI5E"}
@@ -115,6 +115,11 @@ export const ItemNode = BaseNode.extend({
115
115
  // mounts the node inside the face frame (`getRoofWallFaceFrame`).
116
116
  roofSegmentId: z.string().optional(),
117
117
  roofFace: z.enum(['front', 'back', 'right', 'left']).optional(),
118
+ // Alternative wall-like host: a planar block face. Position is
119
+ // FACE-LOCAL [u, v, normal offset], relative to the live face centroid.
120
+ // The renderer rebuilds the frame from the face normal so the item follows
121
+ // later edits that translate or slope the face.
122
+ blockFaceId: z.string().optional(),
118
123
  // Persisted floor-support host (canonical doc — the same field on other
119
124
  // floor-placed kinds and walls follows these rules). Written at
120
125
  // placement/commit ONLY when overlapping slabs disagree on elevation
@@ -0,0 +1,212 @@
1
+ import { z } from 'zod';
2
+ export declare const LeanToConnectionMode: z.ZodEnum<{
3
+ manual: "manual";
4
+ auto: "auto";
5
+ }>;
6
+ export declare const LeanToCanopyForm: z.ZodEnum<{
7
+ gable: "gable";
8
+ mono: "mono";
9
+ butterfly: "butterfly";
10
+ }>;
11
+ export declare const LeanToHostKind: z.ZodEnum<{
12
+ wall: "wall";
13
+ "slab-edge": "slab-edge";
14
+ freestanding: "freestanding";
15
+ "conical-roof": "conical-roof";
16
+ }>;
17
+ export declare const LeanToRoofEdge: z.ZodEnum<{
18
+ "+X": "+X";
19
+ "-X": "-X";
20
+ "+Z": "+Z";
21
+ "-Z": "-Z";
22
+ }>;
23
+ export declare const LeanToResizeLock: z.ZodEnum<{
24
+ "preserve-high-edge": "preserve-high-edge";
25
+ "preserve-low-edge": "preserve-low-edge";
26
+ "preserve-pitch": "preserve-pitch";
27
+ }>;
28
+ export declare const LeanToEndCondition: z.ZodEnum<{
29
+ open: "open";
30
+ "wall-abutment": "wall-abutment";
31
+ joined: "joined";
32
+ }>;
33
+ export declare const LeanToFramingStrategy: z.ZodEnum<{
34
+ hidden: "hidden";
35
+ rafters: "rafters";
36
+ purlins: "purlins";
37
+ "covering-specific": "covering-specific";
38
+ }>;
39
+ export declare const LeanToHighSideMode: z.ZodEnum<{
40
+ "wall-ledger": "wall-ledger";
41
+ "independent-high-beam": "independent-high-beam";
42
+ }>;
43
+ export declare const LeanToPostLayoutMode: z.ZodEnum<{
44
+ count: "count";
45
+ "target-spacing": "target-spacing";
46
+ }>;
47
+ export declare const LeanToFootingStyle: z.ZodEnum<{
48
+ none: "none";
49
+ "base-plate": "base-plate";
50
+ "concrete-pad": "concrete-pad";
51
+ }>;
52
+ export declare const LeanToCoveringType: z.ZodEnum<{
53
+ generic: "generic";
54
+ shingle: "shingle";
55
+ "metal-panel": "metal-panel";
56
+ }>;
57
+ export type LeanToConnectionMode = z.infer<typeof LeanToConnectionMode>;
58
+ export type LeanToCanopyForm = z.infer<typeof LeanToCanopyForm>;
59
+ export type LeanToRoofEdge = z.infer<typeof LeanToRoofEdge>;
60
+ export declare const LeanToExtensionNode: z.ZodObject<{
61
+ object: z.ZodDefault<z.ZodLiteral<"node">>;
62
+ name: z.ZodOptional<z.ZodString>;
63
+ parentId: z.ZodDefault<z.ZodNullable<z.ZodString>>;
64
+ visible: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
65
+ camera: z.ZodOptional<z.ZodObject<{
66
+ position: z.ZodTuple<[z.ZodNumber, z.ZodNumber, z.ZodNumber], null>;
67
+ target: z.ZodTuple<[z.ZodNumber, z.ZodNumber, z.ZodNumber], null>;
68
+ mode: z.ZodDefault<z.ZodEnum<{
69
+ perspective: "perspective";
70
+ orthographic: "orthographic";
71
+ }>>;
72
+ fov: z.ZodOptional<z.ZodNumber>;
73
+ zoom: z.ZodOptional<z.ZodNumber>;
74
+ }, z.core.$strip>>;
75
+ metadata: z.ZodDefault<z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
76
+ id: z.ZodDefault<z.ZodTemplateLiteral<`leanto_${string}`>>;
77
+ type: z.ZodDefault<z.ZodLiteral<"lean-to-extension">>;
78
+ position: z.ZodDefault<z.ZodTuple<[z.ZodNumber, z.ZodNumber, z.ZodNumber], null>>;
79
+ rotation: z.ZodDefault<z.ZodTuple<[z.ZodNumber, z.ZodNumber, z.ZodNumber], null>>;
80
+ children: z.ZodDefault<z.ZodArray<z.ZodUnion<readonly [z.ZodDefault<z.ZodTemplateLiteral<`column_${string}`>>, z.ZodDefault<z.ZodTemplateLiteral<`roof_${string}`>>]>>>;
81
+ canopyForm: z.ZodDefault<z.ZodEnum<{
82
+ gable: "gable";
83
+ mono: "mono";
84
+ butterfly: "butterfly";
85
+ }>>;
86
+ hostKind: z.ZodDefault<z.ZodEnum<{
87
+ wall: "wall";
88
+ "slab-edge": "slab-edge";
89
+ freestanding: "freestanding";
90
+ "conical-roof": "conical-roof";
91
+ }>>;
92
+ hostHeightOffset: z.ZodDefault<z.ZodNumber>;
93
+ hostSlabId: z.ZodOptional<z.ZodDefault<z.ZodTemplateLiteral<`slab_${string}`>>>;
94
+ hostSlabEdgeIndex: z.ZodOptional<z.ZodNumber>;
95
+ hostSlabEdgeT: z.ZodOptional<z.ZodNumber>;
96
+ span: z.ZodDefault<z.ZodNumber>;
97
+ autoSpan: z.ZodDefault<z.ZodBoolean>;
98
+ projection: z.ZodDefault<z.ZodNumber>;
99
+ spanArcCenterZ: z.ZodOptional<z.ZodNumber>;
100
+ spanArcRadius: z.ZodOptional<z.ZodNumber>;
101
+ highEdgeHeight: z.ZodDefault<z.ZodNumber>;
102
+ lowEdgeHeight: z.ZodDefault<z.ZodNumber>;
103
+ pitch: z.ZodDefault<z.ZodNumber>;
104
+ resizeLock: z.ZodDefault<z.ZodEnum<{
105
+ "preserve-high-edge": "preserve-high-edge";
106
+ "preserve-low-edge": "preserve-low-edge";
107
+ "preserve-pitch": "preserve-pitch";
108
+ }>>;
109
+ leftEndCondition: z.ZodDefault<z.ZodEnum<{
110
+ open: "open";
111
+ "wall-abutment": "wall-abutment";
112
+ joined: "joined";
113
+ }>>;
114
+ rightEndCondition: z.ZodDefault<z.ZodEnum<{
115
+ open: "open";
116
+ "wall-abutment": "wall-abutment";
117
+ joined: "joined";
118
+ }>>;
119
+ autoMiterCorners: z.ZodDefault<z.ZodBoolean>;
120
+ sideFlashing: z.ZodDefault<z.ZodBoolean>;
121
+ flashingProjection: z.ZodDefault<z.ZodNumber>;
122
+ flashingHeight: z.ZodDefault<z.ZodNumber>;
123
+ slots: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
124
+ highSideMode: z.ZodDefault<z.ZodEnum<{
125
+ "wall-ledger": "wall-ledger";
126
+ "independent-high-beam": "independent-high-beam";
127
+ }>>;
128
+ ledgerVerticalOffset: z.ZodDefault<z.ZodNumber>;
129
+ lowBeamInset: z.ZodDefault<z.ZodNumber>;
130
+ gutterEnabled: z.ZodDefault<z.ZodBoolean>;
131
+ gutterProfile: z.ZodDefault<z.ZodEnum<{
132
+ box: "box";
133
+ "k-style": "k-style";
134
+ "half-round": "half-round";
135
+ }>>;
136
+ gutterSize: z.ZodDefault<z.ZodNumber>;
137
+ downspoutEnabled: z.ZodDefault<z.ZodBoolean>;
138
+ downspoutPosition: z.ZodDefault<z.ZodNumber>;
139
+ connectionMode: z.ZodDefault<z.ZodEnum<{
140
+ manual: "manual";
141
+ auto: "auto";
142
+ }>>;
143
+ hostRoofId: z.ZodOptional<z.ZodDefault<z.ZodTemplateLiteral<`roof_${string}`>>>;
144
+ hostRoofSegmentId: z.ZodOptional<z.ZodString>;
145
+ hostRoofEdge: z.ZodOptional<z.ZodEnum<{
146
+ "+X": "+X";
147
+ "-X": "-X";
148
+ "+Z": "+Z";
149
+ "-Z": "-Z";
150
+ }>>;
151
+ hostRoofEdgeRange: z.ZodOptional<z.ZodTuple<[z.ZodNumber, z.ZodNumber], null>>;
152
+ connectionOffset: z.ZodDefault<z.ZodNumber>;
153
+ connectionInset: z.ZodDefault<z.ZodNumber>;
154
+ matchHostRoofMaterial: z.ZodDefault<z.ZodBoolean>;
155
+ matchHostRoofStructure: z.ZodDefault<z.ZodBoolean>;
156
+ roofThickness: z.ZodDefault<z.ZodNumber>;
157
+ shingleThickness: z.ZodDefault<z.ZodNumber>;
158
+ highOverhang: z.ZodDefault<z.ZodNumber>;
159
+ lowOverhang: z.ZodDefault<z.ZodNumber>;
160
+ leftOverhang: z.ZodDefault<z.ZodNumber>;
161
+ rightOverhang: z.ZodDefault<z.ZodNumber>;
162
+ coveringType: z.ZodDefault<z.ZodEnum<{
163
+ generic: "generic";
164
+ shingle: "shingle";
165
+ "metal-panel": "metal-panel";
166
+ }>>;
167
+ beamWidth: z.ZodDefault<z.ZodNumber>;
168
+ beamHeight: z.ZodDefault<z.ZodNumber>;
169
+ ledgerDepth: z.ZodDefault<z.ZodNumber>;
170
+ ledgerHeight: z.ZodDefault<z.ZodNumber>;
171
+ rafterWidth: z.ZodDefault<z.ZodNumber>;
172
+ rafterHeight: z.ZodDefault<z.ZodNumber>;
173
+ rafterSpacing: z.ZodDefault<z.ZodNumber>;
174
+ rafterEndInset: z.ZodDefault<z.ZodNumber>;
175
+ framingStrategy: z.ZodDefault<z.ZodEnum<{
176
+ hidden: "hidden";
177
+ rafters: "rafters";
178
+ purlins: "purlins";
179
+ "covering-specific": "covering-specific";
180
+ }>>;
181
+ purlinWidth: z.ZodDefault<z.ZodNumber>;
182
+ purlinHeight: z.ZodDefault<z.ZodNumber>;
183
+ purlinSpacing: z.ZodDefault<z.ZodNumber>;
184
+ postWidth: z.ZodDefault<z.ZodNumber>;
185
+ postDepth: z.ZodDefault<z.ZodNumber>;
186
+ postCount: z.ZodDefault<z.ZodNumber>;
187
+ postLayoutMode: z.ZodDefault<z.ZodEnum<{
188
+ count: "count";
189
+ "target-spacing": "target-spacing";
190
+ }>>;
191
+ postSpacing: z.ZodDefault<z.ZodNumber>;
192
+ postInset: z.ZodDefault<z.ZodNumber>;
193
+ omittedPostSlots: z.ZodDefault<z.ZodArray<z.ZodObject<{
194
+ side: z.ZodEnum<{
195
+ low: "low";
196
+ high: "high";
197
+ }>;
198
+ index: z.ZodNumber;
199
+ layoutCount: z.ZodNumber;
200
+ }, z.core.$strip>>>;
201
+ postBracing: z.ZodDefault<z.ZodEnum<{
202
+ none: "none";
203
+ knee: "knee";
204
+ }>>;
205
+ footingStyle: z.ZodDefault<z.ZodEnum<{
206
+ none: "none";
207
+ "base-plate": "base-plate";
208
+ "concrete-pad": "concrete-pad";
209
+ }>>;
210
+ }, z.core.$strip>;
211
+ export type LeanToExtensionNode = z.infer<typeof LeanToExtensionNode>;
212
+ //# sourceMappingURL=lean-to-extension.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lean-to-extension.d.ts","sourceRoot":"","sources":["../../../src/schema/nodes/lean-to-extension.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAMvB,eAAO,MAAM,oBAAoB;;;EAA6B,CAAA;AAC9D,eAAO,MAAM,gBAAgB;;;;EAAyC,CAAA;AACtE,eAAO,MAAM,cAAc;;;;;EAAgE,CAAA;AAC3F,eAAO,MAAM,cAAc;;;;;EAAmC,CAAA;AAC9D,eAAO,MAAM,gBAAgB;;;;EAI3B,CAAA;AACF,eAAO,MAAM,kBAAkB;;;;EAA8C,CAAA;AAC7E,eAAO,MAAM,qBAAqB;;;;;EAAgE,CAAA;AAClG,eAAO,MAAM,kBAAkB;;;EAAmD,CAAA;AAClF,eAAO,MAAM,oBAAoB;;;EAAsC,CAAA;AACvE,eAAO,MAAM,kBAAkB;;;;EAAiD,CAAA;AAChF,eAAO,MAAM,kBAAkB;;;;EAAgD,CAAA;AAQ/E,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAA;AACvE,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAA;AAC/D,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAA;AAE3D,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAgG/B,CAAA;AAED,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAA"}