@klarkxy/dsh-web-search-manager 0.3.0 → 0.3.1

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
@@ -225,6 +225,17 @@ ${scope} {
225
225
  /* --- Layout scaffolding. --- */
226
226
  & .dsh-ui-stack { display: flex; flex-direction: column; gap: 12px; }
227
227
  & .dsh-ui-stack-lg { display: flex; flex-direction: column; gap: 20px; }
228
+ /* Plugin detail pages share one reading column. These are layout recipes;
229
+ * controls keep their own primitive styles. Form spacing follows the host's
230
+ * settings-form/fields.module.css and SettingsForm.module.css. */
231
+ & .dsh-ui-page { display: flex; flex-direction: column; gap: 16px; width: 100%; max-width: 760px; min-width: 0; }
232
+ & .dsh-ui-form { display: flex; flex-direction: column; gap: 0; min-width: 0; }
233
+ &.dsh-ui-form > .dsh-ui-field, & .dsh-ui-form > .dsh-ui-field { padding: 12px 0; }
234
+ & .dsh-ui-form-footer { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; padding-top: 16px; min-width: 0; }
235
+ & .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; }
236
+ @media (max-width: 560px) {
237
+ & .dsh-ui-fields-grid { grid-template-columns: minmax(0, 1fr); }
238
+ }
228
239
  & .dsh-ui-row { display: flex; align-items: center; gap: 8px; min-width: 0; }
229
240
  & .dsh-ui-row-wrap { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; }
230
241
  & .dsh-ui-spacer { flex: 1; min-width: 0; }
@@ -252,6 +263,9 @@ ${scope} {
252
263
  * official primitive, so this only owns the vertical rhythm. --- */
253
264
  & .dsh-ui-field { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
254
265
  & .dsh-ui-field + .dsh-ui-field { border-top: 0.5px solid var(--dsw-alias-border-l2); padding-top: 12px; }
266
+ /* Grid fields share a row, so the stacked-field divider must not win later in
267
+ * the cascade. Reset it here, after the field recipe. */
268
+ & .dsh-ui-fields-grid > .dsh-ui-field { padding: 0; border: 0; }
255
269
  & .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); }
256
270
  & .dsh-ui-label-row { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; }
257
271
  & .dsh-ui-help { font-size: 12px; line-height: 1.6; color: var(--dsw-alias-label-secondary); }
@@ -442,9 +456,87 @@ ${scope} {
442
456
  & *, & *::before, & *::after { transition-duration: 0.01ms !important; animation-duration: 0.01ms !important; }
443
457
  }
444
458
  }
445
- `.replace(/^& (\.dsh-ui-[a-z0-9-]+)(?![+>~])/gm, (_match, className) => `&${className}, & ${className}`);
459
+ `.replace(/^& (\.dsh-ui-[a-z0-9-]+)(?=\s*\{)/gm, (_match, className) => `&${className}, & ${className}`);
446
460
  }
447
461
  //#endregion
462
+ //#region src/client-styles.ts
463
+ /**
464
+ * The shared contract paints this page: the type tiers, the card, the field,
465
+ * the button row, the notice, the focus ring and the state colours. What is
466
+ * left here is only the geometry the contract does not cover — the reading
467
+ * width of the panel, the ranked three-column row, the drag affordance, the
468
+ * drop indicator, the screen-reader-only announcer and the limits grid.
469
+ *
470
+ * Nothing below declares a colour of its own beyond naming a host token, and
471
+ * nothing carries a literal fallback: the host publishes both themes and a
472
+ * literal would pin one of them.
473
+ *
474
+ * Every plugin rule nests under the plugin root, as the contract does, so a
475
+ * .ws-* or .web-search-* class never paints a neighbouring plugin. Selectors
476
+ * that start with an element name keep an explicit `&`, the form every
477
+ * nesting implementation accepts.
478
+ */
479
+ const webSearchClientStyles = `${officialUiCss("ws-root")}
480
+ .ws-root {
481
+
482
+ .ws-card-head { display: flex; justify-content: space-between; align-items: center; gap: 12px; padding-bottom: 8px; }
483
+ .ws-sr-only {
484
+ position: absolute;
485
+ width: 1px;
486
+ height: 1px;
487
+ padding: 0;
488
+ margin: -1px;
489
+ overflow: hidden;
490
+ clip-path: inset(50%);
491
+ white-space: nowrap;
492
+ border: 0;
493
+ }
494
+ .ws-provider-note { display: flex; align-items: center; gap: 6px; }
495
+ .web-search-provider { display: grid; gap: 8px; min-width: 0; }
496
+ .web-search-provider-info { display: grid; gap: 3px; font-size: 12px; line-height: 18px; color: var(--dsw-alias-label-secondary); overflow-wrap: anywhere; }
497
+ .web-search-provider-heading { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 12px; min-height: 24px; }
498
+ & a { color: var(--dsw-alias-state-business-primary); font-size: 12px; line-height: 18px; text-underline-offset: 3px; }
499
+ /* The primitive renders a 32px control in an inline-flex wrapper; a settings
500
+ * field needs it to fill the column it sits in. */
501
+ .ws-input { width: 100%; }
502
+ .web-search-rank { margin: 0; padding: 0; list-style: none; }
503
+ .web-search-rank li {
504
+ position: relative;
505
+ display: grid;
506
+ grid-template-columns: 24px minmax(0, 1fr) auto;
507
+ gap: 10px;
508
+ align-items: start;
509
+ padding: 14px 0;
510
+ border-top: 0.5px solid var(--dsw-alias-border-l2);
511
+ }
512
+ & button.web-search-drag-handle {
513
+ display: grid;
514
+ place-items: center;
515
+ width: 24px;
516
+ height: 24px;
517
+ min-height: 24px;
518
+ padding: 0;
519
+ cursor: grab;
520
+ opacity: 0.65;
521
+ }
522
+ & button.web-search-drag-handle:hover { opacity: 1; }
523
+ & button.web-search-drag-handle:active { cursor: grabbing; }
524
+ & button.web-search-drag-handle[aria-disabled='true'] { cursor: wait; opacity: 0.4; }
525
+ .web-search-rank li[data-dragging] { opacity: 0.45; }
526
+ .web-search-rank li[data-drop]::after { content: ''; position: absolute; left: 0; right: 0; height: 2px; background: var(--dsw-alias-state-business-primary); pointer-events: none; }
527
+ .web-search-rank li[data-drop='before']::after { top: -1px; }
528
+ .web-search-rank li[data-drop='after']::after { bottom: -1px; }
529
+ .web-search-rank-index { color: var(--dsw-alias-label-tertiary); font-variant-numeric: tabular-nums; line-height: 24px; }
530
+ .web-search-rank-move { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; justify-content: flex-end; padding-top: 2px; }
531
+ .ws-danger:hover:not(:disabled),
532
+ .ws-danger[data-armed] { color: var(--dsw-alias-state-error-primary); border-color: var(--dsw-alias-state-error-primary); }
533
+ .ws-danger:hover:not(:disabled) { background: var(--dsw-alias-interactive-bg-hover-danger); }
534
+ @media (max-width: 560px) {
535
+ .web-search-rank-move { flex-direction: column; align-items: flex-end; }
536
+ }
537
+ }
538
+ `;
539
+ //#endregion
448
540
  //#region ../dsh-plugin-kit/src/client-utils.ts
449
541
  /** Fixed pause for failing background reads; manual work is never replayed. */
450
542
  function createPluginReadGate(now = Date.now) {
@@ -1292,7 +1384,7 @@ function NetworkSearchSettings({ client, hidden }) {
1292
1384
  setNote({ key: "keyDeleted" });
1293
1385
  }
1294
1386
  if (!status || !limitDraft) return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
1295
- className: "web-search-settings ws-root dsh-ui-panel",
1387
+ className: "web-search-settings ws-root dsh-ui-page",
1296
1388
  children: [loadError ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", {
1297
1389
  role: "alert",
1298
1390
  className: "dsh-ui-error",
@@ -1386,7 +1478,7 @@ function NetworkSearchSettings({ client, hidden }) {
1386
1478
  });
1387
1479
  }
1388
1480
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
1389
- className: "web-search-settings ws-root dsh-ui-panel",
1481
+ className: "web-search-settings ws-root dsh-ui-page",
1390
1482
  "data-testid": "web-search-settings",
1391
1483
  children: [
1392
1484
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.SegmentedTabs, {
@@ -1747,11 +1839,11 @@ function NetworkSearchSettings({ client, hidden }) {
1747
1839
  hidden: tab !== "limits",
1748
1840
  tabIndex: 0,
1749
1841
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("fieldset", {
1750
- className: "web-search-limits",
1842
+ className: "dsh-ui-fields-grid",
1751
1843
  disabled: busy || reordering,
1752
1844
  "aria-label": text.tabLimits,
1753
1845
  children: LIMITS.map(([key, min, max]) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
1754
- className: "ws-limit",
1846
+ className: "dsh-ui-field",
1755
1847
  children: [
1756
1848
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1757
1849
  className: "dsh-ui-label",
@@ -1790,7 +1882,7 @@ function NetworkSearchSettings({ client, hidden }) {
1790
1882
  })
1791
1883
  }),
1792
1884
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1793
- className: "dsh-ui-actions dsh-ui-actions-end",
1885
+ className: "dsh-ui-form-footer dsh-ui-actions-end",
1794
1886
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1795
1887
  className: "dsh-ui-meta",
1796
1888
  children: limitsDirty || keysDirty ? text.unsaved : text.saveHint
@@ -1805,74 +1897,13 @@ function NetworkSearchSettings({ client, hidden }) {
1805
1897
  ]
1806
1898
  });
1807
1899
  }
1808
- const styles = `${officialUiCss("ws-root")}
1809
- .ws-root { max-width: 760px; }
1810
- .ws-card-head { display: flex; justify-content: space-between; align-items: center; gap: 12px; padding-bottom: 8px; }
1811
- .ws-sr-only {
1812
- position: absolute;
1813
- width: 1px;
1814
- height: 1px;
1815
- padding: 0;
1816
- margin: -1px;
1817
- overflow: hidden;
1818
- clip-path: inset(50%);
1819
- white-space: nowrap;
1820
- border: 0;
1821
- }
1822
- .ws-provider-note { display: flex; align-items: center; gap: 6px; }
1823
- .web-search-provider { display: grid; gap: 8px; min-width: 0; }
1824
- .web-search-provider-info { display: grid; gap: 3px; font-size: 12px; line-height: 18px; color: var(--dsw-alias-label-secondary); overflow-wrap: anywhere; }
1825
- .web-search-provider-heading { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 12px; min-height: 24px; }
1826
- .web-search-settings a { color: var(--dsw-alias-state-business-primary); font-size: 12px; line-height: 18px; text-underline-offset: 3px; }
1827
- /* The primitive renders a 32px control in an inline-flex wrapper; a settings
1828
- * field needs it to fill the column it sits in. */
1829
- .ws-input { width: 100%; }
1830
- .web-search-rank { margin: 0; padding: 0; list-style: none; }
1831
- .web-search-rank li {
1832
- position: relative;
1833
- display: grid;
1834
- grid-template-columns: 24px minmax(0, 1fr) auto;
1835
- gap: 10px;
1836
- align-items: start;
1837
- padding: 14px 0;
1838
- border-top: 0.5px solid var(--dsw-alias-border-l2);
1839
- }
1840
- .web-search-settings button.web-search-drag-handle {
1841
- display: grid;
1842
- place-items: center;
1843
- width: 24px;
1844
- height: 24px;
1845
- min-height: 24px;
1846
- padding: 0;
1847
- cursor: grab;
1848
- opacity: 0.65;
1849
- }
1850
- .web-search-settings button.web-search-drag-handle:hover { opacity: 1; }
1851
- .web-search-settings button.web-search-drag-handle:active { cursor: grabbing; }
1852
- .web-search-settings button.web-search-drag-handle[aria-disabled='true'] { cursor: wait; opacity: 0.4; }
1853
- .web-search-rank li[data-dragging] { opacity: 0.45; }
1854
- .web-search-rank li[data-drop]::after { content: ''; position: absolute; left: 0; right: 0; height: 2px; background: var(--dsw-alias-state-business-primary); pointer-events: none; }
1855
- .web-search-rank li[data-drop='before']::after { top: -1px; }
1856
- .web-search-rank li[data-drop='after']::after { bottom: -1px; }
1857
- .web-search-rank-index { color: var(--dsw-alias-label-tertiary); font-variant-numeric: tabular-nums; line-height: 24px; }
1858
- .web-search-rank-move { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; justify-content: flex-end; padding-top: 2px; }
1859
- .web-search-limits { margin: 0; border: 0; padding: 0; display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px 20px; }
1860
- /* A two-column grid, so these fields keep the contract's caption and the
1861
- * primitive's control and only own their vertical rhythm — a stacked list is
1862
- * what draws the hairline between fields, and there is nothing to separate. */
1863
- .ws-limit { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
1864
- .ws-danger:hover:not(:disabled),
1865
- .ws-danger[data-armed] { color: var(--dsw-alias-state-error-primary); border-color: var(--dsw-alias-state-error-primary); }
1866
- .ws-danger:hover:not(:disabled) { background: var(--dsw-alias-interactive-bg-hover-danger); }
1867
- @media (max-width: 560px) { .web-search-rank-move { flex-direction: column; align-items: flex-end; } .web-search-limits { grid-template-columns: minmax(0, 1fr); } }
1868
- `;
1869
1900
  function apply(ctx) {
1870
1901
  const client = ctx;
1871
1902
  ctx.effect(() => {
1872
1903
  if (typeof document === "undefined") return () => {};
1873
1904
  const style = document.createElement("style");
1874
1905
  style.setAttribute("data-plugin", "@klarkxy/dsh-web-search-manager");
1875
- style.textContent = styles;
1906
+ style.textContent = webSearchClientStyles;
1876
1907
  style.dataset.dshWebSearch = "";
1877
1908
  document.head.appendChild(style);
1878
1909
  return () => style.remove();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@klarkxy/dsh-web-search-manager",
3
- "version": "0.3.0",
3
+ "version": "0.3.1",
4
4
  "description": "Manage and rank search and page-reading services, including providers from installed plugins, in one settings page.",
5
5
  "icon": "./icon.svg",
6
6
  "license": "SEE LICENSE IN LICENSE",
@@ -80,7 +80,7 @@
80
80
  },
81
81
  "dependencies": {
82
82
  "@deepseek-ai/dsh-web-search-exa": ">=0.2.0-rc.2",
83
- "@klarkxy/dsh-plugin-kit": "0.4.0",
83
+ "@klarkxy/dsh-plugin-kit": "0.5.0",
84
84
  "zod": "^4.1.5"
85
85
  },
86
86
  "peerDependencies": {
@@ -152,6 +152,6 @@
152
152
  "registry": "https://registry.npmjs.org/"
153
153
  },
154
154
  "dshRelease": {
155
- "contentHash": "e86bf9ef6ca28eaf4dc5a9047a5718f54ef20befd42d82fe247477cef17564f7"
155
+ "contentHash": "b13ef2869d849beeed7fa30c94ddb05a2ec803a59d0d258a098c92c211b8a91f"
156
156
  }
157
157
  }