gridstack 10.3.1 → 11.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 (121) 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/package.json +7 -13
  17. package/dist/angular/src/base-widget.ts +10 -2
  18. package/dist/angular/src/gridstack-item.component.ts +11 -7
  19. package/dist/angular/src/gridstack.component.ts +67 -44
  20. package/dist/angular/src/gridstack.module.ts +2 -2
  21. package/dist/dd-base-impl.d.ts +2 -2
  22. package/dist/dd-base-impl.js +2 -2
  23. package/dist/dd-base-impl.js.map +1 -1
  24. package/dist/dd-draggable.d.ts +7 -16
  25. package/dist/dd-draggable.js +22 -34
  26. package/dist/dd-draggable.js.map +1 -1
  27. package/dist/dd-droppable.d.ts +2 -2
  28. package/dist/dd-droppable.js +2 -2
  29. package/dist/dd-droppable.js.map +1 -1
  30. package/dist/dd-element.d.ts +5 -5
  31. package/dist/dd-element.js +2 -2
  32. package/dist/dd-element.js.map +1 -1
  33. package/dist/dd-gridstack.d.ts +4 -4
  34. package/dist/dd-gridstack.js +8 -8
  35. package/dist/dd-gridstack.js.map +1 -1
  36. package/dist/dd-manager.d.ts +2 -2
  37. package/dist/dd-manager.js +2 -2
  38. package/dist/dd-manager.js.map +1 -1
  39. package/dist/dd-resizable-handle.d.ts +2 -2
  40. package/dist/dd-resizable-handle.js +3 -3
  41. package/dist/dd-resizable-handle.js.map +1 -1
  42. package/dist/dd-resizable.d.ts +2 -2
  43. package/dist/dd-resizable.js +4 -4
  44. package/dist/dd-resizable.js.map +1 -1
  45. package/dist/dd-touch.d.ts +2 -2
  46. package/dist/dd-touch.js +2 -2
  47. package/dist/dd-touch.js.map +1 -1
  48. package/dist/es5/dd-base-impl.d.ts +2 -2
  49. package/dist/es5/dd-base-impl.js +2 -2
  50. package/dist/es5/dd-base-impl.js.map +1 -1
  51. package/dist/es5/dd-draggable.d.ts +7 -16
  52. package/dist/es5/dd-draggable.js +19 -29
  53. package/dist/es5/dd-draggable.js.map +1 -1
  54. package/dist/es5/dd-droppable.d.ts +2 -2
  55. package/dist/es5/dd-droppable.js +2 -2
  56. package/dist/es5/dd-droppable.js.map +1 -1
  57. package/dist/es5/dd-element.d.ts +5 -5
  58. package/dist/es5/dd-element.js +2 -2
  59. package/dist/es5/dd-element.js.map +1 -1
  60. package/dist/es5/dd-gridstack.d.ts +4 -4
  61. package/dist/es5/dd-gridstack.js +9 -6
  62. package/dist/es5/dd-gridstack.js.map +1 -1
  63. package/dist/es5/dd-manager.d.ts +2 -2
  64. package/dist/es5/dd-manager.js +2 -2
  65. package/dist/es5/dd-manager.js.map +1 -1
  66. package/dist/es5/dd-resizable-handle.d.ts +2 -2
  67. package/dist/es5/dd-resizable-handle.js +2 -2
  68. package/dist/es5/dd-resizable-handle.js.map +1 -1
  69. package/dist/es5/dd-resizable.d.ts +2 -2
  70. package/dist/es5/dd-resizable.js +2 -2
  71. package/dist/es5/dd-resizable.js.map +1 -1
  72. package/dist/es5/dd-touch.d.ts +2 -2
  73. package/dist/es5/dd-touch.js +2 -2
  74. package/dist/es5/dd-touch.js.map +1 -1
  75. package/dist/es5/gridstack-all.js +1 -1
  76. package/dist/es5/gridstack-all.js.LICENSE.txt +2 -2
  77. package/dist/es5/gridstack-all.js.map +1 -1
  78. package/dist/es5/gridstack-engine.d.ts +2 -2
  79. package/dist/es5/gridstack-engine.js +13 -5
  80. package/dist/es5/gridstack-engine.js.map +1 -1
  81. package/dist/es5/gridstack-poly.js +2 -2
  82. package/dist/es5/gridstack.d.ts +22 -17
  83. package/dist/es5/gridstack.js +158 -141
  84. package/dist/es5/gridstack.js.map +1 -1
  85. package/dist/es5/types.d.ts +16 -8
  86. package/dist/es5/types.js +3 -10
  87. package/dist/es5/types.js.map +1 -1
  88. package/dist/es5/utils.d.ts +6 -2
  89. package/dist/es5/utils.js +36 -3
  90. package/dist/es5/utils.js.map +1 -1
  91. package/dist/gridstack-all.js +1 -1
  92. package/dist/gridstack-all.js.LICENSE.txt +2 -2
  93. package/dist/gridstack-all.js.map +1 -1
  94. package/dist/gridstack-engine.d.ts +2 -2
  95. package/dist/gridstack-engine.js +69 -61
  96. package/dist/gridstack-engine.js.map +1 -1
  97. package/dist/gridstack-extra.css +1 -1
  98. package/dist/gridstack.css +2 -2
  99. package/dist/gridstack.d.ts +22 -17
  100. package/dist/gridstack.js +244 -226
  101. package/dist/gridstack.js.map +1 -1
  102. package/dist/src/gridstack-extra.scss +1 -1
  103. package/dist/src/gridstack.scss +2 -2
  104. package/dist/types.d.ts +16 -8
  105. package/dist/types.js +2 -9
  106. package/dist/types.js.map +1 -1
  107. package/dist/utils.d.ts +6 -2
  108. package/dist/utils.js +50 -20
  109. package/dist/utils.js.map +1 -1
  110. package/doc/CHANGES.md +13 -0
  111. package/doc/README.md +18 -23
  112. package/package.json +2 -2
  113. package/dist/angular/esm2020/lib/base-widget.mjs +0 -30
  114. package/dist/angular/esm2020/lib/gridstack-item.component.mjs +0 -68
  115. package/dist/angular/esm2020/lib/gridstack.component.mjs +0 -280
  116. package/dist/angular/esm2020/lib/gridstack.module.mjs +0 -39
  117. package/dist/angular/esm2020/public-api.mjs +0 -8
  118. package/dist/angular/fesm2015/gridstack-angular.mjs +0 -420
  119. package/dist/angular/fesm2015/gridstack-angular.mjs.map +0 -1
  120. package/dist/angular/fesm2020/gridstack-angular.mjs.map +0 -1
  121. package/dist/angular/public-api.d.ts +0 -4
package/dist/gridstack.js CHANGED
@@ -1,13 +1,13 @@
1
1
  /*!
2
- * GridStack 10.3.1
2
+ * GridStack 11.0.1
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);
@@ -1292,14 +1285,14 @@ class GridStack {
1292
1285
  */
1293
1286
  rotate(els, relative) {
1294
1287
  GridStack.getElements(els).forEach(el => {
1295
- let n = el.gridstackNode;
1288
+ const n = el.gridstackNode;
1296
1289
  if (!Utils.canBeRotated(n))
1297
1290
  return;
1298
1291
  const rot = { w: n.h, h: n.w, minH: n.minW, minW: n.minH, maxH: n.maxW, maxW: n.maxH };
1299
1292
  // if given an offset, adjust x/y by column/row bounds when user presses 'r' during dragging
1300
1293
  if (relative) {
1301
- let pivotX = relative.left > 0 ? Math.floor(relative.left / this.cellWidth()) : 0;
1302
- 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;
1303
1296
  rot.x = n.x + pivotX - (n.h - (pivotY + 1));
1304
1297
  rot.y = (n.y + pivotY) - pivotX;
1305
1298
  }
@@ -1316,10 +1309,10 @@ class GridStack {
1316
1309
  * @param value margin value
1317
1310
  */
1318
1311
  margin(value) {
1319
- let isMultiValue = (typeof value === 'string' && value.split(' ').length > 1);
1312
+ const isMultiValue = (typeof value === 'string' && value.split(' ').length > 1);
1320
1313
  // check if we can skip re-creating our CSS file... won't check if multi values (too much hassle)
1321
1314
  if (!isMultiValue) {
1322
- let data = Utils.parseHeight(value);
1315
+ const data = Utils.parseHeight(value);
1323
1316
  if (this.opts.marginUnit === data.unit && this.opts.margin === data.h)
1324
1317
  return;
1325
1318
  }
@@ -1349,7 +1342,8 @@ class GridStack {
1349
1342
  if (arguments.length > 1) {
1350
1343
  console.warn('gridstack.ts: `willItFit(x,y,w,h,autoPosition)` is deprecated. Use `willItFit({x, y,...})`. It will be removed soon');
1351
1344
  // eslint-disable-next-line prefer-rest-params
1352
- 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++] };
1353
1347
  return this.willItFit(w);
1354
1348
  }
1355
1349
  return this.engine.willItFit(node);
@@ -1358,7 +1352,7 @@ class GridStack {
1358
1352
  _triggerChangeEvent() {
1359
1353
  if (this.engine.batchMode)
1360
1354
  return this;
1361
- let elements = this.engine.getDirtyNodes(true); // verify they really changed
1355
+ const elements = this.engine.getDirtyNodes(true); // verify they really changed
1362
1356
  if (elements && elements.length) {
1363
1357
  if (!this._ignoreLayoutsNodeChange) {
1364
1358
  this.engine.layoutsNodesChange(elements);
@@ -1397,7 +1391,7 @@ class GridStack {
1397
1391
  }
1398
1392
  /** @internal */
1399
1393
  _triggerEvent(type, data) {
1400
- 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);
1401
1395
  this.el.dispatchEvent(event);
1402
1396
  return this;
1403
1397
  }
@@ -1423,9 +1417,9 @@ class GridStack {
1423
1417
  if (this.opts.cellHeight === 0) {
1424
1418
  return this;
1425
1419
  }
1426
- let cellHeight = this.opts.cellHeight;
1427
- let cellHeightUnit = this.opts.cellHeightUnit;
1428
- 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}`;
1429
1423
  // create one as needed
1430
1424
  if (!this._styles) {
1431
1425
  // insert style to parent (instead of 'head' by default) to support WebComponent
@@ -1439,12 +1433,12 @@ class GridStack {
1439
1433
  // these are done once only
1440
1434
  Utils.addCSSRule(this._styles, prefix, `height: ${cellHeight}${cellHeightUnit}`);
1441
1435
  // content margins
1442
- let top = this.opts.marginTop + this.opts.marginUnit;
1443
- let bottom = this.opts.marginBottom + this.opts.marginUnit;
1444
- let right = this.opts.marginRight + this.opts.marginUnit;
1445
- let left = this.opts.marginLeft + this.opts.marginUnit;
1446
- let content = `${prefix} > .grid-stack-item-content`;
1447
- 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`;
1448
1442
  Utils.addCSSRule(this._styles, content, `top: ${top}; right: ${right}; bottom: ${bottom}; left: ${left};`);
1449
1443
  Utils.addCSSRule(this._styles, placeholder, `top: ${top}; right: ${right}; bottom: ${bottom}; left: ${left};`);
1450
1444
  // resize handles offset (to match margin)
@@ -1460,7 +1454,7 @@ class GridStack {
1460
1454
  // now update the height specific fields
1461
1455
  maxH = maxH || this._styles._max;
1462
1456
  if (maxH > this._styles._max) {
1463
- let getHeight = (rows) => (cellHeight * rows) + cellHeightUnit;
1457
+ const getHeight = (rows) => (cellHeight * rows) + cellHeightUnit;
1464
1458
  for (let i = this._styles._max + 1; i <= maxH; i++) { // start at 1
1465
1459
  Utils.addCSSRule(this._styles, `${prefix}[gs-y="${i}"]`, `top: ${getHeight(i)}`);
1466
1460
  Utils.addCSSRule(this._styles, `${prefix}[gs-h="${i + 1}"]`, `height: ${getHeight(i + 1)}`); // start at 2
@@ -1473,7 +1467,7 @@ class GridStack {
1473
1467
  _updateContainerHeight() {
1474
1468
  if (!this.engine || this.engine.batchMode)
1475
1469
  return this;
1476
- const parent = this.parentGridItem;
1470
+ const parent = this.parentGridNode;
1477
1471
  let row = this.getRow() + this._extraDragRow; // this checks for minRow already
1478
1472
  const cellHeight = this.opts.cellHeight;
1479
1473
  const unit = this.opts.cellHeightUnit;
@@ -1536,8 +1530,8 @@ class GridStack {
1536
1530
  if (!node)
1537
1531
  return this;
1538
1532
  this._writePosAttr(el, node);
1539
- let attrs /*: GridStackWidget but strings */ = {
1540
- 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
1541
1535
  noResize: 'gs-no-resize',
1542
1536
  noMove: 'gs-no-move',
1543
1537
  locked: 'gs-locked',
@@ -1555,7 +1549,7 @@ class GridStack {
1555
1549
  }
1556
1550
  /** @internal call to read any default attributes from element */
1557
1551
  _readAttr(el, clearDefaultAttr = true) {
1558
- let n = {};
1552
+ const n = {};
1559
1553
  n.x = Utils.toNumber(el.getAttribute('gs-x'));
1560
1554
  n.y = Utils.toNumber(el.getAttribute('gs-y'));
1561
1555
  n.w = Utils.toNumber(el.getAttribute('gs-w'));
@@ -1597,7 +1591,7 @@ class GridStack {
1597
1591
  }
1598
1592
  /** @internal */
1599
1593
  _setStaticClass() {
1600
- let classes = ['grid-stack-static'];
1594
+ const classes = ['grid-stack-static'];
1601
1595
  if (this.opts.staticGrid) {
1602
1596
  this.el.classList.add(...classes);
1603
1597
  this.el.setAttribute('gs-static', 'true');
@@ -1623,9 +1617,9 @@ class GridStack {
1623
1617
  this.batchUpdate();
1624
1618
  // see if we're nested and take our column count from our parent....
1625
1619
  let columnChanged = false;
1626
- if (this._autoColumn && this.parentGridItem) {
1627
- if (this.opts.column !== this.parentGridItem.w) {
1628
- 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');
1629
1623
  columnChanged = true;
1630
1624
  }
1631
1625
  }
@@ -1676,7 +1670,7 @@ class GridStack {
1676
1670
  _updateResizeEvent(forceRemove = false) {
1677
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)
1678
1672
  // or supporting new sizeToContent option.
1679
- 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
1680
1674
  || this.engine.nodes.find(n => n.sizeToContent));
1681
1675
  if (!forceRemove && trackSize && !this.resizeObserver) {
1682
1676
  this._sizeThrottle = Utils.throttle(() => this.onResize(), this.opts.cellHeightThrottle);
@@ -1775,21 +1769,23 @@ class GridStack {
1775
1769
  * call to setup dragging in from the outside (say toolbar), by specifying the class selection and options.
1776
1770
  * Called during GridStack.init() as options, but can also be called directly (last param are used) in case the toolbar
1777
1771
  * is dynamically create and needs to be set later.
1778
- * @param dragIn string selector (ex: '.sidebar .grid-stack-item') or list of dom elements
1779
- * @param dragInOptions options - see DDDragInOpt. (default: {handle: '.grid-stack-item-content', appendTo: 'body'}
1780
- * @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)
1781
1776
  */
1782
- static setupDragIn(dragIn, dragInOptions, root = document) {
1777
+ static setupDragIn(dragIn, dragInOptions, widgets, root = document) {
1783
1778
  if (dragInOptions?.pause !== undefined) {
1784
1779
  DDManager.pauseDrag = dragInOptions.pause;
1785
1780
  }
1786
- dragInOptions = { ...dragInDefaultOptions, ...(dragInOptions || {}) };
1787
- let els = (typeof dragIn === 'string') ? Utils.getElements(dragIn, root) : dragIn;
1788
- if (els.length)
1789
- els?.forEach(el => {
1790
- if (!dd.isDraggable(el))
1791
- dd.dragIn(el, dragInOptions);
1792
- });
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
+ });
1793
1789
  }
1794
1790
  /**
1795
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.
@@ -1818,7 +1814,7 @@ class GridStack {
1818
1814
  if (this.opts.staticGrid)
1819
1815
  return this; // can't resize a static grid!
1820
1816
  GridStack.getElements(els).forEach(el => {
1821
- let n = el.gridstackNode;
1817
+ const n = el.gridstackNode;
1822
1818
  if (!n)
1823
1819
  return;
1824
1820
  val ? delete n.noResize : n.noResize = true;
@@ -1909,11 +1905,11 @@ class GridStack {
1909
1905
  }
1910
1906
  // vars shared across all methods
1911
1907
  let cellHeight, cellWidth;
1912
- let onDrag = (event, el, helper) => {
1913
- let node = el.gridstackNode;
1908
+ const onDrag = (event, el, helper) => {
1909
+ helper = helper || el;
1910
+ const node = helper.gridstackNode;
1914
1911
  if (!node)
1915
1912
  return;
1916
- helper = helper || el;
1917
1913
  // if the element is being dragged from outside, scale it down to match the grid's scale
1918
1914
  // and slightly adjust its position relative to the mouse
1919
1915
  if (!node.grid?.el) {
@@ -1925,11 +1921,11 @@ class GridStack {
1925
1921
  helper.style.top = helperRect.y + (this.dragTransform.yScale - 1) * (event.clientY - helperRect.y) / this.dragTransform.yScale + 'px';
1926
1922
  helper.style.transformOrigin = `0px 0px`;
1927
1923
  }
1928
- let parent = this.el.getBoundingClientRect();
1929
1924
  let { top, left } = helper.getBoundingClientRect();
1930
- left -= parent.left;
1931
- top -= parent.top;
1932
- let ui = {
1925
+ const rect = this.el.getBoundingClientRect();
1926
+ left -= rect.left;
1927
+ top -= rect.top;
1928
+ const ui = {
1933
1929
  position: {
1934
1930
  top: top * this.dragTransform.xScale,
1935
1931
  left: left * this.dragTransform.yScale
@@ -1963,7 +1959,7 @@ class GridStack {
1963
1959
  };
1964
1960
  dd.droppable(this.el, {
1965
1961
  accept: (el) => {
1966
- let node = el.gridstackNode || this._readAttr(el, false);
1962
+ const node = el.gridstackNode || this._readAttr(el, false);
1967
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
1968
1964
  if (node?.grid === this)
1969
1965
  return true;
@@ -1975,12 +1971,12 @@ class GridStack {
1975
1971
  canAccept = this.opts.acceptWidgets(el);
1976
1972
  }
1977
1973
  else {
1978
- 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);
1979
1975
  canAccept = el.matches(selector);
1980
1976
  }
1981
1977
  // finally check to make sure we actually have space left #1571 #2633
1982
1978
  if (canAccept && node && this.opts.maxRow) {
1983
- 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
1984
1980
  canAccept = this.engine.willItFit(n);
1985
1981
  }
1986
1982
  return canAccept;
@@ -1991,7 +1987,7 @@ class GridStack {
1991
1987
  */
1992
1988
  .on(this.el, 'dropover', (event, el, helper) => {
1993
1989
  // console.log(`over ${this.el.gridstack.opts.id} ${count++}`); // TEST
1994
- let node = el.gridstackNode;
1990
+ let node = helper?.gridstackNode || el.gridstackNode;
1995
1991
  // ignore drop enter on ourself (unless we temporarily removed) which happens on a simple drag of our item
1996
1992
  if (node?.grid === this && !node._temporaryRemoved) {
1997
1993
  // delete node._added; // reset this to track placeholder again in case we were over other grid #1484 (dropout doesn't always clear)
@@ -2000,24 +1996,36 @@ class GridStack {
2000
1996
  // fix #1578 when dragging fast, we may not get a leave on the previous grid so force one now
2001
1997
  if (node?.grid && node.grid !== this && !node._temporaryRemoved) {
2002
1998
  // console.log('dropover without leave'); // TEST
2003
- let otherGrid = node.grid;
1999
+ const otherGrid = node.grid;
2004
2000
  otherGrid._leave(el, helper);
2005
2001
  }
2002
+ helper = helper || el;
2006
2003
  // cache cell dimensions (which don't change), position can animate if we removed an item in otherGrid that affects us...
2007
2004
  cellWidth = this.cellWidth();
2008
2005
  cellHeight = this.getCellHeight(true);
2009
- // 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
2010
2007
  if (!node) {
2011
- 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
2012
2019
  }
2013
- 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)
2014
2023
  node._isExternal = true;
2015
- el.gridstackNode = node;
2024
+ helper.gridstackNode = node;
2016
2025
  }
2017
2026
  // calculate the grid size based on element outer size
2018
- helper = helper || el;
2019
- let w = node.w || Math.round(helper.offsetWidth / cellWidth) || 1;
2020
- 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;
2021
2029
  // if the item came from another grid, make a copy and save the original info in case we go back there
2022
2030
  if (node.grid && node.grid !== this) {
2023
2031
  // copy the node original values (min/max/id/etc...) but override width/height/other flags which are this grid specific
@@ -2051,7 +2059,7 @@ class GridStack {
2051
2059
  */
2052
2060
  .on(this.el, 'dropout', (event, el, helper) => {
2053
2061
  // console.log(`out ${this.el.gridstack.opts.id} ${count++}`); // TEST
2054
- let node = el.gridstackNode;
2062
+ const node = helper?.gridstackNode || el.gridstackNode;
2055
2063
  if (!node)
2056
2064
  return false;
2057
2065
  // fix #1578 when dragging fast, we might get leave after other grid gets enter (which calls us to clean)
@@ -2069,11 +2077,12 @@ class GridStack {
2069
2077
  * end - releasing the mouse
2070
2078
  */
2071
2079
  .on(this.el, 'drop', (event, el, helper) => {
2072
- let node = el.gridstackNode;
2080
+ const node = helper?.gridstackNode || el.gridstackNode;
2073
2081
  // ignore drop on ourself from ourself that didn't come from the outside - dragend will handle the simple move instead
2074
2082
  if (node?.grid === this && !node._isExternal)
2075
2083
  return false;
2076
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;
2077
2086
  this.placeholder.remove();
2078
2087
  // disable animation when replacing a placeholder (already positioned) with actual content
2079
2088
  const noAnim = wasAdded && this.opts.animate;
@@ -2081,15 +2090,15 @@ class GridStack {
2081
2090
  this.setAnimation(false);
2082
2091
  // notify previous grid of removal
2083
2092
  // console.log('drop delete _gridstackNodeOrig') // TEST
2084
- let origNode = el._gridstackNodeOrig;
2093
+ const origNode = el._gridstackNodeOrig;
2085
2094
  delete el._gridstackNodeOrig;
2086
2095
  if (wasAdded && origNode?.grid && origNode.grid !== this) {
2087
- let oGrid = origNode.grid;
2096
+ const oGrid = origNode.grid;
2088
2097
  oGrid.engine.removeNodeFromLayoutCache(origNode);
2089
2098
  oGrid.engine.removedNodes.push(origNode);
2090
2099
  oGrid._triggerRemoveEvent()._triggerChangeEvent();
2091
2100
  // if it's an empty sub-grid that got auto-created, nuke it
2092
- if (oGrid.parentGridItem && !oGrid.engine.nodes.length && oGrid.opts.subGridDynamic) {
2101
+ if (oGrid.parentGridNode && !oGrid.engine.nodes.length && oGrid.opts.subGridDynamic) {
2093
2102
  oGrid.removeAsSubGrid();
2094
2103
  }
2095
2104
  }
@@ -2102,37 +2111,39 @@ class GridStack {
2102
2111
  }
2103
2112
  delete node.grid?._isTemp;
2104
2113
  dd.off(el, 'drag');
2105
- // if we made a copy ('helper' which is temp) of the original node then insert a copy, else we move the original node (#1102)
2106
- // 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)
2107
2115
  if (helper !== el) {
2108
2116
  helper.remove();
2109
- el.gridstackNode = origNode; // original item (left behind) is re-stored to pre dragging as the node now has drop info
2110
- if (wasAdded) {
2111
- el = el.cloneNode(true);
2112
- }
2117
+ el = helper;
2113
2118
  }
2114
2119
  else {
2115
2120
  el.remove(); // reduce flicker as we change depth here, and size further down
2116
- this._removeDD(el);
2117
2121
  }
2122
+ this._removeDD(el);
2118
2123
  if (!wasAdded)
2119
2124
  return false;
2120
- el.gridstackNode = node;
2121
- node.el = el;
2122
- let subGrid = node.subGrid?.el?.gridstack; // set when actual sub-grid present
2123
- // @ts-ignore
2125
+ const subGrid = node.subGrid?.el?.gridstack; // set when actual sub-grid present
2124
2126
  Utils.copyPos(node, this._readAttr(this.placeholder)); // placeholder values as moving VERY fast can throw things off #1578
2125
- Utils.removePositioningStyles(el); // @ts-ignore
2126
- this.el.appendChild(el); // @ts-ignore // TODO: now would be ideal time to _removeHelperStyle() overriding floating styles (native only)
2127
- this._prepareElement(el, true, node);
2128
- if (subGrid) {
2129
- subGrid.parentGridItem = node;
2130
- if (!subGrid.opts.styleInHead)
2131
- 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);
2132
2132
  }
2133
- this._updateContainerHeight();
2134
- this.engine.addedNodes.push(node); // @ts-ignore
2135
- 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();
2136
2147
  this._triggerChangeEvent();
2137
2148
  this.engine.endUpdate();
2138
2149
  if (this._gsEventHandler['dropped']) {
@@ -2147,6 +2158,8 @@ class GridStack {
2147
2158
  }
2148
2159
  /** @internal mark item for removal */
2149
2160
  static _itemRemoving(el, remove) {
2161
+ if (!el)
2162
+ return;
2150
2163
  const node = el ? el.gridstackNode : undefined;
2151
2164
  if (!node?.grid || el.classList.contains(node.grid.opts.removableOptions.decline))
2152
2165
  return;
@@ -2157,7 +2170,7 @@ class GridStack {
2157
2170
  _setupRemoveDrop() {
2158
2171
  if (typeof this.opts.removable !== 'string')
2159
2172
  return this;
2160
- let trashEl = document.querySelector(this.opts.removable);
2173
+ const trashEl = document.querySelector(this.opts.removable);
2161
2174
  if (!trashEl)
2162
2175
  return this;
2163
2176
  // only register ONE static drop-over/dropout callback for the 'trash', and it will
@@ -2172,7 +2185,7 @@ class GridStack {
2172
2185
  }
2173
2186
  /** @internal prepares the element for drag&drop */
2174
2187
  _prepareDragDropByNode(node) {
2175
- let el = node.el;
2188
+ const el = node.el;
2176
2189
  const noMove = node.noMove || this.opts.disableDrag;
2177
2190
  const noResize = node.noResize || this.opts.disableResize;
2178
2191
  // check for disabled grid first
@@ -2189,7 +2202,7 @@ class GridStack {
2189
2202
  let cellWidth;
2190
2203
  let cellHeight;
2191
2204
  /** called when item starts moving/resizing */
2192
- let onStartMoving = (event, ui) => {
2205
+ const onStartMoving = (event, ui) => {
2193
2206
  // trigger any 'dragstart' / 'resizestart' manually
2194
2207
  if (this._gsEventHandler[event.type]) {
2195
2208
  this._gsEventHandler[event.type](event, event.target);
@@ -2199,23 +2212,23 @@ class GridStack {
2199
2212
  this._onStartMoving(el, event, ui, node, cellWidth, cellHeight);
2200
2213
  };
2201
2214
  /** called when item is being dragged/resized */
2202
- let dragOrResize = (event, ui) => {
2215
+ const dragOrResize = (event, ui) => {
2203
2216
  this._dragOrResize(el, event, ui, node, cellWidth, cellHeight);
2204
2217
  };
2205
2218
  /** called when the item stops moving/resizing */
2206
- let onEndMoving = (event) => {
2219
+ const onEndMoving = (event) => {
2207
2220
  this.placeholder.remove();
2208
2221
  delete node._moving;
2209
2222
  delete node._event;
2210
2223
  delete node._lastTried;
2211
2224
  const widthChanged = node.w !== node._orig.w;
2212
2225
  // if the item has moved to another grid, we're done here
2213
- let target = event.target;
2226
+ const target = event.target;
2214
2227
  if (!target.gridstackNode || target.gridstackNode.grid !== this)
2215
2228
  return;
2216
2229
  node.el = target;
2217
2230
  if (node._isAboutToRemove) {
2218
- let grid = el.gridstackNode.grid;
2231
+ const grid = el.gridstackNode.grid;
2219
2232
  if (grid._gsEventHandler[event.type]) {
2220
2233
  grid._gsEventHandler[event.type](event, target);
2221
2234
  }
@@ -2319,11 +2332,11 @@ class GridStack {
2319
2332
  }
2320
2333
  /** @internal handles actual drag/resize */
2321
2334
  _dragOrResize(el, event, ui, node, cellWidth, cellHeight) {
2322
- 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)
2323
2336
  let resizing;
2324
2337
  let mLeft = this.opts.marginLeft, mRight = this.opts.marginRight, mTop = this.opts.marginTop, mBottom = this.opts.marginBottom;
2325
2338
  // if margins (which are used to pass mid point by) are large relative to cell height/width, reduce them down #1855
2326
- 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);
2327
2340
  mLeft = Math.min(mLeft, mWidth);
2328
2341
  mRight = Math.min(mRight, mWidth);
2329
2342
  mTop = Math.min(mTop, mHeight);
@@ -2331,20 +2344,20 @@ class GridStack {
2331
2344
  if (event.type === 'drag') {
2332
2345
  if (node._temporaryRemoved)
2333
2346
  return; // handled by dropover
2334
- let distance = ui.position.top - node._prevYPix;
2347
+ const distance = ui.position.top - node._prevYPix;
2335
2348
  node._prevYPix = ui.position.top;
2336
2349
  if (this.opts.draggable.scroll !== false) {
2337
2350
  Utils.updateScrollPosition(el, ui.position, distance);
2338
2351
  }
2339
2352
  // get new position taking into account the margin in the direction we are moving! (need to pass mid point by margin)
2340
- let left = ui.position.left + (ui.position.left > node._lastUiPosition.left ? -mRight : mLeft);
2341
- 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);
2342
2355
  p.x = Math.round(left / cellWidth);
2343
2356
  p.y = Math.round(top / cellHeight);
2344
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
2345
- let prev = this._extraDragRow;
2358
+ const prev = this._extraDragRow;
2346
2359
  if (this.engine.collide(node, p)) {
2347
- let row = this.getRow();
2360
+ const row = this.getRow();
2348
2361
  let extra = Math.max(0, (p.y + node.h) - row);
2349
2362
  if (this.opts.maxRow && row + extra > this.opts.maxRow) {
2350
2363
  extra = Math.max(0, this.opts.maxRow - row);
@@ -2373,15 +2386,15 @@ class GridStack {
2373
2386
  if (node._lastTried && node._lastTried.w === p.w && node._lastTried.h === p.h)
2374
2387
  return; // skip one we tried (but failed)
2375
2388
  // if we size on left/top side this might move us, so get possible new position as well
2376
- let left = ui.position.left + mLeft;
2377
- let top = ui.position.top + mTop;
2389
+ const left = ui.position.left + mLeft;
2390
+ const top = ui.position.top + mTop;
2378
2391
  p.x = Math.round(left / cellWidth);
2379
2392
  p.y = Math.round(top / cellHeight);
2380
2393
  resizing = true;
2381
2394
  }
2382
2395
  node._event = event;
2383
2396
  node._lastTried = p; // set as last tried (will nuke if we go there)
2384
- let rect = {
2397
+ const rect = {
2385
2398
  x: ui.position.left + mLeft,
2386
2399
  y: ui.position.top + mTop,
2387
2400
  w: (ui.size ? ui.size.width : node.w * cellWidth) - mLeft - mRight,
@@ -2395,7 +2408,7 @@ class GridStack {
2395
2408
  node.subGrid.onResize();
2396
2409
  this._extraDragRow = 0; // @ts-ignore
2397
2410
  this._updateContainerHeight();
2398
- let target = event.target; // @ts-ignore
2411
+ const target = event.target; // @ts-ignore
2399
2412
  this._writePosAttr(target, node);
2400
2413
  if (this._gsEventHandler[event.type]) {
2401
2414
  this._gsEventHandler[event.type](event, target);
@@ -2407,12 +2420,12 @@ class GridStack {
2407
2420
  * our item to start with else restore prev node values from prev grid it came from.
2408
2421
  */
2409
2422
  _leave(el, helper) {
2410
- let node = el.gridstackNode;
2423
+ helper = helper || el;
2424
+ const node = helper.gridstackNode;
2411
2425
  if (!node)
2412
2426
  return;
2413
- helper = helper || el;
2414
- // restore the scale of the helper on leave
2415
- helper.style.transform = 'scale(1)';
2427
+ // remove the scale of the helper on leave
2428
+ helper.style.transform = helper.style.transformOrigin = null;
2416
2429
  dd.off(el, 'drag'); // no need to track while being outside
2417
2430
  // this gets called when cursor leaves and shape is outside, so only do this once
2418
2431
  if (node._temporaryRemoved)
@@ -2420,6 +2433,8 @@ class GridStack {
2420
2433
  node._temporaryRemoved = true;
2421
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
2422
2435
  node.el = node._isExternal && helper ? helper : el; // point back to real item being dragged
2436
+ if (node._isExternal)
2437
+ this.engine.cleanupNode(node);
2423
2438
  if (this.opts.removable === true) { // boolean vs a class string
2424
2439
  // item leaving us and we are supposed to remove on leave (no need to drag onto trash) mark it so
2425
2440
  GridStack._itemRemoving(el, true);
@@ -2431,22 +2446,25 @@ class GridStack {
2431
2446
  delete el._gridstackNodeOrig;
2432
2447
  }
2433
2448
  else if (node._isExternal) {
2434
- // item came from outside (like a toolbar) so nuke any node info
2435
- delete node.el;
2436
- delete el.gridstackNode;
2437
- // and restore all nodes back to original
2449
+ // item came from outside restore all nodes back to original
2438
2450
  this.engine.restoreInitial();
2439
2451
  }
2440
2452
  }
2441
2453
  // legacy method removed
2442
2454
  commit() { obsolete(this, this.batchUpdate(false), 'commit', 'batchUpdate', '5.2'); return this; }
2443
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; };
2444
2462
  /** parent class for sizing content. defaults to '.grid-stack-item-content' */
2445
2463
  GridStack.resizeToContentParent = '.grid-stack-item-content';
2446
2464
  /** scoping so users can call GridStack.Utils.sort() for example */
2447
2465
  GridStack.Utils = Utils;
2448
2466
  /** scoping so users can call new GridStack.Engine(12) for example */
2449
2467
  GridStack.Engine = GridStackEngine;
2450
- GridStack.GDRev = '10.3.1';
2468
+ GridStack.GDRev = '11.0.1';
2451
2469
  export { GridStack };
2452
2470
  //# sourceMappingURL=gridstack.js.map