diff --git a/CHANGELOG.md b/CHANGELOG.md index 5635cb3..747850c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed +## [7.3.1] 2022-08-17 + +### Fixed + +- Fixed an issue with `WYSIWYGInput` where it would skip the cursor to the start when using controlled input + ## [7.3.0] 2022-08-17 ### Added diff --git a/package.json b/package.json index 55339c1..4a86eeb 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@perimetre/ui", "description": "A component library made by @perimetre", - "version": "7.3.0", + "version": "7.3.1", "repository": { "type": "git", "url": "git+https://github.com/perimetre/ui.git" diff --git a/src/components/WYSIWYGInput/WYSIWYGInput.stories.tsx b/src/components/WYSIWYGInput/WYSIWYGInput.stories.tsx index cab1924..fe4d057 100644 --- a/src/components/WYSIWYGInput/WYSIWYGInput.stories.tsx +++ b/src/components/WYSIWYGInput/WYSIWYGInput.stories.tsx @@ -1,6 +1,6 @@ // also exported from '@storybook/react' if you can deal with breaking changes in 6.1 import { Meta, Story } from '@storybook/react/types-6-0'; -import React, { useEffect, useRef, useState } from 'react'; +import React, { useRef, useState } from 'react'; import { WYSIWYGInput, WYSIWYGInputProps, WYSIWYGInputRef } from '.'; import { Button } from '../Button'; import { HTMLParsedContent } from '../HTMLParsedContent'; @@ -81,24 +81,24 @@ DefaultValue.args = { * @param props.htmlValueSlow The html value to fill the input with * @param props.className the component classes */ -const ValueChangeTemplate: Story = ({ +const ControlledValueTemplate: Story = ({ htmlValueSlow, ...props }) => { const [htmlValue, setHtmlValue] = useState(htmlValueSlow); - useEffect(() => { - const id = setInterval(() => setHtmlValue((htmlValue) => htmlValue + ' a'), 1000); - return () => clearInterval(id); - }, []); + // useEffect(() => { + // const id = setInterval(() => setHtmlValue((htmlValue) => htmlValue + ' a'), 1000); + // return () => clearInterval(id); + // }, []); return ; }; -export const ValueChange = ValueChangeTemplate.bind({}); -ValueChange.args = { - htmlValueSlow: - '

Lorem ipsum dolor, sit amet consectetur adipisicing elit. Atque quaerat, minus suscipit totam nam sequi hic expedita quae fugit blanditiis ad voluptate eligendi adipisci. Quaerat similique numquam corporis molestias, blanditiis enim saepe accusamus debitis ipsa provident cumque voluptatum dolor beatae odit, odio ipsum maiores! Reiciendis, debitis fugiat consequuntur ex quae necessitatibus laboriosam sit quas et nam! Maxime, necessitatibus velit veniam, assumenda minima soluta, molestias rem eos harum reiciendis tempore consequatur? Vel quos similique rem, delectus maiores inventore quisquam ab asperiores explicabo accusantium quas doloribus iusto dolorem repellat. Necessitatibus repellendus consectetur hic autem perspiciatis voluptatibus, eius laudantium quas iste, nobis unde?

Totam numquam sunt iure recusandae harum nihil itaque assumenda facilis in repellat sed sapiente, esse blanditiis fuga aliquid pariatur architecto laboriosam. Id ex temporibus voluptatum maiores, error eveniet totam in ipsa beatae iure obcaecati corrupti, numquam nesciunt ipsum a dicta ad! Veritatis labore cum necessitatibus, a delectus doloremque voluptate ut blanditiis nisi atque soluta repellendus earum fugiat fugit totam harum commodi saepe! Totam qui cumque recusandae beatae unde atque nobis ipsa nihil

' +export const ControlledValue = ControlledValueTemplate.bind({}); +ControlledValue.args = { + // htmlValueSlow: + // '

Lorem ipsum dolor, sit amet consectetur adipisicing elit. Atque quaerat, minus suscipit totam nam sequi hic expedita quae fugit blanditiis ad voluptate eligendi adipisci. Quaerat similique numquam corporis molestias, blanditiis enim saepe accusamus debitis ipsa provident cumque voluptatum dolor beatae odit, odio ipsum maiores! Reiciendis, debitis fugiat consequuntur ex quae necessitatibus laboriosam sit quas et nam! Maxime, necessitatibus velit veniam, assumenda minima soluta, molestias rem eos harum reiciendis tempore consequatur? Vel quos similique rem, delectus maiores inventore quisquam ab asperiores explicabo accusantium quas doloribus iusto dolorem repellat. Necessitatibus repellendus consectetur hic autem perspiciatis voluptatibus, eius laudantium quas iste, nobis unde?

Totam numquam sunt iure recusandae harum nihil itaque assumenda facilis in repellat sed sapiente, esse blanditiis fuga aliquid pariatur architecto laboriosam. Id ex temporibus voluptatum maiores, error eveniet totam in ipsa beatae iure obcaecati corrupti, numquam nesciunt ipsum a dicta ad! Veritatis labore cum necessitatibus, a delectus doloremque voluptate ut blanditiis nisi atque soluta repellendus earum fugiat fugit totam harum commodi saepe! Totam qui cumque recusandae beatae unde atque nobis ipsa nihil

' }; /** diff --git a/src/components/WYSIWYGInput/helpers.tsx b/src/components/WYSIWYGInput/helpers.tsx index 12d4231..260aa04 100644 --- a/src/components/WYSIWYGInput/helpers.tsx +++ b/src/components/WYSIWYGInput/helpers.tsx @@ -7,17 +7,35 @@ import DOMPurify from 'isomorphic-dompurify'; * * @param htmlValue html value to set the editor state to * @param defaultDecorators the decorators setting to use if any + * @param editorState an existing editor state to derive to, if any */ -export const getStateFromHtml = async (htmlValue: string, defaultDecorators?: CompositeDecorator) => { +export const getStateFromHtml = async ( + htmlValue: string, + defaultDecorators?: CompositeDecorator, + editorState?: EditorState +) => { const htmlToDraft = (await import('html-to-draftjs')).default; // Ref(HTML part at the end): https://jpuri.github.io/react-draft-wysiwyg/#/docs const contentBlock = htmlToDraft(DOMPurify.sanitize(htmlValue, { ADD_ATTR: ['target'] })); - return EditorState.createWithContent( - ContentState.createFromBlockArray(contentBlock.contentBlocks, contentBlock.entityMap), - defaultDecorators - ); + if (!editorState) { + return EditorState.createWithContent( + ContentState.createFromBlockArray(contentBlock.contentBlocks, contentBlock.entityMap), + defaultDecorators + ); + } else { + const newEditorState = EditorState.createWithContent( + ContentState.createFromBlockArray(contentBlock.contentBlocks, contentBlock.entityMap), + defaultDecorators + ); + + const selection = editorState.getSelection(); + + EditorState.forceSelection(newEditorState, selection); + + return newEditorState; + } }; /** diff --git a/src/components/WYSIWYGInput/index.tsx b/src/components/WYSIWYGInput/index.tsx index ee6717a..2928680 100644 --- a/src/components/WYSIWYGInput/index.tsx +++ b/src/components/WYSIWYGInput/index.tsx @@ -183,7 +183,11 @@ export const WYSIWYGInput = forwardRef( useEffect(() => { // If the onChange prop is provided and we have initialized the component state if (onHtmlChangeSlow && isEditorStateInitialized.current && !wasLastStateUpdateFromHtmlValue.current) { - onHtmlChangeSlow(getSanitizedHtmlFromState(editorState, entityLinkTransform)); + const htmlSlow = getSanitizedHtmlFromState(editorState, entityLinkTransform); + if (htmlSlow !== lastHtmlValueSlow.current) { + onHtmlChangeSlow(htmlSlow); + lastHtmlValueSlow.current = htmlSlow; + } } // If the editor state changes }, [editorState, onHtmlChangeSlow]);