@lvce-editor/main-area-worker 1.2.0 → 1.3.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.
@@ -1031,6 +1031,7 @@ const createMockRpc = ({
1031
1031
  const Button = 1;
1032
1032
  const Div = 4;
1033
1033
  const Span = 8;
1034
+ const Text = 12;
1034
1035
  const Pre = 51;
1035
1036
 
1036
1037
  const TargetName = 'event.target.name';
@@ -1263,13 +1264,131 @@ const initialize = async () => {
1263
1264
  };
1264
1265
 
1265
1266
  const loadContent = async state => {
1267
+ const tabs = [{
1268
+ content: '',
1269
+ editorType: 'text',
1270
+ id: '1',
1271
+ isDirty: false,
1272
+ title: 'tab 1'
1273
+ }, {
1274
+ content: '',
1275
+ editorType: 'text',
1276
+ id: '2',
1277
+ isDirty: false,
1278
+ title: 'tab 2'
1279
+ }];
1280
+ return {
1281
+ ...state,
1282
+ layout: {
1283
+ activeGroupId: '0',
1284
+ direction: 'horizontal',
1285
+ groups: [{
1286
+ activeTabId: '',
1287
+ direction: 'horizontal',
1288
+ focused: false,
1289
+ id: '0',
1290
+ size: 300,
1291
+ tabs
1292
+ }]
1293
+ }
1294
+ };
1295
+ };
1296
+
1297
+ const text = data => {
1266
1298
  return {
1267
- ...state
1299
+ childCount: 0,
1300
+ text: data,
1301
+ type: Text
1268
1302
  };
1269
1303
  };
1270
1304
 
1305
+ const CSS_CLASSES = {
1306
+ CUSTOM_EDITOR: 'custom-editor',
1307
+ EDITOR_CONTAINER: 'editor-container',
1308
+ EDITOR_CONTENT: 'editor-content',
1309
+ EDITOR_GROUP: 'editor-group',
1310
+ EDITOR_GROUP_FOCUSED: 'focused',
1311
+ EDITOR_GROUPS_CONTAINER: 'editor-groups-container',
1312
+ MAIN_AREA: 'main-area',
1313
+ TAB: 'tab',
1314
+ TAB_ACTIVE: 'active',
1315
+ TAB_BAR: 'tab-bar',
1316
+ TAB_CLOSE: 'tab-close',
1317
+ TAB_TITLE: 'tab-title',
1318
+ TEXT_EDITOR: 'text-editor'
1319
+ };
1320
+
1321
+ const renderTab = (tab, isActive) => {
1322
+ return [{
1323
+ childCount: 2,
1324
+ className: `${CSS_CLASSES.TAB} ${isActive ? CSS_CLASSES.TAB_ACTIVE : ''}`,
1325
+ type: Div
1326
+ }, {
1327
+ childCount: 1,
1328
+ className: CSS_CLASSES.TAB_TITLE,
1329
+ type: Span
1330
+ }, text(tab.isDirty ? `*${tab.title}` : tab.title), {
1331
+ childCount: 1,
1332
+ className: CSS_CLASSES.TAB_CLOSE,
1333
+ type: Button
1334
+ }, text('×')];
1335
+ };
1336
+ const renderTabBar = group => {
1337
+ return [{
1338
+ childCount: group.tabs.length,
1339
+ className: CSS_CLASSES.TAB_BAR,
1340
+ type: Div
1341
+ }, ...group.tabs.flatMap(tab => renderTab(tab, tab.id === group.activeTabId))];
1342
+ };
1343
+ const renderEditor = tab => {
1344
+ if (tab.editorType === 'custom') {
1345
+ return [{
1346
+ childCount: 1,
1347
+ className: CSS_CLASSES.CUSTOM_EDITOR,
1348
+ type: Div
1349
+ }, text(`Custom Editor: ${tab.customEditorId}`)];
1350
+ }
1351
+ return [{
1352
+ childCount: 1,
1353
+ className: CSS_CLASSES.TEXT_EDITOR,
1354
+ type: Div
1355
+ }, {
1356
+ childCount: 1,
1357
+ className: CSS_CLASSES.EDITOR_CONTENT,
1358
+ type: Pre
1359
+ }, text(tab.content || '')];
1360
+ };
1361
+ const renderEditorGroup = group => {
1362
+ const activeTab = group.tabs.find(tab => tab.id === group.activeTabId);
1363
+ return [{
1364
+ childCount: 2,
1365
+ className: `${CSS_CLASSES.EDITOR_GROUP} ${group.focused ? CSS_CLASSES.EDITOR_GROUP_FOCUSED : ''}`,
1366
+ type: Div
1367
+ }, ...renderTabBar(group), {
1368
+ childCount: activeTab ? 1 : 1,
1369
+ className: CSS_CLASSES.EDITOR_CONTAINER,
1370
+ type: Div
1371
+ }, ...renderEditor(activeTab)];
1372
+ };
1373
+ const getMainAreaVirtualDom = layout => {
1374
+ return [{
1375
+ childCount: 1,
1376
+ className: CSS_CLASSES.MAIN_AREA,
1377
+ type: Div
1378
+ }, {
1379
+ childCount: layout.groups.length,
1380
+ className: CSS_CLASSES.EDITOR_GROUPS_CONTAINER,
1381
+ type: Div
1382
+ }, ...layout.groups.flatMap(renderEditorGroup)];
1383
+ };
1384
+
1271
1385
  const renderItems = (oldState, newState) => {
1272
- return [SetDom2, newState.uid, []];
1386
+ const {
1387
+ layout,
1388
+ uid
1389
+ } = newState;
1390
+ const dom = getMainAreaVirtualDom(layout);
1391
+ return [SetDom2, uid, dom];
1273
1392
  };
1274
1393
 
1275
1394
  const getRenderer = diffType => {
@@ -1361,560 +1480,10 @@ const main$2 = async () => {
1361
1480
  await listen();
1362
1481
  };
1363
1482
 
1364
- const closeEditorGroup = (state, groupId) => {
1365
- const groupIndex = state.layout.groups.findIndex(group => group.id === groupId);
1366
- if (groupIndex === -1 || state.layout.groups.length <= 1) {
1367
- return state;
1368
- }
1369
- const remainingGroups = state.layout.groups.filter(group => group.id !== groupId);
1370
- const redistributedGroups = remainingGroups.map((group, index) => ({
1371
- ...group,
1372
- size: Math.round(100 / remainingGroups.length)
1373
- }));
1374
- const newActiveGroupId = state.layout.activeGroupId === groupId ? remainingGroups[0].id : state.layout.activeGroupId;
1375
- return {
1376
- ...state,
1377
- layout: {
1378
- ...state.layout,
1379
- activeGroupId: newActiveGroupId,
1380
- groups: redistributedGroups
1381
- }
1382
- };
1383
- };
1384
-
1385
- const closeTab = (state, groupId, tabId) => {
1386
- const groups = state.layout.groups.map(group => {
1387
- if (group.id === groupId) {
1388
- const newTabs = group.tabs.filter(tab => tab.id !== tabId);
1389
- let newActiveTabId = group.activeTabId;
1390
- if (group.activeTabId === tabId) {
1391
- const tabIndex = group.tabs.findIndex(tab => tab.id === tabId);
1392
- if (newTabs.length > 0) {
1393
- newActiveTabId = newTabs[Math.min(tabIndex, newTabs.length - 1)].id;
1394
- } else {
1395
- newActiveTabId = undefined;
1396
- }
1397
- }
1398
- return {
1399
- ...group,
1400
- activeTabId: newActiveTabId,
1401
- tabs: newTabs
1402
- };
1403
- }
1404
- return group;
1405
- });
1406
- return {
1407
- ...state,
1408
- layout: {
1409
- ...state.layout,
1410
- groups
1411
- }
1412
- };
1413
- };
1414
-
1415
- const focusEditorGroup = (state, groupId) => {
1416
- const groups = state.layout.groups.map(group => ({
1417
- ...group,
1418
- focused: group.id === groupId
1419
- }));
1420
- return {
1421
- ...state,
1422
- layout: {
1423
- ...state.layout,
1424
- activeGroupId: groupId,
1425
- groups
1426
- }
1427
- };
1428
- };
1429
-
1430
- const CSS_CLASSES = {
1431
- CUSTOM_EDITOR: 'custom-editor',
1432
- EDITOR_CONTAINER: 'editor-container',
1433
- EDITOR_CONTENT: 'editor-content',
1434
- EDITOR_GROUP: 'editor-group',
1435
- EDITOR_GROUP_FOCUSED: 'focused',
1436
- EDITOR_GROUPS_CONTAINER: 'editor-groups-container',
1437
- EMPTY_EDITOR: 'empty-editor',
1438
- MAIN_AREA: 'main-area',
1439
- TAB: 'tab',
1440
- TAB_ACTIVE: 'active',
1441
- TAB_BAR: 'tab-bar',
1442
- TAB_CLOSE: 'tab-close',
1443
- TAB_TITLE: 'tab-title',
1444
- TEXT_EDITOR: 'text-editor'
1445
- };
1446
- const CSS_ATTRIBUTES = {
1447
- DATA_ACTION: 'data-action',
1448
- DATA_CUSTOM_EDITOR_ID: 'data-custom-editor-id',
1449
- DATA_DIRECTION: 'data-direction',
1450
- DATA_GROUP_ID: 'data-group-id',
1451
- DATA_LANGUAGE: 'data-language',
1452
- DATA_TAB_ID: 'data-tab-id'
1453
- };
1454
- const CSS_STYLES = {
1455
- CUSTOM_EDITOR_STYLE: 'flex: 1; overflow: auto;',
1456
- EDITOR_GROUP_BASE: 'display: flex; flex-direction: column; border-right: 1px solid var(--border-color);',
1457
- EDITOR_GROUP_FOCUSED_STYLE: 'box-shadow: 0 0 0 1px var(--focus-border-color);',
1458
- EMPTY_EDITOR_STYLE: 'flex: 1; display: flex; align-items: center; justify-content: center; color: var(--dimmed-color);',
1459
- FLEX_COLUMN: 'display: flex; flex-direction: column; height: 100%;',
1460
- FLEX_ROW: 'display: flex; flex-direction: row; height: 100%;',
1461
- TAB_ACTIVE_STYLE: 'background: var(--tab-active-background); color: var(--tab-active-color);',
1462
- TAB_BAR_BASE: 'display: flex; align-items: center; background: var(--tab-bar-background); border-bottom: 1px solid var(--border-color);',
1463
- TAB_BASE: 'padding: 4px 8px; cursor: pointer; border-right: 1px solid var(--border-color); display: flex; align-items: center; gap: 4px;',
1464
- TAB_CLOSE_STYLE: 'background: none; border: none; cursor: pointer; padding: 2px; border-radius: 2px; opacity: 0.7;',
1465
- TEXT_EDITOR_STYLE: 'flex: 1; overflow: auto; font-family: var(--editor-font-family); font-size: var(--editor-font-size);'
1466
- };
1467
- const THEMES = {
1468
- DARK: {
1469
- '--border-color': '#3e3e42',
1470
- '--dimmed-color': '#858585',
1471
- '--editor-font-family': 'Consolas, Monaco, "Courier New", monospace',
1472
- '--editor-font-size': '14px',
1473
- '--focus-border-color': '#0078d4',
1474
- '--tab-active-background': '#1e1e1e',
1475
- '--tab-active-color': '#ffffff',
1476
- '--tab-bar-background': '#252526',
1477
- '--tab-close-hover-background': '#3e3e42'
1478
- },
1479
- LIGHT: {
1480
- '--border-color': '#e1e1e1',
1481
- '--dimmed-color': '#999999',
1482
- '--editor-font-family': 'Consolas, Monaco, "Courier New", monospace',
1483
- '--editor-font-size': '14px',
1484
- '--focus-border-color': '#0078d4',
1485
- '--tab-active-background': '#ffffff',
1486
- '--tab-active-color': '#333333',
1487
- '--tab-bar-background': '#f3f3f3',
1488
- '--tab-close-hover-background': '#e1e1e1'
1489
- }
1490
- };
1491
- const getThemeStyles = (theme = 'DARK') => {
1492
- const themeVars = THEMES[theme];
1493
- return Object.entries(themeVars).map(([key, value]) => `${key}: ${value};`).join(' ');
1494
- };
1495
-
1496
- const renderTab = (tab, isActive) => {
1497
- return {
1498
- attributes: {
1499
- [CSS_ATTRIBUTES.DATA_TAB_ID]: tab.id,
1500
- style: `${CSS_STYLES.TAB_BASE} ${isActive ? CSS_STYLES.TAB_ACTIVE_STYLE : ''}`
1501
- },
1502
- childCount: 2,
1503
- children: [{
1504
- childCount: 1,
1505
- children: [tab.isDirty ? `*${tab.title}` : tab.title],
1506
- className: CSS_CLASSES.TAB_TITLE,
1507
- type: Span
1508
- }, {
1509
- attributes: {
1510
- [CSS_ATTRIBUTES.DATA_ACTION]: 'close-tab',
1511
- [CSS_ATTRIBUTES.DATA_TAB_ID]: tab.id,
1512
- style: CSS_STYLES.TAB_CLOSE_STYLE
1513
- },
1514
- childCount: 1,
1515
- children: ['×'],
1516
- className: CSS_CLASSES.TAB_CLOSE,
1517
- type: Button
1518
- }],
1519
- className: `${CSS_CLASSES.TAB} ${isActive ? CSS_CLASSES.TAB_ACTIVE : ''}`,
1520
- type: Div
1521
- };
1522
- };
1523
- const renderTabBar = group => {
1524
- return {
1525
- attributes: {
1526
- [CSS_ATTRIBUTES.DATA_GROUP_ID]: group.id,
1527
- style: CSS_STYLES.TAB_BAR_BASE
1528
- },
1529
- childCount: group.tabs.length,
1530
- children: group.tabs.map(tab => renderTab(tab, tab.id === group.activeTabId)),
1531
- className: CSS_CLASSES.TAB_BAR,
1532
- type: Div
1533
- };
1534
- };
1535
- const renderEditor = tab => {
1536
- if (tab.editorType === 'custom') {
1537
- return {
1538
- attributes: {
1539
- [CSS_ATTRIBUTES.DATA_CUSTOM_EDITOR_ID]: tab.customEditorId,
1540
- [CSS_ATTRIBUTES.DATA_TAB_ID]: tab.id,
1541
- style: CSS_STYLES.CUSTOM_EDITOR_STYLE
1542
- },
1543
- childCount: 1,
1544
- children: [`Custom Editor: ${tab.customEditorId}`],
1545
- className: CSS_CLASSES.CUSTOM_EDITOR,
1546
- type: Div
1547
- };
1548
- }
1549
- return {
1550
- attributes: {
1551
- [CSS_ATTRIBUTES.DATA_LANGUAGE]: tab.language || 'plaintext',
1552
- [CSS_ATTRIBUTES.DATA_TAB_ID]: tab.id,
1553
- style: CSS_STYLES.TEXT_EDITOR_STYLE
1554
- },
1555
- childCount: 1,
1556
- children: [{
1557
- childCount: 1,
1558
- children: [tab.content || ''],
1559
- className: CSS_CLASSES.EDITOR_CONTENT,
1560
- type: Pre
1561
- }],
1562
- className: CSS_CLASSES.TEXT_EDITOR,
1563
- type: Div
1564
- };
1565
- };
1566
- const renderEditorGroup = group => {
1567
- const activeTab = group.tabs.find(tab => tab.id === group.activeTabId);
1568
- return {
1569
- attributes: {
1570
- [CSS_ATTRIBUTES.DATA_GROUP_ID]: group.id,
1571
- style: `${CSS_STYLES.EDITOR_GROUP_BASE} flex: ${group.size}; ${group.focused ? CSS_STYLES.EDITOR_GROUP_FOCUSED_STYLE : ''}`
1572
- },
1573
- childCount: 2,
1574
- children: [renderTabBar(group), {
1575
- childCount: activeTab ? 1 : 1,
1576
- children: activeTab ? [renderEditor(activeTab)] : [{
1577
- attributes: {
1578
- style: CSS_STYLES.EMPTY_EDITOR_STYLE
1579
- },
1580
- childCount: 1,
1581
- children: ['No open tabs'],
1582
- className: CSS_CLASSES.EMPTY_EDITOR,
1583
- type: Div
1584
- }],
1585
- className: CSS_CLASSES.EDITOR_CONTAINER,
1586
- type: Div
1587
- }],
1588
- className: `${CSS_CLASSES.EDITOR_GROUP} ${group.focused ? CSS_CLASSES.EDITOR_GROUP_FOCUSED : ''}`,
1589
- type: Div
1590
- };
1591
- };
1592
- const getMainAreaVirtualDom = state => {
1593
- return [{
1594
- attributes: {
1595
- [CSS_ATTRIBUTES.DATA_DIRECTION]: state.layout.direction,
1596
- style: getThemeStyles('DARK')
1597
- },
1598
- childCount: 1,
1599
- children: [{
1600
- attributes: {
1601
- style: state.layout.direction === 'horizontal' ? CSS_STYLES.FLEX_ROW : CSS_STYLES.FLEX_COLUMN
1602
- },
1603
- childCount: state.layout.groups.length,
1604
- children: state.layout.groups.map(renderEditorGroup),
1605
- className: CSS_CLASSES.EDITOR_GROUPS_CONTAINER,
1606
- type: Div
1607
- }],
1608
- className: CSS_CLASSES.MAIN_AREA,
1609
- type: Div
1610
- }];
1611
- };
1612
-
1613
- const splitEditorGroup = (state, groupId, direction) => {
1614
- const sourceGroup = state.layout.groups.find(group => group.id === groupId);
1615
- if (!sourceGroup) {
1616
- return state;
1617
- }
1618
- const newGroupId = `group-${Date.now()}-${Math.random().toString(36).slice(2, 11)}`;
1619
- const isHorizontalSplit = direction === 'left' || direction === 'right';
1620
- const newLayoutDirection = isHorizontalSplit ? 'horizontal' : 'vertical';
1621
- const updatedGroups = state.layout.groups.map(group => {
1622
- if (group.id === groupId) {
1623
- return {
1624
- ...group,
1625
- focused: false,
1626
- size: 50
1627
- };
1628
- }
1629
- return group;
1630
- });
1631
- const newGroup = {
1632
- activeTabId: undefined,
1633
- focused: true,
1634
- id: newGroupId,
1635
- size: 50,
1636
- tabs: []
1637
- };
1638
- let reorderedGroups;
1639
- if (direction === 'right' || direction === 'down') {
1640
- reorderedGroups = [...updatedGroups, newGroup];
1641
- } else {
1642
- const sourceIndex = updatedGroups.findIndex(group => group.id === groupId);
1643
- reorderedGroups = [...updatedGroups.slice(0, sourceIndex), newGroup, ...updatedGroups.slice(sourceIndex)];
1644
- }
1645
- return {
1646
- ...state,
1647
- layout: {
1648
- activeGroupId: newGroupId,
1649
- direction: newLayoutDirection,
1650
- groups: reorderedGroups
1651
- }
1652
- };
1653
- };
1654
-
1655
- const switchTab = (state, groupId, tabId) => {
1656
- const groups = state.layout.groups.map(group => {
1657
- if (group.id === groupId) {
1658
- const tabExists = group.tabs.some(tab => tab.id === tabId);
1659
- if (tabExists) {
1660
- return {
1661
- ...group,
1662
- activeTabId: tabId
1663
- };
1664
- }
1665
- }
1666
- return group;
1667
- });
1668
- return {
1669
- ...state,
1670
- layout: {
1671
- ...state.layout,
1672
- groups
1673
- }
1674
- };
1675
- };
1676
-
1677
- const handleMainAreaClick = (state, event) => {
1678
- const {
1679
- target
1680
- } = event;
1681
- if (!target.dataset) {
1682
- return state;
1683
- }
1684
- const {
1685
- dataset
1686
- } = target;
1687
-
1688
- // Handle tab click
1689
- if (dataset.tabId) {
1690
- const {
1691
- groupId
1692
- } = dataset;
1693
- if (groupId) {
1694
- return switchTab(state, groupId, dataset.tabId);
1695
- }
1696
- }
1697
-
1698
- // Handle tab close button
1699
- if (dataset.action === 'close-tab' && dataset.tabId) {
1700
- const {
1701
- groupId
1702
- } = dataset;
1703
- if (groupId) {
1704
- return closeTab(state, groupId, dataset.tabId);
1705
- }
1706
- }
1707
-
1708
- // Handle editor group focus
1709
- if (dataset.groupId && !dataset.tabId) {
1710
- return focusEditorGroup(state, dataset.groupId);
1711
- }
1712
-
1713
- // Handle split actions
1714
- if (dataset.action?.startsWith('split-')) {
1715
- const {
1716
- groupId
1717
- } = dataset;
1718
- if (groupId) {
1719
- const direction = dataset.action.replace('split-', '');
1720
- return splitEditorGroup(state, groupId, direction);
1721
- }
1722
- }
1723
- return state;
1724
- };
1725
-
1726
- const handleMainAreaKeyboard = (state, event) => {
1727
- const {
1728
- ctrlKey = false,
1729
- key,
1730
- metaKey = false,
1731
- shiftKey = false
1732
- } = event;
1733
- const isCtrl = ctrlKey || metaKey;
1734
- const activeGroup = state.layout.groups.find(group => group.focused);
1735
- if (!activeGroup) {
1736
- return state;
1737
- }
1738
-
1739
- // Tab navigation
1740
- if (key === 'Tab' && isCtrl) {
1741
- const groupIndex = state.layout.groups.findIndex(group => group.id === activeGroup.id);
1742
- const nextGroupIndex = shiftKey ? (groupIndex - 1 + state.layout.groups.length) % state.layout.groups.length : (groupIndex + 1) % state.layout.groups.length;
1743
- const nextGroup = state.layout.groups[nextGroupIndex];
1744
- return focusEditorGroup(state, nextGroup.id);
1745
- }
1746
-
1747
- // Switch between tabs within group
1748
- if (key === 'ArrowLeft' && isCtrl && !shiftKey) {
1749
- const activeTabIndex = activeGroup.tabs.findIndex(tab => tab.id === activeGroup.activeTabId);
1750
- if (activeTabIndex > 0) {
1751
- const prevTab = activeGroup.tabs[activeTabIndex - 1];
1752
- return switchTab(state, activeGroup.id, prevTab.id);
1753
- }
1754
- }
1755
- if (key === 'ArrowRight' && isCtrl && !shiftKey) {
1756
- const activeTabIndex = activeGroup.tabs.findIndex(tab => tab.id === activeGroup.activeTabId);
1757
- if (activeTabIndex < activeGroup.tabs.length - 1) {
1758
- const nextTab = activeGroup.tabs[activeTabIndex + 1];
1759
- return switchTab(state, activeGroup.id, nextTab.id);
1760
- }
1761
- }
1762
-
1763
- // Close current tab
1764
- if (key === 'w' && isCtrl && activeGroup.activeTabId) {
1765
- return closeTab(state, activeGroup.id, activeGroup.activeTabId);
1766
- }
1767
-
1768
- // Split editor
1769
- if (key === '\\' && isCtrl) {
1770
- const direction = shiftKey ? 'down' : 'right';
1771
- return splitEditorGroup(state, activeGroup.id, direction);
1772
- }
1773
- return state;
1774
- };
1775
-
1776
- const moveTabToGroup = (state, sourceGroupId, targetGroupId, tabId, targetIndex) => {
1777
- const sourceGroup = state.layout.groups.find(group => group.id === sourceGroupId);
1778
- const targetGroup = state.layout.groups.find(group => group.id === targetGroupId);
1779
- if (!sourceGroup || !targetGroup || sourceGroupId === targetGroupId) {
1780
- return state;
1781
- }
1782
- const tabToMove = sourceGroup.tabs.find(tab => tab.id === tabId);
1783
- if (!tabToMove) {
1784
- return state;
1785
- }
1786
- const updatedGroups = state.layout.groups.map(group => {
1787
- if (group.id === sourceGroupId) {
1788
- const newTabs = group.tabs.filter(tab => tab.id !== tabId);
1789
- let newActiveTabId = group.activeTabId;
1790
- if (group.activeTabId === tabId) {
1791
- if (newTabs.length > 0) {
1792
- const removedIndex = group.tabs.findIndex(tab => tab.id === tabId);
1793
- newActiveTabId = newTabs[Math.min(removedIndex, newTabs.length - 1)].id;
1794
- } else {
1795
- newActiveTabId = undefined;
1796
- }
1797
- }
1798
- return {
1799
- ...group,
1800
- activeTabId: newActiveTabId,
1801
- tabs: newTabs
1802
- };
1803
- }
1804
- if (group.id === targetGroupId) {
1805
- const insertIndex = targetIndex === undefined ? group.tabs.length : targetIndex;
1806
- const newTabs = [...group.tabs];
1807
- newTabs.splice(insertIndex, 0, tabToMove);
1808
- return {
1809
- ...group,
1810
- activeTabId: tabId,
1811
- tabs: newTabs
1812
- };
1813
- }
1814
- return group;
1815
- });
1816
- return {
1817
- ...state,
1818
- layout: {
1819
- ...state.layout,
1820
- activeGroupId: targetGroupId,
1821
- groups: updatedGroups
1822
- }
1823
- };
1824
- };
1825
-
1826
- const startTabDrag = (state, tabId, groupId) => {
1827
- return {
1828
- dragState: {
1829
- draggedTabId: tabId,
1830
- sourceGroupId: groupId
1831
- },
1832
- state
1833
- };
1834
- };
1835
- const updateTabDrag = (state, dragState, targetGroupId, targetIndex) => {
1836
- return {
1837
- ...dragState,
1838
- targetGroupId,
1839
- targetIndex
1840
- };
1841
- };
1842
- const endTabDrag = (state, dragState) => {
1843
- if (dragState.targetGroupId && dragState.targetGroupId !== dragState.sourceGroupId) {
1844
- return moveTabToGroup(state, dragState.sourceGroupId, dragState.targetGroupId, dragState.draggedTabId, dragState.targetIndex);
1845
- }
1846
- return state;
1847
- };
1848
-
1849
- const openTab = (state, groupId, tab) => {
1850
- const newTab = {
1851
- ...tab,
1852
- id: `tab-${Date.now()}-${Math.random().toString(36).slice(2, 11)}`
1853
- };
1854
- const groups = state.layout.groups.map(group => {
1855
- if (group.id === groupId) {
1856
- return {
1857
- ...group,
1858
- activeTabId: newTab.id,
1859
- tabs: [...group.tabs, newTab]
1860
- };
1861
- }
1862
- return group;
1863
- });
1864
- return {
1865
- ...state,
1866
- layout: {
1867
- ...state.layout,
1868
- groups
1869
- }
1870
- };
1871
- };
1872
-
1873
- const restoreMainAreaState = (savedState, currentState) => {
1874
- try {
1875
- const parsed = JSON.parse(savedState);
1876
- return {
1877
- ...currentState,
1878
- layout: parsed.layout
1879
- };
1880
- } catch (error) {
1881
- console.error('Failed to restore main area state:', error);
1882
- return currentState;
1883
- }
1884
- };
1885
-
1886
- const saveMainAreaState = state => {
1887
- return JSON.stringify({
1888
- layout: state.layout,
1889
- version: '1.0.0'
1890
- });
1891
- };
1892
-
1893
- const mainAreaCommandMap = {
1894
- 'MainArea.closeEditorGroup': wrapCommand((state, groupId) => closeEditorGroup(state, groupId)),
1895
- 'MainArea.closeTab': wrapCommand((state, groupId, tabId) => closeTab(state, groupId, tabId)),
1896
- 'MainArea.create': () => {},
1897
- 'MainArea.endTabDrag': wrapCommand((state, dragState) => endTabDrag(state, dragState)),
1898
- 'MainArea.focusEditorGroup': wrapCommand((state, groupId) => focusEditorGroup(state, groupId)),
1899
- 'MainArea.getCommandIds': getCommandIds,
1900
- 'MainArea.getVirtualDom': state => getMainAreaVirtualDom(state),
1901
- 'MainArea.handleClick': wrapCommand((state, event) => handleMainAreaClick(state, event)),
1902
- 'MainArea.handleKeyboard': wrapCommand((state, event) => handleMainAreaKeyboard(state, event)),
1903
- 'MainArea.moveTabToGroup': wrapCommand((state, sourceGroupId, targetGroupId, tabId, targetIndex) => moveTabToGroup(state, sourceGroupId, targetGroupId, tabId, targetIndex)),
1904
- 'MainArea.openTab': wrapCommand((state, groupId, tab) => openTab(state, groupId, tab)),
1905
- 'MainArea.restoreState': wrapCommand((state, savedState) => restoreMainAreaState(savedState, state)),
1906
- 'MainArea.saveState': state => saveMainAreaState(state),
1907
- 'MainArea.splitEditorGroup': wrapCommand((state, groupId, direction) => splitEditorGroup(state, groupId, direction)),
1908
- 'MainArea.startTabDrag': (state, tabId, groupId) => startTabDrag(state, tabId, groupId),
1909
- 'MainArea.switchTab': wrapCommand((state, groupId, tabId) => switchTab(state, groupId, tabId)),
1910
- 'MainArea.terminate': terminate,
1911
- 'MainArea.updateTabDrag': (state, dragState, targetGroupId, targetIndex) => updateTabDrag(state, dragState, targetGroupId, targetIndex)
1912
- };
1913
-
1914
1483
  const main$1 = async () => {
1915
- registerCommands(mainAreaCommandMap);
1484
+ registerCommands(commandMap);
1916
1485
  const rpc = await WebWorkerRpcClient.create({
1917
- commandMap: mainAreaCommandMap
1486
+ commandMap: commandMap
1918
1487
  });
1919
1488
  set$1(rpc);
1920
1489
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lvce-editor/main-area-worker",
3
- "version": "1.2.0",
3
+ "version": "1.3.0",
4
4
  "description": "Main Area Worker",
5
5
  "repository": {
6
6
  "type": "git",