@dxos/react-ui-thread 0.4.10-main.4ae4df1 → 0.4.10-main.4c7b3fa
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib/browser/index.mjs.map +2 -2
- package/dist/lib/browser/meta.json +1 -1
- package/dist/types/src/Message/Message.d.ts.map +1 -1
- package/dist/types/src/Thread/Comments.stories.d.ts +2 -2
- package/dist/types/src/Thread/Comments.stories.d.ts.map +1 -1
- package/dist/types/src/Thread/Thread.stories.d.ts.map +1 -1
- package/package.json +14 -13
- package/src/Message/Message.tsx +1 -0
- package/src/Thread/Comments.stories.tsx +35 -26
- package/src/Thread/Thread.stories.tsx +25 -9
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/translations.ts", "../../../src/Thread/Thread.tsx", "../../../src/Message/Message.tsx"],
|
|
4
|
-
"sourcesContent": ["//\n// Copyright 2023 DXOS.org\n//\n\nexport const translationKey = 'thread';\n\nexport default [\n {\n 'en-US': {\n [translationKey]: {\n 'plugin name': 'Threads',\n 'thread title placeholder': 'New thread',\n 'thread title label': 'Title',\n 'delete thread label': 'Delete',\n 'create thread label': 'Create thread',\n 'message placeholder': 'Enter message...',\n 'comment placeholder': 'Enter comment...',\n 'settings standalone label': 'Enable standalone thread creation',\n 'anonymous label': 'Anonymous',\n 'enter to send message': 'Enter to add ⏎',\n },\n },\n },\n];\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport { ArrowBendLeftDown, Spinner } from '@phosphor-icons/react';\nimport React, { type ComponentProps, type ComponentPropsWithRef, forwardRef } from 'react';\n\nimport { type ThemedClassName, useTranslation } from '@dxos/react-ui';\nimport { hoverableControlItem, hoverableFocusedWithinControls, mx } from '@dxos/react-ui-theme';\n\nimport { translationKey } from '../translations';\nimport type { ThreadEntity } from '../types';\n\nexport type ThreadProps = ThemedClassName<ComponentPropsWithRef<'div'>> &\n ThreadEntity & { current?: boolean | ComponentProps<'div'>['aria-current'] };\n\nexport const threadLayout = 'is-full place-self-start grid grid-cols-[var(--rail-size)_1fr]';\n\nexport const Thread = forwardRef<HTMLDivElement, ThreadProps>(\n ({ current, children, classNames, ...props }, forwardedRef) => {\n return (\n <div\n role='group'\n data-testid='thread'\n {...(current && { 'aria-current': typeof current === 'string' ? current : 'location' })}\n {...props}\n className={mx(\n threadLayout,\n hoverableFocusedWithinControls,\n 'bg-[var(--surface-bg)] border-[color:var(--surface-separator)] border-bs border-be plb-1.5 attention attention-within attention-current [--controls-opacity:0]',\n classNames,\n )}\n ref={forwardedRef}\n >\n {children}\n </div>\n );\n },\n);\n\nexport type ThreadHeadingProps = ThemedClassName<ComponentPropsWithRef<'div'>> & { detached?: boolean };\n\nexport const ThreadHeading = forwardRef<HTMLParagraphElement, ThreadHeadingProps>(\n ({ classNames, children, detached, ...props }, forwardedRef) => {\n return (\n <>\n <div role='none' className='grid place-items-end pie-3.5 fg-description'>\n <ArrowBendLeftDown />\n </div>\n <p\n role='heading'\n data-testid='thread.heading'\n {...props}\n className={mx(\n 'fg-description font-medium truncate before:content-[open-quote] after:content-[close-quote]',\n detached && 'line-through decoration-1',\n )}\n ref={forwardedRef}\n >\n {children}\n </p>\n </>\n );\n },\n);\n\nexport type ThreadFooterProps = ThemedClassName<ComponentPropsWithRef<'div'>> & {\n activity?: boolean;\n};\n\nexport const ThreadFooter = forwardRef<HTMLDivElement, ThreadFooterProps>(\n ({ activity, classNames, children, ...props }, forwardedRef) => {\n const { t } = useTranslation(translationKey);\n return (\n <div\n {...props}\n className={mx('col-start-2 grid grid-cols-[min-content_1fr_max-content] text-xs fg-description', classNames)}\n ref={forwardedRef}\n >\n <Spinner\n weight='bold'\n data-visible={activity ? 'show' : 'hide'}\n className='is-6 bs-4 invisible data-[visible=show]:visible animate-spin-slow'\n />\n <span className='truncate min-is-0' aria-live='polite'>\n {activity ? children : null}\n </span>\n <span className={mx('text-end pie-1', hoverableControlItem)}>{t('enter to send message')}</span>\n </div>\n );\n },\n);\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport { X } from '@phosphor-icons/react';\nimport { formatDistanceToNow } from 'date-fns/formatDistanceToNow';\nimport React, { type ComponentPropsWithRef, type FC, forwardRef, useMemo } from 'react';\n\n// TODO(burdon): Remove dep.\nimport { Avatar, Button, type ThemedClassName, useTranslation } from '@dxos/react-ui';\nimport { type TextEditorProps, keymap, listener, TextEditor } from '@dxos/react-ui-editor';\nimport {\n focusRing,\n hoverableControlItem,\n hoverableControls,\n hoverableFocusedWithinControls,\n mx,\n} from '@dxos/react-ui-theme';\nimport { safeParseJson, hexToEmoji, hexToHue, isNotFalsy } from '@dxos/util';\n\nimport { translationKey } from '../translations';\nimport { type MessageEntity, type MessageEntityBlock, type MessageMetadata } from '../types';\n\nconst avatarSize = 7;\n\nexport type MessageMetaProps = ThemedClassName<ComponentPropsWithRef<'div'>> &\n MessageMetadata &\n Partial<{ continues: boolean }>;\n\nexport const MessageMeta = forwardRef<HTMLDivElement, MessageMetaProps>(\n (\n { authorImgSrc, authorId, authorName, authorAvatarProps, continues = true, children, classNames, ...rootProps },\n forwardedRef,\n ) => {\n return (\n <Avatar.Root size={avatarSize} hue={authorAvatarProps?.hue || hexToHue(authorId ?? '0')}>\n <div\n role='none'\n data-testid='thread.message'\n {...rootProps}\n className={mx('grid grid-cols-subgrid col-span-2', classNames)}\n ref={forwardedRef}\n >\n <div role='none' className={mx('flex flex-col items-center gap-2 plb-2')}>\n <Avatar.Frame>\n <Avatar.Fallback text={authorAvatarProps?.emoji || hexToEmoji(authorId ?? '0')} />\n {authorImgSrc && <Avatar.Image href={authorImgSrc} />}\n </Avatar.Frame>\n {continues && <div role='none' className='is-px grow surface-separator' />}\n </div>\n <div role='none' className='plb-1 min-is-0'>\n {children}\n </div>\n </div>\n </Avatar.Root>\n );\n },\n);\n\nexport type MessageBlockProps<BlockValue> = {\n block: MessageEntityBlock<BlockValue>;\n authorId?: string;\n onBlockDelete?: () => void;\n};\n\nconst DefaultMessageBlock = ({ block, onBlockDelete }: MessageBlockProps<{ data?: any; text?: string }>) => {\n const contentWidth = onBlockDelete ? 'col-span-2' : 'col-span-3';\n return (\n <div\n role='none'\n className={mx('grid grid-cols-subgrid col-span-3', hoverableControls, hoverableFocusedWithinControls)}\n >\n {block.data ? (\n <pre className={mx('font-mono max-is-full overflow-x-auto', contentWidth)}>\n <code>{JSON.stringify(safeParseJson(block.data), undefined, 2)}</code>\n </pre>\n ) : (\n <p className={contentWidth}>{block.text ?? ''}</p>\n )}\n {onBlockDelete && (\n <Button\n variant='ghost'\n classNames={['p-1.5 min-bs-0 mie-1 items-start transition-opacity', hoverableControlItem]}\n onClick={() => onBlockDelete()}\n >\n <X />\n </Button>\n )}\n </div>\n );\n};\n\nexport type MessageProps<BlockValue> = MessageEntity<BlockValue> & {\n onDelete?: (messageId: string, blockIndex: number) => void;\n MessageBlockComponent?: FC<MessageBlockProps<BlockValue>>;\n};\n\nexport const Message = <BlockValue,>(props: MessageProps<BlockValue>) => {\n const { id, authorName, onDelete, blocks, MessageBlockComponent = DefaultMessageBlock, ...metaProps } = props;\n const { t, dtLocale } = useTranslation(translationKey);\n const firstBlock = blocks[0];\n const dt = firstBlock.timestamp ? new Date(firstBlock.timestamp) : undefined;\n\n return (\n <MessageMeta {...metaProps} id={id} continues>\n <p className='grid grid-cols-[1fr_max-content] gap-2 pie-2'>\n <Avatar.Label classNames={['truncate text-sm font-medium', !authorName && 'fg-description']}>\n {authorName ?? t('anonymous label')}\n </Avatar.Label>\n <time className='fg-description text-xs pbs-0.5' dateTime={dt?.toISOString()}>\n {dt ? formatDistanceToNow(dt, { locale: dtLocale, addSuffix: true }) : ''}\n </time>\n </p>\n <div role='none' className='grid gap-y-1 grid-cols-[min-content_1fr_min-content]'>\n {blocks.map((block, i) => (\n <MessageBlockComponent\n key={i}\n block={block}\n authorId={metaProps.authorId}\n onBlockDelete={onDelete && (() => onDelete(id, i))}\n />\n ))}\n </div>\n </MessageMeta>\n );\n};\n\nexport type MessageTextboxProps = {\n disabled?: boolean;\n onSend?: () => void;\n onClear?: () => void;\n onEditorFocus?: () => void;\n} & MessageMetadata &\n TextEditorProps;\n\nconst keyBindings = ({ onSend, onClear }: Pick<MessageTextboxProps, 'onSend' | 'onClear'>) => [\n {\n key: 'Enter',\n run: () => {\n if (onSend) {\n onSend();\n return true;\n } else {\n return false;\n }\n },\n },\n {\n // TODO(burdon): Other key bindings.\n key: 'Meta+Backspace',\n run: () => {\n if (onClear) {\n onClear();\n return true;\n } else {\n return false;\n }\n },\n },\n];\n\nexport const MessageTextbox = ({\n id,\n onSend,\n onClear,\n onEditorFocus,\n authorId,\n authorName,\n authorImgSrc,\n authorAvatarProps,\n disabled,\n extensions: _extensions,\n ...editorProps\n}: MessageTextboxProps) => {\n const extensions = useMemo<TextEditorProps['extensions']>(() => {\n return [\n keymap.of(keyBindings({ onSend, onClear })),\n listener({\n onFocus: (focusing) => {\n if (focusing) {\n onEditorFocus?.();\n }\n },\n }),\n _extensions,\n ].filter(isNotFalsy);\n }, [_extensions]);\n\n return (\n <MessageMeta {...{ id, authorId, authorName, authorImgSrc, authorAvatarProps }} continues={false}>\n <TextEditor\n {...editorProps}\n extensions={extensions}\n className={mx('plb-0.5 mie-1 rounded-sm', focusRing, disabled && 'opacity-50')}\n />\n </MessageMeta>\n );\n};\n"],
|
|
5
|
-
"mappings": "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
|
|
4
|
+
"sourcesContent": ["//\n// Copyright 2023 DXOS.org\n//\n\nexport const translationKey = 'thread';\n\nexport default [\n {\n 'en-US': {\n [translationKey]: {\n 'plugin name': 'Threads',\n 'thread title placeholder': 'New thread',\n 'thread title label': 'Title',\n 'delete thread label': 'Delete',\n 'create thread label': 'Create thread',\n 'message placeholder': 'Enter message...',\n 'comment placeholder': 'Enter comment...',\n 'settings standalone label': 'Enable standalone thread creation',\n 'anonymous label': 'Anonymous',\n 'enter to send message': 'Enter to add ⏎',\n },\n },\n },\n];\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport { ArrowBendLeftDown, Spinner } from '@phosphor-icons/react';\nimport React, { type ComponentProps, type ComponentPropsWithRef, forwardRef } from 'react';\n\nimport { type ThemedClassName, useTranslation } from '@dxos/react-ui';\nimport { hoverableControlItem, hoverableFocusedWithinControls, mx } from '@dxos/react-ui-theme';\n\nimport { translationKey } from '../translations';\nimport type { ThreadEntity } from '../types';\n\nexport type ThreadProps = ThemedClassName<ComponentPropsWithRef<'div'>> &\n ThreadEntity & { current?: boolean | ComponentProps<'div'>['aria-current'] };\n\nexport const threadLayout = 'is-full place-self-start grid grid-cols-[var(--rail-size)_1fr]';\n\nexport const Thread = forwardRef<HTMLDivElement, ThreadProps>(\n ({ current, children, classNames, ...props }, forwardedRef) => {\n return (\n <div\n role='group'\n data-testid='thread'\n {...(current && { 'aria-current': typeof current === 'string' ? current : 'location' })}\n {...props}\n className={mx(\n threadLayout,\n hoverableFocusedWithinControls,\n 'bg-[var(--surface-bg)] border-[color:var(--surface-separator)] border-bs border-be plb-1.5 attention attention-within attention-current [--controls-opacity:0]',\n classNames,\n )}\n ref={forwardedRef}\n >\n {children}\n </div>\n );\n },\n);\n\nexport type ThreadHeadingProps = ThemedClassName<ComponentPropsWithRef<'div'>> & { detached?: boolean };\n\nexport const ThreadHeading = forwardRef<HTMLParagraphElement, ThreadHeadingProps>(\n ({ classNames, children, detached, ...props }, forwardedRef) => {\n return (\n <>\n <div role='none' className='grid place-items-end pie-3.5 fg-description'>\n <ArrowBendLeftDown />\n </div>\n <p\n role='heading'\n data-testid='thread.heading'\n {...props}\n className={mx(\n 'fg-description font-medium truncate before:content-[open-quote] after:content-[close-quote]',\n detached && 'line-through decoration-1',\n )}\n ref={forwardedRef}\n >\n {children}\n </p>\n </>\n );\n },\n);\n\nexport type ThreadFooterProps = ThemedClassName<ComponentPropsWithRef<'div'>> & {\n activity?: boolean;\n};\n\nexport const ThreadFooter = forwardRef<HTMLDivElement, ThreadFooterProps>(\n ({ activity, classNames, children, ...props }, forwardedRef) => {\n const { t } = useTranslation(translationKey);\n return (\n <div\n {...props}\n className={mx('col-start-2 grid grid-cols-[min-content_1fr_max-content] text-xs fg-description', classNames)}\n ref={forwardedRef}\n >\n <Spinner\n weight='bold'\n data-visible={activity ? 'show' : 'hide'}\n className='is-6 bs-4 invisible data-[visible=show]:visible animate-spin-slow'\n />\n <span className='truncate min-is-0' aria-live='polite'>\n {activity ? children : null}\n </span>\n <span className={mx('text-end pie-1', hoverableControlItem)}>{t('enter to send message')}</span>\n </div>\n );\n },\n);\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport { X } from '@phosphor-icons/react';\nimport { formatDistanceToNow } from 'date-fns/formatDistanceToNow';\nimport React, { type ComponentPropsWithRef, type FC, forwardRef, useMemo } from 'react';\n\n// TODO(burdon): Remove dep.\nimport { Avatar, Button, type ThemedClassName, useTranslation } from '@dxos/react-ui';\nimport { type TextEditorProps, keymap, listener, TextEditor } from '@dxos/react-ui-editor';\nimport {\n focusRing,\n hoverableControlItem,\n hoverableControls,\n hoverableFocusedWithinControls,\n mx,\n} from '@dxos/react-ui-theme';\nimport { safeParseJson, hexToEmoji, hexToHue, isNotFalsy } from '@dxos/util';\n\nimport { translationKey } from '../translations';\nimport { type MessageEntity, type MessageEntityBlock, type MessageMetadata } from '../types';\n\nconst avatarSize = 7;\n\nexport type MessageMetaProps = ThemedClassName<ComponentPropsWithRef<'div'>> &\n MessageMetadata &\n Partial<{ continues: boolean }>;\n\nexport const MessageMeta = forwardRef<HTMLDivElement, MessageMetaProps>(\n (\n { authorImgSrc, authorId, authorName, authorAvatarProps, continues = true, children, classNames, ...rootProps },\n forwardedRef,\n ) => {\n return (\n <Avatar.Root size={avatarSize} hue={authorAvatarProps?.hue || hexToHue(authorId ?? '0')}>\n <div\n role='none'\n data-testid='thread.message'\n {...rootProps}\n className={mx('grid grid-cols-subgrid col-span-2', classNames)}\n ref={forwardedRef}\n >\n <div role='none' className={mx('flex flex-col items-center gap-2 plb-2')}>\n <Avatar.Frame>\n <Avatar.Fallback text={authorAvatarProps?.emoji || hexToEmoji(authorId ?? '0')} />\n {authorImgSrc && <Avatar.Image href={authorImgSrc} />}\n </Avatar.Frame>\n {continues && <div role='none' className='is-px grow surface-separator' />}\n </div>\n <div role='none' className='plb-1 min-is-0'>\n {children}\n </div>\n </div>\n </Avatar.Root>\n );\n },\n);\n\nexport type MessageBlockProps<BlockValue> = {\n block: MessageEntityBlock<BlockValue>;\n authorId?: string;\n onBlockDelete?: () => void;\n};\n\nconst DefaultMessageBlock = ({ block, onBlockDelete }: MessageBlockProps<{ data?: any; text?: string }>) => {\n const contentWidth = onBlockDelete ? 'col-span-2' : 'col-span-3';\n return (\n <div\n role='none'\n className={mx('grid grid-cols-subgrid col-span-3', hoverableControls, hoverableFocusedWithinControls)}\n >\n {block.data ? (\n <pre className={mx('font-mono max-is-full overflow-x-auto', contentWidth)}>\n <code>{JSON.stringify(safeParseJson(block.data), undefined, 2)}</code>\n </pre>\n ) : (\n <p className={contentWidth}>{block.text ?? ''}</p>\n )}\n {onBlockDelete && (\n <Button\n variant='ghost'\n classNames={['p-1.5 min-bs-0 mie-1 items-start transition-opacity', hoverableControlItem]}\n onClick={() => onBlockDelete()}\n >\n <X />\n </Button>\n )}\n </div>\n );\n};\n\nexport type MessageProps<BlockValue> = MessageEntity<BlockValue> & {\n onDelete?: (messageId: string, blockIndex: number) => void;\n MessageBlockComponent?: FC<MessageBlockProps<BlockValue>>;\n};\n\nexport const Message = <BlockValue,>(props: MessageProps<BlockValue>) => {\n const { id, authorName, onDelete, blocks, MessageBlockComponent = DefaultMessageBlock, ...metaProps } = props;\n const { t, dtLocale } = useTranslation(translationKey);\n const firstBlock = blocks[0];\n const dt = firstBlock.timestamp ? new Date(firstBlock.timestamp) : undefined;\n\n return (\n <MessageMeta {...metaProps} id={id} continues>\n <p className='grid grid-cols-[1fr_max-content] gap-2 pie-2'>\n <Avatar.Label classNames={['truncate text-sm font-medium', !authorName && 'fg-description']}>\n {authorName ?? t('anonymous label')}\n </Avatar.Label>\n <time className='fg-description text-xs pbs-0.5' dateTime={dt?.toISOString()}>\n {dt ? formatDistanceToNow(dt, { locale: dtLocale, addSuffix: true }) : ''}\n </time>\n </p>\n <div role='none' className='grid gap-y-1 grid-cols-[min-content_1fr_min-content]'>\n {blocks.map((block, i) => (\n <MessageBlockComponent\n key={i}\n block={block}\n authorId={metaProps.authorId}\n onBlockDelete={onDelete && (() => onDelete(id, i))}\n />\n ))}\n </div>\n </MessageMeta>\n );\n};\n\nexport type MessageTextboxProps = {\n disabled?: boolean;\n onSend?: () => void;\n onClear?: () => void;\n onEditorFocus?: () => void;\n} & MessageMetadata &\n TextEditorProps;\n\nconst keyBindings = ({ onSend, onClear }: Pick<MessageTextboxProps, 'onSend' | 'onClear'>) => [\n {\n key: 'Enter',\n run: () => {\n if (onSend) {\n onSend();\n return true;\n } else {\n return false;\n }\n },\n },\n {\n // TODO(burdon): Other key bindings.\n key: 'Meta+Backspace',\n run: () => {\n if (onClear) {\n onClear();\n return true;\n } else {\n return false;\n }\n },\n },\n];\n\nexport const MessageTextbox = ({\n id,\n onSend,\n onClear,\n onEditorFocus,\n authorId,\n authorName,\n authorImgSrc,\n authorAvatarProps,\n disabled,\n extensions: _extensions,\n ...editorProps\n}: MessageTextboxProps) => {\n const extensions = useMemo<TextEditorProps['extensions']>(() => {\n return [\n keymap.of(keyBindings({ onSend, onClear })),\n listener({\n onFocus: (focusing) => {\n if (focusing) {\n onEditorFocus?.();\n }\n },\n }),\n _extensions,\n ].filter(isNotFalsy);\n // TODO(wittjosiah): Should probably include callbacks in the dependency array.\n }, [_extensions]);\n\n return (\n <MessageMeta {...{ id, authorId, authorName, authorImgSrc, authorAvatarProps }} continues={false}>\n <TextEditor\n {...editorProps}\n extensions={extensions}\n className={mx('plb-0.5 mie-1 rounded-sm', focusRing, disabled && 'opacity-50')}\n />\n </MessageMeta>\n );\n};\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["translationKey", "ArrowBendLeftDown", "Spinner", "React", "forwardRef", "useTranslation", "hoverableControlItem", "hoverableFocusedWithinControls", "mx", "threadLayout", "Thread", "forwardRef", "current", "children", "classNames", "props", "forwardedRef", "div", "role", "data-testid", "className", "mx", "hoverableFocusedWithinControls", "ref", "ThreadHeading", "detached", "ArrowBendLeftDown", "p", "ThreadFooter", "activity", "t", "useTranslation", "translationKey", "Spinner", "weight", "data-visible", "span", "aria-live", "hoverableControlItem", "X", "formatDistanceToNow", "React", "forwardRef", "useMemo", "Avatar", "Button", "useTranslation", "keymap", "listener", "TextEditor", "focusRing", "hoverableControlItem", "hoverableControls", "hoverableFocusedWithinControls", "mx", "safeParseJson", "hexToEmoji", "hexToHue", "isNotFalsy", "avatarSize", "MessageMeta", "forwardRef", "authorImgSrc", "authorId", "authorName", "authorAvatarProps", "continues", "children", "classNames", "rootProps", "forwardedRef", "React", "Avatar", "Root", "size", "hue", "hexToHue", "div", "role", "data-testid", "className", "mx", "ref", "Frame", "Fallback", "text", "emoji", "hexToEmoji", "Image", "href", "DefaultMessageBlock", "block", "onBlockDelete", "contentWidth", "hoverableControls", "hoverableFocusedWithinControls", "data", "pre", "code", "JSON", "stringify", "safeParseJson", "undefined", "p", "Button", "variant", "hoverableControlItem", "onClick", "X", "Message", "props", "id", "onDelete", "blocks", "MessageBlockComponent", "metaProps", "t", "dtLocale", "useTranslation", "translationKey", "firstBlock", "dt", "timestamp", "Date", "Label", "time", "dateTime", "toISOString", "formatDistanceToNow", "locale", "addSuffix", "map", "i", "key", "keyBindings", "onSend", "onClear", "run", "MessageTextbox", "onEditorFocus", "disabled", "extensions", "_extensions", "editorProps", "useMemo", "keymap", "of", "listener", "onFocus", "focusing", "filter", "isNotFalsy", "TextEditor", "focusRing"]
|
|
7
7
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"inputs":{"packages/ui/react-ui-thread/src/translations.ts":{"bytes":2281,"imports":[],"format":"esm"},"packages/ui/react-ui-thread/src/Thread/Thread.tsx":{"bytes":9343,"imports":[{"path":"@phosphor-icons/react","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"@dxos/react-ui","kind":"import-statement","external":true},{"path":"@dxos/react-ui-theme","kind":"import-statement","external":true},{"path":"packages/ui/react-ui-thread/src/translations.ts","kind":"import-statement","original":"../translations"}],"format":"esm"},"packages/ui/react-ui-thread/src/Thread/index.ts":{"bytes":472,"imports":[{"path":"packages/ui/react-ui-thread/src/Thread/Thread.tsx","kind":"import-statement","original":"./Thread"}],"format":"esm"},"packages/ui/react-ui-thread/src/Message/Message.tsx":{"bytes":
|
|
1
|
+
{"inputs":{"packages/ui/react-ui-thread/src/translations.ts":{"bytes":2281,"imports":[],"format":"esm"},"packages/ui/react-ui-thread/src/Thread/Thread.tsx":{"bytes":9343,"imports":[{"path":"@phosphor-icons/react","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"@dxos/react-ui","kind":"import-statement","external":true},{"path":"@dxos/react-ui-theme","kind":"import-statement","external":true},{"path":"packages/ui/react-ui-thread/src/translations.ts","kind":"import-statement","original":"../translations"}],"format":"esm"},"packages/ui/react-ui-thread/src/Thread/index.ts":{"bytes":472,"imports":[{"path":"packages/ui/react-ui-thread/src/Thread/Thread.tsx","kind":"import-statement","original":"./Thread"}],"format":"esm"},"packages/ui/react-ui-thread/src/Message/Message.tsx":{"bytes":20183,"imports":[{"path":"@phosphor-icons/react","kind":"import-statement","external":true},{"path":"date-fns/formatDistanceToNow","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"@dxos/react-ui","kind":"import-statement","external":true},{"path":"@dxos/react-ui-editor","kind":"import-statement","external":true},{"path":"@dxos/react-ui-theme","kind":"import-statement","external":true},{"path":"@dxos/util","kind":"import-statement","external":true},{"path":"packages/ui/react-ui-thread/src/translations.ts","kind":"import-statement","original":"../translations"}],"format":"esm"},"packages/ui/react-ui-thread/src/Message/index.ts":{"bytes":474,"imports":[{"path":"packages/ui/react-ui-thread/src/Message/Message.tsx","kind":"import-statement","original":"./Message"}],"format":"esm"},"packages/ui/react-ui-thread/src/types.ts":{"bytes":1115,"imports":[],"format":"esm"},"packages/ui/react-ui-thread/src/index.ts":{"bytes":877,"imports":[{"path":"packages/ui/react-ui-thread/src/translations.ts","kind":"import-statement","original":"./translations"},{"path":"packages/ui/react-ui-thread/src/Thread/index.ts","kind":"import-statement","original":"./Thread"},{"path":"packages/ui/react-ui-thread/src/Message/index.ts","kind":"import-statement","original":"./Message"},{"path":"packages/ui/react-ui-thread/src/types.ts","kind":"import-statement","original":"./types"}],"format":"esm"}},"outputs":{"packages/ui/react-ui-thread/dist/lib/browser/index.mjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":16909},"packages/ui/react-ui-thread/dist/lib/browser/index.mjs":{"imports":[{"path":"@phosphor-icons/react","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"@dxos/react-ui","kind":"import-statement","external":true},{"path":"@dxos/react-ui-theme","kind":"import-statement","external":true},{"path":"@phosphor-icons/react","kind":"import-statement","external":true},{"path":"date-fns/formatDistanceToNow","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"@dxos/react-ui","kind":"import-statement","external":true},{"path":"@dxos/react-ui-editor","kind":"import-statement","external":true},{"path":"@dxos/react-ui-theme","kind":"import-statement","external":true},{"path":"@dxos/util","kind":"import-statement","external":true}],"exports":["Message","MessageMeta","MessageTextbox","Thread","ThreadFooter","ThreadHeading","threadLayout","translations"],"entryPoint":"packages/ui/react-ui-thread/src/index.ts","inputs":{"packages/ui/react-ui-thread/src/translations.ts":{"bytesInOutput":609},"packages/ui/react-ui-thread/src/Thread/Thread.tsx":{"bytesInOutput":2487},"packages/ui/react-ui-thread/src/Thread/index.ts":{"bytesInOutput":0},"packages/ui/react-ui-thread/src/index.ts":{"bytesInOutput":0},"packages/ui/react-ui-thread/src/Message/Message.tsx":{"bytesInOutput":5333},"packages/ui/react-ui-thread/src/Message/index.ts":{"bytesInOutput":0}},"bytes":8779}}}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Message.d.ts","sourceRoot":"","sources":["../../../../src/Message/Message.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,EAAE,KAAK,qBAAqB,EAAE,KAAK,EAAE,EAAuB,MAAM,OAAO,CAAC;AAGxF,OAAO,EAAkB,KAAK,eAAe,EAAkB,MAAM,gBAAgB,CAAC;AACtF,OAAO,EAAE,KAAK,eAAe,EAAgC,MAAM,uBAAuB,CAAC;AAW3F,OAAO,EAAE,KAAK,aAAa,EAAE,KAAK,kBAAkB,EAAE,KAAK,eAAe,EAAE,MAAM,UAAU,CAAC;AAI7F,MAAM,MAAM,gBAAgB,GAAG,eAAe,CAAC,qBAAqB,CAAC,KAAK,CAAC,CAAC,GAC1E,eAAe,GACf,OAAO,CAAC;IAAE,SAAS,EAAE,OAAO,CAAA;CAAE,CAAC,CAAC;AAElC,eAAO,MAAM,WAAW,qnJA4BvB,CAAC;AAEF,MAAM,MAAM,iBAAiB,CAAC,UAAU,IAAI;IAC1C,KAAK,EAAE,kBAAkB,CAAC,UAAU,CAAC,CAAC;IACtC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,aAAa,CAAC,EAAE,MAAM,IAAI,CAAC;CAC5B,CAAC;AA6BF,MAAM,MAAM,YAAY,CAAC,UAAU,IAAI,aAAa,CAAC,UAAU,CAAC,GAAG;IACjE,QAAQ,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3D,qBAAqB,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,UAAU,CAAC,CAAC,CAAC;CAC3D,CAAC;AAEF,eAAO,MAAM,OAAO,8DA4BnB,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAChC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,IAAI,CAAC;CAC5B,GAAG,eAAe,GACjB,eAAe,CAAC;AA4BlB,eAAO,MAAM,cAAc,qJAYxB,mBAAmB,
|
|
1
|
+
{"version":3,"file":"Message.d.ts","sourceRoot":"","sources":["../../../../src/Message/Message.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,EAAE,KAAK,qBAAqB,EAAE,KAAK,EAAE,EAAuB,MAAM,OAAO,CAAC;AAGxF,OAAO,EAAkB,KAAK,eAAe,EAAkB,MAAM,gBAAgB,CAAC;AACtF,OAAO,EAAE,KAAK,eAAe,EAAgC,MAAM,uBAAuB,CAAC;AAW3F,OAAO,EAAE,KAAK,aAAa,EAAE,KAAK,kBAAkB,EAAE,KAAK,eAAe,EAAE,MAAM,UAAU,CAAC;AAI7F,MAAM,MAAM,gBAAgB,GAAG,eAAe,CAAC,qBAAqB,CAAC,KAAK,CAAC,CAAC,GAC1E,eAAe,GACf,OAAO,CAAC;IAAE,SAAS,EAAE,OAAO,CAAA;CAAE,CAAC,CAAC;AAElC,eAAO,MAAM,WAAW,qnJA4BvB,CAAC;AAEF,MAAM,MAAM,iBAAiB,CAAC,UAAU,IAAI;IAC1C,KAAK,EAAE,kBAAkB,CAAC,UAAU,CAAC,CAAC;IACtC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,aAAa,CAAC,EAAE,MAAM,IAAI,CAAC;CAC5B,CAAC;AA6BF,MAAM,MAAM,YAAY,CAAC,UAAU,IAAI,aAAa,CAAC,UAAU,CAAC,GAAG;IACjE,QAAQ,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3D,qBAAqB,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,UAAU,CAAC,CAAC,CAAC;CAC3D,CAAC;AAEF,eAAO,MAAM,OAAO,8DA4BnB,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAChC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,IAAI,CAAC;CAC5B,GAAG,eAAe,GACjB,eAAe,CAAC;AA4BlB,eAAO,MAAM,cAAc,qJAYxB,mBAAmB,gBAyBrB,CAAC"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import '@dxosTheme';
|
|
2
2
|
import React from 'react';
|
|
3
|
-
import {
|
|
3
|
+
import { TextV0Type } from '@braneframe/types';
|
|
4
4
|
import { type Range } from '@dxos/react-ui-editor';
|
|
5
5
|
import { type MessageEntity } from '../types';
|
|
6
6
|
type StoryCommentThread = {
|
|
@@ -9,7 +9,7 @@ type StoryCommentThread = {
|
|
|
9
9
|
range?: Range;
|
|
10
10
|
yPos?: number;
|
|
11
11
|
messages: MessageEntity<{
|
|
12
|
-
|
|
12
|
+
content?: TextV0Type;
|
|
13
13
|
}>[];
|
|
14
14
|
};
|
|
15
15
|
type StoryProps = {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Comments.stories.d.ts","sourceRoot":"","sources":["../../../../src/Thread/Comments.stories.tsx"],"names":[],"mappings":"AAIA,OAAO,YAAY,CAAC;AAGpB,OAAO,KAAwD,MAAM,OAAO,CAAC;AAE7E,OAAO,
|
|
1
|
+
{"version":3,"file":"Comments.stories.d.ts","sourceRoot":"","sources":["../../../../src/Thread/Comments.stories.tsx"],"names":[],"mappings":"AAIA,OAAO,YAAY,CAAC;AAGpB,OAAO,KAAwD,MAAM,OAAO,CAAC;AAE7E,OAAO,EAAe,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAM5D,OAAO,EAML,KAAK,KAAK,EAMX,MAAM,uBAAuB,CAAC;AAM/B,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,UAAU,CAAC;AAoE9C,KAAK,kBAAkB,GAAG;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,aAAa,CAAC;QAAE,OAAO,CAAC,EAAE,UAAU,CAAA;KAAE,CAAC,EAAE,CAAC;CACrD,CAAC;AA6IF,KAAK,UAAU,GAAG;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB,CAAC;;;;;;;;;;mBA+He,UAAU;;;;;;;;;;;;;;;;;;;;;AAJ3B,wBAME;AAWF,eAAO,MAAM,OAAO;;;;CAInB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Thread.stories.d.ts","sourceRoot":"","sources":["../../../../src/Thread/Thread.stories.tsx"],"names":[],"mappings":"AAIA,OAAO,YAAY,CAAC;AACpB,OAAO,
|
|
1
|
+
{"version":3,"file":"Thread.stories.d.ts","sourceRoot":"","sources":["../../../../src/Thread/Thread.stories.tsx"],"names":[],"mappings":"AAIA,OAAO,YAAY,CAAC;AACpB,OAAO,KAAoC,MAAM,OAAO,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;AAwFzD,wBAME;AAEF,eAAO,MAAM,OAAO,IAAK,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dxos/react-ui-thread",
|
|
3
|
-
"version": "0.4.10-main.
|
|
3
|
+
"version": "0.4.10-main.4c7b3fa",
|
|
4
4
|
"description": "A set of components to use with threads, including comments and messages.",
|
|
5
5
|
"homepage": "https://dxos.org",
|
|
6
6
|
"bugs": "https://github.com/dxos/dxos/issues",
|
|
@@ -18,25 +18,26 @@
|
|
|
18
18
|
"dependencies": {
|
|
19
19
|
"@radix-ui/react-primitive": "^1.0.2",
|
|
20
20
|
"date-fns": "^3.3.1",
|
|
21
|
-
"@dxos/react-ui": "0.4.10-main.
|
|
22
|
-
"@dxos/react-ui-editor": "0.4.10-main.
|
|
23
|
-
"@dxos/
|
|
24
|
-
"@dxos/react-ui-
|
|
25
|
-
"@dxos/
|
|
21
|
+
"@dxos/react-ui": "0.4.10-main.4c7b3fa",
|
|
22
|
+
"@dxos/react-ui-editor": "0.4.10-main.4c7b3fa",
|
|
23
|
+
"@dxos/react-ui-theme": "0.4.10-main.4c7b3fa",
|
|
24
|
+
"@dxos/react-ui-mosaic": "0.4.10-main.4c7b3fa",
|
|
25
|
+
"@dxos/util": "0.4.10-main.4c7b3fa"
|
|
26
26
|
},
|
|
27
27
|
"devDependencies": {
|
|
28
|
-
"@phosphor-icons/react": "^2.
|
|
28
|
+
"@phosphor-icons/react": "^2.1.5",
|
|
29
29
|
"@types/react": "^18.0.21",
|
|
30
30
|
"@types/react-dom": "^18.0.6",
|
|
31
31
|
"react": "^18.2.0",
|
|
32
32
|
"react-dom": "^18.2.0",
|
|
33
|
-
"vite": "^5.
|
|
33
|
+
"vite": "^5.2.9",
|
|
34
34
|
"vite-plugin-turbosnap": "^1.0.2",
|
|
35
|
-
"@
|
|
36
|
-
"@dxos/echo-schema": "0.4.10-main.
|
|
37
|
-
"@dxos/
|
|
38
|
-
"@dxos/
|
|
39
|
-
"@dxos/
|
|
35
|
+
"@braneframe/types": "0.4.10-main.4c7b3fa",
|
|
36
|
+
"@dxos/echo-schema": "0.4.10-main.4c7b3fa",
|
|
37
|
+
"@dxos/keys": "0.4.10-main.4c7b3fa",
|
|
38
|
+
"@dxos/log": "0.4.10-main.4c7b3fa",
|
|
39
|
+
"@dxos/random": "0.4.10-main.4c7b3fa",
|
|
40
|
+
"@dxos/storybook-utils": "0.4.10-main.4c7b3fa"
|
|
40
41
|
},
|
|
41
42
|
"peerDependencies": {
|
|
42
43
|
"@phosphor-icons/react": "^2.0.5",
|
package/src/Message/Message.tsx
CHANGED
|
@@ -7,7 +7,8 @@ import '@dxosTheme';
|
|
|
7
7
|
import { Check, Trash } from '@phosphor-icons/react';
|
|
8
8
|
import React, { type FC, useEffect, useMemo, useRef, useState } from 'react';
|
|
9
9
|
|
|
10
|
-
import {
|
|
10
|
+
import { MessageType, TextV0Type } from '@braneframe/types';
|
|
11
|
+
import { createDocAccessor, create, createEchoObject } from '@dxos/echo-schema';
|
|
11
12
|
import { PublicKey } from '@dxos/keys';
|
|
12
13
|
import { log } from '@dxos/log';
|
|
13
14
|
import { faker } from '@dxos/random';
|
|
@@ -23,7 +24,7 @@ import {
|
|
|
23
24
|
createBasicExtensions,
|
|
24
25
|
createThemeExtensions,
|
|
25
26
|
automerge,
|
|
26
|
-
|
|
27
|
+
listener,
|
|
27
28
|
} from '@dxos/react-ui-editor';
|
|
28
29
|
import { withTheme } from '@dxos/storybook-utils';
|
|
29
30
|
|
|
@@ -42,7 +43,7 @@ const authorId = PublicKey.random().toHex();
|
|
|
42
43
|
|
|
43
44
|
const Editor: FC<{
|
|
44
45
|
id?: string;
|
|
45
|
-
item:
|
|
46
|
+
item: TextV0Type;
|
|
46
47
|
comments: Comment[];
|
|
47
48
|
selected?: string;
|
|
48
49
|
onCreateComment: CommentsOptions['onCreate'];
|
|
@@ -62,16 +63,16 @@ const Editor: FC<{
|
|
|
62
63
|
const [selected, setSelected] = useState<string>();
|
|
63
64
|
|
|
64
65
|
const { themeMode } = useThemeContext();
|
|
65
|
-
const { doc, accessor } = useDocAccessor(item.text);
|
|
66
66
|
const { parentRef, view } = useTextEditor(
|
|
67
67
|
() => ({
|
|
68
68
|
id,
|
|
69
|
-
doc,
|
|
69
|
+
doc: item.content,
|
|
70
70
|
extensions: [
|
|
71
71
|
createBasicExtensions(),
|
|
72
72
|
createThemeExtensions({ themeMode }),
|
|
73
|
-
automerge(
|
|
73
|
+
automerge(createDocAccessor(item, ['content'])),
|
|
74
74
|
comments({
|
|
75
|
+
id,
|
|
75
76
|
onCreate: onCreateComment,
|
|
76
77
|
onDelete: onDeleteComment,
|
|
77
78
|
onUpdate: onUpdateComment,
|
|
@@ -79,7 +80,7 @@ const Editor: FC<{
|
|
|
79
80
|
}),
|
|
80
81
|
],
|
|
81
82
|
}),
|
|
82
|
-
[
|
|
83
|
+
[id, item, themeMode],
|
|
83
84
|
);
|
|
84
85
|
useComments(view, id, commentRanges);
|
|
85
86
|
useEffect(() => {
|
|
@@ -103,12 +104,13 @@ type StoryCommentThread = {
|
|
|
103
104
|
cursor?: string;
|
|
104
105
|
range?: Range;
|
|
105
106
|
yPos?: number;
|
|
106
|
-
messages: MessageEntity<{
|
|
107
|
+
messages: MessageEntity<{ content?: TextV0Type }>[];
|
|
107
108
|
};
|
|
108
109
|
|
|
109
|
-
const StoryMessageBlock = (props: MessageBlockProps<{
|
|
110
|
+
const StoryMessageBlock = (props: MessageBlockProps<{ content?: TextV0Type }>) => {
|
|
110
111
|
const { themeMode } = useThemeContext();
|
|
111
|
-
const
|
|
112
|
+
const doc = props.block.content?.content;
|
|
113
|
+
const accessor = createDocAccessor(props.block.content!, ['content']);
|
|
112
114
|
const { parentRef } = useTextEditor(
|
|
113
115
|
() => ({
|
|
114
116
|
doc,
|
|
@@ -133,15 +135,17 @@ const StoryThread: FC<{
|
|
|
133
135
|
}> = ({ thread, selected, onSelect, onResolve }) => {
|
|
134
136
|
const containerRef = useRef<HTMLDivElement>(null);
|
|
135
137
|
const { themeMode } = useThemeContext();
|
|
136
|
-
|
|
137
|
-
const
|
|
138
|
+
// TODO(wittjosiah): This is a hack to reset the editor after a message is sent.
|
|
139
|
+
const [_count, _setCount] = useState(0);
|
|
140
|
+
const rerenderEditor = () => _setCount((count) => count + 1);
|
|
141
|
+
const messageRef = useRef('');
|
|
138
142
|
const extensions = useMemo(
|
|
139
143
|
() => [
|
|
140
144
|
createBasicExtensions({ placeholder: 'Enter comment' }),
|
|
141
145
|
createThemeExtensions({ themeMode }),
|
|
142
|
-
|
|
146
|
+
listener({ onChange: (text) => (messageRef.current = text) }),
|
|
143
147
|
],
|
|
144
|
-
[themeMode,
|
|
148
|
+
[themeMode, _count],
|
|
145
149
|
);
|
|
146
150
|
|
|
147
151
|
const [autoFocus, setAutoFocus] = useState(false);
|
|
@@ -156,15 +160,21 @@ const StoryThread: FC<{
|
|
|
156
160
|
}, [selected]);
|
|
157
161
|
|
|
158
162
|
const handleCreateMessage = () => {
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
163
|
+
if (messageRef.current?.length) {
|
|
164
|
+
const message = create(MessageType, {
|
|
165
|
+
from: { identityKey: authorId },
|
|
166
|
+
blocks: [
|
|
167
|
+
{
|
|
168
|
+
timestamp: new Date().toISOString(),
|
|
169
|
+
content: create(TextV0Type, { content: messageRef.current }),
|
|
170
|
+
},
|
|
171
|
+
],
|
|
165
172
|
});
|
|
166
|
-
|
|
173
|
+
thread.messages.push(message);
|
|
174
|
+
|
|
175
|
+
messageRef.current = '';
|
|
167
176
|
setAutoFocus(true);
|
|
177
|
+
rerenderEditor();
|
|
168
178
|
}
|
|
169
179
|
};
|
|
170
180
|
|
|
@@ -182,13 +192,12 @@ const StoryThread: FC<{
|
|
|
182
192
|
</ThreadHeading>
|
|
183
193
|
|
|
184
194
|
{thread.messages.map((message) => (
|
|
185
|
-
<Message<{
|
|
195
|
+
<Message<{ content?: TextV0Type }> key={message.id} {...message} MessageBlockComponent={StoryMessageBlock} />
|
|
186
196
|
))}
|
|
187
197
|
|
|
188
198
|
<div ref={containerRef} className='contents'>
|
|
189
199
|
<MessageTextbox
|
|
190
|
-
id={
|
|
191
|
-
doc={doc}
|
|
200
|
+
id={thread.id}
|
|
192
201
|
authorId={authorId}
|
|
193
202
|
autoFocus={autoFocus}
|
|
194
203
|
extensions={extensions}
|
|
@@ -243,7 +252,7 @@ type StoryProps = {
|
|
|
243
252
|
};
|
|
244
253
|
|
|
245
254
|
const Story = ({ text, autoCreate }: StoryProps) => {
|
|
246
|
-
const [item] = useState({
|
|
255
|
+
const [item] = useState(createEchoObject(create(TextV0Type, { content: text ?? '' })));
|
|
247
256
|
const [threads, setThreads] = useState<StoryCommentThread[]>([]);
|
|
248
257
|
const [selected, setSelected] = useState<string>();
|
|
249
258
|
|
|
@@ -269,7 +278,7 @@ const Story = ({ text, autoCreate }: StoryProps) => {
|
|
|
269
278
|
blocks: [
|
|
270
279
|
{
|
|
271
280
|
timestamp: new Date().toISOString(),
|
|
272
|
-
|
|
281
|
+
content: create(TextV0Type, { content: faker.lorem.sentence() }),
|
|
273
282
|
},
|
|
274
283
|
],
|
|
275
284
|
}),
|
|
@@ -3,11 +3,10 @@
|
|
|
3
3
|
//
|
|
4
4
|
|
|
5
5
|
import '@dxosTheme';
|
|
6
|
-
import React, { useMemo, useState } from 'react';
|
|
6
|
+
import React, { useMemo, useRef, useState } from 'react';
|
|
7
7
|
|
|
8
|
-
import { setTextContent, TextObject } from '@dxos/echo-schema';
|
|
9
8
|
import { PublicKey } from '@dxos/keys';
|
|
10
|
-
import {
|
|
9
|
+
import { createBasicExtensions, createThemeExtensions } from '@dxos/react-ui-editor';
|
|
11
10
|
import { withTheme } from '@dxos/storybook-utils';
|
|
12
11
|
|
|
13
12
|
import { Thread, ThreadFooter } from './Thread';
|
|
@@ -19,7 +18,7 @@ const Story = () => {
|
|
|
19
18
|
const [pending, setPending] = useState(false);
|
|
20
19
|
const [identityKey1] = useState(PublicKey.random());
|
|
21
20
|
const [identityKey2] = useState(PublicKey.random());
|
|
22
|
-
const [messages] = useState<MessageEntity<{ id: string; text: string }>[]>([
|
|
21
|
+
const [messages, setMesssages] = useState<MessageEntity<{ id: string; text: string }>[]>([
|
|
23
22
|
{
|
|
24
23
|
id: 'm1',
|
|
25
24
|
authorId: identityKey1.toHex(),
|
|
@@ -44,17 +43,34 @@ const Story = () => {
|
|
|
44
43
|
},
|
|
45
44
|
]);
|
|
46
45
|
|
|
47
|
-
|
|
48
|
-
const
|
|
49
|
-
const
|
|
46
|
+
// TODO(wittjosiah): This is a hack to reset the editor after a message is sent.
|
|
47
|
+
const [_count, _setCount] = useState(3);
|
|
48
|
+
const rerenderEditor = () => _setCount((count) => count + 1);
|
|
49
|
+
const messageRef = useRef('');
|
|
50
|
+
const extensions = useMemo(() => [createBasicExtensions(), createThemeExtensions()], []);
|
|
50
51
|
|
|
51
52
|
// TODO(thure): Why does pressing Enter clear the text content?
|
|
52
53
|
// Something to do with the in-memory text model perhaps?
|
|
53
54
|
const handleSend = () => {
|
|
54
55
|
setPending(true);
|
|
55
56
|
setTimeout(() => {
|
|
56
|
-
|
|
57
|
+
setMesssages((messages) => [
|
|
58
|
+
...messages,
|
|
59
|
+
{
|
|
60
|
+
id: `m${_count}`,
|
|
61
|
+
authorId: identityKey1.toHex(),
|
|
62
|
+
blocks: [
|
|
63
|
+
{
|
|
64
|
+
id: `b${_count}`,
|
|
65
|
+
timestamp: new Date().toISOString(),
|
|
66
|
+
text: messageRef.current,
|
|
67
|
+
},
|
|
68
|
+
],
|
|
69
|
+
},
|
|
70
|
+
]);
|
|
71
|
+
messageRef.current = '';
|
|
57
72
|
setPending(false);
|
|
73
|
+
rerenderEditor();
|
|
58
74
|
}, 2_000);
|
|
59
75
|
};
|
|
60
76
|
|
|
@@ -64,7 +80,7 @@ const Story = () => {
|
|
|
64
80
|
<Message key={message.id} {...message} />
|
|
65
81
|
))}
|
|
66
82
|
<MessageTextbox
|
|
67
|
-
id={
|
|
83
|
+
id={String(_count)}
|
|
68
84
|
authorId={identityKey1.toHex()}
|
|
69
85
|
disabled={pending}
|
|
70
86
|
extensions={extensions}
|