eventmodeler 0.6.12 → 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.
Files changed (2) hide show
  1. package/dist/index.js +297 -129
  2. 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
- sourceChapterId: z.string().uuid(),
2942
+ sourceSheetId: z.string().uuid(),
2941
2943
  sourceHandle: z.string().min(1),
2942
- targetChapterId: z.string().uuid(),
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(sliceId, swimLaneId) {
3009
- return `${sliceId}:${swimLaneId}`;
3012
+ function cellKey(columnId, swimLaneId) {
3013
+ return `${columnId}:${swimLaneId}`;
3010
3014
  }
3011
- function resolveSheet(doc, chapterId) {
3015
+ function resolveSheet(doc, sheetId) {
3012
3016
  const grid = getGridMap(doc);
3013
- let sheet = grid.get(chapterId);
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
- grid.set(chapterId, sheet);
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, chapterId) {
3039
+ function ensureSheet(doc, sheetId) {
3029
3040
  doc.transact(() => {
3030
- resolveSheet(doc, chapterId);
3041
+ resolveSheet(doc, sheetId);
3031
3042
  });
3032
3043
  }
3033
- function readSheet(doc, chapterId) {
3034
- const sheet = getGridMap(doc).get(chapterId);
3044
+ function readSheet(doc, sheetId) {
3045
+ const sheet = getGridMap(doc).get(sheetId);
3035
3046
  if (!sheet)
3036
3047
  return;
3037
- return sheet.toJSON();
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, chapterId, sliceId, at) {
3066
+ function addColumn(doc, sheetId, sliceId, at) {
3050
3067
  doc.transact(() => {
3051
- const { columns } = resolveSheet(doc, chapterId);
3052
- insertUnique(columns, sliceId, at);
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, chapterId, sliceId, toIndex) {
3075
+ function moveColumn(doc, sheetId, columnId, toIndex) {
3056
3076
  doc.transact(() => {
3057
- const { columns } = resolveSheet(doc, chapterId);
3058
- const from = columns.toArray().indexOf(sliceId);
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), [sliceId]);
3082
+ columns.insert(clampIndex(toIndex, columns.length), [columnId]);
3063
3083
  });
3064
3084
  }
3065
- function removeColumn(doc, chapterId, sliceId) {
3085
+ function removeColumn(doc, sheetId, columnId) {
3066
3086
  doc.transact(() => {
3067
- const sheet = getGridMap(doc).get(chapterId);
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 idx = columns.toArray().indexOf(sliceId);
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(`${sliceId}:`))
3099
+ if (key.startsWith(`${columnId}:`))
3078
3100
  cells.delete(key);
3079
3101
  }
3080
3102
  for (const key of [...cellNotes?.keys() ?? []]) {
3081
- if (key.startsWith(`${sliceId}:`))
3103
+ if (key.startsWith(`${columnId}:`))
3082
3104
  cellNotes.delete(key);
3083
3105
  }
3084
3106
  });
3085
3107
  }
3086
- function addRow(doc, chapterId, swimLaneId, at) {
3108
+ function ensureColumnSlices(doc, sheetId) {
3109
+ doc.transact(() => {
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) {
3087
3118
  doc.transact(() => {
3088
- const { rows } = resolveSheet(doc, chapterId);
3119
+ const { rows } = resolveSheet(doc, sheetId);
3089
3120
  insertUnique(rows, swimLaneId, at);
3090
3121
  });
3091
3122
  }
3092
- function moveRow(doc, chapterId, swimLaneId, toIndex) {
3123
+ function moveRow(doc, sheetId, swimLaneId, toIndex) {
3093
3124
  doc.transact(() => {
3094
- const { rows } = resolveSheet(doc, chapterId);
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, chapterId, swimLaneId) {
3133
+ function removeRow(doc, sheetId, swimLaneId) {
3103
3134
  doc.transact(() => {
3104
- const sheet = getGridMap(doc).get(chapterId);
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, chapterId, sliceId, swimLaneId, ref, at) {
3171
+ function placeInCell(doc, sheetId, sliceId, swimLaneId, ref, at) {
3141
3172
  doc.transact(() => {
3142
- const { cells } = resolveSheet(doc, chapterId);
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, chapterId, stickyId) {
3188
+ function removeSticky(doc, sheetId, stickyId) {
3158
3189
  doc.transact(() => {
3159
- const sheet = getGridMap(doc).get(chapterId);
3190
+ const sheet = getGridMap(doc).get(sheetId);
3160
3191
  if (!sheet)
3161
3192
  return;
3162
3193
  const cells = sheet.get("cells");
@@ -3166,8 +3197,13 @@ function removeSticky(doc, chapterId, stickyId) {
3166
3197
  cells.get(loc.key).delete(loc.index, 1);
3167
3198
  });
3168
3199
  }
3169
- function getCellNotesMap(doc, chapterId, create) {
3170
- const sheet = getGridMap(doc).get(chapterId);
3200
+ function removeSheet(doc, sheetId) {
3201
+ doc.transact(() => {
3202
+ getGridMap(doc).delete(sheetId);
3203
+ });
3204
+ }
3205
+ function getCellNotesMap(doc, sheetId, create) {
3206
+ const sheet = getGridMap(doc).get(sheetId);
3171
3207
  if (!sheet)
3172
3208
  return;
3173
3209
  let notes = sheet.get("cellNotes");
@@ -3177,19 +3213,98 @@ function getCellNotesMap(doc, chapterId, create) {
3177
3213
  }
3178
3214
  return notes;
3179
3215
  }
3180
- function readCellNotes(doc, chapterId) {
3181
- const notes = getGridMap(doc).get(chapterId)?.get("cellNotes");
3216
+ function readCellNotes(doc, sheetId) {
3217
+ const notes = getGridMap(doc).get(sheetId)?.get("cellNotes");
3182
3218
  return notes ? notes.toJSON() : {};
3183
3219
  }
3184
- function setCellNote(doc, chapterId, sliceId, swimLaneId, text) {
3220
+ function setCellNote(doc, sheetId, sliceId, swimLaneId, text) {
3185
3221
  doc.transact(() => {
3186
3222
  const key = cellKey(sliceId, swimLaneId);
3187
3223
  const trimmed = text.trim();
3188
3224
  if (!trimmed) {
3189
- getCellNotesMap(doc, chapterId, false)?.delete(key);
3225
+ getCellNotesMap(doc, sheetId, false)?.delete(key);
3190
3226
  return;
3191
3227
  }
3192
- getCellNotesMap(doc, chapterId, true).set(key, trimmed);
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
+ }
3260
+ });
3261
+ }
3262
+ // ../packages/canvas-model/src/sheet-delete.ts
3263
+ var SHEETS_SCOPE = "sheets";
3264
+ var SLICES_SCOPE2 = "slices";
3265
+ var SWIM_LANES_SCOPE = "swimLanes";
3266
+ var SCENARIOS_SCOPE2 = "scenarios";
3267
+ var SHEET_FLOWS_SCOPE = "sheetFlows";
3268
+ function deleteSheet(doc, sheetId) {
3269
+ doc.transact(() => {
3270
+ const sheet = getGridMap(doc).get(sheetId);
3271
+ const removedStickies = new Set;
3272
+ const sliceIds = new Set;
3273
+ const laneIds = new Set;
3274
+ if (sheet) {
3275
+ for (const id of sheet.get("columns").toArray())
3276
+ sliceIds.add(id);
3277
+ for (const id of sheet.get("rows").toArray())
3278
+ laneIds.add(id);
3279
+ const cells = sheet.get("cells");
3280
+ for (const key of cells.keys()) {
3281
+ for (const ref of cells.get(key).toArray()) {
3282
+ const stickyId = ref.get("stickyId");
3283
+ getScopeMap(doc, ref.get("scope")).delete(stickyId);
3284
+ removedStickies.add(stickyId);
3285
+ }
3286
+ }
3287
+ }
3288
+ for (const id of sliceIds)
3289
+ getScopeMap(doc, SLICES_SCOPE2).delete(id);
3290
+ for (const id of laneIds)
3291
+ getScopeMap(doc, SWIM_LANES_SCOPE).delete(id);
3292
+ const scenarios = getScopeMap(doc, SCENARIOS_SCOPE2);
3293
+ for (const [id, sc] of scenarios.entries()) {
3294
+ if (sliceIds.has(sc.get("sliceId"))) {
3295
+ scenarios.delete(id);
3296
+ removedStickies.add(id);
3297
+ }
3298
+ }
3299
+ cascadeStickyRemoval(doc, removedStickies);
3300
+ const sheetFlows = getScopeMap(doc, SHEET_FLOWS_SCOPE);
3301
+ for (const [id, f] of sheetFlows.entries()) {
3302
+ if (f.get("sourceSheetId") === sheetId || f.get("targetSheetId") === sheetId) {
3303
+ sheetFlows.delete(id);
3304
+ }
3305
+ }
3306
+ removeSheet(doc, sheetId);
3307
+ getScopeMap(doc, SHEETS_SCOPE).delete(sheetId);
3193
3308
  });
3194
3309
  }
3195
3310
  // ../packages/canvas-model/src/sheet-layout.ts
@@ -3242,8 +3357,8 @@ function cellContentSize(refs) {
3242
3357
  });
3243
3358
  return { width, height };
3244
3359
  }
3245
- function pruneOrphanCellRefs(doc, chapterId) {
3246
- const sheet = getGridMap(doc).get(chapterId);
3360
+ function pruneOrphanCellRefs(doc, sheetId) {
3361
+ const sheet = getGridMap(doc).get(sheetId);
3247
3362
  if (!sheet)
3248
3363
  return 0;
3249
3364
  const cells = sheet.get("cells");
@@ -3262,19 +3377,21 @@ function pruneOrphanCellRefs(doc, chapterId) {
3262
3377
  }
3263
3378
  return pruned;
3264
3379
  }
3265
- function computeSheetLayout(doc, chapterId, override) {
3266
- const structure = readSheet(doc, chapterId);
3380
+ function computeSheetLayout(doc, sheetId, override) {
3381
+ const structure = readSheet(doc, sheetId);
3267
3382
  if (!structure)
3268
3383
  return;
3269
- const chapter = getEntry(doc, "chapters", chapterId);
3270
- const originX = snap(chapter?.x ?? 0);
3271
- const originY = snap(chapter?.y ?? 0);
3384
+ const sheet = getEntry(doc, "sheets", sheetId);
3385
+ const originX = snap(sheet?.x ?? 0);
3386
+ const originY = snap(sheet?.y ?? 0);
3272
3387
  const { columns, rows } = structure;
3388
+ const columnSlices = structure.columnSlices ?? {};
3389
+ const ownerOf = (columnId) => columnSlices[columnId] ?? columnId;
3273
3390
  const cells = override ? applyLayoutOverride(structure.cells, override) : structure.cells;
3274
- const colWidths = columns.map((sliceId) => {
3391
+ const colWidths = columns.map((columnId) => {
3275
3392
  let w = 0;
3276
3393
  for (const swimLaneId of rows) {
3277
- const refs = cells[cellKey(sliceId, swimLaneId)] ?? [];
3394
+ const refs = cells[cellKey(columnId, swimLaneId)] ?? [];
3278
3395
  const c = cellContentSize(refs);
3279
3396
  if (c.width > 0)
3280
3397
  w = Math.max(w, c.width + SHEET_LAYOUT.cellPadX * 2);
@@ -3283,8 +3400,8 @@ function computeSheetLayout(doc, chapterId, override) {
3283
3400
  });
3284
3401
  const rowHeights = rows.map((swimLaneId) => {
3285
3402
  let h = 0;
3286
- for (const sliceId of columns) {
3287
- const refs = cells[cellKey(sliceId, swimLaneId)] ?? [];
3403
+ for (const columnId of columns) {
3404
+ const refs = cells[cellKey(columnId, swimLaneId)] ?? [];
3288
3405
  const c = cellContentSize(refs);
3289
3406
  if (c.height > 0)
3290
3407
  h = Math.max(h, c.height + SHEET_LAYOUT.cellPadY * 2);
@@ -3305,14 +3422,33 @@ function computeSheetLayout(doc, chapterId, override) {
3305
3422
  });
3306
3423
  const gridWidth = SHEET_LAYOUT.headerLeft + colWidths.reduce((a, b) => a + b, 0);
3307
3424
  const gridHeight = SHEET_LAYOUT.headerTop + rowHeights.reduce((a, b) => a + b, 0);
3308
- const columnLayouts = columns.map((sliceId, i) => ({
3309
- sliceId,
3425
+ const columnLayouts = columns.map((columnId, i) => ({
3426
+ columnId,
3427
+ sliceId: ownerOf(columnId),
3310
3428
  index: i,
3311
3429
  x: colX[i],
3312
3430
  y: originY,
3313
3431
  width: colWidths[i],
3314
3432
  height: gridHeight
3315
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
+ }
3316
3452
  const rowLayouts = rows.map((swimLaneId, i) => ({
3317
3453
  swimLaneId,
3318
3454
  index: i,
@@ -3322,9 +3458,10 @@ function computeSheetLayout(doc, chapterId, override) {
3322
3458
  height: rowHeights[i]
3323
3459
  }));
3324
3460
  const stickies = [];
3325
- columns.forEach((sliceId, ci) => {
3461
+ columns.forEach((columnId, ci) => {
3462
+ const sliceId = ownerOf(columnId);
3326
3463
  rows.forEach((swimLaneId, ri) => {
3327
- const refs = cells[cellKey(sliceId, swimLaneId)] ?? [];
3464
+ const refs = cells[cellKey(columnId, swimLaneId)] ?? [];
3328
3465
  if (refs.length === 0)
3329
3466
  return;
3330
3467
  const content = cellContentSize(refs);
@@ -3339,6 +3476,7 @@ function computeSheetLayout(doc, chapterId, override) {
3339
3476
  stickies.push({
3340
3477
  stickyId: ref.stickyId,
3341
3478
  scope: ref.scope,
3479
+ columnId,
3342
3480
  sliceId,
3343
3481
  swimLaneId,
3344
3482
  x: Math.round(midX - size.width / 2),
@@ -3355,6 +3493,7 @@ function computeSheetLayout(doc, chapterId, override) {
3355
3493
  stickies.push({
3356
3494
  stickyId: ref.stickyId,
3357
3495
  scope: ref.scope,
3496
+ columnId,
3358
3497
  sliceId,
3359
3498
  swimLaneId,
3360
3499
  x: Math.round(cursorX),
@@ -3368,18 +3507,19 @@ function computeSheetLayout(doc, chapterId, override) {
3368
3507
  });
3369
3508
  });
3370
3509
  return {
3371
- chapterId,
3372
- chapter: { x: originX, y: originY, width: gridWidth, height: gridHeight },
3510
+ sheetId,
3511
+ sheet: { x: originX, y: originY, width: gridWidth, height: gridHeight },
3373
3512
  columns: columnLayouts,
3513
+ slices: sliceLayouts,
3374
3514
  rows: rowLayouts,
3375
3515
  stickies
3376
3516
  };
3377
3517
  }
3378
3518
  // ../packages/canvas-model/src/reflow.ts
3379
3519
  var REFLOW_ORIGIN = Symbol("sheet-reflow");
3380
- var CHAPTERS_SCOPE = "chapters";
3381
- var SLICES_SCOPE2 = "slices";
3382
- var SWIM_LANES_SCOPE = "swimLanes";
3520
+ var SHEETS_SCOPE2 = "sheets";
3521
+ var SLICES_SCOPE3 = "slices";
3522
+ var SWIM_LANES_SCOPE2 = "swimLanes";
3383
3523
  var STICKY_SCOPES = [
3384
3524
  "commands",
3385
3525
  "events",
@@ -3404,27 +3544,30 @@ function applyBox(m, box, size = true) {
3404
3544
  }
3405
3545
  }
3406
3546
  function reflowAllSheets(doc, origin = REFLOW_ORIGIN) {
3407
- const chapters = getScopeMap(doc, CHAPTERS_SCOPE);
3408
- if (chapters.size === 0)
3547
+ migrateChaptersToSheets(doc);
3548
+ const sheets = getScopeMap(doc, SHEETS_SCOPE2);
3549
+ if (sheets.size === 0)
3409
3550
  return;
3410
3551
  doc.transact(() => {
3411
- for (const chapterId of chapters.keys())
3412
- ensureSheet(doc, chapterId);
3413
- const slices = getScopeMap(doc, SLICES_SCOPE2);
3414
- const lanes = getScopeMap(doc, SWIM_LANES_SCOPE);
3552
+ for (const sheetId of sheets.keys()) {
3553
+ ensureSheet(doc, sheetId);
3554
+ ensureColumnSlices(doc, sheetId);
3555
+ }
3556
+ const slices = getScopeMap(doc, SLICES_SCOPE3);
3557
+ const lanes = getScopeMap(doc, SWIM_LANES_SCOPE2);
3415
3558
  const stickyMaps = STICKY_SCOPES.map((s) => getScopeMap(doc, s));
3416
- for (const chapterId of getGridMap(doc).keys()) {
3417
- pruneOrphanCellRefs(doc, chapterId);
3418
- const layout = computeSheetLayout(doc, chapterId);
3559
+ for (const sheetId of getGridMap(doc).keys()) {
3560
+ pruneOrphanCellRefs(doc, sheetId);
3561
+ const layout = computeSheetLayout(doc, sheetId);
3419
3562
  if (!layout)
3420
3563
  continue;
3421
- const ch = chapters.get(chapterId);
3564
+ const ch = sheets.get(sheetId);
3422
3565
  if (ch) {
3423
- setIfChanged(ch, "width", layout.chapter.width);
3424
- setIfChanged(ch, "height", layout.chapter.height);
3566
+ setIfChanged(ch, "width", layout.sheet.width);
3567
+ setIfChanged(ch, "height", layout.sheet.height);
3425
3568
  }
3426
- for (const col of layout.columns)
3427
- applyBox(slices.get(col.sliceId), col);
3569
+ for (const band of layout.slices)
3570
+ applyBox(slices.get(band.sliceId), band);
3428
3571
  for (const row of layout.rows)
3429
3572
  applyBox(lanes.get(row.swimLaneId), row);
3430
3573
  const scenarioOrder = new Map;
@@ -4884,12 +5027,12 @@ function pad(s, width) {
4884
5027
  return s.length >= width ? s : s + " ".repeat(width - s.length);
4885
5028
  }
4886
5029
  var NOTE = "†";
4887
- function resolve4(doc, chapterId) {
4888
- const structure = readSheet(doc, chapterId);
5030
+ function resolve4(doc, sheetId) {
5031
+ const structure = readSheet(doc, sheetId);
4889
5032
  if (!structure)
4890
5033
  return;
4891
5034
  const { columns, rows, cells } = structure;
4892
- const notes = readCellNotes(doc, chapterId);
5035
+ const notes = readCellNotes(doc, sheetId);
4893
5036
  const cols = columns.map((sliceId, i) => ({
4894
5037
  label: colLabel(i),
4895
5038
  name: entityName(doc, "slices", sliceId),
@@ -4902,7 +5045,7 @@ function resolve4(doc, chapterId) {
4902
5045
  const elems = columns.map((sliceId) => rows.map((swimLaneId) => (cells[cellKey(sliceId, swimLaneId)] ?? []).map((r) => elementText(doc, r))));
4903
5046
  const cellNote = columns.map((sliceId) => rows.map((swimLaneId) => Boolean(notes[cellKey(sliceId, swimLaneId)])));
4904
5047
  return {
4905
- title: entityName(doc, "chapters", chapterId),
5048
+ title: entityName(doc, "sheets", sheetId),
4906
5049
  columns: cols,
4907
5050
  rows: lanes2,
4908
5051
  elems,
@@ -4984,9 +5127,9 @@ function renderListing(r) {
4984
5127
  return lines.join(`
4985
5128
  `).trimEnd();
4986
5129
  }
4987
- function renderSheetOverview(doc, chapterId, options = {}) {
5130
+ function renderSheetOverview(doc, sheetId, options = {}) {
4988
5131
  const opts = { ...DEFAULTS, ...options };
4989
- const r = resolve4(doc, chapterId);
5132
+ const r = resolve4(doc, sheetId);
4990
5133
  if (!r)
4991
5134
  return;
4992
5135
  if (r.empty)
@@ -5020,23 +5163,23 @@ function resolveSheet2(doc, ref) {
5020
5163
  const ids = [...grid2.keys()];
5021
5164
  if (ids.length === 0)
5022
5165
  throw new SheetAddressError("This model has no sheets.");
5023
- const done = (chapterId) => ({ chapterId, structure: readSheet(doc, chapterId) });
5166
+ const done = (sheetId) => ({ sheetId, structure: readSheet(doc, sheetId) });
5024
5167
  if (ref && grid2.has(ref))
5025
5168
  return done(ref);
5026
5169
  if (!ref) {
5027
5170
  if (ids.length === 1)
5028
5171
  return done(ids[0]);
5029
- const list = ids.map((id) => `"${name(doc, "chapters", id)}"`).join(", ");
5172
+ const list = ids.map((id) => `"${name(doc, "sheets", id)}"`).join(", ");
5030
5173
  throw new SheetAddressError(`Multiple sheets — name one. Available: ${list}`);
5031
5174
  }
5032
5175
  const lower = ref.toLowerCase();
5033
- const matches = ids.filter((id) => name(doc, "chapters", id).toLowerCase() === lower);
5176
+ const matches = ids.filter((id) => name(doc, "sheets", id).toLowerCase() === lower);
5034
5177
  if (matches.length === 0) {
5035
- const list = ids.map((id) => `"${name(doc, "chapters", id)}"`).join(", ") || "(none)";
5178
+ const list = ids.map((id) => `"${name(doc, "sheets", id)}"`).join(", ") || "(none)";
5036
5179
  throw new SheetAddressError(`No sheet named "${ref}". Available: ${list}`);
5037
5180
  }
5038
5181
  if (matches.length > 1)
5039
- throw new SheetAddressError(`Ambiguous sheet name "${ref}" — pass the chapterId instead.`);
5182
+ throw new SheetAddressError(`Ambiguous sheet name "${ref}" — pass the sheetId instead.`);
5040
5183
  return done(matches[0]);
5041
5184
  }
5042
5185
  function resolveColumn(doc, s, ref) {
@@ -5240,9 +5383,9 @@ function insertColumn(doc, s, modelId, name2, at) {
5240
5383
  throw new SheetAddressError(`Invalid slice: ${v.issues.join("; ")}`);
5241
5384
  doc.transact(() => {
5242
5385
  getScopeMap(doc, "slices").set(id, deepToY({ ...v.data, sliceId: id, modelId }));
5243
- addColumn(doc, s.chapterId, id, at);
5386
+ addColumn(doc, s.sheetId, id, at);
5244
5387
  });
5245
- const idx = readSheet(doc, s.chapterId).columns.indexOf(id);
5388
+ const idx = readSheet(doc, s.sheetId).columns.indexOf(id);
5246
5389
  return `${colLabel2(idx)} "${name2}" ${id}`;
5247
5390
  }
5248
5391
  function insertLane(doc, s, modelId, kind, name2, at) {
@@ -5253,9 +5396,9 @@ function insertLane(doc, s, modelId, kind, name2, at) {
5253
5396
  throw new SheetAddressError(`Invalid lane: ${v.issues.join("; ")}`);
5254
5397
  doc.transact(() => {
5255
5398
  getScopeMap(doc, "swimLanes").set(id, deepToY({ ...v.data, swimLaneId: id, modelId }));
5256
- addRow(doc, s.chapterId, id, at);
5399
+ addRow(doc, s.sheetId, id, at);
5257
5400
  });
5258
- const idx = readSheet(doc, s.chapterId).rows.indexOf(id);
5401
+ const idx = readSheet(doc, s.sheetId).rows.indexOf(id);
5259
5402
  return `${idx + 1} "${name2}" (${kind}) ${id}`;
5260
5403
  }
5261
5404
  function insertElement(doc, s, modelId, type, cellArg, nameOrJson) {
@@ -5284,7 +5427,7 @@ function insertElement(doc, s, modelId, type, cellArg, nameOrJson) {
5284
5427
  };
5285
5428
  doc.transact(() => {
5286
5429
  getScopeMap(doc, "scenarios").set(id, deepToY(entry2));
5287
- placeInCell(doc, s.chapterId, cell.sliceId, cell.swimLaneId, { stickyId: id, scope: "scenarios" });
5430
+ placeInCell(doc, s.sheetId, cell.sliceId, cell.swimLaneId, { stickyId: id, scope: "scenarios" });
5288
5431
  });
5289
5432
  return addressOf(doc, s, cell.sliceId, cell.swimLaneId, id, cell.address);
5290
5433
  }
@@ -5299,12 +5442,12 @@ function insertElement(doc, s, modelId, type, cellArg, nameOrJson) {
5299
5442
  const final = { ...v.data, [meta.idKey]: id, modelId };
5300
5443
  doc.transact(() => {
5301
5444
  getScopeMap(doc, meta.scope).set(id, deepToY(final));
5302
- placeInCell(doc, s.chapterId, cell.sliceId, cell.swimLaneId, { stickyId: id, scope: meta.scope });
5445
+ placeInCell(doc, s.sheetId, cell.sliceId, cell.swimLaneId, { stickyId: id, scope: meta.scope });
5303
5446
  });
5304
5447
  return addressOf(doc, s, cell.sliceId, cell.swimLaneId, id, cell.address);
5305
5448
  }
5306
5449
  function addressOf(doc, s, sliceId, swimLaneId, id, cellAddr) {
5307
- const refs = readSheet(doc, s.chapterId).cells[cellKey(sliceId, swimLaneId)] ?? [];
5450
+ const refs = readSheet(doc, s.sheetId).cells[cellKey(sliceId, swimLaneId)] ?? [];
5308
5451
  const ord = refs.findIndex((r) => r.stickyId === id) + 1;
5309
5452
  return `${cellAddr}.${ord} ${id}`;
5310
5453
  }
@@ -5315,7 +5458,7 @@ function moveElement(doc, s, elAddr, toCell) {
5315
5458
  if (!laneAllows(kind, el.scope))
5316
5459
  rejectLane(doc, dest.swimLaneId, dest.rowIndex, kind, TYPE_LABEL[el.scope] ?? el.scope);
5317
5460
  doc.transact(() => {
5318
- placeInCell(doc, s.chapterId, dest.sliceId, dest.swimLaneId, { stickyId: el.stickyId, scope: el.scope });
5461
+ placeInCell(doc, s.sheetId, dest.sliceId, dest.swimLaneId, { stickyId: el.stickyId, scope: el.scope });
5319
5462
  });
5320
5463
  return addressOf(doc, s, dest.sliceId, dest.swimLaneId, el.stickyId, dest.address);
5321
5464
  }
@@ -5323,14 +5466,14 @@ function reorderAxis(doc, s, ref, to) {
5323
5466
  const toIndex = to - 1;
5324
5467
  if (/^\d+$/.test(ref)) {
5325
5468
  const row = resolveRow(doc, s, ref);
5326
- doc.transact(() => moveRow(doc, s.chapterId, row.swimLaneId, toIndex));
5327
- const idx = readSheet(doc, s.chapterId).rows.indexOf(row.swimLaneId);
5469
+ doc.transact(() => moveRow(doc, s.sheetId, row.swimLaneId, toIndex));
5470
+ const idx = readSheet(doc, s.sheetId).rows.indexOf(row.swimLaneId);
5328
5471
  return `row → ${idx + 1}`;
5329
5472
  }
5330
5473
  if (colIndexFromLabel(ref) >= 0 || s.structure.columns.length > 0) {
5331
5474
  const col = resolveColumn(doc, s, ref);
5332
- doc.transact(() => moveColumn(doc, s.chapterId, col.sliceId, toIndex));
5333
- const idx = readSheet(doc, s.chapterId).columns.indexOf(col.sliceId);
5475
+ doc.transact(() => moveColumn(doc, s.sheetId, col.sliceId, toIndex));
5476
+ const idx = readSheet(doc, s.sheetId).columns.indexOf(col.sliceId);
5334
5477
  return `column → ${colLabel2(idx)}`;
5335
5478
  }
5336
5479
  throw new SheetAddressError(`reorder takes a column letter (A) or row number (1), got "${ref}".`);
@@ -5339,7 +5482,7 @@ function removeTarget(doc, s, target) {
5339
5482
  if (/^[A-Za-z]+\d+(\.\d+)?$/.test(target)) {
5340
5483
  const el = resolveElement(doc, s, target);
5341
5484
  doc.transact(() => {
5342
- removeSticky(doc, s.chapterId, el.stickyId);
5485
+ removeSticky(doc, s.sheetId, el.stickyId);
5343
5486
  getScopeMap(doc, el.scope).delete(el.stickyId);
5344
5487
  cascadeStickyRemoval(doc, new Set([el.stickyId]));
5345
5488
  });
@@ -5350,7 +5493,7 @@ function removeTarget(doc, s, target) {
5350
5493
  const laneName = nameOf(doc, "swimLanes", row.swimLaneId);
5351
5494
  const refs2 = s.structure.columns.flatMap((sliceId) => s.structure.cells[cellKey(sliceId, row.swimLaneId)] ?? []);
5352
5495
  doc.transact(() => {
5353
- removeRow(doc, s.chapterId, row.swimLaneId);
5496
+ removeRow(doc, s.sheetId, row.swimLaneId);
5354
5497
  getScopeMap(doc, "swimLanes").delete(row.swimLaneId);
5355
5498
  for (const r of refs2)
5356
5499
  getScopeMap(doc, r.scope).delete(r.stickyId);
@@ -5362,7 +5505,7 @@ function removeTarget(doc, s, target) {
5362
5505
  const sliceName = nameOf(doc, "slices", col.sliceId);
5363
5506
  const refs = s.structure.rows.flatMap((swimLaneId) => s.structure.cells[cellKey(col.sliceId, swimLaneId)] ?? []);
5364
5507
  doc.transact(() => {
5365
- removeColumn(doc, s.chapterId, col.sliceId);
5508
+ removeColumn(doc, s.sheetId, col.sliceId);
5366
5509
  getScopeMap(doc, "slices").delete(col.sliceId);
5367
5510
  for (const r of refs)
5368
5511
  getScopeMap(doc, r.scope).delete(r.stickyId);
@@ -5440,7 +5583,7 @@ function sheetEdgeHandle(side, dir) {
5440
5583
  }
5441
5584
  function resolveAnchor(doc, sheet, dir, col, side) {
5442
5585
  const flag = dir === "source" ? "from" : "to";
5443
- const sheetName = nameOf(doc, "chapters", sheet.chapterId);
5586
+ const sheetName = nameOf(doc, "sheets", sheet.sheetId);
5444
5587
  if (col !== undefined) {
5445
5588
  const c = resolveColumn(doc, sheet, col);
5446
5589
  const s2 = side ?? (dir === "source" ? "bottom" : "top");
@@ -5458,7 +5601,7 @@ function resolveAnchor(doc, sheet, dir, col, side) {
5458
5601
  function connectSheets(doc, modelId, fromRef, toRef, opts) {
5459
5602
  const src = resolveSheet2(doc, fromRef);
5460
5603
  const dst = resolveSheet2(doc, toRef);
5461
- if (src.chapterId === dst.chapterId) {
5604
+ if (src.sheetId === dst.sheetId) {
5462
5605
  throw new SheetAddressError("Connect joins two different sheets — source and target are the same sheet.");
5463
5606
  }
5464
5607
  const from = resolveAnchor(doc, src, "source", opts.from, opts.fromSide);
@@ -5466,9 +5609,9 @@ function connectSheets(doc, modelId, fromRef, toRef, opts) {
5466
5609
  const id = crypto.randomUUID();
5467
5610
  const entry = {
5468
5611
  sheetFlowId: id,
5469
- sourceChapterId: src.chapterId,
5612
+ sourceSheetId: src.sheetId,
5470
5613
  sourceHandle: from.handle,
5471
- targetChapterId: dst.chapterId,
5614
+ targetSheetId: dst.sheetId,
5472
5615
  targetHandle: to.handle
5473
5616
  };
5474
5617
  const v = validateEntry("sheetFlows", entry);
@@ -5501,7 +5644,7 @@ function copyElement(doc, s, modelId, srcAddr, toCell) {
5501
5644
  const dim = FIXED_SIZE_DIM(src.scope);
5502
5645
  doc.transact(() => {
5503
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 }));
5504
- placeInCell(doc, s.chapterId, dest.sliceId, dest.swimLaneId, { stickyId: id, scope: src.scope });
5647
+ placeInCell(doc, s.sheetId, dest.sliceId, dest.swimLaneId, { stickyId: id, scope: src.scope });
5505
5648
  });
5506
5649
  return addressOf(doc, s, dest.sliceId, dest.swimLaneId, id, dest.address);
5507
5650
  }
@@ -5531,7 +5674,7 @@ function noteTarget(doc, s, target, text) {
5531
5674
  }
5532
5675
  if (/^[A-Za-z]+\d+$/.test(target)) {
5533
5676
  const cell = resolveCell(doc, s, target);
5534
- setCellNote(doc, s.chapterId, cell.sliceId, cell.swimLaneId, t);
5677
+ setCellNote(doc, s.sheetId, cell.sliceId, cell.swimLaneId, t);
5535
5678
  return `${verb} cell ${cell.address}`;
5536
5679
  }
5537
5680
  if (/^\d+$/.test(target)) {
@@ -5631,12 +5774,12 @@ function buildFromSpec(doc, modelId, nameArg, spec) {
5631
5774
  if (f.type && f.type !== inferred)
5632
5775
  throw new SheetAddressError(`Flow ${f.from}→${f.to} is ${inferred}, not ${f.type}.`);
5633
5776
  }
5634
- const chapterId = crypto.randomUUID();
5777
+ const sheetId = crypto.randomUUID();
5635
5778
  const idByAddress = {};
5636
5779
  doc.transact(() => {
5637
- const cd = ELEMENT_DIMENSIONS.chapter;
5638
- getScopeMap(doc, "chapters").set(chapterId, deepToY({ chapterId, modelId, name: sheetName, x: 0, y: 0, width: cd.width, height: cd.height }));
5639
- ensureSheet(doc, chapterId);
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);
5640
5783
  const sd = ELEMENT_DIMENSIONS.slice;
5641
5784
  const sliceIds = cols.map((c) => {
5642
5785
  const id = crypto.randomUUID();
@@ -5646,7 +5789,7 @@ function buildFromSpec(doc, modelId, nameArg, spec) {
5646
5789
  if (c.note)
5647
5790
  entry.note = c.note;
5648
5791
  getScopeMap(doc, "slices").set(id, deepToY(entry));
5649
- addColumn(doc, chapterId, id);
5792
+ addColumn(doc, sheetId, id);
5650
5793
  return id;
5651
5794
  });
5652
5795
  const ld = ELEMENT_DIMENSIONS.swimLane;
@@ -5656,7 +5799,7 @@ function buildFromSpec(doc, modelId, nameArg, spec) {
5656
5799
  if (r.note)
5657
5800
  entry.note = r.note;
5658
5801
  getScopeMap(doc, "swimLanes").set(id, deepToY(entry));
5659
- addRow(doc, chapterId, id);
5802
+ addRow(doc, sheetId, id);
5660
5803
  return id;
5661
5804
  });
5662
5805
  for (const op of ops) {
@@ -5678,10 +5821,10 @@ function buildFromSpec(doc, modelId, nameArg, spec) {
5678
5821
  width: SCENARIO_CARD.width,
5679
5822
  height: SCENARIO_CARD.height
5680
5823
  }));
5681
- placeInCell(doc, chapterId, sliceIds[op.ci], laneIds[op.ri], { stickyId: id, scope: "scenarios" });
5824
+ placeInCell(doc, sheetId, sliceIds[op.ci], laneIds[op.ri], { stickyId: id, scope: "scenarios" });
5682
5825
  } else {
5683
5826
  getScopeMap(doc, op.scope).set(id, deepToY({ ...op.data, [op.idKey]: id, modelId }));
5684
- placeInCell(doc, chapterId, sliceIds[op.ci], laneIds[op.ri], { stickyId: id, scope: op.scope });
5827
+ placeInCell(doc, sheetId, sliceIds[op.ci], laneIds[op.ri], { stickyId: id, scope: op.scope });
5685
5828
  }
5686
5829
  idByAddress[op.address] = id;
5687
5830
  }
@@ -5692,7 +5835,7 @@ function buildFromSpec(doc, modelId, nameArg, spec) {
5692
5835
  const id = crypto.randomUUID();
5693
5836
  const dim = FIXED_SIZE_DIM(op.scope);
5694
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] }));
5695
- placeInCell(doc, chapterId, sliceIds[op.ci], laneIds[op.ri], { stickyId: id, scope: op.scope });
5838
+ placeInCell(doc, sheetId, sliceIds[op.ci], laneIds[op.ri], { stickyId: id, scope: op.scope });
5696
5839
  idByAddress[op.address] = id;
5697
5840
  }
5698
5841
  for (const f of specFlows) {
@@ -5707,13 +5850,13 @@ function buildFromSpec(doc, modelId, nameArg, spec) {
5707
5850
  const ci = colIndexFromLabel(cl);
5708
5851
  const ri = rowNum - 1;
5709
5852
  if (ci >= 0 && ci < cols.length && ri >= 0 && ri < rows.length && text) {
5710
- setCellNote(doc, chapterId, sliceIds[ci], laneIds[ri], text);
5853
+ setCellNote(doc, sheetId, sliceIds[ci], laneIds[ri], text);
5711
5854
  }
5712
5855
  }
5713
5856
  });
5714
5857
  reflowAllSheets(doc);
5715
5858
  const nElems = ops.length;
5716
- return `built sheet "${sheetName}" — ${cols.length} slices, ${rows.length} lanes, ${nElems} elements, ${specFlows.length} flows ${chapterId}`;
5859
+ return `built sheet "${sheetName}" — ${cols.length} slices, ${rows.length} lanes, ${nElems} elements, ${specFlows.length} flows ${sheetId}`;
5717
5860
  }
5718
5861
  function buildSheetJson(doc, s) {
5719
5862
  const { columns, rows, cells } = s.structure;
@@ -5725,7 +5868,7 @@ function buildSheetJson(doc, s) {
5725
5868
  const e = getEntry(doc, "swimLanes", swimLaneId);
5726
5869
  return { label: String(i + 1), name: e?.name ?? "(unnamed)", laneKind: e?.laneKind ?? null, swimLaneId, note: e?.note ?? null };
5727
5870
  });
5728
- const cellNotes = readCellNotes(doc, s.chapterId);
5871
+ const cellNotes = readCellNotes(doc, s.sheetId);
5729
5872
  const cellNotesByAddr = {};
5730
5873
  for (const [k, text] of Object.entries(cellNotes)) {
5731
5874
  const [sliceId, swimLaneId] = k.split(":");
@@ -5748,7 +5891,7 @@ function buildSheetJson(doc, s) {
5748
5891
  }));
5749
5892
  });
5750
5893
  });
5751
- return { sheet: nameOf(doc, "chapters", s.chapterId), chapterId: s.chapterId, columns: columnViews, rows: rowViews, cells: cellViews, cellNotes: cellNotesByAddr };
5894
+ return { sheet: nameOf(doc, "sheets", s.sheetId), sheetId: s.sheetId, columns: columnViews, rows: rowViews, cells: cellViews, cellNotes: cellNotesByAddr };
5752
5895
  }
5753
5896
  function buildCellView(doc, s, cellArg) {
5754
5897
  const { ordinal } = parseCellAddress(cellArg);
@@ -5765,7 +5908,7 @@ function buildCellView(doc, s, cellArg) {
5765
5908
  const flows = getEntries(doc, "flows");
5766
5909
  return {
5767
5910
  cell: cell.address,
5768
- note: readCellNotes(doc, s.chapterId)[cellKey(cell.sliceId, cell.swimLaneId)] ?? null,
5911
+ note: readCellNotes(doc, s.sheetId)[cellKey(cell.sliceId, cell.swimLaneId)] ?? null,
5769
5912
  slice: { label: colLabel2(cell.colIndex), name: slice?.name ?? "(unnamed)", sliceId: cell.sliceId, note: slice?.note ?? null },
5770
5913
  lane: { label: String(cell.rowIndex + 1), name: lane?.name ?? "(unnamed)", laneKind: lane?.laneKind ?? null, swimLaneId: cell.swimLaneId, note: lane?.note ?? null },
5771
5914
  elements: refs.map((r) => ({
@@ -5811,7 +5954,7 @@ function registerSheetCommands(program) {
5811
5954
  return JSON.stringify(buildCellView(doc, s, cellArg), null, 2);
5812
5955
  if (opts.json)
5813
5956
  return JSON.stringify(buildSheetJson(doc, s), null, 2);
5814
- return renderSheetOverview(doc, s.chapterId) ?? "(empty sheet)";
5957
+ return renderSheetOverview(doc, s.sheetId) ?? "(empty sheet)";
5815
5958
  });
5816
5959
  console.log(output);
5817
5960
  } catch (err) {
@@ -5842,13 +5985,13 @@ function registerSheetCommands(program) {
5842
5985
  if (!name2)
5843
5986
  throw new SheetAddressError("Pass a <name> (or --from <file>).");
5844
5987
  const id = crypto.randomUUID();
5845
- const d = ELEMENT_DIMENSIONS.chapter;
5846
- const v = validateEntry("chapters", { name: name2, x: 0, y: 0, width: d.width, height: d.height });
5988
+ const d = ELEMENT_DIMENSIONS.sheet;
5989
+ const v = validateEntry("sheets", { name: name2, x: 0, y: 0, width: d.width, height: d.height });
5847
5990
  if (!v.ok)
5848
5991
  throw new SheetAddressError(`Invalid sheet: ${v.issues.join("; ")}`);
5849
5992
  const out = await withDoc(modelId, (doc) => {
5850
5993
  doc.transact(() => {
5851
- getScopeMap(doc, "chapters").set(id, deepToY({ ...v.data, chapterId: id, modelId }));
5994
+ getScopeMap(doc, "sheets").set(id, deepToY({ ...v.data, sheetId: id, modelId }));
5852
5995
  ensureSheet(doc, id);
5853
5996
  });
5854
5997
  reflowAllSheets(doc);
@@ -5863,13 +6006,38 @@ function registerSheetCommands(program) {
5863
6006
  throw err;
5864
6007
  }
5865
6008
  });
6009
+ sheet.command("delete [sheet]").description("Delete a whole sheet and everything in it — slices, lanes, elements, scenarios, flows. Destructive; pass --yes to confirm.").option("--yes", "Confirm the deletion (required — this cannot be undone)").option("--model <id>", "Target model id").action(async (sheetRef, opts) => {
6010
+ const modelId = resolveModelId(opts.model);
6011
+ try {
6012
+ const out = await withDoc(modelId, (doc) => {
6013
+ const s = resolveSheet2(doc, sheetRef);
6014
+ const name2 = getEntry(doc, "sheets", s.sheetId)?.name ?? s.sheetId;
6015
+ const elements = Object.values(s.structure.cells).reduce((n, refs) => n + refs.length, 0);
6016
+ const summary = `sheet "${name2}" — ${s.structure.columns.length} slice(s), ${s.structure.rows.length} lane(s), ${elements} element(s)`;
6017
+ if (!opts.yes) {
6018
+ return `Would delete ${summary}.
6019
+ This cannot be undone. Re-run with --yes to confirm.`;
6020
+ }
6021
+ deleteSheet(doc, s.sheetId);
6022
+ reflowAllSheets(doc);
6023
+ return `Deleted ${summary}.`;
6024
+ });
6025
+ console.log(out);
6026
+ } catch (err) {
6027
+ if (err instanceof SheetAddressError) {
6028
+ console.error(err.message);
6029
+ process.exit(2);
6030
+ }
6031
+ throw err;
6032
+ }
6033
+ });
5866
6034
  const insert = sheet.command("insert").description("Insert a slice (column), a lane (row), or an element into a cell");
5867
- 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 chapterId) 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))));
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))));
5868
6036
  for (const kind of LANE_KINDS) {
5869
- 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 chapterId) 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))));
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))));
5870
6038
  }
5871
6039
  for (const type of ELEMENT_TYPES) {
5872
- 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 chapterId) 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)));
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)));
5873
6041
  }
5874
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)));
5875
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))));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eventmodeler",
3
- "version": "0.6.12",
3
+ "version": "0.6.14",
4
4
  "description": "CLI tool for event modeling - explore, design, and generate code from your event models",
5
5
  "type": "module",
6
6
  "repository": {