gridstack 8.1.2 → 8.2.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 (117) hide show
  1. package/angular/package.json +1 -1
  2. package/angular/projects/demo/src/app/app.component.ts +11 -10
  3. package/angular/projects/demo/src/app/app.module.ts +4 -3
  4. package/angular/projects/demo/src/app/dummy.component.ts +12 -6
  5. package/angular/projects/lib/package.json +1 -1
  6. package/angular/projects/lib/src/lib/base-widget.ts +28 -0
  7. package/angular/projects/lib/src/lib/gridstack-item.component.ts +10 -2
  8. package/angular/projects/lib/src/lib/gridstack.component.ts +83 -36
  9. package/angular/projects/lib/src/lib/gridstack.module.ts +1 -1
  10. package/angular/projects/lib/src/public-api.ts +1 -0
  11. package/dist/angular/esm2020/lib/base-widget.mjs +30 -0
  12. package/dist/angular/esm2020/lib/gridstack-item.component.mjs +3 -2
  13. package/dist/angular/esm2020/lib/gridstack.component.mjs +79 -34
  14. package/dist/angular/esm2020/lib/gridstack.module.mjs +2 -2
  15. package/dist/angular/esm2020/public-api.mjs +2 -1
  16. package/dist/angular/fesm2015/gridstack-angular.mjs +110 -38
  17. package/dist/angular/fesm2015/gridstack-angular.mjs.map +1 -1
  18. package/dist/angular/fesm2020/gridstack-angular.mjs +108 -37
  19. package/dist/angular/fesm2020/gridstack-angular.mjs.map +1 -1
  20. package/dist/angular/lib/base-widget.d.ts +16 -0
  21. package/dist/angular/lib/gridstack-item.component.d.ts +7 -2
  22. package/dist/angular/lib/gridstack.component.d.ts +15 -7
  23. package/dist/angular/package.json +1 -1
  24. package/dist/angular/public-api.d.ts +1 -0
  25. package/dist/angular/src/base-widget.ts +28 -0
  26. package/dist/angular/src/gridstack-item.component.ts +10 -2
  27. package/dist/angular/src/gridstack.component.ts +83 -36
  28. package/dist/angular/src/gridstack.module.ts +1 -1
  29. package/dist/dd-base-impl.d.ts +1 -1
  30. package/dist/dd-base-impl.js +1 -1
  31. package/dist/dd-base-impl.js.map +1 -1
  32. package/dist/dd-draggable.d.ts +1 -1
  33. package/dist/dd-draggable.js +1 -1
  34. package/dist/dd-draggable.js.map +1 -1
  35. package/dist/dd-droppable.d.ts +1 -1
  36. package/dist/dd-droppable.js +1 -1
  37. package/dist/dd-droppable.js.map +1 -1
  38. package/dist/dd-element.d.ts +1 -1
  39. package/dist/dd-element.js +1 -1
  40. package/dist/dd-element.js.map +1 -1
  41. package/dist/dd-gridstack.d.ts +1 -1
  42. package/dist/dd-gridstack.js +1 -1
  43. package/dist/dd-gridstack.js.map +1 -1
  44. package/dist/dd-manager.d.ts +1 -1
  45. package/dist/dd-manager.js +1 -1
  46. package/dist/dd-manager.js.map +1 -1
  47. package/dist/dd-resizable-handle.d.ts +1 -1
  48. package/dist/dd-resizable-handle.js +1 -1
  49. package/dist/dd-resizable-handle.js.map +1 -1
  50. package/dist/dd-resizable.d.ts +1 -1
  51. package/dist/dd-resizable.js +1 -1
  52. package/dist/dd-resizable.js.map +1 -1
  53. package/dist/dd-touch.d.ts +1 -1
  54. package/dist/dd-touch.js +1 -1
  55. package/dist/dd-touch.js.map +1 -1
  56. package/dist/es5/dd-base-impl.d.ts +1 -1
  57. package/dist/es5/dd-base-impl.js +1 -1
  58. package/dist/es5/dd-base-impl.js.map +1 -1
  59. package/dist/es5/dd-draggable.d.ts +1 -1
  60. package/dist/es5/dd-draggable.js +1 -1
  61. package/dist/es5/dd-draggable.js.map +1 -1
  62. package/dist/es5/dd-droppable.d.ts +1 -1
  63. package/dist/es5/dd-droppable.js +1 -1
  64. package/dist/es5/dd-droppable.js.map +1 -1
  65. package/dist/es5/dd-element.d.ts +1 -1
  66. package/dist/es5/dd-element.js +1 -1
  67. package/dist/es5/dd-element.js.map +1 -1
  68. package/dist/es5/dd-gridstack.d.ts +1 -1
  69. package/dist/es5/dd-gridstack.js +1 -1
  70. package/dist/es5/dd-gridstack.js.map +1 -1
  71. package/dist/es5/dd-manager.d.ts +1 -1
  72. package/dist/es5/dd-manager.js +1 -1
  73. package/dist/es5/dd-manager.js.map +1 -1
  74. package/dist/es5/dd-resizable-handle.d.ts +1 -1
  75. package/dist/es5/dd-resizable-handle.js +1 -1
  76. package/dist/es5/dd-resizable-handle.js.map +1 -1
  77. package/dist/es5/dd-resizable.d.ts +1 -1
  78. package/dist/es5/dd-resizable.js +1 -1
  79. package/dist/es5/dd-resizable.js.map +1 -1
  80. package/dist/es5/dd-touch.d.ts +1 -1
  81. package/dist/es5/dd-touch.js +1 -1
  82. package/dist/es5/dd-touch.js.map +1 -1
  83. package/dist/es5/gridstack-all.js +1 -1
  84. package/dist/es5/gridstack-all.js.LICENSE.txt +1 -1
  85. package/dist/es5/gridstack-all.js.map +1 -1
  86. package/dist/es5/gridstack-engine.d.ts +1 -1
  87. package/dist/es5/gridstack-engine.js +10 -6
  88. package/dist/es5/gridstack-engine.js.map +1 -1
  89. package/dist/es5/gridstack-poly.js +1 -1
  90. package/dist/es5/gridstack.d.ts +8 -5
  91. package/dist/es5/gridstack.js +30 -23
  92. package/dist/es5/gridstack.js.map +1 -1
  93. package/dist/es5/types.d.ts +2 -4
  94. package/dist/es5/types.js +1 -1
  95. package/dist/es5/types.js.map +1 -1
  96. package/dist/es5/utils.d.ts +1 -1
  97. package/dist/es5/utils.js +1 -1
  98. package/dist/es5/utils.js.map +1 -1
  99. package/dist/gridstack-all.js +1 -1
  100. package/dist/gridstack-all.js.LICENSE.txt +1 -1
  101. package/dist/gridstack-all.js.map +1 -1
  102. package/dist/gridstack-engine.d.ts +1 -1
  103. package/dist/gridstack-engine.js +10 -6
  104. package/dist/gridstack-engine.js.map +1 -1
  105. package/dist/gridstack.css +1 -1
  106. package/dist/gridstack.d.ts +8 -5
  107. package/dist/gridstack.js +30 -23
  108. package/dist/gridstack.js.map +1 -1
  109. package/dist/src/gridstack.scss +1 -1
  110. package/dist/types.d.ts +2 -4
  111. package/dist/types.js +1 -1
  112. package/dist/types.js.map +1 -1
  113. package/dist/utils.d.ts +1 -1
  114. package/dist/utils.js +1 -1
  115. package/dist/utils.js.map +1 -1
  116. package/doc/CHANGES.md +15 -2
  117. package/package.json +1 -1
@@ -18,7 +18,7 @@
18
18
  "@angular/platform-browser": "^14.2.0",
19
19
  "@angular/platform-browser-dynamic": "^14.2.0",
20
20
  "@angular/router": "^14.2.0",
21
- "gridstack": "^8.1.1",
21
+ "gridstack": "^8.2.0",
22
22
  "rxjs": "~7.5.0",
23
23
  "tslib": "^2.3.0",
24
24
  "zone.js": "~0.11.4"
@@ -4,9 +4,9 @@ import { AngularSimpleComponent } from './simple';
4
4
  import { AngularNgForTestComponent } from './ngFor';
5
5
  import { AngularNgForCmdTestComponent } from './ngFor_cmd';
6
6
 
7
- // NOTE: local testing of file, but normal include would be 'gridstack/dist/angular'
8
- import { GridstackComponent, NgGridStackOptions, NgGridStackWidget, elementCB, gsCreateNgComponents, nodesCB } from '../../../../../dist/angular';
9
- // import { GridstackComponent, NgGridStackOptions, NgGridStackWidget, elementCB, gsCreateNgComponents, nodesCB } from 'gridstack/dist/angular';
7
+ // NOTE: local testing of file
8
+ // import { GridstackComponent, NgGridStackOptions, NgGridStackWidget, elementCB, gsCreateNgComponents, nodesCB } from './gridstack.component';
9
+ import { GridstackComponent, NgGridStackOptions, NgGridStackWidget, elementCB, gsCreateNgComponents, nodesCB } from 'gridstack/dist/angular';
10
10
 
11
11
  // unique ids sets for each item for correct ngFor updating
12
12
  let ids = 1;
@@ -25,7 +25,7 @@ export class AppComponent implements OnInit {
25
25
  @ViewChild('textArea', {static: true}) textEl?: ElementRef<HTMLTextAreaElement>;
26
26
 
27
27
  // which sample to show
28
- public show = 6;
28
+ public show = 5;
29
29
 
30
30
  /** sample grid options and items to load... */
31
31
  public items: GridStackWidget[] = [
@@ -35,12 +35,13 @@ export class AppComponent implements OnInit {
35
35
  ];
36
36
  public gridOptions: GridStackOptions = {
37
37
  margin: 5,
38
- float: true,
38
+ // float: true,
39
39
  minRow: 1,
40
40
  }
41
- public gridOptionsFull: GridStackOptions = {
41
+ private sub0: NgGridStackWidget[] = [{x:0, y:0, selector:'app-a'}, {x:1, y:0, content:'plain html'}, {x:0, y:1, selector:'app-b'} ];
42
+ public gridOptionsFull: NgGridStackOptions = {
42
43
  ...this.gridOptions,
43
- children: this.items,
44
+ children: this.sub0,
44
45
  }
45
46
 
46
47
  // nested grid options
@@ -50,7 +51,7 @@ export class AppComponent implements OnInit {
50
51
  acceptWidgets: true, // will accept .grid-stack-item by default
51
52
  margin: 5,
52
53
  };
53
- private sub1: NgGridStackWidget[] = [ {x:0, y:0, type:'app-a'}, {x:1, y:0, type:'app-b'}, {x:2, y:0, type:'app-c'}, {x:3, y:0}, {x:0, y:1}, {x:1, y:1}];
54
+ private sub1: NgGridStackWidget[] = [ {x:0, y:0, selector:'app-a'}, {x:1, y:0, selector:'app-b'}, {x:2, y:0, selector:'app-c'}, {x:3, y:0}, {x:0, y:1}, {x:1, y:1}];
54
55
  private sub2: NgGridStackWidget[] = [ {x:0, y:0}, {x:0, y:1, w:2}];
55
56
  private subChildren: NgGridStackWidget[] = [
56
57
  {x:0, y:0, content: 'regular item'},
@@ -70,8 +71,8 @@ export class AppComponent implements OnInit {
70
71
 
71
72
  constructor() {
72
73
  // give them content and unique id to make sure we track them during changes below...
73
- [...this.items, ...this.subChildren, ...this.sub1, ...this.sub2].forEach((w: NgGridStackWidget) => {
74
- if (!w.type && !w.subGridOpts) w.content = `item ${ids}`;
74
+ [...this.items, ...this.subChildren, ...this.sub1, ...this.sub2, ...this.sub0].forEach((w: NgGridStackWidget) => {
75
+ if (!w.selector && !w.content && !w.subGridOpts) w.content = `item ${ids}`;
75
76
  w.id = String(ids++);
76
77
  });
77
78
  }
@@ -7,9 +7,10 @@ import { AngularNgForCmdTestComponent } from './ngFor_cmd';
7
7
  import { AngularSimpleComponent } from './simple';
8
8
  import { AComponent, BComponent, CComponent } from './dummy.component';
9
9
 
10
- // local copy but user would use 'gridstack/dist/angular'
11
- import { GridstackModule, GridstackComponent } from '../../../../../dist/angular';
12
- // import { GridstackModule, GridstackComponent } from 'gridstack/dist/angular';
10
+ // local testing
11
+ // import { GridstackModule } from './gridstack.module';
12
+ // import { GridstackComponent } from './gridstack.component';
13
+ import { GridstackModule, GridstackComponent } from 'gridstack/dist/angular';
13
14
 
14
15
  @NgModule({
15
16
  imports: [
@@ -1,29 +1,35 @@
1
1
  /**
2
- * gridstack.component.ts 8.1.2
2
+ * gridstack.component.ts 8.2.1
3
3
  * Copyright (c) 2022 Alain Dumesny - see GridStack root license
4
4
  */
5
5
 
6
6
  // dummy testing component that will be grid items content
7
7
 
8
- import { Component } from '@angular/core';
8
+ import { Component, OnDestroy, Input } from '@angular/core';
9
+ import { BaseWidget, NgCompInputs } from 'gridstack/dist/angular';
9
10
 
10
11
  @Component({
11
12
  selector: 'app-a',
12
- template: 'Comp A',
13
+ template: 'Comp A {{text}}',
13
14
  })
14
- export class AComponent {
15
+ export class AComponent extends BaseWidget implements OnDestroy {
16
+ @Input() text: string = 'foo'; // test custom input data
17
+ public override serialize(): NgCompInputs | undefined { return this.text ? {text: this.text} : undefined; }
18
+ ngOnDestroy() {
19
+ console.log('Comp A destroyed'); // test to make sure cleanup happens
20
+ }
15
21
  }
16
22
 
17
23
  @Component({
18
24
  selector: 'app-b',
19
25
  template: 'Comp B',
20
26
  })
21
- export class BComponent {
27
+ export class BComponent extends BaseWidget {
22
28
  }
23
29
 
24
30
  @Component({
25
31
  selector: 'app-c',
26
32
  template: 'Comp C',
27
33
  })
28
- export class CComponent {
34
+ export class CComponent extends BaseWidget {
29
35
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gridstack-angular",
3
- "version": "8.1.2",
3
+ "version": "8.2.1",
4
4
  "peerDependencies": {
5
5
  "@angular/common": "^14.2.0",
6
6
  "@angular/core": "^14.2.0"
@@ -0,0 +1,28 @@
1
+ /**
2
+ * gridstack-item.component.ts 8.2.1
3
+ * Copyright (c) 2022 Alain Dumesny - see GridStack root license
4
+ */
5
+
6
+ /**
7
+ * Base interface that all widgets need to implement in order for GridstackItemComponent to correctly save/load/delete/..
8
+ */
9
+
10
+ import { Injectable } from '@angular/core';
11
+ import { NgCompInputs, NgGridStackWidget } from './gridstack.component';
12
+
13
+ @Injectable()
14
+ export abstract class BaseWidget {
15
+ /**
16
+ * REDEFINE to return an object representing the data needed to re-create yourself, other than `selector` already handled.
17
+ * This should map directly to the @Input() fields of this objects on create, so a simple apply can be used on read
18
+ */
19
+ public serialize(): NgCompInputs | undefined { return; }
20
+
21
+ /**
22
+ * REDEFINE this if your widget needs to read from saved data and transform it to create itself - you do this for
23
+ * things that are not mapped directly into @Input() fields for example.
24
+ */
25
+ public deserialize(w: NgGridStackWidget) {
26
+ if (w.input) Object.assign(this, w.input);
27
+ }
28
+ }
@@ -1,10 +1,11 @@
1
1
  /**
2
- * gridstack-item.component.ts 8.1.2
2
+ * gridstack-item.component.ts 8.2.1
3
3
  * Copyright (c) 2022 Alain Dumesny - see GridStack root license
4
4
  */
5
5
 
6
- import { Component, ElementRef, Input, ViewChild, ViewContainerRef, OnDestroy } from '@angular/core';
6
+ import { Component, ElementRef, Input, ViewChild, ViewContainerRef, OnDestroy, ComponentRef } from '@angular/core';
7
7
  import { GridItemHTMLElement, GridStackNode } from 'gridstack';
8
+ import { BaseWidget } from './base-widget';
8
9
 
9
10
  /** store element to Ng Class pointer back */
10
11
  export interface GridItemCompHTMLElement extends GridItemHTMLElement {
@@ -35,6 +36,12 @@ export class GridstackItemComponent implements OnDestroy {
35
36
  /** container to append items dynamically */
36
37
  @ViewChild('container', { read: ViewContainerRef, static: true}) public container?: ViewContainerRef;
37
38
 
39
+ /** ComponentRef of ourself - used by dynamic object to correctly get removed */
40
+ public ref: ComponentRef<GridstackItemComponent> | undefined;
41
+
42
+ /** child component so we can save/restore additional data to be saved along */
43
+ public childWidget: BaseWidget | undefined;
44
+
38
45
  /** list of options for creating/updating this item */
39
46
  @Input() public set options(val: GridStackNode) {
40
47
  if (this.el.gridstackNode?.grid) {
@@ -65,6 +72,7 @@ export class GridstackItemComponent implements OnDestroy {
65
72
  }
66
73
 
67
74
  public ngOnDestroy(): void {
75
+ delete this.ref;
68
76
  delete this.el._gridItemComp;
69
77
  }
70
78
  }
@@ -1,15 +1,16 @@
1
1
  /**
2
- * gridstack.component.ts 8.1.2
2
+ * gridstack.component.ts 8.2.1
3
3
  * Copyright (c) 2022 Alain Dumesny - see GridStack root license
4
4
  */
5
5
 
6
6
  import { AfterContentInit, Component, ContentChildren, ElementRef, EventEmitter, Input,
7
- OnDestroy, OnInit, Output, QueryList, Type, ViewChild, ViewContainerRef, reflectComponentType } from '@angular/core';
7
+ OnDestroy, OnInit, Output, QueryList, Type, ViewChild, ViewContainerRef, reflectComponentType, ComponentRef } from '@angular/core';
8
8
  import { Subject } from 'rxjs';
9
9
  import { takeUntil } from 'rxjs/operators';
10
10
  import { GridHTMLElement, GridItemHTMLElement, GridStack, GridStackNode, GridStackOptions, GridStackWidget } from 'gridstack';
11
11
 
12
12
  import { GridItemCompHTMLElement, GridstackItemComponent } from './gridstack-item.component';
13
+ import { BaseWidget } from './base-widget';
13
14
 
14
15
  /** events handlers emitters signature for different events */
15
16
  export type eventCB = {event: Event};
@@ -17,12 +18,15 @@ export type elementCB = {event: Event, el: GridItemHTMLElement};
17
18
  export type nodesCB = {event: Event, nodes: GridStackNode[]};
18
19
  export type droppedCB = {event: Event, previousNode: GridStackNode, newNode: GridStackNode};
19
20
 
21
+ export type NgCompInputs = {[key: string]: any};
22
+
20
23
  /** extends to store Ng Component selector, instead/inAddition to content */
21
24
  export interface NgGridStackWidget extends GridStackWidget {
22
- type?: string; // component type to create as content
25
+ selector?: string; // component type to create as content
26
+ input?: NgCompInputs; // serialized data for the component input fields
23
27
  }
24
28
  export interface NgGridStackNode extends GridStackNode {
25
- type?: string; // component type to create as content
29
+ selector?: string; // component type to create as content
26
30
  }
27
31
  export interface NgGridStackOptions extends GridStackOptions {
28
32
  children?: NgGridStackWidget[];
@@ -96,6 +100,9 @@ export class GridstackComponent implements OnInit, AfterContentInit, OnDestroy {
96
100
  /** return the GridStack class */
97
101
  public get grid(): GridStack | undefined { return this._grid; }
98
102
 
103
+ /** ComponentRef of ourself - used by dynamic object to correctly get removed */
104
+ public ref: ComponentRef<GridstackComponent> | undefined;
105
+
99
106
  /**
100
107
  * stores the selector -> Type mapping, so we can create items dynamically from a string.
101
108
  * Unfortunately Ng doesn't provide public access to that mapping.
@@ -107,8 +114,7 @@ export class GridstackComponent implements OnInit, AfterContentInit, OnDestroy {
107
114
  }
108
115
  /** return the ng Component selector */
109
116
  public static getSelector(type: Type<Object>): string {
110
- const mirror = reflectComponentType(type)!;
111
- return mirror.selector;
117
+ return reflectComponentType(type)!.selector;
112
118
  }
113
119
 
114
120
  private _options?: GridStackOptions;
@@ -145,6 +151,7 @@ export class GridstackComponent implements OnInit, AfterContentInit, OnDestroy {
145
151
  }
146
152
 
147
153
  public ngOnDestroy(): void {
154
+ delete this.ref;
148
155
  this.ngUnsubscribe.next();
149
156
  this.ngUnsubscribe.complete();
150
157
  this.grid?.destroy();
@@ -197,44 +204,84 @@ export class GridstackComponent implements OnInit, AfterContentInit, OnDestroy {
197
204
  /**
198
205
  * can be used when a new item needs to be created, which we do as a Angular component, or deleted (skip)
199
206
  **/
200
- export function gsCreateNgComponents(host: GridCompHTMLElement | HTMLElement, w: NgGridStackWidget | GridStackOptions, add: boolean, isGrid: boolean): HTMLElement | undefined {
201
- // only care about creating ng components here...
202
- if (!add || !host) return;
203
-
204
- // create the component dynamically - see https://angular.io/docs/ts/latest/cookbook/dynamic-component-loader.html
205
- if (isGrid) {
206
- let grid: GridstackComponent | undefined;
207
- const gridItemComp = (host.parentElement as GridItemCompHTMLElement)?._gridItemComp;
208
- if (gridItemComp) {
209
- grid = gridItemComp.container?.createComponent(GridstackComponent)?.instance;
210
- } else {
207
+ export function gsCreateNgComponents(host: GridCompHTMLElement | HTMLElement, w: NgGridStackWidget | GridStackNode, add: boolean, isGrid: boolean): HTMLElement | undefined {
208
+ if (add) {
209
+ //
210
+ // create the component dynamically - see https://angular.io/docs/ts/latest/cookbook/dynamic-component-loader.html
211
+ //
212
+ if (!host) return;
213
+ if (isGrid) {
214
+ const container = (host.parentElement as GridItemCompHTMLElement)?._gridItemComp?.container;
211
215
  // TODO: figure out how to create ng component inside regular Div. need to access app injectors...
212
- // const hostElement: Element = host;
213
- // const environmentInjector: EnvironmentInjector;
214
- // grid = createComponent(GridstackComponent, {environmentInjector, hostElement})?.instance;
216
+ // if (!container) {
217
+ // const hostElement: Element = host;
218
+ // const environmentInjector: EnvironmentInjector;
219
+ // grid = createComponent(GridstackComponent, {environmentInjector, hostElement})?.instance;
220
+ // }
221
+ const gridRef = container?.createComponent(GridstackComponent);
222
+ const grid = gridRef?.instance;
223
+ if (!grid) return;
224
+ grid.ref = gridRef;
225
+ grid.options = w as GridStackOptions;
226
+ return grid.el;
227
+ } else {
228
+ const gridComp = (host as GridCompHTMLElement)._gridComp;
229
+ const gridItemRef = gridComp?.container?.createComponent(GridstackItemComponent);
230
+ const gridItem = gridItemRef?.instance;
231
+ if (!gridItem) return;
232
+ gridItem.ref = gridItemRef
233
+
234
+ // IFF we're not a subGrid, define what type of component to create as child, OR you can do it GridstackItemComponent template, but this is more generic
235
+ const selector = (w as NgGridStackWidget).selector;
236
+ const type = selector ? GridstackComponent.selectorToType[selector] : undefined;
237
+ if (!w.subGridOpts && type) {
238
+ const childWidget = gridItem.container?.createComponent(type)?.instance as BaseWidget;
239
+ if (typeof childWidget?.serialize === 'function' && typeof childWidget?.deserialize === 'function') {
240
+ // proper BaseWidget subclass, save it and load additional data
241
+ gridItem.childWidget = childWidget;
242
+ childWidget.deserialize(w);
243
+ }
244
+ }
245
+
246
+ return gridItem.el;
215
247
  }
216
- if (grid) grid.options = w as GridStackOptions;
217
- return grid?.el;
218
248
  } else {
219
- const gridComp = (host as GridCompHTMLElement)._gridComp;
220
- const gridItem = gridComp?.container?.createComponent(GridstackItemComponent)?.instance;
221
-
222
- // IFF we're not a subGrid, define what type of component to create as child, OR you can do it GridstackItemComponent template, but this is more generic
223
- const selector = (w as NgGridStackWidget).type;
224
- const type = selector ? GridstackComponent.selectorToType[selector] : undefined;
225
- if (!w.subGridOpts && type) {
226
- gridItem?.container?.createComponent(type);
249
+ //
250
+ // REMOVE - have to call ComponentRef:destroy() for dynamic objects to correctly remove themselves
251
+ // Note: this will destroy all children dynamic components as well: gridItem -> childWidget
252
+ //
253
+ const n = w as GridStackNode;
254
+ if (isGrid) {
255
+ const grid = (n.el as GridCompHTMLElement)?._gridComp;
256
+ if (grid?.ref) grid.ref.destroy();
257
+ else grid?.ngOnDestroy();
258
+ } else {
259
+ const gridItem = (n.el as GridItemCompHTMLElement)?._gridItemComp;
260
+ if (gridItem?.ref) gridItem.ref.destroy();
261
+ else gridItem?.ngOnDestroy();
227
262
  }
228
-
229
- return gridItem?.el;
230
263
  }
264
+ return;
231
265
  }
232
266
 
233
267
  /**
234
- * can be used when saving the grid - make sure we save the content from the field (not HTML as we get ng markups)
235
- * and can put the extra info of type, otherwise content
268
+ * called for each item in the grid - check if additional information needs to be saved.
269
+ * Note: since this is options minus gridstack private members using Utils.removeInternalForSave(),
270
+ * this typically doesn't need to do anything. However your custom Component @Input() are now supported
271
+ * using BaseWidget.serialize()
236
272
  */
237
273
  export function gsSaveAdditionalNgInfo(n: NgGridStackNode, w: NgGridStackWidget) {
238
- if (n.type) w.type = n.type;
239
- else if (n.content) w.content = n.content;
274
+ const gridItem = (n.el as GridItemCompHTMLElement)?._gridItemComp;
275
+ if (gridItem) {
276
+ const input = gridItem.childWidget?.serialize();
277
+ if (input) {
278
+ w.input = input;
279
+ }
280
+ return;
281
+ }
282
+ // else check if Grid
283
+ const grid = (n.el as GridCompHTMLElement)?._gridComp;
284
+ if (grid) {
285
+ //.... save any custom data
286
+ }
240
287
  }
@@ -1,5 +1,5 @@
1
1
  /**
2
- * gridstack.component.ts 8.1.2
2
+ * gridstack.component.ts 8.2.1
3
3
  * Copyright (c) 2022 Alain Dumesny - see GridStack root license
4
4
  */
5
5
 
@@ -4,4 +4,5 @@
4
4
 
5
5
  export * from './lib/gridstack-item.component';
6
6
  export * from './lib/gridstack.component';
7
+ export * from './lib/base-widget';
7
8
  export * from './lib/gridstack.module';
@@ -0,0 +1,30 @@
1
+ /**
2
+ * gridstack-item.component.ts 8.2.1
3
+ * Copyright (c) 2022 Alain Dumesny - see GridStack root license
4
+ */
5
+ /**
6
+ * Base interface that all widgets need to implement in order for GridstackItemComponent to correctly save/load/delete/..
7
+ */
8
+ import { Injectable } from '@angular/core';
9
+ import * as i0 from "@angular/core";
10
+ export class BaseWidget {
11
+ /**
12
+ * REDEFINE to return an object representing the data needed to re-create yourself, other than `selector` already handled.
13
+ * This should map directly to the @Input() fields of this objects on create, so a simple apply can be used on read
14
+ */
15
+ serialize() { return; }
16
+ /**
17
+ * REDEFINE this if your widget needs to read from saved data and transform it to create itself - you do this for
18
+ * things that are not mapped directly into @Input() fields for example.
19
+ */
20
+ deserialize(w) {
21
+ if (w.input)
22
+ Object.assign(this, w.input);
23
+ }
24
+ }
25
+ BaseWidget.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: BaseWidget, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
26
+ BaseWidget.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: BaseWidget });
27
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: BaseWidget, decorators: [{
28
+ type: Injectable
29
+ }] });
30
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmFzZS13aWRnZXQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9hbmd1bGFyL3Byb2plY3RzL2xpYi9zcmMvbGliL2Jhc2Utd2lkZ2V0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7R0FHRztBQUVIOztHQUVHO0FBRUgsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLGVBQWUsQ0FBQzs7QUFJMUMsTUFBTSxPQUFnQixVQUFVO0lBQy9COzs7T0FHRztJQUNJLFNBQVMsS0FBZ0MsT0FBTyxDQUFDLENBQUM7SUFFekQ7OztPQUdHO0lBQ0ksV0FBVyxDQUFDLENBQW9CO1FBQ3JDLElBQUksQ0FBQyxDQUFDLEtBQUs7WUFBRyxNQUFNLENBQUMsTUFBTSxDQUFDLElBQUksRUFBRSxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDN0MsQ0FBQzs7dUdBYm9CLFVBQVU7MkdBQVYsVUFBVTsyRkFBVixVQUFVO2tCQUQvQixVQUFVIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXHJcbiAqIGdyaWRzdGFjay1pdGVtLmNvbXBvbmVudC50cyA4LjIuMVxyXG4gKiBDb3B5cmlnaHQgKGMpIDIwMjIgQWxhaW4gRHVtZXNueSAtIHNlZSBHcmlkU3RhY2sgcm9vdCBsaWNlbnNlXHJcbiAqL1xyXG5cclxuLyoqXHJcbiAqIEJhc2UgaW50ZXJmYWNlIHRoYXQgYWxsIHdpZGdldHMgbmVlZCB0byBpbXBsZW1lbnQgaW4gb3JkZXIgZm9yIEdyaWRzdGFja0l0ZW1Db21wb25lbnQgdG8gY29ycmVjdGx5IHNhdmUvbG9hZC9kZWxldGUvLi5cclxuICovXHJcblxyXG5pbXBvcnQgeyBJbmplY3RhYmxlIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XHJcbmltcG9ydCB7IE5nQ29tcElucHV0cywgTmdHcmlkU3RhY2tXaWRnZXQgfSBmcm9tICcuL2dyaWRzdGFjay5jb21wb25lbnQnO1xyXG5cclxuIEBJbmplY3RhYmxlKClcclxuIGV4cG9ydCBhYnN0cmFjdCBjbGFzcyBCYXNlV2lkZ2V0IHtcclxuICAvKipcclxuICAgKiBSRURFRklORSB0byByZXR1cm4gYW4gb2JqZWN0IHJlcHJlc2VudGluZyB0aGUgZGF0YSBuZWVkZWQgdG8gcmUtY3JlYXRlIHlvdXJzZWxmLCBvdGhlciB0aGFuIGBzZWxlY3RvcmAgYWxyZWFkeSBoYW5kbGVkLlxyXG4gICAqIFRoaXMgc2hvdWxkIG1hcCBkaXJlY3RseSB0byB0aGUgQElucHV0KCkgZmllbGRzIG9mIHRoaXMgb2JqZWN0cyBvbiBjcmVhdGUsIHNvIGEgc2ltcGxlIGFwcGx5IGNhbiBiZSB1c2VkIG9uIHJlYWRcclxuICAgKi9cclxuICBwdWJsaWMgc2VyaWFsaXplKCk6IE5nQ29tcElucHV0cyB8IHVuZGVmaW5lZCAgeyByZXR1cm47IH1cclxuXHJcbiAgLyoqXHJcbiAgICogUkVERUZJTkUgdGhpcyBpZiB5b3VyIHdpZGdldCBuZWVkcyB0byByZWFkIGZyb20gc2F2ZWQgZGF0YSBhbmQgdHJhbnNmb3JtIGl0IHRvIGNyZWF0ZSBpdHNlbGYgLSB5b3UgZG8gdGhpcyBmb3JcclxuICAgKiB0aGluZ3MgdGhhdCBhcmUgbm90IG1hcHBlZCBkaXJlY3RseSBpbnRvIEBJbnB1dCgpIGZpZWxkcyBmb3IgZXhhbXBsZS5cclxuICAgKi9cclxuICBwdWJsaWMgZGVzZXJpYWxpemUodzogTmdHcmlkU3RhY2tXaWRnZXQpICB7XHJcbiAgICBpZiAody5pbnB1dCkgIE9iamVjdC5hc3NpZ24odGhpcywgdy5pbnB1dCk7XHJcbiAgfVxyXG4gfVxyXG4iXX0=
@@ -1,5 +1,5 @@
1
1
  /**
2
- * gridstack-item.component.ts 8.1.2
2
+ * gridstack-item.component.ts 8.2.1
3
3
  * Copyright (c) 2022 Alain Dumesny - see GridStack root license
4
4
  */
5
5
  import { Component, Input, ViewChild, ViewContainerRef } from '@angular/core';
@@ -34,6 +34,7 @@ export class GridstackItemComponent {
34
34
  delete this._options;
35
35
  }
36
36
  ngOnDestroy() {
37
+ delete this.ref;
37
38
  delete this.el._gridItemComp;
38
39
  }
39
40
  }
@@ -64,4 +65,4 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImpor
64
65
  }], options: [{
65
66
  type: Input
66
67
  }] } });
67
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ3JpZHN0YWNrLWl0ZW0uY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vYW5ndWxhci9wcm9qZWN0cy9saWIvc3JjL2xpYi9ncmlkc3RhY2staXRlbS5jb21wb25lbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7OztHQUdHO0FBRUgsT0FBTyxFQUFFLFNBQVMsRUFBYyxLQUFLLEVBQUUsU0FBUyxFQUFFLGdCQUFnQixFQUFhLE1BQU0sZUFBZSxDQUFDOztBQVFyRzs7R0FFRztBQWlCSCxNQUFNLE9BQU8sc0JBQXNCO0lBOEJqQyxZQUE2QixVQUEyQztRQUEzQyxlQUFVLEdBQVYsVUFBVSxDQUFpQztRQUN0RSxJQUFJLENBQUMsRUFBRSxDQUFDLGFBQWEsR0FBRyxJQUFJLENBQUM7SUFDL0IsQ0FBQztJQTNCRCxzREFBc0Q7SUFDdEQsSUFBb0IsT0FBTyxDQUFDLEdBQWtCO1FBQzVDLElBQUksSUFBSSxDQUFDLEVBQUUsQ0FBQyxhQUFhLEVBQUUsSUFBSSxFQUFFO1lBQy9CLGlDQUFpQztZQUNqQyxJQUFJLENBQUMsRUFBRSxDQUFDLGFBQWEsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxFQUFFLEVBQUUsR0FBRyxDQUFDLENBQUM7U0FDakQ7YUFBTTtZQUNMLDJGQUEyRjtZQUMzRixJQUFJLENBQUMsUUFBUSxHQUFHLEVBQUMsR0FBRyxHQUFHLEVBQUUsRUFBRSxFQUFFLElBQUksQ0FBQyxFQUFFLEVBQUMsQ0FBQztTQUN2QztJQUNILENBQUM7SUFDRCxvRkFBb0Y7SUFDcEYsSUFBVyxPQUFPO1FBQ2hCLE9BQU8sSUFBSSxDQUFDLEVBQUUsQ0FBQyxhQUFhLElBQUksSUFBSSxDQUFDLFFBQVEsSUFBSSxFQUFDLEVBQUUsRUFBRSxJQUFJLENBQUMsRUFBRSxFQUFDLENBQUM7SUFDakUsQ0FBQztJQUlELDJFQUEyRTtJQUMzRSxJQUFXLEVBQUUsS0FBOEIsT0FBTyxJQUFJLENBQUMsVUFBVSxDQUFDLGFBQWEsQ0FBQyxDQUFDLENBQUM7SUFFbEYsc0RBQXNEO0lBQy9DLFlBQVk7UUFDakIsT0FBTyxJQUFJLENBQUMsUUFBUSxDQUFDO0lBQ3ZCLENBQUM7SUFNTSxXQUFXO1FBQ2hCLE9BQU8sSUFBSSxDQUFDLEVBQUUsQ0FBQyxhQUFhLENBQUM7SUFDL0IsQ0FBQzs7bUhBcENVLHNCQUFzQjt1R0FBdEIsc0JBQXNCLHlLQUdELGdCQUFnQiwyQ0FqQnRDOzs7Ozs7OztXQVFEOzJGQU1FLHNCQUFzQjtrQkFoQmxDLFNBQVM7K0JBQ0UsZ0JBQWdCLFlBQ2hCOzs7Ozs7OztXQVFEO2lHQVMrRCxTQUFTO3NCQUFoRixTQUFTO3VCQUFDLFdBQVcsRUFBRSxFQUFFLElBQUksRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFDO2dCQUczQyxPQUFPO3NCQUExQixLQUFLIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBncmlkc3RhY2staXRlbS5jb21wb25lbnQudHMgOC4xLjJcbiAqIENvcHlyaWdodCAoYykgMjAyMiBBbGFpbiBEdW1lc255IC0gc2VlIEdyaWRTdGFjayByb290IGxpY2Vuc2VcbiAqL1xuXG5pbXBvcnQgeyBDb21wb25lbnQsIEVsZW1lbnRSZWYsIElucHV0LCBWaWV3Q2hpbGQsIFZpZXdDb250YWluZXJSZWYsIE9uRGVzdHJveSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgR3JpZEl0ZW1IVE1MRWxlbWVudCwgR3JpZFN0YWNrTm9kZSB9IGZyb20gJ2dyaWRzdGFjayc7XG5cbi8qKiBzdG9yZSBlbGVtZW50IHRvIE5nIENsYXNzIHBvaW50ZXIgYmFjayAqL1xuZXhwb3J0IGludGVyZmFjZSBHcmlkSXRlbUNvbXBIVE1MRWxlbWVudCBleHRlbmRzIEdyaWRJdGVtSFRNTEVsZW1lbnQge1xuICBfZ3JpZEl0ZW1Db21wPzogR3JpZHN0YWNrSXRlbUNvbXBvbmVudDtcbn1cblxuLyoqXG4gKiBIVE1MIENvbXBvbmVudCBXcmFwcGVyIGZvciBncmlkc3RhY2sgaXRlbXMsIGluIGNvbWJpbmF0aW9uIHdpdGggR3JpZHN0YWNrQ29tcG9uZW50IGZvciBwYXJlbnQgZ3JpZFxuICovXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdncmlkc3RhY2staXRlbScsXG4gIHRlbXBsYXRlOiBgXG4gICAgPGRpdiBjbGFzcz1cImdyaWQtc3RhY2staXRlbS1jb250ZW50XCI+XG4gICAgICA8IS0tIHdoZXJlIGR5bmFtaWMgaXRlbXMgZ28gYmFzZWQgb24gY29tcG9uZW50IHR5cGVzLCBvciBzdWItZ3JpZHMsIGV0Yy4uLikgLS0+XG4gICAgICA8bmctdGVtcGxhdGUgI2NvbnRhaW5lcj48L25nLXRlbXBsYXRlPlxuICAgICAgPCEtLSBhbnkgc3RhdGljIChkZWZpbmVkIGluIGRvbSkgY29udGVudCBnb2VzIGhlcmUgLS0+XG4gICAgICA8bmctY29udGVudD48L25nLWNvbnRlbnQ+XG4gICAgICA8IS0tIGZhbGxiYWNrIEhUTUwgY29udGVudCBmcm9tIEdyaWRTdGFja1dpZGdldCBjb250ZW50IGZpZWxkIGlmIHVzZWQgaW5zdGVhZCAtLT5cbiAgICAgIHt7b3B0aW9ucy5jb250ZW50fX1cbiAgICA8L2Rpdj5gLFxuICBzdHlsZXM6IFtgXG4gICAgOmhvc3QgeyBkaXNwbGF5OiBibG9jazsgfVxuICBgXSxcbiAgLy8gY2hhbmdlRGV0ZWN0aW9uOiBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneS5PblB1c2gsIC8vIElGRiB5b3Ugd2FudCB0byBvcHRpbWl6ZSBhbmQgY29udHJvbCB3aGVuIENoYW5nZURldGVjdGlvbiBuZWVkcyB0byBoYXBwZW4uLi5cbn0pXG5leHBvcnQgY2xhc3MgR3JpZHN0YWNrSXRlbUNvbXBvbmVudCBpbXBsZW1lbnRzIE9uRGVzdHJveSB7XG5cbiAgLyoqIGNvbnRhaW5lciB0byBhcHBlbmQgaXRlbXMgZHluYW1pY2FsbHkgKi9cbiAgQFZpZXdDaGlsZCgnY29udGFpbmVyJywgeyByZWFkOiBWaWV3Q29udGFpbmVyUmVmLCBzdGF0aWM6IHRydWV9KSBwdWJsaWMgY29udGFpbmVyPzogVmlld0NvbnRhaW5lclJlZjtcblxuICAvKiogbGlzdCBvZiBvcHRpb25zIGZvciBjcmVhdGluZy91cGRhdGluZyB0aGlzIGl0ZW0gKi9cbiAgQElucHV0KCkgcHVibGljIHNldCBvcHRpb25zKHZhbDogR3JpZFN0YWNrTm9kZSkge1xuICAgIGlmICh0aGlzLmVsLmdyaWRzdGFja05vZGU/LmdyaWQpIHtcbiAgICAgIC8vIGFscmVhZHkgYnVpbHQsIGRvIGFuIHVwZGF0ZS4uLlxuICAgICAgdGhpcy5lbC5ncmlkc3RhY2tOb2RlLmdyaWQudXBkYXRlKHRoaXMuZWwsIHZhbCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIHN0b3JlIG91ciBjdXN0b20gZWxlbWVudCBpbiBvcHRpb25zIHNvIHdlIGNhbiB1cGRhdGUgaXQgYW5kIG5vdCByZS1jcmVhdGUgYSBnZW5lcmljIGRpdiFcbiAgICAgIHRoaXMuX29wdGlvbnMgPSB7Li4udmFsLCBlbDogdGhpcy5lbH07XG4gICAgfVxuICB9XG4gIC8qKiByZXR1cm4gdGhlIGxhdGVzdCBncmlkIG9wdGlvbnMgKGZyb20gR1Mgb25jZSBidWlsdCwgb3RoZXJ3aXNlIGluaXRpYWwgdmFsdWVzKSAqL1xuICBwdWJsaWMgZ2V0IG9wdGlvbnMoKTogR3JpZFN0YWNrTm9kZSB7XG4gICAgcmV0dXJuIHRoaXMuZWwuZ3JpZHN0YWNrTm9kZSB8fCB0aGlzLl9vcHRpb25zIHx8IHtlbDogdGhpcy5lbH07XG4gIH1cblxuICBwcml2YXRlIF9vcHRpb25zPzogR3JpZFN0YWNrTm9kZTtcblxuICAvKiogcmV0dXJuIHRoZSBuYXRpdmUgZWxlbWVudCB0aGF0IGNvbnRhaW5zIGdyaWQgc3BlY2lmaWMgZmllbGRzIGFzIHdlbGwgKi9cbiAgcHVibGljIGdldCBlbCgpOiBHcmlkSXRlbUNvbXBIVE1MRWxlbWVudCB7IHJldHVybiB0aGlzLmVsZW1lbnRSZWYubmF0aXZlRWxlbWVudDsgfVxuXG4gIC8qKiBjbGVhcnMgdGhlIGluaXRpYWwgb3B0aW9ucyBub3cgdGhhdCB3ZSd2ZSBidWlsdCAqL1xuICBwdWJsaWMgY2xlYXJPcHRpb25zKCkge1xuICAgIGRlbGV0ZSB0aGlzLl9vcHRpb25zO1xuICB9XG5cbiAgY29uc3RydWN0b3IocHJpdmF0ZSByZWFkb25seSBlbGVtZW50UmVmOiBFbGVtZW50UmVmPEdyaWRJdGVtSFRNTEVsZW1lbnQ+KSB7XG4gICAgdGhpcy5lbC5fZ3JpZEl0ZW1Db21wID0gdGhpcztcbiAgfVxuXG4gIHB1YmxpYyBuZ09uRGVzdHJveSgpOiB2b2lkIHtcbiAgICBkZWxldGUgdGhpcy5lbC5fZ3JpZEl0ZW1Db21wO1xuICB9XG59XG4iXX0=
68
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ3JpZHN0YWNrLWl0ZW0uY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vYW5ndWxhci9wcm9qZWN0cy9saWIvc3JjL2xpYi9ncmlkc3RhY2staXRlbS5jb21wb25lbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7OztHQUdHO0FBRUgsT0FBTyxFQUFFLFNBQVMsRUFBYyxLQUFLLEVBQUUsU0FBUyxFQUFFLGdCQUFnQixFQUEyQixNQUFNLGVBQWUsQ0FBQzs7QUFTbkg7O0dBRUc7QUFpQkgsTUFBTSxPQUFPLHNCQUFzQjtJQW9DakMsWUFBNkIsVUFBMkM7UUFBM0MsZUFBVSxHQUFWLFVBQVUsQ0FBaUM7UUFDdEUsSUFBSSxDQUFDLEVBQUUsQ0FBQyxhQUFhLEdBQUcsSUFBSSxDQUFDO0lBQy9CLENBQUM7SUEzQkQsc0RBQXNEO0lBQ3RELElBQW9CLE9BQU8sQ0FBQyxHQUFrQjtRQUM1QyxJQUFJLElBQUksQ0FBQyxFQUFFLENBQUMsYUFBYSxFQUFFLElBQUksRUFBRTtZQUMvQixpQ0FBaUM7WUFDakMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxhQUFhLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsRUFBRSxFQUFFLEdBQUcsQ0FBQyxDQUFDO1NBQ2pEO2FBQU07WUFDTCwyRkFBMkY7WUFDM0YsSUFBSSxDQUFDLFFBQVEsR0FBRyxFQUFDLEdBQUcsR0FBRyxFQUFFLEVBQUUsRUFBRSxJQUFJLENBQUMsRUFBRSxFQUFDLENBQUM7U0FDdkM7SUFDSCxDQUFDO0lBQ0Qsb0ZBQW9GO0lBQ3BGLElBQVcsT0FBTztRQUNoQixPQUFPLElBQUksQ0FBQyxFQUFFLENBQUMsYUFBYSxJQUFJLElBQUksQ0FBQyxRQUFRLElBQUksRUFBQyxFQUFFLEVBQUUsSUFBSSxDQUFDLEVBQUUsRUFBQyxDQUFDO0lBQ2pFLENBQUM7SUFJRCwyRUFBMkU7SUFDM0UsSUFBVyxFQUFFLEtBQThCLE9BQU8sSUFBSSxDQUFDLFVBQVUsQ0FBQyxhQUFhLENBQUMsQ0FBQyxDQUFDO0lBRWxGLHNEQUFzRDtJQUMvQyxZQUFZO1FBQ2pCLE9BQU8sSUFBSSxDQUFDLFFBQVEsQ0FBQztJQUN2QixDQUFDO0lBTU0sV0FBVztRQUNoQixPQUFPLElBQUksQ0FBQyxHQUFHLENBQUM7UUFDaEIsT0FBTyxJQUFJLENBQUMsRUFBRSxDQUFDLGFBQWEsQ0FBQztJQUMvQixDQUFDOzttSEEzQ1Usc0JBQXNCO3VHQUF0QixzQkFBc0IseUtBR0QsZ0JBQWdCLDJDQWpCdEM7Ozs7Ozs7O1dBUUQ7MkZBTUUsc0JBQXNCO2tCQWhCbEMsU0FBUzsrQkFDRSxnQkFBZ0IsWUFDaEI7Ozs7Ozs7O1dBUUQ7aUdBUytELFNBQVM7c0JBQWhGLFNBQVM7dUJBQUMsV0FBVyxFQUFFLEVBQUUsSUFBSSxFQUFFLGdCQUFnQixFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUM7Z0JBUzNDLE9BQU87c0JBQTFCLEtBQUsiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIGdyaWRzdGFjay1pdGVtLmNvbXBvbmVudC50cyA4LjIuMVxuICogQ29weXJpZ2h0IChjKSAyMDIyIEFsYWluIER1bWVzbnkgLSBzZWUgR3JpZFN0YWNrIHJvb3QgbGljZW5zZVxuICovXG5cbmltcG9ydCB7IENvbXBvbmVudCwgRWxlbWVudFJlZiwgSW5wdXQsIFZpZXdDaGlsZCwgVmlld0NvbnRhaW5lclJlZiwgT25EZXN0cm95LCBDb21wb25lbnRSZWYgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IEdyaWRJdGVtSFRNTEVsZW1lbnQsIEdyaWRTdGFja05vZGUgfSBmcm9tICdncmlkc3RhY2snO1xuaW1wb3J0IHsgQmFzZVdpZGdldCB9IGZyb20gJy4vYmFzZS13aWRnZXQnO1xuXG4vKiogc3RvcmUgZWxlbWVudCB0byBOZyBDbGFzcyBwb2ludGVyIGJhY2sgKi9cbmV4cG9ydCBpbnRlcmZhY2UgR3JpZEl0ZW1Db21wSFRNTEVsZW1lbnQgZXh0ZW5kcyBHcmlkSXRlbUhUTUxFbGVtZW50IHtcbiAgX2dyaWRJdGVtQ29tcD86IEdyaWRzdGFja0l0ZW1Db21wb25lbnQ7XG59XG5cbi8qKlxuICogSFRNTCBDb21wb25lbnQgV3JhcHBlciBmb3IgZ3JpZHN0YWNrIGl0ZW1zLCBpbiBjb21iaW5hdGlvbiB3aXRoIEdyaWRzdGFja0NvbXBvbmVudCBmb3IgcGFyZW50IGdyaWRcbiAqL1xuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnZ3JpZHN0YWNrLWl0ZW0nLFxuICB0ZW1wbGF0ZTogYFxuICAgIDxkaXYgY2xhc3M9XCJncmlkLXN0YWNrLWl0ZW0tY29udGVudFwiPlxuICAgICAgPCEtLSB3aGVyZSBkeW5hbWljIGl0ZW1zIGdvIGJhc2VkIG9uIGNvbXBvbmVudCB0eXBlcywgb3Igc3ViLWdyaWRzLCBldGMuLi4pIC0tPlxuICAgICAgPG5nLXRlbXBsYXRlICNjb250YWluZXI+PC9uZy10ZW1wbGF0ZT5cbiAgICAgIDwhLS0gYW55IHN0YXRpYyAoZGVmaW5lZCBpbiBkb20pIGNvbnRlbnQgZ29lcyBoZXJlIC0tPlxuICAgICAgPG5nLWNvbnRlbnQ+PC9uZy1jb250ZW50PlxuICAgICAgPCEtLSBmYWxsYmFjayBIVE1MIGNvbnRlbnQgZnJvbSBHcmlkU3RhY2tXaWRnZXQgY29udGVudCBmaWVsZCBpZiB1c2VkIGluc3RlYWQgLS0+XG4gICAgICB7e29wdGlvbnMuY29udGVudH19XG4gICAgPC9kaXY+YCxcbiAgc3R5bGVzOiBbYFxuICAgIDpob3N0IHsgZGlzcGxheTogYmxvY2s7IH1cbiAgYF0sXG4gIC8vIGNoYW5nZURldGVjdGlvbjogQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3kuT25QdXNoLCAvLyBJRkYgeW91IHdhbnQgdG8gb3B0aW1pemUgYW5kIGNvbnRyb2wgd2hlbiBDaGFuZ2VEZXRlY3Rpb24gbmVlZHMgdG8gaGFwcGVuLi4uXG59KVxuZXhwb3J0IGNsYXNzIEdyaWRzdGFja0l0ZW1Db21wb25lbnQgaW1wbGVtZW50cyBPbkRlc3Ryb3kge1xuXG4gIC8qKiBjb250YWluZXIgdG8gYXBwZW5kIGl0ZW1zIGR5bmFtaWNhbGx5ICovXG4gIEBWaWV3Q2hpbGQoJ2NvbnRhaW5lcicsIHsgcmVhZDogVmlld0NvbnRhaW5lclJlZiwgc3RhdGljOiB0cnVlfSkgcHVibGljIGNvbnRhaW5lcj86IFZpZXdDb250YWluZXJSZWY7XG5cbiAgLyoqIENvbXBvbmVudFJlZiBvZiBvdXJzZWxmIC0gdXNlZCBieSBkeW5hbWljIG9iamVjdCB0byBjb3JyZWN0bHkgZ2V0IHJlbW92ZWQgKi9cbiAgcHVibGljIHJlZjogQ29tcG9uZW50UmVmPEdyaWRzdGFja0l0ZW1Db21wb25lbnQ+IHwgdW5kZWZpbmVkO1xuXG4gIC8qKiBjaGlsZCBjb21wb25lbnQgc28gd2UgY2FuIHNhdmUvcmVzdG9yZSBhZGRpdGlvbmFsIGRhdGEgdG8gYmUgc2F2ZWQgYWxvbmcgKi9cbiAgcHVibGljIGNoaWxkV2lkZ2V0OiBCYXNlV2lkZ2V0IHwgdW5kZWZpbmVkO1xuXG4gIC8qKiBsaXN0IG9mIG9wdGlvbnMgZm9yIGNyZWF0aW5nL3VwZGF0aW5nIHRoaXMgaXRlbSAqL1xuICBASW5wdXQoKSBwdWJsaWMgc2V0IG9wdGlvbnModmFsOiBHcmlkU3RhY2tOb2RlKSB7XG4gICAgaWYgKHRoaXMuZWwuZ3JpZHN0YWNrTm9kZT8uZ3JpZCkge1xuICAgICAgLy8gYWxyZWFkeSBidWlsdCwgZG8gYW4gdXBkYXRlLi4uXG4gICAgICB0aGlzLmVsLmdyaWRzdGFja05vZGUuZ3JpZC51cGRhdGUodGhpcy5lbCwgdmFsKTtcbiAgICB9IGVsc2Uge1xuICAgICAgLy8gc3RvcmUgb3VyIGN1c3RvbSBlbGVtZW50IGluIG9wdGlvbnMgc28gd2UgY2FuIHVwZGF0ZSBpdCBhbmQgbm90IHJlLWNyZWF0ZSBhIGdlbmVyaWMgZGl2IVxuICAgICAgdGhpcy5fb3B0aW9ucyA9IHsuLi52YWwsIGVsOiB0aGlzLmVsfTtcbiAgICB9XG4gIH1cbiAgLyoqIHJldHVybiB0aGUgbGF0ZXN0IGdyaWQgb3B0aW9ucyAoZnJvbSBHUyBvbmNlIGJ1aWx0LCBvdGhlcndpc2UgaW5pdGlhbCB2YWx1ZXMpICovXG4gIHB1YmxpYyBnZXQgb3B0aW9ucygpOiBHcmlkU3RhY2tOb2RlIHtcbiAgICByZXR1cm4gdGhpcy5lbC5ncmlkc3RhY2tOb2RlIHx8IHRoaXMuX29wdGlvbnMgfHwge2VsOiB0aGlzLmVsfTtcbiAgfVxuXG4gIHByaXZhdGUgX29wdGlvbnM/OiBHcmlkU3RhY2tOb2RlO1xuXG4gIC8qKiByZXR1cm4gdGhlIG5hdGl2ZSBlbGVtZW50IHRoYXQgY29udGFpbnMgZ3JpZCBzcGVjaWZpYyBmaWVsZHMgYXMgd2VsbCAqL1xuICBwdWJsaWMgZ2V0IGVsKCk6IEdyaWRJdGVtQ29tcEhUTUxFbGVtZW50IHsgcmV0dXJuIHRoaXMuZWxlbWVudFJlZi5uYXRpdmVFbGVtZW50OyB9XG5cbiAgLyoqIGNsZWFycyB0aGUgaW5pdGlhbCBvcHRpb25zIG5vdyB0aGF0IHdlJ3ZlIGJ1aWx0ICovXG4gIHB1YmxpYyBjbGVhck9wdGlvbnMoKSB7XG4gICAgZGVsZXRlIHRoaXMuX29wdGlvbnM7XG4gIH1cblxuICBjb25zdHJ1Y3Rvcihwcml2YXRlIHJlYWRvbmx5IGVsZW1lbnRSZWY6IEVsZW1lbnRSZWY8R3JpZEl0ZW1IVE1MRWxlbWVudD4pIHtcbiAgICB0aGlzLmVsLl9ncmlkSXRlbUNvbXAgPSB0aGlzO1xuICB9XG5cbiAgcHVibGljIG5nT25EZXN0cm95KCk6IHZvaWQge1xuICAgIGRlbGV0ZSB0aGlzLnJlZjtcbiAgICBkZWxldGUgdGhpcy5lbC5fZ3JpZEl0ZW1Db21wO1xuICB9XG59XG4iXX0=