@ifc-lite/viewer 1.17.4 → 1.18.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/.turbo/turbo-build.log +20 -17
- package/.turbo/turbo-typecheck.log +1 -1
- package/CHANGELOG.md +630 -0
- package/DESKTOP_CONTRACT_VERSION +1 -1
- package/dist/assets/{basketViewActivator-BmnNtVfZ.js → basketViewActivator-Cm1QEk_R.js} +1 -1
- package/dist/assets/drawing-2d-DoxKMqbO.js +257 -0
- package/dist/assets/{exporters-ChAtBmlj.js → exporters-B_OBqIyD.js} +3479 -2845
- package/dist/assets/{geometry.worker-BQ0rzNo-.js → geometry.worker-xHHy-9DV.js} +1 -1
- package/dist/assets/ids-DQ5jY0E8.js +1 -0
- package/dist/assets/ifc-lite_bg-ADjKXSms.wasm +0 -0
- package/dist/assets/{index-Co8E2-FE.js → index-BKq-M3Mk.js} +55873 -40593
- package/dist/assets/index-COnQRuqY.css +1 -0
- package/dist/assets/{native-bridge-BRvbckFQ.js → native-bridge-SHXiQwFW.js} +104 -104
- package/dist/assets/sandbox-jez21HtV.js +9627 -0
- package/dist/assets/{server-client-BV8zHZ7Y.js → server-client-ncOQVNso.js} +1 -1
- package/dist/assets/{wasm-bridge-g01g7T9b.js → wasm-bridge-DyfBSB8z.js} +1 -1
- package/dist/index.html +8 -7
- package/index.html +1 -0
- package/package.json +13 -13
- package/src/App.tsx +16 -2
- package/src/apache-arrow.d.ts +30 -0
- package/src/components/viewer/AddElementPanel.tsx +758 -0
- package/src/components/viewer/BulkPropertyEditor.tsx +7 -0
- package/src/components/viewer/CesiumOverlay.tsx +62 -19
- package/src/components/viewer/ChatPanel.tsx +259 -93
- package/src/components/viewer/CommandPalette.tsx +56 -7
- package/src/components/viewer/EntityContextMenu.tsx +168 -4
- package/src/components/viewer/ExportChangesButton.tsx +25 -5
- package/src/components/viewer/ExportDialog.tsx +19 -1
- package/src/components/viewer/MainToolbar.tsx +73 -13
- package/src/components/viewer/PropertiesPanel.tsx +237 -23
- package/src/components/viewer/SearchInline.tsx +669 -0
- package/src/components/viewer/SearchModal.filter.builder.tsx +766 -0
- package/src/components/viewer/SearchModal.filter.tsx +514 -0
- package/src/components/viewer/SearchModal.text.tsx +388 -0
- package/src/components/viewer/SearchModal.tsx +235 -0
- package/src/components/viewer/SettingsPage.tsx +252 -101
- package/src/components/viewer/ThemeSwitch.tsx +63 -7
- package/src/components/viewer/ToolOverlays.tsx +5 -0
- package/src/components/viewer/ViewerLayout.tsx +25 -4
- package/src/components/viewer/Viewport.tsx +25 -3
- package/src/components/viewer/ViewportContainer.tsx +51 -64
- package/src/components/viewer/ViewportOverlays.tsx +5 -2
- package/src/components/viewer/annotations/AnnotationDropInput.tsx +203 -0
- package/src/components/viewer/annotations/AnnotationLayer.tsx +287 -0
- package/src/components/viewer/annotations/AnnotationPin.tsx +90 -0
- package/src/components/viewer/annotations/AnnotationPopover.tsx +296 -0
- package/src/components/viewer/bcf/BCFTopicDetail.tsx +4 -4
- package/src/components/viewer/chat/ModelSelector.tsx +90 -54
- package/src/components/viewer/lists/ListPanel.tsx +14 -21
- package/src/components/viewer/properties/GeoreferencingPanel.tsx +113 -51
- package/src/components/viewer/properties/LocationMap.tsx +9 -7
- package/src/components/viewer/properties/ModelMetadataPanel.tsx +1 -1
- package/src/components/viewer/properties/RawStepCard.tsx +332 -0
- package/src/components/viewer/properties/RawStepRow.tsx +261 -0
- package/src/components/viewer/properties/ScheduleCard.tsx +224 -0
- package/src/components/viewer/properties/TaskEditCard.tsx +510 -0
- package/src/components/viewer/properties/raw-step-format.ts +193 -0
- package/src/components/viewer/schedule/AnimationSettingsPopover.tsx +542 -0
- package/src/components/viewer/schedule/GanttDependencyArrows.tsx +89 -0
- package/src/components/viewer/schedule/GanttDragTooltip.tsx +48 -0
- package/src/components/viewer/schedule/GanttEmptyState.tsx +97 -0
- package/src/components/viewer/schedule/GanttPanel.tsx +295 -0
- package/src/components/viewer/schedule/GanttTaskBar.tsx +199 -0
- package/src/components/viewer/schedule/GanttTaskTree.tsx +250 -0
- package/src/components/viewer/schedule/GanttTimeline.tsx +305 -0
- package/src/components/viewer/schedule/GanttToolbar.tsx +406 -0
- package/src/components/viewer/schedule/GenerateAdvancedPanel.tsx +147 -0
- package/src/components/viewer/schedule/GenerateScheduleDialog.tsx +392 -0
- package/src/components/viewer/schedule/HeightStrategyPanel.tsx +120 -0
- package/src/components/viewer/schedule/generate-schedule.test.ts +439 -0
- package/src/components/viewer/schedule/generate-schedule.ts +648 -0
- package/src/components/viewer/schedule/schedule-animator.test.ts +452 -0
- package/src/components/viewer/schedule/schedule-animator.ts +488 -0
- package/src/components/viewer/schedule/schedule-selection.test.ts +148 -0
- package/src/components/viewer/schedule/schedule-selection.ts +163 -0
- package/src/components/viewer/schedule/schedule-utils.ts +223 -0
- package/src/components/viewer/schedule/useConstructionSequence.ts +156 -0
- package/src/components/viewer/schedule/useGanttBarDrag.test.ts +90 -0
- package/src/components/viewer/schedule/useGanttBarDrag.ts +305 -0
- package/src/components/viewer/schedule/useGanttSelection3DHighlight.ts +152 -0
- package/src/components/viewer/schedule/useOverlayCompositor.ts +108 -0
- package/src/components/viewer/selectionHandlers.ts +446 -0
- package/src/components/viewer/tools/AddElementOverlay.tsx +540 -0
- package/src/components/viewer/tools/SectionCapControls.tsx +237 -0
- package/src/components/viewer/tools/SectionPanel.tsx +39 -18
- package/src/components/viewer/useAnimationLoop.ts +9 -1
- package/src/components/viewer/useDuplicateShortcut.ts +77 -0
- package/src/components/viewer/useMouseControls.ts +9 -1
- package/src/components/viewer/useRenderUpdates.ts +1 -1
- package/src/hooks/ids/idsDataAccessor.ts +60 -24
- package/src/hooks/ingest/viewerModelIngest.ts +7 -2
- package/src/hooks/useIfcFederation.ts +326 -71
- package/src/hooks/useIfcLoader.ts +23 -10
- package/src/hooks/useKeyboardShortcuts.ts +25 -0
- package/src/hooks/useSandbox.ts +1 -1
- package/src/hooks/useSearchIndex.ts +125 -0
- package/src/hooks/useViewControls.ts +13 -5
- package/src/index.css +550 -10
- package/src/lib/desktop-entitlement.ts +2 -4
- package/src/lib/geo/cesium-bridge.ts +15 -7
- package/src/lib/geo/effective-georef.test.ts +73 -0
- package/src/lib/geo/effective-georef.ts +111 -0
- package/src/lib/geo/reproject.ts +105 -19
- package/src/lib/llm/byok-guard.test.ts +77 -0
- package/src/lib/llm/byok-guard.ts +39 -0
- package/src/lib/llm/free-models.test.ts +0 -6
- package/src/lib/llm/models.ts +104 -42
- package/src/lib/llm/stream-client.ts +74 -110
- package/src/lib/llm/stream-direct.test.ts +130 -0
- package/src/lib/llm/stream-direct.ts +316 -0
- package/src/lib/llm/system-prompt.test.ts +14 -0
- package/src/lib/llm/system-prompt.ts +102 -1
- package/src/lib/llm/types.ts +20 -2
- package/src/lib/recent-files.ts +38 -4
- package/src/lib/scripts/templates/bim-globals.d.ts +136 -114
- package/src/lib/scripts/templates/construction-schedule.ts +223 -0
- package/src/lib/scripts/templates.ts +7 -0
- package/src/lib/search/common-ifc-types.ts +36 -0
- package/src/lib/search/filter-evaluate.test.ts +537 -0
- package/src/lib/search/filter-evaluate.ts +610 -0
- package/src/lib/search/filter-rules.test.ts +119 -0
- package/src/lib/search/filter-rules.ts +198 -0
- package/src/lib/search/filter-schema.test.ts +233 -0
- package/src/lib/search/filter-schema.ts +146 -0
- package/src/lib/search/recent-searches.test.ts +116 -0
- package/src/lib/search/recent-searches.ts +93 -0
- package/src/lib/search/result-export.test.ts +101 -0
- package/src/lib/search/result-export.ts +104 -0
- package/src/lib/search/saved-filters.test.ts +118 -0
- package/src/lib/search/saved-filters.ts +154 -0
- package/src/lib/search/tier0-scan.test.ts +196 -0
- package/src/lib/search/tier0-scan.ts +237 -0
- package/src/lib/search/tier1-index.test.ts +242 -0
- package/src/lib/search/tier1-index.ts +448 -0
- package/src/main.tsx +1 -10
- package/src/sdk/adapters/export-adapter.test.ts +434 -1
- package/src/sdk/adapters/export-adapter.ts +404 -1
- package/src/sdk/adapters/export-schedule-splice.test.ts +127 -0
- package/src/sdk/adapters/export-schedule-splice.ts +87 -0
- package/src/sdk/adapters/model-compat.ts +8 -2
- package/src/sdk/adapters/schedule-adapter.ts +73 -0
- package/src/sdk/adapters/store-adapter.ts +201 -0
- package/src/sdk/adapters/visibility-adapter.ts +3 -0
- package/src/sdk/local-backend.ts +16 -8
- package/src/services/api-keys.ts +73 -0
- package/src/services/desktop-export.ts +3 -1
- package/src/services/desktop-native-metadata.ts +41 -18
- package/src/services/file-dialog.ts +4 -1
- package/src/services/tauri-modules.d.ts +25 -0
- package/src/store/basketVisibleSet.ts +3 -0
- package/src/store/constants.ts +20 -2
- package/src/store/globalId.ts +4 -1
- package/src/store/index.ts +82 -6
- package/src/store/slices/addElementMeshes.ts +365 -0
- package/src/store/slices/addElementSlice.ts +275 -0
- package/src/store/slices/annotationsSlice.test.ts +133 -0
- package/src/store/slices/annotationsSlice.ts +251 -0
- package/src/store/slices/cesiumSlice.ts +5 -0
- package/src/store/slices/chatSlice.test.ts +6 -76
- package/src/store/slices/chatSlice.ts +17 -58
- package/src/store/slices/dataSlice.test.ts +23 -4
- package/src/store/slices/dataSlice.ts +1 -1
- package/src/store/slices/modelSlice.test.ts +67 -9
- package/src/store/slices/modelSlice.ts +39 -7
- package/src/store/slices/mutationSlice.ts +964 -3
- package/src/store/slices/overlayCompositor.test.ts +164 -0
- package/src/store/slices/overlaySlice.test.ts +93 -0
- package/src/store/slices/overlaySlice.ts +151 -0
- package/src/store/slices/pinboardSlice.test.ts +6 -1
- package/src/store/slices/playbackSlice.ts +128 -0
- package/src/store/slices/schedule-edit-helpers.test.ts +97 -0
- package/src/store/slices/schedule-edit-helpers.ts +179 -0
- package/src/store/slices/scheduleSlice.test.ts +694 -0
- package/src/store/slices/scheduleSlice.ts +1330 -0
- package/src/store/slices/searchSlice.test.ts +342 -0
- package/src/store/slices/searchSlice.ts +341 -0
- package/src/store/slices/sectionSlice.test.ts +87 -7
- package/src/store/slices/sectionSlice.ts +151 -5
- package/src/store/slices/selectionSlice.test.ts +46 -0
- package/src/store/slices/selectionSlice.ts +20 -0
- package/src/store/slices/uiSlice.ts +28 -5
- package/src/store/types.ts +26 -0
- package/src/store.ts +14 -0
- package/src/utils/nativeSpatialDataStore.ts +4 -1
- package/src/utils/viewportUtils.ts +7 -2
- package/src/vite-env.d.ts +0 -4
- package/dist/assets/drawing-2d-gWfpdfYe.js +0 -257
- package/dist/assets/ids-B4jTqB1O.js +0 -1
- package/dist/assets/ifc-lite_bg-BX4E7TX8.wasm +0 -0
- package/dist/assets/index-DckuDqlv.css +0 -1
- package/dist/assets/sandbox-DZiNLNMk.js +0 -5933
- package/src/components/viewer/UpgradePage.tsx +0 -71
- package/src/lib/desktop/ClerkDesktopEntitlementSync.tsx +0 -175
- package/src/lib/llm/ClerkChatSync.tsx +0 -74
- package/src/lib/llm/clerk-auth.ts +0 -62
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
|
+
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
|
+
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* useSearchIndex — lazy builder for the Tier-1 search index.
|
|
7
|
+
*
|
|
8
|
+
* Mount once near the root of the viewer shell (currently `SearchInline`,
|
|
9
|
+
* since it's always rendered once the toolbar is up). The hook watches
|
|
10
|
+
* the federated `models` map; for each model with a populated
|
|
11
|
+
* `ifcDataStore` that doesn't yet have a Tier-1 record, it spawns a
|
|
12
|
+
* chunked build. Models that disappear get their index record dropped.
|
|
13
|
+
*
|
|
14
|
+
* Load-perf guarantee: the build NEVER runs during the actual IFC load
|
|
15
|
+
* because `ifcDataStore` is non-null only after the parser reports the
|
|
16
|
+
* model is ready (`onSpatialReady` + geometry). The build itself yields
|
|
17
|
+
* to the event loop every `DEFAULT_CHUNK_SIZE` rows so a 4M-entity
|
|
18
|
+
* index doesn't hog the main thread.
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
import { useEffect, useRef } from 'react';
|
|
22
|
+
import { useShallow } from 'zustand/react/shallow';
|
|
23
|
+
import { useViewerStore } from '@/store';
|
|
24
|
+
import { buildTier1Index } from '@/lib/search/tier1-index';
|
|
25
|
+
|
|
26
|
+
export function useSearchIndex(): void {
|
|
27
|
+
const {
|
|
28
|
+
models,
|
|
29
|
+
searchIndexes,
|
|
30
|
+
setSearchIndexRecord,
|
|
31
|
+
removeSearchIndexRecord,
|
|
32
|
+
searchFilterSchema,
|
|
33
|
+
removeFilterSchema,
|
|
34
|
+
} = useViewerStore(
|
|
35
|
+
useShallow((s) => ({
|
|
36
|
+
models: s.models,
|
|
37
|
+
searchIndexes: s.searchIndexes,
|
|
38
|
+
setSearchIndexRecord: s.setSearchIndexRecord,
|
|
39
|
+
removeSearchIndexRecord: s.removeSearchIndexRecord,
|
|
40
|
+
searchFilterSchema: s.searchFilterSchema,
|
|
41
|
+
removeFilterSchema: s.removeFilterSchema,
|
|
42
|
+
})),
|
|
43
|
+
);
|
|
44
|
+
|
|
45
|
+
// One AbortController per in-flight build. Lets us cancel cleanly when a
|
|
46
|
+
// model is removed mid-build or when the component unmounts.
|
|
47
|
+
const controllersRef = useRef<Map<string, AbortController>>(new Map());
|
|
48
|
+
|
|
49
|
+
useEffect(() => {
|
|
50
|
+
const controllers = controllersRef.current;
|
|
51
|
+
|
|
52
|
+
// Drop records / abort builds for models that no longer exist.
|
|
53
|
+
for (const modelId of Array.from(searchIndexes.keys())) {
|
|
54
|
+
if (!models.has(modelId)) {
|
|
55
|
+
controllers.get(modelId)?.abort();
|
|
56
|
+
controllers.delete(modelId);
|
|
57
|
+
removeSearchIndexRecord(modelId);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Drop the filter-schema cache for departed models too. Stale entries
|
|
62
|
+
// would surface in the chip dropdowns the next time a model with the
|
|
63
|
+
// same id loaded (e.g. user reopens a different file as model_0).
|
|
64
|
+
for (const modelId of Array.from(searchFilterSchema.keys())) {
|
|
65
|
+
if (!models.has(modelId)) removeFilterSchema(modelId);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// Kick off builds for models that are loaded but not yet indexed.
|
|
69
|
+
for (const [modelId, model] of models) {
|
|
70
|
+
if (!model.ifcDataStore) continue;
|
|
71
|
+
const existing = searchIndexes.get(modelId);
|
|
72
|
+
if (existing && existing.status !== 'pending') continue;
|
|
73
|
+
if (controllers.has(modelId)) continue;
|
|
74
|
+
|
|
75
|
+
const controller = new AbortController();
|
|
76
|
+
controllers.set(modelId, controller);
|
|
77
|
+
|
|
78
|
+
setSearchIndexRecord(modelId, { status: 'building', progress: 0 });
|
|
79
|
+
|
|
80
|
+
// Fire-and-forget — the build is cancellable via the controller, and
|
|
81
|
+
// the completion handlers update the store without needing a ref.
|
|
82
|
+
void buildTier1Index(modelId, model.ifcDataStore, {
|
|
83
|
+
signal: controller.signal,
|
|
84
|
+
onProgress: (done, total) => {
|
|
85
|
+
if (controller.signal.aborted) return;
|
|
86
|
+
const progress = total > 0 ? done / total : 1;
|
|
87
|
+
setSearchIndexRecord(modelId, { status: 'building', progress });
|
|
88
|
+
},
|
|
89
|
+
})
|
|
90
|
+
.then((index) => {
|
|
91
|
+
if (controller.signal.aborted) return;
|
|
92
|
+
controllers.delete(modelId);
|
|
93
|
+
setSearchIndexRecord(modelId, { status: 'ready', index, progress: 1 });
|
|
94
|
+
})
|
|
95
|
+
.catch((err: unknown) => {
|
|
96
|
+
controllers.delete(modelId);
|
|
97
|
+
if (err instanceof DOMException && err.name === 'AbortError') return;
|
|
98
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
99
|
+
// Don't set a 'ready' record — Tier-0 fallback stays live.
|
|
100
|
+
console.warn(`[useSearchIndex] build failed for ${modelId}:`, message);
|
|
101
|
+
setSearchIndexRecord(modelId, { status: 'error', error: message });
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// On unmount OR next effect pass, abort everything. The effect re-runs
|
|
106
|
+
// only when `models` / `searchIndexes` changes, so steady-state
|
|
107
|
+
// incurs no abort — the `controllers.has(modelId)` guard above makes
|
|
108
|
+
// re-entry idempotent.
|
|
109
|
+
return () => {
|
|
110
|
+
// Intentionally NOT aborting everything on every re-render — only
|
|
111
|
+
// models that went missing got aborted above. The real cleanup is
|
|
112
|
+
// the component-unmount pass below.
|
|
113
|
+
};
|
|
114
|
+
}, [models, searchIndexes, setSearchIndexRecord, removeSearchIndexRecord, searchFilterSchema, removeFilterSchema]);
|
|
115
|
+
|
|
116
|
+
// Abort any in-flight builds when the consumer unmounts. Separate effect
|
|
117
|
+
// so it only fires on unmount (no deps).
|
|
118
|
+
useEffect(() => {
|
|
119
|
+
const controllers = controllersRef.current;
|
|
120
|
+
return () => {
|
|
121
|
+
for (const c of controllers.values()) c.abort();
|
|
122
|
+
controllers.clear();
|
|
123
|
+
};
|
|
124
|
+
}, []);
|
|
125
|
+
}
|
|
@@ -43,6 +43,7 @@ function useViewControls({
|
|
|
43
43
|
const [viewTransform, setViewTransform] = useState({ x: 0, y: 0, scale: 1 });
|
|
44
44
|
const [needsFit, setNeedsFit] = useState(true); // Force fit on first open and axis change
|
|
45
45
|
const prevAxisRef = useRef(sectionPlane.axis); // Track axis changes
|
|
46
|
+
const prevFlippedRef = useRef(sectionPlane.flipped); // Track flip changes
|
|
46
47
|
|
|
47
48
|
// Wheel zoom handler
|
|
48
49
|
useEffect(() => {
|
|
@@ -158,14 +159,21 @@ function useViewControls({
|
|
|
158
159
|
// Track axis changes for forced fit-to-view
|
|
159
160
|
const lastFitAxisRef = useRef(sectionPlane.axis);
|
|
160
161
|
|
|
161
|
-
// Set needsFit when axis changes
|
|
162
|
+
// Set needsFit when axis OR flip changes. Flip mirrors the projection's U
|
|
163
|
+
// axis (see `projectTo2D` in @ifc-lite/drawing-2d), so the polygon bounds
|
|
164
|
+
// jump from positive X into negative X (or vice versa). Without re-fitting
|
|
165
|
+
// the new bounds end up off-screen and the user sees "empty 2D panel after
|
|
166
|
+
// I pressed Flip" — that was the bug behind the recent screenshot report.
|
|
162
167
|
useEffect(() => {
|
|
163
|
-
|
|
168
|
+
const axisChanged = sectionPlane.axis !== prevAxisRef.current;
|
|
169
|
+
const flipChanged = sectionPlane.flipped !== prevFlippedRef.current;
|
|
170
|
+
if (axisChanged || flipChanged) {
|
|
164
171
|
prevAxisRef.current = sectionPlane.axis;
|
|
165
|
-
|
|
166
|
-
|
|
172
|
+
prevFlippedRef.current = sectionPlane.flipped;
|
|
173
|
+
setNeedsFit(true);
|
|
174
|
+
cachedSheetTransformRef.current = null;
|
|
167
175
|
}
|
|
168
|
-
}, [sectionPlane.axis]);
|
|
176
|
+
}, [sectionPlane.axis, sectionPlane.flipped]);
|
|
169
177
|
|
|
170
178
|
// Track previous sheet mode to detect toggle
|
|
171
179
|
const prevSheetEnabledRef = useRef(sheetEnabled);
|