From 2c26d7c96e56344a1a73a7c6f6dec3d6b0f0ee7e Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Fri, 16 May 2025 11:46:22 -0400
Subject: changed isGroup to freeform_isGroup to fix issues with groups that
 are changed into other collection types.  fixed toggleTarget links to work
 when opening in a light box (previously they flickered on, then off).  fixed
 text boxes with a number field as data to act like a number input box.

---
 .../collectionFreeForm/CollectionFreeFormView.tsx  | 42 +++++++++++-----------
 1 file changed, 22 insertions(+), 20 deletions(-)

(limited to 'src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx')

diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 77615c650..3571dab1a 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -176,7 +176,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
         return renderableEles;
     }
     @computed get fitContentsToBox() {
-        return (this._props.fitContentsToBox?.() || this.Document._freeform_fitContentsToBox) && !this.isAnnotationOverlay;
+        return (this._props.fitContentsToBox?.() || this.Document._freeform_fitContentsToBox || this.Document.freeform_isGroup) && !this.isAnnotationOverlay;
     }
     @computed get nativeWidth() {
         return this._props.NativeWidth?.() || Doc.NativeWidth(this.Document);
@@ -342,7 +342,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
      */
     focusOnPoint = (options: FocusViewOptions) => {
         const { pointFocus, zoomTime, didMove } = options;
-        if (!this.Document.isGroup && pointFocus && !didMove) {
+        if (!this.Document.freeform_isGroup && pointFocus && !didMove) {
             const dfltScale = this.isAnnotationOverlay ? 1 : 0.25;
             if (this.layoutDoc[this.scaleFieldKey] !== dfltScale) {
                 this.zoomSmoothlyAboutPt(this.screenToFreeformContentsXf.transformPoint(pointFocus.X, pointFocus.Y), dfltScale, zoomTime);
@@ -380,7 +380,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
      * @returns
      */
     focus = (anchor: Doc, options: FocusViewOptions) => {
-        if (anchor.isGroup && !options.docTransform && options.contextPath?.length) {
+        if (Doc.IsFreeformGroup(anchor) && !options.docTransform && options.contextPath?.length) {
             // don't focus on group if there's a context path because we're about to focus on a group item
             // which will override any group focus. (If we allowed the group to focus, it would mark didMove even if there were no net movement)
             return undefined;
@@ -395,7 +395,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
         }
         const xfToCollection = options?.docTransform ?? Transform.Identity();
         const savedState = { panX: NumCast(this.Document[this.panXFieldKey]), panY: NumCast(this.Document[this.panYFieldKey]), scale: options?.willZoomCentered ? this.Document[this.scaleFieldKey] : undefined };
-        const cantTransform = this.fitContentsToBox || ((this.Document.isGroup || this.layoutDoc._lockedTransform) && !DocumentView.LightboxDoc());
+        const cantTransform = this.fitContentsToBox || ((this.Document.freeform_isGroup || this.layoutDoc._lockedTransform) && !DocumentView.LightboxDoc());
         const { panX, panY, scale } = cantTransform || (!options.willPan && !options.willZoomCentered) ? savedState : this.calculatePanIntoView(anchor, xfToCollection, options?.willZoomCentered ? (options?.zoomScale ?? 0.75) : undefined);
 
         // focus on the document in the collection
@@ -514,7 +514,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
         this._downTime = Date.now();
         const scrollMode = e.altKey ? (Doc.UserDoc().freeformScrollMode === freeformScrollMode.Pan ? freeformScrollMode.Zoom : freeformScrollMode.Pan) : Doc.UserDoc().freeformScrollMode;
         if (e.button === 0 && (!(e.ctrlKey && !e.metaKey) || scrollMode !== freeformScrollMode.Pan) && this._props.isContentActive()) {
-            if (!this.Document.isGroup) {
+            if (!this.Document.freeform_isGroup) {
                 // group freeforms don't pan when dragged -- instead let the event go through to allow the group itself to drag
                 // prettier-ignore
                 const hit = this._clusters.handlePointerDown(this.screenToFreeformContentsXf.transformPoint(e.clientX, e.clientY));
@@ -1271,7 +1271,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
 
     @action
     zoom = (pointX: number, pointY: number, deltaY: number): void => {
-        if (this.Document.isGroup || this.Document[(this._props.viewField ?? '_') + 'freeform_noZoom']) return;
+        if (this.Document.freeform_isGroup || this.Document[(this._props.viewField ?? '_') + 'freeform_noZoom']) return;
         let deltaScale = deltaY > 0 ? 1 / 1.05 : 1.05;
         if (deltaScale < 0) deltaScale = -deltaScale;
         const [x, y] = this.screenToFreeformContentsXf.transformPoint(pointX, pointY);
@@ -1298,7 +1298,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
 
     @action
     onPointerWheel = (e: React.WheelEvent): void => {
-        if (this.Document.isGroup || !this.isContentActive()) return; // group style collections neither pan nor zoom
+        if (this.Document.freeform_isGroup || !this.isContentActive()) return; // group style collections neither pan nor zoom
         SnappingManager.TriggerUserPanned();
         if (this.layoutDoc._Transform || this.Document.treeView_OutlineMode === TreeViewType.outline) return;
         e.stopPropagation();
@@ -1422,7 +1422,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
 
     @action
     zoomSmoothlyAboutPt(docpt: number[], scale: number, transitionTime = 500) {
-        if (this.Document.isGroup) return;
+        if (this.Document.freeform_isGroup) return;
         this.setPanZoomTransition(transitionTime);
         const screenXY = this.screenToFreeformContentsXf.inverse().transformPoint(docpt[0], docpt[1]);
         this.layoutDoc[this.scaleFieldKey] = scale;
@@ -1505,7 +1505,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
     removeDocument = (docs: Doc | Doc[], annotationKey?: string | undefined) => {
         const ret = !!this._props.removeDocument?.(docs, annotationKey);
         // if this is a group and we have fewer than 2 Docs, then just promote what's left to our parent and get rid of the group.
-        if (ret && DocListCast(this.dataDoc[annotationKey ?? this.fieldKey]).length < 2 && this.Document.isGroup) {
+        if (ret && DocListCast(this.dataDoc[annotationKey ?? this.fieldKey]).length < 2 && this.Document.freeform_isGroup) {
             this.promoteCollection();
         }
         return ret;
@@ -1548,7 +1548,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
                 searchFilterDocs={this.searchFilterDocs}
                 isDocumentActive={childLayout.pointerEvents === 'none' ? returnFalse : this._props.childDocumentsActive?.() ? this._props.isDocumentActive : this.isContentActive}
                 isContentActive={this.childContentsActive}
-                focus={this.Document.isGroup ? this.groupFocus : this.isAnnotationOverlay ? this._props.focus : this.focus}
+                focus={this.Document.freeform_isGroup ? this.groupFocus : this.isAnnotationOverlay ? this._props.focus : this.focus}
                 addDocTab={this.addDocTab}
                 addDocument={this._props.addDocument}
                 removeDocument={this.removeDocument}
@@ -1733,7 +1733,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
         });
         PinDocView(
             anchor,
-            { pinDocLayout: pinProps?.pinDocLayout, pinData: { ...(pinProps?.pinData ? { ...pinProps.pinData, poslayoutview: pinProps.pinData.dataview } : {}), pannable: !this.Document.isGroup, collectionType: true, filters: true } },
+            { pinDocLayout: pinProps?.pinDocLayout, pinData: { ...(pinProps?.pinData ? { ...pinProps.pinData, poslayoutview: pinProps.pinData.dataview } : {}), pannable: !this.Document.freeform_isGroup, collectionType: true, filters: true } },
             this.Document
         );
 
@@ -1767,7 +1767,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
                 this._firstRender = false;
                 this._disposers.groupBounds = reaction(
                     () => {
-                        if (this.Document.isGroup && this.childDocs.length === this.childDocList?.length) {
+                        if (this.Document.freeform_isGroup && this.childDocs.length === this.childDocList?.length) {
                             const clist = this.childDocs.map(cd => ({ x: NumCast(cd.x), y: NumCast(cd.y), width: NumCast(cd._width), height: NumCast(cd._height) }));
                             return aggregateBounds(clist, NumCast(this.layoutDoc._xMargin), NumCast(this.layoutDoc._yMargin));
                         }
@@ -1929,8 +1929,8 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
 
         const appearance = ContextMenu.Instance.findByDescription('Appearance...');
         const appearanceItems = appearance?.subitems ?? [];
-        !this.Document.isGroup && appearanceItems.push({ description: 'Reset View', event: this.resetView, icon: 'compress-arrows-alt' });
-        !this.Document.isGroup && appearanceItems.push({ description: 'Toggle Auto Reset View', event: this.toggleResetView, icon: 'compress-arrows-alt' });
+        !this.Document.freeform_isGroup && appearanceItems.push({ description: 'Reset View', event: this.resetView, icon: 'compress-arrows-alt' });
+        !this.Document.freeform_isGroup && appearanceItems.push({ description: 'Toggle Auto Reset View', event: this.toggleResetView, icon: 'compress-arrows-alt' });
         if (this._props.setContentViewBox === emptyFunction) {
             !appearance && ContextMenu.Instance.addItem({ description: 'Appearance...', subitems: appearanceItems, icon: 'eye' });
             return;
@@ -1948,7 +1948,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
         !Doc.noviceMode && appearanceItems.push({ description: `update icon`, event: () => this.updateIcon(), icon: 'compress-arrows-alt' });
         this._props.renderDepth && appearanceItems.push({ description: 'Ungroup collection', event: this.promoteCollection, icon: 'table' });
 
-        this.Document.isGroup && this.Document.transcription && appearanceItems.push({ description: 'Ink to text', event: this.transcribeStrokes, icon: 'font' });
+        this.Document.freeform_isGroup && this.Document.transcription && appearanceItems.push({ description: 'Ink to text', event: this.transcribeStrokes, icon: 'font' });
 
         !Doc.noviceMode ? appearanceItems.push({ description: 'Arrange contents in grid', event: this.layoutDocsInGrid, icon: 'table' }) : null;
         !Doc.noviceMode ? appearanceItems.push({ description: (this.Document._freeform_useClusters ? 'Hide' : 'Show') + ' Clusters', event: () => this._clusters.updateClusters(!this.Document._freeform_useClusters), icon: 'braille' }) : null;
@@ -2007,7 +2007,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
     };
 
     transcribeStrokes = undoable(() => {
-        if (this.Document.isGroup && this.Document.transcription) {
+        if (this.Document.freeform_isGroup && this.Document.transcription) {
             const text = StrCast(this.Document.transcription);
             const lines = text.split('\n');
             const height = 30 + 15 * lines.length;
@@ -2025,7 +2025,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
     dragStarting = (snapToDraggedDoc: boolean = false, showGroupDragTarget: boolean = true, visited = new Set<Doc>()) => {
         if (visited.has(this.Document)) return;
         visited.add(this.Document);
-        showGroupDragTarget && (this.GroupChildDrag = BoolCast(this.Document.isGroup));
+        showGroupDragTarget && (this.GroupChildDrag = BoolCast(this.Document.freeform_isGroup));
         const activeDocs = this.getActiveDocuments();
         const size = this.screenToFreeformContentsXf.transformDirection(this._props.PanelWidth(), this._props.PanelHeight());
         const selRect = { left: this.panX() - size[0] / 2, top: this.panY() - size[1] / 2, width: size[0], height: size[1] };
@@ -2033,13 +2033,15 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
         const isDocInView = (doc: Doc, rect: { left: number; top: number; width: number; height: number }) => intersectRect(docDims(doc), rect);
 
         const snappableDocs = activeDocs.filter(doc => doc.z === undefined && isDocInView(doc, selRect)); // first see if there are any foreground docs to snap to
-        activeDocs.filter(doc => doc.isGroup && SnappingManager.IsResizing !== doc[Id] && !DragManager.docsBeingDragged.includes(doc)).forEach(doc => DocumentView.getDocumentView(doc)?.ComponentView?.dragStarting?.(snapToDraggedDoc, false, visited));
+        activeDocs
+            .filter(doc => Doc.IsFreeformGroup(doc) && SnappingManager.IsResizing !== doc[Id] && !DragManager.docsBeingDragged.includes(doc))
+            .forEach(doc => DocumentView.getDocumentView(doc)?.ComponentView?.dragStarting?.(snapToDraggedDoc, false, visited));
 
         const horizLines: number[] = [];
         const vertLines: number[] = [];
         const invXf = this.screenToFreeformContentsXf.inverse();
         snappableDocs
-            .filter(doc => !doc.isGroup && (snapToDraggedDoc || (SnappingManager.IsResizing !== doc[Id] && !DragManager.docsBeingDragged.includes(doc))))
+            .filter(doc => !Doc.IsFreeformGroup(doc) && (snapToDraggedDoc || (SnappingManager.IsResizing !== doc[Id] && !DragManager.docsBeingDragged.includes(doc))))
             .forEach(doc => {
                 const { left, top, width, height } = docDims(doc);
                 const topLeftInScreen = invXf.transformPoint(left, top);
@@ -2131,7 +2133,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
                 {...this._props}
                 ref={this._marqueeViewRef}
                 Doc={this.Document}
-                ungroup={this.Document.isGroup ? this.promoteCollection : undefined}
+                ungroup={this.Document.freeform_isGroup ? this.promoteCollection : undefined}
                 nudge={this.isAnnotationOverlay || this._props.renderDepth > 0 ? undefined : this.nudge}
                 addDocTab={this.addDocTab}
                 slowLoadDocuments={this.slowLoadDocuments}
-- 
cgit v1.2.3-70-g09d2

