@kyro-cms/admin 0.2.4 → 0.3.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.
Files changed (68) hide show
  1. package/README.md +46 -272
  2. package/package.json +37 -10
  3. package/src/blocks/examples/sample-block-2.tsx +27 -0
  4. package/src/blocks/examples/sample-block.tsx +26 -0
  5. package/src/blocks/index.ts +14 -0
  6. package/src/blocks/registry.ts +38 -0
  7. package/src/blocks/types.ts +23 -0
  8. package/src/components/Admin.tsx +1 -1
  9. package/src/components/ApiKeysManager.tsx +1 -1
  10. package/src/components/AuditLogsPage.tsx +1 -1
  11. package/src/components/AutoForm.tsx +2 -2
  12. package/src/components/BrandingHub.tsx +1 -1
  13. package/src/components/CreateView.tsx +1 -1
  14. package/src/components/DetailView.tsx +1 -1
  15. package/src/components/DeveloperCenter.tsx +1 -1
  16. package/src/components/EnhancedListView.tsx +1 -1
  17. package/src/components/ListView.tsx +1 -1
  18. package/src/components/LoginPage.tsx +1 -1
  19. package/src/components/MediaGallery.tsx +1 -1
  20. package/src/components/UserManagement.tsx +1 -1
  21. package/src/components/WebhookManager.tsx +2 -2
  22. package/src/components/fields/RelationshipBlockField.tsx +1 -1
  23. package/src/components/fields/RelationshipField.tsx +1 -1
  24. package/src/components/fields/UploadField.tsx +1 -6
  25. package/src/components/ui/CommandPalette.tsx +1 -1
  26. package/src/fields/examples/sample-field-2.tsx +30 -0
  27. package/src/fields/examples/sample-field.tsx +30 -0
  28. package/src/fields/index.ts +33 -0
  29. package/src/fields/registry.tsx +46 -0
  30. package/src/fields/types.ts +24 -0
  31. package/src/hooks/data.ts +116 -0
  32. package/src/hooks/examples/sample-hook-2.ts +13 -0
  33. package/src/hooks/examples/sample-hook.ts +12 -0
  34. package/src/hooks/index.ts +19 -0
  35. package/src/hooks/lifecycle.ts +81 -0
  36. package/src/hooks/types.ts +40 -0
  37. package/src/index.ts +78 -0
  38. package/src/integration.ts +52 -0
  39. package/src/pages/api/[collection]/[id]/publish.ts +2 -2
  40. package/src/pages/api/[collection]/[id]/unpublish.ts +2 -2
  41. package/src/pages/api/[collection]/[id]/versions.ts +1 -1
  42. package/src/pages/api/[collection]/[id].ts +2 -2
  43. package/src/pages/api/[collection]/index.ts +2 -2
  44. package/src/pages/api/collections.ts +1 -1
  45. package/src/pages/api/globals/[slug].ts +2 -2
  46. package/src/pages/api/graphql.ts +3 -3
  47. package/src/pages/api/media/folders.ts +1 -1
  48. package/src/pages/api/media/index.ts +1 -1
  49. package/src/pages/api/media/resize.ts +1 -1
  50. package/src/pages/api/slug-availability.ts +2 -2
  51. package/src/pages/api/storage-config.ts +1 -1
  52. package/src/pages/api/storage-status.ts +1 -1
  53. package/src/pages/api/upload.ts +1 -1
  54. package/src/plugins/examples/sample-plugin-2.ts +21 -0
  55. package/src/plugins/examples/sample-plugin.ts +21 -0
  56. package/src/plugins/index.ts +10 -0
  57. package/src/plugins/registry.ts +36 -0
  58. package/src/plugins/types.ts +22 -0
  59. package/src/styles/main.css +2 -41
  60. package/src/theme/ThemeProvider.tsx +238 -0
  61. package/src/theme/index.ts +20 -0
  62. package/src/theme/tokens.ts +222 -0
  63. package/src/components/Modal.tsx +0 -206
  64. package/src/components/index.ts +0 -29
  65. package/src/env.ts +0 -20
  66. package/src/lib/i18n.tsx +0 -353
  67. package/src/lib/validation.ts +0 -250
  68. package/src/pages/api/globals/[slug]/test.ts +0 -171
package/README.md CHANGED
@@ -1,272 +1,46 @@
1
- # @kyro-cms/admin
2
-
3
- Admin dashboard for Kyro CMS — a React-based admin interface built with Astro.
4
-
5
- Uses `@kyro-cms/utils` for API calls, date formatting, and validation.
6
-
7
- ## Features
8
-
9
- - **Multi-Database Support** SQLite, PostgreSQL, MySQL, MongoDB
10
- - **Authentication** JWT-based login/logout with auto-selecting auth adapter
11
- - **Shared Utilities** — Uses @kyro-cms/utils for consistent API handling
12
- - **Collection Management** — Create, edit, and manage content collections
13
- - **User Management** — Manage users, roles, and permissions
14
- - **Settings** — Configure CMS settings, globals, and plugins
15
- - **Responsive** Mobile-friendly dashboard with Tailwind CSS
16
-
17
- ## Quick Start
18
-
19
- ### Prerequisites
20
-
21
- - Node.js 18+
22
- - A Kyro CMS project with `@kyro-cms/core` installed
23
-
24
- ### Development
25
-
26
- ```bash
27
- # Install dependencies
28
- npm install
29
-
30
- # Start dev server
31
- npm run dev
32
-
33
- # Build for production
34
- npm run build
35
-
36
- # Preview production build
37
- npm run preview
38
-
39
- # Type check
40
- npm run check
41
-
42
- # Run tests
43
- npm run test:run
44
- ```
45
-
46
- ### Integration with Kyro CMS
47
-
48
- The admin dashboard is designed to work alongside a Kyro CMS project. In your Astro project:
49
-
50
- 1. Install the admin package:
51
-
52
- ```bash
53
- npm install @kyro-cms/admin
54
- ```
55
-
56
- 2. Create an admin page at `src/pages/admin/index.astro`:
57
-
58
- ```astro
59
- ---
60
- import { Admin } from '@kyro-cms/admin';
61
- import config from '../../../kyro.config';
62
- ---
63
- <!DOCTYPE html>
64
- <html lang="en">
65
- <head>
66
- <meta charset="UTF-8" />
67
- <meta name="viewport" content="width=device-width, initial-scale=1.0" />
68
- <title>Admin - My Kyro CMS</title>
69
- </head>
70
- <body>
71
- <Admin client:load config={config} />
72
- </body>
73
- </html>
74
- ```
75
-
76
- 3. Configure your `astro.config.mjs` with the Node adapter:
77
-
78
- ```js
79
- import { defineConfig } from "astro/config";
80
- import node from "@astrojs/node";
81
-
82
- export default defineConfig({
83
- output: "server",
84
- adapter: node({ mode: "standalone" }),
85
- });
86
- ```
87
-
88
- ## Database Configuration
89
-
90
- The admin supports multiple database backends. The auth system automatically uses the same database as your content data.
91
-
92
- ### SQLite (Default)
93
-
94
- ```bash
95
- # No configuration needed - uses ./data/kyro.db
96
- DB_TYPE=sqlite
97
- ```
98
-
99
- ### PostgreSQL
100
-
101
- ```bash
102
- DB_TYPE=postgres
103
- DB_HOST=localhost
104
- DB_PORT=5432
105
- DB_NAME=kyro
106
- DB_USER=admin
107
- DB_PASSWORD=secret
108
- # Or use connection string
109
- DB_CONNECTION_STRING=postgresql://admin:secret@localhost:5432/kyro
110
- ```
111
-
112
- ### MySQL
113
-
114
- ```bash
115
- DB_TYPE=mysql
116
- DB_HOST=localhost
117
- DB_PORT=3306
118
- DB_NAME=kyro
119
- DB_USER=root
120
- DB_PASSWORD=secret
121
- ```
122
-
123
- ### MongoDB
124
-
125
- ```bash
126
- DB_TYPE=mongodb
127
- DB_HOST=localhost
128
- DB_PORT=27017
129
- DB_NAME=kyro
130
- # Or use connection string
131
- DB_CONNECTION_STRING=mongodb://admin:secret@localhost:27017/kyro
132
- ```
133
-
134
- ### Connection Pooling
135
-
136
- For PostgreSQL and MySQL, configure connection pool:
137
-
138
- ```bash
139
- DB_POOL_MIN=5
140
- DB_POOL_MAX=20
141
- ```
142
-
143
- ### Environment Variables
144
-
145
- | Variable | Description | Default |
146
- | ------------------------- | --------------------------------------------- | ------------------------- |
147
- | `DB_TYPE` | Database type (sqlite/postgres/mysql/mongodb) | `sqlite` |
148
- | `DB_CONNECTION_STRING` | Full connection URI | - |
149
- | `DB_HOST` | Database host | `localhost` |
150
- | `DB_PORT` | Database port | 5432/3306/27017 |
151
- | `DB_NAME` | Database name | `kyro` |
152
- | `DB_USER` | Database username | - |
153
- | `DB_PASSWORD` | Database password | - |
154
- | `DB_POOL_MIN` | Minimum pool connections | 5 |
155
- | `DB_POOL_MAX` | Maximum pool connections | 20 |
156
- | `JWT_SECRET` | Secret for signing JWT tokens | `change-me-in-production` |
157
- | `JWT_EXPIRES_IN` | Token expiration time | `24h` |
158
- | `KYRO_ALLOW_REGISTRATION` | Allow public registration | `true` |
159
-
160
- ## Authentication
161
-
162
- Auth is automatically handled by the adapter matching your `DB_TYPE`:
163
-
164
- - **SQLite** → Uses SQLiteAuthAdapter (local file-based)
165
- - **Postgres** → Uses PostgresAuthAdapter (same DB)
166
- - **MongoDB** → Uses MongoDBAuthAdapter (same DB)
167
-
168
- ### Creating Your First Admin User
169
-
170
- 1. Start the dev server: `npm run dev`
171
- 2. Visit `http://localhost:4321/admin`
172
- 3. Register with your email and password
173
- 4. The first user automatically gets the `super_admin` role
174
-
175
- ### Auth API Endpoints
176
-
177
- | Endpoint | Method | Description |
178
- | -------------------- | ------ | ---------------------------- |
179
- | `/api/auth/login` | POST | Authenticate user |
180
- | `/api/auth/register` | POST | Register new user |
181
- | `/api/auth/logout` | POST | Invalidate session |
182
- | `/api/auth/me` | GET | Get current user info |
183
- | `/api/auth/users` | GET | List all users (admin only) |
184
- | `/api/auth/users` | POST | Create new user (admin only) |
185
-
186
- ## Project Structure
187
-
188
- ```
189
- admin/
190
- ├── src/
191
- │ ├── lib/
192
- │ │ ├── db/ # Database adapters
193
- │ │ │ ├── adapter.ts # DatabaseAdapter interface
194
- │ │ │ ├── index.ts # Factory & config
195
- │ │ │ ├── sqlite-adapter.ts
196
- │ │ │ ├── postgres-adapter.ts
197
- │ │ │ ├── mysql-adapter.ts
198
- │ │ │ ├── mongodb-adapter.ts
199
- │ │ │ └── mongodb-auth-adapter.ts
200
- │ │ ├── auth/ # Auth adapter
201
- │ │ │ └── sqlite-adapter.ts
202
- │ │ ├── dataStore.ts # Content data wrapper
203
- │ │ └── config.ts # Collection/global config
204
- │ ├── components/ # React UI components
205
- │ ├── pages/ # Astro pages + API routes
206
- │ │ └── api/ # REST API endpoints
207
- │ │ └── auth/ # Authentication endpoints
208
- │ └── collections/ # Auth collection config
209
- ├── test/ # Vitest tests
210
- ├── public/ # Static assets
211
- └── astro.config.mjs # Astro configuration
212
- ```
213
-
214
- ## Adapter Architecture
215
-
216
- ```
217
- ┌─────────────────────────────────────────────────────────────┐
218
- │ Application Code │
219
- └─────────────────────────┬───────────────────────────────────┘
220
-
221
-
222
- ┌─────────────────────────────────────────────────────────────┐
223
- │ dataStore.ts (Wrapper) │
224
- └─────────────────────────┬───────────────────────────────────┘
225
-
226
-
227
- ┌─────────────────────────────────────────────────────────────┐
228
- │ db/index.ts (Factory/Registry) │
229
- │ - Reads DB_TYPE from env │
230
- │ - Lazy-loads appropriate adapter │
231
- │ - Auto-selects matching auth adapter │
232
- └─────────────────────────┬───────────────────────────────────┘
233
-
234
-
235
- ┌─────────────────────────────────────────────────────────────┐
236
- │ adapter.ts (DatabaseAdapter Interface) │
237
- │ - find, findById, create, update, delete │
238
- │ - findGlobal, updateGlobal, seedGlobal │
239
- │ - seed, isSeeded, count │
240
- └─────────────────────────┬───────────────────────────────────┘
241
-
242
- ┌─────────────────────┼─────────────────────┐
243
- ▼ ▼ ▼
244
- ┌─────────┐ ┌─────────┐ ┌─────────┐
245
- │ SQLite │ │ PG │ │ MySQL │
246
- └─────────┘ └─────────┘ └─────────┘
247
- ┌─────────┐
248
- │ MongoDB │
249
- └─────────┘
250
- ```
251
-
252
- ## Security
253
-
254
- - **Password Hashing** — bcryptjs with 10 salt rounds
255
- - **JWT Tokens** — Signed tokens with configurable expiration
256
- - **Session Management** — Server-side session tracking via DB adapter
257
- - **Middleware Protection** — All non-auth routes require valid JWT
258
- - **Password Policy** — Minimum 8 characters
259
-
260
- ## Testing
261
-
262
- ```bash
263
- # Run all tests
264
- npm run test:run
265
-
266
- # Run tests with watch mode
267
- npm run test
268
- ```
269
-
270
- ## License
271
-
272
- MIT
1
+ # Kyro Admin MVP Extensibility
2
+
3
+ This repository contains a minimal, upgrade-safe extension surface for @kyro-cms/admin.
4
+
5
+ - Exposed modules: theme, hooks, plugins, blocks, fields, and the Astro integration (kyroAdmin).
6
+ - MVP samples are included for quick experimentation:
7
+ - MVP Hook samples: sampleHook, sampleHook2
8
+ - MVP Block samples: sampleBlock, sampleBlock2
9
+ - MVP Field samples: sampleField, sampleField2
10
+ - MVP Plugin sample: samplePlugin
11
+
12
+ How to try locally
13
+
14
+ - Build:
15
+ - Run: bun install
16
+ - Run: bun run build
17
+ - Dist artifacts will be emitted in admin/dist
18
+ - Test:
19
+ - Run: bun run test
20
+ - Tests cover MVP hooks; additional MVP tests can be added later
21
+
22
+ Usage notes
23
+
24
+ - kyroAdmin() is available from @kyro-cms/admin/integration and can be wired into Astro config
25
+ - MVP samples are designed to be initial templates for plugin authors; replace or extend with real logic
26
+
27
+ Next steps
28
+
29
+ - Decide on final API shape (per-feature exports vs central namespace)
30
+ - Add more MVP samples for blocks/fields/plugins and write accompanying tests
31
+ - Add documentation explaining how to author plugins and blocks
32
+ - MVP samples are included for quick experimentation:
33
+ - MVP Hook samples: sampleHook, sampleHook2
34
+ - MVP Block samples: sampleBlock, sampleBlock2
35
+ - MVP Field samples: sampleField, sampleField2
36
+ - MVP Plugin sample: samplePlugin
37
+
38
+ Export surface (MVP)
39
+
40
+ - The MVP exports are available per module:
41
+ - @kyro-cms/admin/hooks -> sampleHook, sampleHook2 (and lifecycle/data hooks)
42
+ - @kyro-cms/admin/blocks -> sampleBlock, sampleBlock2 (and registry)
43
+ - @kyro-cms/admin/fields -> sampleField, sampleField2 (and registry)
44
+ - @kyro-cms/admin/plugins -> samplePlugin, samplePlugin2 (and registry)
45
+ - The main integration (kyroAdmin) is available via @kyro-cms/admin/integration
46
+ - The theme module is available via @kyro-cms/admin/theme
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kyro-cms/admin",
3
- "version": "0.2.4",
3
+ "version": "0.3.0",
4
4
  "private": false,
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -14,6 +14,30 @@
14
14
  ".": {
15
15
  "import": "./src/index.ts",
16
16
  "default": "./src/index.ts"
17
+ },
18
+ "./theme": {
19
+ "import": "./src/theme/index.ts",
20
+ "default": "./src/theme/index.ts"
21
+ },
22
+ "./hooks": {
23
+ "import": "./src/hooks/index.ts",
24
+ "default": "./src/hooks/index.ts"
25
+ },
26
+ "./plugins": {
27
+ "import": "./src/plugins/index.ts",
28
+ "default": "./src/plugins/index.ts"
29
+ },
30
+ "./blocks": {
31
+ "import": "./src/blocks/index.ts",
32
+ "default": "./src/blocks/index.ts"
33
+ },
34
+ "./fields": {
35
+ "import": "./src/fields/index.ts",
36
+ "default": "./src/fields/index.ts"
37
+ },
38
+ "./integration": {
39
+ "import": "./src/integration.ts",
40
+ "default": "./src/integration.ts"
17
41
  }
18
42
  },
19
43
  "files": [
@@ -21,7 +45,7 @@
21
45
  ],
22
46
  "scripts": {
23
47
  "dev": "astro dev",
24
- "build": "astro build",
48
+ "build": "tsup src/index.ts --format esm,cjs --dts --clean",
25
49
  "preview": "astro preview",
26
50
  "check": "astro check",
27
51
  "test": "vitest",
@@ -47,9 +71,7 @@
47
71
  "@dnd-kit/sortable": "^10.0.0",
48
72
  "@dnd-kit/utilities": "^3.2.2",
49
73
  "@graphiql/react": "^0.37.3",
50
- "@kyro-cms/core": "^0.2.4",
51
- "@kyro-cms/utils": "^0.2.4",
52
- "@platejs/dnd": "^53.0.0",
74
+ "@kyro-cms/core": "^0.3.0",
53
75
  "@portabletext/editor": "^6.6.3",
54
76
  "@portabletext/react": "^6.0.3",
55
77
  "@portabletext/schema": "^2.1.1",
@@ -57,20 +79,19 @@
57
79
  "@portabletext/types": "^4.0.2",
58
80
  "@tailwindcss/vite": "^4.0.0",
59
81
  "@types/pg": "^8.20.0",
60
- "@udecode/plate-dnd": "^49.0.0",
61
82
  "@uiw/codemirror-theme-aura": "^4.25.9",
62
83
  "@uiw/codemirror-theme-dracula": "^4.25.9",
63
84
  "@uiw/codemirror-theme-github": "^4.25.9",
64
85
  "@uiw/react-codemirror": "^4.25.9",
65
86
  "astro": "^5.4.0",
66
87
  "better-sqlite3": "^11.10.0",
88
+ "bcryptjs": "^2.4.3",
67
89
  "drizzle-orm": "^0.45.2",
68
90
  "graphiql": "^5.2.2",
69
91
  "lucide-react": "^0.475.0",
70
92
  "mongodb": "^7.1.1",
71
93
  "mysql2": "^3.21.0",
72
94
  "pg": "^8.20.0",
73
- "platejs": "^53.0.0",
74
95
  "react": "^19.0.0",
75
96
  "react-dom": "^19.0.0",
76
97
  "react-image-crop": "^11.0.10",
@@ -82,15 +103,21 @@
82
103
  "zustand": "^5.0.3"
83
104
  },
84
105
  "devDependencies": {
106
+ "@astrojs/check": "^0.9.9",
85
107
  "@types/react": "^19.0.0",
86
108
  "@types/react-dom": "^19.0.0",
87
109
  "dotenv": "^17.4.2",
88
110
  "dotenv-cli": "^11.0.0",
89
111
  "drizzle-kit": "^0.31.10",
90
- "typescript": "^5.7.0",
91
- "vitest": "^4.1.4"
112
+ "typescript": "^6.0.3",
113
+ "vitest": "^4.1.4",
114
+ "tsup": "^6.0.0"
92
115
  },
93
116
  "peerDependencies": {
94
- "@kyro-cms/core": "^0.1.2"
117
+ "@kyro-cms/core": "^0.3.0"
118
+ },
119
+ "repository": {
120
+ "type": "git",
121
+ "url": "https://github.com/danielDozie/kyro-cms"
95
122
  }
96
123
  }
@@ -0,0 +1,27 @@
1
+ import React from "react";
2
+ import type { KyroBlock } from "../types.ts";
3
+ import { registerBlock } from "../registry.ts";
4
+
5
+ const SampleBlock2Renderer: KyroBlock["render"] = (props) => {
6
+ const { data } = props;
7
+ return (
8
+ <div style={{ border: "2px dashed #888", padding: 10, borderRadius: 8 }}>
9
+ <strong>Sample Block 2</strong>
10
+ <pre style={{ marginTop: 6 }}>{JSON.stringify(data ?? {}, null, 2)}</pre>
11
+ </div>
12
+ );
13
+ };
14
+
15
+ const block: KyroBlock = {
16
+ id: "sample-block-2",
17
+ label: "Sample Block 2",
18
+ category: "demo",
19
+ schema: [
20
+ { name: "subtitle", label: "Subtitle", type: "text", required: false },
21
+ ],
22
+ render: SampleBlock2Renderer,
23
+ };
24
+
25
+ registerBlock(block);
26
+ export default block;
27
+ export { block as sampleBlock2 };
@@ -0,0 +1,26 @@
1
+ import React from "react";
2
+ import type { KyroBlock } from "../types.ts";
3
+ import { registerBlock } from "../registry.ts";
4
+
5
+ const SampleBlockRenderer: KyroBlock["render"] = (props) => {
6
+ const { data } = props;
7
+ return (
8
+ <div style={{ border: "1px solid #ccc", padding: 8, borderRadius: 6 }}>
9
+ <strong>Sample Block</strong>
10
+ <pre style={{ marginTop: 6 }}>{JSON.stringify(data ?? {}, null, 2)}</pre>
11
+ </div>
12
+ );
13
+ };
14
+
15
+ const block: KyroBlock = {
16
+ id: "sample-block",
17
+ label: "Sample Block",
18
+ category: "demo",
19
+ schema: [{ name: "title", label: "Title", type: "text", required: true }],
20
+ render: SampleBlockRenderer,
21
+ };
22
+
23
+ registerBlock(block);
24
+
25
+ export default block;
26
+ export { block as sampleBlock };
@@ -0,0 +1,14 @@
1
+ export {
2
+ registerBlock,
3
+ unregisterBlock,
4
+ getBlock,
5
+ getBlocks,
6
+ getBlocksByCategory,
7
+ useBlockRenderer,
8
+ } from "./registry.ts";
9
+ export type { KyroBlock, BlockRenderProps } from "./types.ts";
10
+ export { default as sampleBlock } from "./examples/sample-block";
11
+ export { default as sampleBlock2 } from "./examples/sample-block-2.tsx";
12
+
13
+ // Re-export core block types for type-safe block registration
14
+ export type { Block as CoreBlock, RichTextBlock } from "@kyro-cms/core";
@@ -0,0 +1,38 @@
1
+ import type { KyroBlock } from "./types.ts";
2
+
3
+ const blocks: Map<string, KyroBlock> = new Map();
4
+
5
+ export function registerBlock(block: KyroBlock): void {
6
+ if (!block.id || typeof block.id !== "string") {
7
+ throw new Error("Block must have a valid id");
8
+ }
9
+ if (!block.label) {
10
+ throw new Error("Block must have a label");
11
+ }
12
+ blocks.set(block.id, block);
13
+ }
14
+
15
+ export function unregisterBlock(id: string): void {
16
+ blocks.delete(id);
17
+ }
18
+
19
+ export function getBlock(id: string): KyroBlock | undefined {
20
+ return blocks.get(id);
21
+ }
22
+
23
+ export function getBlocks(): KyroBlock[] {
24
+ return Array.from(blocks.values());
25
+ }
26
+
27
+ export function getBlocksByCategory(category: string): KyroBlock[] {
28
+ return Array.from(blocks.values()).filter((b) => b.category === category);
29
+ }
30
+
31
+ export function useBlockRenderer(id: string) {
32
+ const block = blocks.get(id);
33
+ if (!block) {
34
+ console.warn(`Block "${id}" not found in registry`);
35
+ return null;
36
+ }
37
+ return block.render;
38
+ }
@@ -0,0 +1,23 @@
1
+ import type { ReactNode } from "react";
2
+ import type { KyroTheme } from "../theme/tokens.ts";
3
+ import type { Block as CoreBlock, Field } from "@kyro-cms/core";
4
+
5
+ export interface BlockRenderProps {
6
+ data: Record<string, unknown>;
7
+ context: {
8
+ theme: KyroTheme;
9
+ locale: string;
10
+ isPreview: boolean;
11
+ };
12
+ }
13
+
14
+ export interface KyroBlock extends Omit<CoreBlock, "fields" | "slug"> {
15
+ id: string;
16
+ label: string;
17
+ category?: string;
18
+ icon?: ReactNode;
19
+ schema: Field[];
20
+ render: (props: BlockRenderProps) => ReactNode;
21
+ preview?: (props: BlockRenderProps) => ReactNode;
22
+ settings?: Record<string, unknown>;
23
+ }
@@ -1,5 +1,5 @@
1
1
  import { useState, useEffect } from "react";
2
- import { apiPost } from "@kyro-cms/utils/lib/api";
2
+ import { apiPost } from "../lib/api";
3
3
  import type { CollectionConfig, GlobalConfig } from "@kyro-cms/core/client";
4
4
  import { ListView } from "./ListView";
5
5
  import { DetailView } from "./DetailView";
@@ -1,5 +1,5 @@
1
1
  import React, { useState, useEffect } from "react";
2
- import { apiGet, apiPost, apiDelete } from "@kyro-cms/utils/lib/api";
2
+ import { apiGet, apiPost, apiDelete } from "../lib/api";
3
3
  import {
4
4
  Key,
5
5
  Plus,
@@ -1,5 +1,5 @@
1
1
  import React, { useState, useEffect, useCallback } from "react";
2
- import { apiGet } from "@kyro-cms/utils/lib/api";
2
+ import { apiGet } from "../lib/api";
3
3
  import { Modal } from "./ui/Modal";
4
4
 
5
5
  interface AuditLog {
@@ -17,7 +17,7 @@ import { slugifyText } from "../lib/slugify";
17
17
 
18
18
  import { BlocksField } from "./fields/BlocksField";
19
19
  import PortableTextField from "./fields/PortableTextField";
20
- import { ConfirmModal, UIModal } from "./Modal";
20
+ import { ConfirmModal, Modal as UIModal } from "./ui/Modal";
21
21
 
22
22
  interface AutoFormProps {
23
23
  config: CollectionConfig | GlobalConfig;
@@ -31,7 +31,7 @@ interface AutoFormProps {
31
31
  layout?: "split" | "single";
32
32
  onActionSuccess?: (message: string) => void;
33
33
  onActionError?: (message: string) => void;
34
- documentStatus?: "draft" | "published";
34
+ documentStatus?: "draft" | "published" | "scheduled" | "archived";
35
35
  justSaved?: boolean;
36
36
  }
37
37
 
@@ -1,5 +1,5 @@
1
1
  import React, { useState, useEffect } from "react";
2
- import { apiGet, apiPatch } from "@kyro-cms/utils/lib/api";
2
+ import { apiGet, apiPatch } from "../lib/api";
3
3
  import {
4
4
  Palette,
5
5
  Tag,
@@ -1,5 +1,5 @@
1
1
  import { useState } from "react";
2
- import { apiPost } from "@kyro-cms/utils/lib/api";
2
+ import { apiPost } from "../lib/api";
3
3
  import type { KyroConfig, CollectionConfig } from "@kyro-cms/core/client";
4
4
  import { AutoForm } from "./AutoForm";
5
5
  import { Spinner } from "./ui/Spinner";
@@ -1,5 +1,5 @@
1
1
  import { useState, useEffect, useCallback, useRef } from "react";
2
- import { apiGet, apiPatch, apiPost, apiDelete } from "@kyro-cms/utils/lib/api";
2
+ import { apiGet, apiPatch, apiPost, apiDelete } from "../lib/api";
3
3
  import type {
4
4
  KyroConfig,
5
5
  CollectionConfig,
@@ -1,5 +1,5 @@
1
1
  import React, { useState, useEffect } from "react";
2
- import { apiGet, apiPost, apiDelete } from "@kyro-cms/utils/lib/api";
2
+ import { apiGet, apiPost, apiDelete } from "../lib/api";
3
3
  import {
4
4
  Terminal,
5
5
  Key,
@@ -1,7 +1,7 @@
1
1
  import { useState, useEffect, useMemo, useCallback } from "react";
2
2
  import { Spinner } from "./ui/Spinner";
3
3
  import { ConfirmModal } from "./ui/Modal";
4
- import { apiGet, apiDelete, withCacheBust } from "@kyro-cms/utils/lib/api";
4
+ import { apiGet, apiDelete, withCacheBust } from "../lib/api";
5
5
 
6
6
  export interface FieldConfig {
7
7
  name: string;
@@ -1,5 +1,5 @@
1
1
  import { useState, useEffect } from "react";
2
- import { apiGet, apiDelete } from "@kyro-cms/utils/lib/api";
2
+ import { apiGet, apiDelete } from "../lib/api";
3
3
  import type { CollectionConfig, KyroConfig } from "@kyro-cms/core/client";
4
4
  import { Spinner } from "./ui/Spinner";
5
5
  import { ConfirmModal } from "./ui/Modal";
@@ -1,5 +1,5 @@
1
1
  import { useState, useEffect } from "react";
2
- import { apiGet, apiPost } from "@kyro-cms/utils/lib/api";
2
+ import { apiGet, apiPost } from "../lib/api";
3
3
  import { ThemeProvider, type ThemeMode } from "./ThemeProvider";
4
4
  import { Toast, ToastProvider } from "./ui/Toast";
5
5
 
@@ -35,7 +35,7 @@ import {
35
35
  apiPatch,
36
36
  withCacheBust,
37
37
  apiUpload,
38
- } from "@kyro-cms/utils/lib/api";
38
+ } from "../lib/api";
39
39
 
40
40
  interface MediaItem {
41
41
  id: string;