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.
- package/CHANGELOG.md +125 -0
- package/CONTRIBUTING.md +90 -0
- package/LICENSE +21 -0
- package/README.md +110 -2
- package/README_en.md +136 -0
- package/THIRD_PARTY_NOTICES.md +15 -0
- package/cordis.patch.yml +15 -0
- package/docs/AGENTS.md +16 -0
- package/docs/README.md +25 -0
- package/docs/architecture.md +170 -0
- package/docs/browser-integration.md +94 -0
- package/docs/distribution.md +66 -0
- package/docs/harness-browser-annotation.patch +1909 -0
- package/docs/images/annotation-expanded-dark.png +0 -0
- package/docs/images/annotation-expanded.png +0 -0
- package/docs/images/annotation-image.png +0 -0
- package/docs/images/annotation-message.png +0 -0
- package/docs/images/annotation-region.png +0 -0
- package/docs/marketplace/cslkkl__dsh-web-annotator.yml +7 -0
- package/docs/publishing.md +169 -0
- package/docs/roadmap.md +31 -0
- package/docs/verification.md +179 -0
- package/dsh-plugin.naming.json +27 -0
- package/examples/responsive-demo/AGENTS.md +12 -0
- package/examples/responsive-demo/README.md +33 -0
- package/examples/responsive-demo/index.html +13 -0
- package/examples/responsive-demo/src/main.tsx +110 -0
- package/examples/responsive-demo/src/style.css +344 -0
- package/examples/responsive-demo/vite.config.ts +9 -0
- package/lib/THIRD_PARTY_LICENSES.md +345 -0
- package/lib/bridge.js +890 -0
- package/lib/bridge.js.map +7 -0
- package/lib/client.js +1083 -0
- package/lib/client.js.map +7 -0
- package/lib/host/THIRD_PARTY_NOTICES.md +15 -0
- package/lib/host/browser-provider/LICENSE +21 -0
- package/lib/host/browser-provider/README.md +130 -0
- package/lib/host/browser-provider/lib/client.css +217 -0
- package/lib/host/browser-provider/lib/client.css.map +7 -0
- package/lib/host/browser-provider/lib/client.js +2360 -0
- package/lib/host/browser-provider/lib/client.js.map +7 -0
- package/lib/host/browser-provider/lib/index.js +7 -0
- package/lib/host/browser-provider/lib/index.js.map +7 -0
- package/lib/host/browser-provider/package.json +23 -0
- package/lib/host/bundle.json +27 -0
- package/lib/host/chat-provider/LICENSE +21 -0
- package/lib/host/chat-provider/README.md +186 -0
- package/lib/host/chat-provider/lib/client.css +1604 -0
- package/lib/host/chat-provider/lib/client.css.map +7 -0
- package/lib/host/chat-provider/lib/client.js +11074 -0
- package/lib/host/chat-provider/lib/client.js.map +7 -0
- package/lib/host/chat-provider/lib/index.js +911 -0
- package/lib/host/chat-provider/lib/index.js.map +7 -0
- package/lib/host/chat-provider/package.json +31 -0
- package/lib/host/layout-provider/LICENSE +21 -0
- package/lib/host/layout-provider/README.md +109 -0
- package/lib/host/layout-provider/lib/client.css +177 -0
- package/lib/host/layout-provider/lib/client.css.map +7 -0
- package/lib/host/layout-provider/lib/client.js +565 -0
- package/lib/host/layout-provider/lib/client.js.map +7 -0
- package/lib/host/layout-provider/lib/index.js +7 -0
- package/lib/host/layout-provider/lib/index.js.map +7 -0
- package/lib/host/layout-provider/package.json +25 -0
- package/lib/index.d.ts +2 -0
- package/lib/index.js +9 -0
- package/lib/index.js.map +7 -0
- package/lib/vite.d.ts +8 -0
- package/lib/vite.js +1254 -0
- package/lib/vite.js.map +7 -0
- package/licenses/deepseek-harness-MIT.txt +21 -0
- package/locale/AGENTS.md +11 -0
- package/locale/README.md +11 -0
- package/locale/en.json +6 -0
- package/locale/zh.json +6 -0
- package/package.json +154 -4
- package/screenshots.json +7 -0
|
@@ -0,0 +1,565 @@
|
|
|
1
|
+
window.__ModuleLoader__.load({ id: '@deepseek-ai/dsh-client-ui-layout', factory: function(require) { var module = { exports: {} }; var exports = module.exports;
|
|
2
|
+
const cssDispose = () => { const style = document.createElement('style'); style.textContent = "/* .host-source/packages/client/ui-layout/src/client/AppFrame.module.css */\n.AppFrame_frame {\n position: relative;\n display: grid;\n grid-template-rows: 100%;\n height: 100%;\n overflow: hidden;\n background: var(--dsw-alias-bg-base);\n}\n.AppFrame_frame[data-animating] {\n transition: grid-template-columns var(--ds-transition-duration-slow) var(--ds-ease-in-out);\n}\n.AppFrame_frame[data-dragging] {\n transition: none;\n}\n[data-windows-titlebar] .AppFrame_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[data-windows-titlebar] .AppFrame_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[data-windows-titlebar] .AppFrame_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[data-windows-titlebar] .AppFrame_sidebarCol {\n border-right: none;\n}\n[data-windows-titlebar] .AppFrame_handle {\n top: var(--dsh-windows-titlebar-height);\n}\n@media (prefers-reduced-motion: reduce) {\n .AppFrame_frame[data-animating] {\n transition: none;\n }\n}\n.AppFrame_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.AppFrame_centerCol {\n min-width: 0;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n}\n.AppFrame_frame[data-rightbar-fullscreen] .AppFrame_centerCol {\n visibility: hidden;\n}\n[data-platform=darwin] .AppFrame_frame {\n background: transparent;\n}\nhtml[data-platform=darwin] {\n --dsh-frame-top-clearance: 48px;\n}\nhtml[data-windows-titlebar] {\n --dsh-frame-top-clearance: var(--dsh-windows-titlebar-height);\n --dsh-frame-chrome-top: var(--dsh-windows-titlebar-height);\n}\nhtml[data-platform=darwin],\nhtml[data-windows-titlebar] {\n --dsh-frame-overlay-top: calc(var(--dsh-frame-top-clearance) + 20px);\n}\nhtml[data-platform=darwin][data-fullscreen],\nhtml[data-windows-titlebar][data-fullscreen] {\n --dsh-frame-overlay-top: 20px;\n --dsh-frame-chrome-top: 0px;\n}\n[data-platform=darwin] .AppFrame_sidebarCol {\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 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[data-platform=darwin] [data-ds-dark-theme] .AppFrame_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 color-mix(in srgb, var(--dsw-specific-sidebar-fill) 50%, transparent);\n}\n@media (prefers-reduced-transparency: reduce) {\n [data-platform=darwin] .AppFrame_sidebarCol,\n [data-platform=darwin] [data-ds-dark-theme] .AppFrame_sidebarCol {\n background: color-mix(in srgb, var(--dsw-specific-sidebar-fill) 90%, transparent);\n }\n}\n[data-platform=darwin] .AppFrame_centerCol {\n background: var(--dsw-alias-bg-base);\n border-left: 0.5px solid var(--dsw-alias-border-l3);\n}\n[data-platform=darwin] .AppFrame_rightbarCol {\n background: var(--dsw-alias-bg-base);\n}\n[data-platform=darwin] [data-sidebar-collapsed] .AppFrame_centerCol {\n border-left: none;\n}\n[data-platform=darwin] .AppFrame_frame[data-sidebar-collapsed] {\n --dsh-frame-leading-clearance: 160px;\n}\n[data-platform=darwin][data-fullscreen] .AppFrame_frame[data-sidebar-collapsed] {\n --dsh-frame-leading-clearance: 84px;\n}\n[data-platform=darwin][data-fullscreen] .AppFrame_leadingSeat {\n left: 12px;\n}\n.AppFrame_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.AppFrame_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.AppFrame_frame[data-animating] .AppFrame_handle {\n transition: left var(--ds-transition-duration-slow) var(--ds-ease-in-out);\n}\n.AppFrame_frame[data-dragging] .AppFrame_handle {\n transition: none;\n}\n.AppFrame_frame[data-rightbar-fullscreen],\n.AppFrame_frame[data-rightbar-fullscreen] .AppFrame_handle,\n.AppFrame_frame[data-rightbar-instant],\n.AppFrame_frame[data-rightbar-instant] .AppFrame_handle {\n transition: none;\n}\n@media (prefers-reduced-motion: reduce) {\n .AppFrame_frame[data-animating] .AppFrame_handle {\n transition: none;\n }\n}\n.AppFrame_rightbarCol {\n position: relative;\n min-width: 0;\n overflow: visible;\n}\n.AppFrame_overlayLayer {\n position: absolute;\n inset: 0;\n z-index: 20;\n pointer-events: none;\n}\n.AppFrame_overlayLayer > * {\n pointer-events: auto;\n}\n/*# sourceMappingURL=client.css.map */\n"; document.head.append(style); return () => style.remove(); };
|
|
3
|
+
|
|
4
|
+
"use strict";
|
|
5
|
+
var __defProp = Object.defineProperty;
|
|
6
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
7
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
8
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
9
|
+
var __export = (target, all) => {
|
|
10
|
+
for (var name in all)
|
|
11
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
12
|
+
};
|
|
13
|
+
var __copyProps = (to, from, except, desc) => {
|
|
14
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
15
|
+
for (let key of __getOwnPropNames(from))
|
|
16
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
17
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
18
|
+
}
|
|
19
|
+
return to;
|
|
20
|
+
};
|
|
21
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
22
|
+
|
|
23
|
+
// .host-source/packages/client/ui-layout/src/client/index.ts
|
|
24
|
+
var index_exports = {};
|
|
25
|
+
__export(index_exports, {
|
|
26
|
+
LayoutController: () => LayoutController,
|
|
27
|
+
apply: () => apply,
|
|
28
|
+
inject: () => inject
|
|
29
|
+
});
|
|
30
|
+
module.exports = __toCommonJS(index_exports);
|
|
31
|
+
|
|
32
|
+
// .host-source/packages/client/ui-layout/src/client/AppFrame.tsx
|
|
33
|
+
var import_react2 = require("react");
|
|
34
|
+
|
|
35
|
+
// .host-source/packages/client/ui-layout/src/client/columns.ts
|
|
36
|
+
var CENTER_MIN = 400;
|
|
37
|
+
var SIDEBAR_MIN = 264;
|
|
38
|
+
var SIDEBAR_MAX = 420;
|
|
39
|
+
var SIDEBAR_DEFAULT = 280;
|
|
40
|
+
var SIDEBAR_COLLAPSED = 56;
|
|
41
|
+
var SIDEBAR_AUTO_COLLAPSE = 1024;
|
|
42
|
+
var RIGHTBAR_MIN = 300;
|
|
43
|
+
var RIGHTBAR_MAX_RATIO = 0.7;
|
|
44
|
+
var RIGHTBAR_DEFAULT_RATIO = 0.45;
|
|
45
|
+
function clampWidth(px, min, max) {
|
|
46
|
+
return Math.min(max, Math.max(min, Math.round(px)));
|
|
47
|
+
}
|
|
48
|
+
function computeColumns(viewport, sidebar, rightbar, collapsedWidth = SIDEBAR_COLLAPSED) {
|
|
49
|
+
const s = sidebar === 0 ? collapsedWidth : clampWidth(sidebar, SIDEBAR_MIN, SIDEBAR_MAX);
|
|
50
|
+
const available = viewport - s - CENTER_MIN;
|
|
51
|
+
const r = rightbar === 0 || available < RIGHTBAR_MIN ? 0 : Math.min(available, clampWidth(rightbar, RIGHTBAR_MIN, viewport * RIGHTBAR_MAX_RATIO));
|
|
52
|
+
return { sidebar: s, center: Math.max(0, viewport - s - r), rightbar: r };
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// .host-source/packages/client/ui-layout/src/client/DocumentTitle.tsx
|
|
56
|
+
var import_react = require("react");
|
|
57
|
+
function DocumentTitle({ useSessions, usePanelInfo, productTitle }) {
|
|
58
|
+
const showSessionTitle = usePanelInfo((info) => info.activePanelId === null);
|
|
59
|
+
const title = useSessions((state) => {
|
|
60
|
+
const current = Object.values(state.byId).find((session) => (session.retainedBy.mainView ?? 0) > 0)?.id;
|
|
61
|
+
return !showSessionTitle || current === void 0 ? void 0 : state.byId[current]?.title;
|
|
62
|
+
});
|
|
63
|
+
(0, import_react.useEffect)(() => {
|
|
64
|
+
document.title = title === void 0 ? productTitle : `${title} \u2014 ${productTitle}`;
|
|
65
|
+
return () => {
|
|
66
|
+
document.title = productTitle;
|
|
67
|
+
};
|
|
68
|
+
}, [productTitle, title]);
|
|
69
|
+
return null;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// .host-source/packages/client/ui-layout/src/client/AppFrame.module.css
|
|
73
|
+
var AppFrame_default = {
|
|
74
|
+
frame: "AppFrame_frame",
|
|
75
|
+
centerCol: "AppFrame_centerCol",
|
|
76
|
+
sidebarCol: "AppFrame_sidebarCol",
|
|
77
|
+
handle: "AppFrame_handle",
|
|
78
|
+
rightbarCol: "AppFrame_rightbarCol",
|
|
79
|
+
leadingSeat: "AppFrame_leadingSeat",
|
|
80
|
+
overlayLayer: "AppFrame_overlayLayer"
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
// .host-source/packages/client/ui-layout/src/client/AppFrame.tsx
|
|
84
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
85
|
+
function CenterColumn(props) {
|
|
86
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
87
|
+
"div",
|
|
88
|
+
{
|
|
89
|
+
className: AppFrame_default.centerCol,
|
|
90
|
+
"aria-hidden": props.covered || void 0,
|
|
91
|
+
...props.covered ? { inert: "" } : {},
|
|
92
|
+
children: props.children
|
|
93
|
+
}
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
function MainPanel({ usePanelInfo, renderSlot }) {
|
|
97
|
+
const panelId = usePanelInfo((info) => info.activePanelId);
|
|
98
|
+
return renderSlot("main", {}, { entryKey: panelId ?? "conversation" });
|
|
99
|
+
}
|
|
100
|
+
function RightbarColumn(props) {
|
|
101
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: AppFrame_default.rightbarCol, "data-rightbar-col": true, children: props.children });
|
|
102
|
+
}
|
|
103
|
+
function DragHandle(props) {
|
|
104
|
+
const [dragging, setDragging] = (0, import_react2.useState)(false);
|
|
105
|
+
const origin = (0, import_react2.useRef)(0);
|
|
106
|
+
const latest = (0, import_react2.useRef)(0);
|
|
107
|
+
const frame = (0, import_react2.useRef)(null);
|
|
108
|
+
const capture = (0, import_react2.useRef)(null);
|
|
109
|
+
const callbacks = (0, import_react2.useRef)({ onStart: props.onStart, onDrag: props.onDrag, onEnd: props.onEnd });
|
|
110
|
+
callbacks.current = { onStart: props.onStart, onDrag: props.onDrag, onEnd: props.onEnd };
|
|
111
|
+
const endDrag = (0, import_react2.useCallback)(() => {
|
|
112
|
+
const active = capture.current;
|
|
113
|
+
if (active === null) return;
|
|
114
|
+
capture.current = null;
|
|
115
|
+
if (frame.current !== null) {
|
|
116
|
+
cancelAnimationFrame(frame.current);
|
|
117
|
+
frame.current = null;
|
|
118
|
+
}
|
|
119
|
+
if (active.element.hasPointerCapture(active.id)) active.element.releasePointerCapture(active.id);
|
|
120
|
+
setDragging(false);
|
|
121
|
+
callbacks.current.onEnd();
|
|
122
|
+
}, []);
|
|
123
|
+
(0, import_react2.useEffect)(() => endDrag, [endDrag]);
|
|
124
|
+
const onPointerDown = (0, import_react2.useCallback)((e) => {
|
|
125
|
+
if (e.button !== 0 || capture.current !== null) return;
|
|
126
|
+
e.preventDefault();
|
|
127
|
+
e.currentTarget.setPointerCapture(e.pointerId);
|
|
128
|
+
capture.current = { element: e.currentTarget, id: e.pointerId };
|
|
129
|
+
origin.current = e.clientX;
|
|
130
|
+
latest.current = e.clientX;
|
|
131
|
+
callbacks.current.onStart();
|
|
132
|
+
setDragging(true);
|
|
133
|
+
}, []);
|
|
134
|
+
const onPointerMove = (0, import_react2.useCallback)((e) => {
|
|
135
|
+
if (capture.current?.id !== e.pointerId) return;
|
|
136
|
+
latest.current = e.clientX;
|
|
137
|
+
frame.current ??= requestAnimationFrame(() => {
|
|
138
|
+
frame.current = null;
|
|
139
|
+
callbacks.current.onDrag(latest.current - origin.current);
|
|
140
|
+
});
|
|
141
|
+
}, []);
|
|
142
|
+
const onPointerUp = (0, import_react2.useCallback)((e) => {
|
|
143
|
+
if (capture.current?.id !== e.pointerId) return;
|
|
144
|
+
callbacks.current.onDrag(e.clientX - origin.current);
|
|
145
|
+
endDrag();
|
|
146
|
+
}, [endDrag]);
|
|
147
|
+
const onPointerCancel = (0, import_react2.useCallback)((e) => {
|
|
148
|
+
if (capture.current?.id === e.pointerId) endDrag();
|
|
149
|
+
}, [endDrag]);
|
|
150
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
151
|
+
"div",
|
|
152
|
+
{
|
|
153
|
+
className: AppFrame_default.handle,
|
|
154
|
+
style: { left: props.left },
|
|
155
|
+
"data-side": props.side,
|
|
156
|
+
"data-dragging": dragging || void 0,
|
|
157
|
+
onPointerDown,
|
|
158
|
+
onPointerMove,
|
|
159
|
+
onPointerUp,
|
|
160
|
+
onPointerCancel,
|
|
161
|
+
onLostPointerCapture: onPointerCancel
|
|
162
|
+
}
|
|
163
|
+
);
|
|
164
|
+
}
|
|
165
|
+
function AppFrame({
|
|
166
|
+
useStore,
|
|
167
|
+
useSessions,
|
|
168
|
+
usePanelInfo,
|
|
169
|
+
actions,
|
|
170
|
+
renderSlot,
|
|
171
|
+
t
|
|
172
|
+
}) {
|
|
173
|
+
const layoutInfo = useStore((state) => state.layoutInfo);
|
|
174
|
+
const frameRef = (0, import_react2.useRef)(null);
|
|
175
|
+
const viewport = layoutInfo.viewportWidth;
|
|
176
|
+
(0, import_react2.useLayoutEffect)(() => {
|
|
177
|
+
const el = frameRef.current;
|
|
178
|
+
if (el === null) return;
|
|
179
|
+
let raf = null;
|
|
180
|
+
let disposed = false;
|
|
181
|
+
const measure = () => {
|
|
182
|
+
const width = el.getBoundingClientRect().width;
|
|
183
|
+
if (width > 0) actions.setViewportWidth(width);
|
|
184
|
+
};
|
|
185
|
+
measure();
|
|
186
|
+
const observer = new ResizeObserver(() => {
|
|
187
|
+
if (disposed) return;
|
|
188
|
+
raf ??= requestAnimationFrame(() => {
|
|
189
|
+
raf = null;
|
|
190
|
+
measure();
|
|
191
|
+
});
|
|
192
|
+
});
|
|
193
|
+
observer.observe(el);
|
|
194
|
+
return () => {
|
|
195
|
+
disposed = true;
|
|
196
|
+
observer.disconnect();
|
|
197
|
+
if (raf !== null) cancelAnimationFrame(raf);
|
|
198
|
+
};
|
|
199
|
+
}, [actions]);
|
|
200
|
+
const narrow = viewport < SIDEBAR_AUTO_COLLAPSE;
|
|
201
|
+
const sidebarCollapsed = narrow ? !layoutInfo.narrowExpanded : layoutInfo.sidebar === 0;
|
|
202
|
+
const sidebarPreference = sidebarCollapsed ? 0 : layoutInfo.sidebar === 0 ? SIDEBAR_DEFAULT : layoutInfo.sidebar;
|
|
203
|
+
const rightbarPreference = layoutInfo.rightbar ?? viewport * RIGHTBAR_DEFAULT_RATIO;
|
|
204
|
+
const darwin = document.documentElement.dataset.platform === "darwin";
|
|
205
|
+
const collapsedWidth = darwin || document.documentElement.hasAttribute("data-windows-titlebar") ? 0 : SIDEBAR_COLLAPSED;
|
|
206
|
+
const normal = computeColumns(viewport, !layoutInfo.rightbarShown && narrow ? 0 : sidebarPreference, rightbarPreference, collapsedWidth);
|
|
207
|
+
const cols = computeColumns(viewport, sidebarPreference, layoutInfo.rightbarTrack ? rightbarPreference : 0, collapsedWidth);
|
|
208
|
+
const colsRef = (0, import_react2.useRef)(cols);
|
|
209
|
+
colsRef.current = cols;
|
|
210
|
+
const rightbarWidth = (0, import_react2.useRef)(normal.rightbar);
|
|
211
|
+
rightbarWidth.current = normal.rightbar;
|
|
212
|
+
const sidebarBase = (0, import_react2.useRef)(0);
|
|
213
|
+
const rightbarBase = (0, import_react2.useRef)(0);
|
|
214
|
+
const [dragging, setDragging] = (0, import_react2.useState)(false);
|
|
215
|
+
const [animating, setAnimating] = (0, import_react2.useState)(0);
|
|
216
|
+
const trackToggle = `${sidebarCollapsed}:${layoutInfo.rightbarTrack}`;
|
|
217
|
+
const previousToggle = (0, import_react2.useRef)(trackToggle);
|
|
218
|
+
const previousViewport = (0, import_react2.useRef)(viewport);
|
|
219
|
+
(0, import_react2.useLayoutEffect)(() => {
|
|
220
|
+
const viewportChanged = previousViewport.current !== viewport;
|
|
221
|
+
previousViewport.current = viewport;
|
|
222
|
+
if (previousToggle.current === trackToggle) return;
|
|
223
|
+
previousToggle.current = trackToggle;
|
|
224
|
+
if (viewportChanged) return;
|
|
225
|
+
setAnimating((token) => token + 1);
|
|
226
|
+
}, [trackToggle, viewport]);
|
|
227
|
+
(0, import_react2.useEffect)(() => {
|
|
228
|
+
if (animating === 0) return;
|
|
229
|
+
const frame = frameRef.current;
|
|
230
|
+
if (frame === null) return;
|
|
231
|
+
const settle = () => {
|
|
232
|
+
setAnimating(0);
|
|
233
|
+
};
|
|
234
|
+
const onTransitionEnd = (event) => {
|
|
235
|
+
if (event.target === frame && event.propertyName === "grid-template-columns") settle();
|
|
236
|
+
};
|
|
237
|
+
frame.addEventListener("transitionend", onTransitionEnd);
|
|
238
|
+
const timer = setTimeout(settle, 600);
|
|
239
|
+
return () => {
|
|
240
|
+
frame.removeEventListener("transitionend", onTransitionEnd);
|
|
241
|
+
clearTimeout(timer);
|
|
242
|
+
};
|
|
243
|
+
}, [animating]);
|
|
244
|
+
const onDragEnd = (0, import_react2.useCallback)(() => {
|
|
245
|
+
setDragging(false);
|
|
246
|
+
}, []);
|
|
247
|
+
const onSidebarStart = (0, import_react2.useCallback)(() => {
|
|
248
|
+
sidebarBase.current = colsRef.current.sidebar;
|
|
249
|
+
setDragging(true);
|
|
250
|
+
}, []);
|
|
251
|
+
const onSidebarDrag = (0, import_react2.useCallback)((dx) => {
|
|
252
|
+
actions.setSidebar(sidebarBase.current + dx);
|
|
253
|
+
}, [actions]);
|
|
254
|
+
const onRightbarStart = (0, import_react2.useCallback)(() => {
|
|
255
|
+
rightbarBase.current = rightbarWidth.current;
|
|
256
|
+
setDragging(true);
|
|
257
|
+
}, []);
|
|
258
|
+
const onRightbarDrag = (0, import_react2.useCallback)((dx) => {
|
|
259
|
+
actions.setRightbar(rightbarBase.current - dx);
|
|
260
|
+
}, [actions]);
|
|
261
|
+
const productTitle = "DeepSeek Harness";
|
|
262
|
+
const rightbarMax = cols.rightbar === 0 ? 0 : clampWidth(rightbarPreference, RIGHTBAR_MIN, viewport * RIGHTBAR_MAX_RATIO);
|
|
263
|
+
const sidebar = (0, import_react2.useMemo)(() => renderSlot("sidebar", {
|
|
264
|
+
collapsed: sidebarCollapsed,
|
|
265
|
+
width: cols.sidebar
|
|
266
|
+
}), [renderSlot, sidebarCollapsed, cols.sidebar]);
|
|
267
|
+
const main = (0, import_react2.useMemo)(() => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(MainPanel, { usePanelInfo, renderSlot }), [usePanelInfo, renderSlot]);
|
|
268
|
+
const overlays = (0, import_react2.useMemo)(() => renderSlot("shell.overlay", {}), [renderSlot]);
|
|
269
|
+
const leading = (0, import_react2.useMemo)(() => renderSlot("shell.leading", {}), [renderSlot]);
|
|
270
|
+
const leadingMounted = darwin && sidebarCollapsed;
|
|
271
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
272
|
+
"div",
|
|
273
|
+
{
|
|
274
|
+
ref: frameRef,
|
|
275
|
+
className: AppFrame_default.frame,
|
|
276
|
+
style: {
|
|
277
|
+
...document.documentElement.hasAttribute("data-windows-titlebar") ? { "--dsh-windows-sidebar-width": `${cols.sidebar}px` } : {},
|
|
278
|
+
gridTemplateColumns: `${cols.sidebar}px minmax(${cols.rightbar === 0 ? 0 : CENTER_MIN}px, 1fr) minmax(0px, ${rightbarMax}px)`
|
|
279
|
+
},
|
|
280
|
+
"data-sidebar-collapsed": sidebarCollapsed || void 0,
|
|
281
|
+
"data-rightbar-collapsed": cols.rightbar === 0 || void 0,
|
|
282
|
+
"data-rightbar-fullscreen": layoutInfo.rightbarFullscreen || void 0,
|
|
283
|
+
"data-rightbar-instant": layoutInfo.rightbarInstant || void 0,
|
|
284
|
+
"data-dragging": dragging || void 0,
|
|
285
|
+
"data-animating": animating > 0 || void 0,
|
|
286
|
+
children: [
|
|
287
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
288
|
+
DocumentTitle,
|
|
289
|
+
{
|
|
290
|
+
productTitle,
|
|
291
|
+
useSessions,
|
|
292
|
+
usePanelInfo
|
|
293
|
+
}
|
|
294
|
+
),
|
|
295
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: AppFrame_default.sidebarCol, children: sidebar }),
|
|
296
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
297
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(CenterColumn, { covered: layoutInfo.rightbarFullscreen, children: main }),
|
|
298
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(RightbarColumn, { children: renderSlot("rightbar", { width: normal.rightbar, viewportWidth: viewport, canShow: normal.rightbar > 0 }) })
|
|
299
|
+
] }),
|
|
300
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: AppFrame_default.overlayLayer, "data-shell-overlay": true, children: overlays }),
|
|
301
|
+
leadingMounted && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: AppFrame_default.leadingSeat, "data-shell-leading": true, children: leading }),
|
|
302
|
+
!sidebarCollapsed && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DragHandle, { side: "sidebar", left: cols.sidebar, onStart: onSidebarStart, onDrag: onSidebarDrag, onEnd: onDragEnd }),
|
|
303
|
+
layoutInfo.rightbarShown && !layoutInfo.rightbarFullscreen && normal.rightbar > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DragHandle, { side: "rightbar", left: viewport - normal.rightbar, onStart: onRightbarStart, onDrag: onRightbarDrag, onEnd: onDragEnd })
|
|
304
|
+
]
|
|
305
|
+
}
|
|
306
|
+
);
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
// .host-source/packages/client/ui-layout/src/client/stores.ts
|
|
310
|
+
var import_dsh_client_store = require("@deepseek-ai/dsh-client-store");
|
|
311
|
+
function createLayoutStore() {
|
|
312
|
+
const handle = (0, import_dsh_client_store.defineStore)({
|
|
313
|
+
init: () => ({
|
|
314
|
+
panelInfo: { activePanelId: null },
|
|
315
|
+
layoutInfo: {
|
|
316
|
+
sidebar: SIDEBAR_DEFAULT,
|
|
317
|
+
viewportWidth: window.innerWidth,
|
|
318
|
+
narrowExpanded: false,
|
|
319
|
+
rightbar: null,
|
|
320
|
+
rightbarShown: false,
|
|
321
|
+
rightbarTrack: false,
|
|
322
|
+
rightbarFullscreen: false,
|
|
323
|
+
rightbarInstant: false
|
|
324
|
+
}
|
|
325
|
+
}),
|
|
326
|
+
actions: {
|
|
327
|
+
selectPanel: (d, panelId) => {
|
|
328
|
+
d.panelInfo.activePanelId = panelId;
|
|
329
|
+
},
|
|
330
|
+
retainMainPanels: (d, panelIds) => {
|
|
331
|
+
if (d.panelInfo.activePanelId !== null && !panelIds.includes(d.panelInfo.activePanelId)) {
|
|
332
|
+
d.panelInfo.activePanelId = null;
|
|
333
|
+
}
|
|
334
|
+
},
|
|
335
|
+
setSidebar: (d, px) => {
|
|
336
|
+
d.layoutInfo.rightbarInstant = false;
|
|
337
|
+
d.layoutInfo.sidebar = clampWidth(px, SIDEBAR_MIN, SIDEBAR_MAX);
|
|
338
|
+
},
|
|
339
|
+
// Narrow toggles flip only the override: the width preference survives
|
|
340
|
+
// untouched, so re-widening restores the pre-squeeze layout.
|
|
341
|
+
toggleSidebar: (d) => {
|
|
342
|
+
d.layoutInfo.rightbarInstant = false;
|
|
343
|
+
if (d.layoutInfo.viewportWidth < SIDEBAR_AUTO_COLLAPSE) d.layoutInfo.narrowExpanded = !d.layoutInfo.narrowExpanded;
|
|
344
|
+
else d.layoutInfo.sidebar = d.layoutInfo.sidebar === 0 ? SIDEBAR_DEFAULT : 0;
|
|
345
|
+
},
|
|
346
|
+
// Crossing the breakpoint in either direction drops the override: the
|
|
347
|
+
// narrow default is auto-collapsed, the wide state is the preference.
|
|
348
|
+
setViewportWidth: (d, width) => {
|
|
349
|
+
if (d.layoutInfo.viewportWidth === width) return;
|
|
350
|
+
d.layoutInfo.rightbarInstant = false;
|
|
351
|
+
if (d.layoutInfo.viewportWidth < SIDEBAR_AUTO_COLLAPSE !== width < SIDEBAR_AUTO_COLLAPSE) {
|
|
352
|
+
d.layoutInfo.narrowExpanded = false;
|
|
353
|
+
}
|
|
354
|
+
d.layoutInfo.viewportWidth = width;
|
|
355
|
+
},
|
|
356
|
+
setRightbar: (d, px) => {
|
|
357
|
+
d.layoutInfo.rightbarInstant = false;
|
|
358
|
+
d.layoutInfo.rightbar = clampWidth(px, RIGHTBAR_MIN, Math.max(RIGHTBAR_MIN, d.layoutInfo.viewportWidth * RIGHTBAR_MAX_RATIO));
|
|
359
|
+
},
|
|
360
|
+
openRightbar: (d, track, fullscreen) => {
|
|
361
|
+
if (!d.layoutInfo.rightbarShown || d.layoutInfo.rightbarTrack !== track || d.layoutInfo.rightbarFullscreen !== fullscreen) {
|
|
362
|
+
d.layoutInfo.rightbarInstant = d.layoutInfo.rightbarFullscreen && !fullscreen;
|
|
363
|
+
}
|
|
364
|
+
if (!d.layoutInfo.rightbarShown && d.layoutInfo.viewportWidth < SIDEBAR_AUTO_COLLAPSE) d.layoutInfo.narrowExpanded = false;
|
|
365
|
+
d.layoutInfo.rightbar ??= Math.max(RIGHTBAR_MIN, Math.round(d.layoutInfo.viewportWidth * RIGHTBAR_DEFAULT_RATIO));
|
|
366
|
+
d.layoutInfo.rightbarShown = true;
|
|
367
|
+
d.layoutInfo.rightbarTrack = track;
|
|
368
|
+
d.layoutInfo.rightbarFullscreen = fullscreen;
|
|
369
|
+
},
|
|
370
|
+
closeRightbar: (d) => {
|
|
371
|
+
if (d.layoutInfo.rightbarShown) d.layoutInfo.rightbarInstant = d.layoutInfo.rightbarFullscreen;
|
|
372
|
+
d.layoutInfo.rightbarShown = false;
|
|
373
|
+
d.layoutInfo.rightbarTrack = false;
|
|
374
|
+
d.layoutInfo.rightbarFullscreen = false;
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
});
|
|
378
|
+
return handle;
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
// .host-source/packages/client/ui-layout/src/client/service.ts
|
|
382
|
+
var LayoutController = class {
|
|
383
|
+
/**
|
|
384
|
+
* @param panels - actions of the instance shared with the root entry.
|
|
385
|
+
* @param hasMainPanel - checks the live main-slot registry for a panel id.
|
|
386
|
+
* @param panelInfo - root store's shared central-panel selection source.
|
|
387
|
+
*/
|
|
388
|
+
constructor(panels, hasMainPanel, panelInfo) {
|
|
389
|
+
this.panels = panels;
|
|
390
|
+
this.hasMainPanel = hasMainPanel;
|
|
391
|
+
this.panelInfo = panelInfo;
|
|
392
|
+
}
|
|
393
|
+
panels;
|
|
394
|
+
hasMainPanel;
|
|
395
|
+
panelInfo;
|
|
396
|
+
navigation = new AbortController();
|
|
397
|
+
/** Select a global panel or return to the Conversation. */
|
|
398
|
+
selectPanel(panelId) {
|
|
399
|
+
if (panelId !== null && !this.hasMainPanel(panelId)) {
|
|
400
|
+
throw new Error(`layout.selectPanel: main panel "${panelId}" is not registered`);
|
|
401
|
+
}
|
|
402
|
+
this.navigation.abort();
|
|
403
|
+
this.panels.selectPanel(panelId);
|
|
404
|
+
}
|
|
405
|
+
/** @returns the new pending navigation's cancellation signal. */
|
|
406
|
+
beginNavigation() {
|
|
407
|
+
this.navigation.abort();
|
|
408
|
+
this.navigation = new AbortController();
|
|
409
|
+
return this.navigation.signal;
|
|
410
|
+
}
|
|
411
|
+
/** Invalidate pending navigations when the layout owner is unloaded. */
|
|
412
|
+
dispose() {
|
|
413
|
+
this.navigation.abort();
|
|
414
|
+
}
|
|
415
|
+
/** Toggle the sidebar panel (closed ⟷ contract default width). */
|
|
416
|
+
toggleSidebar() {
|
|
417
|
+
this.panels.toggleSidebar();
|
|
418
|
+
}
|
|
419
|
+
/** Report the right panel's track and fullscreen presentation. */
|
|
420
|
+
openRightbar(track, fullscreen) {
|
|
421
|
+
this.panels.openRightbar(track, fullscreen);
|
|
422
|
+
}
|
|
423
|
+
/** Report the right panel as hidden: no track, no handle. */
|
|
424
|
+
closeRightbar() {
|
|
425
|
+
this.panels.closeRightbar();
|
|
426
|
+
}
|
|
427
|
+
};
|
|
428
|
+
|
|
429
|
+
// .host-source/packages/client/ui-layout/src/client/shortcut-locales.ts
|
|
430
|
+
var zh = { toggle: "\u5C55\u5F00\uFF0F\u6536\u8D77\u5DE6\u4FA7\u680F" };
|
|
431
|
+
var en = { toggle: "Toggle left sidebar" };
|
|
432
|
+
|
|
433
|
+
// .host-source/packages/client/ui-layout/src/client/theme-presenter.ts
|
|
434
|
+
var DARK_ATTRIBUTE = "data-ds-dark-theme";
|
|
435
|
+
var THEME_SOURCE_ATTRIBUTE = "data-ds-theme-source";
|
|
436
|
+
var CONTENT_FONT_SIZE_VARIABLE = "--dsh-content-font-size";
|
|
437
|
+
var ThemePresenter = class {
|
|
438
|
+
/** Token names this presenter wrote in the last apply (its retraction set). */
|
|
439
|
+
appliedTokens = [];
|
|
440
|
+
/** The single metadata node this presenter inserts and removes. */
|
|
441
|
+
themeColorMeta;
|
|
442
|
+
/** Create the presenter-owned metadata node before the first snapshot arrives. */
|
|
443
|
+
constructor() {
|
|
444
|
+
this.themeColorMeta = document.createElement("meta");
|
|
445
|
+
this.themeColorMeta.name = "theme-color";
|
|
446
|
+
}
|
|
447
|
+
/**
|
|
448
|
+
* Project a snapshot onto the document: set root `color-scheme` and the body
|
|
449
|
+
* palette attribute from `active.colorScheme` (never the id — `system` is
|
|
450
|
+
* resolved upstream), publish the content font-size axis, then replace the
|
|
451
|
+
* previously applied token variables with `active.tokens`. Browser
|
|
452
|
+
* theme-color metadata follows the computed body background after those
|
|
453
|
+
* writes, so the rendered palette remains the color authority.
|
|
454
|
+
* @param snapshot - resolved theme snapshot from ctx.theme.
|
|
455
|
+
*/
|
|
456
|
+
apply(snapshot) {
|
|
457
|
+
const scheme = snapshot.active.colorScheme;
|
|
458
|
+
document.documentElement.style.colorScheme = scheme;
|
|
459
|
+
document.documentElement.setAttribute(
|
|
460
|
+
THEME_SOURCE_ATTRIBUTE,
|
|
461
|
+
snapshot.preference === "system" ? "system" : scheme
|
|
462
|
+
);
|
|
463
|
+
const body = document.body;
|
|
464
|
+
if (scheme === "dark") body.setAttribute(DARK_ATTRIBUTE, "");
|
|
465
|
+
else body.removeAttribute(DARK_ATTRIBUTE);
|
|
466
|
+
body.style.setProperty(CONTENT_FONT_SIZE_VARIABLE, `${snapshot.fontSize}px`);
|
|
467
|
+
for (const name of this.appliedTokens) body.style.removeProperty(name);
|
|
468
|
+
this.appliedTokens = [];
|
|
469
|
+
for (const [name, value] of Object.entries(snapshot.active.tokens)) {
|
|
470
|
+
body.style.setProperty(name, value);
|
|
471
|
+
this.appliedTokens.push(name);
|
|
472
|
+
}
|
|
473
|
+
this.themeColorMeta.content = getComputedStyle(body).backgroundColor;
|
|
474
|
+
if (!this.themeColorMeta.isConnected) document.head.append(this.themeColorMeta);
|
|
475
|
+
}
|
|
476
|
+
/**
|
|
477
|
+
* Retract root color-scheme, the theme-source attribute, the palette
|
|
478
|
+
* attribute, token variables, the font-size axis, and the owned metadata node.
|
|
479
|
+
*/
|
|
480
|
+
dispose() {
|
|
481
|
+
document.documentElement.style.removeProperty("color-scheme");
|
|
482
|
+
document.documentElement.removeAttribute(THEME_SOURCE_ATTRIBUTE);
|
|
483
|
+
const body = document.body;
|
|
484
|
+
body.removeAttribute(DARK_ATTRIBUTE);
|
|
485
|
+
body.style.removeProperty(CONTENT_FONT_SIZE_VARIABLE);
|
|
486
|
+
for (const name of this.appliedTokens) body.style.removeProperty(name);
|
|
487
|
+
this.appliedTokens = [];
|
|
488
|
+
this.themeColorMeta.remove();
|
|
489
|
+
}
|
|
490
|
+
};
|
|
491
|
+
|
|
492
|
+
// .host-source/packages/client/ui-layout/src/client/index.ts
|
|
493
|
+
var inject = ["slots", "theme", "locale", "shortcuts"];
|
|
494
|
+
function apply(ctx) {
|
|
495
|
+
ctx.effect(cssDispose);
|
|
496
|
+
ctx.effect(() => ctx.locale.register("shortcuts.layout", { zh, en }), "layout: command labels");
|
|
497
|
+
const t = ctx.locale.bind("shortcuts.layout");
|
|
498
|
+
ctx.effect(() => {
|
|
499
|
+
const handle = createLayoutStore();
|
|
500
|
+
const instance = handle.create();
|
|
501
|
+
const store = { ...handle, create: () => instance };
|
|
502
|
+
const retainMainPanels = () => {
|
|
503
|
+
instance.actions.retainMainPanels(ctx.slots.entries("main").flatMap((entry) => entry.options.key === void 0 ? [] : [entry.options.key]));
|
|
504
|
+
};
|
|
505
|
+
const panelInfo = {
|
|
506
|
+
getSnapshot: () => instance.getSnapshot().panelInfo,
|
|
507
|
+
subscribe: (listener) => instance.subscribe(listener)
|
|
508
|
+
};
|
|
509
|
+
const layout = new LayoutController(instance.actions, (id) => ctx.slots.entries("main").some((entry) => entry.options.key === id), panelInfo);
|
|
510
|
+
const disposePanelInfo = ctx.slots.provideRoot({ hooks: { panelInfo: layout.panelInfo } });
|
|
511
|
+
const disposeService = ctx.reflect.provide("layout", layout);
|
|
512
|
+
const disposeRegistration = ctx.slots.register({
|
|
513
|
+
name: "root",
|
|
514
|
+
locale: "common",
|
|
515
|
+
children: {
|
|
516
|
+
"sidebar": { kind: "single", scope: "root" },
|
|
517
|
+
"main": { kind: "keyed", scope: "root" },
|
|
518
|
+
"rightbar": { kind: "single", scope: "root" },
|
|
519
|
+
"shell.overlay": { kind: "list", scope: "root" },
|
|
520
|
+
"shell.leading": { kind: "single", scope: "root" }
|
|
521
|
+
},
|
|
522
|
+
store
|
|
523
|
+
}, AppFrame);
|
|
524
|
+
const disposeShortcut = ctx.shortcuts.register({
|
|
525
|
+
id: "sidebar.left.toggle",
|
|
526
|
+
label: () => t("toggle"),
|
|
527
|
+
aliases: ["sidebar", "toggle left sidebar"],
|
|
528
|
+
defaults: {
|
|
529
|
+
"desktop:macos": { code: "KeyB", modifiers: ["primary"] },
|
|
530
|
+
"desktop:windows": { code: "KeyB", modifiers: ["primary"] },
|
|
531
|
+
"desktop:linux": { code: "KeyB", modifiers: ["primary"] },
|
|
532
|
+
"web:macos": { code: "KeyB", modifiers: ["primary", "alt"] },
|
|
533
|
+
"web:windows": { code: "KeyB", modifiers: ["primary", "alt"] }
|
|
534
|
+
},
|
|
535
|
+
regions: ["page", "editable"],
|
|
536
|
+
modals: [],
|
|
537
|
+
resolve: () => ({ status: "handled", run: () => {
|
|
538
|
+
layout.toggleSidebar();
|
|
539
|
+
} })
|
|
540
|
+
});
|
|
541
|
+
const disposePanels = ctx.slots.subscribe("main", retainMainPanels);
|
|
542
|
+
retainMainPanels();
|
|
543
|
+
return () => {
|
|
544
|
+
disposeShortcut();
|
|
545
|
+
layout.dispose();
|
|
546
|
+
disposePanels();
|
|
547
|
+
disposeRegistration();
|
|
548
|
+
disposePanelInfo();
|
|
549
|
+
void disposeService();
|
|
550
|
+
};
|
|
551
|
+
}, "ui-layout: service + root registration");
|
|
552
|
+
ctx.effect(() => {
|
|
553
|
+
const presenter = new ThemePresenter();
|
|
554
|
+
presenter.apply(ctx.theme.getTheme());
|
|
555
|
+
const off = ctx.on("theme/change", (snapshot) => {
|
|
556
|
+
presenter.apply(snapshot);
|
|
557
|
+
});
|
|
558
|
+
return () => {
|
|
559
|
+
off();
|
|
560
|
+
presenter.dispose();
|
|
561
|
+
};
|
|
562
|
+
}, "ui-layout: theme presenter");
|
|
563
|
+
}
|
|
564
|
+
return module.exports; } });
|
|
565
|
+
//# sourceMappingURL=client.js.map
|