@authhero/react-admin 0.10.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 (110) hide show
  1. package/.eslintrc.js +21 -0
  2. package/.vercelignore +4 -0
  3. package/CHANGELOG.md +56 -0
  4. package/LICENSE +21 -0
  5. package/README.md +50 -0
  6. package/index.html +125 -0
  7. package/package.json +61 -0
  8. package/prettier.config.js +1 -0
  9. package/public/favicon.ico +0 -0
  10. package/public/manifest.json +15 -0
  11. package/src/App.spec.tsx +42 -0
  12. package/src/App.tsx +232 -0
  13. package/src/AuthCallback.tsx +138 -0
  14. package/src/Layout.tsx +12 -0
  15. package/src/TenantsApp.tsx +115 -0
  16. package/src/auth0DataProvider.ts +1242 -0
  17. package/src/authProvider.ts +521 -0
  18. package/src/components/CertificateErrorDialog.tsx +116 -0
  19. package/src/components/DomainSelector.tsx +401 -0
  20. package/src/components/TenantAppBar.tsx +83 -0
  21. package/src/components/TenantLayout.tsx +25 -0
  22. package/src/components/TenantsAppBar.tsx +21 -0
  23. package/src/components/TenantsLayout.tsx +28 -0
  24. package/src/components/activity/ActivityDashboard.tsx +381 -0
  25. package/src/components/activity/index.ts +1 -0
  26. package/src/components/branding/BrandingList.tsx +0 -0
  27. package/src/components/branding/BrandingShow.tsx +0 -0
  28. package/src/components/branding/ThemesTab.tsx +286 -0
  29. package/src/components/branding/edit.tsx +149 -0
  30. package/src/components/branding/hooks/useThemesData.ts +123 -0
  31. package/src/components/branding/index.ts +2 -0
  32. package/src/components/branding/list.tsx +12 -0
  33. package/src/components/clients/create.tsx +12 -0
  34. package/src/components/clients/edit.tsx +1285 -0
  35. package/src/components/clients/index.ts +3 -0
  36. package/src/components/clients/list.tsx +37 -0
  37. package/src/components/common/DateAgo.tsx +6 -0
  38. package/src/components/common/JsonOutput.tsx +26 -0
  39. package/src/components/common/index.ts +1 -0
  40. package/src/components/connections/create.tsx +35 -0
  41. package/src/components/connections/edit.tsx +212 -0
  42. package/src/components/connections/index.ts +3 -0
  43. package/src/components/connections/list.tsx +15 -0
  44. package/src/components/custom-domains/create.tsx +26 -0
  45. package/src/components/custom-domains/edit.tsx +101 -0
  46. package/src/components/custom-domains/index.ts +3 -0
  47. package/src/components/custom-domains/list.tsx +16 -0
  48. package/src/components/flows/create.tsx +30 -0
  49. package/src/components/flows/edit.tsx +238 -0
  50. package/src/components/flows/index.ts +3 -0
  51. package/src/components/flows/list.tsx +15 -0
  52. package/src/components/forms/FlowEditor.tsx +1363 -0
  53. package/src/components/forms/NodeEditor.tsx +1119 -0
  54. package/src/components/forms/RichTextEditor.tsx +145 -0
  55. package/src/components/forms/create.tsx +30 -0
  56. package/src/components/forms/edit.tsx +256 -0
  57. package/src/components/forms/index.ts +3 -0
  58. package/src/components/forms/list.tsx +16 -0
  59. package/src/components/hooks/create.tsx +96 -0
  60. package/src/components/hooks/edit.tsx +114 -0
  61. package/src/components/hooks/index.ts +3 -0
  62. package/src/components/hooks/list.tsx +17 -0
  63. package/src/components/listActions/PostListActions.tsx +10 -0
  64. package/src/components/logs/LogIcon.tsx +32 -0
  65. package/src/components/logs/LogShow.tsx +82 -0
  66. package/src/components/logs/LogType.tsx +38 -0
  67. package/src/components/logs/index.ts +4 -0
  68. package/src/components/logs/list.tsx +41 -0
  69. package/src/components/organizations/create.tsx +13 -0
  70. package/src/components/organizations/edit.tsx +682 -0
  71. package/src/components/organizations/index.ts +3 -0
  72. package/src/components/organizations/list.tsx +21 -0
  73. package/src/components/resource-servers/create.tsx +87 -0
  74. package/src/components/resource-servers/edit.tsx +121 -0
  75. package/src/components/resource-servers/index.ts +3 -0
  76. package/src/components/resource-servers/list.tsx +47 -0
  77. package/src/components/roles/create.tsx +12 -0
  78. package/src/components/roles/edit.tsx +426 -0
  79. package/src/components/roles/index.ts +3 -0
  80. package/src/components/roles/list.tsx +24 -0
  81. package/src/components/sessions/edit.tsx +101 -0
  82. package/src/components/sessions/index.ts +3 -0
  83. package/src/components/sessions/list.tsx +20 -0
  84. package/src/components/sessions/show.tsx +113 -0
  85. package/src/components/settings/edit.tsx +236 -0
  86. package/src/components/settings/index.ts +2 -0
  87. package/src/components/settings/list.tsx +14 -0
  88. package/src/components/tenants/create.tsx +20 -0
  89. package/src/components/tenants/edit.tsx +54 -0
  90. package/src/components/tenants/index.ts +2 -0
  91. package/src/components/tenants/list.tsx +67 -0
  92. package/src/components/themes/edit.tsx +200 -0
  93. package/src/components/themes/index.ts +2 -0
  94. package/src/components/themes/list.tsx +12 -0
  95. package/src/components/users/create.tsx +144 -0
  96. package/src/components/users/edit.tsx +1711 -0
  97. package/src/components/users/index.ts +3 -0
  98. package/src/components/users/list.tsx +35 -0
  99. package/src/data.json +121 -0
  100. package/src/dataProvider.ts +97 -0
  101. package/src/index.tsx +106 -0
  102. package/src/lib/logs.ts +21 -0
  103. package/src/types/reactflow.d.ts +86 -0
  104. package/src/utils/domainUtils.ts +169 -0
  105. package/src/utils/tokenUtils.ts +75 -0
  106. package/src/vite-env.d.ts +1 -0
  107. package/tsconfig.json +37 -0
  108. package/tsconfig.node.json +10 -0
  109. package/vercel.json +17 -0
  110. package/vite.config.ts +30 -0
@@ -0,0 +1,149 @@
1
+ import {
2
+ DateField,
3
+ Edit,
4
+ FieldTitle,
5
+ Labeled,
6
+ TextInput,
7
+ TabbedForm,
8
+ } from "react-admin";
9
+ import { ColorInput } from "react-admin-color-picker";
10
+ import { useInput, useRecordContext } from "react-admin";
11
+ import { useState, useEffect } from "react";
12
+ import { ThemesTab } from "./ThemesTab";
13
+
14
+ function PageBackgroundInput(props) {
15
+ const { field } = useInput(props);
16
+ const record = useRecordContext();
17
+ const value = field.value ?? record?.colors?.page_background;
18
+ const [mode, setMode] = useState(
19
+ typeof value === "string" || !value ? "color" : "gradient",
20
+ );
21
+ const [color, setColor] = useState(typeof value === "string" ? value : "");
22
+ const [gradient, setGradient] = useState(
23
+ typeof value === "object" && value
24
+ ? {
25
+ type: value.type || "linear-gradient",
26
+ start: value.start || "",
27
+ end: value.end || "",
28
+ angle_deg: value.angle_deg || 0,
29
+ }
30
+ : { type: "linear-gradient", start: "", end: "", angle_deg: 0 },
31
+ );
32
+
33
+ useEffect(() => {
34
+ if (mode === "color") {
35
+ field.onChange(color);
36
+ } else {
37
+ field.onChange(gradient);
38
+ }
39
+ // eslint-disable-next-line react-hooks/exhaustive-deps
40
+ }, [mode, color, gradient]);
41
+
42
+ // ColorInput is uncontrolled, so we use a key to force remount on value change
43
+ return (
44
+ <div style={{ marginBottom: 16 }}>
45
+ <label style={{ fontWeight: 500 }}>Page Background</label>
46
+ <div style={{ margin: "8px 0" }}>
47
+ <select
48
+ value={mode}
49
+ onChange={(e) => setMode(e.target.value)}
50
+ style={{ marginBottom: 8 }}
51
+ >
52
+ <option value="color">Solid Color</option>
53
+ <option value="gradient">Gradient</option>
54
+ </select>
55
+ </div>
56
+ {mode === "color" ? (
57
+ <>
58
+ <ColorInput
59
+ key={color}
60
+ source={props.source}
61
+ label="Solid Color"
62
+ // No value prop, uncontrolled
63
+ />
64
+ <TextInput
65
+ source="_page_background_color_helper"
66
+ style={{ display: "none" }}
67
+ value={color}
68
+ onChange={(e) => setColor(e.target.value)}
69
+ />
70
+ </>
71
+ ) : (
72
+ <div style={{ display: "flex", flexDirection: "column", gap: 8 }}>
73
+ <TextInput
74
+ source="colors.page_background.type"
75
+ label="Type"
76
+ value={gradient.type}
77
+ onChange={(e) =>
78
+ setGradient((g) => ({ ...g, type: e.target.value }))
79
+ }
80
+ />
81
+ <ColorInput
82
+ key={gradient.start}
83
+ source="colors.page_background.start"
84
+ label="Start Color"
85
+ />
86
+ <TextInput
87
+ source="_page_background_start_helper"
88
+ style={{ display: "none" }}
89
+ value={gradient.start}
90
+ onChange={(e) =>
91
+ setGradient((g) => ({ ...g, start: e.target.value }))
92
+ }
93
+ />
94
+ <ColorInput
95
+ key={gradient.end}
96
+ source="colors.page_background.end"
97
+ label="End Color"
98
+ />
99
+ <TextInput
100
+ source="_page_background_end_helper"
101
+ style={{ display: "none" }}
102
+ value={gradient.end}
103
+ onChange={(e) =>
104
+ setGradient((g) => ({ ...g, end: e.target.value }))
105
+ }
106
+ />
107
+ <TextInput
108
+ source="colors.page_background.angle_deg"
109
+ label="Angle (deg)"
110
+ type="number"
111
+ value={gradient.angle_deg}
112
+ onChange={(e) =>
113
+ setGradient((g) => ({ ...g, angle_deg: Number(e.target.value) }))
114
+ }
115
+ />
116
+ </div>
117
+ )}
118
+ </div>
119
+ );
120
+ }
121
+
122
+ export function BrandingEdit() {
123
+ return (
124
+ <Edit>
125
+ <TabbedForm>
126
+ <TabbedForm.Tab label="Info">
127
+ <TextInput source="id" />
128
+ <TextInput source="name" />
129
+ <Labeled label={<FieldTitle source="created_at" />}>
130
+ <DateField source="created_at" showTime={true} />
131
+ </Labeled>
132
+ <Labeled label={<FieldTitle source="updated_at" />}>
133
+ <DateField source="updated_at" showTime={true} />
134
+ </Labeled>
135
+ </TabbedForm.Tab>
136
+ <TabbedForm.Tab label="Style">
137
+ <ColorInput source="colors.primary" label="Primary Color" />
138
+ <PageBackgroundInput source="colors.page_background" />
139
+ <TextInput source="favicon_url" label="Favicon URL" />
140
+ <TextInput source="logo_url" label="Logo URL" />
141
+ <TextInput source="font.url" label="Font URL" />
142
+ </TabbedForm.Tab>
143
+ <TabbedForm.Tab label="Themes">
144
+ <ThemesTab />
145
+ </TabbedForm.Tab>
146
+ </TabbedForm>
147
+ </Edit>
148
+ );
149
+ }
@@ -0,0 +1,123 @@
1
+ import { useState, useEffect } from "react";
2
+ import { useDataProvider, useNotify } from "react-admin";
3
+
4
+ export interface ThemeData {
5
+ displayName: string;
6
+ colors: {
7
+ primary_button?: string;
8
+ primary_button_label?: string;
9
+ secondary_button_border?: string;
10
+ secondary_button_label?: string;
11
+ base_focus_color?: string;
12
+ base_hover_color?: string;
13
+ body_text?: string;
14
+ captcha_widget_theme?: string;
15
+ error?: string;
16
+ header?: string;
17
+ icons?: string;
18
+ input_background?: string;
19
+ input_border?: string;
20
+ input_filled_text?: string;
21
+ input_labels_placeholders?: string;
22
+ links_focused_components?: string;
23
+ success?: string;
24
+ widget_background?: string;
25
+ widget_border?: string;
26
+ };
27
+ borders: {
28
+ button_border_radius?: number;
29
+ button_border_weight?: number;
30
+ buttons_style?: string;
31
+ input_border_radius?: number;
32
+ input_border_weight?: number;
33
+ inputs_style?: string;
34
+ show_widget_shadow?: boolean;
35
+ widget_border_weight?: number;
36
+ widget_corner_radius?: number;
37
+ };
38
+ fonts: {
39
+ font_url?: string;
40
+ reference_text_size?: number;
41
+ body_text?: { bold?: boolean; size?: number };
42
+ buttons_text?: { bold?: boolean; size?: number };
43
+ input_labels?: { bold?: boolean; size?: number };
44
+ links?: { bold?: boolean; size?: number };
45
+ links_style?: string;
46
+ subtitle?: { bold?: boolean; size?: number };
47
+ title?: { bold?: boolean; size?: number };
48
+ };
49
+ page_background: {
50
+ background_color?: string;
51
+ background_image_url?: string;
52
+ page_layout?: string;
53
+ };
54
+ widget: {
55
+ header_text_alignment?: string;
56
+ logo_height?: number;
57
+ logo_position?: string;
58
+ logo_url?: string;
59
+ social_buttons_layout?: string;
60
+ };
61
+ }
62
+
63
+ export function useThemesData() {
64
+ const [themeData, setThemeData] = useState<ThemeData | null>(null);
65
+ const [loading, setLoading] = useState(true);
66
+ const [error, setError] = useState<string | null>(null);
67
+ const dataProvider = useDataProvider();
68
+ const notify = useNotify();
69
+
70
+ const fetchThemes = async () => {
71
+ try {
72
+ setLoading(true);
73
+ const response = await dataProvider.getOne("branding/themes/default", {
74
+ id: "default",
75
+ });
76
+ setThemeData(response.data);
77
+ setError(null);
78
+ } catch (err) {
79
+ console.error("Failed to fetch themes:", err);
80
+ setError("Failed to fetch themes");
81
+ // Initialize with empty structure if fetch fails
82
+ setThemeData({
83
+ displayName: "",
84
+ colors: {},
85
+ borders: {},
86
+ fonts: {},
87
+ page_background: {},
88
+ widget: {},
89
+ });
90
+ } finally {
91
+ setLoading(false);
92
+ }
93
+ };
94
+
95
+ const updateThemes = async (data: Partial<ThemeData>) => {
96
+ try {
97
+ const response = await dataProvider.update("branding/themes/default", {
98
+ id: "default",
99
+ data,
100
+ previousData: themeData,
101
+ });
102
+ setThemeData(response.data);
103
+ notify("Theme updated successfully", { type: "success" });
104
+ return response.data;
105
+ } catch (err) {
106
+ console.error("Failed to update themes:", err);
107
+ notify("Failed to update theme", { type: "error" });
108
+ throw err;
109
+ }
110
+ };
111
+
112
+ useEffect(() => {
113
+ fetchThemes();
114
+ }, []);
115
+
116
+ return {
117
+ themeData,
118
+ loading,
119
+ error,
120
+ updateThemes,
121
+ refetch: fetchThemes,
122
+ };
123
+ }
@@ -0,0 +1,2 @@
1
+ export * from "./edit";
2
+ export * from "./list";
@@ -0,0 +1,12 @@
1
+ import { useEffect } from "react";
2
+ import { useRedirect, useBasename } from "react-admin";
3
+
4
+ export function BrandingList() {
5
+ const redirect = useRedirect();
6
+ const basename = useBasename();
7
+ useEffect(() => {
8
+ // For singleton resources, redirect to edit with "branding" as the ID
9
+ redirect(`${basename}/branding/branding`);
10
+ }, [redirect, basename]);
11
+ return null;
12
+ }
@@ -0,0 +1,12 @@
1
+ import { Create, SimpleForm, TextInput, required } from "react-admin";
2
+
3
+ export function ClientCreate() {
4
+ return (
5
+ <Create>
6
+ <SimpleForm>
7
+ <TextInput source="name" validate={[required()]} />
8
+ <TextInput source="client_id" validate={[required()]} />
9
+ </SimpleForm>
10
+ </Create>
11
+ );
12
+ }