dockview-core 6.3.0 → 6.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (123) hide show
  1. package/README.md +1 -0
  2. package/dist/cjs/dnd/backend.d.ts +70 -0
  3. package/dist/cjs/dnd/backend.js +171 -0
  4. package/dist/cjs/dnd/dropOverlay.d.ts +20 -0
  5. package/dist/cjs/dnd/dropOverlay.js +197 -0
  6. package/dist/cjs/dnd/droptarget.d.ts +20 -6
  7. package/dist/cjs/dnd/droptarget.js +14 -208
  8. package/dist/cjs/dnd/pointer/index.d.ts +11 -0
  9. package/dist/cjs/dnd/pointer/index.js +13 -0
  10. package/dist/cjs/dnd/pointer/longPress.d.ts +32 -0
  11. package/dist/cjs/dnd/pointer/longPress.js +151 -0
  12. package/dist/cjs/dnd/pointer/pointerDragController.d.ts +60 -0
  13. package/dist/cjs/dnd/pointer/pointerDragController.js +241 -0
  14. package/dist/cjs/dnd/pointer/pointerDragSource.d.ts +61 -0
  15. package/dist/cjs/dnd/pointer/pointerDragSource.js +195 -0
  16. package/dist/cjs/dnd/pointer/pointerDropTarget.d.ts +39 -0
  17. package/dist/cjs/dnd/pointer/pointerDropTarget.js +198 -0
  18. package/dist/cjs/dnd/pointer/pointerGhost.d.ts +30 -0
  19. package/dist/cjs/dnd/pointer/pointerGhost.js +44 -0
  20. package/dist/cjs/dnd/pointer/types.d.ts +16 -0
  21. package/dist/cjs/dnd/pointer/types.js +2 -0
  22. package/dist/cjs/dockview/components/panel/content.d.ts +3 -1
  23. package/dist/cjs/dockview/components/panel/content.js +33 -16
  24. package/dist/cjs/dockview/components/popupService.js +34 -0
  25. package/dist/cjs/dockview/components/tab/tab.d.ts +11 -3
  26. package/dist/cjs/dockview/components/tab/tab.js +151 -117
  27. package/dist/cjs/dockview/components/titlebar/tabGroupChip.d.ts +9 -2
  28. package/dist/cjs/dockview/components/titlebar/tabGroupChip.js +15 -6
  29. package/dist/cjs/dockview/components/titlebar/tabGroups.d.ts +33 -5
  30. package/dist/cjs/dockview/components/titlebar/tabGroups.js +231 -40
  31. package/dist/cjs/dockview/components/titlebar/tabs.d.ts +38 -1
  32. package/dist/cjs/dockview/components/titlebar/tabs.js +372 -251
  33. package/dist/cjs/dockview/components/titlebar/tabsContainer.d.ts +5 -3
  34. package/dist/cjs/dockview/components/titlebar/voidContainer.d.ts +6 -2
  35. package/dist/cjs/dockview/components/titlebar/voidContainer.js +189 -27
  36. package/dist/cjs/dockview/contextMenu.js +19 -4
  37. package/dist/cjs/dockview/dndCapabilities.d.ts +19 -0
  38. package/dist/cjs/dockview/dndCapabilities.js +39 -0
  39. package/dist/cjs/dockview/dockviewComponent.d.ts +1 -0
  40. package/dist/cjs/dockview/dockviewComponent.js +54 -33
  41. package/dist/cjs/dockview/dockviewGroupPanelModel.d.ts +9 -5
  42. package/dist/cjs/dockview/dockviewGroupPanelModel.js +25 -11
  43. package/dist/cjs/dockview/events.d.ts +2 -1
  44. package/dist/cjs/dockview/events.js +1 -0
  45. package/dist/cjs/dockview/options.d.ts +18 -3
  46. package/dist/cjs/dockview/options.js +1 -0
  47. package/dist/cjs/dom.js +7 -3
  48. package/dist/cjs/overlay/overlay.d.ts +12 -0
  49. package/dist/cjs/overlay/overlay.js +84 -16
  50. package/dist/cjs/paneview/draggablePaneviewPanel.d.ts +3 -1
  51. package/dist/cjs/paneview/draggablePaneviewPanel.js +27 -26
  52. package/dist/cjs/paneview/options.d.ts +4 -3
  53. package/dist/dockview-core.js +2199 -834
  54. package/dist/dockview-core.min.js +2 -2
  55. package/dist/dockview-core.min.js.map +1 -1
  56. package/dist/dockview-core.min.noStyle.js +2 -2
  57. package/dist/dockview-core.min.noStyle.js.map +1 -1
  58. package/dist/dockview-core.noStyle.js +2202 -837
  59. package/dist/esm/dnd/backend.d.ts +70 -0
  60. package/dist/esm/dnd/backend.js +148 -0
  61. package/dist/esm/dnd/dropOverlay.d.ts +20 -0
  62. package/dist/esm/dnd/dropOverlay.js +192 -0
  63. package/dist/esm/dnd/droptarget.d.ts +20 -6
  64. package/dist/esm/dnd/droptarget.js +16 -210
  65. package/dist/esm/dnd/pointer/index.d.ts +11 -0
  66. package/dist/esm/dnd/pointer/index.js +5 -0
  67. package/dist/esm/dnd/pointer/longPress.d.ts +32 -0
  68. package/dist/esm/dnd/pointer/longPress.js +127 -0
  69. package/dist/esm/dnd/pointer/pointerDragController.d.ts +60 -0
  70. package/dist/esm/dnd/pointer/pointerDragController.js +191 -0
  71. package/dist/esm/dnd/pointer/pointerDragSource.d.ts +61 -0
  72. package/dist/esm/dnd/pointer/pointerDragSource.js +171 -0
  73. package/dist/esm/dnd/pointer/pointerDropTarget.d.ts +39 -0
  74. package/dist/esm/dnd/pointer/pointerDropTarget.js +168 -0
  75. package/dist/esm/dnd/pointer/pointerGhost.d.ts +30 -0
  76. package/dist/esm/dnd/pointer/pointerGhost.js +39 -0
  77. package/dist/esm/dnd/pointer/types.d.ts +16 -0
  78. package/dist/esm/dnd/pointer/types.js +1 -0
  79. package/dist/esm/dockview/components/panel/content.d.ts +3 -1
  80. package/dist/esm/dockview/components/panel/content.js +33 -16
  81. package/dist/esm/dockview/components/popupService.js +34 -0
  82. package/dist/esm/dockview/components/tab/tab.d.ts +11 -3
  83. package/dist/esm/dockview/components/tab/tab.js +139 -114
  84. package/dist/esm/dockview/components/titlebar/tabGroupChip.d.ts +9 -2
  85. package/dist/esm/dockview/components/titlebar/tabGroupChip.js +15 -6
  86. package/dist/esm/dockview/components/titlebar/tabGroups.d.ts +33 -5
  87. package/dist/esm/dockview/components/titlebar/tabGroups.js +177 -12
  88. package/dist/esm/dockview/components/titlebar/tabs.d.ts +38 -1
  89. package/dist/esm/dockview/components/titlebar/tabs.js +348 -227
  90. package/dist/esm/dockview/components/titlebar/tabsContainer.d.ts +5 -3
  91. package/dist/esm/dockview/components/titlebar/voidContainer.d.ts +6 -2
  92. package/dist/esm/dockview/components/titlebar/voidContainer.js +179 -31
  93. package/dist/esm/dockview/contextMenu.js +19 -4
  94. package/dist/esm/dockview/dndCapabilities.d.ts +19 -0
  95. package/dist/esm/dockview/dndCapabilities.js +36 -0
  96. package/dist/esm/dockview/dockviewComponent.d.ts +1 -0
  97. package/dist/esm/dockview/dockviewComponent.js +55 -34
  98. package/dist/esm/dockview/dockviewGroupPanelModel.d.ts +9 -5
  99. package/dist/esm/dockview/dockviewGroupPanelModel.js +24 -11
  100. package/dist/esm/dockview/events.d.ts +2 -1
  101. package/dist/esm/dockview/events.js +1 -0
  102. package/dist/esm/dockview/options.d.ts +18 -3
  103. package/dist/esm/dockview/options.js +1 -0
  104. package/dist/esm/dom.js +7 -3
  105. package/dist/esm/overlay/overlay.d.ts +12 -0
  106. package/dist/esm/overlay/overlay.js +85 -17
  107. package/dist/esm/paneview/draggablePaneviewPanel.d.ts +3 -1
  108. package/dist/esm/paneview/draggablePaneviewPanel.js +26 -20
  109. package/dist/esm/paneview/options.d.ts +4 -3
  110. package/dist/package/main.cjs.js +2202 -837
  111. package/dist/package/main.cjs.min.js +2 -2
  112. package/dist/package/main.esm.min.mjs +2 -2
  113. package/dist/package/main.esm.mjs +2202 -837
  114. package/dist/styles/dockview.css +117 -1
  115. package/package.json +3 -1
  116. package/dist/cjs/dnd/abstractDragHandler.d.ts +0 -14
  117. package/dist/cjs/dnd/abstractDragHandler.js +0 -86
  118. package/dist/cjs/dnd/groupDragHandler.d.ts +0 -12
  119. package/dist/cjs/dnd/groupDragHandler.js +0 -104
  120. package/dist/esm/dnd/abstractDragHandler.d.ts +0 -14
  121. package/dist/esm/dnd/abstractDragHandler.js +0 -63
  122. package/dist/esm/dnd/groupDragHandler.d.ts +0 -12
  123. package/dist/esm/dnd/groupDragHandler.js +0 -81
@@ -0,0 +1,70 @@
1
+ import { IDisposable } from '../lifecycle';
2
+ import { DroptargetOptions, IDropTarget } from './droptarget';
3
+ /**
4
+ * Backend factory surface. Each implementation hides one concrete DnD
5
+ * mechanism (HTML5 native events, pointer events) behind a uniform set of
6
+ * `createX` methods.
7
+ *
8
+ * The backends are stateless — `html5Backend` and `pointerBackend` below
9
+ * are exported as module-level singletons so they need no construction
10
+ * or wiring through the component tree.
11
+ */
12
+ export interface IDragBackend {
13
+ /** Stable identifier, mostly for debugging / tests. */
14
+ readonly kind: 'html5' | 'pointer';
15
+ createDropTarget(element: HTMLElement, options: DroptargetOptions): IDropTarget;
16
+ createDragSource(element: HTMLElement, options: DragSourceOptions): IDragSource;
17
+ }
18
+ /**
19
+ * Visual specification handed to the backend. HTML5 calls `setDragImage`
20
+ * with `(element, offsetX, offsetY)` and discards the element after a
21
+ * microtask. Pointer wraps the element in a `PointerGhost` that follows
22
+ * the cursor for the duration of the drag.
23
+ */
24
+ export interface IDragGhostSpec {
25
+ element: HTMLElement;
26
+ /** Pixels from cursor to ghost's top-left. Default 0. */
27
+ offsetX?: number;
28
+ offsetY?: number;
29
+ /**
30
+ * Called when the backend is done with the ghost. HTML5 fires it after
31
+ * the drag-image snapshot is captured (next tick); pointer fires it
32
+ * when the follow-cursor ghost is removed at drag end. Use for custom
33
+ * framework renderers that need teardown.
34
+ */
35
+ dispose?: () => void;
36
+ }
37
+ export interface DragSourceOptions {
38
+ /** Populate transfer; returned disposer clears it on drag end. */
39
+ getData: (event: DragEvent | PointerEvent) => IDisposable;
40
+ /** Veto a drag at start time. */
41
+ isCancelled?: (event: DragEvent | PointerEvent) => boolean;
42
+ createGhost?: (event: DragEvent | PointerEvent) => IDragGhostSpec | undefined;
43
+ onDragStart?: (event: DragEvent | PointerEvent) => void;
44
+ onDragEnd?: (event: DragEvent | PointerEvent) => void;
45
+ /** Initial disabled state; toggle later via `setDisabled`. */
46
+ disabled?: boolean;
47
+ /**
48
+ * Pointer-only. When true (default), the pointer backend ignores mouse
49
+ * pointers and lets the HTML5 path handle them. HTML5 backend ignores.
50
+ */
51
+ touchOnly?: boolean;
52
+ /**
53
+ * Pointer-only long-press delay in ms. May be a function so the value
54
+ * can vary per gesture (e.g. floating-group redock vs docked rearrange).
55
+ */
56
+ touchInitiationDelay?: number | (() => number);
57
+ /** Pointer-only pre-arm movement tolerance in px. May also be a function. */
58
+ pressTolerance?: number | (() => number);
59
+ /** Pointer-only movement threshold to promote pointerdown → drag. */
60
+ threshold?: number;
61
+ }
62
+ export interface IDragSource extends IDisposable {
63
+ setDisabled(value: boolean): void;
64
+ /** Pointer-only knob; no-op on HTML5 backend. */
65
+ setTouchOnly(value: boolean): void;
66
+ /** Pointer-only; no-op on HTML5 backend. */
67
+ cancelPending(): void;
68
+ }
69
+ export declare const html5Backend: IDragBackend;
70
+ export declare const pointerBackend: IDragBackend;
@@ -0,0 +1,148 @@
1
+ import { addDisposableListener } from '../events';
2
+ import { CompositeDisposable, MutableDisposable, } from '../lifecycle';
3
+ import { Droptarget } from './droptarget';
4
+ import { addGhostImage } from './ghost';
5
+ import { PointerDropTarget } from './pointer/pointerDropTarget';
6
+ import { PointerDragSource } from './pointer/pointerDragSource';
7
+ import { PointerGhost } from './pointer/pointerGhost';
8
+ import { disableIframePointEvents } from '../dom';
9
+ /**
10
+ * HTML5 drag source. Listens for the native `dragstart` event, calls
11
+ * `getData` to populate transfer, optionally renders the ghost via
12
+ * `setDragImage`, fires `onDragStart` / `onDragEnd`, and tears down the
13
+ * transfer disposer after `dragend`.
14
+ */
15
+ class Html5DragSource extends CompositeDisposable {
16
+ constructor(el, opts) {
17
+ super();
18
+ this.el = el;
19
+ this.opts = opts;
20
+ this._dataDisposable = new MutableDisposable();
21
+ this._pointerEventsDisposable = new MutableDisposable();
22
+ this._disabled = !!opts.disabled;
23
+ this.addDisposables(this._dataDisposable, this._pointerEventsDisposable, addDisposableListener(this.el, 'dragstart', (event) => {
24
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j;
25
+ if (event.defaultPrevented ||
26
+ this._disabled ||
27
+ ((_b = (_a = this.opts).isCancelled) === null || _b === void 0 ? void 0 : _b.call(_a, event))) {
28
+ event.preventDefault();
29
+ return;
30
+ }
31
+ // Iframes capture pointermove once the cursor enters them,
32
+ // which freezes drag tracking from the parent window's
33
+ // POV. Shield the source's owning document so popout-window
34
+ // drags shield the popout, not the main window.
35
+ const iframes = disableIframePointEvents((_c = this.el.ownerDocument) !== null && _c !== void 0 ? _c : document);
36
+ this._pointerEventsDisposable.value = {
37
+ dispose: () => iframes.release(),
38
+ };
39
+ this.el.classList.add('dv-dragged');
40
+ setTimeout(() => this.el.classList.remove('dv-dragged'), 0);
41
+ this._dataDisposable.value = this.opts.getData(event);
42
+ const ghost = (_e = (_d = this.opts).createGhost) === null || _e === void 0 ? void 0 : _e.call(_d, event);
43
+ if (ghost && event.dataTransfer) {
44
+ addGhostImage(event.dataTransfer, ghost.element, {
45
+ x: (_f = ghost.offsetX) !== null && _f !== void 0 ? _f : 0,
46
+ y: (_g = ghost.offsetY) !== null && _g !== void 0 ? _g : 0,
47
+ });
48
+ if (ghost.dispose) {
49
+ // addGhostImage removes the element from the DOM on
50
+ // the next tick; dispose the framework renderer on
51
+ // the same schedule.
52
+ const disposeGhost = ghost.dispose;
53
+ setTimeout(() => disposeGhost(), 0);
54
+ }
55
+ }
56
+ if (event.dataTransfer) {
57
+ event.dataTransfer.effectAllowed = 'move';
58
+ // Some third-party DnD libs (e.g. react-dnd) cancel the
59
+ // dragstart when `dataTransfer.types` is empty.
60
+ if (event.dataTransfer.items.length === 0) {
61
+ event.dataTransfer.setData('text/plain', '');
62
+ }
63
+ }
64
+ (_j = (_h = this.opts).onDragStart) === null || _j === void 0 ? void 0 : _j.call(_h, event);
65
+ }), addDisposableListener(this.el, 'dragend', (event) => {
66
+ var _a, _b;
67
+ this._pointerEventsDisposable.dispose();
68
+ // Defer disposal so drop handlers can still read the
69
+ // transfer payload before it clears.
70
+ setTimeout(() => this._dataDisposable.dispose(), 0);
71
+ (_b = (_a = this.opts).onDragEnd) === null || _b === void 0 ? void 0 : _b.call(_a, event);
72
+ }));
73
+ }
74
+ setDisabled(value) {
75
+ this._disabled = value;
76
+ }
77
+ setTouchOnly(_) {
78
+ // No-op — HTML5 path can't filter by pointer type.
79
+ }
80
+ cancelPending() {
81
+ // No-op — HTML5 has no pre-arm phase to cancel.
82
+ }
83
+ }
84
+ class Html5DragBackend {
85
+ constructor() {
86
+ this.kind = 'html5';
87
+ }
88
+ createDropTarget(element, options) {
89
+ return new Droptarget(element, options);
90
+ }
91
+ createDragSource(element, options) {
92
+ return new Html5DragSource(element, options);
93
+ }
94
+ }
95
+ class PointerDragBackend {
96
+ constructor() {
97
+ this.kind = 'pointer';
98
+ }
99
+ createDropTarget(element, options) {
100
+ return new PointerDropTarget(element, options);
101
+ }
102
+ createDragSource(element, options) {
103
+ const pointerCreateGhost = options.createGhost
104
+ ? (event) => {
105
+ const spec = options.createGhost(event);
106
+ if (!spec) {
107
+ return undefined;
108
+ }
109
+ const ghost = new PointerGhost({
110
+ element: spec.element,
111
+ initialX: event.clientX,
112
+ initialY: event.clientY,
113
+ offsetX: spec.offsetX,
114
+ offsetY: spec.offsetY,
115
+ owner: element,
116
+ });
117
+ if (spec.dispose) {
118
+ const baseDispose = ghost.dispose.bind(ghost);
119
+ const disposeSpec = spec.dispose;
120
+ ghost.dispose = () => {
121
+ baseDispose();
122
+ disposeSpec();
123
+ };
124
+ }
125
+ return ghost;
126
+ }
127
+ : undefined;
128
+ const source = new PointerDragSource(element, {
129
+ getData: options.getData,
130
+ isCancelled: options.isCancelled,
131
+ onDragStart: options.onDragStart,
132
+ onDragEnd: options.onDragEnd
133
+ ? (event) => options.onDragEnd(event.pointerEvent)
134
+ : undefined,
135
+ createGhost: pointerCreateGhost,
136
+ touchOnly: options.touchOnly,
137
+ touchInitiationDelay: options.touchInitiationDelay,
138
+ pressTolerance: options.pressTolerance,
139
+ threshold: options.threshold,
140
+ });
141
+ if (options.disabled) {
142
+ source.setDisabled(true);
143
+ }
144
+ return source;
145
+ }
146
+ }
147
+ export const html5Backend = new Html5DragBackend();
148
+ export const pointerBackend = new PointerDragBackend();
@@ -0,0 +1,20 @@
1
+ import { DropTargetTargetModel, DroptargetOverlayModel, Position } from './droptarget';
2
+ export interface OverlayElements {
3
+ dropzone: HTMLElement;
4
+ selection: HTMLElement;
5
+ }
6
+ export declare function createOverlayElements(): OverlayElements;
7
+ export declare function renderInPlaceOverlay(overlay: HTMLElement, quadrant: Position, width: number, height: number, overlayModel?: DroptargetOverlayModel): void;
8
+ /** `boundsChanged: false` lets callers skip redundant work on tight drag loops. */
9
+ export declare function renderAnchoredOverlay(args: {
10
+ outlineElement: HTMLElement;
11
+ targetModel: DropTargetTargetModel;
12
+ quadrant: Position;
13
+ width: number;
14
+ height: number;
15
+ overlayModel?: DroptargetOverlayModel;
16
+ className?: string;
17
+ }): {
18
+ boundsChanged: boolean;
19
+ targetChanged: boolean;
20
+ };
@@ -0,0 +1,192 @@
1
+ // Two render paths: in-place (dropzone appended to drop element) and
2
+ // anchored (overlay rendered into an external anchor container).
3
+ import { toggleClass } from '../dom';
4
+ import { clamp } from '../math';
5
+ const DEFAULT_SIZE = { value: 50, type: 'percentage' };
6
+ const SMALL_WIDTH_BOUNDARY = 100;
7
+ const SMALL_HEIGHT_BOUNDARY = 100;
8
+ export function createOverlayElements() {
9
+ const dropzone = document.createElement('div');
10
+ dropzone.className = 'dv-drop-target-dropzone';
11
+ const selection = document.createElement('div');
12
+ selection.className = 'dv-drop-target-selection';
13
+ dropzone.appendChild(selection);
14
+ return { dropzone, selection };
15
+ }
16
+ function computeOverlayShape(quadrant, width, height, overlayModel) {
17
+ var _a, _b, _c;
18
+ const smallWidthBoundary = (_a = overlayModel === null || overlayModel === void 0 ? void 0 : overlayModel.smallWidthBoundary) !== null && _a !== void 0 ? _a : SMALL_WIDTH_BOUNDARY;
19
+ const smallHeightBoundary = (_b = overlayModel === null || overlayModel === void 0 ? void 0 : overlayModel.smallHeightBoundary) !== null && _b !== void 0 ? _b : SMALL_HEIGHT_BOUNDARY;
20
+ const isSmallX = width < smallWidthBoundary;
21
+ const isSmallY = height < smallHeightBoundary;
22
+ const isLeft = quadrant === 'left';
23
+ const isRight = quadrant === 'right';
24
+ const isTop = quadrant === 'top';
25
+ const isBottom = quadrant === 'bottom';
26
+ const rightClass = !isSmallX && isRight;
27
+ const leftClass = !isSmallX && isLeft;
28
+ const topClass = !isSmallY && isTop;
29
+ const bottomClass = !isSmallY && isBottom;
30
+ let size = 1;
31
+ const sizeOptions = (_c = overlayModel === null || overlayModel === void 0 ? void 0 : overlayModel.size) !== null && _c !== void 0 ? _c : DEFAULT_SIZE;
32
+ if (sizeOptions.type === 'percentage') {
33
+ size = clamp(sizeOptions.value, 0, 100) / 100;
34
+ }
35
+ else {
36
+ if (rightClass || leftClass) {
37
+ size = clamp(0, sizeOptions.value, width) / width;
38
+ }
39
+ if (topClass || bottomClass) {
40
+ size = clamp(0, sizeOptions.value, height) / height;
41
+ }
42
+ }
43
+ return {
44
+ isSmallX,
45
+ isSmallY,
46
+ isLeft,
47
+ isRight,
48
+ isTop,
49
+ isBottom,
50
+ rightClass,
51
+ leftClass,
52
+ topClass,
53
+ bottomClass,
54
+ size,
55
+ };
56
+ }
57
+ export function renderInPlaceOverlay(overlay, quadrant, width, height, overlayModel) {
58
+ const shape = computeOverlayShape(quadrant, width, height, overlayModel);
59
+ const { rightClass, leftClass, topClass, bottomClass, size } = shape;
60
+ const box = { top: '0px', left: '0px', width: '100%', height: '100%' };
61
+ if (rightClass) {
62
+ box.left = `${100 * (1 - size)}%`;
63
+ box.width = `${100 * size}%`;
64
+ }
65
+ else if (leftClass) {
66
+ box.width = `${100 * size}%`;
67
+ }
68
+ else if (topClass) {
69
+ box.height = `${100 * size}%`;
70
+ }
71
+ else if (bottomClass) {
72
+ box.top = `${100 * (1 - size)}%`;
73
+ box.height = `${100 * size}%`;
74
+ }
75
+ if (shape.isSmallX && shape.isLeft) {
76
+ box.width = '4px';
77
+ }
78
+ if (shape.isSmallX && shape.isRight) {
79
+ box.left = `${width - 4}px`;
80
+ box.width = '4px';
81
+ }
82
+ if (shape.isSmallY && shape.isTop) {
83
+ box.height = '4px';
84
+ }
85
+ if (shape.isSmallY && shape.isBottom) {
86
+ box.top = `${height - 4}px`;
87
+ box.height = '4px';
88
+ }
89
+ overlay.style.top = box.top;
90
+ overlay.style.left = box.left;
91
+ overlay.style.width = box.width;
92
+ overlay.style.height = box.height;
93
+ overlay.style.visibility = 'visible';
94
+ if (!overlay.style.transform || overlay.style.transform === '') {
95
+ overlay.style.transform = 'translate3d(0, 0, 0)';
96
+ }
97
+ const isLine = (shape.isSmallX && (shape.isLeft || shape.isRight)) ||
98
+ (shape.isSmallY && (shape.isTop || shape.isBottom));
99
+ toggleClass(overlay, 'dv-drop-target-small-vertical', shape.isSmallY);
100
+ toggleClass(overlay, 'dv-drop-target-small-horizontal', shape.isSmallX);
101
+ toggleClass(overlay, 'dv-drop-target-selection-line', isLine);
102
+ toggleClass(overlay, 'dv-drop-target-left', shape.isLeft);
103
+ toggleClass(overlay, 'dv-drop-target-right', shape.isRight);
104
+ toggleClass(overlay, 'dv-drop-target-top', shape.isTop);
105
+ toggleClass(overlay, 'dv-drop-target-bottom', shape.isBottom);
106
+ toggleClass(overlay, 'dv-drop-target-center', quadrant === 'center');
107
+ }
108
+ function checkAnchoredBoundsChanged(overlay, bounds) {
109
+ const topPx = `${Math.round(bounds.top)}px`;
110
+ const leftPx = `${Math.round(bounds.left)}px`;
111
+ const widthPx = `${Math.round(bounds.width)}px`;
112
+ const heightPx = `${Math.round(bounds.height)}px`;
113
+ return (overlay.style.top !== topPx ||
114
+ overlay.style.left !== leftPx ||
115
+ overlay.style.width !== widthPx ||
116
+ overlay.style.height !== heightPx);
117
+ }
118
+ function applyAnchoredBounds(overlay, bounds) {
119
+ overlay.style.top = `${Math.round(bounds.top)}px`;
120
+ overlay.style.left = `${Math.round(bounds.left)}px`;
121
+ overlay.style.width = `${Math.round(bounds.width)}px`;
122
+ overlay.style.height = `${Math.round(bounds.height)}px`;
123
+ overlay.style.visibility = 'visible';
124
+ if (!overlay.style.transform || overlay.style.transform === '') {
125
+ overlay.style.transform = 'translate3d(0, 0, 0)';
126
+ }
127
+ }
128
+ /** `boundsChanged: false` lets callers skip redundant work on tight drag loops. */
129
+ export function renderAnchoredOverlay(args) {
130
+ const shape = computeOverlayShape(args.quadrant, args.width, args.height, args.overlayModel);
131
+ const { rightClass, leftClass, topClass, bottomClass, size } = shape;
132
+ const elBox = args.outlineElement.getBoundingClientRect();
133
+ const ta = args.targetModel.getElements(undefined, args.outlineElement);
134
+ const el = ta.root;
135
+ const overlay = ta.overlay;
136
+ const bigbox = el.getBoundingClientRect();
137
+ const rootTop = elBox.top - bigbox.top;
138
+ const rootLeft = elBox.left - bigbox.left;
139
+ const box = {
140
+ top: rootTop,
141
+ left: rootLeft,
142
+ width: args.width,
143
+ height: args.height,
144
+ };
145
+ if (rightClass) {
146
+ box.left = rootLeft + args.width * (1 - size);
147
+ box.width = args.width * size;
148
+ }
149
+ else if (leftClass) {
150
+ box.width = args.width * size;
151
+ }
152
+ else if (topClass) {
153
+ box.height = args.height * size;
154
+ }
155
+ else if (bottomClass) {
156
+ box.top = rootTop + args.height * (1 - size);
157
+ box.height = args.height * size;
158
+ }
159
+ if (shape.isSmallX && shape.isLeft) {
160
+ box.width = 4;
161
+ }
162
+ if (shape.isSmallX && shape.isRight) {
163
+ box.left = rootLeft + args.width - 4;
164
+ box.width = 4;
165
+ }
166
+ if (shape.isSmallY && shape.isTop) {
167
+ box.height = 4;
168
+ }
169
+ if (shape.isSmallY && shape.isBottom) {
170
+ box.top = rootTop + args.height - 4;
171
+ box.height = 4;
172
+ }
173
+ if (!checkAnchoredBoundsChanged(overlay, box)) {
174
+ return { boundsChanged: false, targetChanged: ta.changed };
175
+ }
176
+ applyAnchoredBounds(overlay, box);
177
+ overlay.className = `dv-drop-target-anchor${args.className ? ` ${args.className}` : ''}`;
178
+ toggleClass(overlay, 'dv-drop-target-left', shape.isLeft);
179
+ toggleClass(overlay, 'dv-drop-target-right', shape.isRight);
180
+ toggleClass(overlay, 'dv-drop-target-top', shape.isTop);
181
+ toggleClass(overlay, 'dv-drop-target-bottom', shape.isBottom);
182
+ toggleClass(overlay, 'dv-drop-target-anchor-line', (shape.isSmallX && (shape.isLeft || shape.isRight)) ||
183
+ (shape.isSmallY && (shape.isTop || shape.isBottom)));
184
+ toggleClass(overlay, 'dv-drop-target-center', args.quadrant === 'center');
185
+ if (ta.changed) {
186
+ toggleClass(overlay, 'dv-drop-target-anchor-container-changed', true);
187
+ setTimeout(() => {
188
+ toggleClass(overlay, 'dv-drop-target-anchor-container-changed', false);
189
+ }, 10);
190
+ }
191
+ return { boundsChanged: true, targetChanged: ta.changed };
192
+ }
@@ -1,24 +1,25 @@
1
1
  import { DockviewEvent, Event } from '../events';
2
- import { CompositeDisposable } from '../lifecycle';
2
+ import { CompositeDisposable, IDisposable } from '../lifecycle';
3
3
  import { DragAndDropObserver } from './dnd';
4
4
  import { Direction } from '../gridview/baseComponentGridview';
5
5
  export interface DroptargetEvent {
6
6
  readonly position: Position;
7
- readonly nativeEvent: DragEvent;
7
+ /** Narrow with `instanceof DragEvent` before reading `dataTransfer`. */
8
+ readonly nativeEvent: DragEvent | PointerEvent;
8
9
  }
9
10
  export declare class WillShowOverlayEvent extends DockviewEvent implements DroptargetEvent {
10
11
  private readonly options;
11
- get nativeEvent(): DragEvent;
12
+ get nativeEvent(): DragEvent | PointerEvent;
12
13
  get position(): Position;
13
14
  constructor(options: {
14
- nativeEvent: DragEvent;
15
+ nativeEvent: DragEvent | PointerEvent;
15
16
  position: Position;
16
17
  });
17
18
  }
18
19
  export declare function directionToPosition(direction: Direction): Position;
19
20
  export declare function positionToDirection(position: Position): Direction;
20
21
  export type Position = 'top' | 'bottom' | 'left' | 'right' | 'center';
21
- export type CanDisplayOverlay = (dragEvent: DragEvent, state: Position) => boolean;
22
+ export type CanDisplayOverlay = (dragEvent: DragEvent | PointerEvent, state: Position) => boolean;
22
23
  export type MeasuredValue = {
23
24
  value: number;
24
25
  type: 'pixels' | 'percentage';
@@ -56,7 +57,20 @@ export interface DroptargetOptions {
56
57
  className?: string;
57
58
  getOverlayOutline?: () => HTMLElement | null;
58
59
  }
59
- export declare class Droptarget extends CompositeDisposable {
60
+ /**
61
+ * Backend-agnostic drop target. Both the HTML5 `Droptarget` and the pointer
62
+ * `PointerDropTarget` implement this shape so consumers can hold one field
63
+ * regardless of which DnD backend produced it.
64
+ */
65
+ export interface IDropTarget extends IDisposable {
66
+ readonly onDrop: Event<DroptargetEvent>;
67
+ readonly onWillShowOverlay: Event<WillShowOverlayEvent>;
68
+ readonly state: Position | undefined;
69
+ disabled: boolean;
70
+ setTargetZones(zones: Position[]): void;
71
+ setOverlayModel(model: DroptargetOverlayModel): void;
72
+ }
73
+ export declare class Droptarget extends CompositeDisposable implements IDropTarget {
60
74
  private readonly element;
61
75
  private readonly options;
62
76
  private targetElement;