gridstack 10.3.0 → 11.0.0

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 (136) hide show
  1. package/README.md +37 -3
  2. package/dist/angular/README.md +47 -25
  3. package/dist/angular/{esm2020 → esm2022}/gridstack-angular.mjs +5 -5
  4. package/dist/angular/esm2022/index.mjs +8 -0
  5. package/dist/angular/esm2022/lib/base-widget.mjs +34 -0
  6. package/dist/angular/esm2022/lib/gridstack-item.component.mjs +72 -0
  7. package/dist/angular/esm2022/lib/gridstack.component.mjs +300 -0
  8. package/dist/angular/esm2022/lib/gridstack.module.mjs +39 -0
  9. package/dist/angular/{fesm2020 → fesm2022}/gridstack-angular.mjs +400 -369
  10. package/dist/angular/fesm2022/gridstack-angular.mjs.map +1 -0
  11. package/dist/angular/index.d.ts +4 -5
  12. package/dist/angular/lib/base-widget.d.ts +18 -16
  13. package/dist/angular/lib/gridstack-item.component.d.ts +37 -37
  14. package/dist/angular/lib/gridstack.component.d.ts +135 -129
  15. package/dist/angular/lib/gridstack.module.d.ts +10 -10
  16. package/dist/angular/src/base-widget.ts +36 -0
  17. package/dist/angular/src/gridstack-item.component.ts +82 -0
  18. package/dist/angular/src/gridstack.component.ts +312 -0
  19. package/dist/angular/src/gridstack.module.ts +32 -0
  20. package/dist/dd-base-impl.d.ts +2 -2
  21. package/dist/dd-base-impl.js +2 -2
  22. package/dist/dd-base-impl.js.map +1 -1
  23. package/dist/dd-draggable.d.ts +7 -16
  24. package/dist/dd-draggable.js +23 -34
  25. package/dist/dd-draggable.js.map +1 -1
  26. package/dist/dd-droppable.d.ts +2 -2
  27. package/dist/dd-droppable.js +2 -2
  28. package/dist/dd-droppable.js.map +1 -1
  29. package/dist/dd-element.d.ts +5 -5
  30. package/dist/dd-element.js +2 -2
  31. package/dist/dd-element.js.map +1 -1
  32. package/dist/dd-gridstack.d.ts +5 -5
  33. package/dist/dd-gridstack.js +8 -8
  34. package/dist/dd-gridstack.js.map +1 -1
  35. package/dist/dd-manager.d.ts +2 -2
  36. package/dist/dd-manager.js +2 -2
  37. package/dist/dd-manager.js.map +1 -1
  38. package/dist/dd-resizable-handle.d.ts +2 -2
  39. package/dist/dd-resizable-handle.js +3 -3
  40. package/dist/dd-resizable-handle.js.map +1 -1
  41. package/dist/dd-resizable.d.ts +4 -2
  42. package/dist/dd-resizable.js +15 -10
  43. package/dist/dd-resizable.js.map +1 -1
  44. package/dist/dd-touch.d.ts +2 -2
  45. package/dist/dd-touch.js +2 -2
  46. package/dist/dd-touch.js.map +1 -1
  47. package/dist/es5/dd-base-impl.d.ts +2 -2
  48. package/dist/es5/dd-base-impl.js +2 -2
  49. package/dist/es5/dd-base-impl.js.map +1 -1
  50. package/dist/es5/dd-draggable.d.ts +7 -16
  51. package/dist/es5/dd-draggable.js +20 -29
  52. package/dist/es5/dd-draggable.js.map +1 -1
  53. package/dist/es5/dd-droppable.d.ts +2 -2
  54. package/dist/es5/dd-droppable.js +2 -2
  55. package/dist/es5/dd-droppable.js.map +1 -1
  56. package/dist/es5/dd-element.d.ts +5 -5
  57. package/dist/es5/dd-element.js +2 -2
  58. package/dist/es5/dd-element.js.map +1 -1
  59. package/dist/es5/dd-gridstack.d.ts +5 -5
  60. package/dist/es5/dd-gridstack.js +9 -6
  61. package/dist/es5/dd-gridstack.js.map +1 -1
  62. package/dist/es5/dd-manager.d.ts +2 -2
  63. package/dist/es5/dd-manager.js +2 -2
  64. package/dist/es5/dd-manager.js.map +1 -1
  65. package/dist/es5/dd-resizable-handle.d.ts +2 -2
  66. package/dist/es5/dd-resizable-handle.js +2 -2
  67. package/dist/es5/dd-resizable-handle.js.map +1 -1
  68. package/dist/es5/dd-resizable.d.ts +4 -2
  69. package/dist/es5/dd-resizable.js +13 -8
  70. package/dist/es5/dd-resizable.js.map +1 -1
  71. package/dist/es5/dd-touch.d.ts +2 -2
  72. package/dist/es5/dd-touch.js +2 -2
  73. package/dist/es5/dd-touch.js.map +1 -1
  74. package/dist/es5/gridstack-all.js +1 -1
  75. package/dist/es5/gridstack-all.js.LICENSE.txt +2 -2
  76. package/dist/es5/gridstack-all.js.map +1 -1
  77. package/dist/es5/gridstack-engine.d.ts +2 -2
  78. package/dist/es5/gridstack-engine.js +5 -5
  79. package/dist/es5/gridstack-engine.js.map +1 -1
  80. package/dist/es5/gridstack-poly.js +2 -2
  81. package/dist/es5/gridstack.d.ts +22 -17
  82. package/dist/es5/gridstack.js +170 -142
  83. package/dist/es5/gridstack.js.map +1 -1
  84. package/dist/es5/types.d.ts +16 -8
  85. package/dist/es5/types.js +3 -10
  86. package/dist/es5/types.js.map +1 -1
  87. package/dist/es5/utils.d.ts +6 -2
  88. package/dist/es5/utils.js +43 -8
  89. package/dist/es5/utils.js.map +1 -1
  90. package/dist/gridstack-all.js +1 -1
  91. package/dist/gridstack-all.js.LICENSE.txt +2 -2
  92. package/dist/gridstack-all.js.map +1 -1
  93. package/dist/gridstack-engine.d.ts +2 -2
  94. package/dist/gridstack-engine.js +61 -61
  95. package/dist/gridstack-engine.js.map +1 -1
  96. package/dist/gridstack-extra.css +1 -1
  97. package/dist/gridstack.css +2 -2
  98. package/dist/gridstack.d.ts +22 -17
  99. package/dist/gridstack.js +255 -227
  100. package/dist/gridstack.js.map +1 -1
  101. package/dist/src/gridstack-extra.scss +25 -0
  102. package/dist/src/gridstack.scss +157 -0
  103. package/dist/types.d.ts +16 -8
  104. package/dist/types.js +2 -9
  105. package/dist/types.js.map +1 -1
  106. package/dist/utils.d.ts +6 -2
  107. package/dist/utils.js +57 -25
  108. package/dist/utils.js.map +1 -1
  109. package/doc/CHANGES.md +16 -0
  110. package/doc/README.md +18 -23
  111. package/package.json +3 -2
  112. package/.github/FUNDING.yml +0 -12
  113. package/angular/.editorconfig +0 -16
  114. package/angular/.vscode/extensions.json +0 -4
  115. package/angular/.vscode/launch.json +0 -20
  116. package/angular/.vscode/tasks.json +0 -42
  117. package/angular/README.md +0 -170
  118. package/angular/README_build.md +0 -27
  119. package/angular/angular.json +0 -135
  120. package/angular/package.json +0 -40
  121. package/angular/projects/lib/README.md +0 -24
  122. package/angular/projects/lib/ng-package.json +0 -7
  123. package/angular/projects/lib/package.json +0 -11
  124. package/angular/projects/lib/tsconfig.lib.json +0 -15
  125. package/angular/projects/lib/tsconfig.lib.prod.json +0 -10
  126. package/angular/projects/lib/tsconfig.spec.json +0 -17
  127. package/dist/angular/esm2020/lib/base-widget.mjs +0 -30
  128. package/dist/angular/esm2020/lib/gridstack-item.component.mjs +0 -68
  129. package/dist/angular/esm2020/lib/gridstack.component.mjs +0 -280
  130. package/dist/angular/esm2020/lib/gridstack.module.mjs +0 -39
  131. package/dist/angular/esm2020/public-api.mjs +0 -8
  132. package/dist/angular/fesm2015/gridstack-angular.mjs +0 -420
  133. package/dist/angular/fesm2015/gridstack-angular.mjs.map +0 -1
  134. package/dist/angular/fesm2020/gridstack-angular.mjs.map +0 -1
  135. package/dist/angular/package.json +0 -31
  136. package/dist/angular/public-api.d.ts +0 -4
package/dist/gridstack.js CHANGED
@@ -1,13 +1,13 @@
1
1
  /*!
2
- * GridStack 10.3.0
2
+ * GridStack 11.0.0
3
3
  * https://gridstackjs.com/
4
4
  *
5
- * Copyright (c) 2021-2022 Alain Dumesny
5
+ * Copyright (c) 2021-2024 Alain Dumesny
6
6
  * see root license https://github.com/gridstack/gridstack.js/tree/master/LICENSE
7
7
  */
8
8
  import { GridStackEngine } from './gridstack-engine';
9
9
  import { Utils, obsolete } from './utils';
10
- import { gridDefaults, dragInDefaultOptions } from './types';
10
+ import { gridDefaults } from './types';
11
11
  /*
12
12
  * and include D&D by default
13
13
  * TODO: while we could generate a gridstack-static.js at smaller size - saves about 31k (41k -> 72k)
@@ -42,15 +42,15 @@ class GridStack {
42
42
  * @param elOrString element or CSS selector (first one used) to convert to a grid (default to '.grid-stack' class selector)
43
43
  *
44
44
  * @example
45
- * let grid = GridStack.init();
45
+ * const grid = GridStack.init();
46
46
  *
47
47
  * Note: the HTMLElement (of type GridHTMLElement) will store a `gridstack: GridStack` value that can be retrieve later
48
- * let grid = document.querySelector('.grid-stack').gridstack;
48
+ * const grid = document.querySelector('.grid-stack').gridstack;
49
49
  */
50
50
  static init(options = {}, elOrString = '.grid-stack') {
51
51
  if (typeof document === 'undefined')
52
52
  return null; // temp workaround SSR
53
- let el = GridStack.getGridElement(elOrString);
53
+ const el = GridStack.getGridElement(elOrString);
54
54
  if (!el) {
55
55
  if (typeof elOrString === 'string') {
56
56
  console.error('GridStack.initAll() no grid was found with selector "' + elOrString + '" - element missing or wrong selector ?' +
@@ -72,11 +72,11 @@ class GridStack {
72
72
  * @param selector elements selector to convert to grids (default to '.grid-stack' class selector)
73
73
  *
74
74
  * @example
75
- * let grids = GridStack.initAll();
75
+ * const grids = GridStack.initAll();
76
76
  * grids.forEach(...)
77
77
  */
78
78
  static initAll(options = {}, selector = '.grid-stack') {
79
- let grids = [];
79
+ const grids = [];
80
80
  if (typeof document === 'undefined')
81
81
  return grids; // temp workaround SSR
82
82
  GridStack.getGridElements(selector).forEach(el => {
@@ -118,14 +118,11 @@ class GridStack {
118
118
  el = GridStack.addRemoveCB(parent, opt, true, true);
119
119
  }
120
120
  else {
121
- let doc = document.implementation.createHTMLDocument(''); // IE needs a param
122
- doc.body.innerHTML = `<div class="grid-stack ${opt.class || ''}"></div>`;
123
- el = doc.body.children[0];
124
- parent.appendChild(el);
121
+ el = Utils.createDiv(['grid-stack', opt.class], parent);
125
122
  }
126
123
  }
127
124
  // create grid class and load any children
128
- let grid = GridStack.init(opt, el);
125
+ const grid = GridStack.init(opt, el);
129
126
  return grid;
130
127
  }
131
128
  /** call this method to register your engine instead of the default one.
@@ -138,10 +135,10 @@ class GridStack {
138
135
  /** @internal create placeholder DIV as needed */
139
136
  get placeholder() {
140
137
  if (!this._placeholder) {
141
- let placeholderChild = document.createElement('div'); // child so padding match item-content
138
+ const placeholderChild = document.createElement('div'); // child so padding match item-content
142
139
  placeholderChild.className = 'placeholder-content';
143
140
  if (this.opts.placeholderText) {
144
- placeholderChild.innerHTML = this.opts.placeholderText;
141
+ placeholderChild.textContent = this.opts.placeholderText;
145
142
  }
146
143
  this._placeholder = document.createElement('div');
147
144
  this._placeholder.classList.add(this.opts.placeholderClass, gridDefaults.itemClass, this.opts.itemClass);
@@ -173,7 +170,7 @@ class GridStack {
173
170
  opts.minRow = opts.maxRow = opts.row;
174
171
  delete opts.row;
175
172
  }
176
- let rowAttr = Utils.toNumber(el.getAttribute('gs-row'));
173
+ const rowAttr = Utils.toNumber(el.getAttribute('gs-row'));
177
174
  // flag only valid in sub-grids (handled by parent, not here)
178
175
  if (opts.column === 'auto') {
179
176
  delete opts.column;
@@ -218,7 +215,7 @@ class GridStack {
218
215
  if (bk?.length > 1)
219
216
  bk.sort((a, b) => (b.w || 0) - (a.w || 0));
220
217
  // elements DOM attributes override any passed options (like CSS style) - merge the two together
221
- let defaults = {
218
+ const defaults = {
222
219
  ...Utils.cloneDeep(gridDefaults),
223
220
  column: Utils.toNumber(el.getAttribute('gs-column')) || gridDefaults.column,
224
221
  minRow: rowAttr ? rowAttr : Utils.toNumber(el.getAttribute('gs-min-row')) || gridDefaults.minRow,
@@ -247,13 +244,13 @@ class GridStack {
247
244
  this.el.classList.add('grid-stack-rtl');
248
245
  }
249
246
  // check if we're been nested, and if so update our style and keep pointer around (used during save)
250
- const grandParent = this.el.parentElement?.parentElement;
251
- let parentGridItem = grandParent?.classList.contains(gridDefaults.itemClass) ? grandParent.gridstackNode : undefined;
252
- if (parentGridItem) {
253
- parentGridItem.subGrid = this;
254
- this.parentGridItem = parentGridItem;
247
+ const parentGridItem = this.el.closest('.' + gridDefaults.itemClass);
248
+ const parentNode = parentGridItem?.gridstackNode;
249
+ if (parentNode) {
250
+ parentNode.subGrid = this;
251
+ this.parentGridNode = parentNode;
255
252
  this.el.classList.add('grid-stack-nested');
256
- parentGridItem.el.classList.add('grid-stack-sub-grid');
253
+ parentNode.el.classList.add('grid-stack-sub-grid');
257
254
  }
258
255
  this._isAutoCellHeight = (opts.cellHeight === 'auto');
259
256
  if (this._isAutoCellHeight || opts.cellHeight === 'initial') {
@@ -275,7 +272,7 @@ class GridStack {
275
272
  this._styleSheetClass = 'gs-id-' + GridStackEngine._idSeq++;
276
273
  this.el.classList.add(this._styleSheetClass);
277
274
  this._setStaticClass();
278
- let engineClass = opts.engineClass || GridStack.engineClass || GridStackEngine;
275
+ const engineClass = opts.engineClass || GridStack.engineClass || GridStackEngine;
279
276
  this.engine = new engineClass({
280
277
  column: this.getColumn(),
281
278
  float: opts.float,
@@ -284,7 +281,7 @@ class GridStack {
284
281
  let maxH = 0;
285
282
  this.engine.nodes.forEach(n => { maxH = Math.max(maxH, n.y + n.h); });
286
283
  cbNodes.forEach(n => {
287
- let el = n.el;
284
+ const el = n.el;
288
285
  if (!el)
289
286
  return;
290
287
  if (n._removeDOM) {
@@ -331,44 +328,35 @@ class GridStack {
331
328
  *
332
329
  * Widget will be always placed even if result height is more than actual grid height.
333
330
  * You need to use `willItFit()` before calling addWidget for additional check.
334
- * See also `makeWidget()`.
331
+ * See also `makeWidget(el)` for DOM element.
335
332
  *
336
333
  * @example
337
- * let grid = GridStack.init();
334
+ * const grid = GridStack.init();
338
335
  * grid.addWidget({w: 3, content: 'hello'});
339
- * grid.addWidget('<div class="grid-stack-item"><div class="grid-stack-item-content">hello</div></div>', {w: 3});
340
336
  *
341
- * @param el GridStackWidget (which can have content string as well), html element, or string definition to add
337
+ * @param w GridStackWidget definition. used MakeWidget(el) if you have dom element instead.
342
338
  * @param options widget position/size options (optional, and ignore if first param is already option) - see GridStackWidget
343
339
  */
344
- addWidget(els, options) {
345
- function isGridStackWidget(w) {
346
- return w.el !== undefined || w.x !== undefined || w.y !== undefined || w.w !== undefined || w.h !== undefined || w.content !== undefined ? true : false;
340
+ addWidget(w) {
341
+ if (typeof w === 'string') {
342
+ console.error('V11: GridStack.addWidget() does not support string anymore. see #2736');
343
+ return;
344
+ }
345
+ if (w.ELEMENT_NODE) {
346
+ console.error('V11: GridStack.addWidget() does not support HTMLElement anymore. use makeWidget()');
347
+ return this.makeWidget(w);
347
348
  }
348
349
  let el;
349
- let node;
350
- if (typeof els === 'string') {
351
- let doc = document.implementation.createHTMLDocument(''); // IE needs a param
352
- doc.body.innerHTML = els;
353
- el = doc.body.children[0];
350
+ let node = w;
351
+ node.grid = this;
352
+ if (node?.el) {
353
+ el = node.el; // re-use element stored in the node
354
354
  }
355
- else if (arguments.length === 0 || arguments.length === 1 && isGridStackWidget(els)) {
356
- node = options = els;
357
- if (node?.el) {
358
- el = node.el; // re-use element stored in the node
359
- }
360
- else if (GridStack.addRemoveCB) {
361
- el = GridStack.addRemoveCB(this.el, options, true, false);
362
- }
363
- else {
364
- let content = options?.content || '';
365
- let doc = document.implementation.createHTMLDocument(''); // IE needs a param
366
- doc.body.innerHTML = `<div class="grid-stack-item ${this.opts.itemClass || ''}"><div class="grid-stack-item-content">${content}</div></div>`;
367
- el = doc.body.children[0];
368
- }
355
+ else if (GridStack.addRemoveCB) {
356
+ el = GridStack.addRemoveCB(this.el, w, true, false);
369
357
  }
370
358
  else {
371
- el = els;
359
+ el = Utils.createWidgetDivs(this.opts.itemClass, node);
372
360
  }
373
361
  if (!el)
374
362
  return;
@@ -379,13 +367,12 @@ class GridStack {
379
367
  // Tempting to initialize the passed in opt with default and valid values, but this break knockout demos
380
368
  // as the actual value are filled in when _prepareElement() calls el.getAttribute('gs-xyz') before adding the node.
381
369
  // So make sure we load any DOM attributes that are not specified in passed in options (which override)
382
- let domAttr = this._readAttr(el);
383
- options = Utils.cloneDeep(options) || {}; // make a copy before we modify in case caller re-uses it
384
- Utils.defaults(options, domAttr);
385
- node = this.engine.prepareNode(options);
386
- this._writeAttr(el, options);
370
+ const domAttr = this._readAttr(el);
371
+ Utils.defaults(w, domAttr);
372
+ this.engine.prepareNode(w);
373
+ this._writeAttr(el, w);
387
374
  this.el.appendChild(el);
388
- this.makeWidget(el, options);
375
+ this.makeWidget(el, w);
389
376
  return el;
390
377
  }
391
378
  /**
@@ -409,7 +396,7 @@ class GridStack {
409
396
  let grid = this;
410
397
  while (grid && !subGridTemplate) {
411
398
  subGridTemplate = grid.opts?.subGridOpts;
412
- grid = grid.parentGridItem?.grid;
399
+ grid = grid.parentGridNode?.grid;
413
400
  }
414
401
  //... and set the create options
415
402
  ops = Utils.cloneDeep({ ...(subGridTemplate || {}), children: undefined, ...(ops || node.subGridOpts || {}) });
@@ -438,33 +425,29 @@ class GridStack {
438
425
  newItem = GridStack.addRemoveCB(this.el, newItemOpt, true, false);
439
426
  }
440
427
  else {
441
- let doc = document.implementation.createHTMLDocument(''); // IE needs a param
442
- doc.body.innerHTML = `<div class="grid-stack-item"></div>`;
443
- newItem = doc.body.children[0];
428
+ newItem = Utils.createDiv(['grid-stack-item']);
444
429
  newItem.appendChild(content);
445
- doc.body.innerHTML = `<div class="grid-stack-item-content"></div>`;
446
- content = doc.body.children[0];
447
- node.el.appendChild(content);
430
+ content = Utils.createDiv(['grid-stack-item-content'], node.el);
448
431
  }
449
432
  this._prepareDragDropByNode(node); // ... and restore original D&D
450
433
  }
451
434
  // if we're adding an additional item, make the container large enough to have them both
452
435
  if (nodeToAdd) {
453
- let w = autoColumn ? ops.column : node.w;
454
- let h = node.h + nodeToAdd.h;
455
- let style = node.el.style;
436
+ const w = autoColumn ? ops.column : node.w;
437
+ const h = node.h + nodeToAdd.h;
438
+ const style = node.el.style;
456
439
  style.transition = 'none'; // show up instantly so we don't see scrollbar with nodeToAdd
457
440
  this.update(node.el, { w, h });
458
441
  setTimeout(() => style.transition = null); // recover animation
459
442
  }
460
- let subGrid = node.subGrid = GridStack.addGrid(content, ops);
443
+ const subGrid = node.subGrid = GridStack.addGrid(content, ops);
461
444
  if (nodeToAdd?._moving)
462
445
  subGrid._isTemp = true; // prevent re-nesting as we add over
463
446
  if (autoColumn)
464
447
  subGrid._autoColumn = true;
465
448
  // add the original content back as a child of hte newly created grid
466
449
  if (saveContent) {
467
- subGrid.addWidget(newItem, newItemOpt);
450
+ subGrid.makeWidget(newItem, newItemOpt);
468
451
  }
469
452
  // now add any additional node
470
453
  if (nodeToAdd) {
@@ -473,7 +456,7 @@ class GridStack {
473
456
  window.setTimeout(() => Utils.simulateMouseEvent(nodeToAdd._event, 'mouseenter', subGrid.el), 0);
474
457
  }
475
458
  else {
476
- subGrid.addWidget(node.el, node);
459
+ subGrid.makeWidget(node.el, node);
477
460
  }
478
461
  }
479
462
  return subGrid;
@@ -483,21 +466,21 @@ class GridStack {
483
466
  * to the original grid-item. Also called to remove empty sub-grids when last item is dragged out (since re-creating is simple)
484
467
  */
485
468
  removeAsSubGrid(nodeThatRemoved) {
486
- let pGrid = this.parentGridItem?.grid;
469
+ const pGrid = this.parentGridNode?.grid;
487
470
  if (!pGrid)
488
471
  return;
489
472
  pGrid.batchUpdate();
490
- pGrid.removeWidget(this.parentGridItem.el, true, true);
473
+ pGrid.removeWidget(this.parentGridNode.el, true, true);
491
474
  this.engine.nodes.forEach(n => {
492
475
  // migrate any children over and offsetting by our location
493
- n.x += this.parentGridItem.x;
494
- n.y += this.parentGridItem.y;
495
- pGrid.addWidget(n.el, n);
476
+ n.x += this.parentGridNode.x;
477
+ n.y += this.parentGridNode.y;
478
+ pGrid.makeWidget(n.el, n);
496
479
  });
497
480
  pGrid.batchUpdate(false);
498
- if (this.parentGridItem)
499
- delete this.parentGridItem.subGrid;
500
- delete this.parentGridItem;
481
+ if (this.parentGridNode)
482
+ delete this.parentGridNode.subGrid;
483
+ delete this.parentGridNode;
501
484
  // create an artificial event for the original grid now that this one is gone (got a leave, but won't get enter)
502
485
  if (nodeThatRemoved) {
503
486
  window.setTimeout(() => Utils.simulateMouseEvent(nodeThatRemoved._event, 'mouseenter', pGrid.el), 0);
@@ -514,12 +497,12 @@ class GridStack {
514
497
  */
515
498
  save(saveContent = true, saveGridOpt = false, saveCB = GridStack.saveCB) {
516
499
  // return copied GridStackWidget (with optionally .el) we can modify at will...
517
- let list = this.engine.save(saveContent, saveCB);
500
+ const list = this.engine.save(saveContent, saveCB);
518
501
  // check for HTML content and nested grids
519
502
  list.forEach(n => {
520
503
  if (saveContent && n.el && !n.subGrid && !saveCB) { // sub-grid are saved differently, not plain content
521
- let sub = n.el.querySelector('.grid-stack-item-content');
522
- n.content = sub ? sub.innerHTML : undefined;
504
+ const itemContent = n.el.querySelector('.grid-stack-item-content');
505
+ n.content = itemContent?.innerHTML;
523
506
  if (!n.content)
524
507
  delete n.content;
525
508
  }
@@ -538,7 +521,7 @@ class GridStack {
538
521
  });
539
522
  // check if save entire grid options (needed for recursive) + children...
540
523
  if (saveGridOpt) {
541
- let o = Utils.cloneDeep(this.opts);
524
+ const o = Utils.cloneDeep(this.opts);
542
525
  // delete default values that will be recreated on launch
543
526
  if (o.marginBottom === o.marginTop && o.marginRight === o.marginLeft && o.marginTop === o.marginRight) {
544
527
  o.margin = o.marginTop;
@@ -599,7 +582,7 @@ class GridStack {
599
582
  const prevCB = GridStack.addRemoveCB;
600
583
  if (typeof (addRemove) === 'function')
601
584
  GridStack.addRemoveCB = addRemove;
602
- let removed = [];
585
+ const removed = [];
603
586
  this.batchUpdate();
604
587
  // if we are loading from empty temporarily remove animation
605
588
  const blank = !this.engine.nodes.length;
@@ -607,11 +590,11 @@ class GridStack {
607
590
  this.setAnimation(false);
608
591
  // see if any items are missing from new layout and need to be removed first
609
592
  if (!blank && addRemove) {
610
- let copyNodes = [...this.engine.nodes]; // don't loop through array you modify
593
+ const copyNodes = [...this.engine.nodes]; // don't loop through array you modify
611
594
  copyNodes.forEach(n => {
612
595
  if (!n.id)
613
596
  return;
614
- let item = Utils.find(items, n.id);
597
+ const item = Utils.find(items, n.id);
615
598
  if (!item) {
616
599
  if (GridStack.addRemoveCB)
617
600
  GridStack.addRemoveCB(this.el, n, false, false);
@@ -623,7 +606,7 @@ class GridStack {
623
606
  // now add/update the widgets - starting with removing items in the new layout we will reposition
624
607
  // to reduce collision and add no-coord ones at next available spot
625
608
  this.engine._loading = true; // help with collision
626
- let updateNodes = [];
609
+ const updateNodes = [];
627
610
  this.engine.nodes = this.engine.nodes.filter(n => {
628
611
  if (Utils.find(items, n.id)) {
629
612
  updateNodes.push(n);
@@ -632,7 +615,7 @@ class GridStack {
632
615
  return true;
633
616
  });
634
617
  items.forEach(w => {
635
- let item = Utils.find(updateNodes, w.id);
618
+ const item = Utils.find(updateNodes, w.id);
636
619
  if (item) {
637
620
  // 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)
638
621
  if (Utils.shouldSizeToContent(item))
@@ -651,7 +634,7 @@ class GridStack {
651
634
  }
652
635
  this.update(item.el, w);
653
636
  if (w.subGridOpts?.children) { // update any sub grid as well
654
- let sub = item.el.querySelector('.grid-stack');
637
+ const sub = item.el.querySelector('.grid-stack');
655
638
  if (sub && sub.gridstack) {
656
639
  sub.gridstack.load(w.subGridOpts.children); // TODO: support updating grid options ?
657
640
  }
@@ -709,13 +692,13 @@ class GridStack {
709
692
  return this.opts.cellHeight * (96 / 2.54) / 10;
710
693
  }
711
694
  // else get first cell height
712
- let el = this.el.querySelector('.' + this.opts.itemClass);
695
+ const el = this.el.querySelector('.' + this.opts.itemClass);
713
696
  if (el) {
714
- let h = Utils.toNumber(el.getAttribute('gs-h')) || 1; // since we don't write 1 anymore
697
+ const h = Utils.toNumber(el.getAttribute('gs-h')) || 1; // since we don't write 1 anymore
715
698
  return Math.round(el.offsetHeight / h);
716
699
  }
717
700
  // else do entire grid and # of rows (but doesn't work if min-height is the actual constrain)
718
- let rows = parseInt(this.el.getAttribute('gs-current-row'));
701
+ const rows = parseInt(this.el.getAttribute('gs-current-row'));
719
702
  return rows ? Math.round(this.el.getBoundingClientRect().height / rows) : this.opts.cellHeight;
720
703
  }
721
704
  /**
@@ -745,11 +728,11 @@ class GridStack {
745
728
  }
746
729
  // make item content be square
747
730
  if (val === undefined) {
748
- let marginDiff = -this.opts.marginRight - this.opts.marginLeft
731
+ const marginDiff = -this.opts.marginRight - this.opts.marginLeft
749
732
  + this.opts.marginTop + this.opts.marginBottom;
750
733
  val = this.cellWidth() + marginDiff;
751
734
  }
752
- let data = Utils.parseHeight(val);
735
+ const data = Utils.parseHeight(val);
753
736
  if (this.opts.cellHeightUnit === data.unit && this.opts.cellHeight === data.h) {
754
737
  return this;
755
738
  }
@@ -821,7 +804,7 @@ class GridStack {
821
804
  column(column, layout = 'moveScale') {
822
805
  if (!column || column < 1 || this.opts.column === column)
823
806
  return this;
824
- let oldColumn = this.getColumn();
807
+ const oldColumn = this.getColumn();
825
808
  this.opts.column = column;
826
809
  if (!this.engine)
827
810
  return this; // called in constructor, noting else to do
@@ -870,9 +853,9 @@ class GridStack {
870
853
  this.el.parentNode.removeChild(this.el);
871
854
  }
872
855
  this._removeStylesheet();
873
- if (this.parentGridItem)
874
- delete this.parentGridItem.subGrid;
875
- delete this.parentGridItem;
856
+ if (this.parentGridNode)
857
+ delete this.parentGridNode.subGrid;
858
+ delete this.parentGridNode;
876
859
  delete this.opts;
877
860
  delete this._placeholder;
878
861
  delete this.engine;
@@ -906,7 +889,7 @@ class GridStack {
906
889
  * Returns an object with properties `x` and `y` i.e. the column and row in the grid.
907
890
  */
908
891
  getCellFromPixel(position, useDocRelative = false) {
909
- let box = this.el.getBoundingClientRect();
892
+ const box = this.el.getBoundingClientRect();
910
893
  // console.log(`getBoundingClientRect left: ${box.left} top: ${box.top} w: ${box.w} h: ${box.h}`)
911
894
  let containerPos;
912
895
  if (useDocRelative) {
@@ -917,10 +900,10 @@ class GridStack {
917
900
  containerPos = { top: this.el.offsetTop, left: this.el.offsetLeft };
918
901
  // console.log(`getCellFromPixel offsetTop: ${containerPos.left} offsetLeft: ${containerPos.top}`)
919
902
  }
920
- let relativeLeft = position.left - containerPos.left;
921
- let relativeTop = position.top - containerPos.top;
922
- let columnWidth = (box.width / this.getColumn());
923
- let rowHeight = (box.height / parseInt(this.el.getAttribute('gs-current-row')));
903
+ const relativeLeft = position.left - containerPos.left;
904
+ const relativeTop = position.top - containerPos.top;
905
+ const columnWidth = (box.width / this.getColumn());
906
+ const rowHeight = (box.height / parseInt(this.el.getAttribute('gs-current-row')));
924
907
  return { x: Math.floor(relativeLeft / columnWidth), y: Math.floor(relativeTop / rowHeight) };
925
908
  }
926
909
  /** returns the current number of rows, which will be at least `minRow` if set */
@@ -945,14 +928,18 @@ class GridStack {
945
928
  * @param options widget definition to use instead of reading attributes or using default sizing values
946
929
  *
947
930
  * @example
948
- * let grid = GridStack.init();
931
+ * const grid = GridStack.init();
949
932
  * grid.el.appendChild('<div id="1" gs-w="3"></div>');
950
933
  * grid.el.appendChild('<div id="2"></div>');
951
934
  * grid.makeWidget('1');
952
935
  * grid.makeWidget('2', {w:2, content: 'hello'});
953
936
  */
954
937
  makeWidget(els, options) {
955
- let el = GridStack.getElement(els);
938
+ const el = GridStack.getElement(els);
939
+ if (!el)
940
+ return;
941
+ if (!el.parentElement)
942
+ this.el.appendChild(el);
956
943
  this._prepareElement(el, true, options);
957
944
  const node = el.gridstackNode;
958
945
  this._updateContainerHeight();
@@ -973,18 +960,19 @@ class GridStack {
973
960
  on(name, callback) {
974
961
  // check for array of names being passed instead
975
962
  if (name.indexOf(' ') !== -1) {
976
- let names = name.split(' ');
963
+ const names = name.split(' ');
977
964
  names.forEach(name => this.on(name, callback));
978
965
  return this;
979
966
  }
980
967
  // native CustomEvent handlers - cash the generic handlers so we can easily remove
981
968
  if (name === 'change' || name === 'added' || name === 'removed' || name === 'enable' || name === 'disable') {
982
- let noData = (name === 'enable' || name === 'disable');
969
+ const noData = (name === 'enable' || name === 'disable');
983
970
  if (noData) {
984
971
  this._gsEventHandler[name] = (event) => callback(event);
985
972
  }
986
973
  else {
987
- this._gsEventHandler[name] = (event) => callback(event, event.detail);
974
+ this._gsEventHandler[name] = (event) => { if (event.detail)
975
+ callback(event, event.detail); };
988
976
  }
989
977
  this.el.addEventListener(name, this._gsEventHandler[name]);
990
978
  }
@@ -1006,7 +994,7 @@ class GridStack {
1006
994
  off(name) {
1007
995
  // check for array of names being passed instead
1008
996
  if (name.indexOf(' ') !== -1) {
1009
- let names = name.split(' ');
997
+ const names = name.split(' ');
1010
998
  names.forEach(name => this.off(name));
1011
999
  return this;
1012
1000
  }
@@ -1031,6 +1019,10 @@ class GridStack {
1031
1019
  * @param triggerEvent if `false` (quiet mode) element will not be added to removed list and no 'removed' callbacks will be called (Default? true).
1032
1020
  */
1033
1021
  removeWidget(els, removeDOM = true, triggerEvent = true) {
1022
+ if (!els) {
1023
+ console.error('Error: GridStack.removeWidget(undefined) called');
1024
+ return this;
1025
+ }
1034
1026
  GridStack.getElements(els).forEach(el => {
1035
1027
  if (el.parentElement && el.parentElement !== this.el)
1036
1028
  return; // not our child!
@@ -1132,20 +1124,21 @@ class GridStack {
1132
1124
  if (arguments.length > 2) {
1133
1125
  console.warn('gridstack.ts: `update(el, x, y, w, h)` is deprecated. Use `update(el, {x, w, content, ...})`. It will be removed soon');
1134
1126
  // eslint-disable-next-line prefer-rest-params
1135
- let a = arguments, i = 1;
1127
+ const a = arguments;
1128
+ let i = 1;
1136
1129
  opt = { x: a[i++], y: a[i++], w: a[i++], h: a[i++] };
1137
1130
  return this.update(els, opt);
1138
1131
  }
1139
1132
  GridStack.getElements(els).forEach(el => {
1140
- let n = el?.gridstackNode;
1133
+ const n = el?.gridstackNode;
1141
1134
  if (!n)
1142
1135
  return;
1143
- let w = Utils.cloneDeep(opt); // make a copy we can modify in case they re-use it or multiple items
1136
+ const w = Utils.cloneDeep(opt); // make a copy we can modify in case they re-use it or multiple items
1144
1137
  this.engine.nodeBoundFix(w);
1145
1138
  delete w.autoPosition;
1146
1139
  delete w.id;
1147
1140
  // move/resize widget if anything changed
1148
- let keys = ['x', 'y', 'w', 'h'];
1141
+ const keys = ['x', 'y', 'w', 'h'];
1149
1142
  let m;
1150
1143
  if (keys.some(k => w[k] !== undefined && w[k] !== n[k])) {
1151
1144
  m = {};
@@ -1161,8 +1154,8 @@ class GridStack {
1161
1154
  // check for content changing
1162
1155
  if (w.content !== undefined) {
1163
1156
  const itemContent = el.querySelector('.grid-stack-item-content');
1164
- if (itemContent && itemContent.innerHTML !== w.content) {
1165
- itemContent.innerHTML = w.content;
1157
+ if (itemContent && itemContent.textContent !== w.content) {
1158
+ GridStack.renderCB(itemContent, w);
1166
1159
  // restore any sub-grid back
1167
1160
  if (n.subGrid?.el) {
1168
1161
  itemContent.appendChild(n.subGrid.el);
@@ -1246,6 +1239,10 @@ class GridStack {
1246
1239
  // sub-grid - use their actual row count * their cell height
1247
1240
  wantedH = n.subGrid.getRow() * n.subGrid.getCellHeight(true);
1248
1241
  }
1242
+ else if (n.subGridOpts?.children?.length) {
1243
+ // not sub-grid just yet (case above) wait until we do
1244
+ return;
1245
+ }
1249
1246
  else {
1250
1247
  // NOTE: clientHeight & getBoundingClientRect() is undefined for text and other leaf nodes. use <div> container!
1251
1248
  const child = item.firstElementChild;
@@ -1288,18 +1285,22 @@ class GridStack {
1288
1285
  */
1289
1286
  rotate(els, relative) {
1290
1287
  GridStack.getElements(els).forEach(el => {
1291
- let n = el.gridstackNode;
1288
+ const n = el.gridstackNode;
1292
1289
  if (!Utils.canBeRotated(n))
1293
1290
  return;
1294
1291
  const rot = { w: n.h, h: n.w, minH: n.minW, minW: n.minH, maxH: n.maxW, maxW: n.maxH };
1295
1292
  // if given an offset, adjust x/y by column/row bounds when user presses 'r' during dragging
1296
1293
  if (relative) {
1297
- let pivotX = relative.left > 0 ? Math.floor(relative.left / this.cellWidth()) : 0;
1298
- let pivotY = relative.top > 0 ? Math.floor(relative.top / this.opts.cellHeight) : 0;
1294
+ const pivotX = relative.left > 0 ? Math.floor(relative.left / this.cellWidth()) : 0;
1295
+ const pivotY = relative.top > 0 ? Math.floor(relative.top / this.opts.cellHeight) : 0;
1299
1296
  rot.x = n.x + pivotX - (n.h - (pivotY + 1));
1300
1297
  rot.y = (n.y + pivotY) - pivotX;
1301
1298
  }
1299
+ Object.keys(rot).forEach(k => { if (rot[k] === undefined)
1300
+ delete rot[k]; });
1301
+ const _orig = n._orig;
1302
1302
  this.update(el, rot);
1303
+ n._orig = _orig; // restore as move() will delete it
1303
1304
  });
1304
1305
  return this;
1305
1306
  }
@@ -1308,10 +1309,10 @@ class GridStack {
1308
1309
  * @param value margin value
1309
1310
  */
1310
1311
  margin(value) {
1311
- let isMultiValue = (typeof value === 'string' && value.split(' ').length > 1);
1312
+ const isMultiValue = (typeof value === 'string' && value.split(' ').length > 1);
1312
1313
  // check if we can skip re-creating our CSS file... won't check if multi values (too much hassle)
1313
1314
  if (!isMultiValue) {
1314
- let data = Utils.parseHeight(value);
1315
+ const data = Utils.parseHeight(value);
1315
1316
  if (this.opts.marginUnit === data.unit && this.opts.margin === data.h)
1316
1317
  return;
1317
1318
  }
@@ -1341,7 +1342,8 @@ class GridStack {
1341
1342
  if (arguments.length > 1) {
1342
1343
  console.warn('gridstack.ts: `willItFit(x,y,w,h,autoPosition)` is deprecated. Use `willItFit({x, y,...})`. It will be removed soon');
1343
1344
  // eslint-disable-next-line prefer-rest-params
1344
- let a = arguments, i = 0, w = { x: a[i++], y: a[i++], w: a[i++], h: a[i++], autoPosition: a[i++] };
1345
+ const a = arguments;
1346
+ let i = 0, w = { x: a[i++], y: a[i++], w: a[i++], h: a[i++], autoPosition: a[i++] };
1345
1347
  return this.willItFit(w);
1346
1348
  }
1347
1349
  return this.engine.willItFit(node);
@@ -1350,7 +1352,7 @@ class GridStack {
1350
1352
  _triggerChangeEvent() {
1351
1353
  if (this.engine.batchMode)
1352
1354
  return this;
1353
- let elements = this.engine.getDirtyNodes(true); // verify they really changed
1355
+ const elements = this.engine.getDirtyNodes(true); // verify they really changed
1354
1356
  if (elements && elements.length) {
1355
1357
  if (!this._ignoreLayoutsNodeChange) {
1356
1358
  this.engine.layoutsNodesChange(elements);
@@ -1389,7 +1391,7 @@ class GridStack {
1389
1391
  }
1390
1392
  /** @internal */
1391
1393
  _triggerEvent(type, data) {
1392
- let event = data ? new CustomEvent(type, { bubbles: false, detail: data }) : new Event(type);
1394
+ const event = data ? new CustomEvent(type, { bubbles: false, detail: data }) : new Event(type);
1393
1395
  this.el.dispatchEvent(event);
1394
1396
  return this;
1395
1397
  }
@@ -1415,9 +1417,9 @@ class GridStack {
1415
1417
  if (this.opts.cellHeight === 0) {
1416
1418
  return this;
1417
1419
  }
1418
- let cellHeight = this.opts.cellHeight;
1419
- let cellHeightUnit = this.opts.cellHeightUnit;
1420
- let prefix = `.${this._styleSheetClass} > .${this.opts.itemClass}`;
1420
+ const cellHeight = this.opts.cellHeight;
1421
+ const cellHeightUnit = this.opts.cellHeightUnit;
1422
+ const prefix = `.${this._styleSheetClass} > .${this.opts.itemClass}`;
1421
1423
  // create one as needed
1422
1424
  if (!this._styles) {
1423
1425
  // insert style to parent (instead of 'head' by default) to support WebComponent
@@ -1431,12 +1433,12 @@ class GridStack {
1431
1433
  // these are done once only
1432
1434
  Utils.addCSSRule(this._styles, prefix, `height: ${cellHeight}${cellHeightUnit}`);
1433
1435
  // content margins
1434
- let top = this.opts.marginTop + this.opts.marginUnit;
1435
- let bottom = this.opts.marginBottom + this.opts.marginUnit;
1436
- let right = this.opts.marginRight + this.opts.marginUnit;
1437
- let left = this.opts.marginLeft + this.opts.marginUnit;
1438
- let content = `${prefix} > .grid-stack-item-content`;
1439
- let placeholder = `.${this._styleSheetClass} > .grid-stack-placeholder > .placeholder-content`;
1436
+ const top = this.opts.marginTop + this.opts.marginUnit;
1437
+ const bottom = this.opts.marginBottom + this.opts.marginUnit;
1438
+ const right = this.opts.marginRight + this.opts.marginUnit;
1439
+ const left = this.opts.marginLeft + this.opts.marginUnit;
1440
+ const content = `${prefix} > .grid-stack-item-content`;
1441
+ const placeholder = `.${this._styleSheetClass} > .grid-stack-placeholder > .placeholder-content`;
1440
1442
  Utils.addCSSRule(this._styles, content, `top: ${top}; right: ${right}; bottom: ${bottom}; left: ${left};`);
1441
1443
  Utils.addCSSRule(this._styles, placeholder, `top: ${top}; right: ${right}; bottom: ${bottom}; left: ${left};`);
1442
1444
  // resize handles offset (to match margin)
@@ -1452,7 +1454,7 @@ class GridStack {
1452
1454
  // now update the height specific fields
1453
1455
  maxH = maxH || this._styles._max;
1454
1456
  if (maxH > this._styles._max) {
1455
- let getHeight = (rows) => (cellHeight * rows) + cellHeightUnit;
1457
+ const getHeight = (rows) => (cellHeight * rows) + cellHeightUnit;
1456
1458
  for (let i = this._styles._max + 1; i <= maxH; i++) { // start at 1
1457
1459
  Utils.addCSSRule(this._styles, `${prefix}[gs-y="${i}"]`, `top: ${getHeight(i)}`);
1458
1460
  Utils.addCSSRule(this._styles, `${prefix}[gs-h="${i + 1}"]`, `height: ${getHeight(i + 1)}`); // start at 2
@@ -1465,7 +1467,7 @@ class GridStack {
1465
1467
  _updateContainerHeight() {
1466
1468
  if (!this.engine || this.engine.batchMode)
1467
1469
  return this;
1468
- const parent = this.parentGridItem;
1470
+ const parent = this.parentGridNode;
1469
1471
  let row = this.getRow() + this._extraDragRow; // this checks for minRow already
1470
1472
  const cellHeight = this.opts.cellHeight;
1471
1473
  const unit = this.opts.cellHeightUnit;
@@ -1528,8 +1530,8 @@ class GridStack {
1528
1530
  if (!node)
1529
1531
  return this;
1530
1532
  this._writePosAttr(el, node);
1531
- let attrs /*: GridStackWidget but strings */ = {
1532
- autoPosition: 'gs-auto-position',
1533
+ const attrs /*: GridStackWidget but strings */ = {
1534
+ // autoPosition: 'gs-auto-position', // no need to write out as already in node and doesn't affect CSS
1533
1535
  noResize: 'gs-no-resize',
1534
1536
  noMove: 'gs-no-move',
1535
1537
  locked: 'gs-locked',
@@ -1547,7 +1549,7 @@ class GridStack {
1547
1549
  }
1548
1550
  /** @internal call to read any default attributes from element */
1549
1551
  _readAttr(el, clearDefaultAttr = true) {
1550
- let n = {};
1552
+ const n = {};
1551
1553
  n.x = Utils.toNumber(el.getAttribute('gs-x'));
1552
1554
  n.y = Utils.toNumber(el.getAttribute('gs-y'));
1553
1555
  n.w = Utils.toNumber(el.getAttribute('gs-w'));
@@ -1589,7 +1591,7 @@ class GridStack {
1589
1591
  }
1590
1592
  /** @internal */
1591
1593
  _setStaticClass() {
1592
- let classes = ['grid-stack-static'];
1594
+ const classes = ['grid-stack-static'];
1593
1595
  if (this.opts.staticGrid) {
1594
1596
  this.el.classList.add(...classes);
1595
1597
  this.el.setAttribute('gs-static', 'true');
@@ -1615,9 +1617,9 @@ class GridStack {
1615
1617
  this.batchUpdate();
1616
1618
  // see if we're nested and take our column count from our parent....
1617
1619
  let columnChanged = false;
1618
- if (this._autoColumn && this.parentGridItem) {
1619
- if (this.opts.column !== this.parentGridItem.w) {
1620
- this.column(this.parentGridItem.w, 'none');
1620
+ if (this._autoColumn && this.parentGridNode) {
1621
+ if (this.opts.column !== this.parentGridNode.w) {
1622
+ this.column(this.parentGridNode.w, 'none');
1621
1623
  columnChanged = true;
1622
1624
  }
1623
1625
  }
@@ -1668,7 +1670,7 @@ class GridStack {
1668
1670
  _updateResizeEvent(forceRemove = false) {
1669
1671
  // 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)
1670
1672
  // or supporting new sizeToContent option.
1671
- const trackSize = !this.parentGridItem && (this._isAutoCellHeight || this.opts.sizeToContent || this.opts.columnOpts
1673
+ const trackSize = !this.parentGridNode && (this._isAutoCellHeight || this.opts.sizeToContent || this.opts.columnOpts
1672
1674
  || this.engine.nodes.find(n => n.sizeToContent));
1673
1675
  if (!forceRemove && trackSize && !this.resizeObserver) {
1674
1676
  this._sizeThrottle = Utils.throttle(() => this.onResize(), this.opts.cellHeightThrottle);
@@ -1767,21 +1769,23 @@ class GridStack {
1767
1769
  * call to setup dragging in from the outside (say toolbar), by specifying the class selection and options.
1768
1770
  * Called during GridStack.init() as options, but can also be called directly (last param are used) in case the toolbar
1769
1771
  * is dynamically create and needs to be set later.
1770
- * @param dragIn string selector (ex: '.sidebar .grid-stack-item') or list of dom elements
1771
- * @param dragInOptions options - see DDDragInOpt. (default: {handle: '.grid-stack-item-content', appendTo: 'body'}
1772
- * @param root optional root which defaults to document (for shadow dom pas the parent HTMLDocument)
1772
+ * @param dragIn string selector (ex: '.sidebar-item') or list of dom elements
1773
+ * @param dragInOptions options - see DDDragOpt. (default: {handle: '.grid-stack-item-content', appendTo: 'body'}
1774
+ * @param widgets GridStackWidget def to assign to each element which defines what to create on drop
1775
+ * @param root optional root which defaults to document (for shadow dom pass the parent HTMLDocument)
1773
1776
  */
1774
- static setupDragIn(dragIn, dragInOptions, root = document) {
1777
+ static setupDragIn(dragIn, dragInOptions, widgets, root = document) {
1775
1778
  if (dragInOptions?.pause !== undefined) {
1776
1779
  DDManager.pauseDrag = dragInOptions.pause;
1777
1780
  }
1778
- dragInOptions = { ...dragInDefaultOptions, ...(dragInOptions || {}) };
1779
- let els = (typeof dragIn === 'string') ? Utils.getElements(dragIn, root) : dragIn;
1780
- if (els.length)
1781
- els?.forEach(el => {
1782
- if (!dd.isDraggable(el))
1783
- dd.dragIn(el, dragInOptions);
1784
- });
1781
+ dragInOptions = { appendTo: 'body', helper: 'clone', ...(dragInOptions || {}) }; // default to handle:undefined = drag by the whole item
1782
+ const els = (typeof dragIn === 'string') ? Utils.getElements(dragIn, root) : dragIn;
1783
+ els.forEach((el, i) => {
1784
+ if (!dd.isDraggable(el))
1785
+ dd.dragIn(el, dragInOptions);
1786
+ if (widgets?.[i])
1787
+ el.gridstackNode = widgets[i];
1788
+ });
1785
1789
  }
1786
1790
  /**
1787
1791
  * Enables/Disables dragging by the user of specific grid element. If you want all items, and have it affect future items, use enableMove() instead. No-op for static grids.
@@ -1810,7 +1814,7 @@ class GridStack {
1810
1814
  if (this.opts.staticGrid)
1811
1815
  return this; // can't resize a static grid!
1812
1816
  GridStack.getElements(els).forEach(el => {
1813
- let n = el.gridstackNode;
1817
+ const n = el.gridstackNode;
1814
1818
  if (!n)
1815
1819
  return;
1816
1820
  val ? delete n.noResize : n.noResize = true;
@@ -1901,11 +1905,11 @@ class GridStack {
1901
1905
  }
1902
1906
  // vars shared across all methods
1903
1907
  let cellHeight, cellWidth;
1904
- let onDrag = (event, el, helper) => {
1905
- let node = el.gridstackNode;
1908
+ const onDrag = (event, el, helper) => {
1909
+ helper = helper || el;
1910
+ const node = helper.gridstackNode;
1906
1911
  if (!node)
1907
1912
  return;
1908
- helper = helper || el;
1909
1913
  // if the element is being dragged from outside, scale it down to match the grid's scale
1910
1914
  // and slightly adjust its position relative to the mouse
1911
1915
  if (!node.grid?.el) {
@@ -1917,11 +1921,11 @@ class GridStack {
1917
1921
  helper.style.top = helperRect.y + (this.dragTransform.yScale - 1) * (event.clientY - helperRect.y) / this.dragTransform.yScale + 'px';
1918
1922
  helper.style.transformOrigin = `0px 0px`;
1919
1923
  }
1920
- let parent = this.el.getBoundingClientRect();
1921
1924
  let { top, left } = helper.getBoundingClientRect();
1922
- left -= parent.left;
1923
- top -= parent.top;
1924
- let ui = {
1925
+ const rect = this.el.getBoundingClientRect();
1926
+ left -= rect.left;
1927
+ top -= rect.top;
1928
+ const ui = {
1925
1929
  position: {
1926
1930
  top: top * this.dragTransform.xScale,
1927
1931
  left: left * this.dragTransform.yScale
@@ -1955,7 +1959,7 @@ class GridStack {
1955
1959
  };
1956
1960
  dd.droppable(this.el, {
1957
1961
  accept: (el) => {
1958
- let node = el.gridstackNode || this._readAttr(el, false);
1962
+ const node = el.gridstackNode || this._readAttr(el, false);
1959
1963
  // set accept drop to true on ourself (which we ignore) so we don't get "can't drop" icon in HTML5 mode while moving
1960
1964
  if (node?.grid === this)
1961
1965
  return true;
@@ -1967,12 +1971,12 @@ class GridStack {
1967
1971
  canAccept = this.opts.acceptWidgets(el);
1968
1972
  }
1969
1973
  else {
1970
- let selector = (this.opts.acceptWidgets === true ? '.grid-stack-item' : this.opts.acceptWidgets);
1974
+ const selector = (this.opts.acceptWidgets === true ? '.grid-stack-item' : this.opts.acceptWidgets);
1971
1975
  canAccept = el.matches(selector);
1972
1976
  }
1973
1977
  // finally check to make sure we actually have space left #1571 #2633
1974
1978
  if (canAccept && node && this.opts.maxRow) {
1975
- let n = { w: node.w, h: node.h, minW: node.minW, minH: node.minH }; // only width/height matters and autoPosition
1979
+ const n = { w: node.w, h: node.h, minW: node.minW, minH: node.minH }; // only width/height matters and autoPosition
1976
1980
  canAccept = this.engine.willItFit(n);
1977
1981
  }
1978
1982
  return canAccept;
@@ -1983,7 +1987,7 @@ class GridStack {
1983
1987
  */
1984
1988
  .on(this.el, 'dropover', (event, el, helper) => {
1985
1989
  // console.log(`over ${this.el.gridstack.opts.id} ${count++}`); // TEST
1986
- let node = el.gridstackNode;
1990
+ let node = helper?.gridstackNode || el.gridstackNode;
1987
1991
  // ignore drop enter on ourself (unless we temporarily removed) which happens on a simple drag of our item
1988
1992
  if (node?.grid === this && !node._temporaryRemoved) {
1989
1993
  // delete node._added; // reset this to track placeholder again in case we were over other grid #1484 (dropout doesn't always clear)
@@ -1992,24 +1996,36 @@ class GridStack {
1992
1996
  // fix #1578 when dragging fast, we may not get a leave on the previous grid so force one now
1993
1997
  if (node?.grid && node.grid !== this && !node._temporaryRemoved) {
1994
1998
  // console.log('dropover without leave'); // TEST
1995
- let otherGrid = node.grid;
1999
+ const otherGrid = node.grid;
1996
2000
  otherGrid._leave(el, helper);
1997
2001
  }
2002
+ helper = helper || el;
1998
2003
  // cache cell dimensions (which don't change), position can animate if we removed an item in otherGrid that affects us...
1999
2004
  cellWidth = this.cellWidth();
2000
2005
  cellHeight = this.getCellHeight(true);
2001
- // load any element attributes if we don't have a node
2006
+ // sidebar items: load any element attributes if we don't have a node
2002
2007
  if (!node) {
2003
- node = this._readAttr(el, false); // don't wipe external (e.g. drag toolbar) attr #2354
2008
+ if (helper.hasAttribute('gridstacknode')) {
2009
+ try {
2010
+ node = JSON.parse(helper.getAttribute('gridstacknode'));
2011
+ }
2012
+ catch (error) {
2013
+ console.error("Gridstack dropover: Bad JSON format: ", helper.getAttribute('gridstacknode'));
2014
+ }
2015
+ helper.removeAttribute('gridstacknode');
2016
+ }
2017
+ if (!node)
2018
+ node = this._readAttr(helper); // used to pass false for #2354, but now we clone top level node
2004
2019
  }
2005
- if (!node.grid) {
2020
+ if (!node.grid) { // sidebar item
2021
+ if (!node.el)
2022
+ node = { ...node }; // clone first time we're coming from sidebar (since 'clone' doesn't copy vars)
2006
2023
  node._isExternal = true;
2007
- el.gridstackNode = node;
2024
+ helper.gridstackNode = node;
2008
2025
  }
2009
2026
  // calculate the grid size based on element outer size
2010
- helper = helper || el;
2011
- let w = node.w || Math.round(helper.offsetWidth / cellWidth) || 1;
2012
- let h = node.h || Math.round(helper.offsetHeight / cellHeight) || 1;
2027
+ const w = node.w || Math.round(helper.offsetWidth / cellWidth) || 1;
2028
+ const h = node.h || Math.round(helper.offsetHeight / cellHeight) || 1;
2013
2029
  // if the item came from another grid, make a copy and save the original info in case we go back there
2014
2030
  if (node.grid && node.grid !== this) {
2015
2031
  // copy the node original values (min/max/id/etc...) but override width/height/other flags which are this grid specific
@@ -2043,7 +2059,7 @@ class GridStack {
2043
2059
  */
2044
2060
  .on(this.el, 'dropout', (event, el, helper) => {
2045
2061
  // console.log(`out ${this.el.gridstack.opts.id} ${count++}`); // TEST
2046
- let node = el.gridstackNode;
2062
+ const node = helper?.gridstackNode || el.gridstackNode;
2047
2063
  if (!node)
2048
2064
  return false;
2049
2065
  // fix #1578 when dragging fast, we might get leave after other grid gets enter (which calls us to clean)
@@ -2061,11 +2077,12 @@ class GridStack {
2061
2077
  * end - releasing the mouse
2062
2078
  */
2063
2079
  .on(this.el, 'drop', (event, el, helper) => {
2064
- let node = el.gridstackNode;
2080
+ const node = helper?.gridstackNode || el.gridstackNode;
2065
2081
  // ignore drop on ourself from ourself that didn't come from the outside - dragend will handle the simple move instead
2066
2082
  if (node?.grid === this && !node._isExternal)
2067
2083
  return false;
2068
2084
  const wasAdded = !!this.placeholder.parentElement; // skip items not actually added to us because of constrains, but do cleanup #1419
2085
+ const wasSidebar = el !== helper;
2069
2086
  this.placeholder.remove();
2070
2087
  // disable animation when replacing a placeholder (already positioned) with actual content
2071
2088
  const noAnim = wasAdded && this.opts.animate;
@@ -2073,15 +2090,15 @@ class GridStack {
2073
2090
  this.setAnimation(false);
2074
2091
  // notify previous grid of removal
2075
2092
  // console.log('drop delete _gridstackNodeOrig') // TEST
2076
- let origNode = el._gridstackNodeOrig;
2093
+ const origNode = el._gridstackNodeOrig;
2077
2094
  delete el._gridstackNodeOrig;
2078
2095
  if (wasAdded && origNode?.grid && origNode.grid !== this) {
2079
- let oGrid = origNode.grid;
2096
+ const oGrid = origNode.grid;
2080
2097
  oGrid.engine.removeNodeFromLayoutCache(origNode);
2081
2098
  oGrid.engine.removedNodes.push(origNode);
2082
2099
  oGrid._triggerRemoveEvent()._triggerChangeEvent();
2083
2100
  // if it's an empty sub-grid that got auto-created, nuke it
2084
- if (oGrid.parentGridItem && !oGrid.engine.nodes.length && oGrid.opts.subGridDynamic) {
2101
+ if (oGrid.parentGridNode && !oGrid.engine.nodes.length && oGrid.opts.subGridDynamic) {
2085
2102
  oGrid.removeAsSubGrid();
2086
2103
  }
2087
2104
  }
@@ -2094,37 +2111,39 @@ class GridStack {
2094
2111
  }
2095
2112
  delete node.grid?._isTemp;
2096
2113
  dd.off(el, 'drag');
2097
- // if we made a copy ('helper' which is temp) of the original node then insert a copy, else we move the original node (#1102)
2098
- // as the helper will be nuked by jquery-ui otherwise. TODO: update old code path
2114
+ // if we made a copy insert that instead of the original (sidebar item)
2099
2115
  if (helper !== el) {
2100
2116
  helper.remove();
2101
- el.gridstackNode = origNode; // original item (left behind) is re-stored to pre dragging as the node now has drop info
2102
- if (wasAdded) {
2103
- el = el.cloneNode(true);
2104
- }
2117
+ el = helper;
2105
2118
  }
2106
2119
  else {
2107
2120
  el.remove(); // reduce flicker as we change depth here, and size further down
2108
- this._removeDD(el);
2109
2121
  }
2122
+ this._removeDD(el);
2110
2123
  if (!wasAdded)
2111
2124
  return false;
2112
- el.gridstackNode = node;
2113
- node.el = el;
2114
- let subGrid = node.subGrid?.el?.gridstack; // set when actual sub-grid present
2115
- // @ts-ignore
2125
+ const subGrid = node.subGrid?.el?.gridstack; // set when actual sub-grid present
2116
2126
  Utils.copyPos(node, this._readAttr(this.placeholder)); // placeholder values as moving VERY fast can throw things off #1578
2117
- Utils.removePositioningStyles(el); // @ts-ignore
2118
- this.el.appendChild(el); // @ts-ignore // TODO: now would be ideal time to _removeHelperStyle() overriding floating styles (native only)
2119
- this._prepareElement(el, true, node);
2120
- if (subGrid) {
2121
- subGrid.parentGridItem = node;
2122
- if (!subGrid.opts.styleInHead)
2123
- subGrid._updateStyles(true); // re-create sub-grid styles now that we've moved
2127
+ Utils.removePositioningStyles(el);
2128
+ // give the user a chance to alter the widget that will get inserted if new sidebar item
2129
+ if (wasSidebar && (node.content || node.subGridOpts || GridStack.addRemoveCB)) {
2130
+ delete node.el;
2131
+ el = this.addWidget(node);
2124
2132
  }
2125
- this._updateContainerHeight();
2126
- this.engine.addedNodes.push(node); // @ts-ignore
2127
- this._triggerAddEvent(); // @ts-ignore
2133
+ else {
2134
+ this._prepareElement(el, true, node);
2135
+ this.el.appendChild(el);
2136
+ // resizeToContent is skipped in _prepareElement() until node is visible (clientHeight=0) so call it now
2137
+ this.resizeToContentCheck(false, node);
2138
+ if (subGrid) {
2139
+ subGrid.parentGridNode = node;
2140
+ if (!subGrid.opts.styleInHead)
2141
+ subGrid._updateStyles(true); // re-create sub-grid styles now that we've moved
2142
+ }
2143
+ this._updateContainerHeight();
2144
+ }
2145
+ this.engine.addedNodes.push(node);
2146
+ this._triggerAddEvent();
2128
2147
  this._triggerChangeEvent();
2129
2148
  this.engine.endUpdate();
2130
2149
  if (this._gsEventHandler['dropped']) {
@@ -2139,6 +2158,8 @@ class GridStack {
2139
2158
  }
2140
2159
  /** @internal mark item for removal */
2141
2160
  static _itemRemoving(el, remove) {
2161
+ if (!el)
2162
+ return;
2142
2163
  const node = el ? el.gridstackNode : undefined;
2143
2164
  if (!node?.grid || el.classList.contains(node.grid.opts.removableOptions.decline))
2144
2165
  return;
@@ -2149,7 +2170,7 @@ class GridStack {
2149
2170
  _setupRemoveDrop() {
2150
2171
  if (typeof this.opts.removable !== 'string')
2151
2172
  return this;
2152
- let trashEl = document.querySelector(this.opts.removable);
2173
+ const trashEl = document.querySelector(this.opts.removable);
2153
2174
  if (!trashEl)
2154
2175
  return this;
2155
2176
  // only register ONE static drop-over/dropout callback for the 'trash', and it will
@@ -2164,7 +2185,7 @@ class GridStack {
2164
2185
  }
2165
2186
  /** @internal prepares the element for drag&drop */
2166
2187
  _prepareDragDropByNode(node) {
2167
- let el = node.el;
2188
+ const el = node.el;
2168
2189
  const noMove = node.noMove || this.opts.disableDrag;
2169
2190
  const noResize = node.noResize || this.opts.disableResize;
2170
2191
  // check for disabled grid first
@@ -2181,7 +2202,7 @@ class GridStack {
2181
2202
  let cellWidth;
2182
2203
  let cellHeight;
2183
2204
  /** called when item starts moving/resizing */
2184
- let onStartMoving = (event, ui) => {
2205
+ const onStartMoving = (event, ui) => {
2185
2206
  // trigger any 'dragstart' / 'resizestart' manually
2186
2207
  if (this._gsEventHandler[event.type]) {
2187
2208
  this._gsEventHandler[event.type](event, event.target);
@@ -2191,23 +2212,23 @@ class GridStack {
2191
2212
  this._onStartMoving(el, event, ui, node, cellWidth, cellHeight);
2192
2213
  };
2193
2214
  /** called when item is being dragged/resized */
2194
- let dragOrResize = (event, ui) => {
2215
+ const dragOrResize = (event, ui) => {
2195
2216
  this._dragOrResize(el, event, ui, node, cellWidth, cellHeight);
2196
2217
  };
2197
2218
  /** called when the item stops moving/resizing */
2198
- let onEndMoving = (event) => {
2219
+ const onEndMoving = (event) => {
2199
2220
  this.placeholder.remove();
2200
2221
  delete node._moving;
2201
2222
  delete node._event;
2202
2223
  delete node._lastTried;
2203
2224
  const widthChanged = node.w !== node._orig.w;
2204
2225
  // if the item has moved to another grid, we're done here
2205
- let target = event.target;
2226
+ const target = event.target;
2206
2227
  if (!target.gridstackNode || target.gridstackNode.grid !== this)
2207
2228
  return;
2208
2229
  node.el = target;
2209
2230
  if (node._isAboutToRemove) {
2210
- let grid = el.gridstackNode.grid;
2231
+ const grid = el.gridstackNode.grid;
2211
2232
  if (grid._gsEventHandler[event.type]) {
2212
2233
  grid._gsEventHandler[event.type](event, target);
2213
2234
  }
@@ -2304,16 +2325,18 @@ class GridStack {
2304
2325
  dd.resizable(el, 'option', 'minWidth', cellWidth * Math.min(node.minW || 1, colLeft))
2305
2326
  .resizable(el, 'option', 'minHeight', cellHeight * Math.min(node.minH || 1, rowLeft))
2306
2327
  .resizable(el, 'option', 'maxWidth', cellWidth * Math.min(node.maxW || Number.MAX_SAFE_INTEGER, colLeft))
2307
- .resizable(el, 'option', 'maxHeight', cellHeight * Math.min(node.maxH || Number.MAX_SAFE_INTEGER, rowLeft));
2328
+ .resizable(el, 'option', 'maxWidthMoveLeft', cellWidth * Math.min(node.maxW || Number.MAX_SAFE_INTEGER, node.x + node.w))
2329
+ .resizable(el, 'option', 'maxHeight', cellHeight * Math.min(node.maxH || Number.MAX_SAFE_INTEGER, rowLeft))
2330
+ .resizable(el, 'option', 'maxHeightMoveUp', cellHeight * Math.min(node.maxH || Number.MAX_SAFE_INTEGER, node.y + node.h));
2308
2331
  }
2309
2332
  }
2310
2333
  /** @internal handles actual drag/resize */
2311
2334
  _dragOrResize(el, event, ui, node, cellWidth, cellHeight) {
2312
- let p = { ...node._orig }; // could be undefined (_isExternal) which is ok (drag only set x,y and w,h will default to node value)
2335
+ const p = { ...node._orig }; // could be undefined (_isExternal) which is ok (drag only set x,y and w,h will default to node value)
2313
2336
  let resizing;
2314
2337
  let mLeft = this.opts.marginLeft, mRight = this.opts.marginRight, mTop = this.opts.marginTop, mBottom = this.opts.marginBottom;
2315
2338
  // if margins (which are used to pass mid point by) are large relative to cell height/width, reduce them down #1855
2316
- let mHeight = Math.round(cellHeight * 0.1), mWidth = Math.round(cellWidth * 0.1);
2339
+ const mHeight = Math.round(cellHeight * 0.1), mWidth = Math.round(cellWidth * 0.1);
2317
2340
  mLeft = Math.min(mLeft, mWidth);
2318
2341
  mRight = Math.min(mRight, mWidth);
2319
2342
  mTop = Math.min(mTop, mHeight);
@@ -2321,20 +2344,20 @@ class GridStack {
2321
2344
  if (event.type === 'drag') {
2322
2345
  if (node._temporaryRemoved)
2323
2346
  return; // handled by dropover
2324
- let distance = ui.position.top - node._prevYPix;
2347
+ const distance = ui.position.top - node._prevYPix;
2325
2348
  node._prevYPix = ui.position.top;
2326
2349
  if (this.opts.draggable.scroll !== false) {
2327
2350
  Utils.updateScrollPosition(el, ui.position, distance);
2328
2351
  }
2329
2352
  // get new position taking into account the margin in the direction we are moving! (need to pass mid point by margin)
2330
- let left = ui.position.left + (ui.position.left > node._lastUiPosition.left ? -mRight : mLeft);
2331
- let top = ui.position.top + (ui.position.top > node._lastUiPosition.top ? -mBottom : mTop);
2353
+ const left = ui.position.left + (ui.position.left > node._lastUiPosition.left ? -mRight : mLeft);
2354
+ const top = ui.position.top + (ui.position.top > node._lastUiPosition.top ? -mBottom : mTop);
2332
2355
  p.x = Math.round(left / cellWidth);
2333
2356
  p.y = Math.round(top / cellHeight);
2334
2357
  // @ts-ignore// if we're at the bottom hitting something else, grow the grid so cursor doesn't leave when trying to place below others
2335
- let prev = this._extraDragRow;
2358
+ const prev = this._extraDragRow;
2336
2359
  if (this.engine.collide(node, p)) {
2337
- let row = this.getRow();
2360
+ const row = this.getRow();
2338
2361
  let extra = Math.max(0, (p.y + node.h) - row);
2339
2362
  if (this.opts.maxRow && row + extra > this.opts.maxRow) {
2340
2363
  extra = Math.max(0, this.opts.maxRow - row);
@@ -2363,15 +2386,15 @@ class GridStack {
2363
2386
  if (node._lastTried && node._lastTried.w === p.w && node._lastTried.h === p.h)
2364
2387
  return; // skip one we tried (but failed)
2365
2388
  // if we size on left/top side this might move us, so get possible new position as well
2366
- let left = ui.position.left + mLeft;
2367
- let top = ui.position.top + mTop;
2389
+ const left = ui.position.left + mLeft;
2390
+ const top = ui.position.top + mTop;
2368
2391
  p.x = Math.round(left / cellWidth);
2369
2392
  p.y = Math.round(top / cellHeight);
2370
2393
  resizing = true;
2371
2394
  }
2372
2395
  node._event = event;
2373
2396
  node._lastTried = p; // set as last tried (will nuke if we go there)
2374
- let rect = {
2397
+ const rect = {
2375
2398
  x: ui.position.left + mLeft,
2376
2399
  y: ui.position.top + mTop,
2377
2400
  w: (ui.size ? ui.size.width : node.w * cellWidth) - mLeft - mRight,
@@ -2385,7 +2408,7 @@ class GridStack {
2385
2408
  node.subGrid.onResize();
2386
2409
  this._extraDragRow = 0; // @ts-ignore
2387
2410
  this._updateContainerHeight();
2388
- let target = event.target; // @ts-ignore
2411
+ const target = event.target; // @ts-ignore
2389
2412
  this._writePosAttr(target, node);
2390
2413
  if (this._gsEventHandler[event.type]) {
2391
2414
  this._gsEventHandler[event.type](event, target);
@@ -2397,12 +2420,12 @@ class GridStack {
2397
2420
  * our item to start with else restore prev node values from prev grid it came from.
2398
2421
  */
2399
2422
  _leave(el, helper) {
2400
- let node = el.gridstackNode;
2423
+ helper = helper || el;
2424
+ const node = helper.gridstackNode;
2401
2425
  if (!node)
2402
2426
  return;
2403
- helper = helper || el;
2404
- // restore the scale of the helper on leave
2405
- helper.style.transform = 'scale(1)';
2427
+ // remove the scale of the helper on leave
2428
+ helper.style.transform = helper.style.transformOrigin = null;
2406
2429
  dd.off(el, 'drag'); // no need to track while being outside
2407
2430
  // this gets called when cursor leaves and shape is outside, so only do this once
2408
2431
  if (node._temporaryRemoved)
@@ -2410,6 +2433,8 @@ class GridStack {
2410
2433
  node._temporaryRemoved = true;
2411
2434
  this.engine.removeNode(node); // remove placeholder as well, otherwise it's a sign node is not in our list, which is a bigger issue
2412
2435
  node.el = node._isExternal && helper ? helper : el; // point back to real item being dragged
2436
+ if (node._isExternal)
2437
+ this.engine.cleanupNode(node);
2413
2438
  if (this.opts.removable === true) { // boolean vs a class string
2414
2439
  // item leaving us and we are supposed to remove on leave (no need to drag onto trash) mark it so
2415
2440
  GridStack._itemRemoving(el, true);
@@ -2421,22 +2446,25 @@ class GridStack {
2421
2446
  delete el._gridstackNodeOrig;
2422
2447
  }
2423
2448
  else if (node._isExternal) {
2424
- // item came from outside (like a toolbar) so nuke any node info
2425
- delete node.el;
2426
- delete el.gridstackNode;
2427
- // and restore all nodes back to original
2449
+ // item came from outside restore all nodes back to original
2428
2450
  this.engine.restoreInitial();
2429
2451
  }
2430
2452
  }
2431
2453
  // legacy method removed
2432
2454
  commit() { obsolete(this, this.batchUpdate(false), 'commit', 'batchUpdate', '5.2'); return this; }
2433
2455
  }
2456
+ /**
2457
+ * callback to create the content of widgets so the app can control how to store and restore it
2458
+ * By default this lib will do 'el.textContent = w.content' forcing text only support for avoiding potential XSS issues.
2459
+ */
2460
+ GridStack.renderCB = (el, w) => { if (el && w?.content)
2461
+ el.textContent = w.content; };
2434
2462
  /** parent class for sizing content. defaults to '.grid-stack-item-content' */
2435
2463
  GridStack.resizeToContentParent = '.grid-stack-item-content';
2436
2464
  /** scoping so users can call GridStack.Utils.sort() for example */
2437
2465
  GridStack.Utils = Utils;
2438
2466
  /** scoping so users can call new GridStack.Engine(12) for example */
2439
2467
  GridStack.Engine = GridStackEngine;
2440
- GridStack.GDRev = '10.3.0';
2468
+ GridStack.GDRev = '11.0.0';
2441
2469
  export { GridStack };
2442
2470
  //# sourceMappingURL=gridstack.js.map