dsh-web-annotator 0.0.0-stage → 0.2.0-alpha.12

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.
Files changed (76) hide show
  1. package/CHANGELOG.md +125 -0
  2. package/CONTRIBUTING.md +90 -0
  3. package/LICENSE +21 -0
  4. package/README.md +110 -2
  5. package/README_en.md +136 -0
  6. package/THIRD_PARTY_NOTICES.md +15 -0
  7. package/cordis.patch.yml +15 -0
  8. package/docs/AGENTS.md +16 -0
  9. package/docs/README.md +25 -0
  10. package/docs/architecture.md +170 -0
  11. package/docs/browser-integration.md +94 -0
  12. package/docs/distribution.md +66 -0
  13. package/docs/harness-browser-annotation.patch +1909 -0
  14. package/docs/images/annotation-expanded-dark.png +0 -0
  15. package/docs/images/annotation-expanded.png +0 -0
  16. package/docs/images/annotation-image.png +0 -0
  17. package/docs/images/annotation-message.png +0 -0
  18. package/docs/images/annotation-region.png +0 -0
  19. package/docs/marketplace/cslkkl__dsh-web-annotator.yml +7 -0
  20. package/docs/publishing.md +169 -0
  21. package/docs/roadmap.md +31 -0
  22. package/docs/verification.md +179 -0
  23. package/dsh-plugin.naming.json +27 -0
  24. package/examples/responsive-demo/AGENTS.md +12 -0
  25. package/examples/responsive-demo/README.md +33 -0
  26. package/examples/responsive-demo/index.html +13 -0
  27. package/examples/responsive-demo/src/main.tsx +110 -0
  28. package/examples/responsive-demo/src/style.css +344 -0
  29. package/examples/responsive-demo/vite.config.ts +9 -0
  30. package/lib/THIRD_PARTY_LICENSES.md +345 -0
  31. package/lib/bridge.js +890 -0
  32. package/lib/bridge.js.map +7 -0
  33. package/lib/client.js +1083 -0
  34. package/lib/client.js.map +7 -0
  35. package/lib/host/THIRD_PARTY_NOTICES.md +15 -0
  36. package/lib/host/browser-provider/LICENSE +21 -0
  37. package/lib/host/browser-provider/README.md +130 -0
  38. package/lib/host/browser-provider/lib/client.css +217 -0
  39. package/lib/host/browser-provider/lib/client.css.map +7 -0
  40. package/lib/host/browser-provider/lib/client.js +2360 -0
  41. package/lib/host/browser-provider/lib/client.js.map +7 -0
  42. package/lib/host/browser-provider/lib/index.js +7 -0
  43. package/lib/host/browser-provider/lib/index.js.map +7 -0
  44. package/lib/host/browser-provider/package.json +23 -0
  45. package/lib/host/bundle.json +27 -0
  46. package/lib/host/chat-provider/LICENSE +21 -0
  47. package/lib/host/chat-provider/README.md +186 -0
  48. package/lib/host/chat-provider/lib/client.css +1604 -0
  49. package/lib/host/chat-provider/lib/client.css.map +7 -0
  50. package/lib/host/chat-provider/lib/client.js +11074 -0
  51. package/lib/host/chat-provider/lib/client.js.map +7 -0
  52. package/lib/host/chat-provider/lib/index.js +911 -0
  53. package/lib/host/chat-provider/lib/index.js.map +7 -0
  54. package/lib/host/chat-provider/package.json +31 -0
  55. package/lib/host/layout-provider/LICENSE +21 -0
  56. package/lib/host/layout-provider/README.md +109 -0
  57. package/lib/host/layout-provider/lib/client.css +177 -0
  58. package/lib/host/layout-provider/lib/client.css.map +7 -0
  59. package/lib/host/layout-provider/lib/client.js +565 -0
  60. package/lib/host/layout-provider/lib/client.js.map +7 -0
  61. package/lib/host/layout-provider/lib/index.js +7 -0
  62. package/lib/host/layout-provider/lib/index.js.map +7 -0
  63. package/lib/host/layout-provider/package.json +25 -0
  64. package/lib/index.d.ts +2 -0
  65. package/lib/index.js +9 -0
  66. package/lib/index.js.map +7 -0
  67. package/lib/vite.d.ts +8 -0
  68. package/lib/vite.js +1254 -0
  69. package/lib/vite.js.map +7 -0
  70. package/licenses/deepseek-harness-MIT.txt +21 -0
  71. package/locale/AGENTS.md +11 -0
  72. package/locale/README.md +11 -0
  73. package/locale/en.json +6 -0
  74. package/locale/zh.json +6 -0
  75. package/package.json +154 -4
  76. package/screenshots.json +7 -0
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../.host-source/packages/client/ui-layout/src/client/index.ts", "../../../.host-source/packages/client/ui-layout/src/client/AppFrame.tsx", "../../../.host-source/packages/client/ui-layout/src/client/columns.ts", "../../../.host-source/packages/client/ui-layout/src/client/DocumentTitle.tsx", "../../../.host-source/packages/client/ui-layout/src/client/AppFrame.module.css", "../../../.host-source/packages/client/ui-layout/src/client/stores.ts", "../../../.host-source/packages/client/ui-layout/src/client/service.ts", "../../../.host-source/packages/client/ui-layout/src/client/shortcut-locales.ts", "../../../.host-source/packages/client/ui-layout/src/client/theme-presenter.ts"],
4
+ "sourcesContent": ["/**\n * Layout plugin, browser half: one register() call contributes AppFrame into\n * the runtime's built-in 'root' slot and, in the same breath, declares the\n * five child slots (declaration = exclusive render authority), seats the\n * layout store (panel geometry), and wires the panel-action service face.\n * ctx.layout selects the main panel and controls column geometry; Session\n * selection belongs to the Session Controller. A second effect seats the theme\n * presenter, which projects ctx.theme snapshots onto document.body.\n */\nimport type { Context as ClientContext } from '@deepseek-ai/cordis'\nimport type {} from '@deepseek-ai/dsh-client-locale/client'\nimport type {} from '@deepseek-ai/dsh-client-ui-renderer/client'\nimport type {} from '@deepseek-ai/dsh-client-ui-session/client'\nimport type {} from '@deepseek-ai/dsh-client-ui-theme/client'\nimport type { HostObservable, SnapshotSelectorHook } from '@deepseek-ai/dsh-client-ui-slots'\nimport type { PanelInfo } from './service.ts'\nimport { AppFrame } from './AppFrame.tsx'\nimport { createLayoutStore } from './stores.ts'\nimport { LayoutController } from './service.ts'\nimport type { ShortcutCommandId } from '@deepseek-ai/dsh-client-shortcuts/client'\nimport { en, zh } from './shortcut-locales.ts'\nimport { ThemePresenter } from './theme-presenter.ts'\n\n// Contract exports only (export-convergence rule: cross-package consumers\n// keep a symbol exported; test-only/package-internal symbols live off /src).\n// ILayout: the ctx.layout face consumers and test fakes type against.\n// OwnerShare contracts below are the render-side halves registrants compose\n// against; the frame components and the store factory are package-internal.\nexport { LayoutController } from './service.ts'\nexport type { ILayout, MainPanelId, PanelInfo } from './service.ts'\n\n/** Selector hook over root-scoped panel selection. */\nexport type UsePanelInfo = SnapshotSelectorHook<PanelInfo>\n\ndeclare module '@deepseek-ai/cordis' {\n interface Context {\n /** The outward face only; the concrete service stays inside this plugin. */\n layout: import('./service.ts').ILayout\n }\n}\n\ndeclare module '@deepseek-ai/dsh-client-ui-slots' {\n interface LocaleNamespaceMap {\n /** Layout keyboard command labels. */\n 'shortcuts.layout': keyof typeof zh\n }\n\n interface GlobalStandardProps {\n /** Subscribe to the selected main panel independently of parent renders. */\n usePanelInfo: UsePanelInfo\n }\n\n interface SlotMap {\n // The 'root' entry itself is the runtime's built-in slot (declared\n // there); these five are the frame's children, declared by the same\n // register() call that contributes AppFrame. Session owners never pass\n // sessionId: the framework injects it as a standard prop.\n /**\n * The whole left column. OCCUPIED by ui-sidebar's SidebarRoot, which\n * declares the workspace and settings seats inside it \u2014 registering here\n * replaces the navigation column outright rather than adding to it, and\n * the seats it declares disappear with it. To add something to the\n * sidebar, register into one of those inner seats instead.\n *\n * The occupant receives the frame's live column state (collapsed, width)\n * and is expected to render the compact control rail while collapsed.\n */\n 'sidebar': { kind: 'single'; scope: 'root'; owner: SidebarOwnerProps }\n /**\n * Central panel selected by sidebar entry id. The reserved `conversation`\n * key hosts the Conversation; other keys receive no Session binding.\n */\n 'main': { kind: 'keyed'; scope: 'root' }\n /**\n * The right column: a track the centre makes room for, or nothing. OCCUPIED\n * by the right Sidebar, which uses the resolved column width in normal\n * mode and covers the viewport in fullscreen, retaining the wide-screen\n * column reservation underneath.\n *\n * Whether the panel is shown, and whether it takes a track, is the\n * occupant's own recorded business \u2014 it reports the composition of its\n * expanded and presentation state through `ctx.layout`, and the frame sizes\n * the track and places the resize handle from that. The expand control is\n * not this column's: it is a button in the conversation header. The root\n * occupant decides when to render its Session-bound content.\n */\n 'rightbar': { kind: 'single'; scope: 'root'; owner: RightbarOwnerProps }\n /**\n * Frame-wide floating layer, above every column and outside their scroll\n * containers. Deliberately generic and unowned by any feature: a badge, a\n * toast stack or a status pill all belong here, and entries order among\n * themselves. The layer itself is click-through \u2014 entries opt back into\n * pointer events \u2014 so an occupant never blocks the app underneath.\n *\n * This is the additive seat for a frame-wide surface of your own: a fresh\n * `id` is added beside the shipped entries instead of replacing them.\n */\n 'shell.overlay': { kind: 'list'; scope: 'root' }\n /**\n * Window-chrome seat at the frame's top-left, over every main panel.\n * Mounted only while the sidebar column is fully hidden (macOS desktop\n * collapse; other platforms keep the rail), so the occupant can assume the\n * frame edge is the window edge and the macOS traffic lights sit before it.\n * OCCUPIED by ui-sidebar's reopen/New Session controls.\n *\n * While the seat is mounted the frame publishes\n * `--dsh-frame-leading-clearance` (the inline inset the seat's band\n * occupies, measured from the frame's left edge); a main panel whose\n * content reaches the top-left corner pads by it so nothing lands under\n * the lights or the controls.\n */\n 'shell.leading': { kind: 'single'; scope: 'root' }\n }\n}\n\n// OwnerShare contracts \u2014 the render-side share the slot owner supplies at\n// renderSlot. Registrants IMPORT these and compose their full component props\n// from the framework-derived shares. Conversation business state and actions arrive through\n// framework-standard hooks and each registrant's inject face, not owner props.\n\n/** Sidebar owner share: live column state from the frame's concession solve. */\nexport interface SidebarOwnerProps {\n /** True when the sidebar is closed (the column renders the compact control rail). */\n collapsed: boolean\n /** Rendered column width in px (SIDEBAR_COLLAPSED when collapsed). */\n width: number\n}\n\n/** Right column owner share: resolved normal geometry and opening eligibility. */\nexport interface RightbarOwnerProps {\n /** Resolved normal panel width in px, not the saved preference; zero if it cannot fit. */\n width: number\n /** Current frame width in px. */\n viewportWidth: number\n /**\n * Whether a normal right panel can retain 300px beside a 400px center.\n * Before a narrow opening, includes the space from collapsing the left sidebar.\n */\n canShow: boolean\n}\n\n/** Required services (cordis fiber inject \u2014 the loader passes all module exports as an object plugin). */\nexport const inject = ['slots', 'theme', 'locale', 'shortcuts']\n\n/**\n * Client plugin body: provide ctx.layout, then one register() call \u2014 AppFrame\n * into 'root' with the five child-slot declarations, the layout store seat,\n * and the shared root instance supplying commands and the panel-info source.\n * @param ctx - client root context.\n */\nexport function apply(ctx: ClientContext): void {\n ctx.effect(() => ctx.locale.register('shortcuts.layout', { zh, en }), 'layout: command labels')\n const t = ctx.locale.bind('shortcuts.layout')\n\n ctx.effect(() => {\n const handle = createLayoutStore()\n const instance = handle.create()\n const store: typeof handle = { ...handle, create: () => instance }\n const retainMainPanels = (): void => {\n instance.actions.retainMainPanels(ctx.slots.entries('main').flatMap(entry =>\n entry.options.key === undefined ? [] : [entry.options.key]))\n }\n const panelInfo: HostObservable<PanelInfo> = {\n getSnapshot: () => instance.getSnapshot().panelInfo,\n subscribe: listener => instance.subscribe(listener),\n }\n const layout = new LayoutController(instance.actions, id =>\n ctx.slots.entries('main').some(entry => entry.options.key === id), panelInfo)\n const disposePanelInfo = ctx.slots.provideRoot({ hooks: { panelInfo: layout.panelInfo } })\n const disposeService = ctx.reflect.provide('layout', layout)\n const disposeRegistration = ctx.slots.register({\n name: 'root',\n locale: 'common',\n children: {\n 'sidebar': { kind: 'single', scope: 'root' },\n 'main': { kind: 'keyed', scope: 'root' },\n 'rightbar': { kind: 'single', scope: 'root' },\n 'shell.overlay': { kind: 'list', scope: 'root' },\n 'shell.leading': { kind: 'single', scope: 'root' },\n },\n store,\n }, AppFrame)\n const disposeShortcut = ctx.shortcuts.register({\n id: 'sidebar.left.toggle' as ShortcutCommandId, label: () => t('toggle'), aliases: ['sidebar', 'toggle left sidebar'],\n defaults: {\n 'desktop:macos': { code: 'KeyB', modifiers: ['primary'] },\n 'desktop:windows': { code: 'KeyB', modifiers: ['primary'] },\n 'desktop:linux': { code: 'KeyB', modifiers: ['primary'] },\n 'web:macos': { code: 'KeyB', modifiers: ['primary', 'alt'] },\n 'web:windows': { code: 'KeyB', modifiers: ['primary', 'alt'] },\n },\n regions: ['page', 'editable'], modals: [],\n resolve: () => ({ status: 'handled', run: () => { layout.toggleSidebar() } }),\n })\n const disposePanels = ctx.slots.subscribe('main', retainMainPanels)\n retainMainPanels()\n return () => {\n disposeShortcut()\n layout.dispose()\n disposePanels()\n disposeRegistration()\n disposePanelInfo()\n // provide()'s disposer settles asynchronously; teardown is synchronous fire-and-forget.\n void disposeService()\n }\n }, 'ui-layout: service + root registration')\n\n // Theme presentation: pure DOM writes from resolved snapshots \u2014 initial\n // state through the getter once, then event-driven only; no React path.\n ctx.effect(() => {\n const presenter = new ThemePresenter()\n presenter.apply(ctx.theme.getTheme())\n const off = ctx.on('theme/change', (snapshot) => { presenter.apply(snapshot) })\n return () => {\n off()\n presenter.dispose()\n }\n }, 'ui-layout: theme presenter')\n}\n", "/**\n * Three-column shell frame, registered into the built-in 'root' slot (the web\n * shell renders only 'root'). Owns the grid tracks (sidebar | center |\n * rightbar), the drag handles (pointer capture + rAF throttle), the column\n * solve (columns.ts), and the child-slot render decisions: the sidebar slot\n * receives live parameters from that solve. The root-scoped main slot selects\n * the Conversation or a global panel. Each column occupant owns its Session\n * binding and reports the geometry it needs.\n *\n * The right column is a track, not a box: its occupant draws its panel anchored\n * to the frame's right edge at the resolved normal width, and the\n * track only decides whether the centre makes room for it. The occupant reports\n * shown/track/fullscreen through `ctx.layout`; fullscreen keeps the reported\n * track but hides the outer resize handle. Everything arrives through the framework\n * shares \u2014 zero cordis or framework imports, zero self-made hooks.\n */\nimport { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react'\nimport type { ReactNode } from 'react'\nimport type {\n PropsLocale, PropsRenderSlots, PropsRuntime, PropsStore,\n} from '@deepseek-ai/dsh-client-ui-slots'\nimport { CENTER_MIN, clampWidth, computeColumns, RIGHTBAR_DEFAULT_RATIO, RIGHTBAR_MAX_RATIO, RIGHTBAR_MIN, SIDEBAR_AUTO_COLLAPSE, SIDEBAR_COLLAPSED, SIDEBAR_DEFAULT } from './columns.ts'\nimport { DocumentTitle } from './DocumentTitle.tsx'\nimport type { createLayoutStore } from './stores.ts'\nimport css from './AppFrame.module.css'\n\n/** Full composed props: runtime share + child-slot render share + store share. */\nexport type AppFrameProps =\n & PropsRuntime<'root'>\n & PropsRenderSlots<'sidebar' | 'main' | 'rightbar' | 'shell.overlay' | 'shell.leading'>\n & PropsStore<ReturnType<typeof createLayoutStore>>\n & PropsLocale<'common'>\n\n/** Center column grid item (session-body building block). */\nfunction CenterColumn(props: { children?: ReactNode; covered: boolean }) {\n return <div className={css.centerCol} aria-hidden={props.covered || undefined}\n {...(props.covered ? { inert: '' } : {})}>{props.children}</div>\n}\n\n/** Subscribe to the main key without subscribing the column frame to each panel id. */\nfunction MainPanel({ usePanelInfo, renderSlot }: Pick<PropsRuntime<'root'>, 'usePanelInfo'> & PropsRenderSlots<'main'>) {\n const panelId = usePanelInfo(info => info.activePanelId)\n return renderSlot('main', {}, { entryKey: panelId ?? 'conversation' })\n}\n\n/**\n * Right column grid item. Zero-width unless the occupant asked for a track; the\n * occupant's panel is positioned against the column's right edge, which never\n * moves, so it can hang over the centre when there is no track.\n */\nfunction RightbarColumn(props: { children?: ReactNode }) {\n return <div className={css.rightbarCol} data-rightbar-col>{props.children}</div>\n}\n\n/**\n * One drag handle: pointer capture, rAF-throttled dx reports against the drag-start origin.\n * `side` keys the hover-reveal CSS to the owning column.\n */\nfunction DragHandle(props: { side: 'sidebar' | 'rightbar'; left: number; onStart: () => void; onDrag: (dx: number) => void; onEnd: () => void }) {\n const [dragging, setDragging] = useState(false)\n const origin = useRef(0)\n const latest = useRef(0)\n const frame = useRef<number | null>(null)\n const capture = useRef<{ element: HTMLDivElement; id: number } | null>(null)\n const callbacks = useRef({ onStart: props.onStart, onDrag: props.onDrag, onEnd: props.onEnd })\n callbacks.current = { onStart: props.onStart, onDrag: props.onDrag, onEnd: props.onEnd }\n\n const endDrag = useCallback(() => {\n const active = capture.current\n if (active === null) return\n capture.current = null\n if (frame.current !== null) { cancelAnimationFrame(frame.current); frame.current = null }\n if (active.element.hasPointerCapture(active.id)) active.element.releasePointerCapture(active.id)\n setDragging(false)\n callbacks.current.onEnd()\n }, [])\n useEffect(() => endDrag, [endDrag])\n\n const onPointerDown = useCallback((e: React.PointerEvent<HTMLDivElement>) => {\n if (e.button !== 0 || capture.current !== null) return\n e.preventDefault()\n e.currentTarget.setPointerCapture(e.pointerId)\n capture.current = { element: e.currentTarget, id: e.pointerId }\n origin.current = e.clientX\n latest.current = e.clientX\n callbacks.current.onStart()\n setDragging(true)\n }, [])\n const onPointerMove = useCallback((e: React.PointerEvent<HTMLDivElement>) => {\n if (capture.current?.id !== e.pointerId) return\n latest.current = e.clientX\n frame.current ??= requestAnimationFrame(() => {\n frame.current = null\n callbacks.current.onDrag(latest.current - origin.current)\n })\n }, [])\n const onPointerUp = useCallback((e: React.PointerEvent<HTMLDivElement>) => {\n if (capture.current?.id !== e.pointerId) return\n callbacks.current.onDrag(e.clientX - origin.current)\n endDrag()\n }, [endDrag])\n const onPointerCancel = useCallback((e: React.PointerEvent<HTMLDivElement>) => {\n if (capture.current?.id === e.pointerId) endDrag()\n }, [endDrag])\n\n return (\n <div\n className={css.handle}\n style={{ left: props.left }}\n data-side={props.side}\n data-dragging={dragging || undefined}\n onPointerDown={onPointerDown}\n onPointerMove={onPointerMove}\n onPointerUp={onPointerUp}\n onPointerCancel={onPointerCancel}\n onLostPointerCapture={onPointerCancel}\n />\n )\n}\n\n/** The three-column frame (see module doc). */\nexport function AppFrame({\n useStore,\n useSessions,\n usePanelInfo,\n actions,\n renderSlot,\n t,\n}: AppFrameProps) {\n const layoutInfo = useStore(state => state.layoutInfo)\n const frameRef = useRef<HTMLDivElement | null>(null)\n const viewport = layoutInfo.viewportWidth\n\n // Track the frame's own box (not the window): rAF-throttled ResizeObserver.\n useLayoutEffect(() => {\n const el = frameRef.current\n /* v8 ignore next -- the ref is always attached by effect time: the frame div renders unconditionally. */\n if (el === null) return\n let raf: number | null = null\n let disposed = false\n const measure = () => {\n const width = el.getBoundingClientRect().width\n if (width > 0) actions.setViewportWidth(width)\n }\n measure()\n const observer = new ResizeObserver(() => {\n if (disposed) return\n raf ??= requestAnimationFrame(() => {\n raf = null\n measure()\n })\n })\n observer.observe(el)\n return () => {\n disposed = true\n observer.disconnect()\n if (raf !== null) cancelAnimationFrame(raf)\n }\n }, [actions])\n\n const narrow = viewport < SIDEBAR_AUTO_COLLAPSE\n const sidebarCollapsed = narrow ? !layoutInfo.narrowExpanded : layoutInfo.sidebar === 0\n const sidebarPreference = sidebarCollapsed\n ? 0\n : layoutInfo.sidebar === 0 ? SIDEBAR_DEFAULT : layoutInfo.sidebar\n const rightbarPreference = layoutInfo.rightbar ?? viewport * RIGHTBAR_DEFAULT_RATIO\n // Desktop reopen controls occupy the frame's shell.leading seat (macOS) or\n // the Windows caption row; neither platform keeps an icon rail.\n const darwin = document.documentElement.dataset.platform === 'darwin'\n const collapsedWidth = darwin\n || document.documentElement.hasAttribute('data-windows-titlebar') ? 0 : SIDEBAR_COLLAPSED\n // Opening on a narrow frame collapses the left sidebar. Eligibility must\n // include that space before the occupant's first shown report arrives.\n const normal = computeColumns(viewport, !layoutInfo.rightbarShown && narrow ? 0 : sidebarPreference, rightbarPreference, collapsedWidth)\n const cols = computeColumns(viewport, sidebarPreference, layoutInfo.rightbarTrack ? rightbarPreference : 0, collapsedWidth)\n const colsRef = useRef(cols)\n colsRef.current = cols\n const rightbarWidth = useRef(normal.rightbar)\n rightbarWidth.current = normal.rightbar\n\n // The drag base is the rendered width captured at drag start (grabbing a\n // concession-clamped panel must not jump back to the stored preference);\n // it stays frozen for the whole gesture so dx deltas do not compound.\n const sidebarBase = useRef(0)\n const rightbarBase = useRef(0)\n // Track-level transitions pause for the whole gesture: eased tracks would\n // detach the column edge from the pointer (AppFrame.module.css).\n const [dragging, setDragging] = useState(false)\n // Track easing is scoped to a discrete open/close toggle: data-animating\n // goes up when the collapse state or the rightbar track flips and comes down\n // at transition end (timeout as the reduced-motion/covered-frame fallback).\n // Steady-state viewport updates stay instant (AppFrame.module.css), and so\n // does a toggle arriving together with a viewport change \u2014 that is the\n // responsive auto-collapse firing mid window-resize, where easing would\n // chase the live window edge. The counter restarts the settle window when a\n // re-toggle interrupts a running transition.\n const [animating, setAnimating] = useState(0)\n const trackToggle = `${sidebarCollapsed}:${layoutInfo.rightbarTrack}`\n const previousToggle = useRef(trackToggle)\n const previousViewport = useRef(viewport)\n useLayoutEffect(() => {\n const viewportChanged = previousViewport.current !== viewport\n previousViewport.current = viewport\n if (previousToggle.current === trackToggle) return\n previousToggle.current = trackToggle\n if (viewportChanged) return\n setAnimating(token => token + 1)\n }, [trackToggle, viewport])\n useEffect(() => {\n if (animating === 0) return\n const frame = frameRef.current\n /* v8 ignore next -- the ref is always attached by effect time: the frame div renders unconditionally. */\n if (frame === null) return\n const settle = () => { setAnimating(0) }\n const onTransitionEnd = (event: TransitionEvent) => {\n if (event.target === frame && event.propertyName === 'grid-template-columns') settle()\n }\n frame.addEventListener('transitionend', onTransitionEnd)\n const timer = setTimeout(settle, 600)\n return () => {\n frame.removeEventListener('transitionend', onTransitionEnd)\n clearTimeout(timer)\n }\n }, [animating])\n const onDragEnd = useCallback(() => { setDragging(false) }, [])\n const onSidebarStart = useCallback(() => { sidebarBase.current = colsRef.current.sidebar; setDragging(true) }, [])\n const onSidebarDrag = useCallback((dx: number) => {\n actions.setSidebar(sidebarBase.current + dx)\n }, [actions])\n const onRightbarStart = useCallback(() => { rightbarBase.current = rightbarWidth.current; setDragging(true) }, [])\n const onRightbarDrag = useCallback((dx: number) => {\n actions.setRightbar(rightbarBase.current - dx)\n }, [actions])\n const productTitle = process.env.DSH_CLIENT_TITLE ?? t('brand.localBuild')\n // The rendered template lets the grid solve the squeeze natively: the centre\n // declares its protected minimum and the right column bids up to the clamped\n // preference, so a window resize lands in the same layout pass as the frame\n // edge. The JS solve lags the viewport by a ResizeObserver + rAF frame; when\n // it priced the squeeze itself, the centre column absorbed each width change\n // whole and was corrected two frames later \u2014 visible jitter. cols keeps only\n // the discrete decisions (track present, collapse state) and the drag base.\n const rightbarMax = cols.rightbar === 0 ? 0 : clampWidth(rightbarPreference, RIGHTBAR_MIN, viewport * RIGHTBAR_MAX_RATIO)\n const sidebar = useMemo(() => renderSlot('sidebar', {\n collapsed: sidebarCollapsed,\n width: cols.sidebar,\n }), [renderSlot, sidebarCollapsed, cols.sidebar])\n const main = useMemo(() => (\n <MainPanel usePanelInfo={usePanelInfo} renderSlot={renderSlot} />\n ), [usePanelInfo, renderSlot])\n const overlays = useMemo(() => renderSlot('shell.overlay', {}), [renderSlot])\n // Window-chrome seat over the main panels' top-left corner: only a fully\n // hidden sidebar column on macOS desktop leaves window chrome without a\n // home \u2014 the Windows zero-width collapse keeps its controls in the caption\n // row (ui-sidebar). AppFrame.module.css publishes the matching\n // --dsh-frame-leading-clearance under the same collapsed condition.\n const leading = useMemo(() => renderSlot('shell.leading', {}), [renderSlot])\n const leadingMounted = darwin && sidebarCollapsed\n\n return (\n <div\n ref={frameRef}\n className={css.frame}\n style={{\n ...(document.documentElement.hasAttribute('data-windows-titlebar')\n ? { '--dsh-windows-sidebar-width': `${cols.sidebar}px` } : {}),\n gridTemplateColumns:\n `${cols.sidebar}px minmax(${cols.rightbar === 0 ? 0 : CENTER_MIN}px, 1fr) minmax(0px, ${rightbarMax}px)`,\n }}\n data-sidebar-collapsed={sidebarCollapsed || undefined}\n data-rightbar-collapsed={cols.rightbar === 0 || undefined}\n data-rightbar-fullscreen={layoutInfo.rightbarFullscreen || undefined}\n data-rightbar-instant={layoutInfo.rightbarInstant || undefined}\n data-dragging={dragging || undefined}\n data-animating={animating > 0 || undefined}\n >\n <DocumentTitle\n productTitle={productTitle}\n useSessions={useSessions}\n usePanelInfo={usePanelInfo}\n />\n <div className={css.sidebarCol}>\n {sidebar}\n </div>\n <>\n <CenterColumn covered={layoutInfo.rightbarFullscreen}>{main}</CenterColumn>\n <RightbarColumn>\n {renderSlot('rightbar', { width: normal.rightbar, viewportWidth: viewport, canShow: normal.rightbar > 0 })}\n </RightbarColumn>\n </>\n <div className={css.overlayLayer} data-shell-overlay>\n {overlays}\n </div>\n {leadingMounted && (\n <div className={css.leadingSeat} data-shell-leading>\n {leading}\n </div>\n )}\n {/* The collapsed rail is fixed-width: no resize handle while closed. */}\n {!sidebarCollapsed && <DragHandle side=\"sidebar\" left={cols.sidebar} onStart={onSidebarStart} onDrag={onSidebarDrag} onEnd={onDragEnd} />}\n {layoutInfo.rightbarShown && !layoutInfo.rightbarFullscreen && normal.rightbar > 0 && (\n <DragHandle side=\"rightbar\" left={viewport - normal.rightbar} onStart={onRightbarStart} onDrag={onRightbarDrag} onEnd={onDragEnd} />\n )}\n </div>\n )\n}\n", "/**\n * Normal column geometry: the right column shrinks, then loses its track,\n * before the center drops below its minimum. The sidebar never concedes here;\n * AppFrame supplies its effective preference after responsive collapse.\n */\n\n/** Resolved widths for one frame. */\nexport interface Columns { sidebar: number; center: number; rightbar: number }\n\n/** Center width protected while the normal right column is open. */\nexport const CENTER_MIN = 400\n/** Sidebar drag clamp floor. */\nexport const SIDEBAR_MIN = 264\n/** Sidebar drag clamp ceiling. */\nexport const SIDEBAR_MAX = 420\n/** Sidebar width before any user drag. */\nexport const SIDEBAR_DEFAULT = 280\n/** Closed-sidebar rail: a 24px icon column between 16px horizontal paddings. */\nexport const SIDEBAR_COLLAPSED = 56\n/** Viewport width below which the sidebar auto-collapses to the rail (deepsuite\n * LG breakpoint); a manual toggle below it re-expands over the squeezed center\n * (stores.ts narrowExpanded). */\nexport const SIDEBAR_AUTO_COLLAPSE = 1024\n/** Right column drag clamp floor. */\nexport const RIGHTBAR_MIN = 300\n/** Maximum normal right panel width as a fraction of the frame. */\nexport const RIGHTBAR_MAX_RATIO = 0.7\n/** First-open right panel preference as a fraction of the frame. */\nexport const RIGHTBAR_DEFAULT_RATIO = 0.45\n\n/**\n * Clamp a panel width into its contract range.\n * @param px - requested width.\n * @param min - range lower bound.\n * @param max - range upper bound.\n * @returns the clamped width.\n */\nexport function clampWidth(px: number, min: number, max: number): number {\n return Math.min(max, Math.max(min, Math.round(px)))\n}\n\n/**\n * Solve the three column widths for one viewport frame.\n * @param viewport - available frame width in px.\n * @param sidebar - sidebar width preference in px (0 = closed).\n * @param rightbar - requested right panel width in px (0 = no track).\n * @param collapsedWidth - track width of the closed sidebar; the default keeps\n * the icon rail, 0 hides the column entirely (macOS desktop).\n * @returns actual widths after shrinking or removing the right track; only\n * without that track may the center fall below its minimum, down to zero.\n */\nexport function computeColumns(viewport: number, sidebar: number, rightbar: number, collapsedWidth = SIDEBAR_COLLAPSED): Columns {\n const s = sidebar === 0 ? collapsedWidth : clampWidth(sidebar, SIDEBAR_MIN, SIDEBAR_MAX)\n const available = viewport - s - CENTER_MIN\n const r = rightbar === 0 || available < RIGHTBAR_MIN\n ? 0\n : Math.min(available, clampWidth(rightbar, RIGHTBAR_MIN, viewport * RIGHTBAR_MAX_RATIO))\n return { sidebar: s, center: Math.max(0, viewport - s - r), rightbar: r }\n}\n", "/** Browser title selection follows the active main panel without subscribing the frame. */\nimport { useEffect } from 'react'\nimport type { PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots'\n\n/** Props for the browser title projection. */\nexport type DocumentTitleProps = Pick<PropsRuntime<'root'>, 'useSessions' | 'usePanelInfo'> & {\n /** Build-configured or localized product title. */\n productTitle: string\n}\n\n/**\n * Project the selected durable session title into the browser title and\n * restore the build-selected product title when unmounted.\n * @param props - Selected session title projection.\n * @returns No rendered content.\n */\nexport function DocumentTitle({ useSessions, usePanelInfo, productTitle }: DocumentTitleProps): null {\n const showSessionTitle = usePanelInfo(info => info.activePanelId === null)\n const title = useSessions((state) => {\n const current = Object.values(state.byId)\n .find(session => (session.retainedBy.mainView ?? 0) > 0)?.id\n return !showSessionTitle || current === undefined ? undefined : state.byId[current]?.title\n })\n useEffect(() => {\n document.title = title === undefined ? productTitle : `${title} \u2014 ${productTitle}`\n return () => { document.title = productTitle }\n }, [productTitle, title])\n return null\n}\n", ".frame {\n position: relative; /* anchors the drag handles, which straddle column borders */\n display: grid;\n grid-template-rows: 100%;\n height: 100%;\n overflow: hidden;\n background: var(--dsw-alias-bg-base);\n}\n\n/* Only a discrete collapse/expand toggle eases the tracks (the TSX holds\n data-animating across the toggle on the deepsuite sider curve). Steady-state\n tracks move only with the viewport, and those updates must land instantly:\n an eased track chases the live window edge and the centre column visibly\n rubber-bands while the user resizes the window. */\n.frame[data-animating] {\n transition: grid-template-columns var(--ds-transition-duration-slow) var(--ds-ease-in-out);\n}\n\n/* Dragging writes widths at pointer cadence; easing them would detach the\n column from the handle. */\n.frame[data-dragging] {\n transition: none;\n}\n\n/* The Windows caption row remains outside every conversation and file panel. */\n:global([data-windows-titlebar]) .frame {\n --dsh-windows-content-radius: 16px;\n box-sizing: border-box;\n padding-top: var(--dsh-windows-titlebar-height);\n grid-template-rows: minmax(0, 1fr);\n background: var(--dsw-specific-sidebar-fill);\n}\n\n:global([data-windows-titlebar]) .centerCol {\n background: var(--dsw-alias-bg-base);\n border-radius: var(--dsh-windows-content-radius) 0 0 0;\n corner-shape: round;\n}\n\n:global([data-windows-titlebar]) .frame::before {\n content: '';\n position: absolute;\n inset: 0 0 auto;\n height: var(--dsh-windows-titlebar-height);\n background: var(--dsw-specific-sidebar-fill);\n -webkit-app-region: drag;\n}\n\n:global([data-windows-titlebar]) .sidebarCol {\n border-right: none;\n}\n\n:global([data-windows-titlebar]) .handle {\n top: var(--dsh-windows-titlebar-height);\n}\n\n@media (prefers-reduced-motion: reduce) {\n .frame[data-animating] {\n transition: none;\n }\n}\n\n.sidebarCol {\n min-width: 0;\n overflow: hidden;\n background: var(--dsw-specific-sidebar-fill);\n border-right: 0.5px solid var(--dsw-alias-border-l3);\n}\n\n.centerCol {\n min-width: 0;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n}\n\n/* Keep the covered main tree mounted and measured, but out of paint and focus.\n A glass theme can create a stacking context on the right panel, trapping its\n dock layer below main content. Fullscreen owns the visible center regardless\n of that theme; restoring it preserves the same composer and draft. */\n.frame[data-rightbar-fullscreen] .centerCol {\n visibility: hidden;\n}\n\n/* macOS desktop: the frame goes transparent so window vibrancy reaches the\n sidebar column, which keeps only a translucent tint; the centre paints the\n base background itself to stay opaque. The sidebar/centre separator moves\n to the opaque centre: on the translucent sidebar the alpha border mixes\n with the wallpaper and reads as a dark seam. */\n:global([data-platform='darwin']) .frame {\n background: transparent;\n}\n\n/* The constant step below the window's top strip (traffic lights, sidebar\n toggle, shell.leading controls), the same in both sidebar states. Entry\n pages in the main panel (plugin manager, settings-like pages \u2014 not the\n conversation, which owns its header) pad their top by it so their leading\n content clears the strip, and overlay primitives add their own safe inset.\n Declared on the root element rather than the frame so\n overlays portalled to document.body inherit it too. */\n:global(html[data-platform='darwin']) {\n --dsh-frame-top-clearance: 48px;\n}\n\n/* In-frame Windows content already clears the caption through .frame padding. */\n:global(html[data-windows-titlebar]) {\n --dsh-frame-top-clearance: var(--dsh-windows-titlebar-height);\n --dsh-frame-chrome-top: var(--dsh-windows-titlebar-height);\n}\n\n/* Portalled overlays share a viewport inset without adding space to entry pages. */\n:global(html[data-platform='darwin']),\n:global(html[data-windows-titlebar]) {\n --dsh-frame-overlay-top: calc(var(--dsh-frame-top-clearance) + 20px);\n}\n\n:global(html[data-platform='darwin'][data-fullscreen]),\n:global(html[data-windows-titlebar][data-fullscreen]) {\n --dsh-frame-overlay-top: 20px;\n --dsh-frame-chrome-top: 0px;\n}\n\n:global([data-platform='darwin']) .sidebarCol {\n /* A blue wash over the top of the translucent tint, gone by a third of the\n column; a faint blue-grey-violet rises through the bottom third; and a\n faint blue cast is mixed into the tint itself. Every layer stays\n transparent so vibrancy shows. */\n background:\n linear-gradient(\n to bottom,\n rgb(122 155 240 / 0.1),\n rgb(122 155 240 / 0) 35%,\n rgb(143 137 184 / 0) 68%,\n rgb(143 137 184 / 0.09)\n ),\n color-mix(in srgb, color-mix(in srgb, var(--dsw-specific-sidebar-fill) 97%, rgb(122 155 240)) 40%, transparent);\n border-right: none;\n}\n\n/* Dark drops the blue cast (the light-mode wash reads purple over dark fills)\n and thins the fill so more wallpaper shows; the washes stay. */\n:global([data-platform='darwin']) :global([data-ds-dark-theme]) .sidebarCol {\n background:\n linear-gradient(\n to bottom,\n rgb(122 155 240 / 0.08),\n rgb(122 155 240 / 0) 35%,\n rgb(143 137 184 / 0) 68%,\n rgb(143 137 184 / 0.07)\n ),\n color-mix(in srgb, var(--dsw-specific-sidebar-fill) 50%, transparent);\n}\n\n/* macOS Reduce Transparency: the OS flattens the window's vibrancy layer to a\n solid grey, so the thin tint and washes read washed-out over it. Replace\n them with a 90%-opaque fill of the same token in both themes (the dark\n selector repeats so this outranks its thinner fill). */\n@media (prefers-reduced-transparency: reduce) {\n :global([data-platform='darwin']) .sidebarCol,\n :global([data-platform='darwin']) :global([data-ds-dark-theme]) .sidebarCol {\n background: color-mix(in srgb, var(--dsw-specific-sidebar-fill) 90%, transparent);\n }\n}\n\n:global([data-platform='darwin']) .centerCol {\n background: var(--dsw-alias-bg-base);\n border-left: 0.5px solid var(--dsw-alias-border-l3);\n}\n\n/* The right track paints the base ground on the transparent frame: while the\n track and the occupant's translateX slide ride the same curve, the grid\n eases in layout and the transform on the compositor, so frames where they\n diverge would otherwise show vibrancy glass between the centre's right edge\n and the incoming panel. The occupant's opaque panel covers this at rest. */\n:global([data-platform='darwin']) .rightbarCol {\n background: var(--dsw-alias-bg-base);\n}\n\n/* The darwin closed sidebar has no rail: the centre reaches the window edge,\n where a separator would draw a seam against nothing. */\n:global([data-platform='darwin']) [data-sidebar-collapsed] .centerCol {\n border-left: none;\n}\n\n/* Published while the shell.leading seat is mounted (same condition as the\n TSX mount: darwin with the sidebar collapsed \u2014 the collapse that hides the\n column entirely): the inline band the window chrome occupies, measured from\n the frame's left edge \u2014 traffic lights to x 68, controls at x 88\n (28 + 8 + 28), then 8px of air. Main panels whose content reaches the\n top-left corner pad by this. */\n:global([data-platform='darwin']) .frame[data-sidebar-collapsed] {\n --dsh-frame-leading-clearance: 160px;\n}\n\n/* Fullscreen hides the traffic lights (preload mirrors the window state onto\n html[data-fullscreen]): the seat takes their band and the clearance keeps\n only the controls (12 + 28 + 8 + 28 + 8). The 12px start matches the\n expanded sidebar strip's inline padding (ui-sidebar .topStrip), so\n collapsing never shifts the toggle. */\n:global([data-platform='darwin'][data-fullscreen]) .frame[data-sidebar-collapsed] {\n --dsh-frame-leading-clearance: 84px;\n}\n\n:global([data-platform='darwin'][data-fullscreen]) .leadingSeat {\n left: 12px;\n}\n\n/* The frame declares no window drag of its own: every chrome row owns the drag\n over its own box (ui-web base.css holds the one rule; the ui-theme app-region\n gate lists the rows). The ordering rule that replaces the old \"band first\"\n invariant: a surface that covers the window and must stay clickable portals\n beside #root, which puts it after every drag row in document order. The Windows\n caption row above is the other platform's chrome and stays. */\n\n/* The seat itself: the two 28px controls centered on the conversation title\n row (10px header inset + 30px row \u2192 centre y 25) and level with the traffic\n lights (centre y \u2248 24). Sits above column content, below frame overlays\n (20) and the fullscreen right panel (40). The box subtracts itself from any\n window drag row beneath (Electron app-regions are geometry, not stacking). */\n.leadingSeat {\n position: absolute;\n top: 11px;\n left: 88px;\n z-index: 15;\n display: flex;\n align-items: center;\n -webkit-app-region: no-drag;\n}\n\n/* Drag handles are frame children (columns clip overflow): an 8px hit strip\n centered on the column border via inline left, above column content. No\n handle draws a visible pill: the details column was the only one that did,\n and the right column never had one. The right handle sits above the right\n panel (which states z-index 10) so it stays grabbable when the panel hangs\n over the centre. */\n.handle {\n position: absolute;\n top: 0;\n bottom: 0;\n width: 8px;\n margin-left: -4px;\n cursor: col-resize;\n z-index: 11;\n touch-action: none;\n}\n\n/* Rides the same curve as the tracks so the pill stays on the moving border\n during collapse/expand; instant at steady state (viewport-driven moves)\n and while dragging. */\n.frame[data-animating] .handle {\n transition: left var(--ds-transition-duration-slow) var(--ds-ease-in-out);\n}\n\n.frame[data-dragging] .handle {\n transition: none;\n}\n\n/* Fullscreen covers the frame while its underlying columns enter or exit. */\n.frame[data-rightbar-fullscreen],\n.frame[data-rightbar-fullscreen] .handle,\n.frame[data-rightbar-instant],\n.frame[data-rightbar-instant] .handle {\n transition: none;\n}\n\n@media (prefers-reduced-motion: reduce) {\n .frame[data-animating] .handle {\n transition: none;\n }\n}\n\n/*\n * The right column never clips: its occupant anchors a fixed-width panel to the\n * column's right edge (the frame's edge, which never moves) and lets the track\n * decide whether the centre makes room. With no track the panel hangs over the\n * centre from a zero-width column, and while the track animates the panel stays\n * where it is. The occupant draws its own left border.\n */\n.rightbarCol {\n position: relative;\n min-width: 0;\n overflow: visible;\n}\n\n.overlayLayer {\n position: absolute;\n inset: 0;\n z-index: 20;\n pointer-events: none;\n}\n\n.overlayLayer > * {\n pointer-events: auto;\n}\n", "/**\n * Root-owned frame measurement, panel preferences, and presentation reports.\n * The registration supplies a fresh store and binds its actions to ctx.layout.\n */\nimport { defineStore, type EngineStoreHandle } from '@deepseek-ai/dsh-client-store'\nimport type { MainPanelId } from './service.ts'\nimport {\n clampWidth, RIGHTBAR_DEFAULT_RATIO, RIGHTBAR_MAX_RATIO, RIGHTBAR_MIN,\n SIDEBAR_AUTO_COLLAPSE, SIDEBAR_DEFAULT, SIDEBAR_MAX, SIDEBAR_MIN,\n} from './columns.ts'\n\n/**\n * Transient layout preferences. Responsive concessions never rewrite widths;\n * the right panel's expanded state belongs to its occupant.\n */\ntype LayoutState = {\n panelInfo: {\n /** Null selects the Conversation; global panels keep the current Session intact. */\n activePanelId: MainPanelId | null\n }\n layoutInfo: LayoutInfo\n}\n\ntype LayoutInfo = {\n sidebar: number\n /** Last positive frame measurement; window width bootstraps the first render. */\n viewportWidth: number\n narrowExpanded: boolean\n /**\n * Saved right panel width in px, or null before its first opening. Resizing\n * the frame and closing the panel preserve this preference.\n */\n rightbar: number | null\n /**\n * Whether the right panel is drawn at all, in either presentation.\n *\n * Derived chrome, not a source of truth: whether the right surface is\n * expanded is a recorded fact owned by that surface, reported here so the\n * frame can place the panel's resize handle. The occupant reports it; nothing\n * else writes it.\n */\n rightbarShown: boolean\n /**\n * Whether the normal panel width reserves a grid track, including beneath\n * fullscreen. Reported by the occupant; always false while hidden.\n */\n rightbarTrack: boolean\n /** Reported fullscreen presentation; hides the outer resize handle. */\n rightbarFullscreen: boolean\n /** Suppress transitions for a fullscreen exit until another geometry action. */\n rightbarInstant: boolean\n}\n\n/**\n * Annotation twin of the actions literal below (the export needs a declared\n * return type); drift fails assignability at the defineStore call.\n */\ntype LayoutActions = {\n selectPanel: (draft: LayoutState, panelId: MainPanelId | null) => void\n retainMainPanels: (draft: LayoutState, panelIds: readonly string[]) => void\n setSidebar: (draft: LayoutState, px: number) => void\n toggleSidebar: (draft: LayoutState) => void\n setViewportWidth: (draft: LayoutState, width: number) => void\n setRightbar: (draft: LayoutState, px: number) => void\n openRightbar: (draft: LayoutState, track: boolean, fullscreen: boolean) => void\n closeRightbar: (draft: LayoutState) => void\n}\n\n/**\n * Create the layout panel store handle. For the sidebar the preference IS the\n * width, so closing it forgets its drag width \u2014 reopening restores the contract\n * default. The right panel initializes at 45% of the frame on first opening\n * and keeps that px preference across resizes and close. Drag writes clamp to\n * the current frame's range. Narrow sidebar toggles change only the expansion\n * override; opening the right panel clears that override.\n * @returns the store handle (spec + type + identity + factory in one).\n */\nexport function createLayoutStore(): EngineStoreHandle<LayoutState, LayoutActions> {\n const handle = defineStore({\n init: (): LayoutState => ({\n panelInfo: { activePanelId: null },\n layoutInfo: {\n sidebar: SIDEBAR_DEFAULT,\n viewportWidth: window.innerWidth,\n narrowExpanded: false,\n rightbar: null,\n rightbarShown: false,\n rightbarTrack: false,\n rightbarFullscreen: false,\n rightbarInstant: false,\n },\n }),\n actions: {\n selectPanel: (d, panelId: MainPanelId | null) => {\n d.panelInfo.activePanelId = panelId\n },\n retainMainPanels: (d, panelIds: readonly string[]) => {\n if (d.panelInfo.activePanelId !== null && !panelIds.includes(d.panelInfo.activePanelId)) {\n d.panelInfo.activePanelId = null\n }\n },\n setSidebar: (d, px: number) => {\n d.layoutInfo.rightbarInstant = false\n d.layoutInfo.sidebar = clampWidth(px, SIDEBAR_MIN, SIDEBAR_MAX)\n },\n // Narrow toggles flip only the override: the width preference survives\n // untouched, so re-widening restores the pre-squeeze layout.\n toggleSidebar: (d) => {\n d.layoutInfo.rightbarInstant = false\n if (d.layoutInfo.viewportWidth < SIDEBAR_AUTO_COLLAPSE) d.layoutInfo.narrowExpanded = !d.layoutInfo.narrowExpanded\n else d.layoutInfo.sidebar = d.layoutInfo.sidebar === 0 ? SIDEBAR_DEFAULT : 0\n },\n // Crossing the breakpoint in either direction drops the override: the\n // narrow default is auto-collapsed, the wide state is the preference.\n setViewportWidth: (d, width: number) => {\n if (d.layoutInfo.viewportWidth === width) return\n d.layoutInfo.rightbarInstant = false\n if ((d.layoutInfo.viewportWidth < SIDEBAR_AUTO_COLLAPSE) !== (width < SIDEBAR_AUTO_COLLAPSE)) {\n d.layoutInfo.narrowExpanded = false\n }\n d.layoutInfo.viewportWidth = width\n },\n setRightbar: (d, px: number) => {\n d.layoutInfo.rightbarInstant = false\n d.layoutInfo.rightbar = clampWidth(px, RIGHTBAR_MIN, Math.max(RIGHTBAR_MIN, d.layoutInfo.viewportWidth * RIGHTBAR_MAX_RATIO))\n },\n openRightbar: (d, track: boolean, fullscreen: boolean) => {\n if (!d.layoutInfo.rightbarShown || d.layoutInfo.rightbarTrack !== track || d.layoutInfo.rightbarFullscreen !== fullscreen) {\n d.layoutInfo.rightbarInstant = d.layoutInfo.rightbarFullscreen && !fullscreen\n }\n if (!d.layoutInfo.rightbarShown && d.layoutInfo.viewportWidth < SIDEBAR_AUTO_COLLAPSE) d.layoutInfo.narrowExpanded = false\n d.layoutInfo.rightbar ??= Math.max(RIGHTBAR_MIN, Math.round(d.layoutInfo.viewportWidth * RIGHTBAR_DEFAULT_RATIO))\n d.layoutInfo.rightbarShown = true\n d.layoutInfo.rightbarTrack = track\n d.layoutInfo.rightbarFullscreen = fullscreen\n },\n closeRightbar: (d) => {\n if (d.layoutInfo.rightbarShown) d.layoutInfo.rightbarInstant = d.layoutInfo.rightbarFullscreen\n d.layoutInfo.rightbarShown = false\n d.layoutInfo.rightbarTrack = false\n d.layoutInfo.rightbarFullscreen = false\n },\n },\n })\n return handle\n}\n", "/**\n * LayoutController: the cross-plugin panel-action face behind ctx.layout.\n * Panel geometry and main-panel selection live in the root layout store;\n * the current-session selection lives with the runtime sessions service, and\n * the per-session active view dissolved into ui-conversation's session store\n * (its only consumer). What remains here is the contract other plugins'\n * apply worlds reach for panel transitions (main-panel selection and sidebar toggle,\n * right-panel show/hide from ui-sidebar-right) \u2014 writes stay inside the\n * store's declared action set, shared with the root registration.\n */\nimport type { BoundActions, HostObservable } from '@deepseek-ai/dsh-client-ui-slots'\nimport type { Branded } from '@deepseek-ai/dsh-brand'\nimport type { createLayoutStore } from './stores.ts'\n\n/** Identity shared by a sidebar panel entry and its main-slot occupant. */\nexport type MainPanelId = Branded<'MainPanelId'>\n\n/** Root-scoped navigation state exposed to panel-aware components. */\nexport interface PanelInfo {\n /** Selected global panel; null displays the current Conversation. */\n readonly activePanelId: MainPanelId | null\n}\n\n/** The layout store's bound action set (framework-baked, draft params peeled). */\nexport type PanelActions = BoundActions<ReturnType<typeof createLayoutStore>>\n\n/** Panel navigation and geometry actions exposed through ctx.layout. */\nexport interface ILayout {\n /** Selected central panel from the same root store used by `usePanelInfo`. */\n readonly panelInfo: HostObservable<PanelInfo>\n /**\n * Select a global central panel without changing the current Session.\n * @param panelId - registered main key, or null to show the Conversation.\n * @throws if the selected main key is not registered; preserves the current selection.\n */\n selectPanel(panelId: MainPanelId | null): void\n /**\n * Start an asynchronous navigation, superseding any earlier pending navigation.\n * @returns a signal aborted by the next navigation or layout disposal; check it before committing UI state.\n */\n beginNavigation(): AbortSignal\n /** Toggle the sidebar panel (closed \u27F7 contract default width). */\n toggleSidebar(): void\n /**\n * Report the right panel's presentation without changing its expanded state.\n * @param track - whether the normal panel width reserves a grid track,\n * including beneath a fullscreen overlay.\n * @param fullscreen - whether the panel covers the frame and hides its outer\n * resize handle; independent of the underlying grid track.\n */\n openRightbar(track: boolean, fullscreen: boolean): void\n /** Report the right panel as hidden: no track, no handle. */\n closeRightbar(): void\n}\n\n/** Cross-plugin panel-action face (ctx.layout). */\nexport class LayoutController implements ILayout {\n private navigation = new AbortController()\n\n /**\n * @param panels - actions of the instance shared with the root entry.\n * @param hasMainPanel - checks the live main-slot registry for a panel id.\n * @param panelInfo - root store's shared central-panel selection source.\n */\n constructor(\n private readonly panels: PanelActions,\n private readonly hasMainPanel: (id: MainPanelId) => boolean,\n readonly panelInfo: HostObservable<PanelInfo>,\n ) {}\n\n /** Select a global panel or return to the Conversation. */\n selectPanel(panelId: MainPanelId | null): void {\n if (panelId !== null && !this.hasMainPanel(panelId)) {\n throw new Error(`layout.selectPanel: main panel \"${panelId}\" is not registered`)\n }\n this.navigation.abort()\n this.panels.selectPanel(panelId)\n }\n\n /** @returns the new pending navigation's cancellation signal. */\n beginNavigation(): AbortSignal {\n this.navigation.abort()\n this.navigation = new AbortController()\n return this.navigation.signal\n }\n\n /** Invalidate pending navigations when the layout owner is unloaded. */\n dispose(): void {\n this.navigation.abort()\n }\n\n /** Toggle the sidebar panel (closed \u27F7 contract default width). */\n toggleSidebar(): void {\n this.panels.toggleSidebar()\n }\n\n /** Report the right panel's track and fullscreen presentation. */\n openRightbar(track: boolean, fullscreen: boolean): void {\n this.panels.openRightbar(track, fullscreen)\n }\n\n /** Report the right panel as hidden: no track, no handle. */\n closeRightbar(): void {\n this.panels.closeRightbar()\n }\n}\n", "/** Layout command labels. */\nexport const zh = { toggle: '\u5C55\u5F00\uFF0F\u6536\u8D77\u5DE6\u4FA7\u680F' }\n/** English labels for the same layout commands. */\nexport const en: Record<keyof typeof zh, string> = { toggle: 'Toggle left sidebar' }\n", "/**\n * Global theme DOM applier: projects the resolved ThemeSnapshot onto the\n * document \u2014 `html { color-scheme }` for native UA chrome (scrollbars, form\n * controls), `body[data-ds-dark-theme]` for the token palette, the active\n * theme's alias-token overrides as inline CSS variables on body, the content\n * font-size axis (`--dsh-content-font-size`), `html[data-ds-theme-source]`\n * for native-chrome mirroring, and one presenter-owned\n * `meta[name=\"theme-color\"]` for surrounding browser UI. Pure DOM writes, no\n * React involvement; the presenter only ever retracts what it wrote itself,\n * so foreign attributes, metadata, and inline styles survive.\n */\nimport type { ThemeSnapshot } from '@deepseek-ai/dsh-client-ui-theme/client'\n\n/** Body attribute selecting the dark base palette in the token stylesheets. */\nexport const DARK_ATTRIBUTE = 'data-ds-dark-theme'\n\n/**\n * Root attribute publishing the theme source (`light`, `dark`, or `system`)\n * for host shells that mirror it into the native theme (the Electron preload\n * forwards it to `nativeTheme.themeSource`, so native chrome, renderer\n * `prefers-color-scheme` queries, and Platform login links follow the app\n * palette on every platform). `system` only when the preference is `system`;\n * a fixed preference (including registered theme ids) publishes its resolved\n * scheme.\n */\nexport const THEME_SOURCE_ATTRIBUTE = 'data-ds-theme-source'\n\n/** Body variable carrying the user's content font size in px. */\nexport const CONTENT_FONT_SIZE_VARIABLE = '--dsh-content-font-size'\n\n/** Applies theme snapshots to the document; one instance per plugin fiber. */\nexport class ThemePresenter {\n /** Token names this presenter wrote in the last apply (its retraction set). */\n private appliedTokens: string[] = []\n /** The single metadata node this presenter inserts and removes. */\n private readonly themeColorMeta: HTMLMetaElement\n\n /** Create the presenter-owned metadata node before the first snapshot arrives. */\n constructor() {\n this.themeColorMeta = document.createElement('meta')\n this.themeColorMeta.name = 'theme-color'\n }\n\n /**\n * Project a snapshot onto the document: set root `color-scheme` and the body\n * palette attribute from `active.colorScheme` (never the id \u2014 `system` is\n * resolved upstream), publish the content font-size axis, then replace the\n * previously applied token variables with `active.tokens`. Browser\n * theme-color metadata follows the computed body background after those\n * writes, so the rendered palette remains the color authority.\n * @param snapshot - resolved theme snapshot from ctx.theme.\n */\n apply(snapshot: ThemeSnapshot): void {\n const scheme = snapshot.active.colorScheme\n document.documentElement.style.colorScheme = scheme\n document.documentElement.setAttribute(THEME_SOURCE_ATTRIBUTE,\n snapshot.preference === 'system' ? 'system' : scheme)\n const body = document.body\n if (scheme === 'dark') body.setAttribute(DARK_ATTRIBUTE, '')\n else body.removeAttribute(DARK_ATTRIBUTE)\n body.style.setProperty(CONTENT_FONT_SIZE_VARIABLE, `${snapshot.fontSize}px`)\n for (const name of this.appliedTokens) body.style.removeProperty(name)\n this.appliedTokens = []\n for (const [name, value] of Object.entries(snapshot.active.tokens)) {\n body.style.setProperty(name, value)\n this.appliedTokens.push(name)\n }\n this.themeColorMeta.content = getComputedStyle(body).backgroundColor\n if (!this.themeColorMeta.isConnected) document.head.append(this.themeColorMeta)\n }\n\n /**\n * Retract root color-scheme, the theme-source attribute, the palette\n * attribute, token variables, the font-size axis, and the owned metadata node.\n */\n dispose(): void {\n document.documentElement.style.removeProperty('color-scheme')\n document.documentElement.removeAttribute(THEME_SOURCE_ATTRIBUTE)\n const body = document.body\n body.removeAttribute(DARK_ATTRIBUTE)\n body.style.removeProperty(CONTENT_FONT_SIZE_VARIABLE)\n for (const name of this.appliedTokens) body.style.removeProperty(name)\n this.appliedTokens = []\n this.themeColorMeta.remove()\n }\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["import_react", "frame", "centerCol", "sidebarCol", "handle", "rightbarCol", "leadingSeat", "overlayLayer"]
7
+ }
@@ -0,0 +1,7 @@
1
+ // .host-source/packages/client/ui-layout/src/index.ts
2
+ function apply() {
3
+ }
4
+ export {
5
+ apply
6
+ };
7
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../.host-source/packages/client/ui-layout/src/index.ts"],
4
+ "sourcesContent": ["/** Host loader entry for the browser-only layout plugin. */\n\n/** Provides no host-side behavior. */\nexport function apply(): void {}\n"],
5
+ "mappings": ";AAGO,SAAS,QAAc;AAAC;",
6
+ "names": []
7
+ }
@@ -0,0 +1,25 @@
1
+ {
2
+ "name": "@deepseek-ai/dsh-client-ui-layout",
3
+ "version": "0.2.0-rc.2",
4
+ "description": "DSH Web Annotator's patched layout provider; derived from DeepSeek Harness",
5
+ "type": "module",
6
+ "license": "MIT",
7
+ "main": "./lib/index.js",
8
+ "exports": {
9
+ ".": "./lib/index.js",
10
+ "./client": "./lib/client.js",
11
+ "./package.json": "./package.json"
12
+ },
13
+ "dsh": {
14
+ "client": {
15
+ "inject": [
16
+ "@deepseek-ai/dsh-client-locale",
17
+ "@deepseek-ai/dsh-client-ui-renderer",
18
+ "@deepseek-ai/dsh-client-ui-session",
19
+ "@deepseek-ai/dsh-client-ui-theme",
20
+ "@deepseek-ai/dsh-client-shortcuts"
21
+ ],
22
+ "platform": "web"
23
+ }
24
+ }
25
+ }
package/lib/index.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ export declare const name = 'cslkkl-web-annotator';
2
+ export declare function apply(): void;
package/lib/index.js ADDED
@@ -0,0 +1,9 @@
1
+ // src/index.ts
2
+ var name = "cslkkl-web-annotator";
3
+ function apply() {
4
+ }
5
+ export {
6
+ apply,
7
+ name
8
+ };
9
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/index.ts"],
4
+ "sourcesContent": ["/** A named Host entry; the development bridge and UI own the feature. */\nexport const name = 'cslkkl-web-annotator';\nexport function apply(): void {}\n"],
5
+ "mappings": ";AACO,IAAM,OAAO;AACb,SAAS,QAAc;AAAC;",
6
+ "names": []
7
+ }
package/lib/vite.d.ts ADDED
@@ -0,0 +1,8 @@
1
+ import type { Plugin } from 'vite';
2
+ export interface WebAnnotatorOptions { allowedParentOrigins?: string[]; sourceAnnotations?: boolean }
3
+ export declare function webAnnotator(options?: WebAnnotatorOptions): Plugin;
4
+ /** @deprecated Use WebAnnotatorOptions. */
5
+ export type LayoutCareOptions = WebAnnotatorOptions;
6
+ /** @deprecated Use webAnnotator. */
7
+ export declare const layoutCare: typeof webAnnotator;
8
+ export default webAnnotator;