@dxos/react-ui-markdown 0.8.4-main.6fa680abb7 → 0.8.4-main.765dc60934

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 (50) hide show
  1. package/LICENSE +102 -5
  2. package/dist/lib/browser/index.mjs +617 -24
  3. package/dist/lib/browser/index.mjs.map +4 -4
  4. package/dist/lib/browser/meta.json +1 -1
  5. package/dist/types/src/MarkdownStream/MarkdownStream.d.ts +101 -0
  6. package/dist/types/src/MarkdownStream/MarkdownStream.d.ts.map +1 -0
  7. package/dist/types/src/MarkdownStream/MarkdownStream.stories.d.ts +23 -0
  8. package/dist/types/src/MarkdownStream/MarkdownStream.stories.d.ts.map +1 -0
  9. package/dist/types/src/MarkdownStream/footer.d.ts +23 -0
  10. package/dist/types/src/MarkdownStream/footer.d.ts.map +1 -0
  11. package/dist/types/src/MarkdownStream/index.d.ts +4 -0
  12. package/dist/types/src/MarkdownStream/index.d.ts.map +1 -0
  13. package/dist/types/src/MarkdownStream/stream.d.ts +39 -0
  14. package/dist/types/src/MarkdownStream/stream.d.ts.map +1 -0
  15. package/dist/types/src/MarkdownStream/stream.test.d.ts +2 -0
  16. package/dist/types/src/MarkdownStream/stream.test.d.ts.map +1 -0
  17. package/dist/types/src/MarkdownStream/testing/index.d.ts +2 -0
  18. package/dist/types/src/MarkdownStream/testing/index.d.ts.map +1 -0
  19. package/dist/types/src/MarkdownStream/testing/testing.d.ts +16 -0
  20. package/dist/types/src/MarkdownStream/testing/testing.d.ts.map +1 -0
  21. package/dist/types/src/{MarkdownViewer/MarkdownViewer.d.ts → MarkdownView/MarkdownView.d.ts} +3 -3
  22. package/dist/types/src/MarkdownView/MarkdownView.d.ts.map +1 -0
  23. package/dist/types/src/{MarkdownViewer/MarkdownViewer.stories.d.ts → MarkdownView/MarkdownView.stories.d.ts} +4 -4
  24. package/dist/types/src/MarkdownView/MarkdownView.stories.d.ts.map +1 -0
  25. package/dist/types/src/MarkdownView/Media.d.ts +35 -0
  26. package/dist/types/src/MarkdownView/Media.d.ts.map +1 -0
  27. package/dist/types/src/MarkdownView/index.d.ts +3 -0
  28. package/dist/types/src/MarkdownView/index.d.ts.map +1 -0
  29. package/dist/types/src/index.d.ts +2 -1
  30. package/dist/types/src/index.d.ts.map +1 -1
  31. package/dist/types/tsconfig.tsbuildinfo +1 -1
  32. package/package.json +30 -26
  33. package/src/MarkdownStream/MarkdownStream.stories.tsx +215 -0
  34. package/src/MarkdownStream/MarkdownStream.tsx +442 -0
  35. package/src/MarkdownStream/footer.ts +119 -0
  36. package/src/MarkdownStream/index.ts +8 -0
  37. package/src/MarkdownStream/stream.test.ts +126 -0
  38. package/src/MarkdownStream/stream.ts +229 -0
  39. package/src/{MarkdownViewer → MarkdownStream/testing}/index.ts +1 -1
  40. package/src/MarkdownStream/testing/testing.ts +56 -0
  41. package/src/MarkdownStream/testing/text.md +67 -0
  42. package/src/{MarkdownViewer/MarkdownViewer.stories.tsx → MarkdownView/MarkdownView.stories.tsx} +10 -10
  43. package/src/{MarkdownViewer/MarkdownViewer.tsx → MarkdownView/MarkdownView.tsx} +32 -9
  44. package/src/MarkdownView/Media.tsx +80 -0
  45. package/src/MarkdownView/index.ts +6 -0
  46. package/src/index.ts +2 -1
  47. package/dist/types/src/MarkdownViewer/MarkdownViewer.d.ts.map +0 -1
  48. package/dist/types/src/MarkdownViewer/MarkdownViewer.stories.d.ts.map +0 -1
  49. package/dist/types/src/MarkdownViewer/index.d.ts +0 -2
  50. package/dist/types/src/MarkdownViewer/index.d.ts.map +0 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dxos/react-ui-markdown",
3
- "version": "0.8.4-main.6fa680abb7",
3
+ "version": "0.8.4-main.765dc60934",
4
4
  "description": "Markdown components.",
5
5
  "homepage": "https://dxos.org",
6
6
  "bugs": "https://github.com/dxos/dxos/issues",
@@ -8,7 +8,7 @@
8
8
  "type": "git",
9
9
  "url": "https://github.com/dxos/dxos"
10
10
  },
11
- "license": "MIT",
11
+ "license": "FSL-1.1-Apache-2.0",
12
12
  "author": "DXOS.org",
13
13
  "type": "module",
14
14
  "exports": {
@@ -19,9 +19,6 @@
19
19
  }
20
20
  },
21
21
  "types": "dist/types/src/index.d.ts",
22
- "typesVersions": {
23
- "*": {}
24
- },
25
22
  "files": [
26
23
  "dist",
27
24
  "src"
@@ -30,47 +27,54 @@
30
27
  "@codemirror/autocomplete": "^6.19.0",
31
28
  "@codemirror/language": "^6.11.3",
32
29
  "@codemirror/state": "^6.5.2",
33
- "@codemirror/view": "^6.38.4",
30
+ "@codemirror/view": "^6.38.5",
34
31
  "@lezer/common": "^1.2.2",
35
32
  "@lezer/highlight": "^1.2.1",
36
33
  "@lezer/markdown": "^1.3.1",
37
34
  "@lezer/xml": "^1.0.6",
38
35
  "@radix-ui/react-compose-refs": "1.1.1",
39
36
  "@radix-ui/react-context": "1.1.1",
40
- "effect": "3.19.16",
37
+ "effect": "3.20.0",
41
38
  "json5": "^2.2.3",
42
39
  "react-markdown": "^10.1.0",
43
40
  "react-resize-detector": "^11.0.1",
44
41
  "remark-gfm": "^4.0.1",
45
- "@dxos/async": "0.8.4-main.6fa680abb7",
46
- "@dxos/invariant": "0.8.4-main.6fa680abb7",
47
- "@dxos/log": "0.8.4-main.6fa680abb7",
48
- "@dxos/echo": "0.8.4-main.6fa680abb7",
49
- "@dxos/util": "0.8.4-main.6fa680abb7",
50
- "@dxos/react-ui-editor": "0.8.4-main.6fa680abb7",
51
- "@dxos/react-ui-syntax-highlighter": "0.8.4-main.6fa680abb7"
42
+ "@dxos/async": "0.8.4-main.765dc60934",
43
+ "@dxos/echo": "0.8.4-main.765dc60934",
44
+ "@dxos/invariant": "0.8.4-main.765dc60934",
45
+ "@dxos/effect": "0.8.4-main.765dc60934",
46
+ "@dxos/log": "0.8.4-main.765dc60934",
47
+ "@dxos/react-ui": "0.8.4-main.765dc60934",
48
+ "@dxos/react-ui-editor": "0.8.4-main.765dc60934",
49
+ "@dxos/react-ui-syntax-highlighter": "0.8.4-main.765dc60934",
50
+ "@dxos/ui": "0.8.4-main.765dc60934",
51
+ "@dxos/ui-theme": "0.8.4-main.765dc60934",
52
+ "@dxos/ui-editor": "0.8.4-main.765dc60934",
53
+ "@dxos/util": "0.8.4-main.765dc60934"
52
54
  },
53
55
  "devDependencies": {
56
+ "@effect/vitest": "0.29.0",
54
57
  "@types/react": "~19.2.7",
55
58
  "@types/react-dom": "~19.2.3",
56
59
  "react": "~19.2.3",
57
60
  "react-dom": "~19.2.3",
58
- "vite": "^7.1.11",
59
- "@dxos/lit-ui": "0.8.4-main.6fa680abb7",
60
- "@dxos/echo": "0.8.4-main.6fa680abb7",
61
- "@dxos/random": "0.8.4-main.6fa680abb7",
62
- "@dxos/react-client": "0.8.4-main.6fa680abb7",
63
- "@dxos/react-ui": "0.8.4-main.6fa680abb7",
64
- "@dxos/storybook-utils": "0.8.4-main.6fa680abb7",
65
- "@dxos/schema": "0.8.4-main.6fa680abb7",
66
- "@dxos/ui-theme": "0.8.4-main.6fa680abb7"
61
+ "vite": "^8.0.13",
62
+ "@dxos/lit-ui": "0.8.4-main.765dc60934",
63
+ "@dxos/keys": "0.8.4-main.765dc60934",
64
+ "@dxos/echo": "0.8.4-main.765dc60934",
65
+ "@dxos/random": "0.8.4-main.765dc60934",
66
+ "@dxos/react-ui": "0.8.4-main.765dc60934",
67
+ "@dxos/react-client": "0.8.4-main.765dc60934",
68
+ "@dxos/schema": "0.8.4-main.765dc60934",
69
+ "@dxos/storybook-utils": "0.8.4-main.765dc60934",
70
+ "@dxos/ui-theme": "0.8.4-main.765dc60934"
67
71
  },
68
72
  "peerDependencies": {
69
- "effect": "3.19.16",
73
+ "effect": "3.20.0",
70
74
  "react": "~19.2.3",
71
75
  "react-dom": "~19.2.3",
72
- "@dxos/react-ui": "0.8.4-main.6fa680abb7",
73
- "@dxos/ui-theme": "0.8.4-main.6fa680abb7"
76
+ "@dxos/ui-theme": "0.8.4-main.765dc60934",
77
+ "@dxos/react-ui": "0.8.4-main.765dc60934"
74
78
  },
75
79
  "publishConfig": {
76
80
  "access": "public"
@@ -0,0 +1,215 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import { WidgetType } from '@codemirror/view';
6
+ import { type Meta, type StoryObj } from '@storybook/react-vite';
7
+ import React, { useCallback, useEffect, useState } from 'react';
8
+
9
+ import '@dxos/lit-ui';
10
+ import { PublicKey } from '@dxos/keys';
11
+ import { random } from '@dxos/random';
12
+ import { Input, Toolbar } from '@dxos/react-ui';
13
+ import { Panel } from '@dxos/react-ui';
14
+ import { withLayout, withTheme } from '@dxos/react-ui/testing';
15
+ import { Domino } from '@dxos/ui';
16
+ import { type XmlWidgetRegistry, getXmlTextChild } from '@dxos/ui-editor';
17
+ import { mx } from '@dxos/ui-theme';
18
+ import { keyToFallback, trim } from '@dxos/util';
19
+
20
+ import { MarkdownStream, type MarkdownStreamController, type MarkdownStreamProps } from './MarkdownStream';
21
+ import { type TextStreamOptions, textStream } from './testing';
22
+ import TEXT from './testing/text.md?raw';
23
+
24
+ random.seed(123);
25
+
26
+ const userHue = keyToFallback(PublicKey.random()).hue;
27
+
28
+ const defaultStreamOptions: TextStreamOptions = {
29
+ wordsPerChunk: 5,
30
+ chunkDelay: 200,
31
+ variance: 0.5,
32
+ };
33
+
34
+ class DOMWidget extends WidgetType {
35
+ constructor(private text: string) {
36
+ super();
37
+ }
38
+
39
+ override eq(other: this) {
40
+ return this.text === other.text;
41
+ }
42
+
43
+ override toDOM() {
44
+ return Domino.of('span').classNames(mx('flex m-2 p-2 border border-separator rounded')).text(this.text).root;
45
+ }
46
+ }
47
+
48
+ const ReactWidget = ({ children }: { children: string }) => {
49
+ return <div className='m-2 p-2 border border-separator rounded'>{children}</div>;
50
+ };
51
+
52
+ const registry: XmlWidgetRegistry = {
53
+ 'dom-widget': {
54
+ block: true,
55
+ streaming: true,
56
+ factory: ({ children }) => {
57
+ const text = getXmlTextChild(children);
58
+ return text ? new DOMWidget(text) : null;
59
+ },
60
+ },
61
+
62
+ 'react-widget': {
63
+ block: true,
64
+ streaming: true,
65
+ Component: ReactWidget,
66
+ },
67
+ };
68
+
69
+ type DefaultStoryProps = MarkdownStreamProps & {
70
+ initialContent?: string;
71
+ streamOptions?: TextStreamOptions;
72
+ };
73
+
74
+ const DefaultStory = ({
75
+ initialContent,
76
+ content,
77
+ streamOptions = defaultStreamOptions,
78
+ debug: debugProp,
79
+ ...props
80
+ }: DefaultStoryProps) => {
81
+ const [controller, setController] = useState<MarkdownStreamController | null>(null);
82
+ const [streaming, setStreaming] = useState(false);
83
+ const [debug, setDebug] = useState(debugProp);
84
+
85
+ useEffect(() => {
86
+ if (initialContent) {
87
+ void controller?.append(initialContent);
88
+ }
89
+ }, [controller, initialContent]);
90
+
91
+ useEffect(() => {
92
+ if (!controller || !streaming || !content) {
93
+ return;
94
+ }
95
+
96
+ let cancelled = false;
97
+ void (async () => {
98
+ for await (const chunk of textStream(content + '\n', streamOptions)) {
99
+ if (cancelled) {
100
+ break;
101
+ }
102
+
103
+ await controller.append(chunk);
104
+ }
105
+
106
+ setStreaming(false);
107
+ })();
108
+
109
+ return () => {
110
+ cancelled = true;
111
+ };
112
+ }, [controller, content, streaming]);
113
+
114
+ const handleReset = useCallback(() => {
115
+ setStreaming(false);
116
+ void controller?.setContent('');
117
+ }, [controller]);
118
+
119
+ const handleAppend = useCallback(() => {
120
+ void controller?.append(
121
+ [
122
+ random.lorem.paragraph(),
123
+ `<dom-widget>${random.lorem.paragraphs(3)}</dom-widget>`,
124
+ random.lorem.paragraph(),
125
+ `<react-widget>${random.lorem.paragraphs(3)}</react-widget>`,
126
+ '',
127
+ ].join('\n\n'),
128
+ );
129
+ }, [controller]);
130
+
131
+ return (
132
+ <Panel.Root data-hue={userHue}>
133
+ <Panel.Toolbar asChild>
134
+ <Toolbar.Root>
135
+ <Toolbar.IconButton
136
+ disabled={streaming}
137
+ icon='ph--play--regular'
138
+ iconOnly
139
+ label='Start'
140
+ onClick={() => setStreaming(true)}
141
+ />
142
+ <Toolbar.IconButton
143
+ disabled={!streaming}
144
+ icon='ph--stop--regular'
145
+ iconOnly
146
+ label='Stop'
147
+ onClick={() => setStreaming(false)}
148
+ />
149
+ <Toolbar.IconButton icon='ph--trash--regular' iconOnly label='Reset' onClick={handleReset} />
150
+ <Toolbar.IconButton
151
+ disabled={streaming}
152
+ icon='ph--plus--regular'
153
+ iconOnly
154
+ label='Append'
155
+ onClick={handleAppend}
156
+ />
157
+ <Toolbar.Separator />
158
+ <Input.Root>
159
+ <Input.Label classNames='pr-1'>Debug</Input.Label>
160
+ <Input.Switch checked={debug} onCheckedChange={setDebug} />
161
+ </Input.Root>
162
+ </Toolbar.Root>
163
+ </Panel.Toolbar>
164
+ <Panel.Content>
165
+ <MarkdownStream {...props} debug={debug} ref={setController} />
166
+ </Panel.Content>
167
+ </Panel.Root>
168
+ );
169
+ };
170
+
171
+ const meta = {
172
+ title: 'ui/react-ui-markdown/MarkdownStream',
173
+ render: DefaultStory,
174
+ decorators: [withTheme(), withLayout({ layout: 'column' })],
175
+ parameters: { layout: 'fullscreen' },
176
+ } satisfies Meta<typeof DefaultStory>;
177
+
178
+ export default meta;
179
+
180
+ type Story = StoryObj<typeof meta>;
181
+
182
+ export const Default: Story = {
183
+ args: {
184
+ initialContent: TEXT,
185
+ options: {
186
+ autoScroll: true,
187
+ },
188
+ },
189
+ };
190
+
191
+ export const Streaming: Story = {
192
+ args: {
193
+ registry,
194
+ content: TEXT,
195
+ options: {
196
+ autoScroll: true,
197
+ typewriter: true,
198
+ fader: true,
199
+ cursor: true,
200
+ },
201
+ },
202
+ };
203
+
204
+ export const Widgets: Story = {
205
+ args: {
206
+ registry,
207
+ initialContent: trim`
208
+ # DOM Widget
209
+ <dom-widget>${random.lorem.paragraph()}</dom-widget>
210
+
211
+ # React Widget
212
+ <react-widget>${random.lorem.paragraph()}</react-widget>
213
+ `,
214
+ },
215
+ };