@yadsh/dsh-plugin-log-ui 0.1.0 → 0.2.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.
@@ -0,0 +1,13 @@
1
+ {
2
+ "deepseekHarness": {
3
+ "channel": "next",
4
+ "range": ">=0.1.1-rc.2 <0.2.0",
5
+ "testedReleases": [
6
+ "0.1.1-rc.2"
7
+ ],
8
+ "requiredClientFeatures": [
9
+ "settings.plugin.item"
10
+ ]
11
+ },
12
+ "node": ">=22"
13
+ }
@@ -1,8 +1,8 @@
1
1
  import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import pluginLogUiRemote from "@yadsh/dsh-plugin-log-ui/remote";
3
+ import { CardShell, bindSettingsExternalStore, registerSettingsCard, startVisibilityAwarePolling, } from "@yadsh/dsh-plugin-kit/client";
3
4
  import { useCallback, useEffect, useMemo, useState, useSyncExternalStore } from "react";
4
5
  import { styles } from "./styles.js";
5
- import { bindSettingsExternalStore } from "./settings-store.js";
6
6
  const SETTINGS_NAMESPACE = "plugin-log";
7
7
  const REFRESH_INTERVAL_MS = 2_000;
8
8
  const LEVELS = [
@@ -24,13 +24,9 @@ function errorText(error) {
24
24
  function LevelOptions({ inherit }) {
25
25
  return (_jsxs(_Fragment, { children: [inherit !== undefined ? _jsxs("option", { value: "", children: ["Inherit default (", inherit, ")"] }) : null, LEVELS.map((level) => (_jsx("option", { value: level, children: level === "silent" ? "silent (off)" : level }, level)))] }));
26
26
  }
27
- function ChevronDown() {
28
- return (_jsx("svg", { className: "dsh-plugin-card__chevron", viewBox: "0 0 14 14", fill: "none", "aria-hidden": "true", children: _jsx("path", { d: "m3.5 5.25 3.5 3.5 3.5-3.5", stroke: "currentColor", strokeLinecap: "round", strokeLinejoin: "round" }) }));
29
- }
30
27
  function PluginLogSettingsCard({ scope, inspect }) {
31
28
  const settingsStore = useMemo(() => bindSettingsExternalStore(scope), [scope]);
32
29
  const settings = useSyncExternalStore(settingsStore.subscribe, settingsStore.getSnapshot, settingsStore.getSnapshot);
33
- const [open, setOpen] = useState(false);
34
30
  const [snapshot, setSnapshot] = useState({ consumers: [] });
35
31
  const [error, setError] = useState(null);
36
32
  const [saving, setSaving] = useState(false);
@@ -55,9 +51,7 @@ function PluginLogSettingsCard({ scope, inspect }) {
55
51
  }
56
52
  }, [inspect]);
57
53
  useEffect(() => {
58
- void refresh();
59
- const timer = window.setInterval(() => void refresh(), REFRESH_INTERVAL_MS);
60
- return () => window.clearInterval(timer);
54
+ return startVisibilityAwarePolling(refresh, REFRESH_INTERVAL_MS);
61
55
  }, [refresh]);
62
56
  const write = useCallback(async (field, value) => {
63
57
  setSaving(true);
@@ -83,7 +77,7 @@ function PluginLogSettingsCard({ scope, inspect }) {
83
77
  }, [levels, write]);
84
78
  if (settings.status === "unavailable")
85
79
  return null;
86
- return (_jsxs("li", { className: `dsh-plugin-card${open ? " dsh-plugin-card--open" : ""}`, children: [_jsxs("button", { type: "button", className: "dsh-plugin-card__header", "aria-expanded": open, "aria-label": `${open ? "Hide" : "Show"} settings: Plugin logging`, onClick: () => setOpen(!open), children: [_jsxs("span", { className: "dsh-plugin-card__head-text", children: [_jsx("span", { className: "dsh-plugin-card__name", children: "Plugin logging" }), _jsx("span", { className: "dsh-plugin-card__description", children: "Levels and readable file output for registered server plugins." })] }), _jsxs("span", { className: "dsh-plugin-card__badge", children: [snapshot.consumers.length, " active"] }), _jsx(ChevronDown, {})] }), open ? (_jsxs("div", { className: "dsh-plugin-card__body plu-body", children: [error !== null ? _jsx("p", { className: "plu-error", role: "status", children: error }) : null, !writable ? _jsx("p", { className: "plu-status", children: "Settings are read-only for this connection." }) : null, _jsxs("section", { className: "plu-section", children: [_jsx("h3", { children: "Defaults" }), _jsxs("div", { className: "plu-grid", children: [_jsxs("label", { className: "plu-field", children: [_jsx("span", { children: "Default level" }), _jsx("select", { className: "plu-select", value: defaultLevel, disabled: !writable || saving, onChange: (event) => void write("defaultLevel", event.currentTarget.value), children: _jsx(LevelOptions, {}) })] }), _jsxs("label", { className: "plu-field", children: [_jsx("span", { children: "File format" }), _jsxs("select", { className: "plu-select", value: format, disabled: !writable || saving, onChange: (event) => void write("format", event.currentTarget.value), children: [_jsx("option", { value: "text", children: "Text \u2014 readable lines" }), _jsx("option", { value: "json", children: "JSON \u2014 NDJSON records" })] })] })] }), _jsx("p", { className: "plu-hint", children: "Changes apply live. A format switch affects new lines; an existing daily file can contain both formats until rotation." })] }), _jsxs("section", { className: "plu-section", children: [_jsx("h3", { children: "Registered plugins" }), snapshot.consumers.length === 0 ? (_jsx("p", { className: "plu-empty", children: "No active plugin logger consumers yet." })) : (_jsx("div", { className: "plu-list", children: snapshot.consumers.map((consumer) => (_jsxs("div", { className: "plu-row", children: [_jsxs("div", { className: "plu-plugin", children: [_jsx("code", { children: consumer.pluginId }), _jsxs("span", { children: [consumer.instances, " instance", consumer.instances === 1 ? "" : "s", " \u00B7 active: ", consumer.level, " \u00B7 ", consumer.format] })] }), _jsx("select", { className: "plu-select", "aria-label": `Log level for ${consumer.pluginId}`, value: levels[consumer.pluginId] ?? "", disabled: !writable || saving, onChange: (event) => setOverride(consumer.pluginId, event.currentTarget.value), children: _jsx(LevelOptions, { inherit: defaultLevel }) })] }, consumer.pluginId))) }))] })] })) : null] }));
80
+ return (_jsxs(CardShell, { title: "Plugin logging", description: "Levels and readable file output for registered server plugins.", badge: _jsxs("span", { className: "dsh-plugin-card__badge", children: [snapshot.consumers.length, " active"] }), label: (open) => `${open ? "Hide" : "Show"} settings: Plugin logging`, bodyClassName: "plu-body", children: [error !== null ? _jsx("p", { className: "plu-error", role: "status", children: error }) : null, !writable ? _jsx("p", { className: "plu-status", children: "Settings are read-only for this connection." }) : null, _jsxs("section", { className: "plu-section", children: [_jsx("h3", { children: "Defaults" }), _jsxs("div", { className: "plu-grid", children: [_jsxs("label", { className: "plu-field", children: [_jsx("span", { children: "Default level" }), _jsx("select", { className: "plu-select", value: defaultLevel, disabled: !writable || saving, onChange: (event) => void write("defaultLevel", event.currentTarget.value), children: _jsx(LevelOptions, {}) })] }), _jsxs("label", { className: "plu-field", children: [_jsx("span", { children: "File format" }), _jsxs("select", { className: "plu-select", value: format, disabled: !writable || saving, onChange: (event) => void write("format", event.currentTarget.value), children: [_jsx("option", { value: "text", children: "Text \u2014 readable lines" }), _jsx("option", { value: "json", children: "JSON \u2014 NDJSON records" })] })] })] }), _jsx("p", { className: "plu-hint", children: "Changes apply live. A format switch affects new lines; an existing daily file can contain both formats until rotation." })] }), _jsxs("section", { className: "plu-section", children: [_jsx("h3", { children: "Registered plugins" }), snapshot.consumers.length === 0 ? (_jsx("p", { className: "plu-empty", children: "No active plugin logger consumers yet." })) : (_jsx("div", { className: "plu-list", children: snapshot.consumers.map((consumer) => (_jsxs("div", { className: "plu-row", children: [_jsxs("div", { className: "plu-plugin", children: [_jsx("code", { children: consumer.pluginId }), _jsxs("span", { children: [consumer.instances, " instance", consumer.instances === 1 ? "" : "s", " \u00B7 active: ", consumer.level, " \u00B7 ", consumer.format] })] }), _jsx("select", { className: "plu-select", "aria-label": `Log level for ${consumer.pluginId}`, value: levels[consumer.pluginId] ?? "", disabled: !writable || saving, onChange: (event) => setOverride(consumer.pluginId, event.currentTarget.value), children: _jsx(LevelOptions, { inherit: defaultLevel }) })] }, consumer.pluginId))) }))] })] }));
87
81
  }
88
82
  export const inject = ["slots", "settingsScope", "remote"];
89
83
  export async function apply(ctx) {
@@ -95,19 +89,13 @@ export async function apply(ctx) {
95
89
  const scope = remoteCtx.settingsScope.bind({
96
90
  namespace: SETTINGS_NAMESPACE,
97
91
  });
98
- const style = document.createElement("style");
99
- style.dataset.plugin = "dsh-plugin-log-ui";
100
- style.textContent = styles;
101
- document.head.append(style);
102
- const disposeSlot = remoteCtx.slots.inject("settings.plugin.item", () => remoteCtx.slots.register({
103
- name: "settings.plugin.item",
92
+ return registerSettingsCard(remoteCtx, {
104
93
  key: SETTINGS_NAMESPACE,
94
+ pluginName: "dsh-plugin-log-ui",
95
+ styles,
96
+ component: PluginLogSettingsCard,
105
97
  inject: () => ({ scope, inspect: () => inspector.inspect() }),
106
- }, PluginLogSettingsCard));
107
- return () => {
108
- disposeSlot();
109
- style.remove();
110
- };
98
+ });
111
99
  });
112
100
  return disposeRemote;
113
101
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/client/index.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/client/index.tsx"],"names":[],"mappings":"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"}
@@ -1,16 +1,5 @@
1
- export const styles = `
2
- .dsh-plugin-card{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);border-radius:12px;list-style:none;transition:border-color .16s,background .16s}
3
- .dsh-plugin-card:hover{border-color:var(--dsw-alias-label-dimmed)}
4
- .dsh-plugin-card--open{background:var(--dsw-alias-bg-layer-2);border-color:var(--dsw-alias-label-dimmed)}
5
- .dsh-plugin-card__header{appearance:none;width:100%;font:inherit;color:inherit;text-align:left;cursor:pointer;background:0 0;border:0;border-radius:12px;align-items:center;gap:12px;padding:14px 16px;display:flex}
6
- .dsh-plugin-card__header:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:-2px}
7
- .dsh-plugin-card__head-text{flex-direction:column;flex:1;gap:4px;min-width:0;display:flex}
8
- .dsh-plugin-card__name{color:var(--dsw-alias-label-primary);font-size:15px;font-weight:600;line-height:1.4}
9
- .dsh-plugin-card__description{color:var(--dsw-alias-label-tertiary);font-size:13px;line-height:1.5}
10
- .dsh-plugin-card__badge{white-space:nowrap;background:var(--dsw-alias-bg-module-platform);color:var(--dsw-alias-label-secondary);border-radius:999px;flex:none;padding:1px 8px;font-size:11px;font-weight:500;line-height:17px}
11
- .dsh-plugin-card__chevron{width:14px;height:14px;color:var(--dsw-alias-label-tertiary);flex:none;transition:transform .16s}
12
- .dsh-plugin-card--open .dsh-plugin-card__chevron{transform:rotate(180deg)}
13
- .dsh-plugin-card__body{border-top:1px solid var(--dsw-alias-border-l2);margin:0 16px;padding-bottom:8px}
1
+ import { PLUGIN_CARD_SHELL_CSS } from "@yadsh/dsh-plugin-kit/client";
2
+ export const styles = `${PLUGIN_CARD_SHELL_CSS}
14
3
  .plu-body{padding-top:16px;display:flex;flex-direction:column;gap:18px}
15
4
  .plu-section{display:flex;flex-direction:column;gap:10px}.plu-section h3{margin:0;font-size:13px;color:var(--dsw-alias-label-primary)}
16
5
  .plu-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px}.plu-field{display:flex;flex-direction:column;gap:6px}.plu-field>span{font-size:12px;font-weight:500;color:var(--dsw-alias-label-secondary)}
@@ -1 +1 @@
1
- {"version":3,"file":"styles.js","sourceRoot":"","sources":["../../src/client/styles.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,MAAM,GAAG;;;;;;;;;;;;;;;;;;;;;CAqBrB,CAAC"}
1
+ {"version":3,"file":"styles.js","sourceRoot":"","sources":["../../src/client/styles.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AAErE,MAAM,CAAC,MAAM,MAAM,GAAG,GAAG,qBAAqB;;;;;;;;;CAS7C,CAAC"}
package/lib/client.js CHANGED
@@ -4,8 +4,8 @@ window.__ModuleLoader__.load({
4
4
  var module = { exports: {} };
5
5
  var exports = module.exports;
6
6
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
7
- let react = require("react");
8
7
  let react_jsx_runtime = require("react/jsx-runtime");
8
+ let react = require("react");
9
9
  //#region ../../node_modules/.pnpm/zod@4.5.2/node_modules/zod/v4/core/util.js
10
10
  function getEnumValues(entries) {
11
11
  const numericValues = Object.values(entries).filter((v) => typeof v === "number");
@@ -4946,14 +4946,20 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
4946
4946
  },
4947
4947
  sourceLocation: {
4948
4948
  "file": "packages/dsh-plugin-log-ui/src/index.ts",
4949
- "line": 62,
4949
+ "line": 75,
4950
4950
  "column": 3
4951
4951
  }
4952
4952
  }]
4953
4953
  };
4954
4954
  //#endregion
4955
- //#region src/client/styles.ts
4956
- const styles = `
4955
+ //#region ../../packages/plugin-kit/lib/client/plugin-card-css.js
4956
+ /**
4957
+ * Canonical DSH settings-plugin card shell CSS — the single source of truth
4958
+ * for the shared `dsh-plugin-card` outer shell (see AGENTS.md). Plugins must
4959
+ * inject this CSS unchanged and may only append rules for their own controls
4960
+ * inside the card body; plugin-specific shell styling is forbidden.
4961
+ */
4962
+ const PLUGIN_CARD_SHELL_CSS = `
4957
4963
  .dsh-plugin-card{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);border-radius:12px;list-style:none;transition:border-color .16s,background .16s}
4958
4964
  .dsh-plugin-card:hover{border-color:var(--dsw-alias-label-dimmed)}
4959
4965
  .dsh-plugin-card--open{background:var(--dsw-alias-bg-layer-2);border-color:var(--dsw-alias-label-dimmed)}
@@ -4966,21 +4972,126 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
4966
4972
  .dsh-plugin-card__chevron{width:14px;height:14px;color:var(--dsw-alias-label-tertiary);flex:none;transition:transform .16s}
4967
4973
  .dsh-plugin-card--open .dsh-plugin-card__chevron{transform:rotate(180deg)}
4968
4974
  .dsh-plugin-card__body{border-top:1px solid var(--dsw-alias-border-l2);margin:0 16px;padding-bottom:8px}
4969
- .plu-body{padding-top:16px;display:flex;flex-direction:column;gap:18px}
4970
- .plu-section{display:flex;flex-direction:column;gap:10px}.plu-section h3{margin:0;font-size:13px;color:var(--dsw-alias-label-primary)}
4971
- .plu-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px}.plu-field{display:flex;flex-direction:column;gap:6px}.plu-field>span{font-size:12px;font-weight:500;color:var(--dsw-alias-label-secondary)}
4972
- .plu-select{box-sizing:border-box;width:100%;height:34px;padding:0 10px;border:1px solid var(--dsw-alias-border-l2);border-radius:8px;background:var(--dsw-alias-bg-layer-3);color:var(--dsw-alias-label-primary);font:inherit;font-size:13px}.plu-select:focus{outline:none;border-color:var(--dsw-alias-border-brand)}.plu-select:disabled{opacity:.55}
4973
- .plu-hint,.plu-status,.plu-empty{margin:0;font-size:12px;line-height:1.5;color:var(--dsw-alias-label-tertiary)}.plu-error{margin:0;padding:9px 10px;border-radius:8px;background:var(--dsw-alias-bg-error);color:var(--dsw-alias-label-error);font-size:12px}
4974
- .plu-list{display:flex;flex-direction:column;border-top:1px solid var(--dsw-alias-border-l2)}.plu-row{display:grid;grid-template-columns:minmax(150px,1fr) minmax(150px,220px);gap:14px;align-items:center;padding:12px 0;border-bottom:1px solid var(--dsw-alias-border-l2)}
4975
- .plu-plugin{min-width:0}.plu-plugin code{display:block;overflow:hidden;text-overflow:ellipsis;font-size:12px;color:var(--dsw-alias-label-primary)}.plu-plugin span{display:block;margin-top:3px;font-size:11px;color:var(--dsw-alias-label-tertiary)}
4976
- @media(max-width:720px){.plu-grid{grid-template-columns:1fr}.plu-row{grid-template-columns:1fr}}
4977
4975
  `;
4978
4976
  //#endregion
4979
- //#region src/client/settings-store.ts
4977
+ //#region ../../packages/plugin-kit/lib/client/chevron.js
4980
4978
  /**
4981
- * React calls external-store callbacks as plain functions. SettingsScope's
4982
- * methods use their receiver, so forwarding them directly loses `this` and
4983
- * crashes while reading the internal store.
4979
+ * The standard disclosure chevron of the shared settings-card shell: a
4980
+ * 14x14 inline SVG stroked with `currentColor` (round caps and joins).
4981
+ * Font glyphs must not be used for this shape — their appearance and
4982
+ * baseline vary by font and encoding.
4983
+ */
4984
+ function ChevronDown() {
4985
+ return (0, react_jsx_runtime.jsx)("svg", {
4986
+ className: "dsh-plugin-card__chevron",
4987
+ viewBox: "0 0 14 14",
4988
+ fill: "none",
4989
+ "aria-hidden": "true",
4990
+ children: (0, react_jsx_runtime.jsx)("path", {
4991
+ d: "m3.5 5.25 3.5 3.5 3.5-3.5",
4992
+ stroke: "currentColor",
4993
+ strokeLinecap: "round",
4994
+ strokeLinejoin: "round"
4995
+ })
4996
+ });
4997
+ }
4998
+ //#endregion
4999
+ //#region ../../packages/plugin-kit/lib/client/card-shell.js
5000
+ /**
5001
+ * Shared outer shell of a plugin configuration card (AGENTS.md contract): a
5002
+ * direct `<li>` child of the host list with a full-width header button
5003
+ * (`type="button"`, `aria-expanded`, accessible show/hide label, the
5004
+ * title/description stack, an optional status badge, then the chevron) and a
5005
+ * body rendered only while open. Plugin-specific controls belong inside the
5006
+ * body and must not restyle the shell.
5007
+ */
5008
+ function CardShell(props) {
5009
+ const [open, setOpen] = (0, react.useState)(false);
5010
+ const body = props.bodyClassName === void 0 ? "dsh-plugin-card__body" : `dsh-plugin-card__body ${props.bodyClassName}`;
5011
+ return (0, react_jsx_runtime.jsxs)("li", {
5012
+ className: open ? "dsh-plugin-card dsh-plugin-card--open" : "dsh-plugin-card",
5013
+ children: [(0, react_jsx_runtime.jsxs)("button", {
5014
+ type: "button",
5015
+ className: "dsh-plugin-card__header",
5016
+ "aria-expanded": open,
5017
+ "aria-label": props.label(open),
5018
+ onClick: () => {
5019
+ setOpen(!open);
5020
+ },
5021
+ children: [
5022
+ (0, react_jsx_runtime.jsxs)("span", {
5023
+ className: "dsh-plugin-card__head-text",
5024
+ children: [(0, react_jsx_runtime.jsx)("span", {
5025
+ className: "dsh-plugin-card__name",
5026
+ children: props.title
5027
+ }), (0, react_jsx_runtime.jsx)("span", {
5028
+ className: "dsh-plugin-card__description",
5029
+ children: props.description
5030
+ })]
5031
+ }),
5032
+ props.badge ?? null,
5033
+ (0, react_jsx_runtime.jsx)(ChevronDown, {})
5034
+ ]
5035
+ }), open ? (0, react_jsx_runtime.jsx)("div", {
5036
+ className: body,
5037
+ children: props.children
5038
+ }) : null]
5039
+ });
5040
+ }
5041
+ function noop() {}
5042
+ /**
5043
+ * Inject one stylesheet tag for the plugin's card CSS. The tag carries
5044
+ * `data-plugin="<pluginName>"` and is guarded against double injection; the
5045
+ * returned disposer removes the tag when this call created it. No-op in
5046
+ * non-DOM environments (headless bundles, module probes).
5047
+ */
5048
+ function injectCardStyles(pluginName, css) {
5049
+ if (typeof document === "undefined") return noop;
5050
+ const selector = `style[data-plugin="${pluginName}"]`;
5051
+ if (typeof document.querySelector === "function" && document.querySelector(selector) !== null) return noop;
5052
+ const tag = document.createElement("style");
5053
+ tag.dataset.plugin = pluginName;
5054
+ tag.textContent = css;
5055
+ document.head.appendChild(tag);
5056
+ return () => {
5057
+ tag.remove();
5058
+ };
5059
+ }
5060
+ /**
5061
+ * Register the card component into the shared settings-plugins slot. Returns
5062
+ * the registration disposer. Use this variant when the plugin drives the
5063
+ * slot's inject-factory itself (e.g. to dispose a form controller alongside).
5064
+ */
5065
+ function registerSettingsSlot(host, options) {
5066
+ const slotOptions = {
5067
+ name: options.slotName ?? "settings.plugin.item",
5068
+ key: options.key,
5069
+ ...options.locale === void 0 ? {} : { locale: options.locale },
5070
+ ...options.inject === void 0 ? {} : { inject: options.inject }
5071
+ };
5072
+ return host.slots.register(slotOptions, options.component);
5073
+ }
5074
+ /**
5075
+ * Full bootstrap: inject {@link options.styles} once (when provided), then
5076
+ * mount the card into the settings-plugins slot. Returns a disposer removing
5077
+ * the slot effect and the injected stylesheet.
5078
+ */
5079
+ function registerSettingsCard(host, options) {
5080
+ const removeStyles = options.styles === void 0 || options.pluginName === void 0 ? void 0 : injectCardStyles(options.pluginName, options.styles);
5081
+ const slotName = options.slotName ?? "settings.plugin.item";
5082
+ const disposeEffect = host.slots.inject(slotName, () => registerSettingsSlot(host, options));
5083
+ return () => {
5084
+ disposeEffect();
5085
+ removeStyles?.();
5086
+ };
5087
+ }
5088
+ //#endregion
5089
+ //#region ../../packages/plugin-kit/lib/client/settings-store.js
5090
+ /**
5091
+ * React calls external-store callbacks as plain functions, while
5092
+ * SettingsScope's methods depend on their receiver. Forwarding the methods
5093
+ * directly loses `this` and crashes while reading the internal store, so
5094
+ * bind them through stable wrappers.
4984
5095
  */
4985
5096
  function bindSettingsExternalStore(scope) {
4986
5097
  return {
@@ -4988,6 +5099,35 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
4988
5099
  getSnapshot: () => scope.getSnapshot()
4989
5100
  };
4990
5101
  }
5102
+ //#endregion
5103
+ //#region ../../packages/plugin-kit/lib/client/polling.js
5104
+ function startVisibilityAwarePolling(refresh, intervalMs, visibilityDocument = document, pollingWindow = window) {
5105
+ const refreshWhenVisible = () => {
5106
+ if (!visibilityDocument.hidden) refresh();
5107
+ };
5108
+ const handleVisibilityChange = () => {
5109
+ refreshWhenVisible();
5110
+ };
5111
+ refreshWhenVisible();
5112
+ const timer = pollingWindow.setInterval(refreshWhenVisible, intervalMs);
5113
+ visibilityDocument.addEventListener("visibilitychange", handleVisibilityChange);
5114
+ return () => {
5115
+ pollingWindow.clearInterval(timer);
5116
+ visibilityDocument.removeEventListener("visibilitychange", handleVisibilityChange);
5117
+ };
5118
+ }
5119
+ //#endregion
5120
+ //#region src/client/styles.ts
5121
+ const styles = `${PLUGIN_CARD_SHELL_CSS}
5122
+ .plu-body{padding-top:16px;display:flex;flex-direction:column;gap:18px}
5123
+ .plu-section{display:flex;flex-direction:column;gap:10px}.plu-section h3{margin:0;font-size:13px;color:var(--dsw-alias-label-primary)}
5124
+ .plu-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px}.plu-field{display:flex;flex-direction:column;gap:6px}.plu-field>span{font-size:12px;font-weight:500;color:var(--dsw-alias-label-secondary)}
5125
+ .plu-select{box-sizing:border-box;width:100%;height:34px;padding:0 10px;border:1px solid var(--dsw-alias-border-l2);border-radius:8px;background:var(--dsw-alias-bg-layer-3);color:var(--dsw-alias-label-primary);font:inherit;font-size:13px}.plu-select:focus{outline:none;border-color:var(--dsw-alias-border-brand)}.plu-select:disabled{opacity:.55}
5126
+ .plu-hint,.plu-status,.plu-empty{margin:0;font-size:12px;line-height:1.5;color:var(--dsw-alias-label-tertiary)}.plu-error{margin:0;padding:9px 10px;border-radius:8px;background:var(--dsw-alias-bg-error);color:var(--dsw-alias-label-error);font-size:12px}
5127
+ .plu-list{display:flex;flex-direction:column;border-top:1px solid var(--dsw-alias-border-l2)}.plu-row{display:grid;grid-template-columns:minmax(150px,1fr) minmax(150px,220px);gap:14px;align-items:center;padding:12px 0;border-bottom:1px solid var(--dsw-alias-border-l2)}
5128
+ .plu-plugin{min-width:0}.plu-plugin code{display:block;overflow:hidden;text-overflow:ellipsis;font-size:12px;color:var(--dsw-alias-label-primary)}.plu-plugin span{display:block;margin-top:3px;font-size:11px;color:var(--dsw-alias-label-tertiary)}
5129
+ @media(max-width:720px){.plu-grid{grid-template-columns:1fr}.plu-row{grid-template-columns:1fr}}
5130
+ `;
4991
5131
  //#endregion
4992
5132
  //#region src/client/index.tsx
4993
5133
  const SETTINGS_NAMESPACE = "plugin-log";
@@ -5019,24 +5159,9 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5019
5159
  children: level === "silent" ? "silent (off)" : level
5020
5160
  }, level))] });
5021
5161
  }
5022
- function ChevronDown() {
5023
- return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
5024
- className: "dsh-plugin-card__chevron",
5025
- viewBox: "0 0 14 14",
5026
- fill: "none",
5027
- "aria-hidden": "true",
5028
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
5029
- d: "m3.5 5.25 3.5 3.5 3.5-3.5",
5030
- stroke: "currentColor",
5031
- strokeLinecap: "round",
5032
- strokeLinejoin: "round"
5033
- })
5034
- });
5035
- }
5036
5162
  function PluginLogSettingsCard({ scope, inspect }) {
5037
5163
  const settingsStore = (0, react.useMemo)(() => bindSettingsExternalStore(scope), [scope]);
5038
5164
  const settings = (0, react.useSyncExternalStore)(settingsStore.subscribe, settingsStore.getSnapshot, settingsStore.getSnapshot);
5039
- const [open, setOpen] = (0, react.useState)(false);
5040
5165
  const [snapshot, setSnapshot] = (0, react.useState)({ consumers: [] });
5041
5166
  const [error, setError] = (0, react.useState)(null);
5042
5167
  const [saving, setSaving] = (0, react.useState)(false);
@@ -5057,9 +5182,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5057
5182
  }
5058
5183
  }, [inspect]);
5059
5184
  (0, react.useEffect)(() => {
5060
- refresh();
5061
- const timer = window.setInterval(() => void refresh(), REFRESH_INTERVAL_MS);
5062
- return () => window.clearInterval(timer);
5185
+ return startVisibilityAwarePolling(refresh, REFRESH_INTERVAL_MS);
5063
5186
  }, [refresh]);
5064
5187
  const write = (0, react.useCallback)(async (field, value) => {
5065
5188
  setSaving(true);
@@ -5080,114 +5203,95 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5080
5203
  write("levels", next);
5081
5204
  }, [levels, write]);
5082
5205
  if (settings.status === "unavailable") return null;
5083
- return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("li", {
5084
- className: `dsh-plugin-card${open ? " dsh-plugin-card--open" : ""}`,
5085
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
5086
- type: "button",
5087
- className: "dsh-plugin-card__header",
5088
- "aria-expanded": open,
5089
- "aria-label": `${open ? "Hide" : "Show"} settings: Plugin logging`,
5090
- onClick: () => setOpen(!open),
5091
- children: [
5092
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
5093
- className: "dsh-plugin-card__head-text",
5094
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5095
- className: "dsh-plugin-card__name",
5096
- children: "Plugin logging"
5097
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
5098
- className: "dsh-plugin-card__description",
5099
- children: "Levels and readable file output for registered server plugins."
5100
- })]
5101
- }),
5102
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
5103
- className: "dsh-plugin-card__badge",
5104
- children: [snapshot.consumers.length, " active"]
5105
- }),
5106
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ChevronDown, {})
5107
- ]
5108
- }), open ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5109
- className: "dsh-plugin-card__body plu-body",
5110
- children: [
5111
- error !== null ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
5112
- className: "plu-error",
5113
- role: "status",
5114
- children: error
5115
- }) : null,
5116
- !writable ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
5117
- className: "plu-status",
5118
- children: "Settings are read-only for this connection."
5119
- }) : null,
5120
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
5121
- className: "plu-section",
5122
- children: [
5123
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", { children: "Defaults" }),
5124
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5125
- className: "plu-grid",
5126
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
5127
- className: "plu-field",
5128
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: "Default level" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("select", {
5129
- className: "plu-select",
5130
- value: defaultLevel,
5131
- disabled: !writable || saving,
5132
- onChange: (event) => void write("defaultLevel", event.currentTarget.value),
5133
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(LevelOptions, {})
5134
- })]
5135
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
5136
- className: "plu-field",
5137
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: "File format" }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
5138
- className: "plu-select",
5139
- value: format,
5140
- disabled: !writable || saving,
5141
- onChange: (event) => void write("format", event.currentTarget.value),
5142
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
5143
- value: "text",
5144
- children: "Text — readable lines"
5145
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
5146
- value: "json",
5147
- children: "JSON — NDJSON records"
5148
- })]
5149
- })]
5206
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(CardShell, {
5207
+ title: "Plugin logging",
5208
+ description: "Levels and readable file output for registered server plugins.",
5209
+ badge: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
5210
+ className: "dsh-plugin-card__badge",
5211
+ children: [snapshot.consumers.length, " active"]
5212
+ }),
5213
+ label: (open) => `${open ? "Hide" : "Show"} settings: Plugin logging`,
5214
+ bodyClassName: "plu-body",
5215
+ children: [
5216
+ error !== null ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
5217
+ className: "plu-error",
5218
+ role: "status",
5219
+ children: error
5220
+ }) : null,
5221
+ !writable ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
5222
+ className: "plu-status",
5223
+ children: "Settings are read-only for this connection."
5224
+ }) : null,
5225
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
5226
+ className: "plu-section",
5227
+ children: [
5228
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", { children: "Defaults" }),
5229
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5230
+ className: "plu-grid",
5231
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
5232
+ className: "plu-field",
5233
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: "Default level" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("select", {
5234
+ className: "plu-select",
5235
+ value: defaultLevel,
5236
+ disabled: !writable || saving,
5237
+ onChange: (event) => void write("defaultLevel", event.currentTarget.value),
5238
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(LevelOptions, {})
5150
5239
  })]
5151
- }),
5152
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
5153
- className: "plu-hint",
5154
- children: "Changes apply live. A format switch affects new lines; an existing daily file can contain both formats until rotation."
5155
- })
5156
- ]
5157
- }),
5158
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
5159
- className: "plu-section",
5160
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", { children: "Registered plugins" }), snapshot.consumers.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
5161
- className: "plu-empty",
5162
- children: "No active plugin logger consumers yet."
5163
- }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
5164
- className: "plu-list",
5165
- children: snapshot.consumers.map((consumer) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5166
- className: "plu-row",
5167
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5168
- className: "plu-plugin",
5169
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("code", { children: consumer.pluginId }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [
5170
- consumer.instances,
5171
- " instance",
5172
- consumer.instances === 1 ? "" : "s",
5173
- " · active: ",
5174
- consumer.level,
5175
- " · ",
5176
- consumer.format
5177
- ] })]
5178
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("select", {
5240
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
5241
+ className: "plu-field",
5242
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: "File format" }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
5179
5243
  className: "plu-select",
5180
- "aria-label": `Log level for ${consumer.pluginId}`,
5181
- value: levels[consumer.pluginId] ?? "",
5244
+ value: format,
5182
5245
  disabled: !writable || saving,
5183
- onChange: (event) => setOverride(consumer.pluginId, event.currentTarget.value),
5184
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(LevelOptions, { inherit: defaultLevel })
5246
+ onChange: (event) => void write("format", event.currentTarget.value),
5247
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
5248
+ value: "text",
5249
+ children: "Text — readable lines"
5250
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
5251
+ value: "json",
5252
+ children: "JSON — NDJSON records"
5253
+ })]
5185
5254
  })]
5186
- }, consumer.pluginId))
5187
- })]
5188
- })
5189
- ]
5190
- }) : null]
5255
+ })]
5256
+ }),
5257
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
5258
+ className: "plu-hint",
5259
+ children: "Changes apply live. A format switch affects new lines; an existing daily file can contain both formats until rotation."
5260
+ })
5261
+ ]
5262
+ }),
5263
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
5264
+ className: "plu-section",
5265
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", { children: "Registered plugins" }), snapshot.consumers.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
5266
+ className: "plu-empty",
5267
+ children: "No active plugin logger consumers yet."
5268
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
5269
+ className: "plu-list",
5270
+ children: snapshot.consumers.map((consumer) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5271
+ className: "plu-row",
5272
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5273
+ className: "plu-plugin",
5274
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("code", { children: consumer.pluginId }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [
5275
+ consumer.instances,
5276
+ " instance",
5277
+ consumer.instances === 1 ? "" : "s",
5278
+ " · active: ",
5279
+ consumer.level,
5280
+ " · ",
5281
+ consumer.format
5282
+ ] })]
5283
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("select", {
5284
+ className: "plu-select",
5285
+ "aria-label": `Log level for ${consumer.pluginId}`,
5286
+ value: levels[consumer.pluginId] ?? "",
5287
+ disabled: !writable || saving,
5288
+ onChange: (event) => setOverride(consumer.pluginId, event.currentTarget.value),
5289
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(LevelOptions, { inherit: defaultLevel })
5290
+ })]
5291
+ }, consumer.pluginId))
5292
+ })]
5293
+ })
5294
+ ]
5191
5295
  });
5192
5296
  }
5193
5297
  const inject = [
@@ -5200,22 +5304,16 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5200
5304
  await ctx.inject(["remote.pluginLogUi"], (remoteCtx) => {
5201
5305
  const inspector = remoteCtx.remote.pluginLogUi;
5202
5306
  const scope = remoteCtx.settingsScope.bind({ namespace: SETTINGS_NAMESPACE });
5203
- const style = document.createElement("style");
5204
- style.dataset.plugin = "dsh-plugin-log-ui";
5205
- style.textContent = styles;
5206
- document.head.append(style);
5207
- const disposeSlot = remoteCtx.slots.inject("settings.plugin.item", () => remoteCtx.slots.register({
5208
- name: "settings.plugin.item",
5307
+ return registerSettingsCard(remoteCtx, {
5209
5308
  key: SETTINGS_NAMESPACE,
5309
+ pluginName: "dsh-plugin-log-ui",
5310
+ styles,
5311
+ component: PluginLogSettingsCard,
5210
5312
  inject: () => ({
5211
5313
  scope,
5212
5314
  inspect: () => inspector.inspect()
5213
5315
  })
5214
- }, PluginLogSettingsCard));
5215
- return () => {
5216
- disposeSlot();
5217
- style.remove();
5218
- };
5316
+ });
5219
5317
  });
5220
5318
  return disposeRemote;
5221
5319
  }