@qilin-agent/client-ui-sidebar 0.0.0-stage → 3.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/client.js ADDED
@@ -0,0 +1,660 @@
1
+ window.__ModuleLoader__.load({
2
+ id: "@qilin-agent/client-ui-sidebar",
3
+ factory: (require) => {
4
+ var module = { exports: {} };
5
+ var exports = module.exports;
6
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
7
+ let _qilin_agent_client_store = require("@qilin-agent/client-store");
8
+ let _qilin_agent_client_ui_slots = require("@qilin-agent/client-ui-slots");
9
+ let _qilin_agent_client_ui_primitives = require("@qilin-agent/client-ui-primitives");
10
+ let react_jsx_runtime = require("react/jsx-runtime");
11
+ let react = require("react");
12
+ //#region \0qilin-css:/home/runner/work/QiLin/QiLin/packages/client/ui-sidebar/src/client/HeaderLeadingControls.module.css.mjs
13
+ const css$1 = ".bVkeZq_controls{display:none}[data-sidebar-collapsed] .bVkeZq_controls{align-items:center;gap:8px;margin-right:8px;padding-left:68px;display:flex}html[data-platform=darwin] [data-sidebar-collapsed] .bVkeZq_controls{margin-top:4px}.bVkeZq_iconButton{corner-shape:round;width:28px;height:28px;color:var(--qilin-alias-label-secondary);cursor:pointer;background:0 0;border:none;border-radius:50%;flex:none;justify-content:center;align-items:center;padding:0;display:inline-flex}.bVkeZq_iconButton:hover{background:var(--qilin-alias-interactive-bg-hover)}.bVkeZq_iconButton svg{width:15px;height:15px}";
14
+ const tagId$1 = "@qilin-agent/client-ui-sidebar/HeaderLeadingControls.module.css";
15
+ if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$1) + "]") === null) {
16
+ const tag = document.createElement("style");
17
+ tag.dataset.plugin = "@qilin-agent/client-ui-sidebar";
18
+ tag.dataset.pluginCss = tagId$1;
19
+ tag.textContent = css$1;
20
+ document.head.appendChild(tag);
21
+ }
22
+ var HeaderLeadingControls_module_css_default = {
23
+ "controls": "bVkeZq_controls",
24
+ "iconButton": "bVkeZq_iconButton"
25
+ };
26
+ //#endregion
27
+ //#region lib/types/client/HeaderLeadingControls.js
28
+ /** macOS-desktop conversation-header controls for the fully hidden sidebar. */
29
+ /**
30
+ * Sidebar-open and New Session controls in the conversation header's
31
+ * root-scoped leading seat, which the resident header renders with or without
32
+ * a selected Session. On macOS desktop a collapsed sidebar hides entirely (no
33
+ * rail), taking both controls off screen; this occupant puts them back beside
34
+ * the traffic lights. Mounted whenever the platform matches; visibility rides the
35
+ * AppFrame-published `data-sidebar-collapsed` attribute in CSS, so no
36
+ * collapse-state pipe is added here.
37
+ * @param props - Injected sidebar actions plus the sidebar locale seat.
38
+ * @returns the two header controls, or null off macOS desktop.
39
+ */
40
+ function HeaderLeadingControls({ toggleSidebar, startSession, useShortcuts, t }) {
41
+ const shortcut = useShortcuts((rows) => rows.find((row) => row.id === "sidebar.left.toggle"));
42
+ const newShortcut = useShortcuts((rows) => rows.find((row) => row.id === "session.new"));
43
+ const newHint = newShortcut?.keys.length ? t("shortcut.hint", {
44
+ label: t("session.new.label"),
45
+ keys: newShortcut.keys.join(" ")
46
+ }) : t("session.new.label");
47
+ if (!(0, _qilin_agent_client_ui_primitives.isDarwinDesktop)()) return null;
48
+ return (0, react_jsx_runtime.jsxs)("div", {
49
+ className: HeaderLeadingControls_module_css_default.controls,
50
+ children: [(0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.Tooltip, {
51
+ label: shortcut?.keys.length ? t("shortcut.hint", {
52
+ label: t("toggle.open"),
53
+ keys: shortcut.keys.join(" ")
54
+ }) : t("toggle.open"),
55
+ delayMs: 500,
56
+ children: (0, react_jsx_runtime.jsx)("button", {
57
+ type: "button",
58
+ className: HeaderLeadingControls_module_css_default.iconButton,
59
+ "aria-label": t("toggle.open"),
60
+ "aria-keyshortcuts": shortcut?.aria,
61
+ onClick: () => {
62
+ toggleSidebar();
63
+ },
64
+ children: (0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.IconPanelLeftOutline16, { size: 16 })
65
+ })
66
+ }), (0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.Tooltip, {
67
+ label: newHint,
68
+ delayMs: 500,
69
+ children: (0, react_jsx_runtime.jsx)("button", {
70
+ type: "button",
71
+ className: HeaderLeadingControls_module_css_default.iconButton,
72
+ "aria-label": t("session.new.label"),
73
+ "aria-keyshortcuts": newShortcut?.aria,
74
+ onClick: () => {
75
+ startSession();
76
+ },
77
+ children: (0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.IconNewChatOutline16, { size: 16 })
78
+ })
79
+ })]
80
+ });
81
+ }
82
+ //#endregion
83
+ //#region ../../../node_modules/.pnpm/clsx@2.1.1/node_modules/clsx/dist/clsx.mjs
84
+ function r(e) {
85
+ var t, f, n = "";
86
+ if ("string" == typeof e || "number" == typeof e) n += e;
87
+ else if ("object" == typeof e) if (Array.isArray(e)) {
88
+ var o = e.length;
89
+ for (t = 0; t < o; t++) e[t] && (f = r(e[t])) && (n && (n += " "), n += f);
90
+ } else for (f in e) e[f] && (n && (n += " "), n += f);
91
+ return n;
92
+ }
93
+ function clsx() {
94
+ for (var e, t, f = 0, n = "", o = arguments.length; f < o; f++) (e = arguments[f]) && (t = r(e)) && (n && (n += " "), n += t);
95
+ return n;
96
+ }
97
+ //#endregion
98
+ //#region \0qilin-css:/home/runner/work/QiLin/QiLin/packages/client/ui-sidebar/src/client/SidebarRoot.module.css.mjs
99
+ const css = "._1HRR8W_root{--qilin-sidebar-inline-padding:12px;height:100%;padding:6px var(--qilin-sidebar-inline-padding);box-sizing:border-box;background:var(--qilin-specific-sidebar-fill);color:var(--qilin-alias-label-primary);--qilin-scrollbar-thumb:var(--qilin-alias-scrollbar-bg-l2);--qilin-scrollbar-thumb-hover:var(--qilin-alias-scrollbar-hover-l2);flex-direction:column;font-size:14px;display:flex}[data-platform=darwin] ._1HRR8W_root{background:0 0}._1HRR8W_root._1HRR8W_collapsed{padding:18px 10px 6px}[data-windows-titlebar] ._1HRR8W_root ._1HRR8W_logoRow{height:40px;margin:0;padding:0}[data-windows-titlebar] ._1HRR8W_toggle{top:calc((var(--qilin-windows-titlebar-height) - 28px) / 2);z-index:30;-webkit-app-region:no-drag;position:fixed;left:12px}[data-windows-titlebar] ._1HRR8W_root._1HRR8W_collapsed ._1HRR8W_logoRow{height:0}[data-windows-titlebar] ._1HRR8W_root:not(._1HRR8W_collapsed) ._1HRR8W_brand{padding-left:4px}[data-windows-titlebar] ._1HRR8W_brandIdentity{transform:translateY(1px)}[data-windows-titlebar] ._1HRR8W_brandMark{transform:translate(1px)}[data-windows-titlebar] ._1HRR8W_brandName{font-weight:400}[data-windows-titlebar] ._1HRR8W_root._1HRR8W_collapsed{padding:0}[data-windows-titlebar] ._1HRR8W_root:not(._1HRR8W_collapsed) ._1HRR8W_newSession{margin-top:8px;margin-left:0}[data-windows-titlebar] ._1HRR8W_collapsed ._1HRR8W_panelList,[data-windows-titlebar] ._1HRR8W_collapsed ._1HRR8W_regionArea,[data-windows-titlebar] ._1HRR8W_collapsed ._1HRR8W_footArea{display:none}html[data-windows-titlebar]:has([data-sidebar-collapsed=true]){--qilin-windows-menu-start:84px}[data-windows-titlebar] ._1HRR8W_collapsed ._1HRR8W_newSession{top:calc((var(--qilin-windows-titlebar-height) - 28px) / 2);z-index:30;-webkit-app-region:no-drag;border:none;margin:0;padding:0;position:fixed;left:48px}[data-windows-titlebar] ._1HRR8W_railIn ._1HRR8W_iconButton,[data-windows-titlebar] ._1HRR8W_railIn ._1HRR8W_newSession{animation:none}[data-windows-titlebar] ._1HRR8W_collapsed ._1HRR8W_toggle,[data-windows-titlebar] ._1HRR8W_collapsed ._1HRR8W_newSession{corner-shape:round;width:28px;height:28px;color:var(--qilin-alias-label-secondary);border-radius:50%}[data-windows-titlebar] ._1HRR8W_collapsed ._1HRR8W_toggle ._1HRR8W_panelIcon{display:inline}._1HRR8W_root._1HRR8W_quietBars{--qilin-scrollbar-thumb:transparent;--qilin-scrollbar-thumb-hover:transparent}._1HRR8W_fading>*{opacity:0;transition:opacity .15s var(--ds-ease-in-out)}._1HRR8W_wide{animation:_1HRR8W_wide-in .2s var(--ds-ease-in-out)}@keyframes _1HRR8W_wide-in{0%{opacity:0}}._1HRR8W_railIn ._1HRR8W_iconButton,._1HRR8W_railIn ._1HRR8W_newSession,._1HRR8W_railIn ._1HRR8W_panelList,._1HRR8W_railIn ._1HRR8W_regionArea{animation:_1HRR8W_rail-in .15s var(--ds-ease-in-out) backwards}._1HRR8W_railIn ._1HRR8W_footArea{animation:_1HRR8W_rail-fade-in .15s var(--ds-ease-in-out) backwards}@keyframes _1HRR8W_rail-in{0%{opacity:0;transform:translate(49px)}}@keyframes _1HRR8W_rail-fade-in{0%{opacity:0}}._1HRR8W_topStrip{box-sizing:border-box;height:52px;margin:-6px calc(-1 * var(--qilin-sidebar-inline-padding)) 0;flex:none;justify-content:flex-end;align-items:center;padding:0 12px;display:flex}._1HRR8W_topStrip+._1HRR8W_logoRow{margin-top:-12px}._1HRR8W_logoRow{box-sizing:border-box;flex:none;justify-content:flex-end;align-items:center;gap:8px;height:60px;margin-bottom:8px;padding:8px 0 8px 4px;display:flex;overflow:hidden}._1HRR8W_collapsed ._1HRR8W_logoRow{justify-content:flex-start;height:36px;margin-bottom:12px;padding:0}._1HRR8W_brand{min-width:0;color:inherit;cursor:pointer;background:0 0;border:none;flex:1;align-items:center;padding:0;display:inline-flex;overflow:hidden}._1HRR8W_brandIdentity{align-items:center;gap:8px;min-width:0;height:24px;display:inline-flex}._1HRR8W_brandMark{flex:none;justify-content:center;align-items:center;display:inline-flex;overflow:visible}._1HRR8W_brandName{letter-spacing:.04em;align-items:center;gap:6px;min-width:0;height:24px;font-size:18px;font-weight:600;line-height:24px;display:inline-flex}._1HRR8W_fallbackBrandName{letter-spacing:0;white-space:nowrap;font-size:17px}._1HRR8W_iconButton{corner-shape:round;cursor:pointer;width:28px;height:28px;color:var(--qilin-alias-label-secondary);background:0 0;border:none;border-radius:50%;flex:none;justify-content:center;align-items:center;padding:0;display:inline-flex;position:relative}._1HRR8W_iconButton:hover{background:var(--qilin-alias-interactive-bg-hover)}._1HRR8W_collapsed ._1HRR8W_iconButton{border-radius:12px;width:36px;height:36px}._1HRR8W_collapsed ._1HRR8W_toggle ._1HRR8W_panelIcon{display:none}._1HRR8W_collapsed ._1HRR8W_toggle:hover ._1HRR8W_panelIcon{display:inline}._1HRR8W_collapsed ._1HRR8W_toggle:hover ._1HRR8W_railMark{display:none}._1HRR8W_railMark{justify-content:center;align-items:center;display:inline-flex}._1HRR8W_collapsed ._1HRR8W_iconButton{color:var(--qilin-alias-label-primary)}._1HRR8W_buildBadge{border:.5px solid var(--qilin-alias-border-l2);height:16px;color:var(--qilin-alias-label-tertiary);background:var(--qilin-alias-bg-layer-2);font-family:var(--ds-font-family-code);white-space:nowrap;pointer-events:none;border-radius:5px;flex:none;align-self:flex-start;align-items:center;margin-top:1px;padding:0 5px;font-size:10px;font-weight:500;line-height:16px;display:inline-flex}._1HRR8W_newSession{box-sizing:border-box;border:.5px solid var(--qilin-alias-border-l3);background:var(--qilin-alias-button-elevated-fill);height:38px;color:var(--qilin-alias-label-primary);cursor:pointer;border-radius:12px;flex:none;justify-content:center;align-items:center;gap:6px;margin:0 2px 12px;padding:8px 16px;font-size:14px;font-weight:500;line-height:22px;display:flex;position:relative;overflow:hidden}._1HRR8W_newSession:hover{background:var(--qilin-alias-button-floating-hover)}[data-platform=darwin] ._1HRR8W_newSession{background:color-mix(in srgb, var(--qilin-alias-button-elevated-fill) 75%, transparent)}[data-platform=darwin] ._1HRR8W_newSession:hover{background:color-mix(in srgb, var(--qilin-alias-button-elevated-fill) 75%, transparent)}._1HRR8W_collapsed ._1HRR8W_newSession{background:0 0;border-color:#0000;justify-content:center;align-self:flex-start;gap:0;width:36px;height:36px;margin:0 0 12px;padding:0}._1HRR8W_collapsed ._1HRR8W_newSession:hover{background:var(--qilin-alias-interactive-bg-hover)}._1HRR8W_newSessionLabel{white-space:nowrap;max-width:min(200px,100% - 88px);overflow:hidden}._1HRR8W_collapsed ._1HRR8W_newSessionLabel{max-width:0}._1HRR8W_newSessionShortcut{pointer-events:none;opacity:0;flex:none;font-weight:400;display:inline-flex;position:absolute;right:12px}._1HRR8W_newSession:is(:hover,:focus-visible) ._1HRR8W_newSessionShortcut{opacity:1}._1HRR8W_panelList{flex-direction:column;flex:none;gap:4px;margin-bottom:8px;display:flex}._1HRR8W_panelSection{letter-spacing:.08em;min-height:0;color:var(--qilin-alias-label-tertiary,#7a8b9f);user-select:none;align-items:center;padding:12px 10px 2px;font-size:11px;display:flex}._1HRR8W_sectionCaret{opacity:.55;margin-left:auto;transition:transform .15s;display:inline-flex}._1HRR8W_panelSection[role=button]{cursor:pointer}._1HRR8W_sectionCaretFolded{transform:rotate(-90deg)}._1HRR8W_panelSectionRail{background:var(--qilin-alias-border-l1,#e8eff712);width:100%;height:.5px;display:block}._1HRR8W_panelList>._1HRR8W_panelSection:first-child{padding-top:4px}._1HRR8W_collapsed ._1HRR8W_panelList ._1HRR8W_panelSection{margin:-3px 0;padding:0}._1HRR8W_panelRow{box-sizing:border-box;min-height:36px;color:var(--qilin-alias-label-primary);font:inherit;text-align:left;cursor:pointer;background:0 0;border:none;border-radius:12px;align-items:center;gap:8px;margin:0 2px;padding:7px 8px;line-height:22px;display:flex}._1HRR8W_panelRow:hover{background:var(--qilin-alias-interactive-bg-hover)}._1HRR8W_panelRow._1HRR8W_panelActive{background:var(--qilin-alias-interactive-bg-hover);color:var(--qilin-alias-label-primary)}._1HRR8W_panelRow:focus-visible{outline:var(--qilin-focus-ring-width) solid var(--qilin-focus-ring-color,var(--qilin-alias-state-business-primary));outline-offset:-2px}._1HRR8W_panelGlyph{flex:none;justify-content:center;align-items:center;display:inline-flex}._1HRR8W_panelTitle{text-overflow:ellipsis;white-space:nowrap;min-width:0;overflow:hidden}._1HRR8W_collapsed ._1HRR8W_panelList{gap:12px;margin-bottom:12px}._1HRR8W_collapsed ._1HRR8W_panelRow{width:36px;height:36px;color:var(--qilin-alias-label-primary);justify-content:center;margin:0;padding:0}._1HRR8W_regionArea{min-height:0;margin-left:-4px;margin-right:calc(-1 * var(--qilin-sidebar-inline-padding));flex-direction:column;flex:1;padding-left:4px;display:flex;overflow:hidden}._1HRR8W_collapsed ._1HRR8W_regionArea{margin-left:0;margin-right:0;padding-left:0}._1HRR8W_footArea{flex-direction:column;flex:none;display:flex}._1HRR8W_settingsArea,._1HRR8W_accountArea,._1HRR8W_footerActions{flex:none;width:100%;min-width:0}._1HRR8W_footerActions{display:flex}._1HRR8W_collapsed ._1HRR8W_footArea{align-items:center}._1HRR8W_collapsed ._1HRR8W_settingsArea,._1HRR8W_collapsed ._1HRR8W_accountArea,._1HRR8W_collapsed ._1HRR8W_footerActions{justify-content:center;width:auto;display:flex}@media (prefers-reduced-motion:reduce){._1HRR8W_wide,._1HRR8W_fading>*,._1HRR8W_railIn ._1HRR8W_iconButton,._1HRR8W_railIn ._1HRR8W_newSession,._1HRR8W_railIn ._1HRR8W_panelList,._1HRR8W_railIn ._1HRR8W_footArea,._1HRR8W_railIn ._1HRR8W_regionArea{transition:none;animation:none}}._1HRR8W_topStripFixed{z-index:40;align-items:center;gap:8px;height:52px;padding:0 8px 0 88px;display:none;position:fixed;top:0;left:0}[data-sidebar-collapsed] ._1HRR8W_topStripFixed{display:flex}[data-sidebar-collapsed]:has([class*=_headerLeading]) ._1HRR8W_topStripFixed{display:none}";
100
+ const tagId = "@qilin-agent/client-ui-sidebar/SidebarRoot.module.css";
101
+ if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId) + "]") === null) {
102
+ const tag = document.createElement("style");
103
+ tag.dataset.plugin = "@qilin-agent/client-ui-sidebar";
104
+ tag.dataset.pluginCss = tagId;
105
+ tag.textContent = css;
106
+ document.head.appendChild(tag);
107
+ }
108
+ var SidebarRoot_module_css_default = {
109
+ "accountArea": "_1HRR8W_accountArea",
110
+ "brand": "_1HRR8W_brand",
111
+ "brandIdentity": "_1HRR8W_brandIdentity",
112
+ "brandMark": "_1HRR8W_brandMark",
113
+ "brandName": "_1HRR8W_brandName",
114
+ "buildBadge": "_1HRR8W_buildBadge",
115
+ "collapsed": "_1HRR8W_collapsed",
116
+ "fading": "_1HRR8W_fading",
117
+ "fallbackBrandName": "_1HRR8W_fallbackBrandName",
118
+ "footArea": "_1HRR8W_footArea",
119
+ "footerActions": "_1HRR8W_footerActions",
120
+ "iconButton": "_1HRR8W_iconButton",
121
+ "logoRow": "_1HRR8W_logoRow",
122
+ "newSession": "_1HRR8W_newSession",
123
+ "newSessionLabel": "_1HRR8W_newSessionLabel",
124
+ "newSessionShortcut": "_1HRR8W_newSessionShortcut",
125
+ "panelActive": "_1HRR8W_panelActive",
126
+ "panelGlyph": "_1HRR8W_panelGlyph",
127
+ "panelIcon": "_1HRR8W_panelIcon",
128
+ "panelList": "_1HRR8W_panelList",
129
+ "panelRow": "_1HRR8W_panelRow",
130
+ "panelSection": "_1HRR8W_panelSection",
131
+ "panelSectionRail": "_1HRR8W_panelSectionRail",
132
+ "panelTitle": "_1HRR8W_panelTitle",
133
+ "quietBars": "_1HRR8W_quietBars",
134
+ "rail-fade-in": "_1HRR8W_rail-fade-in",
135
+ "rail-in": "_1HRR8W_rail-in",
136
+ "railIn": "_1HRR8W_railIn",
137
+ "railMark": "_1HRR8W_railMark",
138
+ "regionArea": "_1HRR8W_regionArea",
139
+ "root": "_1HRR8W_root",
140
+ "sectionCaret": "_1HRR8W_sectionCaret",
141
+ "sectionCaretFolded": "_1HRR8W_sectionCaretFolded",
142
+ "settingsArea": "_1HRR8W_settingsArea",
143
+ "toggle": "_1HRR8W_toggle",
144
+ "topStrip": "_1HRR8W_topStrip",
145
+ "topStripFixed": "_1HRR8W_topStripFixed",
146
+ "wide": "_1HRR8W_wide",
147
+ "wide-in": "_1HRR8W_wide-in"
148
+ };
149
+ //#endregion
150
+ //#region lib/types/client/SidebarRoot.js
151
+ /**
152
+ * Sidebar shell: column geometry and global panel navigation.
153
+ * Collapse is a slide plus crossfade:
154
+ * content freezes at its expanded width (inline style) and fades out in place
155
+ * while the sliding column (AppFrame grid tracks) clips it — nothing reflows
156
+ * mid-slide. At settle the wide-only content unmounts and the upper
157
+ * controls enter the 56px rail from the same horizontal offset (one icon each,
158
+ * same top-down order) on one fade that ends with the slide. The bottom-pinned
159
+ * footer seats only fade. The workspace/session browsing region between
160
+ * global panel rows and the foot is the `sidebar.workspaces` registrant's,
161
+ * and the foot stacks `sidebar.footer.action`, the `sidebar.account` row, and
162
+ * `sidebar.settings`; the shell hands them the wide flag (plus an expand
163
+ * request callback for the browser).
164
+ *
165
+ * The column also owns whether the scroll regions nested in it draw a
166
+ * scrollbar at all: the shell tracks the pointer and rebinds ui-theme's
167
+ * scrollbar indirection away while it is elsewhere, so a list the user is not
168
+ * pointing at carries no bar.
169
+ */
170
+ /** Folded sections of the panel list, scoped to the account the document names. */
171
+ const FOLDED_SECTIONS_KEY = "qilin.sidebar.folded-sections.v1";
172
+ /** Wide-content unmount delay; matches the 150ms wide-content fade-out. */
173
+ const COLLAPSE_SETTLE_MS = 150;
174
+ /**
175
+ * How long the column's scrollbars stay drawn after the pointer leaves it.
176
+ * The bar is a pointer affordance here, and hiding it on the leave event
177
+ * itself makes it blink out while the pointer is only crossing the column's
178
+ * edge — on the way to the conversation, or around a portalled menu.
179
+ */
180
+ const SCROLLBAR_LINGER_MS = 2e3;
181
+ /**
182
+ * Read the build identity the client artifact was compiled with.
183
+ * @returns the badge facts, or undefined when the artifact carries no version.
184
+ */
185
+ function localBuild() {
186
+ const engine = "3.1.4";
187
+ const version = {}.QILIN_CLIENT_PRODUCT_VERSION ?? engine;
188
+ if (version === void 0) return void 0;
189
+ return {
190
+ version,
191
+ detail: version + `-e180446` + ({}.QILIN_CLIENT_GIT_DIRTY === "true" ? "-dirty" : "") + (engine === version ? "" : `(引擎 ${engine})`)
192
+ };
193
+ }
194
+ /** Each panel row subscribes only to its own selection state. */
195
+ function PanelRow({ id, label, wide, usePanelInfo, selectPanel, renderSlot }) {
196
+ const active = usePanelInfo((info) => info.activePanelId === id);
197
+ return (0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.Tooltip, {
198
+ label,
199
+ delayMs: 500,
200
+ disabled: wide,
201
+ children: (0, react_jsx_runtime.jsxs)("button", {
202
+ type: "button",
203
+ className: clsx(SidebarRoot_module_css_default.panelRow, active && SidebarRoot_module_css_default.panelActive),
204
+ "aria-label": label,
205
+ "aria-current": active ? "page" : void 0,
206
+ onClick: () => {
207
+ selectPanel(id);
208
+ },
209
+ children: [(0, react_jsx_runtime.jsx)("span", {
210
+ className: SidebarRoot_module_css_default.panelGlyph,
211
+ "aria-hidden": "true",
212
+ children: renderSlot("sidebar.panellist", {
213
+ size: wide ? 16 : 18,
214
+ active
215
+ }, { only: id })
216
+ }), wide && (0, react_jsx_runtime.jsx)("span", {
217
+ className: clsx(SidebarRoot_module_css_default.panelTitle, SidebarRoot_module_css_default.wide),
218
+ children: label
219
+ })]
220
+ })
221
+ });
222
+ }
223
+ /**
224
+ * Render the sidebar column shell.
225
+ * @param props - composed slot props (runtime share + injected callbacks, contract/slots.ts).
226
+ * @returns the sidebar element tree.
227
+ */
228
+ function SidebarRoot({ collapsed, width, startSession, toggleSidebar, selectPanel, usePanels, useShortcuts, usePanelInfo, t, renderSlot }) {
229
+ const panels = usePanels((snapshot) => snapshot);
230
+ const shortcut = useShortcuts((rows) => rows.find((row) => row.id === "sidebar.left.toggle"));
231
+ const newShortcut = useShortcuts((rows) => rows.find((row) => row.id === "session.new"));
232
+ const [settled, setSettled] = (0, react.useState)(collapsed);
233
+ (0, react.useEffect)(() => {
234
+ if (!collapsed) {
235
+ setSettled(false);
236
+ return;
237
+ }
238
+ const timer = window.setTimeout(() => {
239
+ setSettled(true);
240
+ }, COLLAPSE_SETTLE_MS);
241
+ return () => {
242
+ window.clearTimeout(timer);
243
+ };
244
+ }, [collapsed]);
245
+ const windowsTitlebar = document.documentElement.hasAttribute("data-windows-titlebar");
246
+ const wide = windowsTitlebar ? !collapsed : !collapsed || !settled;
247
+ const lastWideWidth = (0, react.useRef)(width);
248
+ if (!collapsed) lastWideWidth.current = width;
249
+ const everWide = (0, react.useRef)(!collapsed);
250
+ if (!collapsed) everWide.current = true;
251
+ const column = (0, react.useRef)(null);
252
+ const [pointerInside, setPointerInside] = (0, react.useState)(false);
253
+ const lingerTimer = (0, react.useRef)(void 0);
254
+ const armLinger = () => {
255
+ if (lingerTimer.current !== void 0) return;
256
+ lingerTimer.current = window.setTimeout(() => {
257
+ lingerTimer.current = void 0;
258
+ setPointerInside(false);
259
+ }, SCROLLBAR_LINGER_MS);
260
+ };
261
+ const cancelLinger = () => {
262
+ window.clearTimeout(lingerTimer.current);
263
+ lingerTimer.current = void 0;
264
+ };
265
+ (0, react.useEffect)(() => {
266
+ if (!pointerInside) return;
267
+ const onMove = (event) => {
268
+ const rect = column.current?.getBoundingClientRect();
269
+ /* v8 ignore next -- the listener only exists while the column is mounted and revealed. */
270
+ if (rect === void 0) return;
271
+ if (event.clientX >= rect.left && event.clientX < rect.right && event.clientY >= rect.top && event.clientY < rect.bottom) cancelLinger();
272
+ else armLinger();
273
+ };
274
+ document.addEventListener("pointermove", onMove);
275
+ return () => {
276
+ document.removeEventListener("pointermove", onMove);
277
+ cancelLinger();
278
+ };
279
+ }, [pointerInside]);
280
+ const build = localBuild();
281
+ const darwinDesktop = (0, _qilin_agent_client_ui_primitives.isDarwinDesktop)();
282
+ const [foldedSections, setFoldedSections] = (0, react.useState)(() => {
283
+ try {
284
+ const raw = localStorage.getItem((0, _qilin_agent_client_store.accountScopedName)(FOLDED_SECTIONS_KEY));
285
+ const list = raw === null ? [] : JSON.parse(raw);
286
+ return new Set(Array.isArray(list) ? list.filter((row) => typeof row === "string") : []);
287
+ } catch {
288
+ return /* @__PURE__ */ new Set();
289
+ }
290
+ });
291
+ const toggleSection = (section) => {
292
+ setFoldedSections((previous) => {
293
+ const next = new Set(previous);
294
+ if (next.has(section)) next.delete(section);
295
+ else next.add(section);
296
+ try {
297
+ localStorage.setItem((0, _qilin_agent_client_store.accountScopedName)(FOLDED_SECTIONS_KEY), JSON.stringify([...next]));
298
+ } catch {}
299
+ return next;
300
+ });
301
+ };
302
+ const toggle = (0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.Tooltip, {
303
+ label: collapsed ? t("toggle.open") : t("toggle.collapse"),
304
+ shortcutKeys: shortcut?.keys,
305
+ delayMs: 500,
306
+ children: (0, react_jsx_runtime.jsxs)("button", {
307
+ type: "button",
308
+ className: clsx(SidebarRoot_module_css_default.iconButton, SidebarRoot_module_css_default.toggle),
309
+ "aria-label": collapsed ? t("toggle.open") : t("toggle.collapse"),
310
+ "aria-keyshortcuts": shortcut?.aria,
311
+ onClick: () => {
312
+ toggleSidebar();
313
+ },
314
+ children: [
315
+ !wide && !windowsTitlebar && (0, react_jsx_runtime.jsx)("span", {
316
+ className: SidebarRoot_module_css_default.railMark,
317
+ "aria-hidden": "true",
318
+ children: renderSlot("sidebar.brand.mark", { size: 24 }, { fallback: (0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.QilinSeal, { size: 24 }) })
319
+ }),
320
+ (0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.IconPanelLeftOutline16, {
321
+ className: SidebarRoot_module_css_default.panelIcon,
322
+ size: wide || windowsTitlebar ? 16 : 18
323
+ }),
324
+ !wide && renderSlot("sidebar.toggle.badge", {})
325
+ ]
326
+ })
327
+ });
328
+ return (0, react_jsx_runtime.jsxs)("div", {
329
+ ref: column,
330
+ className: clsx(SidebarRoot_module_css_default.root, !wide && SidebarRoot_module_css_default.collapsed, !wide && everWide.current && SidebarRoot_module_css_default.railIn, collapsed && wide && SidebarRoot_module_css_default.fading, !pointerInside && SidebarRoot_module_css_default.quietBars),
331
+ style: wide ? { width: collapsed ? lastWideWidth.current : width } : void 0,
332
+ onPointerEnter: () => {
333
+ cancelLinger();
334
+ setPointerInside(true);
335
+ },
336
+ onPointerLeave: () => {
337
+ armLinger();
338
+ },
339
+ children: [
340
+ darwinDesktop && (0, react_jsx_runtime.jsx)("div", {
341
+ className: SidebarRoot_module_css_default.topStrip,
342
+ "data-window-drag": true,
343
+ children: toggle
344
+ }),
345
+ darwinDesktop && !wide && (0, react_jsx_runtime.jsxs)("div", {
346
+ className: SidebarRoot_module_css_default.topStripFixed,
347
+ "data-window-drag": true,
348
+ children: [(0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.Tooltip, {
349
+ label: t("toggle.open"),
350
+ delayMs: 500,
351
+ children: (0, react_jsx_runtime.jsx)("button", {
352
+ type: "button",
353
+ className: SidebarRoot_module_css_default.iconButton,
354
+ "aria-label": t("toggle.open"),
355
+ onClick: () => {
356
+ toggleSidebar();
357
+ },
358
+ children: (0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.IconPanelLeftOutline16, { size: 16 })
359
+ })
360
+ }), (0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.Tooltip, {
361
+ label: t("session.new.label"),
362
+ delayMs: 500,
363
+ children: (0, react_jsx_runtime.jsx)("button", {
364
+ type: "button",
365
+ className: SidebarRoot_module_css_default.iconButton,
366
+ "aria-label": t("session.new.label"),
367
+ "aria-keyshortcuts": newShortcut?.aria,
368
+ onClick: () => {
369
+ startSession();
370
+ },
371
+ children: (0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.IconNewChatOutline16, { size: 16 })
372
+ })
373
+ })]
374
+ }),
375
+ (0, react_jsx_runtime.jsxs)("div", {
376
+ className: SidebarRoot_module_css_default.logoRow,
377
+ children: [wide && (0, react_jsx_runtime.jsx)("button", {
378
+ type: "button",
379
+ className: clsx(SidebarRoot_module_css_default.brand, SidebarRoot_module_css_default.wide),
380
+ "aria-label": t("session.new.label"),
381
+ "aria-keyshortcuts": newShortcut?.aria,
382
+ onClick: () => {
383
+ startSession();
384
+ },
385
+ children: (0, react_jsx_runtime.jsxs)("span", {
386
+ className: SidebarRoot_module_css_default.brandIdentity,
387
+ "aria-hidden": "true",
388
+ children: [(0, react_jsx_runtime.jsx)("span", {
389
+ className: SidebarRoot_module_css_default.brandMark,
390
+ children: renderSlot("sidebar.brand.mark", { size: 24 }, { fallback: (0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.QilinSeal, { size: 24 }) })
391
+ }), (0, react_jsx_runtime.jsxs)("span", {
392
+ className: SidebarRoot_module_css_default.brandName,
393
+ children: [renderSlot("sidebar.brand.name", {}, { fallback: (0, react_jsx_runtime.jsx)("span", {
394
+ className: SidebarRoot_module_css_default.fallbackBrandName,
395
+ children: t("brand.localBuild")
396
+ }) }), build !== void 0 && (0, react_jsx_runtime.jsx)("span", {
397
+ className: SidebarRoot_module_css_default.buildBadge,
398
+ title: build.detail,
399
+ children: build.version
400
+ })]
401
+ })]
402
+ })
403
+ }), !darwinDesktop && toggle]
404
+ }),
405
+ (0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.Tooltip, {
406
+ label: t("session.new.label"),
407
+ shortcutKeys: newShortcut?.keys,
408
+ delayMs: 500,
409
+ disabled: wide,
410
+ children: (0, react_jsx_runtime.jsxs)("button", {
411
+ type: "button",
412
+ className: SidebarRoot_module_css_default.newSession,
413
+ "aria-label": t("session.new.label"),
414
+ "aria-keyshortcuts": newShortcut?.aria,
415
+ onClick: () => {
416
+ startSession();
417
+ },
418
+ children: [
419
+ (0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.IconNewChatOutline16, { size: wide ? 14 : windowsTitlebar ? 16 : 18 }),
420
+ wide && (0, react_jsx_runtime.jsx)("span", {
421
+ className: clsx(SidebarRoot_module_css_default.newSessionLabel, SidebarRoot_module_css_default.wide),
422
+ children: t("session.new")
423
+ }),
424
+ wide && newShortcut !== void 0 && newShortcut.keys.length > 0 && (0, react_jsx_runtime.jsx)("span", {
425
+ className: SidebarRoot_module_css_default.newSessionShortcut,
426
+ "aria-hidden": "true",
427
+ children: (0, react_jsx_runtime.jsx)(_qilin_agent_client_ui_primitives.ShortcutKeys, { keys: newShortcut.keys })
428
+ })
429
+ ]
430
+ })
431
+ }),
432
+ panels.length > 0 && (0, react_jsx_runtime.jsx)("nav", {
433
+ className: SidebarRoot_module_css_default.panelList,
434
+ "aria-label": t("panels.label"),
435
+ children: panels.map(({ id, label, section }, index) => {
436
+ const sectionFolded = section !== void 0 && foldedSections.has(section);
437
+ return (0, react_jsx_runtime.jsxs)(react.Fragment, { children: [section !== void 0 && section !== panels[index - 1]?.section ? (0, react_jsx_runtime.jsxs)("div", {
438
+ className: clsx(SidebarRoot_module_css_default.panelSection, wide && SidebarRoot_module_css_default.wide),
439
+ "aria-hidden": !wide,
440
+ ...wide ? {
441
+ role: "button",
442
+ tabIndex: 0,
443
+ "aria-expanded": !foldedSections.has(section),
444
+ onClick: () => {
445
+ toggleSection(section);
446
+ },
447
+ onKeyDown: (event) => {
448
+ if (event.key === "Enter" || event.key === " ") {
449
+ event.preventDefault();
450
+ toggleSection(section);
451
+ }
452
+ }
453
+ } : {},
454
+ children: [wide ? section : (0, react_jsx_runtime.jsx)("span", { className: SidebarRoot_module_css_default.panelSectionRail }), wide && (0, react_jsx_runtime.jsx)("span", {
455
+ className: clsx(SidebarRoot_module_css_default.sectionCaret, foldedSections.has(section) && SidebarRoot_module_css_default.sectionCaretFolded),
456
+ "aria-hidden": "true",
457
+ children: (0, react_jsx_runtime.jsx)("svg", {
458
+ width: "10",
459
+ height: "10",
460
+ viewBox: "0 0 16 16",
461
+ fill: "none",
462
+ stroke: "currentColor",
463
+ strokeWidth: "1.6",
464
+ strokeLinecap: "round",
465
+ strokeLinejoin: "round",
466
+ children: (0, react_jsx_runtime.jsx)("path", { d: "M4 6.5 8 10.5 12 6.5" })
467
+ })
468
+ })]
469
+ }) : null, section === void 0 || !sectionFolded ? (0, react_jsx_runtime.jsx)(PanelRow, {
470
+ id,
471
+ label,
472
+ wide,
473
+ usePanelInfo,
474
+ selectPanel,
475
+ renderSlot
476
+ }) : null] }, id);
477
+ })
478
+ }),
479
+ (0, react_jsx_runtime.jsx)("div", {
480
+ className: SidebarRoot_module_css_default.regionArea,
481
+ children: renderSlot("sidebar.workspaces", {
482
+ wide,
483
+ expandSidebar: () => {
484
+ if (collapsed) toggleSidebar();
485
+ }
486
+ })
487
+ }),
488
+ (0, react_jsx_runtime.jsxs)("div", {
489
+ className: SidebarRoot_module_css_default.footArea,
490
+ children: [
491
+ (0, react_jsx_runtime.jsx)("div", {
492
+ className: SidebarRoot_module_css_default.footerActions,
493
+ children: renderSlot("sidebar.footer.action", { wide })
494
+ }),
495
+ (0, react_jsx_runtime.jsx)("div", {
496
+ className: SidebarRoot_module_css_default.accountArea,
497
+ children: renderSlot("sidebar.account", { wide })
498
+ }),
499
+ (0, react_jsx_runtime.jsx)("div", {
500
+ className: SidebarRoot_module_css_default.settingsArea,
501
+ children: renderSlot("sidebar.settings", { wide })
502
+ })
503
+ ]
504
+ })
505
+ ]
506
+ });
507
+ }
508
+ //#endregion
509
+ //#region lib/types/client/locales.js
510
+ /** `sidebar` namespace dictionaries for shell controls and global panels. */
511
+ /** Simplified Chinese dictionary (the key-set source of truth). */
512
+ const zh = {
513
+ "shortcut.hint": "{label} {keys}",
514
+ "session.new": "新会话",
515
+ "session.new.label": "新建会话",
516
+ "toggle.open": "打开侧边栏",
517
+ "toggle.collapse": "收起侧边栏",
518
+ "panels.label": "全局面板"
519
+ };
520
+ /** English dictionary, checked complete against the zh key set. */
521
+ const en = {
522
+ "shortcut.hint": "{label} {keys}",
523
+ "session.new": "New Session",
524
+ "session.new.label": "New session",
525
+ "toggle.open": "Open sidebar",
526
+ "toggle.collapse": "Collapse sidebar",
527
+ "panels.label": "Global panels"
528
+ };
529
+ //#endregion
530
+ //#region lib/types/client/index.js
531
+ /** Dictionary namespace owned by this plugin. */
532
+ const NS = "sidebar";
533
+ /** Services required by the sidebar plugin. */
534
+ const inject = [
535
+ "slots",
536
+ "layout",
537
+ "uiWorkspace",
538
+ "locale",
539
+ "shortcuts"
540
+ ];
541
+ /** Registers the sidebar shell and its service callbacks.
542
+ * @param ctx - Client root context.
543
+ */
544
+ function apply(ctx) {
545
+ const workspaceNavigation = ctx.get("uiWorkspace");
546
+ ctx.effect(() => ctx.locale.register(NS, {
547
+ zh,
548
+ en
549
+ }), "ui-sidebar: dictionaries");
550
+ const panels = (0, _qilin_agent_client_store.createSnapshotStore)([]);
551
+ const syncPanels = () => {
552
+ const desktop = (0, _qilin_agent_client_ui_primitives.isDarwinDesktop)();
553
+ const assigned = {};
554
+ for (const entry of ctx.slots.entriesOfSlot("sidebar.section.assignments")) {
555
+ const face = entry.inject?.(void 0);
556
+ if (face?.assignments !== void 0) Object.assign(assigned, face.assignments);
557
+ }
558
+ const next = ctx.slots.entriesOfSlot("sidebar.panellist").map(({ options }) => {
559
+ const id = options.id;
560
+ const trailing = desktop && assigned[id] === void 0 && (0, _qilin_agent_client_ui_slots.resolveSlotLabel)(options.section) === void 0 ? "扩展" : void 0;
561
+ const section = assigned[id] ?? (0, _qilin_agent_client_ui_slots.resolveSlotLabel)(options.section) ?? trailing;
562
+ return {
563
+ id,
564
+ order: options.order ?? 0,
565
+ label: (0, _qilin_agent_client_ui_slots.resolveSlotLabel)(options.label) ?? id,
566
+ section
567
+ };
568
+ }).sort((a, b) => a.order - b.order);
569
+ const previous = panels.getSnapshot();
570
+ if (previous.length === next.length && previous.every((panel, index) => {
571
+ const candidate = next[index];
572
+ return panel.id === candidate.id && panel.order === candidate.order && panel.label === candidate.label && panel.section === candidate.section;
573
+ })) return;
574
+ panels.set(next);
575
+ };
576
+ ctx.effect(() => ctx.slots.subscribe("sidebar.panellist", syncPanels), "ui-sidebar: panel entries");
577
+ ctx.effect(() => ctx.slots.subscribe("sidebar.section.assignments", syncPanels), "ui-sidebar: section assignments");
578
+ ctx.effect(() => ctx.locale.subscribe(syncPanels), "ui-sidebar: panel labels");
579
+ ctx.effect(() => (0, _qilin_agent_client_ui_primitives.watchDarwinDesktop)(syncPanels), "ui-sidebar: darwin mark");
580
+ const injectProps = () => ({
581
+ startSession: (workspaceId) => {
582
+ workspaceNavigation.startSession(workspaceId);
583
+ },
584
+ toggleSidebar: () => {
585
+ ctx.layout.toggleSidebar();
586
+ },
587
+ selectPanel: (id) => {
588
+ ctx.layout.selectPanel(id);
589
+ },
590
+ hooks: {
591
+ panels,
592
+ shortcuts: ctx.shortcuts.catalog
593
+ }
594
+ });
595
+ ctx.slots.inject("sidebar", () => ctx.slots.register({
596
+ name: "sidebar",
597
+ locale: NS,
598
+ children: {
599
+ "sidebar.brand.mark": {
600
+ kind: "single",
601
+ scope: "root"
602
+ },
603
+ "sidebar.brand.name": {
604
+ kind: "single",
605
+ scope: "root"
606
+ },
607
+ "sidebar.toggle.badge": {
608
+ kind: "single",
609
+ scope: "root"
610
+ },
611
+ "sidebar.panellist": {
612
+ kind: "list",
613
+ scope: "root"
614
+ },
615
+ "sidebar.section.assignments": {
616
+ kind: "list",
617
+ scope: "root"
618
+ },
619
+ "sidebar.workspaces": {
620
+ kind: "single",
621
+ scope: "root"
622
+ },
623
+ "sidebar.settings": {
624
+ kind: "single",
625
+ scope: "root"
626
+ },
627
+ "sidebar.account": {
628
+ kind: "single",
629
+ scope: "root"
630
+ },
631
+ "sidebar.footer.action": {
632
+ kind: "list",
633
+ scope: "root"
634
+ }
635
+ },
636
+ inject: injectProps
637
+ }, SidebarRoot));
638
+ ctx.slots.inject("conversation.header.leading", () => ctx.slots.register({
639
+ name: "conversation.header.leading",
640
+ locale: NS,
641
+ inject: injectProps
642
+ }, HeaderLeadingControls));
643
+ ctx.slots.inject("sidebar.section.assignments", () => ctx.slots.register({
644
+ name: "sidebar.section.assignments",
645
+ id: "ok-desktop-sections",
646
+ inject: () => (0, _qilin_agent_client_ui_primitives.isDarwinDesktop)() ? { assignments: {
647
+ plugins: "通用",
648
+ schedules: "通用"
649
+ } } : {}
650
+ }, () => null));
651
+ syncPanels();
652
+ }
653
+ //#endregion
654
+ exports.apply = apply;
655
+ exports.inject = inject;
656
+ return module.exports;
657
+ }
658
+ });
659
+
660
+ //# sourceMappingURL=client.js.map