@powerhousedao/connect 1.0.24-dev.0 → 1.1.1

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.
Files changed (37) hide show
  1. package/dist/.env +1 -1
  2. package/dist/assets/{app-B5yYl0zv.js → app-CZSKsD-w.js} +11239 -12745
  3. package/dist/assets/{app-DWlDE8AF.css → app-W_mH4m8_.css} +182 -241
  4. package/dist/assets/{app-loader-NDVZu4bS.css → app-loader-4GyeoNTc.css} +229 -239
  5. package/dist/assets/{app-loader-CmEZOj3m.js → app-loader-CyUyHxMC.js} +436 -745
  6. package/dist/assets/{ccip-KtRjx9vh.js → ccip-BPO0EeBI.js} +8 -6
  7. package/dist/assets/{content-2lJzkjLx.js → content-fzZoyU8t.js} +466 -1103
  8. package/dist/assets/{index-BVVRVlZN.js → index-C3PlmBGF.js} +3 -4
  9. package/dist/assets/{index-dSMCpjcQ.js → index-DFiZ2Eug.js} +171 -23
  10. package/dist/assets/{index-BhHOiwFw.js → index-D_CfC9G5.js} +3702 -3517
  11. package/dist/assets/{main.DA6nl4Ov.js → main.8RNzWcZO.js} +12 -3
  12. package/dist/assets/{style-CdxGKc2g.css → style-U7Kx3_hE.css} +95 -39
  13. package/dist/external-packages.js +0 -1
  14. package/dist/hmr.js +0 -1
  15. package/dist/index.html +1 -1
  16. package/dist/service-worker.js +0 -1
  17. package/dist/vite-envs.sh +1 -1
  18. package/package.json +20 -21
  19. package/dist/assets/app-B5yYl0zv.js.map +0 -1
  20. package/dist/assets/app-loader-CmEZOj3m.js.map +0 -1
  21. package/dist/assets/browser-D5LEpLBa.js +0 -27224
  22. package/dist/assets/browser-D5LEpLBa.js.map +0 -1
  23. package/dist/assets/ccip-KtRjx9vh.js.map +0 -1
  24. package/dist/assets/content-2lJzkjLx.js.map +0 -1
  25. package/dist/assets/index-BVVRVlZN.js.map +0 -1
  26. package/dist/assets/index-BhHOiwFw.js.map +0 -1
  27. package/dist/assets/index-DZiF5od7.js +0 -208
  28. package/dist/assets/index-DZiF5od7.js.map +0 -1
  29. package/dist/assets/index-dSMCpjcQ.js.map +0 -1
  30. package/dist/assets/main.DA6nl4Ov.js.map +0 -1
  31. package/dist/assets/reactor-analytics-CF_JKt8H.js +0 -42
  32. package/dist/assets/reactor-analytics-CF_JKt8H.js.map +0 -1
  33. package/dist/assets/router-Ch1WZD-6.js +0 -1585
  34. package/dist/assets/router-Ch1WZD-6.js.map +0 -1
  35. package/dist/external-packages.js.map +0 -1
  36. package/dist/hmr.js.map +0 -1
  37. 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, aO as mergeClassNameProps, aP as INITIAL_SYNC, aQ as SYNCING, S as SUCCESS, C as CONFLICT, aR as MISSING, x as ERROR, aS as ConnectDropdownMenu, aT as useOnClickOutside, aU as useEventListener, aV as useCopyToClipboard, aW as Select, aX as Provider, aY as Root3, aZ as Trigger, a_ as Portal, a$ as Content2, b0 as validateInitialState, b1 as validateStateSchemaName, b2 as validateModules, b3 as useDocumentDrives, A as useUiNodesContext, b4 as useDriveContext, b5 as FILE$1, F as useUnwrappedReactor, b6 as useConnectDid, b7 as useConnectCrypto, o as useTranslation, G as useModal, b8 as useAtomValue, b9 as themeAtom, ba as useUser, bb as useUserPermissions$1, p as useUiNodes, bc as exportFile, bd as useGetDocumentModelModule, be as addActionContext$1, bf as signOperation$1, e as useDocumentDriveServer, bg as useHotkeys, bh as DriveLayout, bi as DriveContextProvider, bj as SearchBar, N as useAnalyticsStore, bk as useQueryClient, u as useQuery, a3 as AnalyticsPath, bl as useAnalyticsEngine, a4 as DateTime, bm as AnalyticsGranularity, bn as useGetEditor, bo as isSameDocument, n as useNavigate, s as useAsyncReactor, bp as useFilteredDocumentModels, bq as useDriveEditor, br as useDocumentDriveById, z as useParams, q as useDocumentDrives$1, w as toast } from "./app-B5yYl0zv.js";
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-CZSKsD-w.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 { $ as Icon, bX as getDimensions, bY as READ, bZ as nodeOptionsMap, b_ as defaultFileOptions, b$ as DUPLICATE, c0 as RENAME, c1 as WRITE, c2 as DELETE, c3 as defaultFolderOptions, c4 as garbageCollect, c5 as sortOperations, c6 as UI_NODE, aQ as DRIVE, aB as FILE, ae as buildSignedOperation, ax as addFolder, at as generateAddNodeAction, ay as isFolderNode, au as isFileNode, az as deleteNode, aA as updateNode, aC as moveNode, aD as generateNodesCopy, aE as copyNode, aq as generateId$1, c7 as undo, c8 as redo, _ as logger, aR as FOLDER, c9 as useDocumentDispatch$1, an as driveDocumentModelModule, ah as connectConfig } from "./app-loader-CmEZOj3m.js";
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-CyUyHxMC.js";
7
6
  import { flushSync } from "react-dom";
8
- import "./main.DA6nl4Ov.js";
7
+ import "./main.8RNzWcZO.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
- context || dates.find((date) => typeof date === "object")
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$1 = (token, count, options) => {
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: formatDistance$1,
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 formatDistance(laterDate, earlierDate, options) {
1723
- const defaultOptions2 = getDefaultOptions();
1724
- const locale = (options == null ? void 0 : options.locale) ?? defaultOptions2.locale ?? enUS;
1725
- const minutesInAlmostTwoDays = 2520;
1726
- const comparison = compareAsc(laterDate, earlierDate);
1727
- if (isNaN(comparison)) throw new RangeError("Invalid time value");
1728
- const localizeOptions = Object.assign({}, options, {
1729
- addSuffix: options == null ? void 0 : options.addSuffix,
1730
- comparison
1731
- });
1732
- const [laterDate_, earlierDate_] = normalizeDates(
1733
- options == null ? void 0 : options.in,
1734
- ...comparison > 0 ? [earlierDate, laterDate] : [laterDate, earlierDate]
1735
- );
1736
- const seconds = differenceInSeconds(earlierDate_, laterDate_);
1737
- const offsetInSeconds = (getTimezoneOffsetInMilliseconds(earlierDate_) - getTimezoneOffsetInMilliseconds(laterDate_)) / 1e3;
1738
- const minutes = Math.round((seconds - offsetInSeconds) / 60);
1739
- let months;
1740
- if (minutes < 2) {
1741
- if (options == null ? void 0 : options.includeSeconds) {
1742
- if (seconds < 5) {
1743
- return locale.formatDistance("lessThanXSeconds", 5, localizeOptions);
1744
- } else if (seconds < 10) {
1745
- return locale.formatDistance("lessThanXSeconds", 10, localizeOptions);
1746
- } else if (seconds < 20) {
1747
- return locale.formatDistance("lessThanXSeconds", 20, localizeOptions);
1748
- } else if (seconds < 40) {
1749
- return locale.formatDistance("halfAMinute", 0, localizeOptions);
1750
- } else if (seconds < 60) {
1751
- return locale.formatDistance("lessThanXMinutes", 1, localizeOptions);
1752
- } else {
1753
- return locale.formatDistance("xMinutes", 1, localizeOptions);
1754
- }
1755
- } else {
1756
- if (minutes === 0) {
1757
- return locale.formatDistance("lessThanXMinutes", 1, localizeOptions);
1758
- } else {
1759
- return locale.formatDistance("xMinutes", minutes, localizeOptions);
1760
- }
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
- return dateStrings;
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
- return dayOfISOWeekYear(year, week, dayOfWeek);
1902
- } else {
1903
- const date = /* @__PURE__ */ new Date(0);
1904
- if (!validateDate(year, month, day) || !validateDayOfYearDate(year, dayOfYear)) {
1905
- return /* @__PURE__ */ new Date(NaN);
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 hours * millisecondsInHour + minutes * millisecondsInMinute + seconds * 1e3;
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 parseTimeUnit(value) {
1926
- return value && parseFloat(value.replace(",", ".")) || 0;
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 parseTimezone(timezoneString) {
1929
- if (timezoneString === "Z") return 0;
1930
- const captures = timezoneString.match(timezoneRegex);
1931
- if (!captures) return 0;
1932
- const sign = captures[1] === "+" ? -1 : 1;
1933
- const hours = parseInt(captures[2]);
1934
- const minutes = captures[3] && parseInt(captures[3]) || 0;
1935
- if (!validateTimezone(hours, minutes)) {
1936
- return NaN;
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 sign * (hours * millisecondsInHour + minutes * millisecondsInMinute);
1939
- }
1940
- function dayOfISOWeekYear(isoWeekYear, week, day) {
1941
- const date = /* @__PURE__ */ new Date(0);
1942
- date.setUTCFullYear(isoWeekYear, 0, 4);
1943
- const fourthOfJanuaryDay = date.getUTCDay() || 7;
1944
- const diff = (week - 1) * 7 + day + 1 - fourthOfJanuaryDay;
1945
- date.setUTCDate(date.getUTCDate() + diff);
1946
- return date;
1947
- }
1948
- const daysInMonths = [31, null, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
1949
- function isLeapYearIndex(year) {
1950
- return year % 400 === 0 || year % 4 === 0 && year % 100 !== 0;
1951
- }
1952
- function validateDate(year, month, date) {
1953
- return month >= 0 && month <= 11 && date >= 1 && date <= (daysInMonths[month] || (isLeapYearIndex(year) ? 29 : 28));
1954
- }
1955
- function validateDayOfYearDate(year, dayOfYear) {
1956
- return dayOfYear >= 1 && dayOfYear <= (isLeapYearIndex(year) ? 366 : 365);
1957
- }
1958
- function validateWeekDate(_year, week, day) {
1959
- return week >= 1 && week <= 53 && day >= 0 && day <= 6;
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 validateTime(hours, minutes, seconds) {
1962
- if (hours === 24) {
1963
- return minutes === 0 && seconds === 0;
1964
- }
1965
- return seconds >= 0 && seconds < 60 && minutes >= 0 && minutes < 60 && hours >= 0 && hours < 25;
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 validateTimezone(_hours, minutes) {
1968
- return minutes >= 0 && minutes <= 59;
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
- const HDivider = (props) => {
1971
- const { className, timestamp, title, subtitle, onClick, isSelected = false } = props;
1972
- const [open, setOpen] = useState(false);
1973
- const hasContent = !!title || !!subtitle || !!timestamp;
1974
- useEffect(() => {
1975
- if (open) {
1976
- setOpen(false);
1977
- setTimeout(() => hasContent && setOpen(true), 50);
1978
- }
1979
- }, [title, subtitle, timestamp, hasContent]);
1980
- const formatTimestamp2 = (isoString) => {
1981
- if (!isoString)
1982
- return "";
1983
- try {
1984
- return formatDistanceToNow(new Date(isoString), { addSuffix: true });
1985
- } catch {
1986
- return isoString;
1987
- }
1988
- };
1989
- const tooltipContent = jsxs("div", { className: "flex flex-col text-xs", children: [!!title && jsx("div", { children: title }), !!subtitle && jsx("div", { className: "text-gray-300", children: subtitle }), !!timestamp && jsx("div", { children: formatTimestamp2(timestamp) })] });
1990
- const handleMouseEnter = () => {
1991
- if (hasContent) {
1992
- setOpen(true);
1993
- }
1994
- };
1995
- const handleMouseLeave = () => {
1996
- setOpen(false);
1997
- };
1998
- return jsxs("div", { className: "relative", onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave, children: [isSelected && jsx(Icon, { name: "TimelineCaret", color: "#4EA9FF", size: 10, className: "absolute top-[-11px] z-40" }), jsx(Tooltip, { className: "rounded-md bg-gray-900 text-white", content: tooltipContent, open: open && hasContent, onOpenChange: setOpen, delayDuration: 0, side: "bottom", sideOffset: 5, children: jsx("div", { className: twMerge("mx-0.5 flex h-[25px] w-1.5 cursor-pointer flex-col items-center justify-center rounded-[2px] hover:bg-blue-300", isSelected && "bg-blue-300", className), onClick, "data-title": title, "data-subtitle": subtitle, "data-timestamp": timestamp, children: jsx("div", { className: "h-0.5 w-1 rounded-full bg-gray-500" }) }) })] });
1999
- };
2000
- const getBarHeight = (size = 0) => {
2001
- switch (true) {
2002
- case size <= 0:
2003
- return "h-[1px]";
2004
- case size === 1:
2005
- return "h-[3px]";
2006
- case size === 2:
2007
- return "h-[6px]";
2008
- case size === 3:
2009
- return "h-[9px]";
2010
- case size >= 4:
2011
- return "h-[12px]";
2012
- default:
2013
- return "h-[1px]";
2014
- }
2015
- };
2016
- const formatTimestamp = (isoString) => {
2017
- if (!isoString)
2018
- return "";
2019
- try {
2020
- const date = parseISO(isoString);
2021
- return format(date, "HH:mm, dd, MMMM");
2022
- } catch {
2023
- return isoString;
2024
- }
2025
- };
2026
- const TimelineBar = ({ onClick, className, timestamp, additions, deletions, addSize = 0, delSize = 0, isSelected = false }) => {
2027
- const [open, setOpen] = useState(false);
2028
- const noChanges = addSize === 0 && delSize === 0;
2029
- const addBarHeight = getBarHeight(addSize);
2030
- const delBarHeight = getBarHeight(delSize);
2031
- const tooltipContent = jsxs("div", { className: "flex flex-col text-xs", children: [jsx("div", { children: formatTimestamp(timestamp) }), jsx("div", { className: "text-green-900", children: `${additions} additions +` }), jsx("div", { className: "text-red-700", children: `${deletions} deletions -` })] });
2032
- const handleMouseEnter = () => {
2033
- if (!noChanges) {
2034
- setOpen(true);
2035
- }
2036
- };
2037
- const handleMouseLeave = () => {
2038
- setOpen(false);
2039
- };
2040
- return jsxs("div", { className: "relative", onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave, children: [isSelected && jsx(Icon, { name: "TimelineCaret", color: "#4EA9FF", size: 10, className: "absolute left-[-2px] top-[-11px] z-40" }), noChanges ? jsx("div", { className: twMerge("flex h-[25px] w-1.5 cursor-pointer flex-col items-center justify-center rounded-[2px] hover:bg-blue-300", className), "data-timestamp": timestamp, onClick, children: jsx("div", { className: "size-[3px] rounded-full bg-gray-500" }) }) : jsx(Tooltip, { className: "rounded-md bg-gray-900 text-white", content: tooltipContent, open, onOpenChange: setOpen, delayDuration: 0, side: "bottom", sideOffset: 5, children: jsxs("div", { className: twMerge("flex h-[25px] w-1.5 cursor-pointer flex-col items-center justify-center rounded-[2px] hover:bg-blue-300", className, isSelected && "bg-blue-300"), "data-timestamp": timestamp, onClick, children: [jsx("div", { className: "flex h-3 w-0.5 items-end", children: jsx("div", { className: twMerge("h-3 w-0.5 rounded-t-full bg-green-600", addBarHeight) }) }), jsx("div", { className: "flex h-3 w-0.5 items-start", children: jsx("div", { className: twMerge("h-3 w-0.5 rounded-b-full bg-red-600", delBarHeight) }) })] }) })] });
2041
- };
2042
- const defaultTimeLineItem = {
2043
- id: "default",
2044
- type: "bar",
2045
- addSize: 0,
2046
- delSize: 0
2047
- };
2048
- const DocumentTimeline = (props) => {
2049
- const { timeline = [], onItemClick } = props;
2050
- const [selectedItem, setSelectedItem] = useState(null);
2051
- const scrollContainerRef = useRef(null);
2052
- const handleClick = (item) => {
2053
- if (item.id === selectedItem || item.id === defaultTimeLineItem.id) {
2054
- onItemClick == null ? void 0 : onItemClick(null);
2055
- setSelectedItem(null);
2056
- } else {
2057
- onItemClick == null ? void 0 : onItemClick(item);
2058
- setSelectedItem(item.id);
2059
- }
2060
- };
2061
- const mergedTimelineItems = [...timeline, defaultTimeLineItem];
2062
- const [unselectedItems, selectedItems] = useMemo(() => {
2063
- const indexSelected = mergedTimelineItems.findIndex((item) => item.id === selectedItem);
2064
- return indexSelected === -1 ? [mergedTimelineItems, []] : [
2065
- mergedTimelineItems.slice(0, indexSelected),
2066
- mergedTimelineItems.slice(indexSelected)
2067
- ];
2068
- }, [mergedTimelineItems, selectedItem]);
2069
- const renderTimelineItems = useCallback((items) => {
2070
- return items.map((item) => {
2071
- if (item.type === "divider") {
2072
- const { timestamp, title, subtitle } = item;
2073
- return jsx(HDivider, { timestamp, title, subtitle, onClick: () => handleClick(item), isSelected: item.id === selectedItem }, item.id);
2074
- }
2075
- return jsx(TimelineBar, { timestamp: item.timestamp, addSize: item.addSize, delSize: item.delSize, additions: item.additions, deletions: item.deletions, isSelected: item.id === selectedItem, onClick: () => handleClick(item) }, item.id);
2076
- });
2077
- }, [handleClick, selectedItem]);
2078
- const unselectedContent = useMemo(() => renderTimelineItems(unselectedItems), [unselectedItems, renderTimelineItems]);
2079
- const selectedContent = useMemo(() => renderTimelineItems(selectedItems), [selectedItems, renderTimelineItems]);
2080
- useEffect(() => {
2081
- if (scrollContainerRef.current) {
2082
- scrollContainerRef.current.scrollLeft = scrollContainerRef.current.scrollWidth;
2083
- }
2084
- }, []);
2085
- return jsx(TooltipProvider, { delayDuration: 0, skipDelayDuration: 0, children: jsxs("div", { className: "relative h-[36px] w-full", children: [jsx("div", { className: "absolute left-[0px] z-[20] h-[17px] w-[6px] bg-white", children: jsx("div", { className: "mt-[11px] h-[6px] w-[6px] rounded-tl-md bg-slate-50" }) }), jsx("div", { className: "absolute right-[0px] top-[11px] z-[20] h-[6px] w-[6px] bg-white", children: jsx("div", { className: "h-[6px] w-[6px] rounded-tr-md bg-slate-50" }) }), jsx("div", { className: "absolute inset-x-0 bottom-0 h-[25px] rounded-md bg-slate-50" }), jsx("div", { className: "absolute inset-x-0 bottom-0 h-[36px]", children: jsx("div", { ref: scrollContainerRef, className: "h-full overflow-x-auto rounded-md", children: jsxs("div", { className: "ml-auto flex h-[36px] w-max items-end px-2 pb-0", children: [jsx("div", { className: "flex", children: unselectedContent }), jsx("div", { className: "flex rounded-sm bg-blue-200", children: selectedContent })] }) }) }), jsx("div", { className: "pointer-events-none absolute bottom-0 left-0 z-10 h-[25px] w-2 rounded-l-md bg-slate-50" }), jsx("div", { className: "pointer-events-none absolute bottom-0 right-0 z-10 h-[25px] w-2 rounded-r-md bg-slate-50" })] }) });
2086
- };
2087
- const DocumentToolbar = (props) => {
2088
- const { undo: undo2, canUndo, redo: redo2, canRedo, title, onClose, onExport, className, onShowRevisionHistory, onSwitchboardLinkClick, timelineItems = [], onTimelineItemClick, initialTimelineVisible = false, timelineButtonVisible = false } = props;
2089
- const [showTimeline, setShowTimeline] = useState(initialTimelineVisible);
2090
- const isUndoDisabled = !canUndo || !undo2;
2091
- const isRedoDisabled = !canRedo || !redo2;
2092
- const isExportDisabled = !onExport;
2093
- const isSwitchboardLinkDisabled = !onSwitchboardLinkClick;
2094
- const isRevisionHistoryDisabled = !onShowRevisionHistory;
2095
- const isTimelineDisabled = timelineItems.length === 0;
2096
- useEffect(() => {
2097
- if (initialTimelineVisible) {
2098
- setShowTimeline(true);
2099
- }
2100
- }, [initialTimelineVisible]);
2101
- const handleTimelineToggle = () => {
2102
- if (isTimelineDisabled)
2103
- return;
2104
- setShowTimeline(!showTimeline);
2105
- };
2106
- return jsxs("div", { className: "flex w-full flex-col", children: [jsxs("div", { className: twMerge("flex h-12 w-full items-center justify-between rounded-xl border border-gray-200 bg-slate-50 px-4", className), children: [jsxs("div", { className: "flex items-center gap-x-2", children: [jsx("button", { className: twMerge("grid size-8 place-items-center rounded-lg border border-gray-200 bg-white", isUndoDisabled ? "cursor-not-allowed" : "cursor-pointer active:opacity-70"), onClick: undo2, disabled: isUndoDisabled, children: jsx(Icon, { name: "ArrowCouterclockwise", size: 16, className: isUndoDisabled ? "text-gray-500" : "text-gray-900" }) }), jsx("button", { className: twMerge("grid size-8 place-items-center rounded-lg border border-gray-200 bg-white", isRedoDisabled ? "cursor-not-allowed" : "cursor-pointer active:opacity-70"), onClick: redo2, disabled: isRedoDisabled, children: jsx("div", { className: "-scale-x-100", children: jsx(Icon, { name: "ArrowCouterclockwise", size: 16, className: isRedoDisabled ? "text-gray-500" : "text-gray-900" }) }) }), jsx("button", { className: twMerge("flex h-8 items-center rounded-lg border border-gray-200 bg-white px-3 text-sm", isExportDisabled ? "cursor-not-allowed" : "cursor-pointer active:opacity-70"), onClick: onExport, disabled: isExportDisabled, children: jsx("span", { className: isExportDisabled ? "text-gray-500" : "text-gray-900", children: "Export" }) })] }), jsx("div", { className: "flex items-center", children: jsx("h1", { className: "text-sm font-medium text-gray-500", children: title }) }), jsxs("div", { className: "flex items-center gap-x-2", children: [jsx("button", { className: twMerge("grid size-8 place-items-center rounded-lg border border-gray-200 bg-white", isSwitchboardLinkDisabled ? "cursor-not-allowed" : "cursor-pointer active:opacity-70"), onClick: onSwitchboardLinkClick, disabled: isSwitchboardLinkDisabled, children: jsx(Icon, { name: "Drive", size: 16, className: isSwitchboardLinkDisabled ? "text-gray-500" : "text-gray-900" }) }), jsx("button", { className: twMerge("grid size-8 place-items-center rounded-lg border border-gray-200 bg-white", isRevisionHistoryDisabled ? "cursor-not-allowed" : "cursor-pointer active:opacity-70"), onClick: onShowRevisionHistory, disabled: isRevisionHistoryDisabled, children: jsx(Icon, { name: "History", size: 16, className: isRevisionHistoryDisabled ? "text-gray-500" : "text-gray-900" }) }), timelineButtonVisible && jsx("button", { className: twMerge("grid size-8 place-items-center rounded-lg border border-gray-200 bg-white", isTimelineDisabled ? "cursor-not-allowed" : "cursor-pointer active:opacity-70"), onClick: handleTimelineToggle, disabled: isTimelineDisabled, "aria-pressed": showTimeline, children: jsx(Icon, { name: "Timeline", size: 16, className: twMerge("text-gray-900", isTimelineDisabled && "opacity-50", showTimeline && "text-blue-600") }) }), jsx("button", { className: "grid size-8 cursor-pointer place-items-center rounded-lg border border-gray-200 bg-white active:opacity-70", onClick: onClose, children: jsx(Icon, { name: "XmarkLight", size: 16, className: "text-gray-900" }) })] })] }), showTimeline && jsx("div", { className: "mt-2 w-full", children: jsx(DocumentTimeline, { timeline: timelineItems, onItemClick: onTimelineItemClick }) })] });
2107
- };
2108
- const syncIcons = {
2109
- SYNCING: "Syncing",
2110
- SUCCESS: "Synced",
2111
- CONFLICT: "Error",
2112
- MISSING: "Circle",
2113
- ERROR: "Error",
2114
- INITIAL_SYNC: "Syncing"
2115
- };
2116
- function SyncStatusIcon(props) {
2117
- const { syncStatus, className, overrideSyncIcons = {}, ...iconProps } = props;
2118
- const icons = { ...syncIcons, ...overrideSyncIcons };
2119
- const syncStatusIcons = {
2120
- [INITIAL_SYNC]: jsx(Icon, { size: 16, ...iconProps, className: twMerge("text-blue-900", className), name: icons[INITIAL_SYNC] }),
2121
- [SYNCING]: jsx(Icon, { size: 16, ...iconProps, className: twMerge("text-blue-900", className), name: icons[SYNCING] }),
2122
- [SUCCESS]: jsx(Icon, { size: 16, ...iconProps, className: twMerge("text-green-900", className), name: icons[SUCCESS] }),
2123
- [CONFLICT]: jsx(Icon, { size: 16, ...iconProps, className: twMerge("text-orange-900", className), name: icons[CONFLICT] }),
2124
- [MISSING]: jsx(Icon, { size: 16, ...iconProps, className: twMerge("text-red-900", className), name: icons[MISSING] }),
2125
- [ERROR]: jsx(Icon, { size: 16, ...iconProps, className: twMerge("text-red-900", className), name: icons[ERROR] })
2126
- };
2127
- return syncStatusIcons[syncStatus];
2128
- }
2129
- function FileItem(props) {
2130
- const { uiNode, className, customDocumentIconSrc, onSelectNode, onRenameNode, onDuplicateNode, onDeleteNode, isAllowedToCreateDocuments } = props;
2131
- const [mode, setMode] = useState(READ);
2132
- const [isDropdownMenuOpen, setIsDropdownMenuOpen] = useState(false);
2133
- const { dragProps } = useDrag({ uiNode });
2134
- const isReadMode = mode === READ;
2135
- const dropdownMenuHandlers = {
2136
- [DUPLICATE]: () => onDuplicateNode(uiNode),
2137
- [RENAME]: () => setMode(WRITE),
2138
- [DELETE]: () => onDeleteNode(uiNode)
2139
- };
2140
- const dropdownMenuOptions = Object.entries(nodeOptionsMap).map(([id, option]) => ({
2141
- ...option,
2142
- id
2143
- })).filter((option) => defaultFileOptions.includes(option.id));
2144
- function onSubmit(name) {
2145
- onRenameNode(name, uiNode);
2146
- setMode(READ);
2147
- }
2148
- function onCancel() {
2149
- setMode(READ);
2150
- }
2151
- function onClick() {
2152
- onSelectNode(uiNode);
2153
- }
2154
- function onDropdownMenuOptionClick(itemId) {
2155
- const handler = dropdownMenuHandlers[itemId];
2156
- if (!handler) {
2157
- console.error(`No handler found for dropdown menu item: ${itemId}`);
2158
- return;
2159
- }
2160
- handler();
2161
- setIsDropdownMenuOpen(false);
2162
- }
2163
- const iconSrc = getDocumentIconSrc(uiNode.documentType, customDocumentIconSrc);
2164
- const iconNode = jsxs("div", { className: "relative", children: [jsx("img", { alt: "file icon", className: "max-w-none", height: 34, src: iconSrc, width: 32 }), isReadMode && uiNode.syncStatus && jsx("div", { className: "absolute bottom-[-2px] right-0 size-3 rounded-full bg-white", children: jsx("div", { className: "absolute left-[-2px] top-[-2px]", children: jsx(SyncStatusIcon, { overrideSyncIcons: { SUCCESS: "CheckCircleFill" }, syncStatus: uiNode.syncStatus }) }) })] });
2165
- const containerStyles = twMerge("group flex h-12 cursor-pointer select-none items-center rounded-lg bg-gray-200 px-2 text-gray-600 hover:text-gray-800", className);
2166
- const content = isReadMode ? jsxs("div", { className: "flex w-52 items-center justify-between", children: [jsxs("div", { className: "mr-2 truncate group-hover:mr-0", children: [jsx("div", { className: "max-h-6 truncate text-sm font-medium group-hover:text-gray-800", children: uiNode.name }), jsx("div", { className: "max-h-6 truncate text-xs font-medium text-gray-600 group-hover:text-gray-800", children: uiNode.documentType })] }), isAllowedToCreateDocuments ? jsx(ConnectDropdownMenu, { items: dropdownMenuOptions, onItemClick: onDropdownMenuOptionClick, onOpenChange: setIsDropdownMenuOpen, open: isDropdownMenuOpen, children: jsx("button", { className: twMerge("hidden group-hover:block", isDropdownMenuOpen && "block"), onClick: (e) => {
2167
- e.stopPropagation();
2168
- setIsDropdownMenuOpen(true);
2169
- }, children: jsx(Icon, { className: "text-gray-600", name: "VerticalDots" }) }) }) : null] }) : jsx(NodeInput, { className: "ml-3 flex-1 font-medium", defaultValue: uiNode.name, onCancel, onSubmit });
2170
- return jsx("div", { className: "relative w-64", onClick, children: jsx("div", { ...dragProps, className: containerStyles, children: jsxs("div", { className: "flex items-center", children: [jsx("div", { className: "mr-1.5", children: iconNode }), content] }) }) });
2171
- }
2172
- function FolderItem(props) {
2173
- const { uiNode, isAllowedToCreateDocuments, className, onRenameNode, onDuplicateNode, onDeleteNode, onSelectNode, onAddFile, onCopyNode, onMoveNode } = props;
2174
- const [mode, setMode] = useState(READ);
2175
- const [isDropdownMenuOpen, setIsDropdownMenuOpen] = useState(false);
2176
- const { dragProps } = useDrag({ ...props, uiNode });
2177
- const { isDropTarget, dropProps } = useDrop({
2178
- uiNode,
2179
- onAddFile,
2180
- onCopyNode,
2181
- onMoveNode
2182
- });
2183
- const isReadMode = mode === READ;
2184
- function onCancel() {
2185
- setMode(READ);
2186
- }
2187
- function onSubmit(name) {
2188
- onRenameNode(name, uiNode);
2189
- setMode(READ);
2190
- }
2191
- function onClick() {
2192
- onSelectNode(uiNode);
2193
- }
2194
- const dropdownMenuHandlers = {
2195
- [DUPLICATE]: () => onDuplicateNode(uiNode),
2196
- [RENAME]: () => setMode(WRITE),
2197
- [DELETE]: () => onDeleteNode(uiNode)
2198
- };
2199
- const dropdownMenuOptions = Object.entries(nodeOptionsMap).map(([id, option]) => ({
2200
- ...option,
2201
- id
2202
- })).filter((option) => defaultFolderOptions.includes(option.id));
2203
- function onDropdownMenuOptionClick(itemId) {
2204
- const handler = dropdownMenuHandlers[itemId];
2205
- if (!handler) {
2206
- console.error(`No handler found for dropdown menu item: ${itemId}`);
2207
- return;
2208
- }
2209
- handler();
2210
- setIsDropdownMenuOpen(false);
2211
- }
2212
- const content = isReadMode || !isAllowedToCreateDocuments ? jsx("div", { className: "ml-3 max-h-6 truncate font-medium text-gray-600 group-hover:text-gray-800", children: uiNode.name }) : jsx(NodeInput, { className: "ml-3 font-medium", defaultValue: uiNode.name, onCancel, onSubmit });
2213
- const containerStyles = twMerge("group flex h-12 cursor-pointer select-none items-center rounded-lg bg-gray-200 px-2", className, isDropTarget && "bg-blue-100");
2214
- return jsx("div", { className: "relative w-64", onClick, children: jsxs("div", { ...dragProps, ...dropProps, className: containerStyles, children: [jsxs("div", { className: "flex items-center overflow-hidden", children: [jsx("div", { className: "p-1", children: jsxs("div", { className: "relative", children: [jsx(Icon, { name: "FolderClose", size: 24 }), isReadMode && uiNode.syncStatus ? jsx("div", { className: "absolute bottom-[-3px] right-[-2px] size-3 rounded-full bg-white", children: jsx("div", { className: "absolute left-[-2px] top-[-2px]", children: jsx(SyncStatusIcon, { overrideSyncIcons: {
2215
- SUCCESS: "CheckCircleFill"
2216
- }, syncStatus: uiNode.syncStatus }) }) }) : null] }) }), content] }), isReadMode && isAllowedToCreateDocuments ? jsx(ConnectDropdownMenu, { items: dropdownMenuOptions, onItemClick: onDropdownMenuOptionClick, onOpenChange: setIsDropdownMenuOpen, open: isDropdownMenuOpen, children: jsx("button", { className: twMerge("ml-auto hidden group-hover:block", isDropdownMenuOpen && "block"), onClick: (e) => {
2217
- e.stopPropagation();
2218
- setIsDropdownMenuOpen(true);
2219
- }, children: jsx(Icon, { className: "text-gray-600", name: "VerticalDots" }) }) }) : null] }) });
2220
- }
2221
- function NodeInput(props) {
2222
- const { onSubmit, onCancel, defaultValue, className, minLength = 1, ...inputProps } = props;
2223
- const [value, setValue] = useState(defaultValue ?? "");
2224
- const ref = useRef(null);
2225
- useOnClickOutside(ref, handleSubmit);
2226
- useEventListener("keyup", (e) => {
2227
- if (e.key === "Enter") {
2228
- handleSubmit();
2229
- }
2230
- if (e.key === "Escape") {
2231
- onCancel();
2232
- }
2233
- });
2234
- useLayoutEffect(() => {
2235
- setTimeout(() => {
2236
- var _a, _b, _c;
2237
- (_a = ref.current) == null ? void 0 : _a.focus();
2238
- (_b = ref.current) == null ? void 0 : _b.select();
2239
- (_c = ref.current) == null ? void 0 : _c.scroll({ left: 9999 });
2240
- }, 100);
2241
- }, []);
2242
- function handleSubmit() {
2243
- if (value.length >= minLength) {
2244
- onSubmit(value);
2245
- }
2246
- }
2247
- return jsx("input", { ...inputProps, autoFocus: true, className: twMerge("bg-inherit text-inherit outline-none", className), minLength, onChange: (e) => setValue(e.target.value), ref, required: true, type: "text", value });
2248
- }
2249
- function Branch(props) {
2250
- const { branch = "main" } = props;
2251
- return jsxs("button", { className: "flex h-8 items-center gap-1 rounded-lg bg-slate-50 pl-1 pr-2 text-xs text-slate-100", children: [jsx(Icon, { name: "Branch" }), jsx("span", { children: "BRANCH" }), jsx("span", { className: "text-gray-900", children: branch })] });
2252
- }
2253
- function DocId(props) {
2254
- const { docId } = props;
2255
- const [, copy] = useCopyToClipboard();
2256
- function handleCopy(text) {
2257
- return () => {
2258
- copy(text).catch((error) => {
2259
- console.error("Failed to copy!", error);
2260
- });
2261
- };
2262
- }
2263
- return jsxs("button", { className: "flex h-8 items-center gap-1 rounded-lg bg-slate-50 pl-1 pr-2 text-xs text-slate-100", onClick: handleCopy(docId), children: [jsx(Icon, { name: "Link" }), "DOC ID", jsx("span", { className: "text-gray-900", children: docId })] });
2264
- }
2265
- function Scope(props) {
2266
- const { value, onChange } = props;
2267
- const items = [
2268
- { displayValue: "Global scope", value: "global" },
2269
- { displayValue: "Local scope", value: "local" }
2270
- ];
2271
- return jsx(Select, { absolutePositionMenu: true, containerClassName: "bg-slate-50 text-gray-500 rounded-lg w-fit text-xs z-10", id: "scope select", itemClassName: "py-2 text-gray-500 grid grid-cols-[auto,auto] gap-1", items, menuClassName: "min-w-0 text-gray-500", onChange, value });
2272
- }
2273
- function Header(props) {
2274
- const { title, docId, scope, onChangeScope, onClose, className, ...divProps } = props;
2275
- return jsxs("header", { className: twMerge("flex items-center justify-between bg-transparent", className), ...divProps, children: [jsxs("div", { className: "flex items-center gap-3", children: [jsx("button", { className: "shadow-button rounded-lg bg-gray-50 p-1 text-slate-100", onClick: onClose, children: jsx(Icon, { name: "VariantArrowLeft" }) }), jsx("h1", { className: "text-xs", children: title })] }), jsxs("div", { className: "flex items-center gap-2", children: [jsx(DocId, { docId }), jsx(Branch, {}), jsx(Scope, { onChange: onChangeScope, value: scope })] })] });
2276
- }
2277
- function memo(getDeps, fn, opts) {
2278
- let deps = opts.initialDeps ?? [];
2279
- let result;
2280
- return () => {
2281
- var _a, _b, _c, _d;
2282
- let depTime;
2283
- if (opts.key && ((_a = opts.debug) == null ? void 0 : _a.call(opts))) depTime = Date.now();
2284
- const newDeps = getDeps();
2285
- const depsChanged = newDeps.length !== deps.length || newDeps.some((dep, index) => deps[index] !== dep);
2286
- if (!depsChanged) {
2287
- return result;
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) {
@@ -2324,7 +1874,7 @@ function notUndefined(value, msg) {
2324
1874
  return value;
2325
1875
  }
2326
1876
  }
2327
- const approxEqual = (a, b) => Math.abs(a - b) < 1;
1877
+ const approxEqual = (a, b) => Math.abs(a - b) <= 1;
2328
1878
  const debounce = (targetWindow, fn, ms) => {
2329
1879
  let timeoutId;
2330
1880
  return function(...args) {
@@ -2332,6 +1882,10 @@ const debounce = (targetWindow, fn, ms) => {
2332
1882
  timeoutId = targetWindow.setTimeout(() => fn.apply(this, args), ms);
2333
1883
  };
2334
1884
  };
1885
+ const getRect = (element) => {
1886
+ const { offsetWidth, offsetHeight } = element;
1887
+ return { width: offsetWidth, height: offsetHeight };
1888
+ };
2335
1889
  const defaultKeyExtractor = (index) => index;
2336
1890
  const defaultRangeExtractor = (range) => {
2337
1891
  const start = Math.max(range.startIndex - range.overscan, 0);
@@ -2355,21 +1909,24 @@ const observeElementRect = (instance, cb) => {
2355
1909
  const { width, height } = rect;
2356
1910
  cb({ width: Math.round(width), height: Math.round(height) });
2357
1911
  };
2358
- handler(element.getBoundingClientRect());
1912
+ handler(getRect(element));
2359
1913
  if (!targetWindow.ResizeObserver) {
2360
1914
  return () => {
2361
1915
  };
2362
1916
  }
2363
1917
  const observer = new targetWindow.ResizeObserver((entries) => {
2364
- const entry = entries[0];
2365
- if (entry == null ? void 0 : entry.borderBoxSize) {
2366
- const box = entry.borderBoxSize[0];
2367
- if (box) {
2368
- handler({ width: box.inlineSize, height: box.blockSize });
2369
- return;
1918
+ const run = () => {
1919
+ const entry = entries[0];
1920
+ if (entry == null ? void 0 : entry.borderBoxSize) {
1921
+ const box = entry.borderBoxSize[0];
1922
+ if (box) {
1923
+ handler({ width: box.inlineSize, height: box.blockSize });
1924
+ return;
1925
+ }
2370
1926
  }
2371
- }
2372
- handler(element.getBoundingClientRect());
1927
+ handler(getRect(element));
1928
+ };
1929
+ instance.options.useAnimationFrameWithResizeObserver ? requestAnimationFrame(run) : run();
2373
1930
  });
2374
1931
  observer.observe(element, { box: "border-box" });
2375
1932
  return () => {
@@ -2407,10 +1964,15 @@ const observeElementOffset = (instance, cb) => {
2407
1964
  const endHandler = createHandler(false);
2408
1965
  endHandler();
2409
1966
  element.addEventListener("scroll", handler, addEventListenerOptions);
2410
- element.addEventListener("scrollend", endHandler, addEventListenerOptions);
1967
+ const registerScrollendEvent = instance.options.useScrollendEvent && supportsScrollend;
1968
+ if (registerScrollendEvent) {
1969
+ element.addEventListener("scrollend", endHandler, addEventListenerOptions);
1970
+ }
2411
1971
  return () => {
2412
1972
  element.removeEventListener("scroll", handler);
2413
- element.removeEventListener("scrollend", endHandler);
1973
+ if (registerScrollendEvent) {
1974
+ element.removeEventListener("scrollend", endHandler);
1975
+ }
2414
1976
  };
2415
1977
  };
2416
1978
  const measureElement = (element, entry, instance) => {
@@ -2423,9 +1985,7 @@ const measureElement = (element, entry, instance) => {
2423
1985
  return size;
2424
1986
  }
2425
1987
  }
2426
- return Math.round(
2427
- element.getBoundingClientRect()[instance.options.horizontal ? "width" : "height"]
2428
- );
1988
+ return element[instance.options.horizontal ? "offsetWidth" : "offsetHeight"];
2429
1989
  };
2430
1990
  const elementScroll = (offset, {
2431
1991
  adjustments = 0,
@@ -2464,7 +2024,10 @@ class Virtualizer {
2464
2024
  }
2465
2025
  return _ro = new this.targetWindow.ResizeObserver((entries) => {
2466
2026
  entries.forEach((entry) => {
2467
- this._measureElement(entry.target, entry);
2027
+ const run = () => {
2028
+ this._measureElement(entry.target, entry);
2029
+ };
2030
+ this.options.useAnimationFrameWithResizeObserver ? requestAnimationFrame(run) : run();
2468
2031
  });
2469
2032
  });
2470
2033
  };
@@ -2512,7 +2075,8 @@ class Virtualizer {
2512
2075
  isScrollingResetDelay: 150,
2513
2076
  enabled: true,
2514
2077
  isRtl: false,
2515
- useScrollendEvent: true,
2078
+ useScrollendEvent: false,
2079
+ useAnimationFrameWithResizeObserver: false,
2516
2080
  ...opts2
2517
2081
  };
2518
2082
  };
@@ -2701,12 +2265,18 @@ class Virtualizer {
2701
2265
  }
2702
2266
  );
2703
2267
  this.calculateRange = memo(
2704
- () => [this.getMeasurements(), this.getSize(), this.getScrollOffset()],
2705
- (measurements, outerSize, scrollOffset) => {
2268
+ () => [
2269
+ this.getMeasurements(),
2270
+ this.getSize(),
2271
+ this.getScrollOffset(),
2272
+ this.options.lanes
2273
+ ],
2274
+ (measurements, outerSize, scrollOffset, lanes) => {
2706
2275
  return this.range = measurements.length > 0 && outerSize > 0 ? calculateRange({
2707
2276
  measurements,
2708
2277
  outerSize,
2709
- scrollOffset
2278
+ scrollOffset,
2279
+ lanes
2710
2280
  }) : null;
2711
2281
  },
2712
2282
  {
@@ -2714,7 +2284,7 @@ class Virtualizer {
2714
2284
  debug: () => this.options.debug
2715
2285
  }
2716
2286
  );
2717
- this.getIndexes = memo(
2287
+ this.getVirtualIndexes = memo(
2718
2288
  () => {
2719
2289
  let startIndex = null;
2720
2290
  let endIndex = null;
@@ -2723,6 +2293,7 @@ class Virtualizer {
2723
2293
  startIndex = range.startIndex;
2724
2294
  endIndex = range.endIndex;
2725
2295
  }
2296
+ this.maybeNotify.updateDeps([this.isScrolling, startIndex, endIndex]);
2726
2297
  return [
2727
2298
  this.options.rangeExtractor,
2728
2299
  this.options.overscan,
@@ -2806,7 +2377,7 @@ class Virtualizer {
2806
2377
  this._measureElement(node, void 0);
2807
2378
  };
2808
2379
  this.getVirtualItems = memo(
2809
- () => [this.getIndexes(), this.getMeasurements()],
2380
+ () => [this.getVirtualIndexes(), this.getMeasurements()],
2810
2381
  (indexes, measurements) => {
2811
2382
  const virtualItems = [];
2812
2383
  for (let k = 0, len = indexes.length; k < len; k++) {
@@ -2835,20 +2406,18 @@ class Virtualizer {
2835
2406
  )]
2836
2407
  );
2837
2408
  };
2838
- this.getOffsetForAlignment = (toOffset, align) => {
2409
+ this.getOffsetForAlignment = (toOffset, align, itemSize = 0) => {
2839
2410
  const size = this.getSize();
2840
2411
  const scrollOffset = this.getScrollOffset();
2841
2412
  if (align === "auto") {
2842
- if (toOffset >= scrollOffset + size) {
2843
- align = "end";
2844
- }
2413
+ align = toOffset >= scrollOffset + size ? "end" : "start";
2845
2414
  }
2846
- if (align === "end") {
2415
+ if (align === "center") {
2416
+ toOffset += (itemSize - size) / 2;
2417
+ } else if (align === "end") {
2847
2418
  toOffset -= size;
2848
2419
  }
2849
- const scrollSizeProp = this.options.horizontal ? "scrollWidth" : "scrollHeight";
2850
- const scrollSize = this.scrollElement ? "document" in this.scrollElement ? this.scrollElement.document.documentElement[scrollSizeProp] : this.scrollElement[scrollSizeProp] : 0;
2851
- const maxOffset = scrollSize - size;
2420
+ const maxOffset = this.getTotalSize() - size;
2852
2421
  return Math.max(Math.min(maxOffset, toOffset), 0);
2853
2422
  };
2854
2423
  this.getOffsetForIndex = (index, align = "auto") => {
@@ -2868,27 +2437,11 @@ class Virtualizer {
2868
2437
  return [scrollOffset, align];
2869
2438
  }
2870
2439
  }
2871
- const centerOffset = item.start - this.options.scrollPaddingStart + (item.size - size) / 2;
2872
- switch (align) {
2873
- case "center":
2874
- return [this.getOffsetForAlignment(centerOffset, align), align];
2875
- case "end":
2876
- return [
2877
- this.getOffsetForAlignment(
2878
- item.end + this.options.scrollPaddingEnd,
2879
- align
2880
- ),
2881
- align
2882
- ];
2883
- default:
2884
- return [
2885
- this.getOffsetForAlignment(
2886
- item.start - this.options.scrollPaddingStart,
2887
- align
2888
- ),
2889
- align
2890
- ];
2891
- }
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 = () => {
@@ -2931,7 +2484,8 @@ class Virtualizer {
2931
2484
  const [latestOffset] = notUndefined(
2932
2485
  this.getOffsetForIndex(index, align)
2933
2486
  );
2934
- if (!approxEqual(latestOffset, this.getScrollOffset())) {
2487
+ const currentScrollOffset = this.getScrollOffset();
2488
+ if (!approxEqual(latestOffset, currentScrollOffset)) {
2935
2489
  this.scrollToIndex(index, { align, behavior });
2936
2490
  }
2937
2491
  } else {
@@ -2958,10 +2512,19 @@ class Virtualizer {
2958
2512
  let end;
2959
2513
  if (measurements.length === 0) {
2960
2514
  end = this.options.paddingStart;
2515
+ } else if (this.options.lanes === 1) {
2516
+ end = ((_a = measurements[measurements.length - 1]) == null ? void 0 : _a.end) ?? 0;
2961
2517
  } else {
2962
- end = this.options.lanes === 1 ? ((_a = measurements[measurements.length - 1]) == null ? void 0 : _a.end) ?? 0 : Math.max(
2963
- ...measurements.slice(-this.options.lanes).map((m) => m.end)
2964
- );
2518
+ const endByLane = Array(this.options.lanes).fill(null);
2519
+ let endIndex = measurements.length - 1;
2520
+ while (endIndex >= 0 && endByLane.some((val) => val === null)) {
2521
+ const item = measurements[endIndex];
2522
+ if (endByLane[item.lane] === null) {
2523
+ endByLane[item.lane] = item.end;
2524
+ }
2525
+ endIndex--;
2526
+ }
2527
+ end = Math.max(...endByLane.filter((val) => val !== null));
2965
2528
  }
2966
2529
  return Math.max(
2967
2530
  end - this.options.scrollMargin + this.options.paddingEnd,
@@ -3002,14 +2565,43 @@ const findNearestBinarySearch = (low, high, getCurrentValue, value) => {
3002
2565
  function calculateRange({
3003
2566
  measurements,
3004
2567
  outerSize,
3005
- scrollOffset
2568
+ scrollOffset,
2569
+ lanes
3006
2570
  }) {
3007
- const count = measurements.length - 1;
2571
+ const lastIndex = measurements.length - 1;
3008
2572
  const getOffset = (index) => measurements[index].start;
3009
- const startIndex = findNearestBinarySearch(0, count, getOffset, scrollOffset);
2573
+ if (measurements.length <= lanes) {
2574
+ return {
2575
+ startIndex: 0,
2576
+ endIndex: lastIndex
2577
+ };
2578
+ }
2579
+ let startIndex = findNearestBinarySearch(
2580
+ 0,
2581
+ lastIndex,
2582
+ getOffset,
2583
+ scrollOffset
2584
+ );
3010
2585
  let endIndex = startIndex;
3011
- while (endIndex < count && measurements[endIndex].end < scrollOffset + outerSize) {
3012
- endIndex++;
2586
+ if (lanes === 1) {
2587
+ while (endIndex < lastIndex && measurements[endIndex].end < scrollOffset + outerSize) {
2588
+ endIndex++;
2589
+ }
2590
+ } else if (lanes > 1) {
2591
+ const endPerLane = Array(lanes).fill(0);
2592
+ while (endIndex < lastIndex && endPerLane.some((pos) => pos < scrollOffset + outerSize)) {
2593
+ const item = measurements[endIndex];
2594
+ endPerLane[item.lane] = item.end;
2595
+ endIndex++;
2596
+ }
2597
+ const startPerLane = Array(lanes).fill(scrollOffset + outerSize);
2598
+ while (startIndex >= 0 && startPerLane.some((pos) => pos >= scrollOffset)) {
2599
+ const item = measurements[startIndex];
2600
+ startPerLane[item.lane] = item.start;
2601
+ startIndex--;
2602
+ }
2603
+ startIndex = Math.max(0, startIndex - startIndex % lanes);
2604
+ endIndex = Math.min(lastIndex, endIndex + (lanes - 1 - endIndex % lanes));
3013
2605
  }
3014
2606
  return { startIndex, endIndex };
3015
2607
  }
@@ -3266,8 +2858,8 @@ function RevisionHistory(props) {
3266
2858
  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
2859
  }
3268
2860
  function Tooltip(props) {
3269
- const { children, content, open, defaultOpen, onOpenChange, className, side = "top", sideOffset = 5, ...rest } = props;
3270
- return jsxs(Root3, { defaultOpen, delayDuration: 0, onOpenChange, open, children: [jsx(Trigger, { asChild: true, children }), jsx(Portal, { children: jsx(Content2, { ...rest, side, sideOffset, className: twMerge("shadow-tooltip rounded-lg border border-gray-200 bg-white p-2 text-xs", className), children: content }) })] });
2861
+ const { children, content, open, defaultOpen, onOpenChange, className, ...rest } = props;
2862
+ return jsxs(Root3, { defaultOpen, delayDuration: 0, onOpenChange, open, children: [jsx(Trigger, { asChild: true, children }), jsx(Portal, { children: jsx(Content2, { ...rest, className: twMerge("shadow-tooltip rounded-lg border border-gray-200 bg-white p-2 text-xs", className), children: content }) })] });
3271
2863
  }
3272
2864
  const TooltipProvider = Provider;
3273
2865
  const BUDGET = "powerhouse/budget-statement";
@@ -3515,7 +3107,9 @@ function useAddDebouncedOperations(reactor, props) {
3515
3107
  const { driveId, documentId } = props;
3516
3108
  const [documentDrives] = useDocumentDrives(reactor);
3517
3109
  const documentDrivesRef = useRef(documentDrives);
3518
- const { isAllowedToEditDocuments } = useUserPermissions();
3110
+ const { isAllowedToEditDocuments } = useUserPermissions() || {
3111
+ isAllowedToEditDocuments: false
3112
+ };
3519
3113
  useEffect(() => {
3520
3114
  documentDrivesRef.current = documentDrives;
3521
3115
  }, [documentDrives]);
@@ -3526,7 +3120,7 @@ function useAddDebouncedOperations(reactor, props) {
3526
3120
  if (!reactor) {
3527
3121
  throw new Error("Reactor is not loaded");
3528
3122
  }
3529
- const drive = documentDrivesRef.current.find((drive2) => drive2.id === driveId2);
3123
+ const drive = documentDrivesRef.current.find((drive2) => drive2.state.global.id === driveId2);
3530
3124
  if (!drive) {
3531
3125
  throw new Error(`Drive with id ${driveId2} not found`);
3532
3126
  }
@@ -3605,7 +3199,7 @@ function getNode(id, drive) {
3605
3199
  }
3606
3200
  function createDriveActions(document2, dispatch, context) {
3607
3201
  const drive = document2;
3608
- const driveId = drive.id;
3202
+ const { id: driveId } = drive.state.global;
3609
3203
  const { selectedNode } = context;
3610
3204
  const handleAddFolder = async (name, parentFolder, id = generateId()) => {
3611
3205
  dispatch(addFolder({
@@ -3895,17 +3489,6 @@ function useEditorProps(document2, node, documentDispatch, onAddOperation) {
3895
3489
  isAllowedToEditDocuments: (userPermissions == null ? void 0 : userPermissions.isAllowedToEditDocuments) ?? false
3896
3490
  };
3897
3491
  }
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
3492
  function useSyncStatus(driveId, documentId) {
3910
3493
  const { getSyncStatusSync, onSyncStatus, documentDrives } = useDocumentDriveServer();
3911
3494
  const syncStatus = useSyncExternalStore(
@@ -3915,7 +3498,9 @@ function useSyncStatus(driveId, documentId) {
3915
3498
  },
3916
3499
  () => {
3917
3500
  var _a;
3918
- const drive = documentDrives.find((_drive) => _drive.id === driveId);
3501
+ const drive = documentDrives.find(
3502
+ (_drive) => _drive.state.global.id === driveId
3503
+ );
3919
3504
  if (!drive) return;
3920
3505
  const isReadDrive = "readContext" in drive;
3921
3506
  const _sharingType = !isReadDrive ? (_a = drive.state.local.sharingType) == null ? void 0 : _a.toUpperCase() : "PUBLIC";
@@ -3974,338 +3559,6 @@ const useUndoRedoShortcuts = (props) => {
3974
3559
  [canRedo, redo2]
3975
3560
  );
3976
3561
  };
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
3562
  function EditorLoader(props) {
4310
3563
  const [showLoading, setShowLoading] = useState(false);
4311
3564
  useEffect(() => {
@@ -4333,11 +3586,9 @@ const DocumentEditor = (props) => {
4333
3586
  onChange,
4334
3587
  onExport,
4335
3588
  onAddOperation,
4336
- onGetDocumentRevision,
4337
3589
  onOpenSwitchboardLink
4338
3590
  } = props;
4339
3591
  const documentId = fileNodeDocument == null ? void 0 : fileNodeDocument.documentId;
4340
- const [selectedTimelineItem, setSelectedTimelineItem] = useState(null);
4341
3592
  const [revisionHistoryVisible, setRevisionHistoryVisible] = useState(false);
4342
3593
  const theme = useAtomValue(themeAtom);
4343
3594
  const user = useUser() || void 0;
@@ -4363,10 +3614,6 @@ const DocumentEditor = (props) => {
4363
3614
  [theme, user]
4364
3615
  );
4365
3616
  const userPermissions = useUserPermissions$1();
4366
- const timelineItems = useTimelineItems(
4367
- documentId,
4368
- initialDocument == null ? void 0 : initialDocument.created
4369
- );
4370
3617
  const currentDocument = useRef({ ...fileNodeDocument, document: document2 });
4371
3618
  useEffect(() => {
4372
3619
  var _a;
@@ -4543,8 +3790,7 @@ const DocumentEditor = (props) => {
4543
3790
  const {
4544
3791
  disableExternalControls,
4545
3792
  documentToolbarEnabled,
4546
- showSwitchboardLink,
4547
- timelineEnabled
3793
+ showSwitchboardLink
4548
3794
  } = editor.config || {};
4549
3795
  const handleSwitchboardLinkClick = showSwitchboardLink !== false ? onOpenSwitchboardLink : void 0;
4550
3796
  return /* @__PURE__ */ jsxs("div", { className: "relative h-full", id: "document-editor-context", children: [
@@ -4555,10 +3801,7 @@ const DocumentEditor = (props) => {
4555
3801
  onExport,
4556
3802
  onShowRevisionHistory: showRevisionHistory,
4557
3803
  title: fileNodeDocument.name || document2.name,
4558
- onSwitchboardLinkClick: handleSwitchboardLinkClick,
4559
- timelineButtonVisible: timelineEnabled,
4560
- timelineItems: timelineItems.data,
4561
- onTimelineItemClick: setSelectedTimelineItem
3804
+ onSwitchboardLinkClick: handleSwitchboardLinkClick
4562
3805
  }
4563
3806
  ),
4564
3807
  !disableExternalControls && /* @__PURE__ */ jsxs("div", { className: "mb-4 flex justify-end gap-10", children: [
@@ -4588,16 +3831,7 @@ const DocumentEditor = (props) => {
4588
3831
  EditorComponent,
4589
3832
  {
4590
3833
  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
- },
3834
+ context,
4601
3835
  document: document2,
4602
3836
  documentNodeName: fileNodeDocument.name,
4603
3837
  dispatch,
@@ -4635,7 +3869,6 @@ function DocumentEditorContainer() {
4635
3869
  renameNode,
4636
3870
  getDocumentModelModule
4637
3871
  } = useUiNodes();
4638
- const getDocument = useGetDocument();
4639
3872
  const handleAddOperationToSelectedDocument = useCallback(
4640
3873
  async (operation) => {
4641
3874
  if (!selectedDocument) {
@@ -4698,20 +3931,6 @@ function DocumentEditorContainer() {
4698
3931
  },
4699
3932
  [getDocumentModelModule, showModal, t]
4700
3933
  );
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
3934
  const onExport = useCallback(() => {
4716
3935
  if (selectedDocument) {
4717
3936
  return exportDocument(selectedDocument);
@@ -4733,7 +3952,6 @@ function DocumentEditorContainer() {
4733
3952
  onChange: onDocumentChangeHandler,
4734
3953
  onClose,
4735
3954
  onExport,
4736
- onGetDocumentRevision,
4737
3955
  onAddOperation: handleAddOperationToSelectedDocument,
4738
3956
  onOpenSwitchboardLink
4739
3957
  }
@@ -4742,6 +3960,165 @@ function DocumentEditorContainer() {
4742
3960
  fileNodeDocument.documentId
4743
3961
  );
4744
3962
  }
3963
+ function getDocumentSpec(doc) {
3964
+ if ("documentModelState" in doc) {
3965
+ return doc.documentModelState;
3966
+ }
3967
+ return doc.documentModel;
3968
+ }
3969
+ const CreateDocument = ({ documentModels, createDocument }) => {
3970
+ return jsxs("div", { className: "px-6", children: [jsx("h3", { className: "mb-3 mt-4 text-xl font-bold text-gray-600", children: "New document" }), jsx("div", { className: "flex w-full flex-wrap gap-4", children: documentModels == null ? void 0 : documentModels.map((doc) => {
3971
+ const spec = getDocumentSpec(doc);
3972
+ return jsx(Button, { color: "light", "aria-details": spec.description, onClick: () => createDocument(doc), children: jsx("span", { className: "text-sm", children: spec.name }) }, spec.id);
3973
+ }) })] });
3974
+ };
3975
+ function sortUiNodesByName(a, b) {
3976
+ return a.name.localeCompare(b.name);
3977
+ }
3978
+ const GAP = 8;
3979
+ const ITEM_WIDTH = 256;
3980
+ const ITEM_HEIGHT = 48;
3981
+ const USED_SPACE = 420;
3982
+ function FileContentView(props) {
3983
+ const parentRef = useRef(null);
3984
+ const { t } = useTranslation();
3985
+ const windowSize = useWindowSize();
3986
+ const { fileNodes, ...fileProps } = props;
3987
+ const availableWidth = windowSize.innerWidth - USED_SPACE;
3988
+ const columnCount = Math.floor(availableWidth / (ITEM_WIDTH + GAP)) || 1;
3989
+ const rowCount = Math.ceil(fileNodes.length / columnCount);
3990
+ const rowVirtualizer = useVirtualizer({
3991
+ count: rowCount,
3992
+ getScrollElement: () => parentRef.current,
3993
+ estimateSize: (index) => {
3994
+ if (index > 0) {
3995
+ return ITEM_HEIGHT + GAP;
3996
+ }
3997
+ return ITEM_HEIGHT;
3998
+ },
3999
+ overscan: 5
4000
+ });
4001
+ const columnVirtualizer = useVirtualizer({
4002
+ horizontal: true,
4003
+ count: columnCount,
4004
+ getScrollElement: () => parentRef.current,
4005
+ estimateSize: (index) => {
4006
+ if (index > 0) {
4007
+ return ITEM_WIDTH + GAP;
4008
+ }
4009
+ return ITEM_WIDTH;
4010
+ },
4011
+ overscan: 5
4012
+ });
4013
+ const getItemIndex = (rowIndex, columnIndex) => rowIndex * columnCount + columnIndex;
4014
+ const getItem = (rowIndex, columnIndex) => {
4015
+ const index = getItemIndex(rowIndex, columnIndex);
4016
+ return fileNodes[index] || null;
4017
+ };
4018
+ if (fileNodes.length === 0) {
4019
+ return jsx("div", { className: "mb-8 text-sm text-gray-400", children: t("folderView.sections.documents.empty", {
4020
+ defaultValue: "No documents or files 📄"
4021
+ }) });
4022
+ }
4023
+ const renderItem = (rowIndex, columnIndex) => {
4024
+ const fileNode = getItem(rowIndex, columnIndex);
4025
+ if (!fileNode) {
4026
+ return null;
4027
+ }
4028
+ return jsx("div", { style: {
4029
+ marginLeft: columnIndex === 0 ? 0 : GAP
4030
+ }, children: jsx(FileItem, { uiNode: fileNode, ...fileProps }, fileNode.id) });
4031
+ };
4032
+ return jsx("div", { ref: parentRef, style: {
4033
+ height: `400px`,
4034
+ width: `100%`,
4035
+ overflow: "auto"
4036
+ }, children: jsx("div", { style: {
4037
+ height: `${rowVirtualizer.getTotalSize()}px`,
4038
+ width: `${columnVirtualizer.getTotalSize()}px`,
4039
+ position: "relative"
4040
+ }, children: rowVirtualizer.getVirtualItems().map((virtualRow) => jsx(React__default.Fragment, { children: columnVirtualizer.getVirtualItems().map((virtualColumn) => jsx("div", { style: {
4041
+ position: "absolute",
4042
+ top: 0,
4043
+ left: 0,
4044
+ marginTop: virtualRow.index === 0 ? 0 : GAP,
4045
+ width: `${virtualColumn.size}px`,
4046
+ height: `${virtualRow.size}px`,
4047
+ transform: `translateX(${virtualColumn.start}px) translateY(${virtualRow.start}px)`
4048
+ }, children: renderItem(virtualRow.index, virtualColumn.index) }, virtualColumn.key)) }, virtualRow.key)) }) });
4049
+ }
4050
+ function FolderView(props) {
4051
+ const { node, className, isDropTarget, containerProps, ...nodeProps } = props;
4052
+ const { t } = useTranslation();
4053
+ const folderNodes = node.children.filter((node2) => node2.kind === FOLDER).sort(sortUiNodesByName);
4054
+ const fileNodes = node.children.filter((node2) => node2.kind === FILE).sort(sortUiNodesByName);
4055
+ const folderCallbacks = {
4056
+ onSelectNode: (node2) => nodeProps.onSelectNode(node2),
4057
+ onRenameNode: (name, node2) => nodeProps.onRenameNode(name, node2),
4058
+ onDuplicateNode: (node2) => nodeProps.onDuplicateNode(node2),
4059
+ onDeleteNode: (node2) => nodeProps.onDeleteNode(node2)
4060
+ };
4061
+ const fileCallbacks = {
4062
+ onSelectNode: (node2) => nodeProps.onSelectNode(node2),
4063
+ onRenameNode: (name, node2) => nodeProps.onRenameNode(name, node2),
4064
+ onDuplicateNode: (node2) => nodeProps.onDuplicateNode(node2),
4065
+ onDeleteNode: (node2) => nodeProps.onDeleteNode(node2)
4066
+ };
4067
+ const baseNodeCallbacks = {
4068
+ onAddFile: async (file, parentNode) => {
4069
+ await nodeProps.onAddFile(file, parentNode);
4070
+ },
4071
+ onCopyNode: async (uiNode, targetNode) => {
4072
+ await nodeProps.onCopyNode(uiNode, targetNode);
4073
+ },
4074
+ onMoveNode: async (uiNode, targetNode) => {
4075
+ await nodeProps.onMoveNode(uiNode, targetNode);
4076
+ }
4077
+ };
4078
+ return jsxs("div", { className: twMerge("rounded-md border-2 border-transparent p-2", isDropTarget && "border-dashed border-blue-100", className), ...containerProps, children: [jsx(DriveLayout.ContentSection, { title: t("folderView.sections.folders.title", {
4079
+ defaultValue: "Folders"
4080
+ }), className: "mb-4", children: folderNodes.length > 0 ? folderNodes.map((folderNode) => jsx(FolderItem, { uiNode: folderNode, ...baseNodeCallbacks, ...folderCallbacks, isAllowedToCreateDocuments: nodeProps.isAllowedToCreateDocuments }, folderNode.id)) : jsx("div", { className: "mb-8 text-sm text-gray-400", children: t("folderView.sections.folders.empty", {
4081
+ defaultValue: "No documents or files 📄"
4082
+ }) }) }), jsx(DriveLayout.ContentSection, { title: t("folderView.sections.documents.title", {
4083
+ defaultValue: "Documents and files"
4084
+ }), children: jsx("div", { className: twMerge("w-full", fileNodes.length > 0 ? "min-h-[400px]" : "min-h-14"), children: jsx(FileContentView, { fileNodes, ...fileCallbacks, isAllowedToCreateDocuments: nodeProps.isAllowedToCreateDocuments }) }) })] });
4085
+ }
4086
+ function BaseEditor(props) {
4087
+ const { document: document2, dispatch, className, children } = props;
4088
+ const { state: { global: { id: driveId } } } = document2;
4089
+ const { showSearchBar, isAllowedToCreateDocuments, documentModels, showCreateDocumentModal } = useDriveContext();
4090
+ const { driveNodes, selectedNode, selectedNodePath, getNodeById, setSelectedNode } = useUiNodesContext();
4091
+ const driveNode = useMemo(() => driveNodes.find((n) => n.id === driveId), [driveNodes, driveId]);
4092
+ const { addDocument, addFile, addFolder: addFolder2, renameNode, deleteNode: deleteNode2, moveNode: moveNode2, copyNode: copyNode2, duplicateNode } = useDriveActionsWithUiNodes(document2, dispatch);
4093
+ const onCreateDocument = useCallback(async (documentModel) => {
4094
+ const { name } = await showCreateDocumentModal(documentModel);
4095
+ const document3 = documentModel.utils.createDocument();
4096
+ await addDocument(name, documentModel.documentModel.name, document3, selectedNode == null ? void 0 : selectedNode.id);
4097
+ }, [addDocument, showCreateDocumentModal, selectedNode == null ? void 0 : selectedNode.id]);
4098
+ const { isDropTarget, dropProps } = useDrop({
4099
+ uiNode: selectedNode,
4100
+ onAddFile: addFile,
4101
+ onCopyNode: copyNode2,
4102
+ onMoveNode: moveNode2
4103
+ });
4104
+ const { breadcrumbs, onBreadcrumbSelected } = useBreadcrumbs({
4105
+ selectedNodePath,
4106
+ getNodeById,
4107
+ setSelectedNode
4108
+ });
4109
+ if (!driveNode) {
4110
+ return jsx("div", { children: "Drive not found" });
4111
+ } else if ((selectedNode == null ? void 0 : selectedNode.kind) === FILE$1) {
4112
+ return jsx(Fragment$1, {});
4113
+ }
4114
+ return jsxs(DriveLayout, { className, children: [children, jsxs(DriveLayout.Header, { children: [jsx(Breadcrumbs, { breadcrumbs, createEnabled: isAllowedToCreateDocuments, onCreate: addFolder2, onBreadcrumbSelected }), showSearchBar && jsx(SearchBar, {})] }), jsx(DriveLayout.Content, { children: jsx(FolderView, { node: selectedNode || driveNode, onSelectNode: setSelectedNode, onRenameNode: renameNode, onDuplicateNode: duplicateNode, onDeleteNode: deleteNode2, onAddFile: addFile, onCopyNode: copyNode2, onMoveNode: moveNode2, isDropTarget, isAllowedToCreateDocuments }) }), jsx(DriveLayout.Footer, { children: isAllowedToCreateDocuments && jsx(CreateDocument, { documentModels, createDocument: onCreateDocument }) })] });
4115
+ }
4116
+ function Editor(props) {
4117
+ return jsx(DriveContextProvider, { value: props.context, children: jsx(BaseEditor, { ...props }) });
4118
+ }
4119
+ const GenericDriveExplorer = {
4120
+ Component: Editor
4121
+ };
4745
4122
  function useDocumentsState(args) {
4746
4123
  const { reactor, driveId, documentIds, options } = args;
4747
4124
  const [statesByDocumentId, setStatesByDocumentId] = useState({});
@@ -4928,19 +4305,8 @@ function DriveEditorContainer() {
4928
4305
  const { addFile, addDocument } = useDocumentDriveServer();
4929
4306
  const documentModels = useFilteredDocumentModels();
4930
4307
  const useDriveDocumentState = makeDriveDocumentStateHook(reactor);
4931
- const getDocument = useGetDocument();
4932
4308
  const getDocumentModelModule = useGetDocumentModelModule();
4933
4309
  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
4310
  const driveContext = useMemo(
4945
4311
  () => ({
4946
4312
  showSearchBar: false,
@@ -4984,8 +4350,6 @@ function DriveEditorContainer() {
4984
4350
  context: {
4985
4351
  ...editorProps.context,
4986
4352
  ...driveContext,
4987
- analyticsDatabaseName: connectConfig.analyticsDatabaseName,
4988
- getDocumentRevision: onGetDocumentRevision,
4989
4353
  getDocumentModelModule,
4990
4354
  getEditor
4991
4355
  },
@@ -5021,7 +4385,7 @@ function Content() {
5021
4385
  }, [selectedDriveNode, selectedNode, addFile]);
5022
4386
  useEffect(() => {
5023
4387
  if ((status === "LOADED" || status === "ERROR") && !documentDrives.find(
5024
- (d) => d.id === driveId || d.slug === driveId || d.state.global.name === driveId
4388
+ (d) => d.state.global.id === driveId || d.state.global.slug === driveId || d.state.global.name === driveId
5025
4389
  )) {
5026
4390
  toast(/* @__PURE__ */ jsxs("p", { children: [
5027
4391
  "Drive ",
@@ -5036,4 +4400,3 @@ function Content() {
5036
4400
  export {
5037
4401
  Content as default
5038
4402
  };
5039
- //# sourceMappingURL=content-2lJzkjLx.js.map