@kyro-cms/admin 0.1.7 → 0.1.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/package.json +5 -3
- package/src/components/Admin.tsx +1 -1
- package/src/components/AutoForm.tsx +966 -337
- package/src/components/CreateView.tsx +1 -1
- package/src/components/DetailView.tsx +1 -1
- package/src/components/EnhancedListView.tsx +156 -52
- package/src/components/ListView.tsx +1 -1
- package/src/components/Modal.tsx +65 -8
- package/src/components/Sidebar.astro +2 -2
- package/src/components/ThemeProvider.tsx +8 -2
- package/src/components/blocks/AccordionBlock.tsx +20 -52
- package/src/components/blocks/ArrayBlock.tsx +40 -31
- package/src/components/blocks/BlockEditModal.tsx +170 -581
- package/src/components/blocks/ButtonBlock.tsx +27 -128
- package/src/components/blocks/CodeBlock.tsx +88 -40
- package/src/components/blocks/ColumnsBlock.tsx +27 -85
- package/src/components/blocks/FileBlock.tsx +38 -39
- package/src/components/blocks/HeadingBlock.tsx +9 -31
- package/src/components/blocks/HeroBlock.tsx +42 -100
- package/src/components/blocks/ImageBlock.tsx +6 -7
- package/src/components/blocks/LinkBlock.tsx +27 -33
- package/src/components/blocks/ListBlock.tsx +47 -26
- package/src/components/blocks/RelationshipBlock.tsx +26 -233
- package/src/components/blocks/RichTextBlock.tsx +66 -0
- package/src/components/blocks/VStackBlock.tsx +23 -37
- package/src/components/blocks/VideoBlock.tsx +52 -32
- package/src/components/fields/AccordionField.tsx +213 -0
- package/src/components/fields/ArrayField.tsx +241 -0
- package/src/components/fields/BlocksField.tsx +5 -5
- package/src/components/fields/ButtonField.tsx +53 -0
- package/src/components/fields/CheckboxField.tsx +7 -3
- package/src/components/fields/ChildrenField.tsx +48 -0
- package/src/components/fields/CodeField.tsx +154 -94
- package/src/components/fields/ColumnsField.tsx +137 -0
- package/src/components/fields/DateField.tsx +9 -24
- package/src/components/fields/EditorClient.tsx +426 -160
- package/src/components/fields/HeadingField.tsx +31 -0
- package/src/components/fields/HeroField.tsx +101 -0
- package/src/components/fields/JSONField.tsx +7 -27
- package/src/components/fields/LinkField.tsx +81 -0
- package/src/components/fields/ListField.tsx +74 -0
- package/src/components/fields/MarkdownField.tsx +4 -26
- package/src/components/fields/NumberField.tsx +9 -27
- package/src/components/fields/PortableTextField.tsx +61 -49
- package/src/components/fields/RelationshipBlockField.tsx +233 -0
- package/src/components/fields/RelationshipField.tsx +59 -13
- package/src/components/fields/SelectField.tsx +6 -4
- package/src/components/fields/TextField.tsx +9 -24
- package/src/components/fields/UploadField.tsx +613 -0
- package/src/components/fields/VideoField.tsx +73 -0
- package/src/components/fields/extensions/blockComponents.tsx +11 -1
- package/src/components/fields/extensions/blocksStore.ts +1 -1
- package/src/components/fields/index.ts +12 -1
- package/src/components/layout/Layout.tsx +1 -1
- package/src/lib/api.ts +163 -0
- package/src/lib/config.ts +1 -1
- package/src/lib/dataStore.ts +87 -30
- package/src/lib/date-utils.ts +69 -0
- package/src/lib/db/version-adapter.ts +248 -0
- package/src/lib/i18n.tsx +353 -0
- package/src/lib/slugify.ts +15 -0
- package/src/lib/validation.ts +250 -0
- package/src/pages/api/[collection]/[id]/publish.ts +12 -4
- package/src/pages/api/[collection]/[id]/versions.ts +39 -9
- package/src/pages/api/[collection]/[id].ts +13 -1
- package/src/pages/api/[collection]/index.ts +5 -6
- package/src/styles/main.css +12 -2
- package/src/components/blocks/BlockEditModal.MARKER +0 -12
- package/src/components/fields/FileField.tsx +0 -390
- package/src/components/fields/HybridContentField.tsx +0 -109
- package/src/components/fields/ImageField.tsx +0 -429
|
@@ -3,95 +3,63 @@ import {
|
|
|
3
3
|
useBlockById,
|
|
4
4
|
useBlockActions,
|
|
5
5
|
} from "../fields/extensions/blocksStore";
|
|
6
|
-
import { ChevronRight, X
|
|
6
|
+
import { ChevronRight, X } from "lucide-react";
|
|
7
|
+
import { AccordionField } from "../fields/AccordionField";
|
|
7
8
|
|
|
8
|
-
|
|
9
|
-
block: any;
|
|
10
|
-
index: number;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export const AccordionBlock: React.FC<AccordionBlockProps> = ({
|
|
9
|
+
export const AccordionBlock: React.FC<{ block: any; index: number }> = ({
|
|
14
10
|
block,
|
|
15
11
|
index,
|
|
16
12
|
}) => {
|
|
17
13
|
const blockData = useBlockById(block.id);
|
|
18
14
|
const { updateBlock, removeBlock, moveBlock } = useBlockActions();
|
|
15
|
+
|
|
19
16
|
const data = blockData?.data ?? block.data ?? {};
|
|
20
17
|
const items = Array.isArray(data.items) ? data.items : [];
|
|
21
|
-
|
|
18
|
+
|
|
19
|
+
const handleChange = (items: any[]) => {
|
|
20
|
+
updateBlock(block.id, { data: { ...data, items } });
|
|
21
|
+
};
|
|
22
22
|
|
|
23
23
|
return (
|
|
24
|
-
<div className="block-accordion border border-[var(--kyro-border)] rounded-
|
|
25
|
-
<div className="flex items-center justify-between mb-
|
|
24
|
+
<div className="block-accordion border border-[var(--kyro-border)] rounded-md p-3 mb-2 relative group">
|
|
25
|
+
<div className="flex items-center justify-between mb-2">
|
|
26
26
|
<div className="flex items-center gap-2">
|
|
27
|
-
<span className="text-
|
|
27
|
+
<span className="text-xs font-semibold text-[var(--kyro-text-muted)] uppercase">
|
|
28
28
|
Accordion
|
|
29
29
|
</span>
|
|
30
|
-
<span className="text-
|
|
30
|
+
<span className="text-[10px] text-[var(--kyro-text-muted)]">
|
|
31
31
|
({items.length} items)
|
|
32
32
|
</span>
|
|
33
33
|
</div>
|
|
34
|
-
<div className="flex gap-
|
|
34
|
+
<div className="flex gap-0.5 opacity-0 group-hover:opacity-100 transition-opacity">
|
|
35
35
|
<button
|
|
36
36
|
type="button"
|
|
37
37
|
onClick={() => moveBlock(block.id, "up")}
|
|
38
|
-
className="p-1
|
|
38
|
+
className="p-1 hover:bg-[var(--kyro-surface-accent)] rounded"
|
|
39
39
|
title="Move up"
|
|
40
40
|
>
|
|
41
|
-
<ChevronRight className="w-3
|
|
41
|
+
<ChevronRight className="w-3 h-3 rotate-90" />
|
|
42
42
|
</button>
|
|
43
43
|
<button
|
|
44
44
|
type="button"
|
|
45
45
|
onClick={() => moveBlock(block.id, "down")}
|
|
46
|
-
className="p-1
|
|
46
|
+
className="p-1 hover:bg-[var(--kyro-surface-accent)] rounded"
|
|
47
47
|
title="Move down"
|
|
48
48
|
>
|
|
49
|
-
<ChevronRight className="w-3
|
|
49
|
+
<ChevronRight className="w-3 h-3" />
|
|
50
50
|
</button>
|
|
51
51
|
<button
|
|
52
52
|
type="button"
|
|
53
53
|
onClick={() => removeBlock(block.id)}
|
|
54
|
-
className="p-1
|
|
54
|
+
className="p-1 hover:bg-red-50 rounded text-red-500"
|
|
55
55
|
title="Remove"
|
|
56
56
|
>
|
|
57
|
-
<X className="w-3
|
|
57
|
+
<X className="w-3 h-3" />
|
|
58
58
|
</button>
|
|
59
59
|
</div>
|
|
60
60
|
</div>
|
|
61
61
|
|
|
62
|
-
<
|
|
63
|
-
{items.map((item: any, i: number) => {
|
|
64
|
-
const isOpen = openIndex === i;
|
|
65
|
-
return (
|
|
66
|
-
<div
|
|
67
|
-
key={i}
|
|
68
|
-
className="border border-[var(--kyro-border)] rounded-lg overflow-hidden"
|
|
69
|
-
>
|
|
70
|
-
<button
|
|
71
|
-
type="button"
|
|
72
|
-
onClick={() => setOpenIndex(isOpen ? null : i)}
|
|
73
|
-
className="w-full flex items-center justify-between p-3 bg-[var(--kyro-surface-accent)] hover:bg-[var(--kyro-sidebar-active)]/10 transition-colors"
|
|
74
|
-
>
|
|
75
|
-
<span className="text-sm font-medium text-[var(--kyro-text-primary)]">
|
|
76
|
-
{item.title || `Item ${i + 1}`}
|
|
77
|
-
</span>
|
|
78
|
-
{isOpen ? (
|
|
79
|
-
<ChevronUp className="w-4 h-4 text-[var(--kyro-text-muted)]" />
|
|
80
|
-
) : (
|
|
81
|
-
<ChevronDown className="w-4 h-4 text-[var(--kyro-text-muted)]" />
|
|
82
|
-
)}
|
|
83
|
-
</button>
|
|
84
|
-
{isOpen && (
|
|
85
|
-
<div className="p-3 bg-[var(--kyro-surface)]">
|
|
86
|
-
<p className="text-sm text-[var(--kyro-text-primary)] whitespace-pre-wrap">
|
|
87
|
-
{item.content || "No content"}
|
|
88
|
-
</p>
|
|
89
|
-
</div>
|
|
90
|
-
)}
|
|
91
|
-
</div>
|
|
92
|
-
);
|
|
93
|
-
})}
|
|
94
|
-
</div>
|
|
62
|
+
<AccordionField items={items} onChange={handleChange} compact />
|
|
95
63
|
</div>
|
|
96
64
|
);
|
|
97
65
|
};
|
|
@@ -4,71 +4,80 @@ import {
|
|
|
4
4
|
useBlockActions,
|
|
5
5
|
} from "../fields/extensions/blocksStore";
|
|
6
6
|
import { ChevronRight, X } from "lucide-react";
|
|
7
|
+
import { ArrayField } from "../fields/ArrayField";
|
|
7
8
|
import { ChildBlocksTree } from "./ChildBlocksTree";
|
|
8
9
|
|
|
9
|
-
|
|
10
|
-
block
|
|
11
|
-
index
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export const ArrayBlock: React.FC<ArrayBlockProps> = ({ block, index }) => {
|
|
10
|
+
export const ArrayBlock: React.FC<{ block: any; index: number }> = ({
|
|
11
|
+
block,
|
|
12
|
+
index,
|
|
13
|
+
}) => {
|
|
15
14
|
const blockData = useBlockById(block.id);
|
|
16
15
|
const { updateBlock, removeBlock, moveBlock } = useBlockActions();
|
|
16
|
+
|
|
17
17
|
const data = blockData?.data ?? block.data ?? {};
|
|
18
18
|
const children = blockData?.children ?? block.children ?? [];
|
|
19
|
-
|
|
20
|
-
const handleUpdateChildren = (newChildren: any[]) => {
|
|
21
|
-
updateBlock(block.id, { children: newChildren });
|
|
22
|
-
};
|
|
19
|
+
const items = Array.isArray(data.items) ? data.items : [];
|
|
23
20
|
|
|
24
21
|
return (
|
|
25
|
-
<div className="block-array border border-[var(--kyro-border)] rounded-
|
|
26
|
-
<div className="flex items-center justify-between mb-
|
|
22
|
+
<div className="block-array border border-[var(--kyro-border)] rounded-md p-3 mb-2 relative group">
|
|
23
|
+
<div className="flex items-center justify-between mb-2">
|
|
27
24
|
<div className="flex items-center gap-2">
|
|
28
|
-
<span className="text-
|
|
25
|
+
<span className="text-xs font-semibold text-[var(--kyro-text-muted)] uppercase">
|
|
29
26
|
Repeater
|
|
30
27
|
</span>
|
|
31
|
-
<span className="text-
|
|
32
|
-
({children.length}
|
|
28
|
+
<span className="text-[10px] text-[var(--kyro-text-muted)]">
|
|
29
|
+
({items.length + children.length} items)
|
|
33
30
|
</span>
|
|
34
31
|
</div>
|
|
35
|
-
<div className="flex gap-
|
|
32
|
+
<div className="flex gap-0.5 opacity-0 group-hover:opacity-100 transition-opacity">
|
|
36
33
|
<button
|
|
37
34
|
type="button"
|
|
38
35
|
onClick={() => moveBlock(block.id, "up")}
|
|
39
|
-
className="p-1
|
|
36
|
+
className="p-1 hover:bg-[var(--kyro-surface-accent)] rounded"
|
|
40
37
|
title="Move up"
|
|
41
38
|
>
|
|
42
|
-
<ChevronRight className="w-3
|
|
39
|
+
<ChevronRight className="w-3 h-3 rotate-90" />
|
|
43
40
|
</button>
|
|
44
41
|
<button
|
|
45
42
|
type="button"
|
|
46
43
|
onClick={() => moveBlock(block.id, "down")}
|
|
47
|
-
className="p-1
|
|
44
|
+
className="p-1 hover:bg-[var(--kyro-surface-accent)] rounded"
|
|
48
45
|
title="Move down"
|
|
49
46
|
>
|
|
50
|
-
<ChevronRight className="w-3
|
|
47
|
+
<ChevronRight className="w-3 h-3" />
|
|
51
48
|
</button>
|
|
52
49
|
<button
|
|
53
50
|
type="button"
|
|
54
51
|
onClick={() => removeBlock(block.id)}
|
|
55
|
-
className="p-1
|
|
52
|
+
className="p-1 hover:bg-red-50 rounded text-red-500"
|
|
56
53
|
title="Remove"
|
|
57
54
|
>
|
|
58
|
-
<X className="w-3
|
|
55
|
+
<X className="w-3 h-3" />
|
|
59
56
|
</button>
|
|
60
57
|
</div>
|
|
61
58
|
</div>
|
|
62
59
|
|
|
63
|
-
<div className="
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
60
|
+
<div className="space-y-3">
|
|
61
|
+
{items.length > 0 && (
|
|
62
|
+
<ArrayField
|
|
63
|
+
items={items}
|
|
64
|
+
onChange={(newItems) =>
|
|
65
|
+
updateBlock(block.id, { data: { ...data, items: newItems } })
|
|
66
|
+
}
|
|
67
|
+
compact
|
|
68
|
+
/>
|
|
69
|
+
)}
|
|
70
|
+
|
|
71
|
+
<div className="pt-2 border-t border-[var(--kyro-border)]">
|
|
72
|
+
<label className="text-[10px] font-medium text-[var(--kyro-text-muted)] mb-1.5 block">
|
|
73
|
+
Children ({children.length})
|
|
74
|
+
</label>
|
|
75
|
+
<ChildBlocksTree
|
|
76
|
+
blockId={block.id}
|
|
77
|
+
children={children}
|
|
78
|
+
onUpdateChildren={(c) => updateBlock(block.id, { children: c })}
|
|
79
|
+
/>
|
|
80
|
+
</div>
|
|
72
81
|
</div>
|
|
73
82
|
</div>
|
|
74
83
|
);
|