@dxos/react-ui-thread 0.3.11-main.80db41b → 0.3.11-main.8452415
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 +39 -6
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/types/src/Message/Message.d.ts.map +1 -1
- package/dist/types/src/Message/command-extension.d.ts +3 -0
- package/dist/types/src/Message/command-extension.d.ts.map +1 -0
- package/package.json +12 -10
- package/src/Message/Message.tsx +7 -9
- package/src/Message/command-extension.ts +40 -0
|
@@ -72,6 +72,39 @@ import { Avatar, Button, useJdenticonHref, useTranslation as useTranslation2 } f
|
|
|
72
72
|
import { TextEditor, keymap, listener } from "@dxos/react-ui-editor";
|
|
73
73
|
import { focusRing, hoverableControlItem as hoverableControlItem2, hoverableControls, hoverableFocusedWithinControls as hoverableFocusedWithinControls2, mx as mx2 } from "@dxos/react-ui-theme";
|
|
74
74
|
import { safeParseJson } from "@dxos/util";
|
|
75
|
+
|
|
76
|
+
// packages/ui/react-ui-thread/src/Message/command-extension.ts
|
|
77
|
+
import { StreamLanguage, HighlightStyle, syntaxHighlighting } from "@codemirror/language";
|
|
78
|
+
import { tags } from "@dxos/react-ui-editor";
|
|
79
|
+
import { tagRoot } from "@dxos/react-ui-theme";
|
|
80
|
+
var parser = StreamLanguage.define({
|
|
81
|
+
startState: () => ({
|
|
82
|
+
count: 0
|
|
83
|
+
}),
|
|
84
|
+
token: (stream, state) => {
|
|
85
|
+
state.count++;
|
|
86
|
+
if (stream.eatSpace()) {
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
89
|
+
if (state.count === 1 && stream.match(/^(\/\w+)/)) {
|
|
90
|
+
return "tagName";
|
|
91
|
+
}
|
|
92
|
+
stream.next();
|
|
93
|
+
return null;
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
var styles = HighlightStyle.define([
|
|
97
|
+
{
|
|
98
|
+
tag: tags.tagName,
|
|
99
|
+
class: tagRoot({})
|
|
100
|
+
}
|
|
101
|
+
]);
|
|
102
|
+
var command = [
|
|
103
|
+
parser,
|
|
104
|
+
syntaxHighlighting(styles)
|
|
105
|
+
];
|
|
106
|
+
|
|
107
|
+
// packages/ui/react-ui-thread/src/Message/Message.tsx
|
|
75
108
|
var avatarSize = 7;
|
|
76
109
|
var messageCell = "plb-1 min-is-0";
|
|
77
110
|
var MessageMeta = /* @__PURE__ */ forwardRef2(({ authorImgSrc, authorStatus, authorId, authorName, continues = true, children, classNames, ...rootProps }, forwardedRef) => {
|
|
@@ -111,7 +144,7 @@ var DefaultMessageBlock = ({ block, onBlockDelete }) => {
|
|
|
111
144
|
}, block.text ?? ""), onBlockDelete && /* @__PURE__ */ React2.createElement(Button, {
|
|
112
145
|
variant: "ghost",
|
|
113
146
|
classNames: [
|
|
114
|
-
"p-1
|
|
147
|
+
"p-1 min-bs-0 mie-1 place-self-start transition-opacity",
|
|
115
148
|
hoverableControlItem2
|
|
116
149
|
],
|
|
117
150
|
onClick: onBlockDelete
|
|
@@ -130,11 +163,11 @@ var Message = (props) => {
|
|
|
130
163
|
className: "grid grid-cols-[1fr_max-content] gap-2 pie-2"
|
|
131
164
|
}, /* @__PURE__ */ React2.createElement(Avatar.Label, {
|
|
132
165
|
classNames: [
|
|
133
|
-
"truncate
|
|
166
|
+
"truncate font-semibold",
|
|
134
167
|
!authorName && "fg-description"
|
|
135
168
|
]
|
|
136
169
|
}, authorName ?? t("anonymous label")), /* @__PURE__ */ React2.createElement("time", {
|
|
137
|
-
className: "fg-description text-xs pbs-
|
|
170
|
+
className: "fg-description text-xs pbs-1",
|
|
138
171
|
dateTime: dt?.toISOString()
|
|
139
172
|
}, dt ? formatDistanceToNow(dt, {
|
|
140
173
|
locale: dtLocale,
|
|
@@ -148,7 +181,7 @@ var Message = (props) => {
|
|
|
148
181
|
onBlockDelete: onDelete && (() => onDelete(id, i))
|
|
149
182
|
}))));
|
|
150
183
|
};
|
|
151
|
-
var MessageTextbox = /* @__PURE__ */ forwardRef2(({ onSend, onClear, onEditorFocus, authorId, authorName, authorImgSrc, disabled,
|
|
184
|
+
var MessageTextbox = /* @__PURE__ */ forwardRef2(({ onSend, onClear, onEditorFocus, authorId, authorName, authorImgSrc, disabled, ...editorProps }, forwardedRef) => {
|
|
152
185
|
return /* @__PURE__ */ React2.createElement(MessageMeta, {
|
|
153
186
|
id: editorProps.model.id,
|
|
154
187
|
authorId,
|
|
@@ -159,12 +192,12 @@ var MessageTextbox = /* @__PURE__ */ forwardRef2(({ onSend, onClear, onEditorFoc
|
|
|
159
192
|
}, /* @__PURE__ */ React2.createElement(TextEditor, {
|
|
160
193
|
slots: {
|
|
161
194
|
root: {
|
|
162
|
-
className: mx2("plb-
|
|
195
|
+
className: mx2("plb-1 mie-1 rounded-sm", focusRing, disabled && "opacity-50")
|
|
163
196
|
}
|
|
164
197
|
},
|
|
165
198
|
readonly: disabled,
|
|
166
199
|
extensions: [
|
|
167
|
-
|
|
200
|
+
command,
|
|
168
201
|
keymap.of([
|
|
169
202
|
{
|
|
170
203
|
key: "Enter",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 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, DotsThreeOutline } 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 Thread = forwardRef<HTMLDivElement, ThreadProps>(\n ({ current, children, classNames, ...props }, forwardedRef) => {\n return (\n <div\n role='group'\n {...(current && { 'aria-current': typeof current === 'string' ? current : 'location' })}\n {...props}\n className={mx(\n 'is-full place-self-start grid grid-cols-[3rem_1fr] 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 hoverableFocusedWithinControls,\n classNames,\n )}\n ref={forwardedRef}\n >\n {children}\n </div>\n );\n },\n);\n\nexport type ThreadHeadingProps = ThemedClassName<ComponentPropsWithRef<'div'>>;\n\nexport const ThreadHeading = forwardRef<HTMLDivElement, ThreadHeadingProps>(\n ({ classNames, children, ...props }, forwardedRef) => {\n return (\n <div\n role='heading'\n {...props}\n className={mx('col-span-2 grid grid-cols-subgrid fg-description font-medium', classNames)}\n ref={forwardedRef}\n >\n <div role='none' className='grid place-items-end pie-3.5 fg-separator'>\n <ArrowBendLeftDown />\n </div>\n <p>{children}</p>\n </div>\n );\n },\n);\n\nexport type ThreadFooterProps = ThemedClassName<ComponentPropsWithRef<'div'>> & {\n activity?: boolean;\n};\n\nexport const ThreadFooter = forwardRef<HTMLDivElement, ThreadFooterProps>(\n ({ activity, classNames, children, ...props }, forwardedRef) => {\n const { t } = useTranslation(translationKey);\n return (\n <div\n {...props}\n className={mx('col-start-2 grid grid-cols-[min-content_1fr_max-content] text-xs fg-description', classNames)}\n ref={forwardedRef}\n >\n <DotsThreeOutline\n weight='fill'\n data-visible={activity ? 'show' : 'hide'}\n className='is-6 bs-4 invisible data-[visible=show]:visible'\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 } from 'react';\n\nimport { Avatar, Button, type ThemedClassName, useJdenticonHref, useTranslation } from '@dxos/react-ui';\nimport { TextEditor, type TextEditorProps, keymap, type EditorView, listener } from '@dxos/react-ui-editor';\nimport {\n focusRing,\n hoverableControlItem,\n hoverableControls,\n hoverableFocusedWithinControls,\n mx,\n} from '@dxos/react-ui-theme';\nimport { safeParseJson } from '@dxos/util';\n\nimport { translationKey } from '../translations';\nimport { type MessageEntity, type MessageEntityBlock, type MessageMetadata } from '../types';\n\nconst avatarSize = 7;\n\nconst messageCell = 'plb-1 min-is-0';\n\nexport type MessageMetaProps = ThemedClassName<ComponentPropsWithRef<'div'>> &\n MessageMetadata &\n Partial<{ continues: boolean }>;\n\nexport const MessageMeta = forwardRef<HTMLDivElement, MessageMetaProps>(\n (\n { authorImgSrc, authorStatus, authorId, authorName, continues = true, children, classNames, ...rootProps },\n forwardedRef,\n ) => {\n const jdenticon = useJdenticonHref(authorId ?? '', avatarSize);\n\n return (\n <Avatar.Root status={authorStatus ?? 'inactive'} size={avatarSize}>\n <div\n role='none'\n {...rootProps}\n className={mx('grid grid-cols-subgrid col-span-2', classNames)}\n ref={forwardedRef}\n >\n <div role='none' className={'flex flex-col items-center gap-2 ' + messageCell}>\n <Avatar.Frame>\n <Avatar.Fallback href={jdenticon} />\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={messageCell}>\n {children}\n </div>\n </div>\n </Avatar.Root>\n );\n },\n);\n\nexport type MessageBlockProps<BlockValue> = {\n block: MessageEntityBlock<BlockValue>;\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 { t, dtLocale } = useTranslation(translationKey);\n\n const { authorName, onDelete, blocks, id, MessageBlockComponent = DefaultMessageBlock, ...metaProps } = props;\n\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 key={i} block={block} onBlockDelete={onDelete && (() => onDelete(id, i))} />\n ))}\n </div>\n </MessageMeta>\n );\n};\n\nexport type MessageTextboxProps = {\n onSend?: () => void;\n onClear?: () => void;\n onEditorFocus?: () => void;\n disabled?: boolean;\n} & Omit<MessageMetadata, 'id' | 'authorStatus'> &\n TextEditorProps;\n\nexport const MessageTextbox = forwardRef<EditorView, MessageTextboxProps>(\n (\n { onSend, onClear, onEditorFocus, authorId, authorName, authorImgSrc, disabled, extensions = [], ...editorProps },\n forwardedRef,\n ) => {\n return (\n <MessageMeta\n {...{ id: editorProps.model.id, authorId, authorName, authorImgSrc }}\n authorStatus='active'\n continues={false}\n >\n <TextEditor\n slots={{ root: { className: mx('plb-0.5 mie-1 rounded-sm', focusRing, disabled && 'opacity-50') } }}\n readonly={disabled}\n extensions={[\n ...extensions,\n keymap.of([\n {\n key: 'Enter',\n run: () => {\n if (onSend) {\n onSend();\n return true;\n } else {\n return false;\n }\n },\n },\n {\n key: 'Meta+Backspace',\n run: () => {\n if (onClear) {\n onClear();\n return true;\n } else {\n return false;\n }\n },\n },\n ]),\n listener({\n onFocus: (focused) => {\n if (focused) {\n onEditorFocus?.();\n }\n },\n }),\n ]}\n {...editorProps}\n ref={forwardedRef}\n />\n </MessageMeta>\n );\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,wBAAwB;AACpD,OAAOC,SAA0DC,kBAAkB;AAEnF,SAA+BC,sBAAsB;AACrD,SAASC,sBAAsBC,gCAAgCC,UAAU;AAQlE,IAAMC,SAASC,2BACpB,CAAC,EAAEC,SAASC,UAAUC,YAAY,GAAGC,MAAAA,GAASC,iBAAAA;AAC5C,SACE,sBAAA,cAACC,OAAAA;IACCC,MAAK;IACJ,GAAIN,WAAW;MAAE,gBAAgB,OAAOA,YAAY,WAAWA,UAAU;IAAW;IACpF,GAAGG;IACJI,WAAWC,GACT,qNACAC,gCACAP,UAAAA;IAEFQ,KAAKN;KAEJH,QAAAA;AAGP,CAAA;AAKK,IAAMU,gBAAgBZ,2BAC3B,CAAC,EAAEG,YAAYD,UAAU,GAAGE,MAAAA,GAASC,iBAAAA;AACnC,SACE,sBAAA,cAACC,OAAAA;IACCC,MAAK;IACJ,GAAGH;IACJI,WAAWC,GAAG,gEAAgEN,UAAAA;IAC9EQ,KAAKN;KAEL,sBAAA,cAACC,OAAAA;IAAIC,MAAK;IAAOC,WAAU;KACzB,sBAAA,cAACK,mBAAAA,IAAAA,CAAAA,GAEH,sBAAA,cAACC,KAAAA,MAAGZ,QAAAA,CAAAA;AAGV,CAAA;AAOK,IAAMa,eAAef,2BAC1B,CAAC,EAAEgB,UAAUb,YAAYD,UAAU,GAAGE,MAAAA,GAASC,iBAAAA;AAC7C,QAAM,EAAEY,EAAC,IAAKC,eAAeC,cAAAA;AAC7B,SACE,sBAAA,cAACb,OAAAA;IACE,GAAGF;IACJI,WAAWC,GAAG,mFAAmFN,UAAAA;IACjGQ,KAAKN;KAEL,sBAAA,cAACe,kBAAAA;IACCC,QAAO;IACPC,gBAAcN,WAAW,SAAS;IAClCR,WAAU;MAEZ,sBAAA,cAACe,QAAAA;IAAKf,WAAU;IAAoBgB,aAAU;KAC3CR,WAAWd,WAAW,IAAA,GAEzB,sBAAA,cAACqB,QAAAA;IAAKf,WAAWC,GAAG,kBAAkBgB,oBAAAA;KAAwBR,EAAE,uBAAA,CAAA,CAAA;AAGtE,CAAA;;;AC5EF,SAASS,SAAS;AAClB,SAASC,2BAA2B;AACpC,OAAOC,UAA8CC,cAAAA,mBAAkB;AAEvE,SAASC,QAAQC,QAA8BC,kBAAkBC,kBAAAA,uBAAsB;AACvF,SAASC,YAAkCC,QAAyBC,gBAAgB;AACpF,SACEC,WACAC,wBAAAA,uBACAC,mBACAC,kCAAAA,iCACAC,MAAAA,WACK;AACP,SAASC,qBAAqB;
|
|
6
|
-
"names": ["translationKey", "ArrowBendLeftDown", "DotsThreeOutline", "React", "forwardRef", "useTranslation", "hoverableControlItem", "hoverableFocusedWithinControls", "mx", "Thread", "forwardRef", "current", "children", "classNames", "props", "forwardedRef", "div", "role", "className", "mx", "hoverableFocusedWithinControls", "ref", "ThreadHeading", "ArrowBendLeftDown", "p", "ThreadFooter", "activity", "t", "useTranslation", "translationKey", "DotsThreeOutline", "weight", "data-visible", "span", "aria-live", "hoverableControlItem", "X", "formatDistanceToNow", "React", "forwardRef", "Avatar", "Button", "useJdenticonHref", "useTranslation", "TextEditor", "keymap", "listener", "focusRing", "hoverableControlItem", "hoverableControls", "hoverableFocusedWithinControls", "mx", "safeParseJson", "avatarSize", "messageCell", "MessageMeta", "forwardRef", "authorImgSrc", "authorStatus", "authorId", "authorName", "continues", "children", "classNames", "rootProps", "forwardedRef", "jdenticon", "useJdenticonHref", "React", "Avatar", "Root", "status", "size", "div", "role", "className", "mx", "ref", "Frame", "Fallback", "href", "Image", "DefaultMessageBlock", "block", "onBlockDelete", "contentWidth", "hoverableControls", "hoverableFocusedWithinControls", "data", "pre", "code", "JSON", "stringify", "safeParseJson", "undefined", "p", "text", "Button", "variant", "hoverableControlItem", "onClick", "X", "Message", "props", "t", "dtLocale", "useTranslation", "translationKey", "onDelete", "blocks", "id", "MessageBlockComponent", "metaProps", "firstBlock", "dt", "timestamp", "Date", "Label", "time", "dateTime", "toISOString", "formatDistanceToNow", "locale", "addSuffix", "map", "i", "key", "MessageTextbox", "onSend", "onClear", "onEditorFocus", "disabled", "
|
|
3
|
+
"sources": ["../../../src/translations.ts", "../../../src/Thread/Thread.tsx", "../../../src/Message/Message.tsx", "../../../src/Message/command-extension.ts"],
|
|
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, DotsThreeOutline } 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 Thread = forwardRef<HTMLDivElement, ThreadProps>(\n ({ current, children, classNames, ...props }, forwardedRef) => {\n return (\n <div\n role='group'\n {...(current && { 'aria-current': typeof current === 'string' ? current : 'location' })}\n {...props}\n className={mx(\n 'is-full place-self-start grid grid-cols-[3rem_1fr] 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 hoverableFocusedWithinControls,\n classNames,\n )}\n ref={forwardedRef}\n >\n {children}\n </div>\n );\n },\n);\n\nexport type ThreadHeadingProps = ThemedClassName<ComponentPropsWithRef<'div'>>;\n\nexport const ThreadHeading = forwardRef<HTMLDivElement, ThreadHeadingProps>(\n ({ classNames, children, ...props }, forwardedRef) => {\n return (\n <div\n role='heading'\n {...props}\n className={mx('col-span-2 grid grid-cols-subgrid fg-description font-medium', classNames)}\n ref={forwardedRef}\n >\n <div role='none' className='grid place-items-end pie-3.5 fg-separator'>\n <ArrowBendLeftDown />\n </div>\n <p>{children}</p>\n </div>\n );\n },\n);\n\nexport type ThreadFooterProps = ThemedClassName<ComponentPropsWithRef<'div'>> & {\n activity?: boolean;\n};\n\nexport const ThreadFooter = forwardRef<HTMLDivElement, ThreadFooterProps>(\n ({ activity, classNames, children, ...props }, forwardedRef) => {\n const { t } = useTranslation(translationKey);\n return (\n <div\n {...props}\n className={mx('col-start-2 grid grid-cols-[min-content_1fr_max-content] text-xs fg-description', classNames)}\n ref={forwardedRef}\n >\n <DotsThreeOutline\n weight='fill'\n data-visible={activity ? 'show' : 'hide'}\n className='is-6 bs-4 invisible data-[visible=show]:visible'\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 } from 'react';\n\nimport { Avatar, Button, type ThemedClassName, useJdenticonHref, useTranslation } from '@dxos/react-ui';\nimport { TextEditor, type TextEditorProps, keymap, type EditorView, listener } from '@dxos/react-ui-editor';\nimport {\n focusRing,\n hoverableControlItem,\n hoverableControls,\n hoverableFocusedWithinControls,\n mx,\n} from '@dxos/react-ui-theme';\nimport { safeParseJson } from '@dxos/util';\n\nimport { command } from './command-extension';\nimport { translationKey } from '../translations';\nimport { type MessageEntity, type MessageEntityBlock, type MessageMetadata } from '../types';\n\nconst avatarSize = 7;\n\nconst messageCell = 'plb-1 min-is-0';\n\nexport type MessageMetaProps = ThemedClassName<ComponentPropsWithRef<'div'>> &\n MessageMetadata &\n Partial<{ continues: boolean }>;\n\nexport const MessageMeta = forwardRef<HTMLDivElement, MessageMetaProps>(\n (\n { authorImgSrc, authorStatus, authorId, authorName, continues = true, children, classNames, ...rootProps },\n forwardedRef,\n ) => {\n const jdenticon = useJdenticonHref(authorId ?? '', avatarSize);\n\n return (\n <Avatar.Root status={authorStatus ?? 'inactive'} size={avatarSize}>\n <div\n role='none'\n {...rootProps}\n className={mx('grid grid-cols-subgrid col-span-2', classNames)}\n ref={forwardedRef}\n >\n <div role='none' className={'flex flex-col items-center gap-2 ' + messageCell}>\n <Avatar.Frame>\n <Avatar.Fallback href={jdenticon} />\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={messageCell}>\n {children}\n </div>\n </div>\n </Avatar.Root>\n );\n },\n);\n\nexport type MessageBlockProps<BlockValue> = {\n block: MessageEntityBlock<BlockValue>;\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 min-bs-0 mie-1 place-self-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 { t, dtLocale } = useTranslation(translationKey);\n\n const { authorName, onDelete, blocks, id, MessageBlockComponent = DefaultMessageBlock, ...metaProps } = props;\n\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 font-semibold', !authorName && 'fg-description']}>\n {authorName ?? t('anonymous label')}\n </Avatar.Label>\n <time className='fg-description text-xs pbs-1' 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 key={i} block={block} onBlockDelete={onDelete && (() => onDelete(id, i))} />\n ))}\n </div>\n </MessageMeta>\n );\n};\n\nexport type MessageTextboxProps = {\n onSend?: () => void;\n onClear?: () => void;\n onEditorFocus?: () => void;\n disabled?: boolean;\n} & Omit<MessageMetadata, 'id' | 'authorStatus'> &\n TextEditorProps;\n\nexport const MessageTextbox = forwardRef<EditorView, MessageTextboxProps>(\n ({ onSend, onClear, onEditorFocus, authorId, authorName, authorImgSrc, disabled, ...editorProps }, forwardedRef) => {\n return (\n <MessageMeta\n {...{ id: editorProps.model.id, authorId, authorName, authorImgSrc }}\n authorStatus='active'\n continues={false}\n >\n <TextEditor\n slots={{ root: { className: mx('plb-1 mie-1 rounded-sm', focusRing, disabled && 'opacity-50') } }}\n readonly={disabled}\n extensions={[\n command,\n keymap.of([\n {\n key: 'Enter',\n run: () => {\n if (onSend) {\n onSend();\n return true;\n } else {\n return false;\n }\n },\n },\n {\n key: 'Meta+Backspace',\n run: () => {\n if (onClear) {\n onClear();\n return true;\n } else {\n return false;\n }\n },\n },\n ]),\n listener({\n onFocus: (focused) => {\n if (focused) {\n onEditorFocus?.();\n }\n },\n }),\n ]}\n {...editorProps}\n ref={forwardedRef}\n />\n </MessageMeta>\n );\n },\n);\n", "//\n// Copyright 2024 DXOS.org\n//\n\nimport { StreamLanguage, HighlightStyle, syntaxHighlighting } from '@codemirror/language';\nimport { type Extension } from '@codemirror/state';\n\nimport { tags } from '@dxos/react-ui-editor';\nimport { tagRoot } from '@dxos/react-ui-theme';\n\n/**\n * https://github.com/codemirror/stream-parser/blob/main/test/test-stream-parser.ts\n */\nconst parser = StreamLanguage.define<{ count: number }>({\n startState: () => ({ count: 0 }),\n token: (stream, state) => {\n state.count++;\n if (stream.eatSpace()) {\n return null;\n }\n if (state.count === 1 && stream.match(/^(\\/\\w+)/)) {\n return 'tagName';\n }\n stream.next();\n return null;\n },\n});\n\n/**\n * https://codemirror.net/examples/styling\n * https://lezer.codemirror.net/docs/ref/#highlight\n */\nconst styles = HighlightStyle.define([\n {\n tag: tags.tagName,\n class: tagRoot({}),\n },\n]);\n\nexport const command: Extension = [parser, syntaxHighlighting(styles)];\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["translationKey", "ArrowBendLeftDown", "DotsThreeOutline", "React", "forwardRef", "useTranslation", "hoverableControlItem", "hoverableFocusedWithinControls", "mx", "Thread", "forwardRef", "current", "children", "classNames", "props", "forwardedRef", "div", "role", "className", "mx", "hoverableFocusedWithinControls", "ref", "ThreadHeading", "ArrowBendLeftDown", "p", "ThreadFooter", "activity", "t", "useTranslation", "translationKey", "DotsThreeOutline", "weight", "data-visible", "span", "aria-live", "hoverableControlItem", "X", "formatDistanceToNow", "React", "forwardRef", "Avatar", "Button", "useJdenticonHref", "useTranslation", "TextEditor", "keymap", "listener", "focusRing", "hoverableControlItem", "hoverableControls", "hoverableFocusedWithinControls", "mx", "safeParseJson", "StreamLanguage", "HighlightStyle", "syntaxHighlighting", "tags", "tagRoot", "parser", "StreamLanguage", "define", "startState", "count", "token", "stream", "state", "eatSpace", "match", "next", "styles", "HighlightStyle", "tag", "tags", "tagName", "class", "tagRoot", "command", "syntaxHighlighting", "avatarSize", "messageCell", "MessageMeta", "forwardRef", "authorImgSrc", "authorStatus", "authorId", "authorName", "continues", "children", "classNames", "rootProps", "forwardedRef", "jdenticon", "useJdenticonHref", "React", "Avatar", "Root", "status", "size", "div", "role", "className", "mx", "ref", "Frame", "Fallback", "href", "Image", "DefaultMessageBlock", "block", "onBlockDelete", "contentWidth", "hoverableControls", "hoverableFocusedWithinControls", "data", "pre", "code", "JSON", "stringify", "safeParseJson", "undefined", "p", "text", "Button", "variant", "hoverableControlItem", "onClick", "X", "Message", "props", "t", "dtLocale", "useTranslation", "translationKey", "onDelete", "blocks", "id", "MessageBlockComponent", "metaProps", "firstBlock", "dt", "timestamp", "Date", "Label", "time", "dateTime", "toISOString", "formatDistanceToNow", "locale", "addSuffix", "map", "i", "key", "MessageTextbox", "onSend", "onClear", "onEditorFocus", "disabled", "editorProps", "model", "TextEditor", "slots", "root", "focusRing", "readonly", "extensions", "command", "keymap", "of", "run", "listener", "onFocus", "focused"]
|
|
7
7
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"inputs":{"packages/ui/react-ui-thread/src/translations.ts":{"bytes":2281,"imports":[],"format":"esm"},"packages/ui/react-ui-thread/src/Thread/Thread.tsx":{"bytes":8591,"imports":[{"path":"@phosphor-icons/react","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"@dxos/react-ui","kind":"import-statement","external":true},{"path":"@dxos/react-ui-theme","kind":"import-statement","external":true},{"path":"packages/ui/react-ui-thread/src/translations.ts","kind":"import-statement","original":"../translations"}],"format":"esm"},"packages/ui/react-ui-thread/src/Thread/index.ts":{"bytes":472,"imports":[{"path":"packages/ui/react-ui-thread/src/Thread/Thread.tsx","kind":"import-statement","original":"./Thread"}],"format":"esm"},"packages/ui/react-ui-thread/src/Message/Message.tsx":{"bytes":
|
|
1
|
+
{"inputs":{"packages/ui/react-ui-thread/src/translations.ts":{"bytes":2281,"imports":[],"format":"esm"},"packages/ui/react-ui-thread/src/Thread/Thread.tsx":{"bytes":8591,"imports":[{"path":"@phosphor-icons/react","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"@dxos/react-ui","kind":"import-statement","external":true},{"path":"@dxos/react-ui-theme","kind":"import-statement","external":true},{"path":"packages/ui/react-ui-thread/src/translations.ts","kind":"import-statement","original":"../translations"}],"format":"esm"},"packages/ui/react-ui-thread/src/Thread/index.ts":{"bytes":472,"imports":[{"path":"packages/ui/react-ui-thread/src/Thread/Thread.tsx","kind":"import-statement","original":"./Thread"}],"format":"esm"},"packages/ui/react-ui-thread/src/Message/command-extension.ts":{"bytes":3654,"imports":[{"path":"@codemirror/language","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}],"format":"esm"},"packages/ui/react-ui-thread/src/Message/Message.tsx":{"bytes":19784,"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/Message/command-extension.ts","kind":"import-statement","original":"./command-extension"},{"path":"packages/ui/react-ui-thread/src/translations.ts","kind":"import-statement","original":"../translations"}],"format":"esm"},"packages/ui/react-ui-thread/src/Message/index.ts":{"bytes":474,"imports":[{"path":"packages/ui/react-ui-thread/src/Message/Message.tsx","kind":"import-statement","original":"./Message"}],"format":"esm"},"packages/ui/react-ui-thread/src/types.ts":{"bytes":1067,"imports":[],"format":"esm"},"packages/ui/react-ui-thread/src/index.ts":{"bytes":877,"imports":[{"path":"packages/ui/react-ui-thread/src/translations.ts","kind":"import-statement","original":"./translations"},{"path":"packages/ui/react-ui-thread/src/Thread/index.ts","kind":"import-statement","original":"./Thread"},{"path":"packages/ui/react-ui-thread/src/Message/index.ts","kind":"import-statement","original":"./Message"},{"path":"packages/ui/react-ui-thread/src/types.ts","kind":"import-statement","original":"./types"}],"format":"esm"}},"outputs":{"packages/ui/react-ui-thread/dist/lib/browser/index.mjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":18149},"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},{"path":"@codemirror/language","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}],"exports":["Message","MessageMeta","MessageTextbox","Thread","ThreadFooter","ThreadHeading","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":2292},"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":5260},"packages/ui/react-ui-thread/src/Message/command-extension.ts":{"bytesInOutput":651},"packages/ui/react-ui-thread/src/Message/index.ts":{"bytesInOutput":0}},"bytes":9267}}}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Message.d.ts","sourceRoot":"","sources":["../../../../src/Message/Message.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,EAAE,KAAK,qBAAqB,EAAE,KAAK,EAAE,EAAc,MAAM,OAAO,CAAC;AAE/E,OAAO,EAAkB,KAAK,eAAe,EAAoC,MAAM,gBAAgB,CAAC;AACxG,OAAO,EAAc,KAAK,eAAe,EAAU,KAAK,UAAU,EAAY,MAAM,uBAAuB,CAAC;
|
|
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,EAAc,MAAM,OAAO,CAAC;AAE/E,OAAO,EAAkB,KAAK,eAAe,EAAoC,MAAM,gBAAgB,CAAC;AACxG,OAAO,EAAc,KAAK,eAAe,EAAU,KAAK,UAAU,EAAY,MAAM,uBAAuB,CAAC;AAY5G,OAAO,EAAE,KAAK,aAAa,EAAE,KAAK,kBAAkB,EAAE,KAAK,eAAe,EAAE,MAAM,UAAU,CAAC;AAM7F,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,qnJA6BvB,CAAC;AAEF,MAAM,MAAM,iBAAiB,CAAC,UAAU,IAAI;IAC1C,KAAK,EAAE,kBAAkB,CAAC,UAAU,CAAC,CAAC;IACtC,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,8DAyBnB,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAChC,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,IAAI,CAAC;IAC3B,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,GAAG,IAAI,CAAC,eAAe,EAAE,IAAI,GAAG,cAAc,CAAC,GAC9C,eAAe,CAAC;AAElB,eAAO,MAAM,cAAc;oBAPV,IAAI;qBACH,IAAI;2BACE,IAAI;;qGAwD3B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"command-extension.d.ts","sourceRoot":"","sources":["../../../../src/Message/command-extension.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAkCnD,eAAO,MAAM,OAAO,EAAE,SAAgD,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dxos/react-ui-thread",
|
|
3
|
-
"version": "0.3.11-main.
|
|
3
|
+
"version": "0.3.11-main.8452415",
|
|
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",
|
|
@@ -16,13 +16,15 @@
|
|
|
16
16
|
"src"
|
|
17
17
|
],
|
|
18
18
|
"dependencies": {
|
|
19
|
+
"@codemirror/language": "^6.10.0",
|
|
20
|
+
"@codemirror/state": "^6.4.0",
|
|
19
21
|
"@radix-ui/react-primitive": "^1.0.2",
|
|
20
22
|
"date-fns": "^3.3.1",
|
|
21
|
-
"@dxos/react-ui": "0.3.11-main.
|
|
22
|
-
"@dxos/react-ui-
|
|
23
|
-
"@dxos/react-ui-theme": "0.3.11-main.
|
|
24
|
-
"@dxos/util": "0.3.11-main.
|
|
25
|
-
"@dxos/react-ui-
|
|
23
|
+
"@dxos/react-ui": "0.3.11-main.8452415",
|
|
24
|
+
"@dxos/react-ui-mosaic": "0.3.11-main.8452415",
|
|
25
|
+
"@dxos/react-ui-theme": "0.3.11-main.8452415",
|
|
26
|
+
"@dxos/util": "0.3.11-main.8452415",
|
|
27
|
+
"@dxos/react-ui-editor": "0.3.11-main.8452415"
|
|
26
28
|
},
|
|
27
29
|
"devDependencies": {
|
|
28
30
|
"@faker-js/faker": "^8.3.1",
|
|
@@ -33,10 +35,10 @@
|
|
|
33
35
|
"react-dom": "^18.2.0",
|
|
34
36
|
"vite": "^5.0.12",
|
|
35
37
|
"vite-plugin-turbosnap": "^1.0.2",
|
|
36
|
-
"@dxos/echo-schema": "0.3.11-main.
|
|
37
|
-
"@dxos/keys": "0.3.11-main.
|
|
38
|
-
"@dxos/log": "0.3.11-main.
|
|
39
|
-
"@dxos/storybook-utils": "0.3.11-main.
|
|
38
|
+
"@dxos/echo-schema": "0.3.11-main.8452415",
|
|
39
|
+
"@dxos/keys": "0.3.11-main.8452415",
|
|
40
|
+
"@dxos/log": "0.3.11-main.8452415",
|
|
41
|
+
"@dxos/storybook-utils": "0.3.11-main.8452415"
|
|
40
42
|
},
|
|
41
43
|
"peerDependencies": {
|
|
42
44
|
"@phosphor-icons/react": "^2.0.5",
|
package/src/Message/Message.tsx
CHANGED
|
@@ -17,6 +17,7 @@ import {
|
|
|
17
17
|
} from '@dxos/react-ui-theme';
|
|
18
18
|
import { safeParseJson } from '@dxos/util';
|
|
19
19
|
|
|
20
|
+
import { command } from './command-extension';
|
|
20
21
|
import { translationKey } from '../translations';
|
|
21
22
|
import { type MessageEntity, type MessageEntityBlock, type MessageMetadata } from '../types';
|
|
22
23
|
|
|
@@ -81,7 +82,7 @@ const DefaultMessageBlock = ({ block, onBlockDelete }: MessageBlockProps<{ data?
|
|
|
81
82
|
{onBlockDelete && (
|
|
82
83
|
<Button
|
|
83
84
|
variant='ghost'
|
|
84
|
-
classNames={['p-1
|
|
85
|
+
classNames={['p-1 min-bs-0 mie-1 place-self-start transition-opacity', hoverableControlItem]}
|
|
85
86
|
onClick={onBlockDelete}
|
|
86
87
|
>
|
|
87
88
|
<X />
|
|
@@ -107,10 +108,10 @@ export const Message = <BlockValue,>(props: MessageProps<BlockValue>) => {
|
|
|
107
108
|
return (
|
|
108
109
|
<MessageMeta {...metaProps} id={id} continues>
|
|
109
110
|
<p className='grid grid-cols-[1fr_max-content] gap-2 pie-2'>
|
|
110
|
-
<Avatar.Label classNames={['truncate
|
|
111
|
+
<Avatar.Label classNames={['truncate font-semibold', !authorName && 'fg-description']}>
|
|
111
112
|
{authorName ?? t('anonymous label')}
|
|
112
113
|
</Avatar.Label>
|
|
113
|
-
<time className='fg-description text-xs pbs-
|
|
114
|
+
<time className='fg-description text-xs pbs-1' dateTime={dt?.toISOString()}>
|
|
114
115
|
{dt ? formatDistanceToNow(dt, { locale: dtLocale, addSuffix: true }) : ''}
|
|
115
116
|
</time>
|
|
116
117
|
</p>
|
|
@@ -132,10 +133,7 @@ export type MessageTextboxProps = {
|
|
|
132
133
|
TextEditorProps;
|
|
133
134
|
|
|
134
135
|
export const MessageTextbox = forwardRef<EditorView, MessageTextboxProps>(
|
|
135
|
-
(
|
|
136
|
-
{ onSend, onClear, onEditorFocus, authorId, authorName, authorImgSrc, disabled, extensions = [], ...editorProps },
|
|
137
|
-
forwardedRef,
|
|
138
|
-
) => {
|
|
136
|
+
({ onSend, onClear, onEditorFocus, authorId, authorName, authorImgSrc, disabled, ...editorProps }, forwardedRef) => {
|
|
139
137
|
return (
|
|
140
138
|
<MessageMeta
|
|
141
139
|
{...{ id: editorProps.model.id, authorId, authorName, authorImgSrc }}
|
|
@@ -143,10 +141,10 @@ export const MessageTextbox = forwardRef<EditorView, MessageTextboxProps>(
|
|
|
143
141
|
continues={false}
|
|
144
142
|
>
|
|
145
143
|
<TextEditor
|
|
146
|
-
slots={{ root: { className: mx('plb-
|
|
144
|
+
slots={{ root: { className: mx('plb-1 mie-1 rounded-sm', focusRing, disabled && 'opacity-50') } }}
|
|
147
145
|
readonly={disabled}
|
|
148
146
|
extensions={[
|
|
149
|
-
|
|
147
|
+
command,
|
|
150
148
|
keymap.of([
|
|
151
149
|
{
|
|
152
150
|
key: 'Enter',
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2024 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { StreamLanguage, HighlightStyle, syntaxHighlighting } from '@codemirror/language';
|
|
6
|
+
import { type Extension } from '@codemirror/state';
|
|
7
|
+
|
|
8
|
+
import { tags } from '@dxos/react-ui-editor';
|
|
9
|
+
import { tagRoot } from '@dxos/react-ui-theme';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* https://github.com/codemirror/stream-parser/blob/main/test/test-stream-parser.ts
|
|
13
|
+
*/
|
|
14
|
+
const parser = StreamLanguage.define<{ count: number }>({
|
|
15
|
+
startState: () => ({ count: 0 }),
|
|
16
|
+
token: (stream, state) => {
|
|
17
|
+
state.count++;
|
|
18
|
+
if (stream.eatSpace()) {
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
if (state.count === 1 && stream.match(/^(\/\w+)/)) {
|
|
22
|
+
return 'tagName';
|
|
23
|
+
}
|
|
24
|
+
stream.next();
|
|
25
|
+
return null;
|
|
26
|
+
},
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* https://codemirror.net/examples/styling
|
|
31
|
+
* https://lezer.codemirror.net/docs/ref/#highlight
|
|
32
|
+
*/
|
|
33
|
+
const styles = HighlightStyle.define([
|
|
34
|
+
{
|
|
35
|
+
tag: tags.tagName,
|
|
36
|
+
class: tagRoot({}),
|
|
37
|
+
},
|
|
38
|
+
]);
|
|
39
|
+
|
|
40
|
+
export const command: Extension = [parser, syntaxHighlighting(styles)];
|