dsh-plugin-shop 0.8.0 → 0.8.1-beta.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/README.md +2 -0
- package/lib/client.js +349 -259
- package/lib/index.js +7 -1
- package/lib/typert.host.js +2 -1
- package/lib/typert.remote-client.js +1 -0
- package/lib/types/client/locales.d.ts +15 -0
- package/lib/types/client/present.d.ts +21 -0
- package/lib/types/host/types.d.ts +6 -0
- package/package.json +1 -1
package/lib/client.js
CHANGED
|
@@ -4314,7 +4314,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
4314
4314
|
"sha256": string()
|
|
4315
4315
|
})]).optional(),
|
|
4316
4316
|
"added": union([_undefined(), string()]).optional(),
|
|
4317
|
-
"peers": union([_undefined(), array(string())]).optional()
|
|
4317
|
+
"peers": union([_undefined(), array(string())]).optional(),
|
|
4318
|
+
"unpackedSize": union([_undefined(), number()]).optional()
|
|
4318
4319
|
})),
|
|
4319
4320
|
"denied": array(object({
|
|
4320
4321
|
"name": string(),
|
|
@@ -6529,6 +6530,42 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
6529
6530
|
if (n < 1e3) return String(n);
|
|
6530
6531
|
return `${(n / 1e3).toFixed(1).replace(/\.0$/, "")}k`;
|
|
6531
6532
|
}
|
|
6533
|
+
/**
|
|
6534
|
+
* One entry's unpacked size as a label: 0 → "0 B", 812 → "812 B",
|
|
6535
|
+
* 25283 → "25.3 kB", 847407 → "847.4 kB", 179562863 → "179.6 MB".
|
|
6536
|
+
*
|
|
6537
|
+
* Decimal kB/MB, not KiB/MiB, because the number itself is npm's
|
|
6538
|
+
* `dist.unpackedSize` and npm's own package page shows it decimal — a reader
|
|
6539
|
+
* comparing the shelf against npmjs.com must not find two different figures
|
|
6540
|
+
* for one package. One fractional digit at every magnitude above a kilobyte,
|
|
6541
|
+
* the same rule `formatStars` follows: a column of sizes is read by comparing
|
|
6542
|
+
* them down the shelf, and switching precision by magnitude makes that column
|
|
6543
|
+
* ragged for no gain.
|
|
6544
|
+
*
|
|
6545
|
+
* Locale-free by construction (`toFixed`, not `toLocaleString`): the shelf's
|
|
6546
|
+
* two languages must not disagree about what a size is, and a decimal comma
|
|
6547
|
+
* in one of them would read as a thousands separator in the other.
|
|
6548
|
+
*
|
|
6549
|
+
* Undefined in, undefined out — a github entry and an old npm publish both
|
|
6550
|
+
* have no figure, and the card renders no label rather than a guess. The
|
|
6551
|
+
* caller need not check first.
|
|
6552
|
+
*/
|
|
6553
|
+
function formatSize(bytes) {
|
|
6554
|
+
if (bytes === void 0) return void 0;
|
|
6555
|
+
if (bytes < 1e3) return `${bytes} B`;
|
|
6556
|
+
let value = bytes;
|
|
6557
|
+
let unit = "B";
|
|
6558
|
+
for (const next of [
|
|
6559
|
+
"kB",
|
|
6560
|
+
"MB",
|
|
6561
|
+
"GB"
|
|
6562
|
+
]) {
|
|
6563
|
+
if (Number(value.toFixed(1)) < 1e3) break;
|
|
6564
|
+
value /= 1e3;
|
|
6565
|
+
unit = next;
|
|
6566
|
+
}
|
|
6567
|
+
return `${value.toFixed(1)} ${unit}`;
|
|
6568
|
+
}
|
|
6532
6569
|
//#endregion
|
|
6533
6570
|
//#region src/client/locales.ts
|
|
6534
6571
|
/** Copy dictionaries for the shop Settings tab. */
|
|
@@ -6581,6 +6618,15 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
6581
6618
|
repository: "仓库",
|
|
6582
6619
|
npmPage: "npm 页面",
|
|
6583
6620
|
authorLine: "作者:{author}",
|
|
6621
|
+
/** The accessible name and tooltip of the size label; the label itself shows
|
|
6622
|
+
* the bare figure. "解包后" is the load-bearing word — the number is npm's
|
|
6623
|
+
* unpacked size, not the download. */
|
|
6624
|
+
sizeLabel: "解包后 {size}",
|
|
6625
|
+
hideIncompatible: "隐藏不兼容 {count}",
|
|
6626
|
+
showIncompatible: "显示不兼容 {count}",
|
|
6627
|
+
incompatibleFilterTitle: "不显示缺少组件的插件",
|
|
6628
|
+
showIncompatibleTitle: "把缺少组件的插件放回列表",
|
|
6629
|
+
emptyIncompatibleFiltered: "匹配的插件都缺少组件,已被「隐藏不兼容」筛掉。",
|
|
6584
6630
|
license: "许可",
|
|
6585
6631
|
customLicense: "自定义许可",
|
|
6586
6632
|
reviewedVersionLine: "已审核 v{reviewed} / 当前 v{current} 未审核",
|
|
@@ -6674,6 +6720,12 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
6674
6720
|
repository: "Repository",
|
|
6675
6721
|
npmPage: "npm page",
|
|
6676
6722
|
authorLine: "Author: {author}",
|
|
6723
|
+
sizeLabel: "{size} unpacked",
|
|
6724
|
+
hideIncompatible: "Hide incompatible {count}",
|
|
6725
|
+
showIncompatible: "Show incompatible {count}",
|
|
6726
|
+
incompatibleFilterTitle: "Leave out plugins whose components are missing",
|
|
6727
|
+
showIncompatibleTitle: "Put plugins whose components are missing back on the shelf",
|
|
6728
|
+
emptyIncompatibleFiltered: "Every matching plugin is missing components, and the incompatible filter is leaving them out.",
|
|
6677
6729
|
license: "License",
|
|
6678
6730
|
customLicense: "Custom license",
|
|
6679
6731
|
reviewedVersionLine: "reviewed v{reviewed} / current v{current} unreviewed",
|
|
@@ -6918,111 +6970,114 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
6918
6970
|
};
|
|
6919
6971
|
}
|
|
6920
6972
|
//#endregion
|
|
6921
|
-
//#region \0dsh-plugin-shop-css:
|
|
6922
|
-
const css = "/* Shop tab styles — a market shelf inside the settings surface. The visual\n * language is the dsh theme's alias tokens ONLY (the four tokens the previous\n * styles referenced that do not exist — bg-layer-3, interactive-bg-hover,\n * state-error, state-success — are corrected to bg-layer-2 and the\n * state-*-primary set). The signature is the category spine: one HUE per\n * category (seven fixed hues, not the brand token — the brand resolves to\n * near-black in the light theme, so seven brand opacities read as seven\n * shades of gray), with the category name as the cover label in the same hue. Class names are mapped to content-derived names at bundle time\n * (tsdown.sfae5fa_client.se9da7d_config.se722f1_ts) and stubbed in tests; only the keys are relied\n * on.\n *\n * One token rule the theme forces: the background LAYERS do not carry\n * contrast. In the light theme bg-base, bg-layer-1, bg-layer-2 and\n * bg-layer-3 all resolve to the same white; only the dark theme spreads them\n * (950/875/850/800). So a layer-2 fill on a layer-1 ground is invisible for\n * half of all users, and anything whose fill is its ONLY affordance — the\n * loading skeleton, the borderless capability chips — derives its fill from\n * label-primary instead, which inverts with the theme by construction.\n * Elements that also carry a border or text may keep a layer fill.\n * `css-tokens.sfae5fa_client.s2f7a8b_spec.se722f1_ts` pins this. */\n\n.s99b207_panel {\n display: flex;\n flex-direction: column;\n gap: 14px;\n /* The shelf never scrolls sideways: a card too wide for its track wraps\n * its badges rather than widening the panel.\n *\n * Clipped on BOTH axes, with a margin, because `.se23a0e_searchInput` sits at\n * exactly (0, 0) of this box — it is the first child of `.s27ad76_toolbar`, itself\n * the first child here, and this rule carries no padding — so its focus\n * ring paints ENTIRELY outside the panel.\n *\n * Both axes is the load-bearing part: `overflow-clip-margin` is inert\n * unless the element clips on both. Clipping x alone left the margin doing\n * nothing — measured against the live app on 0.7.1, the ring reached 0 of\n * its 3px on the left at every device pixel ratio (1, 1.25, 1.5, 2), while\n * keeping the full 3px on the right, where the 280px input stops short of\n * the panel and never meets the clip edge. Raising the margin to 6px\n * changed nothing; clipping both axes with the SAME 3px restored the whole\n * ring. A test that reads declarations cannot see that difference, which is\n * why the first attempt at this shipped broken.\n *\n * `clip` is not a scroll container, so this does not bring back the\n * accidental scrolling `hidden` caused by coercing the other axis to\n * `auto`. Nothing is lost vertically: the panel's scrollHeight equals its\n * height and no descendant paints outside the clip rect (measured).\n * `overflow-x: hidden` stays as the fallback for engines without `clip`,\n * where the ring is clipped as it was before, never worse. */\n overflow-x: hidden;\n overflow: clip;\n overflow-clip-margin: 3px;\n}\n\n.s2abe0f_stateLine {\n margin: 0;\n color: var(--dsw-alias-label-primary);\n font-size: 13px;\n}\n\n/* Visually hidden but screen-reader readable (the loading copy while the\n * skeleton stands in visually). */\n.sfb85e5_srOnly {\n position: absolute;\n width: 1px;\n height: 1px;\n margin: -1px;\n padding: 0;\n border: 0;\n clip: rect(0 0 0 0);\n clip-path: inset(50%);\n overflow: hidden;\n white-space: nowrap;\n}\n\n/* The loading shelf: ghost cards with the same geometry as the real grid, so\n * the swap to content is a same-shape handoff instead of a jump. */\n.s728a01_skeletonGrid {\n display: grid;\n grid-template-columns: 1fr;\n gap: 8px;\n}\n\n.s33d002_skeletonCard {\n position: relative;\n display: flex;\n flex-direction: column;\n border: 1px solid var(--dsw-alias-border-l1);\n border-radius: 10px;\n background: var(--dsw-alias-bg-layer-1);\n overflow: hidden;\n}\n\n/* The shimmer sweep: one gradient band travels across each ghost card while\n * the bars breathe, so the loading state reads as \"the shelf is scanning\". */\n.s33d002_skeletonCard::after {\n content: '';\n position: absolute;\n inset: 0;\n background: linear-gradient(\n 100deg,\n transparent 25%,\n color-mix(in srgb, var(--dsw-alias-label-primary) 14%, transparent) 50%,\n transparent 75%\n );\n transform: translateX(-100%);\n animation: dshShopSkeletonSweep 1.4s ease-in-out infinite;\n pointer-events: none;\n}\n\n@keyframes dshShopSkeletonSweep {\n to { transform: translateX(100%); }\n}\n\n.s46e666_skeletonName {\n width: 55%;\n height: 14px;\n margin: 10px 12px 0;\n border-radius: 4px;\n background: color-mix(in srgb, var(--dsw-alias-label-primary) 8%, transparent);\n}\n\n.s2a467d_skeletonSummary {\n width: 92%;\n height: 12px;\n margin: 10px 12px 0;\n border-radius: 4px;\n background: color-mix(in srgb, var(--dsw-alias-label-primary) 8%, transparent);\n}\n\n.s232601_skeletonSummaryShort {\n width: 68%;\n height: 12px;\n margin: 6px 12px 10px;\n border-radius: 4px;\n background: color-mix(in srgb, var(--dsw-alias-label-primary) 8%, transparent);\n}\n\n/* The ghost of the action line, right where the real buttons land. */\n.sde9b0c_skeletonActions {\n display: block;\n width: 84px;\n height: 24px;\n margin: 0 12px 10px;\n border-radius: 999px;\n background: color-mix(in srgb, var(--dsw-alias-label-primary) 8%, transparent);\n}\n\n.s33d002_skeletonCard span {\n animation: dshShopSkeletonPulse 1.6s ease-in-out infinite;\n}\n\n@keyframes dshShopSkeletonPulse {\n 0%, 100% { opacity: 0.5; }\n 50% { opacity: 1; }\n}\n\n@media (prefers-reduced-motion: reduce) {\n .s33d002_skeletonCard span { animation: none; opacity: 0.75; }\n .s33d002_skeletonCard::after { content: none; }\n}\n\n.sb632c0_actionButton {\n align-self: flex-start;\n padding: 5px 14px;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 6px;\n background: var(--dsw-alias-bg-layer-2);\n color: var(--dsw-alias-label-primary);\n font-size: 13px;\n cursor: pointer;\n}\n\n.sb632c0_actionButton:hover {\n border-color: color-mix(in srgb, var(--dsw-alias-brand-primary) 45%, var(--dsw-alias-border-l2));\n color: var(--dsw-alias-brand-primary);\n}\n\n.sb632c0_actionButton:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary);\n outline-offset: 1px;\n}\n\n.s27ad76_toolbar {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 12px;\n flex-wrap: wrap;\n}\n\n.saba3c3_toolbarRight {\n display: flex;\n align-items: center;\n gap: 12px;\n flex-wrap: wrap;\n}\n\n/* The shop's own version, right of the search box: `v0.4.4`, plus the\n * update button when the version check found a newer release. */\n.s6736c0_versionBlock {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.s2dff04_versionText {\n font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;\n font-size: 12px;\n letter-spacing: 0.02em;\n color: var(--dsw-alias-label-secondary);\n}\n\n.s40b16e_updateSelfButton {\n padding: 2px 10px;\n border: 1px solid var(--dsw-alias-brand-primary);\n border-radius: 999px;\n background: color-mix(in srgb, var(--dsw-alias-brand-primary) 12%, transparent);\n color: var(--dsw-alias-brand-primary);\n font-size: 12px;\n font-weight: 600;\n cursor: pointer;\n}\n\n.s40b16e_updateSelfButton:hover {\n background: color-mix(in srgb, var(--dsw-alias-brand-primary) 20%, transparent);\n}\n\n.s40b16e_updateSelfButton:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary);\n outline-offset: 1px;\n}\n\n/* The on-demand re-check next to the version number: a quiet pill; the\n * border and text carry it in the light theme where bg layers are white. */\n.secd6a2_checkUpdateButton {\n padding: 2px 10px;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 999px;\n background: var(--dsw-alias-bg-layer-2);\n color: var(--dsw-alias-label-secondary);\n font-size: 12px;\n cursor: pointer;\n}\n\n.secd6a2_checkUpdateButton:hover {\n border-color: var(--dsw-alias-label-secondary);\n color: var(--dsw-alias-label-primary);\n}\n\n.secd6a2_checkUpdateButton:disabled {\n opacity: 0.6;\n cursor: default;\n}\n\n.secd6a2_checkUpdateButton:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary);\n outline-offset: 1px;\n}\n\n/* The project's GitHub mark, right of the version row: a quiet icon link.\n * The octocat carries itself — color shift on hover, no text, no border. */\n.s5e1ce3_githubLink {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n padding: 3px;\n border-radius: 6px;\n color: var(--dsw-alias-label-secondary);\n}\n\n.s5e1ce3_githubLink:hover {\n color: var(--dsw-alias-label-primary);\n background: var(--dsw-alias-bg-layer-2);\n}\n\n.s5e1ce3_githubLink:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary);\n outline-offset: 1px;\n}\n\n/* The self-update's expanded states (running log / done + restart /\n * failure detail) sit under the toolbar, above the category bar. */\n.s798348_selfUpdatePanel {\n display: flex;\n flex-direction: column;\n gap: 8px;\n margin-top: 8px;\n}\n\n.se23a0e_searchInput {\n width: min(280px, 100%);\n padding: 6px 10px;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 6px;\n background: var(--dsw-alias-bg-layer-1);\n color: var(--dsw-alias-label-primary);\n font-size: 13px;\n}\n\n.se23a0e_searchInput:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary);\n outline-offset: 1px;\n}\n\n.see2588_staleBadge {\n padding: 2px 8px;\n border-radius: 999px;\n background: color-mix(in srgb, var(--dsw-alias-state-warn-primary) 14%, transparent);\n border: 1px solid color-mix(in srgb, var(--dsw-alias-state-warn-primary) 40%, transparent);\n color: var(--dsw-alias-state-warn-primary);\n font-size: 12px;\n}\n\n.se67e0b_categoryBar {\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n margin-top: 6px;\n}\n\n.s8c06a0_categoryButton {\n padding: 3px 10px;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 999px;\n background: var(--dsw-alias-bg-layer-1);\n color: var(--dsw-alias-label-secondary);\n font-size: 12px;\n cursor: pointer;\n}\n\n.s8c06a0_categoryButton:hover {\n border-color: color-mix(in srgb, var(--dsw-alias-brand-primary) 45%, var(--dsw-alias-border-l2));\n color: var(--dsw-alias-brand-primary);\n}\n\n.s65a55a_categoryButtonOn {\n border-color: var(--dsw-alias-brand-primary);\n background: color-mix(in srgb, var(--dsw-alias-brand-primary) 12%, transparent);\n color: var(--dsw-alias-brand-primary);\n font-weight: 600;\n}\n\n.s8c06a0_categoryButton:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary);\n outline-offset: 1px;\n}\n\n.sb6cdd6_catalogHeading {\n margin: 2px 0 0;\n font-size: 16px;\n font-weight: 600;\n letter-spacing: 0.02em;\n color: var(--dsw-alias-label-primary);\n}\n\n.sf2305c_catalogStatsRow {\n display: flex;\n align-items: center;\n gap: 10px;\n margin: 6px 0 0;\n}\n\n.s38a33e_catalogStats {\n margin: 0;\n font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;\n font-size: 12px;\n letter-spacing: 0.02em;\n color: var(--dsw-alias-label-secondary);\n}\n\n/* Sits beside the 12px stats caption, so it is quieter than `.sb632c0_actionButton`:\n * this is an affordance, not a call to action — the catalog reloads on its\n * own at mount and the shelf is already usable without it. */\n.s71d105_reloadButton {\n padding: 1px 9px;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 999px;\n background: transparent;\n color: var(--dsw-alias-label-secondary);\n font-size: 11px;\n line-height: 17px;\n cursor: pointer;\n}\n\n.s71d105_reloadButton:hover:not(:disabled) {\n border-color: color-mix(in srgb, var(--dsw-alias-brand-primary) 45%, var(--dsw-alias-border-l2));\n color: var(--dsw-alias-brand-primary);\n}\n\n.s71d105_reloadButton:disabled {\n cursor: default;\n opacity: 0.6;\n}\n\n.s71d105_reloadButton:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary);\n outline-offset: 1px;\n}\n\n.sa079ea_reloadFailed {\n font-size: 11px;\n color: var(--dsw-alias-state-warn-primary);\n}\n\n.se3ba96_emptyLine {\n margin: 0;\n color: var(--dsw-alias-label-primary);\n font-size: 13px;\n}\n\n/* The shelf: a responsive grid of cards. */\n/* Single-line rows: one full-width column, one plugin per line. */\n.sb41fe1_cards {\n display: grid;\n grid-template-columns: 1fr;\n max-width: 100%;\n gap: 8px;\n list-style: none;\n margin: 0;\n padding: 0;\n animation: dshShopCardsIn 220ms ease;\n}\n\n@keyframes dshShopCardsIn {\n from { opacity: 0; transform: translateY(3px); }\n to { opacity: 1; transform: none; }\n}\n\n@media (prefers-reduced-motion: reduce) {\n .sb41fe1_cards { animation: none; }\n}\n\n.sfcd584_card {\n position: relative;\n display: flex;\n flex-direction: column;\n /* A grid item's min-width is auto by default: its content would widen the\n * 1fr track past the panel and overflow horizontally. */\n min-width: 0;\n border: 1px solid var(--dsw-alias-border-l1);\n border-radius: 10px;\n background: var(--dsw-alias-bg-layer-1);\n overflow: hidden;\n transition: border-color 120ms ease, transform 120ms ease, box-shadow 120ms ease;\n /* Off-screen cards skip layout and paint; the placeholder keeps scrollbar\n * estimation sane before the browser has measured the real height. */\n content-visibility: auto;\n contain-intrinsic-size: auto 140px;\n}\n\n/* The sentinel that triggers the next shelf batch: zero visual footprint. */\n.sf2d932_cardsSentry {\n height: 1px;\n margin: 0;\n padding: 0;\n}\n\n.s947694_showingLine {\n margin: 0;\n font-size: 12px;\n letter-spacing: 0.02em;\n color: var(--dsw-alias-label-secondary);\n}\n\n.sfcd584_card:hover {\n border-color: color-mix(in srgb, var(--dsw-alias-brand-primary) 45%, var(--dsw-alias-border-l1));\n transform: translateY(-1px);\n box-shadow: 0 2px 8px color-mix(in srgb, var(--dsw-alias-brand-primary) 12%, transparent);\n}\n\n@media (prefers-reduced-motion: reduce) {\n .sfcd584_card { transition: none; }\n .sfcd584_card:hover { transform: none; }\n}\n\n/* The signature: a spine and cover in the category's own hue. The hues are\n * fixed mid-bright colors that read on both themes; `other` deliberately\n * stays a neutral gray so the fallback category does not compete. */\n.sfc4028_cardSpine {\n position: absolute;\n top: 0;\n bottom: 0;\n left: 0;\n width: 3px;\n background: var(--spine-hue, #8B8E96);\n}\n\n.sfcd584_card[data-category='tool'] { --spine-hue: #4C8DFF; }\n.sfcd584_card[data-category='provider'] { --spine-hue: #A78BFA; }\n.sfcd584_card[data-category='ui'] { --spine-hue: #2DD4BF; }\n.sfcd584_card[data-category='workflow'] { --spine-hue: #F59E0B; }\n.sfcd584_card[data-category='integration'] { --spine-hue: #34D399; }\n.sfcd584_card[data-category='theme'] { --spine-hue: #F472B6; }\n.sfcd584_card[data-category='other'] { --spine-hue: #8B8E96; }\n\n/* The category sits in the badge row as a quiet chip in the category's own\n * hue — the border carries it where the light theme's white layers cannot\n * (the same lesson as the check button). */\n.sb94610_categoryBadge {\n padding: 1px 7px;\n border: 1px solid color-mix(in srgb, var(--spine-hue, #8B8E96) 45%, transparent);\n border-radius: 999px;\n font-size: 11px;\n font-weight: 600;\n letter-spacing: 0.08em;\n text-transform: uppercase;\n color: var(--spine-hue, #8B8E96);\n white-space: nowrap;\n}\n\n.s50a94e_entryHeader {\n display: flex;\n flex-direction: row;\n align-items: center;\n gap: 12px;\n min-width: 0;\n padding: 8px 12px 2px;\n border: none;\n background: transparent;\n color: inherit;\n font: inherit;\n text-align: left;\n cursor: pointer;\n}\n\n.s50a94e_entryHeader:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary);\n outline-offset: -2px;\n}\n\n/* The name fills the row and truncates rather than wraps; the badges stay\n * intact beside it. */\n.sfdbf47_name {\n font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;\n font-size: 13px;\n font-weight: 600;\n flex: 1 1 auto;\n min-width: 0;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n color: var(--dsw-alias-label-primary);\n}\n\n.s28e55e_badges {\n display: flex;\n align-items: center;\n flex-wrap: wrap;\n gap: 6px;\n}\n\n/* The action line: buttons side by side; an active install/uninstall flow\n * (gate, log, notices) takes the full width below them. */\n.s9359c0_cardActions {\n display: flex;\n flex-direction: row;\n flex-wrap: wrap;\n align-items: center;\n gap: 8px;\n padding: 8px 12px 10px;\n}\n\n.s9359c0_cardActions > .s549462_gate,\n.s9359c0_cardActions > .s20fbe0_installPanel,\n.s9359c0_cardActions > .s94517f_installedActions {\n flex-basis: 100%;\n}\n\n/* The entry's version, always visible on the card (the expanded detail\n * repeats it in the version row) — the same quiet mono as the toolbar. */\n.sc54e24_cardVersion {\n font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;\n font-size: 12px;\n letter-spacing: 0.02em;\n color: var(--dsw-alias-label-secondary);\n}\n\n/* The octocat marking a github-sourced entry, beside its short commit. */\n.s623bee_sourceBadge {\n display: inline-flex;\n align-items: center;\n color: var(--dsw-alias-label-secondary);\n}\n\n.sf9a12c_tierBadge {\n padding: 1px 7px;\n border-radius: 999px;\n font-size: 11px;\n line-height: 1.6;\n}\n\n.sf9a12c_tierBadge[data-tier='verified'] {\n color: var(--dsw-alias-state-success-primary);\n background: color-mix(in srgb, var(--dsw-alias-state-success-primary) 14%, transparent);\n border: 1px solid color-mix(in srgb, var(--dsw-alias-state-success-primary) 40%, transparent);\n}\n\n.sf9a12c_tierBadge[data-tier='verified-stale'] {\n color: var(--dsw-alias-state-warn-primary);\n background: color-mix(in srgb, var(--dsw-alias-state-warn-primary) 14%, transparent);\n border: 1px solid color-mix(in srgb, var(--dsw-alias-state-warn-primary) 40%, transparent);\n}\n\n.sf9a12c_tierBadge[data-tier='community'] {\n color: var(--dsw-alias-label-secondary);\n background: var(--dsw-alias-bg-layer-2);\n border: 1px solid var(--dsw-alias-border-l2);\n}\n\n.s671f97_incompatibleBadge {\n flex-shrink: 0;\n padding: 3px 9px;\n border-radius: 999px;\n font-size: 12px;\n white-space: nowrap;\n color: var(--dsw-alias-state-error-primary);\n background: color-mix(in srgb, var(--dsw-alias-state-error-primary) 14%, transparent);\n border: 1px solid color-mix(in srgb, var(--dsw-alias-state-error-primary) 40%, transparent);\n}\n\n.s963e5c_starsBadge {\n font-size: 11px;\n color: var(--dsw-alias-label-secondary);\n}\n\n.sbb5739_chevron, .s4e56e8_chevronOpen {\n color: var(--dsw-alias-label-secondary);\n transition: transform 120ms ease;\n}\n\n.s4e56e8_chevronOpen { transform: rotate(180deg); }\n\n@media (prefers-reduced-motion: reduce) {\n .sbb5739_chevron, .s4e56e8_chevronOpen { transition: none; }\n}\n\n.sf9a60a_body {\n display: flex;\n flex-direction: column;\n gap: 8px;\n padding: 0 12px;\n}\n\n.sfd2791_summary {\n margin: 0;\n font-size: 13px;\n line-height: 1.5;\n color: var(--dsw-alias-label-primary);\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n overflow: hidden;\n}\n\n.s69ed84_summaryZh {\n margin: -4px 0 0;\n font-size: 12px;\n line-height: 1.5;\n color: var(--dsw-alias-label-secondary);\n display: -webkit-box;\n -webkit-line-clamp: 1;\n -webkit-box-orient: vertical;\n overflow: hidden;\n}\n\n/* Expanded cards show the full summary: the clamp is lifted, never raised —\n * a higher number would still truncate the author's text, just later. */\n.s83c8c8_summaryExpanded {\n -webkit-line-clamp: unset;\n display: block;\n}\n\n.s20b5b9_summaryZhExpanded {\n -webkit-line-clamp: unset;\n display: block;\n}\n\n/* `white-space: pre-line` so the newline in the copy is the copy's own: the\n dictionary decides where the line breaks, and a translator changes it\n without touching the component. Collapses runs of spaces like `normal`, so\n only the explicit \\n survives. */\n.s45793c_incompatibleDetail {\n margin: 0;\n font-size: 12px;\n line-height: 1.5;\n white-space: pre-line;\n color: var(--dsw-alias-state-error-primary);\n}\n\n.s551fd2_capabilitiesBlock {\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.sb1f0de_capabilitiesNote {\n margin: 0;\n font-size: 11px;\n color: var(--dsw-alias-label-secondary);\n}\n\n.s9a5379_capabilities {\n display: flex;\n flex-wrap: wrap;\n gap: 4px;\n list-style: none;\n margin: 0;\n padding: 0;\n}\n\n.s9a5379_capabilities li {\n padding: 1px 6px;\n border-radius: 4px;\n background: color-mix(in srgb, var(--dsw-alias-label-primary) 6%, transparent);\n font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;\n font-size: 11px;\n color: var(--dsw-alias-label-secondary);\n}\n\n.s9e0e76_detail {\n border-top: 1px solid var(--dsw-alias-border-l1);\n padding-top: 8px;\n}\n\n.s41121d_detailRows {\n display: flex;\n flex-direction: column;\n gap: 4px;\n margin: 0;\n}\n\n.s852a05_detailRow {\n display: flex;\n justify-content: space-between;\n gap: 12px;\n font-size: 12px;\n}\n\n.s852a05_detailRow dt {\n color: var(--dsw-alias-label-secondary);\n}\n\n.s852a05_detailRow dd {\n margin: 0;\n font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;\n overflow-wrap: anywhere;\n text-align: right;\n color: var(--dsw-alias-label-primary);\n}\n\n.s852a05_detailRow a {\n color: var(--dsw-alias-brand-primary);\n text-decoration: none;\n}\n\n.s852a05_detailRow a:hover {\n text-decoration: underline;\n}\n\n.s852a05_detailRow a:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary);\n outline-offset: 1px;\n}\n\n/* The publishing account, beside the npm link. Secondary label colour and a\n * middot separator carry the distinction — never a background fill, which is\n * invisible in the light theme where every bg-layer token is the same white. */\n/* Who published the entry, at the right edge of the action row. `margin-left:\n * auto` is what pushes it there; the row is a wrapping flex, so an active\n * install flow (which claims the full width) drops this to the next line\n * rather than squeezing it. */\n.s367f3b_author {\n margin-left: auto;\n color: var(--dsw-alias-label-secondary);\n font-size: 12px;\n}\n\n.s2f9e91_reviewedLine {\n margin: 8px 0 0;\n padding: 6px 8px;\n border-radius: 6px;\n background: color-mix(in srgb, var(--dsw-alias-state-warn-primary) 12%, transparent);\n font-size: 12px;\n color: var(--dsw-alias-state-warn-primary);\n}\n\n/* Install flow. */\n.s20fbe0_installPanel {\n display: flex;\n flex-direction: column;\n gap: 8px;\n margin-top: 2px;\n}\n\n.s89d599_installButton, .s7b4348_confirmButton, .s20b00b_cancelButton {\n align-self: flex-start;\n padding: 5px 14px;\n border-radius: 6px;\n font-size: 13px;\n cursor: pointer;\n}\n\n.s89d599_installButton {\n border: 1px solid var(--dsw-alias-brand-primary);\n background: var(--dsw-alias-brand-primary);\n color: var(--dsw-alias-bg-base);\n}\n\n.s89d599_installButton:hover {\n background: color-mix(in srgb, var(--dsw-alias-brand-primary) 88%, var(--dsw-alias-label-primary));\n}\n\n.s7b4348_confirmButton {\n border: 1px solid var(--dsw-alias-brand-primary);\n background: var(--dsw-alias-brand-primary);\n color: var(--dsw-alias-bg-base);\n}\n\n.s7b4348_confirmButton:hover {\n background: color-mix(in srgb, var(--dsw-alias-brand-primary) 88%, var(--dsw-alias-label-primary));\n}\n\n.s20b00b_cancelButton {\n border: 1px solid var(--dsw-alias-border-l2);\n background: var(--dsw-alias-bg-layer-2);\n color: var(--dsw-alias-label-primary);\n}\n\n.s20b00b_cancelButton:hover {\n border-color: var(--dsw-alias-label-secondary);\n}\n\n.s89d599_installButton:focus-visible, .s7b4348_confirmButton:focus-visible, .s20b00b_cancelButton:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary);\n outline-offset: 1px;\n}\n\n/* The shelf card of a plugin that is installed and current carries this\n * non-interactive label instead of an install button. Border + text do the\n * work in the light theme, where every bg-layer token resolves to white. */\n.s1e55fb_installedLabel {\n align-self: flex-start;\n margin: 0;\n padding: 5px 14px;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 6px;\n font-size: 13px;\n color: var(--dsw-alias-label-secondary);\n background: var(--dsw-alias-bg-layer-2);\n}\n\n/* An installed card's controls: the installed label or the update button,\n * plus the uninstall button. The install panel's running/failed states are\n * column layouts and sit as one item of this row. */\n.s94517f_installedActions {\n display: flex;\n align-items: flex-start;\n flex-wrap: wrap;\n gap: 8px;\n}\n\n/* Uninstall revokes privilege; the quiet outline keeps it from competing\n * with the primary action, and the error tint says \"removes\". */\n.s432016_uninstallButton {\n align-self: flex-start;\n padding: 5px 14px;\n border: 1px solid color-mix(in srgb, var(--dsw-alias-state-error-primary) 55%, transparent);\n border-radius: 6px;\n background: transparent;\n color: var(--dsw-alias-state-error-primary);\n font-size: 13px;\n cursor: pointer;\n}\n\n.s432016_uninstallButton:hover {\n background: color-mix(in srgb, var(--dsw-alias-state-error-primary) 10%, transparent);\n}\n\n.s432016_uninstallButton:focus-visible {\n outline: 2px solid var(--dsw-alias-state-error-primary);\n outline-offset: 1px;\n}\n\n/* The restart dsh button on a done install: quiet outline, same rank as\n * the other secondary actions. */\n.sdc8ac4_restartSelfButton {\n /* The version row's third state. Geometry matches .secd6a2_checkUpdateButton and\n * .s40b16e_updateSelfButton exactly — the row is one evolving control and a\n * different pill would read as a different kind of thing. It takes the\n * emphasised fill rather than the neutral one because at that moment the\n * restart is the only thing left to do, the same reason Update has it. */\n padding: 2px 10px;\n border: 1px solid var(--dsw-alias-brand-primary);\n border-radius: 999px;\n background: color-mix(in srgb, var(--dsw-alias-brand-primary) 12%, transparent);\n color: var(--dsw-alias-brand-primary);\n font-size: 12px;\n font-weight: 600;\n cursor: pointer;\n}\n\n.sdc8ac4_restartSelfButton:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary);\n outline-offset: 1px;\n}\n\n.s5c0f5a_restartButton {\n align-self: flex-start;\n padding: 5px 14px;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 6px;\n background: var(--dsw-alias-bg-layer-2);\n color: var(--dsw-alias-label-primary);\n font-size: 13px;\n cursor: pointer;\n}\n\n.s5c0f5a_restartButton:hover {\n border-color: var(--dsw-alias-label-secondary);\n}\n\n.s5c0f5a_restartButton:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary);\n outline-offset: 1px;\n}\n\n.s549462_gate {\n display: flex;\n flex-direction: column;\n gap: 8px;\n padding: 10px;\n border: 1px solid var(--dsw-alias-state-warn-primary);\n border-radius: 8px;\n background: color-mix(in srgb, var(--dsw-alias-state-warn-primary) 8%, transparent);\n}\n\n.sed2c7d_gateTitle {\n margin: 0;\n font-size: 13px;\n font-weight: 600;\n color: var(--dsw-alias-state-warn-primary);\n}\n\n.sdce129_gateBody {\n margin: 0;\n font-size: 12px;\n line-height: 1.6;\n color: var(--dsw-alias-label-primary);\n}\n\n.sfae869_gateWarning {\n margin: 0;\n font-size: 12px;\n line-height: 1.6;\n white-space: pre-line;\n color: var(--dsw-alias-state-error-primary);\n}\n\n.sae8426_gateActions {\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n}\n\n.s260a62_installing {\n margin: 0;\n font-size: 12px;\n color: var(--dsw-alias-label-secondary);\n}\n\n.sba0b9c_log {\n max-height: 160px;\n overflow: auto;\n margin: 0;\n padding: 8px;\n border-radius: 6px;\n background: var(--dsw-alias-bg-base);\n border: 1px solid var(--dsw-alias-border-l1);\n list-style: none;\n font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;\n font-size: 11px;\n line-height: 1.5;\n}\n\n.s5c7c9d_logLine {\n white-space: pre-wrap;\n word-break: break-all;\n color: var(--dsw-alias-label-secondary);\n}\n\n.sebdc74_notice {\n margin: 0;\n font-size: 12px;\n color: var(--dsw-alias-state-success-primary);\n}\n\n.s2672db_failedHeading {\n margin: 0;\n font-size: 12px;\n font-weight: 600;\n color: var(--dsw-alias-state-error-primary);\n}\n\n.s3a9748_failedDetail {\n margin: 0;\n font-size: 12px;\n line-height: 1.6;\n color: var(--dsw-alias-label-primary);\n}\n\n.sc1144d_rejectedCode {\n margin: 0;\n font-size: 12px;\n font-weight: 600;\n color: var(--dsw-alias-state-error-primary);\n}\n\n.s2209a3_rejectedDetail {\n margin: 0;\n font-size: 12px;\n line-height: 1.6;\n color: var(--dsw-alias-label-primary);\n}\n\n/* Installed section. */\n.sb4abbb_outdatedSection {\n display: flex;\n flex-direction: column;\n gap: 8px;\n margin-top: 6px;\n}\n\n.sbca39c_outdatedList {\n display: flex;\n flex-direction: column;\n gap: 8px;\n list-style: none;\n margin: 0;\n padding: 0;\n}\n\n.s1abd04_outdatedRow {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 12px;\n flex-wrap: wrap;\n padding: 10px 12px;\n border: 1px solid var(--dsw-alias-border-l1);\n border-radius: 8px;\n background: var(--dsw-alias-bg-layer-1);\n}\n\n.s10dca9_outdatedInfo {\n display: flex;\n flex-direction: column;\n gap: 2px;\n min-width: 0;\n}\n\n.s10dca9_outdatedInfo strong {\n font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;\n font-size: 13px;\n word-break: break-all;\n color: var(--dsw-alias-label-primary);\n}\n\n.sb04966_outdatedVersions {\n /* Two inline labels with nothing between them in the markup ran together as\n * `installed v1.0.0latest v2.0.0`: JSX drops the whitespace-only line, and\n * the per-label class the markup asked for was never defined (singular\n * against this rule's plural). The container owns the gap, the same idiom\n * as .s28e55e_badges — the labels need no class of their own. */\n display: inline-flex;\n align-items: center;\n gap: 8px;\n font-size: 12px;\n color: var(--dsw-alias-label-secondary);\n}\n\n.see54bf_outdatedActions {\n display: flex;\n align-items: center;\n gap: 10px;\n}\n\n/* The enable/disable switch. */\n.sa65b66_switch {\n position: relative;\n width: 32px;\n height: 18px;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 999px;\n background: var(--dsw-alias-bg-layer-2);\n cursor: pointer;\n transition: background 120ms ease, border-color 120ms ease;\n}\n\n.s50b82f_switchOn {\n border-color: var(--dsw-alias-state-success-primary);\n background: color-mix(in srgb, var(--dsw-alias-state-success-primary) 55%, transparent);\n}\n\n.sbbb39a_switchKnob {\n position: absolute;\n top: 2px;\n left: 2px;\n width: 12px;\n height: 12px;\n border-radius: 999px;\n background: var(--dsw-alias-label-primary);\n transition: transform 120ms ease, background 120ms ease;\n}\n\n.s50b82f_switchOn .sbbb39a_switchKnob {\n transform: translateX(14px);\n background: var(--dsw-alias-bg-base);\n}\n\n.sa65b66_switch:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary);\n outline-offset: 1px;\n}\n\n@media (prefers-reduced-motion: reduce) {\n .sa65b66_switch, .sbbb39a_switchKnob { transition: none; }\n}\n\n/* The hot enable/disable switch on installed rows: the knob button plus the\n * §8 hot-apply / failure notices rendered beside it. */\n.s24b48c_switchWrap {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n}\n";
|
|
6923
|
-
if (typeof document !== "undefined" && !document.querySelector("style[data-plugin-css=\"
|
|
6973
|
+
//#region \0dsh-plugin-shop-css:e3675a89
|
|
6974
|
+
const css = "/* Shop tab styles — a market shelf inside the settings surface. The visual\n * language is the dsh theme's alias tokens ONLY (the four tokens the previous\n * styles referenced that do not exist — bg-layer-3, interactive-bg-hover,\n * state-error, state-success — are corrected to bg-layer-2 and the\n * state-*-primary set). The signature is the category spine: one HUE per\n * category (seven fixed hues, not the brand token — the brand resolves to\n * near-black in the light theme, so seven brand opacities read as seven\n * shades of gray), with the category name as the cover label in the same hue. Class names are mapped to content-derived names at bundle time\n * (tsdown.s8583e3_client.s942a79_config.s5f67aa_ts) and stubbed in tests; only the keys are relied\n * on.\n *\n * One token rule the theme forces: the background LAYERS do not carry\n * contrast. In the light theme bg-base, bg-layer-1, bg-layer-2 and\n * bg-layer-3 all resolve to the same white; only the dark theme spreads them\n * (950/875/850/800). So a layer-2 fill on a layer-1 ground is invisible for\n * half of all users, and anything whose fill is its ONLY affordance — the\n * loading skeleton, the borderless capability chips — derives its fill from\n * label-primary instead, which inverts with the theme by construction.\n * Elements that also carry a border or text may keep a layer fill.\n * `css-tokens.s8583e3_client.sfd9d8a_spec.s5f67aa_ts` pins this. */\n\n.s255e5a_panel {\n display: flex;\n flex-direction: column;\n gap: 14px;\n /* The shelf never scrolls sideways: a card too wide for its track wraps\n * its badges rather than widening the panel.\n *\n * Clipped on BOTH axes, with a margin, because `.s232ec4_searchInput` sits at\n * exactly (0, 0) of this box — it is the first child of `.s646509_toolbar`, itself\n * the first child here, and this rule carries no padding — so its focus\n * ring paints ENTIRELY outside the panel.\n *\n * Both axes is the load-bearing part: `overflow-clip-margin` is inert\n * unless the element clips on both. Clipping x alone left the margin doing\n * nothing — measured against the live app on 0.7.1, the ring reached 0 of\n * its 3px on the left at every device pixel ratio (1, 1.25, 1.5, 2), while\n * keeping the full 3px on the right, where the 280px input stops short of\n * the panel and never meets the clip edge. Raising the margin to 6px\n * changed nothing; clipping both axes with the SAME 3px restored the whole\n * ring. A test that reads declarations cannot see that difference, which is\n * why the first attempt at this shipped broken.\n *\n * `clip` is not a scroll container, so this does not bring back the\n * accidental scrolling `hidden` caused by coercing the other axis to\n * `auto`. Nothing is lost vertically: the panel's scrollHeight equals its\n * height and no descendant paints outside the clip rect (measured).\n * `overflow-x: hidden` stays as the fallback for engines without `clip`,\n * where the ring is clipped as it was before, never worse. */\n overflow-x: hidden;\n overflow: clip;\n overflow-clip-margin: 3px;\n}\n\n.s44a3ec_stateLine {\n margin: 0;\n color: var(--dsw-alias-label-primary);\n font-size: 13px;\n}\n\n/* Visually hidden but screen-reader readable (the loading copy while the\n * skeleton stands in visually). */\n.s3a0ece_srOnly {\n position: absolute;\n width: 1px;\n height: 1px;\n margin: -1px;\n padding: 0;\n border: 0;\n clip: rect(0 0 0 0);\n clip-path: inset(50%);\n overflow: hidden;\n white-space: nowrap;\n}\n\n/* The loading shelf: ghost cards with the same geometry as the real grid, so\n * the swap to content is a same-shape handoff instead of a jump. */\n.se0c3b4_skeletonGrid {\n display: grid;\n grid-template-columns: 1fr;\n gap: 8px;\n}\n\n.s520416_skeletonCard {\n position: relative;\n display: flex;\n flex-direction: column;\n border: 1px solid var(--dsw-alias-border-l1);\n border-radius: 10px;\n background: var(--dsw-alias-bg-layer-1);\n overflow: hidden;\n}\n\n/* The shimmer sweep: one gradient band travels across each ghost card while\n * the bars breathe, so the loading state reads as \"the shelf is scanning\". */\n.s520416_skeletonCard::after {\n content: '';\n position: absolute;\n inset: 0;\n background: linear-gradient(\n 100deg,\n transparent 25%,\n color-mix(in srgb, var(--dsw-alias-label-primary) 14%, transparent) 50%,\n transparent 75%\n );\n transform: translateX(-100%);\n animation: dshShopSkeletonSweep 1.4s ease-in-out infinite;\n pointer-events: none;\n}\n\n@keyframes dshShopSkeletonSweep {\n to { transform: translateX(100%); }\n}\n\n.s8c7d6f_skeletonName {\n width: 55%;\n height: 14px;\n margin: 10px 12px 0;\n border-radius: 4px;\n background: color-mix(in srgb, var(--dsw-alias-label-primary) 8%, transparent);\n}\n\n.sf5179e_skeletonSummary {\n width: 92%;\n height: 12px;\n margin: 10px 12px 0;\n border-radius: 4px;\n background: color-mix(in srgb, var(--dsw-alias-label-primary) 8%, transparent);\n}\n\n.sbb0d25_skeletonSummaryShort {\n width: 68%;\n height: 12px;\n margin: 6px 12px 10px;\n border-radius: 4px;\n background: color-mix(in srgb, var(--dsw-alias-label-primary) 8%, transparent);\n}\n\n/* The ghost of the action line, right where the real buttons land. */\n.s96e910_skeletonActions {\n display: block;\n width: 84px;\n height: 24px;\n margin: 0 12px 10px;\n border-radius: 999px;\n background: color-mix(in srgb, var(--dsw-alias-label-primary) 8%, transparent);\n}\n\n.s520416_skeletonCard span {\n animation: dshShopSkeletonPulse 1.6s ease-in-out infinite;\n}\n\n@keyframes dshShopSkeletonPulse {\n 0%, 100% { opacity: 0.5; }\n 50% { opacity: 1; }\n}\n\n@media (prefers-reduced-motion: reduce) {\n .s520416_skeletonCard span { animation: none; opacity: 0.75; }\n .s520416_skeletonCard::after { content: none; }\n}\n\n.s73242a_actionButton {\n align-self: flex-start;\n padding: 5px 14px;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 6px;\n background: var(--dsw-alias-bg-layer-2);\n color: var(--dsw-alias-label-primary);\n font-size: 13px;\n cursor: pointer;\n}\n\n.s73242a_actionButton:hover {\n border-color: color-mix(in srgb, var(--dsw-alias-brand-primary) 45%, var(--dsw-alias-border-l2));\n color: var(--dsw-alias-brand-primary);\n}\n\n.s73242a_actionButton:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary);\n outline-offset: 1px;\n}\n\n.s646509_toolbar {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 12px;\n flex-wrap: wrap;\n}\n\n.s745e3c_toolbarRight {\n display: flex;\n align-items: center;\n gap: 12px;\n flex-wrap: wrap;\n}\n\n/* The shop's own version, right of the search box: `v0.4.4`, plus the\n * update button when the version check found a newer release. */\n.s4fe61f_versionBlock {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.sb9b924_versionText {\n font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;\n font-size: 12px;\n letter-spacing: 0.02em;\n color: var(--dsw-alias-label-secondary);\n}\n\n.sa04455_updateSelfButton {\n padding: 2px 10px;\n border: 1px solid var(--dsw-alias-brand-primary);\n border-radius: 999px;\n background: color-mix(in srgb, var(--dsw-alias-brand-primary) 12%, transparent);\n color: var(--dsw-alias-brand-primary);\n font-size: 12px;\n font-weight: 600;\n cursor: pointer;\n}\n\n.sa04455_updateSelfButton:hover {\n background: color-mix(in srgb, var(--dsw-alias-brand-primary) 20%, transparent);\n}\n\n.sa04455_updateSelfButton:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary);\n outline-offset: 1px;\n}\n\n/* The on-demand re-check next to the version number: a quiet pill; the\n * border and text carry it in the light theme where bg layers are white. */\n.s614a38_checkUpdateButton {\n padding: 2px 10px;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 999px;\n background: var(--dsw-alias-bg-layer-2);\n color: var(--dsw-alias-label-secondary);\n font-size: 12px;\n cursor: pointer;\n}\n\n.s614a38_checkUpdateButton:hover {\n border-color: var(--dsw-alias-label-secondary);\n color: var(--dsw-alias-label-primary);\n}\n\n.s614a38_checkUpdateButton:disabled {\n opacity: 0.6;\n cursor: default;\n}\n\n.s614a38_checkUpdateButton:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary);\n outline-offset: 1px;\n}\n\n/* The project's GitHub mark, right of the version row: a quiet icon link.\n * The octocat carries itself — color shift on hover, no text, no border. */\n.sa987f7_githubLink {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n padding: 3px;\n border-radius: 6px;\n color: var(--dsw-alias-label-secondary);\n}\n\n.sa987f7_githubLink:hover {\n color: var(--dsw-alias-label-primary);\n background: var(--dsw-alias-bg-layer-2);\n}\n\n.sa987f7_githubLink:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary);\n outline-offset: 1px;\n}\n\n/* The self-update's expanded states (running log / done + restart /\n * failure detail) sit under the toolbar, above the category bar. */\n.sb81ba5_selfUpdatePanel {\n display: flex;\n flex-direction: column;\n gap: 8px;\n margin-top: 8px;\n}\n\n.s232ec4_searchInput {\n width: min(280px, 100%);\n padding: 6px 10px;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 6px;\n background: var(--dsw-alias-bg-layer-1);\n color: var(--dsw-alias-label-primary);\n font-size: 13px;\n}\n\n.s232ec4_searchInput:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary);\n outline-offset: 1px;\n}\n\n.s3946f1_staleBadge {\n padding: 2px 8px;\n border-radius: 999px;\n background: color-mix(in srgb, var(--dsw-alias-state-warn-primary) 14%, transparent);\n border: 1px solid color-mix(in srgb, var(--dsw-alias-state-warn-primary) 40%, transparent);\n color: var(--dsw-alias-state-warn-primary);\n font-size: 12px;\n}\n\n.sb2c859_categoryBar {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 6px;\n margin-top: 6px;\n}\n\n.s26d58e_categoryButton {\n /* The hue this button carries when selected. `All` and `Installed` select by\n * something other than a category and keep the brand token; the six category\n * buttons override it from the shared hue table below, so a pressed Tool tab\n * turns the same blue as a tool card's spine. */\n --category-hue: var(--dsw-alias-brand-primary);\n padding: 3px 10px;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 999px;\n background: var(--dsw-alias-bg-layer-1);\n color: var(--dsw-alias-label-secondary);\n font-size: 12px;\n cursor: pointer;\n}\n\n/* Blend text with the theme foreground: darker on light backgrounds, lighter\n * on dark ones. The unblended category hue belongs on the border and fill. */\n.s26d58e_categoryButton:hover {\n border-color: color-mix(in srgb, var(--category-hue) 45%, var(--dsw-alias-border-l2));\n color: color-mix(in srgb, var(--category-hue) 45%, var(--dsw-alias-label-primary) 55%);\n}\n\n/* Selected. Written `.s26d58e_categoryButton.s5f68c4_categoryButtonOn` — TWO classes — so it\n * matches `.s26d58e_categoryButton:hover`'s specificity and, coming after it, wins.\n * As a bare `.s5f68c4_categoryButtonOn` it lost both `border-color` and `color` to the\n * hover rule for as long as the pointer stayed on the tab that had just been\n * clicked, which is precisely when a reader looks for confirmation.\n *\n * EVERY declaration here is a colour or a shadow: a pressed tab must occupy\n * exactly the same box as an unpressed one, so the bar does not reflow — and\n * with ~9 pills on a wrapping row, one that grows can push the rest onto\n * another line and move the tab out from under the pointer that just clicked\n * it. That is what `font-weight: 600` did (bold metrics are wider than\n * regular), and it is why nothing may be added here that resolves to a length:\n * no padding, no border-width, no font-size, no letter-spacing.\n * `css-tokens.s8583e3_client.sfd9d8a_spec.s5f67aa_ts` fails the build on one.\n *\n * `box-shadow` is the exception that earns its place: it paints outside the\n * layout box, so an inset ring doubles the border's weight at zero cost to the\n * metrics. It is what `font-weight: 600` used to be — a second, thickness-\n * based signal that hover does not also produce — and the `other` tab needs it\n * most: its hue IS the neutral gray this file uses for \"no category\", so on\n * the light theme hue alone barely separates pressed from unpressed. */\n.s26d58e_categoryButton.s5f68c4_categoryButtonOn {\n border-color: var(--category-hue);\n background: color-mix(in srgb, var(--category-hue) 14%, transparent);\n color: color-mix(in srgb, var(--category-hue) 45%, var(--dsw-alias-label-primary) 55%);\n box-shadow: inset 0 0 0 1px var(--category-hue);\n}\n\n/* Forced colours replace every colour above with the system palette, which\n * would leave the three colour declarations saying nothing and the pressed tab\n * indistinguishable from its neighbours. `box-shadow` is dropped in this mode\n * too, so the ring has to come back as an outline. */\n@media (forced-colors: active) {\n .s26d58e_categoryButton.s5f68c4_categoryButtonOn {\n outline: 2px solid ButtonText;\n outline-offset: -4px;\n }\n}\n\n.s26d58e_categoryButton:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary);\n outline-offset: 1px;\n}\n\n/* The incompatible filter, at the right edge of the category bar: `margin-left:\n * auto` pushes it past the pills, and the bar wraps, so on a narrow panel it\n * drops to its own line rather than squeezing them. It is a MODIFIER, not a\n * ninth category — the categories select what to show and this one subtracts\n * from whatever they selected — so it takes the error hue it filters on rather\n * than joining the hue table.\n *\n * It IS a pill, so it wears `.s26d58e_categoryButton` and states only its two\n * differences. The geometry rule the pills follow then covers it by\n * construction rather than by a second copy that has to be kept in step: this\n * rule was a verbatim clone of the four `.s26d58e_categoryButton` rules, and every\n * padding or border change to the bar had to be made twice or the two silently\n * drifted. `--category-hue` is the knob that makes the clone unnecessary —\n * declared here at the same specificity as `.s26d58e_categoryButton`'s fallback and\n * after it, so it wins; the button carries no `data-category`, so the hue\n * table below cannot reach it. */\n.sfd887b_incompatibleFilter {\n --category-hue: var(--dsw-alias-state-error-primary);\n margin-left: auto;\n}\n\n.s668774_catalogHeading {\n margin: 2px 0 0;\n font-size: 16px;\n font-weight: 600;\n letter-spacing: 0.02em;\n color: var(--dsw-alias-label-primary);\n}\n\n.seb0a1e_catalogStatsRow {\n display: flex;\n align-items: center;\n gap: 10px;\n margin: 6px 0 0;\n}\n\n.sccc4d1_catalogStats {\n margin: 0;\n font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;\n font-size: 12px;\n letter-spacing: 0.02em;\n color: var(--dsw-alias-label-secondary);\n}\n\n/* Sits beside the 12px stats caption, so it is quieter than `.s73242a_actionButton`:\n * this is an affordance, not a call to action — the catalog reloads on its\n * own at mount and the shelf is already usable without it. */\n.s64a5ff_reloadButton {\n padding: 1px 9px;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 999px;\n background: transparent;\n color: var(--dsw-alias-label-secondary);\n font-size: 11px;\n line-height: 17px;\n cursor: pointer;\n}\n\n.s64a5ff_reloadButton:hover:not(:disabled) {\n border-color: color-mix(in srgb, var(--dsw-alias-brand-primary) 45%, var(--dsw-alias-border-l2));\n color: var(--dsw-alias-brand-primary);\n}\n\n.s64a5ff_reloadButton:disabled {\n cursor: default;\n opacity: 0.6;\n}\n\n.s64a5ff_reloadButton:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary);\n outline-offset: 1px;\n}\n\n.s4453f3_reloadFailed {\n font-size: 11px;\n color: var(--dsw-alias-state-warn-primary);\n}\n\n.s6de1ab_emptyLine {\n margin: 0;\n color: var(--dsw-alias-label-primary);\n font-size: 13px;\n}\n\n/* The shelf: a responsive grid of cards. */\n/* Single-line rows: one full-width column, one plugin per line. */\n.sf657f5_cards {\n display: grid;\n grid-template-columns: 1fr;\n max-width: 100%;\n gap: 8px;\n list-style: none;\n margin: 0;\n padding: 0;\n animation: dshShopCardsIn 220ms ease;\n}\n\n@keyframes dshShopCardsIn {\n from { opacity: 0; transform: translateY(3px); }\n to { opacity: 1; transform: none; }\n}\n\n@media (prefers-reduced-motion: reduce) {\n .sf657f5_cards { animation: none; }\n}\n\n.s65f383_card {\n position: relative;\n display: flex;\n flex-direction: column;\n /* A grid item's min-width is auto by default: its content would widen the\n * 1fr track past the panel and overflow horizontally. */\n min-width: 0;\n border: 1px solid var(--dsw-alias-border-l1);\n border-radius: 10px;\n background: var(--dsw-alias-bg-layer-1);\n overflow: hidden;\n transition: border-color 120ms ease, transform 120ms ease, box-shadow 120ms ease;\n /* Off-screen cards skip layout and paint; the placeholder keeps scrollbar\n * estimation sane before the browser has measured the real height. */\n content-visibility: auto;\n contain-intrinsic-size: auto 140px;\n}\n\n/* The sentinel that triggers the next shelf batch: zero visual footprint. */\n.sd7ee01_cardsSentry {\n height: 1px;\n margin: 0;\n padding: 0;\n}\n\n.s705cc6_showingLine {\n margin: 0;\n font-size: 12px;\n letter-spacing: 0.02em;\n color: var(--dsw-alias-label-secondary);\n}\n\n.s65f383_card:hover {\n border-color: color-mix(in srgb, var(--dsw-alias-brand-primary) 45%, var(--dsw-alias-border-l1));\n transform: translateY(-1px);\n box-shadow: 0 2px 8px color-mix(in srgb, var(--dsw-alias-brand-primary) 12%, transparent);\n}\n\n@media (prefers-reduced-motion: reduce) {\n .s65f383_card { transition: none; }\n .s65f383_card:hover { transform: none; }\n}\n\n/* The signature: a spine and cover in the category's own hue. The hues are\n * fixed mid-bright colors that read on both themes; `other` deliberately\n * stays a neutral gray so the fallback category does not compete. */\n.s4ce25d_cardSpine {\n position: absolute;\n top: 0;\n bottom: 0;\n left: 0;\n width: 3px;\n background: var(--category-hue, #8B8E96);\n}\n\n/* The hue table, keyed by `data-category` and read by BOTH surfaces that\n * speak in category colour: a card's spine and badge, and the category bar's\n * own tab. One table, so a tab can never disagree with the cards it filters to\n * — which is the whole point of colouring the tab. `.s26d58e_categoryButton` sets the\n * brand fallback for `All`/`Installed`; these attribute selectors are one\n * specificity step above it and win wherever the attribute is present. */\n.s65f383_card[data-category='tool'], .s26d58e_categoryButton[data-category='tool'] { --category-hue: #4C8DFF; }\n.s65f383_card[data-category='provider'], .s26d58e_categoryButton[data-category='provider'] { --category-hue: #A78BFA; }\n.s65f383_card[data-category='ui'], .s26d58e_categoryButton[data-category='ui'] { --category-hue: #2DD4BF; }\n.s65f383_card[data-category='workflow'], .s26d58e_categoryButton[data-category='workflow'] { --category-hue: #F59E0B; }\n.s65f383_card[data-category='integration'], .s26d58e_categoryButton[data-category='integration'] { --category-hue: #34D399; }\n.s65f383_card[data-category='theme'], .s26d58e_categoryButton[data-category='theme'] { --category-hue: #F472B6; }\n.s65f383_card[data-category='other'], .s26d58e_categoryButton[data-category='other'] { --category-hue: #8B8E96; }\n\n/* The category sits in the badge row as a quiet chip in the category's own\n * hue — the border carries it where the light theme's white layers cannot\n * (the same lesson as the check button). */\n.s9c8eaa_categoryBadge {\n padding: 1px 7px;\n border: 1px solid color-mix(in srgb, var(--category-hue, #8B8E96) 45%, transparent);\n border-radius: 999px;\n font-size: 11px;\n font-weight: 600;\n letter-spacing: 0.08em;\n text-transform: uppercase;\n color: var(--category-hue, #8B8E96);\n white-space: nowrap;\n}\n\n.sa97234_entryHeader {\n display: flex;\n flex-direction: row;\n align-items: center;\n gap: 12px;\n min-width: 0;\n padding: 8px 12px 2px;\n border: none;\n background: transparent;\n color: inherit;\n font: inherit;\n text-align: left;\n cursor: pointer;\n}\n\n.sa97234_entryHeader:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary);\n outline-offset: -2px;\n}\n\n/* The name fills the row and truncates rather than wraps; the badges stay\n * intact beside it. */\n.sc3f149_name {\n font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;\n font-size: 13px;\n font-weight: 600;\n flex: 1 1 auto;\n min-width: 0;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n color: var(--dsw-alias-label-primary);\n}\n\n.s513026_badges {\n display: flex;\n align-items: center;\n flex-wrap: wrap;\n gap: 6px;\n}\n\n/* The action line: buttons side by side; an active install/uninstall flow\n * (gate, log, notices) takes the full width below them. */\n.s9b5048_cardActions {\n display: flex;\n flex-direction: row;\n flex-wrap: wrap;\n align-items: center;\n gap: 8px;\n padding: 8px 12px 10px;\n}\n\n.s9b5048_cardActions > .sc4f2ac_gate,\n.s9b5048_cardActions > .s4d374c_installPanel,\n.s9b5048_cardActions > .sf53ca0_installedActions {\n flex-basis: 100%;\n}\n\n/* The entry's version, always visible on the card (the expanded detail\n * repeats it in the version row) — the same quiet mono as the toolbar. */\n.sc6ec6e_cardVersion {\n font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;\n font-size: 12px;\n letter-spacing: 0.02em;\n color: var(--dsw-alias-label-secondary);\n}\n\n/* The octocat marking a github-sourced entry, beside its short commit. */\n.s71f10f_sourceBadge {\n display: inline-flex;\n align-items: center;\n color: var(--dsw-alias-label-secondary);\n}\n\n.s5e82cb_tierBadge {\n padding: 1px 7px;\n border-radius: 999px;\n font-size: 11px;\n line-height: 1.6;\n}\n\n.s5e82cb_tierBadge[data-tier='verified'] {\n color: var(--dsw-alias-state-success-primary);\n background: color-mix(in srgb, var(--dsw-alias-state-success-primary) 14%, transparent);\n border: 1px solid color-mix(in srgb, var(--dsw-alias-state-success-primary) 40%, transparent);\n}\n\n.s5e82cb_tierBadge[data-tier='verified-stale'] {\n color: var(--dsw-alias-state-warn-primary);\n background: color-mix(in srgb, var(--dsw-alias-state-warn-primary) 14%, transparent);\n border: 1px solid color-mix(in srgb, var(--dsw-alias-state-warn-primary) 40%, transparent);\n}\n\n.s5e82cb_tierBadge[data-tier='community'] {\n color: var(--dsw-alias-label-secondary);\n background: var(--dsw-alias-bg-layer-2);\n border: 1px solid var(--dsw-alias-border-l2);\n}\n\n.s4bbe02_incompatibleBadge {\n flex-shrink: 0;\n padding: 3px 9px;\n border-radius: 999px;\n font-size: 12px;\n white-space: nowrap;\n color: var(--dsw-alias-state-error-primary);\n background: color-mix(in srgb, var(--dsw-alias-state-error-primary) 14%, transparent);\n border: 1px solid color-mix(in srgb, var(--dsw-alias-state-error-primary) 40%, transparent);\n}\n\n.sff43b4_starsBadge {\n font-size: 11px;\n color: var(--dsw-alias-label-secondary);\n}\n\n.s73f7fb_chevron, .s61393c_chevronOpen {\n color: var(--dsw-alias-label-secondary);\n transition: transform 120ms ease;\n}\n\n.s61393c_chevronOpen { transform: rotate(180deg); }\n\n@media (prefers-reduced-motion: reduce) {\n .s73f7fb_chevron, .s61393c_chevronOpen { transition: none; }\n}\n\n.s820ebf_body {\n display: flex;\n flex-direction: column;\n gap: 8px;\n padding: 0 12px;\n}\n\n.sb8fbc8_summary {\n margin: 0;\n font-size: 13px;\n line-height: 1.5;\n color: var(--dsw-alias-label-primary);\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n overflow: hidden;\n}\n\n.se507db_summaryZh {\n margin: -4px 0 0;\n font-size: 12px;\n line-height: 1.5;\n color: var(--dsw-alias-label-secondary);\n display: -webkit-box;\n -webkit-line-clamp: 1;\n -webkit-box-orient: vertical;\n overflow: hidden;\n}\n\n/* Expanded cards show the full summary: the clamp is lifted, never raised —\n * a higher number would still truncate the author's text, just later. */\n.s10baf0_summaryExpanded {\n -webkit-line-clamp: unset;\n display: block;\n}\n\n.sb9dba9_summaryZhExpanded {\n -webkit-line-clamp: unset;\n display: block;\n}\n\n/* `white-space: pre-line` so the newline in the copy is the copy's own: the\n dictionary decides where the line breaks, and a translator changes it\n without touching the component. Collapses runs of spaces like `normal`, so\n only the explicit \\n survives. */\n.s6eca19_incompatibleDetail {\n margin: 0;\n font-size: 12px;\n line-height: 1.5;\n white-space: pre-line;\n color: var(--dsw-alias-state-error-primary);\n}\n\n.s9d2029_capabilitiesBlock {\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.s3bdbd5_capabilitiesNote {\n margin: 0;\n font-size: 11px;\n color: var(--dsw-alias-label-secondary);\n}\n\n.s441702_capabilities {\n display: flex;\n flex-wrap: wrap;\n gap: 4px;\n list-style: none;\n margin: 0;\n padding: 0;\n}\n\n.s441702_capabilities li {\n padding: 1px 6px;\n border-radius: 4px;\n background: color-mix(in srgb, var(--dsw-alias-label-primary) 6%, transparent);\n font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;\n font-size: 11px;\n color: var(--dsw-alias-label-secondary);\n}\n\n.sde3f0c_detail {\n border-top: 1px solid var(--dsw-alias-border-l1);\n padding-top: 8px;\n}\n\n.se98179_detailRows {\n display: flex;\n flex-direction: column;\n gap: 4px;\n margin: 0;\n}\n\n.sfb4d2f_detailRow {\n display: flex;\n justify-content: space-between;\n gap: 12px;\n font-size: 12px;\n}\n\n.sfb4d2f_detailRow dt {\n color: var(--dsw-alias-label-secondary);\n}\n\n.sfb4d2f_detailRow dd {\n margin: 0;\n font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;\n overflow-wrap: anywhere;\n text-align: right;\n color: var(--dsw-alias-label-primary);\n}\n\n.sfb4d2f_detailRow a {\n color: var(--dsw-alias-brand-primary);\n text-decoration: none;\n}\n\n.sfb4d2f_detailRow a:hover {\n text-decoration: underline;\n}\n\n.sfb4d2f_detailRow a:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary);\n outline-offset: 1px;\n}\n\n/* What the entry IS rather than what you can do with it — how big it is and\n * who published it — at the right edge of the action row. `margin-left: auto`\n * is what pushes it there, and it lives on this wrapper rather than on either\n * label so the group stays flush right when only one of the two has a value:\n * a github entry has no npm size, and a packument that named no account has no\n * author. The row is a wrapping flex, so an active install flow (which claims\n * the full width) drops the whole group to the next line rather than squeezing\n * it. */\n.s5fbaf9_cardMeta {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n margin-left: auto;\n min-width: 0;\n}\n\n/* The unpacked size, left of the author. Mono and tabular so the digits of one\n * figure line up with the digits of another WHEREVER the two land: `.s5fbaf9_cardMeta`\n * is flush right and the author sits outside the size, so a size's x position\n * moves with the author's width and is different again on the many entries\n * that carry no author at all. There is no column to align to, which is why\n * the reason given here is per-figure legibility rather than the column the\n * first version of this comment claimed. Secondary colour, because it\n * qualifies the entry rather than announcing it.\n *\n * `font-variant-numeric` is safe HERE and would not be on a pill: this element\n * has no state rules, so nothing it does can reflow a wrapping row. */\n.s2d3c05_size {\n font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;\n font-variant-numeric: tabular-nums;\n font-size: 12px;\n letter-spacing: 0.02em;\n white-space: nowrap;\n color: var(--dsw-alias-label-secondary);\n}\n\n/* The publishing account, at the outer end of `.s5fbaf9_cardMeta` on the action row —\n * NOT beside the npm link in the expanded detail, which is where it used to\n * live and what this comment described until the accurate half was deleted\n * with the `margin-left: auto` that moved to `.s5fbaf9_cardMeta`. There is no middot:\n * `.s5fbaf9_cardMeta`'s 8px gap separates it from the size.\n *\n * Secondary label colour carries the distinction — never a background fill,\n * which is invisible in the light theme where every bg-layer token is the\n * same white. */\n.s1ff66f_author {\n color: var(--dsw-alias-label-secondary);\n font-size: 12px;\n}\n\n.sd58c6d_reviewedLine {\n margin: 8px 0 0;\n padding: 6px 8px;\n border-radius: 6px;\n background: color-mix(in srgb, var(--dsw-alias-state-warn-primary) 12%, transparent);\n font-size: 12px;\n color: var(--dsw-alias-state-warn-primary);\n}\n\n/* Install flow. */\n.s4d374c_installPanel {\n display: flex;\n flex-direction: column;\n gap: 8px;\n margin-top: 2px;\n}\n\n.se7aaed_installButton, .sb43a49_confirmButton, .s6e45d1_cancelButton {\n align-self: flex-start;\n padding: 5px 14px;\n border-radius: 6px;\n font-size: 13px;\n cursor: pointer;\n}\n\n.se7aaed_installButton {\n border: 1px solid var(--dsw-alias-brand-primary);\n background: var(--dsw-alias-brand-primary);\n color: var(--dsw-alias-bg-base);\n}\n\n.se7aaed_installButton:hover {\n background: color-mix(in srgb, var(--dsw-alias-brand-primary) 88%, var(--dsw-alias-label-primary));\n}\n\n.sb43a49_confirmButton {\n border: 1px solid var(--dsw-alias-brand-primary);\n background: var(--dsw-alias-brand-primary);\n color: var(--dsw-alias-bg-base);\n}\n\n.sb43a49_confirmButton:hover {\n background: color-mix(in srgb, var(--dsw-alias-brand-primary) 88%, var(--dsw-alias-label-primary));\n}\n\n.s6e45d1_cancelButton {\n border: 1px solid var(--dsw-alias-border-l2);\n background: var(--dsw-alias-bg-layer-2);\n color: var(--dsw-alias-label-primary);\n}\n\n.s6e45d1_cancelButton:hover {\n border-color: var(--dsw-alias-label-secondary);\n}\n\n.se7aaed_installButton:focus-visible, .sb43a49_confirmButton:focus-visible, .s6e45d1_cancelButton:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary);\n outline-offset: 1px;\n}\n\n/* The shelf card of a plugin that is installed and current carries this\n * non-interactive label instead of an install button. Border + text do the\n * work in the light theme, where every bg-layer token resolves to white. */\n.sb6fc74_installedLabel {\n align-self: flex-start;\n margin: 0;\n padding: 5px 14px;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 6px;\n font-size: 13px;\n color: var(--dsw-alias-label-secondary);\n background: var(--dsw-alias-bg-layer-2);\n}\n\n/* An installed card's controls: the installed label or the update button,\n * plus the uninstall button. The install panel's running/failed states are\n * column layouts and sit as one item of this row. */\n.sf53ca0_installedActions {\n display: flex;\n align-items: flex-start;\n flex-wrap: wrap;\n gap: 8px;\n}\n\n/* Uninstall revokes privilege; the quiet outline keeps it from competing\n * with the primary action, and the error tint says \"removes\". */\n.s96967f_uninstallButton {\n align-self: flex-start;\n padding: 5px 14px;\n border: 1px solid color-mix(in srgb, var(--dsw-alias-state-error-primary) 55%, transparent);\n border-radius: 6px;\n background: transparent;\n color: var(--dsw-alias-state-error-primary);\n font-size: 13px;\n cursor: pointer;\n}\n\n.s96967f_uninstallButton:hover {\n background: color-mix(in srgb, var(--dsw-alias-state-error-primary) 10%, transparent);\n}\n\n.s96967f_uninstallButton:focus-visible {\n outline: 2px solid var(--dsw-alias-state-error-primary);\n outline-offset: 1px;\n}\n\n/* The restart dsh button on a done install: quiet outline, same rank as\n * the other secondary actions. */\n.sb00c36_restartSelfButton {\n /* The version row's third state. Geometry matches .s614a38_checkUpdateButton and\n * .sa04455_updateSelfButton exactly — the row is one evolving control and a\n * different pill would read as a different kind of thing. It takes the\n * emphasised fill rather than the neutral one because at that moment the\n * restart is the only thing left to do, the same reason Update has it. */\n padding: 2px 10px;\n border: 1px solid var(--dsw-alias-brand-primary);\n border-radius: 999px;\n background: color-mix(in srgb, var(--dsw-alias-brand-primary) 12%, transparent);\n color: var(--dsw-alias-brand-primary);\n font-size: 12px;\n font-weight: 600;\n cursor: pointer;\n}\n\n.sb00c36_restartSelfButton:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary);\n outline-offset: 1px;\n}\n\n.s6ac237_restartButton {\n align-self: flex-start;\n padding: 5px 14px;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 6px;\n background: var(--dsw-alias-bg-layer-2);\n color: var(--dsw-alias-label-primary);\n font-size: 13px;\n cursor: pointer;\n}\n\n.s6ac237_restartButton:hover {\n border-color: var(--dsw-alias-label-secondary);\n}\n\n.s6ac237_restartButton:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary);\n outline-offset: 1px;\n}\n\n.sc4f2ac_gate {\n display: flex;\n flex-direction: column;\n gap: 8px;\n padding: 10px;\n border: 1px solid var(--dsw-alias-state-warn-primary);\n border-radius: 8px;\n background: color-mix(in srgb, var(--dsw-alias-state-warn-primary) 8%, transparent);\n}\n\n.s559c38_gateTitle {\n margin: 0;\n font-size: 13px;\n font-weight: 600;\n color: var(--dsw-alias-state-warn-primary);\n}\n\n.s3c0ace_gateBody {\n margin: 0;\n font-size: 12px;\n line-height: 1.6;\n color: var(--dsw-alias-label-primary);\n}\n\n.sc323e5_gateWarning {\n margin: 0;\n font-size: 12px;\n line-height: 1.6;\n white-space: pre-line;\n color: var(--dsw-alias-state-error-primary);\n}\n\n.s4b2373_gateActions {\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n}\n\n.s52b5a5_installing {\n margin: 0;\n font-size: 12px;\n color: var(--dsw-alias-label-secondary);\n}\n\n.s64ab71_log {\n max-height: 160px;\n overflow: auto;\n margin: 0;\n padding: 8px;\n border-radius: 6px;\n background: var(--dsw-alias-bg-base);\n border: 1px solid var(--dsw-alias-border-l1);\n list-style: none;\n font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;\n font-size: 11px;\n line-height: 1.5;\n}\n\n.s1531a8_logLine {\n white-space: pre-wrap;\n word-break: break-all;\n color: var(--dsw-alias-label-secondary);\n}\n\n.sf20dda_notice {\n margin: 0;\n font-size: 12px;\n color: var(--dsw-alias-state-success-primary);\n}\n\n.seb9b08_failedHeading {\n margin: 0;\n font-size: 12px;\n font-weight: 600;\n color: var(--dsw-alias-state-error-primary);\n}\n\n.sfd3021_failedDetail {\n margin: 0;\n font-size: 12px;\n line-height: 1.6;\n color: var(--dsw-alias-label-primary);\n}\n\n.s50ba35_rejectedCode {\n margin: 0;\n font-size: 12px;\n font-weight: 600;\n color: var(--dsw-alias-state-error-primary);\n}\n\n.se75489_rejectedDetail {\n margin: 0;\n font-size: 12px;\n line-height: 1.6;\n color: var(--dsw-alias-label-primary);\n}\n\n/* Installed section. */\n.sa276cf_outdatedSection {\n display: flex;\n flex-direction: column;\n gap: 8px;\n margin-top: 6px;\n}\n\n.sceae6e_outdatedList {\n display: flex;\n flex-direction: column;\n gap: 8px;\n list-style: none;\n margin: 0;\n padding: 0;\n}\n\n.s8d2072_outdatedRow {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 12px;\n flex-wrap: wrap;\n padding: 10px 12px;\n border: 1px solid var(--dsw-alias-border-l1);\n border-radius: 8px;\n background: var(--dsw-alias-bg-layer-1);\n}\n\n.s5c2545_outdatedInfo {\n display: flex;\n flex-direction: column;\n gap: 2px;\n min-width: 0;\n}\n\n.s5c2545_outdatedInfo strong {\n font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;\n font-size: 13px;\n word-break: break-all;\n color: var(--dsw-alias-label-primary);\n}\n\n.s877c68_outdatedVersions {\n /* Two inline labels with nothing between them in the markup ran together as\n * `installed v1.0.0latest v2.0.0`: JSX drops the whitespace-only line, and\n * the per-label class the markup asked for was never defined (singular\n * against this rule's plural). The container owns the gap, the same idiom\n * as .s513026_badges — the labels need no class of their own. */\n display: inline-flex;\n align-items: center;\n gap: 8px;\n font-size: 12px;\n color: var(--dsw-alias-label-secondary);\n}\n\n.sa1f556_outdatedActions {\n display: flex;\n align-items: center;\n gap: 10px;\n}\n\n/* The enable/disable switch. */\n.s11c019_switch {\n position: relative;\n width: 32px;\n height: 18px;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 999px;\n background: var(--dsw-alias-bg-layer-2);\n cursor: pointer;\n transition: background 120ms ease, border-color 120ms ease;\n}\n\n.s7580e8_switchOn {\n border-color: var(--dsw-alias-state-success-primary);\n background: color-mix(in srgb, var(--dsw-alias-state-success-primary) 55%, transparent);\n}\n\n.saab2b3_switchKnob {\n position: absolute;\n top: 2px;\n left: 2px;\n width: 12px;\n height: 12px;\n border-radius: 999px;\n background: var(--dsw-alias-label-primary);\n transition: transform 120ms ease, background 120ms ease;\n}\n\n.s7580e8_switchOn .saab2b3_switchKnob {\n transform: translateX(14px);\n background: var(--dsw-alias-bg-base);\n}\n\n.s11c019_switch:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary);\n outline-offset: 1px;\n}\n\n@media (prefers-reduced-motion: reduce) {\n .s11c019_switch, .saab2b3_switchKnob { transition: none; }\n}\n\n/* The hot enable/disable switch on installed rows: the knob button plus the\n * §8 hot-apply / failure notices rendered beside it. */\n.sd9f9e4_switchWrap {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n}\n";
|
|
6975
|
+
if (typeof document !== "undefined" && !document.querySelector("style[data-plugin-css=\"e3675a89\"]")) {
|
|
6924
6976
|
const tag = document.createElement("style");
|
|
6925
|
-
tag.dataset.pluginCss = "
|
|
6977
|
+
tag.dataset.pluginCss = "e3675a89";
|
|
6926
6978
|
tag.textContent = css;
|
|
6927
6979
|
document.head.appendChild(tag);
|
|
6928
6980
|
}
|
|
6929
|
-
var
|
|
6930
|
-
"client": "
|
|
6931
|
-
"config": "
|
|
6932
|
-
"ts": "
|
|
6933
|
-
"spec": "
|
|
6934
|
-
"panel": "
|
|
6935
|
-
"searchInput": "
|
|
6936
|
-
"toolbar": "
|
|
6937
|
-
"stateLine": "
|
|
6938
|
-
"srOnly": "
|
|
6939
|
-
"skeletonGrid": "
|
|
6940
|
-
"skeletonCard": "
|
|
6941
|
-
"skeletonName": "
|
|
6942
|
-
"skeletonSummary": "
|
|
6943
|
-
"skeletonSummaryShort": "
|
|
6944
|
-
"skeletonActions": "
|
|
6945
|
-
"actionButton": "
|
|
6946
|
-
"toolbarRight": "
|
|
6947
|
-
"versionBlock": "
|
|
6948
|
-
"versionText": "
|
|
6949
|
-
"updateSelfButton": "
|
|
6950
|
-
"checkUpdateButton": "
|
|
6951
|
-
"githubLink": "
|
|
6952
|
-
"selfUpdatePanel": "
|
|
6953
|
-
"staleBadge": "
|
|
6954
|
-
"categoryBar": "
|
|
6955
|
-
"categoryButton": "
|
|
6956
|
-
"categoryButtonOn": "
|
|
6957
|
-
"
|
|
6958
|
-
"
|
|
6959
|
-
"
|
|
6960
|
-
"
|
|
6961
|
-
"
|
|
6962
|
-
"
|
|
6963
|
-
"
|
|
6964
|
-
"
|
|
6965
|
-
"
|
|
6966
|
-
"
|
|
6967
|
-
"
|
|
6968
|
-
"
|
|
6969
|
-
"
|
|
6970
|
-
"
|
|
6971
|
-
"
|
|
6972
|
-
"
|
|
6973
|
-
"
|
|
6974
|
-
"
|
|
6975
|
-
"
|
|
6976
|
-
"
|
|
6977
|
-
"
|
|
6978
|
-
"
|
|
6979
|
-
"
|
|
6980
|
-
"
|
|
6981
|
-
"
|
|
6982
|
-
"
|
|
6983
|
-
"
|
|
6984
|
-
"
|
|
6985
|
-
"
|
|
6986
|
-
"
|
|
6987
|
-
"
|
|
6988
|
-
"
|
|
6989
|
-
"
|
|
6990
|
-
"
|
|
6991
|
-
"
|
|
6992
|
-
"
|
|
6993
|
-
"
|
|
6994
|
-
"
|
|
6995
|
-
"
|
|
6996
|
-
"
|
|
6997
|
-
"
|
|
6998
|
-
"
|
|
6999
|
-
"
|
|
7000
|
-
"
|
|
7001
|
-
"
|
|
7002
|
-
"
|
|
7003
|
-
"
|
|
7004
|
-
"
|
|
7005
|
-
"
|
|
7006
|
-
"
|
|
7007
|
-
"
|
|
7008
|
-
"
|
|
7009
|
-
"
|
|
7010
|
-
"
|
|
7011
|
-
"
|
|
7012
|
-
"
|
|
7013
|
-
"
|
|
7014
|
-
"
|
|
7015
|
-
"
|
|
7016
|
-
"
|
|
7017
|
-
"
|
|
7018
|
-
"
|
|
7019
|
-
"
|
|
7020
|
-
"
|
|
7021
|
-
"
|
|
7022
|
-
"
|
|
7023
|
-
"
|
|
7024
|
-
"
|
|
7025
|
-
"
|
|
6981
|
+
var _dsh_plugin_shop_css_e3675a89_default = {
|
|
6982
|
+
"client": "s8583e3_client",
|
|
6983
|
+
"config": "s942a79_config",
|
|
6984
|
+
"ts": "s5f67aa_ts",
|
|
6985
|
+
"spec": "sfd9d8a_spec",
|
|
6986
|
+
"panel": "s255e5a_panel",
|
|
6987
|
+
"searchInput": "s232ec4_searchInput",
|
|
6988
|
+
"toolbar": "s646509_toolbar",
|
|
6989
|
+
"stateLine": "s44a3ec_stateLine",
|
|
6990
|
+
"srOnly": "s3a0ece_srOnly",
|
|
6991
|
+
"skeletonGrid": "se0c3b4_skeletonGrid",
|
|
6992
|
+
"skeletonCard": "s520416_skeletonCard",
|
|
6993
|
+
"skeletonName": "s8c7d6f_skeletonName",
|
|
6994
|
+
"skeletonSummary": "sf5179e_skeletonSummary",
|
|
6995
|
+
"skeletonSummaryShort": "sbb0d25_skeletonSummaryShort",
|
|
6996
|
+
"skeletonActions": "s96e910_skeletonActions",
|
|
6997
|
+
"actionButton": "s73242a_actionButton",
|
|
6998
|
+
"toolbarRight": "s745e3c_toolbarRight",
|
|
6999
|
+
"versionBlock": "s4fe61f_versionBlock",
|
|
7000
|
+
"versionText": "sb9b924_versionText",
|
|
7001
|
+
"updateSelfButton": "sa04455_updateSelfButton",
|
|
7002
|
+
"checkUpdateButton": "s614a38_checkUpdateButton",
|
|
7003
|
+
"githubLink": "sa987f7_githubLink",
|
|
7004
|
+
"selfUpdatePanel": "sb81ba5_selfUpdatePanel",
|
|
7005
|
+
"staleBadge": "s3946f1_staleBadge",
|
|
7006
|
+
"categoryBar": "sb2c859_categoryBar",
|
|
7007
|
+
"categoryButton": "s26d58e_categoryButton",
|
|
7008
|
+
"categoryButtonOn": "s5f68c4_categoryButtonOn",
|
|
7009
|
+
"incompatibleFilter": "sfd887b_incompatibleFilter",
|
|
7010
|
+
"catalogHeading": "s668774_catalogHeading",
|
|
7011
|
+
"catalogStatsRow": "seb0a1e_catalogStatsRow",
|
|
7012
|
+
"catalogStats": "sccc4d1_catalogStats",
|
|
7013
|
+
"reloadButton": "s64a5ff_reloadButton",
|
|
7014
|
+
"reloadFailed": "s4453f3_reloadFailed",
|
|
7015
|
+
"emptyLine": "s6de1ab_emptyLine",
|
|
7016
|
+
"cards": "sf657f5_cards",
|
|
7017
|
+
"card": "s65f383_card",
|
|
7018
|
+
"cardsSentry": "sd7ee01_cardsSentry",
|
|
7019
|
+
"showingLine": "s705cc6_showingLine",
|
|
7020
|
+
"cardSpine": "s4ce25d_cardSpine",
|
|
7021
|
+
"categoryBadge": "s9c8eaa_categoryBadge",
|
|
7022
|
+
"entryHeader": "sa97234_entryHeader",
|
|
7023
|
+
"name": "sc3f149_name",
|
|
7024
|
+
"badges": "s513026_badges",
|
|
7025
|
+
"cardActions": "s9b5048_cardActions",
|
|
7026
|
+
"gate": "sc4f2ac_gate",
|
|
7027
|
+
"installPanel": "s4d374c_installPanel",
|
|
7028
|
+
"installedActions": "sf53ca0_installedActions",
|
|
7029
|
+
"cardVersion": "sc6ec6e_cardVersion",
|
|
7030
|
+
"sourceBadge": "s71f10f_sourceBadge",
|
|
7031
|
+
"tierBadge": "s5e82cb_tierBadge",
|
|
7032
|
+
"incompatibleBadge": "s4bbe02_incompatibleBadge",
|
|
7033
|
+
"starsBadge": "sff43b4_starsBadge",
|
|
7034
|
+
"chevron": "s73f7fb_chevron",
|
|
7035
|
+
"chevronOpen": "s61393c_chevronOpen",
|
|
7036
|
+
"body": "s820ebf_body",
|
|
7037
|
+
"summary": "sb8fbc8_summary",
|
|
7038
|
+
"summaryZh": "se507db_summaryZh",
|
|
7039
|
+
"summaryExpanded": "s10baf0_summaryExpanded",
|
|
7040
|
+
"summaryZhExpanded": "sb9dba9_summaryZhExpanded",
|
|
7041
|
+
"incompatibleDetail": "s6eca19_incompatibleDetail",
|
|
7042
|
+
"capabilitiesBlock": "s9d2029_capabilitiesBlock",
|
|
7043
|
+
"capabilitiesNote": "s3bdbd5_capabilitiesNote",
|
|
7044
|
+
"capabilities": "s441702_capabilities",
|
|
7045
|
+
"detail": "sde3f0c_detail",
|
|
7046
|
+
"detailRows": "se98179_detailRows",
|
|
7047
|
+
"detailRow": "sfb4d2f_detailRow",
|
|
7048
|
+
"cardMeta": "s5fbaf9_cardMeta",
|
|
7049
|
+
"size": "s2d3c05_size",
|
|
7050
|
+
"author": "s1ff66f_author",
|
|
7051
|
+
"reviewedLine": "sd58c6d_reviewedLine",
|
|
7052
|
+
"installButton": "se7aaed_installButton",
|
|
7053
|
+
"confirmButton": "sb43a49_confirmButton",
|
|
7054
|
+
"cancelButton": "s6e45d1_cancelButton",
|
|
7055
|
+
"installedLabel": "sb6fc74_installedLabel",
|
|
7056
|
+
"uninstallButton": "s96967f_uninstallButton",
|
|
7057
|
+
"restartSelfButton": "sb00c36_restartSelfButton",
|
|
7058
|
+
"restartButton": "s6ac237_restartButton",
|
|
7059
|
+
"gateTitle": "s559c38_gateTitle",
|
|
7060
|
+
"gateBody": "s3c0ace_gateBody",
|
|
7061
|
+
"gateWarning": "sc323e5_gateWarning",
|
|
7062
|
+
"gateActions": "s4b2373_gateActions",
|
|
7063
|
+
"installing": "s52b5a5_installing",
|
|
7064
|
+
"log": "s64ab71_log",
|
|
7065
|
+
"logLine": "s1531a8_logLine",
|
|
7066
|
+
"notice": "sf20dda_notice",
|
|
7067
|
+
"failedHeading": "seb9b08_failedHeading",
|
|
7068
|
+
"failedDetail": "sfd3021_failedDetail",
|
|
7069
|
+
"rejectedCode": "s50ba35_rejectedCode",
|
|
7070
|
+
"rejectedDetail": "se75489_rejectedDetail",
|
|
7071
|
+
"outdatedSection": "sa276cf_outdatedSection",
|
|
7072
|
+
"outdatedList": "sceae6e_outdatedList",
|
|
7073
|
+
"outdatedRow": "s8d2072_outdatedRow",
|
|
7074
|
+
"outdatedInfo": "s5c2545_outdatedInfo",
|
|
7075
|
+
"outdatedVersions": "s877c68_outdatedVersions",
|
|
7076
|
+
"outdatedActions": "sa1f556_outdatedActions",
|
|
7077
|
+
"switch": "s11c019_switch",
|
|
7078
|
+
"switchOn": "s7580e8_switchOn",
|
|
7079
|
+
"switchKnob": "saab2b3_switchKnob",
|
|
7080
|
+
"switchWrap": "sd9f9e4_switchWrap"
|
|
7026
7081
|
};
|
|
7027
7082
|
//#endregion
|
|
7028
7083
|
//#region src/client/ShopTab.tsx
|
|
@@ -7039,7 +7094,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
7039
7094
|
width: "14",
|
|
7040
7095
|
height: "14",
|
|
7041
7096
|
"aria-hidden": "true",
|
|
7042
|
-
className: open ?
|
|
7097
|
+
className: open ? _dsh_plugin_shop_css_e3675a89_default.chevronOpen : _dsh_plugin_shop_css_e3675a89_default.chevron,
|
|
7043
7098
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
|
|
7044
7099
|
fill: "currentColor",
|
|
7045
7100
|
d: "M3.5 6 8 10.5 12.5 6l1 1L8 12.5 2.5 7l1-1Z"
|
|
@@ -7059,6 +7114,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
7059
7114
|
const summary = entry.catalog?.summary;
|
|
7060
7115
|
const npmUrl = npmPageUrl(entry);
|
|
7061
7116
|
const author = authorOf(entry);
|
|
7117
|
+
const size = formatSize(entry.unpackedSize);
|
|
7062
7118
|
const category = entry.catalog?.category ?? "other";
|
|
7063
7119
|
const installTarget = {
|
|
7064
7120
|
name: entry.name,
|
|
@@ -7073,32 +7129,32 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
7073
7129
|
onSettled();
|
|
7074
7130
|
}, [flow, onSettled]);
|
|
7075
7131
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
7076
|
-
className:
|
|
7132
|
+
className: _dsh_plugin_shop_css_e3675a89_default.card,
|
|
7077
7133
|
"data-shop-entry": entry.name,
|
|
7078
7134
|
"data-category": category,
|
|
7079
7135
|
children: [
|
|
7080
7136
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
7081
|
-
className:
|
|
7137
|
+
className: _dsh_plugin_shop_css_e3675a89_default.cardSpine,
|
|
7082
7138
|
"aria-hidden": "true"
|
|
7083
7139
|
}),
|
|
7084
7140
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
7085
7141
|
type: "button",
|
|
7086
|
-
className:
|
|
7142
|
+
className: _dsh_plugin_shop_css_e3675a89_default.entryHeader,
|
|
7087
7143
|
"aria-expanded": open,
|
|
7088
7144
|
"aria-controls": detailId,
|
|
7089
7145
|
onClick: () => setOpen((current) => !current),
|
|
7090
7146
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
7091
|
-
className:
|
|
7147
|
+
className: _dsh_plugin_shop_css_e3675a89_default.name,
|
|
7092
7148
|
children: entry.name
|
|
7093
7149
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
7094
|
-
className:
|
|
7150
|
+
className: _dsh_plugin_shop_css_e3675a89_default.badges,
|
|
7095
7151
|
children: [
|
|
7096
7152
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
7097
|
-
className:
|
|
7153
|
+
className: _dsh_plugin_shop_css_e3675a89_default.categoryBadge,
|
|
7098
7154
|
children: t(categoryKey(entry))
|
|
7099
7155
|
}),
|
|
7100
7156
|
entry.source === "npm" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
7101
|
-
className:
|
|
7157
|
+
className: _dsh_plugin_shop_css_e3675a89_default.sourceBadge,
|
|
7102
7158
|
"data-shop-source-npm": true,
|
|
7103
7159
|
role: "img",
|
|
7104
7160
|
"aria-label": t("npmSource"),
|
|
@@ -7115,7 +7171,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
7115
7171
|
})
|
|
7116
7172
|
}),
|
|
7117
7173
|
hasGithubHome(entry) && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
7118
|
-
className:
|
|
7174
|
+
className: _dsh_plugin_shop_css_e3675a89_default.sourceBadge,
|
|
7119
7175
|
"data-shop-source-github": true,
|
|
7120
7176
|
role: "img",
|
|
7121
7177
|
"aria-label": t("githubSource"),
|
|
@@ -7129,17 +7185,17 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
7129
7185
|
})
|
|
7130
7186
|
}),
|
|
7131
7187
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
7132
|
-
className:
|
|
7188
|
+
className: _dsh_plugin_shop_css_e3675a89_default.cardVersion,
|
|
7133
7189
|
"data-card-version": true,
|
|
7134
7190
|
children: ["v", displayVersion(entry)]
|
|
7135
7191
|
}),
|
|
7136
7192
|
entry.tier !== "community" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
7137
|
-
className:
|
|
7193
|
+
className: _dsh_plugin_shop_css_e3675a89_default.tierBadge,
|
|
7138
7194
|
"data-tier": entry.tier,
|
|
7139
7195
|
children: t(tierKey(entry.tier))
|
|
7140
7196
|
}),
|
|
7141
7197
|
stars !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
7142
|
-
className:
|
|
7198
|
+
className: _dsh_plugin_shop_css_e3675a89_default.starsBadge,
|
|
7143
7199
|
role: "img",
|
|
7144
7200
|
"aria-label": t("stars", { count: stars }),
|
|
7145
7201
|
children: ["★ ", formatStars(stars)]
|
|
@@ -7149,39 +7205,39 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
7149
7205
|
})]
|
|
7150
7206
|
}),
|
|
7151
7207
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
7152
|
-
className:
|
|
7208
|
+
className: _dsh_plugin_shop_css_e3675a89_default.body,
|
|
7153
7209
|
children: [
|
|
7154
7210
|
summary !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
7155
|
-
className: open ? `${
|
|
7211
|
+
className: open ? `${_dsh_plugin_shop_css_e3675a89_default.summary} ${_dsh_plugin_shop_css_e3675a89_default.summaryExpanded}` : _dsh_plugin_shop_css_e3675a89_default.summary,
|
|
7156
7212
|
children: summary.en
|
|
7157
7213
|
}),
|
|
7158
7214
|
summary?.zh !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
7159
|
-
className: open ? `${
|
|
7215
|
+
className: open ? `${_dsh_plugin_shop_css_e3675a89_default.summaryZh} ${_dsh_plugin_shop_css_e3675a89_default.summaryZhExpanded}` : _dsh_plugin_shop_css_e3675a89_default.summaryZh,
|
|
7160
7216
|
children: summary.zh
|
|
7161
7217
|
}),
|
|
7162
7218
|
blockers.map((blocker) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
7163
|
-
className:
|
|
7219
|
+
className: _dsh_plugin_shop_css_e3675a89_default.incompatibleDetail,
|
|
7164
7220
|
"data-shop-incompatible-detail": true,
|
|
7165
7221
|
children: blocker.text
|
|
7166
7222
|
}, blocker.kind)),
|
|
7167
7223
|
open && entry.catalog !== void 0 && entry.catalog.capabilities.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
7168
|
-
className:
|
|
7224
|
+
className: _dsh_plugin_shop_css_e3675a89_default.capabilitiesBlock,
|
|
7169
7225
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
7170
|
-
className:
|
|
7226
|
+
className: _dsh_plugin_shop_css_e3675a89_default.capabilitiesNote,
|
|
7171
7227
|
children: t("capabilitiesNote")
|
|
7172
7228
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("ul", {
|
|
7173
|
-
className:
|
|
7229
|
+
className: _dsh_plugin_shop_css_e3675a89_default.capabilities,
|
|
7174
7230
|
children: entry.catalog.capabilities.map((capability) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", { children: capability }, capability))
|
|
7175
7231
|
})]
|
|
7176
7232
|
}),
|
|
7177
7233
|
open && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
7178
7234
|
id: detailId,
|
|
7179
|
-
className:
|
|
7235
|
+
className: _dsh_plugin_shop_css_e3675a89_default.detail,
|
|
7180
7236
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("dl", {
|
|
7181
|
-
className:
|
|
7237
|
+
className: _dsh_plugin_shop_css_e3675a89_default.detailRows,
|
|
7182
7238
|
children: [
|
|
7183
7239
|
npmUrl !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
7184
|
-
className:
|
|
7240
|
+
className: _dsh_plugin_shop_css_e3675a89_default.detailRow,
|
|
7185
7241
|
"data-shop-npm": true,
|
|
7186
7242
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("dt", { children: t("npmPage") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("dd", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", {
|
|
7187
7243
|
href: npmUrl,
|
|
@@ -7191,7 +7247,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
7191
7247
|
}) })]
|
|
7192
7248
|
}),
|
|
7193
7249
|
entry.repository !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
7194
|
-
className:
|
|
7250
|
+
className: _dsh_plugin_shop_css_e3675a89_default.detailRow,
|
|
7195
7251
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("dt", { children: t("repository") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("dd", { children: /^https?:\/\//.test(entry.repository) ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", {
|
|
7196
7252
|
href: entry.repository,
|
|
7197
7253
|
target: "_blank",
|
|
@@ -7200,12 +7256,12 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
7200
7256
|
}) : entry.repository })]
|
|
7201
7257
|
}),
|
|
7202
7258
|
entry.license !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
7203
|
-
className:
|
|
7259
|
+
className: _dsh_plugin_shop_css_e3675a89_default.detailRow,
|
|
7204
7260
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("dt", { children: t("license") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("dd", { children: isCustomLicense(entry.license) ? t("customLicense") : entry.license })]
|
|
7205
7261
|
})
|
|
7206
7262
|
]
|
|
7207
7263
|
}), entry.tier === "verified-stale" && entry.review !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
7208
|
-
className:
|
|
7264
|
+
className: _dsh_plugin_shop_css_e3675a89_default.reviewedLine,
|
|
7209
7265
|
children: entry.review.reviewedVersion !== void 0 ? t("reviewedVersionLine", {
|
|
7210
7266
|
reviewed: entry.review.reviewedVersion,
|
|
7211
7267
|
current: entry.version
|
|
@@ -7218,7 +7274,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
7218
7274
|
]
|
|
7219
7275
|
}),
|
|
7220
7276
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
7221
|
-
className:
|
|
7277
|
+
className: _dsh_plugin_shop_css_e3675a89_default.cardActions,
|
|
7222
7278
|
"data-shop-actions": true,
|
|
7223
7279
|
children: [installed === void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(InstallPanel, {
|
|
7224
7280
|
target: installTarget,
|
|
@@ -7243,7 +7299,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
7243
7299
|
restart,
|
|
7244
7300
|
restartSupported
|
|
7245
7301
|
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
7246
|
-
className:
|
|
7302
|
+
className: _dsh_plugin_shop_css_e3675a89_default.installedLabel,
|
|
7247
7303
|
"data-shop-installed": true,
|
|
7248
7304
|
children: t("installed")
|
|
7249
7305
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(BlockerBadge, {
|
|
@@ -7264,10 +7320,20 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
7264
7320
|
restartSupported,
|
|
7265
7321
|
onSettled: uninstallSettled
|
|
7266
7322
|
})
|
|
7267
|
-
] }), author !== null && /* @__PURE__ */ (0, react_jsx_runtime.
|
|
7268
|
-
className:
|
|
7269
|
-
"
|
|
7270
|
-
|
|
7323
|
+
] }), (size !== void 0 || author !== null) && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
7324
|
+
className: _dsh_plugin_shop_css_e3675a89_default.cardMeta,
|
|
7325
|
+
children: [size !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
7326
|
+
className: _dsh_plugin_shop_css_e3675a89_default.size,
|
|
7327
|
+
"data-shop-size": true,
|
|
7328
|
+
role: "img",
|
|
7329
|
+
"aria-label": t("sizeLabel", { size }),
|
|
7330
|
+
title: t("sizeLabel", { size }),
|
|
7331
|
+
children: size
|
|
7332
|
+
}), author !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
7333
|
+
className: _dsh_plugin_shop_css_e3675a89_default.author,
|
|
7334
|
+
"data-shop-author": true,
|
|
7335
|
+
children: t("authorLine", { author })
|
|
7336
|
+
})]
|
|
7271
7337
|
})]
|
|
7272
7338
|
})
|
|
7273
7339
|
]
|
|
@@ -7303,7 +7369,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
7303
7369
|
const detail = blockers.map((blocker) => blocker.text).join("\n");
|
|
7304
7370
|
const taken = blockers.some((blocker) => blocker.kind === "name-taken");
|
|
7305
7371
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
7306
|
-
className:
|
|
7372
|
+
className: _dsh_plugin_shop_css_e3675a89_default.incompatibleBadge,
|
|
7307
7373
|
"data-shop-blocker": taken ? "name-taken" : "missing-peers",
|
|
7308
7374
|
role: "img",
|
|
7309
7375
|
"aria-label": detail,
|
|
@@ -7320,30 +7386,30 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
7320
7386
|
const [gateOpen, setGateOpen] = (0, react.useState)(false);
|
|
7321
7387
|
const { view, start } = flow;
|
|
7322
7388
|
if (view.kind === "running") return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
7323
|
-
className:
|
|
7389
|
+
className: _dsh_plugin_shop_css_e3675a89_default.installPanel,
|
|
7324
7390
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
7325
|
-
className:
|
|
7391
|
+
className: _dsh_plugin_shop_css_e3675a89_default.installing,
|
|
7326
7392
|
children: t("installing")
|
|
7327
7393
|
}), view.log.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
7328
|
-
className:
|
|
7394
|
+
className: _dsh_plugin_shop_css_e3675a89_default.log,
|
|
7329
7395
|
children: view.log.map((line, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
7330
|
-
className:
|
|
7396
|
+
className: _dsh_plugin_shop_css_e3675a89_default.logLine,
|
|
7331
7397
|
children: line
|
|
7332
7398
|
}, index))
|
|
7333
7399
|
})]
|
|
7334
7400
|
});
|
|
7335
7401
|
if (view.kind === "done") return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
7336
|
-
className:
|
|
7402
|
+
className: _dsh_plugin_shop_css_e3675a89_default.installedActions,
|
|
7337
7403
|
children: [
|
|
7338
7404
|
view.log.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
7339
|
-
className:
|
|
7405
|
+
className: _dsh_plugin_shop_css_e3675a89_default.log,
|
|
7340
7406
|
children: view.log.map((line, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
7341
|
-
className:
|
|
7407
|
+
className: _dsh_plugin_shop_css_e3675a89_default.logLine,
|
|
7342
7408
|
children: line
|
|
7343
7409
|
}, index))
|
|
7344
7410
|
}),
|
|
7345
7411
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
7346
|
-
className:
|
|
7412
|
+
className: _dsh_plugin_shop_css_e3675a89_default.notice,
|
|
7347
7413
|
"data-shop-restart-notice": true,
|
|
7348
7414
|
children: view.needsRestart ? t(restartReasonKey(view.restartReason)) : t("installedNoRestartNotice")
|
|
7349
7415
|
}),
|
|
@@ -7352,63 +7418,63 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
7352
7418
|
restart
|
|
7353
7419
|
}),
|
|
7354
7420
|
view.needsRestart && !restartSupported && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
7355
|
-
className:
|
|
7421
|
+
className: _dsh_plugin_shop_css_e3675a89_default.notice,
|
|
7356
7422
|
"data-shop-restart-disabled": true,
|
|
7357
7423
|
children: t("restartDisabledNotice")
|
|
7358
7424
|
})
|
|
7359
7425
|
]
|
|
7360
7426
|
});
|
|
7361
7427
|
if (view.kind === "failed") return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
7362
|
-
className:
|
|
7428
|
+
className: _dsh_plugin_shop_css_e3675a89_default.installPanel,
|
|
7363
7429
|
children: [
|
|
7364
7430
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
7365
|
-
className:
|
|
7431
|
+
className: _dsh_plugin_shop_css_e3675a89_default.failedHeading,
|
|
7366
7432
|
children: t("installFailed")
|
|
7367
7433
|
}),
|
|
7368
7434
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
7369
|
-
className:
|
|
7435
|
+
className: _dsh_plugin_shop_css_e3675a89_default.log,
|
|
7370
7436
|
children: view.log.map((line, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
7371
|
-
className:
|
|
7437
|
+
className: _dsh_plugin_shop_css_e3675a89_default.logLine,
|
|
7372
7438
|
children: line
|
|
7373
7439
|
}, index))
|
|
7374
7440
|
}),
|
|
7375
7441
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
7376
|
-
className:
|
|
7442
|
+
className: _dsh_plugin_shop_css_e3675a89_default.failedDetail,
|
|
7377
7443
|
children: view.detail === "" ? t("installTransportFailed") : view.detail
|
|
7378
7444
|
})
|
|
7379
7445
|
]
|
|
7380
7446
|
});
|
|
7381
7447
|
if (view.kind === "rejected") return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
7382
|
-
className:
|
|
7448
|
+
className: _dsh_plugin_shop_css_e3675a89_default.installPanel,
|
|
7383
7449
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
7384
|
-
className:
|
|
7450
|
+
className: _dsh_plugin_shop_css_e3675a89_default.rejectedCode,
|
|
7385
7451
|
children: t(rejectionCodeKey(view.code))
|
|
7386
7452
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
7387
|
-
className:
|
|
7453
|
+
className: _dsh_plugin_shop_css_e3675a89_default.rejectedDetail,
|
|
7388
7454
|
children: view.detail
|
|
7389
7455
|
})]
|
|
7390
7456
|
});
|
|
7391
7457
|
if (gateOpen) return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
7392
|
-
className:
|
|
7458
|
+
className: _dsh_plugin_shop_css_e3675a89_default.gate,
|
|
7393
7459
|
children: [
|
|
7394
7460
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
7395
|
-
className:
|
|
7461
|
+
className: _dsh_plugin_shop_css_e3675a89_default.gateTitle,
|
|
7396
7462
|
children: t("acknowledgementTitle")
|
|
7397
7463
|
}),
|
|
7398
7464
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
7399
|
-
className:
|
|
7465
|
+
className: _dsh_plugin_shop_css_e3675a89_default.gateBody,
|
|
7400
7466
|
children: t("acknowledgementBody")
|
|
7401
7467
|
}),
|
|
7402
7468
|
!missingStated && blockersOf(missing, void 0, t).map((blocker) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
7403
|
-
className:
|
|
7469
|
+
className: _dsh_plugin_shop_css_e3675a89_default.gateWarning,
|
|
7404
7470
|
"data-shop-incompatible-warning": true,
|
|
7405
7471
|
children: blocker.text
|
|
7406
7472
|
}, blocker.kind)),
|
|
7407
7473
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
7408
|
-
className:
|
|
7474
|
+
className: _dsh_plugin_shop_css_e3675a89_default.gateActions,
|
|
7409
7475
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
7410
7476
|
type: "button",
|
|
7411
|
-
className:
|
|
7477
|
+
className: _dsh_plugin_shop_css_e3675a89_default.confirmButton,
|
|
7412
7478
|
"data-shop-confirm": true,
|
|
7413
7479
|
onClick: () => {
|
|
7414
7480
|
setGateOpen(false);
|
|
@@ -7420,7 +7486,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
7420
7486
|
children: t("confirm")
|
|
7421
7487
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
7422
7488
|
type: "button",
|
|
7423
|
-
className:
|
|
7489
|
+
className: _dsh_plugin_shop_css_e3675a89_default.cancelButton,
|
|
7424
7490
|
onClick: () => setGateOpen(false),
|
|
7425
7491
|
children: t("cancel")
|
|
7426
7492
|
})]
|
|
@@ -7431,7 +7497,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
7431
7497
|
const refused = blockers.some((blocker) => blocker.kind === "name-taken");
|
|
7432
7498
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
7433
7499
|
type: "button",
|
|
7434
|
-
className:
|
|
7500
|
+
className: _dsh_plugin_shop_css_e3675a89_default.installButton,
|
|
7435
7501
|
disabled: refused,
|
|
7436
7502
|
...refused ? { "data-shop-refused": true } : {},
|
|
7437
7503
|
...update ? { "data-shop-update": true } : { "data-shop-install": true },
|
|
@@ -7462,23 +7528,23 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
7462
7528
|
if (view.kind === "done") settled.current();
|
|
7463
7529
|
}, [view.kind]);
|
|
7464
7530
|
if (view.kind === "running") return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
7465
|
-
className:
|
|
7531
|
+
className: _dsh_plugin_shop_css_e3675a89_default.installPanel,
|
|
7466
7532
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
7467
|
-
className:
|
|
7533
|
+
className: _dsh_plugin_shop_css_e3675a89_default.installing,
|
|
7468
7534
|
children: t("uninstalling")
|
|
7469
7535
|
}), view.log.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
7470
|
-
className:
|
|
7536
|
+
className: _dsh_plugin_shop_css_e3675a89_default.log,
|
|
7471
7537
|
children: view.log.map((line, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
7472
|
-
className:
|
|
7538
|
+
className: _dsh_plugin_shop_css_e3675a89_default.logLine,
|
|
7473
7539
|
children: line
|
|
7474
7540
|
}, index))
|
|
7475
7541
|
})]
|
|
7476
7542
|
});
|
|
7477
7543
|
if (view.kind === "done") return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
7478
|
-
className:
|
|
7544
|
+
className: _dsh_plugin_shop_css_e3675a89_default.installedActions,
|
|
7479
7545
|
children: [
|
|
7480
7546
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
7481
|
-
className:
|
|
7547
|
+
className: _dsh_plugin_shop_css_e3675a89_default.notice,
|
|
7482
7548
|
"data-shop-uninstall-done": true,
|
|
7483
7549
|
children: view.needsRestart ? t("uninstalledRestartNotice") : t("uninstalledLiveNotice")
|
|
7484
7550
|
}),
|
|
@@ -7487,28 +7553,28 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
7487
7553
|
restart
|
|
7488
7554
|
}),
|
|
7489
7555
|
view.needsRestart && !restartSupported && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
7490
|
-
className:
|
|
7556
|
+
className: _dsh_plugin_shop_css_e3675a89_default.notice,
|
|
7491
7557
|
"data-shop-restart-disabled": true,
|
|
7492
7558
|
children: t("restartDisabledNotice")
|
|
7493
7559
|
})
|
|
7494
7560
|
]
|
|
7495
7561
|
});
|
|
7496
7562
|
if (view.kind === "failed") return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
7497
|
-
className:
|
|
7563
|
+
className: _dsh_plugin_shop_css_e3675a89_default.installPanel,
|
|
7498
7564
|
children: [
|
|
7499
7565
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
7500
|
-
className:
|
|
7566
|
+
className: _dsh_plugin_shop_css_e3675a89_default.failedHeading,
|
|
7501
7567
|
children: t("uninstallFailed")
|
|
7502
7568
|
}),
|
|
7503
7569
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
7504
|
-
className:
|
|
7570
|
+
className: _dsh_plugin_shop_css_e3675a89_default.log,
|
|
7505
7571
|
children: view.log.map((line, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
7506
|
-
className:
|
|
7572
|
+
className: _dsh_plugin_shop_css_e3675a89_default.logLine,
|
|
7507
7573
|
children: line
|
|
7508
7574
|
}, index))
|
|
7509
7575
|
}),
|
|
7510
7576
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
7511
|
-
className:
|
|
7577
|
+
className: _dsh_plugin_shop_css_e3675a89_default.failedDetail,
|
|
7512
7578
|
children: view.detail === "" ? t("uninstallTransportFailed") : view.detail
|
|
7513
7579
|
})
|
|
7514
7580
|
]
|
|
@@ -7516,7 +7582,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
7516
7582
|
if (view.kind !== "idle") return null;
|
|
7517
7583
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
7518
7584
|
type: "button",
|
|
7519
|
-
className:
|
|
7585
|
+
className: _dsh_plugin_shop_css_e3675a89_default.uninstallButton,
|
|
7520
7586
|
"data-shop-uninstall": true,
|
|
7521
7587
|
onClick: () => void start({ name }),
|
|
7522
7588
|
children: t("uninstall")
|
|
@@ -7578,37 +7644,37 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
7578
7644
|
return () => clearInterval(timer);
|
|
7579
7645
|
}, [state, t]);
|
|
7580
7646
|
if (state.kind === "restarting") return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
7581
|
-
className:
|
|
7647
|
+
className: _dsh_plugin_shop_css_e3675a89_default.notice,
|
|
7582
7648
|
"data-shop-restarting": true,
|
|
7583
7649
|
children: t("restarting")
|
|
7584
7650
|
});
|
|
7585
7651
|
if (state.kind === "failed") return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
7586
|
-
className:
|
|
7652
|
+
className: _dsh_plugin_shop_css_e3675a89_default.failedDetail,
|
|
7587
7653
|
"data-shop-restart-error": true,
|
|
7588
7654
|
children: state.detail
|
|
7589
7655
|
});
|
|
7590
7656
|
if (gateOpen) return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
7591
|
-
className:
|
|
7657
|
+
className: _dsh_plugin_shop_css_e3675a89_default.gate,
|
|
7592
7658
|
children: [
|
|
7593
7659
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
7594
|
-
className:
|
|
7660
|
+
className: _dsh_plugin_shop_css_e3675a89_default.gateTitle,
|
|
7595
7661
|
children: t("restartTitle")
|
|
7596
7662
|
}),
|
|
7597
7663
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
7598
|
-
className:
|
|
7664
|
+
className: _dsh_plugin_shop_css_e3675a89_default.gateBody,
|
|
7599
7665
|
children: t("restartBody")
|
|
7600
7666
|
}),
|
|
7601
7667
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
7602
|
-
className:
|
|
7668
|
+
className: _dsh_plugin_shop_css_e3675a89_default.gateActions,
|
|
7603
7669
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
7604
7670
|
type: "button",
|
|
7605
|
-
className:
|
|
7671
|
+
className: _dsh_plugin_shop_css_e3675a89_default.confirmButton,
|
|
7606
7672
|
"data-shop-restart-confirm": true,
|
|
7607
7673
|
onClick: () => void onConfirm(),
|
|
7608
7674
|
children: t("restartConfirm")
|
|
7609
7675
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
7610
7676
|
type: "button",
|
|
7611
|
-
className:
|
|
7677
|
+
className: _dsh_plugin_shop_css_e3675a89_default.cancelButton,
|
|
7612
7678
|
onClick: () => setGateOpen(false),
|
|
7613
7679
|
children: t("cancel")
|
|
7614
7680
|
})]
|
|
@@ -7618,7 +7684,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
7618
7684
|
if (gate !== void 0) return null;
|
|
7619
7685
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
7620
7686
|
type: "button",
|
|
7621
|
-
className:
|
|
7687
|
+
className: _dsh_plugin_shop_css_e3675a89_default.restartButton,
|
|
7622
7688
|
"data-shop-restart": true,
|
|
7623
7689
|
onClick: () => setGateOpen(true),
|
|
7624
7690
|
children: t("restart")
|
|
@@ -7658,7 +7724,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
7658
7724
|
}
|
|
7659
7725
|
};
|
|
7660
7726
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
7661
|
-
className:
|
|
7727
|
+
className: _dsh_plugin_shop_css_e3675a89_default.switchWrap,
|
|
7662
7728
|
"data-shop-enabled-switch": row.name,
|
|
7663
7729
|
children: [
|
|
7664
7730
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
@@ -7667,18 +7733,18 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
7667
7733
|
"aria-checked": enabled,
|
|
7668
7734
|
"aria-label": t("enabledSwitch"),
|
|
7669
7735
|
"data-shop-toggle": true,
|
|
7670
|
-
className: `${
|
|
7736
|
+
className: `${_dsh_plugin_shop_css_e3675a89_default.switch} ${enabled ? _dsh_plugin_shop_css_e3675a89_default.switchOn : ""}`,
|
|
7671
7737
|
onClick: () => void onToggle(),
|
|
7672
7738
|
disabled: toggle.kind === "saving",
|
|
7673
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className:
|
|
7739
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: _dsh_plugin_shop_css_e3675a89_default.switchKnob })
|
|
7674
7740
|
}),
|
|
7675
7741
|
toggle.kind === "saved" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
7676
|
-
className:
|
|
7742
|
+
className: _dsh_plugin_shop_css_e3675a89_default.notice,
|
|
7677
7743
|
"data-shop-hot-apply": true,
|
|
7678
7744
|
children: t("hotApplyNote")
|
|
7679
7745
|
}),
|
|
7680
7746
|
toggle.kind === "error" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
7681
|
-
className:
|
|
7747
|
+
className: _dsh_plugin_shop_css_e3675a89_default.failedDetail,
|
|
7682
7748
|
"data-shop-toggle-error": true,
|
|
7683
7749
|
children: toggle.detail
|
|
7684
7750
|
})
|
|
@@ -7690,19 +7756,19 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
7690
7756
|
* install flow for `name@latest`, reusing `InstallPanel`). */
|
|
7691
7757
|
function OutdatedRow({ row, tier, missing, t, setEnabled, flowFor, restart, restartSupported }) {
|
|
7692
7758
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
7693
|
-
className:
|
|
7759
|
+
className: _dsh_plugin_shop_css_e3675a89_default.outdatedRow,
|
|
7694
7760
|
"data-shop-outdated-entry": row.name,
|
|
7695
7761
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
7696
|
-
className:
|
|
7762
|
+
className: _dsh_plugin_shop_css_e3675a89_default.outdatedInfo,
|
|
7697
7763
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
7698
|
-
className:
|
|
7764
|
+
className: _dsh_plugin_shop_css_e3675a89_default.name,
|
|
7699
7765
|
children: row.name
|
|
7700
7766
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
7701
|
-
className:
|
|
7767
|
+
className: _dsh_plugin_shop_css_e3675a89_default.outdatedVersions,
|
|
7702
7768
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("installedVersion", { version: row.source === "github" ? row.installed.slice(0, 7) : row.installed }) }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("latestVersion", { version: row.latest }) })]
|
|
7703
7769
|
})]
|
|
7704
7770
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
7705
|
-
className:
|
|
7771
|
+
className: _dsh_plugin_shop_css_e3675a89_default.outdatedActions,
|
|
7706
7772
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(EnabledSwitch, {
|
|
7707
7773
|
row,
|
|
7708
7774
|
t,
|
|
@@ -7737,20 +7803,20 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
7737
7803
|
function OutdatedSection({ state, entriesByKey, missingByKey, t, setEnabled, flowFor, restart, restartSupported }) {
|
|
7738
7804
|
if (state.kind === "loading") return null;
|
|
7739
7805
|
if (state.kind === "error") return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
7740
|
-
className:
|
|
7806
|
+
className: _dsh_plugin_shop_css_e3675a89_default.stateLine,
|
|
7741
7807
|
"data-shop-outdated-error": true,
|
|
7742
7808
|
children: t("error")
|
|
7743
7809
|
});
|
|
7744
7810
|
const outdated = state.entries.filter((entry) => entry.outdated);
|
|
7745
7811
|
if (outdated.length === 0) return null;
|
|
7746
7812
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
7747
|
-
className:
|
|
7813
|
+
className: _dsh_plugin_shop_css_e3675a89_default.outdatedSection,
|
|
7748
7814
|
"data-shop-outdated": true,
|
|
7749
7815
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h2", {
|
|
7750
|
-
className:
|
|
7816
|
+
className: _dsh_plugin_shop_css_e3675a89_default.catalogHeading,
|
|
7751
7817
|
children: t("installedSection")
|
|
7752
7818
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("ul", {
|
|
7753
|
-
className:
|
|
7819
|
+
className: _dsh_plugin_shop_css_e3675a89_default.outdatedList,
|
|
7754
7820
|
children: outdated.map((row) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(OutdatedRow, {
|
|
7755
7821
|
row,
|
|
7756
7822
|
tier: entriesByKey.get(identityKey(row))?.tier ?? "community",
|
|
@@ -7789,6 +7855,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
7789
7855
|
const [reloadFailed, setReloadFailed] = (0, react.useState)(false);
|
|
7790
7856
|
const [query, setQuery] = (0, react.useState)("");
|
|
7791
7857
|
const [category, setCategory] = (0, react.useState)(null);
|
|
7858
|
+
const [hideIncompatible, setHideIncompatible] = (0, react.useState)(false);
|
|
7792
7859
|
const incremental = typeof IntersectionObserver !== "undefined";
|
|
7793
7860
|
const [visibleCount, setVisibleCount] = (0, react.useState)(48);
|
|
7794
7861
|
const sentinelRef = (0, react.useRef)(null);
|
|
@@ -7887,7 +7954,22 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
7887
7954
|
}, [catalogState]);
|
|
7888
7955
|
const stars = (0, react.useMemo)(() => catalogState.kind === "ready" ? catalogState.result.stars : {}, [catalogState]);
|
|
7889
7956
|
const sortedBrowsable = (0, react.useMemo)(() => sortByStars(browsable, stars), [browsable, stars]);
|
|
7890
|
-
const
|
|
7957
|
+
const missingByKey = (0, react.useMemo)(() => {
|
|
7958
|
+
const map = /* @__PURE__ */ new Map();
|
|
7959
|
+
if (catalogState.kind === "ready") for (const entry of catalogState.result.plugins) map.set(entryKey(entry), missingPeersOf(catalogState.result.incompatible, entryKey(entry)));
|
|
7960
|
+
return map;
|
|
7961
|
+
}, [catalogState]);
|
|
7962
|
+
const nameTakenByKey = (0, react.useMemo)(() => {
|
|
7963
|
+
const map = /* @__PURE__ */ new Map();
|
|
7964
|
+
if (catalogState.kind !== "ready") return map;
|
|
7965
|
+
for (const entry of catalogState.result.plugins) {
|
|
7966
|
+
const holder = heldBy(entry, specs);
|
|
7967
|
+
if (holder !== void 0) map.set(entryKey(entry), holder);
|
|
7968
|
+
}
|
|
7969
|
+
return map;
|
|
7970
|
+
}, [catalogState, specs]);
|
|
7971
|
+
const badgedIncompatible = (0, react.useCallback)((key) => (missingByKey.get(key) ?? []).length > 0 && !nameTakenByKey.has(key), [missingByKey, nameTakenByKey]);
|
|
7972
|
+
const matched = (0, react.useMemo)(() => {
|
|
7891
7973
|
const q = query.trim().toLowerCase();
|
|
7892
7974
|
return sortedBrowsable.filter((entry) => {
|
|
7893
7975
|
if (category === "installed") {
|
|
@@ -7904,6 +7986,12 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
7904
7986
|
category,
|
|
7905
7987
|
installedByKey
|
|
7906
7988
|
]);
|
|
7989
|
+
const filtered = (0, react.useMemo)(() => hideIncompatible && category !== "installed" ? matched.filter((entry) => !badgedIncompatible(entryKey(entry))) : matched, [
|
|
7990
|
+
matched,
|
|
7991
|
+
hideIncompatible,
|
|
7992
|
+
category,
|
|
7993
|
+
badgedIncompatible
|
|
7994
|
+
]);
|
|
7907
7995
|
filteredLenRef.current = filtered.length;
|
|
7908
7996
|
(0, react.useEffect)(() => {
|
|
7909
7997
|
if (!incremental) return;
|
|
@@ -7933,70 +8021,57 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
7933
8021
|
if (installedState.kind !== "ready") return 0;
|
|
7934
8022
|
return installedState.entries.filter((entry) => !isShopLike(entry.name)).length;
|
|
7935
8023
|
}, [installedState]);
|
|
8024
|
+
const incompatibleCount = (0, react.useMemo)(() => browsable.filter((entry) => badgedIncompatible(entryKey(entry))).length, [browsable, badgedIncompatible]);
|
|
7936
8025
|
const entriesByKey = (0, react.useMemo)(() => {
|
|
7937
8026
|
const map = /* @__PURE__ */ new Map();
|
|
7938
8027
|
if (catalogState.kind === "ready") for (const entry of catalogState.result.plugins) map.set(entryKey(entry), entry);
|
|
7939
8028
|
return map;
|
|
7940
8029
|
}, [catalogState]);
|
|
7941
|
-
const missingByKey = (0, react.useMemo)(() => {
|
|
7942
|
-
const map = /* @__PURE__ */ new Map();
|
|
7943
|
-
if (catalogState.kind === "ready") for (const entry of catalogState.result.plugins) map.set(entryKey(entry), missingPeersOf(catalogState.result.incompatible, entryKey(entry)));
|
|
7944
|
-
return map;
|
|
7945
|
-
}, [catalogState]);
|
|
7946
|
-
const nameTakenByKey = (0, react.useMemo)(() => {
|
|
7947
|
-
const map = /* @__PURE__ */ new Map();
|
|
7948
|
-
if (catalogState.kind !== "ready") return map;
|
|
7949
|
-
for (const entry of catalogState.result.plugins) {
|
|
7950
|
-
const holder = heldBy(entry, specs);
|
|
7951
|
-
if (holder !== void 0) map.set(entryKey(entry), holder);
|
|
7952
|
-
}
|
|
7953
|
-
return map;
|
|
7954
|
-
}, [catalogState, specs]);
|
|
7955
8030
|
if (catalogState.kind === "loading") return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
7956
|
-
className:
|
|
8031
|
+
className: _dsh_plugin_shop_css_e3675a89_default.panel,
|
|
7957
8032
|
"data-shop-tab": true,
|
|
7958
8033
|
"aria-busy": "true",
|
|
7959
8034
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
7960
|
-
className:
|
|
8035
|
+
className: _dsh_plugin_shop_css_e3675a89_default.srOnly,
|
|
7961
8036
|
children: t("loading")
|
|
7962
8037
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
7963
|
-
className:
|
|
8038
|
+
className: _dsh_plugin_shop_css_e3675a89_default.skeletonGrid,
|
|
7964
8039
|
"data-shop-skeleton": true,
|
|
7965
8040
|
"aria-hidden": "true",
|
|
7966
8041
|
children: Array.from({ length: 8 }, (_, i) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
7967
|
-
className:
|
|
8042
|
+
className: _dsh_plugin_shop_css_e3675a89_default.skeletonCard,
|
|
7968
8043
|
children: [
|
|
7969
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className:
|
|
7970
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className:
|
|
7971
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className:
|
|
7972
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className:
|
|
8044
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: _dsh_plugin_shop_css_e3675a89_default.skeletonName }),
|
|
8045
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: _dsh_plugin_shop_css_e3675a89_default.skeletonSummary }),
|
|
8046
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: _dsh_plugin_shop_css_e3675a89_default.skeletonSummaryShort }),
|
|
8047
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: _dsh_plugin_shop_css_e3675a89_default.skeletonActions })
|
|
7973
8048
|
]
|
|
7974
8049
|
}, i))
|
|
7975
8050
|
})]
|
|
7976
8051
|
});
|
|
7977
8052
|
if (catalogState.kind === "error") return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
7978
|
-
className:
|
|
8053
|
+
className: _dsh_plugin_shop_css_e3675a89_default.panel,
|
|
7979
8054
|
"data-shop-tab": true,
|
|
7980
8055
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
7981
|
-
className:
|
|
8056
|
+
className: _dsh_plugin_shop_css_e3675a89_default.stateLine,
|
|
7982
8057
|
children: t("error")
|
|
7983
8058
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
7984
8059
|
type: "button",
|
|
7985
|
-
className:
|
|
8060
|
+
className: _dsh_plugin_shop_css_e3675a89_default.actionButton,
|
|
7986
8061
|
onClick: () => setRequest({ kind: "retry" }),
|
|
7987
8062
|
children: t("retry")
|
|
7988
8063
|
})]
|
|
7989
8064
|
});
|
|
7990
8065
|
const { result } = catalogState;
|
|
7991
8066
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
7992
|
-
className:
|
|
8067
|
+
className: _dsh_plugin_shop_css_e3675a89_default.panel,
|
|
7993
8068
|
"data-shop-tab": true,
|
|
7994
8069
|
children: [
|
|
7995
8070
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
7996
|
-
className:
|
|
8071
|
+
className: _dsh_plugin_shop_css_e3675a89_default.toolbar,
|
|
7997
8072
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
7998
8073
|
type: "search",
|
|
7999
|
-
className:
|
|
8074
|
+
className: _dsh_plugin_shop_css_e3675a89_default.searchInput,
|
|
8000
8075
|
"aria-label": t("search"),
|
|
8001
8076
|
placeholder: t("search"),
|
|
8002
8077
|
value: query,
|
|
@@ -8005,27 +8080,27 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
8005
8080
|
setVisibleCount(48);
|
|
8006
8081
|
}
|
|
8007
8082
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
8008
|
-
className:
|
|
8083
|
+
className: _dsh_plugin_shop_css_e3675a89_default.toolbarRight,
|
|
8009
8084
|
children: [
|
|
8010
8085
|
result.stale && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
8011
|
-
className:
|
|
8086
|
+
className: _dsh_plugin_shop_css_e3675a89_default.staleBadge,
|
|
8012
8087
|
children: t("staleLabel", { date: result.builtAt.slice(0, 10) })
|
|
8013
8088
|
}),
|
|
8014
8089
|
selfVersion !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
8015
|
-
className:
|
|
8090
|
+
className: _dsh_plugin_shop_css_e3675a89_default.versionBlock,
|
|
8016
8091
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
8017
|
-
className:
|
|
8092
|
+
className: _dsh_plugin_shop_css_e3675a89_default.versionText,
|
|
8018
8093
|
"data-shop-version": true,
|
|
8019
8094
|
children: ["v", selfVersion.installed]
|
|
8020
8095
|
}), selfUpdate.view.kind === "done" && restartSupported ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
8021
8096
|
type: "button",
|
|
8022
|
-
className:
|
|
8097
|
+
className: _dsh_plugin_shop_css_e3675a89_default.restartSelfButton,
|
|
8023
8098
|
"data-shop-restart": true,
|
|
8024
8099
|
onClick: () => setSelfRestartGate(true),
|
|
8025
8100
|
children: t("restart")
|
|
8026
8101
|
}) : selfVersion.outdated && selfVersion.latest !== null && selfUpdate.view.kind === "idle" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
8027
8102
|
type: "button",
|
|
8028
|
-
className:
|
|
8103
|
+
className: _dsh_plugin_shop_css_e3675a89_default.updateSelfButton,
|
|
8029
8104
|
"data-shop-update-self": true,
|
|
8030
8105
|
onClick: () => {
|
|
8031
8106
|
if (selfVersion.latest !== null) selfUpdate.start({ version: selfVersion.latest });
|
|
@@ -8033,7 +8108,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
8033
8108
|
children: t("update")
|
|
8034
8109
|
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
8035
8110
|
type: "button",
|
|
8036
|
-
className:
|
|
8111
|
+
className: _dsh_plugin_shop_css_e3675a89_default.checkUpdateButton,
|
|
8037
8112
|
"data-shop-check-update": true,
|
|
8038
8113
|
title: t("checkUpdateTitle"),
|
|
8039
8114
|
disabled: checkState !== "idle",
|
|
@@ -8042,7 +8117,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
8042
8117
|
})]
|
|
8043
8118
|
}),
|
|
8044
8119
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", {
|
|
8045
|
-
className:
|
|
8120
|
+
className: _dsh_plugin_shop_css_e3675a89_default.githubLink,
|
|
8046
8121
|
href: SHOP_REPO_URL,
|
|
8047
8122
|
target: "_blank",
|
|
8048
8123
|
rel: "noopener noreferrer",
|
|
@@ -8061,27 +8136,27 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
8061
8136
|
})]
|
|
8062
8137
|
}),
|
|
8063
8138
|
selfUpdate.view.kind === "running" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
8064
|
-
className:
|
|
8139
|
+
className: _dsh_plugin_shop_css_e3675a89_default.selfUpdatePanel,
|
|
8065
8140
|
"data-shop-self-updating": true,
|
|
8066
8141
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
8067
|
-
className:
|
|
8142
|
+
className: _dsh_plugin_shop_css_e3675a89_default.installing,
|
|
8068
8143
|
children: t("installing")
|
|
8069
8144
|
}), selfUpdate.view.log.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
8070
|
-
className:
|
|
8145
|
+
className: _dsh_plugin_shop_css_e3675a89_default.log,
|
|
8071
8146
|
children: selfUpdate.view.log.map((line, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
8072
|
-
className:
|
|
8147
|
+
className: _dsh_plugin_shop_css_e3675a89_default.logLine,
|
|
8073
8148
|
children: line
|
|
8074
8149
|
}, index))
|
|
8075
8150
|
})]
|
|
8076
8151
|
}),
|
|
8077
8152
|
selfUpdate.view.kind === "done" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
8078
|
-
className:
|
|
8153
|
+
className: _dsh_plugin_shop_css_e3675a89_default.selfUpdatePanel,
|
|
8079
8154
|
"data-shop-self-update-done": true,
|
|
8080
8155
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
8081
|
-
className:
|
|
8156
|
+
className: _dsh_plugin_shop_css_e3675a89_default.installedActions,
|
|
8082
8157
|
children: [
|
|
8083
8158
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
8084
|
-
className:
|
|
8159
|
+
className: _dsh_plugin_shop_css_e3675a89_default.notice,
|
|
8085
8160
|
children: t("installedRestartNotice")
|
|
8086
8161
|
}),
|
|
8087
8162
|
restartSupported && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RestartPanel, {
|
|
@@ -8093,7 +8168,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
8093
8168
|
}
|
|
8094
8169
|
}),
|
|
8095
8170
|
!restartSupported && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
8096
|
-
className:
|
|
8171
|
+
className: _dsh_plugin_shop_css_e3675a89_default.notice,
|
|
8097
8172
|
"data-shop-restart-disabled": true,
|
|
8098
8173
|
children: t("restartDisabledNotice")
|
|
8099
8174
|
})
|
|
@@ -8101,34 +8176,34 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
8101
8176
|
})
|
|
8102
8177
|
}),
|
|
8103
8178
|
selfUpdate.view.kind === "failed" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
8104
|
-
className:
|
|
8179
|
+
className: _dsh_plugin_shop_css_e3675a89_default.selfUpdatePanel,
|
|
8105
8180
|
"data-shop-self-update-failed": true,
|
|
8106
8181
|
children: [
|
|
8107
8182
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
8108
|
-
className:
|
|
8183
|
+
className: _dsh_plugin_shop_css_e3675a89_default.failedHeading,
|
|
8109
8184
|
children: t("updateFailed")
|
|
8110
8185
|
}),
|
|
8111
8186
|
selfUpdate.view.log.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
8112
|
-
className:
|
|
8187
|
+
className: _dsh_plugin_shop_css_e3675a89_default.log,
|
|
8113
8188
|
children: selfUpdate.view.log.map((line, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
8114
|
-
className:
|
|
8189
|
+
className: _dsh_plugin_shop_css_e3675a89_default.logLine,
|
|
8115
8190
|
children: line
|
|
8116
8191
|
}, index))
|
|
8117
8192
|
}),
|
|
8118
8193
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
8119
|
-
className:
|
|
8194
|
+
className: _dsh_plugin_shop_css_e3675a89_default.failedDetail,
|
|
8120
8195
|
children: selfUpdate.view.detail === "" ? t("updateTransportFailed") : selfUpdate.view.detail
|
|
8121
8196
|
})
|
|
8122
8197
|
]
|
|
8123
8198
|
}),
|
|
8124
8199
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
8125
|
-
className:
|
|
8200
|
+
className: _dsh_plugin_shop_css_e3675a89_default.categoryBar,
|
|
8126
8201
|
role: "group",
|
|
8127
8202
|
"aria-label": t("catalog"),
|
|
8128
8203
|
children: [
|
|
8129
8204
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
8130
8205
|
type: "button",
|
|
8131
|
-
className: category === null ? `${
|
|
8206
|
+
className: category === null ? `${_dsh_plugin_shop_css_e3675a89_default.categoryButton} ${_dsh_plugin_shop_css_e3675a89_default.categoryButtonOn}` : _dsh_plugin_shop_css_e3675a89_default.categoryButton,
|
|
8132
8207
|
"aria-pressed": category === null,
|
|
8133
8208
|
onClick: () => {
|
|
8134
8209
|
setCategory(null);
|
|
@@ -8143,8 +8218,10 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
8143
8218
|
}),
|
|
8144
8219
|
CATEGORY_ORDER.map((key) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
8145
8220
|
type: "button",
|
|
8146
|
-
className: category === key ? `${
|
|
8221
|
+
className: category === key ? `${_dsh_plugin_shop_css_e3675a89_default.categoryButton} ${_dsh_plugin_shop_css_e3675a89_default.categoryButtonOn}` : _dsh_plugin_shop_css_e3675a89_default.categoryButton,
|
|
8147
8222
|
"aria-pressed": category === key,
|
|
8223
|
+
"data-category": key,
|
|
8224
|
+
"data-shop-category-tab": key,
|
|
8148
8225
|
onClick: () => {
|
|
8149
8226
|
setCategory(key);
|
|
8150
8227
|
setVisibleCount(48);
|
|
@@ -8157,8 +8234,9 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
8157
8234
|
}, key)),
|
|
8158
8235
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
8159
8236
|
type: "button",
|
|
8160
|
-
className: category === "installed" ? `${
|
|
8237
|
+
className: category === "installed" ? `${_dsh_plugin_shop_css_e3675a89_default.categoryButton} ${_dsh_plugin_shop_css_e3675a89_default.categoryButtonOn}` : _dsh_plugin_shop_css_e3675a89_default.categoryButton,
|
|
8161
8238
|
"aria-pressed": category === "installed",
|
|
8239
|
+
"data-shop-category-installed": true,
|
|
8162
8240
|
onClick: () => {
|
|
8163
8241
|
setCategory("installed");
|
|
8164
8242
|
setVisibleCount(48);
|
|
@@ -8168,14 +8246,25 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
8168
8246
|
" ",
|
|
8169
8247
|
installedCount
|
|
8170
8248
|
]
|
|
8249
|
+
}),
|
|
8250
|
+
category !== "installed" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
8251
|
+
type: "button",
|
|
8252
|
+
className: hideIncompatible ? `${_dsh_plugin_shop_css_e3675a89_default.categoryButton} ${_dsh_plugin_shop_css_e3675a89_default.incompatibleFilter} ${_dsh_plugin_shop_css_e3675a89_default.categoryButtonOn}` : `${_dsh_plugin_shop_css_e3675a89_default.categoryButton} ${_dsh_plugin_shop_css_e3675a89_default.incompatibleFilter}`,
|
|
8253
|
+
title: t(hideIncompatible ? "showIncompatibleTitle" : "incompatibleFilterTitle"),
|
|
8254
|
+
"data-shop-hide-incompatible": true,
|
|
8255
|
+
onClick: () => {
|
|
8256
|
+
setHideIncompatible((current) => !current);
|
|
8257
|
+
setVisibleCount(48);
|
|
8258
|
+
},
|
|
8259
|
+
children: t(hideIncompatible ? "showIncompatible" : "hideIncompatible", { count: incompatibleCount })
|
|
8171
8260
|
})
|
|
8172
8261
|
]
|
|
8173
8262
|
}),
|
|
8174
8263
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
8175
|
-
className:
|
|
8264
|
+
className: _dsh_plugin_shop_css_e3675a89_default.catalogStatsRow,
|
|
8176
8265
|
children: [
|
|
8177
8266
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
8178
|
-
className:
|
|
8267
|
+
className: _dsh_plugin_shop_css_e3675a89_default.catalogStats,
|
|
8179
8268
|
"data-shop-catalog-stats": true,
|
|
8180
8269
|
children: t("catalogStats", {
|
|
8181
8270
|
count: String(browsable.length),
|
|
@@ -8184,7 +8273,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
8184
8273
|
}),
|
|
8185
8274
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
8186
8275
|
type: "button",
|
|
8187
|
-
className:
|
|
8276
|
+
className: _dsh_plugin_shop_css_e3675a89_default.reloadButton,
|
|
8188
8277
|
"data-shop-reload": true,
|
|
8189
8278
|
disabled: reloading,
|
|
8190
8279
|
onClick: () => {
|
|
@@ -8195,20 +8284,21 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
8195
8284
|
children: reloading ? t("refreshing") : t("refresh")
|
|
8196
8285
|
}),
|
|
8197
8286
|
reloadFailed && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
8198
|
-
className:
|
|
8287
|
+
className: _dsh_plugin_shop_css_e3675a89_default.reloadFailed,
|
|
8199
8288
|
"data-shop-reload-failed": true,
|
|
8200
8289
|
children: t("refreshFailed")
|
|
8201
8290
|
})
|
|
8202
8291
|
]
|
|
8203
8292
|
}),
|
|
8204
8293
|
result.plugins.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
8205
|
-
className:
|
|
8294
|
+
className: _dsh_plugin_shop_css_e3675a89_default.emptyLine,
|
|
8206
8295
|
children: t("empty")
|
|
8207
8296
|
}) : filtered.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
8208
|
-
className:
|
|
8209
|
-
|
|
8297
|
+
className: _dsh_plugin_shop_css_e3675a89_default.emptyLine,
|
|
8298
|
+
"data-shop-empty": true,
|
|
8299
|
+
children: matched.length > 0 ? t("emptyIncompatibleFiltered") : t("emptySearch")
|
|
8210
8300
|
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("ul", {
|
|
8211
|
-
className:
|
|
8301
|
+
className: _dsh_plugin_shop_css_e3675a89_default.cards,
|
|
8212
8302
|
children: [visible.map((entry) => {
|
|
8213
8303
|
const key = entryKey(entry);
|
|
8214
8304
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(EntryCard, {
|
|
@@ -8228,12 +8318,12 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
8228
8318
|
}) }, key);
|
|
8229
8319
|
}), incremental && visibleCount < filtered.length && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", {
|
|
8230
8320
|
ref: sentinelRef,
|
|
8231
|
-
className:
|
|
8321
|
+
className: _dsh_plugin_shop_css_e3675a89_default.cardsSentry,
|
|
8232
8322
|
"data-shop-sentry": true,
|
|
8233
8323
|
"aria-hidden": "true"
|
|
8234
8324
|
})]
|
|
8235
8325
|
}), incremental && visibleCount < filtered.length && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
8236
|
-
className:
|
|
8326
|
+
className: _dsh_plugin_shop_css_e3675a89_default.showingLine,
|
|
8237
8327
|
"aria-live": "polite",
|
|
8238
8328
|
children: t("showing", {
|
|
8239
8329
|
shown: String(visibleCount),
|