@kyro-cms/admin 0.3.2 → 0.3.5
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/EditorClient-XEUOVAAC.js +466 -0
- package/dist/EditorClient-XEUOVAAC.js.map +1 -0
- package/dist/EditorClient-YLCGVDXY.cjs +468 -0
- package/dist/EditorClient-YLCGVDXY.cjs.map +1 -0
- package/dist/chunk-7KPIUCGT.js +384 -0
- package/dist/chunk-7KPIUCGT.js.map +1 -0
- package/dist/chunk-GOACG6R7.cjs +473 -0
- package/dist/chunk-GOACG6R7.cjs.map +1 -0
- package/dist/index.cjs +14861 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.css +1661 -0
- package/dist/index.css.map +1 -0
- package/dist/index.d.ts +563 -0
- package/dist/index.js +14784 -0
- package/dist/index.js.map +1 -0
- package/package.json +19 -19
- package/src/components/ActionBar.tsx +7 -43
- package/src/components/Admin.tsx +138 -277
- package/src/components/ApiKeysManager.tsx +428 -419
- package/src/components/AuditLogsPage.tsx +35 -39
- package/src/components/AuthBridge.tsx +51 -0
- package/src/components/AutoForm.tsx +495 -1230
- package/src/components/BrandingHub.tsx +18 -19
- package/src/components/BulkActionsBar.tsx +1 -1
- package/src/components/CreateView.tsx +22 -36
- package/src/components/Dashboard.tsx +60 -84
- package/src/components/DetailView.tsx +113 -91
- package/src/components/DeveloperCenter.tsx +200 -198
- package/src/components/FieldRenderer.tsx +206 -0
- package/src/components/GraphQLPlayground.tsx +340 -480
- package/src/components/ListView.tsx +828 -254
- package/src/components/LoginPage.tsx +3 -4
- package/src/components/MarketplaceManager.tsx +254 -0
- package/src/components/MediaGallery.tsx +856 -1192
- package/src/components/PluginsManager.tsx +277 -0
- package/src/components/RestPlayground.tsx +398 -560
- package/src/components/SessionsManager.tsx +211 -0
- package/src/components/Sidebar.astro +179 -151
- package/src/components/ThemeProvider.tsx +7 -161
- package/src/components/UserManagement.tsx +162 -146
- package/src/components/UserMenu.tsx +110 -0
- package/src/components/WebhookManager.tsx +305 -367
- package/src/components/blocks/AccordionBlock.tsx +4 -4
- package/src/components/blocks/ArrayBlock.tsx +3 -3
- package/src/components/blocks/BlockEditModal.tsx +8 -8
- package/src/components/blocks/BlockWrapper.tsx +61 -0
- package/src/components/blocks/ButtonBlock.tsx +4 -4
- package/src/components/blocks/ChildBlocksTree.tsx +23 -25
- package/src/components/blocks/CodeBlock.tsx +15 -15
- package/src/components/blocks/ColumnsBlock.tsx +6 -44
- package/src/components/blocks/DividerBlock.tsx +3 -3
- package/src/components/blocks/FileBlock.tsx +4 -4
- package/src/components/blocks/HeadingBlock.tsx +6 -38
- package/src/components/blocks/HeroBlock.tsx +4 -4
- package/src/components/blocks/ImageBlock.tsx +4 -4
- package/src/components/blocks/LinkBlock.tsx +4 -4
- package/src/components/blocks/ListBlock.tsx +3 -3
- package/src/components/blocks/ParagraphBlock.tsx +12 -42
- package/src/components/blocks/RelationshipBlock.tsx +4 -4
- package/src/components/blocks/RichTextBlock.tsx +4 -4
- package/src/components/blocks/VStackBlock.tsx +5 -37
- package/src/components/blocks/VideoBlock.tsx +4 -4
- package/src/components/blocks/types.ts +11 -0
- package/src/components/fields/AccordionField.tsx +1 -1
- package/src/components/fields/ArrayField.tsx +2 -2
- package/src/components/fields/ArrayLayout.tsx +93 -0
- package/src/components/fields/BlocksField.tsx +122 -111
- package/src/components/fields/ButtonField.tsx +1 -1
- package/src/components/fields/CheckboxField.tsx +14 -15
- package/src/components/fields/ChildrenField.tsx +2 -2
- package/src/components/fields/CodeField.tsx +3 -3
- package/src/components/fields/ColumnsField.tsx +2 -2
- package/src/components/fields/DateField.tsx +13 -26
- package/src/components/fields/EditorClient.tsx +26 -28
- package/src/components/fields/FieldLayout.tsx +52 -0
- package/src/components/fields/GroupLayout.tsx +35 -0
- package/src/components/fields/JSONField.tsx +7 -7
- package/src/components/fields/LinkField.tsx +1 -1
- package/src/components/fields/MarkdownField.tsx +1 -1
- package/src/components/fields/NumberField.tsx +13 -26
- package/src/components/fields/PortableTextField.tsx +4 -4
- package/src/components/fields/PortableTextRenderer.tsx +1 -1
- package/src/components/fields/RelationshipBlockField.tsx +31 -23
- package/src/components/fields/RelationshipField.tsx +14 -14
- package/src/components/fields/SelectField.tsx +17 -26
- package/src/components/fields/TabsLayout.tsx +69 -0
- package/src/components/fields/TextField.tsx +85 -38
- package/src/components/fields/UploadField.tsx +71 -41
- package/src/components/fields/VideoField.tsx +1 -1
- package/src/components/fields/extensions/blockComponents.tsx +2 -2
- package/src/components/fields/extensions/blocksStore.ts +207 -193
- package/src/components/fields/types.ts +22 -0
- package/src/components/layout/Layout.tsx +1 -1
- package/src/components/ui/ActionMenu.tsx +63 -0
- package/src/components/ui/Badge.tsx +59 -5
- package/src/components/ui/BlockDrawer.tsx +4 -5
- package/src/components/ui/CommandPalette.tsx +58 -36
- package/src/components/ui/CommandPaletteWrapper.tsx +18 -17
- package/src/components/ui/Dropdown.tsx +18 -16
- package/src/components/ui/EmptyState.tsx +25 -0
- package/src/components/ui/GlobalModal.tsx +49 -0
- package/src/components/ui/IconButton.tsx +44 -0
- package/src/components/ui/Modal.tsx +19 -20
- package/src/components/ui/PageHeader.tsx +158 -0
- package/src/components/ui/Pagination.tsx +61 -0
- package/src/components/ui/PromptModal.tsx +1 -1
- package/src/components/ui/SearchInput.tsx +57 -0
- package/src/components/ui/SeoPreview.tsx +31 -0
- package/src/components/ui/SessionModal.tsx +0 -0
- package/src/components/ui/SlidePanel.tsx +2 -0
- package/src/components/ui/Toast.tsx +65 -122
- package/src/components/ui/Toaster.tsx +18 -0
- package/src/components/ui/icons.tsx +112 -0
- package/src/components/users/UserDetail.tsx +290 -0
- package/src/components/users/UserForm.tsx +242 -0
- package/src/components/users/UsersList.tsx +338 -0
- package/src/env.d.ts +13 -13
- package/src/fields/index.ts +2 -1
- package/src/global.d.ts +7 -0
- package/src/hooks/data.ts +2 -9
- package/src/hooks/useAsyncData.ts +36 -0
- package/src/hooks/useAutoFormState.ts +527 -0
- package/src/hooks/useSelection.ts +49 -0
- package/src/hooks/useSession.ts +0 -0
- package/src/index.ts +11 -1
- package/src/integration.ts +86 -11
- package/src/kyro-cms.d.ts +209 -0
- package/src/layouts/AdminLayout.astro +128 -11
- package/src/layouts/AuthLayout.astro +21 -5
- package/src/lib/api.ts +175 -55
- package/src/lib/autoform-store.ts +435 -0
- package/src/lib/config.ts +82 -34
- package/src/lib/createRegistry.ts +29 -0
- package/src/lib/default-kyro-config.ts +4 -0
- package/src/lib/globals.ts +50 -0
- package/src/lib/media-utils.ts +18 -0
- package/src/lib/object-utils.ts +77 -0
- package/src/lib/paths.ts +61 -0
- package/src/lib/stores/index.ts +370 -0
- package/src/lib/types.ts +43 -0
- package/src/lib/useResourceManager.ts +105 -0
- package/src/pages/403.astro +67 -0
- package/src/pages/[collection]/[id].astro +14 -180
- package/src/pages/[collection]/index.astro +11 -6
- package/src/pages/api-explorer.astro +173 -0
- package/src/pages/audit/index.astro +2 -0
- package/src/pages/auth/login.astro +122 -0
- package/src/pages/auth/register.astro +167 -0
- package/src/pages/graphql-explorer.astro +59 -0
- package/src/pages/{admin/graphql.astro → graphql.astro} +51 -17
- package/src/pages/index.astro +577 -0
- package/src/pages/index_ALT.astro +3 -0
- package/src/pages/keys.astro +11 -0
- package/src/pages/marketplace.astro +11 -0
- package/src/pages/media.astro +3 -0
- package/src/pages/plugins.astro +8 -0
- package/src/pages/preview/[collection]/[id].astro +188 -123
- package/src/pages/rest-playground.astro +62 -0
- package/src/pages/roles/index.astro +183 -76
- package/src/pages/sessions.astro +8 -0
- package/src/pages/settings/[slug].astro +92 -114
- package/src/pages/settings/index.astro +5 -3
- package/src/pages/users/[id].astro +25 -154
- package/src/pages/users/index.astro +19 -130
- package/src/pages/users/new.astro +9 -86
- package/src/pages/webhooks.astro +11 -0
- package/src/routes.ts +80 -0
- package/src/styles/main.css +119 -79
- package/src/theme/tokens.ts +1 -0
- package/src/vite-env.d.ts +14 -0
- package/src/collections/auth/index.ts +0 -155
- package/src/collections/portfolio/index.ts +0 -343
- package/src/components/ApiExplorer.tsx +0 -325
- package/src/components/EnhancedListView.tsx +0 -889
- package/src/components/GraphQLExplorer.tsx +0 -675
- package/src/components/Icons.tsx +0 -23
- package/src/components/StatusBadge.tsx +0 -76
- package/src/lib/MediaService.ts +0 -541
- package/src/lib/auth/sqlite-adapter.ts +0 -319
- package/src/lib/dataStore.ts +0 -226
- package/src/lib/db/adapter.ts +0 -54
- package/src/lib/db/drizzle-mysql-adapter.ts +0 -194
- package/src/lib/db/drizzle-mysql-auth-adapter.ts +0 -327
- package/src/lib/db/drizzle-postgres-adapter.ts +0 -202
- package/src/lib/db/drizzle-postgres-auth-adapter.ts +0 -304
- package/src/lib/db/drizzle-sqlite-adapter.ts +0 -227
- package/src/lib/db/drizzle-sqlite-auth-adapter.ts +0 -548
- package/src/lib/db/index.ts +0 -449
- package/src/lib/db/mongodb-adapter.ts +0 -207
- package/src/lib/db/mongodb-auth-adapter.ts +0 -305
- package/src/lib/db/schema/mysql-auth.ts +0 -113
- package/src/lib/db/schema/mysql-content.ts +0 -20
- package/src/lib/db/schema/postgres-auth.ts +0 -116
- package/src/lib/db/schema/postgres-content.ts +0 -35
- package/src/lib/db/schema/postgres-media.ts +0 -52
- package/src/lib/db/schema/postgres-settings.ts +0 -11
- package/src/lib/db/schema/sqlite-auth.ts +0 -112
- package/src/lib/db/schema/sqlite-content.ts +0 -20
- package/src/lib/db/version-adapter.ts +0 -248
- package/src/lib/graphql/index.ts +0 -1
- package/src/lib/graphql/schema.ts +0 -443
- package/src/lib/rate-limit.ts +0 -267
- package/src/lib/storage.ts +0 -374
- package/src/lib/store.ts +0 -85
- package/src/middleware.ts +0 -177
- package/src/pages/admin/api-explorer.astro +0 -98
- package/src/pages/admin/graphql-explorer.astro +0 -40
- package/src/pages/admin/index.astro +0 -286
- package/src/pages/admin/keys.astro +0 -8
- package/src/pages/admin/rest-playground.astro +0 -44
- package/src/pages/admin/webhooks.astro +0 -8
- package/src/pages/api/[collection]/[id]/publish.ts +0 -52
- package/src/pages/api/[collection]/[id]/unpublish.ts +0 -42
- package/src/pages/api/[collection]/[id]/versions.ts +0 -66
- package/src/pages/api/[collection]/[id].ts +0 -213
- package/src/pages/api/[collection]/index.ts +0 -209
- package/src/pages/api/auth/[id].ts +0 -121
- package/src/pages/api/auth/audit-logs.ts +0 -57
- package/src/pages/api/auth/login.ts +0 -211
- package/src/pages/api/auth/logout.ts +0 -66
- package/src/pages/api/auth/me.ts +0 -36
- package/src/pages/api/auth/refresh.ts +0 -119
- package/src/pages/api/auth/register.ts +0 -188
- package/src/pages/api/auth/users.ts +0 -97
- package/src/pages/api/collections.ts +0 -59
- package/src/pages/api/globals/[slug].ts +0 -42
- package/src/pages/api/graphql.ts +0 -90
- package/src/pages/api/health.ts +0 -426
- package/src/pages/api/keys/[id].ts +0 -26
- package/src/pages/api/keys/index.ts +0 -75
- package/src/pages/api/media/[id].ts +0 -309
- package/src/pages/api/media/folders.ts +0 -609
- package/src/pages/api/media/index.ts +0 -146
- package/src/pages/api/media/resize.ts +0 -267
- package/src/pages/api/search.ts +0 -82
- package/src/pages/api/slug-availability.ts +0 -70
- package/src/pages/api/storage-config.ts +0 -20
- package/src/pages/api/storage-status.ts +0 -206
- package/src/pages/api/upload.ts +0 -334
- package/src/pages/api/webhooks/index.ts +0 -71
- package/src/pages/login.astro +0 -82
- package/src/pages/register.astro +0 -102
|
@@ -3,12 +3,12 @@ import {
|
|
|
3
3
|
useBlockById,
|
|
4
4
|
useBlockActions,
|
|
5
5
|
} from "../fields/extensions/blocksStore";
|
|
6
|
-
import { ChevronRight, X } from "
|
|
6
|
+
import { ChevronRight, X } from "../ui/icons";
|
|
7
7
|
import { HeroField } from "../fields/HeroField";
|
|
8
8
|
import { UploadField } from "../fields/UploadField";
|
|
9
9
|
import { ChildBlocksTree } from "./ChildBlocksTree";
|
|
10
10
|
|
|
11
|
-
export const HeroBlock: React.FC<{ block:
|
|
11
|
+
export const HeroBlock: React.FC<{ block: Record<string, unknown>; index: number }> = ({
|
|
12
12
|
block,
|
|
13
13
|
index,
|
|
14
14
|
}) => {
|
|
@@ -18,7 +18,7 @@ export const HeroBlock: React.FC<{ block: any; index: number }> = ({
|
|
|
18
18
|
const data = blockData?.data ?? block.data ?? {};
|
|
19
19
|
const children = blockData?.children ?? block.children ?? [];
|
|
20
20
|
|
|
21
|
-
const handleChange = (field: string, value:
|
|
21
|
+
const handleChange = (field: string, value: unknown) => {
|
|
22
22
|
updateBlock(block.id, { data: { ...data, [field]: value } });
|
|
23
23
|
};
|
|
24
24
|
|
|
@@ -26,7 +26,7 @@ export const HeroBlock: React.FC<{ block: any; index: number }> = ({
|
|
|
26
26
|
<div className="block-hero border border-[var(--kyro-border)] rounded-md p-3 mb-2 relative group">
|
|
27
27
|
<div className="flex items-center justify-between mb-2">
|
|
28
28
|
<div className="flex items-center gap-2">
|
|
29
|
-
<span className="text-xs font-semibold text-[var(--kyro-text-muted)]
|
|
29
|
+
<span className="text-xs font-semibold text-[var(--kyro-text-muted)] ">
|
|
30
30
|
Hero Section
|
|
31
31
|
</span>
|
|
32
32
|
</div>
|
|
@@ -3,10 +3,10 @@ import {
|
|
|
3
3
|
useBlockById,
|
|
4
4
|
useBlockActions,
|
|
5
5
|
} from "../fields/extensions/blocksStore";
|
|
6
|
-
import { ChevronRight, X } from "
|
|
6
|
+
import { ChevronRight, X } from "../ui/icons";
|
|
7
7
|
import { UploadField } from "../fields/UploadField";
|
|
8
8
|
|
|
9
|
-
export const ImageBlock: React.FC<{ block:
|
|
9
|
+
export const ImageBlock: React.FC<{ block: Record<string, unknown>; index: number }> = ({
|
|
10
10
|
block,
|
|
11
11
|
index,
|
|
12
12
|
}) => {
|
|
@@ -14,14 +14,14 @@ export const ImageBlock: React.FC<{ block: any; index: number }> = ({
|
|
|
14
14
|
const { updateBlock, removeBlock, moveBlock } = useBlockActions();
|
|
15
15
|
const data = blockData?.data || block.data || {};
|
|
16
16
|
|
|
17
|
-
const handleChange = (field: string, value:
|
|
17
|
+
const handleChange = (field: string, value: unknown) => {
|
|
18
18
|
updateBlock(block.id, { data: { ...data, [field]: value } });
|
|
19
19
|
};
|
|
20
20
|
|
|
21
21
|
return (
|
|
22
22
|
<div className="block-image border border-[var(--kyro-border)] rounded-lg p-4 mb-4 relative group">
|
|
23
23
|
<div className="flex items-center justify-between mb-2">
|
|
24
|
-
<span className="text-xs font-semibold text-[var(--kyro-text-muted)]
|
|
24
|
+
<span className="text-xs font-semibold text-[var(--kyro-text-muted)] ">
|
|
25
25
|
Image
|
|
26
26
|
</span>
|
|
27
27
|
<div className="flex gap-1 opacity-0 group-hover:opacity-100 transition-opacity">
|
|
@@ -3,10 +3,10 @@ import {
|
|
|
3
3
|
useBlockById,
|
|
4
4
|
useBlockActions,
|
|
5
5
|
} from "../fields/extensions/blocksStore";
|
|
6
|
-
import { ChevronRight, X } from "
|
|
6
|
+
import { ChevronRight, X } from "../ui/icons";
|
|
7
7
|
import { LinkField } from "../fields/LinkField";
|
|
8
8
|
|
|
9
|
-
export const LinkBlock: React.FC<{ block:
|
|
9
|
+
export const LinkBlock: React.FC<{ block: Record<string, unknown>; index: number }> = ({
|
|
10
10
|
block,
|
|
11
11
|
index,
|
|
12
12
|
}) => {
|
|
@@ -15,14 +15,14 @@ export const LinkBlock: React.FC<{ block: any; index: number }> = ({
|
|
|
15
15
|
|
|
16
16
|
const data = blockData?.data ?? block.data ?? {};
|
|
17
17
|
|
|
18
|
-
const handleChange = (field: string, value:
|
|
18
|
+
const handleChange = (field: string, value: unknown) => {
|
|
19
19
|
updateBlock(block.id, { data: { ...data, [field]: value } });
|
|
20
20
|
};
|
|
21
21
|
|
|
22
22
|
return (
|
|
23
23
|
<div className="block-link border border-[var(--kyro-border)] rounded-md p-2.5 mb-2 relative group">
|
|
24
24
|
<div className="flex items-center gap-2">
|
|
25
|
-
<span className="text-[10px] font-bold text-[var(--kyro-text-muted)]
|
|
25
|
+
<span className="text-[10px] font-bold text-[var(--kyro-text-muted)] shrink-0 w-8">
|
|
26
26
|
Link
|
|
27
27
|
</span>
|
|
28
28
|
<div className="flex-1 min-w-0">
|
|
@@ -3,10 +3,10 @@ import {
|
|
|
3
3
|
useBlockById,
|
|
4
4
|
useBlockActions,
|
|
5
5
|
} from "../fields/extensions/blocksStore";
|
|
6
|
-
import { ChevronRight, X } from "
|
|
6
|
+
import { ChevronRight, X } from "../ui/icons";
|
|
7
7
|
import { ListField } from "../fields/ListField";
|
|
8
8
|
|
|
9
|
-
export const ListBlock: React.FC<{ block:
|
|
9
|
+
export const ListBlock: React.FC<{ block: Record<string, unknown>; index: number }> = ({
|
|
10
10
|
block,
|
|
11
11
|
index,
|
|
12
12
|
}) => {
|
|
@@ -23,7 +23,7 @@ export const ListBlock: React.FC<{ block: any; index: number }> = ({
|
|
|
23
23
|
return (
|
|
24
24
|
<div className="block-list border border-[var(--kyro-border)] rounded-md p-3 mb-2 relative group">
|
|
25
25
|
<div className="flex items-center justify-between mb-1">
|
|
26
|
-
<span className="text-xs font-semibold text-[var(--kyro-text-muted)]
|
|
26
|
+
<span className="text-xs font-semibold text-[var(--kyro-text-muted)] ">
|
|
27
27
|
List
|
|
28
28
|
</span>
|
|
29
29
|
<div className="flex gap-1 opacity-0 group-hover:opacity-100 transition-opacity">
|
|
@@ -3,59 +3,29 @@ import {
|
|
|
3
3
|
useBlockById,
|
|
4
4
|
useBlockActions,
|
|
5
5
|
} from "../fields/extensions/blocksStore";
|
|
6
|
-
import {
|
|
6
|
+
import { BlockWrapper } from "./BlockWrapper";
|
|
7
7
|
|
|
8
|
-
export const ParagraphBlock: React.FC<{ block:
|
|
8
|
+
export const ParagraphBlock: React.FC<{ block: Record<string, unknown>; index: number }> = ({
|
|
9
9
|
block,
|
|
10
10
|
index,
|
|
11
11
|
}) => {
|
|
12
12
|
const blockData = useBlockById(block.id);
|
|
13
|
-
const { updateBlock
|
|
13
|
+
const { updateBlock } = useBlockActions();
|
|
14
14
|
|
|
15
15
|
const data = blockData?.data || block.data || {};
|
|
16
16
|
|
|
17
|
-
const handleChange = (field: string, value:
|
|
17
|
+
const handleChange = (field: string, value: unknown) => {
|
|
18
18
|
updateBlock(block.id, { data: { ...data, [field]: value } });
|
|
19
19
|
};
|
|
20
20
|
|
|
21
21
|
return (
|
|
22
|
-
<
|
|
23
|
-
<
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
className="p-1 hover:bg-[var(--kyro-surface-accent)] rounded"
|
|
31
|
-
title="Move up"
|
|
32
|
-
>
|
|
33
|
-
<ChevronRight className="w-3 h-3 rotate-90" />
|
|
34
|
-
</button>
|
|
35
|
-
<button type="button"
|
|
36
|
-
onClick={() => moveBlock(block.id, "down")}
|
|
37
|
-
className="p-1 hover:bg-[var(--kyro-surface-accent)] rounded"
|
|
38
|
-
title="Move down"
|
|
39
|
-
>
|
|
40
|
-
<ChevronRight className="w-3 h-3" />
|
|
41
|
-
</button>
|
|
42
|
-
<button type="button"
|
|
43
|
-
onClick={() => removeBlock(block.id)}
|
|
44
|
-
className="p-1 hover:bg-[var(--kyro-surface-accent)] rounded"
|
|
45
|
-
title="Remove"
|
|
46
|
-
>
|
|
47
|
-
<X className="w-3 h-3" />
|
|
48
|
-
</button>
|
|
49
|
-
</div>
|
|
50
|
-
</div>
|
|
51
|
-
<div>
|
|
52
|
-
<textarea
|
|
53
|
-
value={data.text || ""}
|
|
54
|
-
onChange={(e) => handleChange("text", e.target.value)}
|
|
55
|
-
className="w-full px-3 py-3 border border-[var(--kyro-border)] rounded bg-[var(--kyro-surface)] text-[var(--kyro-text-primary)] text-sm min-h-[100px] resize-none"
|
|
56
|
-
placeholder="Enter paragraph text..."
|
|
57
|
-
/>
|
|
58
|
-
</div>
|
|
59
|
-
</div>
|
|
22
|
+
<BlockWrapper id={block.id} type="paragraph" label="Paragraph">
|
|
23
|
+
<textarea
|
|
24
|
+
value={data.text || ""}
|
|
25
|
+
onChange={(e) => handleChange("text", e.target.value)}
|
|
26
|
+
className="w-full px-3 py-3 border border-[var(--kyro-border)] rounded bg-[var(--kyro-surface)] text-[var(--kyro-text-primary)] text-sm min-h-[100px] resize-none"
|
|
27
|
+
placeholder="Enter paragraph text..."
|
|
28
|
+
/>
|
|
29
|
+
</BlockWrapper>
|
|
60
30
|
);
|
|
61
31
|
};
|
|
@@ -3,10 +3,10 @@ import {
|
|
|
3
3
|
useBlockById,
|
|
4
4
|
useBlockActions,
|
|
5
5
|
} from "../fields/extensions/blocksStore";
|
|
6
|
-
import { ChevronRight, X } from "
|
|
6
|
+
import { ChevronRight, X } from "../ui/icons";
|
|
7
7
|
import { RelationshipBlockField } from "../fields/RelationshipBlockField";
|
|
8
8
|
|
|
9
|
-
export const RelationshipBlock: React.FC<{ block:
|
|
9
|
+
export const RelationshipBlock: React.FC<{ block: Record<string, unknown>; index: number }> = ({
|
|
10
10
|
block,
|
|
11
11
|
index,
|
|
12
12
|
}) => {
|
|
@@ -15,7 +15,7 @@ export const RelationshipBlock: React.FC<{ block: any; index: number }> = ({
|
|
|
15
15
|
|
|
16
16
|
const data = blockData?.data ?? block.data ?? {};
|
|
17
17
|
|
|
18
|
-
const handleChange = (field: string, value:
|
|
18
|
+
const handleChange = (field: string, value: unknown) => {
|
|
19
19
|
updateBlock(block.id, { data: { ...data, [field]: value } });
|
|
20
20
|
};
|
|
21
21
|
|
|
@@ -23,7 +23,7 @@ export const RelationshipBlock: React.FC<{ block: any; index: number }> = ({
|
|
|
23
23
|
<div className="block-relationship border border-[var(--kyro-border)] rounded-md p-3 mb-2 relative group">
|
|
24
24
|
<div className="flex items-center justify-between mb-1">
|
|
25
25
|
<div className="flex items-center gap-2">
|
|
26
|
-
<span className="text-xs font-semibold text-[var(--kyro-text-muted)]
|
|
26
|
+
<span className="text-xs font-semibold text-[var(--kyro-text-muted)] ">
|
|
27
27
|
Relationship
|
|
28
28
|
</span>
|
|
29
29
|
<span className="text-[10px] text-[var(--kyro-text-muted)]">
|
|
@@ -3,10 +3,10 @@ import {
|
|
|
3
3
|
useBlockById,
|
|
4
4
|
useBlockActions,
|
|
5
5
|
} from "../fields/extensions/blocksStore";
|
|
6
|
-
import { ChevronRight, X, AlignLeft } from "
|
|
6
|
+
import { ChevronRight, X, AlignLeft } from "../ui/icons";
|
|
7
7
|
import PortableTextField from "../fields/PortableTextField";
|
|
8
8
|
|
|
9
|
-
export const RichTextBlock: React.FC<{ block:
|
|
9
|
+
export const RichTextBlock: React.FC<{ block: Record<string, unknown>; index: number }> = ({
|
|
10
10
|
block,
|
|
11
11
|
index,
|
|
12
12
|
}) => {
|
|
@@ -15,7 +15,7 @@ export const RichTextBlock: React.FC<{ block: any; index: number }> = ({
|
|
|
15
15
|
|
|
16
16
|
const data = blockData?.data || block.data || {};
|
|
17
17
|
|
|
18
|
-
const handleChange = (newValue:
|
|
18
|
+
const handleChange = (newValue: unknown) => {
|
|
19
19
|
updateBlock(block.id, { data: { ...data, content: newValue } });
|
|
20
20
|
};
|
|
21
21
|
|
|
@@ -24,7 +24,7 @@ export const RichTextBlock: React.FC<{ block: any; index: number }> = ({
|
|
|
24
24
|
<div className="flex items-center justify-between mb-2">
|
|
25
25
|
<div className="flex items-center gap-2">
|
|
26
26
|
<AlignLeft className="w-3.5 h-3.5 text-[var(--kyro-primary)]" />
|
|
27
|
-
<span className="text-xs font-semibold text-[var(--kyro-text-muted)]
|
|
27
|
+
<span className="text-xs font-semibold text-[var(--kyro-text-muted)] ">
|
|
28
28
|
Rich Text
|
|
29
29
|
</span>
|
|
30
30
|
</div>
|
|
@@ -3,59 +3,27 @@ import {
|
|
|
3
3
|
useBlockById,
|
|
4
4
|
useBlockActions,
|
|
5
5
|
} from "../fields/extensions/blocksStore";
|
|
6
|
-
import { ChevronRight, X } from "lucide-react";
|
|
7
6
|
import { ChildrenField } from "../fields/ChildrenField";
|
|
7
|
+
import { BlockWrapper } from "./BlockWrapper";
|
|
8
8
|
|
|
9
|
-
export const VStackBlock: React.FC<{ block:
|
|
9
|
+
export const VStackBlock: React.FC<{ block: Record<string, unknown>; index: number }> = ({
|
|
10
10
|
block,
|
|
11
11
|
index,
|
|
12
12
|
}) => {
|
|
13
13
|
const blockData = useBlockById(block.id);
|
|
14
|
-
const { updateBlock
|
|
14
|
+
const { updateBlock } = useBlockActions();
|
|
15
15
|
|
|
16
16
|
const data = blockData?.data ?? block.data ?? {};
|
|
17
17
|
const children = blockData?.children ?? block.children ?? [];
|
|
18
18
|
|
|
19
19
|
return (
|
|
20
|
-
<
|
|
21
|
-
<div className="flex items-center justify-between mb-1">
|
|
22
|
-
<span className="text-xs font-semibold text-[var(--kyro-text-muted)] uppercase">
|
|
23
|
-
Stack
|
|
24
|
-
</span>
|
|
25
|
-
<div className="flex gap-1 opacity-0 group-hover:opacity-100 transition-opacity">
|
|
26
|
-
<button
|
|
27
|
-
type="button"
|
|
28
|
-
onClick={() => moveBlock(block.id, "up")}
|
|
29
|
-
className="p-1 hover:bg-[var(--kyro-surface-accent)] rounded"
|
|
30
|
-
title="Move up"
|
|
31
|
-
>
|
|
32
|
-
<ChevronRight className="w-3 h-3 rotate-90" />
|
|
33
|
-
</button>
|
|
34
|
-
<button
|
|
35
|
-
type="button"
|
|
36
|
-
onClick={() => moveBlock(block.id, "down")}
|
|
37
|
-
className="p-1 hover:bg-[var(--kyro-surface-accent)] rounded"
|
|
38
|
-
title="Move down"
|
|
39
|
-
>
|
|
40
|
-
<ChevronRight className="w-3 h-3" />
|
|
41
|
-
</button>
|
|
42
|
-
<button
|
|
43
|
-
type="button"
|
|
44
|
-
onClick={() => removeBlock(block.id)}
|
|
45
|
-
className="p-1 hover:bg-red-50 rounded text-red-500"
|
|
46
|
-
title="Remove"
|
|
47
|
-
>
|
|
48
|
-
<X className="w-3 h-3" />
|
|
49
|
-
</button>
|
|
50
|
-
</div>
|
|
51
|
-
</div>
|
|
52
|
-
|
|
20
|
+
<BlockWrapper id={block.id} type="vstack" label="Stack">
|
|
53
21
|
<ChildrenField
|
|
54
22
|
blockId={block.id}
|
|
55
23
|
children={children}
|
|
56
24
|
onUpdateChildren={(c) => updateBlock(block.id, { children: c })}
|
|
57
25
|
compact
|
|
58
26
|
/>
|
|
59
|
-
</
|
|
27
|
+
</BlockWrapper>
|
|
60
28
|
);
|
|
61
29
|
};
|
|
@@ -3,10 +3,10 @@ import {
|
|
|
3
3
|
useBlockById,
|
|
4
4
|
useBlockActions,
|
|
5
5
|
} from "../fields/extensions/blocksStore";
|
|
6
|
-
import { ChevronRight, X } from "
|
|
6
|
+
import { ChevronRight, X } from "../ui/icons";
|
|
7
7
|
import { VideoField } from "../fields/VideoField";
|
|
8
8
|
|
|
9
|
-
export const VideoBlock: React.FC<{ block:
|
|
9
|
+
export const VideoBlock: React.FC<{ block: Record<string, unknown>; index: number }> = ({
|
|
10
10
|
block,
|
|
11
11
|
index,
|
|
12
12
|
}) => {
|
|
@@ -15,14 +15,14 @@ export const VideoBlock: React.FC<{ block: any; index: number }> = ({
|
|
|
15
15
|
|
|
16
16
|
const data = blockData?.data ?? block.data ?? {};
|
|
17
17
|
|
|
18
|
-
const handleChange = (field: string, value:
|
|
18
|
+
const handleChange = (field: string, value: unknown) => {
|
|
19
19
|
updateBlock(block.id, { data: { ...data, [field]: value } });
|
|
20
20
|
};
|
|
21
21
|
|
|
22
22
|
return (
|
|
23
23
|
<div className="block-video border border-[var(--kyro-border)] rounded-md p-3 mb-2 relative group">
|
|
24
24
|
<div className="flex items-center justify-between mb-1">
|
|
25
|
-
<span className="text-xs font-semibold text-[var(--kyro-text-muted)]
|
|
25
|
+
<span className="text-xs font-semibold text-[var(--kyro-text-muted)] ">
|
|
26
26
|
Video
|
|
27
27
|
</span>
|
|
28
28
|
<div className="flex gap-1 opacity-0 group-hover:opacity-100 transition-opacity">
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import { Plus, ChevronDown, ChevronUp, X } from "
|
|
2
|
+
import { Plus, ChevronDown, ChevronUp, X } from "../ui/icons";
|
|
3
3
|
|
|
4
4
|
interface ArrayFieldItem {
|
|
5
|
-
[key: string]:
|
|
5
|
+
[key: string]: unknown;
|
|
6
6
|
}
|
|
7
7
|
|
|
8
8
|
interface ArrayFieldProps {
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import type { Field } from "@kyro-cms/core/client";
|
|
3
|
+
import RelationshipField from "./RelationshipField";
|
|
4
|
+
|
|
5
|
+
interface ArrayLayoutProps {
|
|
6
|
+
field: Field;
|
|
7
|
+
value: unknown[];
|
|
8
|
+
onChange: (value: unknown[]) => void;
|
|
9
|
+
renderField: (
|
|
10
|
+
field: Field,
|
|
11
|
+
parentData: Record<string, unknown>,
|
|
12
|
+
onChange: (value: unknown) => void,
|
|
13
|
+
) => React.ReactNode;
|
|
14
|
+
disabled?: boolean;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function ArrayLayout({
|
|
18
|
+
field,
|
|
19
|
+
value,
|
|
20
|
+
onChange,
|
|
21
|
+
renderField,
|
|
22
|
+
disabled,
|
|
23
|
+
}: ArrayLayoutProps) {
|
|
24
|
+
const items = Array.isArray(value) ? value : [];
|
|
25
|
+
const labelField = (field as Field & { fields?: { name?: string; type?: string; relationTo?: string; label?: string }[] }).fields?.[0]?.name || "user";
|
|
26
|
+
const isRelationship = (field as Field & { fields?: { type?: string }[] }).fields?.[0]?.type === "relationship";
|
|
27
|
+
|
|
28
|
+
return (
|
|
29
|
+
<div className="kyro-form-field">
|
|
30
|
+
<label className="kyro-form-label">{field.label || field.name}</label>
|
|
31
|
+
{isRelationship ? (
|
|
32
|
+
<RelationshipField
|
|
33
|
+
field={{
|
|
34
|
+
name: labelField,
|
|
35
|
+
relationTo: (field as Field & { fields?: { relationTo?: string }[] }).fields?.[0]?.relationTo || "",
|
|
36
|
+
hasMany: true,
|
|
37
|
+
label: (field as Field & { fields?: { label?: string }[] }).fields?.[0]?.label,
|
|
38
|
+
}}
|
|
39
|
+
value={(items as Record<string, unknown>[]).map((i) => i[labelField]).filter(Boolean)}
|
|
40
|
+
onChange={(newValue) => {
|
|
41
|
+
const newItems = (newValue || []).map((id: string) => ({
|
|
42
|
+
[labelField]: id,
|
|
43
|
+
}));
|
|
44
|
+
onChange(newItems);
|
|
45
|
+
}}
|
|
46
|
+
disabled={disabled}
|
|
47
|
+
/>
|
|
48
|
+
) : (
|
|
49
|
+
<div className="kyro-form-array border border-[var(--kyro-border)] bg-[var(--kyro-surface-accent)]/30 rounded-[var(--kyro-radius-md)] p-4 space-y-4">
|
|
50
|
+
{(items as Record<string, unknown>[]).map((item, index) => (
|
|
51
|
+
<div
|
|
52
|
+
key={index}
|
|
53
|
+
className="kyro-form-array-item bg-[var(--kyro-surface)] border border-[var(--kyro-border)] rounded-[var(--kyro-radius-md)] p-4 relative group"
|
|
54
|
+
>
|
|
55
|
+
<div className="flex justify-between items-center mb-4 pb-2 border-b border-[var(--kyro-border)]">
|
|
56
|
+
<span className="text-[10px] font-bold tracking-widest text-[var(--kyro-text-muted)]">
|
|
57
|
+
Item {index + 1}
|
|
58
|
+
</span>
|
|
59
|
+
<button
|
|
60
|
+
type="button"
|
|
61
|
+
disabled={disabled}
|
|
62
|
+
className="text-[11px] font-bold text-[var(--kyro-error)] opacity-50 hover:opacity-100 transition-opacity disabled:opacity-30"
|
|
63
|
+
onClick={() =>
|
|
64
|
+
onChange(items.filter((_: unknown, i: number) => i !== index))
|
|
65
|
+
}
|
|
66
|
+
>
|
|
67
|
+
Remove
|
|
68
|
+
</button>
|
|
69
|
+
</div>
|
|
70
|
+
<div className="space-y-4">
|
|
71
|
+
{(field as Field & { fields?: Field[] }).fields.map((f: Field) =>
|
|
72
|
+
renderField(f, item, (newItem) => {
|
|
73
|
+
const newItems = [...items];
|
|
74
|
+
newItems[index] = newItem;
|
|
75
|
+
onChange(newItems);
|
|
76
|
+
}),
|
|
77
|
+
)}
|
|
78
|
+
</div>
|
|
79
|
+
</div>
|
|
80
|
+
))}
|
|
81
|
+
<button
|
|
82
|
+
type="button"
|
|
83
|
+
className="w-full py-3 border-2 border-dashed border-[var(--kyro-border)] rounded-[var(--kyro-radius-md)] text-xs font-bold text-[var(--kyro-text-secondary)] hover:text-[var(--kyro-primary)] hover:border-[var(--kyro-primary)] transition-all disabled:opacity-50"
|
|
84
|
+
disabled={disabled}
|
|
85
|
+
onClick={() => onChange([...items, {}])}
|
|
86
|
+
>
|
|
87
|
+
+ Add Item
|
|
88
|
+
</button>
|
|
89
|
+
</div>
|
|
90
|
+
)}
|
|
91
|
+
</div>
|
|
92
|
+
);
|
|
93
|
+
}
|