@routevn/creator-model 1.5.2 → 1.6.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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/model.js +62 -7
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@routevn/creator-model",
3
- "version": "1.5.2",
3
+ "version": "1.6.0",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "license": "MIT",
package/src/model.js CHANGED
@@ -381,7 +381,7 @@ const LAYOUT_ELEMENT_BASE_TYPES = [
381
381
  "container-ref-confirm-dialog-ok",
382
382
  "container-ref-confirm-dialog-cancel",
383
383
  ];
384
- export const SCHEMA_VERSION = 5;
384
+ export const SCHEMA_VERSION = 6;
385
385
  const LAYOUT_CONTAINER_ELEMENT_TYPES = [
386
386
  "folder",
387
387
  "container",
@@ -13181,6 +13181,7 @@ const COMMAND_DEFINITIONS = [
13181
13181
  value: payload,
13182
13182
  allowedKeys: [
13183
13183
  "sectionId",
13184
+ "sceneId",
13184
13185
  "parentId",
13185
13186
  "index",
13186
13187
  "position",
@@ -13198,6 +13199,12 @@ const COMMAND_DEFINITIONS = [
13198
13199
  return invalidPayload("payload.sectionId must be a non-empty string");
13199
13200
  }
13200
13201
 
13202
+ if (payload.sceneId !== undefined && !isNonEmptyString(payload.sceneId)) {
13203
+ return invalidPayload(
13204
+ "payload.sceneId must be a non-empty string when provided",
13205
+ );
13206
+ }
13207
+
13201
13208
  if (
13202
13209
  payload.parentId !== undefined &&
13203
13210
  payload.parentId !== null &&
@@ -13229,10 +13236,42 @@ const COMMAND_DEFINITIONS = [
13229
13236
  );
13230
13237
  }
13231
13238
 
13239
+ const targetSceneId = payload.sceneId ?? location.sceneId;
13240
+ const targetScene = state.scenes.items[targetSceneId];
13241
+ if (!isPlainObject(targetScene)) {
13242
+ return invalidPrecondition(
13243
+ "payload.sceneId must reference an existing scene",
13244
+ );
13245
+ }
13246
+
13247
+ if (targetScene.type !== "scene") {
13248
+ return invalidPrecondition(
13249
+ "payload.sceneId must reference a non-folder scene",
13250
+ );
13251
+ }
13252
+
13253
+ const targetSections =
13254
+ targetScene.sections ?? createEmptyNestedCollection();
13232
13255
  const sectionNode = findTreeNode({
13233
13256
  nodes: location.sections.tree,
13234
13257
  nodeId: payload.sectionId,
13235
13258
  });
13259
+ const isCrossSceneMove = targetSceneId !== location.sceneId;
13260
+
13261
+ if (isCrossSceneMove) {
13262
+ const sourceSectionCount = Object.keys(
13263
+ location.sections?.items ?? {},
13264
+ ).length;
13265
+ const movedSectionCount = collectTreeDescendantIds({
13266
+ node: sectionNode,
13267
+ }).length;
13268
+
13269
+ if (sourceSectionCount <= movedSectionCount) {
13270
+ return invalidPrecondition(
13271
+ "payload.sectionId must not move the last section out of a scene",
13272
+ );
13273
+ }
13274
+ }
13236
13275
 
13237
13276
  if (payload.parentId !== undefined && payload.parentId !== null) {
13238
13277
  const parentLocation = findSectionLocation({
@@ -13245,9 +13284,9 @@ const COMMAND_DEFINITIONS = [
13245
13284
  );
13246
13285
  }
13247
13286
 
13248
- if (parentLocation.sceneId !== location.sceneId) {
13287
+ if (parentLocation.sceneId !== targetSceneId) {
13249
13288
  return invalidPrecondition(
13250
- "payload.parentId must reference a section in the same scene",
13289
+ "payload.parentId must reference a section in the target scene",
13251
13290
  );
13252
13291
  }
13253
13292
 
@@ -13281,14 +13320,14 @@ const COMMAND_DEFINITIONS = [
13281
13320
  );
13282
13321
  }
13283
13322
 
13284
- if (targetLocation.sceneId !== location.sceneId) {
13323
+ if (targetLocation.sceneId !== targetSceneId) {
13285
13324
  return invalidPrecondition(
13286
- "payload.positionTargetId must reference a section in the same scene",
13325
+ "payload.positionTargetId must reference a section in the target scene",
13287
13326
  );
13288
13327
  }
13289
13328
 
13290
13329
  const targetParentId = getNodeParentId({
13291
- tree: location.sections.tree,
13330
+ tree: targetSections.tree,
13292
13331
  nodeId: payload.positionTargetId,
13293
13332
  });
13294
13333
 
@@ -13304,6 +13343,10 @@ const COMMAND_DEFINITIONS = [
13304
13343
  state,
13305
13344
  sectionId: payload.sectionId,
13306
13345
  });
13346
+ const targetSceneId = payload.sceneId ?? location.sceneId;
13347
+ const targetScene = state.scenes.items[targetSceneId];
13348
+ targetScene.sections ??= createEmptyNestedCollection();
13349
+ const targetSections = targetScene.sections;
13307
13350
  const sectionNodeResult = removeNodeOrResult({
13308
13351
  tree: location.sections.tree,
13309
13352
  nodeId: payload.sectionId,
@@ -13313,8 +13356,20 @@ const COMMAND_DEFINITIONS = [
13313
13356
  return sectionNodeResult;
13314
13357
  }
13315
13358
 
13359
+ if (targetSections !== location.sections) {
13360
+ const movedSectionIds = collectTreeDescendantIds({
13361
+ node: sectionNodeResult.node,
13362
+ });
13363
+
13364
+ for (const movedSectionId of movedSectionIds) {
13365
+ targetSections.items[movedSectionId] =
13366
+ location.sections.items[movedSectionId];
13367
+ delete location.sections.items[movedSectionId];
13368
+ }
13369
+ }
13370
+
13316
13371
  insertTreeNode({
13317
- tree: location.sections.tree,
13372
+ tree: targetSections.tree,
13318
13373
  node: sectionNodeResult.node,
13319
13374
  parentId: payload.parentId ?? null,
13320
13375
  index: payload.index,