dockview 1.8.3 → 1.8.4

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.
package/dist/dockview.js CHANGED
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * dockview
3
- * @version 1.8.3
3
+ * @version 1.8.4
4
4
  * @link https://github.com/mathuo/dockview
5
5
  * @license MIT
6
6
  */
@@ -922,7 +922,17 @@
922
922
  size = typeof size === 'number' ? size : item.size;
923
923
  size = clamp(size, item.minimumSize, item.maximumSize);
924
924
  item.size = size;
925
- this.relayout([index]);
925
+ const indexes = range(this.viewItems.length).filter((i) => i !== index);
926
+ const lowPriorityIndexes = [
927
+ ...indexes.filter((i) => this.viewItems[i].priority === exports.LayoutPriority.Low),
928
+ index,
929
+ ];
930
+ const highPriorityIndexes = indexes.filter((i) => this.viewItems[i].priority === exports.LayoutPriority.High);
931
+ /**
932
+ * add this view we are changing to the low-index list since we have determined the size
933
+ * here and don't want it changed
934
+ */
935
+ this.relayout([...lowPriorityIndexes, index], highPriorityIndexes);
926
936
  }
927
937
  addView(view, size = { type: 'distribute' }, index = this.viewItems.length, skipLayout) {
928
938
  const container = document.createElement('div');
@@ -1679,6 +1689,7 @@
1679
1689
  orientation: this.orientation,
1680
1690
  descriptor,
1681
1691
  proportionalLayout,
1692
+ styles,
1682
1693
  });
1683
1694
  }
1684
1695
  this.addDisposables(this._onDidChange, this.splitview.onDidSashEnd(() => {
@@ -2190,6 +2201,14 @@
2190
2201
  const child = sibling.children[i];
2191
2202
  grandParent.addChild(child, child.size, parentIndex + i);
2192
2203
  }
2204
+ /**
2205
+ * clean down the branch node since we need to dipose of it and
2206
+ * when .dispose() it called on a branch it will dispose of any
2207
+ * views it is holding onto.
2208
+ */
2209
+ while (sibling.children.length > 0) {
2210
+ sibling.removeChild(0);
2211
+ }
2193
2212
  }
2194
2213
  else {
2195
2214
  // otherwise create a new leaf node and add that to the grandparent
@@ -3248,6 +3267,19 @@
3248
3267
  this.leftActions = element;
3249
3268
  }
3250
3269
  }
3270
+ setPrefixActionsElement(element) {
3271
+ if (this.preActions === element) {
3272
+ return;
3273
+ }
3274
+ if (this.preActions) {
3275
+ this.preActions.remove();
3276
+ this.preActions = undefined;
3277
+ }
3278
+ if (element) {
3279
+ this.preActionsContainer.appendChild(element);
3280
+ this.preActions = element;
3281
+ }
3282
+ }
3251
3283
  get element() {
3252
3284
  return this._element;
3253
3285
  }
@@ -3288,9 +3320,12 @@
3288
3320
  this.rightActionsContainer.className = 'right-actions-container';
3289
3321
  this.leftActionsContainer = document.createElement('div');
3290
3322
  this.leftActionsContainer.className = 'left-actions-container';
3323
+ this.preActionsContainer = document.createElement('div');
3324
+ this.preActionsContainer.className = 'pre-actions-container';
3291
3325
  this.tabContainer = document.createElement('div');
3292
3326
  this.tabContainer.className = 'tabs-container';
3293
3327
  this.voidContainer = new VoidContainer(this.accessor, this.group);
3328
+ this._element.appendChild(this.preActionsContainer);
3294
3329
  this._element.appendChild(this.tabContainer);
3295
3330
  this._element.appendChild(this.leftActionsContainer);
3296
3331
  this._element.appendChild(this.voidContainer.element);
@@ -3580,6 +3615,16 @@
3580
3615
  });
3581
3616
  this.tabsContainer.setLeftActionsElement(this._leftHeaderActions.element);
3582
3617
  }
3618
+ if (this.accessor.options.createPrefixHeaderActionsElement) {
3619
+ this._prefixHeaderActions =
3620
+ this.accessor.options.createPrefixHeaderActionsElement(this.groupPanel);
3621
+ this.addDisposables(this._prefixHeaderActions);
3622
+ this._prefixHeaderActions.init({
3623
+ containerApi: new DockviewApi(this.accessor),
3624
+ api: this.groupPanel.api,
3625
+ });
3626
+ this.tabsContainer.setPrefixActionsElement(this._prefixHeaderActions.element);
3627
+ }
3583
3628
  }
3584
3629
  indexOf(panel) {
3585
3630
  return this.tabsContainer.indexOf(panel.id);
@@ -3922,6 +3967,14 @@
3922
3967
  */
3923
3968
  return;
3924
3969
  }
3970
+ if (!document.body.contains(this._element)) {
3971
+ /**
3972
+ * since the event is dispatched through requestAnimationFrame there is a small chance
3973
+ * the component is no longer attached to the DOM, if that is the case the dimensions
3974
+ * are mostly likely all zero and meaningless. we should skip this case.
3975
+ */
3976
+ return;
3977
+ }
3925
3978
  const { width, height } = entry.contentRect;
3926
3979
  this.layout(width, height);
3927
3980
  }));
@@ -5950,61 +6003,114 @@
5950
6003
  fromJSON(data) {
5951
6004
  var _a;
5952
6005
  this.clear();
6006
+ if (typeof data !== 'object' || data === null) {
6007
+ throw new Error('serialized layout must be a non-null object');
6008
+ }
5953
6009
  const { grid, panels, activeGroup } = data;
5954
6010
  if (grid.root.type !== 'branch' || !Array.isArray(grid.root.data)) {
5955
6011
  throw new Error('root must be of type branch');
5956
6012
  }
5957
- // take note of the existing dimensions
5958
- const width = this.width;
5959
- const height = this.height;
5960
- const createGroupFromSerializedState = (data) => {
5961
- const { id, locked, hideHeader, views, activeView } = data;
5962
- const group = this.createGroup({
5963
- id,
5964
- locked: !!locked,
5965
- hideHeader: !!hideHeader,
5966
- });
5967
- this._onDidAddGroup.fire(group);
5968
- for (const child of views) {
5969
- const panel = this._deserializer.fromJSON(panels[child], group);
5970
- const isActive = typeof activeView === 'string' && activeView === panel.id;
5971
- group.model.openPanel(panel, {
5972
- skipSetPanelActive: !isActive,
5973
- skipSetGroupActive: true,
6013
+ try {
6014
+ // take note of the existing dimensions
6015
+ const width = this.width;
6016
+ const height = this.height;
6017
+ const createGroupFromSerializedState = (data) => {
6018
+ const { id, locked, hideHeader, views, activeView } = data;
6019
+ if (typeof id !== 'string') {
6020
+ throw new Error('group id must be of type string');
6021
+ }
6022
+ const group = this.createGroup({
6023
+ id,
6024
+ locked: !!locked,
6025
+ hideHeader: !!hideHeader,
5974
6026
  });
6027
+ const createdPanels = [];
6028
+ for (const child of views) {
6029
+ /**
6030
+ * Run the deserializer step seperately since this may fail to due corrupted external state.
6031
+ * In running this section first we avoid firing lots of 'add' events in the event of a failure
6032
+ * due to a corruption of input data.
6033
+ */
6034
+ const panel = this._deserializer.fromJSON(panels[child], group);
6035
+ createdPanels.push(panel);
6036
+ }
6037
+ this._onDidAddGroup.fire(group);
6038
+ for (let i = 0; i < views.length; i++) {
6039
+ const panel = createdPanels[i];
6040
+ const isActive = typeof activeView === 'string' &&
6041
+ activeView === panel.id;
6042
+ group.model.openPanel(panel, {
6043
+ skipSetPanelActive: !isActive,
6044
+ skipSetGroupActive: true,
6045
+ });
6046
+ }
6047
+ if (!group.activePanel && group.panels.length > 0) {
6048
+ group.model.openPanel(group.panels[group.panels.length - 1], {
6049
+ skipSetGroupActive: true,
6050
+ });
6051
+ }
6052
+ return group;
6053
+ };
6054
+ this.gridview.deserialize(grid, {
6055
+ fromJSON: (node) => {
6056
+ return createGroupFromSerializedState(node.data);
6057
+ },
6058
+ });
6059
+ this.layout(width, height, true);
6060
+ const serializedFloatingGroups = (_a = data.floatingGroups) !== null && _a !== void 0 ? _a : [];
6061
+ for (const serializedFloatingGroup of serializedFloatingGroups) {
6062
+ const { data, position } = serializedFloatingGroup;
6063
+ const group = createGroupFromSerializedState(data);
6064
+ this.addFloatingGroup(group, {
6065
+ x: position.left,
6066
+ y: position.top,
6067
+ height: position.height,
6068
+ width: position.width,
6069
+ }, { skipRemoveGroup: true, inDragMode: false });
6070
+ }
6071
+ for (const floatingGroup of this.floatingGroups) {
6072
+ floatingGroup.overlay.setBounds();
6073
+ }
6074
+ if (typeof activeGroup === 'string') {
6075
+ const panel = this.getPanel(activeGroup);
6076
+ if (panel) {
6077
+ this.doSetGroupActive(panel);
6078
+ }
5975
6079
  }
5976
- if (!group.activePanel && group.panels.length > 0) {
5977
- group.model.openPanel(group.panels[group.panels.length - 1], {
5978
- skipSetGroupActive: true,
5979
- });
6080
+ }
6081
+ catch (err) {
6082
+ /**
6083
+ * Takes all the successfully created groups and remove all of their panels.
6084
+ */
6085
+ for (const group of this.groups) {
6086
+ for (const panel of group.panels) {
6087
+ this.removePanel(panel, {
6088
+ removeEmptyGroup: false,
6089
+ skipDispose: false,
6090
+ });
6091
+ }
5980
6092
  }
5981
- return group;
5982
- };
5983
- this.gridview.deserialize(grid, {
5984
- fromJSON: (node) => {
5985
- return createGroupFromSerializedState(node.data);
5986
- },
5987
- });
5988
- this.layout(width, height, true);
5989
- const serializedFloatingGroups = (_a = data.floatingGroups) !== null && _a !== void 0 ? _a : [];
5990
- for (const serializedFloatingGroup of serializedFloatingGroups) {
5991
- const { data, position } = serializedFloatingGroup;
5992
- const group = createGroupFromSerializedState(data);
5993
- this.addFloatingGroup(group, {
5994
- x: position.left,
5995
- y: position.top,
5996
- height: position.height,
5997
- width: position.width,
5998
- }, { skipRemoveGroup: true, inDragMode: false });
5999
- }
6000
- for (const floatingGroup of this.floatingGroups) {
6001
- floatingGroup.overlay.setBounds();
6002
- }
6003
- if (typeof activeGroup === 'string') {
6004
- const panel = this.getPanel(activeGroup);
6005
- if (panel) {
6006
- this.doSetGroupActive(panel);
6093
+ /**
6094
+ * To remove a group we cannot call this.removeGroup(...) since this makes assumptions about
6095
+ * the underlying HTMLElement existing in the Gridview.
6096
+ */
6097
+ for (const group of this.groups) {
6098
+ group.dispose();
6099
+ this._groups.delete(group.id);
6100
+ this._onDidRemoveGroup.fire(group);
6007
6101
  }
6102
+ // iterate over a reassigned array since original array will be modified
6103
+ for (const floatingGroup of [...this.floatingGroups]) {
6104
+ floatingGroup.dispose();
6105
+ }
6106
+ // fires clean-up events and clears the underlying HTML gridview.
6107
+ this.clear();
6108
+ /**
6109
+ * even though we have cleaned-up we still want to inform the caller of their error
6110
+ * and we'll do this through re-throwing the original error since afterall you would
6111
+ * expect trying to load a corrupted layout to result in an error and not silently fail...
6112
+ */
6113
+ throw err;
6008
6114
  }
6009
6115
  this._onDidLayoutFromJSON.fire();
6010
6116
  }
@@ -6218,6 +6324,7 @@
6218
6324
  if (!(options === null || options === void 0 ? void 0 : options.skipDispose)) {
6219
6325
  floatingGroup.group.dispose();
6220
6326
  this._groups.delete(group.id);
6327
+ // TODO: fire group removed event?
6221
6328
  }
6222
6329
  floatingGroup.dispose();
6223
6330
  return floatingGroup.group;
@@ -6458,43 +6565,64 @@
6458
6565
  fromJSON(serializedGridview) {
6459
6566
  this.clear();
6460
6567
  const { grid, activePanel } = serializedGridview;
6461
- const queue = [];
6462
- // take note of the existing dimensions
6463
- const width = this.width;
6464
- const height = this.height;
6465
- this.gridview.deserialize(grid, {
6466
- fromJSON: (node) => {
6467
- const { data } = node;
6468
- const view = createComponent(data.id, data.component, this.options.components || {}, this.options.frameworkComponents || {}, this.options.frameworkComponentFactory
6469
- ? {
6470
- createComponent: this.options.frameworkComponentFactory
6471
- .createComponent,
6472
- }
6473
- : undefined);
6474
- queue.push(() => view.init({
6475
- params: data.params,
6476
- minimumWidth: data.minimumWidth,
6477
- maximumWidth: data.maximumWidth,
6478
- minimumHeight: data.minimumHeight,
6479
- maximumHeight: data.maximumHeight,
6480
- priority: data.priority,
6481
- snap: !!data.snap,
6482
- accessor: this,
6483
- isVisible: node.visible,
6484
- }));
6485
- this._onDidAddGroup.fire(view);
6486
- this.registerPanel(view);
6487
- return view;
6488
- },
6489
- });
6490
- this.layout(width, height, true);
6491
- queue.forEach((f) => f());
6492
- if (typeof activePanel === 'string') {
6493
- const panel = this.getPanel(activePanel);
6494
- if (panel) {
6495
- this.doSetGroupActive(panel);
6568
+ try {
6569
+ const queue = [];
6570
+ // take note of the existing dimensions
6571
+ const width = this.width;
6572
+ const height = this.height;
6573
+ this.gridview.deserialize(grid, {
6574
+ fromJSON: (node) => {
6575
+ const { data } = node;
6576
+ const view = createComponent(data.id, data.component, this.options.components || {}, this.options.frameworkComponents || {}, this.options.frameworkComponentFactory
6577
+ ? {
6578
+ createComponent: this.options.frameworkComponentFactory
6579
+ .createComponent,
6580
+ }
6581
+ : undefined);
6582
+ queue.push(() => view.init({
6583
+ params: data.params,
6584
+ minimumWidth: data.minimumWidth,
6585
+ maximumWidth: data.maximumWidth,
6586
+ minimumHeight: data.minimumHeight,
6587
+ maximumHeight: data.maximumHeight,
6588
+ priority: data.priority,
6589
+ snap: !!data.snap,
6590
+ accessor: this,
6591
+ isVisible: node.visible,
6592
+ }));
6593
+ this._onDidAddGroup.fire(view);
6594
+ this.registerPanel(view);
6595
+ return view;
6596
+ },
6597
+ });
6598
+ this.layout(width, height, true);
6599
+ queue.forEach((f) => f());
6600
+ if (typeof activePanel === 'string') {
6601
+ const panel = this.getPanel(activePanel);
6602
+ if (panel) {
6603
+ this.doSetGroupActive(panel);
6604
+ }
6496
6605
  }
6497
6606
  }
6607
+ catch (err) {
6608
+ /**
6609
+ * To remove a group we cannot call this.removeGroup(...) since this makes assumptions about
6610
+ * the underlying HTMLElement existing in the Gridview.
6611
+ */
6612
+ for (const group of this.groups) {
6613
+ group.dispose();
6614
+ this._groups.delete(group.id);
6615
+ this._onDidRemoveGroup.fire(group);
6616
+ }
6617
+ // fires clean-up events and clears the underlying HTML gridview.
6618
+ this.clear();
6619
+ /**
6620
+ * even though we have cleaned-up we still want to inform the caller of their error
6621
+ * and we'll do this through re-throwing the original error since afterall you would
6622
+ * expect trying to load a corrupted layout to result in an error and not silently fail...
6623
+ */
6624
+ throw err;
6625
+ }
6498
6626
  this._onDidLayoutfromJSON.fire();
6499
6627
  }
6500
6628
  clear() {
@@ -7678,6 +7806,7 @@
7678
7806
  showDndOverlay: props.showDndOverlay,
7679
7807
  createLeftHeaderActionsElement: createGroupControlElement(props.leftHeaderActionsComponent, { addPortal }),
7680
7808
  createRightHeaderActionsElement: createGroupControlElement(props.rightHeaderActionsComponent, { addPortal }),
7809
+ createPrefixHeaderActionsElement: createGroupControlElement(props.prefixHeaderActionsComponent, { addPortal }),
7681
7810
  singleTabMode: props.singleTabMode,
7682
7811
  disableFloatingGroups: props.disableFloatingGroups,
7683
7812
  floatingGroupBounds: props.floatingGroupBounds,
@@ -7787,6 +7916,14 @@
7787
7916
  createLeftHeaderActionsElement: createGroupControlElement(props.leftHeaderActionsComponent, { addPortal }),
7788
7917
  });
7789
7918
  }, [props.leftHeaderActionsComponent]);
7919
+ React__namespace.useEffect(() => {
7920
+ if (!dockviewRef.current) {
7921
+ return;
7922
+ }
7923
+ dockviewRef.current.updateOptions({
7924
+ createPrefixHeaderActionsElement: createGroupControlElement(props.prefixHeaderActionsComponent, { addPortal }),
7925
+ });
7926
+ }, [props.prefixHeaderActionsComponent]);
7790
7927
  return (React__namespace.createElement("div", { className: props.className, style: { height: '100%', width: '100%' }, ref: domRef }, portals));
7791
7928
  });
7792
7929
  DockviewReact.displayName = 'DockviewComponent';