@lvce-editor/title-bar-worker 1.1.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.
@@ -94,6 +94,12 @@ const number = value => {
94
94
  throw new AssertionError('expected value to be of type number');
95
95
  }
96
96
  };
97
+ const array = value => {
98
+ const type = getType(value);
99
+ if (type !== 'array') {
100
+ throw new AssertionError('expected value to be of type array');
101
+ }
102
+ };
97
103
  const string = value => {
98
104
  const type = getType(value);
99
105
  if (type !== 'string') {
@@ -442,10 +448,10 @@ const create$4 = (method, params) => {
442
448
  };
443
449
  };
444
450
  const callbacks = Object.create(null);
445
- const set = (id, fn) => {
451
+ const set$1 = (id, fn) => {
446
452
  callbacks[id] = fn;
447
453
  };
448
- const get = id => {
454
+ const get$1 = id => {
449
455
  return callbacks[id];
450
456
  };
451
457
  const remove = id => {
@@ -461,13 +467,13 @@ const registerPromise = () => {
461
467
  resolve,
462
468
  promise
463
469
  } = Promise.withResolvers();
464
- set(id, resolve);
470
+ set$1(id, resolve);
465
471
  return {
466
472
  id,
467
473
  promise
468
474
  };
469
475
  };
470
- const create$2 = (method, params) => {
476
+ const create$2$1 = (method, params) => {
471
477
  const {
472
478
  id,
473
479
  promise
@@ -618,7 +624,7 @@ const warn = (...args) => {
618
624
  console.warn(...args);
619
625
  };
620
626
  const resolve = (id, response) => {
621
- const fn = get(id);
627
+ const fn = get$1(id);
622
628
  if (!fn) {
623
629
  console.log(response);
624
630
  warn(`callback ${id} may already be disposed`);
@@ -759,7 +765,7 @@ const invokeHelper = async (ipc, method, params, useSendAndTransfer) => {
759
765
  const {
760
766
  message,
761
767
  promise
762
- } = create$2(method, params);
768
+ } = create$2$1(method, params);
763
769
  if (useSendAndTransfer && ipc.sendAndTransfer) {
764
770
  ipc.sendAndTransfer(message);
765
771
  } else {
@@ -843,7 +849,7 @@ const listen$1 = async (module, options) => {
843
849
  const ipc = module.wrap(rawIpc);
844
850
  return ipc;
845
851
  };
846
- const create$1 = async ({
852
+ const create$2 = async ({
847
853
  commandMap
848
854
  }) => {
849
855
  // TODO create a commandMap per rpc instance
@@ -855,121 +861,331 @@ const create$1 = async ({
855
861
  };
856
862
  const WebWorkerRpcClient = {
857
863
  __proto__: null,
858
- create: create$1
859
- };
860
-
861
- const Enter = 3;
862
- const Escape = 8;
863
- const Space = 9;
864
- const End = 255;
865
- const Home = 12;
866
- const LeftArrow = 13;
867
- const UpArrow = 14;
868
- const RightArrow = 15;
869
- const DownArrow = 16;
870
- const Delete = 18;
871
- const KeyC = 31;
872
- const KeyV = 50;
873
- const F2 = 58;
874
- const Star = 131;
875
-
876
- const CtrlCmd = 1 << 11 >>> 0;
877
- const Alt = 1 << 9 >>> 0;
878
-
879
- const FocusExplorer = 13;
880
- const FocusExplorerEditBox = 14;
881
- const FocusTitleBarMenuBar = 26;
882
-
883
- const getKeyBindings = () => {
884
- return [{
885
- key: RightArrow,
886
- command: 'Explorer.handleArrowRight',
887
- when: FocusExplorer
888
- }, {
889
- key: LeftArrow,
890
- command: 'Explorer.handleArrowLeft',
891
- when: FocusExplorer
892
- }, {
893
- key: Home,
894
- command: 'Explorer.focusFirst',
895
- when: FocusExplorer
896
- }, {
897
- key: End,
898
- command: 'Explorer.focusLast',
899
- when: FocusExplorer
900
- }, {
901
- key: UpArrow,
902
- command: 'Explorer.focusPrevious',
903
- when: FocusExplorer
904
- }, {
905
- key: DownArrow,
906
- command: 'Explorer.focusNext',
907
- when: FocusExplorer
908
- }, {
909
- key: CtrlCmd | Star,
910
- command: 'Explorer.expandAll',
911
- when: FocusExplorer
912
- }, {
913
- key: Alt | RightArrow,
914
- command: 'Explorer.expandRecursively',
915
- when: FocusExplorer
916
- }, {
917
- key: CtrlCmd | LeftArrow,
918
- command: 'Explorer.collapseAll',
919
- when: FocusExplorer
920
- }, {
921
- key: CtrlCmd | KeyV,
922
- command: 'Explorer.handlePaste',
923
- when: FocusExplorer
924
- }, {
925
- key: CtrlCmd | KeyC,
926
- command: 'Explorer.handleCopy',
927
- when: FocusExplorer
928
- }, {
929
- key: F2,
930
- command: 'Explorer.rename',
931
- when: FocusExplorer
932
- }, {
933
- key: Escape,
934
- command: 'Explorer.cancelEdit',
935
- when: FocusExplorerEditBox
936
- }, {
937
- key: Enter,
938
- command: 'Explorer.acceptEdit',
939
- when: FocusExplorerEditBox
940
- }, {
941
- key: Delete,
942
- command: 'Explorer.removeDirent',
943
- when: FocusExplorer
944
- }, {
945
- key: Escape,
946
- command: 'Explorer.focusNone',
947
- when: FocusExplorer
948
- }, {
949
- key: Space,
950
- command: 'Explorer.handleClickCurrentButKeepFocus',
951
- when: FocusExplorer
952
- }, {
953
- key: Enter,
954
- command: 'Explorer.handleClickCurrent',
955
- when: FocusExplorer
956
- }];
864
+ create: create$2
957
865
  };
958
866
 
867
+ const Menu$1 = 'menu';
959
868
  const MenuBar = 'menubar';
960
- const MenuItem = 'menuitem';
961
-
962
- const HandleClick = 'handleClick';
963
- const HandleFocusIn = 'handleFocusIn';
964
- const HandleFocusOut = 'handleFocusOut';
965
- const HandlePointerOut = 'handlePointerOut';
966
- const HandlePointerOver = 'handlePointerOver';
967
-
869
+ const MenuItem$1 = 'menuitem';
870
+ const MenuItemCheckBox = 'menuitemcheckbox';
871
+ const Separator$1 = 'separator';
872
+
873
+ const Menu = 'Menu';
874
+ const MenuItem = 'MenuItem';
875
+ const MenuItemFocused = 'MenuItemFocused';
876
+ const MenuItemSeparator = 'MenuItemSeparator';
877
+ const MenuItemSeparatorLine = 'MenuItemSeparatorLine';
878
+ const MenuItemSubMenu = 'MenuItemSubMenu';
879
+ const MenuItemSubMenuArrowRight = 'MenuItemSubMenuArrowRight';
968
880
  const TitleBarEntryActive = 'TitleBarEntryActive';
969
881
  const TitleBarTopLevelEntry = 'TitleBarTopLevelEntry';
970
882
  const TitleBarTopLevelEntryLabel = 'TitleBarTopLevelEntryLabel';
971
883
 
884
+ const getKeyBindingString = (key, altKey, ctrlKey, shiftKey, metaKey) => {
885
+ let string = '';
886
+ if (ctrlKey) {
887
+ string += 'Ctrl+';
888
+ }
889
+ if (shiftKey) {
890
+ string += 'Shift+';
891
+ }
892
+ string += key.toUpperCase();
893
+ return string;
894
+ };
895
+
896
+ const Separator = 1;
897
+ const None = 0;
898
+ const SubMenu = 4;
899
+ const Checked = 2;
900
+ const Unchecked = 3;
901
+ const Disabled = 5;
902
+ const RestoreFocus = 6;
903
+ const Ignore = 7;
904
+
905
+ const Backspace$1 = 1;
906
+ const Tab$1 = 2;
907
+ const Enter$1 = 3;
908
+ const Escape$1 = 8;
909
+ const Space$1 = 9;
910
+ const PageUp$1 = 10;
911
+ const PageDown$1 = 11;
912
+ const End$1 = 255;
913
+ const Home$1 = 12;
914
+ const LeftArrow$1 = 13;
915
+ const UpArrow$1 = 14;
916
+ const RightArrow$1 = 15;
917
+ const DownArrow$1 = 16;
918
+ const Insert$1 = 17;
919
+ const Delete$1 = 18;
920
+ const Digit0$1 = 19;
921
+ const Digit1$1 = 20;
922
+ const Digit2$1 = 21;
923
+ const Digit3$1 = 22;
924
+ const Digit4$1 = 23;
925
+ const Digit5$1 = 24;
926
+ const Digit6$1 = 25;
927
+ const Digit7$1 = 26;
928
+ const Digit8$1 = 27;
929
+ const Digit9$1 = 28;
930
+ const KeyA$1 = 29;
931
+ const KeyB$1 = 30;
932
+ const KeyC$1 = 31;
933
+ const KeyD$1 = 32;
934
+ const KeyE$1 = 33;
935
+ const KeyF$1 = 34;
936
+ const KeyG$1 = 35;
937
+ const KeyH$1 = 36;
938
+ const KeyI$1 = 37;
939
+ const KeyJ$1 = 38;
940
+ const KeyK$1 = 39;
941
+ const KeyL$1 = 40;
942
+ const KeyM$1 = 41;
943
+ const KeyN$1 = 42;
944
+ const KeyO$1 = 43;
945
+ const KeyP$1 = 44;
946
+ const KeyQ$1 = 45;
947
+ const KeyR$1 = 46;
948
+ const KeyS$1 = 47;
949
+ const KeyT$1 = 48;
950
+ const KeyU$1 = 49;
951
+ const KeyV$1 = 50;
952
+ const KeyW$1 = 51;
953
+ const KeyX$1 = 52;
954
+ const KeyY$1 = 53;
955
+ const KeyZ$1 = 54;
956
+ const F1$1 = 57;
957
+ const F2$1 = 58;
958
+ const F3$1 = 59;
959
+ const F4$1 = 60;
960
+ const F5$1 = 61;
961
+ const F6$1 = 62;
962
+ const Equal$1 = 84;
963
+ const Comma$1 = 85;
964
+ const Minus$1 = 86;
965
+ const Backquote$1 = 89;
966
+ const Backslash$1 = 91;
967
+ const Star$1 = 131;
968
+ const Plus$1 = 132;
969
+
970
+ const Unknown = 'Unknown';
971
+ const Backspace = 'Backspace';
972
+ const Tab = 'Tab';
973
+ const Enter = 'Enter';
974
+ const Escape = 'Escape';
975
+ const Space = 'Space';
976
+ const PageUp = 'PageUp';
977
+ const PageDown = 'PageDown';
978
+ const End = 'End';
979
+ const Home = 'Home';
980
+ const LeftArrow = 'LeftArrow';
981
+ const UpArrow = 'UpArrow';
982
+ const RightArrow = 'RightArrow';
983
+ const DownArrow = 'DownArrow';
984
+ const Insert = 'Insert';
985
+ const Delete = 'Delete';
986
+ const Digit0 = '0';
987
+ const Digit1 = '1';
988
+ const Digit2 = '2';
989
+ const Digit3 = '3';
990
+ const Digit4 = '4';
991
+ const Digit5 = '5';
992
+ const Digit6 = '6';
993
+ const Digit7 = '7';
994
+ const Digit8 = '8';
995
+ const Digit9 = '9';
996
+ const KeyA = 'a';
997
+ const KeyB = 'b';
998
+ const KeyC = 'c';
999
+ const KeyD = 'd';
1000
+ const KeyE = 'e';
1001
+ const KeyF = 'f';
1002
+ const KeyG = 'g';
1003
+ const KeyH = 'h';
1004
+ const KeyI = 'i';
1005
+ const KeyJ = 'j';
1006
+ const KeyK = 'k';
1007
+ const KeyL = 'l';
1008
+ const KeyM = 'm';
1009
+ const KeyN = 'n';
1010
+ const KeyO = 'o';
1011
+ const KeyP = 'p';
1012
+ const KeyQ = 'q';
1013
+ const KeyR = 'r';
1014
+ const KeyS = 's';
1015
+ const KeyT = 't';
1016
+ const KeyU = 'u';
1017
+ const KeyV = 'v';
1018
+ const KeyW = 'w';
1019
+ const KeyX = 'x';
1020
+ const KeyY = 'y';
1021
+ const KeyZ = 'z';
1022
+ const F1 = 'F1';
1023
+ const F2 = 'F2';
1024
+ const F3 = 'F3';
1025
+ const F4 = 'F4';
1026
+ const F5 = 'F5';
1027
+ const F6 = 'F6';
1028
+ const Equal = '=';
1029
+ const Comma = ',';
1030
+ const Minus = 'Minus';
1031
+ const Backquote = 'Backquote';
1032
+ const Backslash = 'Backslash';
1033
+ const Star = '*';
1034
+ const Plus = '+';
1035
+
1036
+ const getKeyCodeString = keyCode => {
1037
+ switch (keyCode) {
1038
+ case Backspace$1:
1039
+ return Backspace;
1040
+ case Tab$1:
1041
+ return Tab;
1042
+ case Escape$1:
1043
+ return Escape;
1044
+ case Enter$1:
1045
+ return Enter;
1046
+ case Space$1:
1047
+ return Space;
1048
+ case PageUp$1:
1049
+ return PageUp;
1050
+ case PageDown$1:
1051
+ return PageDown;
1052
+ case End$1:
1053
+ return End;
1054
+ case Home$1:
1055
+ return Home;
1056
+ case LeftArrow$1:
1057
+ return LeftArrow;
1058
+ case UpArrow$1:
1059
+ return UpArrow;
1060
+ case RightArrow$1:
1061
+ return RightArrow;
1062
+ case DownArrow$1:
1063
+ return DownArrow;
1064
+ case Insert$1:
1065
+ return Insert;
1066
+ case Delete$1:
1067
+ return Delete;
1068
+ case Digit0$1:
1069
+ return Digit0;
1070
+ case Digit1$1:
1071
+ return Digit1;
1072
+ case Digit2$1:
1073
+ return Digit2;
1074
+ case Digit3$1:
1075
+ return Digit3;
1076
+ case Digit4$1:
1077
+ return Digit4;
1078
+ case Digit5$1:
1079
+ return Digit5;
1080
+ case Digit6$1:
1081
+ return Digit6;
1082
+ case Digit7$1:
1083
+ return Digit7;
1084
+ case Digit8$1:
1085
+ return Digit8;
1086
+ case Digit9$1:
1087
+ return Digit9;
1088
+ case KeyA$1:
1089
+ return KeyA;
1090
+ case KeyB$1:
1091
+ return KeyB;
1092
+ case KeyC$1:
1093
+ return KeyC;
1094
+ case KeyD$1:
1095
+ return KeyD;
1096
+ case KeyE$1:
1097
+ return KeyE;
1098
+ case KeyF$1:
1099
+ return KeyF;
1100
+ case KeyG$1:
1101
+ return KeyG;
1102
+ case KeyH$1:
1103
+ return KeyH;
1104
+ case KeyI$1:
1105
+ return KeyI;
1106
+ case KeyJ$1:
1107
+ return KeyJ;
1108
+ case KeyK$1:
1109
+ return KeyK;
1110
+ case KeyL$1:
1111
+ return KeyL;
1112
+ case KeyM$1:
1113
+ return KeyM;
1114
+ case KeyN$1:
1115
+ return KeyN;
1116
+ case KeyO$1:
1117
+ return KeyO;
1118
+ case KeyP$1:
1119
+ return KeyP;
1120
+ case KeyQ$1:
1121
+ return KeyQ;
1122
+ case KeyR$1:
1123
+ return KeyR;
1124
+ case KeyS$1:
1125
+ return KeyS;
1126
+ case KeyT$1:
1127
+ return KeyT;
1128
+ case KeyU$1:
1129
+ return KeyU;
1130
+ case KeyV$1:
1131
+ return KeyV;
1132
+ case KeyW$1:
1133
+ return KeyW;
1134
+ case KeyX$1:
1135
+ return KeyX;
1136
+ case KeyY$1:
1137
+ return KeyY;
1138
+ case KeyZ$1:
1139
+ return KeyZ;
1140
+ case F1$1:
1141
+ return F1;
1142
+ case F2$1:
1143
+ return F2;
1144
+ case F3$1:
1145
+ return F3;
1146
+ case F4$1:
1147
+ return F4;
1148
+ case F5$1:
1149
+ return F5;
1150
+ case F6$1:
1151
+ return F6;
1152
+ case Backslash$1:
1153
+ return Backslash;
1154
+ case Equal$1:
1155
+ return Equal;
1156
+ case Comma$1:
1157
+ return Comma;
1158
+ case Backquote$1:
1159
+ return Backquote;
1160
+ case Plus$1:
1161
+ return Plus;
1162
+ case Star$1:
1163
+ return Star;
1164
+ case Minus$1:
1165
+ return Minus;
1166
+ default:
1167
+ return Unknown;
1168
+ }
1169
+ };
1170
+
1171
+ const CtrlCmd = 1 << 11 >>> 0;
1172
+ const Shift = 1 << 10 >>> 0;
1173
+
1174
+ const parseKey = rawKey => {
1175
+ number(rawKey);
1176
+ const isCtrl = Boolean(rawKey & CtrlCmd);
1177
+ const isShift = Boolean(rawKey & Shift);
1178
+ const keyCode = rawKey & 0x00_00_00_ff;
1179
+ const key = getKeyCodeString(keyCode);
1180
+ return {
1181
+ key,
1182
+ isCtrl,
1183
+ isShift
1184
+ };
1185
+ };
1186
+
972
1187
  const Div = 4;
1188
+ const Span = 8;
973
1189
  const Text = 12;
974
1190
 
975
1191
  const text = data => {
@@ -980,6 +1196,165 @@ const text = data => {
980
1196
  };
981
1197
  };
982
1198
 
1199
+ const separator = {
1200
+ type: Div,
1201
+ className: MenuItemSeparator,
1202
+ role: Separator$1,
1203
+ childCount: 1
1204
+ };
1205
+ const separatorLine = {
1206
+ type: Div,
1207
+ className: MenuItemSeparatorLine,
1208
+ childCount: 0
1209
+ };
1210
+ const checkboxUnchecked = {
1211
+ type: Div,
1212
+ className: MenuItem,
1213
+ role: MenuItemCheckBox,
1214
+ ariaChecked: false,
1215
+ tabIndex: -1,
1216
+ childCount: 1
1217
+ };
1218
+ const checkboxChecked = {
1219
+ type: Div,
1220
+ className: `${MenuItem} MenuItemCheckMark`,
1221
+ role: MenuItemCheckBox,
1222
+ ariaChecked: true,
1223
+ tabIndex: -1,
1224
+ childCount: 2
1225
+ };
1226
+ const disabled = {
1227
+ type: Div,
1228
+ className: MenuItem,
1229
+ role: MenuItem$1,
1230
+ tabIndex: -1,
1231
+ disabled: true,
1232
+ childCount: 1
1233
+ };
1234
+ const arrowRight = {
1235
+ type: Div,
1236
+ className: MenuItemSubMenuArrowRight,
1237
+ childCount: 0
1238
+ };
1239
+ const getMenuItemSeparatorDom = menuItem => {
1240
+ return [separator, separatorLine];
1241
+ };
1242
+ const getMenuItemCheckedDom = menuItem => {
1243
+ const {
1244
+ label
1245
+ } = menuItem;
1246
+ return [checkboxChecked, {
1247
+ type: Div,
1248
+ className: 'MenuItemCheckmarkIcon MaskIconCheck'
1249
+ }, text(label)];
1250
+ };
1251
+ const getMenuItemUncheckedDom = menuItem => {
1252
+ const {
1253
+ label
1254
+ } = menuItem;
1255
+ return [checkboxUnchecked, text(label)];
1256
+ };
1257
+ const getMenuItemDisabledDom = menuItem => {
1258
+ const {
1259
+ label
1260
+ } = menuItem;
1261
+ return [disabled, text(label)];
1262
+ };
1263
+ const getMenuItemDefaultDom = menuItem => {
1264
+ const {
1265
+ label,
1266
+ isFocused,
1267
+ key
1268
+ } = menuItem;
1269
+ let className = MenuItem;
1270
+ if (isFocused) {
1271
+ className += ' ' + MenuItemFocused;
1272
+ }
1273
+ const dom = [];
1274
+ dom.push({
1275
+ type: Div,
1276
+ className,
1277
+ role: MenuItem$1,
1278
+ tabIndex: -1,
1279
+ childCount: 1
1280
+ }, text(label));
1281
+ if (key) {
1282
+ dom[0].childCount++;
1283
+ const parsedKey = parseKey(key);
1284
+ const keyBindingsString = getKeyBindingString(parsedKey.key, false, parsedKey.isCtrl, parsedKey.isShift);
1285
+ dom.push({
1286
+ type: Span,
1287
+ className: 'MenuItemKeyBinding',
1288
+ childCount: 1
1289
+ }, text(keyBindingsString));
1290
+ }
1291
+ return dom;
1292
+ };
1293
+ const getMenuItemSubMenuDom = menuItem => {
1294
+ const {
1295
+ label,
1296
+ isFocused,
1297
+ isExpanded,
1298
+ level
1299
+ } = menuItem;
1300
+ let className = MenuItem;
1301
+ className += ' ' + MenuItemSubMenu;
1302
+ if (isFocused) {
1303
+ className += ' ' + MenuItemFocused;
1304
+ }
1305
+ return [{
1306
+ type: Div,
1307
+ className,
1308
+ role: MenuItem$1,
1309
+ tabIndex: -1,
1310
+ ariaHasPopup: true,
1311
+ ariaExpanded: isExpanded,
1312
+ ariaOwns: isExpanded ? `Menu-${level + 1}` : undefined,
1313
+ childCount: 2
1314
+ }, text(label), arrowRight];
1315
+ };
1316
+ const getMenuItemVirtualDom = menuItem => {
1317
+ const {
1318
+ flags
1319
+ } = menuItem;
1320
+ switch (flags) {
1321
+ case None:
1322
+ case RestoreFocus:
1323
+ case Ignore:
1324
+ return getMenuItemDefaultDom(menuItem);
1325
+ case Separator:
1326
+ return getMenuItemSeparatorDom();
1327
+ case Checked:
1328
+ return getMenuItemCheckedDom(menuItem);
1329
+ case Unchecked:
1330
+ return getMenuItemUncheckedDom(menuItem);
1331
+ case Disabled:
1332
+ return getMenuItemDisabledDom(menuItem);
1333
+ case SubMenu:
1334
+ return getMenuItemSubMenuDom(menuItem);
1335
+ default:
1336
+ return [];
1337
+ }
1338
+ };
1339
+ const getMenuVirtualDom = menuItems => {
1340
+ const dom = [];
1341
+ dom.push({
1342
+ type: Div,
1343
+ className: Menu,
1344
+ role: Menu$1,
1345
+ tabIndex: -1,
1346
+ childCount: menuItems.length
1347
+ });
1348
+ dom.push(...menuItems.flatMap(getMenuItemVirtualDom));
1349
+ return dom;
1350
+ };
1351
+
1352
+ const HandleClick = 'handleClick';
1353
+ const HandleFocusIn = 'handleFocusIn';
1354
+ const HandleFocusOut = 'handleFocusOut';
1355
+ const HandlePointerOut = 'handlePointerOut';
1356
+ const HandlePointerOver = 'handlePointerOver';
1357
+
983
1358
  const getItemVirtualDom = item => {
984
1359
  // @ts-ignore
985
1360
  const {
@@ -994,7 +1369,7 @@ const getItemVirtualDom = item => {
994
1369
  className: TitleBarTopLevelEntry,
995
1370
  ariaHasPopup: true,
996
1371
  ariaExpanded: isOpen,
997
- role: MenuItem,
1372
+ role: MenuItem$1,
998
1373
  childCount: 1,
999
1374
  ariaKeyShortcuts: keyboardShortCut
1000
1375
  });
@@ -1035,6 +1410,31 @@ const getTitleBarMenuBarVirtualDom = visibleItems => {
1035
1410
  }, ...getTitleBarMenuBarItemsVirtualDom(visibleItems)];
1036
1411
  };
1037
1412
 
1413
+ const getVisible = (items, focusedIndex, expanded, level) => {
1414
+ const visibleItems = [];
1415
+ const {
1416
+ length
1417
+ } = items;
1418
+ for (let i = 0; i < length; i++) {
1419
+ const item = items[i];
1420
+ const {
1421
+ flags,
1422
+ label
1423
+ } = item;
1424
+ visibleItems.push({
1425
+ label,
1426
+ flags,
1427
+ isFocused: i === focusedIndex,
1428
+ isExpanded: i === focusedIndex && expanded,
1429
+ level,
1430
+ key: item.key
1431
+ });
1432
+ }
1433
+ return visibleItems;
1434
+ };
1435
+
1436
+ const Ellipsis = 'Ellipsis';
1437
+
1038
1438
  const emptyObject = {};
1039
1439
  const RE_PLACEHOLDER = /\{(PH\d+)\}/g;
1040
1440
  const i18nString = (key, placeholders = emptyObject) => {
@@ -1047,10 +1447,292 @@ const i18nString = (key, placeholders = emptyObject) => {
1047
1447
  return key.replaceAll(RE_PLACEHOLDER, replacer);
1048
1448
  };
1049
1449
 
1450
+ const About = 'About';
1451
+ const CheckForUpdates = 'Check For Updates';
1452
+ const ClearRecentlyOpened = 'Clear Recently Opened';
1453
+ const Edit$1 = 'Edit';
1454
+ const File$1 = 'File';
1455
+ const Go$1 = 'Go';
1456
+ const Help$1 = 'Help';
1457
+ const MoreDot = 'More ...';
1458
+ const Run$1 = 'Run';
1459
+ const Selection$1 = 'Selection';
1460
+ const Terminal$1 = 'Terminal';
1461
+ const View$1 = 'View';
1462
+
1463
+ const moreDot = () => {
1464
+ return i18nString(MoreDot);
1465
+ };
1466
+ const clearRecentlyOpened = () => {
1467
+ return i18nString(ClearRecentlyOpened);
1468
+ };
1469
+
1470
+ const getVisibleTitleBarEntries = (entries, width, focusedIndex, isMenuOpen) => {
1471
+ array(entries);
1472
+ number(width);
1473
+ let total = 0;
1474
+ const visible = [];
1475
+ for (let i = 0; i < entries.length; i++) {
1476
+ const entry = entries[i];
1477
+ total += entry.width;
1478
+ if (total >= width) {
1479
+ break;
1480
+ }
1481
+ const isOpen = i === focusedIndex && isMenuOpen;
1482
+ const isFocused = i === focusedIndex;
1483
+ visible.push({
1484
+ ...entry,
1485
+ isOpen,
1486
+ isFocused
1487
+ });
1488
+ }
1489
+ const hasOverflow = visible.length < entries.length;
1490
+ if (hasOverflow) {
1491
+ const padding = 8;
1492
+ const moreIconWidth = 22;
1493
+ const totalPadding = padding * 2;
1494
+ const hasStillOverflow = total + moreIconWidth + totalPadding > width;
1495
+ if (hasStillOverflow) {
1496
+ visible.pop();
1497
+ }
1498
+ visible.push({
1499
+ ariaLabel: moreDot(),
1500
+ icon: Ellipsis,
1501
+ label: '',
1502
+ width: moreIconWidth + totalPadding
1503
+ });
1504
+ }
1505
+ return visible;
1506
+ };
1507
+
1508
+ const SetFocusedIndex = 'setFocusedIndex';
1509
+ const SetMenus = 'setMenus';
1510
+
1511
+ const renderTitleBarEntries = {
1512
+ isEqual(oldState, newState) {
1513
+ return oldState.titleBarEntries === newState.titleBarEntries && oldState.width === newState.width && oldState.focusedIndex === newState.focusedIndex && oldState.isMenuOpen === newState.isMenuOpen;
1514
+ },
1515
+ apply(oldState, newState) {
1516
+ const visibleEntries = getVisibleTitleBarEntries(newState.titleBarEntries, newState.width, newState.focusedIndex, newState.isMenuOpen);
1517
+ const dom = getTitleBarMenuBarVirtualDom(visibleEntries);
1518
+ return ['Viewlet.setDom2', newState.uid, dom];
1519
+ }
1520
+ };
1521
+ const renderFocusedIndex = {
1522
+ isEqual(oldState, newState) {
1523
+ return oldState.focusedIndex === newState.focusedIndex && oldState.isMenuOpen === newState.isMenuOpen;
1524
+ },
1525
+ apply(oldState, newState) {
1526
+ return ['Viewlet.send', newState.uid, /* method */SetFocusedIndex, /* oldFocusedIndex */oldState.focusedIndex, /* newfocusedIndex */newState.focusedIndex, /* oldIsMenuOpen */oldState.isMenuOpen, /* newIsMenuOpen */newState.isMenuOpen];
1527
+ }
1528
+ };
1529
+ const renderMenus = {
1530
+ isEqual(oldState, newState) {
1531
+ return oldState.menus === newState.menus;
1532
+ },
1533
+ apply(oldState, newState) {
1534
+ const oldMenus = oldState.menus;
1535
+ const newMenus = newState.menus;
1536
+ const oldLength = oldMenus.length;
1537
+ const newLength = newMenus.length;
1538
+ const commonLength = Math.min(oldLength, newLength);
1539
+ const changes = [];
1540
+ for (let i = 0; i < commonLength; i++) {
1541
+ const oldMenu = oldMenus[i];
1542
+ const newMenu = newMenus[i];
1543
+ if (oldMenu !== newMenu) {
1544
+ const visible = getVisible(newMenu.items, newMenu.focusedIndex, newMenu.expanded, newMenu.level);
1545
+ const dom = getMenuVirtualDom(visible).slice(1);
1546
+ changes.push([/* method */'updateMenu', newMenu, /* newLength */newLength, dom]);
1547
+ }
1548
+ }
1549
+ const difference = newLength - oldLength;
1550
+ if (difference > 0) {
1551
+ const newMenu = newMenus.at(-1);
1552
+ const visible = getVisible(newMenu.items, newMenu.focusedIndex, newMenu.expanded, newMenu.level);
1553
+ const dom = getMenuVirtualDom(visible).slice(1);
1554
+ changes.push(['addMenu', newMenu, dom]);
1555
+ } else if (difference < 0) {
1556
+ changes.push(['closeMenus', newLength]);
1557
+ }
1558
+ return ['Viewlet.send', newState.uid, /* method */SetMenus, /* changes */changes, newState.uid];
1559
+ }
1560
+ };
1561
+ const render = [renderTitleBarEntries, renderFocusedIndex, renderMenus];
1562
+
1563
+ const create$1 = () => {
1564
+ const states = Object.create(null);
1565
+ return {
1566
+ get(uid) {
1567
+ return states[uid];
1568
+ },
1569
+ set(uid, oldState, newState) {
1570
+ states[uid] = {
1571
+ oldState,
1572
+ newState
1573
+ };
1574
+ }
1575
+ };
1576
+ };
1577
+
1578
+ const {
1579
+ get,
1580
+ set
1581
+ } = create$1();
1582
+
1583
+ const doRender = async uid => {
1584
+ const {
1585
+ oldState,
1586
+ newState
1587
+ } = get(uid);
1588
+ const commands = [];
1589
+ for (const item of render) {
1590
+ if (!item.isEqual(oldState, newState)) {
1591
+ commands.push(item.apply(oldState, newState));
1592
+ }
1593
+ }
1594
+ return commands;
1595
+ };
1596
+
1597
+ const commandsIds = ['closeMenu', 'focus', 'focusFirst', 'focusIndex', 'focusLast', 'focusNext', 'focusPrevious', 'handleKeyArrowDown', 'handleKeyArrowLeft', 'handleKeyArrowRight', 'handleKeyArrowUp', 'handleKeyEnd', 'handleKeyEnter', 'handleKeyEscape', 'handleKeyHome', 'handleKeySpace', 'handleMenuClick', 'handleMenuMouseOver', 'handleMouseOver', 'handleMouseOut', 'toggleIndex', 'toggleMenu', 'handleClick', 'handleFocus'];
1598
+ const getCommandIds = () => {
1599
+ return commandsIds;
1600
+ };
1601
+
1602
+ const FocusTitleBarMenuBar = 26;
1603
+
1604
+ const getKeyBindings = () => {
1605
+ return [{
1606
+ key: DownArrow$1,
1607
+ command: 'TitleBarMenuBar.handleKeyArrowDown',
1608
+ when: FocusTitleBarMenuBar
1609
+ }, {
1610
+ key: UpArrow$1,
1611
+ command: 'TitleBarMenuBar.handleKeyArrowUp',
1612
+ when: FocusTitleBarMenuBar
1613
+ }, {
1614
+ key: RightArrow$1,
1615
+ command: 'TitleBarMenuBar.handleKeyArrowRight',
1616
+ when: FocusTitleBarMenuBar
1617
+ }, {
1618
+ key: LeftArrow$1,
1619
+ command: 'TitleBarMenuBar.handleKeyArrowLeft',
1620
+ when: FocusTitleBarMenuBar
1621
+ }, {
1622
+ key: Space$1,
1623
+ command: 'TitleBarMenuBar.handleKeySpace',
1624
+ when: FocusTitleBarMenuBar
1625
+ }, {
1626
+ key: Home$1,
1627
+ command: 'TitleBarMenuBar.handleKeyHome',
1628
+ when: FocusTitleBarMenuBar
1629
+ }, {
1630
+ key: End$1,
1631
+ command: 'TitleBarMenuBar.handleKeyEnd',
1632
+ when: FocusTitleBarMenuBar
1633
+ }, {
1634
+ key: Escape$1,
1635
+ command: 'TitleBarMenuBar.handleKeyEscape',
1636
+ when: FocusTitleBarMenuBar
1637
+ }];
1638
+ };
1639
+
1640
+ const getFontString = (fontWeight, fontSize, fontFamily) => {
1641
+ return `${fontWeight} ${fontSize}px ${fontFamily}`;
1642
+ };
1643
+
1644
+ const state$1 = {
1645
+ ctx: undefined
1646
+ };
1647
+ const getOrCreate = createCtx => {
1648
+ if (state$1.ctx) {
1649
+ return state$1.ctx;
1650
+ }
1651
+ state$1.ctx = createCtx();
1652
+ return state$1.ctx;
1653
+ };
1654
+
1655
+ const createCtx = () => {
1656
+ const canvas = new OffscreenCanvas(0, 0);
1657
+ const ctx = /** @type {OffscreenCanvasRenderingContext2D} */canvas.getContext('2d');
1658
+ if (!ctx) {
1659
+ throw new Error('Failed to get canvas context 2d');
1660
+ }
1661
+ return ctx;
1662
+ };
1663
+ const getContext = () => {
1664
+ const ctx = getOrCreate(createCtx);
1665
+ return ctx;
1666
+ };
1667
+
1668
+ const px = value => {
1669
+ return `${value}px`;
1670
+ };
1671
+
1672
+ const getLetterSpacingString = letterSpacing => {
1673
+ return px(letterSpacing);
1674
+ };
1675
+ const measureTextWidth = (text, fontWeight, fontSize, fontFamily, letterSpacing, isMonoSpaceFont, charWidth) => {
1676
+ string(text);
1677
+ number(fontWeight);
1678
+ number(fontSize);
1679
+ string(fontFamily);
1680
+ boolean(isMonoSpaceFont);
1681
+ number(charWidth);
1682
+ if (typeof letterSpacing !== 'number') {
1683
+ throw new TypeError('letterSpacing must be of type number');
1684
+ }
1685
+ const letterSpacingString = getLetterSpacingString(letterSpacing);
1686
+ const fontString = getFontString(fontWeight, fontSize, fontFamily);
1687
+ const ctx = getContext();
1688
+ // @ts-ignore
1689
+ ctx.letterSpacing = letterSpacingString;
1690
+ ctx.font = fontString;
1691
+ const metrics = ctx.measureText(text);
1692
+ const {
1693
+ width
1694
+ } = metrics;
1695
+ return width;
1696
+ };
1697
+
1698
+ const measureTitleBarEntryWidth = (label, fontWeight, fontSize, fontFamily, letterSpacing) => {
1699
+ const isMonospaceFont = false;
1700
+ const charWidth = 0;
1701
+ return measureTextWidth(label, fontWeight, fontSize, fontFamily, letterSpacing, isMonospaceFont, charWidth);
1702
+ };
1703
+
1704
+ const addWidths = (entries, labelPadding, fontWeight, fontSize, fontFamily, letterSpacing) => {
1705
+ const withWidths = [];
1706
+ for (const entry of entries) {
1707
+ const textWidth = measureTitleBarEntryWidth(entry.label, fontWeight, fontSize, fontFamily, letterSpacing);
1708
+ const width = textWidth + labelPadding * 2;
1709
+ withWidths.push({
1710
+ ...entry,
1711
+ width
1712
+ });
1713
+ }
1714
+ return withWidths;
1715
+ };
1716
+
1717
+ const loadContent = async (state, titleBarEntries) => {
1718
+ const {
1719
+ labelFontFamily,
1720
+ labelFontSize,
1721
+ labelFontWeight,
1722
+ labelLetterSpacing,
1723
+ labelPadding
1724
+ } = state;
1725
+ const withWidths = addWidths(titleBarEntries, labelPadding, labelFontWeight, labelFontSize, labelFontFamily, labelLetterSpacing);
1726
+ return {
1727
+ ...state,
1728
+ titleBarEntries: withWidths
1729
+ };
1730
+ };
1731
+
1050
1732
  /**
1051
1733
  * @enum {string}
1052
1734
  */
1053
- const UiStrings$5 = {
1735
+ const UiStrings$2 = {
1054
1736
  Copy: 'Copy',
1055
1737
  CopyLineDown: 'Copy Line Down',
1056
1738
  CopyLineUp: 'Copy Line Up',
@@ -1064,54 +1746,40 @@ const UiStrings$5 = {
1064
1746
  ToggleLineComment: 'Toggle Line Comment',
1065
1747
  Undo: 'Undo'};
1066
1748
  const cut = () => {
1067
- return i18nString(UiStrings$5.Cut);
1749
+ return i18nString(UiStrings$2.Cut);
1068
1750
  };
1069
1751
  const copy = () => {
1070
- return i18nString(UiStrings$5.Copy);
1752
+ return i18nString(UiStrings$2.Copy);
1071
1753
  };
1072
1754
  const paste = () => {
1073
- return i18nString(UiStrings$5.Paste);
1755
+ return i18nString(UiStrings$2.Paste);
1074
1756
  };
1075
1757
  const undo = () => {
1076
- return i18nString(UiStrings$5.Undo);
1758
+ return i18nString(UiStrings$2.Undo);
1077
1759
  };
1078
1760
  const redo = () => {
1079
- return i18nString(UiStrings$5.Redo);
1761
+ return i18nString(UiStrings$2.Redo);
1080
1762
  };
1081
1763
  const toggleLineComment = () => {
1082
- return i18nString(UiStrings$5.ToggleLineComment);
1764
+ return i18nString(UiStrings$2.ToggleLineComment);
1083
1765
  };
1084
1766
  const toggleBlockComment = () => {
1085
- return i18nString(UiStrings$5.ToggleBlockComment);
1767
+ return i18nString(UiStrings$2.ToggleBlockComment);
1086
1768
  };
1087
1769
  const selectAll = () => {
1088
- return i18nString(UiStrings$5.SelectAll);
1770
+ return i18nString(UiStrings$2.SelectAll);
1089
1771
  };
1090
1772
  const copyLineUp = () => {
1091
- return i18nString(UiStrings$5.CopyLineUp);
1773
+ return i18nString(UiStrings$2.CopyLineUp);
1092
1774
  };
1093
1775
  const copyLineDown = () => {
1094
- return i18nString(UiStrings$5.CopyLineDown);
1776
+ return i18nString(UiStrings$2.CopyLineDown);
1095
1777
  };
1096
1778
  const moveLineUp = () => {
1097
- return i18nString(UiStrings$5.MoveLineUp);
1779
+ return i18nString(UiStrings$2.MoveLineUp);
1098
1780
  };
1099
1781
  const moveLineDown = () => {
1100
- return i18nString(UiStrings$5.MoveLineDown);
1101
- };
1102
-
1103
- const Separator = 1;
1104
- const None = 0;
1105
- const SubMenu = 4;
1106
- const Disabled = 5;
1107
- const RestoreFocus = 6;
1108
- const Ignore = 7;
1109
-
1110
- const menuEntrySeparator = {
1111
- id: 'separator',
1112
- label: '',
1113
- flags: Separator,
1114
- command: ''
1782
+ return i18nString(UiStrings$2.MoveLineDown);
1115
1783
  };
1116
1784
 
1117
1785
  const Edit = 2;
@@ -1125,6 +1793,13 @@ const Terminal = 14;
1125
1793
  const TitleBar = 15;
1126
1794
  const View = 16;
1127
1795
 
1796
+ const menuEntrySeparator = {
1797
+ id: 'separator',
1798
+ label: '',
1799
+ flags: Separator,
1800
+ command: ''
1801
+ };
1802
+
1128
1803
  const id$9 = Edit;
1129
1804
  const getMenuEntries$c = () => {
1130
1805
  return [{
@@ -1174,7 +1849,7 @@ const MenuEntriesEdit = {
1174
1849
  /**
1175
1850
  * @enum {string}
1176
1851
  */
1177
- const UiStrings$4 = {
1852
+ const UiStrings$1 = {
1178
1853
  NewFile: 'New File',
1179
1854
  NewWindow: 'New Window',
1180
1855
  OpenFile: 'Open File',
@@ -1184,25 +1859,25 @@ const UiStrings$4 = {
1184
1859
  SaveAll: 'Save All'
1185
1860
  };
1186
1861
  const newFile = () => {
1187
- return i18nString(UiStrings$4.NewFile);
1862
+ return i18nString(UiStrings$1.NewFile);
1188
1863
  };
1189
1864
  const newWindow = () => {
1190
- return i18nString(UiStrings$4.NewWindow);
1865
+ return i18nString(UiStrings$1.NewWindow);
1191
1866
  };
1192
1867
  const openFile = () => {
1193
- return i18nString(UiStrings$4.OpenFile);
1868
+ return i18nString(UiStrings$1.OpenFile);
1194
1869
  };
1195
1870
  const openFolder = () => {
1196
- return i18nString(UiStrings$4.OpenFolder);
1871
+ return i18nString(UiStrings$1.OpenFolder);
1197
1872
  };
1198
1873
  const openRecent = () => {
1199
- return i18nString(UiStrings$4.OpenRecent);
1874
+ return i18nString(UiStrings$1.OpenRecent);
1200
1875
  };
1201
1876
  const save = () => {
1202
- return i18nString(UiStrings$4.Save);
1877
+ return i18nString(UiStrings$1.Save);
1203
1878
  };
1204
1879
  const saveAll = () => {
1205
- return i18nString(UiStrings$4.SaveAll);
1880
+ return i18nString(UiStrings$1.SaveAll);
1206
1881
  };
1207
1882
 
1208
1883
  const platform = 1;
@@ -1267,17 +1942,11 @@ const MenuEntriesGo = {
1267
1942
  id: id$7
1268
1943
  };
1269
1944
 
1270
- /**
1271
- * @enum {string}
1272
- */
1273
- const UiStrings$3 = {
1274
- About: 'About',
1275
- CheckForUpdates: 'Check For Updates'};
1276
1945
  const checkForUpdates = () => {
1277
- return i18nString(UiStrings$3.CheckForUpdates);
1946
+ return i18nString(CheckForUpdates);
1278
1947
  };
1279
1948
  const about = () => {
1280
- return i18nString(UiStrings$3.About);
1949
+ return i18nString(About);
1281
1950
  };
1282
1951
 
1283
1952
  const isAutoUpdateSupported = () => {
@@ -1316,16 +1985,18 @@ const MenuEntriesHelp = {
1316
1985
  id: id$6
1317
1986
  };
1318
1987
 
1319
- const state$1 = {
1988
+ const state = {
1320
1989
  rpc: undefined
1321
1990
  };
1322
1991
  const invoke = (method, ...params) => {
1323
- const rpc = state$1.rpc;
1992
+ const {
1993
+ rpc
1994
+ } = state;
1324
1995
  // @ts-ignore
1325
1996
  return rpc.invoke(method, ...params);
1326
1997
  };
1327
1998
  const setRpc = rpc => {
1328
- state$1.rpc = rpc;
1999
+ state.rpc = rpc;
1329
2000
  };
1330
2001
 
1331
2002
  const getTitle = uri => {
@@ -1335,20 +2006,6 @@ const getTitle = uri => {
1335
2006
  return uri;
1336
2007
  };
1337
2008
 
1338
- /**
1339
- * @enum {string}
1340
- */
1341
- const UiStrings$2 = {
1342
- MoreDot: 'More ...',
1343
- ClearRecentlyOpened: 'Clear Recently Opened'
1344
- };
1345
- const moreDot = () => {
1346
- return i18nString(UiStrings$2.MoreDot);
1347
- };
1348
- const clearRecentlyOpened = () => {
1349
- return i18nString(UiStrings$2.ClearRecentlyOpened);
1350
- };
1351
-
1352
2009
  const MAX_MENU_RECENT_ENTRIES = 10;
1353
2010
  const toMenuItem = folder => {
1354
2011
  const label = getTitle(folder);
@@ -1440,11 +2097,11 @@ const MenuEntriesSelection = {
1440
2097
  /**
1441
2098
  * @enum {string}
1442
2099
  */
1443
- const UiStrings$1 = {
2100
+ const UiStrings = {
1444
2101
  NewTerminal: 'New Terminal'
1445
2102
  };
1446
2103
  const newTerminal = () => {
1447
- return i18nString(UiStrings$1.NewTerminal);
2104
+ return i18nString(UiStrings.NewTerminal);
1448
2105
  };
1449
2106
 
1450
2107
  const id$2 = Terminal;
@@ -1464,42 +2121,29 @@ const MenuEntriesTerminal = {
1464
2121
  id: id$2
1465
2122
  };
1466
2123
 
1467
- /**
1468
- * @enum {string}
1469
- */
1470
- const UiStrings = {
1471
- File: 'File',
1472
- Edit: 'Edit',
1473
- Selection: 'Selection',
1474
- View: 'View',
1475
- Go: 'Go',
1476
- Run: 'Run',
1477
- Terminal: 'Terminal',
1478
- Help: 'Help'
1479
- };
1480
2124
  const file = () => {
1481
- return i18nString(UiStrings.File);
2125
+ return i18nString(File$1);
1482
2126
  };
1483
2127
  const edit = () => {
1484
- return i18nString(UiStrings.Edit);
2128
+ return i18nString(Edit$1);
1485
2129
  };
1486
2130
  const selection = () => {
1487
- return i18nString(UiStrings.Selection);
2131
+ return i18nString(Selection$1);
1488
2132
  };
1489
2133
  const view = () => {
1490
- return i18nString(UiStrings.View);
2134
+ return i18nString(View$1);
1491
2135
  };
1492
2136
  const go = () => {
1493
- return i18nString(UiStrings.Go);
2137
+ return i18nString(Go$1);
1494
2138
  };
1495
2139
  const run = () => {
1496
- return i18nString(UiStrings.Run);
2140
+ return i18nString(Run$1);
1497
2141
  };
1498
2142
  const terminal = () => {
1499
- return i18nString(UiStrings.Terminal);
2143
+ return i18nString(Terminal$1);
1500
2144
  };
1501
2145
  const help = () => {
1502
- return i18nString(UiStrings.Help);
2146
+ return i18nString(Help$1);
1503
2147
  };
1504
2148
 
1505
2149
  const getMenuEntries$4 = () => {
@@ -1604,9 +2248,17 @@ const menus = [MenuEntriesEdit, MenuEntriesFile, MenuEntriesGo, MenuEntriesHelp,
1604
2248
  const getMenus = () => {
1605
2249
  return menus;
1606
2250
  };
2251
+ const getModule = id => {
2252
+ for (const module of menus) {
2253
+ if (module.id === id) {
2254
+ return module;
2255
+ }
2256
+ }
2257
+ return undefined;
2258
+ };
1607
2259
  const getMenuEntries = async (id, ...args) => {
1608
2260
  try {
1609
- const module = menus[0];
2261
+ const module = getModule(id);
1610
2262
  // @ts-ignore
1611
2263
  const inject = module.inject || [];
1612
2264
  // @ts-ignore
@@ -1616,70 +2268,16 @@ const getMenuEntries = async (id, ...args) => {
1616
2268
  }
1617
2269
  };
1618
2270
 
1619
- const getFontString = (fontWeight, fontSize, fontFamily) => {
1620
- return `${fontWeight} ${fontSize}px ${fontFamily}`;
1621
- };
1622
-
1623
- const state = {
1624
- ctx: undefined
1625
- };
1626
- const getOrCreate = createCtx => {
1627
- if (state.ctx) {
1628
- return state.ctx;
1629
- }
1630
- state.ctx = createCtx();
1631
- return state.ctx;
1632
- };
1633
-
1634
- const createCtx = () => {
1635
- const canvas = new OffscreenCanvas(0, 0);
1636
- const ctx = /** @type {OffscreenCanvasRenderingContext2D} */canvas.getContext('2d');
1637
- if (!ctx) {
1638
- throw new Error('Failed to get canvas context 2d');
1639
- }
1640
- return ctx;
1641
- };
1642
- const getContext = () => {
1643
- const ctx = getOrCreate(createCtx);
1644
- return ctx;
1645
- };
1646
-
1647
- const px = value => {
1648
- return `${value}px`;
2271
+ const saveState = uid => {
2272
+ return {};
1649
2273
  };
1650
2274
 
1651
- const getLetterSpacingString = letterSpacing => {
1652
- return px(letterSpacing);
1653
- };
1654
- const measureTextWidth = (text, fontWeight, fontSize, fontFamily, letterSpacing, isMonoSpaceFont, charWidth) => {
1655
- string(text);
1656
- number(fontWeight);
1657
- number(fontSize);
1658
- string(fontFamily);
1659
- boolean(isMonoSpaceFont);
1660
- number(charWidth);
1661
- if (typeof letterSpacing !== 'number') {
1662
- throw new TypeError('letterSpacing must be of type number');
1663
- }
1664
- const letterSpacingString = getLetterSpacingString(letterSpacing);
1665
- const fontString = getFontString(fontWeight, fontSize, fontFamily);
1666
- const ctx = getContext();
1667
- // @ts-ignore
1668
- ctx.letterSpacing = letterSpacingString;
1669
- ctx.font = fontString;
1670
- const metrics = ctx.measureText(text);
1671
- const width = metrics.width;
1672
- return width;
1673
- };
1674
-
1675
- const measureTitleBarEntryWidth = (label, fontWeight, fontSize, fontFamily, letterSpacing) => {
1676
- const isMonospaceFont = false;
1677
- const charWidth = 0;
1678
- return measureTextWidth(label, fontWeight, fontSize, fontFamily, letterSpacing, isMonospaceFont, charWidth);
2275
+ const terminate = () => {
2276
+ globalThis.close();
1679
2277
  };
1680
2278
 
1681
2279
  const create = (id, uri, x, y, width, height) => {
1682
- return {
2280
+ const state = {
1683
2281
  uid: id,
1684
2282
  titleBarEntries: [],
1685
2283
  focusedIndex: -1,
@@ -1696,35 +2294,8 @@ const create = (id, uri, x, y, width, height) => {
1696
2294
  width,
1697
2295
  height
1698
2296
  };
1699
- };
1700
- const addWidths = (entries, labelPadding, fontWeight, fontSize, fontFamily, letterSpacing) => {
1701
- const withWidths = [];
1702
- for (const entry of entries) {
1703
- const textWidth = measureTitleBarEntryWidth(entry.label, fontWeight, fontSize, fontFamily, letterSpacing);
1704
- const width = textWidth + labelPadding * 2;
1705
- withWidths.push({
1706
- ...entry,
1707
- width
1708
- });
1709
- }
1710
- return withWidths;
1711
- };
1712
- const loadContent = async state => {
1713
- const {
1714
- labelFontFamily,
1715
- labelFontSize,
1716
- labelFontWeight,
1717
- labelLetterSpacing,
1718
- labelPadding
1719
- } = state;
1720
- const titleBarEntries = [];
1721
- const withWidths = addWidths(titleBarEntries, labelPadding, labelFontWeight, labelFontSize, labelFontFamily, labelLetterSpacing);
1722
- // const visible = GetVisibleTitleBarEntries.getVisibleTitleBarEntries(withWidths, width)
1723
- // console.log({ visible })
1724
- return {
1725
- ...state,
1726
- titleBarEntries: withWidths
1727
- };
2297
+ set(id, state, state);
2298
+ return state;
1728
2299
  };
1729
2300
 
1730
2301
  const closeMenu = (state, keepFocus) => {
@@ -1756,6 +2327,14 @@ const previous = (items, index) => {
1756
2327
  return index === 0 ? items.length - 1 : index - 1;
1757
2328
  };
1758
2329
 
2330
+ const getTotalWidth = entries => {
2331
+ let total = 0;
2332
+ for (const entry of entries) {
2333
+ total += entry.width;
2334
+ }
2335
+ return total;
2336
+ };
2337
+
1759
2338
  // TODO lazyload menuEntries and use Command.execute (maybe)
1760
2339
  const MENU_WIDTH = 150;
1761
2340
  const CONTEXT_MENU_ITEM_HEIGHT = 26;
@@ -1836,13 +2415,6 @@ const getIndexToFocusNext = menu => {
1836
2415
 
1837
2416
  // TODO more tests
1838
2417
 
1839
- const getTotalWidth = entries => {
1840
- let total = 0;
1841
- for (const entry of entries) {
1842
- total += entry.width;
1843
- }
1844
- return total;
1845
- };
1846
2418
  const openMenuAtIndex = async (state, index, shouldBeFocused) => {
1847
2419
  const {
1848
2420
  titleBarEntries,
@@ -1887,7 +2459,7 @@ const openMenuAtIndex = async (state, index, shouldBeFocused) => {
1887
2459
  };
1888
2460
  };
1889
2461
 
1890
- const focusIndex = (state, index) => {
2462
+ const focusIndex = async (state, index) => {
1891
2463
  object(state);
1892
2464
  number(index);
1893
2465
  const {
@@ -2187,17 +2759,16 @@ const handleKeySpaceMenuOpen = state => {
2187
2759
  const handleKeySpace = ifElse(handleKeySpaceMenuOpen, handleKeySpaceMenuClosed);
2188
2760
 
2189
2761
  const executeMenuItemCommand = async item => {
2190
- // TODO
2191
- throw new Error('not implemented');
2762
+ await invoke(item.command, ...(item.args || []));
2192
2763
  };
2193
2764
 
2194
2765
  const selectIndexIgnore = async (state, item) => {
2195
- await executeMenuItemCommand();
2766
+ await executeMenuItemCommand(item);
2196
2767
  return state;
2197
2768
  };
2198
2769
 
2199
2770
  const selectIndexNone = async (state, item) => {
2200
- await executeMenuItemCommand();
2771
+ await executeMenuItemCommand(item);
2201
2772
  return {
2202
2773
  ...state,
2203
2774
  menus: [],
@@ -2206,7 +2777,7 @@ const selectIndexNone = async (state, item) => {
2206
2777
  };
2207
2778
 
2208
2779
  const selectIndexRestoreFocus = async (state, item) => {
2209
- await executeMenuItemCommand();
2780
+ await executeMenuItemCommand(item);
2210
2781
  return {
2211
2782
  ...state,
2212
2783
  menus: [],
@@ -2252,13 +2823,13 @@ const handleMenuClick = (state, level, index) => {
2252
2823
  const item = menu.items[index];
2253
2824
  switch (item.flags) {
2254
2825
  case None:
2255
- return selectIndexNone(state);
2826
+ return selectIndexNone(state, item);
2256
2827
  case SubMenu:
2257
2828
  return selectIndexSubMenu(state, menu, index);
2258
2829
  case RestoreFocus:
2259
- return selectIndexRestoreFocus(state);
2830
+ return selectIndexRestoreFocus(state, item);
2260
2831
  case Ignore:
2261
- return selectIndexIgnore(state);
2832
+ return selectIndexIgnore(state, item);
2262
2833
  default:
2263
2834
  return state;
2264
2835
  }
@@ -2353,7 +2924,7 @@ const handleMouseOverMenuClosed = (state, index) => {
2353
2924
  return focusIndex(state, index);
2354
2925
  };
2355
2926
 
2356
- const handleMouseOverMenuOpen = (state, index) => {
2927
+ const handleMouseOverMenuOpen = async (state, index) => {
2357
2928
  if (index === -1) {
2358
2929
  return state;
2359
2930
  }
@@ -2372,36 +2943,51 @@ const toggleMenu = state => {
2372
2943
  return openMenu(state, /* focus */false);
2373
2944
  };
2374
2945
 
2946
+ const wrapCommand = fn => {
2947
+ const wrapped = async (uid, ...args) => {
2948
+ const {
2949
+ newState
2950
+ } = get(uid);
2951
+ const newerState = await fn(newState, ...args);
2952
+ set(uid, newState, newerState);
2953
+ };
2954
+ return wrapped;
2955
+ };
2956
+
2375
2957
  const commandMap = {
2376
2958
  'TitleBarMenuBar.closeMenu': closeMenu,
2377
2959
  'TitleBarMenuBar.create': create,
2378
- 'TitleBarMenuBar.focus': focus,
2379
- 'TitleBarMenuBar.focusFirst': focusFirst,
2380
- 'TitleBarMenuBar.focusIndex': focusLast,
2381
- 'TitleBarMenuBar.focusLast': focusIndex,
2382
- 'TitleBarMenuBar.focusNext': focusNext,
2383
- 'TitleBarMenuBar.focusPrevious': focusPrevious,
2960
+ 'TitleBarMenuBar.focus': wrapCommand(focus),
2961
+ 'TitleBarMenuBar.focusFirst': wrapCommand(focusFirst),
2962
+ 'TitleBarMenuBar.focusIndex': wrapCommand(focusLast),
2963
+ 'TitleBarMenuBar.focusLast': wrapCommand(focusIndex),
2964
+ 'TitleBarMenuBar.focusNext': wrapCommand(focusNext),
2965
+ 'TitleBarMenuBar.focusPrevious': wrapCommand(focusPrevious),
2966
+ 'TitleBarMenuBar.getCommands': getCommandIds,
2384
2967
  'TitleBarMenuBar.getKeyBindings': getKeyBindings,
2385
2968
  'TitleBarMenuBar.getMenus': getMenus,
2386
2969
  'TitleBarMenuBar.getVirtualDom': getTitleBarMenuBarVirtualDom,
2387
- 'TitleBarMenuBar.handleClick': handleClick,
2388
- 'TitleBarMenuBar.handleFocus': handleFocus,
2389
- 'TitleBarMenuBar.handleKeyArrowDown': handleKeyArrowDown,
2390
- 'TitleBarMenuBar.handleKeyArrowLeft': handleKeyArrowLeft,
2391
- 'TitleBarMenuBar.handleKeyArrowRight': handleKeyArrowRight,
2392
- 'TitleBarMenuBar.handleKeyArrowUp': handleKeyArrowUp,
2393
- 'TitleBarMenuBar.handleKeyEnd': handleKeyEnd,
2394
- 'TitleBarMenuBar.handleKeyEnter': handleKeyEnter,
2395
- 'TitleBarMenuBar.handleKeyEscape': handleKeyEscape,
2396
- 'TitleBarMenuBar.handleKeyHome': handleKeyHome,
2397
- 'TitleBarMenuBar.handleKeySpace': handleKeySpace,
2398
- 'TitleBarMenuBar.handleMenuClick': handleMenuClick,
2399
- 'TitleBarMenuBar.handleMenuMouseOver': handleMenuMouseOver,
2400
- 'TitleBarMenuBar.handleMouseOut': handleMouseOut,
2401
- 'TitleBarMenuBar.handleMouseOver': handleMouseOver,
2402
- 'TitleBarMenuBar.loadContent': loadContent,
2403
- 'TitleBarMenuBar.toggleIndex': toggleIndex,
2404
- 'TitleBarMenuBar.toggleMenu': toggleMenu
2970
+ 'TitleBarMenuBar.handleClick': wrapCommand(handleClick),
2971
+ 'TitleBarMenuBar.handleFocus': wrapCommand(handleFocus),
2972
+ 'TitleBarMenuBar.handleKeyArrowDown': wrapCommand(handleKeyArrowDown),
2973
+ 'TitleBarMenuBar.handleKeyArrowLeft': wrapCommand(handleKeyArrowLeft),
2974
+ 'TitleBarMenuBar.handleKeyArrowRight': wrapCommand(handleKeyArrowRight),
2975
+ 'TitleBarMenuBar.handleKeyArrowUp': wrapCommand(handleKeyArrowUp),
2976
+ 'TitleBarMenuBar.handleKeyEnd': wrapCommand(handleKeyEnd),
2977
+ 'TitleBarMenuBar.handleKeyEnter': wrapCommand(handleKeyEnter),
2978
+ 'TitleBarMenuBar.handleKeyEscape': wrapCommand(handleKeyEscape),
2979
+ 'TitleBarMenuBar.saveState': saveState,
2980
+ 'TitleBarMenuBar.handleKeyHome': wrapCommand(handleKeyHome),
2981
+ 'TitleBarMenuBar.handleKeySpace': wrapCommand(handleKeySpace),
2982
+ 'TitleBarMenuBar.handleMenuClick': wrapCommand(handleMenuClick),
2983
+ 'TitleBarMenuBar.handleMenuMouseOver': wrapCommand(handleMenuMouseOver),
2984
+ 'TitleBarMenuBar.handleMouseOut': wrapCommand(handleMouseOut),
2985
+ 'TitleBarMenuBar.handleMouseOver': wrapCommand(handleMouseOver),
2986
+ 'TitleBarMenuBar.loadContent': wrapCommand(loadContent),
2987
+ 'TitleBarMenuBar.render': doRender,
2988
+ 'TitleBarMenuBar.toggleIndex': wrapCommand(toggleIndex),
2989
+ 'TitleBarMenuBar.toggleMenu': wrapCommand(toggleMenu),
2990
+ 'TitleBarMenuBar.terminate': terminate
2405
2991
  };
2406
2992
 
2407
2993
  const listen = async () => {