@powerhousedao/connect 1.0.24-dev.0 → 1.1.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-DWlDE8AF.css → app-Dtx0nq4m.css} +181 -240
- package/dist/assets/{app-B5yYl0zv.js → app-SJyv410V.js} +33037 -34663
- package/dist/assets/{app-loader-NDVZu4bS.css → app-loader-3ipafc56.css} +228 -238
- package/dist/assets/{app-loader-CmEZOj3m.js → app-loader-BsJCIY3v.js} +417 -735
- package/dist/assets/{ccip-KtRjx9vh.js → ccip-CWiYf37C.js} +8 -6
- package/dist/assets/{content-2lJzkjLx.js → content-DrqtiFBt.js} +456 -1094
- package/dist/assets/{index-BVVRVlZN.js → index-CS0mQFrd.js} +3 -4
- package/dist/assets/{index-BhHOiwFw.js → index-DFoYtrS6.js} +3693 -3516
- package/dist/assets/{index-dSMCpjcQ.js → index-n2OSuQ3g.js} +171 -23
- package/dist/assets/{main.DA6nl4Ov.js → main.BcxEuVs0.js} +12 -3
- package/dist/assets/{style-CdxGKc2g.css → style-0ej1afQi.css} +95 -39
- package/dist/external-packages.js +0 -1
- package/dist/hmr.js +0 -1
- package/dist/index.html +1 -1
- package/dist/service-worker.js +0 -1
- package/dist/vite-envs.sh +1 -1
- package/package.json +20 -21
- package/dist/assets/app-B5yYl0zv.js.map +0 -1
- package/dist/assets/app-loader-CmEZOj3m.js.map +0 -1
- package/dist/assets/browser-D5LEpLBa.js +0 -27224
- package/dist/assets/browser-D5LEpLBa.js.map +0 -1
- package/dist/assets/ccip-KtRjx9vh.js.map +0 -1
- package/dist/assets/content-2lJzkjLx.js.map +0 -1
- package/dist/assets/index-BVVRVlZN.js.map +0 -1
- package/dist/assets/index-BhHOiwFw.js.map +0 -1
- package/dist/assets/index-DZiF5od7.js +0 -208
- package/dist/assets/index-DZiF5od7.js.map +0 -1
- package/dist/assets/index-dSMCpjcQ.js.map +0 -1
- package/dist/assets/main.DA6nl4Ov.js.map +0 -1
- package/dist/assets/reactor-analytics-CF_JKt8H.js +0 -42
- package/dist/assets/reactor-analytics-CF_JKt8H.js.map +0 -1
- package/dist/assets/router-Ch1WZD-6.js +0 -1585
- package/dist/assets/router-Ch1WZD-6.js.map +0 -1
- package/dist/external-packages.js.map +0 -1
- package/dist/hmr.js.map +0 -1
- package/dist/service-worker.js.map +0 -1
|
@@ -1,11 +1,10 @@
|
|
|
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, m as mergeClassNameProps, E as ERROR, M as MISSING, C as CONFLICT, S as SUCCESS, k as SYNCING, I as INITIAL_SYNC, l as ConnectDropdownMenu, u as useOnClickOutside, n as useEventListener, o as useCopyToClipboard, p as Select, q as ENSAvatar, P as Provider, v as Root3, T as Trigger, w as Portal, x as Content2, y as validateInitialState, z as validateStateSchemaName, A as validateModules, D as useDocumentDrives, F as useUiNodesContext, G as useDriveContext, H as FILE$1, J as useUnwrappedReactor, K as useConnectDid, L as useConnectCrypto, N as useTranslation, O as useModal, Q as useAtomValue, U as themeAtom, V as useUser, W as useUserPermissions$1, X as useUiNodes, Y as exportFile, Z as useGetDocumentModelModule, _ as addActionContext$1, $ as signOperation$1, a0 as useDocumentDriveServer, a1 as useHotkeys, a2 as useGetEditor, a3 as isSameDocument, a4 as useNavigate, a5 as ErrorBoundary, a6 as DriveLayout, a7 as DriveContextProvider, a8 as SearchBar, a9 as useAsyncReactor, aa as useFilteredDocumentModels, ab as useDriveEditor, ac as useDocumentDriveById, ad as useParams, ae as useDocumentDrives$1, af as toast } from "./app-SJyv410V.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 {
|
|
6
|
-
import { E as ENSAvatar, a as ErrorBoundary } from "./router-Ch1WZD-6.js";
|
|
5
|
+
import { _ as Icon, aX as getDimensions, aY as READ, aZ as nodeOptionsMap, a_ as defaultFileOptions, a$ as DELETE, b0 as RENAME, b1 as WRITE, b2 as DUPLICATE, b3 as defaultFolderOptions, b4 as garbageCollect, b5 as sortOperations, b6 as UI_NODE, aP as DRIVE, az as FILE, ae as buildSignedOperation, b7 as generateId$1, aw as isFolderNode, aB as generateNodesCopy, aC as copyNode, aA as moveNode, ay as updateNode, ax as deleteNode, ar as generateAddNodeAction, as as isFileNode, av as addFolder, b8 as undo, b9 as redo, ac as logger, ba as useDocumentDispatch$1, aQ as FOLDER, al as driveDocumentModelModule } from "./app-loader-BsJCIY3v.js";
|
|
7
6
|
import { flushSync } from "react-dom";
|
|
8
|
-
import "./main.
|
|
7
|
+
import "./main.BcxEuVs0.js";
|
|
9
8
|
const PaginationButton = ({ active = false, ...props }) => {
|
|
10
9
|
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");
|
|
11
10
|
return jsx(Button, { color: "light", size: "small", ...mergeClassNameProps(props, className), children: props.children });
|
|
@@ -15,7 +14,7 @@ const Pagination = (props) => {
|
|
|
15
14
|
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] });
|
|
16
15
|
};
|
|
17
16
|
function usePagination(items, options) {
|
|
18
|
-
const { itemsPerPage = 20, initialPage = 0, pageRange = 3 } = options;
|
|
17
|
+
const { itemsPerPage = 20, initialPage = 0, pageRange = 3 } = options || {};
|
|
19
18
|
const [currentPage, setCurrentPage] = useState(initialPage);
|
|
20
19
|
const pageCount = Math.ceil(items.length / itemsPerPage);
|
|
21
20
|
const isNextPageAvailable = currentPage < pageCount - 1;
|
|
@@ -152,12 +151,131 @@ function DefaultEditorLoader(props) {
|
|
|
152
151
|
const { message: message2 = "Loading editor", ...divProps } = props;
|
|
153
152
|
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, {})] }) });
|
|
154
153
|
}
|
|
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
|
+
}
|
|
155
277
|
const millisecondsInWeek = 6048e5;
|
|
156
278
|
const millisecondsInDay = 864e5;
|
|
157
|
-
const millisecondsInMinute = 6e4;
|
|
158
|
-
const millisecondsInHour = 36e5;
|
|
159
|
-
const minutesInMonth = 43200;
|
|
160
|
-
const minutesInDay = 1440;
|
|
161
279
|
const constructFromSymbol = Symbol.for("constructDateFrom");
|
|
162
280
|
function constructFrom(date, value) {
|
|
163
281
|
if (typeof date === "function") return date(value);
|
|
@@ -225,7 +343,7 @@ function getTimezoneOffsetInMilliseconds(date) {
|
|
|
225
343
|
function normalizeDates(context, ...dates) {
|
|
226
344
|
const normalize = constructFrom.bind(
|
|
227
345
|
null,
|
|
228
|
-
|
|
346
|
+
dates.find((date) => typeof date === "object")
|
|
229
347
|
);
|
|
230
348
|
return dates.map(normalize);
|
|
231
349
|
}
|
|
@@ -253,83 +371,12 @@ function startOfISOWeekYear(date, options) {
|
|
|
253
371
|
fourthOfJanuary.setHours(0, 0, 0, 0);
|
|
254
372
|
return startOfISOWeek(fourthOfJanuary);
|
|
255
373
|
}
|
|
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
|
-
}
|
|
265
374
|
function isDate(value) {
|
|
266
375
|
return value instanceof Date || typeof value === "object" && Object.prototype.toString.call(value) === "[object Date]";
|
|
267
376
|
}
|
|
268
377
|
function isValid(date) {
|
|
269
378
|
return !(!isDate(date) && typeof date !== "number" || isNaN(+toDate(date)));
|
|
270
379
|
}
|
|
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
|
-
}
|
|
333
380
|
function startOfYear(date, options) {
|
|
334
381
|
const date_ = toDate(date, options == null ? void 0 : options.in);
|
|
335
382
|
date_.setFullYear(date_.getFullYear(), 0, 1);
|
|
@@ -399,7 +446,7 @@ const formatDistanceLocale = {
|
|
|
399
446
|
other: "almost {{count}} years"
|
|
400
447
|
}
|
|
401
448
|
};
|
|
402
|
-
const formatDistance
|
|
449
|
+
const formatDistance = (token, count, options) => {
|
|
403
450
|
let result;
|
|
404
451
|
const tokenValue = formatDistanceLocale[token];
|
|
405
452
|
if (typeof tokenValue === "string") {
|
|
@@ -815,7 +862,7 @@ const match = {
|
|
|
815
862
|
};
|
|
816
863
|
const enUS = {
|
|
817
864
|
code: "en-US",
|
|
818
|
-
formatDistance
|
|
865
|
+
formatDistance,
|
|
819
866
|
formatLong,
|
|
820
867
|
formatRelative,
|
|
821
868
|
localize,
|
|
@@ -938,8 +985,6 @@ const lightFormatters = {
|
|
|
938
985
|
}
|
|
939
986
|
};
|
|
940
987
|
const dayPeriodEnum = {
|
|
941
|
-
am: "am",
|
|
942
|
-
pm: "pm",
|
|
943
988
|
midnight: "midnight",
|
|
944
989
|
noon: "noon",
|
|
945
990
|
morning: "morning",
|
|
@@ -1719,572 +1764,73 @@ function cleanEscapedString(input) {
|
|
|
1719
1764
|
}
|
|
1720
1765
|
return matched[1].replace(doubleQuoteRegExp, "'");
|
|
1721
1766
|
}
|
|
1722
|
-
function
|
|
1723
|
-
const
|
|
1724
|
-
const
|
|
1725
|
-
const
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
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
|
-
}
|
|
1761
|
-
}
|
|
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);
|
|
1791
|
-
}
|
|
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
|
-
);
|
|
1861
|
-
}
|
|
1862
|
-
}
|
|
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;
|
|
1767
|
+
function NodeInput(props) {
|
|
1768
|
+
const { onSubmit, onCancel, defaultValue, className, minLength = 1, ...inputProps } = props;
|
|
1769
|
+
const [value, setValue] = useState(defaultValue ?? "");
|
|
1770
|
+
const ref = useRef(null);
|
|
1771
|
+
useOnClickOutside(ref, handleSubmit);
|
|
1772
|
+
useEventListener("keyup", (e) => {
|
|
1773
|
+
if (e.key === "Enter") {
|
|
1774
|
+
handleSubmit();
|
|
1870
1775
|
}
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
}
|
|
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
|
-
};
|
|
1886
|
-
}
|
|
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);
|
|
1776
|
+
if (e.key === "Escape") {
|
|
1777
|
+
onCancel();
|
|
1900
1778
|
}
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1779
|
+
});
|
|
1780
|
+
useLayoutEffect(() => {
|
|
1781
|
+
setTimeout(() => {
|
|
1782
|
+
var _a, _b, _c;
|
|
1783
|
+
(_a = ref.current) == null ? void 0 : _a.focus();
|
|
1784
|
+
(_b = ref.current) == null ? void 0 : _b.select();
|
|
1785
|
+
(_c = ref.current) == null ? void 0 : _c.scroll({ left: 9999 });
|
|
1786
|
+
}, 100);
|
|
1787
|
+
}, []);
|
|
1788
|
+
function handleSubmit() {
|
|
1789
|
+
if (value.length >= minLength) {
|
|
1790
|
+
onSubmit(value);
|
|
1906
1791
|
}
|
|
1907
|
-
date.setUTCFullYear(year, month, Math.max(dayOfYear, day));
|
|
1908
|
-
return date;
|
|
1909
|
-
}
|
|
1910
|
-
}
|
|
1911
|
-
function parseDateUnit(value) {
|
|
1912
|
-
return value ? parseInt(value) : 1;
|
|
1913
|
-
}
|
|
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
1792
|
}
|
|
1923
|
-
return
|
|
1793
|
+
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 });
|
|
1924
1794
|
}
|
|
1925
|
-
function
|
|
1926
|
-
|
|
1795
|
+
function Branch(props) {
|
|
1796
|
+
const { branch = "main" } = props;
|
|
1797
|
+
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 })] });
|
|
1927
1798
|
}
|
|
1928
|
-
function
|
|
1929
|
-
|
|
1930
|
-
const
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
1799
|
+
function DocId(props) {
|
|
1800
|
+
const { docId } = props;
|
|
1801
|
+
const [, copy] = useCopyToClipboard();
|
|
1802
|
+
function handleCopy(text) {
|
|
1803
|
+
return () => {
|
|
1804
|
+
copy(text).catch((error) => {
|
|
1805
|
+
console.error("Failed to copy!", error);
|
|
1806
|
+
});
|
|
1807
|
+
};
|
|
1937
1808
|
}
|
|
1938
|
-
return
|
|
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;
|
|
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 })] });
|
|
1960
1810
|
}
|
|
1961
|
-
function
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1811
|
+
function Scope(props) {
|
|
1812
|
+
const { value, onChange } = props;
|
|
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 });
|
|
1966
1818
|
}
|
|
1967
|
-
function
|
|
1968
|
-
|
|
1819
|
+
function Header(props) {
|
|
1820
|
+
const { title, docId, scope, onChangeScope, onClose, className, ...divProps } = props;
|
|
1821
|
+
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 })] })] });
|
|
1969
1822
|
}
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
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;
|
|
1823
|
+
function memo(getDeps, fn, opts) {
|
|
1824
|
+
let deps = opts.initialDeps ?? [];
|
|
1825
|
+
let result;
|
|
1826
|
+
function memoizedFunction() {
|
|
1827
|
+
var _a, _b, _c, _d;
|
|
1828
|
+
let depTime;
|
|
1829
|
+
if (opts.key && ((_a = opts.debug) == null ? void 0 : _a.call(opts))) depTime = Date.now();
|
|
1830
|
+
const newDeps = getDeps();
|
|
1831
|
+
const depsChanged = newDeps.length !== deps.length || newDeps.some((dep, index) => deps[index] !== dep);
|
|
1832
|
+
if (!depsChanged) {
|
|
1833
|
+
return result;
|
|
2288
1834
|
}
|
|
2289
1835
|
deps = newDeps;
|
|
2290
1836
|
let resultTime;
|
|
@@ -2315,7 +1861,11 @@ function memo(getDeps, fn, opts) {
|
|
|
2315
1861
|
}
|
|
2316
1862
|
(_d = opts == null ? void 0 : opts.onChange) == null ? void 0 : _d.call(opts, result);
|
|
2317
1863
|
return result;
|
|
1864
|
+
}
|
|
1865
|
+
memoizedFunction.updateDeps = (newDeps) => {
|
|
1866
|
+
deps = newDeps;
|
|
2318
1867
|
};
|
|
1868
|
+
return memoizedFunction;
|
|
2319
1869
|
}
|
|
2320
1870
|
function notUndefined(value, msg) {
|
|
2321
1871
|
if (value === void 0) {
|
|
@@ -2361,15 +1911,18 @@ const observeElementRect = (instance, cb) => {
|
|
|
2361
1911
|
};
|
|
2362
1912
|
}
|
|
2363
1913
|
const observer = new targetWindow.ResizeObserver((entries) => {
|
|
2364
|
-
const
|
|
2365
|
-
|
|
2366
|
-
|
|
2367
|
-
|
|
2368
|
-
|
|
2369
|
-
|
|
1914
|
+
const run = () => {
|
|
1915
|
+
const entry = entries[0];
|
|
1916
|
+
if (entry == null ? void 0 : entry.borderBoxSize) {
|
|
1917
|
+
const box = entry.borderBoxSize[0];
|
|
1918
|
+
if (box) {
|
|
1919
|
+
handler({ width: box.inlineSize, height: box.blockSize });
|
|
1920
|
+
return;
|
|
1921
|
+
}
|
|
2370
1922
|
}
|
|
2371
|
-
|
|
2372
|
-
|
|
1923
|
+
handler(element.getBoundingClientRect());
|
|
1924
|
+
};
|
|
1925
|
+
instance.options.useAnimationFrameWithResizeObserver ? requestAnimationFrame(run) : run();
|
|
2373
1926
|
});
|
|
2374
1927
|
observer.observe(element, { box: "border-box" });
|
|
2375
1928
|
return () => {
|
|
@@ -2407,10 +1960,15 @@ const observeElementOffset = (instance, cb) => {
|
|
|
2407
1960
|
const endHandler = createHandler(false);
|
|
2408
1961
|
endHandler();
|
|
2409
1962
|
element.addEventListener("scroll", handler, addEventListenerOptions);
|
|
2410
|
-
|
|
1963
|
+
const registerScrollendEvent = instance.options.useScrollendEvent && supportsScrollend;
|
|
1964
|
+
if (registerScrollendEvent) {
|
|
1965
|
+
element.addEventListener("scrollend", endHandler, addEventListenerOptions);
|
|
1966
|
+
}
|
|
2411
1967
|
return () => {
|
|
2412
1968
|
element.removeEventListener("scroll", handler);
|
|
2413
|
-
|
|
1969
|
+
if (registerScrollendEvent) {
|
|
1970
|
+
element.removeEventListener("scrollend", endHandler);
|
|
1971
|
+
}
|
|
2414
1972
|
};
|
|
2415
1973
|
};
|
|
2416
1974
|
const measureElement = (element, entry, instance) => {
|
|
@@ -2464,7 +2022,10 @@ class Virtualizer {
|
|
|
2464
2022
|
}
|
|
2465
2023
|
return _ro = new this.targetWindow.ResizeObserver((entries) => {
|
|
2466
2024
|
entries.forEach((entry) => {
|
|
2467
|
-
|
|
2025
|
+
const run = () => {
|
|
2026
|
+
this._measureElement(entry.target, entry);
|
|
2027
|
+
};
|
|
2028
|
+
this.options.useAnimationFrameWithResizeObserver ? requestAnimationFrame(run) : run();
|
|
2468
2029
|
});
|
|
2469
2030
|
});
|
|
2470
2031
|
};
|
|
@@ -2512,7 +2073,8 @@ class Virtualizer {
|
|
|
2512
2073
|
isScrollingResetDelay: 150,
|
|
2513
2074
|
enabled: true,
|
|
2514
2075
|
isRtl: false,
|
|
2515
|
-
useScrollendEvent:
|
|
2076
|
+
useScrollendEvent: false,
|
|
2077
|
+
useAnimationFrameWithResizeObserver: false,
|
|
2516
2078
|
...opts2
|
|
2517
2079
|
};
|
|
2518
2080
|
};
|
|
@@ -2701,12 +2263,18 @@ class Virtualizer {
|
|
|
2701
2263
|
}
|
|
2702
2264
|
);
|
|
2703
2265
|
this.calculateRange = memo(
|
|
2704
|
-
() => [
|
|
2705
|
-
|
|
2266
|
+
() => [
|
|
2267
|
+
this.getMeasurements(),
|
|
2268
|
+
this.getSize(),
|
|
2269
|
+
this.getScrollOffset(),
|
|
2270
|
+
this.options.lanes
|
|
2271
|
+
],
|
|
2272
|
+
(measurements, outerSize, scrollOffset, lanes) => {
|
|
2706
2273
|
return this.range = measurements.length > 0 && outerSize > 0 ? calculateRange({
|
|
2707
2274
|
measurements,
|
|
2708
2275
|
outerSize,
|
|
2709
|
-
scrollOffset
|
|
2276
|
+
scrollOffset,
|
|
2277
|
+
lanes
|
|
2710
2278
|
}) : null;
|
|
2711
2279
|
},
|
|
2712
2280
|
{
|
|
@@ -2714,7 +2282,7 @@ class Virtualizer {
|
|
|
2714
2282
|
debug: () => this.options.debug
|
|
2715
2283
|
}
|
|
2716
2284
|
);
|
|
2717
|
-
this.
|
|
2285
|
+
this.getVirtualIndexes = memo(
|
|
2718
2286
|
() => {
|
|
2719
2287
|
let startIndex = null;
|
|
2720
2288
|
let endIndex = null;
|
|
@@ -2723,6 +2291,7 @@ class Virtualizer {
|
|
|
2723
2291
|
startIndex = range.startIndex;
|
|
2724
2292
|
endIndex = range.endIndex;
|
|
2725
2293
|
}
|
|
2294
|
+
this.maybeNotify.updateDeps([this.isScrolling, startIndex, endIndex]);
|
|
2726
2295
|
return [
|
|
2727
2296
|
this.options.rangeExtractor,
|
|
2728
2297
|
this.options.overscan,
|
|
@@ -2806,7 +2375,7 @@ class Virtualizer {
|
|
|
2806
2375
|
this._measureElement(node, void 0);
|
|
2807
2376
|
};
|
|
2808
2377
|
this.getVirtualItems = memo(
|
|
2809
|
-
() => [this.
|
|
2378
|
+
() => [this.getVirtualIndexes(), this.getMeasurements()],
|
|
2810
2379
|
(indexes, measurements) => {
|
|
2811
2380
|
const virtualItems = [];
|
|
2812
2381
|
for (let k = 0, len = indexes.length; k < len; k++) {
|
|
@@ -2835,15 +2404,15 @@ class Virtualizer {
|
|
|
2835
2404
|
)]
|
|
2836
2405
|
);
|
|
2837
2406
|
};
|
|
2838
|
-
this.getOffsetForAlignment = (toOffset, align) => {
|
|
2407
|
+
this.getOffsetForAlignment = (toOffset, align, itemSize = 0) => {
|
|
2839
2408
|
const size = this.getSize();
|
|
2840
2409
|
const scrollOffset = this.getScrollOffset();
|
|
2841
2410
|
if (align === "auto") {
|
|
2842
|
-
|
|
2843
|
-
align = "end";
|
|
2844
|
-
}
|
|
2411
|
+
align = toOffset >= scrollOffset + size ? "end" : "start";
|
|
2845
2412
|
}
|
|
2846
|
-
if (align === "
|
|
2413
|
+
if (align === "center") {
|
|
2414
|
+
toOffset += (itemSize - size) / 2;
|
|
2415
|
+
} else if (align === "end") {
|
|
2847
2416
|
toOffset -= size;
|
|
2848
2417
|
}
|
|
2849
2418
|
const scrollSizeProp = this.options.horizontal ? "scrollWidth" : "scrollHeight";
|
|
@@ -2868,27 +2437,11 @@ class Virtualizer {
|
|
|
2868
2437
|
return [scrollOffset, align];
|
|
2869
2438
|
}
|
|
2870
2439
|
}
|
|
2871
|
-
const
|
|
2872
|
-
|
|
2873
|
-
|
|
2874
|
-
|
|
2875
|
-
|
|
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
|
-
}
|
|
2440
|
+
const toOffset = align === "end" ? item.end + this.options.scrollPaddingEnd : item.start - this.options.scrollPaddingStart;
|
|
2441
|
+
return [
|
|
2442
|
+
this.getOffsetForAlignment(toOffset, align, item.size),
|
|
2443
|
+
align
|
|
2444
|
+
];
|
|
2892
2445
|
};
|
|
2893
2446
|
this.isDynamicMode = () => this.elementsCache.size > 0;
|
|
2894
2447
|
this.cancelScrollToIndex = () => {
|
|
@@ -2958,10 +2511,19 @@ class Virtualizer {
|
|
|
2958
2511
|
let end;
|
|
2959
2512
|
if (measurements.length === 0) {
|
|
2960
2513
|
end = this.options.paddingStart;
|
|
2514
|
+
} else if (this.options.lanes === 1) {
|
|
2515
|
+
end = ((_a = measurements[measurements.length - 1]) == null ? void 0 : _a.end) ?? 0;
|
|
2961
2516
|
} else {
|
|
2962
|
-
|
|
2963
|
-
|
|
2964
|
-
)
|
|
2517
|
+
const endByLane = Array(this.options.lanes).fill(null);
|
|
2518
|
+
let endIndex = measurements.length - 1;
|
|
2519
|
+
while (endIndex >= 0 && endByLane.some((val) => val === null)) {
|
|
2520
|
+
const item = measurements[endIndex];
|
|
2521
|
+
if (endByLane[item.lane] === null) {
|
|
2522
|
+
endByLane[item.lane] = item.end;
|
|
2523
|
+
}
|
|
2524
|
+
endIndex--;
|
|
2525
|
+
}
|
|
2526
|
+
end = Math.max(...endByLane.filter((val) => val !== null));
|
|
2965
2527
|
}
|
|
2966
2528
|
return Math.max(
|
|
2967
2529
|
end - this.options.scrollMargin + this.options.paddingEnd,
|
|
@@ -3002,14 +2564,43 @@ const findNearestBinarySearch = (low, high, getCurrentValue, value) => {
|
|
|
3002
2564
|
function calculateRange({
|
|
3003
2565
|
measurements,
|
|
3004
2566
|
outerSize,
|
|
3005
|
-
scrollOffset
|
|
2567
|
+
scrollOffset,
|
|
2568
|
+
lanes
|
|
3006
2569
|
}) {
|
|
3007
|
-
const
|
|
2570
|
+
const lastIndex = measurements.length - 1;
|
|
3008
2571
|
const getOffset = (index) => measurements[index].start;
|
|
3009
|
-
|
|
2572
|
+
if (measurements.length <= lanes) {
|
|
2573
|
+
return {
|
|
2574
|
+
startIndex: 0,
|
|
2575
|
+
endIndex: lastIndex
|
|
2576
|
+
};
|
|
2577
|
+
}
|
|
2578
|
+
let startIndex = findNearestBinarySearch(
|
|
2579
|
+
0,
|
|
2580
|
+
lastIndex,
|
|
2581
|
+
getOffset,
|
|
2582
|
+
scrollOffset
|
|
2583
|
+
);
|
|
3010
2584
|
let endIndex = startIndex;
|
|
3011
|
-
|
|
3012
|
-
endIndex
|
|
2585
|
+
if (lanes === 1) {
|
|
2586
|
+
while (endIndex < lastIndex && measurements[endIndex].end < scrollOffset + outerSize) {
|
|
2587
|
+
endIndex++;
|
|
2588
|
+
}
|
|
2589
|
+
} else if (lanes > 1) {
|
|
2590
|
+
const endPerLane = Array(lanes).fill(0);
|
|
2591
|
+
while (endIndex < lastIndex && endPerLane.some((pos) => pos < scrollOffset + outerSize)) {
|
|
2592
|
+
const item = measurements[endIndex];
|
|
2593
|
+
endPerLane[item.lane] = item.end;
|
|
2594
|
+
endIndex++;
|
|
2595
|
+
}
|
|
2596
|
+
const startPerLane = Array(lanes).fill(scrollOffset + outerSize);
|
|
2597
|
+
while (startIndex >= 0 && startPerLane.some((pos) => pos >= scrollOffset)) {
|
|
2598
|
+
const item = measurements[startIndex];
|
|
2599
|
+
startPerLane[item.lane] = item.start;
|
|
2600
|
+
startIndex--;
|
|
2601
|
+
}
|
|
2602
|
+
startIndex = Math.max(0, startIndex - startIndex % lanes);
|
|
2603
|
+
endIndex = Math.min(lastIndex, endIndex + (lanes - 1 - endIndex % lanes));
|
|
3013
2604
|
}
|
|
3014
2605
|
return { startIndex, endIndex };
|
|
3015
2606
|
}
|
|
@@ -3266,8 +2857,8 @@ function RevisionHistory(props) {
|
|
|
3266
2857
|
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] });
|
|
3267
2858
|
}
|
|
3268
2859
|
function Tooltip(props) {
|
|
3269
|
-
const { children, content, open, defaultOpen, onOpenChange, className,
|
|
3270
|
-
return jsxs(Root3, { defaultOpen, delayDuration: 0, onOpenChange, open, children: [jsx(Trigger, { asChild: true, children }), jsx(Portal, { children: jsx(Content2, { ...rest,
|
|
2860
|
+
const { children, content, open, defaultOpen, onOpenChange, className, ...rest } = props;
|
|
2861
|
+
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 }) })] });
|
|
3271
2862
|
}
|
|
3272
2863
|
const TooltipProvider = Provider;
|
|
3273
2864
|
const BUDGET = "powerhouse/budget-statement";
|
|
@@ -3515,7 +3106,9 @@ function useAddDebouncedOperations(reactor, props) {
|
|
|
3515
3106
|
const { driveId, documentId } = props;
|
|
3516
3107
|
const [documentDrives] = useDocumentDrives(reactor);
|
|
3517
3108
|
const documentDrivesRef = useRef(documentDrives);
|
|
3518
|
-
const { isAllowedToEditDocuments } = useUserPermissions()
|
|
3109
|
+
const { isAllowedToEditDocuments } = useUserPermissions() || {
|
|
3110
|
+
isAllowedToEditDocuments: false
|
|
3111
|
+
};
|
|
3519
3112
|
useEffect(() => {
|
|
3520
3113
|
documentDrivesRef.current = documentDrives;
|
|
3521
3114
|
}, [documentDrives]);
|
|
@@ -3526,7 +3119,7 @@ function useAddDebouncedOperations(reactor, props) {
|
|
|
3526
3119
|
if (!reactor) {
|
|
3527
3120
|
throw new Error("Reactor is not loaded");
|
|
3528
3121
|
}
|
|
3529
|
-
const drive = documentDrivesRef.current.find((drive2) => drive2.id === driveId2);
|
|
3122
|
+
const drive = documentDrivesRef.current.find((drive2) => drive2.state.global.id === driveId2);
|
|
3530
3123
|
if (!drive) {
|
|
3531
3124
|
throw new Error(`Drive with id ${driveId2} not found`);
|
|
3532
3125
|
}
|
|
@@ -3605,7 +3198,7 @@ function getNode(id, drive) {
|
|
|
3605
3198
|
}
|
|
3606
3199
|
function createDriveActions(document2, dispatch, context) {
|
|
3607
3200
|
const drive = document2;
|
|
3608
|
-
const driveId = drive.
|
|
3201
|
+
const { id: driveId } = drive.state.global;
|
|
3609
3202
|
const { selectedNode } = context;
|
|
3610
3203
|
const handleAddFolder = async (name, parentFolder, id = generateId()) => {
|
|
3611
3204
|
dispatch(addFolder({
|
|
@@ -3895,17 +3488,6 @@ function useEditorProps(document2, node, documentDispatch, onAddOperation) {
|
|
|
3895
3488
|
isAllowedToEditDocuments: (userPermissions == null ? void 0 : userPermissions.isAllowedToEditDocuments) ?? false
|
|
3896
3489
|
};
|
|
3897
3490
|
}
|
|
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
|
-
}
|
|
3909
3491
|
function useSyncStatus(driveId, documentId) {
|
|
3910
3492
|
const { getSyncStatusSync, onSyncStatus, documentDrives } = useDocumentDriveServer();
|
|
3911
3493
|
const syncStatus = useSyncExternalStore(
|
|
@@ -3915,7 +3497,9 @@ function useSyncStatus(driveId, documentId) {
|
|
|
3915
3497
|
},
|
|
3916
3498
|
() => {
|
|
3917
3499
|
var _a;
|
|
3918
|
-
const drive = documentDrives.find(
|
|
3500
|
+
const drive = documentDrives.find(
|
|
3501
|
+
(_drive) => _drive.state.global.id === driveId
|
|
3502
|
+
);
|
|
3919
3503
|
if (!drive) return;
|
|
3920
3504
|
const isReadDrive = "readContext" in drive;
|
|
3921
3505
|
const _sharingType = !isReadDrive ? (_a = drive.state.local.sharingType) == null ? void 0 : _a.toUpperCase() : "PUBLIC";
|
|
@@ -3974,338 +3558,6 @@ const useUndoRedoShortcuts = (props) => {
|
|
|
3974
3558
|
[canRedo, redo2]
|
|
3975
3559
|
);
|
|
3976
3560
|
};
|
|
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
3561
|
function EditorLoader(props) {
|
|
4310
3562
|
const [showLoading, setShowLoading] = useState(false);
|
|
4311
3563
|
useEffect(() => {
|
|
@@ -4333,11 +3585,9 @@ const DocumentEditor = (props) => {
|
|
|
4333
3585
|
onChange,
|
|
4334
3586
|
onExport,
|
|
4335
3587
|
onAddOperation,
|
|
4336
|
-
onGetDocumentRevision,
|
|
4337
3588
|
onOpenSwitchboardLink
|
|
4338
3589
|
} = props;
|
|
4339
3590
|
const documentId = fileNodeDocument == null ? void 0 : fileNodeDocument.documentId;
|
|
4340
|
-
const [selectedTimelineItem, setSelectedTimelineItem] = useState(null);
|
|
4341
3591
|
const [revisionHistoryVisible, setRevisionHistoryVisible] = useState(false);
|
|
4342
3592
|
const theme = useAtomValue(themeAtom);
|
|
4343
3593
|
const user = useUser() || void 0;
|
|
@@ -4363,10 +3613,6 @@ const DocumentEditor = (props) => {
|
|
|
4363
3613
|
[theme, user]
|
|
4364
3614
|
);
|
|
4365
3615
|
const userPermissions = useUserPermissions$1();
|
|
4366
|
-
const timelineItems = useTimelineItems(
|
|
4367
|
-
documentId,
|
|
4368
|
-
initialDocument == null ? void 0 : initialDocument.created
|
|
4369
|
-
);
|
|
4370
3616
|
const currentDocument = useRef({ ...fileNodeDocument, document: document2 });
|
|
4371
3617
|
useEffect(() => {
|
|
4372
3618
|
var _a;
|
|
@@ -4543,8 +3789,7 @@ const DocumentEditor = (props) => {
|
|
|
4543
3789
|
const {
|
|
4544
3790
|
disableExternalControls,
|
|
4545
3791
|
documentToolbarEnabled,
|
|
4546
|
-
showSwitchboardLink
|
|
4547
|
-
timelineEnabled
|
|
3792
|
+
showSwitchboardLink
|
|
4548
3793
|
} = editor.config || {};
|
|
4549
3794
|
const handleSwitchboardLinkClick = showSwitchboardLink !== false ? onOpenSwitchboardLink : void 0;
|
|
4550
3795
|
return /* @__PURE__ */ jsxs("div", { className: "relative h-full", id: "document-editor-context", children: [
|
|
@@ -4555,10 +3800,7 @@ const DocumentEditor = (props) => {
|
|
|
4555
3800
|
onExport,
|
|
4556
3801
|
onShowRevisionHistory: showRevisionHistory,
|
|
4557
3802
|
title: fileNodeDocument.name || document2.name,
|
|
4558
|
-
onSwitchboardLinkClick: handleSwitchboardLinkClick
|
|
4559
|
-
timelineButtonVisible: timelineEnabled,
|
|
4560
|
-
timelineItems: timelineItems.data,
|
|
4561
|
-
onTimelineItemClick: setSelectedTimelineItem
|
|
3803
|
+
onSwitchboardLinkClick: handleSwitchboardLinkClick
|
|
4562
3804
|
}
|
|
4563
3805
|
),
|
|
4564
3806
|
!disableExternalControls && /* @__PURE__ */ jsxs("div", { className: "mb-4 flex justify-end gap-10", children: [
|
|
@@ -4588,16 +3830,7 @@ const DocumentEditor = (props) => {
|
|
|
4588
3830
|
EditorComponent,
|
|
4589
3831
|
{
|
|
4590
3832
|
error,
|
|
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
|
-
},
|
|
3833
|
+
context,
|
|
4601
3834
|
document: document2,
|
|
4602
3835
|
documentNodeName: fileNodeDocument.name,
|
|
4603
3836
|
dispatch,
|
|
@@ -4635,7 +3868,6 @@ function DocumentEditorContainer() {
|
|
|
4635
3868
|
renameNode,
|
|
4636
3869
|
getDocumentModelModule
|
|
4637
3870
|
} = useUiNodes();
|
|
4638
|
-
const getDocument = useGetDocument();
|
|
4639
3871
|
const handleAddOperationToSelectedDocument = useCallback(
|
|
4640
3872
|
async (operation) => {
|
|
4641
3873
|
if (!selectedDocument) {
|
|
@@ -4698,20 +3930,6 @@ function DocumentEditorContainer() {
|
|
|
4698
3930
|
},
|
|
4699
3931
|
[getDocumentModelModule, showModal, t]
|
|
4700
3932
|
);
|
|
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
|
-
);
|
|
4715
3933
|
const onExport = useCallback(() => {
|
|
4716
3934
|
if (selectedDocument) {
|
|
4717
3935
|
return exportDocument(selectedDocument);
|
|
@@ -4733,7 +3951,6 @@ function DocumentEditorContainer() {
|
|
|
4733
3951
|
onChange: onDocumentChangeHandler,
|
|
4734
3952
|
onClose,
|
|
4735
3953
|
onExport,
|
|
4736
|
-
onGetDocumentRevision,
|
|
4737
3954
|
onAddOperation: handleAddOperationToSelectedDocument,
|
|
4738
3955
|
onOpenSwitchboardLink
|
|
4739
3956
|
}
|
|
@@ -4742,6 +3959,165 @@ function DocumentEditorContainer() {
|
|
|
4742
3959
|
fileNodeDocument.documentId
|
|
4743
3960
|
);
|
|
4744
3961
|
}
|
|
3962
|
+
function getDocumentSpec(doc) {
|
|
3963
|
+
if ("documentModelState" in doc) {
|
|
3964
|
+
return doc.documentModelState;
|
|
3965
|
+
}
|
|
3966
|
+
return doc.documentModel;
|
|
3967
|
+
}
|
|
3968
|
+
const CreateDocument = ({ documentModels, createDocument }) => {
|
|
3969
|
+
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) => {
|
|
3970
|
+
const spec = getDocumentSpec(doc);
|
|
3971
|
+
return jsx(Button, { color: "light", "aria-details": spec.description, onClick: () => createDocument(doc), children: jsx("span", { className: "text-sm", children: spec.name }) }, spec.id);
|
|
3972
|
+
}) })] });
|
|
3973
|
+
};
|
|
3974
|
+
function sortUiNodesByName(a, b) {
|
|
3975
|
+
return a.name.localeCompare(b.name);
|
|
3976
|
+
}
|
|
3977
|
+
const GAP = 8;
|
|
3978
|
+
const ITEM_WIDTH = 256;
|
|
3979
|
+
const ITEM_HEIGHT = 48;
|
|
3980
|
+
const USED_SPACE = 420;
|
|
3981
|
+
function FileContentView(props) {
|
|
3982
|
+
const parentRef = useRef(null);
|
|
3983
|
+
const { t } = useTranslation();
|
|
3984
|
+
const windowSize = useWindowSize();
|
|
3985
|
+
const { fileNodes, ...fileProps } = props;
|
|
3986
|
+
const availableWidth = windowSize.innerWidth - USED_SPACE;
|
|
3987
|
+
const columnCount = Math.floor(availableWidth / (ITEM_WIDTH + GAP)) || 1;
|
|
3988
|
+
const rowCount = Math.ceil(fileNodes.length / columnCount);
|
|
3989
|
+
const rowVirtualizer = useVirtualizer({
|
|
3990
|
+
count: rowCount,
|
|
3991
|
+
getScrollElement: () => parentRef.current,
|
|
3992
|
+
estimateSize: (index) => {
|
|
3993
|
+
if (index > 0) {
|
|
3994
|
+
return ITEM_HEIGHT + GAP;
|
|
3995
|
+
}
|
|
3996
|
+
return ITEM_HEIGHT;
|
|
3997
|
+
},
|
|
3998
|
+
overscan: 5
|
|
3999
|
+
});
|
|
4000
|
+
const columnVirtualizer = useVirtualizer({
|
|
4001
|
+
horizontal: true,
|
|
4002
|
+
count: columnCount,
|
|
4003
|
+
getScrollElement: () => parentRef.current,
|
|
4004
|
+
estimateSize: (index) => {
|
|
4005
|
+
if (index > 0) {
|
|
4006
|
+
return ITEM_WIDTH + GAP;
|
|
4007
|
+
}
|
|
4008
|
+
return ITEM_WIDTH;
|
|
4009
|
+
},
|
|
4010
|
+
overscan: 5
|
|
4011
|
+
});
|
|
4012
|
+
const getItemIndex = (rowIndex, columnIndex) => rowIndex * columnCount + columnIndex;
|
|
4013
|
+
const getItem = (rowIndex, columnIndex) => {
|
|
4014
|
+
const index = getItemIndex(rowIndex, columnIndex);
|
|
4015
|
+
return fileNodes[index] || null;
|
|
4016
|
+
};
|
|
4017
|
+
if (fileNodes.length === 0) {
|
|
4018
|
+
return jsx("div", { className: "mb-8 text-sm text-gray-400", children: t("folderView.sections.documents.empty", {
|
|
4019
|
+
defaultValue: "No documents or files 📄"
|
|
4020
|
+
}) });
|
|
4021
|
+
}
|
|
4022
|
+
const renderItem = (rowIndex, columnIndex) => {
|
|
4023
|
+
const fileNode = getItem(rowIndex, columnIndex);
|
|
4024
|
+
if (!fileNode) {
|
|
4025
|
+
return null;
|
|
4026
|
+
}
|
|
4027
|
+
return jsx("div", { style: {
|
|
4028
|
+
marginLeft: columnIndex === 0 ? 0 : GAP
|
|
4029
|
+
}, children: jsx(FileItem, { uiNode: fileNode, ...fileProps }, fileNode.id) });
|
|
4030
|
+
};
|
|
4031
|
+
return jsx("div", { ref: parentRef, style: {
|
|
4032
|
+
height: `400px`,
|
|
4033
|
+
width: `100%`,
|
|
4034
|
+
overflow: "auto"
|
|
4035
|
+
}, children: jsx("div", { style: {
|
|
4036
|
+
height: `${rowVirtualizer.getTotalSize()}px`,
|
|
4037
|
+
width: `${columnVirtualizer.getTotalSize()}px`,
|
|
4038
|
+
position: "relative"
|
|
4039
|
+
}, children: rowVirtualizer.getVirtualItems().map((virtualRow) => jsx(React__default.Fragment, { children: columnVirtualizer.getVirtualItems().map((virtualColumn) => jsx("div", { style: {
|
|
4040
|
+
position: "absolute",
|
|
4041
|
+
top: 0,
|
|
4042
|
+
left: 0,
|
|
4043
|
+
marginTop: virtualRow.index === 0 ? 0 : GAP,
|
|
4044
|
+
width: `${virtualColumn.size}px`,
|
|
4045
|
+
height: `${virtualRow.size}px`,
|
|
4046
|
+
transform: `translateX(${virtualColumn.start}px) translateY(${virtualRow.start}px)`
|
|
4047
|
+
}, children: renderItem(virtualRow.index, virtualColumn.index) }, virtualColumn.key)) }, virtualRow.key)) }) });
|
|
4048
|
+
}
|
|
4049
|
+
function FolderView(props) {
|
|
4050
|
+
const { node, className, isDropTarget, containerProps, ...nodeProps } = props;
|
|
4051
|
+
const { t } = useTranslation();
|
|
4052
|
+
const folderNodes = node.children.filter((node2) => node2.kind === FOLDER).sort(sortUiNodesByName);
|
|
4053
|
+
const fileNodes = node.children.filter((node2) => node2.kind === FILE).sort(sortUiNodesByName);
|
|
4054
|
+
const folderCallbacks = {
|
|
4055
|
+
onSelectNode: (node2) => nodeProps.onSelectNode(node2),
|
|
4056
|
+
onRenameNode: (name, node2) => nodeProps.onRenameNode(name, node2),
|
|
4057
|
+
onDuplicateNode: (node2) => nodeProps.onDuplicateNode(node2),
|
|
4058
|
+
onDeleteNode: (node2) => nodeProps.onDeleteNode(node2)
|
|
4059
|
+
};
|
|
4060
|
+
const fileCallbacks = {
|
|
4061
|
+
onSelectNode: (node2) => nodeProps.onSelectNode(node2),
|
|
4062
|
+
onRenameNode: (name, node2) => nodeProps.onRenameNode(name, node2),
|
|
4063
|
+
onDuplicateNode: (node2) => nodeProps.onDuplicateNode(node2),
|
|
4064
|
+
onDeleteNode: (node2) => nodeProps.onDeleteNode(node2)
|
|
4065
|
+
};
|
|
4066
|
+
const baseNodeCallbacks = {
|
|
4067
|
+
onAddFile: async (file, parentNode) => {
|
|
4068
|
+
await nodeProps.onAddFile(file, parentNode);
|
|
4069
|
+
},
|
|
4070
|
+
onCopyNode: async (uiNode, targetNode) => {
|
|
4071
|
+
await nodeProps.onCopyNode(uiNode, targetNode);
|
|
4072
|
+
},
|
|
4073
|
+
onMoveNode: async (uiNode, targetNode) => {
|
|
4074
|
+
await nodeProps.onMoveNode(uiNode, targetNode);
|
|
4075
|
+
}
|
|
4076
|
+
};
|
|
4077
|
+
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", {
|
|
4078
|
+
defaultValue: "Folders"
|
|
4079
|
+
}), 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", {
|
|
4080
|
+
defaultValue: "No documents or files 📄"
|
|
4081
|
+
}) }) }), jsx(DriveLayout.ContentSection, { title: t("folderView.sections.documents.title", {
|
|
4082
|
+
defaultValue: "Documents and files"
|
|
4083
|
+
}), children: jsx("div", { className: twMerge("w-full", fileNodes.length > 0 ? "min-h-[400px]" : "min-h-14"), children: jsx(FileContentView, { fileNodes, ...fileCallbacks, isAllowedToCreateDocuments: nodeProps.isAllowedToCreateDocuments }) }) })] });
|
|
4084
|
+
}
|
|
4085
|
+
function BaseEditor(props) {
|
|
4086
|
+
const { document: document2, dispatch, className, children } = props;
|
|
4087
|
+
const { state: { global: { id: driveId } } } = document2;
|
|
4088
|
+
const { showSearchBar, isAllowedToCreateDocuments, documentModels, showCreateDocumentModal } = useDriveContext();
|
|
4089
|
+
const { driveNodes, selectedNode, selectedNodePath, getNodeById, setSelectedNode } = useUiNodesContext();
|
|
4090
|
+
const driveNode = useMemo(() => driveNodes.find((n) => n.id === driveId), [driveNodes, driveId]);
|
|
4091
|
+
const { addDocument, addFile, addFolder: addFolder2, renameNode, deleteNode: deleteNode2, moveNode: moveNode2, copyNode: copyNode2, duplicateNode } = useDriveActionsWithUiNodes(document2, dispatch);
|
|
4092
|
+
const onCreateDocument = useCallback(async (documentModel) => {
|
|
4093
|
+
const { name } = await showCreateDocumentModal(documentModel);
|
|
4094
|
+
const document3 = documentModel.utils.createDocument();
|
|
4095
|
+
await addDocument(name, documentModel.documentModel.name, document3, selectedNode == null ? void 0 : selectedNode.id);
|
|
4096
|
+
}, [addDocument, showCreateDocumentModal, selectedNode == null ? void 0 : selectedNode.id]);
|
|
4097
|
+
const { isDropTarget, dropProps } = useDrop({
|
|
4098
|
+
uiNode: selectedNode,
|
|
4099
|
+
onAddFile: addFile,
|
|
4100
|
+
onCopyNode: copyNode2,
|
|
4101
|
+
onMoveNode: moveNode2
|
|
4102
|
+
});
|
|
4103
|
+
const { breadcrumbs, onBreadcrumbSelected } = useBreadcrumbs({
|
|
4104
|
+
selectedNodePath,
|
|
4105
|
+
getNodeById,
|
|
4106
|
+
setSelectedNode
|
|
4107
|
+
});
|
|
4108
|
+
if (!driveNode) {
|
|
4109
|
+
return jsx("div", { children: "Drive not found" });
|
|
4110
|
+
} else if ((selectedNode == null ? void 0 : selectedNode.kind) === FILE$1) {
|
|
4111
|
+
return jsx(Fragment$1, {});
|
|
4112
|
+
}
|
|
4113
|
+
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 }) })] });
|
|
4114
|
+
}
|
|
4115
|
+
function Editor(props) {
|
|
4116
|
+
return jsx(DriveContextProvider, { value: props.context, children: jsx(BaseEditor, { ...props }) });
|
|
4117
|
+
}
|
|
4118
|
+
const GenericDriveExplorer = {
|
|
4119
|
+
Component: Editor
|
|
4120
|
+
};
|
|
4745
4121
|
function useDocumentsState(args) {
|
|
4746
4122
|
const { reactor, driveId, documentIds, options } = args;
|
|
4747
4123
|
const [statesByDocumentId, setStatesByDocumentId] = useState({});
|
|
@@ -4928,19 +4304,8 @@ function DriveEditorContainer() {
|
|
|
4928
4304
|
const { addFile, addDocument } = useDocumentDriveServer();
|
|
4929
4305
|
const documentModels = useFilteredDocumentModels();
|
|
4930
4306
|
const useDriveDocumentState = makeDriveDocumentStateHook(reactor);
|
|
4931
|
-
const getDocument = useGetDocument();
|
|
4932
4307
|
const getDocumentModelModule = useGetDocumentModelModule();
|
|
4933
4308
|
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
|
-
);
|
|
4944
4309
|
const driveContext = useMemo(
|
|
4945
4310
|
() => ({
|
|
4946
4311
|
showSearchBar: false,
|
|
@@ -4984,8 +4349,6 @@ function DriveEditorContainer() {
|
|
|
4984
4349
|
context: {
|
|
4985
4350
|
...editorProps.context,
|
|
4986
4351
|
...driveContext,
|
|
4987
|
-
analyticsDatabaseName: connectConfig.analyticsDatabaseName,
|
|
4988
|
-
getDocumentRevision: onGetDocumentRevision,
|
|
4989
4352
|
getDocumentModelModule,
|
|
4990
4353
|
getEditor
|
|
4991
4354
|
},
|
|
@@ -5021,7 +4384,7 @@ function Content() {
|
|
|
5021
4384
|
}, [selectedDriveNode, selectedNode, addFile]);
|
|
5022
4385
|
useEffect(() => {
|
|
5023
4386
|
if ((status === "LOADED" || status === "ERROR") && !documentDrives.find(
|
|
5024
|
-
(d) => d.id === driveId || d.slug === driveId || d.state.global.name === driveId
|
|
4387
|
+
(d) => d.state.global.id === driveId || d.state.global.slug === driveId || d.state.global.name === driveId
|
|
5025
4388
|
)) {
|
|
5026
4389
|
toast(/* @__PURE__ */ jsxs("p", { children: [
|
|
5027
4390
|
"Drive ",
|
|
@@ -5036,4 +4399,3 @@ function Content() {
|
|
|
5036
4399
|
export {
|
|
5037
4400
|
Content as default
|
|
5038
4401
|
};
|
|
5039
|
-
//# sourceMappingURL=content-2lJzkjLx.js.map
|