@lvce-editor/panel-worker 2.2.0 → 2.3.1

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.
@@ -63,7 +63,7 @@ class AssertionError extends Error {
63
63
  const Object$1 = 1;
64
64
  const Number$1 = 2;
65
65
  const Array$1 = 3;
66
- const String = 4;
66
+ const String$1 = 4;
67
67
  const Boolean$1 = 5;
68
68
  const Function = 6;
69
69
  const Null = 7;
@@ -75,7 +75,7 @@ const getType = value => {
75
75
  case 'function':
76
76
  return Function;
77
77
  case 'string':
78
- return String;
78
+ return String$1;
79
79
  case 'object':
80
80
  if (value === null) {
81
81
  return Null;
@@ -98,7 +98,7 @@ const object = value => {
98
98
  };
99
99
  const string = value => {
100
100
  const type = getType(value);
101
- if (type !== String) {
101
+ if (type !== String$1) {
102
102
  throw new AssertionError('expected value to be of type string');
103
103
  }
104
104
  };
@@ -1003,11 +1003,175 @@ const Tab = 'tab';
1003
1003
  const TabList = 'tablist';
1004
1004
  const ToolBar = 'toolbar';
1005
1005
 
1006
+ const Audio = 0;
1006
1007
  const Button = 1;
1008
+ const Col = 2;
1009
+ const ColGroup = 3;
1007
1010
  const Div = 4;
1011
+ const H1 = 5;
1012
+ const Input = 6;
1013
+ const Kbd = 7;
1014
+ const Span = 8;
1015
+ const Table = 9;
1016
+ const TBody = 10;
1017
+ const Td = 11;
1008
1018
  const Text = 12;
1019
+ const Th = 13;
1020
+ const THead = 14;
1021
+ const Tr = 15;
1022
+ const I = 16;
1023
+ const Img = 17;
1024
+ const Root = 0;
1025
+ const Ins = 20;
1026
+ const Del = 21;
1027
+ const H2 = 22;
1028
+ const H3 = 23;
1029
+ const H4 = 24;
1030
+ const H5 = 25;
1031
+ const H6 = 26;
1032
+ const Article = 27;
1033
+ const Aside = 28;
1034
+ const Footer = 29;
1035
+ const Header = 30;
1036
+ const Nav = 40;
1037
+ const Section = 41;
1038
+ const Search = 42;
1039
+ const Dd = 43;
1040
+ const Dl = 44;
1041
+ const Figcaption = 45;
1042
+ const Figure = 46;
1043
+ const Hr = 47;
1044
+ const Li = 48;
1045
+ const Ol = 49;
1046
+ const P = 50;
1047
+ const Pre = 51;
1048
+ const A = 53;
1049
+ const Abbr = 54;
1050
+ const Br = 55;
1051
+ const Cite = 56;
1052
+ const Data = 57;
1053
+ const Time = 58;
1054
+ const Tfoot = 59;
1055
+ const Ul = 60;
1056
+ const Video = 61;
1057
+ const TextArea = 62;
1058
+ const Select = 63;
1059
+ const Option = 64;
1060
+ const Code = 65;
1061
+ const Label = 66;
1062
+ const Dt = 67;
1063
+ const Iframe = 68;
1064
+ const Main = 69;
1065
+ const Strong = 70;
1066
+ const Em = 71;
1067
+ const Style = 72;
1068
+ const Html = 73;
1069
+ const Head = 74;
1070
+ const Title = 75;
1071
+ const Meta = 76;
1072
+ const Canvas = 77;
1073
+ const Form = 78;
1074
+ const BlockQuote = 79;
1075
+ const Quote = 80;
1076
+ const Circle = 81;
1077
+ const Defs = 82;
1078
+ const Ellipse = 83;
1079
+ const G = 84;
1080
+ const Line = 85;
1081
+ const Path = 86;
1082
+ const Polygon = 87;
1083
+ const Polyline = 88;
1084
+ const Rect = 89;
1085
+ const Svg = 90;
1086
+ const Use = 91;
1009
1087
  const Reference = 100;
1010
1088
 
1089
+ const VirtualDomElements = {
1090
+ __proto__: null,
1091
+ A,
1092
+ Abbr,
1093
+ Article,
1094
+ Aside,
1095
+ Audio,
1096
+ BlockQuote,
1097
+ Br,
1098
+ Button,
1099
+ Canvas,
1100
+ Circle,
1101
+ Cite,
1102
+ Code,
1103
+ Col,
1104
+ ColGroup,
1105
+ Data,
1106
+ Dd,
1107
+ Defs,
1108
+ Del,
1109
+ Div,
1110
+ Dl,
1111
+ Dt,
1112
+ Ellipse,
1113
+ Em,
1114
+ Figcaption,
1115
+ Figure,
1116
+ Footer,
1117
+ Form,
1118
+ G,
1119
+ H1,
1120
+ H2,
1121
+ H3,
1122
+ H4,
1123
+ H5,
1124
+ H6,
1125
+ Head,
1126
+ Header,
1127
+ Hr,
1128
+ Html,
1129
+ I,
1130
+ Iframe,
1131
+ Img,
1132
+ Input,
1133
+ Ins,
1134
+ Kbd,
1135
+ Label,
1136
+ Li,
1137
+ Line,
1138
+ Main,
1139
+ Meta,
1140
+ Nav,
1141
+ Ol,
1142
+ Option,
1143
+ P,
1144
+ Path,
1145
+ Polygon,
1146
+ Polyline,
1147
+ Pre,
1148
+ Quote,
1149
+ Rect,
1150
+ Reference,
1151
+ Root,
1152
+ Search,
1153
+ Section,
1154
+ Select,
1155
+ Span,
1156
+ Strong,
1157
+ Style,
1158
+ Svg,
1159
+ TBody,
1160
+ THead,
1161
+ Table,
1162
+ Td,
1163
+ Text,
1164
+ TextArea,
1165
+ Tfoot,
1166
+ Th,
1167
+ Time,
1168
+ Title,
1169
+ Tr,
1170
+ Ul,
1171
+ Use,
1172
+ Video
1173
+ };
1174
+
1011
1175
  const TargetName = 'event.target.name';
1012
1176
 
1013
1177
  const RendererWorker = 1;
@@ -1024,29 +1188,87 @@ const toCommandId = key => {
1024
1188
  return key.slice(dotIndex + 1);
1025
1189
  };
1026
1190
  const create$1 = () => {
1191
+ const commandQueues = new Map();
1192
+ const generations = Object.create(null);
1027
1193
  const states = Object.create(null);
1028
1194
  const commandMapRef = {};
1195
+ const getGeneration = uid => generations[uid] || 0;
1196
+ const isCurrentGeneration = (uid, generation) => {
1197
+ return states[uid] !== undefined && getGeneration(uid) === generation;
1198
+ };
1199
+ const updateState = (uid, generation, fallbackState, updater) => {
1200
+ if (!isCurrentGeneration(uid, generation)) {
1201
+ return Promise.resolve(fallbackState);
1202
+ }
1203
+ const current = states[uid];
1204
+ const updatedState = updater(current.newState);
1205
+ if (updatedState !== current.newState) {
1206
+ states[uid] = {
1207
+ newState: updatedState,
1208
+ oldState: current.oldState,
1209
+ scheduledState: updatedState
1210
+ };
1211
+ }
1212
+ return Promise.resolve(updatedState);
1213
+ };
1214
+ const createAsyncCommandContext = (uid, generation) => {
1215
+ let latestState = states[uid].newState;
1216
+ return {
1217
+ getState: () => {
1218
+ if (isCurrentGeneration(uid, generation)) {
1219
+ latestState = states[uid].newState;
1220
+ }
1221
+ return latestState;
1222
+ },
1223
+ updateState: async updater => {
1224
+ latestState = await updateState(uid, generation, latestState, updater);
1225
+ return latestState;
1226
+ }
1227
+ };
1228
+ };
1229
+ const enqueueCommand = async (uid, command) => {
1230
+ const previous = commandQueues.get(uid) || Promise.resolve();
1231
+ const run = async () => {
1232
+ try {
1233
+ await previous;
1234
+ } catch {
1235
+ // The previous caller receives its error; later commands must still run.
1236
+ }
1237
+ await command();
1238
+ };
1239
+ const current = run();
1240
+ commandQueues.set(uid, current);
1241
+ try {
1242
+ await current;
1243
+ } finally {
1244
+ if (commandQueues.get(uid) === current) {
1245
+ commandQueues.delete(uid);
1246
+ }
1247
+ }
1248
+ };
1029
1249
  return {
1030
1250
  clear() {
1251
+ commandQueues.clear();
1031
1252
  for (const key of Object.keys(states)) {
1032
1253
  delete states[key];
1033
1254
  }
1034
1255
  },
1035
1256
  diff(uid, modules, numbers) {
1036
1257
  const {
1037
- newState,
1038
- oldState
1258
+ oldState,
1259
+ scheduledState
1039
1260
  } = states[uid];
1040
1261
  const diffResult = [];
1041
1262
  for (let i = 0; i < modules.length; i++) {
1042
1263
  const fn = modules[i];
1043
- if (!fn(oldState, newState)) {
1264
+ if (!fn(oldState, scheduledState)) {
1044
1265
  diffResult.push(numbers[i]);
1045
1266
  }
1046
1267
  }
1047
1268
  return diffResult;
1048
1269
  },
1049
1270
  dispose(uid) {
1271
+ commandQueues.delete(uid);
1050
1272
  delete states[uid];
1051
1273
  },
1052
1274
  get(uid) {
@@ -1058,21 +1280,33 @@ const create$1 = () => {
1058
1280
  return ids;
1059
1281
  },
1060
1282
  getKeys() {
1061
- return Object.keys(states).map(key => {
1062
- return Number.parseFloat(key);
1063
- });
1283
+ return Object.keys(states).map(Number);
1064
1284
  },
1065
1285
  registerCommands(commandMap) {
1066
1286
  Object.assign(commandMapRef, commandMap);
1067
1287
  },
1068
- set(uid, oldState, newState) {
1288
+ set(uid, oldState, newState, scheduledState) {
1289
+ const current = states[uid];
1290
+ if (!current || oldState === newState && newState !== current.newState) {
1291
+ generations[uid] = getGeneration(uid) + 1;
1292
+ }
1069
1293
  states[uid] = {
1070
1294
  newState,
1071
- oldState
1295
+ oldState,
1296
+ scheduledState: scheduledState ?? newState
1072
1297
  };
1073
1298
  },
1299
+ wrapAsyncCommand(fn) {
1300
+ const wrapped = async (uid, ...args) => {
1301
+ const generation = getGeneration(uid);
1302
+ const context = createAsyncCommandContext(uid, generation);
1303
+ await fn(context, ...args);
1304
+ };
1305
+ return wrapped;
1306
+ },
1074
1307
  wrapCommand(fn) {
1075
1308
  const wrapped = async (uid, ...args) => {
1309
+ const generation = getGeneration(uid);
1076
1310
  const {
1077
1311
  newState,
1078
1312
  oldState
@@ -1081,6 +1315,9 @@ const create$1 = () => {
1081
1315
  if (oldState === newerState || newState === newerState) {
1082
1316
  return;
1083
1317
  }
1318
+ if (!isCurrentGeneration(uid, generation)) {
1319
+ return;
1320
+ }
1084
1321
  const latestOld = states[uid];
1085
1322
  const latestNew = {
1086
1323
  ...latestOld.newState,
@@ -1088,7 +1325,8 @@ const create$1 = () => {
1088
1325
  };
1089
1326
  states[uid] = {
1090
1327
  newState: latestNew,
1091
- oldState: latestOld.oldState
1328
+ oldState: latestOld.oldState,
1329
+ scheduledState: latestNew
1092
1330
  };
1093
1331
  };
1094
1332
  return wrapped;
@@ -1104,6 +1342,7 @@ const create$1 = () => {
1104
1342
  },
1105
1343
  wrapLoadContent(fn) {
1106
1344
  const wrapped = async (uid, ...args) => {
1345
+ const generation = getGeneration(uid);
1107
1346
  const {
1108
1347
  newState,
1109
1348
  oldState
@@ -1118,6 +1357,11 @@ const create$1 = () => {
1118
1357
  error
1119
1358
  };
1120
1359
  }
1360
+ if (!isCurrentGeneration(uid, generation)) {
1361
+ return {
1362
+ error
1363
+ };
1364
+ }
1121
1365
  const latestOld = states[uid];
1122
1366
  const latestNew = {
1123
1367
  ...latestOld.newState,
@@ -1125,13 +1369,59 @@ const create$1 = () => {
1125
1369
  };
1126
1370
  states[uid] = {
1127
1371
  newState: latestNew,
1128
- oldState: latestOld.oldState
1372
+ oldState: latestOld.oldState,
1373
+ scheduledState: latestNew
1129
1374
  };
1130
1375
  return {
1131
1376
  error
1132
1377
  };
1133
1378
  };
1134
1379
  return wrapped;
1380
+ },
1381
+ wrapSerialAsyncCommand(fn) {
1382
+ const wrapped = async (uid, ...args) => {
1383
+ await enqueueCommand(uid, async () => {
1384
+ if (!states[uid]) {
1385
+ return;
1386
+ }
1387
+ const generation = getGeneration(uid);
1388
+ const context = createAsyncCommandContext(uid, generation);
1389
+ await fn(context, ...args);
1390
+ });
1391
+ };
1392
+ return wrapped;
1393
+ },
1394
+ wrapSerialCommand(fn) {
1395
+ const wrapped = async (uid, ...args) => {
1396
+ await enqueueCommand(uid, async () => {
1397
+ if (!states[uid]) {
1398
+ return;
1399
+ }
1400
+ const generation = getGeneration(uid);
1401
+ const {
1402
+ newState,
1403
+ oldState
1404
+ } = states[uid];
1405
+ const newerState = await fn(newState, ...args);
1406
+ if (oldState === newerState || newState === newerState) {
1407
+ return;
1408
+ }
1409
+ if (!isCurrentGeneration(uid, generation)) {
1410
+ return;
1411
+ }
1412
+ const latestOld = states[uid];
1413
+ const latestNew = {
1414
+ ...latestOld.newState,
1415
+ ...newerState
1416
+ };
1417
+ states[uid] = {
1418
+ newState: latestNew,
1419
+ oldState: latestOld.oldState,
1420
+ scheduledState: latestNew
1421
+ };
1422
+ });
1423
+ };
1424
+ return wrapped;
1135
1425
  }
1136
1426
  };
1137
1427
  };
@@ -1275,8 +1565,8 @@ const getSavedViewletId = savedState => {
1275
1565
  return Problems;
1276
1566
  };
1277
1567
 
1278
- const createViewlet = async (viewletModuleId, editorUid, tabId, actionsUid, bounds, uri) => {
1279
- await invoke('Layout.createPanelViewlet', viewletModuleId, editorUid, tabId, actionsUid, bounds, uri);
1568
+ const createViewlet = async (viewletModuleId, editorUid, tabId, actionsUid, bounds, uri, focus) => {
1569
+ await invoke('Layout.createPanelViewlet', viewletModuleId, editorUid, tabId, actionsUid, bounds, uri, focus);
1280
1570
  };
1281
1571
 
1282
1572
  const getContentDimensions = dimensions => {
@@ -1301,7 +1591,7 @@ const openViewlet = async (state, id, focus = false) => {
1301
1591
  const tabId = getUid();
1302
1592
  const actionsUid = getUid();
1303
1593
  const index = views.indexOf(id);
1304
- await createViewlet(id, childUid, tabId, actionsUid, childDimensions, '');
1594
+ await createViewlet(id, childUid, tabId, actionsUid, childDimensions, '', focus);
1305
1595
  return {
1306
1596
  ...state,
1307
1597
  actionsUid,
@@ -1327,7 +1617,7 @@ const selectIndex = async (state, index) => {
1327
1617
  const {
1328
1618
  views
1329
1619
  } = state;
1330
- return openViewlet(state, views[index]);
1620
+ return openViewlet(state, views[index], true);
1331
1621
  };
1332
1622
 
1333
1623
  const selectRaw = async (state, rawIndex) => {
@@ -1391,6 +1681,8 @@ const text = data => {
1391
1681
  };
1392
1682
  };
1393
1683
 
1684
+ new Set(Object.values(VirtualDomElements));
1685
+
1394
1686
  const SetText = 1;
1395
1687
  const Replace = 2;
1396
1688
  const SetAttribute = 3;
@@ -1462,21 +1754,18 @@ const getChildrenWithCount = (nodes, startIndex, childCount) => {
1462
1754
  };
1463
1755
 
1464
1756
  const compareNodes = (oldNode, newNode) => {
1465
- const patches = [];
1466
1757
  // Check if node type changed - return null to signal incompatible nodes
1467
1758
  // (caller should handle this with a Replace operation)
1468
1759
  if (oldNode.type !== newNode.type) {
1469
1760
  return null;
1470
1761
  }
1762
+ const patches = [];
1471
1763
  // Handle reference nodes - special handling for uid changes
1472
- if (oldNode.type === Reference) {
1473
- if (oldNode.uid !== newNode.uid) {
1474
- patches.push({
1475
- type: SetReferenceNodeUid,
1476
- uid: newNode.uid
1477
- });
1478
- }
1479
- return patches;
1764
+ if (oldNode.type === Reference && oldNode.uid !== newNode.uid) {
1765
+ patches.push({
1766
+ type: SetReferenceNodeUid,
1767
+ uid: newNode.uid
1768
+ });
1480
1769
  }
1481
1770
  // Handle text nodes
1482
1771
  if (oldNode.type === Text && newNode.type === Text) {
@@ -1489,8 +1778,8 @@ const compareNodes = (oldNode, newNode) => {
1489
1778
  return patches;
1490
1779
  }
1491
1780
  // Compare attributes
1492
- const oldKeys = getKeys(oldNode);
1493
- const newKeys = getKeys(newNode);
1781
+ const oldKeys = getKeys(oldNode).filter(key => oldNode.type !== Reference || key !== 'uid');
1782
+ const newKeys = getKeys(newNode).filter(key => newNode.type !== Reference || key !== 'uid');
1494
1783
  // Check for attribute changes
1495
1784
  for (const key of newKeys) {
1496
1785
  if (oldNode[key] !== newNode[key]) {
@@ -1503,7 +1792,7 @@ const compareNodes = (oldNode, newNode) => {
1503
1792
  }
1504
1793
  // Check for removed attributes
1505
1794
  for (const key of oldKeys) {
1506
- if (!(key in newNode)) {
1795
+ if (!Object.hasOwn(newNode, key)) {
1507
1796
  patches.push({
1508
1797
  type: RemoveAttribute,
1509
1798
  key
@@ -1521,11 +1810,78 @@ const treeToArray = node => {
1521
1810
  return result;
1522
1811
  };
1523
1812
 
1813
+ const navigateToChild = (patches, currentChildIndex, index) => {
1814
+ if (currentChildIndex === -1) {
1815
+ patches.push({
1816
+ type: NavigateChild,
1817
+ index
1818
+ });
1819
+ return index;
1820
+ }
1821
+ if (currentChildIndex !== index) {
1822
+ patches.push({
1823
+ type: NavigateSibling,
1824
+ index
1825
+ });
1826
+ }
1827
+ return index;
1828
+ };
1829
+ const navigateToParent = (patches, currentChildIndex) => {
1830
+ if (currentChildIndex >= 0) {
1831
+ patches.push({
1832
+ type: NavigateParent
1833
+ });
1834
+ }
1835
+ return -1;
1836
+ };
1837
+ const addTree = (newNode, patches) => {
1838
+ patches.push({
1839
+ type: Add,
1840
+ nodes: treeToArray(newNode)
1841
+ });
1842
+ };
1843
+ const replaceTree = (newNode, patches) => {
1844
+ patches.push({
1845
+ type: Replace,
1846
+ nodes: treeToArray(newNode)
1847
+ });
1848
+ };
1849
+ const diffExistingChild = (oldNode, newNode, patches, currentChildIndex, index) => {
1850
+ const nodePatches = compareNodes(oldNode.node, newNode.node);
1851
+ if (nodePatches === null) {
1852
+ const nextChildIndex = navigateToChild(patches, currentChildIndex, index);
1853
+ replaceTree(newNode, patches);
1854
+ return nextChildIndex;
1855
+ }
1856
+ const hasChildrenToCompare = oldNode.children.length > 0 || newNode.children.length > 0;
1857
+ if (nodePatches.length === 0 && !hasChildrenToCompare) {
1858
+ return currentChildIndex;
1859
+ }
1860
+ const nextChildIndex = navigateToChild(patches, currentChildIndex, index);
1861
+ if (nodePatches.length > 0) {
1862
+ patches.push(...nodePatches);
1863
+ }
1864
+ if (hasChildrenToCompare) {
1865
+ diffChildren(oldNode.children, newNode.children, patches);
1866
+ }
1867
+ return nextChildIndex;
1868
+ };
1869
+ const diffRootNode = (oldNode, newNode, patches) => {
1870
+ const nodePatches = compareNodes(oldNode.node, newNode.node);
1871
+ if (nodePatches === null) {
1872
+ replaceTree(newNode, patches);
1873
+ return;
1874
+ }
1875
+ if (nodePatches.length > 0) {
1876
+ patches.push(...nodePatches);
1877
+ }
1878
+ if (oldNode.children.length > 0 || newNode.children.length > 0) {
1879
+ diffChildren(oldNode.children, newNode.children, patches);
1880
+ }
1881
+ };
1524
1882
  const diffChildren = (oldChildren, newChildren, patches) => {
1525
1883
  const maxLength = Math.max(oldChildren.length, newChildren.length);
1526
- // Track where we are: -1 means at parent, >= 0 means at child index
1527
1884
  let currentChildIndex = -1;
1528
- // Collect indices of children to remove (we'll add these patches at the end in reverse order)
1529
1885
  const indicesToRemove = [];
1530
1886
  for (let i = 0; i < maxLength; i++) {
1531
1887
  const oldNode = oldChildren[i];
@@ -1534,88 +1890,17 @@ const diffChildren = (oldChildren, newChildren, patches) => {
1534
1890
  continue;
1535
1891
  }
1536
1892
  if (!oldNode) {
1537
- // Add new node - we should be at the parent
1538
- if (currentChildIndex >= 0) {
1539
- // Navigate back to parent
1540
- patches.push({
1541
- type: NavigateParent
1542
- });
1543
- currentChildIndex = -1;
1544
- }
1545
- // Flatten the entire subtree so renderInternal can handle it
1546
- const flatNodes = treeToArray(newNode);
1547
- patches.push({
1548
- type: Add,
1549
- nodes: flatNodes
1550
- });
1551
- } else if (newNode) {
1552
- // Compare nodes to see if we need any patches
1553
- const nodePatches = compareNodes(oldNode.node, newNode.node);
1554
- // If nodePatches is null, the node types are incompatible - need to replace
1555
- if (nodePatches === null) {
1556
- // Navigate to this child
1557
- if (currentChildIndex === -1) {
1558
- patches.push({
1559
- type: NavigateChild,
1560
- index: i
1561
- });
1562
- currentChildIndex = i;
1563
- } else if (currentChildIndex !== i) {
1564
- patches.push({
1565
- type: NavigateSibling,
1566
- index: i
1567
- });
1568
- currentChildIndex = i;
1569
- }
1570
- // Replace the entire subtree
1571
- const flatNodes = treeToArray(newNode);
1572
- patches.push({
1573
- type: Replace,
1574
- nodes: flatNodes
1575
- });
1576
- // After replace, we're at the new element (same position)
1577
- continue;
1578
- }
1579
- // Check if we need to recurse into children
1580
- const hasChildrenToCompare = oldNode.children.length > 0 || newNode.children.length > 0;
1581
- // Only navigate to this element if we need to do something
1582
- if (nodePatches.length > 0 || hasChildrenToCompare) {
1583
- // Navigate to this child if not already there
1584
- if (currentChildIndex === -1) {
1585
- patches.push({
1586
- type: NavigateChild,
1587
- index: i
1588
- });
1589
- currentChildIndex = i;
1590
- } else if (currentChildIndex !== i) {
1591
- patches.push({
1592
- type: NavigateSibling,
1593
- index: i
1594
- });
1595
- currentChildIndex = i;
1596
- }
1597
- // Apply node patches (these apply to the current element, not children)
1598
- if (nodePatches.length > 0) {
1599
- patches.push(...nodePatches);
1600
- }
1601
- // Compare children recursively
1602
- if (hasChildrenToCompare) {
1603
- diffChildren(oldNode.children, newNode.children, patches);
1604
- }
1605
- }
1606
- } else {
1607
- // Remove old node - collect the index for later removal
1893
+ currentChildIndex = navigateToParent(patches, currentChildIndex);
1894
+ addTree(newNode, patches);
1895
+ continue;
1896
+ }
1897
+ if (!newNode) {
1608
1898
  indicesToRemove.push(i);
1899
+ continue;
1609
1900
  }
1901
+ currentChildIndex = diffExistingChild(oldNode, newNode, patches, currentChildIndex, i);
1610
1902
  }
1611
- // Navigate back to parent if we ended at a child
1612
- if (currentChildIndex >= 0) {
1613
- patches.push({
1614
- type: NavigateParent
1615
- });
1616
- }
1617
- // Add remove patches in reverse order (highest index first)
1618
- // This ensures indices remain valid as we remove
1903
+ navigateToParent(patches, currentChildIndex);
1619
1904
  for (let j = indicesToRemove.length - 1; j >= 0; j--) {
1620
1905
  patches.push({
1621
1906
  type: RemoveChild,
@@ -1624,47 +1909,22 @@ const diffChildren = (oldChildren, newChildren, patches) => {
1624
1909
  }
1625
1910
  };
1626
1911
  const diffTrees = (oldTree, newTree, patches, path) => {
1627
- // At the root level (path.length === 0), we're already AT the element
1628
- // So we compare the root node directly, then compare its children
1629
1912
  if (path.length === 0 && oldTree.length === 1 && newTree.length === 1) {
1630
- const oldNode = oldTree[0];
1631
- const newNode = newTree[0];
1632
- // Compare root nodes
1633
- const nodePatches = compareNodes(oldNode.node, newNode.node);
1634
- // If nodePatches is null, the root node types are incompatible - need to replace
1635
- if (nodePatches === null) {
1636
- const flatNodes = treeToArray(newNode);
1637
- patches.push({
1638
- type: Replace,
1639
- nodes: flatNodes
1640
- });
1641
- return;
1642
- }
1643
- if (nodePatches.length > 0) {
1644
- patches.push(...nodePatches);
1645
- }
1646
- // Compare children
1647
- if (oldNode.children.length > 0 || newNode.children.length > 0) {
1648
- diffChildren(oldNode.children, newNode.children, patches);
1649
- }
1650
- } else {
1651
- // Non-root level or multiple root elements - use the regular comparison
1652
- diffChildren(oldTree, newTree, patches);
1913
+ diffRootNode(oldTree[0], newTree[0], patches);
1914
+ return;
1653
1915
  }
1916
+ diffChildren(oldTree, newTree, patches);
1654
1917
  };
1655
1918
 
1656
1919
  const removeTrailingNavigationPatches = patches => {
1657
- // Find the last non-navigation patch
1658
- let lastNonNavigationIndex = -1;
1659
- for (let i = patches.length - 1; i >= 0; i--) {
1660
- const patch = patches[i];
1920
+ while (patches.length > 0) {
1921
+ const patch = patches.at(-1);
1661
1922
  if (patch.type !== NavigateChild && patch.type !== NavigateParent && patch.type !== NavigateSibling) {
1662
- lastNonNavigationIndex = i;
1663
1923
  break;
1664
1924
  }
1925
+ patches.pop();
1665
1926
  }
1666
- // Return patches up to and including the last non-navigation patch
1667
- return lastNonNavigationIndex === -1 ? [] : patches.slice(0, lastNonNavigationIndex + 1);
1927
+ return patches;
1668
1928
  };
1669
1929
 
1670
1930
  const diffTree = (oldNodes, newNodes) => {
@@ -1716,15 +1976,15 @@ const HandleClickSelectTab = 'HandleClickSelectTab';
1716
1976
  const HandleClickTab = 'HandleClickTab';
1717
1977
 
1718
1978
  const emptyObject = {};
1719
- const RE_PLACEHOLDER = /\{(PH\d+)\}/g;
1720
1979
  const i18nString = (key, placeholders = emptyObject) => {
1721
1980
  if (placeholders === emptyObject) {
1722
1981
  return key;
1723
1982
  }
1724
- const replacer = (match, rest) => {
1725
- return placeholders[rest];
1726
- };
1727
- return key.replaceAll(RE_PLACEHOLDER, replacer);
1983
+ let result = key;
1984
+ for (const [placeholder, replacement] of Object.entries(placeholders)) {
1985
+ result = result.split(`{${placeholder}}`).join(String(replacement));
1986
+ }
1987
+ return result;
1728
1988
  };
1729
1989
 
1730
1990
  const Maximize = 'Maximize';
@@ -1779,12 +2039,12 @@ const getGlobalActionsDom = state => {
1779
2039
  }];
1780
2040
  };
1781
2041
 
2042
+ const selectedClass = mergeClassNames(PanelTab, PanelTabSelected);
1782
2043
  const getTabClassName = isSelected => {
1783
- let className = PanelTab;
1784
2044
  if (isSelected) {
1785
- className = mergeClassNames(className, PanelTabSelected);
2045
+ return selectedClass;
1786
2046
  }
1787
- return className;
2047
+ return PanelTab;
1788
2048
  };
1789
2049
 
1790
2050
  const badgeNode = {
@@ -1807,7 +2067,8 @@ const createPanelTab = (tab, badgeCount, isSelected) => {
1807
2067
  };
1808
2068
  const dom = [tabDom, text(label)];
1809
2069
  if (badgeCount) {
1810
- dom.push(badgeNode, text(' ' + badgeCount));
2070
+ const badgeCountText = ` ${badgeCount}`;
2071
+ dom.push(badgeNode, text(badgeCountText));
1811
2072
  }
1812
2073
  return dom;
1813
2074
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lvce-editor/panel-worker",
3
- "version": "2.2.0",
3
+ "version": "2.3.1",
4
4
  "description": "Panel Worker",
5
5
  "repository": {
6
6
  "type": "git",