minecodex 2.0.49 → 2.0.50
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.
|
@@ -18,6 +18,7 @@ export function installModelSlider(signal, { feature, ui, createIcon, requestRef
|
|
|
18
18
|
const modelSelectorNativeToggleHandlers = new Map();
|
|
19
19
|
const modelSelectorPositionObservers = new Map();
|
|
20
20
|
const modelSelectorMenuSizeFrames = new Map();
|
|
21
|
+
const modelSelectorOpeningFrames = new Map();
|
|
21
22
|
let modelSelectorReturnTimer = null;
|
|
22
23
|
let modelSelectorPendingReturn = false;
|
|
23
24
|
let modelSelectorEffortTransactionTimer = null;
|
|
@@ -91,6 +92,16 @@ export function installModelSlider(signal, { feature, ui, createIcon, requestRef
|
|
|
91
92
|
[data-codex-model-slider-trigger][data-codex-model-slider-trigger-placeholder] [class*="_ModelPickerTriggerContent_"] {
|
|
92
93
|
width: 160px; min-width: 160px !important; max-width: 160px;
|
|
93
94
|
}
|
|
95
|
+
/* 打开时先完成占位态,避免原生 crossfade 的宽度动画带动弹层。 */
|
|
96
|
+
[data-codex-model-slider-trigger][data-state="open"][data-codex-model-slider-trigger-placeholder] [class*="_ModelPickerTriggerContent_"] > span:has(> span > [class*="_ModelPickerTriggerPlaceholder_"]) {
|
|
97
|
+
width: 160px !important;
|
|
98
|
+
}
|
|
99
|
+
[data-codex-model-slider-trigger][data-state="open"][data-codex-model-slider-trigger-placeholder] span:has(> [class*="_ModelPickerTriggerPlaceholder_"]) {
|
|
100
|
+
opacity: 1 !important;
|
|
101
|
+
}
|
|
102
|
+
[data-codex-model-slider-trigger][data-state="open"][data-codex-model-slider-trigger-placeholder] [class*="_ModelPickerTriggerLabel_"] {
|
|
103
|
+
visibility: hidden;
|
|
104
|
+
}
|
|
94
105
|
[data-codex-model-slider-trigger] [class*="_ModelPickerTriggerEffortLabel_"] {
|
|
95
106
|
display: inline-flex; align-items: center; align-self: center;
|
|
96
107
|
}
|
|
@@ -126,6 +137,11 @@ export function installModelSlider(signal, { feature, ui, createIcon, requestRef
|
|
|
126
137
|
[data-codex-model-slider-generic-menu] {
|
|
127
138
|
overflow-x: hidden;
|
|
128
139
|
transform: translateX(var(--codex-model-slider-menu-center-shift, 0px)) !important;
|
|
140
|
+
/* 居中修正不能继承原生 transform 过渡,否则定位本身会播放位移。 */
|
|
141
|
+
transition-property: opacity, filter !important;
|
|
142
|
+
}
|
|
143
|
+
html[data-codex-model-slider-catalog-ready] [role="menu"][data-state="open"]:has([data-reasoning-slider]):not([data-codex-model-slider-opening-ready]) {
|
|
144
|
+
visibility: hidden !important;
|
|
129
145
|
}
|
|
130
146
|
[data-codex-model-slider-generic] { box-sizing: border-box; width: 100%; }
|
|
131
147
|
[data-codex-model-slider-fast] { border: 0; background: transparent; cursor: pointer; }
|
|
@@ -991,11 +1007,13 @@ export function installModelSlider(signal, { feature, ui, createIcon, requestRef
|
|
|
991
1007
|
const original = modelSelectorGenericContainers.get(container);
|
|
992
1008
|
if (!original) return;
|
|
993
1009
|
original.effectMirror?.disconnect();
|
|
1010
|
+
original.positionObserver?.disconnect();
|
|
994
1011
|
if (container.isConnected) {
|
|
995
1012
|
const menu = container.parentElement;
|
|
996
1013
|
menu?.querySelector(":scope > [data-codex-model-slider-generic]")?.remove();
|
|
997
1014
|
menu?.removeAttribute("data-codex-model-slider-generic-menu");
|
|
998
1015
|
menu?.style.removeProperty("--codex-model-slider-menu-center-shift");
|
|
1016
|
+
menu?.removeAttribute("data-codex-model-slider-opening-ready");
|
|
999
1017
|
container.style.position = original.position;
|
|
1000
1018
|
container.style.inset = original.inset;
|
|
1001
1019
|
container.style.opacity = original.opacity;
|
|
@@ -1095,11 +1113,10 @@ export function installModelSlider(signal, { feature, ui, createIcon, requestRef
|
|
|
1095
1113
|
if (!record) return false;
|
|
1096
1114
|
if (record.closing && !immediate) return true;
|
|
1097
1115
|
record.reveal?.cancel();
|
|
1098
|
-
const placeholder =
|
|
1099
|
-
|
|
1100
|
-
)
|
|
1101
|
-
|
|
1102
|
-
placeholder.firstChild.nodeValue = record.placeholderText;
|
|
1116
|
+
const placeholder = record.trigger?.querySelector('[class*="_ModelPickerTriggerPlaceholder_"]');
|
|
1117
|
+
const placeholderNode = placeholder && firstVisibleTextNode(placeholder);
|
|
1118
|
+
if (placeholderNode && record.placeholderText != null) {
|
|
1119
|
+
placeholderNode.nodeValue = record.placeholderText;
|
|
1103
1120
|
}
|
|
1104
1121
|
record.button.setAttribute("aria-expanded", "false");
|
|
1105
1122
|
record.closing = true;
|
|
@@ -1279,15 +1296,15 @@ export function installModelSlider(signal, { feature, ui, createIcon, requestRef
|
|
|
1279
1296
|
});
|
|
1280
1297
|
renderEnhancedModelMenu(menu, selector);
|
|
1281
1298
|
|
|
1282
|
-
const
|
|
1283
|
-
|
|
1284
|
-
);
|
|
1285
|
-
const placeholderText =
|
|
1299
|
+
const trigger = nativeComposerTrigger();
|
|
1300
|
+
const placeholder = trigger?.querySelector('[class*="_ModelPickerTriggerPlaceholder_"]');
|
|
1301
|
+
const placeholderNode = placeholder && firstVisibleTextNode(placeholder);
|
|
1302
|
+
const placeholderText = placeholderNode?.nodeValue ?? null;
|
|
1286
1303
|
// 保留产品行为:模型列表打开时 chip 显示 Select model。只能原地更新
|
|
1287
1304
|
// 同一个文本节点(nodeValue),不能 textContent 替换整个节点,否则
|
|
1288
1305
|
// React 卸载菜单时 removeChild 找不到旧文本节点会触发错误边界。
|
|
1289
|
-
if (
|
|
1290
|
-
|
|
1306
|
+
if (placeholderNode) {
|
|
1307
|
+
placeholderNode.nodeValue = locale === "zh-CN" ? "选择模型" : "Select model";
|
|
1291
1308
|
}
|
|
1292
1309
|
|
|
1293
1310
|
modelSelectorControllerMenu = {
|
|
@@ -1295,6 +1312,7 @@ export function installModelSlider(signal, { feature, ui, createIcon, requestRef
|
|
|
1295
1312
|
content,
|
|
1296
1313
|
parentMenu,
|
|
1297
1314
|
button: modelButton,
|
|
1315
|
+
trigger,
|
|
1298
1316
|
placeholderText,
|
|
1299
1317
|
position: parentMenu.style.position,
|
|
1300
1318
|
overflow: parentMenu.style.overflow,
|
|
@@ -2000,11 +2018,42 @@ export function installModelSlider(signal, { feature, ui, createIcon, requestRef
|
|
|
2000
2018
|
const previousShift = Number.parseFloat(
|
|
2001
2019
|
parentMenu.style.getPropertyValue("--codex-model-slider-menu-center-shift"),
|
|
2002
2020
|
) || 0;
|
|
2003
|
-
const
|
|
2004
|
-
const
|
|
2021
|
+
const zoom = parentMenu.currentCSSZoom || 1;
|
|
2022
|
+
const unshiftedCenter = menuRect.left + (menuRect.width / 2) - previousShift * zoom;
|
|
2023
|
+
const nextShift = (triggerRect.left + (triggerRect.width / 2) - unshiftedCenter) / zoom;
|
|
2005
2024
|
parentMenu.style.setProperty("--codex-model-slider-menu-center-shift", `${nextShift}px`);
|
|
2006
2025
|
}
|
|
2007
2026
|
|
|
2027
|
+
function revealCenteredModelPicker(parentMenu) {
|
|
2028
|
+
if (parentMenu.hasAttribute("data-codex-model-slider-opening-ready")) {
|
|
2029
|
+
centerGenericModelPicker(parentMenu);
|
|
2030
|
+
return;
|
|
2031
|
+
}
|
|
2032
|
+
parentMenu.style.visibility = "hidden";
|
|
2033
|
+
if (modelSelectorOpeningFrames.has(parentMenu)) return;
|
|
2034
|
+
let previous = null;
|
|
2035
|
+
const position = () => {
|
|
2036
|
+
modelSelectorOpeningFrames.delete(parentMenu);
|
|
2037
|
+
const trigger = nativeComposerTrigger();
|
|
2038
|
+
if (!parentMenu.isConnected || !trigger || signal.aborted) return;
|
|
2039
|
+
centerGenericModelPicker(parentMenu);
|
|
2040
|
+
const menuRect = parentMenu.getBoundingClientRect();
|
|
2041
|
+
const triggerRect = trigger.getBoundingClientRect();
|
|
2042
|
+
const geometry = [menuRect.left, menuRect.width, triggerRect.left, triggerRect.width];
|
|
2043
|
+
// 等原生 Popper 跟上入口宽度;首次可见的位置必须已经稳定且居中。
|
|
2044
|
+
if (menuRect.width > 0 && triggerRect.width > 0
|
|
2045
|
+
&& Math.abs(menuRect.left + menuRect.width / 2 - triggerRect.left - triggerRect.width / 2) < 1
|
|
2046
|
+
&& previous && geometry.every((value, index) => Math.abs(value - previous[index]) < 0.5)) {
|
|
2047
|
+
parentMenu.setAttribute("data-codex-model-slider-opening-ready", "");
|
|
2048
|
+
parentMenu.style.removeProperty("visibility");
|
|
2049
|
+
return;
|
|
2050
|
+
}
|
|
2051
|
+
previous = geometry;
|
|
2052
|
+
modelSelectorOpeningFrames.set(parentMenu, requestAnimationFrame(position));
|
|
2053
|
+
};
|
|
2054
|
+
modelSelectorOpeningFrames.set(parentMenu, requestAnimationFrame(position));
|
|
2055
|
+
}
|
|
2056
|
+
|
|
2008
2057
|
// ========================================================================
|
|
2009
2058
|
// 通用 picker 增强与恢复 — 菜单/触发器增强、布局居中与恢复降级
|
|
2010
2059
|
// ========================================================================
|
|
@@ -2053,13 +2102,12 @@ export function installModelSlider(signal, { feature, ui, createIcon, requestRef
|
|
|
2053
2102
|
return true;
|
|
2054
2103
|
}
|
|
2055
2104
|
parentMenu.removeAttribute("data-codex-model-slider-template-wait");
|
|
2056
|
-
parentMenu.style.removeProperty("visibility");
|
|
2057
2105
|
const canUpgradeFallback = Boolean(
|
|
2058
2106
|
existing?.querySelector("[data-codex-model-slider-fallback]") && nativeTemplateReady,
|
|
2059
2107
|
);
|
|
2060
2108
|
if (existing?.getAttribute("data-codex-model-slider-structure-key") === structureKey
|
|
2061
2109
|
&& existing.hasAttribute("data-codex-model-slider-fast-transitioning") && !canUpgradeFallback) {
|
|
2062
|
-
|
|
2110
|
+
revealCenteredModelPicker(parentMenu);
|
|
2063
2111
|
return true;
|
|
2064
2112
|
}
|
|
2065
2113
|
const currentFast = existing?.querySelector("[data-codex-model-slider-rail]")?.getAttribute("data-fast-mode");
|
|
@@ -2068,11 +2116,11 @@ export function installModelSlider(signal, { feature, ui, createIcon, requestRef
|
|
|
2068
2116
|
if (existing?.getAttribute("data-codex-model-slider-structure-key") === structureKey
|
|
2069
2117
|
&& currentFast != null && currentFast === nativeFast && !canUpgradeFallback) {
|
|
2070
2118
|
existing.setAttribute("data-codex-model-slider-generic", key);
|
|
2071
|
-
|
|
2119
|
+
revealCenteredModelPicker(parentMenu);
|
|
2072
2120
|
return true;
|
|
2073
2121
|
}
|
|
2074
2122
|
if (existing?.getAttribute("data-codex-model-slider-generic") === key && !canUpgradeFallback) {
|
|
2075
|
-
|
|
2123
|
+
revealCenteredModelPicker(parentMenu);
|
|
2076
2124
|
return true;
|
|
2077
2125
|
}
|
|
2078
2126
|
const nativeContainer = parentMenu.firstElementChild;
|
|
@@ -2090,7 +2138,13 @@ export function installModelSlider(signal, { feature, ui, createIcon, requestRef
|
|
|
2090
2138
|
}
|
|
2091
2139
|
modelSelectorGenericContainers.get(nativeContainer)?.effectMirror?.disconnect();
|
|
2092
2140
|
if (!modelSelectorGenericContainers.has(nativeContainer)) {
|
|
2141
|
+
// Popper 会在后续帧改写 wrapper;同一轮微任务内重新居中,避免露出一帧旧位置。
|
|
2142
|
+
const positionObserver = new MutationObserver(() => centerGenericModelPicker(parentMenu));
|
|
2143
|
+
if (parentMenu.parentElement?.hasAttribute("data-radix-popper-content-wrapper")) {
|
|
2144
|
+
positionObserver.observe(parentMenu.parentElement, { attributes: true, attributeFilter: ["style"] });
|
|
2145
|
+
}
|
|
2093
2146
|
modelSelectorGenericContainers.set(nativeContainer, {
|
|
2147
|
+
positionObserver,
|
|
2094
2148
|
position: nativeContainer.style.position,
|
|
2095
2149
|
inset: nativeContainer.style.inset,
|
|
2096
2150
|
opacity: nativeContainer.style.opacity,
|
|
@@ -2110,12 +2164,14 @@ export function installModelSlider(signal, { feature, ui, createIcon, requestRef
|
|
|
2110
2164
|
shell.setAttribute("data-codex-model-slider-structure-key", structureKey);
|
|
2111
2165
|
replaceModelSliderShell(parentMenu, existing, shell);
|
|
2112
2166
|
modelSelectorGenericContainers.get(nativeContainer).effectMirror = syncClonedPowerEffects(nativeContainer, shell);
|
|
2113
|
-
|
|
2167
|
+
revealCenteredModelPicker(parentMenu);
|
|
2114
2168
|
return true;
|
|
2115
2169
|
}
|
|
2116
2170
|
|
|
2117
2171
|
function enhanceNativeModelPicker(parentMenu, selector) {
|
|
2118
2172
|
if (enhanceGenericModelPicker(parentMenu, selector)) return;
|
|
2173
|
+
parentMenu.setAttribute("data-codex-model-slider-opening-ready", "");
|
|
2174
|
+
parentMenu.style.removeProperty("visibility");
|
|
2119
2175
|
const toggle = parentMenu.querySelector("[data-model-picker-view-toggle]");
|
|
2120
2176
|
if (toggle && typeof nativeComposerModelController()?.onSelectModel === "function") {
|
|
2121
2177
|
// 私有 DOM 无法满足 MCX shell 契约时,保留原生菜单作为降级路径。
|
|
@@ -2171,10 +2227,20 @@ export function installModelSlider(signal, { feature, ui, createIcon, requestRef
|
|
|
2171
2227
|
|
|
2172
2228
|
function enhanceComposerModelTrigger(trigger, selector) {
|
|
2173
2229
|
if (!modelSelectorTriggerObservers.has(trigger)) {
|
|
2174
|
-
const observer = new MutationObserver(
|
|
2175
|
-
|
|
2230
|
+
const observer = new MutationObserver(() => {
|
|
2231
|
+
enhanceComposerModelTrigger(trigger, selector);
|
|
2232
|
+
queueEnsure();
|
|
2233
|
+
});
|
|
2234
|
+
observer.observe(trigger, { childList: true, subtree: true, characterData: true, attributes: true, attributeFilter: ["data-state"] });
|
|
2176
2235
|
modelSelectorTriggerObservers.set(trigger, observer);
|
|
2177
2236
|
}
|
|
2237
|
+
const openPlaceholder = trigger.getAttribute("data-state") === "open"
|
|
2238
|
+
&& trigger.querySelector('[class*="_ModelPickerTriggerPlaceholder_"]');
|
|
2239
|
+
if (openPlaceholder && modelSelectorControllerMenu?.trigger === trigger && !modelSelectorControllerMenu.closing) {
|
|
2240
|
+
const textNode = firstVisibleTextNode(openPlaceholder);
|
|
2241
|
+
const label = locale === "zh-CN" ? "选择模型" : "Select model";
|
|
2242
|
+
if (textNode && textNode.nodeValue !== label) textNode.nodeValue = label;
|
|
2243
|
+
}
|
|
2178
2244
|
const nativeLabels = Array.from(trigger.querySelectorAll(
|
|
2179
2245
|
'[class*="_ModelPickerTriggerModelText_"]:not([data-codex-model-slider-trigger-label])',
|
|
2180
2246
|
));
|
|
@@ -2182,7 +2248,7 @@ export function installModelSlider(signal, { feature, ui, createIcon, requestRef
|
|
|
2182
2248
|
trigger.setAttribute("data-codex-model-slider-trigger", "");
|
|
2183
2249
|
trigger.toggleAttribute(
|
|
2184
2250
|
"data-codex-model-slider-trigger-placeholder",
|
|
2185
|
-
isComposerModelPlaceholder(trigger.innerText),
|
|
2251
|
+
isComposerModelPlaceholder(openPlaceholder?.textContent || trigger.innerText),
|
|
2186
2252
|
);
|
|
2187
2253
|
restoreTriggerLabelWithoutNative(trigger, selector);
|
|
2188
2254
|
return;
|
|
@@ -2199,7 +2265,7 @@ export function installModelSlider(signal, { feature, ui, createIcon, requestRef
|
|
|
2199
2265
|
trigger.setAttribute("data-codex-model-slider-trigger-raw", raw);
|
|
2200
2266
|
// 区分占位态(Select model / Select effort)与真实模型态:占位态沿用
|
|
2201
2267
|
// 原生宽度契约,真实模型态让芯片 HUG 完整名称,避免第三方长名被截断。
|
|
2202
|
-
const placeholder = isComposerModelPlaceholder(label);
|
|
2268
|
+
const placeholder = isComposerModelPlaceholder(openPlaceholder?.textContent || label);
|
|
2203
2269
|
trigger.toggleAttribute("data-codex-model-slider-trigger-placeholder", placeholder);
|
|
2204
2270
|
for (const nativeLabel of nativeLabels) {
|
|
2205
2271
|
let displayLabel = nativeLabel.nextElementSibling;
|
|
@@ -2216,12 +2282,7 @@ export function installModelSlider(signal, { feature, ui, createIcon, requestRef
|
|
|
2216
2282
|
}
|
|
2217
2283
|
if (displayLabel.textContent !== label) displayLabel.textContent = label;
|
|
2218
2284
|
}
|
|
2219
|
-
//
|
|
2220
|
-
// 探针的测量;把探针文本同步为 MCX 显示标签,原生机制即可测得
|
|
2221
|
-
// 真实显示宽度。保留 React 持有的子节点,避免切模型时卸载失败。
|
|
2222
|
-
const measurement = trigger.querySelector('[class*="_ModelPickerTriggerMeasurement_"]');
|
|
2223
|
-
const measurementText = measurement && firstVisibleTextNode(measurement);
|
|
2224
|
-
if (measurementText && measurementText.nodeValue !== label) measurementText.nodeValue = label;
|
|
2285
|
+
// Measurement 属于原生 openLabel,占位宽度不能用真实模型名覆盖。
|
|
2225
2286
|
}
|
|
2226
2287
|
|
|
2227
2288
|
function ensureModelSelector() {
|
|
@@ -2284,6 +2345,11 @@ export function installModelSlider(signal, { feature, ui, createIcon, requestRef
|
|
|
2284
2345
|
modelSelectorPositionObservers.clear();
|
|
2285
2346
|
for (const frame of modelSelectorMenuSizeFrames.values()) cancelAnimationFrame(frame);
|
|
2286
2347
|
modelSelectorMenuSizeFrames.clear();
|
|
2348
|
+
for (const [menu, frame] of modelSelectorOpeningFrames) {
|
|
2349
|
+
cancelAnimationFrame(frame);
|
|
2350
|
+
menu.style.removeProperty("visibility");
|
|
2351
|
+
}
|
|
2352
|
+
modelSelectorOpeningFrames.clear();
|
|
2287
2353
|
modelSelectorReturnTimer = null;
|
|
2288
2354
|
modelSelectorEffortTransactionTimer = null;
|
|
2289
2355
|
modelSelectorPendingOutsideDismiss = false;
|
|
@@ -2318,6 +2384,8 @@ export function installModelSlider(signal, { feature, ui, createIcon, requestRef
|
|
|
2318
2384
|
document.querySelectorAll("[data-codex-model-slider-generic]").forEach((element) => element.remove());
|
|
2319
2385
|
document.querySelectorAll("[data-codex-model-slider-generic-menu]")
|
|
2320
2386
|
.forEach((element) => element.removeAttribute("data-codex-model-slider-generic-menu"));
|
|
2387
|
+
document.querySelectorAll("[data-codex-model-slider-opening-ready]")
|
|
2388
|
+
.forEach((element) => element.removeAttribute("data-codex-model-slider-opening-ready"));
|
|
2321
2389
|
document.querySelectorAll("[data-codex-model-slider-menu]")
|
|
2322
2390
|
.forEach((element) => element.removeAttribute("data-codex-model-slider-menu"));
|
|
2323
2391
|
document.querySelectorAll("[data-codex-model-slider-trigger]").forEach((element) => {
|