dockview-react 8.6.1 → 8.6.2

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-react
3
- * @version 8.6.1
3
+ * @version 8.6.2
4
4
  * @link https://github.com/dockview/dockview
5
5
  * @license MIT
6
6
  */
@@ -51,7 +51,7 @@ react_dom = __toESM(react_dom);
51
51
  //#region ../dockview-core/dist/package/main.esm.mjs
52
52
  /**
53
53
  * dockview-core
54
- * @version 8.6.1
54
+ * @version 8.6.2
55
55
  * @link https://github.com/dockview/dockview
56
56
  * @license MIT
57
57
  */
@@ -725,7 +725,7 @@ react_dom = __toESM(react_dom);
725
725
  resizeTimeout = setTimeout(() => {
726
726
  cb();
727
727
  }, DEBOUCE_DELAY);
728
- }));
728
+ }), Disposable.from(() => clearTimeout(resizeTimeout)));
729
729
  }
730
730
  function shiftAbsoluteElementIntoView(element, root, options) {
731
731
  var _options$buffer;
@@ -3953,6 +3953,33 @@ react_dom = __toESM(react_dom);
3953
3953
  return this.component.withOrigin("api", () => this.component.addGroup(options));
3954
3954
  }
3955
3955
  /**
3956
+ * Serialize one group together with the state of every panel it holds.
3957
+ * The result is self-contained and can be rehydrated with
3958
+ * `addGroupFromJSON`, on this instance or another one.
3959
+ */
3960
+ serializeGroup(group) {
3961
+ return this.component.serializeGroup(group);
3962
+ }
3963
+ /**
3964
+ * Rebuild a group from `serializeGroup` output and add it to the live
3965
+ * layout, positioned as for `addGroup`, leaving the rest of the layout
3966
+ * untouched. Throws before changing anything if a panel id is already in
3967
+ * use.
3968
+ */
3969
+ addGroupFromJSON(data, options) {
3970
+ return this.component.withOrigin("api", () => this.component.addGroupFromJSON(data, options));
3971
+ }
3972
+ /**
3973
+ * Add a panel from its `toJSON()` state, placed as `addPanel` places
3974
+ * one: the counterpart to `panel.toJSON()` for a single tab moving
3975
+ * between layouts or instances, as `addGroupFromJSON` is to
3976
+ * `serializeGroup`. Throws before changing anything if the panel id is
3977
+ * already in use.
3978
+ */
3979
+ addPanelFromJSON(state, options) {
3980
+ return this.component.withOrigin("api", () => this.component.addPanelFromJSON(state, options));
3981
+ }
3982
+ /**
3956
3983
  * Close all groups and panels.
3957
3984
  */
3958
3985
  closeAllGroups() {
@@ -6933,6 +6960,7 @@ react_dom = __toESM(react_dom);
6933
6960
  className: void 0,
6934
6961
  noPanelsOverlay: void 0,
6935
6962
  closeEmptyGroups: void 0,
6963
+ groupIdGenerator: void 0,
6936
6964
  dndEdges: void 0,
6937
6965
  dropPositionResolver: void 0,
6938
6966
  dndCompass: void 0,
@@ -10461,6 +10489,15 @@ react_dom = __toESM(react_dom);
10461
10489
  get panel() {
10462
10490
  return this.options.panel;
10463
10491
  }
10492
+ /**
10493
+ * For a drop on a group's tab bar, the tab index the drop landed at:
10494
+ * where a panel added in response belongs (`addPanel`'s `index`, or
10495
+ * `addGroupFromJSON` with `direction: 'within'`). `undefined` for a
10496
+ * drop on a group's content or a layout edge.
10497
+ */
10498
+ get index() {
10499
+ return this.options.index;
10500
+ }
10464
10501
  get group() {
10465
10502
  return this.options.group;
10466
10503
  }
@@ -11396,6 +11433,7 @@ react_dom = __toESM(react_dom);
11396
11433
  nativeEvent: event,
11397
11434
  position,
11398
11435
  panel,
11436
+ index,
11399
11437
  getData: () => getPanelData(),
11400
11438
  kind: getKind(),
11401
11439
  group: this.groupPanel,
@@ -11441,6 +11479,7 @@ react_dom = __toESM(react_dom);
11441
11479
  nativeEvent: event,
11442
11480
  position,
11443
11481
  panel,
11482
+ index,
11444
11483
  getData: () => getPanelData(),
11445
11484
  group: this.groupPanel,
11446
11485
  api: this._api
@@ -15656,6 +15695,8 @@ react_dom = __toESM(react_dom);
15656
15695
  /** A never-firing history-change event, the fallback `onDidChangeHistory`
15657
15696
  * returns when the LayoutHistory module is absent. */
15658
15697
  const NO_LAYOUT_HISTORY_CHANGES = NO_EVENT;
15698
+ /** How many live ids a custom `groupIdGenerator` may return before giving up. */
15699
+ const MAX_GROUP_ID_ATTEMPTS = 100;
15659
15700
  var DockviewComponent = class extends BaseGrid {
15660
15701
  fireDidCreateTabGroup(event) {
15661
15702
  this._onDidCreateTabGroup.fire(event);
@@ -17505,7 +17546,7 @@ react_dom = __toESM(react_dom);
17505
17546
  if (typeof id !== "string") throw new TypeError("dockview: group id must be of type string");
17506
17547
  const group = this.createGroup({
17507
17548
  id,
17508
- locked: !!locked,
17549
+ locked: locked !== null && locked !== void 0 ? locked : false,
17509
17550
  hideHeader: !!hideHeader,
17510
17551
  headerPosition
17511
17552
  });
@@ -17778,6 +17819,32 @@ react_dom = __toESM(react_dom);
17778
17819
  addPanel(options) {
17779
17820
  return this.mutation("add", () => this._doAddPanel(options));
17780
17821
  }
17822
+ /**
17823
+ * Add a panel from its `toJSON()` state, placed as `addPanel` places
17824
+ * one: the counterpart to `panel.toJSON()` for a single tab moving
17825
+ * between layouts or instances, as `addGroupFromJSON` is to
17826
+ * `serializeGroup`. Throws before changing anything if the panel id is
17827
+ * already in use.
17828
+ */
17829
+ addPanelFromJSON(state, options) {
17830
+ if (!state.contentComponent) throw new Error(`dockview: serialized panel ${state.id} has no contentComponent`);
17831
+ return this.mutation("add", () => {
17832
+ const panel = this._doAddPanel(_objectSpread2$1(_objectSpread2$1({}, options), {}, {
17833
+ id: state.id,
17834
+ component: state.contentComponent,
17835
+ tabComponent: state.tabComponent,
17836
+ title: state.title,
17837
+ renderer: state.renderer,
17838
+ params: state.params,
17839
+ minimumWidth: state.minimumWidth,
17840
+ minimumHeight: state.minimumHeight,
17841
+ maximumWidth: state.maximumWidth,
17842
+ maximumHeight: state.maximumHeight
17843
+ }));
17844
+ if (state.pinned) this.setPanelPinned(panel, true);
17845
+ return panel;
17846
+ });
17847
+ }
17781
17848
  _doAddPanel(options) {
17782
17849
  if (this.panels.some((_) => _.id === options.id)) throw new Error(`dockview: panel with id ${options.id} already exists`);
17783
17850
  let referenceGroup;
@@ -17919,6 +17986,152 @@ react_dom = __toESM(react_dom);
17919
17986
  addGroup(options) {
17920
17987
  return this.mutation("add", () => this._doAddGroup(options));
17921
17988
  }
17989
+ /**
17990
+ * Serialize one group and the state of every panel it holds. The result
17991
+ * is self-contained: `addGroupFromJSON` on any dockview instance rebuilds
17992
+ * the group from it, with the same tab order, active tab, panel titles,
17993
+ * parameters and renderers.
17994
+ */
17995
+ serializeGroup(group) {
17996
+ const panels = {};
17997
+ for (const panel of group.panels) panels[panel.id] = panel.toJSON();
17998
+ return {
17999
+ group: group.model.toJSON(),
18000
+ panels
18001
+ };
18002
+ }
18003
+ /**
18004
+ * Rebuild a group from `serializeGroup` output and add it to the live
18005
+ * layout at `options` (as for `addGroup`), without touching the rest of
18006
+ * the layout. This is the counterpart to `fromJSON`, which replaces the
18007
+ * whole layout, for moving one group between layouts or instances.
18008
+ *
18009
+ * With `direction: 'within'` and a reference group or panel, no group is
18010
+ * created: the serialized panels are merged into that group, in their
18011
+ * order, at `index` if given, and the serialized active panel becomes
18012
+ * the group's. The serialized group's own shape (id, locked, header,
18013
+ * tab groups) does not apply then. This is what a drop on a group's
18014
+ * centre or tab bar calls for, and the only form that works against a
18015
+ * floating or edge group, which has no grid neighbours.
18016
+ *
18017
+ * A panel id that is already live throws, as `addPanel` does, before
18018
+ * anything is changed. A group id that is already live is reassigned with
18019
+ * a warning, as `addGroup` does.
18020
+ */
18021
+ addGroupFromJSON(data, options) {
18022
+ this.validateSerializedGroup(data);
18023
+ return this.mutation("add", () => this._doAddGroupFromJSON(data, options));
18024
+ }
18025
+ /**
18026
+ * Refuse an envelope that cannot be applied cleanly, before any mutation
18027
+ * is opened, so a refused call leaves no trace in the layout or its
18028
+ * events.
18029
+ */
18030
+ validateSerializedGroup(data) {
18031
+ const state = data === null || data === void 0 ? void 0 : data.group;
18032
+ if (typeof (state === null || state === void 0 ? void 0 : state.id) !== "string") throw new TypeError("dockview: group id must be of type string");
18033
+ if (!Array.isArray(state.views)) throw new TypeError(`dockview: serialized group ${state.id} has no views`);
18034
+ for (const id of state.views) {
18035
+ var _data$panels;
18036
+ if (!((_data$panels = data.panels) === null || _data$panels === void 0 ? void 0 : _data$panels[id])) throw new Error(`dockview: serialized group ${state.id} is missing panel state for ${id}`);
18037
+ if (this.panels.some((panel) => panel.id === id)) throw new Error(`dockview: panel with id ${id} already exists`);
18038
+ }
18039
+ }
18040
+ _doAddGroupFromJSON(data, options) {
18041
+ var _options$direction;
18042
+ const { id, locked, hideHeader, headerPosition, constraints, activeView, tabGroups } = data.group;
18043
+ if (options && ((_options$direction = options.direction) !== null && _options$direction !== void 0 ? _options$direction : "within") === "within") {
18044
+ const target = this.resolveReferenceGroup(options);
18045
+ if (target) return this.mergeGroupFromJSON(data, target, options);
18046
+ }
18047
+ const groupOptions = {
18048
+ id,
18049
+ locked: locked !== null && locked !== void 0 ? locked : false,
18050
+ hideHeader: !!hideHeader,
18051
+ headerPosition,
18052
+ constraints,
18053
+ initialWidth: options === null || options === void 0 ? void 0 : options.initialWidth,
18054
+ initialHeight: options === null || options === void 0 ? void 0 : options.initialHeight,
18055
+ skipSetActive: true
18056
+ };
18057
+ const group = this.addEmptyGroupAt(groupOptions, options);
18058
+ let panels;
18059
+ try {
18060
+ panels = this.deserializePanels(data, group);
18061
+ } catch (err) {
18062
+ this.doRemoveGroup(group, { skipActive: true });
18063
+ throw err;
18064
+ }
18065
+ for (const panel of panels) group.model.openPanel(panel, {
18066
+ skipSetActive: panel.id !== activeView,
18067
+ skipSetGroupActive: true
18068
+ });
18069
+ if (tabGroups && tabGroups.length > 0) group.model.restoreTabGroups(tabGroups);
18070
+ if (!group.activePanel && group.panels.length > 0) group.model.openPanel(group.panels[group.panels.length - 1], { skipSetGroupActive: true });
18071
+ if (!(options === null || options === void 0 ? void 0 : options.skipSetActive)) this.doSetGroupAndPanelActive(group);
18072
+ return group;
18073
+ }
18074
+ /**
18075
+ * Add an empty group at the placement `options` names, or append it
18076
+ * when they name none.
18077
+ */
18078
+ addEmptyGroupAt(groupOptions, options) {
18079
+ if (options !== void 0 && (isGroupOptionsWithPanel(options) || isGroupOptionsWithGroup(options) || typeof options.direction === "string")) return this._doAddGroup(_objectSpread2$1(_objectSpread2$1({}, options), groupOptions));
18080
+ const group = this.createGroup(groupOptions);
18081
+ this.doAddGroup(group);
18082
+ return group;
18083
+ }
18084
+ /**
18085
+ * Create every panel of a serialized group in `group`, in tab order,
18086
+ * before any is opened, so a corrupt panel state fails before a single
18087
+ * add event has fired (the ordering `fromJSON` uses). On failure the
18088
+ * panels made so far are disposed and the error rethrown.
18089
+ */
18090
+ deserializePanels(data, group) {
18091
+ const panels = [];
18092
+ try {
18093
+ for (const child of data.group.views) panels.push(this._deserializer.fromJSON(data.panels[child], group));
18094
+ } catch (err) {
18095
+ for (const panel of panels) panel.dispose();
18096
+ throw err;
18097
+ }
18098
+ return panels;
18099
+ }
18100
+ /**
18101
+ * The group an `AddGroupOptions` placement names, or `undefined` for an
18102
+ * absolute placement. Throws for a reference that names nothing.
18103
+ */
18104
+ resolveReferenceGroup(options) {
18105
+ if (isGroupOptionsWithPanel(options)) {
18106
+ const referencePanelId = typeof options.referencePanel === "string" ? options.referencePanel : options.referencePanel.id;
18107
+ const referencePanel = this.getGroupPanel(referencePanelId);
18108
+ if (!referencePanel) throw new Error(`dockview: reference panel ${referencePanelId} does not exist`);
18109
+ return referencePanel.group;
18110
+ }
18111
+ if (isGroupOptionsWithGroup(options)) {
18112
+ const referenceId = typeof options.referenceGroup === "string" ? options.referenceGroup : options.referenceGroup.id;
18113
+ const referenceGroup = this.getPanel(referenceId);
18114
+ if (!referenceGroup) throw new Error(`dockview: reference group ${referenceId} does not exist`);
18115
+ return referenceGroup;
18116
+ }
18117
+ }
18118
+ /**
18119
+ * The `direction: 'within'` form of `addGroupFromJSON`: the serialized
18120
+ * panels join `target` rather than a group of their own.
18121
+ */
18122
+ mergeGroupFromJSON(data, target, options) {
18123
+ const { activeView } = data.group;
18124
+ const index = options.index;
18125
+ this.deserializePanels(data, target).forEach((panel, offset) => {
18126
+ target.model.openPanel(panel, {
18127
+ index: index === void 0 ? void 0 : index + offset,
18128
+ skipSetActive: panel.id !== activeView,
18129
+ skipSetGroupActive: true
18130
+ });
18131
+ });
18132
+ if (!options.skipSetActive) this.doSetGroupAndPanelActive(target);
18133
+ return target;
18134
+ }
17922
18135
  _doAddGroup(options) {
17923
18136
  if (options) {
17924
18137
  let referenceGroup;
@@ -18623,10 +18836,26 @@ react_dom = __toESM(react_dom);
18623
18836
  if (group && this.hasMaximizedGroup() && !this.isMaximizedGroup(group)) this.exitMaximizedGroup();
18624
18837
  if (!this._moving && activePanel !== ((_this$_onDidActivePan2 = this._onDidActivePanelChange.value) === null || _this$_onDidActivePan2 === void 0 ? void 0 : _this$_onDidActivePan2.panel)) this.fireActivePanelChange(activePanel);
18625
18838
  }
18839
+ /**
18840
+ * The id for a group created without one: from `groupIdGenerator` when
18841
+ * the option is set, else the sequential counter. An id already in use is
18842
+ * skipped. The counter never repeats, so it can skip any number of live
18843
+ * ids (a restored layout may hold many); a custom generator is given a
18844
+ * bounded number of tries so a broken one cannot hang the call.
18845
+ */
18626
18846
  getNextGroupId() {
18627
- let id = this.nextGroupId.next();
18628
- while (this._groups.has(id)) id = this.nextGroupId.next();
18629
- return id;
18847
+ const generate = this.options.groupIdGenerator;
18848
+ if (!generate) {
18849
+ let id = this.nextGroupId.next();
18850
+ while (this._groups.has(id)) id = this.nextGroupId.next();
18851
+ return id;
18852
+ }
18853
+ for (let attempt = 0; attempt < MAX_GROUP_ID_ATTEMPTS; attempt++) {
18854
+ const id = generate();
18855
+ if (typeof id !== "string" || id.length === 0) throw new TypeError("dockview: groupIdGenerator must return a non-empty string");
18856
+ if (!this._groups.has(id)) return id;
18857
+ }
18858
+ throw new Error(`dockview: groupIdGenerator returned an id already in use ${MAX_GROUP_ID_ATTEMPTS} times in a row`);
18630
18859
  }
18631
18860
  createGroup(options) {
18632
18861
  var _options;
@@ -18636,10 +18865,7 @@ react_dom = __toESM(react_dom);
18636
18865
  console.warn(`dockview: Duplicate group id ${options === null || options === void 0 ? void 0 : options.id}. reassigning group id to avoid errors`);
18637
18866
  id = void 0;
18638
18867
  }
18639
- if (!id) {
18640
- id = this.nextGroupId.next();
18641
- while (this._groups.has(id)) id = this.nextGroupId.next();
18642
- }
18868
+ if (!id) id = this.getNextGroupId();
18643
18869
  const view = new DockviewGroupPanel(this, id, options);
18644
18870
  view.init({
18645
18871
  params: {},