@ifc-lite/viewer 1.14.2 → 1.14.3
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/CHANGELOG.md +24 -0
- package/dist/assets/{Arrow.dom-CSgnLhN4.js → Arrow.dom-BgkZDIQm.js} +1 -1
- package/dist/assets/basketViewActivator-h_M3YbMW.js +1 -0
- package/dist/assets/{browser-qSKWrKQW.js → browser-CRQ0bPh1.js} +1 -1
- package/dist/assets/ifc-lite_bg-DyBKoGgk.wasm +0 -0
- package/dist/assets/{index-4Y4XaV8N.js → index-Be6XjVeM.js} +72324 -61561
- package/dist/assets/index-C4VVJRL-.js +229 -0
- package/dist/assets/index-DdwD4c-E.css +1 -0
- package/dist/assets/{native-bridge-CSFDsEkg.js → native-bridge-DtcJqlOi.js} +1 -1
- package/dist/assets/{wasm-bridge-Zf90ysEm.js → wasm-bridge-BJJVu9P2.js} +1 -1
- package/dist/index.html +2 -2
- package/package.json +21 -20
- package/src/App.tsx +17 -1
- package/src/components/viewer/BasketPresentationDock.tsx +8 -4
- package/src/components/viewer/ChatPanel.tsx +1402 -0
- package/src/components/viewer/CodeEditor.tsx +70 -4
- package/src/components/viewer/MainToolbar.tsx +1 -1
- package/src/components/viewer/ScriptPanel.tsx +351 -184
- package/src/components/viewer/UpgradePage.tsx +69 -0
- package/src/components/viewer/Viewport.tsx +23 -0
- package/src/components/viewer/chat/ChatMessage.tsx +144 -0
- package/src/components/viewer/chat/ExecutableCodeBlock.tsx +416 -0
- package/src/components/viewer/chat/ModelSelector.tsx +102 -0
- package/src/components/viewer/chat/renderTextContent.test.ts +23 -0
- package/src/components/viewer/chat/renderTextContent.ts +19 -0
- package/src/hooks/useIfcCache.ts +1 -2
- package/src/hooks/useSandbox.ts +122 -6
- package/src/index.css +10 -0
- package/src/lib/attachments.ts +46 -0
- package/src/lib/llm/ClerkChatSync.tsx +74 -0
- package/src/lib/llm/clerk-auth.ts +62 -0
- package/src/lib/llm/code-extractor.ts +50 -0
- package/src/lib/llm/context-builder.test.ts +18 -0
- package/src/lib/llm/context-builder.ts +305 -0
- package/src/lib/llm/free-models.test.ts +118 -0
- package/src/lib/llm/message-capabilities.test.ts +131 -0
- package/src/lib/llm/message-capabilities.ts +94 -0
- package/src/lib/llm/models.ts +197 -0
- package/src/lib/llm/repair-loop.test.ts +91 -0
- package/src/lib/llm/repair-loop.ts +76 -0
- package/src/lib/llm/script-diagnostics.ts +445 -0
- package/src/lib/llm/script-edit-ops.test.ts +399 -0
- package/src/lib/llm/script-edit-ops.ts +954 -0
- package/src/lib/llm/script-preflight.test.ts +513 -0
- package/src/lib/llm/script-preflight.ts +990 -0
- package/src/lib/llm/script-preservation.test.ts +128 -0
- package/src/lib/llm/script-preservation.ts +152 -0
- package/src/lib/llm/stream-client.test.ts +97 -0
- package/src/lib/llm/stream-client.ts +410 -0
- package/src/lib/llm/system-prompt.test.ts +181 -0
- package/src/lib/llm/system-prompt.ts +665 -0
- package/src/lib/llm/types.ts +150 -0
- package/src/lib/scripts/templates/bim-globals.d.ts +226 -7
- package/src/lib/scripts/templates/create-building.ts +12 -12
- package/src/main.tsx +10 -1
- package/src/sdk/adapters/export-adapter.test.ts +24 -0
- package/src/sdk/adapters/export-adapter.ts +40 -16
- package/src/sdk/adapters/files-adapter.ts +39 -0
- package/src/sdk/adapters/model-compat.ts +1 -1
- package/src/sdk/adapters/mutate-adapter.ts +20 -6
- package/src/sdk/adapters/mutation-view.ts +112 -0
- package/src/sdk/adapters/query-adapter.ts +100 -4
- package/src/sdk/local-backend.ts +4 -0
- package/src/store/index.ts +15 -1
- package/src/store/slices/chatSlice.test.ts +325 -0
- package/src/store/slices/chatSlice.ts +468 -0
- package/src/store/slices/scriptSlice.test.ts +75 -0
- package/src/store/slices/scriptSlice.ts +256 -9
- package/src/vite-env.d.ts +10 -0
- package/vite.config.ts +21 -2
- package/dist/assets/ifc-lite_bg-BOvNXJA_.wasm +0 -0
- package/dist/assets/index-ByrFvN5A.css +0 -1
- package/dist/assets/index-CN7qDq7G.js +0 -216
|
@@ -12,13 +12,14 @@
|
|
|
12
12
|
|
|
13
13
|
import { useRef, useEffect } from 'react';
|
|
14
14
|
import { EditorView, keymap, lineNumbers, highlightActiveLine, highlightActiveLineGutter, drawSelection } from '@codemirror/view';
|
|
15
|
-
import { EditorState, Compartment } from '@codemirror/state';
|
|
15
|
+
import { EditorState, Compartment, Transaction } from '@codemirror/state';
|
|
16
16
|
import { javascript } from '@codemirror/lang-javascript';
|
|
17
17
|
import { autocompletion, type CompletionContext, type CompletionResult, type Completion } from '@codemirror/autocomplete';
|
|
18
|
-
import { defaultKeymap, history, historyKeymap, indentWithTab } from '@codemirror/commands';
|
|
18
|
+
import { defaultKeymap, history, historyKeymap, indentWithTab, undo, redo, undoDepth, redoDepth } from '@codemirror/commands';
|
|
19
19
|
import { syntaxHighlighting, defaultHighlightStyle, bracketMatching, indentOnInput } from '@codemirror/language';
|
|
20
20
|
import { highlightSelectionMatches } from '@codemirror/search';
|
|
21
21
|
import { NAMESPACE_SCHEMAS } from '@ifc-lite/sandbox/schema';
|
|
22
|
+
import type { ScriptEditorSelection, ScriptEditorTextChange } from '@/lib/llm/types';
|
|
22
23
|
|
|
23
24
|
/** Shared structural styles (mode-agnostic) */
|
|
24
25
|
const baseTheme = EditorView.theme({
|
|
@@ -201,20 +202,44 @@ function bimCompletions(context: CompletionContext): CompletionResult | null {
|
|
|
201
202
|
interface CodeEditorProps {
|
|
202
203
|
value: string;
|
|
203
204
|
onChange: (value: string) => void;
|
|
205
|
+
onSelectionChange?: (selection: ScriptEditorSelection) => void;
|
|
206
|
+
onHistoryChange?: (canUndo: boolean, canRedo: boolean) => void;
|
|
207
|
+
registerApplyAdapter?: ((adapter: {
|
|
208
|
+
apply: (
|
|
209
|
+
nextContent: string,
|
|
210
|
+
selection: ScriptEditorSelection,
|
|
211
|
+
options?: { userEvent?: string; changes?: ScriptEditorTextChange[] },
|
|
212
|
+
) => void;
|
|
213
|
+
undo: () => void;
|
|
214
|
+
redo: () => void;
|
|
215
|
+
} | null) => void);
|
|
204
216
|
onRun?: () => void;
|
|
205
217
|
onSave?: () => void;
|
|
206
218
|
className?: string;
|
|
207
219
|
}
|
|
208
220
|
|
|
209
|
-
export function CodeEditor({
|
|
221
|
+
export function CodeEditor({
|
|
222
|
+
value,
|
|
223
|
+
onChange,
|
|
224
|
+
onSelectionChange,
|
|
225
|
+
onHistoryChange,
|
|
226
|
+
registerApplyAdapter,
|
|
227
|
+
onRun,
|
|
228
|
+
onSave,
|
|
229
|
+
className,
|
|
230
|
+
}: CodeEditorProps) {
|
|
210
231
|
const containerRef = useRef<HTMLDivElement>(null);
|
|
211
232
|
const viewRef = useRef<EditorView | null>(null);
|
|
212
233
|
const onChangeRef = useRef(onChange);
|
|
234
|
+
const onSelectionChangeRef = useRef(onSelectionChange);
|
|
235
|
+
const onHistoryChangeRef = useRef(onHistoryChange);
|
|
213
236
|
const onRunRef = useRef(onRun);
|
|
214
237
|
const onSaveRef = useRef(onSave);
|
|
215
238
|
|
|
216
239
|
// Keep callback refs up to date without recreating the editor
|
|
217
240
|
onChangeRef.current = onChange;
|
|
241
|
+
onSelectionChangeRef.current = onSelectionChange;
|
|
242
|
+
onHistoryChangeRef.current = onHistoryChange;
|
|
218
243
|
onRunRef.current = onRun;
|
|
219
244
|
onSaveRef.current = onSave;
|
|
220
245
|
|
|
@@ -239,6 +264,16 @@ export function CodeEditor({ value, onChange, onRun, onSave, className }: CodeEd
|
|
|
239
264
|
if (update.docChanged) {
|
|
240
265
|
onChangeRef.current(update.state.doc.toString());
|
|
241
266
|
}
|
|
267
|
+
if (update.selectionSet || update.docChanged) {
|
|
268
|
+
const main = update.state.selection.main;
|
|
269
|
+
onSelectionChangeRef.current?.({ from: main.from, to: main.to });
|
|
270
|
+
}
|
|
271
|
+
if (update.docChanged) {
|
|
272
|
+
onHistoryChangeRef.current?.(
|
|
273
|
+
undoDepth(update.state) > 0,
|
|
274
|
+
redoDepth(update.state) > 0,
|
|
275
|
+
);
|
|
276
|
+
}
|
|
242
277
|
});
|
|
243
278
|
|
|
244
279
|
const state = EditorState.create({
|
|
@@ -274,6 +309,35 @@ export function CodeEditor({ value, onChange, onRun, onSave, className }: CodeEd
|
|
|
274
309
|
});
|
|
275
310
|
|
|
276
311
|
viewRef.current = view;
|
|
312
|
+
const initialSelection = view.state.selection.main;
|
|
313
|
+
onSelectionChangeRef.current?.({ from: initialSelection.from, to: initialSelection.to });
|
|
314
|
+
onHistoryChangeRef.current?.(undoDepth(view.state) > 0, redoDepth(view.state) > 0);
|
|
315
|
+
registerApplyAdapter?.({
|
|
316
|
+
apply: (nextContent, selection, options) => {
|
|
317
|
+
const active = viewRef.current;
|
|
318
|
+
if (!active) return;
|
|
319
|
+
const safeFrom = Math.max(0, Math.min(selection.from, nextContent.length));
|
|
320
|
+
const safeTo = Math.max(safeFrom, Math.min(selection.to, nextContent.length));
|
|
321
|
+
const changes = options?.changes && options.changes.length > 0
|
|
322
|
+
? options.changes
|
|
323
|
+
: [{ from: 0, to: active.state.doc.length, insert: nextContent }];
|
|
324
|
+
active.dispatch({
|
|
325
|
+
changes,
|
|
326
|
+
selection: { anchor: safeFrom, head: safeTo },
|
|
327
|
+
annotations: options?.userEvent ? [Transaction.userEvent.of(options.userEvent)] : undefined,
|
|
328
|
+
});
|
|
329
|
+
},
|
|
330
|
+
undo: () => {
|
|
331
|
+
const active = viewRef.current;
|
|
332
|
+
if (!active) return;
|
|
333
|
+
undo(active);
|
|
334
|
+
},
|
|
335
|
+
redo: () => {
|
|
336
|
+
const active = viewRef.current;
|
|
337
|
+
if (!active) return;
|
|
338
|
+
redo(active);
|
|
339
|
+
},
|
|
340
|
+
});
|
|
277
341
|
|
|
278
342
|
// Watch for light/dark mode changes on <html> class
|
|
279
343
|
const observer = new MutationObserver(() => {
|
|
@@ -282,13 +346,15 @@ export function CodeEditor({ value, onChange, onRun, onSave, className }: CodeEd
|
|
|
282
346
|
observer.observe(document.documentElement, { attributes: true, attributeFilter: ['class'] });
|
|
283
347
|
|
|
284
348
|
return () => {
|
|
349
|
+
onHistoryChangeRef.current?.(false, false);
|
|
350
|
+
registerApplyAdapter?.(null);
|
|
285
351
|
observer.disconnect();
|
|
286
352
|
view.destroy();
|
|
287
353
|
viewRef.current = null;
|
|
288
354
|
};
|
|
289
355
|
// Only create once — value is set via initial doc
|
|
290
356
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
291
|
-
}, []);
|
|
357
|
+
}, [registerApplyAdapter]);
|
|
292
358
|
|
|
293
359
|
// Sync external value changes into the editor (e.g., loading a different script)
|
|
294
360
|
const lastExternalValue = useRef(value);
|
|
@@ -680,7 +680,7 @@ export function MainToolbar({ onShowShortcuts }: MainToolbarProps = {} as MainTo
|
|
|
680
680
|
size="icon-sm"
|
|
681
681
|
onClick={(e) => {
|
|
682
682
|
(e.currentTarget as HTMLButtonElement).blur();
|
|
683
|
-
// Close
|
|
683
|
+
// Close other bottom panels (bottom-panel exclusivity)
|
|
684
684
|
useViewerStore.getState().setScriptPanelVisible(false);
|
|
685
685
|
if (!listPanelVisible) {
|
|
686
686
|
setRightPanelCollapsed(false);
|