@lmzhen/dsh-evolution-ui 0.34.0 → 0.35.0

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
@@ -841,12 +841,12 @@ window.__ModuleLoader__.load({
841
841
  projectionFailed: "这一块读设置时出错,已记入日志;其它参数不受影响",
842
842
  readonly: "本次会话不允许写入设置(临时运行模式)",
843
843
  apply: "保存",
844
- reset: "恢复默认值",
844
+ reset: "复位",
845
845
  empty: "这里没有可改项",
846
846
  changed: "{n} 项已覆盖",
847
847
  discard: "放弃修改",
848
848
  saving: "保存中…",
849
- resetting: "恢复中…",
849
+ resetting: "复位中…",
850
850
  writeTargetHost: "保存去向:宿主配置(对所有会话生效)",
851
851
  invalidNumber: "需要一个数字",
852
852
  invalidSelect: "不在允许的取值里",
@@ -949,7 +949,7 @@ window.__ModuleLoader__.load({
949
949
  projectionFailed: "reading this row failed and the error is in the log; the other parameters are unaffected",
950
950
  readonly: "settings cannot be written in this session (temporary mode)",
951
951
  apply: "Save",
952
- reset: "Reset to default",
952
+ reset: "Reset",
953
953
  empty: "nothing to change here",
954
954
  changed: "{n} overridden",
955
955
  discard: "Discard",
@@ -1270,10 +1270,12 @@ window.__ModuleLoader__.load({
1270
1270
  type: "button",
1271
1271
  className: "evolution-param-button",
1272
1272
  disabled: props.disabled || props.clearing,
1273
+ "data-role": "reset",
1274
+ title: props.resetTo === null ? void 0 : t("resetTo", { value: props.resetTo }),
1273
1275
  onClick: () => {
1274
1276
  props.onClear(field.id);
1275
1277
  }
1276
- }, props.clearing ? t("resetting") : t("reset")), props.resetTo === null ? null : (0, react.createElement)("span", { className: "evolution-param-hint" }, t("resetTo", { value: props.resetTo }))) : null);
1278
+ }, props.clearing ? t("resetting") : t("reset"))) : null);
1277
1279
  }
1278
1280
  /**
1279
1281
  * Render one row's card body from a supplied snapshot.
@@ -1780,6 +1782,28 @@ window.__ModuleLoader__.load({
1780
1782
  };
1781
1783
  }
1782
1784
  //#endregion
1785
+ //#region ../evolution-client-kit/src/format.ts
1786
+ /**
1787
+ * Format an ISO string, epoch milliseconds, or null as local wall time.
1788
+ * Invalid values return null; callers decide how to say "unknown".
1789
+ * @param value - ISO string, epoch ms, or null.
1790
+ * @param options - seconds on/off; defaults to on.
1791
+ * @returns the formatted local time, or null when the value is absent/invalid.
1792
+ */
1793
+ function formatLocalDateTime(value, options = {}) {
1794
+ if (value === null || value === void 0) return null;
1795
+ const ms = typeof value === "number" ? value : Date.parse(value);
1796
+ if (!Number.isFinite(ms)) return null;
1797
+ const date = new Date(ms);
1798
+ if (Number.isNaN(date.getTime())) return null;
1799
+ const pad = (part) => String(part).padStart(2, "0");
1800
+ const head = String(date.getFullYear()) + "-" + pad(date.getMonth() + 1) + "-" + pad(date.getDate()) + " " + pad(date.getHours()) + ":" + pad(date.getMinutes());
1801
+ return options.seconds === false ? head : head + ":" + pad(date.getSeconds());
1802
+ }
1803
+ //#endregion
1804
+ //#region ../evolution-client-kit/src/notice.ts
1805
+ /** One inline state notice: semantic tone plus text, no surface-specific styling. */
1806
+ //#endregion
1783
1807
  //#region ../evolution-client-kit/src/action.ts
1784
1808
  /**
1785
1809
  * Command-only actions. Approval decisions are a separate host API and must never
@@ -2903,6 +2927,7 @@ window.__ModuleLoader__.load({
2903
2927
  const zh = {
2904
2928
  "entry.label": "技能历史",
2905
2929
  title: "技能历史",
2930
+ bodyTitle: "正文版本",
2906
2931
  "workbench.history": "技能历史",
2907
2932
  "workbench.pending": "待批",
2908
2933
  "workbench.merge": "合并",
@@ -2932,6 +2957,7 @@ window.__ModuleLoader__.load({
2932
2957
  "failure.server": "读取失败,可以重试。",
2933
2958
  "fallback.hint": "可以改用命令:{command}",
2934
2959
  "undo.confirm": "确认回退(会写入一版,可再回退)",
2960
+ "undo.confirmUnit": "确认回退整个跨技能写入单元(会写入一版,可再回退)",
2935
2961
  "undo.no": "取消",
2936
2962
  current: "当前",
2937
2963
  "versions.count": "{n} 个版本",
@@ -2972,6 +2998,7 @@ window.__ModuleLoader__.load({
2972
2998
  "action.archive": "归档",
2973
2999
  "action.archive.note": "这一版存的是被归档的正文",
2974
3000
  "action.consolidate": "合并",
3001
+ "action.merge": "合并",
2975
3002
  "action.restructure": "结构调整",
2976
3003
  "action.extract": "跨技能提取",
2977
3004
  "action.support-write": "写入附带文件",
@@ -2995,6 +3022,7 @@ window.__ModuleLoader__.load({
2995
3022
  const en = {
2996
3023
  "entry.label": "Skill history",
2997
3024
  title: "Skill history",
3025
+ bodyTitle: "Body versions",
2998
3026
  "workbench.history": "Skill history",
2999
3027
  "workbench.pending": "Pending",
3000
3028
  "workbench.merge": "Merge",
@@ -3024,6 +3052,7 @@ window.__ModuleLoader__.load({
3024
3052
  "failure.server": "The read failed; you can retry.",
3025
3053
  "fallback.hint": "Command fallback: {command}",
3026
3054
  "undo.confirm": "Confirm restore (writes a new version; can be undone)",
3055
+ "undo.confirmUnit": "Confirm restoring the whole cross-skill unit (writes a new version; can be undone)",
3027
3056
  "undo.no": "Cancel",
3028
3057
  current: "Current",
3029
3058
  "versions.count": "{n} versions",
@@ -3064,6 +3093,7 @@ window.__ModuleLoader__.load({
3064
3093
  "action.archive": "archived",
3065
3094
  "action.archive.note": "this version holds the archived body",
3066
3095
  "action.consolidate": "merged",
3096
+ "action.merge": "merged",
3067
3097
  "action.restructure": "restructured",
3068
3098
  "action.extract": "extracted across skills",
3069
3099
  "action.support-write": "support file written",
@@ -3130,6 +3160,7 @@ window.__ModuleLoader__.load({
3130
3160
  ".evo-hist-skill[aria-current=\"true\"]{background:var(--dsw-alias-interactive-bg-active);color:var(--dsw-alias-label-primary);font-weight:500}",
3131
3161
  ".evo-hist-cell-line{display:flex;align-items:baseline;gap:var(--evo-space-6);min-width:0}",
3132
3162
  ".evo-hist-cell-meta{margin-top:var(--evo-space-2)}",
3163
+ ".evo-hist-skill-description{display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;margin-top:var(--evo-space-2);color:var(--dsw-alias-label-tertiary)}",
3133
3164
  ".evo-hist-cell{min-width:0;font-variant-numeric:tabular-nums}",
3134
3165
  ".evo-hist-slot-lead{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}",
3135
3166
  ".evo-hist-slot-meta{flex:none;white-space:nowrap}",
@@ -3173,7 +3204,7 @@ window.__ModuleLoader__.load({
3173
3204
  ".evo-doc-tag{position:absolute;left:var(--evo-space-8);top:var(--evo-space-8);color:var(--dsw-alias-label-tertiary)}",
3174
3205
  ".evo-doc-line-add{color:var(--evo-tone-success)}",
3175
3206
  ".evo-doc-line-del{color:var(--evo-tone-danger)}",
3176
- "@media (max-width:720px){.evo-hist-root{flex-direction:column}.evo-hist-aside{flex:0 0 auto;width:100%;max-height:42%;border-right:0;border-bottom:var(--evo-hairline-width) solid var(--dsw-alias-border-l2)}.evo-hist-row{max-width:none}}"
3207
+ "@media (max-width:900px){.evo-hist-root{flex-direction:column}.evo-hist-aside{flex:0 0 auto;width:100%;max-height:42%;border-right:0;border-bottom:var(--evo-hairline-width) solid var(--dsw-alias-border-l2)}.evo-hist-row{max-width:none}}"
3177
3208
  ].join("\n");
3178
3209
  //#endregion
3179
3210
  //#region src/panels/history/client/atoms.ts
@@ -3281,11 +3312,7 @@ window.__ModuleLoader__.load({
3281
3312
  */
3282
3313
  /** The local time an ISO timestamp names, as the operator's own clock shows it. */
3283
3314
  function localTime(at) {
3284
- const parsed = Date.parse(at);
3285
- if (Number.isNaN(parsed)) return at;
3286
- const date = new Date(parsed);
3287
- const pad = (value) => String(value).padStart(2, "0");
3288
- return String(date.getFullYear()) + "-" + pad(date.getMonth() + 1) + "-" + pad(date.getDate()) + " " + pad(date.getHours()) + ":" + pad(date.getMinutes());
3315
+ return formatLocalDateTime(at, { seconds: false }) ?? at;
3289
3316
  }
3290
3317
  /** The text one cell shows, resolved through the seat. */
3291
3318
  function cellText(copy, cell) {
@@ -3334,7 +3361,11 @@ window.__ModuleLoader__.load({
3334
3361
  className: "evo-hist-skill",
3335
3362
  "aria-current": selected ? "true" : void 0,
3336
3363
  onClick: onOpen
3337
- }, cellLine(row.cells.title, copy, "evo-hist-cell-line"), cellLine(row.cells.meta, copy, "evo-hist-cell-line evo-hist-cell-meta"));
3364
+ }, cellLine(row.cells.title, copy, "evo-hist-cell-line"), (() => {
3365
+ const description = row.cells.meta.filter((cell) => cell.key === "description");
3366
+ const facts = row.cells.meta.filter((cell) => cell.key !== "description");
3367
+ return [description.length === 0 ? null : cellLine(description, copy, "evo-hist-cell-line evo-hist-skill-description"), facts.length === 0 ? null : cellLine(facts, copy, "evo-hist-cell-line evo-hist-cell-meta")];
3368
+ })());
3338
3369
  }
3339
3370
  /**
3340
3371
  * One version row: what happened, when, how big — then the controls, then whatever is expanded.
@@ -3362,7 +3393,7 @@ window.__ModuleLoader__.load({
3362
3393
  key: "undo",
3363
3394
  tone: confirming ? "primary" : "quiet",
3364
3395
  onClick: onRestore,
3365
- children: confirming ? copy.t("undo.confirm") : copy.t("undo")
3396
+ children: confirming ? copy.t(row.unitId === void 0 ? "undo.confirm" : "undo.confirmUnit") : copy.t("undo")
3366
3397
  }));
3367
3398
  }
3368
3399
  if (row.undoable === true || row.charsDelta !== void 0) actions.push(button({
@@ -3422,8 +3453,8 @@ window.__ModuleLoader__.load({
3422
3453
  });
3423
3454
  }
3424
3455
  /** The pane's heading and its one control. */
3425
- function panelHead(copy, onRefresh) {
3426
- return (0, react.createElement)("div", { className: "evo-hist-head" }, (0, react.createElement)("h2", { className: "evo-hist-title" }, copy.t("title")), button({
3456
+ function panelHead(copy, onRefresh, title) {
3457
+ return (0, react.createElement)("div", { className: "evo-hist-head" }, (0, react.createElement)("h2", { className: "evo-hist-title" }, title ?? copy.t("title")), button({
3427
3458
  key: "refresh",
3428
3459
  title: copy.t("refresh"),
3429
3460
  onClick: onRefresh,
@@ -3949,7 +3980,7 @@ window.__ModuleLoader__.load({
3949
3980
  };
3950
3981
  return (0, react.createElement)("div", { className: "evo-hist-root" }, (0, react.createElement)("aside", { className: "evo-hist-aside" }, searchField(face, query, setQuery), (0, react.createElement)("div", { className: "evo-hist-list" }, skills.length === 0 ? emptyState(face.t(skillsLoaded ? "empty.skills" : "loading")) : visible.length === 0 ? emptyState(face.t("search.none")) : visible.map((skill) => skillLine(face, skill, skill.name === selected, () => {
3951
3982
  open(skill.name);
3952
- })))), (0, react.createElement)("div", { className: "evo-hist-main" }, panelHead(face, refresh), notice(noteText, noteError), failure === void 0 ? null : (0, react.createElement)("div", { className: "evo-hist-failure" }, failureBlock(face.t, failure)), selected === void 0 ? [emptyState(face.t(skills.length === 0 ? skillsLoaded ? "empty.skills" : "loading" : "empty.pick"), "empty"), (0, react.createElement)("p", {
3983
+ })))), (0, react.createElement)("div", { className: "evo-hist-main" }, panelHead(face, refresh, selected ?? face.t("bodyTitle")), notice(noteText, noteError), failure === void 0 ? null : (0, react.createElement)("div", { className: "evo-hist-failure" }, failureBlock(face.t, failure)), selected === void 0 ? [emptyState(face.t(skills.length === 0 ? skillsLoaded ? "empty.skills" : "loading" : "empty.pick"), "empty"), (0, react.createElement)("p", {
3953
3984
  key: "hint",
3954
3985
  className: "evo-hist-hint"
3955
3986
  }, face.t("hint"))] : loaded ? null : emptyState(versionsFailed === void 0 ? face.t("loading") : `${face.t("empty.versions.failed")} — ${versionsFailed}`), loaded ? (0, react.createElement)("div", null, group(face.t("group.content"), payload.content, void 0), group(face.t("group.support"), payload.support, face.t("group.support.note")), payload.content.length === 0 && payload.support.length === 0 ? (0, react.createElement)("p", { className: "evo-hist-hint" }, face.t("empty.versions")) : null) : null));
@@ -4029,19 +4060,26 @@ window.__ModuleLoader__.load({
4029
4060
  const translate = (key, values) => t(key, values);
4030
4061
  const [state, setState] = (0, react.useState)({ phase: "loading" });
4031
4062
  const [refreshing, setRefreshing] = (0, react.useState)(false);
4063
+ const [refreshFailure, setRefreshFailure] = (0, react.useState)(void 0);
4032
4064
  const [open, setOpen] = (0, react.useState)(false);
4033
4065
  const ticket = (0, react.useRef)(0);
4034
4066
  const read = (keepView) => {
4035
4067
  const current = ticket.current + 1;
4036
4068
  ticket.current = current;
4037
- if (keepView) setRefreshing(true);
4038
- else setState({ phase: "loading" });
4069
+ if (keepView) {
4070
+ setRefreshing(true);
4071
+ setRefreshFailure(void 0);
4072
+ } else setState({ phase: "loading" });
4039
4073
  api.view().then((answer) => {
4040
4074
  if (ticket.current !== current) return;
4041
- setState(answer.ok ? {
4042
- phase: "ready",
4043
- view: answer.data
4044
- } : {
4075
+ if (answer.ok) {
4076
+ setState({
4077
+ phase: "ready",
4078
+ view: answer.data
4079
+ });
4080
+ setRefreshFailure(void 0);
4081
+ } else if (keepView) setRefreshFailure(answer.failure);
4082
+ else setState({
4045
4083
  phase: "failed",
4046
4084
  failure: answer.failure
4047
4085
  });
@@ -4056,6 +4094,7 @@ window.__ModuleLoader__.load({
4056
4094
  read(true);
4057
4095
  };
4058
4096
  const summary = state.phase === "ready" ? summaryOf(state.view.runtime) : void 0;
4097
+ const focusRow = summary === void 0 || summary.status === "ok" || state.phase !== "ready" ? void 0 : state.view.runtime.find((row) => row.status === summary.status);
4059
4098
  const header = (0, react.createElement)("button", {
4060
4099
  type: "button",
4061
4100
  className: "evolution-param-head",
@@ -4066,7 +4105,7 @@ window.__ModuleLoader__.load({
4066
4105
  }, (0, react.createElement)("span", { className: "evolution-param-card-title" }, t("diagTitle")), summary === void 0 ? null : (0, react.createElement)("span", {
4067
4106
  className: "evo-diag-badge",
4068
4107
  "data-status": summary.status
4069
- }, t(SUMMARY_KEYS[summary.status], summary.count === 0 ? void 0 : { n: summary.count })), (0, react.createElement)("span", { className: "evolution-param-chevron" }, open ? "▲" : "▼"));
4108
+ }, t(SUMMARY_KEYS[summary.status], summary.count === 0 ? void 0 : { n: summary.count })), focusRow === void 0 ? null : (0, react.createElement)("span", { "data-role": "diag-focus" }, focusRow.label), (0, react.createElement)("span", { className: "evolution-param-chevron" }, open ? "▲" : "▼"));
4070
4109
  const runtime = (view) => view.runtime.length === 0 ? null : (0, react.createElement)("div", {}, (0, react.createElement)("h3", { className: "evolution-param-group" }, t("diagRuntimeTitle")), (0, react.createElement)("div", { className: "evo-diag-list" }, ...view.runtime.map((row) => (0, react.createElement)("div", {
4071
4110
  key: "runtime-" + row.key,
4072
4111
  className: "evo-diag-item",
@@ -4081,7 +4120,11 @@ window.__ModuleLoader__.load({
4081
4120
  fallback: props.fallback
4082
4121
  });
4083
4122
  const view = state.view;
4084
- return (0, react.createElement)("div", {}, (0, react.createElement)("p", { className: "evolution-param-note" }, t("diagSubtitle")), (0, react.createElement)("div", { className: "evolution-param-actions" }, (0, react.createElement)("button", {
4123
+ return (0, react.createElement)("div", {}, (0, react.createElement)("p", { className: "evolution-param-note" }, t("diagSubtitle")), refreshFailure === void 0 ? null : FailureBlock({
4124
+ failure: refreshFailure,
4125
+ t: translate,
4126
+ fallback: props.fallback
4127
+ }), (0, react.createElement)("div", { className: "evolution-param-actions" }, (0, react.createElement)("button", {
4085
4128
  type: "button",
4086
4129
  className: "evolution-param-button",
4087
4130
  onClick: refresh,
@@ -72,5 +72,5 @@ export declare function emptyState(text: string, key?: string): ReactNode;
72
72
  /** One notice about what just happened. */
73
73
  export declare function notice(text: string | undefined, error: boolean): ReactNode;
74
74
  /** The pane's heading and its one control. */
75
- export declare function panelHead(copy: Copy, onRefresh: () => void): ReactNode;
75
+ export declare function panelHead(copy: Copy, onRefresh: () => void, title?: string): ReactNode;
76
76
  //# sourceMappingURL=chrome.d.ts.map
@@ -5,7 +5,7 @@
5
5
  * description, so the settings surface can state both without a hand-written copy.
6
6
  */
7
7
  /** The family version this surface belongs to. */
8
- export declare const FAMILY_VERSION = "0.34.0";
8
+ export declare const FAMILY_VERSION = "0.35.0";
9
9
  /** What this surface is for, in one line. */
10
10
  export declare const PACKAGE_PURPOSE = "Web UI umbrella for the evolution family: settings and skill-history panels";
11
11
  //# sourceMappingURL=generated-about.d.ts.map
@@ -23,12 +23,12 @@ export declare const zh: {
23
23
  readonly projectionFailed: "这一块读设置时出错,已记入日志;其它参数不受影响";
24
24
  readonly readonly: "本次会话不允许写入设置(临时运行模式)";
25
25
  readonly apply: "保存";
26
- readonly reset: "恢复默认值";
26
+ readonly reset: "复位";
27
27
  readonly empty: "这里没有可改项";
28
28
  readonly changed: "{n} 项已覆盖";
29
29
  readonly discard: "放弃修改";
30
30
  readonly saving: "保存中…";
31
- readonly resetting: "恢复中…";
31
+ readonly resetting: "复位中…";
32
32
  readonly writeTargetHost: "保存去向:宿主配置(对所有会话生效)";
33
33
  readonly invalidNumber: "需要一个数字";
34
34
  readonly invalidSelect: "不在允许的取值里";
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@lmzhen/dsh-evolution-ui",
3
3
  "description": "Web UI umbrella for the evolution family: settings and skill-history panels (community build)",
4
- "version": "0.34.0",
4
+ "version": "0.35.0",
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },
@@ -45,9 +45,9 @@
45
45
  "react": "^18.2.0"
46
46
  },
47
47
  "dependencies": {
48
- "@lmzhen/dsh-evolution-client-kit": "^0.34.0",
49
- "@lmzhen/dsh-evolution-core": "^0.34.0",
50
- "@lmzhen/dsh-evolution-curator": "^0.34.0"
48
+ "@lmzhen/dsh-evolution-client-kit": "^0.35.0",
49
+ "@lmzhen/dsh-evolution-core": "^0.35.0",
50
+ "@lmzhen/dsh-evolution-curator": "^0.35.0"
51
51
  },
52
52
  "devDependencies": {
53
53
  "@types/react": "~18.3.1",