@actuate-media/cms-admin 0.54.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 +30 -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__/lib/page-editor-service.test.js +1 -0
- package/dist/__tests__/lib/page-editor-service.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/lib/seo-service.d.ts +0 -2
- package/dist/lib/seo-service.d.ts.map +1 -1
- 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 +10 -0
- package/dist/views/page-editor/sections/EmbedSection.d.ts.map +1 -0
- package/dist/views/page-editor/sections/EmbedSection.js +24 -0
- package/dist/views/page-editor/sections/EmbedSection.js.map +1 -0
- 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.d.ts.map +1 -1
- package/dist/views/page-editor/sections/SectionRenderer.js +5 -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/seo/TechnicalTab.d.ts.map +1 -1
- package/dist/views/seo/TechnicalTab.js +0 -10
- package/dist/views/seo/TechnicalTab.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/__tests__/lib/page-editor-service.test.ts +1 -0
- 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/lib/seo-service.ts +0 -2
- 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 +43 -0
- 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 +6 -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/seo/TechnicalTab.tsx +0 -10
- package/src/views/settings/components.tsx +1 -1
|
@@ -228,13 +228,13 @@ export function CommentSidePanel({
|
|
|
228
228
|
[api, onError, refresh, activeCommentId, setActive],
|
|
229
229
|
)
|
|
230
230
|
|
|
231
|
-
const wrapperClass = `flex h-full flex-col gap-3 border-l border-
|
|
231
|
+
const wrapperClass = `flex h-full flex-col gap-3 border-l border-border bg-card p-3 ${className ?? ''}`
|
|
232
232
|
|
|
233
233
|
return (
|
|
234
234
|
<aside className={wrapperClass} data-testid="comment-side-panel">
|
|
235
235
|
<header className="flex items-center justify-between">
|
|
236
|
-
<h2 className="text-sm font-medium
|
|
237
|
-
<label className="flex cursor-pointer items-center gap-1 text-xs
|
|
236
|
+
<h2 className="text-foreground text-sm font-medium">Comments</h2>
|
|
237
|
+
<label className="text-muted-foreground flex cursor-pointer items-center gap-1 text-xs">
|
|
238
238
|
<input
|
|
239
239
|
type="checkbox"
|
|
240
240
|
checked={includeResolved}
|
|
@@ -247,7 +247,7 @@ export function CommentSidePanel({
|
|
|
247
247
|
|
|
248
248
|
<section className="flex flex-col gap-1.5">
|
|
249
249
|
<MentionableTextarea
|
|
250
|
-
className="w-full resize-none rounded border
|
|
250
|
+
className="border-border focus-visible:border-ring w-full resize-none rounded border p-2 text-sm focus:outline-none"
|
|
251
251
|
rows={3}
|
|
252
252
|
placeholder="Write a comment… Type @ to mention a teammate."
|
|
253
253
|
value={draft}
|
|
@@ -258,7 +258,7 @@ export function CommentSidePanel({
|
|
|
258
258
|
<div className="flex justify-end">
|
|
259
259
|
<button
|
|
260
260
|
type="button"
|
|
261
|
-
className="
|
|
261
|
+
className="bg-primary hover:bg-info rounded px-3 py-1 text-xs font-medium text-white disabled:opacity-50"
|
|
262
262
|
disabled={!draft.trim()}
|
|
263
263
|
onClick={handleCompose}
|
|
264
264
|
data-testid="comment-submit"
|
|
@@ -270,9 +270,9 @@ export function CommentSidePanel({
|
|
|
270
270
|
|
|
271
271
|
<section className="flex-1 overflow-y-auto" aria-busy={loading} data-testid="comment-list">
|
|
272
272
|
{loading ? (
|
|
273
|
-
<p className="text-
|
|
273
|
+
<p className="text-muted-foreground text-xs">Loading…</p>
|
|
274
274
|
) : threads.length === 0 ? (
|
|
275
|
-
<p className="text-
|
|
275
|
+
<p className="text-muted-foreground text-xs">No comments yet.</p>
|
|
276
276
|
) : (
|
|
277
277
|
<ul className="flex flex-col gap-2">
|
|
278
278
|
{threads.map((thread) => (
|
|
@@ -323,8 +323,8 @@ function CommentThreadView({
|
|
|
323
323
|
mentionSearch,
|
|
324
324
|
}: CommentThreadViewProps): React.JSX.Element {
|
|
325
325
|
const [replyDraft, setReplyDraft] = useState('')
|
|
326
|
-
const cardClass = `rounded border bg-
|
|
327
|
-
isActive ? 'border-yellow-400 ring-1 ring-yellow-300' : 'border-
|
|
326
|
+
const cardClass = `rounded border bg-muted p-2 ${
|
|
327
|
+
isActive ? 'border-yellow-400 ring-1 ring-yellow-300' : 'border-border'
|
|
328
328
|
}`
|
|
329
329
|
|
|
330
330
|
return (
|
|
@@ -344,7 +344,7 @@ function CommentThreadView({
|
|
|
344
344
|
mentionSearch={mentionSearch}
|
|
345
345
|
/>
|
|
346
346
|
{thread.replies.length > 0 && (
|
|
347
|
-
<ul className="mt-2 flex flex-col gap-1 border-l-2
|
|
347
|
+
<ul className="border-border mt-2 flex flex-col gap-1 border-l-2 pl-2">
|
|
348
348
|
{thread.replies.map((reply) => (
|
|
349
349
|
<li key={reply.id}>
|
|
350
350
|
<CommentRow
|
|
@@ -365,7 +365,7 @@ function CommentThreadView({
|
|
|
365
365
|
<div className="mt-2 flex items-start gap-1">
|
|
366
366
|
<div className="flex-1">
|
|
367
367
|
<MentionableTextarea
|
|
368
|
-
className="w-full resize-none rounded border
|
|
368
|
+
className="border-border focus-visible:border-ring w-full resize-none rounded border px-2 py-1 text-xs focus:outline-none"
|
|
369
369
|
placeholder="Reply… Type @ to mention."
|
|
370
370
|
rows={1}
|
|
371
371
|
value={replyDraft}
|
|
@@ -377,7 +377,7 @@ function CommentThreadView({
|
|
|
377
377
|
</div>
|
|
378
378
|
<button
|
|
379
379
|
type="button"
|
|
380
|
-
className="
|
|
380
|
+
className="bg-foreground hover:bg-foreground/90 rounded px-2 py-1 text-xs font-medium text-white disabled:opacity-50"
|
|
381
381
|
disabled={!replyDraft.trim()}
|
|
382
382
|
onClick={(e) => {
|
|
383
383
|
e.stopPropagation()
|
|
@@ -420,7 +420,7 @@ function CommentRow({
|
|
|
420
420
|
|
|
421
421
|
const canMutate = isAdmin || comment.userId === currentUserId
|
|
422
422
|
const meta = (
|
|
423
|
-
<div className="text-
|
|
423
|
+
<div className="text-muted-foreground text-xs">
|
|
424
424
|
{comment.userId ?? 'deleted user'} · {formatRelative(comment.createdAt)}
|
|
425
425
|
{comment.isResolved ? ' · resolved' : null}
|
|
426
426
|
</div>
|
|
@@ -432,7 +432,7 @@ function CommentRow({
|
|
|
432
432
|
{editing ? (
|
|
433
433
|
<>
|
|
434
434
|
<MentionableTextarea
|
|
435
|
-
className="w-full resize-none rounded border
|
|
435
|
+
className="border-border w-full resize-none rounded border p-1 text-sm"
|
|
436
436
|
rows={3}
|
|
437
437
|
value={draft}
|
|
438
438
|
onChange={setDraft}
|
|
@@ -443,7 +443,7 @@ function CommentRow({
|
|
|
443
443
|
<div className="flex gap-1">
|
|
444
444
|
<button
|
|
445
445
|
type="button"
|
|
446
|
-
className="
|
|
446
|
+
className="bg-primary rounded px-2 py-1 text-xs font-medium text-white"
|
|
447
447
|
onClick={async (e) => {
|
|
448
448
|
e.stopPropagation()
|
|
449
449
|
const ok = await onEdit(comment.id, draft)
|
|
@@ -455,7 +455,7 @@ function CommentRow({
|
|
|
455
455
|
</button>
|
|
456
456
|
<button
|
|
457
457
|
type="button"
|
|
458
|
-
className="rounded border
|
|
458
|
+
className="border-border rounded border px-2 py-1 text-xs"
|
|
459
459
|
onClick={(e) => {
|
|
460
460
|
e.stopPropagation()
|
|
461
461
|
setDraft(comment.body)
|
|
@@ -469,7 +469,7 @@ function CommentRow({
|
|
|
469
469
|
</>
|
|
470
470
|
) : (
|
|
471
471
|
<p
|
|
472
|
-
className="text-sm whitespace-pre-wrap
|
|
472
|
+
className="text-foreground text-sm whitespace-pre-wrap"
|
|
473
473
|
data-testid={`comment-body-${comment.id}`}
|
|
474
474
|
>
|
|
475
475
|
{comment.body}
|
|
@@ -480,7 +480,7 @@ function CommentRow({
|
|
|
480
480
|
{canMutate && (
|
|
481
481
|
<button
|
|
482
482
|
type="button"
|
|
483
|
-
className="text-
|
|
483
|
+
className="text-muted-foreground hover:text-foreground"
|
|
484
484
|
onClick={(e) => {
|
|
485
485
|
e.stopPropagation()
|
|
486
486
|
setEditing(true)
|
|
@@ -493,7 +493,7 @@ function CommentRow({
|
|
|
493
493
|
{onToggleResolve && (
|
|
494
494
|
<button
|
|
495
495
|
type="button"
|
|
496
|
-
className="text-
|
|
496
|
+
className="text-muted-foreground hover:text-foreground"
|
|
497
497
|
onClick={(e) => {
|
|
498
498
|
e.stopPropagation()
|
|
499
499
|
onToggleResolve()
|
|
@@ -506,7 +506,7 @@ function CommentRow({
|
|
|
506
506
|
{canMutate && (
|
|
507
507
|
<button
|
|
508
508
|
type="button"
|
|
509
|
-
className="text-
|
|
509
|
+
className="text-destructive hover:text-destructive"
|
|
510
510
|
onClick={(e) => {
|
|
511
511
|
e.stopPropagation()
|
|
512
512
|
onDelete()
|
|
@@ -20,7 +20,7 @@ export function ContentOverviewChart({ published, drafts, scheduled }: ContentOv
|
|
|
20
20
|
|
|
21
21
|
if (total === 0) {
|
|
22
22
|
return (
|
|
23
|
-
<div className="flex h-full items-center justify-center text-sm
|
|
23
|
+
<div className="text-muted-foreground flex h-full items-center justify-center text-sm">
|
|
24
24
|
No content yet
|
|
25
25
|
</div>
|
|
26
26
|
)
|
|
@@ -58,12 +58,12 @@ export function ContentOverviewChart({ published, drafts, scheduled }: ContentOv
|
|
|
58
58
|
style={{ backgroundColor: COLORS[idx] }}
|
|
59
59
|
/>
|
|
60
60
|
<div className="min-w-0">
|
|
61
|
-
<span className="text-
|
|
61
|
+
<span className="text-foreground text-sm">{entry.name}</span>
|
|
62
62
|
<div className="flex items-baseline gap-2">
|
|
63
|
-
<span className="text-lg font-medium
|
|
63
|
+
<span className="text-foreground text-lg font-medium">
|
|
64
64
|
{entry.value.toLocaleString()}
|
|
65
65
|
</span>
|
|
66
|
-
<span className="text-
|
|
66
|
+
<span className="text-muted-foreground text-xs">{pct}%</span>
|
|
67
67
|
</div>
|
|
68
68
|
</div>
|
|
69
69
|
</div>
|
|
@@ -50,10 +50,10 @@ export function FocalPointPicker({ imageUrl, focalX, focalY, onChange }: FocalPo
|
|
|
50
50
|
draggable={false}
|
|
51
51
|
/>
|
|
52
52
|
<div
|
|
53
|
-
className="pointer-events-none absolute -mt-3 -ml-3 h-6 w-6 rounded-full border-2 border-white
|
|
53
|
+
className="bg-info/50 pointer-events-none absolute -mt-3 -ml-3 h-6 w-6 rounded-full border-2 border-white shadow-lg"
|
|
54
54
|
style={{ left: `${focalX * 100}%`, top: `${focalY * 100}%` }}
|
|
55
55
|
>
|
|
56
|
-
<div className="absolute inset-1 rounded-full
|
|
56
|
+
<div className="bg-card absolute inset-1 rounded-full" />
|
|
57
57
|
</div>
|
|
58
58
|
</div>
|
|
59
59
|
<p className="text-xs text-[var(--muted-foreground)]">
|
|
@@ -155,13 +155,16 @@ export function LivePreview({
|
|
|
155
155
|
|
|
156
156
|
if (!previewSrc) {
|
|
157
157
|
return (
|
|
158
|
-
<div className="flex h-full flex-col items-center justify-center rounded-lg border border-dashed
|
|
159
|
-
<p className="text-
|
|
158
|
+
<div className="border-border bg-muted flex h-full flex-col items-center justify-center rounded-lg border border-dashed p-8">
|
|
159
|
+
<p className="text-muted-foreground text-center text-sm">
|
|
160
160
|
{!documentId
|
|
161
161
|
? 'Save the document first to enable preview'
|
|
162
162
|
: 'Configure a preview URL in the collection settings to enable live preview'}
|
|
163
163
|
</p>
|
|
164
|
-
<button
|
|
164
|
+
<button
|
|
165
|
+
onClick={onClose}
|
|
166
|
+
className="text-muted-foreground hover:text-muted-foreground mt-4 text-xs"
|
|
167
|
+
>
|
|
165
168
|
Close Preview
|
|
166
169
|
</button>
|
|
167
170
|
</div>
|
|
@@ -169,8 +172,8 @@ export function LivePreview({
|
|
|
169
172
|
}
|
|
170
173
|
|
|
171
174
|
return (
|
|
172
|
-
<div className="flex h-full flex-col border-l
|
|
173
|
-
<div className="flex items-center justify-between border-b
|
|
175
|
+
<div className="border-border bg-card flex h-full flex-col border-l">
|
|
176
|
+
<div className="border-border bg-muted flex items-center justify-between border-b px-3 py-2">
|
|
174
177
|
<div className="flex items-center gap-1">
|
|
175
178
|
{(
|
|
176
179
|
[
|
|
@@ -182,14 +185,14 @@ export function LivePreview({
|
|
|
182
185
|
<button
|
|
183
186
|
key={vp}
|
|
184
187
|
onClick={() => setViewport(vp)}
|
|
185
|
-
className={`rounded p-1.5 ${viewport === vp ? 'bg-
|
|
188
|
+
className={`rounded p-1.5 ${viewport === vp ? 'bg-card text-primary shadow-sm' : 'text-muted-foreground hover:text-muted-foreground'}`}
|
|
186
189
|
title={vp}
|
|
187
190
|
>
|
|
188
191
|
<Icon className="h-4 w-4" />
|
|
189
192
|
</button>
|
|
190
193
|
))}
|
|
191
194
|
<span
|
|
192
|
-
className="ml-2 inline-flex items-center gap-1 rounded-full
|
|
195
|
+
className="bg-card text-muted-foreground ml-2 inline-flex items-center gap-1 rounded-full px-2 py-0.5 text-[10px] font-medium"
|
|
193
196
|
title={
|
|
194
197
|
streamStatus === 'connected'
|
|
195
198
|
? 'Live preview is streaming updates from the server.'
|
|
@@ -202,19 +205,19 @@ export function LivePreview({
|
|
|
202
205
|
>
|
|
203
206
|
{streamStatus === 'connected' ? (
|
|
204
207
|
<>
|
|
205
|
-
<Wifi className="h-3 w-3
|
|
208
|
+
<Wifi className="text-success h-3 w-3" aria-hidden /> Live
|
|
206
209
|
</>
|
|
207
210
|
) : streamStatus === 'connecting' ? (
|
|
208
211
|
<>
|
|
209
|
-
<Wifi className="h-3 w-3 animate-pulse
|
|
212
|
+
<Wifi className="text-info h-3 w-3 animate-pulse" aria-hidden /> Connecting
|
|
210
213
|
</>
|
|
211
214
|
) : streamStatus === 'offline' ? (
|
|
212
215
|
<>
|
|
213
|
-
<WifiOff className="h-3 w-3
|
|
216
|
+
<WifiOff className="text-warning h-3 w-3" aria-hidden /> Reconnecting
|
|
214
217
|
</>
|
|
215
218
|
) : (
|
|
216
219
|
<>
|
|
217
|
-
<WifiOff className="h-3 w-3
|
|
220
|
+
<WifiOff className="text-muted-foreground h-3 w-3" aria-hidden /> Idle
|
|
218
221
|
</>
|
|
219
222
|
)}
|
|
220
223
|
</span>
|
|
@@ -222,21 +225,21 @@ export function LivePreview({
|
|
|
222
225
|
<div className="flex items-center gap-1">
|
|
223
226
|
<button
|
|
224
227
|
onClick={handleRefresh}
|
|
225
|
-
className="
|
|
228
|
+
className="text-muted-foreground hover:text-muted-foreground rounded p-1.5"
|
|
226
229
|
title="Refresh"
|
|
227
230
|
>
|
|
228
231
|
<RefreshCw className="h-4 w-4" />
|
|
229
232
|
</button>
|
|
230
233
|
<button
|
|
231
234
|
onClick={handleOpenExternal}
|
|
232
|
-
className="
|
|
235
|
+
className="text-muted-foreground hover:text-muted-foreground rounded p-1.5"
|
|
233
236
|
title="Open in new tab"
|
|
234
237
|
>
|
|
235
238
|
<ExternalLink className="h-4 w-4" />
|
|
236
239
|
</button>
|
|
237
240
|
<button
|
|
238
241
|
onClick={onClose}
|
|
239
|
-
className="
|
|
242
|
+
className="text-muted-foreground hover:text-muted-foreground rounded p-1.5"
|
|
240
243
|
title="Close"
|
|
241
244
|
>
|
|
242
245
|
<X className="h-4 w-4" />
|
|
@@ -244,20 +247,20 @@ export function LivePreview({
|
|
|
244
247
|
</div>
|
|
245
248
|
</div>
|
|
246
249
|
|
|
247
|
-
<div className="flex flex-1 justify-center overflow-auto
|
|
250
|
+
<div className="bg-muted flex flex-1 justify-center overflow-auto p-4">
|
|
248
251
|
<div
|
|
249
252
|
style={{ width: VIEWPORT_WIDTHS[viewport], maxWidth: '100%', transition: 'width 0.3s' }}
|
|
250
253
|
className="relative"
|
|
251
254
|
>
|
|
252
255
|
{loading && (
|
|
253
|
-
<div className="absolute inset-0 z-10 flex items-center justify-center rounded-lg
|
|
256
|
+
<div className="bg-card/80 absolute inset-0 z-10 flex items-center justify-center rounded-lg">
|
|
254
257
|
<div className="h-8 w-8 animate-spin rounded-full border-b-2 border-blue-600" />
|
|
255
258
|
</div>
|
|
256
259
|
)}
|
|
257
260
|
<iframe
|
|
258
261
|
ref={iframeRef}
|
|
259
262
|
src={previewSrc}
|
|
260
|
-
className="h-full w-full rounded-lg border
|
|
263
|
+
className="border-border bg-card h-full w-full rounded-lg border shadow-lg"
|
|
261
264
|
style={{ minHeight: '600px' }}
|
|
262
265
|
onLoad={() => setLoading(false)}
|
|
263
266
|
title="Page Preview"
|
|
@@ -25,7 +25,7 @@ export function LogoPlaceholder({ tone, label }: LogoPlaceholderProps) {
|
|
|
25
25
|
role="img"
|
|
26
26
|
aria-label="Logo placeholder"
|
|
27
27
|
title="Add a logo in Settings → Appearance"
|
|
28
|
-
className="mx-auto mb-4 flex h-14 w-14 items-center justify-center rounded-lg border border-dashed
|
|
28
|
+
className="border-border text-muted-foreground mx-auto mb-4 flex h-14 w-14 items-center justify-center rounded-lg border border-dashed"
|
|
29
29
|
>
|
|
30
30
|
<ImagePlus className="h-6 w-6" aria-hidden="true" />
|
|
31
31
|
</span>
|
|
@@ -283,11 +283,11 @@ export function MentionableTextarea({
|
|
|
283
283
|
id={pickerId}
|
|
284
284
|
role="listbox"
|
|
285
285
|
aria-label="Mention a teammate"
|
|
286
|
-
className="absolute top-full left-0 z-30 mt-1 max-h-56 w-64 overflow-y-auto rounded border
|
|
286
|
+
className="border-border bg-card absolute top-full left-0 z-30 mt-1 max-h-56 w-64 overflow-y-auto rounded border shadow-lg"
|
|
287
287
|
data-testid={testId ? `${testId}-picker` : 'mention-picker'}
|
|
288
288
|
>
|
|
289
289
|
{picker.users.length === 0 ? (
|
|
290
|
-
<p className="px-3 py-2 text-xs
|
|
290
|
+
<p className="text-muted-foreground px-3 py-2 text-xs">
|
|
291
291
|
{picker.query ? 'No matches' : 'Type a name…'}
|
|
292
292
|
</p>
|
|
293
293
|
) : (
|
|
@@ -309,13 +309,13 @@ export function MentionableTextarea({
|
|
|
309
309
|
onMouseEnter={() => setPicker((s) => ({ ...s, highlight: idx }))}
|
|
310
310
|
className={`block w-full px-3 py-1.5 text-left text-xs ${
|
|
311
311
|
idx === picker.highlight
|
|
312
|
-
? 'bg-
|
|
313
|
-
: 'text-
|
|
312
|
+
? 'bg-info/10 text-foreground'
|
|
313
|
+
: 'text-foreground hover:bg-accent'
|
|
314
314
|
}`}
|
|
315
315
|
data-testid={testId ? `${testId}-picker-row-${u.id}` : `mention-row-${u.id}`}
|
|
316
316
|
>
|
|
317
317
|
<div className="font-medium">{formatLabel(u)}</div>
|
|
318
|
-
<div className="text-[10px]
|
|
318
|
+
<div className="text-muted-foreground text-[10px]">{u.email}</div>
|
|
319
319
|
</button>
|
|
320
320
|
</li>
|
|
321
321
|
))}
|
|
@@ -246,7 +246,7 @@ export function NotificationBell({
|
|
|
246
246
|
<div className={`relative ${className ?? ''}`} data-testid="notification-bell">
|
|
247
247
|
<button
|
|
248
248
|
type="button"
|
|
249
|
-
className="
|
|
249
|
+
className="text-muted-foreground hover:bg-accent hover:text-foreground relative rounded p-1.5"
|
|
250
250
|
aria-label="Notifications"
|
|
251
251
|
aria-haspopup="menu"
|
|
252
252
|
aria-expanded={open}
|
|
@@ -256,7 +256,7 @@ export function NotificationBell({
|
|
|
256
256
|
<BellIcon />
|
|
257
257
|
{unread > 0 && (
|
|
258
258
|
<span
|
|
259
|
-
className="absolute -top-0.5 -right-0.5 inline-flex h-4 min-w-4 items-center justify-center rounded-full
|
|
259
|
+
className="bg-destructive absolute -top-0.5 -right-0.5 inline-flex h-4 min-w-4 items-center justify-center rounded-full px-1 text-[10px] font-medium text-white"
|
|
260
260
|
data-testid="bell-badge"
|
|
261
261
|
>
|
|
262
262
|
{unread > 99 ? '99+' : unread}
|
|
@@ -266,14 +266,14 @@ export function NotificationBell({
|
|
|
266
266
|
{open && (
|
|
267
267
|
<div
|
|
268
268
|
role="menu"
|
|
269
|
-
className="absolute right-0 z-50 mt-1 w-80 rounded border
|
|
269
|
+
className="border-border bg-card absolute right-0 z-50 mt-1 w-80 rounded border shadow-lg"
|
|
270
270
|
data-testid="bell-dropdown"
|
|
271
271
|
>
|
|
272
272
|
<header className="flex items-center justify-between border-b border-gray-100 px-3 py-2">
|
|
273
|
-
<span className="text-sm font-medium
|
|
273
|
+
<span className="text-foreground text-sm font-medium">Notifications</span>
|
|
274
274
|
<button
|
|
275
275
|
type="button"
|
|
276
|
-
className="text-
|
|
276
|
+
className="text-muted-foreground hover:text-foreground text-xs disabled:opacity-50"
|
|
277
277
|
onClick={handleMarkAll}
|
|
278
278
|
disabled={unread === 0}
|
|
279
279
|
data-testid="bell-mark-all"
|
|
@@ -283,9 +283,9 @@ export function NotificationBell({
|
|
|
283
283
|
</header>
|
|
284
284
|
<div className="max-h-80 overflow-y-auto" aria-busy={loading} data-testid="bell-list">
|
|
285
285
|
{loading ? (
|
|
286
|
-
<p className="px-3 py-2 text-xs
|
|
286
|
+
<p className="text-muted-foreground px-3 py-2 text-xs">Loading…</p>
|
|
287
287
|
) : items.length === 0 ? (
|
|
288
|
-
<p className="px-3 py-2 text-xs
|
|
288
|
+
<p className="text-muted-foreground px-3 py-2 text-xs">All caught up.</p>
|
|
289
289
|
) : (
|
|
290
290
|
<ul>
|
|
291
291
|
{items.map((n) => (
|
|
@@ -293,15 +293,15 @@ export function NotificationBell({
|
|
|
293
293
|
<button
|
|
294
294
|
type="button"
|
|
295
295
|
role="menuitem"
|
|
296
|
-
className={`block w-full px-3 py-2 text-left text-xs
|
|
297
|
-
n.readAt ? 'text-
|
|
296
|
+
className={`hover:bg-accent block w-full px-3 py-2 text-left text-xs ${
|
|
297
|
+
n.readAt ? 'text-muted-foreground' : 'text-foreground font-medium'
|
|
298
298
|
}`}
|
|
299
299
|
onClick={() => handleClickRow(n)}
|
|
300
300
|
data-testid={`bell-row-${n.id}`}
|
|
301
301
|
data-read={n.readAt ? 'true' : 'false'}
|
|
302
302
|
>
|
|
303
303
|
<div>{notificationSummary(n)}</div>
|
|
304
|
-
<div className="mt-0.5 text-[10px]
|
|
304
|
+
<div className="text-muted-foreground mt-0.5 text-[10px]">{n.createdAt}</div>
|
|
305
305
|
</button>
|
|
306
306
|
</li>
|
|
307
307
|
))}
|
|
@@ -51,17 +51,17 @@ export function OfflineStatus({ connection, offline }: OfflineStatusProps): Reac
|
|
|
51
51
|
export type OfflineTone = 'good' | 'warn' | 'info' | 'bad'
|
|
52
52
|
|
|
53
53
|
const TONE_CLASSES: Record<OfflineTone, string> = {
|
|
54
|
-
good: 'bg-
|
|
55
|
-
warn: 'bg-
|
|
56
|
-
info: 'bg-
|
|
57
|
-
bad: 'bg-
|
|
54
|
+
good: 'bg-success/10 text-emerald-700',
|
|
55
|
+
warn: 'bg-warning/10 text-warning',
|
|
56
|
+
info: 'bg-info/10 text-info',
|
|
57
|
+
bad: 'bg-destructive/10 text-destructive',
|
|
58
58
|
}
|
|
59
59
|
|
|
60
60
|
const DOT_CLASSES: Record<OfflineTone, string> = {
|
|
61
|
-
good: 'bg-
|
|
62
|
-
warn: 'bg-
|
|
63
|
-
info: 'bg-
|
|
64
|
-
bad: 'bg-
|
|
61
|
+
good: 'bg-success',
|
|
62
|
+
warn: 'bg-warning',
|
|
63
|
+
info: 'bg-info',
|
|
64
|
+
bad: 'bg-destructive',
|
|
65
65
|
}
|
|
66
66
|
|
|
67
67
|
/**
|
|
@@ -70,7 +70,7 @@ export function PresenceChips({
|
|
|
70
70
|
>
|
|
71
71
|
{status && <StatusPill status={status} />}
|
|
72
72
|
{shown.length === 0 && status !== 'connecting' && (
|
|
73
|
-
<span className="text-
|
|
73
|
+
<span className="text-muted-foreground" data-testid="presence-empty">
|
|
74
74
|
You're the only one here
|
|
75
75
|
</span>
|
|
76
76
|
)}
|
|
@@ -79,7 +79,7 @@ export function PresenceChips({
|
|
|
79
79
|
))}
|
|
80
80
|
{overflow > 0 && (
|
|
81
81
|
<span
|
|
82
|
-
className="
|
|
82
|
+
className="bg-muted text-foreground rounded-full px-2 py-0.5"
|
|
83
83
|
data-testid="presence-overflow"
|
|
84
84
|
>
|
|
85
85
|
+{overflow}
|
|
@@ -91,14 +91,18 @@ export function PresenceChips({
|
|
|
91
91
|
|
|
92
92
|
function StatusPill({ status }: { status: CollaborationStatus }) {
|
|
93
93
|
const palette: Record<CollaborationStatus, { dot: string; label: string; text: string }> = {
|
|
94
|
-
connected: { dot: 'bg-
|
|
95
|
-
connecting: { dot: 'bg-amber-400 animate-pulse', label: 'Connecting', text: 'text-
|
|
96
|
-
disconnected: {
|
|
94
|
+
connected: { dot: 'bg-success', label: 'Live', text: 'text-emerald-700' },
|
|
95
|
+
connecting: { dot: 'bg-amber-400 animate-pulse', label: 'Connecting', text: 'text-warning' },
|
|
96
|
+
disconnected: {
|
|
97
|
+
dot: 'bg-muted-foreground/30',
|
|
98
|
+
label: 'Offline',
|
|
99
|
+
text: 'text-muted-foreground',
|
|
100
|
+
},
|
|
97
101
|
}
|
|
98
102
|
const cfg = palette[status]
|
|
99
103
|
return (
|
|
100
104
|
<span
|
|
101
|
-
className={`inline-flex items-center gap-1 rounded-full
|
|
105
|
+
className={`bg-muted inline-flex items-center gap-1 rounded-full px-2 py-0.5 ${cfg.text}`}
|
|
102
106
|
data-testid={`presence-status-${status}`}
|
|
103
107
|
>
|
|
104
108
|
<span className={`h-1.5 w-1.5 rounded-full ${cfg.dot}`} />
|
|
@@ -111,7 +115,7 @@ function Chip({ name, color, avatarUrl }: { name: string; color: string; avatarU
|
|
|
111
115
|
const initials = nameToInitials(name)
|
|
112
116
|
return (
|
|
113
117
|
<span
|
|
114
|
-
className="inline-flex items-center gap-1 rounded-full
|
|
118
|
+
className="bg-card inline-flex items-center gap-1 rounded-full px-1.5 py-0.5 ring-1 ring-gray-200"
|
|
115
119
|
title={name}
|
|
116
120
|
data-testid="presence-chip"
|
|
117
121
|
>
|
|
@@ -131,7 +135,7 @@ function Chip({ name, color, avatarUrl }: { name: string; color: string; avatarU
|
|
|
131
135
|
{initials}
|
|
132
136
|
</span>
|
|
133
137
|
)}
|
|
134
|
-
<span className="max-w-[80px] truncate
|
|
138
|
+
<span className="text-foreground max-w-[80px] truncate">{name}</span>
|
|
135
139
|
</span>
|
|
136
140
|
)
|
|
137
141
|
}
|