@firecms/editor 3.0.0-canary.8 → 3.0.0-canary.80
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +113 -21
- package/dist/components/editor-command-item.d.ts +4 -5
- package/dist/components/editor-command.d.ts +8 -9
- package/dist/components/editor.d.ts +4 -12
- package/dist/extensions/_image-resizer.d.ts +0 -1
- package/dist/index.es.js +10 -19
- package/dist/index.es.js.map +1 -1
- package/dist/index.umd.js +1 -1
- package/dist/index.umd.js.map +1 -1
- package/dist/utils/utils.d.ts +1 -1
- package/package.json +29 -29
package/dist/index.umd.js.map
CHANGED
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"index.umd.js","sources":["../src/components/editor.tsx","../src/components/editor-bubble.tsx","../src/components/editor-bubble-item.tsx","../src/components/editor-command.tsx","../src/components/editor-command-item.tsx","../src/extensions/slash-command.tsx","../src/extensions/index.ts","../src/selectors/node-selector.tsx","../src/selectors/link-selector.tsx","../src/selectors/text-buttons.tsx","../src/utils/useDebouncedCallback.ts","../src/utils/remove_classes.ts","../src/editor_extensions.tsx","../src/extensions/Image.ts","../src/extensions/custom-keymap.ts","../src/extensions/drag-and-drop.tsx","../src/editor.tsx"],"sourcesContent":["import { type ReactNode } from \"react\";\nimport { createStore, Provider } from \"jotai\";\n\nexport const editorStore = createStore();\n\nexport const EditorRoot = ({ children }: { children: ReactNode }): JSX.Element => {\n return <Provider store={editorStore}>{children}</Provider>;\n};\n","import { BubbleMenu, type BubbleMenuProps, isNodeSelection, useCurrentEditor } from \"@tiptap/react\";\nimport { type ReactNode, useMemo, useRef, useEffect, forwardRef } from \"react\";\nimport type { Instance, Props } from \"tippy.js\";\n\nexport interface EditorBubbleProps extends Omit<BubbleMenuProps, \"editor\"> {\n children: ReactNode;\n}\n\nexport const EditorBubble = forwardRef<HTMLDivElement, EditorBubbleProps>(\n ({ children, tippyOptions, ...rest }, ref) => {\n const { editor } = useCurrentEditor();\n const instanceRef = useRef<Instance<Props> | null>(null);\n\n useEffect(() => {\n if (!instanceRef.current || !tippyOptions?.placement) return;\n\n instanceRef.current.setProps({ placement: tippyOptions.placement });\n instanceRef.current.popperInstance?.update();\n }, [tippyOptions?.placement]);\n\n const bubbleMenuProps: Omit<BubbleMenuProps, \"children\"> = useMemo(() => {\n const shouldShow: BubbleMenuProps[\"shouldShow\"] = ({ editor, state }) => {\n const { selection } = state;\n const { empty } = selection;\n\n // don't show bubble menu if:\n // - the selected node is an image\n // - the selection is empty\n // - the selection is a node selection (for drag handles)\n if (editor.isActive(\"image\") || empty || isNodeSelection(selection)) {\n return false;\n }\n return true;\n };\n\n return {\n shouldShow,\n tippyOptions: {\n onCreate: (val) => {\n instanceRef.current = val;\n },\n moveTransition: \"transform 0.15s ease-out\",\n ...tippyOptions,\n },\n ...rest,\n };\n }, [rest, tippyOptions]);\n\n if (!editor) return null;\n\n return (\n //We need to add this because of https://github.com/ueberdosis/tiptap/issues/2658\n <div ref={ref}>\n <BubbleMenu editor={editor} {...bubbleMenuProps}>\n {children}\n </BubbleMenu>\n </div>\n );\n }\n);\n\nexport default EditorBubble;\n","import { type ComponentPropsWithoutRef, type ReactNode, forwardRef } from \"react\";\nimport { Slot } from \"@radix-ui/react-slot\";\nimport { useCurrentEditor, type Editor } from \"@tiptap/react\";\n\ninterface EditorBubbleItemProps {\n children: ReactNode;\n asChild?: boolean;\n onSelect?: (editor: Editor) => void;\n}\n\nexport const EditorBubbleItem = forwardRef<\n HTMLDivElement,\n EditorBubbleItemProps & Omit<ComponentPropsWithoutRef<\"div\">, \"onSelect\">\n>(({ children, asChild, onSelect, ...rest }, ref) => {\n const { editor } = useCurrentEditor();\n const Comp = asChild ? Slot : \"div\";\n\n if (!editor) return null;\n\n return (\n <Comp ref={ref} {...rest} onClick={() => onSelect?.(editor)}>\n {children}\n </Comp>\n );\n});\n\nEditorBubbleItem.displayName = \"EditorBubbleItem\";\n\nexport default EditorBubbleItem;\n","import { atom, useAtom, useSetAtom } from \"jotai\";\nimport { useEffect, useRef, type ComponentPropsWithoutRef, forwardRef } from \"react\";\nimport tunnel from \"tunnel-rat\";\nimport { editorStore } from \"./editor\";\nimport { Command } from \"cmdk\";\nimport type { Range } from \"@tiptap/core\";\n\nconst t = tunnel();\n\nexport const queryAtom = atom(\"\");\nexport const rangeAtom = atom<Range | null>(null);\n\nexport const EditorCommandOut = ({\n query,\n range,\n}: {\n query: string;\n range: Range;\n}): JSX.Element => {\n const setQuery = useSetAtom(queryAtom, { store: editorStore });\n const setRange = useSetAtom(rangeAtom, { store: editorStore });\n\n useEffect(() => {\n setQuery(query);\n }, [query, setQuery]);\n\n useEffect(() => {\n setRange(range);\n }, [range, setRange]);\n\n useEffect(() => {\n const navigationKeys = [\"ArrowUp\", \"ArrowDown\", \"Enter\"];\n const onKeyDown = (e: KeyboardEvent) => {\n if (navigationKeys.includes(e.key)) {\n e.preventDefault();\n const commandRef = document.querySelector(\"#slash-command\");\n\n if (commandRef)\n commandRef.dispatchEvent(\n new KeyboardEvent(\"keydown\", { key: e.key, cancelable: true, bubbles: true })\n );\n\n }\n };\n document.addEventListener(\"keydown\", onKeyDown);\n return () => {\n document.removeEventListener(\"keydown\", onKeyDown);\n };\n }, []);\n\n return <t.Out />;\n};\n\nexport const EditorCommand = forwardRef<HTMLDivElement, ComponentPropsWithoutRef<typeof Command>>(\n ({ children, className, ...rest }, ref) => {\n const commandListRef = useRef<HTMLDivElement>(null);\n const [query, setQuery] = useAtom(queryAtom);\n\n return (\n <t.In>\n <Command\n ref={ref}\n onKeyDown={(e) => {\n e.stopPropagation();\n }}\n id='slash-command'\n className={className}\n {...rest}>\n <Command.Input value={query} onValueChange={setQuery} style={{ display: \"none\" }} />\n <Command.List ref={commandListRef}>{children}</Command.List>\n </Command>\n </t.In>\n );\n }\n);\n","import { type ComponentPropsWithoutRef, forwardRef } from \"react\";\nimport { CommandEmpty, CommandItem } from \"cmdk\";\nimport { Editor, type Range } from \"@tiptap/core\";\nimport { useCurrentEditor } from \"@tiptap/react\";\nimport { useAtomValue } from \"jotai\";\nimport { rangeAtom } from \"./editor-command\";\n\ninterface EditorCommandItemProps {\n onCommand: ({ editor, range }: { editor: Editor; range: Range }) => void;\n}\n\nexport const EditorCommandItem = forwardRef<\n HTMLDivElement,\n EditorCommandItemProps & ComponentPropsWithoutRef<typeof CommandItem>\n>(({ children, onCommand, ...rest }, ref) => {\n const { editor } = useCurrentEditor();\n const range = useAtomValue(rangeAtom);\n\n if (!editor || !range) return null;\n\n return (\n <CommandItem ref={ref} {...rest} onSelect={() => onCommand({ editor, range })}>\n {children}\n </CommandItem>\n );\n});\n\nEditorCommandItem.displayName = \"EditorCommandItem\";\n\nexport const EditorCommandEmpty = CommandEmpty;\n\nexport default EditorCommandItem;\n","import { type Editor, type Range, Extension } from \"@tiptap/core\";\nimport Suggestion from \"@tiptap/suggestion\";\nimport { ReactRenderer } from \"@tiptap/react\";\nimport tippy from \"tippy.js\";\n\nimport { EditorCommandOut } from \"../components/editor-command\";\nimport type { ReactNode } from \"react\";\n\nconst Command = Extension.create({\n name: \"slash-command\",\n addOptions() {\n return {\n suggestion: {\n char: \"/\",\n command: ({ editor, range, props }: { editor: Editor; range: Range; props: any }) => {\n props.command({ editor, range });\n },\n },\n };\n },\n addProseMirrorPlugins() {\n return [\n Suggestion({\n editor: this.editor,\n ...this.options.suggestion,\n }),\n ];\n },\n});\n\nconst renderItems = () => {\n let component: ReactRenderer | null = null;\n let popup: any | null = null;\n\n return {\n onStart: (props: { editor: Editor; clientRect: DOMRect }) => {\n component = new ReactRenderer(EditorCommandOut, {\n props,\n editor: props.editor,\n });\n\n // @ts-ignore\n popup = tippy(\"body\", {\n getReferenceClientRect: props.clientRect,\n appendTo: () => document.body,\n content: component.element,\n showOnCreate: true,\n interactive: true,\n trigger: \"manual\",\n placement: \"bottom-start\",\n });\n },\n onUpdate: (props: { editor: Editor; clientRect: DOMRect }) => {\n component?.updateProps(props);\n\n popup &&\n popup[0].setProps({\n getReferenceClientRect: props.clientRect,\n });\n },\n\n onKeyDown: (props: { event: KeyboardEvent }) => {\n if (props.event.key === \"Escape\") {\n popup?.[0].hide();\n\n return true;\n }\n\n // @ts-ignore\n return component?.ref?.onKeyDown(props);\n },\n onExit: () => {\n popup?.[0].destroy();\n component?.destroy();\n },\n };\n};\n\nexport interface SuggestionItem {\n title: string;\n description: string;\n icon: ReactNode;\n searchTerms?: string[];\n command?: (props: { editor: Editor; range: Range }) => void;\n}\n\nexport const createSuggestionItems = (items: SuggestionItem[]) => items;\n\nexport { Command, renderItems };\n","import StarterKit from \"@tiptap/starter-kit\";\nimport HorizontalRule from \"@tiptap/extension-horizontal-rule\";\nimport TiptapLink from \"@tiptap/extension-link\";\nimport TiptapImage from \"@tiptap/extension-image\";\nimport Placeholder from \"@tiptap/extension-placeholder\";\n\nimport { TaskItem } from \"@tiptap/extension-task-item\";\nimport { TaskList } from \"@tiptap/extension-task-list\";\nimport { InputRule } from \"@tiptap/core\";\n\nconst PlaceholderExtension = Placeholder.configure({\n placeholder: ({ node }) => {\n if (node.type.name === \"heading\") {\n return `Heading ${node.attrs.level}`;\n }\n return \"Press '/' for commands\";\n },\n includeChildren: true,\n});\n\nconst Horizontal = HorizontalRule.extend({\n addInputRules() {\n return [\n new InputRule({\n find: /^(?:---|—-|___\\s|\\*\\*\\*\\s)$/,\n handler: ({ state, range }) => {\n const attributes = {};\n\n const { tr } = state;\n const start = range.from;\n const end = range.to;\n\n tr.insert(start - 1, this.type.create(attributes)).delete(\n tr.mapping.map(start),\n tr.mapping.map(end)\n );\n },\n }),\n ];\n },\n});\n\nexport {\n PlaceholderExtension as Placeholder,\n StarterKit,\n Horizontal as HorizontalRule,\n TiptapLink,\n TiptapImage,\n TaskItem,\n TaskList,\n InputRule,\n};\nexport * from \"./slash-command\";\n\nexport { getPrevText } from \"../utils/utils\";\n","import React from \"react\";\nimport { EditorBubbleItem, useEditor } from \"../components\";\n\nimport {\n Button,\n CheckBoxIcon,\n CheckIcon,\n CodeIcon,\n ExpandMoreIcon,\n FormatListBulletedIcon,\n FormatListNumberedIcon,\n FormatQuoteIcon,\n Looks3Icon,\n LooksOneIcon,\n LooksTwoIcon,\n Popover,\n TextFieldsIcon\n} from \"@firecms/ui\";\n\nexport type SelectorItem = {\n name: string;\n icon: React.ElementType;\n command: (editor: ReturnType<typeof useEditor>[\"editor\"]) => void;\n isActive: (editor: ReturnType<typeof useEditor>[\"editor\"]) => boolean;\n};\n\nconst items: SelectorItem[] = [\n {\n name: \"Text\",\n icon: TextFieldsIcon,\n command: (editor) =>\n editor?.chain().focus().toggleNode(\"paragraph\", \"paragraph\").run(),\n // I feel like there has to be a more efficient way to do this – feel free to PR if you know how!\n isActive: (editor) =>\n (editor?.isActive(\"paragraph\") &&\n !editor?.isActive(\"bulletList\") &&\n !editor?.isActive(\"orderedList\")) ?? false,\n },\n {\n name: \"Heading 1\",\n icon: LooksOneIcon,\n command: (editor) =>\n editor?.chain().focus().toggleHeading({ level: 1 }).run(),\n isActive: (editor) => editor?.isActive(\"heading\", { level: 1 }) ?? false,\n },\n {\n name: \"Heading 2\",\n icon: LooksTwoIcon,\n command: (editor) =>\n editor?.chain().focus().toggleHeading({ level: 2 }).run(),\n isActive: (editor) => editor?.isActive(\"heading\", { level: 2 }) ?? false,\n },\n {\n name: \"Heading 3\",\n icon: Looks3Icon,\n command: (editor) =>\n editor?.chain().focus().toggleHeading({ level: 3 }).run(),\n isActive: (editor) => editor?.isActive(\"heading\", { level: 3 }) ?? false,\n },\n {\n name: \"To-do List\",\n icon: CheckBoxIcon,\n command: (editor) => editor?.chain().focus().toggleTaskList().run(),\n isActive: (editor) => editor?.isActive(\"taskItem\") ?? false,\n },\n {\n name: \"Bullet List\",\n icon: FormatListBulletedIcon,\n command: (editor) => editor?.chain().focus().toggleBulletList().run(),\n isActive: (editor) => editor?.isActive(\"bulletList\") ?? false,\n },\n {\n name: \"Numbered List\",\n icon: FormatListNumberedIcon,\n command: (editor) => editor?.chain().focus().toggleOrderedList().run(),\n isActive: (editor) => editor?.isActive(\"orderedList\") ?? false,\n },\n {\n name: \"Quote\",\n icon: FormatQuoteIcon,\n command: (editor) => editor?.chain()\n .focus()\n .toggleNode(\"paragraph\", \"paragraph\")\n .toggleBlockquote()\n .run(),\n isActive: (editor) => editor?.isActive(\"blockquote\") ?? false,\n },\n {\n name: \"Code\",\n icon: CodeIcon,\n command: (editor) => editor?.chain().focus().toggleCodeBlock().run(),\n isActive: (editor) => editor?.isActive(\"codeBlock\") ?? false,\n },\n];\n\ninterface NodeSelectorProps {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n}\n\nexport const NodeSelector = ({\n open,\n onOpenChange\n }: NodeSelectorProps) => {\n const { editor } = useEditor();\n if (!editor) return null;\n const activeItem = items.filter((item) => item.isActive(editor)).pop() ?? {\n name: \"Multiple\",\n };\n\n return (\n\n <Popover\n sideOffset={5}\n align=\"start\"\n className=\"w-48 p-1\"\n trigger={<Button variant=\"text\"\n className=\"gap-2 rounded-none\"\n color=\"text\">\n <span className=\"whitespace-nowrap text-sm\">{activeItem.name}</span>\n <ExpandMoreIcon size={\"small\"}/>\n </Button>}\n modal={true}\n open={open}\n onOpenChange={onOpenChange}>\n {items.map((item, index) => (\n <EditorBubbleItem\n key={index}\n onSelect={(editor) => {\n item.command(editor);\n onOpenChange(false);\n }}\n className=\"flex cursor-pointer items-center justify-between rounded px-2 py-1 text-sm hover:bg-blue-50 hover:dark:bg-gray-700 text-gray-900 dark:text-white\"\n >\n <div className=\"flex items-center space-x-2\">\n <item.icon size=\"smallest\"/>\n <span>{item.name}</span>\n </div>\n {activeItem.name === item.name && <CheckIcon size=\"smallest\"/>}\n </EditorBubbleItem>\n ))}\n\n </Popover>\n );\n};\n","import { useEditor } from \"../components\";\nimport { useEffect, useRef, } from \"react\";\nimport { Button, CheckIcon, cn, DeleteIcon, Popover } from \"@firecms/ui\";\n\nexport function isValidUrl(url: string) {\n try {\n // eslint-disable-next-line no-new\n new URL(url);\n return true;\n } catch (e) {\n return false;\n }\n}\n\nexport function getUrlFromString(str: string) {\n if (isValidUrl(str)) return str;\n try {\n if (str.includes(\".\") && !str.includes(\" \")) {\n return new URL(`https://${str}`).toString();\n }\n return null;\n } catch (e) {\n return null;\n }\n}\n\ninterface LinkSelectorProps {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n}\n\nexport const LinkSelector = ({\n open,\n onOpenChange\n }: LinkSelectorProps) => {\n const inputRef = useRef<HTMLInputElement>(null);\n const { editor } = useEditor();\n\n // Autofocus on input by default\n useEffect(() => {\n inputRef.current && inputRef.current?.focus();\n });\n\n if (!editor) return null;\n\n return (\n <Popover modal={true}\n open={open}\n onOpenChange={onOpenChange}\n trigger={<Button variant=\"text\"\n className=\"gap-2 rounded-none\"\n color={\"text\"}>\n <p className={cn(\"underline decoration-stone-400 underline-offset-4\", {\n \"text-blue-500\": editor.isActive(\"link\"),\n })}>\n Link\n </p>\n </Button>}>\n <form\n onSubmit={(e) => {\n const target = e.currentTarget as HTMLFormElement;\n e.preventDefault();\n const input = target[0] as HTMLInputElement;\n const url = getUrlFromString(input.value);\n url && editor.chain().focus().setLink({ href: url }).run();\n }}\n className=\"flex p-1\"\n >\n <input\n ref={inputRef}\n autoFocus={open}\n placeholder=\"Paste a link\"\n defaultValue={editor.getAttributes(\"link\").href || \"\"}\n className={\"text-gray-900 dark:text-white flex-grow bg-transparent p-1 text-sm outline-none\"}/>\n\n {editor.getAttributes(\"link\").href ? (\n <Button\n size={\"small\"}\n variant=\"text\"\n type=\"button\"\n color={\"text\"}\n className=\"flex items-center\"\n onClick={() => {\n editor.chain().focus().unsetLink().run();\n }}\n >\n <DeleteIcon size=\"small\"/>\n </Button>\n ) : (\n <Button size={\"small\"}\n variant={\"text\"}>\n <CheckIcon size=\"small\"/>\n </Button>\n )}\n </form>\n </Popover>\n );\n};\n","import { EditorBubbleItem, useEditor } from \"../components\";\nimport type { SelectorItem } from \"./node-selector\";\nimport {\n Button,\n cn,\n CodeIcon,\n FormatBoldIcon,\n FormatItalicIcon,\n FormatStrikethroughIcon,\n FormatUnderlinedIcon\n} from \"@firecms/ui\";\n\nexport const TextButtons = () => {\n const { editor } = useEditor();\n if (!editor) return null;\n const items: SelectorItem[] = [\n {\n name: \"bold\",\n isActive: (editor) => editor?.isActive(\"bold\") ?? false,\n command: (editor) => editor?.chain().focus().toggleBold().run(),\n icon: FormatBoldIcon,\n },\n {\n name: \"italic\",\n isActive: (editor) => editor?.isActive(\"italic\") ?? false,\n command: (editor) => editor?.chain().focus().toggleItalic().run(),\n icon: FormatItalicIcon,\n },\n {\n name: \"underline\",\n isActive: (editor) => editor?.isActive(\"underline\") ?? false,\n command: (editor) => editor?.chain().focus().toggleUnderline().run(),\n icon: FormatUnderlinedIcon,\n },\n {\n name: \"strike\",\n isActive: (editor) => editor?.isActive(\"strike\") ?? false,\n command: (editor) => editor?.chain().focus().toggleStrike().run(),\n icon: FormatStrikethroughIcon,\n },\n {\n name: \"code\",\n isActive: (editor) => editor?.isActive(\"code\") ?? false,\n command: (editor) => editor?.chain().focus().toggleCode().run(),\n icon: CodeIcon,\n },\n ];\n return (\n <div className=\"flex\">\n {items.map((item, index) => (\n <EditorBubbleItem\n key={index}\n onSelect={(editor) => {\n item.command(editor);\n }}\n >\n <Button size={\"small\"}\n color=\"text\"\n className=\"gap-2 rounded-none h-full\"\n variant=\"text\">\n <item.icon\n className={cn( {\n \"text-inherit\": !item.isActive(editor),\n \"text-blue-500\": item.isActive(editor),\n })}\n />\n </Button>\n </EditorBubbleItem>\n ))}\n </div>\n );\n};\n","import React from \"react\";\n\nexport function useDebouncedCallback<T>(value: T, callback: () => void, immediate: boolean, timeoutMs = 300) {\n\n const pendingUpdate = React.useRef(false);\n const performUpdate = () => {\n callback();\n pendingUpdate.current = false;\n };\n\n const handlerRef = React.useRef<number | undefined>(undefined);\n\n React.useEffect(\n () => {\n pendingUpdate.current = true;\n clearTimeout(handlerRef.current);\n handlerRef.current = setTimeout(performUpdate, timeoutMs) as any;\n return () => {\n if (immediate)\n performUpdate();\n };\n },\n [immediate, value]\n );\n}\n","export function removeClassesFromJson(jsonObj: any): any {\n // If it's an array, apply the function to each element\n if (Array.isArray(jsonObj)) {\n return jsonObj.map(item => removeClassesFromJson(item));\n } else if (typeof jsonObj === \"object\" && jsonObj !== null) { // If it's an object, recurse through its properties\n // If the object has an `attrs` property and `class` field, delete the `class` field\n if (jsonObj.attrs && typeof jsonObj.attrs === \"object\" && \"class\" in jsonObj.attrs) {\n delete jsonObj.attrs.class;\n }\n\n // Apply the function recursively to object properties\n Object.keys(jsonObj).forEach(key => {\n jsonObj[key] = removeClassesFromJson(jsonObj[key]);\n });\n }\n return jsonObj;\n}\n","import { HorizontalRule, Placeholder, StarterKit, TaskItem, TaskList, TiptapImage, TiptapLink, } from \"./extensions\";\n\nimport { cn, defaultBorderMixin } from \"@firecms/ui\";\n\n//You can overwrite the placeholder with your own configuration\nexport const placeholder = Placeholder;\nexport const tiptapLink = TiptapLink.configure({\n HTMLAttributes: {\n class: cn(\n \"text-gray-600 dark:text-slate-300 underline underline-offset-[3px] hover:text-primary transition-colors cursor-pointer\",\n ),\n },\n});\n\n// export const tiptapImage = TiptapImage.extend({\n// addProseMirrorPlugins() {\n// return [UploadImagesPlugin()];\n// },\n// }).configure({\n// allowBase64: true,\n// HTMLAttributes: {\n// class: cn(\"rounded-lg border\", defaultBorderMixin),\n// },\n// });\n\n// const updatedImage = UpdatedImage.configure({\n// HTMLAttributes: {\n// class: cn(\"rounded-lg border\", defaultBorderMixin),\n// },\n// });\n\nexport const taskList = TaskList.configure({\n HTMLAttributes: {\n class: cn(\"not-prose\"),\n },\n});\nexport const taskItem = TaskItem.configure({\n HTMLAttributes: {\n class: cn(\"flex items-start my-4\"),\n },\n nested: true,\n});\n\nexport const horizontalRule = HorizontalRule.configure({\n HTMLAttributes: {\n class: cn(\"mt-4 mb-6 border-t\", defaultBorderMixin),\n },\n});\n\nexport const starterKit = StarterKit.configure({\n bulletList: {\n HTMLAttributes: {\n class: cn(\"list-disc list-outside leading-3 -mt-2\"),\n },\n },\n orderedList: {\n HTMLAttributes: {\n class: cn(\"list-decimal list-outside leading-3 -mt-2\"),\n },\n },\n listItem: {\n HTMLAttributes: {\n class: cn(\"leading-normal -mb-2\"),\n },\n },\n blockquote: {\n HTMLAttributes: {\n class: cn(\"border-l-4 border-primary\"),\n },\n },\n codeBlock: {\n HTMLAttributes: {\n class: cn(\"rounded bg-blue-50 dark:bg-gray-700 border p-5 font-mono font-medium\", defaultBorderMixin),\n },\n },\n code: {\n HTMLAttributes: {\n class: cn(\"rounded-md bg-slate-50 dark:bg-gray-700 px-1.5 py-1 font-mono font-medium\"),\n spellcheck: \"false\",\n },\n },\n horizontalRule: false,\n dropcursor: {\n color: \"#DBEAFE\",\n width: 4,\n },\n gapcursor: false,\n});\n","import { Plugin, } from \"prosemirror-state\";\nimport { TiptapImage } from \"./index\";\nimport { cn, defaultBorderMixin } from \"@firecms/ui\";\nimport { Decoration, DecorationSet, EditorView } from \"@tiptap/pm/view\";\n\nexport type UploadFn = (image: File) => Promise<string>;\n\nasync function onFileRead(plugin: Plugin, view: EditorView, readerEvent: ProgressEvent<FileReader>, pos: number, upload: UploadFn, image: File) {\n\n const { schema } = view.state;\n let decorationSet = plugin.getState(view.state);\n\n const placeholder = document.createElement(\"div\");\n const imageElement = document.createElement(\"img\");\n imageElement.setAttribute(\"class\", \"opacity-40 rounded-lg border border-stone-200\");\n imageElement.src = readerEvent.target?.result as string;\n placeholder.appendChild(imageElement);\n\n const deco = Decoration.widget(pos, placeholder);\n decorationSet = decorationSet?.add(view.state.doc, [deco]);\n view.dispatch(view.state.tr.setMeta(plugin, { decorationSet }));\n\n // Image Upload Logic\n const src = await upload(image);\n console.log(\"uploaded image\", src);\n\n // Replace placeholder with actual image\n const imageNode = schema.nodes.image.create({ src });\n const tr = view.state.tr.replaceWith(pos, pos, imageNode);\n\n // Remove placeholder decoration\n decorationSet = decorationSet?.remove([deco]);\n tr.setMeta(plugin, { decorationSet });\n view.dispatch(tr);\n}\n\nexport const dropImagePlugin = (upload: UploadFn) => {\n const plugin: Plugin = new Plugin({\n state: {\n // Initialize the plugin state with an empty DecorationSet\n init: () => DecorationSet.empty,\n // Apply transactions to update the state\n apply: (tr, old) => {\n // Handle custom transaction steps that update decorations\n const meta = tr.getMeta(plugin);\n if (meta && meta.decorationSet) {\n return meta.decorationSet;\n }\n // Map decorations to the new document structure\n return old.map(tr.mapping, tr.doc);\n }\n },\n props: {\n handleDOMEvents: {\n drop: (view, event) => {\n console.log(\"drop event\", event)\n if (!event.dataTransfer?.files || event.dataTransfer?.files.length === 0) {\n return false;\n }\n event.preventDefault();\n\n const files = Array.from(event.dataTransfer.files);\n const images = files.filter(file => /image/i.test(file.type));\n\n if (images.length === 0) return false;\n\n images.forEach(image => {\n\n const position = view.posAtCoords({ left: event.clientX, top: event.clientY });\n if (!position) return;\n\n const reader = new FileReader();\n reader.onload = async (readerEvent) => {\n await onFileRead(plugin, view, readerEvent, position.pos, upload, image);\n };\n reader.readAsDataURL(image);\n });\n\n return true;\n }\n },\n handlePaste(view, event, slice) {\n const items = Array.from(event.clipboardData?.items || []);\n const pos = view.state.selection.from;\n console.log(\"pos\", pos)\n let anyImageFound = false;\n\n items.forEach((item) => {\n const image = item.getAsFile();\n console.log(\"image\", image);\n if (image) {\n anyImageFound = true;\n // if (item.type.indexOf(\"image\") === 0) {\n // event.preventDefault();\n //\n // if (upload && image) {\n // upload(image).then((src) => {\n // const node = schema.nodes.image.create({\n // src\n // });\n // const transaction = view.state.tr.replaceSelectionWith(node);\n // view.dispatch(transaction);\n // });\n // }\n // } else {\n const reader = new FileReader();\n\n reader.onload = async (readerEvent) => {\n await onFileRead(plugin, view, readerEvent, pos, upload, image);\n };\n reader.readAsDataURL(image);\n }\n });\n\n return anyImageFound;\n },\n decorations(state) {\n return plugin.getState(state);\n }\n },\n view(editorView) {\n // This is needed to immediately apply the decoration updates\n return {\n update(view, prevState) {\n const prevDecos = plugin.getState(prevState);\n const newDecos = plugin.getState(view.state);\n\n if (prevDecos !== newDecos) {\n view.updateState(view.state);\n }\n }\n };\n }\n });\n return plugin;\n};\n\n/**\n * Matches following attributes in Markdown-typed image: [, alt, src, title]\n *\n * Example:\n *  -> [, \"Lorem\", \"image.jpg\"]\n *  -> [, \"\", \"image.jpg\", \"Ipsum\"]\n *  -> [, \"Lorem\", \"image.jpg\", \"Ipsum\"]\n */\nconst IMAGE_INPUT_REGEX = /!\\[(.+|:?)\\]\\((\\S+)(?:(?:\\s+)[\"'](\\S+)[\"'])?\\)/;\n\nexport const createImageExtension = (uploadFn: UploadFn) => {\n return TiptapImage.extend({\n addProseMirrorPlugins() {\n return [dropImagePlugin(uploadFn)];\n }\n }).configure({\n allowBase64: true,\n HTMLAttributes: {\n class: cn(\"rounded-lg border\", defaultBorderMixin)\n }\n });\n};\n","import { Extension } from \"@tiptap/core\";\n\ndeclare module \"@tiptap/core\" {\n // eslint-disable-next-line no-unused-vars\n interface Commands<ReturnType> {\n customkeymap: {\n /**\n * Select text between node boundaries\n */\n selectTextWithinNodeBoundaries: () => ReturnType;\n };\n }\n}\n\nexport const CustomKeymap = Extension.create({\n name: \"CustomKeymap\",\n\n addCommands() {\n return {\n selectTextWithinNodeBoundaries:\n () =>\n ({ editor, commands }) => {\n const { state } = editor;\n const { tr } = state;\n const startNodePos = tr.selection.$from.start();\n const endNodePos = tr.selection.$to.end();\n return commands.setTextSelection({\n from: startNodePos,\n to: endNodePos,\n });\n },\n };\n },\n\n addKeyboardShortcuts() {\n return {\n \"Mod-a\": ({ editor }) => {\n const { state } = editor;\n const { tr } = state;\n const startSelectionPos = tr.selection.from;\n const endSelectionPos = tr.selection.to;\n const startNodePos = tr.selection.$from.start();\n const endNodePos = tr.selection.$to.end();\n const isCurrentTextSelectionNotExtendedToNodeBoundaries =\n startSelectionPos > startNodePos || endSelectionPos < endNodePos;\n if (isCurrentTextSelectionNotExtendedToNodeBoundaries) {\n editor.chain().selectTextWithinNodeBoundaries().run();\n return true;\n }\n return false;\n },\n };\n },\n});\n\n","import { Extension } from \"@tiptap/core\";\n\nimport { NodeSelection, Plugin } from \"@tiptap/pm/state\";\n// @ts-ignore\nimport { __serializeForClipboard, EditorView } from \"@tiptap/pm/view\";\n\nexport interface DragHandleOptions {\n /**\n * The width of the drag handle\n */\n dragHandleWidth: number;\n}\nfunction absoluteRect(node: Element) {\n const data = node.getBoundingClientRect();\n\n return {\n top: data.top,\n left: data.left,\n width: data.width,\n };\n}\n\nfunction nodeDOMAtCoords(coords: { x: number; y: number }) {\n return document\n .elementsFromPoint(coords.x, coords.y)\n .find(\n (elem: Element) =>\n elem.parentElement?.matches?.(\".ProseMirror\") ||\n elem.matches(\n [\"li\", \"p:not(:first-child)\", \"pre\", \"blockquote\", \"h1, h2, h3, h4, h5, h6\"].join(\", \")\n )\n );\n}\n\nfunction nodePosAtDOM(node: Element, view: EditorView, options: DragHandleOptions) {\n const boundingRect = node.getBoundingClientRect();\n\n return view.posAtCoords({\n left: boundingRect.left + 50 + options.dragHandleWidth,\n top: boundingRect.top + 1,\n })?.inside;\n}\n\nfunction DragHandle(options: DragHandleOptions) {\n function handleDragStart(event: DragEvent, view: EditorView) {\n view.focus();\n\n if (!event.dataTransfer) return;\n\n const node = nodeDOMAtCoords({\n x: event.clientX + 50 + options.dragHandleWidth,\n y: event.clientY,\n });\n\n if (!(node instanceof Element)) return;\n\n const nodePos = nodePosAtDOM(node, view, options);\n if (nodePos == null || nodePos < 0) return;\n\n view.dispatch(view.state.tr.setSelection(NodeSelection.create(view.state.doc, nodePos)));\n\n const slice = view.state.selection.content();\n const { dom, text } = __serializeForClipboard(view, slice);\n\n event.dataTransfer.clearData();\n event.dataTransfer.setData(\"text/html\", dom.innerHTML);\n event.dataTransfer.setData(\"text/plain\", text);\n event.dataTransfer.effectAllowed = \"copyMove\";\n\n event.dataTransfer.setDragImage(node, 0, 0);\n\n view.dragging = { slice, move: event.ctrlKey };\n }\n\n function handleClick(event: MouseEvent, view: EditorView) {\n view.focus();\n\n view.dom.classList.remove(\"dragging\");\n\n const node = nodeDOMAtCoords({\n x: event.clientX + 50 + options.dragHandleWidth,\n y: event.clientY,\n });\n\n if (!(node instanceof Element)) return;\n\n const nodePos = nodePosAtDOM(node, view, options);\n if (!nodePos) return;\n\n view.dispatch(view.state.tr.setSelection(NodeSelection.create(view.state.doc, nodePos)));\n }\n\n let dragHandleElement: HTMLElement | null = null;\n\n function hideDragHandle() {\n if (dragHandleElement) {\n dragHandleElement.classList.add(\"hide\");\n }\n }\n\n function showDragHandle() {\n if (dragHandleElement) {\n dragHandleElement.classList.remove(\"hide\");\n }\n }\n\n return new Plugin({\n view: (view) => {\n dragHandleElement = document.createElement(\"div\");\n dragHandleElement.draggable = true;\n dragHandleElement.dataset.dragHandle = \"\";\n dragHandleElement.classList.add(\"drag-handle\");\n dragHandleElement.addEventListener(\"dragstart\", (e) => {\n handleDragStart(e, view);\n });\n dragHandleElement.addEventListener(\"click\", (e) => {\n handleClick(e, view);\n });\n\n hideDragHandle();\n\n view?.dom?.parentElement?.appendChild(dragHandleElement);\n\n return {\n destroy: () => {\n dragHandleElement?.remove?.();\n dragHandleElement = null;\n },\n };\n },\n props: {\n handleDOMEvents: {\n mousemove: (view, event) => {\n if (!view.editable) {\n return;\n }\n\n const node = nodeDOMAtCoords({\n x: event.clientX + 50 + options.dragHandleWidth,\n y: event.clientY,\n });\n\n if (!(node instanceof Element)) {\n hideDragHandle();\n return;\n }\n\n const compStyle = window.getComputedStyle(node);\n const lineHeight = parseInt(compStyle.lineHeight, 10);\n const paddingTop = parseInt(compStyle.paddingTop, 10);\n\n const rect = absoluteRect(node);\n\n rect.top += (lineHeight - 24) / 2;\n rect.top += paddingTop;\n // Li markers\n if (node.matches(\"ul:not([data-type=taskList]) li, ol li\")) {\n rect.left -= options.dragHandleWidth;\n }\n rect.width = options.dragHandleWidth;\n\n if (!dragHandleElement) return;\n\n dragHandleElement.style.left = `${rect.left - rect.width}px`;\n dragHandleElement.style.top = `${rect.top}px`;\n showDragHandle();\n },\n keydown: () => {\n hideDragHandle();\n },\n mousewheel: () => {\n hideDragHandle();\n },\n // dragging class is used for CSS\n dragstart: (view) => {\n view.dom.classList.add(\"dragging\");\n },\n drop: (view) => {\n view.dom.classList.remove(\"dragging\");\n },\n dragend: (view) => {\n view.dom.classList.remove(\"dragging\");\n },\n },\n },\n });\n}\n\nexport const DragAndDrop = Extension.create({\n name: \"dragAndDrop\",\n\n addProseMirrorPlugins() {\n return [\n DragHandle({\n dragHandleWidth: 24,\n }),\n ];\n },\n});\n\n","\"use client\";\nimport React, { useMemo, useState } from \"react\";\n\nimport TiptapUnderline from \"@tiptap/extension-underline\";\nimport TextStyle from \"@tiptap/extension-text-style\";\nimport { Color } from \"@tiptap/extension-color\";\n\nimport { Markdown } from \"tiptap-markdown\";\nimport Highlight from \"@tiptap/extension-highlight\";\n\nimport {\n EditorBubble,\n EditorCommand,\n EditorCommandEmpty,\n EditorCommandItem,\n EditorRoot,\n type JSONContent\n} from \"./components\";\nimport { Command, createSuggestionItems, renderItems } from \"./extensions\";\n\nimport { NodeSelector } from \"./selectors/node-selector\";\nimport { LinkSelector } from \"./selectors/link-selector\";\nimport { TextButtons } from \"./selectors/text-buttons\";\n\nimport {\n CheckBoxIcon,\n cn,\n CodeIcon,\n defaultBorderMixin,\n FormatListBulletedIcon,\n FormatListNumberedIcon,\n FormatQuoteIcon,\n ImageIcon,\n Looks3Icon,\n LooksOneIcon,\n LooksTwoIcon,\n Separator,\n TextFieldsIcon,\n useInjectStyles\n} from \"@firecms/ui\";\n// import { startImageUpload } from \"./plugins\";\nimport { Editor, EditorProvider, EditorProviderProps } from \"@tiptap/react\";\nimport { useDebouncedCallback } from \"./utils/useDebouncedCallback\";\nimport { removeClassesFromJson } from \"./utils/remove_classes\";\nimport { horizontalRule, placeholder, starterKit, taskItem, taskList, tiptapLink } from \"./editor_extensions\";\nimport { createImageExtension } from \"./extensions/Image\";\nimport { CustomKeymap } from \"./extensions/custom-keymap\";\nimport { DragAndDrop } from \"./extensions/drag-and-drop\";\n\nexport type FireCMSEditorProps = {\n initialContent?: JSONContent | string,\n onMarkdownContentChange?: (content: string) => void,\n onJsonContentChange?: (content: JSONContent | null) => void,\n onHtmlContentChange?: (content: string) => void,\n handleImageUpload: (file: File) => Promise<string>\n};\n\nexport const FireCMSEditor = ({\n handleImageUpload,\n initialContent,\n onJsonContentChange,\n onHtmlContentChange,\n onMarkdownContentChange\n }: FireCMSEditorProps) => {\n\n const defaultEditorProps: EditorProviderProps[\"editorProps\"] = {\n handleDOMEvents: {\n keydown: (_view, event) => {\n // prevent default event listeners from firing when slash command is active\n if ([\"ArrowUp\", \"ArrowDown\", \"Enter\"].includes(event.key)) {\n const slashCommand = document.querySelector(\"#slash-command\");\n if (slashCommand) {\n return true;\n }\n }\n return false;\n }\n },\n // handlePaste: (view, event) => {\n // if (event.clipboardData && event.clipboardData.files && event.clipboardData.files[0]) {\n // event.preventDefault();\n // const file = event.clipboardData.files[0];\n // const pos = view.state.selection.from;\n //\n // // startImageUpload({ file, view, pos, handleImageUpload });\n // return true;\n // }\n // return false;\n // },\n // handleDrop: (view, event, _slice, moved) => {\n // console.log(\"handleDrop\", { event, moved });\n // if (!moved && event.dataTransfer && event.dataTransfer.files && event.dataTransfer.files[0]) {\n // console.log(\"handleDrop!!!\", { event, moved });\n // event.preventDefault();\n // const file = event.dataTransfer.files[0];\n // const coordinates = view.posAtCoords({\n // left: event.clientX,\n // top: event.clientY\n // });\n // // here we deduct 1 from the pos or else the image will create an extra node\n // startImageUpload({\n // file,\n // view,\n // pos: coordinates?.pos || 0 - 1,\n // handleImageUpload,\n // });\n // return true;\n // }\n // return false;\n // }\n };\n\n const suggestionItems = createSuggestionItems([\n {\n title: \"Text\",\n description: \"Just start typing with plain text.\",\n searchTerms: [\"p\", \"paragraph\"],\n icon: <TextFieldsIcon size={18}/>,\n command: ({ editor, range }) => {\n editor\n .chain()\n .focus()\n .deleteRange(range)\n .toggleNode(\"paragraph\", \"paragraph\")\n .run();\n }\n },\n {\n title: \"To-do List\",\n description: \"Track tasks with a to-do list.\",\n searchTerms: [\"todo\", \"task\", \"list\", \"check\", \"checkbox\"],\n icon: <CheckBoxIcon size={18}/>,\n command: ({ editor, range }) => {\n editor.chain().focus().deleteRange(range).toggleTaskList().run();\n }\n },\n {\n title: \"Heading 1\",\n description: \"Big section heading.\",\n searchTerms: [\"title\", \"big\", \"large\"],\n icon: <LooksOneIcon size={18}/>,\n command: ({ editor, range }) => {\n editor\n .chain()\n .focus()\n .deleteRange(range)\n .setNode(\"heading\", { level: 1 })\n .run();\n }\n },\n {\n title: \"Heading 2\",\n description: \"Medium section heading.\",\n searchTerms: [\"subtitle\", \"medium\"],\n icon: <LooksTwoIcon size={18}/>,\n command: ({ editor, range }) => {\n editor\n .chain()\n .focus()\n .deleteRange(range)\n .setNode(\"heading\", { level: 2 })\n .run();\n }\n },\n {\n title: \"Heading 3\",\n description: \"Small section heading.\",\n searchTerms: [\"subtitle\", \"small\"],\n icon: <Looks3Icon size={18}/>,\n command: ({ editor, range }) => {\n editor\n .chain()\n .focus()\n .deleteRange(range)\n .setNode(\"heading\", { level: 3 })\n .run();\n }\n },\n {\n title: \"Bullet List\",\n description: \"Create a simple bullet list.\",\n searchTerms: [\"unordered\", \"point\"],\n icon: <FormatListBulletedIcon size={18}/>,\n command: ({ editor, range }) => {\n editor.chain().focus().deleteRange(range).toggleBulletList().run();\n }\n },\n {\n title: \"Numbered List\",\n description: \"Create a list with numbering.\",\n searchTerms: [\"ordered\"],\n icon: <FormatListNumberedIcon size={18}/>,\n command: ({ editor, range }) => {\n editor.chain().focus().deleteRange(range).toggleOrderedList().run();\n }\n },\n {\n title: \"Quote\",\n description: \"Capture a quote.\",\n searchTerms: [\"blockquote\"],\n icon: <FormatQuoteIcon size={18}/>,\n command: ({ editor, range }) =>\n editor\n .chain()\n .focus()\n .deleteRange(range)\n .toggleNode(\"paragraph\", \"paragraph\")\n .toggleBlockquote()\n .run()\n },\n {\n title: \"Code\",\n description: \"Capture a code snippet.\",\n searchTerms: [\"codeblock\"],\n icon: <CodeIcon size={18}/>,\n command: ({ editor, range }) =>\n editor.chain().focus().deleteRange(range).toggleCodeBlock().run()\n },\n {\n title: \"Image\",\n description: \"Upload an image from your computer.\",\n searchTerms: [\"photo\", \"picture\", \"media\"],\n icon: <ImageIcon size={18}/>,\n command: ({ editor, range }) => {\n editor.chain().focus().deleteRange(range).run();\n // upload image\n const input = document.createElement(\"input\");\n input.type = \"file\";\n input.accept = \"image/*\";\n input.onchange = async () => {\n if (input.files?.length) {\n const file = input.files[0];\n if (!file) return;\n const pos = editor.view.state.selection.from;\n // startImageUpload({\n // file,\n // view: editor.view,\n // pos,\n // handleImageUpload\n // });\n }\n };\n input.click();\n }\n }\n ]);\n\n const slashCommand = Command.configure({\n suggestion: {\n items: () => suggestionItems,\n render: renderItems\n }\n });\n\n const imageExtension = useMemo(() => createImageExtension(handleImageUpload), []);\n\n const extensions = [\n TiptapUnderline,\n TextStyle,\n Color,\n Highlight.configure({\n multicolor: true,\n }),\n Markdown.configure({\n html: false,\n transformCopiedText: true,\n }),\n CustomKeymap,\n DragAndDrop,\n starterKit,\n placeholder,\n tiptapLink,\n // tiptapImage,\n imageExtension,\n // updatedImage,\n taskList,\n taskItem,\n horizontalRule,\n slashCommand];\n const [openNode, setOpenNode] = useState(false);\n const [openLink, setOpenLink] = useState(false);\n\n useInjectStyles(\"Editor\", cssStyles);\n\n const editorRef = React.useRef<Editor | null>(null);\n const [markdownContent, setMarkdownContent] = useState<string | null>(null);\n const [jsonContent, setJsonContent] = useState<JSONContent | null>(null);\n const [htmlContent, setHtmlContent] = useState<string | null>(null);\n\n const onEditorUpdate = (editor: Editor) => {\n editorRef.current = editor;\n if (onMarkdownContentChange) {\n setMarkdownContent(editor.storage.markdown.getMarkdown());\n }\n if (onJsonContentChange) {\n setJsonContent(removeClassesFromJson(editor.getJSON()));\n }\n if (onHtmlContentChange) {\n setHtmlContent(editor.getHTML());\n }\n }\n\n useDebouncedCallback(markdownContent, () => {\n\n if (editorRef.current) {\n const markdown = editorRef.current.storage.markdown.getMarkdown();\n onMarkdownContentChange?.(addLineBreakAfterImages(markdown));\n }\n }, false, 500);\n\n useDebouncedCallback(jsonContent, () => {\n if (jsonContent)\n onJsonContentChange?.(jsonContent);\n }, false, 500);\n\n useDebouncedCallback(htmlContent, () => {\n if (htmlContent)\n onHtmlContentChange?.(htmlContent);\n }, false, 500);\n\n if (!initialContent) return null;\n\n return (\n <div className=\"relative w-full p-8\">\n <EditorRoot>\n <div\n className=\"relative min-h-[500px] w-full bg-white dark:bg-gray-950 rounded-lg\">\n <EditorProvider\n content={initialContent}\n extensions={extensions}\n editorProps={{\n ...defaultEditorProps,\n attributes: {\n class: \"prose-lg prose-headings:font-title font-default focus:outline-none max-w-full p-12\"\n }\n }}\n onUpdate={({ editor }) => {\n console.log(\"editor updated\");\n onEditorUpdate(editor as Editor);\n }}>\n\n <EditorCommand\n className={cn(\"text-gray-900 dark:text-white z-50 h-auto max-h-[330px] w-72 overflow-y-auto rounded-md border bg-white dark:bg-gray-900 px-1 py-2 shadow transition-all\", defaultBorderMixin)}>\n <EditorCommandEmpty className=\"px-2 text-gray-700 dark:text-slate-300\">\n No results\n </EditorCommandEmpty>\n {suggestionItems.map((item) => (\n <EditorCommandItem\n value={item.title}\n onCommand={(val) => item?.command?.(val)}\n className={\"flex w-full items-center space-x-2 rounded-md px-2 py-1 text-left text-sm hover:bg-blue-50 hover:dark:bg-gray-700 aria-selected:bg-blue-50 aria-selected:dark:bg-gray-700\"}\n key={item.title}\n >\n <div\n className={cn(\"flex h-10 w-10 items-center justify-center rounded-md border bg-white dark:bg-gray-900\", defaultBorderMixin)}>\n {item.icon}\n </div>\n <div>\n <p className=\"font-medium\">{item.title}</p>\n <p className=\"text-xs text-gray-700 dark:text-slate-300\">\n {item.description}\n </p>\n </div>\n </EditorCommandItem>\n ))}\n </EditorCommand>\n\n <EditorBubble\n tippyOptions={{\n placement: \"top\"\n }}\n className={cn(\"flex w-fit max-w-[90vw] h-10 overflow-hidden rounded border bg-white dark:bg-gray-900 shadow\", defaultBorderMixin)}\n >\n {/*<Separator orientation=\"vertical\"/>*/}\n <NodeSelector open={openNode} onOpenChange={setOpenNode}/>\n <Separator orientation=\"vertical\"/>\n\n <LinkSelector open={openLink} onOpenChange={setOpenLink}/>\n <Separator orientation=\"vertical\"/>\n <TextButtons/>\n {/*<Separator orientation=\"vertical\"/>*/}\n {/*<ColorSelector open={openColor} onOpenChange={setOpenColor}/>*/}\n </EditorBubble>\n\n </EditorProvider>\n </div>\n\n </EditorRoot>\n </div>\n );\n};\n\nfunction addLineBreakAfterImages(markdown: string): string {\n // Regular expression to match markdown image syntax\n const imageRegex = /!\\[.*?\\]\\(.*?\\)/g;\n // Replace image with image followed by a line break\n return markdown.replace(imageRegex, (match) => `${match}\\n`);\n}\n\nconst cssStyles = `\n\n.ProseMirror .is-editor-empty:first-child::before {\n content: attr(data-placeholder);\n float: left;\n color: rgb(100 116 139); //500\n pointer-events: none;\n height: 0;\n}\n.ProseMirror .is-empty::before {\n content: attr(data-placeholder);\n float: left;\n color: rgb(100 116 139); //500\n pointer-events: none;\n height: 0;\n}\n\n[data-theme=\"dark\"] {\n .ProseMirror .is-empty::before {\n color: rgb(100 116 139); //500\n }\n}\n\n.is-empty {\n color: rgb(100 116 139); //500\n}\n\n\n/* Custom image styles */\n\n.ProseMirror img {\n transition: filter 0.1s ease-in-out;\n\n &:hover {\n cursor: pointer;\n filter: brightness(90%);\n }\n\n &.ProseMirror-selectednode {\n outline: 3px solid #5abbf7;\n filter: brightness(90%);\n }\n}\n\n/* Custom TODO list checkboxes – shoutout to this awesome tutorial: https://moderncss.dev/pure-css-custom-checkbox-style/ */\n\nul[data-type=\"taskList\"] li > label {\n margin-right: 0.2rem;\n user-select: none;\n}\n\n@media screen and (max-width: 768px) {\n ul[data-type=\"taskList\"] li > label {\n margin-right: 0.5rem;\n }\n}\n\n\n[data-theme=\"dark\"] {\n ul[data-type=\"taskList\"] li > label input[type=\"checkbox\"] {\n background-color: rgb(30 41 59); // 800\n border: 2px solid #666;\n \n &:hover {\n background-color: rgb(51 65 85); // 700\n }\n \n &:active {\n background-color: rgb(71 85 105);;\n }\n }\n}\n \n\nul[data-type=\"taskList\"] li > label input[type=\"checkbox\"] {\n -webkit-appearance: none;\n appearance: none;\n background-color: white;\n margin: 0;\n cursor: pointer;\n width: 1.2em;\n height: 1.2em;\n position: relative;\n top: 5px;\n border: 2px solid #777;\n border-radius: 0.25em;\n margin-right: 0.3rem;\n display: grid;\n place-content: center;\n\n &:hover {\n background-color: rgb(241 245 249); //100\n }\n\n &:active {\n background-color: rgb(226 232 240); //200\n }\n\n &::before {\n content: \"\";\n width: 0.65em;\n height: 0.65em;\n transform: scale(0);\n transition: 120ms transform ease-in-out;\n box-shadow: inset 1em 1em;\n transform-origin: center;\n clip-path: polygon(14% 44%, 0 65%, 50% 100%, 100% 16%, 80% 0%, 43% 62%);\n }\n\n &:checked::before {\n transform: scale(1);\n }\n}\n\n[data-theme=\"dark\"] {\n ul[data-type=\"taskList\"] li[data-checked=\"true\"] > div > p {\n color: rgb(226 232 240);\n text-decoration: line-through;\n text-decoration-thickness: 2px;\n }\n}\n\nul[data-type=\"taskList\"] li[data-checked=\"true\"] > div > p {\n color: rgb(51 65 85); // 700\n text-decoration: line-through;\n text-decoration-thickness: 2px;\n}\n\n/* Overwrite tippy-box original max-width */\n\n.tippy-box {\n max-width: 400px !important;\n}\n\n.ProseMirror:not(.dragging) .ProseMirror-selectednode {\n outline: none !important;\n background-color: rgb(219 234 254); // blue 100\n transition: background-color 0.2s;\n box-shadow: none;\n}\n\n[data-theme=\"dark\"] .ProseMirror:not(.dragging) .ProseMirror-selectednode {\n background-color: rgb(51 65 85); // 700\n}\n\n.drag-handle {\n position: fixed;\n opacity: 1;\n transition: opacity ease-in 0.2s;\n border-radius: 0.25rem;\n\n background-image: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 10' style='fill: rgba(128, 128, 128, 0.9)'%3E%3Cpath d='M3,2 C2.44771525,2 2,1.55228475 2,1 C2,0.44771525 2.44771525,0 3,0 C3.55228475,0 4,0.44771525 4,1 C4,1.55228475 3.55228475,2 3,2 Z M3,6 C2.44771525,6 2,5.55228475 2,5 C2,4.44771525 2.44771525,4 3,4 C3.55228475,4 4,4.44771525 4,5 C4,5.55228475 3.55228475,6 3,6 Z M3,10 C2.44771525,10 2,9.55228475 2,9 C2,8.44771525 2.44771525,8 3,8 C3.55228475,8 4,8.44771525 4,9 C4,9.55228475 3.55228475,10 3,10 Z M7,2 C6.44771525,2 6,1.55228475 6,1 C6,0.44771525 6.44771525,0 7,0 C7.55228475,0 8,0.44771525 8,1 C8,1.55228475 7.55228475,2 7,2 Z M7,6 C6.44771525,6 6,5.55228475 6,5 C6,4.44771525 6.44771525,4 7,4 C7.55228475,4 8,4.44771525 8,5 C8,5.55228475 7.55228475,6 7,6 Z M7,10 C6.44771525,10 6,9.55228475 6,9 C6,8.44771525 6.44771525,8 7,8 C7.55228475,8 8,8.44771525 8,9 C8,9.55228475 7.55228475,10 7,10 Z'%3E%3C/path%3E%3C/svg%3E\");\n background-size: calc(0.5em + 0.375rem) calc(0.5em + 0.375rem);\n background-repeat: no-repeat;\n background-position: center;\n width: 1.2rem;\n height: 1.5rem;\n z-index: 50;\n cursor: grab;\n\n &:hover {\n background-color: rgb(241 245 249); //100\n transition: background-color 0.2s;\n }\n\n &:active {\n background-color: rgb(226 232 240); //200\n transition: background-color 0.2s;\n }\n\n &.hide {\n opacity: 0;\n pointer-events: none;\n }\n\n @media screen and (max-width: 600px) {\n display: none;\n pointer-events: none;\n }\n}\n\n[data-theme=\"dark\"] .drag-handle {\n &:hover {\n background-color: rgb(51 65 85); // 700\n }\n\n &:active {\n background-color: rgb(51 65 85); // 700\n }\n}\n`;\n"],"names":["editorStore","createStore","EditorRoot","children","jsx","Provider","EditorBubble","forwardRef","tippyOptions","rest","ref","editor","useCurrentEditor","instanceRef","useRef","useEffect","bubbleMenuProps","useMemo","state","selection","empty","isNodeSelection","val","BubbleMenu","EditorBubbleItem","asChild","onSelect","Comp","Slot","t","tunnel","queryAtom","atom","rangeAtom","EditorCommandOut","query","range","setQuery","useSetAtom","setRange","navigationKeys","onKeyDown","e","commandRef","EditorCommand","className","commandListRef","useAtom","jsxs","Command","EditorCommandItem","onCommand","useAtomValue","CommandItem","EditorCommandEmpty","CommandEmpty","Extension","props","Suggestion","renderItems","component","popup","ReactRenderer","tippy","createSuggestionItems","items","PlaceholderExtension","Placeholder","node","Horizontal","HorizontalRule","InputRule","attributes","tr","start","end","TextFieldsIcon","LooksOneIcon","LooksTwoIcon","Looks3Icon","CheckBoxIcon","FormatListBulletedIcon","FormatListNumberedIcon","FormatQuoteIcon","CodeIcon","NodeSelector","open","onOpenChange","useEditor","activeItem","item","Popover","Button","ExpandMoreIcon","index","CheckIcon","isValidUrl","url","getUrlFromString","str","LinkSelector","inputRef","cn","target","input","DeleteIcon","TextButtons","FormatBoldIcon","FormatItalicIcon","FormatUnderlinedIcon","FormatStrikethroughIcon","useDebouncedCallback","value","callback","immediate","timeoutMs","pendingUpdate","React","performUpdate","handlerRef","removeClassesFromJson","jsonObj","key","placeholder","tiptapLink","TiptapLink","taskList","TaskList","taskItem","TaskItem","horizontalRule","defaultBorderMixin","starterKit","StarterKit","onFileRead","plugin","view","readerEvent","pos","upload","image","schema","decorationSet","imageElement","deco","Decoration","src","imageNode","dropImagePlugin","Plugin","DecorationSet","old","meta","event","images","file","position","reader","slice","anyImageFound","editorView","prevState","prevDecos","newDecos","createImageExtension","uploadFn","TiptapImage","CustomKeymap","commands","startNodePos","endNodePos","startSelectionPos","endSelectionPos","absoluteRect","data","nodeDOMAtCoords","coords","elem","nodePosAtDOM","options","boundingRect","DragHandle","handleDragStart","nodePos","NodeSelection","dom","text","__serializeForClipboard","handleClick","dragHandleElement","hideDragHandle","showDragHandle","compStyle","lineHeight","paddingTop","rect","DragAndDrop","FireCMSEditor","handleImageUpload","initialContent","onJsonContentChange","onHtmlContentChange","onMarkdownContentChange","defaultEditorProps","_view","suggestionItems","ImageIcon","slashCommand","imageExtension","extensions","TiptapUnderline","TextStyle","Color","Highlight","Markdown","openNode","setOpenNode","useState","openLink","setOpenLink","useInjectStyles","cssStyles","editorRef","markdownContent","setMarkdownContent","jsonContent","setJsonContent","htmlContent","setHtmlContent","onEditorUpdate","markdown","addLineBreakAfterImages","EditorProvider","Separator","imageRegex","match"],"mappings":"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"}
|
1
|
+
{"version":3,"file":"index.umd.js","sources":["../src/components/editor.tsx","../src/components/editor-bubble.tsx","../src/components/editor-bubble-item.tsx","../src/components/editor-command.tsx","../src/components/editor-command-item.tsx","../src/extensions/slash-command.tsx","../src/extensions/index.ts","../src/selectors/node-selector.tsx","../src/selectors/link-selector.tsx","../src/selectors/text-buttons.tsx","../src/utils/useDebouncedCallback.ts","../src/utils/remove_classes.ts","../src/editor_extensions.tsx","../src/extensions/Image.ts","../src/extensions/custom-keymap.ts","../src/extensions/drag-and-drop.tsx","../src/editor.tsx"],"sourcesContent":["import { type ReactNode } from \"react\";\nimport { createStore, Provider } from \"jotai\";\n\nexport const editorStore = createStore();\n\nexport const EditorRoot = ({ children }: { children: ReactNode }): JSX.Element => {\n return <Provider store={editorStore}>{children}</Provider>;\n};\n","import { BubbleMenu, type BubbleMenuProps, isNodeSelection, useCurrentEditor } from \"@tiptap/react\";\nimport { type ReactNode, useMemo, useRef, useEffect, forwardRef } from \"react\";\nimport type { Instance, Props } from \"tippy.js\";\n\nexport interface EditorBubbleProps extends Omit<BubbleMenuProps, \"editor\"> {\n children: ReactNode;\n}\n\nexport const EditorBubble = forwardRef<HTMLDivElement, EditorBubbleProps>(\n ({ children, tippyOptions, ...rest }, ref) => {\n const { editor } = useCurrentEditor();\n const instanceRef = useRef<Instance<Props> | null>(null);\n\n useEffect(() => {\n if (!instanceRef.current || !tippyOptions?.placement) return;\n\n instanceRef.current.setProps({ placement: tippyOptions.placement });\n instanceRef.current.popperInstance?.update();\n }, [tippyOptions?.placement]);\n\n const bubbleMenuProps: Omit<BubbleMenuProps, \"editor\" | \"children\"> = useMemo(() => {\n const shouldShow: BubbleMenuProps[\"shouldShow\"] = ({ editor, state }) => {\n const { selection } = state;\n const { empty } = selection;\n\n // don't show bubble menu if:\n // - the selected node is an image\n // - the selection is empty\n // - the selection is a node selection (for drag handles)\n if (editor.isActive(\"image\") || empty || isNodeSelection(selection)) {\n return false;\n }\n return true;\n };\n\n return {\n shouldShow,\n tippyOptions: {\n onCreate: (val) => {\n instanceRef.current = val;\n },\n moveTransition: \"transform 0.15s ease-out\",\n ...tippyOptions,\n },\n ...rest,\n };\n }, [rest, tippyOptions]);\n\n if (!editor) return null;\n\n return (\n //We need to add this because of https://github.com/ueberdosis/tiptap/issues/2658\n <div ref={ref}>\n <BubbleMenu editor={editor} {...bubbleMenuProps}>\n {children}\n </BubbleMenu>\n </div>\n );\n }\n);\n\nexport default EditorBubble;\n","import { type ComponentPropsWithoutRef, type ReactNode, forwardRef } from \"react\";\nimport { Slot } from \"@radix-ui/react-slot\";\nimport { useCurrentEditor, type Editor } from \"@tiptap/react\";\n\ninterface EditorBubbleItemProps {\n children: ReactNode;\n asChild?: boolean;\n onSelect?: (editor: Editor) => void;\n}\n\nexport const EditorBubbleItem = forwardRef<\n HTMLDivElement,\n EditorBubbleItemProps & Omit<ComponentPropsWithoutRef<\"div\">, \"onSelect\">\n>(({ children, asChild, onSelect, ...rest }, ref) => {\n const { editor } = useCurrentEditor();\n const Comp = asChild ? Slot : \"div\";\n\n if (!editor) return null;\n\n return (\n <Comp ref={ref} {...rest} onClick={() => onSelect?.(editor)}>\n {children}\n </Comp>\n );\n});\n\nEditorBubbleItem.displayName = \"EditorBubbleItem\";\n\nexport default EditorBubbleItem;\n","import { atom, useAtom, useSetAtom } from \"jotai\";\nimport { useEffect, useRef, type ComponentPropsWithoutRef, forwardRef } from \"react\";\nimport tunnel from \"tunnel-rat\";\nimport { editorStore } from \"./editor\";\nimport { Command } from \"cmdk\";\nimport type { Range } from \"@tiptap/core\";\n\nconst t = tunnel();\n\nexport const queryAtom = atom(\"\");\nexport const rangeAtom = atom<Range | null>(null);\n\nexport const EditorCommandOut = ({\n query,\n range,\n}: {\n query: string;\n range: Range;\n}): JSX.Element => {\n const setQuery = useSetAtom(queryAtom, { store: editorStore });\n const setRange = useSetAtom(rangeAtom, { store: editorStore });\n\n useEffect(() => {\n setQuery(query);\n }, [query, setQuery]);\n\n useEffect(() => {\n setRange(range);\n }, [range, setRange]);\n\n useEffect(() => {\n const navigationKeys = [\"ArrowUp\", \"ArrowDown\", \"Enter\"];\n const onKeyDown = (e: KeyboardEvent) => {\n if (navigationKeys.includes(e.key)) {\n e.preventDefault();\n const commandRef = document.querySelector(\"#slash-command\");\n\n if (commandRef)\n commandRef.dispatchEvent(\n new KeyboardEvent(\"keydown\", { key: e.key, cancelable: true, bubbles: true })\n );\n\n }\n };\n document.addEventListener(\"keydown\", onKeyDown);\n return () => {\n document.removeEventListener(\"keydown\", onKeyDown);\n };\n }, []);\n\n return <t.Out />;\n};\n\nexport const EditorCommand = forwardRef<HTMLDivElement, ComponentPropsWithoutRef<typeof Command>>(\n ({ children, className, ...rest }, ref) => {\n const commandListRef = useRef<HTMLDivElement>(null);\n const [query, setQuery] = useAtom(queryAtom);\n\n return (\n <t.In>\n <Command\n ref={ref}\n onKeyDown={(e) => {\n e.stopPropagation();\n }}\n id='slash-command'\n className={className}\n {...rest}>\n <Command.Input value={query} onValueChange={setQuery} style={{ display: \"none\" }} />\n <Command.List ref={commandListRef}>{children}</Command.List>\n </Command>\n </t.In>\n );\n }\n);\n","import { type ComponentPropsWithoutRef, forwardRef } from \"react\";\nimport { CommandEmpty, CommandItem } from \"cmdk\";\nimport { Editor, type Range } from \"@tiptap/core\";\nimport { useCurrentEditor } from \"@tiptap/react\";\nimport { useAtomValue } from \"jotai\";\nimport { rangeAtom } from \"./editor-command\";\n\ninterface EditorCommandItemProps {\n onCommand: ({ editor, range }: { editor: Editor; range: Range }) => void;\n}\n\nexport const EditorCommandItem = forwardRef<\n HTMLDivElement,\n EditorCommandItemProps & ComponentPropsWithoutRef<typeof CommandItem>\n>(({ children, onCommand, ...rest }, ref) => {\n const { editor } = useCurrentEditor();\n const range = useAtomValue(rangeAtom);\n\n if (!editor || !range) return null;\n\n return (\n <CommandItem ref={ref} {...rest} onSelect={() => onCommand({ editor, range })}>\n {children}\n </CommandItem>\n );\n});\n\nEditorCommandItem.displayName = \"EditorCommandItem\";\n\nexport const EditorCommandEmpty = CommandEmpty;\n\nexport default EditorCommandItem;\n","import { type Editor, type Range, Extension } from \"@tiptap/core\";\nimport Suggestion from \"@tiptap/suggestion\";\nimport { ReactRenderer } from \"@tiptap/react\";\nimport tippy from \"tippy.js\";\n\nimport { EditorCommandOut } from \"../components/editor-command\";\nimport type { ReactNode } from \"react\";\n\nconst Command = Extension.create({\n name: \"slash-command\",\n addOptions() {\n return {\n suggestion: {\n char: \"/\",\n command: ({ editor, range, props }: { editor: Editor; range: Range; props: any }) => {\n props.command({ editor, range });\n },\n },\n };\n },\n addProseMirrorPlugins() {\n return [\n Suggestion({\n editor: this.editor,\n ...this.options.suggestion,\n }),\n ];\n },\n});\n\nconst renderItems = () => {\n let component: ReactRenderer | null = null;\n let popup: any | null = null;\n\n return {\n onStart: (props: { editor: Editor; clientRect: DOMRect }) => {\n component = new ReactRenderer(EditorCommandOut, {\n props,\n editor: props.editor,\n });\n\n // @ts-ignore\n popup = tippy(\"body\", {\n getReferenceClientRect: props.clientRect,\n appendTo: () => document.body,\n content: component.element,\n showOnCreate: true,\n interactive: true,\n trigger: \"manual\",\n placement: \"bottom-start\",\n });\n },\n onUpdate: (props: { editor: Editor; clientRect: DOMRect }) => {\n component?.updateProps(props);\n\n popup &&\n popup[0].setProps({\n getReferenceClientRect: props.clientRect,\n });\n },\n\n onKeyDown: (props: { event: KeyboardEvent }) => {\n if (props.event.key === \"Escape\") {\n popup?.[0].hide();\n\n return true;\n }\n\n // @ts-ignore\n return component?.ref?.onKeyDown(props);\n },\n onExit: () => {\n popup?.[0].destroy();\n component?.destroy();\n },\n };\n};\n\nexport interface SuggestionItem {\n title: string;\n description: string;\n icon: ReactNode;\n searchTerms?: string[];\n command?: (props: { editor: Editor; range: Range }) => void;\n}\n\nexport const createSuggestionItems = (items: SuggestionItem[]) => items;\n\nexport { Command, renderItems };\n","import StarterKit from \"@tiptap/starter-kit\";\nimport HorizontalRule from \"@tiptap/extension-horizontal-rule\";\nimport TiptapLink from \"@tiptap/extension-link\";\nimport TiptapImage from \"@tiptap/extension-image\";\nimport Placeholder from \"@tiptap/extension-placeholder\";\n\nimport { TaskItem } from \"@tiptap/extension-task-item\";\nimport { TaskList } from \"@tiptap/extension-task-list\";\nimport { InputRule } from \"@tiptap/core\";\n\nconst PlaceholderExtension = Placeholder.configure({\n placeholder: ({ node }) => {\n if (node.type.name === \"heading\") {\n return `Heading ${node.attrs.level}`;\n }\n return \"Press '/' for commands\";\n },\n includeChildren: true,\n});\n\nconst Horizontal = HorizontalRule.extend({\n addInputRules() {\n return [\n new InputRule({\n find: /^(?:---|—-|___\\s|\\*\\*\\*\\s)$/,\n handler: ({ state, range }) => {\n const attributes = {};\n\n const { tr } = state;\n const start = range.from;\n const end = range.to;\n\n tr.insert(start - 1, this.type.create(attributes)).delete(\n tr.mapping.map(start),\n tr.mapping.map(end)\n );\n },\n }),\n ];\n },\n});\n\nexport {\n PlaceholderExtension as Placeholder,\n StarterKit,\n Horizontal as HorizontalRule,\n TiptapLink,\n TiptapImage,\n TaskItem,\n TaskList,\n InputRule,\n};\nexport * from \"./slash-command\";\n\nexport { getPrevText } from \"../utils/utils\";\n","import React from \"react\";\nimport { EditorBubbleItem, useEditor } from \"../components\";\n\nimport {\n Button,\n CheckBoxIcon,\n CheckIcon,\n CodeIcon,\n ExpandMoreIcon,\n FormatListBulletedIcon,\n FormatListNumberedIcon,\n FormatQuoteIcon,\n Looks3Icon,\n LooksOneIcon,\n LooksTwoIcon,\n Popover,\n TextFieldsIcon\n} from \"@firecms/ui\";\n\nexport type SelectorItem = {\n name: string;\n icon: React.ElementType;\n command: (editor: ReturnType<typeof useEditor>[\"editor\"]) => void;\n isActive: (editor: ReturnType<typeof useEditor>[\"editor\"]) => boolean;\n};\n\nconst items: SelectorItem[] = [\n {\n name: \"Text\",\n icon: TextFieldsIcon,\n command: (editor) =>\n editor?.chain().focus().toggleNode(\"paragraph\", \"paragraph\").run(),\n // I feel like there has to be a more efficient way to do this – feel free to PR if you know how!\n isActive: (editor) =>\n (editor?.isActive(\"paragraph\") &&\n !editor?.isActive(\"bulletList\") &&\n !editor?.isActive(\"orderedList\")) ?? false,\n },\n {\n name: \"Heading 1\",\n icon: LooksOneIcon,\n command: (editor) =>\n editor?.chain().focus().toggleHeading({ level: 1 }).run(),\n isActive: (editor) => editor?.isActive(\"heading\", { level: 1 }) ?? false,\n },\n {\n name: \"Heading 2\",\n icon: LooksTwoIcon,\n command: (editor) =>\n editor?.chain().focus().toggleHeading({ level: 2 }).run(),\n isActive: (editor) => editor?.isActive(\"heading\", { level: 2 }) ?? false,\n },\n {\n name: \"Heading 3\",\n icon: Looks3Icon,\n command: (editor) =>\n editor?.chain().focus().toggleHeading({ level: 3 }).run(),\n isActive: (editor) => editor?.isActive(\"heading\", { level: 3 }) ?? false,\n },\n {\n name: \"To-do List\",\n icon: CheckBoxIcon,\n command: (editor) => editor?.chain().focus().toggleTaskList().run(),\n isActive: (editor) => editor?.isActive(\"taskItem\") ?? false,\n },\n {\n name: \"Bullet List\",\n icon: FormatListBulletedIcon,\n command: (editor) => editor?.chain().focus().toggleBulletList().run(),\n isActive: (editor) => editor?.isActive(\"bulletList\") ?? false,\n },\n {\n name: \"Numbered List\",\n icon: FormatListNumberedIcon,\n command: (editor) => editor?.chain().focus().toggleOrderedList().run(),\n isActive: (editor) => editor?.isActive(\"orderedList\") ?? false,\n },\n {\n name: \"Quote\",\n icon: FormatQuoteIcon,\n command: (editor) => editor?.chain()\n .focus()\n .toggleNode(\"paragraph\", \"paragraph\")\n .toggleBlockquote()\n .run(),\n isActive: (editor) => editor?.isActive(\"blockquote\") ?? false,\n },\n {\n name: \"Code\",\n icon: CodeIcon,\n command: (editor) => editor?.chain().focus().toggleCodeBlock().run(),\n isActive: (editor) => editor?.isActive(\"codeBlock\") ?? false,\n },\n];\n\ninterface NodeSelectorProps {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n}\n\nexport const NodeSelector = ({\n open,\n onOpenChange\n }: NodeSelectorProps) => {\n const { editor } = useEditor();\n if (!editor) return null;\n const activeItem = items.filter((item) => item.isActive(editor)).pop() ?? {\n name: \"Multiple\",\n };\n\n return (\n\n <Popover\n sideOffset={5}\n align=\"start\"\n className=\"w-48 p-1\"\n trigger={<Button variant=\"text\"\n className=\"gap-2 rounded-none\"\n color=\"text\">\n <span className=\"whitespace-nowrap text-sm\">{activeItem.name}</span>\n <ExpandMoreIcon size={\"small\"}/>\n </Button>}\n modal={true}\n open={open}\n onOpenChange={onOpenChange}>\n {items.map((item, index) => (\n <EditorBubbleItem\n key={index}\n onSelect={(editor) => {\n item.command(editor);\n onOpenChange(false);\n }}\n className=\"flex cursor-pointer items-center justify-between rounded px-2 py-1 text-sm hover:bg-blue-50 hover:dark:bg-gray-700 text-gray-900 dark:text-white\"\n >\n <div className=\"flex items-center space-x-2\">\n <item.icon size=\"smallest\"/>\n <span>{item.name}</span>\n </div>\n {activeItem.name === item.name && <CheckIcon size=\"smallest\"/>}\n </EditorBubbleItem>\n ))}\n\n </Popover>\n );\n};\n","import { useEditor } from \"../components\";\nimport { useEffect, useRef, } from \"react\";\nimport { Button, CheckIcon, cls, DeleteIcon, Popover } from \"@firecms/ui\";\n\nexport function isValidUrl(url: string) {\n try {\n // eslint-disable-next-line no-new\n new URL(url);\n return true;\n } catch (e) {\n return false;\n }\n}\n\nexport function getUrlFromString(str: string) {\n if (isValidUrl(str)) return str;\n try {\n if (str.includes(\".\") && !str.includes(\" \")) {\n return new URL(`https://${str}`).toString();\n }\n return null;\n } catch (e) {\n return null;\n }\n}\n\ninterface LinkSelectorProps {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n}\n\nexport const LinkSelector = ({\n open,\n onOpenChange\n }: LinkSelectorProps) => {\n const inputRef = useRef<HTMLInputElement>(null);\n const { editor } = useEditor();\n\n // Autofocus on input by default\n useEffect(() => {\n inputRef.current && inputRef.current?.focus();\n });\n\n if (!editor) return null;\n\n return (\n <Popover modal={true}\n open={open}\n onOpenChange={onOpenChange}\n trigger={<Button variant=\"text\"\n className=\"gap-2 rounded-none\"\n color={\"text\"}>\n <p className={cls(\"underline decoration-stone-400 underline-offset-4\", {\n \"text-blue-500\": editor.isActive(\"link\"),\n })}>\n Link\n </p>\n </Button>}>\n <form\n onSubmit={(e) => {\n const target = e.currentTarget as HTMLFormElement;\n e.preventDefault();\n const input = target[0] as HTMLInputElement;\n const url = getUrlFromString(input.value);\n url && editor.chain().focus().setLink({ href: url }).run();\n }}\n className=\"flex p-1\"\n >\n <input\n ref={inputRef}\n autoFocus={open}\n placeholder=\"Paste a link\"\n defaultValue={editor.getAttributes(\"link\").href || \"\"}\n className={\"text-gray-900 dark:text-white flex-grow bg-transparent p-1 text-sm outline-none\"}/>\n\n {editor.getAttributes(\"link\").href ? (\n <Button\n size={\"small\"}\n variant=\"text\"\n type=\"button\"\n color={\"text\"}\n className=\"flex items-center\"\n onClick={() => {\n editor.chain().focus().unsetLink().run();\n }}\n >\n <DeleteIcon size=\"small\"/>\n </Button>\n ) : (\n <Button size={\"small\"}\n variant={\"text\"}>\n <CheckIcon size=\"small\"/>\n </Button>\n )}\n </form>\n </Popover>\n );\n};\n","import { EditorBubbleItem, useEditor } from \"../components\";\nimport type { SelectorItem } from \"./node-selector\";\nimport {\n Button,\n cls,\n CodeIcon,\n FormatBoldIcon,\n FormatItalicIcon,\n FormatStrikethroughIcon,\n FormatUnderlinedIcon\n} from \"@firecms/ui\";\n\nexport const TextButtons = () => {\n const { editor } = useEditor();\n if (!editor) return null;\n const items: SelectorItem[] = [\n {\n name: \"bold\",\n isActive: (editor) => editor?.isActive(\"bold\") ?? false,\n command: (editor) => editor?.chain().focus().toggleBold().run(),\n icon: FormatBoldIcon,\n },\n {\n name: \"italic\",\n isActive: (editor) => editor?.isActive(\"italic\") ?? false,\n command: (editor) => editor?.chain().focus().toggleItalic().run(),\n icon: FormatItalicIcon,\n },\n {\n name: \"underline\",\n isActive: (editor) => editor?.isActive(\"underline\") ?? false,\n command: (editor) => editor?.chain().focus().toggleUnderline().run(),\n icon: FormatUnderlinedIcon,\n },\n {\n name: \"strike\",\n isActive: (editor) => editor?.isActive(\"strike\") ?? false,\n command: (editor) => editor?.chain().focus().toggleStrike().run(),\n icon: FormatStrikethroughIcon,\n },\n {\n name: \"code\",\n isActive: (editor) => editor?.isActive(\"code\") ?? false,\n command: (editor) => editor?.chain().focus().toggleCode().run(),\n icon: CodeIcon,\n },\n ];\n return (\n <div className=\"flex\">\n {items.map((item, index) => (\n <EditorBubbleItem\n key={index}\n onSelect={(editor) => {\n item.command(editor);\n }}\n >\n <Button size={\"small\"}\n color=\"text\"\n className=\"gap-2 rounded-none h-full\"\n variant=\"text\">\n <item.icon\n className={cls( {\n \"text-inherit\": !item.isActive(editor),\n \"text-blue-500\": item.isActive(editor),\n })}\n />\n </Button>\n </EditorBubbleItem>\n ))}\n </div>\n );\n};\n","import React from \"react\";\n\nexport function useDebouncedCallback<T>(value: T, callback: () => void, immediate: boolean, timeoutMs = 300) {\n\n const pendingUpdate = React.useRef(false);\n const performUpdate = () => {\n callback();\n pendingUpdate.current = false;\n };\n\n const handlerRef = React.useRef<number | undefined>(undefined);\n\n React.useEffect(\n () => {\n pendingUpdate.current = true;\n clearTimeout(handlerRef.current);\n handlerRef.current = setTimeout(performUpdate, timeoutMs) as any;\n return () => {\n if (immediate)\n performUpdate();\n };\n },\n [immediate, value]\n );\n}\n","export function removeClassesFromJson(jsonObj: any): any {\n // If it's an array, apply the function to each element\n if (Array.isArray(jsonObj)) {\n return jsonObj.map(item => removeClassesFromJson(item));\n } else if (typeof jsonObj === \"object\" && jsonObj !== null) { // If it's an object, recurse through its properties\n // If the object has an `attrs` property and `class` field, delete the `class` field\n if (jsonObj.attrs && typeof jsonObj.attrs === \"object\" && \"class\" in jsonObj.attrs) {\n delete jsonObj.attrs.class;\n }\n\n // Apply the function recursively to object properties\n Object.keys(jsonObj).forEach(key => {\n jsonObj[key] = removeClassesFromJson(jsonObj[key]);\n });\n }\n return jsonObj;\n}\n","import { HorizontalRule, Placeholder, StarterKit, TaskItem, TaskList, TiptapImage, TiptapLink, } from \"./extensions\";\n\nimport { cls, defaultBorderMixin } from \"@firecms/ui\";\n\n//You can overwrite the placeholder with your own configuration\nexport const placeholder = Placeholder;\nexport const tiptapLink = TiptapLink.configure({\n HTMLAttributes: {\n class: cls(\n \"text-gray-600 dark:text-slate-300 underline underline-offset-[3px] hover:text-primary transition-colors cursor-pointer\",\n ),\n },\n});\n\n// export const tiptapImage = TiptapImage.extend({\n// addProseMirrorPlugins() {\n// return [UploadImagesPlugin()];\n// },\n// }).configure({\n// allowBase64: true,\n// HTMLAttributes: {\n// class: cn(\"rounded-lg border\", defaultBorderMixin),\n// },\n// });\n\n// const updatedImage = UpdatedImage.configure({\n// HTMLAttributes: {\n// class: cn(\"rounded-lg border\", defaultBorderMixin),\n// },\n// });\n\nexport const taskList = TaskList.configure({\n HTMLAttributes: {\n class: cls(\"not-prose\"),\n },\n});\nexport const taskItem = TaskItem.configure({\n HTMLAttributes: {\n class: cls(\"flex items-start my-4\"),\n },\n nested: true,\n});\n\nexport const horizontalRule = HorizontalRule.configure({\n HTMLAttributes: {\n class: cls(\"mt-4 mb-6 border-t\", defaultBorderMixin),\n },\n});\n\nexport const starterKit = StarterKit.configure({\n bulletList: {\n HTMLAttributes: {\n class: cls(\"list-disc list-outside leading-3 -mt-2\"),\n },\n },\n orderedList: {\n HTMLAttributes: {\n class: cls(\"list-decimal list-outside leading-3 -mt-2\"),\n },\n },\n listItem: {\n HTMLAttributes: {\n class: cls(\"leading-normal -mb-2\"),\n },\n },\n blockquote: {\n HTMLAttributes: {\n class: cls(\"border-l-4 border-primary\"),\n },\n },\n codeBlock: {\n HTMLAttributes: {\n class: cls(\"rounded bg-blue-50 dark:bg-gray-700 border p-5 font-mono font-medium\", defaultBorderMixin),\n },\n },\n code: {\n HTMLAttributes: {\n class: cls(\"rounded-md bg-slate-50 dark:bg-gray-700 px-1.5 py-1 font-mono font-medium\"),\n spellcheck: \"false\",\n },\n },\n horizontalRule: false,\n dropcursor: {\n color: \"#DBEAFE\",\n width: 4,\n },\n gapcursor: false,\n});\n","import { Plugin, } from \"prosemirror-state\";\nimport { TiptapImage } from \"./index\";\nimport { cls, defaultBorderMixin } from \"@firecms/ui\";\nimport { Decoration, DecorationSet, EditorView } from \"@tiptap/pm/view\";\n\nexport type UploadFn = (image: File) => Promise<string>;\n\nasync function onFileRead(plugin: Plugin, view: EditorView, readerEvent: ProgressEvent<FileReader>, pos: number, upload: UploadFn, image: File) {\n\n const { schema } = view.state;\n let decorationSet = plugin.getState(view.state);\n\n const placeholder = document.createElement(\"div\");\n const imageElement = document.createElement(\"img\");\n imageElement.setAttribute(\"class\", \"opacity-40 rounded-lg border border-stone-200\");\n imageElement.src = readerEvent.target?.result as string;\n placeholder.appendChild(imageElement);\n\n const deco = Decoration.widget(pos, placeholder);\n decorationSet = decorationSet?.add(view.state.doc, [deco]);\n view.dispatch(view.state.tr.setMeta(plugin, { decorationSet }));\n\n // Image Upload Logic\n const src = await upload(image);\n console.log(\"uploaded image\", src);\n\n // Replace placeholder with actual image\n const imageNode = schema.nodes.image.create({ src });\n const tr = view.state.tr.replaceWith(pos, pos, imageNode);\n\n // Remove placeholder decoration\n decorationSet = decorationSet?.remove([deco]);\n tr.setMeta(plugin, { decorationSet });\n view.dispatch(tr);\n}\n\nexport const dropImagePlugin = (upload: UploadFn) => {\n const plugin: Plugin = new Plugin({\n state: {\n // Initialize the plugin state with an empty DecorationSet\n init: () => DecorationSet.empty,\n // Apply transactions to update the state\n apply: (tr, old) => {\n // Handle custom transaction steps that update decorations\n const meta = tr.getMeta(plugin);\n if (meta && meta.decorationSet) {\n return meta.decorationSet;\n }\n // Map decorations to the new document structure\n return old.map(tr.mapping, tr.doc);\n }\n },\n props: {\n handleDOMEvents: {\n drop: (view, event) => {\n console.log(\"drop event\", event)\n if (!event.dataTransfer?.files || event.dataTransfer?.files.length === 0) {\n return false;\n }\n event.preventDefault();\n\n const files = Array.from(event.dataTransfer.files);\n const images = files.filter(file => /image/i.test(file.type));\n\n if (images.length === 0) return false;\n\n images.forEach(image => {\n\n const position = view.posAtCoords({ left: event.clientX, top: event.clientY });\n if (!position) return;\n\n const reader = new FileReader();\n reader.onload = async (readerEvent) => {\n await onFileRead(plugin, view, readerEvent, position.pos, upload, image);\n };\n reader.readAsDataURL(image);\n });\n\n return true;\n }\n },\n handlePaste(view, event, slice) {\n const items = Array.from(event.clipboardData?.items || []);\n const pos = view.state.selection.from;\n console.log(\"pos\", pos)\n let anyImageFound = false;\n\n items.forEach((item) => {\n const image = item.getAsFile();\n console.log(\"image\", image);\n if (image) {\n anyImageFound = true;\n // if (item.type.indexOf(\"image\") === 0) {\n // event.preventDefault();\n //\n // if (upload && image) {\n // upload(image).then((src) => {\n // const node = schema.nodes.image.create({\n // src\n // });\n // const transaction = view.state.tr.replaceSelectionWith(node);\n // view.dispatch(transaction);\n // });\n // }\n // } else {\n const reader = new FileReader();\n\n reader.onload = async (readerEvent) => {\n await onFileRead(plugin, view, readerEvent, pos, upload, image);\n };\n reader.readAsDataURL(image);\n }\n });\n\n return anyImageFound;\n },\n decorations(state) {\n return plugin.getState(state);\n }\n },\n view(editorView) {\n // This is needed to immediately apply the decoration updates\n return {\n update(view, prevState) {\n const prevDecos = plugin.getState(prevState);\n const newDecos = plugin.getState(view.state);\n\n if (prevDecos !== newDecos) {\n view.updateState(view.state);\n }\n }\n };\n }\n });\n return plugin;\n};\n\n/**\n * Matches following attributes in Markdown-typed image: [, alt, src, title]\n *\n * Example:\n *  -> [, \"Lorem\", \"image.jpg\"]\n *  -> [, \"\", \"image.jpg\", \"Ipsum\"]\n *  -> [, \"Lorem\", \"image.jpg\", \"Ipsum\"]\n */\nconst IMAGE_INPUT_REGEX = /!\\[(.+|:?)\\]\\((\\S+)(?:(?:\\s+)[\"'](\\S+)[\"'])?\\)/;\n\nexport const createImageExtension = (uploadFn: UploadFn) => {\n return TiptapImage.extend({\n addProseMirrorPlugins() {\n return [dropImagePlugin(uploadFn)];\n }\n }).configure({\n allowBase64: true,\n HTMLAttributes: {\n class: cls(\"rounded-lg border\", defaultBorderMixin)\n }\n });\n};\n","import { Extension } from \"@tiptap/core\";\n\ndeclare module \"@tiptap/core\" {\n // eslint-disable-next-line no-unused-vars\n interface Commands<ReturnType> {\n customkeymap: {\n /**\n * Select text between node boundaries\n */\n selectTextWithinNodeBoundaries: () => ReturnType;\n };\n }\n}\n\nexport const CustomKeymap = Extension.create({\n name: \"CustomKeymap\",\n\n addCommands() {\n return {\n selectTextWithinNodeBoundaries:\n () =>\n ({ editor, commands }) => {\n const { state } = editor;\n const { tr } = state;\n const startNodePos = tr.selection.$from.start();\n const endNodePos = tr.selection.$to.end();\n return commands.setTextSelection({\n from: startNodePos,\n to: endNodePos,\n });\n },\n };\n },\n\n addKeyboardShortcuts() {\n return {\n \"Mod-a\": ({ editor }) => {\n const { state } = editor;\n const { tr } = state;\n const startSelectionPos = tr.selection.from;\n const endSelectionPos = tr.selection.to;\n const startNodePos = tr.selection.$from.start();\n const endNodePos = tr.selection.$to.end();\n const isCurrentTextSelectionNotExtendedToNodeBoundaries =\n startSelectionPos > startNodePos || endSelectionPos < endNodePos;\n if (isCurrentTextSelectionNotExtendedToNodeBoundaries) {\n editor.chain().selectTextWithinNodeBoundaries().run();\n return true;\n }\n return false;\n },\n };\n },\n});\n\n","import { Extension } from \"@tiptap/core\";\n\nimport { NodeSelection, Plugin } from \"@tiptap/pm/state\";\n// @ts-ignore\nimport { __serializeForClipboard, EditorView } from \"@tiptap/pm/view\";\n\nexport interface DragHandleOptions {\n /**\n * The width of the drag handle\n */\n dragHandleWidth: number;\n}\nfunction absoluteRect(node: Element) {\n const data = node.getBoundingClientRect();\n\n return {\n top: data.top,\n left: data.left,\n width: data.width,\n };\n}\n\nfunction nodeDOMAtCoords(coords: { x: number; y: number }) {\n return document\n .elementsFromPoint(coords.x, coords.y)\n .find(\n (elem: Element) =>\n elem.parentElement?.matches?.(\".ProseMirror\") ||\n elem.matches(\n [\"li\", \"p:not(:first-child)\", \"pre\", \"blockquote\", \"h1, h2, h3, h4, h5, h6\"].join(\", \")\n )\n );\n}\n\nfunction nodePosAtDOM(node: Element, view: EditorView, options: DragHandleOptions) {\n const boundingRect = node.getBoundingClientRect();\n\n return view.posAtCoords({\n left: boundingRect.left + 50 + options.dragHandleWidth,\n top: boundingRect.top + 1,\n })?.inside;\n}\n\nfunction DragHandle(options: DragHandleOptions) {\n function handleDragStart(event: DragEvent, view: EditorView) {\n view.focus();\n\n if (!event.dataTransfer) return;\n\n const node = nodeDOMAtCoords({\n x: event.clientX + 50 + options.dragHandleWidth,\n y: event.clientY,\n });\n\n if (!(node instanceof Element)) return;\n\n const nodePos = nodePosAtDOM(node, view, options);\n if (nodePos == null || nodePos < 0) return;\n\n view.dispatch(view.state.tr.setSelection(NodeSelection.create(view.state.doc, nodePos)));\n\n const slice = view.state.selection.content();\n const { dom, text } = __serializeForClipboard(view, slice);\n\n event.dataTransfer.clearData();\n event.dataTransfer.setData(\"text/html\", dom.innerHTML);\n event.dataTransfer.setData(\"text/plain\", text);\n event.dataTransfer.effectAllowed = \"copyMove\";\n\n event.dataTransfer.setDragImage(node, 0, 0);\n\n view.dragging = { slice, move: event.ctrlKey };\n }\n\n function handleClick(event: MouseEvent, view: EditorView) {\n view.focus();\n\n view.dom.classList.remove(\"dragging\");\n\n const node = nodeDOMAtCoords({\n x: event.clientX + 50 + options.dragHandleWidth,\n y: event.clientY,\n });\n\n if (!(node instanceof Element)) return;\n\n const nodePos = nodePosAtDOM(node, view, options);\n if (!nodePos) return;\n\n view.dispatch(view.state.tr.setSelection(NodeSelection.create(view.state.doc, nodePos)));\n }\n\n let dragHandleElement: HTMLElement | null = null;\n\n function hideDragHandle() {\n if (dragHandleElement) {\n dragHandleElement.classList.add(\"hide\");\n }\n }\n\n function showDragHandle() {\n if (dragHandleElement) {\n dragHandleElement.classList.remove(\"hide\");\n }\n }\n\n return new Plugin({\n view: (view) => {\n dragHandleElement = document.createElement(\"div\");\n dragHandleElement.draggable = true;\n dragHandleElement.dataset.dragHandle = \"\";\n dragHandleElement.classList.add(\"drag-handle\");\n dragHandleElement.addEventListener(\"dragstart\", (e) => {\n handleDragStart(e, view);\n });\n dragHandleElement.addEventListener(\"click\", (e) => {\n handleClick(e, view);\n });\n\n hideDragHandle();\n\n view?.dom?.parentElement?.appendChild(dragHandleElement);\n\n return {\n destroy: () => {\n dragHandleElement?.remove?.();\n dragHandleElement = null;\n },\n };\n },\n props: {\n handleDOMEvents: {\n mousemove: (view, event) => {\n if (!view.editable) {\n return;\n }\n\n const node = nodeDOMAtCoords({\n x: event.clientX + 50 + options.dragHandleWidth,\n y: event.clientY,\n });\n\n if (!(node instanceof Element)) {\n hideDragHandle();\n return;\n }\n\n const compStyle = window.getComputedStyle(node);\n const lineHeight = parseInt(compStyle.lineHeight, 10);\n const paddingTop = parseInt(compStyle.paddingTop, 10);\n\n const rect = absoluteRect(node);\n\n rect.top += (lineHeight - 24) / 2;\n rect.top += paddingTop;\n // Li markers\n if (node.matches(\"ul:not([data-type=taskList]) li, ol li\")) {\n rect.left -= options.dragHandleWidth;\n }\n rect.width = options.dragHandleWidth;\n\n if (!dragHandleElement) return;\n\n dragHandleElement.style.left = `${rect.left - rect.width}px`;\n dragHandleElement.style.top = `${rect.top}px`;\n showDragHandle();\n },\n keydown: () => {\n hideDragHandle();\n },\n mousewheel: () => {\n hideDragHandle();\n },\n // dragging class is used for CSS\n dragstart: (view) => {\n view.dom.classList.add(\"dragging\");\n },\n drop: (view) => {\n view.dom.classList.remove(\"dragging\");\n },\n dragend: (view) => {\n view.dom.classList.remove(\"dragging\");\n },\n },\n },\n });\n}\n\nexport const DragAndDrop = Extension.create({\n name: \"dragAndDrop\",\n\n addProseMirrorPlugins() {\n return [\n DragHandle({\n dragHandleWidth: 24,\n }),\n ];\n },\n});\n\n","\"use client\";\nimport React, { useMemo, useState } from \"react\";\n\nimport TiptapUnderline from \"@tiptap/extension-underline\";\nimport TextStyle from \"@tiptap/extension-text-style\";\nimport { Color } from \"@tiptap/extension-color\";\n\nimport { Markdown } from \"tiptap-markdown\";\nimport Highlight from \"@tiptap/extension-highlight\";\n\nimport {\n EditorBubble,\n EditorCommand,\n EditorCommandEmpty,\n EditorCommandItem,\n EditorRoot,\n type JSONContent\n} from \"./components\";\nimport { Command, createSuggestionItems, renderItems } from \"./extensions\";\n\nimport { NodeSelector } from \"./selectors/node-selector\";\nimport { LinkSelector } from \"./selectors/link-selector\";\nimport { TextButtons } from \"./selectors/text-buttons\";\n\nimport {\n CheckBoxIcon,\n cls,\n CodeIcon,\n defaultBorderMixin,\n FormatListBulletedIcon,\n FormatListNumberedIcon,\n FormatQuoteIcon,\n ImageIcon,\n Looks3Icon,\n LooksOneIcon,\n LooksTwoIcon,\n Separator,\n TextFieldsIcon,\n useInjectStyles\n} from \"@firecms/ui\";\n// import { startImageUpload } from \"./plugins\";\nimport { Editor, EditorProvider, EditorProviderProps } from \"@tiptap/react\";\nimport { useDebouncedCallback } from \"./utils/useDebouncedCallback\";\nimport { removeClassesFromJson } from \"./utils/remove_classes\";\nimport { horizontalRule, placeholder, starterKit, taskItem, taskList, tiptapLink } from \"./editor_extensions\";\nimport { createImageExtension } from \"./extensions/Image\";\nimport { CustomKeymap } from \"./extensions/custom-keymap\";\nimport { DragAndDrop } from \"./extensions/drag-and-drop\";\n\nexport type FireCMSEditorProps = {\n initialContent?: JSONContent | string,\n onMarkdownContentChange?: (content: string) => void,\n onJsonContentChange?: (content: JSONContent | null) => void,\n onHtmlContentChange?: (content: string) => void,\n handleImageUpload: (file: File) => Promise<string>\n};\n\nexport const FireCMSEditor = ({\n handleImageUpload,\n initialContent,\n onJsonContentChange,\n onHtmlContentChange,\n onMarkdownContentChange\n }: FireCMSEditorProps) => {\n\n const defaultEditorProps: EditorProviderProps[\"editorProps\"] = {\n handleDOMEvents: {\n keydown: (_view, event) => {\n // prevent default event listeners from firing when slash command is active\n if ([\"ArrowUp\", \"ArrowDown\", \"Enter\"].includes(event.key)) {\n const slashCommand = document.querySelector(\"#slash-command\");\n if (slashCommand) {\n return true;\n }\n }\n return false;\n }\n },\n // handlePaste: (view, event) => {\n // if (event.clipboardData && event.clipboardData.files && event.clipboardData.files[0]) {\n // event.preventDefault();\n // const file = event.clipboardData.files[0];\n // const pos = view.state.selection.from;\n //\n // // startImageUpload({ file, view, pos, handleImageUpload });\n // return true;\n // }\n // return false;\n // },\n // handleDrop: (view, event, _slice, moved) => {\n // console.log(\"handleDrop\", { event, moved });\n // if (!moved && event.dataTransfer && event.dataTransfer.files && event.dataTransfer.files[0]) {\n // console.log(\"handleDrop!!!\", { event, moved });\n // event.preventDefault();\n // const file = event.dataTransfer.files[0];\n // const coordinates = view.posAtCoords({\n // left: event.clientX,\n // top: event.clientY\n // });\n // // here we deduct 1 from the pos or else the image will create an extra node\n // startImageUpload({\n // file,\n // view,\n // pos: coordinates?.pos || 0 - 1,\n // handleImageUpload,\n // });\n // return true;\n // }\n // return false;\n // }\n };\n\n const suggestionItems = createSuggestionItems([\n {\n title: \"Text\",\n description: \"Just start typing with plain text.\",\n searchTerms: [\"p\", \"paragraph\"],\n icon: <TextFieldsIcon size={18}/>,\n command: ({ editor, range }) => {\n editor\n .chain()\n .focus()\n .deleteRange(range)\n .toggleNode(\"paragraph\", \"paragraph\")\n .run();\n }\n },\n {\n title: \"To-do List\",\n description: \"Track tasks with a to-do list.\",\n searchTerms: [\"todo\", \"task\", \"list\", \"check\", \"checkbox\"],\n icon: <CheckBoxIcon size={18}/>,\n command: ({ editor, range }) => {\n editor.chain().focus().deleteRange(range).toggleTaskList().run();\n }\n },\n {\n title: \"Heading 1\",\n description: \"Big section heading.\",\n searchTerms: [\"title\", \"big\", \"large\"],\n icon: <LooksOneIcon size={18}/>,\n command: ({ editor, range }) => {\n editor\n .chain()\n .focus()\n .deleteRange(range)\n .setNode(\"heading\", { level: 1 })\n .run();\n }\n },\n {\n title: \"Heading 2\",\n description: \"Medium section heading.\",\n searchTerms: [\"subtitle\", \"medium\"],\n icon: <LooksTwoIcon size={18}/>,\n command: ({ editor, range }) => {\n editor\n .chain()\n .focus()\n .deleteRange(range)\n .setNode(\"heading\", { level: 2 })\n .run();\n }\n },\n {\n title: \"Heading 3\",\n description: \"Small section heading.\",\n searchTerms: [\"subtitle\", \"small\"],\n icon: <Looks3Icon size={18}/>,\n command: ({ editor, range }) => {\n editor\n .chain()\n .focus()\n .deleteRange(range)\n .setNode(\"heading\", { level: 3 })\n .run();\n }\n },\n {\n title: \"Bullet List\",\n description: \"Create a simple bullet list.\",\n searchTerms: [\"unordered\", \"point\"],\n icon: <FormatListBulletedIcon size={18}/>,\n command: ({ editor, range }) => {\n editor.chain().focus().deleteRange(range).toggleBulletList().run();\n }\n },\n {\n title: \"Numbered List\",\n description: \"Create a list with numbering.\",\n searchTerms: [\"ordered\"],\n icon: <FormatListNumberedIcon size={18}/>,\n command: ({ editor, range }) => {\n editor.chain().focus().deleteRange(range).toggleOrderedList().run();\n }\n },\n {\n title: \"Quote\",\n description: \"Capture a quote.\",\n searchTerms: [\"blockquote\"],\n icon: <FormatQuoteIcon size={18}/>,\n command: ({ editor, range }) =>\n editor\n .chain()\n .focus()\n .deleteRange(range)\n .toggleNode(\"paragraph\", \"paragraph\")\n .toggleBlockquote()\n .run()\n },\n {\n title: \"Code\",\n description: \"Capture a code snippet.\",\n searchTerms: [\"codeblock\"],\n icon: <CodeIcon size={18}/>,\n command: ({ editor, range }) =>\n editor.chain().focus().deleteRange(range).toggleCodeBlock().run()\n },\n {\n title: \"Image\",\n description: \"Upload an image from your computer.\",\n searchTerms: [\"photo\", \"picture\", \"media\"],\n icon: <ImageIcon size={18}/>,\n command: ({ editor, range }) => {\n editor.chain().focus().deleteRange(range).run();\n // upload image\n const input = document.createElement(\"input\");\n input.type = \"file\";\n input.accept = \"image/*\";\n input.onchange = async () => {\n if (input.files?.length) {\n const file = input.files[0];\n if (!file) return;\n const pos = editor.view.state.selection.from;\n // startImageUpload({\n // file,\n // view: editor.view,\n // pos,\n // handleImageUpload\n // });\n }\n };\n input.click();\n }\n }\n ]);\n\n const slashCommand = Command.configure({\n suggestion: {\n items: () => suggestionItems,\n render: renderItems\n }\n });\n\n const imageExtension = useMemo(() => createImageExtension(handleImageUpload), []);\n\n const extensions = [\n TiptapUnderline,\n TextStyle,\n Color,\n Highlight.configure({\n multicolor: true,\n }),\n Markdown.configure({\n html: false,\n transformCopiedText: true,\n }),\n CustomKeymap,\n DragAndDrop,\n starterKit,\n placeholder,\n tiptapLink,\n // tiptapImage,\n imageExtension,\n // updatedImage,\n taskList,\n taskItem,\n horizontalRule,\n slashCommand];\n const [openNode, setOpenNode] = useState(false);\n const [openLink, setOpenLink] = useState(false);\n\n useInjectStyles(\"Editor\", cssStyles);\n\n const editorRef = React.useRef<Editor | null>(null);\n const [markdownContent, setMarkdownContent] = useState<string | null>(null);\n const [jsonContent, setJsonContent] = useState<JSONContent | null>(null);\n const [htmlContent, setHtmlContent] = useState<string | null>(null);\n\n const onEditorUpdate = (editor: Editor) => {\n editorRef.current = editor;\n if (onMarkdownContentChange) {\n setMarkdownContent(editor.storage.markdown.getMarkdown());\n }\n if (onJsonContentChange) {\n setJsonContent(removeClassesFromJson(editor.getJSON()));\n }\n if (onHtmlContentChange) {\n setHtmlContent(editor.getHTML());\n }\n }\n\n useDebouncedCallback(markdownContent, () => {\n\n if (editorRef.current) {\n const markdown = editorRef.current.storage.markdown.getMarkdown();\n onMarkdownContentChange?.(addLineBreakAfterImages(markdown));\n }\n }, false, 500);\n\n useDebouncedCallback(jsonContent, () => {\n if (jsonContent)\n onJsonContentChange?.(jsonContent);\n }, false, 500);\n\n useDebouncedCallback(htmlContent, () => {\n if (htmlContent)\n onHtmlContentChange?.(htmlContent);\n }, false, 500);\n\n if (!initialContent) return null;\n\n return (\n <div className=\"relative w-full p-8\">\n <EditorRoot>\n <div\n className=\"relative min-h-[500px] w-full bg-white dark:bg-gray-950 rounded-lg\">\n <EditorProvider\n content={initialContent}\n extensions={extensions}\n editorProps={{\n ...defaultEditorProps,\n attributes: {\n class: \"prose-lg prose-headings:font-title font-default focus:outline-none max-w-full p-12\"\n }\n }}\n onUpdate={({ editor }) => {\n console.debug(\"Editor updated\");\n onEditorUpdate(editor as Editor);\n }}>\n\n <EditorCommand\n className={cls(\"text-gray-900 dark:text-white z-50 h-auto max-h-[330px] w-72 overflow-y-auto rounded-md border bg-white dark:bg-gray-900 px-1 py-2 shadow transition-all\", defaultBorderMixin)}>\n <EditorCommandEmpty className=\"px-2 text-gray-700 dark:text-slate-300\">\n No results\n </EditorCommandEmpty>\n {suggestionItems.map((item) => (\n <EditorCommandItem\n value={item.title}\n onCommand={(val) => item?.command?.(val)}\n className={\"flex w-full items-center space-x-2 rounded-md px-2 py-1 text-left text-sm hover:bg-blue-50 hover:dark:bg-gray-700 aria-selected:bg-blue-50 aria-selected:dark:bg-gray-700\"}\n key={item.title}\n >\n <div\n className={cls(\"flex h-10 w-10 items-center justify-center rounded-md border bg-white dark:bg-gray-900\", defaultBorderMixin)}>\n {item.icon}\n </div>\n <div>\n <p className=\"font-medium\">{item.title}</p>\n <p className=\"text-xs text-gray-700 dark:text-slate-300\">\n {item.description}\n </p>\n </div>\n </EditorCommandItem>\n ))}\n </EditorCommand>\n\n <EditorBubble\n tippyOptions={{\n placement: \"top\"\n }}\n className={cls(\"flex w-fit max-w-[90vw] h-10 overflow-hidden rounded border bg-white dark:bg-gray-900 shadow\", defaultBorderMixin)}\n >\n {/*<Separator orientation=\"vertical\"/>*/}\n <NodeSelector open={openNode} onOpenChange={setOpenNode}/>\n <Separator orientation=\"vertical\"/>\n\n <LinkSelector open={openLink} onOpenChange={setOpenLink}/>\n <Separator orientation=\"vertical\"/>\n <TextButtons/>\n {/*<Separator orientation=\"vertical\"/>*/}\n {/*<ColorSelector open={openColor} onOpenChange={setOpenColor}/>*/}\n </EditorBubble>\n\n </EditorProvider>\n </div>\n\n </EditorRoot>\n </div>\n );\n};\n\nfunction addLineBreakAfterImages(markdown: string): string {\n // Regular expression to match markdown image syntax\n const imageRegex = /!\\[.*?\\]\\(.*?\\)/g;\n // Replace image with image followed by a line break\n return markdown.replace(imageRegex, (match) => `${match}\\n`);\n}\n\nconst cssStyles = `\n\n.ProseMirror .is-editor-empty:first-child::before {\n content: attr(data-placeholder);\n float: left;\n color: rgb(100 116 139); //500\n pointer-events: none;\n height: 0;\n}\n.ProseMirror .is-empty::before {\n content: attr(data-placeholder);\n float: left;\n color: rgb(100 116 139); //500\n pointer-events: none;\n height: 0;\n}\n\n[data-theme=\"dark\"] {\n .ProseMirror .is-empty::before {\n color: rgb(100 116 139); //500\n }\n}\n\n.is-empty {\n color: rgb(100 116 139); //500\n}\n\n\n/* Custom image styles */\n\n.ProseMirror img {\n transition: filter 0.1s ease-in-out;\n\n &:hover {\n cursor: pointer;\n filter: brightness(90%);\n }\n\n &.ProseMirror-selectednode {\n outline: 3px solid #5abbf7;\n filter: brightness(90%);\n }\n}\n\n/* Custom TODO list checkboxes – shoutout to this awesome tutorial: https://moderncss.dev/pure-css-custom-checkbox-style/ */\n\nul[data-type=\"taskList\"] li > label {\n margin-right: 0.2rem;\n user-select: none;\n}\n\n@media screen and (max-width: 768px) {\n ul[data-type=\"taskList\"] li > label {\n margin-right: 0.5rem;\n }\n}\n\n\n[data-theme=\"dark\"] {\n ul[data-type=\"taskList\"] li > label input[type=\"checkbox\"] {\n background-color: rgb(30 41 59); // 800\n border: 2px solid #666;\n \n &:hover {\n background-color: rgb(51 65 85); // 700\n }\n \n &:active {\n background-color: rgb(71 85 105);;\n }\n }\n}\n \n\nul[data-type=\"taskList\"] li > label input[type=\"checkbox\"] {\n -webkit-appearance: none;\n appearance: none;\n background-color: white;\n margin: 0;\n cursor: pointer;\n width: 1.2em;\n height: 1.2em;\n position: relative;\n top: 5px;\n border: 2px solid #777;\n border-radius: 0.25em;\n margin-right: 0.3rem;\n display: grid;\n place-content: center;\n\n &:hover {\n background-color: rgb(241 245 249); //100\n }\n\n &:active {\n background-color: rgb(226 232 240); //200\n }\n\n &::before {\n content: \"\";\n width: 0.65em;\n height: 0.65em;\n transform: scale(0);\n transition: 120ms transform ease-in-out;\n box-shadow: inset 1em 1em;\n transform-origin: center;\n clip-path: polygon(14% 44%, 0 65%, 50% 100%, 100% 16%, 80% 0%, 43% 62%);\n }\n\n &:checked::before {\n transform: scale(1);\n }\n}\n\n[data-theme=\"dark\"] {\n ul[data-type=\"taskList\"] li[data-checked=\"true\"] > div > p {\n color: rgb(226 232 240);\n text-decoration: line-through;\n text-decoration-thickness: 2px;\n }\n}\n\nul[data-type=\"taskList\"] li[data-checked=\"true\"] > div > p {\n color: rgb(51 65 85); // 700\n text-decoration: line-through;\n text-decoration-thickness: 2px;\n}\n\n/* Overwrite tippy-box original max-width */\n\n.tippy-box {\n max-width: 400px !important;\n}\n\n.ProseMirror:not(.dragging) .ProseMirror-selectednode {\n outline: none !important;\n background-color: rgb(219 234 254); // blue 100\n transition: background-color 0.2s;\n box-shadow: none;\n}\n\n[data-theme=\"dark\"] .ProseMirror:not(.dragging) .ProseMirror-selectednode {\n background-color: rgb(51 65 85); // 700\n}\n\n.drag-handle {\n position: fixed;\n opacity: 1;\n transition: opacity ease-in 0.2s;\n border-radius: 0.25rem;\n\n background-image: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 10' style='fill: rgba(128, 128, 128, 0.9)'%3E%3Cpath d='M3,2 C2.44771525,2 2,1.55228475 2,1 C2,0.44771525 2.44771525,0 3,0 C3.55228475,0 4,0.44771525 4,1 C4,1.55228475 3.55228475,2 3,2 Z M3,6 C2.44771525,6 2,5.55228475 2,5 C2,4.44771525 2.44771525,4 3,4 C3.55228475,4 4,4.44771525 4,5 C4,5.55228475 3.55228475,6 3,6 Z M3,10 C2.44771525,10 2,9.55228475 2,9 C2,8.44771525 2.44771525,8 3,8 C3.55228475,8 4,8.44771525 4,9 C4,9.55228475 3.55228475,10 3,10 Z M7,2 C6.44771525,2 6,1.55228475 6,1 C6,0.44771525 6.44771525,0 7,0 C7.55228475,0 8,0.44771525 8,1 C8,1.55228475 7.55228475,2 7,2 Z M7,6 C6.44771525,6 6,5.55228475 6,5 C6,4.44771525 6.44771525,4 7,4 C7.55228475,4 8,4.44771525 8,5 C8,5.55228475 7.55228475,6 7,6 Z M7,10 C6.44771525,10 6,9.55228475 6,9 C6,8.44771525 6.44771525,8 7,8 C7.55228475,8 8,8.44771525 8,9 C8,9.55228475 7.55228475,10 7,10 Z'%3E%3C/path%3E%3C/svg%3E\");\n background-size: calc(0.5em + 0.375rem) calc(0.5em + 0.375rem);\n background-repeat: no-repeat;\n background-position: center;\n width: 1.2rem;\n height: 1.5rem;\n z-index: 50;\n cursor: grab;\n\n &:hover {\n background-color: rgb(241 245 249); //100\n transition: background-color 0.2s;\n }\n\n &:active {\n background-color: rgb(226 232 240); //200\n transition: background-color 0.2s;\n }\n\n &.hide {\n opacity: 0;\n pointer-events: none;\n }\n\n @media screen and (max-width: 600px) {\n display: none;\n pointer-events: none;\n }\n}\n\n[data-theme=\"dark\"] .drag-handle {\n &:hover {\n background-color: rgb(51 65 85); // 700\n }\n\n &:active {\n background-color: rgb(51 65 85); // 700\n }\n}\n`;\n"],"names":["editorStore","createStore","EditorRoot","children","jsx","Provider","EditorBubble","forwardRef","tippyOptions","rest","ref","editor","useCurrentEditor","instanceRef","useRef","useEffect","bubbleMenuProps","useMemo","state","selection","empty","isNodeSelection","val","BubbleMenu","EditorBubbleItem","asChild","onSelect","Comp","Slot","t","tunnel","queryAtom","atom","rangeAtom","EditorCommandOut","query","range","setQuery","useSetAtom","setRange","navigationKeys","onKeyDown","e","commandRef","EditorCommand","className","commandListRef","useAtom","jsxs","Command","EditorCommandItem","onCommand","useAtomValue","CommandItem","EditorCommandEmpty","CommandEmpty","Extension","props","Suggestion","renderItems","component","popup","ReactRenderer","tippy","createSuggestionItems","items","PlaceholderExtension","Placeholder","node","Horizontal","HorizontalRule","InputRule","attributes","tr","start","end","TextFieldsIcon","LooksOneIcon","LooksTwoIcon","Looks3Icon","CheckBoxIcon","FormatListBulletedIcon","FormatListNumberedIcon","FormatQuoteIcon","CodeIcon","NodeSelector","open","onOpenChange","useEditor","activeItem","item","Popover","Button","ExpandMoreIcon","index","CheckIcon","isValidUrl","url","getUrlFromString","str","LinkSelector","inputRef","cls","target","input","DeleteIcon","TextButtons","FormatBoldIcon","FormatItalicIcon","FormatUnderlinedIcon","FormatStrikethroughIcon","useDebouncedCallback","value","callback","immediate","timeoutMs","pendingUpdate","React","performUpdate","handlerRef","removeClassesFromJson","jsonObj","key","placeholder","tiptapLink","TiptapLink","taskList","TaskList","taskItem","TaskItem","horizontalRule","defaultBorderMixin","starterKit","StarterKit","onFileRead","plugin","view","readerEvent","pos","upload","image","schema","decorationSet","imageElement","deco","Decoration","src","imageNode","dropImagePlugin","Plugin","DecorationSet","old","meta","event","images","file","position","reader","slice","anyImageFound","editorView","prevState","prevDecos","newDecos","createImageExtension","uploadFn","TiptapImage","CustomKeymap","commands","startNodePos","endNodePos","startSelectionPos","endSelectionPos","absoluteRect","data","nodeDOMAtCoords","coords","elem","nodePosAtDOM","options","boundingRect","DragHandle","handleDragStart","nodePos","NodeSelection","dom","text","__serializeForClipboard","handleClick","dragHandleElement","hideDragHandle","showDragHandle","compStyle","lineHeight","paddingTop","rect","DragAndDrop","FireCMSEditor","handleImageUpload","initialContent","onJsonContentChange","onHtmlContentChange","onMarkdownContentChange","defaultEditorProps","_view","suggestionItems","ImageIcon","slashCommand","imageExtension","extensions","TiptapUnderline","TextStyle","Color","Highlight","Markdown","openNode","setOpenNode","useState","openLink","setOpenLink","useInjectStyles","cssStyles","editorRef","markdownContent","setMarkdownContent","jsonContent","setJsonContent","htmlContent","setHtmlContent","onEditorUpdate","markdown","addLineBreakAfterImages","EditorProvider","Separator","imageRegex","match"],"mappings":"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"}
|
package/dist/utils/utils.d.ts
CHANGED
@@ -3,5 +3,5 @@ export declare function isValidUrl(url: string): boolean;
|
|
3
3
|
export declare function getUrlFromString(str: string): string | null;
|
4
4
|
export declare const getPrevText: (editor: Editor, { chars, offset, }: {
|
5
5
|
chars: number;
|
6
|
-
offset?: number
|
6
|
+
offset?: number;
|
7
7
|
}) => string;
|
package/package.json
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
{
|
2
2
|
"name": "@firecms/editor",
|
3
|
-
"version": "3.0.0-canary.
|
3
|
+
"version": "3.0.0-canary.80",
|
4
4
|
"description": "Notion-style WYSIWYG editor for FireCMS",
|
5
5
|
"license": "Apache-2.0",
|
6
6
|
"type": "module",
|
7
7
|
"main": "dist/index.cjs",
|
8
8
|
"module": "dist/index.js",
|
9
|
-
"types": "dist/
|
9
|
+
"types": "dist/index.d.ts",
|
10
10
|
"publishConfig": {
|
11
11
|
"access": "public"
|
12
12
|
},
|
@@ -16,8 +16,8 @@
|
|
16
16
|
"exports": {
|
17
17
|
".": {
|
18
18
|
"types": "./dist/index.d.ts",
|
19
|
-
"import": "./dist/index.
|
20
|
-
"require": "./dist/index.
|
19
|
+
"import": "./dist/index.es.js",
|
20
|
+
"require": "./dist/index.umd.js"
|
21
21
|
}
|
22
22
|
},
|
23
23
|
"scripts": {
|
@@ -30,37 +30,37 @@
|
|
30
30
|
"react-dom": "^18.0.0"
|
31
31
|
},
|
32
32
|
"dependencies": {
|
33
|
-
"@firecms/ui": "^3.0.0-canary.
|
34
|
-
"@radix-ui/react-slot": "^1.0
|
35
|
-
"@tiptap/core": "^2.
|
36
|
-
"@tiptap/extension-color": "^2.
|
37
|
-
"@tiptap/extension-highlight": "^2.
|
38
|
-
"@tiptap/extension-horizontal-rule": "^2.
|
39
|
-
"@tiptap/extension-image": "^2.
|
40
|
-
"@tiptap/extension-link": "^2.
|
41
|
-
"@tiptap/extension-placeholder": "2.
|
42
|
-
"@tiptap/extension-task-item": "^2.
|
43
|
-
"@tiptap/extension-task-list": "^2.
|
44
|
-
"@tiptap/extension-text-style": "^2.
|
45
|
-
"@tiptap/extension-underline": "^2.
|
46
|
-
"@tiptap/pm": "^2.
|
47
|
-
"@tiptap/react": "^2.
|
48
|
-
"@tiptap/starter-kit": "^2.
|
49
|
-
"@tiptap/suggestion": "^2.
|
50
|
-
"@types/node": "
|
33
|
+
"@firecms/ui": "^3.0.0-canary.80",
|
34
|
+
"@radix-ui/react-slot": "^1.1.0",
|
35
|
+
"@tiptap/core": "^2.4.0",
|
36
|
+
"@tiptap/extension-color": "^2.4.0",
|
37
|
+
"@tiptap/extension-highlight": "^2.4.0",
|
38
|
+
"@tiptap/extension-horizontal-rule": "^2.4.0",
|
39
|
+
"@tiptap/extension-image": "^2.4.0",
|
40
|
+
"@tiptap/extension-link": "^2.4.0",
|
41
|
+
"@tiptap/extension-placeholder": "2.4.0",
|
42
|
+
"@tiptap/extension-task-item": "^2.4.0",
|
43
|
+
"@tiptap/extension-task-list": "^2.4.0",
|
44
|
+
"@tiptap/extension-text-style": "^2.4.0",
|
45
|
+
"@tiptap/extension-underline": "^2.4.0",
|
46
|
+
"@tiptap/pm": "^2.4.0",
|
47
|
+
"@tiptap/react": "^2.4.0",
|
48
|
+
"@tiptap/starter-kit": "^2.4.0",
|
49
|
+
"@tiptap/suggestion": "^2.4.0",
|
50
|
+
"@types/node": "20.14.9",
|
51
51
|
"cmdk": "^0.2.1",
|
52
|
-
"jotai": "^2.
|
52
|
+
"jotai": "^2.8.0",
|
53
53
|
"react-markdown": "^9.0.1",
|
54
54
|
"react-moveable": "^0.56.0",
|
55
55
|
"tippy.js": "^6.3.7",
|
56
|
-
"tiptap-markdown": "^0.8.
|
56
|
+
"tiptap-markdown": "^0.8.10",
|
57
57
|
"tunnel-rat": "^0.1.2"
|
58
58
|
},
|
59
59
|
"devDependencies": {
|
60
|
-
"@types/react": "^18.
|
61
|
-
"@types/react-dom": "18.
|
62
|
-
"typescript": "^5.
|
63
|
-
"vite": "^5.
|
60
|
+
"@types/react": "^18.3.3",
|
61
|
+
"@types/react-dom": "18.3.0",
|
62
|
+
"typescript": "^5.5.3",
|
63
|
+
"vite": "^5.3.2"
|
64
64
|
},
|
65
|
-
"gitHead": "
|
65
|
+
"gitHead": "e41e7401fda1929c44300ada0b993e5b0703b7a1"
|
66
66
|
}
|