From 0bd3d85f186a724d4ef0c5bb58d57ee7b2627c86 Mon Sep 17 00:00:00 2001 From: Alain Dumesny Date: Sun, 23 Mar 2025 19:02:30 -0700 Subject: [PATCH] more CSS var cleanup * further cleanup and fixed for #2997 --- doc/CHANGES.md | 2 + src/gridstack.scss | 55 ++++++++--------------- src/gridstack.ts | 110 +++++++++++++-------------------------------- 3 files changed, 51 insertions(+), 116 deletions(-) diff --git a/doc/CHANGES.md b/doc/CHANGES.md index 63e42686..811d3d58 100644 --- a/doc/CHANGES.md +++ b/doc/CHANGES.md @@ -5,6 +5,7 @@ Change log **Table of Contents** *generated with [DocToc](http://doctoc.herokuapp.com/)* +- [11.5.0-dev (TBD)](#1150-dev-tbd) - [11.5.0 (2025-03-16)](#1150-2025-03-16) - [11.4.0 (2025-02-27)](#1140-2025-02-27) - [11.3.0 (2025-01-26)](#1130-2025-01-26) @@ -122,6 +123,7 @@ Change log ## 11.5.0-dev (TBD) +* feat: [#2854](https://github.com/gridstack/gridstack.js/pull/2854) Removed dynamic stylesheet and migrated to CSS vars. Thank you [lmartorella](https://github.com/lmartorella) ## 11.5.0 (2025-03-16) * feat: [#2975](https://github.com/gridstack/gridstack.js/pull/2975) `prepareDragDrop(el, force)` option to force re-creation of the drag&drop event binding diff --git a/src/gridstack.scss b/src/gridstack.scss index dafb6a06..2f5f7dbb 100644 --- a/src/gridstack.scss +++ b/src/gridstack.scss @@ -55,6 +55,16 @@ $animation_speed: .3s !default; } } +.grid-stack { + > .grid-stack-item > .grid-stack-item-content, + > .grid-stack-placeholder > .placeholder-content { + top: var(--gs-item-margin-top); + right: var(--gs-item-margin-right); + bottom: var(--gs-item-margin-bottom); + left: var(--gs-item-margin-left); + } +} + .grid-stack-item { > .ui-resizable-handle { position: absolute; @@ -90,34 +100,15 @@ $animation_speed: .3s !default; @include vendor(transform, rotate(-45deg)); } - > .ui-resizable-nw { cursor: nw-resize; width: 20px; height: 20px; top: 0; } - > .ui-resizable-n { cursor: n-resize; height: 10px; top: 0; left: 25px; right: 25px; } - > .ui-resizable-ne { cursor: ne-resize; width: 20px; height: 20px; top: 0; } - > .ui-resizable-e { cursor: e-resize; width: 10px; top: 15px; bottom: 15px; } - > .ui-resizable-se { cursor: se-resize; width: 20px; height: 20px;} - > .ui-resizable-s { cursor: s-resize; height: 10px; left: 25px; bottom: 0; right: 25px; } - > .ui-resizable-sw { cursor: sw-resize; width: 20px; height: 20px;} - > .ui-resizable-w { cursor: w-resize; width: 10px; top: 15px; bottom: 15px; } + > .ui-resizable-nw { cursor: nw-resize; width: 20px; height: 20px; top: var(--gs-item-margin-top); left: var(--gs-item-margin-left); } + > .ui-resizable-n { cursor: n-resize; height: 10px; top: var(--gs-item-margin-top); left: 25px; right: 25px; } + > .ui-resizable-ne { cursor: ne-resize; width: 20px; height: 20px; top: var(--gs-item-margin-top); right: var(--gs-item-margin-right); } + > .ui-resizable-e { cursor: e-resize; width: 10px; top: 15px; bottom: 15px; right: var(--gs-item-margin-right);} + > .ui-resizable-se { cursor: se-resize; width: 20px; height: 20px; bottom: var(--gs-item-margin-bottom); right: var(--gs-item-margin-right); } + > .ui-resizable-s { cursor: s-resize; height: 10px; left: 25px; bottom: var(--gs-item-margin-bottom); right: 25px; } + > .ui-resizable-sw { cursor: sw-resize; width: 20px; height: 20px; bottom: var(--gs-item-margin-bottom); left: var(--gs-item-margin-left); } + > .ui-resizable-w { cursor: w-resize; width: 10px; top: 15px; bottom: 15px; left: var(--gs-item-margin-left); } - > .ui-resizable-n { - top: var(--gs-item-margin-top); - } - > .ui-resizable-s - , > .ui-resizable-se - , > .ui-resizable-sw { - bottom: var(--gs-item-margin-bottom); - } - > .ui-resizable-ne, - > .ui-resizable-e, - > .ui-resizable-se { - right: var(--gs-item-margin-right); - } - > .ui-resizable-nw, - > .ui-resizable-w, - > .ui-resizable-sw { - left: var(--gs-item-margin-left); - } - &.ui-draggable-dragging { &> .ui-resizable-handle { display: none !important; @@ -176,13 +167,3 @@ $animation_speed: .3s !default; width: 100%; } -.grid-stack { - > .grid-stack-item > .grid-stack-item-content, - > .grid-stack-placeholder > .placeholder-content { - top: var(--gs-item-margin-top); - right: var(--gs-item-margin-right); - bottom: var(--gs-item-margin-bottom); - left: var(--gs-item-margin-left); - } -} - diff --git a/src/gridstack.ts b/src/gridstack.ts index 82f9f7d7..bfff7753 100644 --- a/src/gridstack.ts +++ b/src/gridstack.ts @@ -364,14 +364,16 @@ export class GridStack { this._isAutoCellHeight = (opts.cellHeight === 'auto'); if (this._isAutoCellHeight || opts.cellHeight === 'initial') { // make the cell content square initially (will use resize/column event to keep it square) - this.cellHeight(undefined, false); + this.cellHeight(undefined); } else { // append unit if any are set if (typeof opts.cellHeight == 'number' && opts.cellHeightUnit && opts.cellHeightUnit !== gridDefaults.cellHeightUnit) { opts.cellHeight = opts.cellHeight + opts.cellHeightUnit; delete opts.cellHeightUnit; } - this.cellHeight(opts.cellHeight, false); + const val = opts.cellHeight; + delete opts.cellHeight; // force initial cellHeight() call to set the value + this.cellHeight(val); } // see if we need to adjust auto-hide @@ -400,13 +402,10 @@ export class GridStack { this._writePosAttr(el, n); } }); - this._updateStyles(); + this._updateContainerHeight(); } }); - // create initial global styles BEFORE loading children so resizeToContent margin can be calculated correctly - this._updateStyles(); - if (opts.auto) { this.batchUpdate(); // prevent in between re-layout #1535 TODO: this only set float=true, need to prevent collision check... this.engine._loading = true; // loading collision check @@ -422,7 +421,6 @@ export class GridStack { if (children.length) this.load(children); // don't load empty } - // if (this.engine.nodes.length) this._updateStyles(); // update based on # of children. done in engine onChange CB this.setAnimation(); // dynamic grids require pausing during drag to detect over to nest vs push @@ -851,17 +849,16 @@ export class GridStack { * * @param val the cell height. If not passed (undefined), cells content will be made square (match width minus margin), * if pass 0 the CSS will be generated by the application instead. - * @param update (Optional) if false, styles will not be updated * * @example * grid.cellHeight(100); // same as 100px * grid.cellHeight('70px'); * grid.cellHeight(grid.cellWidth() * 1.2); */ - public cellHeight(val?: numberOrString, update = true): GridStack { + public cellHeight(val?: numberOrString): GridStack { // if not called internally, check if we're changing mode - if (update && val !== undefined) { + if (val !== undefined) { if (this._isAutoCellHeight !== (val === 'auto')) { this._isAutoCellHeight = (val === 'auto'); this._updateResizeEvent(); @@ -883,11 +880,11 @@ export class GridStack { this.opts.cellHeightUnit = data.unit; this.opts.cellHeight = data.h; + // finally update var and container + this.el.style.setProperty('--gs-cell-height', `${this.opts.cellHeight}${this.opts.cellHeightUnit}`); + this._updateContainerHeight(); this.resizeToContentCheck(); - if (update) { - this._updateStyles(); - } return this; } @@ -1305,7 +1302,7 @@ export class GridStack { const opts = this.opts; if (o.acceptWidgets !== undefined) this._setupAcceptWidget(); if (o.animate !== undefined) this.setAnimation(); - if (o.cellHeight) { this.cellHeight(o.cellHeight, true); delete o.cellHeight; } + if (o.cellHeight) { this.cellHeight(o.cellHeight); delete o.cellHeight; } if (o.class && o.class !== opts.class) { if (opts.class) this.el.classList.remove(opts.class); this.el.classList.add(o.class); } if (typeof(o.column) === 'number' && !o.columnOpts) { this.column(o.column); delete o.column; }// responsive column take over actual count if (o.margin !== undefined) this.margin(o.margin); @@ -1360,7 +1357,7 @@ export class GridStack { // restore any sub-grid back if (n.subGrid?.el) { itemContent.appendChild(n.subGrid.el); - n.subGrid._updateStyles(); + n.subGrid._updateContainerHeight(); } } delete w.content; @@ -1508,7 +1505,7 @@ export class GridStack { */ public margin(value: numberOrString): GridStack { const isMultiValue = (typeof value === 'string' && value.split(' ').length > 1); - // check if we can skip re-creating our CSS file... won't check if multi values (too much hassle) + // check if we can skip... won't check if multi values (too much hassle) if (!isMultiValue) { const data = Utils.parseHeight(value); if (this.opts.marginUnit === data.unit && this.opts.margin === data.h) return; @@ -1518,8 +1515,6 @@ export class GridStack { this.opts.marginTop = this.opts.marginBottom = this.opts.marginLeft = this.opts.marginRight = undefined; this._initMargin(); - this._updateStyles(); - return this; } @@ -1598,34 +1593,6 @@ export class GridStack { return this; } - private setVar(el: HTMLElement, varName: string, varValue: string) { - el.style.setProperty(varName, varValue); - } - - /** - * Updates the CSS variables (used in CSS and inline style) for row based layout and initial margin setting, - * Variables are scoped in DOM so they works for nested grids as well - * @internal - */ - protected _updateStyles(): GridStack { - this._updateContainerHeight(); - - // if user is telling us they will handle the CSS themselves by setting heights to 0. Do we need this opts really ?? - if (this.opts.cellHeight === 0) { - return this; - } - - // Set CSS var of cell height - this.setVar(this.el, "--gs-cell-height", `${this.opts.cellHeight}${this.opts.cellHeightUnit}`); - // content margins - this.setVar(this.el, "--gs-item-margin-top", `${this.opts.marginTop}${this.opts.marginUnit}`); - this.setVar(this.el, "--gs-item-margin-bottom", `${this.opts.marginBottom}${this.opts.marginUnit}`); - this.setVar(this.el, "--gs-item-margin-right", `${this.opts.marginRight}${this.opts.marginUnit}`); - this.setVar(this.el, "--gs-item-margin-left", `${this.opts.marginLeft}${this.opts.marginUnit}`); - - return this; - } - /** @internal */ protected _updateContainerHeight(): GridStack { if (!this.engine || this.engine.batchMode) return this; @@ -1880,7 +1847,6 @@ export class GridStack { /** @internal initialize margin top/bottom/left/right and units */ protected _initMargin(): GridStack { - let data: HeightData; let margin = 0; @@ -1904,41 +1870,28 @@ export class GridStack { } // see if top/bottom/left/right need to be set as well - if (this.opts.marginTop === undefined) { - this.opts.marginTop = margin; - } else { - data = Utils.parseHeight(this.opts.marginTop); - this.opts.marginTop = data.h; - delete this.opts.margin; - } - - if (this.opts.marginBottom === undefined) { - this.opts.marginBottom = margin; - } else { - data = Utils.parseHeight(this.opts.marginBottom); - this.opts.marginBottom = data.h; - delete this.opts.margin; - } - - if (this.opts.marginRight === undefined) { - this.opts.marginRight = margin; - } else { - data = Utils.parseHeight(this.opts.marginRight); - this.opts.marginRight = data.h; - delete this.opts.margin; - } - - if (this.opts.marginLeft === undefined) { - this.opts.marginLeft = margin; - } else { - data = Utils.parseHeight(this.opts.marginLeft); - this.opts.marginLeft = data.h; - delete this.opts.margin; - } + const keys = ['marginTop', 'marginRight', 'marginBottom', 'marginLeft']; + keys.forEach(k => { + if (this.opts[k] === undefined) { + this.opts[k] = margin; + } else { + data = Utils.parseHeight(this.opts[k]); + this.opts[k] = data.h; + delete this.opts.margin; + } + }); this.opts.marginUnit = data.unit; // in case side were spelled out, use those units instead... if (this.opts.marginTop === this.opts.marginBottom && this.opts.marginLeft === this.opts.marginRight && this.opts.marginTop === this.opts.marginRight) { this.opts.margin = this.opts.marginTop; // makes it easier to check for no-ops in setMargin() } + + // finally Update the CSS margin variables (inside the cell height) */ + const style = this.el.style; + style.setProperty('--gs-item-margin-top', `${this.opts.marginTop}${this.opts.marginUnit}`); + style.setProperty('--gs-item-margin-bottom', `${this.opts.marginBottom}${this.opts.marginUnit}`); + style.setProperty('--gs-item-margin-right', `${this.opts.marginRight}${this.opts.marginUnit}`); + style.setProperty('--gs-item-margin-left', `${this.opts.marginLeft}${this.opts.marginUnit}`); + return this; } @@ -2355,7 +2308,6 @@ export class GridStack { this.resizeToContentCheck(false, node); if (subGrid) { subGrid.parentGridNode = node; - subGrid._updateStyles(); // re-create sub-grid styles now that we've moved } this._updateContainerHeight(); }