@lvce-editor/extension-search-view 7.7.0 → 7.8.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.
@@ -1086,6 +1086,7 @@ const None$3 = 'none';
1086
1086
  const Button$2 = 1;
1087
1087
  const Div = 4;
1088
1088
  const Input$1 = 6;
1089
+ const Span = 8;
1089
1090
  const Text = 12;
1090
1091
  const Img = 17;
1091
1092
  const Reference = 100;
@@ -1095,6 +1096,8 @@ const ClientX = 'event.clientX';
1095
1096
  const ClientY = 'event.clientY';
1096
1097
  const DeltaMode = 'event.deltaMode';
1097
1098
  const DeltaY = 'event.deltaY';
1099
+ const TargetName = 'event.target.name';
1100
+ const TargetSelectionStart = 'event.target.selectionStart';
1098
1101
  const TargetValue = 'event.target.value';
1099
1102
 
1100
1103
  const Script$1 = 2;
@@ -1140,6 +1143,12 @@ const showContextMenu2 = async (uid, menuId, x, y, args) => {
1140
1143
  number(y);
1141
1144
  await invoke$1('ContextMenu.show2', uid, menuId, x, y, args);
1142
1145
  };
1146
+ const disableExtension = async id => {
1147
+ return invoke$1('ExtensionManagement.disable', id);
1148
+ };
1149
+ const enableExtension = async id => {
1150
+ return invoke$1('ExtensionManagement.enable', id);
1151
+ };
1143
1152
  const sendMessagePortToExtensionHostWorker$1 = async (port, rpcId = 0) => {
1144
1153
  const command = 'HandleMessagePort.handleMessagePort2';
1145
1154
  await invokeAndTransfer('SendMessagePortToExtensionHostWorker.sendMessagePortToExtensionHostWorker', port, command, rpcId);
@@ -1158,6 +1167,12 @@ const sendMessagePortToExtensionManagementWorker = async (port, rpcId) => {
1158
1167
  const openUri$1 = async (uri, focus, options) => {
1159
1168
  await invoke$1('Main.openUri', uri, focus, options);
1160
1169
  };
1170
+ const uninstallExtension = async id => {
1171
+ return invoke$1('ExtensionManagement.uninstall', id);
1172
+ };
1173
+ const installExtension = async id => {
1174
+ return invoke$1('ExtensionManagement.install', id);
1175
+ };
1161
1176
 
1162
1177
  const toCommandId = key => {
1163
1178
  const dotIndex = key.indexOf('.');
@@ -1284,6 +1299,29 @@ const None$2 = 0;
1284
1299
  const Input = 1;
1285
1300
  const List$2 = 2;
1286
1301
 
1302
+ const isWhiteSpace = character => {
1303
+ return /\s/.test(character);
1304
+ };
1305
+ const getCompletionRange = (value, cursorOffset) => {
1306
+ const offset = Math.min(Math.max(cursorOffset, 0), value.length);
1307
+ let start = offset;
1308
+ while (start > 0 && !isWhiteSpace(value[start - 1])) {
1309
+ start--;
1310
+ }
1311
+ if (value[start] !== '@') {
1312
+ return undefined;
1313
+ }
1314
+ let end = offset;
1315
+ while (end < value.length && !isWhiteSpace(value[end])) {
1316
+ end++;
1317
+ }
1318
+ return {
1319
+ end,
1320
+ query: value.slice(start, offset),
1321
+ start
1322
+ };
1323
+ };
1324
+
1287
1325
  const handleError = async (error, notify = true, prefix = '') => {
1288
1326
  // @ts-ignore
1289
1327
  console.error(error);
@@ -1309,11 +1347,16 @@ const Enable = 'Enable';
1309
1347
  const Disable = 'Disable';
1310
1348
  const EnableWorkspace = 'Enable Workspace';
1311
1349
  const DisableWorkspace = 'Disable Workspace';
1350
+ const Uninstall = 'Uninstall';
1351
+ const Install = 'Install';
1352
+ const Installing$1 = 'Installing';
1353
+ const Uninstalling$1 = 'Uninstalling';
1312
1354
  const InstallAnotherVersion = 'Install Another Version';
1313
1355
  const SearchExtensionsInMarketplace = 'Search Extensions in Marketplace';
1314
1356
  const ViewsAndMoreActions = 'Views and more Actions...';
1315
1357
  const Extensions$2 = 'Extensions';
1316
1358
  const Installed$1 = 'Installed';
1359
+ const Marketplace = 'Marketplace';
1317
1360
  const Copy = 'Copy';
1318
1361
  const CopyExtensionId = 'Copy Extension Id';
1319
1362
  const Name = 'Name';
@@ -1323,16 +1366,17 @@ const Version = 'Version';
1323
1366
  const Publisher = 'Publisher';
1324
1367
  const MarketplaceLink = 'Marketplace Link';
1325
1368
  const Category$1 = 'Category';
1326
- const Disabled$1 = 'Disabled';
1327
- const Featured = 'Featured';
1328
- const McpServers = 'MCP Servers';
1329
- const MostPopular = 'Most Popular';
1330
- const RecentlyPublished = 'Recently Published';
1331
- const Recommended = 'Recommended';
1369
+ const Disabled$2 = 'Disabled';
1370
+ const Featured$1 = 'Featured';
1371
+ const McpServers$1 = 'MCP Servers';
1372
+ const MostPopular$1 = 'Most Popular';
1373
+ const RecentlyPublished$1 = 'Recently Published';
1374
+ const Recommended$1 = 'Recommended';
1332
1375
  const Updates = 'Updates';
1333
1376
  const BuiltIn = 'Built-in';
1334
- const Enabled$1 = 'Enabled';
1335
- const WorkspaceUnsupported = 'Workspace Unsupported';
1377
+ const Enabled$2 = 'Enabled';
1378
+ const WorkspaceUnsupported$1 = 'Workspace Unsupported';
1379
+ const Deprecated$1 = 'Deprecated';
1336
1380
  const SortBy = 'Sort By';
1337
1381
 
1338
1382
  const noExtensionsFound = () => {
@@ -1368,10 +1412,10 @@ const extensions = () => {
1368
1412
  const clearExtensionSearchResults = () => {
1369
1413
  return i18nString(ClearExtensionSearchResults);
1370
1414
  };
1371
- const enable$1 = () => {
1415
+ const enable$2 = () => {
1372
1416
  return i18nString(Enable);
1373
1417
  };
1374
- const disable$1 = () => {
1418
+ const disable$2 = () => {
1375
1419
  return i18nString(Disable);
1376
1420
  };
1377
1421
  const enableWorkspace$1 = () => {
@@ -1380,6 +1424,18 @@ const enableWorkspace$1 = () => {
1380
1424
  const disableWorkspace$1 = () => {
1381
1425
  return i18nString(DisableWorkspace);
1382
1426
  };
1427
+ const uninstall$1 = () => {
1428
+ return i18nString(Uninstall);
1429
+ };
1430
+ const install$1 = () => {
1431
+ return i18nString(Install);
1432
+ };
1433
+ const installing$1 = () => {
1434
+ return i18nString(Installing$1);
1435
+ };
1436
+ const uninstalling$1 = () => {
1437
+ return i18nString(Uninstalling$1);
1438
+ };
1383
1439
  const installAnotherVersion$1 = () => {
1384
1440
  return i18nString(InstallAnotherVersion);
1385
1441
  };
@@ -1398,26 +1454,29 @@ const viewsAndMoreActions = () => {
1398
1454
  const installed = () => {
1399
1455
  return i18nString(Installed$1);
1400
1456
  };
1457
+ const marketplace = () => {
1458
+ return i18nString(Marketplace);
1459
+ };
1401
1460
  const category = () => {
1402
1461
  return i18nString(Category$1);
1403
1462
  };
1404
1463
  const disabled = () => {
1405
- return i18nString(Disabled$1);
1464
+ return i18nString(Disabled$2);
1406
1465
  };
1407
1466
  const featured = () => {
1408
- return i18nString(Featured);
1467
+ return i18nString(Featured$1);
1409
1468
  };
1410
1469
  const mcpServers = () => {
1411
- return i18nString(McpServers);
1470
+ return i18nString(McpServers$1);
1412
1471
  };
1413
1472
  const mostPopular = () => {
1414
- return i18nString(MostPopular);
1473
+ return i18nString(MostPopular$1);
1415
1474
  };
1416
1475
  const recentlyPublished = () => {
1417
- return i18nString(RecentlyPublished);
1476
+ return i18nString(RecentlyPublished$1);
1418
1477
  };
1419
1478
  const recommended = () => {
1420
- return i18nString(Recommended);
1479
+ return i18nString(Recommended$1);
1421
1480
  };
1422
1481
  const updates = () => {
1423
1482
  return i18nString(Updates);
@@ -1426,10 +1485,13 @@ const builtIn = () => {
1426
1485
  return i18nString(BuiltIn);
1427
1486
  };
1428
1487
  const enabled = () => {
1429
- return i18nString(Enabled$1);
1488
+ return i18nString(Enabled$2);
1430
1489
  };
1431
1490
  const workspaceUnsupported = () => {
1432
- return i18nString(WorkspaceUnsupported);
1491
+ return i18nString(WorkspaceUnsupported$1);
1492
+ };
1493
+ const deprecated = () => {
1494
+ return i18nString(Deprecated$1);
1433
1495
  };
1434
1496
  const sortBy = () => {
1435
1497
  return i18nString(SortBy);
@@ -1458,6 +1520,12 @@ const HandleTouchStart = 14;
1458
1520
  const HandleWheel = 15;
1459
1521
  const HandleHeaderContextMenu = 16;
1460
1522
  const HandleBlur = 17;
1523
+ const HandleInstall = 19;
1524
+ const HandleUninstall = 20;
1525
+ const HandleEnable = 21;
1526
+ const HandleDisable = 22;
1527
+ const HandleInputFocus = 23;
1528
+ const HandleInputBlur = 24;
1461
1529
 
1462
1530
  const ClearAll = 'ClearAll';
1463
1531
  const Filter = 'Filter';
@@ -1516,13 +1584,20 @@ const getScrollBarY$1 = (delta, finalDelta, size, scrollBarSize) => {
1516
1584
  };
1517
1585
 
1518
1586
  const Installed = '@installed';
1519
- const Enabled = '@enabled';
1520
- const Disabled = '@disabled';
1587
+ const Enabled$1 = '@enabled';
1588
+ const Disabled$1 = '@disabled';
1521
1589
  const Builtin = '@builtin';
1522
1590
  const Sort = '@sort';
1523
1591
  const Id = '@id';
1524
1592
  const Category = '@category';
1525
1593
  const Outdated = '@outdated';
1594
+ const Featured = '@featured';
1595
+ const McpServers = '@mcpservers';
1596
+ const MostPopular = '@mostpopular';
1597
+ const RecentlyPublished = '@recentlypublished';
1598
+ const Recommended = '@recommended';
1599
+ const WorkspaceUnsupported = '@workspaceunsupported';
1600
+ const Deprecated = '@deprecated';
1526
1601
 
1527
1602
  const RE_PARAM = /@\w+(?::\w+)?/g;
1528
1603
  const deserializeCategory = value => {
@@ -1553,10 +1628,10 @@ const parseValue = value => {
1553
1628
  if (match.startsWith(Installed)) {
1554
1629
  installed = true;
1555
1630
  }
1556
- if (match.startsWith(Enabled)) {
1631
+ if (match.startsWith(Enabled$1)) {
1557
1632
  enabled = true;
1558
1633
  }
1559
- if (match.startsWith(Disabled)) {
1634
+ if (match.startsWith(Disabled$1)) {
1560
1635
  disabled = true;
1561
1636
  }
1562
1637
  if (match.startsWith(Builtin)) {
@@ -1687,10 +1762,11 @@ const handleChange = async (state, update) => {
1687
1762
  ...update
1688
1763
  };
1689
1764
  try {
1690
- const value = fullNewState.searchValue.trim();
1691
1765
  const {
1692
- inputSource
1766
+ inputSource,
1767
+ searchValue
1693
1768
  } = fullNewState;
1769
+ const value = searchValue.trim();
1694
1770
  const hasValue = value.length > 0;
1695
1771
  const inputActions = getInputActions(hasValue);
1696
1772
  const {
@@ -1707,7 +1783,7 @@ const handleChange = async (state, update) => {
1707
1783
  const items = await searchExtensions(allExtensions, value, platform, assetDir);
1708
1784
  if (items.length === 0) {
1709
1785
  return {
1710
- ...state,
1786
+ ...fullNewState,
1711
1787
  allExtensions,
1712
1788
  deltaY: 0,
1713
1789
  finalDeltaY: 0,
@@ -1720,7 +1796,7 @@ const handleChange = async (state, update) => {
1720
1796
  minLineY: 0,
1721
1797
  placeholder: searchExtensionsInMarketPlace(),
1722
1798
  scrollBarHeight: 0,
1723
- searchValue: value
1799
+ searchValue
1724
1800
  };
1725
1801
  }
1726
1802
  const total = items.length;
@@ -1733,7 +1809,7 @@ const handleChange = async (state, update) => {
1733
1809
  const finalDeltaY = getFinalDeltaY(listHeight, itemHeight, total);
1734
1810
  const scrollBarY = getScrollBarY$1(0, finalDeltaY, listHeight, scrollBarHeight);
1735
1811
  return {
1736
- ...state,
1812
+ ...fullNewState,
1737
1813
  allExtensions,
1738
1814
  deltaY: 0,
1739
1815
  finalDeltaY,
@@ -1746,7 +1822,7 @@ const handleChange = async (state, update) => {
1746
1822
  placeholder: searchExtensionsInMarketPlace(),
1747
1823
  scrollBarHeight,
1748
1824
  scrollBarY,
1749
- searchValue: value
1825
+ searchValue
1750
1826
  };
1751
1827
 
1752
1828
  // TODO handle out of order responses (a bit complicated)
@@ -1761,17 +1837,51 @@ const handleChange = async (state, update) => {
1761
1837
  }
1762
1838
  };
1763
1839
 
1840
+ const User = 1;
1841
+ const Script = 2;
1842
+
1843
+ const acceptCompletion = async (state, label) => {
1844
+ const completion = label || state.completionItems[state.completionFocusedIndex]?.label;
1845
+ if (!completion) {
1846
+ return state;
1847
+ }
1848
+ const range = getCompletionRange(state.searchValue, state.cursorOffset);
1849
+ if (!range) {
1850
+ return state;
1851
+ }
1852
+ const searchValue = `${state.searchValue.slice(0, range.start)}${completion}${state.searchValue.slice(range.end)}`;
1853
+ return handleChange(state, {
1854
+ completionFocusedIndex: 0,
1855
+ completionItems: [],
1856
+ cursorOffset: range.start + completion.length,
1857
+ focus: Input,
1858
+ inputSource: Script,
1859
+ searchValue,
1860
+ suggestOpen: false
1861
+ });
1862
+ };
1863
+
1764
1864
  const clearSearchResults = state => {
1765
1865
  return handleChange(state, {
1766
1866
  ...state,
1867
+ completionFocusedIndex: 0,
1868
+ completionItems: [],
1869
+ cursorOffset: 0,
1767
1870
  focus: Input,
1768
1871
  inputSource: Script$1,
1769
- searchValue: ''
1872
+ searchValue: '',
1873
+ suggestOpen: false
1770
1874
  });
1771
1875
  };
1772
1876
 
1773
1877
  const closeSuggest = state => {
1774
- return state;
1878
+ if (!state.suggestOpen) {
1879
+ return state;
1880
+ }
1881
+ return {
1882
+ ...state,
1883
+ suggestOpen: false
1884
+ };
1775
1885
  };
1776
1886
 
1777
1887
  const getFocusedItem = state => {
@@ -1859,10 +1969,13 @@ const {
1859
1969
  wrapGetter
1860
1970
  } = create$1();
1861
1971
 
1862
- const create = (id, uri, x, y, width, height, platform, assetDir) => {
1972
+ const create = (id, uri, x, y, width, height, platform, assetDir, parentUid) => {
1863
1973
  const state = {
1864
1974
  allExtensions: [],
1865
1975
  assetDir,
1976
+ completionFocusedIndex: 0,
1977
+ completionItems: [],
1978
+ cursorOffset: 0,
1866
1979
  deltaY: 0,
1867
1980
  finalDeltaY: 0,
1868
1981
  focus: 0,
@@ -1881,11 +1994,13 @@ const create = (id, uri, x, y, width, height, platform, assetDir) => {
1881
1994
  minimumSliderSize: 0,
1882
1995
  minLineY: 0,
1883
1996
  negativeMargin: 0,
1997
+ parentUid,
1884
1998
  placeholder: '',
1885
1999
  platform,
1886
2000
  scrollBarActive: false,
1887
2001
  scrollBarHeight: 0,
1888
2002
  scrollBarY: 0,
2003
+ scrollSensitivity: 1,
1889
2004
  searchValue: '',
1890
2005
  size: 0,
1891
2006
  suggestOpen: false,
@@ -1897,26 +2012,27 @@ const create = (id, uri, x, y, width, height, platform, assetDir) => {
1897
2012
  set$1(id, state, state);
1898
2013
  };
1899
2014
 
1900
- const isEqual$3 = (oldState, newState) => {
1901
- return oldState.scrollBarHeight === newState.scrollBarHeight && oldState.scrollBarY === newState.scrollBarY && oldState.initial === newState.initial && oldState.deltaY === newState.deltaY;
2015
+ const isEqual$4 = (oldState, newState) => {
2016
+ return oldState.cursorOffset === newState.cursorOffset && oldState.scrollBarHeight === newState.scrollBarHeight && oldState.scrollBarY === newState.scrollBarY && oldState.initial === newState.initial && oldState.deltaY === newState.deltaY && oldState.width === newState.width;
1902
2017
  };
1903
2018
 
1904
- const isEqual$2 = (oldState, newState) => {
2019
+ const isEqual$3 = (oldState, newState) => {
1905
2020
  if (!newState.focus) {
1906
2021
  return true;
1907
2022
  }
1908
2023
  return oldState.focus === newState.focus && oldState.inputSource === newState.inputSource;
1909
2024
  };
1910
2025
 
1911
- const isEqual$1 = (oldState, newState) => {
1912
- return oldState.items === newState.items && oldState.minLineY === newState.minLineY && oldState.maxLineY === newState.maxLineY && oldState.focusedIndex === newState.focusedIndex && oldState.message === newState.message && oldState.focus === newState.focus && oldState.inputActions === newState.inputActions && oldState.placeholder === newState.placeholder;
2026
+ const isEqual$2 = (oldState, newState) => {
2027
+ return oldState.completionFocusedIndex === newState.completionFocusedIndex && oldState.completionItems === newState.completionItems && oldState.items === newState.items && oldState.minLineY === newState.minLineY && oldState.maxLineY === newState.maxLineY && oldState.focusedIndex === newState.focusedIndex && oldState.message === newState.message && oldState.focus === newState.focus && oldState.inputActions === newState.inputActions && oldState.placeholder === newState.placeholder && oldState.suggestOpen === newState.suggestOpen;
1913
2028
  };
1914
2029
 
1915
- const User = 1;
1916
- const Script = 2;
2030
+ const isEqual$1 = (oldState, newState) => {
2031
+ return newState.inputSource === User || oldState.searchValue === newState.searchValue;
2032
+ };
1917
2033
 
1918
2034
  const isEqual = (oldState, newState) => {
1919
- return newState.inputSource === User || oldState.searchValue === newState.searchValue;
2035
+ return newState.parentUid === undefined || oldState.searchValue === newState.searchValue;
1920
2036
  };
1921
2037
 
1922
2038
  const RenderHeader = 1;
@@ -1928,15 +2044,16 @@ const RenderSearchValue = 7;
1928
2044
  const RenderFocusContext = 8;
1929
2045
  const RenderIncremental = 9;
1930
2046
  const RenderCss = 10;
2047
+ const RenderTitle = 11;
1931
2048
 
1932
- const modules = [isEqual$1, isEqual$2, isEqual, isEqual$2, isEqual$3];
1933
- const numbers = [RenderIncremental, RenderFocus, RenderSearchValue, RenderFocusContext, RenderCss];
2049
+ const modules = [isEqual$2, isEqual$3, isEqual$1, isEqual$3, isEqual$4, isEqual];
2050
+ const numbers = [RenderIncremental, RenderFocus, RenderSearchValue, RenderFocusContext, RenderCss, RenderTitle];
1934
2051
 
1935
2052
  const diff2 = uid => {
1936
2053
  return diff(uid, modules, numbers);
1937
2054
  };
1938
2055
 
1939
- const disable = async (state, _id) => {
2056
+ const disable$1 = async (state, _id) => {
1940
2057
  await confirm('not implemented');
1941
2058
  return state;
1942
2059
  };
@@ -1950,7 +2067,7 @@ const dispose = uid => {
1950
2067
  dispose$1(uid);
1951
2068
  };
1952
2069
 
1953
- const enable = async (state, _id) => {
2070
+ const enable$1 = async (state, _id) => {
1954
2071
  await confirm('not implemented');
1955
2072
  return state;
1956
2073
  };
@@ -2145,6 +2262,7 @@ const getActions = () => {
2145
2262
  };
2146
2263
 
2147
2264
  const Enter = 3;
2265
+ const Escape = 8;
2148
2266
  const Space = 9;
2149
2267
  const PageUp = 10;
2150
2268
  const PageDown = 11;
@@ -2160,6 +2278,26 @@ const FocusExtensionsInput = 7000;
2160
2278
 
2161
2279
  const getKeyBindings = () => {
2162
2280
  return [{
2281
+ command: 'Extensions.closeSuggest',
2282
+ key: Escape,
2283
+ when: FocusExtensionsInput
2284
+ }, {
2285
+ command: 'Extensions.acceptCompletion',
2286
+ key: Enter,
2287
+ when: FocusExtensionsInput
2288
+ }, {
2289
+ command: 'Extensions.selectPreviousCompletion',
2290
+ key: UpArrow,
2291
+ when: FocusExtensionsInput
2292
+ }, {
2293
+ command: 'Extensions.selectNextCompletion',
2294
+ key: DownArrow,
2295
+ when: FocusExtensionsInput
2296
+ }, {
2297
+ command: 'Extensions.toggleSuggest',
2298
+ key: CtrlCmd | Space,
2299
+ when: FocusExtensionsInput
2300
+ }, {
2163
2301
  command: 'Extensions.focusFirst',
2164
2302
  key: Home,
2165
2303
  when: FocusExtensions
@@ -2211,7 +2349,7 @@ const getMenuEntriesList = () => {
2211
2349
  command: 'SearchExtensions.enable',
2212
2350
  flags: None$1,
2213
2351
  id: 'enable',
2214
- label: enable$1()
2352
+ label: enable$2()
2215
2353
  }, {
2216
2354
  command: 'SearchExtensions.enableWorkspace',
2217
2355
  flags: None$1,
@@ -2226,7 +2364,7 @@ const getMenuEntriesList = () => {
2226
2364
  command: 'SearchExtensions.disable',
2227
2365
  flags: None$1,
2228
2366
  id: 'disable',
2229
- label: disable$1()
2367
+ label: disable$2()
2230
2368
  }, {
2231
2369
  command: 'SearchExtensions.disableWorkspace',
2232
2370
  flags: None$1,
@@ -2353,7 +2491,8 @@ const getMenuIds = () => {
2353
2491
  const handleBlur = state => {
2354
2492
  return {
2355
2493
  ...state,
2356
- focus: None$2
2494
+ focus: None$2,
2495
+ suggestOpen: false
2357
2496
  };
2358
2497
  };
2359
2498
 
@@ -2669,7 +2808,17 @@ const getListIndex = (eventX, eventY, x, y, deltaY, itemHeight, headerHeight) =>
2669
2808
  return index;
2670
2809
  };
2671
2810
 
2672
- const handleClickAt = async (state, button, eventX, eventY) => {
2811
+ const handleCompletionPointerDown = (state, label) => {
2812
+ if (state.completionItems.every(item => item.label !== label)) {
2813
+ return Promise.resolve(state);
2814
+ }
2815
+ return acceptCompletion(state, label);
2816
+ };
2817
+
2818
+ const handleClickAt = async (state, button, eventX, eventY, name = '') => {
2819
+ if (name.startsWith('@')) {
2820
+ return handleCompletionPointerDown(state, name);
2821
+ }
2673
2822
  if (button !== LeftClick) {
2674
2823
  return state;
2675
2824
  }
@@ -2740,17 +2889,50 @@ const handleContextMenu = async (state, button, eventX, eventY) => {
2740
2889
  return state;
2741
2890
  };
2742
2891
 
2743
- const handleDisable = (state, id) => {
2744
- return state;
2745
- // TODO
2892
+ const Disabled = 'disabled';
2893
+ const Enabled = 'enabled';
2894
+ const Installing = 'installing';
2895
+ const NotInstalled = 'not-installed';
2896
+ const Uninstalling = 'uninstalling';
2897
+ const statuses = [Disabled, Enabled, Installing, NotInstalled, Uninstalling];
2898
+ const isExtensionStatus = status => {
2899
+ return statuses.includes(status);
2900
+ };
2901
+
2902
+ const updateStatus = (extension, id, status, builtin) => {
2903
+ if (extension.id !== id) {
2904
+ return extension;
2905
+ }
2906
+ return {
2907
+ ...extension,
2908
+ builtin: builtin ?? extension.builtin,
2909
+ disabled: status === Disabled,
2910
+ status
2911
+ };
2912
+ };
2913
+ const setExtensionStatus = (state, id, status, builtin) => {
2914
+ if (!isExtensionStatus(status)) {
2915
+ throw new TypeError(`Invalid extension status: ${status}`);
2916
+ }
2917
+ return {
2918
+ ...state,
2919
+ allExtensions: state.allExtensions.map(extension => updateStatus(extension, id, status, builtin)),
2920
+ items: state.items.map(extension => updateStatus(extension, id, status, builtin))
2921
+ };
2922
+ };
2923
+
2924
+ const handleDisable = async (state, id) => {
2925
+ const error = await disableExtension(id);
2926
+ return error ? state : setExtensionStatus(state, id, Disabled);
2746
2927
  };
2747
2928
 
2748
2929
  const handleDisableWorkspace = (state, id) => {
2749
2930
  return state;
2750
2931
  };
2751
2932
 
2752
- const handleEnable = (state, id) => {
2753
- return state;
2933
+ const handleEnable = async (state, id) => {
2934
+ const error = await enableExtension(id);
2935
+ return error ? state : setExtensionStatus(state, id, Enabled);
2754
2936
  };
2755
2937
 
2756
2938
  const handleEnableWorkspace = (state, id) => {
@@ -2768,17 +2950,74 @@ const handleHeaderContextMenu = async state => {
2768
2950
  return state;
2769
2951
  };
2770
2952
 
2771
- const handleInput = async (state, value, inputSource = User) => {
2953
+ const getFuzzyHighlights = (label, query) => {
2954
+ const lowerLabel = label.toLowerCase();
2955
+ const lowerQuery = query.toLowerCase();
2956
+ const matchedIndexes = [];
2957
+ let labelIndex = 0;
2958
+ for (const character of lowerQuery) {
2959
+ labelIndex = lowerLabel.indexOf(character, labelIndex);
2960
+ if (labelIndex === -1) {
2961
+ return undefined;
2962
+ }
2963
+ matchedIndexes.push(labelIndex);
2964
+ labelIndex++;
2965
+ }
2966
+ const highlights = [];
2967
+ for (const index of matchedIndexes) {
2968
+ const lastEnd = highlights.at(-1);
2969
+ if (lastEnd === index) {
2970
+ highlights[highlights.length - 1] = index + 1;
2971
+ } else {
2972
+ highlights.push(index, index + 1);
2973
+ }
2974
+ }
2975
+ return highlights;
2976
+ };
2977
+
2978
+ const Suggestions = ['@builtin', '@category:', '@disabled', '@enabled', '@featured', '@id:', '@installed', '@mcpservers', '@mostpopular', '@outdated', '@recentlypublished', '@recommended', '@sort:installs', '@workspaceunsupported'];
2979
+
2980
+ const getCompletionItems = (value, cursorOffset) => {
2981
+ const range = getCompletionRange(value, cursorOffset);
2982
+ if (!range) {
2983
+ return [];
2984
+ }
2985
+ const items = [];
2986
+ for (const label of Suggestions) {
2987
+ const highlights = getFuzzyHighlights(label, range.query);
2988
+ if (highlights) {
2989
+ items.push({
2990
+ highlights,
2991
+ label
2992
+ });
2993
+ }
2994
+ }
2995
+ return items;
2996
+ };
2997
+
2998
+ const handleInput = async (state, value, inputSource = User, cursorOffset = value.length) => {
2999
+ const completionItems = getCompletionItems(value, cursorOffset);
2772
3000
  return handleChange(state, {
3001
+ completionFocusedIndex: 0,
3002
+ completionItems,
3003
+ cursorOffset,
3004
+ focus: Input,
2773
3005
  inputSource,
2774
- searchValue: value
3006
+ searchValue: value,
3007
+ suggestOpen: inputSource === User && completionItems.length > 0
2775
3008
  });
2776
3009
  };
2777
3010
 
2778
- // TODO show error / warning when installment fails / times out
3011
+ const handleInputFocus = state => {
3012
+ return {
3013
+ ...state,
3014
+ focus: Input
3015
+ };
3016
+ };
3017
+
2779
3018
  const handleInstall = async (state, id) => {
2780
- return state;
2781
- // TODO
3019
+ await installExtension(id);
3020
+ return setExtensionStatus(state, id, Enabled);
2782
3021
  };
2783
3022
 
2784
3023
  const handleScrollBarCaptureLost = state => {
@@ -2939,15 +3178,15 @@ const handleSettingsButtonClick = async (state, index) => {
2939
3178
  return state;
2940
3179
  };
2941
3180
 
2942
- // TODO show error / warning when installment fails / times out
2943
3181
  const handleUninstall = async (state, id) => {
2944
- return state;
3182
+ await uninstallExtension(id);
3183
+ return setExtensionStatus(state, id, NotInstalled);
2945
3184
  };
2946
3185
 
2947
3186
  const handleWheel = (state, deltaMode, deltaY) => {
2948
3187
  number(deltaMode);
2949
3188
  number(deltaY);
2950
- return setDeltaY(state, state.deltaY + deltaY);
3189
+ return setDeltaY(state, state.deltaY + deltaY * state.scrollSensitivity);
2951
3190
  };
2952
3191
 
2953
3192
  const sendMessagePortToExtensionHostWorker = async port => {
@@ -3041,6 +3280,11 @@ const getViewletSize = width => {
3041
3280
  return Large;
3042
3281
  };
3043
3282
 
3283
+ const getIsFirefox = () => {
3284
+ const globalWithNavigator = globalThis;
3285
+ return globalWithNavigator.navigator?.userAgent.toLowerCase().includes('firefox') ?? false;
3286
+ };
3287
+
3044
3288
  const getRemoteUrl = (extension, platform, assetDir) => {
3045
3289
  if (platform === Remote || platform === Electron) {
3046
3290
  if (extension.builtin) {
@@ -3086,6 +3330,15 @@ const getExtensionIcon = (extension, platform, assetDir) => {
3086
3330
  return getRemoteUrl(extension, platform, assetDir);
3087
3331
  };
3088
3332
 
3333
+ const getBuiltin = extension => {
3334
+ return extension?.builtin === true;
3335
+ };
3336
+ const getDisabled = extension => {
3337
+ return extension?.disabled === true;
3338
+ };
3339
+ const getStatus = extension => {
3340
+ return typeof extension?.status === 'string' ? extension.status : undefined;
3341
+ };
3089
3342
  const getIcon = (extension, platform, assetDir) => {
3090
3343
  return getExtensionIcon(extension, platform, assetDir);
3091
3344
  };
@@ -3149,13 +3402,16 @@ const getPublisher = extension => {
3149
3402
 
3150
3403
  const normalizeExtension = (extension, platform, assetDir) => {
3151
3404
  return {
3405
+ builtin: getBuiltin(extension),
3152
3406
  categories: getCategories(extension),
3153
3407
  description: getDescription(extension),
3408
+ disabled: getDisabled(extension),
3154
3409
  icon: getIcon(extension, platform, assetDir),
3155
3410
  id: getId$1(extension),
3156
3411
  name: getName(extension),
3157
3412
  publisher: getPublisher(extension),
3158
3413
  size: getSize(extension),
3414
+ status: getStatus(extension),
3159
3415
  updatedDate: getUpdatedDate(extension),
3160
3416
  uri: ''
3161
3417
  };
@@ -3201,30 +3457,47 @@ const loadContent = async (state, savedState) => {
3201
3457
  const allExtensions = await getAllExtensions(platform);
3202
3458
  const size = getViewletSize(width);
3203
3459
  const normalized = normalizeExtensions(allExtensions, platform, assetDir);
3460
+ const scrollSensitivity = getIsFirefox() ? 2.5 : 1;
3204
3461
  const updatedState = await handleInput({
3205
3462
  ...state,
3206
3463
  allExtensions: normalized,
3207
3464
  deltaY,
3208
3465
  initial: false,
3209
3466
  inputSource: Script,
3467
+ scrollSensitivity,
3210
3468
  size
3211
3469
  }, searchValue, Script);
3212
3470
  return updatedState;
3213
3471
  };
3214
3472
 
3215
3473
  const openSuggest = state => {
3216
- return state;
3474
+ const completionItems = getCompletionItems(state.searchValue, state.cursorOffset);
3475
+ if (completionItems.length === 0) {
3476
+ return state;
3477
+ }
3478
+ return {
3479
+ ...state,
3480
+ completionFocusedIndex: 0,
3481
+ completionItems,
3482
+ suggestOpen: true
3483
+ };
3217
3484
  };
3218
3485
 
3219
3486
  const getCss = state => {
3220
3487
  const {
3488
+ cursorOffset,
3221
3489
  deltaY,
3490
+ headerHeight,
3222
3491
  itemHeight,
3223
3492
  scrollBarHeight,
3224
- scrollBarY
3493
+ scrollBarY,
3494
+ width
3225
3495
  } = state;
3226
3496
  const relative = -(deltaY % itemHeight);
3227
3497
  const roundedScrollBarY = Math.round(scrollBarY);
3498
+ const maximumCompletionLeft = Math.max(8, width - 168);
3499
+ const completionLeft = Math.min(Math.round(8 + cursorOffset * 7.5), maximumCompletionLeft);
3500
+ const completionTop = Math.max(0, headerHeight - 10);
3228
3501
  return `.Extensions .ScrollBarThumb {
3229
3502
  height: ${scrollBarHeight}px;
3230
3503
  translate: 0 ${roundedScrollBarY}px;
@@ -3247,6 +3520,61 @@ const getCss = state => {
3247
3520
  gap: 0;
3248
3521
  overflow-y: hidden;
3249
3522
  }
3523
+
3524
+ .ExtensionHeader {
3525
+ contain: layout style;
3526
+ position: relative;
3527
+ z-index: 1;
3528
+ }
3529
+
3530
+ .ExtensionSearchCompletionWidget {
3531
+ position: absolute;
3532
+ left: ${completionLeft}px;
3533
+ top: ${completionTop}px;
3534
+ width: min(320px, calc(100% - ${completionLeft + 8}px));
3535
+ max-height: 240px;
3536
+ overflow-y: auto;
3537
+ z-index: 10;
3538
+ box-sizing: border-box;
3539
+ border: 1px solid var(--CompletionListBorder, #95a29d);
3540
+ background: var(--CompletionListBackground, #282e2f);
3541
+ color: var(--CompletionListForeground, white);
3542
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.36);
3543
+ font-size: 13px;
3544
+ line-height: 20px;
3545
+ user-select: none;
3546
+ }
3547
+
3548
+ .ExtensionSearchCompletionItem {
3549
+ display: block;
3550
+ width: 100%;
3551
+ min-height: 20px;
3552
+ padding: 0 6px;
3553
+ border: 0;
3554
+ background: transparent;
3555
+ color: inherit;
3556
+ font: inherit;
3557
+ line-height: inherit;
3558
+ text-align: left;
3559
+ overflow: hidden;
3560
+ text-overflow: ellipsis;
3561
+ white-space: nowrap;
3562
+ cursor: pointer;
3563
+ }
3564
+
3565
+ .ExtensionSearchCompletionItem:hover {
3566
+ background: var(--CompletionListItemHoverBackground, rgba(64, 92, 80, 0.2));
3567
+ }
3568
+
3569
+ .ExtensionSearchCompletionItemFocused {
3570
+ background: var(--CompletionListItemActiveBackground, #405c50);
3571
+ color: var(--CompletionListItemActiveForeground);
3572
+ }
3573
+
3574
+ .ExtensionSearchCompletionHighlight {
3575
+ color: var(--CompletionHighlightForeground, #e1b974);
3576
+ font-weight: 700;
3577
+ }
3250
3578
  `;
3251
3579
  };
3252
3580
 
@@ -3295,21 +3623,35 @@ const renderFocusContext = newState => {
3295
3623
  return [];
3296
3624
  };
3297
3625
 
3626
+ const ComboBox = 'combobox';
3627
+ const List$1 = 'list';
3628
+ const ListBox = 'listbox';
3629
+ const ListItem = 'listitem';
3630
+ const None = 'none';
3631
+ const Option = 'option';
3632
+ const ToolBar = 'toolbar';
3633
+
3298
3634
  const Actions = 'Actions';
3299
3635
  const ExtensionActions = 'ExtensionActions';
3636
+ const ExtensionActionButton = 'ExtensionActionButton';
3300
3637
  const ExtensionActive = 'ExtensionActive';
3301
3638
  const ExtensionHeader = 'ExtensionHeader';
3302
3639
  const ExtensionListItem = 'ExtensionListItem';
3640
+ const ExtensionListItemActionInstall = 'ExtensionListItemActionInstall';
3303
3641
  const ExtensionListItemAuthorName = 'ExtensionListItemAuthorName';
3304
3642
  const ExtensionListItemDescription = 'ExtensionListItemDescription';
3305
3643
  const ExtensionListItemDetail = 'ExtensionListItemDetail';
3306
3644
  const ExtensionListItemFooter = 'ExtensionListItemFooter';
3307
3645
  const ExtensionListItemIcon = 'ExtensionListItemIcon';
3308
3646
  const ExtensionListItemName = 'ExtensionListItemName';
3647
+ const ExtensionSearchCompletionHighlight = 'ExtensionSearchCompletionHighlight';
3648
+ const ExtensionSearchCompletionItem = 'ExtensionSearchCompletionItem';
3649
+ const ExtensionSearchCompletionItemFocused = 'ExtensionSearchCompletionItemFocused';
3650
+ const ExtensionSearchCompletionWidget = 'ExtensionSearchCompletionWidget';
3309
3651
  const Extensions = 'Extensions';
3310
3652
  const FocusOutline = 'FocusOutline';
3311
3653
  const IconButton = 'IconButton';
3312
- const List$1 = 'List';
3654
+ const List = 'List';
3313
3655
  const ListItems = 'ListItems';
3314
3656
  const MaskIcon = 'MaskIcon';
3315
3657
  const MultilineInputBox = 'MultilineInputBox';
@@ -3325,10 +3667,71 @@ const SearchFieldButtons = 'SearchFieldButtons';
3325
3667
  const SearchFieldContainer = 'SearchFieldContainer';
3326
3668
  const Viewlet = 'Viewlet';
3327
3669
 
3328
- const List = 'list';
3329
- const ListItem = 'listitem';
3330
- const None = 'none';
3331
- const ToolBar = 'toolbar';
3670
+ const getCompletionLabelVirtualDom = (label, highlights) => {
3671
+ const dom = [];
3672
+ let position = 0;
3673
+ for (let i = 0; i < highlights.length; i += 2) {
3674
+ const start = highlights[i];
3675
+ const end = highlights[i + 1];
3676
+ if (position < start) {
3677
+ dom.push(text(label.slice(position, start)));
3678
+ }
3679
+ dom.push({
3680
+ childCount: 1,
3681
+ className: ExtensionSearchCompletionHighlight,
3682
+ name: label,
3683
+ type: Span
3684
+ }, text(label.slice(start, end)));
3685
+ position = end;
3686
+ }
3687
+ if (position < label.length) {
3688
+ dom.push(text(label.slice(position)));
3689
+ }
3690
+ return dom;
3691
+ };
3692
+
3693
+ const getRootNodeCount = nodes => {
3694
+ let count = 0;
3695
+ const remainingChildCounts = [];
3696
+ for (const node of nodes) {
3697
+ while (remainingChildCounts.length > 0 && remainingChildCounts.at(-1) === 0) {
3698
+ remainingChildCounts.pop();
3699
+ }
3700
+ if (remainingChildCounts.length === 0) {
3701
+ count++;
3702
+ } else {
3703
+ const lastIndex = remainingChildCounts.length - 1;
3704
+ remainingChildCounts[lastIndex]--;
3705
+ }
3706
+ remainingChildCounts.push(node.childCount);
3707
+ }
3708
+ return count;
3709
+ };
3710
+ const getCompletionItemVirtualDom = (item, index, focusedIndex) => {
3711
+ const labelDom = getCompletionLabelVirtualDom(item.label, item.highlights);
3712
+ const focused = index === focusedIndex;
3713
+ return [{
3714
+ ariaSelected: focused,
3715
+ childCount: getRootNodeCount(labelDom),
3716
+ className: focused ? mergeClassNames(ExtensionSearchCompletionItem, ExtensionSearchCompletionItemFocused) : ExtensionSearchCompletionItem,
3717
+ id: `ExtensionSearchCompletion-${index}`,
3718
+ name: item.label,
3719
+ onPointerDown: HandlePointerDown,
3720
+ role: Option,
3721
+ type: Button$2
3722
+ }, ...labelDom];
3723
+ };
3724
+
3725
+ const getCompletionWidgetVirtualDom = (items, focusedIndex) => {
3726
+ return [{
3727
+ ariaLabel: 'Extension search completions',
3728
+ childCount: items.length,
3729
+ className: ExtensionSearchCompletionWidget,
3730
+ id: 'ExtensionSearchCompletions',
3731
+ role: ListBox,
3732
+ type: Div
3733
+ }, ...items.flatMap((item, index) => getCompletionItemVirtualDom(item, index, focusedIndex))];
3734
+ };
3332
3735
 
3333
3736
  const disabledClassName = mergeClassNames(SearchFieldButton, SearchFieldButtonDisabled);
3334
3737
  const getClassName$1 = enabled => {
@@ -3358,7 +3761,7 @@ const getSearchFieldButtonVirtualDom = button => {
3358
3761
  }];
3359
3762
  };
3360
3763
 
3361
- const getSearchFieldVirtualDom = (name, placeholder, onInput, insideButtons, outsideButtons, onFocus = '') => {
3764
+ const getSearchFieldVirtualDom = (name, placeholder, onInput, insideButtons, outsideButtons, onFocus = '', onBlur = '', inputProperties = {}) => {
3362
3765
  // TODO avoid mutation
3363
3766
  const dom = [{
3364
3767
  childCount: 2,
@@ -3373,11 +3776,15 @@ const getSearchFieldVirtualDom = (name, placeholder, onInput, insideButtons, out
3373
3776
  className: MultilineInputBox,
3374
3777
  inputType: 'search',
3375
3778
  name,
3779
+ ...(onBlur && {
3780
+ onBlur
3781
+ }),
3376
3782
  onFocus,
3377
3783
  onInput,
3378
3784
  placeholder,
3379
3785
  spellcheck: false,
3380
- type: Input$1
3786
+ type: Input$1,
3787
+ ...inputProperties
3381
3788
  }, {
3382
3789
  childCount: insideButtons.length,
3383
3790
  className: SearchFieldButtons,
@@ -3395,24 +3802,98 @@ const getSearchFieldVirtualDom = (name, placeholder, onInput, insideButtons, out
3395
3802
  return dom;
3396
3803
  };
3397
3804
 
3398
- const parentNode = {
3399
- childCount: 1,
3400
- className: ExtensionHeader,
3401
- onContextMenu: HandleHeaderContextMenu,
3402
- type: Div
3403
- };
3404
- const getExtensionHeaderVirtualDom = (placeholder, actions) => {
3405
- return [parentNode, ...getSearchFieldVirtualDom(Extensions$1, placeholder, HandleExtensionsInput, actions, [])];
3805
+ const getExtensionHeaderVirtualDom = (placeholder, actions, completionItems = [], completionFocusedIndex = 0, suggestOpen = false) => {
3806
+ const inputProperties = suggestOpen ? {
3807
+ ariaActivedescendant: `ExtensionSearchCompletion-${completionFocusedIndex}`,
3808
+ ariaAutoComplete: 'list',
3809
+ ariaControls: 'ExtensionSearchCompletions',
3810
+ ariaExpanded: true,
3811
+ role: ComboBox
3812
+ } : {
3813
+ ariaAutoComplete: 'list',
3814
+ ariaExpanded: false,
3815
+ role: ComboBox
3816
+ };
3817
+ return [{
3818
+ childCount: suggestOpen ? 2 : 1,
3819
+ className: ExtensionHeader,
3820
+ onContextMenu: HandleHeaderContextMenu,
3821
+ type: Div
3822
+ }, ...getSearchFieldVirtualDom(Extensions$1, placeholder, HandleExtensionsInput, actions, [], HandleInputFocus, HandleInputBlur, inputProperties), ...(suggestOpen ? getCompletionWidgetVirtualDom(completionItems, completionFocusedIndex) : [])];
3406
3823
  };
3407
3824
 
3408
3825
  const renderHeader = newState => {
3409
3826
  const actions = getInputActions(newState.searchValue.length > 0);
3410
- const dom = getExtensionHeaderVirtualDom(newState.placeholder, actions);
3827
+ const dom = getExtensionHeaderVirtualDom(newState.placeholder, actions, newState.completionItems, newState.completionFocusedIndex, newState.suggestOpen);
3411
3828
  return ['setHeaderDom', dom];
3412
3829
  };
3413
3830
 
3414
3831
  const Extension = 'Extension';
3415
3832
 
3833
+ const install = {
3834
+ disabled: false,
3835
+ label: install$1(),
3836
+ onClick: HandleInstall
3837
+ };
3838
+ const installing = {
3839
+ disabled: true,
3840
+ label: installing$1(),
3841
+ onClick: HandleInstall
3842
+ };
3843
+ const enable = {
3844
+ disabled: false,
3845
+ label: enable$2(),
3846
+ onClick: HandleEnable
3847
+ };
3848
+ const disable = {
3849
+ disabled: false,
3850
+ label: disable$2(),
3851
+ onClick: HandleDisable
3852
+ };
3853
+ const uninstall = {
3854
+ disabled: false,
3855
+ label: uninstall$1(),
3856
+ onClick: HandleUninstall
3857
+ };
3858
+ const uninstalling = {
3859
+ disabled: true,
3860
+ label: uninstalling$1(),
3861
+ onClick: HandleUninstall
3862
+ };
3863
+ const getExtensionActions = (builtin, disabled, status) => {
3864
+ if (status === NotInstalled) {
3865
+ return [install];
3866
+ }
3867
+ if (status === Installing) {
3868
+ return [installing];
3869
+ }
3870
+ if (status === Uninstalling) {
3871
+ return builtin ? [] : [uninstalling];
3872
+ }
3873
+ const enableOrDisable = status === Disabled || status === undefined && disabled ? enable : disable;
3874
+ return builtin ? [enableOrDisable] : [enableOrDisable, uninstall];
3875
+ };
3876
+
3877
+ const className = mergeClassNames(ExtensionListItemActionInstall, ExtensionActionButton);
3878
+ const getActionVirtualDom$1 = (action, id) => {
3879
+ return [{
3880
+ childCount: 1,
3881
+ className,
3882
+ disabled: action.disabled,
3883
+ name: id,
3884
+ onClick: action.onClick,
3885
+ type: Button$2
3886
+ }, text(action.label)];
3887
+ };
3888
+ const getExtensionActionsVirtualDom = (id, builtin, disabled, status) => {
3889
+ const actions = getExtensionActions(builtin, disabled, status);
3890
+ return [{
3891
+ childCount: actions.length,
3892
+ className: ExtensionActions,
3893
+ type: Div
3894
+ }, ...actions.flatMap(action => getActionVirtualDom$1(action, id))];
3895
+ };
3896
+
3416
3897
  const listItemDetail = {
3417
3898
  childCount: 3,
3418
3899
  className: ExtensionListItemDetail,
@@ -3452,14 +3933,19 @@ const getId = focused => {
3452
3933
  };
3453
3934
  const getExtensionListItemVirtualDom = extension => {
3454
3935
  const {
3936
+ builtin = false,
3455
3937
  description,
3938
+ disabled = false,
3456
3939
  focused,
3457
3940
  icon,
3941
+ id,
3458
3942
  name,
3459
3943
  posInSet,
3460
3944
  publisher,
3461
- setSize
3945
+ setSize,
3946
+ status
3462
3947
  } = extension;
3948
+ const actionsDom = getExtensionActionsVirtualDom(id, builtin, disabled, status);
3463
3949
  const dom = [{
3464
3950
  ariaPosInSet: posInSet,
3465
3951
  ariaRoleDescription: Extension,
@@ -3475,11 +3961,7 @@ const getExtensionListItemVirtualDom = extension => {
3475
3961
  role: None,
3476
3962
  src: icon,
3477
3963
  type: Img
3478
- }, listItemDetail, listItemName, text(name), listItemDescription, text(description), listItemFooter, listItemAuthorName, text(publisher), {
3479
- childCount: 0,
3480
- className: ExtensionActions,
3481
- type: Div
3482
- }];
3964
+ }, listItemDetail, listItemName, text(name), listItemDescription, text(description), listItemFooter, listItemAuthorName, text(publisher), ...actionsDom];
3483
3965
  return dom;
3484
3966
  };
3485
3967
 
@@ -3498,7 +3980,7 @@ const getExtensionsListVirtualDom = (visibleExtensions, focusOutline) => {
3498
3980
  onTouchMove: HandleTouchMove,
3499
3981
  onTouchStart: HandleTouchStart,
3500
3982
  onWheel: HandleWheel,
3501
- role: List,
3983
+ role: List$1,
3502
3984
  tabIndex: 0,
3503
3985
  type: Div
3504
3986
  }, ...visibleExtensions.flatMap(getExtensionListItemVirtualDom)];
@@ -3540,14 +4022,19 @@ const getScrollBarVirtualDom = (scrollBarHeight, scrollBarTop) => {
3540
4022
  const getVisibleItem = (item, setSize, itemHeight, minLineY, relative, i, focusedIndex) => {
3541
4023
  // TODO use normal parameters
3542
4024
  const {
4025
+ builtin,
3543
4026
  description,
4027
+ disabled,
3544
4028
  icon,
3545
4029
  id,
3546
4030
  name,
3547
- publisher
4031
+ publisher,
4032
+ status
3548
4033
  } = item;
3549
4034
  return {
4035
+ builtin,
3550
4036
  description,
4037
+ disabled,
3551
4038
  focused: i === focusedIndex,
3552
4039
  icon,
3553
4040
  id,
@@ -3556,6 +4043,7 @@ const getVisibleItem = (item, setSize, itemHeight, minLineY, relative, i, focuse
3556
4043
  posInSet: i + 1,
3557
4044
  publisher,
3558
4045
  setSize,
4046
+ status,
3559
4047
  top: (i - minLineY) * itemHeight - relative
3560
4048
  };
3561
4049
  };
@@ -3585,19 +4073,22 @@ const getContentVirtualDom = (visibleExtensions, message, scrollBarHeight, scrol
3585
4073
  }
3586
4074
  return [{
3587
4075
  childCount: 2,
3588
- className: mergeClassNames(Viewlet, List$1),
4076
+ className: mergeClassNames(Viewlet, List),
3589
4077
  type: Div
3590
4078
  }, ...getExtensionsVirtualDom(visibleExtensions, focusOutline), ...getScrollBarVirtualDom(scrollBarHeight)];
3591
4079
  };
3592
4080
  const getExtensionsViewVirtualDom = state => {
3593
4081
  const visibleExtensions = getVisible(state);
3594
4082
  const {
4083
+ completionFocusedIndex,
4084
+ completionItems,
3595
4085
  focusedIndex,
3596
4086
  inputActions,
3597
4087
  message,
3598
4088
  placeholder,
3599
4089
  scrollBarHeight,
3600
- scrollBarY
4090
+ scrollBarY,
4091
+ suggestOpen
3601
4092
  } = state;
3602
4093
  const focusOutline = focusedIndex === -1 && state.focus === List$2;
3603
4094
  return [{
@@ -3607,7 +4098,7 @@ const getExtensionsViewVirtualDom = state => {
3607
4098
  className: mergeClassNames(Viewlet, Extensions),
3608
4099
  role: None$3,
3609
4100
  type: Div
3610
- }, ...getExtensionHeaderVirtualDom(placeholder, inputActions), ...getContentVirtualDom(visibleExtensions, message, scrollBarHeight, scrollBarY, focusOutline)];
4101
+ }, ...getExtensionHeaderVirtualDom(placeholder, inputActions, completionItems, completionFocusedIndex, suggestOpen), ...getContentVirtualDom(visibleExtensions, message, scrollBarHeight, scrollBarY, focusOutline)];
3611
4102
  };
3612
4103
 
3613
4104
  const renderItems2 = newState => {
@@ -3665,6 +4156,66 @@ const renderSearchValue = newState => {
3665
4156
  return [/* method */'Viewlet.setValueByName', newState.uid, Extensions$1, newState.searchValue];
3666
4157
  };
3667
4158
 
4159
+ const titleFilters = [{
4160
+ label: deprecated,
4161
+ value: Deprecated
4162
+ }, {
4163
+ label: installed,
4164
+ value: Installed
4165
+ }, {
4166
+ label: enabled,
4167
+ value: Enabled$1
4168
+ }, {
4169
+ label: disabled,
4170
+ value: Disabled$1
4171
+ }, {
4172
+ label: builtIn,
4173
+ value: Builtin
4174
+ }, {
4175
+ label: updates,
4176
+ value: Outdated
4177
+ }, {
4178
+ label: featured,
4179
+ value: Featured
4180
+ }, {
4181
+ label: mcpServers,
4182
+ value: McpServers
4183
+ }, {
4184
+ label: mostPopular,
4185
+ value: MostPopular
4186
+ }, {
4187
+ label: recentlyPublished,
4188
+ value: RecentlyPublished
4189
+ }, {
4190
+ label: recommended,
4191
+ value: Recommended
4192
+ }, {
4193
+ label: workspaceUnsupported,
4194
+ value: WorkspaceUnsupported
4195
+ }];
4196
+ const getTitleSuffix = searchValue => {
4197
+ if (!searchValue.trim()) {
4198
+ return installed();
4199
+ }
4200
+ const normalizedSearchValue = searchValue.toLowerCase();
4201
+ for (const filter of titleFilters) {
4202
+ if (normalizedSearchValue.includes(filter.value)) {
4203
+ return filter.label();
4204
+ }
4205
+ }
4206
+ return marketplace();
4207
+ };
4208
+ const renderTitle = state => {
4209
+ return `${extensions()}: ${getTitleSuffix(state.searchValue)}`;
4210
+ };
4211
+
4212
+ const renderTitleCommand = newState => {
4213
+ if (newState.parentUid === undefined) {
4214
+ return [];
4215
+ }
4216
+ return ['Viewlet.send', newState.parentUid, 'setTitle', renderTitle(newState)];
4217
+ };
4218
+
3668
4219
  const getRenderer = diffType => {
3669
4220
  switch (diffType) {
3670
4221
  case RenderCss:
@@ -3685,6 +4236,8 @@ const getRenderer = diffType => {
3685
4236
  return renderScrollBar;
3686
4237
  case RenderSearchValue:
3687
4238
  return renderSearchValue;
4239
+ case RenderTitle:
4240
+ return renderTitleCommand;
3688
4241
  default:
3689
4242
  throw new Error('unknown renderer');
3690
4243
  }
@@ -3773,7 +4326,7 @@ const renderEventListeners = () => {
3773
4326
  preventDefault: true
3774
4327
  }, {
3775
4328
  name: HandlePointerDown,
3776
- params: ['handleClickAt', Button$1, ClientX, ClientY],
4329
+ params: ['handleClickAt', Button$1, ClientX, ClientY, TargetName],
3777
4330
  preventDefault: true
3778
4331
  }, {
3779
4332
  name: HandleScrollBarPointerDown,
@@ -3792,7 +4345,7 @@ const renderEventListeners = () => {
3792
4345
  passive: true
3793
4346
  }, {
3794
4347
  name: HandleExtensionsInput,
3795
- params: ['handleInput', TargetValue, User]
4348
+ params: ['handleInput', TargetValue, User, TargetSelectionStart]
3796
4349
  }, {
3797
4350
  name: HandleClearSearchResults,
3798
4351
  params: ['clearSearchResults']
@@ -3805,6 +4358,24 @@ const renderEventListeners = () => {
3805
4358
  }, {
3806
4359
  name: HandleBlur,
3807
4360
  params: ['handleBlur']
4361
+ }, {
4362
+ name: HandleInstall,
4363
+ params: ['handleInstall', TargetName]
4364
+ }, {
4365
+ name: HandleUninstall,
4366
+ params: ['handleUninstall', TargetName]
4367
+ }, {
4368
+ name: HandleEnable,
4369
+ params: ['handleEnable', TargetName]
4370
+ }, {
4371
+ name: HandleDisable,
4372
+ params: ['handleDisable', TargetName]
4373
+ }, {
4374
+ name: HandleInputFocus,
4375
+ params: ['handleInputFocus']
4376
+ }, {
4377
+ name: HandleInputBlur,
4378
+ params: ['handleBlur']
3808
4379
  }];
3809
4380
  };
3810
4381
 
@@ -3875,26 +4446,44 @@ const selectIndex = (state, index) => {
3875
4446
  };
3876
4447
  };
3877
4448
 
3878
- const toggleSuggest = state => {
4449
+ const selectNextCompletion = state => {
4450
+ if (!state.suggestOpen || state.completionItems.length === 0) {
4451
+ return state;
4452
+ }
4453
+ return {
4454
+ ...state,
4455
+ completionFocusedIndex: (state.completionFocusedIndex + 1) % state.completionItems.length
4456
+ };
4457
+ };
4458
+
4459
+ const selectPreviousCompletion = state => {
4460
+ if (!state.suggestOpen || state.completionItems.length === 0) {
4461
+ return state;
4462
+ }
3879
4463
  return {
3880
4464
  ...state,
3881
- suggestOpen: !state.suggestOpen
4465
+ completionFocusedIndex: (state.completionFocusedIndex - 1 + state.completionItems.length) % state.completionItems.length
3882
4466
  };
3883
4467
  };
3884
4468
 
4469
+ const toggleSuggest = state => {
4470
+ return state.suggestOpen ? closeSuggest(state) : openSuggest(state);
4471
+ };
4472
+
3885
4473
  const commandMap = {
3886
4474
  'Extensions.copyExtensionId': wrapCommand(copyExtensionId),
3887
4475
  'Extensions.copyExtensionInfo': wrapCommand(copyExtensionInfo),
4476
+ 'SearchExtensions.acceptCompletion': wrapCommand(acceptCompletion),
3888
4477
  'SearchExtensions.clearSearchResults': wrapCommand(clearSearchResults),
3889
4478
  'SearchExtensions.closeSuggest': wrapCommand(closeSuggest),
3890
4479
  'SearchExtensions.copyExtensionId': wrapCommand(copyExtensionId),
3891
4480
  'SearchExtensions.copyExtensionInfo': wrapCommand(copyExtensionInfo),
3892
4481
  'SearchExtensions.create': create,
3893
4482
  'SearchExtensions.diff2': diff2,
3894
- 'SearchExtensions.disable': wrapCommand(disable),
4483
+ 'SearchExtensions.disable': wrapCommand(disable$1),
3895
4484
  'SearchExtensions.disableWorkspace': wrapCommand(disableWorkspace),
3896
4485
  'SearchExtensions.dispose': dispose,
3897
- 'SearchExtensions.enable': wrapCommand(enable),
4486
+ 'SearchExtensions.enable': wrapCommand(enable$1),
3898
4487
  'SearchExtensions.enableWorkspace': wrapCommand(enableWorkspace),
3899
4488
  'SearchExtensions.focusFirst': wrapCommand(focusFirst),
3900
4489
  'SearchExtensions.focusIndex': wrapCommand(focusIndex),
@@ -3924,6 +4513,7 @@ const commandMap = {
3924
4513
  'SearchExtensions.handleFocus': wrapCommand(handleFocus),
3925
4514
  'SearchExtensions.handleHeaderContextMenu': wrapCommand(handleHeaderContextMenu),
3926
4515
  'SearchExtensions.handleInput': wrapCommand(handleInput),
4516
+ 'SearchExtensions.handleInputFocus': wrapCommand(handleInputFocus),
3927
4517
  'SearchExtensions.handleInstall': wrapCommand(handleInstall),
3928
4518
  'SearchExtensions.handleScrollBarCaptureLost': wrapCommand(handleScrollBarCaptureLost),
3929
4519
  'SearchExtensions.handleScrollBarClick': wrapCommand(handleScrollBarClick),
@@ -3945,7 +4535,10 @@ const commandMap = {
3945
4535
  'SearchExtensions.scrollDown': wrapCommand(scrollDown),
3946
4536
  'SearchExtensions.searchExtensions': searchExtensions,
3947
4537
  'SearchExtensions.selectIndex': wrapCommand(selectIndex),
4538
+ 'SearchExtensions.selectNextCompletion': wrapCommand(selectNextCompletion),
4539
+ 'SearchExtensions.selectPreviousCompletion': wrapCommand(selectPreviousCompletion),
3948
4540
  'SearchExtensions.setDeltaY': wrapCommand(setDeltaY),
4541
+ 'SearchExtensions.setExtensionStatus': wrapCommand(setExtensionStatus),
3949
4542
  'SearchExtensions.terminate': terminate,
3950
4543
  'SearchExtensions.toggleSuggest': wrapCommand(toggleSuggest)
3951
4544
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lvce-editor/extension-search-view",
3
- "version": "7.7.0",
3
+ "version": "7.8.0",
4
4
  "description": "Extension Search View Worker",
5
5
  "repository": {
6
6
  "type": "git",