dsh-plugin-core-demo 0.6.0 → 0.7.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 (2) hide show
  1. package/dist/client.js +366 -148
  2. package/package.json +1 -1
package/dist/client.js CHANGED
@@ -186,6 +186,8 @@ var PICKER_CSS = `
186
186
  .dshpc-picker__option:hover{background:var(--dshpc-surface-sunken)}
187
187
  .dshpc-picker__option--active{background:var(--dshpc-open-bg);color:var(--dshpc-business)}
188
188
  .dshpc-picker__option--disabled{color:var(--dshpc-fg-dim);cursor:not-allowed}
189
+ /* \u9009\u9879\u6587\u5B57\u5403\u6389\u5269\u4F59\u5BBD\u5EA6\uFF1A\u8D85\u957F\u7701\u7565\u53F7\uFF08\u914D\u5408 MarqueeText hover \u8DD1\u9A6C\u706F\uFF09\uFF0C\u4E0D\u6491\u5BBD\u83DC\u5355\u3002 */
190
+ .dshpc-picker__option-label{flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
189
191
  .dshpc-picker__tick{width:12px;color:var(--dshpc-business)}
190
192
  .dshpc-picker__empty{padding:8px;color:var(--dshpc-fg-3);text-align:center}
191
193
  .dshpc-picker__degraded{
@@ -209,7 +211,7 @@ var CHIP_CSS = "\n/* \u4E09\u6761\u5C40\u90E8\u53D8\u91CF\u627F\u8F7D\u914D\u827
209
211
  var CODE_VIEWER_CSS = "/* CodeViewer\uFF08\u53EA\u8BFB CodeMirror \u67E5\u770B\u5668\uFF09\u6837\u5F0F\u3002\u7C7B\u540D\u56FA\u5B9A dshpc-cv*\uFF1B\u989C\u8272\u5403 --dshpc-* token\uFF0C\n \u6DF1\u8272\u7531 design \u7684 token \u6DF1\u8272\u6BB5\u81EA\u52A8\u751F\u6548\uFF08\u4E0D\u5199\u6B7B\u989C\u8272\u503C\uFF09\u3002 */\n.dshpc-cv{position:relative;display:flex;flex-direction:column;height:100%;min-height:0;}\n.dshpc-cv__copy{position:absolute;top:6px;right:6px;z-index:5;display:inline-flex;align-items:center;justify-content:center;width:28px;height:28px;padding:0;appearance:none;border:1px solid var(--dshpc-border,rgba(128,128,128,.35));border-radius:var(--dshpc-radius-sm,6px);background:var(--dshpc-surface-1,#fff);color:var(--dshpc-fg-2,rgba(128,128,128,.95));cursor:pointer;opacity:0;transition:opacity .12s var(--dshpc-ease,ease),background .12s,color .12s;}\n.dshpc-cv:hover .dshpc-cv__copy,.dshpc-cv__copy:focus-visible{opacity:1;}\n.dshpc-cv__copy:hover{background:var(--dshpc-hover,rgba(38,49,72,.06));color:var(--dshpc-fg,#1f2328);}\n.dshpc-cv__copy svg{width:16px;height:16px;}\n.dshpc-cv__editor{flex:1 1 auto;min-height:0;overflow:hidden;}\n.dshpc-cv__editor .cm-editor{height:100%;}\n.dshpc-cv__editor .cm-scroller{overflow:auto;}\n";
210
212
 
211
213
  // dist/ui/panel-dock-css.generated.js
212
- var PANEL_DOCK_CSS = "\n/* \u505C\u9760\u680F = **\u5E03\u5C40\u6210\u5458**\uFF0C\u4E0D\u662F\u6D6E\u5C42\uFF1A\u5B83\u5360\u5BBD\u5EA6\u3001\u628A\u4E3B\u533A\u771F\u6B63\u6324\u7A84\uFF08\u5144\u5F1F\u9879\u76EE 2026-09-28\uFF1A\n \u300C\u5206\u680F\u538B\u8FC7\u6765\uFF0C\u4E0D\u662F\u76D6\u4E0A\u53BB\u300D\uFF09\u3002\u6240\u4EE5\u8C03\u7528\u65B9\u5FC5\u987B\u628A\u5B83\u653E\u8FDB\u81EA\u5DF1\u7684 flex \u6839\u91CC\u3002 */\n.dshpc-dock{display:flex;flex:0 0 auto;align-self:stretch;min-width:0}\n\n/* \u5355\u680F\uFF1Asticky + 100vh \u8BA9\u5B83\u5728\u9875\u9762\u6EDA\u52A8\u65F6\u4FDD\u6301\u53EF\u89C1\uFF0C\u540C\u65F6\u4ECD\u7136\u5360\u5BBD\u5EA6\u3002\n \u26A0\uFE0F **\u672C\u6761\u523B\u610F\u4E0D\u8BBE z-index**\uFF1A\u5E03\u5C40\u6210\u5458\u4E00\u65E6\u5E26\u6B63 z-index\uFF0C\u5C31\u4F1A\u65E0\u6761\u4EF6\u538B\u8FC7\u5BBF\u4E3B portal \u5230 body \u7684\n \u5F39\u7A97\uFF08\u5144\u5F1F\u9879\u76EE 2026-10-05 \u771F\u673A\u4E8B\u6545\u300C\u4FA7\u8FB9\u680F\u76D6\u4F4F\u5BBF\u4E3B\u8BBE\u7F6E\u5F39\u7A97\u300D\uFF09\u3002\u5C42\u5E8F\u4EA4\u7ED9 DOM \u987A\u5E8F\u88C1\u51B3\u3002 */\n.dshpc-dock__panel{\n box-sizing:border-box;position:sticky;top:0;align-self:stretch;\n display:flex;flex-direction:column;flex:0 0 auto;\n /* \u9AD8\u5EA6\u9ED8\u8BA4\u89C6\u53E3\u9AD8\uFF08\u6574\u9875\u573A\u666F\uFF09\uFF1B\u5D4C\u5728\u5B9A\u9AD8\u5BB9\u5668\u91CC\u65F6\u7531\u8C03\u7528\u65B9\u7ED9 --dshpc-dock-h\uFF08\u5982 420px / 100%\uFF09\u3002 */\n height:var(--dshpc-dock-h,100vh);max-height:var(--dshpc-dock-h,100vh);min-width:0;\n background:var(--dshpc-surface-base);color:var(--dshpc-fg);\n border-left:1px solid var(--dshpc-border);\n box-shadow:var(--dshpc-shadow-2);\n}\n\n.dshpc-dock__head{\n flex:none;display:flex;align-items:center;gap:8px;\n /* \u53F3\u4FA7 34px = 8(\u8FB9\u8DDD) + 20(\u5173\u94AE) + 6(\u547C\u5438)\uFF1A\u7ED9\u7EDD\u5BF9\u5B9A\u4F4D\u7684\u5173\u94AE\u7559\u4F4D\uFF0C\u6807\u9898/extra \u4E0D\u4ECE\u5B83\u5E95\u4E0B\u94BB */\n padding:10px 34px 10px 14px;\n border-bottom:1px solid var(--dshpc-border-faint);\n}\n/* \u56FE\u6807\u4F4D / \u6807\u9898\u53F3\u4FA7\u7684\u5185\u5BB9\u4F4D\uFF1A\u6D88\u8D39\u65B9\u4F20 ReactNode\uFF0C\u53EF\u585E\u591A\u4E2A\uFF1B\u5E93\u53EA\u8D1F\u8D23\u6392\u5E03\uFF0C\u4E0D\u62A2\u5BBD\u5EA6\u3002 */\n.dshpc-dock__lead{display:inline-flex;align-items:center;gap:6px;flex:none;color:var(--dshpc-fg-2)}\n.dshpc-dock__extra{display:inline-flex;align-items:center;gap:6px;flex:none;margin-left:auto}\n/* \u81EA\u5B9A\u4E49\u5934\u90E8\uFF1A\u6574\u884C\u5F52\u8C03\u7528\u65B9 \u2014\u2014 \u4E0D\u52A0\u5185\u8FB9\u8DDD/\u8FB9\u6846/\u80CC\u666F\uFF0C\u4E5F\u4E0D\u7ED9\u5173\u94AE\u7559\u5185\u8054\u7A7A\u95F4\uFF08\u5173\u94AE\u662F\u7EDD\u5BF9\u5B9A\u4F4D\u7684\uFF09\u3002 */\n.dshpc-dock__head--custom{display:block;padding:0;border-bottom:none}\n.dshpc-dock__title{\n flex:1 1 auto;min-width:0;\n overflow:hidden;text-overflow:ellipsis;white-space:nowrap;\n font-size:var(--dshpc-font-md);font-weight:600;\n}\n/* \u5173\u95ED\u94AE\uFF1A20\xD720 \u65B9\u89D2\u56FE\u6807\u4F4D\uFF08\u4E0E Modal \u7684\u5173\u95ED\u94AE\u540C\u89C4\u683C\uFF0C\u4E0D\u501F Picker \u89E6\u53D1\u5668\u76AE\u80A4\uFF09\u3002 */\n.dshpc-dock__close{\n display:inline-flex;align-items:center;justify-content:center;flex:none;\n width:20px;height:20px;padding:0;border:none;border-radius:var(--dshpc-radius-sm);\n background:transparent;color:var(--dshpc-fg-3);\n font-family:inherit;font-size:13px;line-height:1;cursor:pointer;\n transition:background-color var(--dshpc-dur-fast) var(--dshpc-ease),color var(--dshpc-dur-fast) var(--dshpc-ease);\n}\n.dshpc-dock__close:hover{background:var(--dshpc-hover);color:var(--dshpc-fg)}\n.dshpc-dock__close:focus-visible{outline:2px solid var(--dshpc-focus);outline-offset:1px}\n/* \u5934\u90E8\u5173\u94AE\uFF1A\u7EDD\u5BF9\u5B9A\u4F4D\uFF0C\u4F4D\u7F6E\u4E0E\u5185\u7F6E\u5934\u5B8C\u5168\u4E00\u81F4\uFF08top 10 / right 8\uFF09\uFF1B\u81EA\u5B9A\u4E49\u5934\u4E5F\u7528\u8FD9\u4E00\u4E2A\u4F4D\u7F6E\u3002\n \u951A\u70B9\u662F\u9762\u677F\u672C\u8EAB\uFF08position:sticky \u5373\u5B9A\u4F4D\u4E0A\u4E0B\u6587\uFF09\uFF0C\u4E0D\u5728\u6EDA\u52A8\u5185\u5BB9\u91CC\uFF0C\u6240\u4EE5\u6B63\u6587\u6EDA\u52A8\u5B83\u4E0D\u8DDF\u6EDA\u3002 */\n.dshpc-dock__close--abs{position:absolute;top:10px;right:8px;z-index:8}\n/* \u6D6E\u52A8\u5173\u94AE\uFF1A\u65E0\u5934\u90E8\u9762\u677F\u7528\uFF0C\u7565\u6536\u4E00\u70B9\u8FB9\u8DDD\u3002 */\n.dshpc-dock__close--floating{\n position:absolute;top:6px;right:6px;z-index:8;\n background:var(--dshpc-surface-menu);border:1px solid var(--dshpc-border-faint);\n}\n\n/* \u5185\u5BB9\u533A\u81EA\u5DF1\u6EDA\uFF1A\u9762\u677F\u9AD8\u5EA6\u9501 100vh\uFF0C\u5185\u5BB9\u4E0D\u8BBE\u5185\u90E8\u6EDA\u52A8\u5C31\u4F1A\u628A\u6574\u9875\u6491\u9AD8\u3002 */\n.dshpc-dock__body{flex:1 1 auto;min-height:0;overflow:auto}\n\n/* \u62D6\u62FD\u6761\uFF1A\u5DE6\u7F18 6px \u547D\u4E2D\u533A\uFF0C**\u4E0D\u753B\u7EBF**\uFF0Chover/\u6309\u4F4F\u65F6\u624D\u6D6E\u51FA\u4E00\u6761\u6D45\u8272\u5E26\u3002\n z-index 7 \u5FC5\u987B\u9AD8\u4E8E\u9762\u677F\u5185\u5BB9\u91CC\u7684\u6D6E\u5C42\uFF08\u590D\u5236\u94AE\u4E00\u7C7B\uFF09\uFF0C\u5426\u5219\u547D\u4E2D\u533A\u4F1A\u88AB\u5185\u5BB9\u76D6\u4F4F\u3002 */\n.dshpc-dock__resizer{\n position:absolute;left:0;top:0;bottom:0;width:6px;\n z-index:7;cursor:col-resize;background:transparent;\n transition:background-color var(--dshpc-dur-fast) var(--dshpc-ease);\n}\n/* hover/\u6309\u4F4F\uFF1A\u4E0D\u586B\u7070\u5E26\uFF0C\u6539\u4E3A\u5B98\u65B9 work \u533A\u6307\u793A\u6761\u6837\u5F0F \u2014\u2014 \u5DE6\u7F18 2px \u84DD\u7AD6\u6761\u3001\u4E0A\u4E0B\u6E10\u9690\n \uFF08\u989C\u8272\u8D70 business \u84DD\u7684\u5B98\u65B9 alias\uFF0C\u660E\u6697\u81EA\u52A8\u8DDF\u968F\u5BBF\u4E3B\uFF1B\u547D\u4E2D\u533A\u4ECD\u662F 6px \u4E0D\u53D8\uFF09\u3002 */\n.dshpc-dock__resizer:hover,.dshpc-dock__resizer:active{\n background:linear-gradient(180deg,transparent,var(--dshpc-business) 30%,var(--dshpc-business) 70%,transparent) left center / 1px 100% no-repeat;\n}\n\n/* \u62D6\u52A8\u671F\uFF1A\u2460 <iframe>\uFF08PDF / HTML \u9884\u89C8\uFF09\u662F\u72EC\u7ACB\u6587\u6863\uFF0C\u4F1A\u541E\u6389\u7236\u6587\u6863\u7684 pointermove\uFF0C\n \u5411\u53F3\u62D6\u8FDB iframe \u5C31\u5361\u6B7B \u2014\u2014 \u6574\u7247\u8BA9\u51FA\u6307\u9488\u4E8B\u4EF6\uFF1B\u2461 contain \u628A\u91CD\u6392\u9694\u79BB\u5728\u680F\u5185\uFF0C\n \u5426\u5219\u6BCF\u5E27\u6539\u5BBD\u5EA6\u90FD\u4F1A\u7275\u52A8\u6574\u9875\u91CD\u6392\uFF08\u5144\u5F1F\u9879\u76EE 2026-10-04 \u771F\u673A\u300C\u632A\u5F88\u4E45\u624D\u52A8\u4E00\u4E0B\u300D\uFF09\u3002 */\n.dshpc-dock.dshpc-dock--resizing iframe{pointer-events:none}\n.dshpc-dock.dshpc-dock--resizing .dshpc-dock__panel{contain:layout paint;will-change:width}\n";
214
+ var PANEL_DOCK_CSS = "\n/* \u505C\u9760\u680F = **\u5E03\u5C40\u6210\u5458**\uFF0C\u4E0D\u662F\u6D6E\u5C42\uFF1A\u5B83\u5360\u5BBD\u5EA6\u3001\u628A\u4E3B\u533A\u771F\u6B63\u6324\u7A84\uFF08\u5144\u5F1F\u9879\u76EE 2026-09-28\uFF1A\n \u300C\u5206\u680F\u538B\u8FC7\u6765\uFF0C\u4E0D\u662F\u76D6\u4E0A\u53BB\u300D\uFF09\u3002\u6240\u4EE5\u8C03\u7528\u65B9\u5FC5\u987B\u628A\u5B83\u653E\u8FDB\u81EA\u5DF1\u7684 flex \u6839\u91CC\u3002 */\n.dshpc-dock{display:flex;flex:0 0 auto;align-self:stretch;min-width:0}\n/* \u5F00\u7740\u65F6\u7ED9\u4E3B\u533A\u6EDA\u52A8\u6761\u8BA9\u51FA\u4E00\u6761\u7F1D\uFF1A\u6EDA\u52A8\u6761\u8D34\u6B7B\u5206\u9694\u7EBF\u5F88\u96BE\u770B\uFF08\u7528\u6237 2026-10-28\uFF0C\u5BF9\u9F50\n dsh-better-sidebar \u7684\u7559\u767D\uFF09\u3002\u5168\u5173\u65F6\u6574\u6761 dock \u9000\u51FA\uFF0C\u7F1D\u9699\u4E00\u8D77\u6D88\u5931\u3001\u4E0D\u7559\u767D\u8FB9\u3002\n \u7F1D\u5BBD\u53EF\u7531\u8C03\u7528\u65B9\u76D6 --dshpc-dock-gap\uFF1BTS \u4FA7\u7684\u8BA9\u4F4D\u91CF\uFF08DOCK_GAP\uFF09\u8981\u4E0E\u5B83\u4E00\u81F4\u3002 */\n.dshpc-dock--open{margin-left:var(--dshpc-dock-gap,1px)}\n\n/* \u81EA\u52A8\u52A0\u7684\u5BBF\u4E3B\u884C\uFF08openFilePreview \u52A0 / \u5173\u95ED\u5373\u6458\uFF09\uFF1A\u6D88\u8D39\u65B9\u90A3\u884C\u4E0D\u5FC5\u81EA\u5DF1\u5199 flex\u3002\n \u53EA\u8BA9\u300C\u7B2C\u4E00\u4E2A\u975E\u9884\u89C8\u5B50\u9879\u300D\u5F53\u4E3B\u533A\u4F38\u5C55\uFF0C\u5176\u4F59\u76F4\u63A5\u5B50\u9879\u4E0D\u52A8\uFF08\u9875\u811A\u6761\u3001\u5DE5\u5177\u6761\u4E0D\u8BEF\u4F24\uFF09\uFF1B\n display \u4E0D\u5728\u8FD9\u91CC\u5199\u6B7B \u2014\u2014 \u672C\u6765\u5C31\u662F grid \u7B49\u5E03\u5C40\u7684\u5143\u7D20\u4FDD\u6301\u539F\u6837\uFF0C\u7531 TS \u4FA7\u6309\u8BA1\u7B97\u503C\u8865 flex\u3002 */\n.dshpc-dock-host{min-width:0;min-height:0}\n.dshpc-dock-host>:not([data-dshpc-file-preview]){min-width:0}\n.dshpc-dock-host>:first-child:not([data-dshpc-file-preview]){flex:1 1 auto}\n\n/* \u5355\u680F\uFF1Asticky + 100vh \u8BA9\u5B83\u5728\u9875\u9762\u6EDA\u52A8\u65F6\u4FDD\u6301\u53EF\u89C1\uFF0C\u540C\u65F6\u4ECD\u7136\u5360\u5BBD\u5EA6\u3002\n \u26A0\uFE0F **\u672C\u6761\u523B\u610F\u4E0D\u8BBE z-index**\uFF1A\u5E03\u5C40\u6210\u5458\u4E00\u65E6\u5E26\u6B63 z-index\uFF0C\u5C31\u4F1A\u65E0\u6761\u4EF6\u538B\u8FC7\u5BBF\u4E3B portal \u5230 body \u7684\n \u5F39\u7A97\uFF08\u5144\u5F1F\u9879\u76EE 2026-10-05 \u771F\u673A\u4E8B\u6545\u300C\u4FA7\u8FB9\u680F\u76D6\u4F4F\u5BBF\u4E3B\u8BBE\u7F6E\u5F39\u7A97\u300D\uFF09\u3002\u5C42\u5E8F\u4EA4\u7ED9 DOM \u987A\u5E8F\u88C1\u51B3\u3002 */\n.dshpc-dock__panel{\n box-sizing:border-box;position:sticky;top:0;align-self:stretch;\n display:flex;flex-direction:column;flex:0 0 auto;\n /* \u9AD8\u5EA6\u9ED8\u8BA4\u89C6\u53E3\u9AD8\uFF08\u6574\u9875\u573A\u666F\uFF09\uFF1B\u5D4C\u5728\u5B9A\u9AD8\u5BB9\u5668\u91CC\u65F6\u7531\u8C03\u7528\u65B9\u7ED9 --dshpc-dock-h\uFF08\u5982 420px / 100%\uFF09\u3002 */\n height:var(--dshpc-dock-h,100vh);max-height:var(--dshpc-dock-h,100vh);min-width:0;\n background:var(--dshpc-surface-base);color:var(--dshpc-fg);\n border-left:1px solid var(--dshpc-border);\n transition:border-color var(--dshpc-dur-fast) var(--dshpc-ease);\n box-shadow:var(--dshpc-shadow-2);\n /* \u5165\u573A\uFF1A\u4ECE 0 \u5BBD\u6ED1\u51FA\u6765\uFF08keyframes \u53EA\u5199 from\uFF0C\u7EC8\u70B9\u53D6\u5185\u8054 width\uFF09\uFF0C\u6253\u5F00 / \u8033\u6735\u5C55\u5F00\u90FD\u8D70\u8FD9\u6761\u3002 */\n animation:dshpc-dock-in .22s var(--dshpc-ease);\n}\n/* overflow:hidden \u53EA\u5728\u52A8\u753B\u524D\u6BB5\uFF08\u79BB\u6563\u5C5E\u6027\u5728 50% \u7FFB\u8F6C\uFF09\u2014\u2014\u5E73\u65F6\u4E0D\u80FD\u88C1\uFF0C\u5426\u5219\u6302\u5728\u5DE6\u7F18\u5916\u7684\n \u6536\u8D77\u94AE\u4F1A\u88AB\u5207\u6389\u4E00\u534A\u3002 */\n@keyframes dshpc-dock-in{from{width:0;opacity:0;overflow:hidden}}\n/* \u6536\u8D77\u7684\u51FA\u573A\uFF1A\u5BBD\u5EA6\u6536\u5230 0\u3001\u900F\u660E\u6DE1\u51FA\uFF1B\u843D\u5B9A\u540E\u7EC4\u4EF6\u624D\u771F\u6B63\u6458\u6389\u8FD9\u4E00\u680F\uFF08JS \u5EF6\u65F6 220ms \u914D\u5408\uFF09\u3002 */\n.dshpc-dock__panel--closing{\n width:0!important;min-width:0!important;opacity:0;border-left-width:0;\n transition:width .2s var(--dshpc-ease),opacity .2s var(--dshpc-ease),border-left-width .2s var(--dshpc-ease);\n}\n\n.dshpc-dock__head{\n flex:none;display:flex;align-items:center;gap:8px;\n /* \u53F3\u4FA7 34px = 8(\u8FB9\u8DDD) + 20(\u5173\u94AE) + 6(\u547C\u5438)\uFF1A\u7ED9\u7EDD\u5BF9\u5B9A\u4F4D\u7684\u5173\u94AE\u7559\u4F4D\uFF0C\u6807\u9898/extra \u4E0D\u4ECE\u5B83\u5E95\u4E0B\u94BB */\n padding:10px 34px 10px 14px;\n border-bottom:1px solid var(--dshpc-border-faint);\n}\n/* \u56FE\u6807\u4F4D / \u6807\u9898\u53F3\u4FA7\u7684\u5185\u5BB9\u4F4D\uFF1A\u6D88\u8D39\u65B9\u4F20 ReactNode\uFF0C\u53EF\u585E\u591A\u4E2A\uFF1B\u5E93\u53EA\u8D1F\u8D23\u6392\u5E03\uFF0C\u4E0D\u62A2\u5BBD\u5EA6\u3002 */\n.dshpc-dock__lead{display:inline-flex;align-items:center;gap:6px;flex:none;color:var(--dshpc-fg-2)}\n.dshpc-dock__extra{display:inline-flex;align-items:center;gap:6px;flex:none;margin-left:auto}\n/* \u81EA\u5B9A\u4E49\u5934\u90E8\uFF1A\u6574\u884C\u5F52\u8C03\u7528\u65B9 \u2014\u2014 \u4E0D\u52A0\u5185\u8FB9\u8DDD/\u8FB9\u6846/\u80CC\u666F\uFF0C\u4E5F\u4E0D\u7ED9\u5173\u94AE\u7559\u5185\u8054\u7A7A\u95F4\uFF08\u5173\u94AE\u662F\u7EDD\u5BF9\u5B9A\u4F4D\u7684\uFF09\u3002 */\n.dshpc-dock__head--custom{display:block;padding:0;border-bottom:none}\n.dshpc-dock__title{\n flex:1 1 auto;min-width:0;\n overflow:hidden;text-overflow:ellipsis;white-space:nowrap;\n font-size:var(--dshpc-font-md);font-weight:600;\n}\n/* \u5173\u95ED\u94AE\uFF1A20\xD720 \u65B9\u89D2\u56FE\u6807\u4F4D\uFF08\u4E0E Modal \u7684\u5173\u95ED\u94AE\u540C\u89C4\u683C\uFF0C\u4E0D\u501F Picker \u89E6\u53D1\u5668\u76AE\u80A4\uFF09\u3002 */\n.dshpc-dock__close{\n display:inline-flex;align-items:center;justify-content:center;flex:none;\n width:20px;height:20px;padding:0;border:none;border-radius:var(--dshpc-radius-sm);\n background:transparent;color:var(--dshpc-fg-3);\n font-family:inherit;font-size:13px;line-height:1;cursor:pointer;\n transition:background-color var(--dshpc-dur-fast) var(--dshpc-ease),color var(--dshpc-dur-fast) var(--dshpc-ease);\n}\n.dshpc-dock__close:hover{background:var(--dshpc-hover);color:var(--dshpc-fg)}\n.dshpc-dock__close:focus-visible{outline:2px solid var(--dshpc-focus);outline-offset:1px}\n/* \u5934\u90E8\u5173\u94AE\uFF1A\u7EDD\u5BF9\u5B9A\u4F4D\uFF0C\u4F4D\u7F6E\u4E0E\u5185\u7F6E\u5934\u5B8C\u5168\u4E00\u81F4\uFF08top 10 / right 8\uFF09\uFF1B\u81EA\u5B9A\u4E49\u5934\u4E5F\u7528\u8FD9\u4E00\u4E2A\u4F4D\u7F6E\u3002\n \u951A\u70B9\u662F\u9762\u677F\u672C\u8EAB\uFF08position:sticky \u5373\u5B9A\u4F4D\u4E0A\u4E0B\u6587\uFF09\uFF0C\u4E0D\u5728\u6EDA\u52A8\u5185\u5BB9\u91CC\uFF0C\u6240\u4EE5\u6B63\u6587\u6EDA\u52A8\u5B83\u4E0D\u8DDF\u6EDA\u3002 */\n.dshpc-dock__close--abs{position:absolute;top:10px;right:8px;z-index:8}\n/* \u6D6E\u52A8\u5173\u94AE\uFF1A\u65E0\u5934\u90E8\u9762\u677F\u7528\uFF0C\u7565\u6536\u4E00\u70B9\u8FB9\u8DDD\u3002 */\n.dshpc-dock__close--floating{\n position:absolute;top:6px;right:6px;z-index:8;\n background:var(--dshpc-surface-menu);border:1px solid var(--dshpc-border-faint);\n}\n\n/* \u5185\u5BB9\u533A\u81EA\u5DF1\u6EDA\uFF1A\u9762\u677F\u9AD8\u5EA6\u9501 100vh\uFF0C\u5185\u5BB9\u4E0D\u8BBE\u5185\u90E8\u6EDA\u52A8\u5C31\u4F1A\u628A\u6574\u9875\u6491\u9AD8\u3002 */\n.dshpc-dock__body{flex:1 1 auto;min-height:0;overflow:auto}\n\n/* \u62D6\u62FD\u6761\uFF1A\u5DE6\u7F18 6px \u547D\u4E2D\u533A\uFF0C**\u81EA\u5DF1\u4E0D\u753B\u4EFB\u4F55\u7EBF**\u3002\n hover / \u62D6\u52A8\u65F6\u628A\u9762\u677F\u81EA\u5DF1\u7684 border-left \u67D3\u6210\u84DD\uFF08\u7528\u6237 2026-10-28 \u56DB\u8F6E\uFF1A\u84DD\u7EBF\u53EA\u51C6\u6539\u539F\u7EBF\uFF0C\n \u4E0D\u51C6\u5728\u539F\u7EBF\u65C1\u8FB9\u52A0\u4E00\u6761 \u2014\u2014 \u4E4B\u524D\u5728 padding box \u5DE6\u7F18\u753B\u6E10\u53D8\uFF0C\u6B63\u597D\u53E0\u51FA\u53CC\u7EBF\uFF09\u3002\n \u547D\u4E2D\u533A\u5728 padding box \u4E0A\u3001border \u5728\u5B83\u5DE6\u5916\u4FA7\uFF0C\u6240\u4EE5\u53EA\u80FD\u6539\u9762\u677F\u7684 border \u8272\u3002\n z-index 7 \u5FC5\u987B\u9AD8\u4E8E\u9762\u677F\u5185\u5BB9\u91CC\u7684\u6D6E\u5C42\uFF08\u590D\u5236\u94AE\u4E00\u7C7B\uFF09\uFF0C\u5426\u5219\u547D\u4E2D\u533A\u4F1A\u88AB\u5185\u5BB9\u76D6\u4F4F\u3002 */\n.dshpc-dock__resizer{\n position:absolute;left:0;top:0;bottom:0;width:6px;\n z-index:7;cursor:col-resize;background:transparent;\n}\n.dshpc-dock__panel:has(> .dshpc-dock__resizer:hover),\n.dshpc-dock__panel--resizing{\n /* \u539F\u7EBF\u4FDD\u7559\u300C\u4E0A\u4E0B\u6E10\u9690\u300D\u5DE5\u4F5C\u533A\u6307\u793A\u6761\u8D28\u611F\uFF1A\u628A\u9762\u677F\u81EA\u5DF1\u7684 border-left \u6362\u6210\u540C\u6B3E\u6E10\u53D8\n \uFF08\u4E0D\u662F\u53E6\u52A0\u4E00\u6761\u7EBF\uFF09\u3002\u9762\u677F\u53EA\u6709\u8FD9\u4E00\u6761\u8FB9\u6846\u3001\u65E0\u5706\u89D2\uFF0C\u6240\u4EE5\u53EA\u4F5C\u7528\u5728\u7EBF\u4E0A\u3002 */\n border-image:linear-gradient(180deg,transparent,var(--dshpc-business) 30% 70%,transparent) 1;\n}\n\n/* \u62D6\u52A8\u671F\uFF1A\u2460 <iframe>\uFF08PDF / HTML \u9884\u89C8\uFF09\u662F\u72EC\u7ACB\u6587\u6863\uFF0C\u4F1A\u541E\u6389\u7236\u6587\u6863\u7684 pointermove\uFF0C\n \u5411\u53F3\u62D6\u8FDB iframe \u5C31\u5361\u6B7B \u2014\u2014 \u6574\u7247\u8BA9\u51FA\u6307\u9488\u4E8B\u4EF6\uFF1B\u2461 contain \u628A\u91CD\u6392\u9694\u79BB\u5728\u680F\u5185\uFF0C\n \u5426\u5219\u6BCF\u5E27\u6539\u5BBD\u5EA6\u90FD\u4F1A\u7275\u52A8\u6574\u9875\u91CD\u6392\uFF08\u5144\u5F1F\u9879\u76EE 2026-10-04 \u771F\u673A\u300C\u632A\u5F88\u4E45\u624D\u52A8\u4E00\u4E0B\u300D\uFF09\u3002 */\n.dshpc-dock.dshpc-dock--resizing iframe{pointer-events:none}\n.dshpc-dock.dshpc-dock--resizing .dshpc-dock__panel{contain:layout paint;will-change:width}\n\n/* \u6536\u8D77\u94AE\uFF1A**\u5F85\u5728\u9762\u677F\u81EA\u5DF1\u7684\u6846\u91CC**\uFF08\u7528\u6237 2026-10-28 \u4E09\u8F6E\uFF1A\u5360\u9762\u677F\u5185\u90E8\u7A7A\u95F4\uFF0C\u4E0D\u4F38\u5230\u5916\u9762\u53BB\uFF09\u3002\n left:0 \u4ECE\u5185\u4FA7\u8D34\u7740\u5206\u9694\u7EBF \u2014\u2014 \u8D34\u7EBF\u7684\u4E00\u8FB9\u4E0D\u63CF\u8FB9\uFF08\u7EBF\u662F\u9762\u677F\u81EA\u5DF1\u7684 border-left\uFF09\uFF0C\u9875\u7B7E\u4E0E\u7EBF\u4E0D\u91CD\u5408\u3002\n 20\xD744\uFF08\u7528\u6237 2026-10-28 \u56DB\u8F6E\u5B9A\u5C3A\u5BF8\uFF09\uFF1B\u5B9E\u8272\u5E95\uFF08--dshpc-plate\uFF0C\u660E\u6697\u5404\u6709\u5B9E\u503C\uFF09\uFF0Chover \u4EAE\u4E00\u6863\u3002\n padding-right:2px \u662F**\u89C6\u89C9\u5C45\u4E2D**\uFF1A\u53F3\u4FA7\u662F\u5706\u89D2\uFF0C\u7BAD\u5934\u5F80\u76F4\u7EBF\u90A3\u8FB9\u632A 1px\uFF08\u7528\u6237 2026-10-28 \u56DB\u8F6E\uFF09\u3002 */\n.dshpc-dock__collapse{\n position:absolute;left:0;top:50%;transform:translateY(-50%);\n z-index:8;display:inline-flex;align-items:center;justify-content:center;\n width:20px;height:44px;padding:0 2px 0 0;\n border-top:1px solid var(--dshpc-border);\n border-bottom:1px solid var(--dshpc-border);\n border-right:1px solid var(--dshpc-border);\n border-left:none;\n border-radius:0 var(--dshpc-radius-sm) var(--dshpc-radius-sm) 0;\n background:var(--dshpc-plate);color:var(--dshpc-fg-3);\n font-family:inherit;font-size:16px;line-height:1;cursor:pointer;\n transition:background-color var(--dshpc-dur-fast) var(--dshpc-ease),color var(--dshpc-dur-fast) var(--dshpc-ease);\n}\n.dshpc-dock__collapse:hover{background:var(--dshpc-plate-hover);color:var(--dshpc-fg)}\n.dshpc-dock__collapse:focus-visible{outline:2px solid var(--dshpc-focus);outline-offset:1px}\n\n/* \u6536\u8D77\u540E\u7684\u6D6E\u52A8\u8033\u6735\uFF1A**fixed \u8D34\u53F3\u7F18\u3001\u5782\u76F4\u5C45\u4E2D\u3001\u72EC\u7ACB\u4E8E\u5206\u680F**\uFF08\u7528\u6237 2026-10-28 \u5B9A\u7A3F\uFF1A\n \u5C0F\u9875\u7B7E\u6302\u4E2D\u95F4\u3001\u91CC\u9762\u653E\u9762\u677F\u56FE\u6807\u3001\u4E0D\u663E\u793A\u6587\u5B57\uFF0C\u7BAD\u5934\u4E0E\u6536\u8D77\u94AE\u53CD\u5411\uFF09\u3002\u591A\u4E2A\u6309\u6536\u8D77\u987A\u5E8F\u7EB5\u5411\u5806\u53E0\u3002\n z \u8D70 dock \u6863\uFF08\u4F4E\u4E8E\u5BBF\u4E3B\u5F39\u7A97\uFF09\uFF0C\u907F\u514D\u76D6\u4F4F\u5BBF\u4E3B portal \u5C42\u3002 */\n.dshpc-dock__ears{\n position:fixed;top:50%;right:0;transform:translateY(-50%);\n z-index:var(--dshpc-z-dock,1030);\n display:flex;flex-direction:column;gap:8px;align-items:flex-end;\n pointer-events:none;\n}\n.dshpc-dock__ear{\n pointer-events:auto;display:inline-flex;align-items:center;justify-content:center;\n /* \u4E0E\u6536\u8D77\u94AE**\u540C\u5C3A\u5BF8**\uFF0820\xD744\uFF0C\u7528\u6237 2026-10-28 \u56DB\u8F6E\uFF09\uFF1A\u4E0A/\u4E0B/\u5DE6\u63CF\u8FB9\uFF0C\u8D34\u53F3\u7F18\u7684\u4E00\u4FA7\u4E0D\u63CF\u3002\n \u5B9E\u8272\u5E95\uFF08--dshpc-plate\uFF09\uFF0C\u4E0D\u7528\u900F\u660E\u8272 \u2014\u2014 \u900F\u660E\u5E95\u4E0B\u900F\u51FA\u4E1C\u897F\u5F88\u96BE\u770B\u3002\n padding-left:2px \u662F**\u89C6\u89C9\u5C45\u4E2D**\uFF1A\u5DE6\u4FA7\u662F\u5706\u89D2\uFF0C\u7BAD\u5934\u5F80\u76F4\u7EBF\uFF08\u53F3\u7F18\uFF09\u90A3\u8FB9\u632A 1px\u3002 */\n width:20px;height:44px;box-sizing:border-box;padding:0 0 0 2px;\n border-top:1px solid var(--dshpc-border);\n border-bottom:1px solid var(--dshpc-border);\n border-left:1px solid var(--dshpc-border);\n border-right:none;\n border-radius:var(--dshpc-radius-sm) 0 0 var(--dshpc-radius-sm);\n background:var(--dshpc-plate);color:var(--dshpc-fg-2);\n cursor:pointer;font-family:inherit;line-height:1;\n animation:dshpc-ear-in .2s var(--dshpc-ease);\n transition:background-color var(--dshpc-dur-fast) var(--dshpc-ease),color var(--dshpc-dur-fast) var(--dshpc-ease);\n}\n/* \u5165\u573A\uFF1A\u4ECE\u53F3\u7F18\u5916\u6ED1\u8FDB\u6765\uFF0C\u522B\u300C\u7A81\u7136\u51FA\u73B0\u300D\uFF08\u7528\u6237 2026-10-28\uFF09\u3002 */\n@keyframes dshpc-ear-in{from{opacity:0;transform:translateX(14px)}}\n.dshpc-dock__ear:hover{background:var(--dshpc-plate-hover);color:var(--dshpc-fg)}\n.dshpc-dock__ear:focus-visible{outline:2px solid var(--dshpc-focus);outline-offset:1px}\n/* \u4E0E\u6536\u8D77\u94AE\u7684\u7BAD\u5934\u540C\u4E00\u5B57\u53F7\uFF0816px\uFF09\uFF1A\u6536\u8FDB\u53BB\u524D\u540E\u7BAD\u5934\u4E00\u6A21\u4E00\u6837\u5927\uFF08\u7528\u6237 2026-10-28\uFF09\u3002 */\n.dshpc-dock__ear-arrow{font-size:16px;color:var(--dshpc-fg-3)}\n.dshpc-dock__ear:hover .dshpc-dock__ear-arrow{color:var(--dshpc-fg)}\n/* \u52A8\u6548\u793C\u8C8C\uFF1A\u7CFB\u7EDF\u58F0\u660E\u51CF\u5C11\u52A8\u6548\u65F6\u5168\u90E8\u5173\u6389\uFF08\u4E0E Segmented \u540C\u4E00\u7EA6\u5B9A\uFF09\uFF0C\u6536\u8D77\u9000\u5316\u4E3A\u77AC\u65F6\u3001\u529F\u80FD\u4E0D\u53D7\u5F71\u54CD\u3002 */\n@media (prefers-reduced-motion:reduce){\n .dshpc-dock__panel{animation:none}\n .dshpc-dock__panel--closing{transition:none}\n .dshpc-dock__ear{animation:none}\n}\n";
213
215
 
214
216
  // dist/explorer/explorer-css.generated.js
215
217
  var EXPLORER_CSS = "/* \u5DE5\u4F5C\u533A\u6587\u4EF6\u6D4F\u89C8\u5668\uFF08dshpc-fb-*\uFF09\u3002\n *\n * \u5EA6\u91CF\u771F\u6E90 = \u5144\u5F1F\u9879\u76EE dsh-task-dispatch-table \u7684 src/client/archive-session-css.ts\n * \uFF08.dsh-tdt-sv-* \u5168\u65CF\uFF09\u3002**\u9010\u6761\u7167\u6284\uFF0C\u4E0D\u8BB8\u81EA\u5DF1\u4F30**\uFF1Apadding / gap / \u5706\u89D2 / \u5B57\u53F7 / \u884C\u9AD8 /\n * \u8FB9\u6846\u8272 / \u60AC\u505C\u8272 / \u900F\u660E\u5EA6\u52A8\u753B / \u6EA2\u51FA\u7B56\u7565\uFF0C\u4E00\u4E00\u5BF9\u5E94\uFF0C\u6539\u8FD9\u91CC\u4E4B\u524D\u5148\u53BB\u90A3\u8FB9\u5BF9\u539F\u6587\u3002\n * \u524D\u7F00\u4E0E\u53D8\u91CF\u540D\u6362\u6210\u672C\u4ED3\u53E3\u5F84\uFF08--tdt-* \u2192 --dshpc-*\uFF09\uFF0C\u6570\u503C\u4E0D\u6362\u3002\n *\n * \u63A7\u4EF6\uFF1A\u80FD\u6838\u5FC3\u5C31\u6838\u5FC3\uFF08\u9762\u5305\u5C51 = Button ghost\u3001\u884C\u5C3E = Button outline\u3001\u5C55\u5F00 / \u56FE\u6807 = IconButton\u3001\n * \u5206\u6BB5 = Segmented\u3001\u6587\u5B57 = MarqueeText\uFF09\u3002\u6838\u5FC3\u63A7\u4EF6\u81EA\u5E26\u7684 padding / \u9AD8\u5EA6 / \u76AE\u80A4\u5728\u672C\u6587\u4EF6\u91CC\n * **\u6309\u5144\u5F1F\u6570\u503C\u8986\u76D6**\uFF08\u9009\u62E9\u5668\u5E26 .dshpc-fb \u524D\u7F00\u63D0\u9AD8\u7279\u5F02\u6027\uFF0C\u786E\u4FDD\u76D6\u5F97\u4F4F\u63A7\u4EF6\u9ED8\u8BA4\u503C\uFF09\u3002\n */\n.dshpc-fb{\n position:relative;display:flex;flex-direction:column;height:100%;min-height:0;\n background:var(--dshpc-surface-base);color:var(--dshpc-fg);\n}\n\n/* \u7B2C\u4E00\u6392\uFF1A\u25BE \u9009\u5C42 + \u9762\u5305\u5C51 + \u52A8\u4F5C\uFF08\u5144\u5F1F .dsh-tdt-sv-crumbbar\uFF09\n \u26A0\uFE0F \u4E0D\u80FD overflow:hidden \u2014\u2014 \u4E0B\u62C9\u6D6E\u5C42\u6302\u5728\u5B83\u4E0B\u9762\uFF0C\u88C1\u4E86\u5C31\u770B\u4E0D\u89C1\u3002 */\n.dshpc-fb__bar{\n position:relative;flex:none;display:flex;align-items:center;gap:2px;\n padding:4px 10px;border-bottom:1px solid var(--dshpc-border);white-space:nowrap;\n}\n.dshpc-fb__menu-wrap{position:relative;flex:none;display:inline-flex}\n.dshpc-fb__crumbs{position:relative;flex:1;min-width:0;display:flex;align-items:center;gap:2px;overflow:hidden}\n.dshpc-fb__crumbs-measure{\n position:absolute;top:0;left:0;display:inline-flex;align-items:center;gap:2px;\n visibility:hidden;pointer-events:none;white-space:nowrap;\n}\n\n/* \u9762\u5305\u5C51\uFF1A\u6838\u5FC3 ghost \u94AE\uFF0C\u4F46\u76AE\u80A4\u4E0E\u5C3A\u5BF8\u53D6\u5144\u5F1F .dsh-tdt-sv-crumb\uFF08\u9AD8\u7531\u5185\u5BB9\u51B3\u5B9A\uFF0C\u4E0D\u9501\u63A7\u5236\u9AD8\uFF09\u3002 */\n.dshpc-fb .dshpc-fb__crumb{\n appearance:none;background:0 0;border:none;height:auto;\n padding:2px 4px;border-radius:var(--dshpc-radius-sm);\n font:inherit;font-size:var(--dshpc-font-sm);line-height:var(--dshpc-line-sm);\n color:var(--dshpc-fg-2);cursor:pointer;\n display:inline-flex;align-items:center;min-width:0;overflow:hidden;text-overflow:ellipsis;\n}\n.dshpc-fb .dshpc-fb__crumb:hover{background:var(--dshpc-hover);color:var(--dshpc-fg)}\n.dshpc-fb .dshpc-fb__crumb:disabled{color:var(--dshpc-fg-2);cursor:default}\n.dshpc-fb .dshpc-fb__crumb--current{cursor:default;color:var(--dshpc-fg);font-weight:600;min-width:0}\n.dshpc-fb .dshpc-fb__crumb--current:hover{background:0 0}\n.dshpc-fb__crumb-mq{flex:1 1 auto;min-width:0}\n.dshpc-fb__crumb-sep{flex:none;color:var(--dshpc-fg-3)}\n\n/* \u8D8A\u754C\uFF08outside-workspace\uFF09\u7B2C\u4E00\u6392\uFF1A\u53EA\u8BFB\u5B8C\u6574\u8DEF\u5F84\uFF08\u5144\u5F1F .dsh-tdt-sv-crumbbar-plain-inner\uFF09\u3002 */\n.dshpc-fb__bar-plain{\n font-family:var(--dshpc-font-mono,ui-monospace,SFMono-Regular,Menlo,Consolas,monospace);\n font-size:var(--dshpc-font-sm);line-height:var(--dshpc-line-sm);color:var(--dshpc-fg-2);\n white-space:nowrap;overflow:hidden;text-overflow:ellipsis;cursor:default;user-select:none;\n}\n.dshpc-fb__actions{flex:none;display:flex;align-items:center;gap:4px}\n\n/* \u25BE \u9009\u5C42\u6D6E\u5C42\uFF08\u5144\u5F1F .dsh-tdt-sv-crumbs-*\uFF09\u3002\n \u5C42\u5E8F\uFF1A\u5144\u5F1F\u662F 30/31\uFF1B\u672C\u4ED3 picker \u9762\u677F\u662F 1100\uFF0C\u906E\u7F69\u5FC5\u987B\u9AD8\u4E8E\u5B83\uFF0C\u5426\u5219\u83DC\u5355\u5F00\u7740\u70B9\u9762\u677F\u4E0D\u7B97\u300C\u70B9\u5916\u90E8\u300D\u3002 */\n.dshpc-fb__crumbs-backdrop{position:fixed;inset:0;z-index:1200;background:transparent}\n.dshpc-fb__crumbs-menu{\n position:absolute;top:calc(100% + 4px);left:0;z-index:1201;min-width:160px;max-height:240px;overflow:auto;\n background:var(--dshpc-surface-menu);border:1px solid var(--dshpc-border);border-radius:var(--dshpc-radius-sm);\n box-shadow:0 4px 16px rgba(0,0,0,.18);padding:4px;display:flex;flex-direction:column;\n}\n.dshpc-fb__menu-item{\n appearance:none;background:0 0;border:none;text-align:left;font:inherit;\n font-size:var(--dshpc-font-sm);line-height:var(--dshpc-line-md);\n padding:4px 8px;border-radius:var(--dshpc-radius-sm);color:var(--dshpc-fg);cursor:pointer;\n max-width:280px;display:flex;align-items:center;gap:2px;\n overflow:hidden;text-overflow:ellipsis;white-space:nowrap;\n}\n.dshpc-fb__menu-item:hover{background:var(--dshpc-hover)}\n.dshpc-fb__menu-empty{\n font-size:var(--dshpc-font-sm);line-height:var(--dshpc-line-md);padding:4px 8px;color:var(--dshpc-fg-3);\n}\n.dshpc-fb__menu-icon{flex:none;display:inline-flex}\n.dshpc-fb__menu-chev{flex:none;color:var(--dshpc-fg-3);margin-right:1px}\n.dshpc-fb__menu-chev-slot{flex:none;width:11px;height:11px;margin-right:1px}\n.dshpc-fb__menu-label{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}\n\n/* \u7B2C\u4E8C\u6392\uFF08\u4EC5\u9884\u89C8\u6001\uFF09\uFF1A\u6587\u4EF6\u540D + \u5DE5\u5177\uFF08\u5144\u5F1F .dsh-tdt-sv-titlebar / -preview-title-inner\uFF09\u3002 */\n.dshpc-fb__title{\n flex:none;display:flex;align-items:center;gap:8px;\n padding:8px 14px;border-bottom:1px solid var(--dshpc-border);\n}\n.dshpc-fb__title-inner{\n font-family:var(--dshpc-font-mono,ui-monospace,SFMono-Regular,Menlo,Consolas,monospace);\n font-size:var(--dshpc-font-sm);line-height:var(--dshpc-line-sm);color:var(--dshpc-fg);\n white-space:nowrap;overflow:hidden;text-overflow:ellipsis;cursor:default;\n}\n\n/* \u4E3B\u4F53\uFF08\u5144\u5F1F .dsh-tdt-sv-preview-body / -hint / -preview-err\uFF09 */\n.dshpc-fb__body{flex:1;min-height:0;overflow-x:hidden;overflow-y:auto;padding:12px 14px}\n.dshpc-fb__note{font-size:var(--dshpc-font-sm);color:var(--dshpc-fg-2);text-align:center;padding:12px 0}\n.dshpc-fb__err{\n display:flex;flex-direction:column;align-items:flex-start;gap:10px;\n font-size:var(--dshpc-font-sm);line-height:1.6;color:var(--dshpc-fg-2);padding:8px 0;\n}\n\n/* \u76EE\u5F55\u6811\uFF08\u5144\u5F1F .dsh-tdt-sv-tree*\uFF09 */\n.dshpc-fb__tree{flex:1;min-height:0;overflow:auto;padding:6px 8px}\n.dshpc-fb__row{\n display:flex;align-items:center;gap:8px;padding:6px 8px;\n border-radius:var(--dshpc-radius-sm);cursor:pointer;user-select:none;\n}\n.dshpc-fb__row:hover{background:var(--dshpc-hover)}\n.dshpc-fb__row:focus-visible{outline:2px solid var(--dshpc-focus);outline-offset:-2px}\n.dshpc-fb__row-icon{flex:none;display:inline-flex;color:var(--dshpc-fg-2)}\n.dshpc-fb__row-name{\n flex:1;min-width:0;font-size:var(--dshpc-font-md);line-height:var(--dshpc-line-md);color:var(--dshpc-fg);\n overflow:hidden;text-overflow:ellipsis;white-space:nowrap;\n}\n\n/* \u5C55\u5F00\u5F00\u5173\uFF1A\u6838\u5FC3 IconButton\uFF0C\u547D\u4E2D\u4F4D 20\xD720 + \u5C55\u5F00\u65F6\u8F6C 90\xB0\uFF08\u5144\u5F1F .dsh-tdt-sv-tree-toggle{,-open}\uFF09\u3002 */\n.dshpc-fb .dshpc-fb__row-toggle{\n appearance:none;background:0 0;border:none;flex:none;\n width:20px;height:20px;padding:0;margin:0;border-radius:var(--dshpc-radius-sm);\n color:var(--dshpc-fg-2);cursor:pointer;\n display:inline-flex;align-items:center;justify-content:center;\n transition:transform var(--dshpc-dur-fast) var(--dshpc-ease),background var(--dshpc-dur-fast) var(--dshpc-ease);\n}\n.dshpc-fb .dshpc-fb__row-toggle--open{transform:rotate(90deg)}\n\n/* \u884C\u5C3E\u300C\u8FDB\u5165 / \u9009\u62E9\u300D\uFF1A\u6838\u5FC3 outline \u94AE\uFF0C\u76AE\u80A4\u53D6\u5144\u5F1F .dsh-tdt-sv-tree-act\uFF08\u9AD8\u7531\u5185\u5BB9\u51B3\u5B9A\uFF09\u3002\n \u5E73\u65F6\u9690\u8EAB\u4F46\u5360\u4F4D\uFF08opacity \u800C\u975E display\uFF09\u21D2 \u51FA\u73B0\u65F6\u4E0D\u9876\u52A8\u884C\u5185\u5E03\u5C40\u3002 */\n.dshpc-fb .dshpc-fb__row-act{\n flex:none;margin-left:auto;appearance:none;background:0 0;\n border:1px solid var(--dshpc-border);border-radius:var(--dshpc-radius-sm);\n height:auto;padding:2px 8px;font-size:var(--dshpc-font-sm);line-height:1.4;\n color:var(--dshpc-fg-2);cursor:pointer;\n opacity:0;pointer-events:none;\n transition:opacity var(--dshpc-dur-fast) var(--dshpc-ease);\n}\n.dshpc-fb__row:hover .dshpc-fb__row-act,.dshpc-fb .dshpc-fb__row-act:focus-visible{opacity:1;pointer-events:auto}\n.dshpc-fb .dshpc-fb__row-act:hover{background:var(--dshpc-hover);color:var(--dshpc-fg)}\n\n.dshpc-fb__row-children{\n margin-left:9px;padding-left:7px;border-left:1px solid var(--dshpc-border);\n display:flex;flex-direction:column;\n}\n.dshpc-fb__row-note{flex:none;padding:8px 10px;font-size:var(--dshpc-font-sm);color:var(--dshpc-fg-3)}\n.dshpc-fb__row-err{padding:4px 8px 4px 36px;font-size:var(--dshpc-font-sm);color:var(--dshpc-danger)}\n\n/* \u9884\u89C8\u4F53\u5185\u90E8\u5BB9\u5668\uFF08\u4EC5\u672C\u4ED3\u9884\u89C8\u7EC4\u4EF6\u7528\uFF1B\u5144\u5F1F\u5BF9\u5E94 preview-fill / preview-body-code \u4E00\u7C7B\uFF09\u3002\n \u5FC5\u987B border-box\uFF1A\u6E32\u67D3\u6001 inline \u52A0\u4E86 padding:12px 14px\uFF0Ccontent-box \u4E0B width:100%+padding\n \u4F1A\u6EA2\u51FA\u7236\u5C42 28px\uFF08\u7236 .dshpc-fb \u65E0 overflow \u88C1\u5207\uFF09\u2192 \u6052\u591A\u4E00\u6761\u6A2A\u6EDA\u6761\uFF1Bborder-box \u628A padding\n \u7B97\u8FDB 100%\uFF0C\u4ECE\u6839\u6D88\u9664\u8BE5\u6EA2\u51FA\u3002 */\n.dshpc-fb__text{flex:1;min-height:0;overflow:auto;width:100%;box-sizing:border-box}\n.dshpc-fb__banner{padding:6px 10px;background:var(--dshpc-open-bg);color:var(--dshpc-fg-2);font-size:var(--dshpc-font-sm)}\n.dshpc-fb__more{display:flex;justify-content:center;padding:10px}\n.dshpc-fb__image{max-width:100%;border-radius:var(--dshpc-radius-sm);border:1px solid var(--dshpc-border)}\n/* iframe \u7684\u5916\u58F3\uFF08\u5144\u5F1F .dsh-tdt-sv-preview-fill\uFF09\uFF1Aiframe \u5FC5\u987B\u5305\u5728\u8FD9\u4E00\u5C42\u91CC\u624D\u62FF\u5F97\u5230\u9AD8\u5EA6\u2014\u2014\n \u88F8\u6302 iframe \u65F6\u66FF\u6362\u5143\u7D20\u7684\u81EA\u52A8\u6700\u5C0F\u5C3A\u5BF8\u4F1A\u8BA9\u9AD8\u5EA6\u7B97\u4E0D\u51FA\u6765\uFF08\u8868\u73B0\u4E3A\u9884\u89C8\u533A\u6574\u7247\u7A7A\u767D\u3001\u50CF\u6CA1\u53CD\u5E94\uFF09\u3002 */\n.dshpc-fb__fill{flex:1;min-height:0;display:flex;overflow:hidden;padding:0}\n.dshpc-fb__frame{flex:1;min-height:0;width:100%;height:100%;border:none;background:var(--dshpc-surface-1)}\n";
@@ -2868,6 +2870,8 @@ var DICT = {
2868
2870
  modalClose: "\u5173\u95ED",
2869
2871
  dockClose: "\u5173\u95ED\u9762\u677F",
2870
2872
  dockResize: "\u62D6\u52A8\u8C03\u6574\u5BBD\u5EA6",
2873
+ dockCollapse: "\u6536\u8D77\u9762\u677F",
2874
+ dockExpand: "\u5C55\u5F00\u9762\u677F",
2871
2875
  errorRetry: "\u91CD\u8BD5",
2872
2876
  confirm: "\u786E\u5B9A",
2873
2877
  cancel: "\u53D6\u6D88",
@@ -3124,6 +3128,8 @@ var DICT = {
3124
3128
  modalClose: "Close",
3125
3129
  dockClose: "Close panel",
3126
3130
  dockResize: "Drag to resize",
3131
+ dockCollapse: "Collapse panel",
3132
+ dockExpand: "Expand panel",
3127
3133
  errorRetry: "Retry",
3128
3134
  confirm: "Confirm",
3129
3135
  cancel: "Cancel",
@@ -3589,15 +3595,22 @@ function Picker(props) {
3589
3595
  blocked ? "dshpc-picker__option--disabled" : ""
3590
3596
  ].filter((s) => s !== "").join(" ");
3591
3597
  const idx = flat.indexOf(o);
3592
- return (0, import_react6.createElement)("div", {
3593
- key: o.value,
3594
- className: activeCls,
3595
- "data-active": idx === active ? "true" : void 0,
3596
- onClick: () => {
3597
- if (!blocked)
3598
- pick2(o.value);
3599
- }
3600
- }, mode === "multiple" ? (0, import_react6.createElement)("span", { className: "dshpc-picker__tick" }, selected.includes(o.value) ? "\u2713" : "") : null, o.icon !== void 0 && o.icon !== null ? (0, import_react6.createElement)("span", { className: "dshpc-picker__option-icon" }, o.icon) : null, (0, import_react6.createElement)("span", null, o.label));
3598
+ return (0, import_react6.createElement)(
3599
+ "div",
3600
+ {
3601
+ key: o.value,
3602
+ className: activeCls,
3603
+ "data-active": idx === active ? "true" : void 0,
3604
+ onClick: () => {
3605
+ if (!blocked)
3606
+ pick2(o.value);
3607
+ }
3608
+ },
3609
+ mode === "multiple" ? (0, import_react6.createElement)("span", { className: "dshpc-picker__tick" }, selected.includes(o.value) ? "\u2713" : "") : null,
3610
+ o.icon !== void 0 && o.icon !== null ? (0, import_react6.createElement)("span", { className: "dshpc-picker__option-icon" }, o.icon) : null,
3611
+ // 选项文字超长时省略号 + hover 跑马灯(与触发器同一套逻辑),不把菜单撑出横向滚动条。
3612
+ (0, import_react6.createElement)(MarqueeText, { text: o.label, className: "dshpc-picker__option-label" })
3613
+ );
3601
3614
  })))
3602
3615
  ])) : null);
3603
3616
  }
@@ -4370,6 +4383,10 @@ var WorkspaceListStore = class {
4370
4383
  }
4371
4384
  };
4372
4385
  var workspaceList = new WorkspaceListStore();
4386
+ var workspaceFiles;
4387
+ function getWorkspaceFiles() {
4388
+ return workspaceFiles;
4389
+ }
4373
4390
  function isWorkspaceSource(value) {
4374
4391
  if (value === null || typeof value !== "object")
4375
4392
  return false;
@@ -4382,6 +4399,13 @@ function connectHost(ctx, options = {}) {
4382
4399
  if (isWorkspaceSource(source))
4383
4400
  workspaceList.setSource(source);
4384
4401
  });
4402
+ ctx.inject(["remote", "remote.workspaceFiles"], (sub) => {
4403
+ const rec = sub;
4404
+ const candidate = rec?.["remote.workspaceFiles"] ?? rec?.remote?.workspaceFiles;
4405
+ if (typeof candidate?.list === "function") {
4406
+ workspaceFiles = candidate;
4407
+ }
4408
+ });
4385
4409
  const modelsPath = options.modelsPath;
4386
4410
  if (modelsPath === void 0)
4387
4411
  return;
@@ -6349,7 +6373,7 @@ var import_react28 = require("react");
6349
6373
  // dist/ui/panel-dock-logic.js
6350
6374
  var DEFAULT_PANEL_ID = "default";
6351
6375
  function emptyDock() {
6352
- return { ids: [], widths: {} };
6376
+ return { ids: [], widths: {}, collapsed: [] };
6353
6377
  }
6354
6378
  function clampWidth(value, min2, max2) {
6355
6379
  const wide = Number.isFinite(value) ? value : min2;
@@ -6359,26 +6383,60 @@ function clampWidth(value, min2, max2) {
6359
6383
  function isOpen(state, id3) {
6360
6384
  return state.ids.includes(id3);
6361
6385
  }
6386
+ function isCollapsed(state, id3) {
6387
+ return state.collapsed.includes(id3);
6388
+ }
6362
6389
  function openPanel(state, id3, maxPanels) {
6363
6390
  if (isOpen(state, id3))
6364
6391
  return { state, result: { ok: true, id: id3, created: false } };
6365
6392
  if (state.ids.length >= maxPanels)
6366
6393
  return { state, result: { ok: false, id: id3, reason: "limit" } };
6367
- return { state: { ids: [...state.ids, id3], widths: state.widths }, result: { ok: true, id: id3, created: true } };
6394
+ return {
6395
+ state: {
6396
+ ids: [...state.ids, id3],
6397
+ widths: state.widths,
6398
+ collapsed: state.collapsed.filter((item) => item !== id3)
6399
+ },
6400
+ result: { ok: true, id: id3, created: true }
6401
+ };
6368
6402
  }
6369
6403
  function closePanel(state, id3) {
6370
- if (!isOpen(state, id3))
6404
+ const open = isOpen(state, id3);
6405
+ const ear = isCollapsed(state, id3);
6406
+ if (!open && !ear)
6371
6407
  return state;
6372
6408
  const widths = { ...state.widths };
6373
6409
  delete widths[id3];
6374
- return { ids: state.ids.filter((item) => item !== id3), widths };
6410
+ return {
6411
+ ids: open ? state.ids.filter((item) => item !== id3) : state.ids,
6412
+ widths,
6413
+ collapsed: ear ? state.collapsed.filter((item) => item !== id3) : state.collapsed
6414
+ };
6375
6415
  }
6376
6416
  function setPanelWidth(state, id3, width) {
6377
6417
  if (!isOpen(state, id3))
6378
6418
  return state;
6379
6419
  if (state.widths[id3] === width)
6380
6420
  return state;
6381
- return { ids: state.ids, widths: { ...state.widths, [id3]: width } };
6421
+ return { ids: state.ids, widths: { ...state.widths, [id3]: width }, collapsed: state.collapsed };
6422
+ }
6423
+ function collapsePanel(state, id3) {
6424
+ if (!isOpen(state, id3))
6425
+ return state;
6426
+ return {
6427
+ ids: state.ids.filter((item) => item !== id3),
6428
+ widths: state.widths,
6429
+ collapsed: state.collapsed.includes(id3) ? state.collapsed : [...state.collapsed, id3]
6430
+ };
6431
+ }
6432
+ function expandPanel(state, id3) {
6433
+ if (!isCollapsed(state, id3))
6434
+ return state;
6435
+ return {
6436
+ ids: state.ids.includes(id3) ? state.ids : [...state.ids, id3],
6437
+ widths: state.widths,
6438
+ collapsed: state.collapsed.filter((item) => item !== id3)
6439
+ };
6382
6440
  }
6383
6441
  function othersWidth(state, id3, fallbackOf) {
6384
6442
  return state.ids.reduce((sum, item) => {
@@ -6390,6 +6448,7 @@ function othersWidth(state, id3, fallbackOf) {
6390
6448
 
6391
6449
  // dist/ui/PanelDock.js
6392
6450
  var INSET_VAR = "--dshpc-page-inset-right";
6451
+ var DOCK_GAP = 1;
6393
6452
  var dockInsets = /* @__PURE__ */ new Map();
6394
6453
  var dockSeq = 0;
6395
6454
  function publishInset(key, width, el) {
@@ -6467,7 +6526,7 @@ function createPanelDock(options = {}) {
6467
6526
  return result;
6468
6527
  },
6469
6528
  close(id3 = DEFAULT_PANEL_ID, reason = "api") {
6470
- if (!isOpen(state, id3))
6529
+ if (!isOpen(state, id3) && !isCollapsed(state, id3))
6471
6530
  return;
6472
6531
  if (options.onBeforeClose?.({ id: id3, reason }) === false)
6473
6532
  return;
@@ -6481,9 +6540,26 @@ function createPanelDock(options = {}) {
6481
6540
  }
6482
6541
  return controller.open(id3);
6483
6542
  },
6543
+ collapse(id3 = DEFAULT_PANEL_ID) {
6544
+ if (!isOpen(state, id3))
6545
+ return;
6546
+ emit(collapsePanel(state, id3));
6547
+ },
6548
+ expand(id3 = DEFAULT_PANEL_ID) {
6549
+ if (!isCollapsed(state, id3))
6550
+ return;
6551
+ if (state.ids.length >= maxPanels) {
6552
+ options.onLimitReached?.({ id: id3 });
6553
+ return;
6554
+ }
6555
+ emit(expandPanel(state, id3));
6556
+ },
6484
6557
  isOpen(id3 = DEFAULT_PANEL_ID) {
6485
6558
  return isOpen(state, id3);
6486
6559
  },
6560
+ isCollapsed(id3 = DEFAULT_PANEL_ID) {
6561
+ return isCollapsed(state, id3);
6562
+ },
6487
6563
  ids() {
6488
6564
  return state.ids;
6489
6565
  },
@@ -6525,6 +6601,24 @@ function PanelDock(props) {
6525
6601
  const panes = panesOf(props.children);
6526
6602
  const { defaultWidth, minWidth: fallbackMin } = props.dock.defaults;
6527
6603
  const widthOf = (pane) => state.widths[pane.id] ?? clampWidth(pane.width ?? defaultWidth, pane.minWidth ?? fallbackMin, pane.maxWidth);
6604
+ const earLabelOf = (id3) => {
6605
+ const pane = panes.find((item) => item.id === id3);
6606
+ if (pane === void 0)
6607
+ return id3;
6608
+ if (typeof pane.title === "string")
6609
+ return pane.title;
6610
+ if (typeof pane.ariaLabel === "string")
6611
+ return pane.ariaLabel;
6612
+ return id3;
6613
+ };
6614
+ const [closing4, setClosing] = (0, import_react28.useState)([]);
6615
+ const collapseWithAnim = (id3) => {
6616
+ setClosing((prev) => prev.includes(id3) ? prev : [...prev, id3]);
6617
+ window.setTimeout(() => {
6618
+ setClosing((prev) => prev.filter((item) => item !== id3));
6619
+ props.dock.collapse(id3);
6620
+ }, 220);
6621
+ };
6528
6622
  const insetKey = (0, import_react28.useRef)("");
6529
6623
  if (insetKey.current === "")
6530
6624
  insetKey.current = `dock-${++dockSeq}`;
@@ -6534,7 +6628,7 @@ function PanelDock(props) {
6534
6628
  });
6535
6629
  const totalWidth = panes.filter((pane) => state.ids.includes(pane.id)).reduce((sum, pane) => sum + widthOf(pane), 0);
6536
6630
  (0, import_react28.useEffect)(() => {
6537
- publishInset(insetKey.current, totalWidth, rootRef.current);
6631
+ publishInset(insetKey.current, state.ids.length > 0 ? totalWidth + DOCK_GAP : 0, rootRef.current);
6538
6632
  });
6539
6633
  (0, import_react28.useEffect)(() => () => {
6540
6634
  publishInset(insetKey.current, 0, null);
@@ -6552,6 +6646,7 @@ function PanelDock(props) {
6552
6646
  const startWidth = widthOf(pane);
6553
6647
  const min2 = pane.minWidth ?? fallbackMin;
6554
6648
  const mainMin = props.mainMinWidth ?? 480;
6649
+ element.classList.add("dshpc-dock__panel--resizing");
6555
6650
  startResizeLayoutWidth({
6556
6651
  startEvent: event,
6557
6652
  root: rootRef.current,
@@ -6565,9 +6660,10 @@ function PanelDock(props) {
6565
6660
  },
6566
6661
  onMove: (width) => {
6567
6662
  element.style.width = `${width}px`;
6568
- publishInset(insetKey.current, restWidth(pane.id) + width, rootRef.current);
6663
+ publishInset(insetKey.current, restWidth(pane.id) + width + DOCK_GAP, rootRef.current);
6569
6664
  },
6570
6665
  onCommit: (width) => {
6666
+ element.classList.remove("dshpc-dock__panel--resizing");
6571
6667
  props.dock.setWidth(pane.id, width);
6572
6668
  }
6573
6669
  });
@@ -6607,30 +6703,69 @@ function PanelDock(props) {
6607
6703
  onClick: () => props.dock.close(pane.id, "button")
6608
6704
  }, pane.closeIcon ?? "\u2715");
6609
6705
  };
6610
- return (0, import_react28.createElement)("div", {
6611
- ref: rootRef,
6612
- className: props.className === void 0 ? "dshpc-dock" : `dshpc-dock ${props.className}`
6613
- }, panes.filter((pane) => state.ids.includes(pane.id)).map((pane) => (0, import_react28.createElement)("section", {
6614
- key: pane.id,
6615
- ref: (element) => {
6616
- if (element === null)
6617
- panelRefs.current.delete(pane.id);
6618
- else
6619
- panelRefs.current.set(pane.id, element);
6706
+ const rootClass = `dshpc-dock${state.ids.length > 0 ? " dshpc-dock--open" : ""}${props.className === void 0 ? "" : ` ${props.className}`}`;
6707
+ return (0, import_react28.createElement)(
6708
+ "div",
6709
+ {
6710
+ ref: rootRef,
6711
+ className: rootClass
6620
6712
  },
6621
- className: "dshpc-dock__panel",
6622
- style: { width: `${widthOf(pane)}px` },
6623
- "data-panel": pane.id,
6624
- "aria-label": pane.ariaLabel ?? (typeof pane.title === "string" ? pane.title : pane.id)
6625
- }, (0, import_react28.createElement)("div", {
6626
- className: "dshpc-dock__resizer",
6627
- role: "separator",
6628
- "aria-orientation": "vertical",
6629
- "aria-label": tt("dockResize"),
6630
- onPointerDown: (event) => {
6631
- beginResize(pane, event);
6632
- }
6633
- }), renderHeader(pane), headerCloseOf(pane), floatingCloseOf(pane), (0, import_react28.createElement)("div", { className: "dshpc-dock__body" }, pane.children ?? null))));
6713
+ panes.filter((pane) => state.ids.includes(pane.id)).map((pane) => (0, import_react28.createElement)(
6714
+ "section",
6715
+ {
6716
+ key: pane.id,
6717
+ ref: (element) => {
6718
+ if (element === null)
6719
+ panelRefs.current.delete(pane.id);
6720
+ else
6721
+ panelRefs.current.set(pane.id, element);
6722
+ },
6723
+ className: closing4.includes(pane.id) ? "dshpc-dock__panel dshpc-dock__panel--closing" : "dshpc-dock__panel",
6724
+ style: { width: `${widthOf(pane)}px` },
6725
+ "data-panel": pane.id,
6726
+ "aria-label": pane.ariaLabel ?? (typeof pane.title === "string" ? pane.title : pane.id)
6727
+ },
6728
+ (0, import_react28.createElement)("div", {
6729
+ className: "dshpc-dock__resizer",
6730
+ role: "separator",
6731
+ "aria-orientation": "vertical",
6732
+ "aria-label": tt("dockResize"),
6733
+ onPointerDown: (event) => {
6734
+ beginResize(pane, event);
6735
+ }
6736
+ }),
6737
+ // 收起钮是 resizer 的**兄弟**,不是子元素 —— 用户 2026-10-28:鼠标停在按钮上时,
6738
+ // 拖宽线不能亮、也不能出蓝色发光(那是在拖宽,不是点按钮)。挂在面板左缘外。
6739
+ (0, import_react28.createElement)("button", {
6740
+ type: "button",
6741
+ className: "dshpc-dock__collapse",
6742
+ "aria-label": tt("dockCollapse"),
6743
+ onClick: () => collapseWithAnim(pane.id)
6744
+ }, "\u203A"),
6745
+ renderHeader(pane),
6746
+ headerCloseOf(pane),
6747
+ floatingCloseOf(pane),
6748
+ (0, import_react28.createElement)("div", { className: "dshpc-dock__body" }, pane.children ?? null)
6749
+ )),
6750
+ // 收起后的耳朵:**独立的 fixed 浮层**,与分栏不是一体(用户 2026-10-28 口径)。
6751
+ // 多个耳朵按收起顺序纵向堆叠,点一只展开回来。
6752
+ state.collapsed.length === 0 ? null : (0, import_react28.createElement)("div", { className: "dshpc-dock__ears" }, state.collapsed.map((id3) => {
6753
+ const label = earLabelOf(id3);
6754
+ return (0, import_react28.createElement)(
6755
+ "button",
6756
+ {
6757
+ key: id3,
6758
+ type: "button",
6759
+ className: "dshpc-dock__ear",
6760
+ // 不放 title:原生 tooltip 会把面板标题弹出来,用户明确「不要显示任何标题」。
6761
+ "aria-label": `${label} \xB7 ${tt("dockExpand")}`,
6762
+ onClick: () => props.dock.expand(id3)
6763
+ },
6764
+ // 只有一个箭头,与收起钮同尺寸反向:收起钮 ›(往右收),耳朵 ‹(往左拉回来)。
6765
+ (0, import_react28.createElement)("span", { className: "dshpc-dock__ear-arrow", "aria-hidden": true }, "\u2039")
6766
+ );
6767
+ }))
6768
+ );
6634
6769
  }
6635
6770
 
6636
6771
  // dist/ui/Field.js
@@ -6745,8 +6880,8 @@ var FileServicesStore = class {
6745
6880
  this.snapshot = { ...this.snapshot, ...patch };
6746
6881
  for (const listener of this.listeners) listener();
6747
6882
  }
6748
- setFiles(workspaceFiles) {
6749
- this.set({ workspaceFiles });
6883
+ setFiles(workspaceFiles2) {
6884
+ this.set({ workspaceFiles: workspaceFiles2 });
6750
6885
  }
6751
6886
  setOffice(officeToPdf) {
6752
6887
  this.set({ officeToPdf });
@@ -55008,7 +55143,7 @@ var DICT2 = {
55008
55143
  installDesc: "\u5F85\u8865\uFF1A\n\xB7 \u4F9D\u8D56\u58F0\u660E\u600E\u4E48\u88C5\uFF08git \u5B89\u88C5\uFF0C\u5BBF\u4E3B\u4E0D\u8DD1\u6784\u5EFA\u811A\u672C\uFF09\n\xB7 \u5165\u53E3\u5FC5\u987B\u505A\u7684\u4E24\u884C\uFF1AsetStyleKit + ensureControls\n\xB7 \u4E3A\u4EC0\u4E48 @deepseek-ai/* \u5FC5\u987B\u6807 external\uFF08\u4E0D\u6807\u6253\u5305\u4F1A\u5931\u8D25\uFF09\n\xB7 \u5BBF\u4E3B slots \u6CE8\u518C\uFF1Asidebar.panellist / main / plugins.bundle.config\uFF08\u8BBE\u7F6E\u9875\uFF09\n\xB7 \u88C5\u4E0D\u4E0A\u7684\u6392\u67E5\u6E05\u5355\uFF08\u5148\u770B build \u7F16\u7801\u662F\u5426\u53D8\u4E86\uFF09",
55009
55144
  quickstartDesc: "\u5F85\u8865\uFF1A\n\xB7 \u4E00\u4E2A\u6700\u5C0F\u53EF\u8DD1\u63D2\u4EF6\u7684\u5B8C\u6574\u6E90\u7801\n\xB7 \u4ECE\u5EFA\u76EE\u5F55\u5230\u5728\u5BBF\u4E3B\u91CC\u770B\u89C1\u5B83\u7684\u5206\u6B65\u8BF4\u660E\n\xB7 \u672C\u9884\u89C8\u63D2\u4EF6\u81EA\u5DF1\u5C31\u662F\u6837\u4F8B\uFF0C\u53EF\u5BF9\u7167 packages/demo/src",
55010
55145
  namingDesc: "\u5F85\u8865\uFF1A\n\xB7 \u53D8\u91CF\u4E0E\u7C7B\u540D\u7EDF\u4E00 dshpc \u524D\u7F00\u7684\u7406\u7531\n\xB7 \u7C7B\u540D\u5FC5\u987B\u4E0E\u7EC4\u4EF6\u91CC\u786C\u7F16\u7801\u7684 className \u9010\u5B57\u4E00\u81F4\u2014\u2014\u4E0D\u4E00\u81F4\u4F1A\u6574\u7247\u5931\u6548\n\xB7 createStyleKit({ id }) \u9694\u79BB\u5230\u4EC0\u4E48\u7C92\u5EA6\n\xB7 \u6CE8\u5165\u987A\u5E8F\uFF1A\u540C\u7279\u5F02\u6027\u65F6\u540E\u6CE8\u5165\u8005\u80DC\u51FA\n\xB7 \u660E\u6697\u5224\u636E\u4E3A\u4EC0\u4E48\u662F body[data-ds-dark-theme] \u800C\u4E0D\u662F\u7CFB\u7EDF\u8BBE\u7F6E",
55011
- dockHint: "\u53F3\u4FA7\u505C\u9760\u5206\u680F\uFF0C\u6302\u5728\u6574\u9875\u4E0A\uFF1A\u7ED3\u6784\u5199\u5728\u9875\u9762\u91CC\uFF08DockPanel\uFF09\uFF0Copen(id) \u53EA\u7BA1\u663E\u9690\u3002\n\u8BD5\u4E00\u904D\uFF1A\u5F00 A\uFF08\u56FE\u6807 + \u6807\u9898 + \u53F3\u4FA7\u6807\u7B7E\uFF09\u2192 \u5F00 B\uFF08\u6574\u5757\u81EA\u5B9A\u4E49\u5934\u90E8\uFF09\u2192 \u5F00 C\uFF08\u65E0\u5934\u90E8\u3001\u5173\u95ED\u94AE\u6D6E\u5728\u53F3\u4E0A\u89D2\uFF09\u2192 \u5173 A \u540E\u518D\u5F00\u65B0\u7EC4\u540D \u2192 \u6EE1 3 \u680F\u518D\u5F00\u4F1A\u88AB\u62D2\u7EDD\u3002",
55146
+ dockHint: "\u53F3\u4FA7\u505C\u9760\u5206\u680F\uFF0C\u6302\u5728\u6574\u9875\u4E0A\uFF1A\u7ED3\u6784\u5199\u5728\u9875\u9762\u91CC\uFF08DockPanel\uFF09\uFF0Copen(id) \u53EA\u7BA1\u663E\u9690\u3002\n\u8BD5\u4E00\u904D\uFF1A\u5F00 A\uFF08\u56FE\u6807 + \u6807\u9898 + \u53F3\u4FA7\u6807\u7B7E\uFF09\u2192 \u5F00 B\uFF08\u6574\u5757\u81EA\u5B9A\u4E49\u5934\u90E8\uFF09\u2192 \u5F00 C\uFF08\u65E0\u5934\u90E8\u3001\u5173\u95ED\u94AE\u6D6E\u5728\u53F3\u4E0A\u89D2\uFF09\u2192 \u5173 A \u540E\u518D\u5F00\u65B0\u7EC4\u540D \u2192 \u6EE1 3 \u680F\u518D\u5F00\u4F1A\u88AB\u62D2\u7EDD\u3002\n\u53E6\uFF1A\u70B9\u5206\u5272\u7EBF\u4E2D\u95F4\u7684 \u203A \u53EF\u628A\u8BE5\u680F\u6536\u8D77\u6210\u53F3\u4FA7\u8033\u6735\uFF08\u5206\u680F\u6D88\u5931\u3001\u4E0D\u5360\u5BBD\uFF09\uFF0C\u70B9\u8033\u6735\u5C55\u5F00\u3002",
55012
55147
  dockMainText: "\u5206\u680F\u662F\u5E03\u5C40\u6210\u5458\uFF1A\u5B83\u628A\u8FD9\u4E00\u9875\u7684\u6B63\u6587\u6324\u7A84\uFF0C\u800C\u4E0D\u662F\u76D6\u5728\u4E0A\u9762\u3002\u4E09\u4E2A\u9762\u677F\u5206\u522B\u6F14\u793A\u5185\u7F6E\u5934\u3001\u81EA\u5B9A\u4E49\u5934\u3001\u65E0\u5934 + \u6D6E\u52A8\u5173\u95ED\u94AE\u3002",
55013
55148
  dockPanelA: "\u5185\u7F6E\u5934\uFF1A\u56FE\u6807 + \u6807\u9898 + \u53F3\u4FA7\u5185\u5BB9",
55014
55149
  dockPanelATag: "\u65B0",
@@ -55017,11 +55152,13 @@ var DICT2 = {
55017
55152
  dockCustomHeadHint: "\u5E93\u4E0D\u52A0\u5185\u8FB9\u8DDD\u3001\u4E0D\u52A0\u8FB9\u6846 \u2014\u2014 \u591A\u9AD8\u3001\u51E0\u884C\u3001\u653E\u4EC0\u4E48\u5F39\u5C42\u90FD\u968F\u4F60",
55018
55153
  dockPanelBody: "\u8FD9\u4E00\u680F\u7684\u5185\u5BB9\u3002\u518D\u5F00\u540C\u540D\u9762\u677F\u4F1A\u66FF\u6362\u5B83\uFF0C\u5BBD\u5EA6\u4E0E\u4F4D\u7F6E\u4FDD\u6301\u4E0D\u53D8\u3002",
55019
55154
  dockOpened: "\u5F53\u524D\u7A97\u53E3\uFF1A",
55155
+ dockCollapsed: "\u5DF2\u6536\u8D77\uFF1A",
55020
55156
  dockLimitWarn: "\u5DF2\u6EE1 3 \u680F\uFF0C\u65B0\u7EC4\u540D\u88AB\u62D2\u7EDD\uFF08open \u8FD4\u56DE ok:false / reason:limit\uFF09",
55021
55157
  dockBtnOpenA: "\u6253\u5F00 A",
55022
55158
  dockBtnOpenB: "\u6253\u5F00 B",
55023
55159
  dockBtnOpenA2: "\u518D\u5F00 A\uFF08\u4E0D\u4F1A\u591A\u5F00\uFF09",
55024
55160
  dockBtnCloseA: "\u5173\u95ED A",
55161
+ dockBtnCollapseA: "\u6536\u8D77 A",
55025
55162
  dockBtnDefault: "\u6253\u5F00\u9ED8\u8BA4\u7A97\u53E3",
55026
55163
  dockBtnOpenC: "\u6253\u5F00 C",
55027
55164
  dockBtnReset: "\u5168\u90E8\u5173\u95ED",
@@ -55236,7 +55373,7 @@ var DICT2 = {
55236
55373
  installDesc: "To be added:\n\xB7 How to install (via git \u2014 the host does not run build scripts)\n\xB7 The two mandatory entry lines: setStyleKit + ensureControls\n\xB7 Why @deepseek-ai/* must stay external (otherwise bundling fails)\n\xB7 Registering host slots: sidebar.panellist / main / plugins.bundle.config (settings page)\n\xB7 Checklist when it does not load (start by checking the build stamp)",
55237
55374
  quickstartDesc: "To be added:\n\xB7 Full source of a minimal working plugin\n\xB7 Step-by-step from empty folder to visible panel\n\xB7 This preview plugin is itself the sample \u2014 see packages/demo/src",
55238
55375
  namingDesc: "To be added:\n\xB7 Why variables and class names share the dshpc prefix\n\xB7 Class names must match the hard-coded className character for character \u2014 any drift kills the whole block\n\xB7 How far createStyleKit({ id }) isolates\n\xB7 Injection order: at equal specificity the later one wins\n\xB7 Why the theme switch is body[data-ds-dark-theme] and not prefers-color-scheme",
55239
- dockHint: "Right-side dock: a group name is one window; reopening the same name replaces its content in place (no extra column).\nTry it: open A \u2192 open B \u2192 reopen A (content replaced) \u2192 close A \u2192 open C (the freed slot is usable) \u2192 with 3 columns open, a new group name is rejected.",
55376
+ dockHint: "Right-side dock: a group name is one window; reopening the same name replaces its content in place (no extra column).\nTry it: open A \u2192 open B \u2192 reopen A (content replaced) \u2192 close A \u2192 open C (the freed slot is usable) \u2192 with 3 columns open, a new group name is rejected.\nTip: click \u203A in the middle of the splitter to collapse that column into a right-edge ear (it leaves the layout); click the ear to expand.",
55240
55377
  dockMainText: "The dock is a layout member: it squeezes the page content instead of covering it. The three panels demo a built-in header, a custom header, and a header-less panel with a floating close button.",
55241
55378
  dockPanelA: "Built-in header: icon + title + right-side content",
55242
55379
  dockPanelATag: "new",
@@ -55245,11 +55382,13 @@ var DICT2 = {
55245
55382
  dockCustomHeadHint: "No padding, no border from the library \u2014 height, rows and popovers are up to you",
55246
55383
  dockPanelBody: "Content of this column. Reopening the same name replaces it; width and position stay put.",
55247
55384
  dockOpened: "Open now: ",
55385
+ dockCollapsed: "Collapsed: ",
55248
55386
  dockLimitWarn: "All 3 columns are taken \u2014 the new group name was rejected (open returns ok:false / reason:limit)",
55249
55387
  dockBtnOpenA: "Open A",
55250
55388
  dockBtnOpenB: "Open B",
55251
55389
  dockBtnOpenA2: "Reopen A (no duplicate)",
55252
55390
  dockBtnCloseA: "Close A",
55391
+ dockBtnCollapseA: "Collapse A",
55253
55392
  dockBtnDefault: "Open default",
55254
55393
  dockBtnOpenC: "Open C",
55255
55394
  dockBtnReset: "Close all",
@@ -55622,8 +55761,16 @@ var docData = {
55622
55761
  "en": "Workspace file browsing and picking, driven by the host-provided workspace file snapshot."
55623
55762
  },
55624
55763
  {
55625
- "zh": "\u6D4F\u89C8\u6001\u505C\u9760\u662F\u5E03\u5C40\u6210\u5458\uFF08\u5360\u5BBD\u5EA6\u3001\u6324\u7A84\u4E3B\u533A\uFF09\uFF0C\u4E0D\u8981\u6302 `document.body` \u518D\u81EA\u5DF1\u5957 fixed\u3002",
55626
- "en": "The browse dock is a layout member (takes width, narrows the main area); never mount it on `document.body` with your own fixed positioning."
55764
+ "zh": "**\u63A5\u7EBF\u5F52\u6838\u5FC3**\uFF1Aclient `apply` \u91CC\u8C03\u4E00\u6B21 `connectHost(ctx)`\uFF0C\u8BFB\u6587\u4EF6\u670D\u52A1\u3001\u4F1A\u8BDD id\u3001\u5DE5\u4F5C\u533A\u5FEB\u7167\u90FD\u7531\u6838\u5FC3\u81EA\u5DF1\u89E3\uFF0C\u8C03\u7528\u65F6\u53EA\u7ED9\u5BB9\u5668\u548C\u8DEF\u5F84\u3002",
55765
+ "en": "**Wiring belongs to core**: call `connectHost(ctx)` once in the client apply; the file service, session id and workspace snapshot are resolved by core \u2014 you only pass a container and a path."
55766
+ },
55767
+ {
55768
+ "zh": "\u843D\u70B9\u53EA\u7ED9\u4E00\u4E2A\u5143\u7D20\uFF1A\u9875\u9762\u91CC**\u5305\u4F4F\u4E3B\u533A**\u7684\u90A3\u4E2A\uFF08\u6838\u5FC3\u4F1A\u8865\u6210 flex \u884C\u3001\u8BA9\u4E3B\u533A\u4F38\u5C55\uFF0C\u5173\u95ED\u65F6\u8FD8\u539F\uFF09\uFF0C\u4E0D\u8981\u4F20 `document.body` \u518D\u81EA\u5DF1\u5957 fixed\u2014\u2014\u90A3\u662F\u6D6E\u5C42\uFF0C\u4E0D\u662F\u5206\u680F\u3002",
55769
+ "en": "Pass one element: the one wrapping the main area. Core makes it a flex row and lets the main area stretch, restoring it on close. Never pass `document.body` with your own fixed positioning \u2014 that is an overlay, not a split."
55770
+ },
55771
+ {
55772
+ "zh": "\u7EDD\u5BF9\u8DEF\u5F84\u6309\u6700\u957F\u524D\u7F00\u5339\u914D\u6240\u5C5E\u5DE5\u4F5C\u533A\uFF1B\u843D\u5728\u4EFB\u4F55\u5DE5\u4F5C\u533A\u5916\u65F6\uFF0C\u6587\u4EF6\u7167\u6837\u80FD\u9884\u89C8\uFF08\u5B98\u65B9 read \u5141\u8BB8\u5DE5\u4F5C\u533A\u5916\u6587\u4EF6\uFF09\uFF0C\u53EA\u6709\u76EE\u5F55\u6811\u9000\u5316\u6210\u53EA\u8BFB\u8DEF\u5F84\u680F\u3002",
55773
+ "en": "Absolute paths are matched to their workspace by longest prefix. Outside every workspace the file still previews (official read allows it); only the directory tree degrades to a read-only path bar."
55627
55774
  }
55628
55775
  ]
55629
55776
  },
@@ -55649,15 +55796,15 @@ var docData = {
55649
55796
  },
55650
55797
  "prose": [
55651
55798
  {
55652
- "zh": "\u4ECE ctx \u53D6\u51FA\u5DE5\u4F5C\u533A\u5FEB\u7167\u518D\u4F20\u7ED9\u80FD\u529B\u63A5\u53E3\uFF0C\u4E0D\u8981\u4F20\u6574\u4E2A ctx\u3002",
55653
- "en": "Pull the workspace snapshot out of ctx and hand it to the capability APIs; do not pass the whole ctx."
55799
+ "zh": "`connectHost(ctx)` \u53EA\u6536\u8FD9\u4E00\u5C0F\u5757\uFF0C\u4E0D\u628A\u6574\u4E2A ctx \u4F20\u8FDB\u6838\u5FC3\u3002",
55800
+ "en": "`connectHost(ctx)` takes just that one slice; the whole ctx never enters core."
55654
55801
  }
55655
55802
  ],
55656
55803
  "code": [
55657
55804
  {
55658
55805
  "id": "explorer-usage-code",
55659
55806
  "lang": "tsx",
55660
- "src": "import { openFilePreview, pickWorkspaceFile } from 'dsh-plugin-core/explorer'\n\n// \u53F3\u4FA7\u5206\u680F\u9884\u89C8\uFF08\u5360\u5BBD\u5EA6\u3001\u6324\u7A84\u4E3B\u533A\uFF09\nopenFilePreview({ mount, workspaceFiles, officeToPdf, sessionId, path, rootName })\n\n// path \u4F20\u7EDD\u5BF9\u8DEF\u5F84\u65F6\uFF1A\u6309\u6700\u957F\u524D\u7F00\u5339\u914D\u6240\u5C5E\u5DE5\u4F5C\u533A\uFF0C\u9762\u5305\u5C51 / \u76EE\u5F55\u6811\u4E0E \u25BE\u300C\u5207\u5DE5\u4F5C\u533A\u300D\u81EA\u52A8\u53EF\u7528\nopenFilePreview({ mount, workspaceFiles, sessionId, path: '/abs/path.md' })\n// \u8981\u8986\u76D6\u5BBF\u4E3B\u5FEB\u7167\u624D\u663E\u5F0F\u4F20 workspaceAnchors\uFF08\u5E26 path + sessionIds\uFF09\nopenFilePreview({ mount, workspaceFiles, sessionId, path: '/abs/path.md', workspaceAnchors })\n\n// \u951A\u5B9A\u5F39\u7A97\u9009\u6587\u4EF6\uFF08Promise \u8FD4\u56DE\u8DEF\u5F84\uFF0C\u4E0D\u81EA\u5DF1\u6302 dock\uFF09\nconst r = await pickWorkspaceFile({ workspaceFiles, sessionId, anchor, rootName })"
55807
+ "src": "import { openFilePreview, pickWorkspaceFile } from 'dsh-plugin-core/explorer'\n\n// \u53EA\u5728 client apply \u91CC\u63A5\u7EBF\u4E00\u6B21\uFF08\u63A5\u5DE5\u4F5C\u533A\u5FEB\u7167 + \u8BFB\u6587\u4EF6\u670D\u52A1\uFF09\uFF0C\u4E4B\u540E\u4E0D\u7528\u518D\u78B0\u670D\u52A1\nconnectHost(ctx)\n\n// \u53F3\u4FA7\u5206\u680F\u9884\u89C8\uFF08\u5360\u5BBD\u5EA6\u3001\u6324\u7A84\u4E3B\u533A\uFF09\uFF1A\u4E00\u4E2A\u5BB9\u5668 + \u4E00\u4E2A\u8DEF\u5F84\u5C31\u591F\nopenFilePreview({ mount, path: '/abs/ledger' }) // \u6587\u4EF6\u5939 \u21D2 \u76EE\u5F55\u6811\uFF1B\u6587\u4EF6 \u21D2 \u76F4\u63A5\u9884\u89C8\nopenFilePreview({ mount, path: 'docs/README.md' }) // \u5DE5\u4F5C\u533A\u76F8\u5BF9\u8DEF\u5F84\u4E5F\u884C\n\n// \u8986\u76D6\u9879\uFF1A\u6307\u5B9A\u5DE5\u4F5C\u533A\u5FEB\u7167 / \u6307\u5B9A\u4F1A\u8BDD / Office \u8F6C PDF / \u4E0E\u522B\u5904\u5171\u7528\u7684\u6839\u7F13\u5B58\nopenFilePreview({ mount, path, workspaceAnchors, sessionId, officeToPdf, rootCache })\n\n// \u951A\u5B9A\u5F39\u7A97\u9009\u6587\u4EF6\uFF08Promise \u8FD4\u56DE\u8DEF\u5F84\uFF0C\u4E0D\u81EA\u5DF1\u6302 dock\uFF09\nconst r = await pickWorkspaceFile({ anchor, filter: { exts: ['md'] } })"
55661
55808
  }
55662
55809
  ]
55663
55810
  },
@@ -55686,8 +55833,8 @@ var docData = {
55686
55833
  "def": "\u2014",
55687
55834
  "required": "\u662F",
55688
55835
  "desc": {
55689
- "zh": "\u9875\u9762\u91CC\u7684 flex \u884C\uFF1B\u9884\u89C8\u9760\u5B83\u5360\u5BBD\u800C\u4E0D\u662F\u6D6E\u5728\u9875\u9762\u4E0A\u65B9",
55690
- "en": "The page\u2019s flex row; the preview takes width there instead of floating"
55836
+ "zh": "\u9875\u9762\u91CC**\u5305\u4F4F\u4E3B\u533A**\u7684\u90A3\u4E2A\u5143\u7D20\uFF1B\u4E0D\u5FC5\u81EA\u5DF1\u5199 flex\uFF08\u6838\u5FC3\u8865\u6210 flex \u884C\u5E76\u8BA9\u4E3B\u533A\u4F38\u5C55\uFF0C\u5173\u95ED\u65F6\u8FD8\u539F\uFF09\u3002\u4E0D\u8981\u4F20 `document.body`",
55837
+ "en": "The element wrapping the main area; no flex needed (core turns it into a flex row, stretches the main area, and restores it on close). Never `document.body`"
55691
55838
  }
55692
55839
  },
55693
55840
  {
@@ -55695,8 +55842,8 @@ var docData = {
55695
55842
  "type": "WorkspaceFilesFace",
55696
55843
  "def": "\u2014",
55697
55844
  "desc": {
55698
- "zh": "\u4ECE ctx \u53D6\u51FA\u7684\u5DE5\u4F5C\u533A\u6587\u4EF6\u670D\u52A1\uFF1B\u4F20 `content` \u65F6\u53EF\u7701",
55699
- "en": "Workspace file service taken from ctx; optional when passing `content`"
55845
+ "zh": "\u8BFB\u6587\u4EF6\u670D\u52A1\u3002**\u4E00\u822C\u4E0D\u7528\u4F20**\uFF1A`connectHost(ctx)` \u63A5\u7EBF\u540E\u6838\u5FC3\u81EA\u5DF1\u6301\u6709\uFF1B\u4F20\u4E86\u4EE5\u4F20\u5165\u4E3A\u51C6\u3002\u4F20 `content` \u65F6\u53EF\u7701",
55846
+ "en": "File service. **Usually unnecessary**: core holds it after `connectHost(ctx)`; when passed it wins. Optional when passing `content`"
55700
55847
  }
55701
55848
  },
55702
55849
  {
@@ -55704,8 +55851,8 @@ var docData = {
55704
55851
  "type": "string",
55705
55852
  "def": "\u2014",
55706
55853
  "desc": {
55707
- "zh": "\u8BE5\u5DE5\u4F5C\u533A\u7684\u771F\u5B9E\u4F1A\u8BDD id\uFF08\u670D\u52A1\u662F\u4F1A\u8BDD\u4F5C\u7528\u57DF\u7684\uFF09\uFF1B\u4F20 `content` \u65F6\u53EF\u7701",
55708
- "en": "A real session id of that workspace (the service is session-scoped); optional when passing `content`"
55854
+ "zh": "\u8BE5\u5DE5\u4F5C\u533A\u7684\u771F\u5B9E\u4F1A\u8BDD id\u3002**\u4E00\u822C\u4E0D\u7528\u4F20**\uFF1A\u6309\u8DEF\u5F84\u5339\u914D\u6240\u5C5E\u5DE5\u4F5C\u533A\uFF0C\u5339\u914D\u4E0D\u51FA\u5C31\u53D6\u6700\u8FD1\u6709\u4F1A\u8BDD\u7684\u5DE5\u4F5C\u533A\uFF1B\u4F20 `content` \u65F6\u53EF\u7701",
55855
+ "en": "A real session id. **Usually unnecessary**: resolved from the path\u2019s workspace, else the most recently updated workspace with a session; optional when passing `content`"
55709
55856
  }
55710
55857
  },
55711
55858
  {
@@ -56862,7 +57009,7 @@ var docData = {
56862
57009
  },
56863
57010
  "prose": [
56864
57011
  {
56865
- "zh": "Picker\uFF1A\u5355 / \u591A\u9009\u3001\u4E0A\u9650\u3001\u641C\u7D22\u3001\u5206\u7EC4\u3001\u7A7A\u6001\uFF0C\u81EA\u7ED8\u3002\u952E\u76D8\uFF1AEsc \u5173\u3001\u2191\u2193 \u79FB\u6E38\u6807\u3001Enter \u9009\u3002\u7EAF\u903B\u8F91\u53EF\u5355\u7528\uFF1A`toGroups` / `filterGroups` / `toggleValue`\u3002\u89E6\u53D1\u5668\u652F\u6301 width / minWidth / maxWidth \u7EA6\u675F\u5BBD\u5EA6\uFF1A\u5B9A\u5BBD\u5FFD\u7565\u53E6\u4E24\u8005\uFF1B\u5185\u5BB9\u8D85\u957F\u5219\u7701\u7565\u53F7 + hover \u8DD1\u9A6C\u706F\u3002",
57012
+ "zh": "Picker\uFF1A\u5355 / \u591A\u9009\u3001\u4E0A\u9650\u3001\u641C\u7D22\u3001\u5206\u7EC4\u3001\u7A7A\u6001\uFF0C\u81EA\u7ED8\u3002\u952E\u76D8\uFF1AEsc \u5173\u3001\u2191\u2193 \u79FB\u6E38\u6807\u3001Enter \u9009\u3002\u7EAF\u903B\u8F91\u53EF\u5355\u7528\uFF1A`toGroups` / `filterGroups` / `toggleValue`\u3002\u89E6\u53D1\u5668\u652F\u6301 width / minWidth / maxWidth \u7EA6\u675F\u5BBD\u5EA6\uFF1A\u5B9A\u5BBD\u5FFD\u7565\u53E6\u4E24\u8005\uFF1B\u5185\u5BB9\u8D85\u957F\u5219\u7701\u7565\u53F7 + hover \u8DD1\u9A6C\u706F\u3002\u83DC\u5355\u91CC\u7684\u9009\u9879\u8D85\u957F\u540C\u6837\u7701\u7565 + hover \u8DD1\u9A6C\u706F\uFF0C\u4E0D\u4F1A\u628A\u83DC\u5355\u6491\u51FA\u6A2A\u5411\u6EDA\u52A8\u6761\u3002",
56866
57013
  "en": "Picker: single/multiple selection, cap, search, grouping, empty state \u2014 self-drawn. Keyboard: Esc closes, \u2191\u2193 move the cursor, Enter selects. Logic reusable standalone: `toGroups` / `filterGroups` / `toggleValue`."
56867
57014
  },
56868
57015
  {
@@ -57637,12 +57784,16 @@ var docData = {
57637
57784
  "en": "A generic shell for right-side columns \u2014 a **layout member**, not an overlay: it takes width and narrows the main area, so the caller puts it in their own flex root. Split of work: structure at the call site (children), visibility in state (`open`/`close` take only an id)."
57638
57785
  },
57639
57786
  {
57640
- "zh": "\u9762\u677F\u9AD8\u5EA6\u9ED8\u8BA4\u89C6\u53E3\u9AD8\uFF1B\u5D4C\u5728\u5B9A\u9AD8\u5BB9\u5668\u91CC\u65F6\u7531\u8C03\u7528\u65B9\u7ED9 `--dshpc-dock-h`\u3002\u4E0D\u652F\u6301\uFF1A\u540C\u540D\u591A\u5B9E\u4F8B\u3001tab \u5207\u6362\u6761\u3001\u81EA\u52A8\u6DD8\u6C70\u3001\u6D6E\u5C42\u2014\u2014\u6807\u7B7E\u5207\u6362\u8BF7\u6D88\u8D39\u65B9\u5728\u81EA\u5DF1\u7684\u9762\u677F\u5185\u5BB9\u91CC\u5B9E\u73B0\u3002",
57641
- "en": "Panel height defaults to viewport height; in a fixed-height container the caller sets `--dshpc-dock-h`. Not supported: same-name duplicates, tab bars, auto-eviction, floating layers \u2014 tab switching belongs in the consumer\u2019s own panel content."
57787
+ "zh": "\u9762\u677F\u9AD8\u5EA6\u9ED8\u8BA4\u89C6\u53E3\u9AD8\uFF1B\u5D4C\u5728\u5B9A\u9AD8\u5BB9\u5668\u91CC\u65F6\u7531\u8C03\u7528\u65B9\u7ED9 `--dshpc-dock-h`\u3002\u4E0D\u652F\u6301\uFF1A\u540C\u540D\u591A\u5B9E\u4F8B\u3001tab \u5207\u6362\u6761\u3001\u81EA\u52A8\u6DD8\u6C70\u2014\u2014\u6807\u7B7E\u5207\u6362\u8BF7\u6D88\u8D39\u65B9\u5728\u81EA\u5DF1\u7684\u9762\u677F\u5185\u5BB9\u91CC\u5B9E\u73B0\u3002\uFF08\u6536\u8D77\u540E\u7684\u8033\u6735\u662F\u72EC\u7ACB `fixed` \u6D6E\u5C42\uFF0C\u4E0D\u662F\u628A\u9762\u677F\u53D8\u6210\u6D6E\u5C42\u3002\uFF09",
57788
+ "en": "Panel height defaults to viewport height; in a fixed-height container the caller sets `--dshpc-dock-h`. Not supported: same-name duplicates, tab bars, auto-eviction \u2014 tab switching belongs in the consumer\u2019s own panel content. (The collapsed ear is a standalone `fixed` overlay; the panel itself never floats.)"
57789
+ },
57790
+ {
57791
+ "zh": "\u5360\u5BBD\u5951\u7EA6\uFF1A\u5DF2\u5F00\u680F\u5BBD\u4E4B\u548C\uFF08\u5916\u52A0\u5F00\u7740\u65F6\u7ED9\u4E3B\u533A\u6EDA\u52A8\u6761\u7559\u7684 1px \u7F1D\uFF0C\u53EF\u7528 `--dshpc-dock-gap` \u8C03\uFF09\u5B9E\u65F6\u5199\u8FDB\u6839\u5143\u7D20 `--dshpc-page-inset-right`\uFF08\u62D6\u62FD\u9010\u5E27\u66F4\u65B0\uFF0C\u5168\u5173\u5373\u79FB\u9664\uFF09\uFF0C\u5168\u5C4F\u906E\u7F69\u636E\u6B64\u8BA9\u4F4D\uFF1B\u540C\u9875\u591A\u4E2A dock \u6C42\u548C\u3002",
57792
+ "en": "Width contract: the sum of open widths plus a 1px scrollbar gutter while open (tunable via `--dshpc-dock-gap`) goes to `--dshpc-page-inset-right` on the root element (every frame while dragging, removed when all close), and full-screen masks yield to it; multiple docks on one page are summed."
57642
57793
  },
57643
57794
  {
57644
- "zh": "\u5360\u5BBD\u5951\u7EA6\uFF1A\u5DF2\u5F00\u680F\u5BBD\u4E4B\u548C\u5B9E\u65F6\u5199\u8FDB\u6839\u5143\u7D20 `--dshpc-page-inset-right`\uFF08\u62D6\u62FD\u9010\u5E27\u66F4\u65B0\uFF0C\u5168\u5173\u5373\u79FB\u9664\uFF09\uFF0C\u5168\u5C4F\u906E\u7F69\u636E\u6B64\u8BA9\u4F4D\uFF1B\u540C\u9875\u591A\u4E2A dock \u6C42\u548C\u3002",
57645
- "en": "Width contract: the sum of open widths goes to `--dshpc-page-inset-right` on the root element (every frame while dragging, removed when all close), and full-screen masks yield to it; multiple docks on one page are summed."
57795
+ "zh": "\u6536\u8D77 / \u5C55\u5F00\uFF1A`dock.collapse(id)` \u8BA9\u9762\u677F\u9000\u51FA\u5E03\u5C40\uFF08\u7ACB\u523B\u4E0D\u5360\u5BBD\uFF09\u3001\u5728\u53F3\u4FA7\u51FA\u4E00\u53EA\u56FA\u5B9A\u8033\u6735\uFF1B`dock.expand(id)` \u628A\u8033\u6735\u6536\u56DE\u3001\u6309\u8BB0\u5FC6\u5BBD\u5EA6\u8FD8\u539F\uFF1B`dock.isCollapsed(id)`\u3002\u8033\u6735\u662F\u5782\u76F4\u5C45\u4E2D\u7684\u5C0F\u56FE\u6807\u9875\u7B7E\uFF08\u4E0D\u653E\u6587\u5B57\uFF09\uFF0C\u5F00\u5408\u5E26\u6ED1\u5165 / \u6536\u62E2\u52A8\u6548\uFF1B\u8033\u6735\u662F\u72EC\u7ACB\u6D6E\u5C42\uFF0C\u4E0E\u5206\u680F\u4E0D\u662F\u4E00\u4F53\uFF1B`close` \u4E0D\u7559\u8033\u6735\u3002",
57796
+ "en": "Collapse / expand: `dock.collapse(id)` takes the panel out of the layout (it stops taking width) and shows a fixed ear at the right edge; `dock.expand(id)` pulls the ear back and restores the remembered width; `dock.isCollapsed(id)`. The ear is a small icon-only tab at the vertical center, with slide/collapse animations; it is a standalone overlay, not part of the dock; `close` leaves no ear."
57646
57797
  }
57647
57798
  ],
57648
57799
  "api": [
@@ -59557,6 +59708,9 @@ if (!result.ok) showToast('\u6700\u591A\u540C\u65F6\u5F00 3 \u680F')
59557
59708
  dock.close('files')
59558
59709
  dock.toggle('preview')
59559
59710
  dock.isOpen('files')
59711
+ dock.collapse('files') // \u6536\u8D77\uFF1A\u9000\u51FA\u5E03\u5C40\u3001\u53D8\u6210\u53F3\u4FA7\u56FA\u5B9A\u8033\u6735\uFF08\u5BBD\u5EA6\u4FDD\u7559\uFF09
59712
+ dock.expand('files') // \u5C55\u5F00\uFF1A\u56DE\u5230\u5E03\u5C40\u3001\u539F\u5BBD\u8FD8\u539F
59713
+ dock.isCollapsed('files')
59560
59714
 
59561
59715
  // 4) \u8BA2\u9605\u72B6\u6001\u9A71\u52A8 UI\uFF08React\uFF09
59562
59716
  const state = useSyncExternalStore(dock.subscribe, dock.getSnapshot, dock.getSnapshot)`;
@@ -59571,7 +59725,12 @@ function LayoutPage() {
59571
59725
  demoDock.close(id3);
59572
59726
  setNotice(null);
59573
59727
  };
59728
+ const collapse = (id3) => {
59729
+ demoDock.collapse(id3);
59730
+ setNotice(null);
59731
+ };
59574
59732
  const opened = state.ids;
59733
+ const collapsedIds = state.collapsed;
59575
59734
  return (0, import_react57.createElement)(
59576
59735
  "div",
59577
59736
  null,
@@ -59586,6 +59745,7 @@ function LayoutPage() {
59586
59745
  (0, import_react57.createElement)(Button, { size: "sm", onClick: () => open("B") }, t3("dockBtnOpenB")),
59587
59746
  (0, import_react57.createElement)(Button, { size: "sm", variant: "primary", onClick: () => open("A") }, t3("dockBtnOpenA2")),
59588
59747
  (0, import_react57.createElement)(Button, { size: "sm", onClick: () => close("A") }, t3("dockBtnCloseA")),
59748
+ (0, import_react57.createElement)(Button, { size: "sm", onClick: () => collapse("A") }, t3("dockBtnCollapseA")),
59589
59749
  (0, import_react57.createElement)(Button, { size: "sm", onClick: () => open("default") }, t3("dockBtnDefault")),
59590
59750
  (0, import_react57.createElement)(Button, { size: "sm", onClick: () => open("C") }, t3("dockBtnOpenC")),
59591
59751
  (0, import_react57.createElement)(
@@ -59594,7 +59754,7 @@ function LayoutPage() {
59594
59754
  size: "sm",
59595
59755
  variant: "ghost",
59596
59756
  onClick: () => {
59597
- for (const id3 of demoDock.ids()) demoDock.close(id3);
59757
+ for (const id3 of [...state.ids, ...state.collapsed]) demoDock.close(id3);
59598
59758
  setNotice(null);
59599
59759
  }
59600
59760
  },
@@ -59605,6 +59765,7 @@ function LayoutPage() {
59605
59765
  "div",
59606
59766
  { style: { fontSize: "12px", color: "var(--dshpc-fg-3)" } },
59607
59767
  `${t3("dockOpened")}${opened.length === 0 ? "\u2014" : opened.join(", ")}`,
59768
+ collapsedIds.length === 0 ? "" : `\u3000${t3("dockCollapsed")}${collapsedIds.join(", ")}`,
59608
59769
  notice === null ? "" : `\u3000${notice}`
59609
59770
  ),
59610
59771
  (0, import_react57.createElement)(
@@ -59851,8 +60012,8 @@ function relativizeToRoot(cache5, sessionId, dir) {
59851
60012
  return dir.slice(norm.length + 1);
59852
60013
  return dir;
59853
60014
  }
59854
- async function findAnyFileAbs(workspaceFiles, sessionId, startDir) {
59855
- const stat = workspaceFiles.stat;
60015
+ async function findAnyFileAbs(workspaceFiles2, sessionId, startDir) {
60016
+ const stat = workspaceFiles2.stat;
59856
60017
  if (stat === void 0)
59857
60018
  return null;
59858
60019
  let frontier = [startDir];
@@ -59861,7 +60022,7 @@ async function findAnyFileAbs(workspaceFiles, sessionId, startDir) {
59861
60022
  for (const dir of frontier.slice(0, 5)) {
59862
60023
  let entries2;
59863
60024
  try {
59864
- const parsed = listingOf(await workspaceFiles.list(sessionId, listPathOf(dir)));
60025
+ const parsed = listingOf(await workspaceFiles2.list(sessionId, listPathOf(dir)));
59865
60026
  if (parsed === null || isFailed(parsed))
59866
60027
  continue;
59867
60028
  entries2 = parsed.entries;
@@ -59887,14 +60048,14 @@ async function findAnyFileAbs(workspaceFiles, sessionId, startDir) {
59887
60048
  }
59888
60049
  return null;
59889
60050
  }
59890
- async function absolutizeDir(cache5, workspaceFiles, sessionId, dir, canonical, entries2) {
60051
+ async function absolutizeDir(cache5, workspaceFiles2, sessionId, dir, canonical, entries2) {
59891
60052
  if (isAbsoluteish(dir))
59892
60053
  return dir;
59893
60054
  const rel = canonical !== "" ? canonical : dir;
59894
60055
  const cached = cache5.get(sessionId);
59895
60056
  if (cached !== void 0)
59896
60057
  return `${cached}/${rel}`;
59897
- const stat = workspaceFiles.stat;
60058
+ const stat = workspaceFiles2.stat;
59898
60059
  if (stat === void 0)
59899
60060
  return dir;
59900
60061
  const file = entries2.find((entry) => entry.type === "file");
@@ -59908,7 +60069,7 @@ async function absolutizeDir(cache5, workspaceFiles, sessionId, dir, canonical,
59908
60069
  } catch {
59909
60070
  }
59910
60071
  }
59911
- const found = await findAnyFileAbs(workspaceFiles, sessionId, rel);
60072
+ const found = await findAnyFileAbs(workspaceFiles2, sessionId, rel);
59912
60073
  if (found === null)
59913
60074
  return dir;
59914
60075
  const root = learnRoot(cache5, sessionId, found.relativePath, found.absolutePath);
@@ -60814,7 +60975,7 @@ function PreviewBody(props) {
60814
60975
  const entryTitle = workspaceAnchorForPath(options.path ?? "", anchors)?.title ?? options.rootName ?? "";
60815
60976
  const [picked, setPicked] = (0, import_react64.useState)(null);
60816
60977
  const wsTitle = picked ?? entryTitle;
60817
- const sessionId = anchorSessionForTitle(anchors, wsTitle) ?? options.sessionId;
60978
+ const sessionId = anchorSessionForTitle(anchors, wsTitle) ?? options.sessionId ?? pickWorkspaceAnchor(anchors)?.sessionId ?? "";
60818
60979
  const switchable = anchors.filter((a) => (a.sessionIds?.length ?? 0) > 0).map((a) => a.title);
60819
60980
  return (0, import_react64.createElement)(FileBrowser, {
60820
60981
  // key 带工作区+会话 ⇒ 切换即重挂载(FileBrowser 的 dir/listing/学根全属于旧工作区)。
@@ -60842,22 +61003,58 @@ function PreviewBody(props) {
60842
61003
  }
60843
61004
  var PREVIEW_HOST_ID = "dshpc-file-preview-host";
60844
61005
  var PREVIEW_PANEL_ID = "file-preview";
60845
- var activePreviewClose = null;
61006
+ var DOCK_HOST_CLASS = "dshpc-dock-host";
61007
+ var activePreview = null;
60846
61008
  function openFilePreview(options) {
60847
61009
  if (typeof document === "undefined")
60848
61010
  return null;
60849
- if (typeof getComputedStyle === "function") {
60850
- const cs = getComputedStyle(options.mount);
60851
- if (cs.display !== "flex" && cs.display !== "inline-flex") {
60852
- console.warn("[dsh-plugin-core/explorer] openFilePreview: mount \u4E0D\u662F flex \u884C \u2014\u2014 PanelDock \u662F\u5E03\u5C40\u6210\u5458\uFF08\u505C\u9760\u53F3\u4FA7 + \u6324\u7A84\u4E3B\u533A\uFF09\u3002\u8BF7\u4F20\u4F60\u9875\u9762\u300C\u4E3B\u533A + \u4FA7\u680F\u300D\u90A3\u4E00\u5C42 flex \u5BB9\u5668\uFF0C\u4E0D\u8981\u4F20 document.body \u6216\u65E0\u5B9A\u9AD8\u7684\u7A84\u5BB9\u5668\u3002");
60853
- }
61011
+ const custom = options.content !== void 0;
61012
+ const files = options.workspaceFiles ?? getWorkspaceFiles();
61013
+ const anchors = options.workspaceAnchors ?? workspaceList.getSnapshot();
61014
+ const sessionId = options.sessionId ?? workspaceAnchorForPath(options.path ?? "", anchors)?.sessionId ?? pickWorkspaceAnchor(anchors)?.sessionId;
61015
+ if (!custom && (files === void 0 || sessionId === void 0)) {
61016
+ console.warn("[dsh-plugin-core/explorer] openFilePreview: " + (files === void 0 ? "\u6CA1\u6709\u5DE5\u4F5C\u533A\u6587\u4EF6\u670D\u52A1\uFF08client apply \u91CC\u6CA1\u8C03 connectHost\uFF0C\u6216\u5BBF\u4E3B\u6CA1\u63D0\u4F9B remote.workspaceFiles\uFF09" : "\u627E\u4E0D\u5230\u53EF\u7528\u7684\u5DE5\u4F5C\u533A\u4F1A\u8BDD\uFF08\u5BBF\u4E3B workspaces \u91CC\u6CA1\u6709\u5E26\u4F1A\u8BDD\u7684\u5DE5\u4F5C\u533A\uFF09") + " \u21D2 \u4E0D\u6253\u5F00\u9884\u89C8");
61017
+ return null;
61018
+ }
61019
+ const opts = { ...options, workspaceFiles: files, sessionId };
61020
+ if (activePreview !== null) {
61021
+ activePreview.keepWidth();
61022
+ activePreview.adopt(opts.mount);
61023
+ activePreview.draw(opts);
61024
+ return { close: activePreview.close, path: opts.path ?? "" };
60854
61025
  }
60855
- activePreviewClose?.();
60856
61026
  const container = document.createElement("div");
60857
61027
  container.id = PREVIEW_HOST_ID;
60858
61028
  container.setAttribute("data-dshpc-file-preview", "");
60859
61029
  container.style.cssText = "display:contents";
60860
- options.mount.appendChild(container);
61030
+ let hostEl = null;
61031
+ let hostPrevDisplay = "";
61032
+ let hostHadClass = false;
61033
+ const restoreHost = () => {
61034
+ if (hostEl === null)
61035
+ return;
61036
+ hostEl.style.display = hostPrevDisplay;
61037
+ if (!hostHadClass)
61038
+ hostEl.classList.remove(DOCK_HOST_CLASS);
61039
+ hostEl = null;
61040
+ };
61041
+ const adopt = (next) => {
61042
+ if (next === hostEl)
61043
+ return;
61044
+ restoreHost();
61045
+ if (next === document.body) {
61046
+ console.warn("[dsh-plugin-core/explorer] openFilePreview: \u4E0D\u8981\u4F20 document.body \u2014\u2014 PanelDock \u662F\u5E03\u5C40\u6210\u5458\uFF08\u505C\u9760\u53F3\u4FA7 + \u6324\u7A84\u4E3B\u533A\uFF09\u3002\u8BF7\u4F20\u4F60\u9875\u9762\u91CC\u5305\u4F4F\u4E3B\u533A\u7684\u90A3\u4E2A\u5143\u7D20\u3002");
61047
+ }
61048
+ hostPrevDisplay = next.style.display;
61049
+ hostHadClass = next.classList.contains(DOCK_HOST_CLASS);
61050
+ next.classList.add(DOCK_HOST_CLASS);
61051
+ const display = typeof getComputedStyle === "function" ? getComputedStyle(next).display : "";
61052
+ if (display !== "flex" && display !== "inline-flex")
61053
+ next.style.display = "flex";
61054
+ next.appendChild(container);
61055
+ hostEl = next;
61056
+ };
61057
+ adopt(options.mount);
60861
61058
  const dock = createPanelDock({
60862
61059
  maxPanels: 1,
60863
61060
  defaultWidth: options.width ?? 460,
@@ -60876,11 +61073,12 @@ function openFilePreview(options) {
60876
61073
  if (closed)
60877
61074
  return;
60878
61075
  closed = true;
60879
- if (activePreviewClose === close)
60880
- activePreviewClose = null;
61076
+ if (activePreview?.close === close)
61077
+ activePreview = null;
60881
61078
  window.removeEventListener("keydown", onKeyDown);
60882
61079
  root.unmount();
60883
61080
  container.remove();
61081
+ restoreHost();
60884
61082
  options.onClose?.();
60885
61083
  };
60886
61084
  const onKeyDown = (event) => {
@@ -60889,40 +61087,59 @@ function openFilePreview(options) {
60889
61087
  };
60890
61088
  window.addEventListener("keydown", onKeyDown);
60891
61089
  ensureControls(getStyleKit());
60892
- const internalSwitch = options.onSelectWorkspace === void 0;
60893
- root.render((0, import_react64.createElement)(
60894
- "div",
60895
- // 高度吃调用方给的 --dshpc-dock-h(demo 的页面行给 100%);退化成视口高是整页场景。
60896
- { style: { display: "contents", ["--dshpc-dock-h"]: "100%" } },
60897
- (0, import_react64.createElement)(PanelDock, { dock, mainMinWidth: options.mainMinWidth ?? 480, translate: options.translate }, (0, import_react64.createElement)(DockPanel, {
60898
- id: PREVIEW_PANEL_ID,
60899
- // 不要头部(用户 2026-10-21:核心的『无 header』那版)——上面不再多一条线。
60900
- header: null,
60901
- // 关闭钮不用核心浮动的(那是 absolute 固定偏移、不垂直居中);关掉它的,
60902
- // 改用 FileBrowser 自己的 ✕(和 pick 弹窗同一个 crumb-bar 钮,垂直居中)。
60903
- closeButton: "none",
60904
- ariaLabel: options.title,
60905
- width: options.width ?? 460,
60906
- minWidth: options.minWidth ?? 320,
60907
- maxWidth: options.maxWidth
60908
- }, options.content !== void 0 ? options.content() : internalSwitch ? (0, import_react64.createElement)(PreviewBody, { options, onClose: close }) : (0, import_react64.createElement)(FileBrowser, {
60909
- workspaceFiles: options.workspaceFiles,
60910
- officeToPdf: options.officeToPdf ?? null,
60911
- sessionId: options.sessionId,
60912
- path: options.path,
60913
- rootName: options.rootName,
60914
- workspaces: options.workspaces,
60915
- workspaceAnchors: options.workspaceAnchors,
60916
- onSelectWorkspace: options.onSelectWorkspace,
60917
- rootCache: options.rootCache,
60918
- translate: options.translate,
60919
- // 传 onClose ⇒ FileBrowser 在面包屑行尾渲染自己的 ✕(垂直居中,与 pick 一致)。
60920
- onClose: close,
60921
- style: { height: "100%", minHeight: 0 }
60922
- })))
60923
- ));
60924
- activePreviewClose = close;
60925
- return { close, path: options.path ?? "" };
61090
+ let pinnedWidth = null;
61091
+ const keepWidth = () => {
61092
+ const panel = container.querySelector(".dshpc-dock__panel");
61093
+ if (panel === null)
61094
+ return;
61095
+ const width = Math.round(panel.getBoundingClientRect().width);
61096
+ if (width < (options.minWidth ?? 320))
61097
+ return;
61098
+ pinnedWidth = width;
61099
+ dock.setWidth(PREVIEW_PANEL_ID, width);
61100
+ };
61101
+ const draw = (o) => {
61102
+ if (dock.isCollapsed(PREVIEW_PANEL_ID))
61103
+ dock.expand(PREVIEW_PANEL_ID);
61104
+ const internalSwitch = o.onSelectWorkspace === void 0;
61105
+ const contentKey = o.path ?? "";
61106
+ root.render((0, import_react64.createElement)(
61107
+ "div",
61108
+ // 高度吃调用方给的 --dshpc-dock-h(demo 的页面行给 100%);退化成视口高是整页场景。
61109
+ { style: { display: "contents", ["--dshpc-dock-h"]: "100%" } },
61110
+ (0, import_react64.createElement)(PanelDock, { dock, mainMinWidth: o.mainMinWidth ?? 480, translate: o.translate }, (0, import_react64.createElement)(DockPanel, {
61111
+ id: PREVIEW_PANEL_ID,
61112
+ // 不要头部(用户 2026-10-21:核心的『无 header』那版)——上面不再多一条线。
61113
+ header: null,
61114
+ // 关闭钮不用核心浮动的(那是 absolute 固定偏移、不垂直居中);关掉它的,
61115
+ // 改用 FileBrowser 自己的 ✕(和 pick 弹窗同一个 crumb-bar 钮,垂直居中)。
61116
+ closeButton: "none",
61117
+ ariaLabel: o.title,
61118
+ // 重画时沿用用户拖出来的宽度(pinnedWidth),不回到默认值。
61119
+ width: pinnedWidth ?? o.width ?? 460,
61120
+ minWidth: o.minWidth ?? 320,
61121
+ maxWidth: o.maxWidth
61122
+ }, o.content !== void 0 ? o.content() : internalSwitch ? (0, import_react64.createElement)(PreviewBody, { key: contentKey, options: o, onClose: close }) : (0, import_react64.createElement)(FileBrowser, {
61123
+ key: contentKey,
61124
+ workspaceFiles: o.workspaceFiles,
61125
+ officeToPdf: o.officeToPdf ?? null,
61126
+ sessionId: o.sessionId,
61127
+ path: o.path,
61128
+ rootName: o.rootName,
61129
+ workspaces: o.workspaces,
61130
+ workspaceAnchors: o.workspaceAnchors,
61131
+ onSelectWorkspace: o.onSelectWorkspace,
61132
+ rootCache: o.rootCache,
61133
+ translate: o.translate,
61134
+ // 传 onClose ⇒ FileBrowser 在面包屑行尾渲染自己的 ✕(垂直居中,与 pick 一致)。
61135
+ onClose: close,
61136
+ style: { height: "100%", minHeight: 0 }
61137
+ })))
61138
+ ));
61139
+ };
61140
+ draw(opts);
61141
+ activePreview = { adopt, keepWidth, draw, close };
61142
+ return { close, path: opts.path ?? "" };
60926
61143
  }
60927
61144
  var PICKER_WIDTH = 480;
60928
61145
  var PICKER_MAX_H = 660;
@@ -60934,6 +61151,13 @@ function pickWorkspaceFile(options) {
60934
61151
  resolve(null);
60935
61152
  return;
60936
61153
  }
61154
+ const files = options.workspaceFiles ?? getWorkspaceFiles();
61155
+ const sessionId = options.sessionId ?? pickWorkspaceAnchor(workspaceList.getSnapshot())?.sessionId;
61156
+ if (files === void 0 || sessionId === void 0) {
61157
+ console.warn("[dsh-plugin-core/explorer] pickWorkspaceFile: " + (files === void 0 ? "\u6CA1\u6709\u5DE5\u4F5C\u533A\u6587\u4EF6\u670D\u52A1\uFF08client apply \u91CC\u6CA1\u8C03 connectHost\uFF09" : "\u627E\u4E0D\u5230\u53EF\u7528\u7684\u5DE5\u4F5C\u533A\u4F1A\u8BDD") + " \u21D2 \u4E0D\u5F39\u9009\u62E9\u6846");
61158
+ resolve(null);
61159
+ return;
61160
+ }
60937
61161
  let settled = false;
60938
61162
  const backdrop = document.createElement("div");
60939
61163
  backdrop.setAttribute("data-dshpc-picker-backdrop", "");
@@ -60982,9 +61206,9 @@ function pickWorkspaceFile(options) {
60982
61206
  ensureControls(getStyleKit());
60983
61207
  const root = (0, import_client5.createRoot)(panel);
60984
61208
  root.render((0, import_react64.createElement)(FileBrowser, {
60985
- workspaceFiles: options.workspaceFiles,
61209
+ workspaceFiles: files,
60986
61210
  officeToPdf: options.officeToPdf ?? null,
60987
- sessionId: options.sessionId,
61211
+ sessionId,
60988
61212
  path: "",
60989
61213
  rootName: options.rootName,
60990
61214
  rootCache: options.rootCache,
@@ -61056,21 +61280,18 @@ async function findSamples(files, sessionId) {
61056
61280
  var CODE_OPEN = `// \u53F3\u4FA7\u5206\u680F\u9884\u89C8\uFF08\u5360\u5BBD\u5EA6\u3001\u6324\u7A84\u4E3B\u533A\uFF1B\u4E0D\u662F\u6D6E\u5C42\uFF09
61057
61281
  import { openFilePreview } from 'dsh-plugin-core/explorer'
61058
61282
 
61283
+ // apply \u91CC connectHost(ctx) \u63A5\u7EBF\u4E00\u6B21\uFF0C\u4E4B\u540E\u53EA\u8981\u4E00\u4E2A\u5BB9\u5668 + \u4E00\u4E2A\u8DEF\u5F84\uFF1A
61059
61284
  openFilePreview({
61060
- mount, // \u4F60\u9875\u9762\u91CC\u90A3\u4E00\u5C42 flex \u884C\uFF0C\u4E0D\u8981\u4F20 document.body \u518D\u81EA\u5DF1\u5957 fixed
61061
- workspaceFiles, // \u4ECE ctx \u53D6\u51FA\u540E\u6CE8\u5165\uFF08host \u80FD\u529B\uFF09
61062
- sessionId, // \u4F1A\u8BDD\u4F5C\u7528\u57DF\uFF08\u9ED8\u8BA4\u951A\u70B9\uFF09
61063
- path: p, // \u7EDD\u5BF9\u8DEF\u5F84\u4E5F\u53EF\u4EE5
61064
- rootName: '\u6211\u7684\u9879\u76EE',
61285
+ mount, // \u4F60\u9875\u9762\u91CC\u5305\u4F4F\u4E3B\u533A\u7684\u90A3\u4E2A\u5143\u7D20\uFF08\u4E0D\u5FC5\u5199\u6210 flex\uFF0C\u6838\u5FC3\u4F1A\u8865\u3001\u5173\u95ED\u5373\u8FD8\u539F\uFF09
61286
+ path: p, // \u6587\u4EF6\u6216\u6587\u4EF6\u5939\u90FD\u884C\uFF1B\u7EDD\u5BF9\u8DEF\u5F84\u4E5F\u53EF\u4EE5
61065
61287
  })
61066
- // path \u662F\u7EDD\u5BF9\u8DEF\u5F84\u65F6\uFF1A\u6838\u5FC3\u81EA\u52A8\u8BFB\u5BBF\u4E3B workspaces \u5FEB\u7167\uFF08\u63D2\u4EF6 apply \u91CC connectHost \u6CE8\u5165\u8FC7\uFF09\uFF0C
61067
- // \u6309\u6700\u957F\u524D\u7F00\u5339\u914D\u6240\u5C5E\u5DE5\u4F5C\u533A\u3001list \u6362\u8BE5\u5DE5\u4F5C\u533A\u7684\u4F1A\u8BDD \u21D2 \u9762\u5305\u5C51/\u76EE\u5F55\u6811\u6B63\u5E38\uFF1B
61068
- // \u25BE \u4E0B\u62C9\u300C\u5207\u5DE5\u4F5C\u533A\u300D\u540C\u6837\u81EA\u52A8\u53EF\u7528\uFF08\u65E0\u4F1A\u8BDD\u7684\u5DE5\u4F5C\u533A\u4E0D\u8FDB\u5217\u8868\uFF09\u3002
61069
- // \u8981\u8986\u76D6\u5FEB\u7167\u624D\u663E\u5F0F\u4F20 workspaceAnchors\uFF08\u5BBF\u4E3B workspaces \u5FEB\u7167\u539F\u6837\uFF09\u3002`;
61288
+ // \u6587\u4EF6\u670D\u52A1 / \u4F1A\u8BDD / \u5DE5\u4F5C\u533A\u5FEB\u7167\u5168\u7531\u6838\u5FC3\u89E3\uFF1A\u7EDD\u5BF9\u8DEF\u5F84\u6309\u6700\u957F\u524D\u7F00\u5339\u914D\u6240\u5C5E\u5DE5\u4F5C\u533A\uFF08connectHost \u6CE8\u5165\u7684
61289
+ // \u5BBF\u4E3B workspaces \u5FEB\u7167\uFF09\uFF1B\u843D\u5728\u5DE5\u4F5C\u533A\u5916 \u21D2 \u6587\u4EF6\u7167\u5E38\u9884\u89C8\u3001\u76EE\u5F55\u6811\u9000\u5316\u6210\u53EA\u8BFB\u8DEF\u5F84\u680F\u3002
61290
+ // \u8981\u8986\u76D6\u5FEB\u7167\u624D\u4F20 workspaceAnchors\uFF0C\u8981\u6307\u5B9A\u4F1A\u8BDD\u624D\u4F20 sessionId\u3002`;
61070
61291
  var CODE_PICK = `// \u951A\u5B9A\u6309\u94AE\u65C1\u5F39\u6A21\u6001\u9009\u6587\u4EF6\uFF08Promise \u8FD4\u56DE\u5DE5\u4F5C\u533A\u76F8\u5BF9\u8DEF\u5F84\uFF0C\u4E0D\u81EA\u5DF1\u6302 dock\uFF09
61071
61292
  import { pickWorkspaceFile } from 'dsh-plugin-core/explorer'
61072
61293
 
61073
- const r = await pickWorkspaceFile({ workspaceFiles, sessionId, anchor: btn, filter: { exts: ['js', 'md'] } })
61294
+ const r = await pickWorkspaceFile({ anchor: btn, filter: { exts: ['js', 'md'] } })
61074
61295
  // r = { path, isDir }`;
61075
61296
  var CODE_SESSION_REAL = `// \u771F\u5B9E\u5BBF\u4E3B\uFF1Asessions.list \u5FEB\u7167\uFF08\u51B7\u5B89\u5168\uFF0C\u4E0D\u6FC0\u6D3B Agent\uFF09\u2192 \u70B9\u5F00\u771F\u9884\u89C8
61076
61297
  // \u670D\u52A1\u6765\u81EA package.json dsh.client.inject \u7684\u4E09\u4E2A\u5B98\u65B9\u5305\uFF1A
@@ -61093,7 +61314,7 @@ h(SessionViewModal, {
61093
61314
  forkSession: (id, atSeq) => sessions.fork({ sessionId: id, increaseTitle: true, atSeq }),
61094
61315
  openHostSession: (id) => uiWorkspace.openSession(id),
61095
61316
  // \u6587\u4EF6\u94FE\u63A5 \u2192 **\u9875\u9762\u53F3\u4FA7**\u5F00\u6838\u5FC3\u6587\u4EF6\u9884\u89C8 dock\uFF08\u6324\u7A84\u4E3B\u533A\uFF09
61096
- onOpenFile: (path) => openFilePreview({ mount: pageRow.element, workspaceFiles, path, ... }),
61317
+ onOpenFile: (path) => openFilePreview({ mount: pageRow.element, path, ... }),
61097
61318
  // \u4E0D\u7528\u7ED9\u5F39\u7A97\u4EFB\u4F55\u5BBD\u5EA6\u53C2\u6570\uFF1Adock \u628A\u5360\u5BBD\u53D1\u5E03\u6210 CSS \u53D8\u91CF\uFF0C\u906E\u7F69\u81EA\u5DF1\u8BA9\u4F4D\uFF08\u7528\u6237 2026-10-22\uFF09
61098
61319
  })`;
61099
61320
  var CODE_BLOCKS_USAGE = `pnpm add dsh-plugin-core
@@ -61101,10 +61322,10 @@ var CODE_BLOCKS_USAGE = `pnpm add dsh-plugin-core
61101
61322
  import { openFilePreview, pickWorkspaceFile } from 'dsh-plugin-core/explorer'
61102
61323
  import { openSessionView, SessionViewModal } from 'dsh-plugin-core/session'`;
61103
61324
  function useExplorerHost() {
61104
- const { workspaceFiles, officeToPdf } = (0, import_react65.useSyncExternalStore)(fileServices.subscribe, fileServices.getSnapshot);
61325
+ const { workspaceFiles: workspaceFiles2, officeToPdf } = (0, import_react65.useSyncExternalStore)(fileServices.subscribe, fileServices.getSnapshot);
61105
61326
  const wsItems = (0, import_react65.useSyncExternalStore)(workspaceList.subscribe, workspaceList.getSnapshot);
61106
61327
  const anchor = pickWorkspaceAnchor(wsItems);
61107
- return { workspaceFiles, officeToPdf, anchor, workspaceNames: wsItems.map((w) => w.title) };
61328
+ return { workspaceFiles: workspaceFiles2, officeToPdf, anchor, workspaceNames: wsItems.map((w) => w.title) };
61108
61329
  }
61109
61330
  function NotReady(props) {
61110
61331
  return (0, import_react65.createElement)(
@@ -61114,23 +61335,23 @@ function NotReady(props) {
61114
61335
  );
61115
61336
  }
61116
61337
  function OpenPreviewDemo() {
61117
- const { workspaceFiles, anchor, workspaceNames } = useExplorerHost();
61338
+ const { workspaceFiles: workspaceFiles2, anchor, workspaceNames } = useExplorerHost();
61118
61339
  const [samples, setSamples] = (0, import_react65.useState)(null);
61119
61340
  const [phase, setPhase] = (0, import_react65.useState)("idle");
61120
61341
  const [last2, setLast] = (0, import_react65.useState)(null);
61121
61342
  const pending = (0, import_react65.useRef)(null);
61122
61343
  const sessionId = anchor === null ? null : anchor.sessionId;
61123
61344
  (0, import_react65.useEffect)(() => {
61124
- if (workspaceFiles === null || sessionId === null) return;
61345
+ if (workspaceFiles2 === null || sessionId === null) return;
61125
61346
  if (pending.current !== null) return;
61126
61347
  setPhase("probing");
61127
- pending.current = findSamples(workspaceFiles, sessionId).then((s) => {
61348
+ pending.current = findSamples(workspaceFiles2, sessionId).then((s) => {
61128
61349
  setSamples(s);
61129
61350
  setPhase(s === null ? "missing" : "found");
61130
61351
  return s;
61131
61352
  });
61132
- }, [workspaceFiles, sessionId]);
61133
- if (workspaceFiles === null) return (0, import_react65.createElement)(NotReady, { which: "files" });
61353
+ }, [workspaceFiles2, sessionId]);
61354
+ if (workspaceFiles2 === null) return (0, import_react65.createElement)(NotReady, { which: "files" });
61134
61355
  if (anchor === null) return (0, import_react65.createElement)(NotReady, { which: "anchor" });
61135
61356
  const open = (path, rootName, workspaces) => {
61136
61357
  const mount = pageRow.element;
@@ -61138,7 +61359,7 @@ function OpenPreviewDemo() {
61138
61359
  console.warn("[demo] pageRow \u672A\u5C31\u7EEA\uFF0C\u65E0\u6CD5\u505C\u9760\u9884\u89C8");
61139
61360
  return;
61140
61361
  }
61141
- openFilePreview({ mount, workspaceFiles, sessionId: anchor.sessionId, path, rootName, workspaces });
61362
+ openFilePreview({ mount, sessionId: anchor.sessionId, path, rootName, workspaces });
61142
61363
  setLast(path === "" ? `${rootName}\uFF08\u6839\uFF09` : path);
61143
61364
  };
61144
61365
  const sampleLabel = (normal3) => phase === "missing" ? t3("samplesNotFound") : t3(normal3);
@@ -61162,13 +61383,12 @@ function OpenPreviewDemo() {
61162
61383
  );
61163
61384
  }
61164
61385
  function PickFileDemo() {
61165
- const { workspaceFiles, anchor } = useExplorerHost();
61386
+ const { workspaceFiles: workspaceFiles2, anchor } = useExplorerHost();
61166
61387
  const [picked, setPicked] = (0, import_react65.useState)(null);
61167
- if (workspaceFiles === null) return (0, import_react65.createElement)(NotReady, { which: "files" });
61388
+ if (workspaceFiles2 === null) return (0, import_react65.createElement)(NotReady, { which: "files" });
61168
61389
  if (anchor === null) return (0, import_react65.createElement)(NotReady, { which: "anchor" });
61169
61390
  const pick2 = (anchorBtn, filter2) => {
61170
61391
  void pickWorkspaceFile({
61171
- workspaceFiles,
61172
61392
  sessionId: anchor.sessionId,
61173
61393
  anchor: anchorBtn,
61174
61394
  rootName: anchor.title,
@@ -61204,15 +61424,14 @@ function RealSessionListDemo() {
61204
61424
  const anchor = pickWorkspaceAnchor(wsItems);
61205
61425
  const [openId, setOpenId] = (0, import_react65.useState)(null);
61206
61426
  const view = (0, import_react65.useMemo)(() => openId === null ? null : openRealSessionView(openId), [openId]);
61207
- const workspaceFiles = files.workspaceFiles;
61208
- const canOpenFile = workspaceFiles !== null && anchor !== null;
61427
+ const workspaceFiles2 = files.workspaceFiles;
61428
+ const canOpenFile = workspaceFiles2 !== null && anchor !== null;
61209
61429
  const openLinkedFile = (path, sessionId) => {
61210
61430
  console.log("[preview] openLinkedFile path=", JSON.stringify(path), "sessionId=", sessionId, "anchorSessionId=", anchor?.sessionId);
61211
61431
  const mount = pageRow.element;
61212
- if (mount === null || workspaceFiles === null || anchor === null) return;
61432
+ if (mount === null || workspaceFiles2 === null || anchor === null) return;
61213
61433
  openFilePreview({
61214
61434
  mount,
61215
- workspaceFiles,
61216
61435
  officeToPdf: files.officeToPdf,
61217
61436
  // 文件 RPC 按会话作用域取工作区:优先用调用方透传的「文件所属会话」,
61218
61437
  // 兜底才用当前工作区锚点会话(explorer 页那种没上下文的入口)。
@@ -61228,7 +61447,6 @@ function RealSessionListDemo() {
61228
61447
  let handle = null;
61229
61448
  handle = openFilePreview({
61230
61449
  mount,
61231
- workspaceFiles: workspaceFiles ?? void 0,
61232
61450
  sessionId: loc.sessionId,
61233
61451
  path: "",
61234
61452
  content: () => (0, import_react65.createElement)(ChangedFileDiff, {
@@ -61509,9 +61727,9 @@ function ReferencePage() {
61509
61727
  "tbody",
61510
61728
  null,
61511
61729
  [
61512
- [t3("buildCore"), `v${"0.6.0"}`],
61513
- [t3("buildDemo"), `v${"0.6.0"}`],
61514
- [t3("buildStamp"), "261028-034237-929"]
61730
+ [t3("buildCore"), `v${"0.7.1"}`],
61731
+ [t3("buildDemo"), `v${"0.7.1"}`],
61732
+ [t3("buildStamp"), "261028-075655-587"]
61515
61733
  ].map(
61516
61734
  ([label, value]) => (0, import_react67.createElement)(
61517
61735
  "tr",
@@ -61833,9 +62051,9 @@ function DemoPage() {
61833
62051
  lineHeight: "14px"
61834
62052
  }
61835
62053
  },
61836
- (0, import_react69.createElement)("span", null, `core v${"0.6.0"}`),
61837
- (0, import_react69.createElement)("span", null, `demo v${"0.6.0"}`),
61838
- (0, import_react69.createElement)("span", { style: { marginTop: "4px", fontSize: "9px" } }, "261028-034237-929")
62054
+ (0, import_react69.createElement)("span", null, `core v${"0.7.1"}`),
62055
+ (0, import_react69.createElement)("span", null, `demo v${"0.7.1"}`),
62056
+ (0, import_react69.createElement)("span", { style: { marginTop: "4px", fontSize: "9px" } }, "261028-075655-587")
61839
62057
  )
61840
62058
  )
61841
62059
  ),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-plugin-core-demo",
3
- "version": "0.6.0",
3
+ "version": "0.7.1",
4
4
  "description": "The shared UI foundation for DSH plugins, with a live component preview: design tokens, common controls, workspace browsing and notifications maintained in one place — install it to preview every component in a real host.",
5
5
  "icon": "./assets/icon-components.svg",
6
6
  "keywords": [