@dust-tt/sparkle 0.2.644 → 0.2.646-rc-1

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 (77) hide show
  1. package/dist/cjs/index.js +1 -1
  2. package/dist/esm/components/DataTable.d.ts +3 -6
  3. package/dist/esm/components/DataTable.d.ts.map +1 -1
  4. package/dist/esm/components/DataTable.js +8 -8
  5. package/dist/esm/components/DataTable.js.map +1 -1
  6. package/dist/esm/components/markdown/BlockquoteBlock.d.ts +3 -1
  7. package/dist/esm/components/markdown/BlockquoteBlock.d.ts.map +1 -1
  8. package/dist/esm/components/markdown/BlockquoteBlock.js +7 -3
  9. package/dist/esm/components/markdown/BlockquoteBlock.js.map +1 -1
  10. package/dist/esm/components/markdown/CodeBlockWithExtendedSupport.d.ts +4 -2
  11. package/dist/esm/components/markdown/CodeBlockWithExtendedSupport.d.ts.map +1 -1
  12. package/dist/esm/components/markdown/CodeBlockWithExtendedSupport.js +11 -6
  13. package/dist/esm/components/markdown/CodeBlockWithExtendedSupport.js.map +1 -1
  14. package/dist/esm/components/markdown/HeaderBlocks.d.ts +24 -0
  15. package/dist/esm/components/markdown/HeaderBlocks.d.ts.map +1 -0
  16. package/dist/esm/components/markdown/HeaderBlocks.js +54 -0
  17. package/dist/esm/components/markdown/HeaderBlocks.js.map +1 -0
  18. package/dist/esm/components/markdown/InputBlock.d.ts +10 -0
  19. package/dist/esm/components/markdown/InputBlock.d.ts.map +1 -0
  20. package/dist/esm/components/markdown/InputBlock.js +26 -0
  21. package/dist/esm/components/markdown/InputBlock.js.map +1 -0
  22. package/dist/esm/components/markdown/LinkBlock.d.ts +10 -0
  23. package/dist/esm/components/markdown/LinkBlock.d.ts.map +1 -0
  24. package/dist/esm/components/markdown/LinkBlock.js +11 -0
  25. package/dist/esm/components/markdown/LinkBlock.js.map +1 -0
  26. package/dist/esm/components/markdown/List.d.ts +17 -3
  27. package/dist/esm/components/markdown/List.d.ts.map +1 -1
  28. package/dist/esm/components/markdown/List.js +21 -7
  29. package/dist/esm/components/markdown/List.js.map +1 -1
  30. package/dist/esm/components/markdown/Markdown.d.ts +0 -8
  31. package/dist/esm/components/markdown/Markdown.d.ts.map +1 -1
  32. package/dist/esm/components/markdown/Markdown.js +39 -62
  33. package/dist/esm/components/markdown/Markdown.js.map +1 -1
  34. package/dist/esm/components/markdown/ParagraphBlock.d.ts +3 -1
  35. package/dist/esm/components/markdown/ParagraphBlock.d.ts.map +1 -1
  36. package/dist/esm/components/markdown/ParagraphBlock.js +7 -3
  37. package/dist/esm/components/markdown/ParagraphBlock.js.map +1 -1
  38. package/dist/esm/components/markdown/PreBlock.d.ts +3 -1
  39. package/dist/esm/components/markdown/PreBlock.d.ts.map +1 -1
  40. package/dist/esm/components/markdown/PreBlock.js +7 -3
  41. package/dist/esm/components/markdown/PreBlock.js.map +1 -1
  42. package/dist/esm/components/markdown/TableBlock.d.ts +17 -11
  43. package/dist/esm/components/markdown/TableBlock.d.ts.map +1 -1
  44. package/dist/esm/components/markdown/TableBlock.js +18 -14
  45. package/dist/esm/components/markdown/TableBlock.js.map +1 -1
  46. package/dist/esm/components/markdown/TextFormattingBlocks.d.ts +10 -0
  47. package/dist/esm/components/markdown/TextFormattingBlocks.d.ts.map +1 -0
  48. package/dist/esm/components/markdown/TextFormattingBlocks.js +12 -0
  49. package/dist/esm/components/markdown/TextFormattingBlocks.js.map +1 -0
  50. package/dist/esm/components/markdown/index.d.ts +4 -0
  51. package/dist/esm/components/markdown/index.d.ts.map +1 -1
  52. package/dist/esm/components/markdown/index.js +4 -0
  53. package/dist/esm/components/markdown/index.js.map +1 -1
  54. package/dist/esm/components/markdown/types.d.ts +13 -0
  55. package/dist/esm/components/markdown/types.d.ts.map +1 -0
  56. package/dist/esm/components/markdown/types.js +2 -0
  57. package/dist/esm/components/markdown/types.js.map +1 -0
  58. package/dist/esm/components/markdown/utils.d.ts +11 -0
  59. package/dist/esm/components/markdown/utils.d.ts.map +1 -1
  60. package/dist/esm/components/markdown/utils.js +21 -0
  61. package/dist/esm/components/markdown/utils.js.map +1 -1
  62. package/package.json +1 -1
  63. package/src/components/DataTable.tsx +2 -18
  64. package/src/components/markdown/BlockquoteBlock.tsx +36 -29
  65. package/src/components/markdown/CodeBlockWithExtendedSupport.tsx +142 -131
  66. package/src/components/markdown/HeaderBlocks.tsx +160 -0
  67. package/src/components/markdown/InputBlock.tsx +60 -0
  68. package/src/components/markdown/LinkBlock.tsx +36 -0
  69. package/src/components/markdown/List.tsx +53 -30
  70. package/src/components/markdown/Markdown.tsx +97 -169
  71. package/src/components/markdown/ParagraphBlock.tsx +18 -12
  72. package/src/components/markdown/PreBlock.tsx +28 -18
  73. package/src/components/markdown/TableBlock.tsx +125 -95
  74. package/src/components/markdown/TextFormattingBlocks.tsx +31 -0
  75. package/src/components/markdown/index.ts +4 -0
  76. package/src/components/markdown/types.ts +5 -0
  77. package/src/components/markdown/utils.ts +37 -0
@@ -2,7 +2,6 @@
2
2
  import React, { useMemo } from "react";
3
3
  import type { Components } from "react-markdown";
4
4
  import ReactMarkdown from "react-markdown";
5
- import type { ReactMarkdownProps } from "react-markdown/lib/ast-to-react";
6
5
  import type { PluggableList } from "react-markdown/lib/react-markdown";
7
6
  import rehypeKatex from "rehype-katex";
8
7
  import remarkDirective from "remark-directive";
@@ -10,32 +9,42 @@ import remarkGfm from "remark-gfm";
10
9
  import remarkMath from "remark-math";
11
10
  import { visit } from "unist-util-visit";
12
11
 
13
- import { Checkbox, Chip } from "@sparkle/components";
14
- import { BlockquoteBlock } from "@sparkle/components/markdown/BlockquoteBlock";
15
- import { CodeBlockWithExtendedSupport } from "@sparkle/components/markdown/CodeBlockWithExtendedSupport";
16
- import { LiBlock, OlBlock, UlBlock } from "@sparkle/components/markdown/List";
12
+ import { Chip } from "@sparkle/components";
13
+ import { MemoBlockquoteBlock } from "@sparkle/components/markdown/BlockquoteBlock";
14
+ import { MemoCodeBlockWithExtendedSupport } from "@sparkle/components/markdown/CodeBlockWithExtendedSupport";
15
+ import {
16
+ markdownHeaderClasses,
17
+ MemoH1Block,
18
+ MemoH2Block,
19
+ MemoH3Block,
20
+ MemoH4Block,
21
+ MemoH5Block,
22
+ MemoH6Block,
23
+ } from "@sparkle/components/markdown/HeaderBlocks";
24
+ import { MemoInputBlock } from "@sparkle/components/markdown/InputBlock";
25
+ import { MemoLinkBlock } from "@sparkle/components/markdown/LinkBlock";
26
+ import {
27
+ MemoLiBlock,
28
+ MemoOlBlock,
29
+ MemoUlBlock,
30
+ } from "@sparkle/components/markdown/List";
17
31
  import { MarkdownContentContext } from "@sparkle/components/markdown/MarkdownContentContext";
18
- import { ParagraphBlock } from "@sparkle/components/markdown/ParagraphBlock";
19
- import { PreBlock } from "@sparkle/components/markdown/PreBlock";
32
+ import { MemoParagraphBlock } from "@sparkle/components/markdown/ParagraphBlock";
33
+ import { MemoPreBlock } from "@sparkle/components/markdown/PreBlock";
20
34
  import {
21
- TableBlock,
22
- TableBodyBlock,
23
- TableDataBlock,
24
- TableHeadBlock,
25
- TableHeaderBlock,
35
+ MemoTableBlock,
36
+ MemoTableBodyBlock,
37
+ MemoTableDataBlock,
38
+ MemoTableHeadBlock,
39
+ MemoTableHeaderBlock,
26
40
  } from "@sparkle/components/markdown/TableBlock";
41
+ import {
42
+ MemoHorizontalRuleBlock,
43
+ MemoStrongBlock,
44
+ } from "@sparkle/components/markdown/TextFormattingBlocks";
27
45
  import { sanitizeContent } from "@sparkle/components/markdown/utils";
28
46
  import { cn } from "@sparkle/lib/utils";
29
47
 
30
- export const markdownHeaderClasses = {
31
- h1: "s-heading-2xl",
32
- h2: "s-heading-xl",
33
- h3: "s-heading-lg",
34
- h4: "s-text-base s-font-semibold",
35
- h5: "s-text-sm s-font-semibold",
36
- h6: "s-text-sm s-font-regular s-italic",
37
- };
38
-
39
48
  const sizes = {
40
49
  p: "s-copy-sm @sm:s-text-base @sm:s-leading-7",
41
50
  ...markdownHeaderClasses,
@@ -89,123 +98,113 @@ export function Markdown({
89
98
  // Memoize markdown components to avoid unnecessary re-renders that disrupt text selection
90
99
  const markdownComponents: Components = useMemo(() => {
91
100
  return {
92
- pre: ({ children }) => <PreBlock>{children}</PreBlock>,
93
- a: LinkBlock,
94
- ul: ({ children }) => (
95
- <UlBlock
101
+ pre: ({ children, node }) => (
102
+ <MemoPreBlock node={node}>{children}</MemoPreBlock>
103
+ ),
104
+ a: MemoLinkBlock,
105
+ ul: ({ children, node }) => (
106
+ <MemoUlBlock
96
107
  textSize={forcedTextSize ? forcedTextSize : sizes.p}
97
108
  textColor={textColor}
109
+ node={node}
98
110
  >
99
111
  {children}
100
- </UlBlock>
112
+ </MemoUlBlock>
101
113
  ),
102
- ol: ({ children, start }) => (
103
- <OlBlock
114
+ ol: ({ children, start, node }) => (
115
+ <MemoOlBlock
104
116
  start={start}
105
117
  textColor={textColor}
106
118
  textSize={forcedTextSize ? forcedTextSize : sizes.p}
119
+ node={node}
107
120
  >
108
121
  {children}
109
- </OlBlock>
122
+ </MemoOlBlock>
110
123
  ),
111
- li: ({ children }) => (
112
- <LiBlock
124
+ li: ({ children, node }) => (
125
+ <MemoLiBlock
113
126
  textColor={textColor}
114
127
  textSize={forcedTextSize ? forcedTextSize : sizes.p}
128
+ node={node}
115
129
  >
116
130
  {children}
117
- </LiBlock>
131
+ </MemoLiBlock>
118
132
  ),
119
- p: ({ children }) => (
120
- <ParagraphBlock
133
+ p: ({ children, node }) => (
134
+ <MemoParagraphBlock
121
135
  textColor={textColor}
122
136
  textSize={forcedTextSize ? forcedTextSize : sizes.p}
137
+ node={node}
123
138
  >
124
139
  {children}
125
- </ParagraphBlock>
140
+ </MemoParagraphBlock>
126
141
  ),
127
- table: TableBlock,
128
- thead: TableHeadBlock,
129
- tbody: TableBodyBlock,
130
- th: TableHeaderBlock,
131
- td: TableDataBlock,
132
- h1: ({ children }) => (
133
- <h1
134
- className={cn(
135
- "s-pb-2 s-pt-4",
136
- forcedTextSize ? forcedTextSize : sizes.h1,
137
- textColor
138
- )}
142
+ table: MemoTableBlock,
143
+ thead: MemoTableHeadBlock,
144
+ tbody: MemoTableBodyBlock,
145
+ th: MemoTableHeaderBlock,
146
+ td: MemoTableDataBlock,
147
+ h1: ({ children, node }) => (
148
+ <MemoH1Block
149
+ textColor={textColor}
150
+ forcedTextSize={forcedTextSize}
151
+ node={node}
139
152
  >
140
153
  {children}
141
- </h1>
154
+ </MemoH1Block>
142
155
  ),
143
- h2: ({ children }) => (
144
- <h2
145
- className={cn(
146
- "s-pb-2 s-pt-4",
147
- forcedTextSize ? forcedTextSize : sizes.h2,
148
- textColor
149
- )}
156
+ h2: ({ children, node }) => (
157
+ <MemoH2Block
158
+ textColor={textColor}
159
+ forcedTextSize={forcedTextSize}
160
+ node={node}
150
161
  >
151
162
  {children}
152
- </h2>
163
+ </MemoH2Block>
153
164
  ),
154
- h3: ({ children }) => (
155
- <h3
156
- className={cn(
157
- "s-pb-2 s-pt-4",
158
- forcedTextSize ? forcedTextSize : sizes.h3,
159
- textColor
160
- )}
165
+ h3: ({ children, node }) => (
166
+ <MemoH3Block
167
+ textColor={textColor}
168
+ forcedTextSize={forcedTextSize}
169
+ node={node}
161
170
  >
162
171
  {children}
163
- </h3>
172
+ </MemoH3Block>
164
173
  ),
165
- h4: ({ children }) => (
166
- <h4
167
- className={cn(
168
- "s-pb-2 s-pt-3",
169
- forcedTextSize ? forcedTextSize : sizes.h4,
170
- textColor
171
- )}
174
+ h4: ({ children, node }) => (
175
+ <MemoH4Block
176
+ textColor={textColor}
177
+ forcedTextSize={forcedTextSize}
178
+ node={node}
172
179
  >
173
180
  {children}
174
- </h4>
181
+ </MemoH4Block>
175
182
  ),
176
- h5: ({ children }) => (
177
- <h5
178
- className={cn(
179
- "s-pb-1.5 s-pt-2.5",
180
- forcedTextSize ? forcedTextSize : sizes.h5,
181
- textColor
182
- )}
183
+ h5: ({ children, node }) => (
184
+ <MemoH5Block
185
+ textColor={textColor}
186
+ forcedTextSize={forcedTextSize}
187
+ node={node}
183
188
  >
184
189
  {children}
185
- </h5>
190
+ </MemoH5Block>
186
191
  ),
187
- h6: ({ children }) => (
188
- <h6
189
- className={cn(
190
- "s-pb-1.5 s-pt-2.5",
191
- forcedTextSize ? forcedTextSize : sizes.h6,
192
- textColor
193
- )}
192
+ h6: ({ children, node }) => (
193
+ <MemoH6Block
194
+ textColor={textColor}
195
+ forcedTextSize={forcedTextSize}
196
+ node={node}
194
197
  >
195
198
  {children}
196
- </h6>
199
+ </MemoH6Block>
197
200
  ),
198
- strong: ({ children }) => (
199
- <strong className="s-font-semibold s-text-foreground dark:s-text-foreground-night">
200
- {children}
201
- </strong>
202
- ),
203
- input: Input,
204
- blockquote: BlockquoteBlock,
205
- hr: () => (
206
- <div className="s-my-6 s-border-b s-border-primary-150 dark:s-border-primary-150-night" />
201
+ strong: ({ children, node }) => (
202
+ <MemoStrongBlock node={node}>{children}</MemoStrongBlock>
207
203
  ),
208
- code: CodeBlockWithExtendedSupport,
204
+ input: MemoInputBlock,
205
+ blockquote: MemoBlockquoteBlock,
206
+ hr: MemoHorizontalRuleBlock,
207
+ code: MemoCodeBlockWithExtendedSupport,
209
208
  ...additionalMarkdownComponents,
210
209
  };
211
210
  }, [textColor, additionalMarkdownComponents]);
@@ -255,74 +254,3 @@ export function Markdown({
255
254
  );
256
255
  }
257
256
  }
258
-
259
- function LinkBlock({
260
- href,
261
- children,
262
- }: {
263
- href?: string;
264
- children: React.ReactNode;
265
- }) {
266
- return (
267
- <a
268
- href={href}
269
- target="_blank"
270
- rel="noopener noreferrer"
271
- className={cn(
272
- "s-break-all s-font-semibold s-transition-all s-duration-200 s-ease-in-out hover:s-underline",
273
- "s-text-highlight dark:s-text-highlight-night",
274
- "hover:s-text-highlight-400 dark:hover:s-text-highlight-400-night",
275
- "active:s-text-highlight-dark dark:active:s-text-highlight-dark-night"
276
- )}
277
- >
278
- {children}
279
- </a>
280
- );
281
- }
282
-
283
- type InputProps = Omit<React.InputHTMLAttributes<HTMLInputElement>, "ref"> &
284
- ReactMarkdownProps & {
285
- ref?: React.Ref<HTMLInputElement>;
286
- };
287
-
288
- function Input({
289
- type,
290
- checked,
291
- className,
292
- onChange,
293
- ref,
294
- ...props
295
- }: InputProps) {
296
- const inputRef = React.useRef<HTMLInputElement>(null);
297
- React.useImperativeHandle(ref, () => inputRef.current!);
298
-
299
- if (type !== "checkbox") {
300
- return (
301
- <input
302
- ref={inputRef}
303
- type={type}
304
- checked={checked}
305
- className={className}
306
- {...props}
307
- />
308
- );
309
- }
310
-
311
- const handleCheckedChange = (isChecked: boolean) => {
312
- onChange?.({
313
- target: { type: "checkbox", checked: isChecked },
314
- } as React.ChangeEvent<HTMLInputElement>);
315
- };
316
-
317
- return (
318
- <div className="s-inline-flex s-items-center">
319
- <Checkbox
320
- ref={inputRef as React.Ref<HTMLButtonElement>}
321
- size="xs"
322
- checked={checked}
323
- className="s-translate-y-[3px]"
324
- onCheckedChange={handleCheckedChange}
325
- />
326
- </div>
327
- );
328
- }
@@ -1,8 +1,11 @@
1
1
  import { cva } from "class-variance-authority";
2
- import React from "react";
2
+ import React, { memo } from "react";
3
3
 
4
4
  import { cn } from "@sparkle/lib";
5
5
 
6
+ import { MarkdownNode } from "./types";
7
+ import { sameNodePosition, sameTextStyling } from "./utils";
8
+
6
9
  export const paragraphBlockVariants = cva([
7
10
  "s-whitespace-pre-wrap s-break-words s-font-normal first:s-pt-0 last:s-pb-0",
8
11
  "s-py-1 @md:s-py-2 @md:s-leading-7",
@@ -12,16 +15,19 @@ interface ParagraphBlockProps {
12
15
  children: React.ReactNode;
13
16
  textColor: string;
14
17
  textSize: string;
18
+ node?: MarkdownNode;
15
19
  }
16
20
 
17
- export function ParagraphBlock({
18
- children,
19
- textColor,
20
- textSize,
21
- }: ParagraphBlockProps) {
22
- return (
23
- <div className={cn(paragraphBlockVariants(), textSize, textColor)}>
24
- {children}
25
- </div>
26
- );
27
- }
21
+ export const MemoParagraphBlock = memo(
22
+ ({ children, textColor, textSize }: ParagraphBlockProps) => {
23
+ return (
24
+ <div className={cn(paragraphBlockVariants(), textSize, textColor)}>
25
+ {children}
26
+ </div>
27
+ );
28
+ },
29
+ (prev, next) =>
30
+ sameNodePosition(prev.node, next.node) && sameTextStyling(prev, next)
31
+ );
32
+
33
+ MemoParagraphBlock.displayName = "ParagraphBlock";
@@ -1,5 +1,8 @@
1
1
  import { cva } from "class-variance-authority";
2
- import React from "react";
2
+ import React, { memo } from "react";
3
+
4
+ import { MarkdownNode } from "./types";
5
+ import { sameNodePosition } from "./utils";
3
6
 
4
7
  export const preBlockVariants = cva(
5
8
  [
@@ -18,25 +21,32 @@ export const preBlockVariants = cva(
18
21
  interface PreBlockProps {
19
22
  children: React.ReactNode;
20
23
  variant?: "surface";
24
+ node?: MarkdownNode;
21
25
  }
22
26
 
23
- export function PreBlock({ children, variant = "surface" }: PreBlockProps) {
24
- const validChildrenContent =
25
- Array.isArray(children) && children[0]
26
- ? children[0].props.children[0]
27
- : null;
28
-
29
- let fallbackData: string | null = null;
30
- if (!validChildrenContent) {
31
- fallbackData =
27
+ export const MemoPreBlock = memo(
28
+ ({ children, variant = "surface" }: PreBlockProps) => {
29
+ const validChildrenContent =
32
30
  Array.isArray(children) && children[0]
33
- ? children[0].props?.node?.data?.meta
31
+ ? children[0].props.children[0]
34
32
  : null;
35
- }
36
33
 
37
- return (
38
- <pre className={preBlockVariants({ variant })}>
39
- {validChildrenContent ? children : fallbackData || children}
40
- </pre>
41
- );
42
- }
34
+ let fallbackData: string | null = null;
35
+ if (!validChildrenContent) {
36
+ fallbackData =
37
+ Array.isArray(children) && children[0]
38
+ ? children[0].props?.node?.data?.meta
39
+ : null;
40
+ }
41
+
42
+ return (
43
+ <pre className={preBlockVariants({ variant })}>
44
+ {validChildrenContent ? children : fallbackData || children}
45
+ </pre>
46
+ );
47
+ },
48
+ (prev, next) =>
49
+ sameNodePosition(prev.node, next.node) && prev.variant === next.variant
50
+ );
51
+
52
+ MemoPreBlock.displayName = "PreBlock";
@@ -1,9 +1,12 @@
1
1
  /* eslint-disable @typescript-eslint/no-explicit-any */
2
- import React, { ReactNode, useMemo } from "react";
2
+ import React, { memo, ReactNode, useMemo } from "react";
3
3
 
4
4
  import { ScrollArea, ScrollBar } from "@sparkle/components";
5
5
  import { ContentBlockWrapper } from "@sparkle/components/markdown/ContentBlockWrapper";
6
6
 
7
+ import { MarkdownNode } from "./types";
8
+ import { sameNodePosition } from "./utils";
9
+
7
10
  const getNodeText = (node: ReactNode): string => {
8
11
  if (["string", "number"].includes(typeof node)) {
9
12
  return node as string;
@@ -18,100 +21,127 @@ const getNodeText = (node: ReactNode): string => {
18
21
  return "";
19
22
  };
20
23
 
21
- export function TableBlock({ children }: { children: React.ReactNode }) {
22
- const tableData = useMemo(() => {
23
- const [headNode, bodyNode] = Array.from(children as [any, any]);
24
- if (
25
- !headNode ||
26
- !bodyNode ||
27
- !("props" in headNode) ||
28
- !("props" in bodyNode)
29
- ) {
30
- return;
31
- }
32
-
33
- const headCells = headNode.props.children[0].props.children.map((c: any) =>
34
- getNodeText(c.props.children)
24
+ export const MemoTableBlock = memo(
25
+ ({ children }: { children: React.ReactNode; node?: MarkdownNode }) => {
26
+ const tableData = useMemo(() => {
27
+ const [headNode, bodyNode] = Array.from(children as [any, any]);
28
+ if (
29
+ !headNode ||
30
+ !bodyNode ||
31
+ !("props" in headNode) ||
32
+ !("props" in bodyNode)
33
+ ) {
34
+ return;
35
+ }
36
+
37
+ const headCells = headNode.props.children[0].props.children.map(
38
+ (c: any) => getNodeText(c.props.children)
39
+ );
40
+
41
+ const headHtml = `<thead><tr>${headCells
42
+ .map((c: any) => `<th><b>${c}</b></th>`)
43
+ .join("")}</tr></thead>`;
44
+ const headPlain = headCells.join("\t");
45
+
46
+ const bodyRows = bodyNode.props.children.map((row: any) =>
47
+ row.props.children.map((cell: any) => {
48
+ const children = cell.props.children;
49
+ return (Array.isArray(children) ? children : [children])
50
+ .map((child: any) =>
51
+ child?.type?.name === "CiteBlock" ? "" : getNodeText(child)
52
+ )
53
+ .join("");
54
+ })
55
+ );
56
+ const bodyHtml = `<tbody>${bodyRows
57
+ .map((row: any) => {
58
+ return `<tr>${row
59
+ .map((cell: any) => `<td>${cell}</td>`)
60
+ .join("")}</tr>`;
61
+ })
62
+ .join("")}</tbody>`;
63
+ const bodyPlain = bodyRows.map((row: any) => row.join("\t")).join("\n");
64
+
65
+ return {
66
+ "text/html": `<table>${headHtml}${bodyHtml}</table>`,
67
+ "text/plain": headPlain + "\n" + bodyPlain,
68
+ };
69
+ }, [children]);
70
+
71
+ return (
72
+ <ContentBlockWrapper
73
+ innerClassName="s-relative s-my-2 s-w-full s-border s-border-border dark:s-border-border-night s-rounded-2xl"
74
+ content={tableData}
75
+ >
76
+ <ScrollArea className="s-w-full s-rounded-2xl">
77
+ <table className="s-w-full">{children}</table>
78
+ <ScrollBar orientation="horizontal" />
79
+ </ScrollArea>
80
+ </ContentBlockWrapper>
35
81
  );
82
+ },
83
+ (prev, next) => sameNodePosition(prev.node, next.node)
84
+ );
36
85
 
37
- const headHtml = `<thead><tr>${headCells
38
- .map((c: any) => `<th><b>${c}</b></th>`)
39
- .join("")}</tr></thead>`;
40
- const headPlain = headCells.join("\t");
41
-
42
- const bodyRows = bodyNode.props.children.map((row: any) =>
43
- row.props.children.map((cell: any) => {
44
- const children = cell.props.children;
45
- return (Array.isArray(children) ? children : [children])
46
- .map((child: any) =>
47
- child?.type?.name === "CiteBlock" ? "" : getNodeText(child)
48
- )
49
- .join("");
50
- })
86
+ MemoTableBlock.displayName = "TableBlock";
87
+
88
+ export const MemoTableHeadBlock = memo(
89
+ ({ children }: { children: React.ReactNode; node?: MarkdownNode }) => {
90
+ return (
91
+ <thead className="s-bg-muted-background s-px-2 s-py-2 dark:s-bg-muted-background-night">
92
+ {children}
93
+ </thead>
51
94
  );
52
- const bodyHtml = `<tbody>${bodyRows
53
- .map((row: any) => {
54
- return `<tr>${row
55
- .map((cell: any) => `<td>${cell}</td>`)
56
- .join("")}</tr>`;
57
- })
58
- .join("")}</tbody>`;
59
- const bodyPlain = bodyRows.map((row: any) => row.join("\t")).join("\n");
60
-
61
- return {
62
- "text/html": `<table>${headHtml}${bodyHtml}</table>`,
63
- "text/plain": headPlain + "\n" + bodyPlain,
64
- };
65
- }, [children]);
66
-
67
- return (
68
- <ContentBlockWrapper
69
- innerClassName="s-relative s-my-2 s-w-full s-border s-border-border dark:s-border-border-night s-rounded-2xl"
70
- content={tableData}
71
- >
72
- <ScrollArea className="s-w-full s-rounded-2xl">
73
- <table className="s-w-full">{children}</table>
74
- <ScrollBar orientation="horizontal" />
75
- </ScrollArea>
76
- </ContentBlockWrapper>
77
- );
78
- }
79
-
80
- export function TableHeadBlock({ children }: { children: React.ReactNode }) {
81
- return (
82
- <thead className="s-bg-muted-background s-px-2 s-py-2 dark:s-bg-muted-background-night">
83
- {children}
84
- </thead>
85
- );
86
- }
87
-
88
- export function TableBodyBlock({ children }: { children: React.ReactNode }) {
89
- return (
90
- <tbody className="s-bg-white dark:s-bg-background-night">{children}</tbody>
91
- );
92
- }
93
-
94
- export function TableHeaderBlock({ children }: { children: React.ReactNode }) {
95
- return (
96
- <th className="s-truncate s-whitespace-nowrap s-break-words s-py-3.5 s-pl-4 s-text-left s-text-xs s-font-semibold s-text-muted-foreground dark:s-text-muted-foreground-night">
97
- {children}
98
- </th>
99
- );
100
- }
101
-
102
- export function TableDataBlock({ children }: { children: React.ReactNode }) {
103
- return (
104
- <td className="s-px-4 s-py-3 s-text-sm s-text-foreground dark:s-text-foreground-night">
105
- {Array.isArray(children) ? (
106
- children.map((child: any, i) => {
107
- if (child === "<br>") {
108
- return <br key={i} />;
109
- }
110
- return <React.Fragment key={i}>{child}</React.Fragment>;
111
- })
112
- ) : (
113
- <>{children}</>
114
- )}
115
- </td>
116
- );
117
- }
95
+ },
96
+ (prev, next) => sameNodePosition(prev.node, next.node)
97
+ );
98
+
99
+ MemoTableHeadBlock.displayName = "TableHeadBlock";
100
+
101
+ export const MemoTableBodyBlock = memo(
102
+ ({ children }: { children: React.ReactNode; node?: MarkdownNode }) => {
103
+ return (
104
+ <tbody className="s-bg-white dark:s-bg-background-night">
105
+ {children}
106
+ </tbody>
107
+ );
108
+ },
109
+ (prev, next) => sameNodePosition(prev.node, next.node)
110
+ );
111
+
112
+ MemoTableBodyBlock.displayName = "TableBodyBlock";
113
+
114
+ export const MemoTableHeaderBlock = memo(
115
+ ({ children }: { children: React.ReactNode; node?: MarkdownNode }) => {
116
+ return (
117
+ <th className="s-truncate s-whitespace-nowrap s-break-words s-py-3.5 s-pl-4 s-text-left s-text-xs s-font-semibold s-text-muted-foreground dark:s-text-muted-foreground-night">
118
+ {children}
119
+ </th>
120
+ );
121
+ },
122
+ (prev, next) => sameNodePosition(prev.node, next.node)
123
+ );
124
+
125
+ MemoTableHeaderBlock.displayName = "TableHeaderBlock";
126
+
127
+ export const MemoTableDataBlock = memo(
128
+ ({ children }: { children: React.ReactNode; node?: MarkdownNode }) => {
129
+ return (
130
+ <td className="s-px-4 s-py-3 s-text-sm s-text-foreground dark:s-text-foreground-night">
131
+ {Array.isArray(children) ? (
132
+ children.map((child: any, i) => {
133
+ if (child === "<br>") {
134
+ return <br key={i} />;
135
+ }
136
+ return <React.Fragment key={i}>{child}</React.Fragment>;
137
+ })
138
+ ) : (
139
+ <>{children}</>
140
+ )}
141
+ </td>
142
+ );
143
+ },
144
+ (prev, next) => sameNodePosition(prev.node, next.node)
145
+ );
146
+
147
+ MemoTableDataBlock.displayName = "TableDataBlock";