@adecore/ui 0.49.6 → 0.50.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.
- package/dist/SlidingColumn.d.ts +2 -1
- package/dist/SlidingColumn.js +90 -87
- package/dist/file-tree/helpers.js +13 -4
- package/dist/index.d.ts +5 -0
- package/dist/index.js +5 -0
- package/dist/locales/en.d.ts +3 -0
- package/dist/locales/en.js +4 -1
- package/dist/locales/nl.d.ts +3 -0
- package/dist/locales/nl.js +4 -1
- package/dist/tabs/use-tab-drag.d.ts +52 -0
- package/dist/tabs/use-tab-drag.js +218 -0
- package/dist/theme.css +65 -13
- package/dist/workspace/PaneBar.d.ts +39 -0
- package/dist/workspace/PaneBar.js +399 -0
- package/dist/workspace/Workspace.d.ts +4 -1
- package/dist/workspace/Workspace.js +207 -155
- package/dist/workspace/WorkspaceRail.d.ts +13 -0
- package/dist/workspace/WorkspaceRail.js +125 -0
- package/dist/workspace/WorkspaceTopRow.d.ts +15 -0
- package/dist/workspace/WorkspaceTopRow.js +81 -0
- package/dist/workspace/context.d.ts +4 -0
- package/dist/workspace/context.js +5 -0
- package/dist/workspace/model.js +9 -1
- package/dist/workspace/top-row-slot.d.ts +2 -0
- package/dist/workspace/top-row-slot.js +6 -0
- package/package.json +1 -1
- package/src/SlidingColumn.tsx +21 -2
- package/src/file-tree/helpers.ts +17 -4
- package/src/index.ts +5 -0
- package/src/locales/en.ts +4 -1
- package/src/locales/nl.ts +4 -1
- package/src/tabs/use-tab-drag.ts +256 -0
- package/src/theme.css +65 -13
- package/src/workspace/PaneBar.tsx +276 -0
- package/src/workspace/Workspace.tsx +28 -12
- package/src/workspace/WorkspaceRail.tsx +30 -0
- package/src/workspace/WorkspaceTopRow.tsx +37 -0
- package/src/workspace/context.ts +6 -0
- package/src/workspace/model.ts +11 -1
- package/src/workspace/top-row-slot.ts +7 -0
package/dist/SlidingColumn.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ export interface SlidingColumnProps {
|
|
|
3
3
|
open: boolean;
|
|
4
4
|
width: number;
|
|
5
5
|
gap?: number;
|
|
6
|
+
edge?: boolean;
|
|
6
7
|
bounds: {
|
|
7
8
|
min: number;
|
|
8
9
|
max(): number;
|
|
@@ -17,4 +18,4 @@ export interface SlidingColumnProps {
|
|
|
17
18
|
ref?: Ref<HTMLElement>;
|
|
18
19
|
children?: ReactNode;
|
|
19
20
|
}
|
|
20
|
-
export declare function SlidingColumn({ open, width, gap, bounds, onWidthChange, instant, body, className, ref, children }: SlidingColumnProps): import("react").JSX.Element;
|
|
21
|
+
export declare function SlidingColumn({ open, width, gap, edge, bounds, onWidthChange, instant, body, className, ref, children }: SlidingColumnProps): import("react").JSX.Element;
|
package/dist/SlidingColumn.js
CHANGED
|
@@ -12,80 +12,82 @@ const TRANSITION_MS = 200;
|
|
|
12
12
|
* moves, and stay mounted until the slide is over, so a close plays out.
|
|
13
13
|
*/
|
|
14
14
|
export function SlidingColumn(t0) {
|
|
15
|
-
const $ = _c(
|
|
15
|
+
const $ = _c(43);
|
|
16
16
|
const {
|
|
17
17
|
open,
|
|
18
18
|
width,
|
|
19
19
|
gap: t1,
|
|
20
|
+
edge: t2,
|
|
20
21
|
bounds,
|
|
21
22
|
onWidthChange,
|
|
22
|
-
instant:
|
|
23
|
+
instant: t3,
|
|
23
24
|
body,
|
|
24
25
|
className,
|
|
25
26
|
ref,
|
|
26
27
|
children
|
|
27
28
|
} = t0;
|
|
28
29
|
const gap = t1 === undefined ? 0 : t1;
|
|
29
|
-
const
|
|
30
|
+
const edge = t2 === undefined ? true : t2;
|
|
31
|
+
const instant = t3 === undefined ? false : t3;
|
|
30
32
|
const [settled, setSettled] = useState(!open);
|
|
31
33
|
if (instant && settled !== !open) {
|
|
32
34
|
setSettled(!open);
|
|
33
35
|
}
|
|
34
36
|
const present = open || !settled;
|
|
35
37
|
const column = useRef(null);
|
|
36
|
-
let
|
|
38
|
+
let t4;
|
|
37
39
|
if ($[0] !== gap) {
|
|
38
|
-
|
|
40
|
+
t4 = Math.round(gap);
|
|
39
41
|
$[0] = gap;
|
|
40
|
-
$[1] =
|
|
42
|
+
$[1] = t4;
|
|
41
43
|
} else {
|
|
42
|
-
|
|
44
|
+
t4 = $[1];
|
|
43
45
|
}
|
|
44
|
-
const spacing = Math.max(0,
|
|
45
|
-
const
|
|
46
|
-
let
|
|
46
|
+
const spacing = Math.max(0, t4);
|
|
47
|
+
const t5 = bounds.min + spacing;
|
|
48
|
+
let t6;
|
|
47
49
|
if ($[2] !== bounds || $[3] !== spacing) {
|
|
48
|
-
|
|
50
|
+
t6 = () => bounds.max() + spacing;
|
|
49
51
|
$[2] = bounds;
|
|
50
52
|
$[3] = spacing;
|
|
51
|
-
$[4] =
|
|
53
|
+
$[4] = t6;
|
|
52
54
|
} else {
|
|
53
|
-
|
|
55
|
+
t6 = $[4];
|
|
54
56
|
}
|
|
55
|
-
const
|
|
56
|
-
let
|
|
57
|
+
const t7 = width + spacing;
|
|
58
|
+
let t8;
|
|
57
59
|
if ($[5] !== onWidthChange || $[6] !== spacing) {
|
|
58
|
-
|
|
60
|
+
t8 = next => onWidthChange(next - spacing);
|
|
59
61
|
$[5] = onWidthChange;
|
|
60
62
|
$[6] = spacing;
|
|
61
|
-
$[7] =
|
|
63
|
+
$[7] = t8;
|
|
62
64
|
} else {
|
|
63
|
-
|
|
65
|
+
t8 = $[7];
|
|
64
66
|
}
|
|
65
|
-
let
|
|
66
|
-
if ($[8] !==
|
|
67
|
-
|
|
68
|
-
min:
|
|
69
|
-
max:
|
|
70
|
-
size:
|
|
67
|
+
let t9;
|
|
68
|
+
if ($[8] !== t5 || $[9] !== t6 || $[10] !== t7 || $[11] !== t8) {
|
|
69
|
+
t9 = {
|
|
70
|
+
min: t5,
|
|
71
|
+
max: t6,
|
|
72
|
+
size: t7,
|
|
71
73
|
from: "right",
|
|
72
|
-
onSize:
|
|
74
|
+
onSize: t8
|
|
73
75
|
};
|
|
74
|
-
$[8] =
|
|
75
|
-
$[9] =
|
|
76
|
-
$[10] =
|
|
77
|
-
$[11] =
|
|
78
|
-
$[12] =
|
|
76
|
+
$[8] = t5;
|
|
77
|
+
$[9] = t6;
|
|
78
|
+
$[10] = t7;
|
|
79
|
+
$[11] = t8;
|
|
80
|
+
$[12] = t9;
|
|
79
81
|
} else {
|
|
80
|
-
|
|
82
|
+
t9 = $[12];
|
|
81
83
|
}
|
|
82
84
|
const {
|
|
83
85
|
startResize
|
|
84
|
-
} = useColumnResize(column,
|
|
86
|
+
} = useColumnResize(column, t9);
|
|
85
87
|
let t10;
|
|
86
|
-
let
|
|
88
|
+
let t11;
|
|
87
89
|
if ($[13] !== open || $[14] !== settled) {
|
|
88
|
-
|
|
90
|
+
t10 = () => {
|
|
89
91
|
if (open || settled) {
|
|
90
92
|
return;
|
|
91
93
|
}
|
|
@@ -94,64 +96,64 @@ export function SlidingColumn(t0) {
|
|
|
94
96
|
window.clearTimeout(timer);
|
|
95
97
|
};
|
|
96
98
|
};
|
|
97
|
-
|
|
99
|
+
t11 = [open, settled];
|
|
98
100
|
$[13] = open;
|
|
99
101
|
$[14] = settled;
|
|
100
102
|
$[15] = t10;
|
|
101
|
-
$[16] =
|
|
103
|
+
$[16] = t11;
|
|
102
104
|
} else {
|
|
103
105
|
t10 = $[15];
|
|
104
|
-
|
|
106
|
+
t11 = $[16];
|
|
105
107
|
}
|
|
106
|
-
useEffect(
|
|
107
|
-
let
|
|
108
|
+
useEffect(t10, t11);
|
|
109
|
+
let t12;
|
|
108
110
|
if ($[17] !== ref) {
|
|
109
|
-
|
|
111
|
+
t12 = mergeRefs(column, ref);
|
|
110
112
|
$[17] = ref;
|
|
111
|
-
$[18] =
|
|
113
|
+
$[18] = t12;
|
|
112
114
|
} else {
|
|
113
|
-
|
|
115
|
+
t12 = $[18];
|
|
114
116
|
}
|
|
115
|
-
const
|
|
116
|
-
const
|
|
117
|
-
const
|
|
118
|
-
let
|
|
117
|
+
const t13 = !open;
|
|
118
|
+
const t14 = instant ? "" : undefined;
|
|
119
|
+
const t15 = spacing > 0 ? "" : undefined;
|
|
120
|
+
let t16;
|
|
119
121
|
if ($[19] !== className) {
|
|
120
|
-
|
|
122
|
+
t16 = clsx("sliding-column flex h-full shrink-0 justify-end overflow-hidden", className);
|
|
121
123
|
$[19] = className;
|
|
122
|
-
$[20] =
|
|
124
|
+
$[20] = t16;
|
|
123
125
|
} else {
|
|
124
|
-
|
|
126
|
+
t16 = $[20];
|
|
125
127
|
}
|
|
126
|
-
const
|
|
127
|
-
let
|
|
128
|
-
if ($[21] !==
|
|
129
|
-
|
|
130
|
-
width:
|
|
128
|
+
const t17 = open ? width + spacing : 0;
|
|
129
|
+
let t18;
|
|
130
|
+
if ($[21] !== t17) {
|
|
131
|
+
t18 = {
|
|
132
|
+
width: t17
|
|
131
133
|
};
|
|
132
|
-
$[21] =
|
|
133
|
-
$[22] =
|
|
134
|
+
$[21] = t17;
|
|
135
|
+
$[22] = t18;
|
|
134
136
|
} else {
|
|
135
|
-
|
|
137
|
+
t18 = $[22];
|
|
136
138
|
}
|
|
137
|
-
let
|
|
139
|
+
let t19;
|
|
138
140
|
if ($[23] !== open) {
|
|
139
|
-
|
|
141
|
+
t19 = event => {
|
|
140
142
|
if (event.propertyName === "width" && event.target === event.currentTarget) {
|
|
141
143
|
setSettled(!open);
|
|
142
144
|
}
|
|
143
145
|
};
|
|
144
146
|
$[23] = open;
|
|
145
|
-
$[24] =
|
|
147
|
+
$[24] = t19;
|
|
146
148
|
} else {
|
|
147
|
-
|
|
149
|
+
t19 = $[24];
|
|
148
150
|
}
|
|
149
|
-
let
|
|
150
|
-
if ($[25] !== body || $[26] !== children || $[27] !==
|
|
151
|
-
|
|
151
|
+
let t20;
|
|
152
|
+
if ($[25] !== body || $[26] !== children || $[27] !== edge || $[28] !== open || $[29] !== present || $[30] !== spacing || $[31] !== startResize || $[32] !== width) {
|
|
153
|
+
t20 = present && /*#__PURE__*/_jsxs("div", {
|
|
152
154
|
ref: body?.ref,
|
|
153
155
|
tabIndex: body ? -1 : undefined,
|
|
154
|
-
className: clsx("relative flex h-full shrink-0 flex-col bg-surface outline-none", spacing === 0 && "border-l border-border"),
|
|
156
|
+
className: clsx("relative flex h-full shrink-0 flex-col bg-surface outline-none", spacing === 0 && clsx("border-l", edge ? "border-border" : "border-transparent")),
|
|
155
157
|
style: {
|
|
156
158
|
width,
|
|
157
159
|
marginLeft: spacing
|
|
@@ -169,38 +171,39 @@ export function SlidingColumn(t0) {
|
|
|
169
171
|
});
|
|
170
172
|
$[25] = body;
|
|
171
173
|
$[26] = children;
|
|
172
|
-
$[27] =
|
|
173
|
-
$[28] =
|
|
174
|
-
$[29] =
|
|
175
|
-
$[30] =
|
|
176
|
-
$[31] =
|
|
177
|
-
$[32] =
|
|
174
|
+
$[27] = edge;
|
|
175
|
+
$[28] = open;
|
|
176
|
+
$[29] = present;
|
|
177
|
+
$[30] = spacing;
|
|
178
|
+
$[31] = startResize;
|
|
179
|
+
$[32] = width;
|
|
180
|
+
$[33] = t20;
|
|
178
181
|
} else {
|
|
179
|
-
|
|
182
|
+
t20 = $[33];
|
|
180
183
|
}
|
|
181
|
-
let
|
|
182
|
-
if ($[
|
|
183
|
-
|
|
184
|
-
ref:
|
|
185
|
-
inert:
|
|
186
|
-
"data-instant":
|
|
187
|
-
"data-gap":
|
|
188
|
-
className:
|
|
189
|
-
style:
|
|
190
|
-
onTransitionEnd:
|
|
191
|
-
children:
|
|
184
|
+
let t21;
|
|
185
|
+
if ($[34] !== t12 || $[35] !== t13 || $[36] !== t14 || $[37] !== t15 || $[38] !== t16 || $[39] !== t18 || $[40] !== t19 || $[41] !== t20) {
|
|
186
|
+
t21 = /*#__PURE__*/_jsx("aside", {
|
|
187
|
+
ref: t12,
|
|
188
|
+
inert: t13,
|
|
189
|
+
"data-instant": t14,
|
|
190
|
+
"data-gap": t15,
|
|
191
|
+
className: t16,
|
|
192
|
+
style: t18,
|
|
193
|
+
onTransitionEnd: t19,
|
|
194
|
+
children: t20
|
|
192
195
|
});
|
|
193
|
-
$[33] = t11;
|
|
194
196
|
$[34] = t12;
|
|
195
197
|
$[35] = t13;
|
|
196
198
|
$[36] = t14;
|
|
197
199
|
$[37] = t15;
|
|
198
|
-
$[38] =
|
|
200
|
+
$[38] = t16;
|
|
199
201
|
$[39] = t18;
|
|
200
202
|
$[40] = t19;
|
|
201
203
|
$[41] = t20;
|
|
204
|
+
$[42] = t21;
|
|
202
205
|
} else {
|
|
203
|
-
|
|
206
|
+
t21 = $[42];
|
|
204
207
|
}
|
|
205
|
-
return
|
|
208
|
+
return t21;
|
|
206
209
|
}
|
|
@@ -150,13 +150,22 @@ function plainKey(rowPath) {
|
|
|
150
150
|
return dirPathOf(rowPath);
|
|
151
151
|
}
|
|
152
152
|
export function collapsedPathsOf(rows, keyOf = plainKey) {
|
|
153
|
-
|
|
153
|
+
const paths = [];
|
|
154
|
+
for (const row of rows) {
|
|
154
155
|
const key = row.kind === 'directory' && !row.isExpanded ? keyOf(row.path) : null;
|
|
155
|
-
|
|
156
|
-
|
|
156
|
+
if (key !== null) {
|
|
157
|
+
paths.push(key);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
return paths;
|
|
157
161
|
}
|
|
158
162
|
export function mergeCollapsedPaths(current, rows, keyOf = plainKey) {
|
|
159
|
-
const known = new Set(
|
|
163
|
+
const known = new Set();
|
|
164
|
+
for (const row of rows) {
|
|
165
|
+
if (row.kind === 'directory') {
|
|
166
|
+
known.add(keyOf(row.path));
|
|
167
|
+
}
|
|
168
|
+
}
|
|
160
169
|
const folded = new Set(collapsedPathsOf(rows, keyOf));
|
|
161
170
|
const next = current.filter(dir => !known.has(dir) || folded.has(dir));
|
|
162
171
|
const existing = new Set(current);
|
package/dist/index.d.ts
CHANGED
|
@@ -16,6 +16,7 @@ export type { MenuCheckProps, MenuHintProps, MenuLabelProps, MenuPopupProps, Men
|
|
|
16
16
|
export type { KeyValueListItemProps, KeyValueListNameProps, KeyValueListRootProps, KeyValueListValueProps } from './key-value-list/parts.tsx';
|
|
17
17
|
export type { PopoverPopupProps, PopupVariant, PreviewCardPopupProps } from './popover/parts.tsx';
|
|
18
18
|
export type { TabsCountProps, TabsListProps, TabsRootProps, TabsTabProps, TabsValue, TabsVariant } from './tabs/parts.tsx';
|
|
19
|
+
export { tabDropIndex, useTabDrag, type TabDrag, type TabDragOptions } from './tabs/use-tab-drag.ts';
|
|
19
20
|
export { AccentSwatches, type AccentSwatchesProps } from './AccentSwatches.tsx';
|
|
20
21
|
export { Banner, type BannerProps, type BannerTone } from './Banner.tsx';
|
|
21
22
|
export { Button, type ButtonProps, type ButtonShape, type ButtonSize, type ButtonVariant } from './Button.tsx';
|
|
@@ -97,6 +98,10 @@ export type { FileTree as FileTreeModel, FileTreeVisibleRow, FileTreeDragAndDrop
|
|
|
97
98
|
export type { FoldKeyOf, SortRow } from './file-tree/helpers.ts';
|
|
98
99
|
export type { TreeRootProps, TreeRowProps, TreeChevronProps, TreeChevronSlotProps, TreeLabelProps, TreeDecorationProps, TreeControlProps, TreeCheckboxProps } from './tree/parts.tsx';
|
|
99
100
|
export { Workspace, type WorkspaceProps } from './workspace/Workspace.tsx';
|
|
101
|
+
export { WorkspaceRail, WorkspaceRailSeparator, WorkspaceRailSpacer, type WorkspaceRailProps } from './workspace/WorkspaceRail.tsx';
|
|
102
|
+
export { WorkspaceTopRow, type WorkspaceTopRowProps } from './workspace/WorkspaceTopRow.tsx';
|
|
103
|
+
export { useTopRowSlot } from './workspace/top-row-slot.ts';
|
|
104
|
+
export { PaneBar, type PaneBarProps } from './workspace/PaneBar.tsx';
|
|
100
105
|
export type { WorkspaceLayout } from './workspace/context.ts';
|
|
101
106
|
export { DocumentTab, TabStrip, type DocumentTabProps, type TabStripProps, type TabStripItem } from './workspace/TabStrip.tsx';
|
|
102
107
|
export { SplitView, type SplitViewProps, type SplitViewInfo, type SplitViewBounds, type SplitDropTarget, type SplitDrag } from './workspace/SplitView.tsx';
|
package/dist/index.js
CHANGED
|
@@ -13,6 +13,7 @@ export * as Menu from './menu/index.parts.js';
|
|
|
13
13
|
export * as Popover from './popover/index.parts.js';
|
|
14
14
|
export * as PreviewCard from './preview-card/index.parts.js';
|
|
15
15
|
export * as Tabs from './tabs/index.parts.js';
|
|
16
|
+
export { tabDropIndex, useTabDrag } from './tabs/use-tab-drag.js';
|
|
16
17
|
export { AccentSwatches } from "./AccentSwatches.js";
|
|
17
18
|
export { Banner } from "./Banner.js";
|
|
18
19
|
export { Button } from "./Button.js";
|
|
@@ -87,6 +88,10 @@ export { useMeasuredWidth } from './useMeasuredWidth.js';
|
|
|
87
88
|
export { useNow, useTickingText } from './useNow.js';
|
|
88
89
|
export { useFileTree } from './file-tree/use-file-tree.js';
|
|
89
90
|
export { Workspace } from "./workspace/Workspace.js";
|
|
91
|
+
export { WorkspaceRail, WorkspaceRailSeparator, WorkspaceRailSpacer } from "./workspace/WorkspaceRail.js";
|
|
92
|
+
export { WorkspaceTopRow } from "./workspace/WorkspaceTopRow.js";
|
|
93
|
+
export { useTopRowSlot } from './workspace/top-row-slot.js';
|
|
94
|
+
export { PaneBar } from "./workspace/PaneBar.js";
|
|
90
95
|
export { DocumentTab, TabStrip } from "./workspace/TabStrip.js";
|
|
91
96
|
export { SplitView } from "./workspace/SplitView.js";
|
|
92
97
|
export { DropPreview } from "./workspace/DropPreview.js";
|
package/dist/locales/en.d.ts
CHANGED
package/dist/locales/en.js
CHANGED
package/dist/locales/nl.d.ts
CHANGED
package/dist/locales/nl.js
CHANGED
|
@@ -86,6 +86,9 @@ export default {
|
|
|
86
86
|
pane: 'Paneel',
|
|
87
87
|
movePane: 'Paneel verplaatsen',
|
|
88
88
|
maximize: 'Paneel maximaliseren',
|
|
89
|
-
restore: 'Panelen herstellen'
|
|
89
|
+
restore: 'Panelen herstellen',
|
|
90
|
+
moreActions: 'Meer acties',
|
|
91
|
+
closePane: 'Paneel sluiten',
|
|
92
|
+
tools: 'Gereedschappen'
|
|
90
93
|
}
|
|
91
94
|
};
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { type PointerEvent, type RefObject } from 'react';
|
|
2
|
+
export interface TabDragOptions {
|
|
3
|
+
/** The keys of the strip in their order, read when a drag needs them. */
|
|
4
|
+
keys(): readonly string[];
|
|
5
|
+
/** Where among the other tabs the tab lands for a drop before the `index`th of them, or null where it stays; pinned tabs keep their own run. */
|
|
6
|
+
landingOf(key: string, index: number): number | null;
|
|
7
|
+
onReorder(key: string, landing: number): void;
|
|
8
|
+
/**
|
|
9
|
+
* The tab leaves the strip while held: pulled `TEAR_DISTANCE` above or below it, or out of the window.
|
|
10
|
+
* `center` is where it is held, at the start of the strip; `width` is its width. Without it a tab stays in the strip.
|
|
11
|
+
*/
|
|
12
|
+
onTearOut?(key: string, center: {
|
|
13
|
+
x: number;
|
|
14
|
+
y: number;
|
|
15
|
+
}, width: number): void;
|
|
16
|
+
/** A release outside the window, for a platform that cannot follow a tab out while it is held. `at` is where the window would stand on screen. */
|
|
17
|
+
onTearOff?(key: string, at: {
|
|
18
|
+
x: number;
|
|
19
|
+
y: number;
|
|
20
|
+
}): void;
|
|
21
|
+
/** Whether dragging this tab moves its window rather than the tab, as for the only tab of a window. */
|
|
22
|
+
dragsWindow?(key: string): boolean;
|
|
23
|
+
onWindowDrag?(key: string, grab: {
|
|
24
|
+
x: number;
|
|
25
|
+
y: number;
|
|
26
|
+
}): void;
|
|
27
|
+
/** The pointer let go after a tear-out or a window drag, wherever it was. `window` says it moved the window. */
|
|
28
|
+
onRelease?(key: string, window: boolean): void;
|
|
29
|
+
}
|
|
30
|
+
export interface TabDrag {
|
|
31
|
+
/** For the element around the tabs, whose box decides when a tab leaves the strip. */
|
|
32
|
+
strip: RefObject<HTMLDivElement | null>;
|
|
33
|
+
/** Where the line that says where the tab lands stands, from the strip's left, or null while there is none. */
|
|
34
|
+
insertion: number | null;
|
|
35
|
+
/** For each tab, which must also carry `data-tab-key`. */
|
|
36
|
+
tabProps(key: string): {
|
|
37
|
+
'data-tab-key': string;
|
|
38
|
+
onPointerDown(event: PointerEvent<HTMLElement>): void;
|
|
39
|
+
onPointerMove(event: PointerEvent<HTMLElement>): void;
|
|
40
|
+
onPointerUp(event: PointerEvent<HTMLElement>): void;
|
|
41
|
+
onPointerCancel(event: PointerEvent<HTMLElement>): void;
|
|
42
|
+
onLostPointerCapture(event: PointerEvent<HTMLElement>): void;
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
/** The place among the other tabs of a strip where a dragged tab lands: before the first one whose middle is right of `x`. */
|
|
46
|
+
export declare function tabDropIndex(strip: Element, key: string, x: number): number;
|
|
47
|
+
/**
|
|
48
|
+
* Pointer handling for a strip of tabs that a person reorders by dragging, and can drag out of the strip into
|
|
49
|
+
* a window of its own. The strip stays put while a tab is held, so the insertion line says where it lands and
|
|
50
|
+
* the drop moves it once. A press on a button inside a tab stays that button's.
|
|
51
|
+
*/
|
|
52
|
+
export declare function useTabDrag(options: TabDragOptions): TabDrag;
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
import { c as _c } from "react/compiler-runtime";
|
|
2
|
+
import { useRef, useState } from 'react';
|
|
3
|
+
/* How far a pressed tab moves before it is a drag rather than a click. */
|
|
4
|
+
const DRAG_THRESHOLD_PX = 4;
|
|
5
|
+
/* How far above or below the strip a dragged tab goes before it tears off. */
|
|
6
|
+
const TEAR_DISTANCE_PX = 24;
|
|
7
|
+
/* The width of `.ade-tab-insertion`, and how far outside the first or last tab it stands. */
|
|
8
|
+
const INSERTION_WIDTH_PX = 2;
|
|
9
|
+
const INSERTION_INSET_PX = 2;
|
|
10
|
+
/** The place among the other tabs of a strip where a dragged tab lands: before the first one whose middle is right of `x`. */
|
|
11
|
+
export function tabDropIndex(strip, key, x) {
|
|
12
|
+
const others = [...strip.querySelectorAll('[data-tab-key]')].filter(tab => tab.dataset.tabKey !== key);
|
|
13
|
+
return others.filter(tab => {
|
|
14
|
+
const box = tab.getBoundingClientRect();
|
|
15
|
+
return box.left + box.width / 2 < x;
|
|
16
|
+
}).length;
|
|
17
|
+
}
|
|
18
|
+
/* Where in the strip the insertion line stands for a tab landing at `landing` among the others: halfway the gap it goes in. */
|
|
19
|
+
function insertionLeft(strip, others, landing) {
|
|
20
|
+
const boxOf = key => key === undefined ? null : strip.querySelector(`[data-tab-key="${CSS.escape(key)}"]`)?.getBoundingClientRect() ?? null;
|
|
21
|
+
const before = boxOf(others[landing - 1]);
|
|
22
|
+
const after = boxOf(others[landing]);
|
|
23
|
+
const origin = strip.getBoundingClientRect().left;
|
|
24
|
+
const x = before !== null && after !== null ? (before.right + after.left) / 2 : after !== null ? after.left - INSERTION_INSET_PX : (before?.right ?? origin) + INSERTION_INSET_PX;
|
|
25
|
+
return Math.max(0, Math.round(x - origin - INSERTION_WIDTH_PX / 2));
|
|
26
|
+
}
|
|
27
|
+
function outsideViewport(x, y) {
|
|
28
|
+
return x < 0 || y < 0 || x > window.innerWidth || y > window.innerHeight;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Pointer handling for a strip of tabs that a person reorders by dragging, and can drag out of the strip into
|
|
32
|
+
* a window of its own. The strip stays put while a tab is held, so the insertion line says where it lands and
|
|
33
|
+
* the drop moves it once. A press on a button inside a tab stays that button's.
|
|
34
|
+
*/
|
|
35
|
+
export function useTabDrag(options) {
|
|
36
|
+
const $ = _c(17);
|
|
37
|
+
const [insertion, setInsertion] = useState(null);
|
|
38
|
+
const press = useRef(null);
|
|
39
|
+
const strip = useRef(null);
|
|
40
|
+
const follows = options.onTearOut !== undefined;
|
|
41
|
+
let t0;
|
|
42
|
+
if ($[0] !== options) {
|
|
43
|
+
t0 = held => {
|
|
44
|
+
const types = ["pointerup", "mouseup", "pointercancel"];
|
|
45
|
+
const release = () => {
|
|
46
|
+
for (const type of types) {
|
|
47
|
+
removeEventListener(type, release);
|
|
48
|
+
}
|
|
49
|
+
if (press.current === held) {
|
|
50
|
+
press.current = null;
|
|
51
|
+
}
|
|
52
|
+
options.onRelease?.(held.key, held.mode === "window");
|
|
53
|
+
};
|
|
54
|
+
for (const type_0 of types) {
|
|
55
|
+
addEventListener(type_0, release);
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
$[0] = options;
|
|
59
|
+
$[1] = t0;
|
|
60
|
+
} else {
|
|
61
|
+
t0 = $[1];
|
|
62
|
+
}
|
|
63
|
+
const awaitRelease = t0;
|
|
64
|
+
let t1;
|
|
65
|
+
if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
|
|
66
|
+
t1 = (event, key) => {
|
|
67
|
+
if (event.button !== 0 || event.target.closest("button") !== null) {
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
event.currentTarget.setPointerCapture(event.pointerId);
|
|
71
|
+
press.current = {
|
|
72
|
+
key,
|
|
73
|
+
pointerId: event.pointerId,
|
|
74
|
+
grab: {
|
|
75
|
+
x: event.clientX,
|
|
76
|
+
y: event.clientY
|
|
77
|
+
},
|
|
78
|
+
mode: "press",
|
|
79
|
+
landing: null
|
|
80
|
+
};
|
|
81
|
+
};
|
|
82
|
+
$[2] = t1;
|
|
83
|
+
} else {
|
|
84
|
+
t1 = $[2];
|
|
85
|
+
}
|
|
86
|
+
const onPointerDown = t1;
|
|
87
|
+
let t2;
|
|
88
|
+
if ($[3] !== awaitRelease || $[4] !== follows || $[5] !== options) {
|
|
89
|
+
t2 = event_0 => {
|
|
90
|
+
const held_0 = press.current;
|
|
91
|
+
if (held_0 === null || held_0.pointerId !== event_0.pointerId) {
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
if (held_0.mode === "press") {
|
|
95
|
+
if (Math.hypot(event_0.clientX - held_0.grab.x, event_0.clientY - held_0.grab.y) < DRAG_THRESHOLD_PX) {
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
if (options.dragsWindow?.(held_0.key) === true && options.onWindowDrag !== undefined) {
|
|
99
|
+
held_0.mode = "window";
|
|
100
|
+
awaitRelease(held_0);
|
|
101
|
+
options.onWindowDrag(held_0.key, held_0.grab);
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
held_0.mode = "reorder";
|
|
105
|
+
}
|
|
106
|
+
if (held_0.mode !== "reorder") {
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
const box = strip.current?.getBoundingClientRect();
|
|
110
|
+
const offStrip = box !== undefined && (event_0.clientY < box.top - TEAR_DISTANCE_PX || event_0.clientY > box.bottom + TEAR_DISTANCE_PX);
|
|
111
|
+
if (follows && (offStrip || outsideViewport(event_0.clientX, event_0.clientY))) {
|
|
112
|
+
held_0.mode = "out";
|
|
113
|
+
held_0.landing = null;
|
|
114
|
+
setInsertion(null);
|
|
115
|
+
awaitRelease(held_0);
|
|
116
|
+
const tab = event_0.currentTarget.getBoundingClientRect();
|
|
117
|
+
const left = box?.left ?? tab.left;
|
|
118
|
+
options.onTearOut?.(held_0.key, {
|
|
119
|
+
x: left + tab.width / 2,
|
|
120
|
+
y: tab.top + tab.height / 2
|
|
121
|
+
}, tab.width);
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
const row = event_0.currentTarget.parentElement;
|
|
125
|
+
if (row === null || strip.current === null) {
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
held_0.landing = options.landingOf(held_0.key, tabDropIndex(row, held_0.key, event_0.clientX));
|
|
129
|
+
const others = options.keys().filter(one => one !== held_0.key);
|
|
130
|
+
setInsertion(held_0.landing === null ? null : insertionLeft(strip.current, others, held_0.landing));
|
|
131
|
+
};
|
|
132
|
+
$[3] = awaitRelease;
|
|
133
|
+
$[4] = follows;
|
|
134
|
+
$[5] = options;
|
|
135
|
+
$[6] = t2;
|
|
136
|
+
} else {
|
|
137
|
+
t2 = $[6];
|
|
138
|
+
}
|
|
139
|
+
const onPointerMove = t2;
|
|
140
|
+
let t3;
|
|
141
|
+
if ($[7] !== follows || $[8] !== options) {
|
|
142
|
+
t3 = (event_1, cancelled) => {
|
|
143
|
+
const held_1 = press.current;
|
|
144
|
+
if (held_1 === null || held_1.pointerId !== event_1.pointerId || held_1.mode === "out" || held_1.mode === "window") {
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
press.current = null;
|
|
148
|
+
setInsertion(null);
|
|
149
|
+
if (held_1.mode !== "reorder" || cancelled) {
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
if (!follows && options.onTearOff !== undefined && outsideViewport(event_1.clientX, event_1.clientY)) {
|
|
153
|
+
options.onTearOff(held_1.key, {
|
|
154
|
+
x: event_1.screenX - held_1.grab.x,
|
|
155
|
+
y: event_1.screenY - held_1.grab.y
|
|
156
|
+
});
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
if (held_1.landing !== null) {
|
|
160
|
+
options.onReorder(held_1.key, held_1.landing);
|
|
161
|
+
}
|
|
162
|
+
};
|
|
163
|
+
$[7] = follows;
|
|
164
|
+
$[8] = options;
|
|
165
|
+
$[9] = t3;
|
|
166
|
+
} else {
|
|
167
|
+
t3 = $[9];
|
|
168
|
+
}
|
|
169
|
+
const onPointerEnd = t3;
|
|
170
|
+
let t4;
|
|
171
|
+
if ($[10] === Symbol.for("react.memo_cache_sentinel")) {
|
|
172
|
+
t4 = event_2 => {
|
|
173
|
+
const held_2 = press.current;
|
|
174
|
+
if (held_2 === null || held_2.pointerId !== event_2.pointerId || held_2.mode !== "press" && held_2.mode !== "reorder") {
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
try {
|
|
178
|
+
event_2.currentTarget.setPointerCapture(event_2.pointerId);
|
|
179
|
+
} catch {
|
|
180
|
+
press.current = null;
|
|
181
|
+
}
|
|
182
|
+
};
|
|
183
|
+
$[10] = t4;
|
|
184
|
+
} else {
|
|
185
|
+
t4 = $[10];
|
|
186
|
+
}
|
|
187
|
+
const onLostPointerCapture = t4;
|
|
188
|
+
let t5;
|
|
189
|
+
if ($[11] !== onPointerEnd || $[12] !== onPointerMove) {
|
|
190
|
+
t5 = key_0 => ({
|
|
191
|
+
"data-tab-key": key_0,
|
|
192
|
+
onPointerDown: event_3 => onPointerDown(event_3, key_0),
|
|
193
|
+
onPointerMove,
|
|
194
|
+
onPointerUp: event_4 => onPointerEnd(event_4, false),
|
|
195
|
+
onPointerCancel: event_5 => onPointerEnd(event_5, true),
|
|
196
|
+
onLostPointerCapture
|
|
197
|
+
});
|
|
198
|
+
$[11] = onPointerEnd;
|
|
199
|
+
$[12] = onPointerMove;
|
|
200
|
+
$[13] = t5;
|
|
201
|
+
} else {
|
|
202
|
+
t5 = $[13];
|
|
203
|
+
}
|
|
204
|
+
let t6;
|
|
205
|
+
if ($[14] !== insertion || $[15] !== t5) {
|
|
206
|
+
t6 = {
|
|
207
|
+
strip,
|
|
208
|
+
insertion,
|
|
209
|
+
tabProps: t5
|
|
210
|
+
};
|
|
211
|
+
$[14] = insertion;
|
|
212
|
+
$[15] = t5;
|
|
213
|
+
$[16] = t6;
|
|
214
|
+
} else {
|
|
215
|
+
t6 = $[16];
|
|
216
|
+
}
|
|
217
|
+
return t6;
|
|
218
|
+
}
|