@lvce-editor/title-bar-worker 4.23.0 → 4.25.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.
@@ -745,7 +745,7 @@ const getErrorResponse = (id, error, preparePrettyError, logError) => {
745
745
  const errorProperty = getErrorProperty(error, prettyError);
746
746
  return create$1$1(id, errorProperty);
747
747
  };
748
- const create$9 = (message, result) => {
748
+ const create$a = (message, result) => {
749
749
  return {
750
750
  id: message.id,
751
751
  jsonrpc: Two$1,
@@ -754,7 +754,7 @@ const create$9 = (message, result) => {
754
754
  };
755
755
  const getSuccessResponse = (message, result) => {
756
756
  const resultProperty = result ?? null;
757
- return create$9(message, resultProperty);
757
+ return create$a(message, resultProperty);
758
758
  };
759
759
  const getErrorResponseSimple = (id, error) => {
760
760
  return {
@@ -848,7 +848,7 @@ const handleJsonRpcMessage = async (...args) => {
848
848
 
849
849
  const Two = '2.0';
850
850
 
851
- const create$8 = (method, params) => {
851
+ const create$9 = (method, params) => {
852
852
  return {
853
853
  jsonrpc: Two,
854
854
  method,
@@ -856,7 +856,7 @@ const create$8 = (method, params) => {
856
856
  };
857
857
  };
858
858
 
859
- const create$7 = (id, method, params) => {
859
+ const create$8 = (id, method, params) => {
860
860
  const message = {
861
861
  id,
862
862
  jsonrpc: Two,
@@ -867,12 +867,12 @@ const create$7 = (id, method, params) => {
867
867
  };
868
868
 
869
869
  let id = 0;
870
- const create$6 = () => {
870
+ const create$7 = () => {
871
871
  return ++id;
872
872
  };
873
873
 
874
874
  const registerPromise = map => {
875
- const id = create$6();
875
+ const id = create$7();
876
876
  const {
877
877
  promise,
878
878
  resolve
@@ -889,7 +889,7 @@ const invokeHelper = async (callbacks, ipc, method, params, useSendAndTransfer)
889
889
  id,
890
890
  promise
891
891
  } = registerPromise(callbacks);
892
- const message = create$7(id, method, params);
892
+ const message = create$8(id, method, params);
893
893
  if (useSendAndTransfer && ipc.sendAndTransfer) {
894
894
  ipc.sendAndTransfer(message);
895
895
  } else {
@@ -925,7 +925,7 @@ const createRpc = ipc => {
925
925
  * @deprecated
926
926
  */
927
927
  send(method, ...params) {
928
- const message = create$8(method, params);
928
+ const message = create$9(method, params);
929
929
  ipc.send(message);
930
930
  }
931
931
  };
@@ -965,7 +965,7 @@ const listen$1 = async (module, options) => {
965
965
  return ipc;
966
966
  };
967
967
 
968
- const create$5 = async ({
968
+ const create$6 = async ({
969
969
  commandMap,
970
970
  isMessagePortOpen = true,
971
971
  messagePort
@@ -983,7 +983,7 @@ const create$5 = async ({
983
983
  return rpc;
984
984
  };
985
985
 
986
- const create$4 = async ({
986
+ const create$5 = async ({
987
987
  commandMap,
988
988
  isMessagePortOpen,
989
989
  send
@@ -993,13 +993,55 @@ const create$4 = async ({
993
993
  port2
994
994
  } = new MessageChannel();
995
995
  await send(port1);
996
- return create$5({
996
+ return create$6({
997
997
  commandMap,
998
998
  isMessagePortOpen,
999
999
  messagePort: port2
1000
1000
  });
1001
1001
  };
1002
1002
 
1003
+ const createSharedLazyRpc = factory => {
1004
+ let rpcPromise;
1005
+ const getOrCreate = () => {
1006
+ if (!rpcPromise) {
1007
+ rpcPromise = factory();
1008
+ }
1009
+ return rpcPromise;
1010
+ };
1011
+ return {
1012
+ async dispose() {
1013
+ const rpc = await getOrCreate();
1014
+ await rpc.dispose();
1015
+ },
1016
+ async invoke(method, ...params) {
1017
+ const rpc = await getOrCreate();
1018
+ return rpc.invoke(method, ...params);
1019
+ },
1020
+ async invokeAndTransfer(method, ...params) {
1021
+ const rpc = await getOrCreate();
1022
+ return rpc.invokeAndTransfer(method, ...params);
1023
+ },
1024
+ async send(method, ...params) {
1025
+ const rpc = await getOrCreate();
1026
+ rpc.send(method, ...params);
1027
+ }
1028
+ };
1029
+ };
1030
+
1031
+ const create$4 = async ({
1032
+ commandMap,
1033
+ isMessagePortOpen,
1034
+ send
1035
+ }) => {
1036
+ return createSharedLazyRpc(() => {
1037
+ return create$5({
1038
+ commandMap,
1039
+ isMessagePortOpen,
1040
+ send
1041
+ });
1042
+ });
1043
+ };
1044
+
1003
1045
  const create$3 = async ({
1004
1046
  commandMap
1005
1047
  }) => {
@@ -1032,7 +1074,7 @@ const createMockRpc = ({
1032
1074
  };
1033
1075
 
1034
1076
  const rpcs = Object.create(null);
1035
- const set$4 = (id, rpc) => {
1077
+ const set$5 = (id, rpc) => {
1036
1078
  rpcs[id] = rpc;
1037
1079
  };
1038
1080
  const get$1 = id => {
@@ -1065,7 +1107,7 @@ const create$2 = rpcId => {
1065
1107
  const mockRpc = createMockRpc({
1066
1108
  commandMap
1067
1109
  });
1068
- set$4(rpcId, mockRpc);
1110
+ set$5(rpcId, mockRpc);
1069
1111
  // @ts-ignore
1070
1112
  mockRpc[Symbol.dispose] = () => {
1071
1113
  remove(rpcId);
@@ -1074,7 +1116,7 @@ const create$2 = rpcId => {
1074
1116
  return mockRpc;
1075
1117
  },
1076
1118
  set(rpc) {
1077
- set$4(rpcId, rpc);
1119
+ set$5(rpcId, rpc);
1078
1120
  }
1079
1121
  };
1080
1122
  };
@@ -1495,6 +1537,7 @@ const parseKey = rawKey => {
1495
1537
 
1496
1538
  const Electron$1 = 2;
1497
1539
 
1540
+ const MainProcess = -5;
1498
1541
  const RendererProcess = 1670;
1499
1542
  const RendererWorker = 1;
1500
1543
 
@@ -1504,6 +1547,11 @@ const SetFocusContext = 'Viewlet.setFocusContext';
1504
1547
 
1505
1548
  const FocusTitleBarMenuBar = 26;
1506
1549
 
1550
+ const {
1551
+ invoke: invoke$3,
1552
+ set: set$4
1553
+ } = create$2(MainProcess);
1554
+
1507
1555
  const {
1508
1556
  invoke: invoke$2,
1509
1557
  set: set$3
@@ -1580,9 +1628,6 @@ const sendMessagePortToTextMeasurementWorker = async port => {
1580
1628
  const command = 'TextMeasurement.handleMessagePort';
1581
1629
  await invokeAndTransfer('SendMessagePortToExtensionHostWorker.sendMessagePortToTextMeasurementWorker', port, command, 0);
1582
1630
  };
1583
- const getWindowId$1 = async () => {
1584
- return invoke$1('GetWindowId.getWindowId');
1585
- };
1586
1631
  const minimizeWindow = async () => {
1587
1632
  return invoke$1('ElectronWindow.minimize');
1588
1633
  };
@@ -3203,11 +3248,18 @@ const getEntryMap = async (state, menuIds, platform) => {
3203
3248
  return map;
3204
3249
  };
3205
3250
 
3206
- // TODO cache window id
3207
-
3208
- const getWindowId = async () => {
3209
- const windowId = await getWindowId$1();
3210
- return windowId;
3251
+ const send = async port => {
3252
+ await invokeAndTransfer('SendMessagePortToMainProcess.sendMessagePortToMainProcess', port, 'HandleElectronMessagePort.handleElectronMessagePort', 0);
3253
+ };
3254
+ const initializeMainProcess = async () => {
3255
+ if (get$1(MainProcess)) {
3256
+ return;
3257
+ }
3258
+ const rpc = await create$4({
3259
+ commandMap: {},
3260
+ send
3261
+ });
3262
+ set$4(rpc);
3211
3263
  };
3212
3264
 
3213
3265
  // based on https://www.electronjs.org/docs/latest/api/menu-item#new-menuitemoptions
@@ -3349,8 +3401,8 @@ const toElectronMenu = (map, rootId) => {
3349
3401
  };
3350
3402
 
3351
3403
  const setItems = async items => {
3352
- const windowId = await getWindowId();
3353
- return invoke$1('WebView.compatSharedProcessInvoke', 'ElectronApplicationMenu.setItems', windowId, items);
3404
+ await initializeMainProcess();
3405
+ return invoke$3('ElectronApplicationMenu.setItems', items);
3354
3406
  };
3355
3407
  const hydrate = async state => {
3356
3408
  const {
@@ -3376,6 +3428,33 @@ const getComponentState = uid => {
3376
3428
  return get(uid).newState;
3377
3429
  };
3378
3430
 
3431
+ const MaskIconCheck = 'MaskIconCheck';
3432
+ const MaskIcon = 'MaskIcon';
3433
+ const Menu = 'Menu';
3434
+ const MenuItem = 'MenuItem';
3435
+ const MenuItemCheckMark = 'MenuItemCheckMark';
3436
+ const MenuItemCheckmarkIcon = 'MenuItemCheckmarkIcon';
3437
+ const MenuItemDisabled = 'MenuItemDisabled';
3438
+ const MenuItemFocused = 'MenuItemFocused';
3439
+ const MenuItemKeyBinding = 'MenuItemKeyBinding';
3440
+ const MenuItemSeparator = 'MenuItemSeparator';
3441
+ const MenuItemSeparatorLine = 'MenuItemSeparatorLine';
3442
+ const MenuItemSubMenu = 'MenuItemSubMenu';
3443
+ const MenuItemSubMenuArrowRight = 'MenuItemSubMenuArrowRight';
3444
+ const TitleBar = 'TitleBar';
3445
+ const TitleBarButton = 'TitleBarButton';
3446
+ const TitleBarButtons = 'TitleBarButtons';
3447
+ const TitleBarCommandCenter = 'TitleBarCommandCenter';
3448
+ const TitleBarEntryActive = 'TitleBarEntryActive';
3449
+ const TitleBarIcon = 'TitleBarIcon';
3450
+ const TitleBarIconIcon = 'TitleBarIconIcon';
3451
+ const TitleBarMenuBar = 'TitleBarMenuBar';
3452
+ const TitleBarTopLevelEntry = 'TitleBarTopLevelEntry';
3453
+ const TitleBarTopLevelEntryLabel = 'TitleBarTopLevelEntryLabel';
3454
+ const Viewlet = 'Viewlet';
3455
+
3456
+ const Focusable = 0;
3457
+
3379
3458
  const mergeClassNames = (...classNames) => {
3380
3459
  return classNames.filter(Boolean).join(' ');
3381
3460
  };
@@ -3390,213 +3469,153 @@ const text = data => {
3390
3469
 
3391
3470
  new Set(Object.values(VirtualDomElements));
3392
3471
 
3393
- const getKeyBindings = () => {
3472
+ const getCommandCenterVirtualDom = commandCenterEnabled => {
3473
+ if (!commandCenterEnabled) {
3474
+ return [];
3475
+ }
3394
3476
  return [{
3395
- command: 'TitleBar.handleKeyArrowDown',
3396
- key: DownArrow$1,
3397
- when: FocusTitleBarMenuBar
3398
- }, {
3399
- command: 'TitleBar.handleKeyArrowUp',
3400
- key: UpArrow$1,
3401
- when: FocusTitleBarMenuBar
3402
- }, {
3403
- command: 'TitleBar.handleKeyArrowRight',
3404
- key: RightArrow$1,
3405
- when: FocusTitleBarMenuBar
3406
- }, {
3407
- command: 'TitleBar.handleKeyArrowLeft',
3408
- key: LeftArrow$1,
3409
- when: FocusTitleBarMenuBar
3410
- }, {
3411
- command: 'TitleBar.handleKeyEnter',
3412
- key: Enter$1,
3413
- when: FocusTitleBarMenuBar
3414
- }, {
3415
- command: 'TitleBar.handleKeySpace',
3416
- key: Space$1,
3417
- when: FocusTitleBarMenuBar
3418
- }, {
3419
- command: 'TitleBar.handleKeyHome',
3420
- key: Home$1,
3421
- when: FocusTitleBarMenuBar
3422
- }, {
3423
- command: 'TitleBar.handleKeyEnd',
3424
- key: End$1,
3425
- when: FocusTitleBarMenuBar
3426
- }, {
3427
- command: 'TitleBar.handleKeyEscape',
3428
- key: Escape$1,
3429
- when: FocusTitleBarMenuBar
3430
- }];
3431
- };
3432
-
3433
- const maximize = async () => {
3434
- await maximizeWindow();
3435
- };
3436
- const minimize = async () => {
3437
- await minimizeWindow();
3438
- };
3439
- const close = async () => {
3440
- await closeWindow();
3477
+ ariaLabel: commandCenter(),
3478
+ childCount: 1,
3479
+ className: TitleBarCommandCenter,
3480
+ onClick: HandleCommandCenterClick,
3481
+ onKeyDown: HandleCommandCenterKeyDown,
3482
+ role: Button$2,
3483
+ tabIndex: Focusable,
3484
+ type: Div
3485
+ }, text(search())];
3441
3486
  };
3442
3487
 
3443
- const handleClickClose = async state => {
3444
- await close();
3445
- return state;
3488
+ const getIcon = assetDir => {
3489
+ return `${assetDir}/icons/icon.svg`;
3446
3490
  };
3447
3491
 
3448
- const handleClickMinimize = async state => {
3449
- await minimize();
3450
- return state;
3492
+ const getIconVirtualDom = (icon, type = Div) => {
3493
+ return {
3494
+ childCount: 0,
3495
+ className: mergeClassNames(MaskIcon, `MaskIcon${icon}`),
3496
+ role: None$1,
3497
+ type
3498
+ };
3451
3499
  };
3452
3500
 
3453
- const handleClickToggleMaximize = async state => {
3454
- const fn = maximize;
3455
- await fn();
3456
- return state;
3501
+ const createTitleBarButton = button => {
3502
+ const {
3503
+ icon,
3504
+ id,
3505
+ label,
3506
+ onClick
3507
+ } = button;
3508
+ const dom = [{
3509
+ ariaLabel: label,
3510
+ childCount: 1,
3511
+ className: mergeClassNames(TitleBarButton, `TitleBarButton${id}`),
3512
+ name: id,
3513
+ onClick,
3514
+ type: Button$1
3515
+ }, getIconVirtualDom(icon, I)];
3516
+ return dom;
3457
3517
  };
3458
3518
 
3459
- const handleClick$1 = async (state, buttonName) => {
3460
- if (buttonName === 'Minimize') {
3461
- return handleClickMinimize(state);
3462
- }
3463
- if (buttonName === 'ToggleMaximize') {
3464
- return handleClickToggleMaximize(state);
3465
- }
3466
- if (buttonName === 'Close') {
3467
- return handleClickClose(state);
3519
+ const getTitleBarButtonsVirtualDom = (buttonsEnabled, buttons) => {
3520
+ if (!buttonsEnabled) {
3521
+ return [];
3468
3522
  }
3469
- return state;
3523
+ return [{
3524
+ childCount: buttons.length,
3525
+ className: mergeClassNames(Viewlet, TitleBarButtons),
3526
+ type: Div
3527
+ }, ...buttons.flatMap(createTitleBarButton)];
3470
3528
  };
3471
3529
 
3472
- const commandCenterItems = [{
3473
- command: 'QuickPick.showFile',
3474
- label: 'Go to File'
3475
- }, {
3476
- command: 'QuickPick.showCommands',
3477
- label: 'Show and Run Commands'
3478
- }, {
3479
- args: ['Search'],
3480
- command: 'Layout.openSideBarViewlet',
3481
- label: 'Search for Text'
3482
- }, {
3483
- args: ['symbol'],
3484
- command: 'QuickPick.show',
3485
- label: 'Go to Symbol in Editor'
3486
- }, {
3487
- args: ['Run And Debug'],
3488
- command: 'Layout.openSideBarViewlet',
3489
- label: 'Start Debugging'
3490
- }, {
3491
- command: 'QuickPick.showCommands',
3492
- label: 'Run Task'
3493
- }, {
3494
- command: 'QuickPick.showEverything',
3495
- label: 'More'
3496
- }];
3497
- const handleCommandCenterClick = async state => {
3498
- await invoke$1('QuickPick.show', 'custom', commandCenterItems, undefined, {
3499
- executeItemCommand: true,
3500
- mode: 'quickPick',
3501
- placeholder: 'Search files by name (append : to go to line or @ to go to symbol)',
3502
- waitUntil: 'visible'
3503
- });
3504
- return state;
3530
+ const parentNode$1 = {
3531
+ childCount: 1,
3532
+ className: mergeClassNames(Viewlet, TitleBarIcon),
3533
+ type: Div
3505
3534
  };
3506
-
3507
- const handleCommandCenterKeyDown = async (state, key) => {
3508
- if (key !== 'Enter' && key !== ' ' && key !== 'Space') {
3509
- return state;
3535
+ const getTitleBarIconVirtualDom = (titleBarIconEnabled, iconSrc) => {
3536
+ if (!titleBarIconEnabled) {
3537
+ return [];
3510
3538
  }
3511
- return handleCommandCenterClick(state);
3539
+ return [parentNode$1, {
3540
+ alt: '',
3541
+ childCount: 0,
3542
+ className: TitleBarIconIcon,
3543
+ src: iconSrc,
3544
+ type: Img
3545
+ }];
3512
3546
  };
3513
3547
 
3514
- const show2 = async (uid, menuId, x, y, args) => {
3515
- await showContextMenu2(uid, menuId, x, y, args);
3548
+ const activeEntryLabelNode = {
3549
+ childCount: 1,
3550
+ className: TitleBarTopLevelEntryLabel,
3551
+ type: Div
3516
3552
  };
3517
-
3518
- const handleContextMenu = async (state, button, eventX, eventY) => {
3519
- const {
3520
- uid
3521
- } = state;
3522
- await show2(uid, MenuIdTitleBarContextMenu, eventX, eventY, {
3523
- menuId: MenuIdTitleBarContextMenu
3524
- });
3525
- return state;
3553
+ const getActiveEntryLabelDom = isFocused => {
3554
+ if (!isFocused) {
3555
+ return [];
3556
+ }
3557
+ return [activeEntryLabelNode];
3526
3558
  };
3527
-
3528
- const handleElectronMenuClick = async (state, label) => {
3559
+ const getItemVirtualDom = item => {
3529
3560
  const {
3530
- commandMap
3531
- } = state;
3532
- const commandPair = commandMap[label];
3533
- if (!commandPair) {
3534
- throw new Error(`no command found for ${label}`);
3535
- }
3536
- const {
3537
- args = [],
3538
- command
3539
- } = commandPair;
3540
- await invoke$1(command, ...args);
3541
- return state;
3542
- };
3543
-
3544
- const state = {
3545
- connected: false
3546
- };
3547
- const isConnected = () => {
3548
- const {
3549
- connected
3550
- } = state;
3551
- return connected;
3552
- };
3553
- const invoke = (method, ...params) => {
3554
- return invoke$2(method, ...params);
3561
+ ariaLabel,
3562
+ isFocused,
3563
+ isOpen,
3564
+ keyboardShortCut,
3565
+ label
3566
+ } = item;
3567
+ const className = isFocused ? mergeClassNames(TitleBarTopLevelEntry, TitleBarEntryActive) : TitleBarTopLevelEntry;
3568
+ return [{
3569
+ ariaExpanded: isOpen,
3570
+ ariaHasPopup: true,
3571
+ ariaKeyShortcuts: keyboardShortCut,
3572
+ ariaLabel: ariaLabel || label,
3573
+ ariaOwns: isOpen ? 'Menu-0' : undefined,
3574
+ childCount: 1,
3575
+ className,
3576
+ id: isFocused ? 'TitleBarEntryActive' : undefined,
3577
+ name: label,
3578
+ // TODO have separate name attribute
3579
+ role: MenuItem$1,
3580
+ type: Button$1
3581
+ }, ...getActiveEntryLabelDom(isFocused), text(label)];
3555
3582
  };
3556
- const set = rpc => {
3557
- set$3(rpc);
3558
- state.connected = true;
3583
+ const getTitleBarMenuBarItemsVirtualDom = visibleItems => {
3584
+ const dom = visibleItems.flatMap(getItemVirtualDom);
3585
+ return dom;
3559
3586
  };
3560
3587
 
3561
- const commandQueues = new Map();
3562
- const handleMessagePort = async (port, viewletCommandMap, setAsRendererProcess = true) => {
3563
- const executeViewletCommand = async (uid, command, ...args) => {
3564
- const fn = viewletCommandMap[`TitleBar.${command}`];
3565
- if (typeof fn !== 'function') {
3566
- throw new TypeError(`Viewlet command not found: ${command}`);
3567
- }
3568
- const previous = commandQueues.get(uid);
3569
- const {
3570
- promise: next,
3571
- resolve
3572
- } = Promise.withResolvers();
3573
- commandQueues.set(uid, next);
3574
- if (previous) {
3575
- await previous;
3576
- }
3577
- try {
3578
- await fn(uid, ...args);
3579
- await invoke$1('Viewlet.requestRender', uid);
3580
- } finally {
3581
- resolve();
3582
- if (commandQueues.get(uid) === next) {
3583
- commandQueues.delete(uid);
3584
- }
3585
- }
3586
- };
3587
- const rpc = await create$5({
3588
- commandMap: {
3589
- 'Viewlet.executeViewletCommand': executeViewletCommand
3590
- },
3591
- messagePort: port
3592
- });
3593
- if (setAsRendererProcess) {
3594
- set(rpc);
3588
+ const activeId = 'TitleBarEntryActive';
3589
+ const getTitleBarMenuBarVirtualDom = (menuBarEnabled, visibleItems, focusedIndex) => {
3590
+ if (!menuBarEnabled) {
3591
+ return [];
3595
3592
  }
3593
+ return [{
3594
+ ariaActivedescendant: focusedIndex === -1 ? '' : activeId,
3595
+ childCount: visibleItems.length,
3596
+ className: mergeClassNames(Viewlet, TitleBarMenuBar),
3597
+ onContextMenu: HandleContextMenu,
3598
+ onFocusIn: HandleFocusIn,
3599
+ onFocusOut: HandleFocusOut,
3600
+ onMouseDown: HandleClick,
3601
+ onPointerOut: HandlePointerOut,
3602
+ onPointerOver: HandlePointerOver,
3603
+ role: MenuBar$1,
3604
+ tabIndex: 0,
3605
+ type: Div
3606
+ }, ...getTitleBarMenuBarItemsVirtualDom(visibleItems)];
3596
3607
  };
3597
3608
 
3598
- const getMenuOffset = (x, clientX, iconWidth) => {
3599
- return clientX - x - iconWidth;
3609
+ const parentNode = {
3610
+ childCount: 1,
3611
+ className: 'TitleBarTitle',
3612
+ type: Div
3613
+ };
3614
+ const getTitleVirtualDom = (titleBarTitleEnabled, title) => {
3615
+ if (!titleBarTitleEnabled) {
3616
+ return [];
3617
+ }
3618
+ return [parentNode, text(title)];
3600
3619
  };
3601
3620
 
3602
3621
  const Ellipsis = 'Ellipsis';
@@ -3651,11 +3670,269 @@ const getVisibleTitleBarEntries = (entries, width, focusedIndex, isMenuOpen) =>
3651
3670
  while (visible.length > 0 && getTotalWidth$1(visible) + MoreEntryWidth > width) {
3652
3671
  visible.pop();
3653
3672
  }
3654
- const hiddenEntries = entries.slice(visible.length);
3655
- const overflowIndex = visible.length;
3656
- visible.push(createOverflowEntry(hiddenEntries, overflowIndex, focusedIndex, isMenuOpen));
3673
+ const hiddenEntries = entries.slice(visible.length);
3674
+ const overflowIndex = visible.length;
3675
+ visible.push(createOverflowEntry(hiddenEntries, overflowIndex, focusedIndex, isMenuOpen));
3676
+ }
3677
+ return visible;
3678
+ };
3679
+
3680
+ const emptyTitleBarNode = {
3681
+ childCount: 0,
3682
+ type: Div
3683
+ };
3684
+ const getTitleBarVirtualDom = state => {
3685
+ const {
3686
+ assetDir,
3687
+ commandCenterEnabled,
3688
+ focusedIndex,
3689
+ isMenuOpen,
3690
+ platform,
3691
+ title,
3692
+ titleBarButtons,
3693
+ titleBarButtonsEnabled,
3694
+ titleBarEntries,
3695
+ titleBarIconEnabled,
3696
+ titleBarMenuBarEnabled,
3697
+ titleBarStyleCustom,
3698
+ titleBarTitleEnabled,
3699
+ width
3700
+ } = state;
3701
+ if (platform === Electron$1 && !titleBarStyleCustom) {
3702
+ return [emptyTitleBarNode];
3703
+ }
3704
+ const iconSrc = getIcon(assetDir);
3705
+ const visibleEntries = getVisibleTitleBarEntries(titleBarEntries, width, focusedIndex, isMenuOpen);
3706
+ const titleEnabled = titleBarTitleEnabled && !commandCenterEnabled;
3707
+ const childCount = Number(titleBarIconEnabled) + Number(titleBarMenuBarEnabled) + Number(commandCenterEnabled) + Number(titleEnabled) + Number(titleBarButtonsEnabled);
3708
+ return [{
3709
+ ariaLabel: titleBar(),
3710
+ childCount,
3711
+ className: mergeClassNames(Viewlet, TitleBar),
3712
+ id: 'TitleBar',
3713
+ onContextMenu: HandleTitleBarContextMenu,
3714
+ role: ContentInfo,
3715
+ type: Div
3716
+ }, ...getTitleBarIconVirtualDom(titleBarIconEnabled, iconSrc), ...getTitleBarMenuBarVirtualDom(titleBarMenuBarEnabled, visibleEntries, focusedIndex), ...getCommandCenterVirtualDom(commandCenterEnabled), ...getTitleVirtualDom(titleEnabled, title), ...getTitleBarButtonsVirtualDom(titleBarButtonsEnabled, titleBarButtons)];
3717
+ };
3718
+
3719
+ const renderTitleBar = (oldState, newState) => {
3720
+ const dom = getTitleBarVirtualDom(newState);
3721
+ return [SetDom2, newState.uid, dom];
3722
+ };
3723
+
3724
+ const getComponentDom = uid => {
3725
+ const state = getComponentState(uid);
3726
+ return renderTitleBar(state, state)[2];
3727
+ };
3728
+
3729
+ const getKeyBindings = () => {
3730
+ return [{
3731
+ command: 'TitleBar.handleKeyArrowDown',
3732
+ key: DownArrow$1,
3733
+ when: FocusTitleBarMenuBar
3734
+ }, {
3735
+ command: 'TitleBar.handleKeyArrowUp',
3736
+ key: UpArrow$1,
3737
+ when: FocusTitleBarMenuBar
3738
+ }, {
3739
+ command: 'TitleBar.handleKeyArrowRight',
3740
+ key: RightArrow$1,
3741
+ when: FocusTitleBarMenuBar
3742
+ }, {
3743
+ command: 'TitleBar.handleKeyArrowLeft',
3744
+ key: LeftArrow$1,
3745
+ when: FocusTitleBarMenuBar
3746
+ }, {
3747
+ command: 'TitleBar.handleKeyEnter',
3748
+ key: Enter$1,
3749
+ when: FocusTitleBarMenuBar
3750
+ }, {
3751
+ command: 'TitleBar.handleKeySpace',
3752
+ key: Space$1,
3753
+ when: FocusTitleBarMenuBar
3754
+ }, {
3755
+ command: 'TitleBar.handleKeyHome',
3756
+ key: Home$1,
3757
+ when: FocusTitleBarMenuBar
3758
+ }, {
3759
+ command: 'TitleBar.handleKeyEnd',
3760
+ key: End$1,
3761
+ when: FocusTitleBarMenuBar
3762
+ }, {
3763
+ command: 'TitleBar.handleKeyEscape',
3764
+ key: Escape$1,
3765
+ when: FocusTitleBarMenuBar
3766
+ }];
3767
+ };
3768
+
3769
+ const maximize = async () => {
3770
+ await maximizeWindow();
3771
+ };
3772
+ const minimize = async () => {
3773
+ await minimizeWindow();
3774
+ };
3775
+ const close = async () => {
3776
+ await closeWindow();
3777
+ };
3778
+
3779
+ const handleClickClose = async state => {
3780
+ await close();
3781
+ return state;
3782
+ };
3783
+
3784
+ const handleClickMinimize = async state => {
3785
+ await minimize();
3786
+ return state;
3787
+ };
3788
+
3789
+ const handleClickToggleMaximize = async state => {
3790
+ const fn = maximize;
3791
+ await fn();
3792
+ return state;
3793
+ };
3794
+
3795
+ const handleClick$1 = async (state, buttonName) => {
3796
+ if (buttonName === 'Minimize') {
3797
+ return handleClickMinimize(state);
3798
+ }
3799
+ if (buttonName === 'ToggleMaximize') {
3800
+ return handleClickToggleMaximize(state);
3801
+ }
3802
+ if (buttonName === 'Close') {
3803
+ return handleClickClose(state);
3804
+ }
3805
+ return state;
3806
+ };
3807
+
3808
+ const commandCenterItems = [{
3809
+ command: 'QuickPick.showFile',
3810
+ label: 'Go to File'
3811
+ }, {
3812
+ command: 'QuickPick.showCommands',
3813
+ label: 'Show and Run Commands'
3814
+ }, {
3815
+ args: ['Search'],
3816
+ command: 'Layout.openSideBarViewlet',
3817
+ label: 'Search for Text'
3818
+ }, {
3819
+ args: ['symbol'],
3820
+ command: 'QuickPick.show',
3821
+ label: 'Go to Symbol in Editor'
3822
+ }, {
3823
+ args: ['Run And Debug'],
3824
+ command: 'Layout.openSideBarViewlet',
3825
+ label: 'Start Debugging'
3826
+ }, {
3827
+ command: 'QuickPick.showCommands',
3828
+ label: 'Run Task'
3829
+ }, {
3830
+ command: 'QuickPick.showEverything',
3831
+ label: 'More'
3832
+ }];
3833
+ const handleCommandCenterClick = async state => {
3834
+ await invoke$1('QuickPick.show', 'custom', commandCenterItems, undefined, {
3835
+ executeItemCommand: true,
3836
+ mode: 'quickPick',
3837
+ placeholder: 'Search files by name (append : to go to line or @ to go to symbol)',
3838
+ waitUntil: 'visible'
3839
+ });
3840
+ return state;
3841
+ };
3842
+
3843
+ const handleCommandCenterKeyDown = async (state, key) => {
3844
+ if (key !== 'Enter' && key !== ' ' && key !== 'Space') {
3845
+ return state;
3846
+ }
3847
+ return handleCommandCenterClick(state);
3848
+ };
3849
+
3850
+ const show2 = async (uid, menuId, x, y, args) => {
3851
+ await showContextMenu2(uid, menuId, x, y, args);
3852
+ };
3853
+
3854
+ const handleContextMenu = async (state, button, eventX, eventY) => {
3855
+ const {
3856
+ uid
3857
+ } = state;
3858
+ await show2(uid, MenuIdTitleBarContextMenu, eventX, eventY, {
3859
+ menuId: MenuIdTitleBarContextMenu
3860
+ });
3861
+ return state;
3862
+ };
3863
+
3864
+ const handleElectronMenuClick = async (state, label) => {
3865
+ const {
3866
+ commandMap
3867
+ } = state;
3868
+ const commandPair = commandMap[label];
3869
+ if (!commandPair) {
3870
+ throw new Error(`no command found for ${label}`);
3871
+ }
3872
+ const {
3873
+ args = [],
3874
+ command
3875
+ } = commandPair;
3876
+ await invoke$1(command, ...args);
3877
+ return state;
3878
+ };
3879
+
3880
+ const state = {
3881
+ connected: false
3882
+ };
3883
+ const isConnected = () => {
3884
+ const {
3885
+ connected
3886
+ } = state;
3887
+ return connected;
3888
+ };
3889
+ const invoke = (method, ...params) => {
3890
+ return invoke$2(method, ...params);
3891
+ };
3892
+ const set = rpc => {
3893
+ set$3(rpc);
3894
+ state.connected = true;
3895
+ };
3896
+
3897
+ const commandQueues = new Map();
3898
+ const handleMessagePort = async (port, viewletCommandMap, setAsRendererProcess = true) => {
3899
+ const executeViewletCommand = async (uid, command, ...args) => {
3900
+ const fn = viewletCommandMap[`TitleBar.${command}`];
3901
+ if (typeof fn !== 'function') {
3902
+ throw new TypeError(`Viewlet command not found: ${command}`);
3903
+ }
3904
+ const previous = commandQueues.get(uid);
3905
+ const {
3906
+ promise: next,
3907
+ resolve
3908
+ } = Promise.withResolvers();
3909
+ commandQueues.set(uid, next);
3910
+ if (previous) {
3911
+ await previous;
3912
+ }
3913
+ try {
3914
+ await fn(uid, ...args);
3915
+ await invoke$1('Viewlet.requestRender', uid);
3916
+ } finally {
3917
+ resolve();
3918
+ if (commandQueues.get(uid) === next) {
3919
+ commandQueues.delete(uid);
3920
+ }
3921
+ }
3922
+ };
3923
+ const rpc = await create$6({
3924
+ commandMap: {
3925
+ 'Viewlet.executeViewletCommand': executeViewletCommand
3926
+ },
3927
+ messagePort: port
3928
+ });
3929
+ if (setAsRendererProcess) {
3930
+ set(rpc);
3657
3931
  }
3658
- return visible;
3932
+ };
3933
+
3934
+ const getMenuOffset = (x, clientX, iconWidth) => {
3935
+ return clientX - x - iconWidth;
3659
3936
  };
3660
3937
 
3661
3938
  const getNavigableTitleBarEntries = state => {
@@ -4017,7 +4294,7 @@ const getTitle = (workspaceUri, titleTemplate, appName) => {
4017
4294
  };
4018
4295
 
4019
4296
  const launchTextMeasurementWorker = async () => {
4020
- const rpc = await create$4({
4297
+ const rpc = await create$5({
4021
4298
  commandMap: {},
4022
4299
  async send(port) {
4023
4300
  await sendMessagePortToTextMeasurementWorker(port);
@@ -4061,7 +4338,9 @@ const handleWorkspaceChange = async (state, uri) => {
4061
4338
  labelFontSize,
4062
4339
  labelFontWeight,
4063
4340
  labelLetterSpacing,
4064
- titleTemplate
4341
+ titleTemplate,
4342
+ titleWidth: oldTitleWidth,
4343
+ width
4065
4344
  } = state;
4066
4345
  const title = getTitle(uri, titleTemplate, appName);
4067
4346
  const titleWidth = await measureTitleWidth(title, labelFontWeight, labelFontSize, labelFontFamily, labelLetterSpacing);
@@ -4069,6 +4348,8 @@ const handleWorkspaceChange = async (state, uri) => {
4069
4348
  ...state,
4070
4349
  title,
4071
4350
  titleWidth,
4351
+ // The title is centered, so half its width change becomes available to the menu.
4352
+ width: width + (oldTitleWidth - titleWidth) / 2,
4072
4353
  workspaceUri: uri
4073
4354
  };
4074
4355
  };
@@ -4188,31 +4469,6 @@ const renderFocusedIndex = (oldState, newState) => {
4188
4469
  return [FocusSelector, newState.uid, '.ViewletTitleBarMenuBar'];
4189
4470
  };
4190
4471
 
4191
- const MaskIconCheck = 'MaskIconCheck';
4192
- const MaskIcon = 'MaskIcon';
4193
- const Menu = 'Menu';
4194
- const MenuItem = 'MenuItem';
4195
- const MenuItemCheckMark = 'MenuItemCheckMark';
4196
- const MenuItemCheckmarkIcon = 'MenuItemCheckmarkIcon';
4197
- const MenuItemDisabled = 'MenuItemDisabled';
4198
- const MenuItemFocused = 'MenuItemFocused';
4199
- const MenuItemKeyBinding = 'MenuItemKeyBinding';
4200
- const MenuItemSeparator = 'MenuItemSeparator';
4201
- const MenuItemSeparatorLine = 'MenuItemSeparatorLine';
4202
- const MenuItemSubMenu = 'MenuItemSubMenu';
4203
- const MenuItemSubMenuArrowRight = 'MenuItemSubMenuArrowRight';
4204
- const TitleBar = 'TitleBar';
4205
- const TitleBarButton = 'TitleBarButton';
4206
- const TitleBarButtons = 'TitleBarButtons';
4207
- const TitleBarCommandCenter = 'TitleBarCommandCenter';
4208
- const TitleBarEntryActive = 'TitleBarEntryActive';
4209
- const TitleBarIcon = 'TitleBarIcon';
4210
- const TitleBarIconIcon = 'TitleBarIconIcon';
4211
- const TitleBarMenuBar = 'TitleBarMenuBar';
4212
- const TitleBarTopLevelEntry = 'TitleBarTopLevelEntry';
4213
- const TitleBarTopLevelEntryLabel = 'TitleBarTopLevelEntryLabel';
4214
- const Viewlet = 'Viewlet';
4215
-
4216
4472
  const getKeyBindingString = (key, altKey, ctrlKey, shiftKey, metaKey) => {
4217
4473
  let string = '';
4218
4474
  if (ctrlKey) {
@@ -4494,201 +4750,6 @@ const renderMenus = (oldState, newState) => {
4494
4750
  return ['Viewlet.send', uid, /* method */SetMenus, /* changes */changes, uid];
4495
4751
  };
4496
4752
 
4497
- const Focusable = 0;
4498
-
4499
- const getCommandCenterVirtualDom = commandCenterEnabled => {
4500
- if (!commandCenterEnabled) {
4501
- return [];
4502
- }
4503
- return [{
4504
- ariaLabel: commandCenter(),
4505
- childCount: 1,
4506
- className: TitleBarCommandCenter,
4507
- onClick: HandleCommandCenterClick,
4508
- onKeyDown: HandleCommandCenterKeyDown,
4509
- role: Button$2,
4510
- tabIndex: Focusable,
4511
- type: Div
4512
- }, text(search())];
4513
- };
4514
-
4515
- const getIcon = assetDir => {
4516
- return `${assetDir}/icons/icon.svg`;
4517
- };
4518
-
4519
- const getIconVirtualDom = (icon, type = Div) => {
4520
- return {
4521
- childCount: 0,
4522
- className: mergeClassNames(MaskIcon, `MaskIcon${icon}`),
4523
- role: None$1,
4524
- type
4525
- };
4526
- };
4527
-
4528
- const createTitleBarButton = button => {
4529
- const {
4530
- icon,
4531
- id,
4532
- label,
4533
- onClick
4534
- } = button;
4535
- const dom = [{
4536
- ariaLabel: label,
4537
- childCount: 1,
4538
- className: mergeClassNames(TitleBarButton, `TitleBarButton${id}`),
4539
- name: id,
4540
- onClick,
4541
- type: Button$1
4542
- }, getIconVirtualDom(icon, I)];
4543
- return dom;
4544
- };
4545
-
4546
- const getTitleBarButtonsVirtualDom = (buttonsEnabled, buttons) => {
4547
- if (!buttonsEnabled) {
4548
- return [];
4549
- }
4550
- return [{
4551
- childCount: buttons.length,
4552
- className: mergeClassNames(Viewlet, TitleBarButtons),
4553
- type: Div
4554
- }, ...buttons.flatMap(createTitleBarButton)];
4555
- };
4556
-
4557
- const parentNode$1 = {
4558
- childCount: 1,
4559
- className: mergeClassNames(Viewlet, TitleBarIcon),
4560
- type: Div
4561
- };
4562
- const getTitleBarIconVirtualDom = (titleBarIconEnabled, iconSrc) => {
4563
- if (!titleBarIconEnabled) {
4564
- return [];
4565
- }
4566
- return [parentNode$1, {
4567
- alt: '',
4568
- childCount: 0,
4569
- className: TitleBarIconIcon,
4570
- src: iconSrc,
4571
- type: Img
4572
- }];
4573
- };
4574
-
4575
- const activeEntryLabelNode = {
4576
- childCount: 1,
4577
- className: TitleBarTopLevelEntryLabel,
4578
- type: Div
4579
- };
4580
- const getActiveEntryLabelDom = isFocused => {
4581
- if (!isFocused) {
4582
- return [];
4583
- }
4584
- return [activeEntryLabelNode];
4585
- };
4586
- const getItemVirtualDom = item => {
4587
- const {
4588
- ariaLabel,
4589
- isFocused,
4590
- isOpen,
4591
- keyboardShortCut,
4592
- label
4593
- } = item;
4594
- const className = isFocused ? mergeClassNames(TitleBarTopLevelEntry, TitleBarEntryActive) : TitleBarTopLevelEntry;
4595
- return [{
4596
- ariaExpanded: isOpen,
4597
- ariaHasPopup: true,
4598
- ariaKeyShortcuts: keyboardShortCut,
4599
- ariaLabel: ariaLabel || label,
4600
- ariaOwns: isOpen ? 'Menu-0' : undefined,
4601
- childCount: 1,
4602
- className,
4603
- id: isFocused ? 'TitleBarEntryActive' : undefined,
4604
- name: label,
4605
- // TODO have separate name attribute
4606
- role: MenuItem$1,
4607
- type: Button$1
4608
- }, ...getActiveEntryLabelDom(isFocused), text(label)];
4609
- };
4610
- const getTitleBarMenuBarItemsVirtualDom = visibleItems => {
4611
- const dom = visibleItems.flatMap(getItemVirtualDom);
4612
- return dom;
4613
- };
4614
-
4615
- const activeId = 'TitleBarEntryActive';
4616
- const getTitleBarMenuBarVirtualDom = (menuBarEnabled, visibleItems, focusedIndex) => {
4617
- if (!menuBarEnabled) {
4618
- return [];
4619
- }
4620
- return [{
4621
- ariaActivedescendant: focusedIndex === -1 ? '' : activeId,
4622
- childCount: visibleItems.length,
4623
- className: mergeClassNames(Viewlet, TitleBarMenuBar),
4624
- onContextMenu: HandleContextMenu,
4625
- onFocusIn: HandleFocusIn,
4626
- onFocusOut: HandleFocusOut,
4627
- onMouseDown: HandleClick,
4628
- onPointerOut: HandlePointerOut,
4629
- onPointerOver: HandlePointerOver,
4630
- role: MenuBar$1,
4631
- tabIndex: 0,
4632
- type: Div
4633
- }, ...getTitleBarMenuBarItemsVirtualDom(visibleItems)];
4634
- };
4635
-
4636
- const parentNode = {
4637
- childCount: 1,
4638
- className: 'TitleBarTitle',
4639
- type: Div
4640
- };
4641
- const getTitleVirtualDom = (titleBarTitleEnabled, title) => {
4642
- if (!titleBarTitleEnabled) {
4643
- return [];
4644
- }
4645
- return [parentNode, text(title)];
4646
- };
4647
-
4648
- const emptyTitleBarNode = {
4649
- childCount: 0,
4650
- type: Div
4651
- };
4652
- const getTitleBarVirtualDom = state => {
4653
- const {
4654
- assetDir,
4655
- commandCenterEnabled,
4656
- focusedIndex,
4657
- isMenuOpen,
4658
- platform,
4659
- title,
4660
- titleBarButtons,
4661
- titleBarButtonsEnabled,
4662
- titleBarEntries,
4663
- titleBarIconEnabled,
4664
- titleBarMenuBarEnabled,
4665
- titleBarStyleCustom,
4666
- titleBarTitleEnabled,
4667
- width
4668
- } = state;
4669
- if (platform === Electron$1 && !titleBarStyleCustom) {
4670
- return [emptyTitleBarNode];
4671
- }
4672
- const iconSrc = getIcon(assetDir);
4673
- const visibleEntries = getVisibleTitleBarEntries(titleBarEntries, width, focusedIndex, isMenuOpen);
4674
- const titleEnabled = titleBarTitleEnabled && !commandCenterEnabled;
4675
- const childCount = Number(titleBarIconEnabled) + Number(titleBarMenuBarEnabled) + Number(commandCenterEnabled) + Number(titleEnabled) + Number(titleBarButtonsEnabled);
4676
- return [{
4677
- ariaLabel: titleBar(),
4678
- childCount,
4679
- className: mergeClassNames(Viewlet, TitleBar),
4680
- id: 'TitleBar',
4681
- onContextMenu: HandleTitleBarContextMenu,
4682
- role: ContentInfo,
4683
- type: Div
4684
- }, ...getTitleBarIconVirtualDom(titleBarIconEnabled, iconSrc), ...getTitleBarMenuBarVirtualDom(titleBarMenuBarEnabled, visibleEntries, focusedIndex), ...getCommandCenterVirtualDom(commandCenterEnabled), ...getTitleVirtualDom(titleEnabled, title), ...getTitleBarButtonsVirtualDom(titleBarButtonsEnabled, titleBarButtons)];
4685
- };
4686
-
4687
- const renderTitleBar = (oldState, newState) => {
4688
- const dom = getTitleBarVirtualDom(newState);
4689
- return [SetDom2, newState.uid, dom];
4690
- };
4691
-
4692
4753
  const getRenderer3 = diffType => {
4693
4754
  switch (diffType) {
4694
4755
  case RenderEntries:
@@ -4837,6 +4898,8 @@ const setTitleTemplate = async (state, titleTemplate) => {
4837
4898
  labelFontSize,
4838
4899
  labelFontWeight,
4839
4900
  labelLetterSpacing,
4901
+ titleWidth: oldTitleWidth,
4902
+ width,
4840
4903
  workspaceUri
4841
4904
  } = state;
4842
4905
  const title = getTitle(workspaceUri, titleTemplate, appName);
@@ -4845,7 +4908,9 @@ const setTitleTemplate = async (state, titleTemplate) => {
4845
4908
  ...state,
4846
4909
  title,
4847
4910
  titleTemplate,
4848
- titleWidth
4911
+ titleWidth,
4912
+ // The title is centered, so half its width change becomes available to the menu.
4913
+ width: width + (oldTitleWidth - titleWidth) / 2
4849
4914
  };
4850
4915
  };
4851
4916
 
@@ -5543,6 +5608,7 @@ const commandMap = {
5543
5608
  'TitleBar.focusPrevious': wrapCommand(focusPrevious),
5544
5609
  'TitleBar.getCommandIds': getCommandIds,
5545
5610
  'TitleBar.getCommands': getCommandIds,
5611
+ 'TitleBar.getComponentDom': getComponentDom,
5546
5612
  'TitleBar.getComponentState': getComponentState,
5547
5613
  'TitleBar.getKeyBindings': getKeyBindings,
5548
5614
  'TitleBar.getMenuEntries2': wrapGetter(getMenuEntries2),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lvce-editor/title-bar-worker",
3
- "version": "4.23.0",
3
+ "version": "4.25.0",
4
4
  "description": "Title Bar Worker",
5
5
  "repository": {
6
6
  "type": "git",