@protobase/ui 0.15.5 → 0.16.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.
Files changed (87) hide show
  1. package/dist/account/two-factor-setup.js +6 -5
  2. package/dist/app/app.js +1 -1
  3. package/dist/app/create/create-page.js +1 -0
  4. package/dist/app/create/create-record-form.js +1 -0
  5. package/dist/app/displays/map-display.js +50 -34
  6. package/dist/app/displays/map-groups.js +12 -3
  7. package/dist/app/displays/measured-heights.js +23 -0
  8. package/dist/app/displays/record-card.js +2 -2
  9. package/dist/app/displays/virtual-cards.js +12 -14
  10. package/dist/app/field-editor.js +9 -1
  11. package/dist/app/list-page.js +1 -1
  12. package/dist/app/map/approximate-position.js +76 -0
  13. package/dist/app/map/area-features.js +80 -0
  14. package/dist/app/map/maplibre.js +11 -0
  15. package/dist/app/map/position-areas.js +78 -0
  16. package/dist/app/map/record-map.js +2 -7
  17. package/dist/app/map/record-position.js +5 -4
  18. package/dist/app/map/records-map.js +24 -7
  19. package/dist/app/map/theme-color.js +23 -0
  20. package/dist/app/nav-recent.js +1 -1
  21. package/dist/app/pages/blocks/card-frame.js +2 -2
  22. package/dist/app/pages/blocks/grid.js +10 -2
  23. package/dist/app/pages/blocks/link.js +1 -1
  24. package/dist/app/pages/blocks/stat.js +9 -5
  25. package/dist/app/pages/field-value.js +1 -1
  26. package/dist/app/record-page.js +5 -1
  27. package/dist/app/router.js +7 -8
  28. package/dist/app/saved/saved-records.js +1 -1
  29. package/dist/app/search/search-model.js +1 -1
  30. package/dist/app/searches/use-save-search.js +4 -3
  31. package/dist/app/use-record-editor.js +5 -3
  32. package/dist/app-shell/app-shell.d.ts +1 -0
  33. package/dist/app-shell/app-shell.js +4 -3
  34. package/dist/app-shell/page-scroll.js +17 -1
  35. package/dist/app-shell/sidebar.d.ts +1 -0
  36. package/dist/app-shell/sidebar.js +4 -4
  37. package/dist/app-shell/top-bar.js +4 -4
  38. package/dist/auth/auth-gate.js +18 -9
  39. package/dist/auth/auth-provider.js +1 -0
  40. package/dist/auth/code-form.js +77 -0
  41. package/dist/auth/email-code-form.js +18 -77
  42. package/dist/auth/forgot-password-form.js +10 -10
  43. package/dist/auth/forgot-password-page.js +2 -2
  44. package/dist/auth/resend-code-button.js +29 -0
  45. package/dist/auth/sign-in-form.js +7 -8
  46. package/dist/auth/sign-in-page.js +3 -3
  47. package/dist/auth/sign-in-prompt.js +13 -9
  48. package/dist/auth/sign-up-code-form.js +22 -0
  49. package/dist/auth/sign-up-details-form.js +81 -111
  50. package/dist/auth/sign-up-page.js +17 -8
  51. package/dist/auth/two-factor-form.js +3 -3
  52. package/dist/auth/use-sign-in-address.js +21 -8
  53. package/dist/index.d.ts +2 -1
  54. package/dist/index.js +2 -1
  55. package/dist/lib/flip-guard.js +43 -0
  56. package/dist/lib/page-scroll-lock.js +20 -0
  57. package/dist/lib/use-focus-trap.js +4 -4
  58. package/dist/organizations/invitation-page.js +7 -6
  59. package/dist/package.js +1 -1
  60. package/dist/primitives/otp-input.d.ts +21 -0
  61. package/dist/primitives/otp-input.js +117 -0
  62. package/dist/primitives/otp-value.js +23 -0
  63. package/dist/primitives/route-link.d.ts +1 -0
  64. package/dist/primitives/route-link.js +20 -0
  65. package/dist/primitives/textarea.js +36 -0
  66. package/dist/record-view/field.js +56 -53
  67. package/dist/shell/assets/app-DJAZP1yB.js +66 -0
  68. package/dist/shell/assets/index-C5pYkUfv.css +2 -0
  69. package/dist/shell/assets/{index-DxmdRnr8.js → index-LBhMBiK4.js} +1 -1
  70. package/dist/shell/assets/maplibre-Dy0ZTnFZ.js +814 -0
  71. package/dist/shell/assets/record-map-BiWSbqqT.js +1 -0
  72. package/dist/shell/assets/records-map-DabYc3ad.js +1 -0
  73. package/dist/shell/assets/shared-protobase-ui-BURelnPG.js +1 -0
  74. package/dist/shell/index.html +4 -4
  75. package/dist/shell/protobase.shell.json +1 -1
  76. package/dist/styles.css +15 -0
  77. package/dist/toasts/toast.js +22 -6
  78. package/package.json +4 -4
  79. package/dist/auth/code-input.js +0 -17
  80. package/dist/auth/sign-in-address.js +0 -47
  81. package/dist/shell/assets/app-BdEV1_xI.js +0 -66
  82. package/dist/shell/assets/index-ibaHR5wQ.css +0 -2
  83. package/dist/shell/assets/maplibre-gl-DFcSGTFJ.js +0 -1
  84. package/dist/shell/assets/record-map-CL9bBLic.js +0 -814
  85. package/dist/shell/assets/records-map-DgtD0cK5.js +0 -1
  86. package/dist/shell/assets/shared-protobase-ui-ibIDwOpE.js +0 -1
  87. /package/dist/shell/assets/{record-map-DBE96hFo.css → maplibre-DBE96hFo.css} +0 -0
@@ -0,0 +1,77 @@
1
+ import { Button } from "../primitives/button.js";
2
+ import { OtpInput } from "../primitives/otp-input.js";
3
+ import { AuthLayout } from "./auth-layout.js";
4
+ import { ResendCodeButton } from "./resend-code-button.js";
5
+ import { useState } from "react";
6
+ import { jsx, jsxs } from "react/jsx-runtime";
7
+ //#region src/auth/code-form.tsx
8
+ /**
9
+ * A step that checks an emailed code on its own: where it went, a box per digit, a new code after a wait, and a way back
10
+ * to another address. Nothing else is asked for until the code is right.
11
+ */
12
+ const CodeForm = ({ title, description, explanation, submitLabel, onSubmit, onResend, onChangeAddress, changeAddressLabel, busy, error, notice, resendCooldown }) => {
13
+ const [code, setCode] = useState("");
14
+ return /* @__PURE__ */ jsxs(AuthLayout, {
15
+ title,
16
+ description,
17
+ children: [
18
+ /* @__PURE__ */ jsx("p", {
19
+ className: "mb-4 text-[13px] text-muted-foreground",
20
+ children: explanation
21
+ }),
22
+ notice && /* @__PURE__ */ jsx("p", {
23
+ role: "status",
24
+ className: "mb-4 rounded-md bg-success-soft px-3 py-2 text-xs font-medium text-success-text",
25
+ children: notice
26
+ }),
27
+ /* @__PURE__ */ jsxs("form", {
28
+ className: "flex flex-col gap-4",
29
+ onSubmit: (event) => {
30
+ event.preventDefault();
31
+ onSubmit(code);
32
+ },
33
+ children: [
34
+ /* @__PURE__ */ jsxs("label", {
35
+ className: "flex flex-col gap-1.5 text-[13px] font-medium",
36
+ children: ["Code", /* @__PURE__ */ jsx(OtpInput, {
37
+ name: "code",
38
+ required: true,
39
+ autoFocus: true,
40
+ value: code,
41
+ invalid: Boolean(error),
42
+ onChange: setCode,
43
+ onComplete: (complete) => !busy && onSubmit(complete)
44
+ })]
45
+ }),
46
+ error && /* @__PURE__ */ jsx("p", {
47
+ role: "alert",
48
+ className: "text-xs font-medium text-danger-text",
49
+ children: error
50
+ }),
51
+ /* @__PURE__ */ jsx(Button, {
52
+ variant: "primary",
53
+ type: "submit",
54
+ loading: busy,
55
+ className: "min-h-10",
56
+ children: submitLabel
57
+ }),
58
+ /* @__PURE__ */ jsxs("div", {
59
+ className: "flex flex-wrap justify-center gap-x-2 sm:justify-between",
60
+ children: [/* @__PURE__ */ jsx(Button, {
61
+ variant: "ghost",
62
+ onClick: onChangeAddress,
63
+ className: "min-h-10",
64
+ children: changeAddressLabel
65
+ }), /* @__PURE__ */ jsx(ResendCodeButton, {
66
+ onResend,
67
+ disabled: busy,
68
+ cooldown: resendCooldown
69
+ })]
70
+ })
71
+ ]
72
+ })
73
+ ]
74
+ });
75
+ };
76
+ //#endregion
77
+ export { CodeForm };
@@ -1,81 +1,22 @@
1
- import { Button } from "../primitives/button.js";
2
- import { CodeInput } from "./code-input.js";
3
- import { AuthLayout } from "./auth-layout.js";
4
- import { useState } from "react";
5
- import { jsx, jsxs } from "react/jsx-runtime";
1
+ import { CodeForm } from "./code-form.js";
2
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
6
3
  //#region src/auth/email-code-form.tsx
7
4
  /** The second half of signing in with an emailed code: the code from the email. */
8
- const EmailCodeForm = ({ email, onSubmit, onResend, onBack, busy, error, notice }) => {
9
- const [code, setCode] = useState("");
10
- return /* @__PURE__ */ jsxs(AuthLayout, {
11
- title: "Check your email",
12
- description: "Enter the code we sent to sign in.",
13
- children: [
14
- /* @__PURE__ */ jsxs("p", {
15
- className: "mb-4 text-[13px] text-muted-foreground",
16
- children: [
17
- "If ",
18
- /* @__PURE__ */ jsx("span", {
19
- className: "font-medium text-foreground",
20
- children: email
21
- }),
22
- " has an account, a 6-digit code is on its way. It works for 5 minutes, once."
23
- ]
24
- }),
25
- notice && /* @__PURE__ */ jsx("p", {
26
- role: "status",
27
- className: "mb-4 rounded-md bg-success-soft px-3 py-2 text-xs font-medium text-success-text",
28
- children: notice
29
- }),
30
- /* @__PURE__ */ jsxs("form", {
31
- className: "flex flex-col gap-4",
32
- onSubmit: (event) => {
33
- event.preventDefault();
34
- onSubmit(code.trim());
35
- },
36
- children: [
37
- /* @__PURE__ */ jsxs("label", {
38
- className: "flex flex-col gap-1.5 text-[13px] font-medium",
39
- children: ["Code", /* @__PURE__ */ jsx(CodeInput, {
40
- name: "code",
41
- required: true,
42
- autoFocus: true,
43
- value: code,
44
- invalid: Boolean(error),
45
- onChange: (event) => setCode(event.target.value)
46
- })]
47
- }),
48
- error && /* @__PURE__ */ jsx("p", {
49
- role: "alert",
50
- className: "text-xs font-medium text-danger-text",
51
- children: error
52
- }),
53
- /* @__PURE__ */ jsx(Button, {
54
- variant: "primary",
55
- type: "submit",
56
- loading: busy,
57
- className: "min-h-10",
58
- children: "Sign in"
59
- }),
60
- /* @__PURE__ */ jsxs("div", {
61
- className: "flex justify-between gap-2",
62
- children: [/* @__PURE__ */ jsx(Button, {
63
- variant: "ghost",
64
- onClick: onBack,
65
- className: "min-h-10",
66
- children: "Back to sign in"
67
- }), /* @__PURE__ */ jsx(Button, {
68
- variant: "ghost",
69
- onClick: onResend,
70
- disabled: busy,
71
- className: "min-h-10",
72
- children: "Send a new code"
73
- })]
74
- })
75
- ]
76
- })
77
- ]
78
- });
79
- };
5
+ const EmailCodeForm = ({ email, onBack, ...rest }) => /* @__PURE__ */ jsx(CodeForm, {
6
+ title: "Check your email",
7
+ description: "Enter the code we sent to sign in.",
8
+ explanation: /* @__PURE__ */ jsxs(Fragment, { children: [
9
+ "If ",
10
+ /* @__PURE__ */ jsx("span", {
11
+ className: "font-medium text-foreground",
12
+ children: email
13
+ }),
14
+ " has an account, a 6-digit code is on its way. It works for 5 minutes, once."
15
+ ] }),
16
+ submitLabel: "Sign in",
17
+ onChangeAddress: onBack,
18
+ changeAddressLabel: "Back to sign in",
19
+ ...rest
20
+ });
80
21
  //#endregion
81
22
  export { EmailCodeForm };
@@ -1,10 +1,12 @@
1
+ import { cn } from "../lib/cn.js";
2
+ import { RouteLink } from "../primitives/route-link.js";
1
3
  import { Input } from "../primitives/input.js";
2
- import { Button } from "../primitives/button.js";
4
+ import { Button, buttonClass } from "../primitives/button.js";
3
5
  import { AuthLayout } from "./auth-layout.js";
4
6
  import { useState } from "react";
5
7
  import { jsx, jsxs } from "react/jsx-runtime";
6
8
  //#region src/auth/forgot-password-form.tsx
7
- const ForgotPasswordForm = ({ onSubmit, onBack, busy, error, sentTo }) => {
9
+ const ForgotPasswordForm = ({ onSubmit, back, busy, error, sentTo }) => {
8
10
  const [email, setEmail] = useState("");
9
11
  if (sentTo) return /* @__PURE__ */ jsxs(AuthLayout, {
10
12
  title: "Check your email",
@@ -18,10 +20,9 @@ const ForgotPasswordForm = ({ onSubmit, onBack, busy, error, sentTo }) => {
18
20
  }),
19
21
  " has an account, an email with a link to choose a new password is on its way. The link works once, for a limited time."
20
22
  ]
21
- }), /* @__PURE__ */ jsx(Button, {
22
- variant: "primary",
23
- className: "mt-4 min-h-10 w-full",
24
- onClick: onBack,
23
+ }), /* @__PURE__ */ jsx(RouteLink, {
24
+ to: back,
25
+ className: cn(buttonClass({ variant: "primary" }), "mt-4 min-h-10 w-full"),
25
26
  children: "Back to sign in"
26
27
  })]
27
28
  });
@@ -61,10 +62,9 @@ const ForgotPasswordForm = ({ onSubmit, onBack, busy, error, sentTo }) => {
61
62
  className: "min-h-10",
62
63
  children: "Send reset link"
63
64
  }),
64
- /* @__PURE__ */ jsx(Button, {
65
- variant: "ghost",
66
- onClick: onBack,
67
- className: "min-h-10",
65
+ /* @__PURE__ */ jsx(RouteLink, {
66
+ to: back,
67
+ className: cn(buttonClass({ variant: "ghost" }), "min-h-10"),
68
68
  children: "Back to sign in"
69
69
  })
70
70
  ]
@@ -6,7 +6,7 @@ import { AuthError } from "@protobase/client";
6
6
  import { jsx } from "react/jsx-runtime";
7
7
  //#region src/auth/forgot-password-page.tsx
8
8
  /** Asks the server to email a reset link that leads back to this page. */
9
- const ForgotPasswordPage = ({ onBack }) => {
9
+ const ForgotPasswordPage = ({ back }) => {
10
10
  const { session } = useAuth();
11
11
  const [busy, setBusy] = useState(false);
12
12
  const [error, setError] = useState();
@@ -27,7 +27,7 @@ const ForgotPasswordPage = ({ onBack }) => {
27
27
  busy,
28
28
  error,
29
29
  sentTo,
30
- onBack,
30
+ back,
31
31
  onSubmit: (email) => void submit(email)
32
32
  });
33
33
  };
@@ -0,0 +1,29 @@
1
+ import { Button } from "../primitives/button.js";
2
+ import { useEffect, useState } from "react";
3
+ import { jsx } from "react/jsx-runtime";
4
+ //#region src/auth/resend-code-button.tsx
5
+ /** "Send a new code", counting down first: the screen opens right after a code went out, and so does every resend. */
6
+ const ResendCodeButton = ({ onResend, cooldown = 30, disabled }) => {
7
+ const [until, setUntil] = useState(() => Date.now() + cooldown * 1e3);
8
+ const [now, setNow] = useState(() => Date.now());
9
+ const left = Math.max(0, Math.ceil((until - now) / 1e3));
10
+ useEffect(() => {
11
+ if (left === 0) return;
12
+ const timer = setInterval(() => setNow(Date.now()), 1e3);
13
+ return () => clearInterval(timer);
14
+ }, [left]);
15
+ return /* @__PURE__ */ jsx(Button, {
16
+ variant: "ghost",
17
+ disabled: disabled || left > 0,
18
+ onClick: () => {
19
+ const sent = Date.now();
20
+ setUntil(sent + cooldown * 1e3);
21
+ setNow(sent);
22
+ onResend();
23
+ },
24
+ className: "min-h-10",
25
+ children: left > 0 ? `Send a new code in ${left}s` : "Send a new code"
26
+ });
27
+ };
28
+ //#endregion
29
+ export { ResendCodeButton };
@@ -1,3 +1,4 @@
1
+ import { RouteLink } from "../primitives/route-link.js";
1
2
  import { Input } from "../primitives/input.js";
2
3
  import { Button } from "../primitives/button.js";
3
4
  import { AuthLayout } from "./auth-layout.js";
@@ -14,7 +15,7 @@ const Divider = () => /* @__PURE__ */ jsxs("div", {
14
15
  /* @__PURE__ */ jsx("span", { className: "h-px flex-1 bg-border" })
15
16
  ]
16
17
  });
17
- const SignInForm = ({ onSubmit, busy, error, workspace, notice, methods = ["password"], onSendCode, onPasskey, passkeyDomains = [], onForgotPassword, providers = [], onContinueWith, onSignUp, onBrowse }) => {
18
+ const SignInForm = ({ onSubmit, busy, error, workspace, notice, methods = ["password"], onSendCode, onPasskey, passkeyDomains = [], forgotPassword, providers = [], onContinueWith, signUp, onBrowse }) => {
18
19
  const [email, setEmail] = useState("");
19
20
  const [password, setPassword] = useState("");
20
21
  const emailInput = useRef(null);
@@ -125,22 +126,20 @@ const SignInForm = ({ onSubmit, busy, error, workspace, notice, methods = ["pass
125
126
  className: "min-h-10",
126
127
  children: [/* @__PURE__ */ jsx(Mail, { className: "size-4" }), "Email me a sign-in code"]
127
128
  }),
128
- withPassword && onForgotPassword && /* @__PURE__ */ jsx("button", {
129
- type: "button",
130
- onClick: onForgotPassword,
129
+ withPassword && forgotPassword && /* @__PURE__ */ jsx(RouteLink, {
130
+ to: forgotPassword,
131
131
  className: "self-center text-[13px] font-medium text-primary-text hover:underline",
132
132
  children: "Forgot password?"
133
133
  })
134
134
  ]
135
135
  }),
136
- onSignUp && /* @__PURE__ */ jsxs("p", {
136
+ signUp && /* @__PURE__ */ jsxs("p", {
137
137
  className: "mt-4 text-center text-[13px] text-muted-foreground",
138
138
  children: [
139
139
  "New here?",
140
140
  " ",
141
- /* @__PURE__ */ jsx("button", {
142
- type: "button",
143
- onClick: onSignUp,
141
+ /* @__PURE__ */ jsx(RouteLink, {
142
+ to: signUp,
144
143
  className: "font-medium text-primary-text hover:underline",
145
144
  children: "Create an account"
146
145
  })
@@ -5,7 +5,7 @@ import { useState } from "react";
5
5
  import { AuthError } from "@protobase/client";
6
6
  import { jsx } from "react/jsx-runtime";
7
7
  //#region src/auth/sign-in-page.tsx
8
- const SignInPage = ({ workspace, notice, onForgotPassword, onSignUp, onBrowse, onCodeSent, error: initialError }) => {
8
+ const SignInPage = ({ workspace, notice, forgotPassword, signUp, onBrowse, onCodeSent, error: initialError }) => {
9
9
  const { signIn, signInSocial, signInProviders, signInMethods, passkeyDomains, sendSignInCode, signInWithPasskey } = useAuth();
10
10
  const [busy, setBusy] = useState(false);
11
11
  const [error, setError] = useState(initialError);
@@ -26,8 +26,8 @@ const SignInPage = ({ workspace, notice, onForgotPassword, onSignUp, onBrowse, o
26
26
  workspace,
27
27
  notice,
28
28
  methods: signInMethods,
29
- onForgotPassword,
30
- onSignUp,
29
+ forgotPassword,
30
+ signUp,
31
31
  onBrowse,
32
32
  providers: signInProviders,
33
33
  onContinueWith: (provider) => void attempt(() => signInSocial(provider), signInMessage),
@@ -1,3 +1,4 @@
1
+ import { RouteLink } from "../primitives/route-link.js";
1
2
  import { useAuth } from "./auth-provider.js";
2
3
  import { Button, buttonClass } from "../primitives/button.js";
3
4
  import { useSignInAddress } from "./use-sign-in-address.js";
@@ -19,21 +20,24 @@ const Benefits = ({ benefits }) => benefits && benefits.length > 0 ? /* @__PURE_
19
20
  }) : null;
20
21
  const Actions = ({ prompt }) => {
21
22
  const { canSignUp } = useAuth();
22
- const { open } = useSignInAddress();
23
- return /* @__PURE__ */ jsxs(Fragment$1, { children: [prompt.signUp ? /* @__PURE__ */ jsx("a", {
23
+ const { link } = useSignInAddress();
24
+ const primary = buttonClass({ variant: "primary" });
25
+ const signUp = prompt.signUp ? /* @__PURE__ */ jsx("a", {
24
26
  href: prompt.signUp.href,
25
27
  target: "_blank",
26
28
  rel: "noreferrer",
27
- className: buttonClass(),
29
+ className: primary,
28
30
  children: prompt.signUp.label
29
- }) : canSignUp && /* @__PURE__ */ jsx(Button, {
30
- onClick: () => open("sign-up"),
31
+ }) : canSignUp && /* @__PURE__ */ jsx(RouteLink, {
32
+ to: link("sign-up"),
33
+ className: primary,
31
34
  children: "Create an account"
32
- }), /* @__PURE__ */ jsx(Button, {
33
- variant: "primary",
34
- onClick: () => open(),
35
+ });
36
+ return /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(RouteLink, {
37
+ to: link(),
38
+ className: signUp ? buttonClass() : primary,
35
39
  children: "Sign in"
36
- })] });
40
+ }), signUp] });
37
41
  };
38
42
  /**
39
43
  * What a visitor who is not signed in is told about something they could use once signed in: the prompt's title, what
@@ -0,0 +1,22 @@
1
+ import { CodeForm } from "./code-form.js";
2
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
3
+ //#region src/auth/sign-up-code-form.tsx
4
+ /** The second step of making an account: the emailed code on its own, before the name and password. */
5
+ const SignUpCodeForm = ({ email, onBack, ...rest }) => /* @__PURE__ */ jsx(CodeForm, {
6
+ title: "Check your email",
7
+ description: "Enter the code we sent to create your account.",
8
+ explanation: /* @__PURE__ */ jsxs(Fragment, { children: [
9
+ "A 6-digit code is on its way to ",
10
+ /* @__PURE__ */ jsx("span", {
11
+ className: "font-medium text-foreground",
12
+ children: email
13
+ }),
14
+ ". It works for 5 minutes, once. If the address has an account already, the email says so instead."
15
+ ] }),
16
+ submitLabel: "Continue",
17
+ onChangeAddress: onBack,
18
+ changeAddressLabel: "Use another address",
19
+ ...rest
20
+ });
21
+ //#endregion
22
+ export { SignUpCodeForm };
@@ -1,129 +1,99 @@
1
1
  import { Input } from "../primitives/input.js";
2
2
  import { Button } from "../primitives/button.js";
3
- import { CodeInput } from "./code-input.js";
4
3
  import { AuthLayout } from "./auth-layout.js";
5
4
  import { useId, useState } from "react";
6
5
  import { jsx, jsxs } from "react/jsx-runtime";
7
6
  //#region src/auth/sign-up-details-form.tsx
8
- /** The second step of making an account: the emailed code, the person's name and how they will sign in. */
9
- const SignUpDetailsForm = ({ email, onSubmit, onResend, onBack, methods, busy, error, notice }) => {
10
- const [code, setCode] = useState("");
7
+ /** The last step of making an account, once the emailed code was right: the person's name and how they will sign in. */
8
+ const SignUpDetailsForm = ({ email, onSubmit, onBack, methods, busy, error }) => {
11
9
  const [name, setName] = useState("");
12
10
  const [password, setPassword] = useState("");
13
11
  const passwordHint = useId();
14
12
  const withPassword = methods.includes("password");
15
13
  const passwordOptional = methods.includes("emailCode");
16
14
  return /* @__PURE__ */ jsxs(AuthLayout, {
17
- title: "Check your email",
18
- description: "Enter the code we sent to create your account.",
19
- children: [
20
- /* @__PURE__ */ jsxs("p", {
21
- className: "mb-4 text-[13px] text-muted-foreground",
22
- children: [
23
- "A 6-digit code is on its way to ",
24
- /* @__PURE__ */ jsx("span", {
25
- className: "font-medium text-foreground",
26
- children: email
27
- }),
28
- ". It works for 5 minutes, once. If the address has an account already, the email says so instead."
29
- ]
30
- }),
31
- notice && /* @__PURE__ */ jsx("p", {
32
- role: "status",
33
- className: "mb-4 rounded-md bg-success-soft px-3 py-2 text-xs font-medium text-success-text",
34
- children: notice
35
- }),
36
- /* @__PURE__ */ jsxs("form", {
37
- className: "flex flex-col gap-4",
38
- onSubmit: (event) => {
39
- event.preventDefault();
40
- onSubmit({
41
- code: code.trim(),
42
- name: name.trim(),
43
- ...withPassword && password && { password }
44
- });
45
- },
46
- children: [
47
- /* @__PURE__ */ jsxs("label", {
15
+ title: "Your details",
16
+ description: "One last step to create your account.",
17
+ children: [/* @__PURE__ */ jsxs("p", {
18
+ className: "mb-4 text-[13px] text-muted-foreground",
19
+ children: [
20
+ "The code was right: the account is for ",
21
+ /* @__PURE__ */ jsx("span", {
22
+ className: "font-medium text-foreground",
23
+ children: email
24
+ }),
25
+ "."
26
+ ]
27
+ }), /* @__PURE__ */ jsxs("form", {
28
+ className: "flex flex-col gap-4",
29
+ onSubmit: (event) => {
30
+ event.preventDefault();
31
+ onSubmit({
32
+ name: name.trim(),
33
+ ...withPassword && password && { password }
34
+ });
35
+ },
36
+ children: [
37
+ /* @__PURE__ */ jsxs("label", {
38
+ className: "flex flex-col gap-1.5 text-[13px] font-medium",
39
+ children: ["Your name", /* @__PURE__ */ jsx(Input, {
40
+ name: "name",
41
+ autoComplete: "name",
42
+ required: true,
43
+ autoFocus: true,
44
+ maxLength: 200,
45
+ value: name,
46
+ onChange: (event) => setName(event.target.value),
47
+ className: "min-h-6"
48
+ })]
49
+ }),
50
+ withPassword && /* @__PURE__ */ jsxs("div", {
51
+ className: "flex flex-col gap-1.5",
52
+ children: [/* @__PURE__ */ jsxs("label", {
48
53
  className: "flex flex-col gap-1.5 text-[13px] font-medium",
49
- children: ["Code", /* @__PURE__ */ jsx(CodeInput, {
50
- name: "code",
51
- required: true,
52
- autoFocus: true,
53
- value: code,
54
- invalid: Boolean(error),
55
- onChange: (event) => setCode(event.target.value)
56
- })]
57
- }),
58
- /* @__PURE__ */ jsxs("label", {
59
- className: "flex flex-col gap-1.5 text-[13px] font-medium",
60
- children: ["Your name", /* @__PURE__ */ jsx(Input, {
61
- name: "name",
62
- autoComplete: "name",
63
- required: true,
64
- maxLength: 200,
65
- value: name,
66
- onChange: (event) => setName(event.target.value),
54
+ children: [passwordOptional ? "Password (optional)" : "Password", /* @__PURE__ */ jsx(Input, {
55
+ type: "password",
56
+ name: "password",
57
+ autoComplete: "new-password",
58
+ "aria-describedby": passwordHint,
59
+ required: !passwordOptional,
60
+ minLength: 12,
61
+ maxLength: 128,
62
+ value: password,
63
+ onChange: (event) => setPassword(event.target.value),
67
64
  className: "min-h-6"
68
65
  })]
69
- }),
70
- withPassword && /* @__PURE__ */ jsxs("div", {
71
- className: "flex flex-col gap-1.5",
72
- children: [/* @__PURE__ */ jsxs("label", {
73
- className: "flex flex-col gap-1.5 text-[13px] font-medium",
74
- children: [passwordOptional ? "Password (optional)" : "Password", /* @__PURE__ */ jsx(Input, {
75
- type: "password",
76
- name: "password",
77
- autoComplete: "new-password",
78
- "aria-describedby": passwordHint,
79
- required: !passwordOptional,
80
- minLength: 12,
81
- maxLength: 128,
82
- value: password,
83
- onChange: (event) => setPassword(event.target.value),
84
- className: "min-h-6"
85
- })]
86
- }), /* @__PURE__ */ jsxs("p", {
87
- id: passwordHint,
88
- className: "text-xs text-muted-foreground",
89
- children: [
90
- "At least ",
91
- 12,
92
- " characters.",
93
- passwordOptional && " Without one, you sign in with a code we email you."
94
- ]
95
- })]
96
- }),
97
- error && /* @__PURE__ */ jsx("p", {
98
- role: "alert",
99
- className: "text-xs font-medium text-danger-text",
100
- children: error
101
- }),
102
- /* @__PURE__ */ jsx(Button, {
103
- variant: "primary",
104
- type: "submit",
105
- loading: busy,
106
- className: "min-h-10",
107
- children: "Create account"
108
- }),
109
- /* @__PURE__ */ jsxs("div", {
110
- className: "flex justify-between gap-2",
111
- children: [/* @__PURE__ */ jsx(Button, {
112
- variant: "ghost",
113
- onClick: onBack,
114
- className: "min-h-10",
115
- children: "Use another address"
116
- }), /* @__PURE__ */ jsx(Button, {
117
- variant: "ghost",
118
- onClick: onResend,
119
- disabled: busy,
120
- className: "min-h-10",
121
- children: "Send a new code"
122
- })]
123
- })
124
- ]
125
- })
126
- ]
66
+ }), /* @__PURE__ */ jsxs("p", {
67
+ id: passwordHint,
68
+ className: "text-xs text-muted-foreground",
69
+ children: [
70
+ "At least ",
71
+ 12,
72
+ " characters.",
73
+ passwordOptional && " Without one, you sign in with a code we email you."
74
+ ]
75
+ })]
76
+ }),
77
+ error && /* @__PURE__ */ jsx("p", {
78
+ role: "alert",
79
+ className: "text-xs font-medium text-danger-text",
80
+ children: error
81
+ }),
82
+ /* @__PURE__ */ jsx(Button, {
83
+ variant: "primary",
84
+ type: "submit",
85
+ loading: busy,
86
+ className: "min-h-10",
87
+ children: "Create account"
88
+ }),
89
+ /* @__PURE__ */ jsx(Button, {
90
+ variant: "ghost",
91
+ onClick: onBack,
92
+ className: "min-h-10",
93
+ children: "Use another address"
94
+ })
95
+ ]
96
+ })]
127
97
  });
128
98
  };
129
99
  //#endregion