[Wip] init Floating extention
This commit is contained in:
parent
20dde76aab
commit
9a8a358a8e
69
package-lock.json
generated
69
package-lock.json
generated
|
@ -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",
|
||||||
|
|
|
@ -367,3 +367,11 @@ img {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[data-float='left'] {
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-float='right'] {
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
|
|
@ -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'
|
||||||
}
|
}
|
||||||
|
|
|
@ -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>
|
||||||
)
|
)
|
||||||
|
|
54
src/components/Editor/extensions/CustomImage.ts
Normal file
54
src/components/Editor/extensions/CustomImage.ts
Normal 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 })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
|
@ -0,0 +1,3 @@
|
||||||
|
.ImageView {
|
||||||
|
border: 1px solid royalblue;
|
||||||
|
}
|
12
src/components/Editor/nodes/ImageView/ImageView.tsx
Normal file
12
src/components/Editor/nodes/ImageView/ImageView.tsx
Normal 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>
|
||||||
|
}
|
1
src/components/Editor/nodes/ImageView/index.ts
Normal file
1
src/components/Editor/nodes/ImageView/index.ts
Normal file
|
@ -0,0 +1 @@
|
||||||
|
export { ImageView } from './ImageView'
|
Loading…
Reference in New Issue
Block a user