@strapi-community/plugin-better-auth-dashboard 1.0.0-alpha.8 → 1.0.0-beta.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.
@@ -0,0 +1,733 @@
1
+ import { jsx, jsxs, Fragment } from "react/jsx-runtime";
2
+ import { Modal, Typography, Button, Portal, Flex, IconButton, Box, Field, TextInput, Combobox, ComboboxOption, Checkbox, SingleSelect, SingleSelectOption, NumberInput, JSONInput, Textarea } from "@strapi/design-system";
3
+ import { Cross, Images, Trash } from "@strapi/icons";
4
+ import { useEffect, useState, useRef } from "react";
5
+ import styled, { keyframes } from "styled-components";
6
+ import { f as getMediaLibraryComponent, i as getEditViewSidePanels } from "./index-D9CiI8Yr.mjs";
7
+ import { useFetchClient } from "@strapi/strapi/admin";
8
+ import { useQuery } from "react-query";
9
+ function ConfirmDialog({
10
+ title,
11
+ message,
12
+ confirmLabel = "Confirm",
13
+ variant = "danger",
14
+ loading = false,
15
+ onConfirm,
16
+ onCancel
17
+ }) {
18
+ return /* @__PURE__ */ jsx(
19
+ Modal.Root,
20
+ {
21
+ defaultOpen: true,
22
+ onOpenChange: (open) => !open && onCancel(),
23
+ children: /* @__PURE__ */ jsxs(Modal.Content, { children: [
24
+ /* @__PURE__ */ jsx(Modal.Header, { children: /* @__PURE__ */ jsx(Typography, { variant: "beta", tag: "h2", children: title }) }),
25
+ /* @__PURE__ */ jsx(Modal.Body, { children: /* @__PURE__ */ jsx(Typography, { variant: "omega", children: message }) }),
26
+ /* @__PURE__ */ jsxs(Modal.Footer, { children: [
27
+ /* @__PURE__ */ jsx(Button, { variant: "tertiary", onClick: onCancel, disabled: loading, children: "Cancel" }),
28
+ /* @__PURE__ */ jsx(Button, { variant, loading, onClick: onConfirm, children: confirmLabel })
29
+ ] })
30
+ ] })
31
+ }
32
+ );
33
+ }
34
+ const DASH_CONTEXT_HEADER = "X-Dash-Context";
35
+ const withContext = (ctx, headers) => ({
36
+ headers: {
37
+ ...headers,
38
+ [DASH_CONTEXT_HEADER]: btoa(JSON.stringify(ctx))
39
+ }
40
+ });
41
+ const slideIn = keyframes`
42
+ from { transform: translateX(100%); opacity: 0.6; }
43
+ to { transform: translateX(0); opacity: 1; }
44
+ `;
45
+ const fadeIn = keyframes`
46
+ from { opacity: 0; }
47
+ to { opacity: 1; }
48
+ `;
49
+ const Overlay = styled.div`
50
+ position: absolute;
51
+ inset: 0;
52
+ background: rgba(33, 33, 52, 0.4);
53
+ animation: ${fadeIn} 180ms ease;
54
+ `;
55
+ const Panel = styled.div`
56
+ position: absolute;
57
+ top: 0;
58
+ right: 0;
59
+ bottom: 0;
60
+ width: min(760px, 95vw);
61
+ display: flex;
62
+ flex-direction: column;
63
+ background: white;
64
+ box-shadow: -8px 0 40px rgba(33, 33, 52, 0.18);
65
+ animation: ${slideIn} 220ms cubic-bezier(0.25, 0.46, 0.45, 0.94);
66
+ `;
67
+ function Drawer({
68
+ title,
69
+ children,
70
+ footer,
71
+ onClose,
72
+ "data-testid": testId
73
+ }) {
74
+ useEffect(() => {
75
+ const prev = document.body.style.overflow;
76
+ document.body.style.overflow = "hidden";
77
+ return () => {
78
+ document.body.style.overflow = prev;
79
+ };
80
+ }, []);
81
+ useEffect(() => {
82
+ const handler = (e) => {
83
+ if (e.key === "Escape") onClose();
84
+ };
85
+ document.addEventListener("keydown", handler);
86
+ return () => document.removeEventListener("keydown", handler);
87
+ }, [onClose]);
88
+ return /* @__PURE__ */ jsx(Portal, { children: /* @__PURE__ */ jsxs("div", { style: { position: "fixed", inset: 0, zIndex: 200 }, children: [
89
+ /* @__PURE__ */ jsx(Overlay, { onClick: onClose, "aria-hidden": "true" }),
90
+ /* @__PURE__ */ jsxs(Panel, { "data-testid": testId, children: [
91
+ /* @__PURE__ */ jsxs(
92
+ Flex,
93
+ {
94
+ justifyContent: "space-between",
95
+ alignItems: "center",
96
+ paddingTop: 5,
97
+ paddingBottom: 5,
98
+ paddingLeft: 6,
99
+ paddingRight: 6,
100
+ borderColor: "neutral150",
101
+ borderStyle: "solid",
102
+ borderWidth: "0 0 1px 0",
103
+ style: { flexShrink: 0 },
104
+ children: [
105
+ /* @__PURE__ */ jsx(Typography, { variant: "beta", tag: "h2", children: title }),
106
+ /* @__PURE__ */ jsx(IconButton, { label: "Close panel", onClick: onClose, children: /* @__PURE__ */ jsx(Cross, {}) })
107
+ ]
108
+ }
109
+ ),
110
+ /* @__PURE__ */ jsx(
111
+ Box,
112
+ {
113
+ paddingTop: 6,
114
+ paddingBottom: 6,
115
+ paddingLeft: 6,
116
+ paddingRight: 6,
117
+ style: { flex: 1, overflowY: "auto" },
118
+ children
119
+ }
120
+ ),
121
+ footer && /* @__PURE__ */ jsx(
122
+ Flex,
123
+ {
124
+ justifyContent: "flex-end",
125
+ gap: 2,
126
+ paddingTop: 4,
127
+ paddingBottom: 4,
128
+ paddingLeft: 6,
129
+ paddingRight: 6,
130
+ borderColor: "neutral150",
131
+ borderStyle: "solid",
132
+ borderWidth: "1px 0 0 0",
133
+ style: { flexShrink: 0 },
134
+ children: footer
135
+ }
136
+ )
137
+ ] })
138
+ ] }) });
139
+ }
140
+ const FormSection = styled.div`
141
+ width: 100%;
142
+ background: #f6f6f9;
143
+ border-radius: 8px;
144
+ padding: 16px 20px;
145
+ display: flex;
146
+ flex-direction: column;
147
+ gap: 14px;
148
+ `;
149
+ const EditLayout = styled.div`
150
+ display: grid;
151
+ grid-template-columns: minmax(0, 1fr) 256px;
152
+ gap: 28px;
153
+ align-items: start;
154
+ padding-top: 24px;
155
+ `;
156
+ const EditSidebar = styled.div`
157
+ display: flex;
158
+ flex-direction: column;
159
+ gap: 20px;
160
+ position: sticky;
161
+ top: 0;
162
+ `;
163
+ const SectionLabel = styled.p`
164
+ font-size: 11px;
165
+ font-weight: 700;
166
+ color: #8e8ea9;
167
+ text-transform: uppercase;
168
+ letter-spacing: 0.05em;
169
+ margin: 0 0 4px;
170
+ `;
171
+ styled.div`
172
+ background: #f6f6f9;
173
+ border-radius: 8px;
174
+ padding: 16px;
175
+ display: grid;
176
+ grid-template-columns: 1fr 1fr;
177
+ gap: 16px;
178
+ `;
179
+ const MetaItem = styled.div`
180
+ display: flex;
181
+ flex-direction: column;
182
+ gap: 4px;
183
+ `;
184
+ const MetaKey = styled.span`
185
+ font-size: 11px;
186
+ font-weight: 600;
187
+ color: #8e8ea9;
188
+ text-transform: uppercase;
189
+ letter-spacing: 0.03em;
190
+ `;
191
+ const MetaVal = styled.span`
192
+ font-size: 13px;
193
+ color: #32324d;
194
+ `;
195
+ const MonoChip = styled.code`
196
+ display: inline;
197
+ font-size: 11px;
198
+ color: #4945ff;
199
+ font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace;
200
+ word-break: break-all;
201
+ background: #f0f0ff;
202
+ padding: 2px 6px;
203
+ border-radius: 3px;
204
+ `;
205
+ const ProviderBadge = styled.span`
206
+ display: inline-flex;
207
+ align-items: center;
208
+ padding: 2px 8px;
209
+ background: #f0f0ff;
210
+ border: 1px solid #d9d8ff;
211
+ border-radius: 4px;
212
+ font-size: 12px;
213
+ font-weight: 600;
214
+ color: #4945ff;
215
+ text-transform: capitalize;
216
+ `;
217
+ const WarnCard = styled.div`
218
+ background: #fcecea;
219
+ border: 1px solid #f5c0b8;
220
+ border-radius: 8px;
221
+ padding: 14px 16px;
222
+ display: flex;
223
+ flex-direction: column;
224
+ gap: 4px;
225
+ `;
226
+ styled.div`
227
+ background: #eafbe7;
228
+ border: 1px solid #c6efbd;
229
+ border-radius: 8px;
230
+ padding: 14px 16px;
231
+ `;
232
+ const PreviewPill = styled.div`
233
+ display: inline-flex;
234
+ align-items: center;
235
+ gap: 6px;
236
+ padding: 6px 12px;
237
+ background: #fff3d3;
238
+ border: 1px solid #f5d97f;
239
+ border-radius: 6px;
240
+ font-size: 12px;
241
+ font-weight: 500;
242
+ color: #8e6a00;
243
+ width: fit-content;
244
+ `;
245
+ const AccountRow = styled.div`
246
+ width: 100%;
247
+ display: flex;
248
+ align-items: center;
249
+ justify-content: space-between;
250
+ padding: 10px 14px;
251
+ background: white;
252
+ border: 1px solid #dcdce4;
253
+ border-radius: 8px;
254
+ gap: 12px;
255
+ `;
256
+ const DangerRow = styled(AccountRow)`
257
+ background: #fef8f8;
258
+ border-color: #f5c0b8;
259
+ `;
260
+ const RoleBadge = styled.span`
261
+ display: inline-flex;
262
+ align-items: center;
263
+ padding: 2px 8px;
264
+ border-radius: 4px;
265
+ font-size: 11px;
266
+ font-weight: 600;
267
+ text-transform: capitalize;
268
+ background: ${(p) => p.$role === "owner" ? "#f0f0ff" : p.$role === "admin" ? "#eafbe7" : "#f5f5f9"};
269
+ border: 1px solid
270
+ ${(p) => p.$role === "owner" ? "#d9d8ff" : p.$role === "admin" ? "#c6efbd" : "#dcdce4"};
271
+ color: ${(p) => p.$role === "owner" ? "#4945ff" : p.$role === "admin" ? "#2e8044" : "#666687"};
272
+ `;
273
+ function MediaPickerField({
274
+ label,
275
+ value,
276
+ onChange,
277
+ hint,
278
+ placeholder,
279
+ name,
280
+ required
281
+ }) {
282
+ const [showMedia, setShowMedia] = useState(false);
283
+ const MediaLibraryDialog = getMediaLibraryComponent();
284
+ const handleSelect = (assets) => {
285
+ const asset = assets[0];
286
+ if (!asset) return;
287
+ const url = asset.formats?.small?.url ?? asset.formats?.thumbnail?.url ?? asset.url;
288
+ onChange(url);
289
+ setShowMedia(false);
290
+ };
291
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
292
+ /* @__PURE__ */ jsxs(Field.Root, { style: { width: "100%" }, hint, required, children: [
293
+ /* @__PURE__ */ jsx(Field.Label, { children: label }),
294
+ /* @__PURE__ */ jsxs(Flex, { gap: 2, alignItems: "center", children: [
295
+ /* @__PURE__ */ jsx("div", { style: { flex: 1, minWidth: 0 }, children: /* @__PURE__ */ jsx(
296
+ TextInput,
297
+ {
298
+ name,
299
+ type: "url",
300
+ value,
301
+ onChange: (e) => onChange(e.target.value),
302
+ placeholder,
303
+ style: { width: "100%" }
304
+ }
305
+ ) }),
306
+ MediaLibraryDialog && /* @__PURE__ */ jsx(
307
+ Button,
308
+ {
309
+ variant: "secondary",
310
+ size: "S",
311
+ startIcon: /* @__PURE__ */ jsx(Images, {}),
312
+ onClick: () => setShowMedia(true),
313
+ style: { flexShrink: 0 },
314
+ children: "Browse"
315
+ }
316
+ )
317
+ ] }),
318
+ hint && /* @__PURE__ */ jsx(Field.Hint, {})
319
+ ] }),
320
+ showMedia && MediaLibraryDialog && /* @__PURE__ */ jsx(
321
+ MediaLibraryDialog,
322
+ {
323
+ allowedTypes: ["images"],
324
+ multiple: false,
325
+ onClose: () => setShowMedia(false),
326
+ onSelectAssets: handleSelect
327
+ }
328
+ )
329
+ ] });
330
+ }
331
+ const EntryRow = styled.div`
332
+ display: flex;
333
+ align-items: center;
334
+ justify-content: space-between;
335
+ gap: 8px;
336
+ padding: 8px 12px;
337
+ width: 100%;
338
+ box-sizing: border-box;
339
+ background: #ffffff;
340
+ border: 1px solid ${({ theme }) => theme.colors?.neutral200 ?? "#dcdce4"};
341
+ border-radius: 4px;
342
+ min-width: 0;
343
+ `;
344
+ function getDisplayLabel(doc) {
345
+ for (const key of ["name", "title", "email", "username", "label", "slug"]) {
346
+ const v = doc[key];
347
+ if (typeof v === "string" && v.trim()) return v;
348
+ }
349
+ return String(doc.documentId ?? doc.id ?? "");
350
+ }
351
+ function normalizeValue(val, cache) {
352
+ if (!val) return [];
353
+ if (typeof val === "object" && !Array.isArray(val) && val !== null && "set" in val) {
354
+ const items2 = val.set ?? [];
355
+ return items2.filter((item) => item?.documentId).map((item) => ({
356
+ documentId: item.documentId,
357
+ label: cache.get(item.documentId) ?? item.documentId
358
+ }));
359
+ }
360
+ const items = Array.isArray(val) ? val : [val];
361
+ return items.filter(
362
+ (item) => typeof item === "object" && item !== null && "documentId" in item
363
+ ).map((item) => ({
364
+ documentId: String(item.documentId),
365
+ label: getDisplayLabel(item)
366
+ }));
367
+ }
368
+ function RelationField({
369
+ name,
370
+ label,
371
+ attribute,
372
+ value,
373
+ onChange,
374
+ readOnly = false
375
+ }) {
376
+ const { get } = useFetchClient();
377
+ const cache = useRef(/* @__PURE__ */ new Map());
378
+ const [search, setSearch] = useState("");
379
+ const [addKey, setAddKey] = useState(0);
380
+ const target = attribute.target ?? "";
381
+ const relationType = attribute.relation ?? "manyToOne";
382
+ const isMulti = relationType === "oneToMany" || relationType === "manyToMany";
383
+ const currentDocs = normalizeValue(value, cache.current);
384
+ const selectedIds = new Set(currentDocs.map((d) => d.documentId));
385
+ const { data: searchResults = [], isLoading } = useQuery({
386
+ queryKey: ["relation-search", target, search],
387
+ queryFn: async () => {
388
+ const params = new URLSearchParams({
389
+ uid: target,
390
+ "pagination[pageSize]": "50"
391
+ });
392
+ if (search) params.set("filters[name][$containsi]", search);
393
+ const { data } = await get(
394
+ `/better-auth-dashboard/db?${params}`
395
+ );
396
+ const docs = data.results ?? [];
397
+ for (const doc of docs) {
398
+ if (doc.documentId) {
399
+ cache.current.set(String(doc.documentId), getDisplayLabel(doc));
400
+ }
401
+ }
402
+ return docs.map((doc) => ({
403
+ documentId: String(doc.documentId ?? ""),
404
+ label: getDisplayLabel(doc)
405
+ })).filter((d) => d.documentId);
406
+ },
407
+ keepPreviousData: true,
408
+ enabled: !readOnly
409
+ });
410
+ const availableOptions = searchResults.filter(
411
+ (r) => !selectedIds.has(r.documentId)
412
+ );
413
+ const commit = (ids) => {
414
+ onChange(name, { set: ids.map((id) => ({ documentId: id })) });
415
+ };
416
+ const handleSelect = (val) => {
417
+ if (!val) return;
418
+ const opt = searchResults.find((r) => r.documentId === val);
419
+ if (opt) cache.current.set(val, opt.label);
420
+ if (isMulti) {
421
+ if (selectedIds.has(val)) return;
422
+ commit([...currentDocs.map((d) => d.documentId), val]);
423
+ } else {
424
+ commit([val]);
425
+ }
426
+ setSearch("");
427
+ setAddKey((k) => k + 1);
428
+ };
429
+ const handleRemove = (docId) => {
430
+ commit(
431
+ currentDocs.filter((d) => d.documentId !== docId).map((d) => d.documentId)
432
+ );
433
+ };
434
+ return /* @__PURE__ */ jsxs(Field.Root, { style: { width: "100%" }, children: [
435
+ /* @__PURE__ */ jsx(Field.Label, { children: label }),
436
+ !readOnly && /* @__PURE__ */ jsx(
437
+ Combobox,
438
+ {
439
+ value: "",
440
+ onChange: (val) => handleSelect(val),
441
+ onInputChange: (e) => setSearch(e.target.value),
442
+ loading: isLoading,
443
+ placeholder: "Search…",
444
+ children: availableOptions.map((opt) => /* @__PURE__ */ jsx(ComboboxOption, { value: opt.documentId, children: opt.label }, opt.documentId))
445
+ },
446
+ addKey
447
+ ),
448
+ currentDocs.length > 0 && /* @__PURE__ */ jsx(
449
+ Flex,
450
+ {
451
+ direction: "column",
452
+ gap: 1,
453
+ style: { marginTop: 8, width: "100%" },
454
+ children: currentDocs.map((doc) => /* @__PURE__ */ jsxs(EntryRow, { children: [
455
+ /* @__PURE__ */ jsx(
456
+ Typography,
457
+ {
458
+ variant: "omega",
459
+ textColor: "neutral800",
460
+ style: {
461
+ overflow: "hidden",
462
+ textOverflow: "ellipsis",
463
+ whiteSpace: "nowrap",
464
+ flex: 1,
465
+ minWidth: 0
466
+ },
467
+ children: doc.label
468
+ }
469
+ ),
470
+ !readOnly && /* @__PURE__ */ jsx(
471
+ IconButton,
472
+ {
473
+ label: "Remove",
474
+ size: "S",
475
+ onClick: () => handleRemove(doc.documentId),
476
+ children: /* @__PURE__ */ jsx(Trash, {})
477
+ }
478
+ )
479
+ ] }, doc.documentId))
480
+ }
481
+ )
482
+ ] });
483
+ }
484
+ function makeLabel(name) {
485
+ return name.replace(/([A-Z])/g, " $1").replace(/^./, (s) => s.toUpperCase()).trim();
486
+ }
487
+ const fieldStyle = { width: "100%" };
488
+ function DynamicField({
489
+ field,
490
+ value,
491
+ onChange,
492
+ readOnly = false
493
+ }) {
494
+ const { name, attribute } = field;
495
+ const { type, required, enum: enumValues } = attribute;
496
+ const label = makeLabel(name);
497
+ if (type === "boolean") {
498
+ return /* @__PURE__ */ jsxs(Field.Root, { style: fieldStyle, children: [
499
+ /* @__PURE__ */ jsx(Field.Label, { children: label }),
500
+ /* @__PURE__ */ jsx(
501
+ Checkbox,
502
+ {
503
+ checked: Boolean(value),
504
+ onCheckedChange: (checked) => onChange(name, checked),
505
+ disabled: readOnly,
506
+ children: label
507
+ }
508
+ )
509
+ ] });
510
+ }
511
+ if (type === "enumeration" && Array.isArray(enumValues)) {
512
+ return /* @__PURE__ */ jsxs(Field.Root, { style: fieldStyle, children: [
513
+ /* @__PURE__ */ jsx(Field.Label, { children: label }),
514
+ /* @__PURE__ */ jsx(
515
+ SingleSelect,
516
+ {
517
+ value: value != null ? String(value) : "",
518
+ onChange: (v) => onChange(name, String(v)),
519
+ disabled: readOnly,
520
+ required,
521
+ placeholder: "—",
522
+ children: enumValues.map((opt) => /* @__PURE__ */ jsx(SingleSelectOption, { value: opt, children: opt }, opt))
523
+ }
524
+ )
525
+ ] });
526
+ }
527
+ if (type === "integer" || type === "biginteger" || type === "float" || type === "decimal") {
528
+ return /* @__PURE__ */ jsxs(Field.Root, { style: fieldStyle, children: [
529
+ /* @__PURE__ */ jsx(Field.Label, { children: label }),
530
+ /* @__PURE__ */ jsx(
531
+ NumberInput,
532
+ {
533
+ value: value != null ? Number(value) : void 0,
534
+ onValueChange: (v) => onChange(name, v),
535
+ disabled: readOnly,
536
+ required
537
+ }
538
+ )
539
+ ] });
540
+ }
541
+ if (type === "json") {
542
+ const jsonStr = value == null ? "" : typeof value === "string" ? value : JSON.stringify(value, null, 2);
543
+ return /* @__PURE__ */ jsxs(Field.Root, { style: fieldStyle, children: [
544
+ /* @__PURE__ */ jsx(Field.Label, { children: label }),
545
+ /* @__PURE__ */ jsx(
546
+ JSONInput,
547
+ {
548
+ value: jsonStr,
549
+ onChange: (v) => {
550
+ try {
551
+ onChange(name, JSON.parse(v));
552
+ } catch {
553
+ onChange(name, v);
554
+ }
555
+ },
556
+ disabled: readOnly
557
+ }
558
+ )
559
+ ] });
560
+ }
561
+ if (type === "date") {
562
+ const dateStr = value instanceof Date ? value.toISOString().slice(0, 10) : typeof value === "string" ? value.slice(0, 10) : "";
563
+ return /* @__PURE__ */ jsxs(Field.Root, { style: fieldStyle, children: [
564
+ /* @__PURE__ */ jsx(Field.Label, { children: label }),
565
+ /* @__PURE__ */ jsx(
566
+ TextInput,
567
+ {
568
+ type: "date",
569
+ value: dateStr,
570
+ onChange: (e) => onChange(name, e.target.value),
571
+ disabled: readOnly,
572
+ required
573
+ }
574
+ )
575
+ ] });
576
+ }
577
+ if (type === "datetime" || type === "timestamp") {
578
+ const dtStr = value instanceof Date ? value.toISOString().slice(0, 16) : typeof value === "string" ? value.slice(0, 16) : "";
579
+ return /* @__PURE__ */ jsxs(Field.Root, { style: fieldStyle, children: [
580
+ /* @__PURE__ */ jsx(Field.Label, { children: label }),
581
+ /* @__PURE__ */ jsx(
582
+ TextInput,
583
+ {
584
+ type: "datetime-local",
585
+ value: dtStr,
586
+ onChange: (e) => onChange(name, e.target.value),
587
+ disabled: readOnly,
588
+ required
589
+ }
590
+ )
591
+ ] });
592
+ }
593
+ if (type === "text" || type === "richtext") {
594
+ return /* @__PURE__ */ jsxs(Field.Root, { style: fieldStyle, children: [
595
+ /* @__PURE__ */ jsx(Field.Label, { children: label }),
596
+ /* @__PURE__ */ jsx(
597
+ Textarea,
598
+ {
599
+ value: value != null ? String(value) : "",
600
+ onChange: (e) => onChange(name, e.target.value),
601
+ disabled: readOnly
602
+ }
603
+ )
604
+ ] });
605
+ }
606
+ if (type === "relation") {
607
+ return /* @__PURE__ */ jsx(
608
+ RelationField,
609
+ {
610
+ name,
611
+ label,
612
+ attribute,
613
+ value,
614
+ onChange,
615
+ readOnly
616
+ }
617
+ );
618
+ }
619
+ const inputType = type === "email" ? "email" : type === "password" ? "password" : type === "time" ? "time" : "text";
620
+ return /* @__PURE__ */ jsxs(Field.Root, { style: fieldStyle, children: [
621
+ /* @__PURE__ */ jsx(Field.Label, { children: label }),
622
+ /* @__PURE__ */ jsx(
623
+ TextInput,
624
+ {
625
+ type: inputType,
626
+ value: value != null ? String(value) : "",
627
+ onChange: (e) => onChange(name, e.target.value),
628
+ disabled: readOnly,
629
+ required
630
+ }
631
+ )
632
+ ] });
633
+ }
634
+ const SKIP_TYPES = /* @__PURE__ */ new Set(["media", "dynamiczone", "blocks", "component"]);
635
+ function CustomFieldsSection({
636
+ fields,
637
+ data,
638
+ onChange
639
+ }) {
640
+ const renderable = fields.filter((f) => !SKIP_TYPES.has(f.attribute.type));
641
+ if (renderable.length === 0) return null;
642
+ return /* @__PURE__ */ jsxs(FormSection, { children: [
643
+ /* @__PURE__ */ jsx(SectionLabel, { children: "Custom fields" }),
644
+ /* @__PURE__ */ jsx(Flex, { direction: "column", gap: 4, alignItems: "stretch", children: renderable.map((field) => /* @__PURE__ */ jsx(
645
+ DynamicField,
646
+ {
647
+ field,
648
+ value: data[field.name],
649
+ onChange
650
+ },
651
+ field.name
652
+ )) })
653
+ ] });
654
+ }
655
+ function EditViewSidePanels({ model, documentId, document: document2 }) {
656
+ const panels = getEditViewSidePanels(model);
657
+ if (panels.length === 0) return null;
658
+ return /* @__PURE__ */ jsx(Fragment, { children: panels.map(({ id, title, Component }) => /* @__PURE__ */ jsxs(FormSection, { children: [
659
+ /* @__PURE__ */ jsx(SectionLabel, { children: title }),
660
+ /* @__PURE__ */ jsx(
661
+ Component,
662
+ {
663
+ model,
664
+ documentId,
665
+ document: document2
666
+ }
667
+ )
668
+ ] }, id)) });
669
+ }
670
+ const SYSTEM_FIELDS = /* @__PURE__ */ new Set([
671
+ "id",
672
+ "documentId",
673
+ "createdAt",
674
+ "updatedAt",
675
+ "publishedAt",
676
+ "createdBy",
677
+ "updatedBy",
678
+ "locale",
679
+ "localizations"
680
+ ]);
681
+ const MODEL_UID = {
682
+ user: "plugin::better-auth.user",
683
+ organization: "plugin::better-auth.organization"
684
+ };
685
+ function useModelSchema(model) {
686
+ const { get } = useFetchClient();
687
+ return useQuery({
688
+ queryKey: ["ba-model-schema", model],
689
+ queryFn: async () => {
690
+ const { data } = await get(
691
+ "/content-manager/content-types"
692
+ );
693
+ const uid = MODEL_UID[model];
694
+ const contentType = data.data.find((ct) => ct.uid === uid);
695
+ if (!contentType) throw new Error(`Content type ${uid} not found`);
696
+ const attributes = {};
697
+ for (const [name, attr] of Object.entries(contentType.attributes)) {
698
+ if (SYSTEM_FIELDS.has(name)) continue;
699
+ if (attr.type === "relation" && typeof attr.target === "string" && (attr.target.startsWith("plugin::users-permissions") || attr.target.startsWith("admin::")))
700
+ continue;
701
+ const baOptions = attr.pluginOptions?.["better-auth"];
702
+ if (baOptions?.managed === true) continue;
703
+ attributes[name] = attr;
704
+ }
705
+ return attributes;
706
+ },
707
+ staleTime: 10 * 60 * 1e3,
708
+ retry: false
709
+ });
710
+ }
711
+ export {
712
+ AccountRow as A,
713
+ CustomFieldsSection as C,
714
+ Drawer as D,
715
+ EditLayout as E,
716
+ FormSection as F,
717
+ MediaPickerField as M,
718
+ ProviderBadge as P,
719
+ RoleBadge as R,
720
+ SectionLabel as S,
721
+ WarnCard as W,
722
+ EditSidebar as a,
723
+ MetaItem as b,
724
+ MetaKey as c,
725
+ MonoChip as d,
726
+ MetaVal as e,
727
+ EditViewSidePanels as f,
728
+ DangerRow as g,
729
+ PreviewPill as h,
730
+ ConfirmDialog as i,
731
+ useModelSchema as u,
732
+ withContext as w
733
+ };