@pascal-app/core 0.5.1 → 0.7.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 (134) hide show
  1. package/dist/events/bus.d.ts +74 -4
  2. package/dist/events/bus.d.ts.map +1 -1
  3. package/dist/events/bus.js +1 -1
  4. package/dist/hooks/scene-registry/scene-registry.d.ts +2 -0
  5. package/dist/hooks/scene-registry/scene-registry.d.ts.map +1 -1
  6. package/dist/hooks/scene-registry/scene-registry.js +2 -0
  7. package/dist/hooks/spatial-grid/spatial-grid-manager.d.ts.map +1 -1
  8. package/dist/hooks/spatial-grid/spatial-grid-manager.js +164 -6
  9. package/dist/hooks/spatial-grid/spatial-grid.d.ts +2 -0
  10. package/dist/hooks/spatial-grid/spatial-grid.d.ts.map +1 -1
  11. package/dist/hooks/spatial-grid/spatial-grid.js +43 -20
  12. package/dist/index.d.ts +9 -13
  13. package/dist/index.d.ts.map +1 -1
  14. package/dist/index.js +7 -11
  15. package/dist/lib/door-operation.d.ts +7 -0
  16. package/dist/lib/door-operation.d.ts.map +1 -0
  17. package/dist/lib/door-operation.js +25 -0
  18. package/dist/lib/polygon-geometry.d.ts +3 -0
  19. package/dist/lib/polygon-geometry.d.ts.map +1 -0
  20. package/dist/lib/polygon-geometry.js +90 -0
  21. package/dist/lib/slab-polygon.d.ts +3 -0
  22. package/dist/lib/slab-polygon.d.ts.map +1 -0
  23. package/dist/lib/slab-polygon.js +58 -0
  24. package/dist/lib/space-detection.d.ts +10 -17
  25. package/dist/lib/space-detection.d.ts.map +1 -1
  26. package/dist/lib/space-detection.js +666 -453
  27. package/dist/material-library.d.ts +20 -0
  28. package/dist/material-library.d.ts.map +1 -0
  29. package/dist/material-library.js +580 -0
  30. package/dist/schema/asset-url.d.ts +34 -0
  31. package/dist/schema/asset-url.d.ts.map +1 -0
  32. package/dist/schema/asset-url.js +79 -0
  33. package/dist/schema/asset-url.test.d.ts +2 -0
  34. package/dist/schema/asset-url.test.d.ts.map +1 -0
  35. package/dist/schema/asset-url.test.js +138 -0
  36. package/dist/schema/index.d.ts +14 -7
  37. package/dist/schema/index.d.ts.map +1 -1
  38. package/dist/schema/index.js +10 -7
  39. package/dist/schema/material.d.ts +112 -2
  40. package/dist/schema/material.d.ts.map +1 -1
  41. package/dist/schema/material.js +55 -1
  42. package/dist/schema/nodes/ceiling.d.ts +11 -1
  43. package/dist/schema/nodes/ceiling.d.ts.map +1 -1
  44. package/dist/schema/nodes/ceiling.js +6 -0
  45. package/dist/schema/nodes/column.d.ts +520 -0
  46. package/dist/schema/nodes/column.d.ts.map +1 -0
  47. package/dist/schema/nodes/column.js +385 -0
  48. package/dist/schema/nodes/door.d.ts +74 -1
  49. package/dist/schema/nodes/door.d.ts.map +1 -1
  50. package/dist/schema/nodes/door.js +39 -2
  51. package/dist/schema/nodes/fence.d.ts +34 -0
  52. package/dist/schema/nodes/fence.d.ts.map +1 -1
  53. package/dist/schema/nodes/fence.js +5 -0
  54. package/dist/schema/nodes/guide.d.ts +17 -0
  55. package/dist/schema/nodes/guide.d.ts.map +1 -1
  56. package/dist/schema/nodes/guide.js +11 -1
  57. package/dist/schema/nodes/item.d.ts +10 -2
  58. package/dist/schema/nodes/item.d.ts.map +1 -1
  59. package/dist/schema/nodes/item.js +18 -1
  60. package/dist/schema/nodes/level.d.ts +1 -1
  61. package/dist/schema/nodes/level.d.ts.map +1 -1
  62. package/dist/schema/nodes/level.js +6 -0
  63. package/dist/schema/nodes/roof-segment.d.ts +3 -1
  64. package/dist/schema/nodes/roof-segment.d.ts.map +1 -1
  65. package/dist/schema/nodes/roof-segment.js +1 -0
  66. package/dist/schema/nodes/roof.d.ts +108 -0
  67. package/dist/schema/nodes/roof.d.ts.map +1 -1
  68. package/dist/schema/nodes/roof.js +58 -2
  69. package/dist/schema/nodes/scan.d.ts.map +1 -1
  70. package/dist/schema/nodes/scan.js +2 -1
  71. package/dist/schema/nodes/site.d.ts +2 -1
  72. package/dist/schema/nodes/site.d.ts.map +1 -1
  73. package/dist/schema/nodes/slab.d.ts +11 -1
  74. package/dist/schema/nodes/slab.d.ts.map +1 -1
  75. package/dist/schema/nodes/slab.js +7 -0
  76. package/dist/schema/nodes/spawn.d.ts +24 -0
  77. package/dist/schema/nodes/spawn.d.ts.map +1 -0
  78. package/dist/schema/nodes/spawn.js +8 -0
  79. package/dist/schema/nodes/stair-segment.d.ts +3 -1
  80. package/dist/schema/nodes/stair-segment.d.ts.map +1 -1
  81. package/dist/schema/nodes/stair-segment.js +1 -0
  82. package/dist/schema/nodes/stair.d.ts +122 -2
  83. package/dist/schema/nodes/stair.d.ts.map +1 -1
  84. package/dist/schema/nodes/stair.js +72 -2
  85. package/dist/schema/nodes/surface-hole-metadata.d.ts +10 -0
  86. package/dist/schema/nodes/surface-hole-metadata.d.ts.map +1 -0
  87. package/dist/schema/nodes/surface-hole-metadata.js +5 -0
  88. package/dist/schema/nodes/wall.d.ts +87 -1
  89. package/dist/schema/nodes/wall.d.ts.map +1 -1
  90. package/dist/schema/nodes/wall.js +45 -4
  91. package/dist/schema/nodes/window.d.ts +57 -1
  92. package/dist/schema/nodes/window.d.ts.map +1 -1
  93. package/dist/schema/nodes/window.js +29 -0
  94. package/dist/schema/types.d.ts +653 -12
  95. package/dist/schema/types.d.ts.map +1 -1
  96. package/dist/schema/types.js +4 -0
  97. package/dist/store/actions/node-actions.d.ts +1 -1
  98. package/dist/store/actions/node-actions.d.ts.map +1 -1
  99. package/dist/store/actions/node-actions.js +181 -5
  100. package/dist/store/history-control.d.ts +14 -0
  101. package/dist/store/history-control.d.ts.map +1 -0
  102. package/dist/store/history-control.js +22 -0
  103. package/dist/store/use-interactive.d.ts +43 -0
  104. package/dist/store/use-interactive.d.ts.map +1 -1
  105. package/dist/store/use-interactive.js +66 -0
  106. package/dist/store/use-scene.d.ts.map +1 -1
  107. package/dist/store/use-scene.js +307 -3
  108. package/dist/systems/ceiling/ceiling-system.d.ts.map +1 -1
  109. package/dist/systems/ceiling/ceiling-system.js +7 -0
  110. package/dist/systems/fence/fence-system.d.ts.map +1 -1
  111. package/dist/systems/fence/fence-system.js +106 -39
  112. package/dist/systems/roof/roof-system.d.ts.map +1 -1
  113. package/dist/systems/roof/roof-system.js +31 -1
  114. package/dist/systems/slab/slab-system.d.ts.map +1 -1
  115. package/dist/systems/slab/slab-system.js +45 -8
  116. package/dist/systems/stair/stair-opening-sync.d.ts +6 -0
  117. package/dist/systems/stair/stair-opening-sync.d.ts.map +1 -0
  118. package/dist/systems/stair/stair-opening-sync.js +576 -0
  119. package/dist/systems/stair/stair-opening-sync.test.d.ts +2 -0
  120. package/dist/systems/stair/stair-opening-sync.test.d.ts.map +1 -0
  121. package/dist/systems/stair/stair-opening-sync.test.js +65 -0
  122. package/dist/systems/stair/stair-system.d.ts.map +1 -1
  123. package/dist/systems/stair/stair-system.js +119 -2
  124. package/dist/systems/wall/wall-curve.d.ts +43 -0
  125. package/dist/systems/wall/wall-curve.d.ts.map +1 -0
  126. package/dist/systems/wall/wall-curve.js +176 -0
  127. package/dist/systems/wall/wall-footprint.d.ts.map +1 -1
  128. package/dist/systems/wall/wall-footprint.js +16 -2
  129. package/dist/systems/wall/wall-mitering.d.ts +7 -0
  130. package/dist/systems/wall/wall-mitering.d.ts.map +1 -1
  131. package/dist/systems/wall/wall-mitering.js +76 -3
  132. package/dist/systems/wall/wall-system.d.ts.map +1 -1
  133. package/dist/systems/wall/wall-system.js +202 -2
  134. package/package.json +33 -5
@@ -0,0 +1,20 @@
1
+ import { type MaterialPresetPayload } from './schema/material';
2
+ export type MaterialCatalogItem = {
3
+ id: string;
4
+ label: string;
5
+ category: MaterialCategory;
6
+ description?: string;
7
+ previewThumbnailUrl?: string;
8
+ previewColor?: string;
9
+ preset: MaterialPresetPayload;
10
+ };
11
+ export declare const MATERIAL_CATEGORIES: readonly ["wood", "wallpaper", "parquet", "granite", "marble", "other"];
12
+ export type MaterialCategory = (typeof MATERIAL_CATEGORIES)[number];
13
+ export declare const MATERIAL_CATALOG: MaterialCatalogItem[];
14
+ export declare function getMaterialsForCategory(category: MaterialCategory): MaterialCatalogItem[];
15
+ export declare function getCatalogMaterialById(id?: string): MaterialCatalogItem | undefined;
16
+ export declare const LIBRARY_MATERIAL_REF_PREFIX = "library:";
17
+ export declare function toLibraryMaterialRef(id: string): string;
18
+ export declare function getLibraryMaterialIdFromRef(materialRef?: string | null): string | null;
19
+ export declare function getMaterialPresetByRef(materialRef?: string | null): MaterialPresetPayload | null;
20
+ //# sourceMappingURL=material-library.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"material-library.d.ts","sourceRoot":"","sources":["../src/material-library.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,qBAAqB,EAC3B,MAAM,mBAAmB,CAAA;AAE1B,MAAM,MAAM,mBAAmB,GAAG;IAChC,EAAE,EAAE,MAAM,CAAA;IACV,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,gBAAgB,CAAA;IAC1B,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,mBAAmB,CAAC,EAAE,MAAM,CAAA;IAC5B,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,MAAM,EAAE,qBAAqB,CAAA;CAC9B,CAAA;AAED,eAAO,MAAM,mBAAmB,yEAOtB,CAAA;AACV,MAAM,MAAM,gBAAgB,GAAG,CAAC,OAAO,mBAAmB,CAAC,CAAC,MAAM,CAAC,CAAA;AAEnE,eAAO,MAAM,gBAAgB,EAAE,mBAAmB,EAiiBjD,CAAA;AAED,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,gBAAgB,GAAG,mBAAmB,EAAE,CAEzF;AAED,wBAAgB,sBAAsB,CAAC,EAAE,CAAC,EAAE,MAAM,GAAG,mBAAmB,GAAG,SAAS,CAGnF;AAED,eAAO,MAAM,2BAA2B,aAAa,CAAA;AAErD,wBAAgB,oBAAoB,CAAC,EAAE,EAAE,MAAM,UAE9C;AAED,wBAAgB,2BAA2B,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,iBAItE;AAED,wBAAgB,sBAAsB,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,qBAAqB,GAAG,IAAI,CAIhG"}
@@ -0,0 +1,580 @@
1
+ import {} from './schema/material';
2
+ export const MATERIAL_CATEGORIES = [
3
+ 'wood',
4
+ 'wallpaper',
5
+ 'parquet',
6
+ 'granite',
7
+ 'marble',
8
+ 'other',
9
+ ];
10
+ export const MATERIAL_CATALOG = [
11
+ {
12
+ id: 'wall-wood1',
13
+ label: 'Wood',
14
+ category: 'wood',
15
+ description: 'Warm wood finish',
16
+ previewThumbnailUrl: '/material/wood1/wood1_thumbnail.webp',
17
+ preset: {
18
+ maps: {
19
+ albedoMap: '/material/wood1/albedoMap_basecolor.jpg',
20
+ normalMap: '/material/wood1/normalMap_normal.jpg',
21
+ },
22
+ mapProperties: {
23
+ color: '#ffffff',
24
+ roughness: 0.575,
25
+ metalness: 0,
26
+ repeatX: 1,
27
+ repeatY: 1,
28
+ rotation: 0,
29
+ wrapS: 'Repeat',
30
+ wrapT: 'Repeat',
31
+ normalScaleX: 1,
32
+ normalScaleY: 1,
33
+ emissiveIntensity: 1,
34
+ displacementScale: 0.02,
35
+ transparent: true,
36
+ flipY: true,
37
+ bumpScale: 1,
38
+ emissiveColor: '#000000',
39
+ aoMapIntensity: 1,
40
+ side: 0,
41
+ opacity: 1,
42
+ lightMapIntensity: 1,
43
+ },
44
+ },
45
+ },
46
+ {
47
+ id: 'wall-wood2',
48
+ label: 'Wood',
49
+ category: 'wood',
50
+ description: 'Textured wood finish',
51
+ previewThumbnailUrl: '/material/wood2/wood2_thumbnail.webp',
52
+ preset: {
53
+ maps: {
54
+ albedoMap: '/material/wood2/albedoMap_Wood.jpg',
55
+ normalMap: '/material/wood2/normalMap_Wood.jpg',
56
+ aoMap: '/material/wood2/aoMap_Wood.jpg',
57
+ },
58
+ mapProperties: {
59
+ color: '#ffffff',
60
+ roughness: 0.467,
61
+ metalness: 0,
62
+ repeatX: 1,
63
+ repeatY: 1,
64
+ rotation: 0,
65
+ wrapS: 'Repeat',
66
+ wrapT: 'Repeat',
67
+ normalScaleX: 2,
68
+ normalScaleY: 2,
69
+ emissiveIntensity: 1,
70
+ displacementScale: 0.02,
71
+ transparent: true,
72
+ flipY: true,
73
+ bumpScale: 1,
74
+ emissiveColor: '#000000',
75
+ aoMapIntensity: 2,
76
+ side: 0,
77
+ opacity: 1,
78
+ lightMapIntensity: 1,
79
+ },
80
+ },
81
+ },
82
+ {
83
+ id: 'wall-wood3',
84
+ label: 'Wood',
85
+ category: 'wood',
86
+ description: 'Knotted timber finish',
87
+ previewThumbnailUrl: '/material/wood3/wood3_thumbnail.webp',
88
+ preset: {
89
+ maps: {
90
+ albedoMap: '/material/wood3/albedoMap_knotted-timber.jpg',
91
+ },
92
+ mapProperties: {
93
+ color: '#ffffff',
94
+ roughness: 0.489,
95
+ metalness: 0,
96
+ repeatX: 1,
97
+ repeatY: 1,
98
+ rotation: 0,
99
+ wrapS: 'Repeat',
100
+ wrapT: 'Repeat',
101
+ normalScaleX: 0.2,
102
+ normalScaleY: 0.2,
103
+ emissiveIntensity: 1,
104
+ displacementScale: 0.02,
105
+ transparent: true,
106
+ flipY: true,
107
+ bumpScale: 1,
108
+ emissiveColor: '#000000',
109
+ aoMapIntensity: 2,
110
+ side: 0,
111
+ opacity: 1,
112
+ lightMapIntensity: 1,
113
+ },
114
+ },
115
+ },
116
+ {
117
+ id: 'wall-wood4',
118
+ label: 'Wood',
119
+ category: 'wood',
120
+ description: 'Oak stretcher finish',
121
+ previewThumbnailUrl: '/material/wood4/wood4_thumbnail.webp',
122
+ preset: {
123
+ maps: {
124
+ albedoMap: '/material/wood4/albedoMap_oak-stretcher.jpg',
125
+ },
126
+ mapProperties: {
127
+ color: '#ffffff',
128
+ roughness: 0.378,
129
+ metalness: 0,
130
+ repeatX: 1,
131
+ repeatY: 1,
132
+ rotation: 0,
133
+ wrapS: 'Repeat',
134
+ wrapT: 'Repeat',
135
+ normalScaleX: 1,
136
+ normalScaleY: 1,
137
+ emissiveIntensity: 1,
138
+ displacementScale: 0.02,
139
+ transparent: true,
140
+ flipY: true,
141
+ bumpScale: 1,
142
+ emissiveColor: '#000000',
143
+ aoMapIntensity: 1,
144
+ side: 0,
145
+ opacity: 1,
146
+ lightMapIntensity: 1,
147
+ },
148
+ },
149
+ },
150
+ {
151
+ id: 'wall-wood5',
152
+ label: 'Wood',
153
+ category: 'wood',
154
+ description: 'Rich grain wood finish',
155
+ previewThumbnailUrl: '/material/wood5/wood5_thumnail.webp',
156
+ preset: {
157
+ maps: {
158
+ albedoMap: '/material/wood5/albedoMap_3_base_color.webp',
159
+ normalMap: '/material/wood5/normalMap_3_normal.jpg',
160
+ aoMap: '/material/wood5/aoMap_3_ao.jpg',
161
+ },
162
+ mapProperties: {
163
+ color: '#ffffff',
164
+ roughness: 0.6,
165
+ metalness: 0,
166
+ repeatX: 1,
167
+ repeatY: 1,
168
+ rotation: 0,
169
+ wrapS: 'Repeat',
170
+ wrapT: 'Repeat',
171
+ normalScaleX: 1,
172
+ normalScaleY: 1,
173
+ emissiveIntensity: 1,
174
+ displacementScale: 0.02,
175
+ transparent: true,
176
+ flipY: true,
177
+ bumpScale: 1,
178
+ emissiveColor: '#000000',
179
+ aoMapIntensity: 10,
180
+ side: 0,
181
+ opacity: 1,
182
+ lightMapIntensity: 1,
183
+ },
184
+ },
185
+ },
186
+ {
187
+ id: 'wall-granite1',
188
+ label: 'Granite',
189
+ category: 'granite',
190
+ description: 'Polished granite finish',
191
+ previewThumbnailUrl: '/material/granite1/granite_thumbnail.webp',
192
+ preset: {
193
+ maps: {
194
+ albedoMap: '/material/granite1/albedoMap_Granite.jpg',
195
+ },
196
+ mapProperties: {
197
+ color: '#ffffff',
198
+ roughness: 0.189,
199
+ metalness: 0,
200
+ repeatX: 1,
201
+ repeatY: 1,
202
+ rotation: 0,
203
+ wrapS: 'Repeat',
204
+ wrapT: 'Repeat',
205
+ normalScaleX: 1,
206
+ normalScaleY: 1,
207
+ emissiveIntensity: 1,
208
+ displacementScale: 0.02,
209
+ transparent: true,
210
+ flipY: true,
211
+ bumpScale: 1,
212
+ emissiveColor: '#000000',
213
+ aoMapIntensity: 1,
214
+ side: 0,
215
+ opacity: 1,
216
+ lightMapIntensity: 1,
217
+ },
218
+ },
219
+ },
220
+ {
221
+ id: 'wall-marble1',
222
+ label: 'Marble',
223
+ category: 'marble',
224
+ description: 'Smooth marble finish',
225
+ previewThumbnailUrl: '/material/marble1/marble1_thumbnail.webp',
226
+ preset: {
227
+ maps: {
228
+ albedoMap: '/material/marble1/albedoMap_marble.jpg',
229
+ },
230
+ mapProperties: {
231
+ color: '#ffffff',
232
+ roughness: 0.133,
233
+ metalness: 0,
234
+ repeatX: 1,
235
+ repeatY: 1,
236
+ rotation: 0,
237
+ wrapS: 'Repeat',
238
+ wrapT: 'Repeat',
239
+ normalScaleX: 1,
240
+ normalScaleY: 1,
241
+ emissiveIntensity: 1,
242
+ displacementScale: 0.02,
243
+ transparent: true,
244
+ flipY: true,
245
+ bumpScale: 1,
246
+ emissiveColor: '#000000',
247
+ aoMapIntensity: 1,
248
+ side: 0,
249
+ opacity: 1,
250
+ lightMapIntensity: 1,
251
+ },
252
+ },
253
+ },
254
+ {
255
+ id: 'wall-marble2',
256
+ label: 'Marble',
257
+ category: 'marble',
258
+ description: 'Soft marble finish',
259
+ previewThumbnailUrl: '/material/marble2/marble2_thumbnail.webp',
260
+ preset: {
261
+ maps: {
262
+ albedoMap: '/material/marble2/albedoMap_marble.jpg',
263
+ },
264
+ mapProperties: {
265
+ color: '#ffffff',
266
+ roughness: 0.122,
267
+ metalness: 0,
268
+ repeatX: 1,
269
+ repeatY: 1,
270
+ rotation: 0,
271
+ wrapS: 'Repeat',
272
+ wrapT: 'Repeat',
273
+ normalScaleX: 1,
274
+ normalScaleY: 1,
275
+ emissiveIntensity: 1,
276
+ displacementScale: 0.02,
277
+ transparent: true,
278
+ flipY: true,
279
+ bumpScale: 1,
280
+ emissiveColor: '#000000',
281
+ aoMapIntensity: 1,
282
+ side: 0,
283
+ opacity: 1,
284
+ lightMapIntensity: 1,
285
+ },
286
+ },
287
+ },
288
+ {
289
+ id: 'wall-parquet1',
290
+ label: 'Parquet',
291
+ category: 'parquet',
292
+ description: 'Parquet wood finish',
293
+ previewThumbnailUrl: '/material/parquet1/parquet_thumnail.webp',
294
+ preset: {
295
+ maps: {
296
+ albedoMap: '/material/parquet1/albedoMap_parquet.jpg',
297
+ },
298
+ mapProperties: {
299
+ color: '#ffffff',
300
+ roughness: 0.644,
301
+ metalness: 0.4,
302
+ repeatX: 1,
303
+ repeatY: 1,
304
+ rotation: 0,
305
+ wrapS: 'Repeat',
306
+ wrapT: 'Repeat',
307
+ normalScaleX: 1,
308
+ normalScaleY: 1,
309
+ emissiveIntensity: 1,
310
+ displacementScale: 0.02,
311
+ transparent: true,
312
+ flipY: true,
313
+ bumpScale: 1,
314
+ emissiveColor: '#000000',
315
+ aoMapIntensity: 1,
316
+ side: 0,
317
+ opacity: 1,
318
+ lightMapIntensity: 1,
319
+ },
320
+ },
321
+ },
322
+ {
323
+ id: 'wall-parquet2',
324
+ label: 'Parquet',
325
+ category: 'parquet',
326
+ description: 'Soft parquet finish',
327
+ previewThumbnailUrl: '/material/parquet2/parquet2_thumbnail.webp',
328
+ preset: {
329
+ maps: {
330
+ albedoMap: '/material/parquet2/albedoMap_parquet.jpg',
331
+ },
332
+ mapProperties: {
333
+ color: '#ffffff',
334
+ roughness: 0.6,
335
+ metalness: 0,
336
+ repeatX: 1,
337
+ repeatY: 1,
338
+ rotation: 0,
339
+ wrapS: 'Repeat',
340
+ wrapT: 'Repeat',
341
+ normalScaleX: 1,
342
+ normalScaleY: 1,
343
+ emissiveIntensity: 1,
344
+ displacementScale: 0.02,
345
+ transparent: true,
346
+ flipY: true,
347
+ bumpScale: 1,
348
+ emissiveColor: '#000000',
349
+ aoMapIntensity: 1,
350
+ side: 0,
351
+ opacity: 1,
352
+ lightMapIntensity: 1,
353
+ },
354
+ },
355
+ },
356
+ {
357
+ id: 'wall-wallpaper1',
358
+ label: 'Wallpaper',
359
+ category: 'wallpaper',
360
+ description: 'Soft wallpaper finish',
361
+ previewThumbnailUrl: '/material/wallpaper1/wallpaper1_thumbnail.webp',
362
+ preset: {
363
+ maps: {
364
+ albedoMap: '/material/wallpaper1/albedoMap_1.webp',
365
+ normalMap: '/material/wallpaper1/normalMap_NormalMap.webp',
366
+ },
367
+ mapProperties: {
368
+ color: '#ffffff',
369
+ roughness: 0.911,
370
+ metalness: 0,
371
+ repeatX: 1,
372
+ repeatY: 1,
373
+ rotation: 0,
374
+ wrapS: 'Repeat',
375
+ wrapT: 'Repeat',
376
+ normalScaleX: 1,
377
+ normalScaleY: 1,
378
+ emissiveIntensity: 1,
379
+ displacementScale: 0.02,
380
+ transparent: true,
381
+ flipY: true,
382
+ bumpScale: 1,
383
+ emissiveColor: '#000000',
384
+ aoMapIntensity: 1,
385
+ side: 0,
386
+ opacity: 1,
387
+ lightMapIntensity: 1,
388
+ },
389
+ },
390
+ },
391
+ {
392
+ id: 'wall-wallpaper2',
393
+ label: 'Wallpaper',
394
+ category: 'wallpaper',
395
+ description: 'Decorative wallpaper finish',
396
+ previewThumbnailUrl: '/material/wallpaper2/wallpaper2_thumnail.webp',
397
+ preset: {
398
+ maps: {
399
+ albedoMap: '/material/wallpaper2/albedoMap_5.webp',
400
+ },
401
+ mapProperties: {
402
+ color: '#ffffff',
403
+ roughness: 0.889,
404
+ metalness: 0.255,
405
+ repeatX: 1,
406
+ repeatY: 1,
407
+ rotation: 0,
408
+ wrapS: 'Repeat',
409
+ wrapT: 'Repeat',
410
+ normalScaleX: 1,
411
+ normalScaleY: 1,
412
+ emissiveIntensity: 1,
413
+ displacementScale: 0.02,
414
+ transparent: true,
415
+ flipY: true,
416
+ bumpScale: 1,
417
+ emissiveColor: '#000000',
418
+ aoMapIntensity: 1,
419
+ side: 0,
420
+ opacity: 1,
421
+ lightMapIntensity: 1,
422
+ },
423
+ },
424
+ },
425
+ {
426
+ id: 'wall-wallpaper3',
427
+ label: 'Wallpaper',
428
+ category: 'wallpaper',
429
+ description: 'Patterned wallpaper finish',
430
+ previewThumbnailUrl: '/material/wallpaper3/wallpaper3_thumbnail.webp',
431
+ preset: {
432
+ maps: {
433
+ albedoMap: '/material/wallpaper3/albedoMap_wallpaper3.avif',
434
+ },
435
+ mapProperties: {
436
+ color: '#ffffff',
437
+ roughness: 0.887,
438
+ metalness: 0.35,
439
+ repeatX: 1,
440
+ repeatY: 1,
441
+ rotation: 0,
442
+ wrapS: 'Repeat',
443
+ wrapT: 'Repeat',
444
+ normalScaleX: 1,
445
+ normalScaleY: 1,
446
+ emissiveIntensity: 1,
447
+ displacementScale: 0.02,
448
+ transparent: true,
449
+ flipY: true,
450
+ bumpScale: 1,
451
+ emissiveColor: '#000000',
452
+ aoMapIntensity: 1,
453
+ side: 0,
454
+ opacity: 1,
455
+ lightMapIntensity: 1,
456
+ },
457
+ },
458
+ },
459
+ {
460
+ id: 'preset-white',
461
+ label: 'White',
462
+ category: 'other',
463
+ description: 'Clean painted finish',
464
+ previewColor: '#ffffff',
465
+ preset: {
466
+ maps: {},
467
+ mapProperties: {
468
+ color: '#ffffff',
469
+ roughness: 0.9,
470
+ metalness: 0,
471
+ repeatX: 1,
472
+ repeatY: 1,
473
+ rotation: 0,
474
+ wrapS: 'Repeat',
475
+ wrapT: 'Repeat',
476
+ normalScaleX: 1,
477
+ normalScaleY: 1,
478
+ emissiveIntensity: 1,
479
+ displacementScale: 0.02,
480
+ transparent: false,
481
+ flipY: true,
482
+ bumpScale: 1,
483
+ emissiveColor: '#000000',
484
+ aoMapIntensity: 1,
485
+ side: 0,
486
+ opacity: 1,
487
+ lightMapIntensity: 1,
488
+ },
489
+ },
490
+ },
491
+ {
492
+ id: 'preset-metal',
493
+ label: 'Metal',
494
+ category: 'other',
495
+ description: 'Brushed metal finish',
496
+ previewColor: '#c0c0c0',
497
+ preset: {
498
+ maps: {},
499
+ mapProperties: {
500
+ color: '#c7ccd2',
501
+ roughness: 0.26,
502
+ metalness: 0.82,
503
+ repeatX: 1,
504
+ repeatY: 1,
505
+ rotation: 0,
506
+ wrapS: 'Repeat',
507
+ wrapT: 'Repeat',
508
+ normalScaleX: 1,
509
+ normalScaleY: 1,
510
+ emissiveIntensity: 1,
511
+ displacementScale: 0.02,
512
+ transparent: false,
513
+ flipY: true,
514
+ bumpScale: 1,
515
+ emissiveColor: '#000000',
516
+ aoMapIntensity: 1,
517
+ side: 0,
518
+ opacity: 1,
519
+ lightMapIntensity: 1,
520
+ },
521
+ },
522
+ },
523
+ {
524
+ id: 'preset-glass',
525
+ label: 'Glass',
526
+ category: 'other',
527
+ description: 'Light glass finish',
528
+ previewColor: '#87ceeb',
529
+ preset: {
530
+ maps: {},
531
+ mapProperties: {
532
+ color: '#87ceeb',
533
+ roughness: 0.1,
534
+ metalness: 0.1,
535
+ repeatX: 1,
536
+ repeatY: 1,
537
+ rotation: 0,
538
+ wrapS: 'Repeat',
539
+ wrapT: 'Repeat',
540
+ normalScaleX: 1,
541
+ normalScaleY: 1,
542
+ emissiveIntensity: 1,
543
+ displacementScale: 0.02,
544
+ transparent: true,
545
+ flipY: true,
546
+ bumpScale: 1,
547
+ emissiveColor: '#000000',
548
+ aoMapIntensity: 1,
549
+ side: 2,
550
+ opacity: 0.3,
551
+ lightMapIntensity: 1,
552
+ },
553
+ },
554
+ },
555
+ ];
556
+ export function getMaterialsForCategory(category) {
557
+ return MATERIAL_CATALOG.filter((item) => item.category === category);
558
+ }
559
+ export function getCatalogMaterialById(id) {
560
+ if (!id)
561
+ return undefined;
562
+ return MATERIAL_CATALOG.find((item) => item.id === id);
563
+ }
564
+ export const LIBRARY_MATERIAL_REF_PREFIX = 'library:';
565
+ export function toLibraryMaterialRef(id) {
566
+ return `${LIBRARY_MATERIAL_REF_PREFIX}${id}`;
567
+ }
568
+ export function getLibraryMaterialIdFromRef(materialRef) {
569
+ if (!materialRef)
570
+ return null;
571
+ if (!materialRef.startsWith(LIBRARY_MATERIAL_REF_PREFIX))
572
+ return null;
573
+ return materialRef.slice(LIBRARY_MATERIAL_REF_PREFIX.length);
574
+ }
575
+ export function getMaterialPresetByRef(materialRef) {
576
+ const materialId = getLibraryMaterialIdFromRef(materialRef);
577
+ if (!materialId)
578
+ return null;
579
+ return getCatalogMaterialById(materialId)?.preset ?? null;
580
+ }
@@ -0,0 +1,34 @@
1
+ import { z } from 'zod';
2
+ /**
3
+ * Scheme allowlist for asset-like URLs embedded in scene graphs.
4
+ *
5
+ * Phase 3 security audit: `scan.url`, `guide.url`, `material.texture.url`, and
6
+ * `item.asset.src` were previously bare `z.string()`. That meant an
7
+ * attacker-crafted scene loaded in the editor could beacon to arbitrary URLs
8
+ * (e.g. `javascript:`, `file:///etc/passwd`, `http://169.254.169.254/...`).
9
+ *
10
+ * This validator rejects URLs that don't match the scheme allowlist below.
11
+ */
12
+ declare const ALLOWED_SCHEMES: readonly ["asset:", "blob:", "https:", "data:image/"];
13
+ /**
14
+ * Optional environment variable that narrows which `https:` origins are
15
+ * accepted. Set to a comma-separated list (e.g. `https://cdn.pascal.app`).
16
+ * When unset, any `https:` origin is permitted.
17
+ */
18
+ export declare const ALLOWED_ORIGINS_ENV = "PASCAL_ALLOWED_ASSET_ORIGINS";
19
+ /**
20
+ * Zod validator for asset-style URL fields. Accepts:
21
+ * - `asset://…` internal handles
22
+ * - `blob:…` in-memory references
23
+ * - `data:image/…` inline images (not `data:text/html` or other types)
24
+ * - `/…` app-relative paths
25
+ * - `https://…` public URLs (optionally narrowed to an env allowlist)
26
+ * - `http://localhost[:port]/…` or `http://127.0.0.1/…` for local dev
27
+ *
28
+ * Rejects every other scheme, including `javascript:`, `file:`, `ftp:`,
29
+ * and `data:text/html`, as well as empty strings and non-URL garbage.
30
+ */
31
+ export declare const AssetUrl: z.ZodString;
32
+ export type AssetUrl = z.infer<typeof AssetUrl>;
33
+ export { ALLOWED_SCHEMES };
34
+ //# sourceMappingURL=asset-url.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"asset-url.d.ts","sourceRoot":"","sources":["../../src/schema/asset-url.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB;;;;;;;;;GASG;AACH,QAAA,MAAM,eAAe,uDAAwD,CAAA;AAE7E;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,iCAAiC,CAAA;AAuCjE;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,QAAQ,aAGnB,CAAA;AAEF,MAAM,MAAM,QAAQ,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,QAAQ,CAAC,CAAA;AAG/C,OAAO,EAAE,eAAe,EAAE,CAAA"}