@indietabletop/appkit 3.2.0-10 → 3.2.0-12

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.
@@ -0,0 +1,36 @@
1
+ import {
2
+ DialogProvider,
3
+ useDialogContext,
4
+ useStoreState,
5
+ } from "@ariakit/react";
6
+ import type { ReactElement, ReactNode } from "react";
7
+
8
+ function DialogGuard(props: { children: ReactNode }) {
9
+ const dialog = useDialogContext();
10
+ const isMounted = useStoreState(dialog, (store) => store?.mounted);
11
+ if (!isMounted) {
12
+ return null;
13
+ }
14
+ return props.children;
15
+ }
16
+
17
+ /**
18
+ * Wraps AriaKit's DialogProvider, but take a tuple of Dialog a DialogDisclosure
19
+ * elements as children, and makes sense that the Dialog component is not
20
+ * rendered when it is hidden.
21
+ *
22
+ * This is important in cases where the dialog contains a form that should only
23
+ * be initialized and re-initialized when the dialog opens, not when it is first
24
+ * rendered.
25
+ */
26
+ export function DialogTrigger(props: {
27
+ children: [ReactElement, ReactElement];
28
+ }) {
29
+ const [dialog, button] = props.children;
30
+ return (
31
+ <DialogProvider>
32
+ <DialogGuard>{dialog}</DialogGuard>
33
+ {button}
34
+ </DialogProvider>
35
+ );
36
+ }
@@ -2,7 +2,7 @@ import { createTheme, style } from "@vanilla-extract/css";
2
2
  import { recipe } from "@vanilla-extract/recipes";
3
3
  import { textVariants } from "../atomic.css.ts";
4
4
  import { manofa, minion } from "../common.css.ts";
5
- import { Hover } from "../media.ts";
5
+ import { Hover, MinWidth } from "../media.ts";
6
6
 
7
7
  const align = {
8
8
  start: textVariants({ textAlign: "start" }),
@@ -11,7 +11,7 @@ const align = {
11
11
  };
12
12
 
13
13
  export const [letterheadTheme, { padding, footerMargin }] = createTheme({
14
- padding: "clamp(1rem, 8vw, 4rem)",
14
+ padding: "1.25rem",
15
15
  footerMargin: "3rem",
16
16
  });
17
17
 
@@ -25,6 +25,14 @@ export const letterhead = recipe({
25
25
  borderRadius: "1rem",
26
26
  marginInline: "auto",
27
27
  maxInlineSize: "36rem",
28
+
29
+ "@media": {
30
+ [MinWidth.SMALL]: {
31
+ vars: {
32
+ [padding]: `clamp(1.5rem, 8%, 4rem)`,
33
+ },
34
+ },
35
+ },
28
36
  },
29
37
  ],
30
38
 
@@ -19,6 +19,7 @@ export const fieldLabel = style([
19
19
  fontSize: "0.75rem",
20
20
  fontWeight: 600,
21
21
  marginBottom: "0.5rem",
22
+ textAlign: "start",
22
23
  },
23
24
  ]);
24
25
 
@@ -31,6 +32,7 @@ export const fieldInput = style([
31
32
  fontSize: "1rem",
32
33
  lineHeight: "1.25rem",
33
34
  padding: "1rem 0 1rem 1rem",
35
+ textAlign: "start",
34
36
 
35
37
  ":read-only": {
36
38
  backgroundColor: "hsl(0 0% 0% / 0.05)",
@@ -50,6 +52,7 @@ export const fieldIssue = style({
50
52
  color: Color.PURPLE,
51
53
  fontSize: "0.875rem",
52
54
  marginTop: "0.5rem",
55
+ textAlign: "start",
53
56
 
54
57
  ":empty": {
55
58
  display: "none",
@@ -60,6 +63,7 @@ export const fieldHint = style({
60
63
  color: Color.MID_GRAY,
61
64
  fontSize: "0.875rem",
62
65
  marginTop: "0.5rem",
66
+ textAlign: "start",
63
67
 
64
68
  selectors: {
65
69
  [`${fieldIssue}:not(:empty) + &`]: {
@@ -73,6 +77,7 @@ export const submitError = style({
73
77
  color: Color.PURPLE,
74
78
  backgroundColor: Color.PALE_GRAY,
75
79
  borderRadius: "0.75rem",
80
+ textAlign: "start",
76
81
 
77
82
  ":empty": {
78
83
  display: "none",
@@ -10,6 +10,11 @@ describe("getFetchFailureMessages", () => {
10
10
 
11
11
  expect(result).toMatchInlineSnapshot(`
12
12
  {
13
+ "action": {
14
+ "href": "~/",
15
+ "label": "Go back",
16
+ "type": "LINK",
17
+ },
13
18
  "description": "The link you have followed might be broken.",
14
19
  "title": "Not found",
15
20
  }
@@ -21,6 +26,10 @@ describe("getFetchFailureMessages", () => {
21
26
 
22
27
  expect(result).toMatchInlineSnapshot(`
23
28
  {
29
+ "action": {
30
+ "label": "Reload app",
31
+ "type": "RELOAD",
32
+ },
24
33
  "description": "This is probably an issue with our servers. You can try refreshing.",
25
34
  "title": "Ooops, something went wrong",
26
35
  }
@@ -35,6 +44,11 @@ describe("getFetchFailureMessages", () => {
35
44
 
36
45
  expect(result).toMatchInlineSnapshot(`
37
46
  {
47
+ "action": {
48
+ "href": "~/",
49
+ "label": "Go back",
50
+ "type": "LINK",
51
+ },
38
52
  "description": "The link you have followed might be broken.",
39
53
  "title": "Army not found",
40
54
  }
@@ -54,6 +68,11 @@ describe("getFetchFailureMessages", () => {
54
68
 
55
69
  expect(result).toMatchInlineSnapshot(`
56
70
  {
71
+ "action": {
72
+ "href": "~/",
73
+ "label": "Go back",
74
+ "type": "LINK",
75
+ },
57
76
  "description": "It might have been deleted.",
58
77
  "title": "Army not found",
59
78
  }
@@ -65,6 +84,10 @@ describe("getFetchFailureMessages", () => {
65
84
 
66
85
  expect(result).toMatchInlineSnapshot(`
67
86
  {
87
+ "action": {
88
+ "label": "Retry request",
89
+ "type": "REFETCH",
90
+ },
68
91
  "description": "Check your interent connection and try again.",
69
92
  "title": "No connection",
70
93
  }
@@ -76,6 +99,10 @@ describe("getFetchFailureMessages", () => {
76
99
 
77
100
  expect(result).toMatchInlineSnapshot(`
78
101
  {
102
+ "action": {
103
+ "label": "Reload app",
104
+ "type": "RELOAD",
105
+ },
79
106
  "description": "This is probably an issue on our side. You can try refreshing.",
80
107
  "title": "Ooops, something went wrong",
81
108
  }
@@ -87,6 +114,10 @@ describe("getFetchFailureMessages", () => {
87
114
 
88
115
  expect(result).toMatchInlineSnapshot(`
89
116
  {
117
+ "action": {
118
+ "label": "Reload app",
119
+ "type": "RELOAD",
120
+ },
90
121
  "description": "This is probably an issue on our side. You can try refreshing.",
91
122
  "title": "Ooops, something went wrong",
92
123
  }
@@ -29,23 +29,44 @@ function createFailureMessageGetter<T>(
29
29
  };
30
30
  }
31
31
 
32
- export const getFetchFailureMessages = createFailureMessageGetter(
32
+ export type FetchFailureAction =
33
+ | {
34
+ type: "LINK";
35
+ href: string;
36
+ label: string;
37
+ }
38
+ | {
39
+ type: "RELOAD" | "REFETCH";
40
+ label: string;
41
+ };
42
+
43
+ export type FetchFailure = {
44
+ title: string;
45
+ description: string;
46
+ action: FetchFailureAction;
47
+ };
48
+
49
+ export const getFetchFailureMessages = createFailureMessageGetter<FetchFailure>(
33
50
  {
34
51
  404: {
35
52
  title: `Not found`,
36
53
  description: `The link you have followed might be broken.`,
54
+ action: { type: "LINK", href: "~/", label: "Go back" },
37
55
  },
38
56
  500: {
39
57
  title: `Ooops, something went wrong`,
40
58
  description: `This is probably an issue with our servers. You can try refreshing.`,
59
+ action: { type: "RELOAD", label: "Reload app" },
41
60
  },
42
61
  connection: {
43
62
  title: `No connection`,
44
63
  description: `Check your interent connection and try again.`,
64
+ action: { type: "REFETCH", label: "Retry request" },
45
65
  },
46
66
  fallback: {
47
67
  title: `Ooops, something went wrong`,
48
68
  description: `This is probably an issue on our side. You can try refreshing.`,
69
+ action: { type: "RELOAD", label: "Reload app" },
49
70
  },
50
71
  },
51
72
  {
package/lib/index.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  // Components
2
+ export * from "./DialogTrigger/index.tsx";
2
3
  export * from "./ExternalLink.tsx";
3
4
  export * from "./FormSubmitButton.tsx";
4
5
  export * from "./FullscreenDismissBlocker.tsx";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@indietabletop/appkit",
3
- "version": "3.2.0-10",
3
+ "version": "3.2.0-12",
4
4
  "description": "A collection of modules used in apps built by Indie Tabletop Club",
5
5
  "private": false,
6
6
  "type": "module",