@rebasepro/app 0.11.1-canary.gfadf355 → 0.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/LoginView/LoginView.d.ts +9 -1
- package/dist/components/RebaseAuth.d.ts +2 -2
- package/dist/core/RebaseProps.d.ts +2 -5
- package/dist/hooks/useRebaseRegistry.d.ts +2 -2
- package/dist/index.es.js +55 -12
- package/dist/index.es.js.map +1 -1
- package/package.json +7 -7
- package/src/collections/property_presentation.ts +9 -4
- package/src/collections/title-property.ts +2 -2
- package/src/components/LoginView/LoginView.tsx +61 -5
- package/src/components/RebaseAuth.tsx +2 -2
- package/src/core/RebaseProps.tsx +2 -4
- package/src/hooks/useRebaseRegistry.tsx +5 -5
- package/src/locales/de.ts +1 -0
- package/src/locales/en.ts +1 -0
- package/src/locales/es.ts +1 -0
- package/src/locales/fr.ts +1 -0
- package/src/locales/hi.ts +1 -0
- package/src/locales/it.ts +1 -0
- package/src/locales/pt.ts +1 -0
|
@@ -104,10 +104,18 @@ export interface LoginViewProps {
|
|
|
104
104
|
* Pre-fill the password field (e.g. for demo or testing environments).
|
|
105
105
|
*/
|
|
106
106
|
defaultPassword?: string;
|
|
107
|
+
/**
|
|
108
|
+
* When set, the email/password forms render a "Join the newsletter"
|
|
109
|
+
* opt-in checkbox. Called with the address that just authenticated —
|
|
110
|
+
* sign-in or registration — if the box was ticked. Wire it to whatever
|
|
111
|
+
* stores the subscription; failures are the callback's problem, the
|
|
112
|
+
* login flow never waits on it.
|
|
113
|
+
*/
|
|
114
|
+
onNewsletterOptIn?: (email: string) => void;
|
|
107
115
|
}
|
|
108
116
|
/**
|
|
109
117
|
* Generic login view component that works with any AuthControllerExtended.
|
|
110
118
|
* Feature-detects capabilities to show/hide login methods.
|
|
111
119
|
* @group Core
|
|
112
120
|
*/
|
|
113
|
-
export declare function LoginView({ logo, authController, noUserComponent, disableSignupScreen, disabled, notAllowedError, googleClientId, githubClientId, linkedinClientId, title, subtitle, needsSetup, registrationEnabled, additionalComponent, topComponent, defaultEmail, defaultPassword }: LoginViewProps): React.JSX.Element;
|
|
121
|
+
export declare function LoginView({ logo, authController, noUserComponent, disableSignupScreen, disabled, notAllowedError, googleClientId, githubClientId, linkedinClientId, title, subtitle, needsSetup, registrationEnabled, additionalComponent, topComponent, defaultEmail, defaultPassword, onNewsletterOptIn }: LoginViewProps): React.JSX.Element;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { RebaseAuthViewConfig } from "@rebasepro/admin-types";
|
|
2
2
|
/**
|
|
3
3
|
* Declarative component to configure authentication in Rebase.
|
|
4
4
|
* Renders nothing — purely registers config into the RebaseRegistry.
|
|
@@ -7,4 +7,4 @@ import type { RebaseAuthConfig } from "@rebasepro/admin-types";
|
|
|
7
7
|
* authentication is cross-cutting (admin, Studio, any app area).
|
|
8
8
|
* @group Core
|
|
9
9
|
*/
|
|
10
|
-
export declare function RebaseAuth({ loginView }:
|
|
10
|
+
export declare function RebaseAuth({ loginView }: RebaseAuthViewConfig): null;
|
|
@@ -43,10 +43,8 @@ type DeepPartial<T> = T extends object ? {
|
|
|
43
43
|
* Controller to simulate different roles when dev mode is active.
|
|
44
44
|
* @group Models
|
|
45
45
|
*/
|
|
46
|
-
export
|
|
47
|
-
|
|
48
|
-
setEffectiveRole: (role: string | null) => void;
|
|
49
|
-
}
|
|
46
|
+
export type { EffectiveRoleController } from "@rebasepro/types";
|
|
47
|
+
import type { EffectiveRoleController } from "@rebasepro/types";
|
|
50
48
|
/**
|
|
51
49
|
* Props for the main {@link Rebase} component.
|
|
52
50
|
*
|
|
@@ -289,4 +287,3 @@ export type RebaseProps<USER extends User> = {
|
|
|
289
287
|
*/
|
|
290
288
|
components?: ComponentOverrideMap;
|
|
291
289
|
};
|
|
292
|
-
export {};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import type { RebaseRegistryController, RebaseAdminConfig, RebaseStudioConfig,
|
|
2
|
+
import type { RebaseRegistryController, RebaseAdminConfig, RebaseStudioConfig, RebaseAuthViewConfig } from "@rebasepro/admin-types";
|
|
3
3
|
/**
|
|
4
4
|
* Split into two contexts to prevent infinite re-render loops:
|
|
5
5
|
* - DispatchContext: stable register/unregister functions (never changes identity)
|
|
@@ -14,7 +14,7 @@ interface RegistryDispatch {
|
|
|
14
14
|
unregisterAdmin: () => void;
|
|
15
15
|
registerStudio: (config: RebaseStudioConfig) => void;
|
|
16
16
|
unregisterStudio: () => void;
|
|
17
|
-
registerAuth: (config:
|
|
17
|
+
registerAuth: (config: RebaseAuthViewConfig) => void;
|
|
18
18
|
unregisterAuth: () => void;
|
|
19
19
|
}
|
|
20
20
|
export declare function RebaseRegistryProvider({ children }: {
|
package/dist/index.es.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React, { createContext, lazy, useCallback, useContext, useEffect, useId, useLayoutEffect, useMemo, useRef, useState } from "react";
|
|
2
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";
|
|
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 } from "@rebasepro/types";
|
|
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";
|
|
@@ -8942,12 +8942,13 @@ function warnAboutHalfConfiguredOAuth(provider, clientId, backendProviders) {
|
|
|
8942
8942
|
* Feature-detects capabilities to show/hide login methods.
|
|
8943
8943
|
* @group Core
|
|
8944
8944
|
*/
|
|
8945
|
-
function LoginView({ logo, authController, noUserComponent, disableSignupScreen = false, disabled = false, notAllowedError, googleClientId, githubClientId, linkedinClientId, title, subtitle, needsSetup, registrationEnabled, additionalComponent, topComponent, defaultEmail, defaultPassword }) {
|
|
8945
|
+
function LoginView({ logo, authController, noUserComponent, disableSignupScreen = false, disabled = false, notAllowedError, googleClientId, githubClientId, linkedinClientId, title, subtitle, needsSetup, registrationEnabled, additionalComponent, topComponent, defaultEmail, defaultPassword, onNewsletterOptIn }) {
|
|
8946
8946
|
const { mode: colorMode, setMode: setColorMode } = useModeController();
|
|
8947
8947
|
const { t } = useTranslation();
|
|
8948
8948
|
const [mode, setMode] = useState("buttons");
|
|
8949
8949
|
const [fadeIn, setFadeIn] = useState(false);
|
|
8950
8950
|
const [viewVisible, setViewVisible] = useState(true);
|
|
8951
|
+
const [newsletterOptIn, setNewsletterOptIn] = useState(false);
|
|
8951
8952
|
const switchMode = (newMode) => {
|
|
8952
8953
|
setViewVisible(false);
|
|
8953
8954
|
setTimeout(() => {
|
|
@@ -9069,7 +9070,10 @@ function LoginView({ logo, authController, noUserComponent, disableSignupScreen
|
|
|
9069
9070
|
disableSignupScreen: false,
|
|
9070
9071
|
bootstrapMode: true,
|
|
9071
9072
|
defaultEmail,
|
|
9072
|
-
defaultPassword
|
|
9073
|
+
defaultPassword,
|
|
9074
|
+
onNewsletterOptIn,
|
|
9075
|
+
newsletterOptIn,
|
|
9076
|
+
setNewsletterOptIn
|
|
9073
9077
|
}), !isBootstrapMode && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
9074
9078
|
mode === "buttons" && /* @__PURE__ */ jsxs("div", {
|
|
9075
9079
|
className: "w-full flex flex-col gap-3 mt-2",
|
|
@@ -9138,7 +9142,10 @@ function LoginView({ logo, authController, noUserComponent, disableSignupScreen
|
|
|
9138
9142
|
disableSignupScreen,
|
|
9139
9143
|
switchToRegister: showRegistration ? () => switchMode("register") : void 0,
|
|
9140
9144
|
defaultEmail,
|
|
9141
|
-
defaultPassword
|
|
9145
|
+
defaultPassword,
|
|
9146
|
+
onNewsletterOptIn,
|
|
9147
|
+
newsletterOptIn,
|
|
9148
|
+
setNewsletterOptIn
|
|
9142
9149
|
}),
|
|
9143
9150
|
mode === "register" && /* @__PURE__ */ jsx(LoginForm, {
|
|
9144
9151
|
authController,
|
|
@@ -9149,7 +9156,10 @@ function LoginView({ logo, authController, noUserComponent, disableSignupScreen
|
|
|
9149
9156
|
disableSignupScreen,
|
|
9150
9157
|
switchToLogin: () => switchMode("login"),
|
|
9151
9158
|
defaultEmail,
|
|
9152
|
-
defaultPassword
|
|
9159
|
+
defaultPassword,
|
|
9160
|
+
onNewsletterOptIn,
|
|
9161
|
+
newsletterOptIn,
|
|
9162
|
+
setNewsletterOptIn
|
|
9153
9163
|
}),
|
|
9154
9164
|
mode === "forgot" && authController.forgotPassword && /* @__PURE__ */ jsx(ForgotPasswordForm, {
|
|
9155
9165
|
authController,
|
|
@@ -9289,8 +9299,9 @@ function LinkedInLoginButton({ disabled, linkedinClientId }) {
|
|
|
9289
9299
|
onClick: handleClick
|
|
9290
9300
|
});
|
|
9291
9301
|
}
|
|
9292
|
-
function LoginForm({ onClose, onForgotPassword, authController, registrationMode, noUserComponent, disableSignupScreen, bootstrapMode = false, switchToRegister, switchToLogin, defaultEmail, defaultPassword }) {
|
|
9302
|
+
function LoginForm({ onClose, onForgotPassword, authController, registrationMode, noUserComponent, disableSignupScreen, bootstrapMode = false, switchToRegister, switchToLogin, defaultEmail, defaultPassword, onNewsletterOptIn, newsletterOptIn = false, setNewsletterOptIn }) {
|
|
9293
9303
|
const passwordRef = useRef(null);
|
|
9304
|
+
const { t } = useTranslation();
|
|
9294
9305
|
const [email, setEmail] = useState(defaultEmail);
|
|
9295
9306
|
const [password, setPassword] = useState(defaultPassword);
|
|
9296
9307
|
const [displayName, setDisplayName] = useState();
|
|
@@ -9304,11 +9315,14 @@ function LoginForm({ onClose, onForgotPassword, authController, registrationMode
|
|
|
9304
9315
|
document.removeEventListener("keydown", escFunction, false);
|
|
9305
9316
|
};
|
|
9306
9317
|
}, [onClose]);
|
|
9318
|
+
function subscribeIfOptedIn(email) {
|
|
9319
|
+
if (newsletterOptIn && onNewsletterOptIn) onNewsletterOptIn(email);
|
|
9320
|
+
}
|
|
9307
9321
|
function handleEnterPassword() {
|
|
9308
|
-
if (email && password && authController.emailPasswordLogin) Promise.resolve(authController.emailPasswordLogin(email, password)).catch(() => void 0);
|
|
9322
|
+
if (email && password && authController.emailPasswordLogin) Promise.resolve(authController.emailPasswordLogin(email, password)).then(() => subscribeIfOptedIn(email)).catch(() => void 0);
|
|
9309
9323
|
}
|
|
9310
9324
|
function handleRegistration() {
|
|
9311
|
-
if (email && password && authController.register) Promise.resolve(authController.register(email, password, displayName)).catch(() => void 0);
|
|
9325
|
+
if (email && password && authController.register) Promise.resolve(authController.register(email, password, displayName)).then(() => subscribeIfOptedIn(email)).catch(() => void 0);
|
|
9312
9326
|
}
|
|
9313
9327
|
const handleSubmit = (event) => {
|
|
9314
9328
|
event.preventDefault();
|
|
@@ -9420,6 +9434,19 @@ function LoginForm({ onClose, onForgotPassword, authController, registrationMode
|
|
|
9420
9434
|
children: "Forgot password?"
|
|
9421
9435
|
})
|
|
9422
9436
|
}),
|
|
9437
|
+
onNewsletterOptIn && /* @__PURE__ */ jsxs("label", {
|
|
9438
|
+
className: "flex items-center gap-2 cursor-pointer mt-1 mb-1",
|
|
9439
|
+
children: [/* @__PURE__ */ jsx(Checkbox, {
|
|
9440
|
+
checked: newsletterOptIn,
|
|
9441
|
+
onCheckedChange: (checked) => setNewsletterOptIn?.(checked === true),
|
|
9442
|
+
size: "small"
|
|
9443
|
+
}), /* @__PURE__ */ jsx(Typography, {
|
|
9444
|
+
variant: "caption",
|
|
9445
|
+
color: "secondary",
|
|
9446
|
+
className: "select-none",
|
|
9447
|
+
children: t("join_newsletter")
|
|
9448
|
+
})]
|
|
9449
|
+
}),
|
|
9423
9450
|
/* @__PURE__ */ jsx(LoadingButton, {
|
|
9424
9451
|
type: "submit",
|
|
9425
9452
|
variant: "filled",
|
|
@@ -9680,6 +9707,7 @@ var en = {
|
|
|
9680
9707
|
dark_mode: "Dark",
|
|
9681
9708
|
light_mode: "Light",
|
|
9682
9709
|
system_mode: "System",
|
|
9710
|
+
join_newsletter: "Join the newsletter, no spam",
|
|
9683
9711
|
ok: "Ok",
|
|
9684
9712
|
save_collection_config: "Save collection structure",
|
|
9685
9713
|
search_for_more_icons: "Search for more icons…",
|
|
@@ -10560,6 +10588,7 @@ var es = {
|
|
|
10560
10588
|
dark_mode: "Oscuro",
|
|
10561
10589
|
light_mode: "Claro",
|
|
10562
10590
|
system_mode: "Sistema",
|
|
10591
|
+
join_newsletter: "Únete a la newsletter, sin spam",
|
|
10563
10592
|
ok: "Aceptar",
|
|
10564
10593
|
save_collection_config: "Guardar la estructura de la colección",
|
|
10565
10594
|
search_for_more_icons: "Buscar más iconos…",
|
|
@@ -11397,6 +11426,7 @@ var de = {
|
|
|
11397
11426
|
dark_mode: "Dunkel",
|
|
11398
11427
|
light_mode: "Hell",
|
|
11399
11428
|
system_mode: "System",
|
|
11429
|
+
join_newsletter: "Newsletter abonnieren, kein Spam",
|
|
11400
11430
|
ok: "Ok",
|
|
11401
11431
|
save_collection_config: "Sammlungsstruktur speichern",
|
|
11402
11432
|
search_for_more_icons: "Nach weiteren Symbolen suchen…",
|
|
@@ -12224,6 +12254,7 @@ var fr = {
|
|
|
12224
12254
|
dark_mode: "Sombre",
|
|
12225
12255
|
light_mode: "Clair",
|
|
12226
12256
|
system_mode: "Système",
|
|
12257
|
+
join_newsletter: "Rejoignez la newsletter, pas de spam",
|
|
12227
12258
|
ok: "Ok",
|
|
12228
12259
|
save_collection_config: "Enregistrer la structure de la collection",
|
|
12229
12260
|
search_for_more_icons: "Rechercher d'autres icônes…",
|
|
@@ -13051,6 +13082,7 @@ var it = {
|
|
|
13051
13082
|
dark_mode: "Scuro",
|
|
13052
13083
|
light_mode: "Chiaro",
|
|
13053
13084
|
system_mode: "Sistema",
|
|
13085
|
+
join_newsletter: "Iscriviti alla newsletter, niente spam",
|
|
13054
13086
|
ok: "Ok",
|
|
13055
13087
|
save_collection_config: "Salva struttura della collezione",
|
|
13056
13088
|
search_for_more_icons: "Cerca altre icone…",
|
|
@@ -13878,6 +13910,7 @@ var hi = {
|
|
|
13878
13910
|
dark_mode: "डार्क",
|
|
13879
13911
|
light_mode: "लाइट",
|
|
13880
13912
|
system_mode: "सिस्टम",
|
|
13913
|
+
join_newsletter: "न्यूज़लेटर से जुड़ें, कोई स्पैम नहीं",
|
|
13881
13914
|
ok: "ठीक है",
|
|
13882
13915
|
save_collection_config: "संग्रह संरचना सहेजें",
|
|
13883
13916
|
search_for_more_icons: "और आइकन खोजें…",
|
|
@@ -14710,6 +14743,7 @@ var pt = {
|
|
|
14710
14743
|
dark_mode: "Escuro",
|
|
14711
14744
|
light_mode: "Claro",
|
|
14712
14745
|
system_mode: "Sistema",
|
|
14746
|
+
join_newsletter: "Assine a newsletter, sem spam",
|
|
14713
14747
|
ok: "Ok",
|
|
14714
14748
|
save_collection_config: "Guardar estrutura da coleção",
|
|
14715
14749
|
search_for_more_icons: "Pesquisar mais ícones…",
|
|
@@ -17478,11 +17512,20 @@ function applyPropertyConditions(property, context) {
|
|
|
17478
17512
|
if ("enum" in result && result.enum && (conditions.enumConditions || conditions.allowedEnumValues || conditions.excludedEnumValues)) result.enum = applyEnumConditions(result.enum, conditions, context);
|
|
17479
17513
|
if (result.type === "reference") {
|
|
17480
17514
|
if (conditions.referencePath) result.path = evaluateCondition(conditions.referencePath, context);
|
|
17481
|
-
if (conditions.referenceFilter)
|
|
17515
|
+
if (conditions.referenceFilter) {
|
|
17516
|
+
result.admin = result.admin || {};
|
|
17517
|
+
result.admin.fixedFilter = evaluateCondition(conditions.referenceFilter, context);
|
|
17518
|
+
}
|
|
17482
17519
|
}
|
|
17483
17520
|
if (result.type === "array") {
|
|
17484
|
-
if (conditions.canAddElements !== void 0)
|
|
17485
|
-
|
|
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
|
+
}
|
|
17486
17529
|
}
|
|
17487
17530
|
return result;
|
|
17488
17531
|
}
|
|
@@ -17612,7 +17655,7 @@ function getForeignKeyColumns(collection) {
|
|
|
17612
17655
|
default: break;
|
|
17613
17656
|
}
|
|
17614
17657
|
};
|
|
17615
|
-
for (const relation of collection.relations ?? []) addRelationKeys(relation);
|
|
17658
|
+
for (const relation of (isRelationalCollectionConfig(collection) ? collection.relations : void 0) ?? []) addRelationKeys(relation);
|
|
17616
17659
|
for (const [key, propertyRaw] of Object.entries(collection.properties ?? {})) {
|
|
17617
17660
|
const property = propertyRaw;
|
|
17618
17661
|
if (!property || isPropertyBuilder(property) || property.type !== "relation") continue;
|