@kyro-cms/admin 0.9.0 → 0.9.1
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 +11960 -11006
- package/dist/index.cjs.map +1 -1
- package/dist/index.css +67 -65
- package/dist/index.css.map +1 -1
- package/dist/index.d.cts +563 -0
- package/dist/index.d.ts +7 -7
- package/dist/index.js +12183 -11238
- package/dist/index.js.map +1 -1
- package/package.json +15 -11
- package/src/components/ActionBar.tsx +27 -14
- package/src/components/Admin.tsx +1 -1
- package/src/components/ApiKeysManager.tsx +5 -5
- package/src/components/AutoForm.tsx +585 -369
- package/src/components/BrandingHub.tsx +7 -4
- package/src/components/CreateView.tsx +2 -0
- package/src/components/DetailView.tsx +71 -56
- package/src/components/DeveloperCenter.tsx +8 -6
- package/src/components/FieldRenderer.tsx +94 -19
- package/src/components/ListView.tsx +33 -20
- package/src/components/MediaGallery.tsx +219 -194
- package/src/components/PluginsManager.tsx +197 -70
- package/src/components/RestPlayground.tsx +7 -7
- package/src/components/SessionsManager.tsx +1 -1
- package/src/components/SettingsPage.tsx +22 -0
- package/src/components/Sidebar.astro +13 -41
- package/src/components/UserManagement.tsx +153 -15
- package/src/components/UserMenu.tsx +30 -4
- package/src/components/VersionHistoryPanel.tsx +112 -119
- package/src/components/WebhookManager.tsx +6 -4
- package/src/components/blocks/ArrayBlock.tsx +6 -23
- package/src/components/blocks/BlockEditModal.tsx +82 -309
- package/src/components/blocks/CardBlock.tsx +35 -0
- package/src/components/blocks/ChildBlocksTree.tsx +57 -31
- package/src/components/blocks/GenericBlock.tsx +44 -0
- package/src/components/blocks/HeadingSubheadingBlock.tsx +32 -0
- package/src/components/blocks/HeroBlock.tsx +5 -14
- package/src/components/blocks/RichTextBlock.tsx +5 -5
- package/src/components/blocks/index.ts +5 -3
- package/src/components/fields/AccordionField.tsx +2 -2
- package/src/components/fields/ArrayField.tsx +1 -1
- package/src/components/fields/ArrayLayout.tsx +120 -29
- package/src/components/fields/BlocksField.tsx +430 -50
- package/src/components/fields/CardField.tsx +73 -0
- package/src/components/fields/CheckboxField.tsx +7 -3
- package/src/components/fields/DateField.tsx +4 -1
- package/src/components/fields/GroupLayout.tsx +2 -2
- package/src/components/fields/HeadingSubheadingField.tsx +43 -0
- package/src/components/fields/ListField.tsx +2 -2
- package/src/components/fields/NumberField.tsx +4 -1
- package/src/components/fields/RelationshipField.tsx +153 -87
- package/src/components/fields/RichTextField.tsx +781 -0
- package/src/components/fields/SecretField.tsx +102 -0
- package/src/components/fields/SelectField.tsx +19 -6
- package/src/components/fields/TabsLayout.tsx +19 -9
- package/src/components/fields/TextField.tsx +4 -1
- package/src/components/fields/UploadField.tsx +122 -56
- package/src/components/fields/extensions/blockComponents.tsx +103 -174
- package/src/components/fields/extensions/blocksStore.ts +8 -1
- package/src/components/fields/index.ts +4 -2
- package/src/components/ui/PageHeader.tsx +5 -5
- package/src/components/ui/SlidePanel.tsx +8 -3
- package/src/components/ui/icons.tsx +109 -109
- package/src/components/users/UserDetail.tsx +79 -16
- package/src/hooks/useAutoFormState.ts +125 -62
- package/src/integration.ts +148 -46
- package/src/kyro-cms.d.ts +7 -2
- package/src/layouts/AuthLayout.astro +14 -2
- package/src/lib/autoform-store.ts +85 -52
- package/src/lib/change-source.ts +9 -0
- package/src/lib/config.ts +104 -8
- package/src/lib/globals.ts +44 -9
- package/src/lib/normalize-upload-fields.ts +41 -0
- package/src/lib/paths.ts +2 -2
- package/src/lib/resolve-field-value.ts +110 -0
- package/src/lib/shim/use-sync-external-store-with-selector.js +30 -0
- package/src/lib/shim/use-sync-external-store.js +1 -0
- package/src/lib/stores/index.ts +1 -0
- package/src/lib/useResourceManager.ts +4 -4
- package/src/lib/vite-shim-plugin.ts +100 -0
- package/src/pages/[collection]/[id].astro +1 -1
- package/src/pages/preview/[collection]/[id].astro +4 -4
- package/src/pages/settings/[slug].astro +2 -2
- package/src/styles/main.css +60 -54
- package/README.md +0 -46
- package/dist/EditorClient-Q23UXR37.cjs +0 -468
- package/dist/EditorClient-Q23UXR37.cjs.map +0 -1
- package/dist/EditorClient-T5PASFNR.js +0 -466
- package/dist/EditorClient-T5PASFNR.js.map +0 -1
- package/dist/chunk-3BGDYKTD.cjs +0 -348
- package/dist/chunk-3BGDYKTD.cjs.map +0 -1
- package/dist/chunk-EEFXLQVT.js +0 -3
- package/dist/chunk-EEFXLQVT.js.map +0 -1
- package/src/components/blocks/ButtonBlock.tsx +0 -64
- package/src/components/blocks/ColumnsBlock.tsx +0 -55
- package/src/components/blocks/DividerBlock.tsx +0 -43
- package/src/components/blocks/LinkBlock.tsx +0 -65
- package/src/components/blocks/VStackBlock.tsx +0 -29
- package/src/components/fields/EditorClient.tsx +0 -535
- package/src/components/fields/PortableTextField.tsx +0 -155
- package/src/components/fields/PortableTextRenderer.tsx +0 -68
|
@@ -1,468 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
var chunk3BGDYKTD_cjs = require('./chunk-3BGDYKTD.cjs');
|
|
4
|
-
var react = require('react');
|
|
5
|
-
var editor = require('@portabletext/editor');
|
|
6
|
-
var schema = require('@portabletext/schema');
|
|
7
|
-
var plugins = require('@portabletext/editor/plugins');
|
|
8
|
-
var toolbar = require('@portabletext/toolbar');
|
|
9
|
-
var jsxRuntime = require('react/jsx-runtime');
|
|
10
|
-
|
|
11
|
-
function sanitizeInitialValue(value) {
|
|
12
|
-
if (!value || !Array.isArray(value))
|
|
13
|
-
return [];
|
|
14
|
-
return value.filter((block) => {
|
|
15
|
-
if (!block || typeof block !== "object")
|
|
16
|
-
return false;
|
|
17
|
-
if (!("_type" in block))
|
|
18
|
-
return false;
|
|
19
|
-
if (block._type === "block" && Array.isArray(block.children)) {
|
|
20
|
-
block.children = block.children.map((child) => ({
|
|
21
|
-
...child,
|
|
22
|
-
_type: child._type || "span",
|
|
23
|
-
text: typeof child.text === "string" ? child.text : ""
|
|
24
|
-
}));
|
|
25
|
-
}
|
|
26
|
-
return true;
|
|
27
|
-
});
|
|
28
|
-
}
|
|
29
|
-
var schemaDefinition = schema.defineSchema({
|
|
30
|
-
decorators: [
|
|
31
|
-
{ name: "strong", title: "Bold" },
|
|
32
|
-
{ name: "em", title: "Italic" },
|
|
33
|
-
{ name: "underline", title: "Underline" },
|
|
34
|
-
{ name: "strikeThrough", title: "Strikethrough" },
|
|
35
|
-
{ name: "code", title: "Code" }
|
|
36
|
-
],
|
|
37
|
-
styles: [
|
|
38
|
-
{ name: "normal", title: "Normal" },
|
|
39
|
-
{ name: "h1", title: "H1" },
|
|
40
|
-
{ name: "h2", title: "H2" },
|
|
41
|
-
{ name: "h3", title: "H3" },
|
|
42
|
-
{ name: "blockquote", title: "Quote" }
|
|
43
|
-
],
|
|
44
|
-
lists: [
|
|
45
|
-
{ name: "bullet", title: "Bullet" },
|
|
46
|
-
{ name: "number", title: "Number" }
|
|
47
|
-
],
|
|
48
|
-
annotations: [
|
|
49
|
-
{
|
|
50
|
-
name: "link",
|
|
51
|
-
title: "Link",
|
|
52
|
-
fields: [{ name: "href", type: "string", title: "URL" }]
|
|
53
|
-
}
|
|
54
|
-
],
|
|
55
|
-
inlineObjects: [],
|
|
56
|
-
blockObjects: []
|
|
57
|
-
});
|
|
58
|
-
var renderStyle = (props) => {
|
|
59
|
-
if (props.schemaType.value === "h1") {
|
|
60
|
-
return /* @__PURE__ */ jsxRuntime.jsx("h1", { className: "text-2xl font-bold mb-2", children: props.children });
|
|
61
|
-
}
|
|
62
|
-
if (props.schemaType.value === "h2") {
|
|
63
|
-
return /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "text-xl font-bold mb-2", children: props.children });
|
|
64
|
-
}
|
|
65
|
-
if (props.schemaType.value === "h3") {
|
|
66
|
-
return /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-lg font-semibold mb-1", children: props.children });
|
|
67
|
-
}
|
|
68
|
-
if (props.schemaType.value === "blockquote") {
|
|
69
|
-
return /* @__PURE__ */ jsxRuntime.jsx("blockquote", { className: "border-l-2 border-[var(--kyro-primary)] pl-4 italic text-[var(--kyro-text-muted)] my-2", children: props.children });
|
|
70
|
-
}
|
|
71
|
-
return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: props.children });
|
|
72
|
-
};
|
|
73
|
-
var renderDecorator = (props) => {
|
|
74
|
-
if (props.value === "strong") {
|
|
75
|
-
return /* @__PURE__ */ jsxRuntime.jsx("strong", { children: props.children });
|
|
76
|
-
}
|
|
77
|
-
if (props.value === "em") {
|
|
78
|
-
return /* @__PURE__ */ jsxRuntime.jsx("em", { children: props.children });
|
|
79
|
-
}
|
|
80
|
-
if (props.value === "underline") {
|
|
81
|
-
return /* @__PURE__ */ jsxRuntime.jsx("u", { children: props.children });
|
|
82
|
-
}
|
|
83
|
-
if (props.value === "strikeThrough") {
|
|
84
|
-
return /* @__PURE__ */ jsxRuntime.jsx("s", { children: props.children });
|
|
85
|
-
}
|
|
86
|
-
if (props.value === "code") {
|
|
87
|
-
return /* @__PURE__ */ jsxRuntime.jsx("code", { className: "px-1 py-0.5 rounded bg-[var(--kyro-surface-accent)] text-[var(--kyro-primary)] text-sm font-mono", children: props.children });
|
|
88
|
-
}
|
|
89
|
-
return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: props.children });
|
|
90
|
-
};
|
|
91
|
-
var renderBlock = (props) => {
|
|
92
|
-
return /* @__PURE__ */ jsxRuntime.jsx("div", { children: props.children });
|
|
93
|
-
};
|
|
94
|
-
var renderListItem = (props) => {
|
|
95
|
-
if (props.schemaType.value === "bullet") {
|
|
96
|
-
return /* @__PURE__ */ jsxRuntime.jsx("li", { className: "list-disc ml-4", children: props.children });
|
|
97
|
-
}
|
|
98
|
-
if (props.schemaType.value === "number") {
|
|
99
|
-
return /* @__PURE__ */ jsxRuntime.jsx("li", { className: "list-decimal ml-4", children: props.children });
|
|
100
|
-
}
|
|
101
|
-
return /* @__PURE__ */ jsxRuntime.jsx("li", { children: props.children });
|
|
102
|
-
};
|
|
103
|
-
var renderAnnotation = (props) => {
|
|
104
|
-
if (props.schemaType.name === "link") {
|
|
105
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
106
|
-
"a",
|
|
107
|
-
{
|
|
108
|
-
href: props.value.href,
|
|
109
|
-
className: "text-[var(--kyro-primary)] underline hover:opacity-80",
|
|
110
|
-
target: "_blank",
|
|
111
|
-
rel: "noopener noreferrer",
|
|
112
|
-
children: props.children
|
|
113
|
-
}
|
|
114
|
-
);
|
|
115
|
-
}
|
|
116
|
-
return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: props.children });
|
|
117
|
-
};
|
|
118
|
-
function FocusRestoringButton({
|
|
119
|
-
onClick,
|
|
120
|
-
children,
|
|
121
|
-
...props
|
|
122
|
-
}) {
|
|
123
|
-
const editor$1 = editor.useEditor();
|
|
124
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
125
|
-
"button",
|
|
126
|
-
{
|
|
127
|
-
type: "button",
|
|
128
|
-
onClick: (e) => {
|
|
129
|
-
onClick?.(e);
|
|
130
|
-
editor$1.send({ type: "focus" });
|
|
131
|
-
},
|
|
132
|
-
...props,
|
|
133
|
-
children
|
|
134
|
-
}
|
|
135
|
-
);
|
|
136
|
-
}
|
|
137
|
-
var decoratorIcons = {
|
|
138
|
-
strong: chunk3BGDYKTD_cjs.LuBold,
|
|
139
|
-
em: chunk3BGDYKTD_cjs.LuItalic,
|
|
140
|
-
underline: chunk3BGDYKTD_cjs.LuUnderline,
|
|
141
|
-
strikeThrough: chunk3BGDYKTD_cjs.LuStrikethrough,
|
|
142
|
-
code: chunk3BGDYKTD_cjs.LuCode
|
|
143
|
-
};
|
|
144
|
-
var DecoratorButton = ({
|
|
145
|
-
name,
|
|
146
|
-
title
|
|
147
|
-
}) => {
|
|
148
|
-
const schema = toolbar.useToolbarSchema({});
|
|
149
|
-
const decoratorSchema = schema.decorators?.find((d) => d.name === name);
|
|
150
|
-
if (!decoratorSchema)
|
|
151
|
-
return null;
|
|
152
|
-
const { snapshot, send } = toolbar.useDecoratorButton({
|
|
153
|
-
schemaType: decoratorSchema
|
|
154
|
-
});
|
|
155
|
-
const Icon = decoratorIcons[name];
|
|
156
|
-
const isActive = snapshot.matches({ enabled: "active" }) || snapshot.matches({ disabled: "active" });
|
|
157
|
-
const isEnabled = snapshot.matches("enabled");
|
|
158
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
159
|
-
FocusRestoringButton,
|
|
160
|
-
{
|
|
161
|
-
disabled: !isEnabled,
|
|
162
|
-
"data-state": isActive ? "on" : "off",
|
|
163
|
-
onClick: () => send({ type: "toggle" }),
|
|
164
|
-
title,
|
|
165
|
-
className: "p-1.5 rounded transition-colors disabled:opacity-30 hover:bg-[var(--kyro-surface-accent)] data-[state=on]:bg-[var(--kyro-primary)] data-[state=on]:text-[var(--kyro-sidebar-text-active)]",
|
|
166
|
-
children: Icon && /* @__PURE__ */ jsxRuntime.jsx(Icon, { className: "w-4 h-4" })
|
|
167
|
-
}
|
|
168
|
-
);
|
|
169
|
-
};
|
|
170
|
-
var ListButton = ({
|
|
171
|
-
name,
|
|
172
|
-
title
|
|
173
|
-
}) => {
|
|
174
|
-
const schema = toolbar.useToolbarSchema({});
|
|
175
|
-
const listSchema = schema.lists?.find((l) => l.name === name);
|
|
176
|
-
if (!listSchema)
|
|
177
|
-
return null;
|
|
178
|
-
const { snapshot, send } = toolbar.useListButton({ schemaType: listSchema });
|
|
179
|
-
const Icon = name === "bullet" ? chunk3BGDYKTD_cjs.LuList : chunk3BGDYKTD_cjs.LuListOrdered;
|
|
180
|
-
const isActive = snapshot.matches({ enabled: "active" }) || snapshot.matches({ disabled: "active" });
|
|
181
|
-
const isEnabled = snapshot.matches("enabled");
|
|
182
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
183
|
-
FocusRestoringButton,
|
|
184
|
-
{
|
|
185
|
-
disabled: !isEnabled,
|
|
186
|
-
"data-state": isActive ? "on" : "off",
|
|
187
|
-
onClick: () => send({ type: "toggle" }),
|
|
188
|
-
title,
|
|
189
|
-
className: "p-1.5 rounded transition-colors disabled:opacity-30 hover:bg-[var(--kyro-surface-accent)] data-[state=on]:bg-[var(--kyro-primary)] data-[state=on]:text-[var(--kyro-sidebar-text-active)]",
|
|
190
|
-
children: Icon && /* @__PURE__ */ jsxRuntime.jsx(Icon, { className: "w-4 h-4" })
|
|
191
|
-
}
|
|
192
|
-
);
|
|
193
|
-
};
|
|
194
|
-
var AnnotationButton = ({
|
|
195
|
-
name,
|
|
196
|
-
title
|
|
197
|
-
}) => {
|
|
198
|
-
const schema = toolbar.useToolbarSchema({});
|
|
199
|
-
const annotationSchema = schema.annotations?.find((a) => a.name === name);
|
|
200
|
-
if (!annotationSchema)
|
|
201
|
-
return null;
|
|
202
|
-
const { snapshot, send } = toolbar.useAnnotationButton({
|
|
203
|
-
schemaType: annotationSchema
|
|
204
|
-
});
|
|
205
|
-
const isActive = snapshot.matches({ enabled: "active" }) || snapshot.matches({ disabled: "active" });
|
|
206
|
-
const isEnabled = snapshot.matches("enabled");
|
|
207
|
-
const isShowingDialog = snapshot.matches({
|
|
208
|
-
enabled: { inactive: "showing dialog" }
|
|
209
|
-
});
|
|
210
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
211
|
-
FocusRestoringButton,
|
|
212
|
-
{
|
|
213
|
-
disabled: !isEnabled,
|
|
214
|
-
"data-state": isActive ? "on" : "off",
|
|
215
|
-
onClick: () => send({
|
|
216
|
-
type: isShowingDialog ? "close dialog" : "open dialog"
|
|
217
|
-
}),
|
|
218
|
-
title,
|
|
219
|
-
className: "p-1.5 rounded transition-colors disabled:opacity-30 hover:bg-[var(--kyro-surface-accent)] data-[state=on]:bg-[var(--kyro-primary)] data-[state=on]:text-[var(--kyro-sidebar-text-active)]",
|
|
220
|
-
children: name === "link" && /* @__PURE__ */ jsxRuntime.jsx(chunk3BGDYKTD_cjs.LuLink, { className: "w-4 h-4" })
|
|
221
|
-
}
|
|
222
|
-
);
|
|
223
|
-
};
|
|
224
|
-
var LinkDialog = () => {
|
|
225
|
-
const schema = toolbar.useToolbarSchema({});
|
|
226
|
-
const popover = toolbar.useAnnotationPopover({
|
|
227
|
-
schemaTypes: schema.annotations || []
|
|
228
|
-
});
|
|
229
|
-
const dialogRef = react.useRef(null);
|
|
230
|
-
const inputRef = react.useRef(null);
|
|
231
|
-
react.useEffect(() => {
|
|
232
|
-
if (popover.snapshot.matches({ enabled: "active" }) && inputRef.current) {
|
|
233
|
-
inputRef.current.focus();
|
|
234
|
-
}
|
|
235
|
-
}, [popover.snapshot]);
|
|
236
|
-
if (!popover.snapshot.matches({ enabled: "active" }))
|
|
237
|
-
return null;
|
|
238
|
-
const activeAnnotations = popover.snapshot.context.annotations || [];
|
|
239
|
-
const activeLink = activeAnnotations.find(
|
|
240
|
-
(a) => a.schemaType.name === "link"
|
|
241
|
-
);
|
|
242
|
-
const currentHref = activeLink?.value?.href;
|
|
243
|
-
const handleSubmit = (e) => {
|
|
244
|
-
e.preventDefault();
|
|
245
|
-
const formData = new FormData(e.target);
|
|
246
|
-
const href = formData.get("href");
|
|
247
|
-
if (activeLink) {
|
|
248
|
-
if (href.trim()) {
|
|
249
|
-
popover.send({
|
|
250
|
-
type: "edit",
|
|
251
|
-
at: activeLink.at,
|
|
252
|
-
props: { href: href.trim() }
|
|
253
|
-
});
|
|
254
|
-
} else {
|
|
255
|
-
popover.send({
|
|
256
|
-
type: "remove",
|
|
257
|
-
schemaType: activeLink.schemaType
|
|
258
|
-
});
|
|
259
|
-
}
|
|
260
|
-
} else {
|
|
261
|
-
if (href.trim()) {
|
|
262
|
-
popover.send({
|
|
263
|
-
type: "edit",
|
|
264
|
-
at: [],
|
|
265
|
-
props: { href: href.trim() }
|
|
266
|
-
});
|
|
267
|
-
}
|
|
268
|
-
}
|
|
269
|
-
popover.send({ type: "close" });
|
|
270
|
-
};
|
|
271
|
-
const handleRemove = () => {
|
|
272
|
-
if (activeLink) {
|
|
273
|
-
popover.send({
|
|
274
|
-
type: "remove",
|
|
275
|
-
schemaType: activeLink.schemaType
|
|
276
|
-
});
|
|
277
|
-
}
|
|
278
|
-
popover.send({ type: "close" });
|
|
279
|
-
};
|
|
280
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
281
|
-
"div",
|
|
282
|
-
{
|
|
283
|
-
ref: dialogRef,
|
|
284
|
-
className: "absolute top-full left-0 z-50 mt-1 w-72 p-3 rounded-lg border border-[var(--kyro-border)] bg-[var(--kyro-bg-primary)] shadow-lg",
|
|
285
|
-
children: [
|
|
286
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between mb-2", children: [
|
|
287
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-medium text-[var(--kyro-text-primary)]", children: "Link" }),
|
|
288
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
289
|
-
"button",
|
|
290
|
-
{
|
|
291
|
-
type: "button",
|
|
292
|
-
onClick: () => popover.send({ type: "close" }),
|
|
293
|
-
className: "p-1 rounded hover:bg-[var(--kyro-surface-accent)]",
|
|
294
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(chunk3BGDYKTD_cjs.LuX, { className: "w-3.5 h-3.5 text-[var(--kyro-text-muted)]" })
|
|
295
|
-
}
|
|
296
|
-
)
|
|
297
|
-
] }),
|
|
298
|
-
/* @__PURE__ */ jsxRuntime.jsxs("form", { onSubmit: handleSubmit, className: "space-y-2", children: [
|
|
299
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-1.5", children: [
|
|
300
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
301
|
-
"input",
|
|
302
|
-
{
|
|
303
|
-
ref: inputRef,
|
|
304
|
-
name: "href",
|
|
305
|
-
type: "url",
|
|
306
|
-
defaultValue: currentHref || "https://",
|
|
307
|
-
placeholder: "Enter URL...",
|
|
308
|
-
className: "flex-1 px-2.5 py-1.5 text-sm rounded border border-[var(--kyro-border)] bg-transparent text-[var(--kyro-text-primary)] placeholder:text-[var(--kyro-text-muted)] focus:outline-none focus:ring-1 focus:ring-[var(--kyro-primary)]"
|
|
309
|
-
}
|
|
310
|
-
),
|
|
311
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
312
|
-
"button",
|
|
313
|
-
{
|
|
314
|
-
type: "submit",
|
|
315
|
-
className: "px-2.5 py-1.5 text-sm rounded bg-[var(--kyro-primary)] text-[var(--kyro-sidebar-text-active)] hover:opacity-90",
|
|
316
|
-
children: activeLink ? "Update" : "Add"
|
|
317
|
-
}
|
|
318
|
-
)
|
|
319
|
-
] }),
|
|
320
|
-
activeLink && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
321
|
-
"button",
|
|
322
|
-
{
|
|
323
|
-
type: "button",
|
|
324
|
-
onClick: handleRemove,
|
|
325
|
-
className: "w-full text-xs text-[var(--kyro-error)] hover:opacity-80 flex items-center justify-center gap-1 py-1",
|
|
326
|
-
children: [
|
|
327
|
-
/* @__PURE__ */ jsxRuntime.jsx(chunk3BGDYKTD_cjs.LuExternalLink, { className: "w-3 h-3" }),
|
|
328
|
-
"Remove link"
|
|
329
|
-
]
|
|
330
|
-
}
|
|
331
|
-
)
|
|
332
|
-
] })
|
|
333
|
-
]
|
|
334
|
-
}
|
|
335
|
-
);
|
|
336
|
-
};
|
|
337
|
-
var StyleSelector = () => {
|
|
338
|
-
const schema = toolbar.useToolbarSchema({});
|
|
339
|
-
const editor$1 = editor.useEditor();
|
|
340
|
-
const { snapshot, send } = toolbar.useStyleSelector({
|
|
341
|
-
schemaTypes: schema.styles || []
|
|
342
|
-
});
|
|
343
|
-
if (!snapshot.matches("enabled"))
|
|
344
|
-
return null;
|
|
345
|
-
const activeStyle = snapshot.context.activeStyle || "normal";
|
|
346
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", children: [
|
|
347
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
348
|
-
"select",
|
|
349
|
-
{
|
|
350
|
-
value: activeStyle,
|
|
351
|
-
onChange: (e) => {
|
|
352
|
-
send({ type: "toggle", style: e.target.value });
|
|
353
|
-
editor$1.send({ type: "focus" });
|
|
354
|
-
},
|
|
355
|
-
className: "appearance-none bg-transparent text-sm pr-6 pl-2 py-1 rounded hover:bg-[var(--kyro-surface-accent)] cursor-pointer focus:outline-none focus:ring-1 focus:ring-[var(--kyro-primary)]",
|
|
356
|
-
children: schema.styles?.map((s) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: s.name, children: s.title }, s.name))
|
|
357
|
-
}
|
|
358
|
-
),
|
|
359
|
-
/* @__PURE__ */ jsxRuntime.jsx(chunk3BGDYKTD_cjs.LuChevronDown, { className: "w-3 h-3 absolute right-1.5 top-1/2 -translate-y-1/2 pointer-events-none text-[var(--kyro-text-muted)]" })
|
|
360
|
-
] });
|
|
361
|
-
};
|
|
362
|
-
var Toolbar = () => {
|
|
363
|
-
const { snapshot: historySnapshot, send: historySend } = toolbar.useHistoryButtons();
|
|
364
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative flex items-center gap-0.5 p-1.5 border-b border-[var(--kyro-border)]", children: [
|
|
365
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
366
|
-
FocusRestoringButton,
|
|
367
|
-
{
|
|
368
|
-
disabled: !historySnapshot.matches("enabled"),
|
|
369
|
-
onClick: () => historySend({ type: "history.undo" }),
|
|
370
|
-
title: "Undo",
|
|
371
|
-
className: "p-1.5 rounded transition-colors hover:bg-[var(--kyro-surface-accent)] disabled:opacity-30",
|
|
372
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(chunk3BGDYKTD_cjs.LuUndo, { className: "w-4 h-4 text-[var(--kyro-text-secondary)]" })
|
|
373
|
-
}
|
|
374
|
-
),
|
|
375
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
376
|
-
FocusRestoringButton,
|
|
377
|
-
{
|
|
378
|
-
disabled: !historySnapshot.matches("enabled"),
|
|
379
|
-
onClick: () => historySend({ type: "history.redo" }),
|
|
380
|
-
title: "Redo",
|
|
381
|
-
className: "p-1.5 rounded transition-colors hover:bg-[var(--kyro-surface-accent)] disabled:opacity-30",
|
|
382
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(chunk3BGDYKTD_cjs.LuRedo, { className: "w-4 h-4 text-[var(--kyro-text-secondary)]" })
|
|
383
|
-
}
|
|
384
|
-
),
|
|
385
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-px h-5 bg-[var(--kyro-border)] mx-1" }),
|
|
386
|
-
/* @__PURE__ */ jsxRuntime.jsx(StyleSelector, {}),
|
|
387
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-px h-5 bg-[var(--kyro-border)] mx-1" }),
|
|
388
|
-
/* @__PURE__ */ jsxRuntime.jsx(DecoratorButton, { name: "strong", title: "Bold" }),
|
|
389
|
-
/* @__PURE__ */ jsxRuntime.jsx(DecoratorButton, { name: "em", title: "Italic" }),
|
|
390
|
-
/* @__PURE__ */ jsxRuntime.jsx(DecoratorButton, { name: "underline", title: "Underline" }),
|
|
391
|
-
/* @__PURE__ */ jsxRuntime.jsx(DecoratorButton, { name: "strikeThrough", title: "Strikethrough" }),
|
|
392
|
-
/* @__PURE__ */ jsxRuntime.jsx(DecoratorButton, { name: "code", title: "Code" }),
|
|
393
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-px h-5 bg-[var(--kyro-border)] mx-1" }),
|
|
394
|
-
/* @__PURE__ */ jsxRuntime.jsx(AnnotationButton, { name: "link", title: "Link" }),
|
|
395
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-px h-5 bg-[var(--kyro-border)] mx-1" }),
|
|
396
|
-
/* @__PURE__ */ jsxRuntime.jsx(ListButton, { name: "bullet", title: "Bullet List" }),
|
|
397
|
-
/* @__PURE__ */ jsxRuntime.jsx(ListButton, { name: "number", title: "Numbered List" }),
|
|
398
|
-
/* @__PURE__ */ jsxRuntime.jsx(LinkDialog, {})
|
|
399
|
-
] });
|
|
400
|
-
};
|
|
401
|
-
var EditorInner = ({ onChange, disabled }) => {
|
|
402
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
403
|
-
/* @__PURE__ */ jsxRuntime.jsx(Toolbar, {}),
|
|
404
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
405
|
-
editor.PortableTextEditable,
|
|
406
|
-
{
|
|
407
|
-
className: "min-h-[200px] p-4 focus:outline-none text-[var(--kyro-text-primary)]",
|
|
408
|
-
placeholder: "Start typing...",
|
|
409
|
-
readOnly: disabled,
|
|
410
|
-
renderStyle,
|
|
411
|
-
renderDecorator,
|
|
412
|
-
renderBlock,
|
|
413
|
-
renderListItem,
|
|
414
|
-
renderAnnotation
|
|
415
|
-
}
|
|
416
|
-
)
|
|
417
|
-
] });
|
|
418
|
-
};
|
|
419
|
-
var EditorClient = ({
|
|
420
|
-
initialValue,
|
|
421
|
-
onChange,
|
|
422
|
-
disabled
|
|
423
|
-
}) => {
|
|
424
|
-
const [value, setValue] = react.useState(() => sanitizeInitialValue(initialValue));
|
|
425
|
-
const prevInitialValueRef = react.useRef(initialValue);
|
|
426
|
-
react.useEffect(() => {
|
|
427
|
-
const sanitized = sanitizeInitialValue(initialValue);
|
|
428
|
-
const prevSanitized = sanitizeInitialValue(prevInitialValueRef.current);
|
|
429
|
-
if (JSON.stringify(sanitized) !== JSON.stringify(prevSanitized)) {
|
|
430
|
-
setValue(sanitized);
|
|
431
|
-
prevInitialValueRef.current = initialValue;
|
|
432
|
-
}
|
|
433
|
-
}, [initialValue]);
|
|
434
|
-
const handleChange = react.useCallback(
|
|
435
|
-
(newValue) => {
|
|
436
|
-
setValue(newValue);
|
|
437
|
-
onChange(newValue);
|
|
438
|
-
},
|
|
439
|
-
[onChange]
|
|
440
|
-
);
|
|
441
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
442
|
-
editor.EditorProvider,
|
|
443
|
-
{
|
|
444
|
-
initialConfig: {
|
|
445
|
-
schemaDefinition,
|
|
446
|
-
initialValue: value
|
|
447
|
-
},
|
|
448
|
-
children: [
|
|
449
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
450
|
-
plugins.EventListenerPlugin,
|
|
451
|
-
{
|
|
452
|
-
on: (event) => {
|
|
453
|
-
if (event.type === "mutation" && event.value) {
|
|
454
|
-
handleChange(event.value);
|
|
455
|
-
}
|
|
456
|
-
}
|
|
457
|
-
}
|
|
458
|
-
),
|
|
459
|
-
/* @__PURE__ */ jsxRuntime.jsx(EditorInner, { onChange: handleChange, disabled })
|
|
460
|
-
]
|
|
461
|
-
},
|
|
462
|
-
JSON.stringify(value)
|
|
463
|
-
);
|
|
464
|
-
};
|
|
465
|
-
|
|
466
|
-
exports.EditorClient = EditorClient;
|
|
467
|
-
//# sourceMappingURL=out.js.map
|
|
468
|
-
//# sourceMappingURL=EditorClient-Q23UXR37.cjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/fields/EditorClient.tsx"],"names":[],"mappings":"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","sourcesContent":["import React, {\n useState,\n useCallback,\n useRef,\n useEffect,\n useMemo,\n} from \"react\";\nimport {\n EditorProvider,\n PortableTextEditable,\n useEditor,\n type RenderStyleFunction,\n type RenderDecoratorFunction,\n type RenderBlockFunction,\n type RenderListItemFunction,\n type RenderAnnotationFunction,\n} from \"@portabletext/editor\";\nimport { defineSchema } from \"@portabletext/schema\";\nimport { EventListenerPlugin } from \"@portabletext/editor/plugins\";\nimport {\n useToolbarSchema,\n useDecoratorButton,\n useListButton,\n useStyleSelector,\n useHistoryButtons,\n useAnnotationButton,\n useAnnotationPopover,\n} from \"@portabletext/toolbar\";\nimport {\n Bold,\n Italic,\n Underline,\n Strikethrough,\n Code,\n Link,\n List,\n ListOrdered,\n Undo,\n Redo,\n ChevronDown,\n X,\n ExternalLink,\n} from \"../ui/icons\";\n\ninterface EditorClientProps {\n initialValue: Record<string, unknown>[];\n onChange: (blocks: Record<string, unknown>[]) => void;\n disabled?: boolean;\n}\n\nfunction sanitizeInitialValue(value: unknown): Record<string, unknown>[] {\n if (!value || !Array.isArray(value)) return [];\n return (value as Record<string, unknown>[]).filter((block) => {\n if (!block || typeof block !== \"object\") return false;\n if (!(\"_type\" in block)) return false;\n if ((block as { _type?: string })._type === \"block\" && Array.isArray((block as { children?: unknown[] }).children)) {\n (block as { children: Record<string, unknown>[] }).children = (block.children as Record<string, unknown>[]).map((child) => ({\n ...child,\n _type: (child as { _type?: string })._type || \"span\",\n text: typeof (child as { text?: unknown }).text === \"string\" ? child.text : \"\",\n }));\n }\n return true;\n });\n}\n\nconst schemaDefinition = defineSchema({\n decorators: [\n { name: \"strong\", title: \"Bold\" },\n { name: \"em\", title: \"Italic\" },\n { name: \"underline\", title: \"Underline\" },\n { name: \"strikeThrough\", title: \"Strikethrough\" },\n { name: \"code\", title: \"Code\" },\n ],\n styles: [\n { name: \"normal\", title: \"Normal\" },\n { name: \"h1\", title: \"H1\" },\n { name: \"h2\", title: \"H2\" },\n { name: \"h3\", title: \"H3\" },\n { name: \"blockquote\", title: \"Quote\" },\n ],\n lists: [\n { name: \"bullet\", title: \"Bullet\" },\n { name: \"number\", title: \"Number\" },\n ],\n annotations: [\n {\n name: \"link\",\n title: \"Link\",\n fields: [{ name: \"href\", type: \"string\", title: \"URL\" }],\n },\n ],\n inlineObjects: [],\n blockObjects: [],\n});\n\nconst renderStyle: RenderStyleFunction = (props) => {\n if (props.schemaType.value === \"h1\") {\n return <h1 className=\"text-2xl font-bold mb-2\">{props.children}</h1>;\n }\n if (props.schemaType.value === \"h2\") {\n return <h2 className=\"text-xl font-bold mb-2\">{props.children}</h2>;\n }\n if (props.schemaType.value === \"h3\") {\n return <h3 className=\"text-lg font-semibold mb-1\">{props.children}</h3>;\n }\n if (props.schemaType.value === \"blockquote\") {\n return (\n <blockquote className=\"border-l-2 border-[var(--kyro-primary)] pl-4 italic text-[var(--kyro-text-muted)] my-2\">\n {props.children}\n </blockquote>\n );\n }\n return <>{props.children}</>;\n};\n\nconst renderDecorator: RenderDecoratorFunction = (props) => {\n if (props.value === \"strong\") {\n return <strong>{props.children}</strong>;\n }\n if (props.value === \"em\") {\n return <em>{props.children}</em>;\n }\n if (props.value === \"underline\") {\n return <u>{props.children}</u>;\n }\n if (props.value === \"strikeThrough\") {\n return <s>{props.children}</s>;\n }\n if (props.value === \"code\") {\n return (\n <code className=\"px-1 py-0.5 rounded bg-[var(--kyro-surface-accent)] text-[var(--kyro-primary)] text-sm font-mono\">\n {props.children}\n </code>\n );\n }\n return <>{props.children}</>;\n};\n\nconst renderBlock: RenderBlockFunction = (props) => {\n return <div>{props.children}</div>;\n};\n\nconst renderListItem: RenderListItemFunction = (props) => {\n if (props.schemaType.value === \"bullet\") {\n return <li className=\"list-disc ml-4\">{props.children}</li>;\n }\n if (props.schemaType.value === \"number\") {\n return <li className=\"list-decimal ml-4\">{props.children}</li>;\n }\n return <li>{props.children}</li>;\n};\n\nconst renderAnnotation: RenderAnnotationFunction = (props) => {\n if (props.schemaType.name === \"link\") {\n return (\n <a\n href={props.value.href as string}\n className=\"text-[var(--kyro-primary)] underline hover:opacity-80\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n {props.children}\n </a>\n );\n }\n return <>{props.children}</>;\n};\n\nfunction FocusRestoringButton({\n onClick,\n children,\n ...props\n}: React.ButtonHTMLAttributes<HTMLButtonElement>) {\n const editor = useEditor();\n return (\n <button\n type=\"button\"\n onClick={(e) => {\n onClick?.(e);\n editor.send({ type: \"focus\" });\n }}\n {...props}\n >\n {children}\n </button>\n );\n}\n\nconst decoratorIcons: Record<\n string,\n React.ComponentType<{ className?: string }>\n> = {\n strong: Bold,\n em: Italic,\n underline: Underline,\n strikeThrough: Strikethrough,\n code: Code,\n};\n\nconst DecoratorButton: React.FC<{ name: string; title: string }> = ({\n name,\n title,\n}) => {\n const schema = useToolbarSchema({});\n const decoratorSchema = schema.decorators?.find((d) => d.name === name);\n if (!decoratorSchema) return null;\n const { snapshot, send } = useDecoratorButton({\n schemaType: decoratorSchema,\n });\n const Icon = decoratorIcons[name];\n const isActive =\n snapshot.matches({ enabled: \"active\" }) ||\n snapshot.matches({ disabled: \"active\" });\n const isEnabled = snapshot.matches(\"enabled\");\n\n return (\n <FocusRestoringButton\n disabled={!isEnabled}\n data-state={isActive ? \"on\" : \"off\"}\n onClick={() => send({ type: \"toggle\" })}\n title={title}\n className=\"p-1.5 rounded transition-colors disabled:opacity-30 hover:bg-[var(--kyro-surface-accent)] data-[state=on]:bg-[var(--kyro-primary)] data-[state=on]:text-[var(--kyro-sidebar-text-active)]\"\n >\n {Icon && <Icon className=\"w-4 h-4\" />}\n </FocusRestoringButton>\n );\n};\n\nconst ListButton: React.FC<{ name: string; title: string }> = ({\n name,\n title,\n}) => {\n const schema = useToolbarSchema({});\n const listSchema = schema.lists?.find((l) => l.name === name);\n if (!listSchema) return null;\n const { snapshot, send } = useListButton({ schemaType: listSchema });\n const Icon = name === \"bullet\" ? List : ListOrdered;\n const isActive =\n snapshot.matches({ enabled: \"active\" }) ||\n snapshot.matches({ disabled: \"active\" });\n const isEnabled = snapshot.matches(\"enabled\");\n\n return (\n <FocusRestoringButton\n disabled={!isEnabled}\n data-state={isActive ? \"on\" : \"off\"}\n onClick={() => send({ type: \"toggle\" })}\n title={title}\n className=\"p-1.5 rounded transition-colors disabled:opacity-30 hover:bg-[var(--kyro-surface-accent)] data-[state=on]:bg-[var(--kyro-primary)] data-[state=on]:text-[var(--kyro-sidebar-text-active)]\"\n >\n {Icon && <Icon className=\"w-4 h-4\" />}\n </FocusRestoringButton>\n );\n};\n\nconst AnnotationButton: React.FC<{ name: string; title: string }> = ({\n name,\n title,\n}) => {\n const schema = useToolbarSchema({});\n const annotationSchema = schema.annotations?.find((a) => a.name === name);\n if (!annotationSchema) return null;\n const { snapshot, send } = useAnnotationButton({\n schemaType: annotationSchema,\n });\n const isActive =\n snapshot.matches({ enabled: \"active\" }) ||\n snapshot.matches({ disabled: \"active\" });\n const isEnabled = snapshot.matches(\"enabled\");\n const isShowingDialog = snapshot.matches({\n enabled: { inactive: \"showing dialog\" },\n });\n\n return (\n <FocusRestoringButton\n disabled={!isEnabled}\n data-state={isActive ? \"on\" : \"off\"}\n onClick={() =>\n send({\n type: isShowingDialog ? \"close dialog\" : \"open dialog\",\n })\n }\n title={title}\n className=\"p-1.5 rounded transition-colors disabled:opacity-30 hover:bg-[var(--kyro-surface-accent)] data-[state=on]:bg-[var(--kyro-primary)] data-[state=on]:text-[var(--kyro-sidebar-text-active)]\"\n >\n {name === \"link\" && <Link className=\"w-4 h-4\" />}\n </FocusRestoringButton>\n );\n};\n\nconst LinkDialog: React.FC = () => {\n const schema = useToolbarSchema({});\n const popover = useAnnotationPopover({\n schemaTypes: schema.annotations || [],\n });\n const dialogRef = useRef<HTMLDivElement>(null);\n const inputRef = useRef<HTMLInputElement>(null);\n\n useEffect(() => {\n if (popover.snapshot.matches({ enabled: \"active\" }) && inputRef.current) {\n inputRef.current.focus();\n }\n }, [popover.snapshot]);\n\n if (!popover.snapshot.matches({ enabled: \"active\" })) return null;\n\n const activeAnnotations = popover.snapshot.context.annotations || [];\n const activeLink = activeAnnotations.find(\n (a) => a.schemaType.name === \"link\",\n );\n const currentHref = activeLink?.value?.href as string | undefined;\n\n const handleSubmit = (e: React.FormEvent) => {\n e.preventDefault();\n const formData = new FormData(e.target as HTMLFormElement);\n const href = formData.get(\"href\") as string;\n\n if (activeLink) {\n if (href.trim()) {\n popover.send({\n type: \"edit\",\n at: activeLink.at,\n props: { href: href.trim() },\n });\n } else {\n popover.send({\n type: \"remove\",\n schemaType: activeLink.schemaType,\n });\n }\n } else {\n if (href.trim()) {\n popover.send({\n type: \"edit\",\n at: [] as string[],\n props: { href: href.trim() },\n });\n }\n }\n popover.send({ type: \"close\" });\n };\n\n const handleRemove = () => {\n if (activeLink) {\n popover.send({\n type: \"remove\",\n schemaType: activeLink.schemaType,\n });\n }\n popover.send({ type: \"close\" });\n };\n\n return (\n <div\n ref={dialogRef}\n className=\"absolute top-full left-0 z-50 mt-1 w-72 p-3 rounded-lg border border-[var(--kyro-border)] bg-[var(--kyro-bg-primary)] shadow-lg\"\n >\n <div className=\"flex items-center justify-between mb-2\">\n <span className=\"text-sm font-medium text-[var(--kyro-text-primary)]\">\n Link\n </span>\n <button\n type=\"button\"\n onClick={() => popover.send({ type: \"close\" })}\n className=\"p-1 rounded hover:bg-[var(--kyro-surface-accent)]\"\n >\n <X className=\"w-3.5 h-3.5 text-[var(--kyro-text-muted)]\" />\n </button>\n </div>\n <form onSubmit={handleSubmit} className=\"space-y-2\">\n <div className=\"flex gap-1.5\">\n <input\n ref={inputRef}\n name=\"href\"\n type=\"url\"\n defaultValue={currentHref || \"https://\"}\n placeholder=\"Enter URL...\"\n className=\"flex-1 px-2.5 py-1.5 text-sm rounded border border-[var(--kyro-border)] bg-transparent text-[var(--kyro-text-primary)] placeholder:text-[var(--kyro-text-muted)] focus:outline-none focus:ring-1 focus:ring-[var(--kyro-primary)]\"\n />\n <button\n type=\"submit\"\n className=\"px-2.5 py-1.5 text-sm rounded bg-[var(--kyro-primary)] text-[var(--kyro-sidebar-text-active)] hover:opacity-90\"\n >\n {activeLink ? \"Update\" : \"Add\"}\n </button>\n </div>\n {activeLink && (\n <button\n type=\"button\"\n onClick={handleRemove}\n className=\"w-full text-xs text-[var(--kyro-error)] hover:opacity-80 flex items-center justify-center gap-1 py-1\"\n >\n <ExternalLink className=\"w-3 h-3\" />\n Remove link\n </button>\n )}\n </form>\n </div>\n );\n};\n\nconst StyleSelector: React.FC = () => {\n const schema = useToolbarSchema({});\n const editor = useEditor();\n const { snapshot, send } = useStyleSelector({\n schemaTypes: schema.styles || [],\n });\n if (!snapshot.matches(\"enabled\")) return null;\n const activeStyle = snapshot.context.activeStyle || \"normal\";\n\n return (\n <div className=\"relative\">\n <select\n value={activeStyle}\n onChange={(e) => {\n send({ type: \"toggle\", style: e.target.value as string });\n editor.send({ type: \"focus\" });\n }}\n className=\"appearance-none bg-transparent text-sm pr-6 pl-2 py-1 rounded hover:bg-[var(--kyro-surface-accent)] cursor-pointer focus:outline-none focus:ring-1 focus:ring-[var(--kyro-primary)]\"\n >\n {schema.styles?.map((s) => (\n <option key={s.name} value={s.name}>\n {s.title}\n </option>\n ))}\n </select>\n <ChevronDown className=\"w-3 h-3 absolute right-1.5 top-1/2 -translate-y-1/2 pointer-events-none text-[var(--kyro-text-muted)]\" />\n </div>\n );\n};\n\nconst Toolbar: React.FC = () => {\n const { snapshot: historySnapshot, send: historySend } = useHistoryButtons();\n return (\n <div className=\"relative flex items-center gap-0.5 p-1.5 border-b border-[var(--kyro-border)]\">\n <FocusRestoringButton\n disabled={!historySnapshot.matches(\"enabled\")}\n onClick={() => historySend({ type: \"history.undo\" })}\n title=\"Undo\"\n className=\"p-1.5 rounded transition-colors hover:bg-[var(--kyro-surface-accent)] disabled:opacity-30\"\n >\n <Undo className=\"w-4 h-4 text-[var(--kyro-text-secondary)]\" />\n </FocusRestoringButton>\n <FocusRestoringButton\n disabled={!historySnapshot.matches(\"enabled\")}\n onClick={() => historySend({ type: \"history.redo\" })}\n title=\"Redo\"\n className=\"p-1.5 rounded transition-colors hover:bg-[var(--kyro-surface-accent)] disabled:opacity-30\"\n >\n <Redo className=\"w-4 h-4 text-[var(--kyro-text-secondary)]\" />\n </FocusRestoringButton>\n <div className=\"w-px h-5 bg-[var(--kyro-border)] mx-1\" />\n <StyleSelector />\n <div className=\"w-px h-5 bg-[var(--kyro-border)] mx-1\" />\n <DecoratorButton name=\"strong\" title=\"Bold\" />\n <DecoratorButton name=\"em\" title=\"Italic\" />\n <DecoratorButton name=\"underline\" title=\"Underline\" />\n <DecoratorButton name=\"strikeThrough\" title=\"Strikethrough\" />\n <DecoratorButton name=\"code\" title=\"Code\" />\n <div className=\"w-px h-5 bg-[var(--kyro-border)] mx-1\" />\n <AnnotationButton name=\"link\" title=\"Link\" />\n <div className=\"w-px h-5 bg-[var(--kyro-border)] mx-1\" />\n <ListButton name=\"bullet\" title=\"Bullet List\" />\n <ListButton name=\"number\" title=\"Numbered List\" />\n <LinkDialog />\n </div>\n );\n};\n\nconst EditorInner: React.FC<{\n onChange: (blocks: Record<string, unknown>[]) => void;\n disabled?: boolean;\n}> = ({ onChange, disabled }) => {\n return (\n <>\n <Toolbar />\n <PortableTextEditable\n className=\"min-h-[200px] p-4 focus:outline-none text-[var(--kyro-text-primary)]\"\n placeholder=\"Start typing...\"\n readOnly={disabled}\n renderStyle={renderStyle}\n renderDecorator={renderDecorator}\n renderBlock={renderBlock}\n renderListItem={renderListItem}\n renderAnnotation={renderAnnotation}\n />\n </>\n );\n};\n\nexport const EditorClient: React.FC<EditorClientProps> = ({\n initialValue,\n onChange,\n disabled,\n}) => {\n const [value, setValue] = useState(() => sanitizeInitialValue(initialValue));\n const prevInitialValueRef = useRef(initialValue);\n\n useEffect(() => {\n const sanitized = sanitizeInitialValue(initialValue);\n const prevSanitized = sanitizeInitialValue(prevInitialValueRef.current);\n if (JSON.stringify(sanitized) !== JSON.stringify(prevSanitized)) {\n setValue(sanitized);\n prevInitialValueRef.current = initialValue;\n }\n }, [initialValue]);\n\nconst handleChange = useCallback(\n (newValue: Record<string, unknown>[]) => {\n setValue(newValue);\n onChange(newValue);\n },\n [onChange],\n );\n\n return (\n <EditorProvider\n key={JSON.stringify(value)}\n initialConfig={{\n schemaDefinition: schemaDefinition as Record<string, unknown>,\n initialValue: value,\n }}\n >\n <EventListenerPlugin\n on={(event: Record<string, unknown>) => {\n if (event.type === \"mutation\" && event.value) {\n handleChange(event.value as Record<string, unknown>);\n }\n }}\n />\n<EditorInner onChange={handleChange} disabled={disabled} />\n </EditorProvider>\n);\n};\n"]}
|