@rebasepro/app 0.12.0 → 0.12.1-canary.g009ed95

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 (49) hide show
  1. package/README.md +1 -1
  2. package/dist/auth/api.d.ts +3 -8
  3. package/dist/auth/index.d.ts +2 -2
  4. package/dist/auth/types.d.ts +1 -5
  5. package/dist/collections/form-layout.d.ts +107 -0
  6. package/dist/collections/index.d.ts +1 -0
  7. package/dist/collections/title-property.d.ts +22 -0
  8. package/dist/components/Debug/collection-views/sample_data.d.ts +3 -2
  9. package/dist/hooks/ApiConfigContext.d.ts +36 -2
  10. package/dist/hooks/useBackendStorageSource.d.ts +6 -1
  11. package/dist/hooks/useNavigationBlocker.d.ts +1 -1
  12. package/dist/hooks/useSnackbarController.d.ts +2 -1
  13. package/dist/hooks/useStudioBridge.d.ts +27 -0
  14. package/dist/index.d.ts +1 -1
  15. package/dist/index.es.js +667 -186
  16. package/dist/index.es.js.map +1 -1
  17. package/dist/internal/common.d.ts +14 -2
  18. package/package.json +29 -25
  19. package/src/auth/api.ts +8 -9
  20. package/src/auth/index.ts +2 -2
  21. package/src/auth/types.ts +5 -6
  22. package/src/collections/form-layout.ts +386 -0
  23. package/src/collections/index.ts +1 -0
  24. package/src/collections/title-property.ts +41 -0
  25. package/src/components/Debug/UIReferenceView.tsx +9 -1
  26. package/src/components/Debug/collection-views/sample_data.ts +4 -2
  27. package/src/components/NotFoundPage.tsx +1 -1
  28. package/src/components/common/useDataTableController.tsx +1 -1
  29. package/src/core/Rebase.tsx +5 -1
  30. package/src/core/RebaseRouter.tsx +2 -1
  31. package/src/core/RebaseRoutes.tsx +1 -1
  32. package/src/hooks/ApiConfigContext.tsx +45 -3
  33. package/src/hooks/useAuthSubscription.ts +29 -3
  34. package/src/hooks/useBackendStorageSource.ts +8 -1
  35. package/src/hooks/useNavigationBlocker.tsx +1 -1
  36. package/src/hooks/useSnackbarController.tsx +34 -6
  37. package/src/hooks/useStudioBridge.tsx +50 -2
  38. package/src/index.ts +1 -1
  39. package/src/internal/common.tsx +15 -3
  40. package/src/internal/useRestoreScroll.tsx +1 -1
  41. package/src/locales/de.ts +21 -2
  42. package/src/locales/en.ts +21 -1
  43. package/src/locales/es.ts +21 -1
  44. package/src/locales/fr.ts +21 -1
  45. package/src/locales/hi.ts +21 -1
  46. package/src/locales/it.ts +21 -1
  47. package/src/locales/pt.ts +21 -1
  48. package/src/util/enums.ts +4 -2
  49. package/src/util/useStorageUploadController.tsx +5 -1
package/dist/index.es.js CHANGED
@@ -1,15 +1,16 @@
1
1
  import React, { createContext, lazy, useCallback, useContext, useEffect, useId, useLayoutEffect, useMemo, useRef, useState } from "react";
2
- import { Alert, AlertCircleIcon, AlertTriangleIcon, AppWindow, ArrowDownIcon, ArrowLeftIcon, ArrowRightLeftIcon, ArrowUpDownIcon, ArrowUpIcon, Avatar, BooleanSwitch, Button, CHIP_COLORS, CalendarIcon, Card, CenteredView, CheckCircle2Icon, CheckIcon, Checkbox, ChevronDownIcon, ChevronLeftIcon, ChevronRightIcon, ChevronsLeftIcon, ChevronsRightIcon, Chip, CircleDotIcon, CircleUserIcon, CircularProgress, ColumnsIcon, Container, Dialog, DialogActions, DialogContent, DialogTitle, DollarSignIcon, ErrorBoundary, FileIcon, FileTextIcon, FilterChip, FilterIcon, FolderIcon, FolderKanbanIcon, IconButton, KanbanIcon, KanbanView, LanguagesIcon, LayoutGridIcon, ListIcon, ListPlusIcon, ListTodoIcon, LoadingButton, LogOutIcon, MailIcon, Menu, MenuItem, MessageCircleIcon, MoonIcon, MultiSelect, MultiSelectItem, PanelLeftIcon, Paper, PenLineIcon, PencilIcon, PhoneIcon, PinIcon, PlusIcon, Popover, RefreshCwIcon, SearchBar, Select, SelectItem, Separator, SettingsIcon, Skeleton, StickyNoteIcon, SunIcon, SunMoonIcon, Tab, Table, TableBody, TableCell, TableHeader, TableRow, Tabs, TagIcon, TextField, ToggleButtonGroup, Tooltip, Trash2Icon, TrendingUpIcon, TypeIcon, Typography, UserIcon, UserPlus, UsersIcon, VideoIcon, Wand2Icon, WrenchIcon, XIcon, cls, colorClassesMapping, coolIconKeys, defaultBorderMixin, getColorSchemeForSeed, iconKeys, iconSize, lucideIcons } from "@rebasepro/ui";
2
+ import { Alert, AlertCircleIcon, AlertTriangleIcon, AppWindow, ArrowDownIcon, ArrowLeftIcon, ArrowRightLeftIcon, ArrowUpDownIcon, ArrowUpIcon, Avatar, BooleanSwitch, Button, CalendarIcon, Card, CenteredView, CheckCircle2Icon, CheckIcon, Checkbox, ChevronDownIcon, ChevronLeftIcon, ChevronRightIcon, ChevronsLeftIcon, ChevronsRightIcon, Chip, CircleDotIcon, CircleUserIcon, CircularProgress, ColumnsIcon, Container, Dialog, DialogActions, DialogContent, DialogTitle, DollarSignIcon, ErrorBoundary, FileIcon, FileTextIcon, FilterChip, FilterIcon, FolderIcon, FolderKanbanIcon, IconButton, KanbanIcon, KanbanView, LanguagesIcon, LayoutGridIcon, ListIcon, ListPlusIcon, ListTodoIcon, LoadingButton, LogOutIcon, MailIcon, Menu, MenuItem, MessageCircleIcon, MoonIcon, MultiSelect, MultiSelectItem, PanelLeftIcon, Paper, PenLineIcon, PencilIcon, PhoneIcon, PinIcon, PlusIcon, Popover, RefreshCwIcon, SearchBar, Select, SelectItem, Separator, SettingsIcon, Skeleton, StickyNoteIcon, SunIcon, SunMoonIcon, Tab, Table, TableBody, TableCell, TableHeader, TableRow, Tabs, TagIcon, TextField, ToggleButtonGroup, Tooltip, Trash2Icon, TrendingUpIcon, TypeIcon, Typography, UserIcon, UserPlus, UsersIcon, VideoIcon, Wand2Icon, WrenchIcon, XIcon, cls, colorClassesMapping, coolIconKeys, defaultBorderMixin, getColorSchemeForKey, getColorSchemeForSeed, iconKeys, iconSize, lucideIcons } from "@rebasepro/ui";
3
3
  import { ALL_WHERE_FILTER_OPS, DEFAULT_DATA_SOURCE_KEY, DEFAULT_FILTERABLE_RELATION_KINDS, DEFAULT_STORAGE_SOURCE_KEY, EntityReference, EntityRelation, GeoPoint, RebaseApiError, Vector, getDataSourceCapabilities, isLazyComponentRef, isRelationalCollectionConfig } from "@rebasepro/types";
4
4
  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, RouterProvider, Routes, createBrowserRouter, useBlocker, useLocation } from "react-router-dom";
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
- updateDialogEntries([...dialogEntriesRef.current.slice(0, -1)]);
166
+ const updatedPanels = [...dialogEntriesRef.current.slice(0, -1)];
167
+ updateDialogEntries(updatedPanels);
166
168
  }, [dialogEntries]);
167
169
  const open = useCallback((dialogEntry) => {
168
- updateDialogEntries([...dialogEntriesRef.current, dialogEntry]);
170
+ const updatedPanels = [...dialogEntriesRef.current, dialogEntry];
171
+ updateDialogEntries(updatedPanels);
169
172
  return { closeDialog: () => {
170
- updateDialogEntries(dialogEntriesRef.current.filter((e) => e.key !== dialogEntry.key));
173
+ const updatedPanels = dialogEntriesRef.current.filter((e) => e.key !== dialogEntry.key);
174
+ updateDialogEntries(updatedPanels);
171
175
  } };
172
176
  }, [dialogEntries]);
173
177
  const dialogsController = useMemo(() => ({
@@ -624,24 +628,37 @@ var useStorageSource = () => {
624
628
  var useSnackbarController = () => {
625
629
  const { enqueueSnackbar, closeSnackbar } = useSnackbar();
626
630
  const open = useCallback((props) => {
627
- const { type, message, autoHideDuration } = props;
631
+ const { type, message, autoHideDuration, action } = props;
628
632
  enqueueSnackbar({
629
633
  message: props.title ? /* @__PURE__ */ jsxs("div", {
630
634
  className: "flex flex-col",
631
635
  children: [/* @__PURE__ */ jsx("strong", { children: props.title }), message]
632
636
  }) : message,
633
637
  variant: type,
634
- autoHideDuration
638
+ autoHideDuration,
639
+ ...action ? { key: nextActionKey() } : {},
640
+ action: action ? (key) => /* @__PURE__ */ jsx(Button, {
641
+ variant: "text",
642
+ size: "small",
643
+ className: "text-inherit",
644
+ onClick: () => {
645
+ action.onClick();
646
+ closeSnackbar(key);
647
+ },
648
+ children: action.label
649
+ }) : void 0
635
650
  });
636
- }, []);
651
+ }, [enqueueSnackbar, closeSnackbar]);
637
652
  const close = useCallback(() => {
638
653
  closeSnackbar();
639
- }, []);
654
+ }, [closeSnackbar]);
640
655
  return useMemo(() => ({
641
656
  open,
642
657
  close
643
658
  }), [open, close]);
644
659
  };
660
+ var actionKeySeq = 0;
661
+ var nextActionKey = () => `rebase-snackbar-action-${actionKeySeq++}`;
645
662
  //#endregion
646
663
  //#region src/hooks/useUserConfigurationPersistence.tsx
647
664
  /**
@@ -908,7 +925,8 @@ function useRelationSelector({ path, collection, fixedFilter, pageSize = DEFAULT
908
925
  setLoading(true);
909
926
  const whereParams = fixedFilter && Object.keys(fixedFilter).length > 0 ? fixedFilter : void 0;
910
927
  const onEntitiesUpdate = (res) => {
911
- setItems(res.data.map((e) => entityToRelationItem(e)));
928
+ const newItems = res.data.map((e) => entityToRelationItem(e));
929
+ setItems(newItems);
912
930
  setHasMore(res.meta.hasMore);
913
931
  setLoading(false);
914
932
  };
@@ -1201,14 +1219,38 @@ function useUnsavedChangesDialog(when, onOk) {
1201
1219
  function useAuthSubscription(authClient) {
1202
1220
  const currentSession = authClient?.getSession();
1203
1221
  const [user, setUser] = useState(currentSession?.user ?? null);
1204
- const [initialLoading, setInitialLoading] = useState(!currentSession);
1205
1222
  const [authLoading, setAuthLoading] = useState(false);
1206
1223
  const [authError, setAuthError] = useState();
1207
1224
  const [loginSkipped, setLoginSkipped] = useState(false);
1208
1225
  const [extra, setExtra] = useState();
1226
+ /**
1227
+ * Whether asking the server "who am I?" could possibly answer.
1228
+ *
1229
+ * A client configured with `persistSession: false` and JSON auth — the
1230
+ * shape used when one client borrows another's credential, as the hosted
1231
+ * Studio does — has no stored session and no auth cookie, so the probe
1232
+ * below is guaranteed to 401. Sending it anyway put three failing
1233
+ * `GET /auth/me` calls on the wire per mount, each one landing in the
1234
+ * *customer's* request log as an authentication failure against their own
1235
+ * backend.
1236
+ *
1237
+ * A client that does not implement the capability is treated as "might
1238
+ * work" — the historical behaviour.
1239
+ */
1240
+ const mayHaveRestorableSession = authClient?.canRestoreSession?.() ?? true;
1241
+ /**
1242
+ * `true` only while a probe is genuinely outstanding.
1243
+ *
1244
+ * It used to be seeded from `!currentSession` alone, which left a client
1245
+ * that cannot restore a session — and therefore never runs the probe that
1246
+ * clears the flag — reporting "still loading" forever. Anything gated on
1247
+ * `initialLoading` (a spinner, a redirect to the login view) would never
1248
+ * resolve.
1249
+ */
1250
+ const [initialLoading, setInitialLoading] = useState(!currentSession && mayHaveRestorableSession);
1209
1251
  useEffect(() => {
1210
1252
  if (!authClient) return;
1211
- if (!currentSession) {
1253
+ if (!currentSession && mayHaveRestorableSession) {
1212
1254
  setInitialLoading(true);
1213
1255
  authClient.getUser().then((user) => {
1214
1256
  if (user) setUser(user);
@@ -1216,7 +1258,11 @@ function useAuthSubscription(authClient) {
1216
1258
  setInitialLoading(false);
1217
1259
  });
1218
1260
  }
1219
- }, [authClient, currentSession]);
1261
+ }, [
1262
+ authClient,
1263
+ currentSession,
1264
+ mayHaveRestorableSession
1265
+ ]);
1220
1266
  useEffect(() => {
1221
1267
  if (!authClient) return;
1222
1268
  return authClient.onAuthStateChange((event, session) => {
@@ -1751,6 +1797,60 @@ function useRebaseRegistryDispatch() {
1751
1797
  return dispatch;
1752
1798
  }
1753
1799
  //#endregion
1800
+ //#region src/hooks/ApiConfigContext.tsx
1801
+ /** What the server uses when `basePath` is not configured. */
1802
+ var DEFAULT_API_PATH = "/api";
1803
+ var ApiConfigContext = React.createContext(void 0);
1804
+ /**
1805
+ * Read the API config from context. Returns `undefined` if no provider is present,
1806
+ * allowing hooks to fall back to their own props.
1807
+ */
1808
+ function useApiConfig() {
1809
+ return useContext(ApiConfigContext);
1810
+ }
1811
+ /**
1812
+ * `apiUrl` and `apiPath` joined, with no trailing slash — the prefix to build a
1813
+ * request URL from.
1814
+ *
1815
+ * Returns `undefined` when there is no provider, so a caller can keep its own
1816
+ * fallback rather than silently requesting a relative path.
1817
+ */
1818
+ function useApiBase() {
1819
+ const config = useApiConfig();
1820
+ if (!config?.apiUrl) return void 0;
1821
+ return config.apiUrl.replace(/\/+$/, "") + (config.apiPath || "/api");
1822
+ }
1823
+ /**
1824
+ * The same prefix, derived from a client rather than from context.
1825
+ *
1826
+ * For the code that holds a `RebaseClient` but sits outside (or above) an
1827
+ * `ApiConfigProvider`. Returns `undefined` when the client has no base URL,
1828
+ * which is the signal every caller already treats as "cannot build a request".
1829
+ */
1830
+ function apiBaseOf(client) {
1831
+ if (!client?.baseUrl) return void 0;
1832
+ return client.baseUrl.replace(/\/+$/, "") + (client.apiPath || "/api");
1833
+ }
1834
+ /**
1835
+ * Provide API configuration (apiUrl, apiPath, getAuthToken) to the entire subtree.
1836
+ * Typically rendered inside `<Rebase>` or at the app root.
1837
+ */
1838
+ function ApiConfigProvider({ apiUrl, apiPath = DEFAULT_API_PATH, getAuthToken, children }) {
1839
+ const value = React.useMemo(() => ({
1840
+ apiUrl,
1841
+ apiPath,
1842
+ getAuthToken
1843
+ }), [
1844
+ apiUrl,
1845
+ apiPath,
1846
+ getAuthToken
1847
+ ]);
1848
+ return /* @__PURE__ */ jsx(ApiConfigContext.Provider, {
1849
+ value,
1850
+ children
1851
+ });
1852
+ }
1853
+ //#endregion
1754
1854
  //#region src/hooks/useBackendStorageSource.ts
1755
1855
  /**
1756
1856
  * React hook for using backend storage API as a StorageSource
@@ -1770,8 +1870,8 @@ function useRebaseRegistryDispatch() {
1770
1870
  * <Rebase storageSource={storageSource} ... />
1771
1871
  * ```
1772
1872
  */
1773
- function useBackendStorageSource({ apiUrl, getAuthToken }) {
1774
- const storageBasePath = `${apiUrl}/api/storage`;
1873
+ function useBackendStorageSource({ apiUrl, apiPath = DEFAULT_API_PATH, getAuthToken }) {
1874
+ const storageBasePath = `${apiUrl.replace(/\/+$/, "")}${apiPath}/storage`;
1775
1875
  const urlsCache = useMemo(() => /* @__PURE__ */ new Map(), []);
1776
1876
  /**
1777
1877
  * Make an authenticated request to the storage API
@@ -1933,30 +2033,6 @@ function usePermissions() {
1933
2033
  ]);
1934
2034
  }
1935
2035
  //#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
2036
  //#region src/hooks/useTranslation.ts
1961
2037
  var REBASE_NS$1 = "rebase_core";
1962
2038
  /**
@@ -6318,7 +6394,7 @@ function KanbanBoardDemo() {
6318
6394
  const [columns, setColumns] = useState(STATUS_COLUMNS);
6319
6395
  const assignColumn = useCallback((item) => item.data.status, []);
6320
6396
  const handleItemsReorder = useCallback((items, moveInfo) => {
6321
- setBoardData(items.map((item) => {
6397
+ const updatedItems = items.map((item) => {
6322
6398
  if (moveInfo && item.id === moveInfo.itemId && moveInfo.sourceColumn !== moveInfo.targetColumn) return {
6323
6399
  ...item,
6324
6400
  data: {
@@ -6328,7 +6404,8 @@ function KanbanBoardDemo() {
6328
6404
  }
6329
6405
  };
6330
6406
  return item;
6331
- }));
6407
+ });
6408
+ setBoardData(updatedItems);
6332
6409
  }, []);
6333
6410
  const handleColumnReorder = useCallback((reordered) => setColumns(reordered), []);
6334
6411
  const columnLoadingState = useMemo(() => {
@@ -7563,6 +7640,22 @@ function UIReferenceView() {
7563
7640
  disabled: true,
7564
7641
  value: "Read only",
7565
7642
  onChange: () => {}
7643
+ }),
7644
+ /* @__PURE__ */ jsx(TextField, {
7645
+ size: "medium",
7646
+ label: "Medium",
7647
+ placeholder: "Placeholder under the label"
7648
+ }),
7649
+ /* @__PURE__ */ jsx(TextField, {
7650
+ size: "small",
7651
+ label: "Small",
7652
+ placeholder: "Placeholder under the label"
7653
+ }),
7654
+ /* @__PURE__ */ jsx(TextField, {
7655
+ size: "smallest",
7656
+ label: "Smallest",
7657
+ value: "Filled value",
7658
+ onChange: () => {}
7566
7659
  })
7567
7660
  ]
7568
7661
  })]
@@ -8012,7 +8105,7 @@ function UIReferenceView() {
8012
8105
  /* @__PURE__ */ jsx(TableCell, { children: /* @__PURE__ */ jsx("div", {
8013
8106
  className: "flex flex-wrap gap-2",
8014
8107
  children: user.roles.map((role) => /* @__PURE__ */ jsx(Chip, {
8015
- colorScheme: role.isAdmin ? "purpleDark" : "blueDark",
8108
+ colorScheme: role.isAdmin ? "purple" : "blue",
8016
8109
  size: "small",
8017
8110
  children: role.name
8018
8111
  }, role.id))
@@ -8336,8 +8429,10 @@ function UserSettingsView() {
8336
8429
  setLoadingSessions(true);
8337
8430
  setSessionsError(null);
8338
8431
  try {
8339
- if (authController.fetchSessions) setSessions((await authController.fetchSessions() || []).sort((a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime()));
8340
- else throw new Error("fetchSessions not implemented in this auth controller.");
8432
+ if (authController.fetchSessions) {
8433
+ const sortedSessions = (await authController.fetchSessions() || []).sort((a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime());
8434
+ setSessions(sortedSessions);
8435
+ } else throw new Error("fetchSessions not implemented in this auth controller.");
8341
8436
  } catch (e) {
8342
8437
  setSessionsError(e instanceof Error ? e.message : String(e));
8343
8438
  } finally {
@@ -9723,6 +9818,7 @@ var en = {
9723
9818
  log_out: "Log out",
9724
9819
  column_cannot_be_edited: "This column can't be edited directly",
9725
9820
  close: "Close",
9821
+ hide_list: "Hide list",
9726
9822
  unsaved_local_changes: "Unsaved Local changes",
9727
9823
  unsaved_local_changes_description: "This document was edited locally and has unsaved changes. These local changes will be lost if you don't apply them.",
9728
9824
  preview_changes: "Preview Changes",
@@ -10527,7 +10623,22 @@ var en = {
10527
10623
  datetime_automatic_value: "Automatic value",
10528
10624
  markdown_paste_behavior: "Paste behavior",
10529
10625
  markdown_strip_html: "Strip HTML on paste",
10530
- markdown_convert_pasted: "Convert pasted text to markdown"
10626
+ markdown_convert_pasted: "Convert pasted text to markdown",
10627
+ entity_saved: "Saved",
10628
+ more_actions: "More actions",
10629
+ record_history: "History",
10630
+ inspect_record: "Inspect record",
10631
+ inspect: "Inspect",
10632
+ close_inspector: "Close inspector",
10633
+ history_revert: "Revert to this version",
10634
+ history_revert_title: "Revert data to this version?",
10635
+ history_reverted: "Reverted to selected version",
10636
+ history_revert_error: "Error reverting entity",
10637
+ history_revert_dirty: "Please save or discard your changes before reverting",
10638
+ history_empty: "No history available",
10639
+ history_empty_description: "When you save a record, a new version is created and stored in the history.",
10640
+ history_new_entity: "History is only available for existing records",
10641
+ history_no_more: "No more history"
10531
10642
  };
10532
10643
  //#endregion
10533
10644
  //#region src/locales/es.ts
@@ -10604,6 +10715,7 @@ var es = {
10604
10715
  log_out: "Cerrar sesión",
10605
10716
  column_cannot_be_edited: "Esta columna no se puede editar directamente",
10606
10717
  close: "Cerrar",
10718
+ hide_list: "Ocultar lista",
10607
10719
  unsaved_local_changes: "Cambios locales sin guardar",
10608
10720
  unsaved_local_changes_description: "Este documento ha sido editado localmente y tiene cambios sin guardar. Estos cambios locales se perderán si no los aplicas.",
10609
10721
  preview_changes: "Previsualizar cambios",
@@ -11373,7 +11485,22 @@ var es = {
11373
11485
  datetime_automatic_value: "Valor automático",
11374
11486
  markdown_paste_behavior: "Comportamiento al pegar",
11375
11487
  markdown_strip_html: "Eliminar HTML al pegar",
11376
- markdown_convert_pasted: "Convertir texto pegado a markdown"
11488
+ markdown_convert_pasted: "Convertir texto pegado a markdown",
11489
+ entity_saved: "Guardado",
11490
+ more_actions: "Más acciones",
11491
+ record_history: "Historial",
11492
+ inspect_record: "Inspeccionar registro",
11493
+ inspect: "Inspeccionar",
11494
+ close_inspector: "Cerrar el inspector",
11495
+ history_revert: "Volver a esta versión",
11496
+ history_revert_title: "¿Volver a esta versión de los datos?",
11497
+ history_reverted: "Se volvió a la versión seleccionada",
11498
+ history_revert_error: "Error al revertir el registro",
11499
+ history_revert_dirty: "Guarda o descarta tus cambios antes de revertir",
11500
+ history_empty: "No hay historial disponible",
11501
+ history_empty_description: "Al guardar un registro se crea una nueva versión y se almacena en el historial.",
11502
+ history_new_entity: "El historial solo está disponible para registros existentes",
11503
+ history_no_more: "No hay más historial"
11377
11504
  };
11378
11505
  //#endregion
11379
11506
  //#region src/locales/de.ts
@@ -11442,6 +11569,7 @@ var de = {
11442
11569
  log_out: "Abmelden",
11443
11570
  column_cannot_be_edited: "Diese Spalte kann nicht direkt bearbeitet werden",
11444
11571
  close: "Schließen",
11572
+ hide_list: "Liste ausblenden",
11445
11573
  unsaved_local_changes: "Ungespeicherte lokale Änderungen",
11446
11574
  unsaved_local_changes_description: "Dieses Dokument wurde lokal bearbeitet und weist ungespeicherte Änderungen auf. Diese lokalen Änderungen gehen verloren, wenn Sie sie nicht anwenden.",
11447
11575
  preview_changes: "Änderungen in der Vorschau anzeigen",
@@ -12201,7 +12329,22 @@ var de = {
12201
12329
  datetime_automatic_value: "Automatischer Wert",
12202
12330
  markdown_paste_behavior: "Einfügeverhalten",
12203
12331
  markdown_strip_html: "HTML beim Einfügen entfernen",
12204
- markdown_convert_pasted: "Eingefügten Text in Markdown umwandeln"
12332
+ markdown_convert_pasted: "Eingefügten Text in Markdown umwandeln",
12333
+ entity_saved: "Gespeichert",
12334
+ more_actions: "Weitere Aktionen",
12335
+ record_history: "Verlauf",
12336
+ inspect_record: "Datensatz inspizieren",
12337
+ inspect: "Inspizieren",
12338
+ close_inspector: "Inspektor schließen",
12339
+ history_revert: "Auf diese Version zurücksetzen",
12340
+ history_revert_title: "Daten auf diese Version zurücksetzen?",
12341
+ history_reverted: "Auf die gewählte Version zurückgesetzt",
12342
+ history_revert_error: "Fehler beim Zurücksetzen des Datensatzes",
12343
+ history_revert_dirty: "Bitte speichere oder verwirf deine Änderungen vor dem Zurücksetzen",
12344
+ history_empty: "Kein Verlauf vorhanden",
12345
+ history_empty_description: "Beim Speichern eines Datensatzes wird eine neue Version erstellt und im Verlauf abgelegt.",
12346
+ history_new_entity: "Der Verlauf ist nur für vorhandene Datensätze verfügbar",
12347
+ history_no_more: "Kein weiterer Verlauf"
12205
12348
  };
12206
12349
  //#endregion
12207
12350
  //#region src/locales/fr.ts
@@ -12270,6 +12413,7 @@ var fr = {
12270
12413
  log_out: "Se déconnecter",
12271
12414
  column_cannot_be_edited: "Cette colonne ne peut pas être modifiée directement",
12272
12415
  close: "Fermer",
12416
+ hide_list: "Masquer la liste",
12273
12417
  unsaved_local_changes: "Modifications locales non enregistrées",
12274
12418
  unsaved_local_changes_description: "Ce document a été modifié localement et contient des modifications non enregistrées. Ces modifications locales seront perdues si vous ne les appliquez pas.",
12275
12419
  preview_changes: "Aperçu des modifications",
@@ -13029,7 +13173,22 @@ var fr = {
13029
13173
  datetime_automatic_value: "Valeur automatique",
13030
13174
  markdown_paste_behavior: "Comportement au collage",
13031
13175
  markdown_strip_html: "Supprimer le HTML au collage",
13032
- markdown_convert_pasted: "Convertir le texte collé en markdown"
13176
+ markdown_convert_pasted: "Convertir le texte collé en markdown",
13177
+ entity_saved: "Enregistré",
13178
+ more_actions: "Plus d'actions",
13179
+ record_history: "Historique",
13180
+ inspect_record: "Inspecter l'enregistrement",
13181
+ inspect: "Inspecter",
13182
+ close_inspector: "Fermer l'inspecteur",
13183
+ history_revert: "Revenir à cette version",
13184
+ history_revert_title: "Revenir à cette version des données ?",
13185
+ history_reverted: "Retour à la version sélectionnée",
13186
+ history_revert_error: "Erreur lors du retour en arrière",
13187
+ history_revert_dirty: "Enregistrez ou annulez vos modifications avant de revenir en arrière",
13188
+ history_empty: "Aucun historique disponible",
13189
+ history_empty_description: "À chaque enregistrement, une nouvelle version est créée et conservée dans l'historique.",
13190
+ history_new_entity: "L'historique n'est disponible que pour les enregistrements existants",
13191
+ history_no_more: "Plus d'historique"
13033
13192
  };
13034
13193
  //#endregion
13035
13194
  //#region src/locales/it.ts
@@ -13098,6 +13257,7 @@ var it = {
13098
13257
  log_out: "Esci",
13099
13258
  column_cannot_be_edited: "Questa colonna non può essere modificata direttamente",
13100
13259
  close: "Chiudi",
13260
+ hide_list: "Nascondi elenco",
13101
13261
  unsaved_local_changes: "Modifiche locali non salvate",
13102
13262
  unsaved_local_changes_description: "Questo documento è stato modificato localmente e ha modifiche non salvate. Queste modifiche locali andranno perse se non le applichi.",
13103
13263
  preview_changes: "Anteprima modifiche",
@@ -13857,7 +14017,22 @@ var it = {
13857
14017
  datetime_automatic_value: "Valore automatico",
13858
14018
  markdown_paste_behavior: "Comportamento incolla",
13859
14019
  markdown_strip_html: "Rimuovi HTML all'incolla",
13860
- markdown_convert_pasted: "Converti testo incollato in markdown"
14020
+ markdown_convert_pasted: "Converti testo incollato in markdown",
14021
+ entity_saved: "Salvato",
14022
+ more_actions: "Altre azioni",
14023
+ record_history: "Cronologia",
14024
+ inspect_record: "Ispeziona record",
14025
+ inspect: "Ispeziona",
14026
+ close_inspector: "Chiudi l'ispettore",
14027
+ history_revert: "Torna a questa versione",
14028
+ history_revert_title: "Ripristinare i dati a questa versione?",
14029
+ history_reverted: "Ripristinata la versione selezionata",
14030
+ history_revert_error: "Errore durante il ripristino del record",
14031
+ history_revert_dirty: "Salva o annulla le modifiche prima di ripristinare",
14032
+ history_empty: "Nessuna cronologia disponibile",
14033
+ history_empty_description: "Quando salvi un record viene creata una nuova versione e conservata nella cronologia.",
14034
+ history_new_entity: "La cronologia è disponibile solo per i record esistenti",
14035
+ history_no_more: "Nessun'altra cronologia"
13861
14036
  };
13862
14037
  //#endregion
13863
14038
  //#region src/locales/hi.ts
@@ -13926,6 +14101,7 @@ var hi = {
13926
14101
  log_out: "लॉग आउट",
13927
14102
  column_cannot_be_edited: "इस कॉलम को सीधे संपादित नहीं किया जा सकता",
13928
14103
  close: "बंद करें",
14104
+ hide_list: "सूची छिपाएँ",
13929
14105
  unsaved_local_changes: "सहेजे नहीं गए स्थानीय परिवर्तन",
13930
14106
  unsaved_local_changes_description: "इस दस्तावेज़ को स्थानीय स्तर पर संपादित किया गया था और इसमें सहेजे नहीं गए परिवर्तन हैं। यदि आप इन्हें लागू नहीं करते हैं तो ये स्थानीय परिवर्तन खो जाएंगे।",
13931
14107
  preview_changes: "परिवर्तनों का पूर्वावलोकन करें",
@@ -14685,7 +14861,22 @@ var hi = {
14685
14861
  datetime_automatic_value: "स्वचालित मान",
14686
14862
  markdown_paste_behavior: "पेस्ट व्यवहार",
14687
14863
  markdown_strip_html: "पेस्ट करते समय HTML हटाएं",
14688
- markdown_convert_pasted: "पेस्ट किए गए टेक्स्ट को मार्कडाउन में बदलें"
14864
+ markdown_convert_pasted: "पेस्ट किए गए टेक्स्ट को मार्कडाउन में बदलें",
14865
+ entity_saved: "सहेजा गया",
14866
+ more_actions: "अधिक क्रियाएँ",
14867
+ record_history: "इतिहास",
14868
+ inspect_record: "रिकॉर्ड जाँचें",
14869
+ inspect: "जाँचें",
14870
+ close_inspector: "इंस्पेक्टर बंद करें",
14871
+ history_revert: "इस संस्करण पर लौटें",
14872
+ history_revert_title: "डेटा को इस संस्करण पर लौटाएँ?",
14873
+ history_reverted: "चयनित संस्करण पर लौटा दिया गया",
14874
+ history_revert_error: "रिकॉर्ड लौटाने में त्रुटि",
14875
+ history_revert_dirty: "लौटाने से पहले अपने बदलाव सहेजें या रद्द करें",
14876
+ history_empty: "कोई इतिहास उपलब्ध नहीं",
14877
+ history_empty_description: "रिकॉर्ड सहेजने पर एक नया संस्करण बनता है और इतिहास में रखा जाता है।",
14878
+ history_new_entity: "इतिहास केवल मौजूदा रिकॉर्ड के लिए उपलब्ध है",
14879
+ history_no_more: "और इतिहास नहीं"
14689
14880
  };
14690
14881
  //#endregion
14691
14882
  //#region src/locales/pt.ts
@@ -14759,6 +14950,7 @@ var pt = {
14759
14950
  log_out: "Terminar sessão",
14760
14951
  column_cannot_be_edited: "Esta coluna não pode ser editada diretamente",
14761
14952
  close: "Fechar",
14953
+ hide_list: "Ocultar lista",
14762
14954
  unsaved_local_changes: "Alterações locais não guardadas",
14763
14955
  unsaved_local_changes_description: "Este documento foi editado localmente e tem alterações não guardadas. Estas alterações locais serão perdidas se não as aplicar.",
14764
14956
  preview_changes: "Pré-visualizar alterações",
@@ -15518,7 +15710,22 @@ var pt = {
15518
15710
  datetime_automatic_value: "Valor automático",
15519
15711
  markdown_paste_behavior: "Comportamento ao colar",
15520
15712
  markdown_strip_html: "Remover HTML ao colar",
15521
- markdown_convert_pasted: "Converter texto colado para markdown"
15713
+ markdown_convert_pasted: "Converter texto colado para markdown",
15714
+ entity_saved: "Guardado",
15715
+ more_actions: "Mais ações",
15716
+ record_history: "Histórico",
15717
+ inspect_record: "Inspecionar registo",
15718
+ inspect: "Inspecionar",
15719
+ close_inspector: "Fechar o inspetor",
15720
+ history_revert: "Voltar a esta versão",
15721
+ history_revert_title: "Reverter os dados para esta versão?",
15722
+ history_reverted: "Revertido para a versão selecionada",
15723
+ history_revert_error: "Erro ao reverter o registo",
15724
+ history_revert_dirty: "Guarde ou descarte as suas alterações antes de reverter",
15725
+ history_empty: "Nenhum histórico disponível",
15726
+ history_empty_description: "Ao guardar um registo é criada uma nova versão, guardada no histórico.",
15727
+ history_new_entity: "O histórico só está disponível para registos existentes",
15728
+ history_no_more: "Sem mais histórico"
15522
15729
  };
15523
15730
  //#endregion
15524
15731
  //#region src/i18n/RebaseI18nProvider.tsx
@@ -15852,6 +16059,7 @@ function Rebase(props) {
15852
16059
  const resolvedApiUrl = apiUrl || client?.baseUrl || (typeof window !== "undefined" ? window.location.origin : "");
15853
16060
  if (resolvedApiUrl) return /* @__PURE__ */ jsx(ApiConfigProvider, {
15854
16061
  apiUrl: resolvedApiUrl,
16062
+ apiPath: client?.apiPath,
15855
16063
  getAuthToken: authController.getAuthToken,
15856
16064
  children: content
15857
16065
  });
@@ -15998,7 +16206,8 @@ function useRebaseAuthController(props = {}) {
15998
16206
  try {
15999
16207
  await auth.signOut();
16000
16208
  } catch (error) {
16001
- setAuthProviderError(error instanceof Error ? error : new Error(String(error)));
16209
+ const err = error instanceof Error ? error : new Error(String(error));
16210
+ setAuthProviderError(err);
16002
16211
  } finally {
16003
16212
  setAuthLoading(false);
16004
16213
  }
@@ -16010,7 +16219,8 @@ function useRebaseAuthController(props = {}) {
16010
16219
  try {
16011
16220
  await auth.signInWithEmail(email, password);
16012
16221
  } catch (error) {
16013
- setAuthProviderError(error instanceof Error ? error : new Error(String(error)));
16222
+ const err = error instanceof Error ? error : new Error(String(error));
16223
+ setAuthProviderError(err);
16014
16224
  throw error;
16015
16225
  } finally {
16016
16226
  setAuthLoading(false);
@@ -16023,7 +16233,8 @@ function useRebaseAuthController(props = {}) {
16023
16233
  try {
16024
16234
  await auth.signUp(email, password, displayName);
16025
16235
  } catch (error) {
16026
- setAuthProviderError(error instanceof Error ? error : new Error(String(error)));
16236
+ const err = error instanceof Error ? error : new Error(String(error));
16237
+ setAuthProviderError(err);
16027
16238
  throw error;
16028
16239
  } finally {
16029
16240
  setAuthLoading(false);
@@ -16036,7 +16247,8 @@ function useRebaseAuthController(props = {}) {
16036
16247
  try {
16037
16248
  await auth.signInWithGoogle(payload);
16038
16249
  } catch (error) {
16039
- setAuthProviderError(error instanceof Error ? error : new Error(String(error)));
16250
+ const err = error instanceof Error ? error : new Error(String(error));
16251
+ setAuthProviderError(err);
16040
16252
  throw error;
16041
16253
  } finally {
16042
16254
  setAuthLoading(false);
@@ -16049,7 +16261,8 @@ function useRebaseAuthController(props = {}) {
16049
16261
  try {
16050
16262
  await auth.signInWithOAuth(providerId, payload);
16051
16263
  } catch (error) {
16052
- setAuthProviderError(error instanceof Error ? error : new Error(String(error)));
16264
+ const err = error instanceof Error ? error : new Error(String(error));
16265
+ setAuthProviderError(err);
16053
16266
  throw error;
16054
16267
  } finally {
16055
16268
  setAuthLoading(false);
@@ -16066,7 +16279,8 @@ function useRebaseAuthController(props = {}) {
16066
16279
  try {
16067
16280
  await auth.resetPasswordForEmail(email);
16068
16281
  } catch (error) {
16069
- setAuthProviderError(error instanceof Error ? error : new Error(String(error)));
16282
+ const err = error instanceof Error ? error : new Error(String(error));
16283
+ setAuthProviderError(err);
16070
16284
  throw error;
16071
16285
  } finally {
16072
16286
  setAuthLoading(false);
@@ -16079,7 +16293,8 @@ function useRebaseAuthController(props = {}) {
16079
16293
  try {
16080
16294
  await auth.resetPassword(token, password);
16081
16295
  } catch (error) {
16082
- setAuthProviderError(error instanceof Error ? error : new Error(String(error)));
16296
+ const err = error instanceof Error ? error : new Error(String(error));
16297
+ setAuthProviderError(err);
16083
16298
  throw error;
16084
16299
  } finally {
16085
16300
  setAuthLoading(false);
@@ -16093,7 +16308,8 @@ function useRebaseAuthController(props = {}) {
16093
16308
  await auth.changePassword(oldPassword, newPassword);
16094
16309
  await auth.signOut();
16095
16310
  } catch (error) {
16096
- setAuthProviderError(error instanceof Error ? error : new Error(String(error)));
16311
+ const err = error instanceof Error ? error : new Error(String(error));
16312
+ setAuthProviderError(err);
16097
16313
  throw error;
16098
16314
  } finally {
16099
16315
  setAuthLoading(false);
@@ -16109,7 +16325,8 @@ function useRebaseAuthController(props = {}) {
16109
16325
  photoURL
16110
16326
  });
16111
16327
  } catch (error) {
16112
- setAuthProviderError(error instanceof Error ? error : new Error(String(error)));
16328
+ const err = error instanceof Error ? error : new Error(String(error));
16329
+ setAuthProviderError(err);
16113
16330
  throw error;
16114
16331
  } finally {
16115
16332
  setAuthLoading(false);
@@ -16180,12 +16397,6 @@ function useRebaseAuthController(props = {}) {
16180
16397
  * here is the unauthenticated `/api/auth/config` probe used to detect
16181
16398
  * bootstrap mode and enabled providers before a session exists.
16182
16399
  */
16183
- /**
16184
- * @deprecated Use {@link RebaseApiError} (from `@rebasepro/types`, re-exported by
16185
- * `@rebasepro/client`). Kept as an alias so `instanceof` / imports keep working;
16186
- * errors thrown here now carry `.code` and `.status` on the unified type.
16187
- */
16188
- var AuthApiError = RebaseApiError;
16189
16400
  async function handleResponse(response) {
16190
16401
  let data;
16191
16402
  try {
@@ -16238,11 +16449,11 @@ function createAuthConfigCache() {
16238
16449
  * Concurrent calls are deduplicated: only one network request is made
16239
16450
  * and all callers share the same promise.
16240
16451
  */
16241
- async function fetchAuthConfig(apiUrl, cache) {
16452
+ async function fetchAuthConfig(apiUrl, cache, apiPath = DEFAULT_API_PATH) {
16242
16453
  if (cache.cached) return cache.cached;
16243
16454
  if (cache.inflight) return cache.inflight;
16244
16455
  cache.inflight = (async () => {
16245
- return handleResponse(await fetchWithHandling(`${apiUrl}/api/auth/config`, {
16456
+ return handleResponse(await fetchWithHandling(`${apiUrl.replace(/\/+$/, "")}${apiPath}/auth/config`, {
16246
16457
  method: "GET",
16247
16458
  headers: { "Content-Type": "application/json" }
16248
16459
  }));
@@ -16568,7 +16779,7 @@ function useStorageUploadController({ entityId, entityValues, path, value, prope
16568
16779
  if (!storage) throw Error("Storage meta must be specified");
16569
16780
  const processFile = storage?.processFile;
16570
16781
  const metadata = storage?.metadata;
16571
- const size = multipleFilesSupported ? "medium" : "large";
16782
+ const size = "medium";
16572
16783
  const imageResize = storage?.imageResize;
16573
16784
  const internalInitialValue = getInternalInitialValue(multipleFilesSupported, value, metadata, size);
16574
16785
  const [initialValue, setInitialValue] = useState(value);
@@ -16660,7 +16871,8 @@ function useStorageUploadController({ entityId, entityValues, path, value, prope
16660
16871
  ]),
16661
16872
  onFileUploadError: useCallback((entry) => {
16662
16873
  console.debug("onFileUploadError", entry);
16663
- setInternalValue(internalValue.filter((item) => item.id !== entry.id));
16874
+ const newValue = internalValue.filter((item) => item.id !== entry.id);
16875
+ setInternalValue(newValue);
16664
16876
  }, [internalValue]),
16665
16877
  onFilesAdded: useCallback(async (acceptedFiles) => {
16666
16878
  if (!acceptedFiles.length || disabled) return;
@@ -16775,7 +16987,7 @@ function getColorScheme(enumValues, key) {
16775
16987
  const labelOrConfig = getLabelOrConfigFrom(enumValues, key);
16776
16988
  if (!labelOrConfig?.color) return getColorSchemeForSeed(key.toString());
16777
16989
  if (typeof labelOrConfig === "object" && "color" in labelOrConfig) {
16778
- if (typeof labelOrConfig.color === "string") return CHIP_COLORS[labelOrConfig.color];
16990
+ if (typeof labelOrConfig.color === "string") return getColorSchemeForKey(labelOrConfig.color);
16779
16991
  if (typeof labelOrConfig.color === "object") return labelOrConfig.color;
16780
16992
  }
16781
16993
  }
@@ -16809,9 +17021,21 @@ var STUDIO_NAVIGATION_GROUPS = [
16809
17021
  */
16810
17022
  var CONTAINER_FULL_WIDTH = "100vw";
16811
17023
  /** @internal See {@link CONTAINER_FULL_WIDTH}. */
16812
- var ADDITIONAL_TAB_WIDTH = "55vw";
16813
- /** @internal See {@link CONTAINER_FULL_WIDTH}. */
16814
17024
  var FORM_CONTAINER_WIDTH = "768px";
17025
+ /**
17026
+ * How wide the side panel opens when neither the caller nor the collection
17027
+ * says otherwise.
17028
+ *
17029
+ * Sized from what it has to hold rather than from a round number: the form's
17030
+ * content column plus its metadata rail plus gutters, which is also the width
17031
+ * at which the form stops being a single stack and picks up the same
17032
+ * two-column layout it has in full screen. Capped against the viewport so a
17033
+ * panel never becomes the whole window on a laptop — at that point you want
17034
+ * full screen, and there is a button for it.
17035
+ *
17036
+ * @internal See {@link CONTAINER_FULL_WIDTH}.
17037
+ */
17038
+ var SIDE_PANEL_DEFAULT_WIDTH = "min(1160px, 88vw)";
16815
17039
  //#endregion
16816
17040
  //#region src/internal/useRestoreScroll.tsx
16817
17041
  var scrollsMap = {};
@@ -16935,7 +17159,8 @@ var NOOP_BRIDGE = {
16935
17159
  breadcrumbs: [],
16936
17160
  set: () => {},
16937
17161
  updateCount: () => {}
16938
- }
17162
+ },
17163
+ capabilities: { codebase: true }
16939
17164
  };
16940
17165
  var StudioBridgeContext = createContext(NOOP_BRIDGE);
16941
17166
  /**
@@ -16959,7 +17184,14 @@ function StudioBridgeProvider({ value, children }) {
16959
17184
  const merged = React.useMemo(() => ({
16960
17185
  ...NOOP_BRIDGE,
16961
17186
  ...value
16962
- }), [value]);
17187
+ }), [
17188
+ value.collectionRegistry,
17189
+ value.sidePanelController,
17190
+ value.urlController,
17191
+ value.navigationState,
17192
+ value.breadcrumbs,
17193
+ value.capabilities
17194
+ ]);
16963
17195
  return /* @__PURE__ */ jsx(StudioBridgeContext.Provider, {
16964
17196
  value: merged,
16965
17197
  children
@@ -16985,6 +17217,10 @@ function useStudioNavigationState() {
16985
17217
  function useStudioBreadcrumbs() {
16986
17218
  return useContext(StudioBridgeContext).breadcrumbs;
16987
17219
  }
17220
+ /** What the host can do — see {@link StudioCapabilities}. */
17221
+ function useStudioCapabilities() {
17222
+ return useContext(StudioBridgeContext).capabilities;
17223
+ }
16988
17224
  var StudioBridgeRegistryContext = createContext(null);
16989
17225
  /**
16990
17226
  * Provider that creates a self-assembling bridge.
@@ -17247,6 +17483,326 @@ function resolveFilterOperators({ property, isArray, engine }) {
17247
17483
  return typeDefaults.filter((op) => engineOps.has(op) && (narrowingSet === void 0 || narrowingSet.has(op)));
17248
17484
  }
17249
17485
  //#endregion
17486
+ //#region src/collections/property_presentation.ts
17487
+ function isReadOnly(property) {
17488
+ if (property.admin?.readOnly) return true;
17489
+ if (property.type === "date") {
17490
+ if (property.autoValue) return true;
17491
+ }
17492
+ if (property.type === "reference") return !property.path && !("Field" in (property.admin || {}) && property.admin?.Field);
17493
+ return false;
17494
+ }
17495
+ function isHidden(property) {
17496
+ return typeof property.admin?.disabled === "object" && Boolean(property.admin?.disabled.hidden);
17497
+ }
17498
+ function applyPropertyConditions(property, context) {
17499
+ const { conditions } = property;
17500
+ if (!conditions) return property;
17501
+ const result = { ...property };
17502
+ if (conditions.disabled) {
17503
+ if (evaluateCondition(conditions.disabled, context)) {
17504
+ result.admin = result.admin || {};
17505
+ result.admin.disabled = {
17506
+ clearOnDisabled: conditions.clearOnDisabled ?? false,
17507
+ disabledMessage: conditions.disabledMessage,
17508
+ hidden: false
17509
+ };
17510
+ }
17511
+ }
17512
+ if (conditions.hidden) {
17513
+ if (evaluateCondition(conditions.hidden, context)) {
17514
+ result.admin = result.admin || {};
17515
+ result.admin.disabled = {
17516
+ ...typeof result.admin?.disabled === "object" ? result.admin.disabled : {},
17517
+ hidden: true,
17518
+ clearOnDisabled: conditions.clearOnDisabled ?? false
17519
+ };
17520
+ }
17521
+ }
17522
+ if (conditions.readOnly) {
17523
+ if (evaluateCondition(conditions.readOnly, context)) {
17524
+ result.admin = result.admin || {};
17525
+ result.admin.readOnly = true;
17526
+ }
17527
+ }
17528
+ if (conditions.required !== void 0) {
17529
+ const isRequired = evaluateCondition(conditions.required, context);
17530
+ result.validation = {
17531
+ ...result.validation,
17532
+ required: isRequired,
17533
+ requiredMessage: conditions.requiredMessage
17534
+ };
17535
+ }
17536
+ if (context.isNew && conditions.defaultValue !== void 0) result.defaultValue = evaluateCondition(conditions.defaultValue, context);
17537
+ if ("enum" in result && result.enum && (conditions.enumConditions || conditions.allowedEnumValues || conditions.excludedEnumValues)) result.enum = applyEnumConditions(result.enum, conditions, context);
17538
+ if (result.type === "reference") {
17539
+ if (conditions.referencePath) result.path = evaluateCondition(conditions.referencePath, context);
17540
+ if (conditions.referenceFilter) {
17541
+ result.admin = result.admin || {};
17542
+ result.admin.fixedFilter = evaluateCondition(conditions.referenceFilter, context);
17543
+ }
17544
+ }
17545
+ if (result.type === "array") {
17546
+ if (conditions.canAddElements !== void 0) {
17547
+ result.admin = result.admin || {};
17548
+ result.admin.canAddElements = evaluateCondition(conditions.canAddElements, context);
17549
+ }
17550
+ if (conditions.sortable !== void 0) {
17551
+ result.admin = result.admin || {};
17552
+ result.admin.sortable = evaluateCondition(conditions.sortable, context);
17553
+ }
17554
+ }
17555
+ return result;
17556
+ }
17557
+ /**
17558
+ * Convert an object with numeric keys back to an array.
17559
+ * Firestore stores arrays as {"0": "a", "1": "b"} to avoid nested arrays.
17560
+ */
17561
+ function objectToArray(obj) {
17562
+ if (Array.isArray(obj)) return obj.map(String);
17563
+ if (obj && typeof obj === "object") {
17564
+ const keys = Object.keys(obj);
17565
+ if (keys.length > 0 && keys.every((k) => !isNaN(Number(k)))) return keys.sort((a, b) => Number(a) - Number(b)).map((k) => obj[k]).filter((v) => typeof v === "string" || typeof v === "number").map(String);
17566
+ }
17567
+ return [];
17568
+ }
17569
+ /**
17570
+ * Apply enum-specific conditions to filter and modify enum values.
17571
+ */
17572
+ function applyEnumConditions(enumValues, conditions, context) {
17573
+ let result = [...enumValues];
17574
+ if (conditions.allowedEnumValues) {
17575
+ const allowedArray = objectToArray(evaluateCondition(conditions.allowedEnumValues, context));
17576
+ if (allowedArray.length > 0) result = result.filter((ev) => allowedArray.includes(String(ev.id)));
17577
+ }
17578
+ if (conditions.excludedEnumValues) {
17579
+ const excludedArray = objectToArray(evaluateCondition(conditions.excludedEnumValues, context));
17580
+ if (excludedArray.length > 0) result = result.filter((ev) => !excludedArray.includes(String(ev.id)));
17581
+ }
17582
+ if (conditions.enumConditions) result = result.map((ev) => {
17583
+ const evConditions = conditions.enumConditions?.[ev.id];
17584
+ if (!evConditions) return ev;
17585
+ if (evConditions.hidden && evaluateCondition(evConditions.hidden, context)) return null;
17586
+ if (evConditions.disabled && evaluateCondition(evConditions.disabled, context)) return {
17587
+ ...ev,
17588
+ disabled: true
17589
+ };
17590
+ return ev;
17591
+ }).filter((ev) => ev !== null);
17592
+ return result;
17593
+ }
17594
+ //#endregion
17595
+ //#region src/collections/form-layout.ts
17596
+ /**
17597
+ * Columns in the form grid.
17598
+ *
17599
+ * A local literal rather than an import of `FORM_GRID_COLUMNS`: everything else
17600
+ * this module takes from `@rebasepro/admin-types` is a *type*, erased at build
17601
+ * time, and a runtime value would make this pure function depend on that
17602
+ * package's built output — which is exactly what broke the dev server, since
17603
+ * `@rebasepro/app` resolves that package to its dist. `satisfies PropertySpan`
17604
+ * keeps the two honest: a full-width field and the column count are the same
17605
+ * number by definition.
17606
+ */
17607
+ var GRID_COLUMNS = 4;
17608
+ /** Does this property's editor need the full width of the column? */
17609
+ function needsFullWidth(property) {
17610
+ switch (property.type) {
17611
+ case "map":
17612
+ case "binary":
17613
+ case "vector": return true;
17614
+ case "array": {
17615
+ if (property.oneOf) return true;
17616
+ const of = Array.isArray(property.of) ? void 0 : property.of;
17617
+ if (!of) return true;
17618
+ if (of.type !== "string" && of.type !== "number") return true;
17619
+ if (of.type === "string" && (of.storage || of.admin?.markdown || of.admin?.multiline)) return true;
17620
+ return false;
17621
+ }
17622
+ case "string": return Boolean(property.storage || property.admin?.markdown || property.admin?.multiline);
17623
+ default: return false;
17624
+ }
17625
+ }
17626
+ /**
17627
+ * The span a property gets when nothing is declared.
17628
+ *
17629
+ * Deliberately coarse: three buckets, chosen by how much room the *editor*
17630
+ * needs, not by how important the field is. Importance is what `admin.form`
17631
+ * sections are for.
17632
+ */
17633
+ function deriveSpan(property, isTitleProperty) {
17634
+ if (needsFullWidth(property)) return 4;
17635
+ if (isTitleProperty) return 4;
17636
+ switch (property.type) {
17637
+ case "number":
17638
+ case "boolean": return 1;
17639
+ case "date":
17640
+ case "geopoint":
17641
+ case "reference":
17642
+ case "relation": return 2;
17643
+ case "array": return 2;
17644
+ case "string": return 2;
17645
+ default: return 2;
17646
+ }
17647
+ }
17648
+ /**
17649
+ * Can the user still type this id?
17650
+ *
17651
+ * A `manual` id is a real field while creating and frozen once the row exists.
17652
+ * Every generated strategy (`uuid`, `cuid`, a raw SQL default) is never typed.
17653
+ * Getting this wrong in the "frozen" direction would make manual-id collections
17654
+ * uncreatable, so it fails towards showing the field.
17655
+ */
17656
+ function isIdPropertyEditable(property, status) {
17657
+ if (!("isId" in property) || !property.isId) return true;
17658
+ if (status === "existing") return false;
17659
+ return property.isId === "manual";
17660
+ }
17661
+ function isIdProperty(property) {
17662
+ return Boolean(property && "isId" in property && property.isId);
17663
+ }
17664
+ /**
17665
+ * An audit timestamp the database maintains — `created_at`, `updated_at`.
17666
+ *
17667
+ * Not a guess from the name: `autoValue` says the column is written by the
17668
+ * system on create or update, so the field is never typed. Rendering it as an
17669
+ * input in the middle of the form promised an edit that cannot happen, and the
17670
+ * record block already shows both values — the same two dates twice on one
17671
+ * screen.
17672
+ */
17673
+ function isAuditTimestamp(property) {
17674
+ return Boolean(property && property.type === "date" && property.autoValue);
17675
+ }
17676
+ /**
17677
+ * Close the trailing gap in each row.
17678
+ *
17679
+ * Without this a section of half-width fields with an odd count leaves a hole —
17680
+ * `name | sku` then `brand | ␣␣` — a field stranded beside half a row of
17681
+ * nothing, which reads as a mistake rather than a layout. The remainder is
17682
+ * spread across the row's derived fields rather than dumped on the last one, so
17683
+ * a lone half-width field becomes full width and a pair grows evenly. Fields
17684
+ * with an explicit span are never resized.
17685
+ */
17686
+ function fillRows(fields) {
17687
+ const rows = [];
17688
+ let row = [];
17689
+ let used = 0;
17690
+ for (const field of fields) {
17691
+ if (used + field.span > GRID_COLUMNS && row.length) {
17692
+ rows.push(row);
17693
+ row = [];
17694
+ used = 0;
17695
+ }
17696
+ row.push(field);
17697
+ used += field.span;
17698
+ }
17699
+ if (row.length) rows.push(row);
17700
+ return rows.flatMap((entries) => {
17701
+ let gap = GRID_COLUMNS - entries.reduce((sum, f) => sum + f.span, 0);
17702
+ if (gap <= 0) return entries;
17703
+ const growable = entries.map((f, i) => [f, i]).filter(([f]) => !f.spanExplicit);
17704
+ if (!growable.length) return entries;
17705
+ const next = [...entries];
17706
+ let cursor = 0;
17707
+ while (gap > 0) {
17708
+ const [, index] = growable[cursor % growable.length];
17709
+ next[index] = {
17710
+ ...next[index],
17711
+ span: next[index].span + 1
17712
+ };
17713
+ gap -= 1;
17714
+ cursor += 1;
17715
+ }
17716
+ return next;
17717
+ });
17718
+ }
17719
+ function buildField(key, collection, titlePropertyKey) {
17720
+ const property = collection.properties?.[key];
17721
+ if (!property) return collection.additionalFields?.some((f) => f.key === key) ? {
17722
+ key,
17723
+ span: 4,
17724
+ additional: true
17725
+ } : void 0;
17726
+ if (isHidden(property)) return void 0;
17727
+ const admin = property.admin;
17728
+ const explicit = admin?.span !== void 0;
17729
+ return {
17730
+ key,
17731
+ span: admin?.span ?? deriveSpan(property, key === titlePropertyKey),
17732
+ additional: false,
17733
+ spanExplicit: explicit
17734
+ };
17735
+ }
17736
+ /**
17737
+ * Resolve the layout for a collection's generated form.
17738
+ *
17739
+ * Never drops a field: anything not named by a section lands in a trailing
17740
+ * group, so adding a column to the database cannot make it silently invisible
17741
+ * in the panel.
17742
+ */
17743
+ function resolveFormLayout({ collection, fieldKeys, status }) {
17744
+ const config = collection.form;
17745
+ const titlePropertyKey = collection.titleProperty;
17746
+ const available = /* @__PURE__ */ new Map();
17747
+ for (const key of fieldKeys) {
17748
+ const field = buildField(key, collection, titlePropertyKey);
17749
+ if (field) available.set(key, field);
17750
+ }
17751
+ const idKeys = [...available.keys()].filter((key) => isIdProperty(collection.properties?.[key]));
17752
+ if (idKeys.length === 1) {
17753
+ const property = collection.properties?.[idKeys[0]];
17754
+ if (!isIdPropertyEditable(property, status)) available.delete(idKeys[0]);
17755
+ }
17756
+ const showRecordMetaResolved = config?.showRecordMeta ?? !collection.hideIdFromForm;
17757
+ if (showRecordMetaResolved) for (const key of [...available.keys()]) {
17758
+ const property = collection.properties?.[key];
17759
+ if (config?.sidebar?.includes(key)) continue;
17760
+ if (isAuditTimestamp(property)) available.delete(key);
17761
+ }
17762
+ const sidebar = [];
17763
+ if (config?.sidebar) for (const key of config.sidebar) {
17764
+ const field = available.get(key);
17765
+ if (!field) continue;
17766
+ sidebar.push(field);
17767
+ available.delete(key);
17768
+ }
17769
+ const showRecordMeta = showRecordMetaResolved;
17770
+ const sections = [];
17771
+ if (config?.sections?.length) for (const section of config.sections) {
17772
+ const fields = [];
17773
+ for (const key of section.properties) {
17774
+ const field = available.get(key);
17775
+ if (!field) continue;
17776
+ fields.push(field);
17777
+ available.delete(key);
17778
+ }
17779
+ const titled = Boolean(section.title);
17780
+ sections.push({
17781
+ key: section.key,
17782
+ title: section.title,
17783
+ collapsible: section.collapsible ?? titled,
17784
+ collapsed: titled ? Boolean(section.collapsed) : false,
17785
+ fields
17786
+ });
17787
+ }
17788
+ const leftovers = fieldKeys.map((key) => available.get(key)).filter((f) => Boolean(f));
17789
+ if (leftovers.length) sections.push({
17790
+ key: sections.length ? "__other" : "__main",
17791
+ collapsible: false,
17792
+ collapsed: false,
17793
+ fields: leftovers
17794
+ });
17795
+ return {
17796
+ sections: sections.filter((s) => s.fields.length > 0).map((s) => ({
17797
+ ...s,
17798
+ fields: fillRows(s.fields)
17799
+ })),
17800
+ sidebar,
17801
+ showRecordMeta,
17802
+ hasRail: sidebar.length > 0 || showRecordMeta
17803
+ };
17804
+ }
17805
+ //#endregion
17250
17806
  //#region src/collections/navigation_utils.ts
17251
17807
  function removeInitialAndTrailingSlashes(s) {
17252
17808
  return removeInitialSlash(removeTrailingSlash(s));
@@ -17458,115 +18014,6 @@ function getParentReferencesFromPath(props) {
17458
18014
  return result;
17459
18015
  }
17460
18016
  //#endregion
17461
- //#region src/collections/property_presentation.ts
17462
- function isReadOnly(property) {
17463
- if (property.admin?.readOnly) return true;
17464
- if (property.type === "date") {
17465
- if (property.autoValue) return true;
17466
- }
17467
- if (property.type === "reference") return !property.path && !("Field" in (property.admin || {}) && property.admin?.Field);
17468
- return false;
17469
- }
17470
- function isHidden(property) {
17471
- return typeof property.admin?.disabled === "object" && Boolean(property.admin?.disabled.hidden);
17472
- }
17473
- function applyPropertyConditions(property, context) {
17474
- const { conditions } = property;
17475
- if (!conditions) return property;
17476
- const result = { ...property };
17477
- if (conditions.disabled) {
17478
- if (evaluateCondition(conditions.disabled, context)) {
17479
- result.admin = result.admin || {};
17480
- result.admin.disabled = {
17481
- clearOnDisabled: conditions.clearOnDisabled ?? false,
17482
- disabledMessage: conditions.disabledMessage,
17483
- hidden: false
17484
- };
17485
- }
17486
- }
17487
- if (conditions.hidden) {
17488
- if (evaluateCondition(conditions.hidden, context)) {
17489
- result.admin = result.admin || {};
17490
- result.admin.disabled = {
17491
- ...typeof result.admin?.disabled === "object" ? result.admin.disabled : {},
17492
- hidden: true,
17493
- clearOnDisabled: conditions.clearOnDisabled ?? false
17494
- };
17495
- }
17496
- }
17497
- if (conditions.readOnly) {
17498
- if (evaluateCondition(conditions.readOnly, context)) {
17499
- result.admin = result.admin || {};
17500
- result.admin.readOnly = true;
17501
- }
17502
- }
17503
- if (conditions.required !== void 0) {
17504
- const isRequired = evaluateCondition(conditions.required, context);
17505
- result.validation = {
17506
- ...result.validation,
17507
- required: isRequired,
17508
- requiredMessage: conditions.requiredMessage
17509
- };
17510
- }
17511
- if (context.isNew && conditions.defaultValue !== void 0) result.defaultValue = evaluateCondition(conditions.defaultValue, context);
17512
- if ("enum" in result && result.enum && (conditions.enumConditions || conditions.allowedEnumValues || conditions.excludedEnumValues)) result.enum = applyEnumConditions(result.enum, conditions, context);
17513
- if (result.type === "reference") {
17514
- if (conditions.referencePath) result.path = evaluateCondition(conditions.referencePath, context);
17515
- if (conditions.referenceFilter) {
17516
- result.admin = result.admin || {};
17517
- result.admin.fixedFilter = evaluateCondition(conditions.referenceFilter, context);
17518
- }
17519
- }
17520
- if (result.type === "array") {
17521
- if (conditions.canAddElements !== void 0) {
17522
- result.admin = result.admin || {};
17523
- result.admin.canAddElements = evaluateCondition(conditions.canAddElements, context);
17524
- }
17525
- if (conditions.sortable !== void 0) {
17526
- result.admin = result.admin || {};
17527
- result.admin.sortable = evaluateCondition(conditions.sortable, context);
17528
- }
17529
- }
17530
- return result;
17531
- }
17532
- /**
17533
- * Convert an object with numeric keys back to an array.
17534
- * Firestore stores arrays as {"0": "a", "1": "b"} to avoid nested arrays.
17535
- */
17536
- function objectToArray(obj) {
17537
- if (Array.isArray(obj)) return obj.map(String);
17538
- if (obj && typeof obj === "object") {
17539
- const keys = Object.keys(obj);
17540
- if (keys.length > 0 && keys.every((k) => !isNaN(Number(k)))) return keys.sort((a, b) => Number(a) - Number(b)).map((k) => obj[k]).filter((v) => typeof v === "string" || typeof v === "number").map(String);
17541
- }
17542
- return [];
17543
- }
17544
- /**
17545
- * Apply enum-specific conditions to filter and modify enum values.
17546
- */
17547
- function applyEnumConditions(enumValues, conditions, context) {
17548
- let result = [...enumValues];
17549
- if (conditions.allowedEnumValues) {
17550
- const allowedArray = objectToArray(evaluateCondition(conditions.allowedEnumValues, context));
17551
- if (allowedArray.length > 0) result = result.filter((ev) => allowedArray.includes(String(ev.id)));
17552
- }
17553
- if (conditions.excludedEnumValues) {
17554
- const excludedArray = objectToArray(evaluateCondition(conditions.excludedEnumValues, context));
17555
- if (excludedArray.length > 0) result = result.filter((ev) => !excludedArray.includes(String(ev.id)));
17556
- }
17557
- if (conditions.enumConditions) result = result.map((ev) => {
17558
- const evConditions = conditions.enumConditions?.[ev.id];
17559
- if (!evConditions) return ev;
17560
- if (evConditions.hidden && evaluateCondition(evConditions.hidden, context)) return null;
17561
- if (evConditions.disabled && evaluateCondition(evConditions.disabled, context)) return {
17562
- ...ev,
17563
- disabled: true
17564
- };
17565
- return ev;
17566
- }).filter((ev) => ev !== null);
17567
- return result;
17568
- }
17569
- //#endregion
17570
18017
  //#region src/collections/title-property.ts
17571
18018
  /**
17572
18019
  * How good a property is as the human-readable title of an entity.
@@ -17600,7 +18047,7 @@ var SCORE = {
17600
18047
  * This is a *bonus* on top of the structural rules — never a requirement, and
17601
18048
  * never the mechanism that keeps identifiers out of the title slot.
17602
18049
  */
17603
- var TITLE_LIKE_KEYS = new Set([
18050
+ var TITLE_LIKE_KEYS = /* @__PURE__ */ new Set([
17604
18051
  "name",
17605
18052
  "fullname",
17606
18053
  "displayname",
@@ -17730,6 +18177,40 @@ function getTitlePropertyCandidates(collection) {
17730
18177
  return scored.map((candidate) => candidate.key);
17731
18178
  }
17732
18179
  /**
18180
+ * The relation a collection *leads* with, if it leads with one.
18181
+ *
18182
+ * A junction-shaped collection — a pipeline entry, a membership, a booking —
18183
+ * holds no label of its own: it is "this candidate, for that vacancy". The
18184
+ * general ranking puts relations last (they only read once the target
18185
+ * resolves), so the title slot would otherwise fall to whatever free text
18186
+ * happens to follow: a note, a comment. Preview surfaces that render one row
18187
+ * per entity (list, cards, board) prefer the leading relation instead.
18188
+ *
18189
+ * The decision is structural — the first property that could be a title, in the
18190
+ * order the developer declared (or ordered) them. Declaration order is a
18191
+ * statement about what the collection is about; property *names* are not
18192
+ * consulted here.
18193
+ *
18194
+ * Returns `undefined` when that first property is anything but a
18195
+ * single-cardinality relation, or when the collection states its own
18196
+ * `titleProperty`.
18197
+ *
18198
+ * @group Collections
18199
+ */
18200
+ function getLeadingRelationTitleKey(collection) {
18201
+ if (!collection.properties) return void 0;
18202
+ if (collection.titleProperty) return void 0;
18203
+ const idKeys = new Set(getPrimaryKeys(collection));
18204
+ const foreignKeys = getForeignKeyColumns(collection);
18205
+ const order = collection.propertiesOrder ?? Object.keys(collection.properties);
18206
+ for (const key of order) {
18207
+ const property = collection.properties[key];
18208
+ if (!property || isPropertyBuilder(property)) continue;
18209
+ if (scoreTitleCandidate(property, key, idKeys, foreignKeys) === SCORE.DISQUALIFIED) continue;
18210
+ return property.type === "relation" ? key : void 0;
18211
+ }
18212
+ }
18213
+ /**
17733
18214
  * The property that should fill the title slot for a collection, ignoring any
17734
18215
  * concrete values. Prefer {@link getTitlePropertyKeyForValues} when an entity
17735
18216
  * is at hand — it can skip candidates that happen to be empty or to hold an id.
@@ -17779,6 +18260,6 @@ function getTitlePropertyKeyForValues(collection, values, entityId) {
17779
18260
  return candidates[0];
17780
18261
  }
17781
18262
  //#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 };
18263
+ export { AIIcon, AIModifiedIndicator, AdminModeControllerContext, AdminModeControllerProvider, AnalyticsContext, ApiConfigProvider, 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, SIDE_PANEL_DEFAULT_WIDTH, 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, deriveSpan, en, es, fetchAuthConfig, fillRows, flattenKeys, getAdminEntityChildViews, getAdminSubcollections, getCollectionBySlugWithin, getCollectionPathsCombinations, getColorScheme, getColumnKeysForProperty, getEntityFromCache, getEntityFromMemoryCache, getEntityImagePreviewPropertyKey, getEntityPreviewKeys, getEntityTitlePropertyKey, getFormFieldKeys, getIcon, getLastSegment, getLeadingRelationTitleKey, getLocalChangesBackup, getNavigationEntriesFromPath, getParentReferencesFromPath, getRelationIncludeParams, getRowHeight, getSubcollectionColumnId, getTitlePropertyCandidates, getTitlePropertyKey, getTitlePropertyKeyForValues, iconsSearch, isAuditTimestamp, isEnumValueDisabled, isFilterableRelation, isHidden, isIdPropertyEditable, isReadOnly, isSchemaDriftError, looksLikeIdentifierValue, populateFetchCache, removeEntityFromCache, removeEntityFromMemoryCache, removeInitialAndTrailingSlashes, removeInitialSlash, removeTrailingSlash, resolveCollectionPathIds, resolveComponentRef, resolveDefaultSelectedView, resolveFilterOperators, resolveFormLayout, 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
18264
 
17784
18265
  //# sourceMappingURL=index.es.js.map