@kyro-cms/admin 0.12.6 → 0.12.8
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/index.cjs +32 -110
- package/dist/index.css +1 -1
- package/dist/index.d.cts +5 -5
- package/dist/index.d.ts +5 -5
- package/dist/index.js +32 -110
- package/package.json +11 -5
- package/src/components/AuthBridge.tsx +2 -2
- package/src/components/AutoForm.tsx +49 -57
- package/src/components/BrandingHub.tsx +1 -1
- package/src/components/DashboardMetrics.tsx +519 -290
- package/src/components/DetailView.tsx +5 -3
- package/src/components/FieldRenderer.tsx +59 -47
- package/src/components/ListView.tsx +25 -10
- package/src/components/MediaGallery.tsx +1 -1
- package/src/components/PluginsManager.tsx +39 -21
- package/src/components/Sidebar.astro +7 -14
- package/src/components/UserMenu.tsx +10 -9
- package/src/components/autoform/AutoFormApiView.tsx +1 -1
- package/src/components/autoform/AutoFormHeader.tsx +1 -1
- package/src/components/autoform/ErrorBoundary.tsx +1 -1
- package/src/components/blocks/AccordionBlock.tsx +8 -4
- package/src/components/blocks/ArrayBlock.tsx +4 -3
- package/src/components/blocks/BlockEditModal.tsx +4 -3
- package/src/components/blocks/CardBlock.tsx +10 -2
- package/src/components/blocks/ChildBlocksTree.tsx +19 -18
- package/src/components/blocks/CodeBlock.tsx +7 -2
- package/src/components/blocks/FileBlock.tsx +6 -2
- package/src/components/blocks/GenericBlock.tsx +1 -1
- package/src/components/blocks/HeadingBlock.tsx +6 -2
- package/src/components/blocks/HeadingSubheadingBlock.tsx +7 -2
- package/src/components/blocks/HeroBlock.tsx +12 -3
- package/src/components/blocks/ImageBlock.tsx +8 -2
- package/src/components/blocks/ListBlock.tsx +6 -2
- package/src/components/blocks/ParagraphBlock.tsx +2 -2
- package/src/components/blocks/RelationshipBlock.tsx +10 -2
- package/src/components/blocks/VideoBlock.tsx +7 -2
- package/src/components/fields/AccordionField.tsx +1 -1
- package/src/components/fields/ArrayLayout.tsx +55 -58
- package/src/components/fields/BlocksField.tsx +1 -1
- package/src/components/fields/ChildrenField.tsx +3 -2
- package/src/components/fields/CodeField.tsx +3 -2
- package/src/components/fields/ColumnsField.tsx +3 -2
- package/src/components/fields/DateField.tsx +2 -2
- package/src/components/fields/FieldLayout.tsx +3 -3
- package/src/components/fields/GroupLayout.tsx +2 -2
- package/src/components/fields/IconField.tsx +1 -1
- package/src/components/fields/MarkdownField.tsx +2 -2
- package/src/components/fields/NumberField.tsx +4 -4
- package/src/components/fields/RelationshipField.tsx +4 -1
- package/src/components/fields/RichTextField.tsx +200 -5
- package/src/components/fields/extensions/blockComponents.tsx +1 -1
- package/src/components/fields/extensions/blocksStore.ts +15 -12
- package/src/components/ui/Button.tsx +5 -2
- package/src/components/ui/Pagination.tsx +1 -1
- package/src/components/users/UserDetail.tsx +7 -7
- package/src/components/users/UserForm.tsx +3 -2
- package/src/components/users/UsersList.tsx +5 -4
- package/src/env.d.ts +4 -0
- package/src/fields/index.ts +1 -1
- package/src/hooks/useAutoFormState.ts +7 -6
- package/src/hooks/useQueue.ts +3 -2
- package/src/index.ts +0 -1
- package/src/integration.ts +50 -12
- package/src/kyro-cms.d.ts +5 -0
- package/src/lib/api.ts +1 -0
- package/src/lib/autoform-store.ts +4 -3
- package/src/lib/config.ts +6 -19
- package/src/lib/core-types.ts +78 -0
- package/src/lib/normalize-upload-fields.ts +17 -4
- package/src/pages/[collection]/index.astro +1 -1
- package/src/pages/users/index.astro +1 -1
- package/src/plugins/seo-admin.tsx +155 -0
- package/src/styles/main.css +2 -0
- package/src/vite-env.d.ts +10 -1
- package/src/components/fix_imports.cjs +0 -23
- package/src/components/fix_imports2.cjs +0 -19
- package/src/components/replace_svgs.cjs +0 -63
|
@@ -4,10 +4,14 @@ import {
|
|
|
4
4
|
useBlockActions,
|
|
5
5
|
} from "../fields/extensions/blocksStore";
|
|
6
6
|
import { ChevronRight, X } from "../ui/icons";
|
|
7
|
-
import { AccordionField } from "../fields/AccordionField";
|
|
7
|
+
import { AccordionField, type AccordionItem } from "../fields/AccordionField";
|
|
8
8
|
import { useTranslation } from "react-i18next";
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
interface AccordionBlockData {
|
|
11
|
+
items?: AccordionItem[];
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export const AccordionBlock: React.FC<{ block: { id: string; data?: Record<string, unknown> }; index: number }> = ({
|
|
11
15
|
block,
|
|
12
16
|
index,
|
|
13
17
|
}) => {
|
|
@@ -15,10 +19,10 @@ export const AccordionBlock: React.FC<{ block: Record<string, unknown>; index: n
|
|
|
15
19
|
const blockData = useBlockById(block.id);
|
|
16
20
|
const { updateBlock, removeBlock, moveBlock } = useBlockActions();
|
|
17
21
|
|
|
18
|
-
const data = blockData?.data ?? block.data ?? {};
|
|
22
|
+
const data = (blockData?.data ?? block.data ?? {}) as AccordionBlockData;
|
|
19
23
|
const items = Array.isArray(data.items) ? data.items : [];
|
|
20
24
|
|
|
21
|
-
const handleChange = (items:
|
|
25
|
+
const handleChange = (items: AccordionItem[]) => {
|
|
22
26
|
updateBlock(block.id, { data: { ...data, items } });
|
|
23
27
|
};
|
|
24
28
|
|
|
@@ -6,8 +6,9 @@ import {
|
|
|
6
6
|
import { ChevronRight, X } from "../ui/icons";
|
|
7
7
|
import { ChildBlocksTree } from "./ChildBlocksTree";
|
|
8
8
|
import { useTranslation } from "react-i18next";
|
|
9
|
+
import type { BlockData } from "@kyro-cms/core/client";
|
|
9
10
|
|
|
10
|
-
export const ArrayBlock: React.FC<{ block: Record<string, unknown>; index: number }> = ({
|
|
11
|
+
export const ArrayBlock: React.FC<{ block: { id: string; data?: Record<string, unknown>; children?: BlockData[] }; index: number }> = ({
|
|
11
12
|
block,
|
|
12
13
|
index,
|
|
13
14
|
}) => {
|
|
@@ -15,8 +16,8 @@ export const ArrayBlock: React.FC<{ block: Record<string, unknown>; index: numbe
|
|
|
15
16
|
const blockData = useBlockById(block.id);
|
|
16
17
|
const { updateBlock, removeBlock, moveBlock } = useBlockActions();
|
|
17
18
|
|
|
18
|
-
const data = blockData?.data ?? block.data ?? {}
|
|
19
|
-
const children = blockData?.children ?? block.children ?? [];
|
|
19
|
+
const data = (blockData?.data ?? block.data ?? {}) as Record<string, unknown>;
|
|
20
|
+
const children = (blockData?.children ?? block.children ?? []) as BlockData[];
|
|
20
21
|
|
|
21
22
|
return (
|
|
22
23
|
<div className="block-array border border-[var(--kyro-border)] rounded-md p-3 mb-2 relative group">
|
|
@@ -7,9 +7,10 @@ import { blockTheme } from "../fields/extensions/blockComponents";
|
|
|
7
7
|
import { SlidePanel } from "../ui/SlidePanel";
|
|
8
8
|
import { ChildBlocksTree } from "./ChildBlocksTree";
|
|
9
9
|
import { FieldRenderer } from "../FieldRenderer";
|
|
10
|
+
import type { BlockData } from "@kyro-cms/core/client";
|
|
10
11
|
|
|
11
12
|
interface BlockEditModalProps {
|
|
12
|
-
block: Record<string,
|
|
13
|
+
block: Record<string, any>;
|
|
13
14
|
blockSchema?: Record<string, any>;
|
|
14
15
|
onClose: () => void;
|
|
15
16
|
}
|
|
@@ -28,7 +29,7 @@ export const BlockEditModal: React.FC<BlockEditModalProps> = ({
|
|
|
28
29
|
updateBlock(block.id, { data: { ...data, [field]: value } });
|
|
29
30
|
};
|
|
30
31
|
|
|
31
|
-
const handleUpdateChildren = (newChildren:
|
|
32
|
+
const handleUpdateChildren = (newChildren: BlockData[]) => {
|
|
32
33
|
updateBlock(block.id, { children: newChildren });
|
|
33
34
|
};
|
|
34
35
|
|
|
@@ -95,7 +96,7 @@ export const BlockEditModal: React.FC<BlockEditModalProps> = ({
|
|
|
95
96
|
);
|
|
96
97
|
};
|
|
97
98
|
|
|
98
|
-
const theme = blockTheme[block.type
|
|
99
|
+
const theme = blockTheme[block.type] || blockTheme.default;
|
|
99
100
|
|
|
100
101
|
return (
|
|
101
102
|
<SlidePanel
|
|
@@ -6,14 +6,22 @@ import {
|
|
|
6
6
|
import { CardField } from "../fields/CardField";
|
|
7
7
|
import { BlockWrapper } from "./BlockWrapper";
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
interface CardBlockData {
|
|
10
|
+
title?: string;
|
|
11
|
+
description?: string;
|
|
12
|
+
icon?: string;
|
|
13
|
+
link?: string;
|
|
14
|
+
linkText?: string;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export const CardBlock: React.FC<{ block: { id: string; data?: Record<string, unknown> }; index: number }> = ({
|
|
10
18
|
block,
|
|
11
19
|
index,
|
|
12
20
|
}) => {
|
|
13
21
|
const blockData = useBlockById(block.id);
|
|
14
22
|
const { updateBlock } = useBlockActions();
|
|
15
23
|
|
|
16
|
-
const data = blockData?.data
|
|
24
|
+
const data = (blockData?.data ?? block.data ?? {}) as CardBlockData;
|
|
17
25
|
|
|
18
26
|
const handleChange = (field: string, value: unknown) => {
|
|
19
27
|
updateBlock(block.id, { data: { ...data, [field]: value } });
|
|
@@ -12,11 +12,12 @@ import { BlockEditModal } from "./BlockEditModal";
|
|
|
12
12
|
import { useStore } from "zustand";
|
|
13
13
|
import { BlocksContext } from "../fields/extensions/blocksStore";
|
|
14
14
|
import { useContext } from "react";
|
|
15
|
+
import type { BlockData } from "@kyro-cms/core/client";
|
|
15
16
|
|
|
16
17
|
interface ChildBlocksTreeProps {
|
|
17
18
|
blockId: string;
|
|
18
|
-
children:
|
|
19
|
-
onUpdateChildren: (children:
|
|
19
|
+
children: BlockData[];
|
|
20
|
+
onUpdateChildren: (children: BlockData[]) => void;
|
|
20
21
|
depth?: number;
|
|
21
22
|
maxDepth?: number;
|
|
22
23
|
}
|
|
@@ -61,12 +62,12 @@ export const ChildBlocksTree: React.FC<ChildBlocksTreeProps> = ({
|
|
|
61
62
|
}
|
|
62
63
|
return child;
|
|
63
64
|
});
|
|
64
|
-
onUpdateChildren(updated);
|
|
65
|
+
onUpdateChildren(updated as BlockData[]);
|
|
65
66
|
};
|
|
66
67
|
|
|
67
68
|
const handleUpdateChildChildren = (
|
|
68
69
|
childId: string,
|
|
69
|
-
newGrandchildren:
|
|
70
|
+
newGrandchildren: BlockData[],
|
|
70
71
|
) => {
|
|
71
72
|
const updated = children.map((child) => {
|
|
72
73
|
if (child.id === childId) {
|
|
@@ -89,7 +90,7 @@ export const ChildBlocksTree: React.FC<ChildBlocksTreeProps> = ({
|
|
|
89
90
|
});
|
|
90
91
|
};
|
|
91
92
|
|
|
92
|
-
const renderBlock = (child:
|
|
93
|
+
const renderBlock = (child: BlockData) => {
|
|
93
94
|
const hasChildren = child.children && child.children.length > 0;
|
|
94
95
|
const isExpanded = expandedIds.has(child.id);
|
|
95
96
|
const BlockComponent = getBlockComponent(child.type);
|
|
@@ -139,8 +140,8 @@ export const ChildBlocksTree: React.FC<ChildBlocksTreeProps> = ({
|
|
|
139
140
|
<div className="flex-1 min-w-0">
|
|
140
141
|
<div className="text-xs font-medium text-[var(--kyro-text-secondary)] truncate">
|
|
141
142
|
{getBlockDisplayLabel(child)}
|
|
142
|
-
{child.data?.text ? ` - ${child.data.text.slice(0, 30)}` : ""}
|
|
143
|
-
{child.data?.heading ? ` - ${child.data.heading.slice(0, 30)}` : ""}
|
|
143
|
+
{typeof child.data?.text === 'string' ? ` - ${child.data.text.slice(0, 30)}` : ""}
|
|
144
|
+
{typeof child.data?.heading === 'string' ? ` - ${child.data.heading.slice(0, 30)}` : ""}
|
|
144
145
|
</div>
|
|
145
146
|
{blockSchema?.admin?.description && (
|
|
146
147
|
<div className="text-[10px] text-[var(--kyro-text-muted)] mt-0.5 truncate opacity-80">
|
|
@@ -151,7 +152,7 @@ export const ChildBlocksTree: React.FC<ChildBlocksTreeProps> = ({
|
|
|
151
152
|
|
|
152
153
|
{hasChildren && (
|
|
153
154
|
<span className="text-[10px] bg-[var(--kyro-surface-accent)] px-2 py-0.5 rounded text-[var(--kyro-text-muted)] font-medium">
|
|
154
|
-
{child.children
|
|
155
|
+
{child.children?.length} nested
|
|
155
156
|
</span>
|
|
156
157
|
)}
|
|
157
158
|
|
|
@@ -203,7 +204,7 @@ export const ChildBlocksTree: React.FC<ChildBlocksTreeProps> = ({
|
|
|
203
204
|
<div className="mt-1">
|
|
204
205
|
<NestedChildBlocks
|
|
205
206
|
parentId={child.id}
|
|
206
|
-
children={child.children}
|
|
207
|
+
children={child.children ?? []}
|
|
207
208
|
onUpdateChildren={(newGrandchildren) =>
|
|
208
209
|
handleUpdateChildChildren(child.id, newGrandchildren)
|
|
209
210
|
}
|
|
@@ -297,8 +298,8 @@ export const ChildBlocksTree: React.FC<ChildBlocksTreeProps> = ({
|
|
|
297
298
|
|
|
298
299
|
interface NestedChildBlocksProps {
|
|
299
300
|
parentId: string;
|
|
300
|
-
children:
|
|
301
|
-
onUpdateChildren: (children:
|
|
301
|
+
children: BlockData[];
|
|
302
|
+
onUpdateChildren: (children: BlockData[]) => void;
|
|
302
303
|
depth: number;
|
|
303
304
|
maxDepth: number;
|
|
304
305
|
}
|
|
@@ -341,12 +342,12 @@ const NestedChildBlocks: React.FC<NestedChildBlocksProps> = ({
|
|
|
341
342
|
}
|
|
342
343
|
return child;
|
|
343
344
|
});
|
|
344
|
-
onUpdateChildren(updated);
|
|
345
|
+
onUpdateChildren(updated as BlockData[]);
|
|
345
346
|
};
|
|
346
347
|
|
|
347
348
|
const handleUpdateChildChildren = (
|
|
348
349
|
childId: string,
|
|
349
|
-
newGrandchildren:
|
|
350
|
+
newGrandchildren: BlockData[],
|
|
350
351
|
) => {
|
|
351
352
|
const updated = children.map((child) => {
|
|
352
353
|
if (child.id === childId) {
|
|
@@ -369,7 +370,7 @@ const NestedChildBlocks: React.FC<NestedChildBlocksProps> = ({
|
|
|
369
370
|
});
|
|
370
371
|
};
|
|
371
372
|
|
|
372
|
-
const renderBlock = (child:
|
|
373
|
+
const renderBlock = (child: BlockData) => {
|
|
373
374
|
const hasChildren = child.children && child.children.length > 0;
|
|
374
375
|
const isExpanded = expandedIds.has(child.id);
|
|
375
376
|
const BlockComponent = getBlockComponent(child.type);
|
|
@@ -419,8 +420,8 @@ const NestedChildBlocks: React.FC<NestedChildBlocksProps> = ({
|
|
|
419
420
|
<div className="flex-1 min-w-0">
|
|
420
421
|
<div className="text-xs font-medium text-[var(--kyro-text-secondary)] truncate">
|
|
421
422
|
{getBlockDisplayLabel(child)}
|
|
422
|
-
{child.data?.text ? ` - ${child.data.text.slice(0, 30)}` : ""}
|
|
423
|
-
{child.data?.heading ? ` - ${child.data.heading.slice(0, 30)}` : ""}
|
|
423
|
+
{typeof child.data?.text === 'string' ? ` - ${child.data.text.slice(0, 30)}` : ""}
|
|
424
|
+
{typeof child.data?.heading === 'string' ? ` - ${child.data.heading.slice(0, 30)}` : ""}
|
|
424
425
|
</div>
|
|
425
426
|
{blockSchema?.admin?.description && (
|
|
426
427
|
<div className="text-[10px] text-[var(--kyro-text-muted)] mt-0.5 truncate opacity-80">
|
|
@@ -431,7 +432,7 @@ const NestedChildBlocks: React.FC<NestedChildBlocksProps> = ({
|
|
|
431
432
|
|
|
432
433
|
{hasChildren && (
|
|
433
434
|
<span className="text-[10px] bg-[var(--kyro-surface-accent)] px-2 py-0.5 rounded text-[var(--kyro-text-muted)] font-medium">
|
|
434
|
-
{child.children
|
|
435
|
+
{child.children?.length} nested
|
|
435
436
|
</span>
|
|
436
437
|
)}
|
|
437
438
|
|
|
@@ -483,7 +484,7 @@ const NestedChildBlocks: React.FC<NestedChildBlocksProps> = ({
|
|
|
483
484
|
<div className="mt-1">
|
|
484
485
|
<NestedChildBlocks
|
|
485
486
|
parentId={child.id}
|
|
486
|
-
children={child.children}
|
|
487
|
+
children={child.children ?? []}
|
|
487
488
|
onUpdateChildren={(newGrandchildren) =>
|
|
488
489
|
handleUpdateChildChildren(child.id, newGrandchildren)
|
|
489
490
|
}
|
|
@@ -7,14 +7,19 @@ import { ChevronRight, X, Code2 } from "../ui/icons";
|
|
|
7
7
|
import { CodeField } from "../fields/CodeField";
|
|
8
8
|
import { useTranslation } from "react-i18next";
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
interface CodeBlockData {
|
|
11
|
+
language?: string;
|
|
12
|
+
code?: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export const CodeBlock: React.FC<{ block: { id: string; data?: Record<string, unknown> }; index: number }> = ({
|
|
11
16
|
block,
|
|
12
17
|
index,
|
|
13
18
|
}) => {
|
|
14
19
|
const { t } = useTranslation();
|
|
15
20
|
const blockData = useBlockById(block.id);
|
|
16
21
|
const { updateBlock, removeBlock, moveBlock } = useBlockActions();
|
|
17
|
-
const data = blockData?.data ?? block.data ?? {};
|
|
22
|
+
const data = (blockData?.data ?? block.data ?? {}) as CodeBlockData;
|
|
18
23
|
|
|
19
24
|
const handleChange = (field: string, value: unknown) => {
|
|
20
25
|
updateBlock(block.id, { data: { ...data, [field]: value } });
|
|
@@ -7,7 +7,11 @@ import { ChevronRight, X } from "../ui/icons";
|
|
|
7
7
|
import { UploadField } from "../fields/UploadField";
|
|
8
8
|
import { useTranslation } from "react-i18next";
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
interface FileBlockData {
|
|
11
|
+
file?: string | null;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export const FileBlock: React.FC<{ block: { id: string; data?: Record<string, unknown> }; index: number }> = ({
|
|
11
15
|
block,
|
|
12
16
|
index,
|
|
13
17
|
}) => {
|
|
@@ -15,7 +19,7 @@ export const FileBlock: React.FC<{ block: Record<string, unknown>; index: number
|
|
|
15
19
|
const blockData = useBlockById(block.id);
|
|
16
20
|
const { updateBlock, removeBlock, moveBlock } = useBlockActions();
|
|
17
21
|
|
|
18
|
-
const data = blockData?.data ?? block.data ?? {};
|
|
22
|
+
const data = (blockData?.data ?? block.data ?? {}) as FileBlockData;
|
|
19
23
|
|
|
20
24
|
const handleChange = (field: string, value: unknown) => {
|
|
21
25
|
updateBlock(block.id, { data: { ...data, [field]: value } });
|
|
@@ -4,7 +4,7 @@ import { FieldRenderer } from "../FieldRenderer";
|
|
|
4
4
|
import { useBlockById, useBlockActions } from "../fields/extensions/blocksStore";
|
|
5
5
|
|
|
6
6
|
interface GenericBlockProps {
|
|
7
|
-
block: Record<string, unknown>;
|
|
7
|
+
block: { id: string; data?: Record<string, unknown>; type?: string };
|
|
8
8
|
index: number;
|
|
9
9
|
blockSchema: Record<string, any>;
|
|
10
10
|
}
|
|
@@ -6,14 +6,18 @@ import {
|
|
|
6
6
|
import { HeadingField } from "../fields/HeadingField";
|
|
7
7
|
import { BlockWrapper } from "./BlockWrapper";
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
interface HeadingBlockData {
|
|
10
|
+
text?: string;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export const HeadingBlock: React.FC<{ block: { id: string; data?: Record<string, unknown> }; index: number }> = ({
|
|
10
14
|
block,
|
|
11
15
|
index,
|
|
12
16
|
}) => {
|
|
13
17
|
const blockData = useBlockById(block.id);
|
|
14
18
|
const { updateBlock } = useBlockActions();
|
|
15
19
|
|
|
16
|
-
const data = blockData?.data
|
|
20
|
+
const data = (blockData?.data ?? block.data ?? {}) as HeadingBlockData;
|
|
17
21
|
|
|
18
22
|
const handleChange = (field: string, value: unknown) => {
|
|
19
23
|
updateBlock(block.id, { data: { ...data, [field]: value } });
|
|
@@ -6,14 +6,19 @@ import {
|
|
|
6
6
|
import { HeadingSubheadingField } from "../fields/HeadingSubheadingField";
|
|
7
7
|
import { BlockWrapper } from "./BlockWrapper";
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
interface HeadingSubheadingBlockData {
|
|
10
|
+
title?: string;
|
|
11
|
+
subtitle?: string;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export const HeadingSubheadingBlock: React.FC<{ block: { id: string; data?: Record<string, unknown> }; index: number }> = ({
|
|
10
15
|
block,
|
|
11
16
|
index,
|
|
12
17
|
}) => {
|
|
13
18
|
const blockData = useBlockById(block.id);
|
|
14
19
|
const { updateBlock } = useBlockActions();
|
|
15
20
|
|
|
16
|
-
const data = blockData?.data
|
|
21
|
+
const data = (blockData?.data ?? block.data ?? {}) as HeadingSubheadingBlockData;
|
|
17
22
|
|
|
18
23
|
const handleChange = (field: string, value: unknown) => {
|
|
19
24
|
updateBlock(block.id, { data: { ...data, [field]: value } });
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
+
import type { BlockData } from "@kyro-cms/core/client";
|
|
2
3
|
import {
|
|
3
4
|
useBlockById,
|
|
4
5
|
useBlockActions,
|
|
@@ -9,7 +10,15 @@ import { UploadField } from "../fields/UploadField";
|
|
|
9
10
|
import { ChildBlocksTree } from "./ChildBlocksTree";
|
|
10
11
|
import { useTranslation } from "react-i18next";
|
|
11
12
|
|
|
12
|
-
|
|
13
|
+
interface HeroBlockData {
|
|
14
|
+
title?: string;
|
|
15
|
+
subtitle?: string;
|
|
16
|
+
ctaText?: string;
|
|
17
|
+
ctaUrl?: string;
|
|
18
|
+
bgImage?: string | null;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export const HeroBlock: React.FC<{ block: { id: string; data?: Record<string, unknown>; children?: BlockData[] }; index: number }> = ({
|
|
13
22
|
block,
|
|
14
23
|
index,
|
|
15
24
|
}) => {
|
|
@@ -17,8 +26,8 @@ export const HeroBlock: React.FC<{ block: Record<string, unknown>; index: number
|
|
|
17
26
|
const blockData = useBlockById(block.id);
|
|
18
27
|
const { updateBlock, removeBlock, moveBlock } = useBlockActions();
|
|
19
28
|
|
|
20
|
-
const data = blockData?.data ?? block.data ?? {};
|
|
21
|
-
const children = blockData?.children ?? block.children ?? [];
|
|
29
|
+
const data = (blockData?.data ?? block.data ?? {}) as HeroBlockData;
|
|
30
|
+
const children = (blockData?.children ?? block.children ?? []) as BlockData[];
|
|
22
31
|
|
|
23
32
|
const handleChange = (field: string, value: unknown) => {
|
|
24
33
|
updateBlock(block.id, { data: { ...data, [field]: value } });
|
|
@@ -7,14 +7,20 @@ import { ChevronRight, X } from "../ui/icons";
|
|
|
7
7
|
import { UploadField } from "../fields/UploadField";
|
|
8
8
|
import { useTranslation } from "react-i18next";
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
interface ImageBlockData {
|
|
11
|
+
src?: string | null;
|
|
12
|
+
alt?: string;
|
|
13
|
+
caption?: string;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export const ImageBlock: React.FC<{ block: { id: string; data?: Record<string, unknown> }; index: number }> = ({
|
|
11
17
|
block,
|
|
12
18
|
index,
|
|
13
19
|
}) => {
|
|
14
20
|
const { t } = useTranslation();
|
|
15
21
|
const blockData = useBlockById(block.id);
|
|
16
22
|
const { updateBlock, removeBlock, moveBlock } = useBlockActions();
|
|
17
|
-
const data = blockData?.data
|
|
23
|
+
const data = (blockData?.data ?? block.data ?? {}) as ImageBlockData;
|
|
18
24
|
|
|
19
25
|
const handleChange = (field: string, value: unknown) => {
|
|
20
26
|
updateBlock(block.id, { data: { ...data, [field]: value } });
|
|
@@ -7,7 +7,11 @@ import { ChevronRight, X } from "../ui/icons";
|
|
|
7
7
|
import { ListField } from "../fields/ListField";
|
|
8
8
|
import { useTranslation } from "react-i18next";
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
interface ListBlockData {
|
|
11
|
+
items?: string[];
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export const ListBlock: React.FC<{ block: { id: string; data?: Record<string, unknown> }; index: number }> = ({
|
|
11
15
|
block,
|
|
12
16
|
index,
|
|
13
17
|
}) => {
|
|
@@ -15,7 +19,7 @@ export const ListBlock: React.FC<{ block: Record<string, unknown>; index: number
|
|
|
15
19
|
const blockData = useBlockById(block.id);
|
|
16
20
|
const { updateBlock, removeBlock, moveBlock } = useBlockActions();
|
|
17
21
|
|
|
18
|
-
const data = blockData?.data
|
|
22
|
+
const data = (blockData?.data ?? block.data ?? {}) as ListBlockData;
|
|
19
23
|
const listItems = Array.isArray(data.items) ? data.items : [];
|
|
20
24
|
|
|
21
25
|
const handleChange = (items: string[]) => {
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
import { BlockWrapper } from "./BlockWrapper";
|
|
7
7
|
import { useTranslation } from "react-i18next";
|
|
8
8
|
|
|
9
|
-
export const ParagraphBlock: React.FC<{ block: Record<string, unknown
|
|
9
|
+
export const ParagraphBlock: React.FC<{ block: { id: string; data?: Record<string, unknown> }; index: number }> = ({
|
|
10
10
|
block,
|
|
11
11
|
index,
|
|
12
12
|
}) => {
|
|
@@ -14,7 +14,7 @@ export const ParagraphBlock: React.FC<{ block: Record<string, unknown>; index: n
|
|
|
14
14
|
const blockData = useBlockById(block.id);
|
|
15
15
|
const { updateBlock } = useBlockActions();
|
|
16
16
|
|
|
17
|
-
const data = blockData?.data || block.data || {};
|
|
17
|
+
const data = (blockData?.data || block.data || {}) as { text?: string };
|
|
18
18
|
|
|
19
19
|
const handleChange = (field: string, value: unknown) => {
|
|
20
20
|
updateBlock(block.id, { data: { ...data, [field]: value } });
|
|
@@ -7,7 +7,15 @@ import { ChevronRight, X } from "../ui/icons";
|
|
|
7
7
|
import { RelationshipBlockField } from "../fields/RelationshipBlockField";
|
|
8
8
|
import { useTranslation } from "react-i18next";
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
interface RelationshipBlockData {
|
|
11
|
+
relationTo?: string;
|
|
12
|
+
hasMany?: boolean;
|
|
13
|
+
selectedIds?: string[];
|
|
14
|
+
selectedId?: string;
|
|
15
|
+
labelField?: string;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export const RelationshipBlock: React.FC<{ block: { id: string; data?: Record<string, unknown> }; index: number }> = ({
|
|
11
19
|
block,
|
|
12
20
|
index,
|
|
13
21
|
}) => {
|
|
@@ -15,7 +23,7 @@ export const RelationshipBlock: React.FC<{ block: Record<string, unknown>; index
|
|
|
15
23
|
const blockData = useBlockById(block.id);
|
|
16
24
|
const { updateBlock, removeBlock, moveBlock } = useBlockActions();
|
|
17
25
|
|
|
18
|
-
const data = blockData?.data ?? block.data ?? {};
|
|
26
|
+
const data = (blockData?.data ?? block.data ?? {}) as RelationshipBlockData;
|
|
19
27
|
|
|
20
28
|
const handleChange = (field: string, value: unknown) => {
|
|
21
29
|
updateBlock(block.id, { data: { ...data, [field]: value } });
|
|
@@ -7,7 +7,12 @@ import { ChevronRight, X } from "../ui/icons";
|
|
|
7
7
|
import { VideoField } from "../fields/VideoField";
|
|
8
8
|
import { useTranslation } from "react-i18next";
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
interface VideoBlockData {
|
|
11
|
+
src?: string;
|
|
12
|
+
title?: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export const VideoBlock: React.FC<{ block: { id: string; data?: Record<string, unknown> }; index: number }> = ({
|
|
11
16
|
block,
|
|
12
17
|
index,
|
|
13
18
|
}) => {
|
|
@@ -15,7 +20,7 @@ export const VideoBlock: React.FC<{ block: Record<string, unknown>; index: numbe
|
|
|
15
20
|
const blockData = useBlockById(block.id);
|
|
16
21
|
const { updateBlock, removeBlock, moveBlock } = useBlockActions();
|
|
17
22
|
|
|
18
|
-
const data = blockData?.data ?? block.data ?? {};
|
|
23
|
+
const data = (blockData?.data ?? block.data ?? {}) as VideoBlockData;
|
|
19
24
|
|
|
20
25
|
const handleChange = (field: string, value: unknown) => {
|
|
21
26
|
updateBlock(block.id, { data: { ...data, [field]: value } });
|
|
@@ -2,7 +2,7 @@ import React, { useState, useCallback } from "react";
|
|
|
2
2
|
import { ChevronDown, ChevronUp, Plus, X } from "../ui/icons";
|
|
3
3
|
import { useTranslation } from "react-i18next";
|
|
4
4
|
|
|
5
|
-
interface AccordionItem {
|
|
5
|
+
export interface AccordionItem {
|
|
6
6
|
title: string;
|
|
7
7
|
content: string;
|
|
8
8
|
}
|