From 57827157823219ffb71047fd65217ebbd2420a9d Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Thu, 1 May 2025 15:32:25 -0400
Subject: from last

---
 src/client/views/ObservableReactComponent.tsx | 27 +++++++++++++++++++++++++++
 1 file changed, 27 insertions(+)

(limited to 'src/client/views/ObservableReactComponent.tsx')

diff --git a/src/client/views/ObservableReactComponent.tsx b/src/client/views/ObservableReactComponent.tsx
index bb7a07f0e..2290516dc 100644
--- a/src/client/views/ObservableReactComponent.tsx
+++ b/src/client/views/ObservableReactComponent.tsx
@@ -15,6 +15,33 @@ export abstract class ObservableReactComponent<T> extends React.Component<T, obj
         this._props = props;
         makeObservable(this);
     }
+    __passiveWheel: HTMLElement | null = null;
+    _isContentActive: () => boolean | undefined = () => false;
+
+    /**
+     * default method to stop wheel events from bubbling up to parent components.
+     * @param e
+     */
+    onPassiveWheel = (e: WheelEvent) => {
+        if (this._isContentActive?.()) e.stopPropagation();
+    };
+
+    /**
+     * This fixes the problem where a component uses wheel events to scroll, but is nested inside another component that
+     * can also scroll. In that case, the wheel event will bubble up to the parent component and cause it to scroll in addition.
+     * This is based on the native HTML5 behavior where wheel events are passive by default, meaning that they do not prevent the default action of scrolling.
+     * This method should be called from a ref={} property on or above the component that uses wheel events to scroll.
+     * @param ele HTMLELement containing the component that will scroll
+     * @param isContentActive function determining if the component is active and should handle the wheel event.
+     * @param onPassiveWheel an optional function to call to handle the wheel event (and block its propagation. If omitted, the event won't propagate.
+     */
+    fixWheelEvents = (ele: HTMLElement | null, isContentActive: () => boolean | undefined, onPassiveWheel?: (e: WheelEvent) => void) => {
+        this._isContentActive = isContentActive;
+        this.__passiveWheel?.removeEventListener('wheel', onPassiveWheel ?? this.onPassiveWheel);
+        this.__passiveWheel = ele;
+        ele?.addEventListener('wheel', onPassiveWheel ?? this.onPassiveWheel, { passive: false });
+    };
+
     componentDidUpdate(prevProps: Readonly<T>): void {
         Object.keys(prevProps)
             .filter(pkey => (prevProps as {[key:string]: unknown})[pkey] !== (this.props as  {[key:string]: unknown})[pkey])
-- 
cgit v1.2.3-70-g09d2


From 19adcca1a89405a47da57fee64fe5fde4720c16a Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Mon, 5 May 2025 14:05:32 -0400
Subject: got rid of dash _xPadding/_yPadding in favor of just using
 _xMargin/_yMargin.  cleaned up linearView field names

---
 src/client/documents/DocUtils.ts                   |  2 +-
 src/client/documents/Documents.ts                  | 14 +++---
 src/client/util/CurrentUserUtils.ts                | 52 +++++++++++-----------
 src/client/util/LinkManager.ts                     |  4 +-
 src/client/views/InkingStroke.tsx                  |  4 +-
 src/client/views/MainView.tsx                      |  2 +-
 src/client/views/ObservableReactComponent.tsx      |  8 ++--
 src/client/views/PropertiesButtons.tsx             |  2 +-
 .../views/collections/CollectionCardDeckView.tsx   |  2 +-
 .../views/collections/CollectionCarouselView.tsx   |  2 +-
 .../views/collections/CollectionStackingView.tsx   |  6 +--
 src/client/views/collections/TabDocView.tsx        |  4 +-
 src/client/views/collections/TreeView.tsx          |  8 ++--
 .../collectionFreeForm/CollectionFreeFormView.tsx  |  6 +--
 .../collectionGrid/CollectionGridView.tsx          |  2 +-
 .../collectionLinear/CollectionLinearView.tsx      | 16 +++----
 src/client/views/nodes/DocumentView.tsx            |  4 +-
 src/client/views/nodes/FieldView.tsx               |  4 +-
 src/client/views/nodes/LabelBox.tsx                | 12 ++---
 src/client/views/nodes/PDFBox.tsx                  |  4 +-
 src/client/views/nodes/ScreenshotBox.tsx           |  4 +-
 .../views/nodes/formattedText/FormattedTextBox.tsx |  8 ++--
 src/client/views/nodes/trails/PresSlideBox.tsx     |  8 ++--
 src/fields/documentSchemas.ts                      |  2 -
 24 files changed, 86 insertions(+), 94 deletions(-)

(limited to 'src/client/views/ObservableReactComponent.tsx')

diff --git a/src/client/documents/DocUtils.ts b/src/client/documents/DocUtils.ts
index df14dce5a..9135899d7 100644
--- a/src/client/documents/DocUtils.ts
+++ b/src/client/documents/DocUtils.ts
@@ -603,7 +603,7 @@ export namespace DocUtils {
                 layout_hideAllLinks: true,
                 _width: 15,
                 _height: 15,
-                _xPadding: 0,
+                _xMargin: 0,
                 onClick: FollowLinkScript(),
                 _timecodeToShow: Cast(doc._timecodeToShow, 'number', null),
             });
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index a4a668085..bbe872a91 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -198,7 +198,6 @@ export class DocumentOptions {
     _height?: NUMt = new NumInfo("height of document in container's coordiantes");
     data_nativeWidth?: NUMt = new NumInfo('native width of data field contents (e.g., the pixel width of an image)', false);
     data_nativeHeight?: NUMt = new NumInfo('native height of data field contents (e.g., the pixel height of an image)', false);
-    linearBtnWidth?: NUMt = new NumInfo('unexpanded width of a linear menu button (button "width" changes when it expands)', false);
     _nativeWidth?: NUMt = new NumInfo('Deprecated: use nativeWidth. native width of document contents (e.g., the pixel width of an image)', false);
     _nativeHeight?: NUMt = new NumInfo('Deprecated: use nativeHeight. native height of document contents (e.g., the pixel height of an image)', false);
     nativeWidth?: NUMt = new NumInfo('native width of document contents (e.g., the pixel width of an image)', false);
@@ -294,10 +293,8 @@ export class DocumentOptions {
     _chromeHidden?: BOOLt = new BoolInfo('whether the editing chrome for a document is hidden');
     hideClickBehaviors?: BOOLt = new BoolInfo('whether to hide click behaviors in context menu');
     _gridGap?: NUMt = new NumInfo('gap between items in masonry view', false);
-    _xMargin?: NUMt = new NumInfo('gap between left edge of document and start of masonry/stacking layouts', false);
-    _yMargin?: NUMt = new NumInfo('gap between top edge of dcoument and start of masonry/stacking layouts', false);
-    _xPadding?: NUMt = new NumInfo('x padding', false);
-    _yPadding?: NUMt = new NumInfo('y padding', false);
+    _xMargin?: NUMt = new NumInfo('gap between left edge of document and contents of freeform/masonry/stacking layouts', false);
+    _yMargin?: NUMt = new NumInfo('gap between top edge of dcoument and contents offreeform/masonry/stacking layouts', false);
     _createDocOnCR?: boolean; // whether carriage returns and tabs create new text documents
     _columnsHideIfEmpty?: BOOLt = new BoolInfo('whether stacking view column headings should be hidden');
     _caption_xMargin?: NUMt = new NumInfo('x margin of caption inside of a carousel collection', false, true);
@@ -427,10 +424,9 @@ export class DocumentOptions {
     badgeValue?: ScriptField;
 
     // LINEAR VIEW
-    linearView_IsOpen?: BOOLt = new BoolInfo('is linear view open');
-    linearView_Expandable?: BOOLt = new BoolInfo('can linear view be expanded');
-    linearView_Dropdown?: BOOLt = new BoolInfo('can linear view be opened as a dropdown');
-    linearView_SubMenu?: BOOLt = new BoolInfo('is doc a sub menu of more linear views');
+    linearView_btnWidth?: NUMt = new NumInfo('unexpanded width of a linear menu button (button "width" changes when it expands)', false);
+    linearView_isOpen?: BOOLt = new BoolInfo('is linear view open');
+    linearView_expandable?: BOOLt = new BoolInfo('can linear view be expanded');
     flexGap?: NUMt = new NumInfo('Linear view flex gap');
     flexDirection?: 'unset' | 'row' | 'column' | 'row-reverse' | 'column-reverse';
 
diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index 8f4d568ab..d460cd0d7 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -52,7 +52,7 @@ export interface Button {
     numBtnMax?: number;
     switchToggle?: boolean;
     width?: number;
-    linearBtnWidth?: number;
+    linearView_btnWidth?: number;
     toolType?: string; // type of pen tool
     expertMode?: boolean;// available only in expert mode
     btnList?: List<string>;
@@ -205,7 +205,7 @@ export class CurrentUserUtils {
         const templateIconsDoc = DocUtils.AssignOpts(DocCast(doc[field]), reqdOpts) ?? (doc[field] = Docs.Create.TreeDocument([], reqdOpts));
 
         const labelBox = (opts: DocumentOptions, fieldKey:string) => Docs.Create.LabelDocument({
-            layout: LabelBox.LayoutString(fieldKey), letterSpacing: "unset", _label_minFontSize: 14, _label_maxFontSize: 14, layout_borderRounding: "5px",  _width: 150, _height: 70, _xPadding: 10, _yPadding: 10, ...opts
+            layout: LabelBox.LayoutString(fieldKey), letterSpacing: "unset", _label_minFontSize: 14, _label_maxFontSize: 14, layout_borderRounding: "5px",  _width: 150, _height: 70, _xMargin: 10, _yMargin: 10, ...opts
         });
         const imageBox = (opts: DocumentOptions, fieldKey:string) => Docs.Create.ImageDocument( "http://www.cs.brown.edu/~bcz/noImage.png", { layout:ImageBox.LayoutString(fieldKey), "icon_nativeWidth": 360 / 4, "icon_nativeHeight": 270 / 4, iconTemplate:DocumentType.IMG,  _width: 360 / 4, _height: 270 / 4,  _layout_showTitle: "title", ...opts });
         const fontBox = (opts:DocumentOptions, fieldKey:string) => Docs.Create.FontIconDocument({ layout:FontIconBox.LayoutString(fieldKey), _nativeHeight: 30, _nativeWidth: 30, _width: 30, _height: 30, ...opts  });
@@ -402,7 +402,7 @@ pie title Minerals in my tap water
             {key: "Map",        creator: opts => Docs.Create.MapDocument([], opts),         opts: { _width: 800, _height: 600, _layout_fitWidth: true, }},
             {key: "Screengrab", creator: Docs.Create.ScreenshotDocument,                    opts: { _width: 400, _height: 200 }},
             {key: "WebCam",     creator: opts => Docs.Create.WebCamDocument("", opts),      opts: { _width: 400, _height: 200, recording:true, isSystem: true, cloneFieldFilter: new List<string>(["isSystem"]) }},
-            {key: "Button",     creator: Docs.Create.ButtonDocument,                        opts: { _width: 150, _height: 50, _xPadding: 10, _yPadding: 10, title_custom: true,  waitForDoubleClickToClick: 'never'}, scripts: {onClick: FollowLinkScript()?.script.originalScript ?? ""}},
+            {key: "Button",     creator: Docs.Create.ButtonDocument,                        opts: { _width: 150, _height: 50, _xMargin: 10, _yMargin: 10, title_custom: true,  waitForDoubleClickToClick: 'never'}, scripts: {onClick: FollowLinkScript()?.script.originalScript ?? ""}},
             {key: "Script",     creator: opts => Docs.Create.ScriptingDocument(null, opts), opts: { _width: 200, _height: 250, }},
             {key: "DataViz",    creator: opts => Docs.Create.DataVizDocument("", opts),     opts: { _width: 300, _height: 300, }},
             // AARAV ADD //
@@ -663,7 +663,7 @@ pie title Minerals in my tap water
     }
 
     static linearButtonList = (opts: DocumentOptions, docs: Doc[]) => Docs.Create.LinearDocument(docs, {
-        ...opts, _gridGap: 0, _xMargin: 5, _yMargin: 5, layout_boxShadow: "0 0", _forceActive: true,
+        ...opts, _gridGap: 0, _xMargin: 5, _yMargin: 5, layout_boxShadow: "0 0", _forceActive: true, linearView: true,
         dropConverter: ScriptField.MakeScript("convertToButtons(dragData)", { dragData: DragManager.DocumentDragData.name }),
         _lockedPosition: true, isSystem: true, flexDirection: "row"
     })
@@ -697,7 +697,7 @@ pie title Minerals in my tap water
         const btns = btnDescs.map(desc => dockBtn({_width: 30, _height: 30, defaultDoubleClick: 'ignore', undoIgnoreFields: new List<string>(['opacity']), _dragOnlyWithinContainer: true, ...desc.opts}, desc.scripts));
         const dockBtnsReqdOpts:DocumentOptions = {
             title: "docked buttons", _height: 40, flexGap: 0, layout_boxShadow: "standard", childDragAction: dropActionType.move,
-            childDontRegisterViews: true, linearView_IsOpen: true, linearView_Expandable: true, ignoreClick: true
+            childDontRegisterViews: true, linearView_isOpen: true, linearView_expandable: true, ignoreClick: true
         };
         reaction(() => UndoManager.redoStack.slice(), () => { Doc.GetProto(btns.find(btn => btn.title === "Redo")!).opacity = UndoManager.CanRedo() ? 1 : 0.4; }, { fireImmediately: true });
         reaction(() => UndoManager.undoStack.slice(), () => { Doc.GetProto(btns.find(btn => btn.title === "Undo")!).opacity = UndoManager.CanUndo() ? 1 : 0.4; }, { fireImmediately: true });
@@ -789,24 +789,24 @@ pie title Minerals in my tap water
             { title: "Circle", toolTip: "Circle (double tap to lock mode)", btnType: ButtonType.ToggleButton, icon: "circle",      toolType: Gestures.Circle,                           scripts: {onClick:`{ return setActiveTool(this.toolType, false, _readOnly_);}`,   onDoubleClick:`{ return setActiveTool(this.toolType, true, _readOnly_);}`} },
             { title: "Square", toolTip: "Square (double tap to lock mode)", btnType: ButtonType.ToggleButton, icon: "square",      toolType: Gestures.Rectangle,                        scripts: {onClick:`{ return setActiveTool(this.toolType, false, _readOnly_);}`,   onDoubleClick:`{ return setActiveTool(this.toolType, true, _readOnly_);}`} },
             { title: "Line",   toolTip: "Line (double tap to lock mode)",   btnType: ButtonType.ToggleButton, icon: "minus",       toolType: Gestures.Line,                             scripts: {onClick:`{ return setActiveTool(this.toolType, false, _readOnly_);}`,   onDoubleClick:`{ return setActiveTool(this.toolType, true, _readOnly_);}`} },
-            { title: "Ink",    toolTip: "Ink",                              btnType: ButtonType.MultiToggleButton,                 toolType: InkTool.Ink,        showUntilToggle: true,  scripts: {onClick:'{ return setActiveTool(this.toolType, true, _readOnly_);}' }, 
+            { title: "Ink",    toolTip: "Ink",                              btnType: ButtonType.MultiToggleButton,                 toolType: InkTool.Ink,        showUntilToggle: true, scripts: {onClick:'{ return setActiveTool(this.toolType, true, _readOnly_);}' }, 
                 subMenu: [
                     { title: "Pen",      toolTip: "Pen (Ctrl+P)",           btnType: ButtonType.ToggleButton, icon: "pen-nib",     toolType: InkInkTool.Pen,         ignoreClick: true, scripts: {onClick:'{ return setActiveTool(this.toolType, true, _readOnly_);}' }},
                     { title: "Highlight",toolTip: "Highlight (Ctrl+H)",     btnType: ButtonType.ToggleButton, icon: "highlighter", toolType: InkInkTool.Highlight,   ignoreClick: true, scripts: {onClick:'{ return setActiveTool(this.toolType, true, _readOnly_);}' }},
                     { title: "Write",    toolTip: "Write (Ctrl+Shift+P)",   btnType: ButtonType.ToggleButton, icon: "pen",         toolType: InkInkTool.Write,       ignoreClick: true, scripts: {onClick:'{ return setActiveTool(this.toolType, true, _readOnly_);}' },  funcs: {hidden:"IsNoviceMode()" }},      
                 ]},
-            { title: "Width",      toolTip: "Stroke width",                 btnType: ButtonType.NumberSliderButton,                toolType: InkProperty.StrokeWidth,ignoreClick: true, scripts: {script: '{ return setInkProperty(this.toolType, value, _readOnly_);}'}, funcs: {hidden:"!activeInkTool()"}, numBtnMin: 1, linearBtnWidth:40},
+            { title: "Width",      toolTip: "Stroke width",                 btnType: ButtonType.NumberSliderButton,                toolType: InkProperty.StrokeWidth,ignoreClick: true, scripts: {script: '{ return setInkProperty(this.toolType, value, _readOnly_);}'}, funcs: {hidden:"!activeInkTool()"}, numBtnMin: 1, linearView_btnWidth:40},
             { title: "Color",      toolTip: "Stroke color",                 btnType: ButtonType.ColorButton,  icon: "pen",         toolType: InkProperty.StrokeColor,ignoreClick: true, scripts: {script: '{ return setInkProperty(this.toolType, value, _readOnly_);}'}, funcs: {hidden:"!activeInkTool()"}},
-            { title: "Eraser",     toolTip: "Eraser (Ctrl+E)",              btnType: ButtonType.MultiToggleButton,                 toolType: InkTool.Eraser,     showUntilToggle: true,  scripts: {onClick:'{ return setActiveTool(this.toolType, false, _readOnly_);}' },
+            { title: "Eraser",     toolTip: "Eraser (Ctrl+E)",              btnType: ButtonType.MultiToggleButton,                 toolType: InkTool.Eraser,     showUntilToggle: true, scripts: {onClick:'{ return setActiveTool(this.toolType, false, _readOnly_);}' },
               subMenu: [
                     { title: "Stroke",   toolTip: "Eraser complete strokes",btnType: ButtonType.ToggleButton, icon: "eraser",      toolType:InkEraserTool.Stroke,    ignoreClick: true, scripts: {onClick: '{ return setActiveTool(this.toolType, false, _readOnly_);}'}},
                     { title: "Segment",  toolTip: "Erase between intersections",btnType:ButtonType.ToggleButton,icon:"xmark",      toolType:InkEraserTool.Segment,   ignoreClick: true, scripts: {onClick: '{ return setActiveTool(this.toolType, false, _readOnly_);}'}},
                     { title: "Area",     toolTip: "Erase like a pencil",    btnType: ButtonType.ToggleButton, icon: "circle-xmark",toolType:InkEraserTool.Radius,    ignoreClick: true, scripts: {onClick: '{ return setActiveTool(this.toolType, false, _readOnly_);}'}},
             ]},
-            { title: " Size",      toolTip: "Size of area pencil eraser",   btnType: ButtonType.NumberSliderButton,                toolType: InkProperty.EraserWidth,ignoreClick: true, scripts: {script: '{ return setInkProperty(this.toolType, value, _readOnly_);}'}, funcs: {hidden:"NotRadiusEraser()"}, numBtnMin: 1, linearBtnWidth:40},
+            { title: " Size",      toolTip: "Size of area pencil eraser",   btnType: ButtonType.NumberSliderButton,                toolType: InkProperty.EraserWidth,ignoreClick: true, scripts: {script: '{ return setInkProperty(this.toolType, value, _readOnly_);}'}, funcs: {hidden:"NotRadiusEraser()"}, numBtnMin: 1, linearView_btnWidth:40},
             { title: "Mask",       toolTip: "Make Stroke a Stencil Mask",   btnType: ButtonType.ToggleButton, icon: "user-circle", toolType: InkProperty.Mask,                          scripts: {onClick:'{ return setInkProperty(this.toolType, value, _readOnly_);}'}, funcs: {hidden:"IsNoviceMode()" } },
             { title: "Labels",     toolTip: "Show Labels Inside Shapes",    btnType: ButtonType.ToggleButton, icon: "text-width",  toolType: InkProperty.Labels,                        scripts: {onClick:'{ return setInkProperty(this.toolType, value, _readOnly_);}'}},
-            { title: "Smart Draw", toolTip: "Draw with AI",                btnType: ButtonType.ToggleButton, icon: "user-pen",    toolType: InkTool.SmartDraw,                         scripts: {onClick:'{ return setActiveTool(this.toolType, false, _readOnly_);}'},  funcs: {hidden: "IsNoviceMode()"}},
+            { title: "Smart Draw", toolTip: "Draw with AI",                 btnType: ButtonType.ToggleButton, icon: "user-pen",    toolType: InkTool.SmartDraw,                         scripts: {onClick:'{ return setActiveTool(this.toolType, false, _readOnly_);}'},  funcs: {hidden: "IsNoviceMode()"}},
         ];
     }
 
@@ -843,7 +843,7 @@ pie title Minerals in my tap water
             { title: "Template",icon: "scroll",        toolTip: "Default Note Template",btnType: ButtonType.ToggleButton, expertMode: false, toolType:DocumentType.RTF,                                                                                                              scripts: { onClick: '{ return setDefaultTemplate(_readOnly_); }'} },
             { title: "Fill",    icon: "fill-drip",     toolTip: "Fill/Background Color",btnType: ButtonType.ColorButton,  expertMode: false,                                                                                                          ignoreClick: true, width: 30,  scripts: { script:  'return setBackgroundColor(value, _readOnly_)'} }, // Only when a document is selected
             { title: "Border",  icon: "border-style",  toolTip: "Border Color",         btnType: ButtonType.ColorButton,  expertMode: false,                                                                                                          ignoreClick: true, width: 30,  scripts: { script:  'return setBorderColor(value, _readOnly_)'} }, // Only when a document is selected
-            { title: "B.Width",                        toolTip: "Border width",         btnType: ButtonType.NumberSliderButton,                                                                                                                       ignoreClick: true,             scripts: {script: '{ return setBorderWidth(value, _readOnly_);}'}, numBtnMin: 0, linearBtnWidth:40},
+            { title: "B.Width",                        toolTip: "Border width",         btnType: ButtonType.NumberSliderButton,                                                                                                                       ignoreClick: true,             scripts: {script: '{ return setBorderWidth(value, _readOnly_);}'}, numBtnMin: 0, linearView_btnWidth:40},
             { title: "Overlay", icon: "layer-group",   toolTip: "Overlay",              btnType: ButtonType.ToggleButton, expertMode: true,  toolType:CollectionViewType.Freeform, funcs: {hidden: '!SelectedDocType(this.toolType, this.expertMode, true)'},                        scripts: { onClick: '{ return toggleOverlay(_readOnly_); }'}}, // Only when floating document is selected in freeform
             { title: "Back",    icon: "chevron-left",  toolTip: "Prev Animation Frame", btnType: ButtonType.ClickButton,  expertMode: true,  toolType:CollectionViewType.Freeform, funcs: {hidden: '!SelectedDocType(this.toolType, this.expertMode)'},                  width: 30,  scripts: { onClick: 'prevKeyFrame(_readOnly_)'}},
             { title: "Num",     icon:"", toolTip: "Frame # (click to toggle edit mode)",btnType: ButtonType.TextButton,   expertMode: true,  toolType:CollectionViewType.Freeform, funcs: {hidden: '!SelectedDocType(this.toolType, this.expertMode)', buttonText: 'selectedDocs()?.lastElement()?.currentFrame?.toString()'}, width: 20, scripts: { onClick: '{ return curKeyFrame(_readOnly_);}'}},
@@ -851,17 +851,17 @@ pie title Minerals in my tap water
             { title: "Chat",    icon: "lightbulb",     toolTip: "Toggle Chat Assistant",btnType: ButtonType.ToggleButton, expertMode: false, toolType:"toggle-chat",               funcs: {},                                                                            width: 30,  scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'} },
             { title: "Filter",  icon: "=",             toolTip: "Filter cards by tags", btnType: ButtonType.MultiToggleButton, 
                                                                                         subMenu: this.filterTools(),      expertMode: false, toolType:DocumentType.COL,            funcs: {hidden: '!SelectedDocType(this.toolType, this.expertMode)'},ignoreClick:true, width: 30},
-            { title: "Sort",    icon: "Sort",          toolTip: "Sort Documents",       subMenu: this.sortTools(),        expertMode: false, toolType:DocumentType.COL,            funcs: {hidden: `!SelectedDocType(this.toolType, this.expertMode)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, // Always available
-            { title: "Text",    icon: "Text",          toolTip: "Text functions",       subMenu: this.textTools(),        expertMode: false, toolType:DocumentType.RTF,            funcs: {                                                            linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, // Always available
-            { title: "Ink",     icon: "Ink",           toolTip: "Ink functions",        subMenu: this.inkTools(),         expertMode: false, toolType:DocumentType.INK,            funcs: {hidden: `IsExploreMode()`,                                  linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`}, scripts: { onClick: 'setInkToolDefaults()'} }, // Always available
-            { title: "Doc",     icon: "Doc",           toolTip: "Freeform Doc tools",   subMenu: this.freeTools(),        expertMode: false, toolType:CollectionViewType.Freeform, funcs: {hidden: `!SelectedDocType(this.toolType, this.expertMode, true)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, // Always available
-            { title: "View",    icon: "View",          toolTip: "View tools",           subMenu: this.viewTools(),        expertMode: false, toolType:DocumentType.COL,            funcs: {hidden: `!SelectedDocType(this.toolType, this.expertMode)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, // Always available
-            { title: "Stack",   icon: "View",          toolTip: "Stacking tools",       subMenu: this.stackTools(),       expertMode: false, toolType:CollectionViewType.Stacking, funcs: {hidden: `!SelectedDocType(this.toolType, this.expertMode)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, // Always available
+            { title: "Sort",    icon: "Sort",          toolTip: "Sort Documents",       subMenu: this.sortTools(),        expertMode: false, toolType:DocumentType.COL,            funcs: {hidden: `!SelectedDocType(this.toolType, this.expertMode)`, linearView_isOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, // Always available
+            { title: "Text",    icon: "Text",          toolTip: "Text functions",       subMenu: this.textTools(),        expertMode: false, toolType:DocumentType.RTF,            funcs: {                                                            linearView_isOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, // Always available
+            { title: "Ink",     icon: "Ink",           toolTip: "Ink functions",        subMenu: this.inkTools(),         expertMode: false, toolType:DocumentType.INK,            funcs: {hidden: `IsExploreMode()`,                                  linearView_isOpen: `SelectedDocType(this.toolType, this.expertMode)`}, scripts: { onClick: 'setInkToolDefaults()'} }, // Always available
+            { title: "Doc",     icon: "Doc",           toolTip: "Freeform Doc tools",   subMenu: this.freeTools(),        expertMode: false, toolType:CollectionViewType.Freeform, funcs: {hidden: `!SelectedDocType(this.toolType, this.expertMode, true)`, linearView_isOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, // Always available
+            { title: "View",    icon: "View",          toolTip: "View tools",           subMenu: this.viewTools(),        expertMode: false, toolType:DocumentType.COL,            funcs: {hidden: `!SelectedDocType(this.toolType, this.expertMode)`, linearView_isOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, // Always available
+            { title: "Stack",   icon: "View",          toolTip: "Stacking tools",       subMenu: this.stackTools(),       expertMode: false, toolType:CollectionViewType.Stacking, funcs: {hidden: `!SelectedDocType(this.toolType, this.expertMode)`, linearView_isOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, // Always available
                    
-            { title: "Web",     icon: "Web",           toolTip: "Web functions",        subMenu: this.webTools(),         expertMode: false, toolType:DocumentType.WEB,            funcs: {hidden: `!SelectedDocType(this.toolType, this.expertMode)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, // Only when Web is selected
-            { title: "Video",   icon: "Video",         toolTip: "Video functions",      subMenu: this.videoTools(),       expertMode: false, toolType:DocumentType.VID,            funcs: {hidden: `!SelectedDocType(this.toolType, this.expertMode)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, // Only when video is selected
-            { title: "Image",   icon: "Image",         toolTip: "Image functions",      subMenu: this.imageTools(),       expertMode: false, toolType:DocumentType.IMG,            funcs: {hidden: `!SelectedDocType(this.toolType, this.expertMode)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, // Only when image is selected
-            { title: "Schema",  icon: "Schema",        toolTip: "Schema functions",     subMenu: this.schemaTools(),      expertMode: false, toolType:CollectionViewType.Schema,   funcs: {hidden: `!SelectedDocType(this.toolType, this.expertMode)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`}, linearBtnWidth:58 }, // Only when Schema is selected
+            { title: "Web",     icon: "Web",           toolTip: "Web functions",        subMenu: this.webTools(),         expertMode: false, toolType:DocumentType.WEB,            funcs: {hidden: `!SelectedDocType(this.toolType, this.expertMode)`, linearView_isOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, // Only when Web is selected
+            { title: "Video",   icon: "Video",         toolTip: "Video functions",      subMenu: this.videoTools(),       expertMode: false, toolType:DocumentType.VID,            funcs: {hidden: `!SelectedDocType(this.toolType, this.expertMode)`, linearView_isOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, // Only when video is selected
+            { title: "Image",   icon: "Image",         toolTip: "Image functions",      subMenu: this.imageTools(),       expertMode: false, toolType:DocumentType.IMG,            funcs: {hidden: `!SelectedDocType(this.toolType, this.expertMode)`, linearView_isOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, // Only when image is selected
+            { title: "Schema",  icon: "Schema",        toolTip: "Schema functions",     subMenu: this.schemaTools(),      expertMode: false, toolType:CollectionViewType.Schema,   funcs: {hidden: `!SelectedDocType(this.toolType, this.expertMode)`, linearView_isOpen: `SelectedDocType(this.toolType, this.expertMode)`}, linearView_btnWidth:58 }, // Only when Schema is selected
          ];
     }
 
@@ -872,7 +872,7 @@ pie title Minerals in my tap water
             ...OmitKeys(params, ["scripts", "funcs", "subMenu"]).omit,
             color: Colors.WHITE, 
             _nativeWidth: params.width ?? 30, _width: params.width ?? 30,
-            _height: 30, _nativeHeight: 30, linearBtnWidth: params.linearBtnWidth,
+            _height: 30, _nativeHeight: 30, linearView_btnWidth: params.linearView_btnWidth,
             toolType: params.toolType, expertMode: params.expertMode,
             _dragOnlyWithinContainer: true, _lockedPosition: true,
             embedContainer: btnContainer
@@ -891,9 +891,9 @@ pie title Minerals in my tap water
             return this.setupContextMenuButton(params, menuBtnDoc, menuDoc);
         }  
         // linear view
-        const reqdSubMenuOpts = { ...OmitKeys(params, ["scripts", "funcs", "subMenu"]).omit, undoIgnoreFields: new List<string>(['width', "linearView_IsOpen"]),
+        const reqdSubMenuOpts = { ...OmitKeys(params, ["scripts", "funcs", "subMenu"]).omit, undoIgnoreFields: new List<string>(['width', "linearView_isOpen"]),
             childDontRegisterViews: true, flexGap: 0, _height: 30, _width: 30, ignoreClick: !params.scripts?.onClick,
-            linearView_SubMenu: true, linearView_Expandable: true, embedContainer: menuDoc};
+            linearView_expandable: true, embedContainer: menuDoc};
         
         const items = (menuBtn?:Doc) => !menuBtn ? [] : subMenu.map(sub => this.setupContextMenuBtn(sub, menuBtn) );
         const creator = params.btnType === ButtonType.MultiToggleButton ? this.multiToggleList : this.linearButtonList;
@@ -905,7 +905,7 @@ pie title Minerals in my tap water
 
     /// Initializes all the default buttons for the top bar context menu
     static setupContextMenuButtons(doc: Doc, field="myContextMenuBtns") {
-        const reqdCtxtOpts:DocumentOptions = { title: "context menu buttons", undoIgnoreFields:new List<string>(['width', "linearView_IsOpen"]), flexGap: 0, childDragAction: dropActionType.embed, childDontRegisterViews: true,  linearView_IsOpen: true, ignoreClick: true, linearView_Expandable: false, _height: 35 };
+        const reqdCtxtOpts:DocumentOptions = { title: "context menu buttons", undoIgnoreFields:new List<string>(['width', "linearView_isOpen"]), flexGap: 0, childDragAction: dropActionType.embed, childDontRegisterViews: true,  linearView_isOpen: true, ignoreClick: true, linearView_expandable: false, _height: 35 };
         const ctxtMenuBtnsDoc = DocUtils.AssignDocField(doc, field, (opts, items) => this.linearButtonList(opts, items??[]), reqdCtxtOpts, undefined);
         const ctxtMenuBtns = CurrentUserUtils.contextMenuTools().map(params => this.setupContextMenuBtn(params, ctxtMenuBtnsDoc) );
         return DocUtils.AssignOpts(ctxtMenuBtnsDoc, reqdCtxtOpts, ctxtMenuBtns);
@@ -932,7 +932,7 @@ pie title Minerals in my tap water
         const btns = btnDescs.map(desc => dockBtn({_width: desc.opts.width??30, _height: 30, defaultDoubleClick: 'ignore', undoIgnoreFields: new List<string>(['opacity']), _dragOnlyWithinContainer: true, ...desc.opts}, desc.scripts, desc.funcs));
         const dockBtnsReqdOpts:DocumentOptions = {
             title: "docked buttons", _height: 40, flexGap: 0, layout_boxShadow: "standard", childDragAction: dropActionType.move,
-            childDontRegisterViews: true, linearView_IsOpen: true, linearView_Expandable: false, ignoreClick: true
+            childDontRegisterViews: true, linearView_isOpen: true, linearView_expandable: false, ignoreClick: true
         };
         return DocUtils.AssignDocField(doc, field, (opts, items) => this.linearButtonList(opts, items??[]), dockBtnsReqdOpts, btns);
     }
diff --git a/src/client/util/LinkManager.ts b/src/client/util/LinkManager.ts
index d8e0c4cbe..6461605a6 100644
--- a/src/client/util/LinkManager.ts
+++ b/src/client/util/LinkManager.ts
@@ -265,10 +265,10 @@ export function UPDATE_SERVER_CACHE() {
     cacheDocumentIds = newCacheUpdate;
 
     // print out cached docs
-    Doc.MyDockedBtns?.linearView_IsOpen && console.log('Set cached docs = ');
+    Doc.MyDockedBtns?.linearView_isOpen && console.log('Set cached docs = ');
     const isFiltered = filtered.filter(doc => !Doc.IsSystem(doc));
     const strings = isFiltered.map(doc => StrCast(doc.title) + ' ' + (Doc.IsDataProto(doc) ? '(data)' : '(embedding)'));
-    Doc.MyDockedBtns?.linearView_IsOpen && strings.sort().forEach((str, i) => console.log(i.toString() + ' ' + str));
+    Doc.MyDockedBtns?.linearView_isOpen && strings.sort().forEach((str, i) => console.log(i.toString() + ' ' + str));
 
     rp.post(ClientUtils.prepend('/setCacheDocumentIds'), {
         body: {
diff --git a/src/client/views/InkingStroke.tsx b/src/client/views/InkingStroke.tsx
index 0136f6abe..253db08de 100644
--- a/src/client/views/InkingStroke.tsx
+++ b/src/client/views/InkingStroke.tsx
@@ -497,8 +497,8 @@ export class InkingStroke extends ViewBoxAnnotatableComponent<FieldViewProps>()
                             {...this._props}
                             setHeight={undefined}
                             setContentViewBox={this.setSubContentView} // this makes the inkingStroke the "dominant" component - ie, it will show the inking UI when selected (not text)
-                            yPadding={10}
-                            xPadding={10}
+                            yMargin={10}
+                            xMargin={10}
                             fieldKey="text"
                             // dontRegisterView={true}
                             noSidebar
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index ad6bb09c7..c49b7e6de 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -173,7 +173,7 @@ export class MainView extends ObservableReactComponent<object> {
             views => views.length > 1 && document.activeElement instanceof HTMLElement && document.activeElement?.blur()
         );
         reaction(
-            () => Doc.MyDockedBtns?.linearView_IsOpen,
+            () => Doc.MyDockedBtns?.linearView_isOpen,
             open => SnappingManager.SetPrintToConsole(!!open)
         );
         const scriptTag = document.createElement('script');
diff --git a/src/client/views/ObservableReactComponent.tsx b/src/client/views/ObservableReactComponent.tsx
index 2290516dc..cf4bf991e 100644
--- a/src/client/views/ObservableReactComponent.tsx
+++ b/src/client/views/ObservableReactComponent.tsx
@@ -16,15 +16,13 @@ export abstract class ObservableReactComponent<T> extends React.Component<T, obj
         makeObservable(this);
     }
     __passiveWheel: HTMLElement | null = null;
-    _isContentActive: () => boolean | undefined = () => false;
+    __isContentActive: () => boolean | undefined = () => false;
 
     /**
      * default method to stop wheel events from bubbling up to parent components.
      * @param e
      */
-    onPassiveWheel = (e: WheelEvent) => {
-        if (this._isContentActive?.()) e.stopPropagation();
-    };
+    onPassiveWheel = (e: WheelEvent) => this.__isContentActive?.() && e.stopPropagation();
 
     /**
      * This fixes the problem where a component uses wheel events to scroll, but is nested inside another component that
@@ -36,7 +34,7 @@ export abstract class ObservableReactComponent<T> extends React.Component<T, obj
      * @param onPassiveWheel an optional function to call to handle the wheel event (and block its propagation. If omitted, the event won't propagate.
      */
     fixWheelEvents = (ele: HTMLElement | null, isContentActive: () => boolean | undefined, onPassiveWheel?: (e: WheelEvent) => void) => {
-        this._isContentActive = isContentActive;
+        this.__isContentActive = isContentActive;
         this.__passiveWheel?.removeEventListener('wheel', onPassiveWheel ?? this.onPassiveWheel);
         this.__passiveWheel = ele;
         ele?.addEventListener('wheel', onPassiveWheel ?? this.onPassiveWheel, { passive: false });
diff --git a/src/client/views/PropertiesButtons.tsx b/src/client/views/PropertiesButtons.tsx
index 28566ba1d..ded342df0 100644
--- a/src/client/views/PropertiesButtons.tsx
+++ b/src/client/views/PropertiesButtons.tsx
@@ -165,7 +165,7 @@ export class PropertiesButtons extends React.Component {
     //                 // containerDoc._forceActive =
     //                 //containerDoc._freeform_fitContentsToBox =
     //                 containerDoc._isLightbox = !containerDoc._isLightbox;
-    //                 //containerDoc._xPadding = containerDoc._yPadding = containerDoc._isLightbox ? 10 : undefined;
+    //                 //containerDoc._xMargin = containerDoc._yMargin = containerDoc._isLightbox ? 10 : undefined;
     //                 const containerContents = DocListCast(dv.dataDoc[dv.props.fieldKey ?? Doc.LayoutFieldKey(containerDoc)]);
     //                 //dv.Document.onClick = ScriptField.MakeScript('{this.data = undefined; documentView.select(false)}', { documentView: 'any' });
     //                 containerContents.forEach(doc => LinkManager.Links(doc).forEach(link => (link.layout_linkDisplay = false)));
diff --git a/src/client/views/collections/CollectionCardDeckView.tsx b/src/client/views/collections/CollectionCardDeckView.tsx
index d5edc3e0b..3dc7bc515 100644
--- a/src/client/views/collections/CollectionCardDeckView.tsx
+++ b/src/client/views/collections/CollectionCardDeckView.tsx
@@ -133,7 +133,7 @@ export class CollectionCardView extends CollectionSubView() {
     }
 
     @computed get yMargin() {
-        return this._props.yPadding || NumCast(this.layoutDoc._yMargin, Math.min(5, 0.05 * this._props.PanelWidth()));
+        return this._props.yMargin || NumCast(this.layoutDoc._yMargin, Math.min(5, 0.05 * this._props.PanelWidth()));
     }
 
     @computed get cardDeckWidth() {
diff --git a/src/client/views/collections/CollectionCarouselView.tsx b/src/client/views/collections/CollectionCarouselView.tsx
index ac1981012..3c5bc10de 100644
--- a/src/client/views/collections/CollectionCarouselView.tsx
+++ b/src/client/views/collections/CollectionCarouselView.tsx
@@ -206,7 +206,7 @@ export class CollectionCarouselView extends CollectionSubView() {
                             marginLeft: this.captionMarginX,
                             width: `calc(100% - ${this.captionMarginX * 2}px)`,
                         }}>
-                        <FormattedTextBox xPadding={10} yPadding={10} {...captionProps} fieldKey={carouselShowsCaptions} styleProvider={this.captionStyleProvider} Document={this.curDoc()} TemplateDataDocument={undefined} />
+                        <FormattedTextBox xMargin={10} yMargin={10} {...captionProps} fieldKey={carouselShowsCaptions} styleProvider={this.captionStyleProvider} Document={this.curDoc()} TemplateDataDocument={undefined} />
                     </div>
                 )}
             </>
diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx
index be570564b..25a222cbb 100644
--- a/src/client/views/collections/CollectionStackingView.tsx
+++ b/src/client/views/collections/CollectionStackingView.tsx
@@ -89,7 +89,7 @@ export class CollectionStackingView extends CollectionSubView<Partial<collection
         return NumCast(this.layoutDoc._xMargin, Math.max(3, 0.05 * this._props.PanelWidth()));
     }
     @computed get yMargin() {
-        return this._props.yPadding || NumCast(this.layoutDoc._yMargin, Math.min(5, 0.05 * this._props.PanelWidth()));
+        return this._props.yMargin || NumCast(this.layoutDoc._yMargin, Math.min(5, 0.05 * this._props.PanelWidth()));
     }
 
     @computed get gridGap() {
@@ -381,8 +381,8 @@ export class CollectionStackingView extends CollectionSubView<Partial<collection
                 hideDecorations={this._props.childHideDecorations}
                 childFiltersByRanges={this.childDocRangeFilters}
                 searchFilterDocs={this.searchFilterDocs}
-                xPadding={NumCast(this.layoutDoc._childXPadding, this._props.childXPadding)}
-                yPadding={NumCast(this.layoutDoc._childYPadding, this._props.childYPadding)}
+                xMargin={NumCast(this.layoutDoc._childXPadding, this._props.childXPadding)}
+                yMargin={NumCast(this.layoutDoc._childYPadding, this._props.childYPadding)}
                 rejectDrop={this._props.childRejectDrop}
                 addDocument={this._props.addDocument}
                 moveDocument={this._props.moveDocument}
diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx
index 4348bc7dc..c4373aaa7 100644
--- a/src/client/views/collections/TabDocView.tsx
+++ b/src/client/views/collections/TabDocView.tsx
@@ -163,8 +163,8 @@ export class TabMinimapView extends ObservableReactComponent<TabMinimapViewProps
                     childFiltersByRanges={CollectionDockingView.Instance?.childDocRangeFilters ?? returnEmptyFilter}
                     searchFilterDocs={CollectionDockingView.Instance?.searchFilterDocs ?? returnEmptyDoclist}
                     fitContentsToBox={returnTrue}
-                    xPadding={this.xPadding}
-                    yPadding={this.yPadding}
+                    xMargin={this.xPadding}
+                    yMargin={this.yPadding}
                 />
                 <div className="miniOverlay" onPointerDown={this.miniDown}>
                     <TabMiniThumb miniLeft={miniLeft} miniTop={miniTop} miniWidth={miniWidth} miniHeight={miniHeight} />
diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx
index fb2d0955f..5b2f1ff81 100644
--- a/src/client/views/collections/TreeView.tsx
+++ b/src/client/views/collections/TreeView.tsx
@@ -1042,8 +1042,8 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> {
                 disableBrushing={this.treeView._props.disableBrushing}
                 hideLinkButton={BoolCast(this.treeView.Document.childHideLinkButton)}
                 dontRegisterView={BoolCast(this.treeView.Document.childDontRegisterViews, this._props.dontRegisterView)}
-                xPadding={NumCast(this.treeView.Document.childXPadding, this.treeView._props.childXPadding)}
-                yPadding={NumCast(this.treeView.Document.childYPadding, this.treeView._props.childYPadding)}
+                xMargin={NumCast(this.treeView.Document.childXPadding, this.treeView._props.childXPadding)}
+                yMargin={NumCast(this.treeView.Document.childYPadding, this.treeView._props.childYPadding)}
                 childFilters={returnEmptyFilter}
                 childFiltersByRanges={returnEmptyFilter}
                 searchFilterDocs={returnEmptyDoclist}
@@ -1148,8 +1148,8 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> {
                 moveDocument={this.move}
                 removeDocument={this._props.removeDoc}
                 whenChildContentsActiveChanged={this._props.whenChildContentsActiveChanged}
-                xPadding={NumCast(this.treeView.Document.childXPadding, this.treeView._props.childXPadding)}
-                yPadding={NumCast(this.treeView.Document.childYPadding, this.treeView._props.childYPadding)}
+                xMargin={NumCast(this.treeView.Document.childXPadding, this.treeView._props.childXPadding)}
+                yMargin={NumCast(this.treeView.Document.childYPadding, this.treeView._props.childYPadding)}
                 addDocTab={this._props.addDocTab}
                 pinToPres={this.treeView._props.pinToPres}
                 disableBrushing={this.treeView._props.disableBrushing}
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 2364fd74a..05958e6b9 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -256,8 +256,8 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
     override contentBounds = () => {
         const { x, y, r, b } = aggregateBounds(
             this._layoutElements.filter(e => e.bounds?.width && !e.bounds.z).map(e => e.bounds!),
-            NumCast(this.layoutDoc._xPadding, NumCast(this.layoutDoc._xMargin, this._props.xPadding ?? 0)),
-            NumCast(this.layoutDoc._yPadding, NumCast(this.layoutDoc._yMargin, this._props.yPadding ?? 0))
+            NumCast(this.layoutDoc._xMargin, this._props.xMargin ?? 0),
+            NumCast(this.layoutDoc._yMargin, this._props.yMargin ?? 0)
         );
         const [width, height] = [r - x, b - y];
         return {
@@ -1775,7 +1775,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
                     () => {
                         if (this.Document.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._xPadding), NumCast(this.layoutDoc._yPadding));
+                            return aggregateBounds(clist, NumCast(this.layoutDoc._xMargin), NumCast(this.layoutDoc._yMargin));
                         }
                         return undefined;
                     },
diff --git a/src/client/views/collections/collectionGrid/CollectionGridView.tsx b/src/client/views/collections/collectionGrid/CollectionGridView.tsx
index 1d5e70be7..3320eacb6 100644
--- a/src/client/views/collections/collectionGrid/CollectionGridView.tsx
+++ b/src/client/views/collections/collectionGrid/CollectionGridView.tsx
@@ -58,7 +58,7 @@ export class CollectionGridView extends CollectionSubView() {
         return NumCast(this.layoutDoc._xMargin, Math.max(3, 0.05 * this._props.PanelWidth()));
     }
     @computed get yMargin() {
-        return this._props.yPadding || NumCast(this.layoutDoc._yMargin, Math.min(5, 0.05 * this._props.PanelWidth()));
+        return this._props.yMargin || NumCast(this.layoutDoc._yMargin, Math.min(5, 0.05 * this._props.PanelWidth()));
     }
     @computed get gridGap() {
         return NumCast(this.Document._gridGap, 10);
diff --git a/src/client/views/collections/collectionLinear/CollectionLinearView.tsx b/src/client/views/collections/collectionLinear/CollectionLinearView.tsx
index 3c2a99b1e..d0a1e6f0d 100644
--- a/src/client/views/collections/collectionLinear/CollectionLinearView.tsx
+++ b/src/client/views/collections/collectionLinear/CollectionLinearView.tsx
@@ -27,7 +27,7 @@ import './CollectionLinearView.scss';
 /**
  * CollectionLinearView is the class for rendering the horizontal collection
  * of documents, it useful for horizontal menus. It can either be expandable
- * or not using the linearView_Expandable field.
+ * or not using the linearView_expandable field.
  * It is used in the following locations:
  * - It is used in the popup menu on the bottom left (see docButtons() in MainView.tsx)
  * - It is used for the context sensitive toolbar at the top (see contMenuButtons() in CollectionMenu.tsx)
@@ -52,7 +52,7 @@ export class CollectionLinearView extends CollectionSubView() {
 
     componentDidMount() {
         this._widthDisposer = reaction(
-            () => 5 + NumCast(this.dataDoc.linearBtnWidth, this.dimension()) + (this.layoutDoc.linearView_IsOpen ? this.childDocs.filter(doc => !doc.hidden).reduce((tot, doc) => (NumCast(doc._width) || this.dimension()) + tot + 4, 0) : 0),
+            () => 5 + NumCast(this.dataDoc.linearView_btnWidth, this.dimension()) + (this.layoutDoc.linearView_isOpen ? this.childDocs.filter(doc => !doc.hidden).reduce((tot, doc) => (NumCast(doc._width) || this.dimension()) + tot + 4, 0) : 0),
             width => {
                 this.childDocs.length && (this.layoutDoc._width = width);
             },
@@ -208,7 +208,7 @@ export class CollectionLinearView extends CollectionSubView() {
     render() {
         const flexDir = StrCast(this.Document.flexDirection); // Specify direction of linear view content
         const flexGap = NumCast(this.Document.flexGap); // Specify the gap between linear view content
-        const isExpanded = BoolCast(this.layoutDoc.linearView_IsOpen);
+        const isExpanded = BoolCast(this.layoutDoc.linearView_isOpen);
 
         const menuOpener = (
             <Toggle
@@ -219,9 +219,9 @@ export class CollectionLinearView extends CollectionSubView() {
                 type={Type.TERT}
                 onPointerDown={e => e.stopPropagation()}
                 toggleType={ToggleType.BUTTON}
-                toggleStatus={BoolCast(this.layoutDoc.linearView_IsOpen)}
+                toggleStatus={BoolCast(this.layoutDoc.linearView_isOpen)}
                 onClick={() => {
-                    this.layoutDoc.linearView_IsOpen = !isExpanded;
+                    this.layoutDoc.linearView_isOpen = !isExpanded;
                     ScriptCast(this.Document.onClick)?.script.run({ this: this.Document }, console.log);
                 }}
                 tooltip={isExpanded ? 'Close' : 'Open'}
@@ -231,10 +231,10 @@ export class CollectionLinearView extends CollectionSubView() {
         );
 
         return (
-            <div className={`collectionLinearView-outer ${this.layoutDoc.linearView_SubMenu}`} style={{ backgroundColor: this.layoutDoc.linearView_IsOpen ? undefined : 'transparent' }}>
+            <div className="collectionLinearView-outer" style={{ backgroundColor: this.layoutDoc.linearView_isOpen ? undefined : 'transparent' }}>
                 <div className="collectionLinearView" ref={this.createDashEventsTarget} onContextMenu={this.myContextMenu} style={{ minHeight: this.dimension(), pointerEvents: 'all' }}>
-                    {!this.layoutDoc.linearView_Expandable ? null : menuOpener}
-                    {!this.layoutDoc.linearView_IsOpen ? null : (
+                    {!this.layoutDoc.linearView_expandable ? null : menuOpener}
+                    {!this.layoutDoc.linearView_isOpen && this.layoutDoc.linearView_expandable ? null : (
                         <div
                             className="collectionLinearView-content"
                             style={{
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 284014e54..d756f3226 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -913,8 +913,8 @@ export class DocumentViewInternal extends DocComponent<DocumentViewProps & Field
                 }}>
                 <FormattedTextBox
                     {...this._props}
-                    yPadding={10}
-                    xPadding={10}
+                    yMargin={10}
+                    xMargin={10}
                     fieldKey={this.showCaption}
                     styleProvider={this.captionStyleProvider}
                     dontRegisterView
diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx
index a6872f8dc..f6b405a43 100644
--- a/src/client/views/nodes/FieldView.tsx
+++ b/src/client/views/nodes/FieldView.tsx
@@ -52,8 +52,8 @@ export interface FieldViewSharedProps {
     renderDepth: number;
     scriptContext?: unknown; // can be assigned anything and will be passed as 'scriptContext' to any OnClick script that executes on this document
     screenXPadding?: (view: DocumentView | undefined) => number; // padding in screen space coordinates (used by text box to reflow around UI buttons in carouselView)
-    xPadding?: number;
-    yPadding?: number;
+    xMargin?: number;
+    yMargin?: number;
     dontRegisterView?: boolean;
     dropAction?: dropActionType;
     dragAction?: dropActionType;
diff --git a/src/client/views/nodes/LabelBox.tsx b/src/client/views/nodes/LabelBox.tsx
index b08ed84b7..f901c32fc 100644
--- a/src/client/views/nodes/LabelBox.tsx
+++ b/src/client/views/nodes/LabelBox.tsx
@@ -181,10 +181,10 @@ export class LabelBox extends ViewBoxBaseComponent<FieldViewProps>() {
                         fontFamily: StrCast(this.layoutDoc._text_fontFamily, StrCast(Doc.UserDoc().fontFamily)) || 'inherit',
                         letterSpacing: StrCast(this.layoutDoc.letterSpacing),
                         textTransform: StrCast(this.layoutDoc[this.fieldKey + '_transform']) as Property.TextTransform,
-                        paddingLeft: NumCast(this.layoutDoc._xPadding),
-                        paddingRight: NumCast(this.layoutDoc._xPadding),
-                        paddingTop: NumCast(this.layoutDoc._yPadding),
-                        paddingBottom: NumCast(this.layoutDoc._yPadding),
+                        paddingLeft: NumCast(this.layoutDoc._xMargin),
+                        paddingRight: NumCast(this.layoutDoc._xMargin),
+                        paddingTop: NumCast(this.layoutDoc._yMargin),
+                        paddingBottom: NumCast(this.layoutDoc._yMargin),
                         width: this._props.PanelWidth(),
                         height: this._props.PanelHeight(),
                         whiteSpace: boxParams.multiLine ? 'pre-wrap' : 'pre',
@@ -192,8 +192,8 @@ export class LabelBox extends ViewBoxBaseComponent<FieldViewProps>() {
                     <div
                         key={this._forceRerender}
                         style={{
-                            width: this._props.PanelWidth() - 2 * NumCast(this.layoutDoc._xPadding),
-                            height: this._props.PanelHeight() - 2 * NumCast(this.layoutDoc._yPadding),
+                            width: this._props.PanelWidth() - 2 * NumCast(this.layoutDoc._xMargin),
+                            height: this._props.PanelHeight() - 2 * NumCast(this.layoutDoc._yMargin),
                             outline: 'unset !important',
                         }}
                         onKeyDown={e => {
diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx
index 83c44c80f..55e6d5596 100644
--- a/src/client/views/nodes/PDFBox.tsx
+++ b/src/client/views/nodes/PDFBox.tsx
@@ -557,8 +557,8 @@ export class PDFBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
                         NativeHeight={this.sidebarNativeHeightFunc}
                         PanelHeight={this._props.PanelHeight}
                         PanelWidth={this.sidebarWidth}
-                        xPadding={0}
-                        yPadding={0}
+                        xMargin={0}
+                        yMargin={0}
                         viewField={this.SidebarKey}
                         isAnnotationOverlay={false}
                         originTopLeft
diff --git a/src/client/views/nodes/ScreenshotBox.tsx b/src/client/views/nodes/ScreenshotBox.tsx
index 4f02d68d6..603dcad5c 100644
--- a/src/client/views/nodes/ScreenshotBox.tsx
+++ b/src/client/views/nodes/ScreenshotBox.tsx
@@ -335,8 +335,8 @@ export class ScreenshotBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
                                 select={emptyFunction}
                                 isContentActive={emptyFunction}
                                 NativeDimScaling={returnOne}
-                                xPadding={25}
-                                yPadding={10}
+                                xMargin={25}
+                                yMargin={10}
                                 whenChildContentsActiveChanged={emptyFunction}
                                 removeDocument={returnFalse}
                                 moveDocument={returnFalse}
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index c51f6c38b..abf44b54d 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -1164,7 +1164,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
     };
 
     @computed get tagsHeight() {
-        return this.DocumentView?.().showTags ? Math.max(0, 20 - Math.max(this._props.yPadding ?? 0, NumCast(this.layoutDoc._yMargin))) * this.ScreenToLocalBoxXf().Scale : 0;
+        return this.DocumentView?.().showTags ? Math.max(0, 20 - Math.max(this._props.yMargin ?? 0, NumCast(this.layoutDoc._yMargin))) * this.ScreenToLocalBoxXf().Scale : 0;
     }
 
     @computed get contentScaling() {
@@ -1880,7 +1880,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
         }
     };
     tryUpdateScrollHeight = () => {
-        const margins = 2 * NumCast(this.layoutDoc._yMargin, this._props.yPadding || 0);
+        const margins = 2 * NumCast(this.layoutDoc._yMargin, this._props.yMargin || 0);
         const children = this.ProseRef?.children.length ? Array.from(this.ProseRef.children[0].children) : undefined;
         if (this.EditorView && children && !SnappingManager.IsDragging) {
             const getChildrenHeights = (kids: Element[] | undefined) => kids?.reduce((p, child) => p + toHgt(child), margins) ?? 0;
@@ -2112,8 +2112,8 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
         const rounded = StrCast(this.layoutDoc._layout_borderRounding) === '100%' ? '-rounded' : '';
         setTimeout(() => !this._props.isContentActive() && FormattedTextBoxComment.textBox === this && FormattedTextBoxComment.Hide);
 
-        const paddingX = Math.max(NumCast(this.layoutDoc._xMargin), 0, this._props.xPadding ?? 0, this._props.screenXPadding?.(this._props.DocumentView?.()) ?? 0);
-        const paddingY = Math.max(NumCast(this.layoutDoc._yMargin), 0, this._props.yPadding ?? 0); // prettier-ignore
+        const paddingX = Math.max(NumCast(this.layoutDoc._xMargin), 0, this._props.xMargin ?? 0, this._props.screenXPadding?.(this._props.DocumentView?.()) ?? 0);
+        const paddingY = Math.max(NumCast(this.layoutDoc._yMargin), 0, this._props.yMargin ?? 0); // prettier-ignore
         const styleFromLayout = styleFromLayoutString(this.Document, this._props, scale); // this converts any expressions in the format string to style props.  e.g., <FormattedTextBox height='{this._header_height}px' >
         return this.isLabel ? (
             <LabelBox {...this._props} />
diff --git a/src/client/views/nodes/trails/PresSlideBox.tsx b/src/client/views/nodes/trails/PresSlideBox.tsx
index 3dbb3da88..3440b29dd 100644
--- a/src/client/views/nodes/trails/PresSlideBox.tsx
+++ b/src/client/views/nodes/trails/PresSlideBox.tsx
@@ -559,10 +559,10 @@ export class PresSlideBox extends ViewBoxBaseComponent<FieldViewProps>() {
                 style={{
                     backgroundColor: presColorBool ? (isSelected ? 'rgba(250,250,250,0.3)' : 'transparent') : isSelected ? Colors.LIGHT_BLUE : 'transparent',
                     opacity: this._dragging ? 0.3 : 1,
-                    paddingLeft: NumCast(this.layoutDoc._xPadding, this._props.xPadding),
-                    paddingRight: NumCast(this.layoutDoc._xPadding, this._props.xPadding),
-                    paddingTop: NumCast(this.layoutDoc._yPadding, this._props.yPadding),
-                    paddingBottom: NumCast(this.layoutDoc._yPadding, this._props.yPadding),
+                    paddingLeft: NumCast(this.layoutDoc._xMargin, this._props._xMargin),
+                    paddingRight: NumCast(this.layoutDoc._xMargin, this._props._xMargin),
+                    paddingTop: NumCast(this.layoutDoc._yPadding, this._props.yMargin),
+                    paddingBottom: NumCast(this.layoutDoc._yPadding, this._props.yMargin),
                 }}
                 onDoubleClick={action(() => {
                     this.toggleProperties();
diff --git a/src/fields/documentSchemas.ts b/src/fields/documentSchemas.ts
index b27816f55..df832d088 100644
--- a/src/fields/documentSchemas.ts
+++ b/src/fields/documentSchemas.ts
@@ -35,8 +35,6 @@ export const documentSchema = createSchema({
     _nativeHeight: 'number', // "
     _width: 'number', // width of document in its container's coordinate system
     _height: 'number', // "
-    _xPadding: 'number', // pixels of padding on left/right of collectionfreeformview contents when freeform_fitContentsToBox is set
-    _yPadding: 'number', // pixels of padding on top/bottom of collectionfreeformview contents when freeform_fitContentsToBox is set
     _xMargin: 'number', // margin added on left/right of most documents to add separation from their container
     _yMargin: 'number', // margin added on top/bottom of most documents to add separation from their container
     _overflow: 'string', // sets overflow behvavior for CollectionFreeForm views
-- 
cgit v1.2.3-70-g09d2

