@restregular/dsh-powerup 0.2.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +10 -2
  2. package/client.js +258 -128
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -66,8 +66,9 @@ unload the dialog mid-flow. Use **Add plugin** with the new package version.
66
66
  inside the plugin's brand SVG artwork.
67
67
  - **Two icons, two jobs.** `icon.svg` is the 256px brand tile shown by the
68
68
  Plugin Manager. The sidebar uses the same double-chevron mark as a 16-grid,
69
- `fill:none`, `stroke:currentColor` line drawing, so it inherits the sidebar's
70
- text color in either theme. The reference line artwork is
69
+ `fill:none`, `stroke:currentColor` line drawing, but without the tile frame:
70
+ the mark gets the full grid, so the chevrons and the amber baseline never
71
+ collide with a border. The reference line artwork is
71
72
  `design/sidebar-icon.svg`; the runtime copy lives in `client.js`.
72
73
  - **No imports from Harness Client packages.** The menu is plain React + CSS and
73
74
  observes the trajectory package's own `data-*` contracts. If those attributes
@@ -80,6 +81,13 @@ unload the dialog mid-flow. Use **Add plugin** with the new package version.
80
81
  installation use the same `remote.pluginManager` calls as **Add plugin**. Only
81
82
  the process restart needs Host code: a loopback-only
82
83
  `/dsh-powerup/api/restart` route.
84
+ - **The dialog mirrors the host modal.** The backdrop is
85
+ `--dsw-alias-bg-mask-1` with the shared mask blur, the surface is
86
+ `--dsw-alias-bg-layer-2` with `--dsw-radius-panel` and
87
+ `--dsw-elevation-prominent`, and the primary button uses
88
+ `--dsw-alias-button-primary-fill` / `-hover`, so the dialog follows both
89
+ themes instead of inventing its own palette. The registry picker and version
90
+ list are custom controls built from `--dsw-alias-*` tokens.
83
91
 
84
92
  ## Development
85
93
 
package/client.js CHANGED
@@ -44,7 +44,7 @@
44
44
 
45
45
  const NS = 'dsh-powerup';
46
46
  const SETTINGS_KEY = 'dsh-powerup:settings:v1';
47
- const VERSION = '0.2.0';
47
+ const VERSION = '0.2.1';
48
48
  const MENU_GAP = 8;
49
49
  const MENU_WIDTH = 248;
50
50
 
@@ -121,6 +121,8 @@
121
121
  'update.loadingVersions': '正在从安装源读取版本…',
122
122
  'update.loading': '正在读取插件信息…',
123
123
  'update.chooseVersion': '选择版本',
124
+ 'update.hideVersions': '收起列表',
125
+ 'update.versionsCount': '共 {count} 个版本',
124
126
  'update.versionsFailed': '读取版本失败:{message}',
125
127
  'update.versionsEmpty': '安装源没有返回可用版本',
126
128
  'update.latest': '最新',
@@ -239,6 +241,8 @@
239
241
  'update.loadingVersions': 'Reading versions from the registry…',
240
242
  'update.loading': 'Reading the plugin…',
241
243
  'update.chooseVersion': 'Choose',
244
+ 'update.hideVersions': 'Hide list',
245
+ 'update.versionsCount': '{count} versions',
242
246
  'update.versionsFailed': 'Could not read versions: {message}',
243
247
  'update.versionsEmpty': 'The registry returned no versions',
244
248
  'update.latest': 'latest',
@@ -415,18 +419,19 @@
415
419
 
416
420
  function PowerUpLineIcon({ size = 16 }) {
417
421
  return h(Icon, { size },
418
- h('rect', {
419
- x: '1.65', y: '1.65', width: '12.7', height: '12.7', rx: '3.8',
420
- fill: 'none', stroke: 'currentColor', strokeWidth: '1.3',
422
+ h('path', {
423
+ d: 'M4.4 6.9 8 3.3l3.6 3.6',
424
+ fill: 'none', stroke: 'currentColor', strokeWidth: '1.4',
425
+ strokeLinecap: 'round', strokeLinejoin: 'round',
421
426
  }),
422
427
  h('path', {
423
- d: 'M4.2 5.8 8 2.7l3.8 3.1M4.2 10.9 8 7.8l3.8 3.1',
424
- fill: 'none', stroke: 'currentColor', strokeWidth: '1.3',
428
+ d: 'M4.4 11.7 8 8.1l3.6 3.6',
429
+ fill: 'none', stroke: 'currentColor', strokeWidth: '1.4',
425
430
  strokeLinecap: 'round', strokeLinejoin: 'round',
426
431
  }),
427
432
  h('path', {
428
- d: 'M5.8 13.1h4.4', fill: 'none', stroke: 'currentColor',
429
- strokeWidth: '1.3', strokeLinecap: 'round',
433
+ d: 'M6.3 13.9h3.4', fill: 'none', stroke: 'currentColor',
434
+ strokeWidth: '1.4', strokeLinecap: 'round',
430
435
  }),
431
436
  );
432
437
  }
@@ -578,6 +583,16 @@
578
583
  );
579
584
  }
580
585
 
586
+ function ChevronDownIcon({ size = 12 }) {
587
+ return h(Icon, { size },
588
+ h('path', {
589
+ d: 'm4 6 4 4 4-4',
590
+ fill: 'none', stroke: 'currentColor', strokeWidth: '1.4',
591
+ strokeLinecap: 'round', strokeLinejoin: 'round',
592
+ }),
593
+ );
594
+ }
595
+
581
596
  function WarnIcon({ size = 16 }) {
582
597
  return h(Icon, { size },
583
598
  h('path', {
@@ -648,56 +663,86 @@
648
663
  @keyframes dsh-powerup-toast-in{from{opacity:0;transform:translate(-50%,5px)}to{opacity:1;transform:translate(-50%,0)}}
649
664
  .dsh-powerup-update-button{flex:none;display:inline-flex;align-items:center;justify-content:center;width:28px;height:28px;padding:0;border:0;border-radius:var(--dsw-radius-sm,6px);background:transparent;color:var(--dsw-alias-label-caption);cursor:pointer}
650
665
  .dsh-powerup-update-button:hover{background:var(--dsw-alias-interactive-bg-hover,var(--dsw-alias-bg-layer-2));color:var(--dsw-alias-label-secondary)}
651
- .dsh-powerup-update-button:focus-visible{outline:2px solid var(--dsw-focus-ring-color,var(--dsw-alias-state-business-primary));outline-offset:1px}
652
- .dsh-powerup-update-mask{position:fixed;inset:0;z-index:1200;display:flex;align-items:center;justify-content:center;padding:24px;background:color-mix(in srgb,var(--dsw-alias-bg-base) 62%,transparent);pointer-events:auto}
653
- .dsh-powerup-update-dialog{display:flex;flex-direction:column;width:min(560px,100%);max-height:min(760px,calc(100vh - 48px));border:1px solid var(--dsw-alias-border-l2);border-radius:14px;background:var(--dsw-alias-bg-overlay,var(--dsw-alias-bg-layer-1));box-shadow:var(--dsw-elevation-prominent,0 24px 64px rgba(15,23,42,.28));color:var(--dsw-alias-label-primary);font-size:13px;line-height:1.5;overflow:hidden}
654
- .dsh-powerup-update-head{display:flex;align-items:center;gap:11px;padding:16px 18px 12px;border-bottom:1px solid var(--dsw-alias-border-l1)}
655
- .dsh-powerup-update-icon{flex:none;display:inline-flex;align-items:center;justify-content:center;width:30px;height:30px;border-radius:9px;background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-secondary)}
666
+ .dsh-powerup-update-mask{position:fixed;inset:0;z-index:1200;display:flex;align-items:center;justify-content:center;padding:24px;background:var(--dsw-alias-bg-mask-1);backdrop-filter:var(--dsw-mask-blur,blur(3px));pointer-events:auto;animation:dsh-powerup-update-fade .16s ease-out}
667
+ @keyframes dsh-powerup-update-fade{from{opacity:0}to{opacity:1}}
668
+ .dsh-powerup-update-dialog{box-sizing:border-box;position:relative;display:flex;flex-direction:column;width:min(560px,100%);max-height:min(760px,calc(100vh - 48px));max-height:min(760px,calc(100dvh - 48px));border-radius:var(--dsw-radius-panel,14px);background:var(--dsw-alias-bg-layer-2);box-shadow:var(--dsw-elevation-prominent);color:var(--dsw-alias-label-primary);font-size:13px;line-height:20px;overflow:hidden;animation:dsh-powerup-update-rise .18s cubic-bezier(.2,.8,.3,1)}
669
+ @keyframes dsh-powerup-update-rise{from{opacity:0;transform:translateY(6px) scale(.995)}to{opacity:1;transform:none}}
670
+ @media (prefers-reduced-motion:reduce){.dsh-powerup-update-mask,.dsh-powerup-update-dialog{animation:none}}
671
+ .dsh-powerup-update-head{display:flex;align-items:flex-start;justify-content:space-between;gap:12px;padding:22px 14px 12px 24px}
656
672
  .dsh-powerup-update-heading{flex:1 1 auto;min-width:0}
657
- .dsh-powerup-update-heading h2{margin:0;font-size:15px;font-weight:650;line-height:1.3}
658
- .dsh-powerup-update-heading p{margin:2px 0 0;color:var(--dsw-alias-label-tertiary);font-size:11.5px;line-height:1.4;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
659
- .dsh-powerup-update-close{flex:none;width:26px;height:26px;padding:0;border:0;border-radius:7px;background:transparent;color:var(--dsw-alias-label-tertiary);font-size:18px;line-height:1;cursor:pointer}
660
- .dsh-powerup-update-close:hover{background:var(--dsw-alias-interactive-bg-hover,var(--dsw-alias-bg-layer-2));color:var(--dsw-alias-label-primary)}
661
- .dsh-powerup-update-close:focus-visible{outline:2px solid var(--dsw-focus-ring-color,var(--dsw-alias-state-business-primary));outline-offset:1px}
662
- .dsh-powerup-update-body{display:flex;flex-direction:column;gap:14px;min-height:0;padding:16px 18px;overflow-y:auto;--dsh-scrollbar-thumb:var(--dsw-alias-scrollbar-bg-l2);--dsh-scrollbar-thumb-hover:var(--dsw-alias-scrollbar-hover-l2)}
663
- .dsh-powerup-update-name{overflow-wrap:anywhere;color:var(--dsw-alias-label-tertiary);font-family:var(--dsw-font-family-code,ui-monospace,SFMono-Regular,Consolas,monospace);font-size:11.5px;line-height:1.4}
664
- .dsh-powerup-update-meta{display:flex;flex-wrap:wrap;align-items:center;gap:8px;color:var(--dsw-alias-label-secondary);font-size:12px}
665
- .dsh-powerup-update-chip{padding:0 7px;border-radius:999px;background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-tertiary);font-size:10.5px;line-height:18px}
666
- .dsh-powerup-update-label{color:var(--dsw-alias-label-tertiary);font-size:11px;font-weight:600;letter-spacing:.04em;text-transform:uppercase}
667
- .dsh-powerup-update-field{display:flex;flex-direction:column;gap:6px}
668
- .dsh-powerup-update-row{display:flex;gap:8px}
669
- .dsh-powerup-update-input{flex:1 1 auto;min-width:0;height:38px;padding:0 12px;border:.5px solid var(--dsw-alias-border-l4);border-radius:8px;background:var(--dsw-alias-bg-layer-3);color:var(--dsw-alias-label-primary);font:inherit;font-size:13px;outline:none}
673
+ .dsh-powerup-update-heading h2{margin:0;font-size:16px;line-height:24px;font-weight:500;color:var(--dsw-alias-label-primary)}
674
+ .dsh-powerup-update-heading p{margin:2px 0 0;color:var(--dsw-alias-label-tertiary);font-family:var(--dsw-font-family-code,ui-monospace,SFMono-Regular,Consolas,monospace);font-size:11.5px;line-height:18px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
675
+ .dsh-powerup-update-close{flex:none;display:inline-flex;align-items:center;justify-content:center;width:28px;height:28px;padding:0;border:0;border-radius:var(--dsw-radius-sm,6px);background:transparent;color:var(--dsw-alias-label-secondary);font:inherit;font-size:18px;line-height:1;cursor:pointer}
676
+ .dsh-powerup-update-close:hover{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}
677
+ .dsh-powerup-update-body{display:flex;flex-direction:column;gap:20px;min-height:0;margin-top:8px;padding:0 24px 4px;overflow-y:auto;--dsh-scrollbar-thumb:var(--dsw-alias-scrollbar-bg-l2);--dsh-scrollbar-thumb-hover:var(--dsw-alias-scrollbar-hover-l2)}
678
+ .dsh-powerup-update-field{display:flex;flex-direction:column;gap:8px;min-width:0}
679
+ .dsh-powerup-update-label{display:block;color:var(--dsw-alias-label-secondary);font-size:12px;line-height:18px;font-weight:500}
680
+ .dsh-powerup-update-note{margin:0;color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:18px;overflow-wrap:anywhere}
681
+ .dsh-powerup-update-name{color:var(--dsw-alias-label-tertiary);font-family:var(--dsw-font-family-code,ui-monospace,SFMono-Regular,Consolas,monospace);font-size:11.5px;line-height:18px;overflow-wrap:anywhere}
682
+ .dsh-powerup-update-summary{display:flex;flex-direction:column;gap:2px;min-width:0}
683
+ .dsh-powerup-update-list-state{display:flex;flex-direction:column;gap:10px;padding:12px}
684
+ .dsh-powerup-update-now{display:flex;align-items:center;gap:10px;min-width:0}
685
+ .dsh-powerup-update-now .label{flex:none;color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:18px}
686
+ .dsh-powerup-update-now code{display:inline-flex;align-items:center;min-height:22px;padding:0 8px;border:.5px solid var(--dsw-alias-border-l1);border-radius:var(--dsw-radius-sm,6px);background:var(--dsw-alias-bg-layer-3);color:var(--dsw-alias-label-primary);font-family:var(--dsw-font-family-code,ui-monospace,SFMono-Regular,Consolas,monospace);font-size:11.5px;line-height:20px;font-variant-numeric:tabular-nums}
687
+ .dsh-powerup-update-row{display:flex;align-items:stretch;gap:8px}
688
+ .dsh-powerup-update-input{flex:1 1 auto;min-width:0;height:38px;padding:0 12px;border:.5px solid var(--dsw-alias-border-l4);border-radius:var(--dsw-radius-md,8px);background:var(--dsw-alias-bg-layer-3);color:var(--dsw-alias-label-primary);font:inherit;font-size:13px;line-height:20px;outline:none;transition:border-color .14s ease,box-shadow .14s ease}
689
+ .dsh-powerup-update-input::placeholder{color:var(--dsw-alias-label-caption)}
670
690
  .dsh-powerup-update-input:focus{border-color:var(--dsw-alias-state-business-primary);box-shadow:inset 0 0 0 .5px var(--dsw-alias-state-business-primary)}
671
- .dsh-powerup-update-toggle{flex:none;height:38px;padding:0 12px;border:.5px solid var(--dsw-alias-border-l3);border-radius:8px;background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-secondary);font:inherit;font-size:12.5px;cursor:pointer}
672
- .dsh-powerup-update-toggle:hover{background:var(--dsw-alias-interactive-bg-hover,var(--dsw-alias-bg-layer-3));color:var(--dsw-alias-label-primary)}
673
- .dsh-powerup-update-toggle:focus-visible{outline:2px solid var(--dsw-focus-ring-color,var(--dsw-alias-state-business-primary));outline-offset:1px}
674
- .dsh-powerup-update-list{display:flex;flex-direction:column;max-height:220px;overflow-y:auto;border:1px solid var(--dsw-alias-border-l1);border-radius:8px;background:var(--dsw-alias-bg-layer-1);--dsh-scrollbar-thumb:var(--dsw-alias-scrollbar-bg-l2);--dsh-scrollbar-thumb-hover:var(--dsw-alias-scrollbar-hover-l2)}
675
- .dsh-powerup-update-version{display:flex;align-items:center;gap:8px;width:100%;padding:7px 11px;border:0;background:transparent;color:var(--dsw-alias-label-primary);font:inherit;font-size:12.5px;text-align:left;cursor:pointer}
676
- .dsh-powerup-update-version:hover{background:var(--dsw-alias-interactive-bg-hover,var(--dsw-alias-bg-layer-2))}
677
- .dsh-powerup-update-version[aria-selected=true]{background:var(--dsw-alias-bg-layer-2)}
678
- .dsh-powerup-update-version:focus-visible{outline:2px solid var(--dsw-focus-ring-color,var(--dsw-alias-state-business-primary));outline-offset:-2px}
679
- .dsh-powerup-update-tag{margin-left:auto;padding:0 6px;border-radius:999px;background:var(--dsw-alias-bg-layer-3);color:var(--dsw-alias-label-tertiary);font-size:10px;line-height:17px}
680
- .dsh-powerup-update-status{display:flex;align-items:center;gap:8px;color:var(--dsw-alias-label-secondary);font-size:12.5px}
681
- .dsh-powerup-update-spinner{flex:none;width:14px;height:14px;border:2px solid var(--dsw-alias-border-l3);border-top-color:var(--dsw-alias-brand-primary);border-radius:50%;animation:dsh-powerup-spin .8s linear infinite}
691
+ .dsh-powerup-update-toggle{flex:none;display:inline-flex;align-items:center;gap:6px;height:38px;padding:0 12px;border:.5px solid var(--dsw-alias-border-l3);border-radius:var(--dsw-radius-md,8px);background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-secondary);font:inherit;font-size:12.5px;line-height:18px;cursor:pointer;transition:background .14s ease,border-color .14s ease,color .14s ease}
692
+ .dsh-powerup-update-toggle:hover{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}
693
+ .dsh-powerup-update-toggle[aria-expanded=true]{border-color:var(--dsw-alias-state-business-primary);background:var(--dsw-alias-bg-layer-3);color:var(--dsw-alias-label-primary)}
694
+ .dsh-powerup-update-toggle .chevron{display:inline-flex;color:var(--dsw-alias-label-tertiary);transition:transform .16s ease}
695
+ .dsh-powerup-update-toggle[aria-expanded=true] .chevron{transform:rotate(180deg);color:var(--dsw-alias-label-secondary)}
696
+ .dsh-powerup-update-list{display:flex;flex-direction:column;max-height:240px;overflow-y:auto;border:.5px solid var(--dsw-alias-border-l2);border-radius:var(--dsw-radius-lg,10px);background:var(--dsw-alias-bg-layer-1);--dsh-scrollbar-thumb:var(--dsw-alias-scrollbar-bg-l2);--dsh-scrollbar-thumb-hover:var(--dsw-alias-scrollbar-hover-l2)}
697
+ .dsh-powerup-update-list-head{position:sticky;top:0;z-index:1;display:flex;align-items:center;justify-content:space-between;gap:8px;padding:7px 12px;border-bottom:.5px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-tertiary);font-size:11px;line-height:16px}
698
+ .dsh-powerup-update-version{display:flex;align-items:center;gap:8px;width:100%;min-height:34px;padding:0 12px;border:0;background:transparent;color:var(--dsw-alias-label-primary);font:inherit;font-size:12.5px;line-height:18px;text-align:left;cursor:pointer;font-variant-numeric:tabular-nums}
699
+ .dsh-powerup-update-version:hover{background:var(--dsw-alias-interactive-bg-hover)}
700
+ .dsh-powerup-update-version[aria-selected=true]{background:var(--dsw-alias-interactive-bg-active)}
701
+ .dsh-powerup-update-trailing{display:inline-flex;align-items:center;gap:8px;margin-left:auto}
702
+ .dsh-powerup-update-tag{padding:0 6px;border:.5px solid var(--dsw-alias-border-l2);border-radius:999px;background:transparent;color:var(--dsw-alias-label-tertiary);font-size:10px;line-height:16px}
703
+ .dsh-powerup-update-check{display:inline-flex;color:var(--dsw-alias-state-business-primary)}
704
+ .dsh-powerup-update-status{display:flex;align-items:center;gap:10px;color:var(--dsw-alias-label-secondary);font-size:13px;line-height:20px}
705
+ .dsh-powerup-update-spinner{flex:none;width:14px;height:14px;border:2px solid color-mix(in srgb,var(--dsw-alias-state-business-primary) 24%,transparent);border-top-color:var(--dsw-alias-state-business-primary);border-radius:50%;animation:dsh-powerup-spin .8s linear infinite}
682
706
  @keyframes dsh-powerup-spin{to{transform:rotate(360deg)}}
683
707
  @media (prefers-reduced-motion:reduce){.dsh-powerup-update-spinner{animation:none}}
684
- .dsh-powerup-update-log{margin:0;max-height:140px;overflow:auto;padding:8px 10px;border-radius:8px;background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-secondary);font-family:var(--dsw-font-family-code,ui-monospace,SFMono-Regular,Consolas,monospace);font-size:11px;line-height:1.5;white-space:pre-wrap;overflow-wrap:anywhere}
685
- .dsh-powerup-update-error{display:flex;align-items:flex-start;gap:8px;padding:9px 11px;border-radius:8px;background:color-mix(in srgb,var(--dsw-alias-state-error-primary) 12%,transparent);color:var(--dsw-alias-state-error-primary);font-size:12px;line-height:1.5}
686
- .dsh-powerup-update-error svg{flex:none;margin-top:1px}
687
- .dsh-powerup-update-error span{min-width:0;overflow-wrap:anywhere}
688
- .dsh-powerup-update-note{margin:0;color:var(--dsw-alias-label-tertiary);font-size:11.5px;line-height:1.55}
689
- .dsh-powerup-update-registry{display:flex;flex-wrap:wrap;align-items:center;gap:8px}
690
- .dsh-powerup-update-select{height:30px;max-width:100%;padding:0 8px;border:.5px solid var(--dsw-alias-border-l3);border-radius:7px;background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-primary);font:inherit;font-size:12px;outline:none}
691
- .dsh-powerup-update-select:focus-visible{outline:2px solid var(--dsw-focus-ring-color,var(--dsw-alias-state-business-primary));outline-offset:1px}
692
- .dsh-powerup-update-foot{display:flex;align-items:center;justify-content:flex-end;gap:8px;padding:12px 18px 16px;border-top:1px solid var(--dsw-alias-border-l1)}
693
- .dsh-powerup-update-primary{height:32px;padding:0 14px;border:0;border-radius:8px;background:var(--dsw-alias-brand-primary);color:var(--dsw-alias-label-primary-foreground,var(--dsw-alias-bg-layer-1));font:inherit;font-size:12.5px;font-weight:600;cursor:pointer}
694
- .dsh-powerup-update-primary:hover:not(:disabled){opacity:.9}
695
- .dsh-powerup-update-primary:disabled{opacity:.5;cursor:default}
696
- .dsh-powerup-update-primary:focus-visible{outline:2px solid var(--dsw-focus-ring-color,var(--dsw-alias-state-business-primary));outline-offset:2px}
697
- .dsh-powerup-update-ghost{height:32px;padding:0 14px;border:1px solid var(--dsw-alias-border-l3);border-radius:8px;background:transparent;color:var(--dsw-alias-label-primary);font:inherit;font-size:12.5px;cursor:pointer}
698
- .dsh-powerup-update-ghost:hover{background:var(--dsw-alias-interactive-bg-hover,var(--dsw-alias-bg-layer-2))}
699
- .dsh-powerup-update-ghost:focus-visible{outline:2px solid var(--dsw-focus-ring-color,var(--dsw-alias-state-business-primary));outline-offset:2px}
700
- @media (max-width:680px){.dsh-powerup-page{padding:20px 16px 42px}.dsh-powerup-actions{grid-template-columns:minmax(0,1fr)}.dsh-powerup-hero-art{width:54px;height:54px}.dsh-powerup-hero h1{font-size:19px}.dsh-powerup-card-head{flex-wrap:wrap}.dsh-powerup-switch{margin-left:auto}.dsh-powerup-update-mask{padding:12px}.dsh-powerup-update-dialog{max-height:calc(100vh - 24px)}}
708
+ .dsh-powerup-update-log{margin:0;max-height:160px;overflow:auto;padding:10px 12px;border:.5px solid var(--dsw-alias-border-l1);border-radius:var(--dsw-radius-md,8px);background:var(--dsw-alias-bg-layer-1);color:var(--dsw-alias-label-secondary);font-family:var(--dsw-font-family-code,ui-monospace,SFMono-Regular,Consolas,monospace);font-size:11px;line-height:17px;white-space:pre-wrap;overflow-wrap:anywhere}
709
+ .dsh-powerup-update-notice{display:flex;align-items:flex-start;gap:8px;padding:10px 12px;border:.5px solid transparent;border-radius:var(--dsw-radius-md,8px);font-size:12.5px;line-height:18px;color:var(--dsw-alias-label-primary)}
710
+ .dsh-powerup-update-notice svg{flex:none;margin-top:2px}
711
+ .dsh-powerup-update-notice span{min-width:0;overflow-wrap:anywhere}
712
+ .dsh-powerup-update-notice-copy{display:flex;flex-direction:column;gap:2px;min-width:0}
713
+ .dsh-powerup-update-notice-title{font-weight:500;color:var(--dsw-alias-label-primary);overflow-wrap:anywhere}
714
+ .dsh-powerup-update-notice.error{border-color:color-mix(in srgb,var(--dsw-alias-state-error-primary) 30%,transparent);background:color-mix(in srgb,var(--dsw-alias-state-error-primary) 8%,transparent)}
715
+ .dsh-powerup-update-notice.error svg{color:var(--dsw-alias-state-error-primary)}
716
+ .dsh-powerup-update-notice.warn{border-color:color-mix(in srgb,var(--dsw-alias-state-warn-primary) 30%,transparent);background:var(--dsw-alias-state-warn-tertiary)}
717
+ .dsh-powerup-update-notice.warn svg{color:var(--dsw-alias-state-warn-primary)}
718
+ .dsh-powerup-update-notice.success{border-color:color-mix(in srgb,var(--dsw-alias-state-success-primary) 28%,transparent);background:color-mix(in srgb,var(--dsw-alias-state-success-primary) 8%,transparent)}
719
+ .dsh-powerup-update-notice.success svg{color:var(--dsw-alias-state-success-primary)}
720
+ .dsh-powerup-update-registry{display:flex;flex-direction:column;gap:8px}
721
+ .dsh-powerup-update-select{position:relative}
722
+ .dsh-powerup-update-select-trigger{display:flex;align-items:center;gap:10px;width:100%;height:38px;padding:0 12px;border:.5px solid var(--dsw-alias-border-l4);border-radius:var(--dsw-radius-md,8px);background:var(--dsw-alias-bg-layer-3);color:var(--dsw-alias-label-primary);font:inherit;font-size:13px;line-height:20px;text-align:left;cursor:pointer;transition:border-color .14s ease,box-shadow .14s ease}
723
+ .dsh-powerup-update-select-trigger:hover{background:var(--dsw-alias-bg-layer-2)}
724
+ .dsh-powerup-update-select-trigger[aria-expanded=true]{border-color:var(--dsw-alias-state-business-primary);box-shadow:inset 0 0 0 .5px var(--dsw-alias-state-business-primary)}
725
+ .dsh-powerup-update-select-value{flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
726
+ .dsh-powerup-update-select-host{flex:none;color:var(--dsw-alias-label-tertiary);font-size:11.5px}
727
+ .dsh-powerup-update-select-trigger .chevron{flex:none;display:inline-flex;color:var(--dsw-alias-label-tertiary);transition:transform .16s ease}
728
+ .dsh-powerup-update-select-trigger[aria-expanded=true] .chevron{transform:rotate(180deg)}
729
+ .dsh-powerup-update-select-menu{display:flex;flex-direction:column;padding:4px;border:.5px solid var(--dsw-alias-border-l2);border-radius:var(--dsw-radius-lg,10px);background:var(--dsw-alias-bg-layer-2);box-shadow:var(--dsw-elevation-prominent)}
730
+ .dsh-powerup-update-option{display:flex;align-items:flex-start;gap:10px;width:100%;padding:8px 10px;border:0;border-radius:var(--dsw-radius-md,8px);background:transparent;color:var(--dsw-alias-label-primary);font:inherit;text-align:left;cursor:pointer}
731
+ .dsh-powerup-update-option:hover{background:var(--dsw-alias-interactive-bg-hover)}
732
+ .dsh-powerup-update-option[aria-selected=true]{background:var(--dsw-alias-interactive-bg-active)}
733
+ .dsh-powerup-update-option-copy{display:flex;flex:1 1 auto;flex-direction:column;gap:1px;min-width:0}
734
+ .dsh-powerup-update-option-title{color:var(--dsw-alias-label-primary);font-size:12.5px;line-height:18px}
735
+ .dsh-powerup-update-option-host{color:var(--dsw-alias-label-tertiary);font-size:11px;line-height:16px;overflow-wrap:anywhere}
736
+ .dsh-powerup-update-option .dsh-powerup-update-check{flex:none;margin-top:2px}
737
+ .dsh-powerup-update-foot{display:flex;align-items:center;justify-content:flex-end;gap:8px;padding:16px 24px 22px;border-top:.5px solid var(--dsw-alias-border-l1)}
738
+ .dsh-powerup-update-primary{height:36px;padding:0 14px;border:0;border-radius:var(--dsw-radius-md,8px);background:var(--dsw-alias-button-primary-fill,var(--dsw-alias-brand-primary));color:var(--dsw-alias-label-primary-foreground);font:inherit;font-size:14px;line-height:22px;cursor:pointer;transition:background .14s ease}
739
+ .dsh-powerup-update-primary:hover:not(:disabled){background:var(--dsw-alias-button-primary-hover,var(--dsw-alias-brand-primary))}
740
+ .dsh-powerup-update-primary:disabled{opacity:.4;cursor:not-allowed}
741
+ .dsh-powerup-update-ghost{height:36px;padding:0 14px;border:0;border-radius:var(--dsw-radius-md,8px);background:transparent;color:var(--dsw-alias-label-primary);font:inherit;font-size:14px;line-height:22px;cursor:pointer}
742
+ .dsh-powerup-update-ghost:hover{background:var(--dsw-alias-interactive-bg-hover)}
743
+ .dsh-powerup-update-ghost:active{background:var(--dsw-alias-interactive-bg-active)}
744
+ .dsh-powerup-update-close:focus-visible,.dsh-powerup-update-toggle:focus-visible,.dsh-powerup-update-version:focus-visible,.dsh-powerup-update-select-trigger:focus-visible,.dsh-powerup-update-option:focus-visible,.dsh-powerup-update-primary:focus-visible,.dsh-powerup-update-ghost:focus-visible,.dsh-powerup-update-button:focus-visible{outline:var(--dsw-focus-ring-width,2px) solid var(--dsw-focus-ring-color,var(--dsw-alias-state-business-primary));outline-offset:1px}
745
+ @media (max-width:680px){.dsh-powerup-page{padding:20px 16px 42px}.dsh-powerup-actions{grid-template-columns:minmax(0,1fr)}.dsh-powerup-hero-art{width:54px;height:54px}.dsh-powerup-hero h1{font-size:19px}.dsh-powerup-card-head{flex-wrap:wrap}.dsh-powerup-switch{margin-left:auto}.dsh-powerup-update-mask{padding:12px}.dsh-powerup-update-dialog{max-height:calc(100dvh - 24px)}.dsh-powerup-update-head{padding:18px 12px 10px 18px}.dsh-powerup-update-body{padding:0 18px 4px}.dsh-powerup-update-foot{padding:14px 18px 18px}}
701
746
  `;
702
747
 
703
748
  function installStyles(ctx) {
@@ -1446,6 +1491,7 @@
1446
1491
  const abortRef = useRef(null);
1447
1492
  const buttonsRef = useRef(new Set());
1448
1493
  const inputRef = useRef(null);
1494
+ const registryRef = useRef(null);
1449
1495
  const versionSeq = useRef(0);
1450
1496
  const tRef = useRef((key, params) => translateCurrent(key, params));
1451
1497
  tRef.current = (key, params) => translateCurrent(key, params);
@@ -1536,6 +1582,7 @@
1536
1582
  versionsRegistry: null,
1537
1583
  version: '',
1538
1584
  listOpen: true,
1585
+ registryOpen: false,
1539
1586
  error: null,
1540
1587
  formError: null,
1541
1588
  log: '',
@@ -1628,18 +1675,39 @@
1628
1675
  }
1629
1676
  }, [view === null ? null : view.phase]);
1630
1677
 
1631
- // Escape closes a dialog that is not in the middle of an operation.
1678
+ // Escape closes the innermost popover first: registry menu, then the
1679
+ // version list, then the dialog itself.
1632
1680
  useEffect(() => {
1633
1681
  if (view === null) return undefined;
1634
1682
  const onKeyDown = (event) => {
1635
1683
  if (event.key !== 'Escape') return;
1636
1684
  event.stopPropagation();
1685
+ if (view.registryOpen === true) {
1686
+ setView((current) => current === null ? current : { ...current, registryOpen: false });
1687
+ return;
1688
+ }
1689
+ if (view.phase === 'choose' && view.listOpen === true) {
1690
+ setView((current) => current === null ? current : { ...current, listOpen: false });
1691
+ return;
1692
+ }
1637
1693
  close();
1638
1694
  };
1639
1695
  document.addEventListener('keydown', onKeyDown, true);
1640
1696
  return () => document.removeEventListener('keydown', onKeyDown, true);
1641
1697
  }, [view, close]);
1642
1698
 
1699
+ // A click outside the custom registry select closes only its menu.
1700
+ useEffect(() => {
1701
+ if (view === null || view.registryOpen !== true) return undefined;
1702
+ const onPointerDown = (event) => {
1703
+ const root = registryRef.current;
1704
+ if (root !== null && event.target instanceof Node && root.contains(event.target)) return;
1705
+ setView((current) => current === null ? current : { ...current, registryOpen: false });
1706
+ };
1707
+ document.addEventListener('pointerdown', onPointerDown, true);
1708
+ return () => document.removeEventListener('pointerdown', onPointerDown, true);
1709
+ }, [view === null ? null : view.registryOpen]);
1710
+
1643
1711
  // Show pnpm output while an installation runs.
1644
1712
  useEffect(() => {
1645
1713
  if (remote === undefined || remote === null || typeof remote.$on !== 'function') return undefined;
@@ -1673,7 +1741,7 @@
1673
1741
  if (current === null) return;
1674
1742
  const choice = current.choices.find((item) => item.key === key);
1675
1743
  if (choice === undefined) return;
1676
- setView((state) => state === null ? state : { ...state, registryKey: key, formError: null });
1744
+ setView((state) => state === null ? state : { ...state, registryKey: key, registryOpen: false, formError: null });
1677
1745
  loadVersions(token, current.name, choice, current.choices, true);
1678
1746
  };
1679
1747
 
@@ -1822,12 +1890,23 @@
1822
1890
  supported ? h('button', { key: 'now', type: 'button', className: 'dsh-powerup-update-primary', disabled: view.restarting === true, onClick: restartNow }, view.restarting === true ? t('update.restarting') : t('update.restartNow')) : null,
1823
1891
  ].filter(Boolean);
1824
1892
  }
1825
- if (view.phase === 'restarting') return [];
1893
+ if (view.phase === 'restarting' || view.phase === 'working' || view.phase === 'loading') return [];
1826
1894
  return [
1827
1895
  h('button', { key: 'done', type: 'button', className: 'dsh-powerup-update-primary', onClick: close }, view.phase === 'done' ? t('update.doneButton') : t('update.close')),
1828
1896
  ];
1829
1897
  })();
1830
1898
 
1899
+ /** One tinted notice: the success/warn/error states share this chrome. */
1900
+ const notice = (tone, icon, title, message) => h('div', { className: `dsh-powerup-update-notice ${tone}` },
1901
+ icon,
1902
+ h('div', { className: 'dsh-powerup-update-notice-copy' },
1903
+ title === null || title === undefined ? null : h('span', { className: 'dsh-powerup-update-notice-title' }, title),
1904
+ message === null || message === undefined ? null : h('span', null, message),
1905
+ ),
1906
+ );
1907
+
1908
+ const currentChoice = view.choices.find((item) => item.key === view.registryKey) ?? view.choices[0];
1909
+
1831
1910
  const body = (() => {
1832
1911
  if (view.phase === 'loading') {
1833
1912
  return h('div', { className: 'dsh-powerup-update-status' },
@@ -1836,22 +1915,67 @@
1836
1915
  );
1837
1916
  }
1838
1917
  if (view.phase === 'self') {
1839
- return [
1840
- h('p', { className: 'dsh-powerup-update-note' }, t('update.selfDesc')),
1841
- ];
1918
+ return notice('warn', h(WarnIcon, { size: 15 }), t('update.selfTitle'), t('update.selfDesc'));
1842
1919
  }
1843
1920
  if (view.phase === 'blocked') {
1844
- return h('div', { className: 'dsh-powerup-update-error' },
1845
- h(WarnIcon, { size: 15 }),
1846
- h('span', null, view.error ?? t('update.notRemovable')),
1847
- );
1921
+ return notice('error', h(WarnIcon, { size: 15 }), t('update.unsupportedTitle'), view.error ?? t('update.notRemovable'));
1848
1922
  }
1849
1923
  if (view.phase === 'choose') {
1924
+ const rows = (() => {
1925
+ if (view.versionsState === 'loading') {
1926
+ return [h('div', { key: 'state', className: 'dsh-powerup-update-list-state' },
1927
+ h('div', { className: 'dsh-powerup-update-status' },
1928
+ h('span', { className: 'dsh-powerup-update-spinner', 'aria-hidden': 'true' }),
1929
+ t('update.loadingVersions'),
1930
+ ),
1931
+ )];
1932
+ }
1933
+ if (view.versionsState === 'error') {
1934
+ return [h('div', { key: 'state', className: 'dsh-powerup-update-list-state' },
1935
+ notice('error', h(WarnIcon, { size: 14 }), null, t('update.versionsFailed', { message: view.versionsError ?? '' })),
1936
+ h('button', {
1937
+ type: 'button',
1938
+ className: 'dsh-powerup-update-ghost',
1939
+ onClick: () => loadVersions(tokenRef.current, view.name, currentChoice, view.choices, false),
1940
+ }, t('update.retry')),
1941
+ )];
1942
+ }
1943
+ if ((view.versions ?? []).length === 0) {
1944
+ return [h('div', { key: 'state', className: 'dsh-powerup-update-list-state' },
1945
+ h('p', { className: 'dsh-powerup-update-note' }, t('update.versionsEmpty')),
1946
+ )];
1947
+ }
1948
+ return [
1949
+ h('div', { key: 'head', className: 'dsh-powerup-update-list-head' },
1950
+ h('span', null, t('update.versionsCount', { count: view.versions.length })),
1951
+ view.versionsRegistry === null || view.versionsRegistry === undefined
1952
+ ? null
1953
+ : h('span', { title: view.versionsRegistry.hint }, view.versionsRegistry.hint),
1954
+ ),
1955
+ ...view.versions.map((version) => h('button', {
1956
+ key: version,
1957
+ type: 'button',
1958
+ role: 'option',
1959
+ className: 'dsh-powerup-update-version',
1960
+ 'aria-selected': version === view.version ? 'true' : 'false',
1961
+ onClick: () => chooseVersion(version),
1962
+ },
1963
+ h('span', null, version),
1964
+ h('span', { className: 'dsh-powerup-update-trailing' },
1965
+ version === view.latest ? h('span', { className: 'dsh-powerup-update-tag' }, t('update.latest')) : null,
1966
+ version === view.version ? h('span', { className: 'dsh-powerup-update-check' }, h(CheckIcon, { size: 13 })) : null,
1967
+ ),
1968
+ )),
1969
+ ];
1970
+ })();
1850
1971
  return [
1851
- h('div', { key: 'name', className: 'dsh-powerup-update-name' }, view.name),
1852
- h('div', { key: 'meta', className: 'dsh-powerup-update-meta' },
1853
- h('span', null, `${t('update.current')} ${view.currentVersion ?? '—'}`),
1854
- view.installed === false ? h('span', { className: 'dsh-powerup-update-chip' }, t('update.installedChip')) : null,
1972
+ h('div', { key: 'summary', className: 'dsh-powerup-update-summary' },
1973
+ h('div', { className: 'dsh-powerup-update-now' },
1974
+ h('span', { className: 'label' }, t('update.current')),
1975
+ h('code', null, view.currentVersion ?? '—'),
1976
+ view.installed === false ? h('span', { className: 'dsh-powerup-update-note' }, t('update.installedChip')) : null,
1977
+ ),
1978
+ h('span', { className: 'dsh-powerup-update-name' }, view.name),
1855
1979
  ),
1856
1980
  h('div', { key: 'version', className: 'dsh-powerup-update-field' },
1857
1981
  h('label', { className: 'dsh-powerup-update-label', htmlFor: 'dsh-powerup-update-version' }, t('update.versionLabel')),
@@ -1874,49 +1998,48 @@
1874
1998
  type: 'button',
1875
1999
  className: 'dsh-powerup-update-toggle',
1876
2000
  'aria-expanded': showVersions ? 'true' : 'false',
2001
+ 'aria-controls': 'dsh-powerup-update-versions',
1877
2002
  onClick: () => setView((current) => current === null ? current : { ...current, listOpen: !(current.listOpen === true) }),
1878
- }, t('update.chooseVersion')),
2003
+ },
2004
+ showVersions ? t('update.hideVersions') : t('update.chooseVersion'),
2005
+ h('span', { className: 'chevron' }, h(ChevronDownIcon, { size: 12 })),
2006
+ ),
1879
2007
  ),
1880
- view.formError === null || view.formError === undefined ? null : h('p', { className: 'dsh-powerup-update-error' }, h(WarnIcon, { size: 14 }), h('span', null, view.formError)),
2008
+ view.formError === null || view.formError === undefined
2009
+ ? null
2010
+ : notice('error', h(WarnIcon, { size: 14 }), null, view.formError),
1881
2011
  ),
1882
- showVersions ? h('div', { key: 'versions', className: 'dsh-powerup-update-list' }, (() => {
1883
- if (view.versionsState === 'loading') {
1884
- return h('div', { className: 'dsh-powerup-update-status' },
1885
- h('span', { className: 'dsh-powerup-update-spinner', 'aria-hidden': 'true' }),
1886
- t('update.loadingVersions'),
1887
- );
1888
- }
1889
- if (view.versionsState === 'error') {
1890
- return h('div', { className: 'dsh-powerup-update-version' },
1891
- h('span', null, t('update.versionsFailed', { message: view.versionsError ?? '' })),
1892
- h('button', {
1893
- type: 'button',
1894
- className: 'dsh-powerup-update-ghost',
1895
- onClick: () => loadVersions(tokenRef.current, view.name, view.choices.find((item) => item.key === view.registryKey) ?? view.choices[0], view.choices, false),
1896
- }, t('update.retry')),
1897
- );
1898
- }
1899
- if ((view.versions ?? []).length === 0) {
1900
- return h('div', { className: 'dsh-powerup-update-version' }, t('update.versionsEmpty'));
1901
- }
1902
- return view.versions.map((version) => h('button', {
1903
- key: version,
1904
- type: 'button',
1905
- className: 'dsh-powerup-update-version',
1906
- 'aria-selected': version === view.version ? 'true' : 'false',
1907
- onClick: () => chooseVersion(version),
1908
- },
1909
- h('span', null, version),
1910
- version === view.latest ? h('span', { className: 'dsh-powerup-update-tag' }, t('update.latest')) : null,
1911
- ));
1912
- })()) : null,
1913
- h('div', { key: 'registry', className: 'dsh-powerup-update-registry' },
2012
+ showVersions ? h('div', { key: 'versions', id: 'dsh-powerup-update-versions', className: 'dsh-powerup-update-list', role: 'listbox', 'aria-label': t('update.versionLabel') }, rows) : null,
2013
+ h('div', { key: 'registry', className: 'dsh-powerup-update-field' },
1914
2014
  h('span', { className: 'dsh-powerup-update-label' }, t('update.registry')),
1915
- h('select', {
1916
- className: 'dsh-powerup-update-select',
1917
- value: view.registryKey,
1918
- onChange: (event) => chooseRegistry(event.target.value),
1919
- }, view.choices.map((choice) => h('option', { key: choice.key, value: choice.key }, `${choice.label} · ${choice.hint}`))),
2015
+ h('div', { className: 'dsh-powerup-update-select', ref: registryRef },
2016
+ h('button', {
2017
+ type: 'button',
2018
+ className: 'dsh-powerup-update-select-trigger',
2019
+ 'aria-haspopup': 'listbox',
2020
+ 'aria-expanded': view.registryOpen === true ? 'true' : 'false',
2021
+ onClick: () => setView((current) => current === null ? current : { ...current, registryOpen: !(current.registryOpen === true) }),
2022
+ },
2023
+ h('span', { className: 'dsh-powerup-update-select-value' }, currentChoice?.label ?? ''),
2024
+ h('span', { className: 'dsh-powerup-update-select-host' }, currentChoice?.hint ?? ''),
2025
+ h('span', { className: 'chevron' }, h(ChevronDownIcon, { size: 12 })),
2026
+ ),
2027
+ view.registryOpen === true ? h('div', { className: 'dsh-powerup-update-select-menu', role: 'listbox', 'aria-label': t('update.registry') },
2028
+ view.choices.map((choice) => h('button', {
2029
+ key: choice.key,
2030
+ type: 'button',
2031
+ role: 'option',
2032
+ className: 'dsh-powerup-update-option',
2033
+ 'aria-selected': choice.key === view.registryKey ? 'true' : 'false',
2034
+ onClick: () => chooseRegistry(choice.key),
2035
+ },
2036
+ h('span', { className: 'dsh-powerup-update-option-copy' },
2037
+ h('span', { className: 'dsh-powerup-update-option-title' }, choice.label),
2038
+ h('span', { className: 'dsh-powerup-update-option-host' }, choice.hint),
2039
+ ),
2040
+ choice.key === view.registryKey ? h('span', { className: 'dsh-powerup-update-check' }, h(CheckIcon, { size: 13 })) : null,
2041
+ ))) : null,
2042
+ ),
1920
2043
  view.versionsRegistry === null || view.versionsRegistry === undefined
1921
2044
  ? null
1922
2045
  : h('span', { className: 'dsh-powerup-update-note' }, t('update.registryFrom', { registry: view.versionsRegistry.hint })),
@@ -1934,7 +2057,9 @@
1934
2057
  h('span', { className: 'dsh-powerup-update-spinner', 'aria-hidden': 'true' }),
1935
2058
  label,
1936
2059
  ),
1937
- h('div', { key: 'name', className: 'dsh-powerup-update-name' }, view.name),
2060
+ h('div', { key: 'summary', className: 'dsh-powerup-update-summary' },
2061
+ h('span', { className: 'dsh-powerup-update-name' }, view.name),
2062
+ ),
1938
2063
  view.log === '' ? null : h('div', { key: 'log', className: 'dsh-powerup-update-field' },
1939
2064
  h('span', { className: 'dsh-powerup-update-label' }, t('update.log')),
1940
2065
  h('pre', { className: 'dsh-powerup-update-log' }, view.log),
@@ -1943,26 +2068,34 @@
1943
2068
  }
1944
2069
  if (view.phase === 'enable') {
1945
2070
  return [
1946
- h('div', { key: 'title', className: 'dsh-powerup-update-meta' },
1947
- h(CheckIcon, { size: 15 }),
1948
- h('span', null, t('update.enableTitle')),
2071
+ notice('success', h(CheckIcon, { size: 15 }), t('update.enableTitle'), t('update.enableDesc')),
2072
+ h('div', { key: 'summary', className: 'dsh-powerup-update-summary' },
2073
+ h('span', { className: 'dsh-powerup-update-name' }, view.name),
2074
+ h('div', { className: 'dsh-powerup-update-now' },
2075
+ h('span', { className: 'label' }, t('update.versionLabel')),
2076
+ h('code', null, view.installedVersion ?? '—'),
2077
+ ),
1949
2078
  ),
1950
- h('p', { key: 'desc', className: 'dsh-powerup-update-note' }, t('update.enableDesc')),
1951
- h('div', { key: 'name', className: 'dsh-powerup-update-name' }, `${view.name} · ${view.installedVersion ?? ''}`),
1952
- view.enableError === null || view.enableError === undefined ? null : h('div', { key: 'error', className: 'dsh-powerup-update-error' }, h(WarnIcon, { size: 14 }), h('span', null, t('update.enableFailed', { message: view.enableError }))),
2079
+ view.enableError === null || view.enableError === undefined
2080
+ ? null
2081
+ : notice('error', h(WarnIcon, { size: 14 }), t('update.errorTitle'), t('update.enableFailed', { message: view.enableError })),
1953
2082
  ];
1954
2083
  }
1955
2084
  if (view.phase === 'restart') {
1956
2085
  const supported = view.restart?.supported === true;
1957
2086
  return [
1958
- h('div', { key: 'title', className: 'dsh-powerup-update-meta' },
1959
- h(CheckIcon, { size: 15 }),
1960
- h('span', null, t('update.restartTitle')),
2087
+ notice('success', h(CheckIcon, { size: 15 }), t('update.restartTitle'), t('update.restartDesc')),
2088
+ h('div', { key: 'summary', className: 'dsh-powerup-update-summary' },
2089
+ h('span', { className: 'dsh-powerup-update-name' }, view.name),
2090
+ h('div', { className: 'dsh-powerup-update-now' },
2091
+ h('span', { className: 'label' }, t('update.versionLabel')),
2092
+ h('code', null, view.installedVersion ?? '—'),
2093
+ ),
1961
2094
  ),
1962
- h('p', { key: 'desc', className: 'dsh-powerup-update-note' }, t('update.restartDesc')),
1963
- h('div', { key: 'name', className: 'dsh-powerup-update-name' }, `${view.name} · ${view.installedVersion ?? ''}`),
1964
- supported ? null : h('p', { key: 'unsupported', className: 'dsh-powerup-update-note' }, t('update.restartUnsupported', { reason: view.restart?.reason ?? '' })),
1965
- view.restartError === null || view.restartError === undefined ? null : h('div', { key: 'error', className: 'dsh-powerup-update-error' }, h(WarnIcon, { size: 14 }), h('span', null, t('update.restartFailed', { message: view.restartError }))),
2095
+ supported ? null : notice('warn', h(WarnIcon, { size: 14 }), null, t('update.restartUnsupported', { reason: view.restart?.reason ?? '' })),
2096
+ view.restartError === null || view.restartError === undefined
2097
+ ? null
2098
+ : notice('error', h(WarnIcon, { size: 14 }), t('update.errorTitle'), t('update.restartFailed', { message: view.restartError })),
1966
2099
  ];
1967
2100
  }
1968
2101
  if (view.phase === 'restarting') {
@@ -1973,8 +2106,7 @@
1973
2106
  }
1974
2107
  if (view.phase === 'done') {
1975
2108
  return [
1976
- h('div', { key: 'title', className: 'dsh-powerup-update-meta' }, h(CheckIcon, { size: 15 }), h('span', null, t('update.doneTitle'))),
1977
- h('p', { key: 'desc', className: 'dsh-powerup-update-note' }, view.enabled === false
2109
+ notice('success', h(CheckIcon, { size: 15 }), t('update.doneTitle'), view.enabled === false
1978
2110
  ? t('update.doneDisabled', { name: view.name, version: view.installedVersion ?? '' })
1979
2111
  : t('update.doneInstalled', { name: view.name, version: view.installedVersion ?? '' })),
1980
2112
  view.restartSkipped === true ? h('p', { key: 'restart', className: 'dsh-powerup-update-note' }, t('update.doneRestart')) : null,
@@ -1982,9 +2114,8 @@
1982
2114
  }
1983
2115
  if (view.phase === 'error') {
1984
2116
  return [
1985
- h('div', { key: 'title', className: 'dsh-powerup-update-error' }, h(WarnIcon, { size: 15 }), h('span', null, t('update.errorTitle'))),
1986
- h('p', { key: 'message', className: 'dsh-powerup-update-note' }, view.error ?? t('update.unknown')),
1987
- h('div', { key: 'name', className: 'dsh-powerup-update-name' }, view.name),
2117
+ notice('error', h(WarnIcon, { size: 15 }), t('update.errorTitle'), view.error ?? t('update.unknown')),
2118
+ h('span', { key: 'name', className: 'dsh-powerup-update-name' }, view.name),
1988
2119
  ];
1989
2120
  }
1990
2121
  return null;
@@ -2003,9 +2134,8 @@
2003
2134
  'aria-labelledby': 'dsh-powerup-update-title',
2004
2135
  },
2005
2136
  h('div', { className: 'dsh-powerup-update-head' },
2006
- h('span', { className: 'dsh-powerup-update-icon' }, h(UpdateIcon, { size: 15 })),
2007
2137
  h('div', { className: 'dsh-powerup-update-heading' },
2008
- h('h2', { id: 'dsh-powerup-update-title' }, view.phase === 'self' ? t('update.selfTitle') : t('update.title')),
2138
+ h('h2', { id: 'dsh-powerup-update-title' }, t('update.title')),
2009
2139
  h('p', { title }, title),
2010
2140
  ),
2011
2141
  canClose ? h('button', { type: 'button', className: 'dsh-powerup-update-close', 'aria-label': t('update.close'), onClick: close }, '×') : null,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@restregular/dsh-powerup",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "description": "Power-Up — small, opt-in upgrades for DeepSeek Harness. Adds a right-click action menu to the Trajectory ledger and an update control for third-party plugins installed from the Plugins page, with version lookup, uninstall-and-reinstall through the Add plugin path, and an optional DSH restart. · 为 DeepSeek Harness 提供小型增强:在轨迹页面右键记录即可复制、引用、查看详情或从该记录 Fork;并在插件页为第三方已安装插件提供带版本查询的更新按钮,沿用「添加插件」的安装流程,并可重启 DSH 使更改生效。",
5
5
  "icon": "./icon.svg",
6
6
  "type": "module",