eventmodeler 0.6.13 → 0.6.14
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/index.js +225 -135
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -2630,6 +2630,7 @@ var ELEMENT_DIMENSIONS = {
|
|
|
2630
2630
|
aggregate: { width: 300, height: 200 },
|
|
2631
2631
|
actor: { width: 300, height: 200 },
|
|
2632
2632
|
chapter: { width: 800, height: 1200 },
|
|
2633
|
+
sheet: { width: 800, height: 1200 },
|
|
2633
2634
|
note: { width: 200, height: 150 },
|
|
2634
2635
|
externalEvent: { width: 160, height: 100 },
|
|
2635
2636
|
context: { width: 300, height: 200 },
|
|
@@ -2834,6 +2835,7 @@ var SliceSchema = baseContainer("sliceId").extend({
|
|
|
2834
2835
|
var AggregateSchema = baseContainer("aggregateId");
|
|
2835
2836
|
var ActorSchema = baseContainer("actorId");
|
|
2836
2837
|
var ChapterSchema = baseContainer("chapterId");
|
|
2838
|
+
var SheetSchema = baseContainer("sheetId");
|
|
2837
2839
|
var ContextSchema = baseContainer("contextId");
|
|
2838
2840
|
var LaneKindSchema = z.enum(["actor", "interaction", "swimlane", "specification"]);
|
|
2839
2841
|
var SwimLaneSchema = baseContainer("swimLaneId").extend({
|
|
@@ -2937,9 +2939,9 @@ var FlowSchema = z.object({
|
|
|
2937
2939
|
var SheetFlowSchema = z.object({
|
|
2938
2940
|
sheetFlowId: z.string().uuid().optional(),
|
|
2939
2941
|
modelId: z.string().uuid().optional(),
|
|
2940
|
-
|
|
2942
|
+
sourceSheetId: z.string().uuid(),
|
|
2941
2943
|
sourceHandle: z.string().min(1),
|
|
2942
|
-
|
|
2944
|
+
targetSheetId: z.string().uuid(),
|
|
2943
2945
|
targetHandle: z.string().min(1)
|
|
2944
2946
|
});
|
|
2945
2947
|
var CellRefSchema = z.object({
|
|
@@ -2958,6 +2960,7 @@ var SheetStructureSchema = z.object({
|
|
|
2958
2960
|
columns: z.array(z.string().uuid()),
|
|
2959
2961
|
rows: z.array(z.string().uuid()),
|
|
2960
2962
|
cells: z.record(z.string(), z.array(CellRefSchema)),
|
|
2963
|
+
columnSlices: z.record(z.string(), z.string().uuid()).optional(),
|
|
2961
2964
|
cellNotes: z.record(z.string(), z.string()).optional()
|
|
2962
2965
|
});
|
|
2963
2966
|
var SCOPE_SCHEMAS = {
|
|
@@ -2971,6 +2974,7 @@ var SCOPE_SCHEMAS = {
|
|
|
2971
2974
|
aggregates: AggregateSchema,
|
|
2972
2975
|
actors: ActorSchema,
|
|
2973
2976
|
chapters: ChapterSchema,
|
|
2977
|
+
sheets: SheetSchema,
|
|
2974
2978
|
contexts: ContextSchema,
|
|
2975
2979
|
swimLanes: SwimLaneSchema,
|
|
2976
2980
|
notes: NoteSchema,
|
|
@@ -3005,36 +3009,49 @@ var GRID_SCOPE = "grid";
|
|
|
3005
3009
|
function getGridMap(doc) {
|
|
3006
3010
|
return doc.getMap(GRID_SCOPE);
|
|
3007
3011
|
}
|
|
3008
|
-
function cellKey(
|
|
3009
|
-
return `${
|
|
3012
|
+
function cellKey(columnId, swimLaneId) {
|
|
3013
|
+
return `${columnId}:${swimLaneId}`;
|
|
3010
3014
|
}
|
|
3011
|
-
function resolveSheet(doc,
|
|
3015
|
+
function resolveSheet(doc, sheetId) {
|
|
3012
3016
|
const grid = getGridMap(doc);
|
|
3013
|
-
let sheet = grid.get(
|
|
3017
|
+
let sheet = grid.get(sheetId);
|
|
3014
3018
|
if (!sheet) {
|
|
3015
3019
|
sheet = new Y6.Map;
|
|
3016
3020
|
sheet.set("columns", new Y6.Array);
|
|
3017
3021
|
sheet.set("rows", new Y6.Array);
|
|
3018
3022
|
sheet.set("cells", new Y6.Map);
|
|
3019
|
-
|
|
3023
|
+
sheet.set("columnSlices", new Y6.Map);
|
|
3024
|
+
grid.set(sheetId, sheet);
|
|
3025
|
+
}
|
|
3026
|
+
let columnSlices = sheet.get("columnSlices");
|
|
3027
|
+
if (!columnSlices) {
|
|
3028
|
+
columnSlices = new Y6.Map;
|
|
3029
|
+
sheet.set("columnSlices", columnSlices);
|
|
3020
3030
|
}
|
|
3021
3031
|
return {
|
|
3022
3032
|
sheet,
|
|
3023
3033
|
columns: sheet.get("columns"),
|
|
3024
3034
|
rows: sheet.get("rows"),
|
|
3025
|
-
cells: sheet.get("cells")
|
|
3035
|
+
cells: sheet.get("cells"),
|
|
3036
|
+
columnSlices
|
|
3026
3037
|
};
|
|
3027
3038
|
}
|
|
3028
|
-
function ensureSheet(doc,
|
|
3039
|
+
function ensureSheet(doc, sheetId) {
|
|
3029
3040
|
doc.transact(() => {
|
|
3030
|
-
resolveSheet(doc,
|
|
3041
|
+
resolveSheet(doc, sheetId);
|
|
3031
3042
|
});
|
|
3032
3043
|
}
|
|
3033
|
-
function readSheet(doc,
|
|
3034
|
-
const sheet = getGridMap(doc).get(
|
|
3044
|
+
function readSheet(doc, sheetId) {
|
|
3045
|
+
const sheet = getGridMap(doc).get(sheetId);
|
|
3035
3046
|
if (!sheet)
|
|
3036
3047
|
return;
|
|
3037
|
-
|
|
3048
|
+
const json = sheet.toJSON();
|
|
3049
|
+
const columns = json.columns ?? [];
|
|
3050
|
+
const columnSlices = { ...json.columnSlices ?? {} };
|
|
3051
|
+
for (const c of columns)
|
|
3052
|
+
if (!(c in columnSlices))
|
|
3053
|
+
columnSlices[c] = c;
|
|
3054
|
+
return { ...json, columns, columnSlices };
|
|
3038
3055
|
}
|
|
3039
3056
|
function clampIndex(at, length) {
|
|
3040
3057
|
if (at === undefined || at > length)
|
|
@@ -3046,52 +3063,66 @@ function insertUnique(arr, value, at) {
|
|
|
3046
3063
|
return;
|
|
3047
3064
|
arr.insert(clampIndex(at, arr.length), [value]);
|
|
3048
3065
|
}
|
|
3049
|
-
function addColumn(doc,
|
|
3066
|
+
function addColumn(doc, sheetId, sliceId, at) {
|
|
3050
3067
|
doc.transact(() => {
|
|
3051
|
-
const { columns } = resolveSheet(doc,
|
|
3052
|
-
|
|
3068
|
+
const { columns, columnSlices } = resolveSheet(doc, sheetId);
|
|
3069
|
+
if (columns.toArray().includes(sliceId))
|
|
3070
|
+
return;
|
|
3071
|
+
columns.insert(clampIndex(at, columns.length), [sliceId]);
|
|
3072
|
+
columnSlices.set(sliceId, sliceId);
|
|
3053
3073
|
});
|
|
3054
3074
|
}
|
|
3055
|
-
function moveColumn(doc,
|
|
3075
|
+
function moveColumn(doc, sheetId, columnId, toIndex) {
|
|
3056
3076
|
doc.transact(() => {
|
|
3057
|
-
const { columns } = resolveSheet(doc,
|
|
3058
|
-
const from = columns.toArray().indexOf(
|
|
3077
|
+
const { columns } = resolveSheet(doc, sheetId);
|
|
3078
|
+
const from = columns.toArray().indexOf(columnId);
|
|
3059
3079
|
if (from === -1)
|
|
3060
3080
|
return;
|
|
3061
3081
|
columns.delete(from, 1);
|
|
3062
|
-
columns.insert(clampIndex(toIndex, columns.length), [
|
|
3082
|
+
columns.insert(clampIndex(toIndex, columns.length), [columnId]);
|
|
3063
3083
|
});
|
|
3064
3084
|
}
|
|
3065
|
-
function removeColumn(doc,
|
|
3085
|
+
function removeColumn(doc, sheetId, columnId) {
|
|
3066
3086
|
doc.transact(() => {
|
|
3067
|
-
const sheet = getGridMap(doc).get(
|
|
3087
|
+
const sheet = getGridMap(doc).get(sheetId);
|
|
3068
3088
|
if (!sheet)
|
|
3069
3089
|
return;
|
|
3070
3090
|
const columns = sheet.get("columns");
|
|
3071
3091
|
const cells = sheet.get("cells");
|
|
3072
3092
|
const cellNotes = sheet.get("cellNotes");
|
|
3073
|
-
const
|
|
3093
|
+
const columnSlices = sheet.get("columnSlices");
|
|
3094
|
+
const idx = columns.toArray().indexOf(columnId);
|
|
3074
3095
|
if (idx !== -1)
|
|
3075
3096
|
columns.delete(idx, 1);
|
|
3097
|
+
columnSlices?.delete(columnId);
|
|
3076
3098
|
for (const key of [...cells.keys()]) {
|
|
3077
|
-
if (key.startsWith(`${
|
|
3099
|
+
if (key.startsWith(`${columnId}:`))
|
|
3078
3100
|
cells.delete(key);
|
|
3079
3101
|
}
|
|
3080
3102
|
for (const key of [...cellNotes?.keys() ?? []]) {
|
|
3081
|
-
if (key.startsWith(`${
|
|
3103
|
+
if (key.startsWith(`${columnId}:`))
|
|
3082
3104
|
cellNotes.delete(key);
|
|
3083
3105
|
}
|
|
3084
3106
|
});
|
|
3085
3107
|
}
|
|
3086
|
-
function
|
|
3108
|
+
function ensureColumnSlices(doc, sheetId) {
|
|
3087
3109
|
doc.transact(() => {
|
|
3088
|
-
const {
|
|
3110
|
+
const { columns, columnSlices } = resolveSheet(doc, sheetId);
|
|
3111
|
+
for (const columnId of columns.toArray()) {
|
|
3112
|
+
if (!columnSlices.has(columnId))
|
|
3113
|
+
columnSlices.set(columnId, columnId);
|
|
3114
|
+
}
|
|
3115
|
+
});
|
|
3116
|
+
}
|
|
3117
|
+
function addRow(doc, sheetId, swimLaneId, at) {
|
|
3118
|
+
doc.transact(() => {
|
|
3119
|
+
const { rows } = resolveSheet(doc, sheetId);
|
|
3089
3120
|
insertUnique(rows, swimLaneId, at);
|
|
3090
3121
|
});
|
|
3091
3122
|
}
|
|
3092
|
-
function moveRow(doc,
|
|
3123
|
+
function moveRow(doc, sheetId, swimLaneId, toIndex) {
|
|
3093
3124
|
doc.transact(() => {
|
|
3094
|
-
const { rows } = resolveSheet(doc,
|
|
3125
|
+
const { rows } = resolveSheet(doc, sheetId);
|
|
3095
3126
|
const from = rows.toArray().indexOf(swimLaneId);
|
|
3096
3127
|
if (from === -1)
|
|
3097
3128
|
return;
|
|
@@ -3099,9 +3130,9 @@ function moveRow(doc, chapterId, swimLaneId, toIndex) {
|
|
|
3099
3130
|
rows.insert(clampIndex(toIndex, rows.length), [swimLaneId]);
|
|
3100
3131
|
});
|
|
3101
3132
|
}
|
|
3102
|
-
function removeRow(doc,
|
|
3133
|
+
function removeRow(doc, sheetId, swimLaneId) {
|
|
3103
3134
|
doc.transact(() => {
|
|
3104
|
-
const sheet = getGridMap(doc).get(
|
|
3135
|
+
const sheet = getGridMap(doc).get(sheetId);
|
|
3105
3136
|
if (!sheet)
|
|
3106
3137
|
return;
|
|
3107
3138
|
const rows = sheet.get("rows");
|
|
@@ -3137,9 +3168,9 @@ function findStickyCell(cells, stickyId) {
|
|
|
3137
3168
|
}
|
|
3138
3169
|
return;
|
|
3139
3170
|
}
|
|
3140
|
-
function placeInCell(doc,
|
|
3171
|
+
function placeInCell(doc, sheetId, sliceId, swimLaneId, ref, at) {
|
|
3141
3172
|
doc.transact(() => {
|
|
3142
|
-
const { cells } = resolveSheet(doc,
|
|
3173
|
+
const { cells } = resolveSheet(doc, sheetId);
|
|
3143
3174
|
const existing = findStickyCell(cells, ref.stickyId);
|
|
3144
3175
|
if (existing)
|
|
3145
3176
|
cells.get(existing.key).delete(existing.index, 1);
|
|
@@ -3154,9 +3185,9 @@ function placeInCell(doc, chapterId, sliceId, swimLaneId, ref, at) {
|
|
|
3154
3185
|
]);
|
|
3155
3186
|
});
|
|
3156
3187
|
}
|
|
3157
|
-
function removeSticky(doc,
|
|
3188
|
+
function removeSticky(doc, sheetId, stickyId) {
|
|
3158
3189
|
doc.transact(() => {
|
|
3159
|
-
const sheet = getGridMap(doc).get(
|
|
3190
|
+
const sheet = getGridMap(doc).get(sheetId);
|
|
3160
3191
|
if (!sheet)
|
|
3161
3192
|
return;
|
|
3162
3193
|
const cells = sheet.get("cells");
|
|
@@ -3166,13 +3197,13 @@ function removeSticky(doc, chapterId, stickyId) {
|
|
|
3166
3197
|
cells.get(loc.key).delete(loc.index, 1);
|
|
3167
3198
|
});
|
|
3168
3199
|
}
|
|
3169
|
-
function removeSheet(doc,
|
|
3200
|
+
function removeSheet(doc, sheetId) {
|
|
3170
3201
|
doc.transact(() => {
|
|
3171
|
-
getGridMap(doc).delete(
|
|
3202
|
+
getGridMap(doc).delete(sheetId);
|
|
3172
3203
|
});
|
|
3173
3204
|
}
|
|
3174
|
-
function getCellNotesMap(doc,
|
|
3175
|
-
const sheet = getGridMap(doc).get(
|
|
3205
|
+
function getCellNotesMap(doc, sheetId, create) {
|
|
3206
|
+
const sheet = getGridMap(doc).get(sheetId);
|
|
3176
3207
|
if (!sheet)
|
|
3177
3208
|
return;
|
|
3178
3209
|
let notes = sheet.get("cellNotes");
|
|
@@ -3182,30 +3213,61 @@ function getCellNotesMap(doc, chapterId, create) {
|
|
|
3182
3213
|
}
|
|
3183
3214
|
return notes;
|
|
3184
3215
|
}
|
|
3185
|
-
function readCellNotes(doc,
|
|
3186
|
-
const notes = getGridMap(doc).get(
|
|
3216
|
+
function readCellNotes(doc, sheetId) {
|
|
3217
|
+
const notes = getGridMap(doc).get(sheetId)?.get("cellNotes");
|
|
3187
3218
|
return notes ? notes.toJSON() : {};
|
|
3188
3219
|
}
|
|
3189
|
-
function setCellNote(doc,
|
|
3220
|
+
function setCellNote(doc, sheetId, sliceId, swimLaneId, text) {
|
|
3190
3221
|
doc.transact(() => {
|
|
3191
3222
|
const key = cellKey(sliceId, swimLaneId);
|
|
3192
3223
|
const trimmed = text.trim();
|
|
3193
3224
|
if (!trimmed) {
|
|
3194
|
-
getCellNotesMap(doc,
|
|
3225
|
+
getCellNotesMap(doc, sheetId, false)?.delete(key);
|
|
3195
3226
|
return;
|
|
3196
3227
|
}
|
|
3197
|
-
getCellNotesMap(doc,
|
|
3228
|
+
getCellNotesMap(doc, sheetId, true).set(key, trimmed);
|
|
3229
|
+
});
|
|
3230
|
+
}
|
|
3231
|
+
// ../packages/canvas-model/src/migrate.ts
|
|
3232
|
+
function migrateChaptersToSheets(doc) {
|
|
3233
|
+
const chapters = getScopeMap(doc, "chapters");
|
|
3234
|
+
const sheets = getScopeMap(doc, "sheets");
|
|
3235
|
+
const sheetFlows = getScopeMap(doc, "sheetFlows");
|
|
3236
|
+
const needsEntityMove = sheets.size === 0 && chapters.size > 0;
|
|
3237
|
+
const needsFlowRename = [...sheetFlows.values()].some((f) => f.has("sourceChapterId") || f.has("targetChapterId"));
|
|
3238
|
+
if (!needsEntityMove && !needsFlowRename)
|
|
3239
|
+
return;
|
|
3240
|
+
doc.transact(() => {
|
|
3241
|
+
if (needsEntityMove) {
|
|
3242
|
+
for (const [id, ch] of [...chapters.entries()]) {
|
|
3243
|
+
const json = ch.toJSON();
|
|
3244
|
+
delete json.chapterId;
|
|
3245
|
+
json.sheetId = id;
|
|
3246
|
+
sheets.set(id, deepToY(json));
|
|
3247
|
+
chapters.delete(id);
|
|
3248
|
+
}
|
|
3249
|
+
}
|
|
3250
|
+
for (const f of sheetFlows.values()) {
|
|
3251
|
+
if (f.has("sourceChapterId")) {
|
|
3252
|
+
f.set("sourceSheetId", f.get("sourceChapterId"));
|
|
3253
|
+
f.delete("sourceChapterId");
|
|
3254
|
+
}
|
|
3255
|
+
if (f.has("targetChapterId")) {
|
|
3256
|
+
f.set("targetSheetId", f.get("targetChapterId"));
|
|
3257
|
+
f.delete("targetChapterId");
|
|
3258
|
+
}
|
|
3259
|
+
}
|
|
3198
3260
|
});
|
|
3199
3261
|
}
|
|
3200
3262
|
// ../packages/canvas-model/src/sheet-delete.ts
|
|
3201
|
-
var
|
|
3263
|
+
var SHEETS_SCOPE = "sheets";
|
|
3202
3264
|
var SLICES_SCOPE2 = "slices";
|
|
3203
3265
|
var SWIM_LANES_SCOPE = "swimLanes";
|
|
3204
3266
|
var SCENARIOS_SCOPE2 = "scenarios";
|
|
3205
3267
|
var SHEET_FLOWS_SCOPE = "sheetFlows";
|
|
3206
|
-
function deleteSheet(doc,
|
|
3268
|
+
function deleteSheet(doc, sheetId) {
|
|
3207
3269
|
doc.transact(() => {
|
|
3208
|
-
const sheet = getGridMap(doc).get(
|
|
3270
|
+
const sheet = getGridMap(doc).get(sheetId);
|
|
3209
3271
|
const removedStickies = new Set;
|
|
3210
3272
|
const sliceIds = new Set;
|
|
3211
3273
|
const laneIds = new Set;
|
|
@@ -3237,12 +3299,12 @@ function deleteSheet(doc, chapterId) {
|
|
|
3237
3299
|
cascadeStickyRemoval(doc, removedStickies);
|
|
3238
3300
|
const sheetFlows = getScopeMap(doc, SHEET_FLOWS_SCOPE);
|
|
3239
3301
|
for (const [id, f] of sheetFlows.entries()) {
|
|
3240
|
-
if (f.get("
|
|
3302
|
+
if (f.get("sourceSheetId") === sheetId || f.get("targetSheetId") === sheetId) {
|
|
3241
3303
|
sheetFlows.delete(id);
|
|
3242
3304
|
}
|
|
3243
3305
|
}
|
|
3244
|
-
removeSheet(doc,
|
|
3245
|
-
getScopeMap(doc,
|
|
3306
|
+
removeSheet(doc, sheetId);
|
|
3307
|
+
getScopeMap(doc, SHEETS_SCOPE).delete(sheetId);
|
|
3246
3308
|
});
|
|
3247
3309
|
}
|
|
3248
3310
|
// ../packages/canvas-model/src/sheet-layout.ts
|
|
@@ -3295,8 +3357,8 @@ function cellContentSize(refs) {
|
|
|
3295
3357
|
});
|
|
3296
3358
|
return { width, height };
|
|
3297
3359
|
}
|
|
3298
|
-
function pruneOrphanCellRefs(doc,
|
|
3299
|
-
const sheet = getGridMap(doc).get(
|
|
3360
|
+
function pruneOrphanCellRefs(doc, sheetId) {
|
|
3361
|
+
const sheet = getGridMap(doc).get(sheetId);
|
|
3300
3362
|
if (!sheet)
|
|
3301
3363
|
return 0;
|
|
3302
3364
|
const cells = sheet.get("cells");
|
|
@@ -3315,19 +3377,21 @@ function pruneOrphanCellRefs(doc, chapterId) {
|
|
|
3315
3377
|
}
|
|
3316
3378
|
return pruned;
|
|
3317
3379
|
}
|
|
3318
|
-
function computeSheetLayout(doc,
|
|
3319
|
-
const structure = readSheet(doc,
|
|
3380
|
+
function computeSheetLayout(doc, sheetId, override) {
|
|
3381
|
+
const structure = readSheet(doc, sheetId);
|
|
3320
3382
|
if (!structure)
|
|
3321
3383
|
return;
|
|
3322
|
-
const
|
|
3323
|
-
const originX = snap(
|
|
3324
|
-
const originY = snap(
|
|
3384
|
+
const sheet = getEntry(doc, "sheets", sheetId);
|
|
3385
|
+
const originX = snap(sheet?.x ?? 0);
|
|
3386
|
+
const originY = snap(sheet?.y ?? 0);
|
|
3325
3387
|
const { columns, rows } = structure;
|
|
3388
|
+
const columnSlices = structure.columnSlices ?? {};
|
|
3389
|
+
const ownerOf = (columnId) => columnSlices[columnId] ?? columnId;
|
|
3326
3390
|
const cells = override ? applyLayoutOverride(structure.cells, override) : structure.cells;
|
|
3327
|
-
const colWidths = columns.map((
|
|
3391
|
+
const colWidths = columns.map((columnId) => {
|
|
3328
3392
|
let w = 0;
|
|
3329
3393
|
for (const swimLaneId of rows) {
|
|
3330
|
-
const refs = cells[cellKey(
|
|
3394
|
+
const refs = cells[cellKey(columnId, swimLaneId)] ?? [];
|
|
3331
3395
|
const c = cellContentSize(refs);
|
|
3332
3396
|
if (c.width > 0)
|
|
3333
3397
|
w = Math.max(w, c.width + SHEET_LAYOUT.cellPadX * 2);
|
|
@@ -3336,8 +3400,8 @@ function computeSheetLayout(doc, chapterId, override) {
|
|
|
3336
3400
|
});
|
|
3337
3401
|
const rowHeights = rows.map((swimLaneId) => {
|
|
3338
3402
|
let h = 0;
|
|
3339
|
-
for (const
|
|
3340
|
-
const refs = cells[cellKey(
|
|
3403
|
+
for (const columnId of columns) {
|
|
3404
|
+
const refs = cells[cellKey(columnId, swimLaneId)] ?? [];
|
|
3341
3405
|
const c = cellContentSize(refs);
|
|
3342
3406
|
if (c.height > 0)
|
|
3343
3407
|
h = Math.max(h, c.height + SHEET_LAYOUT.cellPadY * 2);
|
|
@@ -3358,14 +3422,33 @@ function computeSheetLayout(doc, chapterId, override) {
|
|
|
3358
3422
|
});
|
|
3359
3423
|
const gridWidth = SHEET_LAYOUT.headerLeft + colWidths.reduce((a, b) => a + b, 0);
|
|
3360
3424
|
const gridHeight = SHEET_LAYOUT.headerTop + rowHeights.reduce((a, b) => a + b, 0);
|
|
3361
|
-
const columnLayouts = columns.map((
|
|
3362
|
-
|
|
3425
|
+
const columnLayouts = columns.map((columnId, i) => ({
|
|
3426
|
+
columnId,
|
|
3427
|
+
sliceId: ownerOf(columnId),
|
|
3363
3428
|
index: i,
|
|
3364
3429
|
x: colX[i],
|
|
3365
3430
|
y: originY,
|
|
3366
3431
|
width: colWidths[i],
|
|
3367
3432
|
height: gridHeight
|
|
3368
3433
|
}));
|
|
3434
|
+
const sliceLayouts = [];
|
|
3435
|
+
for (const col of columnLayouts) {
|
|
3436
|
+
const last = sliceLayouts[sliceLayouts.length - 1];
|
|
3437
|
+
if (last && last.sliceId === col.sliceId) {
|
|
3438
|
+
last.columnIds.push(col.columnId);
|
|
3439
|
+
last.width += col.width;
|
|
3440
|
+
} else {
|
|
3441
|
+
sliceLayouts.push({
|
|
3442
|
+
sliceId: col.sliceId,
|
|
3443
|
+
columnIds: [col.columnId],
|
|
3444
|
+
index: sliceLayouts.length,
|
|
3445
|
+
x: col.x,
|
|
3446
|
+
y: originY,
|
|
3447
|
+
width: col.width,
|
|
3448
|
+
height: gridHeight
|
|
3449
|
+
});
|
|
3450
|
+
}
|
|
3451
|
+
}
|
|
3369
3452
|
const rowLayouts = rows.map((swimLaneId, i) => ({
|
|
3370
3453
|
swimLaneId,
|
|
3371
3454
|
index: i,
|
|
@@ -3375,9 +3458,10 @@ function computeSheetLayout(doc, chapterId, override) {
|
|
|
3375
3458
|
height: rowHeights[i]
|
|
3376
3459
|
}));
|
|
3377
3460
|
const stickies = [];
|
|
3378
|
-
columns.forEach((
|
|
3461
|
+
columns.forEach((columnId, ci) => {
|
|
3462
|
+
const sliceId = ownerOf(columnId);
|
|
3379
3463
|
rows.forEach((swimLaneId, ri) => {
|
|
3380
|
-
const refs = cells[cellKey(
|
|
3464
|
+
const refs = cells[cellKey(columnId, swimLaneId)] ?? [];
|
|
3381
3465
|
if (refs.length === 0)
|
|
3382
3466
|
return;
|
|
3383
3467
|
const content = cellContentSize(refs);
|
|
@@ -3392,6 +3476,7 @@ function computeSheetLayout(doc, chapterId, override) {
|
|
|
3392
3476
|
stickies.push({
|
|
3393
3477
|
stickyId: ref.stickyId,
|
|
3394
3478
|
scope: ref.scope,
|
|
3479
|
+
columnId,
|
|
3395
3480
|
sliceId,
|
|
3396
3481
|
swimLaneId,
|
|
3397
3482
|
x: Math.round(midX - size.width / 2),
|
|
@@ -3408,6 +3493,7 @@ function computeSheetLayout(doc, chapterId, override) {
|
|
|
3408
3493
|
stickies.push({
|
|
3409
3494
|
stickyId: ref.stickyId,
|
|
3410
3495
|
scope: ref.scope,
|
|
3496
|
+
columnId,
|
|
3411
3497
|
sliceId,
|
|
3412
3498
|
swimLaneId,
|
|
3413
3499
|
x: Math.round(cursorX),
|
|
@@ -3421,16 +3507,17 @@ function computeSheetLayout(doc, chapterId, override) {
|
|
|
3421
3507
|
});
|
|
3422
3508
|
});
|
|
3423
3509
|
return {
|
|
3424
|
-
|
|
3425
|
-
|
|
3510
|
+
sheetId,
|
|
3511
|
+
sheet: { x: originX, y: originY, width: gridWidth, height: gridHeight },
|
|
3426
3512
|
columns: columnLayouts,
|
|
3513
|
+
slices: sliceLayouts,
|
|
3427
3514
|
rows: rowLayouts,
|
|
3428
3515
|
stickies
|
|
3429
3516
|
};
|
|
3430
3517
|
}
|
|
3431
3518
|
// ../packages/canvas-model/src/reflow.ts
|
|
3432
3519
|
var REFLOW_ORIGIN = Symbol("sheet-reflow");
|
|
3433
|
-
var
|
|
3520
|
+
var SHEETS_SCOPE2 = "sheets";
|
|
3434
3521
|
var SLICES_SCOPE3 = "slices";
|
|
3435
3522
|
var SWIM_LANES_SCOPE2 = "swimLanes";
|
|
3436
3523
|
var STICKY_SCOPES = [
|
|
@@ -3457,27 +3544,30 @@ function applyBox(m, box, size = true) {
|
|
|
3457
3544
|
}
|
|
3458
3545
|
}
|
|
3459
3546
|
function reflowAllSheets(doc, origin = REFLOW_ORIGIN) {
|
|
3460
|
-
|
|
3461
|
-
|
|
3547
|
+
migrateChaptersToSheets(doc);
|
|
3548
|
+
const sheets = getScopeMap(doc, SHEETS_SCOPE2);
|
|
3549
|
+
if (sheets.size === 0)
|
|
3462
3550
|
return;
|
|
3463
3551
|
doc.transact(() => {
|
|
3464
|
-
for (const
|
|
3465
|
-
ensureSheet(doc,
|
|
3552
|
+
for (const sheetId of sheets.keys()) {
|
|
3553
|
+
ensureSheet(doc, sheetId);
|
|
3554
|
+
ensureColumnSlices(doc, sheetId);
|
|
3555
|
+
}
|
|
3466
3556
|
const slices = getScopeMap(doc, SLICES_SCOPE3);
|
|
3467
3557
|
const lanes = getScopeMap(doc, SWIM_LANES_SCOPE2);
|
|
3468
3558
|
const stickyMaps = STICKY_SCOPES.map((s) => getScopeMap(doc, s));
|
|
3469
|
-
for (const
|
|
3470
|
-
pruneOrphanCellRefs(doc,
|
|
3471
|
-
const layout = computeSheetLayout(doc,
|
|
3559
|
+
for (const sheetId of getGridMap(doc).keys()) {
|
|
3560
|
+
pruneOrphanCellRefs(doc, sheetId);
|
|
3561
|
+
const layout = computeSheetLayout(doc, sheetId);
|
|
3472
3562
|
if (!layout)
|
|
3473
3563
|
continue;
|
|
3474
|
-
const ch =
|
|
3564
|
+
const ch = sheets.get(sheetId);
|
|
3475
3565
|
if (ch) {
|
|
3476
|
-
setIfChanged(ch, "width", layout.
|
|
3477
|
-
setIfChanged(ch, "height", layout.
|
|
3566
|
+
setIfChanged(ch, "width", layout.sheet.width);
|
|
3567
|
+
setIfChanged(ch, "height", layout.sheet.height);
|
|
3478
3568
|
}
|
|
3479
|
-
for (const
|
|
3480
|
-
applyBox(slices.get(
|
|
3569
|
+
for (const band of layout.slices)
|
|
3570
|
+
applyBox(slices.get(band.sliceId), band);
|
|
3481
3571
|
for (const row of layout.rows)
|
|
3482
3572
|
applyBox(lanes.get(row.swimLaneId), row);
|
|
3483
3573
|
const scenarioOrder = new Map;
|
|
@@ -4937,12 +5027,12 @@ function pad(s, width) {
|
|
|
4937
5027
|
return s.length >= width ? s : s + " ".repeat(width - s.length);
|
|
4938
5028
|
}
|
|
4939
5029
|
var NOTE = "†";
|
|
4940
|
-
function resolve4(doc,
|
|
4941
|
-
const structure = readSheet(doc,
|
|
5030
|
+
function resolve4(doc, sheetId) {
|
|
5031
|
+
const structure = readSheet(doc, sheetId);
|
|
4942
5032
|
if (!structure)
|
|
4943
5033
|
return;
|
|
4944
5034
|
const { columns, rows, cells } = structure;
|
|
4945
|
-
const notes = readCellNotes(doc,
|
|
5035
|
+
const notes = readCellNotes(doc, sheetId);
|
|
4946
5036
|
const cols = columns.map((sliceId, i) => ({
|
|
4947
5037
|
label: colLabel(i),
|
|
4948
5038
|
name: entityName(doc, "slices", sliceId),
|
|
@@ -4955,7 +5045,7 @@ function resolve4(doc, chapterId) {
|
|
|
4955
5045
|
const elems = columns.map((sliceId) => rows.map((swimLaneId) => (cells[cellKey(sliceId, swimLaneId)] ?? []).map((r) => elementText(doc, r))));
|
|
4956
5046
|
const cellNote = columns.map((sliceId) => rows.map((swimLaneId) => Boolean(notes[cellKey(sliceId, swimLaneId)])));
|
|
4957
5047
|
return {
|
|
4958
|
-
title: entityName(doc, "
|
|
5048
|
+
title: entityName(doc, "sheets", sheetId),
|
|
4959
5049
|
columns: cols,
|
|
4960
5050
|
rows: lanes2,
|
|
4961
5051
|
elems,
|
|
@@ -5037,9 +5127,9 @@ function renderListing(r) {
|
|
|
5037
5127
|
return lines.join(`
|
|
5038
5128
|
`).trimEnd();
|
|
5039
5129
|
}
|
|
5040
|
-
function renderSheetOverview(doc,
|
|
5130
|
+
function renderSheetOverview(doc, sheetId, options = {}) {
|
|
5041
5131
|
const opts = { ...DEFAULTS, ...options };
|
|
5042
|
-
const r = resolve4(doc,
|
|
5132
|
+
const r = resolve4(doc, sheetId);
|
|
5043
5133
|
if (!r)
|
|
5044
5134
|
return;
|
|
5045
5135
|
if (r.empty)
|
|
@@ -5073,23 +5163,23 @@ function resolveSheet2(doc, ref) {
|
|
|
5073
5163
|
const ids = [...grid2.keys()];
|
|
5074
5164
|
if (ids.length === 0)
|
|
5075
5165
|
throw new SheetAddressError("This model has no sheets.");
|
|
5076
|
-
const done = (
|
|
5166
|
+
const done = (sheetId) => ({ sheetId, structure: readSheet(doc, sheetId) });
|
|
5077
5167
|
if (ref && grid2.has(ref))
|
|
5078
5168
|
return done(ref);
|
|
5079
5169
|
if (!ref) {
|
|
5080
5170
|
if (ids.length === 1)
|
|
5081
5171
|
return done(ids[0]);
|
|
5082
|
-
const list = ids.map((id) => `"${name(doc, "
|
|
5172
|
+
const list = ids.map((id) => `"${name(doc, "sheets", id)}"`).join(", ");
|
|
5083
5173
|
throw new SheetAddressError(`Multiple sheets — name one. Available: ${list}`);
|
|
5084
5174
|
}
|
|
5085
5175
|
const lower = ref.toLowerCase();
|
|
5086
|
-
const matches = ids.filter((id) => name(doc, "
|
|
5176
|
+
const matches = ids.filter((id) => name(doc, "sheets", id).toLowerCase() === lower);
|
|
5087
5177
|
if (matches.length === 0) {
|
|
5088
|
-
const list = ids.map((id) => `"${name(doc, "
|
|
5178
|
+
const list = ids.map((id) => `"${name(doc, "sheets", id)}"`).join(", ") || "(none)";
|
|
5089
5179
|
throw new SheetAddressError(`No sheet named "${ref}". Available: ${list}`);
|
|
5090
5180
|
}
|
|
5091
5181
|
if (matches.length > 1)
|
|
5092
|
-
throw new SheetAddressError(`Ambiguous sheet name "${ref}" — pass the
|
|
5182
|
+
throw new SheetAddressError(`Ambiguous sheet name "${ref}" — pass the sheetId instead.`);
|
|
5093
5183
|
return done(matches[0]);
|
|
5094
5184
|
}
|
|
5095
5185
|
function resolveColumn(doc, s, ref) {
|
|
@@ -5293,9 +5383,9 @@ function insertColumn(doc, s, modelId, name2, at) {
|
|
|
5293
5383
|
throw new SheetAddressError(`Invalid slice: ${v.issues.join("; ")}`);
|
|
5294
5384
|
doc.transact(() => {
|
|
5295
5385
|
getScopeMap(doc, "slices").set(id, deepToY({ ...v.data, sliceId: id, modelId }));
|
|
5296
|
-
addColumn(doc, s.
|
|
5386
|
+
addColumn(doc, s.sheetId, id, at);
|
|
5297
5387
|
});
|
|
5298
|
-
const idx = readSheet(doc, s.
|
|
5388
|
+
const idx = readSheet(doc, s.sheetId).columns.indexOf(id);
|
|
5299
5389
|
return `${colLabel2(idx)} "${name2}" ${id}`;
|
|
5300
5390
|
}
|
|
5301
5391
|
function insertLane(doc, s, modelId, kind, name2, at) {
|
|
@@ -5306,9 +5396,9 @@ function insertLane(doc, s, modelId, kind, name2, at) {
|
|
|
5306
5396
|
throw new SheetAddressError(`Invalid lane: ${v.issues.join("; ")}`);
|
|
5307
5397
|
doc.transact(() => {
|
|
5308
5398
|
getScopeMap(doc, "swimLanes").set(id, deepToY({ ...v.data, swimLaneId: id, modelId }));
|
|
5309
|
-
addRow(doc, s.
|
|
5399
|
+
addRow(doc, s.sheetId, id, at);
|
|
5310
5400
|
});
|
|
5311
|
-
const idx = readSheet(doc, s.
|
|
5401
|
+
const idx = readSheet(doc, s.sheetId).rows.indexOf(id);
|
|
5312
5402
|
return `${idx + 1} "${name2}" (${kind}) ${id}`;
|
|
5313
5403
|
}
|
|
5314
5404
|
function insertElement(doc, s, modelId, type, cellArg, nameOrJson) {
|
|
@@ -5337,7 +5427,7 @@ function insertElement(doc, s, modelId, type, cellArg, nameOrJson) {
|
|
|
5337
5427
|
};
|
|
5338
5428
|
doc.transact(() => {
|
|
5339
5429
|
getScopeMap(doc, "scenarios").set(id, deepToY(entry2));
|
|
5340
|
-
placeInCell(doc, s.
|
|
5430
|
+
placeInCell(doc, s.sheetId, cell.sliceId, cell.swimLaneId, { stickyId: id, scope: "scenarios" });
|
|
5341
5431
|
});
|
|
5342
5432
|
return addressOf(doc, s, cell.sliceId, cell.swimLaneId, id, cell.address);
|
|
5343
5433
|
}
|
|
@@ -5352,12 +5442,12 @@ function insertElement(doc, s, modelId, type, cellArg, nameOrJson) {
|
|
|
5352
5442
|
const final = { ...v.data, [meta.idKey]: id, modelId };
|
|
5353
5443
|
doc.transact(() => {
|
|
5354
5444
|
getScopeMap(doc, meta.scope).set(id, deepToY(final));
|
|
5355
|
-
placeInCell(doc, s.
|
|
5445
|
+
placeInCell(doc, s.sheetId, cell.sliceId, cell.swimLaneId, { stickyId: id, scope: meta.scope });
|
|
5356
5446
|
});
|
|
5357
5447
|
return addressOf(doc, s, cell.sliceId, cell.swimLaneId, id, cell.address);
|
|
5358
5448
|
}
|
|
5359
5449
|
function addressOf(doc, s, sliceId, swimLaneId, id, cellAddr) {
|
|
5360
|
-
const refs = readSheet(doc, s.
|
|
5450
|
+
const refs = readSheet(doc, s.sheetId).cells[cellKey(sliceId, swimLaneId)] ?? [];
|
|
5361
5451
|
const ord = refs.findIndex((r) => r.stickyId === id) + 1;
|
|
5362
5452
|
return `${cellAddr}.${ord} ${id}`;
|
|
5363
5453
|
}
|
|
@@ -5368,7 +5458,7 @@ function moveElement(doc, s, elAddr, toCell) {
|
|
|
5368
5458
|
if (!laneAllows(kind, el.scope))
|
|
5369
5459
|
rejectLane(doc, dest.swimLaneId, dest.rowIndex, kind, TYPE_LABEL[el.scope] ?? el.scope);
|
|
5370
5460
|
doc.transact(() => {
|
|
5371
|
-
placeInCell(doc, s.
|
|
5461
|
+
placeInCell(doc, s.sheetId, dest.sliceId, dest.swimLaneId, { stickyId: el.stickyId, scope: el.scope });
|
|
5372
5462
|
});
|
|
5373
5463
|
return addressOf(doc, s, dest.sliceId, dest.swimLaneId, el.stickyId, dest.address);
|
|
5374
5464
|
}
|
|
@@ -5376,14 +5466,14 @@ function reorderAxis(doc, s, ref, to) {
|
|
|
5376
5466
|
const toIndex = to - 1;
|
|
5377
5467
|
if (/^\d+$/.test(ref)) {
|
|
5378
5468
|
const row = resolveRow(doc, s, ref);
|
|
5379
|
-
doc.transact(() => moveRow(doc, s.
|
|
5380
|
-
const idx = readSheet(doc, s.
|
|
5469
|
+
doc.transact(() => moveRow(doc, s.sheetId, row.swimLaneId, toIndex));
|
|
5470
|
+
const idx = readSheet(doc, s.sheetId).rows.indexOf(row.swimLaneId);
|
|
5381
5471
|
return `row → ${idx + 1}`;
|
|
5382
5472
|
}
|
|
5383
5473
|
if (colIndexFromLabel(ref) >= 0 || s.structure.columns.length > 0) {
|
|
5384
5474
|
const col = resolveColumn(doc, s, ref);
|
|
5385
|
-
doc.transact(() => moveColumn(doc, s.
|
|
5386
|
-
const idx = readSheet(doc, s.
|
|
5475
|
+
doc.transact(() => moveColumn(doc, s.sheetId, col.sliceId, toIndex));
|
|
5476
|
+
const idx = readSheet(doc, s.sheetId).columns.indexOf(col.sliceId);
|
|
5387
5477
|
return `column → ${colLabel2(idx)}`;
|
|
5388
5478
|
}
|
|
5389
5479
|
throw new SheetAddressError(`reorder takes a column letter (A) or row number (1), got "${ref}".`);
|
|
@@ -5392,7 +5482,7 @@ function removeTarget(doc, s, target) {
|
|
|
5392
5482
|
if (/^[A-Za-z]+\d+(\.\d+)?$/.test(target)) {
|
|
5393
5483
|
const el = resolveElement(doc, s, target);
|
|
5394
5484
|
doc.transact(() => {
|
|
5395
|
-
removeSticky(doc, s.
|
|
5485
|
+
removeSticky(doc, s.sheetId, el.stickyId);
|
|
5396
5486
|
getScopeMap(doc, el.scope).delete(el.stickyId);
|
|
5397
5487
|
cascadeStickyRemoval(doc, new Set([el.stickyId]));
|
|
5398
5488
|
});
|
|
@@ -5403,7 +5493,7 @@ function removeTarget(doc, s, target) {
|
|
|
5403
5493
|
const laneName = nameOf(doc, "swimLanes", row.swimLaneId);
|
|
5404
5494
|
const refs2 = s.structure.columns.flatMap((sliceId) => s.structure.cells[cellKey(sliceId, row.swimLaneId)] ?? []);
|
|
5405
5495
|
doc.transact(() => {
|
|
5406
|
-
removeRow(doc, s.
|
|
5496
|
+
removeRow(doc, s.sheetId, row.swimLaneId);
|
|
5407
5497
|
getScopeMap(doc, "swimLanes").delete(row.swimLaneId);
|
|
5408
5498
|
for (const r of refs2)
|
|
5409
5499
|
getScopeMap(doc, r.scope).delete(r.stickyId);
|
|
@@ -5415,7 +5505,7 @@ function removeTarget(doc, s, target) {
|
|
|
5415
5505
|
const sliceName = nameOf(doc, "slices", col.sliceId);
|
|
5416
5506
|
const refs = s.structure.rows.flatMap((swimLaneId) => s.structure.cells[cellKey(col.sliceId, swimLaneId)] ?? []);
|
|
5417
5507
|
doc.transact(() => {
|
|
5418
|
-
removeColumn(doc, s.
|
|
5508
|
+
removeColumn(doc, s.sheetId, col.sliceId);
|
|
5419
5509
|
getScopeMap(doc, "slices").delete(col.sliceId);
|
|
5420
5510
|
for (const r of refs)
|
|
5421
5511
|
getScopeMap(doc, r.scope).delete(r.stickyId);
|
|
@@ -5493,7 +5583,7 @@ function sheetEdgeHandle(side, dir) {
|
|
|
5493
5583
|
}
|
|
5494
5584
|
function resolveAnchor(doc, sheet, dir, col, side) {
|
|
5495
5585
|
const flag = dir === "source" ? "from" : "to";
|
|
5496
|
-
const sheetName = nameOf(doc, "
|
|
5586
|
+
const sheetName = nameOf(doc, "sheets", sheet.sheetId);
|
|
5497
5587
|
if (col !== undefined) {
|
|
5498
5588
|
const c = resolveColumn(doc, sheet, col);
|
|
5499
5589
|
const s2 = side ?? (dir === "source" ? "bottom" : "top");
|
|
@@ -5511,7 +5601,7 @@ function resolveAnchor(doc, sheet, dir, col, side) {
|
|
|
5511
5601
|
function connectSheets(doc, modelId, fromRef, toRef, opts) {
|
|
5512
5602
|
const src = resolveSheet2(doc, fromRef);
|
|
5513
5603
|
const dst = resolveSheet2(doc, toRef);
|
|
5514
|
-
if (src.
|
|
5604
|
+
if (src.sheetId === dst.sheetId) {
|
|
5515
5605
|
throw new SheetAddressError("Connect joins two different sheets — source and target are the same sheet.");
|
|
5516
5606
|
}
|
|
5517
5607
|
const from = resolveAnchor(doc, src, "source", opts.from, opts.fromSide);
|
|
@@ -5519,9 +5609,9 @@ function connectSheets(doc, modelId, fromRef, toRef, opts) {
|
|
|
5519
5609
|
const id = crypto.randomUUID();
|
|
5520
5610
|
const entry = {
|
|
5521
5611
|
sheetFlowId: id,
|
|
5522
|
-
|
|
5612
|
+
sourceSheetId: src.sheetId,
|
|
5523
5613
|
sourceHandle: from.handle,
|
|
5524
|
-
|
|
5614
|
+
targetSheetId: dst.sheetId,
|
|
5525
5615
|
targetHandle: to.handle
|
|
5526
5616
|
};
|
|
5527
5617
|
const v = validateEntry("sheetFlows", entry);
|
|
@@ -5554,7 +5644,7 @@ function copyElement(doc, s, modelId, srcAddr, toCell) {
|
|
|
5554
5644
|
const dim = FIXED_SIZE_DIM(src.scope);
|
|
5555
5645
|
doc.transact(() => {
|
|
5556
5646
|
getScopeMap(doc, src.scope).set(id, deepToY({ [meta.idKey]: id, modelId, name: "", x: 0, y: 0, width: dim.width, height: dim.height, isLinkedCopy: true, [meta.originalIdKey]: originalId }));
|
|
5557
|
-
placeInCell(doc, s.
|
|
5647
|
+
placeInCell(doc, s.sheetId, dest.sliceId, dest.swimLaneId, { stickyId: id, scope: src.scope });
|
|
5558
5648
|
});
|
|
5559
5649
|
return addressOf(doc, s, dest.sliceId, dest.swimLaneId, id, dest.address);
|
|
5560
5650
|
}
|
|
@@ -5584,7 +5674,7 @@ function noteTarget(doc, s, target, text) {
|
|
|
5584
5674
|
}
|
|
5585
5675
|
if (/^[A-Za-z]+\d+$/.test(target)) {
|
|
5586
5676
|
const cell = resolveCell(doc, s, target);
|
|
5587
|
-
setCellNote(doc, s.
|
|
5677
|
+
setCellNote(doc, s.sheetId, cell.sliceId, cell.swimLaneId, t);
|
|
5588
5678
|
return `${verb} cell ${cell.address}`;
|
|
5589
5679
|
}
|
|
5590
5680
|
if (/^\d+$/.test(target)) {
|
|
@@ -5684,12 +5774,12 @@ function buildFromSpec(doc, modelId, nameArg, spec) {
|
|
|
5684
5774
|
if (f.type && f.type !== inferred)
|
|
5685
5775
|
throw new SheetAddressError(`Flow ${f.from}→${f.to} is ${inferred}, not ${f.type}.`);
|
|
5686
5776
|
}
|
|
5687
|
-
const
|
|
5777
|
+
const sheetId = crypto.randomUUID();
|
|
5688
5778
|
const idByAddress = {};
|
|
5689
5779
|
doc.transact(() => {
|
|
5690
|
-
const cd = ELEMENT_DIMENSIONS.
|
|
5691
|
-
getScopeMap(doc, "
|
|
5692
|
-
ensureSheet(doc,
|
|
5780
|
+
const cd = ELEMENT_DIMENSIONS.sheet;
|
|
5781
|
+
getScopeMap(doc, "sheets").set(sheetId, deepToY({ sheetId, modelId, name: sheetName, x: 0, y: 0, width: cd.width, height: cd.height }));
|
|
5782
|
+
ensureSheet(doc, sheetId);
|
|
5693
5783
|
const sd = ELEMENT_DIMENSIONS.slice;
|
|
5694
5784
|
const sliceIds = cols.map((c) => {
|
|
5695
5785
|
const id = crypto.randomUUID();
|
|
@@ -5699,7 +5789,7 @@ function buildFromSpec(doc, modelId, nameArg, spec) {
|
|
|
5699
5789
|
if (c.note)
|
|
5700
5790
|
entry.note = c.note;
|
|
5701
5791
|
getScopeMap(doc, "slices").set(id, deepToY(entry));
|
|
5702
|
-
addColumn(doc,
|
|
5792
|
+
addColumn(doc, sheetId, id);
|
|
5703
5793
|
return id;
|
|
5704
5794
|
});
|
|
5705
5795
|
const ld = ELEMENT_DIMENSIONS.swimLane;
|
|
@@ -5709,7 +5799,7 @@ function buildFromSpec(doc, modelId, nameArg, spec) {
|
|
|
5709
5799
|
if (r.note)
|
|
5710
5800
|
entry.note = r.note;
|
|
5711
5801
|
getScopeMap(doc, "swimLanes").set(id, deepToY(entry));
|
|
5712
|
-
addRow(doc,
|
|
5802
|
+
addRow(doc, sheetId, id);
|
|
5713
5803
|
return id;
|
|
5714
5804
|
});
|
|
5715
5805
|
for (const op of ops) {
|
|
@@ -5731,10 +5821,10 @@ function buildFromSpec(doc, modelId, nameArg, spec) {
|
|
|
5731
5821
|
width: SCENARIO_CARD.width,
|
|
5732
5822
|
height: SCENARIO_CARD.height
|
|
5733
5823
|
}));
|
|
5734
|
-
placeInCell(doc,
|
|
5824
|
+
placeInCell(doc, sheetId, sliceIds[op.ci], laneIds[op.ri], { stickyId: id, scope: "scenarios" });
|
|
5735
5825
|
} else {
|
|
5736
5826
|
getScopeMap(doc, op.scope).set(id, deepToY({ ...op.data, [op.idKey]: id, modelId }));
|
|
5737
|
-
placeInCell(doc,
|
|
5827
|
+
placeInCell(doc, sheetId, sliceIds[op.ci], laneIds[op.ri], { stickyId: id, scope: op.scope });
|
|
5738
5828
|
}
|
|
5739
5829
|
idByAddress[op.address] = id;
|
|
5740
5830
|
}
|
|
@@ -5745,7 +5835,7 @@ function buildFromSpec(doc, modelId, nameArg, spec) {
|
|
|
5745
5835
|
const id = crypto.randomUUID();
|
|
5746
5836
|
const dim = FIXED_SIZE_DIM(op.scope);
|
|
5747
5837
|
getScopeMap(doc, op.scope).set(id, deepToY({ [meta.idKey]: id, modelId, name: "", x: 0, y: 0, width: dim.width, height: dim.height, isLinkedCopy: true, [meta.originalIdKey]: idByAddress[op.copyOf] }));
|
|
5748
|
-
placeInCell(doc,
|
|
5838
|
+
placeInCell(doc, sheetId, sliceIds[op.ci], laneIds[op.ri], { stickyId: id, scope: op.scope });
|
|
5749
5839
|
idByAddress[op.address] = id;
|
|
5750
5840
|
}
|
|
5751
5841
|
for (const f of specFlows) {
|
|
@@ -5760,13 +5850,13 @@ function buildFromSpec(doc, modelId, nameArg, spec) {
|
|
|
5760
5850
|
const ci = colIndexFromLabel(cl);
|
|
5761
5851
|
const ri = rowNum - 1;
|
|
5762
5852
|
if (ci >= 0 && ci < cols.length && ri >= 0 && ri < rows.length && text) {
|
|
5763
|
-
setCellNote(doc,
|
|
5853
|
+
setCellNote(doc, sheetId, sliceIds[ci], laneIds[ri], text);
|
|
5764
5854
|
}
|
|
5765
5855
|
}
|
|
5766
5856
|
});
|
|
5767
5857
|
reflowAllSheets(doc);
|
|
5768
5858
|
const nElems = ops.length;
|
|
5769
|
-
return `built sheet "${sheetName}" — ${cols.length} slices, ${rows.length} lanes, ${nElems} elements, ${specFlows.length} flows ${
|
|
5859
|
+
return `built sheet "${sheetName}" — ${cols.length} slices, ${rows.length} lanes, ${nElems} elements, ${specFlows.length} flows ${sheetId}`;
|
|
5770
5860
|
}
|
|
5771
5861
|
function buildSheetJson(doc, s) {
|
|
5772
5862
|
const { columns, rows, cells } = s.structure;
|
|
@@ -5778,7 +5868,7 @@ function buildSheetJson(doc, s) {
|
|
|
5778
5868
|
const e = getEntry(doc, "swimLanes", swimLaneId);
|
|
5779
5869
|
return { label: String(i + 1), name: e?.name ?? "(unnamed)", laneKind: e?.laneKind ?? null, swimLaneId, note: e?.note ?? null };
|
|
5780
5870
|
});
|
|
5781
|
-
const cellNotes = readCellNotes(doc, s.
|
|
5871
|
+
const cellNotes = readCellNotes(doc, s.sheetId);
|
|
5782
5872
|
const cellNotesByAddr = {};
|
|
5783
5873
|
for (const [k, text] of Object.entries(cellNotes)) {
|
|
5784
5874
|
const [sliceId, swimLaneId] = k.split(":");
|
|
@@ -5801,7 +5891,7 @@ function buildSheetJson(doc, s) {
|
|
|
5801
5891
|
}));
|
|
5802
5892
|
});
|
|
5803
5893
|
});
|
|
5804
|
-
return { sheet: nameOf(doc, "
|
|
5894
|
+
return { sheet: nameOf(doc, "sheets", s.sheetId), sheetId: s.sheetId, columns: columnViews, rows: rowViews, cells: cellViews, cellNotes: cellNotesByAddr };
|
|
5805
5895
|
}
|
|
5806
5896
|
function buildCellView(doc, s, cellArg) {
|
|
5807
5897
|
const { ordinal } = parseCellAddress(cellArg);
|
|
@@ -5818,7 +5908,7 @@ function buildCellView(doc, s, cellArg) {
|
|
|
5818
5908
|
const flows = getEntries(doc, "flows");
|
|
5819
5909
|
return {
|
|
5820
5910
|
cell: cell.address,
|
|
5821
|
-
note: readCellNotes(doc, s.
|
|
5911
|
+
note: readCellNotes(doc, s.sheetId)[cellKey(cell.sliceId, cell.swimLaneId)] ?? null,
|
|
5822
5912
|
slice: { label: colLabel2(cell.colIndex), name: slice?.name ?? "(unnamed)", sliceId: cell.sliceId, note: slice?.note ?? null },
|
|
5823
5913
|
lane: { label: String(cell.rowIndex + 1), name: lane?.name ?? "(unnamed)", laneKind: lane?.laneKind ?? null, swimLaneId: cell.swimLaneId, note: lane?.note ?? null },
|
|
5824
5914
|
elements: refs.map((r) => ({
|
|
@@ -5864,7 +5954,7 @@ function registerSheetCommands(program) {
|
|
|
5864
5954
|
return JSON.stringify(buildCellView(doc, s, cellArg), null, 2);
|
|
5865
5955
|
if (opts.json)
|
|
5866
5956
|
return JSON.stringify(buildSheetJson(doc, s), null, 2);
|
|
5867
|
-
return renderSheetOverview(doc, s.
|
|
5957
|
+
return renderSheetOverview(doc, s.sheetId) ?? "(empty sheet)";
|
|
5868
5958
|
});
|
|
5869
5959
|
console.log(output);
|
|
5870
5960
|
} catch (err) {
|
|
@@ -5895,13 +5985,13 @@ function registerSheetCommands(program) {
|
|
|
5895
5985
|
if (!name2)
|
|
5896
5986
|
throw new SheetAddressError("Pass a <name> (or --from <file>).");
|
|
5897
5987
|
const id = crypto.randomUUID();
|
|
5898
|
-
const d = ELEMENT_DIMENSIONS.
|
|
5899
|
-
const v = validateEntry("
|
|
5988
|
+
const d = ELEMENT_DIMENSIONS.sheet;
|
|
5989
|
+
const v = validateEntry("sheets", { name: name2, x: 0, y: 0, width: d.width, height: d.height });
|
|
5900
5990
|
if (!v.ok)
|
|
5901
5991
|
throw new SheetAddressError(`Invalid sheet: ${v.issues.join("; ")}`);
|
|
5902
5992
|
const out = await withDoc(modelId, (doc) => {
|
|
5903
5993
|
doc.transact(() => {
|
|
5904
|
-
getScopeMap(doc, "
|
|
5994
|
+
getScopeMap(doc, "sheets").set(id, deepToY({ ...v.data, sheetId: id, modelId }));
|
|
5905
5995
|
ensureSheet(doc, id);
|
|
5906
5996
|
});
|
|
5907
5997
|
reflowAllSheets(doc);
|
|
@@ -5921,14 +6011,14 @@ function registerSheetCommands(program) {
|
|
|
5921
6011
|
try {
|
|
5922
6012
|
const out = await withDoc(modelId, (doc) => {
|
|
5923
6013
|
const s = resolveSheet2(doc, sheetRef);
|
|
5924
|
-
const name2 = getEntry(doc, "
|
|
6014
|
+
const name2 = getEntry(doc, "sheets", s.sheetId)?.name ?? s.sheetId;
|
|
5925
6015
|
const elements = Object.values(s.structure.cells).reduce((n, refs) => n + refs.length, 0);
|
|
5926
6016
|
const summary = `sheet "${name2}" — ${s.structure.columns.length} slice(s), ${s.structure.rows.length} lane(s), ${elements} element(s)`;
|
|
5927
6017
|
if (!opts.yes) {
|
|
5928
6018
|
return `Would delete ${summary}.
|
|
5929
6019
|
This cannot be undone. Re-run with --yes to confirm.`;
|
|
5930
6020
|
}
|
|
5931
|
-
deleteSheet(doc, s.
|
|
6021
|
+
deleteSheet(doc, s.sheetId);
|
|
5932
6022
|
reflowAllSheets(doc);
|
|
5933
6023
|
return `Deleted ${summary}.`;
|
|
5934
6024
|
});
|
|
@@ -5942,12 +6032,12 @@ This cannot be undone. Re-run with --yes to confirm.`;
|
|
|
5942
6032
|
}
|
|
5943
6033
|
});
|
|
5944
6034
|
const insert = sheet.command("insert").description("Insert a slice (column), a lane (row), or an element into a cell");
|
|
5945
|
-
insert.command("slice <name>").description("Insert a new slice (column)").option("--at <n>", "Position (1-based); appends if omitted").option("--sheet <ref>", "Which sheet (name or
|
|
6035
|
+
insert.command("slice <name>").description("Insert a new slice (column)").option("--at <n>", "Position (1-based); appends if omitted").option("--sheet <ref>", "Which sheet (name or sheetId) when the model has several").option("--model <id>", "Target model id").action((name2, opts) => runWrite(opts, (doc, s, modelId) => insertColumn(doc, s, modelId, name2, atIndex(opts.at))));
|
|
5946
6036
|
for (const kind of LANE_KINDS) {
|
|
5947
|
-
insert.command(`${kind} <name>`).description(`Insert a ${kind} lane (row)`).option("--at <n>", "Position (1-based); appends if omitted").option("--sheet <ref>", "Which sheet (name or
|
|
6037
|
+
insert.command(`${kind} <name>`).description(`Insert a ${kind} lane (row)`).option("--at <n>", "Position (1-based); appends if omitted").option("--sheet <ref>", "Which sheet (name or sheetId) when the model has several").option("--model <id>", "Target model id").action((name2, opts) => runWrite(opts, (doc, s, modelId) => insertLane(doc, s, modelId, kind, name2, atIndex(opts.at))));
|
|
5948
6038
|
}
|
|
5949
6039
|
for (const type of ELEMENT_TYPES) {
|
|
5950
|
-
insert.command(`${type} <cell> <element>`).description(`Insert a ${type} into a cell (e.g. B2). <element> is a name or a JSON object.`).option("--sheet <ref>", "Which sheet (name or
|
|
6040
|
+
insert.command(`${type} <cell> <element>`).description(`Insert a ${type} into a cell (e.g. B2). <element> is a name or a JSON object.`).option("--sheet <ref>", "Which sheet (name or sheetId) when the model has several").option("--model <id>", "Target model id").action((cell, element, opts) => runWrite(opts, (doc, s, modelId) => insertElement(doc, s, modelId, type, cell, element)));
|
|
5951
6041
|
}
|
|
5952
6042
|
sheet.command("move <element>").description("Move an element to another cell, e.g. `move B2.1 --to C2` (keeps its id + flows)").requiredOption("--to <cell>", "Destination cell (e.g. C2)").option("--sheet <ref>", "Which sheet when the model has several").option("--model <id>", "Target model id").action((element, opts) => runWrite(opts, (doc, s) => moveElement(doc, s, element, opts.to)));
|
|
5953
6043
|
sheet.command("reorder <ref>").description("Reorder a slice (column letter) or lane (row number), e.g. `reorder A --to 3`").requiredOption("--to <n>", "New 1-based position").option("--sheet <ref>", "Which sheet when the model has several").option("--model <id>", "Target model id").action((ref, opts) => runWrite(opts, (doc, s) => reorderAxis(doc, s, ref, parseInt(opts.to, 10))));
|