@dxos/react-ui-thread 0.8.4-main.84f28bd → 0.8.4-main.a4bbb77

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dxos/react-ui-thread",
3
- "version": "0.8.4-main.84f28bd",
3
+ "version": "0.8.4-main.a4bbb77",
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",
@@ -10,6 +10,7 @@
10
10
  "type": "module",
11
11
  "exports": {
12
12
  ".": {
13
+ "source": "./src/index.ts",
13
14
  "types": "./dist/types/src/index.d.ts",
14
15
  "browser": "./dist/lib/browser/index.mjs"
15
16
  }
@@ -26,32 +27,30 @@
26
27
  "@preact-signals/safe-react": "^0.9.0",
27
28
  "@radix-ui/react-primitive": "2.0.2",
28
29
  "date-fns": "^3.3.1",
29
- "@dxos/react-ui-editor": "0.8.4-main.84f28bd",
30
- "@dxos/util": "0.8.4-main.84f28bd"
30
+ "@dxos/util": "0.8.4-main.a4bbb77",
31
+ "@dxos/react-ui-editor": "0.8.4-main.a4bbb77"
31
32
  },
32
33
  "devDependencies": {
33
- "@phosphor-icons/react": "^2.1.5",
34
- "@types/react": "~18.2.0",
35
- "@types/react-dom": "~18.2.0",
36
- "react": "~18.2.0",
37
- "react-dom": "~18.2.0",
38
- "vite": "5.4.7",
39
- "@dxos/echo-db": "0.8.4-main.84f28bd",
40
- "@dxos/echo-schema": "0.8.4-main.84f28bd",
41
- "@dxos/keys": "0.8.4-main.84f28bd",
42
- "@dxos/live-object": "0.8.4-main.84f28bd",
43
- "@dxos/log": "0.8.4-main.84f28bd",
44
- "@dxos/random": "0.8.4-main.84f28bd",
45
- "@dxos/react-ui": "0.8.4-main.84f28bd",
46
- "@dxos/react-ui-theme": "0.8.4-main.84f28bd",
47
- "@dxos/storybook-utils": "0.8.4-main.84f28bd"
34
+ "@types/react": "~19.2.0",
35
+ "@types/react-dom": "~19.2.0",
36
+ "react": "~19.2.0",
37
+ "react-dom": "~19.2.0",
38
+ "vite": "7.1.9",
39
+ "@dxos/echo-schema": "0.8.4-main.a4bbb77",
40
+ "@dxos/live-object": "0.8.4-main.a4bbb77",
41
+ "@dxos/echo-db": "0.8.4-main.a4bbb77",
42
+ "@dxos/log": "0.8.4-main.a4bbb77",
43
+ "@dxos/keys": "0.8.4-main.a4bbb77",
44
+ "@dxos/react-ui-theme": "0.8.4-main.a4bbb77",
45
+ "@dxos/react-ui": "0.8.4-main.a4bbb77",
46
+ "@dxos/random": "0.8.4-main.a4bbb77",
47
+ "@dxos/storybook-utils": "0.8.4-main.a4bbb77"
48
48
  },
49
49
  "peerDependencies": {
50
- "@phosphor-icons/react": "^2.1.5",
51
- "react": "~18.2.0",
52
- "react-dom": "~18.2.0",
53
- "@dxos/react-ui": "0.8.4-main.84f28bd",
54
- "@dxos/react-ui-theme": "0.8.4-main.84f28bd"
50
+ "react": "^19.0.0",
51
+ "react-dom": "^19.0.0",
52
+ "@dxos/react-ui": "0.8.4-main.a4bbb77",
53
+ "@dxos/react-ui-theme": "0.8.4-main.a4bbb77"
55
54
  },
56
55
  "publishConfig": {
57
56
  "access": "public"
@@ -2,19 +2,19 @@
2
2
  // Copyright 2023 DXOS.org
3
3
  //
4
4
 
5
- import '@dxos-theme';
6
-
5
+ import { type Meta, type StoryObj } from '@storybook/react-vite';
7
6
  import React, { useState } from 'react';
8
7
 
9
8
  import { PublicKey } from '@dxos/keys';
9
+ import { withTheme } from '@dxos/react-ui/testing';
10
10
  import { hoverableControls, hoverableFocusedWithinControls } from '@dxos/react-ui-theme';
11
- import { withLayout, withTheme } from '@dxos/storybook-utils';
12
11
 
13
- import { MessageRoot } from './Message';
12
+ import { type MessageEntity, MessageStoryText } from '../testing';
14
13
  import { Thread } from '../Thread';
15
- import { MessageStoryText, type MessageEntity } from '../testing';
16
14
  import { translations } from '../translations';
17
15
 
16
+ import { MessageRoot } from './Message';
17
+
18
18
  const DefaultStory = () => {
19
19
  const [identityKey] = useState(PublicKey.random());
20
20
  const [message] = useState<MessageEntity>({
@@ -35,12 +35,19 @@ const DefaultStory = () => {
35
35
  );
36
36
  };
37
37
 
38
- export default {
38
+ const meta = {
39
39
  title: 'ui/react-ui-thread/Message',
40
- component: MessageRoot,
40
+ component: MessageRoot as any,
41
41
  render: DefaultStory,
42
- decorators: [withTheme, withLayout({ fullscreen: true })],
43
- parameters: { translations },
44
- };
42
+ decorators: [withTheme],
43
+ parameters: {
44
+ layout: 'fullscreen',
45
+ translations,
46
+ },
47
+ } satisfies Meta<typeof DefaultStory>;
48
+
49
+ export default meta;
50
+
51
+ type Story = StoryObj<typeof meta>;
45
52
 
46
- export const Default = {};
53
+ export const Default: Story = {};
@@ -3,13 +3,13 @@
3
3
  //
4
4
 
5
5
  import { formatDistanceToNow } from 'date-fns/formatDistanceToNow';
6
- import React, { type ComponentPropsWithRef, forwardRef, type ComponentPropsWithoutRef } from 'react';
6
+ import React, { type ComponentPropsWithRef, type ComponentPropsWithoutRef, forwardRef } from 'react';
7
7
 
8
8
  // TODO(burdon): Remove dep.
9
9
  import { Avatar, type ThemedClassName, useTranslation } from '@dxos/react-ui';
10
10
  import { type UseTextEditorProps, keymap, listener, useTextEditor } from '@dxos/react-ui-editor';
11
11
  import { focusRing, mx } from '@dxos/react-ui-theme';
12
- import { hexToEmoji, hexToHue, isNotFalsy } from '@dxos/util';
12
+ import { hexToEmoji, hexToHue, isTruthy } from '@dxos/util';
13
13
 
14
14
  import { translationKey } from '../translations';
15
15
  import { type MessageMetadata } from '../types';
@@ -20,6 +20,7 @@ export type MessageRootProps = ThemedClassName<ComponentPropsWithRef<'div'>> &
20
20
  MessageMetadata &
21
21
  Partial<{ continues: boolean }>;
22
22
 
23
+ // TODO(burdon): Show authorName on tooltip.
23
24
  export const MessageRoot = forwardRef<HTMLDivElement, MessageRootProps>(
24
25
  (
25
26
  { authorImgSrc, authorId, authorName, authorAvatarProps, continues = true, children, classNames, ...rootProps },
@@ -35,7 +36,7 @@ export const MessageRoot = forwardRef<HTMLDivElement, MessageRootProps>(
35
36
  className={mx('grid grid-cols-subgrid col-span-2', classNames)}
36
37
  ref={forwardedRef}
37
38
  >
38
- <div role='none' className='flex flex-col items-center gap-2 pbs-2'>
39
+ <div role='none' className='flex flex-col items-center gap-2 pbs-1'>
39
40
  <Avatar.Content
40
41
  size={avatarSize}
41
42
  hue={authorAvatarProps?.hue || hexToHue(authorId ?? '0')}
@@ -155,7 +156,7 @@ export const MessageTextbox = ({
155
156
  },
156
157
  }),
157
158
  extensions,
158
- ].filter(isNotFalsy),
159
+ ].filter(isTruthy),
159
160
  ...editorProps,
160
161
  }),
161
162
  [id, extensions],
@@ -2,9 +2,7 @@
2
2
  // Copyright 2023 DXOS.org
3
3
  //
4
4
 
5
- import '@dxos-theme';
6
-
7
- import { Check, Trash } from '@phosphor-icons/react';
5
+ import { type Meta, type StoryObj } from '@storybook/react-vite';
8
6
  import React, { type FC, useEffect, useMemo, useRef, useState } from 'react';
9
7
 
10
8
  import { createDocAccessor, createObject } from '@dxos/echo-db';
@@ -13,7 +11,8 @@ import { PublicKey } from '@dxos/keys';
13
11
  import { live } from '@dxos/live-object';
14
12
  import { log } from '@dxos/log';
15
13
  import { faker } from '@dxos/random';
16
- import { Button, useThemeContext } from '@dxos/react-ui';
14
+ import { Button, Icon, useThemeContext } from '@dxos/react-ui';
15
+ import { withTheme } from '@dxos/react-ui/testing';
17
16
  import {
18
17
  type Comment,
19
18
  type CommentsOptions,
@@ -28,13 +27,13 @@ import {
28
27
  useTextEditor,
29
28
  } from '@dxos/react-ui-editor';
30
29
  import { hoverableControls, hoverableFocusedWithinControls } from '@dxos/react-ui-theme';
31
- import { withTheme } from '@dxos/storybook-utils';
32
30
 
33
- import { Thread } from './Thread';
34
31
  import { MessageBody, MessageHeading, MessageRoot, MessageTextbox } from '../Message';
35
32
  import { type MessageEntity } from '../testing';
36
33
  import { translations } from '../translations';
37
34
 
35
+ import { Thread } from './Thread';
36
+
38
37
  faker.seed(101);
39
38
 
40
39
  const authorId = PublicKey.random().toHex();
@@ -162,7 +161,7 @@ const StoryThread: FC<{
162
161
  <span>id:{thread.id.slice(0, 4)}</span>
163
162
  <span>y:{thread.yPos}</span>
164
163
  <span className='grow' />
165
- {!thread.cursor && <Trash />}
164
+ {!thread.cursor && <Icon icon='ph--trash--regular' />}
166
165
  </div>
167
166
 
168
167
  <Thread.Header>
@@ -187,7 +186,7 @@ const StoryThread: FC<{
187
186
  />
188
187
  <Thread.Status />
189
188
  <Button variant='ghost' classNames='px-1' title='Resolve' onClick={onResolve}>
190
- <Check />
189
+ <Icon icon='ph--check--regular' />
191
190
  </Button>
192
191
  </div>
193
192
  </Thread.Root>
@@ -232,7 +231,7 @@ type StoryProps = {
232
231
  autoCreate?: boolean;
233
232
  };
234
233
 
235
- const Story = ({ text, autoCreate }: StoryProps) => {
234
+ const DefaultStory = ({ text, autoCreate }: StoryProps) => {
236
235
  const [item] = useState(createObject(live(Expando, { content: text ?? '' })));
237
236
  const [threads, setThreads] = useState<StoryCommentThread[]>([]);
238
237
  const [selected, setSelected] = useState<string>();
@@ -349,17 +348,24 @@ const Story = ({ text, autoCreate }: StoryProps) => {
349
348
  );
350
349
  };
351
350
 
352
- export default {
351
+ const meta = {
353
352
  title: 'ui/react-ui-thread/Comments',
354
- component: StoryThread,
353
+ component: StoryThread as any,
354
+ render: DefaultStory,
355
355
  decorators: [withTheme],
356
- render: (args: StoryProps) => <Story {...args} />,
357
- parameters: { translations, layout: 'fullscreen' },
358
- };
356
+ parameters: {
357
+ translations,
358
+ layout: 'fullscreen',
359
+ },
360
+ } satisfies Meta<typeof DefaultStory>;
361
+
362
+ export default meta;
363
+
364
+ type Story = StoryObj<typeof meta>;
359
365
 
360
366
  const str = (...lines: string[]) => lines.join('\n');
361
367
 
362
- export const Default = {
368
+ export const Default: Story = {
363
369
  args: {
364
370
  text: str(
365
371
  '# Comments',
@@ -2,21 +2,21 @@
2
2
  // Copyright 2023 DXOS.org
3
3
  //
4
4
 
5
- import '@dxos-theme';
6
-
5
+ import { type Meta, type StoryObj } from '@storybook/react-vite';
7
6
  import React, { useMemo, useRef, useState } from 'react';
8
7
 
9
8
  import { PublicKey } from '@dxos/keys';
10
9
  import { faker } from '@dxos/random';
10
+ import { withTheme } from '@dxos/react-ui/testing';
11
11
  import { createBasicExtensions, createThemeExtensions } from '@dxos/react-ui-editor';
12
12
  import { hoverableControls, hoverableFocusedWithinControls } from '@dxos/react-ui-theme';
13
- import { type Meta, withLayout, withTheme } from '@dxos/storybook-utils';
14
13
 
15
- import { Thread } from './Thread';
16
14
  import { MessageRoot, MessageTextbox } from '../Message';
17
- import { MessageStoryText, type MessageEntity } from '../testing';
15
+ import { type MessageEntity, MessageStoryText } from '../testing';
18
16
  import { translations } from '../translations';
19
17
 
18
+ import { Thread } from './Thread';
19
+
20
20
  faker.seed(1);
21
21
 
22
22
  const DefaultStory = () => {
@@ -81,14 +81,19 @@ const DefaultStory = () => {
81
81
  );
82
82
  };
83
83
 
84
- const meta: Meta<typeof Thread.Root> = {
84
+ const meta = {
85
85
  title: 'ui/react-ui-thread/Thread',
86
86
  component: Thread.Root,
87
87
  render: DefaultStory,
88
- decorators: [withTheme, withLayout({ fullscreen: true })],
89
- parameters: { translations },
90
- };
88
+ decorators: [withTheme],
89
+ parameters: {
90
+ layout: 'fullscreen',
91
+ translations,
92
+ },
93
+ } satisfies Meta<typeof Thread.Root>;
91
94
 
92
95
  export default meta;
93
96
 
94
- export const Default = {};
97
+ type Story = StoryObj<typeof meta>;
98
+
99
+ export const Default: Story = {};
@@ -2,10 +2,9 @@
2
2
  // Copyright 2023 DXOS.org
3
3
  //
4
4
 
5
- import { CaretDoubleRight, Spinner } from '@phosphor-icons/react';
6
5
  import React, { type ComponentPropsWithRef, forwardRef } from 'react';
7
6
 
8
- import { type ThemedClassName, useTranslation } from '@dxos/react-ui';
7
+ import { Icon, type ThemedClassName, useTranslation } from '@dxos/react-ui';
9
8
  import { hoverableControlItem, hoverableFocusedWithinControls, mx } from '@dxos/react-ui-theme';
10
9
 
11
10
  import { translationKey } from '../translations';
@@ -53,7 +52,7 @@ const ThreadHeader = forwardRef<HTMLParagraphElement, ThreadHeaderProps>(
53
52
  return (
54
53
  <>
55
54
  <div role='none' className='flex items-center justify-center text-description'>
56
- <CaretDoubleRight />
55
+ <Icon icon='ph--caret-double-right--regular' />
57
56
  </div>
58
57
  <div role='none' className='flex items-center overflow-hidden'>
59
58
  <p
@@ -94,10 +93,10 @@ const ThreadStatus = forwardRef<HTMLDivElement, ThreadStatusProps>(
94
93
  )}
95
94
  ref={forwardedRef}
96
95
  >
97
- <Spinner
98
- weight='bold'
96
+ <Icon
97
+ icon='ph--spinner--bold'
98
+ classNames='is-6 bs-4 invisible data-[visible=show]:visible animate-spin-slow'
99
99
  data-visible={activity ? 'show' : 'hide'}
100
- className='is-6 bs-4 invisible data-[visible=show]:visible animate-spin-slow'
101
100
  />
102
101
  <span className='truncate min-is-0' aria-live='polite'>
103
102
  {activity ? children : null}
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,10 +2,9 @@
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';
7
+ import { Button, Icon } from '@dxos/react-ui';
9
8
  import { hoverableControlItem, hoverableControls, hoverableFocusedWithinControls, mx } from '@dxos/react-ui-theme';
10
9
 
11
10
  import { MessageBody, MessageHeading } from './Message';
@@ -31,7 +30,7 @@ export const MessageStoryText = ({ text, onDelete, authorName, timestamp }: Mess
31
30
  classNames={['p-1.5 min-bs-0 mie-1 items-start transition-opacity', hoverableControlItem]}
32
31
  onClick={() => onDelete()}
33
32
  >
34
- <X />
33
+ <Icon icon='ph--x--regular' />
35
34
  </Button>
36
35
  )}
37
36
  </MessageHeading>
@@ -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