@byline/ui 2.4.0 → 2.4.2

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,119 +0,0 @@
1
- /**
2
- * UserRoles — drawer for assigning roles to a user.
3
- *
4
- * Override handles:
5
- * .byline-user-roles-wrap — outer container
6
- * .byline-user-roles-empty — "no roles created yet" empty-state
7
- * .byline-user-roles-empty-hint — inline machine-name hint
8
- * .byline-user-roles-list — flat checkbox list
9
- * .byline-user-roles-row — single role row
10
- * .byline-user-roles-label — clickable label
11
- * .byline-user-roles-label-head — name + machine-name pill row
12
- * .byline-user-roles-name — role display name
13
- * .byline-user-roles-machine — inline code pill (machine name)
14
- * .byline-user-roles-description — role description
15
- * .byline-user-roles-actions — Cancel/Save row
16
- * .byline-user-roles-action — buttons in the actions row
17
- */
18
-
19
- .wrap,
20
- :global(.byline-user-roles-wrap) {
21
- display: flex;
22
- flex-direction: column;
23
- gap: var(--spacing-12);
24
- padding: var(--spacing-4);
25
- margin-top: var(--spacing-4);
26
- }
27
-
28
- .empty,
29
- :global(.byline-user-roles-empty) {
30
- margin: 0;
31
- font-style: italic;
32
- }
33
-
34
- .empty-hint,
35
- :global(.byline-user-roles-empty-hint) {
36
- /* Inherits muted colour from the parent .muted utility. */
37
- }
38
-
39
- .list,
40
- :global(.byline-user-roles-list) {
41
- display: flex;
42
- flex-direction: column;
43
- gap: var(--spacing-4);
44
- }
45
-
46
- .row,
47
- :global(.byline-user-roles-row) {
48
- display: flex;
49
- align-items: flex-start;
50
- gap: var(--spacing-8);
51
- padding: var(--spacing-4) 0;
52
- }
53
-
54
- .label,
55
- :global(.byline-user-roles-label) {
56
- min-width: 0;
57
- flex: 1 1 0;
58
- cursor: pointer;
59
- }
60
-
61
- .label-head,
62
- :global(.byline-user-roles-label-head) {
63
- display: flex;
64
- align-items: center;
65
- gap: var(--spacing-8);
66
- }
67
-
68
- .name,
69
- :global(.byline-user-roles-name) {
70
- font-size: var(--font-size-sm);
71
- font-weight: var(--font-weight-medium);
72
- }
73
-
74
- .machine,
75
- :global(.byline-user-roles-machine) {
76
- background-color: var(--gray-100);
77
- padding: 0.125rem 0.375rem;
78
- font-size: var(--font-size-xs);
79
- border-radius: var(--border-radius-sm);
80
- }
81
-
82
- .description,
83
- :global(.byline-user-roles-description) {
84
- margin-bottom: 0;
85
- font-size: var(--font-size-xs);
86
- }
87
-
88
- .actions,
89
- :global(.byline-user-roles-actions) {
90
- display: flex;
91
- align-items: center;
92
- justify-content: flex-end;
93
- gap: var(--spacing-8);
94
- margin-top: var(--spacing-16);
95
- }
96
-
97
- .action,
98
- :global(.byline-user-roles-action) {
99
- min-width: 4rem;
100
- }
101
-
102
- /*
103
- * Checkbox shrink-fit — see admin-roles/permissions.module.css for the
104
- * rationale; the same override is needed here for the per-user role
105
- * checkbox list. `!important` is required to win over the uikit
106
- * Checkbox's `width: 100%` default at equal specificity.
107
- */
108
- .checkbox-auto,
109
- :global(.byline-user-roles-checkbox-auto) {
110
- /* biome-ignore lint/complexity/noImportantStyles: see admin-roles/permissions.module.css */
111
- width: auto !important;
112
- }
113
-
114
- :is([data-theme="dark"], :global(.dark)) {
115
- .machine,
116
- :global(.byline-user-roles-machine) {
117
- background-color: var(--canvas-800);
118
- }
119
- }
@@ -1,172 +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
- * User-roles drawer.
13
- *
14
- * Renders a flat checkbox list of every available role, pre-checked
15
- * from the user's current assignments. On save we wholesale-replace
16
- * the user's role-set via `setUserRoles`; the response carries the
17
- * authoritative stored set so the editor's "initial" baseline resets
18
- * cleanly.
19
- *
20
- * Standard drawer pattern (no view/edit mode toggle) — role lists are
21
- * short by design and the drawer is a short-lived edit context, not
22
- * a steady-state inspector. Save + Cancel are always visible; Save
23
- * is disabled until dirty.
24
- */
25
-
26
- import { useState } from 'react'
27
-
28
- import type { AdminRoleResponse, UserRolesResponse } from '@byline/admin/admin-roles'
29
- import type { AdminUserResponse } from '@byline/admin/admin-users'
30
- import cx from 'classnames'
31
-
32
- import { useBylineAdminServices } from '../../../services/admin-services-context.js'
33
- import { Alert, Button, Checkbox, LoaderEllipsis } from '../../../uikit.js'
34
- import styles from './roles.module.css'
35
-
36
- interface UserRolesProps {
37
- user: AdminUserResponse
38
- allRoles: AdminRoleResponse[]
39
- initialRoleIds: string[]
40
- onClose?: () => void
41
- onSaved?: (response: UserRolesResponse) => void
42
- }
43
-
44
- function setsEqual(a: ReadonlySet<string>, b: ReadonlySet<string>): boolean {
45
- if (a.size !== b.size) return false
46
- for (const item of a) if (!b.has(item)) return false
47
- return true
48
- }
49
-
50
- export function UserRoles({ user, allRoles, initialRoleIds, onClose, onSaved }: UserRolesProps) {
51
- const { setUserRoles } = useBylineAdminServices()
52
- const [initialSet, setInitialSet] = useState<ReadonlySet<string>>(() => new Set(initialRoleIds))
53
- const [selected, setSelected] = useState<Set<string>>(() => new Set(initialRoleIds))
54
- const [saving, setSaving] = useState(false)
55
- const [error, setError] = useState<string | null>(null)
56
- const [successMessage, setSuccessMessage] = useState<string | null>(null)
57
-
58
- const isDirty = !setsEqual(selected, initialSet)
59
-
60
- function handleToggle(roleId: string, checked: boolean): void {
61
- setSelected((current) => {
62
- const next = new Set(current)
63
- if (checked) next.add(roleId)
64
- else next.delete(roleId)
65
- return next
66
- })
67
- setSuccessMessage(null)
68
- }
69
-
70
- async function handleSave(): Promise<void> {
71
- if (saving) return
72
- setSaving(true)
73
- setError(null)
74
- setSuccessMessage(null)
75
- try {
76
- const response = await setUserRoles({
77
- data: { userId: user.id, roleIds: Array.from(selected) },
78
- })
79
- const storedSet = new Set(response.roles.map((r) => r.id))
80
- setInitialSet(storedSet)
81
- setSelected(new Set(storedSet))
82
- setSuccessMessage('Saved.')
83
- onSaved?.(response)
84
- } catch (err) {
85
- const code = getErrorCode(err)
86
- if (code === 'admin.roles.userNotFound') {
87
- setError('This user no longer exists.')
88
- } else if (code === 'admin.roles.notFound') {
89
- setError('One or more selected roles no longer exist. Reload the page and try again.')
90
- } else {
91
- setError('Could not save roles. Please try again.')
92
- }
93
- } finally {
94
- setSaving(false)
95
- }
96
- }
97
-
98
- return (
99
- <div className={cx('byline-user-roles-wrap', styles.wrap)}>
100
- {error ? <Alert intent="danger">{error}</Alert> : null}
101
- {successMessage ? <Alert intent="success">{successMessage}</Alert> : null}
102
-
103
- {allRoles.length === 0 ? (
104
- <p className={cx('muted', 'byline-user-roles-empty', styles.empty)}>
105
- No roles have been created yet. Create roles in{' '}
106
- <span className="muted">/admin/roles</span> first.
107
- </p>
108
- ) : (
109
- <div className={cx('byline-user-roles-list', styles.list)}>
110
- {allRoles.map((role) => (
111
- <div key={role.id} className={cx('byline-user-roles-row', styles.row)}>
112
- <Checkbox
113
- id={`role-${role.id}`}
114
- name={`role-${role.id}`}
115
- checked={selected.has(role.id)}
116
- disabled={saving}
117
- onCheckedChange={(checked) => handleToggle(role.id, checked === true)}
118
- containerClasses={cx('byline-user-roles-checkbox-auto', styles['checkbox-auto'])}
119
- componentClasses={cx('byline-user-roles-checkbox-auto', styles['checkbox-auto'])}
120
- />
121
- <label
122
- htmlFor={`role-${role.id}`}
123
- className={cx('byline-user-roles-label', styles.label)}
124
- >
125
- <div className={cx('byline-user-roles-label-head', styles['label-head'])}>
126
- <span className={cx('byline-user-roles-name', styles.name)}>{role.name}</span>
127
- <code className={cx('byline-user-roles-machine', styles.machine)}>
128
- {role.machine_name}
129
- </code>
130
- </div>
131
- {role.description ? (
132
- <p className={cx('muted', 'byline-user-roles-description', styles.description)}>
133
- {role.description}
134
- </p>
135
- ) : null}
136
- </label>
137
- </div>
138
- ))}
139
- </div>
140
- )}
141
-
142
- <div className={cx('byline-user-roles-actions', styles.actions)}>
143
- <Button
144
- type="button"
145
- intent="secondary"
146
- size="xs"
147
- onClick={onClose}
148
- disabled={saving}
149
- className={cx('byline-user-roles-action', styles.action)}
150
- >
151
- {successMessage ? 'Close' : 'Cancel'}
152
- </Button>
153
- <Button
154
- type="button"
155
- intent="primary"
156
- size="xs"
157
- onClick={() => void handleSave()}
158
- disabled={saving || !isDirty}
159
- className={cx('byline-user-roles-action', styles.action)}
160
- >
161
- {saving ? <LoaderEllipsis size={30} /> : 'Save'}
162
- </Button>
163
- </div>
164
- </div>
165
- )
166
- }
167
-
168
- function getErrorCode(err: unknown): string | null {
169
- return typeof (err as { code?: unknown })?.code === 'string'
170
- ? (err as { code: string }).code
171
- : null
172
- }
@@ -1,46 +0,0 @@
1
- /**
2
- * SetAdminUserPassword — privileged "set password" drawer form.
3
- *
4
- * Override handles:
5
- * .byline-user-set-password-wrap — outer container
6
- * .byline-user-set-password-form — vertical-stack form element
7
- * .byline-user-set-password-target — bold target email span in the lead-in
8
- * .byline-user-set-password-actions — Cancel/Save row
9
- * .byline-user-set-password-action — buttons in the actions row
10
- */
11
-
12
- .wrap,
13
- :global(.byline-user-set-password-wrap) {
14
- display: flex;
15
- flex-direction: column;
16
- gap: var(--spacing-8);
17
- padding: var(--spacing-4);
18
- margin-top: var(--spacing-4);
19
- }
20
-
21
- .form,
22
- :global(.byline-user-set-password-form) {
23
- display: flex;
24
- flex-direction: column;
25
- gap: var(--spacing-16);
26
- padding-top: var(--spacing-8);
27
- }
28
-
29
- .target,
30
- :global(.byline-user-set-password-target) {
31
- font-weight: var(--font-weight-semibold);
32
- }
33
-
34
- .actions,
35
- :global(.byline-user-set-password-actions) {
36
- display: flex;
37
- align-items: center;
38
- justify-content: flex-end;
39
- gap: var(--spacing-8);
40
- margin-top: var(--spacing-16);
41
- }
42
-
43
- .action,
44
- :global(.byline-user-set-password-action) {
45
- min-width: 4rem;
46
- }
@@ -1,199 +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
- * Set-password drawer form.
13
- *
14
- * Admin-facing "set this user's password" flow — used when an admin is
15
- * resetting someone else's password. Server-side policy (min 12 chars,
16
- * max 256) is duplicated client-side via Zod for immediate field
17
- * validation. A matching-confirmation field catches typos without a
18
- * round-trip.
19
- *
20
- * The server fn returns the updated user so we can lift the bumped
21
- * `vid` back into the container; the drawer doesn't need to re-fetch.
22
- */
23
-
24
- import { useState } from 'react'
25
- import { revalidateLogic, useForm } from '@tanstack/react-form-start'
26
-
27
- import type { AdminUserResponse } from '@byline/admin/admin-users'
28
- import { passwordSchema } from '@byline/core/validation'
29
- import cx from 'classnames'
30
- import { z } from 'zod'
31
-
32
- import { useBylineAdminServices } from '../../../services/admin-services-context.js'
33
- import { Alert, Button, InputPassword, LoaderEllipsis } from '../../../uikit.js'
34
- import styles from './set-password.module.css'
35
-
36
- const setPasswordFormSchema = z
37
- .object({
38
- password: passwordSchema,
39
- confirm: z.string({ message: 'Please confirm the password' }),
40
- })
41
- .refine((v) => v.password === v.confirm, {
42
- message: 'Passwords do not match',
43
- path: ['confirm'],
44
- })
45
-
46
- type SetPasswordValues = z.infer<typeof setPasswordFormSchema>
47
-
48
- interface SetPasswordProps {
49
- user: AdminUserResponse
50
- onClose?: () => void
51
- onSuccess?: (user: AdminUserResponse) => void
52
- }
53
-
54
- export function SetPassword({ user, onClose, onSuccess }: SetPasswordProps) {
55
- const { setAdminUserPassword } = useBylineAdminServices()
56
- const [formError, setFormError] = useState<string | null>(null)
57
- const [successMessage, setSuccessMessage] = useState<string | null>(null)
58
-
59
- const form = useForm({
60
- defaultValues: { password: '', confirm: '' } as SetPasswordValues,
61
- validationLogic: revalidateLogic({
62
- mode: 'blur',
63
- modeAfterSubmission: 'change',
64
- }),
65
- validators: {
66
- onDynamic: setPasswordFormSchema,
67
- },
68
- onSubmit: async ({ value }) => {
69
- setFormError(null)
70
- setSuccessMessage(null)
71
- try {
72
- const updated = await setAdminUserPassword({
73
- data: { id: user.id, vid: user.vid, password: value.password },
74
- })
75
- setSuccessMessage('Password updated.')
76
- form.reset({ password: '', confirm: '' })
77
- onSuccess?.(updated)
78
- } catch (err) {
79
- const code = getErrorCode(err)
80
- if (code === 'admin.users.versionConflict') {
81
- setFormError(
82
- 'This user has been modified elsewhere since you opened this form. Reload to refresh and try again.'
83
- )
84
- return
85
- }
86
- if (code === 'admin.users.notFound') {
87
- setFormError('This user no longer exists.')
88
- return
89
- }
90
- setFormError('Could not set the password. Please try again.')
91
- }
92
- },
93
- })
94
-
95
- return (
96
- <div className={cx('byline-user-set-password-wrap', styles.wrap)}>
97
- <form
98
- noValidate
99
- onSubmit={(event) => {
100
- event.preventDefault()
101
- event.stopPropagation()
102
- void form.handleSubmit()
103
- }}
104
- className={cx('byline-user-set-password-form', styles.form)}
105
- >
106
- {formError ? <Alert intent="danger">{formError}</Alert> : null}
107
- {successMessage ? <Alert intent="success">{successMessage}</Alert> : null}
108
-
109
- <p className="muted">
110
- Sets a new password for{' '}
111
- <span className={cx('byline-user-set-password-target', styles.target)}>{user.email}</span>
112
- . The user will need to sign in again with the new password.
113
- </p>
114
-
115
- <form.Field name="password">
116
- {(field) => (
117
- <InputPassword
118
- label="New password"
119
- id="password"
120
- name={field.name}
121
- value={field.state.value}
122
- onBlur={field.handleBlur}
123
- onChange={(e) => field.handleChange(e.currentTarget.value)}
124
- error={field.state.meta.errors.length > 0}
125
- errorText={firstError(field.state.meta.errors)}
126
- autoComplete="new-password"
127
- required
128
- />
129
- )}
130
- </form.Field>
131
-
132
- <form.Field name="confirm">
133
- {(field) => (
134
- <InputPassword
135
- label="Confirm new password"
136
- id="confirm"
137
- name={field.name}
138
- value={field.state.value}
139
- onBlur={field.handleBlur}
140
- onChange={(e) => field.handleChange(e.currentTarget.value)}
141
- error={field.state.meta.errors.length > 0}
142
- errorText={firstError(field.state.meta.errors)}
143
- autoComplete="new-password"
144
- required
145
- />
146
- )}
147
- </form.Field>
148
-
149
- <div className={cx('byline-user-set-password-actions', styles.actions)}>
150
- <Button
151
- type="button"
152
- intent="secondary"
153
- size="sm"
154
- onClick={onClose}
155
- className={cx('byline-user-set-password-action', styles.action)}
156
- >
157
- {successMessage ? 'Close' : 'Cancel'}
158
- </Button>
159
- <form.Subscribe
160
- selector={(state) => ({
161
- canSubmit: state.canSubmit,
162
- isSubmitting: state.isSubmitting,
163
- isDirty: state.isDirty,
164
- })}
165
- >
166
- {({ canSubmit, isSubmitting }) => (
167
- <Button
168
- size="sm"
169
- intent="primary"
170
- type="submit"
171
- disabled={!canSubmit || isSubmitting}
172
- className={cx('byline-user-set-password-action', styles.action)}
173
- >
174
- {isSubmitting === true ? <LoaderEllipsis size={42} /> : 'Save'}
175
- </Button>
176
- )}
177
- </form.Subscribe>
178
- </div>
179
- </form>
180
- </div>
181
- )
182
- }
183
-
184
- function firstError(errors: readonly unknown[]): string | undefined {
185
- for (const err of errors) {
186
- if (typeof err === 'string') return err
187
- if (err && typeof err === 'object' && 'message' in err) {
188
- const msg = (err as { message?: unknown }).message
189
- if (typeof msg === 'string') return msg
190
- }
191
- }
192
- return undefined
193
- }
194
-
195
- function getErrorCode(err: unknown): string | null {
196
- return typeof (err as { code?: unknown })?.code === 'string'
197
- ? (err as { code: string }).code
198
- : null
199
- }
@@ -1,49 +0,0 @@
1
- /**
2
- * UpdateAdminUser — drawer form for editing an admin user.
3
- *
4
- * Override handles:
5
- * .byline-user-update-wrap — outer container
6
- * .byline-user-update-form — vertical-stack form element
7
- * .byline-user-update-flags — checkbox stack (enabled / verified / super)
8
- * .byline-user-update-actions — Cancel/Save row
9
- * .byline-user-update-action — buttons in the actions row
10
- */
11
-
12
- .wrap,
13
- :global(.byline-user-update-wrap) {
14
- display: flex;
15
- flex-direction: column;
16
- gap: var(--spacing-8);
17
- padding: var(--spacing-4);
18
- margin-top: var(--spacing-4);
19
- }
20
-
21
- .form,
22
- :global(.byline-user-update-form) {
23
- display: flex;
24
- flex-direction: column;
25
- gap: var(--spacing-16);
26
- padding-top: var(--spacing-8);
27
- }
28
-
29
- .flags,
30
- :global(.byline-user-update-flags) {
31
- display: flex;
32
- flex-direction: column;
33
- gap: var(--spacing-8);
34
- padding: var(--spacing-4);
35
- }
36
-
37
- .actions,
38
- :global(.byline-user-update-actions) {
39
- display: flex;
40
- align-items: center;
41
- justify-content: flex-end;
42
- gap: var(--spacing-8);
43
- margin-top: var(--spacing-16);
44
- }
45
-
46
- .action,
47
- :global(.byline-user-update-action) {
48
- min-width: 4rem;
49
- }