@indietabletop/appkit 4.1.1 → 5.0.0-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.
@@ -7,7 +7,7 @@ import { ExternalLink } from "../ExternalLink.tsx";
7
7
  import {
8
8
  FormSubmitButton,
9
9
  type FormSubmitButtonProps,
10
- } from "../FormSubmitButton.tsx";
10
+ } from "../form/FormSubmitButton.tsx";
11
11
  import { IndieTabletopClubLogo } from "../IndieTabletopClubLogo.tsx";
12
12
  import { IndieTabletopClubSymbol } from "../IndieTabletopClubSymbol.tsx";
13
13
  import { LoadingIndicator } from "../LoadingIndicator.tsx";
@@ -5,11 +5,10 @@ import {
5
5
  FormInput,
6
6
  type FormInputProps,
7
7
  FormLabel,
8
- useFormContext,
9
- useStoreState,
10
8
  } from "@ariakit/react";
11
9
  import { type ReactNode } from "react";
12
10
  import { cx } from "../class-names.ts";
11
+ import { SubmitErrorAlert } from "../form/SubmitErrorAlert.tsx";
13
12
  import * as css from "./style.css.ts";
14
13
 
15
14
  export type LetterheadTextFieldProps = FormInputProps & {
@@ -101,16 +100,7 @@ type LetterheadSubmitErrorProps = {
101
100
  * is no need to guard it with an if statement.
102
101
  */
103
102
  export function LetterheadSubmitError(props: LetterheadSubmitErrorProps) {
104
- const form = useFormContext();
105
- const message = useStoreState(form, (s) => {
106
- return s?.errors[props.name] as string | undefined;
107
- });
108
-
109
- return (
110
- <div role="alert" className={css.submitError}>
111
- {message}
112
- </div>
113
- );
103
+ return <SubmitErrorAlert {...props} className={css.submitError} />;
114
104
  }
115
105
 
116
106
  export function LetterheadHeader(props: { children: ReactNode }) {
@@ -82,10 +82,6 @@ export const submitError = style({
82
82
  backgroundColor: Color.PALE_GRAY,
83
83
  borderRadius: "0.75rem",
84
84
  textAlign: "start",
85
-
86
- ":empty": {
87
- display: "none",
88
- },
89
85
  });
90
86
 
91
87
  export const header = style({
@@ -5,7 +5,7 @@ import {
5
5
  useStoreState,
6
6
  } from "@ariakit/react";
7
7
  import type { ReactNode } from "react";
8
- import { fadeIn } from "./animations.css.ts";
8
+ import { fadeIn } from "../animations.css.ts";
9
9
 
10
10
  export type FormSubmitButtonProps = FormSubmitProps & {
11
11
  children: ReactNode;
@@ -0,0 +1,21 @@
1
+ import { useFormContext, useStoreState } from "@ariakit/react";
2
+ import { cx } from "../class-names.ts";
3
+ import { submitErrorAlert } from "./style.css.ts";
4
+
5
+ export type SubmitErrorMessageProps = {
6
+ name: string;
7
+ className?: string;
8
+ };
9
+
10
+ export function SubmitErrorAlert(props: SubmitErrorMessageProps) {
11
+ const form = useFormContext();
12
+ const message = useStoreState(form, (s) => {
13
+ return s?.errors[props.name] as string | undefined;
14
+ });
15
+
16
+ return (
17
+ <div role="alert" {...cx(props, submitErrorAlert.container)}>
18
+ {message}
19
+ </div>
20
+ );
21
+ }
@@ -0,0 +1,9 @@
1
+ import { style } from "@vanilla-extract/css";
2
+
3
+ export const submitErrorAlert = {
4
+ container: style({
5
+ ":empty": {
6
+ display: "none",
7
+ },
8
+ }),
9
+ };
package/lib/index.ts CHANGED
@@ -8,7 +8,8 @@ export * from "./AuthCard/AuthCard.tsx";
8
8
  export * from "./DialogTrigger/index.tsx";
9
9
  export * from "./DocumentTitle/DocumentTitle.tsx";
10
10
  export * from "./ExternalLink.tsx";
11
- export * from "./FormSubmitButton.tsx";
11
+ export * from "./form/FormSubmitButton.tsx";
12
+ export * from "./form/SubmitErrorAlert.tsx";
12
13
  export * from "./FullscreenDismissBlocker.tsx";
13
14
  export * from "./IndieTabletopClubLogo.tsx";
14
15
  export * from "./IndieTabletopClubSymbol.tsx";
package/lib/use-form.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import { type FormStoreState, useFormStore } from "@ariakit/react";
2
2
  import { useState } from "react";
3
3
  import { Failure, Success } from "./async-op.ts";
4
+ import { caughtValueToString } from "./caught-value.ts";
4
5
 
5
6
  type Validator<T> = (value: T) => string | null;
6
7
 
@@ -39,17 +40,21 @@ export function useForm<T extends object, R>(props: {
39
40
  });
40
41
 
41
42
  form.useSubmit(async (state) => {
42
- const submitOp = await props.onSubmit(state);
43
+ try {
44
+ const submitOp = await props.onSubmit(state);
43
45
 
44
- if (submitOp.isFailure) {
45
- form.setError(submitName, submitOp.failure);
46
- }
46
+ if (submitOp.isFailure) {
47
+ form.setError(submitName, submitOp.failure);
48
+ }
47
49
 
48
- if (submitOp.isSuccess) {
49
- await props.onSuccess?.(submitOp.value, state);
50
- }
50
+ if (submitOp.isSuccess) {
51
+ await props.onSuccess?.(submitOp.value, state);
52
+ }
51
53
 
52
- setOp(submitOp);
54
+ setOp(submitOp);
55
+ } catch (error) {
56
+ form.setError(submitName, caughtValueToString(error));
57
+ }
53
58
  });
54
59
 
55
60
  form.useValidate((state) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@indietabletop/appkit",
3
- "version": "4.1.1",
3
+ "version": "5.0.0-0",
4
4
  "description": "A collection of modules used in apps built by Indie Tabletop Club",
5
5
  "private": false,
6
6
  "type": "module",