minecodex 2.0.40 → 2.0.42
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.
- package/README.md +3 -1
- package/apps/dashboard/assets/preview-content.js +5 -2
- package/features/composer-expand/assets/maximize-2.svg +16 -0
- package/features/composer-expand/codex-feature.json +24 -0
- package/features/composer-expand/src/entry.mjs +1 -0
- package/features/composer-expand/src/injection-source.mjs +7 -0
- package/features/composer-expand/src/install.mjs +91 -0
- package/features/composer-expand/src/native.mjs +79 -0
- package/features/composer-expand/vendor/lucide-LICENSE +15 -0
- package/features/hide-upsell-banner/src/hide-upsell-banner.mjs +2 -0
- package/features/images/codex-feature.json +1 -1
- package/features/images/src/adapters/codex/native-image-modules.mjs +10 -1
- package/features/quick-chat/codex-feature.json +4 -5
- package/features/quick-chat/src/adapters/codex/shortcut.mjs +15 -7
- package/features/quick-chat/src/adapters/codex/sidebar.mjs +35 -0
- package/features/quick-chat/src/frontend/entry.mjs +6 -8
- package/features/quick-chat/src/frontend/sidebar.mjs +63 -0
- package/features/quick-chat/src/injection-source.mjs +6 -5
- package/features/session-status/src/adapters/codex/context-usage.mjs +11 -6
- package/features/sidebar-focus/src/adapters/codex/renderer.mjs +11 -5
- package/features/sidebar-focus/src/sidebar-focus.mjs +5 -3
- package/features/sites/src/adapters/codex/renderer.mjs +1 -1
- package/features/sites/src/frontend/entry.mjs +1 -0
- package/package.json +6 -2
- package/packages/cli/src/config.mjs +3 -2
- package/packages/cli/src/control-server.mjs +1 -1
- package/packages/cli/src/paths.mjs +2 -1
- package/packages/cli/src/platform.mjs +43 -12
- package/packages/codex-adapter/src/markdown/markdown-native.mjs +7 -4
- package/packages/codex-adapter/src/markdown/toc-native.mjs +5 -4
- package/packages/plugin/assets/app.js +2 -2
- package/packages/plugin/assets/prompts.js +1 -1
- package/features/quick-chat/assets/pin.svg +0 -1
- package/features/quick-chat/src/adapters/codex/pin.mjs +0 -29
- package/features/quick-chat/src/adapters/codex/presence.mjs +0 -74
- package/features/quick-chat/src/frontend/exit.mjs +0 -14
- package/features/quick-chat/src/frontend/pin.mjs +0 -54
|
@@ -426,7 +426,7 @@ ${U.body}`.toLocaleLowerCase().includes(y)));if(!k.length){g.append(jn(!!y));ret
|
|
|
426
426
|
font-family:var(--mcx-font-sans-default);font-size:var(--mcx-text-sm);line-height:18px;
|
|
427
427
|
font-weight:var(--mcx-tooltip-compact-font-weight);letter-spacing:var(--mcx-tracking-tooltip);user-select:none; }
|
|
428
428
|
`,document.head.append(o);function r(m){return m.setAttribute("data-mcx-ui-tooltip",""),m}r(i),i.style.cssText=`zoom:var(--codex-window-zoom,1);max-width:min(320px,calc(100vw - 16px));
|
|
429
|
-
text-align:center;overflow-wrap:anywhere;`;let n=null,a,s,c=-1/0;function l(){if(clearTimeout(a),cancelAnimationFrame(s),n){let m=(n.getAttribute("aria-describedby")||"").split(/\s+/).filter(A=>A&&A!==i.id);m.length?n.setAttribute("aria-describedby",m.join(" ")):n.removeAttribute("aria-describedby")}i.hidden||(c=Date.now()),n=null,i.hidden=!0}function d(){if(!n?.isConnected||!n.getClientRects().length||n.getAttribute("aria-expanded")==="true")return l();let m=Number.parseFloat(getComputedStyle(i).zoom)||1,A=n.getBoundingClientRect(),x=i.offsetWidth,C=i.offsetHeight,M=n.getAttribute("data-minecodex-tooltip-side")||(n.closest("[data-app-navigation-rail]")?"right":getComputedStyle(n).getPropertyValue("--side-tooltip").trim()||"top"),T=2/m,Q=(A.left+A.width/2)/m-x/2,re=M==="bottom"?A.bottom/m+T:A.top/m-C-T;M==="right"||M==="left"?(Q=M==="right"?A.right/m+T:A.left/m-x-T,re=(A.top+A.height/2)/m-C/2,Q+x>innerWidth/m-8?Q=A.left/m-x-T:Q<8&&(Q=A.right/m+T)):re<8?re=A.bottom/m+T:re+C>innerHeight/m-8&&(re=A.top/m-C-T),i.style.left=`${Math.max(8,Math.min(Q,innerWidth/m-x-8))}px`,i.style.top=`${Math.max(8,Math.min(re,innerHeight/m-C-8))}px`,s=requestAnimationFrame(d)}function f(m,A=!1){!m||m===n||(l(),!(m.getAttribute("aria-expanded")==="true"||!m.getAttribute(t))&&(n=m,a=setTimeout(()=>{if(!n?.isConnected)return l();i.isConnected||document.body.append(i);let x=getComputedStyle(n);for(let M of["--radius-2xl","--codex-corner-shape","--color-background-tooltip","--color-text-tooltip","--color-border-tooltip","--shadow-tooltip","--tooltip-compact-font-weight","--tracking-tooltip","--spacing","--text-sm","--font-sans-default"]){let T=x.getPropertyValue(M).trim();T?i.style.setProperty(M,T):i.style.removeProperty(M)}i.textContent=n.getAttribute(t),i.hidden=!1;let C=(n.getAttribute("aria-describedby")||"").split(/\s+/).filter(Boolean);n.setAttribute("aria-describedby",[...new Set([...C,i.id])].join(" ")),d()},A||Date.now()-c<300?0:200)))}let h=m=>m.target instanceof Element?m.target.closest(`[${t}]`):null;return document.addEventListener("pointerover",m=>f(h(m)),{signal:e}),document.addEventListener("pointerout",m=>{n&&!n.contains(m.relatedTarget)&&l()},{signal:e}),document.addEventListener("focusin",m=>f(h(m),!0),{signal:e}),document.addEventListener("focusout",l,{signal:e}),document.addEventListener("pointerdown",l,{signal:e,capture:!0}),document.addEventListener("keydown",m=>{m.key==="Escape"&&l()},{signal:e}),window.addEventListener("blur",l,{signal:e}),e.addEventListener("abort",()=>{l(),i.remove(),o.remove()},{once:!0}),{tooltipSurface:r}}var Mo=new vd({name:"Prompt",version:"2.0.
|
|
429
|
+
text-align:center;overflow-wrap:anywhere;`;let n=null,a,s,c=-1/0;function l(){if(clearTimeout(a),cancelAnimationFrame(s),n){let m=(n.getAttribute("aria-describedby")||"").split(/\s+/).filter(A=>A&&A!==i.id);m.length?n.setAttribute("aria-describedby",m.join(" ")):n.removeAttribute("aria-describedby")}i.hidden||(c=Date.now()),n=null,i.hidden=!0}function d(){if(!n?.isConnected||!n.getClientRects().length||n.getAttribute("aria-expanded")==="true")return l();let m=Number.parseFloat(getComputedStyle(i).zoom)||1,A=n.getBoundingClientRect(),x=i.offsetWidth,C=i.offsetHeight,M=n.getAttribute("data-minecodex-tooltip-side")||(n.closest("[data-app-navigation-rail]")?"right":getComputedStyle(n).getPropertyValue("--side-tooltip").trim()||"top"),T=2/m,Q=(A.left+A.width/2)/m-x/2,re=M==="bottom"?A.bottom/m+T:A.top/m-C-T;M==="right"||M==="left"?(Q=M==="right"?A.right/m+T:A.left/m-x-T,re=(A.top+A.height/2)/m-C/2,Q+x>innerWidth/m-8?Q=A.left/m-x-T:Q<8&&(Q=A.right/m+T)):re<8?re=A.bottom/m+T:re+C>innerHeight/m-8&&(re=A.top/m-C-T),i.style.left=`${Math.max(8,Math.min(Q,innerWidth/m-x-8))}px`,i.style.top=`${Math.max(8,Math.min(re,innerHeight/m-C-8))}px`,s=requestAnimationFrame(d)}function f(m,A=!1){!m||m===n||(l(),!(m.getAttribute("aria-expanded")==="true"||!m.getAttribute(t))&&(n=m,a=setTimeout(()=>{if(!n?.isConnected)return l();i.isConnected||document.body.append(i);let x=getComputedStyle(n);for(let M of["--radius-2xl","--codex-corner-shape","--color-background-tooltip","--color-text-tooltip","--color-border-tooltip","--shadow-tooltip","--tooltip-compact-font-weight","--tracking-tooltip","--spacing","--text-sm","--font-sans-default"]){let T=x.getPropertyValue(M).trim();T?i.style.setProperty(M,T):i.style.removeProperty(M)}i.textContent=n.getAttribute(t),i.hidden=!1;let C=(n.getAttribute("aria-describedby")||"").split(/\s+/).filter(Boolean);n.setAttribute("aria-describedby",[...new Set([...C,i.id])].join(" ")),d()},A||Date.now()-c<300?0:200)))}let h=m=>m.target instanceof Element?m.target.closest(`[${t}]`):null;return document.addEventListener("pointerover",m=>f(h(m)),{signal:e}),document.addEventListener("pointerout",m=>{n&&!n.contains(m.relatedTarget)&&l()},{signal:e}),document.addEventListener("focusin",m=>f(h(m),!0),{signal:e}),document.addEventListener("focusout",l,{signal:e}),document.addEventListener("pointerdown",l,{signal:e,capture:!0}),document.addEventListener("keydown",m=>{m.key==="Escape"&&l()},{signal:e}),window.addEventListener("blur",l,{signal:e}),e.addEventListener("abort",()=>{l(),i.remove(),o.remove()},{once:!0}),{tooltipSurface:r}}var Mo=new vd({name:"Prompt",version:"2.0.42"});Mo.ontoolresult=()=>{};await Mo.connect();uv(Mo.getHostContext());Mo.addEventListener("hostcontextchanged",uv);var bx=new AbortController,Ad=bx.signal,bi={};for(let e of[hx,gx,vx,Ax,yx])Object.assign(bi,e(Ad,bi));bi.page=e=>(bi.surface(e,"page"),bi.layer(e,"page"));bi.releasePage=()=>{};var j_=dx(Ad,{management:!0,ui:bi,resources:{icons:mx,previews:px,styles:fx},insertPrompt:e=>new Promise((t,i)=>{let o=new MessageChannel,r,n=s=>{clearTimeout(r),o.port1.close(),Ad.removeEventListener("abort",a),s?i(s):t()},a=()=>n(new Error("Prompt page closed"));Ad.addEventListener("abort",a,{once:!0}),r=setTimeout(()=>n(new Error("No available input in the focused window")),4500),o.port1.onmessage=({data:s})=>n(s.ok?null:new Error(s.error)),window.top.postMessage({type:"minecodex:insert-prompt",promptId:e,expiresAt:Date.now()+4e3},"*",[o.port2])}),requestHostAction:async(e,t)=>{let i=await Mo.callServerTool({name:t.method&&t.method!=="GET"?"minecodex_prompts_write":"minecodex_prompts_read",arguments:t});if(i.isError)throw new Error(i.content?.find(o=>o.type==="text")?.text??"Prompts request failed");return i.structuredContent.result}});Mo.onteardown=async()=>(bx.abort(),j_(),{});
|
|
430
430
|
/*! Bundled license information:
|
|
431
431
|
|
|
432
432
|
@modelcontextprotocol/client/dist/src-WCy6ifGf.mjs:
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 17v5"/><path d="M9 10.76a2 2 0 0 1-1.11 1.79l-1.78.9A2 2 0 0 0 5 15.24V16a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1v-.76a2 2 0 0 0-1.11-1.79l-1.78-.9A2 2 0 0 1 15 10.76V7a1 1 0 0 1 1-1 2 2 0 0 0 0-4H8a2 2 0 0 0 0 4 1 1 0 0 1 1 1z"/></svg>
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import {quickChatHistoryVisible} from "./history.mjs";
|
|
2
|
-
export function createQuickChatPinAdapter(codex) {
|
|
3
|
-
const layerSelector = '.fixed.inset-0.zoom-adjusted-viewport.pointer-events-auto';
|
|
4
|
-
|
|
5
|
-
function surfaces() {
|
|
6
|
-
const inCodex = [...document.querySelectorAll('button[aria-haspopup="menu"]')].some(button => button.checkVisibility({visibilityProperty:true})
|
|
7
|
-
&& codex.props(button, p => typeof p.onModeSelect === 'function' && typeof p.mode === 'string', 80)?.mode === 'codex');
|
|
8
|
-
if (!inCodex) return [];
|
|
9
|
-
return [...document.querySelectorAll('[data-floating-chat-surface]')].flatMap(surface => {
|
|
10
|
-
const layer = surface.closest(layerSelector);
|
|
11
|
-
if (!layer || layer.closest('[hidden], [inert], [aria-hidden="true"]')) return [];
|
|
12
|
-
if (!codex.props(surface, p => p.name === 'QuickChatWindow', 120)) return [];
|
|
13
|
-
const presence = codex.props(surface, p => typeof p.isPresent === 'boolean' && typeof p.onExitComplete === 'function', 120);
|
|
14
|
-
if (presence?.isPresent === false) return [];
|
|
15
|
-
const editable = surface.querySelector('[data-chatgpt-composer] [contenteditable="true"]');
|
|
16
|
-
const composer = editable && codex.props(editable, p => typeof p.isWorkConversation === 'boolean' && p.conversationId);
|
|
17
|
-
const session = codex.props(surface, p => p.session?.conversationId)?.session;
|
|
18
|
-
const floating = codex.props(surface, p => typeof p.onMinimizedChange === 'function' && typeof p.renderMenu === 'function');
|
|
19
|
-
if (!composer || composer.isWorkConversation || composer.annotationSubmitTarget || composer.isWidgetOverlay || !session?.hasConversation || !floating) return [];
|
|
20
|
-
const anchor = surface.querySelector('header button[data-quick-chat-drag-handle]');
|
|
21
|
-
const expanded = floating.presentation === 'expanded' || floating.forceExpanded;
|
|
22
|
-
const history = quickChatHistoryVisible(floating.renderTranscript?.());
|
|
23
|
-
return [{surface, layer, sessionId:session.conversationId, anchor, minimized:Boolean(floating.isMinimized), expanded:Boolean(expanded), history,
|
|
24
|
-
expand:() => floating.onPresentationChange('expanded'),
|
|
25
|
-
showPin:Boolean(anchor && expanded && !floating.isMinimized && !history)}];
|
|
26
|
-
});
|
|
27
|
-
}
|
|
28
|
-
return {surfaces};
|
|
29
|
-
}
|
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
export function createQuickChatExitAdapter(codex) {
|
|
2
|
-
const completed = new WeakSet();
|
|
3
|
-
const selector = '.fixed.inset-0.zoom-adjusted-viewport.pointer-events-auto';
|
|
4
|
-
function currentLayer(layer) {
|
|
5
|
-
const attached = codex.currentFiber(layer);
|
|
6
|
-
let host = attached;
|
|
7
|
-
while (host?.return) host = host.return;
|
|
8
|
-
const current = host?.stateNode?.current;
|
|
9
|
-
if (!current) return attached;
|
|
10
|
-
// Host props 可原样复用,DOM 上的 Fiber 因此可能仍指向上一棵树。
|
|
11
|
-
const pending = [current];
|
|
12
|
-
let visited = 0;
|
|
13
|
-
while (pending.length && visited++ < 10000) {
|
|
14
|
-
const fiber = pending.pop();
|
|
15
|
-
if (fiber.stateNode === layer) return fiber;
|
|
16
|
-
for (let child = fiber.child; child; child = child.sibling) pending.push(child);
|
|
17
|
-
}
|
|
18
|
-
return null;
|
|
19
|
-
}
|
|
20
|
-
function presence(fiber) {
|
|
21
|
-
for (let dependency = fiber.dependencies?.firstContext; dependency; dependency = dependency.next) {
|
|
22
|
-
const context = dependency.memoizedValue;
|
|
23
|
-
if (context?.isPresent === false && typeof context.register === 'function' && typeof context.onExitComplete === 'function') return context;
|
|
24
|
-
}
|
|
25
|
-
return null;
|
|
26
|
-
}
|
|
27
|
-
function completion(fiber) {
|
|
28
|
-
const props = fiber.memoizedProps;
|
|
29
|
-
if (props?.propagate !== true || fiber.child || typeof fiber.type !== 'function') return null;
|
|
30
|
-
const source = Function.prototype.toString.call(fiber.type);
|
|
31
|
-
if (!source.includes('presenceAffectsLayout:') || !source.includes('propagate:') || !source.includes('.useState)')) return null;
|
|
32
|
-
const context = presence(fiber);
|
|
33
|
-
if (!context) return null;
|
|
34
|
-
for (let hook = fiber.memoizedState, count = 0; hook && count < 40; hook = hook.next, count++) {
|
|
35
|
-
const value = hook.memoizedState;
|
|
36
|
-
if (!Array.isArray(value) || typeof value[0] !== 'function') continue;
|
|
37
|
-
const deps = value[1];
|
|
38
|
-
if (!Array.isArray(deps) || deps.length !== 3 || typeof deps[0] !== 'string' || deps[1] !== context.onExitComplete || deps[2] !== true) continue;
|
|
39
|
-
// 仅补齐仍未完成的 usePresence 登记,不绕过父层或其他子动画。
|
|
40
|
-
for (let parent = fiber.return, depth = 0; parent && depth < 40; parent = parent.return, depth++) {
|
|
41
|
-
if (parent.memoizedProps?.value !== context) continue;
|
|
42
|
-
for (let owner = parent.return, level = 0; owner && level < 5; owner = owner.return, level++) {
|
|
43
|
-
for (let state = owner.memoizedState, n = 0; state && n < 20; state = state.next, n++) {
|
|
44
|
-
const map = state.memoizedState?.current;
|
|
45
|
-
if (map instanceof Map && map.get(deps[0]) === false) return value[0];
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
return null;
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
return null;
|
|
52
|
-
}
|
|
53
|
-
function repair(layer) {
|
|
54
|
-
if (!layer.isConnected) return 0;
|
|
55
|
-
let root = currentLayer(layer);
|
|
56
|
-
for (let depth = 0; root && depth < 40; root = root.return, depth++) {
|
|
57
|
-
if (typeof root.memoizedProps?.isPresent === 'boolean' && typeof root.memoizedProps?.onExitComplete === 'function') break;
|
|
58
|
-
}
|
|
59
|
-
if (!root || root.memoizedProps.isPresent !== false) return 0;
|
|
60
|
-
const pending = [root];
|
|
61
|
-
const completions = [];
|
|
62
|
-
let quickChat = false, count = 0, visited = 0;
|
|
63
|
-
while (pending.length && visited++ < 1000) {
|
|
64
|
-
const fiber = pending.pop(), finish = completion(fiber);
|
|
65
|
-
if (fiber.memoizedProps?.name === 'QuickChatWindow') quickChat = true;
|
|
66
|
-
if (finish && !completed.has(finish)) completions.push(finish);
|
|
67
|
-
for (let child = fiber.child; child; child = child.sibling) pending.push(child);
|
|
68
|
-
}
|
|
69
|
-
if (!quickChat || pending.length) return 0;
|
|
70
|
-
for (const finish of completions) { completed.add(finish); finish(); count++; }
|
|
71
|
-
return count;
|
|
72
|
-
}
|
|
73
|
-
return { selector, repair, reconcile:() => [...document.querySelectorAll(selector)].reduce((count, layer) => count + repair(layer), 0) };
|
|
74
|
-
}
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
export function installQuickChatExitRepair(signal, native) {
|
|
2
|
-
let scheduled = false, disposed = false;
|
|
3
|
-
function schedule() {
|
|
4
|
-
if (scheduled || disposed) return;
|
|
5
|
-
scheduled = true;
|
|
6
|
-
queueMicrotask(() => { scheduled = false; if (!disposed) native.reconcile(); });
|
|
7
|
-
}
|
|
8
|
-
const observer = new MutationObserver(schedule);
|
|
9
|
-
observer.observe(document.documentElement, {subtree:true, childList:true, attributes:true, attributeFilter:['style']});
|
|
10
|
-
schedule();
|
|
11
|
-
function dispose() { disposed = true; observer.disconnect(); }
|
|
12
|
-
signal.addEventListener('abort',dispose,{once:true});
|
|
13
|
-
return {dispose,status:()=>!disposed};
|
|
14
|
-
}
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
export function installQuickChatPin(signal, config) {
|
|
2
|
-
const native = createQuickChatPinAdapter(config.codex), instances = new Map();
|
|
3
|
-
const style = document.createElement('style');
|
|
4
|
-
// 保留原生可交互子元素的 pointer-events-auto,仅让透明背景穿透。
|
|
5
|
-
style.textContent = '[data-mcx-quick-chat-pinned-layer]{pointer-events:none!important}';
|
|
6
|
-
document.head.append(style);
|
|
7
|
-
const text = (en,zh) => (document.documentElement.lang || navigator.language).startsWith('zh') ? zh : en;
|
|
8
|
-
function render(instance) {
|
|
9
|
-
if (instance.pinned) instance.layer.setAttribute('data-mcx-quick-chat-pinned-layer','');
|
|
10
|
-
else instance.layer.removeAttribute('data-mcx-quick-chat-pinned-layer');
|
|
11
|
-
const button = instance.button;
|
|
12
|
-
if (!button) return;
|
|
13
|
-
button.setAttribute('aria-pressed',String(instance.pinned));
|
|
14
|
-
const label = instance.pinned ? text('Unpin chat','取消固定聊天') : text('Pin chat','固定聊天');
|
|
15
|
-
button.setAttribute('aria-label',label); button.setAttribute('data-minecodex-tooltip',label);
|
|
16
|
-
button.querySelector('svg path:last-child')?.setAttribute('fill',instance.pinned ? 'currentColor' : 'none');
|
|
17
|
-
}
|
|
18
|
-
function release(instance) { instance.layer.removeAttribute('data-mcx-quick-chat-pinned-layer'); instance.button?.remove(); }
|
|
19
|
-
function sync() {
|
|
20
|
-
const live = new Set();
|
|
21
|
-
for (const snapshot of native.surfaces()) {
|
|
22
|
-
live.add(snapshot.sessionId);
|
|
23
|
-
let instance = instances.get(snapshot.sessionId);
|
|
24
|
-
if (!instance) { instance={pinned:false,layer:snapshot.layer,button:null}; instances.set(snapshot.sessionId,instance); }
|
|
25
|
-
if (instance.layer !== snapshot.layer) { release(instance); instance.layer=snapshot.layer; instance.button=null; }
|
|
26
|
-
if (snapshot.minimized || snapshot.history) instance.pinned=false;
|
|
27
|
-
if (instance.pinned && !snapshot.minimized && !snapshot.expanded && !snapshot.history) snapshot.expand();
|
|
28
|
-
if (!snapshot.showPin) { instance.button?.remove(); instance.button=null; render(instance); continue; }
|
|
29
|
-
const anchor = snapshot.anchor;
|
|
30
|
-
if (!instance.button?.isConnected || instance.button.parentElement !== anchor.parentElement) {
|
|
31
|
-
instance.button?.remove();
|
|
32
|
-
const button = document.createElement('button');
|
|
33
|
-
button.type='button'; button.setAttribute('data-mcx-quick-chat-pin',''); button.innerHTML=config.resources.pin;
|
|
34
|
-
const icon=button.querySelector('svg'), original=anchor.querySelector('svg');
|
|
35
|
-
for (const attr of ['width','height','class']) if (original?.hasAttribute(attr)) icon?.setAttribute(attr,original.getAttribute(attr));
|
|
36
|
-
icon?.setAttribute('aria-hidden','true');
|
|
37
|
-
button.addEventListener('pointerdown',event=>event.stopPropagation(),{signal});
|
|
38
|
-
button.addEventListener('click',event=>{event.stopPropagation();instance.pinned=!instance.pinned;render(instance);},{signal});
|
|
39
|
-
anchor.before(button); instance.button=button;
|
|
40
|
-
}
|
|
41
|
-
if (instance.button.className !== anchor.className) instance.button.className=anchor.className;
|
|
42
|
-
render(instance);
|
|
43
|
-
}
|
|
44
|
-
for (const [id,instance] of instances) if (!live.has(id)) { release(instance); instances.delete(id); }
|
|
45
|
-
}
|
|
46
|
-
function escape(event) {
|
|
47
|
-
if (event.key !== 'Escape' || event.defaultPrevented || event.repeat || event.isComposing) return;
|
|
48
|
-
for (const instance of instances.values()) if (instance.layer.contains(event.target)) { instance.pinned=false; render(instance); }
|
|
49
|
-
}
|
|
50
|
-
document.addEventListener('keydown',escape,{capture:true,signal});
|
|
51
|
-
function dispose() { document.removeEventListener('keydown',escape,true); for (const instance of instances.values()) release(instance); instances.clear(); style.remove(); }
|
|
52
|
-
function status() { const applicable=native.surfaces().some(snapshot=>snapshot.showPin); return {applicable,available:applicable && [...instances.values()].some(instance=>instance.button?.isConnected)}; }
|
|
53
|
-
return {sync,dispose,status};
|
|
54
|
-
}
|