@byline/ui 2.4.0 → 2.4.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 (95) hide show
  1. package/dist/react.d.ts +10 -18
  2. package/dist/react.js +2 -15
  3. package/dist/{admin/components/collections → widgets/diff-viewer}/diff-modal.d.ts +8 -1
  4. package/dist/{admin/components/collections → widgets/diff-viewer}/diff-modal.js +4 -6
  5. package/dist/widgets/diff-viewer/diff-modal.module.js +14 -0
  6. package/dist/{admin/components/collections → widgets/diff-viewer}/diff-modal_module.css +9 -9
  7. package/dist/{admin/components/collections → widgets/status-badge}/status-badge.js +1 -1
  8. package/dist/{admin/components/collections → widgets/status-badge}/status-badge.module.js +3 -3
  9. package/dist/{admin/components/collections → widgets/status-badge}/status-badge_module.css +3 -3
  10. package/package.json +2 -4
  11. package/src/react.ts +12 -34
  12. package/src/{admin/components/collections → widgets/diff-viewer}/diff-modal.tsx +16 -5
  13. package/src/{admin/components/collections → widgets/status-badge}/status-badge.tsx +1 -1
  14. package/dist/admin/components/admin-account/change-password.d.ts +0 -8
  15. package/dist/admin/components/admin-account/change-password.js +0 -192
  16. package/dist/admin/components/admin-account/change-password.module.js +0 -8
  17. package/dist/admin/components/admin-account/change-password_module.css +0 -27
  18. package/dist/admin/components/admin-account/container.d.ts +0 -29
  19. package/dist/admin/components/admin-account/container.js +0 -299
  20. package/dist/admin/components/admin-account/container.module.js +0 -28
  21. package/dist/admin/components/admin-account/container_module.css +0 -106
  22. package/dist/admin/components/admin-account/update.d.ts +0 -8
  23. package/dist/admin/components/admin-account/update.js +0 -207
  24. package/dist/admin/components/admin-account/update.module.js +0 -8
  25. package/dist/admin/components/admin-account/update_module.css +0 -27
  26. package/dist/admin/components/admin-permissions/inspector.d.ts +0 -4
  27. package/dist/admin/components/admin-permissions/inspector.js +0 -284
  28. package/dist/admin/components/admin-permissions/inspector.module.js +0 -56
  29. package/dist/admin/components/admin-permissions/inspector_module.css +0 -238
  30. package/dist/admin/components/admin-roles/create.d.ts +0 -7
  31. package/dist/admin/components/admin-roles/create.js +0 -177
  32. package/dist/admin/components/admin-roles/create.module.js +0 -8
  33. package/dist/admin/components/admin-roles/create_module.css +0 -27
  34. package/dist/admin/components/admin-roles/permissions.d.ts +0 -10
  35. package/dist/admin/components/admin-roles/permissions.js +0 -303
  36. package/dist/admin/components/admin-roles/permissions.module.js +0 -44
  37. package/dist/admin/components/admin-roles/permissions_module.css +0 -192
  38. package/dist/admin/components/admin-roles/update.d.ts +0 -8
  39. package/dist/admin/components/admin-roles/update.js +0 -166
  40. package/dist/admin/components/admin-roles/update.module.js +0 -8
  41. package/dist/admin/components/admin-roles/update_module.css +0 -27
  42. package/dist/admin/components/admin-users/create.d.ts +0 -8
  43. package/dist/admin/components/admin-users/create.js +0 -268
  44. package/dist/admin/components/admin-users/create.module.js +0 -10
  45. package/dist/admin/components/admin-users/create_module.css +0 -45
  46. package/dist/admin/components/admin-users/roles.d.ts +0 -11
  47. package/dist/admin/components/admin-users/roles.js +0 -148
  48. package/dist/admin/components/admin-users/roles.module.js +0 -18
  49. package/dist/admin/components/admin-users/roles_module.css +0 -75
  50. package/dist/admin/components/admin-users/set-password.d.ts +0 -8
  51. package/dist/admin/components/admin-users/set-password.js +0 -170
  52. package/dist/admin/components/admin-users/set-password.module.js +0 -9
  53. package/dist/admin/components/admin-users/set-password_module.css +0 -31
  54. package/dist/admin/components/admin-users/update.d.ts +0 -8
  55. package/dist/admin/components/admin-users/update.js +0 -254
  56. package/dist/admin/components/admin-users/update.module.js +0 -9
  57. package/dist/admin/components/admin-users/update_module.css +0 -34
  58. package/dist/admin/components/auth/sign-in-form.d.ts +0 -12
  59. package/dist/admin/components/auth/sign-in-form.js +0 -115
  60. package/dist/admin/components/auth/sign-in-form.module.js +0 -12
  61. package/dist/admin/components/auth/sign-in-form_module.css +0 -41
  62. package/dist/admin/components/collections/diff-modal.module.js +0 -14
  63. package/dist/services/admin-services-context.d.ts +0 -16
  64. package/dist/services/admin-services-context.js +0 -13
  65. package/dist/services/admin-services-types.d.ts +0 -129
  66. package/dist/services/admin-services-types.js +0 -1
  67. package/src/admin/components/admin-account/change-password.module.css +0 -40
  68. package/src/admin/components/admin-account/change-password.tsx +0 -232
  69. package/src/admin/components/admin-account/container.module.css +0 -158
  70. package/src/admin/components/admin-account/container.tsx +0 -230
  71. package/src/admin/components/admin-account/update.module.css +0 -40
  72. package/src/admin/components/admin-account/update.tsx +0 -263
  73. package/src/admin/components/admin-permissions/inspector.module.css +0 -326
  74. package/src/admin/components/admin-permissions/inspector.tsx +0 -298
  75. package/src/admin/components/admin-roles/create.module.css +0 -40
  76. package/src/admin/components/admin-roles/create.tsx +0 -218
  77. package/src/admin/components/admin-roles/permissions.module.css +0 -279
  78. package/src/admin/components/admin-roles/permissions.tsx +0 -396
  79. package/src/admin/components/admin-roles/update.module.css +0 -40
  80. package/src/admin/components/admin-roles/update.tsx +0 -218
  81. package/src/admin/components/admin-users/create.module.css +0 -63
  82. package/src/admin/components/admin-users/create.tsx +0 -323
  83. package/src/admin/components/admin-users/roles.module.css +0 -119
  84. package/src/admin/components/admin-users/roles.tsx +0 -172
  85. package/src/admin/components/admin-users/set-password.module.css +0 -46
  86. package/src/admin/components/admin-users/set-password.tsx +0 -199
  87. package/src/admin/components/admin-users/update.module.css +0 -49
  88. package/src/admin/components/admin-users/update.tsx +0 -328
  89. package/src/admin/components/auth/sign-in-form.module.css +0 -62
  90. package/src/admin/components/auth/sign-in-form.tsx +0 -132
  91. package/src/services/admin-services-context.tsx +0 -35
  92. package/src/services/admin-services-types.ts +0 -177
  93. /package/dist/{admin/components/collections → widgets/status-badge}/status-badge.d.ts +0 -0
  94. /package/src/{admin/components/collections → widgets/diff-viewer}/diff-modal.module.css +0 -0
  95. /package/src/{admin/components/collections → widgets/status-badge}/status-badge.module.css +0 -0
@@ -1,328 +0,0 @@
1
- 'use client'
2
-
3
- /**
4
- * This Source Code is subject to the terms of the Mozilla Public
5
- * License, v. 2.0. If a copy of the MPL was not distributed with this
6
- * file, You can obtain one at http://mozilla.org/MPL/2.0/.
7
- *
8
- * Copyright (c) Infonomic Company Limited
9
- */
10
-
11
- /**
12
- * Account details drawer form.
13
- *
14
- * Client-side validation runs through TanStack Form's `onDynamic` +
15
- * Zod — same rules the server uses, re-declared here so field errors
16
- * show up without a network round-trip. On submit the form diffs
17
- * against the original row and sends only the *changed* fields as a
18
- * patch, plus the `vid` the form was opened with, so a concurrent edit
19
- * elsewhere comes back as `admin.users.versionConflict` and we surface
20
- * a reload prompt.
21
- */
22
-
23
- import { useState } from 'react'
24
- import { revalidateLogic, useForm } from '@tanstack/react-form-start'
25
-
26
- import type { AdminUserResponse } from '@byline/admin/admin-users'
27
- import cx from 'classnames'
28
- import { z } from 'zod'
29
-
30
- import { useBylineAdminServices } from '../../../services/admin-services-context.js'
31
- import { Alert, Button, Checkbox, Input, LoaderEllipsis } from '../../../uikit.js'
32
- import styles from './update.module.css'
33
-
34
- const updateUserSchema = z.object({
35
- given_name: z.string().max(100, 'Given name must not exceed 100 characters'),
36
- family_name: z.string().max(100, 'Family name must not exceed 100 characters'),
37
- username: z.string().max(100, 'Username must not exceed 100 characters'),
38
- email: z
39
- .email({ message: 'Enter a valid email address' })
40
- .min(3)
41
- .max(254, 'Email must not exceed 254 characters'),
42
- is_super_admin: z.boolean(),
43
- is_enabled: z.boolean(),
44
- is_email_verified: z.boolean(),
45
- })
46
-
47
- type UpdateUserValues = z.infer<typeof updateUserSchema>
48
-
49
- function defaultsFrom(user: AdminUserResponse): UpdateUserValues {
50
- return {
51
- given_name: user.given_name ?? '',
52
- family_name: user.family_name ?? '',
53
- username: user.username ?? '',
54
- email: user.email,
55
- is_super_admin: user.is_super_admin,
56
- is_enabled: user.is_enabled,
57
- is_email_verified: user.is_email_verified,
58
- }
59
- }
60
-
61
- /** Build a patch object containing only fields whose values differ from the original user row. */
62
- function buildPatch(values: UpdateUserValues, user: AdminUserResponse) {
63
- const patch: {
64
- given_name?: string | null
65
- family_name?: string | null
66
- username?: string | null
67
- email?: string
68
- is_super_admin?: boolean
69
- is_enabled?: boolean
70
- is_email_verified?: boolean
71
- } = {}
72
- // Text fields: treat empty string as null (clear). null === null matches,
73
- // '' → null ≠ current null stays consistent.
74
- const normaliseText = (value: string): string | null => (value.trim().length > 0 ? value : null)
75
- const nextGiven = normaliseText(values.given_name)
76
- const nextFamily = normaliseText(values.family_name)
77
- const nextUsername = normaliseText(values.username)
78
-
79
- if (nextGiven !== user.given_name) patch.given_name = nextGiven
80
- if (nextFamily !== user.family_name) patch.family_name = nextFamily
81
- if (nextUsername !== user.username) patch.username = nextUsername
82
- if (values.email !== user.email) patch.email = values.email
83
- if (values.is_super_admin !== user.is_super_admin) patch.is_super_admin = values.is_super_admin
84
- if (values.is_enabled !== user.is_enabled) patch.is_enabled = values.is_enabled
85
- if (values.is_email_verified !== user.is_email_verified)
86
- patch.is_email_verified = values.is_email_verified
87
- return patch
88
- }
89
-
90
- interface UpdateUserProps {
91
- user: AdminUserResponse
92
- onClose?: () => void
93
- onSuccess?: (user: AdminUserResponse) => void
94
- }
95
-
96
- export function UpdateUser({ user, onClose, onSuccess }: UpdateUserProps) {
97
- const { updateAdminUser } = useBylineAdminServices()
98
- const [formError, setFormError] = useState<string | null>(null)
99
- const [successMessage, setSuccessMessage] = useState<string | null>(null)
100
-
101
- const form = useForm({
102
- defaultValues: defaultsFrom(user),
103
- validationLogic: revalidateLogic({
104
- mode: 'blur',
105
- modeAfterSubmission: 'change',
106
- }),
107
- validators: {
108
- onDynamic: updateUserSchema,
109
- },
110
- onSubmit: async ({ value }) => {
111
- setFormError(null)
112
- setSuccessMessage(null)
113
- const patch = buildPatch(value, user)
114
- if (Object.keys(patch).length === 0) {
115
- setSuccessMessage('No changes to save.')
116
- return
117
- }
118
-
119
- try {
120
- const updated = await updateAdminUser({
121
- data: { id: user.id, vid: user.vid, patch },
122
- })
123
- setSuccessMessage('Saved.')
124
- onSuccess?.(updated)
125
- } catch (err) {
126
- const code = getErrorCode(err)
127
- if (code === 'admin.users.emailInUse') {
128
- // Surface on the email field directly.
129
- form.setFieldMeta('email', (meta) => ({
130
- ...meta,
131
- errorMap: { ...meta.errorMap, onServer: 'This email is already in use.' },
132
- errors: ['This email is already in use.'],
133
- }))
134
- return
135
- }
136
- if (code === 'admin.users.versionConflict') {
137
- setFormError(
138
- 'This user has been modified elsewhere since you opened this form. Reload to get the latest values and try again.'
139
- )
140
- return
141
- }
142
- if (code === 'admin.users.notFound') {
143
- setFormError('This user no longer exists.')
144
- return
145
- }
146
- setFormError('Could not save changes. Please try again.')
147
- }
148
- },
149
- })
150
-
151
- return (
152
- <div className={cx('byline-user-update-wrap', styles.wrap)}>
153
- <form
154
- noValidate
155
- onSubmit={(event) => {
156
- event.preventDefault()
157
- event.stopPropagation()
158
- void form.handleSubmit()
159
- }}
160
- className={cx('byline-user-update-form', styles.form)}
161
- >
162
- {formError ? <Alert intent="danger">{formError}</Alert> : null}
163
- {successMessage ? <Alert intent="success">{successMessage}</Alert> : null}
164
-
165
- <form.Field name="given_name">
166
- {(field) => (
167
- <Input
168
- label="Given name"
169
- id="given_name"
170
- name={field.name}
171
- value={field.state.value}
172
- onBlur={field.handleBlur}
173
- onChange={(e) => field.handleChange(e.currentTarget.value)}
174
- error={field.state.meta.errors.length > 0}
175
- errorText={firstError(field.state.meta.errors)}
176
- autoComplete="given-name"
177
- />
178
- )}
179
- </form.Field>
180
-
181
- <form.Field name="family_name">
182
- {(field) => (
183
- <Input
184
- label="Family name"
185
- id="family_name"
186
- name={field.name}
187
- value={field.state.value}
188
- onBlur={field.handleBlur}
189
- onChange={(e) => field.handleChange(e.currentTarget.value)}
190
- error={field.state.meta.errors.length > 0}
191
- errorText={firstError(field.state.meta.errors)}
192
- autoComplete="family-name"
193
- />
194
- )}
195
- </form.Field>
196
-
197
- <form.Field name="username">
198
- {(field) => (
199
- <Input
200
- label="Username"
201
- id="username"
202
- name={field.name}
203
- value={field.state.value}
204
- onBlur={field.handleBlur}
205
- onChange={(e) => field.handleChange(e.currentTarget.value)}
206
- error={field.state.meta.errors.length > 0}
207
- errorText={firstError(field.state.meta.errors)}
208
- helpText="Optional. Leave blank to clear."
209
- autoComplete="username"
210
- />
211
- )}
212
- </form.Field>
213
-
214
- <form.Field name="email">
215
- {(field) => (
216
- <Input
217
- label="Email"
218
- id="email"
219
- name={field.name}
220
- type="email"
221
- value={field.state.value}
222
- onBlur={field.handleBlur}
223
- onChange={(e) => field.handleChange(e.currentTarget.value)}
224
- error={field.state.meta.errors.length > 0}
225
- errorText={firstError(field.state.meta.errors)}
226
- autoComplete="email"
227
- required
228
- />
229
- )}
230
- </form.Field>
231
-
232
- <div className={cx('byline-user-update-flags', styles.flags)}>
233
- <form.Field name="is_enabled">
234
- {(field) => (
235
- <Checkbox
236
- id="is_enabled"
237
- name={field.name}
238
- label="Enabled"
239
- checked={field.state.value}
240
- onCheckedChange={(checked) => field.handleChange(checked === true)}
241
- helpText="Disabled accounts cannot sign in."
242
- />
243
- )}
244
- </form.Field>
245
-
246
- <form.Field name="is_email_verified">
247
- {(field) => (
248
- <Checkbox
249
- id="is_email_verified"
250
- name={field.name}
251
- label="Email verified"
252
- checked={field.state.value}
253
- onCheckedChange={(checked) => field.handleChange(checked === true)}
254
- />
255
- )}
256
- </form.Field>
257
-
258
- <form.Field name="is_super_admin">
259
- {(field) => (
260
- <Checkbox
261
- id="is_super_admin"
262
- name={field.name}
263
- label="Super admin"
264
- checked={field.state.value}
265
- onCheckedChange={(checked) => field.handleChange(checked === true)}
266
- helpText="Super admins bypass every ability check — grant with care."
267
- />
268
- )}
269
- </form.Field>
270
- </div>
271
-
272
- <div className={cx('byline-user-update-actions', styles.actions)}>
273
- <Button
274
- type="button"
275
- intent="secondary"
276
- size="sm"
277
- onClick={onClose}
278
- className={cx('byline-user-update-action', styles.action)}
279
- >
280
- {successMessage ? 'Close' : 'Cancel'}
281
- </Button>
282
- <form.Subscribe
283
- selector={(state) => ({
284
- canSubmit: state.canSubmit,
285
- isSubmitting: state.isSubmitting,
286
- isDirty: state.isDirty,
287
- })}
288
- >
289
- {({ canSubmit, isSubmitting }) => (
290
- <Button
291
- size="sm"
292
- intent="primary"
293
- type="submit"
294
- disabled={!canSubmit || isSubmitting}
295
- className={cx('byline-user-update-action', styles.action)}
296
- >
297
- {isSubmitting === true ? <LoaderEllipsis size={42} /> : 'Save'}
298
- </Button>
299
- )}
300
- </form.Subscribe>
301
- </div>
302
- </form>
303
- </div>
304
- )
305
- }
306
-
307
- function firstError(errors: readonly unknown[]): string | undefined {
308
- for (const err of errors) {
309
- if (typeof err === 'string') return err
310
- if (err && typeof err === 'object' && 'message' in err) {
311
- const msg = (err as { message?: unknown }).message
312
- if (typeof msg === 'string') return msg
313
- }
314
- }
315
- return undefined
316
- }
317
-
318
- /**
319
- * Extract the admin-users error code from a thrown server-fn response.
320
- * Typed errors (`AdminUsersError`, `AuthError`) survive the server-fn
321
- * boundary with their `code` intact thanks to the `BylineCodedError`
322
- * serialization adapter registered in `src/start.ts`.
323
- */
324
- function getErrorCode(err: unknown): string | null {
325
- return typeof (err as { code?: unknown })?.code === 'string'
326
- ? (err as { code: string }).code
327
- : null
328
- }
@@ -1,62 +0,0 @@
1
- /**
2
- * SignInForm — admin sign-in card form.
3
- *
4
- * Override handles:
5
- * .byline-sign-in-card — outer Card (responsive width)
6
- * .byline-sign-in-alert — error alert spacing
7
- * .byline-sign-in-form — the form element
8
- * .byline-sign-in-fields — vertical stack of inputs
9
- * .byline-sign-in-actions — action row (optional Home link + submit button)
10
- * .byline-sign-in-home-link — left-side "Home" link (rendered when homeUrl is set)
11
- * .byline-sign-in-button — the submit button (min-width)
12
- */
13
-
14
- .card,
15
- :global(.byline-sign-in-card) {
16
- width: 100%;
17
- }
18
-
19
- @media (min-width: 40rem) {
20
- .card,
21
- :global(.byline-sign-in-card) {
22
- max-width: 380px;
23
- }
24
- }
25
-
26
- .alert,
27
- :global(.byline-sign-in-alert) {
28
- margin-top: var(--spacing-12);
29
- }
30
-
31
- .form,
32
- :global(.byline-sign-in-form) {
33
- padding-top: var(--spacing-8);
34
- margin-bottom: var(--spacing-8);
35
- }
36
-
37
- .fields,
38
- :global(.byline-sign-in-fields) {
39
- display: flex;
40
- flex-direction: column;
41
- gap: var(--spacing-16);
42
- }
43
-
44
- .actions,
45
- :global(.byline-sign-in-actions) {
46
- display: flex;
47
- align-items: center;
48
- margin-top: var(--spacing-24);
49
- }
50
-
51
- .home-link,
52
- :global(.byline-sign-in-home-link) {
53
- font-size: 0.9rem;
54
- text-decoration: underline;
55
- }
56
-
57
- .button,
58
- :global(.byline-sign-in-button) {
59
- min-width: 5rem;
60
- /* Always floats right whether or not a Home link is present on the left. */
61
- margin-left: auto;
62
- }
@@ -1,132 +0,0 @@
1
- 'use client'
2
-
3
- /**
4
- * This Source Code is subject to the terms of the Mozilla Public
5
- * License, v. 2.0. If a copy of the MPL was not distributed with this
6
- * file, You can obtain one at http://mozilla.org/MPL/2.0/.
7
- *
8
- * Copyright (c) Infonomic Company Limited
9
- */
10
-
11
- /**
12
- * Admin sign-in form.
13
- *
14
- * Client component — collects email + password, calls the `adminSignIn`
15
- * server fn, and on success navigates to the caller-supplied
16
- * `callbackUrl` (or `/admin`). On failure renders a generic "Invalid
17
- * credentials" alert; the provider equalises timing between
18
- * unknown-email and wrong-password so the UI doesn't distinguish the two.
19
- *
20
- * Stable override handles: `.byline-sign-in-card`, `.byline-sign-in-alert`,
21
- * `.byline-sign-in-form`, `.byline-sign-in-fields`,
22
- * `.byline-sign-in-actions`, `.byline-sign-in-button`,
23
- * `.byline-sign-in-home-link`.
24
- */
25
-
26
- import { type FormEvent, useState } from 'react'
27
-
28
- import cx from 'classnames'
29
-
30
- import { useBylineAdminServices } from '../../../services/admin-services-context.js'
31
- import { Alert, Button, Card, Input, LoaderEllipsis } from '../../../uikit.js'
32
- import styles from './sign-in-form.module.css'
33
-
34
- interface SignInFormProps {
35
- /** Destination after successful sign-in. Defaults to `/admin`. */
36
- callbackUrl?: string
37
- /**
38
- * Optional plain "Home" link rendered on the left of the action row.
39
- * Typically the host's configured `serverURL` so signed-out admins can
40
- * navigate back to the public site without typing the URL.
41
- */
42
- homeUrl?: string
43
- }
44
-
45
- export function SignInForm({ callbackUrl, homeUrl }: SignInFormProps) {
46
- const { adminSignIn } = useBylineAdminServices()
47
- const [email, setEmail] = useState('')
48
- const [password, setPassword] = useState('')
49
- const [pending, setPending] = useState(false)
50
- const [error, setError] = useState<string | null>(null)
51
-
52
- async function handleSubmit(event: FormEvent<HTMLFormElement>) {
53
- event.preventDefault()
54
- if (pending) return
55
- if (email.trim().length === 0 || password.length === 0) {
56
- setError('Enter your email and password.')
57
- return
58
- }
59
-
60
- setPending(true)
61
- setError(null)
62
- try {
63
- await adminSignIn({ data: { email: email.trim(), password } })
64
- const target = callbackUrl && callbackUrl.length > 0 ? callbackUrl : '/admin'
65
- // Full-page navigation — the admin layout needs to re-run its
66
- // `beforeLoad` guard against the freshly-set session cookies.
67
- window.location.assign(target)
68
- } catch (err) {
69
- console.warn('sign-in failed', err)
70
- setError('Invalid credentials.')
71
- setPending(false)
72
- }
73
- }
74
-
75
- return (
76
- <Card className={cx('byline-sign-in-card', styles.card)}>
77
- <Card.Header>
78
- <Card.Title>
79
- <h2>Sign in</h2>
80
- </Card.Title>
81
- <Card.Description>Sign in to the Byline admin.</Card.Description>
82
- {error && (
83
- <Alert intent="danger" className={cx('byline-sign-in-alert', styles.alert)}>
84
- {error}
85
- </Alert>
86
- )}
87
- </Card.Header>
88
- <Card.Content>
89
- <form onSubmit={handleSubmit} noValidate className={cx('byline-sign-in-form', styles.form)}>
90
- <div className={cx('byline-sign-in-fields', styles.fields)}>
91
- <Input
92
- label="Email"
93
- id="email"
94
- name="email"
95
- type="email"
96
- autoComplete="email"
97
- required
98
- value={email}
99
- onChange={(event) => setEmail(event.currentTarget.value)}
100
- disabled={pending}
101
- />
102
- <Input
103
- label="Password"
104
- id="password"
105
- name="password"
106
- type="password"
107
- autoComplete="current-password"
108
- required
109
- value={password}
110
- onChange={(event) => setPassword(event.currentTarget.value)}
111
- disabled={pending}
112
- />
113
- </div>
114
- <div className={cx('byline-sign-in-actions', styles.actions)}>
115
- {homeUrl && (
116
- <a href={homeUrl} className={cx('byline-sign-in-home-link', styles['home-link'])}>
117
- Home
118
- </a>
119
- )}
120
- <Button
121
- type="submit"
122
- disabled={pending}
123
- className={cx('byline-sign-in-button', styles.button)}
124
- >
125
- {pending ? <LoaderEllipsis size={30} color="#aaaaaa" /> : <span>Sign In</span>}
126
- </Button>
127
- </div>
128
- </form>
129
- </Card.Content>
130
- </Card>
131
- )
132
- }
@@ -1,35 +0,0 @@
1
- /**
2
- * This Source Code is subject to the terms of the Mozilla Public
3
- * License, v. 2.0. If a copy of the MPL was not distributed with this
4
- * file, You can obtain one at http://mozilla.org/MPL/2.0/.
5
- *
6
- * Copyright (c) Infonomic Company Limited
7
- */
8
-
9
- import { createContext, type ReactNode, useContext } from 'react'
10
-
11
- import type { BylineAdminServices } from './admin-services-types.js'
12
-
13
- const AdminServicesContext = createContext<BylineAdminServices | null>(null)
14
-
15
- interface BylineAdminServicesProviderProps {
16
- services: BylineAdminServices
17
- children: ReactNode
18
- }
19
-
20
- export const BylineAdminServicesProvider = ({
21
- services,
22
- children,
23
- }: BylineAdminServicesProviderProps) => (
24
- <AdminServicesContext.Provider value={services}>{children}</AdminServicesContext.Provider>
25
- )
26
-
27
- export const useBylineAdminServices = (): BylineAdminServices => {
28
- const ctx = useContext(AdminServicesContext)
29
- if (!ctx) {
30
- throw new Error(
31
- '@byline/ui: BylineAdminServicesProvider missing. Wrap your admin tree with <BylineAdminServicesProvider services={…} />.'
32
- )
33
- }
34
- return ctx
35
- }