@civilization/dsh-workspace-files 0.3.2 → 0.3.3

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
@@ -4,7 +4,30 @@ window.__ModuleLoader__.load({
4
4
  var module = { exports: {} };
5
5
  var exports = module.exports;
6
6
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
7
+ //#region \0rolldown/runtime.js
8
+ var __create = Object.create;
9
+ var __defProp = Object.defineProperty;
10
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
11
+ var __getOwnPropNames = Object.getOwnPropertyNames;
12
+ var __getProtoOf = Object.getPrototypeOf;
13
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
14
+ var __copyProps = (to, from, except, desc) => {
15
+ if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
16
+ key = keys[i];
17
+ if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
18
+ get: ((k) => from[k]).bind(null, key),
19
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
20
+ });
21
+ }
22
+ return to;
23
+ };
24
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule || !__hasOwnProp.call(mod, "default") ? __defProp(target, "default", {
25
+ value: mod,
26
+ enumerable: true
27
+ }) : target, mod));
28
+ //#endregion
7
29
  let react = require("react");
30
+ react = __toESM(react, 1);
8
31
  let react_jsx_runtime = require("react/jsx-runtime");
9
32
  //#region src/client/icons.tsx
10
33
  function IconFolder({ size = 15, open = false }) {
@@ -204,6 +227,30 @@ window.__ModuleLoader__.load({
204
227
  } else if (ext === "yml" || ext === "yaml") {
205
228
  color = "#cb171e";
206
229
  badge = "Y";
230
+ } else if (ext === "rs") {
231
+ color = "#dea584";
232
+ badge = "RS";
233
+ } else if (ext === "go") {
234
+ color = "#00add8";
235
+ badge = "GO";
236
+ } else if (ext === "vue") {
237
+ color = "#41b883";
238
+ badge = "V";
239
+ } else if (ext === "svelte") {
240
+ color = "#ff3e00";
241
+ badge = "S";
242
+ } else if (ext === "toml") {
243
+ color = "#9c4121";
244
+ badge = "T";
245
+ } else if (ext === "sql") {
246
+ color = "#e38c00";
247
+ badge = "SQL";
248
+ } else if (ext === "sh" || ext === "bash" || ext === "zsh" || ext === "ps1" || ext === "bat" || ext === "cmd") {
249
+ color = "#4eaa25";
250
+ badge = ">_";
251
+ } else if (ext === "lock") {
252
+ color = "var(--dsw-alias-label-tertiary, #8c9ba5)";
253
+ badge = "🔒";
207
254
  }
208
255
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
209
256
  style: {
@@ -247,22 +294,23 @@ window.__ModuleLoader__.load({
247
294
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", { d: "M2 3h4v4H2zM10 9h4v4h-4zM4 7v6h6" })
248
295
  });
249
296
  }
250
- function IconChevronDown({ size = 14 }) {
297
+ function IconChevronRight({ size = 11, className, style }) {
251
298
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
252
299
  width: size,
253
300
  height: size,
254
301
  viewBox: "0 0 16 16",
255
- fill: "none",
256
- stroke: "currentColor",
257
- strokeWidth: "1.5",
258
- strokeLinecap: "round",
259
- strokeLinejoin: "round",
302
+ fill: "currentColor",
303
+ className,
260
304
  style: {
261
305
  display: "inline-block",
262
306
  verticalAlign: "middle",
263
- flexShrink: 0
307
+ flexShrink: 0,
308
+ ...style
264
309
  },
265
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("polyline", { points: "4 6 8 10 12 6" })
310
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
311
+ fillRule: "evenodd",
312
+ d: "M6.22 3.22a.75.75 0 0 1 1.06 0l4.25 4.25a.75.75 0 0 1 0 1.06l-4.25 4.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042L9.94 8 6.22 4.28a.75.75 0 0 1 0-1.06z"
313
+ })
266
314
  });
267
315
  }
268
316
  function IconExplorer({ size = 12 }) {
@@ -411,16 +459,16 @@ window.__ModuleLoader__.load({
411
459
  style.id = id;
412
460
  style.textContent = `
413
461
  .dsh-wf-card {
414
- border: 1px solid var(--dsw-alias-border-l2, #e5e7eb);
415
- background: var(--dsw-alias-bg-layer-3, #fff);
416
- border-radius: 12px;
462
+ border: 0.5px solid var(--dsw-alias-border-l1);
463
+ background: var(--dsw-alias-fill-base, #ffffff);
464
+ border-radius: var(--dsw-radius-md, 8px);
417
465
  list-style: none;
418
- transition: border-color .16s, background .16s;
466
+ transition: border-color 0.16s, background 0.16s;
419
467
  box-sizing: border-box;
420
468
  }
421
469
  .dsh-wf-card-open {
422
- background: var(--dsw-alias-bg-layer-2, #f7f8fa);
423
- border-color: var(--dsw-alias-label-dimmed, #c8ccd4);
470
+ background: var(--dsw-alias-fill-base, #ffffff);
471
+ border-color: var(--dsw-alias-state-business-primary);
424
472
  }
425
473
  .dsh-wf-header {
426
474
  -webkit-appearance: none;
@@ -430,24 +478,24 @@ window.__ModuleLoader__.load({
430
478
  color: inherit;
431
479
  text-align: left;
432
480
  cursor: pointer;
433
- background: 0 0;
481
+ background: transparent;
434
482
  border: 0;
435
- border-radius: 12px;
483
+ border-radius: var(--dsw-radius-md, 8px);
436
484
  align-items: center;
437
485
  gap: 12px;
438
- padding: 14px 16px;
486
+ padding: 12px 14px;
439
487
  display: flex;
440
488
  }
441
489
  .dsh-wf-head-text {
442
490
  flex-direction: column;
443
491
  flex: 1;
444
- gap: 4px;
492
+ gap: 3px;
445
493
  min-width: 0;
446
494
  display: flex;
447
495
  }
448
496
  .dsh-wf-name {
449
- color: var(--dsw-alias-label-primary, #1f2328);
450
- font-size: 15px;
497
+ color: var(--dsw-alias-label-primary);
498
+ font-size: 14px;
451
499
  font-weight: 600;
452
500
  line-height: 1.4;
453
501
  display: flex;
@@ -455,38 +503,38 @@ window.__ModuleLoader__.load({
455
503
  gap: 8px;
456
504
  }
457
505
  .dsh-wf-version {
458
- font-size: 12px;
506
+ font-size: 11px;
459
507
  font-weight: 400;
460
- color: var(--dsw-alias-label-tertiary, #8b93a1);
508
+ color: var(--dsw-alias-label-tertiary);
461
509
  }
462
510
  .dsh-wf-desc {
463
- color: var(--dsw-alias-label-tertiary, #8b93a1);
464
- font-size: 13px;
511
+ color: var(--dsw-alias-label-secondary);
512
+ font-size: 12px;
465
513
  line-height: 1.5;
466
514
  }
467
515
  .dsh-wf-chevron {
468
- color: var(--dsw-alias-label-tertiary, #8b93a1);
516
+ color: var(--dsw-alias-label-tertiary);
469
517
  flex: none;
470
- transition: transform .16s ease-in-out;
518
+ transition: transform 0.18s cubic-bezier(0.16, 1, 0.3, 1);
471
519
  display: inline-flex;
472
520
  }
473
521
  .dsh-wf-chevron-open {
474
522
  transform: rotate(180deg);
475
523
  }
476
524
  .dsh-wf-body {
477
- border-top: 1px solid var(--dsw-alias-border-l2, #e5e7eb);
478
- margin: 0 16px;
525
+ border-top: 0.5px solid var(--dsw-alias-border-l2);
526
+ margin: 0 14px;
479
527
  padding: 8px 0 12px;
480
528
  }
481
529
  .dsh-wf-row {
482
530
  align-items: center;
483
531
  gap: 16px;
484
- padding: 12px 0;
532
+ padding: 10px 0;
485
533
  display: flex;
486
534
  justify-content: space-between;
487
535
  }
488
536
  .dsh-wf-row + .dsh-wf-row {
489
- border-top: 1px solid var(--dsw-alias-border-l2, rgba(118, 137, 166, 0.12));
537
+ border-top: 0.5px solid var(--dsw-alias-border-l2);
490
538
  }
491
539
  .dsh-wf-label-box {
492
540
  flex-direction: column;
@@ -496,14 +544,14 @@ window.__ModuleLoader__.load({
496
544
  display: flex;
497
545
  }
498
546
  .dsh-wf-label {
499
- font-size: 13.5px;
547
+ font-size: 13px;
500
548
  font-weight: 550;
501
- color: var(--dsw-alias-label-primary, #1f2328);
549
+ color: var(--dsw-alias-label-primary);
502
550
  }
503
551
  .dsh-wf-hint {
504
- color: var(--dsw-alias-label-tertiary, #8b93a1);
505
- font-size: 12px;
506
- line-height: 18px;
552
+ color: var(--dsw-alias-label-tertiary);
553
+ font-size: 11.5px;
554
+ line-height: 16px;
507
555
  }
508
556
  .dsh-wf-ctrl {
509
557
  flex-shrink: 0;
@@ -512,56 +560,56 @@ window.__ModuleLoader__.load({
512
560
  gap: 8px;
513
561
  }
514
562
  .dsh-wf-seg {
515
- border: 1px solid var(--dsw-alias-border-l2, #e5e7eb);
516
- border-radius: 8px;
563
+ border: 0.5px solid var(--dsw-alias-border-l1);
564
+ border-radius: var(--dsw-radius-sm, 6px);
517
565
  gap: 2px;
518
566
  padding: 2px;
519
567
  display: inline-flex;
520
- background: var(--dsw-alias-bg-layer-1, rgba(255, 255, 255, 0.05));
568
+ background: var(--dsw-alias-fill-base, #ffffff);
521
569
  }
522
570
  .dsh-wf-seg-btn {
523
571
  font: inherit;
524
- color: var(--dsw-alias-label-secondary, #6b7280);
572
+ color: var(--dsw-alias-label-secondary);
525
573
  cursor: pointer;
526
- background: 0 0;
574
+ background: transparent;
527
575
  border: none;
528
- border-radius: 6px;
529
- padding: 4px 10px;
530
- font-size: 12px;
531
- line-height: 18px;
532
- transition: all 0.15s;
576
+ border-radius: 4px;
577
+ padding: 3px 8px;
578
+ font-size: 11.5px;
579
+ transition: all 0.15s cubic-bezier(0.16, 1, 0.3, 1);
533
580
  }
534
581
  .dsh-wf-seg-btn:hover {
535
- color: var(--dsw-alias-label-primary, #1f2328);
582
+ color: var(--dsw-alias-label-primary);
583
+ background: var(--dsw-alias-interactive-bg-hover);
536
584
  }
537
585
  .dsh-wf-seg-active {
538
- background: var(--dsw-alias-bg-layer-3, #eef0f4);
539
- color: var(--dsw-alias-brand-primary, #4f6ef7);
586
+ background: color-mix(in srgb, var(--dsw-alias-state-business-primary) 12%, transparent);
587
+ color: var(--dsw-alias-state-business-primary);
540
588
  font-weight: 600;
541
- box-shadow: 0 1px 2px rgba(0,0,0,0.05);
542
589
  }
543
590
  .dsh-wf-input {
544
591
  box-sizing: border-box;
545
- border: 1px solid var(--dsw-alias-border-l2, #d1d5db);
546
- background: var(--dsw-alias-bg-layer-3, #fff);
547
- width: 64px;
592
+ border: 0.5px solid var(--dsw-alias-border-l1);
593
+ background: var(--dsw-alias-fill-base, #ffffff);
594
+ width: 58px;
548
595
  text-align: center;
549
- color: var(--dsw-alias-label-primary, #1f2328);
596
+ color: var(--dsw-alias-label-primary);
550
597
  font: inherit;
551
- border-radius: 7px;
552
- padding: 4px 6px;
553
- font-size: 12.5px;
554
- line-height: 18px;
598
+ border-radius: 6px;
599
+ padding: 3px 6px;
600
+ font-size: 12px;
601
+ outline: none;
602
+ transition: border-color 0.15s, box-shadow 0.15s;
555
603
  }
556
604
  .dsh-wf-input:focus {
557
- border-color: var(--dsw-alias-brand-primary, #4f6ef7);
558
- outline: 2px solid color-mix(in srgb, var(--dsw-alias-brand-primary, #4f6ef7) 18%, transparent);
605
+ border-color: var(--dsw-alias-state-business-primary);
606
+ box-shadow: 0 0 0 2px color-mix(in srgb, var(--dsw-alias-state-business-primary) 18%, transparent);
559
607
  }
560
608
  .dsh-wf-toggle {
561
609
  position: relative;
562
610
  display: inline-block;
563
- width: 40px;
564
- height: 22px;
611
+ width: 36px;
612
+ height: 20px;
565
613
  cursor: pointer;
566
614
  }
567
615
  .dsh-wf-toggle input {
@@ -573,55 +621,55 @@ window.__ModuleLoader__.load({
573
621
  .dsh-wf-toggle-track {
574
622
  position: absolute;
575
623
  top: 0; left: 0; right: 0; bottom: 0;
576
- background-color: var(--dsw-alias-border-l2, #ccc);
577
- transition: .2s cubic-bezier(.4, 0, .2, 1);
578
- border-radius: 22px;
624
+ background-color: var(--dsw-alias-border-l1);
625
+ transition: 0.18s cubic-bezier(0.16, 1, 0.3, 1);
626
+ border-radius: 20px;
579
627
  }
580
628
  .dsh-wf-toggle input:checked + .dsh-wf-toggle-track {
581
- background-color: var(--dsw-alias-brand-primary, #4f6ef7);
629
+ background-color: var(--dsw-alias-state-business-primary);
582
630
  }
583
631
  .dsh-wf-toggle-thumb {
584
632
  position: absolute;
585
- height: 16px;
586
- width: 16px;
633
+ height: 14px;
634
+ width: 14px;
587
635
  left: 3px;
588
636
  bottom: 3px;
589
- background-color: white;
590
- transition: .2s cubic-bezier(.4, 0, .2, 1);
637
+ background-color: #ffffff;
638
+ transition: 0.18s cubic-bezier(0.16, 1, 0.3, 1);
591
639
  border-radius: 50%;
592
- box-shadow: 0 1px 3px rgba(0,0,0,0.2);
640
+ box-shadow: 0 1px 2px rgba(0,0,0,0.18);
593
641
  }
594
642
  .dsh-wf-toggle input:checked + .dsh-wf-toggle-track .dsh-wf-toggle-thumb {
595
- transform: translateX(18px);
643
+ transform: translateX(16px);
596
644
  }
597
645
  .dsh-wf-footer {
598
- margin-top: 8px;
599
- padding-top: 10px;
600
- border-top: 1px solid var(--dsw-alias-border-l2, rgba(118, 137, 166, 0.12));
646
+ margin-top: 6px;
647
+ padding-top: 8px;
648
+ border-top: 0.5px solid var(--dsw-alias-border-l2);
601
649
  display: flex;
602
650
  align-items: center;
603
651
  justify-content: space-between;
604
652
  }
605
653
  .dsh-wf-saved-hint {
606
- font-size: 11.5px;
607
- color: var(--dsw-alias-state-success-primary, #10b981);
654
+ font-size: 11px;
655
+ color: var(--dsw-alias-state-business-primary);
608
656
  display: flex;
609
657
  align-items: center;
610
658
  gap: 4px;
611
659
  }
612
660
  .dsh-wf-btn-reset {
613
661
  background: transparent;
614
- border: 1px solid var(--dsw-alias-border-l2, #e5e7eb);
615
- border-radius: 6px;
616
- padding: 3px 10px;
617
- font-size: 12px;
618
- color: var(--dsw-alias-label-secondary, #6b7280);
662
+ border: 0.5px solid var(--dsw-alias-border-l1);
663
+ border-radius: 4px;
664
+ padding: 3px 8px;
665
+ font-size: 11px;
666
+ color: var(--dsw-alias-label-secondary);
619
667
  cursor: pointer;
620
- transition: all 0.15s;
668
+ transition: all 0.12s;
621
669
  }
622
670
  .dsh-wf-btn-reset:hover {
623
- background: var(--dsw-alias-bg-layer-2, rgba(255,255,255,0.08));
624
- color: var(--dsw-alias-label-primary, #1f2328);
671
+ background: var(--dsw-alias-interactive-bg-hover);
672
+ color: var(--dsw-alias-label-primary);
625
673
  }
626
674
  `;
627
675
  document.head.appendChild(style);
@@ -660,32 +708,39 @@ window.__ModuleLoader__.load({
660
708
  };
661
709
  setConfig(def);
662
710
  saveWorkspaceFilesConfig(def);
663
- setSavedTick(true);
664
- setTimeout(() => setSavedTick(false), 2e3);
665
711
  };
666
712
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
667
- className: open ? "dsh-wf-card dsh-wf-card-open" : "dsh-wf-card",
713
+ className: `dsh-wf-card ${open ? "dsh-wf-card-open" : ""}`,
668
714
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
669
715
  type: "button",
670
716
  className: "dsh-wf-header",
671
- "aria-expanded": open,
672
717
  onClick: () => setOpen(!open),
673
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
674
- className: "dsh-wf-head-text",
675
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
676
- className: "dsh-wf-name",
677
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: "工作区文件" }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
678
- className: "dsh-wf-version",
679
- children: ["v", "0.3.2"]
718
+ children: [
719
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FolderGuideGlyph, { size: 22 }),
720
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
721
+ className: "dsh-wf-head-text",
722
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
723
+ className: "dsh-wf-name",
724
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: "工作区文件" }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
725
+ className: "dsh-wf-version",
726
+ children: ["v", "0.3.3"]
727
+ })]
728
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
729
+ className: "dsh-wf-desc",
730
+ children: "全量项目文件树浏览、即时检索与 @-mention 会话一键引用。"
680
731
  })]
681
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
682
- className: "dsh-wf-desc",
683
- children: "浏览与检索工作区文件树,支持递归目录扫描与一键引用。"
684
- })]
685
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
686
- className: open ? "dsh-wf-chevron dsh-wf-chevron-open" : "dsh-wf-chevron",
687
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconChevronDown, { size: 14 })
688
- })]
732
+ }),
733
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
734
+ className: `dsh-wf-chevron ${open ? "dsh-wf-chevron-open" : ""}`,
735
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconChevronRight, {
736
+ size: 14,
737
+ style: {
738
+ transform: open ? "rotate(90deg)" : "rotate(0deg)",
739
+ transition: "transform 0.16s"
740
+ }
741
+ })
742
+ })
743
+ ]
689
744
  }), open && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
690
745
  className: "dsh-wf-body",
691
746
  children: [
@@ -693,12 +748,12 @@ window.__ModuleLoader__.load({
693
748
  className: "dsh-wf-row",
694
749
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
695
750
  className: "dsh-wf-label-box",
696
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
751
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
697
752
  className: "dsh-wf-label",
698
- children: "目录扫描最大深度"
699
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
753
+ children: "扫描最大深度 (层级)"
754
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
700
755
  className: "dsh-wf-hint",
701
- children: "工作区递归扫描的最大目录层级(默认 16,范围 1~100)。若工程目录较深可适当调大。"
756
+ children: "控制文件树深入遍历的最大文件夹嵌套层级,防止庞大项目深度过大产生卡顿。"
702
757
  })]
703
758
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
704
759
  className: "dsh-wf-ctrl",
@@ -707,22 +762,22 @@ window.__ModuleLoader__.load({
707
762
  children: [
708
763
  8,
709
764
  16,
710
- 32,
711
- 64
712
- ].map((d) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
765
+ 24,
766
+ 32
767
+ ].map((d) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
713
768
  type: "button",
714
- className: config.maxDepth === d ? "dsh-wf-seg-btn dsh-wf-seg-active" : "dsh-wf-seg-btn",
769
+ className: `dsh-wf-seg-btn ${config.maxDepth === d ? "dsh-wf-seg-active" : ""}`,
715
770
  onClick: () => handleDepthSelect(d),
716
- children: d
771
+ children: [d, " 层"]
717
772
  }, d))
718
773
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
719
774
  type: "number",
720
- min: "1",
721
- max: "100",
775
+ min: 1,
776
+ max: 100,
722
777
  className: "dsh-wf-input",
723
778
  value: config.maxDepth,
724
779
  onChange: handleDepthInput,
725
- title: "自定义深度 (1-100)"
780
+ title: "手动输入层级深度 (1-100)"
726
781
  })]
727
782
  })]
728
783
  }),
@@ -730,12 +785,12 @@ window.__ModuleLoader__.load({
730
785
  className: "dsh-wf-row",
731
786
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
732
787
  className: "dsh-wf-label-box",
733
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
788
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
734
789
  className: "dsh-wf-label",
735
- children: "默认显示隐藏文件"
736
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
790
+ children: "显示以点开头的隐藏文件"
791
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
737
792
  className: "dsh-wf-hint",
738
- children: "打开文件树时是否默认展示以点开头的隐藏文件或文件夹(如 .gitignore, .env 等)。"
793
+ children: "开启后,文件树中将展现如 .env, .editorconfig 等以点开头的配置文件(.git 等缓存黑名单除外)。"
739
794
  })]
740
795
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
741
796
  className: "dsh-wf-ctrl",
@@ -754,15 +809,9 @@ window.__ModuleLoader__.load({
754
809
  }),
755
810
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
756
811
  className: "dsh-wf-footer",
757
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { children: savedTick ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
812
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { children: savedTick && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
758
813
  className: "dsh-wf-saved-hint",
759
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconCheck, { size: 12 }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: "已保存设置" })]
760
- }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
761
- style: {
762
- fontSize: 11,
763
- color: "var(--dsw-alias-label-tertiary, #8b93a1)"
764
- },
765
- children: "设置改动即时生效并同步至工作区文件树"
814
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconCheck, { size: 12 }), "配置已自动保存并实时同步"]
766
815
  }) }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
767
816
  type: "button",
768
817
  className: "dsh-wf-btn-reset",
@@ -774,21 +823,85 @@ window.__ModuleLoader__.load({
774
823
  })]
775
824
  });
776
825
  }
826
+ /**
827
+ * 线性遍历计算可视行。未展开目录的子节点绝不遍历,彻底解决 DOM 节点爆炸问题。
828
+ */
829
+ function flattenVisibleTree(items, expandedPaths, depth = 0, out = []) {
830
+ for (const it of items) {
831
+ const isDir = it.isDirectory;
832
+ const hasChildren = isDir && Array.isArray(it.children) && it.children.length > 0;
833
+ const isExpanded = isDir && expandedPaths.has(it.path);
834
+ const childCount = hasChildren ? it.children.length : 0;
835
+ out.push({
836
+ id: it.path,
837
+ name: it.name,
838
+ path: it.path,
839
+ isDirectory: isDir,
840
+ depth,
841
+ isExpanded,
842
+ hasChildren,
843
+ childCount,
844
+ size: it.size,
845
+ item: it
846
+ });
847
+ if (isDir && isExpanded && hasChildren) flattenVisibleTree(it.children, expandedPaths, depth + 1, out);
848
+ }
849
+ return out;
850
+ }
851
+ /**
852
+ * 树形过滤模式:仅保留包含匹配项的分支并保持展开
853
+ */
854
+ function filterTreeWithAutoExpand(nodes, q) {
855
+ const autoExpand = /* @__PURE__ */ new Set();
856
+ function filterNode(node) {
857
+ const matchSelf = node.name.toLowerCase().includes(q) || node.path.toLowerCase().includes(q);
858
+ if (node.isDirectory) {
859
+ const children = [];
860
+ for (const child of node.children || []) {
861
+ const c = filterNode(child);
862
+ if (c) children.push(c);
863
+ }
864
+ if (matchSelf || children.length > 0) {
865
+ autoExpand.add(node.path);
866
+ return {
867
+ ...node,
868
+ children
869
+ };
870
+ }
871
+ return null;
872
+ }
873
+ return matchSelf ? node : null;
874
+ }
875
+ const result = [];
876
+ for (const it of nodes) {
877
+ const f = filterNode(it);
878
+ if (f) result.push(f);
879
+ }
880
+ return {
881
+ filteredItems: result,
882
+ autoExpandPaths: autoExpand
883
+ };
884
+ }
777
885
  function WorkspaceFilesView({ sessionId, cwd, onOpenFile }) {
778
886
  const [data, setData] = (0, react.useState)(null);
779
887
  const [loading, setLoading] = (0, react.useState)(true);
780
888
  const [error, setError] = (0, react.useState)(null);
781
- const [query, setQuery] = (0, react.useState)("");
889
+ const [inputQuery, setInputQuery] = (0, react.useState)("");
782
890
  const [toast, setToast] = (0, react.useState)(null);
783
891
  const [expandedPaths, setExpandedPaths] = (0, react.useState)(() => /* @__PURE__ */ new Set());
784
892
  const [activeConfig, setActiveConfig] = (0, react.useState)(() => loadWorkspaceFilesConfig());
785
893
  const [showHidden, setShowHidden] = (0, react.useState)(() => loadWorkspaceFilesConfig().showHidden);
894
+ const [searchViewMode, setSearchViewMode] = (0, react.useState)("flat");
895
+ const deferredQuery = (0, react.useDeferredValue)(inputQuery.trim().toLowerCase());
786
896
  const toastTimer = (0, react.useRef)(null);
787
897
  const showToastMsg = (0, react.useCallback)((msg) => {
788
898
  setToast(msg);
789
899
  if (toastTimer.current) window.clearTimeout(toastTimer.current);
790
900
  toastTimer.current = window.setTimeout(() => setToast(null), 2e3);
791
901
  }, []);
902
+ (0, react.useEffect)(() => {
903
+ ensureFilesStyle();
904
+ }, []);
792
905
  (0, react.useEffect)(() => {
793
906
  const handleCfgChange = (e) => {
794
907
  if (e.detail) {
@@ -831,7 +944,7 @@ window.__ModuleLoader__.load({
831
944
  (0, react.useEffect)(() => {
832
945
  loadTree();
833
946
  }, [loadTree]);
834
- const handleToggleExpand = (path) => {
947
+ const handleToggleExpand = (0, react.useCallback)((path) => {
835
948
  setExpandedPaths((prev) => {
836
949
  const next = new Set(prev);
837
950
  if (next.has(path)) next.delete(path);
@@ -839,8 +952,8 @@ window.__ModuleLoader__.load({
839
952
  saveStoredExpandedPaths(data?.root || cwd, next);
840
953
  return next;
841
954
  });
842
- };
843
- const handleExpandAll = () => {
955
+ }, [data?.root, cwd]);
956
+ const handleExpandAll = (0, react.useCallback)(() => {
844
957
  if (!data) return;
845
958
  const all = /* @__PURE__ */ new Set();
846
959
  function collect(items) {
@@ -852,13 +965,13 @@ window.__ModuleLoader__.load({
852
965
  collect(data.items);
853
966
  setExpandedPaths(all);
854
967
  saveStoredExpandedPaths(data.root || cwd, all);
855
- };
856
- const handleCollapseAll = () => {
968
+ }, [data, cwd]);
969
+ const handleCollapseAll = (0, react.useCallback)(() => {
857
970
  const empty = /* @__PURE__ */ new Set();
858
971
  setExpandedPaths(empty);
859
972
  saveStoredExpandedPaths(data?.root || cwd, empty);
860
- };
861
- const handleJumpToFolderInTree = (dirPath) => {
973
+ }, [data?.root, cwd]);
974
+ const handleJumpToFolderInTree = (0, react.useCallback)((dirPath) => {
862
975
  const parts = dirPath.split("/");
863
976
  const toExpand = [];
864
977
  let acc = "";
@@ -873,7 +986,7 @@ window.__ModuleLoader__.load({
873
986
  saveStoredExpandedPaths(data?.root || cwd, next);
874
987
  return next;
875
988
  });
876
- setQuery("");
989
+ setInputQuery("");
877
990
  showToastMsg(`已定位并展开目录: ${dirPath}/`);
878
991
  setTimeout(() => {
879
992
  try {
@@ -884,14 +997,18 @@ window.__ModuleLoader__.load({
884
997
  });
885
998
  } catch {}
886
999
  }, 60);
887
- };
888
- const handleCopyPath = (e, path) => {
1000
+ }, [
1001
+ data?.root,
1002
+ cwd,
1003
+ showToastMsg
1004
+ ]);
1005
+ const handleCopyPath = (0, react.useCallback)((e, path) => {
889
1006
  e.stopPropagation();
890
1007
  navigator.clipboard.writeText(path).then(() => {
891
1008
  showToastMsg(`已复制路径: ${path}`);
892
1009
  });
893
- };
894
- const handleMention = (e, itemOrPath) => {
1010
+ }, [showToastMsg]);
1011
+ const handleMention = (0, react.useCallback)((e, itemOrPath) => {
895
1012
  e.stopPropagation();
896
1013
  const itemObj = typeof itemOrPath === "string" ? {
897
1014
  name: itemOrPath.split("/").pop() || itemOrPath,
@@ -902,21 +1019,17 @@ window.__ModuleLoader__.load({
902
1019
  let inserted = false;
903
1020
  try {
904
1021
  inserted = tryInsertNativeReferenceChip(globalCtx, sessionId, itemObj);
905
- } catch (err) {
906
- console.warn("[dsh-workspace-files] 原生 Chip 插入失败:", err);
907
- }
1022
+ } catch {}
908
1023
  if (!inserted) try {
909
1024
  inserted = insertMentionToComposer(mentionText);
910
- } catch (err) {
911
- console.warn("[dsh-workspace-files] 降级纯文本插入失败:", err);
912
- }
1025
+ } catch {}
913
1026
  const displayName = itemObj.isDirectory ? `${itemObj.name}/` : itemObj.name;
914
1027
  navigator.clipboard.writeText(mentionText.trim()).then(() => {
915
1028
  if (inserted) showToastMsg(`已引用${itemObj.isDirectory ? "目录" : "文件"}: ${displayName}`);
916
1029
  else showToastMsg(`已复制引用: ${mentionText.trim()}`);
917
1030
  });
918
- };
919
- const handleRevealInExplorer = (e, item) => {
1031
+ }, [sessionId, showToastMsg]);
1032
+ const handleRevealInExplorer = (0, react.useCallback)((e, item) => {
920
1033
  e.stopPropagation();
921
1034
  fetch("/dsh-workspace-files/api/files.open", {
922
1035
  method: "POST",
@@ -934,8 +1047,12 @@ window.__ModuleLoader__.load({
934
1047
  }).catch((err) => {
935
1048
  showToastMsg(`请求失败: ${err?.message || String(err)}`);
936
1049
  });
937
- };
938
- const handleOpenDefaultApp = (e, item) => {
1050
+ }, [
1051
+ sessionId,
1052
+ cwd,
1053
+ showToastMsg
1054
+ ]);
1055
+ const handleOpenDefaultApp = (0, react.useCallback)((e, item) => {
939
1056
  e.stopPropagation();
940
1057
  fetch("/dsh-workspace-files/api/files.open", {
941
1058
  method: "POST",
@@ -953,76 +1070,51 @@ window.__ModuleLoader__.load({
953
1070
  }).catch((err) => {
954
1071
  showToastMsg(`请求失败: ${err?.message || String(err)}`);
955
1072
  });
956
- };
957
- const [searchViewMode, setSearchViewMode] = (0, react.useState)("flat");
958
- const [searchExpandedPaths, setSearchExpandedPaths] = (0, react.useState)(() => /* @__PURE__ */ new Set());
959
- const { filteredTreeItems, flatSearchResults } = (0, react.useMemo)(() => {
960
- if (!data) return {
961
- filteredTreeItems: [],
962
- flatSearchResults: []
963
- };
964
- const q = query.trim().toLowerCase();
965
- if (!q) return {
966
- filteredTreeItems: data.items,
967
- flatSearchResults: []
968
- };
969
- const flat = [];
970
- function traverseFlat(items, parentDir) {
1073
+ }, [
1074
+ sessionId,
1075
+ cwd,
1076
+ showToastMsg
1077
+ ]);
1078
+ const isSearchActive = Boolean(deferredQuery);
1079
+ const flatSearchResults = (0, react.useMemo)(() => {
1080
+ if (!data || !isSearchActive) return [];
1081
+ const results = [];
1082
+ function traverse(items, parentDir) {
971
1083
  for (const it of items) {
972
- if (it.name.toLowerCase().includes(q) || it.path.toLowerCase().includes(q)) flat.push({
973
- item: it,
974
- parentDir
975
- });
976
- if (it.isDirectory && it.children) traverseFlat(it.children, it.path);
977
- }
978
- }
979
- traverseFlat(data.items, "");
980
- function filterNode(node) {
981
- const selfMatch = node.name.toLowerCase().includes(q) || node.path.toLowerCase().includes(q);
982
- if (node.isDirectory) {
983
- const filteredChildren = [];
984
- for (const child of node.children || []) {
985
- const matchedChild = filterNode(child);
986
- if (matchedChild) filteredChildren.push(matchedChild);
1084
+ if (it.name.toLowerCase().includes(deferredQuery) || it.path.toLowerCase().includes(deferredQuery)) {
1085
+ results.push({
1086
+ item: it,
1087
+ parentDir
1088
+ });
1089
+ if (results.length >= 300) return;
1090
+ }
1091
+ if (it.isDirectory && it.children) {
1092
+ traverse(it.children, it.path);
1093
+ if (results.length >= 300) return;
987
1094
  }
988
- if (selfMatch || filteredChildren.length > 0) return {
989
- ...node,
990
- children: filteredChildren
991
- };
992
- return null;
993
- }
994
- return selfMatch ? node : null;
995
- }
996
- const tree = [];
997
- for (const rootNode of data.items) {
998
- const matched = filterNode(rootNode);
999
- if (matched) tree.push(matched);
1000
- }
1001
- return {
1002
- filteredTreeItems: tree,
1003
- flatSearchResults: flat
1004
- };
1005
- }, [data, query]);
1006
- (0, react.useEffect)(() => {
1007
- if (!query.trim() || !data) return;
1008
- const q = query.trim().toLowerCase();
1009
- const autoExpand = /* @__PURE__ */ new Set();
1010
- function collect(items) {
1011
- for (const it of items) if (it.isDirectory) {
1012
- const selfMatch = it.name.toLowerCase().includes(q) || it.path.toLowerCase().includes(q);
1013
- const childMatch = it.children?.some((c) => c.name.toLowerCase().includes(q) || c.path.toLowerCase().includes(q));
1014
- if (selfMatch || childMatch) autoExpand.add(it.path);
1015
- if (it.children) collect(it.children);
1016
1095
  }
1017
1096
  }
1018
- collect(data.items);
1019
- setSearchExpandedPaths(autoExpand);
1020
- }, [query, data]);
1021
- const isSearchActive = Boolean(query.trim());
1097
+ traverse(data.items, "");
1098
+ return results;
1099
+ }, [
1100
+ data,
1101
+ deferredQuery,
1102
+ isSearchActive
1103
+ ]);
1104
+ const visibleFlatRows = (0, react.useMemo)(() => {
1105
+ if (!data) return [];
1106
+ if (!isSearchActive) return flattenVisibleTree(data.items, expandedPaths);
1107
+ const { filteredItems, autoExpandPaths } = filterTreeWithAutoExpand(data.items, deferredQuery);
1108
+ return flattenVisibleTree(filteredItems, autoExpandPaths);
1109
+ }, [
1110
+ data,
1111
+ isSearchActive,
1112
+ deferredQuery,
1113
+ expandedPaths
1114
+ ]);
1022
1115
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1023
1116
  className: "dsh-files-root",
1024
1117
  children: [
1025
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(GlobalFilesStyle, {}),
1026
1118
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("header", {
1027
1119
  className: "dsh-files-header",
1028
1120
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
@@ -1031,7 +1123,7 @@ window.__ModuleLoader__.load({
1031
1123
  className: "dsh-files-title-row",
1032
1124
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1033
1125
  className: "dsh-files-title",
1034
- children: "文件"
1126
+ children: "工作区文件"
1035
1127
  }), data && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
1036
1128
  className: "dsh-files-stats-badge",
1037
1129
  children: [
@@ -1060,18 +1152,18 @@ window.__ModuleLoader__.load({
1060
1152
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
1061
1153
  type: "text",
1062
1154
  className: "dsh-files-search-input",
1063
- placeholder: "搜索文件 (支持路径筛选)...",
1064
- value: query,
1065
- onChange: (e) => setQuery(e.target.value),
1155
+ placeholder: "搜索文件或路径 (Esc 清空)...",
1156
+ value: inputQuery,
1157
+ onChange: (e) => setInputQuery(e.target.value),
1066
1158
  onKeyDown: (e) => {
1067
- if (e.key === "Escape") setQuery("");
1159
+ if (e.key === "Escape") setInputQuery("");
1068
1160
  }
1069
1161
  }),
1070
- query && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1162
+ inputQuery && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1071
1163
  type: "button",
1072
1164
  className: "dsh-files-clear-btn",
1073
- onClick: () => setQuery(""),
1074
- title: "清除搜索",
1165
+ onClick: () => setInputQuery(""),
1166
+ title: "清空搜索",
1075
1167
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconClose, { size: 12 })
1076
1168
  })
1077
1169
  ]
@@ -1082,29 +1174,29 @@ window.__ModuleLoader__.load({
1082
1174
  type: "button",
1083
1175
  className: "dsh-files-tool-btn is-active",
1084
1176
  onClick: () => setSearchViewMode(searchViewMode === "flat" ? "tree" : "flat"),
1085
- title: searchViewMode === "flat" ? "当前为扁平列表,点击切换为树形视图" : "当前为树形视图,点击切换为扁平列表",
1177
+ title: searchViewMode === "flat" ? "切为树形匹配视图" : "切为扁平列表视图",
1086
1178
  children: searchViewMode === "flat" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconTree, { size: 13 }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconList, { size: 13 })
1087
1179
  }) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1088
1180
  type: "button",
1089
1181
  className: "dsh-files-tool-btn",
1090
1182
  onClick: handleExpandAll,
1091
- title: "全部展开",
1183
+ title: "展开全部目录",
1092
1184
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconExpandAll, { size: 13 })
1093
1185
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1094
1186
  type: "button",
1095
1187
  className: "dsh-files-tool-btn",
1096
1188
  onClick: handleCollapseAll,
1097
- title: "全部折叠",
1189
+ title: "折叠全部目录",
1098
1190
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconCollapseAll, { size: 13 })
1099
1191
  })] }),
1100
1192
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1101
1193
  type: "button",
1102
1194
  className: `dsh-files-tool-btn ${showHidden ? "is-active" : ""}`,
1103
1195
  onClick: () => setShowHidden(!showHidden),
1104
- title: showHidden ? "隐藏点号开头的文件" : "显示点号开头的文件",
1196
+ title: showHidden ? "隐藏以点开头的文件" : "显示以点开头的文件",
1105
1197
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1106
1198
  style: {
1107
- fontSize: 11,
1199
+ fontSize: 10.5,
1108
1200
  fontWeight: 700
1109
1201
  },
1110
1202
  children: ".*"
@@ -1134,21 +1226,21 @@ window.__ModuleLoader__.load({
1134
1226
  className: "dsh-files-body",
1135
1227
  children: loading && !data ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1136
1228
  className: "dsh-files-centered",
1137
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: "dsh-files-spinner" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: "加载文件…" })]
1229
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: "dsh-files-spinner" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: "正在索引工作区文件…" })]
1138
1230
  }) : isSearchActive && flatSearchResults.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1139
1231
  className: "dsh-files-empty",
1140
1232
  children: [
1141
1233
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1142
1234
  className: "dsh-files-empty-icon",
1143
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconFolder, { size: 26 })
1235
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconFolder, { size: 28 })
1144
1236
  }),
1145
1237
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1146
1238
  className: "dsh-files-empty-title",
1147
- children: "未搜索到匹配的文件"
1239
+ children: "未匹配到相关文件"
1148
1240
  }),
1149
1241
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1150
1242
  className: "dsh-files-empty-detail",
1151
- children: "请尝试更换搜索关键字,或按 Esc 清除搜索。"
1243
+ children: "请尝试更换关键字或按 Esc 恢复完整目录树。"
1152
1244
  })
1153
1245
  ]
1154
1246
  }) : !isSearchActive && (!data || data.items.length === 0) ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
@@ -1156,7 +1248,7 @@ window.__ModuleLoader__.load({
1156
1248
  children: [
1157
1249
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1158
1250
  className: "dsh-files-empty-icon",
1159
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconFolder, { size: 26 })
1251
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconFolder, { size: 28 })
1160
1252
  }),
1161
1253
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1162
1254
  className: "dsh-files-empty-title",
@@ -1164,7 +1256,7 @@ window.__ModuleLoader__.load({
1164
1256
  }),
1165
1257
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1166
1258
  className: "dsh-files-empty-detail",
1167
- children: "当前工作目录下暂无可显示的文件。"
1259
+ children: "当前工作目录下暂无可展示的文件。"
1168
1260
  })
1169
1261
  ]
1170
1262
  }) : isSearchActive && searchViewMode === "flat" ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
@@ -1177,24 +1269,24 @@ window.__ModuleLoader__.load({
1177
1269
  "找到 ",
1178
1270
  flatSearchResults.length,
1179
1271
  " 个匹配项",
1180
- flatSearchResults.length > 150 ? "(展示前 150 项)" : ""
1272
+ flatSearchResults.length > 150 ? "(已展示前 150 项)" : ""
1181
1273
  ]
1182
1274
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
1183
1275
  type: "button",
1184
1276
  className: "dsh-files-view-toggle-btn",
1185
1277
  onClick: () => setSearchViewMode("tree"),
1186
- title: "切换为可折叠的树形视图",
1278
+ title: "切换为树形视图",
1187
1279
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconTree, { size: 12 }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: "切为树形" })]
1188
1280
  })]
1189
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1281
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1190
1282
  className: "dsh-files-flat-list",
1191
- children: [flatSearchResults.slice(0, 150).map(({ item, parentDir }) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1283
+ children: flatSearchResults.slice(0, 150).map(({ item, parentDir }) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1192
1284
  className: `dsh-files-flat-row ${item.isDirectory ? "is-directory" : ""}`,
1193
1285
  onClick: () => {
1194
1286
  if (item.isDirectory) handleJumpToFolderInTree(item.path);
1195
1287
  else onOpenFile(item.path);
1196
1288
  },
1197
- title: item.isDirectory ? `点击退出搜索并定位展开目录: ${item.path}/` : `点击预览打开文件: ${item.path}`,
1289
+ title: item.isDirectory ? `点击定位并展开目录: ${item.path}/` : `点击预览打开: ${item.path}`,
1198
1290
  children: [
1199
1291
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1200
1292
  className: "dsh-files-flat-icon",
@@ -1212,7 +1304,7 @@ window.__ModuleLoader__.load({
1212
1304
  className: "dsh-files-flat-name",
1213
1305
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(HighlightText, {
1214
1306
  text: item.name,
1215
- query
1307
+ query: deferredQuery
1216
1308
  }), item.isDirectory && "/"]
1217
1309
  }),
1218
1310
  item.size !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
@@ -1237,8 +1329,8 @@ window.__ModuleLoader__.load({
1237
1329
  type: "button",
1238
1330
  className: "dsh-files-action-btn dsh-files-action-at",
1239
1331
  onClick: (e) => handleMention(e, item),
1240
- title: `一键 @ 引用此${item.isDirectory ? "目录" : "文件"}到当前会话`,
1241
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconAt, { size: 13 }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1332
+ title: `@ 引用${item.isDirectory ? "目录" : "文件"}到会话`,
1333
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconAt, { size: 12 }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1242
1334
  className: "dsh-files-action-at-text",
1243
1335
  children: "@引用"
1244
1336
  })]
@@ -1247,14 +1339,14 @@ window.__ModuleLoader__.load({
1247
1339
  type: "button",
1248
1340
  className: "dsh-files-action-btn",
1249
1341
  onClick: (e) => handleRevealInExplorer(e, item),
1250
- title: `在文件资源管理器中显示此${item.isDirectory ? "目录" : "文件"}`,
1342
+ title: "在文件资源管理器中显示",
1251
1343
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconExplorer, { size: 12 })
1252
1344
  }),
1253
1345
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1254
1346
  type: "button",
1255
1347
  className: "dsh-files-action-btn",
1256
1348
  onClick: (e) => handleOpenDefaultApp(e, item),
1257
- title: `用系统默认应用打开此${item.isDirectory ? "目录" : "文件"}`,
1349
+ title: "用系统默认应用打开",
1258
1350
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconExternalApp, { size: 12 })
1259
1351
  }),
1260
1352
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
@@ -1267,24 +1359,19 @@ window.__ModuleLoader__.load({
1267
1359
  ]
1268
1360
  })
1269
1361
  ]
1270
- }, item.path)), flatSearchResults.length > 150 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1271
- style: {
1272
- padding: "10px 14px",
1273
- fontSize: 11,
1274
- textAlign: "center",
1275
- color: "var(--dsw-alias-label-tertiary, #8b93a1)",
1276
- borderTop: "1px dashed var(--dsw-alias-border-l2, #e5e7eb)"
1277
- },
1278
- children: "匹配项较多,已限制展示前 150 项以保证流畅度,请输入更详细关键字"
1279
- })]
1362
+ }, item.path))
1280
1363
  })]
1281
1364
  }) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1282
1365
  className: "dsh-files-tree",
1283
1366
  children: [isSearchActive && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1284
1367
  className: "dsh-files-search-header",
1285
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1368
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
1286
1369
  className: "dsh-files-search-count",
1287
- children: "树形匹配(自由折叠/展开)"
1370
+ children: [
1371
+ "树形匹配(共 ",
1372
+ visibleFlatRows.length,
1373
+ " 项)"
1374
+ ]
1288
1375
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
1289
1376
  type: "button",
1290
1377
  className: "dsh-files-view-toggle-btn",
@@ -1292,27 +1379,16 @@ window.__ModuleLoader__.load({
1292
1379
  title: "切换为扁平搜索结果列表",
1293
1380
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconList, { size: 12 }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: "切为列表" })]
1294
1381
  })]
1295
- }), filteredTreeItems.map((item) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FileTreeNode, {
1296
- item,
1297
- depth: 0,
1298
- query,
1299
- isSearchMode: isSearchActive,
1300
- expandedPaths: isSearchActive ? searchExpandedPaths : expandedPaths,
1301
- onToggleExpand: (path) => {
1302
- if (isSearchActive) setSearchExpandedPaths((prev) => {
1303
- const next = new Set(prev);
1304
- if (next.has(path)) next.delete(path);
1305
- else next.add(path);
1306
- return next;
1307
- });
1308
- else handleToggleExpand(path);
1309
- },
1382
+ }), visibleFlatRows.map((row) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FileTreeRow, {
1383
+ row,
1384
+ query: deferredQuery,
1385
+ onToggleExpand: handleToggleExpand,
1310
1386
  onOpenFile,
1311
1387
  onMention: handleMention,
1312
- onCopyPath: handleCopyPath,
1313
1388
  onRevealInExplorer: handleRevealInExplorer,
1314
- onOpenDefaultApp: handleOpenDefaultApp
1315
- }, item.path))]
1389
+ onOpenDefaultApp: handleOpenDefaultApp,
1390
+ onCopyPath: handleCopyPath
1391
+ }, row.id))]
1316
1392
  })
1317
1393
  }),
1318
1394
  toast && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
@@ -1322,120 +1398,101 @@ window.__ModuleLoader__.load({
1322
1398
  ]
1323
1399
  });
1324
1400
  }
1325
- function FileTreeNode(props) {
1326
- const { item, depth, query, isSearchMode, expandedPaths, onToggleExpand, onOpenFile, onMention, onCopyPath, onRevealInExplorer, onOpenDefaultApp } = props;
1327
- const isExpanded = expandedPaths.has(item.path);
1328
- if (item.isDirectory) {
1329
- const childCount = item.children?.length ?? 0;
1330
- return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1331
- className: "dsh-files-dir-block",
1332
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1333
- className: "dsh-files-dir-row",
1334
- "data-tree-path": item.path,
1335
- style: { paddingLeft: `${depth * 14 + 10}px` },
1336
- onClick: () => onToggleExpand(item.path),
1401
+ const FileTreeRow = (0, react.memo)(function FileTreeRow(props) {
1402
+ const { row, query, onToggleExpand, onOpenFile, onMention, onRevealInExplorer, onOpenDefaultApp, onCopyPath } = props;
1403
+ const indentPx = row.depth * 14 + 8;
1404
+ if (row.isDirectory) return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1405
+ className: "dsh-files-dir-row",
1406
+ "data-tree-path": row.path,
1407
+ style: { paddingLeft: `${indentPx}px` },
1408
+ onClick: () => onToggleExpand(row.path),
1409
+ children: [
1410
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1411
+ className: `dsh-files-chevron-wrap ${row.isExpanded ? "is-expanded" : ""}`,
1412
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconChevronRight, { size: 11 })
1413
+ }),
1414
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1415
+ className: "dsh-files-folder-icon",
1416
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconFolder, {
1417
+ size: 14,
1418
+ open: row.isExpanded
1419
+ })
1420
+ }),
1421
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1422
+ className: "dsh-files-folder-name",
1423
+ title: row.path,
1424
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(HighlightText, {
1425
+ text: row.name,
1426
+ query
1427
+ })
1428
+ }),
1429
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1430
+ className: "dsh-files-count-badge",
1431
+ children: row.childCount
1432
+ }),
1433
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1434
+ className: "dsh-files-row-actions",
1337
1435
  children: [
1338
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1339
- className: "dsh-files-chevron",
1340
- "data-collapsed": !isExpanded ? "true" : void 0,
1341
- children: "▾"
1342
- }),
1343
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1344
- className: "dsh-files-folder-icon",
1345
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconFolder, {
1346
- size: 14,
1347
- open: isExpanded
1348
- })
1436
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
1437
+ type: "button",
1438
+ className: "dsh-files-action-btn dsh-files-action-at",
1439
+ onClick: (e) => onMention(e, row.item),
1440
+ title: "一键 @ 引用此目录到会话",
1441
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconAt, { size: 12 }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1442
+ className: "dsh-files-action-at-text",
1443
+ children: "@引用"
1444
+ })]
1349
1445
  }),
1350
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1351
- className: "dsh-files-folder-name",
1352
- title: item.path,
1353
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(HighlightText, {
1354
- text: item.name,
1355
- query
1356
- })
1446
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1447
+ type: "button",
1448
+ className: "dsh-files-action-btn",
1449
+ onClick: (e) => onRevealInExplorer(e, row.item),
1450
+ title: "在文件资源管理器中打开此目录",
1451
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconExplorer, { size: 12 })
1357
1452
  }),
1358
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1359
- className: "dsh-files-count-badge",
1360
- children: childCount
1453
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1454
+ type: "button",
1455
+ className: "dsh-files-action-btn",
1456
+ onClick: (e) => onOpenDefaultApp(e, row.item),
1457
+ title: "用系统默认应用打开此目录",
1458
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconExternalApp, { size: 12 })
1361
1459
  }),
1362
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1363
- className: "dsh-files-row-actions",
1364
- children: [
1365
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
1366
- type: "button",
1367
- className: "dsh-files-action-btn dsh-files-action-at",
1368
- onClick: (e) => onMention(e, item),
1369
- title: "一键 @ 引用此目录到当前会话",
1370
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconAt, { size: 13 }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1371
- className: "dsh-files-action-at-text",
1372
- children: "@引用"
1373
- })]
1374
- }),
1375
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1376
- type: "button",
1377
- className: "dsh-files-action-btn",
1378
- onClick: (e) => onRevealInExplorer(e, item),
1379
- title: "在文件资源管理器中打开此目录",
1380
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconExplorer, { size: 12 })
1381
- }),
1382
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1383
- type: "button",
1384
- className: "dsh-files-action-btn",
1385
- onClick: (e) => onOpenDefaultApp(e, item),
1386
- title: "用系统默认应用打开此目录",
1387
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconExternalApp, { size: 12 })
1388
- }),
1389
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1390
- type: "button",
1391
- className: "dsh-files-action-btn",
1392
- onClick: (e) => onCopyPath(e, item.path),
1393
- title: "复制目录路径",
1394
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconCopy, { size: 12 })
1395
- })
1396
- ]
1460
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1461
+ type: "button",
1462
+ className: "dsh-files-action-btn",
1463
+ onClick: (e) => onCopyPath(e, row.path),
1464
+ title: "复制目录路径",
1465
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconCopy, { size: 12 })
1397
1466
  })
1398
1467
  ]
1399
- }), isExpanded && item.children && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1400
- className: "dsh-files-children",
1401
- children: item.children.map((child) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FileTreeNode, {
1402
- item: child,
1403
- depth: depth + 1,
1404
- query,
1405
- isSearchMode,
1406
- expandedPaths,
1407
- onToggleExpand,
1408
- onOpenFile,
1409
- onMention,
1410
- onCopyPath,
1411
- onRevealInExplorer,
1412
- onOpenDefaultApp
1413
- }, child.path))
1414
- })]
1415
- });
1416
- }
1468
+ })
1469
+ ]
1470
+ });
1417
1471
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1418
1472
  className: "dsh-files-row",
1419
- "data-tree-path": item.path,
1420
- style: { paddingLeft: `${depth * 14 + 10}px` },
1421
- onClick: () => onOpenFile(item.path),
1422
- title: `点击打开: ${item.path}`,
1473
+ "data-tree-path": row.path,
1474
+ style: { paddingLeft: `${indentPx}px` },
1475
+ onClick: () => onOpenFile(row.path),
1476
+ title: `点击打开文件: ${row.path}`,
1423
1477
  children: [
1424
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FileGlyphIcon, {
1425
- filename: item.name,
1426
- size: 14
1478
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1479
+ className: "dsh-files-file-glyph",
1480
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FileGlyphIcon, {
1481
+ filename: row.name,
1482
+ size: 14
1483
+ })
1427
1484
  }),
1428
1485
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1429
1486
  className: "dsh-files-name",
1430
1487
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(HighlightText, {
1431
- text: item.name,
1488
+ text: row.name,
1432
1489
  query
1433
1490
  })
1434
1491
  }),
1435
- item.size !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1492
+ row.size !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1436
1493
  className: "dsh-files-size",
1437
- title: `大小: ${item.size} 字节`,
1438
- children: formatFileSize(item.size)
1494
+ title: `大小: ${row.size} 字节`,
1495
+ children: formatFileSize(row.size)
1439
1496
  }),
1440
1497
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1441
1498
  className: "dsh-files-row-actions",
@@ -1443,9 +1500,9 @@ window.__ModuleLoader__.load({
1443
1500
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
1444
1501
  type: "button",
1445
1502
  className: "dsh-files-action-btn dsh-files-action-at",
1446
- onClick: (e) => onMention(e, item),
1447
- title: "一键 @ 引用此文件到当前会话",
1448
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconAt, { size: 13 }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1503
+ onClick: (e) => onMention(e, row.item),
1504
+ title: "一键 @ 引用此文件到会话",
1505
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconAt, { size: 12 }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1449
1506
  className: "dsh-files-action-at-text",
1450
1507
  children: "@引用"
1451
1508
  })]
@@ -1453,21 +1510,21 @@ window.__ModuleLoader__.load({
1453
1510
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1454
1511
  type: "button",
1455
1512
  className: "dsh-files-action-btn",
1456
- onClick: (e) => onRevealInExplorer(e, item),
1457
- title: "在文件资源管理器中显示此文件",
1513
+ onClick: (e) => onRevealInExplorer(e, row.item),
1514
+ title: "在文件资源管理器中定位",
1458
1515
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconExplorer, { size: 12 })
1459
1516
  }),
1460
1517
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1461
1518
  type: "button",
1462
1519
  className: "dsh-files-action-btn",
1463
- onClick: (e) => onOpenDefaultApp(e, item),
1464
- title: "用系统默认应用打开此文件",
1520
+ onClick: (e) => onOpenDefaultApp(e, row.item),
1521
+ title: "用系统默认应用打开",
1465
1522
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconExternalApp, { size: 12 })
1466
1523
  }),
1467
1524
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1468
1525
  type: "button",
1469
1526
  className: "dsh-files-action-btn",
1470
- onClick: (e) => onCopyPath(e, item.path),
1527
+ onClick: (e) => onCopyPath(e, row.path),
1471
1528
  title: "复制相对路径",
1472
1529
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconCopy, { size: 12 })
1473
1530
  })
@@ -1475,15 +1532,16 @@ window.__ModuleLoader__.load({
1475
1532
  })
1476
1533
  ]
1477
1534
  });
1478
- }
1535
+ }, (prev, next) => {
1536
+ return prev.row.id === next.row.id && prev.row.isExpanded === next.row.isExpanded && prev.row.depth === next.row.depth && prev.row.childCount === next.row.childCount && prev.query === next.query;
1537
+ });
1479
1538
  function HighlightText({ text, query }) {
1480
- const q = query.trim().toLowerCase();
1481
- if (!q) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: text });
1482
- const index = text.toLowerCase().indexOf(q);
1539
+ if (!query) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: text });
1540
+ const index = text.toLowerCase().indexOf(query);
1483
1541
  if (index === -1) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: text });
1484
1542
  const before = text.slice(0, index);
1485
- const match = text.slice(index, index + q.length);
1486
- const after = text.slice(index + q.length);
1543
+ const match = text.slice(index, index + query.length);
1544
+ const after = text.slice(index + query.length);
1487
1545
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [
1488
1546
  before,
1489
1547
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("mark", {
@@ -1499,12 +1557,6 @@ window.__ModuleLoader__.load({
1499
1557
  if (kb < 1024) return `${kb.toFixed(1)} KB`;
1500
1558
  return `${(kb / 1024).toFixed(1)} MB`;
1501
1559
  }
1502
- /**
1503
- * 按照 DSH 官方规范格式化引用路径:
1504
- * - 纯路径无空格:@path
1505
- * - 路径含空格:@"path"
1506
- * - 目录末尾保留斜杠:@folder/ 或 @"folder/"
1507
- */
1508
1560
  function formatMentionText(path, isDirectory = false) {
1509
1561
  const cleanPath = path.replace(/\\/g, "/").replace(/^\.?\//, "");
1510
1562
  const finalPath = isDirectory ? cleanPath.endsWith("/") ? cleanPath : `${cleanPath}/` : cleanPath;
@@ -1530,9 +1582,6 @@ window.__ModuleLoader__.load({
1530
1582
  window.localStorage.setItem(getStorageKey(workspaceRoot), JSON.stringify(Array.from(paths)));
1531
1583
  } catch {}
1532
1584
  }
1533
- /**
1534
- * 从当前 DOM 的 React Fiber 树或 Cordis RootContext 中提取当前活跃输入框的 SessionInputShell 实例
1535
- */
1536
1585
  function findComposerShell(ctx, sessionId) {
1537
1586
  try {
1538
1587
  const composerDom = document.querySelector("[data-composer-input=\"true\"], [data-composer-input], [data-composer-card], div[role=\"textbox\"][contenteditable=\"true\"]");
@@ -1552,9 +1601,7 @@ window.__ModuleLoader__.load({
1552
1601
  }
1553
1602
  }
1554
1603
  }
1555
- } catch (e) {
1556
- console.debug("[dsh-workspace-files] 从 Fiber 查找 keyboard 失败:", e);
1557
- }
1604
+ } catch {}
1558
1605
  if (ctx) try {
1559
1606
  const root = ctx.root || ctx;
1560
1607
  const inputService = (root.conversation || root.get?.("conversation") || window.__dsh_conversation)?.input || root["conversation.input"] || root.get?.("conversation.input");
@@ -1568,14 +1615,9 @@ window.__ModuleLoader__.load({
1568
1615
  return values[values.length - 1];
1569
1616
  }
1570
1617
  }
1571
- } catch (e) {
1572
- console.debug("[dsh-workspace-files] 从 RootContext 查找 shell 失败:", e);
1573
- }
1618
+ } catch {}
1574
1619
  return null;
1575
1620
  }
1576
- /**
1577
- * 尝试向会话输入框插入原生的 ReferenceChipNode(官方胶囊 Tag 卡片)
1578
- */
1579
1621
  function tryInsertNativeReferenceChip(ctx, sessionId, item) {
1580
1622
  if (typeof document === "undefined") return false;
1581
1623
  try {
@@ -1612,16 +1654,9 @@ window.__ModuleLoader__.load({
1612
1654
  span
1613
1655
  }) === true) return true;
1614
1656
  }
1615
- } catch (err) {
1616
- console.debug("[dsh-workspace-files] 插入原生 Chip 异常:", err);
1617
- }
1657
+ } catch {}
1618
1658
  return false;
1619
1659
  }
1620
- /**
1621
- * 将引用文本注入到 DSH 当前会话的主输入框。
1622
- * 兼容 DSH 官方基于 Lexical 的 ComposerContentEditable (div[data-composer-input])
1623
- * 以及传统的 textarea / input,并自动消除用户手动输入的冗余 '@'。
1624
- */
1625
1660
  function insertMentionToComposer(mentionText) {
1626
1661
  if (typeof document === "undefined") return false;
1627
1662
  const target = [
@@ -1722,16 +1757,21 @@ window.__ModuleLoader__.load({
1722
1757
  if (!response.ok || envelope?.ok !== true || envelope.value === void 0) throw new Error(envelope?.error?.message ?? `HTTP ${response.status}`);
1723
1758
  return envelope.value;
1724
1759
  }
1725
- function GlobalFilesStyle() {
1726
- return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("style", { children: `
1760
+ function ensureFilesStyle() {
1761
+ if (typeof document === "undefined") return;
1762
+ const id = "dsh-workspace-files-core-style";
1763
+ if (document.getElementById(id)) return;
1764
+ const style = document.createElement("style");
1765
+ style.id = id;
1766
+ style.textContent = `
1727
1767
  .dsh-files-root {
1728
1768
  display: flex;
1729
1769
  flex-direction: column;
1730
1770
  height: 100%;
1731
1771
  min-height: 0;
1732
1772
  box-sizing: border-box;
1733
- background: var(--dsw-alias-bg-base, #ffffff);
1734
- color: var(--dsw-alias-label-primary, #17233c);
1773
+ background: var(--dsw-alias-fill-base, #ffffff);
1774
+ color: var(--dsw-alias-label-primary);
1735
1775
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
1736
1776
  font-size: 12px;
1737
1777
  line-height: 1.4;
@@ -1747,7 +1787,8 @@ window.__ModuleLoader__.load({
1747
1787
  justify-content: space-between;
1748
1788
  gap: 8px;
1749
1789
  padding: 8px 12px;
1750
- border-bottom: 1px solid var(--dsw-alias-border-l1, rgba(118,137,166,.18));
1790
+ border-bottom: 0.5px solid var(--dsw-alias-border-l1);
1791
+ background: var(--dsw-alias-fill-base, #ffffff);
1751
1792
  }
1752
1793
  .dsh-files-header-info {
1753
1794
  flex: 1;
@@ -1761,33 +1802,34 @@ window.__ModuleLoader__.load({
1761
1802
  .dsh-files-title {
1762
1803
  font-weight: 600;
1763
1804
  font-size: 13px;
1764
- color: var(--dsw-alias-label-primary, inherit);
1805
+ color: var(--dsw-alias-label-primary);
1765
1806
  }
1766
1807
  .dsh-files-stats-badge {
1767
1808
  font-size: 10px;
1768
1809
  font-weight: 500;
1769
- color: var(--dsw-alias-label-tertiary, #8c9ba5);
1770
- background: var(--dsw-alias-interactive-bg-hover, rgba(100,120,150,.1));
1771
- padding: 1px 6px;
1810
+ color: var(--dsw-alias-label-tertiary);
1811
+ background: color-mix(in srgb, var(--dsw-alias-label-primary) 6%, transparent);
1812
+ padding: 1px 7px;
1772
1813
  border-radius: 99px;
1773
1814
  }
1774
1815
  .dsh-files-root-path {
1775
1816
  font-size: 11px;
1776
- color: var(--dsw-alias-label-tertiary, #8c9ba5);
1817
+ color: var(--dsw-alias-label-tertiary);
1777
1818
  overflow: hidden;
1778
1819
  text-overflow: ellipsis;
1779
1820
  white-space: nowrap;
1780
- margin-top: 1px;
1821
+ margin-top: 2px;
1781
1822
  }
1782
1823
 
1783
- /* ── Toolbar & Search ── */
1824
+ /* ── Toolbar & Pure White Input ── */
1784
1825
  .dsh-files-toolbar {
1785
1826
  display: flex;
1786
1827
  align-items: center;
1787
1828
  gap: 6px;
1788
- padding: 6px 8px 6px 12px;
1789
- border-bottom: 1px solid var(--dsw-alias-border-l1, rgba(118,137,166,.15));
1790
- background: var(--dsw-alias-bg-base, #ffffff);
1829
+ padding: 6px 10px;
1830
+ border-bottom: 0.5px solid var(--dsw-alias-border-l2);
1831
+ background: var(--dsw-alias-fill-base, #ffffff);
1832
+ flex-shrink: 0;
1791
1833
  }
1792
1834
  .dsh-files-search-wrap {
1793
1835
  position: relative;
@@ -1798,70 +1840,77 @@ window.__ModuleLoader__.load({
1798
1840
  }
1799
1841
  .dsh-files-search-icon {
1800
1842
  position: absolute;
1801
- left: 7px;
1802
- color: var(--dsw-alias-label-tertiary, #8c9ba5);
1843
+ left: 8px;
1844
+ color: var(--dsw-alias-label-tertiary);
1803
1845
  pointer-events: none;
1804
1846
  display: flex;
1805
1847
  }
1806
1848
  .dsh-files-search-input {
1807
1849
  box-sizing: border-box;
1808
1850
  width: 100%;
1809
- height: 25px;
1810
- padding: 0 22px 0 26px;
1811
- border: 1px solid var(--dsw-alias-border-l2, rgba(118,137,166,.25));
1812
- border-radius: 4px;
1813
- background: var(--dsw-alias-interactive-bg-hover, rgba(100,120,150,.06));
1814
- color: inherit;
1815
- font-size: 11.5px;
1851
+ height: 28px;
1852
+ padding: 0 24px 0 28px;
1853
+ border: 0.5px solid var(--dsw-alias-border-l1);
1854
+ border-radius: var(--dsw-radius-sm, 6px);
1855
+ background: var(--dsw-alias-fill-base, #ffffff);
1856
+ color: var(--dsw-alias-label-primary);
1857
+ font-size: 11px;
1816
1858
  outline: none;
1817
- transition: all 0.15s ease;
1859
+ transition: border-color 0.15s ease, box-shadow 0.15s ease, background 0.15s ease;
1818
1860
  }
1819
1861
  .dsh-files-search-input:focus {
1820
- background: var(--dsw-alias-bg-base, #ffffff);
1821
- border-color: var(--dsw-alias-brand-primary, #4b70e2);
1822
- box-shadow: 0 0 0 2px color-mix(in srgb, var(--dsw-alias-brand-primary, #4b70e2) 15%, transparent);
1862
+ border-color: var(--dsw-alias-state-business-primary);
1863
+ background: var(--dsw-alias-fill-base, #ffffff);
1864
+ box-shadow: 0 0 0 2px color-mix(in srgb, var(--dsw-alias-state-business-primary) 18%, transparent);
1823
1865
  }
1824
1866
  .dsh-files-clear-btn {
1825
1867
  position: absolute;
1826
- right: 5px;
1868
+ right: 6px;
1827
1869
  border: none;
1828
1870
  background: transparent;
1829
- color: var(--dsw-alias-label-tertiary, #8c9ba5);
1871
+ color: var(--dsw-alias-label-tertiary);
1830
1872
  cursor: pointer;
1831
1873
  padding: 2px;
1832
1874
  display: flex;
1875
+ border-radius: 50%;
1876
+ transition: all 0.12s ease;
1833
1877
  }
1834
1878
  .dsh-files-clear-btn:hover {
1835
- color: var(--dsw-alias-label-primary, inherit);
1879
+ color: var(--dsw-alias-label-primary);
1880
+ background: var(--dsw-alias-interactive-bg-hover);
1836
1881
  }
1837
1882
  .dsh-files-toolbar-btns {
1838
1883
  display: flex;
1839
1884
  align-items: center;
1840
1885
  gap: 2px;
1886
+ flex-shrink: 0;
1841
1887
  }
1842
1888
  .dsh-files-tool-btn {
1843
1889
  display: inline-flex;
1844
1890
  align-items: center;
1845
1891
  justify-content: center;
1846
- width: 24px;
1847
- height: 24px;
1892
+ width: 26px;
1893
+ height: 26px;
1848
1894
  border: none;
1849
- border-radius: 4px;
1895
+ border-radius: var(--dsw-radius-xs, 4px);
1850
1896
  background: transparent;
1851
- color: var(--dsw-alias-label-secondary, #6f7f9b);
1897
+ color: var(--dsw-alias-label-secondary);
1852
1898
  cursor: pointer;
1853
- transition: all 0.12s ease;
1899
+ transition: all 0.15s cubic-bezier(0.16, 1, 0.3, 1);
1854
1900
  }
1855
1901
  .dsh-files-tool-btn:hover:not(:disabled) {
1856
- color: var(--dsw-alias-label-primary, inherit);
1857
- background: var(--dsw-alias-interactive-bg-hover, rgba(100,120,150,.1));
1902
+ color: var(--dsw-alias-label-primary);
1903
+ background: var(--dsw-alias-interactive-bg-hover);
1904
+ }
1905
+ .dsh-files-tool-btn:active:not(:disabled) {
1906
+ transform: scale(0.94);
1858
1907
  }
1859
1908
  .dsh-files-tool-btn.is-active {
1860
- color: var(--dsw-alias-brand-primary, #4b70e2);
1861
- background: var(--dsw-alias-interactive-bg-active, rgba(75,112,226,.15));
1909
+ color: var(--dsw-alias-state-business-primary);
1910
+ background: color-mix(in srgb, var(--dsw-alias-state-business-primary) 14%, transparent);
1862
1911
  }
1863
1912
  .dsh-files-tool-btn:disabled {
1864
- opacity: 0.4;
1913
+ opacity: 0.35;
1865
1914
  cursor: not-allowed;
1866
1915
  }
1867
1916
 
@@ -1873,10 +1922,8 @@ window.__ModuleLoader__.load({
1873
1922
  overflow-x: hidden;
1874
1923
  padding: 4px 0;
1875
1924
  }
1876
- .dsh-files-dir-block {
1877
- display: flex;
1878
- flex-direction: column;
1879
- }
1925
+
1926
+ /* ── Directory Row (with Motion Chevron) ── */
1880
1927
  .dsh-files-dir-row {
1881
1928
  display: flex;
1882
1929
  align-items: center;
@@ -1886,29 +1933,35 @@ window.__ModuleLoader__.load({
1886
1933
  cursor: pointer;
1887
1934
  user-select: none;
1888
1935
  position: relative;
1889
- color: var(--dsw-alias-label-secondary, #6f7f9b);
1936
+ color: var(--dsw-alias-label-primary);
1937
+ border-radius: var(--dsw-radius-xs, 4px);
1938
+ margin: 0 4px;
1890
1939
  transition: background 0.12s ease;
1891
1940
  }
1892
1941
  .dsh-files-dir-row:hover {
1893
- background: var(--dsw-alias-interactive-bg-hover, rgba(100,120,150,.08));
1894
- color: var(--dsw-alias-label-primary, inherit);
1942
+ background: var(--dsw-alias-interactive-bg-hover);
1895
1943
  }
1896
- .dsh-files-chevron {
1897
- font-size: 10px;
1898
- transition: transform 0.15s ease;
1899
- display: inline-block;
1900
- opacity: 0.8;
1944
+ .dsh-files-chevron-wrap {
1945
+ width: 12px;
1946
+ height: 12px;
1947
+ display: inline-flex;
1948
+ align-items: center;
1949
+ justify-content: center;
1950
+ color: var(--dsw-alias-label-tertiary);
1951
+ transition: transform 0.18s cubic-bezier(0.16, 1, 0.3, 1);
1952
+ flex-shrink: 0;
1901
1953
  }
1902
- .dsh-files-chevron[data-collapsed='true'] {
1903
- transform: rotate(-90deg);
1954
+ .dsh-files-chevron-wrap.is-expanded {
1955
+ transform: rotate(90deg);
1904
1956
  }
1905
1957
  .dsh-files-folder-icon {
1906
1958
  display: flex;
1959
+ flex-shrink: 0;
1907
1960
  }
1908
1961
  .dsh-files-folder-name {
1909
1962
  flex: 1;
1910
1963
  min-width: 0;
1911
- font-weight: 500;
1964
+ font-weight: 550;
1912
1965
  font-size: 12px;
1913
1966
  overflow: hidden;
1914
1967
  text-overflow: ellipsis;
@@ -1919,8 +1972,8 @@ window.__ModuleLoader__.load({
1919
1972
  font-weight: 600;
1920
1973
  padding: 0 5px;
1921
1974
  border-radius: 99px;
1922
- background: var(--dsw-alias-interactive-bg-hover, rgba(100,120,150,.1));
1923
- color: var(--dsw-alias-label-tertiary, #8c9ba5);
1975
+ background: color-mix(in srgb, var(--dsw-alias-label-primary) 6%, transparent);
1976
+ color: var(--dsw-alias-label-tertiary);
1924
1977
  }
1925
1978
 
1926
1979
  /* ── File Row ── */
@@ -1933,44 +1986,95 @@ window.__ModuleLoader__.load({
1933
1986
  cursor: pointer;
1934
1987
  user-select: none;
1935
1988
  position: relative;
1989
+ border-radius: var(--dsw-radius-xs, 4px);
1990
+ margin: 0 4px;
1936
1991
  transition: background 0.12s ease;
1937
1992
  }
1938
1993
  .dsh-files-row:hover {
1939
- background: var(--dsw-alias-interactive-bg-hover, rgba(100,120,150,.08));
1994
+ background: var(--dsw-alias-interactive-bg-hover);
1995
+ }
1996
+ .dsh-files-file-glyph {
1997
+ margin-left: 12px;
1998
+ display: inline-flex;
1999
+ align-items: center;
2000
+ justify-content: center;
1940
2001
  }
1941
2002
  .dsh-files-name {
1942
2003
  flex: 1;
1943
2004
  min-width: 0;
1944
2005
  font-size: 12px;
1945
- color: var(--dsw-alias-label-primary, inherit);
2006
+ color: var(--dsw-alias-label-primary);
1946
2007
  overflow: hidden;
1947
2008
  text-overflow: ellipsis;
1948
2009
  white-space: nowrap;
1949
2010
  }
1950
2011
  .dsh-files-size {
1951
2012
  font-size: 10px;
1952
- color: var(--dsw-alias-label-tertiary, #8c9ba5);
2013
+ color: var(--dsw-alias-label-tertiary);
1953
2014
  flex-shrink: 0;
1954
2015
  margin-right: 4px;
1955
2016
  }
1956
2017
 
1957
- /* ── Hover Actions on Rows ── */
2018
+ /* ── Micro-Interaction Hover Action Pills ── */
1958
2019
  .dsh-files-row-actions {
1959
- display: none;
2020
+ display: flex;
1960
2021
  align-items: center;
1961
- gap: 3px;
2022
+ gap: 2px;
1962
2023
  flex-shrink: 0;
2024
+ opacity: 0;
2025
+ transform: translateX(4px);
2026
+ pointer-events: none;
2027
+ transition: opacity 0.15s cubic-bezier(0.16, 1, 0.3, 1), transform 0.15s cubic-bezier(0.16, 1, 0.3, 1);
2028
+ margin-left: auto;
1963
2029
  }
1964
2030
  .dsh-files-row:hover .dsh-files-row-actions,
1965
2031
  .dsh-files-dir-row:hover .dsh-files-row-actions,
1966
2032
  .dsh-files-flat-row:hover .dsh-files-row-actions {
1967
- display: flex;
2033
+ opacity: 1;
2034
+ transform: translateX(0);
2035
+ pointer-events: auto;
1968
2036
  }
1969
2037
  .dsh-files-row:hover .dsh-files-size,
1970
2038
  .dsh-files-dir-row:hover .dsh-files-count-badge,
1971
2039
  .dsh-files-flat-row:hover .dsh-files-size {
1972
2040
  display: none;
1973
2041
  }
2042
+ .dsh-files-action-btn {
2043
+ display: inline-flex;
2044
+ align-items: center;
2045
+ justify-content: center;
2046
+ gap: 3px;
2047
+ height: 20px;
2048
+ padding: 0 5px;
2049
+ border: 0.5px solid var(--dsw-alias-border-l1);
2050
+ border-radius: var(--dsw-radius-xs, 3px);
2051
+ background: var(--dsw-alias-fill-base, #ffffff);
2052
+ color: var(--dsw-alias-label-secondary);
2053
+ cursor: pointer;
2054
+ transition: all 0.12s cubic-bezier(0.16, 1, 0.3, 1);
2055
+ }
2056
+ .dsh-files-action-btn:hover {
2057
+ color: var(--dsw-alias-label-primary);
2058
+ border-color: var(--dsw-alias-state-business-primary);
2059
+ background: var(--dsw-alias-interactive-bg-hover);
2060
+ }
2061
+ .dsh-files-action-btn:active {
2062
+ transform: scale(0.92);
2063
+ }
2064
+ .dsh-files-action-at {
2065
+ color: var(--dsw-alias-state-business-primary);
2066
+ border-color: color-mix(in srgb, var(--dsw-alias-state-business-primary) 35%, transparent);
2067
+ background: color-mix(in srgb, var(--dsw-alias-state-business-primary) 8%, transparent);
2068
+ }
2069
+ .dsh-files-action-at:hover {
2070
+ color: var(--dsw-alias-label-primary-inverted, #ffffff);
2071
+ background: var(--dsw-alias-state-business-primary);
2072
+ border-color: var(--dsw-alias-state-business-primary);
2073
+ }
2074
+ .dsh-files-action-at-text {
2075
+ font-size: 10px;
2076
+ font-weight: 600;
2077
+ }
1974
2078
 
1975
2079
  /* ── Flat Search Result List ── */
1976
2080
  .dsh-files-search-container {
@@ -1983,9 +2087,9 @@ window.__ModuleLoader__.load({
1983
2087
  justify-content: space-between;
1984
2088
  padding: 6px 12px;
1985
2089
  font-size: 11px;
1986
- color: var(--dsw-alias-label-tertiary, #8c9ba5);
1987
- background: color-mix(in srgb, var(--dsw-alias-brand-primary, #4b70e2) 4%, transparent);
1988
- border-bottom: 1px solid var(--dsw-alias-border-l1, rgba(118,137,166,.15));
2090
+ color: var(--dsw-alias-label-tertiary);
2091
+ background: color-mix(in srgb, var(--dsw-alias-state-business-primary) 4%, transparent);
2092
+ border-bottom: 0.5px solid var(--dsw-alias-border-l2);
1989
2093
  }
1990
2094
  .dsh-files-search-count {
1991
2095
  font-weight: 500;
@@ -1994,20 +2098,20 @@ window.__ModuleLoader__.load({
1994
2098
  display: inline-flex;
1995
2099
  align-items: center;
1996
2100
  gap: 4px;
1997
- border: 1px solid var(--dsw-alias-border-l2, rgba(118,137,166,.25));
1998
- background: var(--dsw-alias-container-bg, var(--dsw-alias-bg-base, #ffffff));
1999
- color: var(--dsw-alias-brand-primary, #4b70e2);
2101
+ border: 0.5px solid var(--dsw-alias-border-l1);
2102
+ background: var(--dsw-alias-fill-base, #ffffff);
2103
+ color: var(--dsw-alias-state-business-primary);
2000
2104
  cursor: pointer;
2001
2105
  font-size: 10.5px;
2002
2106
  font-weight: 500;
2003
2107
  padding: 2px 7px;
2004
- border-radius: 4px;
2005
- transition: all 0.12s ease;
2108
+ border-radius: var(--dsw-radius-xs, 4px);
2109
+ transition: all 0.12s cubic-bezier(0.16, 1, 0.3, 1);
2006
2110
  }
2007
2111
  .dsh-files-view-toggle-btn:hover {
2008
- background: var(--dsw-alias-brand-primary, #4b70e2);
2009
- color: #ffffff;
2010
- border-color: var(--dsw-alias-brand-primary, #4b70e2);
2112
+ background: var(--dsw-alias-state-business-primary);
2113
+ color: var(--dsw-alias-label-primary-inverted, #ffffff);
2114
+ border-color: var(--dsw-alias-state-business-primary);
2011
2115
  }
2012
2116
  .dsh-files-flat-list {
2013
2117
  padding: 4px 0;
@@ -2016,7 +2120,7 @@ window.__ModuleLoader__.load({
2016
2120
  display: flex;
2017
2121
  align-items: center;
2018
2122
  gap: 8px;
2019
- padding: 4px 12px;
2123
+ padding: 5px 12px;
2020
2124
  cursor: pointer;
2021
2125
  user-select: none;
2022
2126
  position: relative;
@@ -2024,7 +2128,7 @@ window.__ModuleLoader__.load({
2024
2128
  min-height: 32px;
2025
2129
  }
2026
2130
  .dsh-files-flat-row:hover {
2027
- background: var(--dsw-alias-interactive-bg-hover, rgba(100,120,150,.08));
2131
+ background: var(--dsw-alias-interactive-bg-hover);
2028
2132
  }
2029
2133
  .dsh-files-flat-icon {
2030
2134
  display: flex;
@@ -2048,22 +2152,21 @@ window.__ModuleLoader__.load({
2048
2152
  .dsh-files-flat-name {
2049
2153
  font-size: 12px;
2050
2154
  font-weight: 500;
2051
- color: var(--dsw-alias-label-primary, inherit);
2155
+ color: var(--dsw-alias-label-primary);
2052
2156
  overflow: hidden;
2053
2157
  text-overflow: ellipsis;
2054
2158
  white-space: nowrap;
2055
2159
  }
2056
2160
  .dsh-files-flat-parent {
2057
2161
  font-size: 10.5px;
2058
- color: var(--dsw-alias-label-tertiary, #8c9ba5);
2162
+ color: var(--dsw-alias-label-tertiary);
2059
2163
  overflow: hidden;
2060
2164
  text-overflow: ellipsis;
2061
2165
  white-space: nowrap;
2062
- opacity: 0.8;
2063
2166
  }
2064
2167
  .dsh-files-jump-hint {
2065
2168
  font-size: 10px;
2066
- color: var(--dsw-alias-brand-primary, #4b70e2);
2169
+ color: var(--dsw-alias-state-business-primary);
2067
2170
  opacity: 0;
2068
2171
  transition: opacity 0.12s ease;
2069
2172
  margin-right: 6px;
@@ -2071,49 +2174,16 @@ window.__ModuleLoader__.load({
2071
2174
  white-space: nowrap;
2072
2175
  }
2073
2176
  .dsh-files-flat-row:hover .dsh-files-jump-hint {
2074
- opacity: 0.85;
2177
+ opacity: 0.9;
2075
2178
  }
2076
2179
  .dsh-files-flat-row.is-directory:hover {
2077
- background: color-mix(in srgb, var(--dsw-alias-brand-primary, #4b70e2) 6%, transparent);
2078
- }
2079
- .dsh-files-action-btn {
2080
- display: inline-flex;
2081
- align-items: center;
2082
- justify-content: center;
2083
- gap: 3px;
2084
- height: 20px;
2085
- padding: 0 5px;
2086
- border: 1px solid var(--dsw-alias-border-l2, rgba(118,137,166,.25));
2087
- border-radius: 3px;
2088
- background: var(--dsw-alias-container-bg, var(--dsw-alias-bg-base, #ffffff));
2089
- color: var(--dsw-alias-label-secondary, #6f7f9b);
2090
- cursor: pointer;
2091
- transition: all 0.12s ease;
2092
- }
2093
- .dsh-files-action-btn:hover {
2094
- color: var(--dsw-alias-label-primary, inherit);
2095
- border-color: var(--dsw-alias-border-l3, rgba(118,137,166,.4));
2096
- background: var(--dsw-alias-interactive-bg-hover, rgba(100,120,150,.12));
2097
- }
2098
- .dsh-files-action-at {
2099
- color: var(--dsw-alias-brand-primary, #4b70e2);
2100
- border-color: color-mix(in srgb, var(--dsw-alias-brand-primary, #4b70e2) 30%, transparent);
2101
- background: color-mix(in srgb, var(--dsw-alias-brand-primary, #4b70e2) 8%, transparent);
2102
- }
2103
- .dsh-files-action-at:hover {
2104
- color: #ffffff;
2105
- background: var(--dsw-alias-brand-primary, #4b70e2);
2106
- border-color: var(--dsw-alias-brand-primary, #4b70e2);
2107
- }
2108
- .dsh-files-action-at-text {
2109
- font-size: 10px;
2110
- font-weight: 600;
2180
+ background: color-mix(in srgb, var(--dsw-alias-state-business-primary) 8%, transparent);
2111
2181
  }
2112
2182
 
2113
2183
  /* ── Highlight & Toast ── */
2114
2184
  .dsh-files-highlight {
2115
- background: color-mix(in srgb, var(--dsw-alias-brand-primary, #4b70e2) 25%, transparent);
2116
- color: var(--dsw-alias-brand-primary, #4b70e2);
2185
+ background: color-mix(in srgb, var(--dsw-alias-state-business-primary) 22%, transparent);
2186
+ color: var(--dsw-alias-state-business-primary);
2117
2187
  font-weight: 600;
2118
2188
  border-radius: 2px;
2119
2189
  padding: 0 1px;
@@ -2127,12 +2197,12 @@ window.__ModuleLoader__.load({
2127
2197
  align-items: center;
2128
2198
  gap: 6px;
2129
2199
  padding: 6px 12px;
2130
- background: var(--dsw-alias-label-primary, #17233c);
2131
- color: var(--dsw-alias-bg-base, #ffffff);
2200
+ background: var(--dsw-alias-label-primary);
2201
+ color: var(--dsw-alias-fill-base, #ffffff);
2132
2202
  font-size: 11px;
2133
2203
  border-radius: 99px;
2134
- box-shadow: 0 4px 16px rgba(0,0,0,.25);
2135
- animation: dsh-files-fade-in 0.15s ease;
2204
+ box-shadow: 0 4px 16px rgba(0,0,0,0.22);
2205
+ animation: dsh-files-fade-in 0.16s cubic-bezier(0.16, 1, 0.3, 1);
2136
2206
  z-index: 100;
2137
2207
  pointer-events: none;
2138
2208
  white-space: nowrap;
@@ -2150,13 +2220,13 @@ window.__ModuleLoader__.load({
2150
2220
  justify-content: center;
2151
2221
  height: 180px;
2152
2222
  gap: 10px;
2153
- color: var(--dsw-alias-label-secondary, #6f7f9b);
2223
+ color: var(--dsw-alias-label-secondary);
2154
2224
  }
2155
2225
  .dsh-files-spinner {
2156
2226
  width: 18px;
2157
2227
  height: 18px;
2158
- border: 2px solid var(--dsw-alias-border-l2, rgba(118,137,166,.3));
2159
- border-top-color: var(--dsw-alias-brand-primary, #4b70e2);
2228
+ border: 2px solid var(--dsw-alias-border-l1);
2229
+ border-top-color: var(--dsw-alias-state-business-primary);
2160
2230
  border-radius: 50%;
2161
2231
  animation: dsh-files-spin 0.8s linear infinite;
2162
2232
  }
@@ -2170,7 +2240,7 @@ window.__ModuleLoader__.load({
2170
2240
  justify-content: center;
2171
2241
  padding: 36px 16px;
2172
2242
  text-align: center;
2173
- color: var(--dsw-alias-label-secondary, #6f7f9b);
2243
+ color: var(--dsw-alias-label-secondary);
2174
2244
  }
2175
2245
  .dsh-files-empty-icon {
2176
2246
  margin-bottom: 8px;
@@ -2183,7 +2253,7 @@ window.__ModuleLoader__.load({
2183
2253
  }
2184
2254
  .dsh-files-empty-detail {
2185
2255
  font-size: 11.5px;
2186
- color: var(--dsw-alias-label-tertiary, #8c9ba5);
2256
+ color: var(--dsw-alias-label-tertiary);
2187
2257
  }
2188
2258
  .dsh-files-banner-error {
2189
2259
  display: flex;
@@ -2192,9 +2262,9 @@ window.__ModuleLoader__.load({
2192
2262
  gap: 8px;
2193
2263
  padding: 6px 12px;
2194
2264
  font-size: 11.5px;
2195
- color: var(--dsw-alias-state-error-primary, #e34c59);
2196
- background: color-mix(in srgb, var(--dsw-alias-state-error-primary, #e34c59) 10%, transparent);
2197
- border-bottom: 1px solid var(--dsw-alias-border-l1, rgba(118,137,166,.2));
2265
+ color: var(--dsw-alias-state-danger-primary, #e34c59);
2266
+ background: color-mix(in srgb, var(--dsw-alias-state-danger-primary, #e34c59) 10%, transparent);
2267
+ border-bottom: 0.5px solid var(--dsw-alias-border-l1);
2198
2268
  }
2199
2269
  .dsh-files-banner-close {
2200
2270
  border: none;
@@ -2202,7 +2272,8 @@ window.__ModuleLoader__.load({
2202
2272
  color: inherit;
2203
2273
  cursor: pointer;
2204
2274
  }
2205
- ` });
2275
+ `;
2276
+ document.head.appendChild(style);
2206
2277
  }
2207
2278
  //#endregion
2208
2279
  exports.WorkspaceFilesSettingsCard = WorkspaceFilesSettingsCard;