dsh-claude-desktop-theme 0.2.0 → 0.4.0

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 (50) hide show
  1. package/README.md +76 -54
  2. package/lib/client.js +9392 -2579
  3. package/lib/index.js +387 -20
  4. package/lib/types/client/compat/account-menu.d.ts +4 -4
  5. package/lib/types/client/compat/account-more.d.ts +3 -0
  6. package/lib/types/client/compat/account-theme.d.ts +3 -0
  7. package/lib/types/client/compat/adapter.d.ts +22 -1
  8. package/lib/types/client/compat/browser-header.d.ts +57 -0
  9. package/lib/types/client/compat/browser-menu.d.ts +16 -0
  10. package/lib/types/client/compat/composer-menus.d.ts +6 -3
  11. package/lib/types/client/compat/context-panel.d.ts +47 -0
  12. package/lib/types/client/compat/empty-groups.d.ts +46 -0
  13. package/lib/types/client/compat/files-pane.d.ts +78 -0
  14. package/lib/types/client/compat/header-menu-actions.d.ts +14 -0
  15. package/lib/types/client/compat/header-menus.d.ts +4 -0
  16. package/lib/types/client/compat/host-dom.d.ts +180 -0
  17. package/lib/types/client/compat/pane-chrome.d.ts +29 -0
  18. package/lib/types/client/compat/pane-icons.d.ts +23 -0
  19. package/lib/types/client/compat/pane-tiles.d.ts +37 -0
  20. package/lib/types/client/compat/permission-menu.d.ts +88 -0
  21. package/lib/types/client/compat/relative-file-path.d.ts +2 -0
  22. package/lib/types/client/compat/right-panes.d.ts +16 -0
  23. package/lib/types/client/compat/scroll-pill.d.ts +70 -0
  24. package/lib/types/client/compat/sidebar-navigation.d.ts +11 -0
  25. package/lib/types/client/compat/stats-values.d.ts +18 -1
  26. package/lib/types/client/compat/view-options.d.ts +58 -0
  27. package/lib/types/client/compat/view-switch.d.ts +46 -5
  28. package/lib/types/client/contracts/ports.d.ts +176 -1
  29. package/lib/types/client/features/context-panel/ContextPanel.d.ts +12 -0
  30. package/lib/types/client/features/context-panel/mount.d.ts +20 -0
  31. package/lib/types/client/features/conversation/index.d.ts +5 -3
  32. package/lib/types/client/features/conversation/view-switch-icons.d.ts +13 -0
  33. package/lib/types/client/features/settings/locales.d.ts +7 -0
  34. package/lib/types/client/features/shell/index.d.ts +9 -3
  35. package/lib/types/client/features/sidebar/index.d.ts +1 -1
  36. package/lib/types/client/features/sidebar/navigation-icons.d.ts +6 -0
  37. package/lib/types/client/features/statistics/books.d.ts +1 -2
  38. package/lib/types/client/features/statistics/format.d.ts +4 -4
  39. package/lib/types/client/features/view-options/ViewOptionsCard.d.ts +30 -0
  40. package/lib/types/client/features/view-options/mount.d.ts +25 -0
  41. package/lib/types/client/theme/mount.d.ts +2 -2
  42. package/lib/types/client/theme/palette.d.ts +1 -1
  43. package/lib/types/host/context/compaction.d.ts +26 -0
  44. package/lib/types/host/context/pricing.d.ts +99 -0
  45. package/lib/types/host/context/service.d.ts +24 -0
  46. package/lib/types/host/context/unit.d.ts +136 -0
  47. package/lib/types/host/index.d.ts +18 -0
  48. package/lib/types/shared/config.d.ts +26 -1
  49. package/lib/types/shared/context.d.ts +243 -0
  50. package/package.json +6 -3
@@ -0,0 +1,47 @@
1
+ import type { ContextPanelPort, ContextProjectionPort } from '../contracts/ports.ts';
2
+ /**
3
+ * The context ring's breakdown panel, driven instead of replaced.
4
+ *
5
+ * DSH opens its own 264px panel from the ring's `onClick` and publishes no face
6
+ * that reads or drives it, so this module owns the interaction outright: it
7
+ * intercepts the trigger's click, holds the open and expanded state, and reads
8
+ * the numbers off the session list — where the host's own `contextPressure` and
9
+ * `contextBreakdown` projections, and this plugin's `ccdContext`, all arrive as
10
+ * wire values.
11
+ *
12
+ * Three details decide how it is written:
13
+ *
14
+ * - **The trigger's click is intercepted in the capture phase.** DSH's handler
15
+ * is React's `onClick`, delegated at the renderer root; stopping the event on
16
+ * the button before it bubbles keeps that handler from running, so the host's
17
+ * panel never opens. This is the same device `compat/view-options.ts` uses for
18
+ * the sidebar's menu, and it is why the host's open state never has to be
19
+ * driven — a driven panel would be dismissed by the host's own
20
+ * `useDismissOnOutsidePointer` the moment the reader clicked inside ours.
21
+ * - **The document element carries the open marker.** `composer.css` keys the
22
+ * host panel's removal off `[data-ccd-context-open]`, so a click that somehow
23
+ * reaches DSH's handler still leaves the reader looking at one panel. The
24
+ * marker is belt to the interception's braces, not the mechanism.
25
+ * - **A trigger that goes away closes the panel.** The ring is drawn by the
26
+ * Conversation page, so a session switch, a page change or a compaction that
27
+ * empties the reading all replace it; each of those has to put the panel away
28
+ * rather than leave it hanging over a control that is no longer there.
29
+ */
30
+ /** Marks the host popup this module has taken over; the sheet keeps it off screen. */
31
+ export declare const OPEN_MARKER = "data-ccd-context-open";
32
+ /** Marks the ring trigger while this plugin's panel is the one on screen. */
33
+ export declare const OPEN_ATTRIBUTE = "data-ccd-context-panel";
34
+ /** The driver's own face, plus the release the mounting scope holds. */
35
+ export interface ContextPanelDriver {
36
+ readonly port: ContextPanelPort;
37
+ dispose(): void;
38
+ }
39
+ /**
40
+ * Watch the context ring and open this plugin's panel from it.
41
+ *
42
+ * @param document - renderer document carrying the Conversation page.
43
+ * @param projections - the host's context readings, off the session list.
44
+ * @param report - sink for observer failures; the ring keeps DSH's own panel.
45
+ * @returns the port the card reads through, and the release of every observer.
46
+ */
47
+ export declare function createContextPanelDriver(document: Document, projections: ContextProjectionPort, report: (error: unknown) => void): ContextPanelDriver;
@@ -0,0 +1,46 @@
1
+ import type { Disposer, SidebarSessionsPort, ViewOptionsSettingsPort } from '../contracts/ports.ts';
2
+ /**
3
+ * Workspaces with nothing to show, kept out of the sidebar.
4
+ *
5
+ * The `显示空分组` row in the view-options card writes `view.showEmptyGroups`,
6
+ * whose default is off: a Workspace whose rows are all hidden by the current
7
+ * filter disappears from the column instead of standing there as a heading over
8
+ * nothing. With no durable history, all headings give way to a welcome prompt
9
+ * even if empty groups are enabled. DSH has no such setting of its own — the host draws one empty state
10
+ * for the whole tree (`EmptySessions`, `data-row-key="empty"`, rendered only
11
+ * when there are no groups at all), never one per Workspace — so this is the
12
+ * plugin's own behaviour and this module is where it is decided.
13
+ *
14
+ * A group is the `WorkspaceBrowser` box that holds one Workspace's row, its
15
+ * nested groups and its Session rows (`._7514NG_groupSection`). It is empty
16
+ * when nothing under it is a row the reader can see:
17
+ *
18
+ * - a Session row keeps it (except one `compat/blank-session-rows.ts` already
19
+ * hides — a provisional New Session is not something to show a group for);
20
+ * - the `overflow:` row ("Show {n} more sessions") keeps it, because it is the
21
+ * host saying there are more rows behind it;
22
+ * - a nested group's Sessions count, which is why the test walks the whole
23
+ * subtree rather than the direct children;
24
+ * - collapsed membership comes from the host catalogs and native filter;
25
+ * while those are loading, an unknown collapsed Workspace stays reachable.
26
+ *
27
+ * The marker is an attribute the sidebar sheet turns into `display: none`. It is
28
+ * written after the commit that drew the rows, which is the one thing about this
29
+ * module worth knowing: the host measures its keyed rows inside that commit
30
+ * (`blank-session-rows.ts` records the 200 ms glide that follows a late change),
31
+ * so a group hidden here can arrive with the rows below it already placed. The
32
+ * plugin's own default makes this the common path, so the first paint is checked
33
+ * on a real machine; if it shows, the fix is to write the same attribute from
34
+ * the previous pass's answer before the rows mount, not to move this test.
35
+ *
36
+ * @param document - renderer document carrying the sidebar.
37
+ * @param hideEmpty - whether empty groups are being kept out (the config's
38
+ * `view.showEmptyGroups`, inverted).
39
+ * @param report - sink for observer failures; the column stays as the host drew it.
40
+ * @returns disposer that disconnects the observer and clears every marker.
41
+ */
42
+ export declare function mountEmptyGroups(document: Document, hideEmpty: boolean, report: (error: unknown) => void, options?: {
43
+ source?: SidebarSessionsPort | null;
44
+ settings?: ViewOptionsSettingsPort;
45
+ showAll?: () => void;
46
+ }): Disposer;
@@ -0,0 +1,78 @@
1
+ import type { Disposer } from '../contracts/ports.ts';
2
+ /**
3
+ * The Files pane's own three controls, and the empty column beside it
4
+ * (DESIGN.md §6.9).
5
+ *
6
+ * `right-panel.css` dresses what the host draws. Three things the reference
7
+ * draws have nothing in the host's pane to dress, so this module supplies them
8
+ * as nodes the sheet styles, and keeps them in place across React's renders:
9
+ *
10
+ * **The filter field.** The host's `FilesBody` header is a root path with a
11
+ * reload and the open-in-app actions after it — there is no filter in the
12
+ * package at all. The reference's pane leads with a rounded field over the tree
13
+ * and nothing else, so the field takes the path's seat (the sheet hides the
14
+ * label) and the host's own controls keep theirs at the row's end. Typing
15
+ * filters the *loaded* rows by name: a row stays when its own name contains the
16
+ * query or when it is an ancestor of a row that does. The host lists a
17
+ * directory only once it is expanded, so a filtered tree can only narrow what
18
+ * the reader has already opened — the reference searches its session on the
19
+ * server, which this interface has no face for.
20
+ *
21
+ * **The tree's show / hide control.** The reference's own pane hides its file
22
+ * tree from a control on the divider between its two columns and, once hidden,
23
+ * leaves a small affordance at the pane's leading edge to bring it back. This
24
+ * pane has one column, so the control lives in the header line: {@link
25
+ * TOGGLE_ATTRIBUTE} marks the button, {@link TREE_ATTRIBUTE} on the root carries
26
+ * the state, and the sheet swaps the rows for {@link EXPAND_ATTRIBUTE}'s row
27
+ * while the tree is away.
28
+ *
29
+ * **The Files tab's mark.** The host's tab title draws a category-coloured
30
+ * folder; the reference draws a three-row list on a tinted square. The mark
31
+ * cannot be drawn on the host's glyph — a mask would clip the square with it —
32
+ * so {@link TAB_ATTRIBUTE} marks the Files tab, {@link MARK_ATTRIBUTE} is the
33
+ * node that takes the glyph's seat, and the sheet paints both.
34
+ *
35
+ * The empty column is DockKit's, not the Files package's: a dock column no tab
36
+ * has claimed shows one line of the host's copy. The reference's landing state
37
+ * is a folder over a title and a line of guidance, so the host's line is marked
38
+ * ({@link EMPTY_SOURCE_ATTRIBUTE}) and left in the document, and a block this
39
+ * module writes ({@link EMPTY_ATTRIBUTE}) is what the column draws.
40
+ *
41
+ * Everything written here lands on host nodes as `data-ccd-files-*` markers or
42
+ * as plugin-owned nodes beside them, and the disposer takes all of it back.
43
+ * The module is unconditional: the right panel exists in both DSH builds and
44
+ * behind every feature switch.
45
+ */
46
+ /** The state of the tree, written on the Files root: `hidden` or absent. */
47
+ export declare const TREE_ATTRIBUTE = "data-ccd-files-tree";
48
+ /** Marks a row the filter excludes; the sheet does not draw it. */
49
+ export declare const ROW_ATTRIBUTE = "data-ccd-files-hidden";
50
+ /** Marks the Files tab in the panel's strip. */
51
+ export declare const TAB_ATTRIBUTE = "data-ccd-files-tab";
52
+ /** The filter field's own box, and the input inside it. */
53
+ export declare const FIELD_ATTRIBUTE = "data-ccd-files-filter";
54
+ /** The filter's clear control. */
55
+ export declare const CLEAR_ATTRIBUTE = "data-ccd-files-clear";
56
+ /** The header's tree show / hide control, and the pane's own re-open row. */
57
+ export declare const TOGGLE_ATTRIBUTE = "data-ccd-files-toggle";
58
+ export declare const EXPAND_ATTRIBUTE = "data-ccd-files-expand";
59
+ /** The Files tab's mark, in the seat the host's file-type glyph had. */
60
+ export declare const MARK_ATTRIBUTE = "data-ccd-files-mark";
61
+ /** The empty column's block, and the host line it stands in for. */
62
+ export declare const EMPTY_ATTRIBUTE = "data-ccd-files-empty";
63
+ export declare const EMPTY_SOURCE_ATTRIBUTE = "data-ccd-files-empty-source";
64
+ /** One empty column's three parts. */
65
+ export declare const EMPTY_MARK_ATTRIBUTE = "data-ccd-files-empty-mark";
66
+ export declare const EMPTY_TITLE_ATTRIBUTE = "data-ccd-files-empty-title";
67
+ export declare const EMPTY_BODY_ATTRIBUTE = "data-ccd-files-empty-body";
68
+ /** The line a query that matched nothing leaves under the list. */
69
+ export declare const NOMATCH_ATTRIBUTE = "data-ccd-files-nomatch";
70
+ /**
71
+ * Mount the Files pane's filter field, its tree control, its tab mark and the
72
+ * empty column beside it.
73
+ *
74
+ * @param document - renderer document carrying the interface.
75
+ * @param report - sink for observer failures; the host's own pane stays usable.
76
+ * @returns disposer that removes every node, marker and listener added here.
77
+ */
78
+ export declare function mountFilesPane(document: Document, report: (error: unknown) => void): Disposer;
@@ -0,0 +1,14 @@
1
+ import type { Context } from '@deepseek-ai/cordis';
2
+ /** Only host-authoritative identity and mutations cross into the menu renderer. */
3
+ export interface HeaderMenuActions {
4
+ read(id: string): {
5
+ title: string;
6
+ folder: string;
7
+ path: string;
8
+ } | null;
9
+ rename(id: string, title: string): Promise<void>;
10
+ fork(id: string): Promise<void>;
11
+ archive(id: string): Promise<void>;
12
+ subscribe(listener: () => void): () => void;
13
+ }
14
+ export declare function headerMenuActions(ctx: Context): HeaderMenuActions;
@@ -0,0 +1,4 @@
1
+ import type { Disposer } from '../contracts/ports.ts';
2
+ import type { HeaderMenuActions } from './header-menu-actions.ts';
3
+ /** Add reference menus beside the native title without moving React-owned nodes. */
4
+ export declare function mountHeaderMenus(document: Document, actions: HeaderMenuActions, report: (error: unknown) => void): Disposer;
@@ -28,6 +28,15 @@
28
28
  * - `packages/client/ui-attachment/src/client/ComposerAttachments.module.css` (`dVdiKa_`)
29
29
  * - `packages/client/ui-chat/src/client/chat/StatsPills.module.css` (`OpZ85W_`)
30
30
  * - `packages/client/ui-workspace/src/client/WorkspaceBrowser.module.css` (`_7514NG_`)
31
+ * - `packages/client/ui-sidebar-right/src/client/shell/SidebarRight.tsx` (the
32
+ * panel box and its `data-sidebar-right-*` hooks)
33
+ * - `packages/client/ui-dockkit/src/client/DockLayout.tsx` and its
34
+ * `DockLayout.module.css` (`_6nhg2_`), shipped on both installers as part of
35
+ * the `dsh-web-frontend` dist (`data-dockkit-*` hooks)
36
+ * - `packages/client/ui-sidebar-files/src/client/FilesBody.tsx` (the file tree
37
+ * and its `data-files-*` hooks)
38
+ * - `packages/client/ui-workspace/src/client/rows/Rows.module.css` (`jJkEga_`: the
39
+ * Workspace and Session rows, and the primary bundle's copy of the same sheet)
31
40
  * - `packages/client/ui-workspace/src/client/rows/Rows.tsx` (`data-row-key` on the
32
41
  * Workspace and Session rows: `workspace:<key>` / `session:<id>`)
33
42
  * - `packages/client/ui-settings/src/client/SettingsRoot.module.css` (`Dws9Sa_`)
@@ -48,6 +57,75 @@ export declare const HOST: Readonly<{
48
57
  readonly centerColumn: '._6Qf49G_centerCol';
49
58
  readonly rightbarColumn: '._6Qf49G_rightbarCol';
50
59
  readonly resizeHandle: '._6Qf49G_handle';
60
+ /**
61
+ * ui-sidebar-right/shell/SidebarRight.tsx: the right panel's own box, which
62
+ * the host positions absolutely against the column's right edge and sizes
63
+ * inline (the resolved width, or `100vw` in full screen). Its
64
+ * `data-sidebar-right-panel` (`push` / `fullscreen`) and
65
+ * `data-sidebar-right-open` are the package's own stable hooks, so the card
66
+ * `shell.css` paints on it survives a build whose classes were rehashed; this
67
+ * plugin authors no selector for the panel's hashed class.
68
+ */
69
+ readonly rightbarPanel: '[data-sidebar-right-panel]';
70
+ /**
71
+ * DockKit (`dsh-web-frontend`'s dock layout, the static bundle both installers
72
+ * ship — the same case `_1ypvv_` records in `host-builds.ts`, so these need no
73
+ * prefix entry): the boxes inside that panel, also addressed by the package's
74
+ * own data attributes. `surface` is the layout root the card's fill is drawn
75
+ * on, `pane` a dock column that would otherwise paint the canvas over it,
76
+ * `strip` the tab strip (the card's header row), `divider` the hairline
77
+ * between two columns, `empty` a column no tab has claimed. Only
78
+ * `features/shell/right-panel.css` reads them.
79
+ */
80
+ readonly dockSurface: '[data-dockkit-surface]';
81
+ readonly dockPane: '[data-dockkit-pane]';
82
+ readonly dockStrip: '[data-dockkit-strip]';
83
+ readonly dockTab: '[data-dockkit-tab]';
84
+ readonly dockTabTitle: '[data-dockkit-tab-title]';
85
+ readonly dockStripChrome: '[data-dockkit-strip-chrome]';
86
+ readonly dockDivider: '[data-dockkit-divider]';
87
+ readonly dockEmpty: '[data-dockkit-empty]';
88
+ /**
89
+ * DockKit's tab body and its two hosts. Every tab of the panel draws one
90
+ * `content` box, and where that box sits says how the tab is hosted: inside a
91
+ * dock column (`host="dock"`) it is a tab of the panel's own strip, while a
92
+ * `float` box carries `data-dockkit-float` itself and is drawn `position:
93
+ * fixed` at the rectangle the layout stores for it. `compat/right-panes.ts`
94
+ * reads the two apart to decide which tabs are still tabs and which are panes.
95
+ */
96
+ readonly dockContent: '[data-dockkit-content]';
97
+ readonly dockFloat: '[data-dockkit-float]';
98
+ /**
99
+ * DockKit's float header: the grip a pointer drags the pane by, and the two
100
+ * controls it draws — "dock back into the panel" and "close". The panes this
101
+ * plugin draws keep the grip's place as their title row (with the drag
102
+ * retired) and hide the dock control, because a pane is already docked in
103
+ * everything but name; the close control stays the reader's way out of one.
104
+ */
105
+ readonly dockFloatGrip: '[data-dockkit-float-grip]';
106
+ readonly dockFloatTitle: '[data-dockkit-float-title]';
107
+ readonly dockFloatDock: '[data-dockkit-float-dock]';
108
+ readonly dockFloatResize: '[data-dockkit-float-resize]';
109
+ /**
110
+ * ui-sidebar-right/shell/SidebarRight.tsx: the Session the panel on screen is
111
+ * drawing. The panel element is reused across Session switches, so the tabs
112
+ * this module floats are read for the Session this hook names rather than for
113
+ * whatever the layout last held.
114
+ */
115
+ readonly rightbarSession: '[data-sidebar-right-session]';
116
+ /**
117
+ * ui-sidebar-files/FilesBody.tsx: the file tree's own hooks. The pane's header
118
+ * is the root's non-body child (the scroller writes `data-files-body`), each
119
+ * entry row carries `data-files-entry` (`directory` / `file` / `other`) with
120
+ * the path it stands for, and the host's folder glyph and per-type glyph are
121
+ * the row button's first child. The tree's rows are dressed through these
122
+ * hooks and their own structure, so the Files sheet needs no class name of
123
+ * that package — whose hashes differ per build and are not in the pinned
124
+ * tables — either.
125
+ */
126
+ readonly filesRoot: '[data-files-root]';
127
+ readonly filesBody: '[data-files-body]';
128
+ readonly filesEntry: '[data-files-entry]';
51
129
  readonly sidebarRoot: '._3WPZCG_root';
52
130
  readonly sidebarLogoRow: '._3WPZCG_logoRow';
53
131
  readonly sidebarBrand: '._3WPZCG_brand';
@@ -56,6 +134,7 @@ export declare const HOST: Readonly<{
56
134
  /** SidebarRoot.module.css: expanded macOS window-chrome toggle. */
57
135
  readonly sidebarToggle: '._3WPZCG_toggle';
58
136
  readonly sidebarNewSession: '._3WPZCG_newSession';
137
+ readonly sidebarNewSessionContent: '._3WPZCG_newSessionContent';
59
138
  readonly sidebarNewSessionLabel: '._3WPZCG_newSessionLabel';
60
139
  readonly sidebarNewSessionShortcut: '._3WPZCG_newSessionShortcut';
61
140
  readonly sidebarPanelList: '._3WPZCG_panelList';
@@ -70,6 +149,41 @@ export declare const HOST: Readonly<{
70
149
  readonly browserSectionHeader: '._7514NG_sectionHeader';
71
150
  readonly browserSectionLabel: '._7514NG_sectionLabel';
72
151
  readonly browserListArea: '._7514NG_listArea';
152
+ /** WorkspaceBrowser.module.css: the header's two control groups, which
153
+ `sidebar.css` keeps clickable while the header is parked over a row. */
154
+ readonly browserSectionActions: '._7514NG_headerActions';
155
+ readonly browserSearchSlot: '._7514NG_searchSlot';
156
+ /** WorkspaceBrowser.module.css: the search control and its expanded state —
157
+ the one the parked header paints a background under, because the field
158
+ then covers the Workspace row it is parked on. */
159
+ readonly browserSearch: '._7514NG_search';
160
+ readonly browserSearchExpanded: '._7514NG_searchExpanded';
161
+ /** WorkspaceBrowser.module.css: the tree's own scroller — the one element
162
+ whose scroll distance the parked header band follows. */
163
+ readonly browserList: '._7514NG_list';
164
+ /** Rows.module.css: one Workspace's row, the line the merged header shares,
165
+ and its trailing action group (`sidebar.css` parks both). */
166
+ readonly workspaceRow: '.jJkEga_projectRow';
167
+ readonly workspaceRowActions: '.jJkEga_rowActions';
168
+ /** Rows.module.css: the state the host puts on a row whose menu is open —
169
+ `sidebar.css` keeps that row's own actions visible through it. */
170
+ readonly workspaceRowMenuOpen: '.jJkEga_menuOpen';
171
+ /**
172
+ * WorkspaceBrowser.module.css: the section header's view-options trigger —
173
+ * the one control there that is an `iconButton` *and* carries `wide` (its
174
+ * neighbours are `searchButton` and a plain `iconButton`), and the list class
175
+ * its card puts on the `Menu` surface. `compat/view-options.ts` reads the
176
+ * values out of that card and clicks its rows; the card itself is kept off
177
+ * screen while it does.
178
+ */
179
+ readonly viewOptionsTrigger: '._7514NG_sectionHeader ._7514NG_iconButton._7514NG_wide';
180
+ readonly viewOptionsMenu: '._7514NG_viewOptionsMenu';
181
+ /**
182
+ * WorkspaceBrowser.module.css: one Workspace's row container — the box that
183
+ * holds its Workspace row, its nested groups and its Session rows, and the
184
+ * box `compat/empty-groups.ts` hides when the group has nothing to show.
185
+ */
186
+ readonly workspaceGroup: '._7514NG_groupSection';
73
187
  readonly settingsTrigger: '.Dws9Sa_trigger';
74
188
  readonly settingsTriggerRow: '.Dws9Sa_triggerRow';
75
189
  readonly accountTrigger: '.ZogL4G_trigger';
@@ -104,6 +218,12 @@ export declare const HOST: Readonly<{
104
218
  readonly assistantMarkdown: '.gKv1-q_root';
105
219
  readonly markdownBody: '._markdown_1ypvv_5:not([data-markdown-variant="compact"])';
106
220
  readonly markdownFileMention: '._fileMention_1ypvv_85';
221
+ /**
222
+ * MarkdownText.module.css: the category glyph the host seats inside a URL
223
+ * anchor (and inside file mentions and URL-promoted inline code). `conversation.css`
224
+ * hides the anchor's copy; the reference draws link text alone.
225
+ */
226
+ readonly markdownLinkIcon: '._linkIcon_1ypvv_94';
107
227
  readonly conversationScroll: '.ST7X_W_scrollBody';
108
228
  /** ChatView.module.css: the transcript's own scroll column, inside the page's
109
229
  scroll viewport, and the two shells of the floating jump-to-bottom control
@@ -156,9 +276,24 @@ export declare const HOST: Readonly<{
156
276
  readonly modelSelectEffort: '.cl2Rlq_triggerEffort';
157
277
  /** PermissionSelect.module.css: compact permission text, keeping its button. */
158
278
  readonly permissionSelectLabel: '.wXeviG_triggerLabel';
279
+ /** PermissionSelect.module.css: the control itself, in the status bar and in
280
+ the new-session card alike — `compat/permission-menu.ts` reads the mode's
281
+ name off it, and writes the card's own wording back. */
282
+ readonly permissionSelectTrigger: '.wXeviG_trigger';
283
+ /** PermissionSelect.module.css: the one preset badge DSH marks (`EXP`), on
284
+ the trigger as well as on the option row it belongs to. */
285
+ readonly permissionSelectBadge: '.wXeviG_badge';
286
+ /** PermissionSelect.module.css: the badge row's own name, told apart from the
287
+ badge beside it — the row label carries both, and only this one is the
288
+ preset's name. */
289
+ readonly permissionSelectOptionLabelText: '.wXeviG_optionLabelText';
159
290
  /** TeamAction.module.css: native team dialog entry, retaining its label at every width. */
160
291
  readonly teamActionTrigger: '._2tNPVa_trigger';
161
292
  readonly teamActionLabel: '._2tNPVa_triggerLabel';
293
+ /** TeamAction.module.css: the panel's own body, the one element of that
294
+ surface that scrolls. `compat/scroll-pill.ts` tracks it like the four
295
+ page-level scrollers, so the panel carries the interface's bar too. */
296
+ readonly teamBody: '._2tNPVa_body';
162
297
  /** AgentPresetLabel.module.css: passive mode description, omitted from the conversation header. */
163
298
  readonly presetModeLabel: '._3li69W_label';
164
299
  /** AgentPresetLabel.module.css: redundant icon may yield space to its text. */
@@ -169,6 +304,15 @@ export declare const HOST: Readonly<{
169
304
  readonly statsSeparator: '.OpZ85W_sep';
170
305
  readonly statsPill: '.OpZ85W_pill';
171
306
  readonly contextMeterTrigger: '.y0jqnG_trigger';
307
+ /**
308
+ * ContextMeter.module.css: the host's own click-open breakdown panel. It is a
309
+ * `position: fixed` portal on `document.body` at `z-index: 1100` rather than a
310
+ * native popover, so this plugin's panel — a top-layer popover — paints over
311
+ * it; the marker the driver writes is the belt to that braces, and it keeps
312
+ * the host's panel out of the paint if a click ever reaches DSH's own
313
+ * handler. `compat/context-panel.ts` is the only reader.
314
+ */
315
+ readonly contextMeterPanel: '.y0jqnG_panel';
172
316
  readonly heroRoot: '.bocITq_root';
173
317
  readonly heroHeadline: '.bocITq_headline';
174
318
  readonly heroWorkspaceChip: '.bocITq_workspace';
@@ -180,6 +324,20 @@ export declare const HOST: Readonly<{
180
324
  /** Every menu surface the `Menu` primitive renders, portal or in place. */
181
325
  readonly menu: '[role="menu"]';
182
326
  readonly menuItem: '[role="menuitem"]';
327
+ /** Menu.module.css: the row's own label seat, the one box this plugin puts a
328
+ second line after (`compat/permission-menu.ts`). The `_4ub78_` prefix is
329
+ the static web frontend's bundle, identical in both installers, so it needs
330
+ no entry in `host-builds.ts` — the same fact `tokens.css` records for the
331
+ primitive's check mark. */
332
+ readonly menuItemLabel: '._itemLabel_4ub78_190';
333
+ /** Menu.module.css: the trailing mark a *selected* row draws — `Menu` renders
334
+ it only for the row whose id is in `selectedIds`, so its presence is how
335
+ `compat/view-options.ts` reads which option is current. */
336
+ readonly menuItemCheck: '._check_4ub78_179';
337
+ /** Menu.module.css: the scrolling row group inside the card — where the
338
+ permission card's heading is written, above the rows and outside the
339
+ keyboard's walk (that walk collects `button`s only). */
340
+ readonly menuViewport: '._viewport_4ub78_19';
183
341
  }>;
184
342
  /**
185
343
  * Anchors that must exist before a feature may touch the host DOM. They are
@@ -197,6 +355,12 @@ export declare const ANCHOR: Readonly<{
197
355
  * Workspace headers share the attribute with other prefixes.
198
356
  */
199
357
  readonly sessionRows: '[data-row-key^="session:"]';
358
+ /**
359
+ * Each Workspace's own row, the first keyed row of its group. `Rows.tsx`
360
+ * writes it, and `browser-header.ts` reads it to tell a grouped tree from a
361
+ * flat list before publishing the region's merged-header state.
362
+ */
363
+ readonly workspaceRows: '[data-row-key^="workspace:"]';
200
364
  readonly settings: '[data-slot="sidebar.settings"]';
201
365
  readonly conversation: '[data-conversation-content]';
202
366
  /**
@@ -206,6 +370,15 @@ export declare const ANCHOR: Readonly<{
206
370
  * reads it rather than a measurement of our own.
207
371
  */
208
372
  readonly rightbarCollapsed: '[data-slot="root"] > div[data-rightbar-collapsed]';
373
+ /**
374
+ * AppFrame.tsx: the same frame element while the sidebar's own track is 0.
375
+ * The host writes `data-sidebar-collapsed` from the layout store, and on the
376
+ * desktop builds the collapsed sidebar is not a rail — the frame solves its
377
+ * grid track to 0px and `sidebarCol`'s `overflow: hidden` clips the whole
378
+ * column. `compat/view-switch.ts` reads it as the state in which the parked
379
+ * View switcher has no corner to sit in.
380
+ */
381
+ readonly sidebarCollapsed: '[data-slot="root"] > div[data-sidebar-collapsed]';
209
382
  /** The element that actually scrolls the Conversation page. In the pinned
210
383
  layout the transcript column inside it is `overflow: visible`, so this is
211
384
  the scroll viewport the edge fade has to describe. */
@@ -220,6 +393,13 @@ export declare const ANCHOR: Readonly<{
220
393
  * with a Session, so this is the seat the no-session pet is measured from.
221
394
  */
222
395
  readonly composerCardHero: ".ST7X_W_root[data-phase=\"hero\"] [data-composer-card]";
396
+ /**
397
+ * ConversationRoot.tsx: the conversation body, carrying the Session identity
398
+ * the context panel reads its projections by. The Composer seat — and so the
399
+ * context ring — is a descendant, which is what makes `closest()` from the
400
+ * trigger enough. The host's own stable hook rather than the hashed class.
401
+ */
402
+ readonly conversationSession: '[data-conversation-session]';
223
403
  }>;
224
404
  /** One document's selector table, resolved for the build that document runs. */
225
405
  export type HostSelectors = Readonly<Record<keyof typeof HOST, string>>;
@@ -0,0 +1,29 @@
1
+ export interface PaneChromeOptions {
2
+ readonly kind: string;
3
+ readonly title: string;
4
+ readonly filesRoot: HTMLElement | null;
5
+ readonly zoomed: boolean;
6
+ readonly onZoom: () => void;
7
+ readonly onNew: () => void;
8
+ readonly onSelect: (id: string) => void;
9
+ readonly onClose: (id: string) => void;
10
+ readonly closeTabs: readonly string[];
11
+ readonly terminals: readonly {
12
+ id: string;
13
+ title: string;
14
+ selected: boolean;
15
+ }[];
16
+ readonly files: readonly {
17
+ id: string;
18
+ title: string;
19
+ selected: boolean;
20
+ }[];
21
+ readonly panel: HTMLElement;
22
+ }
23
+ export interface PaneChrome {
24
+ update(options: PaneChromeOptions): void;
25
+ release(): void;
26
+ }
27
+ /** Claude's toolbar beside host controls. Page picking keeps its reference
28
+ * silhouette and explains the host limitation; pane windows are omitted. */
29
+ export declare function mountPaneChrome(node: HTMLElement): PaneChrome | null;
@@ -0,0 +1,23 @@
1
+ /** Toolbar silhouettes matching the Claude recording. Static SVG only. */
2
+ declare const ICONS: {
3
+ readonly Add: "<svg viewBox=\"0 0 1000 1000\" fill=\"currentColor\" aria-hidden=\"true\"><path transform=\"translate(0 1000) scale(1 -1)\" d=\"M472 800Q472 812 480.0 820.0Q488 828 500 828Q512 828 520.0 820.0Q528 812 528 800V200Q528 188 520.0 180.0Q512 172 500 172Q488 172 480.0 180.0Q472 188 472 200ZM800 528Q812 528 820.0 520.0Q828 512 828 500Q828 488 820.0 480.0Q812 472 800 472H200Q188 472 180.0 480.0Q172 488 172 500Q172 512 180.0 520.0Q188 528 200 528Z\"/></svg>";
4
+ readonly DotsVertical: "<svg viewBox=\"0 0 1000 1000\" fill=\"currentColor\" aria-hidden=\"true\"><path transform=\"translate(0 1000) scale(1 -1)\" d=\"M434 221Q434 232 441.5 241.0Q449 250 461 251Q472 251 481.0 243.5Q490 236 491 224Q491 221 493.5 218.5Q496 216 500 216Q504 216 506.5 218.5Q509 221 509 225Q509 229 506.5 231.5Q504 234 500 234Q496 234 493.5 231.5Q491 229 491 226Q491 237 483.5 246.0Q476 255 464 255L502 253Q513 252 521.0 243.5Q529 235 528 223Q527 212 518.5 204.0Q510 196 498 197L461 199Q449 200 441.5 209.0Q434 218 434 229Q436 255 455.0 273.0Q474 291 500 291Q518 291 533.0 282.0Q548 273 557.0 258.0Q566 243 566 225Q566 207 557.0 192.0Q548 177 533.0 168.0Q518 159 500 159Q474 159 455.0 177.0Q436 195 434 221ZM434 496Q434 507 441.5 516.0Q449 525 461 526Q472 526 481.0 518.5Q490 511 491 499Q491 496 493.5 493.5Q496 491 500 491Q504 491 506.5 493.5Q509 496 509 500Q509 504 506.5 506.5Q504 509 500 509Q496 509 493.5 506.5Q491 504 491 501Q491 512 483.5 521.0Q476 530 464 530L502 528Q513 527 521.0 518.5Q529 510 528 498Q527 487 518.5 479.0Q510 471 498 472L461 474Q449 475 441.5 484.0Q434 493 434 504Q436 530 455.0 548.0Q474 566 500 566Q518 566 533.0 557.0Q548 548 557.0 533.0Q566 518 566 500Q566 482 557.0 467.0Q548 452 533.0 443.0Q518 434 500 434Q474 434 455.0 452.0Q436 470 434 496ZM434 771Q434 782 441.5 791.0Q449 800 461 801Q472 801 481.0 793.5Q490 786 491 774Q491 771 493.5 768.5Q496 766 500 766Q504 766 506.5 768.5Q509 771 509 775Q509 779 506.5 781.5Q504 784 500 784Q496 784 493.5 781.5Q491 779 491 776Q491 787 483.5 796.0Q476 805 464 805L502 803Q513 802 521.0 793.5Q529 785 528 773Q527 762 518.5 754.0Q510 746 498 747L461 749Q449 750 441.5 759.0Q434 768 434 779Q436 805 455.0 823.0Q474 841 500 841Q518 841 533.0 832.0Q548 823 557.0 808.0Q566 793 566 775Q566 757 557.0 742.0Q548 727 533.0 718.0Q518 709 500 709Q474 709 455.0 727.0Q436 745 434 771Z\"/></svg>";
5
+ readonly WindowNew: "<svg viewBox=\"0 0 1000 1000\" fill=\"currentColor\" aria-hidden=\"true\"><path transform=\"translate(0 1000) scale(1 -1)\" d=\"M325 647V703H875V647ZM297 425V775Q297 797 307.5 814.5Q318 832 335.5 842.5Q353 853 375 853H825Q847 853 864.5 842.5Q882 832 892.5 814.5Q903 797 903 775V425Q903 403 892.5 385.5Q882 368 864.5 357.5Q847 347 825 347H375Q353 347 335.5 357.5Q318 368 307.5 385.5Q297 403 297 425ZM353 425Q353 416 359.5 409.5Q366 403 375 403H825Q834 403 840.5 409.5Q847 416 847 425V775Q847 784 840.5 790.5Q834 797 825 797H375Q366 797 359.5 790.5Q353 784 353 775ZM647 375H703V225Q703 203 692.5 185.5Q682 168 664.5 157.5Q647 147 625 147H175Q153 147 135.5 157.5Q118 168 107.5 185.5Q97 203 97 225V575Q97 597 107.5 614.5Q118 632 135.5 642.5Q153 653 175 653H325V597H175Q166 597 159.5 590.5Q153 584 153 575V225Q153 216 159.5 209.5Q166 203 175 203H625Q634 203 640.5 209.5Q647 216 647 225Z\"/></svg>";
6
+ readonly Expand: "<svg viewBox=\"0 0 1000 1000\" fill=\"currentColor\" aria-hidden=\"true\"><path transform=\"translate(0 1000) scale(1 -1)\" d=\"M595 555Q587 547 575.0 547.0Q563 547 555 555Q547 563 547.0 575.0Q547 587 555 595L805 845L845 805ZM625 797Q613 797 605.0 805.0Q597 813 597 825Q597 837 605.0 845.0Q613 853 625 853H825Q837 853 845.0 845.0Q853 837 853 825V625Q853 613 845.0 605.0Q837 597 825 597Q813 597 805.0 605.0Q797 613 797 625V797ZM405 445Q413 453 425.0 453.0Q437 453 445 445Q453 437 453.0 425.0Q453 413 445 405L195 155L155 195ZM375 203Q387 203 395.0 195.0Q403 187 403 175Q403 163 395.0 155.0Q387 147 375 147H175Q163 147 155.0 155.0Q147 163 147 175V375Q147 387 155.0 395.0Q163 403 175 403Q187 403 195.0 395.0Q203 387 203 375V203Z\"/></svg>";
7
+ readonly Collapse: "<svg viewBox=\"0 0 1000 1000\" fill=\"currentColor\" aria-hidden=\"true\"><path transform=\"translate(0 1000) scale(1 -1)\" d=\"M805 845Q813 853 825.0 853.0Q837 853 845 845Q853 837 853.0 825.0Q853 813 845 805L595 555L555 595ZM775 603Q787 603 795.0 595.0Q803 587 803 575Q803 563 795.0 555.0Q787 547 775 547H575Q563 547 555.0 555.0Q547 563 547 575V775Q547 787 555.0 795.0Q563 803 575 803Q587 803 595.0 795.0Q603 787 603 775V603ZM195 155Q187 147 175.0 147.0Q163 147 155 155Q147 163 147.0 175.0Q147 187 155 195L405 445L445 405ZM225 397Q213 397 205.0 405.0Q197 413 197 425Q197 437 205.0 445.0Q213 453 225 453H425Q437 453 445.0 445.0Q453 437 453 425V225Q453 213 445.0 205.0Q437 197 425 197Q413 197 405.0 205.0Q397 213 397 225V397Z\"/></svg>";
8
+ readonly Search: "<svg viewBox=\"0 0 1000 1000\" fill=\"currentColor\" aria-hidden=\"true\"><path transform=\"translate(0 1000) scale(1 -1)\" d=\"M753 575Q753 510 728.0 449.5Q703 389 657 343Q611 297 550.5 272.0Q490 247 425 247Q360 247 299.5 272.0Q239 297 193 343Q147 389 122.0 449.5Q97 510 97 575Q97 640 122.0 700.5Q147 761 193 807Q239 853 299.5 878.0Q360 903 425 903Q490 903 550.5 878.0Q611 853 657 807Q703 761 728.0 700.5Q753 640 753 575ZM697 575Q697 629 676.0 679.0Q655 729 617 767Q579 805 529.0 826.0Q479 847 425 847Q371 847 321.0 826.0Q271 805 233 767Q195 729 174.0 679.0Q153 629 153 575Q153 521 174.0 471.0Q195 421 233 383Q271 345 321.0 324.0Q371 303 425 303Q479 303 529.0 324.0Q579 345 617 383Q655 421 676.0 471.0Q697 521 697 575ZM618 343 657 382 895 145Q903 137 903.0 125.0Q903 113 895 105Q887 97 875.0 97.0Q863 97 855 105Z\"/></svg>";
9
+ readonly Cursor: "<svg viewBox=\"0 0 1000 1000\" fill=\"currentColor\" aria-hidden=\"true\"><path transform=\"translate(0 1000) scale(1 -1)\" d=\"M174 826Q188 840 207.5 845.0Q227 850 246 844L855 648Q877 642 890.0 623.5Q903 605 903 583Q903 559 888.0 540.0Q873 521 849 516L624 467Q634 470 640.0 478.0Q646 486 645.5 496.5Q645 507 638 515L852 300Q868 285 868.0 263.0Q868 241 852 225L775 148Q760 132 737.5 132.0Q715 132 700 148L485 362Q493 355 503.5 354.5Q514 354 522.0 360.0Q530 366 533 376L484 151Q479 127 460.0 112.0Q441 97 417 97Q395 97 377.0 110.0Q359 123 352 145L156 754Q150 773 155.0 792.5Q160 812 174 826ZM214 786Q207 780 210 771L405 162Q406 158 409.5 155.5Q413 153 417 153Q422 153 425.0 156.0Q428 159 429 163L478 388Q480 399 488.5 405.0Q497 411 507.0 410.5Q517 410 525 402L740 188H735L812 265V260L598 475Q590 483 589.5 493.0Q589 503 595.0 511.5Q601 520 612 522L837 571Q841 572 844.0 575.0Q847 578 847 583Q847 587 844.5 590.5Q842 594 838 595L229 790Q220 793 214 786Z\"/></svg>";
10
+ readonly Globe: "<svg viewBox=\"0 0 1000 1000\" fill=\"currentColor\" aria-hidden=\"true\"><path transform=\"translate(0 1000) scale(1 -1)\" d=\"M872 500Q872 426 843.5 357.5Q815 289 763 237Q711 185 642.5 156.5Q574 128 500 128Q426 128 357.5 156.5Q289 185 237 237Q185 289 156.5 357.5Q128 426 128 500Q128 574 156.5 642.5Q185 711 237 763Q289 815 357.5 843.5Q426 872 500 872Q574 872 642.5 843.5Q711 815 763 763Q815 711 843.5 642.5Q872 574 872 500ZM816 500Q816 563 792.0 621.0Q768 679 723 723Q679 768 621.0 792.0Q563 816 500 816Q437 816 379.0 792.0Q321 768 277 723Q232 679 208.0 621.0Q184 563 184 500Q184 437 208.0 379.0Q232 321 277 277Q321 232 379.0 208.0Q437 184 500 184Q563 184 621.0 208.0Q679 232 723 277Q768 321 792.0 379.0Q816 437 816 500ZM684 500Q684 426 671.5 360.5Q659 295 636 245Q625 220 611.0 199.0Q597 178 580 163Q562 146 543 138Q500 118 457 138Q438 146 420 163Q403 178 389.0 199.0Q375 220 364 245Q341 295 328.5 360.5Q316 426 316 500Q316 574 328.5 639.5Q341 705 364 755Q375 780 389.0 801.0Q403 822 420 837Q438 854 457 862Q500 882 543 862Q562 854 580 837Q597 822 611.0 801.0Q625 780 636 755Q659 705 671.5 639.5Q684 574 684 500ZM628 500Q628 569 616.5 628.5Q605 688 585 731Q575 753 564.0 769.5Q553 786 542 796Q531 806 520 811Q500 820 480 811Q469 806 458 796Q447 786 436.0 769.5Q425 753 415 731Q395 688 383.5 628.5Q372 569 372 500Q372 431 383.5 371.5Q395 312 415 269Q425 247 436.0 230.5Q447 214 458 204Q469 194 480 189Q500 180 520 189Q531 194 542 204Q553 214 564.0 230.5Q575 247 585 269Q605 312 616.5 371.5Q628 431 628 500ZM156 472V528H844V472Z\"/></svg>";
11
+ readonly CaretDown: "<svg viewBox=\"0 0 1000 1000\" fill=\"currentColor\" aria-hidden=\"true\"><path transform=\"translate(0 1000) scale(1 -1)\" d=\"M805 670Q813 678 825.0 678.0Q837 678 845 670Q853 662 853.0 650.0Q853 638 845 630L520 305Q512 297 500.0 297.0Q488 297 480 305L155 630Q147 638 147.0 650.0Q147 662 155 670Q163 678 175.0 678.0Q187 678 195 670L500 365Z\"/></svg>";
12
+ readonly CaretLeft: "<svg viewBox=\"0 0 1000 1000\" fill=\"currentColor\" aria-hidden=\"true\"><path transform=\"translate(0 1000) scale(1 -1)\" d=\"M670 195Q678 187 678.0 175.0Q678 163 670 155Q662 147 650.0 147.0Q638 147 630 155L305 480Q297 488 297.0 500.0Q297 512 305 520L630 845Q638 853 650.0 853.0Q662 853 670 845Q678 837 678.0 825.0Q678 813 670 805L365 500Z\"/></svg>";
13
+ readonly CaretRight: "<svg viewBox=\"0 0 1000 1000\" fill=\"currentColor\" aria-hidden=\"true\"><path transform=\"translate(0 1000) scale(1 -1)\" d=\"M370 155Q362 147 350.0 147.0Q338 147 330 155Q322 163 322.0 175.0Q322 187 330 195L635 500L330 805Q322 813 322.0 825.0Q322 837 330 845Q338 853 350.0 853.0Q362 853 370 845L695 520Q703 512 703.0 500.0Q703 488 695 480Z\"/></svg>";
14
+ readonly ArrowClockwise: "<svg viewBox=\"0 0 1000 1000\" fill=\"currentColor\" aria-hidden=\"true\"><path transform=\"translate(0 1000) scale(1 -1)\" d=\"M869 609Q872 598 867.0 587.5Q862 577 851 573Q840 570 829.5 575.0Q819 580 815 591Q801 634 773.0 675.0Q745 716 704.5 749.0Q664 782 612.5 802.0Q561 822 500 822Q433 822 375.0 797.0Q317 772 272.5 727.5Q228 683 203.0 625.0Q178 567 178 500Q178 433 203.0 375.0Q228 317 272.5 272.5Q317 228 375.0 203.0Q433 178 500 178Q576 178 642.5 208.0Q709 238 753 293Q760 302 772.0 303.0Q784 304 793 297Q802 290 803.0 278.0Q804 266 797 257Q745 193 667.0 157.5Q589 122 500 122Q422 122 353.5 151.5Q285 181 233.0 233.0Q181 285 151.5 353.5Q122 422 122 500Q122 578 151.5 646.5Q181 715 233.0 767.0Q285 819 353.5 848.5Q422 878 500 878Q570 878 630.0 855.5Q690 833 737.5 794.5Q785 756 818.0 708.0Q851 660 869 609ZM847 825Q847 837 855.0 845.0Q863 853 875 853Q887 853 895.0 845.0Q903 837 903 825V575Q903 563 895.0 555.0Q887 547 875 547H625Q613 547 605.0 555.0Q597 563 597 575Q597 587 605.0 595.0Q613 603 625 603H847Z\"/></svg>";
15
+ readonly X: "<svg viewBox=\"0 0 1000 1000\" fill=\"currentColor\" aria-hidden=\"true\"><path transform=\"translate(0 1000) scale(1 -1)\" d=\"M705 745Q713 753 725.0 753.0Q737 753 745 745Q753 737 753.0 725.0Q753 713 745 705L295 255Q287 247 275.0 247.0Q263 247 255 255Q247 263 247.0 275.0Q247 287 255 295ZM745 295Q753 287 753.0 275.0Q753 263 745 255Q737 247 725.0 247.0Q713 247 705 255L255 705Q247 713 247.0 725.0Q247 737 255 745Q263 753 275.0 753.0Q287 753 295 745Z\"/></svg>";
16
+ readonly Folder: "<svg viewBox=\"0 0 1000 1000\" fill=\"currentColor\" aria-hidden=\"true\"><path transform=\"translate(0 1000) scale(1 -1)\" d=\"M275 647Q263 647 255.0 655.0Q247 663 247 675Q247 687 255.0 695.0Q263 703 275 703H825Q847 703 864.5 692.5Q882 682 892.5 664.5Q903 647 903 625V225Q903 203 892.5 185.5Q882 168 864.5 157.5Q847 147 825 147H175Q153 147 135.5 157.5Q118 168 107.5 185.5Q97 203 97 225V775Q97 797 107.5 814.5Q118 832 135.5 842.5Q153 853 175 853H444Q466 853 485.0 841.5Q504 830 514 810L575 688Q580 677 576.5 666.0Q573 655 563 650Q552 645 541.0 648.5Q530 652 525 662L464 785Q458 797 444 797H175Q166 797 159.5 790.5Q153 784 153 775V225Q153 216 159.5 209.5Q166 203 175 203H825Q834 203 840.5 209.5Q847 216 847 225V625Q847 634 840.5 640.5Q834 647 825 647Z\"/></svg>";
17
+ readonly Files: "<svg viewBox=\"0 0 1000 1000\" fill=\"currentColor\" aria-hidden=\"true\"><path transform=\"translate(0 1000) scale(1 -1)\" d=\"M785 247H415Q396 247 380.5 256.0Q365 265 356.0 280.5Q347 296 347 315V835Q347 854 356.0 869.5Q365 885 380.5 894.0Q396 903 415 903H666Q693 903 713 884L833 767Q853 747 853 718V315Q853 296 844.0 280.5Q835 265 819.5 256.0Q804 247 785 247ZM785 303Q790 303 793.5 306.5Q797 310 797 315V718L793 727L674 844L666 847H415Q410 847 406.5 843.5Q403 840 403 835V315Q403 310 406.5 306.5Q410 303 415 303ZM375 753V697H215Q210 697 206.5 693.5Q203 690 203 685V165Q203 160 206.5 156.5Q210 153 215 153H585Q590 153 593.5 156.5Q597 160 597 165V275H653V165Q653 146 644.0 130.5Q635 115 619.5 106.0Q604 97 585 97H215Q196 97 180.5 106.0Q165 115 156.0 130.5Q147 146 147 165V685Q147 704 156.0 719.5Q165 735 180.5 744.0Q196 753 215 753ZM622 850Q622 862 630.0 870.0Q638 878 650 878Q662 878 670.0 870.0Q678 862 678 850V750Q678 741 684.5 734.5Q691 728 700 728H800Q812 728 820.0 720.0Q828 712 828 700Q828 688 820.0 680.0Q812 672 800 672H700Q678 672 660.5 682.5Q643 693 632.5 710.5Q622 728 622 750Z\"/></svg>";
18
+ readonly SidebarClose: "<svg viewBox=\"0 0 1000 1000\" fill=\"currentColor\" aria-hidden=\"true\"><path transform=\"translate(0 1000) scale(1 -1)\" d=\"M147 825Q147 837 155.0 845.0Q163 853 175 853Q187 853 195.0 845.0Q203 837 203 825V175Q203 163 195.0 155.0Q187 147 175 147Q163 147 155.0 155.0Q147 163 147 175ZM825 528Q837 528 845.0 520.0Q853 512 853 500Q853 488 845.0 480.0Q837 472 825 472H393L570 295Q578 287 578.0 275.0Q578 263 570 255Q562 247 550.0 247.0Q538 247 530 255L305 480Q296 489 296.5 500.5Q297 512 304.5 520.0Q312 528 325 528ZM530 745Q538 753 550.0 753.0Q562 753 570 745Q578 737 578.0 725.0Q578 713 570 705L345 480L305 520Z\"/></svg>";
19
+ readonly SidebarOpen: "<svg viewBox=\"0 0 1000 1000\" fill=\"currentColor\" aria-hidden=\"true\"><path transform=\"translate(0 1000) scale(1 -1)\" d=\"M797 825Q797 837 805.0 845.0Q813 853 825 853Q837 853 845.0 845.0Q853 837 853 825V175Q853 163 845.0 155.0Q837 147 825 147Q813 147 805.0 155.0Q797 163 797 175ZM175 472Q163 472 155.0 480.0Q147 488 147 500Q147 512 155.0 520.0Q163 528 175 528H675Q688 528 695.5 520.0Q703 512 703.5 500.5Q704 489 695 480L470 255Q462 247 450.0 247.0Q438 247 430 255Q422 263 422.0 275.0Q422 287 430 295L607 472ZM430 705Q422 713 422.0 725.0Q422 737 430 745Q438 753 450.0 753.0Q462 753 470 745L695 520L655 480Z\"/></svg>";
20
+ };
21
+ export type PaneIcon = keyof typeof ICONS;
22
+ export declare function paneIcon(name: PaneIcon): string;
23
+ export {};
@@ -0,0 +1,37 @@
1
+ /** Stateful two-column tiling. Closing a view keeps its neighbours in place;
2
+ * each column has its own row sizes, as in the Claude sidebar recording. */
3
+ export interface PaneRect {
4
+ readonly x: number;
5
+ readonly y: number;
6
+ readonly width: number;
7
+ readonly height: number;
8
+ }
9
+ export interface PaneColumn {
10
+ readonly ids: readonly string[];
11
+ readonly sizes: readonly number[];
12
+ }
13
+ /** Session-owned membership and proportions, independent of DOM mount order. */
14
+ export interface PaneLayout {
15
+ readonly columns: readonly PaneColumn[];
16
+ readonly column: number;
17
+ }
18
+ export interface PaneSeam {
19
+ readonly axis: 'row' | 'column';
20
+ readonly column: number;
21
+ readonly index: number;
22
+ readonly rect: PaneRect;
23
+ }
24
+ export interface PaneTiles {
25
+ readonly rects: ReadonlyMap<string, PaneRect>;
26
+ readonly seams: readonly PaneSeam[];
27
+ }
28
+ export declare const MIN_SHARE = 0.15;
29
+ export declare const EMPTY_LAYOUT: PaneLayout;
30
+ /** First two views stack; the third starts a second column. Further views split
31
+ * the roomiest cell in the less populated column. Existing cells stay put. */
32
+ export declare function reconcilePanes(layout: PaneLayout, liveIds: readonly string[]): PaneLayout;
33
+ /** Rectangles fill the card edge to edge, with gaps only between neighbours. */
34
+ export declare function tilePanes(area: PaneRect, layout: PaneLayout, gap: number): PaneTiles;
35
+ /** Resize just the pair beside this seam, keeping both usable. The caller
36
+ * supplies a minimum in viewport pixels converted to an axis fraction. */
37
+ export declare function resizePanes(layout: PaneLayout, seam: PaneSeam, fraction: number, minimum?: number): PaneLayout;