dockview-core 6.6.1 → 7.0.3

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 (203) hide show
  1. package/README.md +8 -1
  2. package/dist/cjs/api/component.api.d.ts +42 -21
  3. package/dist/cjs/api/component.api.js +111 -20
  4. package/dist/cjs/api/dockviewGroupPanelApi.d.ts +23 -8
  5. package/dist/cjs/api/dockviewGroupPanelApi.js +24 -1
  6. package/dist/cjs/api/dockviewPanelApi.d.ts +4 -3
  7. package/dist/cjs/api/dockviewPanelApi.js +8 -0
  8. package/dist/cjs/dnd/dropTargetAnchorContainer.js +1 -2
  9. package/dist/cjs/dnd/droptarget.d.ts +8 -0
  10. package/dist/cjs/dnd/droptarget.js +28 -0
  11. package/dist/cjs/dnd/pointer/longPress.js +1 -1
  12. package/dist/cjs/dnd/pointer/pointerDragController.js +9 -7
  13. package/dist/cjs/dnd/pointer/pointerDragSource.js +4 -2
  14. package/dist/cjs/dockview/accessibilityMessages.d.ts +32 -0
  15. package/dist/cjs/dockview/accessibilityMessages.js +51 -0
  16. package/dist/cjs/dockview/allModules.d.ts +8 -0
  17. package/dist/cjs/dockview/allModules.js +25 -0
  18. package/dist/cjs/dockview/components/panel/content.d.ts +2 -0
  19. package/dist/cjs/dockview/components/panel/content.js +41 -10
  20. package/dist/cjs/dockview/components/popupService.js +1 -1
  21. package/dist/cjs/dockview/components/tab/tab.js +35 -7
  22. package/dist/cjs/dockview/components/titlebar/floatingTitleBar.d.ts +34 -0
  23. package/dist/cjs/dockview/components/titlebar/floatingTitleBar.js +95 -0
  24. package/dist/cjs/dockview/components/titlebar/groupDragSource.d.ts +51 -0
  25. package/dist/cjs/dockview/components/titlebar/groupDragSource.js +218 -0
  26. package/dist/cjs/dockview/components/titlebar/tabGroupIndicator.d.ts +2 -1
  27. package/dist/cjs/dockview/components/titlebar/tabGroupIndicator.js +36 -30
  28. package/dist/cjs/dockview/components/titlebar/tabGroups.d.ts +27 -5
  29. package/dist/cjs/dockview/components/titlebar/tabGroups.js +104 -53
  30. package/dist/cjs/dockview/components/titlebar/tabs.d.ts +12 -0
  31. package/dist/cjs/dockview/components/titlebar/tabs.js +121 -25
  32. package/dist/cjs/dockview/components/titlebar/tabsContainer.d.ts +4 -0
  33. package/dist/cjs/dockview/components/titlebar/tabsContainer.js +13 -3
  34. package/dist/cjs/dockview/components/titlebar/voidContainer.d.ts +1 -4
  35. package/dist/cjs/dockview/components/titlebar/voidContainer.js +32 -156
  36. package/dist/cjs/dockview/dndCapabilities.js +3 -3
  37. package/dist/cjs/dockview/dockviewComponent.d.ts +304 -49
  38. package/dist/cjs/dockview/dockviewComponent.js +1839 -1075
  39. package/dist/cjs/dockview/dockviewFloatingGroupPanel.d.ts +33 -2
  40. package/dist/cjs/dockview/dockviewFloatingGroupPanel.js +39 -3
  41. package/dist/cjs/dockview/dockviewGroupPanel.d.ts +1 -2
  42. package/dist/cjs/dockview/dockviewGroupPanelModel.d.ts +36 -14
  43. package/dist/cjs/dockview/dockviewGroupPanelModel.js +151 -125
  44. package/dist/cjs/dockview/dockviewPanel.d.ts +2 -2
  45. package/dist/cjs/dockview/dockviewPanel.js +4 -5
  46. package/dist/cjs/dockview/dockviewShell.d.ts +29 -7
  47. package/dist/cjs/dockview/dockviewShell.js +94 -36
  48. package/dist/cjs/dockview/edgeGroupService.d.ts +38 -0
  49. package/dist/cjs/dockview/edgeGroupService.js +128 -0
  50. package/dist/cjs/dockview/floatingGroupService.d.ts +37 -0
  51. package/dist/cjs/dockview/floatingGroupService.js +231 -0
  52. package/dist/cjs/dockview/headerActionsService.d.ts +32 -0
  53. package/dist/cjs/dockview/headerActionsService.js +149 -0
  54. package/dist/cjs/dockview/liveRegionService.d.ts +53 -0
  55. package/dist/cjs/dockview/liveRegionService.js +185 -0
  56. package/dist/cjs/dockview/moduleContracts.d.ts +119 -0
  57. package/dist/cjs/dockview/moduleContracts.js +2 -0
  58. package/dist/cjs/dockview/modules.d.ts +110 -0
  59. package/dist/cjs/dockview/modules.js +304 -0
  60. package/dist/cjs/dockview/options.d.ts +159 -6
  61. package/dist/cjs/dockview/options.js +8 -1
  62. package/dist/cjs/dockview/popoutWindowService.d.ts +95 -0
  63. package/dist/cjs/dockview/popoutWindowService.js +261 -0
  64. package/dist/cjs/dockview/rootDropTargetService.d.ts +35 -0
  65. package/dist/cjs/dockview/rootDropTargetService.js +87 -0
  66. package/dist/cjs/dockview/strictEventsSequencing.js +6 -6
  67. package/dist/cjs/dockview/tabGroup.js +3 -3
  68. package/dist/cjs/dockview/tabGroupAccent.js +1 -3
  69. package/dist/cjs/dockview/watermarkService.d.ts +30 -0
  70. package/dist/cjs/dockview/watermarkService.js +61 -0
  71. package/dist/cjs/dom.js +1 -1
  72. package/dist/cjs/events.js +1 -1
  73. package/dist/cjs/gridview/baseComponentGridview.d.ts +1 -1
  74. package/dist/cjs/gridview/baseComponentGridview.js +6 -10
  75. package/dist/cjs/gridview/branchNode.js +13 -17
  76. package/dist/cjs/gridview/gridview.js +8 -8
  77. package/dist/cjs/gridview/gridviewComponent.d.ts +3 -3
  78. package/dist/cjs/gridview/gridviewComponent.js +1 -6
  79. package/dist/cjs/gridview/gridviewPanel.d.ts +1 -1
  80. package/dist/cjs/index.d.ts +11 -4
  81. package/dist/cjs/index.js +14 -1
  82. package/dist/cjs/overlay/overlay.d.ts +43 -1
  83. package/dist/cjs/overlay/overlay.js +82 -36
  84. package/dist/cjs/overlay/overlayRenderContainer.js +3 -4
  85. package/dist/cjs/paneview/draggablePaneviewPanel.d.ts +2 -2
  86. package/dist/cjs/paneview/draggablePaneviewPanel.js +5 -5
  87. package/dist/cjs/paneview/paneviewComponent.d.ts +3 -3
  88. package/dist/cjs/paneview/paneviewComponent.js +7 -11
  89. package/dist/cjs/popoutWindow.js +4 -4
  90. package/dist/cjs/scrollbar.d.ts +1 -1
  91. package/dist/cjs/scrollbar.js +7 -6
  92. package/dist/cjs/splitview/splitview.d.ts +1 -1
  93. package/dist/cjs/splitview/splitview.js +21 -20
  94. package/dist/cjs/splitview/viewItem.js +1 -1
  95. package/dist/dockview-core.js +3548 -1544
  96. package/dist/dockview-core.min.js +2 -2
  97. package/dist/dockview-core.min.js.map +1 -1
  98. package/dist/dockview-core.min.noStyle.js +2 -2
  99. package/dist/dockview-core.min.noStyle.js.map +1 -1
  100. package/dist/dockview-core.noStyle.js +3547 -1543
  101. package/dist/esm/api/component.api.d.ts +42 -21
  102. package/dist/esm/api/component.api.js +63 -18
  103. package/dist/esm/api/dockviewGroupPanelApi.d.ts +23 -8
  104. package/dist/esm/api/dockviewGroupPanelApi.js +20 -1
  105. package/dist/esm/api/dockviewPanelApi.d.ts +4 -3
  106. package/dist/esm/api/dockviewPanelApi.js +7 -0
  107. package/dist/esm/dnd/dropTargetAnchorContainer.js +1 -2
  108. package/dist/esm/dnd/droptarget.d.ts +8 -0
  109. package/dist/esm/dnd/droptarget.js +28 -0
  110. package/dist/esm/dnd/pointer/longPress.js +1 -1
  111. package/dist/esm/dnd/pointer/pointerDragController.js +9 -7
  112. package/dist/esm/dnd/pointer/pointerDragSource.js +4 -2
  113. package/dist/esm/dockview/accessibilityMessages.d.ts +32 -0
  114. package/dist/esm/dockview/accessibilityMessages.js +30 -0
  115. package/dist/esm/dockview/allModules.d.ts +8 -0
  116. package/dist/esm/dockview/allModules.js +22 -0
  117. package/dist/esm/dockview/components/panel/content.d.ts +2 -0
  118. package/dist/esm/dockview/components/panel/content.js +42 -11
  119. package/dist/esm/dockview/components/popupService.js +1 -1
  120. package/dist/esm/dockview/components/tab/tab.js +35 -7
  121. package/dist/esm/dockview/components/titlebar/floatingTitleBar.d.ts +34 -0
  122. package/dist/esm/dockview/components/titlebar/floatingTitleBar.js +65 -0
  123. package/dist/esm/dockview/components/titlebar/groupDragSource.d.ts +51 -0
  124. package/dist/esm/dockview/components/titlebar/groupDragSource.js +178 -0
  125. package/dist/esm/dockview/components/titlebar/tabGroupIndicator.d.ts +2 -1
  126. package/dist/esm/dockview/components/titlebar/tabGroupIndicator.js +36 -30
  127. package/dist/esm/dockview/components/titlebar/tabGroups.d.ts +27 -5
  128. package/dist/esm/dockview/components/titlebar/tabGroups.js +91 -41
  129. package/dist/esm/dockview/components/titlebar/tabs.d.ts +12 -0
  130. package/dist/esm/dockview/components/titlebar/tabs.js +119 -26
  131. package/dist/esm/dockview/components/titlebar/tabsContainer.d.ts +4 -0
  132. package/dist/esm/dockview/components/titlebar/tabsContainer.js +8 -2
  133. package/dist/esm/dockview/components/titlebar/voidContainer.d.ts +1 -4
  134. package/dist/esm/dockview/components/titlebar/voidContainer.js +34 -146
  135. package/dist/esm/dockview/dndCapabilities.js +3 -3
  136. package/dist/esm/dockview/dockviewComponent.d.ts +304 -49
  137. package/dist/esm/dockview/dockviewComponent.js +1459 -772
  138. package/dist/esm/dockview/dockviewFloatingGroupPanel.d.ts +33 -2
  139. package/dist/esm/dockview/dockviewFloatingGroupPanel.js +35 -3
  140. package/dist/esm/dockview/dockviewGroupPanel.d.ts +1 -2
  141. package/dist/esm/dockview/dockviewGroupPanelModel.d.ts +36 -14
  142. package/dist/esm/dockview/dockviewGroupPanelModel.js +127 -117
  143. package/dist/esm/dockview/dockviewPanel.d.ts +2 -2
  144. package/dist/esm/dockview/dockviewPanel.js +1 -2
  145. package/dist/esm/dockview/dockviewShell.d.ts +29 -7
  146. package/dist/esm/dockview/dockviewShell.js +89 -37
  147. package/dist/esm/dockview/edgeGroupService.d.ts +38 -0
  148. package/dist/esm/dockview/edgeGroupService.js +63 -0
  149. package/dist/esm/dockview/floatingGroupService.d.ts +37 -0
  150. package/dist/esm/dockview/floatingGroupService.js +150 -0
  151. package/dist/esm/dockview/headerActionsService.d.ts +32 -0
  152. package/dist/esm/dockview/headerActionsService.js +86 -0
  153. package/dist/esm/dockview/liveRegionService.d.ts +53 -0
  154. package/dist/esm/dockview/liveRegionService.js +159 -0
  155. package/dist/esm/dockview/moduleContracts.d.ts +119 -0
  156. package/dist/esm/dockview/moduleContracts.js +1 -0
  157. package/dist/esm/dockview/modules.d.ts +110 -0
  158. package/dist/esm/dockview/modules.js +170 -0
  159. package/dist/esm/dockview/options.d.ts +159 -6
  160. package/dist/esm/dockview/options.js +8 -1
  161. package/dist/esm/dockview/popoutWindowService.d.ts +95 -0
  162. package/dist/esm/dockview/popoutWindowService.js +175 -0
  163. package/dist/esm/dockview/rootDropTargetService.d.ts +35 -0
  164. package/dist/esm/dockview/rootDropTargetService.js +82 -0
  165. package/dist/esm/dockview/strictEventsSequencing.js +6 -6
  166. package/dist/esm/dockview/tabGroup.js +3 -3
  167. package/dist/esm/dockview/tabGroupAccent.js +1 -3
  168. package/dist/esm/dockview/watermarkService.d.ts +30 -0
  169. package/dist/esm/dockview/watermarkService.js +56 -0
  170. package/dist/esm/dom.js +1 -1
  171. package/dist/esm/events.js +1 -1
  172. package/dist/esm/gridview/baseComponentGridview.d.ts +1 -1
  173. package/dist/esm/gridview/baseComponentGridview.js +5 -10
  174. package/dist/esm/gridview/branchNode.js +13 -15
  175. package/dist/esm/gridview/gridview.js +8 -8
  176. package/dist/esm/gridview/gridviewComponent.d.ts +3 -3
  177. package/dist/esm/gridview/gridviewComponent.js +1 -6
  178. package/dist/esm/gridview/gridviewPanel.d.ts +1 -1
  179. package/dist/esm/index.d.ts +11 -4
  180. package/dist/esm/index.js +4 -0
  181. package/dist/esm/overlay/overlay.d.ts +43 -1
  182. package/dist/esm/overlay/overlay.js +78 -36
  183. package/dist/esm/overlay/overlayRenderContainer.js +3 -4
  184. package/dist/esm/paneview/draggablePaneviewPanel.d.ts +2 -2
  185. package/dist/esm/paneview/draggablePaneviewPanel.js +5 -5
  186. package/dist/esm/paneview/paneviewComponent.d.ts +3 -3
  187. package/dist/esm/paneview/paneviewComponent.js +7 -11
  188. package/dist/esm/popoutWindow.js +4 -4
  189. package/dist/esm/scrollbar.d.ts +1 -1
  190. package/dist/esm/scrollbar.js +7 -6
  191. package/dist/esm/splitview/splitview.d.ts +1 -1
  192. package/dist/esm/splitview/splitview.js +21 -20
  193. package/dist/esm/splitview/viewItem.js +1 -1
  194. package/dist/package/main.cjs.js +3550 -1546
  195. package/dist/package/main.cjs.min.js +2 -2
  196. package/dist/package/main.esm.min.mjs +2 -2
  197. package/dist/package/main.esm.mjs +3538 -1545
  198. package/dist/styles/dockview.css +283 -21
  199. package/package.json +10 -1
  200. package/dist/cjs/dockview/contextMenu.d.ts +0 -10
  201. package/dist/cjs/dockview/contextMenu.js +0 -313
  202. package/dist/esm/dockview/contextMenu.d.ts +0 -10
  203. package/dist/esm/dockview/contextMenu.js +0 -228
@@ -4,8 +4,11 @@ import { IGridView } from '../gridview/gridview';
4
4
  import { IContentRenderer, ITabRenderer, IWatermarkRenderer } from './types';
5
5
  import { Parameters } from '../panel/types';
6
6
  import { DockviewGroupPanel } from './dockviewGroupPanel';
7
+ import { DockviewMessages } from './accessibilityMessages';
8
+ export type { DockviewMessages } from './accessibilityMessages';
7
9
  import { PanelTransfer } from '../dnd/dataTransfer';
8
10
  import { IDisposable } from '../lifecycle';
11
+ import { Box } from '../types';
9
12
  import { DroptargetOverlayModel, Position } from '../dnd/droptarget';
10
13
  import { GroupOptions } from './dockviewGroupPanelModel';
11
14
  import { DockviewGroupDropLocation } from './events';
@@ -13,7 +16,7 @@ import { IDockviewPanel } from './dockviewPanel';
13
16
  import { DockviewPanelRenderer } from '../overlay/overlayRenderContainer';
14
17
  import { IGroupDragGhostRenderer, IGroupHeaderProps, ITabGroupChipRenderer } from './framework';
15
18
  import { FloatingGroupOptions } from './dockviewComponent';
16
- import { Contraints } from '../gridview/gridviewPanel';
19
+ import { Constraints } from '../gridview/gridviewPanel';
17
20
  import { AcceptableEvent, IAcceptableEvent } from '../events';
18
21
  import { DockviewTheme } from './theme';
19
22
  import { ITabGroup } from './tabGroup';
@@ -43,6 +46,54 @@ export interface ContextMenuItemConfig {
43
46
  disabled?: boolean;
44
47
  }
45
48
  export type ContextMenuItem = BuiltInContextMenuItem | ContextMenuItemConfig;
49
+ export interface DropOverlayModelParams {
50
+ /** Which of a group's drop targets the overlay is for. `'edge'` is shaped by `dndEdges`, not this option. */
51
+ location: DockviewGroupDropLocation;
52
+ /** The group the target belongs to, where known (tab / header_space / content). */
53
+ group?: DockviewGroupPanel;
54
+ }
55
+ /** A layout change to be announced — see the `getAnnouncement` option. */
56
+ export interface LiveRegionEvent {
57
+ /**
58
+ * What changed: a panel was added (`'open'`) or removed (`'close'`); a
59
+ * group was maximized (`'maximize'`) / restored (`'restore'`); or a group
60
+ * moved to a floating window (`'float'`), back into the grid (`'dock'`), or
61
+ * out to a popout window (`'popout'`). `panel` is the affected panel — for
62
+ * group events, the group's active panel.
63
+ */
64
+ kind: 'open' | 'close' | 'maximize' | 'restore' | 'float' | 'dock' | 'popout';
65
+ panel: IDockviewPanel;
66
+ }
67
+ /** A resolved announcement handed to a custom `announcer`. */
68
+ export interface AnnouncementEvent {
69
+ /** The (already localised) text to announce. */
70
+ message: string;
71
+ /** `'assertive'` interrupts the screen reader; `'polite'` waits for a pause. */
72
+ politeness: 'polite' | 'assertive';
73
+ }
74
+ /**
75
+ * Key bindings for {@link DockviewComponentOptions.keyboardNavigation}. Each
76
+ * value is a string of `+`-separated parts, modifiers first, e.g. `'ctrl+]'`,
77
+ * `'shift+f6'`. Recognised modifiers: `ctrl`, `shift`, `alt`, `meta` (alias
78
+ * `cmd`). The final part is the `KeyboardEvent.key` to match, case-insensitively
79
+ * (`']'`, `'f6'`, `'arrowleft'`).
80
+ */
81
+ export interface DockviewKeybindings {
82
+ /** Switch to the next tab in the focused group. Default `ctrl+]`. */
83
+ nextTab: string;
84
+ /** Switch to the previous tab in the focused group. Default `ctrl+[`. */
85
+ prevTab: string;
86
+ /** Move focus to the next group. Default `f6`. */
87
+ focusNextGroup: string;
88
+ /** Move focus to the previous group. Default `shift+f6`. */
89
+ focusPrevGroup: string;
90
+ /** Move focus from panel content to the focused group's tab strip. Default `ctrl+shift+\`. */
91
+ focusTabs: string;
92
+ }
93
+ export interface KeyboardNavigationOptions {
94
+ /** Override individual {@link DockviewKeybindings}; unset keys keep their defaults. */
95
+ keymap?: Partial<DockviewKeybindings>;
96
+ }
46
97
  export interface GetTabContextMenuItemsParams {
47
98
  panel: IDockviewPanel;
48
99
  group: DockviewGroupPanel;
@@ -78,6 +129,26 @@ export interface ViewFactoryData {
78
129
  export type DockviewHeaderPosition = 'top' | 'bottom' | 'left' | 'right';
79
130
  export type DockviewHeaderDirection = 'horizontal' | 'vertical';
80
131
  export type DockviewDndStrategy = 'auto' | 'pointer' | 'html5';
132
+ /**
133
+ * Context handed to {@link DockviewOptions.transformFloatingGroupDrag} on each
134
+ * pointer-move frame while a floating group is being dragged.
135
+ */
136
+ export interface FloatingGroupDragContext {
137
+ /** The floating group being dragged. */
138
+ readonly group: DockviewGroupPanel;
139
+ /** Proposed top-left + size this frame, in container pixels (pre-clamp). */
140
+ readonly proposed: Box;
141
+ /** Size of the container the floating group is dragged within. */
142
+ readonly container: {
143
+ width: number;
144
+ height: number;
145
+ };
146
+ /**
147
+ * Bounds of the other floating groups (relative to the same container),
148
+ * snapshotted at drag start.
149
+ */
150
+ readonly others: readonly Box[];
151
+ }
81
152
  export interface DockviewOptions {
82
153
  /**
83
154
  * Disable the auto-resizing which is controlled through a `ResizeObserver`.
@@ -91,16 +162,39 @@ export interface DockviewOptions {
91
162
  minimumHeightWithinViewport?: number;
92
163
  minimumWidthWithinViewport?: number;
93
164
  };
165
+ /**
166
+ * Adjust a floating group's position while it is being dragged. Runs on
167
+ * each pointer-move frame with the proposed top-left (before the container
168
+ * clamp) and returns an adjusted top-left, or nothing to leave it
169
+ * unchanged. Use it for snapping, alignment, or custom bounds. Move only —
170
+ * resizing a floating group is unaffected.
171
+ *
172
+ * `context.others` holds the bounds of the other floating groups (relative
173
+ * to the same container), snapshotted at drag start, so the callback can
174
+ * align the dragged group against its siblings.
175
+ */
176
+ transformFloatingGroupDrag?: (context: FloatingGroupDragContext) => {
177
+ top: number;
178
+ left: number;
179
+ } | void;
180
+ /**
181
+ * Selects which element moves a floating group when dragged.
182
+ *
183
+ * - `'titlebar'` (default): a dedicated, blank drag-handle bar is rendered
184
+ * above the group's tab bar. Dragging it moves the floating window;
185
+ * shift+drag (mouse) / long-press (touch) redocks into the grid. Style
186
+ * it with the `--dv-floating-titlebar-*` theme variables.
187
+ * - `'tabbar'`: the legacy behaviour — the empty space in the tab bar
188
+ * (the "void container") doubles as the move handle. No dedicated bar
189
+ * is rendered.
190
+ */
191
+ floatingGroupDragHandle?: 'titlebar' | 'tabbar';
94
192
  popoutUrl?: string;
95
193
  nonce?: CspNonceProvider;
96
194
  defaultRenderer?: DockviewPanelRenderer;
97
195
  defaultHeaderPosition?: DockviewHeaderPosition;
98
196
  debug?: boolean;
99
197
  dndEdges?: false | DroptargetOverlayModel;
100
- /**
101
- * @deprecated use `dndEdges` instead. To be removed in a future version.
102
- * */
103
- rootOverlayModel?: DroptargetOverlayModel;
104
198
  disableDnd?: boolean;
105
199
  /**
106
200
  * Selects which drag-and-drop implementation is active.
@@ -166,6 +260,65 @@ export interface DockviewOptions {
166
260
  * enabling i18n / custom visuals.
167
261
  */
168
262
  createGroupDragGhostComponent?: (group: DockviewGroupPanel) => IGroupDragGhostRenderer;
263
+ /**
264
+ * Shape the drop overlay shown over a group's drop targets — the tab
265
+ * strip (`'tab'`), the header void space (`'header_space'`) and the
266
+ * panel content area (`'content'`). Return a {@link DroptargetOverlayModel}
267
+ * to override that target's default overlay (size, activation threshold,
268
+ * small-element boundaries), or `undefined` to keep the default.
269
+ *
270
+ * `group` is provided where known (tab / header_space). The outer-layout
271
+ * edge overlay is shaped by `dndEdges`, not this option, so `'edge'` is
272
+ * not dispatched here.
273
+ */
274
+ dropOverlayModel?: (params: DropOverlayModelParams) => DroptargetOverlayModel | undefined;
275
+ /**
276
+ * Built-in screen-reader announcements of layout changes (a visually-hidden
277
+ * `aria-live` region narrating panel open/close etc.). On by default —
278
+ * set to `false` to disable, e.g. when the host app provides its own
279
+ * announcement system. Honoured live via `updateOptions`.
280
+ */
281
+ announcements?: boolean;
282
+ /**
283
+ * Localise or override the built-in announcement strings (the default
284
+ * messages are English). Return a string to use it, `null` / `''` to
285
+ * suppress that announcement, or `undefined` to keep the default. This is
286
+ * how non-English apps translate announcements — core ships no message
287
+ * catalog, only the default strings + this hook.
288
+ */
289
+ getAnnouncement?: (event: LiveRegionEvent) => string | null | undefined;
290
+ /**
291
+ * Route announcements to your own screen-reader infrastructure instead of
292
+ * the built-in `aria-live` regions (e.g. an app-wide live region). When
293
+ * set, dockview hands you each {@link AnnouncementEvent} and writes nothing
294
+ * to its own regions. `getAnnouncement` (localisation) still applies first.
295
+ */
296
+ announcer?: (event: AnnouncementEvent) => void;
297
+ /**
298
+ * Translate / override the strings dockview speaks to assistive technology
299
+ * — both the LiveRegion announcements and the keyboard-docking narration.
300
+ * Provide any subset of {@link DockviewMessages}; unset entries keep the
301
+ * English defaults. (`getAnnouncement` still applies first, per-event, for
302
+ * announcements.)
303
+ */
304
+ messages?: Partial<DockviewMessages>;
305
+ /**
306
+ * Operate the dock with the keyboard. `true` enables the default bindings;
307
+ * pass an object to override individual ones via `keymap`. Off by default
308
+ * (opt-in while the feature matures). Enables:
309
+ *
310
+ * - **Switch tab** within the focused group — `Ctrl`+`]` / `Ctrl`+`[`.
311
+ * - **Move focus between groups** — `F6` / `Shift`+`F6` (sequential) or
312
+ * `Ctrl`+`Shift`+arrow keys (spatial: focus the group in that direction).
313
+ * - **Dock the active panel** without a mouse — `Ctrl`+`M` arms a two-phase
314
+ * move (arrows cycle the target group with a live drop preview +
315
+ * screen-reader narration, `Enter` docks, `Escape` cancels).
316
+ *
317
+ * Defaults avoid `Cmd`-based and browser-reserved combinations (e.g.
318
+ * `Cmd`+`M` is the macOS minimise-window shortcut); use {@link keymap} to
319
+ * rebind for your platform.
320
+ */
321
+ keyboardNavigation?: boolean | KeyboardNavigationOptions;
169
322
  /**
170
323
  * Replace the built-in tab group color palette with a user-defined list.
171
324
  *
@@ -300,7 +453,7 @@ export type AddPanelOptions<P extends object = Parameters> = {
300
453
  inactive?: boolean;
301
454
  initialWidth?: number;
302
455
  initialHeight?: number;
303
- } & Partial<AddPanelOptionsUnion> & Partial<Contraints>;
456
+ } & Partial<AddPanelOptionsUnion> & Partial<Constraints>;
304
457
  type AddGroupOptionsWithPanel = {
305
458
  referencePanel: string | IDockviewPanel;
306
459
  direction?: Omit<Direction, 'within'>;
@@ -20,12 +20,13 @@ export const PROPERTY_KEYS_DOCKVIEW = (() => {
20
20
  singleTabMode: undefined,
21
21
  disableFloatingGroups: undefined,
22
22
  floatingGroupBounds: undefined,
23
+ transformFloatingGroupDrag: undefined,
24
+ floatingGroupDragHandle: undefined,
23
25
  popoutUrl: undefined,
24
26
  nonce: undefined,
25
27
  defaultRenderer: undefined,
26
28
  defaultHeaderPosition: undefined,
27
29
  debug: undefined,
28
- rootOverlayModel: undefined,
29
30
  locked: undefined,
30
31
  disableDnd: undefined,
31
32
  dndStrategy: undefined,
@@ -39,6 +40,12 @@ export const PROPERTY_KEYS_DOCKVIEW = (() => {
39
40
  getTabGroupChipContextMenuItems: undefined,
40
41
  createTabGroupChipComponent: undefined,
41
42
  createGroupDragGhostComponent: undefined,
43
+ dropOverlayModel: undefined,
44
+ announcements: undefined,
45
+ getAnnouncement: undefined,
46
+ announcer: undefined,
47
+ messages: undefined,
48
+ keyboardNavigation: undefined,
42
49
  tabGroupColors: undefined,
43
50
  tabGroupAccent: undefined,
44
51
  };
@@ -0,0 +1,95 @@
1
+ import { IDisposable } from '../lifecycle';
2
+ import { Event } from '../events';
3
+ import { PopupService } from './components/popupService';
4
+ import { PopoutWindow } from '../popoutWindow';
5
+ import { DockviewGroupPanel } from './dockviewGroupPanel';
6
+ import { SerializedPopoutGroup } from './dockviewComponent';
7
+ import { Gridview } from '../gridview/gridview';
8
+ import { OverlayRenderContainer } from '../overlay/overlayRenderContainer';
9
+ import { DropTargetAnchorContainer } from '../dnd/dropTargetAnchorContainer';
10
+ export interface PopoutGroupEntry {
11
+ window: PopoutWindow;
12
+ popoutGroup: DockviewGroupPanel;
13
+ referenceGroup?: string;
14
+ /**
15
+ * The popout window hosts its own gridview so it can hold a nested
16
+ * splitview layout of groups. `popoutGroup` is the window's anchor group.
17
+ */
18
+ gridview: Gridview;
19
+ /**
20
+ * Render / drop-target containers and window accessor for this popout, so
21
+ * groups relocated into the window can be wired to its own document.
22
+ */
23
+ overlayRenderContainer: OverlayRenderContainer;
24
+ dropTargetContainer: DropTargetAnchorContainer;
25
+ getWindow: () => Window;
26
+ popoutUrl?: string;
27
+ disposable: {
28
+ dispose: () => DockviewGroupPanel | undefined;
29
+ };
30
+ }
31
+ /**
32
+ * Narrow callback surface the PopoutWindowService needs from its host.
33
+ */
34
+ export interface IPopoutWindowHost {
35
+ readonly isDisposed: boolean;
36
+ }
37
+ export interface IPopoutWindowService extends IDisposable {
38
+ readonly entries: readonly PopoutGroupEntry[];
39
+ readonly onDidRemove: Event<PopoutGroupEntry>;
40
+ add(entry: PopoutGroupEntry): void;
41
+ remove(entry: PopoutGroupEntry): void;
42
+ findByGroup(group: DockviewGroupPanel): PopoutGroupEntry | undefined;
43
+ findReferenceGroupId(group: DockviewGroupPanel): string | undefined;
44
+ observeGridviewSize(popoutWindow: PopoutWindow, gridview: Gridview, overlayRenderContainer: OverlayRenderContainer): IDisposable | undefined;
45
+ getPopupService(groupId: string): PopupService | undefined;
46
+ setPopupService(groupId: string, service: PopupService): void;
47
+ deletePopupService(groupId: string): void;
48
+ readonly restorationPromise: Promise<void>;
49
+ scheduleRestoration(delayMs: number, work: () => void, onCancel?: () => void): Promise<void>;
50
+ finishRestoration(promises: Promise<void>[]): void;
51
+ cancelPendingRestorations(): void;
52
+ serialize(): SerializedPopoutGroup[];
53
+ disposeAll(): void;
54
+ }
55
+ export declare class PopoutWindowService implements IPopoutWindowService {
56
+ private readonly _host;
57
+ private readonly _entries;
58
+ private readonly _popupServices;
59
+ private readonly _restorationCleanups;
60
+ private _restorationPromise;
61
+ private readonly _onDidRemove;
62
+ readonly onDidRemove: Event<PopoutGroupEntry>;
63
+ constructor(host: IPopoutWindowHost);
64
+ get entries(): readonly PopoutGroupEntry[];
65
+ get restorationPromise(): Promise<void>;
66
+ add(entry: PopoutGroupEntry): void;
67
+ remove(entry: PopoutGroupEntry): void;
68
+ findByGroup(group: DockviewGroupPanel): PopoutGroupEntry | undefined;
69
+ findReferenceGroupId(group: DockviewGroupPanel): string | undefined;
70
+ /**
71
+ * The popout window's innerWidth/innerHeight are often 0/stale until it has
72
+ * painted, and the nested gridview lays its children out to the size passed
73
+ * to layout() (a plain group fills via CSS instead). To stop content
74
+ * rendering into a zero box until a manual resize — and to avoid the race a
75
+ * fixed number of animation frames had — observe the gridview element with
76
+ * a ResizeObserver created in the POPOUT window's OWN realm. A parent-realm
77
+ * observer fires unreliably across the window boundary; a same-realm one
78
+ * fires reliably, including the initial observation once the window is
79
+ * sized.
80
+ *
81
+ * @returns a disposable that disconnects the observer, or `undefined` when
82
+ * the popout realm has no ResizeObserver (e.g. jsdom).
83
+ */
84
+ observeGridviewSize(popoutWindow: PopoutWindow, gridview: Gridview, overlayRenderContainer: OverlayRenderContainer): IDisposable | undefined;
85
+ getPopupService(groupId: string): PopupService | undefined;
86
+ setPopupService(groupId: string, service: PopupService): void;
87
+ deletePopupService(groupId: string): void;
88
+ scheduleRestoration(delayMs: number, work: () => void, onCancel?: () => void): Promise<void>;
89
+ finishRestoration(promises: Promise<void>[]): void;
90
+ cancelPendingRestorations(): void;
91
+ serialize(): SerializedPopoutGroup[];
92
+ disposeAll(): void;
93
+ dispose(): void;
94
+ }
95
+ export declare const PopoutWindowModule: import("./modules").DockviewModule<IPopoutWindowHost>;
@@ -0,0 +1,175 @@
1
+ import { Emitter } from '../events';
2
+ import { remove } from '../array';
3
+ import { defineModule } from './modules';
4
+ export class PopoutWindowService {
5
+ constructor(host) {
6
+ this._entries = [];
7
+ this._popupServices = new Map();
8
+ this._restorationCleanups = new Set();
9
+ this._restorationPromise = Promise.resolve();
10
+ this._onDidRemove = new Emitter();
11
+ this.onDidRemove = this._onDidRemove.event;
12
+ this._host = host;
13
+ }
14
+ get entries() {
15
+ return this._entries;
16
+ }
17
+ get restorationPromise() {
18
+ return this._restorationPromise;
19
+ }
20
+ add(entry) {
21
+ this._entries.push(entry);
22
+ }
23
+ remove(entry) {
24
+ // Fire only on a genuine removal, and not while the host component is
25
+ // tearing down (consumers don't want popout-removed events during
26
+ // dispose).
27
+ if (remove(this._entries, entry) && !this._host.isDisposed) {
28
+ this._onDidRemove.fire(entry);
29
+ }
30
+ }
31
+ findByGroup(group) {
32
+ // A popout window may host several groups in a nested gridview, so
33
+ // match by membership (DOM containment) rather than only the anchor.
34
+ return this._entries.find((entry) => entry.popoutGroup === group ||
35
+ entry.gridview.element.contains(group.element));
36
+ }
37
+ findReferenceGroupId(group) {
38
+ var _a;
39
+ return (_a = this._entries.find((entry) => entry.popoutGroup === group)) === null || _a === void 0 ? void 0 : _a.referenceGroup;
40
+ }
41
+ /**
42
+ * The popout window's innerWidth/innerHeight are often 0/stale until it has
43
+ * painted, and the nested gridview lays its children out to the size passed
44
+ * to layout() (a plain group fills via CSS instead). To stop content
45
+ * rendering into a zero box until a manual resize — and to avoid the race a
46
+ * fixed number of animation frames had — observe the gridview element with
47
+ * a ResizeObserver created in the POPOUT window's OWN realm. A parent-realm
48
+ * observer fires unreliably across the window boundary; a same-realm one
49
+ * fires reliably, including the initial observation once the window is
50
+ * sized.
51
+ *
52
+ * @returns a disposable that disconnects the observer, or `undefined` when
53
+ * the popout realm has no ResizeObserver (e.g. jsdom).
54
+ */
55
+ observeGridviewSize(popoutWindow, gridview, overlayRenderContainer) {
56
+ var _a;
57
+ const PopoutResizeObserver = (_a = popoutWindow.window) === null || _a === void 0 ? void 0 : _a.ResizeObserver;
58
+ if (!PopoutResizeObserver) {
59
+ return undefined;
60
+ }
61
+ let lastWidth = -1;
62
+ let lastHeight = -1;
63
+ const relayout = () => {
64
+ const win = popoutWindow.window;
65
+ if (this._host.isDisposed || !win || win.closed) {
66
+ return;
67
+ }
68
+ const width = Math.round(gridview.element.clientWidth);
69
+ const height = Math.round(gridview.element.clientHeight);
70
+ if (width === lastWidth && height === lastHeight) {
71
+ return;
72
+ }
73
+ lastWidth = width;
74
+ lastHeight = height;
75
+ if (width > 0 && height > 0) {
76
+ gridview.layout(width, height);
77
+ }
78
+ overlayRenderContainer.updateAllPositions();
79
+ };
80
+ const observer = new PopoutResizeObserver(() => {
81
+ var _a;
82
+ // Defer out of the observer callback into the popout's own frame to
83
+ // size against the settled layout and to avoid resize-loop warnings.
84
+ const raf = (_a = popoutWindow.window) === null || _a === void 0 ? void 0 : _a.requestAnimationFrame;
85
+ if (raf) {
86
+ raf.call(popoutWindow.window, relayout);
87
+ }
88
+ else {
89
+ relayout();
90
+ }
91
+ });
92
+ observer.observe(gridview.element);
93
+ return { dispose: () => observer.disconnect() };
94
+ }
95
+ getPopupService(groupId) {
96
+ return this._popupServices.get(groupId);
97
+ }
98
+ setPopupService(groupId, service) {
99
+ this._popupServices.set(groupId, service);
100
+ }
101
+ deletePopupService(groupId) {
102
+ this._popupServices.delete(groupId);
103
+ }
104
+ scheduleRestoration(delayMs, work, onCancel) {
105
+ return new Promise((resolve) => {
106
+ const cleanup = () => {
107
+ this._restorationCleanups.delete(cleanup);
108
+ clearTimeout(handle);
109
+ onCancel === null || onCancel === void 0 ? void 0 : onCancel();
110
+ resolve();
111
+ };
112
+ const handle = setTimeout(() => {
113
+ this._restorationCleanups.delete(cleanup);
114
+ // Guard against the component being disposed before this
115
+ // timer fires. Under React StrictMode the component is
116
+ // mounted -> disposed -> remounted, and without this guard
117
+ // the first instance's queued restoration would open a
118
+ // second popout window. See issue #851.
119
+ if (this._host.isDisposed) {
120
+ resolve();
121
+ return;
122
+ }
123
+ work();
124
+ resolve();
125
+ }, delayMs);
126
+ this._restorationCleanups.add(cleanup);
127
+ });
128
+ }
129
+ finishRestoration(promises) {
130
+ this._restorationPromise = Promise.all(promises).then(() => void 0);
131
+ }
132
+ cancelPendingRestorations() {
133
+ for (const cleanup of [...this._restorationCleanups]) {
134
+ cleanup();
135
+ }
136
+ this._restorationCleanups.clear();
137
+ }
138
+ serialize() {
139
+ return this._entries.map((entry) => {
140
+ const grid = entry.gridview.serialize();
141
+ const root = grid.root;
142
+ const url = entry.popoutGroup.api.location.type === 'popout'
143
+ ? entry.popoutGroup.api.location.popoutUrl
144
+ : undefined;
145
+ const base = {
146
+ gridReferenceGroup: entry.referenceGroup,
147
+ position: entry.window.dimensions(),
148
+ url,
149
+ };
150
+ // Single-group window keeps the legacy `data` shape so layouts
151
+ // round-trip byte-stably and older readers keep working.
152
+ if (root.type === 'branch' &&
153
+ root.data.length === 1 &&
154
+ root.data[0].type === 'leaf') {
155
+ return Object.assign(Object.assign({}, base), { data: root.data[0].data });
156
+ }
157
+ return Object.assign(Object.assign({}, base), { grid });
158
+ });
159
+ }
160
+ disposeAll() {
161
+ for (const entry of [...this._entries]) {
162
+ entry.disposable.dispose();
163
+ }
164
+ }
165
+ dispose() {
166
+ this.cancelPendingRestorations();
167
+ this.disposeAll();
168
+ this._onDidRemove.dispose();
169
+ }
170
+ }
171
+ export const PopoutWindowModule = defineModule({
172
+ name: 'PopoutWindow',
173
+ serviceKey: 'popoutWindowService',
174
+ create: (host) => new PopoutWindowService(host),
175
+ });
@@ -0,0 +1,35 @@
1
+ import { IDisposable } from '../lifecycle';
2
+ import { Event } from '../events';
3
+ import { DroptargetEvent, DropTargetTargetModel, Position, WillShowOverlayEvent } from '../dnd/droptarget';
4
+ import { DockviewComponentOptions } from './options';
5
+ export interface IRootDropTargetHost {
6
+ readonly id: string;
7
+ readonly element: HTMLElement;
8
+ readonly options: DockviewComponentOptions;
9
+ isGridEmpty(): boolean;
10
+ rootDropTargetOverrideTarget(): DropTargetTargetModel | undefined;
11
+ /**
12
+ * Build, fire, and return the verdict for an unhandled-drag-over event.
13
+ * Implemented on the component side so the service stays free of
14
+ * circular imports with the event class declared in dockviewComponent.
15
+ */
16
+ dispatchUnhandledDragOver(nativeEvent: DragEvent | PointerEvent, position: Position): boolean;
17
+ }
18
+ export interface IRootDropTargetService extends IDisposable {
19
+ /** Merged stream from both DnD backends. */
20
+ readonly onWillShowOverlay: Event<WillShowOverlayEvent>;
21
+ /** Merged stream from both DnD backends. */
22
+ readonly onDrop: Event<DroptargetEvent>;
23
+ /** Apply changed options (dndEdges). */
24
+ setOptions(options: Partial<DockviewComponentOptions>): void;
25
+ }
26
+ export declare class RootDropTargetService implements IRootDropTargetService {
27
+ private readonly _html5Target;
28
+ private readonly _pointerTarget;
29
+ readonly onWillShowOverlay: Event<WillShowOverlayEvent>;
30
+ readonly onDrop: Event<DroptargetEvent>;
31
+ constructor(host: IRootDropTargetHost);
32
+ setOptions(options: Partial<DockviewComponentOptions>): void;
33
+ dispose(): void;
34
+ }
35
+ export declare const RootDropTargetModule: import("./modules").DockviewModule<IRootDropTargetHost>;
@@ -0,0 +1,82 @@
1
+ import { Event } from '../events';
2
+ import { html5Backend, pointerBackend } from '../dnd/backend';
3
+ import { getPanelData } from '../dnd/dataTransfer';
4
+ import { defineModule } from './modules';
5
+ const DEFAULT_ROOT_OVERLAY_MODEL = {
6
+ activationSize: { type: 'pixels', value: 10 },
7
+ size: { type: 'pixels', value: 20 },
8
+ };
9
+ export class RootDropTargetService {
10
+ constructor(host) {
11
+ const canDisplayOverlay = (event, position) => {
12
+ const data = getPanelData();
13
+ if (data) {
14
+ if (data.viewId !== host.id) {
15
+ return false;
16
+ }
17
+ if (position === 'center') {
18
+ // center drop target only allowed if no panels in primary
19
+ // grid; floating panels are allowed
20
+ return host.isGridEmpty();
21
+ }
22
+ return true;
23
+ }
24
+ if (position === 'center' && !host.isGridEmpty()) {
25
+ // for external events only show the four-corner drag overlays,
26
+ // disable center so external drag events can fall through to
27
+ // the group and panel drop target handlers
28
+ return false;
29
+ }
30
+ return host.dispatchUnhandledDragOver(event, position);
31
+ };
32
+ const overlayModel = typeof host.options.dndEdges === 'object' &&
33
+ host.options.dndEdges !== null
34
+ ? host.options.dndEdges
35
+ : DEFAULT_ROOT_OVERLAY_MODEL;
36
+ this._html5Target = html5Backend.createDropTarget(host.element, {
37
+ className: 'dv-drop-target-edge',
38
+ canDisplayOverlay,
39
+ acceptedTargetZones: ['top', 'bottom', 'left', 'right', 'center'],
40
+ overlayModel,
41
+ getOverrideTarget: () => host.rootDropTargetOverrideTarget(),
42
+ });
43
+ this._pointerTarget = pointerBackend.createDropTarget(host.element, {
44
+ className: 'dv-drop-target-edge',
45
+ canDisplayOverlay,
46
+ acceptedTargetZones: ['top', 'bottom', 'left', 'right', 'center'],
47
+ overlayModel,
48
+ getOverrideTarget: () => host.rootDropTargetOverrideTarget(),
49
+ });
50
+ this.onWillShowOverlay = Event.any(this._html5Target.onWillShowOverlay, this._pointerTarget.onWillShowOverlay);
51
+ this.onDrop = Event.any(this._html5Target.onDrop, this._pointerTarget.onDrop);
52
+ // Apply initial-state options now that the targets exist; setOptions
53
+ // handles dndEdges (disable + overlay model) and late changes.
54
+ this.setOptions(host.options);
55
+ }
56
+ setOptions(options) {
57
+ if ('dndEdges' in options) {
58
+ const disabled = typeof options.dndEdges === 'boolean' &&
59
+ options.dndEdges === false;
60
+ this._html5Target.disabled = disabled;
61
+ this._pointerTarget.disabled = disabled;
62
+ if (typeof options.dndEdges === 'object' &&
63
+ options.dndEdges !== null) {
64
+ this._html5Target.setOverlayModel(options.dndEdges);
65
+ this._pointerTarget.setOverlayModel(options.dndEdges);
66
+ }
67
+ else {
68
+ this._html5Target.setOverlayModel(DEFAULT_ROOT_OVERLAY_MODEL);
69
+ this._pointerTarget.setOverlayModel(DEFAULT_ROOT_OVERLAY_MODEL);
70
+ }
71
+ }
72
+ }
73
+ dispose() {
74
+ this._html5Target.dispose();
75
+ this._pointerTarget.dispose();
76
+ }
77
+ }
78
+ export const RootDropTargetModule = defineModule({
79
+ name: 'RootDropTarget',
80
+ serviceKey: 'rootDropTargetService',
81
+ create: (host) => new RootDropTargetService(host),
82
+ });
@@ -16,11 +16,11 @@ export class StrictEventsSequencing extends CompositeDisposable {
16
16
  panels.add(panel.api.id);
17
17
  }
18
18
  }), this.accessor.onDidRemovePanel((panel) => {
19
- if (!panels.has(panel.api.id)) {
20
- throw new Error(`dockview: Invalid event sequence. [onDidRemovePanel] called for panel ${panel.api.id} but panel does not exists`);
19
+ if (panels.has(panel.api.id)) {
20
+ panels.delete(panel.api.id);
21
21
  }
22
22
  else {
23
- panels.delete(panel.api.id);
23
+ throw new Error(`dockview: Invalid event sequence. [onDidRemovePanel] called for panel ${panel.api.id} but panel does not exists`);
24
24
  }
25
25
  }), this.accessor.onDidAddGroup((group) => {
26
26
  if (groups.has(group.api.id)) {
@@ -30,11 +30,11 @@ export class StrictEventsSequencing extends CompositeDisposable {
30
30
  groups.add(group.api.id);
31
31
  }
32
32
  }), this.accessor.onDidRemoveGroup((group) => {
33
- if (!groups.has(group.api.id)) {
34
- throw new Error(`dockview: Invalid event sequence. [onDidRemoveGroup] called for group ${group.api.id} but group does not exists`);
33
+ if (groups.has(group.api.id)) {
34
+ groups.delete(group.api.id);
35
35
  }
36
36
  else {
37
- groups.delete(group.api.id);
37
+ throw new Error(`dockview: Invalid event sequence. [onDidRemoveGroup] called for group ${group.api.id} but group does not exists`);
38
38
  }
39
39
  }));
40
40
  }