@atproto/oauth-provider-ui 0.1.0 → 0.1.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.
Files changed (194) hide show
  1. package/dist/authorization-page-Cms-rcBA.js +3 -0
  2. package/dist/authorization-page-Cms-rcBA.js.map +1 -0
  3. package/dist/bundle-manifest.json +630 -0
  4. package/dist/error-page-DC6Vc-cv.js +2 -0
  5. package/dist/error-page-DC6Vc-cv.js.map +1 -0
  6. package/dist/error-view-CRGNTAn2.css +1 -0
  7. package/dist/error-view-MVy7C9l0.js +59 -0
  8. package/dist/error-view-MVy7C9l0.js.map +1 -0
  9. package/dist/index-CHPoD7Rp.js +20 -0
  10. package/dist/index-CHPoD7Rp.js.map +1 -0
  11. package/dist/messages-B0mgsxS-.js +2 -0
  12. package/dist/messages-B0mgsxS-.js.map +1 -0
  13. package/dist/messages-B5g8Fkio.js +2 -0
  14. package/dist/messages-B5g8Fkio.js.map +1 -0
  15. package/dist/messages-BCMss-Kt.js +2 -0
  16. package/dist/messages-BCMss-Kt.js.map +1 -0
  17. package/dist/messages-BGUrKgyK.js +2 -0
  18. package/dist/messages-BGUrKgyK.js.map +1 -0
  19. package/dist/messages-BjxAnLDp.js +2 -0
  20. package/dist/messages-BjxAnLDp.js.map +1 -0
  21. package/dist/messages-Bjysz3rI.js +2 -0
  22. package/dist/messages-Bjysz3rI.js.map +1 -0
  23. package/dist/messages-BvvEr3UX.js +2 -0
  24. package/dist/messages-BvvEr3UX.js.map +1 -0
  25. package/dist/messages-Bz6JOhJf.js +2 -0
  26. package/dist/messages-Bz6JOhJf.js.map +1 -0
  27. package/dist/messages-BzL3D1EU.js +2 -0
  28. package/dist/messages-BzL3D1EU.js.map +1 -0
  29. package/dist/messages-CAvN5UoW.js +2 -0
  30. package/dist/messages-CAvN5UoW.js.map +1 -0
  31. package/dist/messages-CEmswT1Q.js +2 -0
  32. package/dist/messages-CEmswT1Q.js.map +1 -0
  33. package/dist/messages-CHYqz0q6.js +2 -0
  34. package/dist/messages-CHYqz0q6.js.map +1 -0
  35. package/dist/messages-CRmpdijj.js +2 -0
  36. package/dist/messages-CRmpdijj.js.map +1 -0
  37. package/dist/messages-Cdb79R6S.js +2 -0
  38. package/dist/messages-Cdb79R6S.js.map +1 -0
  39. package/dist/messages-ChkJ_0WT.js +2 -0
  40. package/dist/messages-ChkJ_0WT.js.map +1 -0
  41. package/dist/messages-CqiEX6JJ.js +2 -0
  42. package/dist/messages-CqiEX6JJ.js.map +1 -0
  43. package/dist/messages-CxkHjJSR.js +2 -0
  44. package/dist/messages-CxkHjJSR.js.map +1 -0
  45. package/dist/messages-D0-cWoJ9.js +2 -0
  46. package/dist/messages-D0-cWoJ9.js.map +1 -0
  47. package/dist/messages-D2MnAxYY.js +2 -0
  48. package/dist/messages-D2MnAxYY.js.map +1 -0
  49. package/dist/messages-D5TZVsui.js +2 -0
  50. package/dist/messages-D5TZVsui.js.map +1 -0
  51. package/dist/messages-DBdV4-iw.js +2 -0
  52. package/dist/messages-DBdV4-iw.js.map +1 -0
  53. package/dist/messages-DEK3zybC.js +2 -0
  54. package/dist/messages-DEK3zybC.js.map +1 -0
  55. package/dist/messages-DGSM5jkd.js +2 -0
  56. package/dist/messages-DGSM5jkd.js.map +1 -0
  57. package/dist/messages-DJgAnSTQ.js +2 -0
  58. package/dist/messages-DJgAnSTQ.js.map +1 -0
  59. package/dist/messages-DK7O7sb_.js +2 -0
  60. package/dist/messages-DK7O7sb_.js.map +1 -0
  61. package/dist/messages-DRp7qc3j.js +2 -0
  62. package/dist/messages-DRp7qc3j.js.map +1 -0
  63. package/dist/messages-DT6xRw0m.js +2 -0
  64. package/dist/messages-DT6xRw0m.js.map +1 -0
  65. package/dist/messages-LnzLtU0L.js +2 -0
  66. package/dist/messages-LnzLtU0L.js.map +1 -0
  67. package/dist/messages-_Nk2qNGw.js +2 -0
  68. package/dist/messages-_Nk2qNGw.js.map +1 -0
  69. package/dist/messages-eHH6nZyF.js +2 -0
  70. package/dist/messages-eHH6nZyF.js.map +1 -0
  71. package/dist/messages-iNw8zY2C.js +2 -0
  72. package/dist/messages-iNw8zY2C.js.map +1 -0
  73. package/dist/messages-ipc0L8yF.js +2 -0
  74. package/dist/messages-ipc0L8yF.js.map +1 -0
  75. package/dist/messages-j7LsWm2F.js +2 -0
  76. package/dist/messages-j7LsWm2F.js.map +1 -0
  77. package/dist/messages-mgE_5UEw.js +2 -0
  78. package/dist/messages-mgE_5UEw.js.map +1 -0
  79. package/dist/messages-oRd-J5--.js +2 -0
  80. package/dist/messages-oRd-J5--.js.map +1 -0
  81. package/package.json +10 -8
  82. package/.linguirc +0 -57
  83. package/CHANGELOG.md +0 -17
  84. package/CONTRIBUTING.md +0 -6
  85. package/authorization-page.html +0 -186
  86. package/error-page.html +0 -118
  87. package/index.html +0 -13
  88. package/src/authorization-page.tsx +0 -49
  89. package/src/components/forms/button-toggle-visibility.tsx +0 -43
  90. package/src/components/forms/button.tsx +0 -60
  91. package/src/components/forms/fieldset.tsx +0 -55
  92. package/src/components/forms/form-card-async.tsx +0 -103
  93. package/src/components/forms/form-card.tsx +0 -49
  94. package/src/components/forms/input-checkbox.tsx +0 -78
  95. package/src/components/forms/input-container.tsx +0 -107
  96. package/src/components/forms/input-email-address.tsx +0 -65
  97. package/src/components/forms/input-new-password.tsx +0 -62
  98. package/src/components/forms/input-password.tsx +0 -87
  99. package/src/components/forms/input-text.tsx +0 -82
  100. package/src/components/forms/input-token.tsx +0 -94
  101. package/src/components/forms/wizard-card.tsx +0 -116
  102. package/src/components/layouts/layout-title-page.tsx +0 -78
  103. package/src/components/layouts/layout-welcome.tsx +0 -78
  104. package/src/components/utils/account-identifier.tsx +0 -23
  105. package/src/components/utils/account-image.tsx +0 -33
  106. package/src/components/utils/admonition.tsx +0 -52
  107. package/src/components/utils/client-name.tsx +0 -71
  108. package/src/components/utils/error-card.tsx +0 -93
  109. package/src/components/utils/error-message.tsx +0 -88
  110. package/src/components/utils/help-card.tsx +0 -46
  111. package/src/components/utils/icons.tsx +0 -88
  112. package/src/components/utils/link-anchor.tsx +0 -28
  113. package/src/components/utils/link-title.tsx +0 -26
  114. package/src/components/utils/multi-lang-string.tsx +0 -62
  115. package/src/components/utils/password-strength-label.tsx +0 -37
  116. package/src/components/utils/password-strength-meter.tsx +0 -58
  117. package/src/components/utils/url-viewer.tsx +0 -73
  118. package/src/error-page.tsx +0 -23
  119. package/src/hooks/use-api.ts +0 -202
  120. package/src/hooks/use-async-action.ts +0 -120
  121. package/src/hooks/use-bound-dispatch.ts +0 -5
  122. package/src/hooks/use-browser-color-scheme.ts +0 -31
  123. package/src/hooks/use-random-string.ts +0 -37
  124. package/src/hooks/use-stepper.ts +0 -87
  125. package/src/lib/api.ts +0 -225
  126. package/src/lib/cookies.ts +0 -17
  127. package/src/lib/json-client.ts +0 -141
  128. package/src/lib/password.ts +0 -98
  129. package/src/lib/ref.ts +0 -17
  130. package/src/lib/util.ts +0 -14
  131. package/src/locales/an/messages.po +0 -494
  132. package/src/locales/ast/messages.po +0 -494
  133. package/src/locales/ca/messages.po +0 -494
  134. package/src/locales/da/messages.po +0 -494
  135. package/src/locales/de/messages.po +0 -494
  136. package/src/locales/el/messages.po +0 -494
  137. package/src/locales/en/messages.po +0 -494
  138. package/src/locales/en-GB/messages.po +0 -494
  139. package/src/locales/es/messages.po +0 -494
  140. package/src/locales/eu/messages.po +0 -494
  141. package/src/locales/fi/messages.po +0 -494
  142. package/src/locales/fr/messages.po +0 -494
  143. package/src/locales/ga/messages.po +0 -494
  144. package/src/locales/gl/messages.po +0 -494
  145. package/src/locales/hi/messages.po +0 -494
  146. package/src/locales/hu/messages.po +0 -494
  147. package/src/locales/ia/messages.po +0 -494
  148. package/src/locales/id/messages.po +0 -494
  149. package/src/locales/it/messages.po +0 -494
  150. package/src/locales/ja/messages.po +0 -494
  151. package/src/locales/km/messages.po +0 -494
  152. package/src/locales/ko/messages.po +0 -494
  153. package/src/locales/load.ts +0 -8
  154. package/src/locales/locale-provider.tsx +0 -108
  155. package/src/locales/locale-selector.tsx +0 -57
  156. package/src/locales/locales.ts +0 -183
  157. package/src/locales/ne/messages.po +0 -494
  158. package/src/locales/nl/messages.po +0 -494
  159. package/src/locales/pl/messages.po +0 -494
  160. package/src/locales/pt-BR/messages.po +0 -494
  161. package/src/locales/ro/messages.po +0 -494
  162. package/src/locales/ru/messages.po +0 -494
  163. package/src/locales/sv/messages.po +0 -494
  164. package/src/locales/th/messages.po +0 -494
  165. package/src/locales/tr/messages.po +0 -494
  166. package/src/locales/uk/messages.po +0 -494
  167. package/src/locales/vi/messages.po +0 -494
  168. package/src/locales/zh-CN/messages.po +0 -494
  169. package/src/locales/zh-HK/messages.po +0 -494
  170. package/src/locales/zh-TW/messages.po +0 -494
  171. package/src/style.css +0 -219
  172. package/src/views/authorize/accept/accept-form.tsx +0 -155
  173. package/src/views/authorize/accept/accept-view.tsx +0 -70
  174. package/src/views/authorize/authorize-view.tsx +0 -186
  175. package/src/views/authorize/reset-password/reset-password-confirm-form.tsx +0 -88
  176. package/src/views/authorize/reset-password/reset-password-request-form.tsx +0 -80
  177. package/src/views/authorize/reset-password/reset-password-view.tsx +0 -127
  178. package/src/views/authorize/sign-in/sign-in-form.tsx +0 -240
  179. package/src/views/authorize/sign-in/sign-in-picker.tsx +0 -116
  180. package/src/views/authorize/sign-in/sign-in-view.tsx +0 -145
  181. package/src/views/authorize/sign-up/sign-up-account-form.tsx +0 -142
  182. package/src/views/authorize/sign-up/sign-up-disclaimer.tsx +0 -51
  183. package/src/views/authorize/sign-up/sign-up-handle-form.tsx +0 -287
  184. package/src/views/authorize/sign-up/sign-up-hcaptcha-form.tsx +0 -108
  185. package/src/views/authorize/sign-up/sign-up-view.tsx +0 -158
  186. package/src/views/authorize/welcome/welcome-view.tsx +0 -56
  187. package/src/views/error/error-view.tsx +0 -31
  188. package/tsconfig.json +0 -7
  189. package/tsconfig.src.json +0 -13
  190. package/tsconfig.src.tsbuildinfo +0 -1
  191. package/tsconfig.tools.json +0 -8
  192. package/tsconfig.tools.tsbuildinfo +0 -1
  193. package/vite.config.mjs +0 -47
  194. /package/{src/hydration-data.d.ts → hydration-data.d.ts} +0 -0
@@ -1,186 +0,0 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="UTF-8" />
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
- <title>Mock - OAuth Provider</title>
7
- </head>
8
- <body>
9
- <div id="root"></div>
10
- <script>
11
- /*
12
- * This file's purpose is to provide a way to develop the UI without
13
- * running a full featured OAuth server. It mocks the server responses and
14
- * provides configuration data to the UI.
15
- *
16
- * This file is not part of the production build.
17
- *
18
- * Start the development server with the following command from the
19
- * oauth-provider root:
20
- *
21
- * ```sh
22
- * pnpm run start:ui
23
- * ```
24
- *
25
- * Then open the browser at http://localhost:5173/
26
- */
27
- </script>
28
- <style>
29
- :root {
30
- --branding-color-primary: 10 122 255;
31
- --branding-color-primary-contrast: 255 255 255;
32
- --branding-color-primary-hue: 212.57142857142856;
33
-
34
- --branding-color-error: 244 11 66;
35
- --branding-color-error-contrast: 255 255 255;
36
- --branding-color-error-hue: 345.83690987124464;
37
-
38
- --branding-color-warning: 251 86 7;
39
- --branding-color-warning-contrast: 255 255 255;
40
- --branding-color-warning-hue: 19.426229508196723;
41
-
42
- --branding-color-success: 2 195 154;
43
- --branding-color-success-contrast: 0 0 0;
44
- --branding-color-success-hue: 167.2538860103627;
45
- }
46
- </style>
47
- <script type="module">
48
- import { API_ENDPOINT_PREFIX } from '@atproto/oauth-provider-api'
49
-
50
- /*
51
- * PDS branding configuration
52
- */
53
-
54
- const name = 'Bluesky'
55
- const links = [
56
- {
57
- title: { en: 'Home' },
58
- href: 'https://bsky.social/',
59
- rel: 'canonical', // prevents the login page from being indexed by search engines
60
- },
61
- {
62
- title: { en: 'Terms of Service' },
63
- href: 'https://bsky.social/about/support/tos',
64
- rel: 'terms-of-service',
65
- },
66
- {
67
- title: { en: 'Privacy Policy' },
68
- href: 'https://bsky.social/about/support/privacy-policy',
69
- rel: 'privacy-policy',
70
- },
71
- {
72
- title: { en: 'Support' },
73
- href: 'https://blueskyweb.zendesk.com/hc/en-us',
74
- rel: 'help',
75
- },
76
- ]
77
- const logo = `data:image/svg+xml,${encodeURIComponent('<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 320 286"><path fill="rgb(10,122,255)" d="M69.364 19.146c36.687 27.806 76.147 84.186 90.636 114.439 14.489-30.253 53.948-86.633 90.636-114.439C277.107-.917 320-16.44 320 32.957c0 9.865-5.603 82.875-8.889 94.729-11.423 41.208-53.045 51.719-90.071 45.357 64.719 11.12 81.182 47.953 45.627 84.785-80 82.874-106.667-44.333-106.667-44.333s-26.667 127.207-106.667 44.333c-35.555-36.832-19.092-73.665 45.627-84.785-37.026 6.362-78.648-4.149-90.071-45.357C5.603 115.832 0 42.822 0 32.957 0-16.44 42.893-.917 69.364 19.147Z" /></svg>')}`
78
-
79
- // Provide a value here to test the "sing-in only" flow
80
- const loginHint = undefined // 'alice.test'
81
-
82
- // Use empty array to disable the "sing-up" flow, use a single value to
83
- // disable the domain selector.
84
- const availableUserDomains = ['.bsky.social', '.bsky.team']
85
-
86
- // Use non empty string to enable hCaptcha during "sing-up" flow
87
- const hcaptchaSiteKey = undefined
88
-
89
- /*
90
- * Client branding configuration
91
- */
92
-
93
- // Use an "http://" URL to test the "an app on your device" flow
94
- const clientId = 'https://example.com/client.json'
95
- const clientName = 'My App'
96
- const clientPolicyUri = 'https://bsky.app'
97
- const clientTosUri = 'https://bsky.app'
98
- const clientLogoUri = 'https://bsky.app'
99
-
100
- // Mock data
101
-
102
- const requestUri = 'foo-bar'
103
-
104
- document.cookie = `csrf-${requestUri}=xyz; path=/`
105
-
106
- window.__customizationData = {
107
- availableUserDomains,
108
- inviteCodeRequired: false,
109
- hcaptchaSiteKey,
110
- name,
111
- links,
112
- logo,
113
- }
114
-
115
- window.__authorizeData = {
116
- clientId: clientId,
117
- clientMetadata: {
118
- client_id: clientId,
119
- client_name: clientName,
120
- policy_uri: clientPolicyUri,
121
- tos_uri: clientTosUri,
122
- logo_uri: clientLogoUri,
123
- },
124
- clientTrusted: false,
125
- requestUri,
126
- loginHint,
127
- sessions: [],
128
- scopeDetails: [
129
- { scope: 'atproto' },
130
- { scope: 'transition:generic' },
131
- { scope: 'transition:chat.bsky' },
132
- ],
133
- }
134
-
135
- const origFetch = window.fetch
136
-
137
- async function mockFetch(...args) {
138
- const [input, init] = args
139
-
140
- const method = init?.method ?? 'GET'
141
- const url =
142
- typeof input === 'string'
143
- ? new URL(input, window.location)
144
- : input instanceof URL
145
- ? input
146
- : undefined
147
- if (url) {
148
- switch (`${method} ${url.pathname}`) {
149
- case `POST ${API_ENDPOINT_PREFIX}/sign-up`:
150
- case `POST ${API_ENDPOINT_PREFIX}/sign-in`:
151
- return new Response(
152
- JSON.stringify({
153
- consentRequired: false,
154
- account: {
155
- sub: 'did:plc:123',
156
- name: 'Alice',
157
- email: 'alice@test.com',
158
- email_verified: false,
159
- preferred_username: 'alice.test',
160
- picture: 'https://cat.com/cat.jpg',
161
- },
162
- }),
163
- {
164
- status: 200,
165
- headers: { 'Content-Type': 'application/json' },
166
- },
167
- )
168
- case `POST ${API_ENDPOINT_PREFIX}/verify-handle-availability`:
169
- case `POST ${API_ENDPOINT_PREFIX}/reset-password-request`:
170
- case `POST ${API_ENDPOINT_PREFIX}/reset-password-confirm`:
171
- return new Response(null, { status: 204 })
172
- }
173
- }
174
-
175
- return origFetch.call(this, ...args)
176
- }
177
-
178
- Object.defineProperty(window, 'fetch', {
179
- value: mockFetch,
180
- writable: true,
181
- configurable: true,
182
- })
183
- </script>
184
- <script src="./src/authorization-page.tsx" type="module"></script>
185
- </body>
186
- </html>
package/error-page.html DELETED
@@ -1,118 +0,0 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="UTF-8" />
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
- <title>Mock - OAuth Provider</title>
7
- </head>
8
- <body>
9
- <div id="root"></div>
10
- <script>
11
- /*
12
- * This file's purpose is to provide a way to develop the UI without
13
- * running a full featured OAuth server. It mocks the server responses and
14
- * provides configuration data to the UI.
15
- *
16
- * This file is not part of the production build.
17
- *
18
- * Start the development server with the following command from the
19
- * oauth-provider root:
20
- *
21
- * ```sh
22
- * pnpm run start:ui
23
- * ```
24
- *
25
- * Then open the browser at http://localhost:5173/
26
- */
27
- </script>
28
- <style>
29
- :root {
30
- --branding-color-primary: 10 122 255;
31
- --branding-color-primary-contrast: 255 255 255;
32
- --branding-color-primary-hue: 212.57142857142856;
33
-
34
- --branding-color-error: 244 11 66;
35
- --branding-color-error-contrast: 255 255 255;
36
- --branding-color-error-hue: 345.83690987124464;
37
-
38
- --branding-color-warning: 251 86 7;
39
- --branding-color-warning-contrast: 255 255 255;
40
- --branding-color-warning-hue: 19.426229508196723;
41
-
42
- --branding-color-success: 2 195 154;
43
- --branding-color-success-contrast: 0 0 0;
44
- --branding-color-success-hue: 167.2538860103627;
45
- }
46
- </style>
47
- <script type="module">
48
- /*
49
- * PDS branding configuration
50
- */
51
-
52
- const name = 'Bluesky'
53
- const links = [
54
- {
55
- title: { en: 'Home', fr: 'Accueil' },
56
- href: 'https://bsky.social/',
57
- rel: 'canonical', // prevents the login page from being indexed by search engines
58
- },
59
- {
60
- title: { en: 'Terms of Service' },
61
- href: 'https://bsky.social/about/support/tos',
62
- rel: 'terms-of-service',
63
- },
64
- {
65
- title: { en: 'Privacy Policy' },
66
- href: 'https://bsky.social/about/support/privacy-policy',
67
- rel: 'privacy-policy',
68
- },
69
- {
70
- title: { en: 'Support' },
71
- href: 'https://blueskyweb.zendesk.com/hc/en-us',
72
- rel: 'help',
73
- },
74
- ]
75
- const logo = `data:image/svg+xml,${encodeURIComponent('<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 320 286"><path fill="rgb(10,122,255)" d="M69.364 19.146c36.687 27.806 76.147 84.186 90.636 114.439 14.489-30.253 53.948-86.633 90.636-114.439C277.107-.917 320-16.44 320 32.957c0 9.865-5.603 82.875-8.889 94.729-11.423 41.208-53.045 51.719-90.071 45.357 64.719 11.12 81.182 47.953 45.627 84.785-80 82.874-106.667-44.333-106.667-44.333s-26.667 127.207-106.667 44.333c-35.555-36.832-19.092-73.665 45.627-84.785-37.026 6.362-78.648-4.149-90.071-45.357C5.603 115.832 0 42.822 0 32.957 0-16.44 42.893-.917 69.364 19.147Z" /></svg>')}`
76
-
77
- // Provide a value here to test the "sing-in only" flow
78
- const loginHint = undefined // 'alice.test'
79
-
80
- // Use empty array to disable the "sing-up" flow, use a single value to
81
- // disable the domain selector.
82
- const availableUserDomains = ['.bsky.social', '.bsky.team']
83
-
84
- // Use non empty string to enable hCaptcha during "sing-up" flow
85
- const hcaptchaSiteKey = undefined
86
-
87
- /*
88
- * Client branding configuration
89
- */
90
-
91
- // Use an "http://" URL to test the "an app on your device" flow
92
- const clientId = 'https://example.com/client.json'
93
- const clientName = 'My App'
94
- const clientPolicyUri = 'https://bsky.app'
95
- const clientTosUri = 'https://bsky.app'
96
- const clientLogoUri = 'https://bsky.app'
97
-
98
- // Mock data
99
-
100
- const requestUri = 'foo-bar'
101
-
102
- window.__customizationData = {
103
- availableUserDomains,
104
- inviteCodeRequired: false,
105
- hcaptchaSiteKey,
106
- name,
107
- links,
108
- logo,
109
- }
110
-
111
- window.__errorData = {
112
- error: 'foo',
113
- error_description: 'bar',
114
- }
115
- </script>
116
- <script src="./src/error-page.tsx" type="module"></script>
117
- </body>
118
- </html>
package/index.html DELETED
@@ -1,13 +0,0 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="UTF-8" />
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
- <title>OAuth mock pages</title>
7
- </head>
8
- <body>
9
- <a href="authorization-page.html">authorization-page</a>
10
- <br />
11
- <a href="error-page.html">error-page</a>
12
- </body>
13
- </html>
@@ -1,49 +0,0 @@
1
- import './style.css'
2
-
3
- import { StrictMode } from 'react'
4
- import { createRoot } from 'react-dom/client'
5
- import { ErrorBoundary } from 'react-error-boundary'
6
- import type { HydrationData } from './hydration-data.d.ts'
7
- import { LocaleProvider } from './locales/locale-provider.tsx'
8
- import { AuthorizeView } from './views/authorize/authorize-view.tsx'
9
- import { ErrorView } from './views/error/error-view.tsx'
10
-
11
- const {
12
- __authorizeData: authorizeData,
13
- __sessions: sessions,
14
- __customizationData: customizationData,
15
- } = window as typeof window & HydrationData['authorization-page']
16
-
17
- // When the user is logging in, make sure the page URL contains the
18
- // "request_uri" in case the user refreshes the page.
19
- // @TODO Actually do this on the backend through a redirect.
20
- const url = new URL(window.location.href)
21
- if (
22
- url.pathname === '/oauth/authorize' &&
23
- !url.searchParams.has('request_uri')
24
- ) {
25
- url.search = ''
26
- url.searchParams.set('client_id', authorizeData.clientId)
27
- url.searchParams.set('request_uri', authorizeData.requestUri)
28
- window.history.replaceState(history.state, '', url.pathname + url.search)
29
- }
30
-
31
- const container = document.getElementById('root')!
32
-
33
- createRoot(container).render(
34
- <StrictMode>
35
- <LocaleProvider userLocales={authorizeData.uiLocales?.split(' ')}>
36
- <ErrorBoundary
37
- fallbackRender={({ error }) => (
38
- <ErrorView error={error} customizationData={customizationData} />
39
- )}
40
- >
41
- <AuthorizeView
42
- customizationData={customizationData}
43
- authorizeData={authorizeData}
44
- sessions={sessions}
45
- />
46
- </ErrorBoundary>
47
- </LocaleProvider>
48
- </StrictMode>,
49
- )
@@ -1,43 +0,0 @@
1
- import { useLingui } from '@lingui/react/macro'
2
- import { Override } from '../../lib/util.ts'
3
- import { EyeIcon, EyeSlashIcon } from '../utils/icons.tsx'
4
- import { Button, ButtonProps } from './button.tsx'
5
-
6
- export type ButtonToggleVisibilityProps = Override<
7
- Omit<ButtonProps, 'aria-label' | 'square'>,
8
- {
9
- visible: boolean
10
- toggleVisible: () => void
11
- }
12
- >
13
-
14
- /**
15
- * Generic button to toggle visibility of an item (e.g. password).
16
- */
17
- export function ButtonToggleVisibility({
18
- visible,
19
- toggleVisible,
20
-
21
- // button
22
- onClick,
23
- ...props
24
- }: ButtonToggleVisibilityProps) {
25
- const { t } = useLingui()
26
- return (
27
- <Button
28
- {...props}
29
- square
30
- onClick={(event) => {
31
- onClick?.(event)
32
- if (!event.defaultPrevented) toggleVisible()
33
- }}
34
- aria-label={visible ? t`Hide` : t`Make visible`}
35
- >
36
- {visible ? (
37
- <EyeIcon className="w-5" aria-hidden />
38
- ) : (
39
- <EyeSlashIcon className="w-5" aria-hidden />
40
- )}
41
- </Button>
42
- )
43
- }
@@ -1,60 +0,0 @@
1
- import { clsx } from 'clsx'
2
- import { JSX } from 'react'
3
- import { Override } from '../../lib/util.ts'
4
-
5
- export type ButtonProps = Override<
6
- JSX.IntrinsicElements['button'],
7
- {
8
- color?: 'primary' | 'grey'
9
- loading?: boolean
10
- transparent?: boolean
11
- square?: boolean
12
- }
13
- >
14
-
15
- export function Button({
16
- color = 'grey',
17
- transparent = false,
18
- loading = undefined,
19
- square = false,
20
-
21
- // button
22
- children,
23
- className,
24
- type = 'button',
25
- role = 'Button',
26
- disabled = false,
27
- ...props
28
- }: ButtonProps) {
29
- return (
30
- <button
31
- role={role}
32
- type={type}
33
- disabled={disabled || loading === true}
34
- {...props}
35
- className={clsx(
36
- 'cursor-pointer touch-manipulation overflow-hidden truncate rounded-md tracking-wide',
37
- square ? 'p-2' : 'px-6 py-2',
38
- color === 'primary'
39
- ? clsx(
40
- 'accent-slate-100',
41
- transparent
42
- ? 'text-primary bg-transparent'
43
- : 'bg-primary text-primary-contrast',
44
- )
45
- : color === 'grey'
46
- ? clsx(
47
- 'accent-primary',
48
- 'text-slate-600 dark:text-slate-300',
49
- 'hover:bg-gray-200 dark:hover:bg-gray-700',
50
- transparent ? 'bg-transparent' : 'bg-gray-100 dark:bg-gray-800',
51
- )
52
- : undefined,
53
- 'disabled:opacity-50',
54
- className,
55
- )}
56
- >
57
- {children}
58
- </button>
59
- )
60
- }
@@ -1,55 +0,0 @@
1
- import { JSX, ReactNode, createContext, useMemo } from 'react'
2
- import { useRandomString } from '../../hooks/use-random-string.ts'
3
- import { Override } from '../../lib/util.ts'
4
-
5
- export type FieldsetContextValue = {
6
- disabled: boolean
7
- labelId?: string
8
- }
9
-
10
- export const FieldsetContext = createContext<FieldsetContextValue>({
11
- disabled: false,
12
- })
13
- FieldsetContext.displayName = 'FieldsetContext'
14
-
15
- export type FieldsetCardProps = Override<
16
- Omit<JSX.IntrinsicElements['fieldset'], 'aria-labelledby'>,
17
- {
18
- label?: ReactNode
19
- }
20
- >
21
-
22
- export function Fieldset({
23
- label,
24
- children,
25
- disabled,
26
- ...props
27
- }: FieldsetCardProps) {
28
- const labelId = useRandomString({ prefix: 'fieldset-' })
29
-
30
- const contextValue = useMemo(
31
- () => ({
32
- disabled: disabled ?? false,
33
- labelId: label ? labelId : undefined,
34
- }),
35
- [disabled, label, labelId],
36
- )
37
-
38
- return (
39
- <fieldset {...props} aria-labelledby={labelId} disabled={disabled}>
40
- {label && (
41
- <legend
42
- id={labelId}
43
- key="title"
44
- className="mb-1 text-sm font-medium text-slate-600 dark:text-slate-400"
45
- >
46
- {label}
47
- </legend>
48
- )}
49
-
50
- <div className="flex flex-col space-y-4">
51
- <FieldsetContext value={contextValue}>{children}</FieldsetContext>
52
- </div>
53
- </fieldset>
54
- )
55
- }
@@ -1,103 +0,0 @@
1
- import { Trans } from '@lingui/react/macro'
2
- import { FormEvent, ReactNode, useCallback } from 'react'
3
- import {
4
- UseAsyncActionOptions,
5
- useAsyncAction,
6
- } from '../../hooks/use-async-action.ts'
7
- import { Override } from '../../lib/util.ts'
8
- import { ErrorCard } from '../utils/error-card.tsx'
9
- import { Button } from './button.tsx'
10
- import { FormCard, FormCardProps } from './form-card.tsx'
11
-
12
- export type { AsyncActionController } from '../../hooks/use-async-action.ts'
13
-
14
- export type ErrorRender = (data: { error: Error }) => ReactNode
15
- export const errorRenderDefault: ErrorRender = ({ error }) => (
16
- <ErrorCard error={error} />
17
- )
18
-
19
- export type FormCardAsyncProps = Override<
20
- Override<
21
- Omit<FormCardProps, 'cancel' | 'actions' | 'prepend'>,
22
- Pick<UseAsyncActionOptions, 'ref' | 'onLoading' | 'onError'>
23
- >,
24
- {
25
- invalid?: boolean
26
- disabled?: boolean
27
-
28
- onSubmit: (signal: AbortSignal) => void | PromiseLike<void>
29
- submitLabel?: ReactNode
30
-
31
- onCancel?: () => void
32
- cancelLabel?: ReactNode
33
-
34
- errorRender?: ErrorRender
35
- }
36
- >
37
-
38
- export function FormCardAsync({
39
- invalid,
40
- disabled,
41
-
42
- onSubmit,
43
- submitLabel,
44
-
45
- onCancel = undefined,
46
- cancelLabel,
47
-
48
- errorRender = errorRenderDefault,
49
-
50
- // UseAsyncActionOptions
51
- ref,
52
- onLoading,
53
- onError,
54
-
55
- // FormCardProps
56
- children,
57
- ...props
58
- }: FormCardAsyncProps) {
59
- const { run, loading, error } = useAsyncAction(onSubmit, {
60
- ref,
61
- onError,
62
- onLoading,
63
- })
64
-
65
- const doSubmit = useCallback(
66
- (event: FormEvent<HTMLFormElement>) => {
67
- event.preventDefault()
68
-
69
- if (!event.currentTarget.reportValidity()) return
70
-
71
- if (!disabled && !invalid) void run()
72
- },
73
- [disabled, invalid, run],
74
- )
75
-
76
- return (
77
- <FormCard
78
- {...props}
79
- onSubmit={doSubmit}
80
- disabled={disabled || loading}
81
- prepend={error != null ? errorRender({ error }) : undefined}
82
- cancel={
83
- onCancel && (
84
- <Button onClick={onCancel}>
85
- {cancelLabel || <Trans>Cancel</Trans>}
86
- </Button>
87
- )
88
- }
89
- actions={
90
- <Button
91
- color="primary"
92
- type="submit"
93
- loading={loading}
94
- disabled={disabled}
95
- >
96
- {submitLabel || <Trans>Submit</Trans>}
97
- </Button>
98
- }
99
- >
100
- {children}
101
- </FormCard>
102
- )
103
- }
@@ -1,49 +0,0 @@
1
- import { JSX, ReactNode } from 'react'
2
- import { Override } from '../../lib/util.ts'
3
-
4
- export type FormCardProps = Override<
5
- JSX.IntrinsicElements['form'],
6
- {
7
- disabled?: boolean
8
- append?: ReactNode
9
- prepend?: ReactNode
10
- cancel?: ReactNode
11
- actions?: ReactNode
12
- }
13
- >
14
-
15
- export function FormCard({
16
- actions,
17
- cancel,
18
- append,
19
- children,
20
- prepend,
21
- disabled,
22
-
23
- // form
24
- inert = disabled,
25
- ...props
26
- }: FormCardProps) {
27
- return (
28
- <form {...props} inert={inert} className="flex flex-col space-y-4">
29
- {prepend && <div key="prepend">{prepend}</div>}
30
-
31
- <div key="children" className="space-y-4">
32
- {children}
33
- </div>
34
-
35
- {append && <div key="append">{append}</div>}
36
-
37
- {(actions || cancel) && (
38
- <div
39
- key="buttons"
40
- className="flex flex-row-reverse flex-wrap items-center justify-end space-x-2 space-x-reverse"
41
- >
42
- {actions}
43
- <div className="flex-auto" />
44
- {cancel}
45
- </div>
46
- )}
47
- </form>
48
- )
49
- }