[Wip] init Floating extention

This commit is contained in:
ilya-bkv 2023-05-06 15:38:22 +03:00
parent 20dde76aab
commit 9a8a358a8e
9 changed files with 107 additions and 65 deletions

69
package-lock.json generated
View File

@ -5723,18 +5723,6 @@
"solid-js": ">=1.4.0" "solid-js": ">=1.4.0"
} }
}, },
"node_modules/@soorria/solid-dropzone": {
"version": "0.0.5",
"resolved": "https://registry.npmjs.org/@soorria/solid-dropzone/-/solid-dropzone-0.0.5.tgz",
"integrity": "sha512-lIuCz33UuHZ/34jMLlhspzUZfpZyPvquJvUIZ4zDFZeaxIvgsspwDblKlk347K/qKu3+WNKhiDoIUodMpM7Yug==",
"dependencies": {
"attr-accept": "^2.2.2",
"file-selector": "^0.6.0"
},
"peerDependencies": {
"solid-js": ">=1.0.0"
}
},
"node_modules/@thisbeyond/solid-select": { "node_modules/@thisbeyond/solid-select": {
"version": "0.13.0", "version": "0.13.0",
"resolved": "https://registry.npmjs.org/@thisbeyond/solid-select/-/solid-select-0.13.0.tgz", "resolved": "https://registry.npmjs.org/@thisbeyond/solid-select/-/solid-select-0.13.0.tgz",
@ -7187,14 +7175,6 @@
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
}, },
"node_modules/attr-accept": {
"version": "2.2.2",
"resolved": "https://registry.npmjs.org/attr-accept/-/attr-accept-2.2.2.tgz",
"integrity": "sha512-7prDjvt9HmqiZ0cl5CRjtS84sEyhsHP2coDkaZKRKVfCDo9s7iw7ChVmar78Gu9pC4SoR/28wFu/G5JJhTnqEg==",
"engines": {
"node": ">=4"
}
},
"node_modules/auto-bind": { "node_modules/auto-bind": {
"version": "4.0.0", "version": "4.0.0",
"resolved": "https://registry.npmjs.org/auto-bind/-/auto-bind-4.0.0.tgz", "resolved": "https://registry.npmjs.org/auto-bind/-/auto-bind-4.0.0.tgz",
@ -8396,7 +8376,8 @@
"node_modules/csstype": { "node_modules/csstype": {
"version": "3.1.1", "version": "3.1.1",
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.1.tgz", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.1.tgz",
"integrity": "sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw==" "integrity": "sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw==",
"dev": true
}, },
"node_modules/damerau-levenshtein": { "node_modules/damerau-levenshtein": {
"version": "1.0.8", "version": "1.0.8",
@ -10168,17 +10149,6 @@
"node": "^10.12.0 || >=12.0.0" "node": "^10.12.0 || >=12.0.0"
} }
}, },
"node_modules/file-selector": {
"version": "0.6.0",
"resolved": "https://registry.npmjs.org/file-selector/-/file-selector-0.6.0.tgz",
"integrity": "sha512-QlZ5yJC0VxHxQQsQhXvBaC7VRJ2uaxTf+Tfpu4Z/OcVQJVpZO+DGU0rkoVW5ce2SccxugvpBJoMvUs59iILYdw==",
"dependencies": {
"tslib": "^2.4.0"
},
"engines": {
"node": ">= 12"
}
},
"node_modules/filelist": { "node_modules/filelist": {
"version": "1.0.4", "version": "1.0.4",
"resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz",
@ -18110,6 +18080,7 @@
"version": "0.5.1", "version": "0.5.1",
"resolved": "https://registry.npmjs.org/seroval/-/seroval-0.5.1.tgz", "resolved": "https://registry.npmjs.org/seroval/-/seroval-0.5.1.tgz",
"integrity": "sha512-ZfhQVB59hmIauJG5Ydynupy8KHyr5imGNtdDhbZG68Ufh1Ynkv9KOYOAABf71oVbQxJ8VkWnMHAjEHE7fWkH5g==", "integrity": "sha512-ZfhQVB59hmIauJG5Ydynupy8KHyr5imGNtdDhbZG68Ufh1Ynkv9KOYOAABf71oVbQxJ8VkWnMHAjEHE7fWkH5g==",
"dev": true,
"engines": { "engines": {
"node": ">=10" "node": ">=10"
} }
@ -24811,15 +24782,6 @@
"dev": true, "dev": true,
"requires": {} "requires": {}
}, },
"@soorria/solid-dropzone": {
"version": "0.0.5",
"resolved": "https://registry.npmjs.org/@soorria/solid-dropzone/-/solid-dropzone-0.0.5.tgz",
"integrity": "sha512-lIuCz33UuHZ/34jMLlhspzUZfpZyPvquJvUIZ4zDFZeaxIvgsspwDblKlk347K/qKu3+WNKhiDoIUodMpM7Yug==",
"requires": {
"attr-accept": "^2.2.2",
"file-selector": "^0.6.0"
}
},
"@thisbeyond/solid-select": { "@thisbeyond/solid-select": {
"version": "0.13.0", "version": "0.13.0",
"resolved": "https://registry.npmjs.org/@thisbeyond/solid-select/-/solid-select-0.13.0.tgz", "resolved": "https://registry.npmjs.org/@thisbeyond/solid-select/-/solid-select-0.13.0.tgz",
@ -25866,11 +25828,6 @@
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
}, },
"attr-accept": {
"version": "2.2.2",
"resolved": "https://registry.npmjs.org/attr-accept/-/attr-accept-2.2.2.tgz",
"integrity": "sha512-7prDjvt9HmqiZ0cl5CRjtS84sEyhsHP2coDkaZKRKVfCDo9s7iw7ChVmar78Gu9pC4SoR/28wFu/G5JJhTnqEg=="
},
"auto-bind": { "auto-bind": {
"version": "4.0.0", "version": "4.0.0",
"resolved": "https://registry.npmjs.org/auto-bind/-/auto-bind-4.0.0.tgz", "resolved": "https://registry.npmjs.org/auto-bind/-/auto-bind-4.0.0.tgz",
@ -26760,7 +26717,8 @@
"csstype": { "csstype": {
"version": "3.1.1", "version": "3.1.1",
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.1.tgz", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.1.tgz",
"integrity": "sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw==" "integrity": "sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw==",
"dev": true
}, },
"damerau-levenshtein": { "damerau-levenshtein": {
"version": "1.0.8", "version": "1.0.8",
@ -28073,14 +28031,6 @@
"flat-cache": "^3.0.4" "flat-cache": "^3.0.4"
} }
}, },
"file-selector": {
"version": "0.6.0",
"resolved": "https://registry.npmjs.org/file-selector/-/file-selector-0.6.0.tgz",
"integrity": "sha512-QlZ5yJC0VxHxQQsQhXvBaC7VRJ2uaxTf+Tfpu4Z/OcVQJVpZO+DGU0rkoVW5ce2SccxugvpBJoMvUs59iILYdw==",
"requires": {
"tslib": "^2.4.0"
}
},
"filelist": { "filelist": {
"version": "1.0.4", "version": "1.0.4",
"resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz",
@ -33956,7 +33906,8 @@
"seroval": { "seroval": {
"version": "0.5.1", "version": "0.5.1",
"resolved": "https://registry.npmjs.org/seroval/-/seroval-0.5.1.tgz", "resolved": "https://registry.npmjs.org/seroval/-/seroval-0.5.1.tgz",
"integrity": "sha512-ZfhQVB59hmIauJG5Ydynupy8KHyr5imGNtdDhbZG68Ufh1Ynkv9KOYOAABf71oVbQxJ8VkWnMHAjEHE7fWkH5g==" "integrity": "sha512-ZfhQVB59hmIauJG5Ydynupy8KHyr5imGNtdDhbZG68Ufh1Ynkv9KOYOAABf71oVbQxJ8VkWnMHAjEHE7fWkH5g==",
"dev": true
}, },
"set-blocking": { "set-blocking": {
"version": "2.0.0", "version": "2.0.0",
@ -34092,9 +34043,9 @@
} }
}, },
"solid-js": { "solid-js": {
"version": "1.7.0", "version": "1.7.3",
"resolved": "https://registry.npmjs.org/solid-js/-/solid-js-1.7.0.tgz", "resolved": "https://registry.npmjs.org/solid-js/-/solid-js-1.7.3.tgz",
"integrity": "sha512-tLG68KWlVRgzYeAW003G3E70emZqTcqCKJR9QoGr0rcuiLIuKrlUoezT8jLME1YSl3Wfu35jzgeY10iLEY4YQQ==", "integrity": "sha512-4hwaF/zV/xbNeBBIYDyu3dcReOZBECbO//mrra6GqOrKy4Soyo+fnKjpZSa0nODm6j1aL0iQRh/7ofYowH+jzw==",
"dev": true, "dev": true,
"requires": { "requires": {
"csstype": "^3.1.0", "csstype": "^3.1.0",

View File

@ -367,3 +367,11 @@ img {
} }
} }
} }
[data-float='left'] {
float: left;
}
[data-float='right'] {
float: right;
}

View File

@ -22,7 +22,8 @@ import { Highlight } from '@tiptap/extension-highlight'
import { Link } from '@tiptap/extension-link' import { Link } from '@tiptap/extension-link'
import { Document } from '@tiptap/extension-document' import { Document } from '@tiptap/extension-document'
import { Text } from '@tiptap/extension-text' import { Text } from '@tiptap/extension-text'
import { Image } from '@tiptap/extension-image' // import { Image } from '@tiptap/extension-image'
import CustomImage from './extensions/CustomImage'
import { Paragraph } from '@tiptap/extension-paragraph' import { Paragraph } from '@tiptap/extension-paragraph'
import Focus from '@tiptap/extension-focus' import Focus from '@tiptap/extension-focus'
import { TrailingNode } from './extensions/TrailingNode' import { TrailingNode } from './extensions/TrailingNode'
@ -34,7 +35,7 @@ import { IndexeddbPersistence } from 'y-indexeddb'
import { useSession } from '../../context/session' import { useSession } from '../../context/session'
import uniqolor from 'uniqolor' import uniqolor from 'uniqolor'
import { HocuspocusProvider } from '@hocuspocus/provider' import { HocuspocusProvider } from '@hocuspocus/provider'
import { Embed } from './extensions/embed' import { Embed } from './extensions/Embed'
import { TextBubbleMenu } from './TextBubbleMenu' import { TextBubbleMenu } from './TextBubbleMenu'
import { ImageBubbleMenu } from './ImageBubbleMenu' import { ImageBubbleMenu } from './ImageBubbleMenu'
import { EditorFloatingMenu } from './EditorFloatingMenu' import { EditorFloatingMenu } from './EditorFloatingMenu'
@ -137,7 +138,7 @@ export const Editor = (props: EditorProps) => {
Gapcursor, Gapcursor,
HardBreak, HardBreak,
Highlight, Highlight,
Image.configure({ CustomImage.configure({
HTMLAttributes: { HTMLAttributes: {
class: 'uploadedImage' class: 'uploadedImage'
} }

View File

@ -11,18 +11,30 @@ type BubbleMenuProps = {
export const ImageBubbleMenu = (props: BubbleMenuProps) => { export const ImageBubbleMenu = (props: BubbleMenuProps) => {
return ( return (
<div ref={props.ref} class={styles.ImageBubbleMenu}> <div ref={props.ref} class={styles.ImageBubbleMenu}>
<button type="button" class={clsx(styles.bubbleMenuButton)}> <button
type="button"
class={clsx(styles.bubbleMenuButton)}
onClick={() => {
props.editor.chain().focus().setFloat('left').run()
}}
>
<Icon name="editor-image-align-left" /> <Icon name="editor-image-align-left" />
</button> </button>
<button type="button" class={clsx(styles.bubbleMenuButton)}> <button type="button" class={clsx(styles.bubbleMenuButton)}>
<Icon name="editor-image-align-center" /> <Icon name="editor-image-align-center" />
</button> </button>
<button type="button" class={clsx(styles.bubbleMenuButton)}> <button
type="button"
class={clsx(styles.bubbleMenuButton)}
onClick={() => {
props.editor.chain().focus().setFloat('right').run()
}}
>
<Icon name="editor-image-align-right" /> <Icon name="editor-image-align-right" />
</button> </button>
<div class={styles.delimiter} /> <div class={styles.delimiter} />
<button type="button" class={clsx(styles.bubbleMenuButton)}> <button type="button" class={clsx(styles.bubbleMenuButton)}>
<Icon name="editor-image-align-add" /> <Icon name="editor-image-add" />
</button> </button>
</div> </div>
) )

View File

@ -0,0 +1,54 @@
import Image from '@tiptap/extension-image'
import { mergeAttributes } from '@tiptap/core'
declare module '@tiptap/core' {
interface Commands<ReturnType> {
resizableMedia: {
setFloat: (float: 'none' | 'left' | 'right') => ReturnType
}
}
}
export const updateAttrs = (attrs, editor, node) => {
const { view } = editor
if (!view.editable) return
const { state } = view
const newAttrs = { ...node.attrs, ...attrs }
const { from } = state.selection
const transaction = state.tr.setNodeMarkup(from, null, newAttrs)
view.dispatch(transaction)
}
export default Image.extend({
addAttributes() {
return {
src: {
default: null
},
alt: {
default: null
},
width: {
default: null
},
height: {
default: null
},
'data-float': {
default: null
}
}
},
renderHTML({ HTMLAttributes }) {
return ['img', mergeAttributes(this.options.HTMLAttributes, HTMLAttributes)]
},
addCommands() {
return {
setFloat:
(value) =>
({ commands }) => {
return commands.updateAttributes(this.name, { 'data-float': value })
}
}
}
})

View File

@ -0,0 +1,3 @@
.ImageView {
border: 1px solid royalblue;
}

View File

@ -0,0 +1,12 @@
import styles from './ImageView.module.scss'
import { ImageDisplay, updateAttrs } from '../../extensions/CustomImage'
import { Editor } from '@tiptap/core'
import { onMount } from 'solid-js'
type Props = {
editor: Editor
}
export const ImageView = (props: Props) => {
return <div class={styles.ImageView}>asdads</div>
}

View File

@ -0,0 +1 @@
export { ImageView } from './ImageView'