dsh-plugin-shop 0.8.7-beta.3 → 0.8.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +10 -11
- package/lib/client.js +299 -299
- package/package.json +1 -1
package/lib/client.js
CHANGED
|
@@ -9312,134 +9312,134 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
9312
9312
|
};
|
|
9313
9313
|
}
|
|
9314
9314
|
//#endregion
|
|
9315
|
-
//#region \0dsh-plugin-shop-css:
|
|
9316
|
-
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.sa85938_client.s94d4e5_config.s91da2e_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.sa85938_client.sbb5706_spec.s91da2e_ts` pins this. */\n\n.s6a01b8_panel {\n display: flex;\n flex-direction: column;\n gap: 14px;\n /* The two reds every red text in this tab is painted with. dsh's error red\n * is #ec1313 in the light theme, which measures 4.498:1 as text on white —\n * a miss of two thousandths — and 3.57:1 on the badge's own 14% red fill\n * (4.00:1 in dark). Mixing it toward label-primary fixes both, because\n * label-primary is the theme's foreground pole: it darkens the red on light\n * surfaces and lightens it on dark ones. Measured in the live app: 90% of\n * the red is 5.30:1 on white and 5.29:1 on the dark card, and 80% is\n * 4.98:1 on the badge's tint, 4.92:1 in dark. Computed: 90% is 4.69:1 on\n * the dark panel itself (#2c2c2e), where the self-update's failure heading\n * sits, and 80% is 5.23:1 on the uninstall button's 10% hover fill.\n * Declared here, on the tab root, because a custom property inherits: one\n * declaration reaches every red element, and a new one cannot be\n * forgotten. */\n --shop-error: color-mix(in srgb, var(--dsw-alias-state-error-primary) 90%, var(--dsw-alias-label-primary));\n --shop-error-on-tint: color-mix(in srgb, var(--dsw-alias-state-error-primary) 80%, var(--dsw-alias-label-primary));\n /* The amber and the green, mixed the same way for the same reason. dsh's\n * warn #f59e0b and success #22c55e are one value in both themes and pass\n * in the dark one, but as text on white they measure 2.15:1 and 2.28:1.\n * Each derived colour keeps the largest multiple of ten of its hue that\n * clears every surface it paints, as the reds do. Computed from the live\n * tokens over every bg layer in both themes: amber at 60% is 4.95:1 on a\n * plain surface but 4.44:1 on its own 14% tint, so text on an amber tint\n * takes 50% (5.66:1); green at 60% is 5.18:1 plain and 4.60:1 on its 14%\n * tint, so one green serves both. */\n --shop-warn: color-mix(in srgb, var(--dsw-alias-state-warn-primary) 60%, var(--dsw-alias-label-primary));\n --shop-warn-on-tint: color-mix(in srgb, var(--dsw-alias-state-warn-primary) 50%, var(--dsw-alias-label-primary));\n --shop-success: color-mix(in srgb, var(--dsw-alias-state-success-primary) 60%, var(--dsw-alias-label-primary));\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 `.sa16cbe_searchInput` sits at\n * exactly (0, 0) of this box — it is the first child of `.sbc1497_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/* The shop's Settings page (design §5.1, amended 2026-10-15): the frame dsh's\n * Built-in plugins page draws around its body, where the shop sat as a tab,\n * measured from dsh 0.2.0-rc.2 — a 760px column, 12px gaps, an 18px semibold\n * title and a 13px intro line. The intro takes label-secondary, not the\n * label-tertiary dsh's own intro lines use: tertiary measures 3.71:1 on the\n * light theme's white, secondary 5.80:1. */\n.sb0400c_section {\n max-width: 760px;\n display: flex;\n flex-direction: column;\n gap: 12px;\n color: var(--dsw-alias-label-primary);\n}\n\n.s43b4f5_sectionTitle {\n margin: 0;\n font-size: 18px;\n font-weight: 600;\n}\n\n.se87c9d_sectionIntro {\n margin: 0;\n font-size: 13px;\n color: var(--dsw-alias-label-secondary);\n}\n\n.s352f7a_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.s60f2f5_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.s34d5f5_skeletonGrid {\n display: grid;\n grid-template-columns: 1fr;\n gap: 8px;\n}\n\n.s11e315_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.s11e315_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.s227d7c_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.s83025b_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.sdb7845_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.sa61117_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.s11e315_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 .s11e315_skeletonCard span { animation: none; opacity: 0.75; }\n .s11e315_skeletonCard::after { content: none; }\n}\n\n.s757132_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.s757132_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.s757132_actionButton:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary);\n outline-offset: 1px;\n}\n\n.sbc1497_toolbar {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 12px;\n flex-wrap: wrap;\n}\n\n.s22d15d_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.s76d3c9_versionBlock {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.s390e34_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.s79450a_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.s79450a_updateSelfButton:hover {\n background: color-mix(in srgb, var(--dsw-alias-brand-primary) 20%, transparent);\n}\n\n.s79450a_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.sb48cbc_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.sb48cbc_checkUpdateButton:hover {\n border-color: var(--dsw-alias-label-secondary);\n color: var(--dsw-alias-label-primary);\n}\n\n.sb48cbc_checkUpdateButton:disabled {\n opacity: 0.6;\n cursor: default;\n}\n\n.sb48cbc_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.s946346_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.s946346_githubLink:hover {\n color: var(--dsw-alias-label-primary);\n background: var(--dsw-alias-bg-layer-2);\n}\n\n.s946346_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.s861599_selfUpdatePanel {\n display: flex;\n flex-direction: column;\n gap: 8px;\n margin-top: 8px;\n}\n\n.sa16cbe_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.sa16cbe_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.seb8329_expansionNote {\n margin: 4px 0 0;\n font-size: 12px;\n color: var(--dsw-alias-label-secondary);\n}\n\n.s31a2f0_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(--shop-warn-on-tint);\n font-size: 12px;\n}\n\n.sab4844_categoryBar {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 6px;\n margin-top: 6px;\n}\n\n.s512425_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.s512425_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 `.s512425_categoryButton.s598384_categoryButtonOn` — TWO classes — so it\n * matches `.s512425_categoryButton:hover`'s specificity and, coming after it, wins.\n * As a bare `.s598384_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: a pressed tab must occupy exactly the\n * same box as an unpressed one, so the bar does not reflow — and with ~9 pills\n * on a wrapping row, one that grows can push the rest onto another line and\n * move the tab out from under the pointer that just clicked it. That is what\n * `font-weight: 600` did (bold metrics are wider than regular), and it is why\n * nothing may be added here that resolves to a length: no padding, no\n * border-width, no font-size, no letter-spacing. `css-tokens.sa85938_client.sbb5706_spec.s91da2e_ts`\n * fails the build on one.\n *\n * Nor a second line. An inset ring once doubled this border, and every control\n * in the stylesheet now draws exactly one 1px line, which is also the thinnest\n * the host paints (Chromium draws 0.5px as 1px). What separates pressed from\n * unpressed is lightness instead of thickness: the border is the hue mixed 30%\n * toward label-primary, the theme's foreground pole, so it clears 3:1 against\n * the bar in both themes for every hue — the raw hue measured 1.86:1 on white\n * for `ui` — and the fill under it is 22% of the hue. The `other` tab is the\n * case this is for: its hue IS the neutral gray this file uses for \"no\n * category\", so on the light theme the hue alone barely separates the two. */\n.s512425_categoryButton.s598384_categoryButtonOn {\n border-color: color-mix(in srgb, var(--category-hue) 70%, var(--dsw-alias-label-primary));\n background: color-mix(in srgb, var(--category-hue) 22%, transparent);\n color: color-mix(in srgb, var(--category-hue) 45%, var(--dsw-alias-label-primary) 55%);\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, so this mode alone gets an outline. */\n@media (forced-colors: active) {\n .s512425_categoryButton.s598384_categoryButtonOn {\n outline: 2px solid ButtonText;\n outline-offset: -4px;\n }\n}\n\n.s512425_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 `.s512425_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.s7ce437_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: `.s7ce437_incompatibleFilter:hover .s3a8382_switch` outranks `.s1e392e_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.s7ce437_incompatibleFilter:hover {\n color: var(--dsw-alias-label-primary);\n}\n\n.s7ce437_incompatibleFilter:hover .s3a8382_switch:not(.s1e392e_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 `.s512425_categoryButton.s598384_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.s7ce437_incompatibleFilter.sd9fa8d_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.s7ce437_incompatibleFilter .s3a8382_switch:not(.s1e392e_switchOn) .s419ba1_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.s7ce437_incompatibleFilter:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary);\n outline-offset: 2px;\n border-radius: 999px;\n}\n\n.s320079_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.s923c82_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.s3edd9f_sortGroup {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n margin-left: auto;\n}\n\n.s73feb1_sortLabel {\n color: var(--dsw-alias-label-secondary);\n font-size: 12px;\n}\n\n.sad5aba_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 `.s757132_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.s4cca13_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.s4cca13_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.s4cca13_catalogRefreshButton:disabled {\n cursor: default;\n opacity: 0.6;\n}\n\n.s4cca13_catalogRefreshButton:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary);\n outline-offset: 1px;\n}\n\n.sc24c97_catalogRefreshFailed {\n font-size: 11px;\n color: var(--shop-warn);\n}\n\n.s1aa6bf_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.sa036b0_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 .sa036b0_cards { animation: none; }\n}\n\n.s88b200_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.s853040_cardsSentry {\n height: 1px;\n margin: 0;\n padding: 0;\n}\n\n.s239c39_showingLine {\n margin: 0;\n font-size: 12px;\n letter-spacing: 0.02em;\n color: var(--dsw-alias-label-secondary);\n}\n\n.s88b200_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 .s88b200_card { transition: none; }\n .s88b200_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.sc1c25e_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. `.s512425_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.s88b200_card[data-category='tool'], .s512425_categoryButton[data-category='tool'] { --category-hue: #4C8DFF; }\n.s88b200_card[data-category='provider'], .s512425_categoryButton[data-category='provider'] { --category-hue: #A78BFA; }\n.s88b200_card[data-category='ui'], .s512425_categoryButton[data-category='ui'] { --category-hue: #2DD4BF; }\n.s88b200_card[data-category='workflow'], .s512425_categoryButton[data-category='workflow'] { --category-hue: #F59E0B; }\n.s88b200_card[data-category='integration'], .s512425_categoryButton[data-category='integration'] { --category-hue: #34D399; }\n.s88b200_card[data-category='theme'], .s512425_categoryButton[data-category='theme'] { --category-hue: #F472B6; }\n.s88b200_card[data-category='other'], .s512425_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.s433c76_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.s6bc968_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.s6bc968_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.s704f0d_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.sba9311_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.s9b33f4_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.s9b33f4_cardActions > .sc99cff_gate,\n.s9b33f4_cardActions > .sbd0905_installPanel,\n.s9b33f4_cardActions > .sd562d9_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.s83e5d6_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.s93d06c_sourceBadge {\n display: inline-flex;\n align-items: center;\n color: var(--dsw-alias-label-secondary);\n}\n\n.s1fe784_tierBadge {\n padding: 1px 7px;\n border-radius: 999px;\n font-size: 11px;\n line-height: 1.6;\n}\n\n.s1fe784_tierBadge[data-tier='verified'] {\n color: var(--shop-success);\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.s1fe784_tierBadge[data-tier='verified-stale'] {\n color: var(--shop-warn-on-tint);\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.s1fe784_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.s1fe784_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.s1fe784_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.s2f456e_incompatibleBadge {\n flex-shrink: 0;\n padding: 3px 9px;\n border-radius: 999px;\n font-size: 12px;\n white-space: nowrap;\n /* On the tint, not on the plain surface: this text reads on its own 14% red\n * fill, where the 90% red would measure 4.21:1 (light) and 4.43:1 (dark). */\n color: var(--shop-error-on-tint);\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.sc6c968_starsBadge {\n font-size: 11px;\n color: var(--dsw-alias-label-secondary);\n}\n\n.s287fda_chevron, .s20b60f_chevronOpen {\n color: var(--dsw-alias-label-secondary);\n transition: transform 120ms ease;\n}\n\n.s20b60f_chevronOpen { transform: rotate(180deg); }\n\n@media (prefers-reduced-motion: reduce) {\n .s287fda_chevron, .s20b60f_chevronOpen { transition: none; }\n}\n\n.s87fcee_body {\n display: flex;\n flex-direction: column;\n gap: 8px;\n padding: 0 12px;\n}\n\n.sf5d0d8_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.sa0923f_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.s20eea8_summaryExpanded {\n -webkit-line-clamp: unset;\n display: block;\n}\n\n.sb53b34_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.sc2cc78_incompatibleDetail {\n margin: 0;\n font-size: 12px;\n line-height: 1.5;\n white-space: pre-line;\n color: var(--shop-error);\n}\n\n/* The way out of dsh's own refusal: the lead-in, then the exemption command\n * on its own line. */\n/* Block layout rather than flex: Firefox 153 will not line-clamp a container\n * that holds a display:flex child (Chromium 151 does), and the fold's\n * measured goal — \"the whole red block, remedy included, as one unit\" —\n * needs the container to clamp in BOTH engines the shop targets. The 4px\n * rhythm between the lead-in and the command is kept by the margins of the\n * children. */\n.sc7602c_remedy {\n display: block;\n}\n\n.sc7602c_remedy > * + * { margin-top: 4px; }\n\n/* The fold under a card's whole red block: two lines by default, a small\n * Refresh-pill-shaped toggle under it. Two containers, one rhythm: the shelf\n * uses `.s895dae_foldBlock` collapsed and `.s6b136d_foldBlockExpanded` open, and they share\n * one `display: block` (Firefox clamps no flex child inside a -webkit-box).\n * The clamp is on the BLOCK rather than any one line, so a 43-line remedy\n * counts as a unit instead of squashing the harness-peers line to a sliver\n * and hiding the command the reader actually came for. Both containers\n * still render the full block to a screen reader — `white-space: normal`\n * instead of pre-line keeps the copy's own `\\n` visible without forcing the\n * browser to lay the block's pieces like a text node. */\n.s895dae_foldBlock {\n display: block;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n display: -webkit-box;\n overflow: hidden;\n}\n\n.s6b136d_foldBlockExpanded { display: block; }\n\n/* The toggle. Geometry and quiet voice are the Refresh pill's\n * (`catalogStatsRow` right beside it on the same screen): one 1px border,\n * 11px text, secondary label, no fill. It is the only one of its kind here,\n * so a class of its own means one function of its own. */\n.s8c3792_foldToggle {\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.s8c3792_foldToggle:hover { border-color: color-mix(in srgb, var(--dsw-alias-brand-primary) 45%, var(--dsw-alias-border-l2)); }\n.s8c3792_foldToggle:focus-visible { outline: 2px solid var(--dsw-alias-brand-primary); outline-offset: 1px; }\n\n.s935bd9_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.se75f45_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 * refused label, the command that clears dsh's refusal included. Block,\n * rather than flex: Firefox will not line-clamp a -webkit-box that holds a\n * display:flex child, and the fold this element can sit inside of carries\n * that clamp. The 6px rhythm between the block's lines is carried by the\n * children's margins. */\n.se69fd7_refusal {\n display: block;\n flex-basis: 100%;\n}\n\n.se69fd7_refusal > * + * { margin-top: 6px; }\n\n.sb2edea_capabilitiesBlock {\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.sa5c8b2_capabilitiesNote {\n margin: 0;\n font-size: 11px;\n color: var(--dsw-alias-label-secondary);\n}\n\n.sb95e1e_capabilities {\n display: flex;\n flex-wrap: wrap;\n gap: 4px;\n list-style: none;\n margin: 0;\n padding: 0;\n}\n\n.sb95e1e_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.s1f4436_detail {\n border-top: 1px solid var(--dsw-alias-border-l1);\n padding-top: 8px;\n}\n\n.sf6f153_detailRows {\n display: flex;\n flex-direction: column;\n gap: 4px;\n margin: 0;\n}\n\n.sbfe178_detailRow {\n display: flex;\n justify-content: space-between;\n gap: 12px;\n font-size: 12px;\n}\n\n.sbfe178_detailRow dt {\n color: var(--dsw-alias-label-secondary);\n}\n\n.sbfe178_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.sbfe178_detailRow a {\n color: var(--dsw-alias-brand-primary);\n text-decoration: none;\n}\n\n.sbfe178_detailRow a:hover {\n text-decoration: underline;\n}\n\n.sbfe178_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 * `.s9b33f4_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.s92d907_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: `.s92d907_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 * `.s6119f4_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.s5889e2_size,\n.s6119f4_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 `.s92d907_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 `.s92d907_cardMeta`. There is no middot:\n * `.s92d907_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.s5efcbe_author {\n color: var(--dsw-alias-label-secondary);\n font-size: 12px;\n}\n\n.sdd3957_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(--shop-warn-on-tint);\n}\n\n/* Install flow. */\n.sbd0905_installPanel {\n display: flex;\n flex-direction: column;\n gap: 8px;\n margin-top: 2px;\n}\n\n/* ONE geometry for everything that occupies the install button's place: the\n * button itself, the confirm/cancel pair beside the restart gate, the installed\n * label, and the refused label. Stated once because a refused label HAS to look\n * like the button it replaces apart from its colour and its text, and four\n * copies of the same five declarations is how they stop looking alike.\n * `cursor: pointer` is NOT here: only the controls that can be pressed take it,\n * while a label renders with the default cursor. */\n.se20cee_installButton,\n.sdf88f9_confirmButton,\n.s330a03_cancelButton,\n.sad029f_installedLabel,\n.s7b7f2d_refusedLabel {\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}\n\n.se20cee_installButton, .sdf88f9_confirmButton, .s330a03_cancelButton {\n cursor: pointer;\n}\n\n.se20cee_installButton {\n border-color: var(--dsw-alias-brand-primary);\n background: var(--dsw-alias-brand-primary);\n color: var(--dsw-alias-bg-base);\n}\n\n/* Between the click and the host's answer. The flow ignores a repeat start for\n * the same identity, so this is the visible half of the same fact: a control\n * that says \"not now\" rather than one that looks ready to send a second\n * install. Only the button can be in this state — a label is never pressed. */\n.se20cee_installButton:disabled {\n cursor: wait;\n}\n\n.se20cee_installButton:hover {\n background: color-mix(in srgb, var(--dsw-alias-brand-primary) 88%, var(--dsw-alias-label-primary));\n}\n\n.sdf88f9_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.sdf88f9_confirmButton:hover {\n background: color-mix(in srgb, var(--dsw-alias-brand-primary) 88%, var(--dsw-alias-label-primary));\n}\n\n.s330a03_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.s330a03_cancelButton:hover {\n border-color: var(--dsw-alias-label-secondary);\n}\n\n.se20cee_installButton:focus-visible, .sdf88f9_confirmButton:focus-visible, .s330a03_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.sad029f_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/* The refused Install/Update button's replacement: the same box as the button\n * (the geometry rule above), filled solid red, not pressable. The fill is the\n * derived red rather than the raw token because text sits on it — bg-base on\n * `--shop-error` measures 5.31:1 light and 6.14:1 dark — and the raw error red\n * under bg-base text measures 4.498:1, the miss this whole family of fixes\n * exists for. Nothing here changes on hover: it is a statement, not a control,\n * so it keeps the default cursor and its colours. */\n.s7b7f2d_refusedLabel {\n border-color: var(--shop-error);\n background: var(--shop-error);\n color: var(--dsw-alias-bg-base);\n white-space: nowrap;\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.sd562d9_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.s1ef16e_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 /* The on-tint red: hovering this button paints a 10% red fill under the\n * word, where the plain red measures 4.50:1 (light) — the same two\n * thousandths short of the floor the raw token shipped at. */\n color: var(--shop-error-on-tint);\n font-size: 13px;\n cursor: pointer;\n}\n\n.s1ef16e_uninstallButton:hover {\n background: color-mix(in srgb, var(--dsw-alias-state-error-primary) 10%, transparent);\n}\n\n.s1ef16e_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.s912ec7_restartSelfButton {\n /* The version row's third state. Geometry matches .sb48cbc_checkUpdateButton and\n * .s79450a_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.s912ec7_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.sa5d8c1_restartButton,\n.se5bd2c_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.sa5d8c1_restartButton:hover,\n.se5bd2c_reloadButton:hover {\n border-color: var(--dsw-alias-label-secondary);\n}\n\n.sa5d8c1_restartButton:focus-visible,\n.se5bd2c_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 * `.sd562d9_installedActions` the way the restart gate is — a column of its own\n * rather than inline with the row. */\n.s76690e_reloadPanel {\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n gap: 6px;\n}\n\n\n.sc99cff_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.s58fe9b_gateTitle {\n margin: 0;\n font-size: 13px;\n font-weight: 600;\n color: var(--shop-warn-on-tint);\n}\n\n.sd510f5_gateBody {\n margin: 0;\n font-size: 12px;\n line-height: 1.6;\n color: var(--dsw-alias-label-primary);\n}\n\n.s943dbd_gateWarning {\n margin: 0;\n font-size: 12px;\n line-height: 1.6;\n white-space: pre-line;\n color: var(--shop-error);\n}\n\n.sb2e35c_gateActions {\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n}\n\n.s407016_installing {\n margin: 0;\n font-size: 12px;\n color: var(--dsw-alias-label-secondary);\n}\n\n.s56c1a5_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.s3d7aca_logLine {\n white-space: pre-wrap;\n word-break: break-all;\n color: var(--dsw-alias-label-secondary);\n}\n\n.s3e1ea0_notice {\n margin: 0;\n font-size: 12px;\n color: var(--shop-success);\n}\n\n.s71965d_failedHeading {\n margin: 0;\n font-size: 12px;\n font-weight: 600;\n color: var(--shop-error);\n}\n\n.s41bb43_failedDetail {\n margin: 0;\n font-size: 12px;\n line-height: 1.6;\n color: var(--dsw-alias-label-primary);\n}\n\n.s3b880d_rejectedCode {\n margin: 0;\n font-size: 12px;\n font-weight: 600;\n color: var(--shop-error);\n}\n\n.s465924_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.sfccf6f_outdatedSection {\n display: flex;\n flex-direction: column;\n gap: 8px;\n margin-top: 6px;\n}\n\n.s403f9e_outdatedList {\n display: flex;\n flex-direction: column;\n gap: 8px;\n list-style: none;\n margin: 0;\n padding: 0;\n}\n\n.sd9cb61_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.s7b2d89_outdatedInfo {\n display: flex;\n flex-direction: column;\n gap: 2px;\n min-width: 0;\n}\n\n.s7b2d89_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.sc33878_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 .sba9311_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.sa88998_shadowedSection {\n display: flex;\n flex-direction: column;\n gap: 8px;\n margin-top: 6px;\n}\n\n.s98799e_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.saaf7ce_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: `.s7ce437_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 `.s3a8382_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.s3a8382_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.s1e392e_switchOn {\n border-color: var(--track-hue);\n background: color-mix(in srgb, var(--track-hue) 55%, transparent);\n}\n\n.s419ba1_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.s1e392e_switchOn .s419ba1_switchKnob {\n transform: translateX(14px);\n background: var(--dsw-alias-bg-base);\n}\n\n.s3a8382_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 .s3a8382_switch, .s419ba1_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.saa9c93_switchWrap {\n display: inline-flex;\n align-items: center;\n /* Same reason as `.saaf7ce_outdatedActions`: `.s76690e_reloadPanel`'s own comment calls\n * itself \"a column of its own rather than inline with the row\", which held\n * for `.sd562d9_installedActions` and not here until this line. */\n flex-wrap: wrap;\n gap: 8px;\n}\n";
|
|
9317
|
-
if (typeof document !== "undefined" && !document.querySelector("style[data-plugin-css=\"
|
|
9315
|
+
//#region \0dsh-plugin-shop-css:c4b688e1
|
|
9316
|
+
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.s3ce4ec_client.s2bd96f_config.s26cef9_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.s3ce4ec_client.sfb0a9a_spec.s26cef9_ts` pins this. */\n\n.s8d78da_panel {\n display: flex;\n flex-direction: column;\n gap: 14px;\n /* The two reds every red text in this tab is painted with. dsh's error red\n * is #ec1313 in the light theme, which measures 4.498:1 as text on white —\n * a miss of two thousandths — and 3.57:1 on the badge's own 14% red fill\n * (4.00:1 in dark). Mixing it toward label-primary fixes both, because\n * label-primary is the theme's foreground pole: it darkens the red on light\n * surfaces and lightens it on dark ones. Measured in the live app: 90% of\n * the red is 5.30:1 on white and 5.29:1 on the dark card, and 80% is\n * 4.98:1 on the badge's tint, 4.92:1 in dark. Computed: 90% is 4.69:1 on\n * the dark panel itself (#2c2c2e), where the self-update's failure heading\n * sits, and 80% is 5.23:1 on the uninstall button's 10% hover fill.\n * Declared here, on the tab root, because a custom property inherits: one\n * declaration reaches every red element, and a new one cannot be\n * forgotten. */\n --shop-error: color-mix(in srgb, var(--dsw-alias-state-error-primary) 90%, var(--dsw-alias-label-primary));\n --shop-error-on-tint: color-mix(in srgb, var(--dsw-alias-state-error-primary) 80%, var(--dsw-alias-label-primary));\n /* The amber and the green, mixed the same way for the same reason. dsh's\n * warn #f59e0b and success #22c55e are one value in both themes and pass\n * in the dark one, but as text on white they measure 2.15:1 and 2.28:1.\n * Each derived colour keeps the largest multiple of ten of its hue that\n * clears every surface it paints, as the reds do. Computed from the live\n * tokens over every bg layer in both themes: amber at 60% is 4.95:1 on a\n * plain surface but 4.44:1 on its own 14% tint, so text on an amber tint\n * takes 50% (5.66:1); green at 60% is 5.18:1 plain and 4.60:1 on its 14%\n * tint, so one green serves both. */\n --shop-warn: color-mix(in srgb, var(--dsw-alias-state-warn-primary) 60%, var(--dsw-alias-label-primary));\n --shop-warn-on-tint: color-mix(in srgb, var(--dsw-alias-state-warn-primary) 50%, var(--dsw-alias-label-primary));\n --shop-success: color-mix(in srgb, var(--dsw-alias-state-success-primary) 60%, var(--dsw-alias-label-primary));\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 `.se2e462_searchInput` sits at\n * exactly (0, 0) of this box — it is the first child of `.s8c0536_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/* The shop's Settings page (design §5.1, amended 2026-10-15): the frame dsh's\n * Built-in plugins page draws around its body, where the shop sat as a tab,\n * measured from dsh 0.2.0-rc.2 — a 760px column, 12px gaps, an 18px semibold\n * title and a 13px intro line. The intro takes label-secondary, not the\n * label-tertiary dsh's own intro lines use: tertiary measures 3.71:1 on the\n * light theme's white, secondary 5.80:1. */\n.s2318c0_section {\n max-width: 760px;\n display: flex;\n flex-direction: column;\n gap: 12px;\n color: var(--dsw-alias-label-primary);\n}\n\n.sf8f08d_sectionTitle {\n margin: 0;\n font-size: 18px;\n font-weight: 600;\n}\n\n.s73f38e_sectionIntro {\n margin: 0;\n font-size: 13px;\n color: var(--dsw-alias-label-secondary);\n}\n\n.sa2fe9b_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.s3d84d8_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.s23fd5f_skeletonGrid {\n display: grid;\n grid-template-columns: 1fr;\n gap: 8px;\n}\n\n.se54361_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.se54361_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.sf859c5_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.sb926ac_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.s2196b0_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.s9cc9e0_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.se54361_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 .se54361_skeletonCard span { animation: none; opacity: 0.75; }\n .se54361_skeletonCard::after { content: none; }\n}\n\n.s67a61e_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.s67a61e_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.s67a61e_actionButton:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary);\n outline-offset: 1px;\n}\n\n.s8c0536_toolbar {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 12px;\n flex-wrap: wrap;\n}\n\n.s5d1722_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.s18aa1e_versionBlock {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.s59f33b_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.sab9c34_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.sab9c34_updateSelfButton:hover {\n background: color-mix(in srgb, var(--dsw-alias-brand-primary) 20%, transparent);\n}\n\n.sab9c34_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.sbc6d1e_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.sbc6d1e_checkUpdateButton:hover {\n border-color: var(--dsw-alias-label-secondary);\n color: var(--dsw-alias-label-primary);\n}\n\n.sbc6d1e_checkUpdateButton:disabled {\n opacity: 0.6;\n cursor: default;\n}\n\n.sbc6d1e_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.s2bb87e_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.s2bb87e_githubLink:hover {\n color: var(--dsw-alias-label-primary);\n background: var(--dsw-alias-bg-layer-2);\n}\n\n.s2bb87e_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.s86377e_selfUpdatePanel {\n display: flex;\n flex-direction: column;\n gap: 8px;\n margin-top: 8px;\n}\n\n.se2e462_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.se2e462_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.sbc236e_expansionNote {\n margin: 4px 0 0;\n font-size: 12px;\n color: var(--dsw-alias-label-secondary);\n}\n\n.sbbc122_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(--shop-warn-on-tint);\n font-size: 12px;\n}\n\n.s127242_categoryBar {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 6px;\n margin-top: 6px;\n}\n\n.sc61628_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.sc61628_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 `.sc61628_categoryButton.sd09021_categoryButtonOn` — TWO classes — so it\n * matches `.sc61628_categoryButton:hover`'s specificity and, coming after it, wins.\n * As a bare `.sd09021_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: a pressed tab must occupy exactly the\n * same box as an unpressed one, so the bar does not reflow — and with ~9 pills\n * on a wrapping row, one that grows can push the rest onto another line and\n * move the tab out from under the pointer that just clicked it. That is what\n * `font-weight: 600` did (bold metrics are wider than regular), and it is why\n * nothing may be added here that resolves to a length: no padding, no\n * border-width, no font-size, no letter-spacing. `css-tokens.s3ce4ec_client.sfb0a9a_spec.s26cef9_ts`\n * fails the build on one.\n *\n * Nor a second line. An inset ring once doubled this border, and every control\n * in the stylesheet now draws exactly one 1px line, which is also the thinnest\n * the host paints (Chromium draws 0.5px as 1px). What separates pressed from\n * unpressed is lightness instead of thickness: the border is the hue mixed 30%\n * toward label-primary, the theme's foreground pole, so it clears 3:1 against\n * the bar in both themes for every hue — the raw hue measured 1.86:1 on white\n * for `ui` — and the fill under it is 22% of the hue. The `other` tab is the\n * case this is for: its hue IS the neutral gray this file uses for \"no\n * category\", so on the light theme the hue alone barely separates the two. */\n.sc61628_categoryButton.sd09021_categoryButtonOn {\n border-color: color-mix(in srgb, var(--category-hue) 70%, var(--dsw-alias-label-primary));\n background: color-mix(in srgb, var(--category-hue) 22%, transparent);\n color: color-mix(in srgb, var(--category-hue) 45%, var(--dsw-alias-label-primary) 55%);\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, so this mode alone gets an outline. */\n@media (forced-colors: active) {\n .sc61628_categoryButton.sd09021_categoryButtonOn {\n outline: 2px solid ButtonText;\n outline-offset: -4px;\n }\n}\n\n.sc61628_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 `.sc61628_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.s917a01_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: `.s917a01_incompatibleFilter:hover .se85a58_switch` outranks `.s7b2df9_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.s917a01_incompatibleFilter:hover {\n color: var(--dsw-alias-label-primary);\n}\n\n.s917a01_incompatibleFilter:hover .se85a58_switch:not(.s7b2df9_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 `.sc61628_categoryButton.sd09021_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.s917a01_incompatibleFilter.s438aff_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.s917a01_incompatibleFilter .se85a58_switch:not(.s7b2df9_switchOn) .s894f35_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.s917a01_incompatibleFilter:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary);\n outline-offset: 2px;\n border-radius: 999px;\n}\n\n.s6d0e29_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.s81108c_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.s6ca63b_sortGroup {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n margin-left: auto;\n}\n\n.sb4b816_sortLabel {\n color: var(--dsw-alias-label-secondary);\n font-size: 12px;\n}\n\n.sb4fd92_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 `.s67a61e_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.s8745d6_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.s8745d6_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.s8745d6_catalogRefreshButton:disabled {\n cursor: default;\n opacity: 0.6;\n}\n\n.s8745d6_catalogRefreshButton:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary);\n outline-offset: 1px;\n}\n\n.s8ac1d5_catalogRefreshFailed {\n font-size: 11px;\n color: var(--shop-warn);\n}\n\n.s5bfb21_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.sa7e6b4_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 .sa7e6b4_cards { animation: none; }\n}\n\n.sc86593_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.s1ecd69_cardsSentry {\n height: 1px;\n margin: 0;\n padding: 0;\n}\n\n.sc06acb_showingLine {\n margin: 0;\n font-size: 12px;\n letter-spacing: 0.02em;\n color: var(--dsw-alias-label-secondary);\n}\n\n.sc86593_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 .sc86593_card { transition: none; }\n .sc86593_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.s7480b4_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. `.sc61628_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.sc86593_card[data-category='tool'], .sc61628_categoryButton[data-category='tool'] { --category-hue: #4C8DFF; }\n.sc86593_card[data-category='provider'], .sc61628_categoryButton[data-category='provider'] { --category-hue: #A78BFA; }\n.sc86593_card[data-category='ui'], .sc61628_categoryButton[data-category='ui'] { --category-hue: #2DD4BF; }\n.sc86593_card[data-category='workflow'], .sc61628_categoryButton[data-category='workflow'] { --category-hue: #F59E0B; }\n.sc86593_card[data-category='integration'], .sc61628_categoryButton[data-category='integration'] { --category-hue: #34D399; }\n.sc86593_card[data-category='theme'], .sc61628_categoryButton[data-category='theme'] { --category-hue: #F472B6; }\n.sc86593_card[data-category='other'], .sc61628_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.s91e3d3_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.s7c9d85_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.s7c9d85_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.sc94f56_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.s6ae450_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.s3529d3_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.s3529d3_cardActions > .s202471_gate,\n.s3529d3_cardActions > .sd26f3f_installPanel,\n.s3529d3_cardActions > .sff3c46_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.sf1425b_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.s8e3025_sourceBadge {\n display: inline-flex;\n align-items: center;\n color: var(--dsw-alias-label-secondary);\n}\n\n.s71e1b7_tierBadge {\n padding: 1px 7px;\n border-radius: 999px;\n font-size: 11px;\n line-height: 1.6;\n}\n\n.s71e1b7_tierBadge[data-tier='verified'] {\n color: var(--shop-success);\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.s71e1b7_tierBadge[data-tier='verified-stale'] {\n color: var(--shop-warn-on-tint);\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.s71e1b7_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.s71e1b7_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.s71e1b7_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.s36b613_incompatibleBadge {\n flex-shrink: 0;\n padding: 3px 9px;\n border-radius: 999px;\n font-size: 12px;\n white-space: nowrap;\n /* On the tint, not on the plain surface: this text reads on its own 14% red\n * fill, where the 90% red would measure 4.21:1 (light) and 4.43:1 (dark). */\n color: var(--shop-error-on-tint);\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.s63d9f6_starsBadge {\n font-size: 11px;\n color: var(--dsw-alias-label-secondary);\n}\n\n.s1faef8_chevron, .s7a4b1f_chevronOpen {\n color: var(--dsw-alias-label-secondary);\n transition: transform 120ms ease;\n}\n\n.s7a4b1f_chevronOpen { transform: rotate(180deg); }\n\n@media (prefers-reduced-motion: reduce) {\n .s1faef8_chevron, .s7a4b1f_chevronOpen { transition: none; }\n}\n\n.sc53619_body {\n display: flex;\n flex-direction: column;\n gap: 8px;\n padding: 0 12px;\n}\n\n.s617f51_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.se22e0f_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.s12a8f7_summaryExpanded {\n -webkit-line-clamp: unset;\n display: block;\n}\n\n.sf04c34_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.s8f5da6_incompatibleDetail {\n margin: 0;\n font-size: 12px;\n line-height: 1.5;\n white-space: pre-line;\n color: var(--shop-error);\n}\n\n/* The way out of dsh's own refusal: the lead-in, then the exemption command\n * on its own line. */\n/* Block layout rather than flex: Firefox 153 will not line-clamp a container\n * that holds a display:flex child (Chromium 151 does), and the fold's\n * measured goal — \"the whole red block, remedy included, as one unit\" —\n * needs the container to clamp in BOTH engines the shop targets. The 4px\n * rhythm between the lead-in and the command is kept by the margins of the\n * children. */\n.sb71cf3_remedy {\n display: block;\n}\n\n.sb71cf3_remedy > * + * { margin-top: 4px; }\n\n/* The fold under a card's whole red block: two lines by default, a small\n * Refresh-pill-shaped toggle under it. Two containers, one rhythm: the shelf\n * uses `.se8b041_foldBlock` collapsed and `.sd5e94d_foldBlockExpanded` open, and they share\n * one `display: block` (Firefox clamps no flex child inside a -webkit-box).\n * The clamp is on the BLOCK rather than any one line, so a 43-line remedy\n * counts as a unit instead of squashing the harness-peers line to a sliver\n * and hiding the command the reader actually came for. Both containers\n * still render the full block to a screen reader — `white-space: normal`\n * instead of pre-line keeps the copy's own `\\n` visible without forcing the\n * browser to lay the block's pieces like a text node. */\n.se8b041_foldBlock {\n display: block;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n display: -webkit-box;\n overflow: hidden;\n}\n\n.sd5e94d_foldBlockExpanded { display: block; }\n\n/* The toggle. Geometry and quiet voice are the Refresh pill's\n * (`catalogStatsRow` right beside it on the same screen): one 1px border,\n * 11px text, secondary label, no fill. It is the only one of its kind here,\n * so a class of its own means one function of its own. */\n.sd63d48_foldToggle {\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.sd63d48_foldToggle:hover { border-color: color-mix(in srgb, var(--dsw-alias-brand-primary) 45%, var(--dsw-alias-border-l2)); }\n.sd63d48_foldToggle:focus-visible { outline: 2px solid var(--dsw-alias-brand-primary); outline-offset: 1px; }\n\n.s9e108c_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.s51d415_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 * refused label, the command that clears dsh's refusal included. Block,\n * rather than flex: Firefox will not line-clamp a -webkit-box that holds a\n * display:flex child, and the fold this element can sit inside of carries\n * that clamp. The 6px rhythm between the block's lines is carried by the\n * children's margins. */\n.sf48b40_refusal {\n display: block;\n flex-basis: 100%;\n}\n\n.sf48b40_refusal > * + * { margin-top: 6px; }\n\n.s24b64d_capabilitiesBlock {\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.s1cdba4_capabilitiesNote {\n margin: 0;\n font-size: 11px;\n color: var(--dsw-alias-label-secondary);\n}\n\n.s4bc6d7_capabilities {\n display: flex;\n flex-wrap: wrap;\n gap: 4px;\n list-style: none;\n margin: 0;\n padding: 0;\n}\n\n.s4bc6d7_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.se00d68_detail {\n border-top: 1px solid var(--dsw-alias-border-l1);\n padding-top: 8px;\n}\n\n.seadb7e_detailRows {\n display: flex;\n flex-direction: column;\n gap: 4px;\n margin: 0;\n}\n\n.s80932b_detailRow {\n display: flex;\n justify-content: space-between;\n gap: 12px;\n font-size: 12px;\n}\n\n.s80932b_detailRow dt {\n color: var(--dsw-alias-label-secondary);\n}\n\n.s80932b_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.s80932b_detailRow a {\n color: var(--dsw-alias-brand-primary);\n text-decoration: none;\n}\n\n.s80932b_detailRow a:hover {\n text-decoration: underline;\n}\n\n.s80932b_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 * `.s3529d3_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.s2c7916_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: `.s2c7916_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 * `.sa2b5c4_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.s983d76_size,\n.sa2b5c4_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 `.s2c7916_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 `.s2c7916_cardMeta`. There is no middot:\n * `.s2c7916_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.s787e2e_author {\n color: var(--dsw-alias-label-secondary);\n font-size: 12px;\n}\n\n.se111f0_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(--shop-warn-on-tint);\n}\n\n/* Install flow. */\n.sd26f3f_installPanel {\n display: flex;\n flex-direction: column;\n gap: 8px;\n margin-top: 2px;\n}\n\n/* ONE geometry for everything that occupies the install button's place: the\n * button itself, the confirm/cancel pair beside the restart gate, the installed\n * label, and the refused label. Stated once because a refused label HAS to look\n * like the button it replaces apart from its colour and its text, and four\n * copies of the same five declarations is how they stop looking alike.\n * `cursor: pointer` is NOT here: only the controls that can be pressed take it,\n * while a label renders with the default cursor. */\n.s62735d_installButton,\n.s53e10c_confirmButton,\n.sd2236a_cancelButton,\n.s9eb0bd_installedLabel,\n.s6c656b_refusedLabel {\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}\n\n.s62735d_installButton, .s53e10c_confirmButton, .sd2236a_cancelButton {\n cursor: pointer;\n}\n\n.s62735d_installButton {\n border-color: var(--dsw-alias-brand-primary);\n background: var(--dsw-alias-brand-primary);\n color: var(--dsw-alias-bg-base);\n}\n\n/* Between the click and the host's answer. The flow ignores a repeat start for\n * the same identity, so this is the visible half of the same fact: a control\n * that says \"not now\" rather than one that looks ready to send a second\n * install. Only the button can be in this state — a label is never pressed. */\n.s62735d_installButton:disabled {\n cursor: wait;\n}\n\n.s62735d_installButton:hover {\n background: color-mix(in srgb, var(--dsw-alias-brand-primary) 88%, var(--dsw-alias-label-primary));\n}\n\n.s53e10c_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.s53e10c_confirmButton:hover {\n background: color-mix(in srgb, var(--dsw-alias-brand-primary) 88%, var(--dsw-alias-label-primary));\n}\n\n.sd2236a_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.sd2236a_cancelButton:hover {\n border-color: var(--dsw-alias-label-secondary);\n}\n\n.s62735d_installButton:focus-visible, .s53e10c_confirmButton:focus-visible, .sd2236a_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.s9eb0bd_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/* The refused Install/Update button's replacement: the same box as the button\n * (the geometry rule above), filled solid red, not pressable. The fill is the\n * derived red rather than the raw token because text sits on it — bg-base on\n * `--shop-error` measures 5.31:1 light and 6.14:1 dark — and the raw error red\n * under bg-base text measures 4.498:1, the miss this whole family of fixes\n * exists for. Nothing here changes on hover: it is a statement, not a control,\n * so it keeps the default cursor and its colours. */\n.s6c656b_refusedLabel {\n border-color: var(--shop-error);\n background: var(--shop-error);\n color: var(--dsw-alias-bg-base);\n white-space: nowrap;\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.sff3c46_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.sd20046_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 /* The on-tint red: hovering this button paints a 10% red fill under the\n * word, where the plain red measures 4.50:1 (light) — the same two\n * thousandths short of the floor the raw token shipped at. */\n color: var(--shop-error-on-tint);\n font-size: 13px;\n cursor: pointer;\n}\n\n.sd20046_uninstallButton:hover {\n background: color-mix(in srgb, var(--dsw-alias-state-error-primary) 10%, transparent);\n}\n\n.sd20046_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.sac213f_restartSelfButton {\n /* The version row's third state. Geometry matches .sbc6d1e_checkUpdateButton and\n * .sab9c34_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.sac213f_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.s34ad1e_restartButton,\n.s234464_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.s34ad1e_restartButton:hover,\n.s234464_reloadButton:hover {\n border-color: var(--dsw-alias-label-secondary);\n}\n\n.s34ad1e_restartButton:focus-visible,\n.s234464_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 * `.sff3c46_installedActions` the way the restart gate is — a column of its own\n * rather than inline with the row. */\n.s55782e_reloadPanel {\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n gap: 6px;\n}\n\n\n.s202471_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.s656d08_gateTitle {\n margin: 0;\n font-size: 13px;\n font-weight: 600;\n color: var(--shop-warn-on-tint);\n}\n\n.s83f089_gateBody {\n margin: 0;\n font-size: 12px;\n line-height: 1.6;\n color: var(--dsw-alias-label-primary);\n}\n\n.s26dca1_gateWarning {\n margin: 0;\n font-size: 12px;\n line-height: 1.6;\n white-space: pre-line;\n color: var(--shop-error);\n}\n\n.sda785e_gateActions {\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n}\n\n.sf3a5fc_installing {\n margin: 0;\n font-size: 12px;\n color: var(--dsw-alias-label-secondary);\n}\n\n.s941e64_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.sc0d45c_logLine {\n white-space: pre-wrap;\n word-break: break-all;\n color: var(--dsw-alias-label-secondary);\n}\n\n.s2ddb67_notice {\n margin: 0;\n font-size: 12px;\n color: var(--shop-success);\n}\n\n.sff109f_failedHeading {\n margin: 0;\n font-size: 12px;\n font-weight: 600;\n color: var(--shop-error);\n}\n\n.sb51cd3_failedDetail {\n margin: 0;\n font-size: 12px;\n line-height: 1.6;\n color: var(--dsw-alias-label-primary);\n}\n\n.s7287ac_rejectedCode {\n margin: 0;\n font-size: 12px;\n font-weight: 600;\n color: var(--shop-error);\n}\n\n.sa26465_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.s438beb_outdatedSection {\n display: flex;\n flex-direction: column;\n gap: 8px;\n margin-top: 6px;\n}\n\n.s6e16fa_outdatedList {\n display: flex;\n flex-direction: column;\n gap: 8px;\n list-style: none;\n margin: 0;\n padding: 0;\n}\n\n.s46b13b_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.sc25007_outdatedInfo {\n display: flex;\n flex-direction: column;\n gap: 2px;\n min-width: 0;\n}\n\n.sc25007_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.s1b342c_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 .s6ae450_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.s6eace4_shadowedSection {\n display: flex;\n flex-direction: column;\n gap: 8px;\n margin-top: 6px;\n}\n\n.s653245_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.s7d34ef_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: `.s917a01_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 `.se85a58_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.se85a58_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.s7b2df9_switchOn {\n border-color: var(--track-hue);\n background: color-mix(in srgb, var(--track-hue) 55%, transparent);\n}\n\n.s894f35_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.s7b2df9_switchOn .s894f35_switchKnob {\n transform: translateX(14px);\n background: var(--dsw-alias-bg-base);\n}\n\n.se85a58_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 .se85a58_switch, .s894f35_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.sf25027_switchWrap {\n display: inline-flex;\n align-items: center;\n /* Same reason as `.s7d34ef_outdatedActions`: `.s55782e_reloadPanel`'s own comment calls\n * itself \"a column of its own rather than inline with the row\", which held\n * for `.sff3c46_installedActions` and not here until this line. */\n flex-wrap: wrap;\n gap: 8px;\n}\n";
|
|
9317
|
+
if (typeof document !== "undefined" && !document.querySelector("style[data-plugin-css=\"c4b688e1\"]")) {
|
|
9318
9318
|
const tag = document.createElement("style");
|
|
9319
|
-
tag.dataset.pluginCss = "
|
|
9319
|
+
tag.dataset.pluginCss = "c4b688e1";
|
|
9320
9320
|
tag.textContent = css;
|
|
9321
9321
|
document.head.appendChild(tag);
|
|
9322
9322
|
}
|
|
9323
|
-
var
|
|
9324
|
-
"client": "
|
|
9325
|
-
"config": "
|
|
9326
|
-
"ts": "
|
|
9327
|
-
"spec": "
|
|
9328
|
-
"panel": "
|
|
9329
|
-
"searchInput": "
|
|
9330
|
-
"toolbar": "
|
|
9331
|
-
"section": "
|
|
9332
|
-
"sectionTitle": "
|
|
9333
|
-
"sectionIntro": "
|
|
9334
|
-
"stateLine": "
|
|
9335
|
-
"srOnly": "
|
|
9336
|
-
"skeletonGrid": "
|
|
9337
|
-
"skeletonCard": "
|
|
9338
|
-
"skeletonName": "
|
|
9339
|
-
"skeletonSummary": "
|
|
9340
|
-
"skeletonSummaryShort": "
|
|
9341
|
-
"skeletonActions": "
|
|
9342
|
-
"actionButton": "
|
|
9343
|
-
"toolbarRight": "
|
|
9344
|
-
"versionBlock": "
|
|
9345
|
-
"versionText": "
|
|
9346
|
-
"updateSelfButton": "
|
|
9347
|
-
"checkUpdateButton": "
|
|
9348
|
-
"githubLink": "
|
|
9349
|
-
"selfUpdatePanel": "
|
|
9350
|
-
"expansionNote": "
|
|
9351
|
-
"staleBadge": "
|
|
9352
|
-
"categoryBar": "
|
|
9353
|
-
"categoryButton": "
|
|
9354
|
-
"categoryButtonOn": "
|
|
9355
|
-
"incompatibleFilter": "
|
|
9356
|
-
"switch": "
|
|
9357
|
-
"switchOn": "
|
|
9358
|
-
"incompatibleFilterOn": "
|
|
9359
|
-
"switchKnob": "
|
|
9360
|
-
"updatableHeading": "
|
|
9361
|
-
"catalogStatsRow": "
|
|
9362
|
-
"sortGroup": "
|
|
9363
|
-
"sortLabel": "
|
|
9364
|
-
"catalogStats": "
|
|
9365
|
-
"catalogRefreshButton": "
|
|
9366
|
-
"catalogRefreshFailed": "
|
|
9367
|
-
"emptyLine": "
|
|
9368
|
-
"cards": "
|
|
9369
|
-
"card": "
|
|
9370
|
-
"cardsSentry": "
|
|
9371
|
-
"showingLine": "
|
|
9372
|
-
"cardSpine": "
|
|
9373
|
-
"categoryBadge": "
|
|
9374
|
-
"entryHeader": "
|
|
9375
|
-
"name": "
|
|
9376
|
-
"badges": "
|
|
9377
|
-
"cardActions": "
|
|
9378
|
-
"gate": "
|
|
9379
|
-
"installPanel": "
|
|
9380
|
-
"installedActions": "
|
|
9381
|
-
"cardVersion": "
|
|
9382
|
-
"sourceBadge": "
|
|
9383
|
-
"tierBadge": "
|
|
9384
|
-
"incompatibleBadge": "
|
|
9385
|
-
"starsBadge": "
|
|
9386
|
-
"chevron": "
|
|
9387
|
-
"chevronOpen": "
|
|
9388
|
-
"body": "
|
|
9389
|
-
"summary": "
|
|
9390
|
-
"summaryZh": "
|
|
9391
|
-
"summaryExpanded": "
|
|
9392
|
-
"summaryZhExpanded": "
|
|
9393
|
-
"incompatibleDetail": "
|
|
9394
|
-
"remedy": "
|
|
9395
|
-
"foldBlock": "
|
|
9396
|
-
"foldBlockExpanded": "
|
|
9397
|
-
"foldToggle": "
|
|
9398
|
-
"remedyLead": "
|
|
9399
|
-
"allowCommand": "
|
|
9400
|
-
"refusal": "
|
|
9401
|
-
"capabilitiesBlock": "
|
|
9402
|
-
"capabilitiesNote": "
|
|
9403
|
-
"capabilities": "
|
|
9404
|
-
"detail": "
|
|
9405
|
-
"detailRows": "
|
|
9406
|
-
"detailRow": "
|
|
9407
|
-
"cardMeta": "
|
|
9408
|
-
"shelfDate": "
|
|
9409
|
-
"size": "
|
|
9410
|
-
"author": "
|
|
9411
|
-
"reviewedLine": "
|
|
9412
|
-
"installButton": "
|
|
9413
|
-
"confirmButton": "
|
|
9414
|
-
"cancelButton": "
|
|
9415
|
-
"installedLabel": "
|
|
9416
|
-
"refusedLabel": "
|
|
9417
|
-
"uninstallButton": "
|
|
9418
|
-
"restartSelfButton": "
|
|
9419
|
-
"restartButton": "
|
|
9420
|
-
"reloadButton": "
|
|
9421
|
-
"reloadPanel": "
|
|
9422
|
-
"gateTitle": "
|
|
9423
|
-
"gateBody": "
|
|
9424
|
-
"gateWarning": "
|
|
9425
|
-
"gateActions": "
|
|
9426
|
-
"installing": "
|
|
9427
|
-
"log": "
|
|
9428
|
-
"logLine": "
|
|
9429
|
-
"notice": "
|
|
9430
|
-
"failedHeading": "
|
|
9431
|
-
"failedDetail": "
|
|
9432
|
-
"rejectedCode": "
|
|
9433
|
-
"rejectedDetail": "
|
|
9434
|
-
"outdatedSection": "
|
|
9435
|
-
"outdatedList": "
|
|
9436
|
-
"outdatedRow": "
|
|
9437
|
-
"outdatedInfo": "
|
|
9438
|
-
"outdatedVersions": "
|
|
9439
|
-
"shadowedSection": "
|
|
9440
|
-
"shadowedDetail": "
|
|
9441
|
-
"outdatedActions": "
|
|
9442
|
-
"switchWrap": "
|
|
9323
|
+
var _dsh_plugin_shop_css_c4b688e1_default = {
|
|
9324
|
+
"client": "s3ce4ec_client",
|
|
9325
|
+
"config": "s2bd96f_config",
|
|
9326
|
+
"ts": "s26cef9_ts",
|
|
9327
|
+
"spec": "sfb0a9a_spec",
|
|
9328
|
+
"panel": "s8d78da_panel",
|
|
9329
|
+
"searchInput": "se2e462_searchInput",
|
|
9330
|
+
"toolbar": "s8c0536_toolbar",
|
|
9331
|
+
"section": "s2318c0_section",
|
|
9332
|
+
"sectionTitle": "sf8f08d_sectionTitle",
|
|
9333
|
+
"sectionIntro": "s73f38e_sectionIntro",
|
|
9334
|
+
"stateLine": "sa2fe9b_stateLine",
|
|
9335
|
+
"srOnly": "s3d84d8_srOnly",
|
|
9336
|
+
"skeletonGrid": "s23fd5f_skeletonGrid",
|
|
9337
|
+
"skeletonCard": "se54361_skeletonCard",
|
|
9338
|
+
"skeletonName": "sf859c5_skeletonName",
|
|
9339
|
+
"skeletonSummary": "sb926ac_skeletonSummary",
|
|
9340
|
+
"skeletonSummaryShort": "s2196b0_skeletonSummaryShort",
|
|
9341
|
+
"skeletonActions": "s9cc9e0_skeletonActions",
|
|
9342
|
+
"actionButton": "s67a61e_actionButton",
|
|
9343
|
+
"toolbarRight": "s5d1722_toolbarRight",
|
|
9344
|
+
"versionBlock": "s18aa1e_versionBlock",
|
|
9345
|
+
"versionText": "s59f33b_versionText",
|
|
9346
|
+
"updateSelfButton": "sab9c34_updateSelfButton",
|
|
9347
|
+
"checkUpdateButton": "sbc6d1e_checkUpdateButton",
|
|
9348
|
+
"githubLink": "s2bb87e_githubLink",
|
|
9349
|
+
"selfUpdatePanel": "s86377e_selfUpdatePanel",
|
|
9350
|
+
"expansionNote": "sbc236e_expansionNote",
|
|
9351
|
+
"staleBadge": "sbbc122_staleBadge",
|
|
9352
|
+
"categoryBar": "s127242_categoryBar",
|
|
9353
|
+
"categoryButton": "sc61628_categoryButton",
|
|
9354
|
+
"categoryButtonOn": "sd09021_categoryButtonOn",
|
|
9355
|
+
"incompatibleFilter": "s917a01_incompatibleFilter",
|
|
9356
|
+
"switch": "se85a58_switch",
|
|
9357
|
+
"switchOn": "s7b2df9_switchOn",
|
|
9358
|
+
"incompatibleFilterOn": "s438aff_incompatibleFilterOn",
|
|
9359
|
+
"switchKnob": "s894f35_switchKnob",
|
|
9360
|
+
"updatableHeading": "s6d0e29_updatableHeading",
|
|
9361
|
+
"catalogStatsRow": "s81108c_catalogStatsRow",
|
|
9362
|
+
"sortGroup": "s6ca63b_sortGroup",
|
|
9363
|
+
"sortLabel": "sb4b816_sortLabel",
|
|
9364
|
+
"catalogStats": "sb4fd92_catalogStats",
|
|
9365
|
+
"catalogRefreshButton": "s8745d6_catalogRefreshButton",
|
|
9366
|
+
"catalogRefreshFailed": "s8ac1d5_catalogRefreshFailed",
|
|
9367
|
+
"emptyLine": "s5bfb21_emptyLine",
|
|
9368
|
+
"cards": "sa7e6b4_cards",
|
|
9369
|
+
"card": "sc86593_card",
|
|
9370
|
+
"cardsSentry": "s1ecd69_cardsSentry",
|
|
9371
|
+
"showingLine": "sc06acb_showingLine",
|
|
9372
|
+
"cardSpine": "s7480b4_cardSpine",
|
|
9373
|
+
"categoryBadge": "s91e3d3_categoryBadge",
|
|
9374
|
+
"entryHeader": "s7c9d85_entryHeader",
|
|
9375
|
+
"name": "sc94f56_name",
|
|
9376
|
+
"badges": "s6ae450_badges",
|
|
9377
|
+
"cardActions": "s3529d3_cardActions",
|
|
9378
|
+
"gate": "s202471_gate",
|
|
9379
|
+
"installPanel": "sd26f3f_installPanel",
|
|
9380
|
+
"installedActions": "sff3c46_installedActions",
|
|
9381
|
+
"cardVersion": "sf1425b_cardVersion",
|
|
9382
|
+
"sourceBadge": "s8e3025_sourceBadge",
|
|
9383
|
+
"tierBadge": "s71e1b7_tierBadge",
|
|
9384
|
+
"incompatibleBadge": "s36b613_incompatibleBadge",
|
|
9385
|
+
"starsBadge": "s63d9f6_starsBadge",
|
|
9386
|
+
"chevron": "s1faef8_chevron",
|
|
9387
|
+
"chevronOpen": "s7a4b1f_chevronOpen",
|
|
9388
|
+
"body": "sc53619_body",
|
|
9389
|
+
"summary": "s617f51_summary",
|
|
9390
|
+
"summaryZh": "se22e0f_summaryZh",
|
|
9391
|
+
"summaryExpanded": "s12a8f7_summaryExpanded",
|
|
9392
|
+
"summaryZhExpanded": "sf04c34_summaryZhExpanded",
|
|
9393
|
+
"incompatibleDetail": "s8f5da6_incompatibleDetail",
|
|
9394
|
+
"remedy": "sb71cf3_remedy",
|
|
9395
|
+
"foldBlock": "se8b041_foldBlock",
|
|
9396
|
+
"foldBlockExpanded": "sd5e94d_foldBlockExpanded",
|
|
9397
|
+
"foldToggle": "sd63d48_foldToggle",
|
|
9398
|
+
"remedyLead": "s9e108c_remedyLead",
|
|
9399
|
+
"allowCommand": "s51d415_allowCommand",
|
|
9400
|
+
"refusal": "sf48b40_refusal",
|
|
9401
|
+
"capabilitiesBlock": "s24b64d_capabilitiesBlock",
|
|
9402
|
+
"capabilitiesNote": "s1cdba4_capabilitiesNote",
|
|
9403
|
+
"capabilities": "s4bc6d7_capabilities",
|
|
9404
|
+
"detail": "se00d68_detail",
|
|
9405
|
+
"detailRows": "seadb7e_detailRows",
|
|
9406
|
+
"detailRow": "s80932b_detailRow",
|
|
9407
|
+
"cardMeta": "s2c7916_cardMeta",
|
|
9408
|
+
"shelfDate": "sa2b5c4_shelfDate",
|
|
9409
|
+
"size": "s983d76_size",
|
|
9410
|
+
"author": "s787e2e_author",
|
|
9411
|
+
"reviewedLine": "se111f0_reviewedLine",
|
|
9412
|
+
"installButton": "s62735d_installButton",
|
|
9413
|
+
"confirmButton": "s53e10c_confirmButton",
|
|
9414
|
+
"cancelButton": "sd2236a_cancelButton",
|
|
9415
|
+
"installedLabel": "s9eb0bd_installedLabel",
|
|
9416
|
+
"refusedLabel": "s6c656b_refusedLabel",
|
|
9417
|
+
"uninstallButton": "sd20046_uninstallButton",
|
|
9418
|
+
"restartSelfButton": "sac213f_restartSelfButton",
|
|
9419
|
+
"restartButton": "s34ad1e_restartButton",
|
|
9420
|
+
"reloadButton": "s234464_reloadButton",
|
|
9421
|
+
"reloadPanel": "s55782e_reloadPanel",
|
|
9422
|
+
"gateTitle": "s656d08_gateTitle",
|
|
9423
|
+
"gateBody": "s83f089_gateBody",
|
|
9424
|
+
"gateWarning": "s26dca1_gateWarning",
|
|
9425
|
+
"gateActions": "sda785e_gateActions",
|
|
9426
|
+
"installing": "sf3a5fc_installing",
|
|
9427
|
+
"log": "s941e64_log",
|
|
9428
|
+
"logLine": "sc0d45c_logLine",
|
|
9429
|
+
"notice": "s2ddb67_notice",
|
|
9430
|
+
"failedHeading": "sff109f_failedHeading",
|
|
9431
|
+
"failedDetail": "sb51cd3_failedDetail",
|
|
9432
|
+
"rejectedCode": "s7287ac_rejectedCode",
|
|
9433
|
+
"rejectedDetail": "sa26465_rejectedDetail",
|
|
9434
|
+
"outdatedSection": "s438beb_outdatedSection",
|
|
9435
|
+
"outdatedList": "s6e16fa_outdatedList",
|
|
9436
|
+
"outdatedRow": "s46b13b_outdatedRow",
|
|
9437
|
+
"outdatedInfo": "sc25007_outdatedInfo",
|
|
9438
|
+
"outdatedVersions": "s1b342c_outdatedVersions",
|
|
9439
|
+
"shadowedSection": "s6eace4_shadowedSection",
|
|
9440
|
+
"shadowedDetail": "s653245_shadowedDetail",
|
|
9441
|
+
"outdatedActions": "s7d34ef_outdatedActions",
|
|
9442
|
+
"switchWrap": "sf25027_switchWrap"
|
|
9443
9443
|
};
|
|
9444
9444
|
//#endregion
|
|
9445
9445
|
//#region src/client/FoldableRedBlock.tsx
|
|
@@ -9447,13 +9447,13 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
9447
9447
|
const { rootRef, expandable, expanded, toggle } = useFoldableRedBlock();
|
|
9448
9448
|
const kindName = attrName.replace(/^data-shop-/, "");
|
|
9449
9449
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
9450
|
-
className: expanded ?
|
|
9450
|
+
className: expanded ? _dsh_plugin_shop_css_c4b688e1_default.foldBlockExpanded : _dsh_plugin_shop_css_c4b688e1_default.foldBlock,
|
|
9451
9451
|
[attrName]: true,
|
|
9452
9452
|
ref: rootRef,
|
|
9453
9453
|
children
|
|
9454
9454
|
}), expandable && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
9455
9455
|
type: "button",
|
|
9456
|
-
className:
|
|
9456
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.foldToggle,
|
|
9457
9457
|
"data-shop-fold": kindName,
|
|
9458
9458
|
"aria-expanded": expanded,
|
|
9459
9459
|
onClick: toggle,
|
|
@@ -9475,14 +9475,14 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
9475
9475
|
* those nodes, and React's next commit throws on the ones it no longer finds
|
|
9476
9476
|
* (design 2026-09-26-market-borrowings §4). The tab renders no portals, so its
|
|
9477
9477
|
* root is its whole surface. */
|
|
9478
|
-
const PANEL_ROOT = `${
|
|
9478
|
+
const PANEL_ROOT = `${_dsh_plugin_shop_css_c4b688e1_default.panel} notranslate`;
|
|
9479
9479
|
function ChevronIcon({ open }) {
|
|
9480
9480
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
|
|
9481
9481
|
viewBox: "0 0 16 16",
|
|
9482
9482
|
width: "14",
|
|
9483
9483
|
height: "14",
|
|
9484
9484
|
"aria-hidden": "true",
|
|
9485
|
-
className: open ?
|
|
9485
|
+
className: open ? _dsh_plugin_shop_css_c4b688e1_default.chevronOpen : _dsh_plugin_shop_css_c4b688e1_default.chevron,
|
|
9486
9486
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
|
|
9487
9487
|
fill: "currentColor",
|
|
9488
9488
|
d: "M3.5 6 8 10.5 12.5 6l1 1L8 12.5 2.5 7l1-1Z"
|
|
@@ -9514,32 +9514,32 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
9514
9514
|
subdir: entry.subdir
|
|
9515
9515
|
};
|
|
9516
9516
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
9517
|
-
className:
|
|
9517
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.card,
|
|
9518
9518
|
"data-shop-entry": entry.name,
|
|
9519
9519
|
"data-category": category,
|
|
9520
9520
|
children: [
|
|
9521
9521
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
9522
|
-
className:
|
|
9522
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.cardSpine,
|
|
9523
9523
|
"aria-hidden": "true"
|
|
9524
9524
|
}),
|
|
9525
9525
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
9526
9526
|
type: "button",
|
|
9527
|
-
className:
|
|
9527
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.entryHeader,
|
|
9528
9528
|
"aria-expanded": open,
|
|
9529
9529
|
"aria-controls": detailId,
|
|
9530
9530
|
onClick: () => setOpen((current) => !current),
|
|
9531
9531
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
9532
|
-
className:
|
|
9532
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.name,
|
|
9533
9533
|
children: entry.name
|
|
9534
9534
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
9535
|
-
className:
|
|
9535
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.badges,
|
|
9536
9536
|
children: [
|
|
9537
9537
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
9538
|
-
className:
|
|
9538
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.categoryBadge,
|
|
9539
9539
|
children: t(categoryKey(entry))
|
|
9540
9540
|
}),
|
|
9541
9541
|
entry.source === "npm" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
9542
|
-
className:
|
|
9542
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.sourceBadge,
|
|
9543
9543
|
"data-shop-source-npm": true,
|
|
9544
9544
|
role: "img",
|
|
9545
9545
|
"aria-label": t("npmSource"),
|
|
@@ -9556,7 +9556,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
9556
9556
|
})
|
|
9557
9557
|
}),
|
|
9558
9558
|
hasGithubHome(entry) && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
9559
|
-
className:
|
|
9559
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.sourceBadge,
|
|
9560
9560
|
"data-shop-source-github": true,
|
|
9561
9561
|
role: "img",
|
|
9562
9562
|
"aria-label": t("githubSource"),
|
|
@@ -9570,7 +9570,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
9570
9570
|
})
|
|
9571
9571
|
}),
|
|
9572
9572
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
9573
|
-
className:
|
|
9573
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.cardVersion,
|
|
9574
9574
|
"data-card-version": true,
|
|
9575
9575
|
role: "img",
|
|
9576
9576
|
"aria-label": versionName,
|
|
@@ -9578,17 +9578,17 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
9578
9578
|
children: version.text
|
|
9579
9579
|
}),
|
|
9580
9580
|
entry.tier !== "community" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
9581
|
-
className:
|
|
9581
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.tierBadge,
|
|
9582
9582
|
"data-tier": entry.tier,
|
|
9583
9583
|
children: t(tierKey(entry.tier))
|
|
9584
9584
|
}),
|
|
9585
9585
|
entry.archived === true && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
9586
|
-
className:
|
|
9586
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.tierBadge,
|
|
9587
9587
|
"data-tier": "archived",
|
|
9588
9588
|
children: t("archivedBadge")
|
|
9589
9589
|
}),
|
|
9590
9590
|
stars !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
9591
|
-
className:
|
|
9591
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.starsBadge,
|
|
9592
9592
|
role: "img",
|
|
9593
9593
|
"aria-label": t("stars", { count: stars }),
|
|
9594
9594
|
children: ["★ ", formatStars(stars)]
|
|
@@ -9598,14 +9598,14 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
9598
9598
|
})]
|
|
9599
9599
|
}),
|
|
9600
9600
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
9601
|
-
className:
|
|
9601
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.body,
|
|
9602
9602
|
children: [
|
|
9603
9603
|
summary !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
9604
|
-
className: open ? `${
|
|
9604
|
+
className: open ? `${_dsh_plugin_shop_css_c4b688e1_default.summary} ${_dsh_plugin_shop_css_c4b688e1_default.summaryExpanded}` : _dsh_plugin_shop_css_c4b688e1_default.summary,
|
|
9605
9605
|
children: summary.en
|
|
9606
9606
|
}),
|
|
9607
9607
|
summary?.zh !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
9608
|
-
className: open ? `${
|
|
9608
|
+
className: open ? `${_dsh_plugin_shop_css_c4b688e1_default.summaryZh} ${_dsh_plugin_shop_css_c4b688e1_default.summaryZhExpanded}` : _dsh_plugin_shop_css_c4b688e1_default.summaryZh,
|
|
9609
9609
|
children: summary.zh
|
|
9610
9610
|
}),
|
|
9611
9611
|
blockers.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FoldableRedBlock, {
|
|
@@ -9613,28 +9613,28 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
9613
9613
|
attrName: "data-shop-remedy",
|
|
9614
9614
|
children: blockers.map((blocker) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(BlockerLine, {
|
|
9615
9615
|
blocker,
|
|
9616
|
-
className:
|
|
9616
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.incompatibleDetail,
|
|
9617
9617
|
surface: "detail"
|
|
9618
9618
|
}, blocker.kind))
|
|
9619
9619
|
}),
|
|
9620
9620
|
open && entry.catalog !== void 0 && entry.catalog.capabilities.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
9621
|
-
className:
|
|
9621
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.capabilitiesBlock,
|
|
9622
9622
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
9623
|
-
className:
|
|
9623
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.capabilitiesNote,
|
|
9624
9624
|
children: t("capabilitiesNote")
|
|
9625
9625
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("ul", {
|
|
9626
|
-
className:
|
|
9626
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.capabilities,
|
|
9627
9627
|
children: entry.catalog.capabilities.map((capability) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", { children: capability }, capability))
|
|
9628
9628
|
})]
|
|
9629
9629
|
}),
|
|
9630
9630
|
open && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
9631
9631
|
id: detailId,
|
|
9632
|
-
className:
|
|
9632
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.detail,
|
|
9633
9633
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("dl", {
|
|
9634
|
-
className:
|
|
9634
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.detailRows,
|
|
9635
9635
|
children: [
|
|
9636
9636
|
npmUrl !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
9637
|
-
className:
|
|
9637
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.detailRow,
|
|
9638
9638
|
"data-shop-npm": true,
|
|
9639
9639
|
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", {
|
|
9640
9640
|
href: npmUrl,
|
|
@@ -9644,7 +9644,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
9644
9644
|
}) })]
|
|
9645
9645
|
}),
|
|
9646
9646
|
entry.repository !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
9647
|
-
className:
|
|
9647
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.detailRow,
|
|
9648
9648
|
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", {
|
|
9649
9649
|
href: entry.repository,
|
|
9650
9650
|
target: "_blank",
|
|
@@ -9653,12 +9653,12 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
9653
9653
|
}) : entry.repository })]
|
|
9654
9654
|
}),
|
|
9655
9655
|
entry.license !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
9656
|
-
className:
|
|
9656
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.detailRow,
|
|
9657
9657
|
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 })]
|
|
9658
9658
|
})
|
|
9659
9659
|
]
|
|
9660
9660
|
}), entry.tier === "verified-stale" && entry.review !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
9661
|
-
className:
|
|
9661
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.reviewedLine,
|
|
9662
9662
|
children: entry.review.reviewedVersion !== void 0 ? t("reviewedVersionLine", {
|
|
9663
9663
|
reviewed: versionLabel("npm", entry.review.reviewedVersion).text,
|
|
9664
9664
|
current: version.text
|
|
@@ -9671,7 +9671,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
9671
9671
|
]
|
|
9672
9672
|
}),
|
|
9673
9673
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
9674
|
-
className:
|
|
9674
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.cardActions,
|
|
9675
9675
|
"data-shop-actions": true,
|
|
9676
9676
|
children: [installed === void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [!inInstalledView && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(InstallPanel, {
|
|
9677
9677
|
target: installTarget,
|
|
@@ -9703,7 +9703,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
9703
9703
|
restartBlocked,
|
|
9704
9704
|
reload
|
|
9705
9705
|
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
9706
|
-
className:
|
|
9706
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.installedLabel,
|
|
9707
9707
|
"data-shop-installed": true,
|
|
9708
9708
|
children: t("installed")
|
|
9709
9709
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(BlockerBadge, {
|
|
@@ -9728,15 +9728,15 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
9728
9728
|
flow: uninstallFlow
|
|
9729
9729
|
})
|
|
9730
9730
|
] }), (size !== void 0 || author !== null || shelfDay !== void 0) && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
9731
|
-
className:
|
|
9731
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.cardMeta,
|
|
9732
9732
|
children: [
|
|
9733
9733
|
shelfDay !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
9734
|
-
className:
|
|
9734
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.shelfDate,
|
|
9735
9735
|
"data-shop-shelf-date": true,
|
|
9736
9736
|
children: t(order === "added" ? "listedOn" : "updatedOn", { date: shelfDay })
|
|
9737
9737
|
}),
|
|
9738
9738
|
size !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
9739
|
-
className:
|
|
9739
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.size,
|
|
9740
9740
|
"data-shop-size": true,
|
|
9741
9741
|
role: "img",
|
|
9742
9742
|
"aria-label": t("sizeLabel", { size }),
|
|
@@ -9744,7 +9744,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
9744
9744
|
children: size
|
|
9745
9745
|
}),
|
|
9746
9746
|
author !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
9747
|
-
className:
|
|
9747
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.author,
|
|
9748
9748
|
"data-shop-author": true,
|
|
9749
9749
|
children: t("authorLine", { author })
|
|
9750
9750
|
})
|
|
@@ -9794,13 +9794,13 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
9794
9794
|
...attribute,
|
|
9795
9795
|
children: blocker.text
|
|
9796
9796
|
}), blocker.remedy !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
9797
|
-
className:
|
|
9797
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.remedy,
|
|
9798
9798
|
"data-shop-remedy": blocker.kind,
|
|
9799
9799
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
9800
|
-
className:
|
|
9800
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.remedyLead,
|
|
9801
9801
|
children: blocker.remedy.lead
|
|
9802
9802
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("code", {
|
|
9803
|
-
className:
|
|
9803
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.allowCommand,
|
|
9804
9804
|
"data-shop-allow-command": true,
|
|
9805
9805
|
children: blocker.remedy.command
|
|
9806
9806
|
})]
|
|
@@ -9838,7 +9838,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
9838
9838
|
if (lead === void 0 || word === null) return null;
|
|
9839
9839
|
const detail = blockers.map((blocker) => blocker.text).join("\n");
|
|
9840
9840
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
9841
|
-
className:
|
|
9841
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.incompatibleBadge,
|
|
9842
9842
|
"data-shop-blocker": lead.kind,
|
|
9843
9843
|
role: "img",
|
|
9844
9844
|
"aria-label": detail,
|
|
@@ -9862,37 +9862,37 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
9862
9862
|
function InstallPanel({ target, tier, blockers, blockersStated = false, variant = "install", flow, t, restart, restartBlocked, reload }) {
|
|
9863
9863
|
const { view, start, starting } = flow;
|
|
9864
9864
|
if (view.kind === "running") return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
9865
|
-
className:
|
|
9865
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.installPanel,
|
|
9866
9866
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
9867
|
-
className:
|
|
9867
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.installing,
|
|
9868
9868
|
children: t(installPhaseKey(view.phase))
|
|
9869
9869
|
}), view.log.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
9870
|
-
className:
|
|
9870
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.log,
|
|
9871
9871
|
children: view.log.map((line, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
9872
|
-
className:
|
|
9872
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.logLine,
|
|
9873
9873
|
"data-shop-log-line": true,
|
|
9874
9874
|
children: line
|
|
9875
9875
|
}, index))
|
|
9876
9876
|
})]
|
|
9877
9877
|
});
|
|
9878
9878
|
if (view.kind === "done") return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
9879
|
-
className:
|
|
9879
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.installedActions,
|
|
9880
9880
|
children: [
|
|
9881
9881
|
view.log.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
9882
|
-
className:
|
|
9882
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.log,
|
|
9883
9883
|
children: view.log.map((line, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
9884
|
-
className:
|
|
9884
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.logLine,
|
|
9885
9885
|
"data-shop-log-line": true,
|
|
9886
9886
|
children: line
|
|
9887
9887
|
}, index))
|
|
9888
9888
|
}),
|
|
9889
9889
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
9890
|
-
className:
|
|
9890
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.notice,
|
|
9891
9891
|
"data-shop-restart-notice": true,
|
|
9892
9892
|
children: t(activationNoticeKey(view.activation, view.restartReason))
|
|
9893
9893
|
}),
|
|
9894
9894
|
view.detail !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
9895
|
-
className:
|
|
9895
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.notice,
|
|
9896
9896
|
"data-shop-done-note": true,
|
|
9897
9897
|
children: view.detail
|
|
9898
9898
|
}),
|
|
@@ -9907,33 +9907,33 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
9907
9907
|
]
|
|
9908
9908
|
});
|
|
9909
9909
|
if (view.kind === "failed") return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
9910
|
-
className:
|
|
9910
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.installPanel,
|
|
9911
9911
|
children: [
|
|
9912
9912
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
9913
|
-
className:
|
|
9913
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.failedHeading,
|
|
9914
9914
|
children: t("installFailed")
|
|
9915
9915
|
}),
|
|
9916
9916
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
9917
|
-
className:
|
|
9917
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.log,
|
|
9918
9918
|
children: view.log.map((line, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
9919
|
-
className:
|
|
9919
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.logLine,
|
|
9920
9920
|
"data-shop-log-line": true,
|
|
9921
9921
|
children: line
|
|
9922
9922
|
}, index))
|
|
9923
9923
|
}),
|
|
9924
9924
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
9925
|
-
className:
|
|
9925
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.failedDetail,
|
|
9926
9926
|
children: view.detail === "" ? t("installTransportFailed") : view.detail
|
|
9927
9927
|
})
|
|
9928
9928
|
]
|
|
9929
9929
|
});
|
|
9930
9930
|
if (view.kind === "rejected") return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
9931
|
-
className:
|
|
9931
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.installPanel,
|
|
9932
9932
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
9933
|
-
className:
|
|
9933
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.rejectedCode,
|
|
9934
9934
|
children: t(rejectionCodeKey(view.code))
|
|
9935
9935
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
9936
|
-
className:
|
|
9936
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.rejectedDetail,
|
|
9937
9937
|
children: view.detail
|
|
9938
9938
|
})]
|
|
9939
9939
|
});
|
|
@@ -9942,7 +9942,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
9942
9942
|
const word = blockerBadgeKey(blockers);
|
|
9943
9943
|
const detail = blockers.map((blocker) => blocker.text).join("\n");
|
|
9944
9944
|
if (refused && word !== null) return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
9945
|
-
className:
|
|
9945
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.refusedLabel,
|
|
9946
9946
|
"data-shop-refused": true,
|
|
9947
9947
|
"data-shop-blocker-kind": blockers[0]?.kind,
|
|
9948
9948
|
role: "img",
|
|
@@ -9954,14 +9954,14 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
9954
9954
|
attrName: "data-shop-refusal",
|
|
9955
9955
|
children: blockers.map((blocker) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(BlockerLine, {
|
|
9956
9956
|
blocker,
|
|
9957
|
-
className:
|
|
9957
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.gateWarning,
|
|
9958
9958
|
surface: "warning"
|
|
9959
9959
|
}, blocker.kind))
|
|
9960
9960
|
})] });
|
|
9961
9961
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
9962
9962
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
9963
9963
|
type: "button",
|
|
9964
|
-
className:
|
|
9964
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.installButton,
|
|
9965
9965
|
disabled: starting,
|
|
9966
9966
|
...update ? { "data-shop-update": true } : { "data-shop-install": true },
|
|
9967
9967
|
onClick: () => {
|
|
@@ -9981,7 +9981,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
9981
9981
|
attrName: "data-shop-blocker-lines",
|
|
9982
9982
|
children: blockers.map((blocker) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(BlockerLine, {
|
|
9983
9983
|
blocker,
|
|
9984
|
-
className:
|
|
9984
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.gateWarning,
|
|
9985
9985
|
surface: "warning"
|
|
9986
9986
|
}, blocker.kind))
|
|
9987
9987
|
})
|
|
@@ -9996,32 +9996,32 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
9996
9996
|
function UninstallPanel({ name, t, restart, restartBlocked, reload, flow }) {
|
|
9997
9997
|
const { view, start, reset } = flow;
|
|
9998
9998
|
if (view.kind === "running") return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
9999
|
-
className:
|
|
9999
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.installPanel,
|
|
10000
10000
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
10001
|
-
className:
|
|
10001
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.installing,
|
|
10002
10002
|
children: t("uninstalling")
|
|
10003
10003
|
}), view.log.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
10004
|
-
className:
|
|
10004
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.log,
|
|
10005
10005
|
children: view.log.map((line, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
10006
|
-
className:
|
|
10006
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.logLine,
|
|
10007
10007
|
"data-shop-log-line": true,
|
|
10008
10008
|
children: line
|
|
10009
10009
|
}, index))
|
|
10010
10010
|
})]
|
|
10011
10011
|
});
|
|
10012
10012
|
if (view.kind === "done") return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
10013
|
-
className:
|
|
10013
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.installedActions,
|
|
10014
10014
|
children: [
|
|
10015
10015
|
view.log.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
10016
|
-
className:
|
|
10016
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.log,
|
|
10017
10017
|
children: view.log.map((line, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
10018
|
-
className:
|
|
10018
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.logLine,
|
|
10019
10019
|
"data-shop-log-line": true,
|
|
10020
10020
|
children: line
|
|
10021
10021
|
}, index))
|
|
10022
10022
|
}),
|
|
10023
10023
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
10024
|
-
className:
|
|
10024
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.notice,
|
|
10025
10025
|
"data-shop-uninstall-done": true,
|
|
10026
10026
|
children: t(uninstallActivationNoticeKey(view.activation))
|
|
10027
10027
|
}),
|
|
@@ -10035,7 +10035,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
10035
10035
|
}),
|
|
10036
10036
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
10037
10037
|
type: "button",
|
|
10038
|
-
className:
|
|
10038
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.cancelButton,
|
|
10039
10039
|
"data-shop-uninstall-dismiss": true,
|
|
10040
10040
|
onClick: reset,
|
|
10041
10041
|
children: t("dismiss")
|
|
@@ -10043,27 +10043,27 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
10043
10043
|
]
|
|
10044
10044
|
});
|
|
10045
10045
|
if (view.kind === "failed") return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
10046
|
-
className:
|
|
10046
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.installPanel,
|
|
10047
10047
|
children: [
|
|
10048
10048
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
10049
|
-
className:
|
|
10049
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.failedHeading,
|
|
10050
10050
|
children: t("uninstallFailed")
|
|
10051
10051
|
}),
|
|
10052
10052
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
10053
|
-
className:
|
|
10053
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.log,
|
|
10054
10054
|
children: view.log.map((line, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
10055
|
-
className:
|
|
10055
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.logLine,
|
|
10056
10056
|
"data-shop-log-line": true,
|
|
10057
10057
|
children: line
|
|
10058
10058
|
}, index))
|
|
10059
10059
|
}),
|
|
10060
10060
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
10061
|
-
className:
|
|
10061
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.failedDetail,
|
|
10062
10062
|
children: view.detail === "" ? t("uninstallTransportFailed") : view.detail
|
|
10063
10063
|
}),
|
|
10064
10064
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
10065
10065
|
type: "button",
|
|
10066
|
-
className:
|
|
10066
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.uninstallButton,
|
|
10067
10067
|
"data-shop-uninstall-retry": true,
|
|
10068
10068
|
onClick: () => void start({ name }),
|
|
10069
10069
|
children: t("retry")
|
|
@@ -10073,7 +10073,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
10073
10073
|
if (view.kind !== "idle") return null;
|
|
10074
10074
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
10075
10075
|
type: "button",
|
|
10076
|
-
className:
|
|
10076
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.uninstallButton,
|
|
10077
10077
|
"data-shop-uninstall": true,
|
|
10078
10078
|
onClick: () => void start({ name }),
|
|
10079
10079
|
children: t("uninstall")
|
|
@@ -10114,39 +10114,39 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
10114
10114
|
else if (outcome.kind === "unreachable") setRefusal(t("restartTransportFailed"));
|
|
10115
10115
|
};
|
|
10116
10116
|
if (monitor?.kind === "requesting" || monitor?.kind === "restarting") return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
10117
|
-
className:
|
|
10117
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.notice,
|
|
10118
10118
|
"data-shop-restarting": true,
|
|
10119
10119
|
children: t("restarting")
|
|
10120
10120
|
});
|
|
10121
10121
|
if (monitor?.kind === "failed") return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
10122
|
-
className:
|
|
10122
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.failedDetail,
|
|
10123
10123
|
"data-shop-restart-error": true,
|
|
10124
10124
|
children: monitor.logFile === void 0 ? t("restartFailedNotice") : t("restartFailedLogNotice", { log: monitor.logFile })
|
|
10125
10125
|
});
|
|
10126
10126
|
if (monitor?.kind === "not-restarted") return null;
|
|
10127
10127
|
if (gateOpen) return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
10128
|
-
className:
|
|
10128
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.gate,
|
|
10129
10129
|
"data-shop-restart-gate": true,
|
|
10130
10130
|
children: [
|
|
10131
10131
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
10132
|
-
className:
|
|
10132
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.gateTitle,
|
|
10133
10133
|
children: t("restartTitle")
|
|
10134
10134
|
}),
|
|
10135
10135
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
10136
|
-
className:
|
|
10136
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.gateBody,
|
|
10137
10137
|
children: t("restartBody")
|
|
10138
10138
|
}),
|
|
10139
10139
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
10140
|
-
className:
|
|
10140
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.gateActions,
|
|
10141
10141
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
10142
10142
|
type: "button",
|
|
10143
|
-
className:
|
|
10143
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.confirmButton,
|
|
10144
10144
|
"data-shop-restart-confirm": true,
|
|
10145
10145
|
onClick: () => void onConfirm(),
|
|
10146
10146
|
children: t("restartConfirm")
|
|
10147
10147
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
10148
10148
|
type: "button",
|
|
10149
|
-
className:
|
|
10149
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.cancelButton,
|
|
10150
10150
|
onClick: () => setGateOpen(false),
|
|
10151
10151
|
children: t("cancel")
|
|
10152
10152
|
})]
|
|
@@ -10154,14 +10154,14 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
10154
10154
|
]
|
|
10155
10155
|
});
|
|
10156
10156
|
const refused = refusal === null ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
10157
|
-
className:
|
|
10157
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.failedDetail,
|
|
10158
10158
|
"data-shop-restart-error": true,
|
|
10159
10159
|
children: refusal
|
|
10160
10160
|
});
|
|
10161
10161
|
if (gate !== void 0) return refused;
|
|
10162
10162
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [refused, /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
10163
10163
|
type: "button",
|
|
10164
|
-
className:
|
|
10164
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.restartButton,
|
|
10165
10165
|
"data-shop-restart": true,
|
|
10166
10166
|
onClick: () => setGateOpen(true),
|
|
10167
10167
|
children: t("restart")
|
|
@@ -10179,13 +10179,13 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
10179
10179
|
*/
|
|
10180
10180
|
function NotRestartedNotice({ t, pid, logFile }) {
|
|
10181
10181
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
10182
|
-
className:
|
|
10182
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.selfUpdatePanel,
|
|
10183
10183
|
"data-shop-not-restarted": true,
|
|
10184
10184
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
10185
|
-
className:
|
|
10185
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.failedDetail,
|
|
10186
10186
|
children: pid === void 0 ? t("notRestartedNotice") : t("notRestartedPidNotice", { pid: String(pid) })
|
|
10187
10187
|
}), logFile !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
10188
|
-
className:
|
|
10188
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.failedDetail,
|
|
10189
10189
|
children: t("notRestartedLogNotice", { log: logFile })
|
|
10190
10190
|
})]
|
|
10191
10191
|
});
|
|
@@ -10215,7 +10215,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
10215
10215
|
restart,
|
|
10216
10216
|
reload
|
|
10217
10217
|
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
10218
|
-
className:
|
|
10218
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.notice,
|
|
10219
10219
|
"data-shop-restart-disabled": true,
|
|
10220
10220
|
children: t(restartBlockedNoticeKey(restartBlocked))
|
|
10221
10221
|
});
|
|
@@ -10226,14 +10226,14 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
10226
10226
|
* would help without knowing that now is a good time. */
|
|
10227
10227
|
function ReloadPanel({ t, reload, where }) {
|
|
10228
10228
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
10229
|
-
className:
|
|
10229
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.reloadPanel,
|
|
10230
10230
|
"data-shop-reload": where,
|
|
10231
10231
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
10232
|
-
className:
|
|
10232
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.notice,
|
|
10233
10233
|
children: t("reloadNote")
|
|
10234
10234
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
10235
10235
|
type: "button",
|
|
10236
|
-
className:
|
|
10236
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.reloadButton,
|
|
10237
10237
|
onClick: reload,
|
|
10238
10238
|
children: t("reload")
|
|
10239
10239
|
})]
|
|
@@ -10284,7 +10284,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
10284
10284
|
}
|
|
10285
10285
|
};
|
|
10286
10286
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
10287
|
-
className:
|
|
10287
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.switchWrap,
|
|
10288
10288
|
"data-shop-enabled-switch": row.name,
|
|
10289
10289
|
children: [
|
|
10290
10290
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
@@ -10293,18 +10293,18 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
10293
10293
|
"aria-checked": enabled,
|
|
10294
10294
|
"aria-label": t("enabledSwitch"),
|
|
10295
10295
|
"data-shop-toggle": true,
|
|
10296
|
-
className: `${
|
|
10296
|
+
className: `${_dsh_plugin_shop_css_c4b688e1_default.switch} ${enabled ? _dsh_plugin_shop_css_c4b688e1_default.switchOn : ""}`,
|
|
10297
10297
|
onClick: () => void onToggle(),
|
|
10298
10298
|
disabled: toggle.kind === "saving",
|
|
10299
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className:
|
|
10299
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: _dsh_plugin_shop_css_c4b688e1_default.switchKnob })
|
|
10300
10300
|
}),
|
|
10301
10301
|
toggle.kind === "saved" && owed === "nothing" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
10302
|
-
className:
|
|
10302
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.notice,
|
|
10303
10303
|
"data-shop-hot-apply": true,
|
|
10304
10304
|
children: t("hotApplyNote")
|
|
10305
10305
|
}),
|
|
10306
10306
|
owed === "restart" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
10307
|
-
className:
|
|
10307
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.notice,
|
|
10308
10308
|
"data-shop-toggle-restart": true,
|
|
10309
10309
|
children: t("toggleRestartNote")
|
|
10310
10310
|
}),
|
|
@@ -10317,7 +10317,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
10317
10317
|
where: "toggle"
|
|
10318
10318
|
}),
|
|
10319
10319
|
toggle.kind === "error" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
10320
|
-
className:
|
|
10320
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.failedDetail,
|
|
10321
10321
|
"data-shop-toggle-error": true,
|
|
10322
10322
|
children: toggle.detail
|
|
10323
10323
|
})
|
|
@@ -10332,19 +10332,19 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
10332
10332
|
* field is narrowed at the parameter. */
|
|
10333
10333
|
function OutdatedRow({ row, tier, missing, harness, t, setEnabled, flowFor, restart, restartBlocked, reload, restarts }) {
|
|
10334
10334
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
10335
|
-
className:
|
|
10335
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.outdatedRow,
|
|
10336
10336
|
"data-shop-outdated-entry": row.name,
|
|
10337
10337
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
10338
|
-
className:
|
|
10338
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.outdatedInfo,
|
|
10339
10339
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
10340
|
-
className:
|
|
10340
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.name,
|
|
10341
10341
|
children: row.name
|
|
10342
10342
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
10343
|
-
className:
|
|
10343
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.outdatedVersions,
|
|
10344
10344
|
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 }) })]
|
|
10345
10345
|
})]
|
|
10346
10346
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
10347
|
-
className:
|
|
10347
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.outdatedActions,
|
|
10348
10348
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(EnabledSwitch, {
|
|
10349
10349
|
row,
|
|
10350
10350
|
t,
|
|
@@ -10395,22 +10395,22 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
10395
10395
|
function OutdatedSection({ state, entriesByKey, missingByKey, harnessVerdicts, t, setEnabled, flowFor, restart, restartBlocked, reload, restarts }) {
|
|
10396
10396
|
if (state.kind === "loading") return null;
|
|
10397
10397
|
if (state.kind === "error") return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
10398
|
-
className:
|
|
10398
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.stateLine,
|
|
10399
10399
|
"data-shop-outdated-error": true,
|
|
10400
10400
|
children: t("installedError")
|
|
10401
10401
|
});
|
|
10402
10402
|
const outdated = state.entries.filter((entry) => entry.outdated && entry.latest !== null);
|
|
10403
10403
|
if (outdated.length === 0) return null;
|
|
10404
10404
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
10405
|
-
className:
|
|
10405
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.outdatedSection,
|
|
10406
10406
|
"data-shop-outdated": true,
|
|
10407
10407
|
"aria-labelledby": UPDATABLE_HEADING_ID,
|
|
10408
10408
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h2", {
|
|
10409
|
-
className:
|
|
10409
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.updatableHeading,
|
|
10410
10410
|
id: UPDATABLE_HEADING_ID,
|
|
10411
10411
|
children: t("updatableSection")
|
|
10412
10412
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("ul", {
|
|
10413
|
-
className:
|
|
10413
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.outdatedList,
|
|
10414
10414
|
children: outdated.map((row) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(OutdatedRow, {
|
|
10415
10415
|
row,
|
|
10416
10416
|
tier: entriesByKey.get(identityKey(row))?.tier ?? "community",
|
|
@@ -10438,37 +10438,37 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
10438
10438
|
const shadowed = entries.filter((entry) => entry.shadowed === true);
|
|
10439
10439
|
if (shadowed.length === 0) return null;
|
|
10440
10440
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("section", {
|
|
10441
|
-
className:
|
|
10441
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.shadowedSection,
|
|
10442
10442
|
"data-shop-shadowed": true,
|
|
10443
10443
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("ul", {
|
|
10444
|
-
className:
|
|
10444
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.outdatedList,
|
|
10445
10445
|
children: shadowed.map((row) => {
|
|
10446
10446
|
const key = identityKey(row);
|
|
10447
10447
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
10448
|
-
className:
|
|
10448
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.outdatedRow,
|
|
10449
10449
|
"data-shop-shadowed-entry": row.name,
|
|
10450
10450
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
10451
|
-
className:
|
|
10451
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.outdatedInfo,
|
|
10452
10452
|
children: [
|
|
10453
10453
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
10454
|
-
className:
|
|
10454
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.name,
|
|
10455
10455
|
children: row.name
|
|
10456
10456
|
}),
|
|
10457
10457
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
10458
|
-
className:
|
|
10458
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.badges,
|
|
10459
10459
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
10460
|
-
className:
|
|
10460
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.tierBadge,
|
|
10461
10461
|
"data-tier": "shadowed",
|
|
10462
10462
|
children: t("shadowedBadge")
|
|
10463
10463
|
})
|
|
10464
10464
|
}),
|
|
10465
10465
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
10466
|
-
className:
|
|
10466
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.shadowedDetail,
|
|
10467
10467
|
children: t("shadowedDetail")
|
|
10468
10468
|
})
|
|
10469
10469
|
]
|
|
10470
10470
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
10471
|
-
className:
|
|
10471
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.outdatedActions,
|
|
10472
10472
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(UninstallPanel, {
|
|
10473
10473
|
name: row.name,
|
|
10474
10474
|
t,
|
|
@@ -10518,16 +10518,16 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
10518
10518
|
role: "alert",
|
|
10519
10519
|
children: [
|
|
10520
10520
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
10521
|
-
className:
|
|
10521
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.stateLine,
|
|
10522
10522
|
children: say("tabCrashed", en.tabCrashed)
|
|
10523
10523
|
}),
|
|
10524
10524
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
10525
|
-
className:
|
|
10525
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.failedDetail,
|
|
10526
10526
|
children: error.message
|
|
10527
10527
|
}),
|
|
10528
10528
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
10529
10529
|
type: "button",
|
|
10530
|
-
className:
|
|
10530
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.actionButton,
|
|
10531
10531
|
onClick: () => this.setState({ error: null }),
|
|
10532
10532
|
children: say("retry", en.retry)
|
|
10533
10533
|
})
|
|
@@ -10825,19 +10825,19 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
10825
10825
|
"data-shop-tab": true,
|
|
10826
10826
|
"aria-busy": "true",
|
|
10827
10827
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
10828
|
-
className:
|
|
10828
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.srOnly,
|
|
10829
10829
|
children: t("loading")
|
|
10830
10830
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
10831
|
-
className:
|
|
10831
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.skeletonGrid,
|
|
10832
10832
|
"data-shop-skeleton": true,
|
|
10833
10833
|
"aria-hidden": "true",
|
|
10834
10834
|
children: Array.from({ length: 8 }, (_, i) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
10835
|
-
className:
|
|
10835
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.skeletonCard,
|
|
10836
10836
|
children: [
|
|
10837
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className:
|
|
10838
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className:
|
|
10839
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className:
|
|
10840
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className:
|
|
10837
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: _dsh_plugin_shop_css_c4b688e1_default.skeletonName }),
|
|
10838
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: _dsh_plugin_shop_css_c4b688e1_default.skeletonSummary }),
|
|
10839
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: _dsh_plugin_shop_css_c4b688e1_default.skeletonSummaryShort }),
|
|
10840
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: _dsh_plugin_shop_css_c4b688e1_default.skeletonActions })
|
|
10841
10841
|
]
|
|
10842
10842
|
}, i))
|
|
10843
10843
|
})]
|
|
@@ -10847,11 +10847,11 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
10847
10847
|
translate: "no",
|
|
10848
10848
|
"data-shop-tab": true,
|
|
10849
10849
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
10850
|
-
className:
|
|
10850
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.stateLine,
|
|
10851
10851
|
children: t("error")
|
|
10852
10852
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
10853
10853
|
type: "button",
|
|
10854
|
-
className:
|
|
10854
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.actionButton,
|
|
10855
10855
|
onClick: () => {
|
|
10856
10856
|
setRequest({ kind: "retry" });
|
|
10857
10857
|
setVersionReload((current) => current + 1);
|
|
@@ -10866,11 +10866,11 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
10866
10866
|
"data-shop-tab": true,
|
|
10867
10867
|
children: [
|
|
10868
10868
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
10869
|
-
className:
|
|
10869
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.toolbar,
|
|
10870
10870
|
children: [
|
|
10871
10871
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
10872
10872
|
type: "search",
|
|
10873
|
-
className:
|
|
10873
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.searchInput,
|
|
10874
10874
|
"aria-label": t("search"),
|
|
10875
10875
|
placeholder: t("search"),
|
|
10876
10876
|
value: query,
|
|
@@ -10881,31 +10881,31 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
10881
10881
|
}),
|
|
10882
10882
|
expansionMemo.intents.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
10883
10883
|
"data-shop-expansion-note": true,
|
|
10884
|
-
className:
|
|
10884
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.expansionNote,
|
|
10885
10885
|
children: t("zhExpansionNote", { terms: expansionMemo.terms.slice(1).map((term) => term.startsWith("#") ? term.slice(1) : term).join(", ") })
|
|
10886
10886
|
}),
|
|
10887
10887
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
10888
|
-
className:
|
|
10888
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.toolbarRight,
|
|
10889
10889
|
children: [
|
|
10890
10890
|
result.stale && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
10891
|
-
className:
|
|
10891
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.staleBadge,
|
|
10892
10892
|
children: t("staleLabel", { date: result.builtAt.slice(0, 10) })
|
|
10893
10893
|
}),
|
|
10894
10894
|
selfVersion !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
10895
|
-
className:
|
|
10895
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.versionBlock,
|
|
10896
10896
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
10897
|
-
className:
|
|
10897
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.versionText,
|
|
10898
10898
|
"data-shop-version": true,
|
|
10899
10899
|
children: ["v", selfVersion.installed]
|
|
10900
10900
|
}), restartMonitor !== null ? null : selfPending && restartBlocked === null ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
10901
10901
|
type: "button",
|
|
10902
|
-
className:
|
|
10902
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.restartSelfButton,
|
|
10903
10903
|
"data-shop-restart": true,
|
|
10904
10904
|
onClick: () => setSelfRestartGate(true),
|
|
10905
10905
|
children: t("restart")
|
|
10906
10906
|
}) : !selfPending && selfVersion.outdated && selfVersion.latest !== null && selfUpdate.view.kind === "idle" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
10907
10907
|
type: "button",
|
|
10908
|
-
className:
|
|
10908
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.updateSelfButton,
|
|
10909
10909
|
"data-shop-update-self": true,
|
|
10910
10910
|
onClick: () => {
|
|
10911
10911
|
if (selfVersion.latest !== null) selfUpdate.start({ version: selfVersion.latest });
|
|
@@ -10913,7 +10913,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
10913
10913
|
children: t("update")
|
|
10914
10914
|
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
10915
10915
|
type: "button",
|
|
10916
|
-
className:
|
|
10916
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.checkUpdateButton,
|
|
10917
10917
|
"data-shop-check-update": true,
|
|
10918
10918
|
title: t("checkUpdateTitle"),
|
|
10919
10919
|
disabled: checkState !== "idle",
|
|
@@ -10922,7 +10922,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
10922
10922
|
})]
|
|
10923
10923
|
}),
|
|
10924
10924
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", {
|
|
10925
|
-
className:
|
|
10925
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.githubLink,
|
|
10926
10926
|
href: SHOP_REPO_URL,
|
|
10927
10927
|
target: "_blank",
|
|
10928
10928
|
rel: "noopener noreferrer",
|
|
@@ -10947,28 +10947,28 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
10947
10947
|
logFile: restartMonitor.logFile
|
|
10948
10948
|
}),
|
|
10949
10949
|
selfUpdate.view.kind === "running" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
10950
|
-
className:
|
|
10950
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.selfUpdatePanel,
|
|
10951
10951
|
"data-shop-self-updating": true,
|
|
10952
10952
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
10953
|
-
className:
|
|
10953
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.installing,
|
|
10954
10954
|
children: t(installPhaseKey(selfUpdate.view.phase))
|
|
10955
10955
|
}), selfUpdate.view.log.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
10956
|
-
className:
|
|
10956
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.log,
|
|
10957
10957
|
children: selfUpdate.view.log.map((line, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
10958
|
-
className:
|
|
10958
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.logLine,
|
|
10959
10959
|
"data-shop-log-line": true,
|
|
10960
10960
|
children: line
|
|
10961
10961
|
}, index))
|
|
10962
10962
|
})]
|
|
10963
10963
|
}),
|
|
10964
10964
|
selfPending && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
10965
|
-
className:
|
|
10965
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.selfUpdatePanel,
|
|
10966
10966
|
"data-shop-self-update-done": true,
|
|
10967
10967
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
10968
|
-
className:
|
|
10968
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.installedActions,
|
|
10969
10969
|
children: [
|
|
10970
10970
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
10971
|
-
className:
|
|
10971
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.notice,
|
|
10972
10972
|
children: t("installedRestartNotice")
|
|
10973
10973
|
}),
|
|
10974
10974
|
restartBlocked === null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RestartPanel, {
|
|
@@ -10981,7 +10981,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
10981
10981
|
}
|
|
10982
10982
|
}),
|
|
10983
10983
|
restartBlocked !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
10984
|
-
className:
|
|
10984
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.notice,
|
|
10985
10985
|
"data-shop-restart-disabled": true,
|
|
10986
10986
|
children: t(restartBlockedNoticeKey(restartBlocked))
|
|
10987
10987
|
})
|
|
@@ -10989,35 +10989,35 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
10989
10989
|
})
|
|
10990
10990
|
}),
|
|
10991
10991
|
selfUpdate.view.kind === "failed" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
10992
|
-
className:
|
|
10992
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.selfUpdatePanel,
|
|
10993
10993
|
"data-shop-self-update-failed": true,
|
|
10994
10994
|
children: [
|
|
10995
10995
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
10996
|
-
className:
|
|
10996
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.failedHeading,
|
|
10997
10997
|
children: t("updateFailed")
|
|
10998
10998
|
}),
|
|
10999
10999
|
selfUpdate.view.log.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
11000
|
-
className:
|
|
11000
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.log,
|
|
11001
11001
|
children: selfUpdate.view.log.map((line, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
11002
|
-
className:
|
|
11002
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.logLine,
|
|
11003
11003
|
"data-shop-log-line": true,
|
|
11004
11004
|
children: line
|
|
11005
11005
|
}, index))
|
|
11006
11006
|
}),
|
|
11007
11007
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
11008
|
-
className:
|
|
11008
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.failedDetail,
|
|
11009
11009
|
children: selfUpdate.view.detail === "" ? t("updateTransportFailed") : selfUpdate.view.detail
|
|
11010
11010
|
})
|
|
11011
11011
|
]
|
|
11012
11012
|
}),
|
|
11013
11013
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
11014
|
-
className:
|
|
11014
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.categoryBar,
|
|
11015
11015
|
role: "group",
|
|
11016
11016
|
"aria-label": t("catalog"),
|
|
11017
11017
|
children: [
|
|
11018
11018
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
11019
11019
|
type: "button",
|
|
11020
|
-
className: category === null ? `${
|
|
11020
|
+
className: category === null ? `${_dsh_plugin_shop_css_c4b688e1_default.categoryButton} ${_dsh_plugin_shop_css_c4b688e1_default.categoryButtonOn}` : _dsh_plugin_shop_css_c4b688e1_default.categoryButton,
|
|
11021
11021
|
"aria-pressed": category === null,
|
|
11022
11022
|
onClick: () => {
|
|
11023
11023
|
setCategory(null);
|
|
@@ -11032,7 +11032,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
11032
11032
|
}),
|
|
11033
11033
|
CATEGORY_ORDER.map((key) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
11034
11034
|
type: "button",
|
|
11035
|
-
className: category === key ? `${
|
|
11035
|
+
className: category === key ? `${_dsh_plugin_shop_css_c4b688e1_default.categoryButton} ${_dsh_plugin_shop_css_c4b688e1_default.categoryButtonOn}` : _dsh_plugin_shop_css_c4b688e1_default.categoryButton,
|
|
11036
11036
|
"aria-pressed": category === key,
|
|
11037
11037
|
"data-category": key,
|
|
11038
11038
|
"data-shop-category-tab": key,
|
|
@@ -11048,7 +11048,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
11048
11048
|
}, key)),
|
|
11049
11049
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
11050
11050
|
type: "button",
|
|
11051
|
-
className: category === "installed" ? `${
|
|
11051
|
+
className: category === "installed" ? `${_dsh_plugin_shop_css_c4b688e1_default.categoryButton} ${_dsh_plugin_shop_css_c4b688e1_default.categoryButtonOn}` : _dsh_plugin_shop_css_c4b688e1_default.categoryButton,
|
|
11052
11052
|
"aria-pressed": category === "installed",
|
|
11053
11053
|
"data-shop-category-installed": true,
|
|
11054
11054
|
onClick: () => {
|
|
@@ -11065,7 +11065,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
11065
11065
|
type: "button",
|
|
11066
11066
|
role: "switch",
|
|
11067
11067
|
"aria-checked": hideIncompatible,
|
|
11068
|
-
className: hideIncompatible ? `${
|
|
11068
|
+
className: hideIncompatible ? `${_dsh_plugin_shop_css_c4b688e1_default.incompatibleFilter} ${_dsh_plugin_shop_css_c4b688e1_default.incompatibleFilterOn}` : _dsh_plugin_shop_css_c4b688e1_default.incompatibleFilter,
|
|
11069
11069
|
title: t(hideIncompatible ? "showIncompatibleTitle" : "incompatibleFilterTitle"),
|
|
11070
11070
|
"data-shop-hide-incompatible": true,
|
|
11071
11071
|
onClick: () => {
|
|
@@ -11073,18 +11073,18 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
11073
11073
|
setVisibleCount(48);
|
|
11074
11074
|
},
|
|
11075
11075
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
11076
|
-
className: hideIncompatible ? `${
|
|
11076
|
+
className: hideIncompatible ? `${_dsh_plugin_shop_css_c4b688e1_default.switch} ${_dsh_plugin_shop_css_c4b688e1_default.switchOn}` : _dsh_plugin_shop_css_c4b688e1_default.switch,
|
|
11077
11077
|
"aria-hidden": "true",
|
|
11078
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className:
|
|
11078
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: _dsh_plugin_shop_css_c4b688e1_default.switchKnob })
|
|
11079
11079
|
}), t("hideIncompatible", { count: incompatibleCount })]
|
|
11080
11080
|
})
|
|
11081
11081
|
]
|
|
11082
11082
|
}),
|
|
11083
11083
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
11084
|
-
className:
|
|
11084
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.catalogStatsRow,
|
|
11085
11085
|
children: [
|
|
11086
11086
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
11087
|
-
className:
|
|
11087
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.catalogStats,
|
|
11088
11088
|
"data-shop-catalog-stats": true,
|
|
11089
11089
|
children: t("catalogStats", {
|
|
11090
11090
|
count: String(browsable.length),
|
|
@@ -11093,7 +11093,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
11093
11093
|
}),
|
|
11094
11094
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
11095
11095
|
type: "button",
|
|
11096
|
-
className:
|
|
11096
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.catalogRefreshButton,
|
|
11097
11097
|
"data-shop-catalog-refresh": true,
|
|
11098
11098
|
disabled: reloading,
|
|
11099
11099
|
onClick: () => {
|
|
@@ -11105,22 +11105,22 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
11105
11105
|
children: reloading ? t("refreshing") : t("refresh")
|
|
11106
11106
|
}),
|
|
11107
11107
|
reloadFailed && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
11108
|
-
className:
|
|
11108
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.catalogRefreshFailed,
|
|
11109
11109
|
"data-shop-catalog-refresh-failed": true,
|
|
11110
11110
|
children: t("refreshFailed")
|
|
11111
11111
|
}),
|
|
11112
11112
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
11113
|
-
className:
|
|
11113
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.sortGroup,
|
|
11114
11114
|
role: "group",
|
|
11115
11115
|
"aria-labelledby": sortLabelId,
|
|
11116
11116
|
"data-shop-sort": true,
|
|
11117
11117
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
11118
|
-
className:
|
|
11118
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.sortLabel,
|
|
11119
11119
|
id: sortLabelId,
|
|
11120
11120
|
children: t("sortLabel")
|
|
11121
11121
|
}), SHELF_ORDERS.map((name) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
11122
11122
|
type: "button",
|
|
11123
|
-
className: order === name ? `${
|
|
11123
|
+
className: order === name ? `${_dsh_plugin_shop_css_c4b688e1_default.categoryButton} ${_dsh_plugin_shop_css_c4b688e1_default.categoryButtonOn}` : _dsh_plugin_shop_css_c4b688e1_default.categoryButton,
|
|
11124
11124
|
"aria-pressed": order === name,
|
|
11125
11125
|
"data-shop-order": name,
|
|
11126
11126
|
onClick: () => {
|
|
@@ -11133,14 +11133,14 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
11133
11133
|
]
|
|
11134
11134
|
}),
|
|
11135
11135
|
result.plugins.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
11136
|
-
className:
|
|
11136
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.emptyLine,
|
|
11137
11137
|
children: t("empty")
|
|
11138
11138
|
}) : filtered.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
11139
|
-
className:
|
|
11139
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.emptyLine,
|
|
11140
11140
|
"data-shop-empty": true,
|
|
11141
11141
|
children: matched.length > 0 ? t("emptyIncompatibleFiltered") : t("emptySearch")
|
|
11142
11142
|
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("ul", {
|
|
11143
|
-
className:
|
|
11143
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.cards,
|
|
11144
11144
|
children: [visible.map((entry) => {
|
|
11145
11145
|
const key = entryKey(entry);
|
|
11146
11146
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(EntryCard, {
|
|
@@ -11164,12 +11164,12 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
11164
11164
|
}) }, key);
|
|
11165
11165
|
}), incremental && visibleCount < filtered.length && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", {
|
|
11166
11166
|
ref: sentinelRef,
|
|
11167
|
-
className:
|
|
11167
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.cardsSentry,
|
|
11168
11168
|
"data-shop-sentry": true,
|
|
11169
11169
|
"aria-hidden": "true"
|
|
11170
11170
|
})]
|
|
11171
11171
|
}), incremental && visibleCount < filtered.length && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
11172
|
-
className:
|
|
11172
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.showingLine,
|
|
11173
11173
|
"aria-live": "polite",
|
|
11174
11174
|
children: t("showing", {
|
|
11175
11175
|
shown: String(visibleCount),
|
|
@@ -11204,15 +11204,15 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
11204
11204
|
//#region src/client/ShopSection.tsx
|
|
11205
11205
|
function ShopSection(props) {
|
|
11206
11206
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
11207
|
-
className:
|
|
11207
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.section,
|
|
11208
11208
|
children: [
|
|
11209
11209
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h2", {
|
|
11210
|
-
className:
|
|
11210
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.sectionTitle,
|
|
11211
11211
|
"data-shop-section-title": true,
|
|
11212
11212
|
children: props.t("title")
|
|
11213
11213
|
}),
|
|
11214
11214
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
11215
|
-
className:
|
|
11215
|
+
className: _dsh_plugin_shop_css_c4b688e1_default.sectionIntro,
|
|
11216
11216
|
"data-shop-section-intro": true,
|
|
11217
11217
|
children: props.t("intro")
|
|
11218
11218
|
}),
|