diff --git a/packages/sanity/src/structure/comments/src/components/pte/comment-input/CommentInput.tsx b/packages/sanity/src/structure/comments/src/components/pte/comment-input/CommentInput.tsx index c247b41bab5..d6d45dfb2b7 100644 --- a/packages/sanity/src/structure/comments/src/components/pte/comment-input/CommentInput.tsx +++ b/packages/sanity/src/structure/comments/src/components/pte/comment-input/CommentInput.tsx @@ -1,4 +1,9 @@ -import {type EditorChange, keyGenerator, PortableTextEditor} from '@sanity/portable-text-editor' +import { + type EditorChange, + keyGenerator, + PortableTextEditor, + type RenderBlockFunction, +} from '@sanity/portable-text-editor' import {type CurrentUser, type PortableTextBlock} from '@sanity/types' import {type AvatarSize, focusFirstDescendant, focusLastDescendant, Stack} from '@sanity/ui' import type * as React from 'react' @@ -6,6 +11,7 @@ import {forwardRef, useCallback, useImperativeHandle, useMemo, useRef, useState} import {type UserListWithPermissionsHookValue} from 'sanity' import {editorSchemaType} from '../config' +import {renderBlock as renderNormalBlock} from '../render' import {CommentInputDiscardDialog} from './CommentInputDiscardDialog' import {CommentInputInner} from './CommentInputInner' import {CommentInputProvider} from './CommentInputProvider' @@ -34,6 +40,7 @@ export interface CommentInputProps { onSubmit?: () => void placeholder?: React.ReactNode readOnly?: boolean + renderBlock?: RenderBlockFunction value: PortableTextBlock[] | null withAvatar?: boolean avatarSize?: AvatarSize @@ -75,6 +82,7 @@ export const CommentInput = forwardRef( onSubmit, placeholder, readOnly, + renderBlock = renderNormalBlock, value = EMPTY_ARRAY, withAvatar = true, } = props @@ -231,6 +239,7 @@ export const CommentInput = forwardRef( onKeyDown={onKeyDown} onSubmit={onSubmit && handleSubmit} placeholder={placeholder} + renderBlock={renderBlock} withAvatar={withAvatar} /> diff --git a/packages/sanity/src/structure/comments/src/components/pte/comment-input/CommentInputInner.tsx b/packages/sanity/src/structure/comments/src/components/pte/comment-input/CommentInputInner.tsx index 58406f1e539..24d1089f2e5 100644 --- a/packages/sanity/src/structure/comments/src/components/pte/comment-input/CommentInputInner.tsx +++ b/packages/sanity/src/structure/comments/src/components/pte/comment-input/CommentInputInner.tsx @@ -1,3 +1,4 @@ +import {type RenderBlockFunction} from '@sanity/portable-text-editor' import {type CurrentUser} from '@sanity/types' import {type AvatarSize, Box, Card, Flex, MenuDivider, Stack} from '@sanity/ui' // eslint-disable-next-line camelcase @@ -107,6 +108,7 @@ interface CommentInputInnerProps { onKeyDown?: (e: React.KeyboardEvent) => void onSubmit?: () => void placeholder?: React.ReactNode + renderBlock: RenderBlockFunction withAvatar?: boolean } @@ -120,6 +122,7 @@ export function CommentInputInner(props: CommentInputInnerProps) { onKeyDown, onSubmit, placeholder, + renderBlock, withAvatar, } = props @@ -164,6 +167,7 @@ export function CommentInputInner(props: CommentInputInnerProps) { onKeyDown={onKeyDown} onSubmit={onSubmit} placeholder={placeholder} + renderBlock={renderBlock} /> diff --git a/packages/sanity/src/structure/comments/src/components/pte/comment-input/Editable.tsx b/packages/sanity/src/structure/comments/src/components/pte/comment-input/Editable.tsx index 71e217d8a49..cffb52c649c 100644 --- a/packages/sanity/src/structure/comments/src/components/pte/comment-input/Editable.tsx +++ b/packages/sanity/src/structure/comments/src/components/pte/comment-input/Editable.tsx @@ -1,6 +1,7 @@ import { type EditorSelection, PortableTextEditable, + type RenderBlockFunction, usePortableTextEditorSelection, } from '@sanity/portable-text-editor' import {isPortableTextSpan, isPortableTextTextBlock} from '@sanity/types' @@ -15,7 +16,7 @@ import styled, {css} from 'styled-components' import {Popover, type PopoverProps} from '../../../../../../ui-components' import {commentsLocaleNamespace} from '../../../../i18n' import {MentionsMenu, type MentionsMenuHandle} from '../../mentions' -import {renderBlock, renderChild} from '../render' +import {renderChild} from '../render' import {useCommentInput} from './useCommentInput' import {useCursorElement} from './useCursorElement' @@ -65,6 +66,7 @@ interface EditableProps { onKeyDown?: (e: React.KeyboardEvent) => void onSubmit?: () => void placeholder?: React.ReactNode + renderBlock: RenderBlockFunction } export interface EditableHandle { @@ -75,11 +77,12 @@ export function Editable(props: EditableProps) { const {t} = useTranslation(commentsLocaleNamespace) const { focusLock, - placeholder = t('compose.create-comment-placeholder'), onFocus, onBlur, onKeyDown, onSubmit, + placeholder = t('compose.create-comment-placeholder'), + renderBlock, } = props const [popoverElement, setPopoverElement] = useState(null) const rootElementRef = useRef(null) @@ -126,19 +129,21 @@ export function Editable(props: EditableProps) { if (event.shiftKey) { break } - // Enter is being used both to select something from the mentionsMenu - // or to submit the comment. Prevent the default behavior. - event.preventDefault() - event.stopPropagation() // If the mention menu is open close it, but don't submit. if (mentionsMenuOpen) { + // Enter is being used both to select something from the mentionsMenu, prevent the default behavior. + event.preventDefault() + event.stopPropagation() closeMentions() break } // Submit the comment if eligible for submission if (onSubmit && canSubmit) { + // Enter is being used to submit the comment, prevent the default behavior. + event.preventDefault() + event.stopPropagation() onSubmit() } break diff --git a/packages/sanity/src/tasks/src/tasks/components/form/fields/DescriptionInput.tsx b/packages/sanity/src/tasks/src/tasks/components/form/fields/descriptionInput/DescriptionInput.tsx similarity index 73% rename from packages/sanity/src/tasks/src/tasks/components/form/fields/DescriptionInput.tsx rename to packages/sanity/src/tasks/src/tasks/components/form/fields/descriptionInput/DescriptionInput.tsx index b06ccf2c63e..a6de6772351 100644 --- a/packages/sanity/src/tasks/src/tasks/components/form/fields/DescriptionInput.tsx +++ b/packages/sanity/src/tasks/src/tasks/components/form/fields/descriptionInput/DescriptionInput.tsx @@ -1,6 +1,6 @@ // eslint-disable-next-line camelcase import {getTheme_v2} from '@sanity/ui/theme' -import {useCallback, useEffect, useRef, useState} from 'react' +import {startTransition, useCallback, useEffect, useState} from 'react' import { type ArrayFieldProps, type PortableTextBlock, @@ -10,10 +10,11 @@ import { } from 'sanity' import styled, {css} from 'styled-components' -import {CommentInput} from '../../../../../../structure/comments' -import {tasksLocaleNamespace} from '../../../../../i18n' -import {useMentionUser} from '../../../context' -import {type FormMode} from '../../../types' +import {CommentInput} from '../../../../../../../structure/comments' +import {tasksLocaleNamespace} from '../../../../../../i18n' +import {useMentionUser} from '../../../../context' +import {type FormMode} from '../../../../types' +import {renderBlock} from './render' const DescriptionInputRoot = styled.div<{$mode: FormMode; $minHeight: number}>((props) => { const theme = getTheme_v2(props.theme) @@ -43,39 +44,42 @@ export function DescriptionInput(props: ArrayFieldProps & {mode: FormMode}) { inputProps: {onChange}, } = props const value = _propValue as PortableTextBlock[] | undefined - const currentUser = useCurrentUser() const {mentionOptions} = useMentionUser() const handleChange = useCallback((next: PortableTextBlock[]) => onChange(set(next)), [onChange]) - const rootRef = useRef(null) + const [rootRef, setRootRef] = useState(null) const [textBoxScrollHeight, setTextBoxScrollHeight] = useState(200) const setTextboxHeight = useCallback((ref: HTMLDivElement) => { const textBox = ref.querySelector('[role="textbox"]') if (!textBox) return + const height = textBox.scrollHeight setTextBoxScrollHeight(height) }, []) - const setRootRef = useCallback( - (ref: HTMLDivElement) => { - if (!ref) return - setTextboxHeight(ref) - rootRef.current = ref - }, - [setTextboxHeight], - ) + const handleSetRootRef = useCallback((ref: HTMLDivElement) => { + if (!ref) return + startTransition(() => { + setRootRef(ref) + }) + }, []) + const {t} = useTranslation(tasksLocaleNamespace) useEffect(() => { - if (!rootRef.current) return - setTextboxHeight(rootRef.current) - }, [value, setTextboxHeight]) + if (!rootRef) return + setTextboxHeight(rootRef) + }, [value, setTextboxHeight, rootRef]) if (!currentUser) return null return ( - + null} + renderBlock={renderBlock} /> ) diff --git a/packages/sanity/src/tasks/src/tasks/components/form/fields/descriptionInput/blocks/DescriptionInputBlock.tsx b/packages/sanity/src/tasks/src/tasks/components/form/fields/descriptionInput/blocks/DescriptionInputBlock.tsx new file mode 100644 index 00000000000..d3072615510 --- /dev/null +++ b/packages/sanity/src/tasks/src/tasks/components/form/fields/descriptionInput/blocks/DescriptionInputBlock.tsx @@ -0,0 +1,21 @@ +import {Box, Text} from '@sanity/ui' +import type * as React from 'react' +import styled from 'styled-components' + +const NormalText = styled(Text)` + word-break: break-word; +` + +interface NormalBlockProps { + children: React.ReactNode +} + +export function DescriptionInputBlock(props: NormalBlockProps) { + const {children} = props + + return ( + + {children} + + ) +} diff --git a/packages/sanity/src/tasks/src/tasks/components/form/fields/descriptionInput/blocks/index.ts b/packages/sanity/src/tasks/src/tasks/components/form/fields/descriptionInput/blocks/index.ts new file mode 100644 index 00000000000..fd5dec25d76 --- /dev/null +++ b/packages/sanity/src/tasks/src/tasks/components/form/fields/descriptionInput/blocks/index.ts @@ -0,0 +1 @@ +export * from './DescriptionInputBlock' diff --git a/packages/sanity/src/tasks/src/tasks/components/form/fields/descriptionInput/index.ts b/packages/sanity/src/tasks/src/tasks/components/form/fields/descriptionInput/index.ts new file mode 100644 index 00000000000..dca5aa6dc89 --- /dev/null +++ b/packages/sanity/src/tasks/src/tasks/components/form/fields/descriptionInput/index.ts @@ -0,0 +1 @@ +export * from './DescriptionInput' diff --git a/packages/sanity/src/tasks/src/tasks/components/form/fields/descriptionInput/render/index.ts b/packages/sanity/src/tasks/src/tasks/components/form/fields/descriptionInput/render/index.ts new file mode 100644 index 00000000000..5216b26a70d --- /dev/null +++ b/packages/sanity/src/tasks/src/tasks/components/form/fields/descriptionInput/render/index.ts @@ -0,0 +1 @@ +export * from './renderBlock' diff --git a/packages/sanity/src/tasks/src/tasks/components/form/fields/descriptionInput/render/renderBlock.tsx b/packages/sanity/src/tasks/src/tasks/components/form/fields/descriptionInput/render/renderBlock.tsx new file mode 100644 index 00000000000..ba42af78491 --- /dev/null +++ b/packages/sanity/src/tasks/src/tasks/components/form/fields/descriptionInput/render/renderBlock.tsx @@ -0,0 +1,9 @@ +import {type RenderBlockFunction} from '@sanity/portable-text-editor' + +import {DescriptionInputBlock} from '../blocks' + +export const renderBlock: RenderBlockFunction = (blockProps) => { + const {children} = blockProps + + return {children} +} diff --git a/packages/sanity/src/tasks/src/tasks/components/form/fields/index.ts b/packages/sanity/src/tasks/src/tasks/components/form/fields/index.ts index a9e35a302b8..a194b73d5d1 100644 --- a/packages/sanity/src/tasks/src/tasks/components/form/fields/index.ts +++ b/packages/sanity/src/tasks/src/tasks/components/form/fields/index.ts @@ -1,6 +1,6 @@ export * from './assignee' export * from './DateEditFormField' -export * from './DescriptionInput' +export * from './descriptionInput' export * from './FieldWrapper' export * from './StatusSelector' export * from './TargetField' diff --git a/packages/sanity/src/tasks/src/tasks/components/form/tasksFormBuilder/TasksFormBuilder.tsx b/packages/sanity/src/tasks/src/tasks/components/form/tasksFormBuilder/TasksFormBuilder.tsx index 92c0e9cb3be..6398e7ccddc 100644 --- a/packages/sanity/src/tasks/src/tasks/components/form/tasksFormBuilder/TasksFormBuilder.tsx +++ b/packages/sanity/src/tasks/src/tasks/components/form/tasksFormBuilder/TasksFormBuilder.tsx @@ -1,6 +1,7 @@ import {Box, rem} from '@sanity/ui' // eslint-disable-next-line camelcase import {getTheme_v2} from '@sanity/ui/theme' +import {motion, type Variants} from 'framer-motion' import {useEffect, useMemo} from 'react' import { type CurrentUser, @@ -20,7 +21,15 @@ import {TasksAddonWorkspaceProvider} from '../addonWorkspace/TasksAddOnWorkspace import {getTargetValue} from '../utils' import {useTasksFormBuilder} from './useTasksFormBuilder' -const FormBuilderRoot = styled.div((props) => { +const VARIANTS: Variants = { + hidden: {opacity: 0}, + visible: { + opacity: 1, + transition: {duration: 0.2, delay: 0.2}, + }, +} + +const FormBuilderRoot = styled(motion.div)((props) => { const theme = getTheme_v2(props.theme) return ` @@ -67,7 +76,7 @@ const TasksFormBuilderInner = ({ {formBuilderProps.loading ? ( ) : ( - + )}