@rebasepro/app 0.12.0 → 0.12.1-canary.g35be8cb
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/README.md +1 -1
- package/dist/auth/api.d.ts +3 -1
- package/dist/hooks/ApiConfigContext.d.ts +36 -2
- package/dist/hooks/useBackendStorageSource.d.ts +6 -1
- package/dist/hooks/useNavigationBlocker.d.ts +1 -1
- package/dist/hooks/useStudioBridge.d.ts +27 -0
- package/dist/index.es.js +159 -54
- package/dist/index.es.js.map +1 -1
- package/package.json +29 -25
- package/src/auth/api.ts +8 -2
- package/src/components/Debug/UIReferenceView.tsx +8 -0
- package/src/components/NotFoundPage.tsx +1 -1
- package/src/components/common/useDataTableController.tsx +1 -1
- package/src/core/Rebase.tsx +5 -1
- package/src/core/RebaseRouter.tsx +2 -1
- package/src/core/RebaseRoutes.tsx +1 -1
- package/src/hooks/ApiConfigContext.tsx +45 -3
- package/src/hooks/useAuthSubscription.ts +29 -3
- package/src/hooks/useBackendStorageSource.ts +8 -1
- package/src/hooks/useNavigationBlocker.tsx +1 -1
- package/src/hooks/useStudioBridge.tsx +50 -2
- package/src/internal/useRestoreScroll.tsx +1 -1
package/README.md
CHANGED
|
@@ -8,7 +8,7 @@ Framework-agnostic runtime for data-driven admin panels — React hooks, provide
|
|
|
8
8
|
pnpm add @rebasepro/app
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
-
**Peer dependencies:** `react >= 19`, `react-dom >= 19
|
|
11
|
+
**Peer dependencies:** `react >= 19.2.7`, `react-dom >= 19.2.7`, `react-router ^8`
|
|
12
12
|
|
|
13
13
|
## What This Package Does
|
|
14
14
|
|
package/dist/auth/api.d.ts
CHANGED
|
@@ -59,7 +59,9 @@ export declare function createAuthConfigCache(): AuthConfigCache;
|
|
|
59
59
|
* Concurrent calls are deduplicated: only one network request is made
|
|
60
60
|
* and all callers share the same promise.
|
|
61
61
|
*/
|
|
62
|
-
export declare function fetchAuthConfig(apiUrl: string, cache: AuthConfigCache
|
|
62
|
+
export declare function fetchAuthConfig(apiUrl: string, cache: AuthConfigCache,
|
|
63
|
+
/** The backend's `basePath`; only needed if it is not the default. */
|
|
64
|
+
apiPath?: string): Promise<AuthConfigResponse>;
|
|
63
65
|
/**
|
|
64
66
|
* Clear the cached auth config (e.g. on logout or for testing).
|
|
65
67
|
*/
|
|
@@ -8,17 +8,51 @@ import React from "react";
|
|
|
8
8
|
*/
|
|
9
9
|
export interface ApiConfig {
|
|
10
10
|
apiUrl: string;
|
|
11
|
+
/**
|
|
12
|
+
* The path the backend mounts its API under, appended to {@link apiUrl}.
|
|
13
|
+
*
|
|
14
|
+
* `"/api"` by default, which is the server's default `basePath`. It is
|
|
15
|
+
* carried here because a good deal of UI builds request URLs by hand
|
|
16
|
+
* instead of going through the client's typed methods, and every one of
|
|
17
|
+
* those sites used to write `/api` as a literal — so a backend configured
|
|
18
|
+
* with any other `basePath` served an admin panel whose auth-provider
|
|
19
|
+
* discovery, storage browser, history panel, user picker and Studio tools
|
|
20
|
+
* all requested paths that did not exist.
|
|
21
|
+
*/
|
|
22
|
+
apiPath: string;
|
|
11
23
|
getAuthToken?: () => Promise<string | null>;
|
|
12
24
|
}
|
|
25
|
+
/** What the server uses when `basePath` is not configured. */
|
|
26
|
+
export declare const DEFAULT_API_PATH = "/api";
|
|
13
27
|
/**
|
|
14
28
|
* Read the API config from context. Returns `undefined` if no provider is present,
|
|
15
29
|
* allowing hooks to fall back to their own props.
|
|
16
30
|
*/
|
|
17
31
|
export declare function useApiConfig(): ApiConfig | undefined;
|
|
18
32
|
/**
|
|
19
|
-
*
|
|
33
|
+
* `apiUrl` and `apiPath` joined, with no trailing slash — the prefix to build a
|
|
34
|
+
* request URL from.
|
|
35
|
+
*
|
|
36
|
+
* Returns `undefined` when there is no provider, so a caller can keep its own
|
|
37
|
+
* fallback rather than silently requesting a relative path.
|
|
38
|
+
*/
|
|
39
|
+
export declare function useApiBase(): string | undefined;
|
|
40
|
+
/**
|
|
41
|
+
* The same prefix, derived from a client rather than from context.
|
|
42
|
+
*
|
|
43
|
+
* For the code that holds a `RebaseClient` but sits outside (or above) an
|
|
44
|
+
* `ApiConfigProvider`. Returns `undefined` when the client has no base URL,
|
|
45
|
+
* which is the signal every caller already treats as "cannot build a request".
|
|
46
|
+
*/
|
|
47
|
+
export declare function apiBaseOf(client?: {
|
|
48
|
+
baseUrl?: string;
|
|
49
|
+
apiPath?: string;
|
|
50
|
+
}): string | undefined;
|
|
51
|
+
/**
|
|
52
|
+
* Provide API configuration (apiUrl, apiPath, getAuthToken) to the entire subtree.
|
|
20
53
|
* Typically rendered inside `<Rebase>` or at the app root.
|
|
21
54
|
*/
|
|
22
|
-
export declare function ApiConfigProvider({ apiUrl, getAuthToken, children }: ApiConfig & {
|
|
55
|
+
export declare function ApiConfigProvider({ apiUrl, apiPath, getAuthToken, children }: Omit<ApiConfig, "apiPath"> & {
|
|
56
|
+
apiPath?: string;
|
|
23
57
|
children: React.ReactNode;
|
|
24
58
|
}): React.JSX.Element;
|
|
@@ -7,6 +7,11 @@ export interface BackendStorageSourceProps {
|
|
|
7
7
|
* Backend API URL (e.g., 'http://localhost:3001')
|
|
8
8
|
*/
|
|
9
9
|
apiUrl: string;
|
|
10
|
+
/**
|
|
11
|
+
* The path the backend mounts its API under. Defaults to the server's own
|
|
12
|
+
* default; pass the backend's `basePath` if it was configured otherwise.
|
|
13
|
+
*/
|
|
14
|
+
apiPath?: string;
|
|
10
15
|
/**
|
|
11
16
|
* Function to get the current auth token
|
|
12
17
|
*/
|
|
@@ -27,4 +32,4 @@ export interface BackendStorageSourceProps {
|
|
|
27
32
|
* <Rebase storageSource={storageSource} ... />
|
|
28
33
|
* ```
|
|
29
34
|
*/
|
|
30
|
-
export declare function useBackendStorageSource({ apiUrl, getAuthToken }: BackendStorageSourceProps): StorageSource;
|
|
35
|
+
export declare function useBackendStorageSource({ apiUrl, apiPath, getAuthToken }: BackendStorageSourceProps): StorageSource;
|
|
@@ -13,6 +13,31 @@ export interface StudioBridge {
|
|
|
13
13
|
urlController: UrlController;
|
|
14
14
|
navigationState: NavigationStateController;
|
|
15
15
|
breadcrumbs: BreadcrumbsController;
|
|
16
|
+
capabilities: StudioCapabilities;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* What the *host* of these tools can do, as opposed to what the backend can.
|
|
20
|
+
*
|
|
21
|
+
* Studio is mounted in two very different places. In a project's own admin
|
|
22
|
+
* panel it runs next to the collection source files and can edit them through
|
|
23
|
+
* the schema-editor routes. In the hosted console it runs against somebody
|
|
24
|
+
* else's deployed container: there is no source to edit — the container is
|
|
25
|
+
* rebuilt from the customer's repository on every deploy — and the routes that
|
|
26
|
+
* would edit it are not mounted at all, because the framework switches the
|
|
27
|
+
* schema editor off under `NODE_ENV=production`.
|
|
28
|
+
*
|
|
29
|
+
* Tools that would otherwise offer a write into the codebase read this to
|
|
30
|
+
* decide whether that write is even meaningful.
|
|
31
|
+
*/
|
|
32
|
+
export interface StudioCapabilities {
|
|
33
|
+
/**
|
|
34
|
+
* Whether the host has the project's collection source at hand and can
|
|
35
|
+
* write to it.
|
|
36
|
+
*
|
|
37
|
+
* Defaults to `true`, which is what an admin panel running beside its own
|
|
38
|
+
* `collectionsDir` has always assumed.
|
|
39
|
+
*/
|
|
40
|
+
codebase: boolean;
|
|
16
41
|
}
|
|
17
42
|
export declare const StudioBridgeContext: React.Context<StudioBridge>;
|
|
18
43
|
/**
|
|
@@ -46,6 +71,8 @@ export declare function useStudioUrlController(): UrlController;
|
|
|
46
71
|
export declare function useStudioNavigationState(): NavigationStateController;
|
|
47
72
|
/** Breadcrumbs controller — returns noop if the admin is not present. */
|
|
48
73
|
export declare function useStudioBreadcrumbs(): BreadcrumbsController;
|
|
74
|
+
/** What the host can do — see {@link StudioCapabilities}. */
|
|
75
|
+
export declare function useStudioCapabilities(): StudioCapabilities;
|
|
49
76
|
/**
|
|
50
77
|
* Registry that controllers use to self-register their implementations
|
|
51
78
|
* into the Studio bridge. Each controller calls `register(key, value)`
|
package/dist/index.es.js
CHANGED
|
@@ -5,11 +5,12 @@ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
|
5
5
|
import { SnackbarProvider as SnackbarProvider$1, useSnackbar } from "notistack";
|
|
6
6
|
import { buildRebaseData, canCreateEntity, canDeleteEntity, canEditEntity, canReadCollection, evaluateCondition, getEntityChildViews, getLabelOrConfigFrom, getPrimaryKeys, getSubcollections, isPropertyBuilder, resolveStorageFilenameString, resolveStoragePathString, resolveStorageSource, stripCollectionPath, wrapAsEntityData, wrapAsSdkData } from "@rebasepro/common";
|
|
7
7
|
import { getTitlePropertyKey as getTitlePropertyKey$1, removeInitialAndTrailingSlashes as removeInitialAndTrailingSlashes$1 } from "@rebasepro/app";
|
|
8
|
-
import { Link,
|
|
8
|
+
import { Link, Routes, createBrowserRouter, useBlocker, useLocation } from "react-router";
|
|
9
9
|
import { generateForeignKeyName, hashString, isObject, isPlainObject, mergeDeep, randomString, slugify } from "@rebasepro/utils";
|
|
10
10
|
import { I18nextProvider, initReactI18next, useTranslation as useTranslation$1 } from "react-i18next";
|
|
11
11
|
import { deepEqual } from "fast-equals";
|
|
12
12
|
import i18next from "i18next";
|
|
13
|
+
import { RouterProvider } from "react-router/dom";
|
|
13
14
|
import Fuse from "fuse.js";
|
|
14
15
|
import Compressor from "compressorjs";
|
|
15
16
|
import { resolveAdminCollection } from "@rebasepro/admin-types";
|
|
@@ -162,12 +163,15 @@ var DialogsProvider = ({ children }) => {
|
|
|
162
163
|
};
|
|
163
164
|
const close = useCallback(() => {
|
|
164
165
|
if (dialogEntries.length === 0) return;
|
|
165
|
-
|
|
166
|
+
const updatedPanels = [...dialogEntriesRef.current.slice(0, -1)];
|
|
167
|
+
updateDialogEntries(updatedPanels);
|
|
166
168
|
}, [dialogEntries]);
|
|
167
169
|
const open = useCallback((dialogEntry) => {
|
|
168
|
-
|
|
170
|
+
const updatedPanels = [...dialogEntriesRef.current, dialogEntry];
|
|
171
|
+
updateDialogEntries(updatedPanels);
|
|
169
172
|
return { closeDialog: () => {
|
|
170
|
-
|
|
173
|
+
const updatedPanels = dialogEntriesRef.current.filter((e) => e.key !== dialogEntry.key);
|
|
174
|
+
updateDialogEntries(updatedPanels);
|
|
171
175
|
} };
|
|
172
176
|
}, [dialogEntries]);
|
|
173
177
|
const dialogsController = useMemo(() => ({
|
|
@@ -908,7 +912,8 @@ function useRelationSelector({ path, collection, fixedFilter, pageSize = DEFAULT
|
|
|
908
912
|
setLoading(true);
|
|
909
913
|
const whereParams = fixedFilter && Object.keys(fixedFilter).length > 0 ? fixedFilter : void 0;
|
|
910
914
|
const onEntitiesUpdate = (res) => {
|
|
911
|
-
|
|
915
|
+
const newItems = res.data.map((e) => entityToRelationItem(e));
|
|
916
|
+
setItems(newItems);
|
|
912
917
|
setHasMore(res.meta.hasMore);
|
|
913
918
|
setLoading(false);
|
|
914
919
|
};
|
|
@@ -1201,14 +1206,38 @@ function useUnsavedChangesDialog(when, onOk) {
|
|
|
1201
1206
|
function useAuthSubscription(authClient) {
|
|
1202
1207
|
const currentSession = authClient?.getSession();
|
|
1203
1208
|
const [user, setUser] = useState(currentSession?.user ?? null);
|
|
1204
|
-
const [initialLoading, setInitialLoading] = useState(!currentSession);
|
|
1205
1209
|
const [authLoading, setAuthLoading] = useState(false);
|
|
1206
1210
|
const [authError, setAuthError] = useState();
|
|
1207
1211
|
const [loginSkipped, setLoginSkipped] = useState(false);
|
|
1208
1212
|
const [extra, setExtra] = useState();
|
|
1213
|
+
/**
|
|
1214
|
+
* Whether asking the server "who am I?" could possibly answer.
|
|
1215
|
+
*
|
|
1216
|
+
* A client configured with `persistSession: false` and JSON auth — the
|
|
1217
|
+
* shape used when one client borrows another's credential, as the hosted
|
|
1218
|
+
* Studio does — has no stored session and no auth cookie, so the probe
|
|
1219
|
+
* below is guaranteed to 401. Sending it anyway put three failing
|
|
1220
|
+
* `GET /auth/me` calls on the wire per mount, each one landing in the
|
|
1221
|
+
* *customer's* request log as an authentication failure against their own
|
|
1222
|
+
* backend.
|
|
1223
|
+
*
|
|
1224
|
+
* A client that does not implement the capability is treated as "might
|
|
1225
|
+
* work" — the historical behaviour.
|
|
1226
|
+
*/
|
|
1227
|
+
const mayHaveRestorableSession = authClient?.canRestoreSession?.() ?? true;
|
|
1228
|
+
/**
|
|
1229
|
+
* `true` only while a probe is genuinely outstanding.
|
|
1230
|
+
*
|
|
1231
|
+
* It used to be seeded from `!currentSession` alone, which left a client
|
|
1232
|
+
* that cannot restore a session — and therefore never runs the probe that
|
|
1233
|
+
* clears the flag — reporting "still loading" forever. Anything gated on
|
|
1234
|
+
* `initialLoading` (a spinner, a redirect to the login view) would never
|
|
1235
|
+
* resolve.
|
|
1236
|
+
*/
|
|
1237
|
+
const [initialLoading, setInitialLoading] = useState(!currentSession && mayHaveRestorableSession);
|
|
1209
1238
|
useEffect(() => {
|
|
1210
1239
|
if (!authClient) return;
|
|
1211
|
-
if (!currentSession) {
|
|
1240
|
+
if (!currentSession && mayHaveRestorableSession) {
|
|
1212
1241
|
setInitialLoading(true);
|
|
1213
1242
|
authClient.getUser().then((user) => {
|
|
1214
1243
|
if (user) setUser(user);
|
|
@@ -1216,7 +1245,11 @@ function useAuthSubscription(authClient) {
|
|
|
1216
1245
|
setInitialLoading(false);
|
|
1217
1246
|
});
|
|
1218
1247
|
}
|
|
1219
|
-
}, [
|
|
1248
|
+
}, [
|
|
1249
|
+
authClient,
|
|
1250
|
+
currentSession,
|
|
1251
|
+
mayHaveRestorableSession
|
|
1252
|
+
]);
|
|
1220
1253
|
useEffect(() => {
|
|
1221
1254
|
if (!authClient) return;
|
|
1222
1255
|
return authClient.onAuthStateChange((event, session) => {
|
|
@@ -1751,6 +1784,60 @@ function useRebaseRegistryDispatch() {
|
|
|
1751
1784
|
return dispatch;
|
|
1752
1785
|
}
|
|
1753
1786
|
//#endregion
|
|
1787
|
+
//#region src/hooks/ApiConfigContext.tsx
|
|
1788
|
+
/** What the server uses when `basePath` is not configured. */
|
|
1789
|
+
var DEFAULT_API_PATH = "/api";
|
|
1790
|
+
var ApiConfigContext = React.createContext(void 0);
|
|
1791
|
+
/**
|
|
1792
|
+
* Read the API config from context. Returns `undefined` if no provider is present,
|
|
1793
|
+
* allowing hooks to fall back to their own props.
|
|
1794
|
+
*/
|
|
1795
|
+
function useApiConfig() {
|
|
1796
|
+
return useContext(ApiConfigContext);
|
|
1797
|
+
}
|
|
1798
|
+
/**
|
|
1799
|
+
* `apiUrl` and `apiPath` joined, with no trailing slash — the prefix to build a
|
|
1800
|
+
* request URL from.
|
|
1801
|
+
*
|
|
1802
|
+
* Returns `undefined` when there is no provider, so a caller can keep its own
|
|
1803
|
+
* fallback rather than silently requesting a relative path.
|
|
1804
|
+
*/
|
|
1805
|
+
function useApiBase() {
|
|
1806
|
+
const config = useApiConfig();
|
|
1807
|
+
if (!config?.apiUrl) return void 0;
|
|
1808
|
+
return config.apiUrl.replace(/\/+$/, "") + (config.apiPath || "/api");
|
|
1809
|
+
}
|
|
1810
|
+
/**
|
|
1811
|
+
* The same prefix, derived from a client rather than from context.
|
|
1812
|
+
*
|
|
1813
|
+
* For the code that holds a `RebaseClient` but sits outside (or above) an
|
|
1814
|
+
* `ApiConfigProvider`. Returns `undefined` when the client has no base URL,
|
|
1815
|
+
* which is the signal every caller already treats as "cannot build a request".
|
|
1816
|
+
*/
|
|
1817
|
+
function apiBaseOf(client) {
|
|
1818
|
+
if (!client?.baseUrl) return void 0;
|
|
1819
|
+
return client.baseUrl.replace(/\/+$/, "") + (client.apiPath || "/api");
|
|
1820
|
+
}
|
|
1821
|
+
/**
|
|
1822
|
+
* Provide API configuration (apiUrl, apiPath, getAuthToken) to the entire subtree.
|
|
1823
|
+
* Typically rendered inside `<Rebase>` or at the app root.
|
|
1824
|
+
*/
|
|
1825
|
+
function ApiConfigProvider({ apiUrl, apiPath = DEFAULT_API_PATH, getAuthToken, children }) {
|
|
1826
|
+
const value = React.useMemo(() => ({
|
|
1827
|
+
apiUrl,
|
|
1828
|
+
apiPath,
|
|
1829
|
+
getAuthToken
|
|
1830
|
+
}), [
|
|
1831
|
+
apiUrl,
|
|
1832
|
+
apiPath,
|
|
1833
|
+
getAuthToken
|
|
1834
|
+
]);
|
|
1835
|
+
return /* @__PURE__ */ jsx(ApiConfigContext.Provider, {
|
|
1836
|
+
value,
|
|
1837
|
+
children
|
|
1838
|
+
});
|
|
1839
|
+
}
|
|
1840
|
+
//#endregion
|
|
1754
1841
|
//#region src/hooks/useBackendStorageSource.ts
|
|
1755
1842
|
/**
|
|
1756
1843
|
* React hook for using backend storage API as a StorageSource
|
|
@@ -1770,8 +1857,8 @@ function useRebaseRegistryDispatch() {
|
|
|
1770
1857
|
* <Rebase storageSource={storageSource} ... />
|
|
1771
1858
|
* ```
|
|
1772
1859
|
*/
|
|
1773
|
-
function useBackendStorageSource({ apiUrl, getAuthToken }) {
|
|
1774
|
-
const storageBasePath = `${apiUrl}/
|
|
1860
|
+
function useBackendStorageSource({ apiUrl, apiPath = DEFAULT_API_PATH, getAuthToken }) {
|
|
1861
|
+
const storageBasePath = `${apiUrl.replace(/\/+$/, "")}${apiPath}/storage`;
|
|
1775
1862
|
const urlsCache = useMemo(() => /* @__PURE__ */ new Map(), []);
|
|
1776
1863
|
/**
|
|
1777
1864
|
* Make an authenticated request to the storage API
|
|
@@ -1933,30 +2020,6 @@ function usePermissions() {
|
|
|
1933
2020
|
]);
|
|
1934
2021
|
}
|
|
1935
2022
|
//#endregion
|
|
1936
|
-
//#region src/hooks/ApiConfigContext.tsx
|
|
1937
|
-
var ApiConfigContext = React.createContext(void 0);
|
|
1938
|
-
/**
|
|
1939
|
-
* Read the API config from context. Returns `undefined` if no provider is present,
|
|
1940
|
-
* allowing hooks to fall back to their own props.
|
|
1941
|
-
*/
|
|
1942
|
-
function useApiConfig() {
|
|
1943
|
-
return useContext(ApiConfigContext);
|
|
1944
|
-
}
|
|
1945
|
-
/**
|
|
1946
|
-
* Provide API configuration (apiUrl, getAuthToken) to the entire subtree.
|
|
1947
|
-
* Typically rendered inside `<Rebase>` or at the app root.
|
|
1948
|
-
*/
|
|
1949
|
-
function ApiConfigProvider({ apiUrl, getAuthToken, children }) {
|
|
1950
|
-
const value = React.useMemo(() => ({
|
|
1951
|
-
apiUrl,
|
|
1952
|
-
getAuthToken
|
|
1953
|
-
}), [apiUrl, getAuthToken]);
|
|
1954
|
-
return /* @__PURE__ */ jsx(ApiConfigContext.Provider, {
|
|
1955
|
-
value,
|
|
1956
|
-
children
|
|
1957
|
-
});
|
|
1958
|
-
}
|
|
1959
|
-
//#endregion
|
|
1960
2023
|
//#region src/hooks/useTranslation.ts
|
|
1961
2024
|
var REBASE_NS$1 = "rebase_core";
|
|
1962
2025
|
/**
|
|
@@ -6318,7 +6381,7 @@ function KanbanBoardDemo() {
|
|
|
6318
6381
|
const [columns, setColumns] = useState(STATUS_COLUMNS);
|
|
6319
6382
|
const assignColumn = useCallback((item) => item.data.status, []);
|
|
6320
6383
|
const handleItemsReorder = useCallback((items, moveInfo) => {
|
|
6321
|
-
|
|
6384
|
+
const updatedItems = items.map((item) => {
|
|
6322
6385
|
if (moveInfo && item.id === moveInfo.itemId && moveInfo.sourceColumn !== moveInfo.targetColumn) return {
|
|
6323
6386
|
...item,
|
|
6324
6387
|
data: {
|
|
@@ -6328,7 +6391,8 @@ function KanbanBoardDemo() {
|
|
|
6328
6391
|
}
|
|
6329
6392
|
};
|
|
6330
6393
|
return item;
|
|
6331
|
-
})
|
|
6394
|
+
});
|
|
6395
|
+
setBoardData(updatedItems);
|
|
6332
6396
|
}, []);
|
|
6333
6397
|
const handleColumnReorder = useCallback((reordered) => setColumns(reordered), []);
|
|
6334
6398
|
const columnLoadingState = useMemo(() => {
|
|
@@ -7563,6 +7627,22 @@ function UIReferenceView() {
|
|
|
7563
7627
|
disabled: true,
|
|
7564
7628
|
value: "Read only",
|
|
7565
7629
|
onChange: () => {}
|
|
7630
|
+
}),
|
|
7631
|
+
/* @__PURE__ */ jsx(TextField, {
|
|
7632
|
+
size: "medium",
|
|
7633
|
+
label: "Medium",
|
|
7634
|
+
placeholder: "Placeholder under the label"
|
|
7635
|
+
}),
|
|
7636
|
+
/* @__PURE__ */ jsx(TextField, {
|
|
7637
|
+
size: "small",
|
|
7638
|
+
label: "Small",
|
|
7639
|
+
placeholder: "Placeholder under the label"
|
|
7640
|
+
}),
|
|
7641
|
+
/* @__PURE__ */ jsx(TextField, {
|
|
7642
|
+
size: "smallest",
|
|
7643
|
+
label: "Smallest",
|
|
7644
|
+
value: "Filled value",
|
|
7645
|
+
onChange: () => {}
|
|
7566
7646
|
})
|
|
7567
7647
|
]
|
|
7568
7648
|
})]
|
|
@@ -8336,8 +8416,10 @@ function UserSettingsView() {
|
|
|
8336
8416
|
setLoadingSessions(true);
|
|
8337
8417
|
setSessionsError(null);
|
|
8338
8418
|
try {
|
|
8339
|
-
if (authController.fetchSessions)
|
|
8340
|
-
|
|
8419
|
+
if (authController.fetchSessions) {
|
|
8420
|
+
const sortedSessions = (await authController.fetchSessions() || []).sort((a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime());
|
|
8421
|
+
setSessions(sortedSessions);
|
|
8422
|
+
} else throw new Error("fetchSessions not implemented in this auth controller.");
|
|
8341
8423
|
} catch (e) {
|
|
8342
8424
|
setSessionsError(e instanceof Error ? e.message : String(e));
|
|
8343
8425
|
} finally {
|
|
@@ -15852,6 +15934,7 @@ function Rebase(props) {
|
|
|
15852
15934
|
const resolvedApiUrl = apiUrl || client?.baseUrl || (typeof window !== "undefined" ? window.location.origin : "");
|
|
15853
15935
|
if (resolvedApiUrl) return /* @__PURE__ */ jsx(ApiConfigProvider, {
|
|
15854
15936
|
apiUrl: resolvedApiUrl,
|
|
15937
|
+
apiPath: client?.apiPath,
|
|
15855
15938
|
getAuthToken: authController.getAuthToken,
|
|
15856
15939
|
children: content
|
|
15857
15940
|
});
|
|
@@ -15998,7 +16081,8 @@ function useRebaseAuthController(props = {}) {
|
|
|
15998
16081
|
try {
|
|
15999
16082
|
await auth.signOut();
|
|
16000
16083
|
} catch (error) {
|
|
16001
|
-
|
|
16084
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
16085
|
+
setAuthProviderError(err);
|
|
16002
16086
|
} finally {
|
|
16003
16087
|
setAuthLoading(false);
|
|
16004
16088
|
}
|
|
@@ -16010,7 +16094,8 @@ function useRebaseAuthController(props = {}) {
|
|
|
16010
16094
|
try {
|
|
16011
16095
|
await auth.signInWithEmail(email, password);
|
|
16012
16096
|
} catch (error) {
|
|
16013
|
-
|
|
16097
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
16098
|
+
setAuthProviderError(err);
|
|
16014
16099
|
throw error;
|
|
16015
16100
|
} finally {
|
|
16016
16101
|
setAuthLoading(false);
|
|
@@ -16023,7 +16108,8 @@ function useRebaseAuthController(props = {}) {
|
|
|
16023
16108
|
try {
|
|
16024
16109
|
await auth.signUp(email, password, displayName);
|
|
16025
16110
|
} catch (error) {
|
|
16026
|
-
|
|
16111
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
16112
|
+
setAuthProviderError(err);
|
|
16027
16113
|
throw error;
|
|
16028
16114
|
} finally {
|
|
16029
16115
|
setAuthLoading(false);
|
|
@@ -16036,7 +16122,8 @@ function useRebaseAuthController(props = {}) {
|
|
|
16036
16122
|
try {
|
|
16037
16123
|
await auth.signInWithGoogle(payload);
|
|
16038
16124
|
} catch (error) {
|
|
16039
|
-
|
|
16125
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
16126
|
+
setAuthProviderError(err);
|
|
16040
16127
|
throw error;
|
|
16041
16128
|
} finally {
|
|
16042
16129
|
setAuthLoading(false);
|
|
@@ -16049,7 +16136,8 @@ function useRebaseAuthController(props = {}) {
|
|
|
16049
16136
|
try {
|
|
16050
16137
|
await auth.signInWithOAuth(providerId, payload);
|
|
16051
16138
|
} catch (error) {
|
|
16052
|
-
|
|
16139
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
16140
|
+
setAuthProviderError(err);
|
|
16053
16141
|
throw error;
|
|
16054
16142
|
} finally {
|
|
16055
16143
|
setAuthLoading(false);
|
|
@@ -16066,7 +16154,8 @@ function useRebaseAuthController(props = {}) {
|
|
|
16066
16154
|
try {
|
|
16067
16155
|
await auth.resetPasswordForEmail(email);
|
|
16068
16156
|
} catch (error) {
|
|
16069
|
-
|
|
16157
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
16158
|
+
setAuthProviderError(err);
|
|
16070
16159
|
throw error;
|
|
16071
16160
|
} finally {
|
|
16072
16161
|
setAuthLoading(false);
|
|
@@ -16079,7 +16168,8 @@ function useRebaseAuthController(props = {}) {
|
|
|
16079
16168
|
try {
|
|
16080
16169
|
await auth.resetPassword(token, password);
|
|
16081
16170
|
} catch (error) {
|
|
16082
|
-
|
|
16171
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
16172
|
+
setAuthProviderError(err);
|
|
16083
16173
|
throw error;
|
|
16084
16174
|
} finally {
|
|
16085
16175
|
setAuthLoading(false);
|
|
@@ -16093,7 +16183,8 @@ function useRebaseAuthController(props = {}) {
|
|
|
16093
16183
|
await auth.changePassword(oldPassword, newPassword);
|
|
16094
16184
|
await auth.signOut();
|
|
16095
16185
|
} catch (error) {
|
|
16096
|
-
|
|
16186
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
16187
|
+
setAuthProviderError(err);
|
|
16097
16188
|
throw error;
|
|
16098
16189
|
} finally {
|
|
16099
16190
|
setAuthLoading(false);
|
|
@@ -16109,7 +16200,8 @@ function useRebaseAuthController(props = {}) {
|
|
|
16109
16200
|
photoURL
|
|
16110
16201
|
});
|
|
16111
16202
|
} catch (error) {
|
|
16112
|
-
|
|
16203
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
16204
|
+
setAuthProviderError(err);
|
|
16113
16205
|
throw error;
|
|
16114
16206
|
} finally {
|
|
16115
16207
|
setAuthLoading(false);
|
|
@@ -16238,11 +16330,11 @@ function createAuthConfigCache() {
|
|
|
16238
16330
|
* Concurrent calls are deduplicated: only one network request is made
|
|
16239
16331
|
* and all callers share the same promise.
|
|
16240
16332
|
*/
|
|
16241
|
-
async function fetchAuthConfig(apiUrl, cache) {
|
|
16333
|
+
async function fetchAuthConfig(apiUrl, cache, apiPath = DEFAULT_API_PATH) {
|
|
16242
16334
|
if (cache.cached) return cache.cached;
|
|
16243
16335
|
if (cache.inflight) return cache.inflight;
|
|
16244
16336
|
cache.inflight = (async () => {
|
|
16245
|
-
return handleResponse(await fetchWithHandling(`${apiUrl}/
|
|
16337
|
+
return handleResponse(await fetchWithHandling(`${apiUrl.replace(/\/+$/, "")}${apiPath}/auth/config`, {
|
|
16246
16338
|
method: "GET",
|
|
16247
16339
|
headers: { "Content-Type": "application/json" }
|
|
16248
16340
|
}));
|
|
@@ -16660,7 +16752,8 @@ function useStorageUploadController({ entityId, entityValues, path, value, prope
|
|
|
16660
16752
|
]),
|
|
16661
16753
|
onFileUploadError: useCallback((entry) => {
|
|
16662
16754
|
console.debug("onFileUploadError", entry);
|
|
16663
|
-
|
|
16755
|
+
const newValue = internalValue.filter((item) => item.id !== entry.id);
|
|
16756
|
+
setInternalValue(newValue);
|
|
16664
16757
|
}, [internalValue]),
|
|
16665
16758
|
onFilesAdded: useCallback(async (acceptedFiles) => {
|
|
16666
16759
|
if (!acceptedFiles.length || disabled) return;
|
|
@@ -16935,7 +17028,8 @@ var NOOP_BRIDGE = {
|
|
|
16935
17028
|
breadcrumbs: [],
|
|
16936
17029
|
set: () => {},
|
|
16937
17030
|
updateCount: () => {}
|
|
16938
|
-
}
|
|
17031
|
+
},
|
|
17032
|
+
capabilities: { codebase: true }
|
|
16939
17033
|
};
|
|
16940
17034
|
var StudioBridgeContext = createContext(NOOP_BRIDGE);
|
|
16941
17035
|
/**
|
|
@@ -16959,7 +17053,14 @@ function StudioBridgeProvider({ value, children }) {
|
|
|
16959
17053
|
const merged = React.useMemo(() => ({
|
|
16960
17054
|
...NOOP_BRIDGE,
|
|
16961
17055
|
...value
|
|
16962
|
-
}), [
|
|
17056
|
+
}), [
|
|
17057
|
+
value.collectionRegistry,
|
|
17058
|
+
value.sidePanelController,
|
|
17059
|
+
value.urlController,
|
|
17060
|
+
value.navigationState,
|
|
17061
|
+
value.breadcrumbs,
|
|
17062
|
+
value.capabilities
|
|
17063
|
+
]);
|
|
16963
17064
|
return /* @__PURE__ */ jsx(StudioBridgeContext.Provider, {
|
|
16964
17065
|
value: merged,
|
|
16965
17066
|
children
|
|
@@ -16985,6 +17086,10 @@ function useStudioNavigationState() {
|
|
|
16985
17086
|
function useStudioBreadcrumbs() {
|
|
16986
17087
|
return useContext(StudioBridgeContext).breadcrumbs;
|
|
16987
17088
|
}
|
|
17089
|
+
/** What the host can do — see {@link StudioCapabilities}. */
|
|
17090
|
+
function useStudioCapabilities() {
|
|
17091
|
+
return useContext(StudioBridgeContext).capabilities;
|
|
17092
|
+
}
|
|
16988
17093
|
var StudioBridgeRegistryContext = createContext(null);
|
|
16989
17094
|
/**
|
|
16990
17095
|
* Provider that creates a self-assembling bridge.
|
|
@@ -17600,7 +17705,7 @@ var SCORE = {
|
|
|
17600
17705
|
* This is a *bonus* on top of the structural rules — never a requirement, and
|
|
17601
17706
|
* never the mechanism that keeps identifiers out of the title slot.
|
|
17602
17707
|
*/
|
|
17603
|
-
var TITLE_LIKE_KEYS = new Set([
|
|
17708
|
+
var TITLE_LIKE_KEYS = /* @__PURE__ */ new Set([
|
|
17604
17709
|
"name",
|
|
17605
17710
|
"fullname",
|
|
17606
17711
|
"displayname",
|
|
@@ -17779,6 +17884,6 @@ function getTitlePropertyKeyForValues(collection, values, entityId) {
|
|
|
17779
17884
|
return candidates[0];
|
|
17780
17885
|
}
|
|
17781
17886
|
//#endregion
|
|
17782
|
-
export { ADDITIONAL_TAB_WIDTH, AIIcon, AIModifiedIndicator, AdminModeControllerContext, AdminModeControllerProvider, AnalyticsContext, ApiConfigProvider, AuthApiError, AuthControllerContext, CONTAINER_FULL_WIDTH, CollectionComponentOverrideProvider, CollectionResolverRegistrationContext, CollectionScopeContext, CollectionScopeProvider, ComponentOverrideContext, ConfirmationDialog, CrmDashboardDemo, CustomizationControllerContext, DEFAULT_PAGE_SIZE, DataDriverContext, DataSourcesContext, DialogsControllerContext, DialogsProvider, EffectiveRoleControllerContext, EffectiveRoleControllerProvider, ErrorTooltip, ErrorView, FORM_CONTAINER_WIDTH, GlobalComponentOverrideProvider, IconForView, LanguageToggle, LoginView, ModeControllerContext, ModeControllerProvider, NavigationBlockerProvider, NotFoundPage, PluginProviderStack, REBASE_LOCALE_STORAGE_KEY, Rebase, RebaseAuth, RebaseClientInstanceContext, RebaseDataContext, RebaseI18nProvider, RebaseLogo, RebaseRegistryProvider, RebaseRouter, RebaseRoutes, STUDIO_NAVIGATION_GROUPS, SchemaDriftBanner, SchemaDriftProvider, SnackbarProvider, StorageSourceContext, StorageSourcesContext, StudioBridgeContext, StudioBridgeProvider, StudioBridgeRegistryContext, StudioBridgeRegistryProvider, UIReferenceView, UIStyleGuide, UnsavedChangesDialog, UserConfigurationPersistenceContext, UserDisplay, UserSelectPopover, UserSettingsView, addInitialSlash, applyPropertyConditions, buildCollapsedDefaults, buildEnumLabel, clearAuthConfigCache, clearFetchCache, createAuthConfigCache, createFormexStub, deleteEntityWithCallbacks, en, es, fetchAuthConfig, flattenKeys, getAdminEntityChildViews, getAdminSubcollections, getCollectionBySlugWithin, getCollectionPathsCombinations, getColorScheme, getColumnKeysForProperty, getEntityFromCache, getEntityFromMemoryCache, getEntityImagePreviewPropertyKey, getEntityPreviewKeys, getEntityTitlePropertyKey, getFormFieldKeys, getIcon, getLastSegment, getLocalChangesBackup, getNavigationEntriesFromPath, getParentReferencesFromPath, getRelationIncludeParams, getRowHeight, getSubcollectionColumnId, getTitlePropertyCandidates, getTitlePropertyKey, getTitlePropertyKeyForValues, iconsSearch, isEnumValueDisabled, isFilterableRelation, isHidden, isReadOnly, isSchemaDriftError, looksLikeIdentifierValue, populateFetchCache, removeEntityFromCache, removeEntityFromMemoryCache, removeInitialAndTrailingSlashes, removeInitialSlash, removeTrailingSlash, resolveCollectionPathIds, resolveComponentRef, resolveDefaultSelectedView, resolveFilterOperators, saveEntityToCache, saveEntityToMemoryCache, saveEntityWithCallbacks, useAdminModeController, useAnalyticsController, useApiConfig, useAuthController, useAuthSubscription, useBackendStorageSource, useBridgeRegistration, useBrowserTitleAndIcon, useBuildAdminModeController, useBuildEffectiveRoleController, useBuildLocalConfigurationPersistence, useBuildModeController, useClipboard, useCollapsedGroups, useCollection, useCollectionScope, useColumnIds, useComponentOverride, useCustomizationController, useData, useDataSources, useDataTableController, useDebouncedData, useDialogsController, useEffectiveRoleController, useFetch, useLargeLayout, useModeController, useNavigationBlocker, usePermissions, useRebaseAuthController, useRebaseClient, useRebaseContext, useRebaseRegistry, useRebaseRegistryDispatch, useRelationSelector, useResolvedComponent, useRestoreScroll, useSchemaDriftContext, useScrollRestoration, useSlot, useSnackbarController, useStorageSource, useStorageSources, useStorageUploadController, useStudioBreadcrumbs, useStudioCollectionRegistry, useStudioNavigationState, useStudioSidePanelController, useStudioUrlController, useTranslation, useUnsavedChangesDialog, useUserConfigurationPersistence };
|
|
17887
|
+
export { ADDITIONAL_TAB_WIDTH, AIIcon, AIModifiedIndicator, AdminModeControllerContext, AdminModeControllerProvider, AnalyticsContext, ApiConfigProvider, AuthApiError, AuthControllerContext, CONTAINER_FULL_WIDTH, CollectionComponentOverrideProvider, CollectionResolverRegistrationContext, CollectionScopeContext, CollectionScopeProvider, ComponentOverrideContext, ConfirmationDialog, CrmDashboardDemo, CustomizationControllerContext, DEFAULT_API_PATH, DEFAULT_PAGE_SIZE, DataDriverContext, DataSourcesContext, DialogsControllerContext, DialogsProvider, EffectiveRoleControllerContext, EffectiveRoleControllerProvider, ErrorTooltip, ErrorView, FORM_CONTAINER_WIDTH, GlobalComponentOverrideProvider, IconForView, LanguageToggle, LoginView, ModeControllerContext, ModeControllerProvider, NavigationBlockerProvider, NotFoundPage, PluginProviderStack, REBASE_LOCALE_STORAGE_KEY, Rebase, RebaseAuth, RebaseClientInstanceContext, RebaseDataContext, RebaseI18nProvider, RebaseLogo, RebaseRegistryProvider, RebaseRouter, RebaseRoutes, STUDIO_NAVIGATION_GROUPS, SchemaDriftBanner, SchemaDriftProvider, SnackbarProvider, StorageSourceContext, StorageSourcesContext, StudioBridgeContext, StudioBridgeProvider, StudioBridgeRegistryContext, StudioBridgeRegistryProvider, UIReferenceView, UIStyleGuide, UnsavedChangesDialog, UserConfigurationPersistenceContext, UserDisplay, UserSelectPopover, UserSettingsView, addInitialSlash, apiBaseOf, applyPropertyConditions, buildCollapsedDefaults, buildEnumLabel, clearAuthConfigCache, clearFetchCache, createAuthConfigCache, createFormexStub, deleteEntityWithCallbacks, en, es, fetchAuthConfig, flattenKeys, getAdminEntityChildViews, getAdminSubcollections, getCollectionBySlugWithin, getCollectionPathsCombinations, getColorScheme, getColumnKeysForProperty, getEntityFromCache, getEntityFromMemoryCache, getEntityImagePreviewPropertyKey, getEntityPreviewKeys, getEntityTitlePropertyKey, getFormFieldKeys, getIcon, getLastSegment, getLocalChangesBackup, getNavigationEntriesFromPath, getParentReferencesFromPath, getRelationIncludeParams, getRowHeight, getSubcollectionColumnId, getTitlePropertyCandidates, getTitlePropertyKey, getTitlePropertyKeyForValues, iconsSearch, isEnumValueDisabled, isFilterableRelation, isHidden, isReadOnly, isSchemaDriftError, looksLikeIdentifierValue, populateFetchCache, removeEntityFromCache, removeEntityFromMemoryCache, removeInitialAndTrailingSlashes, removeInitialSlash, removeTrailingSlash, resolveCollectionPathIds, resolveComponentRef, resolveDefaultSelectedView, resolveFilterOperators, saveEntityToCache, saveEntityToMemoryCache, saveEntityWithCallbacks, useAdminModeController, useAnalyticsController, useApiBase, useApiConfig, useAuthController, useAuthSubscription, useBackendStorageSource, useBridgeRegistration, useBrowserTitleAndIcon, useBuildAdminModeController, useBuildEffectiveRoleController, useBuildLocalConfigurationPersistence, useBuildModeController, useClipboard, useCollapsedGroups, useCollection, useCollectionScope, useColumnIds, useComponentOverride, useCustomizationController, useData, useDataSources, useDataTableController, useDebouncedData, useDialogsController, useEffectiveRoleController, useFetch, useLargeLayout, useModeController, useNavigationBlocker, usePermissions, useRebaseAuthController, useRebaseClient, useRebaseContext, useRebaseRegistry, useRebaseRegistryDispatch, useRelationSelector, useResolvedComponent, useRestoreScroll, useSchemaDriftContext, useScrollRestoration, useSlot, useSnackbarController, useStorageSource, useStorageSources, useStorageUploadController, useStudioBreadcrumbs, useStudioCapabilities, useStudioCollectionRegistry, useStudioNavigationState, useStudioSidePanelController, useStudioUrlController, useTranslation, useUnsavedChangesDialog, useUserConfigurationPersistence };
|
|
17783
17888
|
|
|
17784
17889
|
//# sourceMappingURL=index.es.js.map
|