@lijian-ui/dsh-file-manager 0.1.21 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/client.js CHANGED
@@ -2348,28 +2348,6 @@ window.__ModuleLoader__.load({
2348
2348
  function maximizedOverlay(availableWidth) {
2349
2349
  return availableWidth > 0 && availableWidth < 640;
2350
2350
  }
2351
- /** The WCO titlebar height when visible; 0 in a plain browser tab. */
2352
- function titlebarAreaHeight() {
2353
- const wco = navigator.windowControlsOverlay;
2354
- if (wco === void 0 || !wco.visible || wco.getTitlebarAreaRect === void 0) return 0;
2355
- try {
2356
- const height = wco.getTitlebarAreaRect()?.height ?? 0;
2357
- return height > 0 ? Math.round(height) : 0;
2358
- } catch {
2359
- return 0;
2360
- }
2361
- }
2362
- /** Clamp a requested top px into the usable vertical range. */
2363
- function clampFloatingTop(top, viewportHeight, buttonHeight, titlebar) {
2364
- const min = titlebar + 6;
2365
- const max = Math.max(min, viewportHeight - buttonHeight - 6);
2366
- if (!Number.isFinite(top)) return min;
2367
- return Math.min(max, Math.max(min, top));
2368
- }
2369
- /** The default top: aligned with the collapse chevron at the top-right. */
2370
- function topAlignedFloatingTop(viewportHeight, buttonHeight, titlebar) {
2371
- return clampFloatingTop(titlebar + 6, viewportHeight, buttonHeight, titlebar);
2372
- }
2373
2351
  //#endregion
2374
2352
  //#region src/client/layout.ts
2375
2353
  /**
@@ -2457,7 +2435,6 @@ window.__ModuleLoader__.load({
2457
2435
  explorerCol = null;
2458
2436
  explorerHandle = null;
2459
2437
  previewHandle = null;
2460
- floatingButton = null;
2461
2438
  styleObserver = null;
2462
2439
  sizeObserver = null;
2463
2440
  waitObserver = null;
@@ -2519,23 +2496,6 @@ window.__ModuleLoader__.load({
2519
2496
  this.previewHandle = this.createHandle("filemgr-preview-handle", 20, true, "preview");
2520
2497
  frame.appendChild(this.explorerHandle);
2521
2498
  frame.appendChild(this.previewHandle);
2522
- this.floatingButton = document.createElement("button");
2523
- this.floatingButton.type = "button";
2524
- this.floatingButton.className = "filemgr-floating-expand";
2525
- this.floatingButton.setAttribute("aria-label", "Expand explorer");
2526
- this.floatingButton.innerHTML = "<svg viewBox=\"0 0 16 16\" width=\"16\" height=\"16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><path d=\"M6 3l5 5-5 5\"/></svg>";
2527
- this.floatingButton.addEventListener("click", () => {
2528
- this.toggleExplorer();
2529
- });
2530
- document.body.appendChild(this.floatingButton);
2531
- const overlay = navigator.windowControlsOverlay;
2532
- if (overlay !== void 0) {
2533
- const onGeometryChange = () => {
2534
- this.positionFloatingButton();
2535
- };
2536
- overlay.addEventListener("geometrychange", onGeometryChange);
2537
- this.disposers.push(() => overlay.removeEventListener("geometrychange", onGeometryChange));
2538
- }
2539
2499
  const onKeyDown = (event) => {
2540
2500
  if (event.key !== "Escape") return;
2541
2501
  const target = event.target instanceof Element ? event.target : null;
@@ -2559,6 +2519,10 @@ window.__ModuleLoader__.load({
2559
2519
  return;
2560
2520
  }
2561
2521
  if (tracks.length === 5 && this.shellTracks.length === 3) return;
2522
+ if (tracks.length === 6 && tracks.includes("[dsh-term]") && this.shellTracks.length === 3) {
2523
+ this.applyGrid();
2524
+ return;
2525
+ }
2562
2526
  };
2563
2527
  this.styleObserver = new MutationObserver(syncGrid);
2564
2528
  this.styleObserver.observe(frame, {
@@ -2682,18 +2646,6 @@ window.__ModuleLoader__.load({
2682
2646
  const bottom = header.getBoundingClientRect().bottom;
2683
2647
  return Number.isFinite(bottom) ? bottom : null;
2684
2648
  }
2685
- /** Position the floating button: docked at the top-right corner, just
2686
- * below the shell header's bottom divider (fallback: the chevron row). */
2687
- positionFloatingButton() {
2688
- const el = this.floatingButton;
2689
- if (el === null) return;
2690
- const height = window.innerHeight;
2691
- const titlebar = titlebarAreaHeight();
2692
- const headerBottom = this.findHeaderBottom();
2693
- const top = headerBottom !== null ? clampFloatingTop(headerBottom + 8, height, 24, titlebar) : topAlignedFloatingTop(height, 24, titlebar);
2694
- el.style.top = `${Math.round(top)}px`;
2695
- el.style.transform = "none";
2696
- }
2697
2649
  /** Apply one store update with transitions disabled for exactly one frame. */
2698
2650
  instant(fn) {
2699
2651
  const frame = this.frame;
@@ -2723,28 +2675,27 @@ window.__ModuleLoader__.load({
2723
2675
  this.clearMaximizedChrome();
2724
2676
  const explorer = this.layout.explorerWidthPx(state);
2725
2677
  const preview = this.layout.previewWidthPx(state);
2726
- frame.style.gridTemplateColumns = `${this.shellTracks[0]} minmax(0, 1fr) ${this.shellTracks[2]} ${Math.round(preview)}px ${Math.round(explorer)}px`;
2678
+ const dshTermCol = parseGridTracks(frame.style.gridTemplateColumns).includes("[dsh-term]") ? frame.querySelector("[data-dsh-term-col]") : null;
2679
+ const dshTermOpen = dshTermCol !== null && dshTermCol.style.display !== "none" && dshTermCol.getBoundingClientRect().width > 0;
2680
+ const dshTermWidth = dshTermOpen ? Math.round(dshTermCol.getBoundingClientRect().width) : 0;
2681
+ const baseGrid = `${this.shellTracks[0]} minmax(0, 1fr) ${this.shellTracks[2]} ${Math.round(preview)}px ${Math.round(explorer)}px`;
2682
+ frame.style.gridTemplateColumns = dshTermOpen ? `${baseGrid} [dsh-term] ${dshTermWidth}px` : baseGrid;
2727
2683
  if (this.explorerCol !== null) this.explorerCol.style.visibility = explorer > 0 ? "visible" : "hidden";
2728
2684
  if (this.previewCol !== null) this.previewCol.style.visibility = preview > 0 ? "visible" : "hidden";
2729
2685
  if (this.explorerHandle !== null) {
2730
- const left = Math.round(width - explorer);
2686
+ const left = Math.round(width - explorer - dshTermWidth);
2731
2687
  this.explorerHandle.style.left = `${left}px`;
2732
2688
  this.explorerHandle.style.marginLeft = `${-12 / 2}px`;
2733
2689
  this.explorerHandle.style.display = explorer > 0 && state.root !== "" ? "block" : "none";
2734
2690
  }
2735
2691
  if (this.previewHandle !== null) {
2736
- const left = Math.round(width - explorer - preview);
2692
+ const left = Math.round(width - explorer - preview - dshTermWidth);
2737
2693
  this.previewHandle.style.left = `${left}px`;
2738
2694
  this.previewHandle.style.display = preview > 0 && state.root !== "" ? "block" : "none";
2739
2695
  }
2740
2696
  const detailsTrack = trackPx(this.shellTracks[2]);
2741
2697
  if (this.detailsHandle === null || !this.detailsHandle.isConnected) this.detailsHandle = frame.querySelector("[data-side=\"details\"]");
2742
- if (this.detailsHandle !== null) this.detailsHandle.style.left = `${Math.round(width - detailsTrack - preview - explorer)}px`;
2743
- if (this.floatingButton !== null) {
2744
- const show = state.root !== "" && state.explorerCollapsed;
2745
- this.floatingButton.style.display = show ? "flex" : "none";
2746
- this.positionFloatingButton();
2747
- }
2698
+ if (this.detailsHandle !== null) this.detailsHandle.style.left = `${Math.round(width - detailsTrack - preview - explorer - dshTermWidth)}px`;
2748
2699
  }
2749
2700
  /**
2750
2701
  * Maximize layout: the target column takes over the whole frame row (the
@@ -2765,7 +2716,6 @@ window.__ModuleLoader__.load({
2765
2716
  }
2766
2717
  if (this.explorerHandle !== null) this.explorerHandle.style.display = "none";
2767
2718
  if (this.previewHandle !== null) this.previewHandle.style.display = "none";
2768
- if (this.floatingButton !== null) this.floatingButton.style.display = "none";
2769
2719
  }
2770
2720
  /** Remove the narrow-screen overlay class from both columns. */
2771
2721
  clearMaximizedChrome() {
@@ -2782,7 +2732,6 @@ window.__ModuleLoader__.load({
2782
2732
  this.explorerCol?.remove();
2783
2733
  this.explorerHandle?.remove();
2784
2734
  this.previewHandle?.remove();
2785
- this.floatingButton?.remove();
2786
2735
  if (this.instantTimer !== void 0) clearTimeout(this.instantTimer);
2787
2736
  if (frameElement === this.frame) frameElement = null;
2788
2737
  this.frame = null;
@@ -4104,7 +4053,7 @@ window.__ModuleLoader__.load({
4104
4053
  };
4105
4054
  //#endregion
4106
4055
  //#region \0dsh-css:src/client/styles/tokens.module.css.mjs
4107
- const css$4 = ":root{--aion-bg-base:#fff;--aion-bg-1:#f9fafb;--aion-bg-2:#f2f3f5;--aion-bg-3:#e5e6eb;--aion-bg-hover:#f3f4f6;--aion-bg-active:#e5e6eb;--aion-text-primary:#000;--aion-text-secondary:#454d5f;--aion-text-tertiary:#86909c;--aion-text-disabled:#c9cdd4;--aion-primary:#165dff;--aion-success:#00b42a;--aion-warning:#ff7d00;--aion-danger:#f53f3f;--aion-brand:#7583b2;--aion-aou-1:#eff0f6;--aion-aou-2:#e5e7f0;--aion-aou-3:#d1d5e5;--aion-aou-4:#b5bcd6;--aion-aou-5:#97a0c5;--aion-aou-6:#7583b2;--aion-fill-2:#f2f3f5;--aion-fill-3:#e5e6eb;--aion-border-base:#e5e6eb;--aion-overlay-shadow:0 8px 24px #0f172a1f;--aion-font-sans:-apple-system, \"system-ui\", \"Segoe UI\", Roboto, \"Helvetica Neue\", \"PingFang SC\", \"Microsoft YaHei\", sans-serif;--aion-font-mono:ui-monospace, \"SF Mono\", SFMono-Regular, Menlo, Consolas, \"Liberation Mono\", monospace}body[data-ds-dark-theme]{--aion-bg-base:#0e0e0e;--aion-bg-1:#1a1a1a;--aion-bg-2:#262626;--aion-bg-3:#333;--aion-bg-hover:#1f1f1f;--aion-bg-active:#2d2d2d;--aion-text-primary:#fff;--aion-text-secondary:#ced3da;--aion-text-tertiary:#737373;--aion-text-disabled:#737373;--aion-primary:#4d9fff;--aion-success:#23c343;--aion-warning:#ff9a2e;--aion-danger:#f76560;--aion-brand:#a1aacb;--aion-aou-1:#2a2a2a;--aion-aou-2:#3d4150;--aion-aou-3:#525a77;--aion-aou-4:#6a749b;--aion-aou-5:#838fba;--aion-aou-6:#a1aacb;--aion-fill-2:#ffffff14;--aion-fill-3:#ffffff1f;--aion-border-base:#333;--aion-overlay-shadow:0 12px 32px #00000073;color-scheme:dark}.filemgr-root{font-family:var(--aion-font-sans);color:var(--aion-text-primary);background-color:var(--aion-bg-1);font-size:13px}.filemgr-root *,.filemgr-root :before,.filemgr-root :after{box-sizing:border-box}.filemgr-root ::-webkit-scrollbar{width:8px;height:8px}.filemgr-root ::-webkit-scrollbar-thumb{background:var(--aion-bg-3);border-radius:4px}.filemgr-root ::-webkit-scrollbar-thumb:hover{background:var(--aion-bg-4,#c9cdd4)}.filemgr-root ::-webkit-scrollbar-track{background:0 0}@media (prefers-reduced-motion:reduce){.filemgr-root *,.filemgr-root :before,.filemgr-root :after{transition:none!important;animation:none!important}}[data-dsh-frame][data-filemgr-instant]{transition:none!important}.filemgr-preview-col,.filemgr-explorer-col{background-color:var(--aion-bg-1);z-index:30;flex-direction:column;min-width:0;display:flex;overflow:hidden}.filemgr-preview-col{border-left:1px solid var(--aion-bg-3)}.filemgr-preview-col.filemgr-maximized,.filemgr-explorer-col.filemgr-maximized{z-index:60;inset:0;position:fixed!important}.filemgr-explorer-col{border-left:1px solid var(--aion-bg-3)}.filemgr-preview-col.filemgr-preview-enter{animation:.25s cubic-bezier(.4,0,.2,1) aPVr2q_filemgr-preview-enter}@keyframes aPVr2q_filemgr-preview-enter{0%{opacity:0;transform:translate(20px)}to{opacity:1;transform:translate(0)}}.filemgr-explorer-handle,.filemgr-preview-handle{touch-action:none}.filemgr-explorer-handle:after,.filemgr-preview-handle:after{content:\"\";background-color:var(--aion-bg-3);opacity:.9;pointer-events:none;border-radius:9999px;width:2px;transition:width .15s cubic-bezier(.4,0,.2,1),background-color .15s cubic-bezier(.4,0,.2,1);position:absolute;top:0;bottom:0;left:0}.filemgr-explorer-handle:hover:after,.filemgr-explorer-handle:active:after,.filemgr-preview-handle:hover:after,.filemgr-preview-handle:active:after{background-color:var(--aion-brand);width:6px}.filemgr-preview-handle:after{opacity:.3;left:auto;right:0}.filemgr-preview-handle:hover:after,.filemgr-preview-handle:active:after{opacity:1}.filemgr-floating-expand{top:calc(6px + env(aPVr2q_titlebar-area-height,0px));background-color:var(--aion-bg-2);width:24px;height:24px;color:var(--aion-text-secondary);cursor:pointer;z-index:100;border:none;border-radius:4px;justify-content:center;align-items:center;transition:background-color .15s cubic-bezier(.4,0,.2,1);display:none;position:fixed;right:8px;box-shadow:0 2px 8px #0000001f}.filemgr-floating-expand:hover{background-color:var(--aion-bg-3);color:var(--aion-text-primary)}.filemgr-floating-expand:active{background-color:var(--aion-bg-active)}.filemgr-floating-expand:focus-visible{outline:2px solid var(--aion-primary);outline-offset:2px}.filemgr-collapse-chevron{top:calc(6px + env(aPVr2q_titlebar-area-height,0px));z-index:30;width:24px;height:24px;color:var(--aion-text-secondary);cursor:pointer;background:0 0;border:none;border-radius:4px;justify-content:center;align-items:center;transition:background-color .15s cubic-bezier(.4,0,.2,1);display:flex;position:absolute;right:8px}.filemgr-collapse-chevron:hover{background-color:var(--aion-bg-3);color:var(--aion-text-primary)}.filemgr-collapse-chevron:active{background-color:var(--aion-bg-active)}.filemgr-collapse-chevron:focus-visible{outline:2px solid var(--aion-primary);outline-offset:2px}.filemgr-overlay{z-index:1000;background:#00000059;justify-content:center;align-items:center;display:flex;position:fixed;inset:0}.filemgr-dialog{background:var(--aion-bg-base);width:400px;max-width:calc(100vw - 48px);box-shadow:var(--aion-overlay-shadow);font-family:var(--aion-font-sans);border-radius:16px;overflow:hidden}.filemgr-dialog-title{color:var(--aion-text-primary);padding:16px 20px 8px;font-size:14px;font-weight:600}.filemgr-dialog-body{color:var(--aion-text-secondary);padding:0 20px;font-size:13px;line-height:1.6}.filemgr-dialog-actions{justify-content:flex-end;gap:8px;padding:16px 20px 20px;display:flex}.filemgr-btn{border:1px solid var(--aion-bg-3);background:var(--aion-bg-base);height:28px;color:var(--aion-text-primary);cursor:pointer;border-radius:4px;padding:0 14px;font-size:13px;transition:background-color .15s cubic-bezier(.4,0,.2,1)}.filemgr-btn:hover{background:var(--aion-bg-hover)}.filemgr-btn:active{background:var(--aion-bg-active)}.filemgr-btn:focus-visible{outline:2px solid var(--aion-primary);outline-offset:2px}.filemgr-btn-primary{background:var(--aion-primary);border-color:var(--aion-primary);color:#fff}.filemgr-btn-primary:hover{background:var(--aion-primary);opacity:.9}.filemgr-btn-primary:active{opacity:.75;filter:saturate(.9)}.filemgr-btn-danger{background:var(--aion-danger);border-color:var(--aion-danger);color:#fff}.filemgr-btn-danger:hover{opacity:.9}.filemgr-btn-danger:active{opacity:.75}.filemgr-menu{z-index:1100;background:var(--aion-bg-base);min-width:160px;box-shadow:var(--aion-overlay-shadow);border:1px solid var(--aion-bg-3);font-family:var(--aion-font-sans);border-radius:8px;padding:4px;position:fixed}.filemgr-menu-item{height:28px;color:var(--aion-text-primary);cursor:pointer;white-space:nowrap;border-radius:4px;align-items:center;padding:0 10px;font-size:13px;display:flex}.filemgr-menu-item:hover{background:var(--aion-fill-2)}.filemgr-menu-item:focus-visible{outline:2px solid var(--aion-primary);outline-offset:-2px}.filemgr-menu-item-disabled{color:var(--aion-text-disabled);cursor:default}.filemgr-menu-item-disabled:hover{background:0 0}.filemgr-menu-sep{background:var(--aion-bg-3);height:1px;margin:4px 8px}.filemgr-input{border:1px solid var(--aion-bg-3);background:var(--aion-bg-base);width:100%;height:32px;color:var(--aion-text-primary);font-size:13px;font-family:var(--aion-font-sans);box-sizing:border-box;border-radius:6px;outline:none;padding:0 10px}.filemgr-input:focus{border-color:var(--aion-primary)}.filemgr-toast{z-index:1200;background:var(--aion-bg-base);max-width:70vw;color:var(--aion-text-primary);font-size:13px;font-family:var(--aion-font-sans);box-shadow:var(--aion-overlay-shadow);border:1px solid var(--aion-bg-3);border-radius:6px;padding:8px 14px;animation:.2s cubic-bezier(.4,0,.2,1) aPVr2q_filemgr-toast-in;position:fixed;bottom:32px;left:50%;transform:translate(-50%)}@keyframes aPVr2q_filemgr-toast-in{0%{opacity:0;transform:translate(-50%)translateY(8px)}to{opacity:1;transform:translate(-50%)translateY(0)}}";
4056
+ const css$4 = ":root{--aion-bg-base:#fff;--aion-bg-1:#f9fafb;--aion-bg-2:#f2f3f5;--aion-bg-3:#e5e6eb;--aion-bg-hover:#f3f4f6;--aion-bg-active:#e5e6eb;--aion-text-primary:#000;--aion-text-secondary:#454d5f;--aion-text-tertiary:#86909c;--aion-text-disabled:#c9cdd4;--aion-primary:#165dff;--aion-success:#00b42a;--aion-warning:#ff7d00;--aion-danger:#f53f3f;--aion-brand:#7583b2;--aion-aou-1:#eff0f6;--aion-aou-2:#e5e7f0;--aion-aou-3:#d1d5e5;--aion-aou-4:#b5bcd6;--aion-aou-5:#97a0c5;--aion-aou-6:#7583b2;--aion-fill-2:#f2f3f5;--aion-fill-3:#e5e6eb;--aion-border-base:#e5e6eb;--aion-overlay-shadow:0 8px 24px #0f172a1f;--aion-font-sans:-apple-system, \"system-ui\", \"Segoe UI\", Roboto, \"Helvetica Neue\", \"PingFang SC\", \"Microsoft YaHei\", sans-serif;--aion-font-mono:ui-monospace, \"SF Mono\", SFMono-Regular, Menlo, Consolas, \"Liberation Mono\", monospace}body[data-ds-dark-theme]{--aion-bg-base:#0e0e0e;--aion-bg-1:#1a1a1a;--aion-bg-2:#262626;--aion-bg-3:#333;--aion-bg-hover:#1f1f1f;--aion-bg-active:#2d2d2d;--aion-text-primary:#fff;--aion-text-secondary:#ced3da;--aion-text-tertiary:#737373;--aion-text-disabled:#737373;--aion-primary:#4d9fff;--aion-success:#23c343;--aion-warning:#ff9a2e;--aion-danger:#f76560;--aion-brand:#a1aacb;--aion-aou-1:#2a2a2a;--aion-aou-2:#3d4150;--aion-aou-3:#525a77;--aion-aou-4:#6a749b;--aion-aou-5:#838fba;--aion-aou-6:#a1aacb;--aion-fill-2:#ffffff14;--aion-fill-3:#ffffff1f;--aion-border-base:#333;--aion-overlay-shadow:0 12px 32px #00000073;color-scheme:dark}.filemgr-root{font-family:var(--aion-font-sans);color:var(--aion-text-primary);background-color:var(--aion-bg-1);font-size:13px}.filemgr-root *,.filemgr-root :before,.filemgr-root :after{box-sizing:border-box}.filemgr-root ::-webkit-scrollbar{width:8px;height:8px}.filemgr-root ::-webkit-scrollbar-thumb{background:var(--aion-bg-3);border-radius:4px}.filemgr-root ::-webkit-scrollbar-thumb:hover{background:var(--aion-bg-4,#c9cdd4)}.filemgr-root ::-webkit-scrollbar-track{background:0 0}@media (prefers-reduced-motion:reduce){.filemgr-root *,.filemgr-root :before,.filemgr-root :after{transition:none!important;animation:none!important}}[data-dsh-frame][data-filemgr-instant]{transition:none!important}.filemgr-preview-col,.filemgr-explorer-col{background-color:var(--aion-bg-1);z-index:30;flex-direction:column;min-width:0;display:flex;overflow:hidden}.filemgr-preview-col{border-left:1px solid var(--aion-bg-3)}.filemgr-preview-col.filemgr-maximized,.filemgr-explorer-col.filemgr-maximized{z-index:60;inset:0;position:fixed!important}.filemgr-explorer-col{border-left:1px solid var(--aion-bg-3)}.filemgr-preview-col.filemgr-preview-enter{animation:.25s cubic-bezier(.4,0,.2,1) aPVr2q_filemgr-preview-enter}@keyframes aPVr2q_filemgr-preview-enter{0%{opacity:0;transform:translate(20px)}to{opacity:1;transform:translate(0)}}.filemgr-explorer-handle,.filemgr-preview-handle{touch-action:none;cursor:col-resize}.filemgr-collapse-chevron{top:calc(6px + env(aPVr2q_titlebar-area-height,0px));z-index:30;width:24px;height:24px;color:var(--aion-text-secondary);cursor:pointer;background:0 0;border:none;border-radius:4px;justify-content:center;align-items:center;transition:background-color .15s cubic-bezier(.4,0,.2,1);display:flex;position:absolute;right:8px}.filemgr-collapse-chevron:hover{background-color:var(--aion-bg-3);color:var(--aion-text-primary)}.filemgr-collapse-chevron:active{background-color:var(--aion-bg-active)}.filemgr-collapse-chevron:focus-visible{outline:2px solid var(--aion-primary);outline-offset:2px}.filemgr-overlay{z-index:1000;background:#00000059;justify-content:center;align-items:center;display:flex;position:fixed;inset:0}.filemgr-dialog{background:var(--aion-bg-base);width:400px;max-width:calc(100vw - 48px);box-shadow:var(--aion-overlay-shadow);font-family:var(--aion-font-sans);border-radius:16px;overflow:hidden}.filemgr-dialog-title{color:var(--aion-text-primary);padding:16px 20px 8px;font-size:14px;font-weight:600}.filemgr-dialog-body{color:var(--aion-text-secondary);padding:0 20px;font-size:13px;line-height:1.6}.filemgr-dialog-actions{justify-content:flex-end;gap:8px;padding:16px 20px 20px;display:flex}.filemgr-btn{border:1px solid var(--aion-bg-3);background:var(--aion-bg-base);height:28px;color:var(--aion-text-primary);cursor:pointer;border-radius:4px;padding:0 14px;font-size:13px;transition:background-color .15s cubic-bezier(.4,0,.2,1)}.filemgr-btn:hover{background:var(--aion-bg-hover)}.filemgr-btn:active{background:var(--aion-bg-active)}.filemgr-btn:focus-visible{outline:2px solid var(--aion-primary);outline-offset:2px}.filemgr-btn-primary{background:var(--aion-primary);border-color:var(--aion-primary);color:#fff}.filemgr-btn-primary:hover{background:var(--aion-primary);opacity:.9}.filemgr-btn-primary:active{opacity:.75;filter:saturate(.9)}.filemgr-btn-danger{background:var(--aion-danger);border-color:var(--aion-danger);color:#fff}.filemgr-btn-danger:hover{opacity:.9}.filemgr-btn-danger:active{opacity:.75}.filemgr-menu{z-index:1100;background:var(--aion-bg-base);min-width:160px;box-shadow:var(--aion-overlay-shadow);border:1px solid var(--aion-bg-3);font-family:var(--aion-font-sans);border-radius:8px;padding:4px;position:fixed}.filemgr-menu-item{height:28px;color:var(--aion-text-primary);cursor:pointer;white-space:nowrap;border-radius:4px;align-items:center;padding:0 10px;font-size:13px;display:flex}.filemgr-menu-item:hover{background:var(--aion-fill-2)}.filemgr-menu-item:focus-visible{outline:2px solid var(--aion-primary);outline-offset:-2px}.filemgr-menu-item-disabled{color:var(--aion-text-disabled);cursor:default}.filemgr-menu-item-disabled:hover{background:0 0}.filemgr-menu-sep{background:var(--aion-bg-3);height:1px;margin:4px 8px}.filemgr-input{border:1px solid var(--aion-bg-3);background:var(--aion-bg-base);width:100%;height:32px;color:var(--aion-text-primary);font-size:13px;font-family:var(--aion-font-sans);box-sizing:border-box;border-radius:6px;outline:none;padding:0 10px}.filemgr-input:focus{border-color:var(--aion-primary)}.filemgr-toast{z-index:1200;background:var(--aion-bg-base);max-width:70vw;color:var(--aion-text-primary);font-size:13px;font-family:var(--aion-font-sans);box-shadow:var(--aion-overlay-shadow);border:1px solid var(--aion-bg-3);border-radius:6px;padding:8px 14px;animation:.2s cubic-bezier(.4,0,.2,1) aPVr2q_filemgr-toast-in;position:fixed;bottom:32px;left:50%;transform:translate(-50%)}@keyframes aPVr2q_filemgr-toast-in{0%{opacity:0;transform:translate(-50%)translateY(8px)}to{opacity:1;transform:translate(-50%)translateY(0)}}";
4108
4057
  const tagId$4 = "@lijian-ui/dsh-file-manager/tokens.module.css";
4109
4058
  if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$4) + "]") === null) {
4110
4059
  const tag = document.createElement("style");
@@ -7339,6 +7288,75 @@ window.__ModuleLoader__.load({
7339
7288
  document.head.appendChild(tag);
7340
7289
  }
7341
7290
  //#endregion
7291
+ //#region src/client/DockItem.tsx
7292
+ const STYLE_ID = "dsh-dock-item-style";
7293
+ function ensureStyle() {
7294
+ if (typeof document === "undefined") return;
7295
+ if (document.getElementById(STYLE_ID) !== null) return;
7296
+ const tag = document.createElement("style");
7297
+ tag.id = STYLE_ID;
7298
+ tag.textContent = ".dsh-dock-item{width:32px;height:32px;border:none;border-radius:9999px;background:#000;color:#fff;cursor:pointer;position:relative;transition:transform .15s ease,background .18s ease;display:inline-flex;align-items:center;justify-content:center}.dsh-dock-item:hover{transform:scale(1.15);background:#1a1a1a}.dsh-dock-item-active{background:var(--aion-primary,#6ea0ff)}.dsh-dock-tooltip{position:absolute;top:calc(100% + 6px);left:50%;transform:translateX(-50%);padding:2px 8px;font-size:12px;line-height:1.4;white-space:nowrap;color:#fff;background:rgba(20,20,30,.9);border:1px solid rgba(255,255,255,.12);border-radius:6px;opacity:0;pointer-events:none;transition:opacity .15s}.dsh-dock-item:hover .dsh-dock-tooltip{opacity:1}";
7299
+ document.head.appendChild(tag);
7300
+ }
7301
+ ensureStyle();
7302
+ function DockItem(props) {
7303
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
7304
+ type: "button",
7305
+ className: `dsh-dock-item${props.active ? " dsh-dock-item-active" : ""}`,
7306
+ onClick: props.onClick,
7307
+ "aria-label": props.label,
7308
+ "aria-pressed": props.active,
7309
+ title: props.label,
7310
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
7311
+ className: "dsh-dock-tooltip",
7312
+ children: props.label
7313
+ }), props.children]
7314
+ });
7315
+ }
7316
+ //#endregion
7317
+ //#region src/client/FilePanelDockItem.tsx
7318
+ /**
7319
+ * FilePanelDockItem — the file-panel dock button rendered into the conversation
7320
+ * session header (the `conversation.session.header.utilities` slot).
7321
+ *
7322
+ * This plugin owns its own dock button independently: dsh-term renders its own
7323
+ * terminal button, dsh-file-manager renders this file-panel button. The two
7324
+ * are fully decoupled — install either alone and you get just its button;
7325
+ * install both and both buttons appear side by side with shared magnification.
7326
+ *
7327
+ * Clicking broadcasts `dsh-dock:toggle-filepanel` (handled in dsh-file-manager
7328
+ * index); the open state is mirrored back through `dsh-dock:filepanel-state`.
7329
+ * @module dsh-file-manager/client/FilePanelDockItem
7330
+ */
7331
+ const EV = {
7332
+ toggleFile: "dsh-dock:toggle-filepanel",
7333
+ fileState: "dsh-dock:filepanel-state"
7334
+ };
7335
+ function FilePanelDockItem() {
7336
+ const [active, setActive] = (0, react.useState)(false);
7337
+ (0, react.useEffect)(() => {
7338
+ const onState = (e) => setActive(Boolean(e.detail));
7339
+ window.addEventListener(EV.fileState, onState);
7340
+ return () => window.removeEventListener(EV.fileState, onState);
7341
+ }, []);
7342
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DockItem, {
7343
+ active,
7344
+ label: "文件面板",
7345
+ onClick: () => window.dispatchEvent(new CustomEvent(EV.toggleFile)),
7346
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
7347
+ width: "16",
7348
+ height: "16",
7349
+ viewBox: "0 0 24 24",
7350
+ fill: "none",
7351
+ stroke: "currentColor",
7352
+ strokeWidth: "2",
7353
+ strokeLinecap: "round",
7354
+ strokeLinejoin: "round",
7355
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", { d: "m6 14 1.45-2.9a2 2 0 0 1 1.79-1.1h11.76a2 2 0 0 1 1.94 1.5l1.55 6a2 2 0 0 1-1.94 2.5H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h3.5a2 2 0 0 1 1.59.79l.91 1.21a2 2 0 0 0 1.59.79H18a2 2 0 0 1 2 2v2" })
7356
+ })
7357
+ });
7358
+ }
7359
+ //#endregion
7342
7360
  //#region src/client/index.ts
7343
7361
  /**
7344
7362
  * FileManager right-panel system — browser half: mounts the explorer and preview
@@ -7365,6 +7383,14 @@ window.__ModuleLoader__.load({
7365
7383
  const panelApi = new PanelApi();
7366
7384
  /** Apply the browser half. */
7367
7385
  function apply(ctx) {
7386
+ ctx.inject(["slots"], (scope) => {
7387
+ scope.slots.inject("conversation.session.header.utilities", () => scope.slots.register({
7388
+ name: "conversation.session.header.utilities",
7389
+ id: "filemgr-dock-item",
7390
+ order: -2,
7391
+ inject: () => ({})
7392
+ }, FilePanelDockItem));
7393
+ });
7368
7394
  ctx.effect(() => ctx.locale.register(NS, dictionaries), "dsh-filemgr: dictionaries");
7369
7395
  ctx.effect(() => registerFileReferenceSource(ctx), "dsh-filemgr: file reference source");
7370
7396
  ctx.inject([