@optilogic/editor 1.0.0-beta.0 → 1.0.0-beta.2

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 CHANGED
@@ -165,12 +165,15 @@ var SlateEditor = React__namespace.forwardRef(
165
165
  onTagCreate,
166
166
  onTagDelete,
167
167
  onSubmit,
168
+ clearOnSubmit = false,
168
169
  placeholder = "Type something...",
169
170
  disabled = false,
170
171
  enableTags = true,
171
172
  minRows = 3,
172
173
  maxRows = 8,
173
- className
174
+ className,
175
+ decorate,
176
+ renderLeaf: customRenderLeaf
174
177
  }, ref) => {
175
178
  const editor = React__namespace.useMemo(
176
179
  () => withTags(slateHistory.withHistory(slateReact.withReact(slate.createEditor()))),
@@ -182,16 +185,46 @@ var SlateEditor = React__namespace.forwardRef(
182
185
  const [editorValue, setEditorValue] = React__namespace.useState(
183
186
  () => deserializeFromText(value)
184
187
  );
188
+ const lastOnChangeValue = React__namespace.useRef(value);
189
+ const getEditableElement = React__namespace.useCallback(() => {
190
+ try {
191
+ return slateReact.ReactEditor.toDOMNode(editor, editor);
192
+ } catch {
193
+ return null;
194
+ }
195
+ }, [editor]);
196
+ const resetEditorContent = React__namespace.useCallback(
197
+ (newContent) => {
198
+ const el = getEditableElement();
199
+ const savedScroll = el ? { top: el.scrollTop, left: el.scrollLeft } : null;
200
+ slate.Editor.withoutNormalizing(editor, () => {
201
+ while (editor.children.length > 0) {
202
+ slate.Transforms.removeNodes(editor, { at: [0] });
203
+ }
204
+ slate.Transforms.insertNodes(editor, newContent, { at: [0] });
205
+ });
206
+ setEditorValue(newContent);
207
+ const point = { path: [0, 0], offset: 0 };
208
+ slate.Transforms.select(editor, { anchor: point, focus: point });
209
+ if (savedScroll && el) {
210
+ requestAnimationFrame(() => {
211
+ el.scrollTop = savedScroll.top;
212
+ el.scrollLeft = savedScroll.left;
213
+ });
214
+ }
215
+ },
216
+ [editor, getEditableElement]
217
+ );
185
218
  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, []));
219
+ if (value !== lastOnChangeValue.current) {
220
+ const currentText = serializeToText(editor.children);
221
+ if (currentText !== value) {
222
+ const newValue = deserializeFromText(value);
223
+ resetEditorContent(newValue);
224
+ }
225
+ lastOnChangeValue.current = value;
193
226
  }
194
- }, [value, editor]);
227
+ }, [value, editor, resetEditorContent]);
195
228
  React__namespace.useImperativeHandle(
196
229
  ref,
197
230
  () => ({
@@ -199,13 +232,13 @@ var SlateEditor = React__namespace.forwardRef(
199
232
  slateReact.ReactEditor.focus(editor);
200
233
  },
201
234
  clear: () => {
202
- const newValue = [
235
+ const emptyValue = [
203
236
  { type: "paragraph", children: [{ text: "" }] }
204
237
  ];
205
- setEditorValue(newValue);
206
- slate.Transforms.select(editor, slate.Editor.start(editor, []));
238
+ resetEditorContent(emptyValue);
239
+ onChange?.("");
207
240
  },
208
- getText: () => serializeToText(editorValue),
241
+ getText: () => serializeToText(editor.children),
209
242
  insertText: (text) => {
210
243
  slate.Transforms.insertText(editor, text);
211
244
  },
@@ -214,11 +247,10 @@ var SlateEditor = React__namespace.forwardRef(
214
247
  onTagCreate?.(tag);
215
248
  }
216
249
  }),
217
- [editor, editorValue, onTagCreate]
250
+ [editor, onTagCreate, resetEditorContent, onChange]
218
251
  );
219
252
  const handleChange = React__namespace.useCallback(
220
253
  (newValue) => {
221
- setEditorValue(newValue);
222
254
  if (isCreatingTag && tagStartPoint) {
223
255
  const { selection } = editor;
224
256
  if (selection && slate.Range.isCollapsed(selection)) {
@@ -269,6 +301,7 @@ var SlateEditor = React__namespace.forwardRef(
269
301
  }
270
302
  }
271
303
  const text = serializeToText(newValue);
304
+ lastOnChangeValue.current = text;
272
305
  onChange?.(text);
273
306
  },
274
307
  [editor, onChange, onTagDelete, isCreatingTag, tagStartPoint]
@@ -353,9 +386,29 @@ var SlateEditor = React__namespace.forwardRef(
353
386
  }
354
387
  if (event.key === "Enter" && !event.shiftKey && !isCreatingTag) {
355
388
  event.preventDefault();
356
- const text = serializeToText(editorValue);
389
+ const text = serializeToText(editor.children);
357
390
  if (text.trim() && onSubmit) {
358
391
  onSubmit(text.trim());
392
+ if (clearOnSubmit) {
393
+ const emptyValue = [
394
+ { type: "paragraph", children: [{ text: "" }] }
395
+ ];
396
+ resetEditorContent(emptyValue);
397
+ onChange?.("");
398
+ }
399
+ }
400
+ return;
401
+ }
402
+ if (event.key === "Enter" && event.shiftKey) {
403
+ event.preventDefault();
404
+ const el = getEditableElement();
405
+ const savedScrollTop = el?.scrollTop ?? 0;
406
+ slate.Transforms.insertText(editor, "\n");
407
+ if (el) {
408
+ el.scrollTop = savedScrollTop;
409
+ requestAnimationFrame(() => {
410
+ el.scrollTop = savedScrollTop;
411
+ });
359
412
  }
360
413
  return;
361
414
  }
@@ -385,13 +438,16 @@ var SlateEditor = React__namespace.forwardRef(
385
438
  },
386
439
  [
387
440
  editor,
388
- editorValue,
389
441
  isCreatingTag,
390
442
  enableTags,
391
443
  completeTag,
392
444
  cancelTag,
393
445
  onSubmit,
394
- onTagDelete
446
+ onTagDelete,
447
+ clearOnSubmit,
448
+ resetEditorContent,
449
+ onChange,
450
+ getEditableElement
395
451
  ]
396
452
  );
397
453
  const renderElement = React__namespace.useCallback((props) => {
@@ -408,9 +464,15 @@ var SlateEditor = React__namespace.forwardRef(
408
464
  return /* @__PURE__ */ jsxRuntime.jsx(DefaultElement, { ...props });
409
465
  }
410
466
  }, []);
411
- const renderLeaf = React__namespace.useCallback((props) => {
412
- return /* @__PURE__ */ jsxRuntime.jsx(Leaf, { ...props });
413
- }, []);
467
+ const renderLeaf = React__namespace.useCallback(
468
+ (props) => {
469
+ if (customRenderLeaf) {
470
+ return customRenderLeaf(props);
471
+ }
472
+ return /* @__PURE__ */ jsxRuntime.jsx(Leaf, { ...props });
473
+ },
474
+ [customRenderLeaf]
475
+ );
414
476
  const lineHeight = 24;
415
477
  const minHeight = lineHeight * minRows;
416
478
  const maxHeight = lineHeight * maxRows;
@@ -437,13 +499,15 @@ var SlateEditor = React__namespace.forwardRef(
437
499
  placeholder,
438
500
  renderElement,
439
501
  renderLeaf,
502
+ decorate,
440
503
  onKeyDown: handleKeyDown,
441
504
  className: core.cn(
442
505
  "w-full outline-none",
443
506
  "text-foreground placeholder:text-muted-foreground",
444
507
  "leading-6",
445
508
  "overflow-y-auto overflow-x-hidden",
446
- "whitespace-pre-wrap break-words"
509
+ "whitespace-pre-wrap break-words",
510
+ "scrollbar-thin"
447
511
  ),
448
512
  style: {
449
513
  minHeight: `${minHeight}px`,
@@ -480,6 +544,14 @@ var SlateEditor = React__namespace.forwardRef(
480
544
  );
481
545
  SlateEditor.displayName = "SlateEditor";
482
546
 
547
+ Object.defineProperty(exports, "Range", {
548
+ enumerable: true,
549
+ get: function () { return slate.Range; }
550
+ });
551
+ Object.defineProperty(exports, "Text", {
552
+ enumerable: true,
553
+ get: function () { return slate.Text; }
554
+ });
483
555
  exports.SlateEditor = SlateEditor;
484
556
  exports.deserializeFromText = deserializeFromText;
485
557
  exports.serializeToText = serializeToText;
@@ -1 +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"]}
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 type { NodeEntry } from \"slate\";\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; [key: string]: unknown };\n\nexport type DecoratedRange = Range & { [key: string]: unknown };\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 /** Automatically clear the editor after onSubmit is called */\n clearOnSubmit?: boolean;\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 /** Custom decoration function for text ranges */\n decorate?: (entry: NodeEntry) => DecoratedRange[];\n /** Custom leaf renderer for decorated text */\n renderLeaf?: (props: RenderLeafProps) => React.ReactElement;\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 clearOnSubmit = false,\n placeholder = \"Type something...\",\n disabled = false,\n enableTags = true,\n minRows = 3,\n maxRows = 8,\n className,\n decorate,\n renderLeaf: customRenderLeaf,\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 // Track the last value we sent via onChange to distinguish user input from external prop changes\n const lastOnChangeValue = React.useRef<string>(value);\n\n // Get the editable DOM element from the editor\n const getEditableElement = React.useCallback(() => {\n try {\n return ReactEditor.toDOMNode(editor, editor) as HTMLElement;\n } catch {\n return null;\n }\n }, [editor]);\n\n const resetEditorContent = React.useCallback(\n (newContent: Descendant[]) => {\n // Save scroll position before resetting content\n const el = getEditableElement();\n const savedScroll = el\n ? { top: el.scrollTop, left: el.scrollLeft }\n : null;\n\n Editor.withoutNormalizing(editor, () => {\n // Remove all existing nodes\n while (editor.children.length > 0) {\n Transforms.removeNodes(editor, { at: [0] });\n }\n // Insert new content\n Transforms.insertNodes(editor, newContent, { at: [0] });\n });\n\n setEditorValue(newContent);\n\n // Set selection to start safely\n const point = { path: [0, 0], offset: 0 };\n Transforms.select(editor, { anchor: point, focus: point });\n\n // Restore scroll position after content reset (use requestAnimationFrame to ensure DOM is updated)\n if (savedScroll && el) {\n requestAnimationFrame(() => {\n el.scrollTop = savedScroll.top;\n el.scrollLeft = savedScroll.left;\n });\n }\n },\n [editor, getEditableElement]\n );\n\n React.useEffect(() => {\n // Only reset content if value changed externally (not from our own onChange)\n // This prevents scroll position reset during user typing\n if (value !== lastOnChangeValue.current) {\n const currentText = serializeToText(editor.children as Descendant[]);\n if (currentText !== value) {\n const newValue = deserializeFromText(value);\n resetEditorContent(newValue);\n }\n lastOnChangeValue.current = value;\n }\n }, [value, editor, resetEditorContent]);\n\n React.useImperativeHandle(\n ref,\n () => ({\n focus: () => {\n ReactEditor.focus(editor);\n },\n clear: () => {\n const emptyValue: Descendant[] = [\n { type: \"paragraph\", children: [{ text: \"\" }] },\n ];\n resetEditorContent(emptyValue);\n onChange?.(\"\");\n },\n getText: () => serializeToText(editor.children as Descendant[]),\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, onTagCreate, resetEditorContent, onChange]\n );\n\n const handleChange = React.useCallback(\n (newValue: Descendant[]) => {\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 lastOnChangeValue.current = text;\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(editor.children as Descendant[]);\n if (text.trim() && onSubmit) {\n onSubmit(text.trim());\n if (clearOnSubmit) {\n const emptyValue: Descendant[] = [\n { type: \"paragraph\", children: [{ text: \"\" }] },\n ];\n resetEditorContent(emptyValue);\n onChange?.(\"\");\n }\n }\n return;\n }\n\n // Shift+Enter: Insert soft line break (newline character) instead of new paragraph\n if (event.key === \"Enter\" && event.shiftKey) {\n event.preventDefault();\n const el = getEditableElement();\n const savedScrollTop = el?.scrollTop ?? 0;\n\n Transforms.insertText(editor, \"\\n\");\n\n // Restore scroll position immediately and after paint to prevent jump\n if (el) {\n el.scrollTop = savedScrollTop;\n requestAnimationFrame(() => {\n el.scrollTop = savedScrollTop;\n });\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 isCreatingTag,\n enableTags,\n completeTag,\n cancelTag,\n onSubmit,\n onTagDelete,\n clearOnSubmit,\n resetEditorContent,\n onChange,\n getEditableElement,\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(\n (props: RenderLeafProps) => {\n if (customRenderLeaf) {\n return customRenderLeaf(props);\n }\n return <Leaf {...props} />;\n },\n [customRenderLeaf]\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 decorate={decorate}\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 \"scrollbar-thin\"\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"]}
package/dist/index.d.cts CHANGED
@@ -1,6 +1,8 @@
1
1
  import * as React from 'react';
2
- import { BaseEditor, Descendant } from 'slate';
3
- import { ReactEditor } from 'slate-react';
2
+ import { BaseEditor, Descendant, NodeEntry, Range } from 'slate';
3
+ export { NodeEntry, Range, Text } from 'slate';
4
+ import { ReactEditor, RenderLeafProps } from 'slate-react';
5
+ export { RenderLeafProps } from 'slate-react';
4
6
  import { HistoryEditor } from 'slate-history';
5
7
 
6
8
  /**
@@ -24,6 +26,10 @@ type ParagraphElement = {
24
26
  type CustomElement = TagElement | ParagraphElement;
25
27
  type CustomText = {
26
28
  text: string;
29
+ [key: string]: unknown;
30
+ };
31
+ type DecoratedRange = Range & {
32
+ [key: string]: unknown;
27
33
  };
28
34
  declare module "slate" {
29
35
  interface CustomTypes {
@@ -55,6 +61,8 @@ interface SlateEditorProps {
55
61
  onTagDelete?: (tag: string) => void;
56
62
  /** Callback when Enter is pressed (without Shift) */
57
63
  onSubmit?: (text: string) => void;
64
+ /** Automatically clear the editor after onSubmit is called */
65
+ clearOnSubmit?: boolean;
58
66
  /** Placeholder text */
59
67
  placeholder?: string;
60
68
  /** Whether the editor is disabled */
@@ -67,6 +75,10 @@ interface SlateEditorProps {
67
75
  maxRows?: number;
68
76
  /** Additional class names */
69
77
  className?: string;
78
+ /** Custom decoration function for text ranges */
79
+ decorate?: (entry: NodeEntry) => DecoratedRange[];
80
+ /** Custom leaf renderer for decorated text */
81
+ renderLeaf?: (props: RenderLeafProps) => React.ReactElement;
70
82
  }
71
83
  /**
72
84
  * Convert Slate content to plain text
@@ -92,4 +104,4 @@ declare function deserializeFromText(text: string): Descendant[];
92
104
  */
93
105
  declare const SlateEditor: React.ForwardRefExoticComponent<SlateEditorProps & React.RefAttributes<SlateEditorRef>>;
94
106
 
95
- export { SlateEditor, type SlateEditorProps, type SlateEditorRef, deserializeFromText, serializeToText };
107
+ export { type DecoratedRange, SlateEditor, type SlateEditorProps, type SlateEditorRef, deserializeFromText, serializeToText };
package/dist/index.d.ts CHANGED
@@ -1,6 +1,8 @@
1
1
  import * as React from 'react';
2
- import { BaseEditor, Descendant } from 'slate';
3
- import { ReactEditor } from 'slate-react';
2
+ import { BaseEditor, Descendant, NodeEntry, Range } from 'slate';
3
+ export { NodeEntry, Range, Text } from 'slate';
4
+ import { ReactEditor, RenderLeafProps } from 'slate-react';
5
+ export { RenderLeafProps } from 'slate-react';
4
6
  import { HistoryEditor } from 'slate-history';
5
7
 
6
8
  /**
@@ -24,6 +26,10 @@ type ParagraphElement = {
24
26
  type CustomElement = TagElement | ParagraphElement;
25
27
  type CustomText = {
26
28
  text: string;
29
+ [key: string]: unknown;
30
+ };
31
+ type DecoratedRange = Range & {
32
+ [key: string]: unknown;
27
33
  };
28
34
  declare module "slate" {
29
35
  interface CustomTypes {
@@ -55,6 +61,8 @@ interface SlateEditorProps {
55
61
  onTagDelete?: (tag: string) => void;
56
62
  /** Callback when Enter is pressed (without Shift) */
57
63
  onSubmit?: (text: string) => void;
64
+ /** Automatically clear the editor after onSubmit is called */
65
+ clearOnSubmit?: boolean;
58
66
  /** Placeholder text */
59
67
  placeholder?: string;
60
68
  /** Whether the editor is disabled */
@@ -67,6 +75,10 @@ interface SlateEditorProps {
67
75
  maxRows?: number;
68
76
  /** Additional class names */
69
77
  className?: string;
78
+ /** Custom decoration function for text ranges */
79
+ decorate?: (entry: NodeEntry) => DecoratedRange[];
80
+ /** Custom leaf renderer for decorated text */
81
+ renderLeaf?: (props: RenderLeafProps) => React.ReactElement;
70
82
  }
71
83
  /**
72
84
  * Convert Slate content to plain text
@@ -92,4 +104,4 @@ declare function deserializeFromText(text: string): Descendant[];
92
104
  */
93
105
  declare const SlateEditor: React.ForwardRefExoticComponent<SlateEditorProps & React.RefAttributes<SlateEditorRef>>;
94
106
 
95
- export { SlateEditor, type SlateEditorProps, type SlateEditorRef, deserializeFromText, serializeToText };
107
+ export { type DecoratedRange, SlateEditor, type SlateEditorProps, type SlateEditorRef, deserializeFromText, serializeToText };
package/dist/index.js CHANGED
@@ -1,5 +1,6 @@
1
1
  import * as React from 'react';
2
- import { createEditor, Transforms, Editor, Range, Path, Text, Node, Element } from 'slate';
2
+ import { createEditor, Editor, Transforms, Range, Path, Text, Node, Element } from 'slate';
3
+ export { Range, Text } from 'slate';
3
4
  import { withReact, ReactEditor, Slate, Editable } from 'slate-react';
4
5
  import { withHistory } from 'slate-history';
5
6
  import { cn } from '@optilogic/core';
@@ -143,12 +144,15 @@ var SlateEditor = React.forwardRef(
143
144
  onTagCreate,
144
145
  onTagDelete,
145
146
  onSubmit,
147
+ clearOnSubmit = false,
146
148
  placeholder = "Type something...",
147
149
  disabled = false,
148
150
  enableTags = true,
149
151
  minRows = 3,
150
152
  maxRows = 8,
151
- className
153
+ className,
154
+ decorate,
155
+ renderLeaf: customRenderLeaf
152
156
  }, ref) => {
153
157
  const editor = React.useMemo(
154
158
  () => withTags(withHistory(withReact(createEditor()))),
@@ -160,16 +164,46 @@ var SlateEditor = React.forwardRef(
160
164
  const [editorValue, setEditorValue] = React.useState(
161
165
  () => deserializeFromText(value)
162
166
  );
167
+ const lastOnChangeValue = React.useRef(value);
168
+ const getEditableElement = React.useCallback(() => {
169
+ try {
170
+ return ReactEditor.toDOMNode(editor, editor);
171
+ } catch {
172
+ return null;
173
+ }
174
+ }, [editor]);
175
+ const resetEditorContent = React.useCallback(
176
+ (newContent) => {
177
+ const el = getEditableElement();
178
+ const savedScroll = el ? { top: el.scrollTop, left: el.scrollLeft } : null;
179
+ Editor.withoutNormalizing(editor, () => {
180
+ while (editor.children.length > 0) {
181
+ Transforms.removeNodes(editor, { at: [0] });
182
+ }
183
+ Transforms.insertNodes(editor, newContent, { at: [0] });
184
+ });
185
+ setEditorValue(newContent);
186
+ const point = { path: [0, 0], offset: 0 };
187
+ Transforms.select(editor, { anchor: point, focus: point });
188
+ if (savedScroll && el) {
189
+ requestAnimationFrame(() => {
190
+ el.scrollTop = savedScroll.top;
191
+ el.scrollLeft = savedScroll.left;
192
+ });
193
+ }
194
+ },
195
+ [editor, getEditableElement]
196
+ );
163
197
  React.useEffect(() => {
164
- const newValue = deserializeFromText(value);
165
- const currentText = serializeToText(editorValue);
166
- if (currentText !== value) {
167
- setEditorValue(newValue);
168
- Transforms.removeNodes(editor, { at: [] });
169
- Transforms.insertNodes(editor, newValue, { at: [0] });
170
- Transforms.select(editor, Editor.start(editor, []));
198
+ if (value !== lastOnChangeValue.current) {
199
+ const currentText = serializeToText(editor.children);
200
+ if (currentText !== value) {
201
+ const newValue = deserializeFromText(value);
202
+ resetEditorContent(newValue);
203
+ }
204
+ lastOnChangeValue.current = value;
171
205
  }
172
- }, [value, editor]);
206
+ }, [value, editor, resetEditorContent]);
173
207
  React.useImperativeHandle(
174
208
  ref,
175
209
  () => ({
@@ -177,13 +211,13 @@ var SlateEditor = React.forwardRef(
177
211
  ReactEditor.focus(editor);
178
212
  },
179
213
  clear: () => {
180
- const newValue = [
214
+ const emptyValue = [
181
215
  { type: "paragraph", children: [{ text: "" }] }
182
216
  ];
183
- setEditorValue(newValue);
184
- Transforms.select(editor, Editor.start(editor, []));
217
+ resetEditorContent(emptyValue);
218
+ onChange?.("");
185
219
  },
186
- getText: () => serializeToText(editorValue),
220
+ getText: () => serializeToText(editor.children),
187
221
  insertText: (text) => {
188
222
  Transforms.insertText(editor, text);
189
223
  },
@@ -192,11 +226,10 @@ var SlateEditor = React.forwardRef(
192
226
  onTagCreate?.(tag);
193
227
  }
194
228
  }),
195
- [editor, editorValue, onTagCreate]
229
+ [editor, onTagCreate, resetEditorContent, onChange]
196
230
  );
197
231
  const handleChange = React.useCallback(
198
232
  (newValue) => {
199
- setEditorValue(newValue);
200
233
  if (isCreatingTag && tagStartPoint) {
201
234
  const { selection } = editor;
202
235
  if (selection && Range.isCollapsed(selection)) {
@@ -247,6 +280,7 @@ var SlateEditor = React.forwardRef(
247
280
  }
248
281
  }
249
282
  const text = serializeToText(newValue);
283
+ lastOnChangeValue.current = text;
250
284
  onChange?.(text);
251
285
  },
252
286
  [editor, onChange, onTagDelete, isCreatingTag, tagStartPoint]
@@ -331,9 +365,29 @@ var SlateEditor = React.forwardRef(
331
365
  }
332
366
  if (event.key === "Enter" && !event.shiftKey && !isCreatingTag) {
333
367
  event.preventDefault();
334
- const text = serializeToText(editorValue);
368
+ const text = serializeToText(editor.children);
335
369
  if (text.trim() && onSubmit) {
336
370
  onSubmit(text.trim());
371
+ if (clearOnSubmit) {
372
+ const emptyValue = [
373
+ { type: "paragraph", children: [{ text: "" }] }
374
+ ];
375
+ resetEditorContent(emptyValue);
376
+ onChange?.("");
377
+ }
378
+ }
379
+ return;
380
+ }
381
+ if (event.key === "Enter" && event.shiftKey) {
382
+ event.preventDefault();
383
+ const el = getEditableElement();
384
+ const savedScrollTop = el?.scrollTop ?? 0;
385
+ Transforms.insertText(editor, "\n");
386
+ if (el) {
387
+ el.scrollTop = savedScrollTop;
388
+ requestAnimationFrame(() => {
389
+ el.scrollTop = savedScrollTop;
390
+ });
337
391
  }
338
392
  return;
339
393
  }
@@ -363,13 +417,16 @@ var SlateEditor = React.forwardRef(
363
417
  },
364
418
  [
365
419
  editor,
366
- editorValue,
367
420
  isCreatingTag,
368
421
  enableTags,
369
422
  completeTag,
370
423
  cancelTag,
371
424
  onSubmit,
372
- onTagDelete
425
+ onTagDelete,
426
+ clearOnSubmit,
427
+ resetEditorContent,
428
+ onChange,
429
+ getEditableElement
373
430
  ]
374
431
  );
375
432
  const renderElement = React.useCallback((props) => {
@@ -386,9 +443,15 @@ var SlateEditor = React.forwardRef(
386
443
  return /* @__PURE__ */ jsx(DefaultElement, { ...props });
387
444
  }
388
445
  }, []);
389
- const renderLeaf = React.useCallback((props) => {
390
- return /* @__PURE__ */ jsx(Leaf, { ...props });
391
- }, []);
446
+ const renderLeaf = React.useCallback(
447
+ (props) => {
448
+ if (customRenderLeaf) {
449
+ return customRenderLeaf(props);
450
+ }
451
+ return /* @__PURE__ */ jsx(Leaf, { ...props });
452
+ },
453
+ [customRenderLeaf]
454
+ );
392
455
  const lineHeight = 24;
393
456
  const minHeight = lineHeight * minRows;
394
457
  const maxHeight = lineHeight * maxRows;
@@ -415,13 +478,15 @@ var SlateEditor = React.forwardRef(
415
478
  placeholder,
416
479
  renderElement,
417
480
  renderLeaf,
481
+ decorate,
418
482
  onKeyDown: handleKeyDown,
419
483
  className: cn(
420
484
  "w-full outline-none",
421
485
  "text-foreground placeholder:text-muted-foreground",
422
486
  "leading-6",
423
487
  "overflow-y-auto overflow-x-hidden",
424
- "whitespace-pre-wrap break-words"
488
+ "whitespace-pre-wrap break-words",
489
+ "scrollbar-thin"
425
490
  ),
426
491
  style: {
427
492
  minHeight: `${minHeight}px`,
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/slate-editor.tsx"],"names":["SlateElement","editor"],"mappings":"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","file":"index.js","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"]}
1
+ {"version":3,"sources":["../src/slate-editor.tsx"],"names":["SlateElement","editor"],"mappings":"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","file":"index.js","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 type { NodeEntry } from \"slate\";\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; [key: string]: unknown };\n\nexport type DecoratedRange = Range & { [key: string]: unknown };\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 /** Automatically clear the editor after onSubmit is called */\n clearOnSubmit?: boolean;\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 /** Custom decoration function for text ranges */\n decorate?: (entry: NodeEntry) => DecoratedRange[];\n /** Custom leaf renderer for decorated text */\n renderLeaf?: (props: RenderLeafProps) => React.ReactElement;\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 clearOnSubmit = false,\n placeholder = \"Type something...\",\n disabled = false,\n enableTags = true,\n minRows = 3,\n maxRows = 8,\n className,\n decorate,\n renderLeaf: customRenderLeaf,\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 // Track the last value we sent via onChange to distinguish user input from external prop changes\n const lastOnChangeValue = React.useRef<string>(value);\n\n // Get the editable DOM element from the editor\n const getEditableElement = React.useCallback(() => {\n try {\n return ReactEditor.toDOMNode(editor, editor) as HTMLElement;\n } catch {\n return null;\n }\n }, [editor]);\n\n const resetEditorContent = React.useCallback(\n (newContent: Descendant[]) => {\n // Save scroll position before resetting content\n const el = getEditableElement();\n const savedScroll = el\n ? { top: el.scrollTop, left: el.scrollLeft }\n : null;\n\n Editor.withoutNormalizing(editor, () => {\n // Remove all existing nodes\n while (editor.children.length > 0) {\n Transforms.removeNodes(editor, { at: [0] });\n }\n // Insert new content\n Transforms.insertNodes(editor, newContent, { at: [0] });\n });\n\n setEditorValue(newContent);\n\n // Set selection to start safely\n const point = { path: [0, 0], offset: 0 };\n Transforms.select(editor, { anchor: point, focus: point });\n\n // Restore scroll position after content reset (use requestAnimationFrame to ensure DOM is updated)\n if (savedScroll && el) {\n requestAnimationFrame(() => {\n el.scrollTop = savedScroll.top;\n el.scrollLeft = savedScroll.left;\n });\n }\n },\n [editor, getEditableElement]\n );\n\n React.useEffect(() => {\n // Only reset content if value changed externally (not from our own onChange)\n // This prevents scroll position reset during user typing\n if (value !== lastOnChangeValue.current) {\n const currentText = serializeToText(editor.children as Descendant[]);\n if (currentText !== value) {\n const newValue = deserializeFromText(value);\n resetEditorContent(newValue);\n }\n lastOnChangeValue.current = value;\n }\n }, [value, editor, resetEditorContent]);\n\n React.useImperativeHandle(\n ref,\n () => ({\n focus: () => {\n ReactEditor.focus(editor);\n },\n clear: () => {\n const emptyValue: Descendant[] = [\n { type: \"paragraph\", children: [{ text: \"\" }] },\n ];\n resetEditorContent(emptyValue);\n onChange?.(\"\");\n },\n getText: () => serializeToText(editor.children as Descendant[]),\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, onTagCreate, resetEditorContent, onChange]\n );\n\n const handleChange = React.useCallback(\n (newValue: Descendant[]) => {\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 lastOnChangeValue.current = text;\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(editor.children as Descendant[]);\n if (text.trim() && onSubmit) {\n onSubmit(text.trim());\n if (clearOnSubmit) {\n const emptyValue: Descendant[] = [\n { type: \"paragraph\", children: [{ text: \"\" }] },\n ];\n resetEditorContent(emptyValue);\n onChange?.(\"\");\n }\n }\n return;\n }\n\n // Shift+Enter: Insert soft line break (newline character) instead of new paragraph\n if (event.key === \"Enter\" && event.shiftKey) {\n event.preventDefault();\n const el = getEditableElement();\n const savedScrollTop = el?.scrollTop ?? 0;\n\n Transforms.insertText(editor, \"\\n\");\n\n // Restore scroll position immediately and after paint to prevent jump\n if (el) {\n el.scrollTop = savedScrollTop;\n requestAnimationFrame(() => {\n el.scrollTop = savedScrollTop;\n });\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 isCreatingTag,\n enableTags,\n completeTag,\n cancelTag,\n onSubmit,\n onTagDelete,\n clearOnSubmit,\n resetEditorContent,\n onChange,\n getEditableElement,\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(\n (props: RenderLeafProps) => {\n if (customRenderLeaf) {\n return customRenderLeaf(props);\n }\n return <Leaf {...props} />;\n },\n [customRenderLeaf]\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 decorate={decorate}\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 \"scrollbar-thin\"\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"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@optilogic/editor",
3
- "version": "1.0.0-beta.0",
3
+ "version": "1.0.0-beta.2",
4
4
  "description": "Rich text editor component for Optilogic - SlateEditor built on Slate.js",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -24,7 +24,7 @@
24
24
  "README.md"
25
25
  ],
26
26
  "dependencies": {
27
- "@optilogic/core": "1.0.0-beta.0"
27
+ "@optilogic/core": "1.0.0-beta.2"
28
28
  },
29
29
  "peerDependencies": {
30
30
  "react": "^18.0.0 || ^19.0.0",
package/src/index.ts CHANGED
@@ -4,4 +4,10 @@ export {
4
4
  deserializeFromText,
5
5
  type SlateEditorProps,
6
6
  type SlateEditorRef,
7
+ type DecoratedRange,
7
8
  } from "./slate-editor";
9
+
10
+ // Re-export Slate types and utilities for convenience
11
+ export { Text, Range } from "slate";
12
+ export type { NodeEntry } from "slate";
13
+ export type { RenderLeafProps } from "slate-react";
@@ -26,6 +26,7 @@ import {
26
26
  RenderElementProps,
27
27
  RenderLeafProps,
28
28
  } from "slate-react";
29
+ import type { NodeEntry } from "slate";
29
30
  import { withHistory, HistoryEditor } from "slate-history";
30
31
  import { cn } from "@optilogic/core";
31
32
 
@@ -41,7 +42,9 @@ type ParagraphElement = {
41
42
  };
42
43
 
43
44
  type CustomElement = TagElement | ParagraphElement;
44
- type CustomText = { text: string };
45
+ type CustomText = { text: string; [key: string]: unknown };
46
+
47
+ export type DecoratedRange = Range & { [key: string]: unknown };
45
48
 
46
49
  declare module "slate" {
47
50
  interface CustomTypes {
@@ -79,6 +82,8 @@ export interface SlateEditorProps {
79
82
  onTagDelete?: (tag: string) => void;
80
83
  /** Callback when Enter is pressed (without Shift) */
81
84
  onSubmit?: (text: string) => void;
85
+ /** Automatically clear the editor after onSubmit is called */
86
+ clearOnSubmit?: boolean;
82
87
  /** Placeholder text */
83
88
  placeholder?: string;
84
89
  /** Whether the editor is disabled */
@@ -91,6 +96,10 @@ export interface SlateEditorProps {
91
96
  maxRows?: number;
92
97
  /** Additional class names */
93
98
  className?: string;
99
+ /** Custom decoration function for text ranges */
100
+ decorate?: (entry: NodeEntry) => DecoratedRange[];
101
+ /** Custom leaf renderer for decorated text */
102
+ renderLeaf?: (props: RenderLeafProps) => React.ReactElement;
94
103
  }
95
104
 
96
105
  const withTags = (editor: Editor) => {
@@ -284,12 +293,15 @@ export const SlateEditor = React.forwardRef<SlateEditorRef, SlateEditorProps>(
284
293
  onTagCreate,
285
294
  onTagDelete,
286
295
  onSubmit,
296
+ clearOnSubmit = false,
287
297
  placeholder = "Type something...",
288
298
  disabled = false,
289
299
  enableTags = true,
290
300
  minRows = 3,
291
301
  maxRows = 8,
292
302
  className,
303
+ decorate,
304
+ renderLeaf: customRenderLeaf,
293
305
  },
294
306
  ref
295
307
  ) => {
@@ -309,16 +321,64 @@ export const SlateEditor = React.forwardRef<SlateEditorRef, SlateEditorProps>(
309
321
  deserializeFromText(value)
310
322
  );
311
323
 
324
+ // Track the last value we sent via onChange to distinguish user input from external prop changes
325
+ const lastOnChangeValue = React.useRef<string>(value);
326
+
327
+ // Get the editable DOM element from the editor
328
+ const getEditableElement = React.useCallback(() => {
329
+ try {
330
+ return ReactEditor.toDOMNode(editor, editor) as HTMLElement;
331
+ } catch {
332
+ return null;
333
+ }
334
+ }, [editor]);
335
+
336
+ const resetEditorContent = React.useCallback(
337
+ (newContent: Descendant[]) => {
338
+ // Save scroll position before resetting content
339
+ const el = getEditableElement();
340
+ const savedScroll = el
341
+ ? { top: el.scrollTop, left: el.scrollLeft }
342
+ : null;
343
+
344
+ Editor.withoutNormalizing(editor, () => {
345
+ // Remove all existing nodes
346
+ while (editor.children.length > 0) {
347
+ Transforms.removeNodes(editor, { at: [0] });
348
+ }
349
+ // Insert new content
350
+ Transforms.insertNodes(editor, newContent, { at: [0] });
351
+ });
352
+
353
+ setEditorValue(newContent);
354
+
355
+ // Set selection to start safely
356
+ const point = { path: [0, 0], offset: 0 };
357
+ Transforms.select(editor, { anchor: point, focus: point });
358
+
359
+ // Restore scroll position after content reset (use requestAnimationFrame to ensure DOM is updated)
360
+ if (savedScroll && el) {
361
+ requestAnimationFrame(() => {
362
+ el.scrollTop = savedScroll.top;
363
+ el.scrollLeft = savedScroll.left;
364
+ });
365
+ }
366
+ },
367
+ [editor, getEditableElement]
368
+ );
369
+
312
370
  React.useEffect(() => {
313
- const newValue = deserializeFromText(value);
314
- const currentText = serializeToText(editorValue);
315
- if (currentText !== value) {
316
- setEditorValue(newValue);
317
- Transforms.removeNodes(editor, { at: [] });
318
- Transforms.insertNodes(editor, newValue, { at: [0] });
319
- Transforms.select(editor, Editor.start(editor, []));
371
+ // Only reset content if value changed externally (not from our own onChange)
372
+ // This prevents scroll position reset during user typing
373
+ if (value !== lastOnChangeValue.current) {
374
+ const currentText = serializeToText(editor.children as Descendant[]);
375
+ if (currentText !== value) {
376
+ const newValue = deserializeFromText(value);
377
+ resetEditorContent(newValue);
378
+ }
379
+ lastOnChangeValue.current = value;
320
380
  }
321
- }, [value, editor]);
381
+ }, [value, editor, resetEditorContent]);
322
382
 
323
383
  React.useImperativeHandle(
324
384
  ref,
@@ -327,13 +387,13 @@ export const SlateEditor = React.forwardRef<SlateEditorRef, SlateEditorProps>(
327
387
  ReactEditor.focus(editor);
328
388
  },
329
389
  clear: () => {
330
- const newValue: Descendant[] = [
390
+ const emptyValue: Descendant[] = [
331
391
  { type: "paragraph", children: [{ text: "" }] },
332
392
  ];
333
- setEditorValue(newValue);
334
- Transforms.select(editor, Editor.start(editor, []));
393
+ resetEditorContent(emptyValue);
394
+ onChange?.("");
335
395
  },
336
- getText: () => serializeToText(editorValue),
396
+ getText: () => serializeToText(editor.children as Descendant[]),
337
397
  insertText: (text: string) => {
338
398
  Transforms.insertText(editor, text);
339
399
  },
@@ -342,13 +402,11 @@ export const SlateEditor = React.forwardRef<SlateEditorRef, SlateEditorProps>(
342
402
  onTagCreate?.(tag);
343
403
  },
344
404
  }),
345
- [editor, editorValue, onTagCreate]
405
+ [editor, onTagCreate, resetEditorContent, onChange]
346
406
  );
347
407
 
348
408
  const handleChange = React.useCallback(
349
409
  (newValue: Descendant[]) => {
350
- setEditorValue(newValue);
351
-
352
410
  if (isCreatingTag && tagStartPoint) {
353
411
  const { selection } = editor;
354
412
  if (selection && Range.isCollapsed(selection)) {
@@ -406,6 +464,7 @@ export const SlateEditor = React.forwardRef<SlateEditorRef, SlateEditorProps>(
406
464
  }
407
465
 
408
466
  const text = serializeToText(newValue);
467
+ lastOnChangeValue.current = text;
409
468
  onChange?.(text);
410
469
  },
411
470
  [editor, onChange, onTagDelete, isCreatingTag, tagStartPoint]
@@ -507,9 +566,34 @@ export const SlateEditor = React.forwardRef<SlateEditorRef, SlateEditorProps>(
507
566
 
508
567
  if (event.key === "Enter" && !event.shiftKey && !isCreatingTag) {
509
568
  event.preventDefault();
510
- const text = serializeToText(editorValue);
569
+ const text = serializeToText(editor.children as Descendant[]);
511
570
  if (text.trim() && onSubmit) {
512
571
  onSubmit(text.trim());
572
+ if (clearOnSubmit) {
573
+ const emptyValue: Descendant[] = [
574
+ { type: "paragraph", children: [{ text: "" }] },
575
+ ];
576
+ resetEditorContent(emptyValue);
577
+ onChange?.("");
578
+ }
579
+ }
580
+ return;
581
+ }
582
+
583
+ // Shift+Enter: Insert soft line break (newline character) instead of new paragraph
584
+ if (event.key === "Enter" && event.shiftKey) {
585
+ event.preventDefault();
586
+ const el = getEditableElement();
587
+ const savedScrollTop = el?.scrollTop ?? 0;
588
+
589
+ Transforms.insertText(editor, "\n");
590
+
591
+ // Restore scroll position immediately and after paint to prevent jump
592
+ if (el) {
593
+ el.scrollTop = savedScrollTop;
594
+ requestAnimationFrame(() => {
595
+ el.scrollTop = savedScrollTop;
596
+ });
513
597
  }
514
598
  return;
515
599
  }
@@ -553,13 +637,16 @@ export const SlateEditor = React.forwardRef<SlateEditorRef, SlateEditorProps>(
553
637
  },
554
638
  [
555
639
  editor,
556
- editorValue,
557
640
  isCreatingTag,
558
641
  enableTags,
559
642
  completeTag,
560
643
  cancelTag,
561
644
  onSubmit,
562
645
  onTagDelete,
646
+ clearOnSubmit,
647
+ resetEditorContent,
648
+ onChange,
649
+ getEditableElement,
563
650
  ]
564
651
  );
565
652
 
@@ -577,9 +664,15 @@ export const SlateEditor = React.forwardRef<SlateEditorRef, SlateEditorProps>(
577
664
  }
578
665
  }, []);
579
666
 
580
- const renderLeaf = React.useCallback((props: RenderLeafProps) => {
581
- return <Leaf {...props} />;
582
- }, []);
667
+ const renderLeaf = React.useCallback(
668
+ (props: RenderLeafProps) => {
669
+ if (customRenderLeaf) {
670
+ return customRenderLeaf(props);
671
+ }
672
+ return <Leaf {...props} />;
673
+ },
674
+ [customRenderLeaf]
675
+ );
583
676
 
584
677
  const lineHeight = 24;
585
678
  const minHeight = lineHeight * minRows;
@@ -604,13 +697,15 @@ export const SlateEditor = React.forwardRef<SlateEditorRef, SlateEditorProps>(
604
697
  placeholder={placeholder}
605
698
  renderElement={renderElement}
606
699
  renderLeaf={renderLeaf}
700
+ decorate={decorate}
607
701
  onKeyDown={handleKeyDown}
608
702
  className={cn(
609
703
  "w-full outline-none",
610
704
  "text-foreground placeholder:text-muted-foreground",
611
705
  "leading-6",
612
706
  "overflow-y-auto overflow-x-hidden",
613
- "whitespace-pre-wrap break-words"
707
+ "whitespace-pre-wrap break-words",
708
+ "scrollbar-thin"
614
709
  )}
615
710
  style={{
616
711
  minHeight: `${minHeight}px`,