@grafloria/element 0.4.51 → 0.4.53
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 +2 -2
- package/src/lib/dashboard-kit/commit.d.ts +82 -0
- package/src/lib/dashboard-kit/commit.js +121 -0
- package/src/lib/dashboard-kit/dashboard.d.ts +1 -1
- package/src/lib/dashboard-kit/grid-binder.d.ts +35 -42
- package/src/lib/dashboard-kit/grid-binder.js +403 -525
- package/src/lib/dashboard-kit/split-binder.js +1 -1
- package/src/lib/dashboard-kit/zones.d.ts +7 -0
- package/src/lib/dashboard-kit/zones.js +12 -6
package/package.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@grafloria/element",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.53",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./src/index.js",
|
|
6
6
|
"types": "./src/index.d.ts",
|
|
7
7
|
"peerDependencies": {
|
|
8
|
-
"@grafloria/engine": "^0.3.
|
|
8
|
+
"@grafloria/engine": "^0.3.9",
|
|
9
9
|
"@grafloria/renderer": "^0.4.0"
|
|
10
10
|
},
|
|
11
11
|
"dependencies": {
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* THE COMMIT (tile first, step 4a) — what a gesture writes into history.
|
|
3
|
+
*
|
|
4
|
+
* Every gesture ends the same way: each board it touched reports the tiles
|
|
5
|
+
* whose cells or pixels differ from the snapshot taken when the gesture
|
|
6
|
+
* entered it, and those deltas become commands. A widget's cell is on its
|
|
7
|
+
* node (`SetGridItemCommand`, then the pixel move and resize the projection
|
|
8
|
+
* derived); a container's cell is on its GROUP, together with the frame the
|
|
9
|
+
* projection wrote. Both come out of ONE function here. Before this the node
|
|
10
|
+
* path skipped groups "by design" and every site that could have displaced
|
|
11
|
+
* a section rebuilt the group command by hand — six of them — and the one
|
|
12
|
+
* that did not (the cross-board drop) dropped the target board's pushed
|
|
13
|
+
* sections on the floor: the drop drew the push and never persisted it.
|
|
14
|
+
*/
|
|
15
|
+
import { Command } from '@grafloria/engine';
|
|
16
|
+
import { type CellRect, type TileDelta, type WorldRect } from './grid-mapping.js';
|
|
17
|
+
/**
|
|
18
|
+
* A CONTAINER's cell lives in its group's metadata and its frame is what the
|
|
19
|
+
* projection wrote for that cell: one command sets both, and undo puts both
|
|
20
|
+
* back. (A node's cell rides on the node itself — see `buildCommitCommands`.)
|
|
21
|
+
*/
|
|
22
|
+
export declare class SetGroupCellCommand extends Command {
|
|
23
|
+
private groupId;
|
|
24
|
+
private cellBefore;
|
|
25
|
+
private cellAfter;
|
|
26
|
+
private frameBefore;
|
|
27
|
+
private frameAfter;
|
|
28
|
+
constructor(groupId: string, cellBefore: CellRect, cellAfter: CellRect, frameBefore: WorldRect, frameAfter: WorldRect);
|
|
29
|
+
private apply;
|
|
30
|
+
execute(context: {
|
|
31
|
+
diagram?: unknown;
|
|
32
|
+
}): void;
|
|
33
|
+
undo(context: {
|
|
34
|
+
diagram?: unknown;
|
|
35
|
+
}): void;
|
|
36
|
+
serialize(): {
|
|
37
|
+
id: string;
|
|
38
|
+
name: string;
|
|
39
|
+
timestamp: number;
|
|
40
|
+
data: {
|
|
41
|
+
groupId: string;
|
|
42
|
+
cellBefore: CellRect;
|
|
43
|
+
cellAfter: CellRect;
|
|
44
|
+
frameBefore: WorldRect;
|
|
45
|
+
frameAfter: WorldRect;
|
|
46
|
+
};
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Steps that depend on each other's RESULT — create a group, then move a page
|
|
51
|
+
* into it, then place the group on the board; or remove a member and then the
|
|
52
|
+
* group it emptied — run as one history step. A batch checks every member's
|
|
53
|
+
* `canExecute` before running any of them and every member's `canUndo` before
|
|
54
|
+
* undoing any, and a membership command's precondition (its group exists) is
|
|
55
|
+
* exactly what a neighbouring step creates or removes. This runs the chain in
|
|
56
|
+
* order and reverses it on undo, judging nothing up front.
|
|
57
|
+
*/
|
|
58
|
+
export declare class SequenceCommand extends Command {
|
|
59
|
+
private steps;
|
|
60
|
+
constructor(name: string, steps: Command[]);
|
|
61
|
+
execute(context: Parameters<Command['execute']>[0]): void;
|
|
62
|
+
undo(context: Parameters<Command['undo']>[0]): void;
|
|
63
|
+
canExecute(): boolean;
|
|
64
|
+
canUndo(): boolean;
|
|
65
|
+
serialize(): {
|
|
66
|
+
id: string;
|
|
67
|
+
name: string;
|
|
68
|
+
timestamp: number;
|
|
69
|
+
data: {
|
|
70
|
+
steps: import("@grafloria/engine").SerializedCommand[];
|
|
71
|
+
};
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* The commands for every tile a board's deltas say moved — nodes AND groups,
|
|
76
|
+
* in the deltas' order. A node's commands are its cell then its pixels; a
|
|
77
|
+
* group's is one cell-and-frame command. A delta whose cell did not change
|
|
78
|
+
* contributes nothing for a group (its frame follows its cell), and only the
|
|
79
|
+
* pixel commands for a node (a fit board re-projects every tile when a row
|
|
80
|
+
* comes or goes: the cells stand, the pixels move).
|
|
81
|
+
*/
|
|
82
|
+
export declare function tileCommands(deltas: TileDelta[]): Command[];
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* THE COMMIT (tile first, step 4a) — what a gesture writes into history.
|
|
3
|
+
*
|
|
4
|
+
* Every gesture ends the same way: each board it touched reports the tiles
|
|
5
|
+
* whose cells or pixels differ from the snapshot taken when the gesture
|
|
6
|
+
* entered it, and those deltas become commands. A widget's cell is on its
|
|
7
|
+
* node (`SetGridItemCommand`, then the pixel move and resize the projection
|
|
8
|
+
* derived); a container's cell is on its GROUP, together with the frame the
|
|
9
|
+
* projection wrote. Both come out of ONE function here. Before this the node
|
|
10
|
+
* path skipped groups "by design" and every site that could have displaced
|
|
11
|
+
* a section rebuilt the group command by hand — six of them — and the one
|
|
12
|
+
* that did not (the cross-board drop) dropped the target board's pushed
|
|
13
|
+
* sections on the floor: the drop drew the push and never persisted it.
|
|
14
|
+
*/
|
|
15
|
+
import { Command } from '@grafloria/engine';
|
|
16
|
+
import { buildCommitCommands, gridItemFromCell } from './grid-mapping.js';
|
|
17
|
+
/**
|
|
18
|
+
* A CONTAINER's cell lives in its group's metadata and its frame is what the
|
|
19
|
+
* projection wrote for that cell: one command sets both, and undo puts both
|
|
20
|
+
* back. (A node's cell rides on the node itself — see `buildCommitCommands`.)
|
|
21
|
+
*/
|
|
22
|
+
export class SetGroupCellCommand extends Command {
|
|
23
|
+
constructor(groupId, cellBefore, cellAfter, frameBefore, frameAfter) {
|
|
24
|
+
super('Resize section');
|
|
25
|
+
this.groupId = groupId;
|
|
26
|
+
this.cellBefore = cellBefore;
|
|
27
|
+
this.cellAfter = cellAfter;
|
|
28
|
+
this.frameBefore = frameBefore;
|
|
29
|
+
this.frameAfter = frameAfter;
|
|
30
|
+
}
|
|
31
|
+
apply(context, cell, frame) {
|
|
32
|
+
const diagram = context.diagram;
|
|
33
|
+
const grp = diagram === null || diagram === void 0 ? void 0 : diagram.getGroup(this.groupId);
|
|
34
|
+
if (!grp)
|
|
35
|
+
return;
|
|
36
|
+
grp.setMetadata('gridItem', gridItemFromCell(cell));
|
|
37
|
+
grp.setFrame(Object.assign({}, frame));
|
|
38
|
+
}
|
|
39
|
+
execute(context) {
|
|
40
|
+
this.apply(context, this.cellAfter, this.frameAfter);
|
|
41
|
+
}
|
|
42
|
+
undo(context) {
|
|
43
|
+
this.apply(context, this.cellBefore, this.frameBefore);
|
|
44
|
+
}
|
|
45
|
+
serialize() {
|
|
46
|
+
return {
|
|
47
|
+
id: this.id,
|
|
48
|
+
name: this.name,
|
|
49
|
+
timestamp: this.timestamp,
|
|
50
|
+
data: {
|
|
51
|
+
groupId: this.groupId,
|
|
52
|
+
cellBefore: this.cellBefore,
|
|
53
|
+
cellAfter: this.cellAfter,
|
|
54
|
+
frameBefore: this.frameBefore,
|
|
55
|
+
frameAfter: this.frameAfter,
|
|
56
|
+
},
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Steps that depend on each other's RESULT — create a group, then move a page
|
|
62
|
+
* into it, then place the group on the board; or remove a member and then the
|
|
63
|
+
* group it emptied — run as one history step. A batch checks every member's
|
|
64
|
+
* `canExecute` before running any of them and every member's `canUndo` before
|
|
65
|
+
* undoing any, and a membership command's precondition (its group exists) is
|
|
66
|
+
* exactly what a neighbouring step creates or removes. This runs the chain in
|
|
67
|
+
* order and reverses it on undo, judging nothing up front.
|
|
68
|
+
*/
|
|
69
|
+
export class SequenceCommand extends Command {
|
|
70
|
+
constructor(name, steps) {
|
|
71
|
+
super(name);
|
|
72
|
+
this.steps = steps;
|
|
73
|
+
}
|
|
74
|
+
execute(context) {
|
|
75
|
+
for (const c of this.steps)
|
|
76
|
+
c.execute(context);
|
|
77
|
+
}
|
|
78
|
+
undo(context) {
|
|
79
|
+
for (let i = this.steps.length - 1; i >= 0; i--)
|
|
80
|
+
this.steps[i].undo(context);
|
|
81
|
+
}
|
|
82
|
+
canExecute() {
|
|
83
|
+
return true;
|
|
84
|
+
}
|
|
85
|
+
canUndo() {
|
|
86
|
+
return true;
|
|
87
|
+
}
|
|
88
|
+
serialize() {
|
|
89
|
+
return { id: this.id, name: this.name, timestamp: this.timestamp, data: { steps: this.steps.map((c) => c.serialize()) } };
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
const sameCell = (a, b) => a.x === b.x && a.y === b.y && a.w === b.w && a.h === b.h;
|
|
93
|
+
/** The frame a delta's pixels describe — a group's frame is its position and size in the model. */
|
|
94
|
+
const frameOf = (pos, size) => ({
|
|
95
|
+
x: pos.x,
|
|
96
|
+
y: pos.y,
|
|
97
|
+
width: size.width,
|
|
98
|
+
height: size.height,
|
|
99
|
+
});
|
|
100
|
+
/**
|
|
101
|
+
* The commands for every tile a board's deltas say moved — nodes AND groups,
|
|
102
|
+
* in the deltas' order. A node's commands are its cell then its pixels; a
|
|
103
|
+
* group's is one cell-and-frame command. A delta whose cell did not change
|
|
104
|
+
* contributes nothing for a group (its frame follows its cell), and only the
|
|
105
|
+
* pixel commands for a node (a fit board re-projects every tile when a row
|
|
106
|
+
* comes or goes: the cells stand, the pixels move).
|
|
107
|
+
*/
|
|
108
|
+
export function tileCommands(deltas) {
|
|
109
|
+
const out = [];
|
|
110
|
+
for (const d of deltas) {
|
|
111
|
+
if (d.isGroup) {
|
|
112
|
+
if (sameCell(d.cellBefore, d.cellAfter))
|
|
113
|
+
continue;
|
|
114
|
+
out.push(new SetGroupCellCommand(d.id, d.cellBefore, d.cellAfter, frameOf(d.posBefore, d.sizeBefore), frameOf(d.posAfter, d.sizeAfter)));
|
|
115
|
+
continue;
|
|
116
|
+
}
|
|
117
|
+
out.push(...buildCommitCommands([d]));
|
|
118
|
+
}
|
|
119
|
+
return out;
|
|
120
|
+
}
|
|
121
|
+
//# sourceMappingURL=commit.js.map
|
|
@@ -227,7 +227,7 @@ export interface DashboardOptions {
|
|
|
227
227
|
* so a designer/viewer pair is one flag apart. Live: `handle.setStatic()`.
|
|
228
228
|
*/
|
|
229
229
|
static?: boolean;
|
|
230
|
-
/** The deepest board a drop may enter (a view is 0; default
|
|
230
|
+
/** The deepest board a drop may enter (a view is 0; unbounded by default). See the grid binder's `nesting`. */
|
|
231
231
|
nesting?: number;
|
|
232
232
|
/**
|
|
233
233
|
* DRAG HANDLE — DevExpress drags an item by its caption. `true`: the caption
|
|
@@ -52,6 +52,8 @@
|
|
|
52
52
|
import { Command, type DiagramModel, type GridColumnLayout, type GroupModel, type NodeModel } from '@grafloria/engine';
|
|
53
53
|
import { type ToolPointerEvent } from '@grafloria/renderer';
|
|
54
54
|
import { type CellRect, type WorldRect } from './grid-mapping.js';
|
|
55
|
+
import { type BesideSide } from './zones.js';
|
|
56
|
+
export { SequenceCommand, SetGroupCellCommand } from './commit.js';
|
|
55
57
|
/** The slice of a DiagramInstance the binder needs (structural, test-friendly). */
|
|
56
58
|
export interface DashboardGridApi {
|
|
57
59
|
getModel(): DiagramModel;
|
|
@@ -184,10 +186,13 @@ export interface DashboardGridOptions {
|
|
|
184
186
|
onRemoveRequest?: (nodeId: string, displaced: Command[]) => void | Promise<void>;
|
|
185
187
|
/**
|
|
186
188
|
* Page hook for palette drag-in release: add `node` (already carrying
|
|
187
|
-
* `cell` in its gridItem
|
|
188
|
-
*
|
|
189
|
+
* `cell` in its gridItem) to `target.boardId` — this view, or a page or
|
|
190
|
+
* section the chip was dropped into (tile first, step 4a) — through the
|
|
191
|
+
* page's command path, folding `displaced` into the same batch.
|
|
189
192
|
*/
|
|
190
|
-
onDropIn?: (node: NodeModel, cell: CellRect, displaced: Command[]
|
|
193
|
+
onDropIn?: (node: NodeModel, cell: CellRect, displaced: Command[], target: {
|
|
194
|
+
boardId: string;
|
|
195
|
+
}) => void | Promise<void>;
|
|
191
196
|
/**
|
|
192
197
|
* A member is about to LEAVE this board through a gesture (moved into
|
|
193
198
|
* another board, made a tab of its own). Answers the commands that follow
|
|
@@ -243,7 +248,7 @@ export interface DashboardGridOptions {
|
|
|
243
248
|
* counting a view as 0 — a widget into a section is 1, into a section
|
|
244
249
|
* inside a tab page is 2. Deeper containers are opaque to a drag: the
|
|
245
250
|
* pointer over them means a cell on their parent board (or beside them).
|
|
246
|
-
*
|
|
251
|
+
* Unbounded by default.
|
|
247
252
|
*/
|
|
248
253
|
nesting?: number;
|
|
249
254
|
/**
|
|
@@ -595,31 +600,6 @@ export interface TearOutPlan {
|
|
|
595
600
|
}
|
|
596
601
|
/** A torn-out page never arrives shorter than this: a strip with no room under it is not a group. */
|
|
597
602
|
export declare const TEAR_OUT_MIN_ROWS = 2;
|
|
598
|
-
/**
|
|
599
|
-
* Steps that depend on each other's RESULT — create a group, then move a page
|
|
600
|
-
* into it, then place the group on the board; or remove a member and then the
|
|
601
|
-
* group it emptied — run as one history step. A batch checks every member's
|
|
602
|
-
* `canExecute` before running any of them and every member's `canUndo` before
|
|
603
|
-
* undoing any, and a membership command's precondition (its group exists) is
|
|
604
|
-
* exactly what a neighbouring step creates or removes. This runs the chain in
|
|
605
|
-
* order and reverses it on undo, judging nothing up front.
|
|
606
|
-
*/
|
|
607
|
-
export declare class SequenceCommand extends Command {
|
|
608
|
-
private steps;
|
|
609
|
-
constructor(name: string, steps: Command[]);
|
|
610
|
-
execute(context: Parameters<Command['execute']>[0]): void;
|
|
611
|
-
undo(context: Parameters<Command['undo']>[0]): void;
|
|
612
|
-
canExecute(): boolean;
|
|
613
|
-
canUndo(): boolean;
|
|
614
|
-
serialize(): {
|
|
615
|
-
id: string;
|
|
616
|
-
name: string;
|
|
617
|
-
timestamp: number;
|
|
618
|
-
data: {
|
|
619
|
-
steps: import("@grafloria/engine").SerializedCommand[];
|
|
620
|
-
};
|
|
621
|
-
};
|
|
622
|
-
}
|
|
623
603
|
/**
|
|
624
604
|
* A WIDGET dropped on a tab strip becomes a new tab there (a tab dropped on
|
|
625
605
|
* one joins; a widget wraps into a page of its own first). The dashboard
|
|
@@ -646,14 +626,35 @@ interface AdoptOptions {
|
|
|
646
626
|
fit?: 'shrink';
|
|
647
627
|
/** Anchor the tile's TOP edge at the pointer instead of centring it (the pointer holds a tab, the page hangs below it). */
|
|
648
628
|
anchor?: 'top';
|
|
629
|
+
/** Enter WITH INTENT: the tile takes the cell under the hand and pushes the solid tiles there (D2 — a section this board holds refused it). */
|
|
630
|
+
push?: boolean;
|
|
631
|
+
/** Enter BESIDE a container of this board: the container gives way, the tile takes the band's side at the pointer's row. */
|
|
632
|
+
beside?: {
|
|
633
|
+
containerId: string;
|
|
634
|
+
side: BesideSide;
|
|
635
|
+
};
|
|
649
636
|
}
|
|
650
637
|
interface AdoptedLeg {
|
|
651
638
|
groupId: string;
|
|
652
|
-
/** Drive the target engine from the source binder's pointer stream. */
|
|
639
|
+
/** Drive the target engine from the source binder's pointer stream. `push`: the tile means it — solid tiles under the wanted cell are pushed (D2). */
|
|
653
640
|
move(world: {
|
|
654
641
|
x: number;
|
|
655
642
|
y: number;
|
|
643
|
+
}, opts?: {
|
|
644
|
+
push?: boolean;
|
|
645
|
+
}): void;
|
|
646
|
+
/** Put the tile BESIDE `containerId` on this board, at the row under `world` — the container shifts or the tiles behind it are pushed; a repeat at the same row is a no-op. */
|
|
647
|
+
beside(containerId: string, side: BesideSide, world: {
|
|
648
|
+
x: number;
|
|
649
|
+
y: number;
|
|
656
650
|
}): void;
|
|
651
|
+
/** The beside this board holds for the tile, for the zone resolve's stickiness: the container's frame at rest and the cell the tile took — null when none. */
|
|
652
|
+
besideState(): {
|
|
653
|
+
containerId: string;
|
|
654
|
+
side: BesideSide;
|
|
655
|
+
frame0: WorldRect;
|
|
656
|
+
vacated: WorldRect;
|
|
657
|
+
} | null;
|
|
657
658
|
/**
|
|
658
659
|
* Take the tile OFF the board while the pointer is somewhere the board is
|
|
659
660
|
* not the target (over a group the page will join instead); the tiles it
|
|
@@ -670,7 +671,7 @@ interface AdoptedLeg {
|
|
|
670
671
|
y: number;
|
|
671
672
|
w: number;
|
|
672
673
|
h: number;
|
|
673
|
-
}): boolean;
|
|
674
|
+
}, pushSolid?: boolean): boolean;
|
|
674
675
|
/** Every other tile's cell before the ghost entered — the layout a row insert translates. */
|
|
675
676
|
baseline(): Map<string, CellRect>;
|
|
676
677
|
/** Where the tile sits right now, or null while it is off the board. */
|
|
@@ -680,22 +681,14 @@ interface AdoptedLeg {
|
|
|
680
681
|
/** Undo the adoption: target board back to its pre-entry layout. */
|
|
681
682
|
abort(): void;
|
|
682
683
|
/**
|
|
683
|
-
* Close the leg for commit:
|
|
684
|
-
* tile's final cell and its projected rect
|
|
685
|
-
*
|
|
686
|
-
* commits them through these). Null when the tile is somehow gone.
|
|
684
|
+
* Close the leg for commit: the target board's displaced commands (widgets
|
|
685
|
+
* and sections alike), the tile's final cell and its projected rect. Null
|
|
686
|
+
* when the tile is somehow gone.
|
|
687
687
|
*/
|
|
688
688
|
finalize(): {
|
|
689
689
|
commands: Command[];
|
|
690
690
|
cell: CellRect;
|
|
691
691
|
rect: WorldRect;
|
|
692
|
-
groups: Array<{
|
|
693
|
-
id: string;
|
|
694
|
-
cellBefore: CellRect;
|
|
695
|
-
cellAfter: CellRect;
|
|
696
|
-
frameBefore: WorldRect;
|
|
697
|
-
frameAfter: WorldRect;
|
|
698
|
-
}>;
|
|
699
692
|
} | null;
|
|
700
693
|
}
|
|
701
694
|
/**
|