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.
@@ -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
  */
@@ -888,7 +888,17 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
888
888
  size = typeof size === 'number' ? size : item.size;
889
889
  size = clamp(size, item.minimumSize, item.maximumSize);
890
890
  item.size = size;
891
- this.relayout([index]);
891
+ const indexes = range(this.viewItems.length).filter((i) => i !== index);
892
+ const lowPriorityIndexes = [
893
+ ...indexes.filter((i) => this.viewItems[i].priority === exports.LayoutPriority.Low),
894
+ index,
895
+ ];
896
+ const highPriorityIndexes = indexes.filter((i) => this.viewItems[i].priority === exports.LayoutPriority.High);
897
+ /**
898
+ * add this view we are changing to the low-index list since we have determined the size
899
+ * here and don't want it changed
900
+ */
901
+ this.relayout([...lowPriorityIndexes, index], highPriorityIndexes);
892
902
  }
893
903
  addView(view, size = { type: 'distribute' }, index = this.viewItems.length, skipLayout) {
894
904
  const container = document.createElement('div');
@@ -1645,6 +1655,7 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
1645
1655
  orientation: this.orientation,
1646
1656
  descriptor,
1647
1657
  proportionalLayout,
1658
+ styles,
1648
1659
  });
1649
1660
  }
1650
1661
  this.addDisposables(this._onDidChange, this.splitview.onDidSashEnd(() => {
@@ -2156,6 +2167,14 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
2156
2167
  const child = sibling.children[i];
2157
2168
  grandParent.addChild(child, child.size, parentIndex + i);
2158
2169
  }
2170
+ /**
2171
+ * clean down the branch node since we need to dipose of it and
2172
+ * when .dispose() it called on a branch it will dispose of any
2173
+ * views it is holding onto.
2174
+ */
2175
+ while (sibling.children.length > 0) {
2176
+ sibling.removeChild(0);
2177
+ }
2159
2178
  }
2160
2179
  else {
2161
2180
  // otherwise create a new leaf node and add that to the grandparent
@@ -3214,6 +3233,19 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
3214
3233
  this.leftActions = element;
3215
3234
  }
3216
3235
  }
3236
+ setPrefixActionsElement(element) {
3237
+ if (this.preActions === element) {
3238
+ return;
3239
+ }
3240
+ if (this.preActions) {
3241
+ this.preActions.remove();
3242
+ this.preActions = undefined;
3243
+ }
3244
+ if (element) {
3245
+ this.preActionsContainer.appendChild(element);
3246
+ this.preActions = element;
3247
+ }
3248
+ }
3217
3249
  get element() {
3218
3250
  return this._element;
3219
3251
  }
@@ -3254,9 +3286,12 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
3254
3286
  this.rightActionsContainer.className = 'right-actions-container';
3255
3287
  this.leftActionsContainer = document.createElement('div');
3256
3288
  this.leftActionsContainer.className = 'left-actions-container';
3289
+ this.preActionsContainer = document.createElement('div');
3290
+ this.preActionsContainer.className = 'pre-actions-container';
3257
3291
  this.tabContainer = document.createElement('div');
3258
3292
  this.tabContainer.className = 'tabs-container';
3259
3293
  this.voidContainer = new VoidContainer(this.accessor, this.group);
3294
+ this._element.appendChild(this.preActionsContainer);
3260
3295
  this._element.appendChild(this.tabContainer);
3261
3296
  this._element.appendChild(this.leftActionsContainer);
3262
3297
  this._element.appendChild(this.voidContainer.element);
@@ -3546,6 +3581,16 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
3546
3581
  });
3547
3582
  this.tabsContainer.setLeftActionsElement(this._leftHeaderActions.element);
3548
3583
  }
3584
+ if (this.accessor.options.createPrefixHeaderActionsElement) {
3585
+ this._prefixHeaderActions =
3586
+ this.accessor.options.createPrefixHeaderActionsElement(this.groupPanel);
3587
+ this.addDisposables(this._prefixHeaderActions);
3588
+ this._prefixHeaderActions.init({
3589
+ containerApi: new DockviewApi(this.accessor),
3590
+ api: this.groupPanel.api,
3591
+ });
3592
+ this.tabsContainer.setPrefixActionsElement(this._prefixHeaderActions.element);
3593
+ }
3549
3594
  }
3550
3595
  indexOf(panel) {
3551
3596
  return this.tabsContainer.indexOf(panel.id);
@@ -3888,6 +3933,14 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
3888
3933
  */
3889
3934
  return;
3890
3935
  }
3936
+ if (!document.body.contains(this._element)) {
3937
+ /**
3938
+ * since the event is dispatched through requestAnimationFrame there is a small chance
3939
+ * the component is no longer attached to the DOM, if that is the case the dimensions
3940
+ * are mostly likely all zero and meaningless. we should skip this case.
3941
+ */
3942
+ return;
3943
+ }
3891
3944
  const { width, height } = entry.contentRect;
3892
3945
  this.layout(width, height);
3893
3946
  }));
@@ -5916,61 +5969,114 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
5916
5969
  fromJSON(data) {
5917
5970
  var _a;
5918
5971
  this.clear();
5972
+ if (typeof data !== 'object' || data === null) {
5973
+ throw new Error('serialized layout must be a non-null object');
5974
+ }
5919
5975
  const { grid, panels, activeGroup } = data;
5920
5976
  if (grid.root.type !== 'branch' || !Array.isArray(grid.root.data)) {
5921
5977
  throw new Error('root must be of type branch');
5922
5978
  }
5923
- // take note of the existing dimensions
5924
- const width = this.width;
5925
- const height = this.height;
5926
- const createGroupFromSerializedState = (data) => {
5927
- const { id, locked, hideHeader, views, activeView } = data;
5928
- const group = this.createGroup({
5929
- id,
5930
- locked: !!locked,
5931
- hideHeader: !!hideHeader,
5932
- });
5933
- this._onDidAddGroup.fire(group);
5934
- for (const child of views) {
5935
- const panel = this._deserializer.fromJSON(panels[child], group);
5936
- const isActive = typeof activeView === 'string' && activeView === panel.id;
5937
- group.model.openPanel(panel, {
5938
- skipSetPanelActive: !isActive,
5939
- skipSetGroupActive: true,
5979
+ try {
5980
+ // take note of the existing dimensions
5981
+ const width = this.width;
5982
+ const height = this.height;
5983
+ const createGroupFromSerializedState = (data) => {
5984
+ const { id, locked, hideHeader, views, activeView } = data;
5985
+ if (typeof id !== 'string') {
5986
+ throw new Error('group id must be of type string');
5987
+ }
5988
+ const group = this.createGroup({
5989
+ id,
5990
+ locked: !!locked,
5991
+ hideHeader: !!hideHeader,
5940
5992
  });
5993
+ const createdPanels = [];
5994
+ for (const child of views) {
5995
+ /**
5996
+ * Run the deserializer step seperately since this may fail to due corrupted external state.
5997
+ * In running this section first we avoid firing lots of 'add' events in the event of a failure
5998
+ * due to a corruption of input data.
5999
+ */
6000
+ const panel = this._deserializer.fromJSON(panels[child], group);
6001
+ createdPanels.push(panel);
6002
+ }
6003
+ this._onDidAddGroup.fire(group);
6004
+ for (let i = 0; i < views.length; i++) {
6005
+ const panel = createdPanels[i];
6006
+ const isActive = typeof activeView === 'string' &&
6007
+ activeView === panel.id;
6008
+ group.model.openPanel(panel, {
6009
+ skipSetPanelActive: !isActive,
6010
+ skipSetGroupActive: true,
6011
+ });
6012
+ }
6013
+ if (!group.activePanel && group.panels.length > 0) {
6014
+ group.model.openPanel(group.panels[group.panels.length - 1], {
6015
+ skipSetGroupActive: true,
6016
+ });
6017
+ }
6018
+ return group;
6019
+ };
6020
+ this.gridview.deserialize(grid, {
6021
+ fromJSON: (node) => {
6022
+ return createGroupFromSerializedState(node.data);
6023
+ },
6024
+ });
6025
+ this.layout(width, height, true);
6026
+ const serializedFloatingGroups = (_a = data.floatingGroups) !== null && _a !== void 0 ? _a : [];
6027
+ for (const serializedFloatingGroup of serializedFloatingGroups) {
6028
+ const { data, position } = serializedFloatingGroup;
6029
+ const group = createGroupFromSerializedState(data);
6030
+ this.addFloatingGroup(group, {
6031
+ x: position.left,
6032
+ y: position.top,
6033
+ height: position.height,
6034
+ width: position.width,
6035
+ }, { skipRemoveGroup: true, inDragMode: false });
6036
+ }
6037
+ for (const floatingGroup of this.floatingGroups) {
6038
+ floatingGroup.overlay.setBounds();
6039
+ }
6040
+ if (typeof activeGroup === 'string') {
6041
+ const panel = this.getPanel(activeGroup);
6042
+ if (panel) {
6043
+ this.doSetGroupActive(panel);
6044
+ }
5941
6045
  }
5942
- if (!group.activePanel && group.panels.length > 0) {
5943
- group.model.openPanel(group.panels[group.panels.length - 1], {
5944
- skipSetGroupActive: true,
5945
- });
6046
+ }
6047
+ catch (err) {
6048
+ /**
6049
+ * Takes all the successfully created groups and remove all of their panels.
6050
+ */
6051
+ for (const group of this.groups) {
6052
+ for (const panel of group.panels) {
6053
+ this.removePanel(panel, {
6054
+ removeEmptyGroup: false,
6055
+ skipDispose: false,
6056
+ });
6057
+ }
5946
6058
  }
5947
- return group;
5948
- };
5949
- this.gridview.deserialize(grid, {
5950
- fromJSON: (node) => {
5951
- return createGroupFromSerializedState(node.data);
5952
- },
5953
- });
5954
- this.layout(width, height, true);
5955
- const serializedFloatingGroups = (_a = data.floatingGroups) !== null && _a !== void 0 ? _a : [];
5956
- for (const serializedFloatingGroup of serializedFloatingGroups) {
5957
- const { data, position } = serializedFloatingGroup;
5958
- const group = createGroupFromSerializedState(data);
5959
- this.addFloatingGroup(group, {
5960
- x: position.left,
5961
- y: position.top,
5962
- height: position.height,
5963
- width: position.width,
5964
- }, { skipRemoveGroup: true, inDragMode: false });
5965
- }
5966
- for (const floatingGroup of this.floatingGroups) {
5967
- floatingGroup.overlay.setBounds();
5968
- }
5969
- if (typeof activeGroup === 'string') {
5970
- const panel = this.getPanel(activeGroup);
5971
- if (panel) {
5972
- this.doSetGroupActive(panel);
6059
+ /**
6060
+ * To remove a group we cannot call this.removeGroup(...) since this makes assumptions about
6061
+ * the underlying HTMLElement existing in the Gridview.
6062
+ */
6063
+ for (const group of this.groups) {
6064
+ group.dispose();
6065
+ this._groups.delete(group.id);
6066
+ this._onDidRemoveGroup.fire(group);
5973
6067
  }
6068
+ // iterate over a reassigned array since original array will be modified
6069
+ for (const floatingGroup of [...this.floatingGroups]) {
6070
+ floatingGroup.dispose();
6071
+ }
6072
+ // fires clean-up events and clears the underlying HTML gridview.
6073
+ this.clear();
6074
+ /**
6075
+ * even though we have cleaned-up we still want to inform the caller of their error
6076
+ * and we'll do this through re-throwing the original error since afterall you would
6077
+ * expect trying to load a corrupted layout to result in an error and not silently fail...
6078
+ */
6079
+ throw err;
5974
6080
  }
5975
6081
  this._onDidLayoutFromJSON.fire();
5976
6082
  }
@@ -6184,6 +6290,7 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
6184
6290
  if (!(options === null || options === void 0 ? void 0 : options.skipDispose)) {
6185
6291
  floatingGroup.group.dispose();
6186
6292
  this._groups.delete(group.id);
6293
+ // TODO: fire group removed event?
6187
6294
  }
6188
6295
  floatingGroup.dispose();
6189
6296
  return floatingGroup.group;
@@ -6424,43 +6531,64 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
6424
6531
  fromJSON(serializedGridview) {
6425
6532
  this.clear();
6426
6533
  const { grid, activePanel } = serializedGridview;
6427
- const queue = [];
6428
- // take note of the existing dimensions
6429
- const width = this.width;
6430
- const height = this.height;
6431
- this.gridview.deserialize(grid, {
6432
- fromJSON: (node) => {
6433
- const { data } = node;
6434
- const view = createComponent(data.id, data.component, this.options.components || {}, this.options.frameworkComponents || {}, this.options.frameworkComponentFactory
6435
- ? {
6436
- createComponent: this.options.frameworkComponentFactory
6437
- .createComponent,
6438
- }
6439
- : undefined);
6440
- queue.push(() => view.init({
6441
- params: data.params,
6442
- minimumWidth: data.minimumWidth,
6443
- maximumWidth: data.maximumWidth,
6444
- minimumHeight: data.minimumHeight,
6445
- maximumHeight: data.maximumHeight,
6446
- priority: data.priority,
6447
- snap: !!data.snap,
6448
- accessor: this,
6449
- isVisible: node.visible,
6450
- }));
6451
- this._onDidAddGroup.fire(view);
6452
- this.registerPanel(view);
6453
- return view;
6454
- },
6455
- });
6456
- this.layout(width, height, true);
6457
- queue.forEach((f) => f());
6458
- if (typeof activePanel === 'string') {
6459
- const panel = this.getPanel(activePanel);
6460
- if (panel) {
6461
- this.doSetGroupActive(panel);
6534
+ try {
6535
+ const queue = [];
6536
+ // take note of the existing dimensions
6537
+ const width = this.width;
6538
+ const height = this.height;
6539
+ this.gridview.deserialize(grid, {
6540
+ fromJSON: (node) => {
6541
+ const { data } = node;
6542
+ const view = createComponent(data.id, data.component, this.options.components || {}, this.options.frameworkComponents || {}, this.options.frameworkComponentFactory
6543
+ ? {
6544
+ createComponent: this.options.frameworkComponentFactory
6545
+ .createComponent,
6546
+ }
6547
+ : undefined);
6548
+ queue.push(() => view.init({
6549
+ params: data.params,
6550
+ minimumWidth: data.minimumWidth,
6551
+ maximumWidth: data.maximumWidth,
6552
+ minimumHeight: data.minimumHeight,
6553
+ maximumHeight: data.maximumHeight,
6554
+ priority: data.priority,
6555
+ snap: !!data.snap,
6556
+ accessor: this,
6557
+ isVisible: node.visible,
6558
+ }));
6559
+ this._onDidAddGroup.fire(view);
6560
+ this.registerPanel(view);
6561
+ return view;
6562
+ },
6563
+ });
6564
+ this.layout(width, height, true);
6565
+ queue.forEach((f) => f());
6566
+ if (typeof activePanel === 'string') {
6567
+ const panel = this.getPanel(activePanel);
6568
+ if (panel) {
6569
+ this.doSetGroupActive(panel);
6570
+ }
6462
6571
  }
6463
6572
  }
6573
+ catch (err) {
6574
+ /**
6575
+ * To remove a group we cannot call this.removeGroup(...) since this makes assumptions about
6576
+ * the underlying HTMLElement existing in the Gridview.
6577
+ */
6578
+ for (const group of this.groups) {
6579
+ group.dispose();
6580
+ this._groups.delete(group.id);
6581
+ this._onDidRemoveGroup.fire(group);
6582
+ }
6583
+ // fires clean-up events and clears the underlying HTML gridview.
6584
+ this.clear();
6585
+ /**
6586
+ * even though we have cleaned-up we still want to inform the caller of their error
6587
+ * and we'll do this through re-throwing the original error since afterall you would
6588
+ * expect trying to load a corrupted layout to result in an error and not silently fail...
6589
+ */
6590
+ throw err;
6591
+ }
6464
6592
  this._onDidLayoutfromJSON.fire();
6465
6593
  }
6466
6594
  clear() {
@@ -7644,6 +7772,7 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
7644
7772
  showDndOverlay: props.showDndOverlay,
7645
7773
  createLeftHeaderActionsElement: createGroupControlElement(props.leftHeaderActionsComponent, { addPortal }),
7646
7774
  createRightHeaderActionsElement: createGroupControlElement(props.rightHeaderActionsComponent, { addPortal }),
7775
+ createPrefixHeaderActionsElement: createGroupControlElement(props.prefixHeaderActionsComponent, { addPortal }),
7647
7776
  singleTabMode: props.singleTabMode,
7648
7777
  disableFloatingGroups: props.disableFloatingGroups,
7649
7778
  floatingGroupBounds: props.floatingGroupBounds,
@@ -7753,6 +7882,14 @@ define(['exports', 'react', 'react-dom'], (function (exports, React, ReactDOM) {
7753
7882
  createLeftHeaderActionsElement: createGroupControlElement(props.leftHeaderActionsComponent, { addPortal }),
7754
7883
  });
7755
7884
  }, [props.leftHeaderActionsComponent]);
7885
+ React__namespace.useEffect(() => {
7886
+ if (!dockviewRef.current) {
7887
+ return;
7888
+ }
7889
+ dockviewRef.current.updateOptions({
7890
+ createPrefixHeaderActionsElement: createGroupControlElement(props.prefixHeaderActionsComponent, { addPortal }),
7891
+ });
7892
+ }, [props.prefixHeaderActionsComponent]);
7756
7893
  return (React__namespace.createElement("div", { className: props.className, style: { height: '100%', width: '100%' }, ref: domRef }, portals));
7757
7894
  });
7758
7895
  DockviewReact.displayName = 'DockviewComponent';