dshmarket 1.4.0 → 1.5.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/client/client.js CHANGED
@@ -64,8 +64,23 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
64
64
  cmdDetails: "安装命令",
65
65
  catsMore: "更多分类",
66
66
  catsLess: "收起",
67
- sortHot: "最热",
68
- sortNew: "最新",
67
+ filter: "筛选",
68
+ filterSort: "排序字段",
69
+ filterDir: "排序方向",
70
+ filterTime: "发布时间范围",
71
+ sortStars: "Star 数",
72
+ sortAdded: "发布时间",
73
+ sortDesc: "降序",
74
+ sortAsc: "升序",
75
+ sortNewest: "最新",
76
+ sortOldest: "最旧",
77
+ timeAll: "全部时间",
78
+ timeDay: "最近 1 天",
79
+ timeWeek: "最近 7 天",
80
+ timeMonth: "最近 30 天",
81
+ timeQuarter: "最近 90 天",
82
+ timeYear: "最近 1 年",
83
+ published: "发布于",
69
84
  prevPage: "上一页",
70
85
  nextPage: "下一页",
71
86
  firstPage: "首页",
@@ -81,7 +96,20 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
81
96
  progressHint: "首次安装需要下载与解析依赖,大插件可能要 1-3 分钟",
82
97
  toastReady: "已装好并已生效",
83
98
  toastTheme: "已启用。到 设置 → 插件市场 → 主题 可随时切换",
84
- gotIt: "知道了"
99
+ gotIt: "知道了",
100
+ stateLive: "已生效(热加载)",
101
+ stateRestart: "已安装,重启后生效",
102
+ stateInert: "已安装但未成为 profile 层",
103
+ stateBroken: "安装完成但校验失败",
104
+ phaseResolving: "解析依赖",
105
+ phaseDownloading: "下载中",
106
+ phaseLinking: "链接依赖",
107
+ phaseBuilding: "运行构建脚本",
108
+ cancelling: "正在取消…",
109
+ packagesDone: "已处理 {0} 个包",
110
+ updatedLive: "✓ 已更新,已生效",
111
+ partialNote: "已取消,部分变更已写入",
112
+ actWhy: "为什么未生效?"
85
113
  };
86
114
  const en = {
87
115
  nav: "Plugin Market",
@@ -138,8 +166,23 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
138
166
  cmdDetails: "Install command",
139
167
  catsMore: "More",
140
168
  catsLess: "Less",
141
- sortHot: "Top",
142
- sortNew: "New",
169
+ filter: "Filter",
170
+ filterSort: "Sort field",
171
+ filterDir: "Order",
172
+ filterTime: "Released within",
173
+ sortStars: "Stars",
174
+ sortAdded: "Release date",
175
+ sortDesc: "Descending",
176
+ sortAsc: "Ascending",
177
+ sortNewest: "Newest",
178
+ sortOldest: "Oldest",
179
+ timeAll: "Any time",
180
+ timeDay: "Last day",
181
+ timeWeek: "Last 7 days",
182
+ timeMonth: "Last 30 days",
183
+ timeQuarter: "Last 90 days",
184
+ timeYear: "Last year",
185
+ published: "released",
143
186
  prevPage: "Previous",
144
187
  nextPage: "Next",
145
188
  firstPage: "First",
@@ -155,7 +198,20 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
155
198
  progressHint: "First installs download and resolve dependencies — large plugins can take 1-3 minutes",
156
199
  toastReady: "installed and live",
157
200
  toastTheme: "is now active. Switch any time in Settings → Plugin Market → Themes",
158
- gotIt: "Got it"
201
+ gotIt: "Got it",
202
+ stateLive: "Live (hot-loaded)",
203
+ stateRestart: "Installed — restart to apply",
204
+ stateInert: "Installed but not a profile-layer plugin",
205
+ stateBroken: "Installed but failed validation",
206
+ phaseResolving: "Resolving dependencies",
207
+ phaseDownloading: "Downloading",
208
+ phaseLinking: "Linking",
209
+ phaseBuilding: "Running build scripts",
210
+ cancelling: "Cancelling…",
211
+ packagesDone: "{0} packages processed",
212
+ updatedLive: "✓ Updated — live",
213
+ partialNote: "Cancelled — some changes were applied",
214
+ actWhy: "Why not live?"
159
215
  };
160
216
  //#endregion
161
217
  //#region src/client/market-data.ts
@@ -176,21 +232,40 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
176
232
  const desc = plugin.description && (plugin.description[lang] || plugin.description.en) || "";
177
233
  return /\b(tui|cli|tty|terminal)\b|终端|命令行/i.test(plugin.name + " " + desc);
178
234
  }
235
+ /** Days per TimeRange (`all` has no cutoff and is handled by the caller). */
236
+ const TIME_RANGE_DAYS = {
237
+ day: 1,
238
+ week: 7,
239
+ month: 30,
240
+ quarter: 90,
241
+ year: 365
242
+ };
243
+ /** True when `added` is a date within the last `days` days (inclusive). */
244
+ function withinDays(added, days) {
245
+ if (added === void 0 || added === "") return false;
246
+ const time = Date.parse(added);
247
+ if (Number.isNaN(time)) return false;
248
+ const age = Date.now() - time;
249
+ return age >= 0 && age <= days * 864e5;
250
+ }
179
251
  /**
180
- * The discover list: category filter, then search across name / owner /
181
- * localized description, then the selected sort. Pure — the section renders
182
- * exactly this.
252
+ * The discover list: category filter, then the published-within window, then
253
+ * search across name / owner / localized description, then the selected sort.
254
+ * Pure — the section renders exactly this.
183
255
  */
184
256
  function visiblePlugins(plugins, options) {
185
257
  const query = options.query.trim().toLowerCase();
186
258
  const list = plugins.filter((p) => {
187
259
  if (options.category !== "all" && p.category !== options.category) return false;
260
+ if (options.sinceDays !== void 0 && !withinDays(p.added, options.sinceDays)) return false;
188
261
  if (query === "") return true;
189
262
  const desc = p.description && (p.description[options.lang] || p.description.en) || "";
190
263
  return p.name.toLowerCase().includes(query) || p.owner.toLowerCase().includes(query) || desc.toLowerCase().includes(query);
191
264
  });
192
- if (options.sort === "hot") return [...list].sort((a, b) => (b.stars ?? -1) - (a.stars ?? -1));
193
- if (options.sort === "new") return [...list].sort((a, b) => String(b.added).localeCompare(String(a.added)));
265
+ if (options.sort === "stars-desc") return [...list].sort((a, b) => (b.stars ?? -1) - (a.stars ?? -1));
266
+ if (options.sort === "stars-asc") return [...list].sort((a, b) => (a.stars ?? -1) - (b.stars ?? -1));
267
+ if (options.sort === "added-desc") return [...list].sort((a, b) => String(b.added).localeCompare(String(a.added)));
268
+ if (options.sort === "added-asc") return [...list].sort((a, b) => String(a.added).localeCompare(String(b.added)));
194
269
  return list;
195
270
  }
196
271
  /** The themes tab listing: theme category only, most-starred first. */
@@ -317,7 +392,7 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
317
392
  }
318
393
  //#endregion
319
394
  //#region \0dsh-css:/home/runner/work/dsh-market/dsh-market/src/client/Market.module.css.mjs
320
- const css = ".eGUBIq_root{min-width:0;height:100%;color:var(--dsw-alias-label-primary,#1f2328);flex-direction:column;display:flex;position:relative}.eGUBIq_head{flex-direction:column;gap:12px;padding:4px 4px 12px;display:flex}.eGUBIq_title{margin:0;font-size:16px;font-weight:500;line-height:24px}.eGUBIq_sub{color:var(--dsw-alias-label-tertiary,#8b93a1);margin:0;font-size:14px;line-height:22px}.eGUBIq_searchInline{flex-shrink:0;width:200px;margin-bottom:6px}.eGUBIq_tabs{border-bottom:1px solid var(--dsw-alias-border-l2,#e5e7eb);align-items:flex-end;gap:2px;display:flex}.eGUBIq_tab{font:inherit;color:var(--dsw-alias-label-secondary,#6b7280);cursor:pointer;white-space:nowrap;background:0 0;border:none;border-bottom:2px solid #0000;padding:7px 12px;font-size:13px}.eGUBIq_tab.eGUBIq_on{color:var(--dsw-alias-brand-primary,#4f6ef7);border-bottom-color:var(--dsw-alias-brand-primary,#4f6ef7);font-weight:600}.eGUBIq_restart{background:var(--dsw-alias-bg-layer-2,#fdf3e3);border:1px solid var(--dsw-alias-border-l2,#f3e3c3);border-radius:8px;align-items:center;gap:8px;margin:0;padding:8px 12px;font-size:12px;display:flex}.eGUBIq_body{flex:1;padding:12px 4px 24px;overflow-x:hidden;overflow-y:auto}.eGUBIq_cats{z-index:5;background:var(--dsw-alias-bg-layer-2,#f7f8fa);margin:-12px -4px 2px;padding:12px 4px 4px;position:sticky;top:-13px}.eGUBIq_catsRow{align-items:flex-start;gap:8px;display:flex;position:relative}.eGUBIq_sort{background:var(--dsw-alias-bg-layer-1,#fff);border:1px solid var(--dsw-alias-border-l1,#e5e7eb);border-radius:8px;flex-shrink:0;gap:2px;padding:2px;display:flex}.eGUBIq_sort button{font:inherit;color:var(--dsw-alias-label-secondary,#6b7280);cursor:pointer;background:0 0;border:none;border-radius:6px;padding:3px 10px;font-size:12px}.eGUBIq_sort button.eGUBIq_on{background:var(--dsw-alias-bg-layer-1,#fff);color:var(--dsw-alias-label-primary,#1f2328);font-weight:600;box-shadow:0 1px 3px #00000014}.eGUBIq_star{color:var(--dsw-alias-label-secondary,#9ca3af);font-size:11px}.eGUBIq_top{z-index:20;border:1px solid var(--dsw-alias-border-l1,#e5e7eb);background:var(--dsw-alias-bg-layer-1,#fff);width:38px;height:38px;color:var(--dsw-alias-label-secondary,#6b7280);cursor:pointer;border-radius:99px;font-size:16px;position:absolute;bottom:18px;right:18px;box-shadow:0 4px 14px #0000001f}.eGUBIq_top:hover{color:var(--dsw-alias-brand-primary,#4f6ef7)}.eGUBIq_tag{border:1px solid var(--dsw-alias-border-l3,#d9dde3);color:var(--dsw-alias-label-secondary,#6b7280);border-radius:4px;flex-shrink:0;padding:1px 6px;font-size:11px;line-height:16px}.eGUBIq_okState{color:var(--dsw-alias-state-success-primary,#16a34a);white-space:nowrap;font-size:12px;font-weight:600}.eGUBIq_dangerBtn.eGUBIq_dangerBtn{border-color:var(--dsw-alias-state-error-primary,#dc2626);color:var(--dsw-alias-state-error-primary,#dc2626)}.eGUBIq_dangerArmed.eGUBIq_dangerArmed{background:var(--dsw-alias-state-error-primary,#dc2626);color:#fff}.eGUBIq_warnBtn.eGUBIq_warnBtn{background:var(--dsw-alias-state-warn-primary,#ea580c);color:#fff}.eGUBIq_catsWrap{flex-wrap:wrap;flex:1;align-items:center;gap:6px;min-width:0;display:flex}.eGUBIq_catsCollapsed{max-height:62px;overflow:hidden}.eGUBIq_catsToggle.eGUBIq_catsToggle{height:26px;min-height:26px;color:var(--dsw-alias-label-secondary,#6b7280);padding:0 6px}.eGUBIq_cmdDetails{margin:0}.eGUBIq_cmdSummary{cursor:pointer;width:fit-content;color:var(--dsw-alias-label-secondary,#6b7280);border-radius:6px;align-items:center;gap:6px;margin-left:-4px;padding:2px 4px;font-size:12px;font-weight:500;line-height:18px;list-style:none;display:flex}.eGUBIq_cmdSummary::-webkit-details-marker{display:none}.eGUBIq_cmdSummary:before{content:\"\";border-bottom:1.5px solid;border-right:1.5px solid;width:5px;height:5px;transition:transform .12s;transform:rotate(-45deg)translate(-1px,-1px)}.eGUBIq_cmdDetails[open]>.eGUBIq_cmdSummary:before{transform:rotate(45deg)translate(-1px,-1px)}.eGUBIq_cmdSummary:hover{color:var(--dsw-alias-label-primary,#1f2328)}.eGUBIq_cmd{background:var(--dsw-alias-bg-layer-2,#f3f4f6);word-break:break-all;border-radius:6px;margin:8px 0 0;padding:8px 10px;font-family:ui-monospace,Menlo,monospace;font-size:11px;line-height:18px}.eGUBIq_warnLine{color:var(--dsw-alias-state-warn-primary,#b45309);margin:0;font-size:12px;font-weight:600;line-height:18px}.eGUBIq_modalNote{color:var(--dsw-alias-label-tertiary,#8b93a1);margin:12px 0 0;font-size:12px;line-height:18px}.eGUBIq_grid{grid-template-columns:repeat(auto-fill,minmax(280px,1fr));gap:12px;display:grid}.eGUBIq_sect{color:var(--dsw-alias-label-secondary,#6b7280);margin:14px 2px 8px;font-size:12px;font-weight:600}.eGUBIq_sect:first-child{margin-top:2px}.eGUBIq_swatches{border:1px solid var(--dsw-alias-border-l2,#e5e7eb);border-radius:8px;gap:0;height:34px;display:flex;overflow:hidden}.eGUBIq_themesGrid{margin-bottom:12px}.eGUBIq_swatches i{flex:1}.eGUBIq_card{background:var(--dsw-alias-bg-layer-1,#fff);border:1px solid var(--dsw-alias-border-l2,#e5e7eb);border-radius:12px;flex-direction:column;gap:12px;padding:12px 14px;display:flex}.eGUBIq_row1{align-items:center;gap:10px;min-width:0;display:flex}.eGUBIq_av{color:#fff;object-fit:cover;background:var(--dsw-alias-bg-layer-2,#f3f4f6);border-radius:8px;flex-shrink:0;place-items:center;width:32px;height:32px;font-size:14px;font-weight:700;display:grid}.eGUBIq_nm{text-overflow:ellipsis;white-space:nowrap;font-size:14px;font-weight:500;line-height:22px;overflow:hidden}.eGUBIq_owner{color:var(--dsw-alias-label-secondary,#9ca3af);font-size:11px}.eGUBIq_desc{color:var(--dsw-alias-label-tertiary,#8b93a1);min-height:36px;margin:0;font-size:12px;line-height:18px}.eGUBIq_foot{align-items:center;gap:8px;margin-top:auto;display:flex}.eGUBIq_grow{flex:1}.eGUBIq_titleRow{align-items:center;gap:10px;display:flex}.eGUBIq_descTight{min-height:0}.eGUBIq_src{color:var(--dsw-alias-label-secondary,#9ca3af);font-size:11px;text-decoration:none}.eGUBIq_src:hover{color:var(--dsw-alias-brand-primary,#4f6ef7)}.eGUBIq_dot{vertical-align:2px;margin-left:5px}.eGUBIq_loading{color:var(--dsw-alias-label-secondary,#9ca3af);flex-direction:column;align-items:center;gap:12px;padding:48px;font-size:13px;display:flex}.eGUBIq_spin{border:3px solid var(--dsw-alias-border-l1,#e5e7eb);border-top-color:var(--dsw-alias-brand-primary,#4f6ef7);border-radius:99px;width:22px;height:22px;animation:.8s linear infinite eGUBIq_sp}@keyframes eGUBIq_sp{to{transform:rotate(360deg)}}.eGUBIq_progress{background:var(--dsw-alias-bg-layer-2,#f3f4f6);border:1px solid var(--dsw-alias-border-l2,#e5e7eb);color:var(--dsw-alias-label-secondary,#6b7280);border-radius:8px;flex-wrap:wrap;align-items:center;gap:9px;margin:0;padding:8px 12px;font-size:12px;display:flex}.eGUBIq_bar{background:var(--dsw-alias-border-l1,#e5e7eb);border-radius:99px;width:100%;height:4px;overflow:hidden}.eGUBIq_barFill{background:var(--dsw-alias-brand-primary,#4f6ef7);border-radius:99px;height:100%;transition:width .6s}.eGUBIq_barWave{width:30%;animation:1.2s ease-in-out infinite eGUBIq_dshmSlide}@keyframes eGUBIq_dshmSlide{0%{margin-left:-30%}to{margin-left:100%}}.eGUBIq_irow .eGUBIq_progress{margin-top:8px}.eGUBIq_progress .eGUBIq_spin{border-width:2px;flex-shrink:0;width:14px;height:14px}.eGUBIq_progress code{text-overflow:ellipsis;white-space:nowrap;font-family:ui-monospace,Menlo,monospace;font-size:11px;overflow:hidden}.eGUBIq_empty{color:var(--dsw-alias-label-secondary,#9ca3af);text-align:center;padding:32px;font-size:13px}.eGUBIq_err{color:var(--dsw-alias-state-error-primary,#dc2626);white-space:pre-wrap;word-break:break-all;margin:8px 0;font-size:12px}.eGUBIq_irow{background:var(--dsw-alias-bg-layer-1,#fff);border:1px solid var(--dsw-alias-border-l2,#e5e7eb);border-radius:12px;align-items:center;gap:10px;margin-bottom:8px;padding:12px 14px;display:flex}.eGUBIq_irow>.eGUBIq_src,.eGUBIq_irow>.eGUBIq_owner,.eGUBIq_dangerBtn.eGUBIq_dangerBtn,.eGUBIq_warnBtn.eGUBIq_warnBtn,.eGUBIq_dangerArmed.eGUBIq_dangerArmed{white-space:nowrap;flex-shrink:0}.eGUBIq_spec{color:var(--dsw-alias-label-secondary,#9ca3af);font-family:ui-monospace,Menlo,monospace;font-size:11px}.eGUBIq_staleAction{margin-top:8px}.eGUBIq_pct{color:var(--dsw-alias-label-secondary,#6b7280);flex-shrink:0;font-size:11px;font-weight:600}.eGUBIq_cancelBtn{border:1px solid var(--dsw-alias-border-l2,#e5e7eb);background:var(--dsw-alias-bg-layer-1,#fff);color:var(--dsw-alias-label-secondary,#6b7280);font:inherit;cursor:pointer;white-space:nowrap;border-radius:6px;flex-shrink:0;padding:2px 10px;font-size:11px;line-height:16px}.eGUBIq_cancelBtn:hover{color:var(--dsw-alias-state-error-primary,#dc2626);border-color:var(--dsw-alias-state-error-primary,#dc2626)}.eGUBIq_pager{flex-wrap:wrap;justify-content:space-between;align-items:center;gap:12px;margin:16px 0 4px;display:flex}.eGUBIq_pagerPages{flex-wrap:wrap;flex:1;justify-content:center;align-items:center;gap:6px;min-width:0;display:flex}.eGUBIq_pagerSize{flex-shrink:0;align-items:center;gap:4px;display:flex}.eGUBIq_sizeLabel{color:var(--dsw-alias-label-secondary,#6b7280);font-size:12px}.eGUBIq_sizeBtn{border:1px solid var(--dsw-alias-border-l2,#e5e7eb);background:var(--dsw-alias-bg-layer-1,#fff);color:var(--dsw-alias-label-secondary,#6b7280);font:inherit;cursor:pointer;border-radius:6px;padding:3px 8px;font-size:12px;line-height:18px}.eGUBIq_sizeBtn:hover{color:var(--dsw-alias-brand-primary,#4f6ef7);border-color:var(--dsw-alias-brand-primary,#4f6ef7)}.eGUBIq_sizeOn{background:var(--dsw-alias-brand-primary,#4f6ef7);border-color:var(--dsw-alias-brand-primary,#4f6ef7);color:#fff;font-weight:600}.eGUBIq_pageBtn{border:1px solid var(--dsw-alias-border-l2,#e5e7eb);background:var(--dsw-alias-bg-layer-1,#fff);color:var(--dsw-alias-label-secondary,#6b7280);font:inherit;cursor:pointer;border-radius:6px;min-width:28px;padding:4px 10px;font-size:12px;line-height:18px}.eGUBIq_pageBtn:hover:not(:disabled){color:var(--dsw-alias-brand-primary,#4f6ef7);border-color:var(--dsw-alias-brand-primary,#4f6ef7)}.eGUBIq_pageBtn:disabled{opacity:.45;cursor:default}.eGUBIq_pageOn{background:var(--dsw-alias-brand-primary,#4f6ef7);border-color:var(--dsw-alias-brand-primary,#4f6ef7);color:#fff;font-weight:600}.eGUBIq_pageEllipsis{color:var(--dsw-alias-label-secondary,#9ca3af);padding:0 2px;font-size:12px}.eGUBIq_pageInfo{color:var(--dsw-alias-label-secondary,#6b7280);white-space:nowrap;font-size:12px}";
395
+ const css = ".eGUBIq_root{min-width:0;height:100%;color:var(--dsw-alias-label-primary,#1f2328);flex-direction:column;display:flex;position:relative}.eGUBIq_head{flex-direction:column;gap:12px;padding:4px 4px 12px;display:flex}.eGUBIq_title{margin:0;font-size:16px;font-weight:500;line-height:24px}.eGUBIq_sub{color:var(--dsw-alias-label-tertiary,#8b93a1);margin:0;font-size:14px;line-height:22px}.eGUBIq_searchInline{flex-shrink:0;width:200px;margin-bottom:6px}.eGUBIq_tabs{border-bottom:1px solid var(--dsw-alias-border-l2,#e5e7eb);align-items:flex-end;gap:2px;display:flex}.eGUBIq_tab{font:inherit;color:var(--dsw-alias-label-secondary,#6b7280);cursor:pointer;white-space:nowrap;background:0 0;border:none;border-bottom:2px solid #0000;padding:7px 12px;font-size:13px}.eGUBIq_tab.eGUBIq_on{color:var(--dsw-alias-brand-primary,#4f6ef7);border-bottom-color:var(--dsw-alias-brand-primary,#4f6ef7);font-weight:600}.eGUBIq_restart{background:var(--dsw-alias-bg-layer-2,#fdf3e3);border:1px solid var(--dsw-alias-border-l2,#f3e3c3);border-radius:8px;align-items:center;gap:8px;margin:0;padding:8px 12px;font-size:12px;display:flex}.eGUBIq_body{flex:1;padding:12px 4px 24px;overflow-x:hidden;overflow-y:auto}.eGUBIq_cats{z-index:5;background:var(--dsw-alias-bg-layer-2,#f7f8fa);margin:-12px -4px 2px;padding:12px 4px 4px;position:sticky;top:-13px}.eGUBIq_catsRow{align-items:flex-start;gap:8px;display:flex;position:relative}.eGUBIq_filterWrap{flex-shrink:0;position:relative}.eGUBIq_filterBtn{border:1px solid var(--dsw-alias-border-l1,#e5e7eb);background:var(--dsw-alias-bg-layer-1,#fff);color:var(--dsw-alias-label-primary,#1f2328);font:inherit;cursor:pointer;white-space:nowrap;border-radius:8px;align-items:center;gap:5px;padding:5px 11px;font-size:12px;line-height:18px;display:flex}.eGUBIq_filterBtn:hover,.eGUBIq_filterBtnOn{color:var(--dsw-alias-brand-primary,#4f6ef7);border-color:var(--dsw-alias-brand-primary,#4f6ef7)}.eGUBIq_filterPanel{z-index:30;background:var(--dsw-alias-bg-layer-1,#fff);border:1px solid var(--dsw-alias-border-l2,#e5e7eb);border-radius:10px;flex-direction:column;gap:10px;width:250px;padding:8px;display:flex;position:absolute;top:calc(100% + 6px);right:0;box-shadow:0 8px 28px #00000024}.eGUBIq_filterGroup{flex-direction:column;gap:2px;display:flex}.eGUBIq_filterTitle{color:var(--dsw-alias-label-secondary,#6b7280);padding:4px 8px 2px;font-size:11px;font-weight:600}.eGUBIq_filterOption{cursor:pointer;color:var(--dsw-alias-label-primary,#1f2328);border-radius:6px;align-items:center;gap:8px;padding:5px 8px;font-size:12px;line-height:18px;display:flex}.eGUBIq_filterOption:hover{background:var(--dsw-alias-bg-layer-2,#f3f4f6)}.eGUBIq_filterOption input{margin:0}.eGUBIq_star{color:var(--dsw-alias-label-secondary,#9ca3af);font-size:11px}.eGUBIq_top{z-index:20;border:1px solid var(--dsw-alias-border-l1,#e5e7eb);background:var(--dsw-alias-bg-layer-1,#fff);width:38px;height:38px;color:var(--dsw-alias-label-secondary,#6b7280);cursor:pointer;border-radius:99px;font-size:16px;position:absolute;bottom:18px;right:18px;box-shadow:0 4px 14px #0000001f}.eGUBIq_top:hover{color:var(--dsw-alias-brand-primary,#4f6ef7)}.eGUBIq_tag{border:1px solid var(--dsw-alias-border-l3,#d9dde3);color:var(--dsw-alias-label-secondary,#6b7280);border-radius:4px;flex-shrink:0;padding:1px 6px;font-size:11px;line-height:16px}.eGUBIq_okState{color:var(--dsw-alias-state-success-primary,#16a34a);white-space:nowrap;font-size:12px;font-weight:600}.eGUBIq_dangerBtn.eGUBIq_dangerBtn{border-color:var(--dsw-alias-state-error-primary,#dc2626);color:var(--dsw-alias-state-error-primary,#dc2626)}.eGUBIq_dangerArmed.eGUBIq_dangerArmed{background:var(--dsw-alias-state-error-primary,#dc2626);color:#fff}.eGUBIq_warnBtn.eGUBIq_warnBtn{background:var(--dsw-alias-state-warn-primary,#ea580c);color:#fff}.eGUBIq_catsWrap{flex-wrap:wrap;flex:1;align-items:center;gap:6px;min-width:0;display:flex}.eGUBIq_catsCollapsed{max-height:62px;overflow:hidden}.eGUBIq_catsToggle.eGUBIq_catsToggle{height:26px;min-height:26px;color:var(--dsw-alias-label-secondary,#6b7280);padding:0 6px}.eGUBIq_cmdDetails{margin:0}.eGUBIq_cmdSummary{cursor:pointer;width:fit-content;color:var(--dsw-alias-label-secondary,#6b7280);border-radius:6px;align-items:center;gap:6px;margin-left:-4px;padding:2px 4px;font-size:12px;font-weight:500;line-height:18px;list-style:none;display:flex}.eGUBIq_cmdSummary::-webkit-details-marker{display:none}.eGUBIq_cmdSummary:before{content:\"\";border-bottom:1.5px solid;border-right:1.5px solid;width:5px;height:5px;transition:transform .12s;transform:rotate(-45deg)translate(-1px,-1px)}.eGUBIq_cmdDetails[open]>.eGUBIq_cmdSummary:before{transform:rotate(45deg)translate(-1px,-1px)}.eGUBIq_cmdSummary:hover{color:var(--dsw-alias-label-primary,#1f2328)}.eGUBIq_cmd{background:var(--dsw-alias-bg-layer-2,#f3f4f6);word-break:break-all;border-radius:6px;margin:8px 0 0;padding:8px 10px;font-family:ui-monospace,Menlo,monospace;font-size:11px;line-height:18px}.eGUBIq_warnLine{color:var(--dsw-alias-state-warn-primary,#b45309);margin:0;font-size:12px;font-weight:600;line-height:18px}.eGUBIq_modalNote{color:var(--dsw-alias-label-tertiary,#8b93a1);margin:12px 0 0;font-size:12px;line-height:18px}.eGUBIq_grid{grid-template-columns:repeat(auto-fill,minmax(280px,1fr));gap:12px;display:grid}.eGUBIq_sect{color:var(--dsw-alias-label-secondary,#6b7280);margin:14px 2px 8px;font-size:12px;font-weight:600}.eGUBIq_sect:first-child{margin-top:2px}.eGUBIq_swatches{border:1px solid var(--dsw-alias-border-l2,#e5e7eb);border-radius:8px;gap:0;height:34px;display:flex;overflow:hidden}.eGUBIq_themesGrid{margin-bottom:12px}.eGUBIq_swatches i{flex:1}.eGUBIq_card{background:var(--dsw-alias-bg-layer-1,#fff);border:1px solid var(--dsw-alias-border-l2,#e5e7eb);border-radius:12px;flex-direction:column;gap:12px;padding:12px 14px;display:flex}.eGUBIq_row1{align-items:center;gap:10px;min-width:0;display:flex}.eGUBIq_av{color:#fff;object-fit:cover;background:var(--dsw-alias-bg-layer-2,#f3f4f6);border-radius:8px;flex-shrink:0;place-items:center;width:32px;height:32px;font-size:14px;font-weight:700;display:grid}.eGUBIq_nm{text-overflow:ellipsis;white-space:nowrap;font-size:14px;font-weight:500;line-height:22px;overflow:hidden}.eGUBIq_owner{color:var(--dsw-alias-label-secondary,#9ca3af);font-size:11px}.eGUBIq_desc{color:var(--dsw-alias-label-tertiary,#8b93a1);min-height:36px;margin:0;font-size:12px;line-height:18px}.eGUBIq_foot{align-items:center;gap:8px;margin-top:auto;display:flex}.eGUBIq_grow{flex:1}.eGUBIq_titleRow{align-items:center;gap:10px;display:flex}.eGUBIq_descTight{min-height:0}.eGUBIq_src{color:var(--dsw-alias-label-secondary,#9ca3af);font-size:11px;text-decoration:none}.eGUBIq_src:hover{color:var(--dsw-alias-brand-primary,#4f6ef7)}.eGUBIq_dot{vertical-align:2px;margin-left:5px}.eGUBIq_act{flex-wrap:wrap;align-items:center;gap:6px;margin-top:6px;font-size:11px;display:flex}.eGUBIq_actLive{color:var(--dsw-alias-state-success-primary,#16a34a);align-items:center;gap:4px;font-weight:600;display:inline-flex}.eGUBIq_actWarn{color:var(--dsw-alias-state-warn-primary,#b45309);align-items:center;gap:4px;font-weight:600;display:inline-flex}.eGUBIq_actBroken{color:var(--dsw-alias-state-error-primary,#dc2626);align-items:center;gap:4px;font-weight:600;display:inline-flex}.eGUBIq_actWhy{margin:0}.eGUBIq_actWhy summary{cursor:pointer;color:var(--dsw-alias-label-secondary,#6b7280);font-size:11px}.eGUBIq_loading{color:var(--dsw-alias-label-secondary,#9ca3af);flex-direction:column;align-items:center;gap:12px;padding:48px;font-size:13px;display:flex}.eGUBIq_spin{border:3px solid var(--dsw-alias-border-l1,#e5e7eb);border-top-color:var(--dsw-alias-brand-primary,#4f6ef7);border-radius:99px;width:22px;height:22px;animation:.8s linear infinite eGUBIq_sp}@keyframes eGUBIq_sp{to{transform:rotate(360deg)}}.eGUBIq_progress{background:var(--dsw-alias-bg-layer-2,#f3f4f6);border:1px solid var(--dsw-alias-border-l2,#e5e7eb);color:var(--dsw-alias-label-secondary,#6b7280);border-radius:8px;flex-wrap:wrap;align-items:center;gap:9px;margin:0;padding:8px 12px;font-size:12px;display:flex}.eGUBIq_bar{background:var(--dsw-alias-border-l1,#e5e7eb);border-radius:99px;width:100%;height:4px;overflow:hidden}.eGUBIq_barFill{background:var(--dsw-alias-brand-primary,#4f6ef7);border-radius:99px;height:100%;transition:width .6s}.eGUBIq_barWave{width:30%;animation:1.2s ease-in-out infinite eGUBIq_dshmSlide}@keyframes eGUBIq_dshmSlide{0%{margin-left:-30%}to{margin-left:100%}}.eGUBIq_irow .eGUBIq_progress{margin-top:8px}.eGUBIq_progress .eGUBIq_spin{border-width:2px;flex-shrink:0;width:14px;height:14px}.eGUBIq_progress code{text-overflow:ellipsis;white-space:nowrap;font-family:ui-monospace,Menlo,monospace;font-size:11px;overflow:hidden}.eGUBIq_empty{color:var(--dsw-alias-label-secondary,#9ca3af);text-align:center;padding:32px;font-size:13px}.eGUBIq_err{color:var(--dsw-alias-state-error-primary,#dc2626);white-space:pre-wrap;word-break:break-all;margin:8px 0;font-size:12px}.eGUBIq_irow{background:var(--dsw-alias-bg-layer-1,#fff);border:1px solid var(--dsw-alias-border-l2,#e5e7eb);border-radius:12px;align-items:center;gap:10px;margin-bottom:8px;padding:12px 14px;display:flex}.eGUBIq_irow>.eGUBIq_src,.eGUBIq_irow>.eGUBIq_owner,.eGUBIq_dangerBtn.eGUBIq_dangerBtn,.eGUBIq_warnBtn.eGUBIq_warnBtn,.eGUBIq_dangerArmed.eGUBIq_dangerArmed{white-space:nowrap;flex-shrink:0}.eGUBIq_spec{color:var(--dsw-alias-label-secondary,#9ca3af);font-family:ui-monospace,Menlo,monospace;font-size:11px}.eGUBIq_staleAction{margin-top:8px}.eGUBIq_pct{color:var(--dsw-alias-label-secondary,#6b7280);flex-shrink:0;font-size:11px;font-weight:600}.eGUBIq_cancelBtn{border:1px solid var(--dsw-alias-border-l2,#e5e7eb);background:var(--dsw-alias-bg-layer-1,#fff);color:var(--dsw-alias-label-secondary,#6b7280);font:inherit;cursor:pointer;white-space:nowrap;border-radius:6px;flex-shrink:0;padding:2px 10px;font-size:11px;line-height:16px}.eGUBIq_cancelBtn:hover{color:var(--dsw-alias-state-error-primary,#dc2626);border-color:var(--dsw-alias-state-error-primary,#dc2626)}.eGUBIq_pager{flex-wrap:wrap;justify-content:space-between;align-items:center;gap:12px;margin:16px 0 4px;display:flex}.eGUBIq_pagerPages{flex-wrap:wrap;flex:1;justify-content:center;align-items:center;gap:6px;min-width:0;display:flex}.eGUBIq_pagerSize{flex-shrink:0;align-items:center;gap:4px;display:flex}.eGUBIq_sizeLabel{color:var(--dsw-alias-label-secondary,#6b7280);font-size:12px}.eGUBIq_sizeBtn{border:1px solid var(--dsw-alias-border-l2,#e5e7eb);background:var(--dsw-alias-bg-layer-1,#fff);color:var(--dsw-alias-label-secondary,#6b7280);font:inherit;cursor:pointer;border-radius:6px;padding:3px 8px;font-size:12px;line-height:18px}.eGUBIq_sizeBtn:hover{color:var(--dsw-alias-brand-primary,#4f6ef7);border-color:var(--dsw-alias-brand-primary,#4f6ef7)}.eGUBIq_sizeOn{background:var(--dsw-alias-brand-primary,#4f6ef7);border-color:var(--dsw-alias-brand-primary,#4f6ef7);color:#fff;font-weight:600}.eGUBIq_pageBtn{border:1px solid var(--dsw-alias-border-l2,#e5e7eb);background:var(--dsw-alias-bg-layer-1,#fff);color:var(--dsw-alias-label-secondary,#6b7280);font:inherit;cursor:pointer;border-radius:6px;min-width:28px;padding:4px 10px;font-size:12px;line-height:18px}.eGUBIq_pageBtn:hover:not(:disabled){color:var(--dsw-alias-brand-primary,#4f6ef7);border-color:var(--dsw-alias-brand-primary,#4f6ef7)}.eGUBIq_pageBtn:disabled{opacity:.45;cursor:default}.eGUBIq_pageOn{background:var(--dsw-alias-brand-primary,#4f6ef7);border-color:var(--dsw-alias-brand-primary,#4f6ef7);color:#fff;font-weight:600}.eGUBIq_pageEllipsis{color:var(--dsw-alias-label-secondary,#9ca3af);padding:0 2px;font-size:12px}.eGUBIq_pageInfo{color:var(--dsw-alias-label-secondary,#6b7280);white-space:nowrap;font-size:12px}";
321
396
  const tagId = "dshmarket/Market.module.css";
322
397
  if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId) + "]") === null) {
323
398
  const tag = document.createElement("style");
@@ -327,75 +402,86 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
327
402
  document.head.appendChild(tag);
328
403
  }
329
404
  var Market_module_css_default = {
330
- "catsWrap": "eGUBIq_catsWrap",
331
- "pageInfo": "eGUBIq_pageInfo",
405
+ "spec": "eGUBIq_spec",
406
+ "spin": "eGUBIq_spin",
407
+ "tag": "eGUBIq_tag",
408
+ "src": "eGUBIq_src",
409
+ "okState": "eGUBIq_okState",
332
410
  "cats": "eGUBIq_cats",
333
- "catsRow": "eGUBIq_catsRow",
334
- "themesGrid": "eGUBIq_themesGrid",
335
- "star": "eGUBIq_star",
336
- "grow": "eGUBIq_grow",
411
+ "staleAction": "eGUBIq_staleAction",
412
+ "filterTitle": "eGUBIq_filterTitle",
413
+ "filterBtn": "eGUBIq_filterBtn",
414
+ "owner": "eGUBIq_owner",
415
+ "sect": "eGUBIq_sect",
416
+ "err": "eGUBIq_err",
417
+ "catsToggle": "eGUBIq_catsToggle",
337
418
  "card": "eGUBIq_card",
338
- "pagerPages": "eGUBIq_pagerPages",
339
- "pageEllipsis": "eGUBIq_pageEllipsis",
340
- "pager": "eGUBIq_pager",
341
- "sort": "eGUBIq_sort",
419
+ "catsWrap": "eGUBIq_catsWrap",
342
420
  "warnBtn": "eGUBIq_warnBtn",
343
- "progress": "eGUBIq_progress",
344
- "okState": "eGUBIq_okState",
345
421
  "root": "eGUBIq_root",
346
- "sub": "eGUBIq_sub",
347
- "pageOn": "eGUBIq_pageOn",
348
- "tabs": "eGUBIq_tabs",
422
+ "catsRow": "eGUBIq_catsRow",
423
+ "dot": "eGUBIq_dot",
349
424
  "swatches": "eGUBIq_swatches",
350
- "descTight": "eGUBIq_descTight",
351
- "irow": "eGUBIq_irow",
352
- "sect": "eGUBIq_sect",
353
- "foot": "eGUBIq_foot",
354
- "sizeBtn": "eGUBIq_sizeBtn",
355
- "staleAction": "eGUBIq_staleAction",
356
- "pct": "eGUBIq_pct",
357
- "barWave": "eGUBIq_barWave",
358
- "catsToggle": "eGUBIq_catsToggle",
359
- "owner": "eGUBIq_owner",
425
+ "loading": "eGUBIq_loading",
426
+ "act": "eGUBIq_act",
427
+ "catsCollapsed": "eGUBIq_catsCollapsed",
428
+ "actWarn": "eGUBIq_actWarn",
360
429
  "body": "eGUBIq_body",
361
- "av": "eGUBIq_av",
362
- "cmd": "eGUBIq_cmd",
363
- "err": "eGUBIq_err",
364
- "head": "eGUBIq_head",
365
- "spec": "eGUBIq_spec",
366
- "grid": "eGUBIq_grid",
367
- "cancelBtn": "eGUBIq_cancelBtn",
368
- "pagerSize": "eGUBIq_pagerSize",
369
- "sizeLabel": "eGUBIq_sizeLabel",
370
430
  "cmdSummary": "eGUBIq_cmdSummary",
371
- "loading": "eGUBIq_loading",
372
- "top": "eGUBIq_top",
373
- "cmdDetails": "eGUBIq_cmdDetails",
374
- "src": "eGUBIq_src",
431
+ "barWave": "eGUBIq_barWave",
432
+ "star": "eGUBIq_star",
433
+ "dangerBtn": "eGUBIq_dangerBtn",
434
+ "title": "eGUBIq_title",
435
+ "actWhy": "eGUBIq_actWhy",
436
+ "progress": "eGUBIq_progress",
375
437
  "on": "eGUBIq_on",
376
- "catsCollapsed": "eGUBIq_catsCollapsed",
377
438
  "restart": "eGUBIq_restart",
378
439
  "dangerArmed": "eGUBIq_dangerArmed",
379
- "dangerBtn": "eGUBIq_dangerBtn",
380
- "dot": "eGUBIq_dot",
381
- "sp": "eGUBIq_sp",
382
- "desc": "eGUBIq_desc",
383
- "bar": "eGUBIq_bar",
440
+ "foot": "eGUBIq_foot",
441
+ "grid": "eGUBIq_grid",
442
+ "tabs": "eGUBIq_tabs",
384
443
  "empty": "eGUBIq_empty",
385
444
  "warnLine": "eGUBIq_warnLine",
386
- "pageBtn": "eGUBIq_pageBtn",
445
+ "sp": "eGUBIq_sp",
387
446
  "dshmSlide": "eGUBIq_dshmSlide",
388
- "tag": "eGUBIq_tag",
389
- "nm": "eGUBIq_nm",
390
- "spin": "eGUBIq_spin",
447
+ "sizeBtn": "eGUBIq_sizeBtn",
448
+ "pageEllipsis": "eGUBIq_pageEllipsis",
449
+ "pageInfo": "eGUBIq_pageInfo",
450
+ "pct": "eGUBIq_pct",
451
+ "desc": "eGUBIq_desc",
452
+ "pageBtn": "eGUBIq_pageBtn",
453
+ "filterWrap": "eGUBIq_filterWrap",
454
+ "sizeLabel": "eGUBIq_sizeLabel",
455
+ "cmd": "eGUBIq_cmd",
456
+ "actLive": "eGUBIq_actLive",
457
+ "themesGrid": "eGUBIq_themesGrid",
458
+ "pagerSize": "eGUBIq_pagerSize",
459
+ "irow": "eGUBIq_irow",
460
+ "filterPanel": "eGUBIq_filterPanel",
461
+ "filterGroup": "eGUBIq_filterGroup",
462
+ "titleRow": "eGUBIq_titleRow",
391
463
  "searchInline": "eGUBIq_searchInline",
392
- "sizeOn": "eGUBIq_sizeOn",
393
464
  "barFill": "eGUBIq_barFill",
394
- "title": "eGUBIq_title",
395
- "titleRow": "eGUBIq_titleRow",
396
- "tab": "eGUBIq_tab",
465
+ "cmdDetails": "eGUBIq_cmdDetails",
466
+ "filterOption": "eGUBIq_filterOption",
467
+ "nm": "eGUBIq_nm",
468
+ "pagerPages": "eGUBIq_pagerPages",
469
+ "modalNote": "eGUBIq_modalNote",
470
+ "grow": "eGUBIq_grow",
471
+ "pager": "eGUBIq_pager",
397
472
  "row1": "eGUBIq_row1",
398
- "modalNote": "eGUBIq_modalNote"
473
+ "head": "eGUBIq_head",
474
+ "descTight": "eGUBIq_descTight",
475
+ "tab": "eGUBIq_tab",
476
+ "bar": "eGUBIq_bar",
477
+ "sub": "eGUBIq_sub",
478
+ "av": "eGUBIq_av",
479
+ "actBroken": "eGUBIq_actBroken",
480
+ "top": "eGUBIq_top",
481
+ "pageOn": "eGUBIq_pageOn",
482
+ "sizeOn": "eGUBIq_sizeOn",
483
+ "cancelBtn": "eGUBIq_cancelBtn",
484
+ "filterBtnOn": "eGUBIq_filterBtnOn"
399
485
  };
400
486
  //#endregion
401
487
  //#region src/client/MarketSection.tsx
@@ -404,6 +490,35 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
404
490
  * /dsh-market/* host routes, with install/update/uninstall flows and the
405
491
  * pending-restart bookkeeping in sessionStorage.
406
492
  */
493
+ /** The state label + dot for one activation result (P0-2). */
494
+ function activationMeta(state, t) {
495
+ if (state === "live") return {
496
+ label: t("stateLive"),
497
+ dot: "done"
498
+ };
499
+ if (state === "restart") return {
500
+ label: t("stateRestart"),
501
+ dot: "warning"
502
+ };
503
+ if (state === "inert") return {
504
+ label: t("stateInert"),
505
+ dot: "warning"
506
+ };
507
+ if (state === "broken") return {
508
+ label: t("stateBroken"),
509
+ dot: "error"
510
+ };
511
+ return {
512
+ label: "—",
513
+ dot: "warning"
514
+ };
515
+ }
516
+ function phaseLabel(phase, t) {
517
+ if (phase === "resolving") return t("phaseResolving");
518
+ if (phase === "downloading") return t("phaseDownloading");
519
+ if (phase === "linking") return t("phaseLinking");
520
+ return t("phaseBuilding");
521
+ }
407
522
  /**
408
523
  * Card avatar: the plugin owner's GitHub avatar (no API, browser-cached),
409
524
  * falling back to the initial-letter tile when it can't load.
@@ -462,6 +577,43 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
462
577
  96
463
578
  ];
464
579
  const DEFAULT_PAGE_SIZE = 24;
580
+ /** Sort field choices in the filter panel. */
581
+ const SORT_FIELD_OPTIONS = [{
582
+ key: "stars",
583
+ label: "sortStars"
584
+ }, {
585
+ key: "added",
586
+ label: "sortAdded"
587
+ }];
588
+ /** Sort direction choices in the filter panel (labels depend on the field). */
589
+ const SORT_DIR_OPTIONS = ["desc", "asc"];
590
+ /** Published-within choices in the filter panel. */
591
+ const TIME_OPTIONS = [
592
+ {
593
+ key: "all",
594
+ label: "timeAll"
595
+ },
596
+ {
597
+ key: "day",
598
+ label: "timeDay"
599
+ },
600
+ {
601
+ key: "week",
602
+ label: "timeWeek"
603
+ },
604
+ {
605
+ key: "month",
606
+ label: "timeMonth"
607
+ },
608
+ {
609
+ key: "quarter",
610
+ label: "timeQuarter"
611
+ },
612
+ {
613
+ key: "year",
614
+ label: "timeYear"
615
+ }
616
+ ];
465
617
  function MarketSection(props) {
466
618
  const t = props.t;
467
619
  const localeSnap = (0, react.useSyncExternalStore)((cb) => props.locale.subscribe(cb), () => props.locale.getSnapshot());
@@ -504,6 +656,15 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
504
656
  const [hotUrls, setHotUrls] = (0, react.useState)([]);
505
657
  const [hotNames, setHotNames] = (0, react.useState)([]);
506
658
  const [progressLine, setProgressLine] = (0, react.useState)(null);
659
+ /** Per-package activation states from /dsh-market/installed + operations. */
660
+ const [activations, setActivations] = (0, react.useState)({});
661
+ /** Structured progress from pnpm ndjson (P1-6). */
662
+ const [progressPhase, setProgressPhase] = (0, react.useState)(null);
663
+ const [progressCurrent, setProgressCurrent] = (0, react.useState)(null);
664
+ const [progressDone, setProgressDone] = (0, react.useState)(0);
665
+ const [cancelling, setCancelling] = (0, react.useState)(false);
666
+ /** Non-live activation results from the last operation, shown as a banner. */
667
+ const [activationWarnings, setActivationWarnings] = (0, react.useState)([]);
507
668
  const [removeArmed, setRemoveArmed] = (0, react.useState)(null);
508
669
  const [removingName, setRemovingName] = (0, react.useState)(null);
509
670
  const [removedCount, setRemovedCount] = (0, react.useState)(0);
@@ -516,7 +677,13 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
516
677
  const [restarting, setRestarting] = (0, react.useState)(false);
517
678
  const [showTop, setShowTop] = (0, react.useState)(false);
518
679
  const bodyRef = (0, react.useRef)(null);
519
- const [sort, setSort] = (0, react.useState)("hot");
680
+ const [sortField, setSortField] = (0, react.useState)("stars");
681
+ const [sortDir, setSortDir] = (0, react.useState)("desc");
682
+ /** Direction labels adapt to the field: stars → asc/desc, added → oldest/newest. */
683
+ const sortDirLabel = (dir) => sortField === "added" ? dir === "desc" ? "sortNewest" : "sortOldest" : dir === "desc" ? "sortDesc" : "sortAsc";
684
+ const [timeRange, setTimeRange] = (0, react.useState)("all");
685
+ const [filterOpen, setFilterOpen] = (0, react.useState)(false);
686
+ const filterWrapRef = (0, react.useRef)(null);
520
687
  const [catsOpen, setCatsOpen] = (0, react.useState)(false);
521
688
  const [visibleCats, setVisibleCats] = (0, react.useState)(null);
522
689
  const catsWrapRef = (0, react.useRef)(null);
@@ -524,6 +691,7 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
524
691
  fetch("/dsh-market/installed", { cache: "no-store" }).then((res) => res.json()).then((body) => {
525
692
  setInstalled(body.installed || {});
526
693
  setSkins(body.live || []);
694
+ if (body.activation && typeof body.activation === "object") setActivations(body.activation);
527
695
  }).catch(() => {});
528
696
  fetch("/dsh-market/updates" + (force === true ? "?force=1" : ""), { cache: "no-store" }).then((res) => res.json()).then((body) => setUpdates(body.updates || {})).catch(() => {});
529
697
  }, []);
@@ -591,20 +759,40 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
591
759
  (0, react.useEffect)(() => {
592
760
  if (busyUrl === null && updatingName === null) {
593
761
  setProgressLine(null);
762
+ setProgressPhase(null);
763
+ setProgressCurrent(null);
764
+ setProgressDone(0);
765
+ setCancelling(false);
594
766
  return;
595
767
  }
596
768
  const timer = setInterval(() => {
597
769
  fetch("/dsh-market/status", { cache: "no-store" }).then((res) => res.json()).then((status) => {
598
770
  if (status.active) {
599
- setProgressLine((status.lastLine || "…") + " (" + status.seconds + "s)");
600
- const m = /resolved (\d+), reused (\d+), downloaded (\d+), added (\d+)/.exec(status.lastLine || "");
601
- if (m !== null && Number(m[1]) > 0) {
602
- const done = Number(m[2]) + Number(m[3]) + Number(m[4]);
603
- setProgressPct(Math.max(4, Math.min(96, Math.round(done / Number(m[1]) * 100))));
771
+ setCancelling(status.cancelling === true);
772
+ if (status.phase !== null && status.phase !== void 0) {
773
+ setProgressPhase(status.phase);
774
+ setProgressCurrent(status.currentPackage ?? null);
775
+ setProgressDone(status.done ?? 0);
776
+ setProgressLine(null);
777
+ if (typeof status.size === "number" && status.size > 0 && typeof status.downloaded === "number") setProgressPct(Math.max(4, Math.min(96, Math.round(status.downloaded / status.size * 100))));
778
+ } else {
779
+ setProgressLine((status.lastLine || "…") + " (" + status.seconds + "s)");
780
+ setProgressPhase(null);
781
+ setProgressCurrent(null);
782
+ setProgressDone(0);
783
+ const m = /resolved (\d+), reused (\d+), downloaded (\d+), added (\d+)/.exec(status.lastLine || "");
784
+ if (m !== null && Number(m[1]) > 0) {
785
+ const done = Number(m[2]) + Number(m[3]) + Number(m[4]);
786
+ setProgressPct(Math.max(4, Math.min(96, Math.round(done / Number(m[1]) * 100))));
787
+ }
604
788
  }
605
789
  } else {
606
790
  setProgressLine(null);
607
791
  setProgressPct(null);
792
+ setProgressPhase(null);
793
+ setProgressCurrent(null);
794
+ setProgressDone(0);
795
+ setCancelling(false);
608
796
  setInstalled(status.installed || {});
609
797
  if (readSession("dshm-pending") !== null && busyUrl !== null) {
610
798
  if (data !== null && data.plugins.some((p) => p.url === busyUrl && isInstalled(p, status.installed || {}))) {
@@ -632,21 +820,34 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
632
820
  category: cat,
633
821
  query: q,
634
822
  lang,
635
- sort
823
+ sort: `${sortField}-${sortDir}`,
824
+ sinceDays: timeRange === "all" ? void 0 : TIME_RANGE_DAYS[timeRange]
636
825
  }), [
637
826
  data,
638
827
  q,
639
828
  cat,
640
829
  lang,
641
- sort
830
+ sortField,
831
+ sortDir,
832
+ timeRange
642
833
  ]);
643
834
  (0, react.useEffect)(() => {
644
835
  setPage(1);
645
836
  }, [
646
837
  q,
647
838
  cat,
648
- sort
839
+ sortField,
840
+ sortDir,
841
+ timeRange
649
842
  ]);
843
+ (0, react.useEffect)(() => {
844
+ if (!filterOpen) return;
845
+ const onDown = (event) => {
846
+ if (filterWrapRef.current !== null && !filterWrapRef.current.contains(event.target)) setFilterOpen(false);
847
+ };
848
+ document.addEventListener("mousedown", onDown);
849
+ return () => document.removeEventListener("mousedown", onDown);
850
+ }, [filterOpen]);
650
851
  const totalPages = Math.max(1, Math.ceil(plugins.length / pageSize));
651
852
  const currentPage = Math.min(page, totalPages);
652
853
  const pagePlugins = plugins.slice((currentPage - 1) * pageSize, currentPage * pageSize);
@@ -673,6 +874,7 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
673
874
  setBuildsSkipped(null);
674
875
  setConfirming(null);
675
876
  setInstallError(null);
877
+ setActivationWarnings([]);
676
878
  setBusyUrl(plugin.url);
677
879
  sessionStorage.setItem("dshm-pending", JSON.stringify({ url: plugin.url }));
678
880
  fetch("/dsh-market/install", {
@@ -692,10 +894,22 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
692
894
  }
693
895
  if (body.cancelled === true) {
694
896
  refreshInstalled();
897
+ if (body.partial === true) setInstallError(t("partialNote"));
695
898
  return;
696
899
  }
697
900
  if (status === 200 && body.ok) {
698
901
  sessionStorage.setItem("dshm-tab", "installed");
902
+ if (body.activation && typeof body.activation === "object") {
903
+ setActivations((prev) => ({
904
+ ...prev,
905
+ ...body.activation
906
+ }));
907
+ const warns = Object.entries(body.activation).filter(([, info]) => info.state !== "live" && info.state !== "missing").map(([name, info]) => ({
908
+ name,
909
+ info
910
+ }));
911
+ setActivationWarnings(warns);
912
+ }
699
913
  if (body.hot) {
700
914
  setHotUrls((urls) => urls.includes(plugin.url) ? urls : urls.concat(plugin.url));
701
915
  setHotNames((names) => names.includes(plugin.name) ? names : names.concat(plugin.name));
@@ -780,6 +994,7 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
780
994
  }, []);
781
995
  const doUpdate = (0, react.useCallback)((name, force = false) => {
782
996
  setInstallError(null);
997
+ setActivationWarnings([]);
783
998
  setStaleName(null);
784
999
  setUpdatingName(name);
785
1000
  return fetch("/dsh-market/update", {
@@ -795,10 +1010,15 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
795
1010
  }))).then(({ status, body }) => {
796
1011
  if (body.cancelled === true) {
797
1012
  refreshInstalled();
1013
+ if (body.partial === true) setInstallError(t("partialNote"));
798
1014
  return;
799
1015
  }
800
1016
  if (status === 200 && body.ok) {
801
1017
  setUpdatedNames((names) => names.concat(name));
1018
+ if (body.activation && typeof body.activation === "object") setActivations((prev) => ({
1019
+ ...prev,
1020
+ ...body.activation
1021
+ }));
802
1022
  refreshInstalled();
803
1023
  } else {
804
1024
  if (status === 409) {
@@ -833,6 +1053,7 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
833
1053
  const doUninstall = (0, react.useCallback)((name) => {
834
1054
  setRemoveArmed(null);
835
1055
  setInstallError(null);
1056
+ setActivationWarnings([]);
836
1057
  setRemovingName(name);
837
1058
  return fetch("/dsh-market/uninstall", {
838
1059
  method: "POST",
@@ -846,6 +1067,11 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
846
1067
  if (!body.hot) setRemovedCount((n) => n + 1);
847
1068
  refreshInstalled();
848
1069
  } else {
1070
+ if (body.cancelled === true) {
1071
+ refreshInstalled();
1072
+ if (body.partial === true) setInstallError(t("partialNote"));
1073
+ return;
1074
+ }
849
1075
  const text = (v) => typeof v === "string" ? v : v && typeof v.text === "string" ? v.text : v == null ? "" : JSON.stringify(v);
850
1076
  setInstallError((text(body.error) || text(body.stderr) || "error").trim().slice(-600));
851
1077
  }
@@ -868,6 +1094,9 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
868
1094
  }, [updatableNames, doUpdate]);
869
1095
  const pendingRestart = doneUrls.length + updatedNames.length + removedCount;
870
1096
  const hasUpdates = Object.keys(installed).some((name) => !updatedNames.includes(name) && updates[name] && updates[name].updateAvailable);
1097
+ /** Live status line: structured phase, or the human-line fallback. */
1098
+ const phasePart = progressPhase != null ? phaseLabel(progressPhase, t) + (progressCurrent !== null ? " · " + progressCurrent : "") + (progressDone > 0 ? " · " + t("packagesDone").replace("{0}", String(progressDone)) : "") : progressLine || t("progressHint");
1099
+ const progressText = cancelling ? t("cancelling") + " · " + phasePart : phasePart;
871
1100
  const themePlugins$1 = data === null ? [] : themePlugins(data.plugins);
872
1101
  const pluginCard = (p) => {
873
1102
  const desc = p.description && (p.description[lang] || p.description.en) || "";
@@ -891,10 +1120,17 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
891
1120
  children: p.name
892
1121
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
893
1122
  className: Market_module_css_default.owner,
894
- children: [p.owner, typeof p.stars === "number" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
895
- className: Market_module_css_default.star,
896
- children: " · " + p.stars
897
- })]
1123
+ children: [
1124
+ p.owner,
1125
+ typeof p.stars === "number" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1126
+ className: Market_module_css_default.star,
1127
+ children: " · ★ " + p.stars
1128
+ }),
1129
+ p.added && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1130
+ className: Market_module_css_default.star,
1131
+ children: " · " + t("published") + " " + p.added
1132
+ })
1133
+ ]
898
1134
  })]
899
1135
  }),
900
1136
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: Market_module_css_default.grow }),
@@ -949,7 +1185,7 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
949
1185
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: Market_module_css_default.spin }),
950
1186
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("code", {
951
1187
  className: Market_module_css_default.grow,
952
- children: progressLine || t("progressHint")
1188
+ children: progressText
953
1189
  }),
954
1190
  progressPct !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
955
1191
  className: Market_module_css_default.pct,
@@ -958,8 +1194,9 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
958
1194
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
959
1195
  type: "button",
960
1196
  className: Market_module_css_default.cancelBtn,
1197
+ disabled: cancelling,
961
1198
  onClick: doCancel,
962
- children: t("cancelOp")
1199
+ children: cancelling ? t("cancelling") : t("cancelOp")
963
1200
  }),
964
1201
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
965
1202
  className: Market_module_css_default.bar,
@@ -997,10 +1234,17 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
997
1234
  children: p.name
998
1235
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
999
1236
  className: Market_module_css_default.owner,
1000
- children: [p.owner, typeof p.stars === "number" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1001
- className: Market_module_css_default.star,
1002
- children: " · " + p.stars
1003
- })]
1237
+ children: [
1238
+ p.owner,
1239
+ typeof p.stars === "number" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1240
+ className: Market_module_css_default.star,
1241
+ children: " · ★ " + p.stars
1242
+ }),
1243
+ p.added && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1244
+ className: Market_module_css_default.star,
1245
+ children: " · " + t("published") + " " + p.added
1246
+ })
1247
+ ]
1004
1248
  })]
1005
1249
  }),
1006
1250
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: Market_module_css_default.grow }),
@@ -1270,6 +1514,25 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
1270
1514
  children: restarting ? t("restarting") : t("restartNow")
1271
1515
  })
1272
1516
  ]
1517
+ }),
1518
+ activationWarnings.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1519
+ className: Market_module_css_default.restart,
1520
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: "⚠️" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1521
+ className: Market_module_css_default.grow,
1522
+ children: activationWarnings.map(({ name, info }) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [
1523
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("b", { children: name }),
1524
+ " — ",
1525
+ activationMeta(info.state, t).label,
1526
+ info.reasons.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
1527
+ className: Market_module_css_default.spec,
1528
+ children: [
1529
+ "(",
1530
+ info.reasons.join(" / "),
1531
+ ")"
1532
+ ]
1533
+ })
1534
+ ] }, name))
1535
+ })]
1273
1536
  })
1274
1537
  ]
1275
1538
  }),
@@ -1354,13 +1617,64 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
1354
1617
  })
1355
1618
  ] });
1356
1619
  })()
1357
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1358
- className: Market_module_css_default.sort,
1359
- children: ["hot", "new"].map((key) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1360
- className: sort === key ? Market_module_css_default.on : "",
1361
- onClick: () => setSort(key),
1362
- children: t(key === "hot" ? "sortHot" : "sortNew")
1363
- }, key))
1620
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1621
+ className: Market_module_css_default.filterWrap,
1622
+ ref: filterWrapRef,
1623
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
1624
+ type: "button",
1625
+ className: filterOpen ? `${Market_module_css_default.filterBtn} ${Market_module_css_default.filterBtnOn}` : Market_module_css_default.filterBtn,
1626
+ onClick: () => setFilterOpen((o) => !o),
1627
+ children: [t("filter"), filterOpen ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronUpOutline14, { size: 14 }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronDownOutline14, { size: 14 })]
1628
+ }), filterOpen && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1629
+ className: Market_module_css_default.filterPanel,
1630
+ children: [
1631
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1632
+ className: Market_module_css_default.filterGroup,
1633
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1634
+ className: Market_module_css_default.filterTitle,
1635
+ children: t("filterSort")
1636
+ }), SORT_FIELD_OPTIONS.map((opt) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
1637
+ className: Market_module_css_default.filterOption,
1638
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
1639
+ type: "radio",
1640
+ name: "dshm-sort-field",
1641
+ checked: sortField === opt.key,
1642
+ onChange: () => setSortField(opt.key)
1643
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t(opt.label) })]
1644
+ }, opt.key))]
1645
+ }),
1646
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1647
+ className: Market_module_css_default.filterGroup,
1648
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1649
+ className: Market_module_css_default.filterTitle,
1650
+ children: t("filterDir")
1651
+ }), SORT_DIR_OPTIONS.map((dir) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
1652
+ className: Market_module_css_default.filterOption,
1653
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
1654
+ type: "radio",
1655
+ name: "dshm-sort-dir",
1656
+ checked: sortDir === dir,
1657
+ onChange: () => setSortDir(dir)
1658
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t(sortDirLabel(dir)) })]
1659
+ }, dir))]
1660
+ }),
1661
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1662
+ className: Market_module_css_default.filterGroup,
1663
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1664
+ className: Market_module_css_default.filterTitle,
1665
+ children: t("filterTime")
1666
+ }), TIME_OPTIONS.map((opt) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
1667
+ className: Market_module_css_default.filterOption,
1668
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
1669
+ type: "radio",
1670
+ name: "dshm-time",
1671
+ checked: timeRange === opt.key,
1672
+ onChange: () => setTimeRange(opt.key)
1673
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t(opt.label) })]
1674
+ }, opt.key))]
1675
+ })
1676
+ ]
1677
+ })]
1364
1678
  })]
1365
1679
  })
1366
1680
  }), plugins.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
@@ -1451,6 +1765,8 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
1451
1765
  }) : Object.entries(installed).map(([name, spec]) => {
1452
1766
  const entry = data === null ? void 0 : entryForDep(data.plugins, name, String(spec));
1453
1767
  const status = updates[name];
1768
+ const act = activations[name];
1769
+ const meta = act !== void 0 ? activationMeta(act.state, t) : null;
1454
1770
  const version = status && status.version ? "v" + status.version : "";
1455
1771
  const specText = String(spec);
1456
1772
  const ghSpec = /^github:([A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+?)(?:#|$)/.exec(specText);
@@ -1483,13 +1799,29 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
1483
1799
  className: `${Market_module_css_default.desc} ${Market_module_css_default.descTight}`,
1484
1800
  children: entry.description && (entry.description[lang] || entry.description.en) || ""
1485
1801
  }),
1802
+ act !== void 0 && meta !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1803
+ className: Market_module_css_default.act,
1804
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
1805
+ className: meta.dot === "done" ? Market_module_css_default.actLive : meta.dot === "error" ? Market_module_css_default.actBroken : Market_module_css_default.actWarn,
1806
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.StateDot, {
1807
+ state: meta.dot,
1808
+ size: 7
1809
+ }), meta.label]
1810
+ }), act.state !== "live" && act.reasons.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("details", {
1811
+ className: Market_module_css_default.actWhy,
1812
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("summary", { children: t("actWhy") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1813
+ className: Market_module_css_default.spec,
1814
+ children: act.reasons.join(" / ")
1815
+ })]
1816
+ })]
1817
+ }),
1486
1818
  updatingName === name && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1487
1819
  className: Market_module_css_default.progress,
1488
1820
  children: [
1489
1821
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: Market_module_css_default.spin }),
1490
1822
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("code", {
1491
1823
  className: Market_module_css_default.grow,
1492
- children: progressLine || t("progressHint")
1824
+ children: progressText
1493
1825
  }),
1494
1826
  progressPct !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
1495
1827
  className: Market_module_css_default.pct,
@@ -1498,8 +1830,9 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
1498
1830
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1499
1831
  type: "button",
1500
1832
  className: Market_module_css_default.cancelBtn,
1833
+ disabled: cancelling,
1501
1834
  onClick: doCancel,
1502
- children: t("cancelOp")
1835
+ children: cancelling ? t("cancelling") : t("cancelOp")
1503
1836
  }),
1504
1837
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1505
1838
  className: Market_module_css_default.bar,
@@ -1522,7 +1855,7 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
1522
1855
  }),
1523
1856
  updatedNames.includes(name) ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1524
1857
  className: Market_module_css_default.okState,
1525
- children: t("updated")
1858
+ children: act?.state === "live" ? t("updatedLive") : t("updated")
1526
1859
  }) : updatingName === name ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
1527
1860
  variant: "primary",
1528
1861
  size: "sm",