@zerotal/admin 1.9.0 → 1.11.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.
- package/api-surface.md +42 -42
- package/package.json +9 -9
- package/src/Resource.ts +4 -4
- package/src/authRoles.ts +2 -2
- package/src/config.ts +35 -26
- package/src/databaseMedia.ts +2 -2
- package/src/databaseNotifications.ts +5 -4
- package/src/history.ts +2 -2
- package/src/media.ts +4 -4
- package/src/theme.ts +4 -4
package/api-surface.md
CHANGED
|
@@ -1115,31 +1115,31 @@ interface ActionContext = {
|
|
|
1115
1115
|
}
|
|
1116
1116
|
|
|
1117
1117
|
interface AdminAuthConfig = {
|
|
1118
|
-
authMiddleware?: MiddlewareClass[]
|
|
1119
|
-
authenticateWhen?: (user: unknown) => boolean | Promise<boolean>
|
|
1120
|
-
emailVerification?: { isVerified(user: unknown): boolean; resend(user: unknown): Promise<void> | void;}
|
|
1121
|
-
enabled?: boolean
|
|
1122
|
-
guestMiddleware?: MiddlewareClass[]
|
|
1123
|
-
heading?: string
|
|
1124
|
-
identifier?: string
|
|
1125
|
-
loginPath?: string
|
|
1126
|
-
passwordReset?: { sendResetLink(email: string): Promise<boolean> | boolean; reset(input: { email: string; token: string; password: string; }): Promise<boolean> | boolean;}
|
|
1127
|
-
profilePath?: string
|
|
1128
|
-
redirectTo?: string
|
|
1129
|
-
remember?: boolean
|
|
1130
|
-
updateProfile?: (user: unknown, data: Record<string, unknown>) => Promise<void> | void
|
|
1118
|
+
authMiddleware?: MiddlewareClass[] | undefined
|
|
1119
|
+
authenticateWhen?: ((user: unknown) => boolean | Promise<boolean>) | undefined
|
|
1120
|
+
emailVerification?: { isVerified(user: unknown): boolean; resend(user: unknown): Promise<void> | void;} | undefined
|
|
1121
|
+
enabled?: boolean | undefined
|
|
1122
|
+
guestMiddleware?: MiddlewareClass[] | undefined
|
|
1123
|
+
heading?: string | undefined
|
|
1124
|
+
identifier?: string | undefined
|
|
1125
|
+
loginPath?: string | undefined
|
|
1126
|
+
passwordReset?: { sendResetLink(email: string): Promise<boolean> | boolean; reset(input: { email: string; token: string; password: string; }): Promise<boolean> | boolean;} | undefined
|
|
1127
|
+
profilePath?: string | undefined
|
|
1128
|
+
redirectTo?: string | undefined
|
|
1129
|
+
remember?: boolean | undefined
|
|
1130
|
+
updateProfile?: ((user: unknown, data: Record<string, unknown>) => Promise<void> | void) | undefined
|
|
1131
1131
|
}
|
|
1132
1132
|
|
|
1133
1133
|
interface AdminConfigShape = {
|
|
1134
|
-
auth?: AdminAuthConfig
|
|
1135
|
-
authorize?: AdminAuthorizer
|
|
1134
|
+
auth?: AdminAuthConfig | undefined
|
|
1135
|
+
authorize?: AdminAuthorizer | undefined
|
|
1136
1136
|
brand: string
|
|
1137
|
-
middleware?: MiddlewareClass[]
|
|
1137
|
+
middleware?: MiddlewareClass[] | undefined
|
|
1138
1138
|
path: string
|
|
1139
|
-
plugins?: Record<string, boolean>
|
|
1140
|
-
tagline?: string
|
|
1141
|
-
theme?: AdminThemeConfig
|
|
1142
|
-
userMenu?: UserMenu
|
|
1139
|
+
plugins?: Record<string, boolean> | undefined
|
|
1140
|
+
tagline?: string | undefined
|
|
1141
|
+
theme?: AdminThemeConfig | undefined
|
|
1142
|
+
userMenu?: UserMenu | undefined
|
|
1143
1143
|
}
|
|
1144
1144
|
|
|
1145
1145
|
interface AdminModel = {
|
|
@@ -1202,15 +1202,15 @@ interface AdminRecord = {
|
|
|
1202
1202
|
}
|
|
1203
1203
|
|
|
1204
1204
|
interface AdminThemeConfig = {
|
|
1205
|
-
cdn?: boolean
|
|
1206
|
-
noFonts?: boolean
|
|
1207
|
-
stylesheet?: string
|
|
1208
|
-
tokensCss?: string
|
|
1205
|
+
cdn?: boolean | undefined
|
|
1206
|
+
noFonts?: boolean | undefined
|
|
1207
|
+
stylesheet?: string | undefined
|
|
1208
|
+
tokensCss?: string | undefined
|
|
1209
1209
|
}
|
|
1210
1210
|
|
|
1211
1211
|
interface AuthRolesOptions = {
|
|
1212
|
-
guard?: string
|
|
1213
|
-
superusers?: string[]
|
|
1212
|
+
guard?: string | undefined
|
|
1213
|
+
superusers?: string[] | undefined
|
|
1214
1214
|
}
|
|
1215
1215
|
|
|
1216
1216
|
interface ChartData = {
|
|
@@ -1312,15 +1312,15 @@ interface DashboardLayoutStore = {
|
|
|
1312
1312
|
}
|
|
1313
1313
|
|
|
1314
1314
|
interface DatabaseMediaOptions = {
|
|
1315
|
-
columns?: Partial<Record<keyof MediaItem, string>>
|
|
1316
|
-
table?: string
|
|
1315
|
+
columns?: Partial<Record<keyof MediaItem, string>> | undefined
|
|
1316
|
+
table?: string | undefined
|
|
1317
1317
|
}
|
|
1318
1318
|
|
|
1319
1319
|
interface DatabaseNotificationOptions = {
|
|
1320
|
-
limit?: number
|
|
1321
|
-
notifiable?: () => Promise<unknown> | unknown
|
|
1322
|
-
present?: (row: StoredNotification, data: Record<string, unknown>) => AdminNotification
|
|
1323
|
-
table?: string
|
|
1320
|
+
limit?: number | undefined
|
|
1321
|
+
notifiable?: (() => Promise<unknown> | unknown) | undefined
|
|
1322
|
+
present?: ((row: StoredNotification, data: Record<string, unknown>) => AdminNotification) | undefined
|
|
1323
|
+
table?: string | undefined
|
|
1324
1324
|
}
|
|
1325
1325
|
|
|
1326
1326
|
interface EmptyState = {
|
|
@@ -1378,8 +1378,8 @@ interface HistoryEntry = {
|
|
|
1378
1378
|
|
|
1379
1379
|
interface HistoryOptions = {
|
|
1380
1380
|
id: unknown
|
|
1381
|
-
limit?: number
|
|
1382
|
-
resolveActor?: (id: number) => Promise<string | null> | string | null
|
|
1381
|
+
limit?: number | undefined
|
|
1382
|
+
resolveActor?: ((id: number) => Promise<string | null> | string | null) | undefined
|
|
1383
1383
|
type: string
|
|
1384
1384
|
}
|
|
1385
1385
|
|
|
@@ -1396,12 +1396,12 @@ interface ImportResult = {
|
|
|
1396
1396
|
}
|
|
1397
1397
|
|
|
1398
1398
|
interface ListOptions = {
|
|
1399
|
-
modifyQuery?: QueryModifier
|
|
1400
|
-
page?: number
|
|
1401
|
-
perPage?: number
|
|
1399
|
+
modifyQuery?: QueryModifier | undefined
|
|
1400
|
+
page?: number | undefined
|
|
1401
|
+
perPage?: number | undefined
|
|
1402
1402
|
search?: string | undefined
|
|
1403
1403
|
sortBy?: string | undefined
|
|
1404
|
-
sortDir?: 'asc' | 'desc'
|
|
1404
|
+
sortDir?: 'asc' | 'desc' | undefined
|
|
1405
1405
|
thenSort?: readonly { column: string; direction: 'asc' | 'desc';}[] | undefined
|
|
1406
1406
|
trashed?: 'with' | 'only' | undefined
|
|
1407
1407
|
}
|
|
@@ -1550,10 +1550,10 @@ interface StoredNotification = {
|
|
|
1550
1550
|
}
|
|
1551
1551
|
|
|
1552
1552
|
interface StoreMediaOptions = {
|
|
1553
|
-
accept?: string[]
|
|
1554
|
-
disk?: string
|
|
1555
|
-
folder?: string
|
|
1556
|
-
maxBytes?: number
|
|
1553
|
+
accept?: string[] | undefined
|
|
1554
|
+
disk?: string | undefined
|
|
1555
|
+
folder?: string | undefined
|
|
1556
|
+
maxBytes?: number | undefined
|
|
1557
1557
|
provider: MediaProvider
|
|
1558
1558
|
}
|
|
1559
1559
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zerotal/admin",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.11.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"maturity": "stable",
|
|
6
6
|
"private": false,
|
|
@@ -32,16 +32,16 @@
|
|
|
32
32
|
"typecheck": "tsc --noEmit"
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"@zerotal/cache": "1.
|
|
36
|
-
"@zerotal/core": "1.
|
|
37
|
-
"@zerotal/flow": "1.
|
|
38
|
-
"@zerotal/flow-ui": "1.
|
|
39
|
-
"@zerotal/validator": "1.
|
|
35
|
+
"@zerotal/cache": "1.11.0",
|
|
36
|
+
"@zerotal/core": "1.11.0",
|
|
37
|
+
"@zerotal/flow": "1.11.0",
|
|
38
|
+
"@zerotal/flow-ui": "1.11.0",
|
|
39
|
+
"@zerotal/validator": "1.11.0"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
|
-
"@zerotal/orm": "1.
|
|
43
|
-
"@zerotal/auth": "1.
|
|
44
|
-
"@zerotal/queue": "1.
|
|
42
|
+
"@zerotal/orm": "1.11.0",
|
|
43
|
+
"@zerotal/auth": "1.11.0",
|
|
44
|
+
"@zerotal/queue": "1.11.0"
|
|
45
45
|
},
|
|
46
46
|
"peerDependencies": {
|
|
47
47
|
"@zerotal/orm": "^1.0.0",
|
package/src/Resource.ts
CHANGED
|
@@ -124,13 +124,13 @@ export interface RecordPage {
|
|
|
124
124
|
}
|
|
125
125
|
|
|
126
126
|
export interface ListOptions {
|
|
127
|
-
page?: number;
|
|
128
|
-
perPage?: number;
|
|
127
|
+
page?: number | undefined;
|
|
128
|
+
perPage?: number | undefined;
|
|
129
129
|
search?: string | undefined;
|
|
130
130
|
sortBy?: string | undefined;
|
|
131
|
-
sortDir?: "asc" | "desc";
|
|
131
|
+
sortDir?: "asc" | "desc" | undefined;
|
|
132
132
|
/** Scope the base query before search/sort/pagination (e.g. the active tab). */
|
|
133
|
-
modifyQuery?: QueryModifier;
|
|
133
|
+
modifyQuery?: QueryModifier | undefined;
|
|
134
134
|
/** Soft-delete scope: include trashed (`with`) or only trashed (`only`). */
|
|
135
135
|
trashed?: "with" | "only" | undefined;
|
|
136
136
|
/**
|
package/src/authRoles.ts
CHANGED
|
@@ -24,7 +24,7 @@ export interface AuthRolesOptions {
|
|
|
24
24
|
* Guard the roles belong to. Defaults to `"web"`, matching the framework's
|
|
25
25
|
* own default, so most apps need not think about it.
|
|
26
26
|
*/
|
|
27
|
-
guard?: string;
|
|
27
|
+
guard?: string | undefined;
|
|
28
28
|
/**
|
|
29
29
|
* Role names that hold every permission.
|
|
30
30
|
*
|
|
@@ -32,7 +32,7 @@ export interface AuthRolesOptions {
|
|
|
32
32
|
* something the data can tell you. A superuser role is shown as holding
|
|
33
33
|
* everything and cannot be edited or deleted from the panel.
|
|
34
34
|
*/
|
|
35
|
-
superusers?: string[];
|
|
35
|
+
superusers?: string[] | undefined;
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
/** The role surface this needs, kept structural so `auth` stays optional. */
|
package/src/config.ts
CHANGED
|
@@ -26,37 +26,46 @@ export interface UserMenu {
|
|
|
26
26
|
*/
|
|
27
27
|
export interface AdminAuthConfig {
|
|
28
28
|
/** Mount the auth pages. */
|
|
29
|
-
enabled?: boolean;
|
|
29
|
+
enabled?: boolean | undefined;
|
|
30
30
|
/** Login route (relative to the panel path). Default `/login`. */
|
|
31
|
-
loginPath?: string;
|
|
31
|
+
loginPath?: string | undefined;
|
|
32
32
|
/** Profile route (relative to the panel path). Default `/profile`. */
|
|
33
|
-
profilePath?: string;
|
|
33
|
+
profilePath?: string | undefined;
|
|
34
34
|
/** Where to send the user after a successful login. Default the panel root. */
|
|
35
|
-
redirectTo?: string;
|
|
35
|
+
redirectTo?: string | undefined;
|
|
36
36
|
/** The credential column users log in with. Default `"email"`. */
|
|
37
|
-
identifier?: string;
|
|
37
|
+
identifier?: string | undefined;
|
|
38
38
|
/** Show a "remember me" checkbox. Default `true`. */
|
|
39
|
-
remember?: boolean;
|
|
39
|
+
remember?: boolean | undefined;
|
|
40
40
|
/** Heading on the auth screens. Defaults to the panel brand. */
|
|
41
|
-
heading?: string;
|
|
41
|
+
heading?: string | undefined;
|
|
42
42
|
/** Extra gate after the password check (e.g. "is the account active?"). */
|
|
43
|
-
authenticateWhen?: (user: unknown) => boolean | Promise<boolean
|
|
43
|
+
authenticateWhen?: ((user: unknown) => boolean | Promise<boolean>) | undefined;
|
|
44
44
|
/** Persist profile edits (name/email). Defaults to `user.fill(data); user.save()`. */
|
|
45
|
-
updateProfile?:
|
|
45
|
+
updateProfile?:
|
|
46
|
+
((user: unknown, data: Record<string, unknown>) => Promise<void> | void) | undefined;
|
|
46
47
|
/** Middleware guarding the guest screens (login/forgot/reset). Default none. */
|
|
47
|
-
guestMiddleware?: MiddlewareClass[];
|
|
48
|
+
guestMiddleware?: MiddlewareClass[] | undefined;
|
|
48
49
|
/** Middleware guarding the profile/verify screens. Defaults to the panel guard. */
|
|
49
|
-
authMiddleware?: MiddlewareClass[];
|
|
50
|
+
authMiddleware?: MiddlewareClass[] | undefined;
|
|
50
51
|
/** Password-reset broker — mounting the forgot/reset pages when provided. */
|
|
51
|
-
passwordReset?:
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
52
|
+
passwordReset?:
|
|
53
|
+
| {
|
|
54
|
+
sendResetLink(email: string): Promise<boolean> | boolean;
|
|
55
|
+
reset(input: {
|
|
56
|
+
email: string;
|
|
57
|
+
token: string;
|
|
58
|
+
password: string;
|
|
59
|
+
}): Promise<boolean> | boolean;
|
|
60
|
+
}
|
|
61
|
+
| undefined;
|
|
55
62
|
/** Email-verification hooks — mounting the verify page when provided. */
|
|
56
|
-
emailVerification?:
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
63
|
+
emailVerification?:
|
|
64
|
+
| {
|
|
65
|
+
isVerified(user: unknown): boolean;
|
|
66
|
+
resend(user: unknown): Promise<void> | void;
|
|
67
|
+
}
|
|
68
|
+
| undefined;
|
|
60
69
|
}
|
|
61
70
|
|
|
62
71
|
/** Admin panel configuration (read from `config/admin.ts`, with defaults). */
|
|
@@ -66,7 +75,7 @@ export interface AdminConfigShape {
|
|
|
66
75
|
/** Brand name shown in the sidebar. */
|
|
67
76
|
brand: string;
|
|
68
77
|
/** Optional short tagline under the brand. */
|
|
69
|
-
tagline?: string;
|
|
78
|
+
tagline?: string | undefined;
|
|
70
79
|
/**
|
|
71
80
|
* Middleware guarding every panel route. When left empty, the panel is
|
|
72
81
|
* default-denied in production-like environments (fail closed) and open only
|
|
@@ -75,13 +84,13 @@ export interface AdminConfigShape {
|
|
|
75
84
|
* `[AuthMiddleware.with({ ... })]`. To deliberately expose it without auth,
|
|
76
85
|
* pass an explicit pass-through middleware.
|
|
77
86
|
*/
|
|
78
|
-
middleware?: MiddlewareClass[];
|
|
87
|
+
middleware?: MiddlewareClass[] | undefined;
|
|
79
88
|
/** Optional top-bar user menu (Profile / Logout / …). */
|
|
80
|
-
userMenu?: UserMenu;
|
|
89
|
+
userMenu?: UserMenu | undefined;
|
|
81
90
|
/** Styling source — Tailwind Play CDN (default) or a prebuilt stylesheet. */
|
|
82
|
-
theme?: AdminThemeConfig;
|
|
91
|
+
theme?: AdminThemeConfig | undefined;
|
|
83
92
|
/** Auth pages (login / profile / password-reset / email-verification). */
|
|
84
|
-
auth?: AdminAuthConfig;
|
|
93
|
+
auth?: AdminAuthConfig | undefined;
|
|
85
94
|
/**
|
|
86
95
|
* Decide the abilities named by pages, widgets, nav entries and search
|
|
87
96
|
* providers. Set this when the app models permissions itself; leave it unset to
|
|
@@ -90,13 +99,13 @@ export interface AdminConfigShape {
|
|
|
90
99
|
* With neither configured, every ability is denied outside a development
|
|
91
100
|
* environment — a panel with no authorization wired stays closed in production.
|
|
92
101
|
*/
|
|
93
|
-
authorize?: AdminAuthorizer;
|
|
102
|
+
authorize?: AdminAuthorizer | undefined;
|
|
94
103
|
/**
|
|
95
104
|
* Switch contributing packages off by id — `{ monitor: false }` keeps the
|
|
96
105
|
* monitor provider installed but drops its pages, widgets and nav entries from
|
|
97
106
|
* the panel. Anything absent here is on.
|
|
98
107
|
*/
|
|
99
|
-
plugins?: Record<string, boolean
|
|
108
|
+
plugins?: Record<string, boolean> | undefined;
|
|
100
109
|
}
|
|
101
110
|
|
|
102
111
|
/**
|
package/src/databaseMedia.ts
CHANGED
|
@@ -21,9 +21,9 @@ import type { MediaItem, MediaProvider } from "./media.ts";
|
|
|
21
21
|
|
|
22
22
|
export interface DatabaseMediaOptions {
|
|
23
23
|
/** Table holding the catalogue. Defaults to `"media"`. */
|
|
24
|
-
table?: string;
|
|
24
|
+
table?: string | undefined;
|
|
25
25
|
/** Map the panel's fields onto your column names. */
|
|
26
|
-
columns?: Partial<Record<keyof MediaItem, string
|
|
26
|
+
columns?: Partial<Record<keyof MediaItem, string>> | undefined;
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
const DEFAULT_COLUMNS: Record<keyof MediaItem, string> = {
|
|
@@ -32,21 +32,22 @@ export interface StoredNotification {
|
|
|
32
32
|
|
|
33
33
|
export interface DatabaseNotificationOptions {
|
|
34
34
|
/** Table holding the notifications. Defaults to `"notifications"`. */
|
|
35
|
-
table?: string;
|
|
35
|
+
table?: string | undefined;
|
|
36
36
|
/**
|
|
37
37
|
* Who the bell is showing. Defaults to the signed-in user from
|
|
38
38
|
* `@zerotal/auth`; returning `null` shows nothing, which is the right answer
|
|
39
39
|
* for a guest.
|
|
40
40
|
*/
|
|
41
|
-
notifiable?: () => Promise<unknown> | unknown;
|
|
41
|
+
notifiable?: (() => Promise<unknown> | unknown) | undefined;
|
|
42
42
|
/** How many to show. Defaults to 20 — a bell is not an archive. */
|
|
43
|
-
limit?: number;
|
|
43
|
+
limit?: number | undefined;
|
|
44
44
|
/**
|
|
45
45
|
* Turn a stored row into what the panel renders. The default reads `title`,
|
|
46
46
|
* `body`/`message`, `url`/`href` and `icon` out of the payload, which is what
|
|
47
47
|
* most notifications carry.
|
|
48
48
|
*/
|
|
49
|
-
present?:
|
|
49
|
+
present?:
|
|
50
|
+
((row: StoredNotification, data: Record<string, unknown>) => AdminNotification) | undefined;
|
|
50
51
|
}
|
|
51
52
|
|
|
52
53
|
/** Parse a row's JSON payload, tolerating a payload that was never JSON. */
|
package/src/history.ts
CHANGED
|
@@ -50,9 +50,9 @@ export interface HistoryOptions {
|
|
|
50
50
|
type: string;
|
|
51
51
|
id: unknown;
|
|
52
52
|
/** How many entries to show. Defaults to 25 — a record page is not an archive. */
|
|
53
|
-
limit?: number;
|
|
53
|
+
limit?: number | undefined;
|
|
54
54
|
/** Turn an actor id into a name. Defaults to `#<id>`. */
|
|
55
|
-
resolveActor?: (id: number) => Promise<string | null> | string | null;
|
|
55
|
+
resolveActor?: ((id: number) => Promise<string | null> | string | null) | undefined;
|
|
56
56
|
}
|
|
57
57
|
|
|
58
58
|
/** Fields that change on every write and say nothing about intent. */
|
package/src/media.ts
CHANGED
|
@@ -220,12 +220,12 @@ export function isUpload(value: unknown): value is UploadedFileLike {
|
|
|
220
220
|
export interface StoreMediaOptions {
|
|
221
221
|
provider: MediaProvider;
|
|
222
222
|
/** Disk to write to; the default disk when omitted. */
|
|
223
|
-
disk?: string;
|
|
224
|
-
folder?: string;
|
|
223
|
+
disk?: string | undefined;
|
|
224
|
+
folder?: string | undefined;
|
|
225
225
|
/** Refuse anything larger, in bytes. */
|
|
226
|
-
maxBytes?: number;
|
|
226
|
+
maxBytes?: number | undefined;
|
|
227
227
|
/** Accepted MIME types; anything goes when omitted. */
|
|
228
|
-
accept?: string[];
|
|
228
|
+
accept?: string[] | undefined;
|
|
229
229
|
}
|
|
230
230
|
|
|
231
231
|
/**
|
package/src/theme.ts
CHANGED
|
@@ -38,13 +38,13 @@ export const THEME_TOGGLE_SCRIPT = FLOW_THEME_TOGGLE_SCRIPT;
|
|
|
38
38
|
*/
|
|
39
39
|
export interface AdminThemeConfig {
|
|
40
40
|
/** A prebuilt stylesheet URL/path to link instead of (or alongside) the CDN. */
|
|
41
|
-
stylesheet?: string;
|
|
41
|
+
stylesheet?: string | undefined;
|
|
42
42
|
/** Keep loading the Tailwind Play CDN. Defaults to `true` unless `stylesheet` is set. */
|
|
43
|
-
cdn?: boolean;
|
|
43
|
+
cdn?: boolean | undefined;
|
|
44
44
|
/** Extra design-token CSS appended after the defaults (override `:root` / `.dark`). */
|
|
45
|
-
tokensCss?: string;
|
|
45
|
+
tokensCss?: string | undefined;
|
|
46
46
|
/** Skip the bundled Google Fonts links (e.g. you self-host Inter). */
|
|
47
|
-
noFonts?: boolean;
|
|
47
|
+
noFonts?: boolean | undefined;
|
|
48
48
|
}
|
|
49
49
|
|
|
50
50
|
/** The design-token CSS (`:root` + `.dark` custom properties + base styles). */
|