@tutti-os/workspace-file-reference 0.0.14 → 0.0.15
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/dist/{chunk-7C3RZYQE.js → chunk-HRC2MZ5H.js} +110 -3
- package/dist/chunk-HRC2MZ5H.js.map +1 -0
- package/dist/{chunk-CD3YNHYJ.js → chunk-KSK6PILG.js} +254 -37
- package/dist/chunk-KSK6PILG.js.map +1 -0
- package/dist/contracts/index.d.ts +46 -3
- package/dist/core/index.d.ts +57 -2
- package/dist/core/index.js +7 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.js +7 -1
- package/dist/react/index.d.ts +62 -3
- package/dist/react/index.js +2 -2
- package/dist/{referenceSourceAggregator-yyyLVOPi.d.ts → referenceSourceAggregator-B8ATnJOZ.d.ts} +5 -0
- package/dist/ui/index.d.ts +32 -5
- package/dist/ui/index.js +807 -368
- package/dist/ui/index.js.map +1 -1
- package/package.json +6 -6
- package/dist/chunk-7C3RZYQE.js.map +0 -1
- package/dist/chunk-CD3YNHYJ.js.map +0 -1
package/dist/ui/index.js
CHANGED
|
@@ -3,23 +3,20 @@ import {
|
|
|
3
3
|
createReferenceSourcePickerController,
|
|
4
4
|
normalizeDirectoryPath,
|
|
5
5
|
useWorkspaceFileReferencePickerView
|
|
6
|
-
} from "../chunk-
|
|
6
|
+
} from "../chunk-KSK6PILG.js";
|
|
7
7
|
import {
|
|
8
|
+
REFERENCE_FILTER_CATEGORIES,
|
|
8
9
|
WORKSPACE_ROOT_GROUP_NODE_ID,
|
|
9
10
|
nodeRefKey,
|
|
10
11
|
selectedReferenceToWorkspaceFileReference
|
|
11
|
-
} from "../chunk-
|
|
12
|
+
} from "../chunk-HRC2MZ5H.js";
|
|
12
13
|
|
|
13
14
|
// src/ui/internal/reference/WorkspaceFileReferencePicker.tsx
|
|
14
|
-
import { useId } from "react";
|
|
15
|
-
import { createPortal } from "react-dom";
|
|
16
15
|
import {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
CardTitle,
|
|
22
|
-
CloseIcon,
|
|
16
|
+
Dialog,
|
|
17
|
+
DialogContent,
|
|
18
|
+
DialogHeader,
|
|
19
|
+
DialogTitle,
|
|
23
20
|
cn as cn2
|
|
24
21
|
} from "@tutti-os/ui-system";
|
|
25
22
|
|
|
@@ -160,6 +157,12 @@ function WorkspaceFileReferencePickerTreeEntry({
|
|
|
160
157
|
}, workspaceFileReferenceTreeCollapseDurationMs);
|
|
161
158
|
return () => window.clearTimeout(timeoutId);
|
|
162
159
|
}, [expanded]);
|
|
160
|
+
const handleRowSelect = () => {
|
|
161
|
+
onFocusPath(entry.path);
|
|
162
|
+
if (isFolder) {
|
|
163
|
+
onToggleFolder(entry);
|
|
164
|
+
}
|
|
165
|
+
};
|
|
163
166
|
const shouldBuildChildContent = expanded || shouldRenderChildContent;
|
|
164
167
|
const childContent = shouldBuildChildContent ? childState?.loading ? /* @__PURE__ */ jsxs(
|
|
165
168
|
"div",
|
|
@@ -202,14 +205,24 @@ function WorkspaceFileReferencePickerTreeEntry({
|
|
|
202
205
|
/* @__PURE__ */ jsxs(
|
|
203
206
|
"div",
|
|
204
207
|
{
|
|
208
|
+
"aria-current": focused ? "true" : void 0,
|
|
205
209
|
className: cn(
|
|
206
|
-
"flex items-center gap-2 rounded-[6px] py-1.5 pr-1 transition-colors",
|
|
210
|
+
"flex cursor-pointer items-center gap-2 rounded-[6px] py-1.5 pr-1 transition-colors select-none",
|
|
207
211
|
"nodrag [-webkit-app-region:no-drag]",
|
|
208
212
|
focused || selected ? "bg-transparency-block" : "hover:bg-transparency-block"
|
|
209
213
|
),
|
|
214
|
+
role: "button",
|
|
215
|
+
tabIndex: 0,
|
|
210
216
|
style: {
|
|
211
217
|
paddingLeft: `${(childDepth - 1) * workspaceFileReferenceTreeIndent + 8}px`
|
|
212
218
|
},
|
|
219
|
+
onClick: handleRowSelect,
|
|
220
|
+
onKeyDown: (event) => {
|
|
221
|
+
if (event.key === "Enter" || event.key === " ") {
|
|
222
|
+
event.preventDefault();
|
|
223
|
+
handleRowSelect();
|
|
224
|
+
}
|
|
225
|
+
},
|
|
213
226
|
children: [
|
|
214
227
|
isFolder ? /* @__PURE__ */ jsx(
|
|
215
228
|
"button",
|
|
@@ -232,24 +245,10 @@ function WorkspaceFileReferencePickerTreeEntry({
|
|
|
232
245
|
)
|
|
233
246
|
}
|
|
234
247
|
) : null,
|
|
235
|
-
/* @__PURE__ */ jsxs(
|
|
236
|
-
"
|
|
237
|
-
{
|
|
238
|
-
|
|
239
|
-
type: "button",
|
|
240
|
-
onClick: (event) => {
|
|
241
|
-
event.stopPropagation();
|
|
242
|
-
onFocusPath(entry.path);
|
|
243
|
-
if (entry.kind === "folder") {
|
|
244
|
-
onToggleFolder(entry);
|
|
245
|
-
}
|
|
246
|
-
},
|
|
247
|
-
children: [
|
|
248
|
-
isFolder ? /* @__PURE__ */ jsx(FolderFilledIcon, { className: "size-4 shrink-0 text-[var(--rich-text-folder)]" }) : /* @__PURE__ */ jsx(FileIcon, { className: "size-4 shrink-0 text-[var(--text-tertiary)]" }),
|
|
249
|
-
/* @__PURE__ */ jsx("span", { className: "truncate text-[13px] text-[var(--text-primary)]", children: resolveWorkspaceFileReferenceLabel(entry) })
|
|
250
|
-
]
|
|
251
|
-
}
|
|
252
|
-
),
|
|
248
|
+
/* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-1 items-center gap-2 text-left", children: [
|
|
249
|
+
isFolder ? /* @__PURE__ */ jsx(FolderFilledIcon, { className: "size-4 shrink-0 text-[var(--rich-text-folder)]" }) : /* @__PURE__ */ jsx(FileIcon, { className: "size-4 shrink-0 text-[var(--text-tertiary)]" }),
|
|
250
|
+
/* @__PURE__ */ jsx("span", { className: "truncate text-[13px] text-[var(--text-primary)]", children: resolveWorkspaceFileReferenceLabel(entry) })
|
|
251
|
+
] }),
|
|
253
252
|
/* @__PURE__ */ jsx(
|
|
254
253
|
Button,
|
|
255
254
|
{
|
|
@@ -305,30 +304,29 @@ function WorkspaceFileReferencePickerSearchEntry({
|
|
|
305
304
|
return /* @__PURE__ */ jsxs(
|
|
306
305
|
"div",
|
|
307
306
|
{
|
|
307
|
+
"aria-current": focused ? "true" : void 0,
|
|
308
308
|
className: cn(
|
|
309
|
-
"grid grid-cols-[minmax(0,1fr)_auto] items-center gap-3 rounded-[6px] border py-2.5 pr-1 pl-3 transition-colors",
|
|
309
|
+
"grid cursor-pointer grid-cols-[minmax(0,1fr)_auto] items-center gap-3 rounded-[6px] border py-2.5 pr-1 pl-3 transition-colors select-none",
|
|
310
310
|
"nodrag [-webkit-app-region:no-drag]",
|
|
311
311
|
focused || selected ? "border-border bg-transparency-block" : "border-transparent bg-transparent hover:border-border/70 hover:bg-transparency-block"
|
|
312
312
|
),
|
|
313
|
+
role: "button",
|
|
314
|
+
tabIndex: 0,
|
|
315
|
+
onClick: () => onFocusPath(entry.path),
|
|
316
|
+
onKeyDown: (event) => {
|
|
317
|
+
if (event.key === "Enter" || event.key === " ") {
|
|
318
|
+
event.preventDefault();
|
|
319
|
+
onFocusPath(entry.path);
|
|
320
|
+
}
|
|
321
|
+
},
|
|
313
322
|
children: [
|
|
314
|
-
/* @__PURE__ */ jsxs(
|
|
315
|
-
"
|
|
316
|
-
{
|
|
317
|
-
className: "
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
onFocusPath(entry.path);
|
|
322
|
-
},
|
|
323
|
-
children: [
|
|
324
|
-
/* @__PURE__ */ jsx("span", { className: "grid size-9 shrink-0 place-items-center rounded-lg bg-[var(--transparency-block)] text-[var(--text-tertiary)]", children: isFolder ? /* @__PURE__ */ jsx(FolderFilledIcon, { className: "size-4 text-[var(--rich-text-folder)]" }) : /* @__PURE__ */ jsx(FileIcon, { className: "size-4 text-[var(--text-tertiary)]" }) }),
|
|
325
|
-
/* @__PURE__ */ jsxs("span", { className: "min-w-0", children: [
|
|
326
|
-
/* @__PURE__ */ jsx("span", { className: "block truncate text-[13px] font-medium text-[var(--text-primary)]", children: resolveWorkspaceFileReferenceLabel(entry) }),
|
|
327
|
-
/* @__PURE__ */ jsx("span", { className: "block truncate text-[11px] text-[var(--text-secondary)]", children: entry.path })
|
|
328
|
-
] })
|
|
329
|
-
]
|
|
330
|
-
}
|
|
331
|
-
),
|
|
323
|
+
/* @__PURE__ */ jsxs("div", { className: "nodrag flex min-w-0 items-center gap-3 text-left [-webkit-app-region:no-drag]", children: [
|
|
324
|
+
/* @__PURE__ */ jsx("span", { className: "grid size-9 shrink-0 place-items-center rounded-lg bg-[var(--transparency-block)] text-[var(--text-tertiary)]", children: isFolder ? /* @__PURE__ */ jsx(FolderFilledIcon, { className: "size-4 text-[var(--rich-text-folder)]" }) : /* @__PURE__ */ jsx(FileIcon, { className: "size-4 text-[var(--text-tertiary)]" }) }),
|
|
325
|
+
/* @__PURE__ */ jsxs("span", { className: "min-w-0", children: [
|
|
326
|
+
/* @__PURE__ */ jsx("span", { className: "block truncate text-[13px] font-medium text-[var(--text-primary)]", children: resolveWorkspaceFileReferenceLabel(entry) }),
|
|
327
|
+
/* @__PURE__ */ jsx("span", { className: "block truncate text-[11px] text-[var(--text-secondary)]", children: entry.path })
|
|
328
|
+
] })
|
|
329
|
+
] }),
|
|
332
330
|
/* @__PURE__ */ jsx(
|
|
333
331
|
Button,
|
|
334
332
|
{
|
|
@@ -546,8 +544,6 @@ function WorkspaceFileReferencePickerFeedback2({
|
|
|
546
544
|
|
|
547
545
|
// src/ui/internal/reference/WorkspaceFileReferencePicker.tsx
|
|
548
546
|
import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
549
|
-
var workspaceFileReferencePickerBackdropMotionClassName = "motion-safe:animate-in motion-safe:fade-in-0 motion-safe:duration-[180ms] motion-safe:ease-[cubic-bezier(0.22,1,0.36,1)] motion-reduce:animate-none";
|
|
550
|
-
var workspaceFileReferencePickerPanelMotionClassName = "motion-safe:animate-in motion-safe:fade-in-0 motion-safe:zoom-in-[0.96] motion-safe:duration-[250ms] motion-safe:ease-[cubic-bezier(0.22,1,0.36,1)] motion-reduce:animate-none";
|
|
551
547
|
function WorkspaceFileReferencePicker({
|
|
552
548
|
copy,
|
|
553
549
|
fileAdapter,
|
|
@@ -555,9 +551,9 @@ function WorkspaceFileReferencePicker({
|
|
|
555
551
|
onClose,
|
|
556
552
|
onConfirm,
|
|
557
553
|
open,
|
|
554
|
+
scoped = false,
|
|
558
555
|
workspaceId
|
|
559
556
|
}) {
|
|
560
|
-
const titleId = useId();
|
|
561
557
|
const {
|
|
562
558
|
browseRootEntries,
|
|
563
559
|
directoryStateByPath,
|
|
@@ -582,52 +578,27 @@ function WorkspaceFileReferencePicker({
|
|
|
582
578
|
open,
|
|
583
579
|
workspaceId
|
|
584
580
|
});
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
}
|
|
588
|
-
const dialog = /* @__PURE__ */ jsx3(
|
|
589
|
-
"div",
|
|
581
|
+
return /* @__PURE__ */ jsx3(
|
|
582
|
+
Dialog,
|
|
590
583
|
{
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
584
|
+
open,
|
|
585
|
+
onOpenChange: (nextOpen) => {
|
|
586
|
+
if (!nextOpen) {
|
|
587
|
+
onClose();
|
|
588
|
+
}
|
|
589
|
+
},
|
|
597
590
|
children: /* @__PURE__ */ jsxs3(
|
|
598
|
-
|
|
591
|
+
DialogContent,
|
|
599
592
|
{
|
|
600
|
-
"aria-
|
|
601
|
-
"aria-modal": "true",
|
|
593
|
+
"aria-describedby": void 0,
|
|
602
594
|
className: cn2(
|
|
603
|
-
"nodrag flex h-[min(88vh,44rem)] w-full max-w-5xl
|
|
604
|
-
workspaceFileReferencePickerPanelMotionClassName
|
|
595
|
+
"nodrag flex h-[min(88vh,44rem)] w-full max-w-5xl flex-col gap-0 overflow-hidden border-[var(--line-1)] bg-[var(--background-fronted)] p-0 text-[var(--text-primary)] shadow-panel [-webkit-app-region:no-drag] sm:h-[min(82vh,44rem)] sm:max-w-5xl"
|
|
605
596
|
),
|
|
606
|
-
|
|
607
|
-
|
|
597
|
+
overlayClassName: cn2("nodrag", scoped && "!absolute"),
|
|
598
|
+
portaled: !scoped,
|
|
608
599
|
children: [
|
|
609
|
-
/* @__PURE__ */ jsx3(
|
|
610
|
-
|
|
611
|
-
{
|
|
612
|
-
className: "border-b px-4 py-4 sm:px-6 sm:py-5",
|
|
613
|
-
style: { borderBottomColor: "var(--line-1)" },
|
|
614
|
-
children: /* @__PURE__ */ jsxs3("div", { className: "flex items-start justify-between gap-4", children: [
|
|
615
|
-
/* @__PURE__ */ jsx3("div", { className: "min-w-0", children: /* @__PURE__ */ jsx3(CardTitle, { id: titleId, children: copy.t("referencePicker.title") }) }),
|
|
616
|
-
/* @__PURE__ */ jsx3(
|
|
617
|
-
Button3,
|
|
618
|
-
{
|
|
619
|
-
"aria-label": copy.t("actions.cancel"),
|
|
620
|
-
size: "icon-sm",
|
|
621
|
-
type: "button",
|
|
622
|
-
variant: "ghost",
|
|
623
|
-
onClick: onClose,
|
|
624
|
-
children: /* @__PURE__ */ jsx3(CloseIcon, { size: 16 })
|
|
625
|
-
}
|
|
626
|
-
)
|
|
627
|
-
] })
|
|
628
|
-
}
|
|
629
|
-
),
|
|
630
|
-
/* @__PURE__ */ jsxs3(CardContent, { className: "grid min-h-0 flex-1 grid-rows-[minmax(0,1fr)_auto] gap-0 overflow-hidden p-0 lg:grid-cols-[minmax(0,1.15fr)_minmax(20rem,0.85fr)] lg:grid-rows-1", children: [
|
|
600
|
+
/* @__PURE__ */ jsx3(DialogHeader, { className: "flex-none border-b border-[var(--line-1)] px-4 py-4 sm:px-6 sm:py-5", children: /* @__PURE__ */ jsx3(DialogTitle, { children: copy.t("referencePicker.title") }) }),
|
|
601
|
+
/* @__PURE__ */ jsxs3("div", { className: "grid min-h-0 flex-1 grid-rows-[minmax(0,1fr)_auto] gap-0 overflow-hidden p-0 lg:grid-cols-[minmax(0,1.15fr)_minmax(20rem,0.85fr)] lg:grid-rows-1", children: [
|
|
631
602
|
/* @__PURE__ */ jsx3(
|
|
632
603
|
WorkspaceFileReferencePickerBrowserPane,
|
|
633
604
|
{
|
|
@@ -671,33 +642,31 @@ function WorkspaceFileReferencePicker({
|
|
|
671
642
|
)
|
|
672
643
|
}
|
|
673
644
|
);
|
|
674
|
-
if (typeof document === "undefined") {
|
|
675
|
-
return dialog;
|
|
676
|
-
}
|
|
677
|
-
return createPortal(dialog, document.body);
|
|
678
645
|
}
|
|
679
646
|
|
|
680
647
|
// src/ui/internal/reference/ReferenceSourcePicker.tsx
|
|
681
648
|
import {
|
|
682
649
|
useEffect as useEffect3,
|
|
683
|
-
useId
|
|
650
|
+
useId,
|
|
684
651
|
useRef as useRef2,
|
|
685
652
|
useState as useState3
|
|
686
653
|
} from "react";
|
|
687
|
-
import { createPortal
|
|
654
|
+
import { createPortal } from "react-dom";
|
|
688
655
|
import {
|
|
689
656
|
ArrowRightIcon as ArrowRightIcon2,
|
|
690
657
|
Badge as Badge2,
|
|
691
|
-
Button as
|
|
692
|
-
Card
|
|
693
|
-
CardContent
|
|
694
|
-
CardHeader
|
|
695
|
-
CardTitle
|
|
658
|
+
Button as Button3,
|
|
659
|
+
Card,
|
|
660
|
+
CardContent,
|
|
661
|
+
CardHeader,
|
|
662
|
+
CardTitle,
|
|
696
663
|
CheckIcon as CheckIcon2,
|
|
697
|
-
|
|
664
|
+
ChevronDownIcon,
|
|
665
|
+
CloseIcon,
|
|
698
666
|
FileIcon as FileIcon3,
|
|
699
667
|
FolderFilledIcon as FolderFilledIcon3,
|
|
700
668
|
Input as Input2,
|
|
669
|
+
IssueIcon,
|
|
701
670
|
ResizableHandle,
|
|
702
671
|
ResizablePanel,
|
|
703
672
|
ResizablePanelGroup,
|
|
@@ -707,6 +676,9 @@ import {
|
|
|
707
676
|
cn as cn3
|
|
708
677
|
} from "@tutti-os/ui-system";
|
|
709
678
|
import { AddIcon } from "@tutti-os/ui-system/icons";
|
|
679
|
+
import {
|
|
680
|
+
WorkspaceFilePreviewSurface
|
|
681
|
+
} from "@tutti-os/workspace-file-preview/react";
|
|
710
682
|
|
|
711
683
|
// src/react/internal/reference/useReferenceSourcePickerView.ts
|
|
712
684
|
import { useCallback, useEffect as useEffect2, useMemo, useRef, useState as useState2 } from "react";
|
|
@@ -714,13 +686,18 @@ import { useSnapshot } from "valtio";
|
|
|
714
686
|
import {
|
|
715
687
|
sortWorkspaceFileEntriesForArrangeMode
|
|
716
688
|
} from "@tutti-os/workspace-file-manager/services";
|
|
717
|
-
|
|
689
|
+
import {
|
|
690
|
+
createWorkspaceFilePreviewLoadedState
|
|
691
|
+
} from "@tutti-os/workspace-file-preview";
|
|
718
692
|
function useReferenceSourcePickerView({
|
|
719
693
|
aggregator,
|
|
720
694
|
workspaceId,
|
|
721
695
|
open,
|
|
696
|
+
workspaceRootGroupLabel,
|
|
697
|
+
initialTarget = null,
|
|
722
698
|
onClose,
|
|
723
|
-
onConfirm
|
|
699
|
+
onConfirm,
|
|
700
|
+
onConfirmBundles
|
|
724
701
|
}) {
|
|
725
702
|
const readSnapshot = useSnapshot;
|
|
726
703
|
const scope = useMemo(() => ({ workspaceId }), [workspaceId]);
|
|
@@ -732,8 +709,6 @@ function useReferenceSourcePickerView({
|
|
|
732
709
|
const [breadcrumbBySource, setBreadcrumbBySource] = useState2({});
|
|
733
710
|
const [focusedNode, setFocusedNode] = useState2(null);
|
|
734
711
|
const [arrangeMode, setArrangeMode] = useState2("none");
|
|
735
|
-
const [expandedSources, setExpandedSources] = useState2({});
|
|
736
|
-
const expandSeededRef = useRef(false);
|
|
737
712
|
const sortNodes = useCallback(
|
|
738
713
|
(nodes) => {
|
|
739
714
|
if (arrangeMode === "none") {
|
|
@@ -757,6 +732,7 @@ function useReferenceSourcePickerView({
|
|
|
757
732
|
[arrangeMode]
|
|
758
733
|
);
|
|
759
734
|
const autoEnteredSourcesRef = useRef(/* @__PURE__ */ new Set());
|
|
735
|
+
const appliedInitialTargetRef = useRef(null);
|
|
760
736
|
useEffect2(() => {
|
|
761
737
|
if (!open) {
|
|
762
738
|
return;
|
|
@@ -765,13 +741,44 @@ function useReferenceSourcePickerView({
|
|
|
765
741
|
controller.open();
|
|
766
742
|
setBreadcrumbBySource({});
|
|
767
743
|
setFocusedNode(null);
|
|
768
|
-
setExpandedSources({});
|
|
769
|
-
expandSeededRef.current = false;
|
|
770
744
|
autoEnteredSourcesRef.current = /* @__PURE__ */ new Set();
|
|
745
|
+
appliedInitialTargetRef.current = null;
|
|
771
746
|
return () => {
|
|
772
747
|
controller.close();
|
|
773
748
|
};
|
|
774
749
|
}, [controller, open]);
|
|
750
|
+
useEffect2(() => {
|
|
751
|
+
const target = initialTarget;
|
|
752
|
+
if (!open || !target || appliedInitialTargetRef.current === target) {
|
|
753
|
+
return;
|
|
754
|
+
}
|
|
755
|
+
appliedInitialTargetRef.current = target;
|
|
756
|
+
autoEnteredSourcesRef.current.add(target.sourceId);
|
|
757
|
+
let canceled = false;
|
|
758
|
+
void controller.locatePath(target).then((path) => {
|
|
759
|
+
if (canceled) {
|
|
760
|
+
return;
|
|
761
|
+
}
|
|
762
|
+
const group = path[0];
|
|
763
|
+
if (!group) {
|
|
764
|
+
autoEnteredSourcesRef.current.delete(target.sourceId);
|
|
765
|
+
return;
|
|
766
|
+
}
|
|
767
|
+
controller.setActiveSource(target.sourceId);
|
|
768
|
+
setBreadcrumbBySource((current) => ({
|
|
769
|
+
...current,
|
|
770
|
+
[group.ref.sourceId]: [group]
|
|
771
|
+
}));
|
|
772
|
+
controller.ensureChildren(group);
|
|
773
|
+
const deepest = path[path.length - 1];
|
|
774
|
+
setFocusedNode(path.length > 1 && deepest ? deepest : null);
|
|
775
|
+
}).catch(() => {
|
|
776
|
+
autoEnteredSourcesRef.current.delete(target.sourceId);
|
|
777
|
+
});
|
|
778
|
+
return () => {
|
|
779
|
+
canceled = true;
|
|
780
|
+
};
|
|
781
|
+
}, [open, initialTarget, controller]);
|
|
775
782
|
const activeSourceId = snapshot.activeSourceId;
|
|
776
783
|
const activeTab = useMemo(
|
|
777
784
|
() => snapshot.tabs.find((tab) => tab.sourceId === activeSourceId) ?? null,
|
|
@@ -782,7 +789,8 @@ function useReferenceSourcePickerView({
|
|
|
782
789
|
const currentNode = breadcrumb.at(-1) ?? null;
|
|
783
790
|
const currentKey = currentNode ? nodeRefKey(currentNode.ref) : ROOT_CHILDREN_KEY;
|
|
784
791
|
const activeTabState = activeSourceId ? snapshot.bySource[activeSourceId] : void 0;
|
|
785
|
-
const
|
|
792
|
+
const activeFilters = activeTabState?.searchFilters ?? [];
|
|
793
|
+
const isQuery = activeTabState?.mode === "search" && (activeTabState.searchQuery.trim() !== "" || activeFilters.length > 0);
|
|
786
794
|
const currentChildren = activeTabState?.childrenByKey[currentKey];
|
|
787
795
|
const currentEntries = useMemo(
|
|
788
796
|
() => sortNodes(currentChildren?.entries ?? []),
|
|
@@ -811,18 +819,51 @@ function useReferenceSourcePickerView({
|
|
|
811
819
|
const workspaceRoot = {
|
|
812
820
|
ref: { sourceId, nodeId: WORKSPACE_ROOT_GROUP_NODE_ID },
|
|
813
821
|
kind: "folder",
|
|
814
|
-
displayName:
|
|
822
|
+
displayName: workspaceRootGroupLabel
|
|
815
823
|
};
|
|
816
824
|
result[sourceId] = [workspaceRoot, ...folders];
|
|
817
825
|
}
|
|
818
826
|
}
|
|
819
827
|
return result;
|
|
828
|
+
}, [
|
|
829
|
+
snapshot.tabs,
|
|
830
|
+
snapshot.bySource,
|
|
831
|
+
aggregator,
|
|
832
|
+
scope,
|
|
833
|
+
workspaceRootGroupLabel
|
|
834
|
+
]);
|
|
835
|
+
const sidebarHasMoreBySource = useMemo(() => {
|
|
836
|
+
const result = {};
|
|
837
|
+
for (const tab of snapshot.tabs) {
|
|
838
|
+
const sourceId = tab.sourceId;
|
|
839
|
+
const provided = aggregator.getLoadedSource(sourceId)?.listSidebarGroups?.(scope);
|
|
840
|
+
if (provided && provided.length > 0) {
|
|
841
|
+
result[sourceId] = false;
|
|
842
|
+
continue;
|
|
843
|
+
}
|
|
844
|
+
const root = snapshot.bySource[sourceId]?.childrenByKey[ROOT_CHILDREN_KEY];
|
|
845
|
+
result[sourceId] = Boolean(root?.nextCursor);
|
|
846
|
+
}
|
|
847
|
+
return result;
|
|
820
848
|
}, [snapshot.tabs, snapshot.bySource, aggregator, scope]);
|
|
849
|
+
const sidebarLoadingMoreBySource = useMemo(() => {
|
|
850
|
+
const result = {};
|
|
851
|
+
for (const tab of snapshot.tabs) {
|
|
852
|
+
const root = snapshot.bySource[tab.sourceId]?.childrenByKey[ROOT_CHILDREN_KEY];
|
|
853
|
+
result[tab.sourceId] = Boolean(root?.loaded && root.loading);
|
|
854
|
+
}
|
|
855
|
+
return result;
|
|
856
|
+
}, [snapshot.tabs, snapshot.bySource]);
|
|
821
857
|
const sidebarGroups = activeSourceId ? sidebarGroupsBySource[activeSourceId] ?? [] : [];
|
|
822
|
-
const
|
|
858
|
+
const rootGroupNode = breadcrumb[0] ?? null;
|
|
859
|
+
const searchScopeNodeId = rootGroupNode ? rootGroupNode.ref.nodeId : null;
|
|
860
|
+
const selectedGroupKey = rootGroupNode ? nodeRefKey(rootGroupNode.ref) : activeSourceId && !capabilities?.navigable ? nodeRefKey({
|
|
823
861
|
sourceId: activeSourceId,
|
|
824
862
|
nodeId: WORKSPACE_ROOT_GROUP_NODE_ID
|
|
825
863
|
}) : null;
|
|
864
|
+
useEffect2(() => {
|
|
865
|
+
controller.setSearchScope(searchScopeNodeId);
|
|
866
|
+
}, [controller, searchScopeNodeId]);
|
|
826
867
|
const setActiveSource = useCallback(
|
|
827
868
|
(sourceId) => {
|
|
828
869
|
controller.setActiveSource(sourceId);
|
|
@@ -850,7 +891,7 @@ function useReferenceSourcePickerView({
|
|
|
850
891
|
[controller]
|
|
851
892
|
);
|
|
852
893
|
useEffect2(() => {
|
|
853
|
-
if (!open || !activeSourceId
|
|
894
|
+
if (!open || !activeSourceId) {
|
|
854
895
|
return;
|
|
855
896
|
}
|
|
856
897
|
if (autoEnteredSourcesRef.current.has(activeSourceId)) {
|
|
@@ -867,23 +908,15 @@ function useReferenceSourcePickerView({
|
|
|
867
908
|
}
|
|
868
909
|
autoEnteredSourcesRef.current.add(activeSourceId);
|
|
869
910
|
enterFolder(firstGroup);
|
|
870
|
-
}, [
|
|
871
|
-
open,
|
|
872
|
-
activeSourceId,
|
|
873
|
-
capabilities?.navigable,
|
|
874
|
-
sidebarGroups,
|
|
875
|
-
breadcrumbBySource,
|
|
876
|
-
enterFolder
|
|
877
|
-
]);
|
|
911
|
+
}, [open, activeSourceId, sidebarGroups, breadcrumbBySource, enterFolder]);
|
|
878
912
|
useEffect2(() => {
|
|
879
|
-
if (!open
|
|
913
|
+
if (!open) {
|
|
880
914
|
return;
|
|
881
915
|
}
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
}, [open, activeSourceId]);
|
|
916
|
+
for (const tab of snapshot.tabs) {
|
|
917
|
+
controller.ensureSourceRoot(tab.sourceId);
|
|
918
|
+
}
|
|
919
|
+
}, [open, snapshot.tabs, controller]);
|
|
887
920
|
const navigateToBreadcrumb = useCallback(
|
|
888
921
|
(index) => {
|
|
889
922
|
if (!activeSourceId) {
|
|
@@ -924,26 +957,11 @@ function useReferenceSourcePickerView({
|
|
|
924
957
|
navigateToRoot(sourceId);
|
|
925
958
|
return;
|
|
926
959
|
}
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
);
|
|
931
|
-
const isSourceExpanded = useCallback(
|
|
932
|
-
(sourceId) => expandedSources[sourceId] ?? false,
|
|
933
|
-
[expandedSources]
|
|
934
|
-
);
|
|
935
|
-
const toggleSourceExpanded = useCallback(
|
|
936
|
-
(sourceId) => {
|
|
937
|
-
const willExpand = !(expandedSources[sourceId] ?? false);
|
|
938
|
-
setExpandedSources((current) => ({
|
|
939
|
-
...current,
|
|
940
|
-
[sourceId]: !(current[sourceId] ?? false)
|
|
941
|
-
}));
|
|
942
|
-
if (willExpand && !aggregator.getLoadedSource(sourceId)?.listSidebarGroups) {
|
|
943
|
-
controller.ensureSourceRoot(sourceId);
|
|
944
|
-
}
|
|
960
|
+
controller.ensureChildren(node);
|
|
961
|
+
setBreadcrumbBySource((current) => ({ ...current, [sourceId]: [node] }));
|
|
962
|
+
setFocusedNode(null);
|
|
945
963
|
},
|
|
946
|
-
[
|
|
964
|
+
[controller, snapshot.activeSourceId, navigateToRoot]
|
|
947
965
|
);
|
|
948
966
|
const isSelected = useCallback(
|
|
949
967
|
(node) => snapshot.selection.some(
|
|
@@ -958,16 +976,122 @@ function useReferenceSourcePickerView({
|
|
|
958
976
|
}
|
|
959
977
|
setIsConfirming(true);
|
|
960
978
|
try {
|
|
961
|
-
|
|
962
|
-
|
|
979
|
+
if (onConfirmBundles) {
|
|
980
|
+
const grouped = await controller.confirmGrouped();
|
|
981
|
+
onConfirmBundles({
|
|
982
|
+
files: grouped.files.map(selectedReferenceToWorkspaceFileReference),
|
|
983
|
+
bundles: grouped.bundles.map((bundle) => ({
|
|
984
|
+
sourceId: bundle.root.ref.sourceId,
|
|
985
|
+
nodeId: bundle.root.ref.nodeId,
|
|
986
|
+
displayName: bundle.root.displayName,
|
|
987
|
+
iconUrl: bundle.root.iconUrl ?? null,
|
|
988
|
+
files: bundle.files.map(selectedReferenceToWorkspaceFileReference)
|
|
989
|
+
}))
|
|
990
|
+
});
|
|
991
|
+
} else {
|
|
992
|
+
const selected = await controller.confirm();
|
|
993
|
+
onConfirm(selected.map(selectedReferenceToWorkspaceFileReference));
|
|
994
|
+
}
|
|
963
995
|
onClose();
|
|
964
996
|
} finally {
|
|
965
997
|
setIsConfirming(false);
|
|
966
998
|
}
|
|
967
|
-
}, [controller, isConfirming, onClose, onConfirm]);
|
|
999
|
+
}, [controller, isConfirming, onClose, onConfirm, onConfirmBundles]);
|
|
1000
|
+
const [previewState, setPreviewState] = useState2({
|
|
1001
|
+
status: "empty"
|
|
1002
|
+
});
|
|
1003
|
+
const previewObjectUrlRef = useRef(null);
|
|
1004
|
+
const revokePreviewObjectUrl = useCallback(() => {
|
|
1005
|
+
if (previewObjectUrlRef.current) {
|
|
1006
|
+
URL.revokeObjectURL(previewObjectUrlRef.current);
|
|
1007
|
+
previewObjectUrlRef.current = null;
|
|
1008
|
+
}
|
|
1009
|
+
}, []);
|
|
1010
|
+
useEffect2(() => {
|
|
1011
|
+
const node = focusedNode;
|
|
1012
|
+
if (!node) {
|
|
1013
|
+
revokePreviewObjectUrl();
|
|
1014
|
+
setPreviewState({ status: "empty" });
|
|
1015
|
+
return;
|
|
1016
|
+
}
|
|
1017
|
+
if (node.kind === "folder") {
|
|
1018
|
+
revokePreviewObjectUrl();
|
|
1019
|
+
setPreviewState({ node, status: "directory" });
|
|
1020
|
+
return;
|
|
1021
|
+
}
|
|
1022
|
+
const previewable = aggregator.getLoadedSource(node.ref.sourceId)?.capabilities.previewable ?? false;
|
|
1023
|
+
if (!previewable) {
|
|
1024
|
+
revokePreviewObjectUrl();
|
|
1025
|
+
setPreviewState({ node, status: "unsupported" });
|
|
1026
|
+
return;
|
|
1027
|
+
}
|
|
1028
|
+
let cancelled = false;
|
|
1029
|
+
revokePreviewObjectUrl();
|
|
1030
|
+
setPreviewState({ node, status: "loading" });
|
|
1031
|
+
void (async () => {
|
|
1032
|
+
try {
|
|
1033
|
+
const preview = await aggregator.readPreview(scope, node);
|
|
1034
|
+
if (cancelled) {
|
|
1035
|
+
return;
|
|
1036
|
+
}
|
|
1037
|
+
if (!preview) {
|
|
1038
|
+
setPreviewState({ node, status: "unsupported" });
|
|
1039
|
+
return;
|
|
1040
|
+
}
|
|
1041
|
+
const loaded = createWorkspaceFilePreviewLoadedState({
|
|
1042
|
+
bytes: preview.bytes,
|
|
1043
|
+
contentType: preview.contentType,
|
|
1044
|
+
entry: {
|
|
1045
|
+
kind: node.kind,
|
|
1046
|
+
name: node.displayName,
|
|
1047
|
+
path: node.ref.nodeId,
|
|
1048
|
+
mtimeMs: node.mtimeMs ?? null,
|
|
1049
|
+
sizeBytes: node.sizeBytes ?? null
|
|
1050
|
+
},
|
|
1051
|
+
target: {
|
|
1052
|
+
fileKind: preview.kind,
|
|
1053
|
+
name: node.displayName,
|
|
1054
|
+
path: node.ref.nodeId,
|
|
1055
|
+
mtimeMs: node.mtimeMs ?? null,
|
|
1056
|
+
sizeBytes: node.sizeBytes ?? null
|
|
1057
|
+
}
|
|
1058
|
+
});
|
|
1059
|
+
if (cancelled) {
|
|
1060
|
+
return;
|
|
1061
|
+
}
|
|
1062
|
+
if (loaded.status === "image") {
|
|
1063
|
+
const objectUrl = URL.createObjectURL(
|
|
1064
|
+
new Blob([loaded.bytes], { type: loaded.contentType })
|
|
1065
|
+
);
|
|
1066
|
+
previewObjectUrlRef.current = objectUrl;
|
|
1067
|
+
setPreviewState({ node, objectUrl, status: "image" });
|
|
1068
|
+
return;
|
|
1069
|
+
}
|
|
1070
|
+
if (loaded.status === "text") {
|
|
1071
|
+
setPreviewState({ content: loaded.content, node, status: "text" });
|
|
1072
|
+
return;
|
|
1073
|
+
}
|
|
1074
|
+
setPreviewState({
|
|
1075
|
+
node,
|
|
1076
|
+
reason: loaded.reason,
|
|
1077
|
+
...loaded.maxSizeBytes == null ? {} : { maxSizeBytes: loaded.maxSizeBytes },
|
|
1078
|
+
status: "readonly"
|
|
1079
|
+
});
|
|
1080
|
+
} catch {
|
|
1081
|
+
if (!cancelled) {
|
|
1082
|
+
setPreviewState({ node, status: "error" });
|
|
1083
|
+
}
|
|
1084
|
+
}
|
|
1085
|
+
})();
|
|
1086
|
+
return () => {
|
|
1087
|
+
cancelled = true;
|
|
1088
|
+
};
|
|
1089
|
+
}, [aggregator, focusedNode, revokePreviewObjectUrl, scope]);
|
|
1090
|
+
useEffect2(() => revokePreviewObjectUrl, [revokePreviewObjectUrl]);
|
|
968
1091
|
return {
|
|
969
1092
|
tabs: snapshot.tabs,
|
|
970
1093
|
activeSourceId,
|
|
1094
|
+
previewState,
|
|
971
1095
|
activeTabLabel: activeTab?.label ?? "",
|
|
972
1096
|
capabilities,
|
|
973
1097
|
// 内容区递归就地树:当前选中二级节点的子条目(本地根时为源根子条目)。
|
|
@@ -983,15 +1107,25 @@ function useReferenceSourcePickerView({
|
|
|
983
1107
|
currentNode,
|
|
984
1108
|
sidebarGroups,
|
|
985
1109
|
sidebarGroupsBySource,
|
|
986
|
-
|
|
987
|
-
|
|
1110
|
+
sidebarHasMoreBySource,
|
|
1111
|
+
sidebarLoadingMoreBySource,
|
|
1112
|
+
loadMoreSidebarGroups: (sourceId) => controller.loadMoreSourceRoot(sourceId),
|
|
988
1113
|
selectedGroupKey,
|
|
989
1114
|
arrangeMode,
|
|
990
1115
|
setArrangeMode,
|
|
991
|
-
|
|
1116
|
+
// 查询态(关键词或筛选任一非空)→ 平铺结果;否则浏览树。
|
|
1117
|
+
isQuery,
|
|
992
1118
|
searchQuery: activeTabState?.searchQuery ?? "",
|
|
993
|
-
|
|
994
|
-
|
|
1119
|
+
// 当前源支持的文件类型筛选分类(不支持则空数组,picker 据此决定是否展示筛选下拉)。
|
|
1120
|
+
filterCategories: capabilities?.filterable ? REFERENCE_FILTER_CATEGORIES : [],
|
|
1121
|
+
activeFilters,
|
|
1122
|
+
// 搜索态:仅在「还没有任何结果」时显示 spinner;细化关键词(已有结果)时
|
|
1123
|
+
// 保留旧结果直到新结果就绪,避免内容区在 spinner/结果间反复切换造成闪烁。
|
|
1124
|
+
isLoading: isQuery ? (activeTabState?.isSearchLoading ?? false) && (activeTabState?.searchEntries.length ?? 0) === 0 : currentChildren?.loading ?? false,
|
|
1125
|
+
// 查询态:增长式分页是否还有更多;浏览态:cursor 是否有下一页。
|
|
1126
|
+
hasMore: isQuery ? activeTabState?.searchHasMore ?? false : Boolean(currentChildren?.nextCursor),
|
|
1127
|
+
// 底部「加载更多」在途(查询态 = 增长重查;浏览态 = cursor append)。
|
|
1128
|
+
isLoadingMore: isQuery ? activeTabState?.isSearchLoadingMore ?? false : currentChildren?.loading ?? false,
|
|
995
1129
|
focusedNode,
|
|
996
1130
|
selection: snapshot.selection,
|
|
997
1131
|
selectionCount: snapshot.selection.length,
|
|
@@ -1001,9 +1135,10 @@ function useReferenceSourcePickerView({
|
|
|
1001
1135
|
navigateToBreadcrumb,
|
|
1002
1136
|
navigateToRoot,
|
|
1003
1137
|
setFocusedNode,
|
|
1004
|
-
setSearchQuery: (query) => controller.setSearchQuery(query),
|
|
1138
|
+
setSearchQuery: (query) => controller.setSearchQuery(query, searchScopeNodeId),
|
|
1139
|
+
setFilters: (filters) => controller.setSearchFilters(filters, searchScopeNodeId),
|
|
1005
1140
|
toggleSelection: (node) => controller.toggleSelection(node),
|
|
1006
|
-
loadMore: () => controller.loadMore(currentNode),
|
|
1141
|
+
loadMore: () => isQuery ? controller.loadMoreSearch() : controller.loadMore(currentNode),
|
|
1007
1142
|
isSelected,
|
|
1008
1143
|
confirm,
|
|
1009
1144
|
isConfirming
|
|
@@ -1012,17 +1147,7 @@ function useReferenceSourcePickerView({
|
|
|
1012
1147
|
|
|
1013
1148
|
// src/ui/internal/reference/ReferenceSourcePicker.tsx
|
|
1014
1149
|
import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
1015
|
-
var
|
|
1016
|
-
sourceColumn: "\u5206\u7C7B",
|
|
1017
|
-
selectGroupHint: "\u4ECE\u5DE6\u4FA7\u9009\u62E9\u4E00\u4E2A\u76EE\u5F55",
|
|
1018
|
-
previewSource: "\u4EA7\u51FA\u6765\u6E90",
|
|
1019
|
-
previewModified: "\u4EA7\u51FA\u65F6\u95F4",
|
|
1020
|
-
previewSize: "\u6587\u4EF6\u5927\u5C0F",
|
|
1021
|
-
previewHierarchy: "\u6240\u5C5E\u5C42\u7EA7",
|
|
1022
|
-
reference: "\u5F15\u7528",
|
|
1023
|
-
loadMore: "\u52A0\u8F7D\u66F4\u591A",
|
|
1024
|
-
emptyPreview: "\u9009\u62E9\u4E00\u4E2A\u6587\u4EF6\u67E5\u770B\u8BE6\u60C5"
|
|
1025
|
-
};
|
|
1150
|
+
var SIDEBAR_GROUP_PAGE_SIZE = 20;
|
|
1026
1151
|
function autoFitPanelWidth(groupEl, contentEl, panel, trailingPx) {
|
|
1027
1152
|
if (!groupEl || !contentEl || !panel) {
|
|
1028
1153
|
return;
|
|
@@ -1051,19 +1176,35 @@ function autoFitPanelWidth(groupEl, contentEl, panel, trailingPx) {
|
|
|
1051
1176
|
function ReferenceSourcePicker({
|
|
1052
1177
|
aggregator,
|
|
1053
1178
|
copy,
|
|
1179
|
+
initialTarget,
|
|
1054
1180
|
onClose,
|
|
1055
1181
|
onConfirm,
|
|
1182
|
+
onConfirmBundles,
|
|
1056
1183
|
open,
|
|
1057
1184
|
workspaceId
|
|
1058
1185
|
}) {
|
|
1059
|
-
const titleId =
|
|
1186
|
+
const titleId = useId();
|
|
1060
1187
|
const view = useReferenceSourcePickerView({
|
|
1061
1188
|
aggregator,
|
|
1062
1189
|
workspaceId,
|
|
1063
1190
|
open,
|
|
1191
|
+
workspaceRootGroupLabel: copy.t("referencePicker.workspaceRootGroup"),
|
|
1192
|
+
initialTarget,
|
|
1064
1193
|
onClose,
|
|
1065
|
-
onConfirm
|
|
1194
|
+
onConfirm,
|
|
1195
|
+
onConfirmBundles
|
|
1066
1196
|
});
|
|
1197
|
+
const activeFilterSet = new Set(view.activeFilters);
|
|
1198
|
+
const toggleFilter = (id) => {
|
|
1199
|
+
const next = new Set(activeFilterSet);
|
|
1200
|
+
if (next.has(id)) {
|
|
1201
|
+
next.delete(id);
|
|
1202
|
+
} else {
|
|
1203
|
+
next.add(id);
|
|
1204
|
+
}
|
|
1205
|
+
view.setFilters([...next]);
|
|
1206
|
+
};
|
|
1207
|
+
const clearFilters = () => view.setFilters([]);
|
|
1067
1208
|
const layoutRef = useRef2(null);
|
|
1068
1209
|
const sidebarContentRef = useRef2(null);
|
|
1069
1210
|
const middleContentRef = useRef2(null);
|
|
@@ -1092,7 +1233,7 @@ function ReferenceSourcePicker({
|
|
|
1092
1233
|
style: { zIndex: "var(--z-panel)" },
|
|
1093
1234
|
onClick: onClose,
|
|
1094
1235
|
children: /* @__PURE__ */ jsxs4(
|
|
1095
|
-
|
|
1236
|
+
Card,
|
|
1096
1237
|
{
|
|
1097
1238
|
"aria-labelledby": titleId,
|
|
1098
1239
|
"aria-modal": "true",
|
|
@@ -1100,38 +1241,45 @@ function ReferenceSourcePicker({
|
|
|
1100
1241
|
role: "dialog",
|
|
1101
1242
|
onClick: (event) => event.stopPropagation(),
|
|
1102
1243
|
children: [
|
|
1103
|
-
/* @__PURE__ */ jsx4(
|
|
1104
|
-
/* @__PURE__ */ jsx4(
|
|
1244
|
+
/* @__PURE__ */ jsx4(CardHeader, { className: "gap-3 px-4 pt-4 pb-4 sm:px-6", children: /* @__PURE__ */ jsxs4("div", { className: "flex items-start justify-between gap-4", children: [
|
|
1245
|
+
/* @__PURE__ */ jsx4(CardTitle, { id: titleId, children: copy.t("referencePicker.title") }),
|
|
1105
1246
|
/* @__PURE__ */ jsx4(
|
|
1106
|
-
|
|
1247
|
+
Button3,
|
|
1107
1248
|
{
|
|
1108
1249
|
"aria-label": copy.t("actions.cancel"),
|
|
1109
1250
|
size: "icon-sm",
|
|
1110
1251
|
type: "button",
|
|
1111
1252
|
variant: "ghost",
|
|
1112
1253
|
onClick: onClose,
|
|
1113
|
-
children: /* @__PURE__ */ jsx4(
|
|
1254
|
+
children: /* @__PURE__ */ jsx4(CloseIcon, { size: 16 })
|
|
1114
1255
|
}
|
|
1115
1256
|
)
|
|
1116
1257
|
] }) }),
|
|
1117
|
-
/* @__PURE__ */ jsx4(
|
|
1258
|
+
/* @__PURE__ */ jsx4(CardContent, { className: "flex min-h-0 flex-1 overflow-hidden border-t border-[var(--line-1)] p-0", children: /* @__PURE__ */ jsx4("div", { ref: layoutRef, className: "flex min-h-0 min-w-0 flex-1", children: /* @__PURE__ */ jsxs4(
|
|
1118
1259
|
ResizablePanelGroup,
|
|
1119
1260
|
{
|
|
1120
|
-
className: "min-h-0 flex-1",
|
|
1261
|
+
className: "min-h-0 min-w-0 flex-1",
|
|
1121
1262
|
orientation: "horizontal",
|
|
1122
|
-
defaultLayout: { sidebar: 2, middle: 5, preview: 3 },
|
|
1263
|
+
defaultLayout: { sidebar: 2.5, middle: 4.5, preview: 3 },
|
|
1123
1264
|
children: [
|
|
1124
1265
|
/* @__PURE__ */ jsx4(
|
|
1125
1266
|
ResizablePanel,
|
|
1126
1267
|
{
|
|
1127
1268
|
id: "sidebar",
|
|
1128
|
-
className: "min-h-0
|
|
1129
|
-
defaultSize:
|
|
1130
|
-
minSize: "
|
|
1269
|
+
className: "min-h-0 min-w-0",
|
|
1270
|
+
defaultSize: 15,
|
|
1271
|
+
minSize: "150px",
|
|
1131
1272
|
panelRef: (handle) => {
|
|
1132
1273
|
sidebarPanelRef.current = handle;
|
|
1133
1274
|
},
|
|
1134
|
-
children: /* @__PURE__ */ jsx4(
|
|
1275
|
+
children: /* @__PURE__ */ jsx4(
|
|
1276
|
+
SourceSidebar,
|
|
1277
|
+
{
|
|
1278
|
+
contentRef: sidebarContentRef,
|
|
1279
|
+
copy,
|
|
1280
|
+
view
|
|
1281
|
+
}
|
|
1282
|
+
)
|
|
1135
1283
|
}
|
|
1136
1284
|
),
|
|
1137
1285
|
/* @__PURE__ */ jsx4(
|
|
@@ -1139,6 +1287,7 @@ function ReferenceSourcePicker({
|
|
|
1139
1287
|
{
|
|
1140
1288
|
disableDoubleClick: true,
|
|
1141
1289
|
withHandle: true,
|
|
1290
|
+
className: "after:bg-[var(--line-1)]",
|
|
1142
1291
|
onDoubleClick: fitSidebar
|
|
1143
1292
|
}
|
|
1144
1293
|
),
|
|
@@ -1146,73 +1295,105 @@ function ReferenceSourcePicker({
|
|
|
1146
1295
|
ResizablePanel,
|
|
1147
1296
|
{
|
|
1148
1297
|
id: "middle",
|
|
1149
|
-
className: "min-h-0",
|
|
1298
|
+
className: "min-h-0 min-w-0",
|
|
1150
1299
|
defaultSize: 50,
|
|
1151
1300
|
minSize: "260px",
|
|
1152
1301
|
panelRef: (handle) => {
|
|
1153
1302
|
middlePanelRef.current = handle;
|
|
1154
1303
|
},
|
|
1155
1304
|
children: /* @__PURE__ */ jsxs4("div", { className: "flex h-full min-h-0 flex-col", children: [
|
|
1156
|
-
/* @__PURE__ */
|
|
1157
|
-
/* @__PURE__ */
|
|
1158
|
-
|
|
1159
|
-
|
|
1305
|
+
/* @__PURE__ */ jsxs4("div", { className: "flex items-center gap-2 border-b border-[var(--line-1)] p-3", children: [
|
|
1306
|
+
/* @__PURE__ */ jsxs4("div", { className: "relative flex-1", children: [
|
|
1307
|
+
/* @__PURE__ */ jsx4(SearchIcon2, { className: "pointer-events-none absolute top-1/2 left-3 size-4 -translate-y-1/2 text-[var(--text-tertiary)]" }),
|
|
1308
|
+
/* @__PURE__ */ jsx4(
|
|
1309
|
+
Input2,
|
|
1310
|
+
{
|
|
1311
|
+
className: "pl-9",
|
|
1312
|
+
placeholder: copy.t(
|
|
1313
|
+
"referencePicker.searchPlaceholder"
|
|
1314
|
+
),
|
|
1315
|
+
value: view.searchQuery,
|
|
1316
|
+
onChange: (event) => view.setSearchQuery(event.target.value)
|
|
1317
|
+
}
|
|
1318
|
+
)
|
|
1319
|
+
] }),
|
|
1320
|
+
view.capabilities?.filterable && view.filterCategories.length > 0 ? /* @__PURE__ */ jsx4(
|
|
1321
|
+
FilterCategoryFilter,
|
|
1160
1322
|
{
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
onChange: (event) => view.setSearchQuery(event.target.value)
|
|
1323
|
+
categories: view.filterCategories,
|
|
1324
|
+
copy,
|
|
1325
|
+
selected: activeFilterSet,
|
|
1326
|
+
onClear: clearFilters,
|
|
1327
|
+
onToggle: toggleFilter
|
|
1167
1328
|
}
|
|
1168
|
-
)
|
|
1169
|
-
] })
|
|
1170
|
-
/* @__PURE__ */ jsx4(
|
|
1171
|
-
|
|
1329
|
+
) : null
|
|
1330
|
+
] }),
|
|
1331
|
+
/* @__PURE__ */ jsx4(
|
|
1332
|
+
ScrollArea2,
|
|
1172
1333
|
{
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
focused: isFocused(view.focusedNode, node),
|
|
1182
|
-
node,
|
|
1183
|
-
selected: view.isSelected(node),
|
|
1184
|
-
onFocus: view.setFocusedNode,
|
|
1185
|
-
onToggle: view.toggleSelection
|
|
1186
|
-
},
|
|
1187
|
-
nodeRefKey(node.ref)
|
|
1188
|
-
))
|
|
1189
|
-
) : !hasSelectedGroup ? /* @__PURE__ */ jsx4(Feedback, { children: L.selectGroupHint }) : view.currentEntries.length === 0 ? /* @__PURE__ */ jsx4(Feedback, { children: copy.t("referencePicker.emptyDirectory") }) : (
|
|
1190
|
-
// 浏览:就地递归展开树(复刻 agent 引用面板文件树交互)
|
|
1191
|
-
view.currentEntries.map((node) => /* @__PURE__ */ jsx4(
|
|
1192
|
-
TreeNodeRow,
|
|
1193
|
-
{
|
|
1194
|
-
copy,
|
|
1195
|
-
depth: 0,
|
|
1196
|
-
node,
|
|
1197
|
-
view
|
|
1198
|
-
},
|
|
1199
|
-
nodeRefKey(node.ref)
|
|
1200
|
-
))
|
|
1201
|
-
),
|
|
1202
|
-
view.hasMore && hasSelectedGroup && !view.isSearch ? /* @__PURE__ */ jsx4(
|
|
1203
|
-
Button4,
|
|
1204
|
-
{
|
|
1205
|
-
className: "mt-1 w-full",
|
|
1206
|
-
size: "sm",
|
|
1207
|
-
type: "button",
|
|
1208
|
-
variant: "ghost",
|
|
1209
|
-
onClick: view.loadMore,
|
|
1210
|
-
children: L.loadMore
|
|
1334
|
+
className: "min-h-0 flex-1",
|
|
1335
|
+
viewportProps: {
|
|
1336
|
+
// 拉到底部(距底 <120px)自动加载更多 —— 查询态走增长式分页,
|
|
1337
|
+
// 浏览态走 cursor 续页。已在加载/无更多时由 loadMore 内部 no-op。
|
|
1338
|
+
onScroll: (event) => {
|
|
1339
|
+
const el = event.currentTarget;
|
|
1340
|
+
if (view.hasMore && !view.isLoading && !view.isLoadingMore && el.scrollHeight - el.scrollTop - el.clientHeight < 120) {
|
|
1341
|
+
view.loadMore();
|
|
1211
1342
|
}
|
|
1212
|
-
|
|
1213
|
-
|
|
1343
|
+
}
|
|
1344
|
+
},
|
|
1345
|
+
children: /* @__PURE__ */ jsxs4(
|
|
1346
|
+
"div",
|
|
1347
|
+
{
|
|
1348
|
+
ref: middleContentRef,
|
|
1349
|
+
className: "flex flex-col gap-[2px] p-3",
|
|
1350
|
+
children: [
|
|
1351
|
+
view.isLoading ? /* @__PURE__ */ jsx4(Feedback, { children: /* @__PURE__ */ jsx4(Spinner2, { size: 16 }) }) : view.isQuery ? (
|
|
1352
|
+
// 查询态(关键词或筛选):扁平结果
|
|
1353
|
+
view.searchResults.length === 0 ? /* @__PURE__ */ jsx4(Feedback, { children: copy.t("referencePicker.emptySearch") }) : view.searchResults.map((node) => /* @__PURE__ */ jsx4(
|
|
1354
|
+
SearchResultRow,
|
|
1355
|
+
{
|
|
1356
|
+
focused: isFocused(view.focusedNode, node),
|
|
1357
|
+
node,
|
|
1358
|
+
selected: view.isSelected(node),
|
|
1359
|
+
onFocus: view.setFocusedNode,
|
|
1360
|
+
onToggle: view.toggleSelection
|
|
1361
|
+
},
|
|
1362
|
+
nodeRefKey(node.ref)
|
|
1363
|
+
))
|
|
1364
|
+
) : !hasSelectedGroup ? /* @__PURE__ */ jsx4(Feedback, { children: copy.t("referencePicker.selectGroupHint") }) : view.currentEntries.length === 0 ? /* @__PURE__ */ jsx4(Feedback, { children: copy.t("referencePicker.emptyDirectory") }) : (
|
|
1365
|
+
// 浏览:就地递归展开树(复刻 agent 引用面板文件树交互)
|
|
1366
|
+
view.currentEntries.map((node) => /* @__PURE__ */ jsx4(
|
|
1367
|
+
TreeNodeRow,
|
|
1368
|
+
{
|
|
1369
|
+
copy,
|
|
1370
|
+
depth: 0,
|
|
1371
|
+
node,
|
|
1372
|
+
view
|
|
1373
|
+
},
|
|
1374
|
+
nodeRefKey(node.ref)
|
|
1375
|
+
))
|
|
1376
|
+
),
|
|
1377
|
+
view.hasMore && (view.isQuery || hasSelectedGroup) ? /* @__PURE__ */ jsxs4(
|
|
1378
|
+
Button3,
|
|
1379
|
+
{
|
|
1380
|
+
className: "mt-1 w-full",
|
|
1381
|
+
disabled: view.isLoadingMore,
|
|
1382
|
+
size: "sm",
|
|
1383
|
+
type: "button",
|
|
1384
|
+
variant: "ghost",
|
|
1385
|
+
onClick: view.loadMore,
|
|
1386
|
+
children: [
|
|
1387
|
+
view.isLoadingMore ? /* @__PURE__ */ jsx4(Spinner2, { className: "text-current", size: 14 }) : null,
|
|
1388
|
+
copy.t("referencePicker.loadMore")
|
|
1389
|
+
]
|
|
1390
|
+
}
|
|
1391
|
+
) : null
|
|
1392
|
+
]
|
|
1393
|
+
}
|
|
1394
|
+
)
|
|
1214
1395
|
}
|
|
1215
|
-
)
|
|
1396
|
+
)
|
|
1216
1397
|
] })
|
|
1217
1398
|
}
|
|
1218
1399
|
),
|
|
@@ -1221,6 +1402,7 @@ function ReferenceSourcePicker({
|
|
|
1221
1402
|
{
|
|
1222
1403
|
disableDoubleClick: true,
|
|
1223
1404
|
withHandle: true,
|
|
1405
|
+
className: "after:bg-[var(--line-1)]",
|
|
1224
1406
|
onDoubleClick: fitMiddle
|
|
1225
1407
|
}
|
|
1226
1408
|
),
|
|
@@ -1228,17 +1410,17 @@ function ReferenceSourcePicker({
|
|
|
1228
1410
|
ResizablePanel,
|
|
1229
1411
|
{
|
|
1230
1412
|
id: "preview",
|
|
1231
|
-
className: "min-h-0
|
|
1413
|
+
className: "min-h-0 min-w-0",
|
|
1232
1414
|
defaultSize: 30,
|
|
1233
1415
|
minSize: "200px",
|
|
1234
1416
|
children: /* @__PURE__ */ jsx4(
|
|
1235
1417
|
PreviewInfoPane,
|
|
1236
1418
|
{
|
|
1419
|
+
copy,
|
|
1237
1420
|
node: view.focusedNode,
|
|
1421
|
+
previewState: view.previewState,
|
|
1238
1422
|
sourceLabel: view.activeTabLabel,
|
|
1239
|
-
hierarchy: view
|
|
1240
|
-
onReference: view.toggleSelection,
|
|
1241
|
-
referenced: view.focusedNode ? view.isSelected(view.focusedNode) : false
|
|
1423
|
+
hierarchy: resolveHierarchyPath(view)
|
|
1242
1424
|
}
|
|
1243
1425
|
)
|
|
1244
1426
|
}
|
|
@@ -1269,81 +1451,125 @@ function ReferenceSourcePicker({
|
|
|
1269
1451
|
if (typeof document === "undefined") {
|
|
1270
1452
|
return dialog;
|
|
1271
1453
|
}
|
|
1272
|
-
return
|
|
1454
|
+
return createPortal(dialog, document.body);
|
|
1455
|
+
}
|
|
1456
|
+
function GroupFallbackIcon({
|
|
1457
|
+
icon,
|
|
1458
|
+
className
|
|
1459
|
+
}) {
|
|
1460
|
+
if (icon === "issue") {
|
|
1461
|
+
return /* @__PURE__ */ jsx4(IssueIcon, { className });
|
|
1462
|
+
}
|
|
1463
|
+
return /* @__PURE__ */ jsx4(FolderFilledIcon3, { className });
|
|
1273
1464
|
}
|
|
1274
1465
|
function SourceSidebar({
|
|
1466
|
+
copy,
|
|
1275
1467
|
view,
|
|
1276
1468
|
contentRef
|
|
1277
1469
|
}) {
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1470
|
+
const selectedGroupRef = useRef2(null);
|
|
1471
|
+
useEffect3(() => {
|
|
1472
|
+
selectedGroupRef.current?.scrollIntoView({ block: "nearest" });
|
|
1473
|
+
}, [view.selectedGroupKey]);
|
|
1474
|
+
const [shownBySource, setShownBySource] = useState3(
|
|
1475
|
+
{}
|
|
1476
|
+
);
|
|
1477
|
+
const loadMoreGroups = (sourceId) => {
|
|
1478
|
+
const groups = view.sidebarGroupsBySource[sourceId] ?? [];
|
|
1479
|
+
const limit = shownBySource[sourceId] ?? SIDEBAR_GROUP_PAGE_SIZE;
|
|
1480
|
+
const selectedIndex = groups.findIndex(
|
|
1481
|
+
(group) => nodeRefKey(group.ref) === view.selectedGroupKey
|
|
1482
|
+
);
|
|
1483
|
+
const visibleCount = selectedIndex >= limit ? selectedIndex + 1 : limit;
|
|
1484
|
+
const next = visibleCount + SIDEBAR_GROUP_PAGE_SIZE;
|
|
1485
|
+
setShownBySource((prev) => ({ ...prev, [sourceId]: next }));
|
|
1486
|
+
if (next > groups.length && (view.sidebarHasMoreBySource[sourceId] ?? false)) {
|
|
1487
|
+
view.loadMoreSidebarGroups(sourceId);
|
|
1488
|
+
}
|
|
1489
|
+
};
|
|
1490
|
+
return /* @__PURE__ */ jsx4(ScrollArea2, { className: "h-full min-h-0 w-full", children: /* @__PURE__ */ jsx4("div", { ref: contentRef, className: "flex flex-col gap-1 p-2", children: view.tabs.map((tab) => {
|
|
1491
|
+
const groups = view.sidebarGroupsBySource[tab.sourceId] ?? [];
|
|
1492
|
+
const limit = shownBySource[tab.sourceId] ?? SIDEBAR_GROUP_PAGE_SIZE;
|
|
1493
|
+
const selectedIndex = groups.findIndex(
|
|
1494
|
+
(group) => nodeRefKey(group.ref) === view.selectedGroupKey
|
|
1495
|
+
);
|
|
1496
|
+
const effectiveLimit = selectedIndex >= limit ? selectedIndex + 1 : limit;
|
|
1497
|
+
const visibleGroups = groups.slice(0, effectiveLimit);
|
|
1498
|
+
const loadingMore = view.sidebarLoadingMoreBySource[tab.sourceId] ?? false;
|
|
1499
|
+
const hasMore = groups.length > effectiveLimit || (view.sidebarHasMoreBySource[tab.sourceId] ?? false);
|
|
1500
|
+
return /* @__PURE__ */ jsxs4("div", { className: "flex flex-col gap-0.5", children: [
|
|
1501
|
+
/* @__PURE__ */ jsx4(
|
|
1502
|
+
"p",
|
|
1503
|
+
{
|
|
1504
|
+
className: "px-2 pt-1.5 pb-0.5 text-[11px] font-semibold text-[var(--text-tertiary)]",
|
|
1505
|
+
"data-autofit-label": true,
|
|
1506
|
+
children: tab.label
|
|
1507
|
+
}
|
|
1508
|
+
),
|
|
1509
|
+
groups.length === 0 ? view.isLoadingTabs ? /* @__PURE__ */ jsx4("p", { className: "px-2 py-1 text-[12px] text-[var(--text-tertiary)]", children: "\u2026" }) : null : visibleGroups.map((group) => {
|
|
1510
|
+
const key = nodeRefKey(group.ref);
|
|
1511
|
+
const selected = key === view.selectedGroupKey;
|
|
1512
|
+
return /* @__PURE__ */ jsxs4(
|
|
1286
1513
|
"button",
|
|
1287
1514
|
{
|
|
1288
|
-
|
|
1515
|
+
ref: selected ? selectedGroupRef : void 0,
|
|
1516
|
+
"aria-current": selected ? "true" : void 0,
|
|
1289
1517
|
className: cn3(
|
|
1290
|
-
"flex items-center gap-
|
|
1291
|
-
|
|
1518
|
+
"flex items-center gap-2 rounded-[6px] px-2 py-1.5 text-left text-[13px] transition-colors",
|
|
1519
|
+
selected ? "bg-primary/10 font-medium text-[var(--text-primary)] hover:bg-primary/15" : "text-[var(--text-secondary)] hover:bg-[var(--transparency-hover)] hover:text-[var(--text-primary)]"
|
|
1292
1520
|
),
|
|
1293
1521
|
type: "button",
|
|
1294
|
-
onClick: () => view.
|
|
1522
|
+
onClick: () => view.selectGroup(group),
|
|
1295
1523
|
children: [
|
|
1524
|
+
group.iconUrl ? /* @__PURE__ */ jsx4(
|
|
1525
|
+
"img",
|
|
1526
|
+
{
|
|
1527
|
+
alt: "",
|
|
1528
|
+
className: "size-4 shrink-0 rounded-[3px] object-cover",
|
|
1529
|
+
src: group.iconUrl
|
|
1530
|
+
}
|
|
1531
|
+
) : /* @__PURE__ */ jsx4(
|
|
1532
|
+
GroupFallbackIcon,
|
|
1533
|
+
{
|
|
1534
|
+
className: "size-4 shrink-0 text-[var(--rich-text-folder)]",
|
|
1535
|
+
icon: tab.icon
|
|
1536
|
+
}
|
|
1537
|
+
),
|
|
1296
1538
|
/* @__PURE__ */ jsx4(
|
|
1297
|
-
|
|
1539
|
+
"span",
|
|
1298
1540
|
{
|
|
1299
|
-
className:
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
)
|
|
1541
|
+
className: "min-w-0 flex-1 truncate",
|
|
1542
|
+
"data-autofit-label": true,
|
|
1543
|
+
children: group.displayName
|
|
1303
1544
|
}
|
|
1304
1545
|
),
|
|
1305
|
-
/* @__PURE__ */ jsx4("span", { className: "
|
|
1546
|
+
group.childCount != null ? /* @__PURE__ */ jsx4("span", { className: "shrink-0 text-[11px] text-[var(--text-tertiary)]", children: group.childCount }) : null
|
|
1306
1547
|
]
|
|
1307
|
-
}
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
{
|
|
1333
|
-
className: "min-w-0 flex-1 truncate",
|
|
1334
|
-
"data-autofit-label": true,
|
|
1335
|
-
children: group.displayName
|
|
1336
|
-
}
|
|
1337
|
-
),
|
|
1338
|
-
group.childCount != null ? /* @__PURE__ */ jsx4("span", { className: "shrink-0 text-[11px] text-[var(--text-tertiary)]", children: group.childCount }) : null
|
|
1339
|
-
]
|
|
1340
|
-
},
|
|
1341
|
-
key
|
|
1342
|
-
);
|
|
1343
|
-
}) }) : null
|
|
1344
|
-
] }, tab.sourceId);
|
|
1345
|
-
})
|
|
1346
|
-
] }) });
|
|
1548
|
+
},
|
|
1549
|
+
key
|
|
1550
|
+
);
|
|
1551
|
+
}),
|
|
1552
|
+
hasMore ? /* @__PURE__ */ jsxs4(
|
|
1553
|
+
"button",
|
|
1554
|
+
{
|
|
1555
|
+
className: "flex items-center gap-1.5 rounded-[6px] px-2 py-1.5 text-left text-[12px] text-[var(--text-secondary)] transition-colors hover:bg-[var(--transparency-hover)] hover:text-[var(--text-primary)] disabled:opacity-60",
|
|
1556
|
+
disabled: loadingMore,
|
|
1557
|
+
type: "button",
|
|
1558
|
+
onClick: () => loadMoreGroups(tab.sourceId),
|
|
1559
|
+
children: [
|
|
1560
|
+
loadingMore ? /* @__PURE__ */ jsx4(
|
|
1561
|
+
Spinner2,
|
|
1562
|
+
{
|
|
1563
|
+
className: "text-[var(--text-secondary)]",
|
|
1564
|
+
size: 12
|
|
1565
|
+
}
|
|
1566
|
+
) : null,
|
|
1567
|
+
/* @__PURE__ */ jsx4("span", { children: copy.t("referencePicker.loadMoreGroups") })
|
|
1568
|
+
]
|
|
1569
|
+
}
|
|
1570
|
+
) : null
|
|
1571
|
+
] }, tab.sourceId);
|
|
1572
|
+
}) }) });
|
|
1347
1573
|
}
|
|
1348
1574
|
function SearchResultRow({
|
|
1349
1575
|
node,
|
|
@@ -1357,34 +1583,28 @@ function SearchResultRow({
|
|
|
1357
1583
|
"div",
|
|
1358
1584
|
{
|
|
1359
1585
|
className: cn3(
|
|
1360
|
-
"grid grid-cols-[minmax(0,1fr)_auto] items-center gap-3 rounded-[6px] border py-2.5 pr-1 pl-3 transition-colors",
|
|
1586
|
+
"grid cursor-pointer grid-cols-[minmax(0,1fr)_auto] items-center gap-3 rounded-[6px] border py-2.5 pr-1 pl-3 transition-colors",
|
|
1361
1587
|
focused || selected ? "border-border bg-transparency-block" : "border-transparent bg-transparent hover:border-border/70 hover:bg-transparency-block"
|
|
1362
1588
|
),
|
|
1589
|
+
onClick: () => onFocus(node),
|
|
1363
1590
|
children: [
|
|
1364
|
-
/* @__PURE__ */ jsxs4(
|
|
1365
|
-
"
|
|
1366
|
-
{
|
|
1367
|
-
className: "
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
/* @__PURE__ */ jsx4("span", { className: "grid size-9 shrink-0 place-items-center rounded-lg bg-[var(--transparency-block)] text-[var(--text-tertiary)]", children: isFolder ? /* @__PURE__ */ jsx4(FolderFilledIcon3, { className: "size-4 text-[var(--rich-text-folder)]" }) : /* @__PURE__ */ jsx4(FileIcon3, { className: "size-4 text-[var(--text-tertiary)]" }) }),
|
|
1372
|
-
/* @__PURE__ */ jsxs4("span", { className: "min-w-0", children: [
|
|
1373
|
-
/* @__PURE__ */ jsx4("span", { className: "block truncate text-[13px] font-medium text-[var(--text-primary)]", children: node.displayName }),
|
|
1374
|
-
/* @__PURE__ */ jsx4("span", { className: "block truncate text-[11px] text-[var(--text-secondary)]", children: node.ref.nodeId })
|
|
1375
|
-
] })
|
|
1376
|
-
]
|
|
1377
|
-
}
|
|
1378
|
-
),
|
|
1591
|
+
/* @__PURE__ */ jsxs4("div", { className: "flex min-w-0 items-center gap-3 text-left", children: [
|
|
1592
|
+
/* @__PURE__ */ jsx4("span", { className: "grid size-9 shrink-0 place-items-center rounded-lg bg-[var(--transparency-block)] text-[var(--text-tertiary)]", children: isFolder ? /* @__PURE__ */ jsx4(FolderFilledIcon3, { className: "size-4 text-[var(--rich-text-folder)]" }) : /* @__PURE__ */ jsx4(FileIcon3, { className: "size-4 text-[var(--text-tertiary)]" }) }),
|
|
1593
|
+
/* @__PURE__ */ jsxs4("span", { className: "min-w-0", children: [
|
|
1594
|
+
/* @__PURE__ */ jsx4("span", { className: "block truncate text-[13px] font-medium text-[var(--text-primary)]", children: node.displayName }),
|
|
1595
|
+
/* @__PURE__ */ jsx4("span", { className: "block truncate text-[11px] text-[var(--text-secondary)]", children: node.contextLabel ?? node.ref.nodeId })
|
|
1596
|
+
] })
|
|
1597
|
+
] }),
|
|
1379
1598
|
/* @__PURE__ */ jsx4(
|
|
1380
|
-
|
|
1599
|
+
Button3,
|
|
1381
1600
|
{
|
|
1382
1601
|
"aria-label": node.displayName,
|
|
1383
1602
|
"aria-pressed": selected,
|
|
1384
1603
|
size: "icon-sm",
|
|
1385
1604
|
type: "button",
|
|
1386
1605
|
variant: "ghost",
|
|
1387
|
-
onClick: () => {
|
|
1606
|
+
onClick: (event) => {
|
|
1607
|
+
event.stopPropagation();
|
|
1388
1608
|
onFocus(node);
|
|
1389
1609
|
onToggle(node);
|
|
1390
1610
|
},
|
|
@@ -1395,35 +1615,111 @@ function SearchResultRow({
|
|
|
1395
1615
|
}
|
|
1396
1616
|
);
|
|
1397
1617
|
}
|
|
1618
|
+
function toPreviewSurfaceState(node, previewState, copy) {
|
|
1619
|
+
if (!("node" in previewState) || nodeRefKey(previewState.node.ref) !== nodeRefKey(node.ref)) {
|
|
1620
|
+
return node.kind === "folder" ? { entry: node, status: "directory" } : { entry: node, status: "loading" };
|
|
1621
|
+
}
|
|
1622
|
+
switch (previewState.status) {
|
|
1623
|
+
case "directory":
|
|
1624
|
+
return { entry: node, status: "directory" };
|
|
1625
|
+
case "loading":
|
|
1626
|
+
return { entry: node, status: "loading" };
|
|
1627
|
+
case "image":
|
|
1628
|
+
return {
|
|
1629
|
+
entry: node,
|
|
1630
|
+
objectUrl: previewState.objectUrl,
|
|
1631
|
+
status: "image"
|
|
1632
|
+
};
|
|
1633
|
+
case "text":
|
|
1634
|
+
return { content: previewState.content, entry: node, status: "text" };
|
|
1635
|
+
case "readonly":
|
|
1636
|
+
return {
|
|
1637
|
+
entry: node,
|
|
1638
|
+
message: previewState.reason === "binary" ? copy.t("referencePicker.previewBinary") : previewState.reason === "file_too_large" || previewState.reason === "text_too_large" ? copy.t("referencePicker.previewTooLarge") : copy.t("referencePicker.previewUnsupported"),
|
|
1639
|
+
status: "readonly"
|
|
1640
|
+
};
|
|
1641
|
+
case "error":
|
|
1642
|
+
return {
|
|
1643
|
+
entry: node,
|
|
1644
|
+
message: copy.t("referencePicker.previewError"),
|
|
1645
|
+
status: "error"
|
|
1646
|
+
};
|
|
1647
|
+
case "unsupported":
|
|
1648
|
+
return {
|
|
1649
|
+
entry: node,
|
|
1650
|
+
message: copy.t("referencePicker.previewUnsupported"),
|
|
1651
|
+
status: "unsupported"
|
|
1652
|
+
};
|
|
1653
|
+
}
|
|
1654
|
+
}
|
|
1655
|
+
function sourceBadgeClassName(sourceId) {
|
|
1656
|
+
return SOURCE_BADGE_CLASSES[sourceId];
|
|
1657
|
+
}
|
|
1658
|
+
var SOURCE_BADGE_CLASSES = {
|
|
1659
|
+
"workspace-file": "bg-[color-mix(in_srgb,var(--rich-text-mention-file)_12%,transparent)] text-[var(--rich-text-mention-file)]",
|
|
1660
|
+
"app-artifact": "bg-[color-mix(in_srgb,var(--rich-text-mention-app)_12%,transparent)] text-[var(--rich-text-mention-app)]",
|
|
1661
|
+
"issue-file": "bg-[color-mix(in_srgb,var(--rich-text-mention-issue)_12%,transparent)] text-[var(--rich-text-mention-issue)]"
|
|
1662
|
+
};
|
|
1398
1663
|
function PreviewInfoPane({
|
|
1664
|
+
copy,
|
|
1399
1665
|
node,
|
|
1666
|
+
previewState,
|
|
1400
1667
|
sourceLabel,
|
|
1401
|
-
hierarchy
|
|
1402
|
-
referenced,
|
|
1403
|
-
onReference
|
|
1668
|
+
hierarchy
|
|
1404
1669
|
}) {
|
|
1405
1670
|
return /* @__PURE__ */ jsx4("aside", { className: "flex h-full min-h-0 w-full flex-col bg-[var(--background-fronted)]", children: node ? /* @__PURE__ */ jsxs4("div", { className: "flex min-h-0 flex-1 flex-col gap-4 p-4", children: [
|
|
1406
|
-
/* @__PURE__ */ jsx4(
|
|
1671
|
+
/* @__PURE__ */ jsx4(
|
|
1672
|
+
WorkspaceFilePreviewSurface,
|
|
1673
|
+
{
|
|
1674
|
+
directoryMessage: copy.t("referencePicker.previewFolder"),
|
|
1675
|
+
emptyMessage: copy.t("referencePicker.emptyPreview"),
|
|
1676
|
+
frameClassName: "flex aspect-[3/2] w-full flex-col items-center justify-center overflow-hidden rounded-[8px] border border-[var(--line-2,var(--border-2))] bg-[var(--transparency-block)] p-0 text-center",
|
|
1677
|
+
imageAlt: (entry) => entry.displayName,
|
|
1678
|
+
imageFrameClassName: "p-3",
|
|
1679
|
+
loadingIndicator: /* @__PURE__ */ jsx4(Spinner2, { size: 16 }),
|
|
1680
|
+
loadingMessage: copy.t("referencePicker.previewLoading"),
|
|
1681
|
+
messageClassName: "mx-auto max-w-[24ch] text-[13px] leading-5 text-[var(--text-secondary)] [overflow-wrap:anywhere]",
|
|
1682
|
+
renderIcon: (entry) => entry.kind === "folder" ? /* @__PURE__ */ jsx4(FolderFilledIcon3, { className: "size-9 text-[var(--rich-text-folder)]" }) : /* @__PURE__ */ jsx4(FileIcon3, { className: "size-9 text-[var(--text-tertiary)]" }),
|
|
1683
|
+
state: toPreviewSurfaceState(node, previewState, copy),
|
|
1684
|
+
textClassName: "h-full w-full overflow-auto p-3 text-left text-[11px] leading-5 whitespace-pre-wrap break-words text-[var(--text-primary)]",
|
|
1685
|
+
textFrameClassName: "items-stretch justify-stretch"
|
|
1686
|
+
}
|
|
1687
|
+
),
|
|
1407
1688
|
/* @__PURE__ */ jsx4("p", { className: "truncate text-[15px] font-semibold", children: node.displayName }),
|
|
1408
1689
|
/* @__PURE__ */ jsxs4("dl", { className: "space-y-2 text-[13px]", children: [
|
|
1409
|
-
/* @__PURE__ */ jsx4(InfoRow, { label:
|
|
1410
|
-
|
|
1411
|
-
|
|
1690
|
+
/* @__PURE__ */ jsx4(InfoRow, { label: copy.t("referencePicker.previewSource"), children: /* @__PURE__ */ jsx4(
|
|
1691
|
+
Badge2,
|
|
1692
|
+
{
|
|
1693
|
+
variant: "secondary",
|
|
1694
|
+
className: sourceBadgeClassName(node.ref.sourceId),
|
|
1695
|
+
children: sourceLabel
|
|
1696
|
+
}
|
|
1697
|
+
) }),
|
|
1698
|
+
node.mtimeMs != null ? /* @__PURE__ */ jsx4(InfoRow, { label: copy.t("referencePicker.previewModified"), children: formatDateTime(node.mtimeMs) }) : null,
|
|
1699
|
+
node.sizeBytes != null ? /* @__PURE__ */ jsx4(InfoRow, { label: copy.t("referencePicker.previewSize"), children: formatBytes(node.sizeBytes) }) : null
|
|
1412
1700
|
] }),
|
|
1413
1701
|
hierarchy.length > 0 ? /* @__PURE__ */ jsxs4("div", { className: "space-y-1.5", children: [
|
|
1414
|
-
/* @__PURE__ */ jsx4("p", { className: "text-[11px] font-semibold text-[var(--text-tertiary)]", children:
|
|
1415
|
-
/* @__PURE__ */ jsx4("div", { className: "flex flex-wrap gap-1", children: hierarchy.map((crumb) => /* @__PURE__ */
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1702
|
+
/* @__PURE__ */ jsx4("p", { className: "text-[11px] font-semibold text-[var(--text-tertiary)]", children: copy.t("referencePicker.previewHierarchy") }),
|
|
1703
|
+
/* @__PURE__ */ jsx4("div", { className: "flex flex-wrap items-center gap-y-1 text-[12px] leading-5", children: hierarchy.map((crumb, index) => /* @__PURE__ */ jsxs4(
|
|
1704
|
+
"span",
|
|
1705
|
+
{
|
|
1706
|
+
className: "flex min-w-0 items-center",
|
|
1707
|
+
children: [
|
|
1708
|
+
index > 0 ? /* @__PURE__ */ jsx4("span", { className: "mx-1 shrink-0 text-[var(--text-tertiary)]", children: "/" }) : null,
|
|
1709
|
+
/* @__PURE__ */ jsx4(
|
|
1710
|
+
"span",
|
|
1711
|
+
{
|
|
1712
|
+
className: "max-w-[14ch] truncate text-[var(--text-secondary)]",
|
|
1713
|
+
title: crumb.displayName,
|
|
1714
|
+
children: crumb.displayName
|
|
1715
|
+
}
|
|
1716
|
+
)
|
|
1717
|
+
]
|
|
1718
|
+
},
|
|
1719
|
+
nodeRefKey(crumb.ref)
|
|
1720
|
+
)) })
|
|
1721
|
+
] }) : null
|
|
1722
|
+
] }) : /* @__PURE__ */ jsx4(Feedback, { children: copy.t("referencePicker.emptyPreview") }) });
|
|
1427
1723
|
}
|
|
1428
1724
|
function InfoRow({
|
|
1429
1725
|
label,
|
|
@@ -1446,17 +1742,25 @@ function Footer({
|
|
|
1446
1742
|
}) {
|
|
1447
1743
|
return /* @__PURE__ */ jsxs4("div", { className: "flex items-center justify-between gap-3 border-t border-[var(--line-1)] px-4 py-3 sm:px-6", children: [
|
|
1448
1744
|
/* @__PURE__ */ jsxs4("div", { className: "flex min-w-0 items-center gap-2", children: [
|
|
1449
|
-
/* @__PURE__ */ jsx4("span", { className: "text-[13px] text-[var(--text-secondary)]", children: countLabel }),
|
|
1450
|
-
selection.slice(0, 2).map((node) => /* @__PURE__ */ jsx4(
|
|
1451
|
-
|
|
1745
|
+
/* @__PURE__ */ jsx4("span", { className: "shrink-0 text-[13px] text-[var(--text-secondary)]", children: countLabel }),
|
|
1746
|
+
selection.slice(0, 2).map((node) => /* @__PURE__ */ jsx4(
|
|
1747
|
+
Badge2,
|
|
1748
|
+
{
|
|
1749
|
+
className: "min-w-0 max-w-[12rem]",
|
|
1750
|
+
variant: "secondary",
|
|
1751
|
+
children: /* @__PURE__ */ jsx4("span", { className: "truncate", children: node.displayName })
|
|
1752
|
+
},
|
|
1753
|
+
nodeRefKey(node.ref)
|
|
1754
|
+
)),
|
|
1755
|
+
selection.length > 2 ? /* @__PURE__ */ jsxs4(Badge2, { className: "shrink-0", variant: "secondary", children: [
|
|
1452
1756
|
"+",
|
|
1453
1757
|
selection.length - 2
|
|
1454
1758
|
] }) : null
|
|
1455
1759
|
] }),
|
|
1456
1760
|
/* @__PURE__ */ jsxs4("div", { className: "flex items-center gap-2", children: [
|
|
1457
|
-
/* @__PURE__ */ jsx4(
|
|
1761
|
+
/* @__PURE__ */ jsx4(Button3, { type: "button", variant: "secondary", onClick: onClose, children: cancelLabel }),
|
|
1458
1762
|
/* @__PURE__ */ jsxs4(
|
|
1459
|
-
|
|
1763
|
+
Button3,
|
|
1460
1764
|
{
|
|
1461
1765
|
disabled: disabled || loading,
|
|
1462
1766
|
type: "button",
|
|
@@ -1473,11 +1777,150 @@ function Footer({
|
|
|
1473
1777
|
function Feedback({ children }) {
|
|
1474
1778
|
return /* @__PURE__ */ jsx4("div", { className: "grid min-h-0 flex-1 place-items-center px-4 py-8 text-center text-[13px] text-[var(--text-secondary)]", children });
|
|
1475
1779
|
}
|
|
1780
|
+
function FilterCategoryFilter({
|
|
1781
|
+
categories,
|
|
1782
|
+
copy,
|
|
1783
|
+
selected,
|
|
1784
|
+
onClear,
|
|
1785
|
+
onToggle
|
|
1786
|
+
}) {
|
|
1787
|
+
const [open, setOpen] = useState3(false);
|
|
1788
|
+
const containerRef = useRef2(null);
|
|
1789
|
+
useEffect3(() => {
|
|
1790
|
+
if (!open) {
|
|
1791
|
+
return;
|
|
1792
|
+
}
|
|
1793
|
+
const onPointerDown = (event) => {
|
|
1794
|
+
if (containerRef.current && !containerRef.current.contains(event.target)) {
|
|
1795
|
+
setOpen(false);
|
|
1796
|
+
}
|
|
1797
|
+
};
|
|
1798
|
+
const onKeyDown = (event) => {
|
|
1799
|
+
if (event.key === "Escape") {
|
|
1800
|
+
setOpen(false);
|
|
1801
|
+
}
|
|
1802
|
+
};
|
|
1803
|
+
document.addEventListener("pointerdown", onPointerDown, true);
|
|
1804
|
+
document.addEventListener("keydown", onKeyDown);
|
|
1805
|
+
return () => {
|
|
1806
|
+
document.removeEventListener("pointerdown", onPointerDown, true);
|
|
1807
|
+
document.removeEventListener("keydown", onKeyDown);
|
|
1808
|
+
};
|
|
1809
|
+
}, [open]);
|
|
1810
|
+
const selectedLabels = categories.filter((category) => selected.has(category.id)).map((category) => copy.t(category.labelKey));
|
|
1811
|
+
const count = selectedLabels.length;
|
|
1812
|
+
const labelText = count > 0 ? selectedLabels.join(copy.t("referencePicker.fileTypeSeparator")) : copy.t("referencePicker.fileTypeAll");
|
|
1813
|
+
return (
|
|
1814
|
+
// shrink-0:不被搜索框挤压;固定宽度让控件不随选中文案变宽。
|
|
1815
|
+
/* @__PURE__ */ jsxs4("div", { ref: containerRef, className: "relative w-[124px] shrink-0", children: [
|
|
1816
|
+
/* @__PURE__ */ jsxs4(
|
|
1817
|
+
Button3,
|
|
1818
|
+
{
|
|
1819
|
+
"aria-expanded": open,
|
|
1820
|
+
"aria-haspopup": "menu",
|
|
1821
|
+
className: "h-8 w-full justify-between gap-1.5 border-0 px-2.5",
|
|
1822
|
+
size: "default",
|
|
1823
|
+
type: "button",
|
|
1824
|
+
variant: "secondary",
|
|
1825
|
+
onClick: () => setOpen((current) => !current),
|
|
1826
|
+
children: [
|
|
1827
|
+
/* @__PURE__ */ jsx4("span", { className: "min-w-0 flex-1 truncate text-left", title: labelText, children: labelText }),
|
|
1828
|
+
count > 1 ? /* @__PURE__ */ jsx4(Badge2, { className: "shrink-0 px-1.5", variant: "secondary", children: count }) : null,
|
|
1829
|
+
count > 0 ? (
|
|
1830
|
+
// 有选中时,右侧箭头位让位给「清除」:role=button 的 span(避免 button 嵌
|
|
1831
|
+
// button 的非法结构),stopPropagation 让点击只清空筛选、不触发触发器的开合。
|
|
1832
|
+
/* @__PURE__ */ jsx4(
|
|
1833
|
+
"span",
|
|
1834
|
+
{
|
|
1835
|
+
"aria-label": copy.t("referencePicker.clearFilter"),
|
|
1836
|
+
className: "grid size-4 shrink-0 cursor-pointer place-items-center rounded-full text-[var(--text-tertiary)] transition-colors hover:bg-[var(--transparency-hover)] hover:text-[var(--text-primary)]",
|
|
1837
|
+
role: "button",
|
|
1838
|
+
tabIndex: 0,
|
|
1839
|
+
onClick: (event) => {
|
|
1840
|
+
event.stopPropagation();
|
|
1841
|
+
onClear();
|
|
1842
|
+
},
|
|
1843
|
+
onKeyDown: (event) => {
|
|
1844
|
+
if (event.key === "Enter" || event.key === " ") {
|
|
1845
|
+
event.preventDefault();
|
|
1846
|
+
event.stopPropagation();
|
|
1847
|
+
onClear();
|
|
1848
|
+
}
|
|
1849
|
+
},
|
|
1850
|
+
children: /* @__PURE__ */ jsx4(CloseIcon, { size: 12 })
|
|
1851
|
+
}
|
|
1852
|
+
)
|
|
1853
|
+
) : /* @__PURE__ */ jsx4(ChevronDownIcon, { className: "size-3.5 shrink-0 text-[var(--text-tertiary)]" })
|
|
1854
|
+
]
|
|
1855
|
+
}
|
|
1856
|
+
),
|
|
1857
|
+
open ? /* @__PURE__ */ jsx4(
|
|
1858
|
+
"div",
|
|
1859
|
+
{
|
|
1860
|
+
className: "absolute top-[calc(100%+4px)] right-0 min-w-40 overflow-hidden rounded-[8px] border border-[var(--line-1)] bg-[var(--background-fronted)] p-1 shadow-panel",
|
|
1861
|
+
role: "menu",
|
|
1862
|
+
style: { zIndex: "var(--z-panel-popover)" },
|
|
1863
|
+
children: categories.map((category) => {
|
|
1864
|
+
const checked = selected.has(category.id);
|
|
1865
|
+
return /* @__PURE__ */ jsxs4(
|
|
1866
|
+
"button",
|
|
1867
|
+
{
|
|
1868
|
+
"aria-checked": checked,
|
|
1869
|
+
className: "flex w-full items-center gap-2 rounded-[6px] px-2 py-1.5 text-left text-[13px] text-[var(--text-primary)] transition-colors hover:bg-[var(--transparency-hover)]",
|
|
1870
|
+
role: "menuitemcheckbox",
|
|
1871
|
+
type: "button",
|
|
1872
|
+
onClick: () => onToggle(category.id),
|
|
1873
|
+
children: [
|
|
1874
|
+
/* @__PURE__ */ jsx4("span", { className: "grid size-4 shrink-0 place-items-center", children: checked ? /* @__PURE__ */ jsx4(CheckIcon2, { className: "size-3.5 text-[var(--tutti-purple)]" }) : null }),
|
|
1875
|
+
/* @__PURE__ */ jsx4("span", { className: "flex-1", children: copy.t(category.labelKey) })
|
|
1876
|
+
]
|
|
1877
|
+
},
|
|
1878
|
+
category.id
|
|
1879
|
+
);
|
|
1880
|
+
})
|
|
1881
|
+
}
|
|
1882
|
+
) : null
|
|
1883
|
+
] })
|
|
1884
|
+
);
|
|
1885
|
+
}
|
|
1476
1886
|
var TREE_INDENT = 28;
|
|
1477
1887
|
var TREE_COLLAPSE_DURATION_MS = 200;
|
|
1478
1888
|
function isFocused(focused, node) {
|
|
1479
1889
|
return focused ? nodeRefKey(focused.ref) === nodeRefKey(node.ref) : false;
|
|
1480
1890
|
}
|
|
1891
|
+
function resolveHierarchyPath(view) {
|
|
1892
|
+
const focused = view.focusedNode;
|
|
1893
|
+
if (!focused) {
|
|
1894
|
+
return view.breadcrumb;
|
|
1895
|
+
}
|
|
1896
|
+
const trail = findFocusedTrail(
|
|
1897
|
+
view.currentEntries,
|
|
1898
|
+
view.childrenByKey,
|
|
1899
|
+
nodeRefKey(focused.ref),
|
|
1900
|
+
[]
|
|
1901
|
+
);
|
|
1902
|
+
return trail ? [...view.breadcrumb, ...trail] : view.breadcrumb;
|
|
1903
|
+
}
|
|
1904
|
+
function findFocusedTrail(roots, childrenByKey, targetKey, trail) {
|
|
1905
|
+
for (const node of roots) {
|
|
1906
|
+
if (nodeRefKey(node.ref) === targetKey) {
|
|
1907
|
+
return [...trail];
|
|
1908
|
+
}
|
|
1909
|
+
if (node.kind === "folder") {
|
|
1910
|
+
const children = childrenByKey[nodeRefKey(node.ref)]?.entries ?? [];
|
|
1911
|
+
if (children.length > 0) {
|
|
1912
|
+
const found = findFocusedTrail(children, childrenByKey, targetKey, [
|
|
1913
|
+
...trail,
|
|
1914
|
+
node
|
|
1915
|
+
]);
|
|
1916
|
+
if (found) {
|
|
1917
|
+
return found;
|
|
1918
|
+
}
|
|
1919
|
+
}
|
|
1920
|
+
}
|
|
1921
|
+
}
|
|
1922
|
+
return null;
|
|
1923
|
+
}
|
|
1481
1924
|
function TreeNodeRow({
|
|
1482
1925
|
node,
|
|
1483
1926
|
depth,
|
|
@@ -1535,10 +1978,16 @@ function TreeNodeRow({
|
|
|
1535
1978
|
"div",
|
|
1536
1979
|
{
|
|
1537
1980
|
className: cn3(
|
|
1538
|
-
"flex items-center gap-2 rounded-[6px] py-1.5 pr-1 transition-colors",
|
|
1981
|
+
"flex cursor-pointer items-center gap-2 rounded-[6px] py-1.5 pr-1 transition-colors",
|
|
1539
1982
|
focused || selected ? "bg-transparency-block" : "hover:bg-transparency-block"
|
|
1540
1983
|
),
|
|
1541
1984
|
style: { paddingLeft: `${depth * TREE_INDENT + 8}px` },
|
|
1985
|
+
onClick: () => {
|
|
1986
|
+
view.setFocusedNode(node);
|
|
1987
|
+
if (isFolder) {
|
|
1988
|
+
view.toggleNode(node);
|
|
1989
|
+
}
|
|
1990
|
+
},
|
|
1542
1991
|
children: [
|
|
1543
1992
|
isFolder ? /* @__PURE__ */ jsx4(
|
|
1544
1993
|
"button",
|
|
@@ -1546,7 +1995,11 @@ function TreeNodeRow({
|
|
|
1546
1995
|
"aria-label": node.displayName,
|
|
1547
1996
|
className: "grid size-5 shrink-0 place-items-center rounded-sm text-[var(--text-secondary)] hover:bg-[var(--transparency-hover)]",
|
|
1548
1997
|
type: "button",
|
|
1549
|
-
onClick: () =>
|
|
1998
|
+
onClick: (event) => {
|
|
1999
|
+
event.stopPropagation();
|
|
2000
|
+
view.setFocusedNode(node);
|
|
2001
|
+
view.toggleNode(node);
|
|
2002
|
+
},
|
|
1550
2003
|
children: /* @__PURE__ */ jsx4(
|
|
1551
2004
|
ArrowRightIcon2,
|
|
1552
2005
|
{
|
|
@@ -1558,32 +2011,17 @@ function TreeNodeRow({
|
|
|
1558
2011
|
)
|
|
1559
2012
|
}
|
|
1560
2013
|
) : null,
|
|
1561
|
-
/* @__PURE__ */
|
|
1562
|
-
|
|
2014
|
+
isFolder ? /* @__PURE__ */ jsx4(FolderFilledIcon3, { className: "size-4 shrink-0 text-[var(--rich-text-folder)]" }) : /* @__PURE__ */ jsx4(FileIcon3, { className: "size-4 shrink-0 text-[var(--text-tertiary)]" }),
|
|
2015
|
+
/* @__PURE__ */ jsx4(
|
|
2016
|
+
"span",
|
|
1563
2017
|
{
|
|
1564
|
-
className: "
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
view.setFocusedNode(node);
|
|
1568
|
-
if (isFolder) {
|
|
1569
|
-
view.toggleNode(node);
|
|
1570
|
-
}
|
|
1571
|
-
},
|
|
1572
|
-
children: [
|
|
1573
|
-
isFolder ? /* @__PURE__ */ jsx4(FolderFilledIcon3, { className: "size-4 shrink-0 text-[var(--rich-text-folder)]" }) : /* @__PURE__ */ jsx4(FileIcon3, { className: "size-4 shrink-0 text-[var(--text-tertiary)]" }),
|
|
1574
|
-
/* @__PURE__ */ jsx4(
|
|
1575
|
-
"span",
|
|
1576
|
-
{
|
|
1577
|
-
className: "truncate text-[13px] text-[var(--text-primary)]",
|
|
1578
|
-
"data-autofit-label": true,
|
|
1579
|
-
children: node.displayName
|
|
1580
|
-
}
|
|
1581
|
-
)
|
|
1582
|
-
]
|
|
2018
|
+
className: "min-w-0 flex-1 truncate text-[13px] text-[var(--text-primary)]",
|
|
2019
|
+
"data-autofit-label": true,
|
|
2020
|
+
children: node.displayName
|
|
1583
2021
|
}
|
|
1584
2022
|
),
|
|
1585
2023
|
/* @__PURE__ */ jsx4(
|
|
1586
|
-
|
|
2024
|
+
Button3,
|
|
1587
2025
|
{
|
|
1588
2026
|
"aria-label": node.displayName,
|
|
1589
2027
|
"aria-pressed": selected,
|
|
@@ -1591,7 +2029,8 @@ function TreeNodeRow({
|
|
|
1591
2029
|
size: "icon-sm",
|
|
1592
2030
|
type: "button",
|
|
1593
2031
|
variant: "ghost",
|
|
1594
|
-
onClick: () => {
|
|
2032
|
+
onClick: (event) => {
|
|
2033
|
+
event.stopPropagation();
|
|
1595
2034
|
view.setFocusedNode(node);
|
|
1596
2035
|
view.toggleSelection(node);
|
|
1597
2036
|
},
|