@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.cjs
CHANGED
|
@@ -11,7 +11,7 @@ var chunkSN2GZ4ZM_cjs = require('../chunk-SN2GZ4ZM.cjs');
|
|
|
11
11
|
var chunkKBO75NLM_cjs = require('../chunk-KBO75NLM.cjs');
|
|
12
12
|
var chunkCQCNU5KT_cjs = require('../chunk-CQCNU5KT.cjs');
|
|
13
13
|
var chunk6I6CVX5G_cjs = require('../chunk-6I6CVX5G.cjs');
|
|
14
|
-
var
|
|
14
|
+
var chunkWV4TD2HZ_cjs = require('../chunk-WV4TD2HZ.cjs');
|
|
15
15
|
require('../chunk-223D4727.cjs');
|
|
16
16
|
var chunkCB4TIDEX_cjs = require('../chunk-CB4TIDEX.cjs');
|
|
17
17
|
var chunkFM3IRQJW_cjs = require('../chunk-FM3IRQJW.cjs');
|
|
@@ -23,10 +23,10 @@ var chunk2WLXQGWC_cjs = require('../chunk-2WLXQGWC.cjs');
|
|
|
23
23
|
var chunk5FYU7ZIU_cjs = require('../chunk-5FYU7ZIU.cjs');
|
|
24
24
|
var chunkGC2FSPSQ_cjs = require('../chunk-GC2FSPSQ.cjs');
|
|
25
25
|
var chunkXAJIKT6Y_cjs = require('../chunk-XAJIKT6Y.cjs');
|
|
26
|
+
var chunkGOWXP5KT_cjs = require('../chunk-GOWXP5KT.cjs');
|
|
26
27
|
var chunkQZTNTP75_cjs = require('../chunk-QZTNTP75.cjs');
|
|
27
28
|
require('../chunk-PCB2BPN3.cjs');
|
|
28
29
|
require('../chunk-NWNVWO6L.cjs');
|
|
29
|
-
var chunkGOWXP5KT_cjs = require('../chunk-GOWXP5KT.cjs');
|
|
30
30
|
var chunkCROGFB46_cjs = require('../chunk-CROGFB46.cjs');
|
|
31
31
|
require('../chunk-7G2LJMUG.cjs');
|
|
32
32
|
require('../chunk-FAXXN7KI.cjs');
|
|
@@ -85,6 +85,8 @@ var client = require('@arbidocs/client');
|
|
|
85
85
|
var reactDom = require('react-dom');
|
|
86
86
|
var zustand = require('zustand');
|
|
87
87
|
var middleware = require('zustand/middleware');
|
|
88
|
+
var core = require('@dnd-kit/core');
|
|
89
|
+
var reactVirtual = require('@tanstack/react-virtual');
|
|
88
90
|
|
|
89
91
|
function ConnectionBoundWebSocket({ children }) {
|
|
90
92
|
const { status } = chunkFM3IRQJW_cjs.useConnection();
|
|
@@ -3470,7 +3472,7 @@ ${nested.length} nested ${tagNoun(nested.length)} ${nested.length === 1 ? "moves
|
|
|
3470
3472
|
onTabChange: () => {
|
|
3471
3473
|
},
|
|
3472
3474
|
variant: "underline",
|
|
3473
|
-
firstTabContent: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3475
|
+
firstTabContent: /* @__PURE__ */ jsxRuntime.jsx(chunkWV4TD2HZ_cjs.FilesFilterBar, { className: "flex-none", "data-testid": "tags-header-actions", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3474
3476
|
chunk2EI7NCUA_cjs.FilterInput,
|
|
3475
3477
|
{
|
|
3476
3478
|
value: filterText,
|
|
@@ -3498,7 +3500,7 @@ ${nested.length} nested ${tagNoun(nested.length)} ${nested.length === 1 ? "moves
|
|
|
3498
3500
|
)
|
|
3499
3501
|
}
|
|
3500
3502
|
) }),
|
|
3501
|
-
centerContent: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3503
|
+
centerContent: /* @__PURE__ */ jsxRuntime.jsx(chunkWV4TD2HZ_cjs.FilesViewCenter, { children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3502
3504
|
chunk2WLXQGWC_cjs.ViewToggle,
|
|
3503
3505
|
{
|
|
3504
3506
|
options: browser.TAG_KINDS.map((k) => ({
|
|
@@ -4356,7 +4358,7 @@ function useFactFilters(notes, view, chat) {
|
|
|
4356
4358
|
(selected, setSelected, opts) => {
|
|
4357
4359
|
const applied = new Set(selected);
|
|
4358
4360
|
return /* @__PURE__ */ jsxRuntime.jsx(chunkB3FMUFAW_cjs.FactFieldRow, { label: "Labels", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
4359
|
-
|
|
4361
|
+
chunkWV4TD2HZ_cjs.FieldLabelsSelect,
|
|
4360
4362
|
{
|
|
4361
4363
|
options: labelOptions,
|
|
4362
4364
|
appliedIds: applied,
|
|
@@ -4582,7 +4584,7 @@ var FactHeader = react.memo(function FactHeader2({
|
|
|
4582
4584
|
if (params.enableSorting) params.progressSort(e.shiftKey);
|
|
4583
4585
|
},
|
|
4584
4586
|
children: [
|
|
4585
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4587
|
+
/* @__PURE__ */ jsxRuntime.jsx(chunkWV4TD2HZ_cjs.FilterButton, { params, colId }),
|
|
4586
4588
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "order-2 min-w-0 flex-1 truncate", children: params.displayName }),
|
|
4587
4589
|
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "ag-sort-indicator-container order-2 flex-shrink-0", "aria-hidden": "true", children: [
|
|
4588
4590
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -4846,7 +4848,7 @@ function useFactsGrid({
|
|
|
4846
4848
|
var DEFAULT_TIMELINE_LABEL_WIDTH = 240;
|
|
4847
4849
|
function useFactsPageView() {
|
|
4848
4850
|
const [view, setView] = react.useState("table");
|
|
4849
|
-
const [rowHeight, setRowHeight] = react.useState(
|
|
4851
|
+
const [rowHeight, setRowHeight] = react.useState(chunkWV4TD2HZ_cjs.ROW_MIN);
|
|
4850
4852
|
const [labelWidth, setLabelWidth] = react.useState(DEFAULT_TIMELINE_LABEL_WIDTH);
|
|
4851
4853
|
const [zoom, setZoom] = react.useState(1);
|
|
4852
4854
|
const [filterText, setFilterText] = react.useState("");
|
|
@@ -5000,7 +5002,7 @@ function ConnectedFactsPage({
|
|
|
5000
5002
|
setView(request.view === "list" ? "table" : request.view);
|
|
5001
5003
|
onRequestHandled?.("view");
|
|
5002
5004
|
}, [request?.view]);
|
|
5003
|
-
const factsRowHeight = pageView.rowHeight ===
|
|
5005
|
+
const factsRowHeight = pageView.rowHeight === chunkWV4TD2HZ_cjs.ROW_MIN ? chunkWV4TD2HZ_cjs.ROW_MIN : chunkWV4TD2HZ_cjs.rowHeightForLines(chunkWV4TD2HZ_cjs.linesForRowHeight(pageView.rowHeight));
|
|
5004
5006
|
const [isExportOpen, setIsExportOpen] = react.useState(false);
|
|
5005
5007
|
const [filterOpen, setFilterOpen] = react.useState(false);
|
|
5006
5008
|
const [factSection, setFactSection] = react.useState(null);
|
|
@@ -5067,7 +5069,7 @@ function ConnectedFactsPage({
|
|
|
5067
5069
|
tools: /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
5068
5070
|
view === "table" && /* @__PURE__ */ jsxRuntime.jsx(chunkB3FMUFAW_cjs.FactsFieldsButton, { getGridApi: () => gridApiRef.current }),
|
|
5069
5071
|
view === "table" && /* @__PURE__ */ jsxRuntime.jsx(
|
|
5070
|
-
|
|
5072
|
+
chunkWV4TD2HZ_cjs.RowDensityControl,
|
|
5071
5073
|
{
|
|
5072
5074
|
rowHeight: factsRowHeight,
|
|
5073
5075
|
onRowHeightChange: pageView.setRowHeight,
|
|
@@ -13135,7 +13137,7 @@ function ConnectedMailbox({
|
|
|
13135
13137
|
onTabChange: () => {
|
|
13136
13138
|
},
|
|
13137
13139
|
compactBreakpoint: 360,
|
|
13138
|
-
firstTabContent: account ? /* @__PURE__ */ jsxRuntime.jsxs(
|
|
13140
|
+
firstTabContent: account ? /* @__PURE__ */ jsxRuntime.jsxs(chunkWV4TD2HZ_cjs.FilesFilterBar, { children: [
|
|
13139
13141
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
13140
13142
|
chunk2EI7NCUA_cjs.FilterInput,
|
|
13141
13143
|
{
|
|
@@ -13170,7 +13172,7 @@ function ConnectedMailbox({
|
|
|
13170
13172
|
}
|
|
13171
13173
|
),
|
|
13172
13174
|
folderList && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex shrink-0 items-center gap-2", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
13173
|
-
|
|
13175
|
+
chunkWV4TD2HZ_cjs.FolderFilterButton,
|
|
13174
13176
|
{
|
|
13175
13177
|
label: folderList.find((f) => f.id === folderId)?.name ?? "Folders",
|
|
13176
13178
|
isActive: false,
|
|
@@ -13178,7 +13180,7 @@ function ConnectedMailbox({
|
|
|
13178
13180
|
onOpenChange: setFolderMenuOpen,
|
|
13179
13181
|
testId: "mail-folder-button",
|
|
13180
13182
|
children: folderList.map((item) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
13181
|
-
|
|
13183
|
+
chunkWV4TD2HZ_cjs.FolderPickerRow,
|
|
13182
13184
|
{
|
|
13183
13185
|
label: item.name,
|
|
13184
13186
|
count: item.unread > 0 ? item.unread : void 0,
|
|
@@ -14385,7 +14387,7 @@ function BookingPagesPanel({ defaultTimeZone, className }) {
|
|
|
14385
14387
|
var selectClass4 = "h-9 w-full rounded-md border border-input bg-background px-2 text-sm text-foreground shadow-sm";
|
|
14386
14388
|
function CreateRoomForm({ zone, onDone }) {
|
|
14387
14389
|
const { notify: notify14 } = chunkCNHUJRQ4_cjs.useBlocksEnvironment();
|
|
14388
|
-
const
|
|
14390
|
+
const create3 = react$1.useCreateRoom();
|
|
14389
14391
|
const [name, setName] = react.useState("");
|
|
14390
14392
|
const [type, setType] = react.useState("room");
|
|
14391
14393
|
const [capacity, setCapacity] = react.useState("");
|
|
@@ -14405,7 +14407,7 @@ function CreateRoomForm({ zone, onDone }) {
|
|
|
14405
14407
|
const cap = capacity.trim() ? Number(capacity) : null;
|
|
14406
14408
|
if (cap !== null && (!Number.isInteger(cap) || cap < 1))
|
|
14407
14409
|
return setError("Capacity must be a whole number");
|
|
14408
|
-
|
|
14410
|
+
create3.mutate(
|
|
14409
14411
|
{
|
|
14410
14412
|
name: name.trim(),
|
|
14411
14413
|
type,
|
|
@@ -14496,8 +14498,8 @@ function CreateRoomForm({ zone, onDone }) {
|
|
|
14496
14498
|
error && /* @__PURE__ */ jsxRuntime.jsx("p", { role: "alert", className: "text-sm text-destructive", children: error }),
|
|
14497
14499
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-end gap-2", children: [
|
|
14498
14500
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Button, { type: "button", variant: "ghost", onClick: onDone, children: "Cancel" }),
|
|
14499
|
-
/* @__PURE__ */ jsxRuntime.jsxs(ui.Button, { type: "submit", disabled:
|
|
14500
|
-
|
|
14501
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.Button, { type: "submit", disabled: create3.isPending, children: [
|
|
14502
|
+
create3.isPending && /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { className: "mr-1 size-4 animate-spin" }),
|
|
14501
14503
|
"Create"
|
|
14502
14504
|
] })
|
|
14503
14505
|
] })
|
|
@@ -16813,6 +16815,1152 @@ function ConnectedPublicBooking({ slug, cancelToken }) {
|
|
|
16813
16815
|
] })
|
|
16814
16816
|
] });
|
|
16815
16817
|
}
|
|
16818
|
+
var useFilesStore = zustand.create()(
|
|
16819
|
+
middleware.persist(
|
|
16820
|
+
(set) => ({
|
|
16821
|
+
pendingFolders: {},
|
|
16822
|
+
addPendingFolder: (workspaceId, path) => set((state) => {
|
|
16823
|
+
const current = state.pendingFolders[workspaceId] ?? [];
|
|
16824
|
+
if (current.includes(path)) return state;
|
|
16825
|
+
return { pendingFolders: { ...state.pendingFolders, [workspaceId]: [...current, path] } };
|
|
16826
|
+
}),
|
|
16827
|
+
removePendingFolder: (workspaceId, path) => set((state) => {
|
|
16828
|
+
const current = state.pendingFolders[workspaceId] ?? [];
|
|
16829
|
+
if (!current.includes(path)) return state;
|
|
16830
|
+
return {
|
|
16831
|
+
pendingFolders: {
|
|
16832
|
+
...state.pendingFolders,
|
|
16833
|
+
[workspaceId]: current.filter((p) => p !== path)
|
|
16834
|
+
}
|
|
16835
|
+
};
|
|
16836
|
+
})
|
|
16837
|
+
}),
|
|
16838
|
+
{
|
|
16839
|
+
name: "arbi_explorer_pending_folders",
|
|
16840
|
+
storage: middleware.createJSONStorage(() => sessionStorage),
|
|
16841
|
+
partialize: (state) => ({ pendingFolders: state.pendingFolders })
|
|
16842
|
+
}
|
|
16843
|
+
)
|
|
16844
|
+
);
|
|
16845
|
+
var NONE = [];
|
|
16846
|
+
function usePendingFolders(workspaceId) {
|
|
16847
|
+
return useFilesStore(
|
|
16848
|
+
(state) => (workspaceId ? state.pendingFolders[workspaceId] : void 0) ?? NONE
|
|
16849
|
+
);
|
|
16850
|
+
}
|
|
16851
|
+
var FilesSupportContext = react.createContext({});
|
|
16852
|
+
function FilesSupportProvider({
|
|
16853
|
+
value,
|
|
16854
|
+
children
|
|
16855
|
+
}) {
|
|
16856
|
+
return /* @__PURE__ */ jsxRuntime.jsx(FilesSupportContext.Provider, { value, children });
|
|
16857
|
+
}
|
|
16858
|
+
function useFilesSupport() {
|
|
16859
|
+
return react.useContext(FilesSupportContext);
|
|
16860
|
+
}
|
|
16861
|
+
var NO_IDS3 = /* @__PURE__ */ new Set();
|
|
16862
|
+
function useOfflineDocumentIds() {
|
|
16863
|
+
const { useOfflineDocumentIds: useHostIds } = useFilesSupport();
|
|
16864
|
+
return useHostIds?.() ?? NO_IDS3;
|
|
16865
|
+
}
|
|
16866
|
+
function useViewingDocumentId() {
|
|
16867
|
+
const { useViewingDocumentId: useHostViewing } = useFilesSupport();
|
|
16868
|
+
return useHostViewing?.() ?? null;
|
|
16869
|
+
}
|
|
16870
|
+
function DocumentSyncGlyph({
|
|
16871
|
+
docExtId,
|
|
16872
|
+
size = 13,
|
|
16873
|
+
className,
|
|
16874
|
+
bgClassName = "bg-muted-foreground"
|
|
16875
|
+
}) {
|
|
16876
|
+
const isAvailableOffline = useOfflineDocumentIds().has(docExtId);
|
|
16877
|
+
if (!isAvailableOffline) return null;
|
|
16878
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
16879
|
+
"span",
|
|
16880
|
+
{
|
|
16881
|
+
title: "Available offline (saved on this device)",
|
|
16882
|
+
"aria-label": "Available offline",
|
|
16883
|
+
"data-testid": `offline-available-badge-${docExtId}`,
|
|
16884
|
+
className: ui.cn(
|
|
16885
|
+
"inline-flex items-center justify-center rounded-full text-white ring-1 ring-white",
|
|
16886
|
+
bgClassName,
|
|
16887
|
+
className
|
|
16888
|
+
),
|
|
16889
|
+
style: { width: size, height: size },
|
|
16890
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowDownToLine, { size: Math.round(size * 0.7), strokeWidth: 2.75 })
|
|
16891
|
+
}
|
|
16892
|
+
);
|
|
16893
|
+
}
|
|
16894
|
+
var ACTIVE_STATUSES = /* @__PURE__ */ new Set([
|
|
16895
|
+
"uploading",
|
|
16896
|
+
"queued",
|
|
16897
|
+
"parsing",
|
|
16898
|
+
"encrypting",
|
|
16899
|
+
"indexing",
|
|
16900
|
+
"analysing"
|
|
16901
|
+
]);
|
|
16902
|
+
var TERMINAL_STATUSES = /* @__PURE__ */ new Set(["completed", "failed", "skipped", "empty", "low-content"]);
|
|
16903
|
+
var STATUS_LABEL = {
|
|
16904
|
+
uploading: "Uploading",
|
|
16905
|
+
queued: "Queued",
|
|
16906
|
+
parsing: "Parsing",
|
|
16907
|
+
encrypting: "Encrypting",
|
|
16908
|
+
indexing: "Indexing",
|
|
16909
|
+
analysing: "Analysing"
|
|
16910
|
+
};
|
|
16911
|
+
function isActiveDocumentStatus(status) {
|
|
16912
|
+
return ACTIVE_STATUSES.has(status.toLowerCase());
|
|
16913
|
+
}
|
|
16914
|
+
function useDocStatus(doc) {
|
|
16915
|
+
const liveStatus = react$1.useProcessingTask(doc.external_id)?.status;
|
|
16916
|
+
const rowStatus = (doc.status ?? "").toLowerCase();
|
|
16917
|
+
if (liveStatus && ACTIVE_STATUSES.has(liveStatus)) return liveStatus;
|
|
16918
|
+
if (TERMINAL_STATUSES.has(rowStatus)) return rowStatus;
|
|
16919
|
+
return liveStatus ?? rowStatus;
|
|
16920
|
+
}
|
|
16921
|
+
function TileStatusBadge({ doc, status }) {
|
|
16922
|
+
let tone = "neutral";
|
|
16923
|
+
let icon2 = null;
|
|
16924
|
+
let title = "";
|
|
16925
|
+
switch (status) {
|
|
16926
|
+
case "completed":
|
|
16927
|
+
tone = "success";
|
|
16928
|
+
icon2 = /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CheckCircle, { className: "size-4 text-green-text", strokeWidth: 2.75 });
|
|
16929
|
+
title = "Ready";
|
|
16930
|
+
break;
|
|
16931
|
+
case "failed":
|
|
16932
|
+
tone = "danger";
|
|
16933
|
+
icon2 = /* @__PURE__ */ jsxRuntime.jsx(
|
|
16934
|
+
chunkWV4TD2HZ_cjs.FailedStageIcon,
|
|
16935
|
+
{
|
|
16936
|
+
stage: doc.failed_stage ?? null,
|
|
16937
|
+
errorMessage: doc.error_message,
|
|
16938
|
+
className: "size-4 text-red-text"
|
|
16939
|
+
}
|
|
16940
|
+
);
|
|
16941
|
+
title = "Failed";
|
|
16942
|
+
break;
|
|
16943
|
+
case "skipped":
|
|
16944
|
+
icon2 = /* @__PURE__ */ jsxRuntime.jsx(lucideReact.SkipForward, { className: "size-4 text-muted-foreground", strokeWidth: 2.75 });
|
|
16945
|
+
title = "Skipped";
|
|
16946
|
+
break;
|
|
16947
|
+
case "empty":
|
|
16948
|
+
tone = "warning";
|
|
16949
|
+
icon2 = /* @__PURE__ */ jsxRuntime.jsx(lucideReact.FileX, { className: "size-4 text-yellow-text", strokeWidth: 2.75 });
|
|
16950
|
+
title = "Empty \u2014 no extractable content";
|
|
16951
|
+
break;
|
|
16952
|
+
case "low-content":
|
|
16953
|
+
tone = "warning";
|
|
16954
|
+
icon2 = /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlertTriangle, { className: "size-4 text-yellow-text", strokeWidth: 2.75 });
|
|
16955
|
+
title = "Low content \u2014 minimal extractable content";
|
|
16956
|
+
break;
|
|
16957
|
+
default:
|
|
16958
|
+
return null;
|
|
16959
|
+
}
|
|
16960
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
16961
|
+
chunkWV4TD2HZ_cjs.StatusPill,
|
|
16962
|
+
{
|
|
16963
|
+
tone,
|
|
16964
|
+
icon: icon2,
|
|
16965
|
+
title,
|
|
16966
|
+
testId: `explorer-file-status-${doc.external_id}`
|
|
16967
|
+
}
|
|
16968
|
+
);
|
|
16969
|
+
}
|
|
16970
|
+
function TileVisibilityBadge({ doc }) {
|
|
16971
|
+
const shared = !!doc.shared;
|
|
16972
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
16973
|
+
chunkWV4TD2HZ_cjs.StatusPill,
|
|
16974
|
+
{
|
|
16975
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(ui.VisibilityIcon, { isShared: shared, className: "size-3.5", "aria-hidden": true }),
|
|
16976
|
+
label: shared ? ui.getEntityLabel("WORKSPACE") : "Only you",
|
|
16977
|
+
title: chunkWV4TD2HZ_cjs.visibilityAudience(shared),
|
|
16978
|
+
testId: `explorer-file-visibility-${doc.external_id}`
|
|
16979
|
+
}
|
|
16980
|
+
);
|
|
16981
|
+
}
|
|
16982
|
+
function MiniUserAvatar({ user }) {
|
|
16983
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(ui.Avatar, { className: "h-4 w-4 border border-white", children: [
|
|
16984
|
+
user.picture && /* @__PURE__ */ jsxRuntime.jsx(ui.AvatarImage, { src: user.picture, alt: ui.getUserDisplayName(user) }),
|
|
16985
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
16986
|
+
ui.AvatarFallback,
|
|
16987
|
+
{
|
|
16988
|
+
className: ui.cn(
|
|
16989
|
+
"text-xs font-semibold leading-none text-white",
|
|
16990
|
+
ui.getUserAvatarColor(user.external_id)
|
|
16991
|
+
),
|
|
16992
|
+
children: ui.getUserInitials(user)
|
|
16993
|
+
}
|
|
16994
|
+
)
|
|
16995
|
+
] });
|
|
16996
|
+
}
|
|
16997
|
+
function FileTooltipContent({
|
|
16998
|
+
doc,
|
|
16999
|
+
modifiedBy,
|
|
17000
|
+
tagNameById
|
|
17001
|
+
}) {
|
|
17002
|
+
const labels = (doc.doctags ?? []).map((dt) => tagNameById.get(dt.tag_ext_id)).filter((name) => !!name);
|
|
17003
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
17004
|
+
chunkWV4TD2HZ_cjs.ExplorerFileTooltip,
|
|
17005
|
+
{
|
|
17006
|
+
title: ui.getDocumentTitle(doc, doc.file_name ?? ""),
|
|
17007
|
+
summary: react$1.getDocumentSubject(doc),
|
|
17008
|
+
modifiedLabel: doc.updated_at ? ui.formatFriendlyDate(doc.updated_at, false) : null,
|
|
17009
|
+
modifiedByAvatar: modifiedBy && /* @__PURE__ */ jsxRuntime.jsx(MiniUserAvatar, { user: modifiedBy }),
|
|
17010
|
+
shared: !!doc.shared,
|
|
17011
|
+
visibilityIcon: /* @__PURE__ */ jsxRuntime.jsx(ui.VisibilityIcon, { isShared: !!doc.shared, className: "h-3 w-3" }),
|
|
17012
|
+
labels,
|
|
17013
|
+
uiLabels: { shared: chunkWV4TD2HZ_cjs.visibilityAudience(true), private: chunkWV4TD2HZ_cjs.visibilityAudience(false) }
|
|
17014
|
+
}
|
|
17015
|
+
);
|
|
17016
|
+
}
|
|
17017
|
+
function startMenuItem(items) {
|
|
17018
|
+
if (items.length === 0) return [];
|
|
17019
|
+
return [
|
|
17020
|
+
{
|
|
17021
|
+
id: "start",
|
|
17022
|
+
label: "Start\u2026",
|
|
17023
|
+
icon: lucideReact.Sparkles,
|
|
17024
|
+
testId: "explorer-start-menu",
|
|
17025
|
+
onSelect: () => {
|
|
17026
|
+
},
|
|
17027
|
+
submenu: items.map((item) => ({
|
|
17028
|
+
id: item.id,
|
|
17029
|
+
label: item.title,
|
|
17030
|
+
icon: lucideReact.Play,
|
|
17031
|
+
onSelect: item.run,
|
|
17032
|
+
testId: `explorer-start-${item.id}`
|
|
17033
|
+
}))
|
|
17034
|
+
}
|
|
17035
|
+
];
|
|
17036
|
+
}
|
|
17037
|
+
var FileTile = react.memo(function FileTile2({
|
|
17038
|
+
doc,
|
|
17039
|
+
density,
|
|
17040
|
+
selected,
|
|
17041
|
+
dragging,
|
|
17042
|
+
dndActive,
|
|
17043
|
+
renaming,
|
|
17044
|
+
canDelete,
|
|
17045
|
+
thumbnailUrl,
|
|
17046
|
+
modifiedBy,
|
|
17047
|
+
tagNameById,
|
|
17048
|
+
onSelect,
|
|
17049
|
+
onToggle,
|
|
17050
|
+
onOpen,
|
|
17051
|
+
onReview,
|
|
17052
|
+
onStartRename,
|
|
17053
|
+
onCommitRename,
|
|
17054
|
+
onCancelRename,
|
|
17055
|
+
onDownload,
|
|
17056
|
+
onMove,
|
|
17057
|
+
onDelete
|
|
17058
|
+
}) {
|
|
17059
|
+
const { attributes, listeners: listeners2, setNodeRef } = core.useDraggable({
|
|
17060
|
+
id: `doc:${doc.external_id}`,
|
|
17061
|
+
data: { type: "doc", docId: doc.external_id }
|
|
17062
|
+
});
|
|
17063
|
+
const { notify: notify14 } = chunkCNHUJRQ4_cjs.useBlocksEnvironment();
|
|
17064
|
+
const { startItemsForFile, openDocumentChat, emailDocument } = useFilesSupport();
|
|
17065
|
+
const status = useDocStatus(doc);
|
|
17066
|
+
const isProcessing = ACTIVE_STATUSES.has(status);
|
|
17067
|
+
const isOffline = useOfflineDocumentIds().has(doc.external_id);
|
|
17068
|
+
const isViewing = useViewingDocumentId() === doc.external_id;
|
|
17069
|
+
const showStatusMarker = !isProcessing && TERMINAL_STATUSES.has(status);
|
|
17070
|
+
const Icon = ui.getFileTypeIcon(doc.file_name, { mime: doc.file_type });
|
|
17071
|
+
const { data: mailPolicy } = react$1.useMailPolicy();
|
|
17072
|
+
const shareAsEmail = async () => {
|
|
17073
|
+
try {
|
|
17074
|
+
await emailDocument?.(doc);
|
|
17075
|
+
} catch (error) {
|
|
17076
|
+
notify14(error instanceof Error ? error.message : "Could not attach document", "error");
|
|
17077
|
+
}
|
|
17078
|
+
};
|
|
17079
|
+
const startItems = startItemsForFile?.(doc);
|
|
17080
|
+
const menuItems = [
|
|
17081
|
+
{ id: "open", label: "Open", icon: lucideReact.SquarePen, onSelect: () => onOpen(doc) },
|
|
17082
|
+
...onReview ? [{ id: "review", label: "Open in Review", icon: lucideReact.BookOpen, onSelect: () => onReview(doc) }] : [],
|
|
17083
|
+
...openDocumentChat ? [
|
|
17084
|
+
{
|
|
17085
|
+
id: "chat",
|
|
17086
|
+
label: "Document chat",
|
|
17087
|
+
icon: lucideReact.MessagesSquare,
|
|
17088
|
+
onSelect: () => openDocumentChat(doc.external_id)
|
|
17089
|
+
}
|
|
17090
|
+
] : [],
|
|
17091
|
+
...startMenuItem(startItems ?? []),
|
|
17092
|
+
{
|
|
17093
|
+
id: "rename",
|
|
17094
|
+
label: "Rename",
|
|
17095
|
+
icon: lucideReact.Pencil,
|
|
17096
|
+
onSelect: () => onStartRename(doc),
|
|
17097
|
+
separatorBefore: true
|
|
17098
|
+
},
|
|
17099
|
+
{ id: "download", label: "Download", icon: lucideReact.Download, onSelect: () => onDownload(doc) },
|
|
17100
|
+
...emailDocument && mailPolicy?.enabled ? [
|
|
17101
|
+
{
|
|
17102
|
+
id: "email",
|
|
17103
|
+
label: "Send as email attachment",
|
|
17104
|
+
icon: lucideReact.Mail,
|
|
17105
|
+
onSelect: () => {
|
|
17106
|
+
void shareAsEmail();
|
|
17107
|
+
}
|
|
17108
|
+
}
|
|
17109
|
+
] : [],
|
|
17110
|
+
...onMove ? [{ id: "move", label: "Move to\u2026", icon: lucideReact.FolderInput, onSelect: () => onMove(doc) }] : [],
|
|
17111
|
+
...canDelete ? [
|
|
17112
|
+
{
|
|
17113
|
+
id: "delete",
|
|
17114
|
+
label: "Delete",
|
|
17115
|
+
icon: lucideReact.Trash2,
|
|
17116
|
+
onSelect: () => onDelete(doc),
|
|
17117
|
+
destructive: true,
|
|
17118
|
+
separatorBefore: true
|
|
17119
|
+
}
|
|
17120
|
+
] : []
|
|
17121
|
+
];
|
|
17122
|
+
const tooltip = renaming || dndActive ? void 0 : /* @__PURE__ */ jsxRuntime.jsx(FileTooltipContent, { doc, modifiedBy, tagNameById });
|
|
17123
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
17124
|
+
chunkWV4TD2HZ_cjs.ExplorerFileTile,
|
|
17125
|
+
{
|
|
17126
|
+
id: doc.external_id,
|
|
17127
|
+
title: ui.getDocumentTitle(doc, doc.file_name ?? ""),
|
|
17128
|
+
density,
|
|
17129
|
+
selected,
|
|
17130
|
+
dragging,
|
|
17131
|
+
renaming,
|
|
17132
|
+
thumbnailUrl,
|
|
17133
|
+
renderFileIcon: (size) => /* @__PURE__ */ jsxRuntime.jsx(Icon, { size, className: "drop-shadow-sm" }),
|
|
17134
|
+
progress: isProcessing ? { label: STATUS_LABEL[status] ?? status, queued: status === "queued" } : void 0,
|
|
17135
|
+
statusMarker: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1", children: [
|
|
17136
|
+
/* @__PURE__ */ jsxRuntime.jsx(TileVisibilityBadge, { doc }),
|
|
17137
|
+
showStatusMarker && /* @__PURE__ */ jsxRuntime.jsx(TileStatusBadge, { doc, status })
|
|
17138
|
+
] }),
|
|
17139
|
+
offlineMarker: isOffline ? /* @__PURE__ */ jsxRuntime.jsx(DocumentSyncGlyph, { docExtId: doc.external_id, size: 24, bgClassName: "bg-primary" }) : void 0,
|
|
17140
|
+
entity: /* @__PURE__ */ jsxRuntime.jsx(
|
|
17141
|
+
ui.DocumentEntity,
|
|
17142
|
+
{
|
|
17143
|
+
doc,
|
|
17144
|
+
labelMaxWidth: "max-w-full",
|
|
17145
|
+
noClamp: true,
|
|
17146
|
+
labelClassName: "whitespace-normal line-clamp-2 break-words",
|
|
17147
|
+
viewing: isViewing,
|
|
17148
|
+
tooltipContent: /* @__PURE__ */ jsxRuntime.jsx(FileTooltipContent, { doc, modifiedBy, tagNameById }),
|
|
17149
|
+
className: ui.cn(
|
|
17150
|
+
"w-full min-w-0 max-w-full bg-background/90 backdrop-blur-sm",
|
|
17151
|
+
density === "list" ? "text-xs" : void 0
|
|
17152
|
+
),
|
|
17153
|
+
onClick: (e) => {
|
|
17154
|
+
e.stopPropagation();
|
|
17155
|
+
onOpen(doc);
|
|
17156
|
+
}
|
|
17157
|
+
}
|
|
17158
|
+
),
|
|
17159
|
+
tooltip,
|
|
17160
|
+
menuItems,
|
|
17161
|
+
rootRef: setNodeRef,
|
|
17162
|
+
rootProps: { ...listeners2, ...attributes },
|
|
17163
|
+
onOpen: () => onOpen(doc),
|
|
17164
|
+
onSelect: (e) => onSelect(doc, e),
|
|
17165
|
+
onToggle: (e) => onToggle(doc, e),
|
|
17166
|
+
onCommitRename: (name) => onCommitRename(doc, name),
|
|
17167
|
+
onCancelRename
|
|
17168
|
+
}
|
|
17169
|
+
);
|
|
17170
|
+
});
|
|
17171
|
+
var FolderTile = react.memo(function FolderTile2({
|
|
17172
|
+
folder,
|
|
17173
|
+
density,
|
|
17174
|
+
editing,
|
|
17175
|
+
selected,
|
|
17176
|
+
partiallySelected,
|
|
17177
|
+
documents,
|
|
17178
|
+
onOpen,
|
|
17179
|
+
onToggleSelect,
|
|
17180
|
+
onCommitName,
|
|
17181
|
+
onCancelName,
|
|
17182
|
+
onStartRename,
|
|
17183
|
+
onDownload,
|
|
17184
|
+
onMove,
|
|
17185
|
+
onDelete
|
|
17186
|
+
}) {
|
|
17187
|
+
const { setNodeRef, isOver } = core.useDroppable({
|
|
17188
|
+
id: `folder:${folder.path.join("/")}`,
|
|
17189
|
+
data: { type: "folder", path: folder.path }
|
|
17190
|
+
});
|
|
17191
|
+
const { startItemsForFolder } = useFilesSupport();
|
|
17192
|
+
const tasks = react$1.useProcessingTasks();
|
|
17193
|
+
const processingCount = react.useMemo(
|
|
17194
|
+
() => documents.filter(
|
|
17195
|
+
(doc) => isActiveDocumentStatus(tasks[doc.external_id]?.status ?? doc.status ?? "")
|
|
17196
|
+
).length,
|
|
17197
|
+
[documents, tasks]
|
|
17198
|
+
);
|
|
17199
|
+
const isEmpty = folder.count === 0;
|
|
17200
|
+
const iconSize = density === "list" ? 34 : 48;
|
|
17201
|
+
const menuItems = [
|
|
17202
|
+
...onStartRename ? [{ id: "rename", label: "Rename", icon: lucideReact.Pencil, onSelect: () => onStartRename(folder) }] : [],
|
|
17203
|
+
...!isEmpty ? startMenuItem(startItemsForFolder?.(folder.path.join("/")) ?? []) : [],
|
|
17204
|
+
...onDownload && !isEmpty ? [{ id: "download", label: "Download", icon: lucideReact.Download, onSelect: () => onDownload(folder) }] : [],
|
|
17205
|
+
...onMove && !isEmpty ? [{ id: "move", label: "Move to\u2026", icon: lucideReact.FolderInput, onSelect: () => onMove(folder) }] : [],
|
|
17206
|
+
...onDelete ? [
|
|
17207
|
+
{
|
|
17208
|
+
id: "delete",
|
|
17209
|
+
label: "Delete",
|
|
17210
|
+
icon: lucideReact.Trash2,
|
|
17211
|
+
onSelect: () => onDelete(folder),
|
|
17212
|
+
destructive: true,
|
|
17213
|
+
separatorBefore: true
|
|
17214
|
+
}
|
|
17215
|
+
] : []
|
|
17216
|
+
];
|
|
17217
|
+
const displayName = folder.path.length === 1 ? chunkWV4TD2HZ_cjs.formatFolderSegment(folder.name) : folder.name;
|
|
17218
|
+
const providerIcon = folder.path.length === 1 && chunkWV4TD2HZ_cjs.hasFolderProviderIcon(folder.name) ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
17219
|
+
"span",
|
|
17220
|
+
{
|
|
17221
|
+
className: "flex items-center justify-center drop-shadow-sm",
|
|
17222
|
+
style: { width: iconSize, height: iconSize },
|
|
17223
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(chunkWV4TD2HZ_cjs.FolderProviderIcon, { folderPath: folder.name, className: "h-full w-full" })
|
|
17224
|
+
}
|
|
17225
|
+
) : void 0;
|
|
17226
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
17227
|
+
chunkWV4TD2HZ_cjs.ExplorerFolderTile,
|
|
17228
|
+
{
|
|
17229
|
+
name: folder.name,
|
|
17230
|
+
displayName: displayName === "" ? null : displayName,
|
|
17231
|
+
path: folder.path,
|
|
17232
|
+
count: folder.count,
|
|
17233
|
+
density,
|
|
17234
|
+
editing,
|
|
17235
|
+
selected,
|
|
17236
|
+
partiallySelected,
|
|
17237
|
+
processingCount,
|
|
17238
|
+
isOver,
|
|
17239
|
+
icon: providerIcon,
|
|
17240
|
+
menuItems,
|
|
17241
|
+
rootRef: setNodeRef,
|
|
17242
|
+
onOpen: () => onOpen(folder),
|
|
17243
|
+
onToggleSelect: onToggleSelect ? (e) => onToggleSelect(folder, e) : void 0,
|
|
17244
|
+
onCommitName: (name) => onCommitName?.(folder, name),
|
|
17245
|
+
onCancelName
|
|
17246
|
+
}
|
|
17247
|
+
);
|
|
17248
|
+
});
|
|
17249
|
+
var GRID_GAP = 12;
|
|
17250
|
+
var SCROLL_PADDING_X = 32;
|
|
17251
|
+
var PAGE_ASPECT = 1.3;
|
|
17252
|
+
var TILE_MIN = 88;
|
|
17253
|
+
var TILE_MAX = 232;
|
|
17254
|
+
var TILE_DEFAULT = 200;
|
|
17255
|
+
var COMPACT_BELOW = 132;
|
|
17256
|
+
var NO_DOCUMENTS = [];
|
|
17257
|
+
function useFilesWorkspace() {
|
|
17258
|
+
const { workspaceId, userId, live } = chunkFM3IRQJW_cjs.useConnectedWorkspace();
|
|
17259
|
+
const { members, role } = chunkCQCNU5KT_cjs.useConnectedWorkspaceRole();
|
|
17260
|
+
const { data: workspaces } = react$1.useWorkspaces({ enabled: live });
|
|
17261
|
+
const workspaceName = workspaces?.find((w) => w.external_id === workspaceId)?.name;
|
|
17262
|
+
return {
|
|
17263
|
+
workspaceId: workspaceId ?? "",
|
|
17264
|
+
workspaceName,
|
|
17265
|
+
userId,
|
|
17266
|
+
role: role ?? null,
|
|
17267
|
+
members
|
|
17268
|
+
};
|
|
17269
|
+
}
|
|
17270
|
+
var ConnectedFilesExplorer = react.forwardRef(function ConnectedFilesExplorer2({
|
|
17271
|
+
documents,
|
|
17272
|
+
isLoading,
|
|
17273
|
+
canUpload,
|
|
17274
|
+
selectedIds,
|
|
17275
|
+
onSelectionChange,
|
|
17276
|
+
onOrderedFilesChange,
|
|
17277
|
+
onOpenDocument,
|
|
17278
|
+
onUploadFiles,
|
|
17279
|
+
folderPath,
|
|
17280
|
+
onFolderPathChange,
|
|
17281
|
+
search = "",
|
|
17282
|
+
sort,
|
|
17283
|
+
sortReversed,
|
|
17284
|
+
tileSize,
|
|
17285
|
+
onMoveSelected,
|
|
17286
|
+
onFolderMove,
|
|
17287
|
+
onOpenInReview,
|
|
17288
|
+
emptyWorkspace
|
|
17289
|
+
}, ref) {
|
|
17290
|
+
const { confirm, notify: notify14 } = chunkCNHUJRQ4_cjs.useBlocksEnvironment();
|
|
17291
|
+
const currentPath = folderPath;
|
|
17292
|
+
const density = tileSize < COMPACT_BELOW ? "list" : "grid";
|
|
17293
|
+
const [containerWidth, setContainerWidth] = react.useState(0);
|
|
17294
|
+
const [activeDragId, setActiveDragId] = react.useState(null);
|
|
17295
|
+
const [isFileDragOver, setIsFileDragOver] = react.useState(false);
|
|
17296
|
+
const [renamingId, setRenamingId] = react.useState(null);
|
|
17297
|
+
const scrollRef = react.useRef(null);
|
|
17298
|
+
const anchorRef = react.useRef(null);
|
|
17299
|
+
const dragIdsRef = react.useRef([]);
|
|
17300
|
+
const fileDragDepth = react.useRef(0);
|
|
17301
|
+
const marqueeOverlayRef = react.useRef(null);
|
|
17302
|
+
const marqueeRef = react.useRef(
|
|
17303
|
+
null
|
|
17304
|
+
);
|
|
17305
|
+
const didMarqueeRef = react.useRef(false);
|
|
17306
|
+
const updateDocument = react$1.useUpdateDocuments();
|
|
17307
|
+
const deleteDocuments = react$1.useDeleteDocuments();
|
|
17308
|
+
const renameFolder = react$1.useRenameFolder();
|
|
17309
|
+
const { workspaceId: wsId, workspaceName, userId, role, members } = useFilesWorkspace();
|
|
17310
|
+
const { downloadDocuments, downloadDocument } = react$1.useDownloadDocuments({ workspaceName });
|
|
17311
|
+
const { data: workspaceTags } = react$1.useTags();
|
|
17312
|
+
const userById = react.useMemo(() => {
|
|
17313
|
+
const map = /* @__PURE__ */ new Map();
|
|
17314
|
+
for (const member of members) map.set(member.user.external_id, member.user);
|
|
17315
|
+
return map;
|
|
17316
|
+
}, [members]);
|
|
17317
|
+
const tagNameById = react.useMemo(() => {
|
|
17318
|
+
const map = /* @__PURE__ */ new Map();
|
|
17319
|
+
for (const tag of workspaceTags ?? []) map.set(tag.external_id, tag.name);
|
|
17320
|
+
return map;
|
|
17321
|
+
}, [workspaceTags]);
|
|
17322
|
+
const pendingFolders = usePendingFolders(wsId);
|
|
17323
|
+
const addPendingFolder = useFilesStore((state) => state.addPendingFolder);
|
|
17324
|
+
const removePendingFolder = useFilesStore((state) => state.removePendingFolder);
|
|
17325
|
+
const [editingFolderPath, setEditingFolderPath] = react.useState(null);
|
|
17326
|
+
const isSearching = search.trim().length > 0;
|
|
17327
|
+
const selectedSet = react.useMemo(() => new Set(selectedIds), [selectedIds]);
|
|
17328
|
+
const selectedIdsRef = react.useRef(selectedIds);
|
|
17329
|
+
selectedIdsRef.current = selectedIds;
|
|
17330
|
+
const { folders, files } = react.useMemo(() => {
|
|
17331
|
+
const result = isSearching ? {
|
|
17332
|
+
folders: [],
|
|
17333
|
+
files: chunkWV4TD2HZ_cjs.searchExplorerDocuments(documents, search, sort)
|
|
17334
|
+
} : chunkWV4TD2HZ_cjs.buildExplorerEntries(documents, currentPath, sort, [...pendingFolders]);
|
|
17335
|
+
if (sortReversed) result.files = [...result.files].reverse();
|
|
17336
|
+
return result;
|
|
17337
|
+
}, [documents, currentPath, sort, isSearching, search, sortReversed, pendingFolders]);
|
|
17338
|
+
const entries = react.useMemo(
|
|
17339
|
+
() => [...folders, ...files.map((doc) => ({ kind: "file", doc }))],
|
|
17340
|
+
[folders, files]
|
|
17341
|
+
);
|
|
17342
|
+
const orderedFileIds = react.useMemo(() => files.map((d) => d.external_id), [files]);
|
|
17343
|
+
const folderDocs = react.useMemo(() => {
|
|
17344
|
+
const map = /* @__PURE__ */ new Map();
|
|
17345
|
+
for (const f of folders) map.set(f.path.join("/"), chunkWV4TD2HZ_cjs.collectFolderDocs(documents, f.path));
|
|
17346
|
+
return map;
|
|
17347
|
+
}, [folders, documents]);
|
|
17348
|
+
const folderSelection = react.useMemo(() => {
|
|
17349
|
+
const map = /* @__PURE__ */ new Map();
|
|
17350
|
+
for (const [key, docs] of folderDocs) {
|
|
17351
|
+
const sel = docs.reduce((n, d) => selectedSet.has(d.external_id) ? n + 1 : n, 0);
|
|
17352
|
+
map.set(key, { all: docs.length > 0 && sel === docs.length, some: sel > 0 });
|
|
17353
|
+
}
|
|
17354
|
+
return map;
|
|
17355
|
+
}, [folderDocs, selectedSet]);
|
|
17356
|
+
const contentWidth = Math.max(0, containerWidth - SCROLL_PADDING_X);
|
|
17357
|
+
const columnCount = Math.max(
|
|
17358
|
+
1,
|
|
17359
|
+
Math.floor((contentWidth + GRID_GAP) / (tileSize + GRID_GAP)) || 1
|
|
17360
|
+
);
|
|
17361
|
+
const colWidth = contentWidth > 0 ? (contentWidth - (columnCount - 1) * GRID_GAP) / columnCount : tileSize;
|
|
17362
|
+
const tileHeight = Math.max(120, Math.round(colWidth * PAGE_ASPECT));
|
|
17363
|
+
const rowHeight = tileHeight + GRID_GAP;
|
|
17364
|
+
const rowCount = Math.ceil(entries.length / columnCount);
|
|
17365
|
+
const rowVirtualizer = reactVirtual.useVirtualizer({
|
|
17366
|
+
count: rowCount,
|
|
17367
|
+
getScrollElement: () => scrollRef.current,
|
|
17368
|
+
estimateSize: () => rowHeight,
|
|
17369
|
+
overscan: 3
|
|
17370
|
+
});
|
|
17371
|
+
const virtualRows = rowVirtualizer.getVirtualItems();
|
|
17372
|
+
const firstRow = virtualRows.length > 0 ? virtualRows[0].index : 0;
|
|
17373
|
+
const lastRow = virtualRows.length > 0 ? virtualRows[virtualRows.length - 1].index : -1;
|
|
17374
|
+
const visibleFileIds = react.useMemo(() => {
|
|
17375
|
+
const ids = [];
|
|
17376
|
+
for (let r = firstRow; r <= lastRow; r++) {
|
|
17377
|
+
const start = r * columnCount;
|
|
17378
|
+
for (let c = 0; c < columnCount; c++) {
|
|
17379
|
+
const entry = entries[start + c];
|
|
17380
|
+
if (entry?.kind === "file") ids.push(entry.doc.external_id);
|
|
17381
|
+
}
|
|
17382
|
+
}
|
|
17383
|
+
return ids;
|
|
17384
|
+
}, [firstRow, lastRow, columnCount, entries]);
|
|
17385
|
+
const thumbnailsById = react$1.useDocumentThumbnails(visibleFileIds);
|
|
17386
|
+
react.useEffect(() => {
|
|
17387
|
+
rowVirtualizer.measure();
|
|
17388
|
+
}, [rowVirtualizer, columnCount, rowHeight, entries.length]);
|
|
17389
|
+
const isWholeWorkspaceEmpty = !isLoading && documents.length === 0 && canUpload && emptyWorkspace !== void 0;
|
|
17390
|
+
react.useLayoutEffect(() => {
|
|
17391
|
+
const el = scrollRef.current;
|
|
17392
|
+
if (!el) return;
|
|
17393
|
+
const apply = () => {
|
|
17394
|
+
const next = Math.round(el.clientWidth);
|
|
17395
|
+
setContainerWidth((prev) => prev === next ? prev : next);
|
|
17396
|
+
};
|
|
17397
|
+
apply();
|
|
17398
|
+
const ro = new ResizeObserver(apply);
|
|
17399
|
+
ro.observe(el);
|
|
17400
|
+
return () => ro.disconnect();
|
|
17401
|
+
}, [isWholeWorkspaceEmpty]);
|
|
17402
|
+
react.useEffect(() => {
|
|
17403
|
+
anchorRef.current = null;
|
|
17404
|
+
if (scrollRef.current) scrollRef.current.scrollTop = 0;
|
|
17405
|
+
}, [currentPath, search]);
|
|
17406
|
+
react.useEffect(() => {
|
|
17407
|
+
const MARQUEE_THRESHOLD = 5;
|
|
17408
|
+
let rafId = 0;
|
|
17409
|
+
let cur = null;
|
|
17410
|
+
const paint = () => {
|
|
17411
|
+
rafId = 0;
|
|
17412
|
+
const el = marqueeOverlayRef.current;
|
|
17413
|
+
if (!el || !cur) return;
|
|
17414
|
+
el.style.display = "block";
|
|
17415
|
+
el.style.left = `${cur.left}px`;
|
|
17416
|
+
el.style.top = `${cur.top}px`;
|
|
17417
|
+
el.style.width = `${cur.right - cur.left}px`;
|
|
17418
|
+
el.style.height = `${cur.bottom - cur.top}px`;
|
|
17419
|
+
};
|
|
17420
|
+
const onMove = (e) => {
|
|
17421
|
+
const m = marqueeRef.current;
|
|
17422
|
+
if (!m) return;
|
|
17423
|
+
if (!didMarqueeRef.current && Math.hypot(e.clientX - m.x, e.clientY - m.y) < MARQUEE_THRESHOLD)
|
|
17424
|
+
return;
|
|
17425
|
+
didMarqueeRef.current = true;
|
|
17426
|
+
const b = scrollRef.current?.getBoundingClientRect();
|
|
17427
|
+
const px = b ? Math.max(b.left, Math.min(e.clientX, b.right)) : e.clientX;
|
|
17428
|
+
const py = b ? Math.max(b.top, Math.min(e.clientY, b.bottom)) : e.clientY;
|
|
17429
|
+
cur = {
|
|
17430
|
+
left: Math.min(m.x, px),
|
|
17431
|
+
top: Math.min(m.y, py),
|
|
17432
|
+
right: Math.max(m.x, px),
|
|
17433
|
+
bottom: Math.max(m.y, py)
|
|
17434
|
+
};
|
|
17435
|
+
if (!rafId) rafId = requestAnimationFrame(paint);
|
|
17436
|
+
};
|
|
17437
|
+
const onUp = () => {
|
|
17438
|
+
const m = marqueeRef.current;
|
|
17439
|
+
if (!m) return;
|
|
17440
|
+
marqueeRef.current = null;
|
|
17441
|
+
if (rafId) cancelAnimationFrame(rafId);
|
|
17442
|
+
rafId = 0;
|
|
17443
|
+
const el = marqueeOverlayRef.current;
|
|
17444
|
+
if (el) el.style.display = "none";
|
|
17445
|
+
if (!didMarqueeRef.current || !cur) return;
|
|
17446
|
+
const box = cur;
|
|
17447
|
+
const hit = [];
|
|
17448
|
+
scrollRef.current?.querySelectorAll("[data-doc-id]").forEach((node) => {
|
|
17449
|
+
const r = node.getBoundingClientRect();
|
|
17450
|
+
if (r.left < box.right && r.right > box.left && r.top < box.bottom && r.bottom > box.top) {
|
|
17451
|
+
const id = node.getAttribute("data-doc-id");
|
|
17452
|
+
if (id) hit.push(id);
|
|
17453
|
+
}
|
|
17454
|
+
});
|
|
17455
|
+
onSelectionChange(m.additive ? Array.from(/* @__PURE__ */ new Set([...m.base, ...hit])) : hit);
|
|
17456
|
+
};
|
|
17457
|
+
window.addEventListener("pointermove", onMove);
|
|
17458
|
+
window.addEventListener("pointerup", onUp);
|
|
17459
|
+
return () => {
|
|
17460
|
+
window.removeEventListener("pointermove", onMove);
|
|
17461
|
+
window.removeEventListener("pointerup", onUp);
|
|
17462
|
+
if (rafId) cancelAnimationFrame(rafId);
|
|
17463
|
+
};
|
|
17464
|
+
}, [onSelectionChange]);
|
|
17465
|
+
const handleScrollPointerDown = react.useCallback((e) => {
|
|
17466
|
+
if (e.button !== 0) return;
|
|
17467
|
+
const el = e.target;
|
|
17468
|
+
if (el.closest(
|
|
17469
|
+
'[data-testid="explorer-file"],[data-testid="explorer-folder"],button,input,select,a,[role="button"]'
|
|
17470
|
+
)) {
|
|
17471
|
+
return;
|
|
17472
|
+
}
|
|
17473
|
+
const additive = e.shiftKey || e.metaKey || e.ctrlKey;
|
|
17474
|
+
marqueeRef.current = {
|
|
17475
|
+
x: e.clientX,
|
|
17476
|
+
y: e.clientY,
|
|
17477
|
+
additive,
|
|
17478
|
+
base: additive ? selectedIdsRef.current : []
|
|
17479
|
+
};
|
|
17480
|
+
didMarqueeRef.current = false;
|
|
17481
|
+
}, []);
|
|
17482
|
+
const openFolder = react.useCallback(
|
|
17483
|
+
(folder) => onFolderPathChange(folder.path),
|
|
17484
|
+
[onFolderPathChange]
|
|
17485
|
+
);
|
|
17486
|
+
const handleNewFolder = react.useCallback(() => {
|
|
17487
|
+
if (!wsId) return;
|
|
17488
|
+
const siblings = new Set(folders.map((f) => f.name.toLowerCase()));
|
|
17489
|
+
const base = "New folder";
|
|
17490
|
+
let name = base;
|
|
17491
|
+
let i = 2;
|
|
17492
|
+
while (siblings.has(name.toLowerCase())) name = `${base} ${i++}`;
|
|
17493
|
+
const path = chunkWV4TD2HZ_cjs.joinFolderPath([...currentPath, name]);
|
|
17494
|
+
if (!path) return;
|
|
17495
|
+
addPendingFolder(wsId, path);
|
|
17496
|
+
setEditingFolderPath(path);
|
|
17497
|
+
}, [wsId, folders, currentPath, addPendingFolder]);
|
|
17498
|
+
const lastOrderedRef = react.useRef([]);
|
|
17499
|
+
react.useEffect(() => {
|
|
17500
|
+
const prev = lastOrderedRef.current;
|
|
17501
|
+
if (prev.length === orderedFileIds.length && prev.every((id, i) => id === orderedFileIds[i])) {
|
|
17502
|
+
return;
|
|
17503
|
+
}
|
|
17504
|
+
lastOrderedRef.current = orderedFileIds;
|
|
17505
|
+
onOrderedFilesChange?.(orderedFileIds);
|
|
17506
|
+
}, [onOrderedFilesChange, orderedFileIds]);
|
|
17507
|
+
const scrollToDocument = react.useCallback(
|
|
17508
|
+
(docId) => {
|
|
17509
|
+
const index = entries.findIndex((e) => e.kind === "file" && e.doc.external_id === docId);
|
|
17510
|
+
if (index < 0) return;
|
|
17511
|
+
rowVirtualizer.scrollToIndex(Math.floor(index / columnCount), { align: "center" });
|
|
17512
|
+
},
|
|
17513
|
+
[entries, columnCount, rowVirtualizer]
|
|
17514
|
+
);
|
|
17515
|
+
react.useImperativeHandle(ref, () => ({ triggerNewFolder: handleNewFolder, scrollToDocument }), [
|
|
17516
|
+
handleNewFolder,
|
|
17517
|
+
scrollToDocument
|
|
17518
|
+
]);
|
|
17519
|
+
const commitFolderName = react.useCallback(
|
|
17520
|
+
async (folder, rawName) => {
|
|
17521
|
+
setEditingFolderPath(null);
|
|
17522
|
+
const name = rawName.trim();
|
|
17523
|
+
if (!wsId || !name || name === folder.name) return;
|
|
17524
|
+
const siblings = new Set(folders.filter((f) => f !== folder).map((f) => f.name.toLowerCase()));
|
|
17525
|
+
if (siblings.has(name.toLowerCase())) {
|
|
17526
|
+
notify14(`A folder named "${name}" already exists here.`, "error");
|
|
17527
|
+
return;
|
|
17528
|
+
}
|
|
17529
|
+
const oldPath = chunkWV4TD2HZ_cjs.joinFolderPath(folder.path);
|
|
17530
|
+
const newPrefix = [...folder.path.slice(0, -1), name];
|
|
17531
|
+
const newPath = chunkWV4TD2HZ_cjs.joinFolderPath(newPrefix);
|
|
17532
|
+
const docs = chunkWV4TD2HZ_cjs.collectFolderDocs(documents, folder.path);
|
|
17533
|
+
try {
|
|
17534
|
+
if (await renameFolder(docs, folder.path, newPrefix) > 0) {
|
|
17535
|
+
notify14(`Renamed folder to "${name}"`, "success");
|
|
17536
|
+
}
|
|
17537
|
+
} catch {
|
|
17538
|
+
notify14("Failed to rename folder. Please try again.", "error");
|
|
17539
|
+
return;
|
|
17540
|
+
}
|
|
17541
|
+
if (oldPath) removePendingFolder(wsId, oldPath);
|
|
17542
|
+
if (docs.length === 0 && newPath) addPendingFolder(wsId, newPath);
|
|
17543
|
+
},
|
|
17544
|
+
[wsId, folders, documents, renameFolder, notify14, addPendingFolder, removePendingFolder]
|
|
17545
|
+
);
|
|
17546
|
+
const cancelFolderName = react.useCallback(() => setEditingFolderPath(null), []);
|
|
17547
|
+
const clearSelection = react.useCallback(() => {
|
|
17548
|
+
if (selectedIdsRef.current.length > 0) onSelectionChange([]);
|
|
17549
|
+
anchorRef.current = null;
|
|
17550
|
+
}, [onSelectionChange]);
|
|
17551
|
+
const handleSelect = react.useCallback(
|
|
17552
|
+
(doc, e) => {
|
|
17553
|
+
const id = doc.external_id;
|
|
17554
|
+
if (e.shiftKey) {
|
|
17555
|
+
const from = anchorRef.current ?? id;
|
|
17556
|
+
const a = orderedFileIds.indexOf(from);
|
|
17557
|
+
const b = orderedFileIds.indexOf(id);
|
|
17558
|
+
if (a !== -1 && b !== -1) {
|
|
17559
|
+
anchorRef.current = from;
|
|
17560
|
+
const [lo, hi] = a < b ? [a, b] : [b, a];
|
|
17561
|
+
onSelectionChange(orderedFileIds.slice(lo, hi + 1));
|
|
17562
|
+
return;
|
|
17563
|
+
}
|
|
17564
|
+
}
|
|
17565
|
+
if (e.metaKey || e.ctrlKey) {
|
|
17566
|
+
onSelectionChange(
|
|
17567
|
+
selectedSet.has(id) ? selectedIds.filter((s) => s !== id) : [...selectedIds, id]
|
|
17568
|
+
);
|
|
17569
|
+
anchorRef.current = id;
|
|
17570
|
+
return;
|
|
17571
|
+
}
|
|
17572
|
+
onSelectionChange([id]);
|
|
17573
|
+
anchorRef.current = id;
|
|
17574
|
+
},
|
|
17575
|
+
[onSelectionChange, orderedFileIds, selectedIds, selectedSet]
|
|
17576
|
+
);
|
|
17577
|
+
const handleToggle = react.useCallback(
|
|
17578
|
+
(doc, e) => {
|
|
17579
|
+
e.stopPropagation();
|
|
17580
|
+
const id = doc.external_id;
|
|
17581
|
+
onSelectionChange(
|
|
17582
|
+
selectedSet.has(id) ? selectedIds.filter((s) => s !== id) : [...selectedIds, id]
|
|
17583
|
+
);
|
|
17584
|
+
anchorRef.current = id;
|
|
17585
|
+
},
|
|
17586
|
+
[onSelectionChange, selectedIds, selectedSet]
|
|
17587
|
+
);
|
|
17588
|
+
const handleToggleFolder = react.useCallback(
|
|
17589
|
+
(folder, e) => {
|
|
17590
|
+
e.stopPropagation();
|
|
17591
|
+
const ids = chunkWV4TD2HZ_cjs.collectFolderDocs(documents, folder.path).map((d) => d.external_id);
|
|
17592
|
+
if (ids.length === 0) return;
|
|
17593
|
+
if (ids.every((id) => selectedSet.has(id))) {
|
|
17594
|
+
const remove = new Set(ids);
|
|
17595
|
+
onSelectionChange(selectedIds.filter((id) => !remove.has(id)));
|
|
17596
|
+
} else {
|
|
17597
|
+
onSelectionChange(Array.from(/* @__PURE__ */ new Set([...selectedIds, ...ids])));
|
|
17598
|
+
}
|
|
17599
|
+
anchorRef.current = null;
|
|
17600
|
+
},
|
|
17601
|
+
[documents, onSelectionChange, selectedIds, selectedSet]
|
|
17602
|
+
);
|
|
17603
|
+
const handleOpenFile = react.useCallback(
|
|
17604
|
+
(doc) => onOpenDocument(doc.external_id),
|
|
17605
|
+
[onOpenDocument]
|
|
17606
|
+
);
|
|
17607
|
+
const handleOpenInReview = react.useMemo(
|
|
17608
|
+
() => onOpenInReview ? (doc) => onOpenInReview(doc.external_id) : void 0,
|
|
17609
|
+
[onOpenInReview]
|
|
17610
|
+
);
|
|
17611
|
+
const startRename = react.useCallback((doc) => setRenamingId(doc.external_id), []);
|
|
17612
|
+
const cancelRename = react.useCallback(() => setRenamingId(null), []);
|
|
17613
|
+
const commitRename = react.useCallback(
|
|
17614
|
+
async (doc, name) => {
|
|
17615
|
+
setRenamingId(null);
|
|
17616
|
+
try {
|
|
17617
|
+
await updateDocument.mutateAsync({
|
|
17618
|
+
documents: [
|
|
17619
|
+
{ external_id: doc.external_id, doc_metadata: { ...doc.doc_metadata, title: name } }
|
|
17620
|
+
]
|
|
17621
|
+
});
|
|
17622
|
+
notify14(`Renamed to "${name}"`, "success");
|
|
17623
|
+
} catch {
|
|
17624
|
+
notify14("Failed to rename. Please try again.", "error");
|
|
17625
|
+
}
|
|
17626
|
+
},
|
|
17627
|
+
[updateDocument, notify14]
|
|
17628
|
+
);
|
|
17629
|
+
react.useEffect(() => {
|
|
17630
|
+
const onKey = (e) => {
|
|
17631
|
+
if (e.key !== "F2" || renamingId) return;
|
|
17632
|
+
const target = e.target;
|
|
17633
|
+
if (target && /^(input|textarea|select)$/i.test(target.tagName)) return;
|
|
17634
|
+
if (selectedIdsRef.current.length === 1) setRenamingId(selectedIdsRef.current[0]);
|
|
17635
|
+
};
|
|
17636
|
+
window.addEventListener("keydown", onKey);
|
|
17637
|
+
return () => window.removeEventListener("keydown", onKey);
|
|
17638
|
+
}, [renamingId]);
|
|
17639
|
+
const handleDownload = react.useCallback(
|
|
17640
|
+
(doc) => void downloadDocument(doc),
|
|
17641
|
+
[downloadDocument]
|
|
17642
|
+
);
|
|
17643
|
+
const handleMove = react.useMemo(
|
|
17644
|
+
() => onMoveSelected ? (doc) => {
|
|
17645
|
+
onSelectionChange([doc.external_id]);
|
|
17646
|
+
onMoveSelected();
|
|
17647
|
+
} : void 0,
|
|
17648
|
+
[onSelectionChange, onMoveSelected]
|
|
17649
|
+
);
|
|
17650
|
+
const handleDelete = react.useCallback(
|
|
17651
|
+
async (doc) => {
|
|
17652
|
+
const name = chunkWV4TD2HZ_cjs.getExplorerDisplayName(doc);
|
|
17653
|
+
const confirmed = await confirm({
|
|
17654
|
+
message: `Delete "${name}"? ${chunkWV4TD2HZ_cjs.RECENTLY_DELETED_HINT}`,
|
|
17655
|
+
title: "Delete file"
|
|
17656
|
+
});
|
|
17657
|
+
if (!confirmed) return;
|
|
17658
|
+
try {
|
|
17659
|
+
await deleteDocuments.mutateAsync([doc.external_id]);
|
|
17660
|
+
onSelectionChange(selectedIdsRef.current.filter((id) => id !== doc.external_id));
|
|
17661
|
+
notify14(`Deleted "${name}"`, "success");
|
|
17662
|
+
} catch {
|
|
17663
|
+
notify14("Failed to delete. Please try again.", "error");
|
|
17664
|
+
}
|
|
17665
|
+
},
|
|
17666
|
+
[confirm, deleteDocuments, onSelectionChange, notify14]
|
|
17667
|
+
);
|
|
17668
|
+
const startFolderRename = react.useCallback(
|
|
17669
|
+
(folder) => setEditingFolderPath(folder.path.join("/")),
|
|
17670
|
+
[]
|
|
17671
|
+
);
|
|
17672
|
+
const handleFolderDownload = react.useCallback(
|
|
17673
|
+
(folder) => {
|
|
17674
|
+
const docs = chunkWV4TD2HZ_cjs.collectFolderDocs(documents, folder.path);
|
|
17675
|
+
if (docs.length > 0) void downloadDocuments(docs);
|
|
17676
|
+
},
|
|
17677
|
+
[documents, downloadDocuments]
|
|
17678
|
+
);
|
|
17679
|
+
const handleFolderMove = react.useMemo(() => {
|
|
17680
|
+
if (onFolderMove) return onFolderMove;
|
|
17681
|
+
if (!onMoveSelected) return void 0;
|
|
17682
|
+
return (folder) => {
|
|
17683
|
+
const ids = chunkWV4TD2HZ_cjs.collectFolderDocs(documents, folder.path).map((d) => d.external_id);
|
|
17684
|
+
if (ids.length === 0) return;
|
|
17685
|
+
onSelectionChange(ids);
|
|
17686
|
+
onMoveSelected();
|
|
17687
|
+
};
|
|
17688
|
+
}, [documents, onFolderMove, onMoveSelected, onSelectionChange]);
|
|
17689
|
+
const handleFolderDelete = react.useCallback(
|
|
17690
|
+
async (folder) => {
|
|
17691
|
+
const docs = chunkWV4TD2HZ_cjs.collectFolderDocs(documents, folder.path);
|
|
17692
|
+
if (docs.length === 0) {
|
|
17693
|
+
const path = chunkWV4TD2HZ_cjs.joinFolderPath(folder.path);
|
|
17694
|
+
if (wsId && path) removePendingFolder(wsId, path);
|
|
17695
|
+
return;
|
|
17696
|
+
}
|
|
17697
|
+
const confirmed = await confirm({
|
|
17698
|
+
message: `Delete folder "${folder.name}" and its ${docs.length} item${docs.length === 1 ? "" : "s"}? ${chunkWV4TD2HZ_cjs.RECENTLY_DELETED_HINT_PLURAL}`,
|
|
17699
|
+
title: "Delete folder"
|
|
17700
|
+
});
|
|
17701
|
+
if (!confirmed) return;
|
|
17702
|
+
try {
|
|
17703
|
+
const ids = docs.map((d) => d.external_id);
|
|
17704
|
+
await deleteDocuments.mutateAsync(ids);
|
|
17705
|
+
const removed = new Set(ids);
|
|
17706
|
+
onSelectionChange(selectedIdsRef.current.filter((id) => !removed.has(id)));
|
|
17707
|
+
notify14(`Deleted folder "${folder.name}"`, "success");
|
|
17708
|
+
} catch {
|
|
17709
|
+
notify14("Failed to delete folder. Please try again.", "error");
|
|
17710
|
+
}
|
|
17711
|
+
},
|
|
17712
|
+
[confirm, documents, deleteDocuments, onSelectionChange, removePendingFolder, wsId, notify14]
|
|
17713
|
+
);
|
|
17714
|
+
const canDeleteFolder = react.useCallback(
|
|
17715
|
+
(folder) => canUpload && chunkWV4TD2HZ_cjs.collectFolderDocs(documents, folder.path).every(
|
|
17716
|
+
(doc) => chunkWV4TD2HZ_cjs.canDeleteDocument(doc, userId, role)
|
|
17717
|
+
),
|
|
17718
|
+
[canUpload, documents, userId, role]
|
|
17719
|
+
);
|
|
17720
|
+
const handleBackgroundClick = react.useCallback(
|
|
17721
|
+
(e) => {
|
|
17722
|
+
if (didMarqueeRef.current) {
|
|
17723
|
+
didMarqueeRef.current = false;
|
|
17724
|
+
return;
|
|
17725
|
+
}
|
|
17726
|
+
if (!e.target.closest('[data-testid^="explorer-"]')) clearSelection();
|
|
17727
|
+
},
|
|
17728
|
+
[clearSelection]
|
|
17729
|
+
);
|
|
17730
|
+
const moveDocs = react.useCallback(
|
|
17731
|
+
async (ids, folder) => {
|
|
17732
|
+
if (ids.length === 0) return;
|
|
17733
|
+
try {
|
|
17734
|
+
await updateDocument.mutateAsync({
|
|
17735
|
+
documents: ids.map((external_id) => ({ external_id, folder }))
|
|
17736
|
+
});
|
|
17737
|
+
clearSelection();
|
|
17738
|
+
notify14(
|
|
17739
|
+
`Moved ${ids.length} item${ids.length === 1 ? "" : "s"} to "${folder ?? "Home"}"`,
|
|
17740
|
+
"success"
|
|
17741
|
+
);
|
|
17742
|
+
} catch {
|
|
17743
|
+
notify14("Failed to move. Please try again.", "error");
|
|
17744
|
+
}
|
|
17745
|
+
},
|
|
17746
|
+
[updateDocument, clearSelection, notify14]
|
|
17747
|
+
);
|
|
17748
|
+
const sensors = core.useSensors(
|
|
17749
|
+
core.useSensor(core.MouseSensor, { activationConstraint: { distance: 6 } }),
|
|
17750
|
+
core.useSensor(core.TouchSensor, { activationConstraint: { delay: 150, tolerance: 8 } })
|
|
17751
|
+
);
|
|
17752
|
+
const collisionDetection = react.useCallback((args) => {
|
|
17753
|
+
const hits = core.pointerWithin(args);
|
|
17754
|
+
return hits.length > 0 ? hits : core.rectIntersection(args);
|
|
17755
|
+
}, []);
|
|
17756
|
+
const handleDragStart = react.useCallback(
|
|
17757
|
+
(event) => {
|
|
17758
|
+
const docId = event.active.data.current?.docId;
|
|
17759
|
+
if (!docId) return;
|
|
17760
|
+
setActiveDragId(docId);
|
|
17761
|
+
if (!selectedIdsRef.current.includes(docId)) {
|
|
17762
|
+
onSelectionChange([docId]);
|
|
17763
|
+
dragIdsRef.current = [docId];
|
|
17764
|
+
} else {
|
|
17765
|
+
dragIdsRef.current = selectedIdsRef.current;
|
|
17766
|
+
}
|
|
17767
|
+
},
|
|
17768
|
+
[onSelectionChange]
|
|
17769
|
+
);
|
|
17770
|
+
const handleDragEnd = react.useCallback(
|
|
17771
|
+
(event) => {
|
|
17772
|
+
setActiveDragId(null);
|
|
17773
|
+
const data = event.over?.data.current;
|
|
17774
|
+
if (data?.type === "folder" && data.path) {
|
|
17775
|
+
const targetFolder = chunkWV4TD2HZ_cjs.joinFolderPath(data.path);
|
|
17776
|
+
const moving = dragIdsRef.current.filter((id) => {
|
|
17777
|
+
const doc = documents.find((d) => d.external_id === id);
|
|
17778
|
+
return doc && (doc.folder ?? null) !== targetFolder;
|
|
17779
|
+
});
|
|
17780
|
+
void moveDocs(moving, targetFolder);
|
|
17781
|
+
}
|
|
17782
|
+
},
|
|
17783
|
+
[documents, moveDocs]
|
|
17784
|
+
);
|
|
17785
|
+
const handleNativeDragOver = react.useCallback(
|
|
17786
|
+
(e) => {
|
|
17787
|
+
if (!canUpload) return;
|
|
17788
|
+
if (e.dataTransfer.types.includes("Files")) {
|
|
17789
|
+
e.preventDefault();
|
|
17790
|
+
e.dataTransfer.dropEffect = "copy";
|
|
17791
|
+
}
|
|
17792
|
+
},
|
|
17793
|
+
[canUpload]
|
|
17794
|
+
);
|
|
17795
|
+
const handleNativeDragEnter = react.useCallback(
|
|
17796
|
+
(e) => {
|
|
17797
|
+
if (!canUpload || !e.dataTransfer.types.includes("Files")) return;
|
|
17798
|
+
fileDragDepth.current += 1;
|
|
17799
|
+
setIsFileDragOver(true);
|
|
17800
|
+
},
|
|
17801
|
+
[canUpload]
|
|
17802
|
+
);
|
|
17803
|
+
const handleNativeDragLeave = react.useCallback(() => {
|
|
17804
|
+
fileDragDepth.current = Math.max(0, fileDragDepth.current - 1);
|
|
17805
|
+
if (fileDragDepth.current === 0) setIsFileDragOver(false);
|
|
17806
|
+
}, []);
|
|
17807
|
+
const handleNativeDrop = react.useCallback(
|
|
17808
|
+
(e) => {
|
|
17809
|
+
fileDragDepth.current = 0;
|
|
17810
|
+
setIsFileDragOver(false);
|
|
17811
|
+
if (!canUpload) return;
|
|
17812
|
+
const dropped = Array.from(e.dataTransfer.files ?? []);
|
|
17813
|
+
if (dropped.length > 0) {
|
|
17814
|
+
e.preventDefault();
|
|
17815
|
+
onUploadFiles(dropped, chunkWV4TD2HZ_cjs.joinFolderPath(currentPath));
|
|
17816
|
+
}
|
|
17817
|
+
},
|
|
17818
|
+
[canUpload, currentPath, onUploadFiles]
|
|
17819
|
+
);
|
|
17820
|
+
const activeDoc = activeDragId ? documents.find((d) => d.external_id === activeDragId) : null;
|
|
17821
|
+
const dragCount = dragIdsRef.current.length || 1;
|
|
17822
|
+
if (isWholeWorkspaceEmpty) return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: emptyWorkspace });
|
|
17823
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
17824
|
+
core.DndContext,
|
|
17825
|
+
{
|
|
17826
|
+
sensors,
|
|
17827
|
+
collisionDetection,
|
|
17828
|
+
onDragStart: handleDragStart,
|
|
17829
|
+
onDragEnd: handleDragEnd,
|
|
17830
|
+
onDragCancel: () => setActiveDragId(null),
|
|
17831
|
+
children: [
|
|
17832
|
+
/* @__PURE__ */ jsxRuntime.jsx(chunkWV4TD2HZ_cjs.ExplorerFrame, { "data-testid": "documents-explorer", children: /* @__PURE__ */ jsxRuntime.jsxs(chunkWV4TD2HZ_cjs.ExplorerStage, { children: [
|
|
17833
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
17834
|
+
chunkWV4TD2HZ_cjs.ExplorerScroller,
|
|
17835
|
+
{
|
|
17836
|
+
ref: scrollRef,
|
|
17837
|
+
onClick: handleBackgroundClick,
|
|
17838
|
+
onPointerDown: handleScrollPointerDown,
|
|
17839
|
+
onDragEnter: handleNativeDragEnter,
|
|
17840
|
+
onDragOver: handleNativeDragOver,
|
|
17841
|
+
onDragLeave: handleNativeDragLeave,
|
|
17842
|
+
onDrop: handleNativeDrop,
|
|
17843
|
+
"data-testid": "explorer-scroll",
|
|
17844
|
+
children: isLoading && documents.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx(chunkWV4TD2HZ_cjs.ExplorerLoadingTiles, {}) : entries.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
17845
|
+
chunkWV4TD2HZ_cjs.ExplorerEmpty,
|
|
17846
|
+
{
|
|
17847
|
+
title: isSearching ? `No files match "${search.trim()}"` : "This folder is empty",
|
|
17848
|
+
description: isSearching ? "Try a different search." : canUpload ? "Drop files here or use Upload to add documents." : "No documents here yet."
|
|
17849
|
+
}
|
|
17850
|
+
) : containerWidth === 0 ? (
|
|
17851
|
+
// Not measured yet: rendering now would flash one stretched column.
|
|
17852
|
+
/* @__PURE__ */ jsxRuntime.jsx(chunkWV4TD2HZ_cjs.ExplorerLoadingTiles, {})
|
|
17853
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
17854
|
+
"div",
|
|
17855
|
+
{
|
|
17856
|
+
style: {
|
|
17857
|
+
height: rowVirtualizer.getTotalSize(),
|
|
17858
|
+
position: "relative",
|
|
17859
|
+
width: "100%"
|
|
17860
|
+
},
|
|
17861
|
+
children: virtualRows.map((virtualRow) => {
|
|
17862
|
+
const start = virtualRow.index * columnCount;
|
|
17863
|
+
const rowEntries = entries.slice(start, start + columnCount);
|
|
17864
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
17865
|
+
"div",
|
|
17866
|
+
{
|
|
17867
|
+
style: {
|
|
17868
|
+
position: "absolute",
|
|
17869
|
+
top: 0,
|
|
17870
|
+
left: 0,
|
|
17871
|
+
width: "100%",
|
|
17872
|
+
height: tileHeight,
|
|
17873
|
+
transform: `translateY(${virtualRow.start}px)`,
|
|
17874
|
+
display: "grid",
|
|
17875
|
+
gridTemplateColumns: `repeat(${columnCount}, minmax(0, 1fr))`,
|
|
17876
|
+
columnGap: GRID_GAP
|
|
17877
|
+
},
|
|
17878
|
+
children: rowEntries.map((entry) => {
|
|
17879
|
+
if (entry.kind === "folder") {
|
|
17880
|
+
const key = entry.path.join("/");
|
|
17881
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
17882
|
+
FolderTile,
|
|
17883
|
+
{
|
|
17884
|
+
folder: entry,
|
|
17885
|
+
density,
|
|
17886
|
+
editing: editingFolderPath === key,
|
|
17887
|
+
selected: folderSelection.get(key)?.all,
|
|
17888
|
+
partiallySelected: folderSelection.get(key)?.some,
|
|
17889
|
+
documents: folderDocs.get(key) ?? NO_DOCUMENTS,
|
|
17890
|
+
onOpen: openFolder,
|
|
17891
|
+
onToggleSelect: handleToggleFolder,
|
|
17892
|
+
onCommitName: commitFolderName,
|
|
17893
|
+
onCancelName: cancelFolderName,
|
|
17894
|
+
onStartRename: canUpload ? startFolderRename : void 0,
|
|
17895
|
+
onDownload: handleFolderDownload,
|
|
17896
|
+
onMove: canUpload ? handleFolderMove : void 0,
|
|
17897
|
+
onDelete: canDeleteFolder(entry) ? handleFolderDelete : void 0
|
|
17898
|
+
},
|
|
17899
|
+
`folder:${key}`
|
|
17900
|
+
);
|
|
17901
|
+
}
|
|
17902
|
+
const doc = entry.doc;
|
|
17903
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
17904
|
+
FileTile,
|
|
17905
|
+
{
|
|
17906
|
+
doc,
|
|
17907
|
+
density,
|
|
17908
|
+
selected: selectedSet.has(doc.external_id),
|
|
17909
|
+
dragging: activeDragId === doc.external_id,
|
|
17910
|
+
dndActive: activeDragId !== null,
|
|
17911
|
+
renaming: renamingId === doc.external_id,
|
|
17912
|
+
canDelete: chunkWV4TD2HZ_cjs.canDeleteDocument(doc, userId, role),
|
|
17913
|
+
thumbnailUrl: thumbnailsById.get(doc.external_id),
|
|
17914
|
+
modifiedBy: userById.get(
|
|
17915
|
+
doc.updated_by_ext_id ?? doc.created_by_ext_id
|
|
17916
|
+
),
|
|
17917
|
+
tagNameById,
|
|
17918
|
+
onSelect: handleSelect,
|
|
17919
|
+
onToggle: handleToggle,
|
|
17920
|
+
onOpen: handleOpenFile,
|
|
17921
|
+
onReview: handleOpenInReview,
|
|
17922
|
+
onStartRename: startRename,
|
|
17923
|
+
onCommitRename: commitRename,
|
|
17924
|
+
onCancelRename: cancelRename,
|
|
17925
|
+
onDownload: handleDownload,
|
|
17926
|
+
onMove: canUpload ? handleMove : void 0,
|
|
17927
|
+
onDelete: handleDelete
|
|
17928
|
+
},
|
|
17929
|
+
doc.external_id
|
|
17930
|
+
);
|
|
17931
|
+
})
|
|
17932
|
+
},
|
|
17933
|
+
virtualRow.key
|
|
17934
|
+
);
|
|
17935
|
+
})
|
|
17936
|
+
}
|
|
17937
|
+
)
|
|
17938
|
+
}
|
|
17939
|
+
),
|
|
17940
|
+
/* @__PURE__ */ jsxRuntime.jsx(chunkWV4TD2HZ_cjs.ExplorerMarquee, { ref: marqueeOverlayRef, "data-testid": "explorer-marquee" }),
|
|
17941
|
+
isFileDragOver && /* @__PURE__ */ jsxRuntime.jsx(
|
|
17942
|
+
chunkWV4TD2HZ_cjs.ExplorerDropOverlay,
|
|
17943
|
+
{
|
|
17944
|
+
label: `Drop to upload${currentPath.length > 0 ? ` to "${currentPath[currentPath.length - 1]}"` : ""}`
|
|
17945
|
+
}
|
|
17946
|
+
)
|
|
17947
|
+
] }) }),
|
|
17948
|
+
/* @__PURE__ */ jsxRuntime.jsx(core.DragOverlay, { dropAnimation: null, children: activeDoc ? /* @__PURE__ */ jsxRuntime.jsx(DragPreview, { doc: activeDoc, count: dragCount }) : null })
|
|
17949
|
+
]
|
|
17950
|
+
}
|
|
17951
|
+
);
|
|
17952
|
+
});
|
|
17953
|
+
function DragPreview({ doc, count }) {
|
|
17954
|
+
const Icon = ui.getFileTypeIcon(doc.file_name, { mime: doc.file_type });
|
|
17955
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
17956
|
+
chunkWV4TD2HZ_cjs.ExplorerDragPreview,
|
|
17957
|
+
{
|
|
17958
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(Icon, { size: 20 }),
|
|
17959
|
+
title: ui.getDocumentTitle(doc, doc.file_name ?? "Untitled"),
|
|
17960
|
+
count
|
|
17961
|
+
}
|
|
17962
|
+
);
|
|
17963
|
+
}
|
|
16816
17964
|
function ActiveChat({ agentId, workspaceId }) {
|
|
16817
17965
|
const chat = react$1.useArbiChat({
|
|
16818
17966
|
agentId,
|
|
@@ -17065,6 +18213,7 @@ exports.ConnectedCalendar = ConnectedCalendar;
|
|
|
17065
18213
|
exports.ConnectedDangerZone = ConnectedDangerZone;
|
|
17066
18214
|
exports.ConnectedDriveSyncDialog = ConnectedDriveSyncDialog;
|
|
17067
18215
|
exports.ConnectedFactsPage = ConnectedFactsPage;
|
|
18216
|
+
exports.ConnectedFilesExplorer = ConnectedFilesExplorer;
|
|
17068
18217
|
exports.ConnectedIdentityVerification = ConnectedIdentityVerification;
|
|
17069
18218
|
exports.ConnectedLogoutDialog = ConnectedLogoutDialog;
|
|
17070
18219
|
exports.ConnectedMailAccounts = ConnectedMailAccounts;
|
|
@@ -17111,7 +18260,10 @@ exports.DEFAULT_SEARCH_ROW_LABELS = DEFAULT_SEARCH_ROW_LABELS;
|
|
|
17111
18260
|
exports.DEFAULT_SETTINGS_SECTIONS = DEFAULT_SETTINGS_SECTIONS;
|
|
17112
18261
|
exports.DEFAULT_TIMELINE_LABEL_WIDTH = DEFAULT_TIMELINE_LABEL_WIDTH;
|
|
17113
18262
|
exports.DEFAULT_WORKSPACE_LIST_LABELS = DEFAULT_WORKSPACE_LIST_LABELS;
|
|
18263
|
+
exports.DocumentSyncGlyph = DocumentSyncGlyph;
|
|
17114
18264
|
exports.FACTS_GRID_ID = FACTS_GRID_ID;
|
|
18265
|
+
exports.FileTooltipContent = FileTooltipContent;
|
|
18266
|
+
exports.FilesSupportProvider = FilesSupportProvider;
|
|
17115
18267
|
exports.InvoicesModal = InvoicesModal;
|
|
17116
18268
|
exports.NewProjectFlow = NewProjectFlow;
|
|
17117
18269
|
exports.NotificationCenter = NotificationCenter;
|
|
@@ -17124,6 +18276,9 @@ exports.SETTINGS_SECTION_IDS = SETTINGS_SECTION_IDS;
|
|
|
17124
18276
|
exports.SessionStatusIcon = SessionStatusIcon;
|
|
17125
18277
|
exports.SharedProjects = SharedProjects;
|
|
17126
18278
|
exports.StreamedArtifact = StreamedArtifact;
|
|
18279
|
+
exports.TILE_DEFAULT = TILE_DEFAULT;
|
|
18280
|
+
exports.TILE_MAX = TILE_MAX;
|
|
18281
|
+
exports.TILE_MIN = TILE_MIN;
|
|
17127
18282
|
exports.WORKSPACES_TAB_ID = WORKSPACES_TAB_ID;
|
|
17128
18283
|
exports.WorkflowRunThread = WorkflowRunThread;
|
|
17129
18284
|
exports.accountSettingsSection = accountSettingsSection;
|
|
@@ -17135,6 +18290,7 @@ exports.countNotificationTypes = countNotificationTypes;
|
|
|
17135
18290
|
exports.defaultUnmetPasswordRequirement = defaultUnmetPasswordRequirement;
|
|
17136
18291
|
exports.filterNotificationCenterItems = filterNotificationCenterItems;
|
|
17137
18292
|
exports.formatLastSync = formatLastSync;
|
|
18293
|
+
exports.isActiveDocumentStatus = isActiveDocumentStatus;
|
|
17138
18294
|
exports.mailSettingsSection = mailSettingsSection;
|
|
17139
18295
|
exports.openMeetingLink = openMeetingLink;
|
|
17140
18296
|
exports.privacySettingsSection = privacySettingsSection;
|
|
@@ -17143,6 +18299,7 @@ exports.requestCalendarComposer = requestCalendarComposer;
|
|
|
17143
18299
|
exports.requestCalendarEvent = requestCalendarEvent;
|
|
17144
18300
|
exports.requestProjectBillingFocus = requestProjectBillingFocus;
|
|
17145
18301
|
exports.resolveMailbox = resolveMailbox;
|
|
18302
|
+
exports.startMenuItem = startMenuItem;
|
|
17146
18303
|
exports.toWorkspaceSummary = toWorkspaceSummary;
|
|
17147
18304
|
exports.useAutoRefreshPendingProjects = useAutoRefreshPendingProjects;
|
|
17148
18305
|
exports.useCalendarViewStore = useCalendarViewStore;
|
|
@@ -17151,9 +18308,14 @@ exports.useConnectedShellWorkspaces = useConnectedShellWorkspaces;
|
|
|
17151
18308
|
exports.useConnectedWorkNotifications = useConnectedWorkNotifications;
|
|
17152
18309
|
exports.useConnectedWorkspaceList = useConnectedWorkspaceList;
|
|
17153
18310
|
exports.useConnectedWorkspaceSettings = useConnectedWorkspaceSettings;
|
|
18311
|
+
exports.useFilesStore = useFilesStore;
|
|
18312
|
+
exports.useFilesSupport = useFilesSupport;
|
|
18313
|
+
exports.useOfflineDocumentIds = useOfflineDocumentIds;
|
|
17154
18314
|
exports.useOpenBillingPortal = useOpenBillingPortal;
|
|
18315
|
+
exports.usePendingFolders = usePendingFolders;
|
|
17155
18316
|
exports.useProjectBillingFocus = useProjectBillingFocus;
|
|
17156
18317
|
exports.useReferralReward = useReferralReward;
|
|
18318
|
+
exports.useViewingDocumentId = useViewingDocumentId;
|
|
17157
18319
|
exports.windowLabel = windowLabel;
|
|
17158
18320
|
exports.workflowRunView = workflowRunView;
|
|
17159
18321
|
//# sourceMappingURL=index.cjs.map
|