dsh-plugin-shop 0.1.4 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +16 -6
- package/cordis.patch.yml +4 -4
- package/lib/client.js +288 -243
- package/lib/index.js +13 -13
- package/lib/typert.host.js +63 -63
- package/lib/typert.remote-client.d.ts +13 -13
- package/lib/typert.remote-client.js +41 -41
- package/lib/types/client/{StoreTab.d.ts → ShopTab.d.ts} +11 -11
- package/lib/types/client/index.d.ts +12 -12
- package/lib/types/client/locales.d.ts +5 -3
- package/lib/types/client/present.d.ts +19 -11
- package/lib/types/client/useInstall.d.ts +3 -3
- package/lib/types/host/executor.d.ts +1 -1
- package/lib/types/host/index.d.ts +22 -22
- package/lib/types/host/types.d.ts +1 -1
- package/lib/types/index.d.ts +2 -2
- package/package.json +3 -3
package/lib/client.js
CHANGED
|
@@ -4093,12 +4093,12 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
4093
4093
|
}
|
|
4094
4094
|
//#endregion
|
|
4095
4095
|
//#region lib/typert.remote-client.js
|
|
4096
|
-
const
|
|
4096
|
+
const dsh_plugin_shop_shop_catalog_parameter_0$schema = union([_undefined(), object({ "refresh": union([
|
|
4097
4097
|
_undefined(),
|
|
4098
4098
|
literal(false),
|
|
4099
4099
|
literal(true)
|
|
4100
4100
|
]).optional() })]);
|
|
4101
|
-
const
|
|
4101
|
+
const dsh_plugin_shop_shop_catalog_result$schema = object({
|
|
4102
4102
|
"schemaVersion": number(),
|
|
4103
4103
|
"builtAt": string(),
|
|
4104
4104
|
"stale": boolean(),
|
|
@@ -4142,7 +4142,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
4142
4142
|
"detail": string()
|
|
4143
4143
|
}))
|
|
4144
4144
|
});
|
|
4145
|
-
const
|
|
4145
|
+
const dsh_plugin_shop_shop_installStart_parameter_0$schema = object({
|
|
4146
4146
|
"name": string(),
|
|
4147
4147
|
"version": string(),
|
|
4148
4148
|
"acknowledged": union([
|
|
@@ -4151,7 +4151,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
4151
4151
|
literal(true)
|
|
4152
4152
|
]).optional()
|
|
4153
4153
|
});
|
|
4154
|
-
const
|
|
4154
|
+
const dsh_plugin_shop_shop_installStart_result$schema = union([object({
|
|
4155
4155
|
"ok": literal(true),
|
|
4156
4156
|
"installId": string()
|
|
4157
4157
|
}), object({
|
|
@@ -4164,8 +4164,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
4164
4164
|
]),
|
|
4165
4165
|
"detail": string()
|
|
4166
4166
|
})]);
|
|
4167
|
-
const
|
|
4168
|
-
const
|
|
4167
|
+
const dsh_plugin_shop_shop_installStatus_parameter_0$schema = object({ "installId": string() });
|
|
4168
|
+
const dsh_plugin_shop_shop_installStatus_result$schema = object({
|
|
4169
4169
|
"found": boolean(),
|
|
4170
4170
|
"state": union([
|
|
4171
4171
|
literal("running"),
|
|
@@ -4180,16 +4180,16 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
4180
4180
|
]).optional(),
|
|
4181
4181
|
"detail": union([_undefined(), string()]).optional()
|
|
4182
4182
|
});
|
|
4183
|
-
const
|
|
4183
|
+
const dsh_plugin_shop_shop_outdated_result$schema = array(object({
|
|
4184
4184
|
"name": string(),
|
|
4185
4185
|
"installed": string(),
|
|
4186
4186
|
"latest": string()
|
|
4187
4187
|
}));
|
|
4188
|
-
const
|
|
4188
|
+
const dsh_plugin_shop_shop_setEnabled_parameter_0$schema = object({
|
|
4189
4189
|
"name": string(),
|
|
4190
4190
|
"enabled": boolean()
|
|
4191
4191
|
});
|
|
4192
|
-
const
|
|
4192
|
+
const dsh_plugin_shop_shop_setEnabled_result$schema = object({
|
|
4193
4193
|
"ok": boolean(),
|
|
4194
4194
|
"detail": union([_undefined(), string()]).optional()
|
|
4195
4195
|
});
|
|
@@ -4197,9 +4197,9 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
4197
4197
|
package: "dsh-plugin-shop",
|
|
4198
4198
|
descriptors: [
|
|
4199
4199
|
{
|
|
4200
|
-
id: "dsh-plugin-shop#
|
|
4201
|
-
service: "
|
|
4202
|
-
namespace: "
|
|
4200
|
+
id: "dsh-plugin-shop#shop/catalog",
|
|
4201
|
+
service: "shop",
|
|
4202
|
+
namespace: "shop",
|
|
4203
4203
|
method: "catalog",
|
|
4204
4204
|
invocation: { kind: "direct" },
|
|
4205
4205
|
parameters: [{
|
|
@@ -4209,14 +4209,14 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
4209
4209
|
acceptsUndefined: true,
|
|
4210
4210
|
codec: {
|
|
4211
4211
|
mode: "strict",
|
|
4212
|
-
typeSymbol: "dsh-plugin-shop#
|
|
4213
|
-
schema:
|
|
4212
|
+
typeSymbol: "dsh-plugin-shop#shop/catalog:args",
|
|
4213
|
+
schema: dsh_plugin_shop_shop_catalog_parameter_0$schema
|
|
4214
4214
|
}
|
|
4215
4215
|
}],
|
|
4216
4216
|
result: {
|
|
4217
4217
|
mode: "strict",
|
|
4218
|
-
typeSymbol: "dsh-plugin-shop/types#
|
|
4219
|
-
schema:
|
|
4218
|
+
typeSymbol: "dsh-plugin-shop/types#ShopCatalogResult",
|
|
4219
|
+
schema: dsh_plugin_shop_shop_catalog_result$schema
|
|
4220
4220
|
},
|
|
4221
4221
|
sourceLocation: {
|
|
4222
4222
|
"file": "packages/dsh-plugin-shop/src/host/index.ts",
|
|
@@ -4225,9 +4225,9 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
4225
4225
|
}
|
|
4226
4226
|
},
|
|
4227
4227
|
{
|
|
4228
|
-
id: "dsh-plugin-shop#
|
|
4229
|
-
service: "
|
|
4230
|
-
namespace: "
|
|
4228
|
+
id: "dsh-plugin-shop#shop/installStart",
|
|
4229
|
+
service: "shop",
|
|
4230
|
+
namespace: "shop",
|
|
4231
4231
|
method: "installStart",
|
|
4232
4232
|
implementation: "install",
|
|
4233
4233
|
invocation: { kind: "direct" },
|
|
@@ -4238,13 +4238,13 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
4238
4238
|
codec: {
|
|
4239
4239
|
mode: "strict",
|
|
4240
4240
|
typeSymbol: "dsh-plugin-shop/types#InstallArgs",
|
|
4241
|
-
schema:
|
|
4241
|
+
schema: dsh_plugin_shop_shop_installStart_parameter_0$schema
|
|
4242
4242
|
}
|
|
4243
4243
|
}],
|
|
4244
4244
|
result: {
|
|
4245
4245
|
mode: "strict",
|
|
4246
|
-
typeSymbol: "dsh-plugin-shop/types#
|
|
4247
|
-
schema:
|
|
4246
|
+
typeSymbol: "dsh-plugin-shop/types#ShopInstallResult",
|
|
4247
|
+
schema: dsh_plugin_shop_shop_installStart_result$schema
|
|
4248
4248
|
},
|
|
4249
4249
|
sourceLocation: {
|
|
4250
4250
|
"file": "packages/dsh-plugin-shop/src/host/index.ts",
|
|
@@ -4253,9 +4253,9 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
4253
4253
|
}
|
|
4254
4254
|
},
|
|
4255
4255
|
{
|
|
4256
|
-
id: "dsh-plugin-shop#
|
|
4257
|
-
service: "
|
|
4258
|
-
namespace: "
|
|
4256
|
+
id: "dsh-plugin-shop#shop/installStatus",
|
|
4257
|
+
service: "shop",
|
|
4258
|
+
namespace: "shop",
|
|
4259
4259
|
method: "installStatus",
|
|
4260
4260
|
invocation: { kind: "direct" },
|
|
4261
4261
|
parameters: [{
|
|
@@ -4264,14 +4264,14 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
4264
4264
|
source: "json",
|
|
4265
4265
|
codec: {
|
|
4266
4266
|
mode: "strict",
|
|
4267
|
-
typeSymbol: "dsh-plugin-shop#
|
|
4268
|
-
schema:
|
|
4267
|
+
typeSymbol: "dsh-plugin-shop#shop/installStatus:args",
|
|
4268
|
+
schema: dsh_plugin_shop_shop_installStatus_parameter_0$schema
|
|
4269
4269
|
}
|
|
4270
4270
|
}],
|
|
4271
4271
|
result: {
|
|
4272
4272
|
mode: "strict",
|
|
4273
|
-
typeSymbol: "dsh-plugin-shop/types#
|
|
4274
|
-
schema:
|
|
4273
|
+
typeSymbol: "dsh-plugin-shop/types#ShopInstallStatusResult",
|
|
4274
|
+
schema: dsh_plugin_shop_shop_installStatus_result$schema
|
|
4275
4275
|
},
|
|
4276
4276
|
sourceLocation: {
|
|
4277
4277
|
"file": "packages/dsh-plugin-shop/src/host/index.ts",
|
|
@@ -4280,16 +4280,16 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
4280
4280
|
}
|
|
4281
4281
|
},
|
|
4282
4282
|
{
|
|
4283
|
-
id: "dsh-plugin-shop#
|
|
4284
|
-
service: "
|
|
4285
|
-
namespace: "
|
|
4283
|
+
id: "dsh-plugin-shop#shop/outdated",
|
|
4284
|
+
service: "shop",
|
|
4285
|
+
namespace: "shop",
|
|
4286
4286
|
method: "outdated",
|
|
4287
4287
|
invocation: { kind: "direct" },
|
|
4288
4288
|
parameters: [],
|
|
4289
4289
|
result: {
|
|
4290
4290
|
mode: "strict",
|
|
4291
|
-
typeSymbol: "dsh-plugin-shop#
|
|
4292
|
-
schema:
|
|
4291
|
+
typeSymbol: "dsh-plugin-shop#shop/outdated:result",
|
|
4292
|
+
schema: dsh_plugin_shop_shop_outdated_result$schema
|
|
4293
4293
|
},
|
|
4294
4294
|
sourceLocation: {
|
|
4295
4295
|
"file": "packages/dsh-plugin-shop/src/host/index.ts",
|
|
@@ -4298,9 +4298,9 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
4298
4298
|
}
|
|
4299
4299
|
},
|
|
4300
4300
|
{
|
|
4301
|
-
id: "dsh-plugin-shop#
|
|
4302
|
-
service: "
|
|
4303
|
-
namespace: "
|
|
4301
|
+
id: "dsh-plugin-shop#shop/setEnabled",
|
|
4302
|
+
service: "shop",
|
|
4303
|
+
namespace: "shop",
|
|
4304
4304
|
method: "setEnabled",
|
|
4305
4305
|
invocation: { kind: "direct" },
|
|
4306
4306
|
parameters: [{
|
|
@@ -4309,14 +4309,14 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
4309
4309
|
source: "json",
|
|
4310
4310
|
codec: {
|
|
4311
4311
|
mode: "strict",
|
|
4312
|
-
typeSymbol: "dsh-plugin-shop#
|
|
4313
|
-
schema:
|
|
4312
|
+
typeSymbol: "dsh-plugin-shop#shop/setEnabled:args",
|
|
4313
|
+
schema: dsh_plugin_shop_shop_setEnabled_parameter_0$schema
|
|
4314
4314
|
}
|
|
4315
4315
|
}],
|
|
4316
4316
|
result: {
|
|
4317
4317
|
mode: "strict",
|
|
4318
|
-
typeSymbol: "dsh-plugin-shop/types#
|
|
4319
|
-
schema:
|
|
4318
|
+
typeSymbol: "dsh-plugin-shop/types#ShopSetEnabledResult",
|
|
4319
|
+
schema: dsh_plugin_shop_shop_setEnabled_result$schema
|
|
4320
4320
|
},
|
|
4321
4321
|
sourceLocation: {
|
|
4322
4322
|
"file": "packages/dsh-plugin-shop/src/host/index.ts",
|
|
@@ -4336,7 +4336,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
4336
4336
|
case "community": return "tierCommunity";
|
|
4337
4337
|
}
|
|
4338
4338
|
}
|
|
4339
|
-
/** A derived listing has no author-declared catalog section; the
|
|
4339
|
+
/** A derived listing has no author-declared catalog section; the shop
|
|
4340
4340
|
* presents it as unclaimed, which is the signal that prompts an author to add
|
|
4341
4341
|
* one (§6.1). Never present a derived entry as though the author wrote it. */
|
|
4342
4342
|
function isUnclaimed(entry) {
|
|
@@ -4359,6 +4359,11 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
4359
4359
|
}
|
|
4360
4360
|
/** §7.2 once-per-second poll cadence, as a named constant. */
|
|
4361
4361
|
const INSTALL_POLL_MS = 1e3;
|
|
4362
|
+
/** The next number of cards to show: the current window plus one batch,
|
|
4363
|
+
* clamped so the window never claims more cards than the list holds. */
|
|
4364
|
+
function nextVisibleCount(visible, total, batch) {
|
|
4365
|
+
return Math.min(visible + batch, total);
|
|
4366
|
+
}
|
|
4362
4367
|
/** Pure install view reducer. A `status` event only applies to the install the
|
|
4363
4368
|
* view is tracking — a status for an install it never started (idle) is an
|
|
4364
4369
|
* unrelated event and a no-op, like any other event it does not recognize. */
|
|
@@ -4399,7 +4404,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
4399
4404
|
}
|
|
4400
4405
|
}
|
|
4401
4406
|
}
|
|
4402
|
-
const
|
|
4407
|
+
const SHOP_KEYWORDS = [
|
|
4403
4408
|
"store",
|
|
4404
4409
|
"market",
|
|
4405
4410
|
"mall",
|
|
@@ -4407,21 +4412,22 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
4407
4412
|
"marketplace"
|
|
4408
4413
|
];
|
|
4409
4414
|
/**
|
|
4410
|
-
* Whether a package name reads as a plugin
|
|
4411
|
-
* plugins, e.g. `dsh-plugin-shop`, `dsh-store`, `pluginstore`). The
|
|
4415
|
+
* Whether a package name reads as a plugin shop (a marketplace for dsh
|
|
4416
|
+
* plugins, e.g. `dsh-plugin-shop`, `dsh-store`, `pluginstore`). The shop
|
|
4412
4417
|
* tab hides these so the market does not list competing markets.
|
|
4413
4418
|
*
|
|
4414
4419
|
* Precision over recall: a name merely CONTAINING a keyword segment without
|
|
4415
4420
|
* a plugin qualifier or a keyword ending (`market-data-provider`,
|
|
4416
|
-
* `marketplace-hub`) is NOT a
|
|
4417
|
-
* match on the substring "store".
|
|
4421
|
+
* `marketplace-hub`) is NOT a shop plugin, and `dsh-restore` must never
|
|
4422
|
+
* match on the substring "store". The keyword list keeps "store" on purpose:
|
|
4423
|
+
* it matches other people's package names, not ours.
|
|
4418
4424
|
*/
|
|
4419
|
-
function
|
|
4425
|
+
function isShopLike(name) {
|
|
4420
4426
|
const segments = name.toLowerCase().split(/[-_.]+/);
|
|
4421
4427
|
const hasPlugin = segments.includes("plugin");
|
|
4422
4428
|
if (segments.some((segment) => /plugin(store|market|mall|shop|marketplace)/.test(segment) || /(store|market|mall|shop|marketplace)plugin/.test(segment))) return true;
|
|
4423
|
-
if (segments.filter((segment) =>
|
|
4424
|
-
return hasPlugin ||
|
|
4429
|
+
if (segments.filter((segment) => SHOP_KEYWORDS.includes(segment)).length === 0) return false;
|
|
4430
|
+
return hasPlugin || SHOP_KEYWORDS.includes(segments.at(-1));
|
|
4425
4431
|
}
|
|
4426
4432
|
const CATEGORY_KEYS = {
|
|
4427
4433
|
tool: "categoryTool",
|
|
@@ -4438,10 +4444,10 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
4438
4444
|
}
|
|
4439
4445
|
//#endregion
|
|
4440
4446
|
//#region src/client/locales.ts
|
|
4441
|
-
/** Copy dictionaries for the
|
|
4447
|
+
/** Copy dictionaries for the shop Settings tab. */
|
|
4442
4448
|
/** Simplified Chinese dictionary and key source of truth. */
|
|
4443
4449
|
const zh = {
|
|
4444
|
-
tab: "
|
|
4450
|
+
tab: "插件商店",
|
|
4445
4451
|
loading: "正在读取目录…",
|
|
4446
4452
|
error: "暂时无法读取目录。",
|
|
4447
4453
|
retry: "重试",
|
|
@@ -4473,6 +4479,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
4473
4479
|
installTransportFailed: "安装请求未能送达。请稍后重试。",
|
|
4474
4480
|
refresh: "刷新",
|
|
4475
4481
|
staleLabel: "显示 {date} 的快照",
|
|
4482
|
+
showing: "显示前 {shown} 个(共 {total})· 继续滚动加载",
|
|
4476
4483
|
version: "版本",
|
|
4477
4484
|
repository: "仓库",
|
|
4478
4485
|
license: "许可",
|
|
@@ -4491,7 +4498,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
4491
4498
|
};
|
|
4492
4499
|
/** English dictionary checked against the Chinese key set. */
|
|
4493
4500
|
const en = {
|
|
4494
|
-
tab: "Plugin
|
|
4501
|
+
tab: "Plugin shop",
|
|
4495
4502
|
loading: "Reading the catalog…",
|
|
4496
4503
|
error: "The catalog is temporarily unavailable.",
|
|
4497
4504
|
retry: "Retry",
|
|
@@ -4523,6 +4530,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
4523
4530
|
installTransportFailed: "The install request could not be delivered. Please retry.",
|
|
4524
4531
|
refresh: "Refresh",
|
|
4525
4532
|
staleLabel: "showing {date}",
|
|
4533
|
+
showing: "showing first {shown} of {total} — scroll to load more",
|
|
4526
4534
|
version: "Version",
|
|
4527
4535
|
repository: "Repository",
|
|
4528
4536
|
license: "License",
|
|
@@ -4591,87 +4599,89 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
4591
4599
|
};
|
|
4592
4600
|
}
|
|
4593
4601
|
//#endregion
|
|
4594
|
-
//#region \0dsh-plugin-shop-css:
|
|
4595
|
-
const css = "/* Store 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 brand hue\n * at six opacities, one per category, with the category name as the cover\n * label. Class names are mapped to content-derived names at bundle time\n * (tsdown.sc0638f_client.s5f77d3_config.s9c91c3_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.sc0638f_client.s456164_spec.s9c91c3_ts` pins this. */\n\n.s3ee4f7_panel {\n display: flex;\n flex-direction: column;\n gap: 14px;\n}\n\n.s34fbb8_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.sf8980c_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.s7cc50d_skeletonGrid {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));\n gap: 12px;\n}\n\n.sc1d9dd_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.sc1d9dd_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: dshStoreSkeletonSweep 1.4s ease-in-out infinite;\n pointer-events: none;\n}\n\n@keyframes dshStoreSkeletonSweep {\n to { transform: translateX(100%); }\n}\n\n.sb9166d_skeletonCover {\n display: block;\n height: 26px;\n background: color-mix(in srgb, var(--dsw-alias-label-primary) 10%, transparent);\n}\n\n.s9f0885_skeletonName {\n width: 55%;\n height: 14px;\n margin: 12px 12px 0;\n border-radius: 4px;\n background: color-mix(in srgb, var(--dsw-alias-label-primary) 8%, transparent);\n}\n\n.s18a7d7_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.se58a1d_skeletonSummaryShort {\n width: 68%;\n height: 12px;\n margin: 6px 12px 14px;\n border-radius: 4px;\n background: color-mix(in srgb, var(--dsw-alias-label-primary) 8%, transparent);\n}\n\n.sc1d9dd_skeletonCard span {\n animation: dshStoreSkeletonPulse 1.6s ease-in-out infinite;\n}\n\n@keyframes dshStoreSkeletonPulse {\n 0%, 100% { opacity: 0.5; }\n 50% { opacity: 1; }\n}\n\n@media (prefers-reduced-motion: reduce) {\n .sc1d9dd_skeletonCard span { animation: none; opacity: 0.75; }\n .sc1d9dd_skeletonCard::after { content: none; }\n}\n\n.sd2f7a7_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.sd2f7a7_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.sd2f7a7_actionButton:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary);\n outline-offset: 1px;\n}\n\n.s8b7c86_toolbar {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 12px;\n flex-wrap: wrap;\n}\n\n.s631085_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.s631085_searchInput:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary);\n outline-offset: 1px;\n}\n\n.sb9cba1_staleBlock {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.s8da7f6_staleBadge {\n padding: 2px 8px;\n border-radius: 999px;\n background: color-mix(in srgb, var(--dsw-alias-state-warn-primary) 14%, transparent);\n border: 1px solid color-mix(in srgb, var(--dsw-alias-state-warn-primary) 40%, transparent);\n color: var(--dsw-alias-state-warn-primary);\n font-size: 12px;\n}\n\n.s7cf245_catalogHeading {\n margin: 2px 0 0;\n font-size: 16px;\n font-weight: 600;\n letter-spacing: 0.02em;\n color: var(--dsw-alias-label-primary);\n}\n\n.s104623_catalogStats {\n margin: -8px 0 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.sc4b2b5_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.s2b38ed_cards {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));\n gap: 12px;\n list-style: none;\n margin: 0;\n padding: 0;\n animation: dshStoreCardsIn 220ms ease;\n}\n\n@keyframes dshStoreCardsIn {\n from { opacity: 0; transform: translateY(3px); }\n to { opacity: 1; transform: none; }\n}\n\n@media (prefers-reduced-motion: reduce) {\n .s2b38ed_cards { animation: none; }\n}\n\n.se139f2_card {\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 transition: border-color 120ms ease, transform 120ms ease, box-shadow 120ms ease;\n}\n\n.se139f2_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 .se139f2_card { transition: none; }\n .se139f2_card:hover { transform: none; }\n}\n\n/* The signature: a brand spine in the category's own opacity. */\n.sd7b5c1_cardSpine {\n position: absolute;\n top: 0;\n bottom: 0;\n left: 0;\n width: 3px;\n background: color-mix(in srgb, var(--dsw-alias-brand-primary) var(--spine-opacity, 40%), transparent);\n}\n\n.se139f2_card[data-category='tool'] { --spine-opacity: 100%; }\n.se139f2_card[data-category='provider'] { --spine-opacity: 82%; }\n.se139f2_card[data-category='ui'] { --spine-opacity: 64%; }\n.se139f2_card[data-category='workflow'] { --spine-opacity: 48%; }\n.se139f2_card[data-category='integration'] { --spine-opacity: 34%; }\n.se139f2_card[data-category='other'] { --spine-opacity: 22%; }\n\n.s3cb96a_cardCover {\n display: block;\n padding: 5px 12px 5px 12px;\n border-bottom: 1px solid var(--dsw-alias-border-l1);\n background: color-mix(in srgb, var(--dsw-alias-brand-primary) var(--spine-opacity, 40%), transparent);\n}\n\n.s756c69_coverLabel {\n display: block;\n font-size: 11px;\n font-weight: 600;\n letter-spacing: 0.08em;\n text-transform: uppercase;\n color: var(--dsw-alias-brand-primary);\n}\n\n.s715e28_entryHeader {\n display: flex;\n flex-direction: column;\n align-items: stretch;\n gap: 8px;\n padding: 10px 12px 6px;\n border: none;\n background: transparent;\n color: inherit;\n font: inherit;\n text-align: left;\n cursor: pointer;\n}\n\n.s715e28_entryHeader:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary);\n outline-offset: -2px;\n}\n\n/* The name owns the full header width; badges sit on their own line below. */\n.s13952b_name {\n font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;\n font-size: 13px;\n font-weight: 600;\n overflow-wrap: anywhere;\n color: var(--dsw-alias-label-primary);\n}\n\n.scf3634_badges {\n display: flex;\n align-items: center;\n flex-wrap: wrap;\n gap: 6px;\n}\n\n.s564750_tierBadge {\n padding: 1px 7px;\n border-radius: 999px;\n font-size: 11px;\n line-height: 1.6;\n}\n\n.s564750_tierBadge[data-tier='verified'] {\n color: var(--dsw-alias-state-success-primary);\n background: color-mix(in srgb, var(--dsw-alias-state-success-primary) 14%, transparent);\n border: 1px solid color-mix(in srgb, var(--dsw-alias-state-success-primary) 40%, transparent);\n}\n\n.s564750_tierBadge[data-tier='verified-stale'] {\n color: var(--dsw-alias-state-warn-primary);\n background: color-mix(in srgb, var(--dsw-alias-state-warn-primary) 14%, transparent);\n border: 1px solid color-mix(in srgb, var(--dsw-alias-state-warn-primary) 40%, transparent);\n}\n\n.s564750_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.s8d8459_unclaimedBadge {\n padding: 1px 7px;\n border-radius: 999px;\n border: 1px dashed var(--dsw-alias-border-l2);\n font-size: 11px;\n line-height: 1.6;\n color: var(--dsw-alias-label-secondary);\n}\n\n.s22f9c9_chevron, .s9812b3_chevronOpen {\n color: var(--dsw-alias-label-secondary);\n transition: transform 120ms ease;\n}\n\n.s9812b3_chevronOpen { transform: rotate(180deg); }\n\n@media (prefers-reduced-motion: reduce) {\n .s22f9c9_chevron, .s9812b3_chevronOpen { transition: none; }\n}\n\n.s1630e4_body {\n display: flex;\n flex-direction: column;\n gap: 8px;\n padding: 0 12px 12px;\n}\n\n.s817163_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.s7b7b74_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.sa1cf55_capabilitiesBlock {\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.sc5187f_capabilitiesNote {\n margin: 0;\n font-size: 11px;\n color: var(--dsw-alias-label-secondary);\n}\n\n.s254ff5_capabilities {\n display: flex;\n flex-wrap: wrap;\n gap: 4px;\n list-style: none;\n margin: 0;\n padding: 0;\n}\n\n.s254ff5_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.sd5c609_detail {\n border-top: 1px solid var(--dsw-alias-border-l1);\n padding-top: 8px;\n}\n\n.s9f6608_detailRows {\n display: flex;\n flex-direction: column;\n gap: 4px;\n margin: 0;\n}\n\n.s60a4c7_detailRow {\n display: flex;\n justify-content: space-between;\n gap: 12px;\n font-size: 12px;\n}\n\n.s60a4c7_detailRow dt {\n color: var(--dsw-alias-label-secondary);\n}\n\n.s60a4c7_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.s27bac7_reviewedLine {\n margin: 8px 0 0;\n padding: 6px 8px;\n border-radius: 6px;\n background: color-mix(in srgb, var(--dsw-alias-state-warn-primary) 12%, transparent);\n font-size: 12px;\n color: var(--dsw-alias-state-warn-primary);\n}\n\n/* Install flow. */\n.se261d7_installPanel {\n display: flex;\n flex-direction: column;\n gap: 8px;\n margin-top: 2px;\n}\n\n.sd477fc_installButton, .sf60f0d_confirmButton, .se03737_cancelButton {\n align-self: flex-start;\n padding: 5px 14px;\n border-radius: 6px;\n font-size: 13px;\n cursor: pointer;\n}\n\n.sd477fc_installButton {\n border: 1px solid var(--dsw-alias-brand-primary);\n background: var(--dsw-alias-brand-primary);\n color: var(--dsw-alias-bg-base);\n}\n\n.sd477fc_installButton:hover {\n background: color-mix(in srgb, var(--dsw-alias-brand-primary) 88%, var(--dsw-alias-label-primary));\n}\n\n.sf60f0d_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.sf60f0d_confirmButton:hover {\n background: color-mix(in srgb, var(--dsw-alias-brand-primary) 88%, var(--dsw-alias-label-primary));\n}\n\n.se03737_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.se03737_cancelButton:hover {\n border-color: var(--dsw-alias-label-secondary);\n}\n\n.sd477fc_installButton:focus-visible, .sf60f0d_confirmButton:focus-visible, .se03737_cancelButton:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary);\n outline-offset: 1px;\n}\n\n.s52e3df_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.s2fa7f4_gateTitle {\n margin: 0;\n font-size: 13px;\n font-weight: 600;\n color: var(--dsw-alias-state-warn-primary);\n}\n\n.sa5c938_gateBody {\n margin: 0;\n font-size: 12px;\n line-height: 1.6;\n color: var(--dsw-alias-label-primary);\n}\n\n.sef3bcb_gateActions {\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n}\n\n.s27c2b0_installing {\n margin: 0;\n font-size: 12px;\n color: var(--dsw-alias-label-secondary);\n}\n\n.sca368e_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.s1b9272_logLine {\n white-space: pre-wrap;\n word-break: break-all;\n color: var(--dsw-alias-label-secondary);\n}\n\n.sa67c51_notice {\n margin: 0;\n font-size: 12px;\n color: var(--dsw-alias-state-success-primary);\n}\n\n.s58085b_failedHeading {\n margin: 0;\n font-size: 12px;\n font-weight: 600;\n color: var(--dsw-alias-state-error-primary);\n}\n\n.sbead84_failedDetail {\n margin: 0;\n font-size: 12px;\n line-height: 1.6;\n color: var(--dsw-alias-label-primary);\n}\n\n.s27ed17_rejectedCode {\n margin: 0;\n font-size: 12px;\n font-weight: 600;\n color: var(--dsw-alias-state-error-primary);\n}\n\n.s42db4e_rejectedDetail {\n margin: 0;\n font-size: 12px;\n line-height: 1.6;\n color: var(--dsw-alias-label-primary);\n}\n\n/* Installed section. */\n.s69767e_outdatedSection {\n display: flex;\n flex-direction: column;\n gap: 8px;\n margin-top: 6px;\n}\n\n.s2d4d0e_outdatedList {\n display: flex;\n flex-direction: column;\n gap: 8px;\n list-style: none;\n margin: 0;\n padding: 0;\n}\n\n.s573b74_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.s2bb39b_outdatedInfo {\n display: flex;\n flex-direction: column;\n gap: 2px;\n min-width: 0;\n}\n\n.s2bb39b_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.s7a2aa4_outdatedVersions {\n font-size: 12px;\n color: var(--dsw-alias-label-secondary);\n}\n\n.s74c7b2_outdatedActions {\n display: flex;\n align-items: center;\n gap: 10px;\n}\n\n/* The enable/disable switch. */\n.s5a5c20_switch {\n position: relative;\n width: 32px;\n height: 18px;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 999px;\n background: var(--dsw-alias-bg-layer-2);\n cursor: pointer;\n transition: background 120ms ease, border-color 120ms ease;\n}\n\n.sa963e5_switchOn {\n border-color: var(--dsw-alias-state-success-primary);\n background: color-mix(in srgb, var(--dsw-alias-state-success-primary) 55%, transparent);\n}\n\n.s2e73a7_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.sa963e5_switchOn .s2e73a7_switchKnob {\n transform: translateX(14px);\n background: var(--dsw-alias-bg-base);\n}\n\n.s5a5c20_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 .s5a5c20_switch, .s2e73a7_switchKnob { transition: none; }\n}\n";
|
|
4596
|
-
if (typeof document !== "undefined" && !document.querySelector("style[data-plugin-css=\"
|
|
4602
|
+
//#region \0dsh-plugin-shop-css:e3675a89
|
|
4603
|
+
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 brand hue\n * at six opacities, one per category, with the category name as the cover\n * label. Class names are mapped to content-derived names at bundle time\n * (tsdown.s8583e3_client.s942a79_config.s5f67aa_ts) and stubbed in tests; only the keys are relied\n * on.\n *\n * One token rule the theme forces: the background LAYERS do not carry\n * contrast. In the light theme bg-base, bg-layer-1, bg-layer-2 and\n * bg-layer-3 all resolve to the same white; only the dark theme spreads them\n * (950/875/850/800). So a layer-2 fill on a layer-1 ground is invisible for\n * half of all users, and anything whose fill is its ONLY affordance — the\n * loading skeleton, the borderless capability chips — derives its fill from\n * label-primary instead, which inverts with the theme by construction.\n * Elements that also carry a border or text may keep a layer fill.\n * `css-tokens.s8583e3_client.sfd9d8a_spec.s5f67aa_ts` pins this. */\n\n.s255e5a_panel {\n display: flex;\n flex-direction: column;\n gap: 14px;\n}\n\n.s44a3ec_stateLine {\n margin: 0;\n color: var(--dsw-alias-label-primary);\n font-size: 13px;\n}\n\n/* Visually hidden but screen-reader readable (the loading copy while the\n * skeleton stands in visually). */\n.s3a0ece_srOnly {\n position: absolute;\n width: 1px;\n height: 1px;\n margin: -1px;\n padding: 0;\n border: 0;\n clip: rect(0 0 0 0);\n clip-path: inset(50%);\n overflow: hidden;\n white-space: nowrap;\n}\n\n/* The loading shelf: ghost cards with the same geometry as the real grid, so\n * the swap to content is a same-shape handoff instead of a jump. */\n.se0c3b4_skeletonGrid {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));\n gap: 12px;\n}\n\n.s520416_skeletonCard {\n position: relative;\n display: flex;\n flex-direction: column;\n border: 1px solid var(--dsw-alias-border-l1);\n border-radius: 10px;\n background: var(--dsw-alias-bg-layer-1);\n overflow: hidden;\n}\n\n/* The shimmer sweep: one gradient band travels across each ghost card while\n * the bars breathe, so the loading state reads as \"the shelf is scanning\". */\n.s520416_skeletonCard::after {\n content: '';\n position: absolute;\n inset: 0;\n background: linear-gradient(\n 100deg,\n transparent 25%,\n color-mix(in srgb, var(--dsw-alias-label-primary) 14%, transparent) 50%,\n transparent 75%\n );\n transform: translateX(-100%);\n animation: dshShopSkeletonSweep 1.4s ease-in-out infinite;\n pointer-events: none;\n}\n\n@keyframes dshShopSkeletonSweep {\n to { transform: translateX(100%); }\n}\n\n.s30e662_skeletonCover {\n display: block;\n height: 26px;\n background: color-mix(in srgb, var(--dsw-alias-label-primary) 10%, transparent);\n}\n\n.s8c7d6f_skeletonName {\n width: 55%;\n height: 14px;\n margin: 12px 12px 0;\n border-radius: 4px;\n background: color-mix(in srgb, var(--dsw-alias-label-primary) 8%, transparent);\n}\n\n.sf5179e_skeletonSummary {\n width: 92%;\n height: 12px;\n margin: 10px 12px 0;\n border-radius: 4px;\n background: color-mix(in srgb, var(--dsw-alias-label-primary) 8%, transparent);\n}\n\n.sbb0d25_skeletonSummaryShort {\n width: 68%;\n height: 12px;\n margin: 6px 12px 14px;\n border-radius: 4px;\n background: color-mix(in srgb, var(--dsw-alias-label-primary) 8%, transparent);\n}\n\n.s520416_skeletonCard span {\n animation: dshShopSkeletonPulse 1.6s ease-in-out infinite;\n}\n\n@keyframes dshShopSkeletonPulse {\n 0%, 100% { opacity: 0.5; }\n 50% { opacity: 1; }\n}\n\n@media (prefers-reduced-motion: reduce) {\n .s520416_skeletonCard span { animation: none; opacity: 0.75; }\n .s520416_skeletonCard::after { content: none; }\n}\n\n.s73242a_actionButton {\n align-self: flex-start;\n padding: 5px 14px;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 6px;\n background: var(--dsw-alias-bg-layer-2);\n color: var(--dsw-alias-label-primary);\n font-size: 13px;\n cursor: pointer;\n}\n\n.s73242a_actionButton:hover {\n border-color: color-mix(in srgb, var(--dsw-alias-brand-primary) 45%, var(--dsw-alias-border-l2));\n color: var(--dsw-alias-brand-primary);\n}\n\n.s73242a_actionButton:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary);\n outline-offset: 1px;\n}\n\n.s646509_toolbar {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 12px;\n flex-wrap: wrap;\n}\n\n.s232ec4_searchInput {\n width: min(280px, 100%);\n padding: 6px 10px;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 6px;\n background: var(--dsw-alias-bg-layer-1);\n color: var(--dsw-alias-label-primary);\n font-size: 13px;\n}\n\n.s232ec4_searchInput:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary);\n outline-offset: 1px;\n}\n\n.s1555aa_staleBlock {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.s3946f1_staleBadge {\n padding: 2px 8px;\n border-radius: 999px;\n background: color-mix(in srgb, var(--dsw-alias-state-warn-primary) 14%, transparent);\n border: 1px solid color-mix(in srgb, var(--dsw-alias-state-warn-primary) 40%, transparent);\n color: var(--dsw-alias-state-warn-primary);\n font-size: 12px;\n}\n\n.s668774_catalogHeading {\n margin: 2px 0 0;\n font-size: 16px;\n font-weight: 600;\n letter-spacing: 0.02em;\n color: var(--dsw-alias-label-primary);\n}\n\n.sccc4d1_catalogStats {\n margin: -8px 0 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.s6de1ab_emptyLine {\n margin: 0;\n color: var(--dsw-alias-label-primary);\n font-size: 13px;\n}\n\n/* The shelf: a responsive grid of cards. */\n.sf657f5_cards {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));\n gap: 12px;\n list-style: none;\n margin: 0;\n padding: 0;\n animation: dshShopCardsIn 220ms ease;\n}\n\n@keyframes dshShopCardsIn {\n from { opacity: 0; transform: translateY(3px); }\n to { opacity: 1; transform: none; }\n}\n\n@media (prefers-reduced-motion: reduce) {\n .sf657f5_cards { animation: none; }\n}\n\n.s65f383_card {\n position: relative;\n display: flex;\n flex-direction: column;\n 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 240px;\n}\n\n/* The sentinel that triggers the next shelf batch: zero visual footprint. */\n.sd7ee01_cardsSentry {\n height: 1px;\n margin: 0;\n padding: 0;\n}\n\n.s705cc6_showingLine {\n margin: 0;\n font-size: 12px;\n letter-spacing: 0.02em;\n color: var(--dsw-alias-label-secondary);\n}\n\n.s65f383_card:hover {\n border-color: color-mix(in srgb, var(--dsw-alias-brand-primary) 45%, var(--dsw-alias-border-l1));\n transform: translateY(-1px);\n box-shadow: 0 2px 8px color-mix(in srgb, var(--dsw-alias-brand-primary) 12%, transparent);\n}\n\n@media (prefers-reduced-motion: reduce) {\n .s65f383_card { transition: none; }\n .s65f383_card:hover { transform: none; }\n}\n\n/* The signature: a brand spine in the category's own opacity. */\n.s4ce25d_cardSpine {\n position: absolute;\n top: 0;\n bottom: 0;\n left: 0;\n width: 3px;\n background: color-mix(in srgb, var(--dsw-alias-brand-primary) var(--spine-opacity, 40%), transparent);\n}\n\n.s65f383_card[data-category='tool'] { --spine-opacity: 100%; }\n.s65f383_card[data-category='provider'] { --spine-opacity: 82%; }\n.s65f383_card[data-category='ui'] { --spine-opacity: 64%; }\n.s65f383_card[data-category='workflow'] { --spine-opacity: 48%; }\n.s65f383_card[data-category='integration'] { --spine-opacity: 34%; }\n.s65f383_card[data-category='other'] { --spine-opacity: 22%; }\n\n.s9e2bec_cardCover {\n display: block;\n padding: 5px 12px 5px 12px;\n border-bottom: 1px solid var(--dsw-alias-border-l1);\n background: color-mix(in srgb, var(--dsw-alias-brand-primary) var(--spine-opacity, 40%), transparent);\n}\n\n.s1a7c5b_coverLabel {\n display: block;\n font-size: 11px;\n font-weight: 600;\n letter-spacing: 0.08em;\n text-transform: uppercase;\n color: var(--dsw-alias-brand-primary);\n}\n\n.sa97234_entryHeader {\n display: flex;\n flex-direction: column;\n align-items: stretch;\n gap: 8px;\n padding: 10px 12px 6px;\n border: none;\n background: transparent;\n color: inherit;\n font: inherit;\n text-align: left;\n cursor: pointer;\n}\n\n.sa97234_entryHeader:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary);\n outline-offset: -2px;\n}\n\n/* The name owns the full header width; badges sit on their own line below. */\n.sc3f149_name {\n font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;\n font-size: 13px;\n font-weight: 600;\n overflow-wrap: anywhere;\n color: var(--dsw-alias-label-primary);\n}\n\n.s513026_badges {\n display: flex;\n align-items: center;\n flex-wrap: wrap;\n gap: 6px;\n}\n\n.s5e82cb_tierBadge {\n padding: 1px 7px;\n border-radius: 999px;\n font-size: 11px;\n line-height: 1.6;\n}\n\n.s5e82cb_tierBadge[data-tier='verified'] {\n color: var(--dsw-alias-state-success-primary);\n background: color-mix(in srgb, var(--dsw-alias-state-success-primary) 14%, transparent);\n border: 1px solid color-mix(in srgb, var(--dsw-alias-state-success-primary) 40%, transparent);\n}\n\n.s5e82cb_tierBadge[data-tier='verified-stale'] {\n color: var(--dsw-alias-state-warn-primary);\n background: color-mix(in srgb, var(--dsw-alias-state-warn-primary) 14%, transparent);\n border: 1px solid color-mix(in srgb, var(--dsw-alias-state-warn-primary) 40%, transparent);\n}\n\n.s5e82cb_tierBadge[data-tier='community'] {\n color: var(--dsw-alias-label-secondary);\n background: var(--dsw-alias-bg-layer-2);\n border: 1px solid var(--dsw-alias-border-l2);\n}\n\n.s23e3e1_unclaimedBadge {\n padding: 1px 7px;\n border-radius: 999px;\n border: 1px dashed var(--dsw-alias-border-l2);\n font-size: 11px;\n line-height: 1.6;\n color: var(--dsw-alias-label-secondary);\n}\n\n.s73f7fb_chevron, .s61393c_chevronOpen {\n color: var(--dsw-alias-label-secondary);\n transition: transform 120ms ease;\n}\n\n.s61393c_chevronOpen { transform: rotate(180deg); }\n\n@media (prefers-reduced-motion: reduce) {\n .s73f7fb_chevron, .s61393c_chevronOpen { transition: none; }\n}\n\n.s820ebf_body {\n display: flex;\n flex-direction: column;\n gap: 8px;\n padding: 0 12px 12px;\n}\n\n.sb8fbc8_summary {\n margin: 0;\n font-size: 13px;\n line-height: 1.5;\n color: var(--dsw-alias-label-primary);\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n overflow: hidden;\n}\n\n.se507db_summaryZh {\n margin: -4px 0 0;\n font-size: 12px;\n line-height: 1.5;\n color: var(--dsw-alias-label-secondary);\n display: -webkit-box;\n -webkit-line-clamp: 1;\n -webkit-box-orient: vertical;\n overflow: hidden;\n}\n\n.s9d2029_capabilitiesBlock {\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.s3bdbd5_capabilitiesNote {\n margin: 0;\n font-size: 11px;\n color: var(--dsw-alias-label-secondary);\n}\n\n.s441702_capabilities {\n display: flex;\n flex-wrap: wrap;\n gap: 4px;\n list-style: none;\n margin: 0;\n padding: 0;\n}\n\n.s441702_capabilities li {\n padding: 1px 6px;\n border-radius: 4px;\n background: color-mix(in srgb, var(--dsw-alias-label-primary) 6%, transparent);\n font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;\n font-size: 11px;\n color: var(--dsw-alias-label-secondary);\n}\n\n.sde3f0c_detail {\n border-top: 1px solid var(--dsw-alias-border-l1);\n padding-top: 8px;\n}\n\n.se98179_detailRows {\n display: flex;\n flex-direction: column;\n gap: 4px;\n margin: 0;\n}\n\n.sfb4d2f_detailRow {\n display: flex;\n justify-content: space-between;\n gap: 12px;\n font-size: 12px;\n}\n\n.sfb4d2f_detailRow dt {\n color: var(--dsw-alias-label-secondary);\n}\n\n.sfb4d2f_detailRow dd {\n margin: 0;\n font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;\n overflow-wrap: anywhere;\n text-align: right;\n color: var(--dsw-alias-label-primary);\n}\n\n.sd58c6d_reviewedLine {\n margin: 8px 0 0;\n padding: 6px 8px;\n border-radius: 6px;\n background: color-mix(in srgb, var(--dsw-alias-state-warn-primary) 12%, transparent);\n font-size: 12px;\n color: var(--dsw-alias-state-warn-primary);\n}\n\n/* Install flow. */\n.s4d374c_installPanel {\n display: flex;\n flex-direction: column;\n gap: 8px;\n margin-top: 2px;\n}\n\n.se7aaed_installButton, .sb43a49_confirmButton, .s6e45d1_cancelButton {\n align-self: flex-start;\n padding: 5px 14px;\n border-radius: 6px;\n font-size: 13px;\n cursor: pointer;\n}\n\n.se7aaed_installButton {\n border: 1px solid var(--dsw-alias-brand-primary);\n background: var(--dsw-alias-brand-primary);\n color: var(--dsw-alias-bg-base);\n}\n\n.se7aaed_installButton:hover {\n background: color-mix(in srgb, var(--dsw-alias-brand-primary) 88%, var(--dsw-alias-label-primary));\n}\n\n.sb43a49_confirmButton {\n border: 1px solid var(--dsw-alias-brand-primary);\n background: var(--dsw-alias-brand-primary);\n color: var(--dsw-alias-bg-base);\n}\n\n.sb43a49_confirmButton:hover {\n background: color-mix(in srgb, var(--dsw-alias-brand-primary) 88%, var(--dsw-alias-label-primary));\n}\n\n.s6e45d1_cancelButton {\n border: 1px solid var(--dsw-alias-border-l2);\n background: var(--dsw-alias-bg-layer-2);\n color: var(--dsw-alias-label-primary);\n}\n\n.s6e45d1_cancelButton:hover {\n border-color: var(--dsw-alias-label-secondary);\n}\n\n.se7aaed_installButton:focus-visible, .sb43a49_confirmButton:focus-visible, .s6e45d1_cancelButton:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary);\n outline-offset: 1px;\n}\n\n.sc4f2ac_gate {\n display: flex;\n flex-direction: column;\n gap: 8px;\n padding: 10px;\n border: 1px solid var(--dsw-alias-state-warn-primary);\n border-radius: 8px;\n background: color-mix(in srgb, var(--dsw-alias-state-warn-primary) 8%, transparent);\n}\n\n.s559c38_gateTitle {\n margin: 0;\n font-size: 13px;\n font-weight: 600;\n color: var(--dsw-alias-state-warn-primary);\n}\n\n.s3c0ace_gateBody {\n margin: 0;\n font-size: 12px;\n line-height: 1.6;\n color: var(--dsw-alias-label-primary);\n}\n\n.s4b2373_gateActions {\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n}\n\n.s52b5a5_installing {\n margin: 0;\n font-size: 12px;\n color: var(--dsw-alias-label-secondary);\n}\n\n.s64ab71_log {\n max-height: 160px;\n overflow: auto;\n margin: 0;\n padding: 8px;\n border-radius: 6px;\n background: var(--dsw-alias-bg-base);\n border: 1px solid var(--dsw-alias-border-l1);\n list-style: none;\n font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;\n font-size: 11px;\n line-height: 1.5;\n}\n\n.s1531a8_logLine {\n white-space: pre-wrap;\n word-break: break-all;\n color: var(--dsw-alias-label-secondary);\n}\n\n.sf20dda_notice {\n margin: 0;\n font-size: 12px;\n color: var(--dsw-alias-state-success-primary);\n}\n\n.seb9b08_failedHeading {\n margin: 0;\n font-size: 12px;\n font-weight: 600;\n color: var(--dsw-alias-state-error-primary);\n}\n\n.sfd3021_failedDetail {\n margin: 0;\n font-size: 12px;\n line-height: 1.6;\n color: var(--dsw-alias-label-primary);\n}\n\n.s50ba35_rejectedCode {\n margin: 0;\n font-size: 12px;\n font-weight: 600;\n color: var(--dsw-alias-state-error-primary);\n}\n\n.se75489_rejectedDetail {\n margin: 0;\n font-size: 12px;\n line-height: 1.6;\n color: var(--dsw-alias-label-primary);\n}\n\n/* Installed section. */\n.sa276cf_outdatedSection {\n display: flex;\n flex-direction: column;\n gap: 8px;\n margin-top: 6px;\n}\n\n.sceae6e_outdatedList {\n display: flex;\n flex-direction: column;\n gap: 8px;\n list-style: none;\n margin: 0;\n padding: 0;\n}\n\n.s8d2072_outdatedRow {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 12px;\n flex-wrap: wrap;\n padding: 10px 12px;\n border: 1px solid var(--dsw-alias-border-l1);\n border-radius: 8px;\n background: var(--dsw-alias-bg-layer-1);\n}\n\n.s5c2545_outdatedInfo {\n display: flex;\n flex-direction: column;\n gap: 2px;\n min-width: 0;\n}\n\n.s5c2545_outdatedInfo strong {\n font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;\n font-size: 13px;\n word-break: break-all;\n color: var(--dsw-alias-label-primary);\n}\n\n.s877c68_outdatedVersions {\n font-size: 12px;\n color: var(--dsw-alias-label-secondary);\n}\n\n.sa1f556_outdatedActions {\n display: flex;\n align-items: center;\n gap: 10px;\n}\n\n/* The enable/disable switch. */\n.s11c019_switch {\n position: relative;\n width: 32px;\n height: 18px;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 999px;\n background: var(--dsw-alias-bg-layer-2);\n cursor: pointer;\n transition: background 120ms ease, border-color 120ms ease;\n}\n\n.s7580e8_switchOn {\n border-color: var(--dsw-alias-state-success-primary);\n background: color-mix(in srgb, var(--dsw-alias-state-success-primary) 55%, transparent);\n}\n\n.saab2b3_switchKnob {\n position: absolute;\n top: 2px;\n left: 2px;\n width: 12px;\n height: 12px;\n border-radius: 999px;\n background: var(--dsw-alias-label-primary);\n transition: transform 120ms ease, background 120ms ease;\n}\n\n.s7580e8_switchOn .saab2b3_switchKnob {\n transform: translateX(14px);\n background: var(--dsw-alias-bg-base);\n}\n\n.s11c019_switch:focus-visible {\n outline: 2px solid var(--dsw-alias-brand-primary);\n outline-offset: 1px;\n}\n\n@media (prefers-reduced-motion: reduce) {\n .s11c019_switch, .saab2b3_switchKnob { transition: none; }\n}\n";
|
|
4604
|
+
if (typeof document !== "undefined" && !document.querySelector("style[data-plugin-css=\"e3675a89\"]")) {
|
|
4597
4605
|
const tag = document.createElement("style");
|
|
4598
|
-
tag.dataset.pluginCss = "
|
|
4606
|
+
tag.dataset.pluginCss = "e3675a89";
|
|
4599
4607
|
tag.textContent = css;
|
|
4600
4608
|
document.head.appendChild(tag);
|
|
4601
4609
|
}
|
|
4602
|
-
var
|
|
4603
|
-
"client": "
|
|
4604
|
-
"config": "
|
|
4605
|
-
"ts": "
|
|
4606
|
-
"spec": "
|
|
4607
|
-
"panel": "
|
|
4608
|
-
"stateLine": "
|
|
4609
|
-
"srOnly": "
|
|
4610
|
-
"skeletonGrid": "
|
|
4611
|
-
"skeletonCard": "
|
|
4612
|
-
"skeletonCover": "
|
|
4613
|
-
"skeletonName": "
|
|
4614
|
-
"skeletonSummary": "
|
|
4615
|
-
"skeletonSummaryShort": "
|
|
4616
|
-
"actionButton": "
|
|
4617
|
-
"toolbar": "
|
|
4618
|
-
"searchInput": "
|
|
4619
|
-
"staleBlock": "
|
|
4620
|
-
"staleBadge": "
|
|
4621
|
-
"catalogHeading": "
|
|
4622
|
-
"catalogStats": "
|
|
4623
|
-
"emptyLine": "
|
|
4624
|
-
"cards": "
|
|
4625
|
-
"card": "
|
|
4626
|
-
"
|
|
4627
|
-
"
|
|
4628
|
-
"
|
|
4629
|
-
"
|
|
4630
|
-
"
|
|
4631
|
-
"
|
|
4632
|
-
"
|
|
4633
|
-
"
|
|
4634
|
-
"
|
|
4635
|
-
"
|
|
4636
|
-
"
|
|
4637
|
-
"
|
|
4638
|
-
"
|
|
4639
|
-
"
|
|
4640
|
-
"
|
|
4641
|
-
"
|
|
4642
|
-
"
|
|
4643
|
-
"
|
|
4644
|
-
"
|
|
4645
|
-
"
|
|
4646
|
-
"
|
|
4647
|
-
"
|
|
4648
|
-
"
|
|
4649
|
-
"
|
|
4650
|
-
"
|
|
4651
|
-
"
|
|
4652
|
-
"
|
|
4653
|
-
"
|
|
4654
|
-
"
|
|
4655
|
-
"
|
|
4656
|
-
"
|
|
4657
|
-
"
|
|
4658
|
-
"
|
|
4659
|
-
"
|
|
4660
|
-
"
|
|
4661
|
-
"
|
|
4662
|
-
"
|
|
4663
|
-
"
|
|
4664
|
-
"
|
|
4665
|
-
"
|
|
4666
|
-
"
|
|
4667
|
-
"
|
|
4668
|
-
"
|
|
4669
|
-
"
|
|
4670
|
-
"
|
|
4610
|
+
var _dsh_plugin_shop_css_e3675a89_default = {
|
|
4611
|
+
"client": "s8583e3_client",
|
|
4612
|
+
"config": "s942a79_config",
|
|
4613
|
+
"ts": "s5f67aa_ts",
|
|
4614
|
+
"spec": "sfd9d8a_spec",
|
|
4615
|
+
"panel": "s255e5a_panel",
|
|
4616
|
+
"stateLine": "s44a3ec_stateLine",
|
|
4617
|
+
"srOnly": "s3a0ece_srOnly",
|
|
4618
|
+
"skeletonGrid": "se0c3b4_skeletonGrid",
|
|
4619
|
+
"skeletonCard": "s520416_skeletonCard",
|
|
4620
|
+
"skeletonCover": "s30e662_skeletonCover",
|
|
4621
|
+
"skeletonName": "s8c7d6f_skeletonName",
|
|
4622
|
+
"skeletonSummary": "sf5179e_skeletonSummary",
|
|
4623
|
+
"skeletonSummaryShort": "sbb0d25_skeletonSummaryShort",
|
|
4624
|
+
"actionButton": "s73242a_actionButton",
|
|
4625
|
+
"toolbar": "s646509_toolbar",
|
|
4626
|
+
"searchInput": "s232ec4_searchInput",
|
|
4627
|
+
"staleBlock": "s1555aa_staleBlock",
|
|
4628
|
+
"staleBadge": "s3946f1_staleBadge",
|
|
4629
|
+
"catalogHeading": "s668774_catalogHeading",
|
|
4630
|
+
"catalogStats": "sccc4d1_catalogStats",
|
|
4631
|
+
"emptyLine": "s6de1ab_emptyLine",
|
|
4632
|
+
"cards": "sf657f5_cards",
|
|
4633
|
+
"card": "s65f383_card",
|
|
4634
|
+
"cardsSentry": "sd7ee01_cardsSentry",
|
|
4635
|
+
"showingLine": "s705cc6_showingLine",
|
|
4636
|
+
"cardSpine": "s4ce25d_cardSpine",
|
|
4637
|
+
"cardCover": "s9e2bec_cardCover",
|
|
4638
|
+
"coverLabel": "s1a7c5b_coverLabel",
|
|
4639
|
+
"entryHeader": "sa97234_entryHeader",
|
|
4640
|
+
"name": "sc3f149_name",
|
|
4641
|
+
"badges": "s513026_badges",
|
|
4642
|
+
"tierBadge": "s5e82cb_tierBadge",
|
|
4643
|
+
"unclaimedBadge": "s23e3e1_unclaimedBadge",
|
|
4644
|
+
"chevron": "s73f7fb_chevron",
|
|
4645
|
+
"chevronOpen": "s61393c_chevronOpen",
|
|
4646
|
+
"body": "s820ebf_body",
|
|
4647
|
+
"summary": "sb8fbc8_summary",
|
|
4648
|
+
"summaryZh": "se507db_summaryZh",
|
|
4649
|
+
"capabilitiesBlock": "s9d2029_capabilitiesBlock",
|
|
4650
|
+
"capabilitiesNote": "s3bdbd5_capabilitiesNote",
|
|
4651
|
+
"capabilities": "s441702_capabilities",
|
|
4652
|
+
"detail": "sde3f0c_detail",
|
|
4653
|
+
"detailRows": "se98179_detailRows",
|
|
4654
|
+
"detailRow": "sfb4d2f_detailRow",
|
|
4655
|
+
"reviewedLine": "sd58c6d_reviewedLine",
|
|
4656
|
+
"installPanel": "s4d374c_installPanel",
|
|
4657
|
+
"installButton": "se7aaed_installButton",
|
|
4658
|
+
"confirmButton": "sb43a49_confirmButton",
|
|
4659
|
+
"cancelButton": "s6e45d1_cancelButton",
|
|
4660
|
+
"gate": "sc4f2ac_gate",
|
|
4661
|
+
"gateTitle": "s559c38_gateTitle",
|
|
4662
|
+
"gateBody": "s3c0ace_gateBody",
|
|
4663
|
+
"gateActions": "s4b2373_gateActions",
|
|
4664
|
+
"installing": "s52b5a5_installing",
|
|
4665
|
+
"log": "s64ab71_log",
|
|
4666
|
+
"logLine": "s1531a8_logLine",
|
|
4667
|
+
"notice": "sf20dda_notice",
|
|
4668
|
+
"failedHeading": "seb9b08_failedHeading",
|
|
4669
|
+
"failedDetail": "sfd3021_failedDetail",
|
|
4670
|
+
"rejectedCode": "s50ba35_rejectedCode",
|
|
4671
|
+
"rejectedDetail": "se75489_rejectedDetail",
|
|
4672
|
+
"outdatedSection": "sa276cf_outdatedSection",
|
|
4673
|
+
"outdatedList": "sceae6e_outdatedList",
|
|
4674
|
+
"outdatedRow": "s8d2072_outdatedRow",
|
|
4675
|
+
"outdatedInfo": "s5c2545_outdatedInfo",
|
|
4676
|
+
"outdatedVersions": "s877c68_outdatedVersions",
|
|
4677
|
+
"outdatedActions": "sa1f556_outdatedActions",
|
|
4678
|
+
"switch": "s11c019_switch",
|
|
4679
|
+
"switchOn": "s7580e8_switchOn",
|
|
4680
|
+
"switchKnob": "saab2b3_switchKnob"
|
|
4671
4681
|
};
|
|
4672
4682
|
//#endregion
|
|
4673
|
-
//#region src/client/
|
|
4674
|
-
/** The
|
|
4683
|
+
//#region src/client/ShopTab.tsx
|
|
4684
|
+
/** The shop tab: browse the catalog, detail an entry, install with the
|
|
4675
4685
|
* acknowledgement gate, poll the install to its terminal state (§7.2).
|
|
4676
4686
|
* Everything the tab renders is text — summaries, capabilities, log lines,
|
|
4677
4687
|
* details — never markup, so hostile npm descriptions cannot inject (spec
|
|
@@ -4682,7 +4692,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
4682
4692
|
width: "14",
|
|
4683
4693
|
height: "14",
|
|
4684
4694
|
"aria-hidden": "true",
|
|
4685
|
-
className: open ?
|
|
4695
|
+
className: open ? _dsh_plugin_shop_css_e3675a89_default.chevronOpen : _dsh_plugin_shop_css_e3675a89_default.chevron,
|
|
4686
4696
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
|
|
4687
4697
|
fill: "currentColor",
|
|
4688
4698
|
d: "M3.5 6 8 10.5 12.5 6l1 1L8 12.5 2.5 7l1-1Z"
|
|
@@ -4693,47 +4703,47 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
4693
4703
|
* (name, tier, category, unclaimed marker), the plain-text summary in both
|
|
4694
4704
|
* languages, the self-declared capabilities, the detail section, and the
|
|
4695
4705
|
* install controls. */
|
|
4696
|
-
function EntryCard({ entry, t, install, installStatus }) {
|
|
4706
|
+
const EntryCard = (0, react.memo)(function EntryCard({ entry, t, install, installStatus }) {
|
|
4697
4707
|
const [open, setOpen] = (0, react.useState)(false);
|
|
4698
4708
|
const detailId = (0, react.useId)();
|
|
4699
4709
|
const summary = entry.catalog?.summary;
|
|
4700
4710
|
const category = entry.catalog?.category ?? "other";
|
|
4701
4711
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4702
|
-
className:
|
|
4703
|
-
"data-
|
|
4712
|
+
className: _dsh_plugin_shop_css_e3675a89_default.card,
|
|
4713
|
+
"data-shop-entry": entry.name,
|
|
4704
4714
|
"data-category": category,
|
|
4705
4715
|
children: [
|
|
4706
4716
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
4707
|
-
className:
|
|
4717
|
+
className: _dsh_plugin_shop_css_e3675a89_default.cardSpine,
|
|
4708
4718
|
"aria-hidden": "true"
|
|
4709
4719
|
}),
|
|
4710
4720
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
4711
|
-
className:
|
|
4721
|
+
className: _dsh_plugin_shop_css_e3675a89_default.cardCover,
|
|
4712
4722
|
"aria-hidden": "true",
|
|
4713
4723
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
4714
|
-
className:
|
|
4724
|
+
className: _dsh_plugin_shop_css_e3675a89_default.coverLabel,
|
|
4715
4725
|
children: t(categoryKey(entry))
|
|
4716
4726
|
})
|
|
4717
4727
|
}),
|
|
4718
4728
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
4719
4729
|
type: "button",
|
|
4720
|
-
className:
|
|
4730
|
+
className: _dsh_plugin_shop_css_e3675a89_default.entryHeader,
|
|
4721
4731
|
"aria-expanded": open,
|
|
4722
4732
|
"aria-controls": detailId,
|
|
4723
4733
|
onClick: () => setOpen((current) => !current),
|
|
4724
4734
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
4725
|
-
className:
|
|
4735
|
+
className: _dsh_plugin_shop_css_e3675a89_default.name,
|
|
4726
4736
|
children: entry.name
|
|
4727
4737
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
4728
|
-
className:
|
|
4738
|
+
className: _dsh_plugin_shop_css_e3675a89_default.badges,
|
|
4729
4739
|
children: [
|
|
4730
4740
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
4731
|
-
className:
|
|
4741
|
+
className: _dsh_plugin_shop_css_e3675a89_default.tierBadge,
|
|
4732
4742
|
"data-tier": entry.tier,
|
|
4733
4743
|
children: t(tierKey(entry.tier))
|
|
4734
4744
|
}),
|
|
4735
4745
|
isUnclaimed(entry) && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
4736
|
-
className:
|
|
4746
|
+
className: _dsh_plugin_shop_css_e3675a89_default.unclaimedBadge,
|
|
4737
4747
|
children: t("unclaimed")
|
|
4738
4748
|
}),
|
|
4739
4749
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(ChevronIcon, { open })
|
|
@@ -4741,47 +4751,47 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
4741
4751
|
})]
|
|
4742
4752
|
}),
|
|
4743
4753
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4744
|
-
className:
|
|
4754
|
+
className: _dsh_plugin_shop_css_e3675a89_default.body,
|
|
4745
4755
|
children: [
|
|
4746
4756
|
summary !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
4747
|
-
className:
|
|
4757
|
+
className: _dsh_plugin_shop_css_e3675a89_default.summary,
|
|
4748
4758
|
children: summary.en
|
|
4749
4759
|
}),
|
|
4750
4760
|
summary?.zh !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
4751
|
-
className:
|
|
4761
|
+
className: _dsh_plugin_shop_css_e3675a89_default.summaryZh,
|
|
4752
4762
|
children: summary.zh
|
|
4753
4763
|
}),
|
|
4754
4764
|
entry.catalog !== void 0 && entry.catalog.capabilities.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4755
|
-
className:
|
|
4765
|
+
className: _dsh_plugin_shop_css_e3675a89_default.capabilitiesBlock,
|
|
4756
4766
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
4757
|
-
className:
|
|
4767
|
+
className: _dsh_plugin_shop_css_e3675a89_default.capabilitiesNote,
|
|
4758
4768
|
children: t("capabilitiesNote")
|
|
4759
4769
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("ul", {
|
|
4760
|
-
className:
|
|
4770
|
+
className: _dsh_plugin_shop_css_e3675a89_default.capabilities,
|
|
4761
4771
|
children: entry.catalog.capabilities.map((capability) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", { children: capability }, capability))
|
|
4762
4772
|
})]
|
|
4763
4773
|
}),
|
|
4764
4774
|
open && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
4765
4775
|
id: detailId,
|
|
4766
|
-
className:
|
|
4776
|
+
className: _dsh_plugin_shop_css_e3675a89_default.detail,
|
|
4767
4777
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("dl", {
|
|
4768
|
-
className:
|
|
4778
|
+
className: _dsh_plugin_shop_css_e3675a89_default.detailRows,
|
|
4769
4779
|
children: [
|
|
4770
4780
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4771
|
-
className:
|
|
4781
|
+
className: _dsh_plugin_shop_css_e3675a89_default.detailRow,
|
|
4772
4782
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("dt", { children: t("version") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("dd", { children: entry.version })]
|
|
4773
4783
|
}),
|
|
4774
4784
|
entry.repository !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4775
|
-
className:
|
|
4785
|
+
className: _dsh_plugin_shop_css_e3675a89_default.detailRow,
|
|
4776
4786
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("dt", { children: t("repository") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("dd", { children: entry.repository })]
|
|
4777
4787
|
}),
|
|
4778
4788
|
entry.license !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4779
|
-
className:
|
|
4789
|
+
className: _dsh_plugin_shop_css_e3675a89_default.detailRow,
|
|
4780
4790
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("dt", { children: t("license") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("dd", { children: entry.license })]
|
|
4781
4791
|
})
|
|
4782
4792
|
]
|
|
4783
4793
|
}), entry.tier === "verified-stale" && entry.review !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
4784
|
-
className:
|
|
4794
|
+
className: _dsh_plugin_shop_css_e3675a89_default.reviewedLine,
|
|
4785
4795
|
children: t("reviewedVersionLine", {
|
|
4786
4796
|
reviewed: entry.review.reviewedVersion,
|
|
4787
4797
|
current: entry.version
|
|
@@ -4800,7 +4810,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
4800
4810
|
})
|
|
4801
4811
|
]
|
|
4802
4812
|
});
|
|
4803
|
-
}
|
|
4813
|
+
});
|
|
4804
4814
|
/** One entry's install flow: the button, the §9.3 acknowledgement gate for
|
|
4805
4815
|
* community-tier entries, and the live view — running log, restart notice,
|
|
4806
4816
|
* failure detail, rejection detail — driven by `useInstall`. Shared by the
|
|
@@ -4810,70 +4820,70 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
4810
4820
|
const [gateOpen, setGateOpen] = (0, react.useState)(false);
|
|
4811
4821
|
const { view, start } = useInstall(install, installStatus);
|
|
4812
4822
|
if (view.kind === "running") return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4813
|
-
className:
|
|
4823
|
+
className: _dsh_plugin_shop_css_e3675a89_default.installPanel,
|
|
4814
4824
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
4815
|
-
className:
|
|
4825
|
+
className: _dsh_plugin_shop_css_e3675a89_default.installing,
|
|
4816
4826
|
children: t("installing")
|
|
4817
4827
|
}), view.log.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
4818
|
-
className:
|
|
4828
|
+
className: _dsh_plugin_shop_css_e3675a89_default.log,
|
|
4819
4829
|
children: view.log.map((line, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
4820
|
-
className:
|
|
4830
|
+
className: _dsh_plugin_shop_css_e3675a89_default.logLine,
|
|
4821
4831
|
children: line
|
|
4822
4832
|
}, index))
|
|
4823
4833
|
})]
|
|
4824
4834
|
});
|
|
4825
4835
|
if (view.kind === "done") return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
4826
|
-
className:
|
|
4827
|
-
"data-
|
|
4836
|
+
className: _dsh_plugin_shop_css_e3675a89_default.notice,
|
|
4837
|
+
"data-shop-restart-notice": true,
|
|
4828
4838
|
children: view.needsRestart ? t("installedRestartNotice") : t("installedNoRestartNotice")
|
|
4829
4839
|
});
|
|
4830
4840
|
if (view.kind === "failed") return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4831
|
-
className:
|
|
4841
|
+
className: _dsh_plugin_shop_css_e3675a89_default.installPanel,
|
|
4832
4842
|
children: [
|
|
4833
4843
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
4834
|
-
className:
|
|
4844
|
+
className: _dsh_plugin_shop_css_e3675a89_default.failedHeading,
|
|
4835
4845
|
children: t("installFailed")
|
|
4836
4846
|
}),
|
|
4837
4847
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
4838
|
-
className:
|
|
4848
|
+
className: _dsh_plugin_shop_css_e3675a89_default.log,
|
|
4839
4849
|
children: view.log.map((line, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
4840
|
-
className:
|
|
4850
|
+
className: _dsh_plugin_shop_css_e3675a89_default.logLine,
|
|
4841
4851
|
children: line
|
|
4842
4852
|
}, index))
|
|
4843
4853
|
}),
|
|
4844
4854
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
4845
|
-
className:
|
|
4855
|
+
className: _dsh_plugin_shop_css_e3675a89_default.failedDetail,
|
|
4846
4856
|
children: view.detail === "" ? t("installTransportFailed") : view.detail
|
|
4847
4857
|
})
|
|
4848
4858
|
]
|
|
4849
4859
|
});
|
|
4850
4860
|
if (view.kind === "rejected") return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4851
|
-
className:
|
|
4861
|
+
className: _dsh_plugin_shop_css_e3675a89_default.installPanel,
|
|
4852
4862
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
4853
|
-
className:
|
|
4863
|
+
className: _dsh_plugin_shop_css_e3675a89_default.rejectedCode,
|
|
4854
4864
|
children: t(rejectionCodeKey(view.code))
|
|
4855
4865
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
4856
|
-
className:
|
|
4866
|
+
className: _dsh_plugin_shop_css_e3675a89_default.rejectedDetail,
|
|
4857
4867
|
children: view.detail
|
|
4858
4868
|
})]
|
|
4859
4869
|
});
|
|
4860
4870
|
if (gateOpen) return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4861
|
-
className:
|
|
4871
|
+
className: _dsh_plugin_shop_css_e3675a89_default.gate,
|
|
4862
4872
|
children: [
|
|
4863
4873
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
4864
|
-
className:
|
|
4874
|
+
className: _dsh_plugin_shop_css_e3675a89_default.gateTitle,
|
|
4865
4875
|
children: t("acknowledgementTitle")
|
|
4866
4876
|
}),
|
|
4867
4877
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
4868
|
-
className:
|
|
4878
|
+
className: _dsh_plugin_shop_css_e3675a89_default.gateBody,
|
|
4869
4879
|
children: t("acknowledgementBody")
|
|
4870
4880
|
}),
|
|
4871
4881
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4872
|
-
className:
|
|
4882
|
+
className: _dsh_plugin_shop_css_e3675a89_default.gateActions,
|
|
4873
4883
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
4874
4884
|
type: "button",
|
|
4875
|
-
className:
|
|
4876
|
-
"data-
|
|
4885
|
+
className: _dsh_plugin_shop_css_e3675a89_default.confirmButton,
|
|
4886
|
+
"data-shop-confirm": true,
|
|
4877
4887
|
onClick: () => {
|
|
4878
4888
|
setGateOpen(false);
|
|
4879
4889
|
start({
|
|
@@ -4885,7 +4895,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
4885
4895
|
children: t("confirm")
|
|
4886
4896
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
4887
4897
|
type: "button",
|
|
4888
|
-
className:
|
|
4898
|
+
className: _dsh_plugin_shop_css_e3675a89_default.cancelButton,
|
|
4889
4899
|
onClick: () => setGateOpen(false),
|
|
4890
4900
|
children: t("cancel")
|
|
4891
4901
|
})]
|
|
@@ -4895,8 +4905,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
4895
4905
|
const update = variant === "update";
|
|
4896
4906
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
4897
4907
|
type: "button",
|
|
4898
|
-
className:
|
|
4899
|
-
...update ? { "data-
|
|
4908
|
+
className: _dsh_plugin_shop_css_e3675a89_default.installButton,
|
|
4909
|
+
...update ? { "data-shop-update": true } : { "data-shop-install": true },
|
|
4900
4910
|
onClick: () => {
|
|
4901
4911
|
if (tier === "verified") start({
|
|
4902
4912
|
name,
|
|
@@ -4941,37 +4951,37 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
4941
4951
|
}
|
|
4942
4952
|
};
|
|
4943
4953
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4944
|
-
className:
|
|
4945
|
-
"data-
|
|
4954
|
+
className: _dsh_plugin_shop_css_e3675a89_default.outdatedRow,
|
|
4955
|
+
"data-shop-outdated-entry": row.name,
|
|
4946
4956
|
children: [
|
|
4947
4957
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4948
|
-
className:
|
|
4958
|
+
className: _dsh_plugin_shop_css_e3675a89_default.outdatedInfo,
|
|
4949
4959
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
4950
|
-
className:
|
|
4960
|
+
className: _dsh_plugin_shop_css_e3675a89_default.name,
|
|
4951
4961
|
children: row.name
|
|
4952
4962
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
4953
|
-
className:
|
|
4963
|
+
className: _dsh_plugin_shop_css_e3675a89_default.outdatedVersions,
|
|
4954
4964
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
4955
|
-
className:
|
|
4965
|
+
className: _dsh_plugin_shop_css_e3675a89_default.outdatedVersion,
|
|
4956
4966
|
children: t("installedVersion", { version: row.installed })
|
|
4957
4967
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
4958
|
-
className:
|
|
4968
|
+
className: _dsh_plugin_shop_css_e3675a89_default.outdatedVersion,
|
|
4959
4969
|
children: t("latestVersion", { version: row.latest })
|
|
4960
4970
|
})]
|
|
4961
4971
|
})]
|
|
4962
4972
|
}),
|
|
4963
4973
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4964
|
-
className:
|
|
4974
|
+
className: _dsh_plugin_shop_css_e3675a89_default.outdatedActions,
|
|
4965
4975
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
4966
4976
|
type: "button",
|
|
4967
4977
|
role: "switch",
|
|
4968
4978
|
"aria-checked": enabled,
|
|
4969
4979
|
"aria-label": t("enabledSwitch"),
|
|
4970
|
-
"data-
|
|
4971
|
-
className: `${
|
|
4980
|
+
"data-shop-toggle": true,
|
|
4981
|
+
className: `${_dsh_plugin_shop_css_e3675a89_default.switch} ${enabled ? _dsh_plugin_shop_css_e3675a89_default.switchOn : ""}`,
|
|
4972
4982
|
onClick: () => void onToggle(),
|
|
4973
4983
|
disabled: toggle.kind === "saving",
|
|
4974
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className:
|
|
4984
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: _dsh_plugin_shop_css_e3675a89_default.switchKnob })
|
|
4975
4985
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(InstallPanel, {
|
|
4976
4986
|
name: row.name,
|
|
4977
4987
|
version: row.latest,
|
|
@@ -4983,13 +4993,13 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
4983
4993
|
})]
|
|
4984
4994
|
}),
|
|
4985
4995
|
toggle.kind === "saved" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
4986
|
-
className:
|
|
4987
|
-
"data-
|
|
4996
|
+
className: _dsh_plugin_shop_css_e3675a89_default.notice,
|
|
4997
|
+
"data-shop-hot-apply": true,
|
|
4988
4998
|
children: t("hotApplyNote")
|
|
4989
4999
|
}),
|
|
4990
5000
|
toggle.kind === "error" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
4991
|
-
className:
|
|
4992
|
-
"data-
|
|
5001
|
+
className: _dsh_plugin_shop_css_e3675a89_default.failedDetail,
|
|
5002
|
+
"data-shop-toggle-error": true,
|
|
4993
5003
|
children: toggle.detail
|
|
4994
5004
|
})
|
|
4995
5005
|
]
|
|
@@ -5002,19 +5012,19 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
5002
5012
|
function OutdatedSection({ state, tiers, t, setEnabled, install, installStatus }) {
|
|
5003
5013
|
if (state.kind === "loading") return null;
|
|
5004
5014
|
if (state.kind === "error") return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
5005
|
-
className:
|
|
5006
|
-
"data-
|
|
5015
|
+
className: _dsh_plugin_shop_css_e3675a89_default.stateLine,
|
|
5016
|
+
"data-shop-outdated-error": true,
|
|
5007
5017
|
children: t("error")
|
|
5008
5018
|
});
|
|
5009
5019
|
if (state.entries.length === 0) return null;
|
|
5010
5020
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
5011
|
-
className:
|
|
5012
|
-
"data-
|
|
5021
|
+
className: _dsh_plugin_shop_css_e3675a89_default.outdatedSection,
|
|
5022
|
+
"data-shop-outdated": true,
|
|
5013
5023
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h2", {
|
|
5014
|
-
className:
|
|
5024
|
+
className: _dsh_plugin_shop_css_e3675a89_default.catalogHeading,
|
|
5015
5025
|
children: t("installedSection")
|
|
5016
5026
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("ul", {
|
|
5017
|
-
className:
|
|
5027
|
+
className: _dsh_plugin_shop_css_e3675a89_default.outdatedList,
|
|
5018
5028
|
children: state.entries.map((row) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(OutdatedRow, {
|
|
5019
5029
|
row,
|
|
5020
5030
|
tier: tiers.get(row.name) ?? "community",
|
|
@@ -5026,14 +5036,18 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
5026
5036
|
})]
|
|
5027
5037
|
});
|
|
5028
5038
|
}
|
|
5029
|
-
/** The
|
|
5039
|
+
/** The shop tab root: browse, search, refresh, and render one card per
|
|
5030
5040
|
* entry. Data attributes on the e2e-relevant nodes follow the Task 3 list. */
|
|
5031
|
-
function
|
|
5041
|
+
function ShopTab(props) {
|
|
5032
5042
|
const { t, catalog, install, installStatus, setEnabled, outdated } = props;
|
|
5033
5043
|
const [catalogState, setCatalogState] = (0, react.useState)({ kind: "loading" });
|
|
5034
5044
|
const [outdatedState, setOutdatedState] = (0, react.useState)({ kind: "loading" });
|
|
5035
5045
|
const [request, setRequest] = (0, react.useState)({ kind: "initial" });
|
|
5036
5046
|
const [query, setQuery] = (0, react.useState)("");
|
|
5047
|
+
const incremental = typeof IntersectionObserver !== "undefined";
|
|
5048
|
+
const [visibleCount, setVisibleCount] = (0, react.useState)(48);
|
|
5049
|
+
const sentinelRef = (0, react.useRef)(null);
|
|
5050
|
+
const filteredLenRef = (0, react.useRef)(0);
|
|
5037
5051
|
(0, react.useEffect)(() => {
|
|
5038
5052
|
let cancelled = false;
|
|
5039
5053
|
if (request.kind !== "refresh") setCatalogState((current) => current.kind === "ready" ? current : { kind: "loading" });
|
|
@@ -5075,106 +5089,137 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
5075
5089
|
if (catalogState.kind !== "ready") return [];
|
|
5076
5090
|
const q = query.trim().toLowerCase();
|
|
5077
5091
|
return catalogState.result.plugins.filter((entry) => {
|
|
5078
|
-
if (
|
|
5092
|
+
if (isShopLike(entry.name)) return false;
|
|
5079
5093
|
if (q === "") return true;
|
|
5080
5094
|
const summaryEn = entry.catalog?.summary.en ?? "";
|
|
5081
5095
|
const summaryZh = entry.catalog?.summary.zh ?? "";
|
|
5082
5096
|
return entry.name.toLowerCase().includes(q) || summaryEn.toLowerCase().includes(q) || summaryZh.toLowerCase().includes(q);
|
|
5083
5097
|
});
|
|
5084
5098
|
}, [catalogState, query]);
|
|
5099
|
+
filteredLenRef.current = filtered.length;
|
|
5100
|
+
(0, react.useEffect)(() => {
|
|
5101
|
+
if (!incremental) return;
|
|
5102
|
+
const node = sentinelRef.current;
|
|
5103
|
+
if (node === null) return;
|
|
5104
|
+
const observer = new IntersectionObserver((entries) => {
|
|
5105
|
+
if (entries.some((entry) => entry.isIntersecting)) setVisibleCount((current) => nextVisibleCount(current, filteredLenRef.current, 48));
|
|
5106
|
+
}, { rootMargin: "0px 0px 1200px 0px" });
|
|
5107
|
+
observer.observe(node);
|
|
5108
|
+
return () => observer.disconnect();
|
|
5109
|
+
}, [
|
|
5110
|
+
incremental,
|
|
5111
|
+
visibleCount,
|
|
5112
|
+
filtered.length
|
|
5113
|
+
]);
|
|
5114
|
+
const visible = incremental ? filtered.slice(0, visibleCount) : filtered;
|
|
5085
5115
|
const tiers = (0, react.useMemo)(() => {
|
|
5086
5116
|
const map = /* @__PURE__ */ new Map();
|
|
5087
5117
|
if (catalogState.kind === "ready") for (const entry of catalogState.result.plugins) map.set(entry.name, entry.tier);
|
|
5088
5118
|
return map;
|
|
5089
5119
|
}, [catalogState]);
|
|
5090
5120
|
if (catalogState.kind === "loading") return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5091
|
-
className:
|
|
5092
|
-
"data-
|
|
5121
|
+
className: _dsh_plugin_shop_css_e3675a89_default.panel,
|
|
5122
|
+
"data-shop-tab": true,
|
|
5093
5123
|
"aria-busy": "true",
|
|
5094
5124
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
5095
|
-
className:
|
|
5125
|
+
className: _dsh_plugin_shop_css_e3675a89_default.srOnly,
|
|
5096
5126
|
children: t("loading")
|
|
5097
5127
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
5098
|
-
className:
|
|
5099
|
-
"data-
|
|
5128
|
+
className: _dsh_plugin_shop_css_e3675a89_default.skeletonGrid,
|
|
5129
|
+
"data-shop-skeleton": true,
|
|
5100
5130
|
"aria-hidden": "true",
|
|
5101
5131
|
children: Array.from({ length: 8 }, (_, i) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5102
|
-
className:
|
|
5132
|
+
className: _dsh_plugin_shop_css_e3675a89_default.skeletonCard,
|
|
5103
5133
|
children: [
|
|
5104
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className:
|
|
5105
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className:
|
|
5106
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className:
|
|
5107
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className:
|
|
5134
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: _dsh_plugin_shop_css_e3675a89_default.skeletonCover }),
|
|
5135
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: _dsh_plugin_shop_css_e3675a89_default.skeletonName }),
|
|
5136
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: _dsh_plugin_shop_css_e3675a89_default.skeletonSummary }),
|
|
5137
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: _dsh_plugin_shop_css_e3675a89_default.skeletonSummaryShort })
|
|
5108
5138
|
]
|
|
5109
5139
|
}, i))
|
|
5110
5140
|
})]
|
|
5111
5141
|
});
|
|
5112
5142
|
if (catalogState.kind === "error") return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5113
|
-
className:
|
|
5114
|
-
"data-
|
|
5143
|
+
className: _dsh_plugin_shop_css_e3675a89_default.panel,
|
|
5144
|
+
"data-shop-tab": true,
|
|
5115
5145
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
5116
|
-
className:
|
|
5146
|
+
className: _dsh_plugin_shop_css_e3675a89_default.stateLine,
|
|
5117
5147
|
children: t("error")
|
|
5118
5148
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
5119
5149
|
type: "button",
|
|
5120
|
-
className:
|
|
5150
|
+
className: _dsh_plugin_shop_css_e3675a89_default.actionButton,
|
|
5121
5151
|
onClick: () => setRequest({ kind: "retry" }),
|
|
5122
5152
|
children: t("retry")
|
|
5123
5153
|
})]
|
|
5124
5154
|
});
|
|
5125
5155
|
const { result } = catalogState;
|
|
5126
5156
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5127
|
-
className:
|
|
5128
|
-
"data-
|
|
5157
|
+
className: _dsh_plugin_shop_css_e3675a89_default.panel,
|
|
5158
|
+
"data-shop-tab": true,
|
|
5129
5159
|
children: [
|
|
5130
5160
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5131
|
-
className:
|
|
5161
|
+
className: _dsh_plugin_shop_css_e3675a89_default.toolbar,
|
|
5132
5162
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
5133
5163
|
type: "search",
|
|
5134
|
-
className:
|
|
5164
|
+
className: _dsh_plugin_shop_css_e3675a89_default.searchInput,
|
|
5135
5165
|
"aria-label": t("search"),
|
|
5136
5166
|
placeholder: t("search"),
|
|
5137
5167
|
value: query,
|
|
5138
|
-
onChange: (event) =>
|
|
5168
|
+
onChange: (event) => {
|
|
5169
|
+
setQuery(event.target.value);
|
|
5170
|
+
setVisibleCount(48);
|
|
5171
|
+
}
|
|
5139
5172
|
}), result.stale && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5140
|
-
className:
|
|
5173
|
+
className: _dsh_plugin_shop_css_e3675a89_default.staleBlock,
|
|
5141
5174
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5142
|
-
className:
|
|
5175
|
+
className: _dsh_plugin_shop_css_e3675a89_default.staleBadge,
|
|
5143
5176
|
children: t("staleLabel", { date: result.builtAt.slice(0, 10) })
|
|
5144
5177
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
5145
5178
|
type: "button",
|
|
5146
|
-
className:
|
|
5179
|
+
className: _dsh_plugin_shop_css_e3675a89_default.actionButton,
|
|
5147
5180
|
onClick: () => setRequest({ kind: "refresh" }),
|
|
5148
5181
|
children: t("refresh")
|
|
5149
5182
|
})]
|
|
5150
5183
|
})]
|
|
5151
5184
|
}),
|
|
5152
5185
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h2", {
|
|
5153
|
-
className:
|
|
5186
|
+
className: _dsh_plugin_shop_css_e3675a89_default.catalogHeading,
|
|
5154
5187
|
children: t("catalog")
|
|
5155
5188
|
}),
|
|
5156
5189
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
5157
|
-
className:
|
|
5190
|
+
className: _dsh_plugin_shop_css_e3675a89_default.catalogStats,
|
|
5158
5191
|
children: t("catalogStats", {
|
|
5159
5192
|
count: String(result.plugins.length),
|
|
5160
5193
|
date: result.builtAt.slice(0, 10)
|
|
5161
5194
|
})
|
|
5162
5195
|
}),
|
|
5163
5196
|
result.plugins.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
5164
|
-
className:
|
|
5197
|
+
className: _dsh_plugin_shop_css_e3675a89_default.emptyLine,
|
|
5165
5198
|
children: t("empty")
|
|
5166
5199
|
}) : filtered.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
5167
|
-
className:
|
|
5200
|
+
className: _dsh_plugin_shop_css_e3675a89_default.emptyLine,
|
|
5168
5201
|
children: t("emptySearch")
|
|
5169
|
-
}) : /* @__PURE__ */ (0, react_jsx_runtime.
|
|
5170
|
-
className:
|
|
5171
|
-
children:
|
|
5202
|
+
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("ul", {
|
|
5203
|
+
className: _dsh_plugin_shop_css_e3675a89_default.cards,
|
|
5204
|
+
children: [visible.map((entry) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(EntryCard, {
|
|
5172
5205
|
entry,
|
|
5173
5206
|
t,
|
|
5174
5207
|
install,
|
|
5175
5208
|
installStatus
|
|
5176
|
-
}) }, entry.name))
|
|
5177
|
-
|
|
5209
|
+
}) }, entry.name)), incremental && visibleCount < filtered.length && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", {
|
|
5210
|
+
ref: sentinelRef,
|
|
5211
|
+
className: _dsh_plugin_shop_css_e3675a89_default.cardsSentry,
|
|
5212
|
+
"data-shop-sentry": true,
|
|
5213
|
+
"aria-hidden": "true"
|
|
5214
|
+
})]
|
|
5215
|
+
}), incremental && visibleCount < filtered.length && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
5216
|
+
className: _dsh_plugin_shop_css_e3675a89_default.showingLine,
|
|
5217
|
+
"aria-live": "polite",
|
|
5218
|
+
children: t("showing", {
|
|
5219
|
+
shown: String(visibleCount),
|
|
5220
|
+
total: String(filtered.length)
|
|
5221
|
+
})
|
|
5222
|
+
})] }),
|
|
5178
5223
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(OutdatedSection, {
|
|
5179
5224
|
state: outdatedState,
|
|
5180
5225
|
tiers,
|
|
@@ -5189,34 +5234,34 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
5189
5234
|
//#endregion
|
|
5190
5235
|
//#region src/client/index.ts
|
|
5191
5236
|
/** Dictionary namespace owned by this plugin. */
|
|
5192
|
-
const NS = "settings.
|
|
5237
|
+
const NS = "settings.shop";
|
|
5193
5238
|
/** Services required by the tab registration and the Remote mount.
|
|
5194
5239
|
*
|
|
5195
|
-
* `remote.
|
|
5240
|
+
* `remote.shop` is deliberately ABSENT: this package both mounts its own
|
|
5196
5241
|
* Remote (the assembly does not know it, §7.3) and consumes it, and cordis
|
|
5197
5242
|
* will not let one package do both through the inject face. Declaring the
|
|
5198
|
-
* face makes the boot's activation gate wait for the `remote.
|
|
5243
|
+
* face makes the boot's activation gate wait for the `remote.shop` service —
|
|
5199
5244
|
* which only this package's own apply can register — and the real web boot
|
|
5200
|
-
* deadlocked on exactly that ("waiting for service: remote.
|
|
5201
|
-
* namespace is therefore read through the reflect
|
|
5245
|
+
* deadlocked on exactly that ("waiting for service: remote.shop"). The
|
|
5246
|
+
* namespace is therefore read through the reflect shop instead (`ctx.get`,
|
|
5202
5247
|
* see apply), which has no inject requirement. */
|
|
5203
5248
|
const inject = [
|
|
5204
5249
|
"remote",
|
|
5205
5250
|
"slots",
|
|
5206
5251
|
"locale"
|
|
5207
5252
|
];
|
|
5208
|
-
/** Mount the
|
|
5253
|
+
/** Mount the shop Remote and contribute the shop tab. */
|
|
5209
5254
|
async function apply(ctx) {
|
|
5210
5255
|
ctx.effect(() => ctx.locale.register(NS, {
|
|
5211
5256
|
zh,
|
|
5212
5257
|
en
|
|
5213
5258
|
}), "dsh-plugin-shop: dictionaries");
|
|
5214
5259
|
const dispose = await ctx.remote.$mount(TYPERT_REMOTE);
|
|
5215
|
-
ctx.effect(() => dispose, "dsh-plugin-shop:
|
|
5216
|
-
const ns = ctx.get("remote.
|
|
5217
|
-
if (ns === void 0) throw new Error("dsh-plugin-shop: the
|
|
5260
|
+
ctx.effect(() => dispose, "dsh-plugin-shop: shop remote mount");
|
|
5261
|
+
const ns = ctx.get("remote.shop");
|
|
5262
|
+
if (ns === void 0) throw new Error("dsh-plugin-shop: the shop remote did not register (service \"remote.shop\" missing after $mount)");
|
|
5218
5263
|
const unwrap = (result) => {
|
|
5219
|
-
if (!result.ok) throw new Error(`
|
|
5264
|
+
if (!result.ok) throw new Error(`shop remote: ${result.error.code}: ${result.error.message}`);
|
|
5220
5265
|
return result.value;
|
|
5221
5266
|
};
|
|
5222
5267
|
const injected = () => ({
|
|
@@ -5228,12 +5273,12 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
5228
5273
|
});
|
|
5229
5274
|
ctx.slots.inject("settings.plugins.tab", () => ctx.slots.register({
|
|
5230
5275
|
name: "settings.plugins.tab",
|
|
5231
|
-
id: "
|
|
5276
|
+
id: "shop",
|
|
5232
5277
|
order: 20,
|
|
5233
5278
|
label: () => ctx.locale.bind(NS)("tab"),
|
|
5234
5279
|
locale: NS,
|
|
5235
5280
|
inject: injected
|
|
5236
|
-
},
|
|
5281
|
+
}, ShopTab));
|
|
5237
5282
|
}
|
|
5238
5283
|
//#endregion
|
|
5239
5284
|
exports.NS = NS;
|