@powerhousedao/connect 6.1.0-staging.0 → 6.2.0-dev.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env +11 -49
- package/README.md +4 -0
- package/dist/{AddDriveModal-ZK9-BWMB.js → AddDriveModal-kzL41qdg.js} +23 -9
- package/dist/AddDriveModal-kzL41qdg.js.map +1 -0
- package/dist/{ClearStorageModal-BLr3sRfl.js → ClearStorageModal-DIKwqiia.js} +8 -9
- package/dist/ClearStorageModal-DIKwqiia.js.map +1 -0
- package/dist/{CookiesPolicyModal-DiXQV82b.js → CookiesPolicyModal-1nOh6oN3.js} +6 -6
- package/dist/{CookiesPolicyModal-DiXQV82b.js.map → CookiesPolicyModal-1nOh6oN3.js.map} +1 -1
- package/dist/{CreateDocumentModal-BhJh4nWt.js → CreateDocumentModal-nQbLVDq3.js} +7 -5
- package/dist/{CreateDocumentModal-BhJh4nWt.js.map → CreateDocumentModal-nQbLVDq3.js.map} +1 -1
- package/dist/{DebugSettingsModal-DHORxOiI.js → DebugSettingsModal-DoY0auxt.js} +12 -12
- package/dist/DebugSettingsModal-DoY0auxt.js.map +1 -0
- package/dist/{DeleteDriveModal-CbuIdjKY.js → DeleteDriveModal-6P0T1QgD.js} +9 -7
- package/dist/{DeleteDriveModal-CbuIdjKY.js.map → DeleteDriveModal-6P0T1QgD.js.map} +1 -1
- package/dist/{DeleteItemModal-9ErYlauT.js → DeleteItemModal-BmV1aQyZ.js} +10 -8
- package/dist/{DeleteItemModal-9ErYlauT.js.map → DeleteItemModal-BmV1aQyZ.js.map} +1 -1
- package/dist/{DisclaimerModal-CfDeiBz8.js → DisclaimerModal-CVTFfN0_.js} +6 -6
- package/dist/{DisclaimerModal-CfDeiBz8.js.map → DisclaimerModal-CVTFfN0_.js.map} +1 -1
- package/dist/{DownloadDocumentWithErrorsModal-KZGWQ4J7.js → DownloadDocumentWithErrorsModal-CXeFUtaz.js} +15 -14
- package/dist/DownloadDocumentWithErrorsModal-CXeFUtaz.js.map +1 -0
- package/dist/{DriveSettingsModal-DEk05PS7.js → DriveSettingsModal-L5sM-rIh.js} +14 -8
- package/dist/{DriveSettingsModal-DEk05PS7.js.map → DriveSettingsModal-L5sM-rIh.js.map} +1 -1
- package/dist/{InspectorModal-DrBnrYZl.js → InspectorModal-C7pIf6OO.js} +19 -18
- package/dist/InspectorModal-C7pIf6OO.js.map +1 -0
- package/dist/{MissingPackageModal-CUdcDjSO.js → MissingPackageModal-D_N96M6a.js} +5 -5
- package/dist/{MissingPackageModal-CUdcDjSO.js.map → MissingPackageModal-D_N96M6a.js.map} +1 -1
- package/dist/{SettingsModal-CwIcZXAy.js → SettingsModal-B4BiV0hg.js} +31 -32
- package/dist/SettingsModal-B4BiV0hg.js.map +1 -0
- package/dist/{UpgradeDriveModal-BwI5E5k3.js → UpgradeDriveModal-CyAUDCU7.js} +6 -6
- package/dist/{UpgradeDriveModal-BwI5E5k3.js.map → UpgradeDriveModal-CyAUDCU7.js.map} +1 -1
- package/dist/{sidebar-BLHOoVIg.js → app-loader-DCYDK6hq.js} +1016 -591
- package/dist/app-loader-DCYDK6hq.js.map +1 -0
- package/dist/app-loader-UqO12emj.js +4 -0
- package/dist/{build-info-Megqmixp.js → build-info-sckG5_D4.js} +4 -4
- package/dist/{build-info-Megqmixp.js.map → build-info-sckG5_D4.js.map} +1 -1
- package/dist/components-B9mRhivD.js +5 -0
- package/dist/connect.config-aPx3rHZQ.js +161 -0
- package/dist/connect.config-aPx3rHZQ.js.map +1 -0
- package/dist/{load-DOIDDXvY.js → load-Cs4KcEw0.js} +16 -27
- package/dist/load-Cs4KcEw0.js.map +1 -0
- package/dist/main.js +5 -3
- package/dist/main.js.map +1 -1
- package/dist/{package-B4r0SFiy.js → package-BFW159r-.js} +19 -11
- package/dist/package-BFW159r-.js.map +1 -0
- package/dist/{pglite-runtime-Btp8ZXVH.js → pglite-runtime-toc1-TWa.js} +12 -6
- package/dist/pglite-runtime-toc1-TWa.js.map +1 -0
- package/dist/{pglite-seed-b1mJUaip.js → pglite-seed-D8oSKkep.js} +7 -7
- package/dist/pglite-seed-D8oSKkep.js.map +1 -0
- package/dist/pglite.worker.js +8 -7
- package/dist/pglite.worker.js.map +1 -1
- package/dist/pglite.worker.legacy.js +7 -6
- package/dist/pglite.worker.legacy.js.map +1 -1
- package/dist/{reactor-CppbYt7w.js → reactor-BlxTyHZ5.js} +113 -57
- package/dist/reactor-BlxTyHZ5.js.map +1 -0
- package/dist/{registerServiceWorker-CMRF2LWE.js → registerServiceWorker-B7uKpkci.js} +13 -11
- package/dist/{registerServiceWorker-CMRF2LWE.js.map → registerServiceWorker-B7uKpkci.js.map} +1 -1
- package/dist/{i18n-4rfcgnb9.js → reload-connect-toast-CwvSc6F-.js} +20 -6
- package/dist/reload-connect-toast-CwvSc6F-.js.map +1 -0
- package/dist/runtime-config-DL3QjcfM.js +24 -0
- package/dist/runtime-config-DL3QjcfM.js.map +1 -0
- package/dist/start-connect.d.ts.map +1 -1
- package/dist/start-connect.js +5 -3
- package/dist/start-connect.js.map +1 -1
- package/dist/style.css +4904 -12773
- package/dist/{toast-DnODOv28.js → toast-BEy42aYx.js} +3 -3
- package/dist/{toast-DnODOv28.js.map → toast-BEy42aYx.js.map} +1 -1
- package/dist/{useRegistryPackages-PUiMxd73.js → useRegistryPackages-Bh0luCvV.js} +6 -6
- package/dist/useRegistryPackages-Bh0luCvV.js.map +1 -0
- package/package.json +22 -14
- package/public/powerhouse.config.json +33 -0
- package/style.css +28 -0
- package/dist/AddDriveModal-ZK9-BWMB.js.map +0 -1
- package/dist/ClearStorageModal-BLr3sRfl.js.map +0 -1
- package/dist/DebugSettingsModal-DHORxOiI.js.map +0 -1
- package/dist/DownloadDocumentWithErrorsModal-KZGWQ4J7.js.map +0 -1
- package/dist/InspectorModal-DrBnrYZl.js.map +0 -1
- package/dist/SettingsModal-CwIcZXAy.js.map +0 -1
- package/dist/connect.config-Cuh0hj_Q.js +0 -142
- package/dist/connect.config-Cuh0hj_Q.js.map +0 -1
- package/dist/i18n-4rfcgnb9.js.map +0 -1
- package/dist/load-DOIDDXvY.js.map +0 -1
- package/dist/package-B4r0SFiy.js.map +0 -1
- package/dist/packages.config-CiH8KJVN.js +0 -32
- package/dist/packages.config-CiH8KJVN.js.map +0 -1
- package/dist/pglite-runtime-Btp8ZXVH.js.map +0 -1
- package/dist/pglite-seed-b1mJUaip.js.map +0 -1
- package/dist/reactor-CppbYt7w.js.map +0 -1
- package/dist/sidebar-BLHOoVIg.js.map +0 -1
- package/dist/useRegistryPackages-PUiMxd73.js.map +0 -1
- package/public/ph-packages.json +0 -4
|
@@ -1,410 +1,26 @@
|
|
|
1
1
|
|
|
2
|
-
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="
|
|
3
|
-
import { n as
|
|
4
|
-
import { n as
|
|
5
|
-
import {
|
|
6
|
-
import { c as subscribeReactorPgMajor, d as createFileDataStore, f as idbError, l as IDB_STORE_NAME, m as readPgVersionFile, p as openIdb, r as getCachedReactorPgMajor, u as PRIMARY_IDB_NAMES } from "./pglite-runtime-
|
|
7
|
-
import { t as serviceWorkerManager } from "./registerServiceWorker-
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import
|
|
11
|
-
import { Trans, useTranslation } from "react-i18next";
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
18
|
-
import {
|
|
19
|
-
import {
|
|
20
|
-
import {
|
|
21
|
-
import {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
const listeners$3 = /* @__PURE__ */ new Set();
|
|
25
|
-
let cookies = getInitial$1();
|
|
26
|
-
function getInitial$1() {
|
|
27
|
-
try {
|
|
28
|
-
const value = localStorage.getItem(ACCEPTED_COOKIES_KEY_STORAGE);
|
|
29
|
-
return value ? JSON.parse(value) : {
|
|
30
|
-
analytics: false,
|
|
31
|
-
marketing: false,
|
|
32
|
-
functional: false
|
|
33
|
-
};
|
|
34
|
-
} catch {
|
|
35
|
-
return {
|
|
36
|
-
analytics: false,
|
|
37
|
-
marketing: false,
|
|
38
|
-
functional: false
|
|
39
|
-
};
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
function getCookies() {
|
|
43
|
-
return cookies;
|
|
44
|
-
}
|
|
45
|
-
function setCookies(setter) {
|
|
46
|
-
cookies = setter(cookies);
|
|
47
|
-
localStorage.setItem(ACCEPTED_COOKIES_KEY_STORAGE, JSON.stringify(cookies));
|
|
48
|
-
listeners$3.forEach((fn) => fn());
|
|
49
|
-
}
|
|
50
|
-
function subscribe$1(fn) {
|
|
51
|
-
listeners$3.add(fn);
|
|
52
|
-
return () => listeners$3.delete(fn);
|
|
53
|
-
}
|
|
54
|
-
const useAcceptedCookies = () => {
|
|
55
|
-
return [useSyncExternalStore(subscribe$1, getCookies, getCookies), setCookies];
|
|
56
|
-
};
|
|
57
|
-
const COOKIE_BANNER_KEY_STORAGE = `${connectConfig.routerBasename}:display-cookie-banner`;
|
|
58
|
-
const listeners$2 = /* @__PURE__ */ new Set();
|
|
59
|
-
let bannerShown = getInitial();
|
|
60
|
-
function getInitial() {
|
|
61
|
-
try {
|
|
62
|
-
return localStorage.getItem(COOKIE_BANNER_KEY_STORAGE) !== "false";
|
|
63
|
-
} catch (error) {
|
|
64
|
-
console.error(error);
|
|
65
|
-
return true;
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
function getCookieBannerState() {
|
|
69
|
-
return bannerShown;
|
|
70
|
-
}
|
|
71
|
-
function setCookieBannerState(state) {
|
|
72
|
-
bannerShown = state;
|
|
73
|
-
localStorage.setItem(COOKIE_BANNER_KEY_STORAGE, JSON.stringify(state));
|
|
74
|
-
}
|
|
75
|
-
function subscribe(fn) {
|
|
76
|
-
listeners$2.add(fn);
|
|
77
|
-
return () => listeners$2.delete(fn);
|
|
78
|
-
}
|
|
79
|
-
const useCookieBanner = () => {
|
|
80
|
-
return [useSyncExternalStore(subscribe, getCookieBannerState, getCookieBannerState), setCookieBannerState];
|
|
81
|
-
};
|
|
82
|
-
//#endregion
|
|
83
|
-
//#region src/hooks/useFailedInstallations.ts
|
|
84
|
-
const emptyArray$1 = [];
|
|
85
|
-
function useFailedInstallations() {
|
|
86
|
-
const discoveryService = usePackageDiscoveryService();
|
|
87
|
-
return useSyncExternalStore((cb) => discoveryService?.subscribeFailed(cb) ?? (() => {}), () => discoveryService?.getFailedInstallations() ?? emptyArray$1);
|
|
88
|
-
}
|
|
89
|
-
//#endregion
|
|
90
|
-
//#region src/hooks/useInitSentry.ts
|
|
91
|
-
const logger$2 = childLogger(["sentry"]);
|
|
92
|
-
let clientStarted = false;
|
|
93
|
-
async function getSentry() {
|
|
94
|
-
return await import("@sentry/react");
|
|
95
|
-
}
|
|
96
|
-
async function initSentry() {
|
|
97
|
-
connectConfig.sentry;
|
|
98
|
-
const Sentry = await getSentry();
|
|
99
|
-
const integrations = [
|
|
100
|
-
Sentry.httpClientIntegration(),
|
|
101
|
-
Sentry.extraErrorDataIntegration({ depth: 5 }),
|
|
102
|
-
Sentry.replayIntegration(),
|
|
103
|
-
Sentry.captureConsoleIntegration({ levels: ["error"] })
|
|
104
|
-
];
|
|
105
|
-
if (connectConfig.sentry.tracing) integrations.push(Sentry.reactRouterV6BrowserTracingIntegration({
|
|
106
|
-
useEffect: React.useEffect,
|
|
107
|
-
useLocation,
|
|
108
|
-
useNavigationType,
|
|
109
|
-
createRoutesFromChildren,
|
|
110
|
-
matchRoutes
|
|
111
|
-
}));
|
|
112
|
-
Sentry.init({
|
|
113
|
-
release: connectConfig.sentry.release,
|
|
114
|
-
dsn: connectConfig.sentry.dsn,
|
|
115
|
-
environment: connectConfig.sentry.env,
|
|
116
|
-
integrations,
|
|
117
|
-
ignoreErrors: [
|
|
118
|
-
"User is not allowed to create files",
|
|
119
|
-
"User is not allowed to move documents",
|
|
120
|
-
"The user aborted a request."
|
|
121
|
-
],
|
|
122
|
-
sendDefaultPii: true,
|
|
123
|
-
tracesSampleRate: 1,
|
|
124
|
-
replaysSessionSampleRate: .1,
|
|
125
|
-
replaysOnErrorSampleRate: 1,
|
|
126
|
-
beforeSend(event, hint) {
|
|
127
|
-
const error = hint.originalException;
|
|
128
|
-
if (error instanceof TypeError && error.message.includes("Failed to fetch") && !navigator.onLine) return null;
|
|
129
|
-
return event;
|
|
130
|
-
}
|
|
131
|
-
});
|
|
132
|
-
clientStarted = true;
|
|
133
|
-
}
|
|
134
|
-
async function closeClient() {
|
|
135
|
-
if (!clientStarted) return;
|
|
136
|
-
return (await getSentry()).getClient()?.close();
|
|
137
|
-
}
|
|
138
|
-
function useInitSentry() {
|
|
139
|
-
const [acceptedCookies] = useAcceptedCookies();
|
|
140
|
-
const { analytics } = acceptedCookies;
|
|
141
|
-
useEffect(() => {
|
|
142
|
-
if (!analytics) {
|
|
143
|
-
closeClient().catch((error) => logger$2.error("@error", error));
|
|
144
|
-
return;
|
|
145
|
-
}
|
|
146
|
-
if (clientStarted || !connectConfig.sentry.dsn || connectConfig.sentry.dsn === "") return;
|
|
147
|
-
initSentry().catch((error) => logger$2.error("@error", error));
|
|
148
|
-
}, [analytics]);
|
|
149
|
-
}
|
|
150
|
-
//#endregion
|
|
151
|
-
//#region src/hooks/usePendingInstallations.ts
|
|
152
|
-
const emptyArray = [];
|
|
153
|
-
function usePendingInstallations() {
|
|
154
|
-
const discoveryService = usePackageDiscoveryService();
|
|
155
|
-
const cacheRef = useRef(emptyArray);
|
|
156
|
-
return useSyncExternalStore((cb) => discoveryService?.subscribePending(cb) ?? (() => {}), useCallback(() => {
|
|
157
|
-
if (!discoveryService) return emptyArray;
|
|
158
|
-
const next = discoveryService.getPendingInstallations() ?? emptyArray;
|
|
159
|
-
const prev = cacheRef.current;
|
|
160
|
-
if (next === prev || next.length === prev.length && next.every((p, i) => p === prev[i])) return prev;
|
|
161
|
-
cacheRef.current = next;
|
|
162
|
-
return next;
|
|
163
|
-
}, [discoveryService]));
|
|
164
|
-
}
|
|
165
|
-
//#endregion
|
|
166
|
-
//#region src/hooks/useUndoRedoShortcuts.ts
|
|
167
|
-
const useUndoRedoShortcuts = (props) => {
|
|
168
|
-
const { undo, redo, canRedo, canUndo } = props;
|
|
169
|
-
const isMac = window.navigator.userAgent.includes("Mac");
|
|
170
|
-
let undoShortcut = "ctrl+z";
|
|
171
|
-
let redoShortcut = "ctrl+y";
|
|
172
|
-
if (isMac) {
|
|
173
|
-
undoShortcut = "mod+z";
|
|
174
|
-
redoShortcut = "mod+shift+z";
|
|
175
|
-
}
|
|
176
|
-
useHotkeys(undoShortcut, (event) => {
|
|
177
|
-
event.preventDefault();
|
|
178
|
-
if (canUndo) undo();
|
|
179
|
-
}, {}, [canUndo, undo]);
|
|
180
|
-
useHotkeys(redoShortcut, (event) => {
|
|
181
|
-
event.preventDefault();
|
|
182
|
-
if (canRedo) redo();
|
|
183
|
-
}, {}, [canRedo, redo]);
|
|
184
|
-
};
|
|
185
|
-
//#endregion
|
|
186
|
-
//#region src/components/analytics.tsx
|
|
187
|
-
function gtag(...args) {
|
|
188
|
-
window.dataLayer?.push(...args);
|
|
189
|
-
}
|
|
190
|
-
const Analytics = () => {
|
|
191
|
-
const gaTrackingId = connectConfig.gaTrackingId;
|
|
192
|
-
const [{ analytics }] = useAcceptedCookies();
|
|
193
|
-
const useAnalytics = gaTrackingId && analytics;
|
|
194
|
-
useEffect(() => {
|
|
195
|
-
if (useAnalytics) {
|
|
196
|
-
const script = document.createElement("script");
|
|
197
|
-
script.src = `https://www.googletagmanager.com/gtag/js?id=${gaTrackingId}`;
|
|
198
|
-
script.async = true;
|
|
199
|
-
document.head.appendChild(script);
|
|
200
|
-
window.dataLayer = window.dataLayer || [];
|
|
201
|
-
gtag("js", /* @__PURE__ */ new Date());
|
|
202
|
-
gtag("config", gaTrackingId);
|
|
203
|
-
return () => {
|
|
204
|
-
document.head.removeChild(script);
|
|
205
|
-
};
|
|
206
|
-
}
|
|
207
|
-
}, [useAnalytics, gaTrackingId]);
|
|
208
|
-
return null;
|
|
209
|
-
};
|
|
210
|
-
//#endregion
|
|
211
|
-
//#region src/components/document-editor-container.tsx
|
|
212
|
-
function DocumentEditorContainer() {
|
|
213
|
-
const [selectedDocument] = useSelectedDocument();
|
|
214
|
-
const parentFolder = useNodeParentFolderById(selectedDocument.header.id);
|
|
215
|
-
useMemo(() => {
|
|
216
|
-
return async () => {};
|
|
217
|
-
}, []);
|
|
218
|
-
useCallback(() => {
|
|
219
|
-
setSelectedNode(parentFolder);
|
|
220
|
-
}, [parentFolder, setSelectedNode]);
|
|
221
|
-
return /* @__PURE__ */ jsx("div", {
|
|
222
|
-
id: "document-editor-container",
|
|
223
|
-
className: "flex-1",
|
|
224
|
-
"data-document-type": selectedDocument.header.documentType,
|
|
225
|
-
children: /* @__PURE__ */ jsx(DocumentEditor, { document: selectedDocument })
|
|
226
|
-
});
|
|
227
|
-
}
|
|
228
|
-
//#endregion
|
|
229
|
-
//#region src/components/editor-loader.tsx
|
|
230
|
-
function EditorLoader(props) {
|
|
231
|
-
const [showLoading, setShowLoading] = useState(false);
|
|
232
|
-
useEffect(() => {
|
|
233
|
-
setTimeout(() => {
|
|
234
|
-
setShowLoading(true);
|
|
235
|
-
}, props.loadingTimeout ?? 200);
|
|
236
|
-
}, [props]);
|
|
237
|
-
if (!showLoading) return null;
|
|
238
|
-
const { customEditorLoader, ...defaultProps } = props;
|
|
239
|
-
if (customEditorLoader) return /* @__PURE__ */ jsx(Fragment, { children: customEditorLoader });
|
|
240
|
-
return /* @__PURE__ */ jsx(DefaultEditorLoader, { ...defaultProps });
|
|
241
|
-
}
|
|
242
|
-
//#endregion
|
|
243
|
-
//#region src/components/error-boundary.tsx
|
|
244
|
-
const logger$1 = childLogger(["Connect"]);
|
|
245
|
-
function hasCustomFallback(props) {
|
|
246
|
-
return "fallbackRender" in props;
|
|
247
|
-
}
|
|
248
|
-
function SilentFallback() {
|
|
249
|
-
return null;
|
|
250
|
-
}
|
|
251
|
-
/**
|
|
252
|
-
* Simple text-based fallback component.
|
|
253
|
-
* Displays a centered message when an error occurs.
|
|
254
|
-
*/
|
|
255
|
-
function TextFallback({ message = "Something went wrong" }) {
|
|
256
|
-
return /* @__PURE__ */ jsx("div", {
|
|
257
|
-
className: "text-center",
|
|
258
|
-
children: message
|
|
259
|
-
});
|
|
260
|
-
}
|
|
261
|
-
/**
|
|
262
|
-
* Detailed fallback component showing full error information.
|
|
263
|
-
* Displays error message with a collapsible details section.
|
|
264
|
-
* Useful for development and debugging purposes.
|
|
265
|
-
*/
|
|
266
|
-
function DetailedFallback({ error, resetErrorBoundary }) {
|
|
267
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
268
|
-
const errorDetails = error instanceof Error ? error.stack ?? String(error.cause) : JSON.stringify(error, null, 2);
|
|
269
|
-
return /* @__PURE__ */ jsx("div", {
|
|
270
|
-
className: "z-10 mx-auto flex max-w-[80%] flex-1 items-center justify-center p-6",
|
|
271
|
-
children: /* @__PURE__ */ jsxs("div", {
|
|
272
|
-
className: "w-full max-w-lg rounded-lg border border-gray-500 bg-white p-6 shadow-sm",
|
|
273
|
-
children: [
|
|
274
|
-
/* @__PURE__ */ jsxs("div", {
|
|
275
|
-
className: "mb-3 flex items-center gap-2",
|
|
276
|
-
children: [/* @__PURE__ */ jsx(Icon, {
|
|
277
|
-
name: "Error",
|
|
278
|
-
className: "size-5 shrink-0"
|
|
279
|
-
}), /* @__PURE__ */ jsx("h1", {
|
|
280
|
-
className: "text-lg font-semibold",
|
|
281
|
-
children: "Something went wrong"
|
|
282
|
-
})]
|
|
283
|
-
}),
|
|
284
|
-
/* @__PURE__ */ jsx("p", {
|
|
285
|
-
className: "mb-4 text-sm text-gray-700",
|
|
286
|
-
children: errorMessage
|
|
287
|
-
}),
|
|
288
|
-
errorDetails !== "{}" && /* @__PURE__ */ jsxs("details", {
|
|
289
|
-
className: "group",
|
|
290
|
-
children: [/* @__PURE__ */ jsx("summary", {
|
|
291
|
-
className: "cursor-pointer text-sm font-medium text-gray-700 underline select-none hover:text-gray-700",
|
|
292
|
-
children: "Show details"
|
|
293
|
-
}), /* @__PURE__ */ jsx("pre", {
|
|
294
|
-
className: "mt-2 max-h-48 overflow-auto rounded-sm bg-gray-100 p-3 text-xs",
|
|
295
|
-
children: errorDetails
|
|
296
|
-
})]
|
|
297
|
-
}),
|
|
298
|
-
/* @__PURE__ */ jsx(PowerhouseButton, {
|
|
299
|
-
type: "button",
|
|
300
|
-
onClick: resetErrorBoundary,
|
|
301
|
-
className: "mt-4 px-3 py-1.5 text-base font-medium",
|
|
302
|
-
children: "Try again"
|
|
303
|
-
})
|
|
304
|
-
]
|
|
305
|
-
})
|
|
306
|
-
});
|
|
307
|
-
}
|
|
308
|
-
/**
|
|
309
|
-
* Centered error message fallback component.
|
|
310
|
-
* Displays the error message in a centered, full-size container.
|
|
311
|
-
* Suitable for use as a custom fallbackRender when you need simple error display.
|
|
312
|
-
*/
|
|
313
|
-
function CenteredErrorMessage({ error }) {
|
|
314
|
-
return /* @__PURE__ */ jsx("div", {
|
|
315
|
-
className: "flex size-full items-center justify-center",
|
|
316
|
-
children: /* @__PURE__ */ jsx("h3", {
|
|
317
|
-
className: "text-lg font-semibold",
|
|
318
|
-
children: error instanceof Error ? error.message : String(error)
|
|
319
|
-
})
|
|
320
|
-
});
|
|
321
|
-
}
|
|
322
|
-
function getFallbackComponent(variant, fallbackMessage) {
|
|
323
|
-
switch (variant) {
|
|
324
|
-
case "silent": return SilentFallback;
|
|
325
|
-
case "text": return () => /* @__PURE__ */ jsx(TextFallback, { message: fallbackMessage });
|
|
326
|
-
case "detailed": return DetailedFallback;
|
|
327
|
-
default: return CenteredErrorMessage;
|
|
328
|
-
}
|
|
329
|
-
}
|
|
330
|
-
/**
|
|
331
|
-
* Unified error boundary component for catching and handling React errors.
|
|
332
|
-
*
|
|
333
|
-
* Built on top of `react-error-boundary`, this component provides:
|
|
334
|
-
* - Automatic error logging with configurable context
|
|
335
|
-
* - Multiple fallback UI variants (silent, text, detailed)
|
|
336
|
-
* - Support for custom fallback render functions
|
|
337
|
-
* - Reset capability via `resetKeys`
|
|
338
|
-
*
|
|
339
|
-
* @example
|
|
340
|
-
* // Using a predefined variant
|
|
341
|
-
* <ErrorBoundary variant="detailed" loggerContext={["Connect", "Editor"]}>
|
|
342
|
-
* <EditorComponent />
|
|
343
|
-
* </ErrorBoundary>
|
|
344
|
-
*
|
|
345
|
-
* @example
|
|
346
|
-
* // Using a custom message with the text variant
|
|
347
|
-
* <ErrorBoundary variant="text" fallbackMessage="Failed to load drives">
|
|
348
|
-
* <DrivesList />
|
|
349
|
-
* </ErrorBoundary>
|
|
350
|
-
*
|
|
351
|
-
* @example
|
|
352
|
-
* // Using a custom fallback render
|
|
353
|
-
* <ErrorBoundary
|
|
354
|
-
* fallbackRender={CenteredErrorMessage}
|
|
355
|
-
* onError={(error) => trackError(error)}
|
|
356
|
-
* >
|
|
357
|
-
* <MyComponent />
|
|
358
|
-
* </ErrorBoundary>
|
|
359
|
-
*
|
|
360
|
-
* @example
|
|
361
|
-
* // Silent mode for modals (renders null on error)
|
|
362
|
-
* <ErrorBoundary variant="silent" loggerContext={["Connect", "Modals"]}>
|
|
363
|
-
* <ModalContent />
|
|
364
|
-
* </ErrorBoundary>
|
|
365
|
-
*/
|
|
366
|
-
function ErrorBoundary$1(props) {
|
|
367
|
-
const { children, onError, resetKeys, loggerContext } = props;
|
|
368
|
-
const handleError = (error, info) => {
|
|
369
|
-
if (error.message.includes("Failed to fetch dynamically imported module") && error.message.includes("node_modules/.vite")) {
|
|
370
|
-
console.error(error);
|
|
371
|
-
console.log("Outdated chunk detected, reloading page...");
|
|
372
|
-
window.location.reload();
|
|
373
|
-
return;
|
|
374
|
-
}
|
|
375
|
-
(loggerContext ? childLogger(loggerContext) : logger$1).error("@error @info", error, info);
|
|
376
|
-
onError?.(error, info);
|
|
377
|
-
};
|
|
378
|
-
return /* @__PURE__ */ jsx(ErrorBoundary, {
|
|
379
|
-
fallbackRender: hasCustomFallback(props) ? props.fallbackRender : getFallbackComponent(props.variant, props.fallbackMessage),
|
|
380
|
-
onError: handleError,
|
|
381
|
-
resetKeys,
|
|
382
|
-
children
|
|
383
|
-
});
|
|
384
|
-
}
|
|
385
|
-
//#endregion
|
|
386
|
-
//#region src/components/app-container.tsx
|
|
387
|
-
function AppContainer() {
|
|
388
|
-
const [selectedDrive] = useSelectedDrive();
|
|
389
|
-
const selectedDocumentId = useSelectedDocumentId();
|
|
390
|
-
const app = useAppModuleById(selectedDrive.header.meta?.preferredEditor);
|
|
391
|
-
const defaultApp = useDefaultAppModule();
|
|
392
|
-
const AppComponent = app?.Component ?? defaultApp?.Component ?? GenericDriveExplorer.Component;
|
|
393
|
-
if (!AppComponent) throw new Error("No app component found");
|
|
394
|
-
return /* @__PURE__ */ jsx(ErrorBoundary$1, {
|
|
395
|
-
variant: "detailed",
|
|
396
|
-
resetKeys: [selectedDrive.header.id],
|
|
397
|
-
loggerContext: ["Connect", "App"],
|
|
398
|
-
children: /* @__PURE__ */ jsx(Suspense, {
|
|
399
|
-
fallback: /* @__PURE__ */ jsx(EditorLoader, {}),
|
|
400
|
-
children: /* @__PURE__ */ jsx(DropZoneWrapper, {
|
|
401
|
-
className: "flex h-full flex-col overflow-auto",
|
|
402
|
-
children: /* @__PURE__ */ jsx(AppComponent, { children: selectedDocumentId ? /* @__PURE__ */ jsx(DocumentEditorContainer, {}) : null })
|
|
403
|
-
})
|
|
404
|
-
})
|
|
405
|
-
});
|
|
406
|
-
}
|
|
407
|
-
//#endregion
|
|
2
|
+
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="ecb0fae1-8b49-5b4b-b37b-86f2feb9a9b6")}catch(e){}}();
|
|
3
|
+
import { n as getRuntimeConfig } from "./runtime-config-DL3QjcfM.js";
|
|
4
|
+
import { n as i18n } from "./reload-connect-toast-CwvSc6F-.js";
|
|
5
|
+
import { a as defaultPHDocumentEditorConfig, i as defaultPHAppConfig, r as connectConfig } from "./connect.config-aPx3rHZQ.js";
|
|
6
|
+
import { c as subscribeReactorPgMajor, d as createFileDataStore, f as idbError, l as IDB_STORE_NAME, m as readPgVersionFile, p as openIdb, r as getCachedReactorPgMajor, u as PRIMARY_IDB_NAMES } from "./pglite-runtime-toc1-TWa.js";
|
|
7
|
+
import { t as serviceWorkerManager } from "./registerServiceWorker-B7uKpkci.js";
|
|
8
|
+
import { n as toast, t as ToastContainer } from "./toast-BEy42aYx.js";
|
|
9
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
10
|
+
import { PGlite } from "@electric-sql/pglite";
|
|
11
|
+
import { Trans, useTranslation } from "react-i18next";
|
|
12
|
+
import React, { StrictMode, Suspense, lazy, useCallback, useEffect, useMemo, useRef, useState, useSyncExternalStore } from "react";
|
|
13
|
+
import { driveCollectionId, getRevisionFromDate, initTheme, logout, openRenown, setPHAppConfig, setPHDocumentEditorConfig, setRevisionHistoryVisible, setSelectedDrive, setSelectedNode, showPHModal, useAppModuleById, useDefaultAppModule, useDocumentById, useDocumentModelModuleById, useDocumentOperations, useDrives, useEditorModuleById, useFallbackEditorModule, useIsAddDriveEnabled, useNodeParentFolderById, usePHModal, usePackageDiscoveryService, useReactorClientModule, useRevisionHistoryVisible, useSelectedDocument, useSelectedDocumentId, useSelectedDriveSafe, useSelectedFolder, useSelectedTimelineItem, useSyncList, useTheme, useUser, useVetraPackageManager, useVetraPackages } from "@powerhousedao/reactor-browser";
|
|
14
|
+
import { childLogger } from "document-model";
|
|
15
|
+
import { ConnectSidebar, ConnectTooltipProvider, CookieBanner, DefaultEditorLoader, DropZoneWrapper, HomeScreen, HomeScreenAddDriveItem, HomeScreenItem, LogoAnimation, PackageInstallModal, RevisionHistory, SidebarAddDriveItem, SidebarItem, useEns } from "@powerhousedao/design-system/connect";
|
|
16
|
+
import { z } from "zod";
|
|
17
|
+
import { Outlet, RouterProvider, createBrowserRouter, createRoutesFromChildren, matchRoutes, useLocation, useNavigationType } from "react-router-dom";
|
|
18
|
+
import { useHotkeys } from "react-hotkeys-hook";
|
|
19
|
+
import { Icon, Modal, PowerhouseButton } from "@powerhousedao/design-system";
|
|
20
|
+
import { ErrorBoundary } from "react-error-boundary";
|
|
21
|
+
import { GenericDriveExplorer } from "@powerhousedao/powerhouse-vetra-packages/editors";
|
|
22
|
+
import { twMerge } from "tailwind-merge";
|
|
23
|
+
import { redo, undo } from "@powerhousedao/shared/document-model";
|
|
408
24
|
//#region src/utils/browser.ts
|
|
409
25
|
function getBasePath() {
|
|
410
26
|
if (typeof document === "undefined") return "/";
|
|
@@ -460,18 +76,18 @@ var DocumentEditorDebugTools = class {
|
|
|
460
76
|
//#endregion
|
|
461
77
|
//#region src/components/migration-status.ts
|
|
462
78
|
let current = null;
|
|
463
|
-
const listeners$
|
|
79
|
+
const listeners$3 = /* @__PURE__ */ new Set();
|
|
464
80
|
function setMigrationStatus(status) {
|
|
465
81
|
current = status;
|
|
466
|
-
for (const l of listeners$
|
|
82
|
+
for (const l of listeners$3) l();
|
|
467
83
|
}
|
|
468
84
|
function getMigrationStatus() {
|
|
469
85
|
return current;
|
|
470
86
|
}
|
|
471
87
|
function subscribeMigrationStatus(cb) {
|
|
472
|
-
listeners$
|
|
88
|
+
listeners$3.add(cb);
|
|
473
89
|
return () => {
|
|
474
|
-
listeners$
|
|
90
|
+
listeners$3.delete(cb);
|
|
475
91
|
};
|
|
476
92
|
}
|
|
477
93
|
//#endregion
|
|
@@ -701,10 +317,418 @@ async function migrateAllIfNeeded() {
|
|
|
701
317
|
await migrateAllLocked();
|
|
702
318
|
return;
|
|
703
319
|
}
|
|
704
|
-
await navigator.locks.request("ph-pglite-migration", { mode: "exclusive" }, async () => {
|
|
705
|
-
await migrateAllLocked();
|
|
706
|
-
});
|
|
707
|
-
}
|
|
320
|
+
await navigator.locks.request("ph-pglite-migration", { mode: "exclusive" }, async () => {
|
|
321
|
+
await migrateAllLocked();
|
|
322
|
+
});
|
|
323
|
+
}
|
|
324
|
+
//#endregion
|
|
325
|
+
//#region src/hooks/useAcceptedCookies.ts
|
|
326
|
+
const ACCEPTED_COOKIES_KEY_STORAGE = `${connectConfig.routerBasename}:acceptedCookies`;
|
|
327
|
+
const listeners$2 = /* @__PURE__ */ new Set();
|
|
328
|
+
let cookies = getInitial$1();
|
|
329
|
+
function getInitial$1() {
|
|
330
|
+
try {
|
|
331
|
+
const value = localStorage.getItem(ACCEPTED_COOKIES_KEY_STORAGE);
|
|
332
|
+
return value ? JSON.parse(value) : {
|
|
333
|
+
analytics: false,
|
|
334
|
+
marketing: false,
|
|
335
|
+
functional: false
|
|
336
|
+
};
|
|
337
|
+
} catch {
|
|
338
|
+
return {
|
|
339
|
+
analytics: false,
|
|
340
|
+
marketing: false,
|
|
341
|
+
functional: false
|
|
342
|
+
};
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
function getCookies() {
|
|
346
|
+
return cookies;
|
|
347
|
+
}
|
|
348
|
+
function setCookies(setter) {
|
|
349
|
+
cookies = setter(cookies);
|
|
350
|
+
localStorage.setItem(ACCEPTED_COOKIES_KEY_STORAGE, JSON.stringify(cookies));
|
|
351
|
+
listeners$2.forEach((fn) => fn());
|
|
352
|
+
}
|
|
353
|
+
function subscribe$1(fn) {
|
|
354
|
+
listeners$2.add(fn);
|
|
355
|
+
return () => listeners$2.delete(fn);
|
|
356
|
+
}
|
|
357
|
+
const useAcceptedCookies = () => {
|
|
358
|
+
return [useSyncExternalStore(subscribe$1, getCookies, getCookies), setCookies];
|
|
359
|
+
};
|
|
360
|
+
//#endregion
|
|
361
|
+
//#region src/services/openpanel/buffer.ts
|
|
362
|
+
const buffer = [];
|
|
363
|
+
let errorHandler;
|
|
364
|
+
function defaultOnError(err) {
|
|
365
|
+
console.warn("[useOpenPanelAnalytics] track failed:", err);
|
|
366
|
+
}
|
|
367
|
+
/**
|
|
368
|
+
* Forward a single event to the active client, swallowing any throw.
|
|
369
|
+
*
|
|
370
|
+
* The outer try/catch handles synchronous throws from `client.track`; the
|
|
371
|
+
* inner `.catch()` handles rejected promises. Both are needed because
|
|
372
|
+
* `Promise.resolve(x).catch()` cannot catch a throw from evaluating `x`.
|
|
373
|
+
*/
|
|
374
|
+
function forward(client, name, props) {
|
|
375
|
+
try {
|
|
376
|
+
Promise.resolve(client.track(name, props)).catch((err) => (errorHandler ?? defaultOnError)(err));
|
|
377
|
+
} catch (err) {
|
|
378
|
+
(errorHandler ?? defaultOnError)(err);
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
/**
|
|
382
|
+
* Drain the pre-init buffer in FIFO order through `client.track`, then forward
|
|
383
|
+
* subsequent events directly. Called once from `getOpenPanelClient()`.
|
|
384
|
+
*/
|
|
385
|
+
function drainOpenPanelBuffer(client, onError) {
|
|
386
|
+
errorHandler = onError;
|
|
387
|
+
const pending = buffer.splice(0, buffer.length);
|
|
388
|
+
for (const [name, props] of pending) forward(client, name, props);
|
|
389
|
+
}
|
|
390
|
+
/**
|
|
391
|
+
* Clear the buffer and reset the active client. Buffered pre-consent events
|
|
392
|
+
* are discarded so they are not replayed if the user later re-accepts.
|
|
393
|
+
*/
|
|
394
|
+
function clearOpenPanelBuffer() {
|
|
395
|
+
buffer.length = 0;
|
|
396
|
+
errorHandler = void 0;
|
|
397
|
+
}
|
|
398
|
+
//#endregion
|
|
399
|
+
//#region src/services/openpanel/client.ts
|
|
400
|
+
let client;
|
|
401
|
+
/**
|
|
402
|
+
* Returns the cached `OpenPanel` singleton, building it on first call.
|
|
403
|
+
*
|
|
404
|
+
* When `config.clientId` is empty it returns `undefined` without importing
|
|
405
|
+
* `@openpanel/web`, so the bundler can tree-shake the SDK out of production.
|
|
406
|
+
*/
|
|
407
|
+
async function getOpenPanelClient(config) {
|
|
408
|
+
if (!config.clientId) return;
|
|
409
|
+
if (client) return client;
|
|
410
|
+
const { OpenPanel: OpenPanelClass } = await import("@openpanel/web");
|
|
411
|
+
client = new OpenPanelClass({
|
|
412
|
+
clientId: config.clientId,
|
|
413
|
+
...config.apiUrl ? { apiUrl: config.apiUrl } : {},
|
|
414
|
+
trackScreenViews: true,
|
|
415
|
+
trackOutgoingLinks: true
|
|
416
|
+
});
|
|
417
|
+
client.setGlobalProperties({ app: "connect" });
|
|
418
|
+
drainOpenPanelBuffer(client);
|
|
419
|
+
return client;
|
|
420
|
+
}
|
|
421
|
+
/**
|
|
422
|
+
* Clears the cached singleton and the pre-init buffer. Call on consent
|
|
423
|
+
* revocation or during tests; buffered events are discarded, not replayed.
|
|
424
|
+
*/
|
|
425
|
+
function resetOpenPanelClient() {
|
|
426
|
+
client = void 0;
|
|
427
|
+
clearOpenPanelBuffer();
|
|
428
|
+
}
|
|
429
|
+
//#endregion
|
|
430
|
+
//#region src/services/openpanel/events.json
|
|
431
|
+
var events_default = [
|
|
432
|
+
{
|
|
433
|
+
"documentType": "powerhouse/document-drive",
|
|
434
|
+
"actionTypes": [
|
|
435
|
+
"ADD_FOLDER",
|
|
436
|
+
"DELETE_NODE",
|
|
437
|
+
"ADD_FILE",
|
|
438
|
+
"UPDATE_FILE",
|
|
439
|
+
"COPY_NODE",
|
|
440
|
+
"MOVE_NODE",
|
|
441
|
+
"SET_DRIVE_NAME",
|
|
442
|
+
"SET_DRIVE_ICON"
|
|
443
|
+
]
|
|
444
|
+
},
|
|
445
|
+
{
|
|
446
|
+
"documentType": "powerhouse/document-model",
|
|
447
|
+
"actionTypes": [
|
|
448
|
+
"SET_MODEL_NAME",
|
|
449
|
+
"SET_MODEL_ID",
|
|
450
|
+
"ADD_MODULE",
|
|
451
|
+
"DELETE_MODULE",
|
|
452
|
+
"ADD_OPERATION",
|
|
453
|
+
"DELETE_OPERATION"
|
|
454
|
+
]
|
|
455
|
+
},
|
|
456
|
+
{
|
|
457
|
+
"documentType": "powerhouse/reactor-drive",
|
|
458
|
+
"actionTypes": [
|
|
459
|
+
"ADD_FOLDER",
|
|
460
|
+
"REMOVE_FOLDER",
|
|
461
|
+
"UPDATE_FOLDER"
|
|
462
|
+
]
|
|
463
|
+
}
|
|
464
|
+
];
|
|
465
|
+
//#endregion
|
|
466
|
+
//#region src/services/openpanel/events.ts
|
|
467
|
+
const EventMappingSchema = z.object({
|
|
468
|
+
documentType: z.string().min(1),
|
|
469
|
+
actionTypes: z.array(z.string().min(1)).min(1),
|
|
470
|
+
alias: z.string().optional()
|
|
471
|
+
}).strict();
|
|
472
|
+
const EventMappingsSchema = z.array(EventMappingSchema).readonly();
|
|
473
|
+
/**
|
|
474
|
+
* Parses and validates the event mapping table, returning the validated array
|
|
475
|
+
* and an O(1) lookup map. Accepts a `raw` override for tests. Throws on zod
|
|
476
|
+
* failures and on duplicate `(documentType, actionType)` pairs.
|
|
477
|
+
*/
|
|
478
|
+
function loadEvents(raw = events_default) {
|
|
479
|
+
const result = EventMappingsSchema.safeParse(raw);
|
|
480
|
+
if (!result.success) throw new Error(`Invalid OpenPanel events.json: ${result.error.message}`);
|
|
481
|
+
const mappings = result.data;
|
|
482
|
+
const lookupMap = /* @__PURE__ */ new Map();
|
|
483
|
+
for (const mapping of mappings) {
|
|
484
|
+
let inner = lookupMap.get(mapping.documentType);
|
|
485
|
+
if (!inner) {
|
|
486
|
+
inner = /* @__PURE__ */ new Map();
|
|
487
|
+
lookupMap.set(mapping.documentType, inner);
|
|
488
|
+
}
|
|
489
|
+
for (const actionType of mapping.actionTypes) {
|
|
490
|
+
if (inner.has(actionType)) throw new Error(`Duplicate OpenPanel event mapping for ${mapping.documentType}/${actionType}`);
|
|
491
|
+
inner.set(actionType, mapping);
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
return {
|
|
495
|
+
mappings,
|
|
496
|
+
lookupMap
|
|
497
|
+
};
|
|
498
|
+
}
|
|
499
|
+
const { mappings: defaultMappings, lookupMap: defaultLookupMap } = loadEvents();
|
|
500
|
+
/** Validated mapping array from the bundled events.json. */
|
|
501
|
+
const eventMappings = defaultMappings;
|
|
502
|
+
/** O(1) lookup map: documentType → actionType → mapping. */
|
|
503
|
+
const eventLookupMap = defaultLookupMap;
|
|
504
|
+
/**
|
|
505
|
+
* Normalizes a document type into a safe event-name segment: lowercased, `/`
|
|
506
|
+
* replaced with `.`, and any character outside `[a-z0-9._-]` stripped.
|
|
507
|
+
* e.g. `powerhouse/document-drive` → `powerhouse.document-drive`.
|
|
508
|
+
*/
|
|
509
|
+
function normalize(documentType) {
|
|
510
|
+
return documentType.toLowerCase().replace(/\//g, ".").replace(/[^a-z0-9._-]/g, "");
|
|
511
|
+
}
|
|
512
|
+
/**
|
|
513
|
+
* Derives the OpenPanel event name: `mapping.alias` when present, otherwise
|
|
514
|
+
* `${normalize(documentType)}.${actionType.toLowerCase()}`.
|
|
515
|
+
*/
|
|
516
|
+
function deriveEventName(mapping, op) {
|
|
517
|
+
if (mapping.alias) return mapping.alias;
|
|
518
|
+
return `${normalize(op.context.documentType)}.${op.operation.action.type.toLowerCase()}`;
|
|
519
|
+
}
|
|
520
|
+
/**
|
|
521
|
+
* Builds the default properties attached to every OpenPanel event. The `app`
|
|
522
|
+
* property is stamped globally by the client, not here.
|
|
523
|
+
*/
|
|
524
|
+
function buildDefaultProperties(op) {
|
|
525
|
+
return {
|
|
526
|
+
documentType: op.context.documentType,
|
|
527
|
+
actionType: op.operation.action.type,
|
|
528
|
+
documentId: op.context.documentId,
|
|
529
|
+
scope: op.context.scope,
|
|
530
|
+
branch: op.context.branch
|
|
531
|
+
};
|
|
532
|
+
}
|
|
533
|
+
//#endregion
|
|
534
|
+
//#region src/services/openpanel/processor.ts
|
|
535
|
+
/**
|
|
536
|
+
* Read-only reactor `IProcessor` that translates matching document operations
|
|
537
|
+
* into OpenPanel analytics events. Operations whose `(documentType, actionType)`
|
|
538
|
+
* pair is absent from the lookup map are skipped; per-operation errors are
|
|
539
|
+
* routed to `onError` and never thrown back to the manager.
|
|
540
|
+
*/
|
|
541
|
+
var OpenPanelProcessor = class {
|
|
542
|
+
constructor(client, lookupMap, onError = (err) => console.warn("[OpenPanelProcessor] Error tracking event:", err)) {
|
|
543
|
+
this.client = client;
|
|
544
|
+
this.lookupMap = lookupMap;
|
|
545
|
+
this.onError = onError;
|
|
546
|
+
}
|
|
547
|
+
async onOperations(operations) {
|
|
548
|
+
for (const op of operations) {
|
|
549
|
+
const inner = this.lookupMap.get(op.context.documentType);
|
|
550
|
+
if (!inner) continue;
|
|
551
|
+
const mapping = inner.get(op.operation.action.type);
|
|
552
|
+
if (!mapping) continue;
|
|
553
|
+
const name = deriveEventName(mapping, op);
|
|
554
|
+
const payload = buildDefaultProperties(op);
|
|
555
|
+
try {
|
|
556
|
+
await this.client.track(name, payload);
|
|
557
|
+
} catch (err) {
|
|
558
|
+
this.onError(err, op);
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
onDisconnect() {
|
|
563
|
+
this.client.flush?.();
|
|
564
|
+
return Promise.resolve();
|
|
565
|
+
}
|
|
566
|
+
};
|
|
567
|
+
//#endregion
|
|
568
|
+
//#region src/services/openpanel/factory.ts
|
|
569
|
+
/**
|
|
570
|
+
* Returns a `ProcessorFactory` that, for each drive, creates a single
|
|
571
|
+
* `OpenPanelProcessor` record whose `filter.documentType` is the union of all
|
|
572
|
+
* document types present in the event mapping table.
|
|
573
|
+
*/
|
|
574
|
+
function createOpenPanelProcessorFactory(config) {
|
|
575
|
+
return function openPanelProcessorFactory(_driveHeader) {
|
|
576
|
+
const documentType = Array.from(config.events.lookupMap.keys());
|
|
577
|
+
return [{
|
|
578
|
+
processor: new OpenPanelProcessor(config.client, config.events.lookupMap, config.onError),
|
|
579
|
+
filter: { documentType },
|
|
580
|
+
startFrom: config.startFrom ?? "current"
|
|
581
|
+
}];
|
|
582
|
+
};
|
|
583
|
+
}
|
|
584
|
+
//#endregion
|
|
585
|
+
//#region src/hooks/useIsEmbedded.ts
|
|
586
|
+
/**
|
|
587
|
+
* Detects whether Connect is being rendered inside another app (e.g. inside
|
|
588
|
+
* an iframe in the vetra-cli drive editor). When `?embed=1` is present in the
|
|
589
|
+
* URL, chrome that doesn't make sense in the embedded context — the cookie
|
|
590
|
+
* banner, the outer sidebar — is suppressed.
|
|
591
|
+
*/
|
|
592
|
+
function getIsEmbedded() {
|
|
593
|
+
if (typeof window === "undefined") return false;
|
|
594
|
+
try {
|
|
595
|
+
const value = new URLSearchParams(window.location.search).get("embed");
|
|
596
|
+
return value !== null && value !== "0" && value !== "false";
|
|
597
|
+
} catch {
|
|
598
|
+
return false;
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
function useIsEmbedded() {
|
|
602
|
+
return getIsEmbedded();
|
|
603
|
+
}
|
|
604
|
+
const COOKIE_BANNER_KEY_STORAGE = `${connectConfig.routerBasename}:display-cookie-banner`;
|
|
605
|
+
const listeners$1 = /* @__PURE__ */ new Set();
|
|
606
|
+
let bannerShown = getInitial();
|
|
607
|
+
function getInitial() {
|
|
608
|
+
if (getIsEmbedded()) return false;
|
|
609
|
+
try {
|
|
610
|
+
return localStorage.getItem(COOKIE_BANNER_KEY_STORAGE) !== "false";
|
|
611
|
+
} catch (error) {
|
|
612
|
+
console.error(error);
|
|
613
|
+
return true;
|
|
614
|
+
}
|
|
615
|
+
}
|
|
616
|
+
function getCookieBannerState() {
|
|
617
|
+
return bannerShown;
|
|
618
|
+
}
|
|
619
|
+
function setCookieBannerState(state) {
|
|
620
|
+
bannerShown = state;
|
|
621
|
+
localStorage.setItem(COOKIE_BANNER_KEY_STORAGE, JSON.stringify(state));
|
|
622
|
+
}
|
|
623
|
+
function subscribe(fn) {
|
|
624
|
+
listeners$1.add(fn);
|
|
625
|
+
return () => listeners$1.delete(fn);
|
|
626
|
+
}
|
|
627
|
+
const useCookieBanner = () => {
|
|
628
|
+
return [useSyncExternalStore(subscribe, getCookieBannerState, getCookieBannerState), setCookieBannerState];
|
|
629
|
+
};
|
|
630
|
+
//#endregion
|
|
631
|
+
//#region src/hooks/useFailedInstallations.ts
|
|
632
|
+
const emptyArray$1 = [];
|
|
633
|
+
function useFailedInstallations() {
|
|
634
|
+
const discoveryService = usePackageDiscoveryService();
|
|
635
|
+
return useSyncExternalStore((cb) => discoveryService?.subscribeFailed(cb) ?? (() => {}), () => discoveryService?.getFailedInstallations() ?? emptyArray$1);
|
|
636
|
+
}
|
|
637
|
+
//#endregion
|
|
638
|
+
//#region src/hooks/useInitSentry.ts
|
|
639
|
+
const logger$2 = childLogger(["sentry"]);
|
|
640
|
+
let clientStarted = false;
|
|
641
|
+
async function getSentry() {
|
|
642
|
+
return await import("@sentry/react");
|
|
643
|
+
}
|
|
644
|
+
async function initSentry() {
|
|
645
|
+
const Sentry = await getSentry();
|
|
646
|
+
const integrations = [
|
|
647
|
+
Sentry.httpClientIntegration(),
|
|
648
|
+
Sentry.extraErrorDataIntegration({ depth: 5 }),
|
|
649
|
+
Sentry.replayIntegration(),
|
|
650
|
+
Sentry.captureConsoleIntegration({ levels: ["error"] })
|
|
651
|
+
];
|
|
652
|
+
if (connectConfig.sentry.tracing) integrations.push(Sentry.reactRouterV6BrowserTracingIntegration({
|
|
653
|
+
useEffect: React.useEffect,
|
|
654
|
+
useLocation,
|
|
655
|
+
useNavigationType,
|
|
656
|
+
createRoutesFromChildren,
|
|
657
|
+
matchRoutes
|
|
658
|
+
}));
|
|
659
|
+
Sentry.init({
|
|
660
|
+
release: connectConfig.sentry.release,
|
|
661
|
+
dsn: connectConfig.sentry.dsn ?? void 0,
|
|
662
|
+
environment: connectConfig.sentry.env,
|
|
663
|
+
integrations,
|
|
664
|
+
ignoreErrors: [
|
|
665
|
+
"User is not allowed to create files",
|
|
666
|
+
"User is not allowed to move documents",
|
|
667
|
+
"The user aborted a request."
|
|
668
|
+
],
|
|
669
|
+
sendDefaultPii: true,
|
|
670
|
+
tracesSampleRate: 1,
|
|
671
|
+
replaysSessionSampleRate: .1,
|
|
672
|
+
replaysOnErrorSampleRate: 1,
|
|
673
|
+
beforeSend(event, hint) {
|
|
674
|
+
const error = hint.originalException;
|
|
675
|
+
if (error instanceof TypeError && error.message.includes("Failed to fetch") && !navigator.onLine) return null;
|
|
676
|
+
return event;
|
|
677
|
+
}
|
|
678
|
+
});
|
|
679
|
+
clientStarted = true;
|
|
680
|
+
}
|
|
681
|
+
async function closeClient() {
|
|
682
|
+
if (!clientStarted) return;
|
|
683
|
+
return (await getSentry()).getClient()?.close();
|
|
684
|
+
}
|
|
685
|
+
function useInitSentry() {
|
|
686
|
+
const [acceptedCookies] = useAcceptedCookies();
|
|
687
|
+
const { analytics } = acceptedCookies;
|
|
688
|
+
useEffect(() => {
|
|
689
|
+
if (!analytics) {
|
|
690
|
+
closeClient().catch((error) => logger$2.error("@error", error));
|
|
691
|
+
return;
|
|
692
|
+
}
|
|
693
|
+
if (clientStarted || connectConfig.sentry.dsn === null || connectConfig.sentry.dsn === void 0 || connectConfig.sentry.dsn === "") return;
|
|
694
|
+
initSentry().catch((error) => logger$2.error("@error", error));
|
|
695
|
+
}, [analytics]);
|
|
696
|
+
}
|
|
697
|
+
//#endregion
|
|
698
|
+
//#region src/hooks/usePendingInstallations.ts
|
|
699
|
+
const emptyArray = [];
|
|
700
|
+
function usePendingInstallations() {
|
|
701
|
+
const discoveryService = usePackageDiscoveryService();
|
|
702
|
+
const cacheRef = useRef(emptyArray);
|
|
703
|
+
return useSyncExternalStore((cb) => discoveryService?.subscribePending(cb) ?? (() => {}), useCallback(() => {
|
|
704
|
+
if (!discoveryService) return emptyArray;
|
|
705
|
+
const next = discoveryService.getPendingInstallations() ?? emptyArray;
|
|
706
|
+
const prev = cacheRef.current;
|
|
707
|
+
if (next === prev || next.length === prev.length && next.every((p, i) => p === prev[i])) return prev;
|
|
708
|
+
cacheRef.current = next;
|
|
709
|
+
return next;
|
|
710
|
+
}, [discoveryService]));
|
|
711
|
+
}
|
|
712
|
+
//#endregion
|
|
713
|
+
//#region src/hooks/useUndoRedoShortcuts.ts
|
|
714
|
+
const useUndoRedoShortcuts = (props) => {
|
|
715
|
+
const { undo, redo, canRedo, canUndo } = props;
|
|
716
|
+
const isMac = window.navigator.userAgent.includes("Mac");
|
|
717
|
+
let undoShortcut = "ctrl+z";
|
|
718
|
+
let redoShortcut = "ctrl+y";
|
|
719
|
+
if (isMac) {
|
|
720
|
+
undoShortcut = "mod+z";
|
|
721
|
+
redoShortcut = "mod+shift+z";
|
|
722
|
+
}
|
|
723
|
+
useHotkeys(undoShortcut, (event) => {
|
|
724
|
+
event.preventDefault();
|
|
725
|
+
if (canUndo) undo();
|
|
726
|
+
}, {}, [canUndo, undo]);
|
|
727
|
+
useHotkeys(redoShortcut, (event) => {
|
|
728
|
+
event.preventDefault();
|
|
729
|
+
if (canRedo) redo();
|
|
730
|
+
}, {}, [canRedo, redo]);
|
|
731
|
+
};
|
|
708
732
|
//#endregion
|
|
709
733
|
//#region src/components/app-skeleton.tsx
|
|
710
734
|
const LOADER_DELAY = 250;
|
|
@@ -719,12 +743,12 @@ const MigrationOverlay = () => {
|
|
|
719
743
|
return /* @__PURE__ */ jsx("div", {
|
|
720
744
|
className: "absolute inset-0 z-20 flex items-center justify-center",
|
|
721
745
|
children: /* @__PURE__ */ jsxs("div", {
|
|
722
|
-
className: "rounded-lg bg-white/90 px-6 py-4 text-sm text-gray-900 shadow-lg",
|
|
746
|
+
className: "rounded-lg bg-white/90 px-6 py-4 text-sm text-gray-900 shadow-lg dark:bg-slate-900/90 dark:text-slate-50",
|
|
723
747
|
children: [/* @__PURE__ */ jsx("div", {
|
|
724
748
|
className: "font-medium",
|
|
725
749
|
children: "Upgrading local database…"
|
|
726
750
|
}), /* @__PURE__ */ jsx("div", {
|
|
727
|
-
className: "text-gray-
|
|
751
|
+
className: "text-gray-700 dark:text-slate-200",
|
|
728
752
|
children: PHASE_LABEL[status.phase]
|
|
729
753
|
})]
|
|
730
754
|
})
|
|
@@ -733,6 +757,7 @@ const MigrationOverlay = () => {
|
|
|
733
757
|
const Loader = ({ delay = LOADER_DELAY }) => {
|
|
734
758
|
const isSSR = typeof window === "undefined";
|
|
735
759
|
const showInitialLoader = typeof document !== "undefined" && document.body.getAttribute("data-show-loader") === "true";
|
|
760
|
+
if (!isSSR) initTheme();
|
|
736
761
|
const [showLoading, setShowLoading] = useState(!delay || showInitialLoader);
|
|
737
762
|
useEffect(() => {
|
|
738
763
|
const id = setTimeout(() => {
|
|
@@ -744,7 +769,7 @@ const Loader = ({ delay = LOADER_DELAY }) => {
|
|
|
744
769
|
className: `skeleton-loader absolute inset-0 z-10 flex items-center justify-center ${showLoading ? "" : "hidden"}`,
|
|
745
770
|
children: [/* @__PURE__ */ jsx("div", {
|
|
746
771
|
className: "animate-pulse overflow-hidden rounded-full shadow-lg",
|
|
747
|
-
children: /* @__PURE__ */ jsx(
|
|
772
|
+
children: /* @__PURE__ */ jsx(LogoAnimation, {})
|
|
748
773
|
}), isSSR ? /* @__PURE__ */ jsx("script", { dangerouslySetInnerHTML: { __html: `setTimeout(() => {
|
|
749
774
|
document.querySelector('.skeleton-loader')?.classList.remove('hidden');
|
|
750
775
|
document.body.setAttribute('data-show-loader', 'true');
|
|
@@ -755,9 +780,9 @@ const AppSkeleton = (props) => {
|
|
|
755
780
|
const isSSR = typeof window === "undefined";
|
|
756
781
|
const isHomeScreen = !isSSR && window.location.pathname === getBasePath();
|
|
757
782
|
return /* @__PURE__ */ jsxs("div", {
|
|
758
|
-
className: "flex h-screen overflow-hidden",
|
|
783
|
+
className: "flex h-screen overflow-hidden bg-gray-50 dark:bg-slate-700",
|
|
759
784
|
children: [
|
|
760
|
-
/* @__PURE__ */ jsx(ConnectSidebar, {
|
|
785
|
+
!(!isSSR && getIsEmbedded()) && /* @__PURE__ */ jsx(ConnectSidebar, {
|
|
761
786
|
className: "animate-pulse",
|
|
762
787
|
onLogin: void 0,
|
|
763
788
|
onDisconnect: void 0,
|
|
@@ -781,164 +806,396 @@ const AppSkeleton = (props) => {
|
|
|
781
806
|
});
|
|
782
807
|
};
|
|
783
808
|
//#endregion
|
|
784
|
-
//#region src/components/
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
for (const l of listeners) l();
|
|
789
|
-
}
|
|
790
|
-
function dismiss() {
|
|
791
|
-
dismissed = true;
|
|
792
|
-
notify();
|
|
809
|
+
//#region src/components/error-boundary.tsx
|
|
810
|
+
const logger$1 = childLogger(["Connect"]);
|
|
811
|
+
function hasCustomFallback(props) {
|
|
812
|
+
return "fallbackRender" in props;
|
|
793
813
|
}
|
|
794
|
-
function
|
|
795
|
-
|
|
796
|
-
return () => {
|
|
797
|
-
listeners.delete(cb);
|
|
798
|
-
};
|
|
814
|
+
function SilentFallback() {
|
|
815
|
+
return null;
|
|
799
816
|
}
|
|
800
|
-
|
|
801
|
-
|
|
817
|
+
/**
|
|
818
|
+
* Simple text-based fallback component.
|
|
819
|
+
* Displays a centered message when an error occurs.
|
|
820
|
+
*/
|
|
821
|
+
function TextFallback({ message = "Something went wrong" }) {
|
|
822
|
+
return /* @__PURE__ */ jsx("div", {
|
|
823
|
+
className: "text-center",
|
|
824
|
+
children: message
|
|
825
|
+
});
|
|
802
826
|
}
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
const
|
|
811
|
-
setError(null);
|
|
812
|
-
setMigrating(true);
|
|
813
|
-
migrateAllIfNeeded().then(() => {
|
|
814
|
-
window.location.reload();
|
|
815
|
-
}).catch((err) => {
|
|
816
|
-
setError(err instanceof Error ? err.message : String(err));
|
|
817
|
-
setMigrating(false);
|
|
818
|
-
});
|
|
819
|
-
};
|
|
827
|
+
/**
|
|
828
|
+
* Detailed fallback component showing full error information.
|
|
829
|
+
* Displays error message with a collapsible details section.
|
|
830
|
+
* Useful for development and debugging purposes.
|
|
831
|
+
*/
|
|
832
|
+
function DetailedFallback({ error, resetErrorBoundary }) {
|
|
833
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
834
|
+
const errorDetails = error instanceof Error ? error.stack ?? String(error.cause) : JSON.stringify(error, null, 2);
|
|
820
835
|
return /* @__PURE__ */ jsx("div", {
|
|
821
|
-
className: "
|
|
836
|
+
className: "z-10 mx-auto flex max-w-[80%] flex-1 items-center justify-center p-6",
|
|
822
837
|
children: /* @__PURE__ */ jsxs("div", {
|
|
823
|
-
className: "
|
|
838
|
+
className: "w-full max-w-lg rounded-lg border border-gray-500 bg-gray-50 p-6 shadow-sm dark:border-slate-400 dark:bg-slate-800",
|
|
824
839
|
children: [
|
|
825
840
|
/* @__PURE__ */ jsxs("div", {
|
|
826
|
-
className: "flex-
|
|
827
|
-
children: [
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
]
|
|
835
|
-
}),
|
|
836
|
-
/* @__PURE__ */ jsxs("div", {
|
|
837
|
-
className: "text-gray-800",
|
|
838
|
-
children: [
|
|
839
|
-
"Migrate to Postgres ",
|
|
840
|
-
17,
|
|
841
|
-
" to pick up the latest features. Your data will be backed up first."
|
|
842
|
-
]
|
|
843
|
-
}),
|
|
844
|
-
error && /* @__PURE__ */ jsxs("div", {
|
|
845
|
-
className: "mt-2 font-medium text-red-900",
|
|
846
|
-
children: ["Migration failed: ", error]
|
|
847
|
-
})
|
|
848
|
-
]
|
|
841
|
+
className: "mb-3 flex items-center gap-2",
|
|
842
|
+
children: [/* @__PURE__ */ jsx(Icon, {
|
|
843
|
+
name: "Error",
|
|
844
|
+
className: "size-5 shrink-0"
|
|
845
|
+
}), /* @__PURE__ */ jsx("h1", {
|
|
846
|
+
className: "text-lg font-semibold",
|
|
847
|
+
children: "Something went wrong"
|
|
848
|
+
})]
|
|
849
849
|
}),
|
|
850
|
-
/* @__PURE__ */ jsx("
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
onClick: handleMigrate,
|
|
854
|
-
className: "rounded-sm bg-gray-900 px-3 py-1 text-sm font-medium text-white hover:bg-gray-800 disabled:opacity-50",
|
|
855
|
-
children: migrating ? "Migrating…" : "Migrate now"
|
|
850
|
+
/* @__PURE__ */ jsx("p", {
|
|
851
|
+
className: "mb-4 text-sm text-gray-700 dark:text-slate-200",
|
|
852
|
+
children: errorMessage
|
|
856
853
|
}),
|
|
857
|
-
/* @__PURE__ */
|
|
854
|
+
errorDetails !== "{}" && /* @__PURE__ */ jsxs("details", {
|
|
855
|
+
className: "group",
|
|
856
|
+
children: [/* @__PURE__ */ jsx("summary", {
|
|
857
|
+
className: "cursor-pointer text-sm font-medium text-gray-700 underline select-none hover:text-gray-700 dark:text-slate-200 dark:hover:text-slate-200",
|
|
858
|
+
children: "Show details"
|
|
859
|
+
}), /* @__PURE__ */ jsx("pre", {
|
|
860
|
+
className: "mt-2 max-h-48 overflow-auto rounded-sm bg-gray-100 p-3 text-xs dark:bg-slate-700",
|
|
861
|
+
children: errorDetails
|
|
862
|
+
})]
|
|
863
|
+
}),
|
|
864
|
+
/* @__PURE__ */ jsx(PowerhouseButton, {
|
|
858
865
|
type: "button",
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
children: "Dismiss"
|
|
866
|
+
onClick: resetErrorBoundary,
|
|
867
|
+
className: "mt-4 px-3 py-1.5 text-base font-medium",
|
|
868
|
+
children: "Try again"
|
|
863
869
|
})
|
|
864
870
|
]
|
|
865
871
|
})
|
|
866
872
|
});
|
|
867
|
-
}
|
|
873
|
+
}
|
|
874
|
+
/**
|
|
875
|
+
* Centered error message fallback component.
|
|
876
|
+
* Displays the error message in a centered, full-size container.
|
|
877
|
+
* Suitable for use as a custom fallbackRender when you need simple error display.
|
|
878
|
+
*/
|
|
879
|
+
function CenteredErrorMessage({ error }) {
|
|
880
|
+
return /* @__PURE__ */ jsx("div", {
|
|
881
|
+
className: "flex size-full items-center justify-center",
|
|
882
|
+
children: /* @__PURE__ */ jsx("h3", {
|
|
883
|
+
className: "text-lg font-semibold",
|
|
884
|
+
children: error instanceof Error ? error.message : String(error)
|
|
885
|
+
})
|
|
886
|
+
});
|
|
887
|
+
}
|
|
888
|
+
function getFallbackComponent(variant, fallbackMessage) {
|
|
889
|
+
switch (variant) {
|
|
890
|
+
case "silent": return SilentFallback;
|
|
891
|
+
case "text": return () => /* @__PURE__ */ jsx(TextFallback, { message: fallbackMessage });
|
|
892
|
+
case "detailed": return DetailedFallback;
|
|
893
|
+
default: return CenteredErrorMessage;
|
|
894
|
+
}
|
|
895
|
+
}
|
|
896
|
+
/**
|
|
897
|
+
* Unified error boundary component for catching and handling React errors.
|
|
898
|
+
*
|
|
899
|
+
* Built on top of `react-error-boundary`, this component provides:
|
|
900
|
+
* - Automatic error logging with configurable context
|
|
901
|
+
* - Multiple fallback UI variants (silent, text, detailed)
|
|
902
|
+
* - Support for custom fallback render functions
|
|
903
|
+
* - Reset capability via `resetKeys`
|
|
904
|
+
*
|
|
905
|
+
* @example
|
|
906
|
+
* // Using a predefined variant
|
|
907
|
+
* <ErrorBoundary variant="detailed" loggerContext={["Connect", "Editor"]}>
|
|
908
|
+
* <EditorComponent />
|
|
909
|
+
* </ErrorBoundary>
|
|
910
|
+
*
|
|
911
|
+
* @example
|
|
912
|
+
* // Using a custom message with the text variant
|
|
913
|
+
* <ErrorBoundary variant="text" fallbackMessage="Failed to load drives">
|
|
914
|
+
* <DrivesList />
|
|
915
|
+
* </ErrorBoundary>
|
|
916
|
+
*
|
|
917
|
+
* @example
|
|
918
|
+
* // Using a custom fallback render
|
|
919
|
+
* <ErrorBoundary
|
|
920
|
+
* fallbackRender={CenteredErrorMessage}
|
|
921
|
+
* onError={(error) => trackError(error)}
|
|
922
|
+
* >
|
|
923
|
+
* <MyComponent />
|
|
924
|
+
* </ErrorBoundary>
|
|
925
|
+
*
|
|
926
|
+
* @example
|
|
927
|
+
* // Silent mode for modals (renders null on error)
|
|
928
|
+
* <ErrorBoundary variant="silent" loggerContext={["Connect", "Modals"]}>
|
|
929
|
+
* <ModalContent />
|
|
930
|
+
* </ErrorBoundary>
|
|
931
|
+
*/
|
|
932
|
+
function ErrorBoundary$1(props) {
|
|
933
|
+
const { children, onError, resetKeys, loggerContext } = props;
|
|
934
|
+
const handleError = (error, info) => {
|
|
935
|
+
if (error.message.includes("Failed to fetch dynamically imported module") && error.message.includes("node_modules/.vite")) {
|
|
936
|
+
console.error(error);
|
|
937
|
+
console.log("Outdated chunk detected, reloading page...");
|
|
938
|
+
window.location.reload();
|
|
939
|
+
return;
|
|
940
|
+
}
|
|
941
|
+
(loggerContext ? childLogger(loggerContext) : logger$1).error("@error @info", error, info);
|
|
942
|
+
onError?.(error, info);
|
|
943
|
+
};
|
|
944
|
+
return /* @__PURE__ */ jsx(ErrorBoundary, {
|
|
945
|
+
fallbackRender: hasCustomFallback(props) ? props.fallbackRender : getFallbackComponent(props.variant, props.fallbackMessage),
|
|
946
|
+
onError: handleError,
|
|
947
|
+
resetKeys,
|
|
948
|
+
children
|
|
949
|
+
});
|
|
950
|
+
}
|
|
951
|
+
//#endregion
|
|
952
|
+
//#region src/components/analytics.tsx
|
|
953
|
+
function gtag(...args) {
|
|
954
|
+
window.dataLayer?.push(...args);
|
|
955
|
+
}
|
|
956
|
+
const Analytics = () => {
|
|
957
|
+
const gaTrackingId = connectConfig.gaTrackingId;
|
|
958
|
+
const [{ analytics }] = useAcceptedCookies();
|
|
959
|
+
const useAnalytics = gaTrackingId && analytics;
|
|
960
|
+
useEffect(() => {
|
|
961
|
+
if (useAnalytics) {
|
|
962
|
+
const script = document.createElement("script");
|
|
963
|
+
script.src = `https://www.googletagmanager.com/gtag/js?id=${gaTrackingId}`;
|
|
964
|
+
script.async = true;
|
|
965
|
+
document.head.appendChild(script);
|
|
966
|
+
window.dataLayer = window.dataLayer || [];
|
|
967
|
+
gtag("js", /* @__PURE__ */ new Date());
|
|
968
|
+
gtag("config", gaTrackingId);
|
|
969
|
+
return () => {
|
|
970
|
+
document.head.removeChild(script);
|
|
971
|
+
};
|
|
972
|
+
}
|
|
973
|
+
}, [useAnalytics, gaTrackingId]);
|
|
974
|
+
return null;
|
|
975
|
+
};
|
|
976
|
+
//#endregion
|
|
977
|
+
//#region src/components/openpanel-traits.ts
|
|
978
|
+
/**
|
|
979
|
+
* Builds the OpenPanel identity traits from a renown User.
|
|
980
|
+
*
|
|
981
|
+
* Canonical trait schema (shared with Renown and Vetra — each app sends every
|
|
982
|
+
* field it has data for, under these names):
|
|
983
|
+
* - `address`, `did`, `networkId`, `chainId`, `caip2` — wallet/chain facts.
|
|
984
|
+
* - `ensName`, `ensAvatar` — raw ENS facts.
|
|
985
|
+
* - `username`, `userImage`, `profileDocumentId`, `profileCreatedAt` — raw
|
|
986
|
+
* Renown profile facts.
|
|
987
|
+
* - `accountType` — wallet-adapter concept; only Renown has it.
|
|
988
|
+
*
|
|
989
|
+
* Rules:
|
|
990
|
+
* - `credential` (contains a JWT) is **never** forwarded.
|
|
991
|
+
* - Traits carry raw facts only; resolved presentation values (avatar,
|
|
992
|
+
* display name) go in OpenPanel's native identify fields — see
|
|
993
|
+
* {@link buildIdentifyPayload}.
|
|
994
|
+
* - Optional fields (`ens`, `profile`) are only included when their value is
|
|
995
|
+
* non-nullish (guards against `null` from `RenownProfile` fields as well
|
|
996
|
+
* as plain `undefined`).
|
|
997
|
+
*
|
|
998
|
+
* Mirror the Sentry pattern in `store/user.ts`: destructure off `credential`
|
|
999
|
+
* first, then assemble the trait payload from the remainder.
|
|
1000
|
+
*/
|
|
1001
|
+
function buildTraits(user) {
|
|
1002
|
+
const { credential: _credential, ...rest } = user;
|
|
1003
|
+
const traits = {
|
|
1004
|
+
address: rest.address,
|
|
1005
|
+
did: rest.did,
|
|
1006
|
+
networkId: rest.networkId,
|
|
1007
|
+
chainId: rest.chainId,
|
|
1008
|
+
caip2: `${rest.networkId}:${rest.chainId}`
|
|
1009
|
+
};
|
|
1010
|
+
if (rest.ens?.name != null) traits.ensName = rest.ens.name;
|
|
1011
|
+
if (rest.ens?.avatarUrl != null) traits.ensAvatar = rest.ens.avatarUrl;
|
|
1012
|
+
if (rest.profile?.username != null) traits.username = rest.profile.username;
|
|
1013
|
+
if (rest.profile?.userImage != null) traits.userImage = rest.profile.userImage;
|
|
1014
|
+
if (rest.profile?.documentId != null) traits.profileDocumentId = rest.profile.documentId;
|
|
1015
|
+
if (rest.profile?.createdAt != null) traits.profileCreatedAt = rest.profile.createdAt;
|
|
1016
|
+
return traits;
|
|
1017
|
+
}
|
|
1018
|
+
/**
|
|
1019
|
+
* Builds the full `identify()` payload:
|
|
1020
|
+
* - `profileId` is the wallet address — the cross-app profile key shared with
|
|
1021
|
+
* Renown and Vetra.
|
|
1022
|
+
* - `avatar` / `firstName` are OpenPanel's native profile fields (they drive
|
|
1023
|
+
* the picture and name in the dashboard UI), resolved as
|
|
1024
|
+
* `userImage ?? ensAvatar` and `ensName ?? username`.
|
|
1025
|
+
* - `properties` are the raw traits from {@link buildTraits}.
|
|
1026
|
+
*/
|
|
1027
|
+
function buildIdentifyPayload(user) {
|
|
1028
|
+
const avatar = user.profile?.userImage ?? user.ens?.avatarUrl;
|
|
1029
|
+
const firstName = user.ens?.name ?? user.profile?.username;
|
|
1030
|
+
return {
|
|
1031
|
+
profileId: user.address,
|
|
1032
|
+
...avatar != null ? { avatar } : {},
|
|
1033
|
+
...firstName != null ? { firstName } : {},
|
|
1034
|
+
properties: buildTraits(user)
|
|
1035
|
+
};
|
|
1036
|
+
}
|
|
1037
|
+
//#endregion
|
|
1038
|
+
//#region src/components/openpanel.tsx
|
|
1039
|
+
/**
|
|
1040
|
+
* `OpenPanel` is a `null`-rendering component that manages the full lifecycle
|
|
1041
|
+
* of the OpenPanel analytics subsystem.
|
|
1042
|
+
*
|
|
1043
|
+
* Gates:
|
|
1044
|
+
* - `useAcceptedCookies().analytics === true` — the existing analytics cookie.
|
|
1045
|
+
* - `connectConfig.openPanel.clientId` non-empty — no client ID → no-op.
|
|
1046
|
+
*
|
|
1047
|
+
* Behaviour when both gates pass:
|
|
1048
|
+
* 1. Lazy-imports `@openpanel/web` and builds the singleton via
|
|
1049
|
+
* `getOpenPanelClient(connectConfig.openPanel)`.
|
|
1050
|
+
* 2. Exposes the client on `window.openPanel` for the card-6
|
|
1051
|
+
* `useOpenPanelAnalytics()` hook to consume.
|
|
1052
|
+
* 3. If `connectConfig.openPanel.trackOperations`, registers the processor
|
|
1053
|
+
* factory against `processorManager` so document operations are forwarded.
|
|
1054
|
+
* 4. Calls `client.identify()` when the renown user transitions from
|
|
1055
|
+
* `undefined` → defined (login). The profile ID is the wallet address —
|
|
1056
|
+
* the cross-app key shared with Renown and Vetra.
|
|
1057
|
+
* 5. Calls `client.clear()` when the user transitions from defined →
|
|
1058
|
+
* `undefined` (logout).
|
|
1059
|
+
*
|
|
1060
|
+
* Teardown (unmount **or** consent revocation):
|
|
1061
|
+
* - `unregisterFactory("openpanel")` to remove the processor.
|
|
1062
|
+
* - `resetOpenPanelClient()` to clear the singleton.
|
|
1063
|
+
* - `window.openPanel` is cleared.
|
|
1064
|
+
*
|
|
1065
|
+
* Mirrors the Sentry pattern in `store/user.ts` for login/logout detection.
|
|
1066
|
+
* Analytics failures are caught and forwarded to `console.warn` — they must
|
|
1067
|
+
* never throw into the application.
|
|
1068
|
+
*
|
|
1069
|
+
* Mounted next to `<Analytics />` in `app.tsx`.
|
|
1070
|
+
*/
|
|
1071
|
+
function OpenPanel() {
|
|
1072
|
+
const [{ analytics }] = useAcceptedCookies();
|
|
1073
|
+
const user = useUser();
|
|
1074
|
+
const reactorClientModule = useReactorClientModule();
|
|
1075
|
+
const [client, setClient] = useState();
|
|
1076
|
+
/**
|
|
1077
|
+
* Tracks the previous `user` value so we can detect the two transitions:
|
|
1078
|
+
* undefined → defined (login)
|
|
1079
|
+
* defined → undefined (logout)
|
|
1080
|
+
*/
|
|
1081
|
+
const prevUserRef = useRef(void 0);
|
|
1082
|
+
const enabled = analytics && !!connectConfig.openPanel.clientId;
|
|
1083
|
+
const processorManager = reactorClientModule?.reactorModule?.processorManager;
|
|
1084
|
+
useEffect(() => {
|
|
1085
|
+
if (!enabled) return;
|
|
1086
|
+
let cancelled = false;
|
|
1087
|
+
const isCancelled = () => cancelled;
|
|
1088
|
+
const setup = async () => {
|
|
1089
|
+
let builtClient;
|
|
1090
|
+
try {
|
|
1091
|
+
builtClient = await getOpenPanelClient(connectConfig.openPanel);
|
|
1092
|
+
} catch (err) {
|
|
1093
|
+
console.warn("[OpenPanel] Failed to build client:", err);
|
|
1094
|
+
return;
|
|
1095
|
+
}
|
|
1096
|
+
if (isCancelled() || !builtClient) return;
|
|
1097
|
+
setClient(builtClient);
|
|
1098
|
+
window.openPanel = builtClient;
|
|
1099
|
+
if (connectConfig.openPanel.trackOperations && processorManager) try {
|
|
1100
|
+
await processorManager.registerFactory("openpanel", createOpenPanelProcessorFactory({
|
|
1101
|
+
client: builtClient,
|
|
1102
|
+
events: {
|
|
1103
|
+
mappings: eventMappings,
|
|
1104
|
+
lookupMap: eventLookupMap
|
|
1105
|
+
},
|
|
1106
|
+
startFrom: "current"
|
|
1107
|
+
}));
|
|
1108
|
+
if (isCancelled()) await processorManager.unregisterFactory("openpanel").catch((err) => console.warn("[OpenPanel] Failed to unregister factory after cancellation:", err));
|
|
1109
|
+
} catch (err) {
|
|
1110
|
+
console.warn("[OpenPanel] Failed to register processor factory:", err);
|
|
1111
|
+
}
|
|
1112
|
+
};
|
|
1113
|
+
setup();
|
|
1114
|
+
return () => {
|
|
1115
|
+
cancelled = true;
|
|
1116
|
+
prevUserRef.current = void 0;
|
|
1117
|
+
if (connectConfig.openPanel.trackOperations && processorManager) processorManager.unregisterFactory("openpanel").catch((err) => console.warn("[OpenPanel] Failed to unregister processor factory:", err));
|
|
1118
|
+
resetOpenPanelClient();
|
|
1119
|
+
window.openPanel = void 0;
|
|
1120
|
+
setClient(void 0);
|
|
1121
|
+
};
|
|
1122
|
+
}, [enabled, processorManager]);
|
|
1123
|
+
useEffect(() => {
|
|
1124
|
+
if (!enabled || !client) return;
|
|
1125
|
+
const prev = prevUserRef.current;
|
|
1126
|
+
prevUserRef.current = user;
|
|
1127
|
+
if (!prev && user) try {
|
|
1128
|
+
client.identify(buildIdentifyPayload(user));
|
|
1129
|
+
} catch (err) {
|
|
1130
|
+
console.warn("[OpenPanel] Failed to identify user:", err);
|
|
1131
|
+
}
|
|
1132
|
+
else if (prev && !user) try {
|
|
1133
|
+
client.clear();
|
|
1134
|
+
} catch (err) {
|
|
1135
|
+
console.warn("[OpenPanel] Failed to clear user:", err);
|
|
1136
|
+
}
|
|
1137
|
+
}, [
|
|
1138
|
+
client,
|
|
1139
|
+
user,
|
|
1140
|
+
enabled
|
|
1141
|
+
]);
|
|
1142
|
+
return null;
|
|
1143
|
+
}
|
|
1144
|
+
//#endregion
|
|
1145
|
+
//#region src/components/document-editor-container.tsx
|
|
1146
|
+
function DocumentEditorContainer() {
|
|
1147
|
+
const [selectedDocument] = useSelectedDocument();
|
|
1148
|
+
const parentFolder = useNodeParentFolderById(selectedDocument.header.id);
|
|
1149
|
+
useMemo(() => {
|
|
1150
|
+
return async () => {};
|
|
1151
|
+
}, []);
|
|
1152
|
+
useCallback(() => {
|
|
1153
|
+
setSelectedNode(parentFolder);
|
|
1154
|
+
}, [parentFolder]);
|
|
1155
|
+
return /* @__PURE__ */ jsx("div", {
|
|
1156
|
+
id: "document-editor-container",
|
|
1157
|
+
className: "flex-1",
|
|
1158
|
+
"data-document-type": selectedDocument.header.documentType,
|
|
1159
|
+
children: /* @__PURE__ */ jsx(DocumentEditor, { document: selectedDocument })
|
|
1160
|
+
});
|
|
1161
|
+
}
|
|
868
1162
|
//#endregion
|
|
869
|
-
//#region src/components/
|
|
870
|
-
|
|
871
|
-
const
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
const
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
const modalComponents = {
|
|
883
|
-
addDrive: AddDriveModal$1,
|
|
884
|
-
clearStorage: ClearStorageModal,
|
|
885
|
-
cookiesPolicy: CookiesPolicyModal,
|
|
886
|
-
createDocument: CreateDocumentModal$1,
|
|
887
|
-
debugSettings: DebugSettingsModal,
|
|
888
|
-
deleteDrive: DeleteDriveModal,
|
|
889
|
-
deleteItem: DeleteItemModal,
|
|
890
|
-
disclaimer: DisclaimerModal,
|
|
891
|
-
driveSettings: DriveSettingsModal$1,
|
|
892
|
-
downloadDocumentWithErrors: DownloadDocumentWithErrorsModal,
|
|
893
|
-
inspector: lazy(() => import("./InspectorModal-DrBnrYZl.js").then((m) => ({ default: m.InspectorModal }))),
|
|
894
|
-
settings: SettingsModal$1,
|
|
895
|
-
upgradeDrive: UpgradeDriveModal,
|
|
896
|
-
missingPackage: lazy(() => import("./MissingPackageModal-CUdcDjSO.js").then((m) => ({ default: m.ConnectMissingPackageModal })))
|
|
897
|
-
};
|
|
898
|
-
const ModalsContainer = lazy(async () => {
|
|
899
|
-
return { default: () => {
|
|
900
|
-
const phModal = usePHModal();
|
|
901
|
-
if (!phModal?.type) return null;
|
|
902
|
-
const ModalComponent = modalComponents[phModal.type];
|
|
903
|
-
return ModalComponent ? /* @__PURE__ */ jsx(ErrorBoundary$1, {
|
|
904
|
-
variant: "silent",
|
|
905
|
-
loggerContext: ["Connect", "Modals"],
|
|
906
|
-
children: /* @__PURE__ */ jsx(Suspense, {
|
|
907
|
-
fallback: null,
|
|
908
|
-
children: /* @__PURE__ */ jsx(ModalComponent, {})
|
|
909
|
-
})
|
|
910
|
-
}) : null;
|
|
911
|
-
} };
|
|
912
|
-
});
|
|
1163
|
+
//#region src/components/editor-loader.tsx
|
|
1164
|
+
function EditorLoader(props) {
|
|
1165
|
+
const [showLoading, setShowLoading] = useState(false);
|
|
1166
|
+
useEffect(() => {
|
|
1167
|
+
setTimeout(() => {
|
|
1168
|
+
setShowLoading(true);
|
|
1169
|
+
}, props.loadingTimeout ?? 200);
|
|
1170
|
+
}, [props]);
|
|
1171
|
+
if (!showLoading) return null;
|
|
1172
|
+
const { customEditorLoader, ...defaultProps } = props;
|
|
1173
|
+
if (customEditorLoader) return /* @__PURE__ */ jsx(Fragment, { children: customEditorLoader });
|
|
1174
|
+
return /* @__PURE__ */ jsx(DefaultEditorLoader, { ...defaultProps });
|
|
1175
|
+
}
|
|
913
1176
|
//#endregion
|
|
914
|
-
//#region src/components/app-
|
|
915
|
-
|
|
916
|
-
const
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
children: /* @__PURE__ */ jsx(ModalsContainer, {})
|
|
937
|
-
}),
|
|
938
|
-
/* @__PURE__ */ jsx(MigrationBanner, {})
|
|
939
|
-
]
|
|
940
|
-
}) });
|
|
941
|
-
};
|
|
1177
|
+
//#region src/components/app-container.tsx
|
|
1178
|
+
function AppContainer() {
|
|
1179
|
+
const [selectedDrive] = useSelectedDriveSafe();
|
|
1180
|
+
const selectedDocumentId = useSelectedDocumentId();
|
|
1181
|
+
const app = useAppModuleById(selectedDrive?.header.meta?.preferredEditor);
|
|
1182
|
+
const defaultApp = useDefaultAppModule();
|
|
1183
|
+
if (!selectedDrive) return /* @__PURE__ */ jsx(EditorLoader, {});
|
|
1184
|
+
const AppComponent = app?.Component ?? defaultApp?.Component ?? GenericDriveExplorer.Component;
|
|
1185
|
+
if (!AppComponent) throw new Error("No app component found");
|
|
1186
|
+
return /* @__PURE__ */ jsx(ErrorBoundary$1, {
|
|
1187
|
+
variant: "detailed",
|
|
1188
|
+
resetKeys: [selectedDrive.header.id],
|
|
1189
|
+
loggerContext: ["Connect", "App"],
|
|
1190
|
+
children: /* @__PURE__ */ jsx(Suspense, {
|
|
1191
|
+
fallback: /* @__PURE__ */ jsx(EditorLoader, {}),
|
|
1192
|
+
children: /* @__PURE__ */ jsx(DropZoneWrapper, {
|
|
1193
|
+
className: "flex h-full flex-col overflow-auto",
|
|
1194
|
+
children: /* @__PURE__ */ jsx(AppComponent, { children: selectedDocumentId ? /* @__PURE__ */ jsx(DocumentEditorContainer, {}) : null })
|
|
1195
|
+
})
|
|
1196
|
+
})
|
|
1197
|
+
});
|
|
1198
|
+
}
|
|
942
1199
|
//#endregion
|
|
943
1200
|
//#region src/context/sentry-provider.tsx
|
|
944
1201
|
const SentryProvider = ({ children }) => {
|
|
@@ -962,11 +1219,11 @@ function MissingModelBanner() {
|
|
|
962
1219
|
const [open, setOpen] = useState(false);
|
|
963
1220
|
if (failed.length === 0) return null;
|
|
964
1221
|
return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs("div", {
|
|
965
|
-
className: "flex items-center justify-between gap-3 bg-amber-100 px-4 py-2 text-sm text-amber-900",
|
|
1222
|
+
className: "flex items-center justify-between gap-3 bg-amber-100 px-4 py-2 text-sm text-amber-900 dark:bg-amber-800 dark:text-amber-100",
|
|
966
1223
|
children: [/* @__PURE__ */ jsx("span", { children: failed.length === 1 ? "1 document type couldn't load (missing model)." : `${failed.length} document types couldn't load (missing models).` }), /* @__PURE__ */ jsx("button", {
|
|
967
1224
|
type: "button",
|
|
968
1225
|
onClick: () => setOpen(true),
|
|
969
|
-
className: "rounded-md border border-amber-300 bg-
|
|
1226
|
+
className: "rounded-md border border-amber-300 bg-gray-50 px-3 py-1 text-amber-900 hover:bg-amber-50 dark:border-amber-600 dark:bg-slate-800 dark:text-amber-100 dark:hover:bg-amber-900",
|
|
970
1227
|
children: "View"
|
|
971
1228
|
})]
|
|
972
1229
|
}), /* @__PURE__ */ jsx(MissingModelDetailsModal, {
|
|
@@ -999,18 +1256,18 @@ function MissingModelDetailsModal(props) {
|
|
|
999
1256
|
},
|
|
1000
1257
|
contentProps: { className: "rounded-3xl" },
|
|
1001
1258
|
children: /* @__PURE__ */ jsxs("div", {
|
|
1002
|
-
className: "w-[520px] max-w-[90vw] bg-
|
|
1259
|
+
className: "w-[520px] max-w-[90vw] bg-gray-50 p-6 dark:bg-slate-800",
|
|
1003
1260
|
children: [
|
|
1004
1261
|
/* @__PURE__ */ jsx("div", {
|
|
1005
|
-
className: "border-b border-
|
|
1262
|
+
className: "border-b border-gray-100 pb-2 text-2xl font-bold text-gray-900 dark:border-slate-500 dark:bg-slate-600 dark:text-slate-100",
|
|
1006
1263
|
children: "Missing document models"
|
|
1007
1264
|
}),
|
|
1008
1265
|
/* @__PURE__ */ jsx("div", {
|
|
1009
|
-
className: "my-4 text-sm text-gray-
|
|
1266
|
+
className: "my-4 text-sm text-gray-700 dark:text-slate-200",
|
|
1010
1267
|
children: "The following document types couldn't be loaded. Documents using them won't display until the underlying package is installed."
|
|
1011
1268
|
}),
|
|
1012
1269
|
failed.length === 0 ? /* @__PURE__ */ jsx("div", {
|
|
1013
|
-
className: "rounded-xl bg-
|
|
1270
|
+
className: "rounded-xl bg-gray-50 p-4 text-sm text-gray-700 dark:bg-slate-800 dark:text-slate-200",
|
|
1014
1271
|
children: "No outstanding failures."
|
|
1015
1272
|
}) : /* @__PURE__ */ jsx("div", {
|
|
1016
1273
|
className: "flex max-h-[60vh] flex-col gap-3 overflow-y-auto",
|
|
@@ -1018,18 +1275,18 @@ function MissingModelDetailsModal(props) {
|
|
|
1018
1275
|
const isRetrying = retrying.has(entry.documentType);
|
|
1019
1276
|
const retryDisabled = !canRetry(entry.reason) || isRetrying;
|
|
1020
1277
|
return /* @__PURE__ */ jsxs("div", {
|
|
1021
|
-
className: "rounded-xl bg-
|
|
1278
|
+
className: "rounded-xl bg-gray-50 p-4 dark:bg-slate-800",
|
|
1022
1279
|
children: [
|
|
1023
1280
|
/* @__PURE__ */ jsx("div", {
|
|
1024
|
-
className: "mb-1 font-mono text-sm font-semibold text-gray-
|
|
1281
|
+
className: "mb-1 font-mono text-sm font-semibold text-gray-900 dark:text-slate-100",
|
|
1025
1282
|
children: entry.documentType
|
|
1026
1283
|
}),
|
|
1027
1284
|
/* @__PURE__ */ jsx("div", {
|
|
1028
|
-
className: "mb-2 text-xs text-gray-
|
|
1285
|
+
className: "mb-2 text-xs text-gray-700 dark:text-slate-200",
|
|
1029
1286
|
children: reasonLabels[entry.reason]
|
|
1030
1287
|
}),
|
|
1031
1288
|
entry.packageNames.length > 0 ? /* @__PURE__ */ jsxs("div", {
|
|
1032
|
-
className: "mb-2 text-xs text-gray-500",
|
|
1289
|
+
className: "mb-2 text-xs text-gray-500 dark:text-slate-400",
|
|
1033
1290
|
children: [
|
|
1034
1291
|
"Package",
|
|
1035
1292
|
entry.packageNames.length > 1 ? "s" : "",
|
|
@@ -1039,7 +1296,7 @@ function MissingModelDetailsModal(props) {
|
|
|
1039
1296
|
]
|
|
1040
1297
|
}) : null,
|
|
1041
1298
|
entry.error ? /* @__PURE__ */ jsx("div", {
|
|
1042
|
-
className: "mb-2 font-mono text-xs wrap-break-word text-red-700",
|
|
1299
|
+
className: "mb-2 font-mono text-xs wrap-break-word text-red-700 dark:text-red-100",
|
|
1043
1300
|
children: entry.error.message
|
|
1044
1301
|
}) : null,
|
|
1045
1302
|
/* @__PURE__ */ jsx("div", {
|
|
@@ -1049,7 +1306,7 @@ function MissingModelDetailsModal(props) {
|
|
|
1049
1306
|
onClick: () => void handleRetry(entry.documentType),
|
|
1050
1307
|
disabled: retryDisabled,
|
|
1051
1308
|
title: canRetry(entry.reason) ? void 0 : "No registry is configured; nothing to retry against.",
|
|
1052
|
-
className: twMerge("min-h-[32px] rounded-xl px-3 py-1 text-sm font-semibold text-white transition-all hover:scale-105", retryDisabled ? "cursor-not-allowed bg-gray-300 hover:scale-100" : "bg-gray-800 active:opacity-75"),
|
|
1309
|
+
className: twMerge("min-h-[32px] rounded-xl px-3 py-1 text-sm font-semibold text-white transition-all hover:scale-105 dark:text-slate-900", retryDisabled ? "cursor-not-allowed bg-gray-300 hover:scale-100 dark:bg-slate-600 dark:text-slate-100" : "bg-gray-800 active:opacity-75 dark:bg-slate-100"),
|
|
1053
1310
|
children: isRetrying ? "Retrying..." : "Try install again"
|
|
1054
1311
|
})
|
|
1055
1312
|
})
|
|
@@ -1062,7 +1319,7 @@ function MissingModelDetailsModal(props) {
|
|
|
1062
1319
|
children: /* @__PURE__ */ jsx("button", {
|
|
1063
1320
|
type: "button",
|
|
1064
1321
|
onClick: onClose,
|
|
1065
|
-
className: "min-h-[36px] rounded-xl border border-
|
|
1322
|
+
className: "min-h-[36px] rounded-xl border border-gray-200 bg-gray-50 px-4 py-2 text-sm font-semibold text-gray-800 hover:bg-gray-50 dark:border-slate-500 dark:bg-slate-600 dark:text-slate-100 dark:hover:bg-slate-800",
|
|
1066
1323
|
children: "Close"
|
|
1067
1324
|
})
|
|
1068
1325
|
})
|
|
@@ -1088,10 +1345,11 @@ function PackageInstallPrompt() {
|
|
|
1088
1345
|
//#endregion
|
|
1089
1346
|
//#region src/components/app.tsx
|
|
1090
1347
|
const App = () => {
|
|
1348
|
+
useTheme();
|
|
1091
1349
|
useEffect(() => {
|
|
1092
1350
|
const handlePreloadError = (event) => {
|
|
1093
1351
|
const payload = event.payload;
|
|
1094
|
-
const failedUrl = (payload instanceof Error ? payload.message :
|
|
1352
|
+
const failedUrl = (payload instanceof Error ? payload.message : typeof payload === "string" ? payload : "").match(/https?:\/\/[^\s"']+/)?.[0];
|
|
1095
1353
|
if (failedUrl && !failedUrl.startsWith(window.location.origin)) {
|
|
1096
1354
|
console.debug(`[Connect] Skipping reload — vite:preloadError for off-origin URL: ${failedUrl}`);
|
|
1097
1355
|
return;
|
|
@@ -1113,7 +1371,8 @@ const App = () => {
|
|
|
1113
1371
|
/* @__PURE__ */ jsx(MissingModelBanner, {}),
|
|
1114
1372
|
/* @__PURE__ */ jsx(Router, {}),
|
|
1115
1373
|
/* @__PURE__ */ jsx(PackageInstallPrompt, {}),
|
|
1116
|
-
/* @__PURE__ */ jsx(Analytics, {})
|
|
1374
|
+
/* @__PURE__ */ jsx(Analytics, {}),
|
|
1375
|
+
/* @__PURE__ */ jsx(OpenPanel, {})
|
|
1117
1376
|
] });
|
|
1118
1377
|
};
|
|
1119
1378
|
//#endregion
|
|
@@ -1151,8 +1410,8 @@ const CookieBanner$1 = () => {
|
|
|
1151
1410
|
if (!showBanner) return null;
|
|
1152
1411
|
return /* @__PURE__ */ jsxs("div", {
|
|
1153
1412
|
className: "absolute inset-0 z-10000 backdrop-blur-sm",
|
|
1154
|
-
children: [/* @__PURE__ */ jsx("div", { className: "absolute inset-0 bg-
|
|
1155
|
-
className: "absolute inset-x-0 bottom-0 flex justify-center bg-
|
|
1413
|
+
children: [/* @__PURE__ */ jsx("div", { className: "absolute inset-0 bg-gray-900 opacity-15 dark:bg-slate-50" }), /* @__PURE__ */ jsx("div", {
|
|
1414
|
+
className: "absolute inset-x-0 bottom-0 flex justify-center bg-gray-50 px-10 pt-10 pb-16 shadow-lg dark:bg-slate-800",
|
|
1156
1415
|
children: /* @__PURE__ */ jsx(CookieBanner, {
|
|
1157
1416
|
className: "max-w-[1024px]",
|
|
1158
1417
|
cookies: cookiesInput,
|
|
@@ -1161,12 +1420,12 @@ const CookieBanner$1 = () => {
|
|
|
1161
1420
|
submitLabel: t("cookieBanner.accept"),
|
|
1162
1421
|
rejectLabel: t("cookieBanner.reject"),
|
|
1163
1422
|
children: /* @__PURE__ */ jsx("p", {
|
|
1164
|
-
className: "font-semibold text-gray-500",
|
|
1423
|
+
className: "font-semibold text-gray-500 dark:text-slate-400",
|
|
1165
1424
|
children: /* @__PURE__ */ jsx(Trans, {
|
|
1166
1425
|
i18nKey: "cookieBanner.message",
|
|
1167
1426
|
components: { a: /* @__PURE__ */ jsx("a", {
|
|
1168
1427
|
onClick: () => showPHModal({ type: "cookiesPolicy" }),
|
|
1169
|
-
className: "cursor-pointer text-gray-900 hover:underline"
|
|
1428
|
+
className: "cursor-pointer text-gray-900 hover:underline dark:text-slate-50"
|
|
1170
1429
|
}, "cookieBanner.message-link") }
|
|
1171
1430
|
}, "cookieBanner.message")
|
|
1172
1431
|
})
|
|
@@ -1345,14 +1604,14 @@ const DocumentEditor = (props) => {
|
|
|
1345
1604
|
//#region src/components/root.tsx
|
|
1346
1605
|
function Root() {
|
|
1347
1606
|
return /* @__PURE__ */ jsx("div", {
|
|
1348
|
-
className: "h-screen",
|
|
1607
|
+
className: "h-screen bg-gray-50 dark:bg-slate-800",
|
|
1349
1608
|
children: /* @__PURE__ */ jsx("div", {
|
|
1350
1609
|
className: `flex h-screen items-stretch overflow-auto`,
|
|
1351
1610
|
role: "presentation",
|
|
1352
1611
|
tabIndex: 0,
|
|
1353
1612
|
children: /* @__PURE__ */ jsxs(Suspense, {
|
|
1354
1613
|
name: "Root",
|
|
1355
|
-
children: [/* @__PURE__ */ jsx(Sidebar, {}), /* @__PURE__ */ jsx("div", {
|
|
1614
|
+
children: [!useIsEmbedded() && /* @__PURE__ */ jsx(Sidebar, {}), /* @__PURE__ */ jsx("div", {
|
|
1356
1615
|
className: "relative flex-1 overflow-auto",
|
|
1357
1616
|
children: /* @__PURE__ */ jsx(Outlet, {})
|
|
1358
1617
|
})]
|
|
@@ -1392,10 +1651,14 @@ function DriveItem({ drive }) {
|
|
|
1392
1651
|
}
|
|
1393
1652
|
function HomeScreenContainer() {
|
|
1394
1653
|
const drives = useDrives();
|
|
1395
|
-
const
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1654
|
+
const isAddDriveEnabled = useIsAddDriveEnabled();
|
|
1655
|
+
const homeBackground = getRuntimeConfig().connect?.branding?.homeBackground;
|
|
1656
|
+
return /* @__PURE__ */ jsxs(HomeScreen, {
|
|
1657
|
+
homeBackground,
|
|
1658
|
+
children: [drives?.map((drive) => {
|
|
1659
|
+
return /* @__PURE__ */ jsx(DriveItem, { drive }, drive.header.id);
|
|
1660
|
+
}), isAddDriveEnabled && /* @__PURE__ */ jsx(HomeScreenAddDriveItem, {})]
|
|
1661
|
+
});
|
|
1399
1662
|
}
|
|
1400
1663
|
//#endregion
|
|
1401
1664
|
//#region src/components/router.tsx
|
|
@@ -1434,6 +1697,7 @@ const Router = () => {
|
|
|
1434
1697
|
function Sidebar() {
|
|
1435
1698
|
const user = useUser();
|
|
1436
1699
|
const drives = useDrives();
|
|
1700
|
+
const isAddDriveEnabled = useIsAddDriveEnabled();
|
|
1437
1701
|
const [selectedDrive] = useSelectedDriveSafe();
|
|
1438
1702
|
const connectDebug = localStorage.getItem("CONNECT_DEBUG") === "true";
|
|
1439
1703
|
const ensName = user?.ens?.name || user?.profile?.username || void 0;
|
|
@@ -1452,7 +1716,9 @@ function Sidebar() {
|
|
|
1452
1716
|
onClickSettings,
|
|
1453
1717
|
address: user?.address,
|
|
1454
1718
|
onLogin: openRenown,
|
|
1455
|
-
onDisconnect:
|
|
1719
|
+
onDisconnect: () => {
|
|
1720
|
+
logout();
|
|
1721
|
+
},
|
|
1456
1722
|
ensName: ensName || ensInfo.data?.ens,
|
|
1457
1723
|
avatarUrl: avatarUrl || ensInfo.data?.avatar_small || ensInfo.data?.avatar_url || void 0,
|
|
1458
1724
|
etherscanUrl,
|
|
@@ -1467,12 +1733,171 @@ function Sidebar() {
|
|
|
1467
1733
|
onClick: () => setSelectedDrive(drive),
|
|
1468
1734
|
active: selectedDrive?.header.id === drive.header.id,
|
|
1469
1735
|
icon: /* @__PURE__ */ jsx(DriveIcon, { drive })
|
|
1470
|
-
}, index)),
|
|
1736
|
+
}, index)), isAddDriveEnabled && /* @__PURE__ */ jsx(SidebarAddDriveItem, { onClick: onAddDriveClick })]
|
|
1471
1737
|
})
|
|
1472
1738
|
}) });
|
|
1473
1739
|
}
|
|
1474
1740
|
//#endregion
|
|
1475
|
-
|
|
1741
|
+
//#region src/components/migration-banner.tsx
|
|
1742
|
+
let dismissed = false;
|
|
1743
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
1744
|
+
function notify() {
|
|
1745
|
+
for (const l of listeners) l();
|
|
1746
|
+
}
|
|
1747
|
+
function dismiss() {
|
|
1748
|
+
dismissed = true;
|
|
1749
|
+
notify();
|
|
1750
|
+
}
|
|
1751
|
+
function subscribeDismissed(cb) {
|
|
1752
|
+
listeners.add(cb);
|
|
1753
|
+
return () => {
|
|
1754
|
+
listeners.delete(cb);
|
|
1755
|
+
};
|
|
1756
|
+
}
|
|
1757
|
+
function getDismissed() {
|
|
1758
|
+
return dismissed;
|
|
1759
|
+
}
|
|
1760
|
+
const MigrationBanner = () => {
|
|
1761
|
+
const isDismissed = useSyncExternalStore(subscribeDismissed, getDismissed, () => false);
|
|
1762
|
+
const major = useSyncExternalStore(subscribeReactorPgMajor, getCachedReactorPgMajor, () => void 0);
|
|
1763
|
+
const [migrating, setMigrating] = useState(false);
|
|
1764
|
+
const [error, setError] = useState(null);
|
|
1765
|
+
if (major === void 0 || major === null || major === 17) return null;
|
|
1766
|
+
if (isDismissed) return null;
|
|
1767
|
+
const handleMigrate = () => {
|
|
1768
|
+
setError(null);
|
|
1769
|
+
setMigrating(true);
|
|
1770
|
+
migrateAllIfNeeded().then(() => {
|
|
1771
|
+
window.location.reload();
|
|
1772
|
+
}).catch((err) => {
|
|
1773
|
+
setError(err instanceof Error ? err.message : String(err));
|
|
1774
|
+
setMigrating(false);
|
|
1775
|
+
});
|
|
1776
|
+
};
|
|
1777
|
+
return /* @__PURE__ */ jsx("div", {
|
|
1778
|
+
className: "absolute inset-x-0 top-0 z-30 flex justify-center p-3",
|
|
1779
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
1780
|
+
className: "flex max-w-3xl items-center gap-3 rounded-lg border border-yellow-500 bg-yellow-400 px-4 py-3 text-sm text-gray-900 shadow-lg dark:border-yellow-400 dark:bg-yellow-500 dark:text-slate-50",
|
|
1781
|
+
children: [
|
|
1782
|
+
/* @__PURE__ */ jsxs("div", {
|
|
1783
|
+
className: "flex-1",
|
|
1784
|
+
children: [
|
|
1785
|
+
/* @__PURE__ */ jsxs("div", {
|
|
1786
|
+
className: "font-semibold",
|
|
1787
|
+
children: [
|
|
1788
|
+
"Your local database uses Postgres ",
|
|
1789
|
+
major,
|
|
1790
|
+
"."
|
|
1791
|
+
]
|
|
1792
|
+
}),
|
|
1793
|
+
/* @__PURE__ */ jsxs("div", {
|
|
1794
|
+
className: "text-gray-900 dark:text-slate-100",
|
|
1795
|
+
children: [
|
|
1796
|
+
"Migrate to Postgres ",
|
|
1797
|
+
17,
|
|
1798
|
+
" to pick up the latest features. Your data will be backed up first."
|
|
1799
|
+
]
|
|
1800
|
+
}),
|
|
1801
|
+
error && /* @__PURE__ */ jsxs("div", {
|
|
1802
|
+
className: "mt-2 font-medium text-red-900 dark:text-red-400",
|
|
1803
|
+
children: ["Migration failed: ", error]
|
|
1804
|
+
})
|
|
1805
|
+
]
|
|
1806
|
+
}),
|
|
1807
|
+
/* @__PURE__ */ jsx("button", {
|
|
1808
|
+
type: "button",
|
|
1809
|
+
disabled: migrating,
|
|
1810
|
+
onClick: handleMigrate,
|
|
1811
|
+
className: "rounded-sm bg-gray-900 px-3 py-1 text-sm font-medium text-white hover:bg-gray-800 disabled:opacity-50 dark:bg-slate-50 dark:text-slate-900 dark:hover:bg-slate-100",
|
|
1812
|
+
children: migrating ? "Migrating…" : "Migrate now"
|
|
1813
|
+
}),
|
|
1814
|
+
/* @__PURE__ */ jsx("button", {
|
|
1815
|
+
type: "button",
|
|
1816
|
+
disabled: migrating,
|
|
1817
|
+
onClick: dismiss,
|
|
1818
|
+
className: "rounded-sm border border-gray-900 bg-transparent px-3 py-1 text-sm font-medium text-gray-900 hover:bg-gray-900/10 disabled:opacity-50 dark:border-slate-50 dark:text-slate-50",
|
|
1819
|
+
children: "Dismiss"
|
|
1820
|
+
})
|
|
1821
|
+
]
|
|
1822
|
+
})
|
|
1823
|
+
});
|
|
1824
|
+
};
|
|
1825
|
+
//#endregion
|
|
1826
|
+
//#region src/components/modal/modals-container.tsx
|
|
1827
|
+
const AddDriveModal$1 = lazy(() => import("./AddDriveModal-kzL41qdg.js").then((m) => ({ default: m.AddDriveModal })));
|
|
1828
|
+
const ClearStorageModal = lazy(() => import("./ClearStorageModal-DIKwqiia.js").then((m) => ({ default: m.ClearStorageModal })));
|
|
1829
|
+
const CookiesPolicyModal = lazy(() => import("./CookiesPolicyModal-1nOh6oN3.js").then((m) => ({ default: m.CookiesPolicyModal })));
|
|
1830
|
+
const CreateDocumentModal$1 = lazy(() => import("./CreateDocumentModal-nQbLVDq3.js").then((m) => ({ default: m.CreateDocumentModal })));
|
|
1831
|
+
const DebugSettingsModal = lazy(() => import("./DebugSettingsModal-DoY0auxt.js").then((m) => ({ default: m.DebugSettingsModal })));
|
|
1832
|
+
const DeleteDriveModal = lazy(() => import("./DeleteDriveModal-6P0T1QgD.js").then((m) => ({ default: m.DeleteDriveModal })));
|
|
1833
|
+
const DeleteItemModal = lazy(() => import("./DeleteItemModal-BmV1aQyZ.js").then((m) => ({ default: m.DeleteItemModal })));
|
|
1834
|
+
const DisclaimerModal = lazy(() => import("./DisclaimerModal-CVTFfN0_.js").then((m) => ({ default: m.DisclaimerModal })));
|
|
1835
|
+
const DriveSettingsModal$1 = lazy(() => import("./DriveSettingsModal-L5sM-rIh.js").then((m) => ({ default: m.DriveSettingsModal })));
|
|
1836
|
+
const DownloadDocumentWithErrorsModal = lazy(() => import("./DownloadDocumentWithErrorsModal-CXeFUtaz.js").then((m) => ({ default: m.DownloadDocumentWithErrorsModal })));
|
|
1837
|
+
const SettingsModal$1 = lazy(() => import("./SettingsModal-B4BiV0hg.js").then((m) => ({ default: m.SettingsModal })));
|
|
1838
|
+
const UpgradeDriveModal = lazy(() => import("./UpgradeDriveModal-CyAUDCU7.js").then((m) => ({ default: m.UpgradeDriveModal })));
|
|
1839
|
+
const modalComponents = {
|
|
1840
|
+
addDrive: AddDriveModal$1,
|
|
1841
|
+
clearStorage: ClearStorageModal,
|
|
1842
|
+
cookiesPolicy: CookiesPolicyModal,
|
|
1843
|
+
createDocument: CreateDocumentModal$1,
|
|
1844
|
+
debugSettings: DebugSettingsModal,
|
|
1845
|
+
deleteDrive: DeleteDriveModal,
|
|
1846
|
+
deleteItem: DeleteItemModal,
|
|
1847
|
+
disclaimer: DisclaimerModal,
|
|
1848
|
+
driveSettings: DriveSettingsModal$1,
|
|
1849
|
+
downloadDocumentWithErrors: DownloadDocumentWithErrorsModal,
|
|
1850
|
+
inspector: lazy(() => import("./InspectorModal-C7pIf6OO.js").then((m) => ({ default: m.InspectorModal }))),
|
|
1851
|
+
settings: SettingsModal$1,
|
|
1852
|
+
upgradeDrive: UpgradeDriveModal,
|
|
1853
|
+
missingPackage: lazy(() => import("./MissingPackageModal-D_N96M6a.js").then((m) => ({ default: m.ConnectMissingPackageModal })))
|
|
1854
|
+
};
|
|
1855
|
+
const ModalsContainer = lazy(() => {
|
|
1856
|
+
return Promise.resolve({ default: () => {
|
|
1857
|
+
const phModal = usePHModal();
|
|
1858
|
+
if (!phModal?.type) return null;
|
|
1859
|
+
const ModalComponent = modalComponents[phModal.type];
|
|
1860
|
+
return ModalComponent ? /* @__PURE__ */ jsx(ErrorBoundary$1, {
|
|
1861
|
+
variant: "silent",
|
|
1862
|
+
loggerContext: ["Connect", "Modals"],
|
|
1863
|
+
children: /* @__PURE__ */ jsx(Suspense, {
|
|
1864
|
+
fallback: null,
|
|
1865
|
+
children: /* @__PURE__ */ jsx(ModalComponent, {})
|
|
1866
|
+
})
|
|
1867
|
+
}) : null;
|
|
1868
|
+
} });
|
|
1869
|
+
});
|
|
1870
|
+
//#endregion
|
|
1871
|
+
//#region src/components/app-loader.tsx
|
|
1872
|
+
const AppLoader = (props) => {
|
|
1873
|
+
const Load = lazy(() => import("./load-Cs4KcEw0.js").then((m) => m.loadComponent(props.localPackage)));
|
|
1874
|
+
return /* @__PURE__ */ jsx(StrictMode, { children: /* @__PURE__ */ jsxs(ErrorBoundary$1, {
|
|
1875
|
+
fallbackRender: (props) => /* @__PURE__ */ jsx(AppSkeleton, { children: /* @__PURE__ */ jsx(DetailedFallback, { ...props }) }),
|
|
1876
|
+
resetKeys: [props.localPackage],
|
|
1877
|
+
loggerContext: ["Connect"],
|
|
1878
|
+
children: [
|
|
1879
|
+
/* @__PURE__ */ jsx(Suspense, {
|
|
1880
|
+
fallback: /* @__PURE__ */ jsx(AppSkeleton, {}),
|
|
1881
|
+
name: "AppLoader",
|
|
1882
|
+
children: /* @__PURE__ */ jsx(Load, {
|
|
1883
|
+
...props,
|
|
1884
|
+
children: /* @__PURE__ */ jsx(App, {})
|
|
1885
|
+
})
|
|
1886
|
+
}),
|
|
1887
|
+
/* @__PURE__ */ jsx(Suspense, {
|
|
1888
|
+
name: "CookieBanner",
|
|
1889
|
+
children: /* @__PURE__ */ jsx(CookieBanner$1, {})
|
|
1890
|
+
}),
|
|
1891
|
+
/* @__PURE__ */ jsx(Suspense, {
|
|
1892
|
+
name: "ModalsContainer",
|
|
1893
|
+
children: /* @__PURE__ */ jsx(ModalsContainer, {})
|
|
1894
|
+
}),
|
|
1895
|
+
/* @__PURE__ */ jsx(MigrationBanner, {})
|
|
1896
|
+
]
|
|
1897
|
+
}) });
|
|
1898
|
+
};
|
|
1899
|
+
//#endregion
|
|
1900
|
+
export { DocumentEditor as a, App as c, DocumentEditorContainer as d, OpenPanel as f, Root as i, AppContainer as l, AppSkeleton as m, Sidebar as n, DriveIcon as o, Analytics as p, Router as r, CookieBanner$1 as s, AppLoader as t, EditorLoader as u };
|
|
1476
1901
|
|
|
1477
|
-
//# sourceMappingURL=
|
|
1478
|
-
//# debugId=
|
|
1902
|
+
//# sourceMappingURL=app-loader-DCYDK6hq.js.map
|
|
1903
|
+
//# debugId=ecb0fae1-8b49-5b4b-b37b-86f2feb9a9b6
|