@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/README.md +14 -14
- package/docs/README.zh-CN.md +12 -12
- package/lib/client.inner.cjs +99 -68
- package/lib/client.inner.cjs.map +1 -1
- package/lib/client.js +99 -68
- package/package.json +3 -3
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-]+)(
|
|
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-
|
|
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-
|
|
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: "
|
|
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: "
|
|
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-
|
|
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 =
|
|
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.
|
|
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.
|
|
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": "
|
|
155
|
+
"contentHash": "b13ef2869d849beeed7fa30c94ddb05a2ec803a59d0d258a098c92c211b8a91f"
|
|
156
156
|
}
|
|
157
157
|
}
|