@rebasepro/admin 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.
Files changed (52) hide show
  1. package/README.md +1 -1
  2. package/dist/{CollectionEditorDialog-Dpc75wIZ.js → CollectionEditorDialog-OBI2wDyv.js} +19 -11
  3. package/dist/{CollectionEditorDialog-Dpc75wIZ.js.map → CollectionEditorDialog-OBI2wDyv.js.map} +1 -1
  4. package/dist/{PropertyEditView-DH3XZC2x.js → PropertyEditView-QaEYldcT.js} +12 -9
  5. package/dist/{PropertyEditView-DH3XZC2x.js.map → PropertyEditView-QaEYldcT.js.map} +1 -1
  6. package/dist/{RouterCollectionsStudioView-BZLq4MGp.js → RouterCollectionsStudioView-CPRuGVXJ.js} +5 -5
  7. package/dist/{RouterCollectionsStudioView-BZLq4MGp.js.map → RouterCollectionsStudioView-CPRuGVXJ.js.map} +1 -1
  8. package/dist/collection_editor_ui.js +5 -5
  9. package/dist/collection_editor_ui.js.map +1 -1
  10. package/dist/editor.js +18 -10
  11. package/dist/editor.js.map +1 -1
  12. package/dist/{export-BzIpUdSK.js → export-BZZfQkT5.js} +2 -2
  13. package/dist/{export-BzIpUdSK.js.map → export-BZZfQkT5.js.map} +1 -1
  14. package/dist/{history-g9688IaK.js → history-Ao1HBAK3.js} +2 -2
  15. package/dist/{history-g9688IaK.js.map → history-Ao1HBAK3.js.map} +1 -1
  16. package/dist/{import-BjUG-cIY.js → import-AFJRUo99.js} +2 -2
  17. package/dist/{import-BjUG-cIY.js.map → import-AFJRUo99.js.map} +1 -1
  18. package/dist/index.js +22 -15
  19. package/dist/index.js.map +1 -1
  20. package/dist/markdown-CklalUUk.js.map +1 -1
  21. package/dist/{util-B5fJm1FA.js → util-ByPlsapJ.js} +103 -61
  22. package/dist/util-ByPlsapJ.js.map +1 -0
  23. package/package.json +32 -34
  24. package/src/collection_editor/ConfigControllerProvider.tsx +1 -1
  25. package/src/collection_editor/ui/collection_editor/RouterCollectionStudioView.tsx +1 -1
  26. package/src/collection_editor/ui/collection_editor/RouterCollectionsStudioView.tsx +1 -1
  27. package/src/collection_editor/useLocalCollectionsConfigController.tsx +6 -1
  28. package/src/components/AdminModeSyncer.tsx +1 -1
  29. package/src/components/CollectionViewBinding/CollectionViewBinding.tsx +1 -1
  30. package/src/components/CollectionViewBinding/CollectionViewStartActions.tsx +1 -1
  31. package/src/components/CollectionViewBinding/SplitListView.tsx +1 -1
  32. package/src/components/DefaultAppBar.tsx +1 -1
  33. package/src/components/DefaultDrawer.tsx +1 -1
  34. package/src/components/DetailViewBinding.tsx +1 -1
  35. package/src/components/DrawerNavigationItem.tsx +1 -1
  36. package/src/components/EditViewBinding.tsx +1 -1
  37. package/src/components/HomePage/FavouritesView.tsx +1 -1
  38. package/src/components/HomePage/NavigationCardBinding.tsx +1 -1
  39. package/src/components/HomePage/SmallNavigationCard.tsx +1 -1
  40. package/src/components/RebaseLayout.tsx +1 -1
  41. package/src/components/RebaseRouteDefs.tsx +1 -1
  42. package/src/components/SidePanelBinding.tsx +1 -1
  43. package/src/components/UserSelector.tsx +6 -5
  44. package/src/components/common/default_entity_actions.tsx +4 -3
  45. package/src/components/history/LastEditedByIndicator.tsx +4 -3
  46. package/src/hooks/navigation/useBuildUrlController.tsx +1 -1
  47. package/src/hooks/useBuildSideDialogsController.tsx +2 -2
  48. package/src/hooks/useBuildSidePanel.tsx +1 -1
  49. package/src/hooks/useHistory.ts +6 -5
  50. package/src/hooks/useResolvedUsers.ts +8 -5
  51. package/src/routes/RebaseRoute.tsx +2 -2
  52. package/dist/util-B5fJm1FA.js.map +0 -1
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@rebasepro/admin",
3
3
  "type": "module",
4
- "version": "0.12.0",
4
+ "version": "0.12.1-canary.g35be8cb",
5
5
  "description": "Rebase CMS — content management views, forms, and routing",
6
6
  "funding": {
7
7
  "url": "https://github.com/sponsors/rebaseco"
@@ -18,7 +18,7 @@
18
18
  "types": "./dist/index.d.ts",
19
19
  "source": "src/index.ts",
20
20
  "engines": {
21
- "node": ">=20"
21
+ "node": ">=22.22.0"
22
22
  },
23
23
  "keywords": [
24
24
  "rebase",
@@ -54,66 +54,64 @@
54
54
  "@dnd-kit/modifiers": "^9.0.0",
55
55
  "@dnd-kit/sortable": "^10.0.0",
56
56
  "@dnd-kit/utilities": "^3.2.2",
57
- "@floating-ui/dom": "^1.7.6",
57
+ "@floating-ui/dom": "^1.8.0",
58
58
  "cmdk": "^1.1.1",
59
59
  "date-fns": "^4.4.0",
60
60
  "exceljs": "^4.4.0",
61
- "fast-equals": "6.0.0",
62
- "fractional-indexing": "3.2.0",
63
- "fuse.js": "^7.4.2",
61
+ "fast-equals": "6.0.2",
62
+ "fractional-indexing": "4.0.0",
63
+ "fuse.js": "^7.5.0",
64
64
  "json5": "^2.2.3",
65
- "markdown-it": "^14.2.0",
65
+ "markdown-it": "^14.3.0",
66
66
  "markdown-it-ins": "^4.0.0",
67
67
  "markdown-it-mark": "^4.0.0",
68
68
  "markdown-it-task-lists": "^2.1.1",
69
69
  "prism-react-renderer": "^2.4.1",
70
70
  "prosemirror-commands": "^1.7.1",
71
- "prosemirror-dropcursor": "^1.8.2",
71
+ "prosemirror-dropcursor": "^1.8.3",
72
72
  "prosemirror-gapcursor": "^1.4.1",
73
73
  "prosemirror-history": "^1.5.0",
74
74
  "prosemirror-inputrules": "^1.5.1",
75
75
  "prosemirror-keymap": "^1.2.3",
76
- "prosemirror-markdown": "^1.13.4",
77
- "prosemirror-model": "^1.25.8",
76
+ "prosemirror-markdown": "^1.13.5",
77
+ "prosemirror-model": "^1.25.11",
78
78
  "prosemirror-schema-list": "^1.5.1",
79
79
  "prosemirror-state": "^1.4.4",
80
80
  "prosemirror-tables": "^1.8.5",
81
81
  "prosemirror-transform": "^1.12.0",
82
- "prosemirror-view": "^1.41.9",
83
- "react-dropzone": "^15.0.0",
82
+ "prosemirror-view": "^1.42.2",
83
+ "react-dropzone": "^19.1.1",
84
84
  "react-use-measure": "^2.1.7",
85
85
  "zod": "^4.4.3",
86
- "@rebasepro/admin-types": "0.12.0",
87
- "@rebasepro/app": "0.12.0",
88
- "@rebasepro/common": "0.12.0",
89
- "@rebasepro/forms": "0.12.0",
90
- "@rebasepro/types": "0.12.0",
91
- "@rebasepro/inference": "0.12.0",
92
- "@rebasepro/ui": "0.12.0",
93
- "@rebasepro/utils": "0.12.0"
86
+ "@rebasepro/admin-types": "0.12.1-canary.g35be8cb",
87
+ "@rebasepro/app": "0.12.1-canary.g35be8cb",
88
+ "@rebasepro/forms": "0.12.1-canary.g35be8cb",
89
+ "@rebasepro/inference": "0.12.1-canary.g35be8cb",
90
+ "@rebasepro/types": "0.12.1-canary.g35be8cb",
91
+ "@rebasepro/ui": "0.12.1-canary.g35be8cb",
92
+ "@rebasepro/utils": "0.12.1-canary.g35be8cb",
93
+ "@rebasepro/common": "0.12.1-canary.g35be8cb"
94
94
  },
95
95
  "peerDependencies": {
96
- "react": ">=19.0.0",
97
- "react-dom": ">=19.0.0",
98
- "react-router": "^7.0.0",
99
- "react-router-dom": "^7.0.0"
96
+ "react": ">=19.2.7",
97
+ "react-dom": ">=19.2.7",
98
+ "react-router": "^8.3.0"
100
99
  },
101
100
  "devDependencies": {
102
101
  "@jest/globals": "^30.4.1",
103
102
  "@testing-library/react": "^16.3.2",
104
103
  "@types/jest": "^30.0.0",
105
104
  "@types/markdown-it": "^14.1.2",
106
- "@types/node": "^25.9.3",
105
+ "@types/node": "^26.1.2",
107
106
  "@types/react": "^19.2.17",
108
107
  "@types/react-dom": "^19.2.3",
109
108
  "@types/react-measure": "^2.0.12",
110
- "@vitejs/plugin-react": "^6.0.2",
109
+ "@vitejs/plugin-react": "^6.0.4",
111
110
  "jest": "^30.4.2",
112
- "react-router": "^7.17.0",
113
- "react-router-dom": "^7.17.0",
114
- "ts-jest": "^29.4.11",
111
+ "react-router": "^8.3.0",
112
+ "ts-jest": "^29.4.12",
115
113
  "typescript": "^6.0.3",
116
- "vite": "^8.0.16"
114
+ "vite": "^8.1.5"
117
115
  },
118
116
  "files": [
119
117
  "dist",
@@ -131,13 +129,15 @@
131
129
  },
132
130
  "jest": {
133
131
  "transform": {
134
- "^.+\\.[jt]sx?$": "ts-jest"
132
+ "^.+\\.tsx?$": "ts-jest",
133
+ "^.+\\.m?jsx?$": "<rootDir>/../../scripts/jest/react-router-esm-transform.cjs"
135
134
  },
136
135
  "testRegex": "(/__tests__/.*|(\\.|/)(test|spec))\\.tsx?$",
137
136
  "moduleFileExtensions": [
138
137
  "ts",
139
138
  "tsx",
140
139
  "js",
140
+ "mjs",
141
141
  "jsx",
142
142
  "json",
143
143
  "node"
@@ -146,9 +146,7 @@
146
146
  "testPathIgnorePatterns": [
147
147
  "/node_modules/"
148
148
  ],
149
- "transformIgnorePatterns": [
150
- "node_modules/(?!.*fractional-indexing)/"
151
- ],
149
+ "transformIgnorePatterns": [],
152
150
  "setupFilesAfterEnv": [
153
151
  "<rootDir>/test/setupTests.ts"
154
152
  ],
@@ -6,7 +6,7 @@ import { deepEqual as equal } from "fast-equals";
6
6
  import { CollectionsConfigController } from "./types/config_controller";
7
7
  import { useCustomizationController, useRebaseContext, useAuthController, useSnackbarController } from "@rebasepro/app";
8
8
  import { getTableName } from "@rebasepro/common";
9
- import { useNavigate } from "react-router-dom";
9
+ import { useNavigate } from "react-router";
10
10
  import { CollectionEditorController } from "./types/collection_editor_controller";
11
11
  import { CollectionInference } from "./types/collection_inference";
12
12
  import { CollectionGenerationCallback } from "./api/generateCollectionApi";
@@ -10,7 +10,7 @@
10
10
  * (which has no react-router dependency).
11
11
  */
12
12
  import React from "react";
13
- import { useNavigate } from "react-router-dom";
13
+ import { useNavigate } from "react-router";
14
14
  import { useUrlController } from "../../_cms_internals";
15
15
  import { useSnackbarController } from "@rebasepro/app";
16
16
  import { CollectionStudioView, CollectionStudioViewProps } from "./CollectionStudioView";
@@ -9,7 +9,7 @@
9
9
  * (which has no react-router dependency).
10
10
  */
11
11
  import React from "react";
12
- import { useLocation, useNavigate } from "react-router-dom";
12
+ import { useLocation, useNavigate } from "react-router";
13
13
  import { useUrlController } from "../../_cms_internals";
14
14
  import { CollectionsStudioView, CollectionsStudioViewProps } from "./CollectionsStudioView";
15
15
 
@@ -4,6 +4,7 @@ import { getSubcollections } from "@rebasepro/common";
4
4
 
5
5
  import React, { useMemo, useRef } from "react";
6
6
  import type { AdminCollection } from "@rebasepro/admin-types";
7
+ import { DEFAULT_API_PATH } from "@rebasepro/app";
7
8
  export function useLocalCollectionsConfigController(
8
9
  clientOrUrl: any,
9
10
  baseCollections: AdminCollection[] = [],
@@ -24,9 +25,13 @@ export function useLocalCollectionsConfigController(
24
25
  try {
25
26
  let token = optionsRef.current?.getAuthToken ? await optionsRef.current.getAuthToken() : null;
26
27
  let baseUrl = typeof clientOrUrl === "string" ? clientOrUrl : "";
28
+ // `/api` only by default — a backend configured with another
29
+ // `basePath` mounts the schema editor under that instead.
30
+ let apiPath = DEFAULT_API_PATH;
27
31
 
28
32
  if (typeof clientOrUrl === "object" && clientOrUrl !== null) {
29
33
  baseUrl = clientOrUrl.baseUrl || baseUrl;
34
+ apiPath = clientOrUrl.apiPath || apiPath;
30
35
  if (!token && clientOrUrl.resolveToken) {
31
36
  token = await clientOrUrl.resolveToken();
32
37
  }
@@ -37,7 +42,7 @@ export function useLocalCollectionsConfigController(
37
42
  headers["Authorization"] = `Bearer ${token}`;
38
43
  }
39
44
 
40
- const response = await fetch(`${baseUrl.replace(/\/$/, "")}/api/schema-editor${endpoint}`, {
45
+ const response = await fetch(`${baseUrl.replace(/\/$/, "")}${apiPath}/schema-editor${endpoint}`, {
41
46
  method: "POST",
42
47
  headers,
43
48
  body: JSON.stringify(payload)
@@ -1,6 +1,6 @@
1
1
  import type { AppView } from "@rebasepro/admin-types";
2
2
  import React, { useEffect } from "react";
3
- import { useLocation } from "react-router-dom";
3
+ import { useLocation } from "react-router";
4
4
  ;
5
5
  import { useUrlController } from "../hooks/navigation/contexts/UrlContext";
6
6
  import { useAdminModeController } from "@rebasepro/app";
@@ -13,7 +13,7 @@ import {
13
13
  ViewMode
14
14
  } from "@rebasepro/admin-types";
15
15
  import React, { useCallback, useEffect, useMemo, useState } from "react";
16
- import { useSearchParams } from "react-router-dom";
16
+ import { useSearchParams } from "react-router";
17
17
 
18
18
  import { deepEqual as equal } from "fast-equals"
19
19
  import { CollectionRowActions, CollectionTableBinding } from "../CollectionTableBinding";
@@ -9,7 +9,7 @@ import { ClearFilterSortButton } from "../ClearFilterSortButton";
9
9
  import { FiltersDialog } from "./FiltersDialog";
10
10
  import { FilterPresetsButton } from "./FilterPresetsButton";
11
11
  import { toArray } from "@rebasepro/utils";
12
- import { useNavigate } from "react-router-dom";
12
+ import { useNavigate } from "react-router";
13
13
  import { useUrlController } from "../../hooks/navigation/contexts/UrlContext";
14
14
  import { useAdminContext } from "../../hooks/useAdminContext";
15
15
  import { withViewMode } from "../../util/view_mode";
@@ -11,7 +11,7 @@ import {
11
11
  } from "@rebasepro/ui";
12
12
  import { useLargeLayout, UnsavedChangesDialog, useNavigationBlocker } from "@rebasepro/app";
13
13
  import { useCollectionRegistryController } from "../../hooks/navigation/contexts/CollectionRegistryContext";
14
- import { useNavigate, useLocation } from "react-router-dom";
14
+ import { useNavigate, useLocation } from "react-router";
15
15
  import { useUrlController } from "../../hooks/navigation/contexts/UrlContext";
16
16
  import { ErrorBoundary } from "@rebasepro/ui";
17
17
  import { withViewMode } from "../../util/view_mode";
@@ -1,7 +1,7 @@
1
1
 
2
2
  import React from "react";
3
3
 
4
- import { Link, useNavigate } from "react-router-dom";
4
+ import { Link, useNavigate } from "react-router";
5
5
  import { RebaseLogo, LanguageToggle } from "@rebasepro/app";
6
6
  import { ErrorBoundary, iconSize } from "@rebasepro/ui";
7
7
  import {
@@ -6,7 +6,7 @@ import { useUrlController } from "../hooks/navigation/contexts/UrlContext";
6
6
  import { useNavigationStateController } from "../hooks/navigation/contexts/NavigationStateContext";
7
7
 
8
8
 
9
- import { Link, useNavigate } from "react-router-dom";
9
+ import { Link, useNavigate } from "react-router";
10
10
  import { AnalyticsEvent } from "@rebasepro/admin-types";
11
11
  import {
12
12
  Avatar,
@@ -41,7 +41,7 @@ import {
41
41
  } from "@rebasepro/app";
42
42
  import { useUrlController } from "../hooks/navigation/contexts/UrlContext";
43
43
  import { useCollectionRegistryController } from "../hooks/navigation/contexts/CollectionRegistryContext";
44
- import { useNavigate } from "react-router-dom";
44
+ import { useNavigate } from "react-router";
45
45
  import { getValueInPath } from "@rebasepro/utils";
46
46
  import { getEntityTitlePropertyKeyForEntity, isUserSelectProperty, resolveTitleToString } from "../util/previews";
47
47
  import { getUserLabel, useResolvedUser } from "../hooks/useResolvedUsers";
@@ -1,6 +1,6 @@
1
1
  import React from "react";
2
2
 
3
- import { NavLink } from "react-router-dom";
3
+ import { NavLink } from "react-router";
4
4
  import { cls, Tooltip } from "@rebasepro/ui";
5
5
 
6
6
  export function DrawerNavigationItem({
@@ -48,7 +48,7 @@ const EntityHistoryView = lazy(() => import("../components/history").then(m => (
48
48
  import { createFormexStub, getEntityFromCache } from "@rebasepro/app";
49
49
  import { usePermissions } from "@rebasepro/app";
50
50
  import { useUrlController } from "../hooks/navigation/contexts/UrlContext";
51
- import { useNavigate } from "react-router-dom";
51
+ import { useNavigate } from "react-router";
52
52
 
53
53
  import { MAIN_TAB_VALUE, JSON_TAB_VALUE, HISTORY_TAB_VALUE } from "../util/view_constants";
54
54
  export { MAIN_TAB_VALUE, JSON_TAB_VALUE, HISTORY_TAB_VALUE };
@@ -1,5 +1,5 @@
1
1
  import type { NavigationEntry } from "@rebasepro/admin-types";
2
- import { useNavigate } from "react-router-dom";
2
+ import { useNavigate } from "react-router";
3
3
  ;
4
4
  import { Chip, Collapse, StarIcon } from "@rebasepro/ui";
5
5
  import { useUserConfigurationPersistence } from "@rebasepro/app";
@@ -1,6 +1,6 @@
1
1
 
2
2
  import type { NavigationEntry, AdminCollection } from "@rebasepro/admin-types";
3
- import { useNavigate } from "react-router-dom";
3
+ import { useNavigate } from "react-router";
4
4
  ;
5
5
  import { IconButton, StarIcon, Tooltip } from "@rebasepro/ui";
6
6
  import { NavigationCard } from "./NavigationCard";
@@ -1,6 +1,6 @@
1
1
  import { cardClickableMixin, cardMixin, cls, Typography } from "@rebasepro/ui";
2
2
 
3
- import { Link } from "react-router-dom";
3
+ import { Link } from "react-router";
4
4
 
5
5
  export type SmallNavigationCardProps = {
6
6
  name: string,
@@ -1,5 +1,5 @@
1
1
  import React from "react";
2
- import { Outlet } from "react-router-dom";
2
+ import { Outlet } from "react-router";
3
3
  import {
4
4
  useAdminModeController,
5
5
  useComponentOverride,
@@ -1,5 +1,5 @@
1
1
  import React, { lazy, Suspense, useMemo } from "react";
2
- import { Route } from "react-router-dom";
2
+ import { Route } from "react-router";
3
3
  import {
4
4
  useRebaseRegistry,
5
5
  RebaseRoutes,
@@ -8,7 +8,7 @@ import { IconButton, Maximize2Icon, XIcon } from "@rebasepro/ui";
8
8
  import { EditViewBinding } from "./EditViewBinding";
9
9
  import { DetailViewBinding } from "./DetailViewBinding";
10
10
  import { useSideDialogContext } from "./SideDialogs";
11
- import { useNavigate } from "react-router-dom";
11
+ import { useNavigate } from "react-router";
12
12
  import { saveEntityToMemoryCache, useComponentOverride } from "@rebasepro/app";
13
13
  import { useCollectionRegistryController } from "../hooks/navigation/contexts/CollectionRegistryContext";
14
14
  import { useSidePanel } from "../hooks/useSidePanel";
@@ -21,7 +21,7 @@ import * as React from "react";
21
21
  import { useCallback, useEffect, useRef, useState } from "react";
22
22
  import { Command as CommandPrimitive } from "cmdk";
23
23
  import { User } from "@rebasepro/types";
24
- import { useRebaseClient, useAuthController, UserDisplay } from "@rebasepro/app";
24
+ import { apiBaseOf, useRebaseClient, useAuthController, UserDisplay } from "@rebasepro/app";
25
25
  import { EmptyValue } from "../preview";
26
26
 
27
27
  interface UserSelectorItem {
@@ -37,7 +37,7 @@ const DEFAULT_PAGE_SIZE = 10;
37
37
  * Local hook to fetch users from the collection REST API with search and pagination.
38
38
  */
39
39
  function useUserSelector({ pageSize = DEFAULT_PAGE_SIZE }: { pageSize?: number } = {}) {
40
- const client = useRebaseClient<{ baseUrl?: string }>();
40
+ const client = useRebaseClient<{ baseUrl?: string, apiPath?: string }>();
41
41
  const { getAuthToken } = useAuthController();
42
42
 
43
43
  const [items, setItems] = useState<UserSelectorItem[]>([]);
@@ -48,7 +48,8 @@ function useUserSelector({ pageSize = DEFAULT_PAGE_SIZE }: { pageSize?: number }
48
48
  const userCacheRef = useRef<Map<string, User>>(new Map());
49
49
 
50
50
  const fetchUsers = useCallback(async (searchStr: string, offset: number, append: boolean) => {
51
- if (!client?.baseUrl) return;
51
+ const apiBase = apiBaseOf(client);
52
+ if (!apiBase) return;
52
53
  setIsLoading(true);
53
54
  try {
54
55
  const token = await getAuthToken?.();
@@ -57,7 +58,7 @@ function useUserSelector({ pageSize = DEFAULT_PAGE_SIZE }: { pageSize?: number }
57
58
  offset: String(offset)
58
59
  });
59
60
  if (searchStr) params.set("search", searchStr);
60
- const response = await fetch(`${client.baseUrl}/api/users?${params}`, {
61
+ const response = await fetch(`${apiBase}/users?${params}`, {
61
62
  headers: token ? { Authorization: `Bearer ${token}` } : {}
62
63
  });
63
64
  if (!response.ok) throw new Error("Failed to fetch users");
@@ -86,7 +87,7 @@ user };
86
87
  } finally {
87
88
  setIsLoading(false);
88
89
  }
89
- }, [client?.baseUrl, getAuthToken, pageSize]);
90
+ }, [client?.baseUrl, client?.apiPath, getAuthToken, pageSize]);
90
91
 
91
92
  useEffect(() => {
92
93
  offsetRef.current = 0;
@@ -21,6 +21,7 @@ import {
21
21
  import type { User } from "@rebasepro/types";
22
22
  import type { EntityAction, UserCreationResult } from "@rebasepro/admin-types";
23
23
  import {
24
+ apiBaseOf,
24
25
  useAuthController,
25
26
  useRebaseClient,
26
27
  useSnackbarController,
@@ -246,7 +247,7 @@ export function ResetPasswordActionDialog({
246
247
  open: boolean;
247
248
  onClose: () => void;
248
249
  }) {
249
- const client = useRebaseClient<{ baseUrl?: string }>();
250
+ const client = useRebaseClient<{ baseUrl?: string, apiPath?: string }>();
250
251
  const { getAuthToken } = useAuthController();
251
252
  const snackbarController = useSnackbarController();
252
253
  const { t } = useTranslation();
@@ -270,9 +271,9 @@ export function ResetPasswordActionDialog({
270
271
  setLoading(true);
271
272
  setError(null);
272
273
  try {
273
- const baseUrl = client?.baseUrl || "";
274
+ const apiBase = apiBaseOf(client) ?? "";
274
275
  const token = await getAuthToken?.();
275
- const response = await fetch(`${baseUrl}/api/admin/users/${user.uid}/reset-password`, {
276
+ const response = await fetch(`${apiBase}/admin/users/${user.uid}/reset-password`, {
276
277
  method: "POST",
277
278
  headers: {
278
279
  "Content-Type": "application/json",
@@ -1,7 +1,7 @@
1
1
 
2
2
  import React, { useEffect, useState, useCallback } from "react";
3
3
  ;
4
- import { useApiConfig } from "@rebasepro/app";
4
+ import { useApiBase, useApiConfig } from "@rebasepro/app";
5
5
  import { useAuthController } from "@rebasepro/app";
6
6
  import { HistoryEntryData } from "../../hooks";
7
7
  import type { AdminCollection } from "@rebasepro/admin-types";
@@ -35,6 +35,7 @@ export function LastEditedByIndicator({
35
35
  collection: AdminCollection;
36
36
  }) {
37
37
  const apiConfig = useApiConfig();
38
+ const apiBase = useApiBase();
38
39
  const authController = useAuthController();
39
40
  const [latestEntry, setLatestEntry] = useState<HistoryEntryData | undefined>();
40
41
 
@@ -46,7 +47,7 @@ export function LastEditedByIndicator({
46
47
  const headers: Record<string, string> = {};
47
48
  if (token) headers["Authorization"] = `Bearer ${token}`;
48
49
 
49
- const url = `${apiConfig.apiUrl}/api/data/${collection.slug}/${entityId}/history?limit=1&offset=0`;
50
+ const url = `${apiBase}/data/${collection.slug}/${entityId}/history?limit=1&offset=0`;
50
51
  const response = await fetch(url, { headers });
51
52
 
52
53
  if (response.ok) {
@@ -59,7 +60,7 @@ export function LastEditedByIndicator({
59
60
  // Silently fail — this is a non-critical UI indicator
60
61
  console.debug("Failed to fetch latest history entry:", error);
61
62
  }
62
- }, [apiConfig, entityId, collection.slug]);
63
+ }, [apiConfig, apiBase, entityId, collection.slug]);
63
64
 
64
65
  useEffect(() => {
65
66
  fetchLatest();
@@ -2,7 +2,7 @@ import type { UrlController, NavigateOptions } from "@rebasepro/admin-types";
2
2
  import { useCallback, useMemo } from "react";
3
3
  import { removeInitialAndTrailingSlashes, resolveCollectionPathIds } from "@rebasepro/app";
4
4
  import { CollectionRegistryController } from "@rebasepro/types";
5
- import { useNavigate } from "react-router-dom";
5
+ import { useNavigate } from "react-router";
6
6
 
7
7
  export function useBuildUrlController(props: {
8
8
  basePath: string,
@@ -1,9 +1,9 @@
1
1
  import type { SideDialogPanelProps, SideDialogsController } from "../hooks/useSideDialogsController";
2
2
  import { useCallback, useEffect, useRef, useState, useMemo } from "react";
3
- import { useLocation, useNavigate } from "react-router-dom";
3
+ import { useLocation, useNavigate } from "react-router";
4
4
  ;
5
5
  import { deepEqual as equal } from "fast-equals"
6
- import { Location } from "react-router-dom";
6
+ import { Location } from "react-router";
7
7
 
8
8
  interface SideDialogLocationState {
9
9
  base_location?: Location;
@@ -4,7 +4,7 @@ import type { CustomizationController, SidePanelBindingProps, SideDialogPanelPro
4
4
  import { useCallback, useEffect, useRef, useMemo } from "react";
5
5
  import { CollectionRegistryController } from "@rebasepro/types";
6
6
  import { AuthController } from "@rebasepro/admin-types";
7
- import { useLocation } from "react-router-dom";
7
+ import { useLocation } from "react-router";
8
8
  import { NavigationViewInternal } from "@rebasepro/app";
9
9
  import { getNavigationEntriesFromPath, removeInitialAndTrailingSlashes, removeTrailingSlash, resolveDefaultSelectedView } from "@rebasepro/app";
10
10
  import { resolvedSelectedEntityView } from "../util/resolutions";
@@ -1,5 +1,5 @@
1
1
  import { useCallback, useEffect, useRef, useState, useMemo } from "react";
2
- import { useApiConfig } from "@rebasepro/app";
2
+ import { useApiBase, useApiConfig } from "@rebasepro/app";
3
3
  import type { EntityHistoryEntry } from "@rebasepro/types";
4
4
 
5
5
  /**
@@ -31,6 +31,7 @@ export function useHistory(params: {
31
31
  }): UseEntityHistoryResult {
32
32
  const { slug, entityId, enabled = true, pageSize = 10 } = params;
33
33
  const apiConfig = useApiConfig();
34
+ const apiBase = useApiBase();
34
35
 
35
36
  const [entries, setEntries] = useState<HistoryEntryData[]>([]);
36
37
  const [total, setTotal] = useState(0);
@@ -59,7 +60,7 @@ export function useHistory(params: {
59
60
  };
60
61
  if (token) headers["Authorization"] = `Bearer ${token}`;
61
62
 
62
- const url = `${apiConfig.apiUrl}/api/data/${slug}/${entityId}/history?limit=${pageSize}&offset=${currentOffset}`;
63
+ const url = `${apiBase}/data/${slug}/${entityId}/history?limit=${pageSize}&offset=${currentOffset}`;
63
64
  const response = await fetch(url, { headers,
64
65
  signal });
65
66
 
@@ -90,7 +91,7 @@ signal });
90
91
  } finally {
91
92
  setIsLoading(false);
92
93
  }
93
- }, [apiConfig, slug, entityId, enabled, pageSize]);
94
+ }, [apiConfig, apiBase, slug, entityId, enabled, pageSize]);
94
95
 
95
96
  // Single unified effect: reset state when entity changes, fetch when offset changes.
96
97
  // Uses AbortController to cancel stale requests on entity change or unmount.
@@ -136,7 +137,7 @@ signal });
136
137
  };
137
138
  if (token) headers["Authorization"] = `Bearer ${token}`;
138
139
 
139
- const url = `${apiConfig.apiUrl}/api/data/${slug}/${entityId}/history/${historyId}/revert`;
140
+ const url = `${apiBase}/data/${slug}/${entityId}/history/${historyId}/revert`;
140
141
  const response = await fetch(url, { method: "POST",
141
142
  headers });
142
143
 
@@ -154,7 +155,7 @@ headers });
154
155
 
155
156
  // Return the reverted entity data so callers can update the form
156
157
  return result.data as Record<string, unknown>;
157
- }, [apiConfig, slug, entityId]);
158
+ }, [apiConfig, apiBase, slug, entityId]);
158
159
 
159
160
  return useMemo(() => ({
160
161
  entries,
@@ -1,6 +1,6 @@
1
1
  import { useEffect, useState } from "react";
2
2
  import type { User } from "@rebasepro/types";
3
- import { useAuthController, useRebaseClient } from "@rebasepro/app";
3
+ import { apiBaseOf, useAuthController, useRebaseClient } from "@rebasepro/app";
4
4
 
5
5
  /**
6
6
  * Resolves the auth users behind `userSelect` values.
@@ -31,12 +31,12 @@ queue: new Set() };
31
31
  return cache;
32
32
  }
33
33
 
34
- async function fetchUsers(baseUrl: string, ids: string[], token: string | undefined): Promise<Map<string, User | null>> {
34
+ async function fetchUsers(apiBase: string, ids: string[], token: string | undefined): Promise<Map<string, User | null>> {
35
35
  const resolved = new Map<string, User | null>();
36
36
  for (const id of ids) resolved.set(id, null);
37
37
 
38
38
  const params = new URLSearchParams({ ids: ids.join(",") });
39
- const response = await fetch(`${baseUrl}/api/users?${params}`, {
39
+ const response = await fetch(`${apiBase}/users?${params}`, {
40
40
  headers: token ? { Authorization: `Bearer ${token}` } : {}
41
41
  });
42
42
  if (!response.ok) {
@@ -103,9 +103,12 @@ function requestUser(
103
103
  * when it cannot be resolved.
104
104
  */
105
105
  export function useResolvedUser(uid: string | undefined): User | null {
106
- const client = useRebaseClient<{ baseUrl?: string }>();
106
+ const client = useRebaseClient<{ baseUrl?: string, apiPath?: string }>();
107
107
  const { getAuthToken } = useAuthController();
108
- const baseUrl = client?.baseUrl;
108
+ /* The API prefix, not the bare origin: it keys the cache and is what a
109
+ request is built from, and a backend with a non-default `basePath`
110
+ serves neither at `/api`. */
111
+ const baseUrl = apiBaseOf(client);
109
112
 
110
113
  const [user, setUser] = useState<User | null>(() =>
111
114
  (baseUrl && uid) ? getCache(baseUrl).users.get(uid) ?? null : null);
@@ -1,10 +1,10 @@
1
1
 
2
2
  import type { ViewMode, AdminCollection } from "@rebasepro/admin-types";
3
- import { useLocation } from "react-router-dom";
3
+ import { useLocation } from "react-router";
4
4
  import { EditViewBinding } from "../components/EditViewBinding";
5
5
  import { DetailViewBinding } from "../components/DetailViewBinding";
6
6
  import { useCallback, useEffect, useRef, useState } from "react";
7
- import { useNavigate } from "react-router-dom";
7
+ import { useNavigate } from "react-router";
8
8
  import { CollectionViewBinding } from "../components/CollectionViewBinding/CollectionViewBinding";
9
9
  import { NotFoundPage, useUserConfigurationPersistence, useComponentOverride, useNavigationBlocker } from "@rebasepro/app";
10
10
  import { resolveOpenEntityMode, resolveViewMode } from "../util/view_mode";