@dyrected/admin 2.0.0 → 2.4.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/CHANGELOG.md +46 -0
- package/package.json +4 -4
- package/scripts/prefix-tailwind-precision.py +98 -0
- package/scripts/prefix-tailwind.py +67 -0
- package/src/components/auth/auth-gate.tsx +4 -4
- package/src/components/error-boundary.tsx +4 -4
- package/src/components/forms/fields/block-builder.tsx +24 -24
- package/src/components/forms/fields/date-picker.tsx +7 -7
- package/src/components/forms/fields/json-editor.tsx +5 -5
- package/src/components/forms/fields/media-picker.tsx +39 -39
- package/src/components/forms/fields/multi-select.tsx +12 -12
- package/src/components/forms/fields/radio-field.tsx +8 -8
- package/src/components/forms/fields/relationship-picker.tsx +13 -13
- package/src/components/forms/fields/rich-text-editor.tsx +22 -22
- package/src/components/forms/fields/select-field.tsx +3 -3
- package/src/components/forms/form-engine.tsx +3 -3
- package/src/components/forms/form-field-renderer.tsx +37 -37
- package/src/components/layout/admin-shell.tsx +60 -60
- package/src/components/live-preview/LivePreviewPane.tsx +14 -14
- package/src/components/media/focal-point-picker.tsx +9 -9
- package/src/components/media/media-card.tsx +10 -10
- package/src/components/media/media-grid.tsx +3 -3
- package/src/components/media/media-library-dialog.tsx +105 -105
- package/src/components/ui/badge.tsx +5 -5
- package/src/components/ui/button.tsx +11 -11
- package/src/components/ui/calendar.tsx +36 -36
- package/src/components/ui/card.tsx +6 -6
- package/src/components/ui/checkbox.tsx +3 -3
- package/src/components/ui/command.tsx +12 -12
- package/src/components/ui/data-table.tsx +18 -18
- package/src/components/ui/dialog.tsx +9 -9
- package/src/components/ui/dropdown-menu.tsx +16 -16
- package/src/components/ui/form.tsx +4 -4
- package/src/components/ui/input.tsx +3 -3
- package/src/components/ui/label.tsx +1 -1
- package/src/components/ui/page-header.tsx +6 -6
- package/src/components/ui/pagination.tsx +6 -6
- package/src/components/ui/popover.tsx +1 -1
- package/src/components/ui/progress.tsx +2 -2
- package/src/components/ui/radio-group.tsx +4 -4
- package/src/components/ui/render-cell.tsx +16 -16
- package/src/components/ui/scroll-area.tsx +6 -6
- package/src/components/ui/select.tsx +14 -14
- package/src/components/ui/separator.tsx +2 -2
- package/src/components/ui/sheet.tsx +13 -13
- package/src/components/ui/sidebar.tsx +60 -60
- package/src/components/ui/skeleton.tsx +1 -1
- package/src/components/ui/sonner.tsx +1 -1
- package/src/components/ui/switch.tsx +2 -2
- package/src/components/ui/table.tsx +7 -7
- package/src/components/ui/tabs.tsx +3 -3
- package/src/components/ui/textarea.tsx +1 -1
- package/src/components/ui/toggle.tsx +6 -6
- package/src/components/ui/tooltip.tsx +1 -1
- package/src/index.css +27 -27
- package/src/index.tsx +4 -4
- package/src/lib/utils.ts +7 -3
- package/src/pages/auth/first-user-page.tsx +18 -18
- package/src/pages/auth/login-page.tsx +14 -14
- package/src/pages/collections/edit-page.tsx +37 -37
- package/src/pages/collections/list-page.tsx +23 -23
- package/src/pages/dashboard/dashboard.tsx +49 -49
- package/src/pages/globals/editor-page.tsx +13 -13
- package/src/pages/media/media-page.tsx +106 -106
- package/src/pages/setup/setup-prompt.tsx +73 -44
- package/tailwind.config.ts +1 -0
- package/vite.config.ts +0 -1
|
@@ -47,18 +47,18 @@ export function FirstUserPage({
|
|
|
47
47
|
};
|
|
48
48
|
|
|
49
49
|
return (
|
|
50
|
-
<div className="flex min-h-screen items-center justify-center bg-background px-4">
|
|
51
|
-
<div className="w-full max-w-sm space-y-8">
|
|
52
|
-
<div className="space-y-2 text-center">
|
|
53
|
-
<div className="mx-auto h-12 w-12 rounded-full bg-primary/5 flex items-center justify-center mb-4">
|
|
54
|
-
<div className="h-6 w-6 rounded-full border-2 border-primary border-t-transparent animate-pulse" />
|
|
50
|
+
<div className="dy-flex dy-min-h-screen dy-items-center dy-justify-center dy-bg-background dy-px-4">
|
|
51
|
+
<div className="dy-w-full dy-max-w-sm dy-space-y-8">
|
|
52
|
+
<div className="dy-space-y-2 dy-text-center">
|
|
53
|
+
<div className="dy-mx-auto dy-h-12 dy-w-12 dy-rounded-full dy-bg-primary/5 dy-flex dy-items-center dy-justify-center dy-mb-4">
|
|
54
|
+
<div className="dy-h-6 dy-w-6 dy-rounded-full dy-border-2 dy-border-primary dy-border-t-transparent dy-animate-pulse" />
|
|
55
55
|
</div>
|
|
56
|
-
<h1 className="text-2xl font-semibold tracking-tight">Setup Admin Account</h1>
|
|
57
|
-
<p className="text-sm text-muted-foreground">Create the first administrative user to get started</p>
|
|
56
|
+
<h1 className="dy-text-2xl dy-font-semibold dy-tracking-tight">Setup Admin Account</h1>
|
|
57
|
+
<p className="dy-text-sm dy-text-muted-foreground">Create the first administrative user to get started</p>
|
|
58
58
|
</div>
|
|
59
59
|
|
|
60
|
-
<form onSubmit={handleSubmit} className="space-y-4">
|
|
61
|
-
<div className="space-y-2">
|
|
60
|
+
<form onSubmit={handleSubmit} className="dy-space-y-4">
|
|
61
|
+
<div className="dy-space-y-2">
|
|
62
62
|
<Label htmlFor="email">Admin Email</Label>
|
|
63
63
|
<Input
|
|
64
64
|
id="email"
|
|
@@ -67,10 +67,10 @@ export function FirstUserPage({
|
|
|
67
67
|
value={email}
|
|
68
68
|
onChange={(e) => setEmail(e.target.value)}
|
|
69
69
|
required
|
|
70
|
-
className="bg-transparent"
|
|
70
|
+
className="dy-bg-transparent"
|
|
71
71
|
/>
|
|
72
72
|
</div>
|
|
73
|
-
<div className="space-y-2">
|
|
73
|
+
<div className="dy-space-y-2">
|
|
74
74
|
<Label htmlFor="password">Password</Label>
|
|
75
75
|
<Input
|
|
76
76
|
id="password"
|
|
@@ -78,10 +78,10 @@ export function FirstUserPage({
|
|
|
78
78
|
value={password}
|
|
79
79
|
onChange={(e) => setPassword(e.target.value)}
|
|
80
80
|
required
|
|
81
|
-
className="bg-transparent"
|
|
81
|
+
className="dy-bg-transparent"
|
|
82
82
|
/>
|
|
83
83
|
</div>
|
|
84
|
-
<div className="space-y-2">
|
|
84
|
+
<div className="dy-space-y-2">
|
|
85
85
|
<Label htmlFor="confirm-password">Confirm Password</Label>
|
|
86
86
|
<Input
|
|
87
87
|
id="confirm-password"
|
|
@@ -89,23 +89,23 @@ export function FirstUserPage({
|
|
|
89
89
|
value={confirmPassword}
|
|
90
90
|
onChange={(e) => setConfirmPassword(e.target.value)}
|
|
91
91
|
required
|
|
92
|
-
className="bg-transparent"
|
|
92
|
+
className="dy-bg-transparent"
|
|
93
93
|
/>
|
|
94
94
|
</div>
|
|
95
95
|
|
|
96
96
|
{error && (
|
|
97
|
-
<div className="text-xs text-destructive font-medium bg-destructive/10 p-3 rounded-md">
|
|
97
|
+
<div className="dy-text-xs dy-text-destructive dy-font-medium dy-bg-destructive/10 dy-p-3 dy-rounded-md">
|
|
98
98
|
{error}
|
|
99
99
|
</div>
|
|
100
100
|
)}
|
|
101
101
|
|
|
102
|
-
<Button type="submit" className="w-full" disabled={loading}>
|
|
102
|
+
<Button type="submit" className="dy-w-full" disabled={loading}>
|
|
103
103
|
{loading ? "Creating account..." : "Create Admin Account"}
|
|
104
104
|
</Button>
|
|
105
105
|
</form>
|
|
106
106
|
|
|
107
|
-
<div className="pt-4 border-t text-center space-y-2">
|
|
108
|
-
<p className="text-[10px] text-muted-foreground uppercase tracking-widest">
|
|
107
|
+
<div className="dy-pt-4 dy-border-t dy-text-center dy-space-y-2">
|
|
108
|
+
<p className="dy-text-[10px] dy-text-muted-foreground dy-uppercase dy-tracking-widest">
|
|
109
109
|
Dyrected CMS · Initial Setup
|
|
110
110
|
</p>
|
|
111
111
|
</div>
|
|
@@ -37,15 +37,15 @@ export function LoginPage({
|
|
|
37
37
|
};
|
|
38
38
|
|
|
39
39
|
return (
|
|
40
|
-
<div className="flex min-h-screen items-center justify-center bg-background px-4">
|
|
41
|
-
<div className="w-full max-w-sm space-y-8">
|
|
42
|
-
<div className="space-y-2 text-center">
|
|
43
|
-
<h1 className="text-2xl font-semibold tracking-tight">Welcome back</h1>
|
|
44
|
-
<p className="text-sm text-muted-foreground">Enter your credentials to access the dashboard</p>
|
|
40
|
+
<div className="dy-flex dy-min-h-screen dy-items-center dy-justify-center dy-bg-background dy-px-4">
|
|
41
|
+
<div className="dy-w-full dy-max-w-sm dy-space-y-8">
|
|
42
|
+
<div className="dy-space-y-2 dy-text-center">
|
|
43
|
+
<h1 className="dy-text-2xl dy-font-semibold dy-tracking-tight">Welcome back</h1>
|
|
44
|
+
<p className="dy-text-sm dy-text-muted-foreground">Enter your credentials to access the dashboard</p>
|
|
45
45
|
</div>
|
|
46
46
|
|
|
47
|
-
<form onSubmit={handleSubmit} className="space-y-4">
|
|
48
|
-
<div className="space-y-2">
|
|
47
|
+
<form onSubmit={handleSubmit} className="dy-space-y-4">
|
|
48
|
+
<div className="dy-space-y-2">
|
|
49
49
|
<Label htmlFor="email">Email</Label>
|
|
50
50
|
<Input
|
|
51
51
|
id="email"
|
|
@@ -54,11 +54,11 @@ export function LoginPage({
|
|
|
54
54
|
value={email}
|
|
55
55
|
onChange={(e) => setEmail(e.target.value)}
|
|
56
56
|
required
|
|
57
|
-
className="bg-transparent"
|
|
57
|
+
className="dy-bg-transparent"
|
|
58
58
|
/>
|
|
59
59
|
</div>
|
|
60
|
-
<div className="space-y-2">
|
|
61
|
-
<div className="flex items-center justify-between">
|
|
60
|
+
<div className="dy-space-y-2">
|
|
61
|
+
<div className="dy-flex dy-items-center dy-justify-between">
|
|
62
62
|
<Label htmlFor="password">Password</Label>
|
|
63
63
|
</div>
|
|
64
64
|
<Input
|
|
@@ -67,22 +67,22 @@ export function LoginPage({
|
|
|
67
67
|
value={password}
|
|
68
68
|
onChange={(e) => setPassword(e.target.value)}
|
|
69
69
|
required
|
|
70
|
-
className="bg-transparent"
|
|
70
|
+
className="dy-bg-transparent"
|
|
71
71
|
/>
|
|
72
72
|
</div>
|
|
73
73
|
|
|
74
74
|
{error && (
|
|
75
|
-
<div className="text-xs text-destructive font-medium bg-destructive/10 p-3 rounded-md">
|
|
75
|
+
<div className="dy-text-xs dy-text-destructive dy-font-medium dy-bg-destructive/10 dy-p-3 dy-rounded-md">
|
|
76
76
|
{error}
|
|
77
77
|
</div>
|
|
78
78
|
)}
|
|
79
79
|
|
|
80
|
-
<Button type="submit" className="w-full" disabled={loading}>
|
|
80
|
+
<Button type="submit" className="dy-w-full" disabled={loading}>
|
|
81
81
|
{loading ? "Signing in..." : "Sign In"}
|
|
82
82
|
</Button>
|
|
83
83
|
</form>
|
|
84
84
|
|
|
85
|
-
<p className="text-center text-xs text-muted-foreground uppercase tracking-widest">
|
|
85
|
+
<p className="dy-text-center dy-text-xs dy-text-muted-foreground dy-uppercase dy-tracking-widest">
|
|
86
86
|
Dyrected CMS
|
|
87
87
|
</p>
|
|
88
88
|
</div>
|
|
@@ -138,33 +138,33 @@ export function EditEntryPage() {
|
|
|
138
138
|
const canUpdate = (schema.access as any)?.update !== false
|
|
139
139
|
|
|
140
140
|
return (
|
|
141
|
-
<div className="flex h-[calc(100vh-0px)] overflow-hidden
|
|
141
|
+
<div className="dy-flex dy-h-[calc(100vh-0px)] dy-overflow-hidden dy--mt-6 dy--mx-4 lg:dy--mt-10 lg:dy--mx-6">
|
|
142
142
|
{/* Left Column: Header + Form */}
|
|
143
143
|
<div className={cn(
|
|
144
|
-
"flex-1 overflow-y-auto px-6 py-6 lg:px-10 lg:py-10 transition-all duration-500",
|
|
145
|
-
showPreview ? "max-w-2xl xl:max-w-3xl" : "max-w-5xl mx-auto w-full"
|
|
144
|
+
"dy-flex-1 dy-overflow-y-auto dy-px-6 dy-py-6 lg:dy-px-10 lg:dy-py-10 dy-transition-all dy-duration-500",
|
|
145
|
+
showPreview ? "dy-max-w-2xl xl:dy-max-w-3xl" : "dy-max-w-5xl dy-mx-auto dy-w-full"
|
|
146
146
|
)}>
|
|
147
|
-
<div className="space-y-8">
|
|
147
|
+
<div className="dy-space-y-8">
|
|
148
148
|
{/* Header */}
|
|
149
|
-
<div className="flex items-center justify-between gap-4 border-b border-border/50 pb-6">
|
|
150
|
-
<div className="flex items-center gap-4">
|
|
149
|
+
<div className="dy-flex dy-items-center dy-justify-between dy-gap-4 dy-border-b dy-border-border/50 dy-pb-6">
|
|
150
|
+
<div className="dy-flex dy-items-center dy-gap-4">
|
|
151
151
|
<Button
|
|
152
152
|
variant="ghost"
|
|
153
153
|
size="icon"
|
|
154
|
-
className="h-8 w-8 rounded-lg hover:bg-muted shrink-0"
|
|
154
|
+
className="dy-h-8 dy-w-8 dy-rounded-lg hover:dy-bg-muted dy-shrink-0"
|
|
155
155
|
onClick={() => navigate(`/collections/${slug}`)}
|
|
156
156
|
>
|
|
157
|
-
<ChevronLeft className="h-4 w-4" />
|
|
157
|
+
<ChevronLeft className="dy-h-4 dy-w-4" />
|
|
158
158
|
</Button>
|
|
159
159
|
<div>
|
|
160
|
-
<div className="flex items-center gap-3">
|
|
161
|
-
<h1 className="text-lg font-serif font-bold tracking-tight text-foreground truncate">
|
|
160
|
+
<div className="dy-flex dy-items-center dy-gap-3">
|
|
161
|
+
<h1 className="dy-text-lg dy-font-serif dy-font-bold dy-tracking-tight dy-text-foreground dy-truncate">
|
|
162
162
|
{isEdit ? `Edit ${schema.label || schema.slug}` : `New ${schema.label || schema.slug}`}
|
|
163
163
|
</h1>
|
|
164
164
|
{hasStatus && (
|
|
165
165
|
<Badge className={cn(
|
|
166
|
-
"px-2 py-0 rounded-full text-[10px] font-bold uppercase tracking-wider",
|
|
167
|
-
currentStatus === "published" ? "bg-emerald-100 text-emerald-700 border-emerald-200" : "bg-amber-100 text-amber-700 border-amber-200"
|
|
166
|
+
"dy-px-2 dy-py-0 dy-rounded-full dy-text-[10px] dy-font-bold dy-uppercase dy-tracking-wider",
|
|
167
|
+
currentStatus === "published" ? "dy-bg-emerald-100 dy-text-emerald-700 dy-border-emerald-200" : "dy-bg-amber-100 dy-text-amber-700 dy-border-amber-200"
|
|
168
168
|
)} variant="outline">
|
|
169
169
|
{currentStatus === "published" ? "Live" : "Draft"}
|
|
170
170
|
</Badge>
|
|
@@ -173,42 +173,42 @@ export function EditEntryPage() {
|
|
|
173
173
|
</div>
|
|
174
174
|
</div>
|
|
175
175
|
|
|
176
|
-
<div className="flex items-center gap-2">
|
|
176
|
+
<div className="dy-flex dy-items-center dy-gap-2">
|
|
177
177
|
{previewUrl && (
|
|
178
178
|
<Button
|
|
179
179
|
variant="ghost"
|
|
180
180
|
size="icon"
|
|
181
181
|
className={cn(
|
|
182
|
-
"h-9 w-9 rounded-lg transition-colors",
|
|
183
|
-
showPreview ? "bg-primary/10 text-primary hover:bg-primary/20" : "hover:bg-muted"
|
|
182
|
+
"dy-h-9 dy-w-9 dy-rounded-lg dy-transition-colors",
|
|
183
|
+
showPreview ? "dy-bg-primary/10 dy-text-primary hover:dy-bg-primary/20" : "hover:dy-bg-muted"
|
|
184
184
|
)}
|
|
185
185
|
onClick={() => setShowPreview(!showPreview)}
|
|
186
186
|
title={showPreview ? "Hide Preview" : "Live Preview"}
|
|
187
187
|
>
|
|
188
|
-
{showPreview ? <EyeOff className="h-4 w-4" /> : <Eye className="h-4 w-4" />}
|
|
188
|
+
{showPreview ? <EyeOff className="dy-h-4 dy-w-4" /> : <Eye className="dy-h-4 dy-w-4" />}
|
|
189
189
|
</Button>
|
|
190
190
|
)}
|
|
191
191
|
<Button
|
|
192
192
|
size="icon"
|
|
193
|
-
className="h-9 w-9 rounded-lg shadow-sm"
|
|
193
|
+
className="dy-h-9 dy-w-9 dy-rounded-lg dy-shadow-sm"
|
|
194
194
|
onClick={() => document.getElementById('dyrected-form-submit')?.click()}
|
|
195
195
|
disabled={saveMutation.isPending || (isEdit ? !canUpdate : !canCreate)}
|
|
196
196
|
title={isEdit ? "Save Changes (⌘S)" : "Create Entry (⌘S)"}
|
|
197
197
|
>
|
|
198
198
|
{saveMutation.isPending ? (
|
|
199
|
-
<div className="h-4 w-4 animate-spin border-2 border-current border-t-transparent rounded-full" />
|
|
199
|
+
<div className="dy-h-4 dy-w-4 dy-animate-spin dy-border-2 dy-border-current dy-border-t-transparent dy-rounded-full" />
|
|
200
200
|
) : (
|
|
201
|
-
<Save className="h-4 w-4" />
|
|
201
|
+
<Save className="dy-h-4 dy-w-4" />
|
|
202
202
|
)}
|
|
203
203
|
</Button>
|
|
204
204
|
</div>
|
|
205
205
|
</div>
|
|
206
206
|
|
|
207
207
|
{/* Form */}
|
|
208
|
-
<div className="animate-in space-y-8 pb-20">
|
|
208
|
+
<div className="dy-animate-in dy-space-y-8 dy-pb-20">
|
|
209
209
|
{!canUpdate && isEdit && (
|
|
210
|
-
<div className="p-4 rounded-lg bg-amber-50 border border-amber-200 text-amber-800 text-sm flex items-center gap-3">
|
|
211
|
-
<Archive className="h-4 w-4" />
|
|
210
|
+
<div className="dy-p-4 dy-rounded-lg dy-bg-amber-50 dy-border dy-border-amber-200 dy-text-amber-800 dy-text-sm dy-flex dy-items-center dy-gap-3">
|
|
211
|
+
<Archive className="dy-h-4 dy-w-4" />
|
|
212
212
|
You have read-only access to this collection.
|
|
213
213
|
</div>
|
|
214
214
|
)}
|
|
@@ -223,29 +223,29 @@ export function EditEntryPage() {
|
|
|
223
223
|
submitLabel={isEdit ? "Save Changes" : "Create Entry"}
|
|
224
224
|
readOnly={isEdit ? !canUpdate : !canCreate}
|
|
225
225
|
/>
|
|
226
|
-
<button id="dyrected-form-submit" type="submit" className="hidden" />
|
|
226
|
+
<button id="dyrected-form-submit" type="submit" className="dy-hidden" />
|
|
227
227
|
|
|
228
228
|
{/* Document Meta */}
|
|
229
|
-
<div className="pt-8 border-t border-border/40">
|
|
230
|
-
<div className="flex flex-wrap items-center gap-x-8 gap-y-4">
|
|
231
|
-
<div className="space-y-1">
|
|
232
|
-
<p className="text-[10px] font-bold uppercase tracking-wider text-muted-foreground/40 text-nowrap">Document ID</p>
|
|
233
|
-
<code className="text-xs font-mono text-muted-foreground/80 select-all">
|
|
229
|
+
<div className="dy-pt-8 dy-border-t dy-border-border/40">
|
|
230
|
+
<div className="dy-flex dy-flex-wrap dy-items-center dy-gap-x-8 dy-gap-y-4">
|
|
231
|
+
<div className="dy-space-y-1">
|
|
232
|
+
<p className="dy-text-[10px] dy-font-bold dy-uppercase dy-tracking-wider dy-text-muted-foreground/40 dy-text-nowrap">Document ID</p>
|
|
233
|
+
<code className="dy-text-xs dy-font-mono dy-text-muted-foreground/80 dy-select-all">
|
|
234
234
|
{isEdit ? id : "Pending..."}
|
|
235
235
|
</code>
|
|
236
236
|
</div>
|
|
237
237
|
|
|
238
238
|
{isEdit && (
|
|
239
239
|
<>
|
|
240
|
-
<div className="space-y-1">
|
|
241
|
-
<p className="text-[10px] font-bold uppercase tracking-wider text-muted-foreground/40 text-nowrap">Created At</p>
|
|
242
|
-
<p className="text-xs font-medium text-muted-foreground/80">
|
|
240
|
+
<div className="dy-space-y-1">
|
|
241
|
+
<p className="dy-text-[10px] dy-font-bold dy-uppercase dy-tracking-wider dy-text-muted-foreground/40 dy-text-nowrap">Created At</p>
|
|
242
|
+
<p className="dy-text-xs dy-font-medium dy-text-muted-foreground/80">
|
|
243
243
|
{entry?.createdAt ? new Date(entry.createdAt).toLocaleString() : 'N/A'}
|
|
244
244
|
</p>
|
|
245
245
|
</div>
|
|
246
|
-
<div className="space-y-1">
|
|
247
|
-
<p className="text-[10px] font-bold uppercase tracking-wider text-muted-foreground/40 text-nowrap">Last Updated</p>
|
|
248
|
-
<p className="text-xs font-medium text-muted-foreground/80">
|
|
246
|
+
<div className="dy-space-y-1">
|
|
247
|
+
<p className="dy-text-[10px] dy-font-bold dy-uppercase dy-tracking-wider dy-text-muted-foreground/40 dy-text-nowrap">Last Updated</p>
|
|
248
|
+
<p className="dy-text-xs dy-font-medium dy-text-muted-foreground/80">
|
|
249
249
|
{entry?.updatedAt ? new Date(entry.updatedAt).toLocaleString() : 'N/A'}
|
|
250
250
|
</p>
|
|
251
251
|
</div>
|
|
@@ -260,13 +260,13 @@ export function EditEntryPage() {
|
|
|
260
260
|
{/* Right Column: Preview (starts from top) */}
|
|
261
261
|
{previewUrl && (
|
|
262
262
|
<div className={cn(
|
|
263
|
-
"hidden lg:block border-l border-border/50 bg-muted/5 transition-all duration-500 overflow-hidden",
|
|
264
|
-
showPreview ? "flex-1 opacity-100" : "w-0 opacity-0 border-l-0"
|
|
263
|
+
"dy-hidden lg:dy-block dy-border-l dy-border-border/50 dy-bg-muted/5 dy-transition-all dy-duration-500 dy-overflow-hidden",
|
|
264
|
+
showPreview ? "dy-flex-1 dy-opacity-100" : "dy-w-0 dy-opacity-0 dy-border-l-0"
|
|
265
265
|
)}>
|
|
266
266
|
{/* We use negative margins to pull the preview up and out to the shell's padding edges if possible,
|
|
267
267
|
but since we're inside a parent with padding, we'll just make it height-full.
|
|
268
268
|
*/}
|
|
269
|
-
<div className="h-full">
|
|
269
|
+
<div className="dy-h-full">
|
|
270
270
|
<LivePreviewPane
|
|
271
271
|
previewUrl={previewUrl}
|
|
272
272
|
data={previewData || entry}
|
|
@@ -127,7 +127,7 @@ export function CollectionListPage({ slug }: CollectionListPageProps) {
|
|
|
127
127
|
{
|
|
128
128
|
accessorKey: "id",
|
|
129
129
|
header: "ID",
|
|
130
|
-
cell: ({ row }) => <span className="font-mono text-xs">{row.getValue("id")}</span>,
|
|
130
|
+
cell: ({ row }) => <span className="dy-font-mono dy-text-xs">{row.getValue("id")}</span>,
|
|
131
131
|
},
|
|
132
132
|
]
|
|
133
133
|
|
|
@@ -173,9 +173,9 @@ export function CollectionListPage({ slug }: CollectionListPageProps) {
|
|
|
173
173
|
cell: ({ row }) => {
|
|
174
174
|
const date = new Date(row.getValue("updatedAt"))
|
|
175
175
|
return (
|
|
176
|
-
<div className="flex items-center gap-2 text-muted-foreground">
|
|
177
|
-
<Calendar className="h-3 w-3" />
|
|
178
|
-
<span className="text-xs">{date.toLocaleDateString()}</span>
|
|
176
|
+
<div className="dy-flex dy-items-center dy-gap-2 dy-text-muted-foreground">
|
|
177
|
+
<Calendar className="dy-h-3 dy-w-3" />
|
|
178
|
+
<span className="dy-text-xs">{date.toLocaleDateString()}</span>
|
|
179
179
|
</div>
|
|
180
180
|
)
|
|
181
181
|
}
|
|
@@ -189,9 +189,9 @@ export function CollectionListPage({ slug }: CollectionListPageProps) {
|
|
|
189
189
|
return (
|
|
190
190
|
<DropdownMenu>
|
|
191
191
|
<DropdownMenuTrigger asChild>
|
|
192
|
-
<Button variant="ghost" className="h-8 w-8 p-0">
|
|
193
|
-
<span className="sr-only">Open menu</span>
|
|
194
|
-
<MoreHorizontal className="h-4 w-4" />
|
|
192
|
+
<Button variant="ghost" className="dy-h-8 dy-w-8 dy-p-0">
|
|
193
|
+
<span className="dy-sr-only">Open menu</span>
|
|
194
|
+
<MoreHorizontal className="dy-h-4 dy-w-4" />
|
|
195
195
|
</Button>
|
|
196
196
|
</DropdownMenuTrigger>
|
|
197
197
|
<DropdownMenuContent align="end">
|
|
@@ -201,17 +201,17 @@ export function CollectionListPage({ slug }: CollectionListPageProps) {
|
|
|
201
201
|
</DropdownMenuItem>
|
|
202
202
|
<DropdownMenuSeparator />
|
|
203
203
|
<Link to={`/collections/${slug}/edit/${item.id}`}>
|
|
204
|
-
<DropdownMenuItem className="flex gap-2">
|
|
205
|
-
<Pencil className="h-4 w-4" />
|
|
204
|
+
<DropdownMenuItem className="dy-flex dy-gap-2">
|
|
205
|
+
<Pencil className="dy-h-4 dy-w-4" />
|
|
206
206
|
Edit
|
|
207
207
|
</DropdownMenuItem>
|
|
208
208
|
</Link>
|
|
209
209
|
<DropdownMenuItem
|
|
210
|
-
className="flex gap-2 text-destructive focus:text-destructive"
|
|
210
|
+
className="dy-flex dy-gap-2 dy-text-destructive focus:dy-text-destructive"
|
|
211
211
|
onClick={() => handleDelete(item.id)}
|
|
212
212
|
disabled={deleteMutation.isPending}
|
|
213
213
|
>
|
|
214
|
-
<Trash2 className="h-4 w-4" />
|
|
214
|
+
<Trash2 className="dy-h-4 dy-w-4" />
|
|
215
215
|
{deleteMutation.isPending ? "Deleting..." : "Delete"}
|
|
216
216
|
</DropdownMenuItem>
|
|
217
217
|
</DropdownMenuContent>
|
|
@@ -246,8 +246,8 @@ export function CollectionListPage({ slug }: CollectionListPageProps) {
|
|
|
246
246
|
|
|
247
247
|
if (isLoading) {
|
|
248
248
|
return (
|
|
249
|
-
<div className="flex h-[400px] items-center justify-center">
|
|
250
|
-
<div className="animate-spin rounded-full border-4 border-primary border-t-transparent h-8 w-8"></div>
|
|
249
|
+
<div className="dy-flex dy-h-[400px] dy-items-center dy-justify-center">
|
|
250
|
+
<div className="dy-animate-spin dy-rounded-full dy-border-4 dy-border-primary dy-border-t-transparent dy-h-8 dy-w-8"></div>
|
|
251
251
|
</div>
|
|
252
252
|
)
|
|
253
253
|
}
|
|
@@ -258,15 +258,15 @@ export function CollectionListPage({ slug }: CollectionListPageProps) {
|
|
|
258
258
|
|
|
259
259
|
if (slug === "media") {
|
|
260
260
|
return (
|
|
261
|
-
<div className="space-y-8 animate-in">
|
|
261
|
+
<div className="dy-space-y-8 dy-animate-in">
|
|
262
262
|
<PageHeader
|
|
263
263
|
title="Media Library"
|
|
264
264
|
description="Manage your media assets and uploads."
|
|
265
265
|
icon={ImageIcon}
|
|
266
266
|
>
|
|
267
267
|
<Link to={`/collections/${slug}/new`}>
|
|
268
|
-
<Button className="h-8 px-4 text-[11px] rounded-md bg-primary hover:bg-primary/90 shadow-sm transition-all active:scale-95">
|
|
269
|
-
<Plus className="mr-1.5 h-3 w-3" />
|
|
268
|
+
<Button className="dy-h-8 dy-px-4 dy-text-[11px] dy-rounded-md dy-bg-primary hover:dy-bg-primary/90 dy-shadow-sm dy-transition-all active:dy-scale-95">
|
|
269
|
+
<Plus className="dy-mr-1.5 dy-h-3 dy-w-3" />
|
|
270
270
|
Upload New
|
|
271
271
|
</Button>
|
|
272
272
|
</Link>
|
|
@@ -285,28 +285,28 @@ export function CollectionListPage({ slug }: CollectionListPageProps) {
|
|
|
285
285
|
hasPrevPage={hasPrevPage}
|
|
286
286
|
hasNextPage={hasNextPage}
|
|
287
287
|
onPageChange={setPage}
|
|
288
|
-
className="mt-8"
|
|
288
|
+
className="dy-mt-8"
|
|
289
289
|
/>
|
|
290
290
|
</div>
|
|
291
291
|
)
|
|
292
292
|
}
|
|
293
293
|
|
|
294
294
|
return (
|
|
295
|
-
<div className="space-y-8 animate-in">
|
|
295
|
+
<div className="dy-space-y-8 dy-animate-in">
|
|
296
296
|
<PageHeader
|
|
297
297
|
title={schema.labels?.plural || schema.label || schema.slug}
|
|
298
298
|
description={`Manage your ${schema.slug} entries and update content.`}
|
|
299
299
|
icon={Database}
|
|
300
300
|
>
|
|
301
301
|
<Link to={`/collections/${slug}/new`}>
|
|
302
|
-
<Button className="h-8 px-4 text-[11px] rounded-md bg-primary hover:bg-primary/90 shadow-sm transition-all active:scale-95">
|
|
303
|
-
<Plus className="mr-1.5 h-3 w-3" />
|
|
302
|
+
<Button className="dy-h-8 dy-px-4 dy-text-[11px] dy-rounded-md dy-bg-primary hover:dy-bg-primary/90 dy-shadow-sm dy-transition-all active:dy-scale-95">
|
|
303
|
+
<Plus className="dy-mr-1.5 dy-h-3 dy-w-3" />
|
|
304
304
|
Create New
|
|
305
305
|
</Button>
|
|
306
306
|
</Link>
|
|
307
307
|
</PageHeader>
|
|
308
308
|
|
|
309
|
-
<div className="overflow-hidden">
|
|
309
|
+
<div className="dy-overflow-hidden">
|
|
310
310
|
<DataTable
|
|
311
311
|
key={slug}
|
|
312
312
|
columns={columns}
|
|
@@ -320,11 +320,11 @@ export function CollectionListPage({ slug }: CollectionListPageProps) {
|
|
|
320
320
|
<Button
|
|
321
321
|
variant="destructive"
|
|
322
322
|
size="sm"
|
|
323
|
-
className="h-8"
|
|
323
|
+
className="dy-h-8"
|
|
324
324
|
onClick={() => handleBulkDelete(selectedIds)}
|
|
325
325
|
disabled={bulkDeleteMutation.isPending}
|
|
326
326
|
>
|
|
327
|
-
<Trash2 className="h-4 w-4 mr-2" />
|
|
327
|
+
<Trash2 className="dy-h-4 dy-w-4 dy-mr-2" />
|
|
328
328
|
Delete Selected ({selectedIds.length})
|
|
329
329
|
</Button>
|
|
330
330
|
)}
|
|
@@ -26,8 +26,8 @@ export function Dashboard() {
|
|
|
26
26
|
|
|
27
27
|
if (isLoadingSchemas) {
|
|
28
28
|
return (
|
|
29
|
-
<div className="flex items-center justify-center h-64">
|
|
30
|
-
<div className="animate-spin rounded-full h-8 w-8 border-b-2 border-primary"></div>
|
|
29
|
+
<div className="dy-flex dy-items-center dy-justify-center dy-h-64">
|
|
30
|
+
<div className="dy-animate-spin dy-rounded-full dy-h-8 dy-w-8 dy-border-b-2 dy-border-primary"></div>
|
|
31
31
|
</div>
|
|
32
32
|
);
|
|
33
33
|
}
|
|
@@ -35,9 +35,9 @@ export function Dashboard() {
|
|
|
35
35
|
// No schema yet — route to /setup
|
|
36
36
|
if (collections.length === 0 && globals.length === 0) {
|
|
37
37
|
return (
|
|
38
|
-
<div className="flex items-center justify-center h-64">
|
|
39
|
-
<div className="text-center space-y-4">
|
|
40
|
-
<p className="text-muted-foreground">No collections configured yet.</p>
|
|
38
|
+
<div className="dy-flex dy-items-center dy-justify-center dy-h-64">
|
|
39
|
+
<div className="dy-text-center dy-space-y-4">
|
|
40
|
+
<p className="dy-text-muted-foreground">No collections configured yet.</p>
|
|
41
41
|
<Button asChild>
|
|
42
42
|
<Link to="/setup">View Integration Guide</Link>
|
|
43
43
|
</Button>
|
|
@@ -47,72 +47,72 @@ export function Dashboard() {
|
|
|
47
47
|
}
|
|
48
48
|
|
|
49
49
|
return (
|
|
50
|
-
<div className="space-y-8 animate-in fade-in duration-500">
|
|
50
|
+
<div className="dy-space-y-8 dy-animate-in dy-fade-in dy-duration-500">
|
|
51
51
|
<div>
|
|
52
|
-
<h2 className="text-2xl font-semibold tracking-tight">Overview</h2>
|
|
53
|
-
<p className="text-muted-foreground">Monitor and manage your site's content and structure.</p>
|
|
52
|
+
<h2 className="dy-text-2xl dy-font-semibold dy-tracking-tight">Overview</h2>
|
|
53
|
+
<p className="dy-text-muted-foreground">Monitor and manage your site's content and structure.</p>
|
|
54
54
|
</div>
|
|
55
55
|
|
|
56
|
-
<div className="grid gap-6 md:grid-cols-2 lg:grid-cols-3">
|
|
57
|
-
<div className="p-1 space-y-2 group border border-card">
|
|
58
|
-
<div className="flex items-center gap-3">
|
|
59
|
-
<div className="rounded-md bg-primary/5 p-1.5 text-primary/60 group-hover:bg-primary/10 group-hover:text-primary transition-colors">
|
|
60
|
-
<Database className="h-4 w-4" />
|
|
56
|
+
<div className="dy-grid dy-gap-6 md:dy-grid-cols-2 lg:dy-grid-cols-3">
|
|
57
|
+
<div className="dy-p-1 dy-space-y-2 dy-group dy-border dy-border-card">
|
|
58
|
+
<div className="dy-flex dy-items-center dy-gap-3">
|
|
59
|
+
<div className="dy-rounded-md dy-bg-primary/5 dy-p-1.5 dy-text-primary/60 dy-group-hover:dy-bg-primary/10 dy-group-hover:dy-text-primary dy-transition-colors">
|
|
60
|
+
<Database className="dy-h-4 dy-w-4" />
|
|
61
61
|
</div>
|
|
62
|
-
<h3 className="text-[10px] font-bold text-muted-foreground/40 uppercase tracking-widest">Collections</h3>
|
|
62
|
+
<h3 className="dy-text-[10px] dy-font-bold dy-text-muted-foreground/40 dy-uppercase dy-tracking-widest">Collections</h3>
|
|
63
63
|
</div>
|
|
64
|
-
<p className="text-3xl font-bold tracking-tight">{collections.length}</p>
|
|
64
|
+
<p className="dy-text-3xl dy-font-bold dy-tracking-tight">{collections.length}</p>
|
|
65
65
|
</div>
|
|
66
66
|
|
|
67
|
-
<div className="p-1 space-y-2 group border border-card">
|
|
68
|
-
<div className="flex items-center gap-3">
|
|
69
|
-
<div className="rounded-md bg-secondary/5 p-1.5 text-muted-foreground/60 group-hover:bg-accent group-hover:text-foreground transition-colors">
|
|
70
|
-
<Globe className="h-4 w-4" />
|
|
67
|
+
<div className="dy-p-1 dy-space-y-2 dy-group dy-border dy-border-card">
|
|
68
|
+
<div className="dy-flex dy-items-center dy-gap-3">
|
|
69
|
+
<div className="dy-rounded-md dy-bg-secondary/5 dy-p-1.5 dy-text-muted-foreground/60 dy-group-hover:dy-bg-accent dy-group-hover:dy-text-foreground dy-transition-colors">
|
|
70
|
+
<Globe className="dy-h-4 dy-w-4" />
|
|
71
71
|
</div>
|
|
72
|
-
<h3 className="text-[10px] font-bold text-muted-foreground/40 uppercase tracking-widest">Global Configs</h3>
|
|
72
|
+
<h3 className="dy-text-[10px] dy-font-bold dy-text-muted-foreground/40 dy-uppercase dy-tracking-widest">Global Configs</h3>
|
|
73
73
|
</div>
|
|
74
|
-
<p className="text-3xl font-bold tracking-tight">{globals.length}</p>
|
|
74
|
+
<p className="dy-text-3xl dy-font-bold dy-tracking-tight">{globals.length}</p>
|
|
75
75
|
</div>
|
|
76
76
|
|
|
77
|
-
<div className="p-1 space-y-2 group border border-card">
|
|
78
|
-
<div className="flex items-center gap-3">
|
|
79
|
-
<div className="rounded-md bg-accent p-1.5 text-muted-foreground/60 group-hover:bg-accent group-hover:text-foreground transition-colors">
|
|
80
|
-
<ImageIcon className="h-4 w-4" />
|
|
77
|
+
<div className="dy-p-1 dy-space-y-2 dy-group dy-border dy-border-card">
|
|
78
|
+
<div className="dy-flex dy-items-center dy-gap-3">
|
|
79
|
+
<div className="dy-rounded-md dy-bg-accent dy-p-1.5 dy-text-muted-foreground/60 dy-group-hover:dy-bg-accent dy-group-hover:dy-text-foreground dy-transition-colors">
|
|
80
|
+
<ImageIcon className="dy-h-4 dy-w-4" />
|
|
81
81
|
</div>
|
|
82
|
-
<h3 className="text-[10px] font-bold text-muted-foreground/40 uppercase tracking-widest">Media Files</h3>
|
|
82
|
+
<h3 className="dy-text-[10px] dy-font-bold dy-text-muted-foreground/40 dy-uppercase dy-tracking-widest">Media Files</h3>
|
|
83
83
|
</div>
|
|
84
|
-
<p className="text-3xl font-bold tracking-tight">-</p>
|
|
84
|
+
<p className="dy-text-3xl dy-font-bold dy-tracking-tight">-</p>
|
|
85
85
|
</div>
|
|
86
86
|
</div>
|
|
87
87
|
|
|
88
|
-
<div className="grid gap-8 md:grid-cols-2">
|
|
88
|
+
<div className="dy-grid dy-gap-8 md:dy-grid-cols-2">
|
|
89
89
|
<section >
|
|
90
|
-
<div className="flex items-center justify-between mb-4">
|
|
91
|
-
<h3 className="text-lg font-semibold flex items-center gap-2">
|
|
92
|
-
<Database className="h-5 w-5 text-primary" />
|
|
90
|
+
<div className="dy-flex dy-items-center dy-justify-between dy-mb-4">
|
|
91
|
+
<h3 className="dy-text-lg dy-font-semibold dy-flex dy-items-center dy-gap-2">
|
|
92
|
+
<Database className="dy-h-5 dy-w-5 dy-text-primary" />
|
|
93
93
|
Collections
|
|
94
94
|
</h3>
|
|
95
|
-
{/* <Button variant="ghost" size="sm" asChild className="text-xs">
|
|
95
|
+
{/* <Button variant="ghost" size="sm" asChild className="dy-text-xs">
|
|
96
96
|
<Link to="/collections">View All</Link>
|
|
97
97
|
</Button> */}
|
|
98
98
|
</div>
|
|
99
|
-
<div className="space-y-1 border border-card">
|
|
99
|
+
<div className="dy-space-y-1 dy-border dy-border-card">
|
|
100
100
|
{collections.map((col: any, idx: number) => (
|
|
101
101
|
<Link
|
|
102
102
|
key={col.slug}
|
|
103
103
|
to={`/collections/${col.slug}`}
|
|
104
|
-
className="group flex items-center justify-between p-3 rounded-md hover:bg-primary/[0.02] transition-colors"
|
|
104
|
+
className="dy-group dy-flex dy-items-center dy-justify-between dy-p-3 dy-rounded-md hover:dy-bg-primary/[0.02] dy-transition-colors"
|
|
105
105
|
>
|
|
106
106
|
<div>
|
|
107
|
-
<p className="font-medium group-hover:text-primary transition-colors">{col.labels?.plural || col.slug}</p>
|
|
108
|
-
<p className="text-xs text-muted-foreground uppercase">{col.slug}</p>
|
|
107
|
+
<p className="dy-font-medium dy-group-hover:dy-text-primary dy-transition-colors">{col.labels?.plural || col.slug}</p>
|
|
108
|
+
<p className="dy-text-xs dy-text-muted-foreground dy-uppercase">{col.slug}</p>
|
|
109
109
|
</div>
|
|
110
|
-
<div className="flex items-center gap-3">
|
|
111
|
-
<div className="text-right mr-4">
|
|
112
|
-
<p className="text-sm font-semibold">{collectionCounts[idx]?.data?.total || 0}</p>
|
|
113
|
-
<p className="text-[10px] text-muted-foreground uppercase">Entries</p>
|
|
110
|
+
<div className="dy-flex dy-items-center dy-gap-3">
|
|
111
|
+
<div className="dy-text-right dy-mr-4">
|
|
112
|
+
<p className="dy-text-sm dy-font-semibold">{collectionCounts[idx]?.data?.total || 0}</p>
|
|
113
|
+
<p className="dy-text-[10px] dy-text-muted-foreground dy-uppercase">Entries</p>
|
|
114
114
|
</div>
|
|
115
|
-
<ArrowRight className="h-4 w-4 text-muted-foreground group-hover:text-primary transition-transform group-hover:translate-x-0.5" />
|
|
115
|
+
<ArrowRight className="dy-h-4 dy-w-4 dy-text-muted-foreground dy-group-hover:dy-text-primary dy-transition-transform dy-group-hover:dy-translate-x-0.5" />
|
|
116
116
|
</div>
|
|
117
117
|
</Link>
|
|
118
118
|
))}
|
|
@@ -120,24 +120,24 @@ export function Dashboard() {
|
|
|
120
120
|
</section>
|
|
121
121
|
|
|
122
122
|
<section>
|
|
123
|
-
<div className="flex items-center justify-between mb-4">
|
|
124
|
-
<h3 className="text-lg font-semibold flex items-center gap-2">
|
|
125
|
-
<Globe className="h-5 w-5 text-secondary-foreground" />
|
|
123
|
+
<div className="dy-flex dy-items-center dy-justify-between dy-mb-4">
|
|
124
|
+
<h3 className="dy-text-lg dy-font-semibold dy-flex dy-items-center dy-gap-2">
|
|
125
|
+
<Globe className="dy-h-5 dy-w-5 dy-text-secondary-foreground" />
|
|
126
126
|
Global Settings
|
|
127
127
|
</h3>
|
|
128
128
|
</div>
|
|
129
|
-
<div className="space-y-1 border border-card">
|
|
129
|
+
<div className="dy-space-y-1 dy-border dy-border-card">
|
|
130
130
|
{globals.map((glb: any) => (
|
|
131
131
|
<Link
|
|
132
132
|
key={glb.slug}
|
|
133
133
|
to={`/globals/${glb.slug}`}
|
|
134
|
-
className="group flex items-center justify-between p-3 rounded-md hover:bg-primary/[0.02] transition-colors"
|
|
134
|
+
className="dy-group dy-flex dy-items-center dy-justify-between dy-p-3 dy-rounded-md hover:dy-bg-primary/[0.02] dy-transition-colors"
|
|
135
135
|
>
|
|
136
136
|
<div>
|
|
137
|
-
<p className="font-medium group-hover:text-secondary-foreground transition-colors">{glb.label || glb.slug}</p>
|
|
138
|
-
<p className="text-xs text-muted-foreground uppercase">{glb.slug}</p>
|
|
137
|
+
<p className="dy-font-medium dy-group-hover:dy-text-secondary-foreground dy-transition-colors">{glb.label || glb.slug}</p>
|
|
138
|
+
<p className="dy-text-xs dy-text-muted-foreground dy-uppercase">{glb.slug}</p>
|
|
139
139
|
</div>
|
|
140
|
-
<div className="bg-secondary/10 px-2 py-1 rounded text-[10px] font-bold text-secondary-foreground uppercase">
|
|
140
|
+
<div className="dy-bg-secondary/10 dy-px-2 dy-py-1 dy-rounded dy-text-[10px] dy-font-bold dy-text-secondary-foreground dy-uppercase">
|
|
141
141
|
Global
|
|
142
142
|
</div>
|
|
143
143
|
</Link>
|