gridstack 9.5.1 → 10.0.1

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 (114) hide show
  1. package/README.md +11 -1
  2. package/angular/package.json +1 -1
  3. package/angular/projects/demo/src/app/app.component.ts +0 -2
  4. package/angular/projects/lib/package.json +1 -1
  5. package/angular/projects/lib/src/lib/base-widget.ts +1 -1
  6. package/angular/projects/lib/src/lib/gridstack-item.component.ts +1 -1
  7. package/angular/projects/lib/src/lib/gridstack.component.ts +1 -1
  8. package/angular/projects/lib/src/lib/gridstack.module.ts +1 -1
  9. package/dist/angular/esm2020/lib/base-widget.mjs +2 -2
  10. package/dist/angular/esm2020/lib/gridstack-item.component.mjs +2 -2
  11. package/dist/angular/esm2020/lib/gridstack.component.mjs +2 -2
  12. package/dist/angular/esm2020/lib/gridstack.module.mjs +2 -2
  13. package/dist/angular/fesm2015/gridstack-angular.mjs +4 -4
  14. package/dist/angular/fesm2015/gridstack-angular.mjs.map +1 -1
  15. package/dist/angular/fesm2020/gridstack-angular.mjs +4 -4
  16. package/dist/angular/fesm2020/gridstack-angular.mjs.map +1 -1
  17. package/dist/angular/lib/gridstack-item.component.d.ts +1 -1
  18. package/dist/angular/lib/gridstack.component.d.ts +1 -1
  19. package/dist/angular/package.json +1 -1
  20. package/dist/angular/src/base-widget.ts +1 -1
  21. package/dist/angular/src/gridstack-item.component.ts +1 -1
  22. package/dist/angular/src/gridstack.component.ts +1 -1
  23. package/dist/angular/src/gridstack.module.ts +1 -1
  24. package/dist/dd-base-impl.d.ts +1 -1
  25. package/dist/dd-base-impl.js +1 -1
  26. package/dist/dd-base-impl.js.map +1 -1
  27. package/dist/dd-draggable.d.ts +1 -1
  28. package/dist/dd-draggable.js +1 -1
  29. package/dist/dd-draggable.js.map +1 -1
  30. package/dist/dd-droppable.d.ts +1 -1
  31. package/dist/dd-droppable.js +1 -1
  32. package/dist/dd-droppable.js.map +1 -1
  33. package/dist/dd-element.d.ts +1 -1
  34. package/dist/dd-element.js +1 -1
  35. package/dist/dd-element.js.map +1 -1
  36. package/dist/dd-gridstack.d.ts +1 -1
  37. package/dist/dd-gridstack.js +1 -1
  38. package/dist/dd-gridstack.js.map +1 -1
  39. package/dist/dd-manager.d.ts +1 -1
  40. package/dist/dd-manager.js +1 -1
  41. package/dist/dd-manager.js.map +1 -1
  42. package/dist/dd-resizable-handle.d.ts +1 -1
  43. package/dist/dd-resizable-handle.js +1 -1
  44. package/dist/dd-resizable-handle.js.map +1 -1
  45. package/dist/dd-resizable.d.ts +1 -1
  46. package/dist/dd-resizable.js +1 -1
  47. package/dist/dd-resizable.js.map +1 -1
  48. package/dist/dd-touch.d.ts +1 -1
  49. package/dist/dd-touch.js +1 -1
  50. package/dist/dd-touch.js.map +1 -1
  51. package/dist/es5/dd-base-impl.d.ts +1 -1
  52. package/dist/es5/dd-base-impl.js +1 -1
  53. package/dist/es5/dd-base-impl.js.map +1 -1
  54. package/dist/es5/dd-draggable.d.ts +1 -1
  55. package/dist/es5/dd-draggable.js +1 -1
  56. package/dist/es5/dd-draggable.js.map +1 -1
  57. package/dist/es5/dd-droppable.d.ts +1 -1
  58. package/dist/es5/dd-droppable.js +1 -1
  59. package/dist/es5/dd-droppable.js.map +1 -1
  60. package/dist/es5/dd-element.d.ts +1 -1
  61. package/dist/es5/dd-element.js +1 -1
  62. package/dist/es5/dd-element.js.map +1 -1
  63. package/dist/es5/dd-gridstack.d.ts +1 -1
  64. package/dist/es5/dd-gridstack.js +1 -1
  65. package/dist/es5/dd-gridstack.js.map +1 -1
  66. package/dist/es5/dd-manager.d.ts +1 -1
  67. package/dist/es5/dd-manager.js +1 -1
  68. package/dist/es5/dd-manager.js.map +1 -1
  69. package/dist/es5/dd-resizable-handle.d.ts +1 -1
  70. package/dist/es5/dd-resizable-handle.js +1 -1
  71. package/dist/es5/dd-resizable-handle.js.map +1 -1
  72. package/dist/es5/dd-resizable.d.ts +1 -1
  73. package/dist/es5/dd-resizable.js +1 -1
  74. package/dist/es5/dd-resizable.js.map +1 -1
  75. package/dist/es5/dd-touch.d.ts +1 -1
  76. package/dist/es5/dd-touch.js +1 -1
  77. package/dist/es5/dd-touch.js.map +1 -1
  78. package/dist/es5/gridstack-all.js +1 -1
  79. package/dist/es5/gridstack-all.js.LICENSE.txt +1 -1
  80. package/dist/es5/gridstack-all.js.map +1 -1
  81. package/dist/es5/gridstack-engine.d.ts +1 -1
  82. package/dist/es5/gridstack-engine.js +1 -1
  83. package/dist/es5/gridstack-engine.js.map +1 -1
  84. package/dist/es5/gridstack-poly.js +1 -1
  85. package/dist/es5/gridstack.d.ts +11 -7
  86. package/dist/es5/gridstack.js +183 -127
  87. package/dist/es5/gridstack.js.map +1 -1
  88. package/dist/es5/types.d.ts +27 -13
  89. package/dist/es5/types.js +1 -4
  90. package/dist/es5/types.js.map +1 -1
  91. package/dist/es5/utils.d.ts +2 -2
  92. package/dist/es5/utils.js +4 -3
  93. package/dist/es5/utils.js.map +1 -1
  94. package/dist/gridstack-all.js +1 -1
  95. package/dist/gridstack-all.js.LICENSE.txt +1 -1
  96. package/dist/gridstack-all.js.map +1 -1
  97. package/dist/gridstack-engine.d.ts +1 -1
  98. package/dist/gridstack-engine.js +1 -1
  99. package/dist/gridstack-engine.js.map +1 -1
  100. package/dist/gridstack.css +2 -2
  101. package/dist/gridstack.d.ts +11 -7
  102. package/dist/gridstack.js +180 -124
  103. package/dist/gridstack.js.map +1 -1
  104. package/dist/gridstack.min.css +1 -1
  105. package/dist/src/gridstack.scss +2 -2
  106. package/dist/types.d.ts +27 -13
  107. package/dist/types.js +1 -4
  108. package/dist/types.js.map +1 -1
  109. package/dist/utils.d.ts +2 -2
  110. package/dist/utils.js +4 -3
  111. package/dist/utils.js.map +1 -1
  112. package/doc/CHANGES.md +15 -1
  113. package/doc/README.md +23 -10
  114. package/package.json +2 -2
package/dist/gridstack.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * GridStack 9.5.1
2
+ * GridStack 10.0.1
3
3
  * https://gridstackjs.com/
4
4
  *
5
5
  * Copyright (c) 2021-2022 Alain Dumesny
@@ -17,7 +17,6 @@ import { gridDefaults, dragInDefaultOptions } from './types';
17
17
  import { DDGridStack } from './dd-gridstack';
18
18
  import { isTouch } from './dd-touch';
19
19
  import { DDManager } from './dd-manager';
20
- /** global instance */
21
20
  const dd = new DDGridStack;
22
21
  // export all dependent file as well to make it easier for users to just import the main file
23
22
  export * from './types';
@@ -156,6 +155,7 @@ class GridStack {
156
155
  this._gsEventHandler = {};
157
156
  /** @internal extra row added when dragging at the bottom of the grid */
158
157
  this._extraDragRow = 0;
158
+ el.gridstack = this;
159
159
  this.el = el; // exposed HTML element to the user
160
160
  opts = opts || {}; // handles null/undefined/0
161
161
  if (!el.classList.contains('grid-stack')) {
@@ -175,6 +175,41 @@ class GridStack {
175
175
  if (opts.alwaysShowResizeHandle !== undefined) {
176
176
  opts._alwaysShowResizeHandle = opts.alwaysShowResizeHandle;
177
177
  }
178
+ let bk = opts.columnOpts?.breakpoints;
179
+ // LEGACY: oneColumnMode stuff changed in v10.x - check if user explicitly set something to convert over
180
+ const oldOpts = opts;
181
+ if (oldOpts.oneColumnModeDomSort) {
182
+ delete oldOpts.oneColumnModeDomSort;
183
+ console.log('Error: Gridstack oneColumnModeDomSort no longer supported. Check GridStackOptions.columnOpts instead.');
184
+ }
185
+ if (oldOpts.oneColumnSize || oldOpts.disableOneColumnMode === false) {
186
+ const oneSize = oldOpts.oneColumnSize || 768;
187
+ delete oldOpts.oneColumnSize;
188
+ delete oldOpts.disableOneColumnMode;
189
+ opts.columnOpts = opts.columnOpts || {};
190
+ bk = opts.columnOpts.breakpoints = opts.columnOpts.breakpoints || [];
191
+ let oneColumn = bk.find(b => b.c === 1);
192
+ if (!oneColumn) {
193
+ oneColumn = { c: 1, w: oneSize };
194
+ bk.push(oneColumn, { c: 12, w: oneSize + 1 });
195
+ }
196
+ else
197
+ oneColumn.w = oneSize;
198
+ }
199
+ //...end LEGACY
200
+ // cleanup responsive opts (must have columnWidth | breakpoints) then sort breakpoints by size (so we can match during resize)
201
+ const resp = opts.columnOpts;
202
+ if (resp) {
203
+ if (!resp.columnWidth && !resp.breakpoints?.length) {
204
+ delete opts.columnOpts;
205
+ bk = undefined;
206
+ }
207
+ else {
208
+ resp.columnMax = resp.columnMax || 12;
209
+ }
210
+ }
211
+ if (bk?.length > 1)
212
+ bk.sort((a, b) => (b.w || 0) - (a.w || 0));
178
213
  // elements DOM attributes override any passed options (like CSS style) - merge the two together
179
214
  let defaults = { ...Utils.cloneDeep(gridDefaults),
180
215
  column: Utils.toNumber(el.getAttribute('gs-column')) || gridDefaults.column,
@@ -196,10 +231,8 @@ class GridStack {
196
231
  opts = null; // make sure we use this.opts instead
197
232
  this._initMargin(); // part of settings defaults...
198
233
  // Now check if we're loading into 1 column mode FIRST so we don't do un-necessary work (like cellHeight = width / 12 then go 1 column)
199
- if (this.opts.column !== 1 && !this.opts.disableOneColumnMode && this._widthOrContainer() <= this.opts.oneColumnSize) {
200
- this._prevColumn = this.getColumn();
201
- this.opts.column = 1;
202
- }
234
+ this.checkDynamicColumn();
235
+ this.el.classList.add('gs-' + this.opts.column);
203
236
  if (this.opts.rtl === 'auto') {
204
237
  this.opts.rtl = (el.style.direction === 'rtl');
205
238
  }
@@ -259,6 +292,8 @@ class GridStack {
259
292
  this._updateStyles(false, maxH); // false = don't recreate, just append if need be
260
293
  }
261
294
  });
295
+ // create initial global styles BEFORE loading children so resizeToContent margin can be calculated correctly
296
+ this._updateStyles(false, 0);
262
297
  if (this.opts.auto) {
263
298
  this.batchUpdate(); // prevent in between re-layout #1535 TODO: this only set float=true, need to prevent collision check...
264
299
  this.getGridItems().forEach(el => this._prepareElement(el));
@@ -271,9 +306,8 @@ class GridStack {
271
306
  if (children.length)
272
307
  this.load(children); // don't load empty
273
308
  }
309
+ // if (this.engine.nodes.length) this._updateStyles(); // update based on # of children. done in engine onChange CB
274
310
  this.setAnimation(this.opts.animate);
275
- this._updateStyles();
276
- this.el.classList.add('gs-' + this.opts.column);
277
311
  // dynamic grids require pausing during drag to detect over to nest vs push
278
312
  if (this.opts.subGridDynamic && !DDManager.pauseDrag)
279
313
  DDManager.pauseDrag = true;
@@ -380,7 +414,7 @@ class GridStack {
380
414
  if (ops.column === 'auto') {
381
415
  autoColumn = true;
382
416
  ops.column = Math.max(node.w || 1, nodeToAdd?.w || 1);
383
- ops.disableOneColumnMode = true; // driven by parent
417
+ delete ops.columnOpts; // driven by parent
384
418
  }
385
419
  // if we're converting an existing full item, move over the content to be the first sub item in the new grid
386
420
  let content = node.el.querySelector('.grid-stack-item-content');
@@ -516,7 +550,6 @@ class GridStack {
516
550
  }
517
551
  if (this._autoColumn) {
518
552
  o.column = 'auto';
519
- delete o.disableOneColumnMode;
520
553
  }
521
554
  const origShow = o._alwaysShowResizeHandle;
522
555
  delete o._alwaysShowResizeHandle;
@@ -544,17 +577,17 @@ class GridStack {
544
577
  */
545
578
  load(items, addRemove = GridStack.addRemoveCB || true) {
546
579
  items = Utils.cloneDeep(items); // so we can mod
547
- // if passed list has coordinates, use them (insert from end to beginning for conflict resolution) else force widget same order
580
+ const column = this.getColumn();
581
+ // if passed list has coordinates, use them (insert from end to beginning for conflict resolution) else keep widget order
548
582
  const haveCoord = items.some(w => w.x !== undefined || w.y !== undefined);
549
583
  if (haveCoord)
550
- items = Utils.sort(items, -1, this._prevColumn || this.getColumn());
584
+ items = Utils.sort(items, -1, column);
551
585
  this._insertNotAppend = haveCoord; // if we create in reverse order...
552
- // if we're loading a layout into for example 1 column (_prevColumn is set only when going to 1) and items don't fit, make sure to save
586
+ // if we're loading a layout into for example 1 column and items don't fit, make sure to save
553
587
  // the original wanted layout so we can scale back up correctly #1471
554
- const column = this.opts.column;
555
- if (this._prevColumn && this._prevColumn !== column && items.some(n => ((n.x || 0) + n.w) > column)) {
588
+ if (items.some(n => ((n.x || 0) + (n.w || 1)) > column)) {
556
589
  this._ignoreLayoutsNodeChange = true; // skip layout update
557
- this.engine.cacheLayout(items, this._prevColumn, true);
590
+ this.engine.cacheLayout(items, 12, true); // TODO: 12 is arbitrary. use max value in layout ?
558
591
  }
559
592
  // if given a different callback, temporally set it as global option so creating will use it
560
593
  const prevCB = GridStack.addRemoveCB;
@@ -562,6 +595,10 @@ class GridStack {
562
595
  GridStack.addRemoveCB = addRemove;
563
596
  let removed = [];
564
597
  this.batchUpdate();
598
+ // if we are blank (loading into empty like startup) temp remove animation
599
+ const noAnim = !this.engine.nodes.length;
600
+ if (noAnim)
601
+ this.setAnimation(false);
565
602
  // see if any items are missing from new layout and need to be removed first
566
603
  if (addRemove) {
567
604
  let copyNodes = [...this.engine.nodes]; // don't loop through array you modify
@@ -587,21 +624,19 @@ class GridStack {
587
624
  } // remove if found from list
588
625
  return true;
589
626
  });
590
- let widthChanged = false;
591
627
  items.forEach(w => {
592
628
  let item = Utils.find(updateNodes, w.id);
593
629
  if (item) {
594
- // if item sizes to content, re-use the exiting height so it's a better guess at the final size 9same if width doesn't change)
630
+ // if item sizes to content, re-use the exiting height so it's a better guess at the final size (same if width doesn't change)
595
631
  if (Utils.shouldSizeToContent(item))
596
632
  w.h = item.h;
597
633
  // check if missing coord, in which case find next empty slot with new (or old if missing) sizes
598
- this.engine.nodeBoundFix(w); // before widthChanged is checked below...
634
+ this.engine.nodeBoundFix(w);
599
635
  if (w.autoPosition || w.x === undefined || w.y === undefined) {
600
636
  w.w = w.w || item.w;
601
637
  w.h = w.h || item.h;
602
638
  this.engine.findEmptyPosition(w);
603
639
  }
604
- widthChanged = widthChanged || (w.w !== undefined && w.w !== item.w);
605
640
  // add back to current list BUT force a collision check if it 'appears' we didn't change to make sure we don't overlap others now
606
641
  this.engine.nodes.push(item);
607
642
  if (Utils.samePos(item, w)) {
@@ -621,12 +656,14 @@ class GridStack {
621
656
  }
622
657
  });
623
658
  this.engine.removedNodes = removed;
624
- this.doContentResize(widthChanged, true); // we only need to wait for animation if we changed any widths
625
659
  this.batchUpdate(false);
626
660
  // after commit, clear that flag
627
661
  delete this._ignoreLayoutsNodeChange;
628
662
  delete this._insertNotAppend;
629
663
  prevCB ? GridStack.addRemoveCB = prevCB : delete GridStack.addRemoveCB;
664
+ // delay adding animation back
665
+ if (noAnim && this.opts.animate)
666
+ setTimeout(() => this.setAnimation(this.opts.animate));
630
667
  return this;
631
668
  }
632
669
  /**
@@ -651,11 +688,18 @@ class GridStack {
651
688
  (!forcePixel || !this.opts.cellHeightUnit || this.opts.cellHeightUnit === 'px')) {
652
689
  return this.opts.cellHeight;
653
690
  }
691
+ // do rem/em to px conversion
692
+ if (this.opts.cellHeightUnit === 'rem') {
693
+ return this.opts.cellHeight * parseFloat(getComputedStyle(document.documentElement).fontSize);
694
+ }
695
+ if (this.opts.cellHeightUnit === 'em') {
696
+ return this.opts.cellHeight * parseFloat(getComputedStyle(this.el).fontSize);
697
+ }
654
698
  // else get first cell height
655
699
  let el = this.el.querySelector('.' + this.opts.itemClass);
656
700
  if (el) {
657
- let height = Utils.toNumber(el.getAttribute('gs-h')) || 1; // since we don't write 1 anymore
658
- return Math.round(el.offsetHeight / height);
701
+ let h = Utils.toNumber(el.getAttribute('gs-h')) || 1; // since we don't write 1 anymore
702
+ return Math.round(el.offsetHeight / h);
659
703
  }
660
704
  // else do entire grid and # of rows (but doesn't work if min-height is the actual constrain)
661
705
  let rows = parseInt(this.el.getAttribute('gs-current-row'));
@@ -698,7 +742,7 @@ class GridStack {
698
742
  }
699
743
  this.opts.cellHeightUnit = data.unit;
700
744
  this.opts.cellHeight = data.h;
701
- this.doContentResize(false, true); // no anim wait, but use attributes since we only change row height
745
+ this.resizeToContentCheck();
702
746
  if (update) {
703
747
  this._updateStyles(true); // true = force re-create for current # of rows
704
748
  }
@@ -708,11 +752,37 @@ class GridStack {
708
752
  cellWidth() {
709
753
  return this._widthOrContainer() / this.getColumn();
710
754
  }
711
- /** return our expected width (or parent) for 1 column check */
712
- _widthOrContainer() {
755
+ /** return our expected width (or parent) , and optionally of window for dynamic column check */
756
+ _widthOrContainer(forBreakpoint = false) {
713
757
  // use `offsetWidth` or `clientWidth` (no scrollbar) ?
714
758
  // https://stackoverflow.com/questions/21064101/understanding-offsetwidth-clientwidth-scrollwidth-and-height-respectively
715
- return (this.el.clientWidth || this.el.parentElement.clientWidth || window.innerWidth);
759
+ return forBreakpoint && this.opts.columnOpts?.breakpointForWindow ? window.innerWidth : (this.el.clientWidth || this.el.parentElement.clientWidth || window.innerWidth);
760
+ }
761
+ /** checks for dynamic column count for our current size, returning true if changed */
762
+ checkDynamicColumn() {
763
+ const resp = this.opts.columnOpts;
764
+ if (!resp || (!resp.columnWidth && !resp.breakpoints?.length))
765
+ return false;
766
+ const column = this.getColumn();
767
+ let newColumn = column;
768
+ const w = this._widthOrContainer(true);
769
+ if (resp.columnWidth) {
770
+ newColumn = Math.min(Math.round(w / resp.columnWidth) || 1, resp.columnMax);
771
+ }
772
+ else {
773
+ // find the closest breakpoint (already sorted big to small) that matches
774
+ newColumn = resp.columnMax;
775
+ let i = 0;
776
+ while (i < resp.breakpoints.length && w <= resp.breakpoints[i].w) {
777
+ newColumn = resp.breakpoints[i++].c || column;
778
+ }
779
+ }
780
+ if (newColumn !== column) {
781
+ const bk = resp.breakpoints?.find(b => b.c === newColumn);
782
+ this.column(newColumn, bk?.layout || resp.layout);
783
+ return true;
784
+ }
785
+ return false;
716
786
  }
717
787
  /**
718
788
  * re-layout grid items to reclaim any empty space. Options are:
@@ -739,34 +809,19 @@ class GridStack {
739
809
  if (!column || column < 1 || this.opts.column === column)
740
810
  return this;
741
811
  let oldColumn = this.getColumn();
742
- // if we go into 1 column mode due to size change (disableOneColumnMode is off and we hit min width)
743
- // then remember the original columns so we can restore.
744
- if (column === 1 && !this.opts.disableOneColumnMode) {
745
- this._prevColumn = oldColumn;
746
- }
747
- else {
748
- delete this._prevColumn;
749
- }
812
+ this.opts.column = column;
813
+ if (!this.engine)
814
+ return this; // called in constructor, noting else to do
815
+ this.engine.column = column;
750
816
  this.el.classList.remove('gs-' + oldColumn);
751
817
  this.el.classList.add('gs-' + column);
752
- this.opts.column = this.engine.column = column;
753
- // update the items now - see if the dom order nodes should be passed instead (else default to current list)
754
- let domNodes;
755
- if (column === 1 && this.opts.oneColumnModeDomSort) {
756
- domNodes = [];
757
- this.getGridItems().forEach(el => {
758
- if (el.gridstackNode) {
759
- domNodes.push(el.gridstackNode);
760
- }
761
- });
762
- if (!domNodes.length) {
763
- domNodes = undefined;
764
- }
765
- }
766
- this.engine.columnChanged(oldColumn, column, domNodes, layout);
818
+ // update the items now, checking if we have a custom children layout
819
+ /*const newChildren = this.opts.columnOpts?.breakpoints?.find(r => r.c === column)?.children;
820
+ if (newChildren) this.load(newChildren);
821
+ else*/ this.engine.columnChanged(oldColumn, column, undefined, layout);
767
822
  if (this._isAutoCellHeight)
768
823
  this.cellHeight();
769
- this.doContentResize();
824
+ this.resizeToContentCheck(true); // wait for width resizing
770
825
  // and trigger our event last...
771
826
  this._ignoreLayoutsNodeChange = true; // skip layout update
772
827
  this._triggerChangeEvent();
@@ -776,9 +831,7 @@ class GridStack {
776
831
  /**
777
832
  * get the number of columns in the grid (default 12)
778
833
  */
779
- getColumn() {
780
- return this.opts.column;
781
- }
834
+ getColumn() { return this.opts.column; }
782
835
  /** returns an array of grid HTML elements (no placeholder) - used to iterate through our children in DOM order */
783
836
  getGridItems() {
784
837
  return Array.from(this.el.children)
@@ -890,14 +943,13 @@ class GridStack {
890
943
  this._prepareElement(el, true, options);
891
944
  const node = el.gridstackNode;
892
945
  this._updateContainerHeight();
893
- this.doContentResize(false, false, node);
894
946
  // see if there is a sub-grid to create
895
947
  if (node.subGridOpts) {
896
948
  this.makeSubGrid(el, node.subGridOpts, undefined, false); // node.subGrid will be used as option in method, no need to pass
897
949
  }
898
- // if we're adding an item into 1 column (_prevColumn is set only when going to 1) make sure
950
+ // if we're adding an item into 1 column make sure
899
951
  // we don't override the larger 12 column layout that was already saved. #1985
900
- if (this._prevColumn && this.opts.column === 1) {
952
+ if (this.opts.column === 1) {
901
953
  this._ignoreLayoutsNodeChange = true;
902
954
  }
903
955
  this._triggerAddEvent();
@@ -928,8 +980,8 @@ class GridStack {
928
980
  names.forEach(name => this.on(name, callback));
929
981
  return this;
930
982
  }
983
+ // native CustomEvent handlers - cash the generic handlers so we can easily remove
931
984
  if (name === 'change' || name === 'added' || name === 'removed' || name === 'enable' || name === 'disable') {
932
- // native CustomEvent handlers - cash the generic handlers so we can easily remove
933
985
  let noData = (name === 'enable' || name === 'disable');
934
986
  if (noData) {
935
987
  this._gsEventHandler[name] = (event) => callback(event);
@@ -946,7 +998,7 @@ class GridStack {
946
998
  this._gsEventHandler[name] = callback;
947
999
  }
948
1000
  else {
949
- console.log('GridStack.on(' + name + ') event not supported, but you can still use $(".grid-stack").on(...) while jquery-ui is still used internally.');
1001
+ console.log('GridStack.on(' + name + ') event not supported');
950
1002
  }
951
1003
  return this;
952
1004
  }
@@ -1036,6 +1088,8 @@ class GridStack {
1036
1088
  }
1037
1089
  return this;
1038
1090
  }
1091
+ /** @internal */
1092
+ hasAnimationCSS() { return this.el.classList.contains('grid-stack-animate'); }
1039
1093
  /**
1040
1094
  * Toggle the grid static state, which permanently removes/add Drag&Drop support, unlike disable()/enable() that just turns it off/on.
1041
1095
  * Also toggle the grid-stack-static class.
@@ -1121,8 +1175,11 @@ class GridStack {
1121
1175
  }
1122
1176
  Utils.sanitizeMinMax(n);
1123
1177
  // finally move the widget and update attr
1124
- if (m)
1178
+ if (m) {
1179
+ const widthChanged = (m.w !== undefined && m.w !== n.w);
1125
1180
  this.moveNode(n, m);
1181
+ this.resizeToContentCheck(widthChanged, n); // wait for animation if we changed width
1182
+ }
1126
1183
  if (m || changed) {
1127
1184
  this._writeAttr(el, n);
1128
1185
  }
@@ -1143,26 +1200,25 @@ class GridStack {
1143
1200
  /**
1144
1201
  * Updates widget height to match the content height to avoid v-scrollbar or dead space.
1145
1202
  * Note: this assumes only 1 child under resizeToContentParent='.grid-stack-item-content' (sized to gridItem minus padding) that is at the entire content size wanted.
1146
- * useAttrSize set to true if GridStackNode.h should be used instead of actual container height when we don't need to wait for animation to finish to get actual DOM heights
1203
+ * @param el grid item element
1204
+ * @param useNodeH set to true if GridStackNode.h should be used instead of actual container height when we don't need to wait for animation to finish to get actual DOM heights
1147
1205
  */
1148
- resizeToContent(el, useAttrSize = false) {
1206
+ resizeToContent(el) {
1149
1207
  if (!el)
1150
1208
  return;
1151
1209
  el.classList.remove('size-to-content-max');
1152
1210
  if (!el.clientHeight)
1153
1211
  return; // 0 when hidden, skip
1154
- let n = el.gridstackNode;
1212
+ const n = el.gridstackNode;
1155
1213
  if (!n)
1156
1214
  return;
1157
1215
  const grid = n.grid;
1158
- if (!grid)
1159
- return;
1160
- if (el.parentElement !== grid.el)
1216
+ if (!grid || el.parentElement !== grid.el)
1161
1217
  return; // skip if we are not inside a grid
1162
- const cell = grid.getCellHeight();
1218
+ const cell = grid.getCellHeight(true);
1163
1219
  if (!cell)
1164
1220
  return;
1165
- let height = useAttrSize && n.h ? n.h * cell : el.clientHeight; // getBoundingClientRect().height seem to flicker back and forth
1221
+ let height = n.h ? n.h * cell : el.clientHeight; // getBoundingClientRect().height seem to flicker back and forth
1166
1222
  let item;
1167
1223
  if (n.resizeToContentParent)
1168
1224
  item = el.querySelector(n.resizeToContentParent);
@@ -1171,11 +1227,11 @@ class GridStack {
1171
1227
  if (!item)
1172
1228
  return;
1173
1229
  const padding = el.clientHeight - item.clientHeight; // full - available height to our child (minus border, padding...)
1174
- const itemH = useAttrSize && n.h ? n.h * cell - padding : item.clientHeight; // calculated to what cellHeight is or will become (rather than actual to prevent waiting for animation to finish)
1230
+ const itemH = n.h ? n.h * cell - padding : item.clientHeight; // calculated to what cellHeight is or will become (rather than actual to prevent waiting for animation to finish)
1175
1231
  let wantedH;
1176
1232
  if (n.subGrid) {
1177
1233
  // sub-grid - use their actual row count * their cell height
1178
- wantedH = n.subGrid.getRow() * n.subGrid.getCellHeight();
1234
+ wantedH = n.subGrid.getRow() * n.subGrid.getCellHeight(true);
1179
1235
  }
1180
1236
  else {
1181
1237
  // NOTE: clientHeight & getBoundingClientRect() is undefined for text and other leaf nodes. use <div> container!
@@ -1207,11 +1263,11 @@ class GridStack {
1207
1263
  }
1208
1264
  }
1209
1265
  /** call the user resize (so they can do extra work) else our build in version */
1210
- resizeToContentCheck(el, useAttr = false) {
1266
+ resizeToContentCBCheck(el) {
1211
1267
  if (GridStack.resizeToContentCB)
1212
- GridStack.resizeToContentCB(el, useAttr);
1268
+ GridStack.resizeToContentCB(el);
1213
1269
  else
1214
- this.resizeToContent(el, useAttr);
1270
+ this.resizeToContent(el);
1215
1271
  }
1216
1272
  /**
1217
1273
  * Updates the margins which will set all 4 sides at once - see `GridStackOptions.margin` for format options (CSS string format of 1,2,4 values or single number).
@@ -1304,7 +1360,8 @@ class GridStack {
1304
1360
  /** @internal called to delete the current dynamic style sheet used for our layout */
1305
1361
  _removeStylesheet() {
1306
1362
  if (this._styles) {
1307
- Utils.removeStylesheet(this._styleSheetClass);
1363
+ const styleLocation = this.opts.styleInHead ? undefined : this.el.parentNode;
1364
+ Utils.removeStylesheet(this._styleSheetClass, styleLocation);
1308
1365
  delete this._styles;
1309
1366
  }
1310
1367
  return this;
@@ -1315,7 +1372,7 @@ class GridStack {
1315
1372
  if (forceUpdate) {
1316
1373
  this._removeStylesheet();
1317
1374
  }
1318
- if (!maxH)
1375
+ if (maxH === undefined)
1319
1376
  maxH = this.getRow();
1320
1377
  this._updateContainerHeight();
1321
1378
  // if user is telling us they will handle the CSS themselves by setting heights to 0. Do we need this opts really ??
@@ -1328,7 +1385,7 @@ class GridStack {
1328
1385
  // create one as needed
1329
1386
  if (!this._styles) {
1330
1387
  // insert style to parent (instead of 'head' by default) to support WebComponent
1331
- let styleLocation = this.opts.styleInHead ? undefined : this.el.parentNode;
1388
+ const styleLocation = this.opts.styleInHead ? undefined : this.el.parentNode;
1332
1389
  this._styles = Utils.createStylesheet(this._styleSheetClass, styleLocation, {
1333
1390
  nonce: this.opts.nonce,
1334
1391
  });
@@ -1395,25 +1452,24 @@ class GridStack {
1395
1452
  }
1396
1453
  // if we're a nested grid inside an sizeToContent item, tell it to resize itself too
1397
1454
  if (parent && !parent.grid.engine.batchMode && Utils.shouldSizeToContent(parent)) {
1398
- parent.grid.resizeToContentCheck(parent.el);
1455
+ parent.grid.resizeToContentCBCheck(parent.el);
1399
1456
  }
1400
1457
  return this;
1401
1458
  }
1402
1459
  /** @internal */
1403
1460
  _prepareElement(el, triggerAddEvent = false, node) {
1404
- el.classList.add(this.opts.itemClass);
1405
1461
  node = node || this._readAttr(el);
1406
1462
  el.gridstackNode = node;
1407
1463
  node.el = el;
1408
1464
  node.grid = this;
1409
- let copy = { ...node };
1410
1465
  node = this.engine.addNode(node, triggerAddEvent);
1411
- // write node attr back in case there was collision or we have to fix bad values during addNode()
1412
- if (!Utils.same(node, copy)) {
1413
- this._writeAttr(el, node);
1414
- }
1415
- if (Utils.shouldSizeToContent(node))
1416
- el.classList.add('size-to-content');
1466
+ // write the dom sizes and class
1467
+ this._writeAttr(el, node);
1468
+ el.classList.add(gridDefaults.itemClass, this.opts.itemClass);
1469
+ const sizeToContent = Utils.shouldSizeToContent(node);
1470
+ sizeToContent ? el.classList.add('size-to-content') : el.classList.remove('size-to-content');
1471
+ if (sizeToContent)
1472
+ this.resizeToContentCheck(false, node);
1417
1473
  this._prepareDragDropByNode(node);
1418
1474
  return this;
1419
1475
  }
@@ -1528,15 +1584,8 @@ class GridStack {
1528
1584
  }
1529
1585
  }
1530
1586
  else {
1531
- // else check for 1 column in/out behavior
1532
- let oneColumn = !this.opts.disableOneColumnMode && this.el.clientWidth <= this.opts.oneColumnSize ||
1533
- (this.opts.column === 1 && !this._prevColumn);
1534
- if ((this.opts.column === 1) !== oneColumn) {
1535
- // if (this.opts.animate) this.setAnimation(false); // 1 <-> 12 is too radical, turn off animation and we need it for sizeToContent
1536
- this.column(oneColumn ? 1 : this._prevColumn);
1537
- // if (this.opts.animate) setTimeout(() => this.setAnimation(true));
1538
- columnChanged = true;
1539
- }
1587
+ // else check for dynamic column
1588
+ columnChanged = this.checkDynamicColumn();
1540
1589
  }
1541
1590
  // make the cells content square again
1542
1591
  if (this._isAutoCellHeight)
@@ -1547,40 +1596,41 @@ class GridStack {
1547
1596
  n.subGrid.onResize();
1548
1597
  });
1549
1598
  if (!this._skipInitialResize)
1550
- this.doContentResize(columnChanged); // wait for anim of column changed (DOM reflow before we can size correctly)
1599
+ this.resizeToContentCheck(columnChanged); // wait for anim of column changed (DOM reflow before we can size correctly)
1551
1600
  delete this._skipInitialResize;
1552
1601
  this.batchUpdate(false);
1553
1602
  return this;
1554
1603
  }
1555
- doContentResize(delay = true, useAttr = false, n = undefined) {
1604
+ /** resizes content for given node (or all) if shouldSizeToContent() is true */
1605
+ resizeToContentCheck(delay = false, n = undefined) {
1606
+ if (!this.engine)
1607
+ return; // we've been deleted in between!
1556
1608
  // update any gridItem height with sizeToContent, but wait for DOM $animation_speed to settle if we changed column count
1557
1609
  // TODO: is there a way to know what the final (post animation) size of the content will be so we can animate the column width and height together rather than sequentially ?
1558
- setTimeout(() => {
1559
- if (!this.engine)
1560
- return; // we've been deleted in between!
1561
- if (n) {
1610
+ if (delay && this.hasAnimationCSS())
1611
+ return setTimeout(() => this.resizeToContentCheck(false, n), 300 + 10);
1612
+ if (n) {
1613
+ if (Utils.shouldSizeToContent(n))
1614
+ this.resizeToContentCBCheck(n.el);
1615
+ }
1616
+ else if (this.engine.nodes.some(n => Utils.shouldSizeToContent(n))) {
1617
+ const nodes = [...this.engine.nodes]; // in case order changes while resizing one
1618
+ this.batchUpdate();
1619
+ nodes.forEach(n => {
1562
1620
  if (Utils.shouldSizeToContent(n))
1563
- this.resizeToContentCheck(n.el, useAttr);
1564
- }
1565
- else if (this.engine.nodes.some(n => Utils.shouldSizeToContent(n))) {
1566
- const nodes = [...this.engine.nodes]; // in case order changes while resizing one
1567
- this.batchUpdate();
1568
- nodes.forEach(n => {
1569
- if (Utils.shouldSizeToContent(n))
1570
- this.resizeToContentCheck(n.el, useAttr);
1571
- });
1572
- this.batchUpdate(false);
1573
- }
1574
- // call this regardless of shouldSizeToContent because widget might need to stretch to take available space after a resize
1575
- if (this._gsEventHandler['resizecontent'])
1576
- this._gsEventHandler['resizecontent'](null, n ? [n] : this.engine.nodes);
1577
- }, delay ? 300 + 10 : 0);
1621
+ this.resizeToContentCBCheck(n.el);
1622
+ });
1623
+ this.batchUpdate(false);
1624
+ }
1625
+ // call this regardless of shouldSizeToContent because widget might need to stretch to take available space after a resize
1626
+ if (this._gsEventHandler['resizecontent'])
1627
+ this._gsEventHandler['resizecontent'](null, n ? [n] : this.engine.nodes);
1578
1628
  }
1579
1629
  /** add or remove the grid element size event handler */
1580
1630
  _updateResizeEvent(forceRemove = false) {
1581
- // only add event if we're not nested (parent will call us) and we're auto sizing cells or supporting oneColumn (i.e. doing work)
1631
+ // only add event if we're not nested (parent will call us) and we're auto sizing cells or supporting dynamic column (i.e. doing work)
1582
1632
  // or supporting new sizeToContent option.
1583
- const trackSize = !this.parentGridItem && (this._isAutoCellHeight || this.opts.sizeToContent || !this.opts.disableOneColumnMode
1633
+ const trackSize = !this.parentGridItem && (this._isAutoCellHeight || this.opts.sizeToContent || this.opts.columnOpts
1584
1634
  || this.engine.nodes.find(n => n.sizeToContent));
1585
1635
  if (!forceRemove && trackSize && !this.resizeObserver) {
1586
1636
  this._sizeThrottle = Utils.throttle(() => this.onResize(), this.opts.cellHeightThrottle);
@@ -1705,7 +1755,7 @@ class GridStack {
1705
1755
  if (this.opts.staticGrid)
1706
1756
  return this; // can't move a static grid!
1707
1757
  GridStack.getElements(els).forEach(el => {
1708
- let n = el.gridstackNode;
1758
+ const n = el.gridstackNode;
1709
1759
  if (!n)
1710
1760
  return;
1711
1761
  val ? delete n.noMove : n.noMove = true;
@@ -1961,8 +2011,12 @@ class GridStack {
1961
2011
  // ignore drop on ourself from ourself that didn't come from the outside - dragend will handle the simple move instead
1962
2012
  if (node?.grid === this && !node._isExternal)
1963
2013
  return false;
1964
- let wasAdded = !!this.placeholder.parentElement; // skip items not actually added to us because of constrains, but do cleanup #1419
2014
+ const wasAdded = !!this.placeholder.parentElement; // skip items not actually added to us because of constrains, but do cleanup #1419
1965
2015
  this.placeholder.remove();
2016
+ // disable animation when replacing a placeholder (already positioned) with actual content
2017
+ const noAnim = wasAdded && this.opts.animate;
2018
+ if (noAnim)
2019
+ this.setAnimation(false);
1966
2020
  // notify previous grid of removal
1967
2021
  // console.log('drop delete _gridstackNodeOrig') // TEST
1968
2022
  let origNode = el._gridstackNodeOrig;
@@ -2007,15 +2061,13 @@ class GridStack {
2007
2061
  // @ts-ignore
2008
2062
  Utils.copyPos(node, this._readAttr(this.placeholder)); // placeholder values as moving VERY fast can throw things off #1578
2009
2063
  Utils.removePositioningStyles(el); // @ts-ignore
2010
- this._writeAttr(el, node);
2011
- el.classList.add(gridDefaults.itemClass, this.opts.itemClass);
2012
2064
  this.el.appendChild(el); // @ts-ignore // TODO: now would be ideal time to _removeHelperStyle() overriding floating styles (native only)
2065
+ this._prepareElement(el, true, node);
2013
2066
  if (subGrid) {
2014
2067
  subGrid.parentGridItem = node;
2015
2068
  if (!subGrid.opts.styleInHead)
2016
2069
  subGrid._updateStyles(true); // re-create sub-grid styles now that we've moved
2017
2070
  }
2018
- this._prepareDragDropByNode(node);
2019
2071
  this._updateContainerHeight();
2020
2072
  this.engine.addedNodes.push(node); // @ts-ignore
2021
2073
  this._triggerAddEvent(); // @ts-ignore
@@ -2024,6 +2076,9 @@ class GridStack {
2024
2076
  if (this._gsEventHandler['dropped']) {
2025
2077
  this._gsEventHandler['dropped']({ ...event, type: 'dropped' }, origNode && origNode.grid ? origNode : undefined, node);
2026
2078
  }
2079
+ // delay adding animation back
2080
+ if (noAnim)
2081
+ setTimeout(() => this.setAnimation(this.opts.animate));
2027
2082
  return false; // prevent parent from receiving msg (which may be grid as well)
2028
2083
  });
2029
2084
  return this;
@@ -2091,6 +2146,7 @@ class GridStack {
2091
2146
  delete node._moving;
2092
2147
  delete node._event;
2093
2148
  delete node._lastTried;
2149
+ const widthChanged = node.w !== node._orig.w;
2094
2150
  // if the item has moved to another grid, we're done here
2095
2151
  let target = event.target;
2096
2152
  if (!target.gridstackNode || target.gridstackNode.grid !== this)
@@ -2128,7 +2184,7 @@ class GridStack {
2128
2184
  if (event.type === 'resizestop') {
2129
2185
  if (Number.isInteger(node.sizeToContent))
2130
2186
  node.sizeToContent = node.h; // new soft limit
2131
- this.doContentResize(false, true, node); // no amin wait as will use the actual sized coordinate attr
2187
+ this.resizeToContentCheck(widthChanged, node); // wait for width animation if changed
2132
2188
  }
2133
2189
  };
2134
2190
  dd.draggable(el, {
@@ -2305,6 +2361,6 @@ GridStack.resizeToContentParent = '.grid-stack-item-content';
2305
2361
  GridStack.Utils = Utils;
2306
2362
  /** scoping so users can call new GridStack.Engine(12) for example */
2307
2363
  GridStack.Engine = GridStackEngine;
2308
- GridStack.GDRev = '9.5.1';
2364
+ GridStack.GDRev = '10.0.1';
2309
2365
  export { GridStack };
2310
2366
  //# sourceMappingURL=gridstack.js.map