@rebasepro/app 0.20.0 → 0.21.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,15 +1,4 @@
1
1
  import type { RebaseProps } from "./RebaseProps.js";
2
2
  import React from "react";
3
3
  import { User } from "@rebasepro/types";
4
- /**
5
- * If you are using independent components of the admin
6
- * you need to wrap them with this main component, so the internal hooks work.
7
- *
8
- * This is the main component of Rebase. It acts as the provider of all the
9
- * internal contexts and hooks.
10
- *
11
- * You only need to use this component if you are building a custom app.
12
- *
13
- * @group Core
14
- */
15
4
  export declare function Rebase<USER extends User, DB = unknown>(props: RebaseProps<USER, DB>): React.JSX.Element;
@@ -220,7 +220,11 @@ export type RebaseProps<USER extends User, DB = unknown> = {
220
220
  databaseAdmin?: DatabaseAdmin;
221
221
  /**
222
222
  * Use this controller to access the configuration that is stored locally,
223
- * and not defined in code
223
+ * and not defined in code.
224
+ *
225
+ * Optional: when omitted the panel builds a localStorage-backed store of
226
+ * its own, so column widths, column order and the view mode a collection
227
+ * was left in survive without the host app wiring anything.
224
228
  */
225
229
  userConfigPersistence?: UserConfigurationPersistence;
226
230
  /**
@@ -1,4 +1,5 @@
1
1
  import React from "react";
2
+ import { type ChipColorKey } from "@rebasepro/ui";
2
3
  interface TaskEntity {
3
4
  id: string;
4
5
  values: {
@@ -44,7 +45,7 @@ export interface TaskTableProps {
44
45
  }
45
46
  export declare const resolutionDisplay: Record<string, {
46
47
  label: string;
47
- colorScheme: string;
48
+ colorScheme: ChipColorKey;
48
49
  }>;
49
50
  export declare function TaskTable({ tasks, loading, pendingTasks, visiblePendingTasks, hasMorePending, onLoadMorePending, pendingCount, togglingIds, onToggleTask, onOpenTask, onOpenClient, clientsMap, stageLabels, recentlyToggledIds, completedTasks, completedLoaded, loadingCompleted, completedHasMore, onExpandCompleted, onLoadMoreCompleted }: TaskTableProps): React.JSX.Element;
50
51
  export {};
package/dist/debug.js CHANGED
@@ -892,7 +892,7 @@ import {
892
892
  import { Fragment as Fragment4, jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
893
893
  var resolutionDisplay = {
894
894
  verified: { label: "Verified", colorScheme: "green" },
895
- needs_followup: { label: "Needs Follow-up", colorScheme: "amber" },
895
+ needs_followup: { label: "Needs Follow-up", colorScheme: "yellow" },
896
896
  suitable: { label: "Suitable", colorScheme: "green" },
897
897
  not_a_fit: { label: "Not a Fit", colorScheme: "red" },
898
898
  response_received: { label: "Response Received", colorScheme: "green" },
@@ -903,13 +903,13 @@ var resolutionDisplay = {
903
903
  signed: { label: "Signed", colorScheme: "green" },
904
904
  reminder_sent: { label: "Reminder Sent", colorScheme: "blue" },
905
905
  payment_confirmed: { label: "Payment Confirmed", colorScheme: "green" },
906
- not_yet_received: { label: "Not Yet Received", colorScheme: "amber" },
906
+ not_yet_received: { label: "Not Yet Received", colorScheme: "yellow" },
907
907
  sent: { label: "Sent", colorScheme: "green" },
908
908
  confirmed: { label: "Confirmed", colorScheme: "green" },
909
- not_yet: { label: "Not Yet", colorScheme: "amber" },
909
+ not_yet: { label: "Not Yet", colorScheme: "yellow" },
910
910
  scheduled: { label: "Scheduled", colorScheme: "green" },
911
911
  feedback_received: { label: "Feedback Received", colorScheme: "green" },
912
- awaiting_response: { label: "Awaiting Response", colorScheme: "amber" },
912
+ awaiting_response: { label: "Awaiting Response", colorScheme: "yellow" },
913
913
  archived: { label: "Archived", colorScheme: "green" },
914
914
  done: { label: "Done", colorScheme: "green" }
915
915
  };
@@ -1538,7 +1538,7 @@ function CalendarWidget({ loading, tasks, onOpenTask }) {
1538
1538
  onClick: () => setSelectedDay(isSelected ? null : day.dateKey),
1539
1539
  className: cls5(
1540
1540
  "flex flex-col items-center justify-center py-1.5 rounded-md transition-colors duration-100 focus:outline-none",
1541
- day.isCurrentMonth ? "text-text-primary dark:text-text-primary-dark" : "text-surface-300 dark:text-surface-650",
1541
+ day.isCurrentMonth ? "text-text-primary dark:text-text-primary-dark" : "text-surface-300 dark:text-surface-600",
1542
1542
  day.isToday && !isSelected && "ring-1 ring-primary/50",
1543
1543
  isSelected ? "bg-primary/10 dark:bg-primary/15 ring-1 ring-primary/60" : "hover:bg-surface-hover",
1544
1544
  hasTasks && "cursor-pointer"
@@ -2136,7 +2136,7 @@ function CrmDashboardDemo() {
2136
2136
  ] }),
2137
2137
  /* @__PURE__ */ jsxs10("div", { children: [
2138
2138
  /* @__PURE__ */ jsx10(Typography8, { variant: "caption", color: "secondary", className: "uppercase text-[9px] tracking-wider block", children: "Priority" }),
2139
- /* @__PURE__ */ jsx10(Typography8, { variant: "body2", className: "font-medium mt-0.5", children: task.values.priority === "high" ? /* @__PURE__ */ jsx10("span", { className: "text-red-500 font-semibold uppercase text-xs", children: "High" }) : task.values.priority === "medium" ? /* @__PURE__ */ jsx10("span", { className: "text-amber-500 font-semibold uppercase text-xs", children: "Medium" }) : /* @__PURE__ */ jsx10("span", { className: "text-surface-450 dark:text-surface-500 uppercase text-xs", children: "Low" }) })
2139
+ /* @__PURE__ */ jsx10(Typography8, { variant: "body2", className: "font-medium mt-0.5", children: task.values.priority === "high" ? /* @__PURE__ */ jsx10("span", { className: "text-red-500 font-semibold uppercase text-xs", children: "High" }) : task.values.priority === "medium" ? /* @__PURE__ */ jsx10("span", { className: "text-amber-500 font-semibold uppercase text-xs", children: "Medium" }) : /* @__PURE__ */ jsx10("span", { className: "text-surface-500 uppercase text-xs", children: "Low" }) })
2140
2140
  ] })
2141
2141
  ] }),
2142
2142
  clientInfo && /* @__PURE__ */ jsxs10("div", { children: [
@@ -1,18 +1,3 @@
1
1
  import type { SlotName, SlotRegistry } from "@rebasepro/cms-types";
2
2
  import React from "react";
3
- /**
4
- * Hook that retrieves and renders all slot contributions for a given slot name.
5
- *
6
- * @param slot - The slot name to render contributions for.
7
- * @param props - Props passed to each slot component.
8
- * @returns An array of rendered React nodes, each wrapped in an ErrorBoundary.
9
- *
10
- * @example
11
- * ```tsx
12
- * const actions = useSlot("home.actions", { context });
13
- * return <div>{actions}</div>;
14
- * ```
15
- *
16
- * @group Hooks
17
- */
18
3
  export declare function useSlot<K extends SlotName>(slot: K, props: SlotRegistry[K]): React.ReactNode[];
package/dist/index.es.js CHANGED
@@ -1971,22 +1971,26 @@ function useBrowserTitleAndIcon(name, logo) {
1971
1971
  *
1972
1972
  * @group Hooks
1973
1973
  */
1974
+ /**
1975
+ * Are these two prop objects the same, one level down?
1976
+ *
1977
+ * Its own function so the comparison can be typed on `object` rather than on
1978
+ * the slot's props. `SlotRegistry[K]` is a union of interfaces, and an
1979
+ * interface has no implicit index signature, so reading it as
1980
+ * `Record<string, unknown>` — which the loop this replaces did, to both
1981
+ * arguments — is a conversion tsc refuses and `as unknown as` was suppressing.
1982
+ * `Object.keys` needs no such claim.
1983
+ */
1984
+ function shallowEqual(a, b) {
1985
+ if (a === b) return true;
1986
+ const keys = Object.keys(a);
1987
+ if (keys.length !== Object.keys(b).length) return false;
1988
+ return keys.every((key) => a[key] === b[key]);
1989
+ }
1974
1990
  function useSlot(slot, props) {
1975
1991
  const { resolvedSlots } = useCustomizationController();
1976
1992
  const propsRef = React.useRef(props);
1977
- const currentProps = props;
1978
- const prevProps = propsRef.current;
1979
- let changed = false;
1980
- if (currentProps !== prevProps) {
1981
- const keys = Object.keys(currentProps);
1982
- const prevKeys = Object.keys(prevProps);
1983
- if (keys.length !== prevKeys.length) changed = true;
1984
- else for (let i = 0; i < keys.length; i++) if (currentProps[keys[i]] !== prevProps[keys[i]]) {
1985
- changed = true;
1986
- break;
1987
- }
1988
- }
1989
- if (changed) propsRef.current = props;
1993
+ if (!shallowEqual(props, propsRef.current)) propsRef.current = props;
1990
1994
  const stableProps = propsRef.current;
1991
1995
  return useMemo(() => {
1992
1996
  return resolvedSlots.filter((s) => s.slot === slot).sort((a, b) => (a.order ?? 50) - (b.order ?? 50)).map((s, i) => {
@@ -2017,12 +2021,13 @@ function useBuildLocalConfigurationPersistence() {
2017
2021
  if (configCache.current[storageKey]) return configCache.current[storageKey];
2018
2022
  return getCollectionFromStorage(storageKey);
2019
2023
  }, [getCollectionFromStorage]);
2024
+ const [configVersion, setConfigVersion] = useState(0);
2020
2025
  const onCollectionModified = useCallback((path, data) => {
2021
2026
  const storageKey = `collection_config::${stripCollectionPath(path)}`;
2022
- writeStoredJson(storageKey, data);
2023
- const cachedConfig = configCache.current[storageKey];
2024
- const newConfig = mergeDeep(cachedConfig ?? getCollectionFromStorage(storageKey), data);
2025
- configCache.current[storageKey] = mergeDeep(configCache.current[storageKey], newConfig);
2027
+ const merged = mergeDeep(configCache.current[storageKey] ?? getCollectionFromStorage(storageKey), data);
2028
+ configCache.current[storageKey] = merged;
2029
+ writeStoredJson(storageKey, merged);
2030
+ setConfigVersion((version) => version + 1);
2026
2031
  }, [getCollectionFromStorage]);
2027
2032
  const [recentlyVisitedPaths, _setRecentlyVisitedPaths] = useState([]);
2028
2033
  const [favouritePaths, _setFavouritePaths] = useState([]);
@@ -2058,6 +2063,7 @@ function useBuildLocalConfigurationPersistence() {
2058
2063
  collapsedGroups,
2059
2064
  setCollapsedGroups
2060
2065
  }), [
2066
+ configVersion,
2061
2067
  onCollectionModified,
2062
2068
  getCollectionConfig,
2063
2069
  recentlyVisitedPaths,
@@ -4806,7 +4812,7 @@ function LoginView({ logo, authController, noUserComponent, disableSignupScreen
4806
4812
  ]
4807
4813
  })]
4808
4814
  }), /* @__PURE__ */ jsxs("div", {
4809
- className: "relative flex flex-col items-center w-[440px] max-w-full p-8 sm:p-10 bg-surface-card/70 backdrop-blur-xl border border-hairline-strong rounded-2xl shadow-2xl z-10 transition-all duration-300 hover:shadow-primary-500/5",
4815
+ className: "relative flex flex-col items-center w-[440px] max-w-full p-8 sm:p-10 bg-surface-card/70 backdrop-blur-xl border border-hairline-strong rounded-2xl shadow-2xl z-10 transition-all duration-300 hover:shadow-primary/5",
4810
4816
  children: [
4811
4817
  /* @__PURE__ */ jsx("div", {
4812
4818
  className: "w-24 h-24 m-2 mb-4 drop-shadow-md",
@@ -4897,7 +4903,7 @@ function LoginView({ logo, authController, noUserComponent, disableSignupScreen
4897
4903
  " ",
4898
4904
  /* @__PURE__ */ jsx("button", {
4899
4905
  type: "button",
4900
- className: "font-semibold hover:underline cursor-pointer text-primary-600 dark:text-primary-400",
4906
+ className: "font-semibold hover:underline cursor-pointer text-primary dark:text-primary-light",
4901
4907
  onClick: () => switchMode("register"),
4902
4908
  children: "Create one"
4903
4909
  })
@@ -5225,7 +5231,7 @@ function LoginForm({ onClose, onForgotPassword, authController, registrationMode
5225
5231
  className: "w-full text-right mb-3",
5226
5232
  children: /* @__PURE__ */ jsx("button", {
5227
5233
  type: "button",
5228
- className: "text-xs font-medium hover:underline cursor-pointer text-primary-600 dark:text-primary-400",
5234
+ className: "text-xs font-medium hover:underline cursor-pointer text-primary dark:text-primary-light",
5229
5235
  onClick: onForgotPassword,
5230
5236
  children: "Forgot password?"
5231
5237
  })
@@ -5263,7 +5269,7 @@ function LoginForm({ onClose, onForgotPassword, authController, registrationMode
5263
5269
  " ",
5264
5270
  /* @__PURE__ */ jsx("button", {
5265
5271
  type: "button",
5266
- className: "font-semibold hover:underline cursor-pointer text-primary-600 dark:text-primary-400",
5272
+ className: "font-semibold hover:underline cursor-pointer text-primary dark:text-primary-light",
5267
5273
  onClick: switchToRegister,
5268
5274
  children: "Create one"
5269
5275
  })
@@ -5280,7 +5286,7 @@ function LoginForm({ onClose, onForgotPassword, authController, registrationMode
5280
5286
  " ",
5281
5287
  /* @__PURE__ */ jsx("button", {
5282
5288
  type: "button",
5283
- className: "font-semibold hover:underline cursor-pointer text-primary-600 dark:text-primary-400",
5289
+ className: "font-semibold hover:underline cursor-pointer text-primary dark:text-primary-light",
5284
5290
  onClick: switchToLogin,
5285
5291
  children: "Sign in"
5286
5292
  })
@@ -5876,6 +5882,20 @@ var en = {
5876
5882
  some_entities_deleted: "Some of the entities have been deleted, but not all",
5877
5883
  error_deleting_entities: "Error deleting entities",
5878
5884
  deleted: "Deleted",
5885
+ selection_options: "Selection options",
5886
+ selection_menu_all_loaded: "All on this page",
5887
+ selection_menu_all_matching: "All {{total}} {{collection}}",
5888
+ selection_menu_none: "None",
5889
+ selection_select_all_loaded: "Select all loaded rows",
5890
+ selection_deselect_all: "Deselect all",
5891
+ selection_reading_rows: "Reading rows… {{loaded}} of {{total}}",
5892
+ selection_reading_rows_unknown: "Reading rows… {{loaded}} so far",
5893
+ selection_deleting_progress: "Deleted {{completed}} of {{total}}",
5894
+ confirm_delete_selection: "Delete {{total}} {{collection}}?",
5895
+ confirm_delete_selection_unknown: "Delete every row matching the current filter?",
5896
+ confirm_delete_selection_body: "This cannot be undone. Each row is deleted individually, so this may take a while.",
5897
+ export_selection_count: "Download the {{total}} selected rows as a {{format}}",
5898
+ export_selection_all_matching: "Download every {{collection}} matching the current filter",
5879
5899
  select_reference: "Select reference",
5880
5900
  select_references: "Select references",
5881
5901
  account_settings: "Account Settings",
@@ -6342,8 +6362,6 @@ var en = {
6342
6362
  storage_save_url: "Save URL instead of storage path",
6343
6363
  datetime_automatic_value: "Automatic value",
6344
6364
  markdown_paste_behavior: "Paste behavior",
6345
- markdown_strip_html: "Strip HTML on paste",
6346
- markdown_convert_pasted: "Convert pasted text to markdown",
6347
6365
  entity_saved: "Saved",
6348
6366
  more_actions: "More actions",
6349
6367
  record_history: "History",
@@ -6876,6 +6894,20 @@ var es = {
6876
6894
  some_entities_deleted: "Algunas entidades han sido eliminadas, pero no todas",
6877
6895
  error_deleting_entities: "Error al eliminar entidades",
6878
6896
  deleted: "eliminado",
6897
+ selection_options: "Opciones de selección",
6898
+ selection_menu_all_loaded: "Todo en esta página",
6899
+ selection_menu_all_matching: "Los {{total}} {{collection}}",
6900
+ selection_menu_none: "Ninguno",
6901
+ selection_select_all_loaded: "Seleccionar las filas cargadas",
6902
+ selection_deselect_all: "Deseleccionar todo",
6903
+ selection_reading_rows: "Leyendo filas… {{loaded}} de {{total}}",
6904
+ selection_reading_rows_unknown: "Leyendo filas… {{loaded}} hasta ahora",
6905
+ selection_deleting_progress: "Eliminados {{completed}} de {{total}}",
6906
+ confirm_delete_selection: "¿Eliminar {{total}} {{collection}}?",
6907
+ confirm_delete_selection_unknown: "¿Eliminar todas las filas que coinciden con el filtro actual?",
6908
+ confirm_delete_selection_body: "Esta acción no se puede deshacer. Cada fila se elimina por separado, así que puede tardar un rato.",
6909
+ export_selection_count: "Descargar las {{total}} filas seleccionadas en {{format}}",
6910
+ export_selection_all_matching: "Descargar todos los {{collection}} que coinciden con el filtro actual",
6879
6911
  select_reference: "Seleccionar referencia",
6880
6912
  select_references: "Seleccionar referencias",
6881
6913
  account_settings: "Configuración de la cuenta",
@@ -7342,8 +7374,6 @@ var es = {
7342
7374
  storage_save_url: "Guardar URL en lugar de la ruta de almacenamiento",
7343
7375
  datetime_automatic_value: "Valor automático",
7344
7376
  markdown_paste_behavior: "Comportamiento al pegar",
7345
- markdown_strip_html: "Eliminar HTML al pegar",
7346
- markdown_convert_pasted: "Convertir texto pegado a markdown",
7347
7377
  entity_saved: "Guardado",
7348
7378
  more_actions: "Más acciones",
7349
7379
  record_history: "Historial",
@@ -7868,6 +7898,20 @@ var de = {
7868
7898
  some_entities_deleted: "Einige der Entitäten wurden gelöscht, aber nicht alle",
7869
7899
  error_deleting_entities: "Fehler beim Löschen der Entitäten",
7870
7900
  deleted: "gelöscht",
7901
+ selection_options: "Auswahloptionen",
7902
+ selection_menu_all_loaded: "Alle auf dieser Seite",
7903
+ selection_menu_all_matching: "Alle {{total}} {{collection}}",
7904
+ selection_menu_none: "Keine",
7905
+ selection_select_all_loaded: "Geladene Zeilen auswählen",
7906
+ selection_deselect_all: "Alle abwählen",
7907
+ selection_reading_rows: "Zeilen werden gelesen… {{loaded}} von {{total}}",
7908
+ selection_reading_rows_unknown: "Zeilen werden gelesen… bisher {{loaded}}",
7909
+ selection_deleting_progress: "{{completed}} von {{total}} gelöscht",
7910
+ confirm_delete_selection: "{{total}} {{collection}} löschen?",
7911
+ confirm_delete_selection_unknown: "Alle Zeilen löschen, die dem aktuellen Filter entsprechen?",
7912
+ confirm_delete_selection_body: "Dies kann nicht rückgängig gemacht werden. Jede Zeile wird einzeln gelöscht, das kann eine Weile dauern.",
7913
+ export_selection_count: "Die {{total}} ausgewählten Zeilen als {{format}} herunterladen",
7914
+ export_selection_all_matching: "Alle {{collection}}, die dem aktuellen Filter entsprechen, herunterladen",
7871
7915
  select_reference: "Referenz auswählen",
7872
7916
  select_references: "Referenzen auswählen",
7873
7917
  account_settings: "Kontoeinstellungen",
@@ -8334,8 +8378,6 @@ var de = {
8334
8378
  storage_save_url: "URL anstelle des Speicherpfads speichern",
8335
8379
  datetime_automatic_value: "Automatischer Wert",
8336
8380
  markdown_paste_behavior: "Einfügeverhalten",
8337
- markdown_strip_html: "HTML beim Einfügen entfernen",
8338
- markdown_convert_pasted: "Eingefügten Text in Markdown umwandeln",
8339
8381
  entity_saved: "Gespeichert",
8340
8382
  more_actions: "Weitere Aktionen",
8341
8383
  record_history: "Verlauf",
@@ -8860,6 +8902,20 @@ var fr = {
8860
8902
  some_entities_deleted: "Certaines des entités ont été supprimées, mais pas toutes",
8861
8903
  error_deleting_entities: "Erreur lors de la suppression des entités",
8862
8904
  deleted: "supprimé",
8905
+ selection_options: "Options de sélection",
8906
+ selection_menu_all_loaded: "Tout sur cette page",
8907
+ selection_menu_all_matching: "Les {{total}} {{collection}}",
8908
+ selection_menu_none: "Aucun",
8909
+ selection_select_all_loaded: "Sélectionner les lignes chargées",
8910
+ selection_deselect_all: "Tout désélectionner",
8911
+ selection_reading_rows: "Lecture des lignes… {{loaded}} sur {{total}}",
8912
+ selection_reading_rows_unknown: "Lecture des lignes… {{loaded}} jusqu’à présent",
8913
+ selection_deleting_progress: "{{completed}} supprimés sur {{total}}",
8914
+ confirm_delete_selection: "Supprimer {{total}} {{collection}} ?",
8915
+ confirm_delete_selection_unknown: "Supprimer toutes les lignes correspondant au filtre actuel ?",
8916
+ confirm_delete_selection_body: "Cette action est irréversible. Chaque ligne est supprimée séparément, l’opération peut donc prendre du temps.",
8917
+ export_selection_count: "Télécharger les {{total}} lignes sélectionnées au format {{format}}",
8918
+ export_selection_all_matching: "Télécharger tous les {{collection}} correspondant au filtre actuel",
8863
8919
  select_reference: "Sélectionner une référence",
8864
8920
  select_references: "Sélectionner des références",
8865
8921
  account_settings: "Paramètres du compte",
@@ -9326,8 +9382,6 @@ var fr = {
9326
9382
  storage_save_url: "Enregistrer l'URL au lieu du chemin de stockage",
9327
9383
  datetime_automatic_value: "Valeur automatique",
9328
9384
  markdown_paste_behavior: "Comportement au collage",
9329
- markdown_strip_html: "Supprimer le HTML au collage",
9330
- markdown_convert_pasted: "Convertir le texte collé en markdown",
9331
9385
  entity_saved: "Enregistré",
9332
9386
  more_actions: "Plus d'actions",
9333
9387
  record_history: "Historique",
@@ -9852,6 +9906,20 @@ var it = {
9852
9906
  some_entities_deleted: "Alcune entità sono state eliminate, ma non tutte",
9853
9907
  error_deleting_entities: "Errore durante l'eliminazione delle entità",
9854
9908
  deleted: "eliminata",
9909
+ selection_options: "Opzioni di selezione",
9910
+ selection_menu_all_loaded: "Tutto in questa pagina",
9911
+ selection_menu_all_matching: "Tutti i {{total}} {{collection}}",
9912
+ selection_menu_none: "Nessuno",
9913
+ selection_select_all_loaded: "Seleziona le righe caricate",
9914
+ selection_deselect_all: "Deseleziona tutto",
9915
+ selection_reading_rows: "Lettura delle righe… {{loaded}} di {{total}}",
9916
+ selection_reading_rows_unknown: "Lettura delle righe… {{loaded}} finora",
9917
+ selection_deleting_progress: "Eliminati {{completed}} di {{total}}",
9918
+ confirm_delete_selection: "Eliminare {{total}} {{collection}}?",
9919
+ confirm_delete_selection_unknown: "Eliminare tutte le righe che corrispondono al filtro attuale?",
9920
+ confirm_delete_selection_body: "L’operazione non può essere annullata. Ogni riga viene eliminata singolarmente, quindi potrebbe richiedere del tempo.",
9921
+ export_selection_count: "Scarica le {{total}} righe selezionate in formato {{format}}",
9922
+ export_selection_all_matching: "Scarica tutti i {{collection}} che corrispondono al filtro attuale",
9855
9923
  select_reference: "Seleziona riferimento",
9856
9924
  select_references: "Seleziona riferimenti",
9857
9925
  account_settings: "Impostazioni account",
@@ -10318,8 +10386,6 @@ var it = {
10318
10386
  storage_save_url: "Salva URL invece del percorso di archiviazione",
10319
10387
  datetime_automatic_value: "Valore automatico",
10320
10388
  markdown_paste_behavior: "Comportamento incolla",
10321
- markdown_strip_html: "Rimuovi HTML all'incolla",
10322
- markdown_convert_pasted: "Converti testo incollato in markdown",
10323
10389
  entity_saved: "Salvato",
10324
10390
  more_actions: "Altre azioni",
10325
10391
  record_history: "Cronologia",
@@ -10844,6 +10910,20 @@ var hi = {
10844
10910
  some_entities_deleted: "कुछ संस्थाएँ हटा दी गई हैं, लेकिन सभी नहीं",
10845
10911
  error_deleting_entities: "संस्थाओं को हटाने में त्रुटि",
10846
10912
  deleted: "हटाया गया",
10913
+ selection_options: "चयन विकल्प",
10914
+ selection_menu_all_loaded: "इस पृष्ठ पर सभी",
10915
+ selection_menu_all_matching: "सभी {{total}} {{collection}}",
10916
+ selection_menu_none: "कोई नहीं",
10917
+ selection_select_all_loaded: "लोड की गई पंक्तियाँ चुनें",
10918
+ selection_deselect_all: "सभी अचयनित करें",
10919
+ selection_reading_rows: "पंक्तियाँ पढ़ी जा रही हैं… {{total}} में से {{loaded}}",
10920
+ selection_reading_rows_unknown: "पंक्तियाँ पढ़ी जा रही हैं… अब तक {{loaded}}",
10921
+ selection_deleting_progress: "{{total}} में से {{completed}} हटाए गए",
10922
+ confirm_delete_selection: "क्या {{total}} {{collection}} हटाएँ?",
10923
+ confirm_delete_selection_unknown: "क्या वर्तमान फ़िल्टर से मेल खाने वाली सभी पंक्तियाँ हटाएँ?",
10924
+ confirm_delete_selection_body: "इसे पूर्ववत नहीं किया जा सकता। हर पंक्ति अलग-अलग हटाई जाती है, इसलिए इसमें कुछ समय लग सकता है।",
10925
+ export_selection_count: "{{total}} चयनित पंक्तियाँ {{format}} रूप में डाउनलोड करें",
10926
+ export_selection_all_matching: "वर्तमान फ़िल्टर से मेल खाने वाले सभी {{collection}} डाउनलोड करें",
10847
10927
  select_reference: "संदर्भ चुनें",
10848
10928
  select_references: "संदर्भ चुनें (एकाधिक)",
10849
10929
  account_settings: "खाता सेटिंग्स",
@@ -11310,8 +11390,6 @@ var hi = {
11310
11390
  storage_save_url: "संग्रहण पथ के बजाय URL सहेजें",
11311
11391
  datetime_automatic_value: "स्वचालित मान",
11312
11392
  markdown_paste_behavior: "पेस्ट व्यवहार",
11313
- markdown_strip_html: "पेस्ट करते समय HTML हटाएं",
11314
- markdown_convert_pasted: "पेस्ट किए गए टेक्स्ट को मार्कडाउन में बदलें",
11315
11393
  entity_saved: "सहेजा गया",
11316
11394
  more_actions: "अधिक क्रियाएँ",
11317
11395
  record_history: "इतिहास",
@@ -11841,6 +11919,20 @@ var pt = {
11841
11919
  some_entities_deleted: "Algumas entidades foram excluídas, mas não todas",
11842
11920
  error_deleting_entities: "Erro ao excluir entidades",
11843
11921
  deleted: "excluído(a)",
11922
+ selection_options: "Opções de seleção",
11923
+ selection_menu_all_loaded: "Tudo nesta página",
11924
+ selection_menu_all_matching: "Todos os {{total}} {{collection}}",
11925
+ selection_menu_none: "Nenhum",
11926
+ selection_select_all_loaded: "Selecionar as linhas carregadas",
11927
+ selection_deselect_all: "Desmarcar tudo",
11928
+ selection_reading_rows: "A ler linhas… {{loaded}} de {{total}}",
11929
+ selection_reading_rows_unknown: "A ler linhas… {{loaded}} até agora",
11930
+ selection_deleting_progress: "Eliminados {{completed}} de {{total}}",
11931
+ confirm_delete_selection: "Eliminar {{total}} {{collection}}?",
11932
+ confirm_delete_selection_unknown: "Eliminar todas as linhas que correspondem ao filtro atual?",
11933
+ confirm_delete_selection_body: "Esta ação não pode ser anulada. Cada linha é eliminada individualmente, pelo que pode demorar algum tempo.",
11934
+ export_selection_count: "Descarregar as {{total}} linhas selecionadas em {{format}}",
11935
+ export_selection_all_matching: "Descarregar todos os {{collection}} que correspondem ao filtro atual",
11844
11936
  select_reference: "Selecionar referência",
11845
11937
  select_references: "Selecionar referências",
11846
11938
  account_settings: "Definições da conta",
@@ -12307,8 +12399,6 @@ var pt = {
12307
12399
  storage_save_url: "Salvar URL em vez do caminho de armazenamento",
12308
12400
  datetime_automatic_value: "Valor automático",
12309
12401
  markdown_paste_behavior: "Comportamento ao colar",
12310
- markdown_strip_html: "Remover HTML ao colar",
12311
- markdown_convert_pasted: "Converter texto colado para markdown",
12312
12402
  entity_saved: "Guardado",
12313
12403
  more_actions: "Mais ações",
12314
12404
  record_history: "Histórico",
@@ -12500,6 +12590,21 @@ function buildResources(translations) {
12500
12590
  *
12501
12591
  * @group Core
12502
12592
  */
12593
+ /**
12594
+ * Does this socket carry the admin surface?
12595
+ *
12596
+ * `RebaseWebSocket` declares none of `DatabaseAdmin`'s methods — the SQL console
12597
+ * is served over the same socket only when the backend enables it — so the
12598
+ * question is genuinely a runtime one. It used to be asked as
12599
+ * `typeof (ws as unknown as Record<string, unknown>).executeSql === "function"`
12600
+ * and then answered a second time, one line down, by asserting the whole socket
12601
+ * to `DatabaseAdmin`: a check and a claim, with nothing connecting them. A
12602
+ * predicate makes the check *be* the narrowing, so the five method reads below
12603
+ * are checked against the interface they came from.
12604
+ */
12605
+ function canExecuteSql(ws) {
12606
+ return typeof ws.executeSql === "function";
12607
+ }
12503
12608
  function Rebase(props) {
12504
12609
  const { children, entityLinkBuilder, userConfigPersistence, dateTimeFormat, locale, client, authController: authControllerProp, storageSource: storageSourceProp, dataSources: dataSourcesProp, storageSources: storageSourcesProp, databaseAdmin, plugins: pluginsProp, slots: directSlots = [], onAnalyticsEvent, propertyConfigs, entityViews, collectionViews, entityActions, effectiveRoleController, apiUrl, translations, components: componentsProp } = props;
12505
12610
  const plugins = pluginsProp;
@@ -12507,6 +12612,8 @@ function Rebase(props) {
12507
12612
  const keys = plugins.map((p) => p.key);
12508
12613
  if (new Set(keys).size !== keys.length) console.error("Duplicate plugin keys detected:", keys.filter((k, i) => keys.indexOf(k) !== i));
12509
12614
  }
12615
+ const localUserConfigPersistence = useBuildLocalConfigurationPersistence();
12616
+ const resolvedUserConfigPersistence = userConfigPersistence ?? localUserConfigPersistence;
12510
12617
  const resolvedSlots = useMemo(() => [...directSlots, ...(plugins ?? []).flatMap((p) => p.slots ?? [])], [directSlots, plugins]);
12511
12618
  useEffect(() => {
12512
12619
  const dead = new Set(UNRENDERED_SLOTS);
@@ -12632,7 +12739,7 @@ function Rebase(props) {
12632
12739
  const defaultDriver = normalizedDataSources.find((d) => d.key === DEFAULT_DATA_SOURCE_KEY && d.driver)?.driver ?? (!client && normalizedDataSources.length === 1 ? normalizedDataSources[0].driver : void 0);
12633
12740
  if (defaultDriver?.admin) return defaultDriver.admin;
12634
12741
  const ws = client?.ws;
12635
- if (ws && typeof ws.executeSql === "function") {
12742
+ if (ws && canExecuteSql(ws)) {
12636
12743
  const wsAdmin = ws;
12637
12744
  return {
12638
12745
  executeSql: wsAdmin.executeSql.bind(wsAdmin),
@@ -12708,7 +12815,7 @@ function Rebase(props) {
12708
12815
  children: /* @__PURE__ */ jsx(CustomizationControllerContext.Provider, {
12709
12816
  value: customizationController,
12710
12817
  children: /* @__PURE__ */ jsx(UserConfigurationPersistenceContext.Provider, {
12711
- value: userConfigPersistence,
12818
+ value: resolvedUserConfigPersistence,
12712
12819
  children: /* @__PURE__ */ jsx(StorageSourcesContext.Provider, {
12713
12820
  value: storageSourcesValue,
12714
12821
  children: /* @__PURE__ */ jsx(StorageSourceContext.Provider, {