dockview-core 1.13.0 → 1.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/dist/cjs/api/dockviewGroupPanelApi.js +4 -5
  2. package/dist/cjs/api/dockviewPanelApi.js +4 -6
  3. package/dist/cjs/dockview/dockviewComponent.js +15 -17
  4. package/dist/cjs/dockview/dockviewPanel.js +1 -10
  5. package/dist/cjs/events.d.ts +13 -2
  6. package/dist/cjs/events.js +47 -15
  7. package/dist/cjs/gridview/baseComponentGridview.d.ts +3 -4
  8. package/dist/cjs/gridview/baseComponentGridview.js +3 -7
  9. package/dist/dockview-core.amd.js +66 -53
  10. package/dist/dockview-core.amd.js.map +1 -1
  11. package/dist/dockview-core.amd.min.js +2 -2
  12. package/dist/dockview-core.amd.min.js.map +1 -1
  13. package/dist/dockview-core.amd.min.noStyle.js +2 -2
  14. package/dist/dockview-core.amd.min.noStyle.js.map +1 -1
  15. package/dist/dockview-core.amd.noStyle.js +66 -53
  16. package/dist/dockview-core.amd.noStyle.js.map +1 -1
  17. package/dist/dockview-core.cjs.js +66 -53
  18. package/dist/dockview-core.cjs.js.map +1 -1
  19. package/dist/dockview-core.esm.js +66 -53
  20. package/dist/dockview-core.esm.js.map +1 -1
  21. package/dist/dockview-core.esm.min.js +2 -2
  22. package/dist/dockview-core.esm.min.js.map +1 -1
  23. package/dist/dockview-core.js +66 -53
  24. package/dist/dockview-core.js.map +1 -1
  25. package/dist/dockview-core.min.js +2 -2
  26. package/dist/dockview-core.min.js.map +1 -1
  27. package/dist/dockview-core.min.noStyle.js +2 -2
  28. package/dist/dockview-core.min.noStyle.js.map +1 -1
  29. package/dist/dockview-core.noStyle.js +66 -53
  30. package/dist/dockview-core.noStyle.js.map +1 -1
  31. package/dist/esm/api/dockviewGroupPanelApi.js +3 -4
  32. package/dist/esm/api/dockviewPanelApi.js +4 -6
  33. package/dist/esm/dockview/components/titlebar/tabsContainer.js +1 -1
  34. package/dist/esm/dockview/dockviewComponent.js +15 -17
  35. package/dist/esm/dockview/dockviewPanel.js +1 -10
  36. package/dist/esm/events.d.ts +13 -2
  37. package/dist/esm/events.js +40 -9
  38. package/dist/esm/gridview/baseComponentGridview.d.ts +3 -4
  39. package/dist/esm/gridview/baseComponentGridview.js +4 -8
  40. package/package.json +1 -1
@@ -2,8 +2,7 @@ import { positionToDirection } from '../dnd/droptarget';
2
2
  import { Emitter } from '../events';
3
3
  import { MutableDisposable } from '../lifecycle';
4
4
  import { GridviewPanelApiImpl } from './gridviewPanelApi';
5
- // TODO find a better way to initialize and avoid needing null checks
6
- const NOT_INITIALIZED_MESSAGE = 'DockviewGroupPanelApiImpl not initialized';
5
+ const NOT_INITIALIZED_MESSAGE = 'dockview: DockviewGroupPanelApiImpl not initialized';
7
6
  export class DockviewGroupPanelApiImpl extends GridviewPanelApiImpl {
8
7
  get location() {
9
8
  if (!this._group) {
@@ -76,14 +75,14 @@ export class DockviewGroupPanelApiImpl extends GridviewPanelApiImpl {
76
75
  }
77
76
  }
78
77
  initialize(group) {
79
- this._group = group;
80
78
  /**
81
- * TODO: Annoying initialization order caveat
79
+ * TODO: Annoying initialization order caveat, find a better way to initialize and avoid needing null checks
82
80
  *
83
81
  * Due to the order on initialization we know that the model isn't defined until later in the same stack-frame of setup.
84
82
  * By queuing a microtask we can ensure the setup is completed within the same stack-frame, but after everything else has
85
83
  * finished ensuring the `model` is defined.
86
84
  */
85
+ this._group = group;
87
86
  queueMicrotask(() => {
88
87
  this._mutableDisposable.value =
89
88
  this._group.model.onDidActivePanelChange((event) => {
@@ -88,12 +88,10 @@ export class DockviewPanelApiImpl extends GridviewPanelApiImpl {
88
88
  var _a;
89
89
  let _trackGroupActive = (_a = previousGroup === null || previousGroup === void 0 ? void 0 : previousGroup.isActive) !== null && _a !== void 0 ? _a : false; // prevent duplicate events with same state
90
90
  this.groupEventsDisposable.value = new CompositeDisposable(this.group.api.onDidVisibilityChange((event) => {
91
- if (!event.isVisible && this.isVisible) {
92
- this._onDidVisibilityChange.fire(event);
93
- }
94
- else if (event.isVisible &&
95
- !this.isVisible &&
96
- this.group.model.isPanelActive(this.panel)) {
91
+ const hasBecomeHidden = !event.isVisible && this.isVisible;
92
+ const hasBecomeVisible = event.isVisible && !this.isVisible;
93
+ const isActivePanel = this.group.model.isPanelActive(this.panel);
94
+ if (hasBecomeHidden || (hasBecomeVisible && isActivePanel)) {
97
95
  this._onDidVisibilityChange.fire(event);
98
96
  }
99
97
  }), this.group.api.onDidLocationChange((event) => {
@@ -3,7 +3,7 @@ import { addDisposableListener, Emitter } from '../../../events';
3
3
  import { Tab } from '../tab/tab';
4
4
  import { VoidContainer } from './voidContainer';
5
5
  import { toggleClass } from '../../../dom';
6
- import { WillShowOverlayLocationEvent, } from '../../dockviewGroupPanelModel';
6
+ import { WillShowOverlayLocationEvent } from '../../dockviewGroupPanelModel';
7
7
  import { getPanelData } from '../../../dnd/dataTransfer';
8
8
  export class TabsContainer extends CompositeDisposable {
9
9
  get panels() {
@@ -328,7 +328,7 @@ export class DockviewComponent extends BaseGrid {
328
328
  return element.getBoundingClientRect();
329
329
  }
330
330
  const box = getBox();
331
- const groupId = (_b = (_a = options === null || options === void 0 ? void 0 : options.overridePopoutGroup) === null || _a === void 0 ? void 0 : _a.id) !== null && _b !== void 0 ? _b : this.getNextGroupId(); //item.id;
331
+ const groupId = (_b = (_a = options === null || options === void 0 ? void 0 : options.overridePopoutGroup) === null || _a === void 0 ? void 0 : _a.id) !== null && _b !== void 0 ? _b : this.getNextGroupId();
332
332
  if (itemToPopout.api.location.type === 'grid') {
333
333
  itemToPopout.api.setVisible(false);
334
334
  }
@@ -444,24 +444,22 @@ export class DockviewComponent extends BaseGrid {
444
444
  });
445
445
  }
446
446
  }
447
- else {
448
- if (this.getPanel(group.id)) {
449
- const removedGroup = this.doRemoveGroup(group, {
450
- skipDispose: true,
451
- skipActive: true,
452
- });
453
- removedGroup.model.renderContainer =
454
- this.overlayRenderContainer;
455
- removedGroup.model.location = { type: 'grid' };
456
- returnedGroup = removedGroup;
457
- }
447
+ else if (this.getPanel(group.id)) {
448
+ const removedGroup = this.doRemoveGroup(group, {
449
+ skipDispose: true,
450
+ skipActive: true,
451
+ });
452
+ removedGroup.model.renderContainer =
453
+ this.overlayRenderContainer;
454
+ removedGroup.model.location = { type: 'grid' };
455
+ returnedGroup = removedGroup;
458
456
  }
459
457
  }));
460
458
  this._popoutGroups.push(value);
461
459
  this.updateWatermark();
462
460
  })
463
461
  .catch((err) => {
464
- console.error(err);
462
+ console.error('dockview: failed to create popout window', err);
465
463
  });
466
464
  }
467
465
  addFloatingGroup(item, coord, options) {
@@ -504,7 +502,7 @@ export class DockviewComponent extends BaseGrid {
504
502
  this.doRemoveGroup(item, {
505
503
  skipDispose: true,
506
504
  skipPopoutReturn: true,
507
- skipPopoutAssociated: !!popoutReferenceGroup,
505
+ skipPopoutAssociated: false,
508
506
  });
509
507
  }
510
508
  }
@@ -866,7 +864,6 @@ export class DockviewComponent extends BaseGrid {
866
864
  clear() {
867
865
  const groups = Array.from(this._groups.values()).map((_) => _.value);
868
866
  const hasActiveGroup = !!this.activeGroup;
869
- const hasActivePanel = !!this.activePanel;
870
867
  for (const group of groups) {
871
868
  // remove the group will automatically remove the panels
872
869
  this.removeGroup(group, { skipActive: true });
@@ -1050,7 +1047,6 @@ export class DockviewComponent extends BaseGrid {
1050
1047
  }
1051
1048
  addGroup(options) {
1052
1049
  var _a;
1053
- const group = this.createGroup(options);
1054
1050
  if (options) {
1055
1051
  let referenceGroup;
1056
1052
  if (isGroupOptionsWithPanel(options)) {
@@ -1084,6 +1080,7 @@ export class DockviewComponent extends BaseGrid {
1084
1080
  const target = toTarget(options.direction || 'within');
1085
1081
  const location = getGridLocation(referenceGroup.element);
1086
1082
  const relativeLocation = getRelativeLocation(this.gridview.orientation, location, target);
1083
+ const group = this.createGroup(options);
1087
1084
  this.doAddGroup(group, relativeLocation);
1088
1085
  if (!options.skipSetActive) {
1089
1086
  this.doSetGroupAndPanelActive(group);
@@ -1091,6 +1088,7 @@ export class DockviewComponent extends BaseGrid {
1091
1088
  return group;
1092
1089
  }
1093
1090
  else {
1091
+ const group = this.createGroup(options);
1094
1092
  this.doAddGroup(group);
1095
1093
  this.doSetGroupAndPanelActive(group);
1096
1094
  return group;
@@ -1371,7 +1369,7 @@ export class DockviewComponent extends BaseGrid {
1371
1369
  }
1372
1370
  let id = options === null || options === void 0 ? void 0 : options.id;
1373
1371
  if (id && this._groups.has(options.id)) {
1374
- console.warn(`Duplicate group id ${options === null || options === void 0 ? void 0 : options.id}. reassigning group id to avoid errors`);
1372
+ console.warn(`dockview: Duplicate group id ${options === null || options === void 0 ? void 0 : options.id}. reassigning group id to avoid errors`);
1375
1373
  id = undefined;
1376
1374
  }
1377
1375
  if (!id) {
@@ -65,12 +65,6 @@ export class DockviewPanel extends CompositeDisposable {
65
65
  const didTitleChange = title !== this.title;
66
66
  if (didTitleChange) {
67
67
  this._title = title;
68
- this.view.update({
69
- params: {
70
- params: this._params,
71
- title: this.title,
72
- },
73
- });
74
68
  this.api._onDidTitleChange.fire({ title });
75
69
  }
76
70
  }
@@ -98,10 +92,7 @@ export class DockviewPanel extends CompositeDisposable {
98
92
  }
99
93
  // update the view with the updated props
100
94
  this.view.update({
101
- params: {
102
- params: this._params,
103
- title: this.title,
104
- },
95
+ params: this._params,
105
96
  });
106
97
  }
107
98
  updateParentGroup(group, options) {
@@ -47,9 +47,20 @@ export declare class Emitter<T> implements IDisposable {
47
47
  }
48
48
  export declare function addDisposableWindowListener<K extends keyof WindowEventMap>(element: Window, type: K, listener: (this: Window, ev: WindowEventMap[K]) => any, options?: boolean | AddEventListenerOptions): IDisposable;
49
49
  export declare function addDisposableListener<K extends keyof HTMLElementEventMap>(element: HTMLElement, type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, options?: boolean | AddEventListenerOptions): IDisposable;
50
- export declare class TickDelayedEvent implements IDisposable {
51
- private timer;
50
+ /**
51
+ *
52
+ * Event Emitter that fires events from a Microtask callback, only one event will fire per event-loop cycle.
53
+ *
54
+ * It's kind of like using an `asapScheduler` in RxJs with additional logic to only fire once per event-loop cycle.
55
+ * This implementation exists to avoid external dependencies.
56
+ *
57
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/queueMicrotask
58
+ * @see https://rxjs.dev/api/index/const/asapScheduler
59
+ */
60
+ export declare class AsapEvent implements IDisposable {
52
61
  private readonly _onFired;
62
+ private _currentFireCount;
63
+ private _queued;
53
64
  readonly onEvent: Event<void>;
54
65
  fire(): void;
55
66
  dispose(): void;
@@ -50,7 +50,7 @@ class Stacktrace {
50
50
  this.value = value;
51
51
  }
52
52
  print() {
53
- console.warn(this.value);
53
+ console.warn('dockview: stacktrace', this.value);
54
54
  }
55
55
  }
56
56
  class Listener {
@@ -92,7 +92,7 @@ export class Emitter {
92
92
  }
93
93
  else if (Emitter.ENABLE_TRACKING) {
94
94
  // console.warn(
95
- // `Listener already disposed`,
95
+ // `dockview: listener already disposed`,
96
96
  // Stacktrace.create().print()
97
97
  // );
98
98
  }
@@ -120,7 +120,7 @@ export class Emitter {
120
120
  var _a;
121
121
  // don't check until stack of execution is completed to allow for out-of-order disposals within the same execution block
122
122
  for (const listener of this._listeners) {
123
- console.warn((_a = listener.stacktrace) === null || _a === void 0 ? void 0 : _a.print());
123
+ console.warn('dockview: stacktrace', (_a = listener.stacktrace) === null || _a === void 0 ? void 0 : _a.print());
124
124
  }
125
125
  });
126
126
  }
@@ -150,18 +150,49 @@ export function addDisposableListener(element, type, listener, options) {
150
150
  },
151
151
  };
152
152
  }
153
- export class TickDelayedEvent {
153
+ /**
154
+ *
155
+ * Event Emitter that fires events from a Microtask callback, only one event will fire per event-loop cycle.
156
+ *
157
+ * It's kind of like using an `asapScheduler` in RxJs with additional logic to only fire once per event-loop cycle.
158
+ * This implementation exists to avoid external dependencies.
159
+ *
160
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/queueMicrotask
161
+ * @see https://rxjs.dev/api/index/const/asapScheduler
162
+ */
163
+ export class AsapEvent {
154
164
  constructor() {
155
165
  this._onFired = new Emitter();
156
- this.onEvent = this._onFired.event;
166
+ this._currentFireCount = 0;
167
+ this._queued = false;
168
+ this.onEvent = (e) => {
169
+ /**
170
+ * when the event is first subscribed to take note of the current fire count
171
+ */
172
+ const fireCountAtTimeOfEventSubscription = this._currentFireCount;
173
+ return this._onFired.event(() => {
174
+ /**
175
+ * if the current fire count is greater than the fire count at event subscription
176
+ * then the event has been fired since we subscribed and it's ok to "on_next" the event.
177
+ *
178
+ * if the count is not greater then what we are recieving is an event from the microtask
179
+ * queue that was triggered before we actually subscribed and therfore we should ignore it.
180
+ */
181
+ if (this._currentFireCount > fireCountAtTimeOfEventSubscription) {
182
+ e();
183
+ }
184
+ });
185
+ };
157
186
  }
158
187
  fire() {
159
- if (this.timer) {
160
- clearTimeout(this.timer);
188
+ this._currentFireCount++;
189
+ if (this._queued) {
190
+ return;
161
191
  }
162
- this.timer = setTimeout(() => {
192
+ this._queued = true;
193
+ queueMicrotask(() => {
194
+ this._queued = false;
163
195
  this._onFired.fire();
164
- clearTimeout(this.timer);
165
196
  });
166
197
  }
167
198
  dispose() {
@@ -1,4 +1,4 @@
1
- import { Event, TickDelayedEvent } from '../events';
1
+ import { Event, AsapEvent } from '../events';
2
2
  import { Gridview, IGridView } from './gridview';
3
3
  import { Position } from '../dnd/droptarget';
4
4
  import { IValueDisposable } from '../lifecycle';
@@ -51,15 +51,14 @@ export declare abstract class BaseGrid<T extends IGridPanelView> extends Resizab
51
51
  protected readonly _groups: Map<string, IValueDisposable<T>>;
52
52
  protected readonly gridview: Gridview;
53
53
  protected _activeGroup: T | undefined;
54
- private _onDidLayoutChange;
55
- readonly onDidLayoutChange: Event<void>;
56
54
  private readonly _onDidRemove;
57
55
  readonly onDidRemove: Event<T>;
58
56
  private readonly _onDidAdd;
59
57
  readonly onDidAdd: Event<T>;
60
58
  private readonly _onDidActiveChange;
61
59
  readonly onDidActiveChange: Event<T | undefined>;
62
- protected readonly _bufferOnDidLayoutChange: TickDelayedEvent;
60
+ protected readonly _bufferOnDidLayoutChange: AsapEvent;
61
+ readonly onDidLayoutChange: Event<void>;
63
62
  get id(): string;
64
63
  get size(): number;
65
64
  get groups(): T[];
@@ -1,4 +1,4 @@
1
- import { Emitter, Event, TickDelayedEvent } from '../events';
1
+ import { Emitter, Event, AsapEvent } from '../events';
2
2
  import { getGridLocation, Gridview } from './gridview';
3
3
  import { Disposable } from '../lifecycle';
4
4
  import { sequentialNumberGenerator } from '../math';
@@ -61,15 +61,14 @@ export class BaseGrid extends Resizable {
61
61
  super(document.createElement('div'), options.disableAutoResizing);
62
62
  this._id = nextLayoutId.next();
63
63
  this._groups = new Map();
64
- this._onDidLayoutChange = new Emitter();
65
- this.onDidLayoutChange = this._onDidLayoutChange.event;
66
64
  this._onDidRemove = new Emitter();
67
65
  this.onDidRemove = this._onDidRemove.event;
68
66
  this._onDidAdd = new Emitter();
69
67
  this.onDidAdd = this._onDidAdd.event;
70
68
  this._onDidActiveChange = new Emitter();
71
69
  this.onDidActiveChange = this._onDidActiveChange.event;
72
- this._bufferOnDidLayoutChange = new TickDelayedEvent();
70
+ this._bufferOnDidLayoutChange = new AsapEvent();
71
+ this.onDidLayoutChange = this._bufferOnDidLayoutChange.onEvent;
73
72
  this.element.style.height = '100%';
74
73
  this.element.style.width = '100%';
75
74
  options.parentElement.appendChild(this.element);
@@ -84,13 +83,11 @@ export class BaseGrid extends Resizable {
84
83
  this._bufferOnDidLayoutChange.fire();
85
84
  }), Event.any(this.onDidAdd, this.onDidRemove, this.onDidActiveChange)(() => {
86
85
  this._bufferOnDidLayoutChange.fire();
87
- }), this._bufferOnDidLayoutChange.onEvent(() => {
88
- this._onDidLayoutChange.fire();
89
86
  }), this._bufferOnDidLayoutChange);
90
87
  }
91
88
  setVisible(panel, visible) {
92
89
  this.gridview.setViewVisible(getGridLocation(panel.element), visible);
93
- this._onDidLayoutChange.fire();
90
+ this._bufferOnDidLayoutChange.fire();
94
91
  }
95
92
  isVisible(panel) {
96
93
  return this.gridview.isViewVisible(getGridLocation(panel.element));
@@ -196,7 +193,6 @@ export class BaseGrid extends Resizable {
196
193
  this._onDidActiveChange.dispose();
197
194
  this._onDidAdd.dispose();
198
195
  this._onDidRemove.dispose();
199
- this._onDidLayoutChange.dispose();
200
196
  for (const group of this.groups) {
201
197
  group.dispose();
202
198
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dockview-core",
3
- "version": "1.13.0",
3
+ "version": "1.14.0",
4
4
  "description": "Zero dependency layout manager supporting tabs, grids and splitviews",
5
5
  "keywords": [
6
6
  "splitview",