From 78e74818cc0525d42986e52fc61e395d42be5bfb Mon Sep 17 00:00:00 2001 From: bishoy melek Date: Sun, 12 Dec 2021 16:22:27 +0200 Subject: [PATCH 1/6] added design plugins --- packages/core/package.json | 2 + packages/design-ui/.npmignore | 3 + packages/design-ui/README.md | 3 + packages/design-ui/package.json | 64 ++++++++ .../src/ImageElement/ImageElement.styles.ts | 76 ++++++++++ .../src/ImageElement/ImageElement.tsx | 138 ++++++++++++++++++ .../src/ImageElement/ImageElement.types.ts | 39 +++++ packages/design-ui/src/ImageElement/index.ts | 7 + .../src/ToolbarImage/ToolbarImage.tsx | 88 +++++++++++ .../src/ToolbarImage/image-toolbar.css | 52 +++++++ packages/design-ui/src/ToolbarImage/index.ts | 5 + packages/design-ui/src/index.ts | 6 + packages/design-ui/src/twin.d.ts | 29 ++++ packages/design-ui/tsconfig.json | 12 ++ packages/design/.npmignore | 3 + packages/design/README.md | 2 + packages/design/package.json | 59 ++++++++ packages/design/src/createImagePlugin.ts | 16 ++ packages/design/src/defaults.ts | 1 + packages/design/src/getImageDeserialize.ts | 19 +++ packages/design/src/index.ts | 11 ++ packages/design/src/transforms/index.ts | 5 + packages/design/src/transforms/insertImage.ts | 19 +++ packages/design/src/types.ts | 24 +++ packages/design/src/utils/index.ts | 5 + packages/design/src/utils/isImageUrl.ts | 132 +++++++++++++++++ packages/design/src/withImageUpload.ts | 49 +++++++ packages/design/tsconfig.json | 11 ++ 28 files changed, 880 insertions(+) create mode 100644 packages/design-ui/.npmignore create mode 100644 packages/design-ui/README.md create mode 100644 packages/design-ui/package.json create mode 100644 packages/design-ui/src/ImageElement/ImageElement.styles.ts create mode 100644 packages/design-ui/src/ImageElement/ImageElement.tsx create mode 100644 packages/design-ui/src/ImageElement/ImageElement.types.ts create mode 100644 packages/design-ui/src/ImageElement/index.ts create mode 100644 packages/design-ui/src/ToolbarImage/ToolbarImage.tsx create mode 100644 packages/design-ui/src/ToolbarImage/image-toolbar.css create mode 100644 packages/design-ui/src/ToolbarImage/index.ts create mode 100644 packages/design-ui/src/index.ts create mode 100644 packages/design-ui/src/twin.d.ts create mode 100644 packages/design-ui/tsconfig.json create mode 100644 packages/design/.npmignore create mode 100644 packages/design/README.md create mode 100644 packages/design/package.json create mode 100644 packages/design/src/createImagePlugin.ts create mode 100644 packages/design/src/defaults.ts create mode 100644 packages/design/src/getImageDeserialize.ts create mode 100644 packages/design/src/index.ts create mode 100644 packages/design/src/transforms/index.ts create mode 100644 packages/design/src/transforms/insertImage.ts create mode 100644 packages/design/src/types.ts create mode 100644 packages/design/src/utils/index.ts create mode 100644 packages/design/src/utils/isImageUrl.ts create mode 100644 packages/design/src/withImageUpload.ts create mode 100644 packages/design/tsconfig.json diff --git a/packages/core/package.json b/packages/core/package.json index 180535a..1b7807f 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -88,6 +88,8 @@ "@dreifuss-wysiwyg-editor/common": "^1.0.2-alpha.1", "@dreifuss-wysiwyg-editor/link": "^1.0.2-alpha.1", "@dreifuss-wysiwyg-editor/link-ui": "^1.0.2-alpha.1", + "@dreifuss-wysiwyg-editor/design": "0.0.0", + "@dreifuss-wysiwyg-editor/design-ui": "0.0.0", "@dreifuss-wysiwyg-editor/image": "0.0.0", "@dreifuss-wysiwyg-editor/image-ui": "0.0.0", "@dreifuss-wysiwyg-editor/table": "0.0.0", diff --git a/packages/design-ui/.npmignore b/packages/design-ui/.npmignore new file mode 100644 index 0000000..7d3b305 --- /dev/null +++ b/packages/design-ui/.npmignore @@ -0,0 +1,3 @@ +__tests__ +__test-utils__ +__mocks__ diff --git a/packages/design-ui/README.md b/packages/design-ui/README.md new file mode 100644 index 0000000..4d88658 --- /dev/null +++ b/packages/design-ui/README.md @@ -0,0 +1,3 @@ +# @dreifuss-wysiwyg-editor/design-ui + +This plugin is based on @udecode/plate-design-ui \ No newline at end of file diff --git a/packages/design-ui/package.json b/packages/design-ui/package.json new file mode 100644 index 0000000..cfa8cad --- /dev/null +++ b/packages/design-ui/package.json @@ -0,0 +1,64 @@ +{ + "name": "@dreifuss-wysiwyg-editor/design-ui", + "version": "0.0.0", + "description": "Dreifuss wysiwyg Editor design ui plugin", + "keywords": [], + "homepage": "https://github.com/wepublish/dreifuss-wysiwyg-editor/tree/main/packages/design-ui#readme", + "bugs": { + "url": "https://github.com/wepublish/dreifuss-wysiwyg-editor/issues" + }, + "repository": { + "type": "git", + "url": "https://github.com/wepublish/dreifuss-wysiwyg-editor.git", + "directory": "packages/image-ui" + }, + "license": "MIT", + "main": "dist/index.js", + "module": "dist/index.es.js", + "types": "dist/index.d.ts", + "files": [ + "dist" + ], + "scripts": { + "clean": "rimraf dist tsconfig.tsbuildinfo", + "build": "tsc && yarn rollup", + "watch": "yarn rollup -w", + "rollup": "rollup -c=../../rollup.config.js", + "test": "jest" + }, + "peerDependencies": { + "react": "^17.0.2", + "react-dom": "^17.0.2", + "slate": "^0.60.0", + "slate-react": "^0.60.0" + }, + "dependencies": { + "@babel/polyfill": "^7.12.1", + "@udecode/plate-core": "^1.0.0", + "twin.macro": "^2.7.0", + "styled-components": "^5.3.1", + "@udecode/plate-styled-components": "^3.1.0", + "@dreifuss-wysiwyg-editor/image": "0.0.0", + "@dreifuss-wysiwyg-editor/common": "^1.0.2-alpha.1" + }, + "devDependencies": { + "@types/react": "^17.0.14", + "@types/react-dom": "^17.0.9", + "@types/slate": "^0.47.8", + "@types/slate-react": "^0.50.1", + "@types/styled-components": "^5.1.14", + "react": "^17.0.2", + "react-dom": "^17.0.2", + "slate": "^0.62.0", + "slate-react": "^0.62.0" + }, + "publishConfig": { + "access": "public" + }, + "eslintConfig": { + "extends": [ + "../../package.json" + ] + }, + "gitHead": "86b71bff4c9b87a901ef6ed530aa1b5882697797" +} diff --git a/packages/design-ui/src/ImageElement/ImageElement.styles.ts b/packages/design-ui/src/ImageElement/ImageElement.styles.ts new file mode 100644 index 0000000..c4aaec4 --- /dev/null +++ b/packages/design-ui/src/ImageElement/ImageElement.styles.ts @@ -0,0 +1,76 @@ +import {createStyles} from '@udecode/plate-styled-components' +import {css} from 'styled-components' +import tw from 'twin.macro' +import {ImageElementStyleProps} from './ImageElement.types' + +export const getImageElementStyles = (props: ImageElementStyleProps) => { + const { + focused, + selected, + caption = { + align: 'center' + } + } = props + + const color = 'rgb(157, 170, 182)' + const colorActive = 'white' + const background = 'rgb(36, 42, 49)' + const borderColor = 'transparent' + + const marginTopLeft = 9 + + return createStyles( + {prefixClassNames: 'ImageElement', ...props}, + { + root: [tw`py-2.5`], + figure: [tw`m-0 relative inline-block`], + img: [ + tw`max-w-full px-0 cursor-pointer w-full`, + tw`borderRadius[3px] object-cover`, + focused && selected && tw`boxShadow[0 0 0 1px rgb(59,130,249)]` + ], + caption: [ + tw`w-full border-none focus:outline-none mt-2 p-0 resize-none`, + caption?.align === 'center' && tw`text-center`, + caption?.align === 'right' && tw`text-right`, + css` + font: inherit; + color: inherit; + background-color: inherit; + + :focus { + ::placeholder { + opacity: 0; + } + } + ` + ], + optionsToolbar: [ + tw`flex items-center select-none box-content`, + tw`color[rgb(68, 68, 68)] minHeight[28px]`, + tw`absolute whitespace-nowrap py-0 px-1`, + props.hidden && tw`invisible`, + !props.hiddenDelay && tw`transition[top 75ms ease-out,left 75ms ease-out]`, + css` + color: ${color}; + background: ${background}; + z-index: 500; + border: 1px solid ${borderColor}; + border-radius: 4px; + margin-top: ${marginTopLeft}px; + margin-left: ${marginTopLeft}px; + .slate-ToolbarButton-active, + .slate-ToolbarButton:hover { + color: ${colorActive}; + } + ` + ], + optionsToolbarButton: [ + tw`bg-transparent text-gray-300 hover:text-white`, + css` + border: 0px; + ` + ] + } + ) +} diff --git a/packages/design-ui/src/ImageElement/ImageElement.tsx b/packages/design-ui/src/ImageElement/ImageElement.tsx new file mode 100644 index 0000000..5a78453 --- /dev/null +++ b/packages/design-ui/src/ImageElement/ImageElement.tsx @@ -0,0 +1,138 @@ +import React, {ChangeEventHandler, Dispatch, useCallback, useEffect, useMemo, useState} from 'react' +import TextareaAutosize from 'react-textarea-autosize' +import {setNodes} from '@udecode/plate-common' +import {useEventEditorId, useStoreEditorState} from '@udecode/plate-core' +import {Node} from 'slate' +import {ReactEditor, useFocused, useSelected} from 'slate-react' +import {getImageElementStyles} from './ImageElement.styles' +import {ImageElementProps} from './ImageElement.types' +import {ImageSizeType} from '@dreifuss-wysiwyg-editor/image' + +export const imageSizeMap = { + [ImageSizeType.fullScreen]: '100%', + [ImageSizeType.large]: '100%', + [ImageSizeType.medium]: '50%', + [ImageSizeType.small]: '30%' +} + +const ImageSizeButton = ({ + label, + type, + onClick, + styles, + isActive +}: { + label: string + type: ImageSizeType + onClick: Dispatch + styles: any + isActive: boolean +}) => { + return ( + + ) +} + +export const ImageElement = (props: ImageElementProps) => { + const {attributes, children, element, nodeProps, caption = {}, draggable} = props + + const {placeholder = 'Write a caption...'} = caption + + const { + url, + size = ImageSizeType.large, + caption: nodeCaption = [{children: [{text: ''}]}] + } = element + const focused = useFocused() + const selected = useSelected() + const editor = useStoreEditorState(useEventEditorId('focus')) + + const [imageSize, setImageSize] = useState(size || ImageSizeType.large) + + useEffect(() => { + const path = ReactEditor.findPath(editor, element) + setNodes(editor, {size: imageSize}, {at: path}) + }, [imageSize]) + + const styles = getImageElementStyles({...props, focused, selected}) + + const onChangeCaption: ChangeEventHandler = useCallback( + e => { + const path = ReactEditor.findPath(editor as ReactEditor, element) + setNodes(editor, {caption: [{text: e.target.value}]}, {at: path}) + }, + [editor, element] + ) + + const captionString = useMemo(() => { + return Node.string(nodeCaption[0]) || '' + }, [nodeCaption]) + + return ( +
+
+
+
+ + + + +
+ {captionString} + {!caption.disabled && (captionString.length || selected) && ( +
+ +
+ )} +
+
+ {children} +
+ ) +} diff --git a/packages/design-ui/src/ImageElement/ImageElement.types.ts b/packages/design-ui/src/ImageElement/ImageElement.types.ts new file mode 100644 index 0000000..226fc97 --- /dev/null +++ b/packages/design-ui/src/ImageElement/ImageElement.types.ts @@ -0,0 +1,39 @@ +import {ImageNodeData} from '@dreifuss-wysiwyg-editor/image' +import {StyledElementProps} from '@udecode/plate-styled-components' +import {CSSProp} from 'styled-components' + +export interface ImageElementStyleProps extends ImageElementProps { + selected?: boolean + focused?: boolean +} + +export interface ImageElementStyles { + figure: CSSProp + img: CSSProp + figcaption: CSSProp + caption: CSSProp + handle: CSSProp + optionsToolbar: CSSProp + optionsToolbarButton: CSSProp +} + +export interface ImageElementProps extends StyledElementProps { + caption?: { + disabled?: boolean + + /** + * Caption alignment. + */ + align?: 'left' | 'center' | 'right' + + /** + * Caption placeholder. + */ + placeholder?: string + } + + /** + * Whether the image is draggable. + */ + draggable?: boolean +} diff --git a/packages/design-ui/src/ImageElement/index.ts b/packages/design-ui/src/ImageElement/index.ts new file mode 100644 index 0000000..cf6822d --- /dev/null +++ b/packages/design-ui/src/ImageElement/index.ts @@ -0,0 +1,7 @@ +/** + * @file Automatically generated by barrelsby. + */ + +export * from './ImageElement.styles' +export * from './ImageElement' +export * from './ImageElement.types' diff --git a/packages/design-ui/src/ToolbarImage/ToolbarImage.tsx b/packages/design-ui/src/ToolbarImage/ToolbarImage.tsx new file mode 100644 index 0000000..51e7f4b --- /dev/null +++ b/packages/design-ui/src/ToolbarImage/ToolbarImage.tsx @@ -0,0 +1,88 @@ +import React, {useContext, useEffect, useRef, useState} from 'react' +import {ReactEditor} from 'slate-react' +import {BaseSelection, Transforms} from 'slate' +import {insertImage} from '@dreifuss-wysiwyg-editor/image' +import {ModalContext} from '@dreifuss-wysiwyg-editor/common' +import {useEventEditorId, useStoreEditorRef, useStoreEditorSelection} from '@udecode/plate-core' + +import './image-toolbar.css' + +export const ToolbarImage = ({CustomComponent, editorRef: passedEditor}: any) => { + const editor = useStoreEditorRef(useEventEditorId('focus')) + const selection = useStoreEditorSelection(useEventEditorId('focus')) + + const latestSelection = useRef() + + const {toggleMenu} = useContext(ModalContext) + + const [url, setURL] = useState('') + + useEffect(() => { + if (passedEditor !== editor) { + if (latestSelection.current) { + Transforms.select(passedEditor, latestSelection.current) + } + ReactEditor.focus(passedEditor) + } + }, [passedEditor, editor]) + + useEffect(() => { + if (selection) { + latestSelection.current = selection + } + }, [selection]) + + if (CustomComponent) + return ( + setURL(newUrl)} + onSubmit={() => { + if (!editor) return + + if (latestSelection.current) { + Transforms.select(editor, latestSelection.current) + } + ReactEditor.focus(editor) + + insertImage(editor, url) + toggleMenu() + }} + /> + ) + + return ( +
+
+ +
+ setURL(e.target.value)} /> +
+
+
+ +
+
+ ) +} + +export interface CustomImageToolbarProps { + onChange: React.Dispatch> + url: string + onSubmit: React.Dispatch> +} diff --git a/packages/design-ui/src/ToolbarImage/image-toolbar.css b/packages/design-ui/src/ToolbarImage/image-toolbar.css new file mode 100644 index 0000000..d7e29b6 --- /dev/null +++ b/packages/design-ui/src/ToolbarImage/image-toolbar.css @@ -0,0 +1,52 @@ +.image-toolbar .input-group { + border: 1px solid #e5e5ea; + padding: 5px 5px; + margin-top: 5px; + display: flex; + flex-wrap: wrap; +} + +.image-toolbar .input-group input { + flex: 1 1 auto; + border: 0px; +} + +.image-toolbar .form-group:not(:last-child) { + margin-bottom: 20px; +} + +.image-toolbar .toolbar button { + margin-bottom: 0; + margin: auto 5px; + font-weight: normal; + text-align: center; + vertical-align: middle; + cursor: pointer; + outline: 0 !important; + white-space: nowrap; + border: none; + user-select: none; + padding: 8px 12px; + font-size: 14px; + line-height: 1.42857143; + border-radius: 6px; +} + +.image-toolbar .toolbar button:first-child { + margin-left: 0px; +} + +.image-toolbar .toolbar button.insert { + color: white; + background-color: #0078d4; +} + +.image-toolbar .toolbar button.cancel { + color: red; + background-color: #f7f7fa; +} + +.image-toolbar .toolbar button.disabled { + color: #c5c6c7; + background-color: #f7f7fa; +} diff --git a/packages/design-ui/src/ToolbarImage/index.ts b/packages/design-ui/src/ToolbarImage/index.ts new file mode 100644 index 0000000..714e6ee --- /dev/null +++ b/packages/design-ui/src/ToolbarImage/index.ts @@ -0,0 +1,5 @@ +/** + * @file Automatically generated by barrelsby. + */ + +export * from './ToolbarImage' diff --git a/packages/design-ui/src/index.ts b/packages/design-ui/src/index.ts new file mode 100644 index 0000000..8f0f6a9 --- /dev/null +++ b/packages/design-ui/src/index.ts @@ -0,0 +1,6 @@ +/** + * @file Automatically generated by barrelsby. + */ + +export * from './ImageElement/index' +export * from './ToolbarImage/index' diff --git a/packages/design-ui/src/twin.d.ts b/packages/design-ui/src/twin.d.ts new file mode 100644 index 0000000..e6d013a --- /dev/null +++ b/packages/design-ui/src/twin.d.ts @@ -0,0 +1,29 @@ +// twin.d.ts +import 'twin.macro' +import styledImport, {CSSProp, css as cssImport} from 'styled-components' + +declare module 'twin.macro' { + // The styled and css imports + const styled: typeof styledImport + const css: typeof cssImport +} + +declare module 'react' { + // The css prop + interface HTMLAttributes extends DOMAttributes { + css?: CSSProp + } + // The inline svg css prop + interface SVGProps extends SVGProps { + css?: CSSProp + } +} + +// The 'as' prop on styled components +declare global { + namespace JSX { + interface IntrinsicAttributes extends DOMAttributes { + as?: string | Element + } + } +} diff --git a/packages/design-ui/tsconfig.json b/packages/design-ui/tsconfig.json new file mode 100644 index 0000000..3e5a034 --- /dev/null +++ b/packages/design-ui/tsconfig.json @@ -0,0 +1,12 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": "dist", + "rootDir": "src", + "target": "ES2019", + "lib": ["dom", "ES2019"], + "jsx": "react-jsx" + }, + "exclude": ["node_modules", "dist"], + "files": ["src/twin.d.ts"] +} diff --git a/packages/design/.npmignore b/packages/design/.npmignore new file mode 100644 index 0000000..7d3b305 --- /dev/null +++ b/packages/design/.npmignore @@ -0,0 +1,3 @@ +__tests__ +__test-utils__ +__mocks__ diff --git a/packages/design/README.md b/packages/design/README.md new file mode 100644 index 0000000..c05903f --- /dev/null +++ b/packages/design/README.md @@ -0,0 +1,2 @@ +# @dreifuss-wysiwyg-editor/design + diff --git a/packages/design/package.json b/packages/design/package.json new file mode 100644 index 0000000..71370df --- /dev/null +++ b/packages/design/package.json @@ -0,0 +1,59 @@ +{ + "name": "@dreifuss-wysiwyg-editor/design", + "version": "0.0.0", + "description": "Dreifuss wysiwyg Editor design plugin", + "keywords": [], + "homepage": "https://github.com/wepublish/dreifuss-wysiwyg-editor/tree/main/packages/design#readme", + "bugs": { + "url": "https://github.com/wepublish/dreifuss-wysiwyg-editor/issues" + }, + "repository": { + "type": "git", + "url": "https://github.com/wepublish/dreifuss-wysiwyg-editor.git", + "directory": "packages/image" + }, + "license": "MIT", + "main": "dist/index.js", + "module": "dist/index.es.js", + "types": "dist/index.d.ts", + "files": [ + "dist" + ], + "scripts": { + "clean": "rimraf dist tsconfig.tsbuildinfo", + "build": "tsc && yarn rollup", + "watch": "yarn rollup -w", + "rollup": "rollup -c=../../rollup.config.js", + "test": "jest" + }, + "peerDependencies": { + "react": "^17.0.2", + "react-dom": "^17.0.2", + "slate": "^0.60.0", + "slate-react": "^0.60.0" + }, + "dependencies": { + "@babel/polyfill": "^7.12.1", + "@udecode/plate-core": "^1.0.0", + "@udecode/plate-common": "^2.0.0" + }, + "devDependencies": { + "@types/react": "^17.0.14", + "@types/react-dom": "^17.0.9", + "@types/slate": "^0.47.8", + "@types/slate-react": "^0.50.1", + "react": "^17.0.2", + "react-dom": "^17.0.2", + "slate": "^0.62.0", + "slate-react": "^0.62.0" + }, + "publishConfig": { + "access": "public" + }, + "eslintConfig": { + "extends": [ + "../../package.json" + ] + }, + "gitHead": "86b71bff4c9b87a901ef6ed530aa1b5882697797" +} diff --git a/packages/design/src/createImagePlugin.ts b/packages/design/src/createImagePlugin.ts new file mode 100644 index 0000000..801c1d6 --- /dev/null +++ b/packages/design/src/createImagePlugin.ts @@ -0,0 +1,16 @@ +import {getPlatePluginTypes, getRenderElement, PlatePlugin} from '@udecode/plate-core' +import {ELEMENT_IMAGE} from './defaults' +import {getImageDeserialize} from './getImageDeserialize' +import {WithImageUploadOptions} from './types' +import {withImageUpload} from './withImageUpload' + +/** + * Enables support for design. + */ +export const createDesignPlugin = (options?: WithImageUploadOptions): PlatePlugin => ({ + pluginKeys: ELEMENT_IMAGE, + renderElement: getRenderElement(ELEMENT_IMAGE), + deserialize: getImageDeserialize(), + voidTypes: getPlatePluginTypes(ELEMENT_IMAGE), + withOverrides: withImageUpload(options) +}) diff --git a/packages/design/src/defaults.ts b/packages/design/src/defaults.ts new file mode 100644 index 0000000..67a9a01 --- /dev/null +++ b/packages/design/src/defaults.ts @@ -0,0 +1 @@ +export const ELEMENT_IMAGE = 'img' diff --git a/packages/design/src/getImageDeserialize.ts b/packages/design/src/getImageDeserialize.ts new file mode 100644 index 0000000..99109fb --- /dev/null +++ b/packages/design/src/getImageDeserialize.ts @@ -0,0 +1,19 @@ +import {getNodeDeserializer} from '@udecode/plate-common' +import {Deserialize, getPlatePluginOptions} from '@udecode/plate-core' +import {ELEMENT_IMAGE} from './defaults' + +export const getImageDeserialize = (): Deserialize => editor => { + const options = getPlatePluginOptions(editor, ELEMENT_IMAGE) + + return { + element: getNodeDeserializer({ + type: options.type, + getNode: el => ({ + type: options.type, + url: el.getAttribute('src') + }), + rules: [{nodeNames: 'IMG'}], + ...options.deserialize + }) + } +} diff --git a/packages/design/src/index.ts b/packages/design/src/index.ts new file mode 100644 index 0000000..4dd39d0 --- /dev/null +++ b/packages/design/src/index.ts @@ -0,0 +1,11 @@ +/** + * @file Automatically generated by barrelsby. + */ + +export * from './createImagePlugin' +export * from './defaults' +export * from './getImageDeserialize' +export * from './types' +export * from './withImageUpload' +export * from './transforms/index' +export * from './utils/index' diff --git a/packages/design/src/transforms/index.ts b/packages/design/src/transforms/index.ts new file mode 100644 index 0000000..cf9c65a --- /dev/null +++ b/packages/design/src/transforms/index.ts @@ -0,0 +1,5 @@ +/** + * @file Automatically generated by barrelsby. + */ + +export * from './insertImage' diff --git a/packages/design/src/transforms/insertImage.ts b/packages/design/src/transforms/insertImage.ts new file mode 100644 index 0000000..89be4c0 --- /dev/null +++ b/packages/design/src/transforms/insertImage.ts @@ -0,0 +1,19 @@ +import {insertNodes} from '@udecode/plate-common' +import {getPlatePluginType, SPEditor, TElement} from '@udecode/plate-core' +import {ELEMENT_IMAGE} from '../defaults' +import {ImageSizeType} from '../types' + +export const insertImage = ( + editor: SPEditor, + url: string | ArrayBuffer, + size: ImageSizeType = ImageSizeType.large +) => { + const text = {text: ''} + const image = { + type: getPlatePluginType(editor, ELEMENT_IMAGE), + url, + size, + children: [text] + } + insertNodes(editor, image) +} diff --git a/packages/design/src/types.ts b/packages/design/src/types.ts new file mode 100644 index 0000000..445b215 --- /dev/null +++ b/packages/design/src/types.ts @@ -0,0 +1,24 @@ +import {TDescendant} from '@udecode/plate-core' + +export enum ImageSizeType { + fullScreen = 'fullScreen', + large = 'large', + medium = 'medium', + small = 'small' +} + +export interface ImageNodeData { + url: string + size: ImageSizeType + caption?: TDescendant[] +} + +export interface WithImageUploadOptions { + /** + * An optional method that will upload the image to a server. + * The method receives the base64 dataUrl of the uploaded image, and should return the URL of the uploaded image. + */ + uploadImage?: ( + dataUrl: string | ArrayBuffer + ) => Promise | string | ArrayBuffer +} diff --git a/packages/design/src/utils/index.ts b/packages/design/src/utils/index.ts new file mode 100644 index 0000000..002b12d --- /dev/null +++ b/packages/design/src/utils/index.ts @@ -0,0 +1,5 @@ +/** + * @file Automatically generated by barrelsby. + */ + +export * from './isImageUrl' diff --git a/packages/design/src/utils/isImageUrl.ts b/packages/design/src/utils/isImageUrl.ts new file mode 100644 index 0000000..ba0ca56 --- /dev/null +++ b/packages/design/src/utils/isImageUrl.ts @@ -0,0 +1,132 @@ +import {isUrl} from '@udecode/plate-common' + +const imageExtensions = [ + 'ase', + 'art', + 'bmp', + 'blp', + 'cd5', + 'cit', + 'cpt', + 'cr2', + 'cut', + 'dds', + 'dib', + 'djvu', + 'egt', + 'exif', + 'gif', + 'gpl', + 'grf', + 'icns', + 'ico', + 'iff', + 'jng', + 'jpeg', + 'jpg', + 'jfif', + 'jp2', + 'jps', + 'lbm', + 'max', + 'miff', + 'mng', + 'msp', + 'nitf', + 'ota', + 'pbm', + 'pc1', + 'pc2', + 'pc3', + 'pcf', + 'pcx', + 'pdn', + 'pgm', + 'PI1', + 'PI2', + 'PI3', + 'pict', + 'pct', + 'pnm', + 'pns', + 'ppm', + 'psb', + 'psd', + 'pdd', + 'psp', + 'px', + 'pxm', + 'pxr', + 'qfx', + 'raw', + 'rle', + 'sct', + 'sgi', + 'rgb', + 'int', + 'bw', + 'tga', + 'tiff', + 'tif', + 'vtf', + 'xbm', + 'xcf', + 'xpm', + '3dv', + 'amf', + 'ai', + 'awg', + 'cgm', + 'cdr', + 'cmx', + 'dxf', + 'e2d', + 'egt', + 'eps', + 'fs', + 'gbr', + 'odg', + 'svg', + 'stl', + 'vrml', + 'x3d', + 'sxd', + 'v2d', + 'vnd', + 'wmf', + 'emf', + 'art', + 'xar', + 'png', + 'webp', + 'jxr', + 'hdp', + 'wdp', + 'cur', + 'ecw', + 'iff', + 'lbm', + 'liff', + 'nrrd', + 'pam', + 'pcx', + 'pgf', + 'sgi', + 'rgb', + 'rgba', + 'bw', + 'int', + 'inta', + 'sid', + 'ras', + 'sun', + 'tga' +] + +export const isImageUrl = (url: string) => { + if (!isUrl(url)) return false + + const ext = new URL(url).pathname.split('.').pop() as string + + return imageExtensions.includes(ext) +} diff --git a/packages/design/src/withImageUpload.ts b/packages/design/src/withImageUpload.ts new file mode 100644 index 0000000..6c8ea3f --- /dev/null +++ b/packages/design/src/withImageUpload.ts @@ -0,0 +1,49 @@ +import {SPEditor, WithOverride} from '@udecode/plate-core' +import {ReactEditor} from 'slate-react' +import {insertImage} from './transforms/insertImage' +import {isImageUrl} from './utils/isImageUrl' +import {WithImageUploadOptions} from './types' + +/** + * Allows for pasting images from clipboard. + * Not yet: dragging and dropping images, selecting them through a file system dialog. + * @param options.type + * @param options.uploadImage + */ +export const withImageUpload = + ({uploadImage}: WithImageUploadOptions = {}): WithOverride => + editor => { + const {insertData} = editor + + editor.insertData = (data: DataTransfer) => { + const text = data.getData('text/plain') + const {files} = data + if (files && files.length > 0) { + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + for (const file of files) { + const reader = new FileReader() + const [mime] = file.type.split('/') + + if (mime === 'image') { + reader.addEventListener('load', async () => { + if (!reader.result) { + return + } + const uploadedUrl = uploadImage ? await uploadImage(reader.result) : reader.result + + insertImage(editor, uploadedUrl) + }) + + reader.readAsDataURL(file) + } + } + } else if (isImageUrl(text)) { + insertImage(editor, text) + } else { + insertData(data) + } + } + + return editor + } diff --git a/packages/design/tsconfig.json b/packages/design/tsconfig.json new file mode 100644 index 0000000..8cb03b1 --- /dev/null +++ b/packages/design/tsconfig.json @@ -0,0 +1,11 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": "dist", + "rootDir": "src", + "target": "ES2019", + "lib": ["dom", "ES2019"], + "jsx": "react-jsx" + }, + "exclude": ["node_modules", "dist"] +} From 36893f7e9097c92b31a3f382cdb03b2a42c9bb9c Mon Sep 17 00:00:00 2001 From: bishoy melek Date: Mon, 13 Dec 2021 03:07:34 +0200 Subject: [PATCH 2/6] remove design --- packages/core/package.json | 2 - packages/design-ui/.npmignore | 3 - packages/design-ui/README.md | 3 - packages/design-ui/package.json | 64 -------- .../src/ImageElement/ImageElement.styles.ts | 76 ---------- .../src/ImageElement/ImageElement.tsx | 138 ------------------ .../src/ImageElement/ImageElement.types.ts | 39 ----- packages/design-ui/src/ImageElement/index.ts | 7 - .../src/ToolbarImage/ToolbarImage.tsx | 88 ----------- .../src/ToolbarImage/image-toolbar.css | 52 ------- packages/design-ui/src/ToolbarImage/index.ts | 5 - packages/design-ui/src/index.ts | 6 - packages/design-ui/src/twin.d.ts | 29 ---- packages/design-ui/tsconfig.json | 12 -- packages/design/.npmignore | 3 - packages/design/README.md | 2 - packages/design/package.json | 59 -------- packages/design/src/createImagePlugin.ts | 16 -- packages/design/src/defaults.ts | 1 - packages/design/src/getImageDeserialize.ts | 19 --- packages/design/src/index.ts | 11 -- packages/design/src/transforms/index.ts | 5 - packages/design/src/transforms/insertImage.ts | 19 --- packages/design/src/types.ts | 24 --- packages/design/src/utils/index.ts | 5 - packages/design/src/utils/isImageUrl.ts | 132 ----------------- packages/design/src/withImageUpload.ts | 49 ------- packages/design/tsconfig.json | 11 -- 28 files changed, 880 deletions(-) delete mode 100644 packages/design-ui/.npmignore delete mode 100644 packages/design-ui/README.md delete mode 100644 packages/design-ui/package.json delete mode 100644 packages/design-ui/src/ImageElement/ImageElement.styles.ts delete mode 100644 packages/design-ui/src/ImageElement/ImageElement.tsx delete mode 100644 packages/design-ui/src/ImageElement/ImageElement.types.ts delete mode 100644 packages/design-ui/src/ImageElement/index.ts delete mode 100644 packages/design-ui/src/ToolbarImage/ToolbarImage.tsx delete mode 100644 packages/design-ui/src/ToolbarImage/image-toolbar.css delete mode 100644 packages/design-ui/src/ToolbarImage/index.ts delete mode 100644 packages/design-ui/src/index.ts delete mode 100644 packages/design-ui/src/twin.d.ts delete mode 100644 packages/design-ui/tsconfig.json delete mode 100644 packages/design/.npmignore delete mode 100644 packages/design/README.md delete mode 100644 packages/design/package.json delete mode 100644 packages/design/src/createImagePlugin.ts delete mode 100644 packages/design/src/defaults.ts delete mode 100644 packages/design/src/getImageDeserialize.ts delete mode 100644 packages/design/src/index.ts delete mode 100644 packages/design/src/transforms/index.ts delete mode 100644 packages/design/src/transforms/insertImage.ts delete mode 100644 packages/design/src/types.ts delete mode 100644 packages/design/src/utils/index.ts delete mode 100644 packages/design/src/utils/isImageUrl.ts delete mode 100644 packages/design/src/withImageUpload.ts delete mode 100644 packages/design/tsconfig.json diff --git a/packages/core/package.json b/packages/core/package.json index 1b7807f..180535a 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -88,8 +88,6 @@ "@dreifuss-wysiwyg-editor/common": "^1.0.2-alpha.1", "@dreifuss-wysiwyg-editor/link": "^1.0.2-alpha.1", "@dreifuss-wysiwyg-editor/link-ui": "^1.0.2-alpha.1", - "@dreifuss-wysiwyg-editor/design": "0.0.0", - "@dreifuss-wysiwyg-editor/design-ui": "0.0.0", "@dreifuss-wysiwyg-editor/image": "0.0.0", "@dreifuss-wysiwyg-editor/image-ui": "0.0.0", "@dreifuss-wysiwyg-editor/table": "0.0.0", diff --git a/packages/design-ui/.npmignore b/packages/design-ui/.npmignore deleted file mode 100644 index 7d3b305..0000000 --- a/packages/design-ui/.npmignore +++ /dev/null @@ -1,3 +0,0 @@ -__tests__ -__test-utils__ -__mocks__ diff --git a/packages/design-ui/README.md b/packages/design-ui/README.md deleted file mode 100644 index 4d88658..0000000 --- a/packages/design-ui/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# @dreifuss-wysiwyg-editor/design-ui - -This plugin is based on @udecode/plate-design-ui \ No newline at end of file diff --git a/packages/design-ui/package.json b/packages/design-ui/package.json deleted file mode 100644 index cfa8cad..0000000 --- a/packages/design-ui/package.json +++ /dev/null @@ -1,64 +0,0 @@ -{ - "name": "@dreifuss-wysiwyg-editor/design-ui", - "version": "0.0.0", - "description": "Dreifuss wysiwyg Editor design ui plugin", - "keywords": [], - "homepage": "https://github.com/wepublish/dreifuss-wysiwyg-editor/tree/main/packages/design-ui#readme", - "bugs": { - "url": "https://github.com/wepublish/dreifuss-wysiwyg-editor/issues" - }, - "repository": { - "type": "git", - "url": "https://github.com/wepublish/dreifuss-wysiwyg-editor.git", - "directory": "packages/image-ui" - }, - "license": "MIT", - "main": "dist/index.js", - "module": "dist/index.es.js", - "types": "dist/index.d.ts", - "files": [ - "dist" - ], - "scripts": { - "clean": "rimraf dist tsconfig.tsbuildinfo", - "build": "tsc && yarn rollup", - "watch": "yarn rollup -w", - "rollup": "rollup -c=../../rollup.config.js", - "test": "jest" - }, - "peerDependencies": { - "react": "^17.0.2", - "react-dom": "^17.0.2", - "slate": "^0.60.0", - "slate-react": "^0.60.0" - }, - "dependencies": { - "@babel/polyfill": "^7.12.1", - "@udecode/plate-core": "^1.0.0", - "twin.macro": "^2.7.0", - "styled-components": "^5.3.1", - "@udecode/plate-styled-components": "^3.1.0", - "@dreifuss-wysiwyg-editor/image": "0.0.0", - "@dreifuss-wysiwyg-editor/common": "^1.0.2-alpha.1" - }, - "devDependencies": { - "@types/react": "^17.0.14", - "@types/react-dom": "^17.0.9", - "@types/slate": "^0.47.8", - "@types/slate-react": "^0.50.1", - "@types/styled-components": "^5.1.14", - "react": "^17.0.2", - "react-dom": "^17.0.2", - "slate": "^0.62.0", - "slate-react": "^0.62.0" - }, - "publishConfig": { - "access": "public" - }, - "eslintConfig": { - "extends": [ - "../../package.json" - ] - }, - "gitHead": "86b71bff4c9b87a901ef6ed530aa1b5882697797" -} diff --git a/packages/design-ui/src/ImageElement/ImageElement.styles.ts b/packages/design-ui/src/ImageElement/ImageElement.styles.ts deleted file mode 100644 index c4aaec4..0000000 --- a/packages/design-ui/src/ImageElement/ImageElement.styles.ts +++ /dev/null @@ -1,76 +0,0 @@ -import {createStyles} from '@udecode/plate-styled-components' -import {css} from 'styled-components' -import tw from 'twin.macro' -import {ImageElementStyleProps} from './ImageElement.types' - -export const getImageElementStyles = (props: ImageElementStyleProps) => { - const { - focused, - selected, - caption = { - align: 'center' - } - } = props - - const color = 'rgb(157, 170, 182)' - const colorActive = 'white' - const background = 'rgb(36, 42, 49)' - const borderColor = 'transparent' - - const marginTopLeft = 9 - - return createStyles( - {prefixClassNames: 'ImageElement', ...props}, - { - root: [tw`py-2.5`], - figure: [tw`m-0 relative inline-block`], - img: [ - tw`max-w-full px-0 cursor-pointer w-full`, - tw`borderRadius[3px] object-cover`, - focused && selected && tw`boxShadow[0 0 0 1px rgb(59,130,249)]` - ], - caption: [ - tw`w-full border-none focus:outline-none mt-2 p-0 resize-none`, - caption?.align === 'center' && tw`text-center`, - caption?.align === 'right' && tw`text-right`, - css` - font: inherit; - color: inherit; - background-color: inherit; - - :focus { - ::placeholder { - opacity: 0; - } - } - ` - ], - optionsToolbar: [ - tw`flex items-center select-none box-content`, - tw`color[rgb(68, 68, 68)] minHeight[28px]`, - tw`absolute whitespace-nowrap py-0 px-1`, - props.hidden && tw`invisible`, - !props.hiddenDelay && tw`transition[top 75ms ease-out,left 75ms ease-out]`, - css` - color: ${color}; - background: ${background}; - z-index: 500; - border: 1px solid ${borderColor}; - border-radius: 4px; - margin-top: ${marginTopLeft}px; - margin-left: ${marginTopLeft}px; - .slate-ToolbarButton-active, - .slate-ToolbarButton:hover { - color: ${colorActive}; - } - ` - ], - optionsToolbarButton: [ - tw`bg-transparent text-gray-300 hover:text-white`, - css` - border: 0px; - ` - ] - } - ) -} diff --git a/packages/design-ui/src/ImageElement/ImageElement.tsx b/packages/design-ui/src/ImageElement/ImageElement.tsx deleted file mode 100644 index 5a78453..0000000 --- a/packages/design-ui/src/ImageElement/ImageElement.tsx +++ /dev/null @@ -1,138 +0,0 @@ -import React, {ChangeEventHandler, Dispatch, useCallback, useEffect, useMemo, useState} from 'react' -import TextareaAutosize from 'react-textarea-autosize' -import {setNodes} from '@udecode/plate-common' -import {useEventEditorId, useStoreEditorState} from '@udecode/plate-core' -import {Node} from 'slate' -import {ReactEditor, useFocused, useSelected} from 'slate-react' -import {getImageElementStyles} from './ImageElement.styles' -import {ImageElementProps} from './ImageElement.types' -import {ImageSizeType} from '@dreifuss-wysiwyg-editor/image' - -export const imageSizeMap = { - [ImageSizeType.fullScreen]: '100%', - [ImageSizeType.large]: '100%', - [ImageSizeType.medium]: '50%', - [ImageSizeType.small]: '30%' -} - -const ImageSizeButton = ({ - label, - type, - onClick, - styles, - isActive -}: { - label: string - type: ImageSizeType - onClick: Dispatch - styles: any - isActive: boolean -}) => { - return ( - - ) -} - -export const ImageElement = (props: ImageElementProps) => { - const {attributes, children, element, nodeProps, caption = {}, draggable} = props - - const {placeholder = 'Write a caption...'} = caption - - const { - url, - size = ImageSizeType.large, - caption: nodeCaption = [{children: [{text: ''}]}] - } = element - const focused = useFocused() - const selected = useSelected() - const editor = useStoreEditorState(useEventEditorId('focus')) - - const [imageSize, setImageSize] = useState(size || ImageSizeType.large) - - useEffect(() => { - const path = ReactEditor.findPath(editor, element) - setNodes(editor, {size: imageSize}, {at: path}) - }, [imageSize]) - - const styles = getImageElementStyles({...props, focused, selected}) - - const onChangeCaption: ChangeEventHandler = useCallback( - e => { - const path = ReactEditor.findPath(editor as ReactEditor, element) - setNodes(editor, {caption: [{text: e.target.value}]}, {at: path}) - }, - [editor, element] - ) - - const captionString = useMemo(() => { - return Node.string(nodeCaption[0]) || '' - }, [nodeCaption]) - - return ( -
-
-
-
- - - - -
- {captionString} - {!caption.disabled && (captionString.length || selected) && ( -
- -
- )} -
-
- {children} -
- ) -} diff --git a/packages/design-ui/src/ImageElement/ImageElement.types.ts b/packages/design-ui/src/ImageElement/ImageElement.types.ts deleted file mode 100644 index 226fc97..0000000 --- a/packages/design-ui/src/ImageElement/ImageElement.types.ts +++ /dev/null @@ -1,39 +0,0 @@ -import {ImageNodeData} from '@dreifuss-wysiwyg-editor/image' -import {StyledElementProps} from '@udecode/plate-styled-components' -import {CSSProp} from 'styled-components' - -export interface ImageElementStyleProps extends ImageElementProps { - selected?: boolean - focused?: boolean -} - -export interface ImageElementStyles { - figure: CSSProp - img: CSSProp - figcaption: CSSProp - caption: CSSProp - handle: CSSProp - optionsToolbar: CSSProp - optionsToolbarButton: CSSProp -} - -export interface ImageElementProps extends StyledElementProps { - caption?: { - disabled?: boolean - - /** - * Caption alignment. - */ - align?: 'left' | 'center' | 'right' - - /** - * Caption placeholder. - */ - placeholder?: string - } - - /** - * Whether the image is draggable. - */ - draggable?: boolean -} diff --git a/packages/design-ui/src/ImageElement/index.ts b/packages/design-ui/src/ImageElement/index.ts deleted file mode 100644 index cf6822d..0000000 --- a/packages/design-ui/src/ImageElement/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -/** - * @file Automatically generated by barrelsby. - */ - -export * from './ImageElement.styles' -export * from './ImageElement' -export * from './ImageElement.types' diff --git a/packages/design-ui/src/ToolbarImage/ToolbarImage.tsx b/packages/design-ui/src/ToolbarImage/ToolbarImage.tsx deleted file mode 100644 index 51e7f4b..0000000 --- a/packages/design-ui/src/ToolbarImage/ToolbarImage.tsx +++ /dev/null @@ -1,88 +0,0 @@ -import React, {useContext, useEffect, useRef, useState} from 'react' -import {ReactEditor} from 'slate-react' -import {BaseSelection, Transforms} from 'slate' -import {insertImage} from '@dreifuss-wysiwyg-editor/image' -import {ModalContext} from '@dreifuss-wysiwyg-editor/common' -import {useEventEditorId, useStoreEditorRef, useStoreEditorSelection} from '@udecode/plate-core' - -import './image-toolbar.css' - -export const ToolbarImage = ({CustomComponent, editorRef: passedEditor}: any) => { - const editor = useStoreEditorRef(useEventEditorId('focus')) - const selection = useStoreEditorSelection(useEventEditorId('focus')) - - const latestSelection = useRef() - - const {toggleMenu} = useContext(ModalContext) - - const [url, setURL] = useState('') - - useEffect(() => { - if (passedEditor !== editor) { - if (latestSelection.current) { - Transforms.select(passedEditor, latestSelection.current) - } - ReactEditor.focus(passedEditor) - } - }, [passedEditor, editor]) - - useEffect(() => { - if (selection) { - latestSelection.current = selection - } - }, [selection]) - - if (CustomComponent) - return ( - setURL(newUrl)} - onSubmit={() => { - if (!editor) return - - if (latestSelection.current) { - Transforms.select(editor, latestSelection.current) - } - ReactEditor.focus(editor) - - insertImage(editor, url) - toggleMenu() - }} - /> - ) - - return ( -
-
- -
- setURL(e.target.value)} /> -
-
-
- -
-
- ) -} - -export interface CustomImageToolbarProps { - onChange: React.Dispatch> - url: string - onSubmit: React.Dispatch> -} diff --git a/packages/design-ui/src/ToolbarImage/image-toolbar.css b/packages/design-ui/src/ToolbarImage/image-toolbar.css deleted file mode 100644 index d7e29b6..0000000 --- a/packages/design-ui/src/ToolbarImage/image-toolbar.css +++ /dev/null @@ -1,52 +0,0 @@ -.image-toolbar .input-group { - border: 1px solid #e5e5ea; - padding: 5px 5px; - margin-top: 5px; - display: flex; - flex-wrap: wrap; -} - -.image-toolbar .input-group input { - flex: 1 1 auto; - border: 0px; -} - -.image-toolbar .form-group:not(:last-child) { - margin-bottom: 20px; -} - -.image-toolbar .toolbar button { - margin-bottom: 0; - margin: auto 5px; - font-weight: normal; - text-align: center; - vertical-align: middle; - cursor: pointer; - outline: 0 !important; - white-space: nowrap; - border: none; - user-select: none; - padding: 8px 12px; - font-size: 14px; - line-height: 1.42857143; - border-radius: 6px; -} - -.image-toolbar .toolbar button:first-child { - margin-left: 0px; -} - -.image-toolbar .toolbar button.insert { - color: white; - background-color: #0078d4; -} - -.image-toolbar .toolbar button.cancel { - color: red; - background-color: #f7f7fa; -} - -.image-toolbar .toolbar button.disabled { - color: #c5c6c7; - background-color: #f7f7fa; -} diff --git a/packages/design-ui/src/ToolbarImage/index.ts b/packages/design-ui/src/ToolbarImage/index.ts deleted file mode 100644 index 714e6ee..0000000 --- a/packages/design-ui/src/ToolbarImage/index.ts +++ /dev/null @@ -1,5 +0,0 @@ -/** - * @file Automatically generated by barrelsby. - */ - -export * from './ToolbarImage' diff --git a/packages/design-ui/src/index.ts b/packages/design-ui/src/index.ts deleted file mode 100644 index 8f0f6a9..0000000 --- a/packages/design-ui/src/index.ts +++ /dev/null @@ -1,6 +0,0 @@ -/** - * @file Automatically generated by barrelsby. - */ - -export * from './ImageElement/index' -export * from './ToolbarImage/index' diff --git a/packages/design-ui/src/twin.d.ts b/packages/design-ui/src/twin.d.ts deleted file mode 100644 index e6d013a..0000000 --- a/packages/design-ui/src/twin.d.ts +++ /dev/null @@ -1,29 +0,0 @@ -// twin.d.ts -import 'twin.macro' -import styledImport, {CSSProp, css as cssImport} from 'styled-components' - -declare module 'twin.macro' { - // The styled and css imports - const styled: typeof styledImport - const css: typeof cssImport -} - -declare module 'react' { - // The css prop - interface HTMLAttributes extends DOMAttributes { - css?: CSSProp - } - // The inline svg css prop - interface SVGProps extends SVGProps { - css?: CSSProp - } -} - -// The 'as' prop on styled components -declare global { - namespace JSX { - interface IntrinsicAttributes extends DOMAttributes { - as?: string | Element - } - } -} diff --git a/packages/design-ui/tsconfig.json b/packages/design-ui/tsconfig.json deleted file mode 100644 index 3e5a034..0000000 --- a/packages/design-ui/tsconfig.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "extends": "../../tsconfig.json", - "compilerOptions": { - "outDir": "dist", - "rootDir": "src", - "target": "ES2019", - "lib": ["dom", "ES2019"], - "jsx": "react-jsx" - }, - "exclude": ["node_modules", "dist"], - "files": ["src/twin.d.ts"] -} diff --git a/packages/design/.npmignore b/packages/design/.npmignore deleted file mode 100644 index 7d3b305..0000000 --- a/packages/design/.npmignore +++ /dev/null @@ -1,3 +0,0 @@ -__tests__ -__test-utils__ -__mocks__ diff --git a/packages/design/README.md b/packages/design/README.md deleted file mode 100644 index c05903f..0000000 --- a/packages/design/README.md +++ /dev/null @@ -1,2 +0,0 @@ -# @dreifuss-wysiwyg-editor/design - diff --git a/packages/design/package.json b/packages/design/package.json deleted file mode 100644 index 71370df..0000000 --- a/packages/design/package.json +++ /dev/null @@ -1,59 +0,0 @@ -{ - "name": "@dreifuss-wysiwyg-editor/design", - "version": "0.0.0", - "description": "Dreifuss wysiwyg Editor design plugin", - "keywords": [], - "homepage": "https://github.com/wepublish/dreifuss-wysiwyg-editor/tree/main/packages/design#readme", - "bugs": { - "url": "https://github.com/wepublish/dreifuss-wysiwyg-editor/issues" - }, - "repository": { - "type": "git", - "url": "https://github.com/wepublish/dreifuss-wysiwyg-editor.git", - "directory": "packages/image" - }, - "license": "MIT", - "main": "dist/index.js", - "module": "dist/index.es.js", - "types": "dist/index.d.ts", - "files": [ - "dist" - ], - "scripts": { - "clean": "rimraf dist tsconfig.tsbuildinfo", - "build": "tsc && yarn rollup", - "watch": "yarn rollup -w", - "rollup": "rollup -c=../../rollup.config.js", - "test": "jest" - }, - "peerDependencies": { - "react": "^17.0.2", - "react-dom": "^17.0.2", - "slate": "^0.60.0", - "slate-react": "^0.60.0" - }, - "dependencies": { - "@babel/polyfill": "^7.12.1", - "@udecode/plate-core": "^1.0.0", - "@udecode/plate-common": "^2.0.0" - }, - "devDependencies": { - "@types/react": "^17.0.14", - "@types/react-dom": "^17.0.9", - "@types/slate": "^0.47.8", - "@types/slate-react": "^0.50.1", - "react": "^17.0.2", - "react-dom": "^17.0.2", - "slate": "^0.62.0", - "slate-react": "^0.62.0" - }, - "publishConfig": { - "access": "public" - }, - "eslintConfig": { - "extends": [ - "../../package.json" - ] - }, - "gitHead": "86b71bff4c9b87a901ef6ed530aa1b5882697797" -} diff --git a/packages/design/src/createImagePlugin.ts b/packages/design/src/createImagePlugin.ts deleted file mode 100644 index 801c1d6..0000000 --- a/packages/design/src/createImagePlugin.ts +++ /dev/null @@ -1,16 +0,0 @@ -import {getPlatePluginTypes, getRenderElement, PlatePlugin} from '@udecode/plate-core' -import {ELEMENT_IMAGE} from './defaults' -import {getImageDeserialize} from './getImageDeserialize' -import {WithImageUploadOptions} from './types' -import {withImageUpload} from './withImageUpload' - -/** - * Enables support for design. - */ -export const createDesignPlugin = (options?: WithImageUploadOptions): PlatePlugin => ({ - pluginKeys: ELEMENT_IMAGE, - renderElement: getRenderElement(ELEMENT_IMAGE), - deserialize: getImageDeserialize(), - voidTypes: getPlatePluginTypes(ELEMENT_IMAGE), - withOverrides: withImageUpload(options) -}) diff --git a/packages/design/src/defaults.ts b/packages/design/src/defaults.ts deleted file mode 100644 index 67a9a01..0000000 --- a/packages/design/src/defaults.ts +++ /dev/null @@ -1 +0,0 @@ -export const ELEMENT_IMAGE = 'img' diff --git a/packages/design/src/getImageDeserialize.ts b/packages/design/src/getImageDeserialize.ts deleted file mode 100644 index 99109fb..0000000 --- a/packages/design/src/getImageDeserialize.ts +++ /dev/null @@ -1,19 +0,0 @@ -import {getNodeDeserializer} from '@udecode/plate-common' -import {Deserialize, getPlatePluginOptions} from '@udecode/plate-core' -import {ELEMENT_IMAGE} from './defaults' - -export const getImageDeserialize = (): Deserialize => editor => { - const options = getPlatePluginOptions(editor, ELEMENT_IMAGE) - - return { - element: getNodeDeserializer({ - type: options.type, - getNode: el => ({ - type: options.type, - url: el.getAttribute('src') - }), - rules: [{nodeNames: 'IMG'}], - ...options.deserialize - }) - } -} diff --git a/packages/design/src/index.ts b/packages/design/src/index.ts deleted file mode 100644 index 4dd39d0..0000000 --- a/packages/design/src/index.ts +++ /dev/null @@ -1,11 +0,0 @@ -/** - * @file Automatically generated by barrelsby. - */ - -export * from './createImagePlugin' -export * from './defaults' -export * from './getImageDeserialize' -export * from './types' -export * from './withImageUpload' -export * from './transforms/index' -export * from './utils/index' diff --git a/packages/design/src/transforms/index.ts b/packages/design/src/transforms/index.ts deleted file mode 100644 index cf9c65a..0000000 --- a/packages/design/src/transforms/index.ts +++ /dev/null @@ -1,5 +0,0 @@ -/** - * @file Automatically generated by barrelsby. - */ - -export * from './insertImage' diff --git a/packages/design/src/transforms/insertImage.ts b/packages/design/src/transforms/insertImage.ts deleted file mode 100644 index 89be4c0..0000000 --- a/packages/design/src/transforms/insertImage.ts +++ /dev/null @@ -1,19 +0,0 @@ -import {insertNodes} from '@udecode/plate-common' -import {getPlatePluginType, SPEditor, TElement} from '@udecode/plate-core' -import {ELEMENT_IMAGE} from '../defaults' -import {ImageSizeType} from '../types' - -export const insertImage = ( - editor: SPEditor, - url: string | ArrayBuffer, - size: ImageSizeType = ImageSizeType.large -) => { - const text = {text: ''} - const image = { - type: getPlatePluginType(editor, ELEMENT_IMAGE), - url, - size, - children: [text] - } - insertNodes(editor, image) -} diff --git a/packages/design/src/types.ts b/packages/design/src/types.ts deleted file mode 100644 index 445b215..0000000 --- a/packages/design/src/types.ts +++ /dev/null @@ -1,24 +0,0 @@ -import {TDescendant} from '@udecode/plate-core' - -export enum ImageSizeType { - fullScreen = 'fullScreen', - large = 'large', - medium = 'medium', - small = 'small' -} - -export interface ImageNodeData { - url: string - size: ImageSizeType - caption?: TDescendant[] -} - -export interface WithImageUploadOptions { - /** - * An optional method that will upload the image to a server. - * The method receives the base64 dataUrl of the uploaded image, and should return the URL of the uploaded image. - */ - uploadImage?: ( - dataUrl: string | ArrayBuffer - ) => Promise | string | ArrayBuffer -} diff --git a/packages/design/src/utils/index.ts b/packages/design/src/utils/index.ts deleted file mode 100644 index 002b12d..0000000 --- a/packages/design/src/utils/index.ts +++ /dev/null @@ -1,5 +0,0 @@ -/** - * @file Automatically generated by barrelsby. - */ - -export * from './isImageUrl' diff --git a/packages/design/src/utils/isImageUrl.ts b/packages/design/src/utils/isImageUrl.ts deleted file mode 100644 index ba0ca56..0000000 --- a/packages/design/src/utils/isImageUrl.ts +++ /dev/null @@ -1,132 +0,0 @@ -import {isUrl} from '@udecode/plate-common' - -const imageExtensions = [ - 'ase', - 'art', - 'bmp', - 'blp', - 'cd5', - 'cit', - 'cpt', - 'cr2', - 'cut', - 'dds', - 'dib', - 'djvu', - 'egt', - 'exif', - 'gif', - 'gpl', - 'grf', - 'icns', - 'ico', - 'iff', - 'jng', - 'jpeg', - 'jpg', - 'jfif', - 'jp2', - 'jps', - 'lbm', - 'max', - 'miff', - 'mng', - 'msp', - 'nitf', - 'ota', - 'pbm', - 'pc1', - 'pc2', - 'pc3', - 'pcf', - 'pcx', - 'pdn', - 'pgm', - 'PI1', - 'PI2', - 'PI3', - 'pict', - 'pct', - 'pnm', - 'pns', - 'ppm', - 'psb', - 'psd', - 'pdd', - 'psp', - 'px', - 'pxm', - 'pxr', - 'qfx', - 'raw', - 'rle', - 'sct', - 'sgi', - 'rgb', - 'int', - 'bw', - 'tga', - 'tiff', - 'tif', - 'vtf', - 'xbm', - 'xcf', - 'xpm', - '3dv', - 'amf', - 'ai', - 'awg', - 'cgm', - 'cdr', - 'cmx', - 'dxf', - 'e2d', - 'egt', - 'eps', - 'fs', - 'gbr', - 'odg', - 'svg', - 'stl', - 'vrml', - 'x3d', - 'sxd', - 'v2d', - 'vnd', - 'wmf', - 'emf', - 'art', - 'xar', - 'png', - 'webp', - 'jxr', - 'hdp', - 'wdp', - 'cur', - 'ecw', - 'iff', - 'lbm', - 'liff', - 'nrrd', - 'pam', - 'pcx', - 'pgf', - 'sgi', - 'rgb', - 'rgba', - 'bw', - 'int', - 'inta', - 'sid', - 'ras', - 'sun', - 'tga' -] - -export const isImageUrl = (url: string) => { - if (!isUrl(url)) return false - - const ext = new URL(url).pathname.split('.').pop() as string - - return imageExtensions.includes(ext) -} diff --git a/packages/design/src/withImageUpload.ts b/packages/design/src/withImageUpload.ts deleted file mode 100644 index 6c8ea3f..0000000 --- a/packages/design/src/withImageUpload.ts +++ /dev/null @@ -1,49 +0,0 @@ -import {SPEditor, WithOverride} from '@udecode/plate-core' -import {ReactEditor} from 'slate-react' -import {insertImage} from './transforms/insertImage' -import {isImageUrl} from './utils/isImageUrl' -import {WithImageUploadOptions} from './types' - -/** - * Allows for pasting images from clipboard. - * Not yet: dragging and dropping images, selecting them through a file system dialog. - * @param options.type - * @param options.uploadImage - */ -export const withImageUpload = - ({uploadImage}: WithImageUploadOptions = {}): WithOverride => - editor => { - const {insertData} = editor - - editor.insertData = (data: DataTransfer) => { - const text = data.getData('text/plain') - const {files} = data - if (files && files.length > 0) { - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - for (const file of files) { - const reader = new FileReader() - const [mime] = file.type.split('/') - - if (mime === 'image') { - reader.addEventListener('load', async () => { - if (!reader.result) { - return - } - const uploadedUrl = uploadImage ? await uploadImage(reader.result) : reader.result - - insertImage(editor, uploadedUrl) - }) - - reader.readAsDataURL(file) - } - } - } else if (isImageUrl(text)) { - insertImage(editor, text) - } else { - insertData(data) - } - } - - return editor - } diff --git a/packages/design/tsconfig.json b/packages/design/tsconfig.json deleted file mode 100644 index 8cb03b1..0000000 --- a/packages/design/tsconfig.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "extends": "../../tsconfig.json", - "compilerOptions": { - "outDir": "dist", - "rootDir": "src", - "target": "ES2019", - "lib": ["dom", "ES2019"], - "jsx": "react-jsx" - }, - "exclude": ["node_modules", "dist"] -} From aad28b4d064fc6416dbc5e43f211817b10cb9d97 Mon Sep 17 00:00:00 2001 From: bishoy melek Date: Mon, 13 Dec 2021 03:11:27 +0200 Subject: [PATCH 3/6] wrap text around image --- packages/common/src/components/Icons.tsx | 21 ++- .../src/ImageElement/ImageElement.tsx | 133 +++++++++++++----- packages/image/src/types.ts | 6 + 3 files changed, 124 insertions(+), 36 deletions(-) diff --git a/packages/common/src/components/Icons.tsx b/packages/common/src/components/Icons.tsx index 7c7bb44..6f33d49 100644 --- a/packages/common/src/components/Icons.tsx +++ b/packages/common/src/components/Icons.tsx @@ -256,7 +256,12 @@ export const SubscriptIcon = () => ( ) export const AlignLeftIcon = () => ( - + ) @@ -268,13 +273,23 @@ export const AlignCenterIcon = () => ( ) export const AlignRightIcon = () => ( - + ) export const AlignJustifyIcon = () => ( - + ) diff --git a/packages/image-ui/src/ImageElement/ImageElement.tsx b/packages/image-ui/src/ImageElement/ImageElement.tsx index 5a78453..51d3d4a 100644 --- a/packages/image-ui/src/ImageElement/ImageElement.tsx +++ b/packages/image-ui/src/ImageElement/ImageElement.tsx @@ -1,4 +1,12 @@ -import React, {ChangeEventHandler, Dispatch, useCallback, useEffect, useMemo, useState} from 'react' +import React, { + ChangeEventHandler, + Dispatch, + ReactNode, + useCallback, + useEffect, + useMemo, + useState +} from 'react' import TextareaAutosize from 'react-textarea-autosize' import {setNodes} from '@udecode/plate-common' import {useEventEditorId, useStoreEditorState} from '@udecode/plate-core' @@ -6,7 +14,8 @@ import {Node} from 'slate' import {ReactEditor, useFocused, useSelected} from 'slate-react' import {getImageElementStyles} from './ImageElement.styles' import {ImageElementProps} from './ImageElement.types' -import {ImageSizeType} from '@dreifuss-wysiwyg-editor/image' +import {ImageSizeType, ImageAlignmentType} from '@dreifuss-wysiwyg-editor/image' +import {AlignRightIcon, AlignLeftIcon, AlignJustifyIcon} from '@dreifuss-wysiwyg-editor/common' export const imageSizeMap = { [ImageSizeType.fullScreen]: '100%', @@ -38,6 +47,27 @@ const ImageSizeButton = ({ ) } +const ImageAlignButton = ({ + icon: Icon, + onClick, + styles, + isActive +}: { + icon: ReactNode + onClick: Dispatch + styles: any + isActive: boolean +}) => ( + + + + +) + export const ImageElement = (props: ImageElementProps) => { const {attributes, children, element, nodeProps, caption = {}, draggable} = props @@ -45,6 +75,7 @@ export const ImageElement = (props: ImageElementProps) => { const { url, + align, size = ImageSizeType.large, caption: nodeCaption = [{children: [{text: ''}]}] } = element @@ -54,11 +85,18 @@ export const ImageElement = (props: ImageElementProps) => { const [imageSize, setImageSize] = useState(size || ImageSizeType.large) + const [imageAlignment, setImageAlignment] = useState(align) + useEffect(() => { const path = ReactEditor.findPath(editor, element) setNodes(editor, {size: imageSize}, {at: path}) }, [imageSize]) + useEffect(() => { + const path = ReactEditor.findPath(editor, element) + setNodes(editor, {align: imageAlignment}, {at: path}) + }, [imageAlignment]) + const styles = getImageElementStyles({...props, focused, selected}) const onChangeCaption: ChangeEventHandler = useCallback( @@ -74,41 +112,70 @@ export const ImageElement = (props: ImageElementProps) => { }, [nodeCaption]) return ( -
+
-
- - - - + style={{width: '100%'}}> +
+
+ + + + +
+
+ setImageAlignment('left')} + styles={styles.optionsToolbarButton} + isActive={imageAlignment === ImageAlignmentType.left} + /> + setImageAlignment('right')} + styles={styles.optionsToolbarButton} + isActive={imageAlignment === ImageAlignmentType.right} + /> + setImageAlignment(null)} + styles={styles.optionsToolbarButton} + isActive={imageAlignment === ImageAlignmentType.justify} + /> +
Date: Mon, 13 Dec 2021 14:01:44 +0200 Subject: [PATCH 4/6] fixes --- .../src/CharacterCounter.tsx | 4 +- .../core/src/DreifussWysiwygEditorDemo.tsx | 37 ++++++++----------- 2 files changed, 18 insertions(+), 23 deletions(-) diff --git a/packages/character-count-ui/src/CharacterCounter.tsx b/packages/character-count-ui/src/CharacterCounter.tsx index c816fcd..12533b4 100644 --- a/packages/character-count-ui/src/CharacterCounter.tsx +++ b/packages/character-count-ui/src/CharacterCounter.tsx @@ -1,7 +1,7 @@ import React from 'react' import {Node} from 'slate' import {toArray} from 'lodash' -import {useStoreEditorState} from '@udecode/plate-core' +import {useStoreEditorRef} from '@udecode/plate-core' import {TEditor} from '@dreifuss-wysiwyg-editor/common' const getTextString = (editor: TEditor) => { @@ -25,7 +25,7 @@ const calculateCharCount = (editor?: TEditor) => { } export function getCharacterCount(id: string): number { - const editor = useStoreEditorState(id) + const editor = useStoreEditorRef(id) return calculateCharCount(editor) } diff --git a/packages/core/src/DreifussWysiwygEditorDemo.tsx b/packages/core/src/DreifussWysiwygEditorDemo.tsx index a3e7624..6781399 100644 --- a/packages/core/src/DreifussWysiwygEditorDemo.tsx +++ b/packages/core/src/DreifussWysiwygEditorDemo.tsx @@ -4,19 +4,26 @@ import {DreifussWysiwygEditor} from './index' import {CustomImageToolbarProps} from '@dreifuss-wysiwyg-editor/image-ui' const value: any = [ - {type: 'action_item', checked: true, children: [{text: 'Slide to the right.'}], id: 10054}, - {type: 'action_item', children: [{text: 'Criss-cross.'}], id: 10055}, + {type: 'action_item', checked: true, children: [{text: 'Slide to the right.'}]}, + {type: 'action_item', children: [{text: 'Criss-cross.'}]}, { type: 'paragraph', - children: [{type: 'link', url: 'http://google.com', children: [{text: 'Links: Add links.'}]}], - id: 10052 + children: [ + {text: ''}, + {type: 'link', url: 'http://google.com', children: [{text: 'Links: Add links.'}]}, + {text: ''} + ] }, + {type: 'paragraph', children: [{text: ''}]}, { - type: 'paragraph', - children: [{text: 'Bold: Make the selected text bold.', code: true}], - id: 10055 + type: 'img', + url: 'https://picsum.photos/500/300', + size: 'medium', + children: [{text: ''}], + align: 'right' }, - + {type: 'paragraph', children: [{text: ''}]}, + {type: 'paragraph', children: [{text: 'Bold: Make the selected text bold.', code: true}]}, {type: 'paragraph', children: [{text: 'Italic: Make the selected text italic.', italic: true}]}, { type: 'paragraph', @@ -125,19 +132,6 @@ const toolbars = { const DreifussWysiwygEditorDemo = () => (
-
-

RichText Component Demo

- { - // console.log(count) - // }} - onChange={e => { - console.log(e) - }} - /> -

RichText Component Demo

( }} onChange={e => { console.log(e) + // console.log(JSON.stringify(e)) }} id="two" value={value} From e6fb685844f825ecf246f66490ef1e82546470c5 Mon Sep 17 00:00:00 2001 From: bishoy melek Date: Mon, 13 Dec 2021 14:40:56 +0200 Subject: [PATCH 5/6] hot fix --- packages/image-ui/src/ImageElement/ImageElement.tsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/image-ui/src/ImageElement/ImageElement.tsx b/packages/image-ui/src/ImageElement/ImageElement.tsx index 51d3d4a..4613ee1 100644 --- a/packages/image-ui/src/ImageElement/ImageElement.tsx +++ b/packages/image-ui/src/ImageElement/ImageElement.tsx @@ -116,7 +116,11 @@ export const ImageElement = (props: ImageElementProps) => { {...attributes} css={styles.root.css} className={styles.root.className} - style={{margin: 10, width: imageSizeMap[imageSize], float: imageAlignment ?? undefined}}> + style={{ + margin: 'auto 10px', + width: imageSizeMap[imageSize], + float: imageAlignment ?? undefined + }}>
Date: Tue, 14 Dec 2021 04:04:15 +0200 Subject: [PATCH 6/6] disabling align btn --- .../src/ImageElement/ImageElement.styles.ts | 2 +- .../src/ImageElement/ImageElement.tsx | 30 ++++++++++++++++--- 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/packages/image-ui/src/ImageElement/ImageElement.styles.ts b/packages/image-ui/src/ImageElement/ImageElement.styles.ts index c4aaec4..0292955 100644 --- a/packages/image-ui/src/ImageElement/ImageElement.styles.ts +++ b/packages/image-ui/src/ImageElement/ImageElement.styles.ts @@ -66,7 +66,7 @@ export const getImageElementStyles = (props: ImageElementStyleProps) => { ` ], optionsToolbarButton: [ - tw`bg-transparent text-gray-300 hover:text-white`, + tw`bg-transparent text-gray-300 hover:text-white cursor-pointer`, css` border: 0px; ` diff --git a/packages/image-ui/src/ImageElement/ImageElement.tsx b/packages/image-ui/src/ImageElement/ImageElement.tsx index 4613ee1..1c78c65 100644 --- a/packages/image-ui/src/ImageElement/ImageElement.tsx +++ b/packages/image-ui/src/ImageElement/ImageElement.tsx @@ -51,14 +51,18 @@ const ImageAlignButton = ({ icon: Icon, onClick, styles, - isActive + isActive, + disabled = false }: { icon: ReactNode onClick: Dispatch styles: any isActive: boolean + disabled?: boolean }) => (