dsh-plugin-shop 0.8.7-beta.0 → 0.8.7-beta.1
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/lib/client.js +540 -317
- package/lib/index.js +2 -1
- package/lib/typert.host.js +2 -1
- package/lib/typert.remote-client.js +1 -0
- package/lib/types/client/locales.d.ts +28 -0
- package/lib/types/client/present.d.ts +83 -8
- package/lib/types/host/types.d.ts +5 -0
- package/package.json +1 -1
package/lib/client.js
CHANGED
|
@@ -4328,6 +4328,11 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
4328
4328
|
_undefined(),
|
|
4329
4329
|
literal(false),
|
|
4330
4330
|
literal(true)
|
|
4331
|
+
]).optional(),
|
|
4332
|
+
"forked": union([
|
|
4333
|
+
_undefined(),
|
|
4334
|
+
literal(false),
|
|
4335
|
+
literal(true)
|
|
4331
4336
|
]).optional()
|
|
4332
4337
|
})),
|
|
4333
4338
|
"denied": array(object({
|
|
@@ -6546,15 +6551,61 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
6546
6551
|
case "desktop-profile": return "desktopProfileCode";
|
|
6547
6552
|
}
|
|
6548
6553
|
}
|
|
6549
|
-
/**
|
|
6550
|
-
|
|
6551
|
-
|
|
6554
|
+
/** A commit pin as the registry writes one: forty lowercase hex. */
|
|
6555
|
+
const COMMIT_PIN = /^[0-9a-f]{40}$/;
|
|
6556
|
+
/**
|
|
6557
|
+
* How a version string reads on the shelf, decided by its source and its
|
|
6558
|
+
* shape alone (market borrowings §11).
|
|
6559
|
+
*
|
|
6560
|
+
* Shape, never the entry's `tarball`, because an installed row carries only
|
|
6561
|
+
* the pin the shop recorded at install — the catalog `version` of that moment
|
|
6562
|
+
* — and no `tarball`. The registry pins a commit as forty lowercase hex and a
|
|
6563
|
+
* release by its tag, so the two shapes do not cross; `present.test.ts`
|
|
6564
|
+
* checks that against the committed live catalog.
|
|
6565
|
+
*
|
|
6566
|
+
* - An npm version takes the `v` the shelf has always shown, and only before
|
|
6567
|
+
* a digit: an installed row reports the manifest's spec, and a range there
|
|
6568
|
+
* (`^1.2.3`) is not a version to prefix.
|
|
6569
|
+
* - A commit is cut to the seven characters git abbreviates to, with no `v`:
|
|
6570
|
+
* it is not a version number.
|
|
6571
|
+
* - A release tag prints exactly as tagged, never cut and never prefixed:
|
|
6572
|
+
* cutting `v0.29.10` to seven characters printed `v0.29.1`, another
|
|
6573
|
+
* version, and the `v` this function no longer adds doubled the tag's own.
|
|
6574
|
+
*/
|
|
6575
|
+
function versionLabel(source, version) {
|
|
6576
|
+
if (source === "npm") return {
|
|
6577
|
+
kind: "npm",
|
|
6578
|
+
text: /^\d/.test(version) ? `v${version}` : version,
|
|
6579
|
+
value: version
|
|
6580
|
+
};
|
|
6581
|
+
if (COMMIT_PIN.test(version)) {
|
|
6582
|
+
const short = version.slice(0, 7);
|
|
6583
|
+
return {
|
|
6584
|
+
kind: "commit",
|
|
6585
|
+
text: short,
|
|
6586
|
+
value: short
|
|
6587
|
+
};
|
|
6588
|
+
}
|
|
6589
|
+
return {
|
|
6590
|
+
kind: "release",
|
|
6591
|
+
text: version,
|
|
6592
|
+
value: version
|
|
6593
|
+
};
|
|
6594
|
+
}
|
|
6595
|
+
/** The copy that names a version's kind, for the accessible name and the
|
|
6596
|
+
* tooltip; its `{version}` takes {@link VersionLabel.value}. */
|
|
6597
|
+
function versionLabelKey(kind) {
|
|
6598
|
+
switch (kind) {
|
|
6599
|
+
case "npm": return "npmVersionLabel";
|
|
6600
|
+
case "commit": return "commitVersionLabel";
|
|
6601
|
+
case "release": return "releaseVersionLabel";
|
|
6602
|
+
}
|
|
6552
6603
|
}
|
|
6553
6604
|
/** The hash pin a stale line names for a repo or release-rescued entry — the
|
|
6554
6605
|
* reviewed commit, or the reviewed release tarball sha256 (market borrowings
|
|
6555
|
-
* §3.1). Shortened to 7 chars like the card
|
|
6556
|
-
* hand-built fixture carrying no pin. The npm form is a version
|
|
6557
|
-
*
|
|
6606
|
+
* §3.1). Shortened to 7 chars like a commit on the card; '' only for a
|
|
6607
|
+
* hand-built fixture carrying no pin. The npm form is a version, which
|
|
6608
|
+
* {@link versionLabel} prints instead. */
|
|
6558
6609
|
function reviewHashPin(review) {
|
|
6559
6610
|
return (review.reviewedCommit ?? review.reviewedSha256 ?? "").slice(0, 7);
|
|
6560
6611
|
}
|
|
@@ -6679,6 +6730,24 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
6679
6730
|
}
|
|
6680
6731
|
}
|
|
6681
6732
|
}
|
|
6733
|
+
/**
|
|
6734
|
+
* Which order the shelf is in (design 2026-10-12-shelf-orders). `stars` is
|
|
6735
|
+
* the default AND the tie-break of both date orders, so the two date orders
|
|
6736
|
+
* are stable re-sorts of it rather than orders with comparators of their own.
|
|
6737
|
+
*/
|
|
6738
|
+
const SHELF_ORDER_KEYS = {
|
|
6739
|
+
stars: "sortStars",
|
|
6740
|
+
added: "sortAdded",
|
|
6741
|
+
updated: "sortUpdated"
|
|
6742
|
+
};
|
|
6743
|
+
/** The three orders in display order (map insertion order). `readonly`: this
|
|
6744
|
+
* is a shared vocabulary, and an order list a caller can push to is a bug
|
|
6745
|
+
* waiting for its second caller. */
|
|
6746
|
+
const SHELF_ORDERS = Object.keys(SHELF_ORDER_KEYS);
|
|
6747
|
+
/** The locale key naming one order (the toggle's buttons). */
|
|
6748
|
+
function shelfOrderLocaleKey(order) {
|
|
6749
|
+
return SHELF_ORDER_KEYS[order];
|
|
6750
|
+
}
|
|
6682
6751
|
const CATEGORY_KEYS = {
|
|
6683
6752
|
tool: "categoryTool",
|
|
6684
6753
|
provider: "categoryProvider",
|
|
@@ -6825,6 +6894,77 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
6825
6894
|
return NAME_COLLATOR.compare(a.name, b.name);
|
|
6826
6895
|
});
|
|
6827
6896
|
}
|
|
6897
|
+
/** The day form the registry writes into `added` (`emit.ts` E9 enforces it
|
|
6898
|
+
* on every build on its side; a catalog is untrusted input on this side). */
|
|
6899
|
+
const DAY_FORM = /^\d{4}-\d{2}-\d{2}$/;
|
|
6900
|
+
/**
|
|
6901
|
+
* The ES date-time form WITH an explicit zone. The zone is required, and not
|
|
6902
|
+
* for tidiness: a date-time string with no zone is parsed as LOCAL time, so
|
|
6903
|
+
* accepting one would make the shelf's order depend on the machine.
|
|
6904
|
+
*/
|
|
6905
|
+
const INSTANT_FORM = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{3})?(?:Z|[+-]\d{2}:\d{2})$/;
|
|
6906
|
+
/**
|
|
6907
|
+
* One date string as milliseconds, or undefined when it cannot be trusted.
|
|
6908
|
+
*
|
|
6909
|
+
* The form is checked BEFORE `Date.parse`, and that order is load-bearing:
|
|
6910
|
+
* V8 answers a real instant for `2026-02-31T00:00:00Z` (3 March) and for
|
|
6911
|
+
* `October 12` (a 2001 date), so `Date.parse` alone is not a validity test.
|
|
6912
|
+
*/
|
|
6913
|
+
function parseForm(value, form) {
|
|
6914
|
+
if (typeof value !== "string" || !form.test(value)) return void 0;
|
|
6915
|
+
const ms = Date.parse(value);
|
|
6916
|
+
return Number.isNaN(ms) ? void 0 : ms;
|
|
6917
|
+
}
|
|
6918
|
+
/** `shelfTime` with the catalog's build time already parsed, for the n calls
|
|
6919
|
+
* `orderShelf` makes in one pass. */
|
|
6920
|
+
function timeOf(entry, order, built) {
|
|
6921
|
+
if (order === "stars") return void 0;
|
|
6922
|
+
const ms = order === "added" ? parseForm(entry.added, DAY_FORM) : parseForm(entry.publishedAt, INSTANT_FORM);
|
|
6923
|
+
if (ms === void 0 || built === void 0 || ms > built) return void 0;
|
|
6924
|
+
return ms;
|
|
6925
|
+
}
|
|
6926
|
+
/**
|
|
6927
|
+
* The entry's sort key under a date order, or undefined when it has no usable
|
|
6928
|
+
* date (design §3): absent, off-form, unparseable, or later than the catalog's
|
|
6929
|
+
* own `builtAt`. Milliseconds since the epoch. `'stars'` carries no date, so
|
|
6930
|
+
* this answers undefined for it.
|
|
6931
|
+
*/
|
|
6932
|
+
function shelfTime(entry, order, builtAt) {
|
|
6933
|
+
return timeOf(entry, order, parseForm(builtAt, INSTANT_FORM));
|
|
6934
|
+
}
|
|
6935
|
+
/**
|
|
6936
|
+
* A UTC calendar day for display: "2026-10-12". Derived from the instant the
|
|
6937
|
+
* sort ranked by, so a card's label and its position cannot disagree. UTC and
|
|
6938
|
+
* never a local getter: a reader in UTC+8 must see the same days the catalog
|
|
6939
|
+
* was built in, the calendar the stats row already prints.
|
|
6940
|
+
*/
|
|
6941
|
+
function utcDay(ms) {
|
|
6942
|
+
return new Date(ms).toISOString().slice(0, 10);
|
|
6943
|
+
}
|
|
6944
|
+
/**
|
|
6945
|
+
* The shelf in `order` (design 2026-10-12-shelf-orders §2, §5). `'stars'`
|
|
6946
|
+
* returns the array it was handed, so the default path allocates nothing and
|
|
6947
|
+
* does not invalidate the memos downstream of it.
|
|
6948
|
+
*
|
|
6949
|
+
* Each key is computed ONCE per entry rather than inside the comparator, and
|
|
6950
|
+
* the sort is stable (ES2019), so entries sharing a date keep the star order
|
|
6951
|
+
* they arrived in — which is how the tie-break is defined without a second
|
|
6952
|
+
* comparator that could drift from `sortByStars`.
|
|
6953
|
+
*/
|
|
6954
|
+
function orderShelf(starOrdered, order, builtAt) {
|
|
6955
|
+
if (order === "stars") return starOrdered;
|
|
6956
|
+
const built = parseForm(builtAt, INSTANT_FORM);
|
|
6957
|
+
const keyed = starOrdered.map((entry) => ({
|
|
6958
|
+
entry,
|
|
6959
|
+
time: timeOf(entry, order, built)
|
|
6960
|
+
}));
|
|
6961
|
+
keyed.sort((a, b) => {
|
|
6962
|
+
if (a.time === void 0) return b.time === void 0 ? 0 : 1;
|
|
6963
|
+
if (b.time === void 0) return -1;
|
|
6964
|
+
return b.time - a.time;
|
|
6965
|
+
});
|
|
6966
|
+
return keyed.map((item) => item.entry);
|
|
6967
|
+
}
|
|
6828
6968
|
/** 999 → "999"; 1000 → "1k"; 1234 → "1.2k"; 1500 → "1.5k"; 99999 → "100k". */
|
|
6829
6969
|
function formatStars(n) {
|
|
6830
6970
|
if (n < 1e3) return String(n);
|
|
@@ -6897,6 +7037,14 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
6897
7037
|
all: "全部",
|
|
6898
7038
|
catalog: "插件目录",
|
|
6899
7039
|
catalogStats: "{count} 个插件 · 构建于 {date}",
|
|
7040
|
+
/** The shelf's order control, and the date each card carries under the two
|
|
7041
|
+
* date orders (design 2026-10-12-shelf-orders §4). */
|
|
7042
|
+
sortLabel: "排序",
|
|
7043
|
+
sortStars: "星标",
|
|
7044
|
+
sortAdded: "最新上架",
|
|
7045
|
+
sortUpdated: "最近更新",
|
|
7046
|
+
listedOn: "上架 {date}",
|
|
7047
|
+
updatedOn: "更新 {date}",
|
|
6900
7048
|
stars: "{count} 星",
|
|
6901
7049
|
categoryTool: "工具",
|
|
6902
7050
|
categoryProvider: "模型服务",
|
|
@@ -6981,7 +7129,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
6981
7129
|
emptyIncompatibleFiltered: "匹配的插件都标为不兼容,已被「隐藏不兼容」筛掉。",
|
|
6982
7130
|
license: "许可",
|
|
6983
7131
|
customLicense: "自定义许可",
|
|
6984
|
-
reviewedVersionLine: "已审核
|
|
7132
|
+
reviewedVersionLine: "已审核 {reviewed} / 当前 {current} 未审核",
|
|
6985
7133
|
reviewedPinLine: "已审核 {pin} / 当前 {current} 未审核",
|
|
6986
7134
|
deniedCode: "已拒绝",
|
|
6987
7135
|
notInCatalogCode: "不在目录中",
|
|
@@ -6995,6 +7143,13 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
6995
7143
|
nameTakenDetail: "已安装同名的另一个插件({holder})。\n两个同名插件声明相同的加载项 id,无法共存;安装它会替换掉已装的那个。",
|
|
6996
7144
|
npmSource: "npm 包",
|
|
6997
7145
|
githubSource: "源码在 GitHub",
|
|
7146
|
+
/** The accessible name and the tooltip of a card's version, which say which
|
|
7147
|
+
* of three things the printed string is (market borrowings §11): the string
|
|
7148
|
+
* alone cannot tell a release tag from a version number, and a short commit
|
|
7149
|
+
* printed with a `v` read as one. */
|
|
7150
|
+
npmVersionLabel: "npm 版本 {version}",
|
|
7151
|
+
commitVersionLabel: "GitHub 提交 {version}",
|
|
7152
|
+
releaseVersionLabel: "GitHub 发布 {version}",
|
|
6998
7153
|
/** The badge and the explanation for an installed github entry no catalog
|
|
6999
7154
|
* row claims (C10 MVP). The mechanism synthesizes a row for ANY github spec
|
|
7000
7155
|
* with no catalog row — shadowed by a same-named npm package, an unlisted
|
|
@@ -7004,8 +7159,10 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
7004
7159
|
shadowedBadge: "目录未列出此包",
|
|
7005
7160
|
shadowedDetail: "此包已安装,但当前的插件目录没有它(可能是被同名 npm 包遮蔽、作者已下架、或目录尚未收录);它照常运行。",
|
|
7006
7161
|
updatableSection: "可更新",
|
|
7007
|
-
|
|
7008
|
-
|
|
7162
|
+
/** `{version}` is the shelf's own version text (`versionLabel`), which
|
|
7163
|
+
* carries the `v` an npm version takes and no other kind does. */
|
|
7164
|
+
installedVersion: "已安装 {version}",
|
|
7165
|
+
latestVersion: "最新 {version}",
|
|
7009
7166
|
update: "更新",
|
|
7010
7167
|
installed: "已安装",
|
|
7011
7168
|
uninstall: "卸载",
|
|
@@ -7061,6 +7218,14 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
7061
7218
|
all: "All",
|
|
7062
7219
|
catalog: "Plugin catalog",
|
|
7063
7220
|
catalogStats: "{count} packages · built {date}",
|
|
7221
|
+
/** The shelf's order control, and the date each card carries under the two
|
|
7222
|
+
* date orders (design 2026-10-12-shelf-orders §4). */
|
|
7223
|
+
sortLabel: "Sort",
|
|
7224
|
+
sortStars: "Stars",
|
|
7225
|
+
sortAdded: "Newest",
|
|
7226
|
+
sortUpdated: "Recently updated",
|
|
7227
|
+
listedOn: "Listed {date}",
|
|
7228
|
+
updatedOn: "Updated {date}",
|
|
7064
7229
|
stars: "{count} stars",
|
|
7065
7230
|
categoryTool: "Tool",
|
|
7066
7231
|
categoryProvider: "Provider",
|
|
@@ -7121,7 +7286,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
7121
7286
|
emptyIncompatibleFiltered: "Every matching plugin is marked incompatible, and the incompatible filter is leaving them out.",
|
|
7122
7287
|
license: "License",
|
|
7123
7288
|
customLicense: "Custom license",
|
|
7124
|
-
reviewedVersionLine: "reviewed
|
|
7289
|
+
reviewedVersionLine: "reviewed {reviewed} / current {current} unreviewed",
|
|
7125
7290
|
reviewedPinLine: "reviewed {pin} / current {current} unreviewed",
|
|
7126
7291
|
deniedCode: "Denied",
|
|
7127
7292
|
notInCatalogCode: "Not in the catalog",
|
|
@@ -7135,11 +7300,14 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
7135
7300
|
nameTakenDetail: "A different plugin of this name is installed ({holder}).\nTwo plugins of one name declare the same loader entry id and cannot both load; installing this one would replace it.",
|
|
7136
7301
|
npmSource: "npm package",
|
|
7137
7302
|
githubSource: "source on GitHub",
|
|
7303
|
+
npmVersionLabel: "npm version {version}",
|
|
7304
|
+
commitVersionLabel: "GitHub commit {version}",
|
|
7305
|
+
releaseVersionLabel: "GitHub release {version}",
|
|
7138
7306
|
shadowedBadge: "Not in the current catalog",
|
|
7139
7307
|
shadowedDetail: "This package is installed but the current catalog does not list it (it may be shadowed by a same-named npm package, removed by the author, or never listed); it runs as before.",
|
|
7140
7308
|
updatableSection: "Updatable",
|
|
7141
|
-
installedVersion: "installed
|
|
7142
|
-
latestVersion: "latest
|
|
7309
|
+
installedVersion: "installed {version}",
|
|
7310
|
+
latestVersion: "latest {version}",
|
|
7143
7311
|
update: "Update",
|
|
7144
7312
|
installed: "Installed",
|
|
7145
7313
|
uninstall: "Uninstall",
|
|
@@ -9047,124 +9215,127 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
9047
9215
|
};
|
|
9048
9216
|
}
|
|
9049
9217
|
//#endregion
|
|
9050
|
-
//#region \0dsh-plugin-shop-css:
|
|
9051
|
-
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/* Subdued line under the search box when a dictionary intent fired (design\n * 2026-10-08-search-query-expansion §4). One fact, no badge. */\n.s76fb13_expansionNote {\n margin: 4px 0 0;\n font-size: 12px;\n color: var(--dsw-alias-label-secondary);\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 * And it is a SWITCH, which is the difference the shape now carries. It used\n * to wear `.s26d58e_categoryButton`: same pill, same row, same size as the eight tabs,\n * differing only in being red. That reads as a ninth tab, and it is not one —\n * the tabs are choose-one and this is on-or-off. So it drops the pill chrome\n * entirely (no border, no fill, nothing to compete with the row it sits\n * beside) and puts the state in a track, the same one every installed card\n * carries. Nothing here restates the switch geometry; `--switch-hue` is the\n * whole of what this control says about it, and it reaches the label too, so\n * one declaration keeps the word and the track the same colour. */\n.sfd887b_incompatibleFilter {\n --switch-hue: var(--dsw-alias-state-error-primary);\n margin-left: auto;\n display: inline-flex;\n align-items: center;\n gap: 6px;\n /* Matches the pills' vertical padding so the bar keeps one line box whether\n * this control wraps onto a row of its own or shares theirs. */\n padding: 3px 0;\n border: 0;\n background: none;\n color: var(--dsw-alias-label-secondary);\n font-size: 12px;\n cursor: pointer;\n}\n\n/* Hover lifts the word to full contrast and warms the track's border. Scoped\n * to the OFF track: `.sfd887b_incompatibleFilter:hover .s11c019_switch` outranks `.s7580e8_switchOn`\n * by two classes, so unscoped it would strip the hue from the border at\n * exactly the moment a reader has the pointer on it to check the state. */\n.sfd887b_incompatibleFilter:hover {\n color: var(--dsw-alias-label-primary);\n}\n\n.sfd887b_incompatibleFilter:hover .s11c019_switch:not(.s7580e8_switchOn) {\n border-color: color-mix(in srgb, var(--switch-hue) 45%, var(--dsw-alias-border-l2));\n}\n\n/* On. Written with both classes for the reason `.s26d58e_categoryButton.s5f68c4_categoryButtonOn`\n * is: it has to match `:hover`'s specificity and come after it, or the colour\n * reverts under a pointer that has not moved since the click. */\n.sfd887b_incompatibleFilter.s6e4cba_incompatibleFilterOn {\n color: color-mix(in srgb, var(--switch-hue) 45%, var(--dsw-alias-label-primary) 55%);\n}\n\n/* Off here means \"nothing is being taken away\" — the resting state — so the\n * knob steps back to the secondary label. The enable switch keeps the full\n * strength dot, where off means \"this plugin is disabled\" and is worth\n * noticing. In this bar it would be the heaviest mark in a row of hairline\n * pills, and on the light theme it is the WHOLE control: bg-layer-2 is the\n * same white as the panel there, so an off track is a hairline outline with a\n * near-black dot sitting in it. */\n.sfd887b_incompatibleFilter .s11c019_switch:not(.s7580e8_switchOn) .saab2b3_switchKnob {\n background: var(--dsw-alias-label-secondary);\n}\n\n/* The ring has no border to trace, so it takes an offset and the pill radius\n * of the tabs it sits beside rather than hugging the text. */\n.sfd887b_incompatibleFilter:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary);\n outline-offset: 2px;\n border-radius: 999px;\n}\n\n.sebf017_updatableHeading {\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. Named\n * `catalogRefresh*` (not `reload*`) so it cannot collide with the §4 page\n * reload offer below, which reloads the whole tab rather than refetching\n * the catalog data. */\n.sff243d_catalogRefreshButton {\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.sff243d_catalogRefreshButton: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.sff243d_catalogRefreshButton:disabled {\n cursor: default;\n opacity: 0.6;\n}\n\n.sff243d_catalogRefreshButton:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary);\n outline-offset: 1px;\n}\n\n.s194168_catalogRefreshFailed {\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/* The §C10 shadowed badge: an installed github entry the catalog refuses\n * shadowed-by-npm. Subdued/secondary rather than a warn tint — nothing is\n * wrong with the install itself; the shelf just cannot show it. */\n.s5e82cb_tierBadge[data-tier='shadowed'] {\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/* The §C5 archived badge: a github repository the owner has frozen.\n * Subdued register, same as shadowed — nothing is wrong with the install;\n * the pinned commit still serves, so the mark is informational only. */\n.s5e82cb_tierBadge[data-tier='archived'] {\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/* The way out of dsh's own refusal: the lead-in, then the exemption command\n * on its own line. */\n.s3d0044_remedy {\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.sdf203f_remedyLead {\n margin: 0;\n font-size: 12px;\n line-height: 1.5;\n color: var(--dsw-alias-label-primary);\n}\n\n/* The exemption command, bound for a terminal unchanged: one click selects\n * all of it, and it wraps anywhere rather than widening the card. A border,\n * not a fill, marks the box: the bg layers are one white in the light theme. */\n.sc32335_allowCommand {\n display: block;\n padding: 6px 8px;\n border-radius: 6px;\n background: var(--dsw-alias-bg-base);\n border: 1px solid var(--dsw-alias-border-l1);\n font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;\n font-size: 11px;\n line-height: 1.5;\n white-space: pre-wrap;\n word-break: break-all;\n user-select: all;\n color: var(--dsw-alias-label-primary);\n}\n\n/* A refused install on a surface that does not state its blockers — the\n * outdated row — writes them out on their own full-width line under the\n * disabled button, the command that clears dsh's refusal included. */\n.sc74941_refusal {\n display: flex;\n flex-direction: column;\n gap: 6px;\n flex-basis: 100%;\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 packument that named no account has no author, and an entry the registry\n * could not measure honestly has no size. Rarer than it was (every live entry\n * now carries a size, github included), but the wrapper is not what makes it\n * rare: without one, an EMPTY meta group still costs 8px, because\n * `.s9b5048_cardActions` is a flex row with `gap: 8px` and a zero-width item is still\n * an item. 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 on-disk 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/* The two activation offers share one recipe: a border in an alias token,\n * never a `bg-layer` fill alone — all four bg-layer tokens collapse to the\n * same white under `body` in the light theme, and a fill-only button would\n * vanish there. Grouped rather than copied, because a copy is a rule that\n * can be corrected on one button and left wrong on the other, silently. */\n.s6ac237_restartButton,\n.s64a5ff_reloadButton {\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.s64a5ff_reloadButton:hover {\n border-color: var(--dsw-alias-label-secondary);\n}\n\n.s6ac237_restartButton:focus-visible,\n.s64a5ff_reloadButton:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary);\n outline-offset: 1px;\n}\n\n/* The §4 reload offer: a notice plus its button, one item of\n * `.sf53ca0_installedActions` the way the restart gate is — a column of its own\n * rather than inline with the row. */\n.sf79aef_reloadPanel {\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n gap: 6px;\n}\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/* The Updatable section. The class keeps the Host's field name; only the\n heading the reader sees was renamed. */\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/* The §C10 shadowed section. Reuses the outdated list's visual language; only\n * the section spacing and the per-row explanation paragraph are its own. */\n.s6c4649_shadowedSection {\n display: flex;\n flex-direction: column;\n gap: 8px;\n margin-top: 6px;\n}\n\n.scc2a21_shadowedDetail {\n margin: 4px 0 0;\n font-size: 12px;\n line-height: 1.5;\n color: var(--dsw-alias-label-secondary);\n}\n\n.sa1f556_outdatedActions {\n display: flex;\n align-items: center;\n /* The reload offer (§4) mounts inside the switch beside the Update button\n * and is a two-line block, not a control: without wrapping, a row reading\n * [switch][notice + Reload][Update] overflows the settings dialog. */\n flex-wrap: wrap;\n gap: 10px;\n}\n\n/* The shop's one switch. It is worn by two controls that mean different\n * things — the enable/disable toggle on an installed card, and the shelf's\n * incompatible filter — so the geometry lives here once and each caller states\n * only its hue.\n *\n * `--switch-hue` is that knob, and it is read from the ANCESTOR rather than\n * declared per state: `.sfd887b_incompatibleFilter` sets it once and it reaches the\n * track and the label together, which is what keeps a red switch from sitting\n * under a neutral word. A declaration on `.s11c019_switch` itself would shadow the\n * inherited value (an element's own rule beats what it inherits), so the\n * default rides in the `var()` fallback and is resolved once into\n * `--track-hue` instead of being spelled out at each use.\n *\n * `box-sizing` and `padding` are stated because the two callers are different\n * elements — a `<button>`, which the UA gives padding, and a `<span>`, which\n * it does not. Without them the same class renders two sizes, and the knob\n * sits 2px above centre in the taller one. */\n.s11c019_switch {\n --track-hue: var(--switch-hue, var(--dsw-alias-state-success-primary));\n box-sizing: border-box;\n display: inline-block;\n position: relative;\n width: 32px;\n height: 18px;\n padding: 0;\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/* The knob's POSITION is the state, which is the reason this control needs no\n * `forced-colors` fallback the way the category pills do: a system palette\n * replaces every colour below and moves nothing. */\n.s7580e8_switchOn {\n border-color: var(--track-hue);\n background: color-mix(in srgb, var(--track-hue) 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 /* Same reason as `.sa1f556_outdatedActions`: `.sf79aef_reloadPanel`'s own comment calls\n * itself \"a column of its own rather than inline with the row\", which held\n * for `.sf53ca0_installedActions` and not here until this line. */\n flex-wrap: wrap;\n gap: 8px;\n}\n";
|
|
9052
|
-
if (typeof document !== "undefined" && !document.querySelector("style[data-plugin-css=\"
|
|
9218
|
+
//#region \0dsh-plugin-shop-css:d74581c2
|
|
9219
|
+
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.s73a3ff_client.s45aee2_config.s8a51a7_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.s73a3ff_client.s117e2f_spec.s8a51a7_ts` pins this. */\n\n.sa2d7b5_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 `.s7c10d7_searchInput` sits at\n * exactly (0, 0) of this box — it is the first child of `.sbee2c3_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.sa89499_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.s90f53b_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.sd5b66e_skeletonGrid {\n display: grid;\n grid-template-columns: 1fr;\n gap: 8px;\n}\n\n.sfb41cd_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.sfb41cd_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.sc9bc63_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.s75708b_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.s772f28_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.s6ce39d_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.sfb41cd_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 .sfb41cd_skeletonCard span { animation: none; opacity: 0.75; }\n .sfb41cd_skeletonCard::after { content: none; }\n}\n\n.s1547e4_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.s1547e4_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.s1547e4_actionButton:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary);\n outline-offset: 1px;\n}\n\n.sbee2c3_toolbar {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 12px;\n flex-wrap: wrap;\n}\n\n.sfb98ad_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.s15df74_versionBlock {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.s9d78e5_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.scb0503_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.scb0503_updateSelfButton:hover {\n background: color-mix(in srgb, var(--dsw-alias-brand-primary) 20%, transparent);\n}\n\n.scb0503_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.seab5ae_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.seab5ae_checkUpdateButton:hover {\n border-color: var(--dsw-alias-label-secondary);\n color: var(--dsw-alias-label-primary);\n}\n\n.seab5ae_checkUpdateButton:disabled {\n opacity: 0.6;\n cursor: default;\n}\n\n.seab5ae_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.s6932e1_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.s6932e1_githubLink:hover {\n color: var(--dsw-alias-label-primary);\n background: var(--dsw-alias-bg-layer-2);\n}\n\n.s6932e1_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.sb1e444_selfUpdatePanel {\n display: flex;\n flex-direction: column;\n gap: 8px;\n margin-top: 8px;\n}\n\n.s7c10d7_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.s7c10d7_searchInput:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary);\n outline-offset: 1px;\n}\n\n/* Subdued line under the search box when a dictionary intent fired (design\n * 2026-10-08-search-query-expansion §4). One fact, no badge. */\n.s1dee54_expansionNote {\n margin: 4px 0 0;\n font-size: 12px;\n color: var(--dsw-alias-label-secondary);\n}\n\n.s5823b0_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.s52084f_categoryBar {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 6px;\n margin-top: 6px;\n}\n\n.sd07f01_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.sd07f01_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 `.sd07f01_categoryButton.s7d231e_categoryButtonOn` — TWO classes — so it\n * matches `.sd07f01_categoryButton:hover`'s specificity and, coming after it, wins.\n * As a bare `.s7d231e_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.s73a3ff_client.s117e2f_spec.s8a51a7_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.sd07f01_categoryButton.s7d231e_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 .sd07f01_categoryButton.s7d231e_categoryButtonOn {\n outline: 2px solid ButtonText;\n outline-offset: -4px;\n }\n}\n\n.sd07f01_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 * And it is a SWITCH, which is the difference the shape now carries. It used\n * to wear `.sd07f01_categoryButton`: same pill, same row, same size as the eight tabs,\n * differing only in being red. That reads as a ninth tab, and it is not one —\n * the tabs are choose-one and this is on-or-off. So it drops the pill chrome\n * entirely (no border, no fill, nothing to compete with the row it sits\n * beside) and puts the state in a track, the same one every installed card\n * carries. Nothing here restates the switch geometry; `--switch-hue` is the\n * whole of what this control says about it, and it reaches the label too, so\n * one declaration keeps the word and the track the same colour. */\n.s7abba7_incompatibleFilter {\n --switch-hue: var(--dsw-alias-state-error-primary);\n margin-left: auto;\n display: inline-flex;\n align-items: center;\n gap: 6px;\n /* Matches the pills' vertical padding so the bar keeps one line box whether\n * this control wraps onto a row of its own or shares theirs. */\n padding: 3px 0;\n border: 0;\n background: none;\n color: var(--dsw-alias-label-secondary);\n font-size: 12px;\n cursor: pointer;\n}\n\n/* Hover lifts the word to full contrast and warms the track's border. Scoped\n * to the OFF track: `.s7abba7_incompatibleFilter:hover .sa4bed2_switch` outranks `.s97d8ec_switchOn`\n * by two classes, so unscoped it would strip the hue from the border at\n * exactly the moment a reader has the pointer on it to check the state. */\n.s7abba7_incompatibleFilter:hover {\n color: var(--dsw-alias-label-primary);\n}\n\n.s7abba7_incompatibleFilter:hover .sa4bed2_switch:not(.s97d8ec_switchOn) {\n border-color: color-mix(in srgb, var(--switch-hue) 45%, var(--dsw-alias-border-l2));\n}\n\n/* On. Written with both classes for the reason `.sd07f01_categoryButton.s7d231e_categoryButtonOn`\n * is: it has to match `:hover`'s specificity and come after it, or the colour\n * reverts under a pointer that has not moved since the click. */\n.s7abba7_incompatibleFilter.sa24b4e_incompatibleFilterOn {\n color: color-mix(in srgb, var(--switch-hue) 45%, var(--dsw-alias-label-primary) 55%);\n}\n\n/* Off here means \"nothing is being taken away\" — the resting state — so the\n * knob steps back to the secondary label. The enable switch keeps the full\n * strength dot, where off means \"this plugin is disabled\" and is worth\n * noticing. In this bar it would be the heaviest mark in a row of hairline\n * pills, and on the light theme it is the WHOLE control: bg-layer-2 is the\n * same white as the panel there, so an off track is a hairline outline with a\n * near-black dot sitting in it. */\n.s7abba7_incompatibleFilter .sa4bed2_switch:not(.s97d8ec_switchOn) .s24e1f5_switchKnob {\n background: var(--dsw-alias-label-secondary);\n}\n\n/* The ring has no border to trace, so it takes an offset and the pill radius\n * of the tabs it sits beside rather than hugging the text. */\n.s7abba7_incompatibleFilter:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary);\n outline-offset: 2px;\n border-radius: 999px;\n}\n\n.s3ffb2a_updatableHeading {\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.sfd3ed8_catalogStatsRow {\n display: flex;\n align-items: center;\n /* The row holds the catalog line, the refresh button and the shelf order's\n * three pills (design 2026-10-12-shelf-orders §4). Without wrapping, the\n * last of them overflows the tab at a narrow width. */\n flex-wrap: wrap;\n gap: 10px;\n margin: 6px 0 0;\n}\n\n/* The shelf's order control, at the right end of the stats row. `margin-left:\n * auto` is what puts it there while the line and the refresh button stay\n * left — and it is safe on a wrapping row, unlike a width. */\n.sc5a073_sortGroup {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n margin-left: auto;\n}\n\n.s275eb9_sortLabel {\n color: var(--dsw-alias-label-secondary);\n font-size: 12px;\n}\n\n.s3c7a5d_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 `.s1547e4_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. Named\n * `catalogRefresh*` (not `reload*`) so it cannot collide with the §4 page\n * reload offer below, which reloads the whole tab rather than refetching\n * the catalog data. */\n.s6d141d_catalogRefreshButton {\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.s6d141d_catalogRefreshButton: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.s6d141d_catalogRefreshButton:disabled {\n cursor: default;\n opacity: 0.6;\n}\n\n.s6d141d_catalogRefreshButton:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary);\n outline-offset: 1px;\n}\n\n.s8b8ed4_catalogRefreshFailed {\n font-size: 11px;\n color: var(--dsw-alias-state-warn-primary);\n}\n\n.s918b21_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.sf66d65_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 .sf66d65_cards { animation: none; }\n}\n\n.sa6c0bf_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.s21cef7_cardsSentry {\n height: 1px;\n margin: 0;\n padding: 0;\n}\n\n.s9babb8_showingLine {\n margin: 0;\n font-size: 12px;\n letter-spacing: 0.02em;\n color: var(--dsw-alias-label-secondary);\n}\n\n.sa6c0bf_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 .sa6c0bf_card { transition: none; }\n .sa6c0bf_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.sce2063_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. `.sd07f01_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.sa6c0bf_card[data-category='tool'], .sd07f01_categoryButton[data-category='tool'] { --category-hue: #4C8DFF; }\n.sa6c0bf_card[data-category='provider'], .sd07f01_categoryButton[data-category='provider'] { --category-hue: #A78BFA; }\n.sa6c0bf_card[data-category='ui'], .sd07f01_categoryButton[data-category='ui'] { --category-hue: #2DD4BF; }\n.sa6c0bf_card[data-category='workflow'], .sd07f01_categoryButton[data-category='workflow'] { --category-hue: #F59E0B; }\n.sa6c0bf_card[data-category='integration'], .sd07f01_categoryButton[data-category='integration'] { --category-hue: #34D399; }\n.sa6c0bf_card[data-category='theme'], .sd07f01_categoryButton[data-category='theme'] { --category-hue: #F472B6; }\n.sa6c0bf_card[data-category='other'], .sd07f01_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.sdc7cd8_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.s6ae6ba_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.s6ae6ba_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.saf3e98_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.s93d243_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.s763b75_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.s763b75_cardActions > .sff1df6_gate,\n.s763b75_cardActions > .s6d7bee_installPanel,\n.s763b75_cardActions > .s10ddb2_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.s9d1d9e_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 /* A release tag prints as tagged, never cut to seven characters (market\n * borrowings §11), and a tag can run to any length. The cap keeps every\n * tag of up to fourteen characters whole, prerelease suffix included\n * (`v0.1.0-alpha.0`): fourteen glyphs plus the letter-spacing above come to\n * about 14.5ch, so the cap is 15ch, not 14. A longer tag ends in an ellipsis,\n * and the tooltip carries the whole of it. */\n max-width: 15ch;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n/* The octocat marking a source the reader can read on GitHub, beside the\n * card's version. */\n.sad456f_sourceBadge {\n display: inline-flex;\n align-items: center;\n color: var(--dsw-alias-label-secondary);\n}\n\n.s7f352e_tierBadge {\n padding: 1px 7px;\n border-radius: 999px;\n font-size: 11px;\n line-height: 1.6;\n}\n\n.s7f352e_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.s7f352e_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.s7f352e_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/* The §C10 shadowed badge: an installed github entry the catalog refuses\n * shadowed-by-npm. Subdued/secondary rather than a warn tint — nothing is\n * wrong with the install itself; the shelf just cannot show it. */\n.s7f352e_tierBadge[data-tier='shadowed'] {\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/* The §C5 archived badge: a github repository the owner has frozen.\n * Subdued register, same as shadowed — nothing is wrong with the install;\n * the pinned commit still serves, so the mark is informational only. */\n.s7f352e_tierBadge[data-tier='archived'] {\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.s649a66_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.se83753_starsBadge {\n font-size: 11px;\n color: var(--dsw-alias-label-secondary);\n}\n\n.sc7129d_chevron, .s3e170e_chevronOpen {\n color: var(--dsw-alias-label-secondary);\n transition: transform 120ms ease;\n}\n\n.s3e170e_chevronOpen { transform: rotate(180deg); }\n\n@media (prefers-reduced-motion: reduce) {\n .sc7129d_chevron, .s3e170e_chevronOpen { transition: none; }\n}\n\n.s249e15_body {\n display: flex;\n flex-direction: column;\n gap: 8px;\n padding: 0 12px;\n}\n\n.sdd4d7a_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.s1a6809_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.sc924dd_summaryExpanded {\n -webkit-line-clamp: unset;\n display: block;\n}\n\n.sab7503_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.s4625f5_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/* The way out of dsh's own refusal: the lead-in, then the exemption command\n * on its own line. */\n.s632e71_remedy {\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.s360025_remedyLead {\n margin: 0;\n font-size: 12px;\n line-height: 1.5;\n color: var(--dsw-alias-label-primary);\n}\n\n/* The exemption command, bound for a terminal unchanged: one click selects\n * all of it, and it wraps anywhere rather than widening the card. A border,\n * not a fill, marks the box: the bg layers are one white in the light theme. */\n.s12ec11_allowCommand {\n display: block;\n padding: 6px 8px;\n border-radius: 6px;\n background: var(--dsw-alias-bg-base);\n border: 1px solid var(--dsw-alias-border-l1);\n font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;\n font-size: 11px;\n line-height: 1.5;\n white-space: pre-wrap;\n word-break: break-all;\n user-select: all;\n color: var(--dsw-alias-label-primary);\n}\n\n/* A refused install on a surface that does not state its blockers — the\n * outdated row — writes them out on their own full-width line under the\n * disabled button, the command that clears dsh's refusal included. */\n.sa92311_refusal {\n display: flex;\n flex-direction: column;\n gap: 6px;\n flex-basis: 100%;\n}\n\n.s99a4f5_capabilitiesBlock {\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.scf0a21_capabilitiesNote {\n margin: 0;\n font-size: 11px;\n color: var(--dsw-alias-label-secondary);\n}\n\n.sc760c8_capabilities {\n display: flex;\n flex-wrap: wrap;\n gap: 4px;\n list-style: none;\n margin: 0;\n padding: 0;\n}\n\n.sc760c8_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.s48edfc_detail {\n border-top: 1px solid var(--dsw-alias-border-l1);\n padding-top: 8px;\n}\n\n.sce5502_detailRows {\n display: flex;\n flex-direction: column;\n gap: 4px;\n margin: 0;\n}\n\n.scc4b2b_detailRow {\n display: flex;\n justify-content: space-between;\n gap: 12px;\n font-size: 12px;\n}\n\n.scc4b2b_detailRow dt {\n color: var(--dsw-alias-label-secondary);\n}\n\n.scc4b2b_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.scc4b2b_detailRow a {\n color: var(--dsw-alias-brand-primary);\n text-decoration: none;\n}\n\n.scc4b2b_detailRow a:hover {\n text-decoration: underline;\n}\n\n.scc4b2b_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 packument that named no account has no author, and an entry the registry\n * could not measure honestly has no size. Rarer than it was (every live entry\n * now carries a size, github included), but the wrapper is not what makes it\n * rare: without one, an EMPTY meta group still costs 8px, because\n * `.s763b75_cardActions` is a flex row with `gap: 8px` and a zero-width item is still\n * an item. 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.s8fb80a_cardMeta {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n margin-left: auto;\n min-width: 0;\n}\n\n/* The on-disk 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: `.s8fb80a_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 *\n * `.s72b045_shelfDate` shares this rule because it is the same kind of fact — a\n * fixed-width figure a reader compares down the shelf (design\n * 2026-10-12-shelf-orders §4) — and two copies of these declarations would\n * drift. */\n.s24611f_size,\n.s72b045_shelfDate {\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 `.s8fb80a_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 `.s8fb80a_cardMeta`. There is no middot:\n * `.s8fb80a_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.seefbaa_author {\n color: var(--dsw-alias-label-secondary);\n font-size: 12px;\n}\n\n.sa79085_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.s6d7bee_installPanel {\n display: flex;\n flex-direction: column;\n gap: 8px;\n margin-top: 2px;\n}\n\n.sdddc5f_installButton, .safd4a8_confirmButton, .sfcf768_cancelButton {\n align-self: flex-start;\n padding: 5px 14px;\n border-radius: 6px;\n font-size: 13px;\n cursor: pointer;\n}\n\n.sdddc5f_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.sdddc5f_installButton:hover {\n background: color-mix(in srgb, var(--dsw-alias-brand-primary) 88%, var(--dsw-alias-label-primary));\n}\n\n.safd4a8_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.safd4a8_confirmButton:hover {\n background: color-mix(in srgb, var(--dsw-alias-brand-primary) 88%, var(--dsw-alias-label-primary));\n}\n\n.sfcf768_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.sfcf768_cancelButton:hover {\n border-color: var(--dsw-alias-label-secondary);\n}\n\n.sdddc5f_installButton:focus-visible, .safd4a8_confirmButton:focus-visible, .sfcf768_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.s563674_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.s10ddb2_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.s767a97_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.s767a97_uninstallButton:hover {\n background: color-mix(in srgb, var(--dsw-alias-state-error-primary) 10%, transparent);\n}\n\n.s767a97_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.sa6b105_restartSelfButton {\n /* The version row's third state. Geometry matches .seab5ae_checkUpdateButton and\n * .scb0503_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.sa6b105_restartSelfButton:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary);\n outline-offset: 1px;\n}\n\n/* The two activation offers share one recipe: a border in an alias token,\n * never a `bg-layer` fill alone — all four bg-layer tokens collapse to the\n * same white under `body` in the light theme, and a fill-only button would\n * vanish there. Grouped rather than copied, because a copy is a rule that\n * can be corrected on one button and left wrong on the other, silently. */\n.s426aa0_restartButton,\n.sa283f9_reloadButton {\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.s426aa0_restartButton:hover,\n.sa283f9_reloadButton:hover {\n border-color: var(--dsw-alias-label-secondary);\n}\n\n.s426aa0_restartButton:focus-visible,\n.sa283f9_reloadButton:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary);\n outline-offset: 1px;\n}\n\n/* The §4 reload offer: a notice plus its button, one item of\n * `.s10ddb2_installedActions` the way the restart gate is — a column of its own\n * rather than inline with the row. */\n.sf20a99_reloadPanel {\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n gap: 6px;\n}\n\n\n.sff1df6_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.see0e3d_gateTitle {\n margin: 0;\n font-size: 13px;\n font-weight: 600;\n color: var(--dsw-alias-state-warn-primary);\n}\n\n.sd04ef9_gateBody {\n margin: 0;\n font-size: 12px;\n line-height: 1.6;\n color: var(--dsw-alias-label-primary);\n}\n\n.s7fd5d3_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.sf6b0aa_gateActions {\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n}\n\n.sa32b72_installing {\n margin: 0;\n font-size: 12px;\n color: var(--dsw-alias-label-secondary);\n}\n\n.sf9b6a4_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.s9e4d00_logLine {\n white-space: pre-wrap;\n word-break: break-all;\n color: var(--dsw-alias-label-secondary);\n}\n\n.s7cd7db_notice {\n margin: 0;\n font-size: 12px;\n color: var(--dsw-alias-state-success-primary);\n}\n\n.sfb1bae_failedHeading {\n margin: 0;\n font-size: 12px;\n font-weight: 600;\n color: var(--dsw-alias-state-error-primary);\n}\n\n.s9591b1_failedDetail {\n margin: 0;\n font-size: 12px;\n line-height: 1.6;\n color: var(--dsw-alias-label-primary);\n}\n\n.saa0605_rejectedCode {\n margin: 0;\n font-size: 12px;\n font-weight: 600;\n color: var(--dsw-alias-state-error-primary);\n}\n\n.sbd5c7c_rejectedDetail {\n margin: 0;\n font-size: 12px;\n line-height: 1.6;\n color: var(--dsw-alias-label-primary);\n}\n\n/* The Updatable section. The class keeps the Host's field name; only the\n heading the reader sees was renamed. */\n.s7c248d_outdatedSection {\n display: flex;\n flex-direction: column;\n gap: 8px;\n margin-top: 6px;\n}\n\n.se144d3_outdatedList {\n display: flex;\n flex-direction: column;\n gap: 8px;\n list-style: none;\n margin: 0;\n padding: 0;\n}\n\n.s6fbe58_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.s8af496_outdatedInfo {\n display: flex;\n flex-direction: column;\n gap: 2px;\n min-width: 0;\n}\n\n.s8af496_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.sf82d51_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 .s93d243_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/* The §C10 shadowed section. Reuses the outdated list's visual language; only\n * the section spacing and the per-row explanation paragraph are its own. */\n.s31b89a_shadowedSection {\n display: flex;\n flex-direction: column;\n gap: 8px;\n margin-top: 6px;\n}\n\n.scf838f_shadowedDetail {\n margin: 4px 0 0;\n font-size: 12px;\n line-height: 1.5;\n color: var(--dsw-alias-label-secondary);\n}\n\n.s109c95_outdatedActions {\n display: flex;\n align-items: center;\n /* The reload offer (§4) mounts inside the switch beside the Update button\n * and is a two-line block, not a control: without wrapping, a row reading\n * [switch][notice + Reload][Update] overflows the settings dialog. */\n flex-wrap: wrap;\n gap: 10px;\n}\n\n/* The shop's one switch. It is worn by two controls that mean different\n * things — the enable/disable toggle on an installed card, and the shelf's\n * incompatible filter — so the geometry lives here once and each caller states\n * only its hue.\n *\n * `--switch-hue` is that knob, and it is read from the ANCESTOR rather than\n * declared per state: `.s7abba7_incompatibleFilter` sets it once and it reaches the\n * track and the label together, which is what keeps a red switch from sitting\n * under a neutral word. A declaration on `.sa4bed2_switch` itself would shadow the\n * inherited value (an element's own rule beats what it inherits), so the\n * default rides in the `var()` fallback and is resolved once into\n * `--track-hue` instead of being spelled out at each use.\n *\n * `box-sizing` and `padding` are stated because the two callers are different\n * elements — a `<button>`, which the UA gives padding, and a `<span>`, which\n * it does not. Without them the same class renders two sizes, and the knob\n * sits 2px above centre in the taller one. */\n.sa4bed2_switch {\n --track-hue: var(--switch-hue, var(--dsw-alias-state-success-primary));\n box-sizing: border-box;\n display: inline-block;\n position: relative;\n width: 32px;\n height: 18px;\n padding: 0;\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/* The knob's POSITION is the state, which is the reason this control needs no\n * `forced-colors` fallback the way the category pills do: a system palette\n * replaces every colour below and moves nothing. */\n.s97d8ec_switchOn {\n border-color: var(--track-hue);\n background: color-mix(in srgb, var(--track-hue) 55%, transparent);\n}\n\n.s24e1f5_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.s97d8ec_switchOn .s24e1f5_switchKnob {\n transform: translateX(14px);\n background: var(--dsw-alias-bg-base);\n}\n\n.sa4bed2_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 .sa4bed2_switch, .s24e1f5_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.s5c21f4_switchWrap {\n display: inline-flex;\n align-items: center;\n /* Same reason as `.s109c95_outdatedActions`: `.sf20a99_reloadPanel`'s own comment calls\n * itself \"a column of its own rather than inline with the row\", which held\n * for `.s10ddb2_installedActions` and not here until this line. */\n flex-wrap: wrap;\n gap: 8px;\n}\n";
|
|
9220
|
+
if (typeof document !== "undefined" && !document.querySelector("style[data-plugin-css=\"d74581c2\"]")) {
|
|
9053
9221
|
const tag = document.createElement("style");
|
|
9054
|
-
tag.dataset.pluginCss = "
|
|
9222
|
+
tag.dataset.pluginCss = "d74581c2";
|
|
9055
9223
|
tag.textContent = css;
|
|
9056
9224
|
document.head.appendChild(tag);
|
|
9057
9225
|
}
|
|
9058
|
-
var
|
|
9059
|
-
"client": "
|
|
9060
|
-
"config": "
|
|
9061
|
-
"ts": "
|
|
9062
|
-
"spec": "
|
|
9063
|
-
"panel": "
|
|
9064
|
-
"searchInput": "
|
|
9065
|
-
"toolbar": "
|
|
9066
|
-
"stateLine": "
|
|
9067
|
-
"srOnly": "
|
|
9068
|
-
"skeletonGrid": "
|
|
9069
|
-
"skeletonCard": "
|
|
9070
|
-
"skeletonName": "
|
|
9071
|
-
"skeletonSummary": "
|
|
9072
|
-
"skeletonSummaryShort": "
|
|
9073
|
-
"skeletonActions": "
|
|
9074
|
-
"actionButton": "
|
|
9075
|
-
"toolbarRight": "
|
|
9076
|
-
"versionBlock": "
|
|
9077
|
-
"versionText": "
|
|
9078
|
-
"updateSelfButton": "
|
|
9079
|
-
"checkUpdateButton": "
|
|
9080
|
-
"githubLink": "
|
|
9081
|
-
"selfUpdatePanel": "
|
|
9082
|
-
"expansionNote": "
|
|
9083
|
-
"staleBadge": "
|
|
9084
|
-
"categoryBar": "
|
|
9085
|
-
"categoryButton": "
|
|
9086
|
-
"categoryButtonOn": "
|
|
9087
|
-
"incompatibleFilter": "
|
|
9088
|
-
"switch": "
|
|
9089
|
-
"switchOn": "
|
|
9090
|
-
"incompatibleFilterOn": "
|
|
9091
|
-
"switchKnob": "
|
|
9092
|
-
"updatableHeading": "
|
|
9093
|
-
"catalogStatsRow": "
|
|
9094
|
-
"
|
|
9095
|
-
"
|
|
9096
|
-
"
|
|
9097
|
-
"
|
|
9098
|
-
"
|
|
9099
|
-
"
|
|
9100
|
-
"
|
|
9101
|
-
"
|
|
9102
|
-
"
|
|
9103
|
-
"
|
|
9104
|
-
"
|
|
9105
|
-
"
|
|
9106
|
-
"
|
|
9107
|
-
"
|
|
9108
|
-
"
|
|
9109
|
-
"
|
|
9110
|
-
"
|
|
9111
|
-
"
|
|
9112
|
-
"
|
|
9113
|
-
"
|
|
9114
|
-
"
|
|
9115
|
-
"
|
|
9116
|
-
"
|
|
9117
|
-
"
|
|
9118
|
-
"
|
|
9119
|
-
"
|
|
9120
|
-
"
|
|
9121
|
-
"
|
|
9122
|
-
"
|
|
9123
|
-
"
|
|
9124
|
-
"
|
|
9125
|
-
"
|
|
9126
|
-
"
|
|
9127
|
-
"
|
|
9128
|
-
"
|
|
9129
|
-
"
|
|
9130
|
-
"
|
|
9131
|
-
"
|
|
9132
|
-
"
|
|
9133
|
-
"
|
|
9134
|
-
"
|
|
9135
|
-
"
|
|
9136
|
-
"
|
|
9137
|
-
"
|
|
9138
|
-
"
|
|
9139
|
-
"
|
|
9140
|
-
"
|
|
9141
|
-
"
|
|
9142
|
-
"
|
|
9143
|
-
"
|
|
9144
|
-
"
|
|
9145
|
-
"
|
|
9146
|
-
"
|
|
9147
|
-
"
|
|
9148
|
-
"
|
|
9149
|
-
"
|
|
9150
|
-
"
|
|
9151
|
-
"
|
|
9152
|
-
"
|
|
9153
|
-
"
|
|
9154
|
-
"
|
|
9155
|
-
"
|
|
9156
|
-
"
|
|
9157
|
-
"
|
|
9158
|
-
"
|
|
9159
|
-
"
|
|
9160
|
-
"
|
|
9161
|
-
"
|
|
9162
|
-
"
|
|
9163
|
-
"
|
|
9164
|
-
"
|
|
9165
|
-
"
|
|
9166
|
-
"
|
|
9167
|
-
"
|
|
9226
|
+
var _dsh_plugin_shop_css_d74581c2_default = {
|
|
9227
|
+
"client": "s73a3ff_client",
|
|
9228
|
+
"config": "s45aee2_config",
|
|
9229
|
+
"ts": "s8a51a7_ts",
|
|
9230
|
+
"spec": "s117e2f_spec",
|
|
9231
|
+
"panel": "sa2d7b5_panel",
|
|
9232
|
+
"searchInput": "s7c10d7_searchInput",
|
|
9233
|
+
"toolbar": "sbee2c3_toolbar",
|
|
9234
|
+
"stateLine": "sa89499_stateLine",
|
|
9235
|
+
"srOnly": "s90f53b_srOnly",
|
|
9236
|
+
"skeletonGrid": "sd5b66e_skeletonGrid",
|
|
9237
|
+
"skeletonCard": "sfb41cd_skeletonCard",
|
|
9238
|
+
"skeletonName": "sc9bc63_skeletonName",
|
|
9239
|
+
"skeletonSummary": "s75708b_skeletonSummary",
|
|
9240
|
+
"skeletonSummaryShort": "s772f28_skeletonSummaryShort",
|
|
9241
|
+
"skeletonActions": "s6ce39d_skeletonActions",
|
|
9242
|
+
"actionButton": "s1547e4_actionButton",
|
|
9243
|
+
"toolbarRight": "sfb98ad_toolbarRight",
|
|
9244
|
+
"versionBlock": "s15df74_versionBlock",
|
|
9245
|
+
"versionText": "s9d78e5_versionText",
|
|
9246
|
+
"updateSelfButton": "scb0503_updateSelfButton",
|
|
9247
|
+
"checkUpdateButton": "seab5ae_checkUpdateButton",
|
|
9248
|
+
"githubLink": "s6932e1_githubLink",
|
|
9249
|
+
"selfUpdatePanel": "sb1e444_selfUpdatePanel",
|
|
9250
|
+
"expansionNote": "s1dee54_expansionNote",
|
|
9251
|
+
"staleBadge": "s5823b0_staleBadge",
|
|
9252
|
+
"categoryBar": "s52084f_categoryBar",
|
|
9253
|
+
"categoryButton": "sd07f01_categoryButton",
|
|
9254
|
+
"categoryButtonOn": "s7d231e_categoryButtonOn",
|
|
9255
|
+
"incompatibleFilter": "s7abba7_incompatibleFilter",
|
|
9256
|
+
"switch": "sa4bed2_switch",
|
|
9257
|
+
"switchOn": "s97d8ec_switchOn",
|
|
9258
|
+
"incompatibleFilterOn": "sa24b4e_incompatibleFilterOn",
|
|
9259
|
+
"switchKnob": "s24e1f5_switchKnob",
|
|
9260
|
+
"updatableHeading": "s3ffb2a_updatableHeading",
|
|
9261
|
+
"catalogStatsRow": "sfd3ed8_catalogStatsRow",
|
|
9262
|
+
"sortGroup": "sc5a073_sortGroup",
|
|
9263
|
+
"sortLabel": "s275eb9_sortLabel",
|
|
9264
|
+
"catalogStats": "s3c7a5d_catalogStats",
|
|
9265
|
+
"catalogRefreshButton": "s6d141d_catalogRefreshButton",
|
|
9266
|
+
"catalogRefreshFailed": "s8b8ed4_catalogRefreshFailed",
|
|
9267
|
+
"emptyLine": "s918b21_emptyLine",
|
|
9268
|
+
"cards": "sf66d65_cards",
|
|
9269
|
+
"card": "sa6c0bf_card",
|
|
9270
|
+
"cardsSentry": "s21cef7_cardsSentry",
|
|
9271
|
+
"showingLine": "s9babb8_showingLine",
|
|
9272
|
+
"cardSpine": "sce2063_cardSpine",
|
|
9273
|
+
"categoryBadge": "sdc7cd8_categoryBadge",
|
|
9274
|
+
"entryHeader": "s6ae6ba_entryHeader",
|
|
9275
|
+
"name": "saf3e98_name",
|
|
9276
|
+
"badges": "s93d243_badges",
|
|
9277
|
+
"cardActions": "s763b75_cardActions",
|
|
9278
|
+
"gate": "sff1df6_gate",
|
|
9279
|
+
"installPanel": "s6d7bee_installPanel",
|
|
9280
|
+
"installedActions": "s10ddb2_installedActions",
|
|
9281
|
+
"cardVersion": "s9d1d9e_cardVersion",
|
|
9282
|
+
"sourceBadge": "sad456f_sourceBadge",
|
|
9283
|
+
"tierBadge": "s7f352e_tierBadge",
|
|
9284
|
+
"incompatibleBadge": "s649a66_incompatibleBadge",
|
|
9285
|
+
"starsBadge": "se83753_starsBadge",
|
|
9286
|
+
"chevron": "sc7129d_chevron",
|
|
9287
|
+
"chevronOpen": "s3e170e_chevronOpen",
|
|
9288
|
+
"body": "s249e15_body",
|
|
9289
|
+
"summary": "sdd4d7a_summary",
|
|
9290
|
+
"summaryZh": "s1a6809_summaryZh",
|
|
9291
|
+
"summaryExpanded": "sc924dd_summaryExpanded",
|
|
9292
|
+
"summaryZhExpanded": "sab7503_summaryZhExpanded",
|
|
9293
|
+
"incompatibleDetail": "s4625f5_incompatibleDetail",
|
|
9294
|
+
"remedy": "s632e71_remedy",
|
|
9295
|
+
"remedyLead": "s360025_remedyLead",
|
|
9296
|
+
"allowCommand": "s12ec11_allowCommand",
|
|
9297
|
+
"refusal": "sa92311_refusal",
|
|
9298
|
+
"capabilitiesBlock": "s99a4f5_capabilitiesBlock",
|
|
9299
|
+
"capabilitiesNote": "scf0a21_capabilitiesNote",
|
|
9300
|
+
"capabilities": "sc760c8_capabilities",
|
|
9301
|
+
"detail": "s48edfc_detail",
|
|
9302
|
+
"detailRows": "sce5502_detailRows",
|
|
9303
|
+
"detailRow": "scc4b2b_detailRow",
|
|
9304
|
+
"cardMeta": "s8fb80a_cardMeta",
|
|
9305
|
+
"shelfDate": "s72b045_shelfDate",
|
|
9306
|
+
"size": "s24611f_size",
|
|
9307
|
+
"author": "seefbaa_author",
|
|
9308
|
+
"reviewedLine": "sa79085_reviewedLine",
|
|
9309
|
+
"installButton": "sdddc5f_installButton",
|
|
9310
|
+
"confirmButton": "safd4a8_confirmButton",
|
|
9311
|
+
"cancelButton": "sfcf768_cancelButton",
|
|
9312
|
+
"installedLabel": "s563674_installedLabel",
|
|
9313
|
+
"uninstallButton": "s767a97_uninstallButton",
|
|
9314
|
+
"restartSelfButton": "sa6b105_restartSelfButton",
|
|
9315
|
+
"restartButton": "s426aa0_restartButton",
|
|
9316
|
+
"reloadButton": "sa283f9_reloadButton",
|
|
9317
|
+
"reloadPanel": "sf20a99_reloadPanel",
|
|
9318
|
+
"gateTitle": "see0e3d_gateTitle",
|
|
9319
|
+
"gateBody": "sd04ef9_gateBody",
|
|
9320
|
+
"gateWarning": "s7fd5d3_gateWarning",
|
|
9321
|
+
"gateActions": "sf6b0aa_gateActions",
|
|
9322
|
+
"installing": "sa32b72_installing",
|
|
9323
|
+
"log": "sf9b6a4_log",
|
|
9324
|
+
"logLine": "s9e4d00_logLine",
|
|
9325
|
+
"notice": "s7cd7db_notice",
|
|
9326
|
+
"failedHeading": "sfb1bae_failedHeading",
|
|
9327
|
+
"failedDetail": "s9591b1_failedDetail",
|
|
9328
|
+
"rejectedCode": "saa0605_rejectedCode",
|
|
9329
|
+
"rejectedDetail": "sbd5c7c_rejectedDetail",
|
|
9330
|
+
"outdatedSection": "s7c248d_outdatedSection",
|
|
9331
|
+
"outdatedList": "se144d3_outdatedList",
|
|
9332
|
+
"outdatedRow": "s6fbe58_outdatedRow",
|
|
9333
|
+
"outdatedInfo": "s8af496_outdatedInfo",
|
|
9334
|
+
"outdatedVersions": "sf82d51_outdatedVersions",
|
|
9335
|
+
"shadowedSection": "s31b89a_shadowedSection",
|
|
9336
|
+
"shadowedDetail": "scf838f_shadowedDetail",
|
|
9337
|
+
"outdatedActions": "s109c95_outdatedActions",
|
|
9338
|
+
"switchWrap": "s5c21f4_switchWrap"
|
|
9168
9339
|
};
|
|
9169
9340
|
//#endregion
|
|
9170
9341
|
//#region src/client/ShopTab.tsx
|
|
@@ -9181,14 +9352,14 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
9181
9352
|
* those nodes, and React's next commit throws on the ones it no longer finds
|
|
9182
9353
|
* (design 2026-09-26-market-borrowings §4). The tab renders no portals, so its
|
|
9183
9354
|
* root is its whole surface. */
|
|
9184
|
-
const PANEL_ROOT = `${
|
|
9355
|
+
const PANEL_ROOT = `${_dsh_plugin_shop_css_d74581c2_default.panel} notranslate`;
|
|
9185
9356
|
function ChevronIcon({ open }) {
|
|
9186
9357
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
|
|
9187
9358
|
viewBox: "0 0 16 16",
|
|
9188
9359
|
width: "14",
|
|
9189
9360
|
height: "14",
|
|
9190
9361
|
"aria-hidden": "true",
|
|
9191
|
-
className: open ?
|
|
9362
|
+
className: open ? _dsh_plugin_shop_css_d74581c2_default.chevronOpen : _dsh_plugin_shop_css_d74581c2_default.chevron,
|
|
9192
9363
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
|
|
9193
9364
|
fill: "currentColor",
|
|
9194
9365
|
d: "M3.5 6 8 10.5 12.5 6l1 1L8 12.5 2.5 7l1-1Z"
|
|
@@ -9201,7 +9372,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
9201
9372
|
* install controls. An installed plugin's card carries its installed row:
|
|
9202
9373
|
* current → the non-interactive installed label, behind → the update button;
|
|
9203
9374
|
* uninstalled → the install button. */
|
|
9204
|
-
const EntryCard = (0, react.memo)(function EntryCard({ entry, stars, installed, missing, harness, nameTakenBy, t, flow, uninstallFlow, restart, restartBlocked, reload, setEnabled, inInstalledView, restarts }) {
|
|
9375
|
+
const EntryCard = (0, react.memo)(function EntryCard({ entry, stars, order, shelfDay, installed, missing, harness, nameTakenBy, t, flow, uninstallFlow, restart, restartBlocked, reload, setEnabled, inInstalledView, restarts }) {
|
|
9205
9376
|
const [open, setOpen] = (0, react.useState)(false);
|
|
9206
9377
|
const blockers = stateBlockers(blockersOf(missing, harness, nameTakenBy), t);
|
|
9207
9378
|
const detailId = (0, react.useId)();
|
|
@@ -9209,6 +9380,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
9209
9380
|
const npmUrl = npmPageUrl(entry);
|
|
9210
9381
|
const author = authorOf(entry);
|
|
9211
9382
|
const size = formatSize(entry.installSize);
|
|
9383
|
+
const version = versionLabel(entry.source, entry.version);
|
|
9384
|
+
const versionName = t(versionLabelKey(version.kind), { version: version.value });
|
|
9212
9385
|
const category = entry.catalog?.category ?? "other";
|
|
9213
9386
|
const installTarget = {
|
|
9214
9387
|
name: entry.name,
|
|
@@ -9218,32 +9391,32 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
9218
9391
|
subdir: entry.subdir
|
|
9219
9392
|
};
|
|
9220
9393
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
9221
|
-
className:
|
|
9394
|
+
className: _dsh_plugin_shop_css_d74581c2_default.card,
|
|
9222
9395
|
"data-shop-entry": entry.name,
|
|
9223
9396
|
"data-category": category,
|
|
9224
9397
|
children: [
|
|
9225
9398
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
9226
|
-
className:
|
|
9399
|
+
className: _dsh_plugin_shop_css_d74581c2_default.cardSpine,
|
|
9227
9400
|
"aria-hidden": "true"
|
|
9228
9401
|
}),
|
|
9229
9402
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
9230
9403
|
type: "button",
|
|
9231
|
-
className:
|
|
9404
|
+
className: _dsh_plugin_shop_css_d74581c2_default.entryHeader,
|
|
9232
9405
|
"aria-expanded": open,
|
|
9233
9406
|
"aria-controls": detailId,
|
|
9234
9407
|
onClick: () => setOpen((current) => !current),
|
|
9235
9408
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
9236
|
-
className:
|
|
9409
|
+
className: _dsh_plugin_shop_css_d74581c2_default.name,
|
|
9237
9410
|
children: entry.name
|
|
9238
9411
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
9239
|
-
className:
|
|
9412
|
+
className: _dsh_plugin_shop_css_d74581c2_default.badges,
|
|
9240
9413
|
children: [
|
|
9241
9414
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
9242
|
-
className:
|
|
9415
|
+
className: _dsh_plugin_shop_css_d74581c2_default.categoryBadge,
|
|
9243
9416
|
children: t(categoryKey(entry))
|
|
9244
9417
|
}),
|
|
9245
9418
|
entry.source === "npm" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
9246
|
-
className:
|
|
9419
|
+
className: _dsh_plugin_shop_css_d74581c2_default.sourceBadge,
|
|
9247
9420
|
"data-shop-source-npm": true,
|
|
9248
9421
|
role: "img",
|
|
9249
9422
|
"aria-label": t("npmSource"),
|
|
@@ -9260,7 +9433,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
9260
9433
|
})
|
|
9261
9434
|
}),
|
|
9262
9435
|
hasGithubHome(entry) && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
9263
|
-
className:
|
|
9436
|
+
className: _dsh_plugin_shop_css_d74581c2_default.sourceBadge,
|
|
9264
9437
|
"data-shop-source-github": true,
|
|
9265
9438
|
role: "img",
|
|
9266
9439
|
"aria-label": t("githubSource"),
|
|
@@ -9273,23 +9446,26 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
9273
9446
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", { d: "M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27s1.36.09 2 .27c1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.01 8.01 0 0 0 16 8c0-4.42-3.58-8-8-8Z" })
|
|
9274
9447
|
})
|
|
9275
9448
|
}),
|
|
9276
|
-
/* @__PURE__ */ (0, react_jsx_runtime.
|
|
9277
|
-
className:
|
|
9449
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
9450
|
+
className: _dsh_plugin_shop_css_d74581c2_default.cardVersion,
|
|
9278
9451
|
"data-card-version": true,
|
|
9279
|
-
|
|
9452
|
+
role: "img",
|
|
9453
|
+
"aria-label": versionName,
|
|
9454
|
+
title: versionName,
|
|
9455
|
+
children: version.text
|
|
9280
9456
|
}),
|
|
9281
9457
|
entry.tier !== "community" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
9282
|
-
className:
|
|
9458
|
+
className: _dsh_plugin_shop_css_d74581c2_default.tierBadge,
|
|
9283
9459
|
"data-tier": entry.tier,
|
|
9284
9460
|
children: t(tierKey(entry.tier))
|
|
9285
9461
|
}),
|
|
9286
9462
|
entry.archived === true && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
9287
|
-
className:
|
|
9463
|
+
className: _dsh_plugin_shop_css_d74581c2_default.tierBadge,
|
|
9288
9464
|
"data-tier": "archived",
|
|
9289
9465
|
children: t("archivedBadge")
|
|
9290
9466
|
}),
|
|
9291
9467
|
stars !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
9292
|
-
className:
|
|
9468
|
+
className: _dsh_plugin_shop_css_d74581c2_default.starsBadge,
|
|
9293
9469
|
role: "img",
|
|
9294
9470
|
"aria-label": t("stars", { count: stars }),
|
|
9295
9471
|
children: ["★ ", formatStars(stars)]
|
|
@@ -9299,39 +9475,39 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
9299
9475
|
})]
|
|
9300
9476
|
}),
|
|
9301
9477
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
9302
|
-
className:
|
|
9478
|
+
className: _dsh_plugin_shop_css_d74581c2_default.body,
|
|
9303
9479
|
children: [
|
|
9304
9480
|
summary !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
9305
|
-
className: open ? `${
|
|
9481
|
+
className: open ? `${_dsh_plugin_shop_css_d74581c2_default.summary} ${_dsh_plugin_shop_css_d74581c2_default.summaryExpanded}` : _dsh_plugin_shop_css_d74581c2_default.summary,
|
|
9306
9482
|
children: summary.en
|
|
9307
9483
|
}),
|
|
9308
9484
|
summary?.zh !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
9309
|
-
className: open ? `${
|
|
9485
|
+
className: open ? `${_dsh_plugin_shop_css_d74581c2_default.summaryZh} ${_dsh_plugin_shop_css_d74581c2_default.summaryZhExpanded}` : _dsh_plugin_shop_css_d74581c2_default.summaryZh,
|
|
9310
9486
|
children: summary.zh
|
|
9311
9487
|
}),
|
|
9312
9488
|
blockers.map((blocker) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(BlockerLine, {
|
|
9313
9489
|
blocker,
|
|
9314
|
-
className:
|
|
9490
|
+
className: _dsh_plugin_shop_css_d74581c2_default.incompatibleDetail,
|
|
9315
9491
|
surface: "detail"
|
|
9316
9492
|
}, blocker.kind)),
|
|
9317
9493
|
open && entry.catalog !== void 0 && entry.catalog.capabilities.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
9318
|
-
className:
|
|
9494
|
+
className: _dsh_plugin_shop_css_d74581c2_default.capabilitiesBlock,
|
|
9319
9495
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
9320
|
-
className:
|
|
9496
|
+
className: _dsh_plugin_shop_css_d74581c2_default.capabilitiesNote,
|
|
9321
9497
|
children: t("capabilitiesNote")
|
|
9322
9498
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("ul", {
|
|
9323
|
-
className:
|
|
9499
|
+
className: _dsh_plugin_shop_css_d74581c2_default.capabilities,
|
|
9324
9500
|
children: entry.catalog.capabilities.map((capability) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", { children: capability }, capability))
|
|
9325
9501
|
})]
|
|
9326
9502
|
}),
|
|
9327
9503
|
open && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
9328
9504
|
id: detailId,
|
|
9329
|
-
className:
|
|
9505
|
+
className: _dsh_plugin_shop_css_d74581c2_default.detail,
|
|
9330
9506
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("dl", {
|
|
9331
|
-
className:
|
|
9507
|
+
className: _dsh_plugin_shop_css_d74581c2_default.detailRows,
|
|
9332
9508
|
children: [
|
|
9333
9509
|
npmUrl !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
9334
|
-
className:
|
|
9510
|
+
className: _dsh_plugin_shop_css_d74581c2_default.detailRow,
|
|
9335
9511
|
"data-shop-npm": true,
|
|
9336
9512
|
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", {
|
|
9337
9513
|
href: npmUrl,
|
|
@@ -9341,7 +9517,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
9341
9517
|
}) })]
|
|
9342
9518
|
}),
|
|
9343
9519
|
entry.repository !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
9344
|
-
className:
|
|
9520
|
+
className: _dsh_plugin_shop_css_d74581c2_default.detailRow,
|
|
9345
9521
|
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", {
|
|
9346
9522
|
href: entry.repository,
|
|
9347
9523
|
target: "_blank",
|
|
@@ -9350,25 +9526,25 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
9350
9526
|
}) : entry.repository })]
|
|
9351
9527
|
}),
|
|
9352
9528
|
entry.license !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
9353
|
-
className:
|
|
9529
|
+
className: _dsh_plugin_shop_css_d74581c2_default.detailRow,
|
|
9354
9530
|
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 })]
|
|
9355
9531
|
})
|
|
9356
9532
|
]
|
|
9357
9533
|
}), entry.tier === "verified-stale" && entry.review !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
9358
|
-
className:
|
|
9534
|
+
className: _dsh_plugin_shop_css_d74581c2_default.reviewedLine,
|
|
9359
9535
|
children: entry.review.reviewedVersion !== void 0 ? t("reviewedVersionLine", {
|
|
9360
|
-
reviewed: entry.review.reviewedVersion,
|
|
9361
|
-
current:
|
|
9536
|
+
reviewed: versionLabel("npm", entry.review.reviewedVersion).text,
|
|
9537
|
+
current: version.text
|
|
9362
9538
|
}) : t("reviewedPinLine", {
|
|
9363
9539
|
pin: reviewHashPin(entry.review),
|
|
9364
|
-
current:
|
|
9540
|
+
current: version.text
|
|
9365
9541
|
})
|
|
9366
9542
|
})]
|
|
9367
9543
|
})
|
|
9368
9544
|
]
|
|
9369
9545
|
}),
|
|
9370
9546
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
9371
|
-
className:
|
|
9547
|
+
className: _dsh_plugin_shop_css_d74581c2_default.cardActions,
|
|
9372
9548
|
"data-shop-actions": true,
|
|
9373
9549
|
children: [installed === void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [!inInstalledView && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(InstallPanel, {
|
|
9374
9550
|
target: installTarget,
|
|
@@ -9400,7 +9576,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
9400
9576
|
restartBlocked,
|
|
9401
9577
|
reload
|
|
9402
9578
|
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
9403
|
-
className:
|
|
9579
|
+
className: _dsh_plugin_shop_css_d74581c2_default.installedLabel,
|
|
9404
9580
|
"data-shop-installed": true,
|
|
9405
9581
|
children: t("installed")
|
|
9406
9582
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(BlockerBadge, {
|
|
@@ -9424,20 +9600,28 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
9424
9600
|
reload,
|
|
9425
9601
|
flow: uninstallFlow
|
|
9426
9602
|
})
|
|
9427
|
-
] }), (size !== void 0 || author !== null) && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
9428
|
-
className:
|
|
9429
|
-
children: [
|
|
9430
|
-
|
|
9431
|
-
|
|
9432
|
-
|
|
9433
|
-
|
|
9434
|
-
|
|
9435
|
-
|
|
9436
|
-
|
|
9437
|
-
|
|
9438
|
-
|
|
9439
|
-
|
|
9440
|
-
|
|
9603
|
+
] }), (size !== void 0 || author !== null || shelfDay !== void 0) && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
9604
|
+
className: _dsh_plugin_shop_css_d74581c2_default.cardMeta,
|
|
9605
|
+
children: [
|
|
9606
|
+
shelfDay !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
9607
|
+
className: _dsh_plugin_shop_css_d74581c2_default.shelfDate,
|
|
9608
|
+
"data-shop-shelf-date": true,
|
|
9609
|
+
children: t(order === "added" ? "listedOn" : "updatedOn", { date: shelfDay })
|
|
9610
|
+
}),
|
|
9611
|
+
size !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
9612
|
+
className: _dsh_plugin_shop_css_d74581c2_default.size,
|
|
9613
|
+
"data-shop-size": true,
|
|
9614
|
+
role: "img",
|
|
9615
|
+
"aria-label": t("sizeLabel", { size }),
|
|
9616
|
+
title: t("sizeLabel", { size }),
|
|
9617
|
+
children: size
|
|
9618
|
+
}),
|
|
9619
|
+
author !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
9620
|
+
className: _dsh_plugin_shop_css_d74581c2_default.author,
|
|
9621
|
+
"data-shop-author": true,
|
|
9622
|
+
children: t("authorLine", { author })
|
|
9623
|
+
})
|
|
9624
|
+
]
|
|
9441
9625
|
})]
|
|
9442
9626
|
})
|
|
9443
9627
|
]
|
|
@@ -9483,13 +9667,13 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
9483
9667
|
...attribute,
|
|
9484
9668
|
children: blocker.text
|
|
9485
9669
|
}), blocker.remedy !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
9486
|
-
className:
|
|
9670
|
+
className: _dsh_plugin_shop_css_d74581c2_default.remedy,
|
|
9487
9671
|
"data-shop-remedy": blocker.kind,
|
|
9488
9672
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
9489
|
-
className:
|
|
9673
|
+
className: _dsh_plugin_shop_css_d74581c2_default.remedyLead,
|
|
9490
9674
|
children: blocker.remedy.lead
|
|
9491
9675
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("code", {
|
|
9492
|
-
className:
|
|
9676
|
+
className: _dsh_plugin_shop_css_d74581c2_default.allowCommand,
|
|
9493
9677
|
"data-shop-allow-command": true,
|
|
9494
9678
|
children: blocker.remedy.command
|
|
9495
9679
|
})]
|
|
@@ -9527,7 +9711,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
9527
9711
|
if (lead === void 0 || word === null) return null;
|
|
9528
9712
|
const detail = blockers.map((blocker) => blocker.text).join("\n");
|
|
9529
9713
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
9530
|
-
className:
|
|
9714
|
+
className: _dsh_plugin_shop_css_d74581c2_default.incompatibleBadge,
|
|
9531
9715
|
"data-shop-blocker": lead.kind,
|
|
9532
9716
|
role: "img",
|
|
9533
9717
|
"aria-label": detail,
|
|
@@ -9544,37 +9728,37 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
9544
9728
|
const [gateOpen, setGateOpen] = (0, react.useState)(false);
|
|
9545
9729
|
const { view, start } = flow;
|
|
9546
9730
|
if (view.kind === "running") return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
9547
|
-
className:
|
|
9731
|
+
className: _dsh_plugin_shop_css_d74581c2_default.installPanel,
|
|
9548
9732
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
9549
|
-
className:
|
|
9733
|
+
className: _dsh_plugin_shop_css_d74581c2_default.installing,
|
|
9550
9734
|
children: t(installPhaseKey(view.phase))
|
|
9551
9735
|
}), view.log.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
9552
|
-
className:
|
|
9736
|
+
className: _dsh_plugin_shop_css_d74581c2_default.log,
|
|
9553
9737
|
children: view.log.map((line, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
9554
|
-
className:
|
|
9738
|
+
className: _dsh_plugin_shop_css_d74581c2_default.logLine,
|
|
9555
9739
|
"data-shop-log-line": true,
|
|
9556
9740
|
children: line
|
|
9557
9741
|
}, index))
|
|
9558
9742
|
})]
|
|
9559
9743
|
});
|
|
9560
9744
|
if (view.kind === "done") return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
9561
|
-
className:
|
|
9745
|
+
className: _dsh_plugin_shop_css_d74581c2_default.installedActions,
|
|
9562
9746
|
children: [
|
|
9563
9747
|
view.log.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
9564
|
-
className:
|
|
9748
|
+
className: _dsh_plugin_shop_css_d74581c2_default.log,
|
|
9565
9749
|
children: view.log.map((line, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
9566
|
-
className:
|
|
9750
|
+
className: _dsh_plugin_shop_css_d74581c2_default.logLine,
|
|
9567
9751
|
"data-shop-log-line": true,
|
|
9568
9752
|
children: line
|
|
9569
9753
|
}, index))
|
|
9570
9754
|
}),
|
|
9571
9755
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
9572
|
-
className:
|
|
9756
|
+
className: _dsh_plugin_shop_css_d74581c2_default.notice,
|
|
9573
9757
|
"data-shop-restart-notice": true,
|
|
9574
9758
|
children: t(activationNoticeKey(view.activation, view.restartReason))
|
|
9575
9759
|
}),
|
|
9576
9760
|
view.detail !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
9577
|
-
className:
|
|
9761
|
+
className: _dsh_plugin_shop_css_d74581c2_default.notice,
|
|
9578
9762
|
"data-shop-done-note": true,
|
|
9579
9763
|
children: view.detail
|
|
9580
9764
|
}),
|
|
@@ -9589,57 +9773,57 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
9589
9773
|
]
|
|
9590
9774
|
});
|
|
9591
9775
|
if (view.kind === "failed") return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
9592
|
-
className:
|
|
9776
|
+
className: _dsh_plugin_shop_css_d74581c2_default.installPanel,
|
|
9593
9777
|
children: [
|
|
9594
9778
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
9595
|
-
className:
|
|
9779
|
+
className: _dsh_plugin_shop_css_d74581c2_default.failedHeading,
|
|
9596
9780
|
children: t("installFailed")
|
|
9597
9781
|
}),
|
|
9598
9782
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
9599
|
-
className:
|
|
9783
|
+
className: _dsh_plugin_shop_css_d74581c2_default.log,
|
|
9600
9784
|
children: view.log.map((line, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
9601
|
-
className:
|
|
9785
|
+
className: _dsh_plugin_shop_css_d74581c2_default.logLine,
|
|
9602
9786
|
"data-shop-log-line": true,
|
|
9603
9787
|
children: line
|
|
9604
9788
|
}, index))
|
|
9605
9789
|
}),
|
|
9606
9790
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
9607
|
-
className:
|
|
9791
|
+
className: _dsh_plugin_shop_css_d74581c2_default.failedDetail,
|
|
9608
9792
|
children: view.detail === "" ? t("installTransportFailed") : view.detail
|
|
9609
9793
|
})
|
|
9610
9794
|
]
|
|
9611
9795
|
});
|
|
9612
9796
|
if (view.kind === "rejected") return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
9613
|
-
className:
|
|
9797
|
+
className: _dsh_plugin_shop_css_d74581c2_default.installPanel,
|
|
9614
9798
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
9615
|
-
className:
|
|
9799
|
+
className: _dsh_plugin_shop_css_d74581c2_default.rejectedCode,
|
|
9616
9800
|
children: t(rejectionCodeKey(view.code))
|
|
9617
9801
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
9618
|
-
className:
|
|
9802
|
+
className: _dsh_plugin_shop_css_d74581c2_default.rejectedDetail,
|
|
9619
9803
|
children: view.detail
|
|
9620
9804
|
})]
|
|
9621
9805
|
});
|
|
9622
9806
|
if (gateOpen) return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
9623
|
-
className:
|
|
9807
|
+
className: _dsh_plugin_shop_css_d74581c2_default.gate,
|
|
9624
9808
|
children: [
|
|
9625
9809
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
9626
|
-
className:
|
|
9810
|
+
className: _dsh_plugin_shop_css_d74581c2_default.gateTitle,
|
|
9627
9811
|
children: t("acknowledgementTitle")
|
|
9628
9812
|
}),
|
|
9629
9813
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
9630
|
-
className:
|
|
9814
|
+
className: _dsh_plugin_shop_css_d74581c2_default.gateBody,
|
|
9631
9815
|
children: t("acknowledgementBody")
|
|
9632
9816
|
}),
|
|
9633
9817
|
!blockersStated && blockers.map((blocker) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(BlockerLine, {
|
|
9634
9818
|
blocker,
|
|
9635
|
-
className:
|
|
9819
|
+
className: _dsh_plugin_shop_css_d74581c2_default.gateWarning,
|
|
9636
9820
|
surface: "warning"
|
|
9637
9821
|
}, blocker.kind)),
|
|
9638
9822
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
9639
|
-
className:
|
|
9823
|
+
className: _dsh_plugin_shop_css_d74581c2_default.gateActions,
|
|
9640
9824
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
9641
9825
|
type: "button",
|
|
9642
|
-
className:
|
|
9826
|
+
className: _dsh_plugin_shop_css_d74581c2_default.confirmButton,
|
|
9643
9827
|
"data-shop-confirm": true,
|
|
9644
9828
|
onClick: () => {
|
|
9645
9829
|
setGateOpen(false);
|
|
@@ -9651,7 +9835,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
9651
9835
|
children: t("confirm")
|
|
9652
9836
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
9653
9837
|
type: "button",
|
|
9654
|
-
className:
|
|
9838
|
+
className: _dsh_plugin_shop_css_d74581c2_default.cancelButton,
|
|
9655
9839
|
onClick: () => setGateOpen(false),
|
|
9656
9840
|
children: t("cancel")
|
|
9657
9841
|
})]
|
|
@@ -9663,7 +9847,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
9663
9847
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
9664
9848
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
9665
9849
|
type: "button",
|
|
9666
|
-
className:
|
|
9850
|
+
className: _dsh_plugin_shop_css_d74581c2_default.installButton,
|
|
9667
9851
|
disabled: refused,
|
|
9668
9852
|
...refused ? { "data-shop-refused": true } : {},
|
|
9669
9853
|
...update ? { "data-shop-update": true } : { "data-shop-install": true },
|
|
@@ -9681,11 +9865,11 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
9681
9865
|
t
|
|
9682
9866
|
}),
|
|
9683
9867
|
refused && !blockersStated && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
9684
|
-
className:
|
|
9868
|
+
className: _dsh_plugin_shop_css_d74581c2_default.refusal,
|
|
9685
9869
|
"data-shop-refusal": true,
|
|
9686
9870
|
children: blockers.map((blocker) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(BlockerLine, {
|
|
9687
9871
|
blocker,
|
|
9688
|
-
className:
|
|
9872
|
+
className: _dsh_plugin_shop_css_d74581c2_default.gateWarning,
|
|
9689
9873
|
surface: "warning"
|
|
9690
9874
|
}, blocker.kind))
|
|
9691
9875
|
})
|
|
@@ -9700,32 +9884,32 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
9700
9884
|
function UninstallPanel({ name, t, restart, restartBlocked, reload, flow }) {
|
|
9701
9885
|
const { view, start, reset } = flow;
|
|
9702
9886
|
if (view.kind === "running") return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
9703
|
-
className:
|
|
9887
|
+
className: _dsh_plugin_shop_css_d74581c2_default.installPanel,
|
|
9704
9888
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
9705
|
-
className:
|
|
9889
|
+
className: _dsh_plugin_shop_css_d74581c2_default.installing,
|
|
9706
9890
|
children: t("uninstalling")
|
|
9707
9891
|
}), view.log.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
9708
|
-
className:
|
|
9892
|
+
className: _dsh_plugin_shop_css_d74581c2_default.log,
|
|
9709
9893
|
children: view.log.map((line, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
9710
|
-
className:
|
|
9894
|
+
className: _dsh_plugin_shop_css_d74581c2_default.logLine,
|
|
9711
9895
|
"data-shop-log-line": true,
|
|
9712
9896
|
children: line
|
|
9713
9897
|
}, index))
|
|
9714
9898
|
})]
|
|
9715
9899
|
});
|
|
9716
9900
|
if (view.kind === "done") return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
9717
|
-
className:
|
|
9901
|
+
className: _dsh_plugin_shop_css_d74581c2_default.installedActions,
|
|
9718
9902
|
children: [
|
|
9719
9903
|
view.log.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
9720
|
-
className:
|
|
9904
|
+
className: _dsh_plugin_shop_css_d74581c2_default.log,
|
|
9721
9905
|
children: view.log.map((line, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
9722
|
-
className:
|
|
9906
|
+
className: _dsh_plugin_shop_css_d74581c2_default.logLine,
|
|
9723
9907
|
"data-shop-log-line": true,
|
|
9724
9908
|
children: line
|
|
9725
9909
|
}, index))
|
|
9726
9910
|
}),
|
|
9727
9911
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
9728
|
-
className:
|
|
9912
|
+
className: _dsh_plugin_shop_css_d74581c2_default.notice,
|
|
9729
9913
|
"data-shop-uninstall-done": true,
|
|
9730
9914
|
children: t(uninstallActivationNoticeKey(view.activation))
|
|
9731
9915
|
}),
|
|
@@ -9739,7 +9923,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
9739
9923
|
}),
|
|
9740
9924
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
9741
9925
|
type: "button",
|
|
9742
|
-
className:
|
|
9926
|
+
className: _dsh_plugin_shop_css_d74581c2_default.cancelButton,
|
|
9743
9927
|
"data-shop-uninstall-dismiss": true,
|
|
9744
9928
|
onClick: reset,
|
|
9745
9929
|
children: t("dismiss")
|
|
@@ -9747,27 +9931,27 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
9747
9931
|
]
|
|
9748
9932
|
});
|
|
9749
9933
|
if (view.kind === "failed") return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
9750
|
-
className:
|
|
9934
|
+
className: _dsh_plugin_shop_css_d74581c2_default.installPanel,
|
|
9751
9935
|
children: [
|
|
9752
9936
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
9753
|
-
className:
|
|
9937
|
+
className: _dsh_plugin_shop_css_d74581c2_default.failedHeading,
|
|
9754
9938
|
children: t("uninstallFailed")
|
|
9755
9939
|
}),
|
|
9756
9940
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
9757
|
-
className:
|
|
9941
|
+
className: _dsh_plugin_shop_css_d74581c2_default.log,
|
|
9758
9942
|
children: view.log.map((line, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
9759
|
-
className:
|
|
9943
|
+
className: _dsh_plugin_shop_css_d74581c2_default.logLine,
|
|
9760
9944
|
"data-shop-log-line": true,
|
|
9761
9945
|
children: line
|
|
9762
9946
|
}, index))
|
|
9763
9947
|
}),
|
|
9764
9948
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
9765
|
-
className:
|
|
9949
|
+
className: _dsh_plugin_shop_css_d74581c2_default.failedDetail,
|
|
9766
9950
|
children: view.detail === "" ? t("uninstallTransportFailed") : view.detail
|
|
9767
9951
|
}),
|
|
9768
9952
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
9769
9953
|
type: "button",
|
|
9770
|
-
className:
|
|
9954
|
+
className: _dsh_plugin_shop_css_d74581c2_default.uninstallButton,
|
|
9771
9955
|
"data-shop-uninstall-retry": true,
|
|
9772
9956
|
onClick: () => void start({ name }),
|
|
9773
9957
|
children: t("retry")
|
|
@@ -9777,7 +9961,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
9777
9961
|
if (view.kind !== "idle") return null;
|
|
9778
9962
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
9779
9963
|
type: "button",
|
|
9780
|
-
className:
|
|
9964
|
+
className: _dsh_plugin_shop_css_d74581c2_default.uninstallButton,
|
|
9781
9965
|
"data-shop-uninstall": true,
|
|
9782
9966
|
onClick: () => void start({ name }),
|
|
9783
9967
|
children: t("uninstall")
|
|
@@ -9818,38 +10002,38 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
9818
10002
|
else if (outcome.kind === "unreachable") setRefusal(t("restartTransportFailed"));
|
|
9819
10003
|
};
|
|
9820
10004
|
if (monitor?.kind === "requesting" || monitor?.kind === "restarting") return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
9821
|
-
className:
|
|
10005
|
+
className: _dsh_plugin_shop_css_d74581c2_default.notice,
|
|
9822
10006
|
"data-shop-restarting": true,
|
|
9823
10007
|
children: t("restarting")
|
|
9824
10008
|
});
|
|
9825
10009
|
if (monitor?.kind === "failed") return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
9826
|
-
className:
|
|
10010
|
+
className: _dsh_plugin_shop_css_d74581c2_default.failedDetail,
|
|
9827
10011
|
"data-shop-restart-error": true,
|
|
9828
10012
|
children: monitor.logFile === void 0 ? t("restartFailedNotice") : t("restartFailedLogNotice", { log: monitor.logFile })
|
|
9829
10013
|
});
|
|
9830
10014
|
if (monitor?.kind === "not-restarted") return null;
|
|
9831
10015
|
if (gateOpen) return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
9832
|
-
className:
|
|
10016
|
+
className: _dsh_plugin_shop_css_d74581c2_default.gate,
|
|
9833
10017
|
children: [
|
|
9834
10018
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
9835
|
-
className:
|
|
10019
|
+
className: _dsh_plugin_shop_css_d74581c2_default.gateTitle,
|
|
9836
10020
|
children: t("restartTitle")
|
|
9837
10021
|
}),
|
|
9838
10022
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
9839
|
-
className:
|
|
10023
|
+
className: _dsh_plugin_shop_css_d74581c2_default.gateBody,
|
|
9840
10024
|
children: t("restartBody")
|
|
9841
10025
|
}),
|
|
9842
10026
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
9843
|
-
className:
|
|
10027
|
+
className: _dsh_plugin_shop_css_d74581c2_default.gateActions,
|
|
9844
10028
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
9845
10029
|
type: "button",
|
|
9846
|
-
className:
|
|
10030
|
+
className: _dsh_plugin_shop_css_d74581c2_default.confirmButton,
|
|
9847
10031
|
"data-shop-restart-confirm": true,
|
|
9848
10032
|
onClick: () => void onConfirm(),
|
|
9849
10033
|
children: t("restartConfirm")
|
|
9850
10034
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
9851
10035
|
type: "button",
|
|
9852
|
-
className:
|
|
10036
|
+
className: _dsh_plugin_shop_css_d74581c2_default.cancelButton,
|
|
9853
10037
|
onClick: () => setGateOpen(false),
|
|
9854
10038
|
children: t("cancel")
|
|
9855
10039
|
})]
|
|
@@ -9857,14 +10041,14 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
9857
10041
|
]
|
|
9858
10042
|
});
|
|
9859
10043
|
const refused = refusal === null ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
9860
|
-
className:
|
|
10044
|
+
className: _dsh_plugin_shop_css_d74581c2_default.failedDetail,
|
|
9861
10045
|
"data-shop-restart-error": true,
|
|
9862
10046
|
children: refusal
|
|
9863
10047
|
});
|
|
9864
10048
|
if (gate !== void 0) return refused;
|
|
9865
10049
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [refused, /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
9866
10050
|
type: "button",
|
|
9867
|
-
className:
|
|
10051
|
+
className: _dsh_plugin_shop_css_d74581c2_default.restartButton,
|
|
9868
10052
|
"data-shop-restart": true,
|
|
9869
10053
|
onClick: () => setGateOpen(true),
|
|
9870
10054
|
children: t("restart")
|
|
@@ -9882,13 +10066,13 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
9882
10066
|
*/
|
|
9883
10067
|
function NotRestartedNotice({ t, pid, logFile }) {
|
|
9884
10068
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
9885
|
-
className:
|
|
10069
|
+
className: _dsh_plugin_shop_css_d74581c2_default.selfUpdatePanel,
|
|
9886
10070
|
"data-shop-not-restarted": true,
|
|
9887
10071
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
9888
|
-
className:
|
|
10072
|
+
className: _dsh_plugin_shop_css_d74581c2_default.failedDetail,
|
|
9889
10073
|
children: pid === void 0 ? t("notRestartedNotice") : t("notRestartedPidNotice", { pid: String(pid) })
|
|
9890
10074
|
}), logFile !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
9891
|
-
className:
|
|
10075
|
+
className: _dsh_plugin_shop_css_d74581c2_default.failedDetail,
|
|
9892
10076
|
children: t("notRestartedLogNotice", { log: logFile })
|
|
9893
10077
|
})]
|
|
9894
10078
|
});
|
|
@@ -9918,7 +10102,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
9918
10102
|
restart,
|
|
9919
10103
|
reload
|
|
9920
10104
|
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
9921
|
-
className:
|
|
10105
|
+
className: _dsh_plugin_shop_css_d74581c2_default.notice,
|
|
9922
10106
|
"data-shop-restart-disabled": true,
|
|
9923
10107
|
children: t(restartBlockedNoticeKey(restartBlocked))
|
|
9924
10108
|
});
|
|
@@ -9929,14 +10113,14 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
9929
10113
|
* would help without knowing that now is a good time. */
|
|
9930
10114
|
function ReloadPanel({ t, reload, where }) {
|
|
9931
10115
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
9932
|
-
className:
|
|
10116
|
+
className: _dsh_plugin_shop_css_d74581c2_default.reloadPanel,
|
|
9933
10117
|
"data-shop-reload": where,
|
|
9934
10118
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
9935
|
-
className:
|
|
10119
|
+
className: _dsh_plugin_shop_css_d74581c2_default.notice,
|
|
9936
10120
|
children: t("reloadNote")
|
|
9937
10121
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
9938
10122
|
type: "button",
|
|
9939
|
-
className:
|
|
10123
|
+
className: _dsh_plugin_shop_css_d74581c2_default.reloadButton,
|
|
9940
10124
|
onClick: reload,
|
|
9941
10125
|
children: t("reload")
|
|
9942
10126
|
})]
|
|
@@ -9987,7 +10171,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
9987
10171
|
}
|
|
9988
10172
|
};
|
|
9989
10173
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
9990
|
-
className:
|
|
10174
|
+
className: _dsh_plugin_shop_css_d74581c2_default.switchWrap,
|
|
9991
10175
|
"data-shop-enabled-switch": row.name,
|
|
9992
10176
|
children: [
|
|
9993
10177
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
@@ -9996,18 +10180,18 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
9996
10180
|
"aria-checked": enabled,
|
|
9997
10181
|
"aria-label": t("enabledSwitch"),
|
|
9998
10182
|
"data-shop-toggle": true,
|
|
9999
|
-
className: `${
|
|
10183
|
+
className: `${_dsh_plugin_shop_css_d74581c2_default.switch} ${enabled ? _dsh_plugin_shop_css_d74581c2_default.switchOn : ""}`,
|
|
10000
10184
|
onClick: () => void onToggle(),
|
|
10001
10185
|
disabled: toggle.kind === "saving",
|
|
10002
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className:
|
|
10186
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: _dsh_plugin_shop_css_d74581c2_default.switchKnob })
|
|
10003
10187
|
}),
|
|
10004
10188
|
toggle.kind === "saved" && owed === "nothing" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
10005
|
-
className:
|
|
10189
|
+
className: _dsh_plugin_shop_css_d74581c2_default.notice,
|
|
10006
10190
|
"data-shop-hot-apply": true,
|
|
10007
10191
|
children: t("hotApplyNote")
|
|
10008
10192
|
}),
|
|
10009
10193
|
owed === "restart" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
10010
|
-
className:
|
|
10194
|
+
className: _dsh_plugin_shop_css_d74581c2_default.notice,
|
|
10011
10195
|
"data-shop-toggle-restart": true,
|
|
10012
10196
|
children: t("toggleRestartNote")
|
|
10013
10197
|
}),
|
|
@@ -10020,7 +10204,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
10020
10204
|
where: "toggle"
|
|
10021
10205
|
}),
|
|
10022
10206
|
toggle.kind === "error" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
10023
|
-
className:
|
|
10207
|
+
className: _dsh_plugin_shop_css_d74581c2_default.failedDetail,
|
|
10024
10208
|
"data-shop-toggle-error": true,
|
|
10025
10209
|
children: toggle.detail
|
|
10026
10210
|
})
|
|
@@ -10035,19 +10219,19 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
10035
10219
|
* field is narrowed at the parameter. */
|
|
10036
10220
|
function OutdatedRow({ row, tier, missing, harness, t, setEnabled, flowFor, restart, restartBlocked, reload, restarts }) {
|
|
10037
10221
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
10038
|
-
className:
|
|
10222
|
+
className: _dsh_plugin_shop_css_d74581c2_default.outdatedRow,
|
|
10039
10223
|
"data-shop-outdated-entry": row.name,
|
|
10040
10224
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
10041
|
-
className:
|
|
10225
|
+
className: _dsh_plugin_shop_css_d74581c2_default.outdatedInfo,
|
|
10042
10226
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
10043
|
-
className:
|
|
10227
|
+
className: _dsh_plugin_shop_css_d74581c2_default.name,
|
|
10044
10228
|
children: row.name
|
|
10045
10229
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
10046
|
-
className:
|
|
10047
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("installedVersion", { version: row.source
|
|
10230
|
+
className: _dsh_plugin_shop_css_d74581c2_default.outdatedVersions,
|
|
10231
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("installedVersion", { version: versionLabel(row.source, row.installed).text }) }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("latestVersion", { version: versionLabel(row.source, row.latest).text }) })]
|
|
10048
10232
|
})]
|
|
10049
10233
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
10050
|
-
className:
|
|
10234
|
+
className: _dsh_plugin_shop_css_d74581c2_default.outdatedActions,
|
|
10051
10235
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(EnabledSwitch, {
|
|
10052
10236
|
row,
|
|
10053
10237
|
t,
|
|
@@ -10096,22 +10280,22 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
10096
10280
|
function OutdatedSection({ state, entriesByKey, missingByKey, harnessVerdicts, t, setEnabled, flowFor, restart, restartBlocked, reload, restarts }) {
|
|
10097
10281
|
if (state.kind === "loading") return null;
|
|
10098
10282
|
if (state.kind === "error") return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
10099
|
-
className:
|
|
10283
|
+
className: _dsh_plugin_shop_css_d74581c2_default.stateLine,
|
|
10100
10284
|
"data-shop-outdated-error": true,
|
|
10101
10285
|
children: t("installedError")
|
|
10102
10286
|
});
|
|
10103
10287
|
const outdated = state.entries.filter((entry) => entry.outdated && entry.latest !== null);
|
|
10104
10288
|
if (outdated.length === 0) return null;
|
|
10105
10289
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
10106
|
-
className:
|
|
10290
|
+
className: _dsh_plugin_shop_css_d74581c2_default.outdatedSection,
|
|
10107
10291
|
"data-shop-outdated": true,
|
|
10108
10292
|
"aria-labelledby": UPDATABLE_HEADING_ID,
|
|
10109
10293
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h2", {
|
|
10110
|
-
className:
|
|
10294
|
+
className: _dsh_plugin_shop_css_d74581c2_default.updatableHeading,
|
|
10111
10295
|
id: UPDATABLE_HEADING_ID,
|
|
10112
10296
|
children: t("updatableSection")
|
|
10113
10297
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("ul", {
|
|
10114
|
-
className:
|
|
10298
|
+
className: _dsh_plugin_shop_css_d74581c2_default.outdatedList,
|
|
10115
10299
|
children: outdated.map((row) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(OutdatedRow, {
|
|
10116
10300
|
row,
|
|
10117
10301
|
tier: entriesByKey.get(identityKey(row))?.tier ?? "community",
|
|
@@ -10139,37 +10323,37 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
10139
10323
|
const shadowed = entries.filter((entry) => entry.shadowed === true);
|
|
10140
10324
|
if (shadowed.length === 0) return null;
|
|
10141
10325
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("section", {
|
|
10142
|
-
className:
|
|
10326
|
+
className: _dsh_plugin_shop_css_d74581c2_default.shadowedSection,
|
|
10143
10327
|
"data-shop-shadowed": true,
|
|
10144
10328
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("ul", {
|
|
10145
|
-
className:
|
|
10329
|
+
className: _dsh_plugin_shop_css_d74581c2_default.outdatedList,
|
|
10146
10330
|
children: shadowed.map((row) => {
|
|
10147
10331
|
const key = identityKey(row);
|
|
10148
10332
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
10149
|
-
className:
|
|
10333
|
+
className: _dsh_plugin_shop_css_d74581c2_default.outdatedRow,
|
|
10150
10334
|
"data-shop-shadowed-entry": row.name,
|
|
10151
10335
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
10152
|
-
className:
|
|
10336
|
+
className: _dsh_plugin_shop_css_d74581c2_default.outdatedInfo,
|
|
10153
10337
|
children: [
|
|
10154
10338
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
10155
|
-
className:
|
|
10339
|
+
className: _dsh_plugin_shop_css_d74581c2_default.name,
|
|
10156
10340
|
children: row.name
|
|
10157
10341
|
}),
|
|
10158
10342
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
10159
|
-
className:
|
|
10343
|
+
className: _dsh_plugin_shop_css_d74581c2_default.badges,
|
|
10160
10344
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
10161
|
-
className:
|
|
10345
|
+
className: _dsh_plugin_shop_css_d74581c2_default.tierBadge,
|
|
10162
10346
|
"data-tier": "shadowed",
|
|
10163
10347
|
children: t("shadowedBadge")
|
|
10164
10348
|
})
|
|
10165
10349
|
}),
|
|
10166
10350
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
10167
|
-
className:
|
|
10351
|
+
className: _dsh_plugin_shop_css_d74581c2_default.shadowedDetail,
|
|
10168
10352
|
children: t("shadowedDetail")
|
|
10169
10353
|
})
|
|
10170
10354
|
]
|
|
10171
10355
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
10172
|
-
className:
|
|
10356
|
+
className: _dsh_plugin_shop_css_d74581c2_default.outdatedActions,
|
|
10173
10357
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(UninstallPanel, {
|
|
10174
10358
|
name: row.name,
|
|
10175
10359
|
t,
|
|
@@ -10219,16 +10403,16 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
10219
10403
|
role: "alert",
|
|
10220
10404
|
children: [
|
|
10221
10405
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
10222
|
-
className:
|
|
10406
|
+
className: _dsh_plugin_shop_css_d74581c2_default.stateLine,
|
|
10223
10407
|
children: say("tabCrashed", en.tabCrashed)
|
|
10224
10408
|
}),
|
|
10225
10409
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
10226
|
-
className:
|
|
10410
|
+
className: _dsh_plugin_shop_css_d74581c2_default.failedDetail,
|
|
10227
10411
|
children: error.message
|
|
10228
10412
|
}),
|
|
10229
10413
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
10230
10414
|
type: "button",
|
|
10231
|
-
className:
|
|
10415
|
+
className: _dsh_plugin_shop_css_d74581c2_default.actionButton,
|
|
10232
10416
|
onClick: () => this.setState({ error: null }),
|
|
10233
10417
|
children: say("retry", en.retry)
|
|
10234
10418
|
})
|
|
@@ -10315,11 +10499,13 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
10315
10499
|
const [reloadFailed, setReloadFailed] = (0, react.useState)(false);
|
|
10316
10500
|
const [query, setQuery] = (0, react.useState)("");
|
|
10317
10501
|
const [category, setCategory] = (0, react.useState)(null);
|
|
10502
|
+
const [order, setOrder] = (0, react.useState)("stars");
|
|
10318
10503
|
const [hideIncompatible, setHideIncompatible] = (0, react.useState)(false);
|
|
10319
10504
|
const incremental = typeof IntersectionObserver !== "undefined";
|
|
10320
10505
|
const [visibleCount, setVisibleCount] = (0, react.useState)(48);
|
|
10321
10506
|
const sentinelRef = (0, react.useRef)(null);
|
|
10322
10507
|
const filteredLenRef = (0, react.useRef)(0);
|
|
10508
|
+
const sortLabelId = (0, react.useId)();
|
|
10323
10509
|
const pendingRefreshRef = (0, react.useRef)(null);
|
|
10324
10510
|
(0, react.useEffect)(() => {
|
|
10325
10511
|
let cancelled = false;
|
|
@@ -10414,7 +10600,13 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
10414
10600
|
return map;
|
|
10415
10601
|
}, [installedState]);
|
|
10416
10602
|
const stars = (0, react.useMemo)(() => catalogState.kind === "ready" ? catalogState.result.stars : {}, [catalogState]);
|
|
10417
|
-
const
|
|
10603
|
+
const starOrder = (0, react.useMemo)(() => catalogState.kind === "ready" ? sortByStars(catalogState.result.plugins, stars) : [], [catalogState, stars]);
|
|
10604
|
+
const builtAt = catalogState.kind === "ready" ? catalogState.result.builtAt : "";
|
|
10605
|
+
const sortedCatalog = (0, react.useMemo)(() => orderShelf(starOrder, order, builtAt), [
|
|
10606
|
+
starOrder,
|
|
10607
|
+
order,
|
|
10608
|
+
builtAt
|
|
10609
|
+
]);
|
|
10418
10610
|
const browsable = (0, react.useMemo)(() => {
|
|
10419
10611
|
if (catalogState.kind !== "ready") return [];
|
|
10420
10612
|
const cleared = new Set(catalogState.result.notAShop ?? []);
|
|
@@ -10487,6 +10679,14 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
10487
10679
|
filtered.length
|
|
10488
10680
|
]);
|
|
10489
10681
|
const visible = incremental ? filtered.slice(0, visibleCount) : filtered;
|
|
10682
|
+
/** The date a card shows under the current order, or undefined under the
|
|
10683
|
+
* star order and for an entry with no usable date. Computed from the same
|
|
10684
|
+
* `shelfTime` the order keyed on, so a label can never name a date the
|
|
10685
|
+
* order ignored. */
|
|
10686
|
+
const shelfDayOf = (entry) => {
|
|
10687
|
+
const ms = shelfTime(entry, order, builtAt);
|
|
10688
|
+
return ms === void 0 ? void 0 : utcDay(ms);
|
|
10689
|
+
};
|
|
10490
10690
|
const categoryCounts = (0, react.useMemo)(() => {
|
|
10491
10691
|
const counts = /* @__PURE__ */ new Map();
|
|
10492
10692
|
for (const entry of browsable) {
|
|
@@ -10509,19 +10709,19 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
10509
10709
|
"data-shop-tab": true,
|
|
10510
10710
|
"aria-busy": "true",
|
|
10511
10711
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
10512
|
-
className:
|
|
10712
|
+
className: _dsh_plugin_shop_css_d74581c2_default.srOnly,
|
|
10513
10713
|
children: t("loading")
|
|
10514
10714
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
10515
|
-
className:
|
|
10715
|
+
className: _dsh_plugin_shop_css_d74581c2_default.skeletonGrid,
|
|
10516
10716
|
"data-shop-skeleton": true,
|
|
10517
10717
|
"aria-hidden": "true",
|
|
10518
10718
|
children: Array.from({ length: 8 }, (_, i) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
10519
|
-
className:
|
|
10719
|
+
className: _dsh_plugin_shop_css_d74581c2_default.skeletonCard,
|
|
10520
10720
|
children: [
|
|
10521
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className:
|
|
10522
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className:
|
|
10523
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className:
|
|
10524
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className:
|
|
10721
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: _dsh_plugin_shop_css_d74581c2_default.skeletonName }),
|
|
10722
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: _dsh_plugin_shop_css_d74581c2_default.skeletonSummary }),
|
|
10723
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: _dsh_plugin_shop_css_d74581c2_default.skeletonSummaryShort }),
|
|
10724
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: _dsh_plugin_shop_css_d74581c2_default.skeletonActions })
|
|
10525
10725
|
]
|
|
10526
10726
|
}, i))
|
|
10527
10727
|
})]
|
|
@@ -10531,11 +10731,11 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
10531
10731
|
translate: "no",
|
|
10532
10732
|
"data-shop-tab": true,
|
|
10533
10733
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
10534
|
-
className:
|
|
10734
|
+
className: _dsh_plugin_shop_css_d74581c2_default.stateLine,
|
|
10535
10735
|
children: t("error")
|
|
10536
10736
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
10537
10737
|
type: "button",
|
|
10538
|
-
className:
|
|
10738
|
+
className: _dsh_plugin_shop_css_d74581c2_default.actionButton,
|
|
10539
10739
|
onClick: () => {
|
|
10540
10740
|
setRequest({ kind: "retry" });
|
|
10541
10741
|
setVersionReload((current) => current + 1);
|
|
@@ -10550,11 +10750,11 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
10550
10750
|
"data-shop-tab": true,
|
|
10551
10751
|
children: [
|
|
10552
10752
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
10553
|
-
className:
|
|
10753
|
+
className: _dsh_plugin_shop_css_d74581c2_default.toolbar,
|
|
10554
10754
|
children: [
|
|
10555
10755
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
10556
10756
|
type: "search",
|
|
10557
|
-
className:
|
|
10757
|
+
className: _dsh_plugin_shop_css_d74581c2_default.searchInput,
|
|
10558
10758
|
"aria-label": t("search"),
|
|
10559
10759
|
placeholder: t("search"),
|
|
10560
10760
|
value: query,
|
|
@@ -10565,31 +10765,31 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
10565
10765
|
}),
|
|
10566
10766
|
expansionMemo.intents.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
10567
10767
|
"data-shop-expansion-note": true,
|
|
10568
|
-
className:
|
|
10768
|
+
className: _dsh_plugin_shop_css_d74581c2_default.expansionNote,
|
|
10569
10769
|
children: t("zhExpansionNote", { terms: expansionMemo.terms.slice(1).map((term) => term.startsWith("#") ? term.slice(1) : term).join(", ") })
|
|
10570
10770
|
}),
|
|
10571
10771
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
10572
|
-
className:
|
|
10772
|
+
className: _dsh_plugin_shop_css_d74581c2_default.toolbarRight,
|
|
10573
10773
|
children: [
|
|
10574
10774
|
result.stale && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
10575
|
-
className:
|
|
10775
|
+
className: _dsh_plugin_shop_css_d74581c2_default.staleBadge,
|
|
10576
10776
|
children: t("staleLabel", { date: result.builtAt.slice(0, 10) })
|
|
10577
10777
|
}),
|
|
10578
10778
|
selfVersion !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
10579
|
-
className:
|
|
10779
|
+
className: _dsh_plugin_shop_css_d74581c2_default.versionBlock,
|
|
10580
10780
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
10581
|
-
className:
|
|
10781
|
+
className: _dsh_plugin_shop_css_d74581c2_default.versionText,
|
|
10582
10782
|
"data-shop-version": true,
|
|
10583
10783
|
children: ["v", selfVersion.installed]
|
|
10584
10784
|
}), restartMonitor !== null ? null : selfPending && restartBlocked === null ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
10585
10785
|
type: "button",
|
|
10586
|
-
className:
|
|
10786
|
+
className: _dsh_plugin_shop_css_d74581c2_default.restartSelfButton,
|
|
10587
10787
|
"data-shop-restart": true,
|
|
10588
10788
|
onClick: () => setSelfRestartGate(true),
|
|
10589
10789
|
children: t("restart")
|
|
10590
10790
|
}) : !selfPending && selfVersion.outdated && selfVersion.latest !== null && selfUpdate.view.kind === "idle" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
10591
10791
|
type: "button",
|
|
10592
|
-
className:
|
|
10792
|
+
className: _dsh_plugin_shop_css_d74581c2_default.updateSelfButton,
|
|
10593
10793
|
"data-shop-update-self": true,
|
|
10594
10794
|
onClick: () => {
|
|
10595
10795
|
if (selfVersion.latest !== null) selfUpdate.start({ version: selfVersion.latest });
|
|
@@ -10597,7 +10797,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
10597
10797
|
children: t("update")
|
|
10598
10798
|
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
10599
10799
|
type: "button",
|
|
10600
|
-
className:
|
|
10800
|
+
className: _dsh_plugin_shop_css_d74581c2_default.checkUpdateButton,
|
|
10601
10801
|
"data-shop-check-update": true,
|
|
10602
10802
|
title: t("checkUpdateTitle"),
|
|
10603
10803
|
disabled: checkState !== "idle",
|
|
@@ -10606,7 +10806,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
10606
10806
|
})]
|
|
10607
10807
|
}),
|
|
10608
10808
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", {
|
|
10609
|
-
className:
|
|
10809
|
+
className: _dsh_plugin_shop_css_d74581c2_default.githubLink,
|
|
10610
10810
|
href: SHOP_REPO_URL,
|
|
10611
10811
|
target: "_blank",
|
|
10612
10812
|
rel: "noopener noreferrer",
|
|
@@ -10631,28 +10831,28 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
10631
10831
|
logFile: restartMonitor.logFile
|
|
10632
10832
|
}),
|
|
10633
10833
|
selfUpdate.view.kind === "running" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
10634
|
-
className:
|
|
10834
|
+
className: _dsh_plugin_shop_css_d74581c2_default.selfUpdatePanel,
|
|
10635
10835
|
"data-shop-self-updating": true,
|
|
10636
10836
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
10637
|
-
className:
|
|
10837
|
+
className: _dsh_plugin_shop_css_d74581c2_default.installing,
|
|
10638
10838
|
children: t(installPhaseKey(selfUpdate.view.phase))
|
|
10639
10839
|
}), selfUpdate.view.log.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
10640
|
-
className:
|
|
10840
|
+
className: _dsh_plugin_shop_css_d74581c2_default.log,
|
|
10641
10841
|
children: selfUpdate.view.log.map((line, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
10642
|
-
className:
|
|
10842
|
+
className: _dsh_plugin_shop_css_d74581c2_default.logLine,
|
|
10643
10843
|
"data-shop-log-line": true,
|
|
10644
10844
|
children: line
|
|
10645
10845
|
}, index))
|
|
10646
10846
|
})]
|
|
10647
10847
|
}),
|
|
10648
10848
|
selfPending && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
10649
|
-
className:
|
|
10849
|
+
className: _dsh_plugin_shop_css_d74581c2_default.selfUpdatePanel,
|
|
10650
10850
|
"data-shop-self-update-done": true,
|
|
10651
10851
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
10652
|
-
className:
|
|
10852
|
+
className: _dsh_plugin_shop_css_d74581c2_default.installedActions,
|
|
10653
10853
|
children: [
|
|
10654
10854
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
10655
|
-
className:
|
|
10855
|
+
className: _dsh_plugin_shop_css_d74581c2_default.notice,
|
|
10656
10856
|
children: t("installedRestartNotice")
|
|
10657
10857
|
}),
|
|
10658
10858
|
restartBlocked === null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RestartPanel, {
|
|
@@ -10665,7 +10865,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
10665
10865
|
}
|
|
10666
10866
|
}),
|
|
10667
10867
|
restartBlocked !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
10668
|
-
className:
|
|
10868
|
+
className: _dsh_plugin_shop_css_d74581c2_default.notice,
|
|
10669
10869
|
"data-shop-restart-disabled": true,
|
|
10670
10870
|
children: t(restartBlockedNoticeKey(restartBlocked))
|
|
10671
10871
|
})
|
|
@@ -10673,35 +10873,35 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
10673
10873
|
})
|
|
10674
10874
|
}),
|
|
10675
10875
|
selfUpdate.view.kind === "failed" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
10676
|
-
className:
|
|
10876
|
+
className: _dsh_plugin_shop_css_d74581c2_default.selfUpdatePanel,
|
|
10677
10877
|
"data-shop-self-update-failed": true,
|
|
10678
10878
|
children: [
|
|
10679
10879
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
10680
|
-
className:
|
|
10880
|
+
className: _dsh_plugin_shop_css_d74581c2_default.failedHeading,
|
|
10681
10881
|
children: t("updateFailed")
|
|
10682
10882
|
}),
|
|
10683
10883
|
selfUpdate.view.log.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
10684
|
-
className:
|
|
10884
|
+
className: _dsh_plugin_shop_css_d74581c2_default.log,
|
|
10685
10885
|
children: selfUpdate.view.log.map((line, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
10686
|
-
className:
|
|
10886
|
+
className: _dsh_plugin_shop_css_d74581c2_default.logLine,
|
|
10687
10887
|
"data-shop-log-line": true,
|
|
10688
10888
|
children: line
|
|
10689
10889
|
}, index))
|
|
10690
10890
|
}),
|
|
10691
10891
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
10692
|
-
className:
|
|
10892
|
+
className: _dsh_plugin_shop_css_d74581c2_default.failedDetail,
|
|
10693
10893
|
children: selfUpdate.view.detail === "" ? t("updateTransportFailed") : selfUpdate.view.detail
|
|
10694
10894
|
})
|
|
10695
10895
|
]
|
|
10696
10896
|
}),
|
|
10697
10897
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
10698
|
-
className:
|
|
10898
|
+
className: _dsh_plugin_shop_css_d74581c2_default.categoryBar,
|
|
10699
10899
|
role: "group",
|
|
10700
10900
|
"aria-label": t("catalog"),
|
|
10701
10901
|
children: [
|
|
10702
10902
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
10703
10903
|
type: "button",
|
|
10704
|
-
className: category === null ? `${
|
|
10904
|
+
className: category === null ? `${_dsh_plugin_shop_css_d74581c2_default.categoryButton} ${_dsh_plugin_shop_css_d74581c2_default.categoryButtonOn}` : _dsh_plugin_shop_css_d74581c2_default.categoryButton,
|
|
10705
10905
|
"aria-pressed": category === null,
|
|
10706
10906
|
onClick: () => {
|
|
10707
10907
|
setCategory(null);
|
|
@@ -10716,7 +10916,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
10716
10916
|
}),
|
|
10717
10917
|
CATEGORY_ORDER.map((key) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
10718
10918
|
type: "button",
|
|
10719
|
-
className: category === key ? `${
|
|
10919
|
+
className: category === key ? `${_dsh_plugin_shop_css_d74581c2_default.categoryButton} ${_dsh_plugin_shop_css_d74581c2_default.categoryButtonOn}` : _dsh_plugin_shop_css_d74581c2_default.categoryButton,
|
|
10720
10920
|
"aria-pressed": category === key,
|
|
10721
10921
|
"data-category": key,
|
|
10722
10922
|
"data-shop-category-tab": key,
|
|
@@ -10732,7 +10932,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
10732
10932
|
}, key)),
|
|
10733
10933
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
10734
10934
|
type: "button",
|
|
10735
|
-
className: category === "installed" ? `${
|
|
10935
|
+
className: category === "installed" ? `${_dsh_plugin_shop_css_d74581c2_default.categoryButton} ${_dsh_plugin_shop_css_d74581c2_default.categoryButtonOn}` : _dsh_plugin_shop_css_d74581c2_default.categoryButton,
|
|
10736
10936
|
"aria-pressed": category === "installed",
|
|
10737
10937
|
"data-shop-category-installed": true,
|
|
10738
10938
|
onClick: () => {
|
|
@@ -10749,7 +10949,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
10749
10949
|
type: "button",
|
|
10750
10950
|
role: "switch",
|
|
10751
10951
|
"aria-checked": hideIncompatible,
|
|
10752
|
-
className: hideIncompatible ? `${
|
|
10952
|
+
className: hideIncompatible ? `${_dsh_plugin_shop_css_d74581c2_default.incompatibleFilter} ${_dsh_plugin_shop_css_d74581c2_default.incompatibleFilterOn}` : _dsh_plugin_shop_css_d74581c2_default.incompatibleFilter,
|
|
10753
10953
|
title: t(hideIncompatible ? "showIncompatibleTitle" : "incompatibleFilterTitle"),
|
|
10754
10954
|
"data-shop-hide-incompatible": true,
|
|
10755
10955
|
onClick: () => {
|
|
@@ -10757,18 +10957,18 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
10757
10957
|
setVisibleCount(48);
|
|
10758
10958
|
},
|
|
10759
10959
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
10760
|
-
className: hideIncompatible ? `${
|
|
10960
|
+
className: hideIncompatible ? `${_dsh_plugin_shop_css_d74581c2_default.switch} ${_dsh_plugin_shop_css_d74581c2_default.switchOn}` : _dsh_plugin_shop_css_d74581c2_default.switch,
|
|
10761
10961
|
"aria-hidden": "true",
|
|
10762
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className:
|
|
10962
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: _dsh_plugin_shop_css_d74581c2_default.switchKnob })
|
|
10763
10963
|
}), t("hideIncompatible", { count: incompatibleCount })]
|
|
10764
10964
|
})
|
|
10765
10965
|
]
|
|
10766
10966
|
}),
|
|
10767
10967
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
10768
|
-
className:
|
|
10968
|
+
className: _dsh_plugin_shop_css_d74581c2_default.catalogStatsRow,
|
|
10769
10969
|
children: [
|
|
10770
10970
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
10771
|
-
className:
|
|
10971
|
+
className: _dsh_plugin_shop_css_d74581c2_default.catalogStats,
|
|
10772
10972
|
"data-shop-catalog-stats": true,
|
|
10773
10973
|
children: t("catalogStats", {
|
|
10774
10974
|
count: String(browsable.length),
|
|
@@ -10777,7 +10977,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
10777
10977
|
}),
|
|
10778
10978
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
10779
10979
|
type: "button",
|
|
10780
|
-
className:
|
|
10980
|
+
className: _dsh_plugin_shop_css_d74581c2_default.catalogRefreshButton,
|
|
10781
10981
|
"data-shop-catalog-refresh": true,
|
|
10782
10982
|
disabled: reloading,
|
|
10783
10983
|
onClick: () => {
|
|
@@ -10789,26 +10989,49 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
10789
10989
|
children: reloading ? t("refreshing") : t("refresh")
|
|
10790
10990
|
}),
|
|
10791
10991
|
reloadFailed && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
10792
|
-
className:
|
|
10992
|
+
className: _dsh_plugin_shop_css_d74581c2_default.catalogRefreshFailed,
|
|
10793
10993
|
"data-shop-catalog-refresh-failed": true,
|
|
10794
10994
|
children: t("refreshFailed")
|
|
10995
|
+
}),
|
|
10996
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
10997
|
+
className: _dsh_plugin_shop_css_d74581c2_default.sortGroup,
|
|
10998
|
+
role: "group",
|
|
10999
|
+
"aria-labelledby": sortLabelId,
|
|
11000
|
+
"data-shop-sort": true,
|
|
11001
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
11002
|
+
className: _dsh_plugin_shop_css_d74581c2_default.sortLabel,
|
|
11003
|
+
id: sortLabelId,
|
|
11004
|
+
children: t("sortLabel")
|
|
11005
|
+
}), SHELF_ORDERS.map((name) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
11006
|
+
type: "button",
|
|
11007
|
+
className: order === name ? `${_dsh_plugin_shop_css_d74581c2_default.categoryButton} ${_dsh_plugin_shop_css_d74581c2_default.categoryButtonOn}` : _dsh_plugin_shop_css_d74581c2_default.categoryButton,
|
|
11008
|
+
"aria-pressed": order === name,
|
|
11009
|
+
"data-shop-order": name,
|
|
11010
|
+
onClick: () => {
|
|
11011
|
+
setOrder(name);
|
|
11012
|
+
setVisibleCount(48);
|
|
11013
|
+
},
|
|
11014
|
+
children: t(shelfOrderLocaleKey(name))
|
|
11015
|
+
}, name))]
|
|
10795
11016
|
})
|
|
10796
11017
|
]
|
|
10797
11018
|
}),
|
|
10798
11019
|
result.plugins.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
10799
|
-
className:
|
|
11020
|
+
className: _dsh_plugin_shop_css_d74581c2_default.emptyLine,
|
|
10800
11021
|
children: t("empty")
|
|
10801
11022
|
}) : filtered.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
10802
|
-
className:
|
|
11023
|
+
className: _dsh_plugin_shop_css_d74581c2_default.emptyLine,
|
|
10803
11024
|
"data-shop-empty": true,
|
|
10804
11025
|
children: matched.length > 0 ? t("emptyIncompatibleFiltered") : t("emptySearch")
|
|
10805
11026
|
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("ul", {
|
|
10806
|
-
className:
|
|
11027
|
+
className: _dsh_plugin_shop_css_d74581c2_default.cards,
|
|
10807
11028
|
children: [visible.map((entry) => {
|
|
10808
11029
|
const key = entryKey(entry);
|
|
10809
11030
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(EntryCard, {
|
|
10810
11031
|
entry,
|
|
10811
11032
|
stars: starsOf(entry, stars),
|
|
11033
|
+
order,
|
|
11034
|
+
shelfDay: shelfDayOf(entry),
|
|
10812
11035
|
installed: installedByKey.get(key),
|
|
10813
11036
|
missing: missingByKey.get(key) ?? [],
|
|
10814
11037
|
harness: harnessVerdictOf(harnessVerdicts, key),
|
|
@@ -10825,12 +11048,12 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
10825
11048
|
}) }, key);
|
|
10826
11049
|
}), incremental && visibleCount < filtered.length && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", {
|
|
10827
11050
|
ref: sentinelRef,
|
|
10828
|
-
className:
|
|
11051
|
+
className: _dsh_plugin_shop_css_d74581c2_default.cardsSentry,
|
|
10829
11052
|
"data-shop-sentry": true,
|
|
10830
11053
|
"aria-hidden": "true"
|
|
10831
11054
|
})]
|
|
10832
11055
|
}), incremental && visibleCount < filtered.length && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
10833
|
-
className:
|
|
11056
|
+
className: _dsh_plugin_shop_css_d74581c2_default.showingLine,
|
|
10834
11057
|
"aria-live": "polite",
|
|
10835
11058
|
children: t("showing", {
|
|
10836
11059
|
shown: String(visibleCount),
|