@actuate-media/cms-admin 0.9.0 → 0.11.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/dist/AdminRoot.d.ts.map +1 -1
- package/dist/AdminRoot.js +8 -5
- package/dist/AdminRoot.js.map +1 -1
- package/dist/__tests__/layout/primitives.test.d.ts +2 -0
- package/dist/__tests__/layout/primitives.test.d.ts.map +1 -0
- package/dist/__tests__/layout/primitives.test.js +34 -0
- package/dist/__tests__/layout/primitives.test.js.map +1 -0
- package/dist/__tests__/lib/cv.test.d.ts +2 -0
- package/dist/__tests__/lib/cv.test.d.ts.map +1 -0
- package/dist/__tests__/lib/cv.test.js +66 -0
- package/dist/__tests__/lib/cv.test.js.map +1 -0
- package/dist/actuate-admin.css +1 -1
- package/dist/assets/actuate-logo.d.ts +36 -0
- package/dist/assets/actuate-logo.d.ts.map +1 -0
- package/dist/assets/actuate-logo.js +15 -0
- package/dist/assets/actuate-logo.js.map +1 -0
- package/dist/components/Breadcrumbs.js +2 -2
- package/dist/components/CommandPalette.js +10 -10
- package/dist/components/ContentOverviewChart.js +3 -3
- package/dist/components/ErrorBoundary.js +1 -1
- package/dist/components/FocalPointPicker.js +2 -2
- package/dist/components/FolderTree.js +20 -20
- package/dist/components/LivePreview.js +3 -3
- package/dist/components/LocaleSwitcher.js +1 -1
- package/dist/components/MediaPickerModal.js +4 -4
- package/dist/components/PresenceIndicator.js +1 -1
- package/dist/components/SEOConfigPanel.d.ts +2 -0
- package/dist/components/SEOConfigPanel.d.ts.map +1 -0
- package/dist/components/SEOConfigPanel.js +174 -0
- package/dist/components/SEOConfigPanel.js.map +1 -0
- package/dist/components/SEOPanel.js +9 -9
- package/dist/components/SEOPerformance.js +2 -2
- package/dist/components/SchedulePublishDialog.d.ts +18 -0
- package/dist/components/SchedulePublishDialog.d.ts.map +1 -0
- package/dist/components/SchedulePublishDialog.js +106 -0
- package/dist/components/SchedulePublishDialog.js.map +1 -0
- package/dist/components/SharePreviewLinkDialog.d.ts +17 -0
- package/dist/components/SharePreviewLinkDialog.d.ts.map +1 -0
- package/dist/components/SharePreviewLinkDialog.js +83 -0
- package/dist/components/SharePreviewLinkDialog.js.map +1 -0
- package/dist/components/TipTapEditor.js +5 -5
- package/dist/components/VersionHistory.js +2 -2
- package/dist/components/ui/Badge.d.ts +33 -3
- package/dist/components/ui/Badge.d.ts.map +1 -1
- package/dist/components/ui/Badge.js +42 -8
- package/dist/components/ui/Badge.js.map +1 -1
- package/dist/components/ui/Button.d.ts +19 -8
- package/dist/components/ui/Button.d.ts.map +1 -1
- package/dist/components/ui/Button.js +35 -14
- package/dist/components/ui/Button.js.map +1 -1
- package/dist/components/ui/Card.d.ts +26 -0
- package/dist/components/ui/Card.d.ts.map +1 -0
- package/dist/components/ui/Card.js +45 -0
- package/dist/components/ui/Card.js.map +1 -0
- package/dist/components/ui/DataTable.js +1 -1
- package/dist/components/ui/Input.d.ts +15 -0
- package/dist/components/ui/Input.d.ts.map +1 -0
- package/dist/components/ui/Input.js +23 -0
- package/dist/components/ui/Input.js.map +1 -0
- package/dist/components/ui/SearchInput.js +1 -1
- package/dist/components/ui/Select.d.ts +16 -0
- package/dist/components/ui/Select.d.ts.map +1 -0
- package/dist/components/ui/Select.js +25 -0
- package/dist/components/ui/Select.js.map +1 -0
- package/dist/components/ui/Toast.js +1 -1
- package/dist/components/ui/index.d.ts +10 -4
- package/dist/components/ui/index.d.ts.map +1 -1
- package/dist/components/ui/index.js +5 -2
- package/dist/components/ui/index.js.map +1 -1
- package/dist/fields/BlockBuilderField.js +3 -3
- package/dist/fields/DateField.js +1 -1
- package/dist/fields/RelationshipField.js +3 -3
- package/dist/fields/TextField.js +1 -1
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -1
- package/dist/layout/Header.js +1 -1
- package/dist/layout/Layout.d.ts +14 -0
- package/dist/layout/Layout.d.ts.map +1 -1
- package/dist/layout/Layout.js +17 -11
- package/dist/layout/Layout.js.map +1 -1
- package/dist/layout/Sidebar.d.ts.map +1 -1
- package/dist/layout/Sidebar.js +21 -11
- package/dist/layout/Sidebar.js.map +1 -1
- package/dist/layout/primitives/AdminShell.d.ts +43 -0
- package/dist/layout/primitives/AdminShell.d.ts.map +1 -0
- package/dist/layout/primitives/AdminShell.js +51 -0
- package/dist/layout/primitives/AdminShell.js.map +1 -0
- package/dist/layout/primitives/Box.d.ts +19 -0
- package/dist/layout/primitives/Box.d.ts.map +1 -0
- package/dist/layout/primitives/Box.js +12 -0
- package/dist/layout/primitives/Box.js.map +1 -0
- package/dist/layout/primitives/Cluster.d.ts +27 -0
- package/dist/layout/primitives/Cluster.d.ts.map +1 -0
- package/dist/layout/primitives/Cluster.js +37 -0
- package/dist/layout/primitives/Cluster.js.map +1 -0
- package/dist/layout/primitives/Grid.d.ts +45 -0
- package/dist/layout/primitives/Grid.d.ts.map +1 -0
- package/dist/layout/primitives/Grid.js +59 -0
- package/dist/layout/primitives/Grid.js.map +1 -0
- package/dist/layout/primitives/PageContainer.d.ts +36 -0
- package/dist/layout/primitives/PageContainer.d.ts.map +1 -0
- package/dist/layout/primitives/PageContainer.js +41 -0
- package/dist/layout/primitives/PageContainer.js.map +1 -0
- package/dist/layout/primitives/Split.d.ts +34 -0
- package/dist/layout/primitives/Split.d.ts.map +1 -0
- package/dist/layout/primitives/Split.js +27 -0
- package/dist/layout/primitives/Split.js.map +1 -0
- package/dist/layout/primitives/Stack.d.ts +23 -0
- package/dist/layout/primitives/Stack.d.ts.map +1 -0
- package/dist/layout/primitives/Stack.js +34 -0
- package/dist/layout/primitives/Stack.js.map +1 -0
- package/dist/layout/primitives/index.d.ts +30 -0
- package/dist/layout/primitives/index.d.ts.map +1 -0
- package/dist/layout/primitives/index.js +22 -0
- package/dist/layout/primitives/index.js.map +1 -0
- package/dist/layout/primitives/tokens.d.ts +48 -0
- package/dist/layout/primitives/tokens.d.ts.map +1 -0
- package/dist/layout/primitives/tokens.js +54 -0
- package/dist/layout/primitives/tokens.js.map +1 -0
- package/dist/lib/cv.d.ts +53 -0
- package/dist/lib/cv.d.ts.map +1 -0
- package/dist/lib/cv.js +39 -0
- package/dist/lib/cv.js.map +1 -0
- package/dist/views/ApiKeys.d.ts.map +1 -1
- package/dist/views/ApiKeys.js +13 -11
- package/dist/views/ApiKeys.js.map +1 -1
- package/dist/views/CollectionList.js +8 -8
- package/dist/views/Dashboard.d.ts.map +1 -1
- package/dist/views/Dashboard.js +333 -78
- package/dist/views/Dashboard.js.map +1 -1
- package/dist/views/DocumentEdit.d.ts.map +1 -1
- package/dist/views/DocumentEdit.js +17 -5
- package/dist/views/DocumentEdit.js.map +1 -1
- package/dist/views/ForgotPassword.js +2 -2
- package/dist/views/FormEditor.js +5 -5
- package/dist/views/FormSubmissions.js +6 -6
- package/dist/views/Forms.js +2 -2
- package/dist/views/Login.d.ts +16 -1
- package/dist/views/Login.d.ts.map +1 -1
- package/dist/views/Login.js +17 -7
- package/dist/views/Login.js.map +1 -1
- package/dist/views/MediaBrowser.js +16 -16
- package/dist/views/PageEditor.js +2 -2
- package/dist/views/Pages.js +10 -10
- package/dist/views/PostEditor.js +2 -2
- package/dist/views/Posts.js +4 -4
- package/dist/views/Redirects.js +4 -4
- package/dist/views/ResetPassword.js +2 -2
- package/dist/views/SEO.js +6 -6
- package/dist/views/ScriptTagEditor.js +4 -4
- package/dist/views/ScriptTags.js +2 -2
- package/dist/views/Settings.d.ts.map +1 -1
- package/dist/views/Settings.js +9 -8
- package/dist/views/Settings.js.map +1 -1
- package/dist/views/SetupWizard.js +2 -2
- package/dist/views/Users.js +4 -4
- package/dist/views/page-builder/AIBlockAssist.js +1 -1
- package/dist/views/page-builder/AIGenerateDialog.js +10 -10
- package/dist/views/page-builder/BlockEditor.js +10 -10
- package/dist/views/page-builder/BlockPicker.js +4 -4
- package/dist/views/page-builder/BottomBar.js +1 -1
- package/dist/views/page-builder/BuilderToolbar.js +2 -2
- package/dist/views/page-builder/ContextPanel.js +2 -2
- package/dist/views/page-builder/DesignScore.js +9 -9
- package/dist/views/page-builder/NodeSettings.js +8 -8
- package/dist/views/page-builder/PageBuilder.js +3 -3
- package/dist/views/page-builder/PageSettings.js +1 -1
- package/dist/views/page-builder/PageTemplates.js +2 -2
- package/dist/views/page-builder/SEOPanel.js +13 -13
- package/dist/views/page-builder/SavedSections.js +5 -5
- package/dist/views/page-builder/TemplatePicker.js +2 -2
- package/dist/views/page-builder/block-renderers/CTAPreview.js +5 -5
- package/dist/views/page-builder/block-renderers/CardsPreview.js +1 -1
- package/dist/views/page-builder/block-renderers/CodePreview.js +1 -1
- package/dist/views/page-builder/block-renderers/FAQPreview.js +3 -3
- package/dist/views/page-builder/block-renderers/FallbackPreview.js +1 -1
- package/dist/views/page-builder/block-renderers/FormPreview.js +3 -3
- package/dist/views/page-builder/block-renderers/GalleryPreview.js +5 -5
- package/dist/views/page-builder/block-renderers/HeroPreview.js +3 -3
- package/dist/views/page-builder/block-renderers/ImagePreview.js +3 -3
- package/dist/views/page-builder/block-renderers/TextPreview.js +3 -3
- package/dist/views/page-builder/block-renderers/VideoPreview.js +4 -4
- package/dist/views/page-builder/canvas/BlockRenderer.js +1 -1
- package/dist/views/page-builder/canvas/BuilderCanvas.js +3 -3
- package/dist/views/page-builder/canvas/ColumnRenderer.js +2 -2
- package/dist/views/page-builder/canvas/ContainerRenderer.js +2 -2
- package/dist/views/page-builder/canvas/RowRenderer.js +2 -2
- package/dist/views/page-builder/canvas/SectionRenderer.js +2 -2
- package/package.json +6 -2
- package/src/AdminRoot.tsx +21 -11
- package/src/__tests__/layout/primitives.test.ts +37 -0
- package/src/__tests__/lib/cv.test.ts +74 -0
- package/src/assets/actuate-logo.tsx +72 -0
- package/src/components/Breadcrumbs.tsx +6 -6
- package/src/components/CommandPalette.tsx +34 -34
- package/src/components/ContentOverviewChart.tsx +3 -3
- package/src/components/ErrorBoundary.tsx +3 -3
- package/src/components/FocalPointPicker.tsx +4 -4
- package/src/components/FolderTree.tsx +38 -38
- package/src/components/LivePreview.tsx +16 -16
- package/src/components/LocaleSwitcher.tsx +7 -7
- package/src/components/MediaPickerModal.tsx +21 -21
- package/src/components/PresenceIndicator.tsx +2 -2
- package/src/components/SEOConfigPanel.tsx +582 -0
- package/src/components/SEOPanel.tsx +46 -46
- package/src/components/SEOPerformance.tsx +21 -21
- package/src/components/SchedulePublishDialog.tsx +241 -0
- package/src/components/SharePreviewLinkDialog.tsx +227 -0
- package/src/components/TipTapEditor.tsx +33 -33
- package/src/components/VersionHistory.tsx +16 -16
- package/src/components/ui/Badge.tsx +66 -14
- package/src/components/ui/Button.tsx +70 -33
- package/src/components/ui/Card.tsx +101 -0
- package/src/components/ui/DataTable.tsx +1 -1
- package/src/components/ui/Input.tsx +35 -0
- package/src/components/ui/SearchInput.tsx +4 -4
- package/src/components/ui/Select.tsx +56 -0
- package/src/components/ui/Toast.tsx +1 -1
- package/src/components/ui/index.ts +18 -4
- package/src/fields/BlockBuilderField.tsx +3 -3
- package/src/fields/DateField.tsx +1 -1
- package/src/fields/RelationshipField.tsx +10 -10
- package/src/fields/TextField.tsx +1 -1
- package/src/index.ts +32 -0
- package/src/layout/Header.tsx +28 -28
- package/src/layout/Layout.tsx +39 -46
- package/src/layout/Sidebar.tsx +37 -64
- package/src/layout/primitives/AdminShell.tsx +118 -0
- package/src/layout/primitives/Box.tsx +30 -0
- package/src/layout/primitives/Cluster.tsx +74 -0
- package/src/layout/primitives/Grid.tsx +120 -0
- package/src/layout/primitives/PageContainer.tsx +96 -0
- package/src/layout/primitives/Split.tsx +73 -0
- package/src/layout/primitives/Stack.tsx +67 -0
- package/src/layout/primitives/index.ts +36 -0
- package/src/layout/primitives/tokens.ts +76 -0
- package/src/lib/cv.ts +96 -0
- package/src/styles/build-input.css +1 -1
- package/src/views/ApiKeys.tsx +57 -57
- package/src/views/CollectionList.tsx +30 -30
- package/src/views/Dashboard.tsx +737 -186
- package/src/views/DocumentEdit.tsx +90 -10
- package/src/views/ForgotPassword.tsx +18 -18
- package/src/views/FormEditor.tsx +75 -75
- package/src/views/FormSubmissions.tsx +76 -76
- package/src/views/Forms.tsx +27 -27
- package/src/views/Login.tsx +65 -25
- package/src/views/MediaBrowser.tsx +127 -127
- package/src/views/PageEditor.tsx +25 -25
- package/src/views/Pages.tsx +59 -59
- package/src/views/PostEditor.tsx +37 -37
- package/src/views/Posts.tsx +48 -48
- package/src/views/Redirects.tsx +21 -21
- package/src/views/ResetPassword.tsx +28 -28
- package/src/views/SEO.tsx +144 -144
- package/src/views/ScriptTagEditor.tsx +24 -24
- package/src/views/ScriptTags.tsx +10 -10
- package/src/views/Settings.tsx +88 -80
- package/src/views/SetupWizard.tsx +28 -28
- package/src/views/Users.tsx +20 -20
- package/src/views/page-builder/AIBlockAssist.tsx +1 -1
- package/src/views/page-builder/AIGenerateDialog.tsx +63 -63
- package/src/views/page-builder/BlockEditor.tsx +26 -26
- package/src/views/page-builder/BlockPicker.tsx +22 -22
- package/src/views/page-builder/BottomBar.tsx +8 -8
- package/src/views/page-builder/BuilderToolbar.tsx +17 -17
- package/src/views/page-builder/ContextPanel.tsx +3 -3
- package/src/views/page-builder/DesignScore.tsx +21 -21
- package/src/views/page-builder/NodeSettings.tsx +27 -27
- package/src/views/page-builder/PageBuilder.tsx +11 -11
- package/src/views/page-builder/PageSettings.tsx +4 -4
- package/src/views/page-builder/PageTemplates.tsx +18 -18
- package/src/views/page-builder/SEOPanel.tsx +53 -53
- package/src/views/page-builder/SavedSections.tsx +37 -37
- package/src/views/page-builder/TemplatePicker.tsx +17 -17
- package/src/views/page-builder/block-renderers/CTAPreview.tsx +13 -13
- package/src/views/page-builder/block-renderers/CardsPreview.tsx +5 -5
- package/src/views/page-builder/block-renderers/CodePreview.tsx +6 -6
- package/src/views/page-builder/block-renderers/FAQPreview.tsx +13 -13
- package/src/views/page-builder/block-renderers/FallbackPreview.tsx +3 -3
- package/src/views/page-builder/block-renderers/FormPreview.tsx +20 -20
- package/src/views/page-builder/block-renderers/GalleryPreview.tsx +8 -8
- package/src/views/page-builder/block-renderers/HeroPreview.tsx +16 -16
- package/src/views/page-builder/block-renderers/ImagePreview.tsx +4 -4
- package/src/views/page-builder/block-renderers/TextPreview.tsx +14 -14
- package/src/views/page-builder/block-renderers/VideoPreview.tsx +12 -12
- package/src/views/page-builder/canvas/BlockRenderer.tsx +4 -4
- package/src/views/page-builder/canvas/BuilderCanvas.tsx +6 -6
- package/src/views/page-builder/canvas/ColumnRenderer.tsx +3 -3
- package/src/views/page-builder/canvas/ContainerRenderer.tsx +2 -2
- package/src/views/page-builder/canvas/RowRenderer.tsx +2 -2
- package/src/views/page-builder/canvas/SectionRenderer.tsx +2 -2
|
@@ -6,7 +6,7 @@ import { useApiData } from '../lib/useApiData.js';
|
|
|
6
6
|
function ScoreBadge({ score }) {
|
|
7
7
|
const color = score >= 80 ? 'text-green-600' : score >= 60 ? 'text-amber-500' : 'text-red-500';
|
|
8
8
|
const bg = score >= 80 ? 'bg-green-50' : score >= 60 ? 'bg-amber-50' : 'bg-red-50';
|
|
9
|
-
return (_jsx("span", { className: `inline-flex items-center justify-center
|
|
9
|
+
return (_jsx("span", { className: `inline-flex h-9 w-9 items-center justify-center rounded-full text-sm font-semibold ${color} ${bg}`, children: score }));
|
|
10
10
|
}
|
|
11
11
|
export function SEOPerformance({ onNavigate }) {
|
|
12
12
|
const { data, loading, error } = useApiData('/seo/summary');
|
|
@@ -19,6 +19,6 @@ export function SEOPerformance({ onNavigate }) {
|
|
|
19
19
|
const topContent = data.topContent ?? [];
|
|
20
20
|
const totalPages = Math.max(1, Math.ceil(topContent.length / perPage));
|
|
21
21
|
const visible = topContent.slice(page * perPage, (page + 1) * perPage);
|
|
22
|
-
return (_jsxs("div", { className: "
|
|
22
|
+
return (_jsxs("div", { className: "rounded-lg border border-gray-200 bg-white", children: [_jsxs("div", { className: "flex items-center justify-between border-b border-gray-200 p-4", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Search, { className: "h-4 w-4 text-gray-500" }), _jsx("h2", { className: "text-sm font-semibold text-gray-900", children: "SEO Performance" })] }), totalIssues > 0 && (_jsxs("span", { className: "text-xs text-gray-500", children: [totalIssues, " issue", totalIssues !== 1 ? 's' : '', " found"] }))] }), _jsxs("div", { className: "grid grid-cols-1 divide-y divide-gray-200 lg:grid-cols-12 lg:divide-x lg:divide-y-0", children: [_jsxs("div", { className: "p-4 lg:col-span-7", children: [_jsx("h3", { className: "mb-3 text-sm font-medium text-gray-700", children: "Top Performing Content" }), _jsxs("div", { className: "space-y-2", children: [visible.map((item) => (_jsxs("div", { className: "flex items-center justify-between py-2", children: [_jsxs("div", { className: "mr-3 min-w-0 flex-1", children: [_jsx("p", { className: "truncate text-sm font-medium text-gray-900", children: item.title }), _jsx("p", { className: "text-xs text-gray-500 capitalize", children: item.collection })] }), _jsx(ScoreBadge, { score: item.score })] }, item.id))), visible.length === 0 && (_jsx("p", { className: "py-4 text-center text-sm text-gray-400", children: "No published content yet" }))] }), topContent.length > perPage && (_jsxs("div", { className: "mt-3 flex items-center justify-between border-t border-gray-100 pt-3 text-xs text-gray-500", children: [_jsxs("span", { children: ["Showing ", page * perPage + 1, "-", Math.min((page + 1) * perPage, topContent.length), " of", ' ', topContent.length] }), _jsxs("div", { className: "flex items-center gap-1", children: [_jsx("button", { onClick: () => setPage(Math.max(0, page - 1)), disabled: page === 0, className: "rounded p-1 hover:bg-gray-100 disabled:opacity-30", children: _jsx(ChevronLeft, { className: "h-3.5 w-3.5" }) }), _jsxs("span", { children: ["Page ", page + 1, " of ", totalPages] }), _jsx("button", { onClick: () => setPage(Math.min(totalPages - 1, page + 1)), disabled: page >= totalPages - 1, className: "rounded p-1 hover:bg-gray-100 disabled:opacity-30", children: _jsx(ChevronRight, { className: "h-3.5 w-3.5" }) })] })] }))] }), _jsxs("div", { className: "p-4 lg:col-span-5", children: [_jsx("h3", { className: "mb-3 text-sm font-medium text-gray-700", children: "SEO Issues" }), _jsxs("div", { className: "space-y-3", children: [_jsxs("div", { className: "flex items-center justify-between", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(FileWarning, { className: "h-4 w-4 text-red-400" }), _jsx("span", { className: "text-sm text-gray-700", children: "Missing meta descriptions" })] }), _jsx("span", { className: "text-sm font-semibold text-gray-900", children: issues.missingMetaDescriptions })] }), _jsxs("div", { className: "flex items-center justify-between", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(LinkIcon, { className: "h-4 w-4 text-red-400" }), _jsx("span", { className: "text-sm text-gray-700", children: "Broken internal links" })] }), _jsx("span", { className: "text-sm font-semibold text-gray-900", children: issues.brokenInternalLinks })] }), _jsxs("div", { className: "flex items-center justify-between", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(ImageOff, { className: "h-4 w-4 text-red-400" }), _jsx("span", { className: "text-sm text-gray-700", children: "Missing alt text" })] }), _jsx("span", { className: "text-sm font-semibold text-gray-900", children: issues.missingAltText })] })] }), totalIssues > 0 && (_jsx("button", { onClick: () => onNavigate?.('/seo'), className: "mt-4 text-sm font-medium text-blue-600 hover:text-blue-700", children: "View All Issues" }))] })] })] }));
|
|
23
23
|
}
|
|
24
24
|
//# sourceMappingURL=SEOPerformance.js.map
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export interface SchedulePublishDialogProps {
|
|
2
|
+
collectionSlug: string;
|
|
3
|
+
documentId: string;
|
|
4
|
+
/** Existing scheduled publish time, if any. */
|
|
5
|
+
scheduledAt?: string | null;
|
|
6
|
+
/** Existing scheduled unpublish time, if any. */
|
|
7
|
+
scheduledUnpublishAt?: string | null;
|
|
8
|
+
open: boolean;
|
|
9
|
+
onClose: () => void;
|
|
10
|
+
/** Called with the updated schedule fields after a successful save. */
|
|
11
|
+
onScheduled?: (next: {
|
|
12
|
+
status: string;
|
|
13
|
+
scheduledAt: string | null;
|
|
14
|
+
scheduledUnpublishAt: string | null;
|
|
15
|
+
}) => void;
|
|
16
|
+
}
|
|
17
|
+
export declare function SchedulePublishDialog({ collectionSlug, documentId, scheduledAt, scheduledUnpublishAt, open, onClose, onScheduled, }: SchedulePublishDialogProps): import("react/jsx-runtime").JSX.Element | null;
|
|
18
|
+
//# sourceMappingURL=SchedulePublishDialog.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SchedulePublishDialog.d.ts","sourceRoot":"","sources":["../../src/components/SchedulePublishDialog.tsx"],"names":[],"mappings":"AAOA,MAAM,WAAW,0BAA0B;IACzC,cAAc,EAAE,MAAM,CAAA;IACtB,UAAU,EAAE,MAAM,CAAA;IAClB,+CAA+C;IAC/C,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3B,iDAAiD;IACjD,oBAAoB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACpC,IAAI,EAAE,OAAO,CAAA;IACb,OAAO,EAAE,MAAM,IAAI,CAAA;IACnB,uEAAuE;IACvE,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE;QACnB,MAAM,EAAE,MAAM,CAAA;QACd,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;QAC1B,oBAAoB,EAAE,MAAM,GAAG,IAAI,CAAA;KACpC,KAAK,IAAI,CAAA;CACX;AAsBD,wBAAgB,qBAAqB,CAAC,EACpC,cAAc,EACd,UAAU,EACV,WAAW,EACX,oBAAoB,EACpB,IAAI,EACJ,OAAO,EACP,WAAW,GACZ,EAAE,0BAA0B,kDA4L5B"}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useEffect, useState } from 'react';
|
|
4
|
+
import { Calendar, Clock, Loader2, X } from 'lucide-react';
|
|
5
|
+
import { toast } from 'sonner';
|
|
6
|
+
import { cmsApi } from '../lib/api.js';
|
|
7
|
+
/**
|
|
8
|
+
* Convert a Date or ISO string to the `YYYY-MM-DDTHH:mm` shape that the
|
|
9
|
+
* `<input type="datetime-local">` element expects, in the user's local
|
|
10
|
+
* timezone (the input is timezone-naive but we present + parse it as local).
|
|
11
|
+
*/
|
|
12
|
+
function toLocalDateTimeInput(value) {
|
|
13
|
+
if (!value)
|
|
14
|
+
return '';
|
|
15
|
+
const d = typeof value === 'string' ? new Date(value) : value;
|
|
16
|
+
if (Number.isNaN(d.getTime()))
|
|
17
|
+
return '';
|
|
18
|
+
const pad = (n) => String(n).padStart(2, '0');
|
|
19
|
+
return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}T${pad(d.getHours())}:${pad(d.getMinutes())}`;
|
|
20
|
+
}
|
|
21
|
+
/** Round "now + 1 hour" to the next quarter-hour for a friendly default. */
|
|
22
|
+
function defaultScheduleTime() {
|
|
23
|
+
const d = new Date(Date.now() + 60 * 60 * 1000);
|
|
24
|
+
d.setMinutes(Math.ceil(d.getMinutes() / 15) * 15, 0, 0);
|
|
25
|
+
return toLocalDateTimeInput(d);
|
|
26
|
+
}
|
|
27
|
+
export function SchedulePublishDialog({ collectionSlug, documentId, scheduledAt, scheduledUnpublishAt, open, onClose, onScheduled, }) {
|
|
28
|
+
const [publishAt, setPublishAt] = useState('');
|
|
29
|
+
const [unpublishAt, setUnpublishAt] = useState('');
|
|
30
|
+
const [includeUnpublish, setIncludeUnpublish] = useState(false);
|
|
31
|
+
const [saving, setSaving] = useState(false);
|
|
32
|
+
const [cancelling, setCancelling] = useState(false);
|
|
33
|
+
const hasExistingSchedule = Boolean(scheduledAt || scheduledUnpublishAt);
|
|
34
|
+
useEffect(() => {
|
|
35
|
+
if (!open)
|
|
36
|
+
return;
|
|
37
|
+
setPublishAt(scheduledAt ? toLocalDateTimeInput(scheduledAt) : defaultScheduleTime());
|
|
38
|
+
setUnpublishAt(scheduledUnpublishAt ? toLocalDateTimeInput(scheduledUnpublishAt) : '');
|
|
39
|
+
setIncludeUnpublish(Boolean(scheduledUnpublishAt));
|
|
40
|
+
}, [open, scheduledAt, scheduledUnpublishAt]);
|
|
41
|
+
async function handleSave() {
|
|
42
|
+
if (!publishAt && !(includeUnpublish && unpublishAt)) {
|
|
43
|
+
toast.error('Pick a publish or unpublish time');
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
// datetime-local is parsed by the browser as local time; new Date() on
|
|
47
|
+
// that string respects the user's timezone and serialises to a UTC
|
|
48
|
+
// ISO string the server can compare against `Date.now()` cleanly.
|
|
49
|
+
const publishDate = publishAt ? new Date(publishAt) : null;
|
|
50
|
+
const unpublishDate = includeUnpublish && unpublishAt ? new Date(unpublishAt) : null;
|
|
51
|
+
if (publishDate && publishDate.getTime() <= Date.now()) {
|
|
52
|
+
toast.error('Publish time must be in the future');
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
if (unpublishDate && unpublishDate.getTime() <= Date.now()) {
|
|
56
|
+
toast.error('Unpublish time must be in the future');
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
if (publishDate && unpublishDate && unpublishDate <= publishDate) {
|
|
60
|
+
toast.error('Unpublish time must be after publish time');
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
setSaving(true);
|
|
64
|
+
const res = await cmsApi(`/collections/${collectionSlug}/${documentId}/schedule`, {
|
|
65
|
+
method: 'POST',
|
|
66
|
+
body: JSON.stringify({
|
|
67
|
+
scheduledAt: publishDate ? publishDate.toISOString() : null,
|
|
68
|
+
scheduledUnpublishAt: unpublishDate ? unpublishDate.toISOString() : null,
|
|
69
|
+
}),
|
|
70
|
+
});
|
|
71
|
+
setSaving(false);
|
|
72
|
+
if (res.error) {
|
|
73
|
+
toast.error(res.error);
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
toast.success(publishDate ? 'Publish scheduled' : 'Unpublish scheduled');
|
|
77
|
+
onScheduled?.({
|
|
78
|
+
status: res.data?.status ?? 'SCHEDULED',
|
|
79
|
+
scheduledAt: res.data?.scheduledAt ?? (publishDate ? publishDate.toISOString() : null),
|
|
80
|
+
scheduledUnpublishAt: res.data?.scheduledUnpublishAt ?? (unpublishDate ? unpublishDate.toISOString() : null),
|
|
81
|
+
});
|
|
82
|
+
onClose();
|
|
83
|
+
}
|
|
84
|
+
async function handleCancelSchedule() {
|
|
85
|
+
setCancelling(true);
|
|
86
|
+
const res = await cmsApi(`/collections/${collectionSlug}/${documentId}/schedule`, {
|
|
87
|
+
method: 'DELETE',
|
|
88
|
+
});
|
|
89
|
+
setCancelling(false);
|
|
90
|
+
if (res.error) {
|
|
91
|
+
toast.error(res.error);
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
toast.success('Schedule cancelled');
|
|
95
|
+
onScheduled?.({
|
|
96
|
+
status: res.data?.status ?? 'DRAFT',
|
|
97
|
+
scheduledAt: null,
|
|
98
|
+
scheduledUnpublishAt: null,
|
|
99
|
+
});
|
|
100
|
+
onClose();
|
|
101
|
+
}
|
|
102
|
+
if (!open)
|
|
103
|
+
return null;
|
|
104
|
+
return (_jsxs("div", { className: "fixed inset-0 z-50 flex items-center justify-center p-4", children: [_jsx("div", { className: "fixed inset-0 bg-black/40", onClick: onClose }), _jsxs("div", { className: "relative w-full max-w-md rounded-lg bg-white shadow-xl", children: [_jsxs("div", { className: "flex items-center justify-between border-b border-gray-200 px-4 py-3", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Calendar, { className: "h-5 w-5 text-gray-600" }), _jsx("h2", { className: "text-lg font-semibold text-gray-900", children: "Schedule publishing" })] }), _jsx("button", { onClick: onClose, className: "rounded-lg p-1.5 transition-colors hover:bg-gray-100", children: _jsx(X, { className: "h-5 w-5 text-gray-500" }) })] }), _jsxs("div", { className: "space-y-4 px-4 py-4", children: [_jsxs("div", { className: "space-y-1.5", children: [_jsx("label", { className: "text-sm font-medium text-gray-700", children: "Publish at" }), _jsxs("div", { className: "relative", children: [_jsx(Clock, { className: "pointer-events-none absolute top-2.5 left-2.5 h-4 w-4 text-gray-400" }), _jsx("input", { type: "datetime-local", value: publishAt, onChange: (e) => setPublishAt(e.target.value), min: toLocalDateTimeInput(new Date(Date.now() + 60 * 1000)), className: "w-full rounded-md border border-gray-300 bg-white py-2 pr-3 pl-9 text-sm focus:border-blue-500 focus:ring-1 focus:ring-blue-500 focus:outline-none" })] }), _jsx("p", { className: "text-xs text-gray-500", children: "The document will move from DRAFT to PUBLISHED at this time (your local timezone)." })] }), _jsxs("label", { className: "flex items-center gap-2 text-sm text-gray-700", children: [_jsx("input", { type: "checkbox", checked: includeUnpublish, onChange: (e) => setIncludeUnpublish(e.target.checked), className: "h-4 w-4 rounded border-gray-300 text-blue-600 focus:ring-blue-500" }), "Also schedule an unpublish"] }), includeUnpublish && (_jsxs("div", { className: "space-y-1.5", children: [_jsx("label", { className: "text-sm font-medium text-gray-700", children: "Unpublish at" }), _jsxs("div", { className: "relative", children: [_jsx(Clock, { className: "pointer-events-none absolute top-2.5 left-2.5 h-4 w-4 text-gray-400" }), _jsx("input", { type: "datetime-local", value: unpublishAt, onChange: (e) => setUnpublishAt(e.target.value), min: publishAt || toLocalDateTimeInput(new Date(Date.now() + 60 * 1000)), className: "w-full rounded-md border border-gray-300 bg-white py-2 pr-3 pl-9 text-sm focus:border-blue-500 focus:ring-1 focus:ring-blue-500 focus:outline-none" })] })] }))] }), _jsxs("div", { className: "flex items-center justify-between gap-2 border-t border-gray-200 px-4 py-3", children: [hasExistingSchedule ? (_jsxs("button", { onClick: handleCancelSchedule, disabled: cancelling || saving, className: "inline-flex items-center gap-1.5 rounded-md px-3 py-1.5 text-sm font-medium text-red-700 hover:bg-red-50 disabled:opacity-50", children: [cancelling ? (_jsx(Loader2, { className: "h-4 w-4 animate-spin" })) : (_jsx(X, { className: "h-4 w-4" })), "Cancel schedule"] })) : (_jsx("span", {})), _jsxs("div", { className: "flex items-center gap-2", children: [_jsx("button", { onClick: onClose, className: "rounded-md px-3 py-1.5 text-sm text-gray-700 hover:bg-gray-100", children: "Close" }), _jsxs("button", { onClick: handleSave, disabled: saving || cancelling, className: "inline-flex items-center gap-1.5 rounded-md bg-blue-600 px-3 py-1.5 text-sm font-medium text-white hover:bg-blue-700 disabled:opacity-50", children: [saving ? (_jsx(Loader2, { className: "h-4 w-4 animate-spin" })) : (_jsx(Calendar, { className: "h-4 w-4" })), hasExistingSchedule ? 'Reschedule' : 'Schedule'] })] })] })] })] }));
|
|
105
|
+
}
|
|
106
|
+
//# sourceMappingURL=SchedulePublishDialog.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SchedulePublishDialog.js","sourceRoot":"","sources":["../../src/components/SchedulePublishDialog.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export interface SharePreviewLinkDialogProps {
|
|
2
|
+
collectionSlug: string;
|
|
3
|
+
documentId: string;
|
|
4
|
+
/** Document slug, used to build a friendly preview URL. */
|
|
5
|
+
documentSlug?: string | null;
|
|
6
|
+
/**
|
|
7
|
+
* Optional site URL (https://...) to prepend. If omitted we just emit the
|
|
8
|
+
* relative path and ask the admin to share it however they want.
|
|
9
|
+
*/
|
|
10
|
+
siteUrl?: string;
|
|
11
|
+
/** Custom URL prefix for this collection (e.g. /blog). Defaults to slug. */
|
|
12
|
+
urlPrefix?: string;
|
|
13
|
+
open: boolean;
|
|
14
|
+
onClose: () => void;
|
|
15
|
+
}
|
|
16
|
+
export declare function SharePreviewLinkDialog({ collectionSlug, documentId, documentSlug, siteUrl, urlPrefix, open, onClose, }: SharePreviewLinkDialogProps): import("react/jsx-runtime").JSX.Element | null;
|
|
17
|
+
//# sourceMappingURL=SharePreviewLinkDialog.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SharePreviewLinkDialog.d.ts","sourceRoot":"","sources":["../../src/components/SharePreviewLinkDialog.tsx"],"names":[],"mappings":"AAOA,MAAM,WAAW,2BAA2B;IAC1C,cAAc,EAAE,MAAM,CAAA;IACtB,UAAU,EAAE,MAAM,CAAA;IAClB,2DAA2D;IAC3D,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC5B;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,4EAA4E;IAC5E,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,IAAI,EAAE,OAAO,CAAA;IACb,OAAO,EAAE,MAAM,IAAI,CAAA;CACpB;AAyCD,wBAAgB,sBAAsB,CAAC,EACrC,cAAc,EACd,UAAU,EACV,YAAY,EACZ,OAAO,EACP,SAAS,EACT,IAAI,EACJ,OAAO,GACR,EAAE,2BAA2B,kDA4J7B"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useState } from 'react';
|
|
4
|
+
import { Check, Copy, Link2, Loader2, Share2, X } from 'lucide-react';
|
|
5
|
+
import { toast } from 'sonner';
|
|
6
|
+
import { cmsApi } from '../lib/api.js';
|
|
7
|
+
const TTL_CHOICES = [
|
|
8
|
+
{ label: '1 hour', seconds: 60 * 60, hint: 'Quick review' },
|
|
9
|
+
{ label: '1 day', seconds: 24 * 60 * 60, hint: 'Single workday' },
|
|
10
|
+
{ label: '7 days', seconds: 7 * 24 * 60 * 60, hint: 'Client review' },
|
|
11
|
+
{ label: '30 days', seconds: 30 * 24 * 60 * 60, hint: 'Long-running staging' },
|
|
12
|
+
];
|
|
13
|
+
function buildPreviewUrl({ siteUrl, urlPrefix, collectionSlug, documentSlug, token, }) {
|
|
14
|
+
const base = (siteUrl ?? '').replace(/\/+$/, '');
|
|
15
|
+
// Build the same path /resolve would match: <urlPrefix>/<slug>, or
|
|
16
|
+
// /<slug> for top-level page collections. If there's no slug yet we
|
|
17
|
+
// fall back to /admin's preview endpoint as a safety net.
|
|
18
|
+
const slug = documentSlug?.toString().trim() ?? '';
|
|
19
|
+
if (!slug) {
|
|
20
|
+
return `${base}/preview/${collectionSlug}/_?token=${encodeURIComponent(token)}`;
|
|
21
|
+
}
|
|
22
|
+
const prefix = (urlPrefix ?? collectionSlug).replace(/^\/+|\/+$/g, '');
|
|
23
|
+
const path = prefix ? `/${prefix}/${slug}` : `/${slug}`;
|
|
24
|
+
return `${base}${path}?preview=${encodeURIComponent(token)}`;
|
|
25
|
+
}
|
|
26
|
+
export function SharePreviewLinkDialog({ collectionSlug, documentId, documentSlug, siteUrl, urlPrefix, open, onClose, }) {
|
|
27
|
+
const [ttl, setTtl] = useState(TTL_CHOICES[2].seconds);
|
|
28
|
+
const [token, setToken] = useState('');
|
|
29
|
+
const [previewUrl, setPreviewUrl] = useState('');
|
|
30
|
+
const [expiresAt, setExpiresAt] = useState('');
|
|
31
|
+
const [generating, setGenerating] = useState(false);
|
|
32
|
+
const [copied, setCopied] = useState(false);
|
|
33
|
+
async function generate() {
|
|
34
|
+
setGenerating(true);
|
|
35
|
+
const res = await cmsApi('/preview/token', {
|
|
36
|
+
method: 'POST',
|
|
37
|
+
body: JSON.stringify({
|
|
38
|
+
collection: collectionSlug,
|
|
39
|
+
documentId,
|
|
40
|
+
ttlSeconds: ttl,
|
|
41
|
+
}),
|
|
42
|
+
});
|
|
43
|
+
setGenerating(false);
|
|
44
|
+
if (res.error || !res.data) {
|
|
45
|
+
toast.error(res.error ?? 'Failed to create preview token');
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
const data = res.data;
|
|
49
|
+
setToken(data.token);
|
|
50
|
+
setExpiresAt(data.expiresAt ?? '');
|
|
51
|
+
const url = buildPreviewUrl({
|
|
52
|
+
siteUrl,
|
|
53
|
+
urlPrefix,
|
|
54
|
+
collectionSlug,
|
|
55
|
+
documentSlug: data.slug ?? documentSlug,
|
|
56
|
+
token: data.token,
|
|
57
|
+
});
|
|
58
|
+
setPreviewUrl(url);
|
|
59
|
+
setCopied(false);
|
|
60
|
+
}
|
|
61
|
+
async function copyToClipboard() {
|
|
62
|
+
if (!previewUrl)
|
|
63
|
+
return;
|
|
64
|
+
try {
|
|
65
|
+
await navigator.clipboard.writeText(previewUrl);
|
|
66
|
+
setCopied(true);
|
|
67
|
+
toast.success('Preview link copied');
|
|
68
|
+
setTimeout(() => setCopied(false), 2000);
|
|
69
|
+
}
|
|
70
|
+
catch {
|
|
71
|
+
toast.error("Couldn't copy to clipboard");
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
if (!open)
|
|
75
|
+
return null;
|
|
76
|
+
return (_jsxs("div", { className: "fixed inset-0 z-50 flex items-center justify-center p-4", children: [_jsx("div", { className: "fixed inset-0 bg-black/40", onClick: onClose }), _jsxs("div", { className: "relative w-full max-w-lg rounded-lg bg-white shadow-xl", children: [_jsxs("div", { className: "flex items-center justify-between border-b border-gray-200 px-4 py-3", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Share2, { className: "h-5 w-5 text-gray-600" }), _jsx("h2", { className: "text-lg font-semibold text-gray-900", children: "Share preview link" })] }), _jsx("button", { onClick: onClose, className: "rounded-lg p-1.5 transition-colors hover:bg-gray-100", children: _jsx(X, { className: "h-5 w-5 text-gray-500" }) })] }), _jsxs("div", { className: "space-y-4 px-4 py-4", children: [_jsx("p", { className: "text-sm text-gray-600", children: "Generate a signed URL that lets anyone with the link view the current draft of this document \u2014 even if it's never been published." }), _jsxs("div", { className: "space-y-2", children: [_jsx("label", { className: "text-sm font-medium text-gray-700", children: "Link lifetime" }), _jsx("div", { className: "grid grid-cols-2 gap-2", children: TTL_CHOICES.map((choice) => {
|
|
77
|
+
const selected = ttl === choice.seconds;
|
|
78
|
+
return (_jsxs("button", { onClick: () => setTtl(choice.seconds), className: `rounded-md border px-3 py-2 text-left text-sm transition-colors ${selected
|
|
79
|
+
? 'border-blue-500 bg-blue-50 text-blue-900'
|
|
80
|
+
: 'border-gray-200 hover:border-gray-300 hover:bg-gray-50'}`, children: [_jsx("div", { className: "font-medium", children: choice.label }), _jsx("div", { className: "text-xs text-gray-500", children: choice.hint })] }, choice.seconds));
|
|
81
|
+
}) }), _jsx("p", { className: "text-xs text-gray-500", children: "Preview tokens can't be revoked individually \u2014 pick the shortest TTL that fits." })] }), previewUrl ? (_jsxs("div", { className: "space-y-2 rounded-lg border border-gray-200 bg-gray-50 p-3", children: [_jsx("label", { className: "text-xs font-medium tracking-wide text-gray-500 uppercase", children: "Preview URL" }), _jsxs("div", { className: "flex items-stretch gap-2", children: [_jsx("input", { readOnly: true, value: previewUrl, onFocus: (e) => e.currentTarget.select(), className: "flex-1 rounded-md border border-gray-300 bg-white px-2 py-1.5 font-mono text-xs" }), _jsxs("button", { onClick: copyToClipboard, className: "inline-flex items-center gap-1.5 rounded-md bg-gray-900 px-3 py-1.5 text-xs font-medium text-white hover:bg-gray-700", children: [copied ? _jsx(Check, { className: "h-3.5 w-3.5" }) : _jsx(Copy, { className: "h-3.5 w-3.5" }), copied ? 'Copied' : 'Copy'] })] }), expiresAt && (_jsxs("p", { className: "text-xs text-gray-500", children: ["Expires ", new Date(expiresAt).toLocaleString()] }))] })) : null] }), _jsxs("div", { className: "flex items-center justify-end gap-2 border-t border-gray-200 px-4 py-3", children: [_jsx("button", { onClick: onClose, className: "rounded-md px-3 py-1.5 text-sm text-gray-700 hover:bg-gray-100", children: "Close" }), _jsxs("button", { onClick: generate, disabled: generating, className: "inline-flex items-center gap-1.5 rounded-md bg-blue-600 px-3 py-1.5 text-sm font-medium text-white hover:bg-blue-700 disabled:opacity-50", children: [generating ? (_jsx(Loader2, { className: "h-4 w-4 animate-spin" })) : (_jsx(Link2, { className: "h-4 w-4" })), previewUrl ? 'Generate new link' : 'Generate link'] })] })] })] }));
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=SharePreviewLinkDialog.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SharePreviewLinkDialog.js","sourceRoot":"","sources":["../../src/components/SharePreviewLinkDialog.tsx"],"names":[],"mappings":"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"}
|
|
@@ -98,12 +98,12 @@ const editorStyles = `
|
|
|
98
98
|
}
|
|
99
99
|
`;
|
|
100
100
|
function ToolbarButton({ onClick, isActive = false, disabled = false, title, children, }) {
|
|
101
|
-
return (_jsx("button", { type: "button", onClick: onClick, disabled: disabled, title: title, className: `p-1.5
|
|
101
|
+
return (_jsx("button", { type: "button", onClick: onClick, disabled: disabled, title: title, className: `rounded p-1.5 transition-colors ${isActive
|
|
102
102
|
? 'bg-blue-100 text-blue-700'
|
|
103
|
-
: 'text-gray-600 hover:bg-gray-100 hover:text-gray-900'} ${disabled ? '
|
|
103
|
+
: 'text-gray-600 hover:bg-gray-100 hover:text-gray-900'} ${disabled ? 'cursor-not-allowed opacity-40' : ''}`, children: children }));
|
|
104
104
|
}
|
|
105
105
|
function Divider() {
|
|
106
|
-
return _jsx("div", { className: "
|
|
106
|
+
return _jsx("div", { className: "mx-1 h-6 w-px bg-gray-200" });
|
|
107
107
|
}
|
|
108
108
|
function Toolbar({ editor, onOpenMediaPicker }) {
|
|
109
109
|
const addLink = () => {
|
|
@@ -121,7 +121,7 @@ function Toolbar({ editor, onOpenMediaPicker }) {
|
|
|
121
121
|
editor.chain().focus().insertTable({ rows: 3, cols: 3, withHeaderRow: true }).run();
|
|
122
122
|
};
|
|
123
123
|
const isInTable = editor.isActive('table');
|
|
124
|
-
return (_jsxs("div", { className: "
|
|
124
|
+
return (_jsxs("div", { className: "sticky top-0 z-10 flex flex-wrap items-center gap-0.5 border-b border-gray-200 bg-gray-50 p-2", children: [_jsx(ToolbarButton, { onClick: () => editor.chain().focus().toggleBold().run(), isActive: editor.isActive('bold'), title: "Bold (Ctrl+B)", children: _jsx(Bold, { className: "h-4 w-4" }) }), _jsx(ToolbarButton, { onClick: () => editor.chain().focus().toggleItalic().run(), isActive: editor.isActive('italic'), title: "Italic (Ctrl+I)", children: _jsx(Italic, { className: "h-4 w-4" }) }), _jsx(ToolbarButton, { onClick: () => editor.chain().focus().toggleUnderline().run(), isActive: editor.isActive('underline'), title: "Underline (Ctrl+U)", children: _jsx(Underline, { className: "h-4 w-4" }) }), _jsx(ToolbarButton, { onClick: () => editor.chain().focus().toggleStrike().run(), isActive: editor.isActive('strike'), title: "Strikethrough", children: _jsx(Strikethrough, { className: "h-4 w-4" }) }), _jsx(ToolbarButton, { onClick: () => editor.chain().focus().toggleCode().run(), isActive: editor.isActive('code'), title: "Inline code", children: _jsx(Code, { className: "h-4 w-4" }) }), _jsx(Divider, {}), _jsx(ToolbarButton, { onClick: () => editor.chain().focus().toggleHeading({ level: 1 }).run(), isActive: editor.isActive('heading', { level: 1 }), title: "Heading 1", children: _jsx(Heading1, { className: "h-4 w-4" }) }), _jsx(ToolbarButton, { onClick: () => editor.chain().focus().toggleHeading({ level: 2 }).run(), isActive: editor.isActive('heading', { level: 2 }), title: "Heading 2", children: _jsx(Heading2, { className: "h-4 w-4" }) }), _jsx(ToolbarButton, { onClick: () => editor.chain().focus().toggleHeading({ level: 3 }).run(), isActive: editor.isActive('heading', { level: 3 }), title: "Heading 3", children: _jsx(Heading3, { className: "h-4 w-4" }) }), _jsx(Divider, {}), _jsx(ToolbarButton, { onClick: () => editor.chain().focus().toggleBulletList().run(), isActive: editor.isActive('bulletList'), title: "Bullet list", children: _jsx(List, { className: "h-4 w-4" }) }), _jsx(ToolbarButton, { onClick: () => editor.chain().focus().toggleOrderedList().run(), isActive: editor.isActive('orderedList'), title: "Ordered list", children: _jsx(ListOrdered, { className: "h-4 w-4" }) }), _jsx(ToolbarButton, { onClick: () => editor.chain().focus().toggleBlockquote().run(), isActive: editor.isActive('blockquote'), title: "Blockquote", children: _jsx(Quote, { className: "h-4 w-4" }) }), _jsx(ToolbarButton, { onClick: () => editor.chain().focus().toggleCodeBlock().run(), isActive: editor.isActive('codeBlock'), title: "Code block", children: _jsx(FileCode, { className: "h-4 w-4" }) }), _jsx(ToolbarButton, { onClick: () => editor.chain().focus().setHorizontalRule().run(), title: "Horizontal rule", children: _jsx(Minus, { className: "h-4 w-4" }) }), _jsx(Divider, {}), _jsx(ToolbarButton, { onClick: () => editor.chain().focus().setTextAlign('left').run(), isActive: editor.isActive({ textAlign: 'left' }), title: "Align left", children: _jsx(AlignLeft, { className: "h-4 w-4" }) }), _jsx(ToolbarButton, { onClick: () => editor.chain().focus().setTextAlign('center').run(), isActive: editor.isActive({ textAlign: 'center' }), title: "Align center", children: _jsx(AlignCenter, { className: "h-4 w-4" }) }), _jsx(ToolbarButton, { onClick: () => editor.chain().focus().setTextAlign('right').run(), isActive: editor.isActive({ textAlign: 'right' }), title: "Align right", children: _jsx(AlignRight, { className: "h-4 w-4" }) }), _jsx(Divider, {}), _jsx(ToolbarButton, { onClick: addLink, isActive: editor.isActive('link'), title: "Insert link", children: _jsx(LinkIcon, { className: "h-4 w-4" }) }), _jsx(ToolbarButton, { onClick: onOpenMediaPicker, title: "Insert image", children: _jsx(ImageIcon, { className: "h-4 w-4" }) }), _jsx(ToolbarButton, { onClick: insertTable, title: "Insert table (3\u00D73)", children: _jsx(TableIcon, { className: "h-4 w-4" }) }), isInTable && (_jsxs(_Fragment, { children: [_jsx(Divider, {}), _jsx(ToolbarButton, { onClick: () => editor.chain().focus().addColumnBefore().run(), title: "Add column before", children: _jsx(Columns, { className: "h-4 w-4" }) }), _jsx(ToolbarButton, { onClick: () => editor.chain().focus().addColumnAfter().run(), title: "Add column after", children: _jsx(Columns, { className: "h-4 w-4" }) }), _jsx(ToolbarButton, { onClick: () => editor.chain().focus().deleteColumn().run(), title: "Delete column", children: _jsx(Columns, { className: "h-4 w-4" }) }), _jsx(ToolbarButton, { onClick: () => editor.chain().focus().addRowBefore().run(), title: "Add row before", children: _jsx(Rows, { className: "h-4 w-4" }) }), _jsx(ToolbarButton, { onClick: () => editor.chain().focus().addRowAfter().run(), title: "Add row after", children: _jsx(Rows, { className: "h-4 w-4" }) }), _jsx(ToolbarButton, { onClick: () => editor.chain().focus().deleteRow().run(), title: "Delete row", children: _jsx(Rows, { className: "h-4 w-4" }) }), _jsx(ToolbarButton, { onClick: () => editor.chain().focus().deleteTable().run(), title: "Delete table", children: _jsx(Trash2, { className: "h-4 w-4" }) })] })), _jsx(Divider, {}), _jsx(ToolbarButton, { onClick: () => editor.chain().focus().undo().run(), disabled: !editor.can().undo(), title: "Undo", children: _jsx(Undo, { className: "h-4 w-4" }) }), _jsx(ToolbarButton, { onClick: () => editor.chain().focus().redo().run(), disabled: !editor.can().redo(), title: "Redo", children: _jsx(Redo, { className: "h-4 w-4" }) })] }));
|
|
125
125
|
}
|
|
126
126
|
export function TipTapEditor({ content, onChange, placeholder, editable = true, className, }) {
|
|
127
127
|
const [mediaPickerOpen, setMediaPickerOpen] = useState(false);
|
|
@@ -166,6 +166,6 @@ export function TipTapEditor({ content, onChange, placeholder, editable = true,
|
|
|
166
166
|
.setImage({ src: url, alt: alt ?? '' })
|
|
167
167
|
.run();
|
|
168
168
|
};
|
|
169
|
-
return (_jsxs("div", { className: `border border-gray-200
|
|
169
|
+
return (_jsxs("div", { className: `overflow-hidden rounded-lg border border-gray-200 bg-white ${className ?? ''}`, children: [editable && _jsx(Toolbar, { editor: editor, onOpenMediaPicker: () => setMediaPickerOpen(true) }), _jsx(EditorContent, { editor: editor }), _jsx("style", { dangerouslySetInnerHTML: { __html: editorStyles } }), _jsx(MediaPickerModal, { open: mediaPickerOpen, onClose: () => setMediaPickerOpen(false), onSelect: handleImageSelected, accept: "image/*" })] }));
|
|
170
170
|
}
|
|
171
171
|
//# sourceMappingURL=TipTapEditor.js.map
|
|
@@ -58,13 +58,13 @@ export function VersionHistory({ collectionSlug, documentId, open, onClose, onRe
|
|
|
58
58
|
}
|
|
59
59
|
if (!open)
|
|
60
60
|
return null;
|
|
61
|
-
return (_jsxs("div", { className: "fixed inset-0 z-50 flex justify-end", children: [_jsx("div", { className: "fixed inset-0 bg-black/30", onClick: onClose }), _jsxs("div", { className: "relative w-full max-w-md bg-white shadow-xl
|
|
61
|
+
return (_jsxs("div", { className: "fixed inset-0 z-50 flex justify-end", children: [_jsx("div", { className: "fixed inset-0 bg-black/30", onClick: onClose }), _jsxs("div", { className: "animate-in slide-in-from-right relative flex w-full max-w-md flex-col bg-white shadow-xl", children: [_jsxs("div", { className: "flex items-center justify-between border-b border-gray-200 px-4 py-3", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Clock, { className: "h-5 w-5 text-gray-600" }), _jsx("h2", { className: "text-lg font-semibold text-gray-900", children: "Version History" })] }), _jsx("button", { onClick: onClose, className: "rounded-lg p-1.5 transition-colors hover:bg-gray-100", children: _jsx(X, { className: "h-5 w-5 text-gray-500" }) })] }), _jsx("div", { className: "flex-1 overflow-y-auto", children: loading ? (_jsx("div", { className: "flex items-center justify-center py-16", children: _jsx(Loader2, { className: "h-6 w-6 animate-spin text-gray-400" }) })) : versions.length === 0 ? (_jsx("div", { className: "py-16 text-center text-sm text-gray-500", children: "No version history available" })) : (_jsx("div", { className: "divide-y divide-gray-100", children: versions.map((version, index) => {
|
|
62
62
|
const typeInfo = CHANGE_TYPE_LABELS[version.changeType] ?? {
|
|
63
63
|
label: version.changeType,
|
|
64
64
|
color: 'bg-gray-100 text-gray-800',
|
|
65
65
|
};
|
|
66
66
|
const isLatest = index === 0;
|
|
67
|
-
return (_jsx("div", { className: "px-4 py-3 hover:bg-gray-50
|
|
67
|
+
return (_jsx("div", { className: "px-4 py-3 transition-colors hover:bg-gray-50", children: _jsxs("div", { className: "flex items-start justify-between gap-3", children: [_jsxs("div", { className: "min-w-0 flex-1", children: [_jsxs("div", { className: "mb-1 flex items-center gap-2", children: [_jsx("span", { className: `inline-flex rounded-full px-2 py-0.5 text-xs font-medium ${typeInfo.color}`, children: typeInfo.label }), isLatest && (_jsx("span", { className: "text-xs font-medium text-gray-400", children: "Current" }))] }), _jsxs("div", { className: "flex items-center gap-3 text-xs text-gray-500", children: [version.changedBy && (_jsxs("span", { className: "flex items-center gap-1", children: [_jsx(User, { className: "h-3 w-3" }), version.changedBy.name ?? version.changedBy.email ?? 'Unknown'] })), _jsx("span", { title: new Date(version.createdAt).toLocaleString(), children: timeAgo(version.createdAt) })] })] }), !isLatest && (_jsxs("button", { onClick: () => handleRestore(version), disabled: restoring === version.id, className: "flex items-center gap-1.5 rounded-lg bg-blue-50 px-2.5 py-1.5 text-xs font-medium text-blue-700 transition-colors hover:bg-blue-100 disabled:opacity-50", children: [restoring === version.id ? (_jsx(Loader2, { className: "h-3.5 w-3.5 animate-spin" })) : (_jsx(RotateCcw, { className: "h-3.5 w-3.5" })), "Restore"] }))] }) }, version.id));
|
|
68
68
|
}) })) })] })] }));
|
|
69
69
|
}
|
|
70
70
|
//# sourceMappingURL=VersionHistory.js.map
|
|
@@ -1,5 +1,35 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import type { HTMLAttributes, ReactNode } from 'react';
|
|
2
|
+
import { type VariantProps } from '../../lib/cv.js';
|
|
3
|
+
declare const badge: (props?: ({
|
|
4
|
+
tone?: "primary" | "danger" | "neutral" | "success" | "warning" | "info" | undefined;
|
|
5
|
+
size?: "sm" | "md" | "lg" | undefined;
|
|
6
|
+
} & {
|
|
7
|
+
class?: string | false | null | undefined;
|
|
8
|
+
className?: string | false | null | undefined;
|
|
9
|
+
}) | undefined) => string;
|
|
10
|
+
export type BadgeVariants = VariantProps<typeof badge>;
|
|
11
|
+
/**
|
|
12
|
+
* Map document statuses to badge tones. Exposed so callers can reuse the
|
|
13
|
+
* mapping (e.g. for the same status rendered as a dot indicator).
|
|
14
|
+
*/
|
|
15
|
+
export declare const STATUS_TONE: Record<DocumentStatus, BadgeVariants['tone']>;
|
|
16
|
+
export declare const STATUS_LABEL: Record<DocumentStatus, string>;
|
|
17
|
+
export type DocumentStatus = 'published' | 'draft' | 'archived' | 'scheduled';
|
|
18
|
+
export interface BadgeProps extends HTMLAttributes<HTMLSpanElement>, BadgeVariants {
|
|
19
|
+
/**
|
|
20
|
+
* Shorthand for the canonical document status badge. When set, takes
|
|
21
|
+
* precedence over `tone` and uses the matching label.
|
|
22
|
+
*/
|
|
23
|
+
status?: DocumentStatus;
|
|
24
|
+
/** Render as outlined (border + transparent background). */
|
|
25
|
+
outline?: boolean;
|
|
26
|
+
children?: ReactNode;
|
|
3
27
|
}
|
|
4
|
-
|
|
28
|
+
/**
|
|
29
|
+
* Generic typed badge. Pass `status` for the canonical document-status
|
|
30
|
+
* variants (preserves the original Badge API), or `tone` / `outline` /
|
|
31
|
+
* `size` for everything else.
|
|
32
|
+
*/
|
|
33
|
+
export declare function Badge({ status, tone, outline, size, className, children, ...rest }: BadgeProps): import("react/jsx-runtime").JSX.Element;
|
|
34
|
+
export { badge as badgeVariants };
|
|
5
35
|
//# sourceMappingURL=Badge.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Badge.d.ts","sourceRoot":"","sources":["../../../src/components/ui/Badge.tsx"],"names":[],"mappings":"AAAA,MAAM,WAAW,
|
|
1
|
+
{"version":3,"file":"Badge.d.ts","sourceRoot":"","sources":["../../../src/components/ui/Badge.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AACtD,OAAO,EAAM,KAAK,YAAY,EAAE,MAAM,iBAAiB,CAAA;AAEvD,QAAA,MAAM,KAAK;;;;;;yBAiBT,CAAA;AAEF,MAAM,MAAM,aAAa,GAAG,YAAY,CAAC,OAAO,KAAK,CAAC,CAAA;AAEtD;;;GAGG;AACH,eAAO,MAAM,WAAW,EAAE,MAAM,CAAC,cAAc,EAAE,aAAa,CAAC,MAAM,CAAC,CAKrE,CAAA;AAED,eAAO,MAAM,YAAY,EAAE,MAAM,CAAC,cAAc,EAAE,MAAM,CAKvD,CAAA;AAED,MAAM,MAAM,cAAc,GAAG,WAAW,GAAG,OAAO,GAAG,UAAU,GAAG,WAAW,CAAA;AAE7E,MAAM,WAAW,UAAW,SAAQ,cAAc,CAAC,eAAe,CAAC,EAAE,aAAa;IAChF;;;OAGG;IACH,MAAM,CAAC,EAAE,cAAc,CAAA;IACvB,4DAA4D;IAC5D,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,QAAQ,CAAC,EAAE,SAAS,CAAA;CACrB;AAID;;;;GAIG;AACH,wBAAgB,KAAK,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,GAAG,IAAI,EAAE,EAAE,UAAU,2CAc9F;AAED,OAAO,EAAE,KAAK,IAAI,aAAa,EAAE,CAAA"}
|
|
@@ -1,17 +1,51 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
2
|
+
import { cv } from '../../lib/cv.js';
|
|
3
|
+
const badge = cv('inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-medium', {
|
|
4
|
+
variants: {
|
|
5
|
+
tone: {
|
|
6
|
+
neutral: 'bg-gray-100 text-gray-800 dark:bg-gray-800 dark:text-gray-300',
|
|
7
|
+
success: 'bg-emerald-100 text-emerald-800 dark:bg-emerald-900/30 dark:text-emerald-400',
|
|
8
|
+
warning: 'bg-amber-100 text-amber-800 dark:bg-amber-900/30 dark:text-amber-400',
|
|
9
|
+
danger: 'bg-red-100 text-red-800 dark:bg-red-900/30 dark:text-red-400',
|
|
10
|
+
info: 'bg-blue-100 text-blue-800 dark:bg-blue-900/30 dark:text-blue-400',
|
|
11
|
+
primary: 'bg-[var(--primary)]/15 text-[var(--primary)] dark:bg-[var(--primary)]/25',
|
|
12
|
+
},
|
|
13
|
+
size: {
|
|
14
|
+
sm: 'px-2 py-0.5 text-[10px]',
|
|
15
|
+
md: 'px-2.5 py-0.5 text-xs',
|
|
16
|
+
lg: 'px-3 py-1 text-sm',
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
defaultVariants: { tone: 'neutral', size: 'md' },
|
|
20
|
+
});
|
|
21
|
+
/**
|
|
22
|
+
* Map document statuses to badge tones. Exposed so callers can reuse the
|
|
23
|
+
* mapping (e.g. for the same status rendered as a dot indicator).
|
|
24
|
+
*/
|
|
25
|
+
export const STATUS_TONE = {
|
|
26
|
+
published: 'success',
|
|
27
|
+
draft: 'neutral',
|
|
28
|
+
archived: 'warning',
|
|
29
|
+
scheduled: 'info',
|
|
7
30
|
};
|
|
8
|
-
const
|
|
31
|
+
export const STATUS_LABEL = {
|
|
9
32
|
published: 'Published',
|
|
10
33
|
draft: 'Draft',
|
|
11
34
|
archived: 'Archived',
|
|
12
35
|
scheduled: 'Scheduled',
|
|
13
36
|
};
|
|
14
|
-
|
|
15
|
-
|
|
37
|
+
const OUTLINE_CLASS = 'border border-current bg-transparent';
|
|
38
|
+
/**
|
|
39
|
+
* Generic typed badge. Pass `status` for the canonical document-status
|
|
40
|
+
* variants (preserves the original Badge API), or `tone` / `outline` /
|
|
41
|
+
* `size` for everything else.
|
|
42
|
+
*/
|
|
43
|
+
export function Badge({ status, tone, outline, size, className, children, ...rest }) {
|
|
44
|
+
const extras = [outline ? OUTLINE_CLASS : '', className].filter(Boolean).join(' ');
|
|
45
|
+
if (status) {
|
|
46
|
+
return (_jsx("span", { className: badge({ tone: STATUS_TONE[status], size, class: extras }), ...rest, children: children ?? STATUS_LABEL[status] }));
|
|
47
|
+
}
|
|
48
|
+
return (_jsx("span", { className: badge({ tone, size, class: extras }), ...rest, children: children }));
|
|
16
49
|
}
|
|
50
|
+
export { badge as badgeVariants };
|
|
17
51
|
//# sourceMappingURL=Badge.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Badge.js","sourceRoot":"","sources":["../../../src/components/ui/Badge.tsx"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"file":"Badge.js","sourceRoot":"","sources":["../../../src/components/ui/Badge.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,EAAE,EAAqB,MAAM,iBAAiB,CAAA;AAEvD,MAAM,KAAK,GAAG,EAAE,CAAC,yEAAyE,EAAE;IAC1F,QAAQ,EAAE;QACR,IAAI,EAAE;YACJ,OAAO,EAAE,+DAA+D;YACxE,OAAO,EAAE,8EAA8E;YACvF,OAAO,EAAE,sEAAsE;YAC/E,MAAM,EAAE,8DAA8D;YACtE,IAAI,EAAE,kEAAkE;YACxE,OAAO,EAAE,0EAA0E;SACpF;QACD,IAAI,EAAE;YACJ,EAAE,EAAE,yBAAyB;YAC7B,EAAE,EAAE,uBAAuB;YAC3B,EAAE,EAAE,mBAAmB;SACxB;KACF;IACD,eAAe,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE;CACjD,CAAC,CAAA;AAIF;;;GAGG;AACH,MAAM,CAAC,MAAM,WAAW,GAAkD;IACxE,SAAS,EAAE,SAAS;IACpB,KAAK,EAAE,SAAS;IAChB,QAAQ,EAAE,SAAS;IACnB,SAAS,EAAE,MAAM;CAClB,CAAA;AAED,MAAM,CAAC,MAAM,YAAY,GAAmC;IAC1D,SAAS,EAAE,WAAW;IACtB,KAAK,EAAE,OAAO;IACd,QAAQ,EAAE,UAAU;IACpB,SAAS,EAAE,WAAW;CACvB,CAAA;AAeD,MAAM,aAAa,GAAG,sCAAsC,CAAA;AAE5D;;;;GAIG;AACH,MAAM,UAAU,KAAK,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,GAAG,IAAI,EAAc;IAC7F,MAAM,MAAM,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,EAAE,SAAS,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;IAClF,IAAI,MAAM,EAAE,CAAC;QACX,OAAO,CACL,eAAM,SAAS,EAAE,KAAK,CAAC,EAAE,IAAI,EAAE,WAAW,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,KAAM,IAAI,YACjF,QAAQ,IAAI,YAAY,CAAC,MAAM,CAAC,GAC5B,CACR,CAAA;IACH,CAAC;IACD,OAAO,CACL,eAAM,SAAS,EAAE,KAAK,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,KAAM,IAAI,YAC5D,QAAQ,GACJ,CACR,CAAA;AACH,CAAC;AAED,OAAO,EAAE,KAAK,IAAI,aAAa,EAAE,CAAA"}
|
|
@@ -1,12 +1,23 @@
|
|
|
1
1
|
import { type ButtonHTMLAttributes, type ReactNode } from 'react';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
2
|
+
import { type VariantProps } from '../../lib/cv.js';
|
|
3
|
+
declare const button: (props?: ({
|
|
4
|
+
variant?: "link" | "primary" | "secondary" | "danger" | "ghost" | "outline" | undefined;
|
|
5
|
+
size?: "icon" | "xs" | "sm" | "md" | "lg" | undefined;
|
|
6
|
+
} & {
|
|
7
|
+
class?: string | false | null | undefined;
|
|
8
|
+
className?: string | false | null | undefined;
|
|
9
|
+
}) | undefined) => string;
|
|
10
|
+
export type ButtonVariants = VariantProps<typeof button>;
|
|
11
|
+
export interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement>, ButtonVariants {
|
|
7
12
|
loading?: boolean;
|
|
8
|
-
|
|
13
|
+
/** Stretch the button to fill its container width. */
|
|
14
|
+
full?: boolean;
|
|
15
|
+
/** Icon rendered before the children. Use with `size="icon"` for icon-only buttons. */
|
|
16
|
+
leftIcon?: ReactNode;
|
|
17
|
+
/** Icon rendered after the children. */
|
|
18
|
+
rightIcon?: ReactNode;
|
|
19
|
+
children?: ReactNode;
|
|
9
20
|
}
|
|
10
|
-
export declare
|
|
11
|
-
export {};
|
|
21
|
+
export declare const Button: import("react").ForwardRefExoticComponent<ButtonProps & import("react").RefAttributes<HTMLButtonElement>>;
|
|
22
|
+
export { button as buttonVariants };
|
|
12
23
|
//# sourceMappingURL=Button.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Button.d.ts","sourceRoot":"","sources":["../../../src/components/ui/Button.tsx"],"names":[],"mappings":"AAEA,OAAO,
|
|
1
|
+
{"version":3,"file":"Button.d.ts","sourceRoot":"","sources":["../../../src/components/ui/Button.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAc,KAAK,oBAAoB,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAC7E,OAAO,EAAM,KAAK,YAAY,EAAE,MAAM,iBAAiB,CAAA;AAEvD,QAAA,MAAM,MAAM;;;;;;yBA2BX,CAAA;AAED,MAAM,MAAM,cAAc,GAAG,YAAY,CAAC,OAAO,MAAM,CAAC,CAAA;AAExD,MAAM,WAAW,WAAY,SAAQ,oBAAoB,CAAC,iBAAiB,CAAC,EAAE,cAAc;IAC1F,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,sDAAsD;IACtD,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,uFAAuF;IACvF,QAAQ,CAAC,EAAE,SAAS,CAAA;IACpB,wCAAwC;IACxC,SAAS,CAAC,EAAE,SAAS,CAAA;IACrB,QAAQ,CAAC,EAAE,SAAS,CAAA;CACrB;AAED,eAAO,MAAM,MAAM,2GAkDjB,CAAA;AAEF,OAAO,EAAE,MAAM,IAAI,cAAc,EAAE,CAAA"}
|