@ifc-lite/viewer 1.17.6 → 1.19.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 (156) hide show
  1. package/.turbo/turbo-build.log +20 -15
  2. package/.turbo/turbo-typecheck.log +1 -1
  3. package/CHANGELOG.md +949 -0
  4. package/dist/assets/{basketViewActivator-86rgogji.js → basketViewActivator-RZy5c3Td.js} +1 -1
  5. package/dist/assets/decode-worker-Collf_X_.js +1320 -0
  6. package/dist/assets/{exporters-CcPS9MK5.js → exporters-BraHBeoi.js} +4194 -3025
  7. package/dist/assets/{geometry.worker-BFUYA08u.js → geometry.worker-DQEZB2rB.js} +1 -1
  8. package/dist/assets/ifc-lite_bg-4yUkDRD8.wasm +0 -0
  9. package/dist/assets/index-0XpVr_S5.css +1 -0
  10. package/dist/assets/{index-Bfms9I4A.js → index-BOi3BuUI.js} +46423 -31181
  11. package/dist/assets/index-XwKzDuw6.js +22 -0
  12. package/dist/assets/{native-bridge-DUyLCMZS.js → native-bridge-CpBeOPQa.js} +1 -1
  13. package/dist/assets/sandbox-Baez7n-t.js +9682 -0
  14. package/dist/assets/{server-client-BuZK7OST.js → server-client-BB6cMAXE.js} +1 -1
  15. package/dist/assets/{wasm-bridge-JsqEGDV8.js → wasm-bridge-CAYCUHbE.js} +1 -1
  16. package/dist/index.html +6 -6
  17. package/package.json +11 -10
  18. package/src/apache-arrow.d.ts +30 -0
  19. package/src/components/viewer/AddElementPanel.tsx +758 -0
  20. package/src/components/viewer/BulkPropertyEditor.tsx +7 -0
  21. package/src/components/viewer/ChatPanel.tsx +64 -2
  22. package/src/components/viewer/CommandPalette.tsx +56 -7
  23. package/src/components/viewer/EntityContextMenu.tsx +168 -4
  24. package/src/components/viewer/ExportChangesButton.tsx +25 -5
  25. package/src/components/viewer/ExportDialog.tsx +19 -1
  26. package/src/components/viewer/MainToolbar.tsx +73 -12
  27. package/src/components/viewer/PointCloudPanel.tsx +174 -0
  28. package/src/components/viewer/PropertiesPanel.tsx +222 -22
  29. package/src/components/viewer/SearchInline.tsx +669 -0
  30. package/src/components/viewer/SearchModal.filter.builder.tsx +766 -0
  31. package/src/components/viewer/SearchModal.filter.tsx +514 -0
  32. package/src/components/viewer/SearchModal.text.tsx +388 -0
  33. package/src/components/viewer/SearchModal.tsx +235 -0
  34. package/src/components/viewer/ToolOverlays.tsx +5 -0
  35. package/src/components/viewer/ViewerLayout.tsx +24 -4
  36. package/src/components/viewer/Viewport.tsx +29 -2
  37. package/src/components/viewer/ViewportContainer.tsx +45 -5
  38. package/src/components/viewer/ViewportOverlays.tsx +13 -2
  39. package/src/components/viewer/annotations/AnnotationDropInput.tsx +203 -0
  40. package/src/components/viewer/annotations/AnnotationLayer.tsx +287 -0
  41. package/src/components/viewer/annotations/AnnotationPin.tsx +90 -0
  42. package/src/components/viewer/annotations/AnnotationPopover.tsx +296 -0
  43. package/src/components/viewer/bcf/BCFTopicDetail.tsx +1 -1
  44. package/src/components/viewer/lists/ListPanel.tsx +14 -21
  45. package/src/components/viewer/properties/RawStepCard.tsx +332 -0
  46. package/src/components/viewer/properties/RawStepRow.tsx +261 -0
  47. package/src/components/viewer/properties/ScheduleCard.tsx +224 -0
  48. package/src/components/viewer/properties/TaskEditCard.tsx +510 -0
  49. package/src/components/viewer/properties/raw-step-format.ts +193 -0
  50. package/src/components/viewer/schedule/AnimationSettingsPopover.tsx +542 -0
  51. package/src/components/viewer/schedule/GanttDependencyArrows.tsx +89 -0
  52. package/src/components/viewer/schedule/GanttDragTooltip.tsx +48 -0
  53. package/src/components/viewer/schedule/GanttEmptyState.tsx +97 -0
  54. package/src/components/viewer/schedule/GanttPanel.tsx +295 -0
  55. package/src/components/viewer/schedule/GanttTaskBar.tsx +199 -0
  56. package/src/components/viewer/schedule/GanttTaskTree.tsx +250 -0
  57. package/src/components/viewer/schedule/GanttTimeline.tsx +305 -0
  58. package/src/components/viewer/schedule/GanttToolbar.tsx +406 -0
  59. package/src/components/viewer/schedule/GenerateAdvancedPanel.tsx +147 -0
  60. package/src/components/viewer/schedule/GenerateScheduleDialog.tsx +392 -0
  61. package/src/components/viewer/schedule/HeightStrategyPanel.tsx +120 -0
  62. package/src/components/viewer/schedule/generate-schedule.test.ts +439 -0
  63. package/src/components/viewer/schedule/generate-schedule.ts +648 -0
  64. package/src/components/viewer/schedule/schedule-animator.test.ts +452 -0
  65. package/src/components/viewer/schedule/schedule-animator.ts +488 -0
  66. package/src/components/viewer/schedule/schedule-selection.test.ts +148 -0
  67. package/src/components/viewer/schedule/schedule-selection.ts +163 -0
  68. package/src/components/viewer/schedule/schedule-utils.ts +223 -0
  69. package/src/components/viewer/schedule/useConstructionSequence.ts +156 -0
  70. package/src/components/viewer/schedule/useGanttBarDrag.test.ts +90 -0
  71. package/src/components/viewer/schedule/useGanttBarDrag.ts +305 -0
  72. package/src/components/viewer/schedule/useGanttSelection3DHighlight.ts +152 -0
  73. package/src/components/viewer/schedule/useOverlayCompositor.ts +108 -0
  74. package/src/components/viewer/selectionHandlers.ts +446 -0
  75. package/src/components/viewer/tools/AddElementOverlay.tsx +581 -0
  76. package/src/components/viewer/useDuplicateShortcut.ts +77 -0
  77. package/src/components/viewer/useMouseControls.ts +9 -1
  78. package/src/components/viewer/usePointCloudLifecycle.ts +64 -0
  79. package/src/components/viewer/usePointCloudSync.ts +98 -0
  80. package/src/hooks/ingest/pointCloudIngest.ts +391 -0
  81. package/src/hooks/ingest/viewerModelIngest.ts +32 -3
  82. package/src/hooks/useIfcFederation.ts +72 -3
  83. package/src/hooks/useIfcLoader.ts +89 -13
  84. package/src/hooks/useKeyboardShortcuts.ts +25 -0
  85. package/src/hooks/useSandbox.ts +1 -1
  86. package/src/hooks/useSearchIndex.ts +125 -0
  87. package/src/index.css +66 -0
  88. package/src/lib/llm/system-prompt.test.ts +14 -0
  89. package/src/lib/llm/system-prompt.ts +102 -1
  90. package/src/lib/llm/types.ts +6 -0
  91. package/src/lib/recent-files.ts +38 -4
  92. package/src/lib/scripts/templates/bim-globals.d.ts +136 -114
  93. package/src/lib/scripts/templates/construction-schedule.ts +223 -0
  94. package/src/lib/scripts/templates.ts +7 -0
  95. package/src/lib/search/common-ifc-types.ts +36 -0
  96. package/src/lib/search/filter-evaluate.test.ts +537 -0
  97. package/src/lib/search/filter-evaluate.ts +610 -0
  98. package/src/lib/search/filter-rules.test.ts +119 -0
  99. package/src/lib/search/filter-rules.ts +198 -0
  100. package/src/lib/search/filter-schema.test.ts +233 -0
  101. package/src/lib/search/filter-schema.ts +146 -0
  102. package/src/lib/search/recent-searches.test.ts +116 -0
  103. package/src/lib/search/recent-searches.ts +93 -0
  104. package/src/lib/search/result-export.test.ts +101 -0
  105. package/src/lib/search/result-export.ts +104 -0
  106. package/src/lib/search/saved-filters.test.ts +118 -0
  107. package/src/lib/search/saved-filters.ts +154 -0
  108. package/src/lib/search/tier0-scan.test.ts +196 -0
  109. package/src/lib/search/tier0-scan.ts +237 -0
  110. package/src/lib/search/tier1-index.test.ts +242 -0
  111. package/src/lib/search/tier1-index.ts +448 -0
  112. package/src/sdk/adapters/export-adapter.test.ts +434 -1
  113. package/src/sdk/adapters/export-adapter.ts +404 -1
  114. package/src/sdk/adapters/export-schedule-splice.test.ts +127 -0
  115. package/src/sdk/adapters/export-schedule-splice.ts +87 -0
  116. package/src/sdk/adapters/model-compat.ts +8 -2
  117. package/src/sdk/adapters/schedule-adapter.ts +73 -0
  118. package/src/sdk/adapters/store-adapter.ts +201 -0
  119. package/src/sdk/adapters/visibility-adapter.ts +3 -0
  120. package/src/sdk/local-backend.ts +16 -8
  121. package/src/services/desktop-export.ts +3 -1
  122. package/src/services/desktop-native-metadata.ts +41 -18
  123. package/src/services/file-dialog.ts +8 -3
  124. package/src/services/tauri-modules.d.ts +25 -0
  125. package/src/store/basketVisibleSet.ts +3 -0
  126. package/src/store/globalId.ts +4 -1
  127. package/src/store/index.ts +79 -1
  128. package/src/store/slices/addElementMeshes.ts +365 -0
  129. package/src/store/slices/addElementSlice.ts +275 -0
  130. package/src/store/slices/annotationsSlice.test.ts +133 -0
  131. package/src/store/slices/annotationsSlice.ts +251 -0
  132. package/src/store/slices/dataSlice.test.ts +23 -4
  133. package/src/store/slices/dataSlice.ts +1 -1
  134. package/src/store/slices/modelSlice.test.ts +67 -9
  135. package/src/store/slices/modelSlice.ts +39 -7
  136. package/src/store/slices/mutationSlice.ts +964 -3
  137. package/src/store/slices/overlayCompositor.test.ts +164 -0
  138. package/src/store/slices/overlaySlice.test.ts +93 -0
  139. package/src/store/slices/overlaySlice.ts +151 -0
  140. package/src/store/slices/pinboardSlice.test.ts +6 -1
  141. package/src/store/slices/playbackSlice.ts +128 -0
  142. package/src/store/slices/pointCloudSlice.ts +102 -0
  143. package/src/store/slices/schedule-edit-helpers.test.ts +97 -0
  144. package/src/store/slices/schedule-edit-helpers.ts +179 -0
  145. package/src/store/slices/scheduleSlice.test.ts +694 -0
  146. package/src/store/slices/scheduleSlice.ts +1330 -0
  147. package/src/store/slices/searchSlice.test.ts +342 -0
  148. package/src/store/slices/searchSlice.ts +341 -0
  149. package/src/store/slices/selectionSlice.test.ts +46 -0
  150. package/src/store/slices/selectionSlice.ts +20 -0
  151. package/src/store/types.ts +7 -0
  152. package/src/store.ts +14 -0
  153. package/vite.config.ts +1 -0
  154. package/dist/assets/ifc-lite_bg-BINvzoCP.wasm +0 -0
  155. package/dist/assets/index-_bfZsDCC.css +0 -1
  156. package/dist/assets/sandbox-C8575tul.js +0 -5951
@@ -106,6 +106,52 @@ describe('SelectionSlice', () => {
106
106
  });
107
107
  });
108
108
 
109
+ describe('multi-model selection: addEntitiesToSelection (batch)', () => {
110
+ it('should add every ref in one set call', () => {
111
+ const refs: EntityRef[] = [
112
+ { modelId: 'model-1', expressId: 1 },
113
+ { modelId: 'model-1', expressId: 2 },
114
+ { modelId: 'model-2', expressId: 3 },
115
+ ];
116
+ state.addEntitiesToSelection(refs);
117
+ assert.strictEqual(state.selectedEntitiesSet.size, 3);
118
+ });
119
+
120
+ it('should set primary selection to the LAST ref (matches single-add convention)', () => {
121
+ const refs: EntityRef[] = [
122
+ { modelId: 'model-1', expressId: 1 },
123
+ { modelId: 'model-2', expressId: 99 },
124
+ ];
125
+ state.addEntitiesToSelection(refs);
126
+ assert.deepStrictEqual(state.selectedEntity, { modelId: 'model-2', expressId: 99 });
127
+ });
128
+
129
+ it('should be a no-op for empty input', () => {
130
+ const before = state.selectedEntitiesSet;
131
+ state.addEntitiesToSelection([]);
132
+ assert.strictEqual(state.selectedEntitiesSet, before, 'state ref unchanged');
133
+ });
134
+
135
+ it('should compose with prior single-adds without losing entries', () => {
136
+ const ref0: EntityRef = { modelId: 'model-1', expressId: 0 };
137
+ state.addEntityToSelection(ref0);
138
+ state.addEntitiesToSelection([
139
+ { modelId: 'model-1', expressId: 1 },
140
+ { modelId: 'model-1', expressId: 2 },
141
+ ]);
142
+ assert.strictEqual(state.selectedEntitiesSet.size, 3);
143
+ });
144
+
145
+ it('should dedupe overlapping refs without changing the set size beyond the union', () => {
146
+ state.addEntityToSelection({ modelId: 'm', expressId: 7 });
147
+ state.addEntitiesToSelection([
148
+ { modelId: 'm', expressId: 7 }, // duplicate
149
+ { modelId: 'm', expressId: 8 },
150
+ ]);
151
+ assert.strictEqual(state.selectedEntitiesSet.size, 2);
152
+ });
153
+ });
154
+
109
155
  describe('multi-model selection: removeEntityFromSelection', () => {
110
156
  it('should remove entity from selection set', () => {
111
157
  const ref: EntityRef = { modelId: 'model-1', expressId: 123 };
@@ -46,6 +46,13 @@ export interface SelectionSlice {
46
46
  setSelectedEntity: (ref: EntityRef | null) => void;
47
47
  /** Add entity to multi-selection */
48
48
  addEntityToSelection: (ref: EntityRef) => void;
49
+ /**
50
+ * Batch-add multiple entities to multi-selection in a single Zustand
51
+ * `set`. Use for bulk paths like "Select all visible results" — the
52
+ * naïve loop over `addEntityToSelection` re-renders every subscriber
53
+ * O(N) times for an N-row select. Empty input is a no-op.
54
+ */
55
+ addEntitiesToSelection: (refs: ReadonlyArray<EntityRef>) => void;
49
56
  /** Remove entity from multi-selection */
50
57
  removeEntityFromSelection: (ref: EntityRef) => void;
51
58
  /** Toggle entity in multi-selection */
@@ -170,6 +177,19 @@ export const createSelectionSlice: StateCreator<SelectionSlice, [], [], Selectio
170
177
  };
171
178
  }),
172
179
 
180
+ addEntitiesToSelection: (refs) => set((state) => {
181
+ if (refs.length === 0) return {};
182
+ const newSet = new Set(state.selectedEntitiesSet);
183
+ for (const ref of refs) newSet.add(entityRefToString(ref));
184
+ // Primary selection becomes the LAST ref in the input — matches the
185
+ // existing addEntityToSelection convention where the most recent
186
+ // add is treated as primary.
187
+ return {
188
+ selectedEntitiesSet: newSet,
189
+ selectedEntity: refs[refs.length - 1],
190
+ };
191
+ }),
192
+
173
193
  removeEntityFromSelection: (ref) => set((state) => {
174
194
  const key = entityRefToString(ref);
175
195
  const newSet = new Set(state.selectedEntitiesSet);
@@ -340,6 +340,13 @@ export interface FederatedModel {
340
340
  cacheState?: 'none' | 'hit' | 'miss' | 'writing';
341
341
  /** Optional load error for this model. */
342
342
  loadError?: string | null;
343
+ /**
344
+ * Renderer handle for a streamed point cloud (LAS/LAZ) attached to
345
+ * this model. Stored as a plain number so the field stays JSON-safe.
346
+ * The viewport's removal effect calls `renderer.removePointCloudAsset`
347
+ * when the model is dropped from the store.
348
+ */
349
+ pointCloudHandleId?: number;
343
350
  }
344
351
 
345
352
  /** Convert EntityRef to string for use as Map/Set key */
package/src/store.ts CHANGED
@@ -48,3 +48,17 @@ export { entityRefToString, stringToEntityRef, entityRefEquals, isIfcxDataStore
48
48
 
49
49
  // Re-export single source of truth for globalId → EntityRef resolution
50
50
  export { resolveEntityRef } from './store/resolveEntityRef.js';
51
+ export { toGlobalIdFromModels, fromGlobalIdFromModels, toGlobalIdForRef } from './store/globalId.js';
52
+ export type { ForwardModelMapLike } from './store/globalId.js';
53
+
54
+ // Re-export Schedule (4D) types + helpers
55
+ export type { ScheduleSlice, ScheduleTimeRange, GanttTimeScale } from './store/slices/scheduleSlice.js';
56
+ export {
57
+ computeScheduleRange,
58
+ computeHiddenProductIds,
59
+ computeActiveProductIds,
60
+ countGeneratedTasks,
61
+ taskStartEpoch,
62
+ taskFinishEpoch,
63
+ parseIsoDate,
64
+ } from './store/slices/scheduleSlice.js';
package/vite.config.ts CHANGED
@@ -253,6 +253,7 @@ export default defineConfig({
253
253
  '@ifc-lite/export': path.resolve(__dirname, '../../packages/export/src'),
254
254
  '@ifc-lite/cache': path.resolve(__dirname, '../../packages/cache/src'),
255
255
  '@ifc-lite/ifcx': path.resolve(__dirname, '../../packages/ifcx/src'),
256
+ '@ifc-lite/pointcloud': path.resolve(__dirname, '../../packages/pointcloud/src'),
256
257
  '@ifc-lite/wasm': path.resolve(__dirname, '../../packages/wasm/pkg/ifc-lite.js'),
257
258
  '@ifc-lite/sdk': path.resolve(__dirname, '../../packages/sdk/src'),
258
259
  '@ifc-lite/create': path.resolve(__dirname, '../../packages/create/src'),