@routevn/creator-model 1.4.0 → 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@routevn/creator-model",
3
- "version": "1.4.0",
3
+ "version": "1.5.0",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "license": "MIT",
package/src/index.js CHANGED
@@ -1,6 +1,7 @@
1
1
  export {
2
2
  replayCommands,
3
3
  SCHEMA_VERSION,
4
+ normalizeState,
4
5
  processCommand,
5
6
  validateAgainstState,
6
7
  validatePayload,
package/src/model.js CHANGED
@@ -45,6 +45,7 @@ const createEmptyCollectionState = () => ({
45
45
  items: {},
46
46
  tree: [],
47
47
  });
48
+ const VALID_VARIABLE_ITEM_TYPES = new Set(["folder", "variable"]);
48
49
  const TAG_SCOPE_BASE_KEYS = [
49
50
  "images",
50
51
  "sounds",
@@ -113,6 +114,123 @@ const normalizeTagsState = (tags) => {
113
114
  return nextTags;
114
115
  };
115
116
 
117
+ const filterVariableTreeNodes = ({ nodes, unsupportedItemIds }) => {
118
+ if (!Array.isArray(nodes)) {
119
+ return {
120
+ nodes,
121
+ changed: false,
122
+ removedIds: new Set(),
123
+ };
124
+ }
125
+
126
+ const filteredNodes = [];
127
+ const removedIds = new Set();
128
+ let changed = false;
129
+
130
+ for (const node of nodes) {
131
+ if (!isPlainObject(node)) {
132
+ filteredNodes.push(node);
133
+ continue;
134
+ }
135
+
136
+ if (unsupportedItemIds.has(node.id)) {
137
+ changed = true;
138
+ collectVariableTreeIds([node], removedIds);
139
+ continue;
140
+ }
141
+
142
+ const childrenResult = filterVariableTreeNodes({
143
+ nodes: node.children,
144
+ unsupportedItemIds,
145
+ });
146
+ for (const removedId of childrenResult.removedIds) {
147
+ removedIds.add(removedId);
148
+ }
149
+
150
+ if (childrenResult.changed) {
151
+ changed = true;
152
+ filteredNodes.push({
153
+ ...node,
154
+ children: childrenResult.nodes,
155
+ });
156
+ continue;
157
+ }
158
+
159
+ filteredNodes.push(node);
160
+ }
161
+
162
+ if (filteredNodes.length !== nodes.length) {
163
+ changed = true;
164
+ }
165
+
166
+ return {
167
+ nodes: changed ? filteredNodes : nodes,
168
+ changed,
169
+ removedIds,
170
+ };
171
+ };
172
+
173
+ const collectVariableTreeIds = (nodes, ids = new Set()) => {
174
+ if (!Array.isArray(nodes)) {
175
+ return ids;
176
+ }
177
+
178
+ for (const node of nodes) {
179
+ if (!isPlainObject(node) || !isNonEmptyString(node.id)) {
180
+ continue;
181
+ }
182
+
183
+ ids.add(node.id);
184
+ collectVariableTreeIds(node.children, ids);
185
+ }
186
+
187
+ return ids;
188
+ };
189
+
190
+ const normalizeVariablesCollection = (variables) => {
191
+ if (!isPlainObject(variables) || !isPlainObject(variables.items)) {
192
+ return variables;
193
+ }
194
+
195
+ const unsupportedItemIds = new Set();
196
+ const nextItems = {};
197
+ let didFilterItems = false;
198
+
199
+ for (const [itemId, item] of Object.entries(variables.items)) {
200
+ if (!VALID_VARIABLE_ITEM_TYPES.has(item?.type)) {
201
+ unsupportedItemIds.add(itemId);
202
+ didFilterItems = true;
203
+ continue;
204
+ }
205
+
206
+ nextItems[itemId] = item;
207
+ }
208
+
209
+ const treeResult = filterVariableTreeNodes({
210
+ nodes: variables.tree,
211
+ unsupportedItemIds,
212
+ });
213
+ const nextTree = treeResult.nodes;
214
+ const didFilterTree = treeResult.changed;
215
+
216
+ for (const removedId of treeResult.removedIds) {
217
+ if (Object.hasOwn(nextItems, removedId)) {
218
+ delete nextItems[removedId];
219
+ didFilterItems = true;
220
+ }
221
+ }
222
+
223
+ if (!didFilterItems && !didFilterTree) {
224
+ return variables;
225
+ }
226
+
227
+ return {
228
+ ...variables,
229
+ items: nextItems,
230
+ tree: nextTree,
231
+ };
232
+ };
233
+
116
234
  const normalizeStateCollections = (state) => {
117
235
  if (!isPlainObject(state)) {
118
236
  return state;
@@ -125,8 +243,14 @@ const normalizeStateCollections = (state) => {
125
243
  ].filter((key) => state[key] === undefined);
126
244
  const normalizedTags = normalizeTagsState(state.tags);
127
245
  const hasNormalizedTags = normalizedTags !== state.tags;
246
+ const normalizedVariables = normalizeVariablesCollection(state.variables);
247
+ const hasNormalizedVariables = normalizedVariables !== state.variables;
128
248
 
129
- if (missingCollectionKeys.length === 0 && !hasNormalizedTags) {
249
+ if (
250
+ missingCollectionKeys.length === 0 &&
251
+ !hasNormalizedTags &&
252
+ !hasNormalizedVariables
253
+ ) {
130
254
  return state;
131
255
  }
132
256
 
@@ -141,6 +265,9 @@ const normalizeStateCollections = (state) => {
141
265
  if (hasNormalizedTags) {
142
266
  nextState.tags = normalizedTags;
143
267
  }
268
+ if (hasNormalizedVariables) {
269
+ nextState.variables = normalizedVariables;
270
+ }
144
271
 
145
272
  return nextState;
146
273
  };
@@ -249,7 +376,7 @@ const LAYOUT_ELEMENT_BASE_TYPES = [
249
376
  "container-ref-confirm-dialog-ok",
250
377
  "container-ref-confirm-dialog-cancel",
251
378
  ];
252
- export const SCHEMA_VERSION = 4;
379
+ export const SCHEMA_VERSION = 5;
253
380
  const LAYOUT_CONTAINER_ELEMENT_TYPES = [
254
381
  "folder",
255
382
  "container",
@@ -3265,6 +3392,8 @@ const validateLayoutElementData = ({
3265
3392
  "hover",
3266
3393
  "click",
3267
3394
  "rightClick",
3395
+ "scrollUp",
3396
+ "scrollDown",
3268
3397
  "anchorToBottom",
3269
3398
  "thumbImageId",
3270
3399
  "barImageId",
@@ -3714,6 +3843,32 @@ const validateLayoutElementData = ({
3714
3843
  }
3715
3844
  }
3716
3845
 
3846
+ if (data.scrollUp !== undefined) {
3847
+ {
3848
+ const result = validateLayoutElementInteraction({
3849
+ interaction: data.scrollUp,
3850
+ path: `${path}.scrollUp`,
3851
+ errorFactory,
3852
+ });
3853
+ if (result?.valid === false) {
3854
+ return result;
3855
+ }
3856
+ }
3857
+ }
3858
+
3859
+ if (data.scrollDown !== undefined) {
3860
+ {
3861
+ const result = validateLayoutElementInteraction({
3862
+ interaction: data.scrollDown,
3863
+ path: `${path}.scrollDown`,
3864
+ errorFactory,
3865
+ });
3866
+ if (result?.valid === false) {
3867
+ return result;
3868
+ }
3869
+ }
3870
+ }
3871
+
3717
3872
  if (
3718
3873
  data.anchorToBottom !== undefined &&
3719
3874
  typeof data.anchorToBottom !== "boolean"
@@ -3813,6 +3968,8 @@ const validateLayoutElementItems = ({ items, path, errorFactory }) => {
3813
3968
  "hover",
3814
3969
  "click",
3815
3970
  "rightClick",
3971
+ "scrollUp",
3972
+ "scrollDown",
3816
3973
  "anchorToBottom",
3817
3974
  "thumbImageId",
3818
3975
  "barImageId",
@@ -7276,6 +7433,8 @@ const runValidateState = ({ state }) => {
7276
7433
 
7277
7434
  export const validateState = ({ state }) => runValidateState({ state });
7278
7435
 
7436
+ export const normalizeState = ({ state }) => normalizeStateCollections(state);
7437
+
7279
7438
  const validatePlacementFields = ({ payload, errorFactory }) => {
7280
7439
  if (
7281
7440
  payload.index !== undefined &&