@mcp-b/aec-components 0.2.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/LICENSE +21 -0
- package/README.md +20 -0
- package/dist/components/ifc-viewer/ifc-viewer.d.ts +73 -0
- package/dist/components/ifc-viewer/ifc-viewer.events.d.ts +36 -0
- package/dist/components/ifc-viewer/ifc-viewer.events.js +47 -0
- package/dist/components/ifc-viewer/ifc-viewer.js +3 -0
- package/dist/docs/custom-elements.json +372 -0
- package/dist/ifc-viewer-Co1EAZcX.js +167 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +3 -0
- package/package.json +81 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 MCP-B contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# @mcp-b/aec-components
|
|
2
|
+
|
|
3
|
+
Lit web components for AEC/BIM viewing. Currently `<sigvelo-ifc-viewer>`, an IFC
|
|
4
|
+
model viewer built on `@thatopen/components` and three.js.
|
|
5
|
+
|
|
6
|
+
`three`, `web-ifc`, `@thatopen/components`, and `@thatopen/fragments` are peer
|
|
7
|
+
dependencies — install them alongside this package.
|
|
8
|
+
|
|
9
|
+
## Storybook fixture
|
|
10
|
+
|
|
11
|
+
The stories render a 4.5KB IFC4 conformance model from `fixtures/column.ifc`. The shared
|
|
12
|
+
Storybook in `packages/web-components` mounts that directory at the site root,
|
|
13
|
+
so a story loads it as `/column.ifc`.
|
|
14
|
+
|
|
15
|
+
The fixture comes from buildingSMART's Sample-Test-Files repository and is
|
|
16
|
+
licensed under CC BY 4.0; attribution and the immutable upstream source are in
|
|
17
|
+
`fixtures/README.md`. Larger IFC files remain gitignored.
|
|
18
|
+
|
|
19
|
+
To use a different model, put it in `fixtures/` and update the `src` attribute
|
|
20
|
+
in `src/components/ifc-viewer/ifc-viewer.stories.ts`.
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { CSSResultGroup, PropertyValues } from "lit";
|
|
2
|
+
import { SigveloElement } from "@mcp-b/wc-support/base/sigvelo-element";
|
|
3
|
+
|
|
4
|
+
//#region src/components/ifc-viewer/ifc-viewer.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* An IFC 3D model viewer powered by ThatOpen engine. Loads and displays
|
|
7
|
+
* Industry Foundation Classes (IFC) building models in an interactive
|
|
8
|
+
* 3D viewport with orbit camera controls.
|
|
9
|
+
*
|
|
10
|
+
* @tag sigvelo-ifc-viewer
|
|
11
|
+
* @summary IFC building model viewer with 3D navigation.
|
|
12
|
+
* @status experimental
|
|
13
|
+
* @since 0.0.0
|
|
14
|
+
*
|
|
15
|
+
* @event sigvelo-ifc-load - Fired when an IFC model finishes loading.
|
|
16
|
+
* @event sigvelo-ifc-error - Fired when IFC loading fails.
|
|
17
|
+
* @event sigvelo-ifc-progress - Fired during IFC loading with progress updates.
|
|
18
|
+
*
|
|
19
|
+
* @csspart container - The 3D viewport container element.
|
|
20
|
+
*
|
|
21
|
+
* @example Default viewer
|
|
22
|
+
* ```html
|
|
23
|
+
* <sigvelo-ifc-viewer
|
|
24
|
+
* src="/model.ifc"
|
|
25
|
+
* style="height: 500px;"
|
|
26
|
+
* ></sigvelo-ifc-viewer>
|
|
27
|
+
* ```
|
|
28
|
+
*
|
|
29
|
+
* @example Without grid
|
|
30
|
+
* ```html
|
|
31
|
+
* <sigvelo-ifc-viewer
|
|
32
|
+
* src="/model.ifc"
|
|
33
|
+
* .grid=${false}
|
|
34
|
+
* style="height: 500px;"
|
|
35
|
+
* ></sigvelo-ifc-viewer>
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
declare class SigveloIfcViewer extends SigveloElement {
|
|
39
|
+
static styles: CSSResultGroup;
|
|
40
|
+
/** URL of the IFC file to load. */
|
|
41
|
+
src: string;
|
|
42
|
+
/** Background color of the 3D scene. */
|
|
43
|
+
backgroundColor: string;
|
|
44
|
+
/** Whether orbit camera controls are enabled. */
|
|
45
|
+
cameraControls: boolean;
|
|
46
|
+
/** Whether to display a ground grid. */
|
|
47
|
+
grid: boolean;
|
|
48
|
+
/** Path to the directory containing web-ifc WASM files. Consumers must host the WASM files from the web-ifc package. */
|
|
49
|
+
wasmPath: string;
|
|
50
|
+
/** URL to the @thatopen/fragments worker script. Consumers must host the worker from @thatopen/fragments/dist/Worker/worker.mjs. */
|
|
51
|
+
workerUrl: string;
|
|
52
|
+
private _components;
|
|
53
|
+
private _world;
|
|
54
|
+
private _resizeObserver;
|
|
55
|
+
firstUpdated(): Promise<void>;
|
|
56
|
+
updated(changed: PropertyValues<this>): Promise<void>;
|
|
57
|
+
disconnectedCallback(): void;
|
|
58
|
+
/** Load an IFC model from a URL. */
|
|
59
|
+
loadUrl(url: string): Promise<void>;
|
|
60
|
+
/** Load an IFC model from a File object. */
|
|
61
|
+
loadFile(file: File): Promise<void>;
|
|
62
|
+
private _initViewer;
|
|
63
|
+
private _loadSrc;
|
|
64
|
+
private _updateBackgroundColor;
|
|
65
|
+
render(): import("lit-html").TemplateResult<1>;
|
|
66
|
+
}
|
|
67
|
+
declare global {
|
|
68
|
+
interface HTMLElementTagNameMap {
|
|
69
|
+
"sigvelo-ifc-viewer": SigveloIfcViewer;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
//#endregion
|
|
73
|
+
export { SigveloIfcViewer };
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
//#region src/components/ifc-viewer/ifc-viewer.events.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Fired when an IFC model finishes loading.
|
|
4
|
+
*
|
|
5
|
+
* @event sigvelo-ifc-load
|
|
6
|
+
*/
|
|
7
|
+
declare class SigveloIfcLoadEvent extends Event {
|
|
8
|
+
constructor();
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Fired when IFC loading fails.
|
|
12
|
+
*
|
|
13
|
+
* @event sigvelo-ifc-error
|
|
14
|
+
*/
|
|
15
|
+
declare class SigveloIfcErrorEvent extends Event {
|
|
16
|
+
readonly error: Error;
|
|
17
|
+
constructor(error: Error);
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Fired during IFC loading with progress updates.
|
|
21
|
+
*
|
|
22
|
+
* @event sigvelo-ifc-progress
|
|
23
|
+
*/
|
|
24
|
+
declare class SigveloIfcProgressEvent extends Event {
|
|
25
|
+
readonly progress: number;
|
|
26
|
+
constructor(progress: number);
|
|
27
|
+
}
|
|
28
|
+
declare global {
|
|
29
|
+
interface GlobalEventHandlersEventMap {
|
|
30
|
+
"sigvelo-ifc-load": SigveloIfcLoadEvent;
|
|
31
|
+
"sigvelo-ifc-error": SigveloIfcErrorEvent;
|
|
32
|
+
"sigvelo-ifc-progress": SigveloIfcProgressEvent;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
//#endregion
|
|
36
|
+
export { SigveloIfcErrorEvent, SigveloIfcLoadEvent, SigveloIfcProgressEvent };
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
//#region src/components/ifc-viewer/ifc-viewer.events.ts
|
|
2
|
+
/**
|
|
3
|
+
* Fired when an IFC model finishes loading.
|
|
4
|
+
*
|
|
5
|
+
* @event sigvelo-ifc-load
|
|
6
|
+
*/
|
|
7
|
+
var SigveloIfcLoadEvent = class extends Event {
|
|
8
|
+
constructor() {
|
|
9
|
+
super("sigvelo-ifc-load", {
|
|
10
|
+
bubbles: true,
|
|
11
|
+
cancelable: false,
|
|
12
|
+
composed: true
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* Fired when IFC loading fails.
|
|
18
|
+
*
|
|
19
|
+
* @event sigvelo-ifc-error
|
|
20
|
+
*/
|
|
21
|
+
var SigveloIfcErrorEvent = class extends Event {
|
|
22
|
+
constructor(error) {
|
|
23
|
+
super("sigvelo-ifc-error", {
|
|
24
|
+
bubbles: true,
|
|
25
|
+
cancelable: false,
|
|
26
|
+
composed: true
|
|
27
|
+
});
|
|
28
|
+
this.error = error;
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* Fired during IFC loading with progress updates.
|
|
33
|
+
*
|
|
34
|
+
* @event sigvelo-ifc-progress
|
|
35
|
+
*/
|
|
36
|
+
var SigveloIfcProgressEvent = class extends Event {
|
|
37
|
+
constructor(progress) {
|
|
38
|
+
super("sigvelo-ifc-progress", {
|
|
39
|
+
bubbles: true,
|
|
40
|
+
cancelable: false,
|
|
41
|
+
composed: true
|
|
42
|
+
});
|
|
43
|
+
this.progress = progress;
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
//#endregion
|
|
47
|
+
export { SigveloIfcErrorEvent, SigveloIfcLoadEvent, SigveloIfcProgressEvent };
|
|
@@ -0,0 +1,372 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": "1.0.0",
|
|
3
|
+
"readme": "",
|
|
4
|
+
"modules": [
|
|
5
|
+
{
|
|
6
|
+
"kind": "javascript-module",
|
|
7
|
+
"path": "src/components/ifc-viewer/ifc-viewer.events.ts",
|
|
8
|
+
"declarations": [
|
|
9
|
+
{
|
|
10
|
+
"kind": "class",
|
|
11
|
+
"description": "Fired when IFC loading fails.",
|
|
12
|
+
"name": "SigveloIfcErrorEvent",
|
|
13
|
+
"members": [
|
|
14
|
+
{
|
|
15
|
+
"kind": "field",
|
|
16
|
+
"name": "error",
|
|
17
|
+
"type": {
|
|
18
|
+
"text": "Error"
|
|
19
|
+
},
|
|
20
|
+
"readonly": true,
|
|
21
|
+
"default": "error"
|
|
22
|
+
}
|
|
23
|
+
],
|
|
24
|
+
"events": [],
|
|
25
|
+
"superclass": {
|
|
26
|
+
"name": "Event",
|
|
27
|
+
"module": "src/components/ifc-viewer/ifc-viewer.events.ts"
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
"kind": "class",
|
|
32
|
+
"description": "Fired when an IFC model finishes loading.",
|
|
33
|
+
"name": "SigveloIfcLoadEvent",
|
|
34
|
+
"events": [],
|
|
35
|
+
"superclass": {
|
|
36
|
+
"name": "Event",
|
|
37
|
+
"module": "src/components/ifc-viewer/ifc-viewer.events.ts"
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
"kind": "class",
|
|
42
|
+
"description": "Fired during IFC loading with progress updates.",
|
|
43
|
+
"name": "SigveloIfcProgressEvent",
|
|
44
|
+
"members": [
|
|
45
|
+
{
|
|
46
|
+
"kind": "field",
|
|
47
|
+
"name": "progress",
|
|
48
|
+
"type": {
|
|
49
|
+
"text": "number"
|
|
50
|
+
},
|
|
51
|
+
"readonly": true,
|
|
52
|
+
"default": "progress"
|
|
53
|
+
}
|
|
54
|
+
],
|
|
55
|
+
"events": [],
|
|
56
|
+
"superclass": {
|
|
57
|
+
"name": "Event",
|
|
58
|
+
"module": "src/components/ifc-viewer/ifc-viewer.events.ts"
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
],
|
|
62
|
+
"exports": [
|
|
63
|
+
{
|
|
64
|
+
"kind": "js",
|
|
65
|
+
"name": "SigveloIfcErrorEvent",
|
|
66
|
+
"declaration": {
|
|
67
|
+
"name": "SigveloIfcErrorEvent",
|
|
68
|
+
"module": "src/components/ifc-viewer/ifc-viewer.events.ts"
|
|
69
|
+
}
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
"kind": "js",
|
|
73
|
+
"name": "SigveloIfcLoadEvent",
|
|
74
|
+
"declaration": {
|
|
75
|
+
"name": "SigveloIfcLoadEvent",
|
|
76
|
+
"module": "src/components/ifc-viewer/ifc-viewer.events.ts"
|
|
77
|
+
}
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
"kind": "js",
|
|
81
|
+
"name": "SigveloIfcProgressEvent",
|
|
82
|
+
"declaration": {
|
|
83
|
+
"name": "SigveloIfcProgressEvent",
|
|
84
|
+
"module": "src/components/ifc-viewer/ifc-viewer.events.ts"
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
]
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
"kind": "javascript-module",
|
|
91
|
+
"path": "src/components/ifc-viewer/ifc-viewer.ts",
|
|
92
|
+
"declarations": [
|
|
93
|
+
{
|
|
94
|
+
"kind": "class",
|
|
95
|
+
"description": "An IFC 3D model viewer powered by ThatOpen engine. Loads and displays\nIndustry Foundation Classes (IFC) building models in an interactive\n3D viewport with orbit camera controls.",
|
|
96
|
+
"name": "SigveloIfcViewer",
|
|
97
|
+
"cssParts": [
|
|
98
|
+
{
|
|
99
|
+
"description": "The 3D viewport container element.",
|
|
100
|
+
"name": "container"
|
|
101
|
+
}
|
|
102
|
+
],
|
|
103
|
+
"members": [
|
|
104
|
+
{
|
|
105
|
+
"kind": "field",
|
|
106
|
+
"name": "_components",
|
|
107
|
+
"type": {
|
|
108
|
+
"text": "OBC.Components | null"
|
|
109
|
+
},
|
|
110
|
+
"privacy": "private",
|
|
111
|
+
"default": "null"
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
"kind": "method",
|
|
115
|
+
"name": "_initViewer",
|
|
116
|
+
"privacy": "private"
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
"kind": "method",
|
|
120
|
+
"name": "_loadSrc",
|
|
121
|
+
"privacy": "private"
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
"kind": "field",
|
|
125
|
+
"name": "_resizeObserver",
|
|
126
|
+
"type": {
|
|
127
|
+
"text": "ResizeObserver | null"
|
|
128
|
+
},
|
|
129
|
+
"privacy": "private",
|
|
130
|
+
"default": "null"
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
"kind": "method",
|
|
134
|
+
"name": "_updateBackgroundColor",
|
|
135
|
+
"privacy": "private"
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
"kind": "field",
|
|
139
|
+
"name": "_world",
|
|
140
|
+
"type": {
|
|
141
|
+
"text": "OBC.SimpleWorld<OBC.SimpleScene, OBC.SimpleCamera, OBC.SimpleRenderer> | null"
|
|
142
|
+
},
|
|
143
|
+
"privacy": "private",
|
|
144
|
+
"default": "null"
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
"kind": "field",
|
|
148
|
+
"name": "backgroundColor",
|
|
149
|
+
"type": {
|
|
150
|
+
"text": "string"
|
|
151
|
+
},
|
|
152
|
+
"default": "\"#202932\"",
|
|
153
|
+
"description": "Background color of the 3D scene.",
|
|
154
|
+
"attribute": "background-color"
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
"kind": "field",
|
|
158
|
+
"name": "cameraControls",
|
|
159
|
+
"type": {
|
|
160
|
+
"text": "boolean"
|
|
161
|
+
},
|
|
162
|
+
"default": "true",
|
|
163
|
+
"description": "Whether orbit camera controls are enabled.",
|
|
164
|
+
"attribute": "camera-controls"
|
|
165
|
+
},
|
|
166
|
+
{
|
|
167
|
+
"kind": "field",
|
|
168
|
+
"name": "grid",
|
|
169
|
+
"type": {
|
|
170
|
+
"text": "boolean"
|
|
171
|
+
},
|
|
172
|
+
"default": "true",
|
|
173
|
+
"description": "Whether to display a ground grid.",
|
|
174
|
+
"attribute": "grid"
|
|
175
|
+
},
|
|
176
|
+
{
|
|
177
|
+
"kind": "method",
|
|
178
|
+
"name": "loadFile",
|
|
179
|
+
"privacy": "public",
|
|
180
|
+
"return": {
|
|
181
|
+
"type": {
|
|
182
|
+
"text": "Promise<void>"
|
|
183
|
+
}
|
|
184
|
+
},
|
|
185
|
+
"parameters": [
|
|
186
|
+
{
|
|
187
|
+
"name": "file",
|
|
188
|
+
"type": {
|
|
189
|
+
"text": "File"
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
],
|
|
193
|
+
"description": "Load an IFC model from a File object."
|
|
194
|
+
},
|
|
195
|
+
{
|
|
196
|
+
"kind": "method",
|
|
197
|
+
"name": "loadUrl",
|
|
198
|
+
"privacy": "public",
|
|
199
|
+
"return": {
|
|
200
|
+
"type": {
|
|
201
|
+
"text": "Promise<void>"
|
|
202
|
+
}
|
|
203
|
+
},
|
|
204
|
+
"parameters": [
|
|
205
|
+
{
|
|
206
|
+
"name": "url",
|
|
207
|
+
"type": {
|
|
208
|
+
"text": "string"
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
],
|
|
212
|
+
"description": "Load an IFC model from a URL."
|
|
213
|
+
},
|
|
214
|
+
{
|
|
215
|
+
"kind": "field",
|
|
216
|
+
"name": "src",
|
|
217
|
+
"type": {
|
|
218
|
+
"text": "string"
|
|
219
|
+
},
|
|
220
|
+
"default": "\"\"",
|
|
221
|
+
"description": "URL of the IFC file to load.",
|
|
222
|
+
"attribute": "src"
|
|
223
|
+
},
|
|
224
|
+
{
|
|
225
|
+
"kind": "field",
|
|
226
|
+
"name": "wasmPath",
|
|
227
|
+
"default": "\"/\"",
|
|
228
|
+
"description": "Path to the directory containing web-ifc WASM files. Consumers must host the WASM files from the web-ifc package.",
|
|
229
|
+
"attribute": "wasm-path",
|
|
230
|
+
"type": {
|
|
231
|
+
"text": "string"
|
|
232
|
+
}
|
|
233
|
+
},
|
|
234
|
+
{
|
|
235
|
+
"kind": "field",
|
|
236
|
+
"name": "workerUrl",
|
|
237
|
+
"type": {
|
|
238
|
+
"text": "string"
|
|
239
|
+
},
|
|
240
|
+
"default": "\"/worker.mjs\"",
|
|
241
|
+
"description": "URL to the",
|
|
242
|
+
"attribute": "worker-url"
|
|
243
|
+
}
|
|
244
|
+
],
|
|
245
|
+
"events": [
|
|
246
|
+
{
|
|
247
|
+
"description": "Fired when IFC loading fails.",
|
|
248
|
+
"name": "sigvelo-ifc-error"
|
|
249
|
+
},
|
|
250
|
+
{
|
|
251
|
+
"description": "Fired when an IFC model finishes loading.",
|
|
252
|
+
"name": "sigvelo-ifc-load"
|
|
253
|
+
},
|
|
254
|
+
{
|
|
255
|
+
"description": "Fired during IFC loading with progress updates.",
|
|
256
|
+
"name": "sigvelo-ifc-progress"
|
|
257
|
+
}
|
|
258
|
+
],
|
|
259
|
+
"attributes": [
|
|
260
|
+
{
|
|
261
|
+
"name": "background-color",
|
|
262
|
+
"type": {
|
|
263
|
+
"text": "string"
|
|
264
|
+
},
|
|
265
|
+
"default": "\"#202932\"",
|
|
266
|
+
"description": "Background color of the 3D scene.",
|
|
267
|
+
"fieldName": "backgroundColor"
|
|
268
|
+
},
|
|
269
|
+
{
|
|
270
|
+
"name": "camera-controls",
|
|
271
|
+
"type": {
|
|
272
|
+
"text": "boolean"
|
|
273
|
+
},
|
|
274
|
+
"default": "true",
|
|
275
|
+
"description": "Whether orbit camera controls are enabled.",
|
|
276
|
+
"fieldName": "cameraControls"
|
|
277
|
+
},
|
|
278
|
+
{
|
|
279
|
+
"name": "grid",
|
|
280
|
+
"type": {
|
|
281
|
+
"text": "boolean"
|
|
282
|
+
},
|
|
283
|
+
"default": "true",
|
|
284
|
+
"description": "Whether to display a ground grid.",
|
|
285
|
+
"fieldName": "grid"
|
|
286
|
+
},
|
|
287
|
+
{
|
|
288
|
+
"name": "src",
|
|
289
|
+
"type": {
|
|
290
|
+
"text": "string"
|
|
291
|
+
},
|
|
292
|
+
"default": "\"\"",
|
|
293
|
+
"description": "URL of the IFC file to load.",
|
|
294
|
+
"fieldName": "src"
|
|
295
|
+
},
|
|
296
|
+
{
|
|
297
|
+
"name": "wasm-path",
|
|
298
|
+
"default": "DEFAULT_WASM_PATH",
|
|
299
|
+
"description": "Path to the directory containing web-ifc WASM files. Consumers must host the WASM files from the web-ifc package.",
|
|
300
|
+
"fieldName": "wasmPath"
|
|
301
|
+
},
|
|
302
|
+
{
|
|
303
|
+
"name": "worker-url",
|
|
304
|
+
"type": {
|
|
305
|
+
"text": "string"
|
|
306
|
+
},
|
|
307
|
+
"default": "\"/worker.mjs\"",
|
|
308
|
+
"description": "URL to the",
|
|
309
|
+
"fieldName": "workerUrl"
|
|
310
|
+
}
|
|
311
|
+
],
|
|
312
|
+
"superclass": {
|
|
313
|
+
"name": "SigveloElement",
|
|
314
|
+
"package": "@mcp-b/wc-support/base/sigvelo-element"
|
|
315
|
+
},
|
|
316
|
+
"tagName": "sigvelo-ifc-viewer",
|
|
317
|
+
"customElement": true,
|
|
318
|
+
"summary": "IFC building model viewer with 3D navigation.",
|
|
319
|
+
"modulePath": "src/components/ifc-viewer/ifc-viewer.ts",
|
|
320
|
+
"definitionPath": "src/components/ifc-viewer/ifc-viewer.ts"
|
|
321
|
+
}
|
|
322
|
+
],
|
|
323
|
+
"exports": [
|
|
324
|
+
{
|
|
325
|
+
"kind": "custom-element-definition",
|
|
326
|
+
"name": "sigvelo-ifc-viewer",
|
|
327
|
+
"declaration": {
|
|
328
|
+
"name": "SigveloIfcViewer",
|
|
329
|
+
"module": "src/components/ifc-viewer/ifc-viewer.ts"
|
|
330
|
+
}
|
|
331
|
+
},
|
|
332
|
+
{
|
|
333
|
+
"kind": "js",
|
|
334
|
+
"name": "SigveloIfcViewer",
|
|
335
|
+
"declaration": {
|
|
336
|
+
"name": "SigveloIfcViewer",
|
|
337
|
+
"module": "src/components/ifc-viewer/ifc-viewer.ts"
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
]
|
|
341
|
+
},
|
|
342
|
+
{
|
|
343
|
+
"kind": "javascript-module",
|
|
344
|
+
"path": "src/index.ts",
|
|
345
|
+
"declarations": [],
|
|
346
|
+
"exports": [
|
|
347
|
+
{
|
|
348
|
+
"kind": "js",
|
|
349
|
+
"name": "*",
|
|
350
|
+
"declaration": {
|
|
351
|
+
"name": "*",
|
|
352
|
+
"module": "src/components/ifc-viewer/ifc-viewer.js"
|
|
353
|
+
}
|
|
354
|
+
},
|
|
355
|
+
{
|
|
356
|
+
"kind": "js",
|
|
357
|
+
"name": "*",
|
|
358
|
+
"declaration": {
|
|
359
|
+
"name": "*",
|
|
360
|
+
"module": "src/components/ifc-viewer/ifc-viewer.events.js"
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
]
|
|
364
|
+
}
|
|
365
|
+
],
|
|
366
|
+
"package": {
|
|
367
|
+
"name": "@mcp-b/aec-components",
|
|
368
|
+
"description": "AEC (Architecture, Engineering, Construction) web components for Sigvelo, built with Lit.",
|
|
369
|
+
"version": "0.2.0",
|
|
370
|
+
"license": "MIT"
|
|
371
|
+
}
|
|
372
|
+
}
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
import { SigveloIfcErrorEvent, SigveloIfcLoadEvent } from "./components/ifc-viewer/ifc-viewer.events.js";
|
|
2
|
+
import { css, html } from "lit";
|
|
3
|
+
import { customElement, property } from "lit/decorators.js";
|
|
4
|
+
import { SigveloElement } from "@mcp-b/wc-support/base/sigvelo-element";
|
|
5
|
+
import hostStyles from "@mcp-b/wc-support/styles/host.styles";
|
|
6
|
+
import * as OBC from "@thatopen/components";
|
|
7
|
+
import * as THREE from "three";
|
|
8
|
+
//#region src/components/ifc-viewer/ifc-viewer.styles.ts
|
|
9
|
+
var ifc_viewer_styles_default = css`
|
|
10
|
+
:host {
|
|
11
|
+
display: block;
|
|
12
|
+
position: relative;
|
|
13
|
+
min-height: 400px;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
.viewer-container {
|
|
17
|
+
width: 100%;
|
|
18
|
+
height: 100%;
|
|
19
|
+
position: absolute;
|
|
20
|
+
inset: 0;
|
|
21
|
+
overflow: hidden;
|
|
22
|
+
}
|
|
23
|
+
`;
|
|
24
|
+
//#endregion
|
|
25
|
+
//#region \0@oxc-project+runtime@0.138.0/helpers/esm/decorate.js
|
|
26
|
+
function __decorate(decorators, target, key, desc) {
|
|
27
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
28
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
29
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
30
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
31
|
+
}
|
|
32
|
+
//#endregion
|
|
33
|
+
//#region src/components/ifc-viewer/ifc-viewer.ts
|
|
34
|
+
const DEFAULT_WASM_PATH = "/";
|
|
35
|
+
let SigveloIfcViewer = class SigveloIfcViewer extends SigveloElement {
|
|
36
|
+
constructor(..._args) {
|
|
37
|
+
super(..._args);
|
|
38
|
+
this.src = "";
|
|
39
|
+
this.backgroundColor = "#202932";
|
|
40
|
+
this.cameraControls = true;
|
|
41
|
+
this.grid = true;
|
|
42
|
+
this.wasmPath = DEFAULT_WASM_PATH;
|
|
43
|
+
this.workerUrl = "/worker.mjs";
|
|
44
|
+
this._components = null;
|
|
45
|
+
this._world = null;
|
|
46
|
+
this._resizeObserver = null;
|
|
47
|
+
}
|
|
48
|
+
static {
|
|
49
|
+
this.styles = [hostStyles, ifc_viewer_styles_default];
|
|
50
|
+
}
|
|
51
|
+
async firstUpdated() {
|
|
52
|
+
await this._initViewer();
|
|
53
|
+
}
|
|
54
|
+
async updated(changed) {
|
|
55
|
+
if (changed.has("src") && this._components && changed.get("src") !== void 0) await this._loadSrc();
|
|
56
|
+
if (changed.has("backgroundColor") && this._world) this._updateBackgroundColor();
|
|
57
|
+
}
|
|
58
|
+
disconnectedCallback() {
|
|
59
|
+
super.disconnectedCallback();
|
|
60
|
+
this._resizeObserver?.disconnect();
|
|
61
|
+
this._resizeObserver = null;
|
|
62
|
+
this._components?.dispose();
|
|
63
|
+
this._components = null;
|
|
64
|
+
this._world = null;
|
|
65
|
+
}
|
|
66
|
+
/** Load an IFC model from a URL. */
|
|
67
|
+
async loadUrl(url) {
|
|
68
|
+
if (!this._components) return;
|
|
69
|
+
try {
|
|
70
|
+
const ifcLoader = this._components.get(OBC.IfcLoader);
|
|
71
|
+
await ifcLoader.setup({
|
|
72
|
+
autoSetWasm: false,
|
|
73
|
+
wasm: {
|
|
74
|
+
path: this.wasmPath,
|
|
75
|
+
absolute: true
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
const response = await fetch(url);
|
|
79
|
+
if (!response.ok) throw new Error(`Failed to fetch IFC file: ${response.status} ${response.statusText}`);
|
|
80
|
+
const buffer = new Uint8Array(await response.arrayBuffer());
|
|
81
|
+
const name = url.split("/").pop()?.replace(".ifc", "") ?? "model";
|
|
82
|
+
await ifcLoader.load(buffer, true, name);
|
|
83
|
+
this.dispatchEvent(new SigveloIfcLoadEvent());
|
|
84
|
+
} catch (err) {
|
|
85
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
86
|
+
this.dispatchEvent(new SigveloIfcErrorEvent(error));
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
/** Load an IFC model from a File object. */
|
|
90
|
+
async loadFile(file) {
|
|
91
|
+
if (!this._components) return;
|
|
92
|
+
try {
|
|
93
|
+
const ifcLoader = this._components.get(OBC.IfcLoader);
|
|
94
|
+
await ifcLoader.setup({
|
|
95
|
+
autoSetWasm: false,
|
|
96
|
+
wasm: {
|
|
97
|
+
path: this.wasmPath,
|
|
98
|
+
absolute: true
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
const buffer = new Uint8Array(await file.arrayBuffer());
|
|
102
|
+
const name = file.name.replace(".ifc", "");
|
|
103
|
+
await ifcLoader.load(buffer, true, name);
|
|
104
|
+
this.dispatchEvent(new SigveloIfcLoadEvent());
|
|
105
|
+
} catch (err) {
|
|
106
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
107
|
+
this.dispatchEvent(new SigveloIfcErrorEvent(error));
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
async _initViewer() {
|
|
111
|
+
const container = this.renderRoot.querySelector(".viewer-container");
|
|
112
|
+
if (!container) return;
|
|
113
|
+
this._components = new OBC.Components();
|
|
114
|
+
const worlds = this._components.get(OBC.Worlds);
|
|
115
|
+
this._world = worlds.create();
|
|
116
|
+
this._world.scene = new OBC.SimpleScene(this._components);
|
|
117
|
+
this._world.renderer = new OBC.SimpleRenderer(this._components, container);
|
|
118
|
+
this._world.camera = new OBC.SimpleCamera(this._components);
|
|
119
|
+
this._components.init();
|
|
120
|
+
this._world.scene.setup();
|
|
121
|
+
this._updateBackgroundColor();
|
|
122
|
+
if (this.grid) this._components.get(OBC.Grids).create(this._world);
|
|
123
|
+
const fragments = this._components.get(OBC.FragmentsManager);
|
|
124
|
+
const workerBlob = await (await fetch(this.workerUrl)).blob();
|
|
125
|
+
const workerFile = new File([workerBlob], "worker.mjs", { type: "text/javascript" });
|
|
126
|
+
const workerObjectUrl = URL.createObjectURL(workerFile);
|
|
127
|
+
fragments.init(workerObjectUrl);
|
|
128
|
+
fragments.list.onItemSet.add(({ value: model }) => {
|
|
129
|
+
if (!this._world) return;
|
|
130
|
+
model.useCamera(this._world.camera.three);
|
|
131
|
+
this._world.scene.three.add(model.object);
|
|
132
|
+
fragments.core.update(true);
|
|
133
|
+
});
|
|
134
|
+
this._world.camera.controls.addEventListener("update", () => {
|
|
135
|
+
fragments.core.update();
|
|
136
|
+
});
|
|
137
|
+
await this._world.camera.controls.setLookAt(12, 6, 8, 0, 0, -10);
|
|
138
|
+
this._resizeObserver = new ResizeObserver(() => {
|
|
139
|
+
this._world?.renderer?.resize();
|
|
140
|
+
});
|
|
141
|
+
this._resizeObserver.observe(container);
|
|
142
|
+
if (this.src) await this._loadSrc();
|
|
143
|
+
}
|
|
144
|
+
async _loadSrc() {
|
|
145
|
+
if (this.src) await this.loadUrl(this.src);
|
|
146
|
+
}
|
|
147
|
+
_updateBackgroundColor() {
|
|
148
|
+
if (!this._world?.scene) return;
|
|
149
|
+
const threeScene = this._world.scene.three;
|
|
150
|
+
threeScene.background = new THREE.Color(this.backgroundColor);
|
|
151
|
+
}
|
|
152
|
+
render() {
|
|
153
|
+
return html`<div class="viewer-container" part="container"></div>`;
|
|
154
|
+
}
|
|
155
|
+
};
|
|
156
|
+
__decorate([property()], SigveloIfcViewer.prototype, "src", void 0);
|
|
157
|
+
__decorate([property({ attribute: "background-color" })], SigveloIfcViewer.prototype, "backgroundColor", void 0);
|
|
158
|
+
__decorate([property({
|
|
159
|
+
attribute: "camera-controls",
|
|
160
|
+
type: Boolean
|
|
161
|
+
})], SigveloIfcViewer.prototype, "cameraControls", void 0);
|
|
162
|
+
__decorate([property({ type: Boolean })], SigveloIfcViewer.prototype, "grid", void 0);
|
|
163
|
+
__decorate([property({ attribute: "wasm-path" })], SigveloIfcViewer.prototype, "wasmPath", void 0);
|
|
164
|
+
__decorate([property({ attribute: "worker-url" })], SigveloIfcViewer.prototype, "workerUrl", void 0);
|
|
165
|
+
SigveloIfcViewer = __decorate([customElement("sigvelo-ifc-viewer")], SigveloIfcViewer);
|
|
166
|
+
//#endregion
|
|
167
|
+
export { SigveloIfcViewer as t };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { SigveloIfcViewer } from "./components/ifc-viewer/ifc-viewer.js";
|
|
2
|
+
import { SigveloIfcErrorEvent, SigveloIfcLoadEvent, SigveloIfcProgressEvent } from "./components/ifc-viewer/ifc-viewer.events.js";
|
|
3
|
+
export { SigveloIfcErrorEvent, SigveloIfcLoadEvent, SigveloIfcProgressEvent, SigveloIfcViewer };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { SigveloIfcErrorEvent, SigveloIfcLoadEvent, SigveloIfcProgressEvent } from "./components/ifc-viewer/ifc-viewer.events.js";
|
|
2
|
+
import { t as SigveloIfcViewer } from "./ifc-viewer-Co1EAZcX.js";
|
|
3
|
+
export { SigveloIfcErrorEvent, SigveloIfcLoadEvent, SigveloIfcProgressEvent, SigveloIfcViewer };
|
package/package.json
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@mcp-b/aec-components",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "AEC (Architecture, Engineering, Construction) web components for Sigvelo, built with Lit.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"aec",
|
|
7
|
+
"bim",
|
|
8
|
+
"custom-elements",
|
|
9
|
+
"ifc",
|
|
10
|
+
"lit-element",
|
|
11
|
+
"web-components",
|
|
12
|
+
"webgl"
|
|
13
|
+
],
|
|
14
|
+
"license": "MIT",
|
|
15
|
+
"repository": {
|
|
16
|
+
"type": "git",
|
|
17
|
+
"url": "git+https://github.com/WebMCP-org/design-system.git",
|
|
18
|
+
"directory": "packages/aec-components"
|
|
19
|
+
},
|
|
20
|
+
"files": [
|
|
21
|
+
"dist"
|
|
22
|
+
],
|
|
23
|
+
"type": "module",
|
|
24
|
+
"types": "dist/index.d.ts",
|
|
25
|
+
"exports": {
|
|
26
|
+
".": {
|
|
27
|
+
"types": "./dist/index.d.ts",
|
|
28
|
+
"import": "./dist/index.js"
|
|
29
|
+
},
|
|
30
|
+
"./components/*": "./dist/components/*",
|
|
31
|
+
"./custom-elements.json": "./dist/docs/custom-elements.json"
|
|
32
|
+
},
|
|
33
|
+
"publishConfig": {
|
|
34
|
+
"access": "public"
|
|
35
|
+
},
|
|
36
|
+
"dependencies": {
|
|
37
|
+
"@mcp-b/wc-support": "0.2.0"
|
|
38
|
+
},
|
|
39
|
+
"devDependencies": {
|
|
40
|
+
"@custom-elements-manifest/analyzer": "^0.10.4",
|
|
41
|
+
"@storybook/addon-a11y": "^10.5.2",
|
|
42
|
+
"@storybook/addon-docs": "^10.5.2",
|
|
43
|
+
"@storybook/addon-vitest": "^10.5.2",
|
|
44
|
+
"@storybook/web-components-vite": "10.5.2",
|
|
45
|
+
"@thatopen/components": "^3.3.3",
|
|
46
|
+
"@thatopen/fragments": "^3.3.0",
|
|
47
|
+
"@types/three": "^0.183.0",
|
|
48
|
+
"@vitest/browser-playwright": "^4.1.10",
|
|
49
|
+
"@vitest/coverage-v8": "^4.1.10",
|
|
50
|
+
"@wc-toolkit/cem-inheritance": "^1.2.2",
|
|
51
|
+
"@wc-toolkit/cem-sorter": "^1.0.1",
|
|
52
|
+
"@wc-toolkit/type-parser": "^1.2.0",
|
|
53
|
+
"camera-controls": "^3.1.2",
|
|
54
|
+
"playwright": "~1.61.0",
|
|
55
|
+
"storybook": "^10.5.2",
|
|
56
|
+
"three": "^0.183.0",
|
|
57
|
+
"tinyglobby": "^0.2.15",
|
|
58
|
+
"typescript": "^6.0.3",
|
|
59
|
+
"vite": "npm:@voidzero-dev/vite-plus-core@0.2.4",
|
|
60
|
+
"vite-plugin-static-copy": "^3.3.0",
|
|
61
|
+
"vitest": "^4.1.10",
|
|
62
|
+
"web-ifc": "^0.0.77"
|
|
63
|
+
},
|
|
64
|
+
"peerDependencies": {
|
|
65
|
+
"@thatopen/components": "^3.0.0",
|
|
66
|
+
"lit": "^3.0.0",
|
|
67
|
+
"lit-html": "^3.0.0",
|
|
68
|
+
"three": ">=0.175.0",
|
|
69
|
+
"web-ifc": ">=0.0.74"
|
|
70
|
+
},
|
|
71
|
+
"customElements": "dist/docs/custom-elements.json",
|
|
72
|
+
"scripts": {
|
|
73
|
+
"analyze": "cem analyze",
|
|
74
|
+
"analyze:dev": "cem analyze --watch",
|
|
75
|
+
"build": "tsc -p tsconfig.prod.json && vp run build:lib && vp run analyze",
|
|
76
|
+
"build:lib": "vp pack",
|
|
77
|
+
"storybook": "vp run @mcp-b/web-components#storybook",
|
|
78
|
+
"test": "vp run @mcp-b/web-components#test",
|
|
79
|
+
"typecheck": "tsc --noEmit"
|
|
80
|
+
}
|
|
81
|
+
}
|