dsh-calorie 0.3.25 → 0.3.27

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/dist/client.js CHANGED
@@ -727,7 +727,7 @@ window.__ModuleLoader__.load({
727
727
  optical: "光驱",
728
728
  other: "磁盘"
729
729
  };
730
- const S$1 = {
730
+ const S$2 = {
731
731
  scrim: {
732
732
  position: "fixed",
733
733
  inset: 0,
@@ -883,21 +883,21 @@ window.__ModuleLoader__.load({
883
883
  listing.crumbs.forEach((crumb, index) => {
884
884
  if (index > 0) parts.push(react.createElement("span", {
885
885
  key: "sep-" + crumb.path,
886
- style: S$1.crumbSep
886
+ style: S$2.crumbSep
887
887
  }, "›"));
888
888
  const isCurrent = crumb.path === listing.path;
889
889
  parts.push(react.createElement("button", {
890
890
  key: crumb.path,
891
891
  type: "button",
892
892
  style: {
893
- ...S$1.chromeButton,
893
+ ...S$2.chromeButton,
894
894
  fontWeight: isCurrent ? 700 : 400
895
895
  },
896
896
  title: crumb.path,
897
897
  onClick: () => onEnter(crumb.path)
898
898
  }, crumb.name));
899
899
  });
900
- return react.createElement("div", { style: S$1.crumbs }, parts);
900
+ return react.createElement("div", { style: S$2.crumbs }, parts);
901
901
  }
902
902
  /** 可跳转的根那一行(Windows 上的盘符等):**就是本机全部磁盘**,故不加行首说明。
903
903
  * **少于两个根就不画**:一个根没有「跳到别处」可言。 */
@@ -907,27 +907,27 @@ window.__ModuleLoader__.load({
907
907
  key: root.path,
908
908
  type: "button",
909
909
  style: {
910
- ...S$1.chromeButton,
911
- ...S$1.rootButton
910
+ ...S$2.chromeButton,
911
+ ...S$2.rootButton
912
912
  },
913
913
  title: ROOT_KIND_TEXT[root.kind] ?? ROOT_KIND_TEXT.other,
914
914
  onClick: () => onEnter(root.path)
915
915
  }, root.path));
916
- return react.createElement("div", { style: S$1.roots }, parts);
916
+ return react.createElement("div", { style: S$2.roots }, parts);
917
917
  }
918
918
  /** 一行子目录:点名字进它,点「选」把它当目标(「选」再点一次取消)。 */
919
919
  function entryRow(entry, selected, labels, onToggleSelect, onEnter) {
920
920
  return react.createElement("div", {
921
921
  key: entry.path,
922
922
  style: {
923
- ...S$1.row,
923
+ ...S$2.row,
924
924
  padding: 0,
925
- ...selected ? S$1.rowSelected : {}
925
+ ...selected ? S$2.rowSelected : {}
926
926
  }
927
927
  }, react.createElement("button", {
928
928
  type: "button",
929
929
  style: {
930
- ...S$1.row,
930
+ ...S$2.row,
931
931
  flex: 1,
932
932
  border: "none"
933
933
  },
@@ -935,7 +935,7 @@ window.__ModuleLoader__.load({
935
935
  }, "📁 " + entry.name), react.createElement("button", {
936
936
  type: "button",
937
937
  style: {
938
- ...S$1.button,
938
+ ...S$2.button,
939
939
  marginRight: 8,
940
940
  padding: "2px 8px"
941
941
  },
@@ -948,10 +948,10 @@ window.__ModuleLoader__.load({
948
948
  function createRow(labels, onName, onCancel, onCreate, creatingName) {
949
949
  if (creatingName === null) return null;
950
950
  return react.createElement("div", { style: {
951
- ...S$1.pathRow,
951
+ ...S$2.pathRow,
952
952
  borderTop: "1px solid var(--dsw-alias-border-l2, rgba(128,128,128,0.25))"
953
953
  } }, react.createElement("input", {
954
- style: S$1.input,
954
+ style: S$2.input,
955
955
  value: creatingName,
956
956
  placeholder: labels.newFolder,
957
957
  "aria-label": labels.newFolder,
@@ -962,11 +962,11 @@ window.__ModuleLoader__.load({
962
962
  }
963
963
  }), react.createElement("button", {
964
964
  type: "button",
965
- style: S$1.button,
965
+ style: S$2.button,
966
966
  onClick: () => onCreate(creatingName)
967
967
  }, labels.createConfirm), react.createElement("button", {
968
968
  type: "button",
969
- style: S$1.button,
969
+ style: S$2.button,
970
970
  onClick: onCancel
971
971
  }, labels.createCancel));
972
972
  }
@@ -995,8 +995,8 @@ window.__ModuleLoader__.load({
995
995
  const body = [];
996
996
  body.push(crumbRow(state, props.onEnter));
997
997
  body.push(rootsRow(state, props.onEnter));
998
- body.push(react.createElement("div", { style: S$1.pathRow }, react.createElement("input", {
999
- style: S$1.input,
998
+ body.push(react.createElement("div", { style: S$2.pathRow }, react.createElement("input", {
999
+ style: S$2.input,
1000
1000
  value: state.draft,
1001
1001
  placeholder: labels.pathPlaceholder,
1002
1002
  "aria-label": labels.pathPlaceholder,
@@ -1006,20 +1006,20 @@ window.__ModuleLoader__.load({
1006
1006
  }
1007
1007
  }), react.createElement("button", {
1008
1008
  type: "button",
1009
- style: S$1.button,
1009
+ style: S$2.button,
1010
1010
  onClick: props.onUp
1011
1011
  }, labels.up), react.createElement("button", {
1012
1012
  type: "button",
1013
- style: S$1.button,
1013
+ style: S$2.button,
1014
1014
  onClick: props.onCommitDraft
1015
1015
  }, labels.go)));
1016
1016
  body.push(react.createElement("div", {
1017
- style: S$1.list,
1017
+ style: S$2.list,
1018
1018
  role: "listbox",
1019
1019
  "aria-label": labels.title
1020
- }, rows.length === 0 ? react.createElement("div", { style: S$1.empty }, state.phase === "loading" ? labels.loading : labels.empty) : rows.map((entry) => entryRow(entry, state.selected === entry.path, labels, props.onSelect, props.onEnter))));
1020
+ }, rows.length === 0 ? react.createElement("div", { style: S$2.empty }, state.phase === "loading" ? labels.loading : labels.empty) : rows.map((entry) => entryRow(entry, state.selected === entry.path, labels, props.onSelect, props.onEnter))));
1021
1021
  body.push(createRow(labels, props.onDraft, () => props.onCreatingChange(null), props.onCreate, state.creating));
1022
- body.push(react.createElement("div", { style: S$1.footNote }, hidden > 0 ? react.createElement("label", { style: {
1022
+ body.push(react.createElement("div", { style: S$2.footNote }, hidden > 0 ? react.createElement("label", { style: {
1023
1023
  fontSize: 12,
1024
1024
  cursor: "pointer",
1025
1025
  marginRight: 10
@@ -1030,41 +1030,41 @@ window.__ModuleLoader__.load({
1030
1030
  }), " " + labels.showHidden(hidden)) : null, state.creating === null ? react.createElement("button", {
1031
1031
  type: "button",
1032
1032
  style: {
1033
- ...S$1.chromeButton,
1033
+ ...S$2.chromeButton,
1034
1034
  textDecoration: "underline"
1035
1035
  },
1036
1036
  onClick: () => props.onCreatingChange("")
1037
- }, labels.newFolder) : null, state.notice !== null ? react.createElement("div", { style: S$1.error }, state.notice) : null, state.phase === "failed" && state.failure !== null ? react.createElement("div", { style: S$1.error }, state.failure.message) : null));
1038
- body.push(react.createElement("div", { style: S$1.foot }, react.createElement("span", {
1039
- style: S$1.target,
1037
+ }, labels.newFolder) : null, state.notice !== null ? react.createElement("div", { style: S$2.error }, state.notice) : null, state.phase === "failed" && state.failure !== null ? react.createElement("div", { style: S$2.error }, state.failure.message) : null));
1038
+ body.push(react.createElement("div", { style: S$2.foot }, react.createElement("span", {
1039
+ style: S$2.target,
1040
1040
  title: target ?? ""
1041
1041
  }, target === null ? "" : labels.willPick + target), react.createElement("button", {
1042
1042
  type: "button",
1043
1043
  style: {
1044
- ...S$1.button,
1045
- ...target === null ? S$1.buttonOff : {}
1044
+ ...S$2.button,
1045
+ ...target === null ? S$2.buttonOff : {}
1046
1046
  },
1047
1047
  onClick: props.onPick
1048
1048
  }, labels.open), react.createElement("button", {
1049
1049
  type: "button",
1050
- style: S$1.button,
1050
+ style: S$2.button,
1051
1051
  onClick: props.onClose
1052
1052
  }, labels.cancel)));
1053
1053
  return react.createElement("div", {
1054
- style: S$1.scrim,
1054
+ style: S$2.scrim,
1055
1055
  role: "presentation",
1056
1056
  onMouseDown: (event) => {
1057
1057
  if (event.target === event.currentTarget) props.onClose();
1058
1058
  }
1059
1059
  }, react.createElement("div", {
1060
- style: S$1.dialog,
1060
+ style: S$2.dialog,
1061
1061
  role: "dialog",
1062
1062
  "aria-modal": true,
1063
1063
  "aria-label": labels.title
1064
- }, react.createElement("div", { style: S$1.head }, react.createElement("span", { style: S$1.title }, labels.title), react.createElement("button", {
1064
+ }, react.createElement("div", { style: S$2.head }, react.createElement("span", { style: S$2.title }, labels.title), react.createElement("button", {
1065
1065
  type: "button",
1066
1066
  style: {
1067
- ...S$1.button,
1067
+ ...S$2.button,
1068
1068
  marginLeft: "auto"
1069
1069
  },
1070
1070
  "aria-label": labels.close,
@@ -1089,6 +1089,84 @@ window.__ModuleLoader__.load({
1089
1089
  });
1090
1090
  }
1091
1091
  //#endregion
1092
+ //#region ../plugin-manager/dist/title-seal.js
1093
+ /** 共用标题 + 印章书签 · 纯组件(#996,不认任何一家)。
1094
+ *
1095
+ * 来源:原型 #995 变体 A(行尾悬签,人裁已定形)——标题左、签贴同行行尾向右探出。
1096
+ * 用它的有两家(共用件的第二个用法从这里长出来):`config-panel-view.ts` 的 `PanelBody`
1097
+ * (`product`=各家产品名/`purpose`=`配置`)与 `health-view.ts` 的 `HealthTable`
1098
+ * (`product`=各家产品名/`purpose`=`体检`)。别处要同形标题才用它,用不出来就留在那两家。
1099
+ *
1100
+ * 形状(逐值照原型锁死,不许自己重新设计):
1101
+ * 标题:同行双样式、无 `·`——`product` 700/1.15em 主色 + `purpose` 400/0.85em 次色,
1102
+ * 同行基线、`gap .5em`(16px 下=8px,满足地图 8px),整块 `h2`(`aria-label`=`product purpose`)。
1103
+ * 字号取原型锁(地图 Notes 写 1.08em/640 是 grill 共识早值,原型后锁 1.15em/700,以原型为准)。
1104
+ * 签:横向书签固定色 `#a5281b` 白字、`clip-path` 右端 V 尾切角 + 微旋 `-3°`、
1105
+ * `white-space:pre` 保空格、`role="note"` 纯展示不可点(无点击、无 tabindex)。
1106
+ * 印文由调用方交 `sealText`(显示形一律带空格大写 HELP,空格=U+0020,997 接线)。
1107
+ *
1108
+ * 纪律(#739/#941):
1109
+ * 零字族(无 `fontFamily`、无 `font:` 简写)、字号一律 em;颜色走 DSH 主题别名,
1110
+ * 唯签固定色沿 health 红黄固定色先例(纸变印不变,印不管纸面派生)。
1111
+ *
1112
+ * 本件是纯函数:吃 props 回元素树,不留状态、不取数。手写 `React.createElement`(本包 client 束禁 JSX)。
1113
+ */
1114
+ const S$1 = {
1115
+ /** 整块 `h2`:同行基线双样式容器(原型 `.titleblock`;`flex:1 1 auto` 把签顶到行尾,390 宽可换行不挤)。 */
1116
+ titleBlock: {
1117
+ display: "flex",
1118
+ flexWrap: "wrap",
1119
+ alignItems: "baseline",
1120
+ gap: "0 0.5em",
1121
+ margin: 0,
1122
+ fontSize: "1em",
1123
+ lineHeight: 1.5,
1124
+ flex: "1 1 auto",
1125
+ minWidth: "9em"
1126
+ },
1127
+ /** 产品名(原型 `.product`:700/1.15em 主色)。 */
1128
+ product: {
1129
+ fontSize: "1.15em",
1130
+ fontWeight: 700,
1131
+ color: "var(--dsw-alias-label-primary, #f9fafb)"
1132
+ },
1133
+ /** 用途(原型 `.purpose`:400/0.85em 次色)。 */
1134
+ purpose: {
1135
+ fontSize: "0.85em",
1136
+ fontWeight: 400,
1137
+ color: "var(--dsw-alias-label-secondary, #9a9a9a)"
1138
+ },
1139
+ /** 签(原型 `.seal`:固定印色+右端 V 尾+微旋,纯展示)。 */
1140
+ seal: {
1141
+ display: "inline-block",
1142
+ flexShrink: 0,
1143
+ fontSize: "0.78em",
1144
+ lineHeight: 1.6,
1145
+ color: "#fff",
1146
+ background: "#a5281b",
1147
+ padding: "0.15em 0.9em 0.15em 0.8em",
1148
+ whiteSpace: "pre",
1149
+ transform: "rotate(-3deg)",
1150
+ clipPath: "polygon(0 0, calc(100% - 0.65em) 0, 100% 50%, calc(100% - 0.65em) 100%, 0 100%)"
1151
+ }
1152
+ };
1153
+ /** 标题分层(同行双样式,无 `·`,整块 `h2`)。 */
1154
+ function TitleBlock(props) {
1155
+ const label = (props.product + " " + props.purpose).trim();
1156
+ return react.createElement("h2", {
1157
+ style: S$1.titleBlock,
1158
+ "aria-label": label
1159
+ }, react.createElement("span", { style: S$1.product }, props.product), react.createElement("span", { style: S$1.purpose }, props.purpose));
1160
+ }
1161
+ /** 印章书签(横向固定印,纯展示)。 */
1162
+ function Seal(props) {
1163
+ return react.createElement("span", {
1164
+ style: S$1.seal,
1165
+ role: "note",
1166
+ "aria-label": props.sealText
1167
+ }, props.sealText);
1168
+ }
1169
+ //#endregion
1092
1170
  //#region ../plugin-manager/dist/config-panel-view.js
1093
1171
  /** 共用配置面板 · 视图半:一行怎么画(`Row`)、整面怎么画(`PanelBody`)。
1094
1172
  *
@@ -1157,14 +1235,19 @@ window.__ModuleLoader__.load({
1157
1235
  color: "var(--dsw-alias-label-primary, #f9fafb)",
1158
1236
  boxShadow: "inset 0 1px 0 rgba(255,255,255,.06)"
1159
1237
  },
1160
- /** `.ic-head{display:flex;align-items:center;gap:10px;min-height:22px}`(徽标靠 `margin-left:auto` 右贴)。 */
1238
+ /** `.ic-head{display:flex;align-items:center;gap:10px;min-height:22px}`(徽标靠 `margin-left:auto` 右贴)。
1239
+ * #996:加 `flexWrap:wrap`——标题(`TitleBlock`,`flex:1 1 auto`+`minWidth:9em`)与签
1240
+ * (`flex-shrink:0`)在 390 宽下换行不挤(原型 A 行尾悬签);`gap`/`minHeight` 照 v3.1 不动。 */
1161
1241
  head: {
1162
1242
  display: "flex",
1243
+ flexWrap: "wrap",
1163
1244
  alignItems: "center",
1164
1245
  gap: 10,
1165
1246
  minHeight: 22
1166
1247
  },
1167
- /** `.ic-title{font-size:13.5px;font-weight:640}`——字号按 60 行那条锚点换算成 `1.08em`。 */
1248
+ /** `.ic-title{font-size:13.5px;font-weight:640}`——字号按 60 行那条锚点换算成 `1.08em`。
1249
+ * #996:卡片标题行改用 `TitleBlock`(见 `title-seal.ts`,原型 A 锁 1.15em/700+0.85em/400),
1250
+ * 这一格保留供附加块(`ConfigStyles` 键名不许改),头部本身不再用它。 */
1168
1251
  title: {
1169
1252
  fontSize: "1.08em",
1170
1253
  fontWeight: 640
@@ -1727,7 +1810,8 @@ window.__ModuleLoader__.load({
1727
1810
  function PanelBody(props) {
1728
1811
  const { state, title } = props;
1729
1812
  const surface = state.kind === "ready" ? state.surface : null;
1730
- const headText = title === void 0 ? "配置" : `${title} · 配置`;
1813
+ const product = title ?? "";
1814
+ const seal = props.sealText === void 0 || props.sealText === "" ? null : react.createElement(Seal, { sealText: props.sealText });
1731
1815
  const headDataDir = surface === null ? "" : surface.resolved?.["dbDir"] ?? surface.dataDir;
1732
1816
  const ready = state.kind === "ready";
1733
1817
  const dirtyCount = ready ? props.dirtyKeys.length : 0;
@@ -1739,7 +1823,10 @@ window.__ModuleLoader__.load({
1739
1823
  dirtyCount,
1740
1824
  saved: props.notice !== null
1741
1825
  });
1742
- const head = react.createElement("div", { style: S.head }, react.createElement("div", { style: S.title }, headText), react.createElement(PanelBadgeView, {
1826
+ const head = react.createElement("div", { style: S.head }, react.createElement(TitleBlock, {
1827
+ product,
1828
+ purpose: "配置"
1829
+ }), seal, react.createElement(PanelBadgeView, {
1743
1830
  kind: badge,
1744
1831
  dirtyCount
1745
1832
  }));
@@ -2144,6 +2231,7 @@ window.__ModuleLoader__.load({
2144
2231
  };
2145
2232
  return react.createElement(PanelBody, {
2146
2233
  title: props.title,
2234
+ sealText: props.sealText,
2147
2235
  items: props.items,
2148
2236
  state,
2149
2237
  draft,