@actuate-media/cms-admin 0.56.0 → 0.56.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.
- package/CHANGELOG.md +12 -0
- package/dist/__tests__/components/posts-badges.test.js +3 -3
- package/dist/__tests__/components/posts-badges.test.js.map +1 -1
- package/dist/actuate-admin.css +1 -1
- package/dist/components/AICoauthorBubbleMenu.js +2 -2
- package/dist/components/AICoauthorBubbleMenu.js.map +1 -1
- package/dist/components/Breadcrumbs.js +2 -2
- package/dist/components/Breadcrumbs.js.map +1 -1
- package/dist/components/CoauthorResultPopover.d.ts.map +1 -1
- package/dist/components/CoauthorResultPopover.js +1 -1
- package/dist/components/CoauthorResultPopover.js.map +1 -1
- package/dist/components/CommandPalette.d.ts.map +1 -1
- package/dist/components/CommandPalette.js +11 -11
- package/dist/components/CommandPalette.js.map +1 -1
- package/dist/components/CommentSidePanel.js +11 -11
- package/dist/components/CommentSidePanel.js.map +1 -1
- package/dist/components/ContentOverviewChart.js +2 -2
- package/dist/components/ContentOverviewChart.js.map +1 -1
- package/dist/components/FocalPointPicker.js +1 -1
- package/dist/components/FocalPointPicker.js.map +1 -1
- package/dist/components/LivePreview.d.ts.map +1 -1
- package/dist/components/LivePreview.js +5 -5
- package/dist/components/LivePreview.js.map +1 -1
- package/dist/components/LogoPlaceholder.js +1 -1
- package/dist/components/LogoPlaceholder.js.map +1 -1
- package/dist/components/MentionableTextarea.js +3 -3
- package/dist/components/MentionableTextarea.js.map +1 -1
- package/dist/components/NotificationBell.js +1 -1
- package/dist/components/NotificationBell.js.map +1 -1
- package/dist/components/OfflineStatus.js +8 -8
- package/dist/components/OfflineStatus.js.map +1 -1
- package/dist/components/PresenceChips.d.ts.map +1 -1
- package/dist/components/PresenceChips.js +10 -6
- package/dist/components/PresenceChips.js.map +1 -1
- package/dist/components/SEOConfigPanel.d.ts.map +1 -1
- package/dist/components/SEOConfigPanel.js +10 -10
- package/dist/components/SEOConfigPanel.js.map +1 -1
- package/dist/components/SEOPanel.js +12 -12
- package/dist/components/SEOPanel.js.map +1 -1
- package/dist/components/SEOPerformance.d.ts.map +1 -1
- package/dist/components/SEOPerformance.js +3 -3
- package/dist/components/SEOPerformance.js.map +1 -1
- package/dist/components/TipTapEditor.js +6 -6
- package/dist/components/TipTapEditor.js.map +1 -1
- package/dist/components/pages/tag-badges.js +6 -6
- package/dist/components/pages/tag-badges.js.map +1 -1
- package/dist/components/posts/badges.d.ts +0 -4
- package/dist/components/posts/badges.d.ts.map +1 -1
- package/dist/components/posts/badges.js +28 -42
- package/dist/components/posts/badges.js.map +1 -1
- package/dist/components/ui/Badge.js +5 -5
- package/dist/components/ui/Badge.js.map +1 -1
- package/dist/components/ui/Toast.d.ts.map +1 -1
- package/dist/components/ui/Toast.js +4 -4
- package/dist/components/ui/Toast.js.map +1 -1
- package/dist/fields/ComponentBlockField.js +2 -2
- package/dist/fields/ComponentBlockField.js.map +1 -1
- package/dist/fields/FieldRenderer.js +1 -1
- package/dist/fields/FieldRenderer.js.map +1 -1
- package/dist/fields/PropInput.js +1 -1
- package/dist/fields/PropInput.js.map +1 -1
- package/dist/fields/RelationshipField.js +5 -5
- package/dist/fields/RelationshipField.js.map +1 -1
- package/dist/fields/ToggleField.js +1 -1
- package/dist/fields/ToggleField.js.map +1 -1
- package/dist/views/Dashboard.js +5 -5
- package/dist/views/Dashboard.js.map +1 -1
- package/dist/views/DocumentEdit.d.ts.map +1 -1
- package/dist/views/DocumentEdit.js +5 -5
- package/dist/views/DocumentEdit.js.map +1 -1
- package/dist/views/ForgotPassword.d.ts.map +1 -1
- package/dist/views/ForgotPassword.js +3 -2
- package/dist/views/ForgotPassword.js.map +1 -1
- package/dist/views/FormEditor.d.ts.map +1 -1
- package/dist/views/FormEditor.js +5 -5
- package/dist/views/FormEditor.js.map +1 -1
- package/dist/views/Login.d.ts.map +1 -1
- package/dist/views/Login.js +17 -17
- package/dist/views/Login.js.map +1 -1
- package/dist/views/PageEditor.d.ts.map +1 -1
- package/dist/views/PageEditor.js +2 -2
- package/dist/views/PageEditor.js.map +1 -1
- package/dist/views/Pages/PagesListView.js +6 -6
- package/dist/views/Pages/PagesListView.js.map +1 -1
- package/dist/views/Pages.d.ts.map +1 -1
- package/dist/views/Pages.js +16 -19
- package/dist/views/Pages.js.map +1 -1
- package/dist/views/ResetPassword.d.ts.map +1 -1
- package/dist/views/ResetPassword.js +3 -2
- package/dist/views/ResetPassword.js.map +1 -1
- package/dist/views/Settings.js +2 -2
- package/dist/views/Settings.js.map +1 -1
- package/dist/views/SetupWizard.d.ts.map +1 -1
- package/dist/views/SetupWizard.js +6 -5
- package/dist/views/SetupWizard.js.map +1 -1
- package/dist/views/page-builder/DesignScore.js +12 -12
- package/dist/views/page-builder/DesignScore.js.map +1 -1
- package/dist/views/page-builder/SEOPanel.js +9 -9
- package/dist/views/page-builder/SEOPanel.js.map +1 -1
- package/dist/views/page-editor/EditorCanvas.js +1 -1
- package/dist/views/page-editor/EditorCanvas.js.map +1 -1
- package/dist/views/page-editor/EditorTopBar.js +2 -2
- package/dist/views/page-editor/EditorTopBar.js.map +1 -1
- package/dist/views/page-editor/PagePreview.js +1 -1
- package/dist/views/page-editor/PagePreview.js.map +1 -1
- package/dist/views/page-editor/SectionInspector.js +1 -1
- package/dist/views/page-editor/SectionInspector.js.map +1 -1
- package/dist/views/page-editor/SitePreviewFrame.js +1 -1
- package/dist/views/page-editor/SitePreviewFrame.js.map +1 -1
- package/dist/views/page-editor/sections/ArticleBodySection.js +1 -1
- package/dist/views/page-editor/sections/ArticleBodySection.js.map +1 -1
- package/dist/views/page-editor/sections/AuthorBioSection.js +2 -2
- package/dist/views/page-editor/sections/AuthorBioSection.js.map +1 -1
- package/dist/views/page-editor/sections/ByTheNumbersSection.js +1 -1
- package/dist/views/page-editor/sections/ByTheNumbersSection.js.map +1 -1
- package/dist/views/page-editor/sections/CtaBannerSection.js +1 -1
- package/dist/views/page-editor/sections/CtaBannerSection.js.map +1 -1
- package/dist/views/page-editor/sections/EmbedSection.d.ts.map +1 -1
- package/dist/views/page-editor/sections/EmbedSection.js +1 -1
- package/dist/views/page-editor/sections/EmbedSection.js.map +1 -1
- package/dist/views/page-editor/sections/FeatureHighlightSection.d.ts.map +1 -1
- package/dist/views/page-editor/sections/FeatureHighlightSection.js +2 -2
- package/dist/views/page-editor/sections/FeatureHighlightSection.js.map +1 -1
- package/dist/views/page-editor/sections/GallerySection.d.ts.map +1 -1
- package/dist/views/page-editor/sections/GallerySection.js +1 -1
- package/dist/views/page-editor/sections/GallerySection.js.map +1 -1
- package/dist/views/page-editor/sections/HeroBannerSection.js +1 -1
- package/dist/views/page-editor/sections/HeroBannerSection.js.map +1 -1
- package/dist/views/page-editor/sections/MissionSection.d.ts.map +1 -1
- package/dist/views/page-editor/sections/MissionSection.js +1 -1
- package/dist/views/page-editor/sections/MissionSection.js.map +1 -1
- package/dist/views/page-editor/sections/PullQuoteSection.js +1 -1
- package/dist/views/page-editor/sections/PullQuoteSection.js.map +1 -1
- package/dist/views/page-editor/sections/RelatedPostsSection.js +1 -1
- package/dist/views/page-editor/sections/RelatedPostsSection.js.map +1 -1
- package/dist/views/page-editor/sections/SectionRenderer.js +1 -1
- package/dist/views/page-editor/sections/SectionRenderer.js.map +1 -1
- package/dist/views/page-editor/sections/parts.js +6 -6
- package/dist/views/page-editor/sections/parts.js.map +1 -1
- package/dist/views/post-editor/PostEditorCanvas.js +2 -2
- package/dist/views/post-editor/PostEditorCanvas.js.map +1 -1
- package/dist/views/post-editor/PostHeader.js +2 -2
- package/dist/views/post-editor/PostHeader.js.map +1 -1
- package/dist/views/post-editor/PostHeaderPanel.js +1 -1
- package/dist/views/post-editor/PostHeaderPanel.js.map +1 -1
- package/dist/views/post-editor/PostPreview.js +1 -1
- package/dist/views/post-editor/PostPreview.js.map +1 -1
- package/dist/views/profile/AccountSecurity.js +1 -1
- package/dist/views/profile/AccountSecurity.js.map +1 -1
- package/dist/views/settings/components.js +1 -1
- package/dist/views/settings/components.js.map +1 -1
- package/package.json +2 -2
- package/src/__tests__/components/posts-badges.test.tsx +3 -3
- package/src/components/AICoauthorBubbleMenu.tsx +4 -4
- package/src/components/Breadcrumbs.tsx +5 -5
- package/src/components/CoauthorResultPopover.tsx +26 -23
- package/src/components/CommandPalette.tsx +41 -39
- package/src/components/CommentSidePanel.tsx +20 -20
- package/src/components/ContentOverviewChart.tsx +4 -4
- package/src/components/FocalPointPicker.tsx +2 -2
- package/src/components/LivePreview.tsx +20 -17
- package/src/components/LogoPlaceholder.tsx +1 -1
- package/src/components/MentionableTextarea.tsx +5 -5
- package/src/components/NotificationBell.tsx +10 -10
- package/src/components/OfflineStatus.tsx +8 -8
- package/src/components/PresenceChips.tsx +12 -8
- package/src/components/SEOConfigPanel.tsx +40 -38
- package/src/components/SEOPanel.tsx +15 -15
- package/src/components/SEOPerformance.tsx +25 -23
- package/src/components/TipTapEditor.tsx +7 -7
- package/src/components/pages/tag-badges.tsx +6 -6
- package/src/components/posts/badges.tsx +28 -46
- package/src/components/ui/Badge.tsx +5 -5
- package/src/components/ui/Toast.tsx +4 -5
- package/src/fields/ComponentBlockField.tsx +2 -2
- package/src/fields/FieldRenderer.tsx +1 -1
- package/src/fields/PropInput.tsx +1 -1
- package/src/fields/RelationshipField.tsx +5 -5
- package/src/fields/ToggleField.tsx +1 -1
- package/src/views/Dashboard.tsx +5 -5
- package/src/views/DocumentEdit.tsx +13 -11
- package/src/views/ForgotPassword.tsx +21 -18
- package/src/views/FormEditor.tsx +74 -69
- package/src/views/Login.tsx +45 -39
- package/src/views/PageEditor.tsx +26 -22
- package/src/views/Pages/PagesListView.tsx +6 -6
- package/src/views/Pages.tsx +64 -65
- package/src/views/ResetPassword.tsx +32 -29
- package/src/views/Settings.tsx +2 -2
- package/src/views/SetupWizard.tsx +42 -33
- package/src/views/page-builder/DesignScore.tsx +12 -12
- package/src/views/page-builder/SEOPanel.tsx +12 -12
- package/src/views/page-editor/EditorCanvas.tsx +1 -1
- package/src/views/page-editor/EditorTopBar.tsx +2 -2
- package/src/views/page-editor/PagePreview.tsx +1 -1
- package/src/views/page-editor/SectionInspector.tsx +1 -1
- package/src/views/page-editor/SitePreviewFrame.tsx +1 -1
- package/src/views/page-editor/sections/ArticleBodySection.tsx +5 -5
- package/src/views/page-editor/sections/AuthorBioSection.tsx +6 -6
- package/src/views/page-editor/sections/ByTheNumbersSection.tsx +5 -5
- package/src/views/page-editor/sections/CtaBannerSection.tsx +1 -1
- package/src/views/page-editor/sections/EmbedSection.tsx +6 -4
- package/src/views/page-editor/sections/FeatureHighlightSection.tsx +7 -5
- package/src/views/page-editor/sections/GallerySection.tsx +6 -4
- package/src/views/page-editor/sections/HeroBannerSection.tsx +2 -2
- package/src/views/page-editor/sections/MissionSection.tsx +4 -2
- package/src/views/page-editor/sections/PullQuoteSection.tsx +4 -4
- package/src/views/page-editor/sections/RelatedPostsSection.tsx +5 -5
- package/src/views/page-editor/sections/SectionRenderer.tsx +2 -2
- package/src/views/page-editor/sections/parts.tsx +6 -6
- package/src/views/post-editor/PostEditorCanvas.tsx +4 -4
- package/src/views/post-editor/PostHeader.tsx +5 -5
- package/src/views/post-editor/PostHeaderPanel.tsx +1 -1
- package/src/views/post-editor/PostPreview.tsx +1 -1
- package/src/views/profile/AccountSecurity.tsx +1 -1
- package/src/views/settings/components.tsx +1 -1
|
@@ -8,6 +8,9 @@ export interface ForgotPasswordProps {
|
|
|
8
8
|
onNavigate: (path: string) => void
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
+
const fieldClass =
|
|
12
|
+
'w-full rounded-lg border border-border bg-input-background px-3 py-2.5 text-sm text-foreground focus-visible:border-ring focus-visible:ring-2 focus-visible:ring-ring/50 focus-visible:outline-none'
|
|
13
|
+
|
|
11
14
|
export function ForgotPassword({ onNavigate }: ForgotPasswordProps) {
|
|
12
15
|
const [email, setEmail] = useState('')
|
|
13
16
|
const [submitting, setSubmitting] = useState(false)
|
|
@@ -42,37 +45,37 @@ export function ForgotPassword({ onNavigate }: ForgotPasswordProps) {
|
|
|
42
45
|
}
|
|
43
46
|
|
|
44
47
|
return (
|
|
45
|
-
<div className="flex min-h-screen items-center justify-center
|
|
48
|
+
<div className="bg-muted flex min-h-screen items-center justify-center px-4">
|
|
46
49
|
<div className="w-full max-w-md">
|
|
47
50
|
<div className="mb-8 text-center">
|
|
48
|
-
<div className="mx-auto mb-4 flex h-14 w-14 items-center justify-center rounded-xl
|
|
49
|
-
<Shield className="h-7 w-7
|
|
51
|
+
<div className="bg-primary mx-auto mb-4 flex h-14 w-14 items-center justify-center rounded-xl">
|
|
52
|
+
<Shield className="text-primary-foreground h-7 w-7" />
|
|
50
53
|
</div>
|
|
51
|
-
<h1 className="text-2xl font-medium
|
|
52
|
-
<p className="mt-2
|
|
54
|
+
<h1 className="text-foreground text-2xl font-medium">Reset Password</h1>
|
|
55
|
+
<p className="text-muted-foreground mt-2">
|
|
53
56
|
{sent
|
|
54
57
|
? 'Check your inbox for a reset link'
|
|
55
58
|
: "Enter your email and we'll send you a reset link"}
|
|
56
59
|
</p>
|
|
57
60
|
</div>
|
|
58
61
|
|
|
59
|
-
<div className="space-y-5 rounded-xl border
|
|
62
|
+
<div className="border-border bg-card space-y-5 rounded-xl border p-6 shadow-sm">
|
|
60
63
|
{sent ? (
|
|
61
64
|
<div className="space-y-4 text-center">
|
|
62
|
-
<div className="mx-auto flex h-12 w-12 items-center justify-center rounded-full
|
|
63
|
-
<CheckCircle2 className="h-6 w-6
|
|
65
|
+
<div className="bg-success/10 mx-auto flex h-12 w-12 items-center justify-center rounded-full">
|
|
66
|
+
<CheckCircle2 className="text-success h-6 w-6" />
|
|
64
67
|
</div>
|
|
65
|
-
<p className="text-
|
|
68
|
+
<p className="text-muted-foreground text-sm">
|
|
66
69
|
If an account exists for <strong>{email}</strong>, you will receive a password reset
|
|
67
70
|
email shortly.
|
|
68
71
|
</p>
|
|
69
|
-
<p className="text-
|
|
72
|
+
<p className="text-muted-foreground text-xs">
|
|
70
73
|
The link expires in 1 hour. Check your spam folder if you don't see it.
|
|
71
74
|
</p>
|
|
72
75
|
<button
|
|
73
76
|
type="button"
|
|
74
77
|
onClick={() => onNavigate('/login')}
|
|
75
|
-
className="w-full rounded-lg
|
|
78
|
+
className="bg-primary text-primary-foreground hover:bg-primary/90 w-full rounded-lg py-2.5 font-medium transition-colors"
|
|
76
79
|
>
|
|
77
80
|
Back to Sign In
|
|
78
81
|
</button>
|
|
@@ -80,16 +83,16 @@ export function ForgotPassword({ onNavigate }: ForgotPasswordProps) {
|
|
|
80
83
|
) : (
|
|
81
84
|
<form onSubmit={handleSubmit} className="space-y-5">
|
|
82
85
|
{error && (
|
|
83
|
-
<div className="flex items-start gap-3 rounded-lg border
|
|
84
|
-
<AlertTriangle className="mt-0.5 h-5 w-5 shrink-0
|
|
85
|
-
<p className="text-
|
|
86
|
+
<div className="border-destructive/30 bg-destructive/10 flex items-start gap-3 rounded-lg border p-3">
|
|
87
|
+
<AlertTriangle className="text-destructive mt-0.5 h-5 w-5 shrink-0" />
|
|
88
|
+
<p className="text-destructive text-sm">{error}</p>
|
|
86
89
|
</div>
|
|
87
90
|
)}
|
|
88
91
|
|
|
89
92
|
<div>
|
|
90
93
|
<label
|
|
91
94
|
htmlFor="forgot-email"
|
|
92
|
-
className="mb-1.5 block text-sm font-medium
|
|
95
|
+
className="text-foreground mb-1.5 block text-sm font-medium"
|
|
93
96
|
>
|
|
94
97
|
Email Address
|
|
95
98
|
</label>
|
|
@@ -99,7 +102,7 @@ export function ForgotPassword({ onNavigate }: ForgotPasswordProps) {
|
|
|
99
102
|
value={email}
|
|
100
103
|
onChange={(e) => setEmail(e.target.value)}
|
|
101
104
|
placeholder="admin@example.com"
|
|
102
|
-
className=
|
|
105
|
+
className={fieldClass}
|
|
103
106
|
required
|
|
104
107
|
autoFocus
|
|
105
108
|
autoComplete="email"
|
|
@@ -109,7 +112,7 @@ export function ForgotPassword({ onNavigate }: ForgotPasswordProps) {
|
|
|
109
112
|
<button
|
|
110
113
|
type="submit"
|
|
111
114
|
disabled={!canSubmit}
|
|
112
|
-
className="flex w-full items-center justify-center gap-2 rounded-lg
|
|
115
|
+
className="bg-primary text-primary-foreground hover:bg-primary/90 flex w-full items-center justify-center gap-2 rounded-lg py-2.5 font-medium transition-colors disabled:cursor-not-allowed disabled:opacity-50"
|
|
113
116
|
>
|
|
114
117
|
{submitting ? (
|
|
115
118
|
<>
|
|
@@ -127,7 +130,7 @@ export function ForgotPassword({ onNavigate }: ForgotPasswordProps) {
|
|
|
127
130
|
<button
|
|
128
131
|
type="button"
|
|
129
132
|
onClick={() => onNavigate('/login')}
|
|
130
|
-
className="flex w-full items-center justify-center gap-2 text-sm
|
|
133
|
+
className="text-muted-foreground hover:text-foreground flex w-full items-center justify-center gap-2 text-sm transition-colors"
|
|
131
134
|
>
|
|
132
135
|
<ArrowLeft className="h-4 w-4" />
|
|
133
136
|
Back to Sign In
|
package/src/views/FormEditor.tsx
CHANGED
|
@@ -175,7 +175,7 @@ export function FormEditor({ formId, onNavigate }: FormEditorProps) {
|
|
|
175
175
|
if (loading) {
|
|
176
176
|
return (
|
|
177
177
|
<div className="flex h-64 items-center justify-center p-4">
|
|
178
|
-
<Loader2 className="h-6 w-6 animate-spin
|
|
178
|
+
<Loader2 className="text-primary h-6 w-6 animate-spin" />
|
|
179
179
|
</div>
|
|
180
180
|
)
|
|
181
181
|
}
|
|
@@ -186,17 +186,19 @@ export function FormEditor({ formId, onNavigate }: FormEditorProps) {
|
|
|
186
186
|
<div className="mb-6 flex items-center gap-3">
|
|
187
187
|
<button
|
|
188
188
|
onClick={() => onNavigate?.('/forms')}
|
|
189
|
-
className="rounded-lg p-2 transition-colors
|
|
189
|
+
className="hover:bg-muted rounded-lg p-2 transition-colors"
|
|
190
190
|
>
|
|
191
|
-
<ArrowLeft className="h-5 w-5
|
|
191
|
+
<ArrowLeft className="text-muted-foreground h-5 w-5" />
|
|
192
192
|
</button>
|
|
193
193
|
<div className="flex-1">
|
|
194
|
-
<h1 className="text-xl font-medium
|
|
194
|
+
<h1 className="text-foreground text-xl font-medium">
|
|
195
|
+
{isNew ? 'New Form' : 'Edit Form'}
|
|
196
|
+
</h1>
|
|
195
197
|
</div>
|
|
196
198
|
<button
|
|
197
199
|
onClick={handleSave}
|
|
198
200
|
disabled={saving || !name.trim()}
|
|
199
|
-
className="flex items-center gap-2 rounded-lg
|
|
201
|
+
className="bg-primary text-primary-foreground hover:bg-primary/90 flex items-center gap-2 rounded-lg px-4 py-2 text-sm transition-colors disabled:opacity-50"
|
|
200
202
|
>
|
|
201
203
|
{saving ? <Loader2 className="h-4 w-4 animate-spin" /> : <Save className="h-4 w-4" />}
|
|
202
204
|
{saving ? 'Saving...' : 'Save'}
|
|
@@ -204,34 +206,34 @@ export function FormEditor({ formId, onNavigate }: FormEditorProps) {
|
|
|
204
206
|
</div>
|
|
205
207
|
|
|
206
208
|
{/* Basic info */}
|
|
207
|
-
<div className="mb-4 rounded-lg border
|
|
209
|
+
<div className="border-border bg-card mb-4 rounded-lg border p-4">
|
|
208
210
|
<div className="grid gap-4">
|
|
209
211
|
<div>
|
|
210
|
-
<label className="mb-1 block text-sm font-medium
|
|
212
|
+
<label className="text-foreground mb-1 block text-sm font-medium">Form Name</label>
|
|
211
213
|
<input
|
|
212
214
|
type="text"
|
|
213
215
|
value={name}
|
|
214
216
|
onChange={(e) => setName(e.target.value)}
|
|
215
217
|
placeholder="e.g. Contact Form"
|
|
216
|
-
className="w-full rounded-lg border
|
|
218
|
+
className="border-border focus-visible:ring-ring/50 w-full rounded-lg border px-3 py-2 text-sm focus:ring-2 focus:outline-none"
|
|
217
219
|
/>
|
|
218
220
|
</div>
|
|
219
221
|
<div>
|
|
220
|
-
<label className="mb-1 block text-sm font-medium
|
|
222
|
+
<label className="text-foreground mb-1 block text-sm font-medium">Description</label>
|
|
221
223
|
<input
|
|
222
224
|
type="text"
|
|
223
225
|
value={description}
|
|
224
226
|
onChange={(e) => setDescription(e.target.value)}
|
|
225
227
|
placeholder="Brief description of this form"
|
|
226
|
-
className="w-full rounded-lg border
|
|
228
|
+
className="border-border focus-visible:ring-ring/50 w-full rounded-lg border px-3 py-2 text-sm focus:ring-2 focus:outline-none"
|
|
227
229
|
/>
|
|
228
230
|
</div>
|
|
229
231
|
<div>
|
|
230
|
-
<label className="mb-1 block text-sm font-medium
|
|
232
|
+
<label className="text-foreground mb-1 block text-sm font-medium">Status</label>
|
|
231
233
|
<select
|
|
232
234
|
value={status}
|
|
233
235
|
onChange={(e) => setStatus(e.target.value)}
|
|
234
|
-
className="rounded-lg border
|
|
236
|
+
className="border-border focus-visible:ring-ring/50 rounded-lg border px-3 py-2 text-sm focus:ring-2 focus:outline-none"
|
|
235
237
|
>
|
|
236
238
|
<option value="active">Active</option>
|
|
237
239
|
<option value="inactive">Inactive</option>
|
|
@@ -241,10 +243,10 @@ export function FormEditor({ formId, onNavigate }: FormEditorProps) {
|
|
|
241
243
|
</div>
|
|
242
244
|
|
|
243
245
|
{/* Fields section */}
|
|
244
|
-
<div className="mb-4 rounded-lg border
|
|
246
|
+
<div className="border-border bg-card mb-4 rounded-lg border">
|
|
245
247
|
<button
|
|
246
248
|
onClick={() => toggleSection('fields')}
|
|
247
|
-
className="flex w-full items-center justify-between p-4 transition-colors
|
|
249
|
+
className="hover:bg-muted flex w-full items-center justify-between p-4 transition-colors"
|
|
248
250
|
>
|
|
249
251
|
<div className="flex items-center gap-2">
|
|
250
252
|
{expandedSection === 'fields' ? (
|
|
@@ -252,18 +254,18 @@ export function FormEditor({ formId, onNavigate }: FormEditorProps) {
|
|
|
252
254
|
) : (
|
|
253
255
|
<ChevronRight className="h-4 w-4" />
|
|
254
256
|
)}
|
|
255
|
-
<span className="font-medium
|
|
256
|
-
<span className="text-
|
|
257
|
+
<span className="text-foreground font-medium">Form Fields</span>
|
|
258
|
+
<span className="text-muted-foreground text-sm">({fields.length})</span>
|
|
257
259
|
</div>
|
|
258
260
|
</button>
|
|
259
261
|
{expandedSection === 'fields' && (
|
|
260
|
-
<div className="border-
|
|
262
|
+
<div className="border-border border-t p-4">
|
|
261
263
|
<div className="mb-4 flex flex-wrap gap-2">
|
|
262
264
|
{FIELD_TYPES.map((ft) => (
|
|
263
265
|
<button
|
|
264
266
|
key={ft.value}
|
|
265
267
|
onClick={() => addField(ft.value)}
|
|
266
|
-
className="flex items-center gap-1 rounded-lg border
|
|
268
|
+
className="border-border hover:bg-muted flex items-center gap-1 rounded-lg border px-3 py-1.5 text-xs transition-colors"
|
|
267
269
|
>
|
|
268
270
|
<Plus className="h-3 w-3" /> {ft.label}
|
|
269
271
|
</button>
|
|
@@ -271,7 +273,7 @@ export function FormEditor({ formId, onNavigate }: FormEditorProps) {
|
|
|
271
273
|
</div>
|
|
272
274
|
|
|
273
275
|
{fields.length === 0 ? (
|
|
274
|
-
<p className="py-6 text-center text-sm
|
|
276
|
+
<p className="text-muted-foreground py-6 text-center text-sm">
|
|
275
277
|
Click a field type above to add it to your form.
|
|
276
278
|
</p>
|
|
277
279
|
) : (
|
|
@@ -286,19 +288,19 @@ export function FormEditor({ formId, onNavigate }: FormEditorProps) {
|
|
|
286
288
|
const from = Number(e.dataTransfer.getData('text/plain'))
|
|
287
289
|
moveField(from, index)
|
|
288
290
|
}}
|
|
289
|
-
className="flex items-center gap-3 rounded-lg border
|
|
291
|
+
className="border-border bg-muted hover:bg-card flex items-center gap-3 rounded-lg border p-3 transition-colors"
|
|
290
292
|
>
|
|
291
|
-
<GripVertical className="h-4 w-4 shrink-0 cursor-grab
|
|
293
|
+
<GripVertical className="text-muted-foreground h-4 w-4 shrink-0 cursor-grab" />
|
|
292
294
|
<input
|
|
293
295
|
type="text"
|
|
294
296
|
value={field.label}
|
|
295
297
|
onChange={(e) => updateField(field.id, { label: e.target.value })}
|
|
296
|
-
className="flex-1 rounded border
|
|
298
|
+
className="border-border focus-visible:ring-ring/50 flex-1 rounded border px-2 py-1 text-sm focus:ring-1 focus:outline-none"
|
|
297
299
|
/>
|
|
298
|
-
<span className="shrink-0 rounded
|
|
300
|
+
<span className="bg-muted text-muted-foreground shrink-0 rounded px-2 py-0.5 text-xs">
|
|
299
301
|
{field.type}
|
|
300
302
|
</span>
|
|
301
|
-
<label className="flex shrink-0 items-center gap-1 text-xs
|
|
303
|
+
<label className="text-muted-foreground flex shrink-0 items-center gap-1 text-xs">
|
|
302
304
|
<input
|
|
303
305
|
type="checkbox"
|
|
304
306
|
checked={field.required}
|
|
@@ -309,7 +311,7 @@ export function FormEditor({ formId, onNavigate }: FormEditorProps) {
|
|
|
309
311
|
</label>
|
|
310
312
|
<button
|
|
311
313
|
onClick={() => removeField(field.id)}
|
|
312
|
-
className="shrink-0 rounded p-1
|
|
314
|
+
className="text-destructive hover:bg-destructive/10 shrink-0 rounded p-1 transition-colors"
|
|
313
315
|
>
|
|
314
316
|
<Trash2 className="h-4 w-4" />
|
|
315
317
|
</button>
|
|
@@ -322,10 +324,10 @@ export function FormEditor({ formId, onNavigate }: FormEditorProps) {
|
|
|
322
324
|
</div>
|
|
323
325
|
|
|
324
326
|
{/* Confirmation section */}
|
|
325
|
-
<div className="mb-4 rounded-lg border
|
|
327
|
+
<div className="border-border bg-card mb-4 rounded-lg border">
|
|
326
328
|
<button
|
|
327
329
|
onClick={() => toggleSection('confirmation')}
|
|
328
|
-
className="flex w-full items-center justify-between p-4 transition-colors
|
|
330
|
+
className="hover:bg-muted flex w-full items-center justify-between p-4 transition-colors"
|
|
329
331
|
>
|
|
330
332
|
<div className="flex items-center gap-2">
|
|
331
333
|
{expandedSection === 'confirmation' ? (
|
|
@@ -333,22 +335,22 @@ export function FormEditor({ formId, onNavigate }: FormEditorProps) {
|
|
|
333
335
|
) : (
|
|
334
336
|
<ChevronRight className="h-4 w-4" />
|
|
335
337
|
)}
|
|
336
|
-
<MessageSquare className="h-4 w-4
|
|
337
|
-
<span className="font-medium
|
|
338
|
-
<span className="
|
|
338
|
+
<MessageSquare className="text-success h-4 w-4" />
|
|
339
|
+
<span className="text-foreground font-medium">Confirmation</span>
|
|
340
|
+
<span className="bg-muted text-muted-foreground rounded px-2 py-0.5 text-xs">
|
|
339
341
|
{confirmation.type === 'message' ? 'Show Message' : 'Redirect'}
|
|
340
342
|
</span>
|
|
341
343
|
</div>
|
|
342
344
|
</button>
|
|
343
345
|
{expandedSection === 'confirmation' && (
|
|
344
|
-
<div className="border-
|
|
346
|
+
<div className="border-border border-t p-4">
|
|
345
347
|
<div className="mb-4">
|
|
346
|
-
<label className="mb-2 block text-sm font-medium
|
|
348
|
+
<label className="text-foreground mb-2 block text-sm font-medium">
|
|
347
349
|
After submission
|
|
348
350
|
</label>
|
|
349
351
|
<div className="flex gap-3">
|
|
350
352
|
<label
|
|
351
|
-
className="flex cursor-pointer items-center gap-2 rounded-lg border px-4 py-2 transition-colors
|
|
353
|
+
className="hover:bg-muted flex cursor-pointer items-center gap-2 rounded-lg border px-4 py-2 transition-colors"
|
|
352
354
|
style={{
|
|
353
355
|
borderColor: confirmation.type === 'message' ? '#2563eb' : '#d1d5db',
|
|
354
356
|
backgroundColor: confirmation.type === 'message' ? '#eff6ff' : 'transparent',
|
|
@@ -360,13 +362,13 @@ export function FormEditor({ formId, onNavigate }: FormEditorProps) {
|
|
|
360
362
|
value="message"
|
|
361
363
|
checked={confirmation.type === 'message'}
|
|
362
364
|
onChange={() => setConfirmation((c) => ({ ...c, type: 'message' }))}
|
|
363
|
-
className="text-
|
|
365
|
+
className="text-primary"
|
|
364
366
|
/>
|
|
365
367
|
<MessageSquare className="h-4 w-4" />
|
|
366
368
|
<span className="text-sm">Show Message</span>
|
|
367
369
|
</label>
|
|
368
370
|
<label
|
|
369
|
-
className="flex cursor-pointer items-center gap-2 rounded-lg border px-4 py-2 transition-colors
|
|
371
|
+
className="hover:bg-muted flex cursor-pointer items-center gap-2 rounded-lg border px-4 py-2 transition-colors"
|
|
370
372
|
style={{
|
|
371
373
|
borderColor: confirmation.type === 'redirect' ? '#2563eb' : '#d1d5db',
|
|
372
374
|
backgroundColor: confirmation.type === 'redirect' ? '#eff6ff' : 'transparent',
|
|
@@ -378,7 +380,7 @@ export function FormEditor({ formId, onNavigate }: FormEditorProps) {
|
|
|
378
380
|
value="redirect"
|
|
379
381
|
checked={confirmation.type === 'redirect'}
|
|
380
382
|
onChange={() => setConfirmation((c) => ({ ...c, type: 'redirect' }))}
|
|
381
|
-
className="text-
|
|
383
|
+
className="text-primary"
|
|
382
384
|
/>
|
|
383
385
|
<ExternalLink className="h-4 w-4" />
|
|
384
386
|
<span className="text-sm">Redirect to Page</span>
|
|
@@ -388,21 +390,21 @@ export function FormEditor({ formId, onNavigate }: FormEditorProps) {
|
|
|
388
390
|
|
|
389
391
|
{confirmation.type === 'message' ? (
|
|
390
392
|
<div>
|
|
391
|
-
<label className="mb-1 block text-sm font-medium
|
|
393
|
+
<label className="text-foreground mb-1 block text-sm font-medium">
|
|
392
394
|
Success Message
|
|
393
395
|
</label>
|
|
394
396
|
<textarea
|
|
395
397
|
value={confirmation.message}
|
|
396
398
|
onChange={(e) => setConfirmation((c) => ({ ...c, message: e.target.value }))}
|
|
397
399
|
rows={3}
|
|
398
|
-
className="w-full rounded-lg border
|
|
400
|
+
className="border-border focus-visible:ring-ring/50 w-full rounded-lg border px-3 py-2 text-sm focus:ring-2 focus:outline-none"
|
|
399
401
|
placeholder="Thank you! Your submission has been received."
|
|
400
402
|
/>
|
|
401
403
|
</div>
|
|
402
404
|
) : (
|
|
403
405
|
<div className="grid gap-3">
|
|
404
406
|
<div>
|
|
405
|
-
<label className="mb-1 block text-sm font-medium
|
|
407
|
+
<label className="text-foreground mb-1 block text-sm font-medium">
|
|
406
408
|
Redirect URL
|
|
407
409
|
</label>
|
|
408
410
|
<input
|
|
@@ -412,11 +414,11 @@ export function FormEditor({ formId, onNavigate }: FormEditorProps) {
|
|
|
412
414
|
setConfirmation((c) => ({ ...c, redirectUrl: e.target.value }))
|
|
413
415
|
}
|
|
414
416
|
placeholder="https://example.com/thank-you"
|
|
415
|
-
className="w-full rounded-lg border
|
|
417
|
+
className="border-border focus-visible:ring-ring/50 w-full rounded-lg border px-3 py-2 text-sm focus:ring-2 focus:outline-none"
|
|
416
418
|
/>
|
|
417
419
|
</div>
|
|
418
420
|
<div>
|
|
419
|
-
<label className="mb-1 block text-sm font-medium
|
|
421
|
+
<label className="text-foreground mb-1 block text-sm font-medium">
|
|
420
422
|
Redirect Delay (ms)
|
|
421
423
|
</label>
|
|
422
424
|
<input
|
|
@@ -427,9 +429,9 @@ export function FormEditor({ formId, onNavigate }: FormEditorProps) {
|
|
|
427
429
|
}
|
|
428
430
|
min={0}
|
|
429
431
|
step={500}
|
|
430
|
-
className="w-32 rounded-lg border
|
|
432
|
+
className="border-border focus-visible:ring-ring/50 w-32 rounded-lg border px-3 py-2 text-sm focus:ring-2 focus:outline-none"
|
|
431
433
|
/>
|
|
432
|
-
<p className="mt-1 text-xs
|
|
434
|
+
<p className="text-muted-foreground mt-1 text-xs">0 = instant redirect</p>
|
|
433
435
|
</div>
|
|
434
436
|
</div>
|
|
435
437
|
)}
|
|
@@ -438,10 +440,10 @@ export function FormEditor({ formId, onNavigate }: FormEditorProps) {
|
|
|
438
440
|
</div>
|
|
439
441
|
|
|
440
442
|
{/* Analytics section */}
|
|
441
|
-
<div className="mb-4 rounded-lg border
|
|
443
|
+
<div className="border-border bg-card mb-4 rounded-lg border">
|
|
442
444
|
<button
|
|
443
445
|
onClick={() => toggleSection('analytics')}
|
|
444
|
-
className="flex w-full items-center justify-between p-4 transition-colors
|
|
446
|
+
className="hover:bg-muted flex w-full items-center justify-between p-4 transition-colors"
|
|
445
447
|
>
|
|
446
448
|
<div className="flex items-center gap-2">
|
|
447
449
|
{expandedSection === 'analytics' ? (
|
|
@@ -449,17 +451,17 @@ export function FormEditor({ formId, onNavigate }: FormEditorProps) {
|
|
|
449
451
|
) : (
|
|
450
452
|
<ChevronRight className="h-4 w-4" />
|
|
451
453
|
)}
|
|
452
|
-
<BarChart3 className="h-4 w-4
|
|
453
|
-
<span className="font-medium
|
|
454
|
+
<BarChart3 className="text-brand h-4 w-4" />
|
|
455
|
+
<span className="text-foreground font-medium">GA4 Analytics</span>
|
|
454
456
|
<span
|
|
455
|
-
className={`rounded px-2 py-0.5 text-xs ${analytics.enabled ? 'bg-
|
|
457
|
+
className={`rounded px-2 py-0.5 text-xs ${analytics.enabled ? 'bg-success/10 text-success' : 'bg-muted text-muted-foreground'}`}
|
|
456
458
|
>
|
|
457
459
|
{analytics.enabled ? 'Enabled' : 'Disabled'}
|
|
458
460
|
</span>
|
|
459
461
|
</div>
|
|
460
462
|
</button>
|
|
461
463
|
{expandedSection === 'analytics' && (
|
|
462
|
-
<div className="border-
|
|
464
|
+
<div className="border-border border-t p-4">
|
|
463
465
|
<div className="mb-4 flex items-center gap-3">
|
|
464
466
|
<label className="relative inline-flex cursor-pointer items-center">
|
|
465
467
|
<input
|
|
@@ -468,9 +470,9 @@ export function FormEditor({ formId, onNavigate }: FormEditorProps) {
|
|
|
468
470
|
onChange={(e) => setAnalytics((a) => ({ ...a, enabled: e.target.checked }))}
|
|
469
471
|
className="peer sr-only"
|
|
470
472
|
/>
|
|
471
|
-
<div className="
|
|
473
|
+
<div className="bg-muted peer peer-checked:bg-primary peer-focus:ring-ring/50 after:border-border after:bg-card h-5 w-9 rounded-full peer-focus:ring-2 peer-focus:outline-none after:absolute after:top-[2px] after:left-[2px] after:h-4 after:w-4 after:rounded-full after:border after:transition-all after:content-[''] peer-checked:after:translate-x-full peer-checked:after:border-white" />
|
|
472
474
|
</label>
|
|
473
|
-
<span className="text-sm font-medium
|
|
475
|
+
<span className="text-foreground text-sm font-medium">
|
|
474
476
|
Push events to Google Analytics 4
|
|
475
477
|
</span>
|
|
476
478
|
</div>
|
|
@@ -478,25 +480,25 @@ export function FormEditor({ formId, onNavigate }: FormEditorProps) {
|
|
|
478
480
|
{analytics.enabled && (
|
|
479
481
|
<div className="grid gap-4 pl-12">
|
|
480
482
|
<div>
|
|
481
|
-
<label className="mb-1 block text-sm font-medium
|
|
483
|
+
<label className="text-foreground mb-1 block text-sm font-medium">
|
|
482
484
|
GA4 Measurement ID
|
|
483
|
-
<span className="font-normal
|
|
485
|
+
<span className="text-muted-foreground font-normal"> (optional)</span>
|
|
484
486
|
</label>
|
|
485
487
|
<input
|
|
486
488
|
type="text"
|
|
487
489
|
value={analytics.measurementId}
|
|
488
490
|
onChange={(e) => setAnalytics((a) => ({ ...a, measurementId: e.target.value }))}
|
|
489
491
|
placeholder="G-XXXXXXXXXX"
|
|
490
|
-
className="w-64 rounded-lg border
|
|
492
|
+
className="border-border focus-visible:ring-ring/50 w-64 rounded-lg border px-3 py-2 text-sm focus:ring-2 focus:outline-none"
|
|
491
493
|
/>
|
|
492
|
-
<p className="mt-1 text-xs
|
|
494
|
+
<p className="text-muted-foreground mt-1 text-xs">
|
|
493
495
|
Leave blank to use your site's default GA4 tag
|
|
494
496
|
</p>
|
|
495
497
|
</div>
|
|
496
498
|
|
|
497
499
|
<div className="grid grid-cols-2 gap-4">
|
|
498
500
|
<div>
|
|
499
|
-
<label className="mb-1 block text-sm font-medium
|
|
501
|
+
<label className="text-foreground mb-1 block text-sm font-medium">
|
|
500
502
|
Submit Event Name
|
|
501
503
|
</label>
|
|
502
504
|
<input
|
|
@@ -505,11 +507,11 @@ export function FormEditor({ formId, onNavigate }: FormEditorProps) {
|
|
|
505
507
|
onChange={(e) =>
|
|
506
508
|
setAnalytics((a) => ({ ...a, submitEventName: e.target.value }))
|
|
507
509
|
}
|
|
508
|
-
className="w-full rounded-lg border
|
|
510
|
+
className="border-border focus-visible:ring-ring/50 w-full rounded-lg border px-3 py-2 text-sm focus:ring-2 focus:outline-none"
|
|
509
511
|
/>
|
|
510
512
|
</div>
|
|
511
513
|
<div>
|
|
512
|
-
<label className="mb-1 block text-sm font-medium
|
|
514
|
+
<label className="text-foreground mb-1 block text-sm font-medium">
|
|
513
515
|
Start Event Name
|
|
514
516
|
</label>
|
|
515
517
|
<input
|
|
@@ -518,12 +520,12 @@ export function FormEditor({ formId, onNavigate }: FormEditorProps) {
|
|
|
518
520
|
onChange={(e) =>
|
|
519
521
|
setAnalytics((a) => ({ ...a, startEventName: e.target.value }))
|
|
520
522
|
}
|
|
521
|
-
className="w-full rounded-lg border
|
|
523
|
+
className="border-border focus-visible:ring-ring/50 w-full rounded-lg border px-3 py-2 text-sm focus:ring-2 focus:outline-none"
|
|
522
524
|
/>
|
|
523
525
|
</div>
|
|
524
526
|
</div>
|
|
525
527
|
|
|
526
|
-
<div className="border-
|
|
528
|
+
<div className="border-border border-t pt-4">
|
|
527
529
|
<div className="mb-3 flex items-center gap-3">
|
|
528
530
|
<input
|
|
529
531
|
type="checkbox"
|
|
@@ -534,7 +536,10 @@ export function FormEditor({ formId, onNavigate }: FormEditorProps) {
|
|
|
534
536
|
}
|
|
535
537
|
className="rounded"
|
|
536
538
|
/>
|
|
537
|
-
<label
|
|
539
|
+
<label
|
|
540
|
+
htmlFor="trackConversion"
|
|
541
|
+
className="text-foreground text-sm font-medium"
|
|
542
|
+
>
|
|
538
543
|
Track as conversion event
|
|
539
544
|
</label>
|
|
540
545
|
</div>
|
|
@@ -542,7 +547,7 @@ export function FormEditor({ formId, onNavigate }: FormEditorProps) {
|
|
|
542
547
|
{analytics.trackAsConversion && (
|
|
543
548
|
<div className="ml-6 grid grid-cols-2 gap-4">
|
|
544
549
|
<div>
|
|
545
|
-
<label className="mb-1 block text-sm font-medium
|
|
550
|
+
<label className="text-foreground mb-1 block text-sm font-medium">
|
|
546
551
|
Conversion Value
|
|
547
552
|
</label>
|
|
548
553
|
<input
|
|
@@ -553,11 +558,11 @@ export function FormEditor({ formId, onNavigate }: FormEditorProps) {
|
|
|
553
558
|
}
|
|
554
559
|
min={0}
|
|
555
560
|
step={0.01}
|
|
556
|
-
className="w-full rounded-lg border
|
|
561
|
+
className="border-border focus-visible:ring-ring/50 w-full rounded-lg border px-3 py-2 text-sm focus:ring-2 focus:outline-none"
|
|
557
562
|
/>
|
|
558
563
|
</div>
|
|
559
564
|
<div>
|
|
560
|
-
<label className="mb-1 block text-sm font-medium
|
|
565
|
+
<label className="text-foreground mb-1 block text-sm font-medium">
|
|
561
566
|
Currency
|
|
562
567
|
</label>
|
|
563
568
|
<select
|
|
@@ -565,7 +570,7 @@ export function FormEditor({ formId, onNavigate }: FormEditorProps) {
|
|
|
565
570
|
onChange={(e) =>
|
|
566
571
|
setAnalytics((a) => ({ ...a, conversionCurrency: e.target.value }))
|
|
567
572
|
}
|
|
568
|
-
className="w-full rounded-lg border
|
|
573
|
+
className="border-border focus-visible:ring-ring/50 w-full rounded-lg border px-3 py-2 text-sm focus:ring-2 focus:outline-none"
|
|
569
574
|
>
|
|
570
575
|
<option value="USD">USD</option>
|
|
571
576
|
<option value="EUR">EUR</option>
|
|
@@ -578,12 +583,12 @@ export function FormEditor({ formId, onNavigate }: FormEditorProps) {
|
|
|
578
583
|
)}
|
|
579
584
|
</div>
|
|
580
585
|
|
|
581
|
-
<div className="
|
|
582
|
-
<p className="text-
|
|
586
|
+
<div className="border-info/30 bg-info/10 rounded-lg border p-3">
|
|
587
|
+
<p className="text-foreground text-xs">
|
|
583
588
|
<strong>Note:</strong> Your site must have the GA4 snippet or GTM container
|
|
584
589
|
installed. Actuate pushes events via{' '}
|
|
585
|
-
<code className="
|
|
586
|
-
<code className="
|
|
590
|
+
<code className="bg-info/10 rounded px-1">gtag()</code> /
|
|
591
|
+
<code className="bg-info/10 rounded px-1">dataLayer</code> — it does not load
|
|
587
592
|
the GA4 script.
|
|
588
593
|
</p>
|
|
589
594
|
</div>
|