@dxos/react-ui-thread 0.5.9-main.1c1903d → 0.5.9-main.1ea2105
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 +9 -36
- package/dist/lib/browser/index.mjs.map +3 -3
- package/dist/lib/browser/meta.json +1 -1
- package/dist/types/src/Message/Message.d.ts +4 -12
- package/dist/types/src/Message/Message.d.ts.map +1 -1
- package/dist/types/src/Message/Message.stories.d.ts +1 -1
- package/dist/types/src/Message/Message.stories.d.ts.map +1 -1
- package/dist/types/src/Thread/Comments.stories.d.ts +2 -5
- package/dist/types/src/Thread/Comments.stories.d.ts.map +1 -1
- package/dist/types/src/Thread/Thread.stories.d.ts +1 -1
- package/dist/types/src/Thread/Thread.stories.d.ts.map +1 -1
- package/dist/types/src/testing.d.ts +16 -0
- package/dist/types/src/testing.d.ts.map +1 -0
- package/dist/types/src/types.d.ts +1 -6
- package/dist/types/src/types.d.ts.map +1 -1
- package/package.json +13 -13
- package/src/Message/Message.stories.tsx +7 -10
- package/src/Message/Message.tsx +12 -64
- package/src/Thread/Comments.stories.tsx +22 -24
- package/src/Thread/Thread.stories.tsx +10 -23
- package/src/testing.tsx +59 -0
- package/src/types.ts +1 -8
|
@@ -68,13 +68,12 @@ var ThreadFooter = /* @__PURE__ */ forwardRef(({ activity, classNames, children,
|
|
|
68
68
|
});
|
|
69
69
|
|
|
70
70
|
// packages/ui/react-ui-thread/src/Message/Message.tsx
|
|
71
|
-
import { X } from "@phosphor-icons/react";
|
|
72
71
|
import { formatDistanceToNow } from "date-fns/formatDistanceToNow";
|
|
73
72
|
import React2, { forwardRef as forwardRef2, useMemo } from "react";
|
|
74
|
-
import { Avatar,
|
|
73
|
+
import { Avatar, useTranslation as useTranslation2 } from "@dxos/react-ui";
|
|
75
74
|
import { keymap, listener, TextEditor } from "@dxos/react-ui-editor";
|
|
76
|
-
import { focusRing,
|
|
77
|
-
import {
|
|
75
|
+
import { focusRing, mx as mx2 } from "@dxos/react-ui-theme";
|
|
76
|
+
import { hexToEmoji, hexToHue, isNotFalsy } from "@dxos/util";
|
|
78
77
|
var avatarSize = 7;
|
|
79
78
|
var MessageMeta = /* @__PURE__ */ forwardRef2(({ authorImgSrc, authorId, authorName, authorAvatarProps, continues = true, children, classNames, ...rootProps }, forwardedRef) => {
|
|
80
79
|
return /* @__PURE__ */ React2.createElement(Avatar.Root, {
|
|
@@ -101,41 +100,20 @@ var MessageMeta = /* @__PURE__ */ forwardRef2(({ authorImgSrc, authorId, authorN
|
|
|
101
100
|
className: "plb-1 min-is-0"
|
|
102
101
|
}, children)));
|
|
103
102
|
});
|
|
104
|
-
var
|
|
105
|
-
const contentWidth = onBlockDelete ? "col-span-2" : "col-span-3";
|
|
106
|
-
return /* @__PURE__ */ React2.createElement("div", {
|
|
107
|
-
role: "none",
|
|
108
|
-
className: mx2("grid grid-cols-subgrid col-span-3", hoverableControls, hoverableFocusedWithinControls2)
|
|
109
|
-
}, block.data ? /* @__PURE__ */ React2.createElement("pre", {
|
|
110
|
-
className: mx2("font-mono max-is-full overflow-x-auto", contentWidth)
|
|
111
|
-
}, /* @__PURE__ */ React2.createElement("code", null, JSON.stringify(safeParseJson(block.data), void 0, 2))) : /* @__PURE__ */ React2.createElement("p", {
|
|
112
|
-
className: contentWidth
|
|
113
|
-
}, block.text ?? ""), onBlockDelete && /* @__PURE__ */ React2.createElement(Button, {
|
|
114
|
-
variant: "ghost",
|
|
115
|
-
classNames: [
|
|
116
|
-
"p-1.5 min-bs-0 mie-1 items-start transition-opacity",
|
|
117
|
-
hoverableControlItem2
|
|
118
|
-
],
|
|
119
|
-
onClick: () => onBlockDelete()
|
|
120
|
-
}, /* @__PURE__ */ React2.createElement(X, null)));
|
|
121
|
-
};
|
|
122
|
-
var Message = (props) => {
|
|
123
|
-
const { id, authorName, onDelete, blocks, MessageBlockComponent = DefaultMessageBlock, ...metaProps } = props;
|
|
103
|
+
var Message = ({ timestamp, children, ...messageMeta }) => {
|
|
124
104
|
const { t, dtLocale } = useTranslation2(translationKey);
|
|
125
|
-
const
|
|
126
|
-
const dt = firstBlock.timestamp ? new Date(firstBlock.timestamp) : void 0;
|
|
105
|
+
const dt = timestamp ? new Date(timestamp) : void 0;
|
|
127
106
|
return /* @__PURE__ */ React2.createElement(MessageMeta, {
|
|
128
|
-
...
|
|
129
|
-
id,
|
|
107
|
+
...messageMeta,
|
|
130
108
|
continues: true
|
|
131
109
|
}, /* @__PURE__ */ React2.createElement("p", {
|
|
132
110
|
className: "grid grid-cols-[1fr_max-content] gap-2 pie-2"
|
|
133
111
|
}, /* @__PURE__ */ React2.createElement(Avatar.Label, {
|
|
134
112
|
classNames: [
|
|
135
113
|
"truncate text-sm font-medium",
|
|
136
|
-
!authorName && "fg-description"
|
|
114
|
+
!messageMeta.authorName && "fg-description"
|
|
137
115
|
]
|
|
138
|
-
}, authorName ?? t("anonymous label")), /* @__PURE__ */ React2.createElement("time", {
|
|
116
|
+
}, messageMeta.authorName ?? t("anonymous label")), /* @__PURE__ */ React2.createElement("time", {
|
|
139
117
|
className: "fg-description text-xs pbs-0.5",
|
|
140
118
|
dateTime: dt?.toISOString()
|
|
141
119
|
}, dt ? formatDistanceToNow(dt, {
|
|
@@ -144,12 +122,7 @@ var Message = (props) => {
|
|
|
144
122
|
}) : "")), /* @__PURE__ */ React2.createElement("div", {
|
|
145
123
|
role: "none",
|
|
146
124
|
className: "grid gap-y-1 grid-cols-[min-content_1fr_min-content]"
|
|
147
|
-
},
|
|
148
|
-
key: i,
|
|
149
|
-
block,
|
|
150
|
-
authorId: metaProps.authorId,
|
|
151
|
-
onBlockDelete: onDelete && (() => onDelete(id, i))
|
|
152
|
-
}))));
|
|
125
|
+
}, children));
|
|
153
126
|
};
|
|
154
127
|
var keyBindings = ({ onSend, onClear }) => [
|
|
155
128
|
{
|
|
@@ -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(\n 'col-start-2 grid grid-cols-[min-content_1fr_max-content] text-xs fg-description pb-2',\n classNames,\n )}\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": ";AAIO,IAAMA,iBAAiB;AAE9B,IAAA,uBAAe;EACb;IACE,SAAS;MACP,CAACA,cAAAA,GAAiB;QAChB,eAAe;QACf,4BAA4B;QAC5B,sBAAsB;QACtB,uBAAuB;QACvB,uBAAuB;QACvB,uBAAuB;QACvB,uBAAuB;QACvB,6BAA6B;QAC7B,mBAAmB;QACnB,yBAAyB;MAC3B;IACF;EACF;;;;AClBF,SAASC,mBAAmBC,eAAe;AAC3C,OAAOC,SAA0DC,kBAAkB;AAEnF,SAA+BC,sBAAsB;AACrD,SAASC,sBAAsBC,gCAAgCC,UAAU;AAQlE,IAAMC,eAAe;AAErB,IAAMC,SAASC,2BACpB,CAAC,EAAEC,SAASC,UAAUC,YAAY,GAAGC,MAAAA,GAASC,iBAAAA;AAC5C,SACE,sBAAA,cAACC,OAAAA;IACCC,MAAK;IACLC,eAAY;IACX,GAAIP,WAAW;MAAE,gBAAgB,OAAOA,YAAY,WAAWA,UAAU;IAAW;IACpF,GAAGG;IACJK,WAAWC,GACTZ,cACAa,gCACA,kKACAR,UAAAA;IAEFS,KAAKP;KAEJH,QAAAA;AAGP,CAAA;AAKK,IAAMW,gBAAgBb,2BAC3B,CAAC,EAAEG,YAAYD,UAAUY,UAAU,GAAGV,MAAAA,GAASC,iBAAAA;AAC7C,SACE,sBAAA,cAAA,MAAA,UAAA,MACE,sBAAA,cAACC,OAAAA;IAAIC,MAAK;IAAOE,WAAU;KACzB,sBAAA,cAACM,mBAAAA,IAAAA,CAAAA,GAEH,sBAAA,cAACC,KAAAA;IACCT,MAAK;IACLC,eAAY;IACX,GAAGJ;IACJK,WAAWC,GACT,+FACAI,YAAY,2BAAA;IAEdF,KAAKP;KAEJH,QAAAA,CAAAA;AAIT,CAAA;AAOK,IAAMe,eAAejB,2BAC1B,CAAC,EAAEkB,UAAUf,YAAYD,UAAU,GAAGE,MAAAA,GAASC,iBAAAA;AAC7C,QAAM,EAAEc,EAAC,IAAKC,eAAeC,cAAAA;AAC7B,SACE,sBAAA,cAACf,OAAAA;IACE,GAAGF;IACJK,WAAWC,GACT,wFACAP,UAAAA;IAEFS,KAAKP;KAEL,sBAAA,cAACiB,SAAAA;IACCC,QAAO;IACPC,gBAAcN,WAAW,SAAS;IAClCT,WAAU;MAEZ,sBAAA,cAACgB,QAAAA;IAAKhB,WAAU;IAAoBiB,aAAU;KAC3CR,WAAWhB,WAAW,IAAA,GAEzB,sBAAA,cAACuB,QAAAA;IAAKhB,WAAWC,GAAG,kBAAkBiB,oBAAAA;KAAwBR,EAAE,uBAAA,CAAA,CAAA;AAGtE,CAAA;;;ACzFF,SAASS,
|
|
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", "
|
|
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(\n 'col-start-2 grid grid-cols-[min-content_1fr_max-content] text-xs fg-description pb-2',\n classNames,\n )}\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 { formatDistanceToNow } from 'date-fns/formatDistanceToNow';\nimport React, { type ComponentPropsWithRef, forwardRef, useMemo, type PropsWithChildren } from 'react';\n\n// TODO(burdon): Remove dep.\nimport { Avatar, type ThemedClassName, useTranslation } from '@dxos/react-ui';\nimport { type TextEditorProps, keymap, listener, TextEditor } from '@dxos/react-ui-editor';\nimport { focusRing, mx } from '@dxos/react-ui-theme';\nimport { hexToEmoji, hexToHue, isNotFalsy } from '@dxos/util';\n\nimport { translationKey } from '../translations';\nimport { 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 MessageProps = PropsWithChildren<MessageMetadata>;\n\nexport const Message = ({ timestamp, children, ...messageMeta }: MessageProps) => {\n const { t, dtLocale } = useTranslation(translationKey);\n const dt = timestamp ? new Date(timestamp) : undefined;\n\n return (\n <MessageMeta {...messageMeta} continues>\n <p className='grid grid-cols-[1fr_max-content] gap-2 pie-2'>\n <Avatar.Label classNames={['truncate text-sm font-medium', !messageMeta.authorName && 'fg-description']}>\n {messageMeta.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 {children}\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
|
+
"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", "formatDistanceToNow", "React", "forwardRef", "useMemo", "Avatar", "useTranslation", "keymap", "listener", "TextEditor", "focusRing", "mx", "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", "Message", "timestamp", "messageMeta", "t", "dtLocale", "useTranslation", "translationKey", "dt", "Date", "undefined", "p", "Label", "time", "dateTime", "toISOString", "formatDistanceToNow", "locale", "addSuffix", "keyBindings", "onSend", "onClear", "key", "run", "MessageTextbox", "id", "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":2337,"imports":[],"format":"esm"},"packages/ui/react-ui-thread/src/Thread/Thread.tsx":{"bytes":9488,"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":500,"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":2337,"imports":[],"format":"esm"},"packages/ui/react-ui-thread/src/Thread/Thread.tsx":{"bytes":9488,"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":500,"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":15102,"imports":[{"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":506,"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":903,"imports":[],"format":"esm"},"packages/ui/react-ui-thread/src/index.ts":{"bytes":913,"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":13913},"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":"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":2492},"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":3877},"packages/ui/react-ui-thread/src/Message/index.ts":{"bytesInOutput":0}},"bytes":7328}}}
|
|
@@ -1,21 +1,13 @@
|
|
|
1
|
-
import React, { type ComponentPropsWithRef, type
|
|
1
|
+
import React, { type ComponentPropsWithRef, type PropsWithChildren } from 'react';
|
|
2
2
|
import { type ThemedClassName } from '@dxos/react-ui';
|
|
3
3
|
import { type TextEditorProps } from '@dxos/react-ui-editor';
|
|
4
|
-
import { type
|
|
4
|
+
import { type MessageMetadata } from '../types';
|
|
5
5
|
export type MessageMetaProps = ThemedClassName<ComponentPropsWithRef<'div'>> & MessageMetadata & Partial<{
|
|
6
6
|
continues: boolean;
|
|
7
7
|
}>;
|
|
8
8
|
export declare const MessageMeta: React.ForwardRefExoticComponent<Pick<MessageMetaProps, "slot" | "style" | "title" | "key" | "defaultChecked" | "defaultValue" | "suppressContentEditableWarning" | "suppressHydrationWarning" | "accessKey" | "contentEditable" | "contextMenu" | "dir" | "draggable" | "hidden" | "lang" | "placeholder" | "spellCheck" | "tabIndex" | "translate" | "radioGroup" | "role" | "about" | "datatype" | "inlist" | "prefix" | "property" | "resource" | "typeof" | "vocab" | "autoCapitalize" | "autoCorrect" | "autoSave" | "color" | "itemProp" | "itemScope" | "itemType" | "itemID" | "itemRef" | "results" | "security" | "unselectable" | "inputMode" | "is" | "children" | "aria-activedescendant" | "aria-atomic" | "aria-autocomplete" | "aria-busy" | "aria-checked" | "aria-colcount" | "aria-colindex" | "aria-colspan" | "aria-controls" | "aria-current" | "aria-describedby" | "aria-details" | "aria-disabled" | "aria-dropeffect" | "aria-errormessage" | "aria-expanded" | "aria-flowto" | "aria-grabbed" | "aria-haspopup" | "aria-hidden" | "aria-invalid" | "aria-keyshortcuts" | "aria-label" | "aria-labelledby" | "aria-level" | "aria-live" | "aria-modal" | "aria-multiline" | "aria-multiselectable" | "aria-orientation" | "aria-owns" | "aria-placeholder" | "aria-posinset" | "aria-pressed" | "aria-readonly" | "aria-relevant" | "aria-required" | "aria-roledescription" | "aria-rowcount" | "aria-rowindex" | "aria-rowspan" | "aria-selected" | "aria-setsize" | "aria-sort" | "aria-valuemax" | "aria-valuemin" | "aria-valuenow" | "aria-valuetext" | "dangerouslySetInnerHTML" | "onCopy" | "onCopyCapture" | "onCut" | "onCutCapture" | "onPaste" | "onPasteCapture" | "onCompositionEnd" | "onCompositionEndCapture" | "onCompositionStart" | "onCompositionStartCapture" | "onCompositionUpdate" | "onCompositionUpdateCapture" | "onFocus" | "onFocusCapture" | "onBlur" | "onBlurCapture" | "onChange" | "onChangeCapture" | "onBeforeInput" | "onBeforeInputCapture" | "onInput" | "onInputCapture" | "onReset" | "onResetCapture" | "onSubmit" | "onSubmitCapture" | "onInvalid" | "onInvalidCapture" | "onLoad" | "onLoadCapture" | "onError" | "onErrorCapture" | "onKeyDown" | "onKeyDownCapture" | "onKeyPress" | "onKeyPressCapture" | "onKeyUp" | "onKeyUpCapture" | "onAbort" | "onAbortCapture" | "onCanPlay" | "onCanPlayCapture" | "onCanPlayThrough" | "onCanPlayThroughCapture" | "onDurationChange" | "onDurationChangeCapture" | "onEmptied" | "onEmptiedCapture" | "onEncrypted" | "onEncryptedCapture" | "onEnded" | "onEndedCapture" | "onLoadedData" | "onLoadedDataCapture" | "onLoadedMetadata" | "onLoadedMetadataCapture" | "onLoadStart" | "onLoadStartCapture" | "onPause" | "onPauseCapture" | "onPlay" | "onPlayCapture" | "onPlaying" | "onPlayingCapture" | "onProgress" | "onProgressCapture" | "onRateChange" | "onRateChangeCapture" | "onSeeked" | "onSeekedCapture" | "onSeeking" | "onSeekingCapture" | "onStalled" | "onStalledCapture" | "onSuspend" | "onSuspendCapture" | "onTimeUpdate" | "onTimeUpdateCapture" | "onVolumeChange" | "onVolumeChangeCapture" | "onWaiting" | "onWaitingCapture" | "onAuxClick" | "onAuxClickCapture" | "onClick" | "onClickCapture" | "onContextMenu" | "onContextMenuCapture" | "onDoubleClick" | "onDoubleClickCapture" | "onDrag" | "onDragCapture" | "onDragEnd" | "onDragEndCapture" | "onDragEnter" | "onDragEnterCapture" | "onDragExit" | "onDragExitCapture" | "onDragLeave" | "onDragLeaveCapture" | "onDragOver" | "onDragOverCapture" | "onDragStart" | "onDragStartCapture" | "onDrop" | "onDropCapture" | "onMouseDown" | "onMouseDownCapture" | "onMouseEnter" | "onMouseLeave" | "onMouseMove" | "onMouseMoveCapture" | "onMouseOut" | "onMouseOutCapture" | "onMouseOver" | "onMouseOverCapture" | "onMouseUp" | "onMouseUpCapture" | "onSelect" | "onSelectCapture" | "onTouchCancel" | "onTouchCancelCapture" | "onTouchEnd" | "onTouchEndCapture" | "onTouchMove" | "onTouchMoveCapture" | "onTouchStart" | "onTouchStartCapture" | "onPointerDown" | "onPointerDownCapture" | "onPointerMove" | "onPointerMoveCapture" | "onPointerUp" | "onPointerUpCapture" | "onPointerCancel" | "onPointerCancelCapture" | "onPointerEnter" | "onPointerEnterCapture" | "onPointerLeave" | "onPointerLeaveCapture" | "onPointerOver" | "onPointerOverCapture" | "onPointerOut" | "onPointerOutCapture" | "onGotPointerCapture" | "onGotPointerCaptureCapture" | "onLostPointerCapture" | "onLostPointerCaptureCapture" | "onScroll" | "onScrollCapture" | "onWheel" | "onWheelCapture" | "onAnimationStart" | "onAnimationStartCapture" | "onAnimationEnd" | "onAnimationEndCapture" | "onAnimationIteration" | "onAnimationIterationCapture" | "onTransitionEnd" | "onTransitionEndCapture" | "classNames" | "continues" | keyof MessageMetadata> & React.RefAttributes<HTMLDivElement>>;
|
|
9
|
-
export type
|
|
10
|
-
|
|
11
|
-
authorId?: string;
|
|
12
|
-
onBlockDelete?: () => void;
|
|
13
|
-
};
|
|
14
|
-
export type MessageProps<BlockValue> = MessageEntity<BlockValue> & {
|
|
15
|
-
onDelete?: (messageId: string, blockIndex: number) => void;
|
|
16
|
-
MessageBlockComponent?: FC<MessageBlockProps<BlockValue>>;
|
|
17
|
-
};
|
|
18
|
-
export declare const Message: <BlockValue>(props: MessageProps<BlockValue>) => JSX.Element;
|
|
9
|
+
export type MessageProps = PropsWithChildren<MessageMetadata>;
|
|
10
|
+
export declare const Message: ({ timestamp, children, ...messageMeta }: MessageProps) => JSX.Element;
|
|
19
11
|
export type MessageTextboxProps = {
|
|
20
12
|
disabled?: boolean;
|
|
21
13
|
onSend?: () => void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Message.d.ts","sourceRoot":"","sources":["../../../../src/Message/Message.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"Message.d.ts","sourceRoot":"","sources":["../../../../src/Message/Message.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,EAAE,KAAK,qBAAqB,EAAuB,KAAK,iBAAiB,EAAE,MAAM,OAAO,CAAC;AAGvG,OAAO,EAAU,KAAK,eAAe,EAAkB,MAAM,gBAAgB,CAAC;AAC9E,OAAO,EAAE,KAAK,eAAe,EAAgC,MAAM,uBAAuB,CAAC;AAK3F,OAAO,EAAE,KAAK,eAAe,EAAE,MAAM,UAAU,CAAC;AAIhD,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,YAAY,GAAG,iBAAiB,CAAC,eAAe,CAAC,CAAC;AAE9D,eAAO,MAAM,OAAO,4CAA6C,YAAY,gBAmB5E,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"}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import '@dxosTheme';
|
|
3
3
|
declare const _default: {
|
|
4
4
|
title: string;
|
|
5
|
-
component:
|
|
5
|
+
component: ({ timestamp, children, ...messageMeta }: import("./Message").MessageProps) => JSX.Element;
|
|
6
6
|
render: () => JSX.Element;
|
|
7
7
|
decorators: import("@storybook/react/*").Decorator[];
|
|
8
8
|
parameters: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Message.stories.d.ts","sourceRoot":"","sources":["../../../../src/Message/Message.stories.tsx"],"names":[],"mappings":";AAIA,OAAO,YAAY,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"Message.stories.d.ts","sourceRoot":"","sources":["../../../../src/Message/Message.stories.tsx"],"names":[],"mappings":";AAIA,OAAO,YAAY,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;AA6BpB,wBAME;AAEF,eAAO,MAAM,OAAO,IAAK,CAAC"}
|
|
@@ -1,16 +1,13 @@
|
|
|
1
1
|
import '@dxosTheme';
|
|
2
2
|
import React from 'react';
|
|
3
|
-
import { TextV0Type } from '@braneframe/types';
|
|
4
3
|
import { type Range } from '@dxos/react-ui-editor';
|
|
5
|
-
import { type MessageEntity } from '../
|
|
4
|
+
import { type MessageEntity } from '../testing';
|
|
6
5
|
type StoryCommentThread = {
|
|
7
6
|
id: string;
|
|
8
7
|
cursor?: string;
|
|
9
8
|
range?: Range;
|
|
10
9
|
yPos?: number;
|
|
11
|
-
messages: MessageEntity
|
|
12
|
-
content?: TextV0Type;
|
|
13
|
-
}>[];
|
|
10
|
+
messages: MessageEntity[];
|
|
14
11
|
};
|
|
15
12
|
type StoryProps = {
|
|
16
13
|
text?: string;
|
|
@@ -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;
|
|
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;AAS7E,OAAO,EAML,KAAK,KAAK,EAMX,MAAM,uBAAuB,CAAC;AAK/B,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,YAAY,CAAC;AAqEhD,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,EAAE,CAAC;CAC3B,CAAC;AA+IF,KAAK,UAAU,GAAG;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB,CAAC;;;;;;;;;;mBA2He,UAAU;;;;;;;;;;;;;;;;;;;;;AAJ3B,wBAME;AAWF,eAAO,MAAM,OAAO;;;;CAInB,CAAC"}
|
|
@@ -2,7 +2,7 @@ import '@dxosTheme';
|
|
|
2
2
|
import React from 'react';
|
|
3
3
|
declare const _default: {
|
|
4
4
|
title: string;
|
|
5
|
-
component: React.ForwardRefExoticComponent<Pick<import("./Thread").ThreadProps, "slot" | "style" | "title" | "key" | "defaultChecked" | "defaultValue" | "suppressContentEditableWarning" | "suppressHydrationWarning" | "accessKey" | "contentEditable" | "contextMenu" | "dir" | "draggable" | "hidden" | "id" | "lang" | "placeholder" | "spellCheck" | "tabIndex" | "translate" | "radioGroup" | "role" | "about" | "datatype" | "inlist" | "prefix" | "property" | "resource" | "typeof" | "vocab" | "autoCapitalize" | "autoCorrect" | "autoSave" | "color" | "itemProp" | "itemScope" | "itemType" | "itemID" | "itemRef" | "results" | "security" | "unselectable" | "inputMode" | "is" | "children" | "aria-activedescendant" | "aria-atomic" | "aria-autocomplete" | "aria-busy" | "aria-checked" | "aria-colcount" | "aria-colindex" | "aria-colspan" | "aria-controls" | "aria-current" | "aria-describedby" | "aria-details" | "aria-disabled" | "aria-dropeffect" | "aria-errormessage" | "aria-expanded" | "aria-flowto" | "aria-grabbed" | "aria-haspopup" | "aria-hidden" | "aria-invalid" | "aria-keyshortcuts" | "aria-label" | "aria-labelledby" | "aria-level" | "aria-live" | "aria-modal" | "aria-multiline" | "aria-multiselectable" | "aria-orientation" | "aria-owns" | "aria-placeholder" | "aria-posinset" | "aria-pressed" | "aria-readonly" | "aria-relevant" | "aria-required" | "aria-roledescription" | "aria-rowcount" | "aria-rowindex" | "aria-rowspan" | "aria-selected" | "aria-setsize" | "aria-sort" | "aria-valuemax" | "aria-valuemin" | "aria-valuenow" | "aria-valuetext" | "dangerouslySetInnerHTML" | "onCopy" | "onCopyCapture" | "onCut" | "onCutCapture" | "onPaste" | "onPasteCapture" | "onCompositionEnd" | "onCompositionEndCapture" | "onCompositionStart" | "onCompositionStartCapture" | "onCompositionUpdate" | "onCompositionUpdateCapture" | "onFocus" | "onFocusCapture" | "onBlur" | "onBlurCapture" | "onChange" | "onChangeCapture" | "onBeforeInput" | "onBeforeInputCapture" | "onInput" | "onInputCapture" | "onReset" | "onResetCapture" | "onSubmit" | "onSubmitCapture" | "onInvalid" | "onInvalidCapture" | "onLoad" | "onLoadCapture" | "onError" | "onErrorCapture" | "onKeyDown" | "onKeyDownCapture" | "onKeyPress" | "onKeyPressCapture" | "onKeyUp" | "onKeyUpCapture" | "onAbort" | "onAbortCapture" | "onCanPlay" | "onCanPlayCapture" | "onCanPlayThrough" | "onCanPlayThroughCapture" | "onDurationChange" | "onDurationChangeCapture" | "onEmptied" | "onEmptiedCapture" | "onEncrypted" | "onEncryptedCapture" | "onEnded" | "onEndedCapture" | "onLoadedData" | "onLoadedDataCapture" | "onLoadedMetadata" | "onLoadedMetadataCapture" | "onLoadStart" | "onLoadStartCapture" | "onPause" | "onPauseCapture" | "onPlay" | "onPlayCapture" | "onPlaying" | "onPlayingCapture" | "onProgress" | "onProgressCapture" | "onRateChange" | "onRateChangeCapture" | "onSeeked" | "onSeekedCapture" | "onSeeking" | "onSeekingCapture" | "onStalled" | "onStalledCapture" | "onSuspend" | "onSuspendCapture" | "onTimeUpdate" | "onTimeUpdateCapture" | "onVolumeChange" | "onVolumeChangeCapture" | "onWaiting" | "onWaitingCapture" | "onAuxClick" | "onAuxClickCapture" | "onClick" | "onClickCapture" | "onContextMenu" | "onContextMenuCapture" | "onDoubleClick" | "onDoubleClickCapture" | "onDrag" | "onDragCapture" | "onDragEnd" | "onDragEndCapture" | "onDragEnter" | "onDragEnterCapture" | "onDragExit" | "onDragExitCapture" | "onDragLeave" | "onDragLeaveCapture" | "onDragOver" | "onDragOverCapture" | "onDragStart" | "onDragStartCapture" | "onDrop" | "onDropCapture" | "onMouseDown" | "onMouseDownCapture" | "onMouseEnter" | "onMouseLeave" | "onMouseMove" | "onMouseMoveCapture" | "onMouseOut" | "onMouseOutCapture" | "onMouseOver" | "onMouseOverCapture" | "onMouseUp" | "onMouseUpCapture" | "onSelect" | "onSelectCapture" | "onTouchCancel" | "onTouchCancelCapture" | "onTouchEnd" | "onTouchEndCapture" | "onTouchMove" | "onTouchMoveCapture" | "onTouchStart" | "onTouchStartCapture" | "onPointerDown" | "onPointerDownCapture" | "onPointerMove" | "onPointerMoveCapture" | "onPointerUp" | "onPointerUpCapture" | "onPointerCancel" | "onPointerCancelCapture" | "onPointerEnter" | "onPointerEnterCapture" | "onPointerLeave" | "onPointerLeaveCapture" | "onPointerOver" | "onPointerOverCapture" | "onPointerOut" | "onPointerOutCapture" | "onGotPointerCapture" | "onGotPointerCaptureCapture" | "onLostPointerCapture" | "onLostPointerCaptureCapture" | "onScroll" | "onScrollCapture" | "onWheel" | "onWheelCapture" | "onAnimationStart" | "onAnimationStartCapture" | "onAnimationEnd" | "onAnimationEndCapture" | "onAnimationIteration" | "onAnimationIterationCapture" | "onTransitionEnd" | "onTransitionEndCapture" | "current" | "classNames" | keyof import("
|
|
5
|
+
component: React.ForwardRefExoticComponent<Pick<import("./Thread").ThreadProps, "slot" | "style" | "title" | "key" | "defaultChecked" | "defaultValue" | "suppressContentEditableWarning" | "suppressHydrationWarning" | "accessKey" | "contentEditable" | "contextMenu" | "dir" | "draggable" | "hidden" | "id" | "lang" | "placeholder" | "spellCheck" | "tabIndex" | "translate" | "radioGroup" | "role" | "about" | "datatype" | "inlist" | "prefix" | "property" | "resource" | "typeof" | "vocab" | "autoCapitalize" | "autoCorrect" | "autoSave" | "color" | "itemProp" | "itemScope" | "itemType" | "itemID" | "itemRef" | "results" | "security" | "unselectable" | "inputMode" | "is" | "children" | "aria-activedescendant" | "aria-atomic" | "aria-autocomplete" | "aria-busy" | "aria-checked" | "aria-colcount" | "aria-colindex" | "aria-colspan" | "aria-controls" | "aria-current" | "aria-describedby" | "aria-details" | "aria-disabled" | "aria-dropeffect" | "aria-errormessage" | "aria-expanded" | "aria-flowto" | "aria-grabbed" | "aria-haspopup" | "aria-hidden" | "aria-invalid" | "aria-keyshortcuts" | "aria-label" | "aria-labelledby" | "aria-level" | "aria-live" | "aria-modal" | "aria-multiline" | "aria-multiselectable" | "aria-orientation" | "aria-owns" | "aria-placeholder" | "aria-posinset" | "aria-pressed" | "aria-readonly" | "aria-relevant" | "aria-required" | "aria-roledescription" | "aria-rowcount" | "aria-rowindex" | "aria-rowspan" | "aria-selected" | "aria-setsize" | "aria-sort" | "aria-valuemax" | "aria-valuemin" | "aria-valuenow" | "aria-valuetext" | "dangerouslySetInnerHTML" | "onCopy" | "onCopyCapture" | "onCut" | "onCutCapture" | "onPaste" | "onPasteCapture" | "onCompositionEnd" | "onCompositionEndCapture" | "onCompositionStart" | "onCompositionStartCapture" | "onCompositionUpdate" | "onCompositionUpdateCapture" | "onFocus" | "onFocusCapture" | "onBlur" | "onBlurCapture" | "onChange" | "onChangeCapture" | "onBeforeInput" | "onBeforeInputCapture" | "onInput" | "onInputCapture" | "onReset" | "onResetCapture" | "onSubmit" | "onSubmitCapture" | "onInvalid" | "onInvalidCapture" | "onLoad" | "onLoadCapture" | "onError" | "onErrorCapture" | "onKeyDown" | "onKeyDownCapture" | "onKeyPress" | "onKeyPressCapture" | "onKeyUp" | "onKeyUpCapture" | "onAbort" | "onAbortCapture" | "onCanPlay" | "onCanPlayCapture" | "onCanPlayThrough" | "onCanPlayThroughCapture" | "onDurationChange" | "onDurationChangeCapture" | "onEmptied" | "onEmptiedCapture" | "onEncrypted" | "onEncryptedCapture" | "onEnded" | "onEndedCapture" | "onLoadedData" | "onLoadedDataCapture" | "onLoadedMetadata" | "onLoadedMetadataCapture" | "onLoadStart" | "onLoadStartCapture" | "onPause" | "onPauseCapture" | "onPlay" | "onPlayCapture" | "onPlaying" | "onPlayingCapture" | "onProgress" | "onProgressCapture" | "onRateChange" | "onRateChangeCapture" | "onSeeked" | "onSeekedCapture" | "onSeeking" | "onSeekingCapture" | "onStalled" | "onStalledCapture" | "onSuspend" | "onSuspendCapture" | "onTimeUpdate" | "onTimeUpdateCapture" | "onVolumeChange" | "onVolumeChangeCapture" | "onWaiting" | "onWaitingCapture" | "onAuxClick" | "onAuxClickCapture" | "onClick" | "onClickCapture" | "onContextMenu" | "onContextMenuCapture" | "onDoubleClick" | "onDoubleClickCapture" | "onDrag" | "onDragCapture" | "onDragEnd" | "onDragEndCapture" | "onDragEnter" | "onDragEnterCapture" | "onDragExit" | "onDragExitCapture" | "onDragLeave" | "onDragLeaveCapture" | "onDragOver" | "onDragOverCapture" | "onDragStart" | "onDragStartCapture" | "onDrop" | "onDropCapture" | "onMouseDown" | "onMouseDownCapture" | "onMouseEnter" | "onMouseLeave" | "onMouseMove" | "onMouseMoveCapture" | "onMouseOut" | "onMouseOutCapture" | "onMouseOver" | "onMouseOverCapture" | "onMouseUp" | "onMouseUpCapture" | "onSelect" | "onSelectCapture" | "onTouchCancel" | "onTouchCancelCapture" | "onTouchEnd" | "onTouchEndCapture" | "onTouchMove" | "onTouchMoveCapture" | "onTouchStart" | "onTouchStartCapture" | "onPointerDown" | "onPointerDownCapture" | "onPointerMove" | "onPointerMoveCapture" | "onPointerUp" | "onPointerUpCapture" | "onPointerCancel" | "onPointerCancelCapture" | "onPointerEnter" | "onPointerEnterCapture" | "onPointerLeave" | "onPointerLeaveCapture" | "onPointerOver" | "onPointerOverCapture" | "onPointerOut" | "onPointerOutCapture" | "onGotPointerCapture" | "onGotPointerCaptureCapture" | "onLostPointerCapture" | "onLostPointerCaptureCapture" | "onScroll" | "onScrollCapture" | "onWheel" | "onWheelCapture" | "onAnimationStart" | "onAnimationStartCapture" | "onAnimationEnd" | "onAnimationEndCapture" | "onAnimationIteration" | "onAnimationIterationCapture" | "onTransitionEnd" | "onTransitionEndCapture" | "current" | "classNames" | keyof import("..").ThreadEntity> & React.RefAttributes<HTMLDivElement>>;
|
|
6
6
|
render: () => JSX.Element;
|
|
7
7
|
decorators: import("@storybook/react/*").Decorator[];
|
|
8
8
|
parameters: {
|
|
@@ -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,KAAoC,MAAM,OAAO,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
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;;;;;;;;;;;;;;;;;;;;;;;;;AA2EzD,wBAME;AAEF,eAAO,MAAM,OAAO,IAAK,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
import { type MessageMetadata } from './types';
|
|
3
|
+
export type MessageEntity<PartValue = any> = MessageMetadata & {
|
|
4
|
+
text: string;
|
|
5
|
+
parts?: PartValue[];
|
|
6
|
+
};
|
|
7
|
+
export type MessageTextProps = {
|
|
8
|
+
text: string;
|
|
9
|
+
onDelete?: () => void;
|
|
10
|
+
};
|
|
11
|
+
export declare const DefaultMessageText: ({ text, onDelete }: MessageTextProps) => JSX.Element;
|
|
12
|
+
export type MessagePartProps<PartValue> = {
|
|
13
|
+
part: PartValue;
|
|
14
|
+
};
|
|
15
|
+
export declare const DefaultMessageBlock: <PartValue>({ part }: MessagePartProps<PartValue>) => JSX.Element;
|
|
16
|
+
//# sourceMappingURL=testing.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"testing.d.ts","sourceRoot":"","sources":["../../../src/testing.tsx"],"names":[],"mappings":";AAUA,OAAO,EAAE,KAAK,eAAe,EAAE,MAAM,SAAS,CAAC;AAE/C,MAAM,MAAM,aAAa,CAAC,SAAS,GAAG,GAAG,IAAI,eAAe,GAAG;IAC7D,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,SAAS,EAAE,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;CACvB,CAAC;AAEF,eAAO,MAAM,kBAAkB,uBAAwB,gBAAgB,gBAmBtE,CAAC;AAEF,MAAM,MAAM,gBAAgB,CAAC,SAAS,IAAI;IACxC,IAAI,EAAE,SAAS,CAAC;CACjB,CAAC;AAEF,eAAO,MAAM,mBAAmB,wBAA0B,iBAAiB,SAAS,CAAC,gBAWpF,CAAC"}
|
|
@@ -1,17 +1,12 @@
|
|
|
1
1
|
import { type FallbackValue } from '@dxos/util';
|
|
2
2
|
export type MessageMetadata = {
|
|
3
3
|
id: string;
|
|
4
|
+
timestamp?: string;
|
|
4
5
|
authorId?: string;
|
|
5
6
|
authorName?: string;
|
|
6
7
|
authorImgSrc?: string;
|
|
7
8
|
authorAvatarProps?: FallbackValue;
|
|
8
9
|
};
|
|
9
|
-
export type MessageEntityBlock<BlockValue> = BlockValue & {
|
|
10
|
-
timestamp?: string;
|
|
11
|
-
};
|
|
12
|
-
export type MessageEntity<BlockValue> = MessageMetadata & {
|
|
13
|
-
blocks: MessageEntityBlock<BlockValue>[];
|
|
14
|
-
};
|
|
15
10
|
export type ThreadEntity = {
|
|
16
11
|
topicId?: string;
|
|
17
12
|
topicTitle?: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/types.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,YAAY,CAAC;AAEhD,MAAM,MAAM,eAAe,GAAG;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/types.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,YAAY,CAAC;AAEhD,MAAM,MAAM,eAAe,GAAG;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,iBAAiB,CAAC,EAAE,aAAa,CAAC;CACnC,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IACzB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dxos/react-ui-thread",
|
|
3
|
-
"version": "0.5.9-main.
|
|
3
|
+
"version": "0.5.9-main.1ea2105",
|
|
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,11 +18,11 @@
|
|
|
18
18
|
"dependencies": {
|
|
19
19
|
"@radix-ui/react-primitive": "^1.0.2",
|
|
20
20
|
"date-fns": "^3.3.1",
|
|
21
|
-
"@dxos/react-ui": "0.5.9-main.
|
|
22
|
-
"@dxos/react-ui-
|
|
23
|
-
"@dxos/react-ui-
|
|
24
|
-
"@dxos/
|
|
25
|
-
"@dxos/
|
|
21
|
+
"@dxos/react-ui-editor": "0.5.9-main.1ea2105",
|
|
22
|
+
"@dxos/react-ui-mosaic": "0.5.9-main.1ea2105",
|
|
23
|
+
"@dxos/react-ui-theme": "0.5.9-main.1ea2105",
|
|
24
|
+
"@dxos/util": "0.5.9-main.1ea2105",
|
|
25
|
+
"@dxos/react-ui": "0.5.9-main.1ea2105"
|
|
26
26
|
},
|
|
27
27
|
"devDependencies": {
|
|
28
28
|
"@phosphor-icons/react": "^2.1.5",
|
|
@@ -31,13 +31,13 @@
|
|
|
31
31
|
"react": "^18.2.0",
|
|
32
32
|
"react-dom": "^18.2.0",
|
|
33
33
|
"vite": "^5.2.9",
|
|
34
|
-
"@braneframe/types": "0.5.9-main.
|
|
35
|
-
"@dxos/
|
|
36
|
-
"@dxos/
|
|
37
|
-
"@dxos/echo-
|
|
38
|
-
"@dxos/log": "0.5.9-main.
|
|
39
|
-
"@dxos/storybook-utils": "0.5.9-main.
|
|
40
|
-
"@dxos/random": "0.5.9-main.
|
|
34
|
+
"@braneframe/types": "0.5.9-main.1ea2105",
|
|
35
|
+
"@dxos/keys": "0.5.9-main.1ea2105",
|
|
36
|
+
"@dxos/echo-schema": "0.5.9-main.1ea2105",
|
|
37
|
+
"@dxos/echo-db": "0.5.9-main.1ea2105",
|
|
38
|
+
"@dxos/log": "0.5.9-main.1ea2105",
|
|
39
|
+
"@dxos/storybook-utils": "0.5.9-main.1ea2105",
|
|
40
|
+
"@dxos/random": "0.5.9-main.1ea2105"
|
|
41
41
|
},
|
|
42
42
|
"peerDependencies": {
|
|
43
43
|
"@phosphor-icons/react": "^2.1.5",
|
|
@@ -10,26 +10,23 @@ import { PublicKey } from '@dxos/keys';
|
|
|
10
10
|
import { withTheme } from '@dxos/storybook-utils';
|
|
11
11
|
|
|
12
12
|
import { Message } from './Message';
|
|
13
|
+
import { DefaultMessageText, type MessageEntity } from '../testing';
|
|
13
14
|
import translations from '../translations';
|
|
14
|
-
import { type MessageEntity } from '../types';
|
|
15
15
|
|
|
16
16
|
const Story = () => {
|
|
17
17
|
const [identityKey] = useState(PublicKey.random());
|
|
18
|
-
const [message] = useState<MessageEntity
|
|
18
|
+
const [message] = useState<MessageEntity>({
|
|
19
19
|
id: 'm1',
|
|
20
|
+
timestamp: new Date().toISOString(),
|
|
20
21
|
authorId: identityKey.toHex(),
|
|
21
|
-
|
|
22
|
-
{
|
|
23
|
-
id: 'b1',
|
|
24
|
-
timestamp: new Date().toISOString(),
|
|
25
|
-
text: 'hello',
|
|
26
|
-
},
|
|
27
|
-
],
|
|
22
|
+
text: 'hello',
|
|
28
23
|
});
|
|
29
24
|
|
|
30
25
|
return (
|
|
31
26
|
<div className='grid grid-cols-[var(--rail-size)_1fr]'>
|
|
32
|
-
<Message {...message}
|
|
27
|
+
<Message {...message}>
|
|
28
|
+
<DefaultMessageText text={message.text} onDelete={() => console.log('delete')} />
|
|
29
|
+
</Message>
|
|
33
30
|
</div>
|
|
34
31
|
);
|
|
35
32
|
};
|
package/src/Message/Message.tsx
CHANGED
|
@@ -2,24 +2,17 @@
|
|
|
2
2
|
// Copyright 2023 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import { X } from '@phosphor-icons/react';
|
|
6
5
|
import { formatDistanceToNow } from 'date-fns/formatDistanceToNow';
|
|
7
|
-
import React, { type ComponentPropsWithRef,
|
|
6
|
+
import React, { type ComponentPropsWithRef, forwardRef, useMemo, type PropsWithChildren } from 'react';
|
|
8
7
|
|
|
9
8
|
// TODO(burdon): Remove dep.
|
|
10
|
-
import { Avatar,
|
|
9
|
+
import { Avatar, type ThemedClassName, useTranslation } from '@dxos/react-ui';
|
|
11
10
|
import { type TextEditorProps, keymap, listener, TextEditor } from '@dxos/react-ui-editor';
|
|
12
|
-
import {
|
|
13
|
-
|
|
14
|
-
hoverableControlItem,
|
|
15
|
-
hoverableControls,
|
|
16
|
-
hoverableFocusedWithinControls,
|
|
17
|
-
mx,
|
|
18
|
-
} from '@dxos/react-ui-theme';
|
|
19
|
-
import { safeParseJson, hexToEmoji, hexToHue, isNotFalsy } from '@dxos/util';
|
|
11
|
+
import { focusRing, mx } from '@dxos/react-ui-theme';
|
|
12
|
+
import { hexToEmoji, hexToHue, isNotFalsy } from '@dxos/util';
|
|
20
13
|
|
|
21
14
|
import { translationKey } from '../translations';
|
|
22
|
-
import { type
|
|
15
|
+
import { type MessageMetadata } from '../types';
|
|
23
16
|
|
|
24
17
|
const avatarSize = 7;
|
|
25
18
|
|
|
@@ -57,69 +50,24 @@ export const MessageMeta = forwardRef<HTMLDivElement, MessageMetaProps>(
|
|
|
57
50
|
},
|
|
58
51
|
);
|
|
59
52
|
|
|
60
|
-
export type
|
|
61
|
-
block: MessageEntityBlock<BlockValue>;
|
|
62
|
-
authorId?: string;
|
|
63
|
-
onBlockDelete?: () => void;
|
|
64
|
-
};
|
|
65
|
-
|
|
66
|
-
const DefaultMessageBlock = ({ block, onBlockDelete }: MessageBlockProps<{ data?: any; text?: string }>) => {
|
|
67
|
-
const contentWidth = onBlockDelete ? 'col-span-2' : 'col-span-3';
|
|
68
|
-
return (
|
|
69
|
-
<div
|
|
70
|
-
role='none'
|
|
71
|
-
className={mx('grid grid-cols-subgrid col-span-3', hoverableControls, hoverableFocusedWithinControls)}
|
|
72
|
-
>
|
|
73
|
-
{block.data ? (
|
|
74
|
-
<pre className={mx('font-mono max-is-full overflow-x-auto', contentWidth)}>
|
|
75
|
-
<code>{JSON.stringify(safeParseJson(block.data), undefined, 2)}</code>
|
|
76
|
-
</pre>
|
|
77
|
-
) : (
|
|
78
|
-
<p className={contentWidth}>{block.text ?? ''}</p>
|
|
79
|
-
)}
|
|
80
|
-
{onBlockDelete && (
|
|
81
|
-
<Button
|
|
82
|
-
variant='ghost'
|
|
83
|
-
classNames={['p-1.5 min-bs-0 mie-1 items-start transition-opacity', hoverableControlItem]}
|
|
84
|
-
onClick={() => onBlockDelete()}
|
|
85
|
-
>
|
|
86
|
-
<X />
|
|
87
|
-
</Button>
|
|
88
|
-
)}
|
|
89
|
-
</div>
|
|
90
|
-
);
|
|
91
|
-
};
|
|
92
|
-
|
|
93
|
-
export type MessageProps<BlockValue> = MessageEntity<BlockValue> & {
|
|
94
|
-
onDelete?: (messageId: string, blockIndex: number) => void;
|
|
95
|
-
MessageBlockComponent?: FC<MessageBlockProps<BlockValue>>;
|
|
96
|
-
};
|
|
53
|
+
export type MessageProps = PropsWithChildren<MessageMetadata>;
|
|
97
54
|
|
|
98
|
-
export const Message =
|
|
99
|
-
const { id, authorName, onDelete, blocks, MessageBlockComponent = DefaultMessageBlock, ...metaProps } = props;
|
|
55
|
+
export const Message = ({ timestamp, children, ...messageMeta }: MessageProps) => {
|
|
100
56
|
const { t, dtLocale } = useTranslation(translationKey);
|
|
101
|
-
const
|
|
102
|
-
const dt = firstBlock.timestamp ? new Date(firstBlock.timestamp) : undefined;
|
|
57
|
+
const dt = timestamp ? new Date(timestamp) : undefined;
|
|
103
58
|
|
|
104
59
|
return (
|
|
105
|
-
<MessageMeta {...
|
|
60
|
+
<MessageMeta {...messageMeta} continues>
|
|
106
61
|
<p className='grid grid-cols-[1fr_max-content] gap-2 pie-2'>
|
|
107
|
-
<Avatar.Label classNames={['truncate text-sm font-medium', !authorName && 'fg-description']}>
|
|
108
|
-
{authorName ?? t('anonymous label')}
|
|
62
|
+
<Avatar.Label classNames={['truncate text-sm font-medium', !messageMeta.authorName && 'fg-description']}>
|
|
63
|
+
{messageMeta.authorName ?? t('anonymous label')}
|
|
109
64
|
</Avatar.Label>
|
|
110
65
|
<time className='fg-description text-xs pbs-0.5' dateTime={dt?.toISOString()}>
|
|
111
66
|
{dt ? formatDistanceToNow(dt, { locale: dtLocale, addSuffix: true }) : ''}
|
|
112
67
|
</time>
|
|
113
68
|
</p>
|
|
114
69
|
<div role='none' className='grid gap-y-1 grid-cols-[min-content_1fr_min-content]'>
|
|
115
|
-
{
|
|
116
|
-
<MessageBlockComponent
|
|
117
|
-
key={i}
|
|
118
|
-
block={block}
|
|
119
|
-
authorId={metaProps.authorId}
|
|
120
|
-
onBlockDelete={onDelete && (() => onDelete(id, i))}
|
|
121
|
-
/>
|
|
122
|
-
))}
|
|
70
|
+
{children}
|
|
123
71
|
</div>
|
|
124
72
|
</MessageMeta>
|
|
125
73
|
);
|
|
@@ -7,7 +7,7 @@ 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 { MessageType,
|
|
10
|
+
import { MessageType, TextType } from '@braneframe/types';
|
|
11
11
|
import { createDocAccessor, createEchoObject } from '@dxos/echo-db';
|
|
12
12
|
import { create } from '@dxos/echo-schema';
|
|
13
13
|
import { PublicKey } from '@dxos/keys';
|
|
@@ -30,9 +30,9 @@ import {
|
|
|
30
30
|
import { withTheme } from '@dxos/storybook-utils';
|
|
31
31
|
|
|
32
32
|
import { Thread, ThreadFooter, ThreadHeading } from './Thread';
|
|
33
|
-
import { Message,
|
|
33
|
+
import { Message, MessageTextbox } from '../Message';
|
|
34
|
+
import { type MessageEntity } from '../testing';
|
|
34
35
|
import translations from '../translations';
|
|
35
|
-
import { type MessageEntity } from '../types';
|
|
36
36
|
|
|
37
37
|
faker.seed(101);
|
|
38
38
|
|
|
@@ -44,7 +44,7 @@ const authorId = PublicKey.random().toHex();
|
|
|
44
44
|
|
|
45
45
|
const Editor: FC<{
|
|
46
46
|
id?: string;
|
|
47
|
-
item:
|
|
47
|
+
item: TextType;
|
|
48
48
|
comments: Comment[];
|
|
49
49
|
selected?: string;
|
|
50
50
|
onCreateComment: CommentsOptions['onCreate'];
|
|
@@ -105,18 +105,22 @@ type StoryCommentThread = {
|
|
|
105
105
|
cursor?: string;
|
|
106
106
|
range?: Range;
|
|
107
107
|
yPos?: number;
|
|
108
|
-
messages: MessageEntity
|
|
108
|
+
messages: MessageEntity[];
|
|
109
109
|
};
|
|
110
110
|
|
|
111
|
-
|
|
111
|
+
type MessageTextProps = {
|
|
112
|
+
message: MessageEntity;
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
const StoryMessageText = ({ message }: MessageTextProps) => {
|
|
112
116
|
const { themeMode } = useThemeContext();
|
|
113
|
-
const doc =
|
|
114
|
-
const accessor = createDocAccessor(
|
|
117
|
+
const doc = message.text;
|
|
118
|
+
const accessor = createDocAccessor(message, ['text']);
|
|
115
119
|
const { parentRef } = useTextEditor(
|
|
116
120
|
() => ({
|
|
117
121
|
doc,
|
|
118
122
|
extensions: [
|
|
119
|
-
//
|
|
123
|
+
// prettier-ignore
|
|
120
124
|
createBasicExtensions(),
|
|
121
125
|
createThemeExtensions({ themeMode }),
|
|
122
126
|
automerge(accessor),
|
|
@@ -163,13 +167,9 @@ const StoryThread: FC<{
|
|
|
163
167
|
const handleCreateMessage = () => {
|
|
164
168
|
if (messageRef.current?.length) {
|
|
165
169
|
const message = create(MessageType, {
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
timestamp: new Date().toISOString(),
|
|
170
|
-
content: create(TextV0Type, { content: messageRef.current }),
|
|
171
|
-
},
|
|
172
|
-
],
|
|
170
|
+
timestamp: new Date().toISOString(),
|
|
171
|
+
sender: { identityKey: authorId },
|
|
172
|
+
text: messageRef.current,
|
|
173
173
|
});
|
|
174
174
|
thread.messages.push(message);
|
|
175
175
|
|
|
@@ -193,7 +193,9 @@ const StoryThread: FC<{
|
|
|
193
193
|
</ThreadHeading>
|
|
194
194
|
|
|
195
195
|
{thread.messages.map((message) => (
|
|
196
|
-
<Message
|
|
196
|
+
<Message key={message.id} {...message}>
|
|
197
|
+
<StoryMessageText message={message} />
|
|
198
|
+
</Message>
|
|
197
199
|
))}
|
|
198
200
|
|
|
199
201
|
<div ref={containerRef} className='contents'>
|
|
@@ -253,7 +255,7 @@ type StoryProps = {
|
|
|
253
255
|
};
|
|
254
256
|
|
|
255
257
|
const Story = ({ text, autoCreate }: StoryProps) => {
|
|
256
|
-
const [item] = useState(createEchoObject(create(
|
|
258
|
+
const [item] = useState(createEchoObject(create(TextType, { content: text ?? '' })));
|
|
257
259
|
const [threads, setThreads] = useState<StoryCommentThread[]>([]);
|
|
258
260
|
const [selected, setSelected] = useState<string>();
|
|
259
261
|
|
|
@@ -275,13 +277,9 @@ const Story = ({ text, autoCreate }: StoryProps) => {
|
|
|
275
277
|
? faker.helpers.multiple(
|
|
276
278
|
() => ({
|
|
277
279
|
id: PublicKey.random().toHex(),
|
|
280
|
+
timestamp: new Date().toISOString(),
|
|
278
281
|
authorId: PublicKey.random().toHex(),
|
|
279
|
-
|
|
280
|
-
{
|
|
281
|
-
timestamp: new Date().toISOString(),
|
|
282
|
-
content: create(TextV0Type, { content: faker.lorem.sentence() }),
|
|
283
|
-
},
|
|
284
|
-
],
|
|
282
|
+
text: faker.lorem.sentence(),
|
|
285
283
|
}),
|
|
286
284
|
{ count: { min: 1, max: 3 } },
|
|
287
285
|
)
|
|
@@ -11,8 +11,8 @@ import { withTheme } from '@dxos/storybook-utils';
|
|
|
11
11
|
|
|
12
12
|
import { Thread, ThreadFooter } from './Thread';
|
|
13
13
|
import { Message, MessageTextbox } from '../Message';
|
|
14
|
+
import { DefaultMessageText, type MessageEntity } from '../testing';
|
|
14
15
|
import translations from '../translations';
|
|
15
|
-
import { type MessageEntity } from '../types';
|
|
16
16
|
|
|
17
17
|
const Story = () => {
|
|
18
18
|
const [pending, setPending] = useState(false);
|
|
@@ -21,25 +21,15 @@ const Story = () => {
|
|
|
21
21
|
const [messages, setMesssages] = useState<MessageEntity<{ id: string; text: string }>[]>([
|
|
22
22
|
{
|
|
23
23
|
id: 'm1',
|
|
24
|
+
timestamp: new Date().toISOString(),
|
|
24
25
|
authorId: identityKey1.toHex(),
|
|
25
|
-
|
|
26
|
-
{
|
|
27
|
-
id: 'b1',
|
|
28
|
-
timestamp: new Date().toISOString(),
|
|
29
|
-
text: 'hello',
|
|
30
|
-
},
|
|
31
|
-
],
|
|
26
|
+
text: 'hello',
|
|
32
27
|
},
|
|
33
28
|
{
|
|
34
29
|
id: 'm2',
|
|
30
|
+
timestamp: new Date().toISOString(),
|
|
35
31
|
authorId: identityKey2.toHex(),
|
|
36
|
-
|
|
37
|
-
{
|
|
38
|
-
id: 'b2',
|
|
39
|
-
timestamp: new Date().toISOString(),
|
|
40
|
-
text: 'hi there',
|
|
41
|
-
},
|
|
42
|
-
],
|
|
32
|
+
text: 'hi there',
|
|
43
33
|
},
|
|
44
34
|
]);
|
|
45
35
|
|
|
@@ -58,14 +48,9 @@ const Story = () => {
|
|
|
58
48
|
...messages,
|
|
59
49
|
{
|
|
60
50
|
id: `m${_count}`,
|
|
51
|
+
timestamp: new Date().toISOString(),
|
|
61
52
|
authorId: identityKey1.toHex(),
|
|
62
|
-
|
|
63
|
-
{
|
|
64
|
-
id: `b${_count}`,
|
|
65
|
-
timestamp: new Date().toISOString(),
|
|
66
|
-
text: messageRef.current,
|
|
67
|
-
},
|
|
68
|
-
],
|
|
53
|
+
text: messageRef.current,
|
|
69
54
|
},
|
|
70
55
|
]);
|
|
71
56
|
messageRef.current = '';
|
|
@@ -77,7 +62,9 @@ const Story = () => {
|
|
|
77
62
|
return (
|
|
78
63
|
<Thread id='t1'>
|
|
79
64
|
{messages.map((message) => (
|
|
80
|
-
<Message key={message.id} {...message}
|
|
65
|
+
<Message key={message.id} {...message}>
|
|
66
|
+
<DefaultMessageText text={message.text} onDelete={() => console.log('delete')} />
|
|
67
|
+
</Message>
|
|
81
68
|
))}
|
|
82
69
|
<MessageTextbox
|
|
83
70
|
id={String(_count)}
|
package/src/testing.tsx
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2024 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { X } from '@phosphor-icons/react';
|
|
6
|
+
import React from 'react';
|
|
7
|
+
|
|
8
|
+
import { Button } from '@dxos/react-ui';
|
|
9
|
+
import { hoverableControlItem, hoverableControls, hoverableFocusedWithinControls, mx } from '@dxos/react-ui-theme';
|
|
10
|
+
|
|
11
|
+
import { type MessageMetadata } from './types';
|
|
12
|
+
|
|
13
|
+
export type MessageEntity<PartValue = any> = MessageMetadata & {
|
|
14
|
+
text: string;
|
|
15
|
+
parts?: PartValue[];
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export type MessageTextProps = {
|
|
19
|
+
text: string;
|
|
20
|
+
onDelete?: () => void;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export const DefaultMessageText = ({ text, onDelete }: MessageTextProps) => {
|
|
24
|
+
const contentWidth = onDelete ? 'col-span-2' : 'col-span-3';
|
|
25
|
+
return (
|
|
26
|
+
<div
|
|
27
|
+
role='none'
|
|
28
|
+
className={mx('grid grid-cols-subgrid col-span-3', hoverableControls, hoverableFocusedWithinControls)}
|
|
29
|
+
>
|
|
30
|
+
<p className={contentWidth}>{text}</p>
|
|
31
|
+
{onDelete && (
|
|
32
|
+
<Button
|
|
33
|
+
variant='ghost'
|
|
34
|
+
classNames={['p-1.5 min-bs-0 mie-1 items-start transition-opacity', hoverableControlItem]}
|
|
35
|
+
onClick={() => onDelete()}
|
|
36
|
+
>
|
|
37
|
+
<X />
|
|
38
|
+
</Button>
|
|
39
|
+
)}
|
|
40
|
+
</div>
|
|
41
|
+
);
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
export type MessagePartProps<PartValue> = {
|
|
45
|
+
part: PartValue;
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
export const DefaultMessageBlock = <PartValue,>({ part }: MessagePartProps<PartValue>) => {
|
|
49
|
+
return (
|
|
50
|
+
<div
|
|
51
|
+
role='none'
|
|
52
|
+
className={mx('grid grid-cols-subgrid col-span-3', hoverableControls, hoverableFocusedWithinControls)}
|
|
53
|
+
>
|
|
54
|
+
<pre className='font-mono max-is-full overflow-x-auto col-span-3'>
|
|
55
|
+
<code>{JSON.stringify(part, undefined, 2)}</code>
|
|
56
|
+
</pre>
|
|
57
|
+
</div>
|
|
58
|
+
);
|
|
59
|
+
};
|
package/src/types.ts
CHANGED
|
@@ -6,20 +6,13 @@ import { type FallbackValue } from '@dxos/util';
|
|
|
6
6
|
|
|
7
7
|
export type MessageMetadata = {
|
|
8
8
|
id: string; // TODO(burdon): Remove/rename?
|
|
9
|
+
timestamp?: string;
|
|
9
10
|
authorId?: string;
|
|
10
11
|
authorName?: string;
|
|
11
12
|
authorImgSrc?: string;
|
|
12
13
|
authorAvatarProps?: FallbackValue;
|
|
13
14
|
};
|
|
14
15
|
|
|
15
|
-
export type MessageEntityBlock<BlockValue> = BlockValue & {
|
|
16
|
-
timestamp?: string;
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
export type MessageEntity<BlockValue> = MessageMetadata & {
|
|
20
|
-
blocks: MessageEntityBlock<BlockValue>[];
|
|
21
|
-
};
|
|
22
|
-
|
|
23
16
|
export type ThreadEntity = {
|
|
24
17
|
topicId?: string;
|
|
25
18
|
topicTitle?: string;
|