@optilogic/editor 1.0.0-beta.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.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Optilogic
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,87 @@
1
+ # @optilogic/editor
2
+
3
+ Rich text editor component for opti-ui - SlateEditor built on Slate.js.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @optilogic/editor @optilogic/core slate slate-react slate-history
9
+ ```
10
+
11
+ ## Setup
12
+
13
+ Make sure you have configured `@optilogic/core` with the Tailwind preset and CSS variables.
14
+
15
+ ## Usage
16
+
17
+ ```tsx
18
+ import { SlateEditor } from '@optilogic/editor';
19
+ import { useState } from 'react';
20
+
21
+ function App() {
22
+ const [content, setContent] = useState('');
23
+
24
+ return (
25
+ <SlateEditor
26
+ value={content}
27
+ onChange={setContent}
28
+ placeholder="Type your message..."
29
+ enableTags
30
+ onSubmit={(text) => {
31
+ console.log('Submitted:', text);
32
+ }}
33
+ />
34
+ );
35
+ }
36
+ ```
37
+
38
+ ## Features
39
+
40
+ - Rich text editing with Slate.js
41
+ - Inline tag support (type # to create tags)
42
+ - Keyboard shortcuts
43
+ - Customizable placeholder
44
+ - Submit on Enter (Shift+Enter for new line)
45
+ - History (undo/redo)
46
+ - Theme-aware styling
47
+
48
+ ## Props
49
+
50
+ | Prop | Type | Default | Description |
51
+ |------|------|---------|-------------|
52
+ | value | string | '' | Initial plain text value |
53
+ | onChange | (value: string) => void | - | Callback when content changes |
54
+ | onSubmit | (text: string) => void | - | Callback when Enter is pressed |
55
+ | onTagCreate | (tag: string) => void | - | Callback when a tag is created |
56
+ | onTagDelete | (tag: string) => void | - | Callback when a tag is deleted |
57
+ | placeholder | string | 'Type something...' | Placeholder text |
58
+ | disabled | boolean | false | Whether the editor is disabled |
59
+ | enableTags | boolean | true | Whether to enable tag detection |
60
+ | minRows | number | 3 | Minimum number of rows |
61
+ | maxRows | number | 8 | Maximum number of rows |
62
+ | className | string | - | Additional class names |
63
+
64
+ ## Ref Methods
65
+
66
+ ```tsx
67
+ const editorRef = useRef<SlateEditorRef>(null);
68
+
69
+ // Focus the editor
70
+ editorRef.current?.focus();
71
+
72
+ // Clear content
73
+ editorRef.current?.clear();
74
+
75
+ // Get plain text
76
+ const text = editorRef.current?.getText();
77
+
78
+ // Insert text at cursor
79
+ editorRef.current?.insertText('Hello');
80
+
81
+ // Insert a tag
82
+ editorRef.current?.insertTag('important');
83
+ ```
84
+
85
+ ## License
86
+
87
+ MIT
package/dist/index.cjs ADDED
@@ -0,0 +1,487 @@
1
+ 'use strict';
2
+
3
+ var React = require('react');
4
+ var slate = require('slate');
5
+ var slateReact = require('slate-react');
6
+ var slateHistory = require('slate-history');
7
+ var core = require('@optilogic/core');
8
+ var jsxRuntime = require('react/jsx-runtime');
9
+
10
+ function _interopNamespace(e) {
11
+ if (e && e.__esModule) return e;
12
+ var n = Object.create(null);
13
+ if (e) {
14
+ Object.keys(e).forEach(function (k) {
15
+ if (k !== 'default') {
16
+ var d = Object.getOwnPropertyDescriptor(e, k);
17
+ Object.defineProperty(n, k, d.get ? d : {
18
+ enumerable: true,
19
+ get: function () { return e[k]; }
20
+ });
21
+ }
22
+ });
23
+ }
24
+ n.default = e;
25
+ return Object.freeze(n);
26
+ }
27
+
28
+ var React__namespace = /*#__PURE__*/_interopNamespace(React);
29
+
30
+ // src/slate-editor.tsx
31
+ var withTags = (editor) => {
32
+ const { isInline, isVoid, deleteBackward, deleteForward } = editor;
33
+ editor.isInline = (element) => {
34
+ return element.type === "tag" ? true : isInline(element);
35
+ };
36
+ editor.isVoid = (element) => {
37
+ return element.type === "tag" ? true : isVoid(element);
38
+ };
39
+ editor.deleteBackward = (unit) => {
40
+ const { selection } = editor;
41
+ if (selection && slate.Range.isCollapsed(selection)) {
42
+ const [tagEntry] = slate.Editor.nodes(editor, {
43
+ match: (n) => !slate.Editor.isEditor(n) && slate.Element.isElement(n) && n.type === "tag"
44
+ });
45
+ if (tagEntry) {
46
+ const [, path] = tagEntry;
47
+ const after = slate.Editor.after(editor, path);
48
+ if (after && slate.Path.equals(selection.anchor.path, after.path)) {
49
+ slate.Transforms.removeNodes(editor, { at: path });
50
+ return;
51
+ }
52
+ }
53
+ const before = slate.Editor.before(editor, selection);
54
+ if (before) {
55
+ const [beforeTagEntry] = slate.Editor.nodes(editor, {
56
+ at: before,
57
+ match: (n) => !slate.Editor.isEditor(n) && slate.Element.isElement(n) && n.type === "tag"
58
+ });
59
+ if (beforeTagEntry) {
60
+ const [, path] = beforeTagEntry;
61
+ slate.Transforms.removeNodes(editor, { at: path });
62
+ return;
63
+ }
64
+ }
65
+ }
66
+ deleteBackward(unit);
67
+ };
68
+ editor.deleteForward = (unit) => {
69
+ const { selection } = editor;
70
+ if (selection && slate.Range.isCollapsed(selection)) {
71
+ const after = slate.Editor.after(editor, selection);
72
+ if (after) {
73
+ const [afterTagEntry] = slate.Editor.nodes(editor, {
74
+ at: after,
75
+ match: (n) => !slate.Editor.isEditor(n) && slate.Element.isElement(n) && n.type === "tag"
76
+ });
77
+ if (afterTagEntry) {
78
+ const [, path] = afterTagEntry;
79
+ slate.Transforms.removeNodes(editor, { at: path });
80
+ return;
81
+ }
82
+ }
83
+ }
84
+ deleteForward(unit);
85
+ };
86
+ return editor;
87
+ };
88
+ function serializeToText(nodes) {
89
+ return nodes.map((n) => {
90
+ if (slate.Text.isText(n)) {
91
+ return n.text;
92
+ }
93
+ if (slate.Element.isElement(n)) {
94
+ if (n.type === "tag") {
95
+ return `#${n.tag}`;
96
+ }
97
+ return serializeToText(n.children);
98
+ }
99
+ return "";
100
+ }).join("");
101
+ }
102
+ function deserializeFromText(text) {
103
+ if (!text) {
104
+ return [{ type: "paragraph", children: [{ text: "" }] }];
105
+ }
106
+ const children = [];
107
+ const tagRegex = /#([a-zA-Z0-9@#$_-]+(?:--[a-zA-Z0-9_-]+)?)/g;
108
+ let lastIndex = 0;
109
+ let match;
110
+ while ((match = tagRegex.exec(text)) !== null) {
111
+ if (match.index > lastIndex) {
112
+ children.push({ text: text.substring(lastIndex, match.index) });
113
+ }
114
+ children.push({
115
+ type: "tag",
116
+ tag: match[1],
117
+ children: [{ text: "" }]
118
+ });
119
+ lastIndex = match.index + match[0].length;
120
+ }
121
+ if (lastIndex < text.length) {
122
+ children.push({ text: text.substring(lastIndex) });
123
+ }
124
+ if (children.length === 0) {
125
+ children.push({ text: "" });
126
+ }
127
+ return [{ type: "paragraph", children }];
128
+ }
129
+ var TagElementRenderer = ({
130
+ attributes,
131
+ children,
132
+ element
133
+ }) => {
134
+ return /* @__PURE__ */ jsxRuntime.jsxs(
135
+ "span",
136
+ {
137
+ ...attributes,
138
+ contentEditable: false,
139
+ className: core.cn(
140
+ "inline-flex items-center",
141
+ "px-1.5 py-0.5 mx-0.5",
142
+ "rounded-md border",
143
+ "bg-accent/20 text-accent border-accent/40",
144
+ "text-sm font-medium",
145
+ "select-none cursor-default"
146
+ ),
147
+ children: [
148
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-bold", children: "#" }),
149
+ element.tag,
150
+ children
151
+ ]
152
+ }
153
+ );
154
+ };
155
+ var DefaultElement = ({ attributes, children }) => {
156
+ return /* @__PURE__ */ jsxRuntime.jsx("p", { ...attributes, children });
157
+ };
158
+ var Leaf = ({ attributes, children }) => {
159
+ return /* @__PURE__ */ jsxRuntime.jsx("span", { ...attributes, children });
160
+ };
161
+ var SlateEditor = React__namespace.forwardRef(
162
+ ({
163
+ value = "",
164
+ onChange,
165
+ onTagCreate,
166
+ onTagDelete,
167
+ onSubmit,
168
+ placeholder = "Type something...",
169
+ disabled = false,
170
+ enableTags = true,
171
+ minRows = 3,
172
+ maxRows = 8,
173
+ className
174
+ }, ref) => {
175
+ const editor = React__namespace.useMemo(
176
+ () => withTags(slateHistory.withHistory(slateReact.withReact(slate.createEditor()))),
177
+ []
178
+ );
179
+ const [isCreatingTag, setIsCreatingTag] = React__namespace.useState(false);
180
+ const [tagStartPoint, setTagStartPoint] = React__namespace.useState(null);
181
+ const [currentTagText, setCurrentTagText] = React__namespace.useState("");
182
+ const [editorValue, setEditorValue] = React__namespace.useState(
183
+ () => deserializeFromText(value)
184
+ );
185
+ React__namespace.useEffect(() => {
186
+ const newValue = deserializeFromText(value);
187
+ const currentText = serializeToText(editorValue);
188
+ if (currentText !== value) {
189
+ setEditorValue(newValue);
190
+ slate.Transforms.removeNodes(editor, { at: [] });
191
+ slate.Transforms.insertNodes(editor, newValue, { at: [0] });
192
+ slate.Transforms.select(editor, slate.Editor.start(editor, []));
193
+ }
194
+ }, [value, editor]);
195
+ React__namespace.useImperativeHandle(
196
+ ref,
197
+ () => ({
198
+ focus: () => {
199
+ slateReact.ReactEditor.focus(editor);
200
+ },
201
+ clear: () => {
202
+ const newValue = [
203
+ { type: "paragraph", children: [{ text: "" }] }
204
+ ];
205
+ setEditorValue(newValue);
206
+ slate.Transforms.select(editor, slate.Editor.start(editor, []));
207
+ },
208
+ getText: () => serializeToText(editorValue),
209
+ insertText: (text) => {
210
+ slate.Transforms.insertText(editor, text);
211
+ },
212
+ insertTag: (tag) => {
213
+ insertTag(editor, tag);
214
+ onTagCreate?.(tag);
215
+ }
216
+ }),
217
+ [editor, editorValue, onTagCreate]
218
+ );
219
+ const handleChange = React__namespace.useCallback(
220
+ (newValue) => {
221
+ setEditorValue(newValue);
222
+ if (isCreatingTag && tagStartPoint) {
223
+ const { selection } = editor;
224
+ if (selection && slate.Range.isCollapsed(selection)) {
225
+ const currentPath = selection.anchor.path;
226
+ const currentOffset = selection.anchor.offset;
227
+ if (slate.Path.equals(currentPath, tagStartPoint.path)) {
228
+ try {
229
+ const [textNode] = slate.Editor.node(editor, currentPath);
230
+ if (slate.Text.isText(textNode)) {
231
+ const tagText = textNode.text.substring(
232
+ tagStartPoint.offset + 1,
233
+ currentOffset
234
+ );
235
+ setCurrentTagText(tagText);
236
+ }
237
+ } catch {
238
+ }
239
+ }
240
+ }
241
+ }
242
+ const oldTags = /* @__PURE__ */ new Set();
243
+ const newTags = /* @__PURE__ */ new Set();
244
+ for (const node of slate.Node.descendants(editor, {
245
+ from: [],
246
+ pass: ([n]) => slate.Element.isElement(n) && n.type === "paragraph"
247
+ })) {
248
+ const [n] = node;
249
+ if (slate.Element.isElement(n) && n.type === "tag") {
250
+ oldTags.add(n.tag);
251
+ }
252
+ }
253
+ const extractTags = (nodes) => {
254
+ for (const node of nodes) {
255
+ if (slate.Element.isElement(node)) {
256
+ if (node.type === "tag") {
257
+ newTags.add(node.tag);
258
+ }
259
+ if ("children" in node) {
260
+ extractTags(node.children);
261
+ }
262
+ }
263
+ }
264
+ };
265
+ extractTags(newValue);
266
+ for (const tag of oldTags) {
267
+ if (!newTags.has(tag)) {
268
+ onTagDelete?.(tag);
269
+ }
270
+ }
271
+ const text = serializeToText(newValue);
272
+ onChange?.(text);
273
+ },
274
+ [editor, onChange, onTagDelete, isCreatingTag, tagStartPoint]
275
+ );
276
+ const insertTag = (editor2, tag) => {
277
+ const tagNode = {
278
+ type: "tag",
279
+ tag,
280
+ children: [{ text: "" }]
281
+ };
282
+ slate.Transforms.insertNodes(editor2, tagNode);
283
+ slate.Transforms.move(editor2);
284
+ slate.Transforms.insertText(editor2, " ");
285
+ };
286
+ const completeTag = React__namespace.useCallback(() => {
287
+ if (!isCreatingTag || !tagStartPoint) return;
288
+ const { selection } = editor;
289
+ if (!selection || !slate.Range.isCollapsed(selection)) return;
290
+ const currentPath = selection.anchor.path;
291
+ const currentOffset = selection.anchor.offset;
292
+ if (!slate.Path.equals(currentPath, tagStartPoint.path)) {
293
+ setIsCreatingTag(false);
294
+ setTagStartPoint(null);
295
+ setCurrentTagText("");
296
+ return;
297
+ }
298
+ const [textNode] = slate.Editor.node(editor, currentPath);
299
+ if (!slate.Text.isText(textNode)) {
300
+ setIsCreatingTag(false);
301
+ setTagStartPoint(null);
302
+ setCurrentTagText("");
303
+ return;
304
+ }
305
+ const tagText = textNode.text.substring(
306
+ tagStartPoint.offset + 1,
307
+ currentOffset
308
+ );
309
+ if (!tagText.trim()) {
310
+ setIsCreatingTag(false);
311
+ setTagStartPoint(null);
312
+ setCurrentTagText("");
313
+ return;
314
+ }
315
+ const start = { path: currentPath, offset: tagStartPoint.offset };
316
+ const end = { path: currentPath, offset: currentOffset };
317
+ slate.Transforms.delete(editor, { at: { anchor: start, focus: end } });
318
+ insertTag(editor, tagText.trim());
319
+ onTagCreate?.(tagText.trim());
320
+ setIsCreatingTag(false);
321
+ setTagStartPoint(null);
322
+ setCurrentTagText("");
323
+ }, [editor, isCreatingTag, tagStartPoint, onTagCreate]);
324
+ const cancelTag = React__namespace.useCallback(() => {
325
+ setIsCreatingTag(false);
326
+ setTagStartPoint(null);
327
+ setCurrentTagText("");
328
+ }, []);
329
+ const handleKeyDown = React__namespace.useCallback(
330
+ (event) => {
331
+ if (isCreatingTag) {
332
+ if (event.key === "Enter" || event.key === " ") {
333
+ event.preventDefault();
334
+ completeTag();
335
+ return;
336
+ }
337
+ if (event.key === "Escape") {
338
+ event.preventDefault();
339
+ cancelTag();
340
+ return;
341
+ }
342
+ }
343
+ if (enableTags && event.key === "#" && !isCreatingTag) {
344
+ const { selection } = editor;
345
+ if (selection && slate.Range.isCollapsed(selection)) {
346
+ setIsCreatingTag(true);
347
+ setCurrentTagText("");
348
+ setTagStartPoint({
349
+ path: selection.anchor.path,
350
+ offset: selection.anchor.offset
351
+ });
352
+ }
353
+ }
354
+ if (event.key === "Enter" && !event.shiftKey && !isCreatingTag) {
355
+ event.preventDefault();
356
+ const text = serializeToText(editorValue);
357
+ if (text.trim() && onSubmit) {
358
+ onSubmit(text.trim());
359
+ }
360
+ return;
361
+ }
362
+ if ((event.key === "Backspace" || event.key === "Delete") && event.ctrlKey) {
363
+ const { selection } = editor;
364
+ if (selection && slate.Range.isCollapsed(selection)) {
365
+ const direction = event.key === "Backspace" ? "backward" : "forward";
366
+ const pointFn = direction === "backward" ? slate.Editor.before : slate.Editor.after;
367
+ const point = pointFn(editor, selection, { unit: "word" });
368
+ if (point) {
369
+ const [tagEntry] = slate.Editor.nodes(editor, {
370
+ at: direction === "backward" ? { anchor: point, focus: selection.anchor } : { anchor: selection.anchor, focus: point },
371
+ match: (n) => !slate.Editor.isEditor(n) && slate.Element.isElement(n) && n.type === "tag"
372
+ });
373
+ if (tagEntry) {
374
+ event.preventDefault();
375
+ const [tagNode, tagPath] = tagEntry;
376
+ if (slate.Element.isElement(tagNode) && tagNode.type === "tag") {
377
+ onTagDelete?.(tagNode.tag);
378
+ }
379
+ slate.Transforms.removeNodes(editor, { at: tagPath });
380
+ return;
381
+ }
382
+ }
383
+ }
384
+ }
385
+ },
386
+ [
387
+ editor,
388
+ editorValue,
389
+ isCreatingTag,
390
+ enableTags,
391
+ completeTag,
392
+ cancelTag,
393
+ onSubmit,
394
+ onTagDelete
395
+ ]
396
+ );
397
+ const renderElement = React__namespace.useCallback((props) => {
398
+ switch (props.element.type) {
399
+ case "tag":
400
+ return /* @__PURE__ */ jsxRuntime.jsx(
401
+ TagElementRenderer,
402
+ {
403
+ ...props,
404
+ element: props.element
405
+ }
406
+ );
407
+ default:
408
+ return /* @__PURE__ */ jsxRuntime.jsx(DefaultElement, { ...props });
409
+ }
410
+ }, []);
411
+ const renderLeaf = React__namespace.useCallback((props) => {
412
+ return /* @__PURE__ */ jsxRuntime.jsx(Leaf, { ...props });
413
+ }, []);
414
+ const lineHeight = 24;
415
+ const minHeight = lineHeight * minRows;
416
+ const maxHeight = lineHeight * maxRows;
417
+ return /* @__PURE__ */ jsxRuntime.jsxs(
418
+ "div",
419
+ {
420
+ className: core.cn(
421
+ "relative w-full rounded-md",
422
+ "bg-transparent",
423
+ disabled && "opacity-50 cursor-not-allowed",
424
+ className
425
+ ),
426
+ children: [
427
+ /* @__PURE__ */ jsxRuntime.jsx(
428
+ slateReact.Slate,
429
+ {
430
+ editor,
431
+ initialValue: editorValue,
432
+ onChange: handleChange,
433
+ children: /* @__PURE__ */ jsxRuntime.jsx(
434
+ slateReact.Editable,
435
+ {
436
+ readOnly: disabled,
437
+ placeholder,
438
+ renderElement,
439
+ renderLeaf,
440
+ onKeyDown: handleKeyDown,
441
+ className: core.cn(
442
+ "w-full outline-none",
443
+ "text-foreground placeholder:text-muted-foreground",
444
+ "leading-6",
445
+ "overflow-y-auto overflow-x-hidden",
446
+ "whitespace-pre-wrap break-words"
447
+ ),
448
+ style: {
449
+ minHeight: `${minHeight}px`,
450
+ maxHeight: `${maxHeight}px`,
451
+ wordBreak: "break-word",
452
+ overflowWrap: "break-word"
453
+ },
454
+ spellCheck: true,
455
+ autoCorrect: "off",
456
+ autoCapitalize: "off"
457
+ }
458
+ )
459
+ }
460
+ ),
461
+ isCreatingTag && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "absolute bottom-full left-0 mb-2 flex items-center gap-2.5 animate-in fade-in-0 slide-in-from-bottom-1 duration-150", children: [
462
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center px-2 py-1 rounded-md border shadow-sm bg-accent/20 border-accent/40", children: [
463
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-bold text-sm text-accent", children: "#" }),
464
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-medium min-w-[2ch] text-accent", children: currentTagText || /* @__PURE__ */ jsxRuntime.jsx("span", { className: "opacity-50 italic", children: "tag" }) })
465
+ ] }),
466
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-muted-foreground/80 text-[11px]", children: [
467
+ /* @__PURE__ */ jsxRuntime.jsx("kbd", { className: "px-1.5 py-0.5 bg-muted rounded text-[10px] font-mono mr-1", children: "Enter" }),
468
+ "or",
469
+ /* @__PURE__ */ jsxRuntime.jsx("kbd", { className: "px-1.5 py-0.5 bg-muted rounded text-[10px] font-mono mx-1", children: "Space" }),
470
+ "to add",
471
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "mx-1.5 text-muted-foreground/50", children: "\xB7" }),
472
+ /* @__PURE__ */ jsxRuntime.jsx("kbd", { className: "px-1.5 py-0.5 bg-muted rounded text-[10px] font-mono mr-1", children: "Esc" }),
473
+ "to cancel"
474
+ ] })
475
+ ] })
476
+ ]
477
+ }
478
+ );
479
+ }
480
+ );
481
+ SlateEditor.displayName = "SlateEditor";
482
+
483
+ exports.SlateEditor = SlateEditor;
484
+ exports.deserializeFromText = deserializeFromText;
485
+ exports.serializeToText = serializeToText;
486
+ //# sourceMappingURL=index.cjs.map
487
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/slate-editor.tsx"],"names":["Range","Editor","SlateElement","Path","Transforms","Text","jsxs","cn","jsx","React","withHistory","withReact","createEditor","ReactEditor","Node","editor","Slate","Editable"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * SlateEditor Component\n *\n * A reusable rich text editor primitive based on Slate.js\n * Provides consistent theming and can be used as an alternative to textarea\n */\n\nimport * as React from \"react\";\nimport {\n createEditor,\n Descendant,\n Editor,\n Transforms,\n Text,\n Element as SlateElement,\n Range,\n Node,\n BaseEditor,\n Path,\n} from \"slate\";\nimport {\n Slate,\n Editable,\n withReact,\n ReactEditor,\n RenderElementProps,\n RenderLeafProps,\n} from \"slate-react\";\nimport { withHistory, HistoryEditor } from \"slate-history\";\nimport { cn } from \"@optilogic/core\";\n\ntype TagElement = {\n type: \"tag\";\n tag: string;\n children: [{ text: \"\" }];\n};\n\ntype ParagraphElement = {\n type: \"paragraph\";\n children: Descendant[];\n};\n\ntype CustomElement = TagElement | ParagraphElement;\ntype CustomText = { text: string };\n\ndeclare module \"slate\" {\n interface CustomTypes {\n Editor: BaseEditor & ReactEditor & HistoryEditor;\n Element: CustomElement;\n Text: CustomText;\n }\n}\n\nconst isTagElement = (element: CustomElement): element is TagElement => {\n return element.type === \"tag\";\n};\n\nexport interface SlateEditorRef {\n /** Focus the editor */\n focus: () => void;\n /** Clear the editor content */\n clear: () => void;\n /** Get plain text content */\n getText: () => string;\n /** Insert text at cursor */\n insertText: (text: string) => void;\n /** Insert a tag element */\n insertTag: (tag: string) => void;\n}\n\nexport interface SlateEditorProps {\n /** Initial plain text value */\n value?: string;\n /** Callback when content changes (plain text) */\n onChange?: (value: string) => void;\n /** Callback when a tag is created */\n onTagCreate?: (tag: string) => void;\n /** Callback when a tag is deleted */\n onTagDelete?: (tag: string) => void;\n /** Callback when Enter is pressed (without Shift) */\n onSubmit?: (text: string) => void;\n /** Placeholder text */\n placeholder?: string;\n /** Whether the editor is disabled */\n disabled?: boolean;\n /** Whether to enable tag detection (# character) */\n enableTags?: boolean;\n /** Minimum number of rows */\n minRows?: number;\n /** Maximum number of rows before scrolling */\n maxRows?: number;\n /** Additional class names */\n className?: string;\n}\n\nconst withTags = (editor: Editor) => {\n const { isInline, isVoid, deleteBackward, deleteForward } = editor;\n\n editor.isInline = (element) => {\n return element.type === \"tag\" ? true : isInline(element);\n };\n\n editor.isVoid = (element) => {\n return element.type === \"tag\" ? true : isVoid(element);\n };\n\n editor.deleteBackward = (unit) => {\n const { selection } = editor;\n\n if (selection && Range.isCollapsed(selection)) {\n const [tagEntry] = Editor.nodes(editor, {\n match: (n) =>\n !Editor.isEditor(n) && SlateElement.isElement(n) && n.type === \"tag\",\n });\n\n if (tagEntry) {\n const [, path] = tagEntry;\n const after = Editor.after(editor, path);\n if (after && Path.equals(selection.anchor.path, after.path)) {\n Transforms.removeNodes(editor, { at: path });\n return;\n }\n }\n\n const before = Editor.before(editor, selection);\n if (before) {\n const [beforeTagEntry] = Editor.nodes(editor, {\n at: before,\n match: (n) =>\n !Editor.isEditor(n) &&\n SlateElement.isElement(n) &&\n n.type === \"tag\",\n });\n\n if (beforeTagEntry) {\n const [, path] = beforeTagEntry;\n Transforms.removeNodes(editor, { at: path });\n return;\n }\n }\n }\n\n deleteBackward(unit);\n };\n\n editor.deleteForward = (unit) => {\n const { selection } = editor;\n\n if (selection && Range.isCollapsed(selection)) {\n const after = Editor.after(editor, selection);\n if (after) {\n const [afterTagEntry] = Editor.nodes(editor, {\n at: after,\n match: (n) =>\n !Editor.isEditor(n) &&\n SlateElement.isElement(n) &&\n n.type === \"tag\",\n });\n\n if (afterTagEntry) {\n const [, path] = afterTagEntry;\n Transforms.removeNodes(editor, { at: path });\n return;\n }\n }\n }\n\n deleteForward(unit);\n };\n\n return editor;\n};\n\n/**\n * Convert Slate content to plain text\n */\nexport function serializeToText(nodes: Descendant[]): string {\n return nodes\n .map((n) => {\n if (Text.isText(n)) {\n return n.text;\n }\n if (SlateElement.isElement(n)) {\n if (n.type === \"tag\") {\n return `#${n.tag}`;\n }\n return serializeToText(n.children);\n }\n return \"\";\n })\n .join(\"\");\n}\n\n/**\n * Convert plain text to Slate nodes (preserving existing tags)\n */\nexport function deserializeFromText(text: string): Descendant[] {\n if (!text) {\n return [{ type: \"paragraph\", children: [{ text: \"\" }] }];\n }\n\n const children: Descendant[] = [];\n const tagRegex = /#([a-zA-Z0-9@#$_-]+(?:--[a-zA-Z0-9_-]+)?)/g;\n let lastIndex = 0;\n let match;\n\n while ((match = tagRegex.exec(text)) !== null) {\n if (match.index > lastIndex) {\n children.push({ text: text.substring(lastIndex, match.index) });\n }\n\n children.push({\n type: \"tag\",\n tag: match[1],\n children: [{ text: \"\" }],\n });\n\n lastIndex = match.index + match[0].length;\n }\n\n if (lastIndex < text.length) {\n children.push({ text: text.substring(lastIndex) });\n }\n\n if (children.length === 0) {\n children.push({ text: \"\" });\n }\n\n return [{ type: \"paragraph\", children }];\n}\n\nconst TagElementRenderer = ({\n attributes,\n children,\n element,\n}: RenderElementProps & { element: TagElement }) => {\n return (\n <span\n {...attributes}\n contentEditable={false}\n className={cn(\n \"inline-flex items-center\",\n \"px-1.5 py-0.5 mx-0.5\",\n \"rounded-md border\",\n \"bg-accent/20 text-accent border-accent/40\",\n \"text-sm font-medium\",\n \"select-none cursor-default\"\n )}\n >\n <span className=\"font-bold\">#</span>\n {element.tag}\n {children}\n </span>\n );\n};\n\nconst DefaultElement = ({ attributes, children }: RenderElementProps) => {\n return <p {...attributes}>{children}</p>;\n};\n\nconst Leaf = ({ attributes, children }: RenderLeafProps) => {\n return <span {...attributes}>{children}</span>;\n};\n\n/**\n * SlateEditor component\n *\n * A rich text editor based on Slate.js with support for inline tags.\n * Can be used as a drop-in replacement for textarea with enhanced features.\n *\n * @example\n * <SlateEditor\n * value={content}\n * onChange={setContent}\n * placeholder=\"Type your message...\"\n * onSubmit={(text) => console.log('Submitted:', text)}\n * />\n */\nexport const SlateEditor = React.forwardRef<SlateEditorRef, SlateEditorProps>(\n (\n {\n value = \"\",\n onChange,\n onTagCreate,\n onTagDelete,\n onSubmit,\n placeholder = \"Type something...\",\n disabled = false,\n enableTags = true,\n minRows = 3,\n maxRows = 8,\n className,\n },\n ref\n ) => {\n const editor = React.useMemo(\n () => withTags(withHistory(withReact(createEditor()))),\n []\n );\n\n const [isCreatingTag, setIsCreatingTag] = React.useState(false);\n const [tagStartPoint, setTagStartPoint] = React.useState<{\n path: Path;\n offset: number;\n } | null>(null);\n const [currentTagText, setCurrentTagText] = React.useState(\"\");\n\n const [editorValue, setEditorValue] = React.useState<Descendant[]>(() =>\n deserializeFromText(value)\n );\n\n React.useEffect(() => {\n const newValue = deserializeFromText(value);\n const currentText = serializeToText(editorValue);\n if (currentText !== value) {\n setEditorValue(newValue);\n Transforms.removeNodes(editor, { at: [] });\n Transforms.insertNodes(editor, newValue, { at: [0] });\n Transforms.select(editor, Editor.start(editor, []));\n }\n }, [value, editor]);\n\n React.useImperativeHandle(\n ref,\n () => ({\n focus: () => {\n ReactEditor.focus(editor);\n },\n clear: () => {\n const newValue: Descendant[] = [\n { type: \"paragraph\", children: [{ text: \"\" }] },\n ];\n setEditorValue(newValue);\n Transforms.select(editor, Editor.start(editor, []));\n },\n getText: () => serializeToText(editorValue),\n insertText: (text: string) => {\n Transforms.insertText(editor, text);\n },\n insertTag: (tag: string) => {\n insertTag(editor, tag);\n onTagCreate?.(tag);\n },\n }),\n [editor, editorValue, onTagCreate]\n );\n\n const handleChange = React.useCallback(\n (newValue: Descendant[]) => {\n setEditorValue(newValue);\n\n if (isCreatingTag && tagStartPoint) {\n const { selection } = editor;\n if (selection && Range.isCollapsed(selection)) {\n const currentPath = selection.anchor.path;\n const currentOffset = selection.anchor.offset;\n\n if (Path.equals(currentPath, tagStartPoint.path)) {\n try {\n const [textNode] = Editor.node(editor, currentPath);\n if (Text.isText(textNode)) {\n const tagText = textNode.text.substring(\n tagStartPoint.offset + 1,\n currentOffset\n );\n setCurrentTagText(tagText);\n }\n } catch {\n // Ignore - node may not exist\n }\n }\n }\n }\n\n const oldTags = new Set<string>();\n const newTags = new Set<string>();\n\n for (const node of Node.descendants(editor, {\n from: [],\n pass: ([n]) => SlateElement.isElement(n) && n.type === \"paragraph\",\n })) {\n const [n] = node;\n if (SlateElement.isElement(n) && n.type === \"tag\") {\n oldTags.add(n.tag);\n }\n }\n\n const extractTags = (nodes: Descendant[]) => {\n for (const node of nodes) {\n if (SlateElement.isElement(node)) {\n if (node.type === \"tag\") {\n newTags.add(node.tag);\n }\n if (\"children\" in node) {\n extractTags(node.children);\n }\n }\n }\n };\n extractTags(newValue);\n\n for (const tag of oldTags) {\n if (!newTags.has(tag)) {\n onTagDelete?.(tag);\n }\n }\n\n const text = serializeToText(newValue);\n onChange?.(text);\n },\n [editor, onChange, onTagDelete, isCreatingTag, tagStartPoint]\n );\n\n const insertTag = (editor: Editor, tag: string) => {\n const tagNode: TagElement = {\n type: \"tag\",\n tag,\n children: [{ text: \"\" }],\n };\n Transforms.insertNodes(editor, tagNode);\n Transforms.move(editor);\n Transforms.insertText(editor, \" \");\n };\n\n const completeTag = React.useCallback(() => {\n if (!isCreatingTag || !tagStartPoint) return;\n\n const { selection } = editor;\n if (!selection || !Range.isCollapsed(selection)) return;\n\n const currentPath = selection.anchor.path;\n const currentOffset = selection.anchor.offset;\n\n if (!Path.equals(currentPath, tagStartPoint.path)) {\n setIsCreatingTag(false);\n setTagStartPoint(null);\n setCurrentTagText(\"\");\n return;\n }\n\n const [textNode] = Editor.node(editor, currentPath);\n if (!Text.isText(textNode)) {\n setIsCreatingTag(false);\n setTagStartPoint(null);\n setCurrentTagText(\"\");\n return;\n }\n\n const tagText = textNode.text.substring(\n tagStartPoint.offset + 1,\n currentOffset\n );\n\n if (!tagText.trim()) {\n setIsCreatingTag(false);\n setTagStartPoint(null);\n setCurrentTagText(\"\");\n return;\n }\n\n const start = { path: currentPath, offset: tagStartPoint.offset };\n const end = { path: currentPath, offset: currentOffset };\n\n Transforms.delete(editor, { at: { anchor: start, focus: end } });\n insertTag(editor, tagText.trim());\n\n onTagCreate?.(tagText.trim());\n\n setIsCreatingTag(false);\n setTagStartPoint(null);\n setCurrentTagText(\"\");\n }, [editor, isCreatingTag, tagStartPoint, onTagCreate]);\n\n const cancelTag = React.useCallback(() => {\n setIsCreatingTag(false);\n setTagStartPoint(null);\n setCurrentTagText(\"\");\n }, []);\n\n const handleKeyDown = React.useCallback(\n (event: React.KeyboardEvent<HTMLDivElement>) => {\n if (isCreatingTag) {\n if (event.key === \"Enter\" || event.key === \" \") {\n event.preventDefault();\n completeTag();\n return;\n }\n\n if (event.key === \"Escape\") {\n event.preventDefault();\n cancelTag();\n return;\n }\n }\n\n if (enableTags && event.key === \"#\" && !isCreatingTag) {\n const { selection } = editor;\n if (selection && Range.isCollapsed(selection)) {\n setIsCreatingTag(true);\n setCurrentTagText(\"\");\n setTagStartPoint({\n path: selection.anchor.path,\n offset: selection.anchor.offset,\n });\n }\n }\n\n if (event.key === \"Enter\" && !event.shiftKey && !isCreatingTag) {\n event.preventDefault();\n const text = serializeToText(editorValue);\n if (text.trim() && onSubmit) {\n onSubmit(text.trim());\n }\n return;\n }\n\n if (\n (event.key === \"Backspace\" || event.key === \"Delete\") &&\n event.ctrlKey\n ) {\n const { selection } = editor;\n if (selection && Range.isCollapsed(selection)) {\n const direction =\n event.key === \"Backspace\" ? \"backward\" : \"forward\";\n const pointFn =\n direction === \"backward\" ? Editor.before : Editor.after;\n const point = pointFn(editor, selection, { unit: \"word\" });\n\n if (point) {\n const [tagEntry] = Editor.nodes(editor, {\n at:\n direction === \"backward\"\n ? { anchor: point, focus: selection.anchor }\n : { anchor: selection.anchor, focus: point },\n match: (n) =>\n !Editor.isEditor(n) &&\n SlateElement.isElement(n) &&\n n.type === \"tag\",\n });\n\n if (tagEntry) {\n event.preventDefault();\n const [tagNode, tagPath] = tagEntry;\n if (SlateElement.isElement(tagNode) && tagNode.type === \"tag\") {\n onTagDelete?.(tagNode.tag);\n }\n Transforms.removeNodes(editor, { at: tagPath });\n return;\n }\n }\n }\n }\n },\n [\n editor,\n editorValue,\n isCreatingTag,\n enableTags,\n completeTag,\n cancelTag,\n onSubmit,\n onTagDelete,\n ]\n );\n\n const renderElement = React.useCallback((props: RenderElementProps) => {\n switch (props.element.type) {\n case \"tag\":\n return (\n <TagElementRenderer\n {...props}\n element={props.element as TagElement}\n />\n );\n default:\n return <DefaultElement {...props} />;\n }\n }, []);\n\n const renderLeaf = React.useCallback((props: RenderLeafProps) => {\n return <Leaf {...props} />;\n }, []);\n\n const lineHeight = 24;\n const minHeight = lineHeight * minRows;\n const maxHeight = lineHeight * maxRows;\n\n return (\n <div\n className={cn(\n \"relative w-full rounded-md\",\n \"bg-transparent\",\n disabled && \"opacity-50 cursor-not-allowed\",\n className\n )}\n >\n <Slate\n editor={editor}\n initialValue={editorValue}\n onChange={handleChange}\n >\n <Editable\n readOnly={disabled}\n placeholder={placeholder}\n renderElement={renderElement}\n renderLeaf={renderLeaf}\n onKeyDown={handleKeyDown}\n className={cn(\n \"w-full outline-none\",\n \"text-foreground placeholder:text-muted-foreground\",\n \"leading-6\",\n \"overflow-y-auto overflow-x-hidden\",\n \"whitespace-pre-wrap break-words\"\n )}\n style={{\n minHeight: `${minHeight}px`,\n maxHeight: `${maxHeight}px`,\n wordBreak: \"break-word\",\n overflowWrap: \"break-word\",\n }}\n spellCheck\n autoCorrect=\"off\"\n autoCapitalize=\"off\"\n />\n </Slate>\n\n {isCreatingTag && (\n <div className=\"absolute bottom-full left-0 mb-2 flex items-center gap-2.5 animate-in fade-in-0 slide-in-from-bottom-1 duration-150\">\n <div className=\"flex items-center px-2 py-1 rounded-md border shadow-sm bg-accent/20 border-accent/40\">\n <span className=\"font-bold text-sm text-accent\">#</span>\n <span className=\"text-sm font-medium min-w-[2ch] text-accent\">\n {currentTagText || (\n <span className=\"opacity-50 italic\">tag</span>\n )}\n </span>\n </div>\n <span className=\"text-muted-foreground/80 text-[11px]\">\n <kbd className=\"px-1.5 py-0.5 bg-muted rounded text-[10px] font-mono mr-1\">\n Enter\n </kbd>\n or\n <kbd className=\"px-1.5 py-0.5 bg-muted rounded text-[10px] font-mono mx-1\">\n Space\n </kbd>\n to add\n <span className=\"mx-1.5 text-muted-foreground/50\">·</span>\n <kbd className=\"px-1.5 py-0.5 bg-muted rounded text-[10px] font-mono mr-1\">\n Esc\n </kbd>\n to cancel\n </span>\n </div>\n )}\n </div>\n );\n }\n);\n\nSlateEditor.displayName = \"SlateEditor\";\n"]}