@craftile/core 0.10.0 → 1.0.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/package.json +3 -3
- package/src/commands/duplicate-block.ts +10 -9
- package/src/commands/insert-block-from-preset.ts +10 -9
- package/src/commands/insert-block.ts +10 -9
- package/src/commands/move-block.ts +19 -18
- package/src/commands/remove-block.ts +6 -5
- package/src/engine.ts +15 -14
- package/src/index.ts +1 -1
- package/src/types.ts +5 -5
- package/src/utils.ts +10 -0
- package/src/vue/useBlocksEngine.ts +8 -8
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@craftile/core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "1.0.0",
|
|
4
4
|
"description": "Framework-agnostic block editor engine for Craftile",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"craftile",
|
|
@@ -26,8 +26,8 @@
|
|
|
26
26
|
"src"
|
|
27
27
|
],
|
|
28
28
|
"dependencies": {
|
|
29
|
-
"@craftile/event-bus": "0.
|
|
30
|
-
"@craftile/types": "0.
|
|
29
|
+
"@craftile/event-bus": "1.0.0",
|
|
30
|
+
"@craftile/types": "1.0.0"
|
|
31
31
|
},
|
|
32
32
|
"devDependencies": {
|
|
33
33
|
"vitest": "^3.2.4",
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Command, EngineEmitFn } from '../types';
|
|
2
|
+
import { getRegionId } from '../utils';
|
|
2
3
|
import type { Block, Page } from '@craftile/types';
|
|
3
4
|
import { generateId } from '../utils';
|
|
4
5
|
|
|
@@ -16,7 +17,7 @@ export class DuplicateBlockCommand implements Command {
|
|
|
16
17
|
private duplicatedBlock?: Block;
|
|
17
18
|
private parentId?: string | null;
|
|
18
19
|
private insertIndex!: number;
|
|
19
|
-
private
|
|
20
|
+
private regionId?: string | null;
|
|
20
21
|
private emit: EngineEmitFn;
|
|
21
22
|
|
|
22
23
|
constructor(page: Page, options: DuplicateBlockOptions) {
|
|
@@ -45,7 +46,7 @@ export class DuplicateBlockCommand implements Command {
|
|
|
45
46
|
newBlock: this.duplicatedBlock,
|
|
46
47
|
parentId: this.parentId || undefined,
|
|
47
48
|
index: this.insertIndex,
|
|
48
|
-
|
|
49
|
+
regionId: this.regionId || undefined,
|
|
49
50
|
});
|
|
50
51
|
}
|
|
51
52
|
|
|
@@ -77,8 +78,8 @@ export class DuplicateBlockCommand implements Command {
|
|
|
77
78
|
return this.insertIndex;
|
|
78
79
|
}
|
|
79
80
|
|
|
80
|
-
|
|
81
|
-
return this.
|
|
81
|
+
getRegionId(): string | null | undefined {
|
|
82
|
+
return this.regionId;
|
|
82
83
|
}
|
|
83
84
|
|
|
84
85
|
private cloneBlockWithNewIds(block: Block, newId: string, newParentId?: string): Block {
|
|
@@ -125,10 +126,10 @@ export class DuplicateBlockCommand implements Command {
|
|
|
125
126
|
const region = this.page.regions.find((r) => r.blocks.includes(this.blockId));
|
|
126
127
|
if (region) {
|
|
127
128
|
const index = region.blocks.indexOf(this.blockId);
|
|
128
|
-
this.
|
|
129
|
+
this.regionId = getRegionId(region);
|
|
129
130
|
this.insertIndex = index + 1;
|
|
130
131
|
} else {
|
|
131
|
-
this.
|
|
132
|
+
this.regionId = getRegionId(this.page.regions[0]) || 'main';
|
|
132
133
|
this.insertIndex = this.page.regions[0].blocks.length || 0;
|
|
133
134
|
}
|
|
134
135
|
}
|
|
@@ -147,10 +148,10 @@ export class DuplicateBlockCommand implements Command {
|
|
|
147
148
|
|
|
148
149
|
targetParent.children.splice(this.insertIndex, 0, this.duplicatedBlockId);
|
|
149
150
|
} else {
|
|
150
|
-
let targetRegion = this.page.regions.find((r) => r.name === this.
|
|
151
|
+
let targetRegion = this.page.regions.find((r) => r.name === this.regionId);
|
|
151
152
|
|
|
152
153
|
if (!targetRegion) {
|
|
153
|
-
targetRegion = { name: this.
|
|
154
|
+
targetRegion = { name: this.regionId || 'main', blocks: [] };
|
|
154
155
|
this.page.regions.push(targetRegion);
|
|
155
156
|
}
|
|
156
157
|
|
|
@@ -177,7 +178,7 @@ export class DuplicateBlockCommand implements Command {
|
|
|
177
178
|
} else {
|
|
178
179
|
// Remove from region
|
|
179
180
|
if (this.page.regions) {
|
|
180
|
-
const targetRegion = this.page.regions.find((r) => r.name === this.
|
|
181
|
+
const targetRegion = this.page.regions.find((r) => r.name === this.regionId);
|
|
181
182
|
if (targetRegion) {
|
|
182
183
|
const index = targetRegion.blocks.indexOf(this.duplicatedBlockId);
|
|
183
184
|
if (index !== -1) {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Block, BlockProperties, BlockSchema, BlockStructure, Page } from '@craftile/types';
|
|
2
|
+
import { getRegionId } from '../utils';
|
|
2
3
|
import type { Command, EngineEmitFn } from '../types';
|
|
3
4
|
import { generateId } from '../utils';
|
|
4
5
|
import type { BlocksManager } from '../blocks-manager';
|
|
@@ -8,7 +9,7 @@ export interface InsertBlockFromPresetOptions {
|
|
|
8
9
|
presetIndex?: number;
|
|
9
10
|
presetData?: BlockStructure;
|
|
10
11
|
parentId?: string;
|
|
11
|
-
|
|
12
|
+
regionId?: string;
|
|
12
13
|
index?: number;
|
|
13
14
|
blocksManager: BlocksManager;
|
|
14
15
|
emit: EngineEmitFn;
|
|
@@ -20,7 +21,7 @@ export class InsertBlockFromPresetCommand implements Command {
|
|
|
20
21
|
private presetIndex?: number;
|
|
21
22
|
private presetData?: BlockStructure;
|
|
22
23
|
private parentId?: string;
|
|
23
|
-
private
|
|
24
|
+
private regionId?: string;
|
|
24
25
|
private index?: number;
|
|
25
26
|
private blockId: string;
|
|
26
27
|
private properties: Record<string, any>;
|
|
@@ -36,7 +37,7 @@ export class InsertBlockFromPresetCommand implements Command {
|
|
|
36
37
|
this.presetIndex = options.presetIndex;
|
|
37
38
|
this.presetData = options.presetData;
|
|
38
39
|
this.parentId = options.parentId;
|
|
39
|
-
this.
|
|
40
|
+
this.regionId = options.regionId;
|
|
40
41
|
this.index = options.index;
|
|
41
42
|
this.blockId = generateId();
|
|
42
43
|
this.blocksManager = options.blocksManager;
|
|
@@ -139,11 +140,11 @@ export class InsertBlockFromPresetCommand implements Command {
|
|
|
139
140
|
}
|
|
140
141
|
} else {
|
|
141
142
|
// Insert as top-level block
|
|
142
|
-
const
|
|
143
|
-
let targetRegion = this.page.regions.find((r) => r
|
|
143
|
+
const targetRegionId = this.regionId || getRegionId(this.page.regions[0]);
|
|
144
|
+
let targetRegion = this.page.regions.find((r) => getRegionId(r) === targetRegionId);
|
|
144
145
|
|
|
145
146
|
if (!targetRegion) {
|
|
146
|
-
targetRegion = { name:
|
|
147
|
+
targetRegion = { id: targetRegionId, name: targetRegionId, blocks: [] };
|
|
147
148
|
this.page.regions.push(targetRegion);
|
|
148
149
|
}
|
|
149
150
|
|
|
@@ -161,7 +162,7 @@ export class InsertBlockFromPresetCommand implements Command {
|
|
|
161
162
|
block: this.insertedBlock,
|
|
162
163
|
parentId: this.parentId,
|
|
163
164
|
index: this.actualIndex,
|
|
164
|
-
|
|
165
|
+
regionId: this.regionId || getRegionId(this.page.regions[0]),
|
|
165
166
|
});
|
|
166
167
|
}
|
|
167
168
|
|
|
@@ -181,8 +182,8 @@ export class InsertBlockFromPresetCommand implements Command {
|
|
|
181
182
|
parent.children.splice(this.actualIndex, 1);
|
|
182
183
|
}
|
|
183
184
|
} else {
|
|
184
|
-
const
|
|
185
|
-
const targetRegion = this.page.regions.find((r) => r
|
|
185
|
+
const targetRegionId = this.regionId || getRegionId(this.page.regions[0]);
|
|
186
|
+
const targetRegion = this.page.regions.find((r) => getRegionId(r) === targetRegionId);
|
|
186
187
|
|
|
187
188
|
if (targetRegion && this.actualIndex !== undefined) {
|
|
188
189
|
targetRegion.blocks.splice(this.actualIndex, 1);
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import type { Block, BlockSchema, Page } from '@craftile/types';
|
|
2
|
+
import { getRegionId } from '../utils';
|
|
2
3
|
import type { Command, EngineEmitFn } from '../types';
|
|
3
4
|
import { generateId } from '../utils';
|
|
4
5
|
|
|
5
6
|
export interface InsertBlockOptions {
|
|
6
7
|
blockType: string;
|
|
7
8
|
parentId?: string;
|
|
8
|
-
|
|
9
|
+
regionId?: string;
|
|
9
10
|
index?: number;
|
|
10
11
|
properties?: Record<string, any>;
|
|
11
12
|
blockSchema?: BlockSchema;
|
|
@@ -16,7 +17,7 @@ export class InsertBlockCommand implements Command {
|
|
|
16
17
|
private page: Page;
|
|
17
18
|
private blockType: string;
|
|
18
19
|
private parentId?: string;
|
|
19
|
-
private
|
|
20
|
+
private regionId?: string;
|
|
20
21
|
private index?: number;
|
|
21
22
|
private blockId: string;
|
|
22
23
|
private properties: Record<string, any>;
|
|
@@ -29,7 +30,7 @@ export class InsertBlockCommand implements Command {
|
|
|
29
30
|
this.page = page;
|
|
30
31
|
this.blockType = options.blockType;
|
|
31
32
|
this.parentId = options.parentId;
|
|
32
|
-
this.
|
|
33
|
+
this.regionId = options.regionId;
|
|
33
34
|
this.index = options.index;
|
|
34
35
|
this.blockId = generateId();
|
|
35
36
|
this.emit = options.emit;
|
|
@@ -70,11 +71,11 @@ export class InsertBlockCommand implements Command {
|
|
|
70
71
|
}
|
|
71
72
|
} else {
|
|
72
73
|
// Insert as top-level block (to the specified region)
|
|
73
|
-
const
|
|
74
|
-
let targetRegion = this.page.regions.find((r) => r
|
|
74
|
+
const targetRegionId = this.regionId || getRegionId(this.page.regions[0]);
|
|
75
|
+
let targetRegion = this.page.regions.find((r) => getRegionId(r) === targetRegionId);
|
|
75
76
|
|
|
76
77
|
if (!targetRegion) {
|
|
77
|
-
targetRegion = { name:
|
|
78
|
+
targetRegion = { id: targetRegionId, name: targetRegionId, blocks: [] };
|
|
78
79
|
this.page.regions.push(targetRegion);
|
|
79
80
|
}
|
|
80
81
|
|
|
@@ -92,7 +93,7 @@ export class InsertBlockCommand implements Command {
|
|
|
92
93
|
block: this.insertedBlock,
|
|
93
94
|
parentId: this.parentId,
|
|
94
95
|
index: this.actualIndex,
|
|
95
|
-
|
|
96
|
+
regionId: this.regionId || getRegionId(this.page.regions[0]),
|
|
96
97
|
});
|
|
97
98
|
}
|
|
98
99
|
|
|
@@ -109,8 +110,8 @@ export class InsertBlockCommand implements Command {
|
|
|
109
110
|
parent.children.splice(this.actualIndex, 1);
|
|
110
111
|
}
|
|
111
112
|
} else {
|
|
112
|
-
const
|
|
113
|
-
const targetRegion = this.page.regions.find((r) => r
|
|
113
|
+
const targetRegionId = this.regionId || getRegionId(this.page.regions[0]);
|
|
114
|
+
const targetRegion = this.page.regions.find((r) => getRegionId(r) === targetRegionId);
|
|
114
115
|
|
|
115
116
|
if (targetRegion && this.actualIndex !== undefined) {
|
|
116
117
|
targetRegion.blocks.splice(this.actualIndex, 1);
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import type { Block, Page } from '@craftile/types';
|
|
2
2
|
import type { Command, EngineEmitFn } from '../types';
|
|
3
|
+
import { getRegionId } from '../utils';
|
|
3
4
|
|
|
4
5
|
export interface MoveBlockOptions {
|
|
5
6
|
blockId: string;
|
|
6
7
|
targetParentId?: string;
|
|
7
8
|
targetIndex?: number;
|
|
8
|
-
|
|
9
|
+
targetRegionId?: string;
|
|
9
10
|
emit: EngineEmitFn;
|
|
10
11
|
}
|
|
11
12
|
|
|
@@ -14,13 +15,13 @@ export class MoveBlockCommand implements Command {
|
|
|
14
15
|
private blockId: string;
|
|
15
16
|
private targetParentId?: string;
|
|
16
17
|
private targetIndex?: number;
|
|
17
|
-
private
|
|
18
|
+
private targetRegionId?: string;
|
|
18
19
|
|
|
19
20
|
// State for reverting
|
|
20
21
|
private blockToMove?: Block;
|
|
21
22
|
private originalParentId?: string;
|
|
22
23
|
private originalIndex!: number;
|
|
23
|
-
private
|
|
24
|
+
private originalRegionId?: string;
|
|
24
25
|
|
|
25
26
|
private emit: EngineEmitFn;
|
|
26
27
|
|
|
@@ -29,7 +30,7 @@ export class MoveBlockCommand implements Command {
|
|
|
29
30
|
this.blockId = options.blockId;
|
|
30
31
|
this.targetParentId = options.targetParentId;
|
|
31
32
|
this.targetIndex = options.targetIndex;
|
|
32
|
-
this.
|
|
33
|
+
this.targetRegionId = options.targetRegionId;
|
|
33
34
|
this.emit = options.emit;
|
|
34
35
|
}
|
|
35
36
|
|
|
@@ -60,7 +61,7 @@ export class MoveBlockCommand implements Command {
|
|
|
60
61
|
const region = this.page.regions.find((r) => r.blocks.includes(this.blockId));
|
|
61
62
|
if (region) {
|
|
62
63
|
this.originalIndex = region.blocks.indexOf(this.blockId);
|
|
63
|
-
this.
|
|
64
|
+
this.originalRegionId = getRegionId(region);
|
|
64
65
|
region.blocks.splice(this.originalIndex, 1);
|
|
65
66
|
}
|
|
66
67
|
}
|
|
@@ -78,11 +79,11 @@ export class MoveBlockCommand implements Command {
|
|
|
78
79
|
} else {
|
|
79
80
|
this.blockToMove.parentId = undefined;
|
|
80
81
|
|
|
81
|
-
const
|
|
82
|
-
let targetRegion = this.page.regions.find((r) => r
|
|
82
|
+
const regionId = this.targetRegionId || getRegionId(this.page.regions[0]) || 'main';
|
|
83
|
+
let targetRegion = this.page.regions.find((r) => getRegionId(r) === regionId);
|
|
83
84
|
|
|
84
85
|
if (!targetRegion) {
|
|
85
|
-
targetRegion = { name:
|
|
86
|
+
targetRegion = { id: regionId, name: regionId, blocks: [] };
|
|
86
87
|
this.page.regions.push(targetRegion);
|
|
87
88
|
}
|
|
88
89
|
|
|
@@ -97,9 +98,9 @@ export class MoveBlockCommand implements Command {
|
|
|
97
98
|
blockId: this.blockId,
|
|
98
99
|
targetParentId: this.targetParentId,
|
|
99
100
|
targetIndex: this.targetIndex,
|
|
100
|
-
|
|
101
|
+
targetRegionId: this.targetRegionId,
|
|
101
102
|
sourceParentId: this.originalParentId || null,
|
|
102
|
-
|
|
103
|
+
sourceRegionId: this.originalRegionId || null,
|
|
103
104
|
sourceIndex: this.originalIndex,
|
|
104
105
|
});
|
|
105
106
|
}
|
|
@@ -134,8 +135,8 @@ export class MoveBlockCommand implements Command {
|
|
|
134
135
|
if (originalParent) {
|
|
135
136
|
originalParent.children.splice(this.originalIndex, 0, this.blockId);
|
|
136
137
|
}
|
|
137
|
-
} else if (this.
|
|
138
|
-
const region = this.page.regions.find((r) => r
|
|
138
|
+
} else if (this.originalRegionId) {
|
|
139
|
+
const region = this.page.regions.find((r) => getRegionId(r) === this.originalRegionId);
|
|
139
140
|
if (region) {
|
|
140
141
|
region.blocks.splice(this.originalIndex, 0, this.blockId);
|
|
141
142
|
}
|
|
@@ -145,9 +146,9 @@ export class MoveBlockCommand implements Command {
|
|
|
145
146
|
blockId: this.blockId,
|
|
146
147
|
targetParentId: this.originalParentId,
|
|
147
148
|
targetIndex: this.originalIndex,
|
|
148
|
-
|
|
149
|
+
targetRegionId: this.originalRegionId,
|
|
149
150
|
sourceParentId: this.targetParentId || null,
|
|
150
|
-
|
|
151
|
+
sourceRegionId: this.targetRegionId || null,
|
|
151
152
|
sourceIndex: this.targetIndex || 0,
|
|
152
153
|
});
|
|
153
154
|
}
|
|
@@ -164,16 +165,16 @@ export class MoveBlockCommand implements Command {
|
|
|
164
165
|
return this.targetIndex;
|
|
165
166
|
}
|
|
166
167
|
|
|
167
|
-
|
|
168
|
-
return this.
|
|
168
|
+
getTargetRegionId(): string | undefined {
|
|
169
|
+
return this.targetRegionId;
|
|
169
170
|
}
|
|
170
171
|
|
|
171
172
|
getSourceParentId(): string | null {
|
|
172
173
|
return this.originalParentId || null;
|
|
173
174
|
}
|
|
174
175
|
|
|
175
|
-
|
|
176
|
-
return this.
|
|
176
|
+
getSourceRegionId(): string | null {
|
|
177
|
+
return this.originalRegionId || null;
|
|
177
178
|
}
|
|
178
179
|
|
|
179
180
|
getSourceIndex(): number {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Block, Page } from '@craftile/types';
|
|
2
|
+
import { getRegionId } from '../utils';
|
|
2
3
|
import type { Command, EngineEmitFn } from '../types';
|
|
3
4
|
|
|
4
5
|
export interface RemoveBlockOptions {
|
|
@@ -12,7 +13,7 @@ export class RemoveBlockCommand implements Command {
|
|
|
12
13
|
private removedBlock?: Block;
|
|
13
14
|
private originalIndex?: number;
|
|
14
15
|
private originalParentId?: string;
|
|
15
|
-
private
|
|
16
|
+
private regionId?: string;
|
|
16
17
|
private emit: EngineEmitFn;
|
|
17
18
|
|
|
18
19
|
constructor(page: Page, options: RemoveBlockOptions) {
|
|
@@ -42,7 +43,7 @@ export class RemoveBlockCommand implements Command {
|
|
|
42
43
|
const region = this.page.regions.find((r) => r.blocks.includes(this.blockId));
|
|
43
44
|
if (region) {
|
|
44
45
|
this.originalIndex = region.blocks.indexOf(this.blockId);
|
|
45
|
-
this.
|
|
46
|
+
this.regionId = getRegionId(region);
|
|
46
47
|
region.blocks.splice(this.originalIndex, 1);
|
|
47
48
|
}
|
|
48
49
|
}
|
|
@@ -68,8 +69,8 @@ export class RemoveBlockCommand implements Command {
|
|
|
68
69
|
if (parent) {
|
|
69
70
|
parent.children.splice(this.originalIndex, 0, this.blockId);
|
|
70
71
|
}
|
|
71
|
-
} else if (this.
|
|
72
|
-
const region = this.page.regions.find((r) => r
|
|
72
|
+
} else if (this.regionId) {
|
|
73
|
+
const region = this.page.regions.find((r) => getRegionId(r) === this.regionId);
|
|
73
74
|
if (region) {
|
|
74
75
|
region.blocks.splice(this.originalIndex, 0, this.blockId);
|
|
75
76
|
}
|
|
@@ -80,7 +81,7 @@ export class RemoveBlockCommand implements Command {
|
|
|
80
81
|
block: this.removedBlock,
|
|
81
82
|
parentId: this.originalParentId,
|
|
82
83
|
index: this.originalIndex,
|
|
83
|
-
|
|
84
|
+
regionId: this.regionId,
|
|
84
85
|
});
|
|
85
86
|
}
|
|
86
87
|
|
package/src/engine.ts
CHANGED
|
@@ -22,7 +22,7 @@ export class Engine extends EventBus<EngineEvents> {
|
|
|
22
22
|
|
|
23
23
|
this.blocksManager = config.blocksManager || new BlocksManager();
|
|
24
24
|
this.historyManager = new HistoryManager();
|
|
25
|
-
this.setPage(config.page ? config.page : { blocks: {}, regions: [{ name: 'main', blocks: [] }] });
|
|
25
|
+
this.setPage(config.page ? config.page : { blocks: {}, regions: [{ id: 'main', name: 'main', blocks: [] }] });
|
|
26
26
|
|
|
27
27
|
if (config.blockSchemas && config.blockSchemas.length > 0) {
|
|
28
28
|
config.blockSchemas.forEach((schema) => {
|
|
@@ -37,7 +37,7 @@ export class Engine extends EventBus<EngineEvents> {
|
|
|
37
37
|
* @param blockType - The type of block to insert (must be registered)
|
|
38
38
|
* @param options - Optional configuration for block insertion
|
|
39
39
|
* @param options.parentId - ID of parent block (for nested blocks)
|
|
40
|
-
* @param options.
|
|
40
|
+
* @param options.regionId - Target region id (defaults to 'main')
|
|
41
41
|
* @param options.index - Position to insert at (defaults to end)
|
|
42
42
|
* @returns The ID of the newly inserted block
|
|
43
43
|
* @throws {Error} When block type is not registered or parent-child relationship is invalid
|
|
@@ -47,7 +47,7 @@ export class Engine extends EventBus<EngineEvents> {
|
|
|
47
47
|
blockType: string,
|
|
48
48
|
options?: {
|
|
49
49
|
parentId?: string;
|
|
50
|
-
|
|
50
|
+
regionId?: string;
|
|
51
51
|
index?: number;
|
|
52
52
|
}
|
|
53
53
|
): string {
|
|
@@ -70,7 +70,7 @@ export class Engine extends EventBus<EngineEvents> {
|
|
|
70
70
|
const command = new InsertBlockCommand(this.page, {
|
|
71
71
|
blockType,
|
|
72
72
|
parentId: options?.parentId,
|
|
73
|
-
|
|
73
|
+
regionId: options?.regionId,
|
|
74
74
|
index: options?.index,
|
|
75
75
|
blockSchema,
|
|
76
76
|
emit: this.emit.bind(this),
|
|
@@ -89,7 +89,7 @@ export class Engine extends EventBus<EngineEvents> {
|
|
|
89
89
|
* @param presetIndex - Index of the preset in the block schema's presets array
|
|
90
90
|
* @param options - Optional configuration for block insertion
|
|
91
91
|
* @param options.parentId - ID of parent block (for nested blocks)
|
|
92
|
-
* @param options.
|
|
92
|
+
* @param options.regionId - Target region id (defaults to 'main')
|
|
93
93
|
* @param options.index - Position to insert at (defaults to end)
|
|
94
94
|
* @returns The ID of the newly inserted block
|
|
95
95
|
* @throws {Error} When block type is not registered, preset not found, or parent-child relationship is invalid
|
|
@@ -100,7 +100,7 @@ export class Engine extends EventBus<EngineEvents> {
|
|
|
100
100
|
presetIndex: number,
|
|
101
101
|
options?: {
|
|
102
102
|
parentId?: string;
|
|
103
|
-
|
|
103
|
+
regionId?: string;
|
|
104
104
|
index?: number;
|
|
105
105
|
}
|
|
106
106
|
): string {
|
|
@@ -128,7 +128,7 @@ export class Engine extends EventBus<EngineEvents> {
|
|
|
128
128
|
blockType,
|
|
129
129
|
presetIndex,
|
|
130
130
|
parentId: options?.parentId,
|
|
131
|
-
|
|
131
|
+
regionId: options?.regionId,
|
|
132
132
|
index: options?.index,
|
|
133
133
|
blocksManager: this.blocksManager,
|
|
134
134
|
emit: this.emit.bind(this),
|
|
@@ -164,14 +164,14 @@ export class Engine extends EventBus<EngineEvents> {
|
|
|
164
164
|
* @param options - Optional configuration for block move operation
|
|
165
165
|
* @param options.targetParentId - ID of target parent block
|
|
166
166
|
* @param options.targetIndex - position in the target parent block children
|
|
167
|
-
* @param options.
|
|
167
|
+
* @param options.targetRegionId - target region id
|
|
168
168
|
*/
|
|
169
169
|
moveBlock(
|
|
170
170
|
blockId: string,
|
|
171
171
|
options?: {
|
|
172
172
|
targetParentId?: string;
|
|
173
173
|
targetIndex?: number;
|
|
174
|
-
|
|
174
|
+
targetRegionId?: string;
|
|
175
175
|
}
|
|
176
176
|
): void {
|
|
177
177
|
const block = this.page.blocks[blockId];
|
|
@@ -191,7 +191,7 @@ export class Engine extends EventBus<EngineEvents> {
|
|
|
191
191
|
blockId,
|
|
192
192
|
targetParentId: options?.targetParentId,
|
|
193
193
|
targetIndex: options?.targetIndex,
|
|
194
|
-
|
|
194
|
+
targetRegionId: options?.targetRegionId,
|
|
195
195
|
emit: this.emit.bind(this),
|
|
196
196
|
});
|
|
197
197
|
|
|
@@ -307,7 +307,7 @@ export class Engine extends EventBus<EngineEvents> {
|
|
|
307
307
|
* @param structure - The block structure to paste
|
|
308
308
|
* @param options - Optional configuration for block insertion
|
|
309
309
|
* @param options.parentId - ID of parent block (for nested blocks)
|
|
310
|
-
* @param options.
|
|
310
|
+
* @param options.regionId - Target region id (defaults to 'main')
|
|
311
311
|
* @param options.index - Position to insert at (defaults to end)
|
|
312
312
|
* @returns The ID of the newly inserted block
|
|
313
313
|
* @throws {Error} When block type is not registered or parent-child relationship is invalid
|
|
@@ -317,7 +317,7 @@ export class Engine extends EventBus<EngineEvents> {
|
|
|
317
317
|
structure: BlockStructure,
|
|
318
318
|
options?: {
|
|
319
319
|
parentId?: string;
|
|
320
|
-
|
|
320
|
+
regionId?: string;
|
|
321
321
|
index?: number;
|
|
322
322
|
}
|
|
323
323
|
): string {
|
|
@@ -341,7 +341,7 @@ export class Engine extends EventBus<EngineEvents> {
|
|
|
341
341
|
blockType: structure.type,
|
|
342
342
|
presetData: structure,
|
|
343
343
|
parentId: options?.parentId,
|
|
344
|
-
|
|
344
|
+
regionId: options?.regionId,
|
|
345
345
|
index: options?.index,
|
|
346
346
|
blocksManager: this.blocksManager,
|
|
347
347
|
emit: this.emit.bind(this),
|
|
@@ -373,13 +373,14 @@ export class Engine extends EventBus<EngineEvents> {
|
|
|
373
373
|
this.page = structuredClone(newPage);
|
|
374
374
|
|
|
375
375
|
if (this.page.regions.length === 0) {
|
|
376
|
-
this.page.regions = [{ name: 'main', blocks: Object.keys(this.page.blocks) }];
|
|
376
|
+
this.page.regions = [{ id: 'main', name: 'main', blocks: Object.keys(this.page.blocks) }];
|
|
377
377
|
}
|
|
378
378
|
|
|
379
379
|
// Initialize regions if not present
|
|
380
380
|
if (this.page.regions.length === 0) {
|
|
381
381
|
this.page.regions = [
|
|
382
382
|
{
|
|
383
|
+
id: 'main',
|
|
383
384
|
name: 'main',
|
|
384
385
|
blocks: Object.values(this.page.blocks)
|
|
385
386
|
.filter((block) => !block.parentId)
|
package/src/index.ts
CHANGED
package/src/types.ts
CHANGED
|
@@ -15,8 +15,8 @@ export interface Command {
|
|
|
15
15
|
// Event system types
|
|
16
16
|
export interface EngineEvents {
|
|
17
17
|
'page:set': { previousPage?: Page; newPage: Page };
|
|
18
|
-
'block:insert': { blockId: string; block: Block; parentId?: string; index?: number;
|
|
19
|
-
'block:remove': { blockId: string; block: Block; parentId?: string };
|
|
18
|
+
'block:insert': { blockId: string; block: Block; parentId?: string; index?: number; regionId?: string };
|
|
19
|
+
'block:remove': { blockId: string; block: Block; parentId?: string; regionId?: string };
|
|
20
20
|
'block:toggle': { blockId: string; disabled: boolean; oldValue?: boolean };
|
|
21
21
|
'block:property:set': { blockId: string; key: string; value: any; oldValue: any };
|
|
22
22
|
'block:update': { blockId: string; block: Block; property: string; value: any; oldValue: any };
|
|
@@ -24,9 +24,9 @@ export interface EngineEvents {
|
|
|
24
24
|
blockId: string;
|
|
25
25
|
targetParentId?: string;
|
|
26
26
|
targetIndex?: number;
|
|
27
|
-
|
|
27
|
+
targetRegionId?: string;
|
|
28
28
|
sourceParentId?: string | null;
|
|
29
|
-
|
|
29
|
+
sourceRegionId?: string | null;
|
|
30
30
|
sourceIndex: number;
|
|
31
31
|
};
|
|
32
32
|
'block:duplicate': {
|
|
@@ -35,7 +35,7 @@ export interface EngineEvents {
|
|
|
35
35
|
newBlock: Block;
|
|
36
36
|
parentId?: string;
|
|
37
37
|
index?: number;
|
|
38
|
-
|
|
38
|
+
regionId?: string;
|
|
39
39
|
};
|
|
40
40
|
undo: { command: any };
|
|
41
41
|
redo: { command: any };
|
package/src/utils.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import type { Region } from '@craftile/types';
|
|
2
|
+
|
|
1
3
|
export const generateId = (): string => {
|
|
2
4
|
if (crypto.randomUUID) {
|
|
3
5
|
return crypto.randomUUID();
|
|
@@ -5,3 +7,11 @@ export const generateId = (): string => {
|
|
|
5
7
|
|
|
6
8
|
return Date.now().toString(36) + Math.random().toString(36).substr(2);
|
|
7
9
|
};
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Get the unique identifier for a region.
|
|
13
|
+
* Falls back to name if id is not provided.
|
|
14
|
+
*/
|
|
15
|
+
export const getRegionId = (region: Region): string => {
|
|
16
|
+
return region.id || region.name;
|
|
17
|
+
};
|
|
@@ -28,7 +28,7 @@ export interface UseBlocksEngineReturn {
|
|
|
28
28
|
blockType: string,
|
|
29
29
|
options?: {
|
|
30
30
|
parentId?: string;
|
|
31
|
-
|
|
31
|
+
regionId?: string;
|
|
32
32
|
index?: number;
|
|
33
33
|
}
|
|
34
34
|
) => string;
|
|
@@ -37,7 +37,7 @@ export interface UseBlocksEngineReturn {
|
|
|
37
37
|
presetIndex: number,
|
|
38
38
|
options?: {
|
|
39
39
|
parentId?: string;
|
|
40
|
-
|
|
40
|
+
regionId?: string;
|
|
41
41
|
index?: number;
|
|
42
42
|
}
|
|
43
43
|
) => string;
|
|
@@ -47,7 +47,7 @@ export interface UseBlocksEngineReturn {
|
|
|
47
47
|
options: {
|
|
48
48
|
targetParentId?: string;
|
|
49
49
|
targetIndex?: number;
|
|
50
|
-
|
|
50
|
+
targetRegionId?: string;
|
|
51
51
|
}
|
|
52
52
|
) => void;
|
|
53
53
|
setBlockProperty: (blockId: string, propertyKey: string, propertyValue: any) => void;
|
|
@@ -58,7 +58,7 @@ export interface UseBlocksEngineReturn {
|
|
|
58
58
|
structure: BlockStructure,
|
|
59
59
|
options?: {
|
|
60
60
|
parentId?: string;
|
|
61
|
-
|
|
61
|
+
regionId?: string;
|
|
62
62
|
index?: number;
|
|
63
63
|
}
|
|
64
64
|
) => string;
|
|
@@ -195,7 +195,7 @@ export function useBlocksEngine(
|
|
|
195
195
|
blockType: string,
|
|
196
196
|
options?: {
|
|
197
197
|
parentId?: string;
|
|
198
|
-
|
|
198
|
+
regionId?: string;
|
|
199
199
|
index?: number;
|
|
200
200
|
}
|
|
201
201
|
): string => {
|
|
@@ -213,7 +213,7 @@ export function useBlocksEngine(
|
|
|
213
213
|
presetIndex: number,
|
|
214
214
|
options?: {
|
|
215
215
|
parentId?: string;
|
|
216
|
-
|
|
216
|
+
regionId?: string;
|
|
217
217
|
index?: number;
|
|
218
218
|
}
|
|
219
219
|
): string => {
|
|
@@ -239,7 +239,7 @@ export function useBlocksEngine(
|
|
|
239
239
|
options: {
|
|
240
240
|
targetParentId?: string;
|
|
241
241
|
targetIndex?: number;
|
|
242
|
-
|
|
242
|
+
targetRegionId?: string;
|
|
243
243
|
}
|
|
244
244
|
): void => {
|
|
245
245
|
engine.moveBlock(blockId, options);
|
|
@@ -287,7 +287,7 @@ export function useBlocksEngine(
|
|
|
287
287
|
structure: BlockStructure,
|
|
288
288
|
options?: {
|
|
289
289
|
parentId?: string;
|
|
290
|
-
|
|
290
|
+
regionId?: string;
|
|
291
291
|
index?: number;
|
|
292
292
|
}
|
|
293
293
|
): string => {
|