@rebasepro/app 0.14.1-canary.g7e666eb → 0.14.1

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.
@@ -105,11 +105,18 @@ export interface LoginViewProps {
105
105
  */
106
106
  defaultPassword?: string;
107
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.
108
+ * When set, a "Join the newsletter" opt-in checkbox is offered. Called with
109
+ * the address that just authenticated — by any method — if the box was
110
+ * ticked. Wire it to whatever stores the subscription; failures are the
111
+ * callback's problem, the login flow never waits on it.
112
+ *
113
+ * The checkbox sits on the **provider screen**, beside the buttons that
114
+ * choose how to sign in, rather than on the credentials form. It is a
115
+ * decision about the visitor, not about the password: asking on the
116
+ * credentials form put it in front of only the people who got that far by
117
+ * typing an address, so anyone signing in with Google was never offered it
118
+ * at all. Bootstrap mode is the exception — there is no provider screen
119
+ * there, so the form keeps it.
113
120
  */
114
121
  onNewsletterOptIn?: (email: string) => void;
115
122
  }
@@ -12,6 +12,6 @@
12
12
  * @internal
13
13
  */
14
14
  export declare function useTranslation(): {
15
- t: (key: string, vars?: Record<string, string>) => string;
15
+ t: (key: string, vars?: Record<string, string | number>) => string;
16
16
  i18n: import("i18next").i18n;
17
17
  };
package/dist/index.es.js CHANGED
@@ -2227,6 +2227,11 @@ function useTranslation() {
2227
2227
  * Also supports i18next interpolation variables, e.g.
2228
2228
  * t("add_to_field", { fieldName: "Tags" })
2229
2229
  * t("error_deleting", { message: err.message })
2230
+ * t("sort_key_position", { position: 2 })
2231
+ *
2232
+ * Numbers are accepted as well as strings: i18next interpolates them
2233
+ * either way, and a signature that took only strings pushed a `String()`
2234
+ * onto every call site with a count in it — `{{count}}`, `{{position}}`.
2230
2235
  */
2231
2236
  const typedT = useCallback((key, vars) => t(key, vars), [t]);
2232
2237
  return useMemo(() => ({
@@ -9533,6 +9538,21 @@ function LoginView({ logo, authController, noUserComponent, disableSignupScreen
9533
9538
  const [fadeIn, setFadeIn] = useState(false);
9534
9539
  const [viewVisible, setViewVisible] = useState(true);
9535
9540
  const [newsletterOptIn, setNewsletterOptIn] = useState(false);
9541
+ const authControllerRef = useRef(authController);
9542
+ authControllerRef.current = authController;
9543
+ /**
9544
+ * Subscribe the address that just authenticated, if the visitor asked for
9545
+ * it. Every sign-in path calls this, which is the point: the checkbox sits
9546
+ * beside the provider buttons, so it has to mean the same thing whichever
9547
+ * one is pressed.
9548
+ *
9549
+ * Only ever from a resolution path — a ticked box on a *failed* attempt
9550
+ * must not subscribe an address nobody proved they control.
9551
+ */
9552
+ const subscribeIfOptedIn = useCallback((email) => {
9553
+ if (!newsletterOptIn || !onNewsletterOptIn || !email) return;
9554
+ onNewsletterOptIn(email);
9555
+ }, [newsletterOptIn, onNewsletterOptIn]);
9536
9556
  const switchMode = (newMode) => {
9537
9557
  setViewVisible(false);
9538
9558
  setTimeout(() => {
@@ -9661,9 +9681,10 @@ function LoginView({ logo, authController, noUserComponent, disableSignupScreen
9661
9681
  bootstrapMode: true,
9662
9682
  defaultEmail,
9663
9683
  defaultPassword,
9664
- onNewsletterOptIn,
9684
+ onSignedIn: subscribeIfOptedIn,
9665
9685
  newsletterOptIn,
9666
- setNewsletterOptIn
9686
+ setNewsletterOptIn,
9687
+ showNewsletterOptIn: Boolean(onNewsletterOptIn)
9667
9688
  }), !isBootstrapMode && /* @__PURE__ */ jsxs(Fragment, { children: [
9668
9689
  mode === "buttons" && /* @__PURE__ */ jsxs("div", {
9669
9690
  className: "w-full flex flex-col gap-3 mt-2",
@@ -9685,6 +9706,19 @@ function LoginView({ logo, authController, noUserComponent, disableSignupScreen
9685
9706
  className: "w-full",
9686
9707
  children: topComponent
9687
9708
  }),
9709
+ onNewsletterOptIn && /* @__PURE__ */ jsxs("label", {
9710
+ className: cls("flex items-center gap-2 cursor-pointer", (topComponent || title || subtitle) && "-mt-3"),
9711
+ children: [/* @__PURE__ */ jsx(Checkbox, {
9712
+ checked: newsletterOptIn,
9713
+ onCheckedChange: (checked) => setNewsletterOptIn(checked === true),
9714
+ size: "small"
9715
+ }), /* @__PURE__ */ jsx(Typography, {
9716
+ variant: "caption",
9717
+ color: "secondary",
9718
+ className: "select-none",
9719
+ children: t("join_newsletter")
9720
+ })]
9721
+ }),
9688
9722
  /* @__PURE__ */ jsx(LoginButton, {
9689
9723
  disabled,
9690
9724
  text: "Sign in with email",
@@ -9694,7 +9728,8 @@ function LoginView({ logo, authController, noUserComponent, disableSignupScreen
9694
9728
  hasGoogleLogin && googleClientId && /* @__PURE__ */ jsx(GoogleLoginButton, {
9695
9729
  disabled,
9696
9730
  googleClientId,
9697
- authController
9731
+ authController,
9732
+ onSignedIn: () => subscribeIfOptedIn(authControllerRef.current.user?.email)
9698
9733
  }),
9699
9734
  hasGitHubLogin && githubClientId && /* @__PURE__ */ jsx(GitHubLoginButton, {
9700
9735
  disabled,
@@ -9733,9 +9768,7 @@ function LoginView({ logo, authController, noUserComponent, disableSignupScreen
9733
9768
  switchToRegister: showRegistration ? () => switchMode("register") : void 0,
9734
9769
  defaultEmail,
9735
9770
  defaultPassword,
9736
- onNewsletterOptIn,
9737
- newsletterOptIn,
9738
- setNewsletterOptIn
9771
+ onSignedIn: subscribeIfOptedIn
9739
9772
  }),
9740
9773
  mode === "register" && /* @__PURE__ */ jsx(LoginForm, {
9741
9774
  authController,
@@ -9747,9 +9780,7 @@ function LoginView({ logo, authController, noUserComponent, disableSignupScreen
9747
9780
  switchToLogin: () => switchMode("login"),
9748
9781
  defaultEmail,
9749
9782
  defaultPassword,
9750
- onNewsletterOptIn,
9751
- newsletterOptIn,
9752
- setNewsletterOptIn
9783
+ onSignedIn: subscribeIfOptedIn
9753
9784
  }),
9754
9785
  mode === "forgot" && authController.forgotPassword && /* @__PURE__ */ jsx(ForgotPasswordForm, {
9755
9786
  authController,
@@ -9807,8 +9838,10 @@ var GoogleIcon = () => /* @__PURE__ */ jsxs("svg", {
9807
9838
  })
9808
9839
  ]
9809
9840
  });
9810
- function GoogleLoginButton({ disabled, googleClientId, authController }) {
9841
+ function GoogleLoginButton({ disabled, googleClientId, authController, onSignedIn }) {
9811
9842
  const codeClientRef = useRef(null);
9843
+ const onSignedInRef = useRef(onSignedIn);
9844
+ onSignedInRef.current = onSignedIn;
9812
9845
  useEffect(() => {
9813
9846
  if (!authController.googleLogin) return;
9814
9847
  const google = window.google;
@@ -9827,6 +9860,7 @@ function GoogleLoginButton({ disabled, googleClientId, authController }) {
9827
9860
  code: response.code,
9828
9861
  redirectUri: "postmessage"
9829
9862
  });
9863
+ onSignedInRef.current?.();
9830
9864
  } catch (err) {
9831
9865
  console.error("Google login error:", err);
9832
9866
  }
@@ -9895,7 +9929,7 @@ function LinkedInLoginButton({ disabled, linkedinClientId }) {
9895
9929
  onClick: handleClick
9896
9930
  });
9897
9931
  }
9898
- function LoginForm({ onClose, onForgotPassword, authController, registrationMode, noUserComponent, disableSignupScreen, bootstrapMode = false, switchToRegister, switchToLogin, defaultEmail, defaultPassword, onNewsletterOptIn, newsletterOptIn = false, setNewsletterOptIn }) {
9932
+ function LoginForm({ onClose, onForgotPassword, authController, registrationMode, noUserComponent, disableSignupScreen, bootstrapMode = false, switchToRegister, switchToLogin, defaultEmail, defaultPassword, onSignedIn, newsletterOptIn = false, setNewsletterOptIn, showNewsletterOptIn = false }) {
9899
9933
  const passwordRef = useRef(null);
9900
9934
  const { t } = useTranslation();
9901
9935
  const emailId = useId();
@@ -9914,14 +9948,14 @@ function LoginForm({ onClose, onForgotPassword, authController, registrationMode
9914
9948
  document.removeEventListener("keydown", escFunction, false);
9915
9949
  };
9916
9950
  }, [onClose]);
9917
- function subscribeIfOptedIn(email) {
9918
- if (newsletterOptIn && onNewsletterOptIn) onNewsletterOptIn(email);
9951
+ function reportSignedIn(email) {
9952
+ onSignedIn?.(email);
9919
9953
  }
9920
9954
  function handleEnterPassword() {
9921
- if (email && password && authController.emailPasswordLogin) Promise.resolve(authController.emailPasswordLogin(email, password)).then(() => subscribeIfOptedIn(email)).catch(() => void 0);
9955
+ if (email && password && authController.emailPasswordLogin) Promise.resolve(authController.emailPasswordLogin(email, password)).then(() => reportSignedIn(email)).catch(() => void 0);
9922
9956
  }
9923
9957
  function handleRegistration() {
9924
- if (email && password && authController.register) Promise.resolve(authController.register(email, password, displayName)).then(() => subscribeIfOptedIn(email)).catch(() => void 0);
9958
+ if (email && password && authController.register) Promise.resolve(authController.register(email, password, displayName)).then(() => reportSignedIn(email)).catch(() => void 0);
9925
9959
  }
9926
9960
  const handleSubmit = (event) => {
9927
9961
  event.preventDefault();
@@ -10042,7 +10076,7 @@ function LoginForm({ onClose, onForgotPassword, authController, registrationMode
10042
10076
  children: "Forgot password?"
10043
10077
  })
10044
10078
  }),
10045
- onNewsletterOptIn && /* @__PURE__ */ jsxs("label", {
10079
+ showNewsletterOptIn && /* @__PURE__ */ jsxs("label", {
10046
10080
  className: "flex items-center gap-2 cursor-pointer mt-1 mb-1",
10047
10081
  children: [/* @__PURE__ */ jsx(Checkbox, {
10048
10082
  checked: newsletterOptIn,
@@ -10304,6 +10338,16 @@ var en = {
10304
10338
  clear_sort: "Clear sort",
10305
10339
  sort: "Sort",
10306
10340
  sort_by: "Sort by",
10341
+ sort_then_by: "Then by",
10342
+ sort_ascending: "Sort ascending",
10343
+ sort_descending: "Sort descending",
10344
+ sort_remove: "Remove sort",
10345
+ sort_move_up: "Make this key more important",
10346
+ sort_move_down: "Make this key less important",
10347
+ sort_remove_key: "Remove this sort key",
10348
+ sort_key_position: "Sort key {{position}}",
10349
+ sort_shift_click_hint: "Shift-click to add a column under the current sort",
10350
+ save_entity_before_subcollections: "You need to save your entity before adding additional collections",
10307
10351
  clear_all: "Clear all",
10308
10352
  no_items: "No items",
10309
10353
  no_entries_found: "No entries found",
@@ -11206,6 +11250,16 @@ var es = {
11206
11250
  clear_sort: "Borrar orden",
11207
11251
  sort: "Ordenar",
11208
11252
  sort_by: "Ordenar por",
11253
+ sort_then_by: "Luego por",
11254
+ sort_ascending: "Ordenar ascendente",
11255
+ sort_descending: "Ordenar descendente",
11256
+ sort_remove: "Quitar orden",
11257
+ sort_move_up: "Dar más importancia a esta clave",
11258
+ sort_move_down: "Dar menos importancia a esta clave",
11259
+ sort_remove_key: "Quitar esta clave de orden",
11260
+ sort_key_position: "Clave de orden {{position}}",
11261
+ sort_shift_click_hint: "Mayús+clic para añadir una columna bajo el orden actual",
11262
+ save_entity_before_subcollections: "Debes guardar la entidad antes de añadir colecciones adicionales",
11209
11263
  clear_all: "Borrar todo",
11210
11264
  no_items: "Sin elementos",
11211
11265
  no_entries_found: "No se encontraron entradas",
@@ -12064,6 +12118,16 @@ var de = {
12064
12118
  clear_sort: "Sortierung löschen",
12065
12119
  sort: "Sortieren",
12066
12120
  sort_by: "Sortieren nach",
12121
+ sort_then_by: "Dann nach",
12122
+ sort_ascending: "Aufsteigend sortieren",
12123
+ sort_descending: "Absteigend sortieren",
12124
+ sort_remove: "Sortierung entfernen",
12125
+ sort_move_up: "Diesen Schlüssel wichtiger machen",
12126
+ sort_move_down: "Diesen Schlüssel weniger wichtig machen",
12127
+ sort_remove_key: "Diesen Sortierschlüssel entfernen",
12128
+ sort_key_position: "Sortierschlüssel {{position}}",
12129
+ sort_shift_click_hint: "Umschalt+Klick, um eine Spalte unter der aktuellen Sortierung hinzuzufügen",
12130
+ save_entity_before_subcollections: "Du musst den Eintrag speichern, bevor du weitere Sammlungen hinzufügst",
12067
12131
  clear_all: "Alle löschen",
12068
12132
  no_items: "Keine Elemente",
12069
12133
  no_entries_found: "Keine Einträge gefunden",
@@ -12912,6 +12976,16 @@ var fr = {
12912
12976
  clear_sort: "Effacer le tri",
12913
12977
  sort: "Trier",
12914
12978
  sort_by: "Trier par",
12979
+ sort_then_by: "Puis par",
12980
+ sort_ascending: "Trier par ordre croissant",
12981
+ sort_descending: "Trier par ordre décroissant",
12982
+ sort_remove: "Supprimer le tri",
12983
+ sort_move_up: "Rendre cette clé plus importante",
12984
+ sort_move_down: "Rendre cette clé moins importante",
12985
+ sort_remove_key: "Supprimer cette clé de tri",
12986
+ sort_key_position: "Clé de tri {{position}}",
12987
+ sort_shift_click_hint: "Maj+clic pour ajouter une colonne sous le tri actuel",
12988
+ save_entity_before_subcollections: "Vous devez enregistrer l'entité avant d'ajouter des collections supplémentaires",
12915
12989
  clear_all: "Tout effacer",
12916
12990
  no_items: "Aucun élément",
12917
12991
  no_entries_found: "Aucune entrée trouvée",
@@ -13760,6 +13834,16 @@ var it = {
13760
13834
  clear_sort: "Cancella ordinamento",
13761
13835
  sort: "Ordina",
13762
13836
  sort_by: "Ordina per",
13837
+ sort_then_by: "Poi per",
13838
+ sort_ascending: "Ordina in modo crescente",
13839
+ sort_descending: "Ordina in modo decrescente",
13840
+ sort_remove: "Rimuovi ordinamento",
13841
+ sort_move_up: "Rendi questa chiave più importante",
13842
+ sort_move_down: "Rendi questa chiave meno importante",
13843
+ sort_remove_key: "Rimuovi questa chiave di ordinamento",
13844
+ sort_key_position: "Chiave di ordinamento {{position}}",
13845
+ sort_shift_click_hint: "Maiusc+clic per aggiungere una colonna sotto l'ordinamento attuale",
13846
+ save_entity_before_subcollections: "Devi salvare l'entità prima di aggiungere altre raccolte",
13763
13847
  clear_all: "Cancella tutto",
13764
13848
  no_items: "Nessun elemento",
13765
13849
  no_entries_found: "Nessuna voce trovata",
@@ -14608,6 +14692,16 @@ var hi = {
14608
14692
  clear_sort: "सॉर्ट साफ़ करें",
14609
14693
  sort: "क्रमबद्ध करें",
14610
14694
  sort_by: "इसके अनुसार क्रमबद्ध करें",
14695
+ sort_then_by: "फिर इसके अनुसार",
14696
+ sort_ascending: "आरोही क्रम में लगाएँ",
14697
+ sort_descending: "अवरोही क्रम में लगाएँ",
14698
+ sort_remove: "क्रम हटाएँ",
14699
+ sort_move_up: "इस कुंजी को अधिक महत्व दें",
14700
+ sort_move_down: "इस कुंजी को कम महत्व दें",
14701
+ sort_remove_key: "यह क्रम कुंजी हटाएँ",
14702
+ sort_key_position: "क्रम कुंजी {{position}}",
14703
+ sort_shift_click_hint: "वर्तमान क्रम के नीचे कॉलम जोड़ने के लिए Shift+क्लिक करें",
14704
+ save_entity_before_subcollections: "अतिरिक्त संग्रह जोड़ने से पहले आपको एंटिटी सहेजनी होगी",
14611
14705
  clear_all: "सभी साफ़ करें",
14612
14706
  no_items: "कोई आइटम नहीं",
14613
14707
  no_entries_found: "कोई प्रविष्टि नहीं मिली",
@@ -15461,6 +15555,16 @@ var pt = {
15461
15555
  clear_sort: "Limpar ordenação",
15462
15556
  sort: "Ordenar",
15463
15557
  sort_by: "Ordenar por",
15558
+ sort_then_by: "Depois por",
15559
+ sort_ascending: "Ordenar ascendente",
15560
+ sort_descending: "Ordenar descendente",
15561
+ sort_remove: "Remover ordenação",
15562
+ sort_move_up: "Tornar esta chave mais importante",
15563
+ sort_move_down: "Tornar esta chave menos importante",
15564
+ sort_remove_key: "Remover esta chave de ordenação",
15565
+ sort_key_position: "Chave de ordenação {{position}}",
15566
+ sort_shift_click_hint: "Shift+clique para adicionar uma coluna sob a ordenação atual",
15567
+ save_entity_before_subcollections: "Precisas de guardar a entidade antes de adicionar coleções adicionais",
15464
15568
  clear_all: "Limpar tudo",
15465
15569
  no_items: "Sem itens",
15466
15570
  no_entries_found: "Nenhum registo encontrado",