@grafloria/element 0.4.50 → 0.4.51
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/package.json
CHANGED
|
@@ -56,7 +56,7 @@ import { buildCommitCommands, cellFromGridItem, cellToRect, columnUnitFor, gridI
|
|
|
56
56
|
import { ensureDashboardKitStyles } from './styles.js';
|
|
57
57
|
import { captionOfGroup, captionPainted, captionPassThrough, captionKey, paintCaptionBand, sectionCaptionReserve, sizeCaptionBand } from './caption.js';
|
|
58
58
|
import { TAB_STRIP_HEIGHT } from './tabs.js';
|
|
59
|
-
import { BESIDE_BAND, resolve as resolveZone } from './zones.js';
|
|
59
|
+
import { BESIDE_BAND, resolve as resolveZone, resolveTabZone } from './zones.js';
|
|
60
60
|
/** The class of the painted grip element (a child of the node host). */
|
|
61
61
|
export const GRIP_CLASS = 'axdb-grip';
|
|
62
62
|
/** The container class that turns the caption strip's grip dots on. */
|
|
@@ -3836,7 +3836,7 @@ export function bindDashboardGrid(api, group, options = {}) {
|
|
|
3836
3836
|
// thirds, and the user, putting a page back into the panel it came from,
|
|
3837
3837
|
// never found the "into": "close to the edge means beside it, the content
|
|
3838
3838
|
// area means inside, the header means a new tab" (0.4.42).
|
|
3839
|
-
const EDGE_BAND =
|
|
3839
|
+
const EDGE_BAND = BESIDE_BAND; // one band for a tab's split and a widget's beside (zones.ts)
|
|
3840
3840
|
const visibleFrame = () => {
|
|
3841
3841
|
const rect = api.container.getBoundingClientRect();
|
|
3842
3842
|
const o = toWorld(rect.left, rect.top);
|
|
@@ -3954,47 +3954,55 @@ export function bindDashboardGrid(api, group, options = {}) {
|
|
|
3954
3954
|
const zoneAt = (cx, cy, world) => {
|
|
3955
3955
|
// A pointer OUTSIDE the visible canvas is off, full stop: a camera that
|
|
3956
3956
|
// moved can map it to a world point inside a group, and that group
|
|
3957
|
-
// took a join or a split from a release in the page header.
|
|
3958
|
-
|
|
3959
|
-
|
|
3960
|
-
const target = targetAt(world.x, world.y);
|
|
3961
|
-
const
|
|
3962
|
-
// A strip is the most precise target there is: anyone's wins outright.
|
|
3963
|
-
if (target) {
|
|
3964
|
-
const idx = plan.stripIndex(target.id, cx, cy);
|
|
3965
|
-
if (idx !== null)
|
|
3966
|
-
return { kind: 'strip', target, index: idx };
|
|
3967
|
-
}
|
|
3968
|
-
else if (home) {
|
|
3969
|
-
const idx = plan.stripIndex(fromGroupId, cx, cy);
|
|
3970
|
-
if (idx !== null)
|
|
3971
|
-
return { kind: 'reorder', index: idx };
|
|
3972
|
-
}
|
|
3973
|
-
// The board's own edges beat whatever sits against them — Dockview's
|
|
3974
|
-
// container edges over its groups — so a group at the top of the board
|
|
3975
|
-
// still leaves the top band to the board.
|
|
3976
|
-
const root = rootAt(cx, cy);
|
|
3977
|
-
if (root)
|
|
3978
|
-
return root;
|
|
3979
|
-
if (target) {
|
|
3980
|
-
const f = anchor && anchor.g === target ? anchor.frame : frameOfGroup(target);
|
|
3981
|
-
const stripH = anchor && anchor.g === target ? anchor.stripH : plan.stripHeight(target.id);
|
|
3982
|
-
const bodyH = Math.max(1, f.height - stripH);
|
|
3983
|
-
const rx = Math.min(1, Math.max(0, (world.x - f.x) / Math.max(1, f.width)));
|
|
3984
|
-
const ry = Math.min(1, Math.max(0, (world.y - f.y - stripH) / bodyH));
|
|
3985
|
-
if (rx >= EDGE_BAND && rx <= 1 - EDGE_BAND && ry >= EDGE_BAND && ry <= 1 - EDGE_BAND)
|
|
3986
|
-
return { kind: 'join', target };
|
|
3987
|
-
const d = [['left', rx], ['right', 1 - rx], ['top', ry], ['bottom', 1 - ry]];
|
|
3988
|
-
d.sort((p, q) => p[1] - q[1]);
|
|
3989
|
-
const h = halves(target, d[0][0]);
|
|
3990
|
-
return h ? Object.assign({ kind: 'split', target, side: d[0][0] }, h) : { kind: 'join', target };
|
|
3991
|
-
}
|
|
3992
|
-
if (home)
|
|
3993
|
-
return { kind: 'home' };
|
|
3957
|
+
// took a join or a split from a release in the page header. The
|
|
3958
|
+
// target is looked up (and anchored) only inside it.
|
|
3959
|
+
const clientInside = clientInsideCanvasGrace(cx, cy);
|
|
3960
|
+
const target = clientInside ? targetAt(world.x, world.y) : null;
|
|
3961
|
+
const root = clientInside ? rootAt(cx, cy) : null;
|
|
3994
3962
|
const foreign = foreignAt(world.x, world.y);
|
|
3995
|
-
|
|
3996
|
-
|
|
3997
|
-
|
|
3963
|
+
// The ORDER is zones.ts's, shared with the split board: a strip, the
|
|
3964
|
+
// board's own edges, the target's fifth or middle, home, then a board.
|
|
3965
|
+
const tz = resolveTabZone({
|
|
3966
|
+
x: world.x,
|
|
3967
|
+
y: world.y,
|
|
3968
|
+
clientInside,
|
|
3969
|
+
ownStrip: plan.stripIndex(fromGroupId, cx, cy),
|
|
3970
|
+
stripOf: (id) => plan.stripIndex(id, cx, cy),
|
|
3971
|
+
root: root && root.kind === 'root' ? { side: root.side } : null,
|
|
3972
|
+
target: target
|
|
3973
|
+
? {
|
|
3974
|
+
id: target.id,
|
|
3975
|
+
frame: anchor && anchor.g === target ? anchor.frame : frameOfGroup(target),
|
|
3976
|
+
stripHeight: anchor && anchor.g === target ? anchor.stripH : plan.stripHeight(target.id),
|
|
3977
|
+
}
|
|
3978
|
+
: null,
|
|
3979
|
+
home: worldInsideGroup(from, world.x, world.y) ? frameOfGroup(from) : null,
|
|
3980
|
+
homeBand: 0, // on a grid board the whole source frame is home
|
|
3981
|
+
band: EDGE_BAND,
|
|
3982
|
+
canSplit: (_id, side) => !!target && !!halves(target, side),
|
|
3983
|
+
pane: false,
|
|
3984
|
+
foreign: !!foreign && (!worldInsideBoard(world.x, world.y) || foreign.frameArea() < boardArea()),
|
|
3985
|
+
});
|
|
3986
|
+
switch (tz.kind) {
|
|
3987
|
+
case 'off':
|
|
3988
|
+
return { kind: 'off' };
|
|
3989
|
+
case 'strip':
|
|
3990
|
+
return { kind: 'strip', target: target, index: tz.index };
|
|
3991
|
+
case 'reorder':
|
|
3992
|
+
return { kind: 'reorder', index: tz.index };
|
|
3993
|
+
case 'root':
|
|
3994
|
+
return root;
|
|
3995
|
+
case 'join':
|
|
3996
|
+
return { kind: 'join', target: target };
|
|
3997
|
+
case 'split': {
|
|
3998
|
+
const h = halves(target, tz.side);
|
|
3999
|
+
return h ? Object.assign({ kind: 'split', target: target, side: tz.side }, h) : { kind: 'join', target: target };
|
|
4000
|
+
}
|
|
4001
|
+
case 'home':
|
|
4002
|
+
return { kind: 'home' };
|
|
4003
|
+
default:
|
|
4004
|
+
return tz.kind === 'board' && tz.foreign && foreign ? { kind: 'board', peer: foreign } : { kind: 'board' };
|
|
4005
|
+
}
|
|
3998
4006
|
};
|
|
3999
4007
|
const zoneKey = (z) => JSON.stringify(z, (k, v) => (k === 'target' ? v.id : k === 'peer' ? v.group.id : v));
|
|
4000
4008
|
// DOCKING PUSHES SECTIONS. A section is a locked tile so that a widget
|
|
@@ -23,6 +23,7 @@
|
|
|
23
23
|
* the authored size.
|
|
24
24
|
*/
|
|
25
25
|
import { __awaiter } from "tslib";
|
|
26
|
+
import { BESIDE_BAND, resolveTabZone } from './zones.js';
|
|
26
27
|
import { BatchCommand, Command } from '@grafloria/engine';
|
|
27
28
|
import { LiveRegionController, registerTool } from '@grafloria/renderer';
|
|
28
29
|
import { anyEdge, clearOtherSelections, dragHandleSelector, gripHostOf, gripOf, normalizeDragHandle, ownsPress, parentPeerOf, pressOnDragHandle, registerBoardPeer, syncGrip, DRAG_HANDLE_CLASS, EDGE_GRIP } from './grid-binder.js';
|
|
@@ -1037,37 +1038,48 @@ export function bindDashboardSplit(api, group, options = {}) {
|
|
|
1037
1038
|
return true;
|
|
1038
1039
|
return cx >= rect.left - EDGE_GRACE && cx <= rect.right + EDGE_GRACE && cy >= rect.top - EDGE_GRACE && cy <= rect.bottom + EDGE_GRACE;
|
|
1039
1040
|
};
|
|
1040
|
-
/** The centre third of a container's BODY (below its strip), both axes — the grid board's join zone. */
|
|
1041
|
-
const centreThird = (g, w) => {
|
|
1042
|
-
const f = frameOfGroup(g);
|
|
1043
|
-
if (!inRect(f, w.x, w.y))
|
|
1044
|
-
return false;
|
|
1045
|
-
const top = f.y + plan.stripHeight(g.id);
|
|
1046
|
-
const h = Math.max(0, f.y + f.height - top);
|
|
1047
|
-
return w.x >= f.x + f.width / 3 && w.x <= f.x + (2 * f.width) / 3 && w.y >= top + h / 3 && w.y <= top + (2 * h) / 3;
|
|
1048
|
-
};
|
|
1049
1041
|
const zoneAt = (cx, cy, w) => {
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1042
|
+
var _a;
|
|
1043
|
+
// The ORDER is zones.ts's, shared with the grid board: a strip, the
|
|
1044
|
+
// target's fifth (a pane beside it on that side, the sides taking the
|
|
1045
|
+
// corners) or its middle (a join), home — the source's middle, its own
|
|
1046
|
+
// edges meaning a pane beside itself — then the pane under the pointer.
|
|
1047
|
+
// The fifth replaced the centre third here too (0.4.42's rule, at last
|
|
1048
|
+
// on both boards).
|
|
1049
|
+
const clientInside = clientInsideCanvasGrace(cx, cy);
|
|
1050
|
+
const target = clientInside ? ((_a = targets.find((t) => inRect(frameOfGroup(t), w.x, w.y))) !== null && _a !== void 0 ? _a : null) : null;
|
|
1051
|
+
const paneTarget = clientInside && worldInsideBoard(w.x, w.y) ? dropTargetAt(tree0, w.x, w.y) : null;
|
|
1052
|
+
const tz = resolveTabZone({
|
|
1053
|
+
x: w.x,
|
|
1054
|
+
y: w.y,
|
|
1055
|
+
clientInside,
|
|
1056
|
+
ownStrip: plan.stripIndex(fromGroupId, cx, cy),
|
|
1057
|
+
stripOf: (id) => plan.stripIndex(id, cx, cy),
|
|
1058
|
+
root: null,
|
|
1059
|
+
target: target ? { id: target.id, frame: frameOfGroup(target), stripHeight: plan.stripHeight(target.id) } : null,
|
|
1060
|
+
home: inRect(frameOfGroup(from), w.x, w.y) ? frameOfGroup(from) : null,
|
|
1061
|
+
homeBand: BESIDE_BAND,
|
|
1062
|
+
band: BESIDE_BAND,
|
|
1063
|
+
canSplit: () => true,
|
|
1064
|
+
pane: !!paneTarget,
|
|
1065
|
+
foreign: false,
|
|
1066
|
+
});
|
|
1067
|
+
switch (tz.kind) {
|
|
1068
|
+
case 'off':
|
|
1069
|
+
return { kind: 'off' };
|
|
1070
|
+
case 'strip':
|
|
1071
|
+
return { kind: 'strip', targetId: tz.targetId, index: tz.index };
|
|
1072
|
+
case 'reorder':
|
|
1073
|
+
return { kind: 'reorder', index: tz.index };
|
|
1074
|
+
case 'join':
|
|
1075
|
+
return { kind: 'join', targetId: tz.targetId };
|
|
1076
|
+
case 'split':
|
|
1077
|
+
return { kind: 'pane', target: { id: tz.targetId, side: tz.side, rect: frameOfGroup(target) } };
|
|
1078
|
+
case 'pane':
|
|
1079
|
+
return { kind: 'pane', target: paneTarget };
|
|
1080
|
+
default:
|
|
1081
|
+
return { kind: 'home' };
|
|
1069
1082
|
}
|
|
1070
|
-
return { kind: 'home' };
|
|
1071
1083
|
};
|
|
1072
1084
|
const apply = (z) => {
|
|
1073
1085
|
plan.markDrop(z.kind === 'reorder' ? fromGroupId : z.kind === 'strip' ? z.targetId : null, z.kind === 'reorder' || z.kind === 'strip' ? z.index : null);
|
|
@@ -111,3 +111,74 @@ export declare const BESIDE_STAY = 0.05;
|
|
|
111
111
|
*/
|
|
112
112
|
export declare function bandOf(f: ZoneRect, stripHeight: number, x: number, y: number, band?: number): BesideSide | null;
|
|
113
113
|
export declare function resolve(input: ResolveInput): Zone;
|
|
114
|
+
/** A join target as the walk sees it: another tab container, its frame anchored by the binder while the pointer is inside it. */
|
|
115
|
+
export interface TabTarget {
|
|
116
|
+
id: string;
|
|
117
|
+
frame: ZoneRect;
|
|
118
|
+
stripHeight: number;
|
|
119
|
+
}
|
|
120
|
+
export interface TabZoneInput {
|
|
121
|
+
x: number;
|
|
122
|
+
y: number;
|
|
123
|
+
/** Inside the visible canvas plus its grace, in CLIENT space: off otherwise, whatever the world point says. */
|
|
124
|
+
clientInside: boolean;
|
|
125
|
+
/** The source strip's slot under the pointer (client space), else null. */
|
|
126
|
+
ownStrip: number | null;
|
|
127
|
+
/** A target strip's slot under the pointer (client space), else null. */
|
|
128
|
+
stripOf(targetId: string): number | null;
|
|
129
|
+
/** The board's own edge band under the pointer (client space) — a dock; null on boards that have none. */
|
|
130
|
+
root: {
|
|
131
|
+
side: BesideSide;
|
|
132
|
+
} | null;
|
|
133
|
+
/** The join target whose frame holds the point, or null. */
|
|
134
|
+
target: TabTarget | null;
|
|
135
|
+
/** The source group's frame, when the pointer is inside it. */
|
|
136
|
+
home: ZoneRect | null;
|
|
137
|
+
/** The source group's own band: 0 keeps its whole frame "home", a fifth lets its edges mean "beside myself". */
|
|
138
|
+
homeBand: number;
|
|
139
|
+
/** The outer fraction of a target's body that splits it (Dockview's fifth). */
|
|
140
|
+
band: number;
|
|
141
|
+
/** Whether the target can be halved on that side (a grid target too small refuses; a pane always can). */
|
|
142
|
+
canSplit(targetId: string, side: BesideSide): boolean;
|
|
143
|
+
/** A pane insertion exists under the pointer (split boards). */
|
|
144
|
+
pane: boolean;
|
|
145
|
+
/** A foreign board lies under the pointer and takes the drop (grid boards). */
|
|
146
|
+
foreign: boolean;
|
|
147
|
+
}
|
|
148
|
+
export type TabZone = {
|
|
149
|
+
kind: 'off';
|
|
150
|
+
} | {
|
|
151
|
+
kind: 'reorder';
|
|
152
|
+
index: number;
|
|
153
|
+
} | {
|
|
154
|
+
kind: 'strip';
|
|
155
|
+
targetId: string;
|
|
156
|
+
index: number;
|
|
157
|
+
} | {
|
|
158
|
+
kind: 'root';
|
|
159
|
+
side: BesideSide;
|
|
160
|
+
} | {
|
|
161
|
+
kind: 'join';
|
|
162
|
+
targetId: string;
|
|
163
|
+
} | {
|
|
164
|
+
kind: 'split';
|
|
165
|
+
targetId: string;
|
|
166
|
+
side: BesideSide;
|
|
167
|
+
} | {
|
|
168
|
+
kind: 'home';
|
|
169
|
+
} | {
|
|
170
|
+
kind: 'pane';
|
|
171
|
+
} | {
|
|
172
|
+
kind: 'board';
|
|
173
|
+
foreign: boolean;
|
|
174
|
+
};
|
|
175
|
+
/**
|
|
176
|
+
* What a pointer means for a TORN-OUT PAGE, in the one order both binders
|
|
177
|
+
* use: off the canvas, then a strip (the most precise target there is —
|
|
178
|
+
* a target's, or the source's own for a reorder), then the board's own
|
|
179
|
+
* edges (Dockview's container edges beat the groups against them), then the
|
|
180
|
+
* target under the pointer — its outer fifth splits it on that side, the
|
|
181
|
+
* sides taking the corners, its middle joins it — then home, then a pane, a
|
|
182
|
+
* foreign board, or this board.
|
|
183
|
+
*/
|
|
184
|
+
export declare function resolveTabZone(input: TabZoneInput): TabZone;
|
|
@@ -159,4 +159,39 @@ function stripHeightOf(roots, containerId) {
|
|
|
159
159
|
}
|
|
160
160
|
return 0;
|
|
161
161
|
}
|
|
162
|
+
/**
|
|
163
|
+
* What a pointer means for a TORN-OUT PAGE, in the one order both binders
|
|
164
|
+
* use: off the canvas, then a strip (the most precise target there is —
|
|
165
|
+
* a target's, or the source's own for a reorder), then the board's own
|
|
166
|
+
* edges (Dockview's container edges beat the groups against them), then the
|
|
167
|
+
* target under the pointer — its outer fifth splits it on that side, the
|
|
168
|
+
* sides taking the corners, its middle joins it — then home, then a pane, a
|
|
169
|
+
* foreign board, or this board.
|
|
170
|
+
*/
|
|
171
|
+
export function resolveTabZone(input) {
|
|
172
|
+
if (!input.clientInside)
|
|
173
|
+
return { kind: 'off' };
|
|
174
|
+
const { x, y } = input;
|
|
175
|
+
if (input.target) {
|
|
176
|
+
const idx = input.stripOf(input.target.id);
|
|
177
|
+
if (idx !== null)
|
|
178
|
+
return { kind: 'strip', targetId: input.target.id, index: idx };
|
|
179
|
+
}
|
|
180
|
+
else if (input.ownStrip !== null)
|
|
181
|
+
return { kind: 'reorder', index: input.ownStrip };
|
|
182
|
+
if (input.root)
|
|
183
|
+
return { kind: 'root', side: input.root.side };
|
|
184
|
+
if (input.target) {
|
|
185
|
+
const t = input.target;
|
|
186
|
+
const side = bandOf(t.frame, t.stripHeight, x, y, input.band);
|
|
187
|
+
if (side && input.canSplit(t.id, side))
|
|
188
|
+
return { kind: 'split', targetId: t.id, side };
|
|
189
|
+
return { kind: 'join', targetId: t.id };
|
|
190
|
+
}
|
|
191
|
+
if (input.home && inRect(input.home, x, y) && !bandOf(input.home, 0, x, y, input.homeBand))
|
|
192
|
+
return { kind: 'home' };
|
|
193
|
+
if (input.pane)
|
|
194
|
+
return { kind: 'pane' };
|
|
195
|
+
return { kind: 'board', foreign: input.foreign };
|
|
196
|
+
}
|
|
162
197
|
//# sourceMappingURL=zones.js.map
|