brep-io-kernel 1.0.17 → 1.0.19

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 (32) hide show
  1. package/dist-kernel/brep-kernel.js +13547 -12034
  2. package/package.json +1 -1
  3. package/src/FeatureRegistry.js +3 -0
  4. package/src/PartHistory.js +141 -0
  5. package/src/UI/CADmaterials.js +2 -2
  6. package/src/UI/MainToolbar.js +39 -2
  7. package/src/UI/SelectionFilter.js +438 -0
  8. package/src/UI/featureDialogWidgets/booleanOperationField.js +33 -52
  9. package/src/UI/featureDialogWidgets/referenceSelectionField.js +10 -0
  10. package/src/UI/featureDialogs.js +841 -8
  11. package/src/UI/history/HistoryCollectionWidget.js +20 -1
  12. package/src/UI/pmi/AnnotationRegistry.js +3 -0
  13. package/src/UI/toolbarButtons/orientToFaceButton.js +3 -0
  14. package/src/UI/toolbarButtons/registerDefaultButtons.js +0 -6
  15. package/src/UI/toolbarButtons/registerSelectionButtons.js +68 -0
  16. package/src/UI/viewer.js +22 -4
  17. package/src/assemblyConstraints/AssemblyConstraintRegistry.js +3 -0
  18. package/src/features/boolean/BooleanFeature.js +15 -0
  19. package/src/features/chamfer/ChamferFeature.js +12 -0
  20. package/src/features/extrude/ExtrudeFeature.js +11 -0
  21. package/src/features/fillet/FilletFeature.js +12 -0
  22. package/src/features/hole/HoleFeature.js +15 -0
  23. package/src/features/loft/LoftFeature.js +17 -0
  24. package/src/features/mirror/MirrorFeature.js +14 -0
  25. package/src/features/patternLinear/PatternLinearFeature.js +9 -0
  26. package/src/features/patternRadial/PatternRadialFeature.js +13 -0
  27. package/src/features/plane/PlaneFeature.js +10 -0
  28. package/src/features/revolve/RevolveFeature.js +15 -0
  29. package/src/features/sketch/SketchFeature.js +11 -0
  30. package/src/features/sweep/SweepFeature.js +17 -0
  31. package/src/features/transform/TransformFeature.js +12 -0
  32. package/src/features/tube/TubeFeature.js +12 -0
@@ -2,11 +2,17 @@
2
2
 
3
3
  import { SelectionFilter } from './SelectionFilter.js';
4
4
  import * as THREE from 'three';
5
+ import { Line2, LineGeometry, LineMaterial } from 'three/examples/jsm/Addons.js';
5
6
  // Use hybrid translate+rotate gizmo used by the Viewer
6
7
  import { CombinedTransformControls } from './controls/CombinedTransformControls.js';
7
8
  import { getWidgetRenderer } from './featureDialogWidgets/index.js';
8
9
  import { normalizeReferenceList, normalizeReferenceName } from './featureDialogWidgets/utils.js';
9
-
10
+ const REF_PREVIEW_COLORS = {
11
+ EDGE: '#ff00ff',
12
+ FACE: '#ffc400',
13
+ PLANE: '#2eff2e',
14
+ VERTEX: '#00ffff',
15
+ };
10
16
 
11
17
 
12
18
 
@@ -29,6 +35,7 @@ export class SchemaForm {
29
35
  if (prev && prev !== el) {
30
36
  try { prev.style.filter = 'none'; } catch (_) { }
31
37
  try { prev.removeAttribute('active-reference-selection'); } catch (_) { }
38
+ try { if (typeof prev.__refPreviewCleanup === 'function') prev.__refPreviewCleanup(); } catch (_) { }
32
39
  }
33
40
  } catch (_) { }
34
41
  SchemaForm.__activeRefInput = el || null;
@@ -198,6 +205,7 @@ export class SchemaForm {
198
205
  // If target is inside the same active element (e.g., clicking within the input), skip
199
206
  if (target && typeof target.closest === 'function') {
200
207
  if (target.closest('[active-reference-selection]')) return;
208
+ if (target.closest('.ref-active')) return;
201
209
  }
202
210
  this._stopActiveReferenceSelection();
203
211
  } catch (_) { }
@@ -494,6 +502,626 @@ export class SchemaForm {
494
502
  || null;
495
503
  }
496
504
 
505
+ _getReferencePreviewCacheRoot() {
506
+ const holder = this.options?.featureRef || this;
507
+ if (!holder) return null;
508
+ if (!holder.__refPreviewCache) {
509
+ try {
510
+ Object.defineProperty(holder, '__refPreviewCache', {
511
+ value: new Map(),
512
+ configurable: true,
513
+ enumerable: false,
514
+ writable: true,
515
+ });
516
+ } catch (_) {
517
+ holder.__refPreviewCache = new Map();
518
+ }
519
+ }
520
+ return holder.__refPreviewCache;
521
+ }
522
+
523
+ _getReferencePreviewCache(inputEl) {
524
+ const root = this._getReferencePreviewCacheRoot();
525
+ if (!root) return null;
526
+ const key = (inputEl?.dataset?.key || inputEl?.dataset?.refKey || inputEl?.__refPreviewKey || '__default');
527
+ let bucket = root.get(key);
528
+ if (!bucket) {
529
+ bucket = new Map();
530
+ root.set(key, bucket);
531
+ }
532
+ return bucket;
533
+ }
534
+
535
+ _getReferencePreviewPersistentBucket(inputEl) {
536
+ const entry = this.options?.featureRef || null;
537
+ if (!entry) return null;
538
+ if (!entry.persistentData || typeof entry.persistentData !== 'object') {
539
+ entry.persistentData = {};
540
+ }
541
+ if (!entry.persistentData.__refPreviewSnapshots || typeof entry.persistentData.__refPreviewSnapshots !== 'object') {
542
+ entry.persistentData.__refPreviewSnapshots = {};
543
+ }
544
+ const key = (inputEl?.dataset?.key || inputEl?.dataset?.refKey || inputEl?.__refPreviewKey || '__default');
545
+ if (!entry.persistentData.__refPreviewSnapshots[key] || typeof entry.persistentData.__refPreviewSnapshots[key] !== 'object') {
546
+ entry.persistentData.__refPreviewSnapshots[key] = {};
547
+ }
548
+ return entry.persistentData.__refPreviewSnapshots[key];
549
+ }
550
+
551
+ _resolveReferencePreviewName(obj) {
552
+ if (!obj) return null;
553
+ const raw = obj.name != null ? String(obj.name).trim() : '';
554
+ if (raw) return raw;
555
+ const type = obj.type || 'OBJECT';
556
+ const pos = obj.position || {};
557
+ const x = Number.isFinite(pos.x) ? pos.x : 0;
558
+ const y = Number.isFinite(pos.y) ? pos.y : 0;
559
+ const z = Number.isFinite(pos.z) ? pos.z : 0;
560
+ return `${type}(${x},${y},${z})`;
561
+ }
562
+
563
+ _extractEdgeWorldPositions(obj) {
564
+ if (!obj) return [];
565
+ try {
566
+ if (typeof obj.points === 'function') {
567
+ const pts = obj.points(true);
568
+ if (Array.isArray(pts) && pts.length) {
569
+ const flat = [];
570
+ for (const p of pts) {
571
+ if (!p) continue;
572
+ const x = Number(p.x);
573
+ const y = Number(p.y);
574
+ const z = Number(p.z);
575
+ if (!Number.isFinite(x) || !Number.isFinite(y) || !Number.isFinite(z)) continue;
576
+ flat.push(x, y, z);
577
+ }
578
+ if (flat.length >= 6) return flat;
579
+ }
580
+ }
581
+ } catch (_) { /* ignore */ }
582
+
583
+ try {
584
+ const geom = obj.geometry;
585
+ const pos = geom && typeof geom.getAttribute === 'function' ? geom.getAttribute('position') : null;
586
+ if (!pos || pos.itemSize !== 3 || pos.count < 2) return [];
587
+ const tmp = new THREE.Vector3();
588
+ const flat = [];
589
+ for (let i = 0; i < pos.count; i++) {
590
+ tmp.set(pos.getX(i), pos.getY(i), pos.getZ(i));
591
+ tmp.applyMatrix4(obj.matrixWorld);
592
+ flat.push(tmp.x, tmp.y, tmp.z);
593
+ }
594
+ return flat.length >= 6 ? flat : [];
595
+ } catch (_) { /* ignore */ }
596
+ return [];
597
+ }
598
+
599
+ _syncPreviewLineResolution(mat) {
600
+ if (!mat || !mat.resolution || typeof mat.resolution.set !== 'function') return;
601
+ let width = 0;
602
+ let height = 0;
603
+ try {
604
+ const viewer = this.options?.viewer || null;
605
+ const el = viewer?.renderer?.domElement || null;
606
+ if (el && typeof el.getBoundingClientRect === 'function') {
607
+ const rect = el.getBoundingClientRect();
608
+ width = rect.width || rect.right - rect.left;
609
+ height = rect.height || rect.bottom - rect.top;
610
+ }
611
+ if ((!width || !height) && viewer?.container) {
612
+ width = viewer.container.clientWidth || width;
613
+ height = viewer.container.clientHeight || height;
614
+ }
615
+ } catch (_) { /* ignore */ }
616
+ if (!width || !height) {
617
+ try {
618
+ if (typeof window !== 'undefined') {
619
+ width = window.innerWidth || width;
620
+ height = window.innerHeight || height;
621
+ }
622
+ } catch (_) { /* ignore */ }
623
+ }
624
+ if (Number.isFinite(width) && Number.isFinite(height) && width > 0 && height > 0) {
625
+ try { mat.resolution.set(width, height); } catch (_) { }
626
+ }
627
+ }
628
+
629
+ _createPreviewLineMaterial(sourceMat, colorHex = REF_PREVIEW_COLORS.EDGE) {
630
+ let mat = null;
631
+ if (sourceMat && typeof sourceMat.clone === 'function') {
632
+ try { mat = sourceMat.clone(); } catch (_) { mat = null; }
633
+ }
634
+ if (!mat) {
635
+ try {
636
+ mat = new LineMaterial({ color: colorHex, linewidth: 3, transparent: true, opacity: 0.95, worldUnits: false, dashed: false });
637
+ } catch (_) { mat = null; }
638
+ }
639
+ if (mat && mat.color && typeof mat.color.set === 'function') {
640
+ try { mat.color.set(colorHex); } catch (_) { }
641
+ }
642
+ if (mat) {
643
+ try { mat.transparent = true; } catch (_) { }
644
+ try { mat.opacity = Number.isFinite(mat.opacity) ? Math.min(0.95, mat.opacity) : 0.95; } catch (_) { }
645
+ try { mat.depthTest = false; } catch (_) { }
646
+ try { mat.depthWrite = false; } catch (_) { }
647
+ try { if (typeof mat.dashed !== 'undefined') mat.dashed = false; } catch (_) { }
648
+ try { if (typeof mat.dashScale !== 'undefined') mat.dashScale = 1; } catch (_) { }
649
+ try { if (typeof mat.dashSize !== 'undefined') mat.dashSize = 1; } catch (_) { }
650
+ try { if (typeof mat.gapSize !== 'undefined') mat.gapSize = 0; } catch (_) { }
651
+ try { this._syncPreviewLineResolution(mat); } catch (_) { }
652
+ }
653
+ return mat;
654
+ }
655
+
656
+ _createPreviewMeshMaterial(sourceMat, colorHex = REF_PREVIEW_COLORS.FACE) {
657
+ let mat = null;
658
+ if (sourceMat && typeof sourceMat.clone === 'function') {
659
+ try { mat = sourceMat.clone(); } catch (_) { mat = null; }
660
+ }
661
+ if (!mat) {
662
+ try {
663
+ mat = new THREE.MeshStandardMaterial({
664
+ color: colorHex,
665
+ transparent: true,
666
+ opacity: 0.25,
667
+ depthWrite: false,
668
+ side: THREE.DoubleSide,
669
+ });
670
+ } catch (_) { mat = null; }
671
+ }
672
+ if (mat && mat.color && typeof mat.color.set === 'function') {
673
+ try { mat.color.set(colorHex); } catch (_) { }
674
+ }
675
+ if (mat) {
676
+ try { mat.transparent = true; } catch (_) { }
677
+ try { mat.opacity = 0.25; } catch (_) { }
678
+ try { mat.depthWrite = false; } catch (_) { }
679
+ try { mat.depthTest = true; } catch (_) { }
680
+ try { mat.side = THREE.DoubleSide; } catch (_) { }
681
+ try { mat.polygonOffset = true; mat.polygonOffsetFactor = -1; mat.polygonOffsetUnits = -1; } catch (_) { }
682
+ }
683
+ return mat;
684
+ }
685
+
686
+ _createPreviewPointMaterial(sourceMat, colorHex = REF_PREVIEW_COLORS.VERTEX) {
687
+ let mat = null;
688
+ if (sourceMat && typeof sourceMat.clone === 'function') {
689
+ try { mat = sourceMat.clone(); } catch (_) { mat = null; }
690
+ }
691
+ if (!mat || !mat.isPointsMaterial) {
692
+ try {
693
+ mat = new THREE.PointsMaterial({
694
+ color: colorHex,
695
+ size: 7,
696
+ sizeAttenuation: false,
697
+ transparent: true,
698
+ opacity: 0.9,
699
+ });
700
+ } catch (_) { mat = null; }
701
+ }
702
+ if (mat && mat.color && typeof mat.color.set === 'function') {
703
+ try { mat.color.set(colorHex); } catch (_) { }
704
+ }
705
+ if (mat) {
706
+ try { mat.transparent = true; } catch (_) { }
707
+ try { mat.opacity = 0.9; } catch (_) { }
708
+ }
709
+ return mat;
710
+ }
711
+
712
+ _configurePreviewObject(obj, refName, previewType) {
713
+ if (!obj) return obj;
714
+ try { obj.name = `__refPreview__${refName}`; } catch (_) { }
715
+ try {
716
+ obj.userData = obj.userData || {};
717
+ obj.userData.refPreview = true;
718
+ obj.userData.refName = refName;
719
+ obj.userData.previewType = previewType;
720
+ obj.userData.excludeFromFit = true;
721
+ } catch (_) { }
722
+ try { obj.renderOrder = Math.max(10050, obj.renderOrder || 0); } catch (_) { }
723
+ try { obj.raycast = () => { }; } catch (_) { }
724
+ try {
725
+ obj.traverse?.((child) => {
726
+ if (!child || child === obj) return;
727
+ try { child.raycast = () => { }; } catch (_) { }
728
+ try {
729
+ child.userData = child.userData || {};
730
+ child.userData.refPreview = true;
731
+ child.userData.refName = refName;
732
+ if (!child.userData.previewType && child.type) child.userData.previewType = child.type;
733
+ } catch (_) { }
734
+ });
735
+ } catch (_) { }
736
+ return obj;
737
+ }
738
+
739
+ _getOwningFeatureIdForObject(obj) {
740
+ let cur = obj;
741
+ let guard = 0;
742
+ while (cur && guard < 8) {
743
+ if (cur.owningFeatureID != null) return cur.owningFeatureID;
744
+ cur = cur.parent || null;
745
+ guard += 1;
746
+ }
747
+ return null;
748
+ }
749
+
750
+ _buildEdgePreviewFromObject(obj, refName, colorHex = REF_PREVIEW_COLORS.EDGE) {
751
+ if (!obj) return null;
752
+ const positions = this._extractEdgeWorldPositions(obj);
753
+ if (!positions || positions.length < 6) return null;
754
+ const geom = new LineGeometry();
755
+ geom.setPositions(positions);
756
+ try { geom.computeBoundingSphere(); } catch (_) { }
757
+ const mat = this._createPreviewLineMaterial(obj.material, colorHex);
758
+ const line = new Line2(geom, mat || undefined);
759
+ try { line.computeLineDistances?.(); } catch (_) { }
760
+ try { if (line.material && typeof line.material.dashed !== 'undefined') line.material.dashed = false; } catch (_) { }
761
+ line.type = 'REF_PREVIEW_EDGE';
762
+ return this._configurePreviewObject(line, refName, 'EDGE');
763
+ }
764
+
765
+ _extractFaceEdgePositions(face) {
766
+ if (!face) return [];
767
+ const out = [];
768
+ const addEdge = (edge) => {
769
+ const positions = this._extractEdgeWorldPositions(edge);
770
+ if (positions && positions.length >= 6) out.push(positions);
771
+ };
772
+
773
+ if (Array.isArray(face.edges) && face.edges.length) {
774
+ for (const edge of face.edges) addEdge(edge);
775
+ return out;
776
+ }
777
+
778
+ const faceName = face?.name || face?.userData?.faceName || null;
779
+ const parentSolid = face?.parentSolid || face?.userData?.parentSolid || face?.parent || null;
780
+ if (!faceName || !parentSolid || !Array.isArray(parentSolid.children)) return out;
781
+
782
+ for (const child of parentSolid.children) {
783
+ if (!child || child.type !== SelectionFilter.EDGE) continue;
784
+ const faceA = child?.userData?.faceA || null;
785
+ const faceB = child?.userData?.faceB || null;
786
+ if (faceA === faceName || faceB === faceName) {
787
+ addEdge(child);
788
+ }
789
+ }
790
+ return out;
791
+ }
792
+
793
+ _buildReferencePreviewObject(obj, refName) {
794
+ if (!obj) return null;
795
+ const type = String(obj.type || '').toUpperCase();
796
+ if (type === SelectionFilter.EDGE || type === 'EDGE') {
797
+ return this._buildEdgePreviewFromObject(obj, refName, REF_PREVIEW_COLORS.EDGE);
798
+ }
799
+ if (type === SelectionFilter.FACE || type === SelectionFilter.PLANE || type === 'FACE' || type === 'PLANE') {
800
+ const geom = obj.geometry && typeof obj.geometry.clone === 'function' ? obj.geometry.clone() : null;
801
+ if (!geom) return null;
802
+ try { geom.applyMatrix4(obj.matrixWorld); } catch (_) { }
803
+ const color = (type === SelectionFilter.PLANE || type === 'PLANE') ? REF_PREVIEW_COLORS.PLANE : REF_PREVIEW_COLORS.FACE;
804
+ const mat = this._createPreviewMeshMaterial(obj.material, color);
805
+ const mesh = new THREE.Mesh(geom, mat || undefined);
806
+ mesh.type = (type === SelectionFilter.PLANE || type === 'PLANE') ? 'REF_PREVIEW_PLANE' : 'REF_PREVIEW_FACE';
807
+ try { mesh.matrixAutoUpdate = false; } catch (_) { }
808
+ const edges = Array.isArray(obj.edges) ? obj.edges : [];
809
+ if (edges.length) {
810
+ const group = new THREE.Group();
811
+ group.type = mesh.type;
812
+ try { group.userData = group.userData || {}; } catch (_) { }
813
+ try { group.userData.previewHasEdges = true; } catch (_) { }
814
+ try { group.userData.previewHasFace = true; } catch (_) { }
815
+ group.add(mesh);
816
+ for (const edge of edges) {
817
+ const edgePreview = this._buildEdgePreviewFromObject(edge, refName, REF_PREVIEW_COLORS.EDGE);
818
+ if (edgePreview) group.add(edgePreview);
819
+ }
820
+ return this._configurePreviewObject(group, refName, mesh.type);
821
+ }
822
+ return this._configurePreviewObject(mesh, refName, mesh.type);
823
+ }
824
+ if (type === SelectionFilter.VERTEX || type === 'VERTEX') {
825
+ const pos = new THREE.Vector3();
826
+ try {
827
+ if (typeof obj.getWorldPosition === 'function') obj.getWorldPosition(pos);
828
+ else pos.set(obj.position?.x || 0, obj.position?.y || 0, obj.position?.z || 0);
829
+ } catch (_) { }
830
+ const geom = new THREE.BufferGeometry();
831
+ geom.setAttribute('position', new THREE.Float32BufferAttribute([0, 0, 0], 3));
832
+ const mat = this._createPreviewPointMaterial(obj.material, REF_PREVIEW_COLORS.VERTEX);
833
+ const pts = new THREE.Points(geom, mat || undefined);
834
+ pts.position.copy(pos);
835
+ pts.type = 'REF_PREVIEW_VERTEX';
836
+ return this._configurePreviewObject(pts, refName, 'VERTEX');
837
+ }
838
+ return null;
839
+ }
840
+
841
+ _buildReferencePreviewFromSnapshot(refName, snapshot) {
842
+ if (!snapshot || !refName) return null;
843
+ const type = String(snapshot.type || '').toUpperCase();
844
+ if (type === 'EDGE') {
845
+ const positions = Array.isArray(snapshot.positions) ? snapshot.positions : null;
846
+ if (!positions || positions.length < 6) return null;
847
+ const geom = new LineGeometry();
848
+ geom.setPositions(positions);
849
+ try { geom.computeBoundingSphere(); } catch (_) { }
850
+ const mat = this._createPreviewLineMaterial(null, REF_PREVIEW_COLORS.EDGE);
851
+ const line = new Line2(geom, mat || undefined);
852
+ try { line.computeLineDistances?.(); } catch (_) { }
853
+ try { if (line.material && typeof line.material.dashed !== 'undefined') line.material.dashed = false; } catch (_) { }
854
+ line.type = 'REF_PREVIEW_EDGE';
855
+ return this._configurePreviewObject(line, refName, 'EDGE');
856
+ }
857
+ if (type === 'FACE' || type === 'PLANE') {
858
+ const group = new THREE.Group();
859
+ group.type = type === 'PLANE' ? 'REF_PREVIEW_PLANE' : 'REF_PREVIEW_FACE';
860
+ try { group.userData = group.userData || {}; } catch (_) { }
861
+ try { group.userData.previewHasEdges = true; } catch (_) { }
862
+ const edges = Array.isArray(snapshot.edgePositions) ? snapshot.edgePositions : [];
863
+ for (const positions of edges) {
864
+ if (!Array.isArray(positions) || positions.length < 6) continue;
865
+ const geom = new LineGeometry();
866
+ geom.setPositions(positions);
867
+ try { geom.computeBoundingSphere(); } catch (_) { }
868
+ const mat = this._createPreviewLineMaterial(null, REF_PREVIEW_COLORS.EDGE);
869
+ const line = new Line2(geom, mat || undefined);
870
+ try { line.computeLineDistances?.(); } catch (_) { }
871
+ try { if (line.material && typeof line.material.dashed !== 'undefined') line.material.dashed = false; } catch (_) { }
872
+ line.type = 'REF_PREVIEW_EDGE';
873
+ this._configurePreviewObject(line, refName, 'EDGE');
874
+ group.add(line);
875
+ }
876
+ if (group.children.length === 0) return null;
877
+ return this._configurePreviewObject(group, refName, group.type);
878
+ }
879
+ if (type === 'VERTEX') {
880
+ const pos = snapshot.position;
881
+ if (!Array.isArray(pos) || pos.length < 3) return null;
882
+ const geom = new THREE.BufferGeometry();
883
+ geom.setAttribute('position', new THREE.Float32BufferAttribute([0, 0, 0], 3));
884
+ const mat = this._createPreviewPointMaterial(null, REF_PREVIEW_COLORS.VERTEX);
885
+ const pts = new THREE.Points(geom, mat || undefined);
886
+ pts.position.set(Number(pos[0]) || 0, Number(pos[1]) || 0, Number(pos[2]) || 0);
887
+ pts.type = 'REF_PREVIEW_VERTEX';
888
+ return this._configurePreviewObject(pts, refName, 'VERTEX');
889
+ }
890
+ return null;
891
+ }
892
+
893
+ _ensureReferencePreviewGroup(inputEl) {
894
+ const scene = this._getReferenceSelectionScene();
895
+ if (!scene || !inputEl) return null;
896
+ const existing = inputEl.__refPreviewGroup;
897
+ if (existing && existing.isObject3D) {
898
+ if (existing.parent !== scene) {
899
+ try { scene.add(existing); } catch (_) { }
900
+ }
901
+ return existing;
902
+ }
903
+ const group = new THREE.Group();
904
+ try { group.name = `__REF_PREVIEW_GROUP__${inputEl?.dataset?.key || ''}`; } catch (_) { }
905
+ try {
906
+ group.userData = group.userData || {};
907
+ group.userData.preventRemove = true;
908
+ group.userData.excludeFromFit = true;
909
+ group.userData.refPreview = true;
910
+ } catch (_) { }
911
+ try { group.renderOrder = 10040; } catch (_) { }
912
+ try { group.raycast = () => { }; } catch (_) { }
913
+ inputEl.__refPreviewGroup = group;
914
+ try { scene.add(group); } catch (_) { }
915
+ return group;
916
+ }
917
+
918
+ _removeReferencePreviewGroup(inputEl) {
919
+ const group = inputEl?.__refPreviewGroup;
920
+ if (!group || !group.isObject3D) return;
921
+ try { if (group.userData) group.userData.preventRemove = false; } catch (_) { }
922
+ try { if (group.parent) group.parent.remove(group); } catch (_) { }
923
+ }
924
+
925
+ _syncActiveReferenceSelectionPreview(inputEl, def = null) {
926
+ try {
927
+ const active = SchemaForm.__activeRefInput;
928
+ if (!active || active !== inputEl) return;
929
+ const scene = this._getReferenceSelectionScene();
930
+ if (!scene) return;
931
+ const names = this._collectReferenceSelectionNames(inputEl, def);
932
+ if (!names.length) {
933
+ this._removeReferencePreviewGroup(inputEl);
934
+ return;
935
+ }
936
+ const cache = this._getReferencePreviewCache(inputEl);
937
+ if (!cache || cache.size === 0) return;
938
+ const group = this._ensureReferencePreviewGroup(inputEl);
939
+ const wanted = new Set(names);
940
+ if (group && Array.isArray(group.children)) {
941
+ for (const child of group.children.slice()) {
942
+ const refName = child?.userData?.refName;
943
+ if (!refName || !wanted.has(refName)) {
944
+ try { group.remove(child); } catch (_) { }
945
+ }
946
+ }
947
+ }
948
+ for (const name of names) {
949
+ const entry = cache.get(name);
950
+ let ghost = entry && entry.object ? entry.object : entry;
951
+ if (!ghost) continue;
952
+ const sourceUuid = entry?.sourceUuid || null;
953
+ let originalPresent = false;
954
+ if (sourceUuid && typeof scene.getObjectByProperty === 'function') {
955
+ try { originalPresent = !!scene.getObjectByProperty('uuid', sourceUuid); } catch (_) { originalPresent = false; }
956
+ } else {
957
+ const real = scene.getObjectByName(name);
958
+ originalPresent = !!real;
959
+ }
960
+ if (originalPresent) {
961
+ const keepGhost = !!(entry?.showWhenOriginalPresent || ghost?.userData?.previewHasEdges);
962
+ if (!keepGhost) {
963
+ if (ghost.parent === group) {
964
+ try { group.remove(ghost); } catch (_) { }
965
+ }
966
+ continue;
967
+ }
968
+ try {
969
+ ghost.traverse?.((child) => {
970
+ if (!child || !child.userData?.refPreview) return;
971
+ const pType = String(child.userData.previewType || child.type || '').toUpperCase();
972
+ if (pType.includes('REF_PREVIEW_FACE') || pType.includes('REF_PREVIEW_PLANE')) {
973
+ child.visible = false;
974
+ } else if (child.type === 'REF_PREVIEW_EDGE') {
975
+ child.visible = true;
976
+ }
977
+ });
978
+ } catch (_) { }
979
+ if (ghost.parent !== group) {
980
+ try { group.add(ghost); } catch (_) { }
981
+ }
982
+ continue;
983
+ }
984
+ if (ghost.parent !== group) {
985
+ try { group.add(ghost); } catch (_) { }
986
+ }
987
+ try { ghost.visible = true; } catch (_) { }
988
+ }
989
+ } catch (_) { }
990
+ }
991
+
992
+ _seedReferencePreviewCacheFromScene(inputEl, def = null, names = null, sceneOverride = null) {
993
+ if (!inputEl) return;
994
+ const scene = sceneOverride || this._getReferenceSelectionScene();
995
+ if (!scene) return;
996
+ const list = Array.isArray(names) ? names : this._collectReferenceSelectionNames(inputEl, def);
997
+ if (!list.length) return;
998
+ const cache = this._getReferencePreviewCache(inputEl);
999
+ if (!cache) return;
1000
+ const store = this._getReferencePreviewPersistentBucket(inputEl);
1001
+ for (const name of list) {
1002
+ if (!name) continue;
1003
+ const existing = cache.get(name) || null;
1004
+ const snapshot = store ? store[name] : null;
1005
+ if (snapshot) {
1006
+ const snapType = String(snapshot.type || '').toUpperCase();
1007
+ const snapEdges = Array.isArray(snapshot.edgePositions) ? snapshot.edgePositions : null;
1008
+ const isFaceSnap = (snapType === 'FACE' || snapType === 'PLANE') && snapEdges && snapEdges.length;
1009
+ const isEdgeSnap = snapType === 'EDGE' && Array.isArray(snapshot.positions) && snapshot.positions.length >= 6;
1010
+ const isVertexSnap = snapType === 'VERTEX' && Array.isArray(snapshot.position) && snapshot.position.length >= 3;
1011
+ if (isFaceSnap || isEdgeSnap || isVertexSnap) {
1012
+ const shouldOverride = !existing || !existing.fromSnapshot || isFaceSnap;
1013
+ if (shouldOverride) {
1014
+ const ghost = this._buildReferencePreviewFromSnapshot(name, snapshot);
1015
+ if (ghost) {
1016
+ cache.set(name, {
1017
+ object: ghost,
1018
+ type: snapshot.type || null,
1019
+ sourceUuid: snapshot.sourceUuid || null,
1020
+ sourceFeatureId: snapshot.sourceFeatureId || null,
1021
+ showWhenOriginalPresent: isFaceSnap || !!ghost?.userData?.previewHasEdges,
1022
+ fromSnapshot: true,
1023
+ });
1024
+ continue;
1025
+ }
1026
+ }
1027
+ }
1028
+ }
1029
+ if (cache.has(name)) continue;
1030
+ const obj = scene.getObjectByName(name);
1031
+ if (obj && !obj?.userData?.refPreview) {
1032
+ this._storeReferencePreviewSnapshot(inputEl, def, obj);
1033
+ continue;
1034
+ }
1035
+ if (store && store[name]) {
1036
+ const snapshot = store[name];
1037
+ const ghost = this._buildReferencePreviewFromSnapshot(name, snapshot);
1038
+ if (ghost) {
1039
+ cache.set(name, {
1040
+ object: ghost,
1041
+ type: snapshot.type || null,
1042
+ sourceUuid: snapshot.sourceUuid || null,
1043
+ sourceFeatureId: snapshot.sourceFeatureId || null,
1044
+ showWhenOriginalPresent: String(snapshot.type || '').toUpperCase() === 'FACE' || String(snapshot.type || '').toUpperCase() === 'PLANE' || !!ghost?.userData?.previewHasEdges,
1045
+ fromSnapshot: true,
1046
+ });
1047
+ }
1048
+ }
1049
+ }
1050
+ }
1051
+
1052
+ _storeReferencePreviewSnapshot(inputEl, def, obj) {
1053
+ try {
1054
+ if (!inputEl || !obj) return;
1055
+ const refName = this._resolveReferencePreviewName(obj);
1056
+ if (!refName) return;
1057
+ const cache = this._getReferencePreviewCache(inputEl);
1058
+ if (!cache) return;
1059
+ const ghost = this._buildReferencePreviewObject(obj, refName);
1060
+ if (!ghost) return;
1061
+ const sourceUuid = obj.uuid || null;
1062
+ const sourceFeatureId = this._getOwningFeatureIdForObject(obj);
1063
+ cache.set(refName, {
1064
+ object: ghost,
1065
+ type: obj.type || null,
1066
+ sourceUuid,
1067
+ sourceFeatureId,
1068
+ showWhenOriginalPresent: !!ghost?.userData?.previewHasEdges,
1069
+ });
1070
+ try {
1071
+ const store = this._getReferencePreviewPersistentBucket(inputEl);
1072
+ if (store) {
1073
+ const objType = String(obj.type || '').toUpperCase();
1074
+ if (objType === SelectionFilter.EDGE || objType === 'EDGE') {
1075
+ const positions = this._extractEdgeWorldPositions(obj);
1076
+ if (positions && positions.length >= 6) {
1077
+ store[refName] = { type: 'EDGE', positions, sourceUuid, sourceFeatureId };
1078
+ }
1079
+ } else if (objType === SelectionFilter.VERTEX || objType === 'VERTEX') {
1080
+ const pos = new THREE.Vector3();
1081
+ try {
1082
+ if (typeof obj.getWorldPosition === 'function') obj.getWorldPosition(pos);
1083
+ else pos.set(obj.position?.x || 0, obj.position?.y || 0, obj.position?.z || 0);
1084
+ } catch (_) { }
1085
+ store[refName] = { type: 'VERTEX', position: [pos.x, pos.y, pos.z], sourceUuid, sourceFeatureId };
1086
+ }
1087
+ }
1088
+ } catch (_) { }
1089
+ if (SchemaForm.__activeRefInput === inputEl) {
1090
+ try { this._syncActiveReferenceSelectionPreview(inputEl, def); } catch (_) { }
1091
+ }
1092
+ } catch (_) { }
1093
+ }
1094
+
1095
+ _startReferencePreviewWatcher(inputEl, def) {
1096
+ if (!inputEl) return;
1097
+ if (this._refPreviewWatcher && this._refPreviewWatcher.inputEl === inputEl) return;
1098
+ this._stopReferencePreviewWatcher();
1099
+ const tick = () => {
1100
+ if (!this._refPreviewWatcher || this._refPreviewWatcher.inputEl !== inputEl) return;
1101
+ if (SchemaForm.__activeRefInput !== inputEl) {
1102
+ this._stopReferencePreviewWatcher();
1103
+ return;
1104
+ }
1105
+ try { this._syncActiveReferenceSelectionPreview(inputEl, def); } catch (_) { }
1106
+ this._refPreviewWatcher.timer = setTimeout(tick, 300);
1107
+ };
1108
+ this._refPreviewWatcher = { inputEl, timer: null };
1109
+ inputEl.__refPreviewCleanup = () => {
1110
+ try { this._stopReferencePreviewWatcher(); } catch (_) { }
1111
+ try { this._removeReferencePreviewGroup(inputEl); } catch (_) { }
1112
+ };
1113
+ tick();
1114
+ }
1115
+
1116
+ _stopReferencePreviewWatcher() {
1117
+ if (!this._refPreviewWatcher) return;
1118
+ const timer = this._refPreviewWatcher.timer;
1119
+ if (timer) {
1120
+ clearTimeout(timer);
1121
+ }
1122
+ this._refPreviewWatcher = null;
1123
+ }
1124
+
497
1125
  _collectReferenceSelectionNames(inputEl, def = null) {
498
1126
  if (!inputEl) return [];
499
1127
  const isMulti = Boolean(def && def.multiple) || (inputEl.dataset && inputEl.dataset.multiple === 'true');
@@ -530,11 +1158,131 @@ export class SchemaForm {
530
1158
  const scene = this._getReferenceSelectionScene();
531
1159
  if (!scene) return;
532
1160
  const names = this._collectReferenceSelectionNames(inputEl, def);
1161
+ try { this._seedReferencePreviewCacheFromScene(inputEl, def, names, scene); } catch (_) { }
533
1162
  SelectionFilter.unselectAll(scene);
534
1163
  for (const name of names) {
535
1164
  if (!name) continue;
536
1165
  try { SelectionFilter.selectItem(scene, name); } catch (_) { }
537
1166
  }
1167
+ try { this._syncActiveReferenceSelectionPreview(inputEl, def); } catch (_) { }
1168
+ } catch (_) { }
1169
+ }
1170
+
1171
+ _ensureReferencePreviewSnapshots(inputEl, def) {
1172
+ try {
1173
+ if (!inputEl) return;
1174
+ if (inputEl.__refPreviewBackfillPromise) return;
1175
+ const names = this._collectReferenceSelectionNames(inputEl, def);
1176
+ if (!names.length) return;
1177
+ const store = this._getReferencePreviewPersistentBucket(inputEl);
1178
+ let missing = false;
1179
+ if (!store) missing = true;
1180
+ if (!missing) {
1181
+ for (const name of names) {
1182
+ const snap = store ? store[name] : null;
1183
+ const type = String(snap?.type || '').toUpperCase();
1184
+ if (!snap) { missing = true; break; }
1185
+ if (type === 'EDGE') {
1186
+ if (!Array.isArray(snap.positions) || snap.positions.length < 6) { missing = true; break; }
1187
+ } else if (type === 'VERTEX') {
1188
+ if (!Array.isArray(snap.position) || snap.position.length < 3) { missing = true; break; }
1189
+ } else if (type === 'FACE' || type === 'PLANE') {
1190
+ if (!Array.isArray(snap.edgePositions) || snap.edgePositions.length === 0) { missing = true; break; }
1191
+ } else {
1192
+ missing = true;
1193
+ break;
1194
+ }
1195
+ }
1196
+ }
1197
+ if (!missing) return;
1198
+
1199
+ const partHistory = this.options?.partHistory || this.options?.viewer?.partHistory || null;
1200
+ if (!partHistory || typeof partHistory.runHistory !== 'function') return;
1201
+
1202
+ const prevStep = partHistory.currentHistoryStepId;
1203
+ const featureId = this.params?.id ?? this.params?.featureID ?? this.params?.featureId ?? null;
1204
+ if (featureId != null) {
1205
+ try { partHistory.currentHistoryStepId = String(featureId); } catch (_) { }
1206
+ }
1207
+ inputEl.__refPreviewBackfillPromise = Promise.resolve()
1208
+ .then(() => partHistory.runHistory())
1209
+ .catch(() => { /* ignore */ })
1210
+ .then(() => {
1211
+ if (featureId != null) {
1212
+ try { partHistory.currentHistoryStepId = prevStep; } catch (_) { }
1213
+ }
1214
+ })
1215
+ .then(() => {
1216
+ inputEl.__refPreviewBackfillPromise = null;
1217
+ if (SchemaForm.__activeRefInput !== inputEl) return;
1218
+ const scene = this._getReferenceSelectionScene();
1219
+ const latest = this._collectReferenceSelectionNames(inputEl, def);
1220
+ try { this._seedReferencePreviewCacheFromScene(inputEl, def, latest, scene); } catch (_) { }
1221
+ try { this._syncActiveReferenceSelectionPreview(inputEl, def); } catch (_) { }
1222
+ })
1223
+ .finally(() => {
1224
+ inputEl.__refPreviewBackfillPromise = null;
1225
+ });
1226
+ } catch (_) { }
1227
+ }
1228
+
1229
+ _hoverReferenceSelectionItem(inputEl, def, name) {
1230
+ try {
1231
+ if (!inputEl) return;
1232
+ const activeInput = SchemaForm.__activeRefInput || null;
1233
+ if (activeInput !== inputEl) {
1234
+ const wrap = inputEl.closest?.('.ref-active') || null;
1235
+ if (!wrap) return;
1236
+ }
1237
+ const normalized = normalizeReferenceName(name);
1238
+ if (!normalized) return;
1239
+ const scene = this._getReferenceSelectionScene();
1240
+ if (!scene) return;
1241
+ try { console.log('[ReferenceSelection] Hover', { name: normalized }); } catch (_) { }
1242
+ try { this._ensureReferencePreviewSnapshots(inputEl, def); } catch (_) { }
1243
+ try { this._seedReferencePreviewCacheFromScene(inputEl, def, [normalized], scene); } catch (_) { }
1244
+ try { this._syncActiveReferenceSelectionPreview(inputEl, def); } catch (_) { }
1245
+
1246
+ let target = null;
1247
+ try { target = scene.getObjectByName(normalized); } catch (_) { target = null; }
1248
+ if (!target) {
1249
+ const cache = this._getReferencePreviewCache(inputEl);
1250
+ const entry = cache ? cache.get(normalized) : null;
1251
+ target = entry?.object || entry || null;
1252
+ }
1253
+ if (!target) {
1254
+ try { target = scene.getObjectByName(`__refPreview__${normalized}`); } catch (_) { target = null; }
1255
+ }
1256
+ if (!target) return;
1257
+ if (!target.material && target.traverse) {
1258
+ let candidate = null;
1259
+ try {
1260
+ target.traverse((child) => {
1261
+ if (!child || candidate) return;
1262
+ if (child.type === 'REF_PREVIEW_EDGE') { candidate = child; return; }
1263
+ if (child.material) candidate = child;
1264
+ });
1265
+ } catch (_) { }
1266
+ if (candidate) target = candidate;
1267
+ }
1268
+ try {
1269
+ console.log('[ReferenceSelection] Hover target', {
1270
+ name: normalized,
1271
+ target: target || null,
1272
+ inScene: !!(target && target.parent),
1273
+ });
1274
+ } catch (_) { }
1275
+ inputEl.__refChipHoverActive = true;
1276
+ try { SelectionFilter.setHoverObject(target, { ignoreFilter: true }); } catch (_) { }
1277
+ } catch (_) { }
1278
+ }
1279
+
1280
+ _clearReferenceSelectionHover(inputEl) {
1281
+ try {
1282
+ if (!inputEl || SchemaForm.__activeRefInput !== inputEl) return;
1283
+ if (!inputEl.__refChipHoverActive) return;
1284
+ inputEl.__refChipHoverActive = false;
1285
+ SelectionFilter.clearHover();
538
1286
  } catch (_) { }
539
1287
  }
540
1288
 
@@ -581,8 +1329,38 @@ export class SchemaForm {
581
1329
  SelectionFilter.SetSelectionTypes(def.selectionFilter);
582
1330
  try { window.__BREP_activeRefInput = inputEl; } catch (_) { }
583
1331
 
1332
+ // Log current selected objects for this reference field on activation
1333
+ try {
1334
+ const scene = this._getReferenceSelectionScene();
1335
+ const names = this._collectReferenceSelectionNames(inputEl, def);
1336
+ const keyLabel = inputEl?.dataset?.key ? ` (${inputEl.dataset.key})` : '';
1337
+ if (!names.length) {
1338
+ console.log(`[ReferenceSelection] Activated${keyLabel}: no selections`);
1339
+ } else {
1340
+ const cache = this._getReferencePreviewCache(inputEl);
1341
+ for (const name of names) {
1342
+ if (!name) continue;
1343
+ const obj = scene ? scene.getObjectByName(name) : null;
1344
+ const cached = cache ? cache.get(name) : null;
1345
+ const cachedObj = cached && cached.object ? cached.object : null;
1346
+ console.log(`[ReferenceSelection] Selected${keyLabel}: ${name}`, {
1347
+ object: obj || cachedObj || null,
1348
+ inScene: !!obj,
1349
+ cached: !!cachedObj,
1350
+ });
1351
+ }
1352
+ }
1353
+ } catch (_) { }
1354
+
584
1355
  // Highlight existing selections while this reference field is active
585
1356
  try { this._syncActiveReferenceSelectionHighlight(inputEl, def); } catch (_) { }
1357
+ try { this._ensureReferencePreviewSnapshots(inputEl, def); } catch (_) { }
1358
+ try {
1359
+ if (typeof inputEl.__captureReferencePreview !== 'function') {
1360
+ inputEl.__captureReferencePreview = (obj) => this._storeReferencePreviewSnapshot(inputEl, def, obj);
1361
+ }
1362
+ } catch (_) { }
1363
+ try { this._startReferencePreviewWatcher(inputEl, def); } catch (_) { }
586
1364
  }
587
1365
 
588
1366
  // Activate a TransformControls session for a transform widget
@@ -1044,17 +1822,25 @@ export class SchemaForm {
1044
1822
 
1045
1823
  _stopActiveReferenceSelection() {
1046
1824
  // Clear global active if it belongs to this instance
1825
+ const activeInput = SchemaForm.__activeRefInput || null;
1047
1826
  try {
1048
- if (SchemaForm.__activeRefInput) {
1049
- try { SchemaForm.__activeRefInput.style.filter = 'none'; } catch (_) { }
1050
- try { SchemaForm.__activeRefInput.removeAttribute('active-reference-selection'); } catch (_) { }
1827
+ if (activeInput) {
1828
+ try { activeInput.style.filter = 'none'; } catch (_) { }
1829
+ try { activeInput.removeAttribute('active-reference-selection'); } catch (_) { }
1051
1830
  try {
1052
- const wrap = SchemaForm.__activeRefInput.closest('.ref-single-wrap, .ref-multi-wrap');
1831
+ const wrap = activeInput.closest('.ref-single-wrap, .ref-multi-wrap');
1053
1832
  if (wrap) wrap.classList.remove('ref-active');
1054
1833
  } catch (_) { }
1055
1834
  }
1056
1835
  } catch (_) { }
1057
- const hadActive = !!SchemaForm.__activeRefInput;
1836
+ const hadActive = !!activeInput;
1837
+ try {
1838
+ if (activeInput && typeof activeInput.__refPreviewCleanup === 'function') {
1839
+ activeInput.__refPreviewCleanup();
1840
+ } else if (activeInput) {
1841
+ this._removeReferencePreviewGroup(activeInput);
1842
+ }
1843
+ } catch (_) { }
1058
1844
  SchemaForm.__activeRefInput = null;
1059
1845
  try { if (window.__BREP_activeRefInput === undefined || window.__BREP_activeRefInput === SchemaForm.__activeRefInput) window.__BREP_activeRefInput = null; } catch (_) { }
1060
1846
  if (hadActive) {
@@ -1070,7 +1856,41 @@ export class SchemaForm {
1070
1856
  chipsWrap.textContent = '';
1071
1857
  const arr = Array.isArray(values) ? values : [];
1072
1858
  const normalizedValues = normalizeReferenceList(arr);
1073
- const inputEl = (this._inputs && typeof this._inputs.get === 'function') ? this._inputs.get(key) : null;
1859
+ let inputEl = (this._inputs && typeof this._inputs.get === 'function') ? this._inputs.get(key) : null;
1860
+ const resolveInput = () => {
1861
+ if (inputEl) return inputEl;
1862
+ const wrap = chipsWrap?.closest?.('.ref-multi-wrap, .ref-single-wrap') || null;
1863
+ const hidden = wrap ? wrap.querySelector('input[type="hidden"]') : null;
1864
+ if (hidden) inputEl = hidden;
1865
+ return inputEl;
1866
+ };
1867
+ const resolveDef = () => {
1868
+ const el = resolveInput();
1869
+ return (el && el.__refSelectionDef) || (this.schema ? (this.schema[key] || null) : null);
1870
+ };
1871
+ const def = resolveDef();
1872
+ if (chipsWrap && !chipsWrap.__refHoverBound) {
1873
+ chipsWrap.__refHoverBound = true;
1874
+ chipsWrap.__refHoverName = null;
1875
+ chipsWrap.addEventListener('mousemove', (ev) => {
1876
+ try {
1877
+ const chip = ev.target?.closest?.('.ref-chip');
1878
+ const refName = chip?.dataset?.refName || null;
1879
+ if (!refName) {
1880
+ chipsWrap.__refHoverName = null;
1881
+ this._clearReferenceSelectionHover(resolveInput());
1882
+ return;
1883
+ }
1884
+ if (chipsWrap.__refHoverName === refName) return;
1885
+ chipsWrap.__refHoverName = refName;
1886
+ this._hoverReferenceSelectionItem(resolveInput(), resolveDef(), refName);
1887
+ } catch (_) { }
1888
+ });
1889
+ chipsWrap.addEventListener('mouseleave', () => {
1890
+ chipsWrap.__refHoverName = null;
1891
+ this._clearReferenceSelectionHover(resolveInput());
1892
+ });
1893
+ }
1074
1894
  if (inputEl) {
1075
1895
  if (typeof inputEl.__updateSelectionMetadata === 'function') {
1076
1896
  try { inputEl.__updateSelectionMetadata(normalizedValues); } catch (_) { }
@@ -1087,6 +1907,7 @@ export class SchemaForm {
1087
1907
  for (const name of normalizedValues) {
1088
1908
  const chip = document.createElement('span');
1089
1909
  chip.className = 'ref-chip';
1910
+ try { chip.dataset.refName = name; } catch (_) { }
1090
1911
 
1091
1912
  const label = document.createElement('span');
1092
1913
  label.className = 'ref-chip-label';
@@ -1095,9 +1916,21 @@ export class SchemaForm {
1095
1916
 
1096
1917
  // Hover highlight on chip hover
1097
1918
  chip.addEventListener('mouseenter', () => {
1919
+ const liveInput = resolveInput();
1920
+ const liveDef = resolveDef();
1921
+ if (liveDef && liveDef.type === 'reference_selection') {
1922
+ this._hoverReferenceSelectionItem(liveInput, liveDef, name);
1923
+ return;
1924
+ }
1098
1925
  try { SelectionFilter.setHoverByName(this.options?.scene || null, name); } catch (_) { }
1099
1926
  });
1100
1927
  chip.addEventListener('mouseleave', () => {
1928
+ const liveInput = resolveInput();
1929
+ const liveDef = resolveDef();
1930
+ if (liveDef && liveDef.type === 'reference_selection') {
1931
+ this._clearReferenceSelectionHover(liveInput);
1932
+ return;
1933
+ }
1101
1934
  try { SelectionFilter.clearHover(); } catch (_) { }
1102
1935
  });
1103
1936
 
@@ -1158,7 +1991,7 @@ export class SchemaForm {
1158
1991
 
1159
1992
  try {
1160
1993
  if (inputEl && inputEl === SchemaForm.__activeRefInput) {
1161
- const def = this.schema ? (this.schema[key] || {}) : null;
1994
+ const def = (inputEl && inputEl.__refSelectionDef) || (this.schema ? (this.schema[key] || {}) : null);
1162
1995
  this._syncActiveReferenceSelectionHighlight(inputEl, def);
1163
1996
  }
1164
1997
  } catch (_) { }