@civilization/dsh-workspace-files 0.3.1 → 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 }) {
@@ -368,23 +416,12 @@ window.__ModuleLoader__.load({
368
416
  key: OFFICIAL_FILES_TAB_ID
369
417
  }, WorkspaceFilesTabTitle)), "dsh-workspace-files: official tab title");
370
418
  }
371
- const registerSettingsCard = (targetCtx) => {
372
- if (!targetCtx?.slots) return;
373
- targetCtx.effect?.(() => targetCtx.slots.inject("settings.plugin.item", function* () {
374
- yield targetCtx.slots.register({
375
- name: "settings.plugin.item",
376
- key: "workspace-files"
377
- }, WorkspaceFilesSettingsCard);
378
- yield targetCtx.slots.register({
379
- name: "settings.plugin.item",
380
- key: "@civilization/dsh-workspace-files"
381
- }, WorkspaceFilesSettingsCard);
382
- }), "dsh-workspace-files: settings card");
383
- };
384
- if (slots) registerSettingsCard(ctx);
385
- if (ctx.inject) ctx.inject(["settingsScope"], (scoped) => {
386
- registerSettingsCard(scoped);
387
- });
419
+ if (slots) ctx.effect(() => slots.inject("settings.plugins.tab", () => slots.register({
420
+ name: "settings.plugins.tab",
421
+ id: "workspace-files",
422
+ order: 20,
423
+ label: () => "工作区文件"
424
+ }, WorkspaceFilesSettingsCard)), "dsh-workspace-files: settings card");
388
425
  }
389
426
  const CONFIG_STORAGE_KEY = "dsh_workspace_files_config";
390
427
  function loadWorkspaceFilesConfig() {
@@ -422,16 +459,16 @@ window.__ModuleLoader__.load({
422
459
  style.id = id;
423
460
  style.textContent = `
424
461
  .dsh-wf-card {
425
- border: 1px solid var(--dsw-alias-border-l2, #e5e7eb);
426
- background: var(--dsw-alias-bg-layer-3, #fff);
427
- 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);
428
465
  list-style: none;
429
- transition: border-color .16s, background .16s;
466
+ transition: border-color 0.16s, background 0.16s;
430
467
  box-sizing: border-box;
431
468
  }
432
469
  .dsh-wf-card-open {
433
- background: var(--dsw-alias-bg-layer-2, #f7f8fa);
434
- 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);
435
472
  }
436
473
  .dsh-wf-header {
437
474
  -webkit-appearance: none;
@@ -441,24 +478,24 @@ window.__ModuleLoader__.load({
441
478
  color: inherit;
442
479
  text-align: left;
443
480
  cursor: pointer;
444
- background: 0 0;
481
+ background: transparent;
445
482
  border: 0;
446
- border-radius: 12px;
483
+ border-radius: var(--dsw-radius-md, 8px);
447
484
  align-items: center;
448
485
  gap: 12px;
449
- padding: 14px 16px;
486
+ padding: 12px 14px;
450
487
  display: flex;
451
488
  }
452
489
  .dsh-wf-head-text {
453
490
  flex-direction: column;
454
491
  flex: 1;
455
- gap: 4px;
492
+ gap: 3px;
456
493
  min-width: 0;
457
494
  display: flex;
458
495
  }
459
496
  .dsh-wf-name {
460
- color: var(--dsw-alias-label-primary, #1f2328);
461
- font-size: 15px;
497
+ color: var(--dsw-alias-label-primary);
498
+ font-size: 14px;
462
499
  font-weight: 600;
463
500
  line-height: 1.4;
464
501
  display: flex;
@@ -466,38 +503,38 @@ window.__ModuleLoader__.load({
466
503
  gap: 8px;
467
504
  }
468
505
  .dsh-wf-version {
469
- font-size: 12px;
506
+ font-size: 11px;
470
507
  font-weight: 400;
471
- color: var(--dsw-alias-label-tertiary, #8b93a1);
508
+ color: var(--dsw-alias-label-tertiary);
472
509
  }
473
510
  .dsh-wf-desc {
474
- color: var(--dsw-alias-label-tertiary, #8b93a1);
475
- font-size: 13px;
511
+ color: var(--dsw-alias-label-secondary);
512
+ font-size: 12px;
476
513
  line-height: 1.5;
477
514
  }
478
515
  .dsh-wf-chevron {
479
- color: var(--dsw-alias-label-tertiary, #8b93a1);
516
+ color: var(--dsw-alias-label-tertiary);
480
517
  flex: none;
481
- transition: transform .16s ease-in-out;
518
+ transition: transform 0.18s cubic-bezier(0.16, 1, 0.3, 1);
482
519
  display: inline-flex;
483
520
  }
484
521
  .dsh-wf-chevron-open {
485
522
  transform: rotate(180deg);
486
523
  }
487
524
  .dsh-wf-body {
488
- border-top: 1px solid var(--dsw-alias-border-l2, #e5e7eb);
489
- margin: 0 16px;
525
+ border-top: 0.5px solid var(--dsw-alias-border-l2);
526
+ margin: 0 14px;
490
527
  padding: 8px 0 12px;
491
528
  }
492
529
  .dsh-wf-row {
493
530
  align-items: center;
494
531
  gap: 16px;
495
- padding: 12px 0;
532
+ padding: 10px 0;
496
533
  display: flex;
497
534
  justify-content: space-between;
498
535
  }
499
536
  .dsh-wf-row + .dsh-wf-row {
500
- 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);
501
538
  }
502
539
  .dsh-wf-label-box {
503
540
  flex-direction: column;
@@ -507,14 +544,14 @@ window.__ModuleLoader__.load({
507
544
  display: flex;
508
545
  }
509
546
  .dsh-wf-label {
510
- font-size: 13.5px;
547
+ font-size: 13px;
511
548
  font-weight: 550;
512
- color: var(--dsw-alias-label-primary, #1f2328);
549
+ color: var(--dsw-alias-label-primary);
513
550
  }
514
551
  .dsh-wf-hint {
515
- color: var(--dsw-alias-label-tertiary, #8b93a1);
516
- font-size: 12px;
517
- line-height: 18px;
552
+ color: var(--dsw-alias-label-tertiary);
553
+ font-size: 11.5px;
554
+ line-height: 16px;
518
555
  }
519
556
  .dsh-wf-ctrl {
520
557
  flex-shrink: 0;
@@ -523,56 +560,56 @@ window.__ModuleLoader__.load({
523
560
  gap: 8px;
524
561
  }
525
562
  .dsh-wf-seg {
526
- border: 1px solid var(--dsw-alias-border-l2, #e5e7eb);
527
- border-radius: 8px;
563
+ border: 0.5px solid var(--dsw-alias-border-l1);
564
+ border-radius: var(--dsw-radius-sm, 6px);
528
565
  gap: 2px;
529
566
  padding: 2px;
530
567
  display: inline-flex;
531
- background: var(--dsw-alias-bg-layer-1, rgba(255, 255, 255, 0.05));
568
+ background: var(--dsw-alias-fill-base, #ffffff);
532
569
  }
533
570
  .dsh-wf-seg-btn {
534
571
  font: inherit;
535
- color: var(--dsw-alias-label-secondary, #6b7280);
572
+ color: var(--dsw-alias-label-secondary);
536
573
  cursor: pointer;
537
- background: 0 0;
574
+ background: transparent;
538
575
  border: none;
539
- border-radius: 6px;
540
- padding: 4px 10px;
541
- font-size: 12px;
542
- line-height: 18px;
543
- 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);
544
580
  }
545
581
  .dsh-wf-seg-btn:hover {
546
- color: var(--dsw-alias-label-primary, #1f2328);
582
+ color: var(--dsw-alias-label-primary);
583
+ background: var(--dsw-alias-interactive-bg-hover);
547
584
  }
548
585
  .dsh-wf-seg-active {
549
- background: var(--dsw-alias-bg-layer-3, #eef0f4);
550
- 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);
551
588
  font-weight: 600;
552
- box-shadow: 0 1px 2px rgba(0,0,0,0.05);
553
589
  }
554
590
  .dsh-wf-input {
555
591
  box-sizing: border-box;
556
- border: 1px solid var(--dsw-alias-border-l2, #d1d5db);
557
- background: var(--dsw-alias-bg-layer-3, #fff);
558
- width: 64px;
592
+ border: 0.5px solid var(--dsw-alias-border-l1);
593
+ background: var(--dsw-alias-fill-base, #ffffff);
594
+ width: 58px;
559
595
  text-align: center;
560
- color: var(--dsw-alias-label-primary, #1f2328);
596
+ color: var(--dsw-alias-label-primary);
561
597
  font: inherit;
562
- border-radius: 7px;
563
- padding: 4px 6px;
564
- font-size: 12.5px;
565
- 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;
566
603
  }
567
604
  .dsh-wf-input:focus {
568
- border-color: var(--dsw-alias-brand-primary, #4f6ef7);
569
- 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);
570
607
  }
571
608
  .dsh-wf-toggle {
572
609
  position: relative;
573
610
  display: inline-block;
574
- width: 40px;
575
- height: 22px;
611
+ width: 36px;
612
+ height: 20px;
576
613
  cursor: pointer;
577
614
  }
578
615
  .dsh-wf-toggle input {
@@ -584,55 +621,55 @@ window.__ModuleLoader__.load({
584
621
  .dsh-wf-toggle-track {
585
622
  position: absolute;
586
623
  top: 0; left: 0; right: 0; bottom: 0;
587
- background-color: var(--dsw-alias-border-l2, #ccc);
588
- transition: .2s cubic-bezier(.4, 0, .2, 1);
589
- 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;
590
627
  }
591
628
  .dsh-wf-toggle input:checked + .dsh-wf-toggle-track {
592
- background-color: var(--dsw-alias-brand-primary, #4f6ef7);
629
+ background-color: var(--dsw-alias-state-business-primary);
593
630
  }
594
631
  .dsh-wf-toggle-thumb {
595
632
  position: absolute;
596
- height: 16px;
597
- width: 16px;
633
+ height: 14px;
634
+ width: 14px;
598
635
  left: 3px;
599
636
  bottom: 3px;
600
- background-color: white;
601
- transition: .2s cubic-bezier(.4, 0, .2, 1);
637
+ background-color: #ffffff;
638
+ transition: 0.18s cubic-bezier(0.16, 1, 0.3, 1);
602
639
  border-radius: 50%;
603
- box-shadow: 0 1px 3px rgba(0,0,0,0.2);
640
+ box-shadow: 0 1px 2px rgba(0,0,0,0.18);
604
641
  }
605
642
  .dsh-wf-toggle input:checked + .dsh-wf-toggle-track .dsh-wf-toggle-thumb {
606
- transform: translateX(18px);
643
+ transform: translateX(16px);
607
644
  }
608
645
  .dsh-wf-footer {
609
- margin-top: 8px;
610
- padding-top: 10px;
611
- 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);
612
649
  display: flex;
613
650
  align-items: center;
614
651
  justify-content: space-between;
615
652
  }
616
653
  .dsh-wf-saved-hint {
617
- font-size: 11.5px;
618
- color: var(--dsw-alias-state-success-primary, #10b981);
654
+ font-size: 11px;
655
+ color: var(--dsw-alias-state-business-primary);
619
656
  display: flex;
620
657
  align-items: center;
621
658
  gap: 4px;
622
659
  }
623
660
  .dsh-wf-btn-reset {
624
661
  background: transparent;
625
- border: 1px solid var(--dsw-alias-border-l2, #e5e7eb);
626
- border-radius: 6px;
627
- padding: 3px 10px;
628
- font-size: 12px;
629
- 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);
630
667
  cursor: pointer;
631
- transition: all 0.15s;
668
+ transition: all 0.12s;
632
669
  }
633
670
  .dsh-wf-btn-reset:hover {
634
- background: var(--dsw-alias-bg-layer-2, rgba(255,255,255,0.08));
635
- color: var(--dsw-alias-label-primary, #1f2328);
671
+ background: var(--dsw-alias-interactive-bg-hover);
672
+ color: var(--dsw-alias-label-primary);
636
673
  }
637
674
  `;
638
675
  document.head.appendChild(style);
@@ -671,32 +708,39 @@ window.__ModuleLoader__.load({
671
708
  };
672
709
  setConfig(def);
673
710
  saveWorkspaceFilesConfig(def);
674
- setSavedTick(true);
675
- setTimeout(() => setSavedTick(false), 2e3);
676
711
  };
677
712
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
678
- className: open ? "dsh-wf-card dsh-wf-card-open" : "dsh-wf-card",
713
+ className: `dsh-wf-card ${open ? "dsh-wf-card-open" : ""}`,
679
714
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
680
715
  type: "button",
681
716
  className: "dsh-wf-header",
682
- "aria-expanded": open,
683
717
  onClick: () => setOpen(!open),
684
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
685
- className: "dsh-wf-head-text",
686
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
687
- className: "dsh-wf-name",
688
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: "工作区文件" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
689
- className: "dsh-wf-version",
690
- children: "v0.3.0"
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 会话一键引用。"
691
731
  })]
692
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
693
- className: "dsh-wf-desc",
694
- children: "浏览与检索工作区文件树,支持递归目录扫描与一键引用。"
695
- })]
696
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
697
- className: open ? "dsh-wf-chevron dsh-wf-chevron-open" : "dsh-wf-chevron",
698
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconChevronDown, { size: 14 })
699
- })]
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
+ ]
700
744
  }), open && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
701
745
  className: "dsh-wf-body",
702
746
  children: [
@@ -704,12 +748,12 @@ window.__ModuleLoader__.load({
704
748
  className: "dsh-wf-row",
705
749
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
706
750
  className: "dsh-wf-label-box",
707
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
751
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
708
752
  className: "dsh-wf-label",
709
- children: "目录扫描最大深度"
710
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
753
+ children: "扫描最大深度 (层级)"
754
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
711
755
  className: "dsh-wf-hint",
712
- children: "工作区递归扫描的最大目录层级(默认 16,范围 1~100)。若工程目录较深可适当调大。"
756
+ children: "控制文件树深入遍历的最大文件夹嵌套层级,防止庞大项目深度过大产生卡顿。"
713
757
  })]
714
758
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
715
759
  className: "dsh-wf-ctrl",
@@ -718,22 +762,22 @@ window.__ModuleLoader__.load({
718
762
  children: [
719
763
  8,
720
764
  16,
721
- 32,
722
- 64
723
- ].map((d) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
765
+ 24,
766
+ 32
767
+ ].map((d) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
724
768
  type: "button",
725
- 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" : ""}`,
726
770
  onClick: () => handleDepthSelect(d),
727
- children: d
771
+ children: [d, " 层"]
728
772
  }, d))
729
773
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
730
774
  type: "number",
731
- min: "1",
732
- max: "100",
775
+ min: 1,
776
+ max: 100,
733
777
  className: "dsh-wf-input",
734
778
  value: config.maxDepth,
735
779
  onChange: handleDepthInput,
736
- title: "自定义深度 (1-100)"
780
+ title: "手动输入层级深度 (1-100)"
737
781
  })]
738
782
  })]
739
783
  }),
@@ -741,12 +785,12 @@ window.__ModuleLoader__.load({
741
785
  className: "dsh-wf-row",
742
786
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
743
787
  className: "dsh-wf-label-box",
744
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
788
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
745
789
  className: "dsh-wf-label",
746
- children: "默认显示隐藏文件"
747
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
790
+ children: "显示以点开头的隐藏文件"
791
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
748
792
  className: "dsh-wf-hint",
749
- children: "打开文件树时是否默认展示以点开头的隐藏文件或文件夹(如 .gitignore, .env 等)。"
793
+ children: "开启后,文件树中将展现如 .env, .editorconfig 等以点开头的配置文件(.git 等缓存黑名单除外)。"
750
794
  })]
751
795
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
752
796
  className: "dsh-wf-ctrl",
@@ -765,15 +809,9 @@ window.__ModuleLoader__.load({
765
809
  }),
766
810
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
767
811
  className: "dsh-wf-footer",
768
- 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", {
769
813
  className: "dsh-wf-saved-hint",
770
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconCheck, { size: 12 }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: "已保存设置" })]
771
- }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
772
- style: {
773
- fontSize: 11,
774
- color: "var(--dsw-alias-label-tertiary, #8b93a1)"
775
- },
776
- children: "设置改动即时生效并同步至工作区文件树"
814
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconCheck, { size: 12 }), "配置已自动保存并实时同步"]
777
815
  }) }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
778
816
  type: "button",
779
817
  className: "dsh-wf-btn-reset",
@@ -785,21 +823,85 @@ window.__ModuleLoader__.load({
785
823
  })]
786
824
  });
787
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
+ }
788
885
  function WorkspaceFilesView({ sessionId, cwd, onOpenFile }) {
789
886
  const [data, setData] = (0, react.useState)(null);
790
887
  const [loading, setLoading] = (0, react.useState)(true);
791
888
  const [error, setError] = (0, react.useState)(null);
792
- const [query, setQuery] = (0, react.useState)("");
889
+ const [inputQuery, setInputQuery] = (0, react.useState)("");
793
890
  const [toast, setToast] = (0, react.useState)(null);
794
891
  const [expandedPaths, setExpandedPaths] = (0, react.useState)(() => /* @__PURE__ */ new Set());
795
892
  const [activeConfig, setActiveConfig] = (0, react.useState)(() => loadWorkspaceFilesConfig());
796
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());
797
896
  const toastTimer = (0, react.useRef)(null);
798
897
  const showToastMsg = (0, react.useCallback)((msg) => {
799
898
  setToast(msg);
800
899
  if (toastTimer.current) window.clearTimeout(toastTimer.current);
801
900
  toastTimer.current = window.setTimeout(() => setToast(null), 2e3);
802
901
  }, []);
902
+ (0, react.useEffect)(() => {
903
+ ensureFilesStyle();
904
+ }, []);
803
905
  (0, react.useEffect)(() => {
804
906
  const handleCfgChange = (e) => {
805
907
  if (e.detail) {
@@ -842,7 +944,7 @@ window.__ModuleLoader__.load({
842
944
  (0, react.useEffect)(() => {
843
945
  loadTree();
844
946
  }, [loadTree]);
845
- const handleToggleExpand = (path) => {
947
+ const handleToggleExpand = (0, react.useCallback)((path) => {
846
948
  setExpandedPaths((prev) => {
847
949
  const next = new Set(prev);
848
950
  if (next.has(path)) next.delete(path);
@@ -850,8 +952,8 @@ window.__ModuleLoader__.load({
850
952
  saveStoredExpandedPaths(data?.root || cwd, next);
851
953
  return next;
852
954
  });
853
- };
854
- const handleExpandAll = () => {
955
+ }, [data?.root, cwd]);
956
+ const handleExpandAll = (0, react.useCallback)(() => {
855
957
  if (!data) return;
856
958
  const all = /* @__PURE__ */ new Set();
857
959
  function collect(items) {
@@ -863,13 +965,13 @@ window.__ModuleLoader__.load({
863
965
  collect(data.items);
864
966
  setExpandedPaths(all);
865
967
  saveStoredExpandedPaths(data.root || cwd, all);
866
- };
867
- const handleCollapseAll = () => {
968
+ }, [data, cwd]);
969
+ const handleCollapseAll = (0, react.useCallback)(() => {
868
970
  const empty = /* @__PURE__ */ new Set();
869
971
  setExpandedPaths(empty);
870
972
  saveStoredExpandedPaths(data?.root || cwd, empty);
871
- };
872
- const handleJumpToFolderInTree = (dirPath) => {
973
+ }, [data?.root, cwd]);
974
+ const handleJumpToFolderInTree = (0, react.useCallback)((dirPath) => {
873
975
  const parts = dirPath.split("/");
874
976
  const toExpand = [];
875
977
  let acc = "";
@@ -884,7 +986,7 @@ window.__ModuleLoader__.load({
884
986
  saveStoredExpandedPaths(data?.root || cwd, next);
885
987
  return next;
886
988
  });
887
- setQuery("");
989
+ setInputQuery("");
888
990
  showToastMsg(`已定位并展开目录: ${dirPath}/`);
889
991
  setTimeout(() => {
890
992
  try {
@@ -895,14 +997,18 @@ window.__ModuleLoader__.load({
895
997
  });
896
998
  } catch {}
897
999
  }, 60);
898
- };
899
- const handleCopyPath = (e, path) => {
1000
+ }, [
1001
+ data?.root,
1002
+ cwd,
1003
+ showToastMsg
1004
+ ]);
1005
+ const handleCopyPath = (0, react.useCallback)((e, path) => {
900
1006
  e.stopPropagation();
901
1007
  navigator.clipboard.writeText(path).then(() => {
902
1008
  showToastMsg(`已复制路径: ${path}`);
903
1009
  });
904
- };
905
- const handleMention = (e, itemOrPath) => {
1010
+ }, [showToastMsg]);
1011
+ const handleMention = (0, react.useCallback)((e, itemOrPath) => {
906
1012
  e.stopPropagation();
907
1013
  const itemObj = typeof itemOrPath === "string" ? {
908
1014
  name: itemOrPath.split("/").pop() || itemOrPath,
@@ -913,21 +1019,17 @@ window.__ModuleLoader__.load({
913
1019
  let inserted = false;
914
1020
  try {
915
1021
  inserted = tryInsertNativeReferenceChip(globalCtx, sessionId, itemObj);
916
- } catch (err) {
917
- console.warn("[dsh-workspace-files] 原生 Chip 插入失败:", err);
918
- }
1022
+ } catch {}
919
1023
  if (!inserted) try {
920
1024
  inserted = insertMentionToComposer(mentionText);
921
- } catch (err) {
922
- console.warn("[dsh-workspace-files] 降级纯文本插入失败:", err);
923
- }
1025
+ } catch {}
924
1026
  const displayName = itemObj.isDirectory ? `${itemObj.name}/` : itemObj.name;
925
1027
  navigator.clipboard.writeText(mentionText.trim()).then(() => {
926
1028
  if (inserted) showToastMsg(`已引用${itemObj.isDirectory ? "目录" : "文件"}: ${displayName}`);
927
1029
  else showToastMsg(`已复制引用: ${mentionText.trim()}`);
928
1030
  });
929
- };
930
- const handleRevealInExplorer = (e, item) => {
1031
+ }, [sessionId, showToastMsg]);
1032
+ const handleRevealInExplorer = (0, react.useCallback)((e, item) => {
931
1033
  e.stopPropagation();
932
1034
  fetch("/dsh-workspace-files/api/files.open", {
933
1035
  method: "POST",
@@ -945,8 +1047,12 @@ window.__ModuleLoader__.load({
945
1047
  }).catch((err) => {
946
1048
  showToastMsg(`请求失败: ${err?.message || String(err)}`);
947
1049
  });
948
- };
949
- const handleOpenDefaultApp = (e, item) => {
1050
+ }, [
1051
+ sessionId,
1052
+ cwd,
1053
+ showToastMsg
1054
+ ]);
1055
+ const handleOpenDefaultApp = (0, react.useCallback)((e, item) => {
950
1056
  e.stopPropagation();
951
1057
  fetch("/dsh-workspace-files/api/files.open", {
952
1058
  method: "POST",
@@ -964,76 +1070,51 @@ window.__ModuleLoader__.load({
964
1070
  }).catch((err) => {
965
1071
  showToastMsg(`请求失败: ${err?.message || String(err)}`);
966
1072
  });
967
- };
968
- const [searchViewMode, setSearchViewMode] = (0, react.useState)("flat");
969
- const [searchExpandedPaths, setSearchExpandedPaths] = (0, react.useState)(() => /* @__PURE__ */ new Set());
970
- const { filteredTreeItems, flatSearchResults } = (0, react.useMemo)(() => {
971
- if (!data) return {
972
- filteredTreeItems: [],
973
- flatSearchResults: []
974
- };
975
- const q = query.trim().toLowerCase();
976
- if (!q) return {
977
- filteredTreeItems: data.items,
978
- flatSearchResults: []
979
- };
980
- const flat = [];
981
- 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) {
982
1083
  for (const it of items) {
983
- if (it.name.toLowerCase().includes(q) || it.path.toLowerCase().includes(q)) flat.push({
984
- item: it,
985
- parentDir
986
- });
987
- if (it.isDirectory && it.children) traverseFlat(it.children, it.path);
988
- }
989
- }
990
- traverseFlat(data.items, "");
991
- function filterNode(node) {
992
- const selfMatch = node.name.toLowerCase().includes(q) || node.path.toLowerCase().includes(q);
993
- if (node.isDirectory) {
994
- const filteredChildren = [];
995
- for (const child of node.children || []) {
996
- const matchedChild = filterNode(child);
997
- 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;
998
1094
  }
999
- if (selfMatch || filteredChildren.length > 0) return {
1000
- ...node,
1001
- children: filteredChildren
1002
- };
1003
- return null;
1004
- }
1005
- return selfMatch ? node : null;
1006
- }
1007
- const tree = [];
1008
- for (const rootNode of data.items) {
1009
- const matched = filterNode(rootNode);
1010
- if (matched) tree.push(matched);
1011
- }
1012
- return {
1013
- filteredTreeItems: tree,
1014
- flatSearchResults: flat
1015
- };
1016
- }, [data, query]);
1017
- (0, react.useEffect)(() => {
1018
- if (!query.trim() || !data) return;
1019
- const q = query.trim().toLowerCase();
1020
- const autoExpand = /* @__PURE__ */ new Set();
1021
- function collect(items) {
1022
- for (const it of items) if (it.isDirectory) {
1023
- const selfMatch = it.name.toLowerCase().includes(q) || it.path.toLowerCase().includes(q);
1024
- const childMatch = it.children?.some((c) => c.name.toLowerCase().includes(q) || c.path.toLowerCase().includes(q));
1025
- if (selfMatch || childMatch) autoExpand.add(it.path);
1026
- if (it.children) collect(it.children);
1027
1095
  }
1028
1096
  }
1029
- collect(data.items);
1030
- setSearchExpandedPaths(autoExpand);
1031
- }, [query, data]);
1032
- 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
+ ]);
1033
1115
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1034
1116
  className: "dsh-files-root",
1035
1117
  children: [
1036
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(GlobalFilesStyle, {}),
1037
1118
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("header", {
1038
1119
  className: "dsh-files-header",
1039
1120
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
@@ -1042,7 +1123,7 @@ window.__ModuleLoader__.load({
1042
1123
  className: "dsh-files-title-row",
1043
1124
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1044
1125
  className: "dsh-files-title",
1045
- children: "文件"
1126
+ children: "工作区文件"
1046
1127
  }), data && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
1047
1128
  className: "dsh-files-stats-badge",
1048
1129
  children: [
@@ -1071,18 +1152,18 @@ window.__ModuleLoader__.load({
1071
1152
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
1072
1153
  type: "text",
1073
1154
  className: "dsh-files-search-input",
1074
- placeholder: "搜索文件 (支持路径筛选)...",
1075
- value: query,
1076
- onChange: (e) => setQuery(e.target.value),
1155
+ placeholder: "搜索文件或路径 (Esc 清空)...",
1156
+ value: inputQuery,
1157
+ onChange: (e) => setInputQuery(e.target.value),
1077
1158
  onKeyDown: (e) => {
1078
- if (e.key === "Escape") setQuery("");
1159
+ if (e.key === "Escape") setInputQuery("");
1079
1160
  }
1080
1161
  }),
1081
- query && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1162
+ inputQuery && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1082
1163
  type: "button",
1083
1164
  className: "dsh-files-clear-btn",
1084
- onClick: () => setQuery(""),
1085
- title: "清除搜索",
1165
+ onClick: () => setInputQuery(""),
1166
+ title: "清空搜索",
1086
1167
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconClose, { size: 12 })
1087
1168
  })
1088
1169
  ]
@@ -1093,29 +1174,29 @@ window.__ModuleLoader__.load({
1093
1174
  type: "button",
1094
1175
  className: "dsh-files-tool-btn is-active",
1095
1176
  onClick: () => setSearchViewMode(searchViewMode === "flat" ? "tree" : "flat"),
1096
- title: searchViewMode === "flat" ? "当前为扁平列表,点击切换为树形视图" : "当前为树形视图,点击切换为扁平列表",
1177
+ title: searchViewMode === "flat" ? "切为树形匹配视图" : "切为扁平列表视图",
1097
1178
  children: searchViewMode === "flat" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconTree, { size: 13 }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconList, { size: 13 })
1098
1179
  }) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1099
1180
  type: "button",
1100
1181
  className: "dsh-files-tool-btn",
1101
1182
  onClick: handleExpandAll,
1102
- title: "全部展开",
1183
+ title: "展开全部目录",
1103
1184
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconExpandAll, { size: 13 })
1104
1185
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1105
1186
  type: "button",
1106
1187
  className: "dsh-files-tool-btn",
1107
1188
  onClick: handleCollapseAll,
1108
- title: "全部折叠",
1189
+ title: "折叠全部目录",
1109
1190
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconCollapseAll, { size: 13 })
1110
1191
  })] }),
1111
1192
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1112
1193
  type: "button",
1113
1194
  className: `dsh-files-tool-btn ${showHidden ? "is-active" : ""}`,
1114
1195
  onClick: () => setShowHidden(!showHidden),
1115
- title: showHidden ? "隐藏点号开头的文件" : "显示点号开头的文件",
1196
+ title: showHidden ? "隐藏以点开头的文件" : "显示以点开头的文件",
1116
1197
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1117
1198
  style: {
1118
- fontSize: 11,
1199
+ fontSize: 10.5,
1119
1200
  fontWeight: 700
1120
1201
  },
1121
1202
  children: ".*"
@@ -1145,21 +1226,21 @@ window.__ModuleLoader__.load({
1145
1226
  className: "dsh-files-body",
1146
1227
  children: loading && !data ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1147
1228
  className: "dsh-files-centered",
1148
- 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: "正在索引工作区文件…" })]
1149
1230
  }) : isSearchActive && flatSearchResults.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1150
1231
  className: "dsh-files-empty",
1151
1232
  children: [
1152
1233
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1153
1234
  className: "dsh-files-empty-icon",
1154
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconFolder, { size: 26 })
1235
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconFolder, { size: 28 })
1155
1236
  }),
1156
1237
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1157
1238
  className: "dsh-files-empty-title",
1158
- children: "未搜索到匹配的文件"
1239
+ children: "未匹配到相关文件"
1159
1240
  }),
1160
1241
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1161
1242
  className: "dsh-files-empty-detail",
1162
- children: "请尝试更换搜索关键字,或按 Esc 清除搜索。"
1243
+ children: "请尝试更换关键字或按 Esc 恢复完整目录树。"
1163
1244
  })
1164
1245
  ]
1165
1246
  }) : !isSearchActive && (!data || data.items.length === 0) ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
@@ -1167,7 +1248,7 @@ window.__ModuleLoader__.load({
1167
1248
  children: [
1168
1249
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1169
1250
  className: "dsh-files-empty-icon",
1170
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconFolder, { size: 26 })
1251
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconFolder, { size: 28 })
1171
1252
  }),
1172
1253
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1173
1254
  className: "dsh-files-empty-title",
@@ -1175,7 +1256,7 @@ window.__ModuleLoader__.load({
1175
1256
  }),
1176
1257
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1177
1258
  className: "dsh-files-empty-detail",
1178
- children: "当前工作目录下暂无可显示的文件。"
1259
+ children: "当前工作目录下暂无可展示的文件。"
1179
1260
  })
1180
1261
  ]
1181
1262
  }) : isSearchActive && searchViewMode === "flat" ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
@@ -1188,24 +1269,24 @@ window.__ModuleLoader__.load({
1188
1269
  "找到 ",
1189
1270
  flatSearchResults.length,
1190
1271
  " 个匹配项",
1191
- flatSearchResults.length > 150 ? "(展示前 150 项)" : ""
1272
+ flatSearchResults.length > 150 ? "(已展示前 150 项)" : ""
1192
1273
  ]
1193
1274
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
1194
1275
  type: "button",
1195
1276
  className: "dsh-files-view-toggle-btn",
1196
1277
  onClick: () => setSearchViewMode("tree"),
1197
- title: "切换为可折叠的树形视图",
1278
+ title: "切换为树形视图",
1198
1279
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconTree, { size: 12 }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: "切为树形" })]
1199
1280
  })]
1200
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1281
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1201
1282
  className: "dsh-files-flat-list",
1202
- 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", {
1203
1284
  className: `dsh-files-flat-row ${item.isDirectory ? "is-directory" : ""}`,
1204
1285
  onClick: () => {
1205
1286
  if (item.isDirectory) handleJumpToFolderInTree(item.path);
1206
1287
  else onOpenFile(item.path);
1207
1288
  },
1208
- title: item.isDirectory ? `点击退出搜索并定位展开目录: ${item.path}/` : `点击预览打开文件: ${item.path}`,
1289
+ title: item.isDirectory ? `点击定位并展开目录: ${item.path}/` : `点击预览打开: ${item.path}`,
1209
1290
  children: [
1210
1291
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1211
1292
  className: "dsh-files-flat-icon",
@@ -1223,7 +1304,7 @@ window.__ModuleLoader__.load({
1223
1304
  className: "dsh-files-flat-name",
1224
1305
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(HighlightText, {
1225
1306
  text: item.name,
1226
- query
1307
+ query: deferredQuery
1227
1308
  }), item.isDirectory && "/"]
1228
1309
  }),
1229
1310
  item.size !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
@@ -1248,8 +1329,8 @@ window.__ModuleLoader__.load({
1248
1329
  type: "button",
1249
1330
  className: "dsh-files-action-btn dsh-files-action-at",
1250
1331
  onClick: (e) => handleMention(e, item),
1251
- title: `一键 @ 引用此${item.isDirectory ? "目录" : "文件"}到当前会话`,
1252
- 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", {
1253
1334
  className: "dsh-files-action-at-text",
1254
1335
  children: "@引用"
1255
1336
  })]
@@ -1258,14 +1339,14 @@ window.__ModuleLoader__.load({
1258
1339
  type: "button",
1259
1340
  className: "dsh-files-action-btn",
1260
1341
  onClick: (e) => handleRevealInExplorer(e, item),
1261
- title: `在文件资源管理器中显示此${item.isDirectory ? "目录" : "文件"}`,
1342
+ title: "在文件资源管理器中显示",
1262
1343
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconExplorer, { size: 12 })
1263
1344
  }),
1264
1345
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1265
1346
  type: "button",
1266
1347
  className: "dsh-files-action-btn",
1267
1348
  onClick: (e) => handleOpenDefaultApp(e, item),
1268
- title: `用系统默认应用打开此${item.isDirectory ? "目录" : "文件"}`,
1349
+ title: "用系统默认应用打开",
1269
1350
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconExternalApp, { size: 12 })
1270
1351
  }),
1271
1352
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
@@ -1278,24 +1359,19 @@ window.__ModuleLoader__.load({
1278
1359
  ]
1279
1360
  })
1280
1361
  ]
1281
- }, item.path)), flatSearchResults.length > 150 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1282
- style: {
1283
- padding: "10px 14px",
1284
- fontSize: 11,
1285
- textAlign: "center",
1286
- color: "var(--dsw-alias-label-tertiary, #8b93a1)",
1287
- borderTop: "1px dashed var(--dsw-alias-border-l2, #e5e7eb)"
1288
- },
1289
- children: "匹配项较多,已限制展示前 150 项以保证流畅度,请输入更详细关键字"
1290
- })]
1362
+ }, item.path))
1291
1363
  })]
1292
1364
  }) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1293
1365
  className: "dsh-files-tree",
1294
1366
  children: [isSearchActive && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1295
1367
  className: "dsh-files-search-header",
1296
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1368
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
1297
1369
  className: "dsh-files-search-count",
1298
- children: "树形匹配(自由折叠/展开)"
1370
+ children: [
1371
+ "树形匹配(共 ",
1372
+ visibleFlatRows.length,
1373
+ " 项)"
1374
+ ]
1299
1375
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
1300
1376
  type: "button",
1301
1377
  className: "dsh-files-view-toggle-btn",
@@ -1303,27 +1379,16 @@ window.__ModuleLoader__.load({
1303
1379
  title: "切换为扁平搜索结果列表",
1304
1380
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconList, { size: 12 }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: "切为列表" })]
1305
1381
  })]
1306
- }), filteredTreeItems.map((item) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FileTreeNode, {
1307
- item,
1308
- depth: 0,
1309
- query,
1310
- isSearchMode: isSearchActive,
1311
- expandedPaths: isSearchActive ? searchExpandedPaths : expandedPaths,
1312
- onToggleExpand: (path) => {
1313
- if (isSearchActive) setSearchExpandedPaths((prev) => {
1314
- const next = new Set(prev);
1315
- if (next.has(path)) next.delete(path);
1316
- else next.add(path);
1317
- return next;
1318
- });
1319
- else handleToggleExpand(path);
1320
- },
1382
+ }), visibleFlatRows.map((row) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FileTreeRow, {
1383
+ row,
1384
+ query: deferredQuery,
1385
+ onToggleExpand: handleToggleExpand,
1321
1386
  onOpenFile,
1322
1387
  onMention: handleMention,
1323
- onCopyPath: handleCopyPath,
1324
1388
  onRevealInExplorer: handleRevealInExplorer,
1325
- onOpenDefaultApp: handleOpenDefaultApp
1326
- }, item.path))]
1389
+ onOpenDefaultApp: handleOpenDefaultApp,
1390
+ onCopyPath: handleCopyPath
1391
+ }, row.id))]
1327
1392
  })
1328
1393
  }),
1329
1394
  toast && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
@@ -1333,120 +1398,101 @@ window.__ModuleLoader__.load({
1333
1398
  ]
1334
1399
  });
1335
1400
  }
1336
- function FileTreeNode(props) {
1337
- const { item, depth, query, isSearchMode, expandedPaths, onToggleExpand, onOpenFile, onMention, onCopyPath, onRevealInExplorer, onOpenDefaultApp } = props;
1338
- const isExpanded = expandedPaths.has(item.path);
1339
- if (item.isDirectory) {
1340
- const childCount = item.children?.length ?? 0;
1341
- return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1342
- className: "dsh-files-dir-block",
1343
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1344
- className: "dsh-files-dir-row",
1345
- "data-tree-path": item.path,
1346
- style: { paddingLeft: `${depth * 14 + 10}px` },
1347
- 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",
1348
1435
  children: [
1349
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1350
- className: "dsh-files-chevron",
1351
- "data-collapsed": !isExpanded ? "true" : void 0,
1352
- children: "▾"
1353
- }),
1354
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1355
- className: "dsh-files-folder-icon",
1356
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconFolder, {
1357
- size: 14,
1358
- open: isExpanded
1359
- })
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
+ })]
1360
1445
  }),
1361
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1362
- className: "dsh-files-folder-name",
1363
- title: item.path,
1364
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(HighlightText, {
1365
- text: item.name,
1366
- query
1367
- })
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 })
1368
1452
  }),
1369
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1370
- className: "dsh-files-count-badge",
1371
- 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 })
1372
1459
  }),
1373
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1374
- className: "dsh-files-row-actions",
1375
- children: [
1376
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
1377
- type: "button",
1378
- className: "dsh-files-action-btn dsh-files-action-at",
1379
- onClick: (e) => onMention(e, item),
1380
- title: "一键 @ 引用此目录到当前会话",
1381
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconAt, { size: 13 }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1382
- className: "dsh-files-action-at-text",
1383
- children: "@引用"
1384
- })]
1385
- }),
1386
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1387
- type: "button",
1388
- className: "dsh-files-action-btn",
1389
- onClick: (e) => onRevealInExplorer(e, item),
1390
- title: "在文件资源管理器中打开此目录",
1391
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconExplorer, { size: 12 })
1392
- }),
1393
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1394
- type: "button",
1395
- className: "dsh-files-action-btn",
1396
- onClick: (e) => onOpenDefaultApp(e, item),
1397
- title: "用系统默认应用打开此目录",
1398
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconExternalApp, { size: 12 })
1399
- }),
1400
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1401
- type: "button",
1402
- className: "dsh-files-action-btn",
1403
- onClick: (e) => onCopyPath(e, item.path),
1404
- title: "复制目录路径",
1405
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconCopy, { size: 12 })
1406
- })
1407
- ]
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 })
1408
1466
  })
1409
1467
  ]
1410
- }), isExpanded && item.children && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1411
- className: "dsh-files-children",
1412
- children: item.children.map((child) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FileTreeNode, {
1413
- item: child,
1414
- depth: depth + 1,
1415
- query,
1416
- isSearchMode,
1417
- expandedPaths,
1418
- onToggleExpand,
1419
- onOpenFile,
1420
- onMention,
1421
- onCopyPath,
1422
- onRevealInExplorer,
1423
- onOpenDefaultApp
1424
- }, child.path))
1425
- })]
1426
- });
1427
- }
1468
+ })
1469
+ ]
1470
+ });
1428
1471
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1429
1472
  className: "dsh-files-row",
1430
- "data-tree-path": item.path,
1431
- style: { paddingLeft: `${depth * 14 + 10}px` },
1432
- onClick: () => onOpenFile(item.path),
1433
- title: `点击打开: ${item.path}`,
1473
+ "data-tree-path": row.path,
1474
+ style: { paddingLeft: `${indentPx}px` },
1475
+ onClick: () => onOpenFile(row.path),
1476
+ title: `点击打开文件: ${row.path}`,
1434
1477
  children: [
1435
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FileGlyphIcon, {
1436
- filename: item.name,
1437
- 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
+ })
1438
1484
  }),
1439
1485
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1440
1486
  className: "dsh-files-name",
1441
1487
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(HighlightText, {
1442
- text: item.name,
1488
+ text: row.name,
1443
1489
  query
1444
1490
  })
1445
1491
  }),
1446
- item.size !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1492
+ row.size !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1447
1493
  className: "dsh-files-size",
1448
- title: `大小: ${item.size} 字节`,
1449
- children: formatFileSize(item.size)
1494
+ title: `大小: ${row.size} 字节`,
1495
+ children: formatFileSize(row.size)
1450
1496
  }),
1451
1497
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1452
1498
  className: "dsh-files-row-actions",
@@ -1454,9 +1500,9 @@ window.__ModuleLoader__.load({
1454
1500
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
1455
1501
  type: "button",
1456
1502
  className: "dsh-files-action-btn dsh-files-action-at",
1457
- onClick: (e) => onMention(e, item),
1458
- title: "一键 @ 引用此文件到当前会话",
1459
- 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", {
1460
1506
  className: "dsh-files-action-at-text",
1461
1507
  children: "@引用"
1462
1508
  })]
@@ -1464,21 +1510,21 @@ window.__ModuleLoader__.load({
1464
1510
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1465
1511
  type: "button",
1466
1512
  className: "dsh-files-action-btn",
1467
- onClick: (e) => onRevealInExplorer(e, item),
1468
- title: "在文件资源管理器中显示此文件",
1513
+ onClick: (e) => onRevealInExplorer(e, row.item),
1514
+ title: "在文件资源管理器中定位",
1469
1515
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconExplorer, { size: 12 })
1470
1516
  }),
1471
1517
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1472
1518
  type: "button",
1473
1519
  className: "dsh-files-action-btn",
1474
- onClick: (e) => onOpenDefaultApp(e, item),
1475
- title: "用系统默认应用打开此文件",
1520
+ onClick: (e) => onOpenDefaultApp(e, row.item),
1521
+ title: "用系统默认应用打开",
1476
1522
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconExternalApp, { size: 12 })
1477
1523
  }),
1478
1524
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1479
1525
  type: "button",
1480
1526
  className: "dsh-files-action-btn",
1481
- onClick: (e) => onCopyPath(e, item.path),
1527
+ onClick: (e) => onCopyPath(e, row.path),
1482
1528
  title: "复制相对路径",
1483
1529
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconCopy, { size: 12 })
1484
1530
  })
@@ -1486,15 +1532,16 @@ window.__ModuleLoader__.load({
1486
1532
  })
1487
1533
  ]
1488
1534
  });
1489
- }
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
+ });
1490
1538
  function HighlightText({ text, query }) {
1491
- const q = query.trim().toLowerCase();
1492
- if (!q) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: text });
1493
- 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);
1494
1541
  if (index === -1) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: text });
1495
1542
  const before = text.slice(0, index);
1496
- const match = text.slice(index, index + q.length);
1497
- const after = text.slice(index + q.length);
1543
+ const match = text.slice(index, index + query.length);
1544
+ const after = text.slice(index + query.length);
1498
1545
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [
1499
1546
  before,
1500
1547
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("mark", {
@@ -1510,12 +1557,6 @@ window.__ModuleLoader__.load({
1510
1557
  if (kb < 1024) return `${kb.toFixed(1)} KB`;
1511
1558
  return `${(kb / 1024).toFixed(1)} MB`;
1512
1559
  }
1513
- /**
1514
- * 按照 DSH 官方规范格式化引用路径:
1515
- * - 纯路径无空格:@path
1516
- * - 路径含空格:@"path"
1517
- * - 目录末尾保留斜杠:@folder/ 或 @"folder/"
1518
- */
1519
1560
  function formatMentionText(path, isDirectory = false) {
1520
1561
  const cleanPath = path.replace(/\\/g, "/").replace(/^\.?\//, "");
1521
1562
  const finalPath = isDirectory ? cleanPath.endsWith("/") ? cleanPath : `${cleanPath}/` : cleanPath;
@@ -1541,9 +1582,6 @@ window.__ModuleLoader__.load({
1541
1582
  window.localStorage.setItem(getStorageKey(workspaceRoot), JSON.stringify(Array.from(paths)));
1542
1583
  } catch {}
1543
1584
  }
1544
- /**
1545
- * 从当前 DOM 的 React Fiber 树或 Cordis RootContext 中提取当前活跃输入框的 SessionInputShell 实例
1546
- */
1547
1585
  function findComposerShell(ctx, sessionId) {
1548
1586
  try {
1549
1587
  const composerDom = document.querySelector("[data-composer-input=\"true\"], [data-composer-input], [data-composer-card], div[role=\"textbox\"][contenteditable=\"true\"]");
@@ -1563,9 +1601,7 @@ window.__ModuleLoader__.load({
1563
1601
  }
1564
1602
  }
1565
1603
  }
1566
- } catch (e) {
1567
- console.debug("[dsh-workspace-files] 从 Fiber 查找 keyboard 失败:", e);
1568
- }
1604
+ } catch {}
1569
1605
  if (ctx) try {
1570
1606
  const root = ctx.root || ctx;
1571
1607
  const inputService = (root.conversation || root.get?.("conversation") || window.__dsh_conversation)?.input || root["conversation.input"] || root.get?.("conversation.input");
@@ -1579,14 +1615,9 @@ window.__ModuleLoader__.load({
1579
1615
  return values[values.length - 1];
1580
1616
  }
1581
1617
  }
1582
- } catch (e) {
1583
- console.debug("[dsh-workspace-files] 从 RootContext 查找 shell 失败:", e);
1584
- }
1618
+ } catch {}
1585
1619
  return null;
1586
1620
  }
1587
- /**
1588
- * 尝试向会话输入框插入原生的 ReferenceChipNode(官方胶囊 Tag 卡片)
1589
- */
1590
1621
  function tryInsertNativeReferenceChip(ctx, sessionId, item) {
1591
1622
  if (typeof document === "undefined") return false;
1592
1623
  try {
@@ -1623,16 +1654,9 @@ window.__ModuleLoader__.load({
1623
1654
  span
1624
1655
  }) === true) return true;
1625
1656
  }
1626
- } catch (err) {
1627
- console.debug("[dsh-workspace-files] 插入原生 Chip 异常:", err);
1628
- }
1657
+ } catch {}
1629
1658
  return false;
1630
1659
  }
1631
- /**
1632
- * 将引用文本注入到 DSH 当前会话的主输入框。
1633
- * 兼容 DSH 官方基于 Lexical 的 ComposerContentEditable (div[data-composer-input])
1634
- * 以及传统的 textarea / input,并自动消除用户手动输入的冗余 '@'。
1635
- */
1636
1660
  function insertMentionToComposer(mentionText) {
1637
1661
  if (typeof document === "undefined") return false;
1638
1662
  const target = [
@@ -1733,16 +1757,21 @@ window.__ModuleLoader__.load({
1733
1757
  if (!response.ok || envelope?.ok !== true || envelope.value === void 0) throw new Error(envelope?.error?.message ?? `HTTP ${response.status}`);
1734
1758
  return envelope.value;
1735
1759
  }
1736
- function GlobalFilesStyle() {
1737
- 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 = `
1738
1767
  .dsh-files-root {
1739
1768
  display: flex;
1740
1769
  flex-direction: column;
1741
1770
  height: 100%;
1742
1771
  min-height: 0;
1743
1772
  box-sizing: border-box;
1744
- background: var(--dsw-alias-bg-base, #ffffff);
1745
- color: var(--dsw-alias-label-primary, #17233c);
1773
+ background: var(--dsw-alias-fill-base, #ffffff);
1774
+ color: var(--dsw-alias-label-primary);
1746
1775
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
1747
1776
  font-size: 12px;
1748
1777
  line-height: 1.4;
@@ -1758,7 +1787,8 @@ window.__ModuleLoader__.load({
1758
1787
  justify-content: space-between;
1759
1788
  gap: 8px;
1760
1789
  padding: 8px 12px;
1761
- 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);
1762
1792
  }
1763
1793
  .dsh-files-header-info {
1764
1794
  flex: 1;
@@ -1772,33 +1802,34 @@ window.__ModuleLoader__.load({
1772
1802
  .dsh-files-title {
1773
1803
  font-weight: 600;
1774
1804
  font-size: 13px;
1775
- color: var(--dsw-alias-label-primary, inherit);
1805
+ color: var(--dsw-alias-label-primary);
1776
1806
  }
1777
1807
  .dsh-files-stats-badge {
1778
1808
  font-size: 10px;
1779
1809
  font-weight: 500;
1780
- color: var(--dsw-alias-label-tertiary, #8c9ba5);
1781
- background: var(--dsw-alias-interactive-bg-hover, rgba(100,120,150,.1));
1782
- 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;
1783
1813
  border-radius: 99px;
1784
1814
  }
1785
1815
  .dsh-files-root-path {
1786
1816
  font-size: 11px;
1787
- color: var(--dsw-alias-label-tertiary, #8c9ba5);
1817
+ color: var(--dsw-alias-label-tertiary);
1788
1818
  overflow: hidden;
1789
1819
  text-overflow: ellipsis;
1790
1820
  white-space: nowrap;
1791
- margin-top: 1px;
1821
+ margin-top: 2px;
1792
1822
  }
1793
1823
 
1794
- /* ── Toolbar & Search ── */
1824
+ /* ── Toolbar & Pure White Input ── */
1795
1825
  .dsh-files-toolbar {
1796
1826
  display: flex;
1797
1827
  align-items: center;
1798
1828
  gap: 6px;
1799
- padding: 6px 8px 6px 12px;
1800
- border-bottom: 1px solid var(--dsw-alias-border-l1, rgba(118,137,166,.15));
1801
- 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;
1802
1833
  }
1803
1834
  .dsh-files-search-wrap {
1804
1835
  position: relative;
@@ -1809,70 +1840,77 @@ window.__ModuleLoader__.load({
1809
1840
  }
1810
1841
  .dsh-files-search-icon {
1811
1842
  position: absolute;
1812
- left: 7px;
1813
- color: var(--dsw-alias-label-tertiary, #8c9ba5);
1843
+ left: 8px;
1844
+ color: var(--dsw-alias-label-tertiary);
1814
1845
  pointer-events: none;
1815
1846
  display: flex;
1816
1847
  }
1817
1848
  .dsh-files-search-input {
1818
1849
  box-sizing: border-box;
1819
1850
  width: 100%;
1820
- height: 25px;
1821
- padding: 0 22px 0 26px;
1822
- border: 1px solid var(--dsw-alias-border-l2, rgba(118,137,166,.25));
1823
- border-radius: 4px;
1824
- background: var(--dsw-alias-interactive-bg-hover, rgba(100,120,150,.06));
1825
- color: inherit;
1826
- 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;
1827
1858
  outline: none;
1828
- transition: all 0.15s ease;
1859
+ transition: border-color 0.15s ease, box-shadow 0.15s ease, background 0.15s ease;
1829
1860
  }
1830
1861
  .dsh-files-search-input:focus {
1831
- background: var(--dsw-alias-bg-base, #ffffff);
1832
- border-color: var(--dsw-alias-brand-primary, #4b70e2);
1833
- 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);
1834
1865
  }
1835
1866
  .dsh-files-clear-btn {
1836
1867
  position: absolute;
1837
- right: 5px;
1868
+ right: 6px;
1838
1869
  border: none;
1839
1870
  background: transparent;
1840
- color: var(--dsw-alias-label-tertiary, #8c9ba5);
1871
+ color: var(--dsw-alias-label-tertiary);
1841
1872
  cursor: pointer;
1842
1873
  padding: 2px;
1843
1874
  display: flex;
1875
+ border-radius: 50%;
1876
+ transition: all 0.12s ease;
1844
1877
  }
1845
1878
  .dsh-files-clear-btn:hover {
1846
- color: var(--dsw-alias-label-primary, inherit);
1879
+ color: var(--dsw-alias-label-primary);
1880
+ background: var(--dsw-alias-interactive-bg-hover);
1847
1881
  }
1848
1882
  .dsh-files-toolbar-btns {
1849
1883
  display: flex;
1850
1884
  align-items: center;
1851
1885
  gap: 2px;
1886
+ flex-shrink: 0;
1852
1887
  }
1853
1888
  .dsh-files-tool-btn {
1854
1889
  display: inline-flex;
1855
1890
  align-items: center;
1856
1891
  justify-content: center;
1857
- width: 24px;
1858
- height: 24px;
1892
+ width: 26px;
1893
+ height: 26px;
1859
1894
  border: none;
1860
- border-radius: 4px;
1895
+ border-radius: var(--dsw-radius-xs, 4px);
1861
1896
  background: transparent;
1862
- color: var(--dsw-alias-label-secondary, #6f7f9b);
1897
+ color: var(--dsw-alias-label-secondary);
1863
1898
  cursor: pointer;
1864
- transition: all 0.12s ease;
1899
+ transition: all 0.15s cubic-bezier(0.16, 1, 0.3, 1);
1865
1900
  }
1866
1901
  .dsh-files-tool-btn:hover:not(:disabled) {
1867
- color: var(--dsw-alias-label-primary, inherit);
1868
- 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);
1869
1907
  }
1870
1908
  .dsh-files-tool-btn.is-active {
1871
- color: var(--dsw-alias-brand-primary, #4b70e2);
1872
- 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);
1873
1911
  }
1874
1912
  .dsh-files-tool-btn:disabled {
1875
- opacity: 0.4;
1913
+ opacity: 0.35;
1876
1914
  cursor: not-allowed;
1877
1915
  }
1878
1916
 
@@ -1884,10 +1922,8 @@ window.__ModuleLoader__.load({
1884
1922
  overflow-x: hidden;
1885
1923
  padding: 4px 0;
1886
1924
  }
1887
- .dsh-files-dir-block {
1888
- display: flex;
1889
- flex-direction: column;
1890
- }
1925
+
1926
+ /* ── Directory Row (with Motion Chevron) ── */
1891
1927
  .dsh-files-dir-row {
1892
1928
  display: flex;
1893
1929
  align-items: center;
@@ -1897,29 +1933,35 @@ window.__ModuleLoader__.load({
1897
1933
  cursor: pointer;
1898
1934
  user-select: none;
1899
1935
  position: relative;
1900
- 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;
1901
1939
  transition: background 0.12s ease;
1902
1940
  }
1903
1941
  .dsh-files-dir-row:hover {
1904
- background: var(--dsw-alias-interactive-bg-hover, rgba(100,120,150,.08));
1905
- color: var(--dsw-alias-label-primary, inherit);
1942
+ background: var(--dsw-alias-interactive-bg-hover);
1906
1943
  }
1907
- .dsh-files-chevron {
1908
- font-size: 10px;
1909
- transition: transform 0.15s ease;
1910
- display: inline-block;
1911
- 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;
1912
1953
  }
1913
- .dsh-files-chevron[data-collapsed='true'] {
1914
- transform: rotate(-90deg);
1954
+ .dsh-files-chevron-wrap.is-expanded {
1955
+ transform: rotate(90deg);
1915
1956
  }
1916
1957
  .dsh-files-folder-icon {
1917
1958
  display: flex;
1959
+ flex-shrink: 0;
1918
1960
  }
1919
1961
  .dsh-files-folder-name {
1920
1962
  flex: 1;
1921
1963
  min-width: 0;
1922
- font-weight: 500;
1964
+ font-weight: 550;
1923
1965
  font-size: 12px;
1924
1966
  overflow: hidden;
1925
1967
  text-overflow: ellipsis;
@@ -1930,8 +1972,8 @@ window.__ModuleLoader__.load({
1930
1972
  font-weight: 600;
1931
1973
  padding: 0 5px;
1932
1974
  border-radius: 99px;
1933
- background: var(--dsw-alias-interactive-bg-hover, rgba(100,120,150,.1));
1934
- 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);
1935
1977
  }
1936
1978
 
1937
1979
  /* ── File Row ── */
@@ -1944,44 +1986,95 @@ window.__ModuleLoader__.load({
1944
1986
  cursor: pointer;
1945
1987
  user-select: none;
1946
1988
  position: relative;
1989
+ border-radius: var(--dsw-radius-xs, 4px);
1990
+ margin: 0 4px;
1947
1991
  transition: background 0.12s ease;
1948
1992
  }
1949
1993
  .dsh-files-row:hover {
1950
- 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;
1951
2001
  }
1952
2002
  .dsh-files-name {
1953
2003
  flex: 1;
1954
2004
  min-width: 0;
1955
2005
  font-size: 12px;
1956
- color: var(--dsw-alias-label-primary, inherit);
2006
+ color: var(--dsw-alias-label-primary);
1957
2007
  overflow: hidden;
1958
2008
  text-overflow: ellipsis;
1959
2009
  white-space: nowrap;
1960
2010
  }
1961
2011
  .dsh-files-size {
1962
2012
  font-size: 10px;
1963
- color: var(--dsw-alias-label-tertiary, #8c9ba5);
2013
+ color: var(--dsw-alias-label-tertiary);
1964
2014
  flex-shrink: 0;
1965
2015
  margin-right: 4px;
1966
2016
  }
1967
2017
 
1968
- /* ── Hover Actions on Rows ── */
2018
+ /* ── Micro-Interaction Hover Action Pills ── */
1969
2019
  .dsh-files-row-actions {
1970
- display: none;
2020
+ display: flex;
1971
2021
  align-items: center;
1972
- gap: 3px;
2022
+ gap: 2px;
1973
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;
1974
2029
  }
1975
2030
  .dsh-files-row:hover .dsh-files-row-actions,
1976
2031
  .dsh-files-dir-row:hover .dsh-files-row-actions,
1977
2032
  .dsh-files-flat-row:hover .dsh-files-row-actions {
1978
- display: flex;
2033
+ opacity: 1;
2034
+ transform: translateX(0);
2035
+ pointer-events: auto;
1979
2036
  }
1980
2037
  .dsh-files-row:hover .dsh-files-size,
1981
2038
  .dsh-files-dir-row:hover .dsh-files-count-badge,
1982
2039
  .dsh-files-flat-row:hover .dsh-files-size {
1983
2040
  display: none;
1984
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
+ }
1985
2078
 
1986
2079
  /* ── Flat Search Result List ── */
1987
2080
  .dsh-files-search-container {
@@ -1994,9 +2087,9 @@ window.__ModuleLoader__.load({
1994
2087
  justify-content: space-between;
1995
2088
  padding: 6px 12px;
1996
2089
  font-size: 11px;
1997
- color: var(--dsw-alias-label-tertiary, #8c9ba5);
1998
- background: color-mix(in srgb, var(--dsw-alias-brand-primary, #4b70e2) 4%, transparent);
1999
- 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);
2000
2093
  }
2001
2094
  .dsh-files-search-count {
2002
2095
  font-weight: 500;
@@ -2005,20 +2098,20 @@ window.__ModuleLoader__.load({
2005
2098
  display: inline-flex;
2006
2099
  align-items: center;
2007
2100
  gap: 4px;
2008
- border: 1px solid var(--dsw-alias-border-l2, rgba(118,137,166,.25));
2009
- background: var(--dsw-alias-container-bg, var(--dsw-alias-bg-base, #ffffff));
2010
- 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);
2011
2104
  cursor: pointer;
2012
2105
  font-size: 10.5px;
2013
2106
  font-weight: 500;
2014
2107
  padding: 2px 7px;
2015
- border-radius: 4px;
2016
- 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);
2017
2110
  }
2018
2111
  .dsh-files-view-toggle-btn:hover {
2019
- background: var(--dsw-alias-brand-primary, #4b70e2);
2020
- color: #ffffff;
2021
- 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);
2022
2115
  }
2023
2116
  .dsh-files-flat-list {
2024
2117
  padding: 4px 0;
@@ -2027,7 +2120,7 @@ window.__ModuleLoader__.load({
2027
2120
  display: flex;
2028
2121
  align-items: center;
2029
2122
  gap: 8px;
2030
- padding: 4px 12px;
2123
+ padding: 5px 12px;
2031
2124
  cursor: pointer;
2032
2125
  user-select: none;
2033
2126
  position: relative;
@@ -2035,7 +2128,7 @@ window.__ModuleLoader__.load({
2035
2128
  min-height: 32px;
2036
2129
  }
2037
2130
  .dsh-files-flat-row:hover {
2038
- background: var(--dsw-alias-interactive-bg-hover, rgba(100,120,150,.08));
2131
+ background: var(--dsw-alias-interactive-bg-hover);
2039
2132
  }
2040
2133
  .dsh-files-flat-icon {
2041
2134
  display: flex;
@@ -2059,22 +2152,21 @@ window.__ModuleLoader__.load({
2059
2152
  .dsh-files-flat-name {
2060
2153
  font-size: 12px;
2061
2154
  font-weight: 500;
2062
- color: var(--dsw-alias-label-primary, inherit);
2155
+ color: var(--dsw-alias-label-primary);
2063
2156
  overflow: hidden;
2064
2157
  text-overflow: ellipsis;
2065
2158
  white-space: nowrap;
2066
2159
  }
2067
2160
  .dsh-files-flat-parent {
2068
2161
  font-size: 10.5px;
2069
- color: var(--dsw-alias-label-tertiary, #8c9ba5);
2162
+ color: var(--dsw-alias-label-tertiary);
2070
2163
  overflow: hidden;
2071
2164
  text-overflow: ellipsis;
2072
2165
  white-space: nowrap;
2073
- opacity: 0.8;
2074
2166
  }
2075
2167
  .dsh-files-jump-hint {
2076
2168
  font-size: 10px;
2077
- color: var(--dsw-alias-brand-primary, #4b70e2);
2169
+ color: var(--dsw-alias-state-business-primary);
2078
2170
  opacity: 0;
2079
2171
  transition: opacity 0.12s ease;
2080
2172
  margin-right: 6px;
@@ -2082,49 +2174,16 @@ window.__ModuleLoader__.load({
2082
2174
  white-space: nowrap;
2083
2175
  }
2084
2176
  .dsh-files-flat-row:hover .dsh-files-jump-hint {
2085
- opacity: 0.85;
2177
+ opacity: 0.9;
2086
2178
  }
2087
2179
  .dsh-files-flat-row.is-directory:hover {
2088
- background: color-mix(in srgb, var(--dsw-alias-brand-primary, #4b70e2) 6%, transparent);
2089
- }
2090
- .dsh-files-action-btn {
2091
- display: inline-flex;
2092
- align-items: center;
2093
- justify-content: center;
2094
- gap: 3px;
2095
- height: 20px;
2096
- padding: 0 5px;
2097
- border: 1px solid var(--dsw-alias-border-l2, rgba(118,137,166,.25));
2098
- border-radius: 3px;
2099
- background: var(--dsw-alias-container-bg, var(--dsw-alias-bg-base, #ffffff));
2100
- color: var(--dsw-alias-label-secondary, #6f7f9b);
2101
- cursor: pointer;
2102
- transition: all 0.12s ease;
2103
- }
2104
- .dsh-files-action-btn:hover {
2105
- color: var(--dsw-alias-label-primary, inherit);
2106
- border-color: var(--dsw-alias-border-l3, rgba(118,137,166,.4));
2107
- background: var(--dsw-alias-interactive-bg-hover, rgba(100,120,150,.12));
2108
- }
2109
- .dsh-files-action-at {
2110
- color: var(--dsw-alias-brand-primary, #4b70e2);
2111
- border-color: color-mix(in srgb, var(--dsw-alias-brand-primary, #4b70e2) 30%, transparent);
2112
- background: color-mix(in srgb, var(--dsw-alias-brand-primary, #4b70e2) 8%, transparent);
2113
- }
2114
- .dsh-files-action-at:hover {
2115
- color: #ffffff;
2116
- background: var(--dsw-alias-brand-primary, #4b70e2);
2117
- border-color: var(--dsw-alias-brand-primary, #4b70e2);
2118
- }
2119
- .dsh-files-action-at-text {
2120
- font-size: 10px;
2121
- font-weight: 600;
2180
+ background: color-mix(in srgb, var(--dsw-alias-state-business-primary) 8%, transparent);
2122
2181
  }
2123
2182
 
2124
2183
  /* ── Highlight & Toast ── */
2125
2184
  .dsh-files-highlight {
2126
- background: color-mix(in srgb, var(--dsw-alias-brand-primary, #4b70e2) 25%, transparent);
2127
- 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);
2128
2187
  font-weight: 600;
2129
2188
  border-radius: 2px;
2130
2189
  padding: 0 1px;
@@ -2138,12 +2197,12 @@ window.__ModuleLoader__.load({
2138
2197
  align-items: center;
2139
2198
  gap: 6px;
2140
2199
  padding: 6px 12px;
2141
- background: var(--dsw-alias-label-primary, #17233c);
2142
- color: var(--dsw-alias-bg-base, #ffffff);
2200
+ background: var(--dsw-alias-label-primary);
2201
+ color: var(--dsw-alias-fill-base, #ffffff);
2143
2202
  font-size: 11px;
2144
2203
  border-radius: 99px;
2145
- box-shadow: 0 4px 16px rgba(0,0,0,.25);
2146
- 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);
2147
2206
  z-index: 100;
2148
2207
  pointer-events: none;
2149
2208
  white-space: nowrap;
@@ -2161,13 +2220,13 @@ window.__ModuleLoader__.load({
2161
2220
  justify-content: center;
2162
2221
  height: 180px;
2163
2222
  gap: 10px;
2164
- color: var(--dsw-alias-label-secondary, #6f7f9b);
2223
+ color: var(--dsw-alias-label-secondary);
2165
2224
  }
2166
2225
  .dsh-files-spinner {
2167
2226
  width: 18px;
2168
2227
  height: 18px;
2169
- border: 2px solid var(--dsw-alias-border-l2, rgba(118,137,166,.3));
2170
- 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);
2171
2230
  border-radius: 50%;
2172
2231
  animation: dsh-files-spin 0.8s linear infinite;
2173
2232
  }
@@ -2181,7 +2240,7 @@ window.__ModuleLoader__.load({
2181
2240
  justify-content: center;
2182
2241
  padding: 36px 16px;
2183
2242
  text-align: center;
2184
- color: var(--dsw-alias-label-secondary, #6f7f9b);
2243
+ color: var(--dsw-alias-label-secondary);
2185
2244
  }
2186
2245
  .dsh-files-empty-icon {
2187
2246
  margin-bottom: 8px;
@@ -2194,7 +2253,7 @@ window.__ModuleLoader__.load({
2194
2253
  }
2195
2254
  .dsh-files-empty-detail {
2196
2255
  font-size: 11.5px;
2197
- color: var(--dsw-alias-label-tertiary, #8c9ba5);
2256
+ color: var(--dsw-alias-label-tertiary);
2198
2257
  }
2199
2258
  .dsh-files-banner-error {
2200
2259
  display: flex;
@@ -2203,9 +2262,9 @@ window.__ModuleLoader__.load({
2203
2262
  gap: 8px;
2204
2263
  padding: 6px 12px;
2205
2264
  font-size: 11.5px;
2206
- color: var(--dsw-alias-state-error-primary, #e34c59);
2207
- background: color-mix(in srgb, var(--dsw-alias-state-error-primary, #e34c59) 10%, transparent);
2208
- 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);
2209
2268
  }
2210
2269
  .dsh-files-banner-close {
2211
2270
  border: none;
@@ -2213,7 +2272,8 @@ window.__ModuleLoader__.load({
2213
2272
  color: inherit;
2214
2273
  cursor: pointer;
2215
2274
  }
2216
- ` });
2275
+ `;
2276
+ document.head.appendChild(style);
2217
2277
  }
2218
2278
  //#endregion
2219
2279
  exports.WorkspaceFilesSettingsCard = WorkspaceFilesSettingsCard;