@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.
- package/dist/mainAreaWorkerMain.js +123 -554
- package/package.json +1 -1
|
@@ -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
|
-
|
|
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
|
-
|
|
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(
|
|
1484
|
+
registerCommands(commandMap);
|
|
1916
1485
|
const rpc = await WebWorkerRpcClient.create({
|
|
1917
|
-
commandMap:
|
|
1486
|
+
commandMap: commandMap
|
|
1918
1487
|
});
|
|
1919
1488
|
set$1(rpc);
|
|
1920
1489
|
};
|