dsh-plugin-core-demo 0.0.1 → 0.1.3

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.
Files changed (3) hide show
  1. package/README.md +5 -1
  2. package/dist/client.js +368 -233
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -22,8 +22,12 @@ pnpm run build:demo
22
22
 
23
23
  ## 发布与安装
24
24
 
25
+ **不要在本目录手跑 `npm publish`。** 本包与核心共用同一个 `vX.Y.Z` tag,由
26
+ `.github/workflows/demo-publish.yml` 自动发布;版本必须与根 `package.json` 完全一致
27
+ (`test/version-sync.test.mjs` 与 CI 都校验,不一致直接失败)。
28
+
25
29
  ```bash
26
- npm publish --access public # 在本目录
30
+ git tag v0.1.3 && git push origin v0.1.3 # 在仓库根:一次 tag 发库 + 本包
27
31
  dsh plugin --profile web add dsh-plugin-core-demo
28
32
  ```
29
33
 
package/dist/client.js CHANGED
@@ -156,6 +156,8 @@ body{
156
156
  --tdt-radius-lg:var(--dsw-radius-lg,16px);
157
157
  --tdt-radius-xl:var(--dsw-radius-xl,20px);
158
158
  --tdt-radius-panel:var(--dsw-radius-panel,28px);
159
+ /* \u5168\u5706\uFF08\u80F6\u56CA\u6807\u7B7E\uFF09\uFF1A\u5BBF\u4E3B\u7684 radius \u6863\u6700\u5927\u53EA\u6709 28px\uFF0C\u6491\u4E0D\u6EE1 24px \u9AD8\u7684 chip */
160
+ --tdt-radius-pill:999px;
159
161
 
160
162
  /* \u2500\u2500 \u95F4\u8DDD\u56DB\u62CD\uFF08\u53EA\u8BB8\u7528\u8FD9\u56DB\u6863\uFF0C\u4E0D\u8BB8\u51FA\u73B0 5 / 7 / 9px\uFF09\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
161
163
  --tdt-space-1:4px;
@@ -446,26 +448,6 @@ var BUTTON_CSS = `
446
448
  .dsh-tdt-iconbtn:focus-visible{outline:2px solid var(--tdt-focus);outline-offset:2px;}
447
449
  .dsh-tdt-iconbtn:disabled{cursor:default;opacity:.4;}
448
450
 
449
- /* \u2500\u2500 \u4EA7\u51FA\u7269\u300C\u56FE\u6807 chip\u300DP2\uFF1A28\xD728 \u65B9\u89D2\u5C0F\u5E95\u677F + \u5B98\u65B9\u6587\u4EF6\u7C7B\u578B\u56FE\u6807 \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
450
- \u7528\u9014\uFF1A\u4EA7\u51FA\u7269\u5217\u8868\u91CC**\u53EA\u7ED9\u56FE\u6807**\u7684\u5C0F\u6309\u94AE\uFF08\u5361\u7247\u300C\u6267\u884C\u8BB0\u5F55\u300D\u9762\u677F\u3001\u6267\u884C\u8BB0\u5F55\u603B\u67E5\u8BE2\u9875\u3001\u5C55\u5F00\u533A\u90FD\u6302\u5B83\uFF09\u3002
451
- \u26A0\uFE0F \u5E95\u677F**\u5FC5\u987B\u8D70 class**\u2014\u2014inline background \u4F1A\u76D6\u6389 :hover\uFF08\u7528\u6237 2026-10-03 \u8E29\u8FC7\uFF09\u3002
452
- hover \u7528 \u300C--tdt-chip-bg-hover\u300D\uFF1A\u6D45\u8272\u66F4\u6DF1\u3001\u6697\u8272\u66F4\u4EAE\uFF08\u4E24\u7AEF\u90FD\u662F\u300C\u66F4\u660E\u663E\u300D\uFF09\uFF1B\u4E0D\u8BB8\u62FF
453
- \u300C--tdt-plate-hover\u300D \u9876\u2014\u2014\u6697\u8272\u4E0B\u53CD\u800C\u66F4\u6DE1\uFF0C\u9F20\u6807\u79FB\u4E0A\u53BB\u5E95\u677F\u5C31\u6D88\u5931\u4E86\u3002
454
- \u2705 **\u5168\u7AD9\u552F\u4E00\u5B9E\u73B0**\uFF082026-10-04 \u6536\u7F16\uFF09\uFF1A\u6B64\u524D\u5361\u7247\u9762\u677F\u4E0E\u6267\u884C\u8BB0\u5F55\u9875\u5404\u5199\u4E00\u4EFD**\u540C\u540D\u4E0D\u540C\u76AE**\u7684
455
- \u300C.dsh-tdt-rec-out\u300D\uFF0C\u4E24\u4EFD CSS \u90FD\u6CE8\u5165\u540C\u4E00\u9875\u9762 \u21D2 \u8C01\u540E\u6CE8\u518C\u8C01\u751F\u6548\u3001\u4E92\u76F8\u6C61\u67D3\uFF1B\u73B0\u5DF2\u6536\u6210\u8FD9\u4E00\u4EFD\u3002 */
456
- .dsh-tdt-chip{appearance:none;-webkit-appearance:none;box-sizing:border-box;display:inline-flex;align-items:center;justify-content:center;
457
- width:var(--tdt-control-h-md);height:var(--tdt-control-h-md);padding:0;border:none;border-radius:var(--tdt-radius-sm);
458
- background:transparent;color:var(--tdt-fg-2);font-family:inherit;line-height:0;cursor:pointer;
459
- transition:background-color var(--tdt-dur) var(--tdt-ease),color var(--tdt-dur) var(--tdt-ease);}
460
- /* \u5E95\u677F**\u5E73\u65F6\u900F\u660E\u3001\u9F20\u6807\u79FB\u4E0A\u53BB\u624D\u6D6E\u51FA\u6765**\uFF08\u7528\u6237 2026-10-04\uFF1A\u300C\u90A3\u4E2A\u5E26\u5E95\u8272\u7684\u6846\uFF0C\u9F20\u6807\u79FB\u4E0A\u53BB\u624D\u6709\u300D\uFF09\u3002
461
- \u53EA\u7ED9\u56FE\u6807\u3001\u6CA1\u6709\u6587\u5B57\u53EF\u8BFB \u21D2 hover \u7528\u66F4\u660E\u663E\u7684\u90A3\u6863\uFF08\u6D45\u8272\u66F4\u6DF1\u3001\u6697\u8272\u66F4\u4EAE\uFF0C\u4E24\u7AEF\u90FD\u662F\u300C\u66F4\u660E\u663E\u300D\uFF09\u3002 */
462
- .dsh-tdt-chip:hover:not(:disabled){background:var(--tdt-chip-bg-hover);}
463
- .dsh-tdt-chip:focus-visible{outline:2px solid var(--tdt-focus);outline-offset:1px;}
464
- /* \u4E0D\u53EF\u70B9\uFF08\u6CA1\u6709\u4F1A\u8BDD / \u9884\u89C8\u9762\u672A\u5C31\u4F4D\uFF09\uFF1A\u6CA1\u6709\u5E95\u677F\u3001\u6CA1\u6709\u624B\u6307\uFF0C\u522B\u7ED9\u5047\u5165\u53E3 */
465
- .dsh-tdt-chip:disabled{cursor:default;background:transparent;color:var(--tdt-fg-3);}
466
- /* \u6587\u5B57\u578B chip\uFF08\u300C\u2026\u300D / \u300C+N\u300D\uFF09\uFF1A\u4E0D\u56FA\u5B9A\u65B9\u5BBD\uFF0C\u6309\u5185\u5BB9\u6491\u5F00 */
467
- .dsh-tdt-chip--label{width:auto;padding:0 6px;font-size:var(--tdt-font-md);line-height:var(--tdt-line-md);}
468
-
469
451
  /* \u2500\u2500 \u884C\u5F0F\u6587\u4EF6\u6309\u94AE\uFF08\u56FE\u6807 + \u6587\u4EF6\u540D\uFF09P2\uFF1A**\u5168\u7AD9\u552F\u4E00\u5B9E\u73B0**\uFF082026-10-04 \u6536\u7F16\uFF09\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
470
452
  \u7528\u9014\uFF1A\u300C\u4EA7\u51FA\u7269 / \u9644\u4EF6\u300D\u90A3\u79CD**\u4E00\u884C\u4E00\u4E2A\u6587\u4EF6**\u7684\u6E05\u5355\u9879\uFF08\u57FA\u7840\u4FE1\u606F\u53F3\u680F\u4EA7\u51FA\u7269\u6E05\u5355\u3001\u9644\u4EF6\u533A\u3001
471
453
  \u6267\u884C\u8BB0\u5F55\u9875\u7684\u5C55\u5F00\u533A\uFF09\u3002\u5E73\u65F6\u900F\u660E\u3001**\u9F20\u6807\u79FB\u4E0A\u53BB\u624D\u51FA\u6D45\u5E95**\uFF08\u6CBF\u7528\u7528\u6237 2026-10-03 \u5B9A\u7684\u89C2\u611F\uFF09\u3002
@@ -484,7 +466,7 @@ var BUTTON_CSS = `
484
466
  padding:4px 6px;font-size:var(--tdt-font-xs);}
485
467
  .dsh-tdt-filechip--inline{display:inline-flex;align-items:center;gap:4px;padding:2px 6px;font-size:var(--tdt-font-sm);}
486
468
 
487
- @media (prefers-reduced-motion: reduce){.dsh-tdt-btn,.dsh-tdt-iconbtn,.dsh-tdt-chip,.dsh-tdt-filechip{transition:none;}}
469
+ @media (prefers-reduced-motion: reduce){.dsh-tdt-btn,.dsh-tdt-iconbtn,.dsh-tdt-filechip{transition:none;}}
488
470
  `;
489
471
  var FIELD_CSS = `
490
472
  /* \u2500\u2500 \u8F93\u5165\u7C7B P3 \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
@@ -739,6 +721,15 @@ var FEEDBACK_CSS = `
739
721
  border-bottom:1px solid var(--tdt-border-faint);color:var(--tdt-fg);font-size:14px;
740
722
  }
741
723
  .dsh-tdt-modal__title{flex:1;min-width:0}
724
+ /* \u5173\u95ED\u6309\u94AE\uFF1A24\xD724 \u65B9\u89D2\u56FE\u6807\u4F4D\uFF0C\u4E0D\u501F\u7528 Picker \u7684\u89E6\u53D1\u5668\u76AE\u80A4\uFF08\u90A3\u4EFD\u5E26 min-width:120px\uFF09\u3002 */
725
+ .dsh-tdt-modal__close{
726
+ display:inline-flex;align-items:center;justify-content:center;flex:none;
727
+ width:24px;height:24px;padding:0;border:none;border-radius:var(--tdt-radius-sm);
728
+ background:transparent;color:var(--tdt-fg-3);font-family:inherit;font-size:12px;line-height:1;cursor:pointer;
729
+ transition:background-color var(--tdt-dur-fast) var(--tdt-ease),color var(--tdt-dur-fast) var(--tdt-ease);
730
+ }
731
+ .dsh-tdt-modal__close:hover{background:var(--tdt-hover);color:var(--tdt-fg)}
732
+ .dsh-tdt-modal__close:focus-visible{outline:2px solid var(--tdt-focus);outline-offset:1px}
742
733
  .dsh-tdt-modal__body{flex:1;min-height:0;overflow:auto;padding:12px 14px}
743
734
  .dsh-tdt-modal__foot{
744
735
  display:flex;justify-content:flex-end;gap:8px;padding:10px 14px;
@@ -805,15 +796,24 @@ var CARD_CSS = `
805
796
  .dsh-tdt-card__caret.is-open{transform:rotate(180deg)}
806
797
  .dsh-tdt-card__panel{margin-top:8px;padding-top:8px;border-top:1px solid var(--tdt-border-faint)}
807
798
  `;
799
+
800
+ // dist/ui/chip-css.js
808
801
  var CHIP_CSS = `
809
802
  .dsh-tdt-chip{
810
- display:inline-flex;align-items:center;gap:4px;padding:1px 8px;border-radius:999px;
811
- background:var(--tdt-chip-bg);color:var(--tdt-fg);font-size:11px;line-height:18px;
803
+ display:inline-flex;align-items:center;justify-content:center;gap:4px;padding:1px 8px;
804
+ box-sizing:border-box;border-radius:var(--tdt-radius-pill,999px);border:none;
805
+ background:var(--tdt-chip-bg);color:var(--tdt-fg);
806
+ font-family:inherit;font-size:11px;line-height:18px;margin:0;
812
807
  /* 2026-10-18\uFF1Achip \u662F flex \u884C\u91CC\u7684\u5E38\u7528\u9879\uFF0C\u7981\u6B62\u88AB\u538B\u7F29\u6362\u884C\uFF08\u9884\u89C8\u7AD9\u51FA\u73B0\u8FC7\u6587\u5B57\u7AD6\u6392\u3001\u4E92\u76F8\u53E0\u538B\u7684\u6324\u538B\uFF09\u3002 */
813
- white-space:nowrap;flex:none;box-sizing:border-box;
814
- }
815
- .dsh-tdt-chip--clickable{cursor:pointer;border:none;font:inherit;font-size:11px}
816
- .dsh-tdt-chip--clickable:hover{background:var(--tdt-chip-bg-hover)}
808
+ white-space:nowrap;flex:none;
809
+ appearance:none;-webkit-appearance:none;
810
+ }
811
+ /* \u53EF\u70B9\u6001\uFF1Abutton \u6E32\u67D3\uFF08\u89C1 Chip.ts\uFF09\uFF0C\u5149\u6807 + hover \u52A0\u6DF1\u3002 */
812
+ .dsh-tdt-chip--clickable{cursor:pointer;transition:background-color var(--tdt-dur-fast) var(--tdt-ease);}
813
+ .dsh-tdt-chip--clickable:hover:not(:disabled){background:var(--tdt-chip-bg-hover)}
814
+ .dsh-tdt-chip:focus-visible{outline:2px solid var(--tdt-focus);outline-offset:1px}
815
+ .dsh-tdt-chip:disabled{cursor:default;color:var(--tdt-fg-3)}
816
+ @media (prefers-reduced-motion: reduce){.dsh-tdt-chip{transition:none}}
817
817
  `;
818
818
 
819
819
  // dist/explorer/explorer-css.js
@@ -1046,6 +1046,12 @@ var DICT = {
1046
1046
  }
1047
1047
  };
1048
1048
  var current2 = "zh";
1049
+ function setLocale(locale) {
1050
+ current2 = locale;
1051
+ }
1052
+ function getLocale() {
1053
+ return current2;
1054
+ }
1049
1055
  function t(key, vars) {
1050
1056
  const template = DICT[current2][key] ?? DICT.zh[key] ?? key;
1051
1057
  if (vars === void 0)
@@ -1306,7 +1312,7 @@ function Modal(props) {
1306
1312
  onClick: (e) => e.stopPropagation()
1307
1313
  }, props.hideHeader === true || props.title === void 0 && props.onClose === void 0 ? null : (0, import_react4.createElement)("div", { className: "dsh-tdt-modal__head" }, (0, import_react4.createElement)("div", { className: "dsh-tdt-modal__title" }, props.title ?? ""), props.onClose === void 0 ? null : (0, import_react4.createElement)("button", {
1308
1314
  type: "button",
1309
- className: "dsh-tdt-picker__trigger",
1315
+ className: "dsh-tdt-modal__close",
1310
1316
  "aria-label": tt("modalClose"),
1311
1317
  onClick: () => props.onClose?.()
1312
1318
  }, "\u2715")), (0, import_react4.createElement)("div", { className: "dsh-tdt-modal__body" }, props.children ?? null), props.footer === void 0 ? null : (0, import_react4.createElement)("div", { className: "dsh-tdt-modal__foot" }, props.footer)));
@@ -1367,12 +1373,11 @@ function showToast(message, opts) {
1367
1373
  el.className = `dsh-tdt-toast${variant === "info" ? "" : ` dsh-tdt-toast--${variant}`}`;
1368
1374
  el.textContent = message;
1369
1375
  host.appendChild(el);
1370
- const timer = setTimeout(() => {
1376
+ setTimeout(() => {
1371
1377
  el.remove();
1372
1378
  if (host.childElementCount === 0)
1373
1379
  host.remove();
1374
1380
  }, opts?.durationMs ?? DEFAULT_MS);
1375
- el.addEventListener("remove", () => clearTimeout(timer));
1376
1381
  }
1377
1382
  function ensureHost() {
1378
1383
  const found = document.getElementById(HOST_ID);
@@ -1743,11 +1748,255 @@ function NumberInput(props) {
1743
1748
  );
1744
1749
  }
1745
1750
 
1746
- // demo/sections/index.tsx
1751
+ // dist/utils/date.js
1752
+ function pad2(value) {
1753
+ return String(value).padStart(2, "0");
1754
+ }
1755
+ var FALLBACK = "\u2014";
1756
+ function formatDateTime(iso, opts) {
1757
+ const ms = Date.parse(iso);
1758
+ if (Number.isNaN(ms))
1759
+ return opts?.fallback ?? iso;
1760
+ const d = new Date(ms);
1761
+ const base = `${d.getFullYear()}-${pad2(d.getMonth() + 1)}-${pad2(d.getDate())} ${pad2(d.getHours())}:${pad2(d.getMinutes())}`;
1762
+ return opts?.seconds === true ? `${base}:${pad2(d.getSeconds())}` : base;
1763
+ }
1764
+ function formatYmd(iso, opts) {
1765
+ const ms = Date.parse(iso);
1766
+ if (Number.isNaN(ms))
1767
+ return opts?.fallback ?? FALLBACK;
1768
+ const d = new Date(ms);
1769
+ return `${d.getFullYear()}-${pad2(d.getMonth() + 1)}-${pad2(d.getDate())}`;
1770
+ }
1771
+ function formatClock(iso, opts) {
1772
+ const fb = opts?.fallback ?? "-";
1773
+ if (iso === null || iso === void 0 || iso === "")
1774
+ return fb;
1775
+ const ms = Date.parse(iso);
1776
+ if (Number.isNaN(ms))
1777
+ return fb;
1778
+ const d = new Date(ms);
1779
+ return `${pad2(d.getHours())}:${pad2(d.getMinutes())}:${pad2(d.getSeconds())}`;
1780
+ }
1781
+ function formatDurationHms(ms) {
1782
+ if (!Number.isFinite(ms) || ms < 0)
1783
+ return "-";
1784
+ const totalSec = Math.round(ms / 1e3);
1785
+ const h31 = Math.floor(totalSec / 3600);
1786
+ const m = Math.floor(totalSec % 3600 / 60);
1787
+ const s = totalSec % 60;
1788
+ return h31 > 0 ? `${h31}:${pad2(m)}:${pad2(s)}` : `${pad2(m)}:${pad2(s)}`;
1789
+ }
1790
+ function sameCalendarDay(a, b) {
1791
+ return a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth() && a.getDate() === b.getDate();
1792
+ }
1793
+ function relativePast(iso, nowMs, translate) {
1794
+ const tt = translate ?? t;
1795
+ const diff = nowMs - Date.parse(iso);
1796
+ if (Number.isNaN(diff) || !(diff >= 0))
1797
+ return tt("relNow");
1798
+ if (diff < 6e4)
1799
+ return tt("relJustNow");
1800
+ const minutes = Math.floor(diff / 6e4);
1801
+ if (minutes < 60)
1802
+ return tt("relMinutesAgo", { n: minutes });
1803
+ const hours = Math.floor(minutes / 60);
1804
+ if (hours < 24)
1805
+ return tt("relHoursAgo", { n: hours });
1806
+ const days = Math.floor(hours / 24);
1807
+ if (days < 7)
1808
+ return tt("relDaysAgo", { n: days });
1809
+ if (days < 30)
1810
+ return tt("relWeeksAgo", { n: Math.floor(days / 7) });
1811
+ const months = Math.floor(days / 30);
1812
+ if (months < 12)
1813
+ return tt("relMonthsAgo", { n: months });
1814
+ return tt("relYearsAgo", { n: Math.floor(days / 365) });
1815
+ }
1816
+ function relativeFuture(iso, nowMs, translate) {
1817
+ const tt = translate ?? t;
1818
+ const diff = Date.parse(iso) - nowMs;
1819
+ if (Number.isNaN(diff))
1820
+ return formatYmd(iso);
1821
+ if (diff <= 0)
1822
+ return tt("relNow");
1823
+ if (diff < 6e4)
1824
+ return tt("relInJustNow");
1825
+ const minutes = Math.floor(diff / 6e4);
1826
+ if (minutes < 60)
1827
+ return tt("relInMinutes", { n: minutes });
1828
+ const hours = Math.floor(minutes / 60);
1829
+ if (hours < 24)
1830
+ return tt("relInHours", { n: hours });
1831
+ const days = Math.floor(hours / 24);
1832
+ if (days < 30)
1833
+ return tt("relInDays", { n: days });
1834
+ const months = Math.floor(days / 30);
1835
+ if (months < 12)
1836
+ return tt("relInMonths", { n: months });
1837
+ return tt("relInYears", { n: Math.floor(days / 365) });
1838
+ }
1839
+ function formatRange(fromIso, toIso, opts) {
1840
+ const from = Date.parse(fromIso);
1841
+ const to = Date.parse(toIso);
1842
+ if (Number.isNaN(from) || Number.isNaN(to))
1843
+ return FALLBACK;
1844
+ const a = new Date(from);
1845
+ const b = new Date(to);
1846
+ const clock = (d) => opts?.seconds === true ? `${pad2(d.getHours())}:${pad2(d.getMinutes())}:${pad2(d.getSeconds())}` : `${pad2(d.getHours())}:${pad2(d.getMinutes())}`;
1847
+ if (sameCalendarDay(a, b))
1848
+ return `${clock(a)} \u2013 ${clock(b)}`;
1849
+ const day = (d) => `${pad2(d.getMonth() + 1)}-${pad2(d.getDate())}`;
1850
+ return `${day(a)} ${clock(a)} \u2013 ${day(b)} ${clock(b)}`;
1851
+ }
1852
+
1853
+ // dist/utils/number.js
1854
+ function formatBytes(bytes) {
1855
+ if (!Number.isFinite(bytes) || bytes <= 0)
1856
+ return "\u2014";
1857
+ if (bytes < 1024)
1858
+ return `${bytes} B`;
1859
+ const units = ["KB", "MB", "GB", "TB"];
1860
+ let value = bytes / 1024;
1861
+ let unit = 0;
1862
+ while (value >= 1024 && unit < units.length - 1) {
1863
+ value /= 1024;
1864
+ unit++;
1865
+ }
1866
+ return `${value >= 10 ? String(Math.round(value)) : value.toFixed(1)} ${units[unit]}`;
1867
+ }
1868
+
1869
+ // dist/utils/path.js
1870
+ var IMAGE_EXT = {
1871
+ png: "image/png",
1872
+ jpg: "image/jpeg",
1873
+ jpeg: "image/jpeg",
1874
+ gif: "image/gif",
1875
+ webp: "image/webp",
1876
+ bmp: "image/bmp",
1877
+ svg: "image/svg+xml",
1878
+ ico: "image/x-icon"
1879
+ };
1880
+ function mimeOf(path) {
1881
+ const ext = extOf(path);
1882
+ return ext === "" ? void 0 : IMAGE_EXT[ext];
1883
+ }
1884
+ function extOf(path) {
1885
+ const name = path.slice(path.lastIndexOf("/") + 1);
1886
+ const dot = name.lastIndexOf(".");
1887
+ return dot <= 0 ? "" : name.slice(dot + 1).toLowerCase();
1888
+ }
1889
+ function crumbsOf(path) {
1890
+ return path.split("/").filter((s) => s !== "");
1891
+ }
1892
+ function parentOf(path) {
1893
+ const cut = path.lastIndexOf("/");
1894
+ return cut < 0 ? "" : path.slice(0, cut);
1895
+ }
1896
+ function joinPath(dir, name) {
1897
+ return dir === "" ? name : `${dir}/${name}`;
1898
+ }
1899
+
1900
+ // packages/demo/src/sections/index.tsx
1747
1901
  var import_react30 = require("react");
1748
1902
 
1749
- // demo/sections/design.tsx
1903
+ // packages/demo/src/sections/design.tsx
1750
1904
  var import_react19 = require("react");
1905
+
1906
+ // packages/demo/src/i18n.ts
1907
+ var DICT2 = {
1908
+ zh: {
1909
+ sessionHint: "\u4E09\u79CD\u627F\u8F7D\uFF1Amodal / sidebar / page\uFF1Bsource \u662F mock \u7684\uFF1BrenderMessage \u53EF\u63A5\u7BA1\u5BCC\u5185\u5BB9",
1910
+ explorerHint: "\u9762\u5305\u5C51 + \u76EE\u5F55\u6811 + \u9884\u89C8\uFF1BworkspaceFiles \u662F mock \u7684\uFF08\u771F\u5B9E\u63D2\u4EF6\u4ECE ctx \u53D6\u51FA\u540E\u6CE8\u5165\uFF09",
1911
+ utilsHint: "\u89E3\u6790\u5931\u8D25\u4E0D\u629B\u9519\u3001\u7ED9\u515C\u5E95\u3001\u4E0D\u7F16\u9020\uFF1B\u6240\u6709\u51FD\u6570\u65E0 UI \u4F9D\u8D56",
1912
+ displayCardHint: "\u6392\u7248\u5B8C\u5168\u7531\u8C03\u7528\u65B9\u51B3\u5B9A\u2014\u2014\u771F\u5B9E\u63D2\u4EF6\u7684\u5F62\u6001\uFF1A\u6807\u9898\u884C + \u53F3\u4FA7\u5143\u4FE1\u606F + chips \u884C\uFF1Baccent \u4E94\u6863\u89C1\u4E0B\u65B9\u901F\u89C8",
1913
+ displayStripHint: "\u540C\u4E00\u4E2A\u8272\u6761\u673A\u5236\uFF0C\u5916\u89C2\u662F\u901A\u9AD8\u8D34\u9876\u5230\u5E95\u2014\u2014\u771F\u5B9E\u63D2\u4EF6\u7684\u5F62\u6001\uFF1A\u6807\u9898 + \u5143\u4FE1\u606F\u884C + \u53F3\u4FA7\u65F6\u95F4/\u64CD\u4F5C",
1914
+ displayChipHint: "chip \u53EA\u6709\u300C\u80F6\u56CA\u6807\u7B7E\u300D\u4E00\u5957\u76AE\u80A4\uFF1A\u5BBD\u5EA6\u6309\u6587\u5B57\u6491\u5F00\u3001\u4E0D\u6362\u884C\uFF1B\u6700\u540E\u4E00\u9897\u662F\u957F\u6587\u5B57\uFF0C\u82E5\u88AB\u538B\u6210 28px \u7AD6\u6392\u5C31\u662F\u53C8\u6DF7\u8FDB\u4E86\u56FE\u6807\u6309\u94AE\u7684\u5B9A\u5BBD\u89C4\u5219",
1915
+ feedbackModalHint: "\u81EA\u7ED8 overlay\uFF08\u4E0D\u7528 portal\uFF09\uFF1B\u70B9\u906E\u7F69 / Esc / \u2715 \u90FD\u80FD\u5173\u3002\u6807\u9898\u680F\u7684 \u2715 \u662F 24\xD724 \u56FE\u6807\u4F4D\uFF0C\u4E0D\u8BE5\u51FA\u73B0\u8FB9\u6846\u6216 120px \u5BBD\u7684\u5E95\u8272\u5757",
1916
+ feedbackToastHint: "\u547D\u4EE4\u5F0F showToast\uFF0C\u4E0D\u8981\u6C42\u6302\u7EC4\u4EF6",
1917
+ pickerHint: "\u5355\u9009 / \u591A\u9009 / \u4E0A\u9650 / \u641C\u7D22 / \u5206\u7EC4 / \u7A7A\u6001 / \u964D\u7EA7\u2014\u2014\u5168\u90E8\u53EF\u7528 props \u63A7\u5236",
1918
+ modelPickerHint: "flat \u4E00\u4E2A\u4E0B\u62C9 / cascade \u5148\u9009\u4F9B\u5E94\u5546\u518D\u9009\u6A21\u578B\u2014\u2014\u540C\u4E00\u4EFD\u6570\u636E\u4E24\u79CD\u5F62\u6001",
1919
+ workspacePickerHint: "\u6570\u636E\u8C03\u7528\u65B9\u7ED9\uFF08\u8981\u8DE8 host\u2194client \u8FB9\u754C\uFF0C\u7EC4\u4EF6\u53D6\u4E0D\u5230\uFF09",
1920
+ buttonHint: "variant \u56DB\u6863 \xD7 size \u4E09\u6863",
1921
+ inputHint: "Input / PrefixedInput / NumberInput / Textarea\uFF0C\u90FD\u652F\u6301 error \u63CF\u7EA2\uFF1B\u884C\u5C3E\u53EF\u6302 FieldHint \u95EE\u53F7\u63D0\u793A",
1922
+ checkboxHint: "\u5916\u89C2\u5BF9\u9F50\u771F\u5B9E\u63D2\u4EF6\uFF1A\u7070\u5E95 inset\uFF08\u65E0\u5916\u63CF\u8FB9\uFF09\uFF1B\u5E26\u63CF\u8FB9\u7684 default \u4EC5\u4F9B\u7279\u6B8A\u573A\u5408\uFF0C\u89C1\u4E0B",
1923
+ designTokenHint: "\u989C\u8272\u5168\u90E8\u6765\u81EA design \u7684 token\uFF1B\u5207\u6362\u53F3\u4E0A\u89D2\u660E\u6697\uFF0C\u4E0B\u9762\u4F1A\u8DDF\u7740\u53D8",
1924
+ designInjectHint: "\u63A7\u4EF6\u6E32\u67D3\u524D\u8C03\u4E00\u6B21 setStyleKit + ensureControls\uFF0Ctoken \u4E0E\u63A7\u4EF6 CSS \u7531 kit \u6CE8\u5165 <head>",
1925
+ fieldHintDate: "\u4EFB\u52A1\u81EA\u8BE5\u65E5\u8D77\u5F00\u59CB\u6267\u884C\u3002\u53EF\u63D0\u524D\u521B\u5EFA\u4EFB\u52A1\uFF0C\u81F3\u8BE5\u65E5\u81EA\u52A8\u5F00\u8DD1\uFF1B\u300C\u6BCF N \u5468\u300D\u4EA6\u81EA\u8BE5\u65E5\u8D77\u7B97\u9996\u5468\u3002",
1926
+ loadingNote: "Loading \u662F\u8D34\u5230\u4E3B\u5BB9\u5668\u53F3\u4E0B\u89D2\u7684\u6307\u793A\u5668\uFF08anchorId \u9ED8\u8BA4 dsh-tdt-main\uFF09\uFF0C\u6B64\u5904\u4E0D\u6E32\u67D3\u4EE5\u514D\u906E\u6321\u3002",
1927
+ secDesign: "\u8BBE\u8BA1\u57FA\u7840",
1928
+ secButtons: "\u6309\u94AE\u4E0E\u8F93\u5165",
1929
+ secPickers: "\u9009\u62E9\u5668",
1930
+ secFeedback: "\u5F39\u7A97\u4E0E\u53CD\u9988",
1931
+ secDisplay: "\u5361\u7247\u4E0E\u5C55\u793A",
1932
+ secUtils: "\u901A\u7528\u65B9\u6CD5",
1933
+ secExplorer: "\u5DE5\u4F5C\u533A\u6D4F\u89C8",
1934
+ secSession: "\u4F1A\u8BDD\u9884\u89C8",
1935
+ demoTokenPalette: "token \u8272\u677F",
1936
+ demoStyleInject: "\u6837\u5F0F\u6CE8\u5165\u673A\u5236",
1937
+ demoInputFamily: "Input \u5BB6\u65CF",
1938
+ demoUtilsTitle: "\u65E5\u671F / \u5B57\u7B26\u4E32 / \u5B57\u8282",
1939
+ demoCardTitle: "Card\uFF08\u5706\u89D2 + \u8FB9\u6846 + \u77ED\u8272\u6761\uFF09",
1940
+ demoStripTitle: "StripCard\uFF08\u65E0\u8FB9\u6846 + \u901A\u9AD8\u7AD6\u7EBF\uFF09",
1941
+ designInjectNote: "\u672C\u9884\u89C8\u63D2\u4EF6\u81EA\u5DF1\u5C31\u662F\u8FD9\u4E48\u505A\u521D\u59CB\u5316\u7684\u2014\u2014\u9884\u89C8\u4E0E\u771F\u5B9E\u63D2\u4EF6\u8D70\u540C\u4E00\u6761\u8DEF\u3002",
1942
+ pluginTitle: "\u7EC4\u4EF6\u9884\u89C8",
1943
+ pluginCardDesc: "\u6253\u5F00 dsh-plugin-core \u7684\u63A7\u4EF6\u4E0E\u4E1A\u52A1\u7EC4\u4EF6\u5C55\u793A\u9875",
1944
+ pluginCardOpen: "\u6253\u5F00 \u203A"
1945
+ },
1946
+ en: {
1947
+ sessionHint: "Three carriers: modal / sidebar / page; source is mocked; renderMessage can take over rich content",
1948
+ explorerHint: "Breadcrumb + directory tree + preview; workspaceFiles is mocked (a real plugin reads it from ctx and injects)",
1949
+ utilsHint: "No throw on parse failure \u2014 falls back gracefully and never fabricates; all functions are UI-free",
1950
+ displayCardHint: "Layout is entirely up to the caller \u2014 the real-plugin shape: title row + right-side meta + chips row; five accent tiers below",
1951
+ displayStripHint: "Same accent-bar mechanism, but full-height edge-to-edge \u2014 real-plugin shape: title + meta row + right-side time/actions",
1952
+ displayChipHint: "Chip has one pill skin only: width hugs the text, no wrap; the last one is long text \u2014 if squeezed into a 28px vertical stack, the icon-button fixed-width rule crept back in",
1953
+ feedbackModalHint: "Hand-rolled overlay (no portal); click backdrop / Esc / \u2715 all close it. The header \u2715 is a 24\xD724 icon slot \u2014 no border or 120px-wide color block should appear",
1954
+ feedbackToastHint: "Imperative showToast \u2014 no component mounting required",
1955
+ pickerHint: "Single / multi / max / search / grouped / empty / degraded \u2014 all driven by props",
1956
+ modelPickerHint: "flat: one dropdown / cascade: pick provider then model \u2014 same data, two shapes",
1957
+ workspacePickerHint: "Data is supplied by the caller (crosses the host\u2194client boundary; the component cannot fetch it)",
1958
+ buttonHint: "Four variants \xD7 three sizes",
1959
+ inputHint: "Input / PrefixedInput / NumberInput / Textarea, all support error highlighting; a FieldHint question-mark tip can hang at the row end",
1960
+ checkboxHint: "Looks match the real plugin: grey inset background (no outer border); the bordered default is for special cases only, see below",
1961
+ designTokenHint: "All colors come from design tokens; switch light/dark at top-right and these update with it",
1962
+ designInjectHint: "Call setStyleKit + ensureControls once before controls render; the kit injects tokens and control CSS into <head>",
1963
+ fieldHintDate: 'The task runs starting from this date. You can create it ahead of time and it auto-starts on that day; "every N weeks" also counts its first week from this date.',
1964
+ loadingNote: "Loading is an indicator pinned to the bottom-right of the main container (anchorId defaults to dsh-tdt-main); not rendered here to avoid covering content.",
1965
+ secDesign: "Design basics",
1966
+ secButtons: "Buttons & inputs",
1967
+ secPickers: "Pickers",
1968
+ secFeedback: "Modal & feedback",
1969
+ secDisplay: "Cards & display",
1970
+ secUtils: "Utilities",
1971
+ secExplorer: "Workspace browsing",
1972
+ secSession: "Session preview",
1973
+ demoTokenPalette: "Token palette",
1974
+ demoStyleInject: "Style injection",
1975
+ demoInputFamily: "Input family",
1976
+ demoUtilsTitle: "Date / String / Bytes",
1977
+ demoCardTitle: "Card (rounded + border + accent bar)",
1978
+ demoStripTitle: "StripCard (borderless + full-height stripe)",
1979
+ designInjectNote: "This preview plugin initializes itself exactly this way \u2014 preview and real plugin take the same path.",
1980
+ pluginTitle: "Component preview",
1981
+ pluginCardDesc: "Open the showcase of dsh-plugin-core controls and business components",
1982
+ pluginCardOpen: "Open \u203A"
1983
+ }
1984
+ };
1985
+ var boundT;
1986
+ function setDemoTranslate(fn) {
1987
+ boundT = fn;
1988
+ }
1989
+ function t2(key, vars) {
1990
+ if (boundT !== void 0) return boundT(key, vars);
1991
+ const template = DICT2[getLocale()][key] ?? DICT2.zh[key] ?? key;
1992
+ if (vars === void 0) return template;
1993
+ return template.replace(/\{(\w+)\}/g, (whole, name) => {
1994
+ const value = vars[name];
1995
+ return value === void 0 ? whole : String(value);
1996
+ });
1997
+ }
1998
+
1999
+ // packages/demo/src/sections/design.tsx
1751
2000
  var TOKENS = [
1752
2001
  { label: "business", cssVar: "--tdt-business" },
1753
2002
  { label: "success", cssVar: "--tdt-success" },
@@ -1767,24 +2016,24 @@ function DesignSection() {
1767
2016
  null,
1768
2017
  (0, import_react19.createElement)(
1769
2018
  Demo,
1770
- { title: "token \u8272\u677F", hint: "\u989C\u8272\u5168\u90E8\u6765\u81EA design \u7684 token\uFF1B\u5207\u6362\u53F3\u4E0A\u89D2\u660E\u6697\uFF0C\u4E0B\u9762\u4F1A\u8DDF\u7740\u53D8" },
2019
+ { title: t2("demoTokenPalette"), hint: t2("designTokenHint") },
1771
2020
  (0, import_react19.createElement)(
1772
2021
  "div",
1773
2022
  { style: { display: "flex", flexWrap: "wrap", gap: "10px" } },
1774
2023
  TOKENS.map(
1775
- (t2) => (0, import_react19.createElement)(
2024
+ (t3) => (0, import_react19.createElement)(
1776
2025
  "div",
1777
- { key: t2.cssVar, style: { width: "104px" } },
2026
+ { key: t3.cssVar, style: { width: "104px" } },
1778
2027
  (0, import_react19.createElement)("div", {
1779
2028
  style: {
1780
2029
  height: "40px",
1781
2030
  borderRadius: "6px",
1782
- background: `var(${t2.cssVar})`,
2031
+ background: `var(${t3.cssVar})`,
1783
2032
  border: "1px solid var(--tdt-border-faint)"
1784
2033
  }
1785
2034
  }),
1786
- (0, import_react19.createElement)("div", { style: { fontSize: "11px", marginTop: "4px" } }, t2.label),
1787
- (0, import_react19.createElement)("div", { style: { fontSize: "10px", color: "var(--tdt-fg-4)" } }, t2.cssVar)
2035
+ (0, import_react19.createElement)("div", { style: { fontSize: "11px", marginTop: "4px" } }, t3.label),
2036
+ (0, import_react19.createElement)("div", { style: { fontSize: "10px", color: "var(--tdt-fg-4)" } }, t3.cssVar)
1788
2037
  )
1789
2038
  )
1790
2039
  )
@@ -1792,8 +2041,8 @@ function DesignSection() {
1792
2041
  (0, import_react19.createElement)(
1793
2042
  Demo,
1794
2043
  {
1795
- title: "\u6837\u5F0F\u6CE8\u5165\u673A\u5236",
1796
- hint: "\u63A7\u4EF6\u6E32\u67D3\u524D\u8C03\u4E00\u6B21 setStyleKit + ensureControls\uFF0Ctoken \u4E0E\u63A7\u4EF6 CSS \u7531 kit \u6CE8\u5165 <head>",
2044
+ title: t2("demoStyleInject"),
2045
+ hint: t2("designInjectHint"),
1797
2046
  code: `import { createStyleKit } from 'dsh-plugin-core/design'
1798
2047
  import { ensureControls, setStyleKit } from 'dsh-plugin-core/ui'
1799
2048
 
@@ -1803,13 +2052,13 @@ ensureControls()`
1803
2052
  (0, import_react19.createElement)(
1804
2053
  "div",
1805
2054
  { style: { color: "var(--tdt-fg-3)", fontSize: "12px" } },
1806
- "\u672C\u9884\u89C8\u7AD9\u81EA\u5DF1\u5C31\u662F\u8FD9\u4E48\u505A\u521D\u59CB\u5316\u7684\uFF08\u89C1 demo/main.tsx\uFF09\u2014\u2014\u9884\u89C8\u4E0E\u771F\u5B9E\u63D2\u4EF6\u8D70\u540C\u4E00\u6761\u8DEF\u3002"
2055
+ t2("designInjectNote")
1807
2056
  )
1808
2057
  )
1809
2058
  );
1810
2059
  }
1811
2060
 
1812
- // demo/sections/buttons.tsx
2061
+ // packages/demo/src/sections/buttons.tsx
1813
2062
  var import_react20 = require("react");
1814
2063
  function ButtonsSection() {
1815
2064
  const [text, setText] = (0, import_react20.useState)("");
@@ -1823,7 +2072,7 @@ function ButtonsSection() {
1823
2072
  null,
1824
2073
  (0, import_react20.createElement)(
1825
2074
  Demo,
1826
- { title: "Button", hint: "variant \u56DB\u6863 \xD7 size \u4E09\u6863" },
2075
+ { title: "Button", hint: t2("buttonHint") },
1827
2076
  (0, import_react20.createElement)(
1828
2077
  "div",
1829
2078
  { style: { display: "flex", gap: "8px", flexWrap: "wrap", alignItems: "center" } },
@@ -1838,7 +2087,7 @@ function ButtonsSection() {
1838
2087
  ),
1839
2088
  (0, import_react20.createElement)(
1840
2089
  Demo,
1841
- { title: "Input \u5BB6\u65CF", hint: "Input / PrefixedInput / NumberInput / Textarea\uFF0C\u90FD\u652F\u6301 error \u63CF\u7EA2\uFF1B\u884C\u5C3E\u53EF\u6302 FieldHint \u95EE\u53F7\u63D0\u793A" },
2090
+ { title: t2("demoInputFamily"), hint: t2("inputHint") },
1842
2091
  (0, import_react20.createElement)(
1843
2092
  "div",
1844
2093
  { style: { display: "flex", flexDirection: "column", gap: "10px", maxWidth: "380px" } },
@@ -1847,7 +2096,7 @@ function ButtonsSection() {
1847
2096
  { style: { display: "flex", alignItems: "center", gap: "6px" } },
1848
2097
  (0, import_react20.createElement)("span", { style: { color: "var(--tdt-fg-2)", fontSize: "13px", flex: "none" } }, "\u5F00\u59CB\u65F6\u95F4"),
1849
2098
  (0, import_react20.createElement)(Input, { value: text, onChange: setText, placeholder: "\u9009\u62E9\u65E5\u671F" }),
1850
- (0, import_react20.createElement)(FieldHint, { text: "\u4EFB\u52A1\u81EA\u8BE5\u65E5\u8D77\u5F00\u59CB\u6267\u884C\u3002\u53EF\u63D0\u524D\u521B\u5EFA\u4EFB\u52A1\uFF0C\u81F3\u8BE5\u65E5\u81EA\u52A8\u5F00\u8DD1\uFF1B\u300C\u6BCF N \u5468\u300D\u4EA6\u81EA\u8BE5\u65E5\u8D77\u7B97\u9996\u5468\u3002" })
2099
+ (0, import_react20.createElement)(FieldHint, { text: t2("fieldHintDate") })
1851
2100
  ),
1852
2101
  (0, import_react20.createElement)(Input, { value: "bad value", onChange: () => {
1853
2102
  }, error: true, placeholder: "\u6821\u9A8C\u5931\u8D25\u6001" }),
@@ -1857,7 +2106,7 @@ function ButtonsSection() {
1857
2106
  ),
1858
2107
  (0, import_react20.createElement)(
1859
2108
  Demo,
1860
- { title: "Checkbox / Segmented", hint: "\u5916\u89C2\u5BF9\u9F50\u771F\u5B9E\u63D2\u4EF6\uFF1A\u7070\u5E95 inset\uFF08\u65E0\u5916\u63CF\u8FB9\uFF09\uFF1B\u5E26\u63CF\u8FB9\u7684 default \u4EC5\u4F9B\u7279\u6B8A\u573A\u5408\uFF0C\u89C1\u4E0B" },
2109
+ { title: "Checkbox / Segmented", hint: t2("checkboxHint") },
1861
2110
  (0, import_react20.createElement)(
1862
2111
  "div",
1863
2112
  { style: { display: "flex", flexDirection: "column", gap: "14px", alignItems: "flex-start" } },
@@ -1935,7 +2184,7 @@ function ButtonsSection() {
1935
2184
  );
1936
2185
  }
1937
2186
 
1938
- // demo/sections/pickers.tsx
2187
+ // packages/demo/src/sections/pickers.tsx
1939
2188
  var import_react21 = require("react");
1940
2189
  var MODELS = [
1941
2190
  {
@@ -1963,7 +2212,7 @@ function PickersSection() {
1963
2212
  null,
1964
2213
  (0, import_react21.createElement)(
1965
2214
  Demo,
1966
- { title: "Picker", hint: "\u5355\u9009 / \u591A\u9009 / \u4E0A\u9650 / \u641C\u7D22 / \u5206\u7EC4 / \u7A7A\u6001 / \u964D\u7EA7\u2014\u2014\u5168\u90E8\u53EF\u7528 props \u63A7\u5236" },
2215
+ { title: "Picker", hint: t2("pickerHint") },
1967
2216
  (0, import_react21.createElement)(
1968
2217
  "div",
1969
2218
  { style: { display: "flex", gap: "12px", flexWrap: "wrap", alignItems: "flex-start" } },
@@ -1998,7 +2247,7 @@ function PickersSection() {
1998
2247
  ),
1999
2248
  (0, import_react21.createElement)(
2000
2249
  Demo,
2001
- { title: "ModelPicker", hint: "flat \u4E00\u4E2A\u4E0B\u62C9 / cascade \u5148\u9009\u4F9B\u5E94\u5546\u518D\u9009\u6A21\u578B\u2014\u2014\u540C\u4E00\u4EFD\u6570\u636E\u4E24\u79CD\u5F62\u6001" },
2250
+ { title: "ModelPicker", hint: t2("modelPickerHint") },
2002
2251
  (0, import_react21.createElement)(
2003
2252
  "div",
2004
2253
  { style: { display: "flex", gap: "12px", flexWrap: "wrap" } },
@@ -2008,7 +2257,7 @@ function PickersSection() {
2008
2257
  ),
2009
2258
  (0, import_react21.createElement)(
2010
2259
  Demo,
2011
- { title: "WorkspacePicker / FilePicker", hint: "\u6570\u636E\u8C03\u7528\u65B9\u7ED9\uFF08\u8981\u8DE8 host\u2194client \u8FB9\u754C\uFF0C\u7EC4\u4EF6\u53D6\u4E0D\u5230\uFF09" },
2260
+ { title: "WorkspacePicker / FilePicker", hint: t2("workspacePickerHint") },
2012
2261
  (0, import_react21.createElement)(
2013
2262
  "div",
2014
2263
  { style: { display: "flex", gap: "12px", flexWrap: "wrap" } },
@@ -2029,7 +2278,7 @@ function PickersSection() {
2029
2278
  );
2030
2279
  }
2031
2280
 
2032
- // demo/sections/feedback.tsx
2281
+ // packages/demo/src/sections/feedback.tsx
2033
2282
  var import_react22 = require("react");
2034
2283
  function Boom() {
2035
2284
  throw new Error("\u6F14\u793A\uFF1A\u5B50\u7EC4\u4EF6\u629B\u9519\u88AB\u8FB9\u754C\u63A5\u4F4F");
@@ -2042,7 +2291,10 @@ function FeedbackSection() {
2042
2291
  null,
2043
2292
  (0, import_react22.createElement)(
2044
2293
  Demo,
2045
- { title: "Modal", hint: "\u81EA\u7ED8 overlay\uFF08\u4E0D\u7528 portal\uFF09\uFF1B\u70B9\u906E\u7F69 / Esc / \u2715 \u90FD\u80FD\u5173" },
2294
+ {
2295
+ title: "Modal",
2296
+ hint: t2("feedbackModalHint")
2297
+ },
2046
2298
  (0, import_react22.createElement)(
2047
2299
  "div",
2048
2300
  null,
@@ -2056,7 +2308,7 @@ function FeedbackSection() {
2056
2308
  ),
2057
2309
  (0, import_react22.createElement)(
2058
2310
  Demo,
2059
- { title: "toast", hint: "\u547D\u4EE4\u5F0F showToast\uFF0C\u4E0D\u8981\u6C42\u6302\u7EC4\u4EF6" },
2311
+ { title: "toast", hint: t2("feedbackToastHint") },
2060
2312
  (0, import_react22.createElement)(
2061
2313
  "div",
2062
2314
  { style: { display: "flex", gap: "8px" } },
@@ -2080,14 +2332,14 @@ function FeedbackSection() {
2080
2332
  (0, import_react22.createElement)(
2081
2333
  "div",
2082
2334
  { style: { color: "var(--tdt-fg-3)", fontSize: "12px" } },
2083
- "Loading \u662F\u8D34\u5230\u4E3B\u5BB9\u5668\u53F3\u4E0B\u89D2\u7684\u6307\u793A\u5668\uFF08anchorId \u9ED8\u8BA4 dsh-tdt-main\uFF09\uFF0C\u6B64\u5904\u4E0D\u6E32\u67D3\u4EE5\u514D\u906E\u6321\u3002"
2335
+ t2("loadingNote")
2084
2336
  )
2085
2337
  )
2086
2338
  )
2087
2339
  );
2088
2340
  }
2089
2341
 
2090
- // demo/sections/display.tsx
2342
+ // packages/demo/src/sections/display.tsx
2091
2343
  var import_react23 = require("react");
2092
2344
  function DisplaySection() {
2093
2345
  const [open, setOpen] = (0, import_react23.useState)(false);
@@ -2096,7 +2348,7 @@ function DisplaySection() {
2096
2348
  null,
2097
2349
  (0, import_react23.createElement)(
2098
2350
  Demo,
2099
- { title: "Card\uFF08\u5706\u89D2 + \u8FB9\u6846 + \u77ED\u8272\u6761\uFF09", hint: "\u6392\u7248\u5B8C\u5168\u7531\u8C03\u7528\u65B9\u51B3\u5B9A\u2014\u2014\u771F\u5B9E\u63D2\u4EF6\u7684\u5F62\u6001\uFF1A\u6807\u9898\u884C + \u53F3\u4FA7\u5143\u4FE1\u606F + chips \u884C\uFF1Baccent \u4E94\u6863\u89C1\u4E0B\u65B9\u901F\u89C8" },
2351
+ { title: t2("demoCardTitle"), hint: t2("displayCardHint") },
2100
2352
  (0, import_react23.createElement)(
2101
2353
  "div",
2102
2354
  { style: { display: "flex", flexDirection: "column", gap: "10px", maxWidth: "640px" } },
@@ -2140,7 +2392,7 @@ function DisplaySection() {
2140
2392
  ),
2141
2393
  (0, import_react23.createElement)(
2142
2394
  Demo,
2143
- { title: "StripCard\uFF08\u65E0\u8FB9\u6846 + \u901A\u9AD8\u7AD6\u7EBF\uFF09", hint: "\u540C\u4E00\u4E2A\u8272\u6761\u673A\u5236\uFF0C\u5916\u89C2\u662F\u901A\u9AD8\u8D34\u9876\u5230\u5E95\u2014\u2014\u771F\u5B9E\u63D2\u4EF6\u7684\u5F62\u6001\uFF1A\u6807\u9898 + \u5143\u4FE1\u606F\u884C + \u53F3\u4FA7\u65F6\u95F4/\u64CD\u4F5C" },
2395
+ { title: t2("demoStripTitle"), hint: t2("displayStripHint") },
2144
2396
  (0, import_react23.createElement)(
2145
2397
  "div",
2146
2398
  { style: { maxWidth: "640px", background: "var(--tdt-surface-sunken)", borderRadius: "8px", overflow: "hidden" } },
@@ -2184,16 +2436,20 @@ function DisplaySection() {
2184
2436
  ),
2185
2437
  (0, import_react23.createElement)(
2186
2438
  Demo,
2187
- { title: "Chip / SectionHead / MarqueeText / LiveText" },
2439
+ {
2440
+ title: "Chip / SectionHead / MarqueeText / LiveText",
2441
+ hint: t2("displayChipHint")
2442
+ },
2188
2443
  (0, import_react23.createElement)(
2189
2444
  "div",
2190
2445
  { style: { display: "flex", flexDirection: "column", gap: "12px" } },
2191
2446
  (0, import_react23.createElement)(
2192
2447
  "div",
2193
- { style: { display: "flex", gap: "6px", flexWrap: "wrap" } },
2448
+ { style: { display: "flex", gap: "6px", flexWrap: "wrap", alignItems: "center" } },
2194
2449
  (0, import_react23.createElement)(Chip, null, "#npm"),
2195
2450
  (0, import_react23.createElement)(Chip, null, "#\u6784\u5EFA"),
2196
- (0, import_react23.createElement)(Chip, { onClick: () => showToast("\u70B9\u4E86 chip") }, "#\u53EF\u70B9")
2451
+ (0, import_react23.createElement)(Chip, { onClick: () => showToast("\u70B9\u4E86 chip") }, "#\u53EF\u70B9"),
2452
+ (0, import_react23.createElement)(Chip, null, "\u4E00\u6574\u6BB5\u6BD4\u8F83\u957F\u7684\u6807\u7B7E\u6587\u5B57\uFF0C\u5BBD\u5EA6\u5E94\u8BE5\u8DDF\u7740\u6587\u5B57\u8D70")
2197
2453
  ),
2198
2454
  (0, import_react23.createElement)(SectionHead, { icon: "\u25B8", title: "\u5206\u533A\u6807\u9898", right: (0, import_react23.createElement)(Button, { size: "sm" }, "\u64CD\u4F5C") }),
2199
2455
  (0, import_react23.createElement)(
@@ -2207,128 +2463,8 @@ function DisplaySection() {
2207
2463
  );
2208
2464
  }
2209
2465
 
2210
- // demo/sections/utils.tsx
2466
+ // packages/demo/src/sections/utils.tsx
2211
2467
  var import_react24 = require("react");
2212
-
2213
- // dist/utils/date.js
2214
- function pad2(value) {
2215
- return String(value).padStart(2, "0");
2216
- }
2217
- var FALLBACK = "\u2014";
2218
- function formatDateTime(iso, opts) {
2219
- const ms = Date.parse(iso);
2220
- if (Number.isNaN(ms))
2221
- return opts?.fallback ?? iso;
2222
- const d = new Date(ms);
2223
- const base = `${d.getFullYear()}-${pad2(d.getMonth() + 1)}-${pad2(d.getDate())} ${pad2(d.getHours())}:${pad2(d.getMinutes())}`;
2224
- return opts?.seconds === true ? `${base}:${pad2(d.getSeconds())}` : base;
2225
- }
2226
- function formatYmd(iso, opts) {
2227
- const ms = Date.parse(iso);
2228
- if (Number.isNaN(ms))
2229
- return opts?.fallback ?? FALLBACK;
2230
- const d = new Date(ms);
2231
- return `${d.getFullYear()}-${pad2(d.getMonth() + 1)}-${pad2(d.getDate())}`;
2232
- }
2233
- function formatClock(iso, opts) {
2234
- const fb = opts?.fallback ?? "-";
2235
- if (iso === null || iso === void 0 || iso === "")
2236
- return fb;
2237
- const ms = Date.parse(iso);
2238
- if (Number.isNaN(ms))
2239
- return fb;
2240
- const d = new Date(ms);
2241
- return `${pad2(d.getHours())}:${pad2(d.getMinutes())}:${pad2(d.getSeconds())}`;
2242
- }
2243
- function formatDurationHms(ms) {
2244
- if (!Number.isFinite(ms) || ms < 0)
2245
- return "-";
2246
- const totalSec = Math.round(ms / 1e3);
2247
- const h31 = Math.floor(totalSec / 3600);
2248
- const m = Math.floor(totalSec % 3600 / 60);
2249
- const s = totalSec % 60;
2250
- return h31 > 0 ? `${h31}:${pad2(m)}:${pad2(s)}` : `${pad2(m)}:${pad2(s)}`;
2251
- }
2252
- function sameCalendarDay(a, b) {
2253
- return a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth() && a.getDate() === b.getDate();
2254
- }
2255
- function relativePast(iso, nowMs, translate) {
2256
- const tt = translate ?? t;
2257
- const diff = nowMs - Date.parse(iso);
2258
- if (Number.isNaN(diff) || !(diff >= 0))
2259
- return tt("relNow");
2260
- if (diff < 6e4)
2261
- return tt("relJustNow");
2262
- const minutes = Math.floor(diff / 6e4);
2263
- if (minutes < 60)
2264
- return tt("relMinutesAgo", { n: minutes });
2265
- const hours = Math.floor(minutes / 60);
2266
- if (hours < 24)
2267
- return tt("relHoursAgo", { n: hours });
2268
- const days = Math.floor(hours / 24);
2269
- if (days < 7)
2270
- return tt("relDaysAgo", { n: days });
2271
- if (days < 30)
2272
- return tt("relWeeksAgo", { n: Math.floor(days / 7) });
2273
- const months = Math.floor(days / 30);
2274
- if (months < 12)
2275
- return tt("relMonthsAgo", { n: months });
2276
- return tt("relYearsAgo", { n: Math.floor(days / 365) });
2277
- }
2278
- function relativeFuture(iso, nowMs, translate) {
2279
- const tt = translate ?? t;
2280
- const diff = Date.parse(iso) - nowMs;
2281
- if (Number.isNaN(diff))
2282
- return formatYmd(iso);
2283
- if (diff <= 0)
2284
- return tt("relNow");
2285
- if (diff < 6e4)
2286
- return tt("relInJustNow");
2287
- const minutes = Math.floor(diff / 6e4);
2288
- if (minutes < 60)
2289
- return tt("relInMinutes", { n: minutes });
2290
- const hours = Math.floor(minutes / 60);
2291
- if (hours < 24)
2292
- return tt("relInHours", { n: hours });
2293
- const days = Math.floor(hours / 24);
2294
- if (days < 30)
2295
- return tt("relInDays", { n: days });
2296
- const months = Math.floor(days / 30);
2297
- if (months < 12)
2298
- return tt("relInMonths", { n: months });
2299
- return tt("relInYears", { n: Math.floor(days / 365) });
2300
- }
2301
- function formatRange(fromIso, toIso, opts) {
2302
- const from = Date.parse(fromIso);
2303
- const to = Date.parse(toIso);
2304
- if (Number.isNaN(from) || Number.isNaN(to))
2305
- return FALLBACK;
2306
- const a = new Date(from);
2307
- const b = new Date(to);
2308
- const clock = (d) => opts?.seconds === true ? `${pad2(d.getHours())}:${pad2(d.getMinutes())}:${pad2(d.getSeconds())}` : `${pad2(d.getHours())}:${pad2(d.getMinutes())}`;
2309
- if (sameCalendarDay(a, b))
2310
- return `${clock(a)} \u2013 ${clock(b)}`;
2311
- const day = (d) => `${pad2(d.getMonth() + 1)}-${pad2(d.getDate())}`;
2312
- return `${day(a)} ${clock(a)} \u2013 ${day(b)} ${clock(b)}`;
2313
- }
2314
-
2315
- // dist/utils/number.js
2316
- function formatBytes(bytes) {
2317
- if (!Number.isFinite(bytes) || bytes <= 0)
2318
- return "\u2014";
2319
- if (bytes < 1024)
2320
- return `${bytes} B`;
2321
- const units = ["KB", "MB", "GB", "TB"];
2322
- let value = bytes / 1024;
2323
- let unit = 0;
2324
- while (value >= 1024 && unit < units.length - 1) {
2325
- value /= 1024;
2326
- unit++;
2327
- }
2328
- return `${value >= 10 ? String(Math.round(value)) : value.toFixed(1)} ${units[unit]}`;
2329
- }
2330
-
2331
- // demo/sections/utils.tsx
2332
2468
  var NOW = Date.parse("2026-10-18T12:00:00.000Z");
2333
2469
  var ROWS = [
2334
2470
  ["formatDateTime", formatDateTime("2026-10-18T09:30:05.000Z", { seconds: true }), "2026-10-18 09:30:05"],
@@ -2343,7 +2479,7 @@ var ROWS = [
2343
2479
  function UtilsSection() {
2344
2480
  return (0, import_react24.createElement)(
2345
2481
  Demo,
2346
- { title: "\u65E5\u671F / \u5B57\u7B26\u4E32 / \u5B57\u8282", hint: "\u89E3\u6790\u5931\u8D25\u4E0D\u629B\u9519\u3001\u7ED9\u515C\u5E95\u3001\u4E0D\u7F16\u9020\uFF1B\u6240\u6709\u51FD\u6570\u65E0 UI \u4F9D\u8D56" },
2482
+ { title: t2("demoUtilsTitle"), hint: t2("utilsHint") },
2347
2483
  (0, import_react24.createElement)(
2348
2484
  "table",
2349
2485
  { style: { borderCollapse: "collapse", fontSize: "13px" } },
@@ -2375,7 +2511,7 @@ function UtilsSection() {
2375
2511
  var th = { textAlign: "left", padding: "6px 14px 6px 0", color: "var(--tdt-fg-3)" };
2376
2512
  var td = { padding: "5px 14px 5px 0", borderTop: "1px solid var(--tdt-border-faint)" };
2377
2513
 
2378
- // demo/sections/explorer.tsx
2514
+ // packages/demo/src/sections/explorer.tsx
2379
2515
  var import_react27 = require("react");
2380
2516
 
2381
2517
  // dist/explorer/ExplorerPanel.js
@@ -2385,25 +2521,6 @@ var import_react26 = require("react");
2385
2521
  var import_react25 = require("react");
2386
2522
 
2387
2523
  // dist/explorer/types.js
2388
- var IMAGE_EXT = {
2389
- png: "image/png",
2390
- jpg: "image/jpeg",
2391
- jpeg: "image/jpeg",
2392
- gif: "image/gif",
2393
- webp: "image/webp",
2394
- bmp: "image/bmp",
2395
- svg: "image/svg+xml",
2396
- ico: "image/x-icon"
2397
- };
2398
- function mimeOf(path) {
2399
- const ext = extOf(path);
2400
- return ext === "" ? void 0 : IMAGE_EXT[ext];
2401
- }
2402
- function extOf(path) {
2403
- const name = path.slice(path.lastIndexOf("/") + 1);
2404
- const dot = name.lastIndexOf(".");
2405
- return dot <= 0 ? "" : name.slice(dot + 1).toLowerCase();
2406
- }
2407
2524
  function previewKindOf(path) {
2408
2525
  if (mimeOf(path) !== void 0)
2409
2526
  return "image";
@@ -2443,16 +2560,6 @@ function previewKindOf(path) {
2443
2560
  ]);
2444
2561
  return textLike.has(ext) ? "text" : "unsupported";
2445
2562
  }
2446
- function crumbsOf(path) {
2447
- return path.split("/").filter((s) => s !== "");
2448
- }
2449
- function parentOf(path) {
2450
- const cut = path.lastIndexOf("/");
2451
- return cut < 0 ? "" : path.slice(0, cut);
2452
- }
2453
- function joinPath(dir, name) {
2454
- return dir === "" ? name : `${dir}/${name}`;
2455
- }
2456
2563
 
2457
2564
  // dist/explorer/preview/index.js
2458
2565
  function FilePreview(props) {
@@ -2587,7 +2694,7 @@ function ExplorerPanel(props) {
2587
2694
  }))));
2588
2695
  }
2589
2696
 
2590
- // demo/mock.ts
2697
+ // packages/demo/src/mock.ts
2591
2698
  var TREE = {
2592
2699
  ".": [
2593
2700
  { name: "src", type: "directory" },
@@ -2722,14 +2829,14 @@ function delay(ms) {
2722
2829
  return new Promise((r) => setTimeout(r, ms));
2723
2830
  }
2724
2831
 
2725
- // demo/sections/explorer.tsx
2832
+ // packages/demo/src/sections/explorer.tsx
2726
2833
  function ExplorerSection() {
2727
2834
  const [selected, setSelected] = (0, import_react27.useState)(null);
2728
2835
  return (0, import_react27.createElement)(
2729
2836
  Demo,
2730
2837
  {
2731
2838
  title: "ExplorerPanel",
2732
- hint: "\u9762\u5305\u5C51 + \u76EE\u5F55\u6811 + \u9884\u89C8\uFF1BworkspaceFiles \u662F mock \u7684\uFF08\u771F\u5B9E\u63D2\u4EF6\u4ECE ctx \u53D6\u51FA\u540E\u6CE8\u5165\uFF09"
2839
+ hint: t2("explorerHint")
2733
2840
  },
2734
2841
  (0, import_react27.createElement)(
2735
2842
  "div",
@@ -2761,7 +2868,7 @@ function ExplorerSection() {
2761
2868
  );
2762
2869
  }
2763
2870
 
2764
- // demo/sections/session.tsx
2871
+ // packages/demo/src/sections/session.tsx
2765
2872
  var import_react29 = require("react");
2766
2873
 
2767
2874
  // dist/session/index.js
@@ -2824,14 +2931,14 @@ function SessionPreview(props) {
2824
2931
  return (0, import_react28.createElement)("div", { className: `dsh-tdt-ses dsh-tdt-ses--${variant}` }, props.onClose === void 0 ? null : (0, import_react28.createElement)("div", { className: "dsh-tdt-ses__head" }, (0, import_react28.createElement)("button", { type: "button", className: "dsh-tdt-exp__crumb", onClick: props.onClose }, "\u2715")), body);
2825
2932
  }
2826
2933
 
2827
- // demo/sections/session.tsx
2934
+ // packages/demo/src/sections/session.tsx
2828
2935
  function SessionSection() {
2829
2936
  const [open, setOpen] = (0, import_react29.useState)(false);
2830
2937
  return (0, import_react29.createElement)(
2831
2938
  Demo,
2832
2939
  {
2833
2940
  title: "SessionPreview",
2834
- hint: "\u4E09\u79CD\u627F\u8F7D\uFF1Amodal / sidebar / page\uFF1Bsource \u662F mock \u7684\uFF1BrenderMessage \u53EF\u63A5\u7BA1\u5BCC\u5185\u5BB9"
2941
+ hint: t2("sessionHint")
2835
2942
  },
2836
2943
  (0, import_react29.createElement)(
2837
2944
  "div",
@@ -2853,7 +2960,7 @@ function SessionSection() {
2853
2960
  }
2854
2961
  }
2855
2962
 
2856
- // demo/sections/index.tsx
2963
+ // packages/demo/src/sections/index.tsx
2857
2964
  function Demo(props) {
2858
2965
  return (0, import_react30.createElement)(
2859
2966
  "section",
@@ -2896,21 +3003,21 @@ function SectionHead2(props) {
2896
3003
  );
2897
3004
  }
2898
3005
  var ALL_SECTIONS = [
2899
- { id: "design", title: "\u8BBE\u8BA1\u57FA\u7840", render: () => (0, import_react30.createElement)(DesignSection, null) },
2900
- { id: "buttons", title: "\u6309\u94AE\u4E0E\u8F93\u5165", render: () => (0, import_react30.createElement)(ButtonsSection, null) },
2901
- { id: "pickers", title: "\u9009\u62E9\u5668", render: () => (0, import_react30.createElement)(PickersSection, null) },
2902
- { id: "feedback", title: "\u5F39\u7A97\u4E0E\u53CD\u9988", render: () => (0, import_react30.createElement)(FeedbackSection, null) },
2903
- { id: "display", title: "\u5361\u7247\u4E0E\u5C55\u793A", render: () => (0, import_react30.createElement)(DisplaySection, null) },
2904
- { id: "utils", title: "\u901A\u7528\u65B9\u6CD5", render: () => (0, import_react30.createElement)(UtilsSection, null) },
2905
- { id: "explorer", title: "\u5DE5\u4F5C\u533A\u6D4F\u89C8", render: () => (0, import_react30.createElement)(ExplorerSection, null) },
2906
- { id: "session", title: "\u4F1A\u8BDD\u9884\u89C8", render: () => (0, import_react30.createElement)(SessionSection, null) }
3006
+ { id: "design", titleKey: "secDesign", render: () => (0, import_react30.createElement)(DesignSection, null) },
3007
+ { id: "buttons", titleKey: "secButtons", render: () => (0, import_react30.createElement)(ButtonsSection, null) },
3008
+ { id: "pickers", titleKey: "secPickers", render: () => (0, import_react30.createElement)(PickersSection, null) },
3009
+ { id: "feedback", titleKey: "secFeedback", render: () => (0, import_react30.createElement)(FeedbackSection, null) },
3010
+ { id: "display", titleKey: "secDisplay", render: () => (0, import_react30.createElement)(DisplaySection, null) },
3011
+ { id: "utils", titleKey: "secUtils", render: () => (0, import_react30.createElement)(UtilsSection, null) },
3012
+ { id: "explorer", titleKey: "secExplorer", render: () => (0, import_react30.createElement)(ExplorerSection, null) },
3013
+ { id: "session", titleKey: "secSession", render: () => (0, import_react30.createElement)(SessionSection, null) }
2907
3014
  ];
2908
3015
  function Sections(props) {
2909
3016
  const current3 = ALL_SECTIONS.find((s) => s.id === props.active) ?? ALL_SECTIONS[0];
2910
3017
  return (0, import_react30.createElement)(
2911
3018
  "div",
2912
3019
  null,
2913
- (0, import_react30.createElement)(SectionHead2, { id: current3.id, title: current3.title }),
3020
+ (0, import_react30.createElement)(SectionHead2, { id: current3.id, title: t2(current3.titleKey) }),
2914
3021
  current3.render()
2915
3022
  );
2916
3023
  }
@@ -2921,11 +3028,23 @@ var ALIAS_TOKEN_NAMES = ["accent", "active", "border", "border-faint", "border-h
2921
3028
  // packages/demo/src/client/index.tsx
2922
3029
  var PANEL_ID = "dsh-plugin-core-demo";
2923
3030
  var PREFIX = "dshpc";
3031
+ var localeRuntime;
3032
+ function useLocaleTick() {
3033
+ const [, setTick] = (0, import_react31.useState)(0);
3034
+ (0, import_react31.useEffect)(() => {
3035
+ const rt = localeRuntime;
3036
+ if (rt === void 0) return;
3037
+ return rt.subscribe(() => {
3038
+ setTick((v) => v + 1);
3039
+ });
3040
+ }, []);
3041
+ }
2924
3042
  function aliasCss() {
2925
3043
  const decls = ALIAS_TOKEN_NAMES.map((n) => `--tdt-${n}:var(--${PREFIX}-${n})`);
2926
3044
  return `body{${decls.join(";")}}`;
2927
3045
  }
2928
3046
  function DemoPage() {
3047
+ useLocaleTick();
2929
3048
  const [active, setActive] = (0, import_react31.useState)(ALL_SECTIONS[0].id);
2930
3049
  return (0, import_react31.createElement)(
2931
3050
  "div",
@@ -2965,7 +3084,7 @@ function DemoPage() {
2965
3084
  marginBottom: "2px"
2966
3085
  }
2967
3086
  },
2968
- s.title
3087
+ t2(s.titleKey)
2969
3088
  )
2970
3089
  )
2971
3090
  ),
@@ -2998,14 +3117,14 @@ function OpenPreviewCard(props) {
2998
3117
  (0, import_react31.createElement)(
2999
3118
  "div",
3000
3119
  null,
3001
- (0, import_react31.createElement)("div", { style: { fontWeight: 600, fontSize: "14px" } }, "\u7EC4\u4EF6\u9884\u89C8"),
3120
+ (0, import_react31.createElement)("div", { style: { fontWeight: 600, fontSize: "14px" } }, t2("pluginTitle")),
3002
3121
  (0, import_react31.createElement)(
3003
3122
  "div",
3004
3123
  { style: { color: "var(--dshpc-fg-3)", fontSize: "12px", marginTop: "2px" } },
3005
- "\u6253\u5F00 dsh-plugin-core \u7684\u63A7\u4EF6\u4E0E\u4E1A\u52A1\u7EC4\u4EF6\u5C55\u793A\u9875"
3124
+ t2("pluginCardDesc")
3006
3125
  )
3007
3126
  ),
3008
- (0, import_react31.createElement)("span", { style: { color: "var(--dshpc-business)", fontSize: "13px" } }, "\u6253\u5F00 \u203A")
3127
+ (0, import_react31.createElement)("span", { style: { color: "var(--dshpc-business)", fontSize: "13px" } }, t2("pluginCardOpen"))
3009
3128
  );
3010
3129
  }
3011
3130
  function PanelIcon() {
@@ -3029,12 +3148,28 @@ function apply(ctx) {
3029
3148
  select(id);
3030
3149
  };
3031
3150
  });
3151
+ ctx.inject(["locale"], (sub) => {
3152
+ const loc = sub?.locale;
3153
+ if (loc === void 0) return;
3154
+ localeRuntime = loc;
3155
+ try {
3156
+ loc.register(PANEL_ID, "zh", { ...DICT2.zh });
3157
+ loc.register(PANEL_ID, "en", { ...DICT2.en });
3158
+ setDemoTranslate(loc.bind(PANEL_ID));
3159
+ } catch {
3160
+ }
3161
+ const sync = () => {
3162
+ setLocale(loc.getLocale().active === "en" ? "en" : "zh");
3163
+ };
3164
+ sync();
3165
+ loc.subscribe(sync);
3166
+ });
3032
3167
  ctx.inject(["slots"], (sub) => {
3033
3168
  const slots = sub.slots;
3034
3169
  if (slots === void 0) return;
3035
3170
  slots.inject("sidebar.panellist", () => {
3036
3171
  slots.register(
3037
- { name: "sidebar.panellist", id: PANEL_ID, order: 90, label: () => "\u7EC4\u4EF6\u9884\u89C8" },
3172
+ { name: "sidebar.panellist", id: PANEL_ID, order: 90, label: () => t2("pluginTitle") },
3038
3173
  PanelIcon
3039
3174
  );
3040
3175
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-plugin-core-demo",
3
- "version": "0.0.1",
3
+ "version": "0.1.3",
4
4
  "description": "dsh-plugin-core 的组件预览插件:装进 DSH 宿主后,在真实宿主环境里预览控件与业务组件",
5
5
  "keywords": ["deepseek", "harness", "dsh", "dsh-plugin", "dsh-plugin-core"],
6
6
  "homepage": "https://github.com/cq-guojia/dsh-plugin-core/tree/main/packages/demo",