@arbidocs/blocks 0.4.154 → 0.4.155
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-6HMCF4AJ.js +1720 -0
- package/dist/chunk-6HMCF4AJ.js.map +1 -0
- package/dist/{chunk-BDA3RHYD.cjs → chunk-MUDEL7UL.cjs} +25 -884
- package/dist/chunk-MUDEL7UL.cjs.map +1 -0
- package/dist/{chunk-RE7NULEY.js → chunk-W7CWGURO.js} +28 -873
- package/dist/chunk-W7CWGURO.js.map +1 -0
- package/dist/chunk-WV4TD2HZ.cjs +1785 -0
- package/dist/chunk-WV4TD2HZ.cjs.map +1 -0
- package/dist/connect/index.cjs +1178 -16
- package/dist/connect/index.cjs.map +1 -1
- package/dist/connect/index.d.ts +1 -0
- package/dist/connect/index.js +1160 -12
- package/dist/connect/index.js.map +1 -1
- package/dist/connect/viewer.cjs +40 -44
- package/dist/connect/viewer.cjs.map +1 -1
- package/dist/connect/viewer.js +2 -6
- package/dist/connect/viewer.js.map +1 -1
- package/dist/connection/files/DocumentSyncGlyph.d.ts +28 -0
- package/dist/connection/files/explorer/ConnectedFilesExplorer.d.ts +56 -0
- package/dist/connection/files/explorer/FileTiles.d.ts +87 -0
- package/dist/connection/files/index.d.ts +5 -0
- package/dist/connection/files/store.d.ts +27 -0
- package/dist/connection/files/support.d.ts +38 -0
- package/dist/files/DocStatusIcon.d.ts +5 -4
- package/dist/files/FailedStageIcon.d.ts +26 -0
- package/dist/files/folders/FolderProviderIcon.d.ts +29 -0
- package/dist/files/folders/folderPaths.d.ts +86 -0
- package/dist/files/folders/index.d.ts +2 -0
- package/dist/files/index.cjs +326 -238
- package/dist/files/index.d.ts +5 -0
- package/dist/files/index.js +2 -2
- package/dist/files/permissions.d.ts +28 -0
- package/dist/files/recently-deleted.d.ts +7 -0
- package/dist/files/visibility.d.ts +31 -0
- package/dist/index.cjs +38 -38
- package/dist/index.js +2 -2
- package/node_modules/@arbidocs/coedit/package.json +1 -1
- package/package.json +6 -5
- package/dist/chunk-BDA3RHYD.cjs.map +0 -1
- package/dist/chunk-JGOST4IL.js +0 -648
- package/dist/chunk-JGOST4IL.js.map +0 -1
- package/dist/chunk-RE7NULEY.js.map +0 -1
- package/dist/chunk-YAEXSCUW.cjs +0 -677
- package/dist/chunk-YAEXSCUW.cjs.map +0 -1
package/dist/connect/index.js
CHANGED
|
@@ -11,11 +11,11 @@ export { ConnectedAssistantDock, redlineStats, textToArtifact, toRedlineMarkdown
|
|
|
11
11
|
import { useConnectedWorkspaceRole, ConnectedNativeDocxEditor } from '../chunk-GO3BN76C.js';
|
|
12
12
|
export { ConnectedWorkflowDocumentsField, ConnectedWorkflowLauncher, ConnectedWorkflowsTable, DEFAULT_CONNECTED_WORKFLOWS_TABLE_LABELS, NativeDocxSupportProvider, toWorkflowFieldDocument, useConnectedAgentOptions, useConnectedWorkflowScopeSource, useConnectedWorkspaceRole, useNativeDocxSupport } from '../chunk-GO3BN76C.js';
|
|
13
13
|
export { DocumentViewerSupportProvider, useDocumentViewerSupport } from '../chunk-EYJMMGXF.js';
|
|
14
|
-
import { FilterButton, FilesViewCenter, FilesFilterBar, ROW_MIN, rowHeightForLines, linesForRowHeight, RowDensityControl, FolderFilterButton, FolderPickerRow, FieldLabelsSelect } from '../chunk-
|
|
14
|
+
import { FilterButton, ExplorerFileTile, formatFolderSegment, hasFolderProviderIcon, FolderProviderIcon, ExplorerFolderTile, searchExplorerDocuments, buildExplorerEntries, collectFolderDocs, joinFolderPath, getExplorerDisplayName, RECENTLY_DELETED_HINT, RECENTLY_DELETED_HINT_PLURAL, canDeleteDocument, ExplorerFrame, ExplorerStage, ExplorerScroller, ExplorerLoadingTiles, ExplorerEmpty, ExplorerMarquee, ExplorerDropOverlay, ExplorerDragPreview, ExplorerFileTooltip, visibilityAudience, StatusPill, FailedStageIcon, FilesViewCenter, FilesFilterBar, ROW_MIN, rowHeightForLines, linesForRowHeight, RowDensityControl, FolderFilterButton, FolderPickerRow, FieldLabelsSelect } from '../chunk-6HMCF4AJ.js';
|
|
15
15
|
import '../chunk-RC6VTY2H.js';
|
|
16
16
|
import { useConnectedTags, useConnectedDocuments, useConnectedConversations } from '../chunk-KDLX5AA7.js';
|
|
17
17
|
export { ConnectedWorkspaceDataProvider, useConnectedConversations, useConnectedDocuments, useConnectedTags } from '../chunk-KDLX5AA7.js';
|
|
18
|
-
import { ConnectionProvider, useConnection
|
|
18
|
+
import { useConnectedWorkspace, ConnectionProvider, useConnection } from '../chunk-TF7HN5EU.js';
|
|
19
19
|
export { ConnectionProvider, SESSION_EXPIRED_MESSAGE, isAuthenticated, useConnectedWorkspace, useConnection } from '../chunk-TF7HN5EU.js';
|
|
20
20
|
import { SignDocumentDialog } from '../chunk-2YOVK524.js';
|
|
21
21
|
import '../chunk-MTSKK3BN.js';
|
|
@@ -25,10 +25,10 @@ import { ViewToggle } from '../chunk-JJA6GQKH.js';
|
|
|
25
25
|
import { FactSourcesPanel, FactPassageItem } from '../chunk-HFZ45FD3.js';
|
|
26
26
|
import { WorkspaceActivityList, WorkspaceNotificationMenu, ThreadFollowMenuItem, ThreadFollowButton, TagTable, TagPicker, tagsPageNouns, entitiesPhrase, ExtractEntitiesDialog, GridRowNavigator, LoadingIndicator, EntityIdentityBar, IDENTITY_NAME_MAX_LENGTH, tagTableDocx, documentCount, tagTableLabels, TagDetail, tagDetailLabels, tagNoteLabel, tagKindDescription, glossaryEntries, glossaryDocx, glossaryMarkdown, glossaryFileName } from '../chunk-MNG7N6M2.js';
|
|
27
27
|
import { MemberAvatarStack } from '../chunk-XNOASBGW.js';
|
|
28
|
+
import { renderSearchSnippet, SearchGroupHeader, isMeaningMatch, extractHighlightTerms, passesRelevanceCutoff, groupSearchResults, SearchPillToggle, SearchPagination, SearchPageFrame, SearchPageHeader, ApplyLabelDialog, SearchPageBody, SearchToolbarRow, SearchBar, SearchControlsBar, RelevanceThreshold, SearchTotalsHeadline, ApplyLabelButton, getSearchMatchHint, SearchResultsMain, SearchResultsInner, SearchErrorBanner, SearchResultList, SearchGroupCard, SearchNoResults, SearchEmptyState } from '../chunk-G4IYES7G.js';
|
|
28
29
|
import { UsageMeter } from '../chunk-66TA5IBN.js';
|
|
29
30
|
import '../chunk-UJE32SST.js';
|
|
30
31
|
import '../chunk-NHZK64TQ.js';
|
|
31
|
-
import { renderSearchSnippet, SearchGroupHeader, isMeaningMatch, extractHighlightTerms, passesRelevanceCutoff, groupSearchResults, SearchPillToggle, SearchPagination, SearchPageFrame, SearchPageHeader, ApplyLabelDialog, SearchPageBody, SearchToolbarRow, SearchBar, SearchControlsBar, RelevanceThreshold, SearchTotalsHeadline, ApplyLabelButton, getSearchMatchHint, SearchResultsMain, SearchResultsInner, SearchErrorBanner, SearchResultList, SearchGroupCard, SearchNoResults, SearchEmptyState } from '../chunk-G4IYES7G.js';
|
|
32
32
|
import { PlainMailBodyEditor, MemberNameCell, MemberMutedText, MemberRoleCell, MemberListLoading, MemberBulkActions, buildMailFolderTree, MailFolderTree, draftMailCompose, replyMailCompose, emptyMailCompose, MailGrid, MailMessageView, MailDocumentPicker, parseMailRecipients } from '../chunk-SZSJGZSO.js';
|
|
33
33
|
import '../chunk-NBV56SGU.js';
|
|
34
34
|
import '../chunk-SDOEHEJP.js';
|
|
@@ -73,13 +73,13 @@ import { useBlocksEnvironment, useRequestedSettingsSection, BlocksProvider } fro
|
|
|
73
73
|
import { ModalScaffold, ModalSection } from '../chunk-TX2ZICS7.js';
|
|
74
74
|
import { fmtDate, initials } from '../chunk-OXF2IFXG.js';
|
|
75
75
|
import '../chunk-VUNV25KB.js';
|
|
76
|
-
import { lazy, memo, useState, useEffect, useCallback, useMemo, useRef, Suspense, useSyncExternalStore,
|
|
76
|
+
import { lazy, memo, useState, useEffect, useCallback, createContext, useMemo, forwardRef, useRef, useLayoutEffect, useImperativeHandle, useContext, Suspense, useSyncExternalStore, useId } from 'react';
|
|
77
77
|
import { QueryClient, QueryClientProvider, useQueryClient, useQuery } from '@tanstack/react-query';
|
|
78
|
-
import { HtmlIcon, useArbiSessionState, ArbiProvider, useConversations, useRunConversation, useWorkspaceActivity, useWorkspaceUsers, isWorkspaceNotificationType, useArbi, useNotifications, useDeleteNotifications, useMarkNotificationsRead,
|
|
78
|
+
import { HtmlIcon, useMailPolicy, useProcessingTasks, useUpdateDocuments, useDeleteDocuments, useRenameFolder, useDownloadDocuments, useTags, useDocumentThumbnails, useArbiSessionState, useProcessingTask, getDocumentSubject, useWorkspaces, ArbiProvider, useConversations, useRunConversation, useWorkspaceActivity, useWorkspaceUsers, isWorkspaceNotificationType, useArbi, useNotifications, useDeleteNotifications, useMarkNotificationsRead, useWorkspaceNotificationLevel, useFollowThread, useUploadSkillFiles, useSkills, useSetSkillVisibility, useDeleteSkill, useSkillSource, useAgentModels, useMcpTools, useAgentConfig, useAgentWorkspaces, useCreateAgent, useSaveAgentConfig, useGrantAgentAccess, useRevokeAgentAccess, useGenerateAgentAvatar, useWorkflowRuns, useConversationActivity, useAgents, ArtifactCanvas, useArbiChat, useDocuments, useTagKindSchema, useCreateTag, useSetTagValues, useUpdateTagKindSchema, useFacts, useDeleteTag, useExtractEntities, useShellWorkspaces, ArbiBotHeadIcon, useProfile, useUpdateProfile, useRequestEmailChange, useConfirmEmailChange, useNameEditor, useAvatarCrop, useEmailChange, ImageCropModal, useIdentityVerification, usePasswordChange, usePasswordChangeForm, useNotificationPreferences, useSessions, useCurrentSessionId, useTerminateSession, useSignOut, useDeleteAccount, useDeleteAccountFlow, useMailClient, defaultMailAlias, useClaimNativeAlias, useMailOnline, useConnectMailAccount, useDisconnectMailAccount, useMailAccounts, useUserSettings, useUpdateUserSettings, useAvailableModels, useConnectorVendorVisibility, useConnectorCatalog, useMyConnectors, useDisconnectConnector, useSlackConnection, useDisconnectSlack, isMailboxSyncVendor, isSharePointVendor, useUpdateWorkspace, useAddWorkspaceMembers, useRemoveWorkspaceMembers, useSetWorkspaceMemberRoles, toShellWorkspace, useEnableMailboxSync, useMailboxFolders, useEnableDriveSync, useDriveFolderChildren, connectorErrorStatus, useProjectInvoices, useProjects, useUpdateProjectFields, useUserUsageToday, formatGbp, useChargeWatch, useAddonQuote, STILL_WORKING, useProjectBillingPortal, useIsSlow, useProducts, useCreateProject, useDeleteProject, useRefreshProject, useCanCreateProjects, useDeleteWorkspaces, PROJECT_CREATION_DENIED_REASON, MAX_RETRIEVE_DOC_IDS, useSemanticSearch, useAssignDocTags, useArbiWebSocket, useWorkNotifications, describeServerNotification, useMailUnlock, useMailFolders, useMailMessages, useMailDraftCompose, useMailMessage, useMailCache, MailOfflineUnavailableError, accountPath, useCalendarEvents, useCalendars, useFetchCalendarEvent, useCalendarSettings, useCalendarOverlays, useCalendarOutbox, useCalendarAccounts, useSyncAccountsOnOpen, useResumeCalendarAccountConnect, useCreateEvent, useUpdateEvent, useDeleteEvent, useMoveEvent, useRespondToEvent, useCreateCalendar, useUpdateCalendar, useDeleteCalendar, useImportCalendar, useSaveCalendarSettings, useRefreshCalendar, useCalendarEvent, useMailAttachmentText, useCalendarEventByUid, getPublicBookingPage, bookPublicSlot, PublicBookingError, useAgentSession, useStartAgentSession, useCloseAgentSession, isQueuedCalendarWrite, isAliasTakenError, nextAliasSuggestion, aliasTakenMessage, mailJson, connectorReturnTo, ArbiWebSocketProvider, isDeploymentUserNotification, getWorkspaceActionText, getWorkspaceSentPhrase, BOX_SEAT_REFUSED, BOX_SEAT_REFUSED_TITLE, documentActivityPhrase, isSignatureNotificationType, inputRequestTitle, WORK_NOTIFICATION_LABELS, documentDisplayName, getWorkspaceKind, formatRelativeTime, useCreateWork, useActOnStep, useConversationThreads, useUpdateTag, usePassageQuotes, useUpdateFact, useDeleteFact, useCreateFact, ProviderIcon, formatGbpPerMillionTokens, useDriveFolderDocCount, useChangeProjectPlan, useCancelProjectSubscription, usePreviewProjectPlanChange, useAddProjectAddonBlock, useProjectUsage, usePlanQuote, useCreateProjectCheckout, useInvalidateProjects, fileAttachment, useMailProjects, useSaveMailDraft, useSendMail, useMailDraftReplaced, useCalendarInvitations, useDecideCounter, useSearchContacts, usePublishCalendar, useCalendarShares, useShareCalendar, useUnshareCalendar, useSubscribeCalendar, useHolidayCountries, useAddHolidayCalendar, cancelPublicBooking, AiAnswer, signatureNotificationPhrase, signatureRequestMeta, getNotificationTypeMeta, useMailDraftEditor, useFreeBusy, useRooms, useFindTime, useCalendarSupport, useStartCalendarAccountOAuth, useConnectOAuthAccount, useBookingPages, useDeleteBookingPage, SHAREPOINT_VENDORS, useUpdateProjectNextPeriodAddons, useUpdateProjectAddonSettings, useSyncCalendarAccount, useUpdateCalendarAccount, useDisconnectCalendarAccount, ACCOUNT_VENDOR, useCalDavProfiles, useConnectCalDavAccount, useSaveBookingPage, useCreateRoom } from '@arbidocs/react';
|
|
79
79
|
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
80
|
-
import { Badge, Button, Label, Input,
|
|
80
|
+
import { getFileTypeIcon, DocumentEntity, cn, getDocumentTitle, Badge, VisibilityIcon, formatFriendlyDate, getEntityLabel, Avatar, AvatarImage, getUserDisplayName, AvatarFallback, getUserInitials, getUserAvatarColor, Button, Label, Input, Textarea, Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, tagKindNouns, tagKindTitle, isImageDocument, getEntityColor, IconToggle, VisibilityToggle, Switch, ProjectEntity, DialogFooter, EntityIcon, getDocIcon, Tooltip, TooltipTrigger, TooltipContent, EntityPill, ShieldIcon, getTagTypeLabel, Popover, PopoverTrigger, DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem, UserEntity, PopoverContent, Tabs, TabsList, TabsTrigger, TabsContent, Select, SelectTrigger, SelectValue, SelectContent, SelectItem, VerifiedToggle, Progress } from '@arbidocs/react/ui';
|
|
81
81
|
import { useNotify, notify, sharedSearchSession, takePendingSearch } from '@arbidocs/react/shell';
|
|
82
|
-
import { Bell, Activity, Info, UserCheck,
|
|
82
|
+
import { SquarePen, BookOpen, MessagesSquare, Pencil, Download, Mail, FolderInput, Trash2, Sparkles, Play, ArrowDownToLine, Bell, Activity, Info, UserCheck, Loader2, Upload, Link2, Search, Plus, ArrowLeft, ExternalLink, Tags, CheckCircle2, Milestone, Monitor, UserCircle, KeyRound, Radio, LogOut, Wifi, RotateCcw, User, HatGlasses, MessageSquare, PlugZap, SquareStack, Table, FileText, Tag, Settings, Video, Printer, CalendarDays, Clock, MapPin, Globe, AlertTriangle, FileX, SkipForward, CheckCircle, ArrowUpCircle, Building2, Contact, Scale, NotebookPen, Check, X, BookA, ChevronDown, Users, Paperclip, Quote, Send, Inbox, CalendarX, CalendarCheck, Minimize2, Maximize2, Minus, CalendarSearch, DoorOpen, RefreshCw } from 'lucide-react';
|
|
83
83
|
import { downloadBlob, useIsOnline, useOptionalDocumentTools, fetchDocumentPdf, DocumentToolsProvider } from '@arbidocs/react/document-tools';
|
|
84
84
|
import { useStreamedArtifact } from '@arbidocs/react/artifacts';
|
|
85
85
|
import { FLAT_TAG_KINDS, TAG_KINDS, refusalReason, getChildTags, tagUseCount, flattenTagTree, isFlatKind, isEntityTag, tagsForScope, filterDocumentTags, isLabelTag, getTagDescendantIds, getEligibleParentTags, canTagHaveParent } from '@arbidocs/sdk/browser';
|
|
@@ -87,6 +87,8 @@ import { bytesToBase64 } from '@arbidocs/client';
|
|
|
87
87
|
import { createPortal } from 'react-dom';
|
|
88
88
|
import { create } from 'zustand';
|
|
89
89
|
import { persist, createJSONStorage } from 'zustand/middleware';
|
|
90
|
+
import { useDraggable, useDroppable, useSensors, useSensor, MouseSensor, TouchSensor, pointerWithin, rectIntersection, DndContext, DragOverlay } from '@dnd-kit/core';
|
|
91
|
+
import { useVirtualizer } from '@tanstack/react-virtual';
|
|
90
92
|
|
|
91
93
|
function ConnectionBoundWebSocket({ children }) {
|
|
92
94
|
const { status } = useConnection();
|
|
@@ -14387,7 +14389,7 @@ function BookingPagesPanel({ defaultTimeZone, className }) {
|
|
|
14387
14389
|
var selectClass4 = "h-9 w-full rounded-md border border-input bg-background px-2 text-sm text-foreground shadow-sm";
|
|
14388
14390
|
function CreateRoomForm({ zone, onDone }) {
|
|
14389
14391
|
const { notify: notify14 } = useBlocksEnvironment();
|
|
14390
|
-
const
|
|
14392
|
+
const create3 = useCreateRoom();
|
|
14391
14393
|
const [name, setName] = useState("");
|
|
14392
14394
|
const [type, setType] = useState("room");
|
|
14393
14395
|
const [capacity, setCapacity] = useState("");
|
|
@@ -14407,7 +14409,7 @@ function CreateRoomForm({ zone, onDone }) {
|
|
|
14407
14409
|
const cap = capacity.trim() ? Number(capacity) : null;
|
|
14408
14410
|
if (cap !== null && (!Number.isInteger(cap) || cap < 1))
|
|
14409
14411
|
return setError("Capacity must be a whole number");
|
|
14410
|
-
|
|
14412
|
+
create3.mutate(
|
|
14411
14413
|
{
|
|
14412
14414
|
name: name.trim(),
|
|
14413
14415
|
type,
|
|
@@ -14498,8 +14500,8 @@ function CreateRoomForm({ zone, onDone }) {
|
|
|
14498
14500
|
error && /* @__PURE__ */ jsx("p", { role: "alert", className: "text-sm text-destructive", children: error }),
|
|
14499
14501
|
/* @__PURE__ */ jsxs("div", { className: "flex justify-end gap-2", children: [
|
|
14500
14502
|
/* @__PURE__ */ jsx(Button, { type: "button", variant: "ghost", onClick: onDone, children: "Cancel" }),
|
|
14501
|
-
/* @__PURE__ */ jsxs(Button, { type: "submit", disabled:
|
|
14502
|
-
|
|
14503
|
+
/* @__PURE__ */ jsxs(Button, { type: "submit", disabled: create3.isPending, children: [
|
|
14504
|
+
create3.isPending && /* @__PURE__ */ jsx(Loader2, { className: "mr-1 size-4 animate-spin" }),
|
|
14503
14505
|
"Create"
|
|
14504
14506
|
] })
|
|
14505
14507
|
] })
|
|
@@ -16815,6 +16817,1152 @@ function ConnectedPublicBooking({ slug, cancelToken }) {
|
|
|
16815
16817
|
] })
|
|
16816
16818
|
] });
|
|
16817
16819
|
}
|
|
16820
|
+
var useFilesStore = create()(
|
|
16821
|
+
persist(
|
|
16822
|
+
(set) => ({
|
|
16823
|
+
pendingFolders: {},
|
|
16824
|
+
addPendingFolder: (workspaceId, path) => set((state) => {
|
|
16825
|
+
const current = state.pendingFolders[workspaceId] ?? [];
|
|
16826
|
+
if (current.includes(path)) return state;
|
|
16827
|
+
return { pendingFolders: { ...state.pendingFolders, [workspaceId]: [...current, path] } };
|
|
16828
|
+
}),
|
|
16829
|
+
removePendingFolder: (workspaceId, path) => set((state) => {
|
|
16830
|
+
const current = state.pendingFolders[workspaceId] ?? [];
|
|
16831
|
+
if (!current.includes(path)) return state;
|
|
16832
|
+
return {
|
|
16833
|
+
pendingFolders: {
|
|
16834
|
+
...state.pendingFolders,
|
|
16835
|
+
[workspaceId]: current.filter((p) => p !== path)
|
|
16836
|
+
}
|
|
16837
|
+
};
|
|
16838
|
+
})
|
|
16839
|
+
}),
|
|
16840
|
+
{
|
|
16841
|
+
name: "arbi_explorer_pending_folders",
|
|
16842
|
+
storage: createJSONStorage(() => sessionStorage),
|
|
16843
|
+
partialize: (state) => ({ pendingFolders: state.pendingFolders })
|
|
16844
|
+
}
|
|
16845
|
+
)
|
|
16846
|
+
);
|
|
16847
|
+
var NONE = [];
|
|
16848
|
+
function usePendingFolders(workspaceId) {
|
|
16849
|
+
return useFilesStore(
|
|
16850
|
+
(state) => (workspaceId ? state.pendingFolders[workspaceId] : void 0) ?? NONE
|
|
16851
|
+
);
|
|
16852
|
+
}
|
|
16853
|
+
var FilesSupportContext = createContext({});
|
|
16854
|
+
function FilesSupportProvider({
|
|
16855
|
+
value,
|
|
16856
|
+
children
|
|
16857
|
+
}) {
|
|
16858
|
+
return /* @__PURE__ */ jsx(FilesSupportContext.Provider, { value, children });
|
|
16859
|
+
}
|
|
16860
|
+
function useFilesSupport() {
|
|
16861
|
+
return useContext(FilesSupportContext);
|
|
16862
|
+
}
|
|
16863
|
+
var NO_IDS3 = /* @__PURE__ */ new Set();
|
|
16864
|
+
function useOfflineDocumentIds() {
|
|
16865
|
+
const { useOfflineDocumentIds: useHostIds } = useFilesSupport();
|
|
16866
|
+
return useHostIds?.() ?? NO_IDS3;
|
|
16867
|
+
}
|
|
16868
|
+
function useViewingDocumentId() {
|
|
16869
|
+
const { useViewingDocumentId: useHostViewing } = useFilesSupport();
|
|
16870
|
+
return useHostViewing?.() ?? null;
|
|
16871
|
+
}
|
|
16872
|
+
function DocumentSyncGlyph({
|
|
16873
|
+
docExtId,
|
|
16874
|
+
size = 13,
|
|
16875
|
+
className,
|
|
16876
|
+
bgClassName = "bg-muted-foreground"
|
|
16877
|
+
}) {
|
|
16878
|
+
const isAvailableOffline = useOfflineDocumentIds().has(docExtId);
|
|
16879
|
+
if (!isAvailableOffline) return null;
|
|
16880
|
+
return /* @__PURE__ */ jsx(
|
|
16881
|
+
"span",
|
|
16882
|
+
{
|
|
16883
|
+
title: "Available offline (saved on this device)",
|
|
16884
|
+
"aria-label": "Available offline",
|
|
16885
|
+
"data-testid": `offline-available-badge-${docExtId}`,
|
|
16886
|
+
className: cn(
|
|
16887
|
+
"inline-flex items-center justify-center rounded-full text-white ring-1 ring-white",
|
|
16888
|
+
bgClassName,
|
|
16889
|
+
className
|
|
16890
|
+
),
|
|
16891
|
+
style: { width: size, height: size },
|
|
16892
|
+
children: /* @__PURE__ */ jsx(ArrowDownToLine, { size: Math.round(size * 0.7), strokeWidth: 2.75 })
|
|
16893
|
+
}
|
|
16894
|
+
);
|
|
16895
|
+
}
|
|
16896
|
+
var ACTIVE_STATUSES = /* @__PURE__ */ new Set([
|
|
16897
|
+
"uploading",
|
|
16898
|
+
"queued",
|
|
16899
|
+
"parsing",
|
|
16900
|
+
"encrypting",
|
|
16901
|
+
"indexing",
|
|
16902
|
+
"analysing"
|
|
16903
|
+
]);
|
|
16904
|
+
var TERMINAL_STATUSES = /* @__PURE__ */ new Set(["completed", "failed", "skipped", "empty", "low-content"]);
|
|
16905
|
+
var STATUS_LABEL = {
|
|
16906
|
+
uploading: "Uploading",
|
|
16907
|
+
queued: "Queued",
|
|
16908
|
+
parsing: "Parsing",
|
|
16909
|
+
encrypting: "Encrypting",
|
|
16910
|
+
indexing: "Indexing",
|
|
16911
|
+
analysing: "Analysing"
|
|
16912
|
+
};
|
|
16913
|
+
function isActiveDocumentStatus(status) {
|
|
16914
|
+
return ACTIVE_STATUSES.has(status.toLowerCase());
|
|
16915
|
+
}
|
|
16916
|
+
function useDocStatus(doc) {
|
|
16917
|
+
const liveStatus = useProcessingTask(doc.external_id)?.status;
|
|
16918
|
+
const rowStatus = (doc.status ?? "").toLowerCase();
|
|
16919
|
+
if (liveStatus && ACTIVE_STATUSES.has(liveStatus)) return liveStatus;
|
|
16920
|
+
if (TERMINAL_STATUSES.has(rowStatus)) return rowStatus;
|
|
16921
|
+
return liveStatus ?? rowStatus;
|
|
16922
|
+
}
|
|
16923
|
+
function TileStatusBadge({ doc, status }) {
|
|
16924
|
+
let tone = "neutral";
|
|
16925
|
+
let icon2 = null;
|
|
16926
|
+
let title = "";
|
|
16927
|
+
switch (status) {
|
|
16928
|
+
case "completed":
|
|
16929
|
+
tone = "success";
|
|
16930
|
+
icon2 = /* @__PURE__ */ jsx(CheckCircle, { className: "size-4 text-green-text", strokeWidth: 2.75 });
|
|
16931
|
+
title = "Ready";
|
|
16932
|
+
break;
|
|
16933
|
+
case "failed":
|
|
16934
|
+
tone = "danger";
|
|
16935
|
+
icon2 = /* @__PURE__ */ jsx(
|
|
16936
|
+
FailedStageIcon,
|
|
16937
|
+
{
|
|
16938
|
+
stage: doc.failed_stage ?? null,
|
|
16939
|
+
errorMessage: doc.error_message,
|
|
16940
|
+
className: "size-4 text-red-text"
|
|
16941
|
+
}
|
|
16942
|
+
);
|
|
16943
|
+
title = "Failed";
|
|
16944
|
+
break;
|
|
16945
|
+
case "skipped":
|
|
16946
|
+
icon2 = /* @__PURE__ */ jsx(SkipForward, { className: "size-4 text-muted-foreground", strokeWidth: 2.75 });
|
|
16947
|
+
title = "Skipped";
|
|
16948
|
+
break;
|
|
16949
|
+
case "empty":
|
|
16950
|
+
tone = "warning";
|
|
16951
|
+
icon2 = /* @__PURE__ */ jsx(FileX, { className: "size-4 text-yellow-text", strokeWidth: 2.75 });
|
|
16952
|
+
title = "Empty \u2014 no extractable content";
|
|
16953
|
+
break;
|
|
16954
|
+
case "low-content":
|
|
16955
|
+
tone = "warning";
|
|
16956
|
+
icon2 = /* @__PURE__ */ jsx(AlertTriangle, { className: "size-4 text-yellow-text", strokeWidth: 2.75 });
|
|
16957
|
+
title = "Low content \u2014 minimal extractable content";
|
|
16958
|
+
break;
|
|
16959
|
+
default:
|
|
16960
|
+
return null;
|
|
16961
|
+
}
|
|
16962
|
+
return /* @__PURE__ */ jsx(
|
|
16963
|
+
StatusPill,
|
|
16964
|
+
{
|
|
16965
|
+
tone,
|
|
16966
|
+
icon: icon2,
|
|
16967
|
+
title,
|
|
16968
|
+
testId: `explorer-file-status-${doc.external_id}`
|
|
16969
|
+
}
|
|
16970
|
+
);
|
|
16971
|
+
}
|
|
16972
|
+
function TileVisibilityBadge({ doc }) {
|
|
16973
|
+
const shared = !!doc.shared;
|
|
16974
|
+
return /* @__PURE__ */ jsx(
|
|
16975
|
+
StatusPill,
|
|
16976
|
+
{
|
|
16977
|
+
icon: /* @__PURE__ */ jsx(VisibilityIcon, { isShared: shared, className: "size-3.5", "aria-hidden": true }),
|
|
16978
|
+
label: shared ? getEntityLabel("WORKSPACE") : "Only you",
|
|
16979
|
+
title: visibilityAudience(shared),
|
|
16980
|
+
testId: `explorer-file-visibility-${doc.external_id}`
|
|
16981
|
+
}
|
|
16982
|
+
);
|
|
16983
|
+
}
|
|
16984
|
+
function MiniUserAvatar({ user }) {
|
|
16985
|
+
return /* @__PURE__ */ jsxs(Avatar, { className: "h-4 w-4 border border-white", children: [
|
|
16986
|
+
user.picture && /* @__PURE__ */ jsx(AvatarImage, { src: user.picture, alt: getUserDisplayName(user) }),
|
|
16987
|
+
/* @__PURE__ */ jsx(
|
|
16988
|
+
AvatarFallback,
|
|
16989
|
+
{
|
|
16990
|
+
className: cn(
|
|
16991
|
+
"text-xs font-semibold leading-none text-white",
|
|
16992
|
+
getUserAvatarColor(user.external_id)
|
|
16993
|
+
),
|
|
16994
|
+
children: getUserInitials(user)
|
|
16995
|
+
}
|
|
16996
|
+
)
|
|
16997
|
+
] });
|
|
16998
|
+
}
|
|
16999
|
+
function FileTooltipContent({
|
|
17000
|
+
doc,
|
|
17001
|
+
modifiedBy,
|
|
17002
|
+
tagNameById
|
|
17003
|
+
}) {
|
|
17004
|
+
const labels = (doc.doctags ?? []).map((dt) => tagNameById.get(dt.tag_ext_id)).filter((name) => !!name);
|
|
17005
|
+
return /* @__PURE__ */ jsx(
|
|
17006
|
+
ExplorerFileTooltip,
|
|
17007
|
+
{
|
|
17008
|
+
title: getDocumentTitle(doc, doc.file_name ?? ""),
|
|
17009
|
+
summary: getDocumentSubject(doc),
|
|
17010
|
+
modifiedLabel: doc.updated_at ? formatFriendlyDate(doc.updated_at, false) : null,
|
|
17011
|
+
modifiedByAvatar: modifiedBy && /* @__PURE__ */ jsx(MiniUserAvatar, { user: modifiedBy }),
|
|
17012
|
+
shared: !!doc.shared,
|
|
17013
|
+
visibilityIcon: /* @__PURE__ */ jsx(VisibilityIcon, { isShared: !!doc.shared, className: "h-3 w-3" }),
|
|
17014
|
+
labels,
|
|
17015
|
+
uiLabels: { shared: visibilityAudience(true), private: visibilityAudience(false) }
|
|
17016
|
+
}
|
|
17017
|
+
);
|
|
17018
|
+
}
|
|
17019
|
+
function startMenuItem(items) {
|
|
17020
|
+
if (items.length === 0) return [];
|
|
17021
|
+
return [
|
|
17022
|
+
{
|
|
17023
|
+
id: "start",
|
|
17024
|
+
label: "Start\u2026",
|
|
17025
|
+
icon: Sparkles,
|
|
17026
|
+
testId: "explorer-start-menu",
|
|
17027
|
+
onSelect: () => {
|
|
17028
|
+
},
|
|
17029
|
+
submenu: items.map((item) => ({
|
|
17030
|
+
id: item.id,
|
|
17031
|
+
label: item.title,
|
|
17032
|
+
icon: Play,
|
|
17033
|
+
onSelect: item.run,
|
|
17034
|
+
testId: `explorer-start-${item.id}`
|
|
17035
|
+
}))
|
|
17036
|
+
}
|
|
17037
|
+
];
|
|
17038
|
+
}
|
|
17039
|
+
var FileTile = memo(function FileTile2({
|
|
17040
|
+
doc,
|
|
17041
|
+
density,
|
|
17042
|
+
selected,
|
|
17043
|
+
dragging,
|
|
17044
|
+
dndActive,
|
|
17045
|
+
renaming,
|
|
17046
|
+
canDelete,
|
|
17047
|
+
thumbnailUrl,
|
|
17048
|
+
modifiedBy,
|
|
17049
|
+
tagNameById,
|
|
17050
|
+
onSelect,
|
|
17051
|
+
onToggle,
|
|
17052
|
+
onOpen,
|
|
17053
|
+
onReview,
|
|
17054
|
+
onStartRename,
|
|
17055
|
+
onCommitRename,
|
|
17056
|
+
onCancelRename,
|
|
17057
|
+
onDownload,
|
|
17058
|
+
onMove,
|
|
17059
|
+
onDelete
|
|
17060
|
+
}) {
|
|
17061
|
+
const { attributes, listeners: listeners2, setNodeRef } = useDraggable({
|
|
17062
|
+
id: `doc:${doc.external_id}`,
|
|
17063
|
+
data: { type: "doc", docId: doc.external_id }
|
|
17064
|
+
});
|
|
17065
|
+
const { notify: notify14 } = useBlocksEnvironment();
|
|
17066
|
+
const { startItemsForFile, openDocumentChat, emailDocument } = useFilesSupport();
|
|
17067
|
+
const status = useDocStatus(doc);
|
|
17068
|
+
const isProcessing = ACTIVE_STATUSES.has(status);
|
|
17069
|
+
const isOffline = useOfflineDocumentIds().has(doc.external_id);
|
|
17070
|
+
const isViewing = useViewingDocumentId() === doc.external_id;
|
|
17071
|
+
const showStatusMarker = !isProcessing && TERMINAL_STATUSES.has(status);
|
|
17072
|
+
const Icon = getFileTypeIcon(doc.file_name, { mime: doc.file_type });
|
|
17073
|
+
const { data: mailPolicy } = useMailPolicy();
|
|
17074
|
+
const shareAsEmail = async () => {
|
|
17075
|
+
try {
|
|
17076
|
+
await emailDocument?.(doc);
|
|
17077
|
+
} catch (error) {
|
|
17078
|
+
notify14(error instanceof Error ? error.message : "Could not attach document", "error");
|
|
17079
|
+
}
|
|
17080
|
+
};
|
|
17081
|
+
const startItems = startItemsForFile?.(doc);
|
|
17082
|
+
const menuItems = [
|
|
17083
|
+
{ id: "open", label: "Open", icon: SquarePen, onSelect: () => onOpen(doc) },
|
|
17084
|
+
...onReview ? [{ id: "review", label: "Open in Review", icon: BookOpen, onSelect: () => onReview(doc) }] : [],
|
|
17085
|
+
...openDocumentChat ? [
|
|
17086
|
+
{
|
|
17087
|
+
id: "chat",
|
|
17088
|
+
label: "Document chat",
|
|
17089
|
+
icon: MessagesSquare,
|
|
17090
|
+
onSelect: () => openDocumentChat(doc.external_id)
|
|
17091
|
+
}
|
|
17092
|
+
] : [],
|
|
17093
|
+
...startMenuItem(startItems ?? []),
|
|
17094
|
+
{
|
|
17095
|
+
id: "rename",
|
|
17096
|
+
label: "Rename",
|
|
17097
|
+
icon: Pencil,
|
|
17098
|
+
onSelect: () => onStartRename(doc),
|
|
17099
|
+
separatorBefore: true
|
|
17100
|
+
},
|
|
17101
|
+
{ id: "download", label: "Download", icon: Download, onSelect: () => onDownload(doc) },
|
|
17102
|
+
...emailDocument && mailPolicy?.enabled ? [
|
|
17103
|
+
{
|
|
17104
|
+
id: "email",
|
|
17105
|
+
label: "Send as email attachment",
|
|
17106
|
+
icon: Mail,
|
|
17107
|
+
onSelect: () => {
|
|
17108
|
+
void shareAsEmail();
|
|
17109
|
+
}
|
|
17110
|
+
}
|
|
17111
|
+
] : [],
|
|
17112
|
+
...onMove ? [{ id: "move", label: "Move to\u2026", icon: FolderInput, onSelect: () => onMove(doc) }] : [],
|
|
17113
|
+
...canDelete ? [
|
|
17114
|
+
{
|
|
17115
|
+
id: "delete",
|
|
17116
|
+
label: "Delete",
|
|
17117
|
+
icon: Trash2,
|
|
17118
|
+
onSelect: () => onDelete(doc),
|
|
17119
|
+
destructive: true,
|
|
17120
|
+
separatorBefore: true
|
|
17121
|
+
}
|
|
17122
|
+
] : []
|
|
17123
|
+
];
|
|
17124
|
+
const tooltip = renaming || dndActive ? void 0 : /* @__PURE__ */ jsx(FileTooltipContent, { doc, modifiedBy, tagNameById });
|
|
17125
|
+
return /* @__PURE__ */ jsx(
|
|
17126
|
+
ExplorerFileTile,
|
|
17127
|
+
{
|
|
17128
|
+
id: doc.external_id,
|
|
17129
|
+
title: getDocumentTitle(doc, doc.file_name ?? ""),
|
|
17130
|
+
density,
|
|
17131
|
+
selected,
|
|
17132
|
+
dragging,
|
|
17133
|
+
renaming,
|
|
17134
|
+
thumbnailUrl,
|
|
17135
|
+
renderFileIcon: (size) => /* @__PURE__ */ jsx(Icon, { size, className: "drop-shadow-sm" }),
|
|
17136
|
+
progress: isProcessing ? { label: STATUS_LABEL[status] ?? status, queued: status === "queued" } : void 0,
|
|
17137
|
+
statusMarker: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", children: [
|
|
17138
|
+
/* @__PURE__ */ jsx(TileVisibilityBadge, { doc }),
|
|
17139
|
+
showStatusMarker && /* @__PURE__ */ jsx(TileStatusBadge, { doc, status })
|
|
17140
|
+
] }),
|
|
17141
|
+
offlineMarker: isOffline ? /* @__PURE__ */ jsx(DocumentSyncGlyph, { docExtId: doc.external_id, size: 24, bgClassName: "bg-primary" }) : void 0,
|
|
17142
|
+
entity: /* @__PURE__ */ jsx(
|
|
17143
|
+
DocumentEntity,
|
|
17144
|
+
{
|
|
17145
|
+
doc,
|
|
17146
|
+
labelMaxWidth: "max-w-full",
|
|
17147
|
+
noClamp: true,
|
|
17148
|
+
labelClassName: "whitespace-normal line-clamp-2 break-words",
|
|
17149
|
+
viewing: isViewing,
|
|
17150
|
+
tooltipContent: /* @__PURE__ */ jsx(FileTooltipContent, { doc, modifiedBy, tagNameById }),
|
|
17151
|
+
className: cn(
|
|
17152
|
+
"w-full min-w-0 max-w-full bg-background/90 backdrop-blur-sm",
|
|
17153
|
+
density === "list" ? "text-xs" : void 0
|
|
17154
|
+
),
|
|
17155
|
+
onClick: (e) => {
|
|
17156
|
+
e.stopPropagation();
|
|
17157
|
+
onOpen(doc);
|
|
17158
|
+
}
|
|
17159
|
+
}
|
|
17160
|
+
),
|
|
17161
|
+
tooltip,
|
|
17162
|
+
menuItems,
|
|
17163
|
+
rootRef: setNodeRef,
|
|
17164
|
+
rootProps: { ...listeners2, ...attributes },
|
|
17165
|
+
onOpen: () => onOpen(doc),
|
|
17166
|
+
onSelect: (e) => onSelect(doc, e),
|
|
17167
|
+
onToggle: (e) => onToggle(doc, e),
|
|
17168
|
+
onCommitRename: (name) => onCommitRename(doc, name),
|
|
17169
|
+
onCancelRename
|
|
17170
|
+
}
|
|
17171
|
+
);
|
|
17172
|
+
});
|
|
17173
|
+
var FolderTile = memo(function FolderTile2({
|
|
17174
|
+
folder,
|
|
17175
|
+
density,
|
|
17176
|
+
editing,
|
|
17177
|
+
selected,
|
|
17178
|
+
partiallySelected,
|
|
17179
|
+
documents,
|
|
17180
|
+
onOpen,
|
|
17181
|
+
onToggleSelect,
|
|
17182
|
+
onCommitName,
|
|
17183
|
+
onCancelName,
|
|
17184
|
+
onStartRename,
|
|
17185
|
+
onDownload,
|
|
17186
|
+
onMove,
|
|
17187
|
+
onDelete
|
|
17188
|
+
}) {
|
|
17189
|
+
const { setNodeRef, isOver } = useDroppable({
|
|
17190
|
+
id: `folder:${folder.path.join("/")}`,
|
|
17191
|
+
data: { type: "folder", path: folder.path }
|
|
17192
|
+
});
|
|
17193
|
+
const { startItemsForFolder } = useFilesSupport();
|
|
17194
|
+
const tasks = useProcessingTasks();
|
|
17195
|
+
const processingCount = useMemo(
|
|
17196
|
+
() => documents.filter(
|
|
17197
|
+
(doc) => isActiveDocumentStatus(tasks[doc.external_id]?.status ?? doc.status ?? "")
|
|
17198
|
+
).length,
|
|
17199
|
+
[documents, tasks]
|
|
17200
|
+
);
|
|
17201
|
+
const isEmpty = folder.count === 0;
|
|
17202
|
+
const iconSize = density === "list" ? 34 : 48;
|
|
17203
|
+
const menuItems = [
|
|
17204
|
+
...onStartRename ? [{ id: "rename", label: "Rename", icon: Pencil, onSelect: () => onStartRename(folder) }] : [],
|
|
17205
|
+
...!isEmpty ? startMenuItem(startItemsForFolder?.(folder.path.join("/")) ?? []) : [],
|
|
17206
|
+
...onDownload && !isEmpty ? [{ id: "download", label: "Download", icon: Download, onSelect: () => onDownload(folder) }] : [],
|
|
17207
|
+
...onMove && !isEmpty ? [{ id: "move", label: "Move to\u2026", icon: FolderInput, onSelect: () => onMove(folder) }] : [],
|
|
17208
|
+
...onDelete ? [
|
|
17209
|
+
{
|
|
17210
|
+
id: "delete",
|
|
17211
|
+
label: "Delete",
|
|
17212
|
+
icon: Trash2,
|
|
17213
|
+
onSelect: () => onDelete(folder),
|
|
17214
|
+
destructive: true,
|
|
17215
|
+
separatorBefore: true
|
|
17216
|
+
}
|
|
17217
|
+
] : []
|
|
17218
|
+
];
|
|
17219
|
+
const displayName = folder.path.length === 1 ? formatFolderSegment(folder.name) : folder.name;
|
|
17220
|
+
const providerIcon = folder.path.length === 1 && hasFolderProviderIcon(folder.name) ? /* @__PURE__ */ jsx(
|
|
17221
|
+
"span",
|
|
17222
|
+
{
|
|
17223
|
+
className: "flex items-center justify-center drop-shadow-sm",
|
|
17224
|
+
style: { width: iconSize, height: iconSize },
|
|
17225
|
+
children: /* @__PURE__ */ jsx(FolderProviderIcon, { folderPath: folder.name, className: "h-full w-full" })
|
|
17226
|
+
}
|
|
17227
|
+
) : void 0;
|
|
17228
|
+
return /* @__PURE__ */ jsx(
|
|
17229
|
+
ExplorerFolderTile,
|
|
17230
|
+
{
|
|
17231
|
+
name: folder.name,
|
|
17232
|
+
displayName: displayName === "" ? null : displayName,
|
|
17233
|
+
path: folder.path,
|
|
17234
|
+
count: folder.count,
|
|
17235
|
+
density,
|
|
17236
|
+
editing,
|
|
17237
|
+
selected,
|
|
17238
|
+
partiallySelected,
|
|
17239
|
+
processingCount,
|
|
17240
|
+
isOver,
|
|
17241
|
+
icon: providerIcon,
|
|
17242
|
+
menuItems,
|
|
17243
|
+
rootRef: setNodeRef,
|
|
17244
|
+
onOpen: () => onOpen(folder),
|
|
17245
|
+
onToggleSelect: onToggleSelect ? (e) => onToggleSelect(folder, e) : void 0,
|
|
17246
|
+
onCommitName: (name) => onCommitName?.(folder, name),
|
|
17247
|
+
onCancelName
|
|
17248
|
+
}
|
|
17249
|
+
);
|
|
17250
|
+
});
|
|
17251
|
+
var GRID_GAP = 12;
|
|
17252
|
+
var SCROLL_PADDING_X = 32;
|
|
17253
|
+
var PAGE_ASPECT = 1.3;
|
|
17254
|
+
var TILE_MIN = 88;
|
|
17255
|
+
var TILE_MAX = 232;
|
|
17256
|
+
var TILE_DEFAULT = 200;
|
|
17257
|
+
var COMPACT_BELOW = 132;
|
|
17258
|
+
var NO_DOCUMENTS = [];
|
|
17259
|
+
function useFilesWorkspace() {
|
|
17260
|
+
const { workspaceId, userId, live } = useConnectedWorkspace();
|
|
17261
|
+
const { members, role } = useConnectedWorkspaceRole();
|
|
17262
|
+
const { data: workspaces } = useWorkspaces({ enabled: live });
|
|
17263
|
+
const workspaceName = workspaces?.find((w) => w.external_id === workspaceId)?.name;
|
|
17264
|
+
return {
|
|
17265
|
+
workspaceId: workspaceId ?? "",
|
|
17266
|
+
workspaceName,
|
|
17267
|
+
userId,
|
|
17268
|
+
role: role ?? null,
|
|
17269
|
+
members
|
|
17270
|
+
};
|
|
17271
|
+
}
|
|
17272
|
+
var ConnectedFilesExplorer = forwardRef(function ConnectedFilesExplorer2({
|
|
17273
|
+
documents,
|
|
17274
|
+
isLoading,
|
|
17275
|
+
canUpload,
|
|
17276
|
+
selectedIds,
|
|
17277
|
+
onSelectionChange,
|
|
17278
|
+
onOrderedFilesChange,
|
|
17279
|
+
onOpenDocument,
|
|
17280
|
+
onUploadFiles,
|
|
17281
|
+
folderPath,
|
|
17282
|
+
onFolderPathChange,
|
|
17283
|
+
search = "",
|
|
17284
|
+
sort,
|
|
17285
|
+
sortReversed,
|
|
17286
|
+
tileSize,
|
|
17287
|
+
onMoveSelected,
|
|
17288
|
+
onFolderMove,
|
|
17289
|
+
onOpenInReview,
|
|
17290
|
+
emptyWorkspace
|
|
17291
|
+
}, ref) {
|
|
17292
|
+
const { confirm, notify: notify14 } = useBlocksEnvironment();
|
|
17293
|
+
const currentPath = folderPath;
|
|
17294
|
+
const density = tileSize < COMPACT_BELOW ? "list" : "grid";
|
|
17295
|
+
const [containerWidth, setContainerWidth] = useState(0);
|
|
17296
|
+
const [activeDragId, setActiveDragId] = useState(null);
|
|
17297
|
+
const [isFileDragOver, setIsFileDragOver] = useState(false);
|
|
17298
|
+
const [renamingId, setRenamingId] = useState(null);
|
|
17299
|
+
const scrollRef = useRef(null);
|
|
17300
|
+
const anchorRef = useRef(null);
|
|
17301
|
+
const dragIdsRef = useRef([]);
|
|
17302
|
+
const fileDragDepth = useRef(0);
|
|
17303
|
+
const marqueeOverlayRef = useRef(null);
|
|
17304
|
+
const marqueeRef = useRef(
|
|
17305
|
+
null
|
|
17306
|
+
);
|
|
17307
|
+
const didMarqueeRef = useRef(false);
|
|
17308
|
+
const updateDocument = useUpdateDocuments();
|
|
17309
|
+
const deleteDocuments = useDeleteDocuments();
|
|
17310
|
+
const renameFolder = useRenameFolder();
|
|
17311
|
+
const { workspaceId: wsId, workspaceName, userId, role, members } = useFilesWorkspace();
|
|
17312
|
+
const { downloadDocuments, downloadDocument } = useDownloadDocuments({ workspaceName });
|
|
17313
|
+
const { data: workspaceTags } = useTags();
|
|
17314
|
+
const userById = useMemo(() => {
|
|
17315
|
+
const map = /* @__PURE__ */ new Map();
|
|
17316
|
+
for (const member of members) map.set(member.user.external_id, member.user);
|
|
17317
|
+
return map;
|
|
17318
|
+
}, [members]);
|
|
17319
|
+
const tagNameById = useMemo(() => {
|
|
17320
|
+
const map = /* @__PURE__ */ new Map();
|
|
17321
|
+
for (const tag of workspaceTags ?? []) map.set(tag.external_id, tag.name);
|
|
17322
|
+
return map;
|
|
17323
|
+
}, [workspaceTags]);
|
|
17324
|
+
const pendingFolders = usePendingFolders(wsId);
|
|
17325
|
+
const addPendingFolder = useFilesStore((state) => state.addPendingFolder);
|
|
17326
|
+
const removePendingFolder = useFilesStore((state) => state.removePendingFolder);
|
|
17327
|
+
const [editingFolderPath, setEditingFolderPath] = useState(null);
|
|
17328
|
+
const isSearching = search.trim().length > 0;
|
|
17329
|
+
const selectedSet = useMemo(() => new Set(selectedIds), [selectedIds]);
|
|
17330
|
+
const selectedIdsRef = useRef(selectedIds);
|
|
17331
|
+
selectedIdsRef.current = selectedIds;
|
|
17332
|
+
const { folders, files } = useMemo(() => {
|
|
17333
|
+
const result = isSearching ? {
|
|
17334
|
+
folders: [],
|
|
17335
|
+
files: searchExplorerDocuments(documents, search, sort)
|
|
17336
|
+
} : buildExplorerEntries(documents, currentPath, sort, [...pendingFolders]);
|
|
17337
|
+
if (sortReversed) result.files = [...result.files].reverse();
|
|
17338
|
+
return result;
|
|
17339
|
+
}, [documents, currentPath, sort, isSearching, search, sortReversed, pendingFolders]);
|
|
17340
|
+
const entries = useMemo(
|
|
17341
|
+
() => [...folders, ...files.map((doc) => ({ kind: "file", doc }))],
|
|
17342
|
+
[folders, files]
|
|
17343
|
+
);
|
|
17344
|
+
const orderedFileIds = useMemo(() => files.map((d) => d.external_id), [files]);
|
|
17345
|
+
const folderDocs = useMemo(() => {
|
|
17346
|
+
const map = /* @__PURE__ */ new Map();
|
|
17347
|
+
for (const f of folders) map.set(f.path.join("/"), collectFolderDocs(documents, f.path));
|
|
17348
|
+
return map;
|
|
17349
|
+
}, [folders, documents]);
|
|
17350
|
+
const folderSelection = useMemo(() => {
|
|
17351
|
+
const map = /* @__PURE__ */ new Map();
|
|
17352
|
+
for (const [key, docs] of folderDocs) {
|
|
17353
|
+
const sel = docs.reduce((n, d) => selectedSet.has(d.external_id) ? n + 1 : n, 0);
|
|
17354
|
+
map.set(key, { all: docs.length > 0 && sel === docs.length, some: sel > 0 });
|
|
17355
|
+
}
|
|
17356
|
+
return map;
|
|
17357
|
+
}, [folderDocs, selectedSet]);
|
|
17358
|
+
const contentWidth = Math.max(0, containerWidth - SCROLL_PADDING_X);
|
|
17359
|
+
const columnCount = Math.max(
|
|
17360
|
+
1,
|
|
17361
|
+
Math.floor((contentWidth + GRID_GAP) / (tileSize + GRID_GAP)) || 1
|
|
17362
|
+
);
|
|
17363
|
+
const colWidth = contentWidth > 0 ? (contentWidth - (columnCount - 1) * GRID_GAP) / columnCount : tileSize;
|
|
17364
|
+
const tileHeight = Math.max(120, Math.round(colWidth * PAGE_ASPECT));
|
|
17365
|
+
const rowHeight = tileHeight + GRID_GAP;
|
|
17366
|
+
const rowCount = Math.ceil(entries.length / columnCount);
|
|
17367
|
+
const rowVirtualizer = useVirtualizer({
|
|
17368
|
+
count: rowCount,
|
|
17369
|
+
getScrollElement: () => scrollRef.current,
|
|
17370
|
+
estimateSize: () => rowHeight,
|
|
17371
|
+
overscan: 3
|
|
17372
|
+
});
|
|
17373
|
+
const virtualRows = rowVirtualizer.getVirtualItems();
|
|
17374
|
+
const firstRow = virtualRows.length > 0 ? virtualRows[0].index : 0;
|
|
17375
|
+
const lastRow = virtualRows.length > 0 ? virtualRows[virtualRows.length - 1].index : -1;
|
|
17376
|
+
const visibleFileIds = useMemo(() => {
|
|
17377
|
+
const ids = [];
|
|
17378
|
+
for (let r = firstRow; r <= lastRow; r++) {
|
|
17379
|
+
const start = r * columnCount;
|
|
17380
|
+
for (let c = 0; c < columnCount; c++) {
|
|
17381
|
+
const entry = entries[start + c];
|
|
17382
|
+
if (entry?.kind === "file") ids.push(entry.doc.external_id);
|
|
17383
|
+
}
|
|
17384
|
+
}
|
|
17385
|
+
return ids;
|
|
17386
|
+
}, [firstRow, lastRow, columnCount, entries]);
|
|
17387
|
+
const thumbnailsById = useDocumentThumbnails(visibleFileIds);
|
|
17388
|
+
useEffect(() => {
|
|
17389
|
+
rowVirtualizer.measure();
|
|
17390
|
+
}, [rowVirtualizer, columnCount, rowHeight, entries.length]);
|
|
17391
|
+
const isWholeWorkspaceEmpty = !isLoading && documents.length === 0 && canUpload && emptyWorkspace !== void 0;
|
|
17392
|
+
useLayoutEffect(() => {
|
|
17393
|
+
const el = scrollRef.current;
|
|
17394
|
+
if (!el) return;
|
|
17395
|
+
const apply = () => {
|
|
17396
|
+
const next = Math.round(el.clientWidth);
|
|
17397
|
+
setContainerWidth((prev) => prev === next ? prev : next);
|
|
17398
|
+
};
|
|
17399
|
+
apply();
|
|
17400
|
+
const ro = new ResizeObserver(apply);
|
|
17401
|
+
ro.observe(el);
|
|
17402
|
+
return () => ro.disconnect();
|
|
17403
|
+
}, [isWholeWorkspaceEmpty]);
|
|
17404
|
+
useEffect(() => {
|
|
17405
|
+
anchorRef.current = null;
|
|
17406
|
+
if (scrollRef.current) scrollRef.current.scrollTop = 0;
|
|
17407
|
+
}, [currentPath, search]);
|
|
17408
|
+
useEffect(() => {
|
|
17409
|
+
const MARQUEE_THRESHOLD = 5;
|
|
17410
|
+
let rafId = 0;
|
|
17411
|
+
let cur = null;
|
|
17412
|
+
const paint = () => {
|
|
17413
|
+
rafId = 0;
|
|
17414
|
+
const el = marqueeOverlayRef.current;
|
|
17415
|
+
if (!el || !cur) return;
|
|
17416
|
+
el.style.display = "block";
|
|
17417
|
+
el.style.left = `${cur.left}px`;
|
|
17418
|
+
el.style.top = `${cur.top}px`;
|
|
17419
|
+
el.style.width = `${cur.right - cur.left}px`;
|
|
17420
|
+
el.style.height = `${cur.bottom - cur.top}px`;
|
|
17421
|
+
};
|
|
17422
|
+
const onMove = (e) => {
|
|
17423
|
+
const m = marqueeRef.current;
|
|
17424
|
+
if (!m) return;
|
|
17425
|
+
if (!didMarqueeRef.current && Math.hypot(e.clientX - m.x, e.clientY - m.y) < MARQUEE_THRESHOLD)
|
|
17426
|
+
return;
|
|
17427
|
+
didMarqueeRef.current = true;
|
|
17428
|
+
const b = scrollRef.current?.getBoundingClientRect();
|
|
17429
|
+
const px = b ? Math.max(b.left, Math.min(e.clientX, b.right)) : e.clientX;
|
|
17430
|
+
const py = b ? Math.max(b.top, Math.min(e.clientY, b.bottom)) : e.clientY;
|
|
17431
|
+
cur = {
|
|
17432
|
+
left: Math.min(m.x, px),
|
|
17433
|
+
top: Math.min(m.y, py),
|
|
17434
|
+
right: Math.max(m.x, px),
|
|
17435
|
+
bottom: Math.max(m.y, py)
|
|
17436
|
+
};
|
|
17437
|
+
if (!rafId) rafId = requestAnimationFrame(paint);
|
|
17438
|
+
};
|
|
17439
|
+
const onUp = () => {
|
|
17440
|
+
const m = marqueeRef.current;
|
|
17441
|
+
if (!m) return;
|
|
17442
|
+
marqueeRef.current = null;
|
|
17443
|
+
if (rafId) cancelAnimationFrame(rafId);
|
|
17444
|
+
rafId = 0;
|
|
17445
|
+
const el = marqueeOverlayRef.current;
|
|
17446
|
+
if (el) el.style.display = "none";
|
|
17447
|
+
if (!didMarqueeRef.current || !cur) return;
|
|
17448
|
+
const box = cur;
|
|
17449
|
+
const hit = [];
|
|
17450
|
+
scrollRef.current?.querySelectorAll("[data-doc-id]").forEach((node) => {
|
|
17451
|
+
const r = node.getBoundingClientRect();
|
|
17452
|
+
if (r.left < box.right && r.right > box.left && r.top < box.bottom && r.bottom > box.top) {
|
|
17453
|
+
const id = node.getAttribute("data-doc-id");
|
|
17454
|
+
if (id) hit.push(id);
|
|
17455
|
+
}
|
|
17456
|
+
});
|
|
17457
|
+
onSelectionChange(m.additive ? Array.from(/* @__PURE__ */ new Set([...m.base, ...hit])) : hit);
|
|
17458
|
+
};
|
|
17459
|
+
window.addEventListener("pointermove", onMove);
|
|
17460
|
+
window.addEventListener("pointerup", onUp);
|
|
17461
|
+
return () => {
|
|
17462
|
+
window.removeEventListener("pointermove", onMove);
|
|
17463
|
+
window.removeEventListener("pointerup", onUp);
|
|
17464
|
+
if (rafId) cancelAnimationFrame(rafId);
|
|
17465
|
+
};
|
|
17466
|
+
}, [onSelectionChange]);
|
|
17467
|
+
const handleScrollPointerDown = useCallback((e) => {
|
|
17468
|
+
if (e.button !== 0) return;
|
|
17469
|
+
const el = e.target;
|
|
17470
|
+
if (el.closest(
|
|
17471
|
+
'[data-testid="explorer-file"],[data-testid="explorer-folder"],button,input,select,a,[role="button"]'
|
|
17472
|
+
)) {
|
|
17473
|
+
return;
|
|
17474
|
+
}
|
|
17475
|
+
const additive = e.shiftKey || e.metaKey || e.ctrlKey;
|
|
17476
|
+
marqueeRef.current = {
|
|
17477
|
+
x: e.clientX,
|
|
17478
|
+
y: e.clientY,
|
|
17479
|
+
additive,
|
|
17480
|
+
base: additive ? selectedIdsRef.current : []
|
|
17481
|
+
};
|
|
17482
|
+
didMarqueeRef.current = false;
|
|
17483
|
+
}, []);
|
|
17484
|
+
const openFolder = useCallback(
|
|
17485
|
+
(folder) => onFolderPathChange(folder.path),
|
|
17486
|
+
[onFolderPathChange]
|
|
17487
|
+
);
|
|
17488
|
+
const handleNewFolder = useCallback(() => {
|
|
17489
|
+
if (!wsId) return;
|
|
17490
|
+
const siblings = new Set(folders.map((f) => f.name.toLowerCase()));
|
|
17491
|
+
const base = "New folder";
|
|
17492
|
+
let name = base;
|
|
17493
|
+
let i = 2;
|
|
17494
|
+
while (siblings.has(name.toLowerCase())) name = `${base} ${i++}`;
|
|
17495
|
+
const path = joinFolderPath([...currentPath, name]);
|
|
17496
|
+
if (!path) return;
|
|
17497
|
+
addPendingFolder(wsId, path);
|
|
17498
|
+
setEditingFolderPath(path);
|
|
17499
|
+
}, [wsId, folders, currentPath, addPendingFolder]);
|
|
17500
|
+
const lastOrderedRef = useRef([]);
|
|
17501
|
+
useEffect(() => {
|
|
17502
|
+
const prev = lastOrderedRef.current;
|
|
17503
|
+
if (prev.length === orderedFileIds.length && prev.every((id, i) => id === orderedFileIds[i])) {
|
|
17504
|
+
return;
|
|
17505
|
+
}
|
|
17506
|
+
lastOrderedRef.current = orderedFileIds;
|
|
17507
|
+
onOrderedFilesChange?.(orderedFileIds);
|
|
17508
|
+
}, [onOrderedFilesChange, orderedFileIds]);
|
|
17509
|
+
const scrollToDocument = useCallback(
|
|
17510
|
+
(docId) => {
|
|
17511
|
+
const index = entries.findIndex((e) => e.kind === "file" && e.doc.external_id === docId);
|
|
17512
|
+
if (index < 0) return;
|
|
17513
|
+
rowVirtualizer.scrollToIndex(Math.floor(index / columnCount), { align: "center" });
|
|
17514
|
+
},
|
|
17515
|
+
[entries, columnCount, rowVirtualizer]
|
|
17516
|
+
);
|
|
17517
|
+
useImperativeHandle(ref, () => ({ triggerNewFolder: handleNewFolder, scrollToDocument }), [
|
|
17518
|
+
handleNewFolder,
|
|
17519
|
+
scrollToDocument
|
|
17520
|
+
]);
|
|
17521
|
+
const commitFolderName = useCallback(
|
|
17522
|
+
async (folder, rawName) => {
|
|
17523
|
+
setEditingFolderPath(null);
|
|
17524
|
+
const name = rawName.trim();
|
|
17525
|
+
if (!wsId || !name || name === folder.name) return;
|
|
17526
|
+
const siblings = new Set(folders.filter((f) => f !== folder).map((f) => f.name.toLowerCase()));
|
|
17527
|
+
if (siblings.has(name.toLowerCase())) {
|
|
17528
|
+
notify14(`A folder named "${name}" already exists here.`, "error");
|
|
17529
|
+
return;
|
|
17530
|
+
}
|
|
17531
|
+
const oldPath = joinFolderPath(folder.path);
|
|
17532
|
+
const newPrefix = [...folder.path.slice(0, -1), name];
|
|
17533
|
+
const newPath = joinFolderPath(newPrefix);
|
|
17534
|
+
const docs = collectFolderDocs(documents, folder.path);
|
|
17535
|
+
try {
|
|
17536
|
+
if (await renameFolder(docs, folder.path, newPrefix) > 0) {
|
|
17537
|
+
notify14(`Renamed folder to "${name}"`, "success");
|
|
17538
|
+
}
|
|
17539
|
+
} catch {
|
|
17540
|
+
notify14("Failed to rename folder. Please try again.", "error");
|
|
17541
|
+
return;
|
|
17542
|
+
}
|
|
17543
|
+
if (oldPath) removePendingFolder(wsId, oldPath);
|
|
17544
|
+
if (docs.length === 0 && newPath) addPendingFolder(wsId, newPath);
|
|
17545
|
+
},
|
|
17546
|
+
[wsId, folders, documents, renameFolder, notify14, addPendingFolder, removePendingFolder]
|
|
17547
|
+
);
|
|
17548
|
+
const cancelFolderName = useCallback(() => setEditingFolderPath(null), []);
|
|
17549
|
+
const clearSelection = useCallback(() => {
|
|
17550
|
+
if (selectedIdsRef.current.length > 0) onSelectionChange([]);
|
|
17551
|
+
anchorRef.current = null;
|
|
17552
|
+
}, [onSelectionChange]);
|
|
17553
|
+
const handleSelect = useCallback(
|
|
17554
|
+
(doc, e) => {
|
|
17555
|
+
const id = doc.external_id;
|
|
17556
|
+
if (e.shiftKey) {
|
|
17557
|
+
const from = anchorRef.current ?? id;
|
|
17558
|
+
const a = orderedFileIds.indexOf(from);
|
|
17559
|
+
const b = orderedFileIds.indexOf(id);
|
|
17560
|
+
if (a !== -1 && b !== -1) {
|
|
17561
|
+
anchorRef.current = from;
|
|
17562
|
+
const [lo, hi] = a < b ? [a, b] : [b, a];
|
|
17563
|
+
onSelectionChange(orderedFileIds.slice(lo, hi + 1));
|
|
17564
|
+
return;
|
|
17565
|
+
}
|
|
17566
|
+
}
|
|
17567
|
+
if (e.metaKey || e.ctrlKey) {
|
|
17568
|
+
onSelectionChange(
|
|
17569
|
+
selectedSet.has(id) ? selectedIds.filter((s) => s !== id) : [...selectedIds, id]
|
|
17570
|
+
);
|
|
17571
|
+
anchorRef.current = id;
|
|
17572
|
+
return;
|
|
17573
|
+
}
|
|
17574
|
+
onSelectionChange([id]);
|
|
17575
|
+
anchorRef.current = id;
|
|
17576
|
+
},
|
|
17577
|
+
[onSelectionChange, orderedFileIds, selectedIds, selectedSet]
|
|
17578
|
+
);
|
|
17579
|
+
const handleToggle = useCallback(
|
|
17580
|
+
(doc, e) => {
|
|
17581
|
+
e.stopPropagation();
|
|
17582
|
+
const id = doc.external_id;
|
|
17583
|
+
onSelectionChange(
|
|
17584
|
+
selectedSet.has(id) ? selectedIds.filter((s) => s !== id) : [...selectedIds, id]
|
|
17585
|
+
);
|
|
17586
|
+
anchorRef.current = id;
|
|
17587
|
+
},
|
|
17588
|
+
[onSelectionChange, selectedIds, selectedSet]
|
|
17589
|
+
);
|
|
17590
|
+
const handleToggleFolder = useCallback(
|
|
17591
|
+
(folder, e) => {
|
|
17592
|
+
e.stopPropagation();
|
|
17593
|
+
const ids = collectFolderDocs(documents, folder.path).map((d) => d.external_id);
|
|
17594
|
+
if (ids.length === 0) return;
|
|
17595
|
+
if (ids.every((id) => selectedSet.has(id))) {
|
|
17596
|
+
const remove = new Set(ids);
|
|
17597
|
+
onSelectionChange(selectedIds.filter((id) => !remove.has(id)));
|
|
17598
|
+
} else {
|
|
17599
|
+
onSelectionChange(Array.from(/* @__PURE__ */ new Set([...selectedIds, ...ids])));
|
|
17600
|
+
}
|
|
17601
|
+
anchorRef.current = null;
|
|
17602
|
+
},
|
|
17603
|
+
[documents, onSelectionChange, selectedIds, selectedSet]
|
|
17604
|
+
);
|
|
17605
|
+
const handleOpenFile = useCallback(
|
|
17606
|
+
(doc) => onOpenDocument(doc.external_id),
|
|
17607
|
+
[onOpenDocument]
|
|
17608
|
+
);
|
|
17609
|
+
const handleOpenInReview = useMemo(
|
|
17610
|
+
() => onOpenInReview ? (doc) => onOpenInReview(doc.external_id) : void 0,
|
|
17611
|
+
[onOpenInReview]
|
|
17612
|
+
);
|
|
17613
|
+
const startRename = useCallback((doc) => setRenamingId(doc.external_id), []);
|
|
17614
|
+
const cancelRename = useCallback(() => setRenamingId(null), []);
|
|
17615
|
+
const commitRename = useCallback(
|
|
17616
|
+
async (doc, name) => {
|
|
17617
|
+
setRenamingId(null);
|
|
17618
|
+
try {
|
|
17619
|
+
await updateDocument.mutateAsync({
|
|
17620
|
+
documents: [
|
|
17621
|
+
{ external_id: doc.external_id, doc_metadata: { ...doc.doc_metadata, title: name } }
|
|
17622
|
+
]
|
|
17623
|
+
});
|
|
17624
|
+
notify14(`Renamed to "${name}"`, "success");
|
|
17625
|
+
} catch {
|
|
17626
|
+
notify14("Failed to rename. Please try again.", "error");
|
|
17627
|
+
}
|
|
17628
|
+
},
|
|
17629
|
+
[updateDocument, notify14]
|
|
17630
|
+
);
|
|
17631
|
+
useEffect(() => {
|
|
17632
|
+
const onKey = (e) => {
|
|
17633
|
+
if (e.key !== "F2" || renamingId) return;
|
|
17634
|
+
const target = e.target;
|
|
17635
|
+
if (target && /^(input|textarea|select)$/i.test(target.tagName)) return;
|
|
17636
|
+
if (selectedIdsRef.current.length === 1) setRenamingId(selectedIdsRef.current[0]);
|
|
17637
|
+
};
|
|
17638
|
+
window.addEventListener("keydown", onKey);
|
|
17639
|
+
return () => window.removeEventListener("keydown", onKey);
|
|
17640
|
+
}, [renamingId]);
|
|
17641
|
+
const handleDownload = useCallback(
|
|
17642
|
+
(doc) => void downloadDocument(doc),
|
|
17643
|
+
[downloadDocument]
|
|
17644
|
+
);
|
|
17645
|
+
const handleMove = useMemo(
|
|
17646
|
+
() => onMoveSelected ? (doc) => {
|
|
17647
|
+
onSelectionChange([doc.external_id]);
|
|
17648
|
+
onMoveSelected();
|
|
17649
|
+
} : void 0,
|
|
17650
|
+
[onSelectionChange, onMoveSelected]
|
|
17651
|
+
);
|
|
17652
|
+
const handleDelete = useCallback(
|
|
17653
|
+
async (doc) => {
|
|
17654
|
+
const name = getExplorerDisplayName(doc);
|
|
17655
|
+
const confirmed = await confirm({
|
|
17656
|
+
message: `Delete "${name}"? ${RECENTLY_DELETED_HINT}`,
|
|
17657
|
+
title: "Delete file"
|
|
17658
|
+
});
|
|
17659
|
+
if (!confirmed) return;
|
|
17660
|
+
try {
|
|
17661
|
+
await deleteDocuments.mutateAsync([doc.external_id]);
|
|
17662
|
+
onSelectionChange(selectedIdsRef.current.filter((id) => id !== doc.external_id));
|
|
17663
|
+
notify14(`Deleted "${name}"`, "success");
|
|
17664
|
+
} catch {
|
|
17665
|
+
notify14("Failed to delete. Please try again.", "error");
|
|
17666
|
+
}
|
|
17667
|
+
},
|
|
17668
|
+
[confirm, deleteDocuments, onSelectionChange, notify14]
|
|
17669
|
+
);
|
|
17670
|
+
const startFolderRename = useCallback(
|
|
17671
|
+
(folder) => setEditingFolderPath(folder.path.join("/")),
|
|
17672
|
+
[]
|
|
17673
|
+
);
|
|
17674
|
+
const handleFolderDownload = useCallback(
|
|
17675
|
+
(folder) => {
|
|
17676
|
+
const docs = collectFolderDocs(documents, folder.path);
|
|
17677
|
+
if (docs.length > 0) void downloadDocuments(docs);
|
|
17678
|
+
},
|
|
17679
|
+
[documents, downloadDocuments]
|
|
17680
|
+
);
|
|
17681
|
+
const handleFolderMove = useMemo(() => {
|
|
17682
|
+
if (onFolderMove) return onFolderMove;
|
|
17683
|
+
if (!onMoveSelected) return void 0;
|
|
17684
|
+
return (folder) => {
|
|
17685
|
+
const ids = collectFolderDocs(documents, folder.path).map((d) => d.external_id);
|
|
17686
|
+
if (ids.length === 0) return;
|
|
17687
|
+
onSelectionChange(ids);
|
|
17688
|
+
onMoveSelected();
|
|
17689
|
+
};
|
|
17690
|
+
}, [documents, onFolderMove, onMoveSelected, onSelectionChange]);
|
|
17691
|
+
const handleFolderDelete = useCallback(
|
|
17692
|
+
async (folder) => {
|
|
17693
|
+
const docs = collectFolderDocs(documents, folder.path);
|
|
17694
|
+
if (docs.length === 0) {
|
|
17695
|
+
const path = joinFolderPath(folder.path);
|
|
17696
|
+
if (wsId && path) removePendingFolder(wsId, path);
|
|
17697
|
+
return;
|
|
17698
|
+
}
|
|
17699
|
+
const confirmed = await confirm({
|
|
17700
|
+
message: `Delete folder "${folder.name}" and its ${docs.length} item${docs.length === 1 ? "" : "s"}? ${RECENTLY_DELETED_HINT_PLURAL}`,
|
|
17701
|
+
title: "Delete folder"
|
|
17702
|
+
});
|
|
17703
|
+
if (!confirmed) return;
|
|
17704
|
+
try {
|
|
17705
|
+
const ids = docs.map((d) => d.external_id);
|
|
17706
|
+
await deleteDocuments.mutateAsync(ids);
|
|
17707
|
+
const removed = new Set(ids);
|
|
17708
|
+
onSelectionChange(selectedIdsRef.current.filter((id) => !removed.has(id)));
|
|
17709
|
+
notify14(`Deleted folder "${folder.name}"`, "success");
|
|
17710
|
+
} catch {
|
|
17711
|
+
notify14("Failed to delete folder. Please try again.", "error");
|
|
17712
|
+
}
|
|
17713
|
+
},
|
|
17714
|
+
[confirm, documents, deleteDocuments, onSelectionChange, removePendingFolder, wsId, notify14]
|
|
17715
|
+
);
|
|
17716
|
+
const canDeleteFolder = useCallback(
|
|
17717
|
+
(folder) => canUpload && collectFolderDocs(documents, folder.path).every(
|
|
17718
|
+
(doc) => canDeleteDocument(doc, userId, role)
|
|
17719
|
+
),
|
|
17720
|
+
[canUpload, documents, userId, role]
|
|
17721
|
+
);
|
|
17722
|
+
const handleBackgroundClick = useCallback(
|
|
17723
|
+
(e) => {
|
|
17724
|
+
if (didMarqueeRef.current) {
|
|
17725
|
+
didMarqueeRef.current = false;
|
|
17726
|
+
return;
|
|
17727
|
+
}
|
|
17728
|
+
if (!e.target.closest('[data-testid^="explorer-"]')) clearSelection();
|
|
17729
|
+
},
|
|
17730
|
+
[clearSelection]
|
|
17731
|
+
);
|
|
17732
|
+
const moveDocs = useCallback(
|
|
17733
|
+
async (ids, folder) => {
|
|
17734
|
+
if (ids.length === 0) return;
|
|
17735
|
+
try {
|
|
17736
|
+
await updateDocument.mutateAsync({
|
|
17737
|
+
documents: ids.map((external_id) => ({ external_id, folder }))
|
|
17738
|
+
});
|
|
17739
|
+
clearSelection();
|
|
17740
|
+
notify14(
|
|
17741
|
+
`Moved ${ids.length} item${ids.length === 1 ? "" : "s"} to "${folder ?? "Home"}"`,
|
|
17742
|
+
"success"
|
|
17743
|
+
);
|
|
17744
|
+
} catch {
|
|
17745
|
+
notify14("Failed to move. Please try again.", "error");
|
|
17746
|
+
}
|
|
17747
|
+
},
|
|
17748
|
+
[updateDocument, clearSelection, notify14]
|
|
17749
|
+
);
|
|
17750
|
+
const sensors = useSensors(
|
|
17751
|
+
useSensor(MouseSensor, { activationConstraint: { distance: 6 } }),
|
|
17752
|
+
useSensor(TouchSensor, { activationConstraint: { delay: 150, tolerance: 8 } })
|
|
17753
|
+
);
|
|
17754
|
+
const collisionDetection = useCallback((args) => {
|
|
17755
|
+
const hits = pointerWithin(args);
|
|
17756
|
+
return hits.length > 0 ? hits : rectIntersection(args);
|
|
17757
|
+
}, []);
|
|
17758
|
+
const handleDragStart = useCallback(
|
|
17759
|
+
(event) => {
|
|
17760
|
+
const docId = event.active.data.current?.docId;
|
|
17761
|
+
if (!docId) return;
|
|
17762
|
+
setActiveDragId(docId);
|
|
17763
|
+
if (!selectedIdsRef.current.includes(docId)) {
|
|
17764
|
+
onSelectionChange([docId]);
|
|
17765
|
+
dragIdsRef.current = [docId];
|
|
17766
|
+
} else {
|
|
17767
|
+
dragIdsRef.current = selectedIdsRef.current;
|
|
17768
|
+
}
|
|
17769
|
+
},
|
|
17770
|
+
[onSelectionChange]
|
|
17771
|
+
);
|
|
17772
|
+
const handleDragEnd = useCallback(
|
|
17773
|
+
(event) => {
|
|
17774
|
+
setActiveDragId(null);
|
|
17775
|
+
const data = event.over?.data.current;
|
|
17776
|
+
if (data?.type === "folder" && data.path) {
|
|
17777
|
+
const targetFolder = joinFolderPath(data.path);
|
|
17778
|
+
const moving = dragIdsRef.current.filter((id) => {
|
|
17779
|
+
const doc = documents.find((d) => d.external_id === id);
|
|
17780
|
+
return doc && (doc.folder ?? null) !== targetFolder;
|
|
17781
|
+
});
|
|
17782
|
+
void moveDocs(moving, targetFolder);
|
|
17783
|
+
}
|
|
17784
|
+
},
|
|
17785
|
+
[documents, moveDocs]
|
|
17786
|
+
);
|
|
17787
|
+
const handleNativeDragOver = useCallback(
|
|
17788
|
+
(e) => {
|
|
17789
|
+
if (!canUpload) return;
|
|
17790
|
+
if (e.dataTransfer.types.includes("Files")) {
|
|
17791
|
+
e.preventDefault();
|
|
17792
|
+
e.dataTransfer.dropEffect = "copy";
|
|
17793
|
+
}
|
|
17794
|
+
},
|
|
17795
|
+
[canUpload]
|
|
17796
|
+
);
|
|
17797
|
+
const handleNativeDragEnter = useCallback(
|
|
17798
|
+
(e) => {
|
|
17799
|
+
if (!canUpload || !e.dataTransfer.types.includes("Files")) return;
|
|
17800
|
+
fileDragDepth.current += 1;
|
|
17801
|
+
setIsFileDragOver(true);
|
|
17802
|
+
},
|
|
17803
|
+
[canUpload]
|
|
17804
|
+
);
|
|
17805
|
+
const handleNativeDragLeave = useCallback(() => {
|
|
17806
|
+
fileDragDepth.current = Math.max(0, fileDragDepth.current - 1);
|
|
17807
|
+
if (fileDragDepth.current === 0) setIsFileDragOver(false);
|
|
17808
|
+
}, []);
|
|
17809
|
+
const handleNativeDrop = useCallback(
|
|
17810
|
+
(e) => {
|
|
17811
|
+
fileDragDepth.current = 0;
|
|
17812
|
+
setIsFileDragOver(false);
|
|
17813
|
+
if (!canUpload) return;
|
|
17814
|
+
const dropped = Array.from(e.dataTransfer.files ?? []);
|
|
17815
|
+
if (dropped.length > 0) {
|
|
17816
|
+
e.preventDefault();
|
|
17817
|
+
onUploadFiles(dropped, joinFolderPath(currentPath));
|
|
17818
|
+
}
|
|
17819
|
+
},
|
|
17820
|
+
[canUpload, currentPath, onUploadFiles]
|
|
17821
|
+
);
|
|
17822
|
+
const activeDoc = activeDragId ? documents.find((d) => d.external_id === activeDragId) : null;
|
|
17823
|
+
const dragCount = dragIdsRef.current.length || 1;
|
|
17824
|
+
if (isWholeWorkspaceEmpty) return /* @__PURE__ */ jsx(Fragment, { children: emptyWorkspace });
|
|
17825
|
+
return /* @__PURE__ */ jsxs(
|
|
17826
|
+
DndContext,
|
|
17827
|
+
{
|
|
17828
|
+
sensors,
|
|
17829
|
+
collisionDetection,
|
|
17830
|
+
onDragStart: handleDragStart,
|
|
17831
|
+
onDragEnd: handleDragEnd,
|
|
17832
|
+
onDragCancel: () => setActiveDragId(null),
|
|
17833
|
+
children: [
|
|
17834
|
+
/* @__PURE__ */ jsx(ExplorerFrame, { "data-testid": "documents-explorer", children: /* @__PURE__ */ jsxs(ExplorerStage, { children: [
|
|
17835
|
+
/* @__PURE__ */ jsx(
|
|
17836
|
+
ExplorerScroller,
|
|
17837
|
+
{
|
|
17838
|
+
ref: scrollRef,
|
|
17839
|
+
onClick: handleBackgroundClick,
|
|
17840
|
+
onPointerDown: handleScrollPointerDown,
|
|
17841
|
+
onDragEnter: handleNativeDragEnter,
|
|
17842
|
+
onDragOver: handleNativeDragOver,
|
|
17843
|
+
onDragLeave: handleNativeDragLeave,
|
|
17844
|
+
onDrop: handleNativeDrop,
|
|
17845
|
+
"data-testid": "explorer-scroll",
|
|
17846
|
+
children: isLoading && documents.length === 0 ? /* @__PURE__ */ jsx(ExplorerLoadingTiles, {}) : entries.length === 0 ? /* @__PURE__ */ jsx(
|
|
17847
|
+
ExplorerEmpty,
|
|
17848
|
+
{
|
|
17849
|
+
title: isSearching ? `No files match "${search.trim()}"` : "This folder is empty",
|
|
17850
|
+
description: isSearching ? "Try a different search." : canUpload ? "Drop files here or use Upload to add documents." : "No documents here yet."
|
|
17851
|
+
}
|
|
17852
|
+
) : containerWidth === 0 ? (
|
|
17853
|
+
// Not measured yet: rendering now would flash one stretched column.
|
|
17854
|
+
/* @__PURE__ */ jsx(ExplorerLoadingTiles, {})
|
|
17855
|
+
) : /* @__PURE__ */ jsx(
|
|
17856
|
+
"div",
|
|
17857
|
+
{
|
|
17858
|
+
style: {
|
|
17859
|
+
height: rowVirtualizer.getTotalSize(),
|
|
17860
|
+
position: "relative",
|
|
17861
|
+
width: "100%"
|
|
17862
|
+
},
|
|
17863
|
+
children: virtualRows.map((virtualRow) => {
|
|
17864
|
+
const start = virtualRow.index * columnCount;
|
|
17865
|
+
const rowEntries = entries.slice(start, start + columnCount);
|
|
17866
|
+
return /* @__PURE__ */ jsx(
|
|
17867
|
+
"div",
|
|
17868
|
+
{
|
|
17869
|
+
style: {
|
|
17870
|
+
position: "absolute",
|
|
17871
|
+
top: 0,
|
|
17872
|
+
left: 0,
|
|
17873
|
+
width: "100%",
|
|
17874
|
+
height: tileHeight,
|
|
17875
|
+
transform: `translateY(${virtualRow.start}px)`,
|
|
17876
|
+
display: "grid",
|
|
17877
|
+
gridTemplateColumns: `repeat(${columnCount}, minmax(0, 1fr))`,
|
|
17878
|
+
columnGap: GRID_GAP
|
|
17879
|
+
},
|
|
17880
|
+
children: rowEntries.map((entry) => {
|
|
17881
|
+
if (entry.kind === "folder") {
|
|
17882
|
+
const key = entry.path.join("/");
|
|
17883
|
+
return /* @__PURE__ */ jsx(
|
|
17884
|
+
FolderTile,
|
|
17885
|
+
{
|
|
17886
|
+
folder: entry,
|
|
17887
|
+
density,
|
|
17888
|
+
editing: editingFolderPath === key,
|
|
17889
|
+
selected: folderSelection.get(key)?.all,
|
|
17890
|
+
partiallySelected: folderSelection.get(key)?.some,
|
|
17891
|
+
documents: folderDocs.get(key) ?? NO_DOCUMENTS,
|
|
17892
|
+
onOpen: openFolder,
|
|
17893
|
+
onToggleSelect: handleToggleFolder,
|
|
17894
|
+
onCommitName: commitFolderName,
|
|
17895
|
+
onCancelName: cancelFolderName,
|
|
17896
|
+
onStartRename: canUpload ? startFolderRename : void 0,
|
|
17897
|
+
onDownload: handleFolderDownload,
|
|
17898
|
+
onMove: canUpload ? handleFolderMove : void 0,
|
|
17899
|
+
onDelete: canDeleteFolder(entry) ? handleFolderDelete : void 0
|
|
17900
|
+
},
|
|
17901
|
+
`folder:${key}`
|
|
17902
|
+
);
|
|
17903
|
+
}
|
|
17904
|
+
const doc = entry.doc;
|
|
17905
|
+
return /* @__PURE__ */ jsx(
|
|
17906
|
+
FileTile,
|
|
17907
|
+
{
|
|
17908
|
+
doc,
|
|
17909
|
+
density,
|
|
17910
|
+
selected: selectedSet.has(doc.external_id),
|
|
17911
|
+
dragging: activeDragId === doc.external_id,
|
|
17912
|
+
dndActive: activeDragId !== null,
|
|
17913
|
+
renaming: renamingId === doc.external_id,
|
|
17914
|
+
canDelete: canDeleteDocument(doc, userId, role),
|
|
17915
|
+
thumbnailUrl: thumbnailsById.get(doc.external_id),
|
|
17916
|
+
modifiedBy: userById.get(
|
|
17917
|
+
doc.updated_by_ext_id ?? doc.created_by_ext_id
|
|
17918
|
+
),
|
|
17919
|
+
tagNameById,
|
|
17920
|
+
onSelect: handleSelect,
|
|
17921
|
+
onToggle: handleToggle,
|
|
17922
|
+
onOpen: handleOpenFile,
|
|
17923
|
+
onReview: handleOpenInReview,
|
|
17924
|
+
onStartRename: startRename,
|
|
17925
|
+
onCommitRename: commitRename,
|
|
17926
|
+
onCancelRename: cancelRename,
|
|
17927
|
+
onDownload: handleDownload,
|
|
17928
|
+
onMove: canUpload ? handleMove : void 0,
|
|
17929
|
+
onDelete: handleDelete
|
|
17930
|
+
},
|
|
17931
|
+
doc.external_id
|
|
17932
|
+
);
|
|
17933
|
+
})
|
|
17934
|
+
},
|
|
17935
|
+
virtualRow.key
|
|
17936
|
+
);
|
|
17937
|
+
})
|
|
17938
|
+
}
|
|
17939
|
+
)
|
|
17940
|
+
}
|
|
17941
|
+
),
|
|
17942
|
+
/* @__PURE__ */ jsx(ExplorerMarquee, { ref: marqueeOverlayRef, "data-testid": "explorer-marquee" }),
|
|
17943
|
+
isFileDragOver && /* @__PURE__ */ jsx(
|
|
17944
|
+
ExplorerDropOverlay,
|
|
17945
|
+
{
|
|
17946
|
+
label: `Drop to upload${currentPath.length > 0 ? ` to "${currentPath[currentPath.length - 1]}"` : ""}`
|
|
17947
|
+
}
|
|
17948
|
+
)
|
|
17949
|
+
] }) }),
|
|
17950
|
+
/* @__PURE__ */ jsx(DragOverlay, { dropAnimation: null, children: activeDoc ? /* @__PURE__ */ jsx(DragPreview, { doc: activeDoc, count: dragCount }) : null })
|
|
17951
|
+
]
|
|
17952
|
+
}
|
|
17953
|
+
);
|
|
17954
|
+
});
|
|
17955
|
+
function DragPreview({ doc, count }) {
|
|
17956
|
+
const Icon = getFileTypeIcon(doc.file_name, { mime: doc.file_type });
|
|
17957
|
+
return /* @__PURE__ */ jsx(
|
|
17958
|
+
ExplorerDragPreview,
|
|
17959
|
+
{
|
|
17960
|
+
icon: /* @__PURE__ */ jsx(Icon, { size: 20 }),
|
|
17961
|
+
title: getDocumentTitle(doc, doc.file_name ?? "Untitled"),
|
|
17962
|
+
count
|
|
17963
|
+
}
|
|
17964
|
+
);
|
|
17965
|
+
}
|
|
16818
17966
|
function ActiveChat({ agentId, workspaceId }) {
|
|
16819
17967
|
const chat = useArbiChat({
|
|
16820
17968
|
agentId,
|
|
@@ -16882,6 +18030,6 @@ function ConnectedAgentChatPanel({
|
|
|
16882
18030
|
] });
|
|
16883
18031
|
}
|
|
16884
18032
|
|
|
16885
|
-
export { AddAddonDialog, ArbiAppProvider, BACKFILL_OPTIONS, BillingProjectEntity, ChangePlanDialog, ConnectedAccountSettings, ConnectedAgentChatPanel, ConnectedAgentCreator, ConnectedAppsSettings, ConnectedCalendar, ConnectedDangerZone, ConnectedDriveSyncDialog, ConnectedFactsPage, ConnectedIdentityVerification, ConnectedLogoutDialog, ConnectedMailAccounts, ConnectedMailComposer, ConnectedMailInviteCard, ConnectedMailMessage, ConnectedMailSettings, ConnectedMailSetup, ConnectedMailbox, ConnectedMailboxSyncDialog, ConnectedNotificationCenter, ConnectedNotificationPreferences, ConnectedPasswordChangeDialog, ConnectedPremiumModels, ConnectedPrivacySettings, ConnectedProfileCard, ConnectedProjectsPanel, ConnectedPublicBooking, ConnectedRequireVerified, ConnectedSearchPage, ConnectedSecuritySection, ConnectedSessionsRow, ConnectedSettingsPage, ConnectedSkillUpload, ConnectedSkillsLibrary, ConnectedTagTable, ConnectedTagsPage, ConnectedTaskAccessRequest, ConnectedTaskActivityDialog, ConnectedThreadFollow, ConnectedUpcomingEvents, ConnectedWorkflowHistory, ConnectedWorkflowRunner, ConnectedWorkspaceActivity, ConnectedWorkspaceDashboard, ConnectedWorkspaceList, ConnectedWorkspaceMembers, ConnectedWorkspaceNotificationMenu, ConnectedWorkspaceSettings, DEFAULT_CONNECTED_SEARCH_PAGE_LABELS, DEFAULT_CONNECTED_SKILL_UPLOAD_LABELS, DEFAULT_CONNECTED_WORKFLOW_RUNNER_LABELS, DEFAULT_SEARCH_ROW_LABELS, DEFAULT_SETTINGS_SECTIONS, DEFAULT_TIMELINE_LABEL_WIDTH, DEFAULT_WORKSPACE_LIST_LABELS, FACTS_GRID_ID, InvoicesModal, NewProjectFlow, NotificationCenter, NotificationEvent, PROJECTS_BASE_TAB_ID, ProjectDetail, ProjectsTable, REFERRAL_OFFER, SETTINGS_SECTION_IDS, SessionStatusIcon, SharedProjects, StreamedArtifact, WORKSPACES_TAB_ID, WorkflowRunThread, accountSettingsSection, bookingCancelLink, buildNotificationCenterItems, chatSettingsSection, connectedAppsSettingsSection, countNotificationTypes, defaultUnmetPasswordRequirement, filterNotificationCenterItems, formatLastSync, mailSettingsSection, openMeetingLink, privacySettingsSection, renderSessionStatusIcon, requestCalendarComposer, requestCalendarEvent, requestProjectBillingFocus, resolveMailbox, toWorkspaceSummary, useAutoRefreshPendingProjects, useCalendarViewStore, useConnectedDocxNotifications, useConnectedShellWorkspaces, useConnectedWorkNotifications, useConnectedWorkspaceList, useConnectedWorkspaceSettings, useOpenBillingPortal, useProjectBillingFocus, useReferralReward, windowLabel, workflowRunView };
|
|
18033
|
+
export { AddAddonDialog, ArbiAppProvider, BACKFILL_OPTIONS, BillingProjectEntity, ChangePlanDialog, ConnectedAccountSettings, ConnectedAgentChatPanel, ConnectedAgentCreator, ConnectedAppsSettings, ConnectedCalendar, ConnectedDangerZone, ConnectedDriveSyncDialog, ConnectedFactsPage, ConnectedFilesExplorer, ConnectedIdentityVerification, ConnectedLogoutDialog, ConnectedMailAccounts, ConnectedMailComposer, ConnectedMailInviteCard, ConnectedMailMessage, ConnectedMailSettings, ConnectedMailSetup, ConnectedMailbox, ConnectedMailboxSyncDialog, ConnectedNotificationCenter, ConnectedNotificationPreferences, ConnectedPasswordChangeDialog, ConnectedPremiumModels, ConnectedPrivacySettings, ConnectedProfileCard, ConnectedProjectsPanel, ConnectedPublicBooking, ConnectedRequireVerified, ConnectedSearchPage, ConnectedSecuritySection, ConnectedSessionsRow, ConnectedSettingsPage, ConnectedSkillUpload, ConnectedSkillsLibrary, ConnectedTagTable, ConnectedTagsPage, ConnectedTaskAccessRequest, ConnectedTaskActivityDialog, ConnectedThreadFollow, ConnectedUpcomingEvents, ConnectedWorkflowHistory, ConnectedWorkflowRunner, ConnectedWorkspaceActivity, ConnectedWorkspaceDashboard, ConnectedWorkspaceList, ConnectedWorkspaceMembers, ConnectedWorkspaceNotificationMenu, ConnectedWorkspaceSettings, DEFAULT_CONNECTED_SEARCH_PAGE_LABELS, DEFAULT_CONNECTED_SKILL_UPLOAD_LABELS, DEFAULT_CONNECTED_WORKFLOW_RUNNER_LABELS, DEFAULT_SEARCH_ROW_LABELS, DEFAULT_SETTINGS_SECTIONS, DEFAULT_TIMELINE_LABEL_WIDTH, DEFAULT_WORKSPACE_LIST_LABELS, DocumentSyncGlyph, FACTS_GRID_ID, FileTooltipContent, FilesSupportProvider, InvoicesModal, NewProjectFlow, NotificationCenter, NotificationEvent, PROJECTS_BASE_TAB_ID, ProjectDetail, ProjectsTable, REFERRAL_OFFER, SETTINGS_SECTION_IDS, SessionStatusIcon, SharedProjects, StreamedArtifact, TILE_DEFAULT, TILE_MAX, TILE_MIN, WORKSPACES_TAB_ID, WorkflowRunThread, accountSettingsSection, bookingCancelLink, buildNotificationCenterItems, chatSettingsSection, connectedAppsSettingsSection, countNotificationTypes, defaultUnmetPasswordRequirement, filterNotificationCenterItems, formatLastSync, isActiveDocumentStatus, mailSettingsSection, openMeetingLink, privacySettingsSection, renderSessionStatusIcon, requestCalendarComposer, requestCalendarEvent, requestProjectBillingFocus, resolveMailbox, startMenuItem, toWorkspaceSummary, useAutoRefreshPendingProjects, useCalendarViewStore, useConnectedDocxNotifications, useConnectedShellWorkspaces, useConnectedWorkNotifications, useConnectedWorkspaceList, useConnectedWorkspaceSettings, useFilesStore, useFilesSupport, useOfflineDocumentIds, useOpenBillingPortal, usePendingFolders, useProjectBillingFocus, useReferralReward, useViewingDocumentId, windowLabel, workflowRunView };
|
|
16886
18034
|
//# sourceMappingURL=index.js.map
|
|
16887
18035
|
//# sourceMappingURL=index.js.map
|