minecodex 0.1.19 → 0.1.20

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.
@@ -22,6 +22,13 @@ distributed under MineCodex's MIT License.
22
22
  (`icons/xiaomi.svg`), licensed under CC0 1.0. The Xiaomi brand mark remains
23
23
  the property of Xiaomi Corporation.
24
24
 
25
+ ## Meta logo (provider mark)
26
+
27
+ `assets/providers/muse.svg` is the official Meta Platforms logo rendered in the
28
+ same 24×24 provider-mark style (Lobe Icons) as the other provider icons in this
29
+ folder. The Meta mark remains the property of Meta Platforms, Inc.; the SVG
30
+ wrapper is distributed under MineCodex's MIT License.
31
+
25
32
  ## Lucide
26
33
 
27
34
  Lucide icons distributed by MineCodex include the Model Slider UI icons, Notes action and
@@ -0,0 +1 @@
1
+ <svg height="1em" style="flex:none;line-height:1" viewBox="0 0 24 24" width="1em" xmlns="http://www.w3.org/2000/svg"><title>Meta</title><path d="M6.897 4h-.024l-.031 2.615h.022c1.715 0 3.046 1.357 5.94 6.246l.175.297.012.02 1.62-2.438-.012-.019a48.763 48.763 0 00-1.098-1.716 28.01 28.01 0 00-1.175-1.629C10.413 4.932 8.812 4 6.896 4z" fill="url(#lobe-icons-meta-0-_R_0_)"></path><path d="M6.873 4C4.95 4.01 3.247 5.258 2.02 7.17a4.352 4.352 0 00-.01.017l2.254 1.231.011-.017c.718-1.083 1.61-1.774 2.568-1.785h.021L6.896 4h-.023z" fill="url(#lobe-icons-meta-1-_R_0_)"></path><path d="M2.019 7.17l-.011.017C1.2 8.447.598 9.995.274 11.664l-.005.022 2.534.6.004-.022c.27-1.467.786-2.828 1.456-3.845l.011-.017L2.02 7.17z" fill="url(#lobe-icons-meta-2-_R_0_)"></path><path d="M2.807 12.264l-2.533-.6-.005.022c-.177.918-.267 1.851-.269 2.786v.023l2.598.233v-.023a12.591 12.591 0 01.21-2.44z" fill="url(#lobe-icons-meta-3-_R_0_)"></path><path d="M2.677 15.537a5.462 5.462 0 01-.079-.813v-.022L0 14.468v.024a8.89 8.89 0 00.146 1.652l2.535-.585a4.106 4.106 0 01-.004-.022z" fill="url(#lobe-icons-meta-4-_R_0_)"></path><path d="M3.27 16.89c-.284-.31-.484-.756-.589-1.328l-.004-.021-2.535.585.004.021c.192 1.01.568 1.85 1.106 2.487l.014.017 2.018-1.745a2.106 2.106 0 01-.015-.016z" fill="url(#lobe-icons-meta-5-_R_0_)"></path><path d="M10.78 9.654c-1.528 2.35-2.454 3.825-2.454 3.825-2.035 3.2-2.739 3.917-3.871 3.917a1.545 1.545 0 01-1.186-.508l-2.017 1.744.014.017C2.01 19.518 3.058 20 4.356 20c1.963 0 3.374-.928 5.884-5.33l1.766-3.13a41.283 41.283 0 00-1.227-1.886z" fill="#0082FB"></path><path d="M13.502 5.946l-.016.016c-.4.43-.786.908-1.16 1.416.378.483.768 1.024 1.175 1.63.48-.743.928-1.345 1.367-1.807l.016-.016-1.382-1.24z" fill="url(#lobe-icons-meta-6-_R_0_)"></path><path d="M20.918 5.713C19.853 4.633 18.583 4 17.225 4c-1.432 0-2.637.787-3.723 1.944l-.016.016 1.382 1.24.016-.017c.715-.747 1.408-1.12 2.176-1.12.826 0 1.6.39 2.27 1.075l.015.016 1.589-1.425-.016-.016z" fill="#0082FB"></path><path d="M23.998 14.125c-.06-3.467-1.27-6.566-3.064-8.396l-.016-.016-1.588 1.424.015.016c1.35 1.392 2.277 3.98 2.361 6.971v.023h2.292v-.022z" fill="url(#lobe-icons-meta-7-_R_0_)"></path><path d="M23.998 14.15v-.023h-2.292v.022c.004.14.006.282.006.424 0 .815-.121 1.474-.368 1.95l-.011.022 1.708 1.782.013-.02c.62-.96.946-2.293.946-3.91 0-.083 0-.165-.002-.247z" fill="url(#lobe-icons-meta-8-_R_0_)"></path><path d="M21.344 16.52l-.011.02c-.214.402-.519.67-.917.787l.778 2.462a3.493 3.493 0 00.438-.182 3.558 3.558 0 001.366-1.218l.044-.065.012-.02-1.71-1.784z" fill="url(#lobe-icons-meta-9-_R_0_)"></path><path d="M19.92 17.393c-.262 0-.492-.039-.718-.14l-.798 2.522c.449.153.927.222 1.46.222.492 0 .943-.073 1.352-.215l-.78-2.462c-.167.05-.341.075-.517.073z" fill="url(#lobe-icons-meta-10-_R_0_)"></path><path d="M18.323 16.534l-.014-.017-1.836 1.914.016.017c.637.682 1.246 1.105 1.937 1.337l.797-2.52c-.291-.125-.573-.353-.9-.731z" fill="url(#lobe-icons-meta-11-_R_0_)"></path><path d="M18.309 16.515c-.55-.642-1.232-1.712-2.303-3.44l-1.396-2.336-.011-.02-1.62 2.438.012.02.989 1.668c.959 1.61 1.74 2.774 2.493 3.585l.016.016 1.834-1.914a2.353 2.353 0 01-.014-.017z" fill="url(#lobe-icons-meta-12-_R_0_)"></path><defs><linearGradient id="lobe-icons-meta-0-_R_0_" x1="75.897%" x2="26.312%" y1="89.199%" y2="12.194%"><stop offset=".06%" stop-color="#0867DF"></stop><stop offset="45.39%" stop-color="#0668E1"></stop><stop offset="85.91%" stop-color="#0064E0"></stop></linearGradient><linearGradient id="lobe-icons-meta-1-_R_0_" x1="21.67%" x2="97.068%" y1="75.874%" y2="23.985%"><stop offset="13.23%" stop-color="#0064DF"></stop><stop offset="99.88%" stop-color="#0064E0"></stop></linearGradient><linearGradient id="lobe-icons-meta-2-_R_0_" x1="38.263%" x2="60.895%" y1="89.127%" y2="16.131%"><stop offset="1.47%" stop-color="#0072EC"></stop><stop offset="68.81%" stop-color="#0064DF"></stop></linearGradient><linearGradient id="lobe-icons-meta-3-_R_0_" x1="47.032%" x2="52.15%" y1="90.19%" y2="15.745%"><stop offset="7.31%" stop-color="#007CF6"></stop><stop offset="99.43%" stop-color="#0072EC"></stop></linearGradient><linearGradient id="lobe-icons-meta-4-_R_0_" x1="52.155%" x2="47.591%" y1="58.301%" y2="37.004%"><stop offset="7.31%" stop-color="#007FF9"></stop><stop offset="100%" stop-color="#007CF6"></stop></linearGradient><linearGradient id="lobe-icons-meta-5-_R_0_" x1="37.689%" x2="61.961%" y1="12.502%" y2="63.624%"><stop offset="7.31%" stop-color="#007FF9"></stop><stop offset="100%" stop-color="#0082FB"></stop></linearGradient><linearGradient id="lobe-icons-meta-6-_R_0_" x1="34.808%" x2="62.313%" y1="68.859%" y2="23.174%"><stop offset="27.99%" stop-color="#007FF8"></stop><stop offset="91.41%" stop-color="#0082FB"></stop></linearGradient><linearGradient id="lobe-icons-meta-7-_R_0_" x1="43.762%" x2="57.602%" y1="6.235%" y2="98.514%"><stop offset="0%" stop-color="#0082FB"></stop><stop offset="99.95%" stop-color="#0081FA"></stop></linearGradient><linearGradient id="lobe-icons-meta-8-_R_0_" x1="60.055%" x2="39.88%" y1="4.661%" y2="69.077%"><stop offset="6.19%" stop-color="#0081FA"></stop><stop offset="100%" stop-color="#0080F9"></stop></linearGradient><linearGradient id="lobe-icons-meta-9-_R_0_" x1="30.282%" x2="61.081%" y1="59.32%" y2="33.244%"><stop offset="0%" stop-color="#027AF3"></stop><stop offset="100%" stop-color="#0080F9"></stop></linearGradient><linearGradient id="lobe-icons-meta-10-_R_0_" x1="20.433%" x2="82.112%" y1="50.001%" y2="50.001%"><stop offset="0%" stop-color="#0377EF"></stop><stop offset="99.94%" stop-color="#0279F1"></stop></linearGradient><linearGradient id="lobe-icons-meta-11-_R_0_" x1="40.303%" x2="72.394%" y1="35.298%" y2="57.811%"><stop offset=".19%" stop-color="#0471E9"></stop><stop offset="100%" stop-color="#0377EF"></stop></linearGradient><linearGradient id="lobe-icons-meta-12-_R_0_" x1="32.254%" x2="68.003%" y1="19.719%" y2="84.908%"><stop offset="27.65%" stop-color="#0867DF"></stop><stop offset="100%" stop-color="#0471E9"></stop></linearGradient></defs></svg>
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
3
  "id": "model-slider",
4
- "version": "0.1.11",
4
+ "version": "0.1.12",
5
5
  "label": {
6
6
  "en": "Model Slider",
7
7
  "zh-CN": "模型滑条"
@@ -22,6 +22,7 @@
22
22
  "xai": "xAI",
23
23
  "zhipu": "Zhipu AI",
24
24
  "google": "Google",
25
+ "meta": "Meta",
25
26
  "anthropic": "Anthropic",
26
27
  "openai": "OpenAI"
27
28
  },
@@ -50,6 +51,7 @@
50
51
  { "id": "minimax", "keywords": ["minimax"], "icon": { "resource": "assets/providers/minimax.svg" } },
51
52
  { "id": "qwen", "keywords": ["qwen", "qwq"], "icon": { "resource": "assets/providers/qwen.svg" } },
52
53
  { "id": "hunyuan", "keywords": ["hunyuan"], "icon": { "resource": "assets/providers/hunyuan.svg" } },
54
+ { "id": "muse", "keywords": ["muse", "muse-spark"], "icon": { "resource": "assets/providers/muse.svg" } },
53
55
  { "id": "zhipu", "keywords": ["zhipu", "chatglm", "glm"], "icon": { "resource": "assets/providers/zhipu.svg" } },
54
56
  { "id": "openai", "keywords": ["openai", "gpt", "codex", "o1", "o3", "o4"], "icon": { "resource": "assets/providers/openai.svg" } }
55
57
  ]
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "minecodex",
3
- "version": "0.1.19",
3
+ "version": "0.1.20",
4
4
  "description": "Lightweight, local-first plugins for the Codex desktop app.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -300,6 +300,10 @@ export function createInjectionSource(features, {
300
300
  let modelSelectorNativeFastIcons = null;
301
301
  // Fast 图标来源标记:bundle 静态提取 vs DOM 克隆,DOM 克隆优先以保持像素一致。
302
302
  let modelSelectorNativeFastIconSources = null;
303
+ // DOM 克隆可见性门控:仅在 Fast 控件从无到有时扫描一次,常驻会话不逐帧扫描。
304
+ let modelSelectorFastControlVisible = false;
305
+ // 持久化脏标记:仅在图标实际变化时写一次 localStorage。
306
+ let modelSelectorNativeFastIconsDirty = false;
303
307
  const modelSelectorStyle = document.createElement("style");
304
308
  modelSelectorStyle.setAttribute("data-codex-model-slider-style", "");
305
309
  modelSelectorStyle.textContent = `
@@ -665,13 +669,14 @@ export function createInjectionSource(features, {
665
669
  const modelSelectorFastIconStorageKey = "codex-model-slider:fast-icons:v1";
666
670
 
667
671
  function persistNativeFastIcons() {
668
- if (!modelSelectorNativeFastIcons) return;
672
+ if (!modelSelectorNativeFastIcons || !modelSelectorNativeFastIconsDirty) return;
669
673
  try {
670
674
  const payload = {};
671
675
  for (const [state, template] of Object.entries(modelSelectorNativeFastIcons)) {
672
676
  payload[state] = template.outerHTML;
673
677
  }
674
678
  localStorage.setItem(modelSelectorFastIconStorageKey, JSON.stringify(payload));
679
+ modelSelectorNativeFastIconsDirty = false;
675
680
  } catch {
676
681
  // localStorage 不可用时静默降级,仅本次会话内生效。
677
682
  }
@@ -701,6 +706,8 @@ export function createInjectionSource(features, {
701
706
  }
702
707
 
703
708
  async function loadNativeFastIconFromBundle() {
709
+ // 两个图标均已就绪(持久化或 DOM 克隆)时不再拉取整包 app-initial 资源。
710
+ if (modelSelectorNativeFastIcons?.active && modelSelectorNativeFastIcons?.inactive) return;
704
711
  const sourceLink = document.querySelector('link[href*="/assets/app-initial-"][href$=".js"]');
705
712
  if (!sourceLink?.href) return;
706
713
  try {
@@ -728,6 +735,7 @@ export function createInjectionSource(features, {
728
735
  define("active", "M11\\.9125 21\\.4125", { viewBox: "0 0 24 24" });
729
736
  define("inactive", "M7\\.38 16\\.2207", { viewBox: "0 0 20 20", transform: "translate(2.43 1.609)" });
730
737
  if (gained) {
738
+ modelSelectorNativeFastIconsDirty = true;
731
739
  persistNativeFastIcons();
732
740
  applyNativeFastIconsToShells();
733
741
  queueEnsure();
@@ -747,32 +755,36 @@ export function createInjectionSource(features, {
747
755
 
748
756
  function captureNativeFastIcon() {
749
757
  // Fast 图标只在 Fast 控件渲染后才出现在 DOM(打开菜单或 GPT 模型);
750
- // 启动阶段已有 bundle/持久化兜底,因此无可见 Fast 控件时不做全页扫描。
751
- if (!hasVisibleFastControl()) {
752
- return modelSelectorNativeFastIcons;
753
- }
754
- const capture = (state, pathPrefix) => {
755
- const current = modelSelectorNativeFastIcons?.[state];
756
- const currentSource = modelSelectorNativeFastIconSources?.[state];
757
- if (current && currentSource === "dom") return;
758
- const path = Array.from(document.querySelectorAll("svg path")).find(
759
- (candidate) => candidate.getAttribute("d")?.startsWith(pathPrefix),
760
- );
761
- const svg = path?.closest("svg");
762
- if (!svg) return;
763
- const template = svg.cloneNode(true);
764
- template.removeAttribute("id");
765
- template.removeAttribute("width");
766
- template.removeAttribute("height");
767
- if (!modelSelectorNativeFastIcons) {
768
- modelSelectorNativeFastIcons = {};
769
- modelSelectorNativeFastIconSources = {};
770
- }
771
- modelSelectorNativeFastIcons[state] = template;
772
- modelSelectorNativeFastIconSources[state] = "dom";
773
- };
774
- capture("active", "M11.9125 21.4125");
775
- capture("inactive", "M7.38 16.2207");
758
+ // 只在控件可见性从无到有时做一次全页扫描(升级为 DOM 克隆),
759
+ // 常驻会话不逐帧扫描整个文档;缺图标时由 bundle/持久化兜底。
760
+ const visible = hasVisibleFastControl();
761
+ const justBecameVisible = visible && !modelSelectorFastControlVisible;
762
+ modelSelectorFastControlVisible = visible;
763
+ if (visible && justBecameVisible) {
764
+ const capture = (state, pathPrefix) => {
765
+ const current = modelSelectorNativeFastIcons?.[state];
766
+ const currentSource = modelSelectorNativeFastIconSources?.[state];
767
+ if (current && currentSource === "dom") return;
768
+ const path = Array.from(document.querySelectorAll("svg path")).find(
769
+ (candidate) => candidate.getAttribute("d")?.startsWith(pathPrefix),
770
+ );
771
+ const svg = path?.closest("svg");
772
+ if (!svg) return;
773
+ const template = svg.cloneNode(true);
774
+ template.removeAttribute("id");
775
+ template.removeAttribute("width");
776
+ template.removeAttribute("height");
777
+ if (!modelSelectorNativeFastIcons) {
778
+ modelSelectorNativeFastIcons = {};
779
+ modelSelectorNativeFastIconSources = {};
780
+ }
781
+ modelSelectorNativeFastIcons[state] = template;
782
+ modelSelectorNativeFastIconSources[state] = "dom";
783
+ modelSelectorNativeFastIconsDirty = true;
784
+ };
785
+ capture("active", "M11.9125 21.4125");
786
+ capture("inactive", "M7.38 16.2207");
787
+ }
776
788
  const ready = Boolean(
777
789
  modelSelectorNativeFastIcons?.active && modelSelectorNativeFastIcons?.inactive,
778
790
  );
@@ -785,14 +797,18 @@ export function createInjectionSource(features, {
785
797
 
786
798
  function applyNativeFastIconsToShells() {
787
799
  document.querySelectorAll("[data-codex-model-slider-fast]").forEach((button) => {
788
- const icon = createNativeFastIcon(button.getAttribute("aria-pressed") === "true");
789
800
  const content = button.querySelector("[data-codex-model-slider-fast-content]");
790
- if (icon && content) content.replaceChildren(icon);
801
+ // 幂等补装:只给还没有图标的按钮补上,避免每次 ensure 都重建节点。
802
+ if (!content || content.querySelector("svg")) return;
803
+ const icon = createNativeFastIcon(button.getAttribute("aria-pressed") === "true");
804
+ if (icon) content.replaceChildren(icon);
791
805
  });
792
806
  }
793
807
 
794
808
  function createNativeFastIcon(active) {
795
- const template = captureNativeFastIcon()?.[active ? "active" : "inactive"];
809
+ // 直接读取已就绪的图标存储(启动时由 bundle/持久化填充,运行期由
810
+ // captureNativeFastIcon 升级为 DOM 克隆),避免再次触发捕获造成递归。
811
+ const template = modelSelectorNativeFastIcons?.[active ? "active" : "inactive"];
796
812
  if (!template) return null;
797
813
  const icon = template.cloneNode(true);
798
814
  icon.setAttribute("aria-hidden", "true");
@@ -1362,18 +1378,19 @@ export function createInjectionSource(features, {
1362
1378
  }
1363
1379
 
1364
1380
  function enhanceModelItem(item, menu, selector, index) {
1365
- if (item.querySelector("[data-codex-model-slider-row]")) return;
1366
1381
  const observedRaw = modelItemRawValue(item);
1367
1382
  if (!observedRaw) return;
1368
- if (!modelSelectorOriginalItems.has(item)) modelSelectorOriginalItems.set(item, item.innerHTML);
1369
1383
  const observedIdentity = modelIdentity(observedRaw);
1370
1384
  const nativeDescriptor = nativeModelDescriptorForItem(item, observedRaw);
1371
1385
  const catalogModel = catalogModelFor(observedIdentity, selector);
1372
1386
  const raw = catalogModel?.slug ?? nativeDescriptor?.slug ?? observedRaw;
1387
+ // 先刷新 dataset:React 原地复用菜单节点时,raw/排序/收藏键不能基于过期值。
1373
1388
  item.dataset.codexModelSliderRaw = raw;
1374
1389
  item.dataset.codexModelSliderItem = "";
1375
1390
  item.dataset.codexModelSliderOrder = String(index);
1376
1391
  item.dataset.codexModelSliderIdentitySource = catalogModel ? "catalog" : nativeDescriptor ? "native" : "visible";
1392
+ if (item.querySelector("[data-codex-model-slider-row]")) return;
1393
+ if (!modelSelectorOriginalItems.has(item)) modelSelectorOriginalItems.set(item, item.innerHTML);
1377
1394
 
1378
1395
  const identity = modelIdentity(raw);
1379
1396
  const display = modelDisplayLabel(identity, selector);
@@ -2077,7 +2094,6 @@ export function createInjectionSource(features, {
2077
2094
  function ensureModelSelector() {
2078
2095
  const selector = modelSelectorFeature?.modelSelector;
2079
2096
  if (!selector) return;
2080
- captureNativeFastIcon();
2081
2097
  pruneModelSubmenuPositionObservers();
2082
2098
  if (!modelSelectorStyle.isConnected) document.head?.append(modelSelectorStyle);
2083
2099
  enhanceComposerModelTrigger(selector);
@@ -2089,11 +2105,17 @@ export function createInjectionSource(features, {
2089
2105
  returnToNativeModelSlider();
2090
2106
  }, 80);
2091
2107
  }
2092
- return;
2108
+ } else {
2109
+ enhanceNativeModelPicker(parentMenu, selector);
2110
+ const submenu = nativeModelSubmenu(parentMenu);
2111
+ if (submenu) enhanceNativeModelSubmenu(submenu, selector);
2112
+ }
2113
+ try {
2114
+ // 图标工作与菜单增强解耦:放在最后并隔离异常,任何失败都不影响标签与菜单。
2115
+ captureNativeFastIcon();
2116
+ } catch (error) {
2117
+ console.warn("[codex-personal] fast icon capture failed", error);
2093
2118
  }
2094
- enhanceNativeModelPicker(parentMenu, selector);
2095
- const submenu = nativeModelSubmenu(parentMenu);
2096
- if (submenu) enhanceNativeModelSubmenu(submenu, selector);
2097
2119
  }
2098
2120
 
2099
2121
  function restoreModelSelectorEnhancements() {
@@ -2399,16 +2421,23 @@ export function createInjectionSource(features, {
2399
2421
  ]);
2400
2422
  for (const element of selected) {
2401
2423
  if (element.hasAttribute(entryMarker) || alreadySuppressed.has(element)) continue;
2402
- suppressedSelections.push({
2424
+ const selection = {
2403
2425
  element,
2404
2426
  ariaCurrent: element.getAttribute("aria-current"),
2405
2427
  threadSelected: element.getAttribute("data-app-action-sidebar-thread-selected"),
2428
+ hadPrimaryGhost: element.classList.contains("bg-primary-ghost-hover"),
2429
+ hadHoverPrimaryGhost: element.classList.contains("hover:bg-primary-ghost-hover"),
2406
2430
  hadActiveClass: element.classList.contains("bg-token-list-hover-background"),
2407
2431
  hadHoverClass: element.classList.contains("hover:bg-token-list-hover-background"),
2408
- });
2432
+ };
2433
+ suppressedSelections.push(selection);
2409
2434
  element.removeAttribute("aria-current");
2410
2435
  element.removeAttribute("data-app-action-sidebar-thread-selected");
2436
+ // 原生选中态(灰底)现在由 bg-primary-ghost-hover 承载,需一并移除;
2437
+ // 旧 token 类仍保留处理,以便兼容旧主题。
2438
+ element.classList.remove("bg-primary-ghost-hover");
2411
2439
  element.classList.remove("bg-token-list-hover-background");
2440
+ if (!selection.hadHoverPrimaryGhost) element.classList.add("hover:bg-primary-ghost-hover");
2412
2441
  element.classList.add("hover:bg-token-list-hover-background");
2413
2442
  }
2414
2443
  }
@@ -2421,6 +2450,8 @@ export function createInjectionSource(features, {
2421
2450
  if (selection.threadSelected !== null) {
2422
2451
  element.setAttribute("data-app-action-sidebar-thread-selected", selection.threadSelected);
2423
2452
  }
2453
+ element.classList.toggle("bg-primary-ghost-hover", Boolean(selection.hadPrimaryGhost));
2454
+ element.classList.toggle("hover:bg-primary-ghost-hover", Boolean(selection.hadHoverPrimaryGhost));
2424
2455
  element.classList.toggle("bg-token-list-hover-background", selection.hadActiveClass);
2425
2456
  element.classList.toggle("hover:bg-token-list-hover-background", selection.hadHoverClass);
2426
2457
  }
@@ -2432,6 +2463,7 @@ export function createInjectionSource(features, {
2432
2463
  const entry = findEntry(feature.id);
2433
2464
  if (!entry) continue;
2434
2465
  const selected = feature.id === activePageFeatureId;
2466
+ entry.classList.toggle("bg-primary-ghost-hover", selected);
2435
2467
  entry.classList.toggle("bg-token-list-hover-background", selected);
2436
2468
  entry.classList.toggle("hover:bg-token-list-hover-background", !selected);
2437
2469
  if (selected) entry.setAttribute("aria-current", "page");