@dungsil/dsh-plugin-ui-model-picker 0.2.1 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/client.js +86 -82
- package/package.json +4 -5
package/dist/client.js
CHANGED
|
@@ -4,29 +4,79 @@ let react = require("react");
|
|
|
4
4
|
let react_dom = require("react-dom");
|
|
5
5
|
let _deepseek_ai_dsh_client_ui_primitives = require("@deepseek-ai/dsh-client-ui-primitives");
|
|
6
6
|
let react_jsx_runtime = require("react/jsx-runtime");
|
|
7
|
+
// ../../tools/ui/src/client.ts
|
|
8
|
+
function useLocaleSnapshot(locale) {
|
|
9
|
+
const subscribe = (0, react.useCallback)((listener) => locale.subscribe(listener), [locale]);
|
|
10
|
+
const getSnapshot = (0, react.useCallback)(() => locale.getSnapshot(), [locale]);
|
|
11
|
+
return (0, react.useSyncExternalStore)(subscribe, getSnapshot);
|
|
12
|
+
}
|
|
13
|
+
/** Each effect owns its sheet, even when another plugin installs the same defaults. */
|
|
14
|
+
function installStyles(css) {
|
|
15
|
+
const style = document.createElement("style");
|
|
16
|
+
style.textContent = css;
|
|
17
|
+
document.head.append(style);
|
|
18
|
+
return () => style.remove();
|
|
19
|
+
}
|
|
20
|
+
// ../../tools/ui/src/icons/rotate-ccw.svg
|
|
21
|
+
var rotate_ccw_default = "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\n <path d=\"M5 7a9 9 0 1 1-1 9M5 3v4h4\"/>\n</svg>\n";
|
|
22
|
+
// ../../tools/ui/src/icons.ts
|
|
23
|
+
function IconResetOutlineRegular() {
|
|
24
|
+
return (0, react.createElement)("span", {
|
|
25
|
+
style: { display: "inline-flex" },
|
|
26
|
+
"aria-hidden": "true",
|
|
27
|
+
dangerouslySetInnerHTML: { __html: rotate_ccw_default }
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
// ../../tools/ui/src/composer.tsx
|
|
31
|
+
const composerStyles = `
|
|
32
|
+
:where(.dsh-plugin-composer-trigger) { display: flex; align-items: center; gap: 4px; min-width: 0; height: 28px; padding: 0 4px 0 8px; border: 0; border-radius: var(--dsw-radius-sm); background: transparent; color: var(--dsw-alias-label-secondary); font: inherit; font-size: 13px; line-height: 20px; cursor: pointer; }
|
|
33
|
+
:where(.dsh-plugin-composer-trigger):disabled { color: var(--dsw-alias-label-dimmed); cursor: default; }
|
|
34
|
+
.dsh-plugin-composer-icon, .dsh-plugin-composer-chevron { display: inline-flex; flex: none; }
|
|
35
|
+
.dsh-plugin-composer-label, .dsh-plugin-composer-detail { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
36
|
+
.dsh-plugin-composer-chevron, .dsh-plugin-composer-detail { color: var(--dsw-alias-label-caption); }
|
|
37
|
+
.dsh-plugin-composer-trigger[aria-expanded=true] .dsh-plugin-composer-chevron { transform: rotate(180deg); }
|
|
38
|
+
`;
|
|
39
|
+
const ComposerTrigger = (0, react.forwardRef)(function ComposerTrigger({ className = "", icon, label, detail, ...props }, ref) {
|
|
40
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
41
|
+
...props,
|
|
42
|
+
ref,
|
|
43
|
+
type: "button",
|
|
44
|
+
className: `dsh-plugin-composer-trigger ${className}`,
|
|
45
|
+
children: [
|
|
46
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
47
|
+
className: "dsh-plugin-composer-icon",
|
|
48
|
+
"aria-hidden": "true",
|
|
49
|
+
children: icon
|
|
50
|
+
}),
|
|
51
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
52
|
+
className: "dsh-plugin-composer-label",
|
|
53
|
+
children: label
|
|
54
|
+
}),
|
|
55
|
+
detail && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
56
|
+
className: "dsh-plugin-composer-detail",
|
|
57
|
+
children: detail
|
|
58
|
+
}),
|
|
59
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
60
|
+
className: "dsh-plugin-composer-chevron",
|
|
61
|
+
"aria-hidden": "true",
|
|
62
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronDownOutlineRegular, {})
|
|
63
|
+
})
|
|
64
|
+
]
|
|
65
|
+
});
|
|
66
|
+
});
|
|
7
67
|
// src/styles.ts
|
|
8
|
-
const styles =
|
|
68
|
+
const styles = `${composerStyles}
|
|
9
69
|
.dsh-codex-picker { display: flex; align-items: center; min-width: 0; }
|
|
10
|
-
.dsh-codex-trigger {
|
|
70
|
+
.dsh-codex-trigger { max-width: min(360px, 45cqw); font-weight: 400; outline: none; }
|
|
11
71
|
.dsh-codex-trigger:hover:not(:disabled) { background: var(--dsw-alias-interactive-bg-hover); }
|
|
12
72
|
.dsh-codex-trigger:focus-visible:not([data-dsh-automatic-focus]) { box-shadow: 0 0 0 2px var(--dsw-focus-ring-color, var(--dsw-alias-state-business-primary)); }
|
|
13
|
-
.dsh-codex-trigger
|
|
14
|
-
.dsh-codex-trigger
|
|
15
|
-
.dsh-codex-
|
|
16
|
-
.dsh-codex-trigger
|
|
17
|
-
.dsh-codex-name, .dsh-codex-effort { display: var(--dsh-composer-model-text-display, block); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
18
|
-
.dsh-codex-effort { color: var(--dsw-alias-label-caption); flex-shrink: 1000; }
|
|
73
|
+
.dsh-codex-trigger .dsh-plugin-composer-icon { display: var(--dsh-composer-model-icon-display, none); }
|
|
74
|
+
.dsh-codex-trigger .dsh-plugin-composer-chevron { transition: transform .12s; }
|
|
75
|
+
.dsh-codex-trigger .dsh-plugin-composer-label, .dsh-codex-trigger .dsh-plugin-composer-detail { display: var(--dsh-composer-model-text-display, block); }
|
|
76
|
+
.dsh-codex-trigger .dsh-plugin-composer-detail { flex-shrink: 1000; }
|
|
19
77
|
.dsh-codex-popover { position: fixed; z-index: 1100; display: flex; flex-direction: column; inset: auto; margin: 0; box-sizing: border-box; width: 256px; max-width: calc(100vw - 32px); max-height: min(360px, calc(100dvh - 96px)); overflow: hidden; padding: 4px; border: 0; --dsw-elevation-stroke-color: var(--dsw-alias-border-l1); --dsh-scrollbar-thumb: var(--dsw-alias-scrollbar-bg-l2); --dsh-scrollbar-thumb-hover: var(--dsw-alias-scrollbar-hover-l2); background: transparent; color: var(--dsw-alias-label-primary); box-shadow: var(--dsw-elevation-prominent); font: 13px/20px var(--dsw-font-family, system-ui); }
|
|
20
|
-
/* rc.5 has no MenuSurface phase API. Match the newer shared menu fades without
|
|
21
|
-
animating the container: container opacity would change its backdrop blur.
|
|
22
|
-
Old hosts forward phase to the div; newer hosts consume it for their own CSS. */
|
|
23
|
-
.dsh-codex-popover[phase=enter] > * { animation: dsh-codex-menu-in 40ms ease-out; }
|
|
24
|
-
.dsh-codex-popover[phase=dismiss] > * { animation: dsh-codex-menu-out 80ms ease-in both; }
|
|
25
|
-
@keyframes dsh-codex-menu-in { from { opacity: 0; } to { opacity: 1; } }
|
|
26
|
-
@keyframes dsh-codex-menu-out { from { opacity: 1; } to { opacity: 0; } }
|
|
27
78
|
@media (prefers-reduced-motion: reduce) {
|
|
28
|
-
.dsh-codex-
|
|
29
|
-
.dsh-codex-chevron { transition: none; }
|
|
79
|
+
.dsh-codex-trigger .dsh-plugin-composer-chevron { transition: none; }
|
|
30
80
|
}
|
|
31
81
|
.dsh-codex-popover > :not([role=radiogroup]) { flex-shrink: 0; }
|
|
32
82
|
.dsh-codex-popover [role=radiogroup] { min-height: 0; overflow-y: auto; }
|
|
@@ -38,6 +88,7 @@ const styles = `
|
|
|
38
88
|
.dsh-codex-model > span { display: block; color: var(--dsw-alias-label-tertiary, #777); font-size: 12px; line-height: 17px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
39
89
|
.dsh-codex-model:hover, .dsh-codex-reset:hover, .dsh-codex-back:hover { background: var(--dsw-alias-interactive-bg-hover, #f2f2f2); }
|
|
40
90
|
.dsh-codex-reset { display: grid; place-items: center; width: 24px; height: 24px; color: var(--dsw-alias-label-tertiary, #999); }
|
|
91
|
+
.dsh-codex-reset svg { width: 16px; height: 16px; }
|
|
41
92
|
.dsh-codex-back { padding: 4px 8px; color: var(--dsw-alias-label-tertiary, #777); }
|
|
42
93
|
.dsh-codex-popover h2, .dsh-codex-provider { margin: 0; padding: 6px 10px; font-size: 12px; font-weight: 400; color: var(--dsw-alias-label-tertiary, #777); }
|
|
43
94
|
.dsh-codex-provider { font-size: 11px; padding-top: 10px; }
|
|
@@ -117,11 +168,12 @@ const copy = {
|
|
|
117
168
|
};
|
|
118
169
|
function apply(ctx) {
|
|
119
170
|
function Picker({ locked, directory }) {
|
|
120
|
-
const
|
|
121
|
-
const
|
|
171
|
+
const subscribe = (0, react.useCallback)((listener) => directory.store.subscribe(listener), [directory]);
|
|
172
|
+
const getSnapshot = (0, react.useCallback)(() => directory.store.getSnapshot(), [directory]);
|
|
173
|
+
const state = (0, react.useSyncExternalStore)(subscribe, getSnapshot);
|
|
174
|
+
const { active: locale } = useLocaleSnapshot(ctx.locale);
|
|
122
175
|
const text = copy[locale.startsWith("ko") ? "ko" : locale.startsWith("zh") ? "zh" : "en"];
|
|
123
176
|
const [panel, setPanel] = (0, react.useState)(null);
|
|
124
|
-
const [exiting, setExiting] = (0, react.useState)(false);
|
|
125
177
|
const [draft, setDraft] = (0, react.useState)(0);
|
|
126
178
|
const [failed, setFailed] = (0, react.useState)(false);
|
|
127
179
|
const trigger = (0, react.useRef)(null);
|
|
@@ -150,27 +202,10 @@ function apply(ctx) {
|
|
|
150
202
|
};
|
|
151
203
|
}, [directory]);
|
|
152
204
|
const close = () => {
|
|
153
|
-
|
|
205
|
+
setPanel(null);
|
|
154
206
|
if (trigger.current) (0, _deepseek_ai_dsh_client_ui_primitives.focusWithoutRing)(trigger.current);
|
|
155
207
|
};
|
|
156
|
-
(0, _deepseek_ai_dsh_client_ui_primitives.useDismissOnOutsidePointer)(anchor, panel !== null
|
|
157
|
-
(0, react.useLayoutEffect)(() => {
|
|
158
|
-
if (!exiting || !popup.current) return;
|
|
159
|
-
const element = popup.current;
|
|
160
|
-
element.inert = true;
|
|
161
|
-
let cancelled = false;
|
|
162
|
-
const animations = element.getAnimations({ subtree: true }).filter((animation) => {
|
|
163
|
-
const name = animation.animationName;
|
|
164
|
-
return name?.includes("dsh-context-menu-out") || name === "dsh-codex-menu-out";
|
|
165
|
-
});
|
|
166
|
-
Promise.all(animations.map((animation) => animation.finished.catch(() => {}))).then(() => {
|
|
167
|
-
if (!cancelled) setPanel(null);
|
|
168
|
-
});
|
|
169
|
-
return () => {
|
|
170
|
-
cancelled = true;
|
|
171
|
-
element.inert = false;
|
|
172
|
-
};
|
|
173
|
-
}, [exiting]);
|
|
208
|
+
(0, _deepseek_ai_dsh_client_ui_primitives.useDismissOnOutsidePointer)(anchor, panel !== null, () => setPanel(null), popup);
|
|
174
209
|
(0, react.useLayoutEffect)(() => {
|
|
175
210
|
if (!panel || !popup.current || !anchor.current) return;
|
|
176
211
|
const element = popup.current;
|
|
@@ -216,10 +251,10 @@ function apply(ctx) {
|
|
|
216
251
|
};
|
|
217
252
|
}, [panel]);
|
|
218
253
|
(0, react.useEffect)(() => {
|
|
219
|
-
if (locked)
|
|
254
|
+
if (locked) setPanel(null);
|
|
220
255
|
}, [locked]);
|
|
221
256
|
(0, react.useEffect)(() => {
|
|
222
|
-
|
|
257
|
+
setPanel(null);
|
|
223
258
|
}, [
|
|
224
259
|
current?.provider,
|
|
225
260
|
current?.model,
|
|
@@ -242,11 +277,10 @@ function apply(ctx) {
|
|
|
242
277
|
};
|
|
243
278
|
const show = (button) => {
|
|
244
279
|
trigger.current = button;
|
|
245
|
-
if (panel
|
|
280
|
+
if (panel) {
|
|
246
281
|
close();
|
|
247
282
|
return;
|
|
248
283
|
}
|
|
249
|
-
setExiting(false);
|
|
250
284
|
setDraft(Math.max(0, effortIndex));
|
|
251
285
|
setFailed(false);
|
|
252
286
|
setPanel("effort");
|
|
@@ -265,39 +299,23 @@ function apply(ctx) {
|
|
|
265
299
|
className: "dsh-codex-picker",
|
|
266
300
|
ref: anchor,
|
|
267
301
|
"aria-busy": busy,
|
|
268
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.
|
|
269
|
-
type: "button",
|
|
302
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ComposerTrigger, {
|
|
270
303
|
className: "dsh-codex-trigger",
|
|
304
|
+
icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconDataOutlineRegular, { size: 16 }),
|
|
305
|
+
label: model?.name ?? current?.model ?? text.model,
|
|
306
|
+
detail: effortLabel,
|
|
271
307
|
disabled,
|
|
272
308
|
"aria-label": `${text.choose}: ${model?.name ?? current?.model ?? text.model}${effortLabel ? `, ${effortLabel}` : ""}`,
|
|
273
309
|
title: `${model?.name ?? current?.model ?? text.model}${effortLabel ? ` ${effortLabel}` : ""}`,
|
|
274
310
|
"aria-haspopup": "dialog",
|
|
275
|
-
"aria-expanded": panel !== null
|
|
276
|
-
"aria-controls": panel
|
|
277
|
-
onClick: (event) => show(event.currentTarget)
|
|
278
|
-
children: [
|
|
279
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconDataOutlineRegular, {
|
|
280
|
-
className: "dsh-codex-trigger-icon",
|
|
281
|
-
size: 16
|
|
282
|
-
}),
|
|
283
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
284
|
-
className: "dsh-codex-name",
|
|
285
|
-
children: model?.name ?? current?.model ?? text.model
|
|
286
|
-
}),
|
|
287
|
-
effortLabel && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
288
|
-
className: "dsh-codex-effort",
|
|
289
|
-
children: effortLabel
|
|
290
|
-
}),
|
|
291
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronDownOutlineRegular, { className: "dsh-codex-chevron" })
|
|
292
|
-
]
|
|
311
|
+
"aria-expanded": panel !== null,
|
|
312
|
+
"aria-controls": panel ? id : void 0,
|
|
313
|
+
onClick: (event) => show(event.currentTarget)
|
|
293
314
|
})
|
|
294
315
|
}), panel && (0, react_dom.createPortal)(/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_deepseek_ai_dsh_client_ui_primitives.MenuSurface, {
|
|
295
316
|
id,
|
|
296
317
|
ref: popup,
|
|
297
318
|
role: "dialog",
|
|
298
|
-
"aria-hidden": exiting || void 0,
|
|
299
|
-
"data-picker-phase": exiting ? "dismiss" : "enter",
|
|
300
|
-
phase: exiting ? "dismiss" : "enter",
|
|
301
319
|
"aria-label": panel === "model" ? text.model : text.effort,
|
|
302
320
|
className: "dsh-codex-popover",
|
|
303
321
|
children: [
|
|
@@ -335,16 +353,7 @@ function apply(ctx) {
|
|
|
335
353
|
model: current.model
|
|
336
354
|
});
|
|
337
355
|
},
|
|
338
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(
|
|
339
|
-
width: "16",
|
|
340
|
-
height: "16",
|
|
341
|
-
viewBox: "0 0 16 16",
|
|
342
|
-
fill: "none",
|
|
343
|
-
stroke: "currentColor",
|
|
344
|
-
strokeWidth: "1.2",
|
|
345
|
-
"aria-hidden": "true",
|
|
346
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", { d: "M3 4a5.5 5.5 0 1 1-1 6M3 1v3h3" })
|
|
347
|
-
})
|
|
356
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconResetOutlineRegular, {})
|
|
348
357
|
})]
|
|
349
358
|
}),
|
|
350
359
|
state.status === "loading" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
@@ -462,12 +471,7 @@ function apply(ctx) {
|
|
|
462
471
|
locked: props.locked,
|
|
463
472
|
directory: ctx.modelDirectories.directoryFor(props.sessionId)
|
|
464
473
|
}, props.sessionId) : null));
|
|
465
|
-
ctx.effect(() =>
|
|
466
|
-
const style = document.createElement("style");
|
|
467
|
-
style.textContent = styles;
|
|
468
|
-
document.head.append(style);
|
|
469
|
-
return () => style.remove();
|
|
470
|
-
}, "ui-model-picker: styles");
|
|
474
|
+
ctx.effect(() => installStyles(styles), "ui-model-picker: styles");
|
|
471
475
|
}
|
|
472
476
|
exports.apply = apply;
|
|
473
477
|
exports.inject = inject;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dungsil/dsh-plugin-ui-model-picker",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.2",
|
|
4
4
|
"description": "Model and reasoning effort picker for the DeepSeek Harness composer.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -32,14 +32,14 @@
|
|
|
32
32
|
"@deepseek-ai/dsh-client-store": "0.2.1-rc.5",
|
|
33
33
|
"@deepseek-ai/dsh-client-ui-conversation": "0.2.1-rc.5",
|
|
34
34
|
"@deepseek-ai/dsh-client-ui-model-selection": "0.2.1-rc.5",
|
|
35
|
-
"@deepseek-ai/dsh-client-ui-primitives": "0.2.1-rc.5",
|
|
36
35
|
"@deepseek-ai/dsh-client-ui-renderer": "0.2.1-rc.5",
|
|
37
36
|
"@deepseek-ai/dsh-client-ui-session": "0.2.1-rc.5",
|
|
38
37
|
"@deepseek-ai/dsh-client-ui-slots": "0.2.1-rc.5",
|
|
39
38
|
"@dungsil/dsh-tsconfig": "0.0.0",
|
|
39
|
+
"@dungsil/dsh-tsdown": "0.0.0",
|
|
40
|
+
"@dungsil/dsh-ui": "0.0.0",
|
|
40
41
|
"@types/react": "18.3.31",
|
|
41
42
|
"@types/react-dom": "18.3.7",
|
|
42
|
-
"happy-dom": "21.0.4",
|
|
43
43
|
"react": "18.3.1",
|
|
44
44
|
"react-dom": "18.3.1",
|
|
45
45
|
"tsdown": "0.23.4"
|
|
@@ -88,7 +88,6 @@
|
|
|
88
88
|
},
|
|
89
89
|
"scripts": {
|
|
90
90
|
"build": "tsdown",
|
|
91
|
-
"typecheck": "tsc --noEmit"
|
|
92
|
-
"test": "node --test test/*.test.mjs"
|
|
91
|
+
"typecheck": "tsc --noEmit"
|
|
93
92
|
}
|
|
94
93
|
}
|