@routevn/creator-model 1.5.1 → 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 +161 -10
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@routevn/creator-model",
3
- "version": "1.5.1",
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",
@@ -2210,7 +2210,7 @@ const validateAnimationItems = ({ items, path, errorFactory }) => {
2210
2210
  }
2211
2211
 
2212
2212
  {
2213
- const result = validatePreviewObject({
2213
+ const result = validateAnimationPreviewObject({
2214
2214
  value: item.preview,
2215
2215
  path: `${itemPath}.preview`,
2216
2216
  errorFactory,
@@ -4906,6 +4906,102 @@ const validatePreviewObject = ({ value, path, errorFactory }) => {
4906
4906
  return VALID_RESULT;
4907
4907
  };
4908
4908
 
4909
+ const validateAnimationPreviewSlot = ({
4910
+ value,
4911
+ path,
4912
+ allowTransform = false,
4913
+ errorFactory,
4914
+ }) => {
4915
+ if (value === undefined) {
4916
+ return VALID_RESULT;
4917
+ }
4918
+
4919
+ if (!isPlainObject(value)) {
4920
+ return invalidFromErrorFactory(
4921
+ errorFactory,
4922
+ `${path} must be an object when provided`,
4923
+ );
4924
+ }
4925
+
4926
+ {
4927
+ const result = validateAllowedKeys({
4928
+ value,
4929
+ allowedKeys: allowTransform ? ["imageId", "transformId"] : ["imageId"],
4930
+ path,
4931
+ errorFactory,
4932
+ });
4933
+ if (result?.valid === false) {
4934
+ return result;
4935
+ }
4936
+ }
4937
+
4938
+ if (value.imageId !== undefined && !isNonEmptyString(value.imageId)) {
4939
+ return invalidFromErrorFactory(
4940
+ errorFactory,
4941
+ `${path}.imageId must be a non-empty string when provided`,
4942
+ );
4943
+ }
4944
+
4945
+ if (value.transformId !== undefined && !isNonEmptyString(value.transformId)) {
4946
+ return invalidFromErrorFactory(
4947
+ errorFactory,
4948
+ `${path}.transformId must be a non-empty string when provided`,
4949
+ );
4950
+ }
4951
+
4952
+ return VALID_RESULT;
4953
+ };
4954
+
4955
+ const validateAnimationPreviewObject = ({ value, path, errorFactory }) => {
4956
+ if (value === undefined) {
4957
+ return VALID_RESULT;
4958
+ }
4959
+
4960
+ if (!isPlainObject(value)) {
4961
+ return invalidFromErrorFactory(
4962
+ errorFactory,
4963
+ `${path} must be an object when provided`,
4964
+ );
4965
+ }
4966
+
4967
+ {
4968
+ const result = validateAllowedKeys({
4969
+ value,
4970
+ allowedKeys: ["background", "target", "outgoing", "incoming"],
4971
+ path,
4972
+ errorFactory,
4973
+ });
4974
+ if (result?.valid === false) {
4975
+ return result;
4976
+ }
4977
+ }
4978
+
4979
+ {
4980
+ const result = validateAnimationPreviewSlot({
4981
+ value: value.background,
4982
+ path: `${path}.background`,
4983
+ errorFactory,
4984
+ });
4985
+ if (result?.valid === false) {
4986
+ return result;
4987
+ }
4988
+ }
4989
+
4990
+ for (const key of ["target", "outgoing", "incoming"]) {
4991
+ const result = validateAnimationPreviewSlot({
4992
+ value: value[key],
4993
+ path: `${path}.${key}`,
4994
+ allowTransform: true,
4995
+ errorFactory,
4996
+ });
4997
+ if (result?.valid === false) {
4998
+ return result;
4999
+ }
5000
+ }
5001
+
5002
+ return VALID_RESULT;
5003
+ };
5004
+
4909
5005
  const validateTransformPreviewSlot = ({ value, path, errorFactory }) => {
4910
5006
  if (value === undefined) {
4911
5007
  return VALID_RESULT;
@@ -9164,7 +9260,7 @@ const validateAnimationCreateData = ({ data, errorFactory }) => {
9164
9260
  }
9165
9261
 
9166
9262
  {
9167
- const result = validatePreviewObject({
9263
+ const result = validateAnimationPreviewObject({
9168
9264
  value: data.preview,
9169
9265
  path: "payload.data.preview",
9170
9266
  errorFactory,
@@ -9250,7 +9346,7 @@ const validateAnimationUpdateData = ({ data, errorFactory }) => {
9250
9346
  }
9251
9347
 
9252
9348
  {
9253
- const result = validatePreviewObject({
9349
+ const result = validateAnimationPreviewObject({
9254
9350
  value: data.preview,
9255
9351
  path: "payload.data.preview",
9256
9352
  errorFactory,
@@ -13085,6 +13181,7 @@ const COMMAND_DEFINITIONS = [
13085
13181
  value: payload,
13086
13182
  allowedKeys: [
13087
13183
  "sectionId",
13184
+ "sceneId",
13088
13185
  "parentId",
13089
13186
  "index",
13090
13187
  "position",
@@ -13102,6 +13199,12 @@ const COMMAND_DEFINITIONS = [
13102
13199
  return invalidPayload("payload.sectionId must be a non-empty string");
13103
13200
  }
13104
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
+
13105
13208
  if (
13106
13209
  payload.parentId !== undefined &&
13107
13210
  payload.parentId !== null &&
@@ -13133,10 +13236,42 @@ const COMMAND_DEFINITIONS = [
13133
13236
  );
13134
13237
  }
13135
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();
13136
13255
  const sectionNode = findTreeNode({
13137
13256
  nodes: location.sections.tree,
13138
13257
  nodeId: payload.sectionId,
13139
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
+ }
13140
13275
 
13141
13276
  if (payload.parentId !== undefined && payload.parentId !== null) {
13142
13277
  const parentLocation = findSectionLocation({
@@ -13149,9 +13284,9 @@ const COMMAND_DEFINITIONS = [
13149
13284
  );
13150
13285
  }
13151
13286
 
13152
- if (parentLocation.sceneId !== location.sceneId) {
13287
+ if (parentLocation.sceneId !== targetSceneId) {
13153
13288
  return invalidPrecondition(
13154
- "payload.parentId must reference a section in the same scene",
13289
+ "payload.parentId must reference a section in the target scene",
13155
13290
  );
13156
13291
  }
13157
13292
 
@@ -13185,14 +13320,14 @@ const COMMAND_DEFINITIONS = [
13185
13320
  );
13186
13321
  }
13187
13322
 
13188
- if (targetLocation.sceneId !== location.sceneId) {
13323
+ if (targetLocation.sceneId !== targetSceneId) {
13189
13324
  return invalidPrecondition(
13190
- "payload.positionTargetId must reference a section in the same scene",
13325
+ "payload.positionTargetId must reference a section in the target scene",
13191
13326
  );
13192
13327
  }
13193
13328
 
13194
13329
  const targetParentId = getNodeParentId({
13195
- tree: location.sections.tree,
13330
+ tree: targetSections.tree,
13196
13331
  nodeId: payload.positionTargetId,
13197
13332
  });
13198
13333
 
@@ -13208,6 +13343,10 @@ const COMMAND_DEFINITIONS = [
13208
13343
  state,
13209
13344
  sectionId: payload.sectionId,
13210
13345
  });
13346
+ const targetSceneId = payload.sceneId ?? location.sceneId;
13347
+ const targetScene = state.scenes.items[targetSceneId];
13348
+ targetScene.sections ??= createEmptyNestedCollection();
13349
+ const targetSections = targetScene.sections;
13211
13350
  const sectionNodeResult = removeNodeOrResult({
13212
13351
  tree: location.sections.tree,
13213
13352
  nodeId: payload.sectionId,
@@ -13217,8 +13356,20 @@ const COMMAND_DEFINITIONS = [
13217
13356
  return sectionNodeResult;
13218
13357
  }
13219
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
+
13220
13371
  insertTreeNode({
13221
- tree: location.sections.tree,
13372
+ tree: targetSections.tree,
13222
13373
  node: sectionNodeResult.node,
13223
13374
  parentId: payload.parentId ?? null,
13224
13375
  index: payload.index,