@powerhousedao/connect 1.0.23-staging.2 → 1.0.25-dev.0
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/.env +1 -1
- package/dist/assets/{app-_0wz8A4r.js → app-BUYipU-h.js} +21101 -19624
- package/dist/assets/app-BUYipU-h.js.map +1 -0
- package/dist/assets/{app-DFQhKB-Q.css → app-DWlDE8AF.css} +240 -181
- package/dist/assets/{app-loader-d7zgN9hh.js → app-loader-BnRwgIP_.js} +763 -437
- package/dist/assets/app-loader-BnRwgIP_.js.map +1 -0
- package/dist/assets/{app-loader-DczGHPG9.css → app-loader-NDVZu4bS.css} +239 -229
- package/dist/assets/browser-DLDtNgow.js +27224 -0
- package/dist/assets/browser-DLDtNgow.js.map +1 -0
- package/dist/assets/{ccip-C6W2FbjW.js → ccip-LS87QwZy.js} +6 -8
- package/dist/assets/ccip-LS87QwZy.js.map +1 -0
- package/dist/assets/{content-Bm5Tr4Hg.js → content-C_bg7acW.js} +1107 -470
- package/dist/assets/content-C_bg7acW.js.map +1 -0
- package/dist/assets/{index-CXXvva-l.js → index-CLG940Kn.js} +2582 -2923
- package/dist/assets/index-CLG940Kn.js.map +1 -0
- package/dist/assets/index-CNFyJkHA.js +208 -0
- package/dist/assets/index-CNFyJkHA.js.map +1 -0
- package/dist/assets/{index-BhxEM16y.js → index-DzfUrip3.js} +23 -171
- package/dist/assets/index-DzfUrip3.js.map +1 -0
- package/dist/assets/{index-DamVoHkh.js → index-N3PIlRbq.js} +4 -3
- package/dist/assets/index-N3PIlRbq.js.map +1 -0
- package/dist/assets/{main.Cq930vY3.js → main.DbDmc7wl.js} +3 -12
- package/dist/assets/main.DbDmc7wl.js.map +1 -0
- package/dist/assets/reactor-analytics-DOjP79na.js +42 -0
- package/dist/assets/reactor-analytics-DOjP79na.js.map +1 -0
- package/dist/assets/router-GU7qCi_d.js +1585 -0
- package/dist/assets/router-GU7qCi_d.js.map +1 -0
- package/dist/assets/{style-BQHqCxXa.css → style-CdxGKc2g.css} +42 -95
- package/dist/external-packages.js +1 -0
- package/dist/external-packages.js.map +1 -0
- package/dist/hmr.js +1 -0
- package/dist/hmr.js.map +1 -0
- package/dist/index.html +1 -1
- package/dist/service-worker.js +1 -0
- package/dist/service-worker.js.map +1 -0
- package/dist/vite-envs.sh +1 -1
- package/package.json +23 -21
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { jsx, jsxs, Fragment as Fragment$1 } from "react/jsx-runtime";
|
|
2
|
-
import { t as twMerge, B as Button,
|
|
2
|
+
import { t as twMerge, B as Button, aO as mergeClassNameProps, aP as INITIAL_SYNC, aQ as SYNCING, S as SUCCESS, C as CONFLICT, aR as MISSING, x as ERROR, aS as ConnectDropdownMenu, aT as useOnClickOutside, aU as useEventListener, aV as useCopyToClipboard, aW as Select, aX as Provider, aY as Root3, aZ as Trigger, a_ as Portal, a$ as Content2, b0 as validateInitialState, b1 as validateStateSchemaName, b2 as validateModules, b3 as useDocumentDrives, A as useUiNodesContext, b4 as useDriveContext, b5 as FILE$1, F as useUnwrappedReactor, b6 as useConnectDid, b7 as useConnectCrypto, o as useTranslation, G as useModal, b8 as useAtomValue, b9 as themeAtom, ba as useUser, bb as useUserPermissions$1, p as useUiNodes, bc as exportFile, bd as useGetDocumentModelModule, be as addActionContext$1, bf as signOperation$1, e as useDocumentDriveServer, bg as useHotkeys, bh as DriveLayout, bi as DriveContextProvider, bj as SearchBar, N as useAnalyticsStore, bk as useQueryClient, u as useQuery, a3 as AnalyticsPath, bl as useAnalyticsEngine, a4 as DateTime, bm as AnalyticsGranularity, bn as useGetEditor, bo as isSameDocument, n as useNavigate, s as useAsyncReactor, bp as useFilteredDocumentModels, bq as useDriveEditor, br as useDocumentDriveById, z as useParams, q as useDocumentDrives$1, w as toast } from "./app-BUYipU-h.js";
|
|
3
3
|
import * as React from "react";
|
|
4
4
|
import React__default, { useState, useCallback, useMemo, useEffect, Fragment, useRef, useLayoutEffect, memo as memo$1, createElement, useSyncExternalStore, Suspense } from "react";
|
|
5
|
-
import {
|
|
5
|
+
import { $ as Icon, bX as getDimensions, bY as READ, bZ as nodeOptionsMap, b_ as defaultFileOptions, b$ as DUPLICATE, c0 as RENAME, c1 as WRITE, c2 as DELETE, c3 as defaultFolderOptions, c4 as garbageCollect, c5 as sortOperations, c6 as UI_NODE, aQ as DRIVE, aB as FILE, ae as buildSignedOperation, ax as addFolder, at as generateAddNodeAction, ay as isFolderNode, au as isFileNode, az as deleteNode, aA as updateNode, aC as moveNode, aD as generateNodesCopy, aE as copyNode, aq as generateId$1, c7 as undo, c8 as redo, _ as logger, aR as FOLDER, c9 as useDocumentDispatch$1, an as driveDocumentModelModule, ah as connectConfig } from "./app-loader-BnRwgIP_.js";
|
|
6
|
+
import { E as ENSAvatar, a as ErrorBoundary } from "./router-GU7qCi_d.js";
|
|
6
7
|
import { flushSync } from "react-dom";
|
|
7
|
-
import "./main.
|
|
8
|
+
import "./main.DbDmc7wl.js";
|
|
8
9
|
const PaginationButton = ({ active = false, ...props }) => {
|
|
9
10
|
const className = twMerge("h-8 min-w-8 border border-solid border-gray-300 bg-white px-3 py-1 text-xs text-gray-900 hover:bg-gray-100", !active && "border-0");
|
|
10
11
|
return jsx(Button, { color: "light", size: "small", ...mergeClassNameProps(props, className), children: props.children });
|
|
@@ -14,7 +15,7 @@ const Pagination = (props) => {
|
|
|
14
15
|
return jsxs("div", { className: "flex gap-x-1", children: [firstPageLabel ? jsx(PaginationButton, { disabled: !isPreviousPageAvailable, onClick: () => goToFirstPage(), children: firstPageLabel }) : null, previousPageLabel ? jsxs(PaginationButton, { disabled: !isPreviousPageAvailable, onClick: () => goToPreviousPage(), children: [jsx(Icon, { className: "rotate-90", name: "ChevronDown", size: 16 }), previousPageLabel] }) : null, pages.map((page) => jsx(PaginationButton, { active: page.active, onClick: () => goToPage(page.index), children: page.number }, page.index)), hiddenNextPages ? jsx("span", { className: "flex items-center justify-center px-2", children: "..." }) : null, nextPageLabel ? jsxs(PaginationButton, { disabled: !isNextPageAvailable, onClick: () => goToNextPage(), children: [nextPageLabel, jsx(Icon, { className: "-rotate-90", name: "ChevronDown", size: 16 })] }) : null, lastPageLabel ? jsx(PaginationButton, { disabled: !isNextPageAvailable, onClick: () => goToLastPage(), children: lastPageLabel }) : null] });
|
|
15
16
|
};
|
|
16
17
|
function usePagination(items, options) {
|
|
17
|
-
const { itemsPerPage = 20, initialPage = 0, pageRange = 3 } = options
|
|
18
|
+
const { itemsPerPage = 20, initialPage = 0, pageRange = 3 } = options;
|
|
18
19
|
const [currentPage, setCurrentPage] = useState(initialPage);
|
|
19
20
|
const pageCount = Math.ceil(items.length / itemsPerPage);
|
|
20
21
|
const isNextPageAvailable = currentPage < pageCount - 1;
|
|
@@ -151,131 +152,12 @@ function DefaultEditorLoader(props) {
|
|
|
151
152
|
const { message: message2 = "Loading editor", ...divProps } = props;
|
|
152
153
|
return jsx("div", { className: "grid h-full place-items-center", ...divProps, children: jsxs("div", { className: "-mt-20 grid place-items-center", children: [jsx("h3", { className: "mb-4 text-xl", children: message2 }), jsx(AnimatedLoader, {})] }) });
|
|
153
154
|
}
|
|
154
|
-
const DocumentToolbar = (props) => {
|
|
155
|
-
const { undo: undo2, canUndo, redo: redo2, canRedo, title, onClose, onExport, className, onShowRevisionHistory, onSwitchboardLinkClick, onShowTimeline } = props;
|
|
156
|
-
const isUndoDisabled = !canUndo || !undo2;
|
|
157
|
-
const isRedoDisabled = !canRedo || !redo2;
|
|
158
|
-
const isExportDisabled = !onExport;
|
|
159
|
-
const isSwitchboardLinkDisabled = !onSwitchboardLinkClick;
|
|
160
|
-
const isRevisionHistoryDisabled = !onShowRevisionHistory;
|
|
161
|
-
const isTimelineDisabled = !onShowTimeline;
|
|
162
|
-
return jsxs("div", { className: twMerge("flex h-12 w-full items-center justify-between rounded-xl border border-gray-200 bg-slate-50 px-4", className), children: [jsxs("div", { className: "flex items-center gap-x-2", children: [jsx("button", { className: twMerge("grid size-8 place-items-center rounded-lg border border-gray-200 bg-white", isUndoDisabled ? "cursor-not-allowed" : "cursor-pointer active:opacity-70"), onClick: undo2, disabled: isUndoDisabled, children: jsx(Icon, { name: "ArrowCouterclockwise", size: 16, className: isUndoDisabled ? "text-gray-500" : "text-gray-900" }) }), jsx("button", { className: twMerge("grid size-8 place-items-center rounded-lg border border-gray-200 bg-white", isRedoDisabled ? "cursor-not-allowed" : "cursor-pointer active:opacity-70"), onClick: redo2, disabled: isRedoDisabled, children: jsx("div", { className: "-scale-x-100", children: jsx(Icon, { name: "ArrowCouterclockwise", size: 16, className: isRedoDisabled ? "text-gray-500" : "text-gray-900" }) }) }), jsx("button", { className: twMerge("flex h-8 items-center rounded-lg border border-gray-200 bg-white px-3 text-sm", isExportDisabled ? "cursor-not-allowed" : "cursor-pointer active:opacity-70"), onClick: onExport, disabled: isExportDisabled, children: jsx("span", { className: isExportDisabled ? "text-gray-500" : "text-gray-900", children: "Export" }) })] }), jsx("div", { className: "flex items-center", children: jsx("h1", { className: "text-sm font-medium text-gray-500", children: title }) }), jsxs("div", { className: "flex items-center gap-x-2", children: [jsx("button", { className: twMerge("grid size-8 place-items-center rounded-lg border border-gray-200 bg-white", isSwitchboardLinkDisabled ? "cursor-not-allowed" : "cursor-pointer active:opacity-70"), onClick: onSwitchboardLinkClick, disabled: isSwitchboardLinkDisabled, children: jsx(Icon, { name: "Drive", size: 16, className: isSwitchboardLinkDisabled ? "text-gray-500" : "text-gray-900" }) }), jsx("button", { className: twMerge("grid size-8 place-items-center rounded-lg border border-gray-200 bg-white", isRevisionHistoryDisabled ? "cursor-not-allowed" : "cursor-pointer active:opacity-70"), onClick: onShowRevisionHistory, disabled: isRevisionHistoryDisabled, children: jsx(Icon, { name: "History", size: 16, className: isRevisionHistoryDisabled ? "text-gray-500" : "text-gray-900" }) }), jsx("button", { className: twMerge("grid size-8 place-items-center rounded-lg border border-gray-200 bg-white", isTimelineDisabled ? "cursor-not-allowed" : "cursor-pointer active:opacity-70"), onClick: onShowTimeline, disabled: isTimelineDisabled, children: jsx(Icon, { name: "Timeline", size: 16, className: twMerge("text-gray-900", isTimelineDisabled && "opacity-50") }) }), jsx("button", { className: "grid size-8 cursor-pointer place-items-center rounded-lg border border-gray-200 bg-white active:opacity-70", onClick: onClose, children: jsx(Icon, { name: "XmarkLight", size: 16, className: "text-gray-900" }) })] })] });
|
|
163
|
-
};
|
|
164
|
-
const syncIcons = {
|
|
165
|
-
SYNCING: "Syncing",
|
|
166
|
-
SUCCESS: "Synced",
|
|
167
|
-
CONFLICT: "Error",
|
|
168
|
-
MISSING: "Circle",
|
|
169
|
-
ERROR: "Error",
|
|
170
|
-
INITIAL_SYNC: "Syncing"
|
|
171
|
-
};
|
|
172
|
-
function SyncStatusIcon(props) {
|
|
173
|
-
const { syncStatus, className, overrideSyncIcons = {}, ...iconProps } = props;
|
|
174
|
-
const icons = { ...syncIcons, ...overrideSyncIcons };
|
|
175
|
-
const syncStatusIcons = {
|
|
176
|
-
[INITIAL_SYNC]: jsx(Icon, { size: 16, ...iconProps, className: twMerge("text-blue-900", className), name: icons[INITIAL_SYNC] }),
|
|
177
|
-
[SYNCING]: jsx(Icon, { size: 16, ...iconProps, className: twMerge("text-blue-900", className), name: icons[SYNCING] }),
|
|
178
|
-
[SUCCESS]: jsx(Icon, { size: 16, ...iconProps, className: twMerge("text-green-900", className), name: icons[SUCCESS] }),
|
|
179
|
-
[CONFLICT]: jsx(Icon, { size: 16, ...iconProps, className: twMerge("text-orange-900", className), name: icons[CONFLICT] }),
|
|
180
|
-
[MISSING]: jsx(Icon, { size: 16, ...iconProps, className: twMerge("text-red-900", className), name: icons[MISSING] }),
|
|
181
|
-
[ERROR]: jsx(Icon, { size: 16, ...iconProps, className: twMerge("text-red-900", className), name: icons[ERROR] })
|
|
182
|
-
};
|
|
183
|
-
return syncStatusIcons[syncStatus];
|
|
184
|
-
}
|
|
185
|
-
function FileItem(props) {
|
|
186
|
-
const { uiNode, className, customDocumentIconSrc, onSelectNode, onRenameNode, onDuplicateNode, onDeleteNode, isAllowedToCreateDocuments } = props;
|
|
187
|
-
const [mode, setMode] = useState(READ);
|
|
188
|
-
const [isDropdownMenuOpen, setIsDropdownMenuOpen] = useState(false);
|
|
189
|
-
const { dragProps } = useDrag({ uiNode });
|
|
190
|
-
const isReadMode = mode === READ;
|
|
191
|
-
const dropdownMenuHandlers = {
|
|
192
|
-
[DUPLICATE]: () => onDuplicateNode(uiNode),
|
|
193
|
-
[RENAME]: () => setMode(WRITE),
|
|
194
|
-
[DELETE]: () => onDeleteNode(uiNode)
|
|
195
|
-
};
|
|
196
|
-
const dropdownMenuOptions = Object.entries(nodeOptionsMap).map(([id, option]) => ({
|
|
197
|
-
...option,
|
|
198
|
-
id
|
|
199
|
-
})).filter((option) => defaultFileOptions.includes(option.id));
|
|
200
|
-
function onSubmit(name) {
|
|
201
|
-
onRenameNode(name, uiNode);
|
|
202
|
-
setMode(READ);
|
|
203
|
-
}
|
|
204
|
-
function onCancel() {
|
|
205
|
-
setMode(READ);
|
|
206
|
-
}
|
|
207
|
-
function onClick() {
|
|
208
|
-
onSelectNode(uiNode);
|
|
209
|
-
}
|
|
210
|
-
function onDropdownMenuOptionClick(itemId) {
|
|
211
|
-
const handler = dropdownMenuHandlers[itemId];
|
|
212
|
-
if (!handler) {
|
|
213
|
-
console.error(`No handler found for dropdown menu item: ${itemId}`);
|
|
214
|
-
return;
|
|
215
|
-
}
|
|
216
|
-
handler();
|
|
217
|
-
setIsDropdownMenuOpen(false);
|
|
218
|
-
}
|
|
219
|
-
const iconSrc = getDocumentIconSrc(uiNode.documentType, customDocumentIconSrc);
|
|
220
|
-
const iconNode = jsxs("div", { className: "relative", children: [jsx("img", { alt: "file icon", className: "max-w-none", height: 34, src: iconSrc, width: 32 }), isReadMode && uiNode.syncStatus && jsx("div", { className: "absolute bottom-[-2px] right-0 size-3 rounded-full bg-white", children: jsx("div", { className: "absolute left-[-2px] top-[-2px]", children: jsx(SyncStatusIcon, { overrideSyncIcons: { SUCCESS: "CheckCircleFill" }, syncStatus: uiNode.syncStatus }) }) })] });
|
|
221
|
-
const containerStyles = twMerge("group flex h-12 cursor-pointer select-none items-center rounded-lg bg-gray-200 px-2 text-gray-600 hover:text-gray-800", className);
|
|
222
|
-
const content = isReadMode ? jsxs("div", { className: "flex w-52 items-center justify-between", children: [jsxs("div", { className: "mr-2 truncate group-hover:mr-0", children: [jsx("div", { className: "max-h-6 truncate text-sm font-medium group-hover:text-gray-800", children: uiNode.name }), jsx("div", { className: "max-h-6 truncate text-xs font-medium text-gray-600 group-hover:text-gray-800", children: uiNode.documentType })] }), isAllowedToCreateDocuments ? jsx(ConnectDropdownMenu, { items: dropdownMenuOptions, onItemClick: onDropdownMenuOptionClick, onOpenChange: setIsDropdownMenuOpen, open: isDropdownMenuOpen, children: jsx("button", { className: twMerge("hidden group-hover:block", isDropdownMenuOpen && "block"), onClick: (e) => {
|
|
223
|
-
e.stopPropagation();
|
|
224
|
-
setIsDropdownMenuOpen(true);
|
|
225
|
-
}, children: jsx(Icon, { className: "text-gray-600", name: "VerticalDots" }) }) }) : null] }) : jsx(NodeInput, { className: "ml-3 flex-1 font-medium", defaultValue: uiNode.name, onCancel, onSubmit });
|
|
226
|
-
return jsx("div", { className: "relative w-64", onClick, children: jsx("div", { ...dragProps, className: containerStyles, children: jsxs("div", { className: "flex items-center", children: [jsx("div", { className: "mr-1.5", children: iconNode }), content] }) }) });
|
|
227
|
-
}
|
|
228
|
-
function FolderItem(props) {
|
|
229
|
-
const { uiNode, isAllowedToCreateDocuments, className, onRenameNode, onDuplicateNode, onDeleteNode, onSelectNode, onAddFile, onCopyNode, onMoveNode } = props;
|
|
230
|
-
const [mode, setMode] = useState(READ);
|
|
231
|
-
const [isDropdownMenuOpen, setIsDropdownMenuOpen] = useState(false);
|
|
232
|
-
const { dragProps } = useDrag({ ...props, uiNode });
|
|
233
|
-
const { isDropTarget, dropProps } = useDrop({
|
|
234
|
-
uiNode,
|
|
235
|
-
onAddFile,
|
|
236
|
-
onCopyNode,
|
|
237
|
-
onMoveNode
|
|
238
|
-
});
|
|
239
|
-
const isReadMode = mode === READ;
|
|
240
|
-
function onCancel() {
|
|
241
|
-
setMode(READ);
|
|
242
|
-
}
|
|
243
|
-
function onSubmit(name) {
|
|
244
|
-
onRenameNode(name, uiNode);
|
|
245
|
-
setMode(READ);
|
|
246
|
-
}
|
|
247
|
-
function onClick() {
|
|
248
|
-
onSelectNode(uiNode);
|
|
249
|
-
}
|
|
250
|
-
const dropdownMenuHandlers = {
|
|
251
|
-
[DUPLICATE]: () => onDuplicateNode(uiNode),
|
|
252
|
-
[RENAME]: () => setMode(WRITE),
|
|
253
|
-
[DELETE]: () => onDeleteNode(uiNode)
|
|
254
|
-
};
|
|
255
|
-
const dropdownMenuOptions = Object.entries(nodeOptionsMap).map(([id, option]) => ({
|
|
256
|
-
...option,
|
|
257
|
-
id
|
|
258
|
-
})).filter((option) => defaultFolderOptions.includes(option.id));
|
|
259
|
-
function onDropdownMenuOptionClick(itemId) {
|
|
260
|
-
const handler = dropdownMenuHandlers[itemId];
|
|
261
|
-
if (!handler) {
|
|
262
|
-
console.error(`No handler found for dropdown menu item: ${itemId}`);
|
|
263
|
-
return;
|
|
264
|
-
}
|
|
265
|
-
handler();
|
|
266
|
-
setIsDropdownMenuOpen(false);
|
|
267
|
-
}
|
|
268
|
-
const content = isReadMode || !isAllowedToCreateDocuments ? jsx("div", { className: "ml-3 max-h-6 truncate font-medium text-gray-600 group-hover:text-gray-800", children: uiNode.name }) : jsx(NodeInput, { className: "ml-3 font-medium", defaultValue: uiNode.name, onCancel, onSubmit });
|
|
269
|
-
const containerStyles = twMerge("group flex h-12 cursor-pointer select-none items-center rounded-lg bg-gray-200 px-2", className, isDropTarget && "bg-blue-100");
|
|
270
|
-
return jsx("div", { className: "relative w-64", onClick, children: jsxs("div", { ...dragProps, ...dropProps, className: containerStyles, children: [jsxs("div", { className: "flex items-center overflow-hidden", children: [jsx("div", { className: "p-1", children: jsxs("div", { className: "relative", children: [jsx(Icon, { name: "FolderClose", size: 24 }), isReadMode && uiNode.syncStatus ? jsx("div", { className: "absolute bottom-[-3px] right-[-2px] size-3 rounded-full bg-white", children: jsx("div", { className: "absolute left-[-2px] top-[-2px]", children: jsx(SyncStatusIcon, { overrideSyncIcons: {
|
|
271
|
-
SUCCESS: "CheckCircleFill"
|
|
272
|
-
}, syncStatus: uiNode.syncStatus }) }) }) : null] }) }), content] }), isReadMode && isAllowedToCreateDocuments ? jsx(ConnectDropdownMenu, { items: dropdownMenuOptions, onItemClick: onDropdownMenuOptionClick, onOpenChange: setIsDropdownMenuOpen, open: isDropdownMenuOpen, children: jsx("button", { className: twMerge("ml-auto hidden group-hover:block", isDropdownMenuOpen && "block"), onClick: (e) => {
|
|
273
|
-
e.stopPropagation();
|
|
274
|
-
setIsDropdownMenuOpen(true);
|
|
275
|
-
}, children: jsx(Icon, { className: "text-gray-600", name: "VerticalDots" }) }) }) : null] }) });
|
|
276
|
-
}
|
|
277
155
|
const millisecondsInWeek = 6048e5;
|
|
278
156
|
const millisecondsInDay = 864e5;
|
|
157
|
+
const millisecondsInMinute = 6e4;
|
|
158
|
+
const millisecondsInHour = 36e5;
|
|
159
|
+
const minutesInMonth = 43200;
|
|
160
|
+
const minutesInDay = 1440;
|
|
279
161
|
const constructFromSymbol = Symbol.for("constructDateFrom");
|
|
280
162
|
function constructFrom(date, value) {
|
|
281
163
|
if (typeof date === "function") return date(value);
|
|
@@ -343,7 +225,7 @@ function getTimezoneOffsetInMilliseconds(date) {
|
|
|
343
225
|
function normalizeDates(context, ...dates) {
|
|
344
226
|
const normalize = constructFrom.bind(
|
|
345
227
|
null,
|
|
346
|
-
dates.find((date) => typeof date === "object")
|
|
228
|
+
context || dates.find((date) => typeof date === "object")
|
|
347
229
|
);
|
|
348
230
|
return dates.map(normalize);
|
|
349
231
|
}
|
|
@@ -371,12 +253,83 @@ function startOfISOWeekYear(date, options) {
|
|
|
371
253
|
fourthOfJanuary.setHours(0, 0, 0, 0);
|
|
372
254
|
return startOfISOWeek(fourthOfJanuary);
|
|
373
255
|
}
|
|
256
|
+
function compareAsc(dateLeft, dateRight) {
|
|
257
|
+
const diff = +toDate(dateLeft) - +toDate(dateRight);
|
|
258
|
+
if (diff < 0) return -1;
|
|
259
|
+
else if (diff > 0) return 1;
|
|
260
|
+
return diff;
|
|
261
|
+
}
|
|
262
|
+
function constructNow(date) {
|
|
263
|
+
return constructFrom(date, Date.now());
|
|
264
|
+
}
|
|
374
265
|
function isDate(value) {
|
|
375
266
|
return value instanceof Date || typeof value === "object" && Object.prototype.toString.call(value) === "[object Date]";
|
|
376
267
|
}
|
|
377
268
|
function isValid(date) {
|
|
378
269
|
return !(!isDate(date) && typeof date !== "number" || isNaN(+toDate(date)));
|
|
379
270
|
}
|
|
271
|
+
function differenceInCalendarMonths(laterDate, earlierDate, options) {
|
|
272
|
+
const [laterDate_, earlierDate_] = normalizeDates(
|
|
273
|
+
options == null ? void 0 : options.in,
|
|
274
|
+
laterDate,
|
|
275
|
+
earlierDate
|
|
276
|
+
);
|
|
277
|
+
const yearsDiff = laterDate_.getFullYear() - earlierDate_.getFullYear();
|
|
278
|
+
const monthsDiff = laterDate_.getMonth() - earlierDate_.getMonth();
|
|
279
|
+
return yearsDiff * 12 + monthsDiff;
|
|
280
|
+
}
|
|
281
|
+
function getRoundingMethod(method) {
|
|
282
|
+
return (number) => {
|
|
283
|
+
const round = method ? Math[method] : Math.trunc;
|
|
284
|
+
const result = round(number);
|
|
285
|
+
return result === 0 ? 0 : result;
|
|
286
|
+
};
|
|
287
|
+
}
|
|
288
|
+
function differenceInMilliseconds(laterDate, earlierDate) {
|
|
289
|
+
return +toDate(laterDate) - +toDate(earlierDate);
|
|
290
|
+
}
|
|
291
|
+
function endOfDay(date, options) {
|
|
292
|
+
const _date = toDate(date, options == null ? void 0 : options.in);
|
|
293
|
+
_date.setHours(23, 59, 59, 999);
|
|
294
|
+
return _date;
|
|
295
|
+
}
|
|
296
|
+
function endOfMonth(date, options) {
|
|
297
|
+
const _date = toDate(date, options == null ? void 0 : options.in);
|
|
298
|
+
const month = _date.getMonth();
|
|
299
|
+
_date.setFullYear(_date.getFullYear(), month + 1, 0);
|
|
300
|
+
_date.setHours(23, 59, 59, 999);
|
|
301
|
+
return _date;
|
|
302
|
+
}
|
|
303
|
+
function isLastDayOfMonth(date, options) {
|
|
304
|
+
const _date = toDate(date, options == null ? void 0 : options.in);
|
|
305
|
+
return +endOfDay(_date, options) === +endOfMonth(_date, options);
|
|
306
|
+
}
|
|
307
|
+
function differenceInMonths(laterDate, earlierDate, options) {
|
|
308
|
+
const [laterDate_, workingLaterDate, earlierDate_] = normalizeDates(
|
|
309
|
+
options == null ? void 0 : options.in,
|
|
310
|
+
laterDate,
|
|
311
|
+
laterDate,
|
|
312
|
+
earlierDate
|
|
313
|
+
);
|
|
314
|
+
const sign = compareAsc(workingLaterDate, earlierDate_);
|
|
315
|
+
const difference = Math.abs(
|
|
316
|
+
differenceInCalendarMonths(workingLaterDate, earlierDate_)
|
|
317
|
+
);
|
|
318
|
+
if (difference < 1) return 0;
|
|
319
|
+
if (workingLaterDate.getMonth() === 1 && workingLaterDate.getDate() > 27)
|
|
320
|
+
workingLaterDate.setDate(30);
|
|
321
|
+
workingLaterDate.setMonth(workingLaterDate.getMonth() - sign * difference);
|
|
322
|
+
let isLastMonthNotFull = compareAsc(workingLaterDate, earlierDate_) === -sign;
|
|
323
|
+
if (isLastDayOfMonth(laterDate_) && difference === 1 && compareAsc(laterDate_, earlierDate_) === 1) {
|
|
324
|
+
isLastMonthNotFull = false;
|
|
325
|
+
}
|
|
326
|
+
const result = sign * (difference - +isLastMonthNotFull);
|
|
327
|
+
return result === 0 ? 0 : result;
|
|
328
|
+
}
|
|
329
|
+
function differenceInSeconds(laterDate, earlierDate, options) {
|
|
330
|
+
const diff = differenceInMilliseconds(laterDate, earlierDate) / 1e3;
|
|
331
|
+
return getRoundingMethod(options == null ? void 0 : options.roundingMethod)(diff);
|
|
332
|
+
}
|
|
380
333
|
function startOfYear(date, options) {
|
|
381
334
|
const date_ = toDate(date, options == null ? void 0 : options.in);
|
|
382
335
|
date_.setFullYear(date_.getFullYear(), 0, 1);
|
|
@@ -446,7 +399,7 @@ const formatDistanceLocale = {
|
|
|
446
399
|
other: "almost {{count}} years"
|
|
447
400
|
}
|
|
448
401
|
};
|
|
449
|
-
const formatDistance = (token, count, options) => {
|
|
402
|
+
const formatDistance$1 = (token, count, options) => {
|
|
450
403
|
let result;
|
|
451
404
|
const tokenValue = formatDistanceLocale[token];
|
|
452
405
|
if (typeof tokenValue === "string") {
|
|
@@ -862,7 +815,7 @@ const match = {
|
|
|
862
815
|
};
|
|
863
816
|
const enUS = {
|
|
864
817
|
code: "en-US",
|
|
865
|
-
formatDistance,
|
|
818
|
+
formatDistance: formatDistance$1,
|
|
866
819
|
formatLong,
|
|
867
820
|
formatRelative,
|
|
868
821
|
localize,
|
|
@@ -985,6 +938,8 @@ const lightFormatters = {
|
|
|
985
938
|
}
|
|
986
939
|
};
|
|
987
940
|
const dayPeriodEnum = {
|
|
941
|
+
am: "am",
|
|
942
|
+
pm: "pm",
|
|
988
943
|
midnight: "midnight",
|
|
989
944
|
noon: "noon",
|
|
990
945
|
morning: "morning",
|
|
@@ -1764,76 +1719,575 @@ function cleanEscapedString(input) {
|
|
|
1764
1719
|
}
|
|
1765
1720
|
return matched[1].replace(doubleQuoteRegExp, "'");
|
|
1766
1721
|
}
|
|
1767
|
-
function
|
|
1768
|
-
const
|
|
1769
|
-
const
|
|
1770
|
-
const
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1722
|
+
function formatDistance(laterDate, earlierDate, options) {
|
|
1723
|
+
const defaultOptions2 = getDefaultOptions();
|
|
1724
|
+
const locale = (options == null ? void 0 : options.locale) ?? defaultOptions2.locale ?? enUS;
|
|
1725
|
+
const minutesInAlmostTwoDays = 2520;
|
|
1726
|
+
const comparison = compareAsc(laterDate, earlierDate);
|
|
1727
|
+
if (isNaN(comparison)) throw new RangeError("Invalid time value");
|
|
1728
|
+
const localizeOptions = Object.assign({}, options, {
|
|
1729
|
+
addSuffix: options == null ? void 0 : options.addSuffix,
|
|
1730
|
+
comparison
|
|
1731
|
+
});
|
|
1732
|
+
const [laterDate_, earlierDate_] = normalizeDates(
|
|
1733
|
+
options == null ? void 0 : options.in,
|
|
1734
|
+
...comparison > 0 ? [earlierDate, laterDate] : [laterDate, earlierDate]
|
|
1735
|
+
);
|
|
1736
|
+
const seconds = differenceInSeconds(earlierDate_, laterDate_);
|
|
1737
|
+
const offsetInSeconds = (getTimezoneOffsetInMilliseconds(earlierDate_) - getTimezoneOffsetInMilliseconds(laterDate_)) / 1e3;
|
|
1738
|
+
const minutes = Math.round((seconds - offsetInSeconds) / 60);
|
|
1739
|
+
let months;
|
|
1740
|
+
if (minutes < 2) {
|
|
1741
|
+
if (options == null ? void 0 : options.includeSeconds) {
|
|
1742
|
+
if (seconds < 5) {
|
|
1743
|
+
return locale.formatDistance("lessThanXSeconds", 5, localizeOptions);
|
|
1744
|
+
} else if (seconds < 10) {
|
|
1745
|
+
return locale.formatDistance("lessThanXSeconds", 10, localizeOptions);
|
|
1746
|
+
} else if (seconds < 20) {
|
|
1747
|
+
return locale.formatDistance("lessThanXSeconds", 20, localizeOptions);
|
|
1748
|
+
} else if (seconds < 40) {
|
|
1749
|
+
return locale.formatDistance("halfAMinute", 0, localizeOptions);
|
|
1750
|
+
} else if (seconds < 60) {
|
|
1751
|
+
return locale.formatDistance("lessThanXMinutes", 1, localizeOptions);
|
|
1752
|
+
} else {
|
|
1753
|
+
return locale.formatDistance("xMinutes", 1, localizeOptions);
|
|
1754
|
+
}
|
|
1755
|
+
} else {
|
|
1756
|
+
if (minutes === 0) {
|
|
1757
|
+
return locale.formatDistance("lessThanXMinutes", 1, localizeOptions);
|
|
1758
|
+
} else {
|
|
1759
|
+
return locale.formatDistance("xMinutes", minutes, localizeOptions);
|
|
1760
|
+
}
|
|
1775
1761
|
}
|
|
1776
|
-
|
|
1777
|
-
|
|
1762
|
+
} else if (minutes < 45) {
|
|
1763
|
+
return locale.formatDistance("xMinutes", minutes, localizeOptions);
|
|
1764
|
+
} else if (minutes < 90) {
|
|
1765
|
+
return locale.formatDistance("aboutXHours", 1, localizeOptions);
|
|
1766
|
+
} else if (minutes < minutesInDay) {
|
|
1767
|
+
const hours = Math.round(minutes / 60);
|
|
1768
|
+
return locale.formatDistance("aboutXHours", hours, localizeOptions);
|
|
1769
|
+
} else if (minutes < minutesInAlmostTwoDays) {
|
|
1770
|
+
return locale.formatDistance("xDays", 1, localizeOptions);
|
|
1771
|
+
} else if (minutes < minutesInMonth) {
|
|
1772
|
+
const days = Math.round(minutes / minutesInDay);
|
|
1773
|
+
return locale.formatDistance("xDays", days, localizeOptions);
|
|
1774
|
+
} else if (minutes < minutesInMonth * 2) {
|
|
1775
|
+
months = Math.round(minutes / minutesInMonth);
|
|
1776
|
+
return locale.formatDistance("aboutXMonths", months, localizeOptions);
|
|
1777
|
+
}
|
|
1778
|
+
months = differenceInMonths(earlierDate_, laterDate_);
|
|
1779
|
+
if (months < 12) {
|
|
1780
|
+
const nearestMonth = Math.round(minutes / minutesInMonth);
|
|
1781
|
+
return locale.formatDistance("xMonths", nearestMonth, localizeOptions);
|
|
1782
|
+
} else {
|
|
1783
|
+
const monthsSinceStartOfYear = months % 12;
|
|
1784
|
+
const years = Math.trunc(months / 12);
|
|
1785
|
+
if (monthsSinceStartOfYear < 3) {
|
|
1786
|
+
return locale.formatDistance("aboutXYears", years, localizeOptions);
|
|
1787
|
+
} else if (monthsSinceStartOfYear < 9) {
|
|
1788
|
+
return locale.formatDistance("overXYears", years, localizeOptions);
|
|
1789
|
+
} else {
|
|
1790
|
+
return locale.formatDistance("almostXYears", years + 1, localizeOptions);
|
|
1778
1791
|
}
|
|
1779
|
-
}
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1792
|
+
}
|
|
1793
|
+
}
|
|
1794
|
+
function formatDistanceToNow(date, options) {
|
|
1795
|
+
return formatDistance(date, constructNow(date), options);
|
|
1796
|
+
}
|
|
1797
|
+
function parseISO(argument, options) {
|
|
1798
|
+
const invalidDate = () => constructFrom(options == null ? void 0 : options.in, NaN);
|
|
1799
|
+
const additionalDigits = 2;
|
|
1800
|
+
const dateStrings = splitDateString(argument);
|
|
1801
|
+
let date;
|
|
1802
|
+
if (dateStrings.date) {
|
|
1803
|
+
const parseYearResult = parseYear(dateStrings.date, additionalDigits);
|
|
1804
|
+
date = parseDate(parseYearResult.restDateString, parseYearResult.year);
|
|
1805
|
+
}
|
|
1806
|
+
if (!date || isNaN(+date)) return invalidDate();
|
|
1807
|
+
const timestamp = +date;
|
|
1808
|
+
let time = 0;
|
|
1809
|
+
let offset;
|
|
1810
|
+
if (dateStrings.time) {
|
|
1811
|
+
time = parseTime(dateStrings.time);
|
|
1812
|
+
if (isNaN(time)) return invalidDate();
|
|
1813
|
+
}
|
|
1814
|
+
if (dateStrings.timezone) {
|
|
1815
|
+
offset = parseTimezone(dateStrings.timezone);
|
|
1816
|
+
if (isNaN(offset)) return invalidDate();
|
|
1817
|
+
} else {
|
|
1818
|
+
const tmpDate = new Date(timestamp + time);
|
|
1819
|
+
const result = toDate(0, options == null ? void 0 : options.in);
|
|
1820
|
+
result.setFullYear(
|
|
1821
|
+
tmpDate.getUTCFullYear(),
|
|
1822
|
+
tmpDate.getUTCMonth(),
|
|
1823
|
+
tmpDate.getUTCDate()
|
|
1824
|
+
);
|
|
1825
|
+
result.setHours(
|
|
1826
|
+
tmpDate.getUTCHours(),
|
|
1827
|
+
tmpDate.getUTCMinutes(),
|
|
1828
|
+
tmpDate.getUTCSeconds(),
|
|
1829
|
+
tmpDate.getUTCMilliseconds()
|
|
1830
|
+
);
|
|
1831
|
+
return result;
|
|
1832
|
+
}
|
|
1833
|
+
return toDate(timestamp + time + offset, options == null ? void 0 : options.in);
|
|
1834
|
+
}
|
|
1835
|
+
const patterns = {
|
|
1836
|
+
dateTimeDelimiter: /[T ]/,
|
|
1837
|
+
timeZoneDelimiter: /[Z ]/i,
|
|
1838
|
+
timezone: /([Z+-].*)$/
|
|
1839
|
+
};
|
|
1840
|
+
const dateRegex = /^-?(?:(\d{3})|(\d{2})(?:-?(\d{2}))?|W(\d{2})(?:-?(\d{1}))?|)$/;
|
|
1841
|
+
const timeRegex = /^(\d{2}(?:[.,]\d*)?)(?::?(\d{2}(?:[.,]\d*)?))?(?::?(\d{2}(?:[.,]\d*)?))?$/;
|
|
1842
|
+
const timezoneRegex = /^([+-])(\d{2})(?::?(\d{2}))?$/;
|
|
1843
|
+
function splitDateString(dateString) {
|
|
1844
|
+
const dateStrings = {};
|
|
1845
|
+
const array = dateString.split(patterns.dateTimeDelimiter);
|
|
1846
|
+
let timeString;
|
|
1847
|
+
if (array.length > 2) {
|
|
1848
|
+
return dateStrings;
|
|
1849
|
+
}
|
|
1850
|
+
if (/:/.test(array[0])) {
|
|
1851
|
+
timeString = array[0];
|
|
1852
|
+
} else {
|
|
1853
|
+
dateStrings.date = array[0];
|
|
1854
|
+
timeString = array[1];
|
|
1855
|
+
if (patterns.timeZoneDelimiter.test(dateStrings.date)) {
|
|
1856
|
+
dateStrings.date = dateString.split(patterns.timeZoneDelimiter)[0];
|
|
1857
|
+
timeString = dateString.substr(
|
|
1858
|
+
dateStrings.date.length,
|
|
1859
|
+
dateString.length
|
|
1860
|
+
);
|
|
1791
1861
|
}
|
|
1792
1862
|
}
|
|
1793
|
-
|
|
1863
|
+
if (timeString) {
|
|
1864
|
+
const token = patterns.timezone.exec(timeString);
|
|
1865
|
+
if (token) {
|
|
1866
|
+
dateStrings.time = timeString.replace(token[1], "");
|
|
1867
|
+
dateStrings.timezone = token[1];
|
|
1868
|
+
} else {
|
|
1869
|
+
dateStrings.time = timeString;
|
|
1870
|
+
}
|
|
1871
|
+
}
|
|
1872
|
+
return dateStrings;
|
|
1794
1873
|
}
|
|
1795
|
-
function
|
|
1796
|
-
const
|
|
1797
|
-
|
|
1874
|
+
function parseYear(dateString, additionalDigits) {
|
|
1875
|
+
const regex = new RegExp(
|
|
1876
|
+
"^(?:(\\d{4}|[+-]\\d{" + (4 + additionalDigits) + "})|(\\d{2}|[+-]\\d{" + (2 + additionalDigits) + "})$)"
|
|
1877
|
+
);
|
|
1878
|
+
const captures = dateString.match(regex);
|
|
1879
|
+
if (!captures) return { year: NaN, restDateString: "" };
|
|
1880
|
+
const year = captures[1] ? parseInt(captures[1]) : null;
|
|
1881
|
+
const century = captures[2] ? parseInt(captures[2]) : null;
|
|
1882
|
+
return {
|
|
1883
|
+
year: century === null ? year : century * 100,
|
|
1884
|
+
restDateString: dateString.slice((captures[1] || captures[2]).length)
|
|
1885
|
+
};
|
|
1798
1886
|
}
|
|
1799
|
-
function
|
|
1800
|
-
|
|
1801
|
-
const
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1887
|
+
function parseDate(dateString, year) {
|
|
1888
|
+
if (year === null) return /* @__PURE__ */ new Date(NaN);
|
|
1889
|
+
const captures = dateString.match(dateRegex);
|
|
1890
|
+
if (!captures) return /* @__PURE__ */ new Date(NaN);
|
|
1891
|
+
const isWeekDate = !!captures[4];
|
|
1892
|
+
const dayOfYear = parseDateUnit(captures[1]);
|
|
1893
|
+
const month = parseDateUnit(captures[2]) - 1;
|
|
1894
|
+
const day = parseDateUnit(captures[3]);
|
|
1895
|
+
const week = parseDateUnit(captures[4]);
|
|
1896
|
+
const dayOfWeek = parseDateUnit(captures[5]) - 1;
|
|
1897
|
+
if (isWeekDate) {
|
|
1898
|
+
if (!validateWeekDate(year, week, dayOfWeek)) {
|
|
1899
|
+
return /* @__PURE__ */ new Date(NaN);
|
|
1900
|
+
}
|
|
1901
|
+
return dayOfISOWeekYear(year, week, dayOfWeek);
|
|
1902
|
+
} else {
|
|
1903
|
+
const date = /* @__PURE__ */ new Date(0);
|
|
1904
|
+
if (!validateDate(year, month, day) || !validateDayOfYearDate(year, dayOfYear)) {
|
|
1905
|
+
return /* @__PURE__ */ new Date(NaN);
|
|
1906
|
+
}
|
|
1907
|
+
date.setUTCFullYear(year, month, Math.max(dayOfYear, day));
|
|
1908
|
+
return date;
|
|
1808
1909
|
}
|
|
1809
|
-
return jsxs("button", { className: "flex h-8 items-center gap-1 rounded-lg bg-slate-50 pl-1 pr-2 text-xs text-slate-100", onClick: handleCopy(docId), children: [jsx(Icon, { name: "Link" }), "DOC ID", jsx("span", { className: "text-gray-900", children: docId })] });
|
|
1810
1910
|
}
|
|
1811
|
-
function
|
|
1812
|
-
|
|
1813
|
-
const items = [
|
|
1814
|
-
{ displayValue: "Global scope", value: "global" },
|
|
1815
|
-
{ displayValue: "Local scope", value: "local" }
|
|
1816
|
-
];
|
|
1817
|
-
return jsx(Select, { absolutePositionMenu: true, containerClassName: "bg-slate-50 text-gray-500 rounded-lg w-fit text-xs z-10", id: "scope select", itemClassName: "py-2 text-gray-500 grid grid-cols-[auto,auto] gap-1", items, menuClassName: "min-w-0 text-gray-500", onChange, value });
|
|
1911
|
+
function parseDateUnit(value) {
|
|
1912
|
+
return value ? parseInt(value) : 1;
|
|
1818
1913
|
}
|
|
1819
|
-
function
|
|
1820
|
-
const
|
|
1821
|
-
|
|
1914
|
+
function parseTime(timeString) {
|
|
1915
|
+
const captures = timeString.match(timeRegex);
|
|
1916
|
+
if (!captures) return NaN;
|
|
1917
|
+
const hours = parseTimeUnit(captures[1]);
|
|
1918
|
+
const minutes = parseTimeUnit(captures[2]);
|
|
1919
|
+
const seconds = parseTimeUnit(captures[3]);
|
|
1920
|
+
if (!validateTime(hours, minutes, seconds)) {
|
|
1921
|
+
return NaN;
|
|
1922
|
+
}
|
|
1923
|
+
return hours * millisecondsInHour + minutes * millisecondsInMinute + seconds * 1e3;
|
|
1822
1924
|
}
|
|
1823
|
-
function
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
1925
|
+
function parseTimeUnit(value) {
|
|
1926
|
+
return value && parseFloat(value.replace(",", ".")) || 0;
|
|
1927
|
+
}
|
|
1928
|
+
function parseTimezone(timezoneString) {
|
|
1929
|
+
if (timezoneString === "Z") return 0;
|
|
1930
|
+
const captures = timezoneString.match(timezoneRegex);
|
|
1931
|
+
if (!captures) return 0;
|
|
1932
|
+
const sign = captures[1] === "+" ? -1 : 1;
|
|
1933
|
+
const hours = parseInt(captures[2]);
|
|
1934
|
+
const minutes = captures[3] && parseInt(captures[3]) || 0;
|
|
1935
|
+
if (!validateTimezone(hours, minutes)) {
|
|
1936
|
+
return NaN;
|
|
1937
|
+
}
|
|
1938
|
+
return sign * (hours * millisecondsInHour + minutes * millisecondsInMinute);
|
|
1939
|
+
}
|
|
1940
|
+
function dayOfISOWeekYear(isoWeekYear, week, day) {
|
|
1941
|
+
const date = /* @__PURE__ */ new Date(0);
|
|
1942
|
+
date.setUTCFullYear(isoWeekYear, 0, 4);
|
|
1943
|
+
const fourthOfJanuaryDay = date.getUTCDay() || 7;
|
|
1944
|
+
const diff = (week - 1) * 7 + day + 1 - fourthOfJanuaryDay;
|
|
1945
|
+
date.setUTCDate(date.getUTCDate() + diff);
|
|
1946
|
+
return date;
|
|
1947
|
+
}
|
|
1948
|
+
const daysInMonths = [31, null, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
|
|
1949
|
+
function isLeapYearIndex(year) {
|
|
1950
|
+
return year % 400 === 0 || year % 4 === 0 && year % 100 !== 0;
|
|
1951
|
+
}
|
|
1952
|
+
function validateDate(year, month, date) {
|
|
1953
|
+
return month >= 0 && month <= 11 && date >= 1 && date <= (daysInMonths[month] || (isLeapYearIndex(year) ? 29 : 28));
|
|
1954
|
+
}
|
|
1955
|
+
function validateDayOfYearDate(year, dayOfYear) {
|
|
1956
|
+
return dayOfYear >= 1 && dayOfYear <= (isLeapYearIndex(year) ? 366 : 365);
|
|
1957
|
+
}
|
|
1958
|
+
function validateWeekDate(_year, week, day) {
|
|
1959
|
+
return week >= 1 && week <= 53 && day >= 0 && day <= 6;
|
|
1960
|
+
}
|
|
1961
|
+
function validateTime(hours, minutes, seconds) {
|
|
1962
|
+
if (hours === 24) {
|
|
1963
|
+
return minutes === 0 && seconds === 0;
|
|
1964
|
+
}
|
|
1965
|
+
return seconds >= 0 && seconds < 60 && minutes >= 0 && minutes < 60 && hours >= 0 && hours < 25;
|
|
1966
|
+
}
|
|
1967
|
+
function validateTimezone(_hours, minutes) {
|
|
1968
|
+
return minutes >= 0 && minutes <= 59;
|
|
1969
|
+
}
|
|
1970
|
+
const HDivider = (props) => {
|
|
1971
|
+
const { className, timestamp, title, subtitle, onClick, isSelected = false } = props;
|
|
1972
|
+
const [open, setOpen] = useState(false);
|
|
1973
|
+
const hasContent = !!title || !!subtitle || !!timestamp;
|
|
1974
|
+
useEffect(() => {
|
|
1975
|
+
if (open) {
|
|
1976
|
+
setOpen(false);
|
|
1977
|
+
setTimeout(() => hasContent && setOpen(true), 50);
|
|
1834
1978
|
}
|
|
1835
|
-
|
|
1836
|
-
|
|
1979
|
+
}, [title, subtitle, timestamp, hasContent]);
|
|
1980
|
+
const formatTimestamp2 = (isoString) => {
|
|
1981
|
+
if (!isoString)
|
|
1982
|
+
return "";
|
|
1983
|
+
try {
|
|
1984
|
+
return formatDistanceToNow(new Date(isoString), { addSuffix: true });
|
|
1985
|
+
} catch {
|
|
1986
|
+
return isoString;
|
|
1987
|
+
}
|
|
1988
|
+
};
|
|
1989
|
+
const tooltipContent = jsxs("div", { className: "flex flex-col text-xs", children: [!!title && jsx("div", { children: title }), !!subtitle && jsx("div", { className: "text-gray-300", children: subtitle }), !!timestamp && jsx("div", { children: formatTimestamp2(timestamp) })] });
|
|
1990
|
+
const handleMouseEnter = () => {
|
|
1991
|
+
if (hasContent) {
|
|
1992
|
+
setOpen(true);
|
|
1993
|
+
}
|
|
1994
|
+
};
|
|
1995
|
+
const handleMouseLeave = () => {
|
|
1996
|
+
setOpen(false);
|
|
1997
|
+
};
|
|
1998
|
+
return jsxs("div", { className: "relative", onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave, children: [isSelected && jsx(Icon, { name: "TimelineCaret", color: "#4EA9FF", size: 10, className: "absolute top-[-11px] z-40" }), jsx(Tooltip, { className: "rounded-md bg-gray-900 text-white", content: tooltipContent, open: open && hasContent, onOpenChange: setOpen, delayDuration: 0, side: "bottom", sideOffset: 5, children: jsx("div", { className: twMerge("mx-0.5 flex h-[25px] w-1.5 cursor-pointer flex-col items-center justify-center rounded-[2px] hover:bg-blue-300", isSelected && "bg-blue-300", className), onClick, "data-title": title, "data-subtitle": subtitle, "data-timestamp": timestamp, children: jsx("div", { className: "h-0.5 w-1 rounded-full bg-gray-500" }) }) })] });
|
|
1999
|
+
};
|
|
2000
|
+
const getBarHeight = (size = 0) => {
|
|
2001
|
+
switch (true) {
|
|
2002
|
+
case size <= 0:
|
|
2003
|
+
return "h-[1px]";
|
|
2004
|
+
case size === 1:
|
|
2005
|
+
return "h-[3px]";
|
|
2006
|
+
case size === 2:
|
|
2007
|
+
return "h-[6px]";
|
|
2008
|
+
case size === 3:
|
|
2009
|
+
return "h-[9px]";
|
|
2010
|
+
case size >= 4:
|
|
2011
|
+
return "h-[12px]";
|
|
2012
|
+
default:
|
|
2013
|
+
return "h-[1px]";
|
|
2014
|
+
}
|
|
2015
|
+
};
|
|
2016
|
+
const formatTimestamp = (isoString) => {
|
|
2017
|
+
if (!isoString)
|
|
2018
|
+
return "";
|
|
2019
|
+
try {
|
|
2020
|
+
const date = parseISO(isoString);
|
|
2021
|
+
return format(date, "HH:mm, dd, MMMM");
|
|
2022
|
+
} catch {
|
|
2023
|
+
return isoString;
|
|
2024
|
+
}
|
|
2025
|
+
};
|
|
2026
|
+
const TimelineBar = ({ onClick, className, timestamp, additions, deletions, addSize = 0, delSize = 0, isSelected = false }) => {
|
|
2027
|
+
const [open, setOpen] = useState(false);
|
|
2028
|
+
const noChanges = addSize === 0 && delSize === 0;
|
|
2029
|
+
const addBarHeight = getBarHeight(addSize);
|
|
2030
|
+
const delBarHeight = getBarHeight(delSize);
|
|
2031
|
+
const tooltipContent = jsxs("div", { className: "flex flex-col text-xs", children: [jsx("div", { children: formatTimestamp(timestamp) }), jsx("div", { className: "text-green-900", children: `${additions} additions +` }), jsx("div", { className: "text-red-700", children: `${deletions} deletions -` })] });
|
|
2032
|
+
const handleMouseEnter = () => {
|
|
2033
|
+
if (!noChanges) {
|
|
2034
|
+
setOpen(true);
|
|
2035
|
+
}
|
|
2036
|
+
};
|
|
2037
|
+
const handleMouseLeave = () => {
|
|
2038
|
+
setOpen(false);
|
|
2039
|
+
};
|
|
2040
|
+
return jsxs("div", { className: "relative", onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave, children: [isSelected && jsx(Icon, { name: "TimelineCaret", color: "#4EA9FF", size: 10, className: "absolute left-[-2px] top-[-11px] z-40" }), noChanges ? jsx("div", { className: twMerge("flex h-[25px] w-1.5 cursor-pointer flex-col items-center justify-center rounded-[2px] hover:bg-blue-300", className), "data-timestamp": timestamp, onClick, children: jsx("div", { className: "size-[3px] rounded-full bg-gray-500" }) }) : jsx(Tooltip, { className: "rounded-md bg-gray-900 text-white", content: tooltipContent, open, onOpenChange: setOpen, delayDuration: 0, side: "bottom", sideOffset: 5, children: jsxs("div", { className: twMerge("flex h-[25px] w-1.5 cursor-pointer flex-col items-center justify-center rounded-[2px] hover:bg-blue-300", className, isSelected && "bg-blue-300"), "data-timestamp": timestamp, onClick, children: [jsx("div", { className: "flex h-3 w-0.5 items-end", children: jsx("div", { className: twMerge("h-3 w-0.5 rounded-t-full bg-green-600", addBarHeight) }) }), jsx("div", { className: "flex h-3 w-0.5 items-start", children: jsx("div", { className: twMerge("h-3 w-0.5 rounded-b-full bg-red-600", delBarHeight) }) })] }) })] });
|
|
2041
|
+
};
|
|
2042
|
+
const defaultTimeLineItem = {
|
|
2043
|
+
id: "default",
|
|
2044
|
+
type: "bar",
|
|
2045
|
+
addSize: 0,
|
|
2046
|
+
delSize: 0
|
|
2047
|
+
};
|
|
2048
|
+
const DocumentTimeline = (props) => {
|
|
2049
|
+
const { timeline = [], onItemClick } = props;
|
|
2050
|
+
const [selectedItem, setSelectedItem] = useState(null);
|
|
2051
|
+
const scrollContainerRef = useRef(null);
|
|
2052
|
+
const handleClick = (item) => {
|
|
2053
|
+
if (item.id === selectedItem || item.id === defaultTimeLineItem.id) {
|
|
2054
|
+
onItemClick == null ? void 0 : onItemClick(null);
|
|
2055
|
+
setSelectedItem(null);
|
|
2056
|
+
} else {
|
|
2057
|
+
onItemClick == null ? void 0 : onItemClick(item);
|
|
2058
|
+
setSelectedItem(item.id);
|
|
2059
|
+
}
|
|
2060
|
+
};
|
|
2061
|
+
const mergedTimelineItems = [...timeline, defaultTimeLineItem];
|
|
2062
|
+
const [unselectedItems, selectedItems] = useMemo(() => {
|
|
2063
|
+
const indexSelected = mergedTimelineItems.findIndex((item) => item.id === selectedItem);
|
|
2064
|
+
return indexSelected === -1 ? [mergedTimelineItems, []] : [
|
|
2065
|
+
mergedTimelineItems.slice(0, indexSelected),
|
|
2066
|
+
mergedTimelineItems.slice(indexSelected)
|
|
2067
|
+
];
|
|
2068
|
+
}, [mergedTimelineItems, selectedItem]);
|
|
2069
|
+
const renderTimelineItems = useCallback((items) => {
|
|
2070
|
+
return items.map((item) => {
|
|
2071
|
+
if (item.type === "divider") {
|
|
2072
|
+
const { timestamp, title, subtitle } = item;
|
|
2073
|
+
return jsx(HDivider, { timestamp, title, subtitle, onClick: () => handleClick(item), isSelected: item.id === selectedItem }, item.id);
|
|
2074
|
+
}
|
|
2075
|
+
return jsx(TimelineBar, { timestamp: item.timestamp, addSize: item.addSize, delSize: item.delSize, additions: item.additions, deletions: item.deletions, isSelected: item.id === selectedItem, onClick: () => handleClick(item) }, item.id);
|
|
2076
|
+
});
|
|
2077
|
+
}, [handleClick, selectedItem]);
|
|
2078
|
+
const unselectedContent = useMemo(() => renderTimelineItems(unselectedItems), [unselectedItems, renderTimelineItems]);
|
|
2079
|
+
const selectedContent = useMemo(() => renderTimelineItems(selectedItems), [selectedItems, renderTimelineItems]);
|
|
2080
|
+
useEffect(() => {
|
|
2081
|
+
if (scrollContainerRef.current) {
|
|
2082
|
+
scrollContainerRef.current.scrollLeft = scrollContainerRef.current.scrollWidth;
|
|
2083
|
+
}
|
|
2084
|
+
}, []);
|
|
2085
|
+
return jsx(TooltipProvider, { delayDuration: 0, skipDelayDuration: 0, children: jsxs("div", { className: "relative h-[36px] w-full", children: [jsx("div", { className: "absolute left-[0px] z-[20] h-[17px] w-[6px] bg-white", children: jsx("div", { className: "mt-[11px] h-[6px] w-[6px] rounded-tl-md bg-slate-50" }) }), jsx("div", { className: "absolute right-[0px] top-[11px] z-[20] h-[6px] w-[6px] bg-white", children: jsx("div", { className: "h-[6px] w-[6px] rounded-tr-md bg-slate-50" }) }), jsx("div", { className: "absolute inset-x-0 bottom-0 h-[25px] rounded-md bg-slate-50" }), jsx("div", { className: "absolute inset-x-0 bottom-0 h-[36px]", children: jsx("div", { ref: scrollContainerRef, className: "h-full overflow-x-auto rounded-md", children: jsxs("div", { className: "ml-auto flex h-[36px] w-max items-end px-2 pb-0", children: [jsx("div", { className: "flex", children: unselectedContent }), jsx("div", { className: "flex rounded-sm bg-blue-200", children: selectedContent })] }) }) }), jsx("div", { className: "pointer-events-none absolute bottom-0 left-0 z-10 h-[25px] w-2 rounded-l-md bg-slate-50" }), jsx("div", { className: "pointer-events-none absolute bottom-0 right-0 z-10 h-[25px] w-2 rounded-r-md bg-slate-50" })] }) });
|
|
2086
|
+
};
|
|
2087
|
+
const DocumentToolbar = (props) => {
|
|
2088
|
+
const { undo: undo2, canUndo, redo: redo2, canRedo, title, onClose, onExport, className, onShowRevisionHistory, onSwitchboardLinkClick, timelineItems = [], onTimelineItemClick, initialTimelineVisible = false, timelineButtonVisible = false } = props;
|
|
2089
|
+
const [showTimeline, setShowTimeline] = useState(initialTimelineVisible);
|
|
2090
|
+
const isUndoDisabled = !canUndo || !undo2;
|
|
2091
|
+
const isRedoDisabled = !canRedo || !redo2;
|
|
2092
|
+
const isExportDisabled = !onExport;
|
|
2093
|
+
const isSwitchboardLinkDisabled = !onSwitchboardLinkClick;
|
|
2094
|
+
const isRevisionHistoryDisabled = !onShowRevisionHistory;
|
|
2095
|
+
const isTimelineDisabled = timelineItems.length === 0;
|
|
2096
|
+
useEffect(() => {
|
|
2097
|
+
if (initialTimelineVisible) {
|
|
2098
|
+
setShowTimeline(true);
|
|
2099
|
+
}
|
|
2100
|
+
}, [initialTimelineVisible]);
|
|
2101
|
+
const handleTimelineToggle = () => {
|
|
2102
|
+
if (isTimelineDisabled)
|
|
2103
|
+
return;
|
|
2104
|
+
setShowTimeline(!showTimeline);
|
|
2105
|
+
};
|
|
2106
|
+
return jsxs("div", { className: "flex w-full flex-col", children: [jsxs("div", { className: twMerge("flex h-12 w-full items-center justify-between rounded-xl border border-gray-200 bg-slate-50 px-4", className), children: [jsxs("div", { className: "flex items-center gap-x-2", children: [jsx("button", { className: twMerge("grid size-8 place-items-center rounded-lg border border-gray-200 bg-white", isUndoDisabled ? "cursor-not-allowed" : "cursor-pointer active:opacity-70"), onClick: undo2, disabled: isUndoDisabled, children: jsx(Icon, { name: "ArrowCouterclockwise", size: 16, className: isUndoDisabled ? "text-gray-500" : "text-gray-900" }) }), jsx("button", { className: twMerge("grid size-8 place-items-center rounded-lg border border-gray-200 bg-white", isRedoDisabled ? "cursor-not-allowed" : "cursor-pointer active:opacity-70"), onClick: redo2, disabled: isRedoDisabled, children: jsx("div", { className: "-scale-x-100", children: jsx(Icon, { name: "ArrowCouterclockwise", size: 16, className: isRedoDisabled ? "text-gray-500" : "text-gray-900" }) }) }), jsx("button", { className: twMerge("flex h-8 items-center rounded-lg border border-gray-200 bg-white px-3 text-sm", isExportDisabled ? "cursor-not-allowed" : "cursor-pointer active:opacity-70"), onClick: onExport, disabled: isExportDisabled, children: jsx("span", { className: isExportDisabled ? "text-gray-500" : "text-gray-900", children: "Export" }) })] }), jsx("div", { className: "flex items-center", children: jsx("h1", { className: "text-sm font-medium text-gray-500", children: title }) }), jsxs("div", { className: "flex items-center gap-x-2", children: [jsx("button", { className: twMerge("grid size-8 place-items-center rounded-lg border border-gray-200 bg-white", isSwitchboardLinkDisabled ? "cursor-not-allowed" : "cursor-pointer active:opacity-70"), onClick: onSwitchboardLinkClick, disabled: isSwitchboardLinkDisabled, children: jsx(Icon, { name: "Drive", size: 16, className: isSwitchboardLinkDisabled ? "text-gray-500" : "text-gray-900" }) }), jsx("button", { className: twMerge("grid size-8 place-items-center rounded-lg border border-gray-200 bg-white", isRevisionHistoryDisabled ? "cursor-not-allowed" : "cursor-pointer active:opacity-70"), onClick: onShowRevisionHistory, disabled: isRevisionHistoryDisabled, children: jsx(Icon, { name: "History", size: 16, className: isRevisionHistoryDisabled ? "text-gray-500" : "text-gray-900" }) }), timelineButtonVisible && jsx("button", { className: twMerge("grid size-8 place-items-center rounded-lg border border-gray-200 bg-white", isTimelineDisabled ? "cursor-not-allowed" : "cursor-pointer active:opacity-70"), onClick: handleTimelineToggle, disabled: isTimelineDisabled, "aria-pressed": showTimeline, children: jsx(Icon, { name: "Timeline", size: 16, className: twMerge("text-gray-900", isTimelineDisabled && "opacity-50", showTimeline && "text-blue-600") }) }), jsx("button", { className: "grid size-8 cursor-pointer place-items-center rounded-lg border border-gray-200 bg-white active:opacity-70", onClick: onClose, children: jsx(Icon, { name: "XmarkLight", size: 16, className: "text-gray-900" }) })] })] }), showTimeline && jsx("div", { className: "mt-2 w-full", children: jsx(DocumentTimeline, { timeline: timelineItems, onItemClick: onTimelineItemClick }) })] });
|
|
2107
|
+
};
|
|
2108
|
+
const syncIcons = {
|
|
2109
|
+
SYNCING: "Syncing",
|
|
2110
|
+
SUCCESS: "Synced",
|
|
2111
|
+
CONFLICT: "Error",
|
|
2112
|
+
MISSING: "Circle",
|
|
2113
|
+
ERROR: "Error",
|
|
2114
|
+
INITIAL_SYNC: "Syncing"
|
|
2115
|
+
};
|
|
2116
|
+
function SyncStatusIcon(props) {
|
|
2117
|
+
const { syncStatus, className, overrideSyncIcons = {}, ...iconProps } = props;
|
|
2118
|
+
const icons = { ...syncIcons, ...overrideSyncIcons };
|
|
2119
|
+
const syncStatusIcons = {
|
|
2120
|
+
[INITIAL_SYNC]: jsx(Icon, { size: 16, ...iconProps, className: twMerge("text-blue-900", className), name: icons[INITIAL_SYNC] }),
|
|
2121
|
+
[SYNCING]: jsx(Icon, { size: 16, ...iconProps, className: twMerge("text-blue-900", className), name: icons[SYNCING] }),
|
|
2122
|
+
[SUCCESS]: jsx(Icon, { size: 16, ...iconProps, className: twMerge("text-green-900", className), name: icons[SUCCESS] }),
|
|
2123
|
+
[CONFLICT]: jsx(Icon, { size: 16, ...iconProps, className: twMerge("text-orange-900", className), name: icons[CONFLICT] }),
|
|
2124
|
+
[MISSING]: jsx(Icon, { size: 16, ...iconProps, className: twMerge("text-red-900", className), name: icons[MISSING] }),
|
|
2125
|
+
[ERROR]: jsx(Icon, { size: 16, ...iconProps, className: twMerge("text-red-900", className), name: icons[ERROR] })
|
|
2126
|
+
};
|
|
2127
|
+
return syncStatusIcons[syncStatus];
|
|
2128
|
+
}
|
|
2129
|
+
function FileItem(props) {
|
|
2130
|
+
const { uiNode, className, customDocumentIconSrc, onSelectNode, onRenameNode, onDuplicateNode, onDeleteNode, isAllowedToCreateDocuments } = props;
|
|
2131
|
+
const [mode, setMode] = useState(READ);
|
|
2132
|
+
const [isDropdownMenuOpen, setIsDropdownMenuOpen] = useState(false);
|
|
2133
|
+
const { dragProps } = useDrag({ uiNode });
|
|
2134
|
+
const isReadMode = mode === READ;
|
|
2135
|
+
const dropdownMenuHandlers = {
|
|
2136
|
+
[DUPLICATE]: () => onDuplicateNode(uiNode),
|
|
2137
|
+
[RENAME]: () => setMode(WRITE),
|
|
2138
|
+
[DELETE]: () => onDeleteNode(uiNode)
|
|
2139
|
+
};
|
|
2140
|
+
const dropdownMenuOptions = Object.entries(nodeOptionsMap).map(([id, option]) => ({
|
|
2141
|
+
...option,
|
|
2142
|
+
id
|
|
2143
|
+
})).filter((option) => defaultFileOptions.includes(option.id));
|
|
2144
|
+
function onSubmit(name) {
|
|
2145
|
+
onRenameNode(name, uiNode);
|
|
2146
|
+
setMode(READ);
|
|
2147
|
+
}
|
|
2148
|
+
function onCancel() {
|
|
2149
|
+
setMode(READ);
|
|
2150
|
+
}
|
|
2151
|
+
function onClick() {
|
|
2152
|
+
onSelectNode(uiNode);
|
|
2153
|
+
}
|
|
2154
|
+
function onDropdownMenuOptionClick(itemId) {
|
|
2155
|
+
const handler = dropdownMenuHandlers[itemId];
|
|
2156
|
+
if (!handler) {
|
|
2157
|
+
console.error(`No handler found for dropdown menu item: ${itemId}`);
|
|
2158
|
+
return;
|
|
2159
|
+
}
|
|
2160
|
+
handler();
|
|
2161
|
+
setIsDropdownMenuOpen(false);
|
|
2162
|
+
}
|
|
2163
|
+
const iconSrc = getDocumentIconSrc(uiNode.documentType, customDocumentIconSrc);
|
|
2164
|
+
const iconNode = jsxs("div", { className: "relative", children: [jsx("img", { alt: "file icon", className: "max-w-none", height: 34, src: iconSrc, width: 32 }), isReadMode && uiNode.syncStatus && jsx("div", { className: "absolute bottom-[-2px] right-0 size-3 rounded-full bg-white", children: jsx("div", { className: "absolute left-[-2px] top-[-2px]", children: jsx(SyncStatusIcon, { overrideSyncIcons: { SUCCESS: "CheckCircleFill" }, syncStatus: uiNode.syncStatus }) }) })] });
|
|
2165
|
+
const containerStyles = twMerge("group flex h-12 cursor-pointer select-none items-center rounded-lg bg-gray-200 px-2 text-gray-600 hover:text-gray-800", className);
|
|
2166
|
+
const content = isReadMode ? jsxs("div", { className: "flex w-52 items-center justify-between", children: [jsxs("div", { className: "mr-2 truncate group-hover:mr-0", children: [jsx("div", { className: "max-h-6 truncate text-sm font-medium group-hover:text-gray-800", children: uiNode.name }), jsx("div", { className: "max-h-6 truncate text-xs font-medium text-gray-600 group-hover:text-gray-800", children: uiNode.documentType })] }), isAllowedToCreateDocuments ? jsx(ConnectDropdownMenu, { items: dropdownMenuOptions, onItemClick: onDropdownMenuOptionClick, onOpenChange: setIsDropdownMenuOpen, open: isDropdownMenuOpen, children: jsx("button", { className: twMerge("hidden group-hover:block", isDropdownMenuOpen && "block"), onClick: (e) => {
|
|
2167
|
+
e.stopPropagation();
|
|
2168
|
+
setIsDropdownMenuOpen(true);
|
|
2169
|
+
}, children: jsx(Icon, { className: "text-gray-600", name: "VerticalDots" }) }) }) : null] }) : jsx(NodeInput, { className: "ml-3 flex-1 font-medium", defaultValue: uiNode.name, onCancel, onSubmit });
|
|
2170
|
+
return jsx("div", { className: "relative w-64", onClick, children: jsx("div", { ...dragProps, className: containerStyles, children: jsxs("div", { className: "flex items-center", children: [jsx("div", { className: "mr-1.5", children: iconNode }), content] }) }) });
|
|
2171
|
+
}
|
|
2172
|
+
function FolderItem(props) {
|
|
2173
|
+
const { uiNode, isAllowedToCreateDocuments, className, onRenameNode, onDuplicateNode, onDeleteNode, onSelectNode, onAddFile, onCopyNode, onMoveNode } = props;
|
|
2174
|
+
const [mode, setMode] = useState(READ);
|
|
2175
|
+
const [isDropdownMenuOpen, setIsDropdownMenuOpen] = useState(false);
|
|
2176
|
+
const { dragProps } = useDrag({ ...props, uiNode });
|
|
2177
|
+
const { isDropTarget, dropProps } = useDrop({
|
|
2178
|
+
uiNode,
|
|
2179
|
+
onAddFile,
|
|
2180
|
+
onCopyNode,
|
|
2181
|
+
onMoveNode
|
|
2182
|
+
});
|
|
2183
|
+
const isReadMode = mode === READ;
|
|
2184
|
+
function onCancel() {
|
|
2185
|
+
setMode(READ);
|
|
2186
|
+
}
|
|
2187
|
+
function onSubmit(name) {
|
|
2188
|
+
onRenameNode(name, uiNode);
|
|
2189
|
+
setMode(READ);
|
|
2190
|
+
}
|
|
2191
|
+
function onClick() {
|
|
2192
|
+
onSelectNode(uiNode);
|
|
2193
|
+
}
|
|
2194
|
+
const dropdownMenuHandlers = {
|
|
2195
|
+
[DUPLICATE]: () => onDuplicateNode(uiNode),
|
|
2196
|
+
[RENAME]: () => setMode(WRITE),
|
|
2197
|
+
[DELETE]: () => onDeleteNode(uiNode)
|
|
2198
|
+
};
|
|
2199
|
+
const dropdownMenuOptions = Object.entries(nodeOptionsMap).map(([id, option]) => ({
|
|
2200
|
+
...option,
|
|
2201
|
+
id
|
|
2202
|
+
})).filter((option) => defaultFolderOptions.includes(option.id));
|
|
2203
|
+
function onDropdownMenuOptionClick(itemId) {
|
|
2204
|
+
const handler = dropdownMenuHandlers[itemId];
|
|
2205
|
+
if (!handler) {
|
|
2206
|
+
console.error(`No handler found for dropdown menu item: ${itemId}`);
|
|
2207
|
+
return;
|
|
2208
|
+
}
|
|
2209
|
+
handler();
|
|
2210
|
+
setIsDropdownMenuOpen(false);
|
|
2211
|
+
}
|
|
2212
|
+
const content = isReadMode || !isAllowedToCreateDocuments ? jsx("div", { className: "ml-3 max-h-6 truncate font-medium text-gray-600 group-hover:text-gray-800", children: uiNode.name }) : jsx(NodeInput, { className: "ml-3 font-medium", defaultValue: uiNode.name, onCancel, onSubmit });
|
|
2213
|
+
const containerStyles = twMerge("group flex h-12 cursor-pointer select-none items-center rounded-lg bg-gray-200 px-2", className, isDropTarget && "bg-blue-100");
|
|
2214
|
+
return jsx("div", { className: "relative w-64", onClick, children: jsxs("div", { ...dragProps, ...dropProps, className: containerStyles, children: [jsxs("div", { className: "flex items-center overflow-hidden", children: [jsx("div", { className: "p-1", children: jsxs("div", { className: "relative", children: [jsx(Icon, { name: "FolderClose", size: 24 }), isReadMode && uiNode.syncStatus ? jsx("div", { className: "absolute bottom-[-3px] right-[-2px] size-3 rounded-full bg-white", children: jsx("div", { className: "absolute left-[-2px] top-[-2px]", children: jsx(SyncStatusIcon, { overrideSyncIcons: {
|
|
2215
|
+
SUCCESS: "CheckCircleFill"
|
|
2216
|
+
}, syncStatus: uiNode.syncStatus }) }) }) : null] }) }), content] }), isReadMode && isAllowedToCreateDocuments ? jsx(ConnectDropdownMenu, { items: dropdownMenuOptions, onItemClick: onDropdownMenuOptionClick, onOpenChange: setIsDropdownMenuOpen, open: isDropdownMenuOpen, children: jsx("button", { className: twMerge("ml-auto hidden group-hover:block", isDropdownMenuOpen && "block"), onClick: (e) => {
|
|
2217
|
+
e.stopPropagation();
|
|
2218
|
+
setIsDropdownMenuOpen(true);
|
|
2219
|
+
}, children: jsx(Icon, { className: "text-gray-600", name: "VerticalDots" }) }) }) : null] }) });
|
|
2220
|
+
}
|
|
2221
|
+
function NodeInput(props) {
|
|
2222
|
+
const { onSubmit, onCancel, defaultValue, className, minLength = 1, ...inputProps } = props;
|
|
2223
|
+
const [value, setValue] = useState(defaultValue ?? "");
|
|
2224
|
+
const ref = useRef(null);
|
|
2225
|
+
useOnClickOutside(ref, handleSubmit);
|
|
2226
|
+
useEventListener("keyup", (e) => {
|
|
2227
|
+
if (e.key === "Enter") {
|
|
2228
|
+
handleSubmit();
|
|
2229
|
+
}
|
|
2230
|
+
if (e.key === "Escape") {
|
|
2231
|
+
onCancel();
|
|
2232
|
+
}
|
|
2233
|
+
});
|
|
2234
|
+
useLayoutEffect(() => {
|
|
2235
|
+
setTimeout(() => {
|
|
2236
|
+
var _a, _b, _c;
|
|
2237
|
+
(_a = ref.current) == null ? void 0 : _a.focus();
|
|
2238
|
+
(_b = ref.current) == null ? void 0 : _b.select();
|
|
2239
|
+
(_c = ref.current) == null ? void 0 : _c.scroll({ left: 9999 });
|
|
2240
|
+
}, 100);
|
|
2241
|
+
}, []);
|
|
2242
|
+
function handleSubmit() {
|
|
2243
|
+
if (value.length >= minLength) {
|
|
2244
|
+
onSubmit(value);
|
|
2245
|
+
}
|
|
2246
|
+
}
|
|
2247
|
+
return jsx("input", { ...inputProps, autoFocus: true, className: twMerge("bg-inherit text-inherit outline-none", className), minLength, onChange: (e) => setValue(e.target.value), ref, required: true, type: "text", value });
|
|
2248
|
+
}
|
|
2249
|
+
function Branch(props) {
|
|
2250
|
+
const { branch = "main" } = props;
|
|
2251
|
+
return jsxs("button", { className: "flex h-8 items-center gap-1 rounded-lg bg-slate-50 pl-1 pr-2 text-xs text-slate-100", children: [jsx(Icon, { name: "Branch" }), jsx("span", { children: "BRANCH" }), jsx("span", { className: "text-gray-900", children: branch })] });
|
|
2252
|
+
}
|
|
2253
|
+
function DocId(props) {
|
|
2254
|
+
const { docId } = props;
|
|
2255
|
+
const [, copy] = useCopyToClipboard();
|
|
2256
|
+
function handleCopy(text) {
|
|
2257
|
+
return () => {
|
|
2258
|
+
copy(text).catch((error) => {
|
|
2259
|
+
console.error("Failed to copy!", error);
|
|
2260
|
+
});
|
|
2261
|
+
};
|
|
2262
|
+
}
|
|
2263
|
+
return jsxs("button", { className: "flex h-8 items-center gap-1 rounded-lg bg-slate-50 pl-1 pr-2 text-xs text-slate-100", onClick: handleCopy(docId), children: [jsx(Icon, { name: "Link" }), "DOC ID", jsx("span", { className: "text-gray-900", children: docId })] });
|
|
2264
|
+
}
|
|
2265
|
+
function Scope(props) {
|
|
2266
|
+
const { value, onChange } = props;
|
|
2267
|
+
const items = [
|
|
2268
|
+
{ displayValue: "Global scope", value: "global" },
|
|
2269
|
+
{ displayValue: "Local scope", value: "local" }
|
|
2270
|
+
];
|
|
2271
|
+
return jsx(Select, { absolutePositionMenu: true, containerClassName: "bg-slate-50 text-gray-500 rounded-lg w-fit text-xs z-10", id: "scope select", itemClassName: "py-2 text-gray-500 grid grid-cols-[auto,auto] gap-1", items, menuClassName: "min-w-0 text-gray-500", onChange, value });
|
|
2272
|
+
}
|
|
2273
|
+
function Header(props) {
|
|
2274
|
+
const { title, docId, scope, onChangeScope, onClose, className, ...divProps } = props;
|
|
2275
|
+
return jsxs("header", { className: twMerge("flex items-center justify-between bg-transparent", className), ...divProps, children: [jsxs("div", { className: "flex items-center gap-3", children: [jsx("button", { className: "shadow-button rounded-lg bg-gray-50 p-1 text-slate-100", onClick: onClose, children: jsx(Icon, { name: "VariantArrowLeft" }) }), jsx("h1", { className: "text-xs", children: title })] }), jsxs("div", { className: "flex items-center gap-2", children: [jsx(DocId, { docId }), jsx(Branch, {}), jsx(Scope, { onChange: onChangeScope, value: scope })] })] });
|
|
2276
|
+
}
|
|
2277
|
+
function memo(getDeps, fn, opts) {
|
|
2278
|
+
let deps = opts.initialDeps ?? [];
|
|
2279
|
+
let result;
|
|
2280
|
+
return () => {
|
|
2281
|
+
var _a, _b, _c, _d;
|
|
2282
|
+
let depTime;
|
|
2283
|
+
if (opts.key && ((_a = opts.debug) == null ? void 0 : _a.call(opts))) depTime = Date.now();
|
|
2284
|
+
const newDeps = getDeps();
|
|
2285
|
+
const depsChanged = newDeps.length !== deps.length || newDeps.some((dep, index) => deps[index] !== dep);
|
|
2286
|
+
if (!depsChanged) {
|
|
2287
|
+
return result;
|
|
2288
|
+
}
|
|
2289
|
+
deps = newDeps;
|
|
2290
|
+
let resultTime;
|
|
1837
2291
|
if (opts.key && ((_b = opts.debug) == null ? void 0 : _b.call(opts))) resultTime = Date.now();
|
|
1838
2292
|
result = fn(...newDeps);
|
|
1839
2293
|
if (opts.key && ((_c = opts.debug) == null ? void 0 : _c.call(opts))) {
|
|
@@ -1861,11 +2315,7 @@ function memo(getDeps, fn, opts) {
|
|
|
1861
2315
|
}
|
|
1862
2316
|
(_d = opts == null ? void 0 : opts.onChange) == null ? void 0 : _d.call(opts, result);
|
|
1863
2317
|
return result;
|
|
1864
|
-
}
|
|
1865
|
-
memoizedFunction.updateDeps = (newDeps) => {
|
|
1866
|
-
deps = newDeps;
|
|
1867
2318
|
};
|
|
1868
|
-
return memoizedFunction;
|
|
1869
2319
|
}
|
|
1870
2320
|
function notUndefined(value, msg) {
|
|
1871
2321
|
if (value === void 0) {
|
|
@@ -1874,7 +2324,7 @@ function notUndefined(value, msg) {
|
|
|
1874
2324
|
return value;
|
|
1875
2325
|
}
|
|
1876
2326
|
}
|
|
1877
|
-
const approxEqual = (a, b) => Math.abs(a - b)
|
|
2327
|
+
const approxEqual = (a, b) => Math.abs(a - b) < 1;
|
|
1878
2328
|
const debounce = (targetWindow, fn, ms) => {
|
|
1879
2329
|
let timeoutId;
|
|
1880
2330
|
return function(...args) {
|
|
@@ -1882,10 +2332,6 @@ const debounce = (targetWindow, fn, ms) => {
|
|
|
1882
2332
|
timeoutId = targetWindow.setTimeout(() => fn.apply(this, args), ms);
|
|
1883
2333
|
};
|
|
1884
2334
|
};
|
|
1885
|
-
const getRect = (element) => {
|
|
1886
|
-
const { offsetWidth, offsetHeight } = element;
|
|
1887
|
-
return { width: offsetWidth, height: offsetHeight };
|
|
1888
|
-
};
|
|
1889
2335
|
const defaultKeyExtractor = (index) => index;
|
|
1890
2336
|
const defaultRangeExtractor = (range) => {
|
|
1891
2337
|
const start = Math.max(range.startIndex - range.overscan, 0);
|
|
@@ -1909,24 +2355,21 @@ const observeElementRect = (instance, cb) => {
|
|
|
1909
2355
|
const { width, height } = rect;
|
|
1910
2356
|
cb({ width: Math.round(width), height: Math.round(height) });
|
|
1911
2357
|
};
|
|
1912
|
-
handler(
|
|
2358
|
+
handler(element.getBoundingClientRect());
|
|
1913
2359
|
if (!targetWindow.ResizeObserver) {
|
|
1914
2360
|
return () => {
|
|
1915
2361
|
};
|
|
1916
2362
|
}
|
|
1917
2363
|
const observer = new targetWindow.ResizeObserver((entries) => {
|
|
1918
|
-
const
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
return;
|
|
1925
|
-
}
|
|
2364
|
+
const entry = entries[0];
|
|
2365
|
+
if (entry == null ? void 0 : entry.borderBoxSize) {
|
|
2366
|
+
const box = entry.borderBoxSize[0];
|
|
2367
|
+
if (box) {
|
|
2368
|
+
handler({ width: box.inlineSize, height: box.blockSize });
|
|
2369
|
+
return;
|
|
1926
2370
|
}
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
instance.options.useAnimationFrameWithResizeObserver ? requestAnimationFrame(run) : run();
|
|
2371
|
+
}
|
|
2372
|
+
handler(element.getBoundingClientRect());
|
|
1930
2373
|
});
|
|
1931
2374
|
observer.observe(element, { box: "border-box" });
|
|
1932
2375
|
return () => {
|
|
@@ -1964,15 +2407,10 @@ const observeElementOffset = (instance, cb) => {
|
|
|
1964
2407
|
const endHandler = createHandler(false);
|
|
1965
2408
|
endHandler();
|
|
1966
2409
|
element.addEventListener("scroll", handler, addEventListenerOptions);
|
|
1967
|
-
|
|
1968
|
-
if (registerScrollendEvent) {
|
|
1969
|
-
element.addEventListener("scrollend", endHandler, addEventListenerOptions);
|
|
1970
|
-
}
|
|
2410
|
+
element.addEventListener("scrollend", endHandler, addEventListenerOptions);
|
|
1971
2411
|
return () => {
|
|
1972
2412
|
element.removeEventListener("scroll", handler);
|
|
1973
|
-
|
|
1974
|
-
element.removeEventListener("scrollend", endHandler);
|
|
1975
|
-
}
|
|
2413
|
+
element.removeEventListener("scrollend", endHandler);
|
|
1976
2414
|
};
|
|
1977
2415
|
};
|
|
1978
2416
|
const measureElement = (element, entry, instance) => {
|
|
@@ -1985,7 +2423,9 @@ const measureElement = (element, entry, instance) => {
|
|
|
1985
2423
|
return size;
|
|
1986
2424
|
}
|
|
1987
2425
|
}
|
|
1988
|
-
return
|
|
2426
|
+
return Math.round(
|
|
2427
|
+
element.getBoundingClientRect()[instance.options.horizontal ? "width" : "height"]
|
|
2428
|
+
);
|
|
1989
2429
|
};
|
|
1990
2430
|
const elementScroll = (offset, {
|
|
1991
2431
|
adjustments = 0,
|
|
@@ -2024,10 +2464,7 @@ class Virtualizer {
|
|
|
2024
2464
|
}
|
|
2025
2465
|
return _ro = new this.targetWindow.ResizeObserver((entries) => {
|
|
2026
2466
|
entries.forEach((entry) => {
|
|
2027
|
-
|
|
2028
|
-
this._measureElement(entry.target, entry);
|
|
2029
|
-
};
|
|
2030
|
-
this.options.useAnimationFrameWithResizeObserver ? requestAnimationFrame(run) : run();
|
|
2467
|
+
this._measureElement(entry.target, entry);
|
|
2031
2468
|
});
|
|
2032
2469
|
});
|
|
2033
2470
|
};
|
|
@@ -2075,8 +2512,7 @@ class Virtualizer {
|
|
|
2075
2512
|
isScrollingResetDelay: 150,
|
|
2076
2513
|
enabled: true,
|
|
2077
2514
|
isRtl: false,
|
|
2078
|
-
useScrollendEvent:
|
|
2079
|
-
useAnimationFrameWithResizeObserver: false,
|
|
2515
|
+
useScrollendEvent: true,
|
|
2080
2516
|
...opts2
|
|
2081
2517
|
};
|
|
2082
2518
|
};
|
|
@@ -2265,18 +2701,12 @@ class Virtualizer {
|
|
|
2265
2701
|
}
|
|
2266
2702
|
);
|
|
2267
2703
|
this.calculateRange = memo(
|
|
2268
|
-
() => [
|
|
2269
|
-
|
|
2270
|
-
this.getSize(),
|
|
2271
|
-
this.getScrollOffset(),
|
|
2272
|
-
this.options.lanes
|
|
2273
|
-
],
|
|
2274
|
-
(measurements, outerSize, scrollOffset, lanes) => {
|
|
2704
|
+
() => [this.getMeasurements(), this.getSize(), this.getScrollOffset()],
|
|
2705
|
+
(measurements, outerSize, scrollOffset) => {
|
|
2275
2706
|
return this.range = measurements.length > 0 && outerSize > 0 ? calculateRange({
|
|
2276
2707
|
measurements,
|
|
2277
2708
|
outerSize,
|
|
2278
|
-
scrollOffset
|
|
2279
|
-
lanes
|
|
2709
|
+
scrollOffset
|
|
2280
2710
|
}) : null;
|
|
2281
2711
|
},
|
|
2282
2712
|
{
|
|
@@ -2284,7 +2714,7 @@ class Virtualizer {
|
|
|
2284
2714
|
debug: () => this.options.debug
|
|
2285
2715
|
}
|
|
2286
2716
|
);
|
|
2287
|
-
this.
|
|
2717
|
+
this.getIndexes = memo(
|
|
2288
2718
|
() => {
|
|
2289
2719
|
let startIndex = null;
|
|
2290
2720
|
let endIndex = null;
|
|
@@ -2293,7 +2723,6 @@ class Virtualizer {
|
|
|
2293
2723
|
startIndex = range.startIndex;
|
|
2294
2724
|
endIndex = range.endIndex;
|
|
2295
2725
|
}
|
|
2296
|
-
this.maybeNotify.updateDeps([this.isScrolling, startIndex, endIndex]);
|
|
2297
2726
|
return [
|
|
2298
2727
|
this.options.rangeExtractor,
|
|
2299
2728
|
this.options.overscan,
|
|
@@ -2377,7 +2806,7 @@ class Virtualizer {
|
|
|
2377
2806
|
this._measureElement(node, void 0);
|
|
2378
2807
|
};
|
|
2379
2808
|
this.getVirtualItems = memo(
|
|
2380
|
-
() => [this.
|
|
2809
|
+
() => [this.getIndexes(), this.getMeasurements()],
|
|
2381
2810
|
(indexes, measurements) => {
|
|
2382
2811
|
const virtualItems = [];
|
|
2383
2812
|
for (let k = 0, len = indexes.length; k < len; k++) {
|
|
@@ -2406,18 +2835,20 @@ class Virtualizer {
|
|
|
2406
2835
|
)]
|
|
2407
2836
|
);
|
|
2408
2837
|
};
|
|
2409
|
-
this.getOffsetForAlignment = (toOffset, align
|
|
2838
|
+
this.getOffsetForAlignment = (toOffset, align) => {
|
|
2410
2839
|
const size = this.getSize();
|
|
2411
2840
|
const scrollOffset = this.getScrollOffset();
|
|
2412
2841
|
if (align === "auto") {
|
|
2413
|
-
|
|
2842
|
+
if (toOffset >= scrollOffset + size) {
|
|
2843
|
+
align = "end";
|
|
2844
|
+
}
|
|
2414
2845
|
}
|
|
2415
|
-
if (align === "
|
|
2416
|
-
toOffset += (itemSize - size) / 2;
|
|
2417
|
-
} else if (align === "end") {
|
|
2846
|
+
if (align === "end") {
|
|
2418
2847
|
toOffset -= size;
|
|
2419
2848
|
}
|
|
2420
|
-
const
|
|
2849
|
+
const scrollSizeProp = this.options.horizontal ? "scrollWidth" : "scrollHeight";
|
|
2850
|
+
const scrollSize = this.scrollElement ? "document" in this.scrollElement ? this.scrollElement.document.documentElement[scrollSizeProp] : this.scrollElement[scrollSizeProp] : 0;
|
|
2851
|
+
const maxOffset = scrollSize - size;
|
|
2421
2852
|
return Math.max(Math.min(maxOffset, toOffset), 0);
|
|
2422
2853
|
};
|
|
2423
2854
|
this.getOffsetForIndex = (index, align = "auto") => {
|
|
@@ -2437,11 +2868,27 @@ class Virtualizer {
|
|
|
2437
2868
|
return [scrollOffset, align];
|
|
2438
2869
|
}
|
|
2439
2870
|
}
|
|
2440
|
-
const
|
|
2441
|
-
|
|
2442
|
-
|
|
2443
|
-
|
|
2444
|
-
|
|
2871
|
+
const centerOffset = item.start - this.options.scrollPaddingStart + (item.size - size) / 2;
|
|
2872
|
+
switch (align) {
|
|
2873
|
+
case "center":
|
|
2874
|
+
return [this.getOffsetForAlignment(centerOffset, align), align];
|
|
2875
|
+
case "end":
|
|
2876
|
+
return [
|
|
2877
|
+
this.getOffsetForAlignment(
|
|
2878
|
+
item.end + this.options.scrollPaddingEnd,
|
|
2879
|
+
align
|
|
2880
|
+
),
|
|
2881
|
+
align
|
|
2882
|
+
];
|
|
2883
|
+
default:
|
|
2884
|
+
return [
|
|
2885
|
+
this.getOffsetForAlignment(
|
|
2886
|
+
item.start - this.options.scrollPaddingStart,
|
|
2887
|
+
align
|
|
2888
|
+
),
|
|
2889
|
+
align
|
|
2890
|
+
];
|
|
2891
|
+
}
|
|
2445
2892
|
};
|
|
2446
2893
|
this.isDynamicMode = () => this.elementsCache.size > 0;
|
|
2447
2894
|
this.cancelScrollToIndex = () => {
|
|
@@ -2484,8 +2931,7 @@ class Virtualizer {
|
|
|
2484
2931
|
const [latestOffset] = notUndefined(
|
|
2485
2932
|
this.getOffsetForIndex(index, align)
|
|
2486
2933
|
);
|
|
2487
|
-
|
|
2488
|
-
if (!approxEqual(latestOffset, currentScrollOffset)) {
|
|
2934
|
+
if (!approxEqual(latestOffset, this.getScrollOffset())) {
|
|
2489
2935
|
this.scrollToIndex(index, { align, behavior });
|
|
2490
2936
|
}
|
|
2491
2937
|
} else {
|
|
@@ -2512,19 +2958,10 @@ class Virtualizer {
|
|
|
2512
2958
|
let end;
|
|
2513
2959
|
if (measurements.length === 0) {
|
|
2514
2960
|
end = this.options.paddingStart;
|
|
2515
|
-
} else if (this.options.lanes === 1) {
|
|
2516
|
-
end = ((_a = measurements[measurements.length - 1]) == null ? void 0 : _a.end) ?? 0;
|
|
2517
2961
|
} else {
|
|
2518
|
-
|
|
2519
|
-
|
|
2520
|
-
|
|
2521
|
-
const item = measurements[endIndex];
|
|
2522
|
-
if (endByLane[item.lane] === null) {
|
|
2523
|
-
endByLane[item.lane] = item.end;
|
|
2524
|
-
}
|
|
2525
|
-
endIndex--;
|
|
2526
|
-
}
|
|
2527
|
-
end = Math.max(...endByLane.filter((val) => val !== null));
|
|
2962
|
+
end = this.options.lanes === 1 ? ((_a = measurements[measurements.length - 1]) == null ? void 0 : _a.end) ?? 0 : Math.max(
|
|
2963
|
+
...measurements.slice(-this.options.lanes).map((m) => m.end)
|
|
2964
|
+
);
|
|
2528
2965
|
}
|
|
2529
2966
|
return Math.max(
|
|
2530
2967
|
end - this.options.scrollMargin + this.options.paddingEnd,
|
|
@@ -2565,43 +3002,14 @@ const findNearestBinarySearch = (low, high, getCurrentValue, value) => {
|
|
|
2565
3002
|
function calculateRange({
|
|
2566
3003
|
measurements,
|
|
2567
3004
|
outerSize,
|
|
2568
|
-
scrollOffset
|
|
2569
|
-
lanes
|
|
3005
|
+
scrollOffset
|
|
2570
3006
|
}) {
|
|
2571
|
-
const
|
|
3007
|
+
const count = measurements.length - 1;
|
|
2572
3008
|
const getOffset = (index) => measurements[index].start;
|
|
2573
|
-
|
|
2574
|
-
return {
|
|
2575
|
-
startIndex: 0,
|
|
2576
|
-
endIndex: lastIndex
|
|
2577
|
-
};
|
|
2578
|
-
}
|
|
2579
|
-
let startIndex = findNearestBinarySearch(
|
|
2580
|
-
0,
|
|
2581
|
-
lastIndex,
|
|
2582
|
-
getOffset,
|
|
2583
|
-
scrollOffset
|
|
2584
|
-
);
|
|
3009
|
+
const startIndex = findNearestBinarySearch(0, count, getOffset, scrollOffset);
|
|
2585
3010
|
let endIndex = startIndex;
|
|
2586
|
-
|
|
2587
|
-
|
|
2588
|
-
endIndex++;
|
|
2589
|
-
}
|
|
2590
|
-
} else if (lanes > 1) {
|
|
2591
|
-
const endPerLane = Array(lanes).fill(0);
|
|
2592
|
-
while (endIndex < lastIndex && endPerLane.some((pos) => pos < scrollOffset + outerSize)) {
|
|
2593
|
-
const item = measurements[endIndex];
|
|
2594
|
-
endPerLane[item.lane] = item.end;
|
|
2595
|
-
endIndex++;
|
|
2596
|
-
}
|
|
2597
|
-
const startPerLane = Array(lanes).fill(scrollOffset + outerSize);
|
|
2598
|
-
while (startIndex >= 0 && startPerLane.some((pos) => pos >= scrollOffset)) {
|
|
2599
|
-
const item = measurements[startIndex];
|
|
2600
|
-
startPerLane[item.lane] = item.start;
|
|
2601
|
-
startIndex--;
|
|
2602
|
-
}
|
|
2603
|
-
startIndex = Math.max(0, startIndex - startIndex % lanes);
|
|
2604
|
-
endIndex = Math.min(lastIndex, endIndex + (lanes - 1 - endIndex % lanes));
|
|
3011
|
+
while (endIndex < count && measurements[endIndex].end < scrollOffset + outerSize) {
|
|
3012
|
+
endIndex++;
|
|
2605
3013
|
}
|
|
2606
3014
|
return { startIndex, endIndex };
|
|
2607
3015
|
}
|
|
@@ -2858,8 +3266,8 @@ function RevisionHistory(props) {
|
|
|
2858
3266
|
return jsxs(TooltipProvider, { children: [jsx(Header, { docId: documentId, onChangeScope, onClose, scope, title: documentTitle }), PaginationComponent, jsx("div", { className: "mt-4 flex justify-center rounded-md bg-slate-50 p-4", children: visibleOperations.length > 0 ? jsx("div", { className: "grid grid-cols-[minmax(min-content,1018px)]", children: jsx(Timeline, { globalOperations: scope === "global" ? pageItems : [], localOperations: scope === "local" ? pageItems : [], scope }) }) : jsx("h3", { className: "my-40 text-gray-600", children: "This document has no recorded operations yet." }) }), PaginationComponent] });
|
|
2859
3267
|
}
|
|
2860
3268
|
function Tooltip(props) {
|
|
2861
|
-
const { children, content, open, defaultOpen, onOpenChange, className, ...rest } = props;
|
|
2862
|
-
return jsxs(Root3, { defaultOpen, delayDuration: 0, onOpenChange, open, children: [jsx(Trigger, { asChild: true, children }), jsx(Portal, { children: jsx(Content2, { ...rest, className: twMerge("shadow-tooltip rounded-lg border border-gray-200 bg-white p-2 text-xs", className), children: content }) })] });
|
|
3269
|
+
const { children, content, open, defaultOpen, onOpenChange, className, side = "top", sideOffset = 5, ...rest } = props;
|
|
3270
|
+
return jsxs(Root3, { defaultOpen, delayDuration: 0, onOpenChange, open, children: [jsx(Trigger, { asChild: true, children }), jsx(Portal, { children: jsx(Content2, { ...rest, side, sideOffset, className: twMerge("shadow-tooltip rounded-lg border border-gray-200 bg-white p-2 text-xs", className), children: content }) })] });
|
|
2863
3271
|
}
|
|
2864
3272
|
const TooltipProvider = Provider;
|
|
2865
3273
|
const BUDGET = "powerhouse/budget-statement";
|
|
@@ -3107,9 +3515,7 @@ function useAddDebouncedOperations(reactor, props) {
|
|
|
3107
3515
|
const { driveId, documentId } = props;
|
|
3108
3516
|
const [documentDrives] = useDocumentDrives(reactor);
|
|
3109
3517
|
const documentDrivesRef = useRef(documentDrives);
|
|
3110
|
-
const { isAllowedToEditDocuments } = useUserPermissions()
|
|
3111
|
-
isAllowedToEditDocuments: false
|
|
3112
|
-
};
|
|
3518
|
+
const { isAllowedToEditDocuments } = useUserPermissions();
|
|
3113
3519
|
useEffect(() => {
|
|
3114
3520
|
documentDrivesRef.current = documentDrives;
|
|
3115
3521
|
}, [documentDrives]);
|
|
@@ -3120,7 +3526,7 @@ function useAddDebouncedOperations(reactor, props) {
|
|
|
3120
3526
|
if (!reactor) {
|
|
3121
3527
|
throw new Error("Reactor is not loaded");
|
|
3122
3528
|
}
|
|
3123
|
-
const drive = documentDrivesRef.current.find((drive2) => drive2.
|
|
3529
|
+
const drive = documentDrivesRef.current.find((drive2) => drive2.id === driveId2);
|
|
3124
3530
|
if (!drive) {
|
|
3125
3531
|
throw new Error(`Drive with id ${driveId2} not found`);
|
|
3126
3532
|
}
|
|
@@ -3199,7 +3605,7 @@ function getNode(id, drive) {
|
|
|
3199
3605
|
}
|
|
3200
3606
|
function createDriveActions(document2, dispatch, context) {
|
|
3201
3607
|
const drive = document2;
|
|
3202
|
-
const
|
|
3608
|
+
const driveId = drive.id;
|
|
3203
3609
|
const { selectedNode } = context;
|
|
3204
3610
|
const handleAddFolder = async (name, parentFolder, id = generateId()) => {
|
|
3205
3611
|
dispatch(addFolder({
|
|
@@ -3489,6 +3895,17 @@ function useEditorProps(document2, node, documentDispatch, onAddOperation) {
|
|
|
3489
3895
|
isAllowedToEditDocuments: (userPermissions == null ? void 0 : userPermissions.isAllowedToEditDocuments) ?? false
|
|
3490
3896
|
};
|
|
3491
3897
|
}
|
|
3898
|
+
function useGetDocument() {
|
|
3899
|
+
const { openFile } = useDocumentDriveServer();
|
|
3900
|
+
const getDocument = useCallback(
|
|
3901
|
+
async (driveId, documentId, options) => {
|
|
3902
|
+
const document2 = await openFile(driveId, documentId, options);
|
|
3903
|
+
return document2;
|
|
3904
|
+
},
|
|
3905
|
+
[openFile]
|
|
3906
|
+
);
|
|
3907
|
+
return getDocument;
|
|
3908
|
+
}
|
|
3492
3909
|
function useSyncStatus(driveId, documentId) {
|
|
3493
3910
|
const { getSyncStatusSync, onSyncStatus, documentDrives } = useDocumentDriveServer();
|
|
3494
3911
|
const syncStatus = useSyncExternalStore(
|
|
@@ -3498,9 +3915,7 @@ function useSyncStatus(driveId, documentId) {
|
|
|
3498
3915
|
},
|
|
3499
3916
|
() => {
|
|
3500
3917
|
var _a;
|
|
3501
|
-
const drive = documentDrives.find(
|
|
3502
|
-
(_drive) => _drive.state.global.id === driveId
|
|
3503
|
-
);
|
|
3918
|
+
const drive = documentDrives.find((_drive) => _drive.id === driveId);
|
|
3504
3919
|
if (!drive) return;
|
|
3505
3920
|
const isReadDrive = "readContext" in drive;
|
|
3506
3921
|
const _sharingType = !isReadDrive ? (_a = drive.state.local.sharingType) == null ? void 0 : _a.toUpperCase() : "PUBLIC";
|
|
@@ -3559,8 +3974,340 @@ const useUndoRedoShortcuts = (props) => {
|
|
|
3559
3974
|
[canRedo, redo2]
|
|
3560
3975
|
);
|
|
3561
3976
|
};
|
|
3562
|
-
function
|
|
3563
|
-
|
|
3977
|
+
function getDocumentSpec(doc) {
|
|
3978
|
+
if ("documentModelState" in doc) {
|
|
3979
|
+
return doc.documentModelState;
|
|
3980
|
+
}
|
|
3981
|
+
return doc.documentModel;
|
|
3982
|
+
}
|
|
3983
|
+
const CreateDocument = ({ documentModels, createDocument }) => {
|
|
3984
|
+
return jsxs("div", { className: "px-6", children: [jsx("h3", { className: "mb-3 mt-4 text-xl font-bold text-gray-600", children: "New document" }), jsx("div", { className: "flex w-full flex-wrap gap-4", children: documentModels == null ? void 0 : documentModels.map((doc) => {
|
|
3985
|
+
const spec = getDocumentSpec(doc);
|
|
3986
|
+
return jsx(Button, { color: "light", "aria-details": spec.description, onClick: () => createDocument(doc), children: jsx("span", { className: "text-sm", children: spec.name }) }, spec.id);
|
|
3987
|
+
}) })] });
|
|
3988
|
+
};
|
|
3989
|
+
function sortUiNodesByName(a, b) {
|
|
3990
|
+
return a.name.localeCompare(b.name);
|
|
3991
|
+
}
|
|
3992
|
+
const GAP = 8;
|
|
3993
|
+
const ITEM_WIDTH = 256;
|
|
3994
|
+
const ITEM_HEIGHT = 48;
|
|
3995
|
+
const USED_SPACE = 420;
|
|
3996
|
+
function FileContentView(props) {
|
|
3997
|
+
const parentRef = useRef(null);
|
|
3998
|
+
const { t } = useTranslation();
|
|
3999
|
+
const windowSize = useWindowSize();
|
|
4000
|
+
const { fileNodes, ...fileProps } = props;
|
|
4001
|
+
const availableWidth = windowSize.innerWidth - USED_SPACE;
|
|
4002
|
+
const columnCount = Math.floor(availableWidth / (ITEM_WIDTH + GAP)) || 1;
|
|
4003
|
+
const rowCount = Math.ceil(fileNodes.length / columnCount);
|
|
4004
|
+
const rowVirtualizer = useVirtualizer({
|
|
4005
|
+
count: rowCount,
|
|
4006
|
+
getScrollElement: () => parentRef.current,
|
|
4007
|
+
estimateSize: (index) => {
|
|
4008
|
+
if (index > 0) {
|
|
4009
|
+
return ITEM_HEIGHT + GAP;
|
|
4010
|
+
}
|
|
4011
|
+
return ITEM_HEIGHT;
|
|
4012
|
+
},
|
|
4013
|
+
overscan: 5
|
|
4014
|
+
});
|
|
4015
|
+
const columnVirtualizer = useVirtualizer({
|
|
4016
|
+
horizontal: true,
|
|
4017
|
+
count: columnCount,
|
|
4018
|
+
getScrollElement: () => parentRef.current,
|
|
4019
|
+
estimateSize: (index) => {
|
|
4020
|
+
if (index > 0) {
|
|
4021
|
+
return ITEM_WIDTH + GAP;
|
|
4022
|
+
}
|
|
4023
|
+
return ITEM_WIDTH;
|
|
4024
|
+
},
|
|
4025
|
+
overscan: 5
|
|
4026
|
+
});
|
|
4027
|
+
const getItemIndex = (rowIndex, columnIndex) => rowIndex * columnCount + columnIndex;
|
|
4028
|
+
const getItem = (rowIndex, columnIndex) => {
|
|
4029
|
+
const index = getItemIndex(rowIndex, columnIndex);
|
|
4030
|
+
return fileNodes[index] || null;
|
|
4031
|
+
};
|
|
4032
|
+
if (fileNodes.length === 0) {
|
|
4033
|
+
return jsx("div", { className: "mb-8 text-sm text-gray-400", children: t("folderView.sections.documents.empty", {
|
|
4034
|
+
defaultValue: "No documents or files 📄"
|
|
4035
|
+
}) });
|
|
4036
|
+
}
|
|
4037
|
+
const renderItem = (rowIndex, columnIndex) => {
|
|
4038
|
+
const fileNode = getItem(rowIndex, columnIndex);
|
|
4039
|
+
if (!fileNode) {
|
|
4040
|
+
return null;
|
|
4041
|
+
}
|
|
4042
|
+
return jsx("div", { style: {
|
|
4043
|
+
marginLeft: columnIndex === 0 ? 0 : GAP
|
|
4044
|
+
}, children: jsx(FileItem, { uiNode: fileNode, ...fileProps }, fileNode.id) });
|
|
4045
|
+
};
|
|
4046
|
+
return jsx("div", { ref: parentRef, style: {
|
|
4047
|
+
height: `400px`,
|
|
4048
|
+
width: `100%`,
|
|
4049
|
+
overflow: "auto"
|
|
4050
|
+
}, children: jsx("div", { style: {
|
|
4051
|
+
height: `${rowVirtualizer.getTotalSize()}px`,
|
|
4052
|
+
width: `${columnVirtualizer.getTotalSize()}px`,
|
|
4053
|
+
position: "relative"
|
|
4054
|
+
}, children: rowVirtualizer.getVirtualItems().map((virtualRow) => jsx(React__default.Fragment, { children: columnVirtualizer.getVirtualItems().map((virtualColumn) => jsx("div", { style: {
|
|
4055
|
+
position: "absolute",
|
|
4056
|
+
top: 0,
|
|
4057
|
+
left: 0,
|
|
4058
|
+
marginTop: virtualRow.index === 0 ? 0 : GAP,
|
|
4059
|
+
width: `${virtualColumn.size}px`,
|
|
4060
|
+
height: `${virtualRow.size}px`,
|
|
4061
|
+
transform: `translateX(${virtualColumn.start}px) translateY(${virtualRow.start}px)`
|
|
4062
|
+
}, children: renderItem(virtualRow.index, virtualColumn.index) }, virtualColumn.key)) }, virtualRow.key)) }) });
|
|
4063
|
+
}
|
|
4064
|
+
function FolderView(props) {
|
|
4065
|
+
const { node, className, isDropTarget, containerProps, ...nodeProps } = props;
|
|
4066
|
+
const { t } = useTranslation();
|
|
4067
|
+
const folderNodes = node.children.filter((node2) => node2.kind === FOLDER).sort(sortUiNodesByName);
|
|
4068
|
+
const fileNodes = node.children.filter((node2) => node2.kind === FILE).sort(sortUiNodesByName);
|
|
4069
|
+
const folderCallbacks = {
|
|
4070
|
+
onSelectNode: (node2) => nodeProps.onSelectNode(node2),
|
|
4071
|
+
onRenameNode: (name, node2) => nodeProps.onRenameNode(name, node2),
|
|
4072
|
+
onDuplicateNode: (node2) => nodeProps.onDuplicateNode(node2),
|
|
4073
|
+
onDeleteNode: (node2) => nodeProps.onDeleteNode(node2)
|
|
4074
|
+
};
|
|
4075
|
+
const fileCallbacks = {
|
|
4076
|
+
onSelectNode: (node2) => nodeProps.onSelectNode(node2),
|
|
4077
|
+
onRenameNode: (name, node2) => nodeProps.onRenameNode(name, node2),
|
|
4078
|
+
onDuplicateNode: (node2) => nodeProps.onDuplicateNode(node2),
|
|
4079
|
+
onDeleteNode: (node2) => nodeProps.onDeleteNode(node2)
|
|
4080
|
+
};
|
|
4081
|
+
const baseNodeCallbacks = {
|
|
4082
|
+
onAddFile: async (file, parentNode) => {
|
|
4083
|
+
await nodeProps.onAddFile(file, parentNode);
|
|
4084
|
+
},
|
|
4085
|
+
onCopyNode: async (uiNode, targetNode) => {
|
|
4086
|
+
await nodeProps.onCopyNode(uiNode, targetNode);
|
|
4087
|
+
},
|
|
4088
|
+
onMoveNode: async (uiNode, targetNode) => {
|
|
4089
|
+
await nodeProps.onMoveNode(uiNode, targetNode);
|
|
4090
|
+
}
|
|
4091
|
+
};
|
|
4092
|
+
return jsxs("div", { className: twMerge("rounded-md border-2 border-transparent p-2", isDropTarget && "border-dashed border-blue-100", className), ...containerProps, children: [jsx(DriveLayout.ContentSection, { title: t("folderView.sections.folders.title", {
|
|
4093
|
+
defaultValue: "Folders"
|
|
4094
|
+
}), className: "mb-4", children: folderNodes.length > 0 ? folderNodes.map((folderNode) => jsx(FolderItem, { uiNode: folderNode, ...baseNodeCallbacks, ...folderCallbacks, isAllowedToCreateDocuments: nodeProps.isAllowedToCreateDocuments }, folderNode.id)) : jsx("div", { className: "mb-8 text-sm text-gray-400", children: t("folderView.sections.folders.empty", {
|
|
4095
|
+
defaultValue: "No documents or files 📄"
|
|
4096
|
+
}) }) }), jsx(DriveLayout.ContentSection, { title: t("folderView.sections.documents.title", {
|
|
4097
|
+
defaultValue: "Documents and files"
|
|
4098
|
+
}), children: jsx("div", { className: twMerge("w-full", fileNodes.length > 0 ? "min-h-[400px]" : "min-h-14"), children: jsx(FileContentView, { fileNodes, ...fileCallbacks, isAllowedToCreateDocuments: nodeProps.isAllowedToCreateDocuments }) }) })] });
|
|
4099
|
+
}
|
|
4100
|
+
function BaseEditor(props) {
|
|
4101
|
+
const { document: document2, dispatch, className, children } = props;
|
|
4102
|
+
const { id: driveId } = document2;
|
|
4103
|
+
const { showSearchBar, isAllowedToCreateDocuments, documentModels, showCreateDocumentModal } = useDriveContext();
|
|
4104
|
+
const { driveNodes, selectedNode, selectedNodePath, getNodeById, setSelectedNode } = useUiNodesContext();
|
|
4105
|
+
const driveNode = useMemo(() => driveNodes.find((n) => n.id === driveId), [driveNodes, driveId]);
|
|
4106
|
+
const { addDocument, addFile, addFolder: addFolder2, renameNode, deleteNode: deleteNode2, moveNode: moveNode2, copyNode: copyNode2, duplicateNode } = useDriveActionsWithUiNodes(document2, dispatch);
|
|
4107
|
+
const onCreateDocument = useCallback(async (documentModel) => {
|
|
4108
|
+
const { name } = await showCreateDocumentModal(documentModel);
|
|
4109
|
+
const document3 = documentModel.utils.createDocument();
|
|
4110
|
+
await addDocument(name, documentModel.documentModel.name, document3, selectedNode == null ? void 0 : selectedNode.id);
|
|
4111
|
+
}, [addDocument, showCreateDocumentModal, selectedNode == null ? void 0 : selectedNode.id]);
|
|
4112
|
+
const { isDropTarget, dropProps } = useDrop({
|
|
4113
|
+
uiNode: selectedNode,
|
|
4114
|
+
onAddFile: addFile,
|
|
4115
|
+
onCopyNode: copyNode2,
|
|
4116
|
+
onMoveNode: moveNode2
|
|
4117
|
+
});
|
|
4118
|
+
const { breadcrumbs, onBreadcrumbSelected } = useBreadcrumbs({
|
|
4119
|
+
selectedNodePath,
|
|
4120
|
+
getNodeById,
|
|
4121
|
+
setSelectedNode
|
|
4122
|
+
});
|
|
4123
|
+
if (!driveNode) {
|
|
4124
|
+
return jsx("div", { children: "Drive not found" });
|
|
4125
|
+
} else if ((selectedNode == null ? void 0 : selectedNode.kind) === FILE$1) {
|
|
4126
|
+
return jsx(Fragment$1, {});
|
|
4127
|
+
}
|
|
4128
|
+
return jsxs(DriveLayout, { className, children: [children, jsxs(DriveLayout.Header, { children: [jsx(Breadcrumbs, { breadcrumbs, createEnabled: isAllowedToCreateDocuments, onCreate: addFolder2, onBreadcrumbSelected }), showSearchBar && jsx(SearchBar, {})] }), jsx(DriveLayout.Content, { children: jsx(FolderView, { node: selectedNode || driveNode, onSelectNode: setSelectedNode, onRenameNode: renameNode, onDuplicateNode: duplicateNode, onDeleteNode: deleteNode2, onAddFile: addFile, onCopyNode: copyNode2, onMoveNode: moveNode2, isDropTarget, isAllowedToCreateDocuments }) }), jsx(DriveLayout.Footer, { children: isAllowedToCreateDocuments && jsx(CreateDocument, { documentModels, createDocument: onCreateDocument }) })] });
|
|
4129
|
+
}
|
|
4130
|
+
function Editor(props) {
|
|
4131
|
+
return jsx(DriveContextProvider, { value: props.context, children: jsx(BaseEditor, { ...props }) });
|
|
4132
|
+
}
|
|
4133
|
+
const GenericDriveExplorer = {
|
|
4134
|
+
Component: Editor,
|
|
4135
|
+
documentTypes: ["powerhouse/document-drive"],
|
|
4136
|
+
config: {
|
|
4137
|
+
id: "GenericDriveExplorer",
|
|
4138
|
+
disableExternalControls: true,
|
|
4139
|
+
documentToolbarEnabled: true,
|
|
4140
|
+
showSwitchboardLink: true
|
|
4141
|
+
}
|
|
4142
|
+
};
|
|
4143
|
+
function useAnalyticsQueryWrapper(options) {
|
|
4144
|
+
const { queryFn, ...queryOptions } = options;
|
|
4145
|
+
const store = useAnalyticsStore();
|
|
4146
|
+
const engine = useAnalyticsEngine();
|
|
4147
|
+
return useQuery({
|
|
4148
|
+
...queryOptions,
|
|
4149
|
+
queryFn: () => {
|
|
4150
|
+
if (!store || !engine) {
|
|
4151
|
+
throw new Error("No analytics store available. Use within an AnalyticsProvider.");
|
|
4152
|
+
}
|
|
4153
|
+
return queryFn({ store, engine });
|
|
4154
|
+
}
|
|
4155
|
+
});
|
|
4156
|
+
}
|
|
4157
|
+
function useAnalyticsQuery(query, options) {
|
|
4158
|
+
const store = useAnalyticsStore();
|
|
4159
|
+
const { data: querySources } = useQuerySources(query);
|
|
4160
|
+
const queryClient = useQueryClient();
|
|
4161
|
+
const subscriptions = useRef([]);
|
|
4162
|
+
const result = useAnalyticsQueryWrapper({
|
|
4163
|
+
queryKey: ["analytics", "query", query],
|
|
4164
|
+
queryFn: ({ engine }) => engine.execute(query),
|
|
4165
|
+
...options
|
|
4166
|
+
});
|
|
4167
|
+
useEffect(() => {
|
|
4168
|
+
if (!(querySources == null ? void 0 : querySources.length) || !store) {
|
|
4169
|
+
return;
|
|
4170
|
+
}
|
|
4171
|
+
querySources.forEach((source) => {
|
|
4172
|
+
const unsub = store.subscribeToSource(source, () => {
|
|
4173
|
+
return queryClient.invalidateQueries({
|
|
4174
|
+
queryKey: ["analytics", "query", query]
|
|
4175
|
+
});
|
|
4176
|
+
});
|
|
4177
|
+
subscriptions.current.push(unsub);
|
|
4178
|
+
});
|
|
4179
|
+
return () => {
|
|
4180
|
+
subscriptions.current.forEach((unsub) => unsub());
|
|
4181
|
+
subscriptions.current = [];
|
|
4182
|
+
};
|
|
4183
|
+
}, [querySources]);
|
|
4184
|
+
return result;
|
|
4185
|
+
}
|
|
4186
|
+
function useMatchingSeries(query, options) {
|
|
4187
|
+
const result = useAnalyticsQueryWrapper({
|
|
4188
|
+
queryKey: ["analytics", "matchingSeries", query],
|
|
4189
|
+
queryFn: ({ store }) => store.getMatchingSeries(query),
|
|
4190
|
+
...options
|
|
4191
|
+
});
|
|
4192
|
+
return result;
|
|
4193
|
+
}
|
|
4194
|
+
function useQuerySources(query, options) {
|
|
4195
|
+
const { data: matchingSeries } = useMatchingSeries(query);
|
|
4196
|
+
return useQuery({
|
|
4197
|
+
queryKey: ["analytics", "sources", query],
|
|
4198
|
+
queryFn: () => {
|
|
4199
|
+
if (!(matchingSeries == null ? void 0 : matchingSeries.length)) {
|
|
4200
|
+
return [];
|
|
4201
|
+
}
|
|
4202
|
+
const uniqueSources = [
|
|
4203
|
+
...new Set(matchingSeries.map((s) => s.source.toString()))
|
|
4204
|
+
];
|
|
4205
|
+
return uniqueSources.map((source) => AnalyticsPath.fromString(source));
|
|
4206
|
+
},
|
|
4207
|
+
enabled: !!matchingSeries,
|
|
4208
|
+
...options
|
|
4209
|
+
});
|
|
4210
|
+
}
|
|
4211
|
+
const getBarSize = (value) => {
|
|
4212
|
+
if (value <= 0)
|
|
4213
|
+
return 0;
|
|
4214
|
+
if (value > 0 && value <= 50)
|
|
4215
|
+
return 1;
|
|
4216
|
+
if (value > 50 && value <= 100)
|
|
4217
|
+
return 2;
|
|
4218
|
+
if (value > 100 && value <= 250)
|
|
4219
|
+
return 3;
|
|
4220
|
+
return 4;
|
|
4221
|
+
};
|
|
4222
|
+
const useTimelineItems = (documentId, startTimestamp) => {
|
|
4223
|
+
const start = startTimestamp ? DateTime.fromISO(startTimestamp) : DateTime.now().startOf("day");
|
|
4224
|
+
const { data: diffResult, isLoading } = useAnalyticsQuery({
|
|
4225
|
+
start,
|
|
4226
|
+
end: DateTime.now().endOf("day"),
|
|
4227
|
+
granularity: AnalyticsGranularity.Hourly,
|
|
4228
|
+
metrics: ["Count"],
|
|
4229
|
+
select: {
|
|
4230
|
+
changes: [AnalyticsPath.fromString(`changes`)],
|
|
4231
|
+
document: [AnalyticsPath.fromString(`document/${documentId}`)]
|
|
4232
|
+
},
|
|
4233
|
+
lod: {
|
|
4234
|
+
changes: 2
|
|
4235
|
+
},
|
|
4236
|
+
currency: AnalyticsPath.fromString("")
|
|
4237
|
+
});
|
|
4238
|
+
const mappedResult = useMemo(() => {
|
|
4239
|
+
if (!diffResult)
|
|
4240
|
+
return [];
|
|
4241
|
+
return diffResult.sort((a, b) => {
|
|
4242
|
+
const aDate = new Date(a.start);
|
|
4243
|
+
const bDate = new Date(b.start);
|
|
4244
|
+
return aDate.getTime() - bDate.getTime();
|
|
4245
|
+
}).filter((result) => {
|
|
4246
|
+
return result.rows.every((row) => row.value > 0);
|
|
4247
|
+
}).map((result) => {
|
|
4248
|
+
const { additions, deletions } = result.rows.reduce((acc, row) => {
|
|
4249
|
+
if (row.dimensions.changes.path === "changes/add") {
|
|
4250
|
+
acc.additions += row.value;
|
|
4251
|
+
} else if (row.dimensions.changes.path === "changes/remove") {
|
|
4252
|
+
acc.deletions += row.value;
|
|
4253
|
+
}
|
|
4254
|
+
return acc;
|
|
4255
|
+
}, { additions: 0, deletions: 0 });
|
|
4256
|
+
const startDate = new Date(result.start);
|
|
4257
|
+
return {
|
|
4258
|
+
id: startDate.toISOString(),
|
|
4259
|
+
type: "bar",
|
|
4260
|
+
addSize: getBarSize(additions),
|
|
4261
|
+
delSize: getBarSize(deletions),
|
|
4262
|
+
additions,
|
|
4263
|
+
deletions,
|
|
4264
|
+
timestamp: startDate.toISOString(),
|
|
4265
|
+
startDate,
|
|
4266
|
+
endDate: new Date(result.end),
|
|
4267
|
+
revision: 0
|
|
4268
|
+
};
|
|
4269
|
+
});
|
|
4270
|
+
}, [diffResult]);
|
|
4271
|
+
const resultWithDividers = useMemo(() => {
|
|
4272
|
+
if (!mappedResult.length)
|
|
4273
|
+
return [];
|
|
4274
|
+
const result = [];
|
|
4275
|
+
mappedResult.forEach((item, index) => {
|
|
4276
|
+
result.push(item);
|
|
4277
|
+
if (index < mappedResult.length - 1) {
|
|
4278
|
+
const currentDate = new Date(item.startDate);
|
|
4279
|
+
const nextDate = new Date(mappedResult[index + 1].startDate);
|
|
4280
|
+
const currentHour = currentDate.getHours();
|
|
4281
|
+
const nextHour = nextDate.getHours();
|
|
4282
|
+
const currentDay = currentDate.toDateString();
|
|
4283
|
+
const nextDay = nextDate.toDateString();
|
|
4284
|
+
if (currentDay !== nextDay || currentDay === nextDay && Math.abs(nextHour - currentHour) > 1) {
|
|
4285
|
+
result.push({
|
|
4286
|
+
id: `divider-${item.id}-${mappedResult[index + 1].id}`,
|
|
4287
|
+
type: "divider",
|
|
4288
|
+
revision: 0
|
|
4289
|
+
});
|
|
4290
|
+
}
|
|
4291
|
+
}
|
|
4292
|
+
});
|
|
4293
|
+
return result;
|
|
4294
|
+
}, [mappedResult]);
|
|
4295
|
+
return {
|
|
4296
|
+
isLoading,
|
|
4297
|
+
data: resultWithDividers
|
|
4298
|
+
};
|
|
4299
|
+
};
|
|
4300
|
+
const getRevisionFromDate = (startDate, endDate, operations = []) => {
|
|
4301
|
+
if (!startDate || !endDate)
|
|
4302
|
+
return 0;
|
|
4303
|
+
const operation = operations.find((operation2) => {
|
|
4304
|
+
const operationDate = new Date(operation2.timestamp);
|
|
4305
|
+
return operationDate >= startDate && operationDate <= endDate;
|
|
4306
|
+
});
|
|
4307
|
+
return operation ? operation.index : 0;
|
|
4308
|
+
};
|
|
4309
|
+
function EditorLoader(props) {
|
|
4310
|
+
const [showLoading, setShowLoading] = useState(false);
|
|
3564
4311
|
useEffect(() => {
|
|
3565
4312
|
setTimeout(() => {
|
|
3566
4313
|
setShowLoading(true);
|
|
@@ -3586,9 +4333,11 @@ const DocumentEditor = (props) => {
|
|
|
3586
4333
|
onChange,
|
|
3587
4334
|
onExport,
|
|
3588
4335
|
onAddOperation,
|
|
4336
|
+
onGetDocumentRevision,
|
|
3589
4337
|
onOpenSwitchboardLink
|
|
3590
4338
|
} = props;
|
|
3591
4339
|
const documentId = fileNodeDocument == null ? void 0 : fileNodeDocument.documentId;
|
|
4340
|
+
const [selectedTimelineItem, setSelectedTimelineItem] = useState(null);
|
|
3592
4341
|
const [revisionHistoryVisible, setRevisionHistoryVisible] = useState(false);
|
|
3593
4342
|
const theme = useAtomValue(themeAtom);
|
|
3594
4343
|
const user = useUser() || void 0;
|
|
@@ -3614,6 +4363,10 @@ const DocumentEditor = (props) => {
|
|
|
3614
4363
|
[theme, user]
|
|
3615
4364
|
);
|
|
3616
4365
|
const userPermissions = useUserPermissions$1();
|
|
4366
|
+
const timelineItems = useTimelineItems(
|
|
4367
|
+
documentId,
|
|
4368
|
+
initialDocument == null ? void 0 : initialDocument.created
|
|
4369
|
+
);
|
|
3617
4370
|
const currentDocument = useRef({ ...fileNodeDocument, document: document2 });
|
|
3618
4371
|
useEffect(() => {
|
|
3619
4372
|
var _a;
|
|
@@ -3790,7 +4543,8 @@ const DocumentEditor = (props) => {
|
|
|
3790
4543
|
const {
|
|
3791
4544
|
disableExternalControls,
|
|
3792
4545
|
documentToolbarEnabled,
|
|
3793
|
-
showSwitchboardLink
|
|
4546
|
+
showSwitchboardLink,
|
|
4547
|
+
timelineEnabled
|
|
3794
4548
|
} = editor.config || {};
|
|
3795
4549
|
const handleSwitchboardLinkClick = showSwitchboardLink !== false ? onOpenSwitchboardLink : void 0;
|
|
3796
4550
|
return /* @__PURE__ */ jsxs("div", { className: "relative h-full", id: "document-editor-context", children: [
|
|
@@ -3801,7 +4555,10 @@ const DocumentEditor = (props) => {
|
|
|
3801
4555
|
onExport,
|
|
3802
4556
|
onShowRevisionHistory: showRevisionHistory,
|
|
3803
4557
|
title: fileNodeDocument.name || document2.name,
|
|
3804
|
-
onSwitchboardLinkClick: handleSwitchboardLinkClick
|
|
4558
|
+
onSwitchboardLinkClick: handleSwitchboardLinkClick,
|
|
4559
|
+
timelineButtonVisible: timelineEnabled,
|
|
4560
|
+
timelineItems: timelineItems.data,
|
|
4561
|
+
onTimelineItemClick: setSelectedTimelineItem
|
|
3805
4562
|
}
|
|
3806
4563
|
),
|
|
3807
4564
|
!disableExternalControls && /* @__PURE__ */ jsxs("div", { className: "mb-4 flex justify-end gap-10", children: [
|
|
@@ -3831,7 +4588,16 @@ const DocumentEditor = (props) => {
|
|
|
3831
4588
|
EditorComponent,
|
|
3832
4589
|
{
|
|
3833
4590
|
error,
|
|
3834
|
-
context
|
|
4591
|
+
context: {
|
|
4592
|
+
...context,
|
|
4593
|
+
getDocumentRevision: onGetDocumentRevision,
|
|
4594
|
+
readMode: !!selectedTimelineItem,
|
|
4595
|
+
selectedTimelineRevision: getRevisionFromDate(
|
|
4596
|
+
selectedTimelineItem == null ? void 0 : selectedTimelineItem.startDate,
|
|
4597
|
+
selectedTimelineItem == null ? void 0 : selectedTimelineItem.endDate,
|
|
4598
|
+
document2.operations.global
|
|
4599
|
+
)
|
|
4600
|
+
},
|
|
3835
4601
|
document: document2,
|
|
3836
4602
|
documentNodeName: fileNodeDocument.name,
|
|
3837
4603
|
dispatch,
|
|
@@ -3869,6 +4635,7 @@ function DocumentEditorContainer() {
|
|
|
3869
4635
|
renameNode,
|
|
3870
4636
|
getDocumentModelModule
|
|
3871
4637
|
} = useUiNodes();
|
|
4638
|
+
const getDocument = useGetDocument();
|
|
3872
4639
|
const handleAddOperationToSelectedDocument = useCallback(
|
|
3873
4640
|
async (operation) => {
|
|
3874
4641
|
if (!selectedDocument) {
|
|
@@ -3931,6 +4698,20 @@ function DocumentEditorContainer() {
|
|
|
3931
4698
|
},
|
|
3932
4699
|
[getDocumentModelModule, showModal, t]
|
|
3933
4700
|
);
|
|
4701
|
+
const onGetDocumentRevision = useCallback(
|
|
4702
|
+
(options) => {
|
|
4703
|
+
if (!selectedNode) {
|
|
4704
|
+
console.error("No selected node");
|
|
4705
|
+
return Promise.reject(new Error("No selected node"));
|
|
4706
|
+
}
|
|
4707
|
+
return getDocument(
|
|
4708
|
+
selectedNode.driveId,
|
|
4709
|
+
selectedNode.id,
|
|
4710
|
+
options
|
|
4711
|
+
);
|
|
4712
|
+
},
|
|
4713
|
+
[getDocument, selectedNode]
|
|
4714
|
+
);
|
|
3934
4715
|
const onExport = useCallback(() => {
|
|
3935
4716
|
if (selectedDocument) {
|
|
3936
4717
|
return exportDocument(selectedDocument);
|
|
@@ -3952,6 +4733,7 @@ function DocumentEditorContainer() {
|
|
|
3952
4733
|
onChange: onDocumentChangeHandler,
|
|
3953
4734
|
onClose,
|
|
3954
4735
|
onExport,
|
|
4736
|
+
onGetDocumentRevision,
|
|
3955
4737
|
onAddOperation: handleAddOperationToSelectedDocument,
|
|
3956
4738
|
onOpenSwitchboardLink
|
|
3957
4739
|
}
|
|
@@ -3960,165 +4742,6 @@ function DocumentEditorContainer() {
|
|
|
3960
4742
|
fileNodeDocument.documentId
|
|
3961
4743
|
);
|
|
3962
4744
|
}
|
|
3963
|
-
function getDocumentSpec(doc) {
|
|
3964
|
-
if ("documentModelState" in doc) {
|
|
3965
|
-
return doc.documentModelState;
|
|
3966
|
-
}
|
|
3967
|
-
return doc.documentModel;
|
|
3968
|
-
}
|
|
3969
|
-
const CreateDocument = ({ documentModels, createDocument }) => {
|
|
3970
|
-
return jsxs("div", { className: "px-6", children: [jsx("h3", { className: "mb-3 mt-4 text-xl font-bold text-gray-600", children: "New document" }), jsx("div", { className: "flex w-full flex-wrap gap-4", children: documentModels == null ? void 0 : documentModels.map((doc) => {
|
|
3971
|
-
const spec = getDocumentSpec(doc);
|
|
3972
|
-
return jsx(Button, { color: "light", "aria-details": spec.description, onClick: () => createDocument(doc), children: jsx("span", { className: "text-sm", children: spec.name }) }, spec.id);
|
|
3973
|
-
}) })] });
|
|
3974
|
-
};
|
|
3975
|
-
function sortUiNodesByName(a, b) {
|
|
3976
|
-
return a.name.localeCompare(b.name);
|
|
3977
|
-
}
|
|
3978
|
-
const GAP = 8;
|
|
3979
|
-
const ITEM_WIDTH = 256;
|
|
3980
|
-
const ITEM_HEIGHT = 48;
|
|
3981
|
-
const USED_SPACE = 420;
|
|
3982
|
-
function FileContentView(props) {
|
|
3983
|
-
const parentRef = useRef(null);
|
|
3984
|
-
const { t } = useTranslation();
|
|
3985
|
-
const windowSize = useWindowSize();
|
|
3986
|
-
const { fileNodes, ...fileProps } = props;
|
|
3987
|
-
const availableWidth = windowSize.innerWidth - USED_SPACE;
|
|
3988
|
-
const columnCount = Math.floor(availableWidth / (ITEM_WIDTH + GAP)) || 1;
|
|
3989
|
-
const rowCount = Math.ceil(fileNodes.length / columnCount);
|
|
3990
|
-
const rowVirtualizer = useVirtualizer({
|
|
3991
|
-
count: rowCount,
|
|
3992
|
-
getScrollElement: () => parentRef.current,
|
|
3993
|
-
estimateSize: (index) => {
|
|
3994
|
-
if (index > 0) {
|
|
3995
|
-
return ITEM_HEIGHT + GAP;
|
|
3996
|
-
}
|
|
3997
|
-
return ITEM_HEIGHT;
|
|
3998
|
-
},
|
|
3999
|
-
overscan: 5
|
|
4000
|
-
});
|
|
4001
|
-
const columnVirtualizer = useVirtualizer({
|
|
4002
|
-
horizontal: true,
|
|
4003
|
-
count: columnCount,
|
|
4004
|
-
getScrollElement: () => parentRef.current,
|
|
4005
|
-
estimateSize: (index) => {
|
|
4006
|
-
if (index > 0) {
|
|
4007
|
-
return ITEM_WIDTH + GAP;
|
|
4008
|
-
}
|
|
4009
|
-
return ITEM_WIDTH;
|
|
4010
|
-
},
|
|
4011
|
-
overscan: 5
|
|
4012
|
-
});
|
|
4013
|
-
const getItemIndex = (rowIndex, columnIndex) => rowIndex * columnCount + columnIndex;
|
|
4014
|
-
const getItem = (rowIndex, columnIndex) => {
|
|
4015
|
-
const index = getItemIndex(rowIndex, columnIndex);
|
|
4016
|
-
return fileNodes[index] || null;
|
|
4017
|
-
};
|
|
4018
|
-
if (fileNodes.length === 0) {
|
|
4019
|
-
return jsx("div", { className: "mb-8 text-sm text-gray-400", children: t("folderView.sections.documents.empty", {
|
|
4020
|
-
defaultValue: "No documents or files 📄"
|
|
4021
|
-
}) });
|
|
4022
|
-
}
|
|
4023
|
-
const renderItem = (rowIndex, columnIndex) => {
|
|
4024
|
-
const fileNode = getItem(rowIndex, columnIndex);
|
|
4025
|
-
if (!fileNode) {
|
|
4026
|
-
return null;
|
|
4027
|
-
}
|
|
4028
|
-
return jsx("div", { style: {
|
|
4029
|
-
marginLeft: columnIndex === 0 ? 0 : GAP
|
|
4030
|
-
}, children: jsx(FileItem, { uiNode: fileNode, ...fileProps }, fileNode.id) });
|
|
4031
|
-
};
|
|
4032
|
-
return jsx("div", { ref: parentRef, style: {
|
|
4033
|
-
height: `400px`,
|
|
4034
|
-
width: `100%`,
|
|
4035
|
-
overflow: "auto"
|
|
4036
|
-
}, children: jsx("div", { style: {
|
|
4037
|
-
height: `${rowVirtualizer.getTotalSize()}px`,
|
|
4038
|
-
width: `${columnVirtualizer.getTotalSize()}px`,
|
|
4039
|
-
position: "relative"
|
|
4040
|
-
}, children: rowVirtualizer.getVirtualItems().map((virtualRow) => jsx(React__default.Fragment, { children: columnVirtualizer.getVirtualItems().map((virtualColumn) => jsx("div", { style: {
|
|
4041
|
-
position: "absolute",
|
|
4042
|
-
top: 0,
|
|
4043
|
-
left: 0,
|
|
4044
|
-
marginTop: virtualRow.index === 0 ? 0 : GAP,
|
|
4045
|
-
width: `${virtualColumn.size}px`,
|
|
4046
|
-
height: `${virtualRow.size}px`,
|
|
4047
|
-
transform: `translateX(${virtualColumn.start}px) translateY(${virtualRow.start}px)`
|
|
4048
|
-
}, children: renderItem(virtualRow.index, virtualColumn.index) }, virtualColumn.key)) }, virtualRow.key)) }) });
|
|
4049
|
-
}
|
|
4050
|
-
function FolderView(props) {
|
|
4051
|
-
const { node, className, isDropTarget, containerProps, ...nodeProps } = props;
|
|
4052
|
-
const { t } = useTranslation();
|
|
4053
|
-
const folderNodes = node.children.filter((node2) => node2.kind === FOLDER).sort(sortUiNodesByName);
|
|
4054
|
-
const fileNodes = node.children.filter((node2) => node2.kind === FILE).sort(sortUiNodesByName);
|
|
4055
|
-
const folderCallbacks = {
|
|
4056
|
-
onSelectNode: (node2) => nodeProps.onSelectNode(node2),
|
|
4057
|
-
onRenameNode: (name, node2) => nodeProps.onRenameNode(name, node2),
|
|
4058
|
-
onDuplicateNode: (node2) => nodeProps.onDuplicateNode(node2),
|
|
4059
|
-
onDeleteNode: (node2) => nodeProps.onDeleteNode(node2)
|
|
4060
|
-
};
|
|
4061
|
-
const fileCallbacks = {
|
|
4062
|
-
onSelectNode: (node2) => nodeProps.onSelectNode(node2),
|
|
4063
|
-
onRenameNode: (name, node2) => nodeProps.onRenameNode(name, node2),
|
|
4064
|
-
onDuplicateNode: (node2) => nodeProps.onDuplicateNode(node2),
|
|
4065
|
-
onDeleteNode: (node2) => nodeProps.onDeleteNode(node2)
|
|
4066
|
-
};
|
|
4067
|
-
const baseNodeCallbacks = {
|
|
4068
|
-
onAddFile: async (file, parentNode) => {
|
|
4069
|
-
await nodeProps.onAddFile(file, parentNode);
|
|
4070
|
-
},
|
|
4071
|
-
onCopyNode: async (uiNode, targetNode) => {
|
|
4072
|
-
await nodeProps.onCopyNode(uiNode, targetNode);
|
|
4073
|
-
},
|
|
4074
|
-
onMoveNode: async (uiNode, targetNode) => {
|
|
4075
|
-
await nodeProps.onMoveNode(uiNode, targetNode);
|
|
4076
|
-
}
|
|
4077
|
-
};
|
|
4078
|
-
return jsxs("div", { className: twMerge("rounded-md border-2 border-transparent p-2", isDropTarget && "border-dashed border-blue-100", className), ...containerProps, children: [jsx(DriveLayout.ContentSection, { title: t("folderView.sections.folders.title", {
|
|
4079
|
-
defaultValue: "Folders"
|
|
4080
|
-
}), className: "mb-4", children: folderNodes.length > 0 ? folderNodes.map((folderNode) => jsx(FolderItem, { uiNode: folderNode, ...baseNodeCallbacks, ...folderCallbacks, isAllowedToCreateDocuments: nodeProps.isAllowedToCreateDocuments }, folderNode.id)) : jsx("div", { className: "mb-8 text-sm text-gray-400", children: t("folderView.sections.folders.empty", {
|
|
4081
|
-
defaultValue: "No documents or files 📄"
|
|
4082
|
-
}) }) }), jsx(DriveLayout.ContentSection, { title: t("folderView.sections.documents.title", {
|
|
4083
|
-
defaultValue: "Documents and files"
|
|
4084
|
-
}), children: jsx("div", { className: twMerge("w-full", fileNodes.length > 0 ? "min-h-[400px]" : "min-h-14"), children: jsx(FileContentView, { fileNodes, ...fileCallbacks, isAllowedToCreateDocuments: nodeProps.isAllowedToCreateDocuments }) }) })] });
|
|
4085
|
-
}
|
|
4086
|
-
function BaseEditor(props) {
|
|
4087
|
-
const { document: document2, dispatch, className, children } = props;
|
|
4088
|
-
const { state: { global: { id: driveId } } } = document2;
|
|
4089
|
-
const { showSearchBar, isAllowedToCreateDocuments, documentModels, showCreateDocumentModal } = useDriveContext();
|
|
4090
|
-
const { driveNodes, selectedNode, selectedNodePath, getNodeById, setSelectedNode } = useUiNodesContext();
|
|
4091
|
-
const driveNode = useMemo(() => driveNodes.find((n) => n.id === driveId), [driveNodes, driveId]);
|
|
4092
|
-
const { addDocument, addFile, addFolder: addFolder2, renameNode, deleteNode: deleteNode2, moveNode: moveNode2, copyNode: copyNode2, duplicateNode } = useDriveActionsWithUiNodes(document2, dispatch);
|
|
4093
|
-
const onCreateDocument = useCallback(async (documentModel) => {
|
|
4094
|
-
const { name } = await showCreateDocumentModal(documentModel);
|
|
4095
|
-
const document3 = documentModel.utils.createDocument();
|
|
4096
|
-
await addDocument(name, documentModel.documentModel.name, document3, selectedNode == null ? void 0 : selectedNode.id);
|
|
4097
|
-
}, [addDocument, showCreateDocumentModal, selectedNode == null ? void 0 : selectedNode.id]);
|
|
4098
|
-
const { isDropTarget, dropProps } = useDrop({
|
|
4099
|
-
uiNode: selectedNode,
|
|
4100
|
-
onAddFile: addFile,
|
|
4101
|
-
onCopyNode: copyNode2,
|
|
4102
|
-
onMoveNode: moveNode2
|
|
4103
|
-
});
|
|
4104
|
-
const { breadcrumbs, onBreadcrumbSelected } = useBreadcrumbs({
|
|
4105
|
-
selectedNodePath,
|
|
4106
|
-
getNodeById,
|
|
4107
|
-
setSelectedNode
|
|
4108
|
-
});
|
|
4109
|
-
if (!driveNode) {
|
|
4110
|
-
return jsx("div", { children: "Drive not found" });
|
|
4111
|
-
} else if ((selectedNode == null ? void 0 : selectedNode.kind) === FILE$1) {
|
|
4112
|
-
return jsx(Fragment$1, {});
|
|
4113
|
-
}
|
|
4114
|
-
return jsxs(DriveLayout, { className, children: [children, jsxs(DriveLayout.Header, { children: [jsx(Breadcrumbs, { breadcrumbs, createEnabled: isAllowedToCreateDocuments, onCreate: addFolder2, onBreadcrumbSelected }), showSearchBar && jsx(SearchBar, {})] }), jsx(DriveLayout.Content, { children: jsx(FolderView, { node: selectedNode || driveNode, onSelectNode: setSelectedNode, onRenameNode: renameNode, onDuplicateNode: duplicateNode, onDeleteNode: deleteNode2, onAddFile: addFile, onCopyNode: copyNode2, onMoveNode: moveNode2, isDropTarget, isAllowedToCreateDocuments }) }), jsx(DriveLayout.Footer, { children: isAllowedToCreateDocuments && jsx(CreateDocument, { documentModels, createDocument: onCreateDocument }) })] });
|
|
4115
|
-
}
|
|
4116
|
-
function Editor(props) {
|
|
4117
|
-
return jsx(DriveContextProvider, { value: props.context, children: jsx(BaseEditor, { ...props }) });
|
|
4118
|
-
}
|
|
4119
|
-
const GenericDriveExplorer = {
|
|
4120
|
-
Component: Editor
|
|
4121
|
-
};
|
|
4122
4745
|
function useDocumentsState(args) {
|
|
4123
4746
|
const { reactor, driveId, documentIds, options } = args;
|
|
4124
4747
|
const [statesByDocumentId, setStatesByDocumentId] = useState({});
|
|
@@ -4305,8 +4928,19 @@ function DriveEditorContainer() {
|
|
|
4305
4928
|
const { addFile, addDocument } = useDocumentDriveServer();
|
|
4306
4929
|
const documentModels = useFilteredDocumentModels();
|
|
4307
4930
|
const useDriveDocumentState = makeDriveDocumentStateHook(reactor);
|
|
4931
|
+
const getDocument = useGetDocument();
|
|
4308
4932
|
const getDocumentModelModule = useGetDocumentModelModule();
|
|
4309
4933
|
const getEditor = useGetEditor();
|
|
4934
|
+
const onGetDocumentRevision = useCallback(
|
|
4935
|
+
(documentId, options) => {
|
|
4936
|
+
if (!selectedNode) {
|
|
4937
|
+
console.error("No selected node");
|
|
4938
|
+
return Promise.reject(new Error("No selected node"));
|
|
4939
|
+
}
|
|
4940
|
+
return getDocument(selectedNode.driveId, documentId, options);
|
|
4941
|
+
},
|
|
4942
|
+
[getDocument, selectedNode]
|
|
4943
|
+
);
|
|
4310
4944
|
const driveContext = useMemo(
|
|
4311
4945
|
() => ({
|
|
4312
4946
|
showSearchBar: false,
|
|
@@ -4350,6 +4984,8 @@ function DriveEditorContainer() {
|
|
|
4350
4984
|
context: {
|
|
4351
4985
|
...editorProps.context,
|
|
4352
4986
|
...driveContext,
|
|
4987
|
+
analyticsDatabaseName: connectConfig.analyticsDatabaseName,
|
|
4988
|
+
getDocumentRevision: onGetDocumentRevision,
|
|
4353
4989
|
getDocumentModelModule,
|
|
4354
4990
|
getEditor
|
|
4355
4991
|
},
|
|
@@ -4385,7 +5021,7 @@ function Content() {
|
|
|
4385
5021
|
}, [selectedDriveNode, selectedNode, addFile]);
|
|
4386
5022
|
useEffect(() => {
|
|
4387
5023
|
if ((status === "LOADED" || status === "ERROR") && !documentDrives.find(
|
|
4388
|
-
(d) => d.
|
|
5024
|
+
(d) => d.id === driveId || d.slug === driveId || d.state.global.name === driveId
|
|
4389
5025
|
)) {
|
|
4390
5026
|
toast(/* @__PURE__ */ jsxs("p", { children: [
|
|
4391
5027
|
"Drive ",
|
|
@@ -4400,3 +5036,4 @@ function Content() {
|
|
|
4400
5036
|
export {
|
|
4401
5037
|
Content as default
|
|
4402
5038
|
};
|
|
5039
|
+
//# sourceMappingURL=content-C_bg7acW.js.map
|