@dxos/react-ui-thread 0.5.9-main.079a532 → 0.5.9-main.0a0e87d
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 +36 -9
- 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 +12 -4
- 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 +5 -2
- 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/types.d.ts +6 -1
- package/dist/types/src/types.d.ts.map +1 -1
- package/package.json +13 -13
- package/src/Message/Message.stories.tsx +10 -7
- package/src/Message/Message.tsx +64 -12
- package/src/Thread/Comments.stories.tsx +24 -22
- package/src/Thread/Thread.stories.tsx +23 -10
- package/src/types.ts +8 -1
- package/dist/types/src/testing.d.ts +0 -16
- package/dist/types/src/testing.d.ts.map +0 -1
- package/src/testing.tsx +0 -59
|
@@ -68,12 +68,13 @@ 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";
|
|
71
72
|
import { formatDistanceToNow } from "date-fns/formatDistanceToNow";
|
|
72
73
|
import React2, { forwardRef as forwardRef2, useMemo } from "react";
|
|
73
|
-
import { Avatar, useTranslation as useTranslation2 } from "@dxos/react-ui";
|
|
74
|
+
import { Avatar, Button, useTranslation as useTranslation2 } from "@dxos/react-ui";
|
|
74
75
|
import { keymap, listener, TextEditor } from "@dxos/react-ui-editor";
|
|
75
|
-
import { focusRing, mx as mx2 } from "@dxos/react-ui-theme";
|
|
76
|
-
import { hexToEmoji, hexToHue, isNotFalsy } from "@dxos/util";
|
|
76
|
+
import { focusRing, hoverableControlItem as hoverableControlItem2, hoverableControls, hoverableFocusedWithinControls as hoverableFocusedWithinControls2, mx as mx2 } from "@dxos/react-ui-theme";
|
|
77
|
+
import { safeParseJson, hexToEmoji, hexToHue, isNotFalsy } from "@dxos/util";
|
|
77
78
|
var avatarSize = 7;
|
|
78
79
|
var MessageMeta = /* @__PURE__ */ forwardRef2(({ authorImgSrc, authorId, authorName, authorAvatarProps, continues = true, children, classNames, ...rootProps }, forwardedRef) => {
|
|
79
80
|
return /* @__PURE__ */ React2.createElement(Avatar.Root, {
|
|
@@ -100,20 +101,41 @@ var MessageMeta = /* @__PURE__ */ forwardRef2(({ authorImgSrc, authorId, authorN
|
|
|
100
101
|
className: "plb-1 min-is-0"
|
|
101
102
|
}, children)));
|
|
102
103
|
});
|
|
103
|
-
var
|
|
104
|
+
var DefaultMessageBlock = ({ block, onBlockDelete }) => {
|
|
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;
|
|
104
124
|
const { t, dtLocale } = useTranslation2(translationKey);
|
|
105
|
-
const
|
|
125
|
+
const firstBlock = blocks[0];
|
|
126
|
+
const dt = firstBlock.timestamp ? new Date(firstBlock.timestamp) : void 0;
|
|
106
127
|
return /* @__PURE__ */ React2.createElement(MessageMeta, {
|
|
107
|
-
...
|
|
128
|
+
...metaProps,
|
|
129
|
+
id,
|
|
108
130
|
continues: true
|
|
109
131
|
}, /* @__PURE__ */ React2.createElement("p", {
|
|
110
132
|
className: "grid grid-cols-[1fr_max-content] gap-2 pie-2"
|
|
111
133
|
}, /* @__PURE__ */ React2.createElement(Avatar.Label, {
|
|
112
134
|
classNames: [
|
|
113
135
|
"truncate text-sm font-medium",
|
|
114
|
-
!
|
|
136
|
+
!authorName && "fg-description"
|
|
115
137
|
]
|
|
116
|
-
},
|
|
138
|
+
}, authorName ?? t("anonymous label")), /* @__PURE__ */ React2.createElement("time", {
|
|
117
139
|
className: "fg-description text-xs pbs-0.5",
|
|
118
140
|
dateTime: dt?.toISOString()
|
|
119
141
|
}, dt ? formatDistanceToNow(dt, {
|
|
@@ -122,7 +144,12 @@ var Message = ({ timestamp, children, ...messageMeta }) => {
|
|
|
122
144
|
}) : "")), /* @__PURE__ */ React2.createElement("div", {
|
|
123
145
|
role: "none",
|
|
124
146
|
className: "grid gap-y-1 grid-cols-[min-content_1fr_min-content]"
|
|
125
|
-
},
|
|
147
|
+
}, blocks.map((block, i) => /* @__PURE__ */ React2.createElement(MessageBlockComponent, {
|
|
148
|
+
key: i,
|
|
149
|
+
block,
|
|
150
|
+
authorId: metaProps.authorId,
|
|
151
|
+
onBlockDelete: onDelete && (() => onDelete(id, i))
|
|
152
|
+
}))));
|
|
126
153
|
};
|
|
127
154
|
var keyBindings = ({ onSend, onClear }) => [
|
|
128
155
|
{
|
|
@@ -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 { 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": ";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,2BAA2B;AACpC,OAAOC,
|
|
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", "
|
|
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": "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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", "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":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":20403,"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":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":1143,"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":16946},"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":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":5333},"packages/ui/react-ui-thread/src/Message/index.ts":{"bytesInOutput":0}},"bytes":8784}}}
|
|
@@ -1,13 +1,21 @@
|
|
|
1
|
-
import React, { type ComponentPropsWithRef, type
|
|
1
|
+
import React, { type ComponentPropsWithRef, type FC } from 'react';
|
|
2
2
|
import { type ThemedClassName } from '@dxos/react-ui';
|
|
3
3
|
import { type TextEditorProps } from '@dxos/react-ui-editor';
|
|
4
|
-
import { type MessageMetadata } from '../types';
|
|
4
|
+
import { type MessageEntity, type MessageEntityBlock, 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
|
-
|
|
9
|
+
export type MessageBlockProps<BlockValue> = {
|
|
10
|
+
block: MessageEntityBlock<BlockValue>;
|
|
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;
|
|
11
19
|
export type MessageTextboxProps = {
|
|
12
20
|
disabled?: boolean;
|
|
13
21
|
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":"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,sBAAwB,aAAa,UAAU,CAAC,gBA4BnE,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: <BlockValue>(props: import("./Message").MessageProps<BlockValue>) => 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;;;;;;;;;;;;;;;;;;;;;;;;;AAgCpB,wBAME;AAEF,eAAO,MAAM,OAAO,IAAK,CAAC"}
|
|
@@ -1,13 +1,16 @@
|
|
|
1
1
|
import '@dxosTheme';
|
|
2
2
|
import React from 'react';
|
|
3
|
+
import { TextV0Type } from '@braneframe/types';
|
|
3
4
|
import { type Range } from '@dxos/react-ui-editor';
|
|
4
|
-
import { type MessageEntity } from '../
|
|
5
|
+
import { type MessageEntity } from '../types';
|
|
5
6
|
type StoryCommentThread = {
|
|
6
7
|
id: string;
|
|
7
8
|
cursor?: string;
|
|
8
9
|
range?: Range;
|
|
9
10
|
yPos?: number;
|
|
10
|
-
messages: MessageEntity
|
|
11
|
+
messages: MessageEntity<{
|
|
12
|
+
content?: TextV0Type;
|
|
13
|
+
}>[];
|
|
11
14
|
};
|
|
12
15
|
type StoryProps = {
|
|
13
16
|
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;AAE7E,OAAO,EAAe,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAO5D,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"}
|
|
@@ -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("../types").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;;;;;;;;;;;;;;;;;;;;;;;;;AAwFzD,wBAME;AAEF,eAAO,MAAM,OAAO,IAAK,CAAC"}
|
|
@@ -1,12 +1,17 @@
|
|
|
1
1
|
import { type FallbackValue } from '@dxos/util';
|
|
2
2
|
export type MessageMetadata = {
|
|
3
3
|
id: string;
|
|
4
|
-
timestamp?: string;
|
|
5
4
|
authorId?: string;
|
|
6
5
|
authorName?: string;
|
|
7
6
|
authorImgSrc?: string;
|
|
8
7
|
authorAvatarProps?: FallbackValue;
|
|
9
8
|
};
|
|
9
|
+
export type MessageEntityBlock<BlockValue> = BlockValue & {
|
|
10
|
+
timestamp?: string;
|
|
11
|
+
};
|
|
12
|
+
export type MessageEntity<BlockValue> = MessageMetadata & {
|
|
13
|
+
blocks: MessageEntityBlock<BlockValue>[];
|
|
14
|
+
};
|
|
10
15
|
export type ThreadEntity = {
|
|
11
16
|
topicId?: string;
|
|
12
17
|
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,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,kBAAkB,CAAC,UAAU,IAAI,UAAU,GAAG;IACxD,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,aAAa,CAAC,UAAU,IAAI,eAAe,GAAG;IACxD,MAAM,EAAE,kBAAkB,CAAC,UAAU,CAAC,EAAE,CAAC;CAC1C,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.0a0e87d",
|
|
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-mosaic": "0.5.9-main.
|
|
23
|
-
"@dxos/react-ui-
|
|
24
|
-
"@dxos/react-ui-
|
|
25
|
-
"@dxos/util": "0.5.9-main.
|
|
21
|
+
"@dxos/react-ui": "0.5.9-main.0a0e87d",
|
|
22
|
+
"@dxos/react-ui-mosaic": "0.5.9-main.0a0e87d",
|
|
23
|
+
"@dxos/react-ui-theme": "0.5.9-main.0a0e87d",
|
|
24
|
+
"@dxos/react-ui-editor": "0.5.9-main.0a0e87d",
|
|
25
|
+
"@dxos/util": "0.5.9-main.0a0e87d"
|
|
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/echo-db": "0.5.9-main.
|
|
36
|
-
"@dxos/echo-schema": "0.5.9-main.
|
|
37
|
-
"@dxos/keys": "0.5.9-main.
|
|
38
|
-
"@dxos/log": "0.5.9-main.
|
|
39
|
-
"@dxos/random": "0.5.9-main.
|
|
40
|
-
"@dxos/storybook-utils": "0.5.9-main.
|
|
34
|
+
"@braneframe/types": "0.5.9-main.0a0e87d",
|
|
35
|
+
"@dxos/echo-db": "0.5.9-main.0a0e87d",
|
|
36
|
+
"@dxos/echo-schema": "0.5.9-main.0a0e87d",
|
|
37
|
+
"@dxos/keys": "0.5.9-main.0a0e87d",
|
|
38
|
+
"@dxos/log": "0.5.9-main.0a0e87d",
|
|
39
|
+
"@dxos/random": "0.5.9-main.0a0e87d",
|
|
40
|
+
"@dxos/storybook-utils": "0.5.9-main.0a0e87d"
|
|
41
41
|
},
|
|
42
42
|
"peerDependencies": {
|
|
43
43
|
"@phosphor-icons/react": "^2.1.5",
|
|
@@ -10,23 +10,26 @@ 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';
|
|
14
13
|
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<{ id: string; text: string }>>({
|
|
19
19
|
id: 'm1',
|
|
20
|
-
timestamp: new Date().toISOString(),
|
|
21
20
|
authorId: identityKey.toHex(),
|
|
22
|
-
|
|
21
|
+
blocks: [
|
|
22
|
+
{
|
|
23
|
+
id: 'b1',
|
|
24
|
+
timestamp: new Date().toISOString(),
|
|
25
|
+
text: 'hello',
|
|
26
|
+
},
|
|
27
|
+
],
|
|
23
28
|
});
|
|
24
29
|
|
|
25
30
|
return (
|
|
26
31
|
<div className='grid grid-cols-[var(--rail-size)_1fr]'>
|
|
27
|
-
<Message {...message}
|
|
28
|
-
<DefaultMessageText text={message.text} onDelete={() => console.log('delete')} />
|
|
29
|
-
</Message>
|
|
32
|
+
<Message {...message} />
|
|
30
33
|
</div>
|
|
31
34
|
);
|
|
32
35
|
};
|
package/src/Message/Message.tsx
CHANGED
|
@@ -2,17 +2,24 @@
|
|
|
2
2
|
// Copyright 2023 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
+
import { X } from '@phosphor-icons/react';
|
|
5
6
|
import { formatDistanceToNow } from 'date-fns/formatDistanceToNow';
|
|
6
|
-
import React, { type ComponentPropsWithRef, forwardRef, useMemo
|
|
7
|
+
import React, { type ComponentPropsWithRef, type FC, forwardRef, useMemo } from 'react';
|
|
7
8
|
|
|
8
9
|
// TODO(burdon): Remove dep.
|
|
9
|
-
import { Avatar, type ThemedClassName, useTranslation } from '@dxos/react-ui';
|
|
10
|
+
import { Avatar, Button, type ThemedClassName, useTranslation } from '@dxos/react-ui';
|
|
10
11
|
import { type TextEditorProps, keymap, listener, TextEditor } from '@dxos/react-ui-editor';
|
|
11
|
-
import {
|
|
12
|
-
|
|
12
|
+
import {
|
|
13
|
+
focusRing,
|
|
14
|
+
hoverableControlItem,
|
|
15
|
+
hoverableControls,
|
|
16
|
+
hoverableFocusedWithinControls,
|
|
17
|
+
mx,
|
|
18
|
+
} from '@dxos/react-ui-theme';
|
|
19
|
+
import { safeParseJson, hexToEmoji, hexToHue, isNotFalsy } from '@dxos/util';
|
|
13
20
|
|
|
14
21
|
import { translationKey } from '../translations';
|
|
15
|
-
import { type MessageMetadata } from '../types';
|
|
22
|
+
import { type MessageEntity, type MessageEntityBlock, type MessageMetadata } from '../types';
|
|
16
23
|
|
|
17
24
|
const avatarSize = 7;
|
|
18
25
|
|
|
@@ -50,24 +57,69 @@ export const MessageMeta = forwardRef<HTMLDivElement, MessageMetaProps>(
|
|
|
50
57
|
},
|
|
51
58
|
);
|
|
52
59
|
|
|
53
|
-
export type
|
|
60
|
+
export type MessageBlockProps<BlockValue> = {
|
|
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
|
+
};
|
|
54
97
|
|
|
55
|
-
export const Message = (
|
|
98
|
+
export const Message = <BlockValue,>(props: MessageProps<BlockValue>) => {
|
|
99
|
+
const { id, authorName, onDelete, blocks, MessageBlockComponent = DefaultMessageBlock, ...metaProps } = props;
|
|
56
100
|
const { t, dtLocale } = useTranslation(translationKey);
|
|
57
|
-
const
|
|
101
|
+
const firstBlock = blocks[0];
|
|
102
|
+
const dt = firstBlock.timestamp ? new Date(firstBlock.timestamp) : undefined;
|
|
58
103
|
|
|
59
104
|
return (
|
|
60
|
-
<MessageMeta {...
|
|
105
|
+
<MessageMeta {...metaProps} id={id} continues>
|
|
61
106
|
<p className='grid grid-cols-[1fr_max-content] gap-2 pie-2'>
|
|
62
|
-
<Avatar.Label classNames={['truncate text-sm font-medium', !
|
|
63
|
-
{
|
|
107
|
+
<Avatar.Label classNames={['truncate text-sm font-medium', !authorName && 'fg-description']}>
|
|
108
|
+
{authorName ?? t('anonymous label')}
|
|
64
109
|
</Avatar.Label>
|
|
65
110
|
<time className='fg-description text-xs pbs-0.5' dateTime={dt?.toISOString()}>
|
|
66
111
|
{dt ? formatDistanceToNow(dt, { locale: dtLocale, addSuffix: true }) : ''}
|
|
67
112
|
</time>
|
|
68
113
|
</p>
|
|
69
114
|
<div role='none' className='grid gap-y-1 grid-cols-[min-content_1fr_min-content]'>
|
|
70
|
-
{
|
|
115
|
+
{blocks.map((block, i) => (
|
|
116
|
+
<MessageBlockComponent
|
|
117
|
+
key={i}
|
|
118
|
+
block={block}
|
|
119
|
+
authorId={metaProps.authorId}
|
|
120
|
+
onBlockDelete={onDelete && (() => onDelete(id, i))}
|
|
121
|
+
/>
|
|
122
|
+
))}
|
|
71
123
|
</div>
|
|
72
124
|
</MessageMeta>
|
|
73
125
|
);
|
|
@@ -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, TextV0Type } 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, MessageTextbox } from '../Message';
|
|
34
|
-
import { type MessageEntity } from '../testing';
|
|
33
|
+
import { Message, type MessageBlockProps, MessageTextbox } from '../Message';
|
|
35
34
|
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: TextV0Type;
|
|
48
48
|
comments: Comment[];
|
|
49
49
|
selected?: string;
|
|
50
50
|
onCreateComment: CommentsOptions['onCreate'];
|
|
@@ -105,22 +105,18 @@ type StoryCommentThread = {
|
|
|
105
105
|
cursor?: string;
|
|
106
106
|
range?: Range;
|
|
107
107
|
yPos?: number;
|
|
108
|
-
messages: MessageEntity[];
|
|
108
|
+
messages: MessageEntity<{ content?: TextV0Type }>[];
|
|
109
109
|
};
|
|
110
110
|
|
|
111
|
-
|
|
112
|
-
message: MessageEntity;
|
|
113
|
-
};
|
|
114
|
-
|
|
115
|
-
const StoryMessageText = ({ message }: MessageTextProps) => {
|
|
111
|
+
const StoryMessageBlock = (props: MessageBlockProps<{ content?: TextV0Type }>) => {
|
|
116
112
|
const { themeMode } = useThemeContext();
|
|
117
|
-
const doc =
|
|
118
|
-
const accessor = createDocAccessor(
|
|
113
|
+
const doc = props.block.content?.content;
|
|
114
|
+
const accessor = createDocAccessor(props.block.content!, ['content']);
|
|
119
115
|
const { parentRef } = useTextEditor(
|
|
120
116
|
() => ({
|
|
121
117
|
doc,
|
|
122
118
|
extensions: [
|
|
123
|
-
//
|
|
119
|
+
//
|
|
124
120
|
createBasicExtensions(),
|
|
125
121
|
createThemeExtensions({ themeMode }),
|
|
126
122
|
automerge(accessor),
|
|
@@ -167,9 +163,13 @@ const StoryThread: FC<{
|
|
|
167
163
|
const handleCreateMessage = () => {
|
|
168
164
|
if (messageRef.current?.length) {
|
|
169
165
|
const message = create(MessageType, {
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
166
|
+
from: { identityKey: authorId },
|
|
167
|
+
blocks: [
|
|
168
|
+
{
|
|
169
|
+
timestamp: new Date().toISOString(),
|
|
170
|
+
content: create(TextV0Type, { content: messageRef.current }),
|
|
171
|
+
},
|
|
172
|
+
],
|
|
173
173
|
});
|
|
174
174
|
thread.messages.push(message);
|
|
175
175
|
|
|
@@ -193,9 +193,7 @@ const StoryThread: FC<{
|
|
|
193
193
|
</ThreadHeading>
|
|
194
194
|
|
|
195
195
|
{thread.messages.map((message) => (
|
|
196
|
-
<Message key={message.id} {...message}
|
|
197
|
-
<StoryMessageText message={message} />
|
|
198
|
-
</Message>
|
|
196
|
+
<Message<{ content?: TextV0Type }> key={message.id} {...message} MessageBlockComponent={StoryMessageBlock} />
|
|
199
197
|
))}
|
|
200
198
|
|
|
201
199
|
<div ref={containerRef} className='contents'>
|
|
@@ -255,7 +253,7 @@ type StoryProps = {
|
|
|
255
253
|
};
|
|
256
254
|
|
|
257
255
|
const Story = ({ text, autoCreate }: StoryProps) => {
|
|
258
|
-
const [item] = useState(createEchoObject(create(
|
|
256
|
+
const [item] = useState(createEchoObject(create(TextV0Type, { content: text ?? '' })));
|
|
259
257
|
const [threads, setThreads] = useState<StoryCommentThread[]>([]);
|
|
260
258
|
const [selected, setSelected] = useState<string>();
|
|
261
259
|
|
|
@@ -277,9 +275,13 @@ const Story = ({ text, autoCreate }: StoryProps) => {
|
|
|
277
275
|
? faker.helpers.multiple(
|
|
278
276
|
() => ({
|
|
279
277
|
id: PublicKey.random().toHex(),
|
|
280
|
-
timestamp: new Date().toISOString(),
|
|
281
278
|
authorId: PublicKey.random().toHex(),
|
|
282
|
-
|
|
279
|
+
blocks: [
|
|
280
|
+
{
|
|
281
|
+
timestamp: new Date().toISOString(),
|
|
282
|
+
content: create(TextV0Type, { content: faker.lorem.sentence() }),
|
|
283
|
+
},
|
|
284
|
+
],
|
|
283
285
|
}),
|
|
284
286
|
{ count: { min: 1, max: 3 } },
|
|
285
287
|
)
|
|
@@ -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';
|
|
15
14
|
import translations from '../translations';
|
|
15
|
+
import { type MessageEntity } from '../types';
|
|
16
16
|
|
|
17
17
|
const Story = () => {
|
|
18
18
|
const [pending, setPending] = useState(false);
|
|
@@ -21,15 +21,25 @@ const Story = () => {
|
|
|
21
21
|
const [messages, setMesssages] = useState<MessageEntity<{ id: string; text: string }>[]>([
|
|
22
22
|
{
|
|
23
23
|
id: 'm1',
|
|
24
|
-
timestamp: new Date().toISOString(),
|
|
25
24
|
authorId: identityKey1.toHex(),
|
|
26
|
-
|
|
25
|
+
blocks: [
|
|
26
|
+
{
|
|
27
|
+
id: 'b1',
|
|
28
|
+
timestamp: new Date().toISOString(),
|
|
29
|
+
text: 'hello',
|
|
30
|
+
},
|
|
31
|
+
],
|
|
27
32
|
},
|
|
28
33
|
{
|
|
29
34
|
id: 'm2',
|
|
30
|
-
timestamp: new Date().toISOString(),
|
|
31
35
|
authorId: identityKey2.toHex(),
|
|
32
|
-
|
|
36
|
+
blocks: [
|
|
37
|
+
{
|
|
38
|
+
id: 'b2',
|
|
39
|
+
timestamp: new Date().toISOString(),
|
|
40
|
+
text: 'hi there',
|
|
41
|
+
},
|
|
42
|
+
],
|
|
33
43
|
},
|
|
34
44
|
]);
|
|
35
45
|
|
|
@@ -48,9 +58,14 @@ const Story = () => {
|
|
|
48
58
|
...messages,
|
|
49
59
|
{
|
|
50
60
|
id: `m${_count}`,
|
|
51
|
-
timestamp: new Date().toISOString(),
|
|
52
61
|
authorId: identityKey1.toHex(),
|
|
53
|
-
|
|
62
|
+
blocks: [
|
|
63
|
+
{
|
|
64
|
+
id: `b${_count}`,
|
|
65
|
+
timestamp: new Date().toISOString(),
|
|
66
|
+
text: messageRef.current,
|
|
67
|
+
},
|
|
68
|
+
],
|
|
54
69
|
},
|
|
55
70
|
]);
|
|
56
71
|
messageRef.current = '';
|
|
@@ -62,9 +77,7 @@ const Story = () => {
|
|
|
62
77
|
return (
|
|
63
78
|
<Thread id='t1'>
|
|
64
79
|
{messages.map((message) => (
|
|
65
|
-
<Message key={message.id} {...message}
|
|
66
|
-
<DefaultMessageText text={message.text} onDelete={() => console.log('delete')} />
|
|
67
|
-
</Message>
|
|
80
|
+
<Message key={message.id} {...message} />
|
|
68
81
|
))}
|
|
69
82
|
<MessageTextbox
|
|
70
83
|
id={String(_count)}
|
package/src/types.ts
CHANGED
|
@@ -6,13 +6,20 @@ import { type FallbackValue } from '@dxos/util';
|
|
|
6
6
|
|
|
7
7
|
export type MessageMetadata = {
|
|
8
8
|
id: string; // TODO(burdon): Remove/rename?
|
|
9
|
-
timestamp?: string;
|
|
10
9
|
authorId?: string;
|
|
11
10
|
authorName?: string;
|
|
12
11
|
authorImgSrc?: string;
|
|
13
12
|
authorAvatarProps?: FallbackValue;
|
|
14
13
|
};
|
|
15
14
|
|
|
15
|
+
export type MessageEntityBlock<BlockValue> = BlockValue & {
|
|
16
|
+
timestamp?: string;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export type MessageEntity<BlockValue> = MessageMetadata & {
|
|
20
|
+
blocks: MessageEntityBlock<BlockValue>[];
|
|
21
|
+
};
|
|
22
|
+
|
|
16
23
|
export type ThreadEntity = {
|
|
17
24
|
topicId?: string;
|
|
18
25
|
topicTitle?: string;
|
|
@@ -1,16 +0,0 @@
|
|
|
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
|
|
@@ -1 +0,0 @@
|
|
|
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"}
|
package/src/testing.tsx
DELETED
|
@@ -1,59 +0,0 @@
|
|
|
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
|
-
};
|