dshmarket 1.3.1 → 1.4.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
@@ -66,6 +66,12 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
66
66
  catsLess: "收起",
67
67
  sortHot: "最热",
68
68
  sortNew: "最新",
69
+ prevPage: "上一页",
70
+ nextPage: "下一页",
71
+ firstPage: "首页",
72
+ lastPage: "末页",
73
+ pageInfo: "第 {0} / {1} 页",
74
+ perPage: "每页",
69
75
  marketUpdate: "市场有新版本,升级",
70
76
  updateAll: "全部更新",
71
77
  tabThemes: "主题",
@@ -134,6 +140,12 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
134
140
  catsLess: "Less",
135
141
  sortHot: "Top",
136
142
  sortNew: "New",
143
+ prevPage: "Previous",
144
+ nextPage: "Next",
145
+ firstPage: "First",
146
+ lastPage: "Last",
147
+ pageInfo: "Page {0} of {1}",
148
+ perPage: "Per page",
137
149
  marketUpdate: "Market update available — upgrade",
138
150
  updateAll: "Update all",
139
151
  tabThemes: "Themes",
@@ -193,6 +205,29 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
193
205
  return open || active === "all" ? categories : [active, ...categories.filter((id) => id !== active)];
194
206
  }
195
207
  /**
208
+ * Page-number list for the discover pager. With few pages it is simply
209
+ * 1..total; with many it windows around the current page and inserts '…'
210
+ * so a 400-plugin catalog stays a compact `1 … 4 5 6 … 17` instead of a
211
+ * long row of numbered buttons. Always begins with 1 and ends with total.
212
+ */
213
+ function pageItems(current, total) {
214
+ if (total <= 7) {
215
+ const all = [];
216
+ for (let i = 1; i <= total; i++) all.push(i);
217
+ return all;
218
+ }
219
+ const items = [1];
220
+ let start = Math.max(2, current - 1);
221
+ let end = Math.min(total - 1, current + 1);
222
+ if (current <= 4) end = 5;
223
+ if (current >= total - 3) start = total - 4;
224
+ if (start > 2) items.push("…");
225
+ for (let i = start; i <= end; i++) items.push(i);
226
+ if (end < total - 1) items.push("…");
227
+ items.push(total);
228
+ return items;
229
+ }
230
+ /**
196
231
  * Unified installed-state matching (#15): both sides collapse to lowercase
197
232
  * identity sets — the registry entry contributes its bare name, npm name and
198
233
  * owner/repo; the dependency contributes its key and the repo inside its
@@ -282,7 +317,7 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
282
317
  }
283
318
  //#endregion
284
319
  //#region \0dsh-css:/home/runner/work/dsh-market/dsh-market/src/client/Market.module.css.mjs
285
- 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;align-items:center;gap:9px;margin:0;padding:8px 12px;font-size:12px;display:flex}.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_sentinel{height:1px}";
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}";
286
321
  const tagId = "dshmarket/Market.module.css";
287
322
  if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId) + "]") === null) {
288
323
  const tag = document.createElement("style");
@@ -292,62 +327,75 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
292
327
  document.head.appendChild(tag);
293
328
  }
294
329
  var Market_module_css_default = {
295
- "warnBtn": "eGUBIq_warnBtn",
296
- "star": "eGUBIq_star",
297
330
  "catsWrap": "eGUBIq_catsWrap",
298
- "row1": "eGUBIq_row1",
299
- "owner": "eGUBIq_owner",
300
- "spin": "eGUBIq_spin",
301
- "empty": "eGUBIq_empty",
302
- "sub": "eGUBIq_sub",
303
- "dangerArmed": "eGUBIq_dangerArmed",
304
- "warnLine": "eGUBIq_warnLine",
305
- "tabs": "eGUBIq_tabs",
306
- "title": "eGUBIq_title",
307
- "sort": "eGUBIq_sort",
308
- "tab": "eGUBIq_tab",
331
+ "pageInfo": "eGUBIq_pageInfo",
332
+ "cats": "eGUBIq_cats",
333
+ "catsRow": "eGUBIq_catsRow",
309
334
  "themesGrid": "eGUBIq_themesGrid",
310
- "root": "eGUBIq_root",
335
+ "star": "eGUBIq_star",
311
336
  "grow": "eGUBIq_grow",
337
+ "card": "eGUBIq_card",
338
+ "pagerPages": "eGUBIq_pagerPages",
339
+ "pageEllipsis": "eGUBIq_pageEllipsis",
340
+ "pager": "eGUBIq_pager",
341
+ "sort": "eGUBIq_sort",
342
+ "warnBtn": "eGUBIq_warnBtn",
343
+ "progress": "eGUBIq_progress",
344
+ "okState": "eGUBIq_okState",
345
+ "root": "eGUBIq_root",
346
+ "sub": "eGUBIq_sub",
347
+ "pageOn": "eGUBIq_pageOn",
348
+ "tabs": "eGUBIq_tabs",
349
+ "swatches": "eGUBIq_swatches",
350
+ "descTight": "eGUBIq_descTight",
351
+ "irow": "eGUBIq_irow",
352
+ "sect": "eGUBIq_sect",
353
+ "foot": "eGUBIq_foot",
354
+ "sizeBtn": "eGUBIq_sizeBtn",
312
355
  "staleAction": "eGUBIq_staleAction",
313
- "cmdDetails": "eGUBIq_cmdDetails",
314
- "cancelBtn": "eGUBIq_cancelBtn",
315
- "nm": "eGUBIq_nm",
316
- "desc": "eGUBIq_desc",
356
+ "pct": "eGUBIq_pct",
357
+ "barWave": "eGUBIq_barWave",
317
358
  "catsToggle": "eGUBIq_catsToggle",
318
- "irow": "eGUBIq_irow",
319
- "loading": "eGUBIq_loading",
359
+ "owner": "eGUBIq_owner",
360
+ "body": "eGUBIq_body",
361
+ "av": "eGUBIq_av",
320
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
+ "cmdSummary": "eGUBIq_cmdSummary",
371
+ "loading": "eGUBIq_loading",
372
+ "top": "eGUBIq_top",
373
+ "cmdDetails": "eGUBIq_cmdDetails",
374
+ "src": "eGUBIq_src",
375
+ "on": "eGUBIq_on",
376
+ "catsCollapsed": "eGUBIq_catsCollapsed",
321
377
  "restart": "eGUBIq_restart",
322
- "sect": "eGUBIq_sect",
323
- "titleRow": "eGUBIq_titleRow",
324
- "catsRow": "eGUBIq_catsRow",
378
+ "dangerArmed": "eGUBIq_dangerArmed",
325
379
  "dangerBtn": "eGUBIq_dangerBtn",
326
380
  "dot": "eGUBIq_dot",
327
- "cats": "eGUBIq_cats",
328
- "progress": "eGUBIq_progress",
329
381
  "sp": "eGUBIq_sp",
330
- "err": "eGUBIq_err",
331
- "spec": "eGUBIq_spec",
332
- "pct": "eGUBIq_pct",
382
+ "desc": "eGUBIq_desc",
383
+ "bar": "eGUBIq_bar",
384
+ "empty": "eGUBIq_empty",
385
+ "warnLine": "eGUBIq_warnLine",
386
+ "pageBtn": "eGUBIq_pageBtn",
387
+ "dshmSlide": "eGUBIq_dshmSlide",
333
388
  "tag": "eGUBIq_tag",
334
- "catsCollapsed": "eGUBIq_catsCollapsed",
335
- "src": "eGUBIq_src",
336
- "cmdSummary": "eGUBIq_cmdSummary",
337
- "on": "eGUBIq_on",
338
- "sentinel": "eGUBIq_sentinel",
389
+ "nm": "eGUBIq_nm",
390
+ "spin": "eGUBIq_spin",
339
391
  "searchInline": "eGUBIq_searchInline",
340
- "foot": "eGUBIq_foot",
341
- "swatches": "eGUBIq_swatches",
342
- "modalNote": "eGUBIq_modalNote",
343
- "body": "eGUBIq_body",
344
- "descTight": "eGUBIq_descTight",
345
- "av": "eGUBIq_av",
346
- "top": "eGUBIq_top",
347
- "okState": "eGUBIq_okState",
348
- "card": "eGUBIq_card",
349
- "head": "eGUBIq_head",
350
- "grid": "eGUBIq_grid"
392
+ "sizeOn": "eGUBIq_sizeOn",
393
+ "barFill": "eGUBIq_barFill",
394
+ "title": "eGUBIq_title",
395
+ "titleRow": "eGUBIq_titleRow",
396
+ "tab": "eGUBIq_tab",
397
+ "row1": "eGUBIq_row1",
398
+ "modalNote": "eGUBIq_modalNote"
351
399
  };
352
400
  //#endregion
353
401
  //#region src/client/MarketSection.tsx
@@ -407,6 +455,13 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
407
455
  */
408
456
  let cachedRegistry = null;
409
457
  let cachedInstalled = null;
458
+ /** Discover grid page-size choices — the catalog grows daily, so cap each page. */
459
+ const PAGE_SIZES = [
460
+ 24,
461
+ 48,
462
+ 96
463
+ ];
464
+ const DEFAULT_PAGE_SIZE = 24;
410
465
  function MarketSection(props) {
411
466
  const t = props.t;
412
467
  const localeSnap = (0, react.useSyncExternalStore)((cb) => props.locale.subscribe(cb), () => props.locale.getSnapshot());
@@ -436,18 +491,10 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
436
491
  const [updates, setUpdates] = (0, react.useState)({});
437
492
  const [updatingName, setUpdatingName] = (0, react.useState)(null);
438
493
  const [staleName, setStaleName] = (0, react.useState)(null);
439
- /**
440
- * Cards rendered so far — the discover grid renders incrementally (60,
441
- * then +120 as the sentinel scrolls into view) instead of all 400+ at
442
- * once, which built a ~70k px DOM and made section switches lag (#30).
443
- */
444
- const [visibleCount, setVisibleCount] = (0, react.useState)(60);
445
- const sentinelRef = (0, react.useCallback)((node) => {
446
- if (node === null) return;
447
- new IntersectionObserver((entries) => {
448
- if (entries.some((entry) => entry.isIntersecting)) setVisibleCount((count) => count + 120);
449
- }, { rootMargin: "600px" }).observe(node);
450
- }, []);
494
+ /** 1-based discover page; reset to 1 whenever the list shape changes. */
495
+ const [page, setPage] = (0, react.useState)(1);
496
+ /** Cards per discover page; changing it jumps back to page 1. */
497
+ const [pageSize, setPageSize] = (0, react.useState)(DEFAULT_PAGE_SIZE);
451
498
  /** Determinate percent parsed from pnpm's Progress line, when available. */
452
499
  const [progressPct, setProgressPct] = (0, react.useState)(null);
453
500
  /** Blocked build scripts from the last install: enables approve-and-retry (#6). */
@@ -594,12 +641,34 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
594
641
  sort
595
642
  ]);
596
643
  (0, react.useEffect)(() => {
597
- setVisibleCount(60);
644
+ setPage(1);
598
645
  }, [
599
646
  q,
600
647
  cat,
601
648
  sort
602
649
  ]);
650
+ const totalPages = Math.max(1, Math.ceil(plugins.length / pageSize));
651
+ const currentPage = Math.min(page, totalPages);
652
+ const pagePlugins = plugins.slice((currentPage - 1) * pageSize, currentPage * pageSize);
653
+ const scrollToTop = () => {
654
+ const el = bodyRef.current;
655
+ if (el) {
656
+ if (typeof el.scrollTo === "function") el.scrollTo({
657
+ top: 0,
658
+ behavior: "smooth"
659
+ });
660
+ else el.scrollTop = 0;
661
+ }
662
+ };
663
+ const goToPage = (next) => {
664
+ setPage(Math.max(1, Math.min(next, totalPages)));
665
+ scrollToTop();
666
+ };
667
+ const changePageSize = (size) => {
668
+ setPageSize(size);
669
+ setPage(1);
670
+ scrollToTop();
671
+ };
603
672
  const doInstall = (0, react.useCallback)((plugin) => {
604
673
  setBuildsSkipped(null);
605
674
  setConfirming(null);
@@ -891,6 +960,13 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
891
960
  className: Market_module_css_default.cancelBtn,
892
961
  onClick: doCancel,
893
962
  children: t("cancelOp")
963
+ }),
964
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
965
+ className: Market_module_css_default.bar,
966
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
967
+ className: progressPct !== null ? Market_module_css_default.barFill : `${Market_module_css_default.barFill} ${Market_module_css_default.barWave}`,
968
+ style: progressPct !== null ? { width: `${progressPct}%` } : void 0
969
+ })
894
970
  })
895
971
  ]
896
972
  })
@@ -1292,10 +1368,68 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
1292
1368
  children: t("empty")
1293
1369
  }) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1294
1370
  className: Market_module_css_default.grid,
1295
- children: plugins.slice(0, visibleCount).map(pluginCard)
1296
- }), plugins.length > visibleCount && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1297
- ref: sentinelRef,
1298
- className: Market_module_css_default.sentinel
1371
+ children: pagePlugins.map(pluginCard)
1372
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1373
+ className: Market_module_css_default.pager,
1374
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1375
+ className: Market_module_css_default.pagerPages,
1376
+ children: totalPages > 1 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
1377
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1378
+ type: "button",
1379
+ className: Market_module_css_default.pageBtn,
1380
+ disabled: currentPage === 1,
1381
+ onClick: () => goToPage(1),
1382
+ "aria-label": t("firstPage"),
1383
+ children: "«"
1384
+ }),
1385
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1386
+ type: "button",
1387
+ className: Market_module_css_default.pageBtn,
1388
+ disabled: currentPage === 1,
1389
+ onClick: () => goToPage(currentPage - 1),
1390
+ children: t("prevPage")
1391
+ }),
1392
+ pageItems(currentPage, totalPages).map((item, i) => item === "…" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1393
+ className: Market_module_css_default.pageEllipsis,
1394
+ children: "…"
1395
+ }, "e" + i) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1396
+ type: "button",
1397
+ className: item === currentPage ? `${Market_module_css_default.pageBtn} ${Market_module_css_default.pageOn}` : Market_module_css_default.pageBtn,
1398
+ onClick: () => goToPage(item),
1399
+ children: item
1400
+ }, item)),
1401
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1402
+ type: "button",
1403
+ className: Market_module_css_default.pageBtn,
1404
+ disabled: currentPage === totalPages,
1405
+ onClick: () => goToPage(currentPage + 1),
1406
+ children: t("nextPage")
1407
+ }),
1408
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1409
+ type: "button",
1410
+ className: Market_module_css_default.pageBtn,
1411
+ disabled: currentPage === totalPages,
1412
+ onClick: () => goToPage(totalPages),
1413
+ "aria-label": t("lastPage"),
1414
+ children: "»"
1415
+ }),
1416
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1417
+ className: Market_module_css_default.pageInfo,
1418
+ children: t("pageInfo").replace("{0}", String(currentPage)).replace("{1}", String(totalPages))
1419
+ })
1420
+ ] })
1421
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1422
+ className: Market_module_css_default.pagerSize,
1423
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1424
+ className: Market_module_css_default.sizeLabel,
1425
+ children: t("perPage")
1426
+ }), PAGE_SIZES.map((size) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1427
+ type: "button",
1428
+ className: size === pageSize ? `${Market_module_css_default.sizeBtn} ${Market_module_css_default.sizeOn}` : Market_module_css_default.sizeBtn,
1429
+ onClick: () => changePageSize(size),
1430
+ children: size
1431
+ }, size))]
1432
+ })]
1299
1433
  })] })] }) : tab === "themes" && themeSnap !== null ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [(() => {
1300
1434
  const extra = themeSnap.themes.filter((def) => def.id !== "light" && def.id !== "dark");
1301
1435
  return extra.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
@@ -1366,6 +1500,13 @@ window.__ModuleLoader__.load({ id: "dshmarket", factory: (require) => {
1366
1500
  className: Market_module_css_default.cancelBtn,
1367
1501
  onClick: doCancel,
1368
1502
  children: t("cancelOp")
1503
+ }),
1504
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1505
+ className: Market_module_css_default.bar,
1506
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1507
+ className: progressPct !== null ? Market_module_css_default.barFill : `${Market_module_css_default.barFill} ${Market_module_css_default.barWave}`,
1508
+ style: progressPct !== null ? { width: `${progressPct}%` } : void 0
1509
+ })
1369
1510
  })
1370
1511
  ]
1371
1512
  })