@formicoidea/labre-core 0.45.0 → 0.46.1
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/_pkgs/affine-block-callout/commands/turn-callout-into.d.ts +43 -0
- package/dist/_pkgs/affine-block-callout/commands/turn-callout-into.js +109 -0
- package/dist/_pkgs/affine-block-callout/commands/turn-into-callout.d.ts +1 -1
- package/dist/_pkgs/affine-block-callout/commands/turn-into-callout.js +1 -1
- package/dist/_pkgs/affine-block-callout/configs/slash-menu.js +4 -2
- package/dist/_pkgs/affine-block-callout/configs/toolbar.d.ts +65 -0
- package/dist/_pkgs/affine-block-callout/configs/toolbar.js +178 -0
- package/dist/_pkgs/affine-block-callout/view.d.ts +30 -1
- package/dist/_pkgs/affine-block-callout/view.js +45 -3
- package/dist/_pkgs/affine-block-code/code-toolbar/components/lang-button.js +1 -1
- package/dist/_pkgs/affine-block-frame/commands.d.ts +27 -0
- package/dist/_pkgs/affine-block-frame/commands.js +49 -0
- package/dist/_pkgs/affine-block-frame/frame-manager.d.ts +11 -6
- package/dist/_pkgs/affine-block-frame/frame-manager.js +10 -5
- package/dist/_pkgs/affine-block-frame/frame-order.d.ts +43 -0
- package/dist/_pkgs/affine-block-frame/frame-order.js +93 -0
- package/dist/_pkgs/affine-block-frame/index.d.ts +2 -0
- package/dist/_pkgs/affine-block-frame/index.js +2 -0
- package/dist/_pkgs/affine-block-frame/present/frame-order-menu.d.ts +10 -2
- package/dist/_pkgs/affine-block-frame/present/frame-order-menu.js +32 -18
- package/dist/_pkgs/affine-block-frame/view.js +6 -0
- package/dist/_pkgs/affine-block-note/configs/toolbar.d.ts +19 -0
- package/dist/_pkgs/affine-block-note/configs/toolbar.js +38 -23
- package/dist/_pkgs/affine-block-note/translations.d.ts +2 -0
- package/dist/_pkgs/affine-block-note/translations.js +14 -1
- package/dist/_pkgs/affine-block-root/configs/toolbar.js +31 -2
- package/dist/_pkgs/affine-block-root/translations.d.ts +7 -2
- package/dist/_pkgs/affine-block-root/translations.js +10 -13
- package/dist/_pkgs/affine-block-surface/extensions/selection-pane/actions.d.ts +20 -9
- package/dist/_pkgs/affine-block-surface/extensions/selection-pane/actions.js +57 -20
- package/dist/_pkgs/affine-block-surface/extensions/selection-pane/commands.d.ts +6 -8
- package/dist/_pkgs/affine-block-surface/extensions/selection-pane/commands.js +21 -8
- package/dist/_pkgs/affine-block-surface/extensions/selection-pane/index.d.ts +1 -1
- package/dist/_pkgs/affine-block-surface/extensions/selection-pane/index.js +1 -1
- package/dist/_pkgs/affine-components/portal/portal.d.ts +1 -1
- package/dist/_pkgs/affine-foundation/view.d.ts +8 -8
- package/dist/_pkgs/affine-fragment-frame-panel/body/frame-panel-body.d.ts +34 -2
- package/dist/_pkgs/affine-fragment-frame-panel/body/frame-panel-body.js +194 -81
- package/dist/_pkgs/affine-fragment-frame-panel/card/frame-card.d.ts +7 -4
- package/dist/_pkgs/affine-fragment-frame-panel/card/frame-card.js +9 -24
- package/dist/_pkgs/affine-fragment-frame-panel/index.d.ts +1 -0
- package/dist/_pkgs/affine-fragment-frame-panel/index.js +1 -0
- package/dist/_pkgs/affine-model/utils/types.d.ts +2 -2
- package/dist/_pkgs/affine-shared/services/edit-props-store.d.ts +4 -4
- package/dist/_pkgs/affine-shared/services/font-loader/config.d.ts +2 -2
- package/dist/_pkgs/affine-shared/services/font-loader/font-loader-service.d.ts +3 -3
- package/dist/_pkgs/affine-shared/services/index.d.ts +1 -1
- package/dist/_pkgs/affine-shared/services/index.js +1 -1
- package/dist/_pkgs/affine-shared/services/link-preview-service/link-preview-storage.d.ts +4 -4
- package/dist/_pkgs/affine-shared/services/outline-panel-service.d.ts +31 -0
- package/dist/_pkgs/affine-shared/services/outline-panel-service.js +17 -0
- package/dist/_pkgs/affine-shared/services/translation-service/chrome.d.ts +11 -0
- package/dist/_pkgs/affine-shared/services/translation-service/chrome.js +19 -0
- package/dist/_pkgs/affine-shared/utils/index.d.ts +1 -0
- package/dist/_pkgs/affine-shared/utils/index.js +1 -0
- package/dist/_pkgs/affine-shared/utils/panel-reorder-drag.d.ts +85 -0
- package/dist/_pkgs/affine-shared/utils/panel-reorder-drag.js +162 -0
- package/dist/_pkgs/affine-widget-edgeless-toolbar/selection-pane/drop.d.ts +7 -6
- package/dist/_pkgs/affine-widget-edgeless-toolbar/selection-pane/drop.js +11 -8
- package/dist/_pkgs/affine-widget-edgeless-toolbar/selection-pane/selection-pane-widget.d.ts +31 -15
- package/dist/_pkgs/affine-widget-edgeless-toolbar/selection-pane/selection-pane-widget.js +178 -142
- package/dist/_pkgs/std/scope/std-scope.d.ts +1 -1
- package/dist/commands.js +2 -0
- package/dist/extensions/view.js +5 -1
- package/dist/flags.d.ts +3 -0
- package/dist/flags.js +3 -0
- package/dist/host-panels.d.ts +90 -0
- package/dist/host-panels.js +111 -0
- package/package.json +5 -1
- package/dist/_pkgs/affine-fragment-frame-panel/utils/drag.d.ts +0 -27
- package/dist/_pkgs/affine-fragment-frame-panel/utils/drag.js +0 -96
- package/dist/_pkgs/affine-shared/services/sidebar-service.d.ts +0 -8
- package/dist/_pkgs/affine-shared/services/sidebar-service.js +0 -7
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { ExtensionType } from '../../store/index.js';
|
|
2
|
+
/**
|
|
3
|
+
* The outline panel (ADR 0034 §1): the document's table of contents, drawn by
|
|
4
|
+
* the host beside the editor.
|
|
5
|
+
*
|
|
6
|
+
* The library never mounts an outline itself, so there is no default: a host
|
|
7
|
+
* that draws one registers this seam, a host that does not leaves it out. Its
|
|
8
|
+
* only caller in the library is the "View in TOC" link of the toast the note
|
|
9
|
+
* toolbar shows after a note's display mode changes
|
|
10
|
+
* (`blocks/note/src/configs/toolbar.ts`). Absent or `null`, that toast offers
|
|
11
|
+
* no link, because a link that opens nothing is a lie.
|
|
12
|
+
*
|
|
13
|
+
* It replaces the `open(tabId?)` seam inherited from AFFiNE (removed in 0.46,
|
|
14
|
+
* ADR 0034 §2): one caller, which opened a tab named by a string nobody typed
|
|
15
|
+
* anywhere else. Shaped exactly like `SelectionPaneService`, so every panel
|
|
16
|
+
* the library asks a host to show answers the same two verbs.
|
|
17
|
+
*/
|
|
18
|
+
export interface OutlinePanelService {
|
|
19
|
+
/** Show the outline. */
|
|
20
|
+
open(): void;
|
|
21
|
+
/** Put it away. Writes nothing. */
|
|
22
|
+
close(): void;
|
|
23
|
+
}
|
|
24
|
+
export declare const OutlinePanelProvider: import("../../global/di/types.js").ServiceIdentifier<OutlinePanelService> & (<U extends OutlinePanelService = OutlinePanelService>(variant: import("../../global/di/types.js").ServiceVariant) => import("../../global/di/types.js").ServiceIdentifier<U>);
|
|
25
|
+
/**
|
|
26
|
+
* Host seam: the host's outline panel, or `null` to say there is none.
|
|
27
|
+
*
|
|
28
|
+
* `di.override`, like `SelectionPaneExtension`, so a later registration always
|
|
29
|
+
* wins and registering twice never throws at boot.
|
|
30
|
+
*/
|
|
31
|
+
export declare function OutlinePanelExtension(service: OutlinePanelService | null): ExtensionType;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { createIdentifier } from '../../global/di/index.js';
|
|
2
|
+
export const OutlinePanelProvider = createIdentifier('AffineOutlinePanel');
|
|
3
|
+
/**
|
|
4
|
+
* Host seam: the host's outline panel, or `null` to say there is none.
|
|
5
|
+
*
|
|
6
|
+
* `di.override`, like `SelectionPaneExtension`, so a later registration always
|
|
7
|
+
* wins and registering twice never throws at boot.
|
|
8
|
+
*/
|
|
9
|
+
export function OutlinePanelExtension(service) {
|
|
10
|
+
return {
|
|
11
|
+
setup: di => {
|
|
12
|
+
// `null` rides through the factory on purpose: `getOptional` then
|
|
13
|
+
// reports the panel as absent, which is the whole "no link" story.
|
|
14
|
+
di.override(OutlinePanelProvider, () => service);
|
|
15
|
+
},
|
|
16
|
+
};
|
|
17
|
+
}
|
|
@@ -464,6 +464,17 @@ export declare const FILL_COLOR_LABEL: ChromeWording;
|
|
|
464
464
|
* `ROOT_TOOLBAR_CREATE_LINKED_DOC` (`blocks/root`).
|
|
465
465
|
*/
|
|
466
466
|
export declare const TOOLBAR_CREATE_LINKED_DOC_TITLE: ChromeWording;
|
|
467
|
+
/**
|
|
468
|
+
* "Turn into" — the block toolbar's conversions dropdown, said identically by
|
|
469
|
+
* the note's text row and the callout's own row (#468). Was
|
|
470
|
+
* `ROOT_TOOLBAR_TURN_INTO` (`blocks/root`); the key is kept.
|
|
471
|
+
*/
|
|
472
|
+
export declare const TOOLBAR_TURN_INTO: ChromeWording;
|
|
473
|
+
/**
|
|
474
|
+
* …and that dropdown's accessible name. Was `ROOT_TOOLBAR_CONVERSIONS_ARIA`
|
|
475
|
+
* (`blocks/root`); the key is kept.
|
|
476
|
+
*/
|
|
477
|
+
export declare const TOOLBAR_CONVERSIONS_ARIA: ChromeWording;
|
|
467
478
|
/**
|
|
468
479
|
* "Edgeless content" — the surface-ref placeholder's own generic reference
|
|
469
480
|
* kind, said identically by the drag-handle preview's fallback label. Was
|
|
@@ -1034,6 +1034,23 @@ export const TOOLBAR_CREATE_LINKED_DOC_TITLE = [
|
|
|
1034
1034
|
'com.labre.root.toolbar.create-linked-doc',
|
|
1035
1035
|
'Create Linked Doc',
|
|
1036
1036
|
];
|
|
1037
|
+
/**
|
|
1038
|
+
* "Turn into" — the block toolbar's conversions dropdown, said identically by
|
|
1039
|
+
* the note's text row and the callout's own row (#468). Was
|
|
1040
|
+
* `ROOT_TOOLBAR_TURN_INTO` (`blocks/root`); the key is kept.
|
|
1041
|
+
*/
|
|
1042
|
+
export const TOOLBAR_TURN_INTO = [
|
|
1043
|
+
'com.labre.root.toolbar.turn-into',
|
|
1044
|
+
'Turn into',
|
|
1045
|
+
];
|
|
1046
|
+
/**
|
|
1047
|
+
* …and that dropdown's accessible name. Was `ROOT_TOOLBAR_CONVERSIONS_ARIA`
|
|
1048
|
+
* (`blocks/root`); the key is kept.
|
|
1049
|
+
*/
|
|
1050
|
+
export const TOOLBAR_CONVERSIONS_ARIA = [
|
|
1051
|
+
'com.labre.root.toolbar.conversions',
|
|
1052
|
+
'Conversions',
|
|
1053
|
+
];
|
|
1037
1054
|
/**
|
|
1038
1055
|
* "Edgeless content" — the surface-ref placeholder's own generic reference
|
|
1039
1056
|
* kind, said identically by the drag-handle preview's fallback label. Was
|
|
@@ -1283,6 +1300,8 @@ export const CHROME_WORDINGS = [
|
|
|
1283
1300
|
COLOR_LABEL,
|
|
1284
1301
|
FILL_COLOR_LABEL,
|
|
1285
1302
|
TOOLBAR_CREATE_LINKED_DOC_TITLE,
|
|
1303
|
+
TOOLBAR_TURN_INTO,
|
|
1304
|
+
TOOLBAR_CONVERSIONS_ARIA,
|
|
1286
1305
|
EDGELESS_CONTENT_LABEL,
|
|
1287
1306
|
TOOLBAR_EDIT,
|
|
1288
1307
|
TOOLBAR_REMOVE_LINK,
|
|
@@ -18,6 +18,7 @@ export * from './label-mode.js';
|
|
|
18
18
|
export * from './link-preview-refresh.js';
|
|
19
19
|
export * from './math.js';
|
|
20
20
|
export * from './model/index.js';
|
|
21
|
+
export * from './panel-reorder-drag.js';
|
|
21
22
|
export * from './popper-position.js';
|
|
22
23
|
export * from './print-to-pdf.js';
|
|
23
24
|
export * from './reference.js';
|
|
@@ -18,6 +18,7 @@ export * from './label-mode.js';
|
|
|
18
18
|
export * from './link-preview-refresh.js';
|
|
19
19
|
export * from './math.js';
|
|
20
20
|
export * from './model/index.js';
|
|
21
|
+
export * from './panel-reorder-drag.js';
|
|
21
22
|
export * from './popper-position.js';
|
|
22
23
|
export * from './print-to-pdf.js';
|
|
23
24
|
export * from './reference.js';
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The ONE drag-to-reorder gesture of the side panels (ADR 0034):
|
|
3
|
+
* the frame panel's cards and the selection pane's rows.
|
|
4
|
+
*
|
|
5
|
+
* Why it exists: the two panels each wrote their own drag and the two
|
|
6
|
+
* drifted. The frame panel's (`fragments/frame-panel/src/utils/drag.ts`, now
|
|
7
|
+
* deleted) ran on mouse events, never refused a read-only document, drew the
|
|
8
|
+
* drop line at 0 for a drop after the last card, and had no way out but the
|
|
9
|
+
* release. The selection pane's (hand-written in `selection-pane-widget.ts`)
|
|
10
|
+
* ran on pointer events, refused read-only and showed a `not-allowed` cursor,
|
|
11
|
+
* and swallowed Escape. Only the threshold was shared, and a comment held the
|
|
12
|
+
* rest together. Both panels now hand this controller what is theirs — the
|
|
13
|
+
* rows, the drop rule, the ghost, the write — and it owns the gesture:
|
|
14
|
+
*
|
|
15
|
+
* - pointer events, listened to on the document in the CAPTURE phase from the
|
|
16
|
+
* press to the end, so a panel that stops its own events' propagation (the
|
|
17
|
+
* pane does, to keep the canvas out of them) still sees every move;
|
|
18
|
+
* - a read-only document never starts one: the press adds no listener;
|
|
19
|
+
* - a press becomes a drag past {@link panelDragStarted} — called here and
|
|
20
|
+
* nowhere else — and only then is anything picked up;
|
|
21
|
+
* - over the whole viewport, a mask carries the cursor: `grabbing` over a gap
|
|
22
|
+
* that takes the drop, `not-allowed` elsewhere (its geometry stays in each
|
|
23
|
+
* panel's stylesheet, the controller sets the cursor and nothing else);
|
|
24
|
+
* - Escape or `pointercancel` CANCELS: nothing is written, the release that
|
|
25
|
+
* follows writes nothing, and the Escape does not reach the panel (which
|
|
26
|
+
* would close it);
|
|
27
|
+
* - the click that follows a release or a cancel is not a click: the panel
|
|
28
|
+
* asks {@link PanelReorderDrag.consumeSwallowedClick} in its click handler.
|
|
29
|
+
*
|
|
30
|
+
* Multi-selection is the panel's business: `onPickUp` decides what moves,
|
|
31
|
+
* `dropAt` skips the rows that move with it.
|
|
32
|
+
*/
|
|
33
|
+
/** A pointer position, in client coordinates. */
|
|
34
|
+
export interface PanelDragPoint {
|
|
35
|
+
clientX: number;
|
|
36
|
+
clientY: number;
|
|
37
|
+
}
|
|
38
|
+
export interface PanelReorderDragOptions<Drop> {
|
|
39
|
+
/** Read at the press: a read-only document never starts a drag. */
|
|
40
|
+
readonly: () => boolean;
|
|
41
|
+
/** The rows, top first, read LIVE at every move. */
|
|
42
|
+
rows: () => readonly HTMLElement[];
|
|
43
|
+
/** The box a drop must land in; outside it, or `null`, refuses. */
|
|
44
|
+
bounds: () => HTMLElement | null;
|
|
45
|
+
/** The press became a drag: select what moves, build the ghost. */
|
|
46
|
+
onPickUp: (press: PanelDragPoint) => void;
|
|
47
|
+
/**
|
|
48
|
+
* What a release at the gap `gap` — before `rows()[gap]`, `rows().length`
|
|
49
|
+
* after the last — would do, or `null` to refuse it.
|
|
50
|
+
*/
|
|
51
|
+
dropAt: (gap: number, point: PanelDragPoint) => Drop | null;
|
|
52
|
+
/** Every move of a drag: draw the ghost at `ghost`, the line for `drop`. */
|
|
53
|
+
onMove: (drop: Drop | null, ghost: PanelDragPoint) => void;
|
|
54
|
+
/** The release, over a gap that takes it. Before `onEnd`. */
|
|
55
|
+
onDrop: (drop: Drop) => void;
|
|
56
|
+
/** A drag ended — dropped, refused, cancelled or disposed. Always last. */
|
|
57
|
+
onEnd: () => void;
|
|
58
|
+
/** The cursor mask: appended to `host()` on pick-up, removed at the end. */
|
|
59
|
+
mask: {
|
|
60
|
+
host: () => ParentNode | null;
|
|
61
|
+
className: string;
|
|
62
|
+
testId?: string;
|
|
63
|
+
};
|
|
64
|
+
/** Carries `data-drag="valid" | "invalid"` while a drag is live. */
|
|
65
|
+
stateHost?: () => HTMLElement | null;
|
|
66
|
+
}
|
|
67
|
+
export interface PanelReorderDrag {
|
|
68
|
+
/** Hand it the row's `pointerdown`. */
|
|
69
|
+
press(event: PointerEvent): void;
|
|
70
|
+
/**
|
|
71
|
+
* Whether the click being handled follows a drag's release or cancel —
|
|
72
|
+
* answered `true` once, then `false`.
|
|
73
|
+
*/
|
|
74
|
+
consumeSwallowedClick(): boolean;
|
|
75
|
+
/** Whether a press has become a drag that has not ended yet. */
|
|
76
|
+
readonly dragging: boolean;
|
|
77
|
+
/** Ends a live drag (`onEnd`, nothing written) and removes the listeners. */
|
|
78
|
+
dispose(): void;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* The gap a pointer at `clientY` is over: how many rows have their middle
|
|
82
|
+
* above it. `0` is before the first row, `rects.length` after the last.
|
|
83
|
+
*/
|
|
84
|
+
export declare function panelReorderGap(rects: readonly DOMRect[], clientY: number): number;
|
|
85
|
+
export declare function createPanelReorderDrag<Drop>(options: PanelReorderDragOptions<Drop>): PanelReorderDrag;
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
import { panelDragStarted } from '../styles/panel-header.js';
|
|
2
|
+
/**
|
|
3
|
+
* The gap a pointer at `clientY` is over: how many rows have their middle
|
|
4
|
+
* above it. `0` is before the first row, `rects.length` after the last.
|
|
5
|
+
*/
|
|
6
|
+
export function panelReorderGap(rects, clientY) {
|
|
7
|
+
let gap = 0;
|
|
8
|
+
for (const rect of rects) {
|
|
9
|
+
if (clientY > rect.top + rect.height / 2)
|
|
10
|
+
gap++;
|
|
11
|
+
}
|
|
12
|
+
return gap;
|
|
13
|
+
}
|
|
14
|
+
export function createPanelReorderDrag(options) {
|
|
15
|
+
let start = null;
|
|
16
|
+
let dragging = false;
|
|
17
|
+
let listening = null;
|
|
18
|
+
let mask = null;
|
|
19
|
+
let swallowClick = false;
|
|
20
|
+
const point = (event) => ({
|
|
21
|
+
clientX: event.clientX,
|
|
22
|
+
clientY: event.clientY,
|
|
23
|
+
});
|
|
24
|
+
const resolve = (at) => {
|
|
25
|
+
const bounds = options.bounds();
|
|
26
|
+
if (!bounds)
|
|
27
|
+
return null;
|
|
28
|
+
const box = bounds.getBoundingClientRect();
|
|
29
|
+
if (at.clientX < box.left ||
|
|
30
|
+
at.clientX > box.right ||
|
|
31
|
+
at.clientY < box.top ||
|
|
32
|
+
at.clientY > box.bottom) {
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
const rects = options.rows().map(row => row.getBoundingClientRect());
|
|
36
|
+
return options.dropAt(panelReorderGap(rects, at.clientY), at);
|
|
37
|
+
};
|
|
38
|
+
const show = (drop) => {
|
|
39
|
+
if (mask)
|
|
40
|
+
mask.style.cursor = drop ? 'grabbing' : 'not-allowed';
|
|
41
|
+
const host = options.stateHost?.();
|
|
42
|
+
if (host)
|
|
43
|
+
host.dataset.drag = drop ? 'valid' : 'invalid';
|
|
44
|
+
};
|
|
45
|
+
const unlisten = () => {
|
|
46
|
+
if (!listening)
|
|
47
|
+
return;
|
|
48
|
+
listening.removeEventListener('pointermove', onPointerMove, true);
|
|
49
|
+
listening.removeEventListener('pointerup', onPointerUp, true);
|
|
50
|
+
listening.removeEventListener('pointercancel', onPointerCancel, true);
|
|
51
|
+
listening.removeEventListener('keydown', onKeydown, true);
|
|
52
|
+
listening = null;
|
|
53
|
+
};
|
|
54
|
+
/** Back to idle; `onEnd` only when something was picked up. */
|
|
55
|
+
const finish = () => {
|
|
56
|
+
unlisten();
|
|
57
|
+
start = null;
|
|
58
|
+
if (!dragging)
|
|
59
|
+
return;
|
|
60
|
+
dragging = false;
|
|
61
|
+
mask?.remove();
|
|
62
|
+
mask = null;
|
|
63
|
+
const host = options.stateHost?.();
|
|
64
|
+
if (host)
|
|
65
|
+
delete host.dataset.drag;
|
|
66
|
+
options.onEnd();
|
|
67
|
+
};
|
|
68
|
+
const cancel = () => {
|
|
69
|
+
if (dragging)
|
|
70
|
+
swallowClick = true;
|
|
71
|
+
finish();
|
|
72
|
+
};
|
|
73
|
+
const pickUp = (event) => {
|
|
74
|
+
dragging = true;
|
|
75
|
+
const host = options.mask.host();
|
|
76
|
+
if (host) {
|
|
77
|
+
const doc = event.target?.ownerDocument ?? document;
|
|
78
|
+
mask = doc.createElement('div');
|
|
79
|
+
mask.className = options.mask.className;
|
|
80
|
+
if (options.mask.testId)
|
|
81
|
+
mask.dataset.testid = options.mask.testId;
|
|
82
|
+
mask.style.cursor = 'grabbing';
|
|
83
|
+
host.append(mask);
|
|
84
|
+
}
|
|
85
|
+
options.onPickUp({ clientX: start.x, clientY: start.y });
|
|
86
|
+
};
|
|
87
|
+
function onPointerMove(event) {
|
|
88
|
+
if (!start)
|
|
89
|
+
return;
|
|
90
|
+
if (!dragging) {
|
|
91
|
+
if (!panelDragStarted(start, { x: event.clientX, y: event.clientY })) {
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
pickUp(event);
|
|
95
|
+
}
|
|
96
|
+
const at = point(event);
|
|
97
|
+
const drop = resolve(at);
|
|
98
|
+
show(drop);
|
|
99
|
+
options.onMove(drop, at);
|
|
100
|
+
}
|
|
101
|
+
function onPointerUp(event) {
|
|
102
|
+
if (!dragging) {
|
|
103
|
+
// A press that never became a drag: the click that follows is a click.
|
|
104
|
+
finish();
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
const drop = resolve(point(event));
|
|
108
|
+
swallowClick = true;
|
|
109
|
+
try {
|
|
110
|
+
if (drop !== null)
|
|
111
|
+
options.onDrop(drop);
|
|
112
|
+
}
|
|
113
|
+
finally {
|
|
114
|
+
finish();
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
function onPointerCancel() {
|
|
118
|
+
cancel();
|
|
119
|
+
}
|
|
120
|
+
function onKeydown(event) {
|
|
121
|
+
if (event.key !== 'Escape')
|
|
122
|
+
return;
|
|
123
|
+
if (!dragging) {
|
|
124
|
+
// A press still under the threshold: forget it, and let the Escape do
|
|
125
|
+
// what it does in the panel.
|
|
126
|
+
finish();
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
event.stopPropagation();
|
|
130
|
+
event.preventDefault();
|
|
131
|
+
cancel();
|
|
132
|
+
}
|
|
133
|
+
return {
|
|
134
|
+
press(event) {
|
|
135
|
+
// Any new press clears a click left armed by a release or a cancel
|
|
136
|
+
// that no click followed (released over another element).
|
|
137
|
+
swallowClick = false;
|
|
138
|
+
if (event.button !== 0 || start)
|
|
139
|
+
return;
|
|
140
|
+
if (options.readonly())
|
|
141
|
+
return;
|
|
142
|
+
start = { x: event.clientX, y: event.clientY };
|
|
143
|
+
const doc = event.target?.ownerDocument ?? document;
|
|
144
|
+
doc.addEventListener('pointermove', onPointerMove, true);
|
|
145
|
+
doc.addEventListener('pointerup', onPointerUp, true);
|
|
146
|
+
doc.addEventListener('pointercancel', onPointerCancel, true);
|
|
147
|
+
doc.addEventListener('keydown', onKeydown, true);
|
|
148
|
+
listening = doc;
|
|
149
|
+
},
|
|
150
|
+
consumeSwallowedClick() {
|
|
151
|
+
const swallowed = swallowClick;
|
|
152
|
+
swallowClick = false;
|
|
153
|
+
return swallowed;
|
|
154
|
+
},
|
|
155
|
+
get dragging() {
|
|
156
|
+
return dragging;
|
|
157
|
+
},
|
|
158
|
+
dispose() {
|
|
159
|
+
finish();
|
|
160
|
+
},
|
|
161
|
+
};
|
|
162
|
+
}
|
|
@@ -44,18 +44,19 @@ export interface PaneSlot {
|
|
|
44
44
|
*/
|
|
45
45
|
export declare function paneSlotAtGap(rows: readonly PaneDropRow[], gap: number, parent: string, { lists, parentOf }: PaneLists): PaneSlot | null;
|
|
46
46
|
/**
|
|
47
|
-
* What a drop at `index` of `list` writes for the dragged
|
|
48
|
-
*
|
|
49
|
-
* when the slot is refused.
|
|
47
|
+
* What a drop at `index` of `list` writes for the dragged rows `dragged` (one
|
|
48
|
+
* id, or the set a multi-row drag moves): the model they land directly ABOVE
|
|
49
|
+
* (`null` = the bottom of their stack), or `null` when the slot is refused.
|
|
50
50
|
*
|
|
51
|
-
* `stackOf(id)` names the model that stands for a row in the dragged
|
|
51
|
+
* `stackOf(id)` names the model that stands for a row in the dragged rows'
|
|
52
52
|
* own stack — itself, or the frame it belongs to when the dragged row is a
|
|
53
53
|
* loose element and that row is a frame's member (a frame's members paint
|
|
54
54
|
* together, right above it) — or `undefined` for a row that is not in that
|
|
55
55
|
* stack at all. A slot is refused when neither neighbour is in the stack, or
|
|
56
56
|
* when both stand for the same model: the inside of a frame's block of rows,
|
|
57
|
-
* where a loose element cannot be put.
|
|
57
|
+
* where a loose element cannot be put. A row that stands for a dragged model
|
|
58
|
+
* (a dragged frame's member) moves with it, so it is no neighbour either.
|
|
58
59
|
*/
|
|
59
|
-
export declare function paneDropAbove(list: readonly SelectionPaneNode[], index: number,
|
|
60
|
+
export declare function paneDropAbove(list: readonly SelectionPaneNode[], index: number, dragged: string | ReadonlySet<string>, stackOf: (id: string) => string | undefined): {
|
|
60
61
|
above: string | null;
|
|
61
62
|
} | null;
|
|
@@ -59,21 +59,24 @@ export function paneSlotAtGap(rows, gap, parent, { lists, parentOf }) {
|
|
|
59
59
|
}
|
|
60
60
|
}
|
|
61
61
|
/**
|
|
62
|
-
* What a drop at `index` of `list` writes for the dragged
|
|
63
|
-
*
|
|
64
|
-
* when the slot is refused.
|
|
62
|
+
* What a drop at `index` of `list` writes for the dragged rows `dragged` (one
|
|
63
|
+
* id, or the set a multi-row drag moves): the model they land directly ABOVE
|
|
64
|
+
* (`null` = the bottom of their stack), or `null` when the slot is refused.
|
|
65
65
|
*
|
|
66
|
-
* `stackOf(id)` names the model that stands for a row in the dragged
|
|
66
|
+
* `stackOf(id)` names the model that stands for a row in the dragged rows'
|
|
67
67
|
* own stack — itself, or the frame it belongs to when the dragged row is a
|
|
68
68
|
* loose element and that row is a frame's member (a frame's members paint
|
|
69
69
|
* together, right above it) — or `undefined` for a row that is not in that
|
|
70
70
|
* stack at all. A slot is refused when neither neighbour is in the stack, or
|
|
71
71
|
* when both stand for the same model: the inside of a frame's block of rows,
|
|
72
|
-
* where a loose element cannot be put.
|
|
72
|
+
* where a loose element cannot be put. A row that stands for a dragged model
|
|
73
|
+
* (a dragged frame's member) moves with it, so it is no neighbour either.
|
|
73
74
|
*/
|
|
74
|
-
export function paneDropAbove(list, index,
|
|
75
|
-
const
|
|
76
|
-
const
|
|
75
|
+
export function paneDropAbove(list, index, dragged, stackOf) {
|
|
76
|
+
const moving = typeof dragged === 'string' ? new Set([dragged]) : dragged;
|
|
77
|
+
const stays = (node) => !moving.has(node.id) && !moving.has(stackOf(node.id) ?? '');
|
|
78
|
+
const before = list.slice(0, index).filter(stays);
|
|
79
|
+
const after = list.slice(index).filter(stays);
|
|
77
80
|
const upper = before.length
|
|
78
81
|
? stackOf(before[before.length - 1].id)
|
|
79
82
|
: undefined;
|
|
@@ -24,8 +24,9 @@ export declare const EDGELESS_SELECTION_PANE_WIDGET = "edgeless-selection-pane-w
|
|
|
24
24
|
* (shift / ctrl / cmd adds or removes it, like on the canvas), the padlock
|
|
25
25
|
* locks that row alone, a double-click renames a group or a frame (a frame is
|
|
26
26
|
* a row at its place in the stack, ADR 0031 amendments), and a drag moves a row
|
|
27
|
-
*
|
|
28
|
-
*
|
|
27
|
+
* — or, pressed on a selected row, the whole selection of one stack — among
|
|
28
|
+
* its siblings (the side panels' one drag, ADR 0034). Every write goes through
|
|
29
|
+
* `runCommand`, so the read-only refusal and the undo step live in one place.
|
|
29
30
|
*/
|
|
30
31
|
export declare class EdgelessSelectionPaneWidget extends WidgetComponent<RootBlockModel> {
|
|
31
32
|
static styles: import("lit").CSSResult;
|
|
@@ -36,19 +37,22 @@ export declare class EdgelessSelectionPaneWidget extends WidgetComponent<RootBlo
|
|
|
36
37
|
private accessor _filter;
|
|
37
38
|
/** The group row being renamed, or `null`. */
|
|
38
39
|
private accessor _renaming;
|
|
39
|
-
/** Where the dragged
|
|
40
|
+
/** Where the dragged rows would land; `null` while refused. */
|
|
40
41
|
private accessor _drop;
|
|
41
42
|
/** Where the dragged row's ghost is drawn, in the panel's own box. */
|
|
42
43
|
private accessor _ghost;
|
|
43
44
|
/** Bumped when the canvas selection changes, so the rows repaint. */
|
|
44
45
|
private accessor _selectionRevision;
|
|
45
|
-
|
|
46
|
+
/** The drag under way, from its pick-up to its end. */
|
|
47
|
+
private accessor _drag;
|
|
48
|
+
/** The last row pressed: what a pick-up picks up. */
|
|
49
|
+
private _pressed;
|
|
50
|
+
/** The side panels' one reorder gesture, wired in `_wire()`. */
|
|
51
|
+
private _reorder;
|
|
46
52
|
/** The rows of the last render, top first: what a drag hit-tests. */
|
|
47
53
|
private _visibleRows;
|
|
48
54
|
/** The sibling lists before the filter: what a drop is computed in. */
|
|
49
55
|
private _lists;
|
|
50
|
-
/** A drag ends with a click on the row it started on; that click is not one. */
|
|
51
|
-
private _swallowNextClick;
|
|
52
56
|
get paneOpen(): boolean;
|
|
53
57
|
private get _gfx();
|
|
54
58
|
private _setOpen;
|
|
@@ -109,7 +113,21 @@ export declare class EdgelessSelectionPaneWidget extends WidgetComponent<RootBlo
|
|
|
109
113
|
private _onRowContextMenu;
|
|
110
114
|
private _commitRename;
|
|
111
115
|
private readonly _onRenameKeydown;
|
|
116
|
+
private _createReorderDrag;
|
|
117
|
+
private _panel;
|
|
118
|
+
private _paneBody;
|
|
119
|
+
/** The rows on screen, top first, with the rows they draw. */
|
|
120
|
+
private _shownRows;
|
|
112
121
|
private _onRowPointerDown;
|
|
122
|
+
/**
|
|
123
|
+
* The press became a drag. A canvas row picked up is selected, as the frame
|
|
124
|
+
* panel selects a card — unless it already is, and then the whole selection
|
|
125
|
+
* moves with it, as in the frame panel: every selected row the pane lists.
|
|
126
|
+
* Rows that are not all in the pressed row's stack and list have no one
|
|
127
|
+
* place to land, so every drop of theirs is refused, honestly, with a
|
|
128
|
+
* `not-allowed` cursor rather than a line that would write nothing.
|
|
129
|
+
*/
|
|
130
|
+
private _pickUp;
|
|
113
131
|
/**
|
|
114
132
|
* Which model stands for a row in the dragged row's own stack — the stack
|
|
115
133
|
* `canvas.element.reorder` restacks it in, the models sharing its raw
|
|
@@ -119,20 +137,18 @@ export declare class EdgelessSelectionPaneWidget extends WidgetComponent<RootBlo
|
|
|
119
137
|
* mindmap node moves with its mindmap).
|
|
120
138
|
*/
|
|
121
139
|
private _stackOf;
|
|
122
|
-
/**
|
|
140
|
+
/**
|
|
141
|
+
* Where a release over the gap `gap` (the controller's count of rows whose
|
|
142
|
+
* middle is above the pointer, at `clientY`) would land the dragged rows,
|
|
143
|
+
* or `null` to refuse it.
|
|
144
|
+
*/
|
|
123
145
|
private _dropAt;
|
|
124
|
-
private _moveGhost;
|
|
125
|
-
private readonly _onDocumentPointerMove;
|
|
126
|
-
/** A canvas row picked up is selected, as the frame panel selects a card. */
|
|
127
|
-
private _pickUp;
|
|
128
|
-
private readonly _onDocumentPointerUp;
|
|
129
146
|
/**
|
|
130
147
|
* One write per gesture, through the command: `layer` for a drop into a
|
|
131
|
-
* layer, one
|
|
132
|
-
* is where the
|
|
148
|
+
* layer, one restack for a slot. The command writes nothing when the slot
|
|
149
|
+
* is where the rows already are, and a refused drop never reaches it.
|
|
133
150
|
*/
|
|
134
151
|
private _commitDrop;
|
|
135
|
-
private _endDrag;
|
|
136
152
|
private _renderGhost;
|
|
137
153
|
private _renderDropIndicator;
|
|
138
154
|
private _filterName;
|