@sequent-org/ifc-viewer 1.2.4-ci.52.0 → 1.2.4-ci.54.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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@sequent-org/ifc-viewer",
3
3
  "private": false,
4
- "version": "1.2.4-ci.52.0",
4
+ "version": "1.2.4-ci.54.0",
5
5
  "type": "module",
6
6
  "description": "IFC 3D model viewer component for web applications - fully self-contained with local IFCLoader",
7
7
  "main": "src/index.js",
package/src/IfcViewer.js CHANGED
@@ -22,7 +22,7 @@ import { TdsModelLoader } from "./model-loading/loaders/TdsModelLoader.js";
22
22
  import { StlModelLoader } from "./model-loading/loaders/StlModelLoader.js";
23
23
  import { DaeModelLoader } from "./model-loading/loaders/DaeModelLoader.js";
24
24
  import { ThreeDmModelLoader } from "./model-loading/loaders/ThreeDmModelLoader.js";
25
- import { CardPlacementController } from "./ui/CardPlacementController.js";
25
+ import { LabelPlacementController } from "./ui/LabelPlacementController.js";
26
26
  import './style.css';
27
27
 
28
28
 
@@ -83,6 +83,7 @@ export class IfcViewer {
83
83
  this.viewer = null;
84
84
  this.ifcService = null;
85
85
  this.ifcTreeView = null;
86
+ this.labelPlacement = null;
86
87
  this.cardPlacement = null;
87
88
  /** @type {ModelLoaderRegistry|null} */
88
89
  this.modelLoaders = null;
@@ -311,10 +312,11 @@ export class IfcViewer {
311
312
  this.ifcService = null;
312
313
  }
313
314
 
314
- if (this.cardPlacement) {
315
- try { this.cardPlacement.dispose(); } catch (_) {}
316
- this.cardPlacement = null;
315
+ if (this.labelPlacement) {
316
+ try { this.labelPlacement.dispose(); } catch (_) {}
317
+ this.labelPlacement = null;
317
318
  }
319
+ this.cardPlacement = null;
318
320
 
319
321
  if (this.viewer) {
320
322
  this.viewer.dispose();
@@ -360,6 +362,49 @@ export class IfcViewer {
360
362
  return this.ifcService;
361
363
  }
362
364
 
365
+ /**
366
+ * Устанавливает метки извне.
367
+ * @param {Array<{id: (number|string), localPoint: {x:number,y:number,z:number}, sceneState: object}>} items
368
+ */
369
+ setLabelMarkers(items) {
370
+ if (!this.labelPlacement) return;
371
+ this.labelPlacement.setLabelMarkers(items);
372
+ }
373
+
374
+ /**
375
+ * Возвращает текущие метки.
376
+ * @returns {Array<{id: (number|string), localPoint: {x:number,y:number,z:number}, sceneState: object}>}
377
+ */
378
+ getLabelMarkers() {
379
+ if (!this.labelPlacement) return [];
380
+ return this.labelPlacement.getLabelMarkers();
381
+ }
382
+
383
+ /**
384
+ * Программно выбирает метку по id.
385
+ * @param {number|string|null} id
386
+ */
387
+ selectLabel(id) {
388
+ if (!this.labelPlacement) return;
389
+ this.labelPlacement.selectLabel(id);
390
+ }
391
+
392
+ /**
393
+ * @deprecated используйте setLabelMarkers
394
+ */
395
+ setCardMarkers(items) {
396
+ if (!this.labelPlacement) return;
397
+ this.labelPlacement.setCardMarkers(items);
398
+ }
399
+
400
+ /**
401
+ * @deprecated используйте getLabelMarkers
402
+ */
403
+ getCardMarkers() {
404
+ if (!this.labelPlacement) return [];
405
+ return this.labelPlacement.getCardMarkers();
406
+ }
407
+
363
408
  /**
364
409
  * Устанавливает видимость боковой панели
365
410
  * @param {boolean} visible - Показать или скрыть
@@ -516,12 +561,14 @@ export class IfcViewer {
516
561
  this.viewer = new Viewer(this.elements.viewerContainer);
517
562
  this.viewer.init();
518
563
 
519
- // В пакете включаем UI "карточек" по умолчанию:
520
- // кнопка "+ Добавить карточку" + режим постановки меток + сохранение/восстановление состояния.
564
+ // В пакете включаем UI "меток" по умолчанию:
565
+ // кнопка "+ Добавить метку" + режим постановки меток + сохранение/восстановление состояния.
521
566
  try {
522
- this.cardPlacement = new CardPlacementController({ viewer: this.viewer, container: this.elements.viewerContainer, logger: console });
567
+ this.labelPlacement = new LabelPlacementController({ viewer: this.viewer, container: this.elements.viewerContainer, logger: console });
568
+ this.cardPlacement = this.labelPlacement;
523
569
  } catch (e) {
524
- console.warn('IfcViewer: CardPlacementController init failed', e);
570
+ console.warn('IfcViewer: LabelPlacementController init failed', e);
571
+ this.labelPlacement = null;
525
572
  this.cardPlacement = null;
526
573
  }
527
574
  }
package/src/main.js CHANGED
@@ -3,7 +3,7 @@ import { Viewer } from "./viewer/Viewer.js";
3
3
  import { IfcService } from "./ifc/IfcService.js";
4
4
  import { IfcTreeView } from "./ifc/IfcTreeView.js";
5
5
  import { ModelLoaderRegistry } from "./model-loading/ModelLoaderRegistry.js";
6
- import { CardPlacementController } from "./ui/CardPlacementController.js";
6
+ import { LabelPlacementController } from "./ui/LabelPlacementController.js";
7
7
  import { IfcModelLoader } from "./model-loading/loaders/IfcModelLoader.js";
8
8
  import { FbxModelLoader } from "./model-loading/loaders/FbxModelLoader.js";
9
9
  import { GltfModelLoader } from "./model-loading/loaders/GltfModelLoader.js";
@@ -19,8 +19,8 @@ if (app) {
19
19
  const viewer = new Viewer(app);
20
20
  viewer.init();
21
21
 
22
- // UI: режим постановки "карточек" (меток) по клику на модель
23
- const cardPlacement = new CardPlacementController({ viewer, container: app, logger: console });
22
+ // UI: режим постановки меток по клику на модель
23
+ const labelPlacement = new LabelPlacementController({ viewer, container: app, logger: console });
24
24
 
25
25
  // ===== Диагностика (включается через query-параметры) =====
26
26
  // ?debugViewer=1 -> window.__viewer = viewer
@@ -680,7 +680,7 @@ if (app) {
680
680
  import.meta.hot.dispose(() => {
681
681
  ifc.dispose();
682
682
  viewer.dispose();
683
- try { cardPlacement.dispose(); } catch (_) {}
683
+ try { labelPlacement.dispose(); } catch (_) {}
684
684
  });
685
685
  }
686
686
  }
@@ -110,7 +110,8 @@
110
110
  .duration-300 { transition-duration: 300ms; }
111
111
  .pointer-events-none { pointer-events: none; }
112
112
 
113
- /* === IFC CARD MARKERS (UI overlay) === */
113
+ /* === IFC LABEL MARKERS (UI overlay) === */
114
+ .ifc-label-add-btn,
114
115
  .ifc-card-add-btn {
115
116
  position: absolute;
116
117
  left: 12px;
@@ -130,10 +131,13 @@
130
131
  backdrop-filter: blur(6px);
131
132
  }
132
133
 
134
+ .ifc-label-add-btn:hover,
133
135
  .ifc-card-add-btn:hover {
134
136
  background: rgba(255, 255, 255, 0.98);
135
137
  }
136
138
 
139
+ .ifc-label-ghost,
140
+ .ifc-label-marker,
137
141
  .ifc-card-ghost,
138
142
  .ifc-card-marker {
139
143
  position: absolute;
@@ -144,10 +148,12 @@
144
148
  will-change: transform;
145
149
  }
146
150
 
151
+ .ifc-label-ghost,
147
152
  .ifc-card-ghost {
148
153
  display: none;
149
154
  }
150
155
 
156
+ .ifc-label-dot,
151
157
  .ifc-card-dot {
152
158
  width: 18px;
153
159
  height: 18px;
@@ -157,6 +163,7 @@
157
163
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.18);
158
164
  }
159
165
 
166
+ .ifc-label-num,
160
167
  .ifc-card-num {
161
168
  position: absolute;
162
169
  left: 0;
@@ -172,6 +179,7 @@
172
179
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.35);
173
180
  }
174
181
 
182
+ .ifc-label-marker,
175
183
  .ifc-card-marker {
176
184
  width: 18px;
177
185
  height: 18px;
@@ -180,11 +188,50 @@
180
188
  }
181
189
 
182
190
  /* Клик ловим на контейнере метки, дочерние элементы пусть не перехватывают */
191
+ .ifc-label-marker .ifc-label-dot,
192
+ .ifc-label-marker .ifc-label-num,
183
193
  .ifc-card-marker .ifc-card-dot,
184
194
  .ifc-card-marker .ifc-card-num {
185
195
  pointer-events: none;
186
196
  }
187
197
 
198
+ .ifc-label-marker--active .ifc-label-dot,
199
+ .ifc-card-marker--active .ifc-card-dot {
200
+ box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.95), 0 0 0 4px rgba(37, 99, 235, 0.95);
201
+ }
202
+
203
+ /* === LABEL CONTEXT MENU === */
204
+ .ifc-label-menu {
205
+ position: absolute;
206
+ z-index: 10000;
207
+ display: block;
208
+ min-width: 140px;
209
+ padding: 6px;
210
+ background: rgba(255, 255, 255, 0.98);
211
+ border: 1px solid rgba(0, 0, 0, 0.12);
212
+ border-radius: 10px;
213
+ box-shadow: 0 8px 24px rgba(0, 0, 0, 0.18);
214
+ backdrop-filter: blur(6px);
215
+ }
216
+
217
+ .ifc-label-menu-item {
218
+ width: 100%;
219
+ display: block;
220
+ text-align: left;
221
+ border: none;
222
+ background: transparent;
223
+ color: #1f2937;
224
+ font-size: 12px;
225
+ font-weight: 600;
226
+ padding: 6px 8px;
227
+ border-radius: 6px;
228
+ cursor: pointer;
229
+ }
230
+
231
+ .ifc-label-menu-item:hover {
232
+ background: rgba(37, 99, 235, 0.12);
233
+ }
234
+
188
235
  /* === NAVBAR COMPONENT === */
189
236
  .navbar {
190
237
  display: flex;