@prenta/admin 1.17.0 → 1.17.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 +18 -0
- package/dist/__tests__/lib/seo-service-errors.test.js +2 -6
- package/dist/__tests__/lib/seo-service-errors.test.js.map +1 -1
- package/dist/__tests__/views/ai-settings.render.test.js +67 -1
- package/dist/__tests__/views/ai-settings.render.test.js.map +1 -1
- package/dist/components/CoauthorResultPopover.d.ts.map +1 -1
- package/dist/components/CoauthorResultPopover.js +4 -1
- package/dist/components/CoauthorResultPopover.js.map +1 -1
- package/dist/components/CommentSidePanel.d.ts +0 -7
- package/dist/components/CommentSidePanel.d.ts.map +1 -1
- package/dist/components/CommentSidePanel.js +0 -2
- package/dist/components/CommentSidePanel.js.map +1 -1
- package/dist/components/EditorRail.d.ts +2 -1
- package/dist/components/EditorRail.d.ts.map +1 -1
- package/dist/components/MediaPickerModal.d.ts +2 -1
- package/dist/components/MediaPickerModal.d.ts.map +1 -1
- package/dist/components/TipTapEditor.d.ts +3 -2
- package/dist/components/TipTapEditor.d.ts.map +1 -1
- package/dist/components/forms/EntriesTable.d.ts +0 -1
- package/dist/components/forms/EntriesTable.d.ts.map +1 -1
- package/dist/components/forms/EntriesTable.js +1 -1
- package/dist/components/forms/EntriesTable.js.map +1 -1
- package/dist/components/pages/tag-badges.d.ts +2 -2
- package/dist/components/pages/tag-badges.d.ts.map +1 -1
- package/dist/components/pages/tag-badges.js.map +1 -1
- package/dist/components/seo/FaqProposalPreview.d.ts +2 -3
- package/dist/components/seo/FaqProposalPreview.d.ts.map +1 -1
- package/dist/components/seo/FaqProposalPreview.js +1 -1
- package/dist/components/seo/FaqProposalPreview.js.map +1 -1
- package/dist/components/seo/SeoCopilotDrawer.js +1 -1
- package/dist/components/seo/SeoCopilotDrawer.js.map +1 -1
- package/dist/components/seo/SeoEditorPane.d.ts.map +1 -1
- package/dist/components/seo/SeoEditorPane.js +4 -1
- package/dist/components/seo/SeoEditorPane.js.map +1 -1
- package/dist/components/ui/Badge.d.ts +3 -9
- package/dist/components/ui/Badge.d.ts.map +1 -1
- package/dist/components/ui/Badge.js +2 -3
- package/dist/components/ui/Badge.js.map +1 -1
- package/dist/components/ui/Button.d.ts +2 -2
- package/dist/components/ui/Button.d.ts.map +1 -1
- package/dist/components/ui/Button.js +0 -1
- package/dist/components/ui/Button.js.map +1 -1
- package/dist/components/ui/Card.d.ts +2 -3
- package/dist/components/ui/Card.d.ts.map +1 -1
- package/dist/components/ui/Card.js +0 -4
- package/dist/components/ui/Card.js.map +1 -1
- package/dist/components/ui/Input.d.ts +6 -8
- package/dist/components/ui/Input.d.ts.map +1 -1
- package/dist/components/ui/Input.js +6 -6
- package/dist/components/ui/Input.js.map +1 -1
- package/dist/components/ui/Modal.d.ts +1 -1
- package/dist/components/ui/Modal.d.ts.map +1 -1
- package/dist/components/ui/ResizableAside.d.ts +0 -13
- package/dist/components/ui/ResizableAside.d.ts.map +1 -1
- package/dist/components/ui/ResizableAside.js +5 -5
- package/dist/components/ui/ResizableAside.js.map +1 -1
- package/dist/components/ui/StatusBadge.d.ts +2 -2
- package/dist/components/ui/StatusBadge.d.ts.map +1 -1
- package/dist/components/ui/StatusBadge.js +0 -1
- package/dist/components/ui/StatusBadge.js.map +1 -1
- package/dist/components/ui/Toggle.d.ts +2 -8
- package/dist/components/ui/Toggle.d.ts.map +1 -1
- package/dist/components/ui/Toggle.js +0 -1
- package/dist/components/ui/Toggle.js.map +1 -1
- package/dist/fields/FieldRenderer.d.ts +2 -1
- package/dist/fields/FieldRenderer.d.ts.map +1 -1
- package/dist/fields/index.d.ts +0 -17
- package/dist/fields/index.d.ts.map +1 -1
- package/dist/fields/index.js +0 -15
- package/dist/fields/index.js.map +1 -1
- package/dist/layout/primitives/tokens.d.ts +0 -2
- package/dist/layout/primitives/tokens.d.ts.map +1 -1
- package/dist/layout/primitives/tokens.js +0 -6
- package/dist/layout/primitives/tokens.js.map +1 -1
- package/dist/lib/brand-voice-client.d.ts +14 -1
- package/dist/lib/brand-voice-client.d.ts.map +1 -1
- package/dist/lib/brand-voice-client.js +7 -0
- package/dist/lib/brand-voice-client.js.map +1 -1
- package/dist/lib/coauthor-client.d.ts +2 -1
- package/dist/lib/coauthor-client.d.ts.map +1 -1
- package/dist/lib/collection-schema.d.ts +0 -9
- package/dist/lib/collection-schema.d.ts.map +1 -1
- package/dist/lib/collection-schema.js +2 -2
- package/dist/lib/collection-schema.js.map +1 -1
- package/dist/lib/editor-seo-content.d.ts +0 -10
- package/dist/lib/editor-seo-content.d.ts.map +1 -1
- package/dist/lib/editor-seo-content.js +0 -13
- package/dist/lib/editor-seo-content.js.map +1 -1
- package/dist/lib/forms-service.d.ts +3 -21
- package/dist/lib/forms-service.d.ts.map +1 -1
- package/dist/lib/forms-service.js +0 -25
- package/dist/lib/forms-service.js.map +1 -1
- package/dist/lib/notifications-client.d.ts +4 -3
- package/dist/lib/notifications-client.d.ts.map +1 -1
- package/dist/lib/page-audit-input.d.ts +0 -10
- package/dist/lib/page-audit-input.d.ts.map +1 -1
- package/dist/lib/page-audit-input.js +1 -1
- package/dist/lib/page-audit-input.js.map +1 -1
- package/dist/lib/page-editor-service.d.ts +2 -4
- package/dist/lib/page-editor-service.d.ts.map +1 -1
- package/dist/lib/page-editor-service.js +3 -3
- package/dist/lib/page-editor-service.js.map +1 -1
- package/dist/lib/pages-service.d.ts +2 -13
- package/dist/lib/pages-service.d.ts.map +1 -1
- package/dist/lib/pages-service.js +3 -24
- package/dist/lib/pages-service.js.map +1 -1
- package/dist/lib/plan.d.ts +2 -1
- package/dist/lib/plan.d.ts.map +1 -1
- package/dist/lib/post-editor-service.d.ts +3 -13
- package/dist/lib/post-editor-service.d.ts.map +1 -1
- package/dist/lib/post-editor-service.js +5 -6
- package/dist/lib/post-editor-service.js.map +1 -1
- package/dist/lib/post-types-service.d.ts +2 -3
- package/dist/lib/post-types-service.d.ts.map +1 -1
- package/dist/lib/post-types-service.js +1 -1
- package/dist/lib/post-types-service.js.map +1 -1
- package/dist/lib/posts-service.d.ts +2 -1
- package/dist/lib/posts-service.d.ts.map +1 -1
- package/dist/lib/preview-link.d.ts +0 -9
- package/dist/lib/preview-link.d.ts.map +1 -1
- package/dist/lib/preview-link.js +0 -15
- package/dist/lib/preview-link.js.map +1 -1
- package/dist/lib/rail-width.d.ts +0 -1
- package/dist/lib/rail-width.d.ts.map +1 -1
- package/dist/lib/rail-width.js +1 -1
- package/dist/lib/rail-width.js.map +1 -1
- package/dist/lib/reflow-probe.d.ts +0 -67
- package/dist/lib/reflow-probe.d.ts.map +1 -1
- package/dist/lib/reflow-probe.js +4 -4
- package/dist/lib/reflow-probe.js.map +1 -1
- package/dist/lib/seo-service.d.ts +14 -37
- package/dist/lib/seo-service.d.ts.map +1 -1
- package/dist/lib/seo-service.js +7 -37
- package/dist/lib/seo-service.js.map +1 -1
- package/dist/lib/theme-chrome.d.ts +0 -1
- package/dist/lib/theme-chrome.d.ts.map +1 -1
- package/dist/lib/theme-chrome.js +1 -1
- package/dist/lib/theme-chrome.js.map +1 -1
- package/dist/lib/version-history.d.ts +2 -2
- package/dist/lib/version-history.d.ts.map +1 -1
- package/dist/lib/workflow-chrome.d.ts +0 -3
- package/dist/lib/workflow-chrome.d.ts.map +1 -1
- package/dist/lib/workflow-chrome.js +3 -3
- package/dist/lib/workflow-chrome.js.map +1 -1
- package/dist/prenta-admin.css +1 -1
- package/dist/views/Login.d.ts +2 -1
- package/dist/views/Login.d.ts.map +1 -1
- package/dist/views/MediaBrowser.d.ts.map +1 -1
- package/dist/views/MediaBrowser.js +3 -2
- package/dist/views/MediaBrowser.js.map +1 -1
- package/dist/views/PageEditor.d.ts +2 -1
- package/dist/views/PageEditor.d.ts.map +1 -1
- package/dist/views/Pages/PagesListView.d.ts +0 -1
- package/dist/views/Pages/PagesListView.d.ts.map +1 -1
- package/dist/views/Pages/PagesListView.js +1 -1
- package/dist/views/Pages/PagesListView.js.map +1 -1
- package/dist/views/Pages.d.ts +2 -1
- package/dist/views/Pages.d.ts.map +1 -1
- package/dist/views/Redirects.d.ts +2 -1
- package/dist/views/Redirects.d.ts.map +1 -1
- package/dist/views/page-editor/section-types.d.ts +2 -2
- package/dist/views/page-editor/section-types.d.ts.map +1 -1
- package/dist/views/page-editor/section-types.js +1 -1
- package/dist/views/page-editor/section-types.js.map +1 -1
- package/dist/views/page-editor/sections/admin-renderers.d.ts +2 -1
- package/dist/views/page-editor/sections/admin-renderers.d.ts.map +1 -1
- package/dist/views/page-editor/theme-chrome/index.d.ts +1 -6
- package/dist/views/page-editor/theme-chrome/index.d.ts.map +1 -1
- package/dist/views/page-editor/theme-chrome/index.js +1 -3
- package/dist/views/page-editor/theme-chrome/index.js.map +1 -1
- package/dist/views/page-editor/viewports.d.ts +1 -1
- package/dist/views/page-editor/viewports.d.ts.map +1 -1
- package/dist/views/page-editor/viewports.js +1 -1
- package/dist/views/page-editor/viewports.js.map +1 -1
- package/dist/views/settings/AISettingsTab.d.ts.map +1 -1
- package/dist/views/settings/AISettingsTab.js +13 -3
- package/dist/views/settings/AISettingsTab.js.map +1 -1
- package/dist/views/settings/BrandVoiceCard.d.ts +3 -0
- package/dist/views/settings/BrandVoiceCard.d.ts.map +1 -1
- package/dist/views/settings/BrandVoiceCard.js +2 -2
- package/dist/views/settings/BrandVoiceCard.js.map +1 -1
- package/dist/views/settings/brand-voice/BrandVoiceAlignmentPanel.d.ts.map +1 -1
- package/dist/views/settings/brand-voice/BrandVoiceAlignmentPanel.js +4 -1
- package/dist/views/settings/brand-voice/BrandVoiceAlignmentPanel.js.map +1 -1
- package/dist/views/settings/featureModel.d.ts +0 -3
- package/dist/views/settings/featureModel.d.ts.map +1 -1
- package/dist/views/settings/featureModel.js +2 -2
- package/dist/views/settings/featureModel.js.map +1 -1
- package/dist/views/settings/useAiSettings.d.ts +2 -2
- package/dist/views/settings/useAiSettings.d.ts.map +1 -1
- package/dist/views/settings/useAiSettings.js +6 -2
- package/dist/views/settings/useAiSettings.js.map +1 -1
- package/dist/views/settings/useAppearanceSettings.d.ts +5 -6
- package/dist/views/settings/useAppearanceSettings.d.ts.map +1 -1
- package/dist/views/settings/useAppearanceSettings.js +1 -1
- package/dist/views/settings/useAppearanceSettings.js.map +1 -1
- package/dist/views/settings/useEmailSettings.d.ts +3 -2
- package/dist/views/settings/useEmailSettings.d.ts.map +1 -1
- package/dist/views/settings/useGeneralSettings.d.ts +2 -11
- package/dist/views/settings/useGeneralSettings.d.ts.map +1 -1
- package/dist/views/settings/useGeneralSettings.js +3 -3
- package/dist/views/settings/useGeneralSettings.js.map +1 -1
- package/dist/views/settings/useSeoSettings.d.ts +1 -1
- package/dist/views/settings/useSeoSettings.d.ts.map +1 -1
- package/dist/views/settings/useUpdates.d.ts +1 -3
- package/dist/views/settings/useUpdates.d.ts.map +1 -1
- package/dist/views/settings/useUpdates.js +1 -1
- package/dist/views/settings/useUpdates.js.map +1 -1
- package/package.json +5 -5
- package/src/__tests__/lib/seo-service-errors.test.ts +1 -9
- package/src/__tests__/views/ai-settings.render.test.tsx +86 -2
- package/src/components/CoauthorResultPopover.tsx +3 -1
- package/src/components/CommentSidePanel.tsx +0 -1
- package/src/components/EditorRail.tsx +1 -1
- package/src/components/MediaPickerModal.tsx +1 -1
- package/src/components/TipTapEditor.tsx +2 -2
- package/src/components/forms/EntriesTable.tsx +1 -1
- package/src/components/pages/tag-badges.tsx +1 -1
- package/src/components/seo/FaqProposalPreview.tsx +2 -2
- package/src/components/seo/SeoCopilotDrawer.tsx +1 -1
- package/src/components/seo/SeoEditorPane.tsx +3 -1
- package/src/components/ui/Badge.tsx +4 -6
- package/src/components/ui/Button.tsx +1 -3
- package/src/components/ui/Card.tsx +1 -14
- package/src/components/ui/Input.tsx +7 -15
- package/src/components/ui/Modal.tsx +1 -1
- package/src/components/ui/ResizableAside.tsx +5 -5
- package/src/components/ui/StatusBadge.tsx +1 -3
- package/src/components/ui/Toggle.tsx +1 -3
- package/src/fields/FieldRenderer.tsx +1 -1
- package/src/fields/index.ts +0 -17
- package/src/layout/primitives/tokens.ts +0 -7
- package/src/lib/brand-voice-client.ts +18 -1
- package/src/lib/coauthor-client.ts +1 -1
- package/src/lib/collection-schema.ts +2 -2
- package/src/lib/editor-seo-content.ts +0 -22
- package/src/lib/forms-service.ts +2 -42
- package/src/lib/notifications-client.ts +3 -3
- package/src/lib/page-audit-input.ts +1 -1
- package/src/lib/page-editor-service.ts +1 -3
- package/src/lib/pages-service.ts +4 -29
- package/src/lib/plan.ts +1 -1
- package/src/lib/post-editor-service.ts +4 -10
- package/src/lib/post-types-service.ts +2 -2
- package/src/lib/posts-service.ts +1 -1
- package/src/lib/preview-link.ts +0 -14
- package/src/lib/rail-width.ts +1 -1
- package/src/lib/reflow-probe.ts +4 -4
- package/src/lib/seo-service.ts +20 -74
- package/src/lib/theme-chrome.ts +1 -1
- package/src/lib/version-history.ts +2 -2
- package/src/lib/workflow-chrome.ts +3 -3
- package/src/views/Login.tsx +1 -1
- package/src/views/MediaBrowser.tsx +3 -2
- package/src/views/PageEditor.tsx +1 -1
- package/src/views/Pages/PagesListView.tsx +1 -1
- package/src/views/Pages.tsx +1 -1
- package/src/views/Redirects.tsx +1 -1
- package/src/views/page-editor/section-types.ts +0 -9
- package/src/views/page-editor/sections/admin-renderers.tsx +1 -1
- package/src/views/page-editor/theme-chrome/index.ts +2 -10
- package/src/views/page-editor/viewports.ts +0 -3
- package/src/views/settings/AISettingsTab.tsx +15 -3
- package/src/views/settings/BrandVoiceCard.tsx +11 -1
- package/src/views/settings/brand-voice/BrandVoiceAlignmentPanel.tsx +3 -1
- package/src/views/settings/featureModel.ts +2 -2
- package/src/views/settings/useAiSettings.ts +8 -3
- package/src/views/settings/useAppearanceSettings.ts +4 -6
- package/src/views/settings/useEmailSettings.ts +2 -2
- package/src/views/settings/useGeneralSettings.ts +5 -10
- package/src/views/settings/useSeoSettings.ts +1 -1
- package/src/views/settings/useUpdates.ts +2 -2
- package/dist/components/ContentOverviewChart.d.ts +0 -8
- package/dist/components/ContentOverviewChart.d.ts.map +0 -1
- package/dist/components/ContentOverviewChart.js +0 -20
- package/dist/components/ContentOverviewChart.js.map +0 -1
- package/dist/components/SEOPerformance.d.ts +0 -5
- package/dist/components/SEOPerformance.d.ts.map +0 -1
- package/dist/components/SEOPerformance.js +0 -29
- package/dist/components/SEOPerformance.js.map +0 -1
- package/dist/components/ui/Avatar.d.ts +0 -9
- package/dist/components/ui/Avatar.d.ts.map +0 -1
- package/dist/components/ui/Avatar.js +0 -21
- package/dist/components/ui/Avatar.js.map +0 -1
- package/dist/components/ui/CommandPalette.d.ts +0 -14
- package/dist/components/ui/CommandPalette.d.ts.map +0 -1
- package/dist/components/ui/CommandPalette.js +0 -58
- package/dist/components/ui/CommandPalette.js.map +0 -1
- package/dist/components/ui/DataTable.d.ts +0 -30
- package/dist/components/ui/DataTable.d.ts.map +0 -1
- package/dist/components/ui/DataTable.js +0 -44
- package/dist/components/ui/DataTable.js.map +0 -1
- package/dist/components/ui/Pagination.d.ts +0 -9
- package/dist/components/ui/Pagination.d.ts.map +0 -1
- package/dist/components/ui/Pagination.js +0 -26
- package/dist/components/ui/Pagination.js.map +0 -1
- package/dist/components/ui/Select.d.ts +0 -16
- package/dist/components/ui/Select.d.ts.map +0 -1
- package/dist/components/ui/Select.js +0 -24
- package/dist/components/ui/Select.js.map +0 -1
- package/dist/components/ui/Toast.d.ts +0 -18
- package/dist/components/ui/Toast.d.ts.map +0 -1
- package/dist/components/ui/Toast.js +0 -29
- package/dist/components/ui/Toast.js.map +0 -1
- package/dist/components/ui/index.d.ts +0 -46
- package/dist/components/ui/index.d.ts.map +0 -1
- package/dist/components/ui/index.js +0 -24
- package/dist/components/ui/index.js.map +0 -1
- package/dist/hooks/useContentLock.d.ts +0 -12
- package/dist/hooks/useContentLock.d.ts.map +0 -1
- package/dist/hooks/useContentLock.js +0 -38
- package/dist/hooks/useContentLock.js.map +0 -1
- package/dist/hooks/useDebounce.d.ts +0 -2
- package/dist/hooks/useDebounce.d.ts.map +0 -1
- package/dist/hooks/useDebounce.js +0 -11
- package/dist/hooks/useDebounce.js.map +0 -1
- package/src/components/ContentOverviewChart.tsx +0 -75
- package/src/components/SEOPerformance.tsx +0 -163
- package/src/components/ui/Avatar.tsx +0 -42
- package/src/components/ui/CommandPalette.tsx +0 -133
- package/src/components/ui/DataTable.tsx +0 -204
- package/src/components/ui/Pagination.tsx +0 -94
- package/src/components/ui/Select.tsx +0 -53
- package/src/components/ui/Toast.tsx +0 -72
- package/src/components/ui/index.ts +0 -61
- package/src/hooks/useContentLock.ts +0 -55
- package/src/hooks/useDebounce.ts +0 -14
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
interface ContentLock {
|
|
2
|
-
lockedBy: string | null;
|
|
3
|
-
lockedAt: Date | null;
|
|
4
|
-
isLocked: boolean;
|
|
5
|
-
isLockedByMe: boolean;
|
|
6
|
-
}
|
|
7
|
-
export declare function useContentLock(documentId: string | undefined, userId: string): ContentLock & {
|
|
8
|
-
acquireLock: () => Promise<boolean>;
|
|
9
|
-
releaseLock: () => Promise<void>;
|
|
10
|
-
};
|
|
11
|
-
export {};
|
|
12
|
-
//# sourceMappingURL=useContentLock.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"useContentLock.d.ts","sourceRoot":"","sources":["../../src/hooks/useContentLock.ts"],"names":[],"mappings":"AAIA,UAAU,WAAW;IACnB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;IACvB,QAAQ,EAAE,IAAI,GAAG,IAAI,CAAA;IACrB,QAAQ,EAAE,OAAO,CAAA;IACjB,YAAY,EAAE,OAAO,CAAA;CACtB;AAED,wBAAgB,cAAc,CAC5B,UAAU,EAAE,MAAM,GAAG,SAAS,EAC9B,MAAM,EAAE,MAAM,GACb,WAAW,GAAG;IACf,WAAW,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAA;IACnC,WAAW,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;CACjC,CAqCA"}
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
import { useState, useEffect, useCallback } from 'react';
|
|
3
|
-
export function useContentLock(documentId, userId) {
|
|
4
|
-
const [lock, setLock] = useState({
|
|
5
|
-
lockedBy: null,
|
|
6
|
-
lockedAt: null,
|
|
7
|
-
isLocked: false,
|
|
8
|
-
isLockedByMe: false,
|
|
9
|
-
});
|
|
10
|
-
const acquireLock = useCallback(async () => {
|
|
11
|
-
if (!documentId)
|
|
12
|
-
return false;
|
|
13
|
-
setLock({
|
|
14
|
-
lockedBy: userId,
|
|
15
|
-
lockedAt: new Date(),
|
|
16
|
-
isLocked: true,
|
|
17
|
-
isLockedByMe: true,
|
|
18
|
-
});
|
|
19
|
-
return true;
|
|
20
|
-
}, [documentId, userId]);
|
|
21
|
-
const releaseLock = useCallback(async () => {
|
|
22
|
-
setLock({
|
|
23
|
-
lockedBy: null,
|
|
24
|
-
lockedAt: null,
|
|
25
|
-
isLocked: false,
|
|
26
|
-
isLockedByMe: false,
|
|
27
|
-
});
|
|
28
|
-
}, []);
|
|
29
|
-
useEffect(() => {
|
|
30
|
-
return () => {
|
|
31
|
-
if (lock.isLockedByMe) {
|
|
32
|
-
releaseLock();
|
|
33
|
-
}
|
|
34
|
-
};
|
|
35
|
-
}, [lock.isLockedByMe, releaseLock]);
|
|
36
|
-
return { ...lock, acquireLock, releaseLock };
|
|
37
|
-
}
|
|
38
|
-
//# sourceMappingURL=useContentLock.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"useContentLock.js","sourceRoot":"","sources":["../../src/hooks/useContentLock.ts"],"names":[],"mappings":"AAAA,YAAY,CAAA;AAEZ,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,OAAO,CAAA;AASxD,MAAM,UAAU,cAAc,CAC5B,UAA8B,EAC9B,MAAc;IAKd,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,QAAQ,CAAc;QAC5C,QAAQ,EAAE,IAAI;QACd,QAAQ,EAAE,IAAI;QACd,QAAQ,EAAE,KAAK;QACf,YAAY,EAAE,KAAK;KACpB,CAAC,CAAA;IAEF,MAAM,WAAW,GAAG,WAAW,CAAC,KAAK,IAAI,EAAE;QACzC,IAAI,CAAC,UAAU;YAAE,OAAO,KAAK,CAAA;QAC7B,OAAO,CAAC;YACN,QAAQ,EAAE,MAAM;YAChB,QAAQ,EAAE,IAAI,IAAI,EAAE;YACpB,QAAQ,EAAE,IAAI;YACd,YAAY,EAAE,IAAI;SACnB,CAAC,CAAA;QACF,OAAO,IAAI,CAAA;IACb,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC,CAAA;IAExB,MAAM,WAAW,GAAG,WAAW,CAAC,KAAK,IAAI,EAAE;QACzC,OAAO,CAAC;YACN,QAAQ,EAAE,IAAI;YACd,QAAQ,EAAE,IAAI;YACd,QAAQ,EAAE,KAAK;YACf,YAAY,EAAE,KAAK;SACpB,CAAC,CAAA;IACJ,CAAC,EAAE,EAAE,CAAC,CAAA;IAEN,SAAS,CAAC,GAAG,EAAE;QACb,OAAO,GAAG,EAAE;YACV,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;gBACtB,WAAW,EAAE,CAAA;YACf,CAAC;QACH,CAAC,CAAA;IACH,CAAC,EAAE,CAAC,IAAI,CAAC,YAAY,EAAE,WAAW,CAAC,CAAC,CAAA;IAEpC,OAAO,EAAE,GAAG,IAAI,EAAE,WAAW,EAAE,WAAW,EAAE,CAAA;AAC9C,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"useDebounce.d.ts","sourceRoot":"","sources":["../../src/hooks/useDebounce.ts"],"names":[],"mappings":"AAIA,wBAAgB,WAAW,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,MAAM,GAAG,CAAC,CAS3D"}
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
import { useState, useEffect } from 'react';
|
|
3
|
-
export function useDebounce(value, delayMs) {
|
|
4
|
-
const [debouncedValue, setDebouncedValue] = useState(value);
|
|
5
|
-
useEffect(() => {
|
|
6
|
-
const timer = setTimeout(() => setDebouncedValue(value), delayMs);
|
|
7
|
-
return () => clearTimeout(timer);
|
|
8
|
-
}, [value, delayMs]);
|
|
9
|
-
return debouncedValue;
|
|
10
|
-
}
|
|
11
|
-
//# sourceMappingURL=useDebounce.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"useDebounce.js","sourceRoot":"","sources":["../../src/hooks/useDebounce.ts"],"names":[],"mappings":"AAAA,YAAY,CAAA;AAEZ,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAE3C,MAAM,UAAU,WAAW,CAAI,KAAQ,EAAE,OAAe;IACtD,MAAM,CAAC,cAAc,EAAE,iBAAiB,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAA;IAE3D,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,iBAAiB,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC,CAAA;QACjE,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,KAAK,CAAC,CAAA;IAClC,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC,CAAA;IAEpB,OAAO,cAAc,CAAA;AACvB,CAAC"}
|
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
'use client'
|
|
2
|
-
|
|
3
|
-
import { PieChart, Pie, Cell, ResponsiveContainer } from 'recharts'
|
|
4
|
-
|
|
5
|
-
interface ContentOverviewChartProps {
|
|
6
|
-
published: number
|
|
7
|
-
drafts: number
|
|
8
|
-
scheduled: number
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
const COLORS = ['#22c55e', '#f59e0b', '#a855f7']
|
|
12
|
-
|
|
13
|
-
export function ContentOverviewChart({ published, drafts, scheduled }: ContentOverviewChartProps) {
|
|
14
|
-
const total = published + drafts + scheduled
|
|
15
|
-
const data = [
|
|
16
|
-
{ name: 'Published', value: published },
|
|
17
|
-
{ name: 'Drafts', value: drafts },
|
|
18
|
-
{ name: 'Scheduled', value: scheduled },
|
|
19
|
-
]
|
|
20
|
-
|
|
21
|
-
if (total === 0) {
|
|
22
|
-
return (
|
|
23
|
-
<div className="text-muted-foreground flex h-full items-center justify-center text-sm">
|
|
24
|
-
No content yet
|
|
25
|
-
</div>
|
|
26
|
-
)
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
return (
|
|
30
|
-
<div className="flex items-center gap-6">
|
|
31
|
-
<div className="h-36 w-36 shrink-0">
|
|
32
|
-
<ResponsiveContainer width="100%" height="100%">
|
|
33
|
-
<PieChart>
|
|
34
|
-
<Pie
|
|
35
|
-
data={data}
|
|
36
|
-
cx="50%"
|
|
37
|
-
cy="50%"
|
|
38
|
-
innerRadius={38}
|
|
39
|
-
outerRadius={65}
|
|
40
|
-
dataKey="value"
|
|
41
|
-
strokeWidth={2}
|
|
42
|
-
stroke="#fff"
|
|
43
|
-
>
|
|
44
|
-
{data.map((_, idx) => (
|
|
45
|
-
<Cell key={idx} fill={COLORS[idx]} />
|
|
46
|
-
))}
|
|
47
|
-
</Pie>
|
|
48
|
-
</PieChart>
|
|
49
|
-
</ResponsiveContainer>
|
|
50
|
-
</div>
|
|
51
|
-
<div className="space-y-3">
|
|
52
|
-
{data.map((entry, idx) => {
|
|
53
|
-
const pct = total > 0 ? Math.round((entry.value / total) * 100) : 0
|
|
54
|
-
return (
|
|
55
|
-
<div key={entry.name} className="flex items-center gap-3">
|
|
56
|
-
<span
|
|
57
|
-
className="h-2.5 w-2.5 shrink-0 rounded-full"
|
|
58
|
-
style={{ backgroundColor: COLORS[idx] }}
|
|
59
|
-
/>
|
|
60
|
-
<div className="min-w-0">
|
|
61
|
-
<span className="text-foreground text-sm">{entry.name}</span>
|
|
62
|
-
<div className="flex items-baseline gap-2">
|
|
63
|
-
<span className="text-foreground text-lg font-medium">
|
|
64
|
-
{entry.value.toLocaleString()}
|
|
65
|
-
</span>
|
|
66
|
-
<span className="text-muted-foreground text-xs">{pct}%</span>
|
|
67
|
-
</div>
|
|
68
|
-
</div>
|
|
69
|
-
</div>
|
|
70
|
-
)
|
|
71
|
-
})}
|
|
72
|
-
</div>
|
|
73
|
-
</div>
|
|
74
|
-
)
|
|
75
|
-
}
|
|
@@ -1,163 +0,0 @@
|
|
|
1
|
-
'use client'
|
|
2
|
-
|
|
3
|
-
import {
|
|
4
|
-
Search,
|
|
5
|
-
AlertTriangle,
|
|
6
|
-
FileWarning,
|
|
7
|
-
ImageOff,
|
|
8
|
-
LinkIcon,
|
|
9
|
-
ChevronLeft,
|
|
10
|
-
ChevronRight,
|
|
11
|
-
} from 'lucide-react'
|
|
12
|
-
import { useState } from 'react'
|
|
13
|
-
import { gradeFromScore, gradeMeta } from './seo/primitives.js'
|
|
14
|
-
import { useApiData } from '../lib/useApiData.js'
|
|
15
|
-
|
|
16
|
-
interface SEOSummary {
|
|
17
|
-
totalPages: number
|
|
18
|
-
issuesSummary: {
|
|
19
|
-
missingMetaDescriptions: number
|
|
20
|
-
brokenInternalLinks: number
|
|
21
|
-
missingAltText: number
|
|
22
|
-
}
|
|
23
|
-
topContent: { id: string; title: string; collection: string; score: number }[]
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* The bands and their colours both come from the SEO primitives — this used to
|
|
28
|
-
* restate 80/60 twice on adjacent lines, and `gradeMeta` already returns
|
|
29
|
-
* exactly the token classes it was hand-writing.
|
|
30
|
-
*/
|
|
31
|
-
function ScoreBadge({ score }: { score: number }) {
|
|
32
|
-
const { text: color, bg } = gradeMeta(gradeFromScore(score))
|
|
33
|
-
return (
|
|
34
|
-
<span
|
|
35
|
-
className={`inline-flex h-9 w-9 items-center justify-center rounded-full text-sm font-medium ${color} ${bg}`}
|
|
36
|
-
>
|
|
37
|
-
{score}
|
|
38
|
-
</span>
|
|
39
|
-
)
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
export interface SEOPerformanceProps {
|
|
43
|
-
onNavigate?: (path: string) => void
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
export function SEOPerformance({ onNavigate }: SEOPerformanceProps) {
|
|
47
|
-
const { data, loading, error } = useApiData<SEOSummary>('/seo/summary')
|
|
48
|
-
const [page, setPage] = useState(0)
|
|
49
|
-
const perPage = 5
|
|
50
|
-
|
|
51
|
-
if (loading || error || !data) return null
|
|
52
|
-
|
|
53
|
-
const issues = data.issuesSummary
|
|
54
|
-
const totalIssues =
|
|
55
|
-
issues.missingMetaDescriptions + issues.brokenInternalLinks + issues.missingAltText
|
|
56
|
-
const topContent = data.topContent ?? []
|
|
57
|
-
const totalPages = Math.max(1, Math.ceil(topContent.length / perPage))
|
|
58
|
-
const visible = topContent.slice(page * perPage, (page + 1) * perPage)
|
|
59
|
-
|
|
60
|
-
return (
|
|
61
|
-
<div className="border-border bg-card rounded-lg border">
|
|
62
|
-
<div className="border-border flex items-center justify-between border-b p-4">
|
|
63
|
-
<div className="flex items-center gap-2">
|
|
64
|
-
<Search className="text-muted-foreground h-4 w-4" />
|
|
65
|
-
<h2 className="text-foreground text-sm font-medium">SEO Performance</h2>
|
|
66
|
-
</div>
|
|
67
|
-
{totalIssues > 0 && (
|
|
68
|
-
<span className="text-muted-foreground text-xs">
|
|
69
|
-
{totalIssues} issue{totalIssues !== 1 ? 's' : ''} found
|
|
70
|
-
</span>
|
|
71
|
-
)}
|
|
72
|
-
</div>
|
|
73
|
-
|
|
74
|
-
<div className="divide-border grid grid-cols-1 divide-y lg:grid-cols-12 lg:divide-x lg:divide-y-0">
|
|
75
|
-
<div className="p-4 lg:col-span-7">
|
|
76
|
-
<h3 className="text-foreground mb-3 text-sm font-medium">Top Performing Content</h3>
|
|
77
|
-
<div className="space-y-2">
|
|
78
|
-
{visible.map((item) => (
|
|
79
|
-
<div key={item.id} className="flex items-center justify-between py-2">
|
|
80
|
-
<div className="mr-3 min-w-0 flex-1">
|
|
81
|
-
<p className="text-foreground truncate text-sm font-medium">{item.title}</p>
|
|
82
|
-
<p className="text-muted-foreground text-xs capitalize">{item.collection}</p>
|
|
83
|
-
</div>
|
|
84
|
-
<ScoreBadge score={item.score} />
|
|
85
|
-
</div>
|
|
86
|
-
))}
|
|
87
|
-
{visible.length === 0 && (
|
|
88
|
-
<p className="text-muted-foreground py-4 text-center text-sm">
|
|
89
|
-
No published content yet
|
|
90
|
-
</p>
|
|
91
|
-
)}
|
|
92
|
-
</div>
|
|
93
|
-
{topContent.length > perPage && (
|
|
94
|
-
<div className="text-muted-foreground mt-3 flex items-center justify-between border-t border-gray-100 pt-3 text-xs">
|
|
95
|
-
<span>
|
|
96
|
-
Showing {page * perPage + 1}-{Math.min((page + 1) * perPage, topContent.length)} of{' '}
|
|
97
|
-
{topContent.length}
|
|
98
|
-
</span>
|
|
99
|
-
<div className="flex items-center gap-1">
|
|
100
|
-
<button
|
|
101
|
-
onClick={() => setPage(Math.max(0, page - 1))}
|
|
102
|
-
disabled={page === 0}
|
|
103
|
-
className="hover:bg-accent rounded p-1 disabled:opacity-30"
|
|
104
|
-
>
|
|
105
|
-
<ChevronLeft className="h-3.5 w-3.5" />
|
|
106
|
-
</button>
|
|
107
|
-
<span>
|
|
108
|
-
Page {page + 1} of {totalPages}
|
|
109
|
-
</span>
|
|
110
|
-
<button
|
|
111
|
-
onClick={() => setPage(Math.min(totalPages - 1, page + 1))}
|
|
112
|
-
disabled={page >= totalPages - 1}
|
|
113
|
-
className="hover:bg-accent rounded p-1 disabled:opacity-30"
|
|
114
|
-
>
|
|
115
|
-
<ChevronRight className="h-3.5 w-3.5" />
|
|
116
|
-
</button>
|
|
117
|
-
</div>
|
|
118
|
-
</div>
|
|
119
|
-
)}
|
|
120
|
-
</div>
|
|
121
|
-
|
|
122
|
-
<div className="p-4 lg:col-span-5">
|
|
123
|
-
<h3 className="text-foreground mb-3 text-sm font-medium">SEO Issues</h3>
|
|
124
|
-
<div className="space-y-3">
|
|
125
|
-
<div className="flex items-center justify-between">
|
|
126
|
-
<div className="flex items-center gap-2">
|
|
127
|
-
<FileWarning className="h-4 w-4 text-red-400" />
|
|
128
|
-
<span className="text-foreground text-sm">Missing meta descriptions</span>
|
|
129
|
-
</div>
|
|
130
|
-
<span className="text-foreground text-sm font-medium">
|
|
131
|
-
{issues.missingMetaDescriptions}
|
|
132
|
-
</span>
|
|
133
|
-
</div>
|
|
134
|
-
<div className="flex items-center justify-between">
|
|
135
|
-
<div className="flex items-center gap-2">
|
|
136
|
-
<LinkIcon className="h-4 w-4 text-red-400" />
|
|
137
|
-
<span className="text-foreground text-sm">Broken internal links</span>
|
|
138
|
-
</div>
|
|
139
|
-
<span className="text-foreground text-sm font-medium">
|
|
140
|
-
{issues.brokenInternalLinks}
|
|
141
|
-
</span>
|
|
142
|
-
</div>
|
|
143
|
-
<div className="flex items-center justify-between">
|
|
144
|
-
<div className="flex items-center gap-2">
|
|
145
|
-
<ImageOff className="h-4 w-4 text-red-400" />
|
|
146
|
-
<span className="text-foreground text-sm">Missing alt text</span>
|
|
147
|
-
</div>
|
|
148
|
-
<span className="text-foreground text-sm font-medium">{issues.missingAltText}</span>
|
|
149
|
-
</div>
|
|
150
|
-
</div>
|
|
151
|
-
{totalIssues > 0 && (
|
|
152
|
-
<button
|
|
153
|
-
onClick={() => onNavigate?.('/seo')}
|
|
154
|
-
className="text-primary hover:text-primary/80 mt-4 text-sm font-medium"
|
|
155
|
-
>
|
|
156
|
-
View All Issues
|
|
157
|
-
</button>
|
|
158
|
-
)}
|
|
159
|
-
</div>
|
|
160
|
-
</div>
|
|
161
|
-
</div>
|
|
162
|
-
)
|
|
163
|
-
}
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
type AvatarSize = 'sm' | 'md' | 'lg'
|
|
2
|
-
|
|
3
|
-
export interface AvatarProps {
|
|
4
|
-
src?: string | null
|
|
5
|
-
name?: string
|
|
6
|
-
size?: AvatarSize
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
const sizeClasses: Record<AvatarSize, string> = {
|
|
10
|
-
sm: 'h-6 w-6 text-[10px]',
|
|
11
|
-
md: 'h-9 w-9 text-xs',
|
|
12
|
-
lg: 'h-12 w-12 text-sm',
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
function getInitials(name: string): string {
|
|
16
|
-
return name
|
|
17
|
-
.split(' ')
|
|
18
|
-
.map((part) => part.charAt(0))
|
|
19
|
-
.join('')
|
|
20
|
-
.toUpperCase()
|
|
21
|
-
.slice(0, 2)
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
export function Avatar({ src, name = '', size = 'md' }: AvatarProps) {
|
|
25
|
-
if (src) {
|
|
26
|
-
return (
|
|
27
|
-
<img
|
|
28
|
-
src={src}
|
|
29
|
-
alt={name}
|
|
30
|
-
className={`inline-block shrink-0 rounded-full object-cover ${sizeClasses[size]}`}
|
|
31
|
-
/>
|
|
32
|
-
)
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
return (
|
|
36
|
-
<span
|
|
37
|
-
className={`inline-flex shrink-0 items-center justify-center rounded-full bg-[var(--primary)] font-medium text-[var(--primary-foreground)] ${sizeClasses[size]}`}
|
|
38
|
-
>
|
|
39
|
-
{getInitials(name) || '?'}
|
|
40
|
-
</span>
|
|
41
|
-
)
|
|
42
|
-
}
|
|
@@ -1,133 +0,0 @@
|
|
|
1
|
-
'use client'
|
|
2
|
-
|
|
3
|
-
import { useState, useEffect, useRef } from 'react'
|
|
4
|
-
|
|
5
|
-
interface CommandItem {
|
|
6
|
-
id: string
|
|
7
|
-
label: string
|
|
8
|
-
group: string
|
|
9
|
-
onSelect: () => void
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export interface CommandPaletteProps {
|
|
13
|
-
open: boolean
|
|
14
|
-
onClose: () => void
|
|
15
|
-
items: CommandItem[]
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export function CommandPalette({ open, onClose, items }: CommandPaletteProps) {
|
|
19
|
-
const [query, setQuery] = useState('')
|
|
20
|
-
const [activeIndex, setActiveIndex] = useState(0)
|
|
21
|
-
const inputRef = useRef<HTMLInputElement>(null)
|
|
22
|
-
|
|
23
|
-
const filtered = items.filter((item) => item.label.toLowerCase().includes(query.toLowerCase()))
|
|
24
|
-
|
|
25
|
-
const groups = Array.from(new Set(filtered.map((i) => i.group)))
|
|
26
|
-
|
|
27
|
-
useEffect(() => {
|
|
28
|
-
if (open) {
|
|
29
|
-
setQuery('')
|
|
30
|
-
setActiveIndex(0)
|
|
31
|
-
requestAnimationFrame(() => inputRef.current?.focus())
|
|
32
|
-
}
|
|
33
|
-
}, [open])
|
|
34
|
-
|
|
35
|
-
useEffect(() => {
|
|
36
|
-
if (!open) return
|
|
37
|
-
|
|
38
|
-
function handleKey(e: KeyboardEvent) {
|
|
39
|
-
if (e.key === 'Escape') {
|
|
40
|
-
onClose()
|
|
41
|
-
return
|
|
42
|
-
}
|
|
43
|
-
if (e.key === 'ArrowDown') {
|
|
44
|
-
e.preventDefault()
|
|
45
|
-
setActiveIndex((i) => Math.min(i + 1, filtered.length - 1))
|
|
46
|
-
}
|
|
47
|
-
if (e.key === 'ArrowUp') {
|
|
48
|
-
e.preventDefault()
|
|
49
|
-
setActiveIndex((i) => Math.max(i - 1, 0))
|
|
50
|
-
}
|
|
51
|
-
if (e.key === 'Enter' && filtered[activeIndex]) {
|
|
52
|
-
filtered[activeIndex].onSelect()
|
|
53
|
-
onClose()
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
document.addEventListener('keydown', handleKey)
|
|
58
|
-
return () => document.removeEventListener('keydown', handleKey)
|
|
59
|
-
}, [open, onClose, filtered, activeIndex])
|
|
60
|
-
|
|
61
|
-
if (!open) return null
|
|
62
|
-
|
|
63
|
-
let flatIndex = -1
|
|
64
|
-
|
|
65
|
-
return (
|
|
66
|
-
<div className="fixed inset-0 z-[70] flex items-start justify-center pt-[20vh]">
|
|
67
|
-
<div className="fixed inset-0 bg-black/50" onClick={onClose} role="presentation" />
|
|
68
|
-
<div className="relative z-10 w-full max-w-lg overflow-hidden rounded-lg border border-[var(--border)] bg-[var(--popover)] shadow-2xl">
|
|
69
|
-
<div className="flex items-center border-b border-[var(--border)] px-4">
|
|
70
|
-
<svg
|
|
71
|
-
className="mr-2 h-4 w-4 text-[var(--muted-foreground)]"
|
|
72
|
-
fill="none"
|
|
73
|
-
viewBox="0 0 24 24"
|
|
74
|
-
stroke="currentColor"
|
|
75
|
-
strokeWidth={2}
|
|
76
|
-
>
|
|
77
|
-
<path
|
|
78
|
-
strokeLinecap="round"
|
|
79
|
-
strokeLinejoin="round"
|
|
80
|
-
d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"
|
|
81
|
-
/>
|
|
82
|
-
</svg>
|
|
83
|
-
<input
|
|
84
|
-
ref={inputRef}
|
|
85
|
-
type="text"
|
|
86
|
-
value={query}
|
|
87
|
-
onChange={(e) => {
|
|
88
|
-
setQuery(e.target.value)
|
|
89
|
-
setActiveIndex(0)
|
|
90
|
-
}}
|
|
91
|
-
placeholder="Type a command or search..."
|
|
92
|
-
className="flex-1 bg-transparent py-3 text-sm outline-none"
|
|
93
|
-
/>
|
|
94
|
-
</div>
|
|
95
|
-
|
|
96
|
-
<div className="max-h-72 overflow-y-auto py-2">
|
|
97
|
-
{groups.map((group) => (
|
|
98
|
-
<div key={group}>
|
|
99
|
-
<div className="px-4 py-1.5 text-xs font-medium text-[var(--muted-foreground)]">
|
|
100
|
-
{group}
|
|
101
|
-
</div>
|
|
102
|
-
{filtered
|
|
103
|
-
.filter((i) => i.group === group)
|
|
104
|
-
.map((item) => {
|
|
105
|
-
flatIndex++
|
|
106
|
-
const idx = flatIndex
|
|
107
|
-
return (
|
|
108
|
-
<button
|
|
109
|
-
key={item.id}
|
|
110
|
-
onClick={() => {
|
|
111
|
-
item.onSelect()
|
|
112
|
-
onClose()
|
|
113
|
-
}}
|
|
114
|
-
className={`flex w-full px-4 py-2 text-sm ${
|
|
115
|
-
idx === activeIndex ? 'bg-[var(--accent)]' : ''
|
|
116
|
-
}`}
|
|
117
|
-
>
|
|
118
|
-
{item.label}
|
|
119
|
-
</button>
|
|
120
|
-
)
|
|
121
|
-
})}
|
|
122
|
-
</div>
|
|
123
|
-
))}
|
|
124
|
-
{filtered.length === 0 && (
|
|
125
|
-
<p className="px-4 py-6 text-center text-sm text-[var(--muted-foreground)]">
|
|
126
|
-
No results found.
|
|
127
|
-
</p>
|
|
128
|
-
)}
|
|
129
|
-
</div>
|
|
130
|
-
</div>
|
|
131
|
-
</div>
|
|
132
|
-
)
|
|
133
|
-
}
|