@actuate-media/cms-admin 0.56.0 → 0.57.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 +21 -0
- package/dist/__tests__/components/posts-badges.test.js +3 -3
- package/dist/__tests__/components/posts-badges.test.js.map +1 -1
- package/dist/__tests__/views/ai-settings.render.test.js +34 -0
- package/dist/__tests__/views/ai-settings.render.test.js.map +1 -1
- package/dist/actuate-admin.css +1 -1
- package/dist/components/AICoauthorBubbleMenu.d.ts.map +1 -1
- package/dist/components/AICoauthorBubbleMenu.js +7 -3
- package/dist/components/AICoauthorBubbleMenu.js.map +1 -1
- package/dist/components/BrandVoiceAlignmentBadge.d.ts +6 -0
- package/dist/components/BrandVoiceAlignmentBadge.d.ts.map +1 -0
- package/dist/components/BrandVoiceAlignmentBadge.js +11 -0
- package/dist/components/BrandVoiceAlignmentBadge.js.map +1 -0
- package/dist/components/Breadcrumbs.js +2 -2
- package/dist/components/Breadcrumbs.js.map +1 -1
- package/dist/components/CoauthorResultPopover.d.ts +5 -1
- package/dist/components/CoauthorResultPopover.d.ts.map +1 -1
- package/dist/components/CoauthorResultPopover.js +35 -6
- package/dist/components/CoauthorResultPopover.js.map +1 -1
- package/dist/components/CommandPalette.d.ts.map +1 -1
- package/dist/components/CommandPalette.js +16 -12
- 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/seo/SeoEditorDrawer.d.ts.map +1 -1
- package/dist/components/seo/SeoEditorDrawer.js +43 -2
- package/dist/components/seo/SeoEditorDrawer.js.map +1 -1
- package/dist/components/ui/Badge.d.ts +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/lib/brand-voice-client.d.ts +21 -0
- package/dist/lib/brand-voice-client.d.ts.map +1 -0
- package/dist/lib/brand-voice-client.js +27 -0
- package/dist/lib/brand-voice-client.js.map +1 -0
- package/dist/lib/coauthor-client.d.ts +2 -0
- package/dist/lib/coauthor-client.d.ts.map +1 -1
- package/dist/lib/coauthor-client.js +1 -0
- package/dist/lib/coauthor-client.js.map +1 -1
- package/dist/lib/seo-service.d.ts +12 -0
- package/dist/lib/seo-service.d.ts.map +1 -1
- package/dist/lib/seo-service.js +0 -10
- package/dist/lib/seo-service.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/AISettingsTab.d.ts +3 -1
- package/dist/views/settings/AISettingsTab.d.ts.map +1 -1
- package/dist/views/settings/AISettingsTab.js +2 -2
- package/dist/views/settings/AISettingsTab.js.map +1 -1
- package/dist/views/settings/BrandVoiceCard.d.ts +39 -2
- package/dist/views/settings/BrandVoiceCard.d.ts.map +1 -1
- package/dist/views/settings/BrandVoiceCard.js +215 -3
- package/dist/views/settings/BrandVoiceCard.js.map +1 -1
- package/dist/views/settings/brand-voice/BrandVoiceAlignmentPanel.d.ts +13 -0
- package/dist/views/settings/brand-voice/BrandVoiceAlignmentPanel.d.ts.map +1 -0
- package/dist/views/settings/brand-voice/BrandVoiceAlignmentPanel.js +74 -0
- package/dist/views/settings/brand-voice/BrandVoiceAlignmentPanel.js.map +1 -0
- package/dist/views/settings/brand-voice/BrandVoiceRulesSections.d.ts +7 -0
- package/dist/views/settings/brand-voice/BrandVoiceRulesSections.d.ts.map +1 -0
- package/dist/views/settings/brand-voice/BrandVoiceRulesSections.js +54 -0
- package/dist/views/settings/brand-voice/BrandVoiceRulesSections.js.map +1 -0
- package/dist/views/settings/components.js +1 -1
- package/dist/views/settings/components.js.map +1 -1
- package/dist/views/settings/useAiSettings.d.ts +32 -0
- package/dist/views/settings/useAiSettings.d.ts.map +1 -1
- package/dist/views/settings/useAiSettings.js +85 -3
- package/dist/views/settings/useAiSettings.js.map +1 -1
- package/package.json +2 -2
- package/src/__tests__/components/posts-badges.test.tsx +3 -3
- package/src/__tests__/views/ai-settings.render.test.tsx +50 -0
- package/src/components/AICoauthorBubbleMenu.tsx +16 -4
- package/src/components/BrandVoiceAlignmentBadge.tsx +39 -0
- package/src/components/Breadcrumbs.tsx +5 -5
- package/src/components/CoauthorResultPopover.tsx +88 -27
- package/src/components/CommandPalette.tsx +53 -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/seo/SeoEditorDrawer.tsx +65 -1
- 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/lib/brand-voice-client.ts +38 -0
- package/src/lib/coauthor-client.ts +4 -0
- package/src/lib/seo-service.ts +2 -0
- 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 +3 -3
- 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/AISettingsTab.tsx +13 -2
- package/src/views/settings/BrandVoiceCard.tsx +592 -76
- package/src/views/settings/brand-voice/BrandVoiceAlignmentPanel.tsx +205 -0
- package/src/views/settings/brand-voice/BrandVoiceRulesSections.tsx +321 -0
- package/src/views/settings/components.tsx +1 -1
- package/src/views/settings/useAiSettings.ts +134 -3
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
'use client'
|
|
2
2
|
|
|
3
|
-
import { useEffect, useRef } from 'react'
|
|
4
|
-
import { Check, Copy, Loader2, Sparkles, X } from 'lucide-react'
|
|
3
|
+
import { useEffect, useRef, useState } from 'react'
|
|
4
|
+
import { Check, Copy, Loader2, Sparkles, Wand2, X } from 'lucide-react'
|
|
5
|
+
import type { BrandAlignmentScoreResult } from '@actuate-media/cms-core/brand-voice'
|
|
5
6
|
import type { CoauthorAction, ProofreadChange } from '../lib/coauthor-client.js'
|
|
6
7
|
import { coauthorActionLabel } from '../lib/coauthor-client.js'
|
|
8
|
+
import { fixBrandVoiceContent } from '../lib/brand-voice-client.js'
|
|
9
|
+
import { BrandVoiceAlignmentBadge } from './BrandVoiceAlignmentBadge.js'
|
|
10
|
+
import { toast } from 'sonner'
|
|
7
11
|
|
|
8
12
|
export interface CoauthorResultPopoverProps {
|
|
9
13
|
open: boolean
|
|
@@ -13,6 +17,9 @@ export interface CoauthorResultPopoverProps {
|
|
|
13
17
|
after: string
|
|
14
18
|
error?: string
|
|
15
19
|
changes?: ProofreadChange[]
|
|
20
|
+
brandAlignment?: BrandAlignmentScoreResult
|
|
21
|
+
/** Called when fix-to-brand updates the after text. */
|
|
22
|
+
onAfterChange?: (text: string, alignment?: BrandAlignmentScoreResult) => void
|
|
16
23
|
/** Label for the apply target, e.g. "Apply to editor" or "Replace selection". */
|
|
17
24
|
applyLabel?: string
|
|
18
25
|
onApply: () => void
|
|
@@ -39,12 +46,15 @@ export function CoauthorResultPopover({
|
|
|
39
46
|
after,
|
|
40
47
|
error,
|
|
41
48
|
changes,
|
|
49
|
+
brandAlignment,
|
|
50
|
+
onAfterChange,
|
|
42
51
|
applyLabel,
|
|
43
52
|
onApply,
|
|
44
53
|
onCopy,
|
|
45
54
|
onDiscard,
|
|
46
55
|
}: CoauthorResultPopoverProps) {
|
|
47
56
|
const dialogRef = useRef<HTMLDivElement>(null)
|
|
57
|
+
const [fixing, setFixing] = useState(false)
|
|
48
58
|
|
|
49
59
|
useEffect(() => {
|
|
50
60
|
if (!open) return
|
|
@@ -65,8 +75,35 @@ export function CoauthorResultPopover({
|
|
|
65
75
|
|
|
66
76
|
if (!open) return null
|
|
67
77
|
|
|
68
|
-
const applyDisabled = loading || !!error || after.length === 0
|
|
69
|
-
const copyDisabled = loading || !!error || after.length === 0
|
|
78
|
+
const applyDisabled = loading || fixing || !!error || after.length === 0
|
|
79
|
+
const copyDisabled = loading || fixing || !!error || after.length === 0
|
|
80
|
+
const showFix =
|
|
81
|
+
!loading &&
|
|
82
|
+
!error &&
|
|
83
|
+
after.length > 0 &&
|
|
84
|
+
brandAlignment &&
|
|
85
|
+
brandAlignment.score < 85 &&
|
|
86
|
+
onAfterChange
|
|
87
|
+
|
|
88
|
+
async function handleFix() {
|
|
89
|
+
if (!onAfterChange || !after.trim()) return
|
|
90
|
+
setFixing(true)
|
|
91
|
+
try {
|
|
92
|
+
const res = await fixBrandVoiceContent({ content: after, channel: 'blog' })
|
|
93
|
+
if (!res.ok || !res.result) {
|
|
94
|
+
toast.error(res.error ?? 'Could not fix copy for brand voice.')
|
|
95
|
+
return
|
|
96
|
+
}
|
|
97
|
+
onAfterChange(res.result.text, res.result.afterScore)
|
|
98
|
+
toast.success(
|
|
99
|
+
res.result.usedAi
|
|
100
|
+
? 'Copy revised to match brand voice.'
|
|
101
|
+
: 'Applied brand voice rule fixes.',
|
|
102
|
+
)
|
|
103
|
+
} finally {
|
|
104
|
+
setFixing(false)
|
|
105
|
+
}
|
|
106
|
+
}
|
|
70
107
|
|
|
71
108
|
return (
|
|
72
109
|
<div
|
|
@@ -81,20 +118,23 @@ export function CoauthorResultPopover({
|
|
|
81
118
|
aria-label={`AI ${coauthorActionLabel(action)} result`}
|
|
82
119
|
tabIndex={-1}
|
|
83
120
|
onClick={(e) => e.stopPropagation()}
|
|
84
|
-
className="w-full max-w-2xl rounded-lg
|
|
121
|
+
className="bg-card w-full max-w-2xl rounded-lg shadow-2xl outline-none"
|
|
85
122
|
>
|
|
86
|
-
<div className="flex items-center justify-between border-b
|
|
87
|
-
<div className="flex items-center gap-2 text-sm font-medium
|
|
88
|
-
<Sparkles className="h-4 w-4
|
|
123
|
+
<div className="border-border flex items-center justify-between border-b px-4 py-3">
|
|
124
|
+
<div className="text-foreground flex items-center gap-2 text-sm font-medium">
|
|
125
|
+
<Sparkles className="text-primary h-4 w-4" aria-hidden />
|
|
89
126
|
<span>AI {coauthorActionLabel(action)}</span>
|
|
90
127
|
{loading && (
|
|
91
|
-
<Loader2
|
|
128
|
+
<Loader2
|
|
129
|
+
className="text-muted-foreground ml-1 h-4 w-4 animate-spin"
|
|
130
|
+
aria-label="Loading"
|
|
131
|
+
/>
|
|
92
132
|
)}
|
|
93
133
|
</div>
|
|
94
134
|
<button
|
|
95
135
|
type="button"
|
|
96
136
|
onClick={onDiscard}
|
|
97
|
-
className="
|
|
137
|
+
className="text-muted-foreground hover:bg-accent hover:text-muted-foreground rounded p-1"
|
|
98
138
|
aria-label="Close"
|
|
99
139
|
>
|
|
100
140
|
<X className="h-4 w-4" />
|
|
@@ -105,34 +145,34 @@ export function CoauthorResultPopover({
|
|
|
105
145
|
<section aria-labelledby="coauthor-before">
|
|
106
146
|
<h3
|
|
107
147
|
id="coauthor-before"
|
|
108
|
-
className="mb-2 text-xs font-medium tracking-wide
|
|
148
|
+
className="text-muted-foreground mb-2 text-xs font-medium tracking-wide uppercase"
|
|
109
149
|
>
|
|
110
150
|
Before
|
|
111
151
|
</h3>
|
|
112
|
-
<pre className="max-h-72 overflow-auto rounded border
|
|
152
|
+
<pre className="border-border bg-muted text-foreground max-h-72 overflow-auto rounded border p-3 text-sm whitespace-pre-wrap">
|
|
113
153
|
{before}
|
|
114
154
|
</pre>
|
|
115
155
|
</section>
|
|
116
156
|
<section aria-labelledby="coauthor-after">
|
|
117
157
|
<h3
|
|
118
158
|
id="coauthor-after"
|
|
119
|
-
className="mb-2 text-xs font-medium tracking-wide
|
|
159
|
+
className="text-muted-foreground mb-2 text-xs font-medium tracking-wide uppercase"
|
|
120
160
|
>
|
|
121
161
|
After
|
|
122
162
|
</h3>
|
|
123
163
|
{loading ? (
|
|
124
164
|
<div
|
|
125
|
-
className="flex h-72 items-center justify-center rounded border border-dashed
|
|
165
|
+
className="border-border bg-muted text-muted-foreground flex h-72 items-center justify-center rounded border border-dashed text-sm"
|
|
126
166
|
role="status"
|
|
127
167
|
>
|
|
128
168
|
Thinking…
|
|
129
169
|
</div>
|
|
130
170
|
) : error ? (
|
|
131
|
-
<div className="flex h-72 items-center justify-center rounded border border-dashed
|
|
171
|
+
<div className="border-destructive/30 bg-destructive/10 text-destructive flex h-72 items-center justify-center rounded border border-dashed p-3 text-sm">
|
|
132
172
|
{error}
|
|
133
173
|
</div>
|
|
134
174
|
) : (
|
|
135
|
-
<pre className="max-h-72 overflow-auto rounded border
|
|
175
|
+
<pre className="border-info/30 bg-info/10 text-foreground max-h-72 overflow-auto rounded border p-3 text-sm whitespace-pre-wrap">
|
|
136
176
|
{after}
|
|
137
177
|
</pre>
|
|
138
178
|
)}
|
|
@@ -140,18 +180,18 @@ export function CoauthorResultPopover({
|
|
|
140
180
|
</div>
|
|
141
181
|
|
|
142
182
|
{changes && changes.length > 0 && !loading && !error && (
|
|
143
|
-
<div className="border-
|
|
144
|
-
<h3 className="mb-2 text-xs font-medium tracking-wide
|
|
183
|
+
<div className="border-border border-t px-4 py-3">
|
|
184
|
+
<h3 className="text-muted-foreground mb-2 text-xs font-medium tracking-wide uppercase">
|
|
145
185
|
Changes ({changes.length})
|
|
146
186
|
</h3>
|
|
147
187
|
<ul className="max-h-32 space-y-1 overflow-auto text-xs">
|
|
148
188
|
{changes.map((change, i) => (
|
|
149
|
-
<li key={i} className="flex items-start gap-2 rounded
|
|
150
|
-
<span className="text-
|
|
151
|
-
<span className="text-
|
|
152
|
-
<span className="text-
|
|
189
|
+
<li key={i} className="bg-muted flex items-start gap-2 rounded px-2 py-1">
|
|
190
|
+
<span className="text-destructive line-through">{change.original}</span>
|
|
191
|
+
<span className="text-muted-foreground">→</span>
|
|
192
|
+
<span className="text-success">{change.corrected}</span>
|
|
153
193
|
{change.reason && (
|
|
154
|
-
<span className="ml-auto
|
|
194
|
+
<span className="text-muted-foreground ml-auto italic">{change.reason}</span>
|
|
155
195
|
)}
|
|
156
196
|
</li>
|
|
157
197
|
))}
|
|
@@ -159,11 +199,32 @@ export function CoauthorResultPopover({
|
|
|
159
199
|
</div>
|
|
160
200
|
)}
|
|
161
201
|
|
|
162
|
-
|
|
202
|
+
{brandAlignment && !loading && !error && (
|
|
203
|
+
<div className="border-border flex flex-wrap items-center justify-between gap-3 border-t px-4 py-3">
|
|
204
|
+
<BrandVoiceAlignmentBadge alignment={brandAlignment} />
|
|
205
|
+
{showFix && (
|
|
206
|
+
<button
|
|
207
|
+
type="button"
|
|
208
|
+
onClick={handleFix}
|
|
209
|
+
disabled={fixing}
|
|
210
|
+
className="border-border bg-card text-foreground hover:bg-accent inline-flex items-center gap-1.5 rounded-md border px-3 py-1.5 text-sm disabled:cursor-not-allowed disabled:opacity-50"
|
|
211
|
+
>
|
|
212
|
+
{fixing ? (
|
|
213
|
+
<Loader2 className="h-3.5 w-3.5 animate-spin" aria-hidden />
|
|
214
|
+
) : (
|
|
215
|
+
<Wand2 className="h-3.5 w-3.5" aria-hidden />
|
|
216
|
+
)}
|
|
217
|
+
Fix to match brand voice
|
|
218
|
+
</button>
|
|
219
|
+
)}
|
|
220
|
+
</div>
|
|
221
|
+
)}
|
|
222
|
+
|
|
223
|
+
<div className="border-border bg-muted flex items-center justify-end gap-2 border-t px-4 py-3">
|
|
163
224
|
<button
|
|
164
225
|
type="button"
|
|
165
226
|
onClick={onDiscard}
|
|
166
|
-
className="
|
|
227
|
+
className="border-border bg-card text-foreground hover:bg-accent rounded-md border px-3 py-1.5 text-sm"
|
|
167
228
|
>
|
|
168
229
|
<X className="mr-1.5 inline h-3.5 w-3.5" aria-hidden />
|
|
169
230
|
Discard
|
|
@@ -172,7 +233,7 @@ export function CoauthorResultPopover({
|
|
|
172
233
|
type="button"
|
|
173
234
|
onClick={onCopy}
|
|
174
235
|
disabled={copyDisabled}
|
|
175
|
-
className="
|
|
236
|
+
className="border-border bg-card text-foreground hover:bg-accent rounded-md border px-3 py-1.5 text-sm disabled:cursor-not-allowed disabled:opacity-50"
|
|
176
237
|
>
|
|
177
238
|
<Copy className="mr-1.5 inline h-3.5 w-3.5" aria-hidden />
|
|
178
239
|
Copy
|
|
@@ -181,7 +242,7 @@ export function CoauthorResultPopover({
|
|
|
181
242
|
type="button"
|
|
182
243
|
onClick={onApply}
|
|
183
244
|
disabled={applyDisabled}
|
|
184
|
-
className="
|
|
245
|
+
className="bg-primary hover:bg-primary/90 rounded-md px-3 py-1.5 text-sm font-medium text-white disabled:cursor-not-allowed disabled:opacity-50"
|
|
185
246
|
>
|
|
186
247
|
<Check className="mr-1.5 inline h-3.5 w-3.5" aria-hidden />
|
|
187
248
|
{applyLabel ?? 'Apply'}
|
|
@@ -31,6 +31,7 @@ import {
|
|
|
31
31
|
type CoauthorAction,
|
|
32
32
|
type ProofreadChange,
|
|
33
33
|
} from '../lib/coauthor-client.js'
|
|
34
|
+
import type { BrandAlignmentScoreResult } from '@actuate-media/cms-core/brand-voice'
|
|
34
35
|
import {
|
|
35
36
|
isAiSlashCommandInput,
|
|
36
37
|
orderedAiActions,
|
|
@@ -116,6 +117,7 @@ interface AiResultState {
|
|
|
116
117
|
after: string
|
|
117
118
|
error?: string
|
|
118
119
|
changes?: ProofreadChange[]
|
|
120
|
+
brandAlignment?: BrandAlignmentScoreResult
|
|
119
121
|
/** Editor captured at submission time; null means clipboard-only. */
|
|
120
122
|
target: Editor | null
|
|
121
123
|
}
|
|
@@ -258,6 +260,7 @@ export function CommandPalette({ open, onOpenChange, onNavigate }: CommandPalett
|
|
|
258
260
|
loading: false,
|
|
259
261
|
after: outcome.result.text,
|
|
260
262
|
changes: outcome.result.changes,
|
|
263
|
+
brandAlignment: outcome.result.brandAlignment,
|
|
261
264
|
error: undefined,
|
|
262
265
|
}))
|
|
263
266
|
},
|
|
@@ -294,6 +297,13 @@ export function CommandPalette({ open, onOpenChange, onNavigate }: CommandPalett
|
|
|
294
297
|
}
|
|
295
298
|
}, [aiResult.after])
|
|
296
299
|
|
|
300
|
+
const handleAiAfterChange = useCallback(
|
|
301
|
+
(after: string, brandAlignment?: BrandAlignmentScoreResult) => {
|
|
302
|
+
setAiResult((prev) => ({ ...prev, after, brandAlignment }))
|
|
303
|
+
},
|
|
304
|
+
[],
|
|
305
|
+
)
|
|
306
|
+
|
|
297
307
|
const handleAiDiscard = useCallback(() => {
|
|
298
308
|
setAiResult(INITIAL_AI_RESULT)
|
|
299
309
|
}, [])
|
|
@@ -314,6 +324,8 @@ export function CommandPalette({ open, onOpenChange, onNavigate }: CommandPalett
|
|
|
314
324
|
after={aiResult.after}
|
|
315
325
|
error={aiResult.error}
|
|
316
326
|
changes={aiResult.changes}
|
|
327
|
+
brandAlignment={aiResult.brandAlignment}
|
|
328
|
+
onAfterChange={handleAiAfterChange}
|
|
317
329
|
applyLabel={aiResult.target ? 'Apply to editor' : 'Copy to clipboard'}
|
|
318
330
|
onApply={handleAiApply}
|
|
319
331
|
onCopy={handleAiCopy}
|
|
@@ -340,7 +352,7 @@ export function CommandPalette({ open, onOpenChange, onNavigate }: CommandPalett
|
|
|
340
352
|
onClick={(e) => e.stopPropagation()}
|
|
341
353
|
>
|
|
342
354
|
<Command
|
|
343
|
-
className="w-full overflow-hidden rounded-lg
|
|
355
|
+
className="bg-card w-full overflow-hidden rounded-lg shadow-2xl"
|
|
344
356
|
onKeyDown={(e) => {
|
|
345
357
|
if (e.key === 'Escape') {
|
|
346
358
|
onOpenChange(false)
|
|
@@ -349,30 +361,30 @@ export function CommandPalette({ open, onOpenChange, onNavigate }: CommandPalett
|
|
|
349
361
|
}}
|
|
350
362
|
shouldFilter={!hasQuery}
|
|
351
363
|
>
|
|
352
|
-
<div className="flex items-center border-b
|
|
353
|
-
<Search className="mr-3 h-5 w-5 shrink-0
|
|
364
|
+
<div className="border-border flex items-center border-b px-4">
|
|
365
|
+
<Search className="text-muted-foreground mr-3 h-5 w-5 shrink-0" />
|
|
354
366
|
<Command.Input
|
|
355
367
|
value={search}
|
|
356
368
|
onValueChange={setSearch}
|
|
357
369
|
placeholder="Search, jump to, or type /ai to use the AI co-author…"
|
|
358
|
-
className="w-full bg-transparent py-4 text-base
|
|
370
|
+
className="placeholder:text-muted-foreground w-full bg-transparent py-4 text-base focus:outline-none"
|
|
359
371
|
/>
|
|
360
372
|
{loading && (
|
|
361
|
-
<div className="mr-2 h-4 w-4 shrink-0 animate-spin rounded-full border-2 border-
|
|
373
|
+
<div className="border-border mr-2 h-4 w-4 shrink-0 animate-spin rounded-full border-2 border-t-gray-600" />
|
|
362
374
|
)}
|
|
363
|
-
<kbd className="hidden shrink-0 rounded
|
|
375
|
+
<kbd className="bg-muted text-muted-foreground hidden shrink-0 rounded px-2 py-1 font-mono text-xs sm:inline-block">
|
|
364
376
|
ESC
|
|
365
377
|
</kbd>
|
|
366
378
|
</div>
|
|
367
379
|
|
|
368
380
|
<Command.List className="max-h-[400px] overflow-y-auto p-2">
|
|
369
|
-
<Command.Empty className="py-6 text-center text-sm
|
|
381
|
+
<Command.Empty className="text-muted-foreground py-6 text-center text-sm">
|
|
370
382
|
{loading ? 'Searching...' : 'No results found.'}
|
|
371
383
|
</Command.Empty>
|
|
372
384
|
|
|
373
385
|
{isAiMode && (
|
|
374
386
|
<Command.Group heading="AI co-author" className="px-2 py-2">
|
|
375
|
-
<div className="mb-2 flex items-center gap-1 text-xs font-medium
|
|
387
|
+
<div className="text-muted-foreground mb-2 flex items-center gap-1 text-xs font-medium">
|
|
376
388
|
<Sparkles className="h-3 w-3" aria-hidden /> AI CO-AUTHOR
|
|
377
389
|
</div>
|
|
378
390
|
{aiActions.map((action) => {
|
|
@@ -384,23 +396,23 @@ export function CommandPalette({ open, onOpenChange, onNavigate }: CommandPalett
|
|
|
384
396
|
key={`ai-${action}`}
|
|
385
397
|
value={`ai ${action}`}
|
|
386
398
|
onSelect={() => runSlashAction(action, aiPayload)}
|
|
387
|
-
className="flex cursor-pointer items-center gap-3 rounded-lg px-3 py-2
|
|
399
|
+
className="hover:bg-accent data-[selected=true]:bg-muted flex cursor-pointer items-center gap-3 rounded-lg px-3 py-2"
|
|
388
400
|
>
|
|
389
|
-
<Icon className="h-4 w-4
|
|
401
|
+
<Icon className="text-primary h-4 w-4" />
|
|
390
402
|
<div className="flex min-w-0 flex-col">
|
|
391
403
|
<span className="font-medium">
|
|
392
404
|
{coauthorActionLabel(action)}
|
|
393
405
|
{previewable && (
|
|
394
|
-
<span className="ml-1 font-normal
|
|
406
|
+
<span className="text-muted-foreground ml-1 font-normal">
|
|
395
407
|
“{truncatePreview(aiPayload)}”
|
|
396
408
|
</span>
|
|
397
409
|
)}
|
|
398
410
|
</span>
|
|
399
|
-
<span className="text-
|
|
411
|
+
<span className="text-muted-foreground text-xs">
|
|
400
412
|
{coauthorActionDescription(action)}
|
|
401
413
|
</span>
|
|
402
414
|
</div>
|
|
403
|
-
<kbd className="ml-auto rounded
|
|
415
|
+
<kbd className="bg-muted text-muted-foreground ml-auto rounded px-1.5 py-0.5 font-mono text-[10px]">
|
|
404
416
|
/ai {action}
|
|
405
417
|
</kbd>
|
|
406
418
|
</Command.Item>
|
|
@@ -411,17 +423,19 @@ export function CommandPalette({ open, onOpenChange, onNavigate }: CommandPalett
|
|
|
411
423
|
|
|
412
424
|
{!isAiMode && !hasQuery && recentItems.length > 0 && (
|
|
413
425
|
<Command.Group heading="Recent" className="px-2 py-2">
|
|
414
|
-
<div className="mb-2 text-xs font-medium
|
|
426
|
+
<div className="text-muted-foreground mb-2 text-xs font-medium">RECENT</div>
|
|
415
427
|
{recentItems.map((item) => (
|
|
416
428
|
<Command.Item
|
|
417
429
|
key={`recent-${item.id}`}
|
|
418
430
|
value={`recent ${item.label}`}
|
|
419
431
|
onSelect={() => handleSelect(item.path, item)}
|
|
420
|
-
className="flex cursor-pointer items-center gap-3 rounded-lg px-3 py-2
|
|
432
|
+
className="hover:bg-accent data-[selected=true]:bg-muted flex cursor-pointer items-center gap-3 rounded-lg px-3 py-2"
|
|
421
433
|
>
|
|
422
|
-
<Clock className="h-4 w-4
|
|
434
|
+
<Clock className="text-muted-foreground h-4 w-4" />
|
|
423
435
|
<span>{item.label}</span>
|
|
424
|
-
<span className="ml-auto text-xs
|
|
436
|
+
<span className="text-muted-foreground ml-auto text-xs capitalize">
|
|
437
|
+
{item.type}
|
|
438
|
+
</span>
|
|
425
439
|
</Command.Item>
|
|
426
440
|
))}
|
|
427
441
|
</Command.Group>
|
|
@@ -429,7 +443,7 @@ export function CommandPalette({ open, onOpenChange, onNavigate }: CommandPalett
|
|
|
429
443
|
|
|
430
444
|
{!isAiMode && hasQuery && documents.length > 0 && (
|
|
431
445
|
<Command.Group heading="Documents" className="px-2 py-2">
|
|
432
|
-
<div className="mb-2 text-xs font-medium
|
|
446
|
+
<div className="text-muted-foreground mb-2 text-xs font-medium">DOCUMENTS</div>
|
|
433
447
|
{documents.map((doc) => (
|
|
434
448
|
<Command.Item
|
|
435
449
|
key={`doc-${doc.id}`}
|
|
@@ -442,12 +456,12 @@ export function CommandPalette({ open, onOpenChange, onNavigate }: CommandPalett
|
|
|
442
456
|
type: 'document',
|
|
443
457
|
})
|
|
444
458
|
}
|
|
445
|
-
className="flex cursor-pointer items-center gap-3 rounded-lg px-3 py-2
|
|
459
|
+
className="hover:bg-accent data-[selected=true]:bg-muted flex cursor-pointer items-center gap-3 rounded-lg px-3 py-2"
|
|
446
460
|
>
|
|
447
|
-
<FileText className="h-4 w-4
|
|
461
|
+
<FileText className="text-muted-foreground h-4 w-4" />
|
|
448
462
|
<div className="flex min-w-0 flex-col">
|
|
449
463
|
<span className="truncate">{doc.title ?? doc.slug ?? doc.id}</span>
|
|
450
|
-
<span className="text-
|
|
464
|
+
<span className="text-muted-foreground text-xs">
|
|
451
465
|
{doc.collection} · {doc.status}
|
|
452
466
|
</span>
|
|
453
467
|
</div>
|
|
@@ -458,7 +472,7 @@ export function CommandPalette({ open, onOpenChange, onNavigate }: CommandPalett
|
|
|
458
472
|
|
|
459
473
|
{!isAiMode && hasQuery && media.length > 0 && (
|
|
460
474
|
<Command.Group heading="Media" className="mt-1 px-2 py-2">
|
|
461
|
-
<div className="mb-2 text-xs font-medium
|
|
475
|
+
<div className="text-muted-foreground mb-2 text-xs font-medium">MEDIA</div>
|
|
462
476
|
{media.map((m) => (
|
|
463
477
|
<Command.Item
|
|
464
478
|
key={`media-${m.id}`}
|
|
@@ -471,12 +485,12 @@ export function CommandPalette({ open, onOpenChange, onNavigate }: CommandPalett
|
|
|
471
485
|
type: 'media',
|
|
472
486
|
})
|
|
473
487
|
}
|
|
474
|
-
className="flex cursor-pointer items-center gap-3 rounded-lg px-3 py-2
|
|
488
|
+
className="hover:bg-accent data-[selected=true]:bg-muted flex cursor-pointer items-center gap-3 rounded-lg px-3 py-2"
|
|
475
489
|
>
|
|
476
|
-
<Image className="h-4 w-4
|
|
490
|
+
<Image className="text-muted-foreground h-4 w-4" />
|
|
477
491
|
<div className="flex min-w-0 flex-col">
|
|
478
492
|
<span className="truncate">{m.filename}</span>
|
|
479
|
-
<span className="text-
|
|
493
|
+
<span className="text-muted-foreground text-xs">{m.mimeType}</span>
|
|
480
494
|
</div>
|
|
481
495
|
</Command.Item>
|
|
482
496
|
))}
|
|
@@ -485,7 +499,7 @@ export function CommandPalette({ open, onOpenChange, onNavigate }: CommandPalett
|
|
|
485
499
|
|
|
486
500
|
{!isAiMode && hasQuery && users.length > 0 && (
|
|
487
501
|
<Command.Group heading="Users" className="mt-1 px-2 py-2">
|
|
488
|
-
<div className="mb-2 text-xs font-medium
|
|
502
|
+
<div className="text-muted-foreground mb-2 text-xs font-medium">USERS</div>
|
|
489
503
|
{users.map((u) => (
|
|
490
504
|
<Command.Item
|
|
491
505
|
key={`user-${u.id}`}
|
|
@@ -498,12 +512,12 @@ export function CommandPalette({ open, onOpenChange, onNavigate }: CommandPalett
|
|
|
498
512
|
type: 'user',
|
|
499
513
|
})
|
|
500
514
|
}
|
|
501
|
-
className="flex cursor-pointer items-center gap-3 rounded-lg px-3 py-2
|
|
515
|
+
className="hover:bg-accent data-[selected=true]:bg-muted flex cursor-pointer items-center gap-3 rounded-lg px-3 py-2"
|
|
502
516
|
>
|
|
503
|
-
<Users className="h-4 w-4
|
|
517
|
+
<Users className="text-muted-foreground h-4 w-4" />
|
|
504
518
|
<div className="flex min-w-0 flex-col">
|
|
505
519
|
<span className="truncate">{u.name}</span>
|
|
506
|
-
<span className="text-
|
|
520
|
+
<span className="text-muted-foreground text-xs">
|
|
507
521
|
{u.email} · {u.role}
|
|
508
522
|
</span>
|
|
509
523
|
</div>
|
|
@@ -514,7 +528,7 @@ export function CommandPalette({ open, onOpenChange, onNavigate }: CommandPalett
|
|
|
514
528
|
|
|
515
529
|
{!isAiMode && (!hasQuery || !hasResults) && (
|
|
516
530
|
<Command.Group heading="Navigation" className="px-2 py-2">
|
|
517
|
-
<div className="mb-2 text-xs font-medium
|
|
531
|
+
<div className="text-muted-foreground mb-2 text-xs font-medium">NAVIGATION</div>
|
|
518
532
|
{navigationCommands.map((cmd) => {
|
|
519
533
|
const Icon = cmd.icon
|
|
520
534
|
return (
|
|
@@ -522,9 +536,9 @@ export function CommandPalette({ open, onOpenChange, onNavigate }: CommandPalett
|
|
|
522
536
|
key={cmd.id}
|
|
523
537
|
value={cmd.label}
|
|
524
538
|
onSelect={() => handleSelect(cmd.action)}
|
|
525
|
-
className="flex cursor-pointer items-center gap-3 rounded-lg px-3 py-2
|
|
539
|
+
className="hover:bg-accent data-[selected=true]:bg-muted flex cursor-pointer items-center gap-3 rounded-lg px-3 py-2"
|
|
526
540
|
>
|
|
527
|
-
<Icon className="h-4 w-4
|
|
541
|
+
<Icon className="text-muted-foreground h-4 w-4" />
|
|
528
542
|
<span>{cmd.label}</span>
|
|
529
543
|
</Command.Item>
|
|
530
544
|
)
|
|
@@ -534,7 +548,7 @@ export function CommandPalette({ open, onOpenChange, onNavigate }: CommandPalett
|
|
|
534
548
|
|
|
535
549
|
{!isAiMode && (
|
|
536
550
|
<Command.Group heading="Actions" className="mt-2 px-2 py-2">
|
|
537
|
-
<div className="mb-2 text-xs font-medium
|
|
551
|
+
<div className="text-muted-foreground mb-2 text-xs font-medium">ACTIONS</div>
|
|
538
552
|
{staticActions.map((cmd) => {
|
|
539
553
|
const Icon = cmd.icon
|
|
540
554
|
return (
|
|
@@ -549,9 +563,9 @@ export function CommandPalette({ open, onOpenChange, onNavigate }: CommandPalett
|
|
|
549
563
|
type: 'action',
|
|
550
564
|
})
|
|
551
565
|
}
|
|
552
|
-
className="flex cursor-pointer items-center gap-3 rounded-lg px-3 py-2
|
|
566
|
+
className="hover:bg-accent data-[selected=true]:bg-muted flex cursor-pointer items-center gap-3 rounded-lg px-3 py-2"
|
|
553
567
|
>
|
|
554
|
-
<Icon className="h-4 w-4
|
|
568
|
+
<Icon className="text-muted-foreground h-4 w-4" />
|
|
555
569
|
<span>{cmd.label}</span>
|
|
556
570
|
</Command.Item>
|
|
557
571
|
)
|
|
@@ -560,19 +574,19 @@ export function CommandPalette({ open, onOpenChange, onNavigate }: CommandPalett
|
|
|
560
574
|
)}
|
|
561
575
|
</Command.List>
|
|
562
576
|
|
|
563
|
-
<div className="flex items-center justify-between border-t
|
|
577
|
+
<div className="border-border bg-muted text-muted-foreground flex items-center justify-between border-t px-4 py-3 text-xs">
|
|
564
578
|
<div className="flex items-center gap-4">
|
|
565
579
|
<span className="flex items-center gap-1">
|
|
566
|
-
<kbd className="
|
|
580
|
+
<kbd className="border-border bg-card rounded border px-1.5 py-0.5 text-[10px]">
|
|
567
581
|
↑
|
|
568
582
|
</kbd>
|
|
569
|
-
<kbd className="
|
|
583
|
+
<kbd className="border-border bg-card rounded border px-1.5 py-0.5 text-[10px]">
|
|
570
584
|
↓
|
|
571
585
|
</kbd>
|
|
572
586
|
to navigate
|
|
573
587
|
</span>
|
|
574
588
|
<span className="flex items-center gap-1">
|
|
575
|
-
<kbd className="
|
|
589
|
+
<kbd className="border-border bg-card rounded border px-1.5 py-0.5 text-[10px]">
|
|
576
590
|
↵
|
|
577
591
|
</kbd>
|
|
578
592
|
to select
|