@dxos/react-ui-thread 0.8.3 → 0.8.4-main.1c7ec43d41

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 +140 -205
  2. package/dist/lib/browser/index.mjs.map +4 -4
  3. package/dist/lib/browser/meta.json +1 -1
  4. package/dist/lib/browser/translations.mjs +25 -0
  5. package/dist/lib/browser/translations.mjs.map +7 -0
  6. package/dist/types/src/Message/Message.d.ts +2 -2
  7. package/dist/types/src/Message/Message.d.ts.map +1 -1
  8. package/dist/types/src/Message/Message.stories.d.ts +21 -19
  9. package/dist/types/src/Message/Message.stories.d.ts.map +1 -1
  10. package/dist/types/src/Thread/Comments.stories.d.ts +22 -39
  11. package/dist/types/src/Thread/Comments.stories.d.ts.map +1 -1
  12. package/dist/types/src/Thread/Thread.d.ts +27 -10
  13. package/dist/types/src/Thread/Thread.d.ts.map +1 -1
  14. package/dist/types/src/Thread/Thread.stories.d.ts +25 -19
  15. package/dist/types/src/Thread/Thread.stories.d.ts.map +1 -1
  16. package/dist/types/src/index.d.ts +1 -3
  17. package/dist/types/src/index.d.ts.map +1 -1
  18. package/dist/types/src/testing.d.ts +1 -2
  19. package/dist/types/src/testing.d.ts.map +1 -1
  20. package/dist/types/src/translations.d.ts +15 -16
  21. package/dist/types/src/translations.d.ts.map +1 -1
  22. package/dist/types/src/types.d.ts +1 -0
  23. package/dist/types/src/types.d.ts.map +1 -1
  24. package/dist/types/tsconfig.tsbuildinfo +1 -1
  25. package/package.json +37 -29
  26. package/src/Message/Message.stories.tsx +24 -17
  27. package/src/Message/Message.tsx +20 -18
  28. package/src/Thread/Comments.stories.tsx +94 -65
  29. package/src/Thread/Thread.stories.tsx +31 -22
  30. package/src/Thread/Thread.tsx +47 -26
  31. package/src/index.ts +1 -4
  32. package/src/testing.tsx +10 -14
  33. package/src/translations.ts +15 -13
  34. package/src/types.ts +1 -0
@@ -2,22 +2,22 @@
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
- import { faker } from '@dxos/random';
11
- import { createBasicExtensions, createThemeExtensions } from '@dxos/react-ui-editor';
12
- import { hoverableControls, hoverableFocusedWithinControls } from '@dxos/react-ui-theme';
13
- import { withLayout, withTheme } from '@dxos/storybook-utils';
9
+ import { random } from '@dxos/random';
10
+ import { withLayout, withTheme } from '@dxos/react-ui/testing';
11
+ import { createBasicExtensions, createThemeExtensions } from '@dxos/ui-editor';
12
+ import { hoverableControls, hoverableFocusedWithinControls } from '@dxos/ui-theme';
13
+
14
+ import { translations } from '#translations';
14
15
 
15
- import { Thread, ThreadFooter } from './Thread';
16
16
  import { MessageRoot, MessageTextbox } from '../Message';
17
- import { ThreadStoryContainer, MessageStoryText, type MessageEntity } from '../testing';
18
- import translations from '../translations';
17
+ import { type MessageEntity, MessageStoryText } from '../testing';
18
+ import { Thread } from './Thread';
19
19
 
20
- faker.seed(1);
20
+ random.seed(1);
21
21
 
22
22
  const DefaultStory = () => {
23
23
  const [pending, setPending] = useState(false);
@@ -28,7 +28,7 @@ const DefaultStory = () => {
28
28
  id: `m${i + 1}`,
29
29
  timestamp: new Date().toISOString(),
30
30
  authorId: [identityKey1.toHex(), identityKey2.toHex()][i % 2],
31
- text: faker.lorem.paragraph(),
31
+ text: random.lorem.paragraph(),
32
32
  })),
33
33
  );
34
34
 
@@ -59,13 +59,14 @@ const DefaultStory = () => {
59
59
  };
60
60
 
61
61
  return (
62
- <ThreadStoryContainer>
63
- <Thread id='t1'>
62
+ <div className='mx-auto w-96 overflow-y-auto'>
63
+ <Thread.Root id='t1'>
64
64
  {messages.map((message) => (
65
65
  <MessageRoot key={message.id} classNames={[hoverableControls, hoverableFocusedWithinControls]} {...message}>
66
66
  <MessageStoryText {...message} text={message.text} onDelete={() => console.log('delete')} />
67
67
  </MessageRoot>
68
68
  ))}
69
+
69
70
  <MessageTextbox
70
71
  id={String(_count)}
71
72
  authorId={identityKey1.toHex()}
@@ -73,18 +74,26 @@ const DefaultStory = () => {
73
74
  extensions={extensions}
74
75
  onSend={handleSend}
75
76
  />
76
- <ThreadFooter activity>Processing...</ThreadFooter>
77
- </Thread>
78
- </ThreadStoryContainer>
77
+
78
+ <Thread.Status activity>Processing...</Thread.Status>
79
+ </Thread.Root>
80
+ </div>
79
81
  );
80
82
  };
81
83
 
82
- export default {
84
+ const meta = {
83
85
  title: 'ui/react-ui-thread/Thread',
84
- component: Thread,
86
+ component: Thread.Root,
85
87
  render: DefaultStory,
86
- decorators: [withTheme, withLayout({ fullscreen: true })],
87
- parameters: { translations },
88
- };
88
+ decorators: [withTheme(), withLayout({ layout: 'fullscreen' })],
89
+ parameters: {
90
+ layout: 'fullscreen',
91
+ translations,
92
+ },
93
+ } satisfies Meta<typeof Thread.Root>;
94
+
95
+ export default meta;
96
+
97
+ type Story = StoryObj<typeof meta>;
89
98
 
90
- export const Default = {};
99
+ export const Default: Story = {};
@@ -2,20 +2,29 @@
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';
9
+
10
+ import { translationKey } from '#translations';
10
11
 
11
- import { translationKey } from '../translations';
12
12
  import type { ThreadEntity } from '../types';
13
13
 
14
- export type ThreadProps = ThemedClassName<ComponentPropsWithRef<'div'>> & ThreadEntity & { current?: boolean };
14
+ // TODO(burdon): Avoid exporting fragments.
15
+ export const threadLayout = 'w-full place-self-start grid grid-cols-[var(--dx-rail-size)_1fr]';
16
+
17
+ //
18
+ // Root
19
+ //
15
20
 
16
- export const threadLayout = 'is-full place-self-start grid grid-cols-[var(--rail-size)_1fr]';
21
+ type ThreadRootProps = ThemedClassName<
22
+ PropsWithChildren<
23
+ ThreadEntity & { current?: boolean } & Pick<ComponentPropsWithRef<'div'>, 'onClickCapture' | 'onFocusCapture'>
24
+ >
25
+ >;
17
26
 
18
- export const Thread = forwardRef<HTMLDivElement, ThreadProps>(
27
+ const ThreadRoot = forwardRef<HTMLDivElement, ThreadRootProps>(
19
28
  ({ current, children, classNames, ...props }, forwardedRef) => {
20
29
  return (
21
30
  <div
@@ -26,8 +35,7 @@ export const Thread = forwardRef<HTMLDivElement, ThreadProps>(
26
35
  className={mx(
27
36
  threadLayout,
28
37
  hoverableFocusedWithinControls,
29
- 'pbs-2 pbe-4 bg-[var(--surface-bg)] border-separator first:border-bs-0 border-be',
30
- 'current-related attention-surface [--controls-opacity:0]',
38
+ 'bg-[var(--surface-bg)] current-related dx-attention-surface [--controls-opacity:0]',
31
39
  classNames,
32
40
  )}
33
41
  ref={forwardedRef}
@@ -38,24 +46,25 @@ export const Thread = forwardRef<HTMLDivElement, ThreadProps>(
38
46
  },
39
47
  );
40
48
 
41
- export type ThreadHeadingProps = ThemedClassName<ComponentPropsWithRef<'div'>> & { detached?: boolean };
49
+ //
50
+ // Heading
51
+ //
52
+
53
+ type ThreadHeaderProps = PropsWithChildren<{ detached?: boolean }>;
42
54
 
43
- export const ThreadHeading = forwardRef<HTMLParagraphElement, ThreadHeadingProps>(
44
- ({ classNames, children, detached, ...props }, forwardedRef) => {
55
+ const ThreadHeader = forwardRef<HTMLParagraphElement, ThreadHeaderProps>(
56
+ ({ children, detached, ...props }, forwardedRef) => {
45
57
  return (
46
58
  <>
47
59
  <div role='none' className='flex items-center justify-center text-description'>
48
- <CaretDoubleRight />
60
+ <Icon icon='ph--caret-double-right--regular' />
49
61
  </div>
50
62
  <div role='none' className='flex items-center overflow-hidden'>
51
63
  <p
52
64
  role='heading'
53
65
  data-testid='thread.heading'
54
66
  {...props}
55
- className={mx(
56
- 'mie-2 text-description font-medium truncate italic',
57
- detached && 'line-through decoration-1',
58
- )}
67
+ className={mx('me-2 text-description font-medium truncate italic', detached && 'line-through decoration-1')}
59
68
  ref={forwardedRef}
60
69
  >
61
70
  {children}
@@ -66,32 +75,44 @@ export const ThreadHeading = forwardRef<HTMLParagraphElement, ThreadHeadingProps
66
75
  },
67
76
  );
68
77
 
69
- export type ThreadFooterProps = ThemedClassName<ComponentPropsWithRef<'div'>> & {
78
+ //
79
+ // Status
80
+ //
81
+
82
+ type ThreadStatusProps = ThemedClassName<PropsWithChildren> & {
70
83
  activity?: boolean;
71
84
  };
72
85
 
73
- export const ThreadFooter = forwardRef<HTMLDivElement, ThreadFooterProps>(
86
+ const ThreadStatus = forwardRef<HTMLDivElement, ThreadStatusProps>(
74
87
  ({ activity, classNames, children, ...props }, forwardedRef) => {
75
88
  const { t } = useTranslation(translationKey);
76
89
  return (
77
90
  <div
78
91
  {...props}
79
92
  className={mx(
80
- 'col-start-2 grid grid-cols-[min-content_1fr_max-content] pb-2 pie-2 text-xs text-description',
93
+ 'col-start-2 grid grid-cols-[min-content_1fr_max-content] pb-2 pe-2 text-xs text-description',
81
94
  classNames,
82
95
  )}
83
96
  ref={forwardedRef}
84
97
  >
85
- <Spinner
86
- weight='bold'
98
+ <Icon
99
+ icon='ph--spinner--bold'
100
+ classNames='w-6 h-4 invisible data-[visible=show]:visible animate-spin-slow'
87
101
  data-visible={activity ? 'show' : 'hide'}
88
- className='is-6 bs-4 invisible data-[visible=show]:visible animate-spin-slow'
89
102
  />
90
- <span className='truncate min-is-0' aria-live='polite'>
103
+ <span className='truncate min-w-0' aria-live='polite'>
91
104
  {activity ? children : null}
92
105
  </span>
93
- <span className={mx('text-end', hoverableControlItem)}>{t('enter to send message')}</span>
106
+ <span className={mx('text-end', hoverableControlItem)}>{t('enter-to-send.message')}</span>
94
107
  </div>
95
108
  );
96
109
  },
97
110
  );
111
+
112
+ export const Thread = {
113
+ Root: ThreadRoot,
114
+ Header: ThreadHeader,
115
+ Status: ThreadStatus,
116
+ };
117
+
118
+ export type { ThreadRootProps, ThreadHeaderProps, ThreadStatusProps };
package/src/index.ts CHANGED
@@ -2,9 +2,6 @@
2
2
  // Copyright 2023 DXOS.org
3
3
  //
4
4
 
5
- import translations from './translations';
6
-
7
5
  export * from './Thread';
8
6
  export * from './Message';
9
- export * from './types';
10
- export { translations };
7
+ export type * from './types';
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
- import React, { type PropsWithChildren } from 'react';
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,13 +50,9 @@ 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>
57
57
  );
58
58
  };
59
-
60
- export const ThreadStoryContainer = ({ children }: PropsWithChildren) => {
61
- return <div className={mx('bg-white dark:bg-black mli-auto is-96 overflow-y-auto')}>{children}</div>;
62
- };
@@ -2,23 +2,25 @@
2
2
  // Copyright 2023 DXOS.org
3
3
  //
4
4
 
5
- export const translationKey = 'thread';
5
+ import { type Resource } from '@dxos/react-ui';
6
6
 
7
- export default [
7
+ export const translationKey = '@dxos/react-ui-thread';
8
+
9
+ export const translations = [
8
10
  {
9
11
  'en-US': {
10
12
  [translationKey]: {
11
- 'plugin name': 'Threads',
12
- 'thread title placeholder': 'New thread',
13
- 'thread title label': 'Title',
14
- 'delete thread label': 'Delete',
15
- 'create thread label': 'Create thread',
16
- 'message placeholder': 'Enter message...',
17
- 'comment placeholder': 'Enter comment...',
18
- 'settings standalone label': 'Enable standalone thread creation',
19
- 'anonymous label': 'Anonymous',
20
- '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 ⏎',
21
23
  },
22
24
  },
23
25
  },
24
- ];
26
+ ] as const satisfies Resource[];
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
  };