@kidecms/core 0.1.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 (93) hide show
  1. package/README.md +28 -0
  2. package/admin/components/AdminCard.astro +25 -0
  3. package/admin/components/AiGenerateButton.tsx +102 -0
  4. package/admin/components/AssetsGrid.tsx +711 -0
  5. package/admin/components/BlockEditor.tsx +996 -0
  6. package/admin/components/CheckboxField.tsx +31 -0
  7. package/admin/components/DocumentActions.tsx +317 -0
  8. package/admin/components/DocumentLock.tsx +54 -0
  9. package/admin/components/DocumentsDataTable.tsx +804 -0
  10. package/admin/components/FieldControl.astro +397 -0
  11. package/admin/components/FocalPointSelector.tsx +100 -0
  12. package/admin/components/ImageBrowseDialog.tsx +176 -0
  13. package/admin/components/ImagePicker.tsx +149 -0
  14. package/admin/components/InternalLinkPicker.tsx +80 -0
  15. package/admin/components/LiveHeading.tsx +17 -0
  16. package/admin/components/MobileSidebar.tsx +29 -0
  17. package/admin/components/RelationField.tsx +204 -0
  18. package/admin/components/RichTextEditor.tsx +685 -0
  19. package/admin/components/SelectField.tsx +65 -0
  20. package/admin/components/SidebarUserMenu.tsx +99 -0
  21. package/admin/components/SlugField.tsx +77 -0
  22. package/admin/components/TaxonomySelect.tsx +52 -0
  23. package/admin/components/Toast.astro +40 -0
  24. package/admin/components/TreeItemsEditor.tsx +790 -0
  25. package/admin/components/TreeSelect.tsx +166 -0
  26. package/admin/components/UnsavedGuard.tsx +181 -0
  27. package/admin/components/tree-utils.ts +86 -0
  28. package/admin/components/ui/alert-dialog.tsx +92 -0
  29. package/admin/components/ui/badge.tsx +83 -0
  30. package/admin/components/ui/button.tsx +53 -0
  31. package/admin/components/ui/card.tsx +70 -0
  32. package/admin/components/ui/checkbox.tsx +28 -0
  33. package/admin/components/ui/collapsible.tsx +26 -0
  34. package/admin/components/ui/command.tsx +88 -0
  35. package/admin/components/ui/dialog.tsx +92 -0
  36. package/admin/components/ui/dropdown-menu.tsx +259 -0
  37. package/admin/components/ui/input.tsx +20 -0
  38. package/admin/components/ui/label.tsx +20 -0
  39. package/admin/components/ui/popover.tsx +42 -0
  40. package/admin/components/ui/select.tsx +165 -0
  41. package/admin/components/ui/separator.tsx +21 -0
  42. package/admin/components/ui/sheet.tsx +104 -0
  43. package/admin/components/ui/skeleton.tsx +7 -0
  44. package/admin/components/ui/table.tsx +74 -0
  45. package/admin/components/ui/textarea.tsx +18 -0
  46. package/admin/components/ui/tooltip.tsx +52 -0
  47. package/admin/layouts/AdminLayout.astro +340 -0
  48. package/admin/lib/utils.ts +19 -0
  49. package/dist/admin.js +92 -0
  50. package/dist/ai.js +67 -0
  51. package/dist/api.js +827 -0
  52. package/dist/assets.js +163 -0
  53. package/dist/auth.js +132 -0
  54. package/dist/blocks.js +110 -0
  55. package/dist/content.js +29 -0
  56. package/dist/create-admin.js +23 -0
  57. package/dist/define.js +36 -0
  58. package/dist/generator.js +370 -0
  59. package/dist/image.js +69 -0
  60. package/dist/index.js +16 -0
  61. package/dist/integration.js +256 -0
  62. package/dist/locks.js +37 -0
  63. package/dist/richtext.js +1 -0
  64. package/dist/runtime.js +26 -0
  65. package/dist/schema.js +13 -0
  66. package/dist/seed.js +84 -0
  67. package/dist/values.js +102 -0
  68. package/middleware/auth.ts +100 -0
  69. package/package.json +102 -0
  70. package/routes/api/cms/[collection]/[...path].ts +366 -0
  71. package/routes/api/cms/ai/alt-text.ts +25 -0
  72. package/routes/api/cms/ai/seo.ts +25 -0
  73. package/routes/api/cms/ai/translate.ts +31 -0
  74. package/routes/api/cms/assets/[id].ts +82 -0
  75. package/routes/api/cms/assets/folders.ts +81 -0
  76. package/routes/api/cms/assets/index.ts +23 -0
  77. package/routes/api/cms/assets/upload.ts +112 -0
  78. package/routes/api/cms/auth/invite.ts +166 -0
  79. package/routes/api/cms/auth/login.ts +124 -0
  80. package/routes/api/cms/auth/logout.ts +33 -0
  81. package/routes/api/cms/auth/setup.ts +77 -0
  82. package/routes/api/cms/cron/publish.ts +33 -0
  83. package/routes/api/cms/img/[...path].ts +24 -0
  84. package/routes/api/cms/locks/[...path].ts +37 -0
  85. package/routes/api/cms/preview/render.ts +36 -0
  86. package/routes/api/cms/references/[collection]/[id].ts +60 -0
  87. package/routes/pages/admin/[...path].astro +1104 -0
  88. package/routes/pages/admin/assets/[id].astro +183 -0
  89. package/routes/pages/admin/assets/index.astro +58 -0
  90. package/routes/pages/admin/invite.astro +116 -0
  91. package/routes/pages/admin/login.astro +57 -0
  92. package/routes/pages/admin/setup.astro +91 -0
  93. package/virtual.d.ts +61 -0
package/README.md ADDED
@@ -0,0 +1,28 @@
1
+ # `@kidecms/core`
2
+
3
+ Kide's runtime and admin package.
4
+
5
+ ## Install shape
6
+
7
+ The goal is to keep onboarding simple:
8
+
9
+ - `@kidecms/core` brings its own CMS runtime, generator, and admin UI dependencies.
10
+ - The host app provides `react` and `react-dom`.
11
+ - Some features are optional:
12
+ - `@ai-sdk/openai` only when AI generation is enabled
13
+ - `sharp` only when local image transforms are enabled
14
+
15
+ ## Why some packages still exist in the app
16
+
17
+ Kide keeps project-specific code inside the app:
18
+
19
+ - database adapters
20
+ - storage adapters
21
+ - email adapters
22
+ - generated schema files
23
+ - framework route glue
24
+
25
+ Because those files live in the app, the app may still depend on packages like
26
+ `drizzle-orm`, `zod`, or `nanoid` when it imports them directly.
27
+
28
+ That is separate from `@kidecms/core`'s own package contract.
@@ -0,0 +1,25 @@
1
+ ---
2
+ import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "./ui/card";
3
+
4
+ const {
5
+ title,
6
+ description,
7
+ compact = false,
8
+ class: className = "",
9
+ } = Astro.props as {
10
+ title: string;
11
+ description?: string;
12
+ compact?: boolean;
13
+ class?: string;
14
+ };
15
+ ---
16
+
17
+ <Card className={className}>
18
+ <CardHeader className={compact ? "px-3 py-3" : "border-b"}>
19
+ <CardTitle className={compact ? "text-sm" : undefined}>{title}</CardTitle>
20
+ {description && <CardDescription>{description}</CardDescription>}
21
+ </CardHeader>
22
+ <CardContent className={compact ? "px-3 pb-3" : undefined}>
23
+ <slot />
24
+ </CardContent>
25
+ </Card>
@@ -0,0 +1,102 @@
1
+ import { useState } from "react";
2
+ import { Sparkles, Loader2 } from "lucide-react";
3
+ import { Button } from "./ui/button";
4
+
5
+ interface AiGenerateButtonProps {
6
+ endpoint: string;
7
+ payload: Record<string, unknown>;
8
+ targetField: string;
9
+ label?: string;
10
+ }
11
+
12
+ function setFieldValue(name: string, value: string) {
13
+ const field = document.querySelector<HTMLInputElement | HTMLTextAreaElement>(`[name="${name}"]`);
14
+ if (!field) return;
15
+
16
+ // Rich text fields use a custom event to update the Tiptap editor
17
+ if (field.type === "hidden") {
18
+ field.dispatchEvent(new CustomEvent("cms:set-value", { detail: value }));
19
+ return;
20
+ }
21
+
22
+ const nativeSetter = Object.getOwnPropertyDescriptor(
23
+ field instanceof HTMLTextAreaElement ? HTMLTextAreaElement.prototype : HTMLInputElement.prototype,
24
+ "value",
25
+ )?.set;
26
+
27
+ if (nativeSetter) {
28
+ nativeSetter.call(field, value);
29
+ } else {
30
+ field.value = value;
31
+ }
32
+
33
+ field.dispatchEvent(new Event("input", { bubbles: true }));
34
+ field.dispatchEvent(new Event("change", { bubbles: true }));
35
+ }
36
+
37
+ export default function AiGenerateButton({
38
+ endpoint,
39
+ payload,
40
+ targetField,
41
+ label = "Generate with AI",
42
+ }: AiGenerateButtonProps) {
43
+ const [loading, setLoading] = useState(false);
44
+ const [error, setError] = useState<string | null>(null);
45
+
46
+ const handleGenerate = async () => {
47
+ setLoading(true);
48
+ setError(null);
49
+ try {
50
+ const livePayload = { ...payload };
51
+ for (const key of Object.keys(livePayload)) {
52
+ const el = document.querySelector<HTMLInputElement | HTMLTextAreaElement>(`[name="${key}"]`);
53
+ if (el) livePayload[key] = el.value;
54
+ }
55
+
56
+ const response = await fetch(endpoint, {
57
+ method: "POST",
58
+ headers: { "Content-Type": "application/json" },
59
+ body: JSON.stringify(livePayload),
60
+ });
61
+
62
+ if (!response.ok) {
63
+ const err = await response.json().catch(() => ({ error: "Generation failed" }));
64
+ throw new Error(err.error || "Generation failed");
65
+ }
66
+
67
+ const reader = response.body?.getReader();
68
+ if (!reader) throw new Error("No response stream");
69
+
70
+ const decoder = new TextDecoder();
71
+ let accumulated = "";
72
+
73
+ while (true) {
74
+ const { done, value } = await reader.read();
75
+ if (done) break;
76
+ accumulated += decoder.decode(value, { stream: true });
77
+ setFieldValue(targetField, accumulated);
78
+ }
79
+ } catch (e) {
80
+ setError(e instanceof Error ? e.message : "Generation failed");
81
+ } finally {
82
+ setLoading(false);
83
+ }
84
+ };
85
+
86
+ return (
87
+ <div>
88
+ <Button
89
+ type="button"
90
+ variant="outline"
91
+ size="sm"
92
+ onClick={handleGenerate}
93
+ disabled={loading}
94
+ className="text-foreground/70"
95
+ >
96
+ {loading ? <Loader2 className="size-3 animate-spin" /> : <Sparkles className="size-4 stroke-1" />}
97
+ {label}
98
+ </Button>
99
+ {error && <p className="text-destructive mt-1 text-xs">{error}</p>}
100
+ </div>
101
+ );
102
+ }