@anionex/dsh-pinned-sessions 0.1.0 → 0.1.2

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/lib/client.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/client/index.tsx","../node_modules/shared/src/utils.ts","../node_modules/lucide-react/src/defaultAttributes.ts","../node_modules/lucide-react/src/Icon.ts","../node_modules/lucide-react/src/createLucideIcon.ts","../node_modules/lucide-react/src/icons/pin.ts","../node_modules/lucide-react/src/icons/x.ts","../node_modules/lucide/src/defaultAttributes.ts","../node_modules/lucide/src/icons/pin-off.ts","../node_modules/lucide/src/icons/pin.ts","../src/client/dom-bridge.ts","../src/client/pin-store.ts","../src/client/presentation.ts"],"sourcesContent":["import {\n useEffect,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n useSyncExternalStore,\n type ReactNode,\n} from 'react'\nimport { Pin, X } from 'lucide-react'\nimport { createPortal } from 'react-dom'\nimport {\n attachSessionMenuHost,\n captureSessionId,\n ensurePinnedHost,\n findSessionActionTarget,\n findUnclaimedPortalMenu,\n focusAfterPinnedRemoval,\n listPortalMenus,\n MENU_OWNER_ATTRIBUTE,\n removeBridgeArtifacts,\n SIDEBAR_SLOT_SELECTOR,\n updateSessionMenuItem,\n type SessionMenuTarget,\n type TriggerRect,\n type SessionsForCapture,\n} from './dom-bridge.js'\nimport { PIN_STORAGE_KEY, PinStore } from './pin-store.js'\nimport { sessionDisplayTitle } from './presentation.js'\n\ninterface SessionSummaryLike {\n readonly id: string\n readonly title?: string | undefined\n readonly cwd?: string | undefined\n readonly blank?: boolean | undefined\n readonly running?: boolean | undefined\n readonly completed?: boolean | undefined\n}\n\ninterface SessionsSnapshotLike {\n readonly ids: readonly string[]\n readonly byId: Readonly<Record<string, SessionSummaryLike | undefined>>\n readonly current?: string | undefined\n readonly phase: string\n}\n\ninterface WorkspaceLike {\n readonly workspaceId: string\n readonly title: string\n readonly sessionIds: readonly string[]\n}\n\ninterface WorkspacesSnapshotLike {\n readonly items: readonly WorkspaceLike[]\n readonly archivedSessionIds: readonly string[]\n readonly phase: string\n}\n\ntype SelectorHook<T> = <S>(selector: (snapshot: T) => S, equal?: (left: S, right: S) => boolean) => S\ntype Translate = (key: string, params?: Readonly<Record<string, unknown>>) => string\n\ninterface SlotsLike {\n inject(name: string, install: () => unknown): void\n register<I, P>(\n entry: {\n readonly name: string\n readonly id: string\n readonly order?: number\n readonly locale?: string\n readonly inject?: () => I\n },\n component: (props: P) => ReactNode,\n ): () => void\n}\n\ninterface LocaleLike {\n register(namespace: string, dictionaries: Readonly<Record<string, Readonly<Record<string, string>>>>): () => void\n}\n\ninterface ClientContextLike {\n readonly slots: SlotsLike\n readonly sessions: SessionsForCapture\n readonly locale: LocaleLike\n effect(setup: () => (() => void), label?: string): unknown\n}\n\ninterface BridgeProps {\n readonly store: PinStore\n readonly sessions: SessionsForCapture\n readonly useSessions: SelectorHook<SessionsSnapshotLike>\n readonly useWorkspaces: SelectorHook<WorkspacesSnapshotLike>\n readonly t: Translate\n}\n\ninterface PinIconProps {\n readonly size?: number\n}\n\ninterface PendingMenuRequest {\n readonly sessionId: string\n readonly createdAt: number\n readonly existingMenus: ReadonlySet<HTMLElement>\n readonly triggerRect: TriggerRect\n}\n\ninterface ActiveMenuBinding {\n readonly target: SessionMenuTarget\n readonly onClick: (event: MouseEvent) => void\n}\n\nconst NS = 'pinnedSessions'\nconst STYLE_ID = '@anionex/dsh-pinned-sessions'\nconst MENU_ASSOCIATION_MS = 2_000\n\nconst zh = {\n 'menu.pin': '置顶会话',\n 'menu.unpin': '取消置顶',\n 'section.label': '置顶会话',\n 'session.open': '打开置顶会话“{name}”',\n 'session.unpin': '取消置顶“{name}”',\n 'workspace.ungrouped': '未分组',\n}\n\nconst en = {\n 'menu.pin': 'Pin session',\n 'menu.unpin': 'Unpin session',\n 'section.label': 'Pinned sessions',\n 'session.open': 'Open pinned session “{name}”',\n 'session.unpin': 'Unpin “{name}”',\n 'workspace.ungrouped': 'Ungrouped',\n}\n\nconst styles = `\n[${'data-dsh-pinned-sessions-host'}]{box-sizing:border-box;min-width:0;flex:none}\n.dsh-pins-section{box-sizing:border-box;min-width:0;margin:0 4px 6px;padding:0 0 6px;border-bottom:1px solid var(--dsw-alias-border-l1)}\n.dsh-pins-header{display:flex;align-items:center;gap:6px;height:28px;padding:0 8px;color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:18px;font-weight:500}\n.dsh-pins-header svg{flex:none;color:var(--dsw-alias-state-business-primary)}\n.dsh-pins-list{box-sizing:border-box;max-height:192px;min-width:0;margin:0;padding:0;overflow-y:auto;overscroll-behavior:contain;list-style:none}\n.dsh-pins-row{box-sizing:border-box;display:flex;align-items:center;gap:0;height:32px;min-width:0;border-radius:6px;color:var(--dsw-alias-label-primary)}\n.dsh-pins-row:hover,.dsh-pins-row[data-current=\"true\"]{background:var(--dsw-alias-interactive-bg-hover)}\n.dsh-pins-open{box-sizing:border-box;display:flex;align-items:center;gap:6px;min-width:0;height:32px;padding:0 4px 0 8px;border:0;background:transparent;color:inherit;cursor:pointer;flex:1;text-align:left}\n.dsh-pins-open:focus-visible,.dsh-pins-remove:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary);outline-offset:-2px}\n.dsh-pins-open>svg{flex:none;color:var(--dsw-alias-state-business-primary)}\n.dsh-pins-title{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:14px;line-height:20px;flex:1}\n.dsh-pins-workspace{max-width:34%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--dsw-alias-label-tertiary);font-size:11px;line-height:18px;flex:none}\n.dsh-pins-remove{display:inline-flex;align-items:center;justify-content:center;width:26px;height:26px;margin-right:3px;padding:0;border:0;border-radius:6px;background:transparent;color:var(--dsw-alias-label-tertiary);cursor:pointer;opacity:0;flex:none}\n.dsh-pins-row:hover .dsh-pins-remove,.dsh-pins-remove:focus-visible{opacity:1}\n.dsh-pins-remove:hover{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}\n.dsh-pins-menu-button{letter-spacing:0}\n@media (max-width:767px){.dsh-pins-workspace{display:none}.dsh-pins-remove{opacity:1}}\n`\n\nexport const inject = ['slots', 'sessions', 'locale']\n\n/** Register the lifecycle bridge in the additive frame overlay slot. */\nexport function apply(ctx: ClientContextLike): void {\n let storage: Storage | undefined\n try {\n storage = window.localStorage\n } catch {\n storage = undefined\n }\n const store = new PinStore(storage)\n\n ctx.effect(() => {\n const onStorage = (event: StorageEvent): void => {\n if (event.key === PIN_STORAGE_KEY || event.key === null) store.reload()\n }\n window.addEventListener('storage', onStorage)\n return () => { window.removeEventListener('storage', onStorage) }\n }, 'pinned-sessions: cross-tab state')\n\n ctx.effect(() => {\n if (document.querySelector(`style[data-plugin-css=\"${STYLE_ID}\"]`) !== null) return () => {}\n const tag = document.createElement('style')\n tag.dataset.plugin = '@anionex/dsh-pinned-sessions'\n tag.dataset.pluginCss = STYLE_ID\n tag.textContent = styles\n document.head.appendChild(tag)\n return () => { tag.remove() }\n }, 'pinned-sessions: styles')\n\n ctx.effect(() => ctx.locale.register(NS, { zh, en }), 'pinned-sessions: dictionaries')\n\n ctx.slots.inject('shell.overlay', () => ctx.slots.register({\n name: 'shell.overlay',\n id: 'pinned-sessions-bridge',\n order: 40,\n locale: NS,\n inject: () => ({ store, sessions: ctx.sessions }),\n }, PinnedSessionsBridge))\n}\n\n/** Keep native behavior intact while mounting the sidebar portal and unmanaged menu item. */\nexport function PinnedSessionsBridge({ store, sessions, useSessions, useWorkspaces, t }: BridgeProps): ReactNode {\n const sessionSnapshot = useSessions(snapshot => snapshot)\n const workspaceSnapshot = useWorkspaces(snapshot => snapshot)\n const pins = useSyncExternalStore(store.subscribe, store.getSnapshot, store.getSnapshot)\n const [sidebarHost, setSidebarHost] = useState<HTMLDivElement | null>(null)\n const [sidebarWide, setSidebarWide] = useState(true)\n const pending = useRef<PendingMenuRequest | null>(null)\n const activeMenu = useRef<ActiveMenuBinding | null>(null)\n const focusAfterUnpin = useRef<number | null>(null)\n\n useLayoutEffect(() => {\n let active = true\n let queued = false\n let settleTimer: number | undefined\n let observedSidebar: Element | null = null\n const sidebarObserver = new MutationObserver(() => { queueRefresh() })\n\n const disposeActiveMenu = (): void => {\n const binding = activeMenu.current\n if (binding === null) return\n activeMenu.current = null\n binding.target.button.removeEventListener('click', binding.onClick)\n binding.target.host.remove()\n if (binding.target.menu.getAttribute(MENU_OWNER_ATTRIBUTE) === binding.target.sessionId) {\n binding.target.menu.removeAttribute(MENU_OWNER_ATTRIBUTE)\n }\n }\n const updateActiveMenu = (): void => {\n const binding = activeMenu.current\n if (binding === null) return\n const pinned = store.isPinned(binding.target.sessionId)\n updateSessionMenuItem(binding.target, pinned, t(pinned ? 'menu.unpin' : 'menu.pin'))\n }\n const observeSidebar = (): void => {\n const slot = document.querySelector(SIDEBAR_SLOT_SELECTOR)\n if (slot === observedSidebar) return\n sidebarObserver.disconnect()\n observedSidebar = slot\n if (slot !== null) {\n sidebarObserver.observe(slot, {\n attributes: true,\n attributeFilter: ['class', 'style'],\n childList: true,\n subtree: true,\n })\n }\n }\n const refresh = (): void => {\n if (!active) return\n const nextHost = ensurePinnedHost(document)\n setSidebarHost(current => current === nextHost ? current : nextHost)\n observeSidebar()\n const rootWidth = nextHost?.parentElement?.getBoundingClientRect().width\n if (rootWidth !== undefined) setSidebarWide(rootWidth >= 160)\n\n const binding = activeMenu.current\n if (binding !== null && (!binding.target.host.isConnected || !binding.target.menu.isConnected)) {\n disposeActiveMenu()\n }\n const request = pending.current\n if (request === null) return\n if (Date.now() - request.createdAt > MENU_ASSOCIATION_MS) {\n pending.current = null\n return\n }\n const menu = findUnclaimedPortalMenu(document, request.existingMenus, request.triggerRect)\n if (menu === null) return\n const target = attachSessionMenuHost(menu, request.sessionId)\n if (target === null) return\n const onClick = (event: MouseEvent): void => {\n event.preventDefault()\n event.stopPropagation()\n store.toggle(target.sessionId)\n disposeActiveMenu()\n document.dispatchEvent(new KeyboardEvent('keydown', { key: 'Escape', bubbles: true }))\n }\n target.button.addEventListener('click', onClick)\n activeMenu.current = { target, onClick }\n pending.current = null\n updateActiveMenu()\n }\n function queueRefresh(): void {\n if (!active) return\n if (settleTimer === undefined) {\n settleTimer = window.setTimeout(() => {\n settleTimer = undefined\n refresh()\n }, 250)\n }\n if (queued) return\n queued = true\n queueMicrotask(() => {\n queued = false\n refresh()\n })\n }\n const onClickCapture = (event: MouseEvent): void => {\n pending.current = null\n const target = findSessionActionTarget(event.target)\n if (target === null) return\n const sessionId = captureSessionId(target.row, sessions)\n if (sessionId === null) return\n const rect = target.button.getBoundingClientRect()\n pending.current = {\n sessionId,\n createdAt: Date.now(),\n existingMenus: new Set(listPortalMenus(document)),\n triggerRect: {\n top: rect.top,\n right: rect.right,\n bottom: rect.bottom,\n left: rect.left,\n width: rect.width,\n height: rect.height,\n },\n }\n queueRefresh()\n }\n const onKeyDownCapture = (): void => { pending.current = null }\n\n refresh()\n document.addEventListener('click', onClickCapture, true)\n document.addEventListener('keydown', onKeyDownCapture, true)\n const bodyObserver = new MutationObserver(() => { queueRefresh() })\n bodyObserver.observe(document.body, { childList: true })\n const unsubscribe = store.subscribe(updateActiveMenu)\n return () => {\n active = false\n pending.current = null\n if (settleTimer !== undefined) window.clearTimeout(settleTimer)\n unsubscribe()\n bodyObserver.disconnect()\n sidebarObserver.disconnect()\n document.removeEventListener('click', onClickCapture, true)\n document.removeEventListener('keydown', onKeyDownCapture, true)\n disposeActiveMenu()\n removeBridgeArtifacts(document)\n }\n }, [sessions, store, t])\n\n useLayoutEffect(() => {\n if (sidebarHost === null) return\n const root = sidebarHost.parentElement\n if (root === null) return\n const update = (): void => { setSidebarWide(root.getBoundingClientRect().width >= 160) }\n update()\n if (typeof ResizeObserver === 'undefined') return\n const observer = new ResizeObserver(update)\n observer.observe(root)\n return () => { observer.disconnect() }\n }, [sidebarHost])\n\n useEffect(() => {\n if (sessionSnapshot.phase !== 'ready' || workspaceSnapshot.phase !== 'ready') return\n const valid = new Set(sessionSnapshot.ids)\n const archived = new Set(workspaceSnapshot.archivedSessionIds)\n store.prune(sessionId => valid.has(sessionId) && !archived.has(sessionId))\n }, [sessionSnapshot, store, workspaceSnapshot])\n\n const rows = useMemo(() => {\n const workspaceBySession = new Map<string, string>()\n for (const workspace of workspaceSnapshot.items) {\n for (const sessionId of workspace.sessionIds) {\n if (!workspaceBySession.has(sessionId)) workspaceBySession.set(sessionId, workspace.title)\n }\n }\n return pins.flatMap(pin => {\n const session = sessionSnapshot.byId[pin.id]\n if (session === undefined || session.blank === true) return []\n const workspaceTitle = workspaceBySession.get(pin.id)\n const workspace = workspaceTitle ?? t('workspace.ungrouped')\n return [{ session, title: sessionDisplayTitle(session, workspaceTitle), workspace }]\n })\n }, [pins, sessionSnapshot.byId, t, workspaceSnapshot.items])\n\n useLayoutEffect(() => {\n const removedIndex = focusAfterUnpin.current\n if (removedIndex === null) return\n focusAfterUnpin.current = null\n focusAfterPinnedRemoval(document, sidebarHost, removedIndex)\n }, [rows, sidebarHost])\n\n return sidebarHost !== null && sidebarHost.isConnected && sidebarWide && rows.length > 0\n ? createPortal(\n <PinnedSessionSection\n currentId={sessionSnapshot.current}\n rows={rows}\n open={sessionId => { sessions.open(sessionId) }}\n unpin={(sessionId, index) => {\n focusAfterUnpin.current = index\n store.toggle(sessionId)\n }}\n t={t}\n />,\n sidebarHost,\n )\n : null\n}\n\ninterface PinnedSessionSectionProps {\n readonly currentId?: string | undefined\n readonly rows: readonly { readonly session: SessionSummaryLike; readonly title: string; readonly workspace: string }[]\n readonly open: (sessionId: string) => void\n readonly unpin: (sessionId: string, index: number) => void\n readonly t: Translate\n}\n\nfunction PinnedSessionSection({ currentId, rows, open, unpin, t }: PinnedSessionSectionProps): ReactNode {\n return <section className=\"dsh-pins-section\" aria-label={t('section.label')}>\n <div className=\"dsh-pins-header\">\n <PinIcon size={13} />\n <span>{t('section.label')}</span>\n </div>\n <ul className=\"dsh-pins-list\">\n {rows.map(({ session, title, workspace }, index) => <li\n className=\"dsh-pins-row\"\n data-current={session.id === currentId ? 'true' : 'false'}\n key={session.id}\n >\n <button\n type=\"button\"\n className=\"dsh-pins-open\"\n aria-current={session.id === currentId ? 'page' : undefined}\n aria-label={t('session.open', { name: title })}\n onClick={() => { open(session.id) }}\n >\n <PinIcon size={13} />\n <span className=\"dsh-pins-title\">{title}</span>\n <span className=\"dsh-pins-workspace\">{workspace}</span>\n </button>\n <button\n type=\"button\"\n className=\"dsh-pins-remove\"\n aria-label={t('session.unpin', { name: title })}\n title={t('session.unpin', { name: title })}\n onClick={() => { unpin(session.id, index) }}\n >\n <CloseIcon />\n </button>\n </li>)}\n </ul>\n </section>\n}\n\nfunction PinIcon({ size = 16 }: PinIconProps): ReactNode {\n return <Pin size={size} strokeWidth={1.8} aria-hidden=\"true\" />\n}\n\nfunction CloseIcon(): ReactNode {\n return <X size={14} strokeWidth={2} aria-hidden=\"true\" />\n}\n","import { CamelToPascal } from './utility-types';\n\n/**\n * Converts string to kebab case\n *\n * @param {string} string\n * @returns {string} A kebabized string\n */\nexport const toKebabCase = (string: string) =>\n string.replace(/([a-z0-9])([A-Z])/g, '$1-$2').toLowerCase();\n\n/**\n * Converts string to camel case\n *\n * @param {string} string\n * @returns {string} A camelized string\n */\nexport const toCamelCase = <T extends string>(string: T) =>\n string.replace(/^([A-Z])|[\\s-_]+(\\w)/g, (match, p1, p2) =>\n p2 ? p2.toUpperCase() : p1.toLowerCase(),\n );\n\n/**\n * Converts string to pascal case\n *\n * @param {string} string\n * @returns {string} A pascalized string\n */\nexport const toPascalCase = <T extends string>(string: T): CamelToPascal<T> => {\n const camelCase = toCamelCase(string);\n\n return (camelCase.charAt(0).toUpperCase() + camelCase.slice(1)) as CamelToPascal<T>;\n};\n\n/**\n * Merges classes into a single string\n *\n * @param {array} classes\n * @returns {string} A string of classes\n */\nexport const mergeClasses = <ClassType = string | undefined | null>(...classes: ClassType[]) =>\n classes\n .filter((className, index, array) => {\n return (\n Boolean(className) &&\n (className as string).trim() !== '' &&\n array.indexOf(className) === index\n );\n })\n .join(' ')\n .trim();\n","export default {\n xmlns: 'http://www.w3.org/2000/svg',\n width: 24,\n height: 24,\n viewBox: '0 0 24 24',\n fill: 'none',\n stroke: 'currentColor',\n strokeWidth: 2,\n strokeLinecap: 'round',\n strokeLinejoin: 'round',\n};\n","import { createElement, forwardRef } from 'react';\nimport defaultAttributes from './defaultAttributes';\nimport { IconNode, LucideProps } from './types';\nimport { mergeClasses } from '@lucide/shared';\n\ninterface IconComponentProps extends LucideProps {\n iconNode: IconNode;\n}\n\n/**\n * Lucide icon component\n *\n * @component Icon\n * @param {object} props\n * @param {string} props.color - The color of the icon\n * @param {number} props.size - The size of the icon\n * @param {number} props.strokeWidth - The stroke width of the icon\n * @param {boolean} props.absoluteStrokeWidth - Whether to use absolute stroke width\n * @param {string} props.className - The class name of the icon\n * @param {IconNode} props.children - The children of the icon\n * @param {IconNode} props.iconNode - The icon node of the icon\n *\n * @returns {ForwardRefExoticComponent} LucideIcon\n */\nconst Icon = forwardRef<SVGSVGElement, IconComponentProps>(\n (\n {\n color = 'currentColor',\n size = 24,\n strokeWidth = 2,\n absoluteStrokeWidth,\n className = '',\n children,\n iconNode,\n ...rest\n },\n ref,\n ) => {\n return createElement(\n 'svg',\n {\n ref,\n ...defaultAttributes,\n width: size,\n height: size,\n stroke: color,\n strokeWidth: absoluteStrokeWidth ? (Number(strokeWidth) * 24) / Number(size) : strokeWidth,\n className: mergeClasses('lucide', className),\n ...rest,\n },\n [\n ...iconNode.map(([tag, attrs]) => createElement(tag, attrs)),\n ...(Array.isArray(children) ? children : [children]),\n ],\n );\n },\n);\n\nexport default Icon;\n","import { createElement, forwardRef } from 'react';\nimport { mergeClasses, toKebabCase } from '@lucide/shared';\nimport { IconNode, LucideProps } from './types';\nimport Icon from './Icon';\n\n/**\n * Create a Lucide icon component\n * @param {string} iconName\n * @param {array} iconNode\n * @returns {ForwardRefExoticComponent} LucideIcon\n */\nconst createLucideIcon = (iconName: string, iconNode: IconNode) => {\n const Component = forwardRef<SVGSVGElement, LucideProps>(({ className, ...props }, ref) =>\n createElement(Icon, {\n ref,\n iconNode,\n className: mergeClasses(`lucide-${toKebabCase(iconName)}`, className),\n ...props,\n }),\n );\n\n Component.displayName = `${iconName}`;\n\n return Component;\n};\n\nexport default createLucideIcon;\n","import createLucideIcon from '../createLucideIcon';\n\n/**\n * @component @name Pin\n * @description Lucide SVG icon component, renders SVG Element with children.\n *\n * @preview ![img](data:image/svg+xml;base64,PHN2ZyAgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIgogIHdpZHRoPSIyNCIKICBoZWlnaHQ9IjI0IgogIHZpZXdCb3g9IjAgMCAyNCAyNCIKICBmaWxsPSJub25lIgogIHN0cm9rZT0iIzAwMCIgc3R5bGU9ImJhY2tncm91bmQtY29sb3I6ICNmZmY7IGJvcmRlci1yYWRpdXM6IDJweCIKICBzdHJva2Utd2lkdGg9IjIiCiAgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIgogIHN0cm9rZS1saW5lam9pbj0icm91bmQiCj4KICA8cGF0aCBkPSJNMTIgMTd2NSIgLz4KICA8cGF0aCBkPSJNOSAxMC43NmEyIDIgMCAwIDEtMS4xMSAxLjc5bC0xLjc4LjlBMiAyIDAgMCAwIDUgMTUuMjRWMTZhMSAxIDAgMCAwIDEgMWgxMmExIDEgMCAwIDAgMS0xdi0uNzZhMiAyIDAgMCAwLTEuMTEtMS43OWwtMS43OC0uOUEyIDIgMCAwIDEgMTUgMTAuNzZWN2ExIDEgMCAwIDEgMS0xIDIgMiAwIDAgMCAwLTRIOGEyIDIgMCAwIDAgMCA0IDEgMSAwIDAgMSAxIDF6IiAvPgo8L3N2Zz4K) - https://lucide.dev/icons/pin\n * @see https://lucide.dev/guide/packages/lucide-react - Documentation\n *\n * @param {Object} props - Lucide icons props and any valid SVG attribute\n * @returns {JSX.Element} JSX Element\n *\n */\nconst Pin = createLucideIcon('Pin', [\n ['path', { d: 'M12 17v5', key: 'bb1du9' }],\n [\n 'path',\n {\n 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',\n key: '1nkz8b',\n },\n ],\n]);\n\nexport default Pin;\n","import createLucideIcon from '../createLucideIcon';\n\n/**\n * @component @name X\n * @description Lucide SVG icon component, renders SVG Element with children.\n *\n * @preview ![img](data:image/svg+xml;base64,PHN2ZyAgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIgogIHdpZHRoPSIyNCIKICBoZWlnaHQ9IjI0IgogIHZpZXdCb3g9IjAgMCAyNCAyNCIKICBmaWxsPSJub25lIgogIHN0cm9rZT0iIzAwMCIgc3R5bGU9ImJhY2tncm91bmQtY29sb3I6ICNmZmY7IGJvcmRlci1yYWRpdXM6IDJweCIKICBzdHJva2Utd2lkdGg9IjIiCiAgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIgogIHN0cm9rZS1saW5lam9pbj0icm91bmQiCj4KICA8cGF0aCBkPSJNMTggNiA2IDE4IiAvPgogIDxwYXRoIGQ9Im02IDYgMTIgMTIiIC8+Cjwvc3ZnPgo=) - https://lucide.dev/icons/x\n * @see https://lucide.dev/guide/packages/lucide-react - Documentation\n *\n * @param {Object} props - Lucide icons props and any valid SVG attribute\n * @returns {JSX.Element} JSX Element\n *\n */\nconst X = createLucideIcon('X', [\n ['path', { d: 'M18 6 6 18', key: '1bl5f8' }],\n ['path', { d: 'm6 6 12 12', key: 'd8bk6v' }],\n]);\n\nexport default X;\n","import { SVGProps } from './types';\n\nconst defaultAttributes: SVGProps = {\n xmlns: 'http://www.w3.org/2000/svg',\n width: 24,\n height: 24,\n viewBox: '0 0 24 24',\n fill: 'none',\n stroke: 'currentColor',\n 'stroke-width': 2,\n 'stroke-linecap': 'round',\n 'stroke-linejoin': 'round',\n};\n\nexport default defaultAttributes;\n","import defaultAttributes from '../defaultAttributes';\nimport type { IconNode } from '../types';\n\n/**\n * @name pin-off\n * @description Lucide SVG icon node.\n *\n * @preview ![img](data:image/svg+xml;base64,PHN2ZyAgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIgogIHdpZHRoPSIyNCIKICBoZWlnaHQ9IjI0IgogIHZpZXdCb3g9IjAgMCAyNCAyNCIKICBmaWxsPSJub25lIgogIHN0cm9rZT0iIzAwMCIgc3R5bGU9ImJhY2tncm91bmQtY29sb3I6ICNmZmY7IGJvcmRlci1yYWRpdXM6IDJweCIKICBzdHJva2Utd2lkdGg9IjIiCiAgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIgogIHN0cm9rZS1saW5lam9pbj0icm91bmQiCj4KICA8cGF0aCBkPSJNMTIgMTd2NSIgLz4KICA8cGF0aCBkPSJNMTUgOS4zNFY3YTEgMSAwIDAgMSAxLTEgMiAyIDAgMCAwIDAtNEg3Ljg5IiAvPgogIDxwYXRoIGQ9Im0yIDIgMjAgMjAiIC8+CiAgPHBhdGggZD0iTTkgOXYxLjc2YTIgMiAwIDAgMS0xLjExIDEuNzlsLTEuNzguOUEyIDIgMCAwIDAgNSAxNS4yNFYxNmExIDEgMCAwIDAgMSAxaDExIiAvPgo8L3N2Zz4K) - https://lucide.dev/icons/pin-off\n * @see https://lucide.dev/guide/packages/lucide - Documentation\n *\n * @returns {Array}\n *\n */\nconst PinOff: IconNode = [\n 'svg',\n defaultAttributes,\n [\n ['path', { d: 'M12 17v5' }],\n ['path', { d: 'M15 9.34V7a1 1 0 0 1 1-1 2 2 0 0 0 0-4H7.89' }],\n ['path', { d: 'm2 2 20 20' }],\n ['path', { d: 'M9 9v1.76a2 2 0 0 1-1.11 1.79l-1.78.9A2 2 0 0 0 5 15.24V16a1 1 0 0 0 1 1h11' }],\n ],\n];\n\nexport default PinOff;\n","import defaultAttributes from '../defaultAttributes';\nimport type { IconNode } from '../types';\n\n/**\n * @name pin\n * @description Lucide SVG icon node.\n *\n * @preview ![img](data:image/svg+xml;base64,PHN2ZyAgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIgogIHdpZHRoPSIyNCIKICBoZWlnaHQ9IjI0IgogIHZpZXdCb3g9IjAgMCAyNCAyNCIKICBmaWxsPSJub25lIgogIHN0cm9rZT0iIzAwMCIgc3R5bGU9ImJhY2tncm91bmQtY29sb3I6ICNmZmY7IGJvcmRlci1yYWRpdXM6IDJweCIKICBzdHJva2Utd2lkdGg9IjIiCiAgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIgogIHN0cm9rZS1saW5lam9pbj0icm91bmQiCj4KICA8cGF0aCBkPSJNMTIgMTd2NSIgLz4KICA8cGF0aCBkPSJNOSAxMC43NmEyIDIgMCAwIDEtMS4xMSAxLjc5bC0xLjc4LjlBMiAyIDAgMCAwIDUgMTUuMjRWMTZhMSAxIDAgMCAwIDEgMWgxMmExIDEgMCAwIDAgMS0xdi0uNzZhMiAyIDAgMCAwLTEuMTEtMS43OWwtMS43OC0uOUEyIDIgMCAwIDEgMTUgMTAuNzZWN2ExIDEgMCAwIDEgMS0xIDIgMiAwIDAgMCAwLTRIOGEyIDIgMCAwIDAgMCA0IDEgMSAwIDAgMSAxIDF6IiAvPgo8L3N2Zz4K) - https://lucide.dev/icons/pin\n * @see https://lucide.dev/guide/packages/lucide - Documentation\n *\n * @returns {Array}\n *\n */\nconst Pin: IconNode = [\n 'svg',\n defaultAttributes,\n [\n ['path', { d: 'M12 17v5' }],\n [\n 'path',\n {\n 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',\n },\n ],\n ],\n];\n\nexport default Pin;\n","import { Pin as PinNode, PinOff as PinOffNode, type IconNode } from 'lucide'\n\nexport const SIDEBAR_SLOT_SELECTOR = '[data-slot=\"sidebar.workspaces\"]'\nexport const PINNED_HOST_ATTRIBUTE = 'data-dsh-pinned-sessions-host'\nexport const MENU_HOST_ATTRIBUTE = 'data-dsh-pinned-session-menu-host'\nexport const MENU_OWNER_ATTRIBUTE = 'data-dsh-pinned-session-menu'\n\nexport interface SessionsForCapture {\n readonly list: {\n getSnapshot(): { readonly current?: string | undefined }\n }\n open(sessionId: string): void\n}\n\nexport interface SessionActionTarget {\n readonly button: HTMLButtonElement\n readonly row: HTMLElement\n}\n\nexport interface SessionMenuTarget {\n readonly host: HTMLDivElement\n readonly menu: HTMLElement\n readonly sessionId: string\n readonly button: HTMLButtonElement\n readonly icon: HTMLSpanElement\n readonly label: HTMLSpanElement\n}\n\nexport interface TriggerRect {\n readonly top: number\n readonly right: number\n readonly bottom: number\n readonly left: number\n readonly width: number\n readonly height: number\n}\n\nfunction elementFromTarget(target: EventTarget | null): Element | null {\n return target !== null && (target as Node).nodeType === 1 ? target as Element : null\n}\n\n/** Identify a native ellipsis trigger inside a real Session row. */\nexport function findSessionActionTarget(target: EventTarget | null): SessionActionTarget | null {\n const element = elementFromTarget(target)\n const button = element?.closest('button')\n if (!(button instanceof HTMLButtonElement)) return null\n const row = button.closest<HTMLElement>('[role=\"treeitem\"][aria-selected]')\n if (row === null || row === button) return null\n if (row.closest(SIDEBAR_SLOT_SELECTOR) === null) return null\n if (row.closest(`[${PINNED_HOST_ATTRIBUTE}]`) !== null) return null\n return { button, row }\n}\n\n/**\n * Ask the native row closure for its Session ID without changing selection.\n * The Workspace browser's row callback calls sessions.open(node.id), so a\n * synchronous, verified interceptor captures the exact ID and is restored\n * before the user's original ellipsis click continues.\n */\nexport function captureSessionId(row: HTMLElement, sessions: SessionsForCapture): string | null {\n const hadOwn = Object.prototype.hasOwnProperty.call(sessions, 'open')\n const ownDescriptor = hadOwn ? Object.getOwnPropertyDescriptor(sessions, 'open') : undefined\n const original = sessions.open\n let captured: string | null = null\n const interceptor = (sessionId: string): void => {\n if (typeof sessionId === 'string' && sessionId.length > 0) captured = sessionId\n }\n\n try {\n Object.defineProperty(sessions, 'open', {\n configurable: true,\n enumerable: ownDescriptor?.enumerable ?? false,\n writable: true,\n value: interceptor,\n })\n if (sessions.open !== interceptor) return null\n row.click()\n } catch {\n return null\n } finally {\n try {\n if (hadOwn && ownDescriptor !== undefined) Object.defineProperty(sessions, 'open', ownDescriptor)\n else delete (sessions as { open?: SessionsForCapture['open'] }).open\n } catch {\n try {\n Object.defineProperty(sessions, 'open', {\n configurable: true,\n writable: true,\n value: original,\n })\n } catch {\n // The verified patch path is configurable; this is a defensive fallback.\n }\n }\n }\n return captured\n}\n\n/** Insert the pinned region immediately after the native Workspace header. */\nexport function ensurePinnedHost(doc: Document): HTMLDivElement | null {\n const slot = doc.querySelector<HTMLElement>(SIDEBAR_SLOT_SELECTOR)\n const root = slot?.firstElementChild\n if (!(root instanceof HTMLElement)) return null\n const existing = root.querySelector<HTMLDivElement>(`:scope > [${PINNED_HOST_ATTRIBUTE}]`)\n if (existing !== null) return existing\n const header = root.firstElementChild\n if (header === null) return null\n const host = doc.createElement('div')\n host.setAttribute(PINNED_HOST_ATTRIBUTE, '')\n header.insertAdjacentElement('afterend', host)\n return host\n}\n\n/** List direct-body portal menus so one trigger can exclude every pre-existing menu. */\nexport function listPortalMenus(doc: Document): readonly HTMLElement[] {\n return [...doc.body.children].filter((node): node is HTMLElement => (\n node instanceof HTMLElement && node.getAttribute('role') === 'menu'\n ))\n}\n\nfunction belongsToTrigger(menu: HTMLElement, trigger: TriggerRect | undefined): boolean {\n if (trigger === undefined || trigger.width === 0 || trigger.height === 0) return true\n const menuRect = menu.getBoundingClientRect()\n if (menuRect.width === 0 || menuRect.height === 0) return true\n const horizontalGap = Math.min(\n Math.abs(menuRect.left - trigger.left),\n Math.abs(menuRect.right - trigger.right),\n )\n const verticalGap = Math.max(\n 0,\n menuRect.top - trigger.bottom,\n trigger.top - menuRect.bottom,\n )\n return horizontalGap <= 64 && verticalGap <= 32\n}\n\n/** Find only a new, geometrically associated portal menu after one trigger click. */\nexport function findUnclaimedPortalMenu(\n doc: Document,\n excluded: ReadonlySet<HTMLElement> = new Set(),\n trigger?: TriggerRect,\n): HTMLElement | null {\n const menus = listPortalMenus(doc).filter(menu => (\n !excluded.has(menu)\n && !menu.hasAttribute(MENU_OWNER_ATTRIBUTE)\n && belongsToTrigger(menu, trigger)\n ))\n return menus.at(-1) ?? null\n}\n\nfunction createLucideIcon(doc: Document, node: IconNode, name: string): SVGSVGElement {\n const [, attributes, children = []] = node\n const svg = doc.createElementNS('http://www.w3.org/2000/svg', 'svg')\n for (const [key, value] of Object.entries(attributes)) svg.setAttribute(key, String(value))\n svg.setAttribute('width', '16')\n svg.setAttribute('height', '16')\n svg.setAttribute('stroke-width', '1.8')\n svg.setAttribute('class', `lucide lucide-${name}`)\n svg.setAttribute('aria-hidden', 'true')\n for (const [tag, childAttributes] of children) {\n const child = doc.createElementNS('http://www.w3.org/2000/svg', tag)\n for (const [key, value] of Object.entries(childAttributes)) child.setAttribute(key, String(value))\n svg.appendChild(child)\n }\n return svg\n}\n\n/** Update the unmanaged item without moving it into the plugin's React tree. */\nexport function updateSessionMenuItem(target: SessionMenuTarget, pinned: boolean, label: string): void {\n target.button.setAttribute('aria-label', label)\n target.label.textContent = label\n target.icon.replaceChildren(createLucideIcon(\n target.menu.ownerDocument,\n pinned ? PinOffNode : PinNode,\n pinned ? 'pin-off' : 'pin',\n ))\n}\n\n/** Add an unmanaged native-styled row before the Session menu's archive tail. */\nexport function attachSessionMenuHost(menu: HTMLElement, sessionId: string): SessionMenuTarget | null {\n if (menu.hasAttribute(MENU_OWNER_ATTRIBUTE)) return null\n const viewport = [...menu.children].find((node): node is HTMLElement => (\n node instanceof HTMLElement && node.getAttribute('role') === 'presentation'\n ))\n if (viewport === undefined) return null\n const wrappers = [...viewport.children].filter((node): node is HTMLElement => (\n node instanceof HTMLElement\n && node.querySelector(':scope > button[role=\"menuitem\"]') instanceof HTMLButtonElement\n ))\n if (wrappers.length < 3 || wrappers.length > 4) return null\n const templateButton = wrappers[0]?.querySelector<HTMLButtonElement>(':scope > button[role=\"menuitem\"]')\n if (templateButton === null || templateButton === undefined) return null\n const spans = [...templateButton.children].filter((node): node is HTMLSpanElement => node instanceof HTMLSpanElement)\n if (spans.length < 2) return null\n\n const doc = menu.ownerDocument\n const host = doc.createElement('div')\n host.className = wrappers[0]?.className ?? ''\n host.setAttribute(MENU_HOST_ATTRIBUTE, '')\n const button = doc.createElement('button')\n button.type = 'button'\n button.setAttribute('role', 'menuitem')\n button.className = `${templateButton.className} dsh-pins-menu-button`\n const icon = doc.createElement('span')\n icon.className = spans[0]?.className ?? ''\n icon.setAttribute('aria-hidden', 'true')\n const label = doc.createElement('span')\n label.className = spans.at(-1)?.className ?? ''\n button.append(icon, label)\n host.appendChild(button)\n viewport.insertBefore(host, wrappers[2] ?? null)\n menu.setAttribute(MENU_OWNER_ATTRIBUTE, sessionId)\n\n const target = { host, menu, sessionId, button, icon, label }\n const view = doc.defaultView\n if (view !== null) view.dispatchEvent(new view.Event('resize'))\n return target\n}\n\n/** Restore useful keyboard focus after a pinned row removes itself. */\nexport function focusAfterPinnedRemoval(doc: Document, host: HTMLElement | null, removedIndex: number): boolean {\n const remaining = host === null ? [] : [...host.querySelectorAll<HTMLButtonElement>('.dsh-pins-open')]\n const next = remaining[Math.min(removedIndex, remaining.length - 1)]\n if (next !== undefined) {\n next.focus({ preventScroll: true })\n return true\n }\n const nativeRow = doc.querySelector<HTMLElement>(`${SIDEBAR_SLOT_SELECTOR} [role=\"treeitem\"][aria-selected=\"true\"]`)\n ?? doc.querySelector<HTMLElement>(`${SIDEBAR_SLOT_SELECTOR} [role=\"treeitem\"]`)\n if (nativeRow === null) return false\n const hadTabIndex = nativeRow.hasAttribute('tabindex')\n if (!hadTabIndex) nativeRow.tabIndex = -1\n nativeRow.focus({ preventScroll: true })\n if (doc.activeElement === nativeRow) return true\n if (!hadTabIndex) nativeRow.removeAttribute('tabindex')\n return false\n}\n\nexport function removeBridgeArtifacts(doc: Document): void {\n for (const node of doc.querySelectorAll(`[${PINNED_HOST_ATTRIBUTE}], [${MENU_HOST_ATTRIBUTE}]`)) node.remove()\n for (const menu of doc.querySelectorAll(`[${MENU_OWNER_ATTRIBUTE}]`)) menu.removeAttribute(MENU_OWNER_ATTRIBUTE)\n}\n","export const PIN_STORAGE_KEY = 'dsh.pinned-sessions.v1'\nconst MAX_PINS = 500\n\nexport interface PinRecord {\n readonly id: string\n readonly pinnedAt: number\n}\n\ninterface PersistedPins {\n readonly version: 1\n readonly pins: readonly PinRecord[]\n}\n\nexport interface StorageLike {\n getItem(key: string): string | null\n setItem(key: string, value: string): void\n}\n\nfunction isPinRecord(value: unknown): value is PinRecord {\n if (typeof value !== 'object' || value === null) return false\n const row = value as Record<string, unknown>\n return typeof row.id === 'string'\n && row.id.length > 0\n && Number.isFinite(row.pinnedAt)\n && (row.pinnedAt as number) >= 0\n}\n\n/** Decode, de-duplicate, and normalize one persisted pin snapshot. */\nexport function decodePins(raw: string | null): readonly PinRecord[] {\n if (raw === null) return []\n try {\n const parsed = JSON.parse(raw) as Partial<PersistedPins>\n if (parsed.version !== 1 || !Array.isArray(parsed.pins)) return []\n const byId = new Map<string, PinRecord>()\n for (const candidate of parsed.pins) {\n if (!isPinRecord(candidate)) continue\n const previous = byId.get(candidate.id)\n if (previous === undefined || candidate.pinnedAt > previous.pinnedAt) {\n byId.set(candidate.id, { id: candidate.id, pinnedAt: candidate.pinnedAt })\n }\n }\n return [...byId.values()]\n .sort((left, right) => right.pinnedAt - left.pinnedAt || left.id.localeCompare(right.id))\n .slice(0, MAX_PINS)\n } catch {\n return []\n }\n}\n\n/** Browser-local, versioned pin state with React-compatible subscriptions. */\nexport class PinStore {\n private snapshot: readonly PinRecord[]\n private readonly listeners = new Set<() => void>()\n\n constructor(private readonly storage: StorageLike | undefined) {\n this.snapshot = this.read()\n }\n\n readonly getSnapshot = (): readonly PinRecord[] => this.snapshot\n\n readonly subscribe = (listener: () => void): (() => void) => {\n this.listeners.add(listener)\n return () => { this.listeners.delete(listener) }\n }\n\n isPinned(id: string): boolean {\n return this.snapshot.some(row => row.id === id)\n }\n\n toggle(id: string, now = Date.now()): void {\n if (id.length === 0) return\n const without = this.snapshot.filter(row => row.id !== id)\n this.publish(this.isPinned(id) ? without : [{ id, pinnedAt: now }, ...without])\n }\n\n prune(keep: (id: string) => boolean): void {\n const next = this.snapshot.filter(row => keep(row.id))\n if (next.length !== this.snapshot.length) this.publish(next)\n }\n\n reload(): void {\n const next = this.read()\n if (samePins(this.snapshot, next)) return\n this.snapshot = next\n this.emit()\n }\n\n private read(): readonly PinRecord[] {\n try {\n return decodePins(this.storage?.getItem(PIN_STORAGE_KEY) ?? null)\n } catch {\n return []\n }\n }\n\n private publish(next: readonly PinRecord[]): void {\n this.snapshot = [...next]\n .sort((left, right) => right.pinnedAt - left.pinnedAt || left.id.localeCompare(right.id))\n .slice(0, MAX_PINS)\n try {\n this.storage?.setItem(PIN_STORAGE_KEY, JSON.stringify({ version: 1, pins: this.snapshot }))\n } catch {\n // Storage can be unavailable in hardened or quota-constrained browser profiles.\n }\n this.emit()\n }\n\n private emit(): void {\n for (const listener of [...this.listeners]) listener()\n }\n}\n\nfunction samePins(left: readonly PinRecord[], right: readonly PinRecord[]): boolean {\n return left.length === right.length\n && left.every((row, index) => row.id === right[index]?.id && row.pinnedAt === right[index]?.pinnedAt)\n}\n","interface SessionPresentationInput {\n readonly id: string\n readonly title?: string | undefined\n readonly cwd?: string | undefined\n}\n\nfunction nonBlank(value: string | undefined): string | undefined {\n const trimmed = value?.trim()\n return trimmed === undefined || trimmed.length === 0 ? undefined : trimmed\n}\n\n/** Match the native sidebar's useful fallback for sessions without a title. */\nexport function sessionDisplayTitle(\n session: SessionPresentationInput,\n workspaceTitle: string | undefined,\n): string {\n const explicit = nonBlank(session.title)\n if (explicit !== undefined) return explicit\n const workspace = nonBlank(workspaceTitle)\n if (workspace !== undefined) return workspace\n const cwd = nonBlank(session.cwd)\n if (cwd !== undefined) {\n const leaf = cwd.replace(/[\\\\/]+$/u, '').split(/[\\\\/]/u).at(-1)\n if (leaf !== undefined && leaf.length > 0) return leaf\n }\n return session.id\n}\n"],"mappings":"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","names":["import_react","defaultAttributes","defaultAttributes","Pin","defaultAttributes","createLucideIcon","Pin"],"file":"client.js"}
1
+ {"version":3,"sources":["../src/client/index.tsx","../node_modules/shared/src/utils.ts","../node_modules/lucide-react/src/defaultAttributes.ts","../node_modules/lucide-react/src/Icon.ts","../node_modules/lucide-react/src/createLucideIcon.ts","../node_modules/lucide-react/src/icons/archive.ts","../node_modules/lucide-react/src/icons/ellipsis.ts","../node_modules/lucide-react/src/icons/git-branch.ts","../node_modules/lucide-react/src/icons/pencil.ts","../node_modules/lucide-react/src/icons/pin-off.ts","../node_modules/lucide-react/src/icons/pin.ts","../node_modules/lucide-react/src/icons/trash-2.ts","../node_modules/lucide/src/defaultAttributes.ts","../node_modules/lucide/src/icons/pin-off.ts","../node_modules/lucide/src/icons/pin.ts","../src/client/dom-bridge.ts","../src/client/pin-store.ts","../src/client/presentation.ts"],"sourcesContent":["import {\n useEffect,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n useSyncExternalStore,\n type ReactNode,\n} from 'react'\nimport {\n Button,\n Menu,\n MenuItemButton,\n Modal,\n Toast,\n type MenuEntry,\n} from '@deepseek-ai/dsh-client-ui-primitives'\nimport { Pin, PinOff, Archive, GitBranch, Pencil, Ellipsis, Trash2 } from 'lucide-react'\nimport { createPortal } from 'react-dom'\nimport {\n attachSessionMenuHost,\n captureSessionId,\n ensurePinnedHost,\n findSessionActionTarget,\n findUnclaimedPortalMenu,\n focusAfterPinnedRemoval,\n listPortalMenus,\n MENU_OWNER_ATTRIBUTE,\n removeBridgeArtifacts,\n SIDEBAR_SLOT_SELECTOR,\n updateSessionMenuItem,\n type SessionMenuTarget,\n type TriggerRect,\n type SessionsForCapture,\n} from './dom-bridge.js'\nimport { PIN_STORAGE_KEY, PinStore } from './pin-store.js'\nimport { sessionDisplayTitle } from './presentation.js'\n\ninterface SessionSummaryLike {\n readonly id: string\n readonly title?: string | undefined\n readonly cwd?: string | undefined\n readonly blank?: boolean | undefined\n readonly running?: boolean | undefined\n readonly completed?: boolean | undefined\n}\n\ninterface SessionsSnapshotLike {\n readonly ids: readonly string[]\n readonly byId: Readonly<Record<string, SessionSummaryLike | undefined>>\n readonly current?: string | undefined\n readonly phase: string\n}\n\ninterface WorkspaceLike {\n readonly workspaceId: string\n readonly title: string\n readonly sessionIds: readonly string[]\n}\n\ninterface WorkspacesSnapshotLike {\n readonly items: readonly WorkspaceLike[]\n readonly archivedSessionIds: readonly string[]\n readonly phase: string\n}\n\ntype SelectorHook<T> = <S>(selector: (snapshot: T) => S, equal?: (left: S, right: S) => boolean) => S\ntype Translate = (key: string, params?: Readonly<Record<string, unknown>>) => string\n\ninterface SlotsLike {\n inject(name: string, install: () => unknown): void\n register<I, P>(\n entry: {\n readonly name: string\n readonly id: string\n readonly order?: number\n readonly locale?: string\n readonly inject?: () => I\n },\n component: (props: P) => ReactNode,\n ): () => void\n}\n\ninterface LocaleLike {\n register(namespace: string, dictionaries: Readonly<Record<string, Readonly<Record<string, string>>>>): () => void\n}\n\ninterface ResultLike {\n readonly ok: boolean\n readonly error?: { readonly message: string } | undefined\n}\n\ninterface ClientSessionsLike extends SessionsForCapture {\n binding(sessionId: string): { readonly session: { rename(title: string): Promise<ResultLike> } } | undefined\n fork(input: { readonly sessionId: string; readonly increaseTitle: boolean }): Promise<string>\n}\n\ninterface WorkspacesServiceLike {\n archiveSession(sessionId: string): Promise<void>\n}\n\ninterface DeleteSessionServiceLike {\n deleteSession(sessionId: string): Promise<ResultLike>\n}\n\ninterface BooleanStoreLike {\n readonly getSnapshot: () => boolean\n readonly subscribe: (listener: () => void) => () => void\n}\n\nclass BooleanStore implements BooleanStoreLike {\n private value = false\n private readonly listeners = new Set<() => void>()\n\n readonly getSnapshot = (): boolean => this.value\n readonly subscribe = (listener: () => void): (() => void) => {\n this.listeners.add(listener)\n return () => { this.listeners.delete(listener) }\n }\n\n set(value: boolean): void {\n if (value === this.value) return\n this.value = value\n for (const listener of this.listeners) listener()\n }\n}\n\ninterface ClientContextLike {\n readonly slots: SlotsLike\n readonly sessions: ClientSessionsLike\n readonly locale: LocaleLike\n get(name: string): unknown\n inject(dependencies: readonly string[], setup: (ctx: ClientContextLike) => void): unknown\n effect(setup: () => (() => void), label?: string): unknown\n}\n\nexport interface PinnedSessionActions {\n readonly openSession?: (sessionId: string) => void\n readonly renameSession: (sessionId: string, title: string) => Promise<void>\n readonly forkSession: (sessionId: string) => Promise<void>\n readonly archiveSession: (sessionId: string) => Promise<void>\n readonly deleteAvailability: BooleanStoreLike\n readonly deleteSession: (sessionId: string) => Promise<void>\n}\n\ninterface BridgeProps {\n readonly store: PinStore\n readonly sessions: SessionsForCapture\n readonly actions: PinnedSessionActions\n readonly useSessions: SelectorHook<SessionsSnapshotLike>\n readonly useWorkspaces: SelectorHook<WorkspacesSnapshotLike>\n readonly t: Translate\n readonly modernMenus?: BooleanStoreLike\n}\n\ninterface PinIconProps {\n readonly size?: number\n}\n\ninterface PendingMenuRequest {\n readonly sessionId: string\n readonly createdAt: number\n readonly existingMenus: ReadonlySet<HTMLElement>\n readonly triggerRect: TriggerRect\n}\n\ninterface ActiveMenuBinding {\n readonly target: SessionMenuTarget\n readonly onClick: (event: MouseEvent) => void\n}\n\ninterface PendingFocusRemoval {\n readonly sessionId: string\n readonly index: number\n}\n\nconst NS = 'pinnedSessions'\nconst STYLE_ID = '@anionex/dsh-pinned-sessions'\nconst MENU_ASSOCIATION_MS = 2_000\n\nconst zh = {\n 'menu.rename': '重命名',\n 'menu.fork': '分叉会话',\n 'menu.pin': '置顶到顶部分组',\n 'menu.unpin': '从顶部分组取消置顶',\n 'menu.archive': '归档会话',\n 'menu.delete': '删除会话',\n 'section.label': '置顶会话',\n 'session.open': '打开置顶会话“{name}”',\n 'session.actions': '置顶会话“{name}”的操作',\n 'session.archiveFailed': '归档会话失败:{detail}',\n 'session.forkFailed': '分叉会话失败:{detail}',\n 'session.unpin': '取消置顶“{name}”',\n 'dialog.close': '关闭',\n 'dialog.cancel': '取消',\n 'rename.title': '重命名会话',\n 'rename.field': '会话名称',\n 'rename.confirm': '重命名',\n 'delete.title': '删除会话',\n 'delete.description': '将永久删除会话“{name}”及其子代理(含正在运行的)和全部记录(对话内容、统计、缓存),此操作不可恢复。',\n 'delete.pending': '正在删除会话…',\n 'workspace.ungrouped': '未分组',\n}\n\nconst en = {\n 'menu.rename': 'Rename',\n 'menu.fork': 'Fork session',\n 'menu.pin': 'Pin to top section',\n 'menu.unpin': 'Unpin from top section',\n 'menu.archive': 'Archive session',\n 'menu.delete': 'Delete session',\n 'section.label': 'Pinned sessions',\n 'session.open': 'Open pinned session “{name}”',\n 'session.actions': 'Actions for pinned session “{name}”',\n 'session.archiveFailed': 'Could not archive session: {detail}',\n 'session.forkFailed': 'Could not fork session: {detail}',\n 'session.unpin': 'Unpin “{name}”',\n 'dialog.close': 'Close',\n 'dialog.cancel': 'Cancel',\n 'rename.title': 'Rename session',\n 'rename.field': 'Session name',\n 'rename.confirm': 'Rename',\n 'delete.title': 'Delete session',\n 'delete.description': 'This permanently deletes session “{name}”, its child agents (including any that are still running), and all of its records (conversation, stats, cache). This cannot be undone.',\n 'delete.pending': 'Deleting session…',\n 'workspace.ungrouped': 'Ungrouped',\n}\n\nconst styles = `\n[${'data-dsh-pinned-sessions-host'}]{box-sizing:border-box;min-width:0;flex:none}\n.dsh-pins-section{box-sizing:border-box;min-width:0;margin:0 4px 6px;padding:0 0 6px;border-bottom:1px solid var(--dsw-alias-border-l1)}\n.dsh-pins-header{display:flex;align-items:center;gap:6px;height:28px;padding:0 8px;color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:18px;font-weight:500}\n.dsh-pins-header svg{flex:none;color:var(--dsw-alias-state-business-primary)}\n.dsh-pins-list{box-sizing:border-box;max-height:192px;min-width:0;margin:0;padding:0;overflow-y:auto;overscroll-behavior:contain;list-style:none}\n.dsh-pins-row{box-sizing:border-box;display:flex;align-items:center;gap:0;height:32px;min-width:0;border-radius:6px;color:var(--dsw-alias-label-primary)}\n.dsh-pins-row:hover,.dsh-pins-row[data-current=\"true\"],.dsh-pins-row[data-menu-open=\"true\"]{background:var(--dsw-alias-interactive-bg-hover)}\n.dsh-pins-open{box-sizing:border-box;display:flex;align-items:center;gap:6px;min-width:0;height:32px;padding:0 4px 0 8px;border:0;background:transparent;color:inherit;cursor:pointer;flex:1;text-align:left}\n.dsh-pins-open:focus-visible,.dsh-pins-actions:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary);outline-offset:-2px}\n.dsh-pins-open>svg{flex:none;color:var(--dsw-alias-state-business-primary)}\n.dsh-pins-title{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:14px;line-height:20px;flex:1}\n.dsh-pins-workspace{max-width:34%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--dsw-alias-label-tertiary);font-size:11px;line-height:18px;flex:none}\n.dsh-pins-actions{display:inline-flex;align-items:center;justify-content:center;width:26px;height:26px;margin-right:3px;padding:0;border:0;border-radius:6px;background:transparent;color:var(--dsw-alias-label-tertiary);cursor:pointer;opacity:0;pointer-events:none;flex:none}\n.dsh-pins-row:hover .dsh-pins-actions,.dsh-pins-row:focus-within .dsh-pins-actions,.dsh-pins-row[data-menu-open=\"true\"] .dsh-pins-actions{opacity:1;pointer-events:auto}\n.dsh-pins-actions:hover,.dsh-pins-row[data-menu-open=\"true\"] .dsh-pins-actions{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}\n.dsh-pins-action-menu{display:inline-flex;flex:none}\n.dsh-pins-rename-input{box-sizing:border-box;width:100%;height:36px;padding:0 11px;border:1px solid var(--dsw-alias-border-l2);border-radius:8px;outline:0;background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-primary);font:inherit}\n.dsh-pins-rename-input:focus{border-color:var(--dsw-alias-state-business-primary)}\n.dsh-pins-dialog-error{margin-top:8px;color:var(--dsw-alias-state-error-primary);font-size:12px;line-height:18px}\n.dsh-pins-dialog-status{color:var(--dsw-alias-label-secondary);font-size:12px;line-height:18px}\n.dsh-pins-delete-action{color:var(--dsw-alias-state-error-primary)!important;border-color:var(--dsw-alias-state-error-primary)!important}\n@media (max-width:767px){.dsh-pins-workspace{display:none}}\n@media (hover:none),(max-width:767px){.dsh-pins-actions{opacity:1;pointer-events:auto}}\n`\n\nexport const inject = ['slots', 'sessions', 'workspaces', 'locale']\n\nfunction deleteSessionService(ctx: ClientContextLike): DeleteSessionServiceLike | null {\n try {\n const service = ctx.get('remote.workspaceRegistry') as Partial<DeleteSessionServiceLike> | undefined\n return typeof service?.deleteSession === 'function' ? service as DeleteSessionServiceLike : null\n } catch {\n return null\n }\n}\n\nfunction makePinnedSessionActions(ctx: ClientContextLike, deleteAvailability: BooleanStoreLike): PinnedSessionActions {\n const workspaces = ctx.get('workspaces') as WorkspacesServiceLike\n return {\n renameSession: async (sessionId, title) => {\n const session = ctx.sessions.binding(sessionId)?.session\n if (session === undefined) throw new Error(`unknown session \"${sessionId}\"`)\n const result = await session.rename(title)\n if (!result.ok) throw new Error(result.error?.message ?? 'Session rename failed')\n },\n forkSession: async sessionId => {\n const childId = await ctx.sessions.fork({ sessionId, increaseTitle: true })\n ctx.sessions.open(childId)\n },\n archiveSession: async sessionId => { await workspaces.archiveSession(sessionId) },\n deleteAvailability,\n deleteSession: async sessionId => {\n const service = deleteSessionService(ctx)\n if (service === null) throw new Error('Session deletion is unavailable')\n const result = await service.deleteSession(sessionId)\n if (!result.ok) throw new Error(result.error?.message ?? 'Session deletion failed')\n },\n }\n}\n\n/** Register the lifecycle bridge in the additive frame overlay slot. */\nexport function apply(ctx: ClientContextLike): void {\n let storage: Storage | undefined\n try {\n storage = window.localStorage\n } catch {\n storage = undefined\n }\n const store = new PinStore(storage)\n const deleteAvailability = new BooleanStore()\n const actions = makePinnedSessionActions(ctx, deleteAvailability)\n const modernMenus = new BooleanStore()\n let openSession = (sessionId: string): void => { ctx.sessions.open(sessionId) }\n const navigationActions = {\n ...actions,\n openSession: (id: string) => { openSession(id) },\n forkSession: async (id: string) => { openSession(await ctx.sessions.fork({ sessionId: id, increaseTitle: true })) },\n }\n ctx.inject(['uiWorkspace'], navigation => {\n const service = navigation.get('uiWorkspace') as { openSession(id: string): void }\n openSession = id => { service.openSession(id) }\n navigation.effect(() => () => { openSession = id => { ctx.sessions.open(id) } })\n })\n\n ctx.slots.inject('sidebar.workspaces.session.menu.item', () => {\n modernMenus.set(true)\n const dispose = ctx.slots.register({\n name: 'sidebar.workspaces.session.menu.item', id: 'pinned-sessions', order: 90, locale: NS,\n inject: () => ({ store }),\n }, PinTopSectionMenuItem)\n return () => { dispose(); modernMenus.set(false) }\n })\n\n ctx.inject(['remote.workspaceRegistry'], serviceCtx => {\n const available = deleteSessionService(serviceCtx) !== null\n deleteAvailability.set(available)\n serviceCtx.effect(() => () => { deleteAvailability.set(false) }, 'pinned-sessions: delete capability')\n })\n\n ctx.effect(() => {\n const onStorage = (event: StorageEvent): void => {\n if (event.key === PIN_STORAGE_KEY || event.key === null) store.reload()\n }\n window.addEventListener('storage', onStorage)\n return () => { window.removeEventListener('storage', onStorage) }\n }, 'pinned-sessions: cross-tab state')\n\n ctx.effect(() => {\n if (document.querySelector(`style[data-plugin-css=\"${STYLE_ID}\"]`) !== null) return () => {}\n const tag = document.createElement('style')\n tag.dataset.plugin = '@anionex/dsh-pinned-sessions'\n tag.dataset.pluginCss = STYLE_ID\n tag.textContent = styles\n document.head.appendChild(tag)\n return () => { tag.remove() }\n }, 'pinned-sessions: styles')\n\n ctx.effect(() => ctx.locale.register(NS, { zh, en }), 'pinned-sessions: dictionaries')\n\n ctx.slots.inject('shell.overlay', () => ctx.slots.register({\n name: 'shell.overlay',\n id: 'pinned-sessions-bridge',\n order: 40,\n locale: NS,\n inject: () => ({ store, sessions: ctx.sessions, actions: navigationActions, modernMenus }),\n }, PinnedSessionsBridge))\n}\n\n/** The official 0.2 menu slot supplies the exact Session identity. */\nfunction PinTopSectionMenuItem({ sessionId, store, useMenuOpenState, t }: {\n sessionId: string\n store: PinStore\n useMenuOpenState: () => [boolean, (open: boolean) => void]\n t: Translate\n}): ReactNode {\n useSyncExternalStore(store.subscribe, store.getSnapshot, store.getSnapshot)\n const [, setMenuOpen] = useMenuOpenState()\n const pinned = store.isPinned(sessionId)\n return <MenuItemButton icon={<PinIcon />} onSelect={() => { store.toggle(sessionId); setMenuOpen(false) }}>\n {t(pinned ? 'menu.unpin' : 'menu.pin')}\n </MenuItemButton>\n}\n\n/** Keep native behavior intact while mounting the sidebar portal and unmanaged menu item. */\nexport function PinnedSessionsBridge({ store, sessions, actions, useSessions, useWorkspaces, t, modernMenus }: BridgeProps): ReactNode {\n const sessionSnapshot = useSessions(snapshot => snapshot)\n const workspaceSnapshot = useWorkspaces(snapshot => snapshot)\n const pins = useSyncExternalStore(store.subscribe, store.getSnapshot, store.getSnapshot)\n const [sidebarHost, setSidebarHost] = useState<HTMLDivElement | null>(null)\n const [sidebarWide, setSidebarWide] = useState(true)\n const pending = useRef<PendingMenuRequest | null>(null)\n const activeMenu = useRef<ActiveMenuBinding | null>(null)\n const focusAfterRemoval = useRef<PendingFocusRemoval | null>(null)\n\n useLayoutEffect(() => {\n let active = true\n let queued = false\n let settleTimer: number | undefined\n let observedSidebar: Element | null = null\n const sidebarObserver = new MutationObserver(() => { queueRefresh() })\n\n const disposeActiveMenu = (): void => {\n const binding = activeMenu.current\n if (binding === null) return\n activeMenu.current = null\n binding.target.button.removeEventListener('click', binding.onClick)\n binding.target.host.remove()\n if (binding.target.menu.getAttribute(MENU_OWNER_ATTRIBUTE) === binding.target.sessionId) {\n binding.target.menu.removeAttribute(MENU_OWNER_ATTRIBUTE)\n }\n }\n const updateActiveMenu = (): void => {\n const binding = activeMenu.current\n if (binding === null) return\n const pinned = store.isPinned(binding.target.sessionId)\n updateSessionMenuItem(binding.target, pinned, t(pinned ? 'menu.unpin' : 'menu.pin'))\n }\n const observeSidebar = (): void => {\n const slot = document.querySelector(SIDEBAR_SLOT_SELECTOR)\n if (slot === observedSidebar) return\n sidebarObserver.disconnect()\n observedSidebar = slot\n if (slot !== null) {\n sidebarObserver.observe(slot, {\n attributes: true,\n attributeFilter: ['class', 'style'],\n childList: true,\n subtree: true,\n })\n }\n }\n const refresh = (): void => {\n if (!active) return\n const nextHost = ensurePinnedHost(document)\n setSidebarHost(current => current === nextHost ? current : nextHost)\n observeSidebar()\n const rootWidth = nextHost?.parentElement?.getBoundingClientRect().width\n if (rootWidth !== undefined) setSidebarWide(rootWidth >= 160)\n\n const binding = activeMenu.current\n if (binding !== null && (!binding.target.host.isConnected || !binding.target.menu.isConnected)) {\n disposeActiveMenu()\n }\n const request = pending.current\n if (request === null) return\n if (Date.now() - request.createdAt > MENU_ASSOCIATION_MS) {\n pending.current = null\n return\n }\n const menu = findUnclaimedPortalMenu(document, request.existingMenus, request.triggerRect)\n if (menu === null) return\n const target = attachSessionMenuHost(menu, request.sessionId)\n if (target === null) return\n const onClick = (event: MouseEvent): void => {\n event.preventDefault()\n event.stopPropagation()\n store.toggle(target.sessionId)\n disposeActiveMenu()\n document.dispatchEvent(new KeyboardEvent('keydown', { key: 'Escape', bubbles: true }))\n }\n target.button.addEventListener('click', onClick)\n activeMenu.current = { target, onClick }\n pending.current = null\n updateActiveMenu()\n }\n function queueRefresh(): void {\n if (!active) return\n if (settleTimer === undefined) {\n settleTimer = window.setTimeout(() => {\n settleTimer = undefined\n refresh()\n }, 250)\n }\n if (queued) return\n queued = true\n queueMicrotask(() => {\n queued = false\n refresh()\n })\n }\n const onClickCapture = (event: MouseEvent): void => {\n pending.current = null\n if (modernMenus?.getSnapshot()) return\n const target = findSessionActionTarget(event.target)\n if (target === null) return\n const sessionId = captureSessionId(target.row, sessions)\n if (sessionId === null) return\n const rect = target.button.getBoundingClientRect()\n pending.current = {\n sessionId,\n createdAt: Date.now(),\n existingMenus: new Set(listPortalMenus(document)),\n triggerRect: {\n top: rect.top,\n right: rect.right,\n bottom: rect.bottom,\n left: rect.left,\n width: rect.width,\n height: rect.height,\n },\n }\n queueRefresh()\n }\n const onKeyDownCapture = (): void => { pending.current = null }\n\n refresh()\n document.addEventListener('click', onClickCapture, true)\n document.addEventListener('keydown', onKeyDownCapture, true)\n const bodyObserver = new MutationObserver(() => { queueRefresh() })\n bodyObserver.observe(document.body, { childList: true })\n const unsubscribe = store.subscribe(updateActiveMenu)\n return () => {\n active = false\n pending.current = null\n if (settleTimer !== undefined) window.clearTimeout(settleTimer)\n unsubscribe()\n bodyObserver.disconnect()\n sidebarObserver.disconnect()\n document.removeEventListener('click', onClickCapture, true)\n document.removeEventListener('keydown', onKeyDownCapture, true)\n disposeActiveMenu()\n removeBridgeArtifacts(document)\n }\n }, [sessions, store, t, modernMenus])\n\n useLayoutEffect(() => {\n if (sidebarHost === null) return\n const root = sidebarHost.parentElement\n if (root === null) return\n const update = (): void => { setSidebarWide(root.getBoundingClientRect().width >= 160) }\n update()\n if (typeof ResizeObserver === 'undefined') return\n const observer = new ResizeObserver(update)\n observer.observe(root)\n return () => { observer.disconnect() }\n }, [sidebarHost])\n\n useEffect(() => {\n if (sessionSnapshot.phase !== 'ready' || workspaceSnapshot.phase !== 'ready') return\n const valid = new Set(sessionSnapshot.ids)\n const archived = new Set(workspaceSnapshot.archivedSessionIds)\n store.prune(sessionId => valid.has(sessionId) && !archived.has(sessionId))\n }, [sessionSnapshot, store, workspaceSnapshot])\n\n const rows = useMemo(() => {\n const workspaceBySession = new Map<string, string>()\n for (const workspace of workspaceSnapshot.items) {\n for (const sessionId of workspace.sessionIds) {\n if (!workspaceBySession.has(sessionId)) workspaceBySession.set(sessionId, workspace.title)\n }\n }\n return pins.flatMap(pin => {\n const session = sessionSnapshot.byId[pin.id]\n if (session === undefined || session.blank === true) return []\n const workspaceTitle = workspaceBySession.get(pin.id)\n const workspace = workspaceTitle ?? t('workspace.ungrouped')\n return [{ session, title: sessionDisplayTitle(session, workspaceTitle), workspace }]\n })\n }, [pins, sessionSnapshot.byId, t, workspaceSnapshot.items])\n\n useLayoutEffect(() => {\n const pendingRemoval = focusAfterRemoval.current\n if (pendingRemoval === null || rows.some(row => row.session.id === pendingRemoval.sessionId)) return\n focusAfterRemoval.current = null\n focusAfterPinnedRemoval(document, sidebarHost, pendingRemoval.index)\n }, [rows, sidebarHost])\n\n return sidebarHost !== null && sidebarHost.isConnected && sidebarWide && rows.length > 0\n ? createPortal(\n <PinnedSessionSection\n actions={actions}\n cancelRemoval={sessionId => {\n if (focusAfterRemoval.current?.sessionId === sessionId) focusAfterRemoval.current = null\n }}\n currentId={sessionSnapshot.current}\n rows={rows}\n open={sessionId => { if (actions.openSession) actions.openSession(sessionId); else sessions.open(sessionId) }}\n prepareRemoval={(sessionId, index) => {\n focusAfterRemoval.current = { sessionId, index }\n }}\n unpin={(sessionId, index) => {\n focusAfterRemoval.current = { sessionId, index }\n store.toggle(sessionId)\n }}\n t={t}\n />,\n sidebarHost,\n )\n : null\n}\n\ninterface PinnedSessionSectionProps {\n readonly actions: PinnedSessionActions\n readonly cancelRemoval: (sessionId: string) => void\n readonly currentId?: string | undefined\n readonly rows: readonly { readonly session: SessionSummaryLike; readonly title: string; readonly workspace: string }[]\n readonly open: (sessionId: string) => void\n readonly prepareRemoval: (sessionId: string, index: number) => void\n readonly unpin: (sessionId: string, index: number) => void\n readonly t: Translate\n}\n\nfunction PinnedSessionSection({ actions, cancelRemoval, currentId, rows, open, prepareRemoval, unpin, t }: PinnedSessionSectionProps): ReactNode {\n return <section className=\"dsh-pins-section\" aria-label={t('section.label')}>\n <div className=\"dsh-pins-header\">\n <PinIcon size={13} />\n <span>{t('section.label')}</span>\n </div>\n <ul className=\"dsh-pins-list\">\n {rows.map(({ session, title, workspace }, index) => <PinnedSessionRow\n actions={actions}\n cancelRemoval={cancelRemoval}\n current={session.id === currentId}\n index={index}\n key={session.id}\n open={open}\n prepareRemoval={prepareRemoval}\n session={session}\n t={t}\n title={title}\n unpin={unpin}\n workspace={workspace}\n />)}\n </ul>\n </section>\n}\n\ninterface PinnedSessionRowProps {\n readonly actions: PinnedSessionActions\n readonly cancelRemoval: (sessionId: string) => void\n readonly current: boolean\n readonly index: number\n readonly open: (sessionId: string) => void\n readonly prepareRemoval: (sessionId: string, index: number) => void\n readonly session: SessionSummaryLike\n readonly t: Translate\n readonly title: string\n readonly unpin: (sessionId: string, index: number) => void\n readonly workspace: string\n}\n\nfunction PinnedSessionRow({ actions, cancelRemoval, current, index, open, prepareRemoval, session, t, title, unpin, workspace }: PinnedSessionRowProps): ReactNode {\n const [menuOpen, setMenuOpen] = useState(false)\n const [renameOpen, setRenameOpen] = useState(false)\n const [renameDraft, setRenameDraft] = useState('')\n const [renaming, setRenaming] = useState(false)\n const [renameError, setRenameError] = useState<string | null>(null)\n const [deleteOpen, setDeleteOpen] = useState(false)\n const [deleting, setDeleting] = useState(false)\n const [deleteError, setDeleteError] = useState<string | null>(null)\n const [actionToast, setActionToast] = useState<{ readonly text: string; readonly seq: number } | null>(null)\n const toastSeq = useRef(0)\n const composing = useRef(false)\n const trigger = useRef<HTMLButtonElement | null>(null)\n const menusBeforeOpen = useRef<ReadonlySet<HTMLElement>>(new Set())\n const focusMenuEdge = useRef<'first' | 'last' | null>(null)\n const actionLabel = t('session.actions', { name: title })\n const renameTrimmed = renameDraft.trim()\n const renameBlocked = renaming || renameTrimmed === ''\n const canDelete = useSyncExternalStore(\n actions.deleteAvailability.subscribe,\n actions.deleteAvailability.getSnapshot,\n actions.deleteAvailability.getSnapshot,\n )\n const showDesktopActionError = (key: string, reason: unknown): void => {\n if (!canDelete) return\n toastSeq.current += 1\n setActionToast({\n text: t(key, { detail: reason instanceof Error ? reason.message : String(reason) }),\n seq: toastSeq.current,\n })\n }\n\n const restoreTriggerFocus = (): void => {\n queueMicrotask(() => { trigger.current?.focus({ preventScroll: true }) })\n }\n const openActionMenu = (focusEdge: 'first' | 'last' | null): void => {\n menusBeforeOpen.current = new Set(document.querySelectorAll<HTMLElement>('[role=\"menu\"]'))\n focusMenuEdge.current = focusEdge\n setMenuOpen(true)\n }\n\n useLayoutEffect(() => {\n if (!menuOpen) return\n let menu: HTMLElement | undefined\n let observer: MutationObserver | undefined\n let disposed = false\n const items = (): HTMLButtonElement[] => menu === undefined\n ? []\n : [...menu.querySelectorAll<HTMLButtonElement>('[role=\"menuitem\"]:not(:disabled)')]\n const onMenuKeyDown = (event: KeyboardEvent): void => {\n if (!['ArrowDown', 'ArrowUp', 'Home', 'End'].includes(event.key)) return\n const available = items()\n if (available.length === 0) return\n const currentIndex = available.indexOf(document.activeElement as HTMLButtonElement)\n let nextIndex: number\n if (event.key === 'Home') nextIndex = 0\n else if (event.key === 'End') nextIndex = available.length - 1\n else if (event.key === 'ArrowDown') nextIndex = currentIndex < 0 ? 0 : (currentIndex + 1) % available.length\n else nextIndex = currentIndex <= 0 ? available.length - 1 : currentIndex - 1\n event.preventDefault()\n available[nextIndex]?.focus({ preventScroll: true })\n }\n const onDocumentKeyDown = (event: KeyboardEvent): void => {\n if (event.key === 'Escape') restoreTriggerFocus()\n }\n const install = (): void => {\n if (disposed) return\n menu = [...document.querySelectorAll<HTMLElement>('[role=\"menu\"]')]\n .find(candidate => !menusBeforeOpen.current.has(candidate))\n if (menu === undefined) return\n observer?.disconnect()\n menu.addEventListener('keydown', onMenuKeyDown)\n const edge = focusMenuEdge.current\n focusMenuEdge.current = null\n if (edge === null) return\n const available = items()\n const target = edge === 'first' ? available[0] : available.at(-1)\n queueMicrotask(() => {\n if (!disposed && target?.isConnected === true) target.focus({ preventScroll: true })\n })\n }\n document.addEventListener('keydown', onDocumentKeyDown, true)\n install()\n if (menu === undefined) {\n observer = new MutationObserver(install)\n observer.observe(document.body, { childList: true, subtree: true })\n install()\n }\n return () => {\n disposed = true\n observer?.disconnect()\n menu?.removeEventListener('keydown', onMenuKeyDown)\n document.removeEventListener('keydown', onDocumentKeyDown, true)\n }\n }, [menuOpen])\n\n const menuItems: MenuEntry[] = [\n { id: 'rename', label: t('menu.rename'), icon: <Pencil size={16} /> },\n { id: 'fork', label: t('menu.fork'), icon: <GitBranch size={16} /> },\n { id: 'unpin', label: t('menu.unpin'), icon: <PinOff size={16} strokeWidth={1.8} aria-hidden=\"true\" /> },\n { id: 'archive', label: t('menu.archive'), icon: <Archive size={16} /> },\n ...(canDelete ? [{ id: 'delete', label: t('menu.delete'), icon: <Trash2 size={16} />, danger: true }] : []),\n ]\n\n const closeRename = (): void => {\n if (renaming) return\n setRenameOpen(false)\n setRenameError(null)\n restoreTriggerFocus()\n }\n const confirmRename = (): void => {\n if (renameBlocked) return\n setRenaming(true)\n setRenameError(null)\n void actions.renameSession(session.id, renameTrimmed).then(() => {\n setRenaming(false)\n setRenameOpen(false)\n restoreTriggerFocus()\n }).catch(reason => {\n setRenaming(false)\n setRenameError(reason instanceof Error ? reason.message : String(reason))\n })\n }\n const closeDelete = (): void => {\n if (deleting) return\n setDeleteOpen(false)\n setDeleteError(null)\n restoreTriggerFocus()\n }\n const confirmDelete = (): void => {\n if (deleting) return\n prepareRemoval(session.id, index)\n setDeleting(true)\n setDeleteError(null)\n void actions.deleteSession(session.id).then(() => {\n setDeleting(false)\n setDeleteOpen(false)\n restoreTriggerFocus()\n }).catch(reason => {\n cancelRemoval(session.id)\n setDeleting(false)\n setDeleteError(reason instanceof Error ? reason.message : String(reason))\n })\n }\n const onSelect = (id: string): void => {\n setMenuOpen(false)\n if (id === 'rename') {\n setRenameDraft(session.title ?? title)\n setRenameError(null)\n setRenameOpen(true)\n }\n if (id === 'fork') {\n restoreTriggerFocus()\n void actions.forkSession(session.id).catch(reason => {\n showDesktopActionError('session.forkFailed', reason)\n })\n }\n if (id === 'unpin') unpin(session.id, index)\n if (id === 'archive') {\n prepareRemoval(session.id, index)\n restoreTriggerFocus()\n void actions.archiveSession(session.id).catch(reason => {\n cancelRemoval(session.id)\n restoreTriggerFocus()\n showDesktopActionError('session.archiveFailed', reason)\n if (!canDelete) console.warn('session archive rejected:', reason)\n })\n }\n if (id === 'delete' && canDelete) {\n setDeleteError(null)\n setDeleteOpen(true)\n }\n }\n\n return <>\n <li\n className=\"dsh-pins-row\"\n data-current={current ? 'true' : 'false'}\n data-menu-open={menuOpen ? 'true' : undefined}\n >\n <button\n type=\"button\"\n className=\"dsh-pins-open\"\n aria-current={current ? 'page' : undefined}\n aria-label={t('session.open', { name: title })}\n onClick={() => { open(session.id) }}\n >\n <PinIcon size={13} />\n <span className=\"dsh-pins-title\">{title}</span>\n <span className=\"dsh-pins-workspace\">{workspace}</span>\n </button>\n <Menu\n className=\"dsh-pins-action-menu\"\n open={menuOpen}\n onClose={() => { setMenuOpen(false) }}\n items={menuItems}\n onSelect={onSelect}\n portal\n closeOnPointerLeave\n anchor={<button\n ref={trigger}\n type=\"button\"\n className=\"dsh-pins-actions\"\n aria-expanded={menuOpen}\n aria-haspopup=\"menu\"\n aria-label={actionLabel}\n title={actionLabel}\n onClick={event => {\n event.stopPropagation()\n if (menuOpen) setMenuOpen(false)\n else openActionMenu(null)\n }}\n onKeyDown={event => {\n if (event.key !== 'ArrowDown' && event.key !== 'ArrowUp') return\n event.preventDefault()\n openActionMenu(event.key === 'ArrowDown' ? 'first' : 'last')\n }}\n >\n <Ellipsis size={16} />\n </button>}\n />\n </li>\n <Modal\n open={renameOpen}\n onClose={closeRename}\n closeLabel={t('dialog.close')}\n title={t('rename.title')}\n footer={<>\n <Button variant=\"outline\" disabled={renaming} onClick={closeRename}>{t('dialog.cancel')}</Button>\n <Button variant=\"primary\" disabled={renameBlocked} onClick={confirmRename}>{t('rename.confirm')}</Button>\n </>}\n >\n <input\n className=\"dsh-pins-rename-input\"\n value={renameDraft}\n aria-label={t('rename.field')}\n autoFocus\n disabled={renaming}\n onFocus={event => { event.currentTarget.select() }}\n onChange={event => {\n setRenameDraft(event.currentTarget.value)\n setRenameError(null)\n }}\n onCompositionStart={() => { composing.current = true }}\n onCompositionEnd={() => { composing.current = false }}\n onKeyDown={event => {\n if (event.key !== 'Enter' || composing.current) return\n event.preventDefault()\n confirmRename()\n }}\n />\n {renameError !== null && <div className=\"dsh-pins-dialog-error\" role=\"alert\">{renameError}</div>}\n </Modal>\n <Modal\n open={deleteOpen}\n onClose={closeDelete}\n closeLabel={t('dialog.close')}\n title={t('delete.title')}\n description={t('delete.description', { name: title })}\n footer={<>\n <Button variant=\"outline\" autoFocus disabled={deleting} onClick={closeDelete}>{t('dialog.cancel')}</Button>\n <Button variant=\"outline\" className=\"dsh-pins-delete-action\" disabled={deleting} onClick={confirmDelete}>{t('delete.title')}</Button>\n </>}\n >\n {deleting && <div className=\"dsh-pins-dialog-status\" role=\"status\">{t('delete.pending')}</div>}\n {deleteError !== null && <div className=\"dsh-pins-dialog-error\" role=\"alert\">{deleteError}</div>}\n </Modal>\n {actionToast !== null && <Toast\n key={actionToast.seq}\n text={actionToast.text}\n onDone={() => { setActionToast(null) }}\n />}\n </>\n}\n\nfunction PinIcon({ size = 16 }: PinIconProps): ReactNode {\n return <Pin size={size} strokeWidth={1.8} aria-hidden=\"true\" />\n}\n","import { CamelToPascal } from './utility-types';\n\n/**\n * Converts string to kebab case\n *\n * @param {string} string\n * @returns {string} A kebabized string\n */\nexport const toKebabCase = (string: string) =>\n string.replace(/([a-z0-9])([A-Z])/g, '$1-$2').toLowerCase();\n\n/**\n * Converts string to camel case\n *\n * @param {string} string\n * @returns {string} A camelized string\n */\nexport const toCamelCase = <T extends string>(string: T) =>\n string.replace(/^([A-Z])|[\\s-_]+(\\w)/g, (match, p1, p2) =>\n p2 ? p2.toUpperCase() : p1.toLowerCase(),\n );\n\n/**\n * Converts string to pascal case\n *\n * @param {string} string\n * @returns {string} A pascalized string\n */\nexport const toPascalCase = <T extends string>(string: T): CamelToPascal<T> => {\n const camelCase = toCamelCase(string);\n\n return (camelCase.charAt(0).toUpperCase() + camelCase.slice(1)) as CamelToPascal<T>;\n};\n\n/**\n * Merges classes into a single string\n *\n * @param {array} classes\n * @returns {string} A string of classes\n */\nexport const mergeClasses = <ClassType = string | undefined | null>(...classes: ClassType[]) =>\n classes\n .filter((className, index, array) => {\n return (\n Boolean(className) &&\n (className as string).trim() !== '' &&\n array.indexOf(className) === index\n );\n })\n .join(' ')\n .trim();\n","export default {\n xmlns: 'http://www.w3.org/2000/svg',\n width: 24,\n height: 24,\n viewBox: '0 0 24 24',\n fill: 'none',\n stroke: 'currentColor',\n strokeWidth: 2,\n strokeLinecap: 'round',\n strokeLinejoin: 'round',\n};\n","import { createElement, forwardRef } from 'react';\nimport defaultAttributes from './defaultAttributes';\nimport { IconNode, LucideProps } from './types';\nimport { mergeClasses } from '@lucide/shared';\n\ninterface IconComponentProps extends LucideProps {\n iconNode: IconNode;\n}\n\n/**\n * Lucide icon component\n *\n * @component Icon\n * @param {object} props\n * @param {string} props.color - The color of the icon\n * @param {number} props.size - The size of the icon\n * @param {number} props.strokeWidth - The stroke width of the icon\n * @param {boolean} props.absoluteStrokeWidth - Whether to use absolute stroke width\n * @param {string} props.className - The class name of the icon\n * @param {IconNode} props.children - The children of the icon\n * @param {IconNode} props.iconNode - The icon node of the icon\n *\n * @returns {ForwardRefExoticComponent} LucideIcon\n */\nconst Icon = forwardRef<SVGSVGElement, IconComponentProps>(\n (\n {\n color = 'currentColor',\n size = 24,\n strokeWidth = 2,\n absoluteStrokeWidth,\n className = '',\n children,\n iconNode,\n ...rest\n },\n ref,\n ) => {\n return createElement(\n 'svg',\n {\n ref,\n ...defaultAttributes,\n width: size,\n height: size,\n stroke: color,\n strokeWidth: absoluteStrokeWidth ? (Number(strokeWidth) * 24) / Number(size) : strokeWidth,\n className: mergeClasses('lucide', className),\n ...rest,\n },\n [\n ...iconNode.map(([tag, attrs]) => createElement(tag, attrs)),\n ...(Array.isArray(children) ? children : [children]),\n ],\n );\n },\n);\n\nexport default Icon;\n","import { createElement, forwardRef } from 'react';\nimport { mergeClasses, toKebabCase } from '@lucide/shared';\nimport { IconNode, LucideProps } from './types';\nimport Icon from './Icon';\n\n/**\n * Create a Lucide icon component\n * @param {string} iconName\n * @param {array} iconNode\n * @returns {ForwardRefExoticComponent} LucideIcon\n */\nconst createLucideIcon = (iconName: string, iconNode: IconNode) => {\n const Component = forwardRef<SVGSVGElement, LucideProps>(({ className, ...props }, ref) =>\n createElement(Icon, {\n ref,\n iconNode,\n className: mergeClasses(`lucide-${toKebabCase(iconName)}`, className),\n ...props,\n }),\n );\n\n Component.displayName = `${iconName}`;\n\n return Component;\n};\n\nexport default createLucideIcon;\n","import createLucideIcon from '../createLucideIcon';\n\n/**\n * @component @name Archive\n * @description Lucide SVG icon component, renders SVG Element with children.\n *\n * @preview ![img](data:image/svg+xml;base64,PHN2ZyAgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIgogIHdpZHRoPSIyNCIKICBoZWlnaHQ9IjI0IgogIHZpZXdCb3g9IjAgMCAyNCAyNCIKICBmaWxsPSJub25lIgogIHN0cm9rZT0iIzAwMCIgc3R5bGU9ImJhY2tncm91bmQtY29sb3I6ICNmZmY7IGJvcmRlci1yYWRpdXM6IDJweCIKICBzdHJva2Utd2lkdGg9IjIiCiAgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIgogIHN0cm9rZS1saW5lam9pbj0icm91bmQiCj4KICA8cmVjdCB3aWR0aD0iMjAiIGhlaWdodD0iNSIgeD0iMiIgeT0iMyIgcng9IjEiIC8+CiAgPHBhdGggZD0iTTQgOHYxMWEyIDIgMCAwIDAgMiAyaDEyYTIgMiAwIDAgMCAyLTJWOCIgLz4KICA8cGF0aCBkPSJNMTAgMTJoNCIgLz4KPC9zdmc+Cg==) - https://lucide.dev/icons/archive\n * @see https://lucide.dev/guide/packages/lucide-react - Documentation\n *\n * @param {Object} props - Lucide icons props and any valid SVG attribute\n * @returns {JSX.Element} JSX Element\n *\n */\nconst Archive = createLucideIcon('Archive', [\n ['rect', { width: '20', height: '5', x: '2', y: '3', rx: '1', key: '1wp1u1' }],\n ['path', { d: 'M4 8v11a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8', key: '1s80jp' }],\n ['path', { d: 'M10 12h4', key: 'a56b0p' }],\n]);\n\nexport default Archive;\n","import createLucideIcon from '../createLucideIcon';\n\n/**\n * @component @name Ellipsis\n * @description Lucide SVG icon component, renders SVG Element with children.\n *\n * @preview ![img](data:image/svg+xml;base64,PHN2ZyAgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIgogIHdpZHRoPSIyNCIKICBoZWlnaHQ9IjI0IgogIHZpZXdCb3g9IjAgMCAyNCAyNCIKICBmaWxsPSJub25lIgogIHN0cm9rZT0iIzAwMCIgc3R5bGU9ImJhY2tncm91bmQtY29sb3I6ICNmZmY7IGJvcmRlci1yYWRpdXM6IDJweCIKICBzdHJva2Utd2lkdGg9IjIiCiAgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIgogIHN0cm9rZS1saW5lam9pbj0icm91bmQiCj4KICA8Y2lyY2xlIGN4PSIxMiIgY3k9IjEyIiByPSIxIiAvPgogIDxjaXJjbGUgY3g9IjE5IiBjeT0iMTIiIHI9IjEiIC8+CiAgPGNpcmNsZSBjeD0iNSIgY3k9IjEyIiByPSIxIiAvPgo8L3N2Zz4K) - https://lucide.dev/icons/ellipsis\n * @see https://lucide.dev/guide/packages/lucide-react - Documentation\n *\n * @param {Object} props - Lucide icons props and any valid SVG attribute\n * @returns {JSX.Element} JSX Element\n *\n */\nconst Ellipsis = createLucideIcon('Ellipsis', [\n ['circle', { cx: '12', cy: '12', r: '1', key: '41hilf' }],\n ['circle', { cx: '19', cy: '12', r: '1', key: '1wjl8i' }],\n ['circle', { cx: '5', cy: '12', r: '1', key: '1pcz8c' }],\n]);\n\nexport default Ellipsis;\n","import createLucideIcon from '../createLucideIcon';\n\n/**\n * @component @name GitBranch\n * @description Lucide SVG icon component, renders SVG Element with children.\n *\n * @preview ![img](data:image/svg+xml;base64,PHN2ZyAgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIgogIHdpZHRoPSIyNCIKICBoZWlnaHQ9IjI0IgogIHZpZXdCb3g9IjAgMCAyNCAyNCIKICBmaWxsPSJub25lIgogIHN0cm9rZT0iIzAwMCIgc3R5bGU9ImJhY2tncm91bmQtY29sb3I6ICNmZmY7IGJvcmRlci1yYWRpdXM6IDJweCIKICBzdHJva2Utd2lkdGg9IjIiCiAgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIgogIHN0cm9rZS1saW5lam9pbj0icm91bmQiCj4KICA8bGluZSB4MT0iNiIgeDI9IjYiIHkxPSIzIiB5Mj0iMTUiIC8+CiAgPGNpcmNsZSBjeD0iMTgiIGN5PSI2IiByPSIzIiAvPgogIDxjaXJjbGUgY3g9IjYiIGN5PSIxOCIgcj0iMyIgLz4KICA8cGF0aCBkPSJNMTggOWE5IDkgMCAwIDEtOSA5IiAvPgo8L3N2Zz4K) - https://lucide.dev/icons/git-branch\n * @see https://lucide.dev/guide/packages/lucide-react - Documentation\n *\n * @param {Object} props - Lucide icons props and any valid SVG attribute\n * @returns {JSX.Element} JSX Element\n *\n */\nconst GitBranch = createLucideIcon('GitBranch', [\n ['line', { x1: '6', x2: '6', y1: '3', y2: '15', key: '17qcm7' }],\n ['circle', { cx: '18', cy: '6', r: '3', key: '1h7g24' }],\n ['circle', { cx: '6', cy: '18', r: '3', key: 'fqmcym' }],\n ['path', { d: 'M18 9a9 9 0 0 1-9 9', key: 'n2h4wq' }],\n]);\n\nexport default GitBranch;\n","import createLucideIcon from '../createLucideIcon';\n\n/**\n * @component @name Pencil\n * @description Lucide SVG icon component, renders SVG Element with children.\n *\n * @preview ![img](data:image/svg+xml;base64,PHN2ZyAgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIgogIHdpZHRoPSIyNCIKICBoZWlnaHQ9IjI0IgogIHZpZXdCb3g9IjAgMCAyNCAyNCIKICBmaWxsPSJub25lIgogIHN0cm9rZT0iIzAwMCIgc3R5bGU9ImJhY2tncm91bmQtY29sb3I6ICNmZmY7IGJvcmRlci1yYWRpdXM6IDJweCIKICBzdHJva2Utd2lkdGg9IjIiCiAgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIgogIHN0cm9rZS1saW5lam9pbj0icm91bmQiCj4KICA8cGF0aCBkPSJNMjEuMTc0IDYuODEyYTEgMSAwIDAgMC0zLjk4Ni0zLjk4N0wzLjg0MiAxNi4xNzRhMiAyIDAgMCAwLS41LjgzbC0xLjMyMSA0LjM1MmEuNS41IDAgMCAwIC42MjMuNjIybDQuMzUzLTEuMzJhMiAyIDAgMCAwIC44My0uNDk3eiIgLz4KICA8cGF0aCBkPSJtMTUgNSA0IDQiIC8+Cjwvc3ZnPgo=) - https://lucide.dev/icons/pencil\n * @see https://lucide.dev/guide/packages/lucide-react - Documentation\n *\n * @param {Object} props - Lucide icons props and any valid SVG attribute\n * @returns {JSX.Element} JSX Element\n *\n */\nconst Pencil = createLucideIcon('Pencil', [\n [\n 'path',\n {\n d: 'M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z',\n key: '1a8usu',\n },\n ],\n ['path', { d: 'm15 5 4 4', key: '1mk7zo' }],\n]);\n\nexport default Pencil;\n","import createLucideIcon from '../createLucideIcon';\n\n/**\n * @component @name PinOff\n * @description Lucide SVG icon component, renders SVG Element with children.\n *\n * @preview ![img](data:image/svg+xml;base64,PHN2ZyAgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIgogIHdpZHRoPSIyNCIKICBoZWlnaHQ9IjI0IgogIHZpZXdCb3g9IjAgMCAyNCAyNCIKICBmaWxsPSJub25lIgogIHN0cm9rZT0iIzAwMCIgc3R5bGU9ImJhY2tncm91bmQtY29sb3I6ICNmZmY7IGJvcmRlci1yYWRpdXM6IDJweCIKICBzdHJva2Utd2lkdGg9IjIiCiAgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIgogIHN0cm9rZS1saW5lam9pbj0icm91bmQiCj4KICA8cGF0aCBkPSJNMTIgMTd2NSIgLz4KICA8cGF0aCBkPSJNMTUgOS4zNFY3YTEgMSAwIDAgMSAxLTEgMiAyIDAgMCAwIDAtNEg3Ljg5IiAvPgogIDxwYXRoIGQ9Im0yIDIgMjAgMjAiIC8+CiAgPHBhdGggZD0iTTkgOXYxLjc2YTIgMiAwIDAgMS0xLjExIDEuNzlsLTEuNzguOUEyIDIgMCAwIDAgNSAxNS4yNFYxNmExIDEgMCAwIDAgMSAxaDExIiAvPgo8L3N2Zz4K) - https://lucide.dev/icons/pin-off\n * @see https://lucide.dev/guide/packages/lucide-react - Documentation\n *\n * @param {Object} props - Lucide icons props and any valid SVG attribute\n * @returns {JSX.Element} JSX Element\n *\n */\nconst PinOff = createLucideIcon('PinOff', [\n ['path', { d: 'M12 17v5', key: 'bb1du9' }],\n ['path', { d: 'M15 9.34V7a1 1 0 0 1 1-1 2 2 0 0 0 0-4H7.89', key: 'znwnzq' }],\n ['path', { d: 'm2 2 20 20', key: '1ooewy' }],\n [\n 'path',\n {\n d: 'M9 9v1.76a2 2 0 0 1-1.11 1.79l-1.78.9A2 2 0 0 0 5 15.24V16a1 1 0 0 0 1 1h11',\n key: 'c9qhm2',\n },\n ],\n]);\n\nexport default PinOff;\n","import createLucideIcon from '../createLucideIcon';\n\n/**\n * @component @name Pin\n * @description Lucide SVG icon component, renders SVG Element with children.\n *\n * @preview ![img](data:image/svg+xml;base64,PHN2ZyAgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIgogIHdpZHRoPSIyNCIKICBoZWlnaHQ9IjI0IgogIHZpZXdCb3g9IjAgMCAyNCAyNCIKICBmaWxsPSJub25lIgogIHN0cm9rZT0iIzAwMCIgc3R5bGU9ImJhY2tncm91bmQtY29sb3I6ICNmZmY7IGJvcmRlci1yYWRpdXM6IDJweCIKICBzdHJva2Utd2lkdGg9IjIiCiAgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIgogIHN0cm9rZS1saW5lam9pbj0icm91bmQiCj4KICA8cGF0aCBkPSJNMTIgMTd2NSIgLz4KICA8cGF0aCBkPSJNOSAxMC43NmEyIDIgMCAwIDEtMS4xMSAxLjc5bC0xLjc4LjlBMiAyIDAgMCAwIDUgMTUuMjRWMTZhMSAxIDAgMCAwIDEgMWgxMmExIDEgMCAwIDAgMS0xdi0uNzZhMiAyIDAgMCAwLTEuMTEtMS43OWwtMS43OC0uOUEyIDIgMCAwIDEgMTUgMTAuNzZWN2ExIDEgMCAwIDEgMS0xIDIgMiAwIDAgMCAwLTRIOGEyIDIgMCAwIDAgMCA0IDEgMSAwIDAgMSAxIDF6IiAvPgo8L3N2Zz4K) - https://lucide.dev/icons/pin\n * @see https://lucide.dev/guide/packages/lucide-react - Documentation\n *\n * @param {Object} props - Lucide icons props and any valid SVG attribute\n * @returns {JSX.Element} JSX Element\n *\n */\nconst Pin = createLucideIcon('Pin', [\n ['path', { d: 'M12 17v5', key: 'bb1du9' }],\n [\n 'path',\n {\n 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',\n key: '1nkz8b',\n },\n ],\n]);\n\nexport default Pin;\n","import createLucideIcon from '../createLucideIcon';\n\n/**\n * @component @name Trash2\n * @description Lucide SVG icon component, renders SVG Element with children.\n *\n * @preview ![img](data:image/svg+xml;base64,PHN2ZyAgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIgogIHdpZHRoPSIyNCIKICBoZWlnaHQ9IjI0IgogIHZpZXdCb3g9IjAgMCAyNCAyNCIKICBmaWxsPSJub25lIgogIHN0cm9rZT0iIzAwMCIgc3R5bGU9ImJhY2tncm91bmQtY29sb3I6ICNmZmY7IGJvcmRlci1yYWRpdXM6IDJweCIKICBzdHJva2Utd2lkdGg9IjIiCiAgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIgogIHN0cm9rZS1saW5lam9pbj0icm91bmQiCj4KICA8cGF0aCBkPSJNMyA2aDE4IiAvPgogIDxwYXRoIGQ9Ik0xOSA2djE0YzAgMS0xIDItMiAySDdjLTEgMC0yLTEtMi0yVjYiIC8+CiAgPHBhdGggZD0iTTggNlY0YzAtMSAxLTIgMi0yaDRjMSAwIDIgMSAyIDJ2MiIgLz4KICA8bGluZSB4MT0iMTAiIHgyPSIxMCIgeTE9IjExIiB5Mj0iMTciIC8+CiAgPGxpbmUgeDE9IjE0IiB4Mj0iMTQiIHkxPSIxMSIgeTI9IjE3IiAvPgo8L3N2Zz4K) - https://lucide.dev/icons/trash-2\n * @see https://lucide.dev/guide/packages/lucide-react - Documentation\n *\n * @param {Object} props - Lucide icons props and any valid SVG attribute\n * @returns {JSX.Element} JSX Element\n *\n */\nconst Trash2 = createLucideIcon('Trash2', [\n ['path', { d: 'M3 6h18', key: 'd0wm0j' }],\n ['path', { d: 'M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6', key: '4alrt4' }],\n ['path', { d: 'M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2', key: 'v07s0e' }],\n ['line', { x1: '10', x2: '10', y1: '11', y2: '17', key: '1uufr5' }],\n ['line', { x1: '14', x2: '14', y1: '11', y2: '17', key: 'xtxkd' }],\n]);\n\nexport default Trash2;\n","import { SVGProps } from './types';\n\nconst defaultAttributes: SVGProps = {\n xmlns: 'http://www.w3.org/2000/svg',\n width: 24,\n height: 24,\n viewBox: '0 0 24 24',\n fill: 'none',\n stroke: 'currentColor',\n 'stroke-width': 2,\n 'stroke-linecap': 'round',\n 'stroke-linejoin': 'round',\n};\n\nexport default defaultAttributes;\n","import defaultAttributes from '../defaultAttributes';\nimport type { IconNode } from '../types';\n\n/**\n * @name pin-off\n * @description Lucide SVG icon node.\n *\n * @preview ![img](data:image/svg+xml;base64,PHN2ZyAgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIgogIHdpZHRoPSIyNCIKICBoZWlnaHQ9IjI0IgogIHZpZXdCb3g9IjAgMCAyNCAyNCIKICBmaWxsPSJub25lIgogIHN0cm9rZT0iIzAwMCIgc3R5bGU9ImJhY2tncm91bmQtY29sb3I6ICNmZmY7IGJvcmRlci1yYWRpdXM6IDJweCIKICBzdHJva2Utd2lkdGg9IjIiCiAgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIgogIHN0cm9rZS1saW5lam9pbj0icm91bmQiCj4KICA8cGF0aCBkPSJNMTIgMTd2NSIgLz4KICA8cGF0aCBkPSJNMTUgOS4zNFY3YTEgMSAwIDAgMSAxLTEgMiAyIDAgMCAwIDAtNEg3Ljg5IiAvPgogIDxwYXRoIGQ9Im0yIDIgMjAgMjAiIC8+CiAgPHBhdGggZD0iTTkgOXYxLjc2YTIgMiAwIDAgMS0xLjExIDEuNzlsLTEuNzguOUEyIDIgMCAwIDAgNSAxNS4yNFYxNmExIDEgMCAwIDAgMSAxaDExIiAvPgo8L3N2Zz4K) - https://lucide.dev/icons/pin-off\n * @see https://lucide.dev/guide/packages/lucide - Documentation\n *\n * @returns {Array}\n *\n */\nconst PinOff: IconNode = [\n 'svg',\n defaultAttributes,\n [\n ['path', { d: 'M12 17v5' }],\n ['path', { d: 'M15 9.34V7a1 1 0 0 1 1-1 2 2 0 0 0 0-4H7.89' }],\n ['path', { d: 'm2 2 20 20' }],\n ['path', { d: 'M9 9v1.76a2 2 0 0 1-1.11 1.79l-1.78.9A2 2 0 0 0 5 15.24V16a1 1 0 0 0 1 1h11' }],\n ],\n];\n\nexport default PinOff;\n","import defaultAttributes from '../defaultAttributes';\nimport type { IconNode } from '../types';\n\n/**\n * @name pin\n * @description Lucide SVG icon node.\n *\n * @preview ![img](data:image/svg+xml;base64,PHN2ZyAgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIgogIHdpZHRoPSIyNCIKICBoZWlnaHQ9IjI0IgogIHZpZXdCb3g9IjAgMCAyNCAyNCIKICBmaWxsPSJub25lIgogIHN0cm9rZT0iIzAwMCIgc3R5bGU9ImJhY2tncm91bmQtY29sb3I6ICNmZmY7IGJvcmRlci1yYWRpdXM6IDJweCIKICBzdHJva2Utd2lkdGg9IjIiCiAgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIgogIHN0cm9rZS1saW5lam9pbj0icm91bmQiCj4KICA8cGF0aCBkPSJNMTIgMTd2NSIgLz4KICA8cGF0aCBkPSJNOSAxMC43NmEyIDIgMCAwIDEtMS4xMSAxLjc5bC0xLjc4LjlBMiAyIDAgMCAwIDUgMTUuMjRWMTZhMSAxIDAgMCAwIDEgMWgxMmExIDEgMCAwIDAgMS0xdi0uNzZhMiAyIDAgMCAwLTEuMTEtMS43OWwtMS43OC0uOUEyIDIgMCAwIDEgMTUgMTAuNzZWN2ExIDEgMCAwIDEgMS0xIDIgMiAwIDAgMCAwLTRIOGEyIDIgMCAwIDAgMCA0IDEgMSAwIDAgMSAxIDF6IiAvPgo8L3N2Zz4K) - https://lucide.dev/icons/pin\n * @see https://lucide.dev/guide/packages/lucide - Documentation\n *\n * @returns {Array}\n *\n */\nconst Pin: IconNode = [\n 'svg',\n defaultAttributes,\n [\n ['path', { d: 'M12 17v5' }],\n [\n 'path',\n {\n 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',\n },\n ],\n ],\n];\n\nexport default Pin;\n","import { Pin as PinNode, PinOff as PinOffNode, type IconNode } from 'lucide'\n\nexport const SIDEBAR_SLOT_SELECTOR = '[data-slot=\"sidebar.workspaces\"]'\nexport const PINNED_HOST_ATTRIBUTE = 'data-dsh-pinned-sessions-host'\nexport const MENU_HOST_ATTRIBUTE = 'data-dsh-pinned-session-menu-host'\nexport const MENU_OWNER_ATTRIBUTE = 'data-dsh-pinned-session-menu'\n\nexport interface SessionsForCapture {\n readonly list: {\n getSnapshot(): { readonly current?: string | undefined }\n }\n open(sessionId: string): void\n}\n\nexport interface SessionActionTarget {\n readonly button: HTMLButtonElement\n readonly row: HTMLElement\n}\n\nexport interface SessionMenuTarget {\n readonly host: HTMLDivElement\n readonly menu: HTMLElement\n readonly sessionId: string\n readonly button: HTMLButtonElement\n readonly icon: HTMLSpanElement\n readonly label: HTMLSpanElement\n}\n\nexport interface TriggerRect {\n readonly top: number\n readonly right: number\n readonly bottom: number\n readonly left: number\n readonly width: number\n readonly height: number\n}\n\nfunction elementFromTarget(target: EventTarget | null): Element | null {\n return target !== null && (target as Node).nodeType === 1 ? target as Element : null\n}\n\n/** Identify a native ellipsis trigger inside a real Session row. */\nexport function findSessionActionTarget(target: EventTarget | null): SessionActionTarget | null {\n const element = elementFromTarget(target)\n const button = element?.closest('button')\n if (!(button instanceof HTMLButtonElement)) return null\n const row = button.closest<HTMLElement>('[role=\"treeitem\"][aria-selected]')\n if (row === null || row === button) return null\n if (row.closest(SIDEBAR_SLOT_SELECTOR) === null) return null\n if (row.closest(`[${PINNED_HOST_ATTRIBUTE}]`) !== null) return null\n return { button, row }\n}\n\n/**\n * Ask the native row closure for its Session ID without changing selection.\n * The Workspace browser's row callback calls sessions.open(node.id), so a\n * synchronous, verified interceptor captures the exact ID and is restored\n * before the user's original ellipsis click continues.\n */\nexport function captureSessionId(row: HTMLElement, sessions: SessionsForCapture): string | null {\n const hadOwn = Object.prototype.hasOwnProperty.call(sessions, 'open')\n const ownDescriptor = hadOwn ? Object.getOwnPropertyDescriptor(sessions, 'open') : undefined\n const original = sessions.open\n let captured: string | null = null\n const interceptor = (sessionId: string): void => {\n if (typeof sessionId === 'string' && sessionId.length > 0) captured = sessionId\n }\n\n try {\n Object.defineProperty(sessions, 'open', {\n configurable: true,\n enumerable: ownDescriptor?.enumerable ?? false,\n writable: true,\n value: interceptor,\n })\n if (sessions.open !== interceptor) return null\n row.click()\n } catch {\n return null\n } finally {\n try {\n if (hadOwn && ownDescriptor !== undefined) Object.defineProperty(sessions, 'open', ownDescriptor)\n else delete (sessions as { open?: SessionsForCapture['open'] }).open\n } catch {\n try {\n Object.defineProperty(sessions, 'open', {\n configurable: true,\n writable: true,\n value: original,\n })\n } catch {\n // The verified patch path is configurable; this is a defensive fallback.\n }\n }\n }\n return captured\n}\n\n/** Insert the pinned region immediately after the native Workspace header. */\nexport function ensurePinnedHost(doc: Document): HTMLDivElement | null {\n const slot = doc.querySelector<HTMLElement>(SIDEBAR_SLOT_SELECTOR)\n const root = slot?.firstElementChild\n if (!(root instanceof HTMLElement)) return null\n const existing = root.querySelector<HTMLDivElement>(`:scope > [${PINNED_HOST_ATTRIBUTE}]`)\n if (existing !== null) return existing\n const header = root.firstElementChild\n if (header === null) return null\n const host = doc.createElement('div')\n host.setAttribute(PINNED_HOST_ATTRIBUTE, '')\n header.insertAdjacentElement('afterend', host)\n return host\n}\n\n/** List direct-body portal menus so one trigger can exclude every pre-existing menu. */\nexport function listPortalMenus(doc: Document): readonly HTMLElement[] {\n return [...doc.body.children].filter((node): node is HTMLElement => (\n node instanceof HTMLElement && node.getAttribute('role') === 'menu'\n ))\n}\n\nfunction belongsToTrigger(menu: HTMLElement, trigger: TriggerRect | undefined): boolean {\n if (trigger === undefined || trigger.width === 0 || trigger.height === 0) return true\n const menuRect = menu.getBoundingClientRect()\n if (menuRect.width === 0 || menuRect.height === 0) return true\n const horizontalGap = Math.min(\n Math.abs(menuRect.left - trigger.left),\n Math.abs(menuRect.right - trigger.right),\n )\n const verticalGap = Math.max(\n 0,\n menuRect.top - trigger.bottom,\n trigger.top - menuRect.bottom,\n )\n return horizontalGap <= 64 && verticalGap <= 32\n}\n\n/** Find only a new, geometrically associated portal menu after one trigger click. */\nexport function findUnclaimedPortalMenu(\n doc: Document,\n excluded: ReadonlySet<HTMLElement> = new Set(),\n trigger?: TriggerRect,\n): HTMLElement | null {\n const menus = listPortalMenus(doc).filter(menu => (\n !excluded.has(menu)\n && !menu.hasAttribute(MENU_OWNER_ATTRIBUTE)\n && belongsToTrigger(menu, trigger)\n ))\n return menus.at(-1) ?? null\n}\n\nfunction createLucideIcon(doc: Document, node: IconNode, name: string): SVGSVGElement {\n const [, attributes, children = []] = node\n const svg = doc.createElementNS('http://www.w3.org/2000/svg', 'svg')\n for (const [key, value] of Object.entries(attributes)) svg.setAttribute(key, String(value))\n svg.setAttribute('width', '16')\n svg.setAttribute('height', '16')\n svg.setAttribute('stroke-width', '1.8')\n svg.setAttribute('class', `lucide lucide-${name}`)\n svg.setAttribute('aria-hidden', 'true')\n for (const [tag, childAttributes] of children) {\n const child = doc.createElementNS('http://www.w3.org/2000/svg', tag)\n for (const [key, value] of Object.entries(childAttributes)) child.setAttribute(key, String(value))\n svg.appendChild(child)\n }\n return svg\n}\n\n/** Update the unmanaged item without moving it into the plugin's React tree. */\nexport function updateSessionMenuItem(target: SessionMenuTarget, pinned: boolean, label: string): void {\n target.button.setAttribute('aria-label', label)\n target.label.textContent = label\n target.icon.replaceChildren(createLucideIcon(\n target.menu.ownerDocument,\n pinned ? PinOffNode : PinNode,\n pinned ? 'pin-off' : 'pin',\n ))\n}\n\n/** Add an unmanaged native-styled row before the Session menu's archive tail. */\nexport function attachSessionMenuHost(menu: HTMLElement, sessionId: string): SessionMenuTarget | null {\n if (menu.hasAttribute(MENU_OWNER_ATTRIBUTE)) return null\n const viewport = [...menu.children].find((node): node is HTMLElement => (\n node instanceof HTMLElement && node.getAttribute('role') === 'presentation'\n ))\n if (viewport === undefined) return null\n const wrappers = [...viewport.children].filter((node): node is HTMLElement => (\n node instanceof HTMLElement\n && node.querySelector(':scope > button[role=\"menuitem\"]') instanceof HTMLButtonElement\n ))\n if (wrappers.length < 3 || wrappers.length > 4) return null\n const templateButton = wrappers[0]?.querySelector<HTMLButtonElement>(':scope > button[role=\"menuitem\"]')\n if (templateButton === null || templateButton === undefined) return null\n const spans = [...templateButton.children].filter((node): node is HTMLSpanElement => node instanceof HTMLSpanElement)\n if (spans.length < 2) return null\n\n const doc = menu.ownerDocument\n const host = doc.createElement('div')\n host.className = wrappers[0]?.className ?? ''\n host.setAttribute(MENU_HOST_ATTRIBUTE, '')\n const button = doc.createElement('button')\n button.type = 'button'\n button.setAttribute('role', 'menuitem')\n button.className = `${templateButton.className} dsh-pins-menu-button`\n const icon = doc.createElement('span')\n icon.className = spans[0]?.className ?? ''\n icon.setAttribute('aria-hidden', 'true')\n const label = doc.createElement('span')\n label.className = spans.at(-1)?.className ?? ''\n button.append(icon, label)\n host.appendChild(button)\n viewport.insertBefore(host, wrappers[2] ?? null)\n menu.setAttribute(MENU_OWNER_ATTRIBUTE, sessionId)\n\n const target = { host, menu, sessionId, button, icon, label }\n const view = doc.defaultView\n if (view !== null) view.dispatchEvent(new view.Event('resize'))\n return target\n}\n\n/** Restore useful keyboard focus after a pinned row removes itself. */\nexport function focusAfterPinnedRemoval(doc: Document, host: HTMLElement | null, removedIndex: number): boolean {\n const remaining = host === null ? [] : [...host.querySelectorAll<HTMLButtonElement>('.dsh-pins-open')]\n const next = remaining[Math.min(removedIndex, remaining.length - 1)]\n if (next !== undefined) {\n next.focus({ preventScroll: true })\n return true\n }\n const nativeRow = doc.querySelector<HTMLElement>(`${SIDEBAR_SLOT_SELECTOR} [role=\"treeitem\"][aria-selected=\"true\"]`)\n ?? doc.querySelector<HTMLElement>(`${SIDEBAR_SLOT_SELECTOR} [role=\"treeitem\"]`)\n if (nativeRow === null) return false\n const hadTabIndex = nativeRow.hasAttribute('tabindex')\n if (!hadTabIndex) nativeRow.tabIndex = -1\n nativeRow.focus({ preventScroll: true })\n if (doc.activeElement === nativeRow) return true\n if (!hadTabIndex) nativeRow.removeAttribute('tabindex')\n return false\n}\n\nexport function removeBridgeArtifacts(doc: Document): void {\n for (const node of doc.querySelectorAll(`[${PINNED_HOST_ATTRIBUTE}], [${MENU_HOST_ATTRIBUTE}]`)) node.remove()\n for (const menu of doc.querySelectorAll(`[${MENU_OWNER_ATTRIBUTE}]`)) menu.removeAttribute(MENU_OWNER_ATTRIBUTE)\n}\n","export const PIN_STORAGE_KEY = 'dsh.pinned-sessions.v1'\nconst MAX_PINS = 500\n\nexport interface PinRecord {\n readonly id: string\n readonly pinnedAt: number\n}\n\ninterface PersistedPins {\n readonly version: 1\n readonly pins: readonly PinRecord[]\n}\n\nexport interface StorageLike {\n getItem(key: string): string | null\n setItem(key: string, value: string): void\n}\n\nfunction isPinRecord(value: unknown): value is PinRecord {\n if (typeof value !== 'object' || value === null) return false\n const row = value as Record<string, unknown>\n return typeof row.id === 'string'\n && row.id.length > 0\n && Number.isFinite(row.pinnedAt)\n && (row.pinnedAt as number) >= 0\n}\n\n/** Decode, de-duplicate, and normalize one persisted pin snapshot. */\nexport function decodePins(raw: string | null): readonly PinRecord[] {\n if (raw === null) return []\n try {\n const parsed = JSON.parse(raw) as Partial<PersistedPins>\n if (parsed.version !== 1 || !Array.isArray(parsed.pins)) return []\n const byId = new Map<string, PinRecord>()\n for (const candidate of parsed.pins) {\n if (!isPinRecord(candidate)) continue\n const previous = byId.get(candidate.id)\n if (previous === undefined || candidate.pinnedAt > previous.pinnedAt) {\n byId.set(candidate.id, { id: candidate.id, pinnedAt: candidate.pinnedAt })\n }\n }\n return [...byId.values()]\n .sort((left, right) => right.pinnedAt - left.pinnedAt || left.id.localeCompare(right.id))\n .slice(0, MAX_PINS)\n } catch {\n return []\n }\n}\n\n/** Browser-local, versioned pin state with React-compatible subscriptions. */\nexport class PinStore {\n private snapshot: readonly PinRecord[]\n private readonly listeners = new Set<() => void>()\n\n constructor(private readonly storage: StorageLike | undefined) {\n this.snapshot = this.read()\n }\n\n readonly getSnapshot = (): readonly PinRecord[] => this.snapshot\n\n readonly subscribe = (listener: () => void): (() => void) => {\n this.listeners.add(listener)\n return () => { this.listeners.delete(listener) }\n }\n\n isPinned(id: string): boolean {\n return this.snapshot.some(row => row.id === id)\n }\n\n toggle(id: string, now = Date.now()): void {\n if (id.length === 0) return\n const without = this.snapshot.filter(row => row.id !== id)\n this.publish(this.isPinned(id) ? without : [{ id, pinnedAt: now }, ...without])\n }\n\n prune(keep: (id: string) => boolean): void {\n const next = this.snapshot.filter(row => keep(row.id))\n if (next.length !== this.snapshot.length) this.publish(next)\n }\n\n reload(): void {\n const next = this.read()\n if (samePins(this.snapshot, next)) return\n this.snapshot = next\n this.emit()\n }\n\n private read(): readonly PinRecord[] {\n try {\n return decodePins(this.storage?.getItem(PIN_STORAGE_KEY) ?? null)\n } catch {\n return []\n }\n }\n\n private publish(next: readonly PinRecord[]): void {\n this.snapshot = [...next]\n .sort((left, right) => right.pinnedAt - left.pinnedAt || left.id.localeCompare(right.id))\n .slice(0, MAX_PINS)\n try {\n this.storage?.setItem(PIN_STORAGE_KEY, JSON.stringify({ version: 1, pins: this.snapshot }))\n } catch {\n // Storage can be unavailable in hardened or quota-constrained browser profiles.\n }\n this.emit()\n }\n\n private emit(): void {\n for (const listener of [...this.listeners]) listener()\n }\n}\n\nfunction samePins(left: readonly PinRecord[], right: readonly PinRecord[]): boolean {\n return left.length === right.length\n && left.every((row, index) => row.id === right[index]?.id && row.pinnedAt === right[index]?.pinnedAt)\n}\n","interface SessionPresentationInput {\n readonly id: string\n readonly title?: string | undefined\n readonly cwd?: string | undefined\n}\n\nfunction nonBlank(value: string | undefined): string | undefined {\n const trimmed = value?.trim()\n return trimmed === undefined || trimmed.length === 0 ? undefined : trimmed\n}\n\n/** Match the native sidebar's useful fallback for sessions without a title. */\nexport function sessionDisplayTitle(\n session: SessionPresentationInput,\n workspaceTitle: string | undefined,\n): string {\n const explicit = nonBlank(session.title)\n if (explicit !== undefined) return explicit\n const workspace = nonBlank(workspaceTitle)\n if (workspace !== undefined) return workspace\n const cwd = nonBlank(session.cwd)\n if (cwd !== undefined) {\n const leaf = cwd.replace(/[\\\\/]+$/u, '').split(/[\\\\/]/u).at(-1)\n if (leaf !== undefined && leaf.length > 0) return leaf\n }\n return session.id\n}\n"],"mappings":"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","names":["import_react","defaultAttributes","PinOff","defaultAttributes","Pin","defaultAttributes","createLucideIcon","PinOff","Pin"],"file":"client.js"}
@@ -40,22 +40,55 @@ interface SlotsLike {
40
40
  interface LocaleLike {
41
41
  register(namespace: string, dictionaries: Readonly<Record<string, Readonly<Record<string, string>>>>): () => void;
42
42
  }
43
+ interface ResultLike {
44
+ readonly ok: boolean;
45
+ readonly error?: {
46
+ readonly message: string;
47
+ } | undefined;
48
+ }
49
+ interface ClientSessionsLike extends SessionsForCapture {
50
+ binding(sessionId: string): {
51
+ readonly session: {
52
+ rename(title: string): Promise<ResultLike>;
53
+ };
54
+ } | undefined;
55
+ fork(input: {
56
+ readonly sessionId: string;
57
+ readonly increaseTitle: boolean;
58
+ }): Promise<string>;
59
+ }
60
+ interface BooleanStoreLike {
61
+ readonly getSnapshot: () => boolean;
62
+ readonly subscribe: (listener: () => void) => () => void;
63
+ }
43
64
  interface ClientContextLike {
44
65
  readonly slots: SlotsLike;
45
- readonly sessions: SessionsForCapture;
66
+ readonly sessions: ClientSessionsLike;
46
67
  readonly locale: LocaleLike;
68
+ get(name: string): unknown;
69
+ inject(dependencies: readonly string[], setup: (ctx: ClientContextLike) => void): unknown;
47
70
  effect(setup: () => (() => void), label?: string): unknown;
48
71
  }
72
+ export interface PinnedSessionActions {
73
+ readonly openSession?: (sessionId: string) => void;
74
+ readonly renameSession: (sessionId: string, title: string) => Promise<void>;
75
+ readonly forkSession: (sessionId: string) => Promise<void>;
76
+ readonly archiveSession: (sessionId: string) => Promise<void>;
77
+ readonly deleteAvailability: BooleanStoreLike;
78
+ readonly deleteSession: (sessionId: string) => Promise<void>;
79
+ }
49
80
  interface BridgeProps {
50
81
  readonly store: PinStore;
51
82
  readonly sessions: SessionsForCapture;
83
+ readonly actions: PinnedSessionActions;
52
84
  readonly useSessions: SelectorHook<SessionsSnapshotLike>;
53
85
  readonly useWorkspaces: SelectorHook<WorkspacesSnapshotLike>;
54
86
  readonly t: Translate;
87
+ readonly modernMenus?: BooleanStoreLike;
55
88
  }
56
89
  export declare const inject: string[];
57
90
  /** Register the lifecycle bridge in the additive frame overlay slot. */
58
91
  export declare function apply(ctx: ClientContextLike): void;
59
92
  /** Keep native behavior intact while mounting the sidebar portal and unmanaged menu item. */
60
- export declare function PinnedSessionsBridge({ store, sessions, useSessions, useWorkspaces, t }: BridgeProps): ReactNode;
93
+ export declare function PinnedSessionsBridge({ store, sessions, actions, useSessions, useWorkspaces, t, modernMenus }: BridgeProps): ReactNode;
61
94
  export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@anionex/dsh-pinned-sessions",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "Pin important DeepSeek Harness sessions at the top of the workspace sidebar",
5
5
  "repository": {
6
6
  "type": "git",
@@ -24,13 +24,15 @@
24
24
  "./package.json": "./package.json"
25
25
  },
26
26
  "files": [
27
+ "assets",
27
28
  "lib",
28
29
  "src",
29
30
  "scripts",
30
31
  "cordis.patch.yml",
31
32
  "README.md",
32
33
  "README.zh.md",
33
- "LICENSE"
34
+ "LICENSE",
35
+ "CHANGELOG.md"
34
36
  ],
35
37
  "dsh": {
36
38
  "bundle": {
@@ -43,14 +45,16 @@
43
45
  "@deepseek-ai/dsh-client-ui-layout",
44
46
  "@deepseek-ai/dsh-client-ui-session",
45
47
  "@deepseek-ai/dsh-client-ui-workspace",
48
+ "@deepseek-ai/dsh-client-ui-primitives",
46
49
  "@deepseek-ai/dsh-client-locale"
47
50
  ]
48
51
  },
49
52
  "compatibility": {
50
- "dsh": ">=0.1.0-rc.8 <0.2.0",
53
+ "dsh": ">=0.1.0-rc.8 <0.2.0 || 0.2.0-rc.2",
51
54
  "dshReleases": {
52
55
  "0.1.1-rc.1": "compatible",
53
- "0.1.2-alpha.1": "compatible"
56
+ "0.1.2-alpha.1": "compatible",
57
+ "0.2.0-rc.2": "compatible"
54
58
  },
55
59
  "profiles": [
56
60
  "web",
@@ -59,7 +63,7 @@
59
63
  }
60
64
  },
61
65
  "scripts": {
62
- "build": "node scripts/clean.mjs && tsc -p tsconfig.build.json && tsc -p tsconfig.client.json && esbuild src/client/index.tsx --bundle --platform=browser --format=cjs --jsx=automatic --external:react --external:react/jsx-runtime --external:react-dom --sourcemap --outfile=.client-build/index.js && node scripts/wrap-client.mjs",
66
+ "build": "node scripts/clean.mjs && tsc -p tsconfig.build.json && tsc -p tsconfig.client.json && esbuild src/client/index.tsx --bundle --platform=browser --format=cjs --jsx=automatic --external:react --external:react/jsx-runtime --external:react-dom --external:@deepseek-ai/dsh-client-ui-primitives --sourcemap --outfile=.client-build/index.js && node scripts/wrap-client.mjs",
63
67
  "check": "tsc -p tsconfig.json && tsc -p tsconfig.client.json --noEmit false --emitDeclarationOnly true && pnpm run build && vitest run && node --test tests/package-layout.test.mjs && pnpm pack --dry-run",
64
68
  "prepack": "pnpm run build",
65
69
  "test": "vitest run && node --test tests/package-layout.test.mjs"
@@ -74,6 +78,7 @@
74
78
  "license": "MIT",
75
79
  "peerDependencies": {
76
80
  "@deepseek-ai/cordis": "^4.0.1",
81
+ "@deepseek-ai/dsh-client-ui-primitives": ">=0.1.0-rc.8 <0.2.0 || 0.2.0-rc.2",
77
82
  "react": "^18.2.0",
78
83
  "react-dom": "^18.2.0"
79
84
  },
@@ -0,0 +1,51 @@
1
+ declare module '@deepseek-ai/dsh-client-ui-primitives' {
2
+ import type { ButtonHTMLAttributes, ReactNode } from 'react'
3
+
4
+ export interface MenuItem {
5
+ readonly id: string
6
+ readonly label: ReactNode
7
+ readonly icon?: ReactNode
8
+ readonly danger?: boolean
9
+ }
10
+
11
+ export type MenuEntry = MenuItem
12
+ export function MenuItemButton(props: { icon?: ReactNode; onSelect: () => void; children: ReactNode }): ReactNode
13
+
14
+ export function Menu(props: {
15
+ readonly open: boolean
16
+ readonly anchor: ReactNode
17
+ readonly items: readonly MenuEntry[]
18
+ readonly onSelect: (id: string) => void
19
+ readonly onClose: () => void
20
+ readonly portal?: boolean
21
+ readonly closeOnPointerLeave?: boolean
22
+ readonly className?: string
23
+ }): ReactNode
24
+
25
+ export function Modal(props: {
26
+ readonly open: boolean
27
+ readonly onClose: () => void
28
+ readonly closeLabel: string
29
+ readonly title: string
30
+ readonly description?: string
31
+ readonly children?: ReactNode
32
+ readonly footer?: ReactNode
33
+ }): ReactNode
34
+
35
+ export function Toast(props: {
36
+ readonly text: string
37
+ readonly icon?: ReactNode
38
+ readonly anchor?: HTMLElement | null
39
+ readonly onDone: () => void
40
+ }): ReactNode
41
+
42
+ export function Button(props: ButtonHTMLAttributes<HTMLButtonElement> & {
43
+ readonly variant?: 'primary' | 'ghost' | 'outline' | 'toolbar'
44
+ }): ReactNode
45
+
46
+ export function IconArchiveOutline20(props: { readonly size?: number }): ReactNode
47
+ export function IconBranchOutline16(): ReactNode
48
+ export function IconEditOutline16(): ReactNode
49
+ export function IconEllipsisOutline16(): ReactNode
50
+ export function IconTrashOutline16(): ReactNode
51
+ }