@klarkxy/dsh-model-hub 0.1.4 → 0.1.5

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 CHANGED
@@ -203,7 +203,14 @@ function groupModelMenuChoices(choices, query) {
203
203
  }
204
204
  //#endregion
205
205
  //#region ../dsh-model-route/src/catalog-ui.tsx
206
- /** Also accepts a mapped state from a caller that owns broader async orchestration. */
206
+ /**
207
+ * Also accepts a mapped state from a caller that owns broader async orchestration.
208
+ *
209
+ * The dsh-ui-* classes carry the styling and resolve through the consuming
210
+ * plugin's own officialUiCss scope (every consumer mounts its root class, so
211
+ * e.g. `.dsh-model-hub .dsh-ui-loading` paints this); dsh-model-catalog-status
212
+ * stays as a structural hook for tests and layout, never a colour source.
213
+ */
207
214
  function ModelCatalogStatus({ state, locale }) {
208
215
  const zh = locale?.toLowerCase().startsWith("zh") === true;
209
216
  const copy = zh ? {
@@ -219,15 +226,17 @@ function ModelCatalogStatus({ state, locale }) {
219
226
  };
220
227
  if (!state.loading && !state.error && state.failures.length === 0) return null;
221
228
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
222
- className: "dsh-model-catalog-status",
229
+ className: "dsh-model-catalog-status dsh-ui-stack",
223
230
  lang: zh ? "zh" : "en",
224
231
  children: [
225
232
  state.loading ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
226
233
  role: "status",
234
+ className: "dsh-ui-loading",
227
235
  children: copy.loading
228
236
  }) : null,
229
237
  state.error ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", {
230
238
  role: "alert",
239
+ className: "dsh-ui-error dsh-ui-wrap",
231
240
  children: [
232
241
  copy.error,
233
242
  ": ",
@@ -236,20 +245,27 @@ function ModelCatalogStatus({ state, locale }) {
236
245
  }) : null,
237
246
  state.failures.length > 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
238
247
  role: "status",
239
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", { children: copy.partial }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("ul", { children: state.failures.map((failure, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("li", { children: [
240
- failure.name || failure.id,
241
- ": ",
242
- failure.message
243
- ] }, `${failure.id}:${index}`)) })]
248
+ className: "dsh-ui-meta",
249
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", { children: copy.partial }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("ul", {
250
+ className: "dsh-ui-list",
251
+ children: state.failures.map((failure, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("li", { children: [
252
+ failure.name || failure.id,
253
+ ": ",
254
+ failure.message
255
+ ] }, `${failure.id}:${index}`))
256
+ })]
244
257
  }) : null,
245
- state.error || state.failures.length > 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
246
- type: "button",
247
- size: "sm",
248
- disabled: state.loading,
249
- onClick: () => {
250
- state.refresh();
251
- },
252
- children: copy.retry
258
+ state.error || state.failures.length > 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
259
+ className: "dsh-ui-actions",
260
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
261
+ type: "button",
262
+ size: "sm",
263
+ disabled: state.loading,
264
+ onClick: () => {
265
+ state.refresh();
266
+ },
267
+ children: copy.retry
268
+ })
253
269
  }) : null
254
270
  ]
255
271
  });
@@ -269,7 +285,8 @@ function ModelCatalogStatus({ state, locale }) {
269
285
  * Sticky group headings, subsequence ranking, highlight walking and focus
270
286
  * hand-back all match the host. SYNC POINT: when the host's ModelSelect or
271
287
  * ModelSelect.module.css changes, this copy must be re-transcribed; styles
272
- * below may only reference --dsw-* theme tokens, never literal colors.
288
+ * below may only reference allowlisted theme tokens (the --dsw-* set plus the
289
+ * host's --ds-* motion tokens), never literal colors.
273
290
  *
274
291
  * It statically imports the primitives, so only browser clients should load
275
292
  * this entry; host code and node tests use the core entry (`./index.ts`).
@@ -777,7 +794,8 @@ function ModelMenu(props) {
777
794
  * sticky group headings (MenuGroup's own CSS), and the l1-stroke prominent
778
795
  * elevation at portal z-index 1100. The trigger mirrors the composer's 28px
779
796
  * model pill, chevron rotating open. MenuSurface paints fill and backdrop.
780
- * Only --dsw-* theme tokens may appear here — a literal color is a bug.
797
+ * Only allowlisted --dsw- and --ds- theme tokens may appear here — a literal
798
+ * color is a bug.
781
799
  */
782
800
  const modelMenuCss = `
783
801
  .dsh-model-menu-root { min-width: 0; position: relative; display: inline-flex; }
@@ -800,12 +818,14 @@ const modelMenuCss = `
800
818
  display: flex;
801
819
  }
802
820
  .dsh-model-menu-trigger:hover:not(:disabled) { background: var(--dsw-alias-interactive-bg-hover); }
803
- .dsh-model-menu-trigger:focus-visible:not([data-selection-focus]) { box-shadow: 0 0 0 2px var(--dsw-focus-ring-color, var(--dsw-alias-state-business-primary)); }
821
+ .dsh-model-menu-trigger:focus-visible:not([data-selection-focus]) { box-shadow: 0 0 0 var(--dsw-focus-ring-width) var(--dsw-focus-ring-color, var(--dsw-alias-state-business-primary)); }
804
822
  .dsh-model-menu-trigger:disabled { color: var(--dsw-alias-label-dimmed); cursor: default; }
805
823
  .dsh-model-menu-triggerLabel { text-overflow: ellipsis; white-space: nowrap; min-width: 0; overflow: hidden; }
806
824
  .dsh-model-menu-triggerEffort { text-overflow: ellipsis; white-space: nowrap; min-width: 0; color: var(--dsw-alias-label-caption); flex-shrink: 1000; overflow: hidden; }
807
- .dsh-model-menu-chevron { color: var(--dsw-alias-label-caption); flex: none; transition: transform 0.12s; }
825
+ .dsh-model-menu-chevron { color: var(--dsw-alias-label-caption); flex: none; transition: transform var(--ds-transition-duration) var(--ds-ease-in-out); }
808
826
  .dsh-model-menu-chevronOpen { transform: rotate(180deg); }
827
+ /* Portal overlay: the host publishes no z-index token, so the card keeps the
828
+ * native menu layer's 1100 verbatim. */
809
829
  .dsh-model-menu-menu {
810
830
  z-index: 1100;
811
831
  --dsw-elevation-stroke-color: var(--dsw-alias-border-l1);
@@ -831,6 +851,8 @@ const modelMenuCss = `
831
851
  .dsh-model-menu-searchWithQuery { padding-right: 34px; }
832
852
  .dsh-model-menu-searchRow .dsh-model-menu-search input { padding: 0; font-size: 12px; line-height: normal; }
833
853
  .dsh-model-menu-searchRow .dsh-model-menu-search input::placeholder { color: var(--dsw-alias-label-caption); }
854
+ /* The clear button is a circle by geometry (border-radius: 50%), a shape the
855
+ * radius token scale does not describe. */
834
856
  .dsh-model-menu-searchClear {
835
857
  width: 24px;
836
858
  height: 24px;
@@ -1078,6 +1100,17 @@ ${scope} {
1078
1100
  /* --- Layout scaffolding. --- */
1079
1101
  & .dsh-ui-stack { display: flex; flex-direction: column; gap: 12px; }
1080
1102
  & .dsh-ui-stack-lg { display: flex; flex-direction: column; gap: 20px; }
1103
+ /* Plugin detail pages share one reading column. These are layout recipes;
1104
+ * controls keep their own primitive styles. Form spacing follows the host's
1105
+ * settings-form/fields.module.css and SettingsForm.module.css. */
1106
+ & .dsh-ui-page { display: flex; flex-direction: column; gap: 16px; width: 100%; max-width: 760px; min-width: 0; }
1107
+ & .dsh-ui-form { display: flex; flex-direction: column; gap: 0; min-width: 0; }
1108
+ &.dsh-ui-form > .dsh-ui-field, & .dsh-ui-form > .dsh-ui-field { padding: 12px 0; }
1109
+ & .dsh-ui-form-footer { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; padding-top: 16px; min-width: 0; }
1110
+ & .dsh-ui-fields-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px 20px; min-width: 0; margin: 0; padding: 0; border: 0; }
1111
+ @media (max-width: 560px) {
1112
+ & .dsh-ui-fields-grid { grid-template-columns: minmax(0, 1fr); }
1113
+ }
1081
1114
  & .dsh-ui-row { display: flex; align-items: center; gap: 8px; min-width: 0; }
1082
1115
  & .dsh-ui-row-wrap { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; }
1083
1116
  & .dsh-ui-spacer { flex: 1; min-width: 0; }
@@ -1105,6 +1138,9 @@ ${scope} {
1105
1138
  * official primitive, so this only owns the vertical rhythm. --- */
1106
1139
  & .dsh-ui-field { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
1107
1140
  & .dsh-ui-field + .dsh-ui-field { border-top: 0.5px solid var(--dsw-alias-border-l2); padding-top: 12px; }
1141
+ /* Grid fields share a row, so the stacked-field divider must not win later in
1142
+ * the cascade. Reset it here, after the field recipe. */
1143
+ & .dsh-ui-fields-grid > .dsh-ui-field { padding: 0; border: 0; }
1108
1144
  & .dsh-ui-label { display: flex; align-items: center; gap: 6px; font-size: 13px; line-height: 20px; font-weight: 500; color: var(--dsw-alias-label-primary); }
1109
1145
  & .dsh-ui-label-row { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; }
1110
1146
  & .dsh-ui-help { font-size: 12px; line-height: 1.6; color: var(--dsw-alias-label-secondary); }
@@ -1295,7 +1331,7 @@ ${scope} {
1295
1331
  & *, & *::before, & *::after { transition-duration: 0.01ms !important; animation-duration: 0.01ms !important; }
1296
1332
  }
1297
1333
  }
1298
- `.replace(/^& (\.dsh-ui-[a-z0-9-]+)(?![+>~])/gm, (_match, className) => `&${className}, & ${className}`);
1334
+ `.replace(/^& (\.dsh-ui-[a-z0-9-]+)(?=\s*\{)/gm, (_match, className) => `&${className}, & ${className}`);
1299
1335
  }
1300
1336
  //#endregion
1301
1337
  //#region ../dsh-plugin-kit/src/contracts.ts
@@ -1997,7 +2033,7 @@ function CastPage({ api, locale }) {
1997
2033
  refresh: refreshNow
1998
2034
  };
1999
2035
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2000
- className: "cast-root dsh-ui-stack",
2036
+ className: "cast-root dsh-model-hub dsh-ui-stack",
2001
2037
  "aria-label": t("title"),
2002
2038
  "aria-busy": saving !== "" || refreshing,
2003
2039
  children: [
@@ -2427,7 +2463,7 @@ function HubPage({ view, api, locale, initialEntries = null, initialCatalog = nu
2427
2463
  refresh: refreshNow
2428
2464
  };
2429
2465
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
2430
- className: "dsh-model-hub dsh-ui-stack",
2466
+ className: "dsh-model-hub dsh-ui-page",
2431
2467
  lang: t.language,
2432
2468
  "aria-label": t("title"),
2433
2469
  "aria-busy": writing !== "" || refreshing,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@klarkxy/dsh-model-hub",
3
- "version": "0.1.4",
3
+ "version": "0.1.5",
4
4
  "description": "Change the models used by DSH plugins and subagents from one page, and see each running subagent's model and reasoning effort.",
5
5
  "license": "SEE LICENSE IN LICENSE",
6
6
  "type": "module",
@@ -49,8 +49,8 @@
49
49
  "test": "vitest run --root ../.. --config vitest.editor-plugins.config.ts --maxWorkers=2 plugins/dsh-model-hub/src"
50
50
  },
51
51
  "dependencies": {
52
- "@klarkxy/dsh-model-route": "0.2.5",
53
- "@klarkxy/dsh-plugin-kit": "0.4.0"
52
+ "@klarkxy/dsh-model-route": "0.2.6",
53
+ "@klarkxy/dsh-plugin-kit": "0.5.0"
54
54
  },
55
55
  "peerDependencies": {
56
56
  "@deepseek-ai/cordis": ">=4.0.4",
@@ -106,6 +106,6 @@
106
106
  },
107
107
  "homepage": "https://klarkxy.github.io/dsh-plugins/plugins/model-hub/",
108
108
  "dshRelease": {
109
- "contentHash": "860363396797e379fd1b251ee3204f9010d08a96e439202a1efc2472fe8732e3"
109
+ "contentHash": "ec880c63d3cca48baf30ec513fc03d42f4303a49d1626dcbc7ac45c8a69c3bb6"
110
110
  }
111
111
  }