@dxos/react-ui-thread 0.8.4-main.f9ba587 → 0.8.4-main.fcfe5033a5

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.
Files changed (34) hide show
  1. package/dist/lib/browser/index.mjs +142 -187
  2. package/dist/lib/browser/index.mjs.map +3 -3
  3. package/dist/lib/browser/meta.json +1 -1
  4. package/dist/types/src/Message/Message.d.ts +2 -2
  5. package/dist/types/src/Message/Message.d.ts.map +1 -1
  6. package/dist/types/src/Message/Message.stories.d.ts +18 -16
  7. package/dist/types/src/Message/Message.stories.d.ts.map +1 -1
  8. package/dist/types/src/Thread/Comments.stories.d.ts +19 -36
  9. package/dist/types/src/Thread/Comments.stories.d.ts.map +1 -1
  10. package/dist/types/src/Thread/Thread.d.ts +25 -11
  11. package/dist/types/src/Thread/Thread.d.ts.map +1 -1
  12. package/dist/types/src/Thread/Thread.stories.d.ts +33 -5
  13. package/dist/types/src/Thread/Thread.stories.d.ts.map +1 -1
  14. package/dist/types/src/index.d.ts +1 -1
  15. package/dist/types/src/index.d.ts.map +1 -1
  16. package/dist/types/src/testing.d.ts.map +1 -1
  17. package/dist/types/src/translations.d.ts +12 -12
  18. package/dist/types/src/translations.d.ts.map +1 -1
  19. package/dist/types/src/types.d.ts +1 -0
  20. package/dist/types/src/types.d.ts.map +1 -1
  21. package/dist/types/tsconfig.tsbuildinfo +1 -1
  22. package/package.json +28 -26
  23. package/src/Message/Message.stories.tsx +19 -13
  24. package/src/Message/Message.tsx +17 -16
  25. package/src/Thread/Comments.stories.tsx +81 -50
  26. package/src/Thread/Thread.stories.tsx +20 -16
  27. package/src/Thread/Thread.tsx +23 -23
  28. package/src/index.ts +1 -1
  29. package/src/testing.tsx +9 -9
  30. package/src/translations.ts +11 -11
  31. package/src/types.ts +1 -0
  32. package/dist/lib/node-esm/index.mjs +0 -268
  33. package/dist/lib/node-esm/index.mjs.map +0 -7
  34. package/dist/lib/node-esm/meta.json +0 -1
@@ -2,23 +2,26 @@
2
2
  // Copyright 2023 DXOS.org
3
3
  //
4
4
 
5
- import { CaretDoubleRight, Spinner } from '@phosphor-icons/react';
6
- import React, { type ComponentPropsWithRef, forwardRef } from 'react';
5
+ import React, { ComponentPropsWithRef, forwardRef, PropsWithChildren } from 'react';
7
6
 
8
- import { type ThemedClassName, useTranslation } from '@dxos/react-ui';
9
- import { hoverableControlItem, hoverableFocusedWithinControls, mx } from '@dxos/react-ui-theme';
7
+ import { Icon, type ThemedClassName, useTranslation } from '@dxos/react-ui';
8
+ import { hoverableControlItem, hoverableFocusedWithinControls, mx } from '@dxos/ui-theme';
10
9
 
11
10
  import { translationKey } from '../translations';
12
11
  import type { ThreadEntity } from '../types';
13
12
 
14
- // TODO(burdon): Why is this exported?
15
- export const threadLayout = 'is-full place-self-start grid grid-cols-[var(--rail-size)_1fr]';
13
+ // TODO(burdon): Avoid exporting fragments.
14
+ export const threadLayout = 'w-full place-self-start grid grid-cols-[var(--dx-rail-size)_1fr]';
16
15
 
17
16
  //
18
17
  // Root
19
18
  //
20
19
 
21
- type ThreadRootProps = ThemedClassName<ComponentPropsWithRef<'div'>> & ThreadEntity & { current?: boolean };
20
+ type ThreadRootProps = ThemedClassName<
21
+ PropsWithChildren<
22
+ ThreadEntity & { current?: boolean } & Pick<ComponentPropsWithRef<'div'>, 'onClickCapture' | 'onFocusCapture'>
23
+ >
24
+ >;
22
25
 
23
26
  const ThreadRoot = forwardRef<HTMLDivElement, ThreadRootProps>(
24
27
  ({ current, children, classNames, ...props }, forwardedRef) => {
@@ -31,7 +34,7 @@ const ThreadRoot = forwardRef<HTMLDivElement, ThreadRootProps>(
31
34
  className={mx(
32
35
  threadLayout,
33
36
  hoverableFocusedWithinControls,
34
- 'bg-[var(--surface-bg)] current-related attention-surface [--controls-opacity:0]',
37
+ 'bg-[var(--surface-bg)] current-related dx-attention-surface [--controls-opacity:0]',
35
38
  classNames,
36
39
  )}
37
40
  ref={forwardedRef}
@@ -46,24 +49,21 @@ const ThreadRoot = forwardRef<HTMLDivElement, ThreadRootProps>(
46
49
  // Heading
47
50
  //
48
51
 
49
- type ThreadHeaderProps = ThemedClassName<ComponentPropsWithRef<'div'>> & { detached?: boolean };
52
+ type ThreadHeaderProps = PropsWithChildren<{ detached?: boolean }>;
50
53
 
51
54
  const ThreadHeader = forwardRef<HTMLParagraphElement, ThreadHeaderProps>(
52
- ({ classNames, children, detached, ...props }, forwardedRef) => {
55
+ ({ children, detached, ...props }, forwardedRef) => {
53
56
  return (
54
57
  <>
55
58
  <div role='none' className='flex items-center justify-center text-description'>
56
- <CaretDoubleRight />
59
+ <Icon icon='ph--caret-double-right--regular' />
57
60
  </div>
58
61
  <div role='none' className='flex items-center overflow-hidden'>
59
62
  <p
60
63
  role='heading'
61
64
  data-testid='thread.heading'
62
65
  {...props}
63
- className={mx(
64
- 'mie-2 text-description font-medium truncate italic',
65
- detached && 'line-through decoration-1',
66
- )}
66
+ className={mx('me-2 text-description font-medium truncate italic', detached && 'line-through decoration-1')}
67
67
  ref={forwardedRef}
68
68
  >
69
69
  {children}
@@ -78,7 +78,7 @@ const ThreadHeader = forwardRef<HTMLParagraphElement, ThreadHeaderProps>(
78
78
  // Status
79
79
  //
80
80
 
81
- type ThreadStatusProps = ThemedClassName<ComponentPropsWithRef<'div'>> & {
81
+ type ThreadStatusProps = ThemedClassName<PropsWithChildren> & {
82
82
  activity?: boolean;
83
83
  };
84
84
 
@@ -89,20 +89,20 @@ const ThreadStatus = forwardRef<HTMLDivElement, ThreadStatusProps>(
89
89
  <div
90
90
  {...props}
91
91
  className={mx(
92
- 'col-start-2 grid grid-cols-[min-content_1fr_max-content] pb-2 pie-2 text-xs text-description',
92
+ 'col-start-2 grid grid-cols-[min-content_1fr_max-content] pb-2 pe-2 text-xs text-description',
93
93
  classNames,
94
94
  )}
95
95
  ref={forwardedRef}
96
96
  >
97
- <Spinner
98
- weight='bold'
97
+ <Icon
98
+ icon='ph--spinner--bold'
99
+ classNames='w-6 h-4 invisible data-[visible=show]:visible animate-spin-slow'
99
100
  data-visible={activity ? 'show' : 'hide'}
100
- className='is-6 bs-4 invisible data-[visible=show]:visible animate-spin-slow'
101
101
  />
102
- <span className='truncate min-is-0' aria-live='polite'>
102
+ <span className='truncate min-w-0' aria-live='polite'>
103
103
  {activity ? children : null}
104
104
  </span>
105
- <span className={mx('text-end', hoverableControlItem)}>{t('enter to send message')}</span>
105
+ <span className={mx('text-end', hoverableControlItem)}>{t('enter-to-send.message')}</span>
106
106
  </div>
107
107
  );
108
108
  },
@@ -114,4 +114,4 @@ export const Thread = {
114
114
  Status: ThreadStatus,
115
115
  };
116
116
 
117
- export type { ThreadRootProps, ThreadHeaderProps as ThreadHeadingProps, ThreadStatusProps };
117
+ export type { ThreadRootProps, ThreadHeaderProps, ThreadStatusProps };
package/src/index.ts CHANGED
@@ -6,5 +6,5 @@ import { translations } from './translations';
6
6
 
7
7
  export * from './Thread';
8
8
  export * from './Message';
9
- export * from './types';
9
+ export type * from './types';
10
10
  export { translations };
package/src/testing.tsx CHANGED
@@ -2,11 +2,10 @@
2
2
  // Copyright 2024 DXOS.org
3
3
  //
4
4
 
5
- import { X } from '@phosphor-icons/react';
6
5
  import React from 'react';
7
6
 
8
- import { Button } from '@dxos/react-ui';
9
- import { hoverableControlItem, hoverableControls, hoverableFocusedWithinControls, mx } from '@dxos/react-ui-theme';
7
+ import { IconButton } from '@dxos/react-ui';
8
+ import { hoverableControlItem, hoverableControls, hoverableFocusedWithinControls, mx } from '@dxos/ui-theme';
10
9
 
11
10
  import { MessageBody, MessageHeading } from './Message';
12
11
  import { type MessageMetadata } from './types';
@@ -26,13 +25,14 @@ export const MessageStoryText = ({ text, onDelete, authorName, timestamp }: Mess
26
25
  <>
27
26
  <MessageHeading authorName={authorName} timestamp={timestamp}>
28
27
  {onDelete && (
29
- <Button
28
+ <IconButton
29
+ icon='ph--x--regular'
30
+ iconOnly
31
+ label='Delete'
30
32
  variant='ghost'
31
- classNames={['p-1.5 min-bs-0 mie-1 items-start transition-opacity', hoverableControlItem]}
33
+ classNames={['p-1.5 min-h-0 me-1 items-start transition-opacity', hoverableControlItem]}
32
34
  onClick={() => onDelete()}
33
- >
34
- <X />
35
- </Button>
35
+ />
36
36
  )}
37
37
  </MessageHeading>
38
38
  <MessageBody>{text}</MessageBody>
@@ -50,7 +50,7 @@ export const MessageStoryBlock = <PartValue,>({ part }: MessagePartProps<PartVal
50
50
  role='none'
51
51
  className={mx('grid grid-cols-subgrid col-span-3', hoverableControls, hoverableFocusedWithinControls)}
52
52
  >
53
- <pre className='font-mono max-is-full overflow-x-auto col-span-3'>
53
+ <pre className='font-mono max-w-full overflow-x-auto col-span-3'>
54
54
  <code>{JSON.stringify(part, undefined, 2)}</code>
55
55
  </pre>
56
56
  </div>
@@ -4,22 +4,22 @@
4
4
 
5
5
  import { type Resource } from '@dxos/react-ui';
6
6
 
7
- export const translationKey = 'react-ui-thread';
7
+ export const translationKey = '@dxos/react-ui-thread';
8
8
 
9
9
  export const translations = [
10
10
  {
11
11
  'en-US': {
12
12
  [translationKey]: {
13
- 'plugin name': 'Threads',
14
- 'thread title placeholder': 'New thread',
15
- 'thread title label': 'Title',
16
- 'delete thread label': 'Delete',
17
- 'create thread label': 'Create thread',
18
- 'message placeholder': 'Enter message...',
19
- 'comment placeholder': 'Enter comment...',
20
- 'settings standalone label': 'Enable standalone thread creation',
21
- 'anonymous label': 'Anonymous',
22
- 'enter to send message': 'Enter to add ⏎',
13
+ 'plugin.name': 'Threads',
14
+ 'thread-title.placeholder': 'New thread',
15
+ 'thread-title.label': 'Title',
16
+ 'delete-thread.label': 'Delete',
17
+ 'create-thread.label': 'Create thread',
18
+ 'message.placeholder': 'Enter message...',
19
+ 'comment.placeholder': 'Enter comment...',
20
+ 'settings-standalone.label': 'Enable standalone thread creation',
21
+ 'anonymous.label': 'Anonymous',
22
+ 'enter-to-send.message': 'Enter to add ⏎',
23
23
  },
24
24
  },
25
25
  },
package/src/types.ts CHANGED
@@ -16,6 +16,7 @@ export type MessageMetadata = {
16
16
  };
17
17
 
18
18
  export type ThreadEntity = {
19
+ id?: string;
19
20
  topicId?: string;
20
21
  topicTitle?: string;
21
22
  };
@@ -1,268 +0,0 @@
1
- import { createRequire } from 'node:module';const require = createRequire(import.meta.url);
2
-
3
- // src/translations.ts
4
- var translationKey = "react-ui-thread";
5
- var translations = [
6
- {
7
- "en-US": {
8
- [translationKey]: {
9
- "plugin name": "Threads",
10
- "thread title placeholder": "New thread",
11
- "thread title label": "Title",
12
- "delete thread label": "Delete",
13
- "create thread label": "Create thread",
14
- "message placeholder": "Enter message...",
15
- "comment placeholder": "Enter comment...",
16
- "settings standalone label": "Enable standalone thread creation",
17
- "anonymous label": "Anonymous",
18
- "enter to send message": "Enter to add \u23CE"
19
- }
20
- }
21
- }
22
- ];
23
-
24
- // src/Thread/Thread.tsx
25
- import { useSignals as _useSignals } from "@preact-signals/safe-react/tracking";
26
- import { CaretDoubleRight, Spinner } from "@phosphor-icons/react";
27
- import React, { forwardRef } from "react";
28
- import { useTranslation } from "@dxos/react-ui";
29
- import { hoverableControlItem, hoverableFocusedWithinControls, mx } from "@dxos/react-ui-theme";
30
- var threadLayout = "is-full place-self-start grid grid-cols-[var(--rail-size)_1fr]";
31
- var ThreadRoot = /* @__PURE__ */ forwardRef(({ current, children, classNames, ...props }, forwardedRef) => {
32
- var _effect = _useSignals();
33
- try {
34
- return /* @__PURE__ */ React.createElement("div", {
35
- role: "group",
36
- "data-testid": "thread",
37
- ...current && {
38
- "aria-current": typeof current === "string" ? current : "location"
39
- },
40
- ...props,
41
- className: mx(threadLayout, hoverableFocusedWithinControls, "bg-[var(--surface-bg)] current-related attention-surface [--controls-opacity:0]", classNames),
42
- ref: forwardedRef
43
- }, children);
44
- } finally {
45
- _effect.f();
46
- }
47
- });
48
- var ThreadHeader = /* @__PURE__ */ forwardRef(({ classNames, children, detached, ...props }, forwardedRef) => {
49
- var _effect = _useSignals();
50
- try {
51
- return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("div", {
52
- role: "none",
53
- className: "flex items-center justify-center text-description"
54
- }, /* @__PURE__ */ React.createElement(CaretDoubleRight, null)), /* @__PURE__ */ React.createElement("div", {
55
- role: "none",
56
- className: "flex items-center overflow-hidden"
57
- }, /* @__PURE__ */ React.createElement("p", {
58
- role: "heading",
59
- "data-testid": "thread.heading",
60
- ...props,
61
- className: mx("mie-2 text-description font-medium truncate italic", detached && "line-through decoration-1"),
62
- ref: forwardedRef
63
- }, children)));
64
- } finally {
65
- _effect.f();
66
- }
67
- });
68
- var ThreadStatus = /* @__PURE__ */ forwardRef(({ activity, classNames, children, ...props }, forwardedRef) => {
69
- var _effect = _useSignals();
70
- try {
71
- const { t } = useTranslation(translationKey);
72
- return /* @__PURE__ */ React.createElement("div", {
73
- ...props,
74
- className: mx("col-start-2 grid grid-cols-[min-content_1fr_max-content] pb-2 pie-2 text-xs text-description", classNames),
75
- ref: forwardedRef
76
- }, /* @__PURE__ */ React.createElement(Spinner, {
77
- weight: "bold",
78
- "data-visible": activity ? "show" : "hide",
79
- className: "is-6 bs-4 invisible data-[visible=show]:visible animate-spin-slow"
80
- }), /* @__PURE__ */ React.createElement("span", {
81
- className: "truncate min-is-0",
82
- "aria-live": "polite"
83
- }, activity ? children : null), /* @__PURE__ */ React.createElement("span", {
84
- className: mx("text-end", hoverableControlItem)
85
- }, t("enter to send message")));
86
- } finally {
87
- _effect.f();
88
- }
89
- });
90
- var Thread = {
91
- Root: ThreadRoot,
92
- Header: ThreadHeader,
93
- Status: ThreadStatus
94
- };
95
-
96
- // src/Message/Message.tsx
97
- import { useSignals as _useSignals2 } from "@preact-signals/safe-react/tracking";
98
- import { formatDistanceToNow } from "date-fns/formatDistanceToNow";
99
- import React2, { forwardRef as forwardRef2 } from "react";
100
- import { Avatar, useTranslation as useTranslation2 } from "@dxos/react-ui";
101
- import { keymap, listener, useTextEditor } from "@dxos/react-ui-editor";
102
- import { focusRing, mx as mx2 } from "@dxos/react-ui-theme";
103
- import { hexToEmoji, hexToHue, isNotFalsy } from "@dxos/util";
104
- var avatarSize = 7;
105
- var MessageRoot = /* @__PURE__ */ forwardRef2(({ authorImgSrc, authorId, authorName, authorAvatarProps, continues = true, children, classNames, ...rootProps }, forwardedRef) => {
106
- var _effect = _useSignals2();
107
- try {
108
- return (
109
- // Must wrap the message since Avatar.Label may be used in the content.
110
- /* @__PURE__ */ React2.createElement(Avatar.Root, null, /* @__PURE__ */ React2.createElement("div", {
111
- role: "none",
112
- "data-testid": "thread.message",
113
- ...rootProps,
114
- className: mx2("grid grid-cols-subgrid col-span-2", classNames),
115
- ref: forwardedRef
116
- }, /* @__PURE__ */ React2.createElement("div", {
117
- role: "none",
118
- className: "flex flex-col items-center gap-2 pbs-2"
119
- }, /* @__PURE__ */ React2.createElement(Avatar.Content, {
120
- size: avatarSize,
121
- hue: authorAvatarProps?.hue || hexToHue(authorId ?? "0"),
122
- fallback: authorAvatarProps?.emoji || hexToEmoji(authorId ?? "0"),
123
- ...authorImgSrc && {
124
- imgSrc: authorImgSrc
125
- }
126
- }), continues && /* @__PURE__ */ React2.createElement("div", {
127
- role: "none",
128
- className: "is-px grow bg-separator"
129
- })), /* @__PURE__ */ React2.createElement("div", {
130
- role: "none",
131
- className: "plb-1 min-is-0"
132
- }, children)))
133
- );
134
- } finally {
135
- _effect.f();
136
- }
137
- });
138
- var MessageHeading = ({ children, classNames, timestamp, authorName, ...props }) => {
139
- var _effect = _useSignals2();
140
- try {
141
- return /* @__PURE__ */ React2.createElement("div", {
142
- role: "none",
143
- ...props,
144
- className: mx2("flex gap-2 items-start", classNames)
145
- }, /* @__PURE__ */ React2.createElement("p", {
146
- className: "grow"
147
- }, /* @__PURE__ */ React2.createElement(MessageAuthorName, {
148
- authorName
149
- }), timestamp && /* @__PURE__ */ React2.createElement(MessageTime, {
150
- timestamp
151
- })), children);
152
- } finally {
153
- _effect.f();
154
- }
155
- };
156
- var MessageAuthorName = ({ authorName }) => {
157
- var _effect = _useSignals2();
158
- try {
159
- const { t } = useTranslation2(translationKey);
160
- return /* @__PURE__ */ React2.createElement(Avatar.Label, {
161
- classNames: "block truncate text-sm text-subdued"
162
- }, authorName ?? t("anonymous label"));
163
- } finally {
164
- _effect.f();
165
- }
166
- };
167
- var MessageTime = ({ timestamp }) => {
168
- var _effect = _useSignals2();
169
- try {
170
- const { dtLocale } = useTranslation2(translationKey);
171
- const dt = timestamp ? new Date(timestamp) : void 0;
172
- return /* @__PURE__ */ React2.createElement("time", {
173
- className: "block text-subdued text-xs pbe-0.5",
174
- dateTime: dt?.toISOString()
175
- }, dt ? formatDistanceToNow(dt, {
176
- locale: dtLocale,
177
- addSuffix: true
178
- }) : "");
179
- } finally {
180
- _effect.f();
181
- }
182
- };
183
- var MessageBody = ({ children, ...props }) => {
184
- var _effect = _useSignals2();
185
- try {
186
- return /* @__PURE__ */ React2.createElement("p", props, children);
187
- } finally {
188
- _effect.f();
189
- }
190
- };
191
- var keyBindings = ({ onSend, onClear }) => [
192
- {
193
- key: "Enter",
194
- run: () => {
195
- if (onSend) {
196
- onSend();
197
- return true;
198
- } else {
199
- return false;
200
- }
201
- }
202
- },
203
- {
204
- // TODO(burdon): Other key bindings.
205
- key: "Meta+Backspace",
206
- run: () => {
207
- if (onClear) {
208
- onClear();
209
- return true;
210
- } else {
211
- return false;
212
- }
213
- }
214
- }
215
- ];
216
- var MessageTextbox = ({ id, authorId, authorName, authorImgSrc, authorAvatarProps, disabled, extensions, onSend, onClear, onEditorFocus, ...editorProps }) => {
217
- var _effect = _useSignals2();
218
- try {
219
- const { parentRef, focusAttributes } = useTextEditor(() => ({
220
- id,
221
- extensions: [
222
- keymap.of(keyBindings({
223
- onSend,
224
- onClear
225
- })),
226
- listener({
227
- onFocus: (focusing) => {
228
- if (focusing) {
229
- onEditorFocus?.();
230
- }
231
- }
232
- }),
233
- extensions
234
- ].filter(isNotFalsy),
235
- ...editorProps
236
- }), [
237
- id,
238
- extensions
239
- ]);
240
- return /* @__PURE__ */ React2.createElement(MessageRoot, {
241
- id,
242
- authorId,
243
- authorName,
244
- authorImgSrc,
245
- authorAvatarProps,
246
- continues: false
247
- }, /* @__PURE__ */ React2.createElement("div", {
248
- role: "none",
249
- ref: parentRef,
250
- className: mx2("plb-0.5 mie-1 rounded-sm", focusRing, disabled && "opacity-50"),
251
- ...focusAttributes
252
- }));
253
- } finally {
254
- _effect.f();
255
- }
256
- };
257
- export {
258
- MessageAuthorName,
259
- MessageBody,
260
- MessageHeading,
261
- MessageRoot,
262
- MessageTextbox,
263
- MessageTime,
264
- Thread,
265
- threadLayout,
266
- translations
267
- };
268
- //# sourceMappingURL=index.mjs.map
@@ -1,7 +0,0 @@
1
- {
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\nimport { type Resource } from '@dxos/react-ui';\n\nexport const translationKey = 'react-ui-thread';\n\nexport const translations = [\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] as const satisfies Resource[];\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport { CaretDoubleRight, Spinner } from '@phosphor-icons/react';\nimport React, { 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\n// TODO(burdon): Why is this exported?\nexport const threadLayout = 'is-full place-self-start grid grid-cols-[var(--rail-size)_1fr]';\n\n//\n// Root\n//\n\ntype ThreadRootProps = ThemedClassName<ComponentPropsWithRef<'div'>> & ThreadEntity & { current?: boolean };\n\nconst ThreadRoot = forwardRef<HTMLDivElement, ThreadRootProps>(\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)] current-related attention-surface [--controls-opacity:0]',\n classNames,\n )}\n ref={forwardedRef}\n >\n {children}\n </div>\n );\n },\n);\n\n//\n// Heading\n//\n\ntype ThreadHeaderProps = ThemedClassName<ComponentPropsWithRef<'div'>> & { detached?: boolean };\n\nconst ThreadHeader = forwardRef<HTMLParagraphElement, ThreadHeaderProps>(\n ({ classNames, children, detached, ...props }, forwardedRef) => {\n return (\n <>\n <div role='none' className='flex items-center justify-center text-description'>\n <CaretDoubleRight />\n </div>\n <div role='none' className='flex items-center overflow-hidden'>\n <p\n role='heading'\n data-testid='thread.heading'\n {...props}\n className={mx(\n 'mie-2 text-description font-medium truncate italic',\n detached && 'line-through decoration-1',\n )}\n ref={forwardedRef}\n >\n {children}\n </p>\n </div>\n </>\n );\n },\n);\n\n//\n// Status\n//\n\ntype ThreadStatusProps = ThemedClassName<ComponentPropsWithRef<'div'>> & {\n activity?: boolean;\n};\n\nconst ThreadStatus = forwardRef<HTMLDivElement, ThreadStatusProps>(\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] pb-2 pie-2 text-xs text-description',\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', hoverableControlItem)}>{t('enter to send message')}</span>\n </div>\n );\n },\n);\n\nexport const Thread = {\n Root: ThreadRoot,\n Header: ThreadHeader,\n Status: ThreadStatus,\n};\n\nexport type { ThreadRootProps, ThreadHeaderProps as ThreadHeadingProps, ThreadStatusProps };\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport { formatDistanceToNow } from 'date-fns/formatDistanceToNow';\nimport React, { type ComponentPropsWithRef, forwardRef, type ComponentPropsWithoutRef } from 'react';\n\n// TODO(burdon): Remove dep.\nimport { Avatar, type ThemedClassName, useTranslation } from '@dxos/react-ui';\nimport { type UseTextEditorProps, keymap, listener, useTextEditor } 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 MessageRootProps = ThemedClassName<ComponentPropsWithRef<'div'>> &\n MessageMetadata &\n Partial<{ continues: boolean }>;\n\nexport const MessageRoot = forwardRef<HTMLDivElement, MessageRootProps>(\n (\n { authorImgSrc, authorId, authorName, authorAvatarProps, continues = true, children, classNames, ...rootProps },\n forwardedRef,\n ) => {\n return (\n // Must wrap the message since Avatar.Label may be used in the content.\n <Avatar.Root>\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='flex flex-col items-center gap-2 pbs-2'>\n <Avatar.Content\n size={avatarSize}\n hue={authorAvatarProps?.hue || hexToHue(authorId ?? '0')}\n fallback={authorAvatarProps?.emoji || hexToEmoji(authorId ?? '0')}\n {...(authorImgSrc && { imgSrc: authorImgSrc })}\n />\n {continues && <div role='none' className='is-px grow bg-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 MessageHeadingProps = ThemedClassName<ComponentPropsWithoutRef<'div'>> &\n Pick<MessageMetadata, 'authorName' | 'timestamp'>;\n\nexport const MessageHeading = ({ children, classNames, timestamp, authorName, ...props }: MessageHeadingProps) => {\n return (\n <div role='none' {...props} className={mx('flex gap-2 items-start', classNames)}>\n <p className='grow'>\n <MessageAuthorName authorName={authorName} />\n {timestamp && <MessageTime timestamp={timestamp} />}\n </p>\n {children}\n </div>\n );\n};\n\nexport type MessageAuthorNameProps = Pick<MessageMetadata, 'authorName'>;\n\nexport const MessageAuthorName = ({ authorName }: MessageAuthorNameProps) => {\n const { t } = useTranslation(translationKey);\n return (\n <Avatar.Label classNames='block truncate text-sm text-subdued'>{authorName ?? t('anonymous label')}</Avatar.Label>\n );\n};\n\nexport type MessageTimeProps = Pick<MessageMetadata, 'timestamp'>;\n\nexport const MessageTime = ({ timestamp }: MessageTimeProps) => {\n const { dtLocale } = useTranslation(translationKey);\n const dt = timestamp ? new Date(timestamp) : undefined;\n return (\n <time className='block text-subdued text-xs pbe-0.5' dateTime={dt?.toISOString()}>\n {dt ? formatDistanceToNow(dt, { locale: dtLocale, addSuffix: true }) : ''}\n </time>\n );\n};\n\nexport type MessageBodyProps = ComponentPropsWithoutRef<'p'>;\n\nexport const MessageBody = ({ children, ...props }: MessageBodyProps) => {\n return <p {...props}>{children}</p>;\n};\n\nexport type MessageTextboxProps = {\n disabled?: boolean;\n onSend?: () => void;\n onClear?: () => void;\n onEditorFocus?: () => void;\n} & MessageMetadata &\n UseTextEditorProps;\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 authorId,\n authorName,\n authorImgSrc,\n authorAvatarProps,\n disabled,\n extensions,\n onSend,\n onClear,\n onEditorFocus,\n ...editorProps\n}: MessageTextboxProps) => {\n const { parentRef, focusAttributes } = useTextEditor(\n () => ({\n id,\n extensions: [\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 ...editorProps,\n }),\n [id, extensions],\n );\n\n return (\n <MessageRoot {...{ id, authorId, authorName, authorImgSrc, authorAvatarProps }} continues={false}>\n <div\n role='none'\n ref={parentRef}\n className={mx('plb-0.5 mie-1 rounded-sm', focusRing, disabled && 'opacity-50')}\n {...focusAttributes}\n />\n </MessageRoot>\n );\n};\n"],
5
- "mappings": "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",
6
- "names": ["translationKey", "translations", "CaretDoubleRight", "Spinner", "React", "forwardRef", "useTranslation", "hoverableControlItem", "hoverableFocusedWithinControls", "mx", "threadLayout", "ThreadRoot", "forwardRef", "current", "children", "classNames", "props", "forwardedRef", "div", "role", "data-testid", "className", "mx", "hoverableFocusedWithinControls", "ref", "ThreadHeader", "detached", "CaretDoubleRight", "p", "ThreadStatus", "activity", "t", "useTranslation", "translationKey", "Spinner", "weight", "data-visible", "span", "aria-live", "hoverableControlItem", "Thread", "Root", "Header", "Status", "formatDistanceToNow", "React", "forwardRef", "Avatar", "useTranslation", "keymap", "listener", "useTextEditor", "focusRing", "mx", "hexToEmoji", "hexToHue", "isNotFalsy", "avatarSize", "MessageRoot", "forwardRef", "authorImgSrc", "authorId", "authorName", "authorAvatarProps", "continues", "children", "classNames", "rootProps", "forwardedRef", "React", "Avatar", "Root", "div", "role", "data-testid", "className", "mx", "ref", "Content", "size", "hue", "hexToHue", "fallback", "emoji", "hexToEmoji", "imgSrc", "MessageHeading", "timestamp", "props", "p", "MessageAuthorName", "MessageTime", "t", "useTranslation", "translationKey", "Label", "dtLocale", "dt", "Date", "undefined", "time", "dateTime", "toISOString", "formatDistanceToNow", "locale", "addSuffix", "MessageBody", "keyBindings", "onSend", "onClear", "key", "run", "MessageTextbox", "id", "disabled", "extensions", "onEditorFocus", "editorProps", "parentRef", "focusAttributes", "useTextEditor", "keymap", "of", "listener", "onFocus", "focusing", "filter", "isNotFalsy", "focusRing"]
7
- }
@@ -1 +0,0 @@
1
- {"inputs":{"src/translations.ts":{"bytes":2466,"imports":[],"format":"esm"},"src/Thread/Thread.tsx":{"bytes":10462,"imports":[{"path":"@preact-signals/safe-react/tracking","kind":"import-statement","external":true},{"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":"src/translations.ts","kind":"import-statement","original":"../translations"}],"format":"esm"},"src/Thread/index.ts":{"bytes":459,"imports":[{"path":"src/Thread/Thread.tsx","kind":"import-statement","original":"./Thread"}],"format":"esm"},"src/Message/Message.tsx":{"bytes":17557,"imports":[{"path":"@preact-signals/safe-react/tracking","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":"src/translations.ts","kind":"import-statement","original":"../translations"}],"format":"esm"},"src/Message/index.ts":{"bytes":461,"imports":[{"path":"src/Message/Message.tsx","kind":"import-statement","original":"./Message"}],"format":"esm"},"src/types.ts":{"bytes":898,"imports":[],"format":"esm"},"src/index.ts":{"bytes":876,"imports":[{"path":"src/translations.ts","kind":"import-statement","original":"./translations"},{"path":"src/Thread/index.ts","kind":"import-statement","original":"./Thread"},{"path":"src/Message/index.ts","kind":"import-statement","original":"./Message"},{"path":"src/types.ts","kind":"import-statement","original":"./types"}],"format":"esm"}},"outputs":{"dist/lib/node-esm/index.mjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":15392},"dist/lib/node-esm/index.mjs":{"imports":[{"path":"@preact-signals/safe-react/tracking","kind":"import-statement","external":true},{"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":"@preact-signals/safe-react/tracking","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":["MessageAuthorName","MessageBody","MessageHeading","MessageRoot","MessageTextbox","MessageTime","Thread","threadLayout","translations"],"entryPoint":"src/index.ts","inputs":{"src/translations.ts":{"bytesInOutput":610},"src/Thread/Thread.tsx":{"bytesInOutput":2965},"src/Thread/index.ts":{"bytesInOutput":0},"src/index.ts":{"bytesInOutput":0},"src/Message/Message.tsx":{"bytesInOutput":4934},"src/Message/index.ts":{"bytesInOutput":0}},"bytes":8869}}}