@contember/react-richtext-renderer 1.3.0-alpha.10

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 (238) hide show
  1. package/dist/development/RichTextRendererError.cjs +6 -0
  2. package/dist/development/RichTextRendererError.cjs.map +1 -0
  3. package/dist/development/RichTextRendererError.js +6 -0
  4. package/dist/development/RichTextRendererError.js.map +1 -0
  5. package/dist/development/components/RichText.cjs +32 -0
  6. package/dist/development/components/RichText.cjs.map +1 -0
  7. package/dist/development/components/RichText.js +32 -0
  8. package/dist/development/components/RichText.js.map +1 -0
  9. package/dist/development/components/RichTextBlocksRenderer.cjs +30 -0
  10. package/dist/development/components/RichTextBlocksRenderer.cjs.map +1 -0
  11. package/dist/development/components/RichTextBlocksRenderer.js +30 -0
  12. package/dist/development/components/RichTextBlocksRenderer.js.map +1 -0
  13. package/dist/development/components/RichTextFieldRenderer.cjs +28 -0
  14. package/dist/development/components/RichTextFieldRenderer.cjs.map +1 -0
  15. package/dist/development/components/RichTextFieldRenderer.js +28 -0
  16. package/dist/development/components/RichTextFieldRenderer.js.map +1 -0
  17. package/dist/development/components/RichTextRenderer.cjs +14 -0
  18. package/dist/development/components/RichTextRenderer.cjs.map +1 -0
  19. package/dist/development/components/RichTextRenderer.js +14 -0
  20. package/dist/development/components/RichTextRenderer.js.map +1 -0
  21. package/dist/development/hooks/useRichTextBlocksSource.cjs +62 -0
  22. package/dist/development/hooks/useRichTextBlocksSource.cjs.map +1 -0
  23. package/dist/development/hooks/useRichTextBlocksSource.js +62 -0
  24. package/dist/development/hooks/useRichTextBlocksSource.js.map +1 -0
  25. package/dist/development/hooks/useRichTextFieldSource.cjs +26 -0
  26. package/dist/development/hooks/useRichTextFieldSource.cjs.map +1 -0
  27. package/dist/development/hooks/useRichTextFieldSource.js +26 -0
  28. package/dist/development/hooks/useRichTextFieldSource.js.map +1 -0
  29. package/dist/development/index.cjs +17 -0
  30. package/dist/development/index.cjs.map +1 -0
  31. package/dist/development/index.js +17 -0
  32. package/dist/development/index.js.map +1 -0
  33. package/dist/development/internal/components/ElementRenderer.cjs +24 -0
  34. package/dist/development/internal/components/ElementRenderer.cjs.map +1 -0
  35. package/dist/development/internal/components/ElementRenderer.js +24 -0
  36. package/dist/development/internal/components/ElementRenderer.js.map +1 -0
  37. package/dist/development/internal/components/LeafRenderer.cjs +23 -0
  38. package/dist/development/internal/components/LeafRenderer.cjs.map +1 -0
  39. package/dist/development/internal/components/LeafRenderer.js +23 -0
  40. package/dist/development/internal/components/LeafRenderer.js.map +1 -0
  41. package/dist/development/internal/components/RenderElementFallback.cjs +84 -0
  42. package/dist/development/internal/components/RenderElementFallback.cjs.map +1 -0
  43. package/dist/development/internal/components/RenderElementFallback.js +84 -0
  44. package/dist/development/internal/components/RenderElementFallback.js.map +1 -0
  45. package/dist/development/internal/components/RenderLeafFallback.cjs +38 -0
  46. package/dist/development/internal/components/RenderLeafFallback.cjs.map +1 -0
  47. package/dist/development/internal/components/RenderLeafFallback.js +38 -0
  48. package/dist/development/internal/components/RenderLeafFallback.js.map +1 -0
  49. package/dist/development/internal/defaultDeserialize.cjs +14 -0
  50. package/dist/development/internal/defaultDeserialize.cjs.map +1 -0
  51. package/dist/development/internal/defaultDeserialize.js +14 -0
  52. package/dist/development/internal/defaultDeserialize.js.map +1 -0
  53. package/dist/development/internal/renderChildren.cjs +18 -0
  54. package/dist/development/internal/renderChildren.cjs.map +1 -0
  55. package/dist/development/internal/renderChildren.js +18 -0
  56. package/dist/development/internal/renderChildren.js.map +1 -0
  57. package/dist/development/internal/useReferenceMetadata.cjs +37 -0
  58. package/dist/development/internal/useReferenceMetadata.cjs.map +1 -0
  59. package/dist/development/internal/useReferenceMetadata.js +37 -0
  60. package/dist/development/internal/useReferenceMetadata.js.map +1 -0
  61. package/dist/production/RichTextRendererError.cjs +6 -0
  62. package/dist/production/RichTextRendererError.cjs.map +1 -0
  63. package/dist/production/RichTextRendererError.js +6 -0
  64. package/dist/production/RichTextRendererError.js.map +1 -0
  65. package/dist/production/components/RichText.cjs +32 -0
  66. package/dist/production/components/RichText.cjs.map +1 -0
  67. package/dist/production/components/RichText.js +32 -0
  68. package/dist/production/components/RichText.js.map +1 -0
  69. package/dist/production/components/RichTextBlocksRenderer.cjs +30 -0
  70. package/dist/production/components/RichTextBlocksRenderer.cjs.map +1 -0
  71. package/dist/production/components/RichTextBlocksRenderer.js +30 -0
  72. package/dist/production/components/RichTextBlocksRenderer.js.map +1 -0
  73. package/dist/production/components/RichTextFieldRenderer.cjs +28 -0
  74. package/dist/production/components/RichTextFieldRenderer.cjs.map +1 -0
  75. package/dist/production/components/RichTextFieldRenderer.js +28 -0
  76. package/dist/production/components/RichTextFieldRenderer.js.map +1 -0
  77. package/dist/production/components/RichTextRenderer.cjs +14 -0
  78. package/dist/production/components/RichTextRenderer.cjs.map +1 -0
  79. package/dist/production/components/RichTextRenderer.js +14 -0
  80. package/dist/production/components/RichTextRenderer.js.map +1 -0
  81. package/dist/production/hooks/useRichTextBlocksSource.cjs +62 -0
  82. package/dist/production/hooks/useRichTextBlocksSource.cjs.map +1 -0
  83. package/dist/production/hooks/useRichTextBlocksSource.js +62 -0
  84. package/dist/production/hooks/useRichTextBlocksSource.js.map +1 -0
  85. package/dist/production/hooks/useRichTextFieldSource.cjs +26 -0
  86. package/dist/production/hooks/useRichTextFieldSource.cjs.map +1 -0
  87. package/dist/production/hooks/useRichTextFieldSource.js +26 -0
  88. package/dist/production/hooks/useRichTextFieldSource.js.map +1 -0
  89. package/dist/production/index.cjs +17 -0
  90. package/dist/production/index.cjs.map +1 -0
  91. package/dist/production/index.js +17 -0
  92. package/dist/production/index.js.map +1 -0
  93. package/dist/production/internal/components/ElementRenderer.cjs +24 -0
  94. package/dist/production/internal/components/ElementRenderer.cjs.map +1 -0
  95. package/dist/production/internal/components/ElementRenderer.js +24 -0
  96. package/dist/production/internal/components/ElementRenderer.js.map +1 -0
  97. package/dist/production/internal/components/LeafRenderer.cjs +23 -0
  98. package/dist/production/internal/components/LeafRenderer.cjs.map +1 -0
  99. package/dist/production/internal/components/LeafRenderer.js +23 -0
  100. package/dist/production/internal/components/LeafRenderer.js.map +1 -0
  101. package/dist/production/internal/components/RenderElementFallback.cjs +84 -0
  102. package/dist/production/internal/components/RenderElementFallback.cjs.map +1 -0
  103. package/dist/production/internal/components/RenderElementFallback.js +84 -0
  104. package/dist/production/internal/components/RenderElementFallback.js.map +1 -0
  105. package/dist/production/internal/components/RenderLeafFallback.cjs +38 -0
  106. package/dist/production/internal/components/RenderLeafFallback.cjs.map +1 -0
  107. package/dist/production/internal/components/RenderLeafFallback.js +38 -0
  108. package/dist/production/internal/components/RenderLeafFallback.js.map +1 -0
  109. package/dist/production/internal/defaultDeserialize.cjs +14 -0
  110. package/dist/production/internal/defaultDeserialize.cjs.map +1 -0
  111. package/dist/production/internal/defaultDeserialize.js +14 -0
  112. package/dist/production/internal/defaultDeserialize.js.map +1 -0
  113. package/dist/production/internal/renderChildren.cjs +18 -0
  114. package/dist/production/internal/renderChildren.cjs.map +1 -0
  115. package/dist/production/internal/renderChildren.js +18 -0
  116. package/dist/production/internal/renderChildren.js.map +1 -0
  117. package/dist/production/internal/useReferenceMetadata.cjs +37 -0
  118. package/dist/production/internal/useReferenceMetadata.cjs.map +1 -0
  119. package/dist/production/internal/useReferenceMetadata.js +37 -0
  120. package/dist/production/internal/useReferenceMetadata.js.map +1 -0
  121. package/dist/types/RichTextRendererError.d.ts +3 -0
  122. package/dist/types/RichTextRendererError.d.ts.map +1 -0
  123. package/dist/types/components/RichText.d.ts +13 -0
  124. package/dist/types/components/RichText.d.ts.map +1 -0
  125. package/dist/types/components/RichTextBlocksRenderer.d.ts +10 -0
  126. package/dist/types/components/RichTextBlocksRenderer.d.ts.map +1 -0
  127. package/dist/types/components/RichTextFieldRenderer.d.ts +10 -0
  128. package/dist/types/components/RichTextFieldRenderer.d.ts.map +1 -0
  129. package/dist/types/components/RichTextRenderer.d.ts +12 -0
  130. package/dist/types/components/RichTextRenderer.d.ts.map +1 -0
  131. package/dist/types/components/index.d.ts +5 -0
  132. package/dist/types/components/index.d.ts.map +1 -0
  133. package/dist/types/hooks/index.d.ts +3 -0
  134. package/dist/types/hooks/index.d.ts.map +1 -0
  135. package/dist/types/hooks/useRichTextBlocksSource.d.ts +3 -0
  136. package/dist/types/hooks/useRichTextBlocksSource.d.ts.map +1 -0
  137. package/dist/types/hooks/useRichTextFieldSource.d.ts +3 -0
  138. package/dist/types/hooks/useRichTextFieldSource.d.ts.map +1 -0
  139. package/dist/types/index.d.ts +5 -0
  140. package/dist/types/index.d.ts.map +1 -0
  141. package/dist/types/internal/components/ElementRenderer.d.ts +14 -0
  142. package/dist/types/internal/components/ElementRenderer.d.ts.map +1 -0
  143. package/dist/types/internal/components/LeafRenderer.d.ts +12 -0
  144. package/dist/types/internal/components/LeafRenderer.d.ts.map +1 -0
  145. package/dist/types/internal/components/RenderElementFallback.d.ts +14 -0
  146. package/dist/types/internal/components/RenderElementFallback.d.ts.map +1 -0
  147. package/dist/types/internal/components/RenderLeafFallback.d.ts +6 -0
  148. package/dist/types/internal/components/RenderLeafFallback.d.ts.map +1 -0
  149. package/dist/types/internal/defaultDeserialize.d.ts +5 -0
  150. package/dist/types/internal/defaultDeserialize.d.ts.map +1 -0
  151. package/dist/types/internal/renderChildren.d.ts +8 -0
  152. package/dist/types/internal/renderChildren.d.ts.map +1 -0
  153. package/dist/types/internal/useReferenceMetadata.d.ts +9 -0
  154. package/dist/types/internal/useReferenceMetadata.d.ts.map +1 -0
  155. package/dist/types/tsconfig.tsbuildinfo +1 -0
  156. package/dist/types/types/RenderChildren.d.ts +9 -0
  157. package/dist/types/types/RenderChildren.d.ts.map +1 -0
  158. package/dist/types/types/RichTextBlock.d.ts +8 -0
  159. package/dist/types/types/RichTextBlock.d.ts.map +1 -0
  160. package/dist/types/types/RichTextBlockSource.d.ts +9 -0
  161. package/dist/types/types/RichTextBlockSource.d.ts.map +1 -0
  162. package/dist/types/types/RichTextFieldSource.d.ts +6 -0
  163. package/dist/types/types/RichTextFieldSource.d.ts.map +1 -0
  164. package/dist/types/types/RichTextReference.d.ts +5 -0
  165. package/dist/types/types/RichTextReference.d.ts.map +1 -0
  166. package/dist/types/types/RichTextReferenceMetadata.d.ts +15 -0
  167. package/dist/types/types/RichTextReferenceMetadata.d.ts.map +1 -0
  168. package/dist/types/types/RichTextRenderingOptions.d.ts +14 -0
  169. package/dist/types/types/RichTextRenderingOptions.d.ts.map +1 -0
  170. package/dist/types/types/builtin/BuiltinElements.d.ts +48 -0
  171. package/dist/types/types/builtin/BuiltinElements.d.ts.map +1 -0
  172. package/dist/types/types/builtin/BuiltinLeaves.d.ts +21 -0
  173. package/dist/types/types/builtin/BuiltinLeaves.d.ts.map +1 -0
  174. package/dist/types/types/builtin/index.d.ts +3 -0
  175. package/dist/types/types/builtin/index.d.ts.map +1 -0
  176. package/dist/types/types/custom/ReferenceRenderer.d.ts +17 -0
  177. package/dist/types/types/custom/ReferenceRenderer.d.ts.map +1 -0
  178. package/dist/types/types/custom/RenderBlock.d.ts +7 -0
  179. package/dist/types/types/custom/RenderBlock.d.ts.map +1 -0
  180. package/dist/types/types/custom/RenderElement.d.ts +24 -0
  181. package/dist/types/types/custom/RenderElement.d.ts.map +1 -0
  182. package/dist/types/types/custom/RenderLeaf.d.ts +11 -0
  183. package/dist/types/types/custom/RenderLeaf.d.ts.map +1 -0
  184. package/dist/types/types/custom/index.d.ts +5 -0
  185. package/dist/types/types/custom/index.d.ts.map +1 -0
  186. package/dist/types/types/index.d.ts +11 -0
  187. package/dist/types/types/index.d.ts.map +1 -0
  188. package/dist/types/types/structure/RichTextChild.d.ts +5 -0
  189. package/dist/types/types/structure/RichTextChild.d.ts.map +1 -0
  190. package/dist/types/types/structure/RichTextElement.d.ts +8 -0
  191. package/dist/types/types/structure/RichTextElement.d.ts.map +1 -0
  192. package/dist/types/types/structure/RichTextLeaf.d.ts +4 -0
  193. package/dist/types/types/structure/RichTextLeaf.d.ts.map +1 -0
  194. package/dist/types/types/structure/RootEditorNode.d.ts +8 -0
  195. package/dist/types/types/structure/RootEditorNode.d.ts.map +1 -0
  196. package/dist/types/types/structure/index.d.ts +5 -0
  197. package/dist/types/types/structure/index.d.ts.map +1 -0
  198. package/package.json +50 -0
  199. package/readme.md +106 -0
  200. package/src/RichTextRendererError.ts +1 -0
  201. package/src/components/RichText.tsx +52 -0
  202. package/src/components/RichTextBlocksRenderer.tsx +40 -0
  203. package/src/components/RichTextFieldRenderer.tsx +42 -0
  204. package/src/components/RichTextRenderer.tsx +31 -0
  205. package/src/components/index.ts +4 -0
  206. package/src/hooks/index.ts +2 -0
  207. package/src/hooks/useRichTextBlocksSource.ts +75 -0
  208. package/src/hooks/useRichTextFieldSource.ts +26 -0
  209. package/src/index.ts +6 -0
  210. package/src/internal/components/ElementRenderer.tsx +48 -0
  211. package/src/internal/components/LeafRenderer.tsx +36 -0
  212. package/src/internal/components/RenderElementFallback.tsx +153 -0
  213. package/src/internal/components/RenderLeafFallback.tsx +43 -0
  214. package/src/internal/defaultDeserialize.ts +19 -0
  215. package/src/internal/renderChildren.tsx +37 -0
  216. package/src/internal/useReferenceMetadata.ts +62 -0
  217. package/src/tsconfig.json +6 -0
  218. package/src/types/RenderChildren.ts +16 -0
  219. package/src/types/RichTextBlock.ts +11 -0
  220. package/src/types/RichTextBlockSource.ts +10 -0
  221. package/src/types/RichTextFieldSource.ts +6 -0
  222. package/src/types/RichTextReference.ts +6 -0
  223. package/src/types/RichTextReferenceMetadata.ts +27 -0
  224. package/src/types/RichTextRenderingOptions.ts +23 -0
  225. package/src/types/builtin/BuiltinElements.ts +111 -0
  226. package/src/types/builtin/BuiltinLeaves.ts +33 -0
  227. package/src/types/builtin/index.ts +2 -0
  228. package/src/types/custom/ReferenceRenderer.ts +33 -0
  229. package/src/types/custom/RenderBlock.ts +8 -0
  230. package/src/types/custom/RenderElement.ts +37 -0
  231. package/src/types/custom/RenderLeaf.ts +14 -0
  232. package/src/types/custom/index.ts +4 -0
  233. package/src/types/index.ts +11 -0
  234. package/src/types/structure/RichTextChild.ts +11 -0
  235. package/src/types/structure/RichTextElement.ts +11 -0
  236. package/src/types/structure/RichTextLeaf.ts +3 -0
  237. package/src/types/structure/RootEditorNode.ts +11 -0
  238. package/src/types/structure/index.ts +4 -0
@@ -0,0 +1,153 @@
1
+ import { createElement, ReactElement } from 'react'
2
+ import type { BuiltinElements, RichTextReferenceElement, RichTextTableRowElement } from '../../types/builtin/BuiltinElements'
3
+ import { renderChildren } from '../renderChildren'
4
+ import { useReferenceMetadata } from '../useReferenceMetadata'
5
+ import type { RichTextElement } from '../../types/structure/RichTextElement'
6
+ import type { RichTextLeaf } from '../../types/structure/RichTextLeaf'
7
+ import { RichTextRendererError } from '../../RichTextRendererError'
8
+ import { RichTextBlock } from '../../types/RichTextBlock'
9
+ import { RichTextRenderingOptions } from '../../types/RichTextRenderingOptions'
10
+
11
+ export interface RenderElementFallbackProps<
12
+ CustomElements extends RichTextElement = never,
13
+ CustomLeaves extends RichTextLeaf = RichTextLeaf,
14
+ > {
15
+ element: BuiltinElements<CustomElements, CustomLeaves>
16
+ children: ReactElement
17
+ options: RichTextRenderingOptions<CustomElements, CustomLeaves>
18
+ block: RichTextBlock<CustomElements, CustomLeaves>
19
+ }
20
+
21
+ const getElementDataAttributes = <
22
+ CustomElements extends RichTextElement = never,
23
+ CustomLeaves extends RichTextLeaf = RichTextLeaf,
24
+ >(
25
+ element: RichTextElement<CustomElements, CustomLeaves>,
26
+ attributeNamePrefix: string = 'contember-',
27
+ ): {
28
+ [dataAttribute: string]: string | number | boolean
29
+ } => {
30
+ const { children, referenceId, ...extendedSpecifics } = element
31
+
32
+ return Object.fromEntries(
33
+ Object.entries(extendedSpecifics)
34
+ .filter(([, value]) => {
35
+ const t = typeof value
36
+ return t === 'string' || t === 'number' || t === 'boolean'
37
+ })
38
+ .map(([attribute, value]) => [`data-${attributeNamePrefix}${attribute.toLowerCase()}`, value]),
39
+ )
40
+ }
41
+
42
+ export function RenderElementFallback<
43
+ CustomElements extends RichTextElement = never,
44
+ CustomLeaves extends RichTextLeaf = RichTextLeaf,
45
+ >({ element, children, options, block }: RenderElementFallbackProps<CustomElements, CustomLeaves>) {
46
+ const attributes = getElementDataAttributes(element, options.attributeNamePrefix)
47
+
48
+ switch (element.type) {
49
+ case 'anchor':
50
+ return (
51
+ <a {...attributes} href={element.href}>
52
+ {children}
53
+ </a>
54
+ )
55
+ case 'heading':
56
+ return createElement(`h${element.level}`, attributes, children) // TODO numbered
57
+ case 'horizontalRule':
58
+ return <hr {...attributes} />
59
+ case 'listItem':
60
+ return <li {...attributes}>{children}</li>
61
+ case 'orderedList':
62
+ return <ol {...attributes}>{children}</ol>
63
+ case 'paragraph':
64
+ return <p {...attributes}>{children}</p>
65
+ case 'reference': {
66
+ return <ReferenceElementFallback element={element} children={children} options={options} block={block} />
67
+ }
68
+ case 'scrollTarget':
69
+ return (
70
+ <span {...attributes} id={element.identifier}>
71
+ {children}
72
+ </span>
73
+ )
74
+ case 'table': {
75
+ const firstRow = element.children[0] as RichTextTableRowElement<CustomElements, CustomLeaves> | undefined
76
+ if (!firstRow || firstRow.headerScope !== 'table') {
77
+ return (
78
+ <table {...attributes}>
79
+ <tbody>{children}</tbody>
80
+ </table>
81
+ )
82
+ }
83
+ return (
84
+ <table {...attributes}>
85
+ <thead>{renderChildren<CustomElements, CustomLeaves>([firstRow], options, block)}</thead>
86
+ <tbody>{renderChildren<CustomElements, CustomLeaves>(element.children.slice(1) as any, options, block)}</tbody>
87
+ </table>
88
+ )
89
+ }
90
+ case 'tableRow':
91
+ return <tr {...attributes}>{children}</tr>
92
+ case 'tableCell': {
93
+ if (element.headerScope) {
94
+ return (
95
+ <th {...attributes} scope={element.headerScope}>
96
+ {children}
97
+ </th>
98
+ )
99
+ }
100
+ return <td {...attributes}>{children}</td>
101
+ }
102
+ case 'unorderedList':
103
+ return <ul {...attributes}>{children}</ul>
104
+ default: {
105
+ if (import.meta.env.DEV) {
106
+ throw new RichTextRendererError(
107
+ `RichTextRenderer: unknown element of type '${(element as { type: string }).type}'.`,
108
+ )
109
+ } else {
110
+ return children // At least render the text contents
111
+ }
112
+ }
113
+ }
114
+ }
115
+
116
+ type ReferenceElementFallbackProps<CustomElements extends RichTextElement = never, CustomLeaves extends RichTextLeaf = RichTextLeaf> = {
117
+ element: RichTextReferenceElement<CustomElements, CustomLeaves>;
118
+ children: ReactElement
119
+ options: RichTextRenderingOptions<CustomElements, CustomLeaves>
120
+ block: RichTextBlock<CustomElements, CustomLeaves>
121
+ }
122
+
123
+ function ReferenceElementFallback<
124
+ CustomElements extends RichTextElement = never,
125
+ CustomLeaves extends RichTextLeaf = RichTextLeaf,
126
+ >({ element, children, options, block }: ReferenceElementFallbackProps<CustomElements, CustomLeaves>) {
127
+ const elementMetadata = useReferenceMetadata<CustomElements, CustomLeaves>(element, options, block, true)
128
+
129
+ if (
130
+ elementMetadata.referenceRenderer === undefined ||
131
+ elementMetadata.referenceType === undefined ||
132
+ elementMetadata.reference === undefined
133
+ ) {
134
+ return children // At least render the text contents
135
+ }
136
+
137
+ let Renderer = elementMetadata.referenceRenderer
138
+ return (
139
+ <>
140
+ <Renderer
141
+ referenceType={elementMetadata.referenceType}
142
+ referenceRenderer={elementMetadata.referenceRenderer}
143
+ reference={elementMetadata.reference}
144
+ formatVersion={block.content.formatVersion}
145
+ block={block}
146
+ options={options}
147
+ element={element}
148
+ >
149
+ {children}
150
+ </Renderer>
151
+ </>
152
+ )
153
+ }
@@ -0,0 +1,43 @@
1
+ import { Fragment, ReactNode } from 'react'
2
+ import type { BuiltinLeaves } from '../../types/builtin/BuiltinLeaves'
3
+
4
+ export interface RenderLeafFallbackProps {
5
+ leaf: BuiltinLeaves
6
+ }
7
+
8
+ function jsxN2br(text: string): ReactNode {
9
+ const lines = text.split('\n')
10
+ if (lines.length <= 1) {
11
+ return text
12
+ }
13
+ return lines.map((line, i) => (
14
+ <Fragment key={i}>
15
+ {!!i && <br />}
16
+ {line}
17
+ </Fragment>
18
+ ))
19
+ }
20
+
21
+ export function RenderLeafFallback({ leaf }: RenderLeafFallbackProps) {
22
+ let element = jsxN2br(leaf.text)
23
+
24
+ if ('isCode' in leaf && leaf.isCode === true) {
25
+ element = <code>{element}</code>
26
+ }
27
+ if ('isStruckThrough' in leaf && leaf.isStruckThrough === true) {
28
+ element = <s>{element}</s>
29
+ }
30
+ if ('isHighlighted' in leaf && leaf.isHighlighted === true) {
31
+ element = <em>{element}</em>
32
+ }
33
+ if ('isUnderlined' in leaf && leaf.isUnderlined === true) {
34
+ element = <u>{element}</u>
35
+ }
36
+ if ('isItalic' in leaf && leaf.isItalic === true) {
37
+ element = <i>{element}</i>
38
+ }
39
+ if ('isBold' in leaf && leaf.isBold === true) {
40
+ element = <b>{element}</b>
41
+ }
42
+ return <>{element}</>
43
+ }
@@ -0,0 +1,19 @@
1
+ import type { RichTextElement } from '../types/structure/RichTextElement'
2
+ import type { RichTextLeaf } from '../types/structure/RichTextLeaf'
3
+ import type { RootEditorNode } from '../types/structure/RootEditorNode'
4
+
5
+ export const defaultDeserialize = <
6
+ CustomElements extends RichTextElement = never,
7
+ CustomLeaves extends RichTextLeaf = RichTextLeaf,
8
+ >(
9
+ source: string,
10
+ ): RootEditorNode<CustomElements, CustomLeaves> => {
11
+ try {
12
+ return JSON.parse(source)
13
+ } catch (e) {
14
+ return {
15
+ formatVersion: 0,
16
+ children: [],
17
+ }
18
+ }
19
+ }
@@ -0,0 +1,37 @@
1
+ import type { ReactElement } from 'react'
2
+ import { ElementRenderer } from './components/ElementRenderer'
3
+ import { LeafRenderer } from './components/LeafRenderer'
4
+ import type { RichTextElement } from '../types/structure/RichTextElement'
5
+ import type { RichTextLeaf } from '../types/structure/RichTextLeaf'
6
+ import { RichTextRenderingOptions } from '../types/RichTextRenderingOptions'
7
+ import { RichTextBlock } from '../types/RichTextBlock'
8
+ import { RichTextChild } from '../types/structure/RichTextChild'
9
+
10
+ export const renderChildren = <
11
+ CustomElements extends RichTextElement = never,
12
+ CustomLeaves extends RichTextLeaf = RichTextLeaf,
13
+ >(
14
+ children:
15
+ | RichTextChild<CustomElements, CustomLeaves>
16
+ | readonly RichTextChild<CustomElements, CustomLeaves>[],
17
+ options: RichTextRenderingOptions<CustomElements, CustomLeaves>,
18
+ block: RichTextBlock<CustomElements, CustomLeaves>,
19
+ ): ReactElement => {
20
+ return (
21
+ <>
22
+ {(Array.isArray(children) ? children : [children]).map((child, i) => {
23
+ if ('text' in child) {
24
+ return <LeafRenderer<CustomElements, CustomLeaves> key={i} leaf={child} options={options} block={block} />
25
+ }
26
+ if ('children' in child) {
27
+ return (
28
+ <ElementRenderer<CustomElements, CustomLeaves> key={i} element={child} options={options} block={block}>
29
+ {renderChildren<CustomElements, CustomLeaves>(child.children as typeof children, options, block)}
30
+ </ElementRenderer>
31
+ )
32
+ }
33
+ return null // Throw?
34
+ })}
35
+ </>
36
+ )
37
+ }
@@ -0,0 +1,62 @@
1
+ import type { BuiltinElements } from '../types/builtin/BuiltinElements'
2
+ import type { RichTextElement } from '../types/structure/RichTextElement'
3
+ import type { RichTextReferenceMetadata } from '../types/RichTextReferenceMetadata'
4
+ import { RichTextReferenceEmptyMetadata } from '../types/RichTextReferenceMetadata'
5
+ import type { RichTextLeaf } from '../types/structure/RichTextLeaf'
6
+ import type { RichTextReference } from '../types/RichTextReference'
7
+ import { RichTextRendererError } from '../RichTextRendererError'
8
+ import { RichTextBlock } from '../types/RichTextBlock'
9
+ import { RichTextRenderingOptions } from '../types/RichTextRenderingOptions'
10
+ import { useMemo } from 'react'
11
+
12
+ const emptyReference: RichTextReferenceEmptyMetadata = {
13
+ reference: undefined,
14
+ referenceType: undefined,
15
+ referenceRenderer: undefined,
16
+ }
17
+ export const useReferenceMetadata = <
18
+ CustomElements extends RichTextElement = never,
19
+ CustomLeaves extends RichTextLeaf = RichTextLeaf,
20
+ Reference extends RichTextReference = RichTextReference,
21
+ >(
22
+ element: CustomElements | BuiltinElements<CustomElements, CustomLeaves>,
23
+ options: RichTextRenderingOptions<CustomElements, CustomLeaves, Reference>,
24
+ block: RichTextBlock<CustomElements, CustomLeaves>,
25
+ expectReference: boolean = false,
26
+ ): RichTextReferenceMetadata<CustomElements, CustomLeaves, Reference> => {
27
+ const undefinedReferenceHandler = options.undefinedReferenceHandler
28
+ const referenceRenderers = options.referenceRenderers
29
+
30
+ return useMemo(() => {
31
+ const id = element['referenceId']
32
+
33
+ if (typeof id !== 'string') {
34
+ if (import.meta.env.DEV && expectReference) {
35
+ throw new RichTextRendererError(
36
+ `RichTextRenderer: Expected element to have a referenceId.`,
37
+ )
38
+ }
39
+ return emptyReference
40
+ }
41
+
42
+ const reference: Reference | undefined = block.references?.[id] as Reference | undefined
43
+
44
+ if (reference === undefined) {
45
+ if (undefinedReferenceHandler) {
46
+ return undefinedReferenceHandler(id) ?? emptyReference
47
+ } else {
48
+ throw new RichTextRendererError(
49
+ `RichTextRenderer: Cannot find reference id '${id}'`,
50
+ )
51
+ }
52
+ }
53
+
54
+ const referenceRenderer = referenceRenderers?.[reference.type]
55
+
56
+ return {
57
+ reference,
58
+ referenceType: reference.type,
59
+ referenceRenderer,
60
+ }
61
+ }, [block.references, element, expectReference, referenceRenderers, undefinedReferenceHandler])
62
+ }
@@ -0,0 +1,6 @@
1
+ {
2
+ "extends": "../../../tsconfig.settings.json",
3
+ "compilerOptions": {
4
+ "outDir": "../dist/types"
5
+ }
6
+ }
@@ -0,0 +1,16 @@
1
+ import { RichTextChild, RichTextElement, RichTextLeaf } from './structure'
2
+ import { RichTextRenderingOptions } from './RichTextRenderingOptions'
3
+ import { ReactElement } from 'react'
4
+
5
+ export type RenderChildren<
6
+ CustomElements extends RichTextElement = never,
7
+ CustomLeaves extends RichTextLeaf = RichTextLeaf,
8
+ > = (
9
+ children:
10
+ | RichTextChild<CustomElements, CustomLeaves>
11
+ | readonly RichTextChild<CustomElements, CustomLeaves>[],
12
+ /**
13
+ * @deprecated No need to pass this anymore.
14
+ */
15
+ options?: RichTextRenderingOptions<CustomElements, CustomLeaves>,
16
+ ) => ReactElement
@@ -0,0 +1,11 @@
1
+ import type { RichTextElement, RichTextLeaf, RootEditorNode } from './structure'
2
+ import type { RichTextReference } from './RichTextReference'
3
+
4
+ export interface RichTextBlock<
5
+ CustomElements extends RichTextElement = never,
6
+ CustomLeaves extends RichTextLeaf = RichTextLeaf,
7
+ > {
8
+ content: RootEditorNode<CustomElements, CustomLeaves>
9
+ references: Record<string, RichTextReference> | undefined
10
+ id: string | undefined
11
+ }
@@ -0,0 +1,10 @@
1
+ import { RichTextElement, RichTextLeaf, RootEditorNode } from './structure'
2
+
3
+ export type RichTextBlockSource<CustomElements extends RichTextElement = never, CustomLeaves extends RichTextLeaf = RichTextLeaf> = {
4
+ blocks: readonly Readonly<Record<string, unknown>>[]
5
+ sourceField?: string
6
+ referencesField?: string
7
+ referenceDiscriminationField?: string
8
+
9
+ deserialize?: (source: string) => RootEditorNode<CustomElements, CustomLeaves>
10
+ }
@@ -0,0 +1,6 @@
1
+ import { RichTextElement, RichTextLeaf, RootEditorNode } from './structure'
2
+
3
+ export interface RichTextFieldSource<CustomElements extends RichTextElement, CustomLeaves extends RichTextLeaf> {
4
+ source: RootEditorNode<CustomElements, CustomLeaves> | string | null
5
+ deserialize?: (source: string) => RootEditorNode<CustomElements, CustomLeaves>
6
+ }
@@ -0,0 +1,6 @@
1
+ export type RichTextReference =
2
+ & {
3
+ id: string
4
+ type: string
5
+ }
6
+ & Record<string, unknown>
@@ -0,0 +1,27 @@
1
+ import type { RichTextElement, RichTextLeaf } from './structure'
2
+ import type { RichTextReference } from './RichTextReference'
3
+ import { ReferenceRenderer } from './custom'
4
+
5
+ export type RichTextReferenceMetadata<
6
+ CustomElements extends RichTextElement = never,
7
+ CustomLeaves extends RichTextLeaf = RichTextLeaf,
8
+ Reference extends RichTextReference = RichTextReference,
9
+ > =
10
+ | RichTextReferenceFilledMetadata<CustomElements, CustomLeaves, Reference>
11
+ | RichTextReferenceEmptyMetadata
12
+
13
+ export interface RichTextReferenceFilledMetadata<
14
+ CustomElements extends RichTextElement = never,
15
+ CustomLeaves extends RichTextLeaf = RichTextLeaf,
16
+ Reference extends RichTextReference = RichTextReference,
17
+ > {
18
+ reference: Reference
19
+ referenceType: string
20
+ referenceRenderer?: ReferenceRenderer<Reference, CustomElements, CustomLeaves>
21
+ }
22
+
23
+ export interface RichTextReferenceEmptyMetadata {
24
+ reference: undefined
25
+ referenceType: undefined
26
+ referenceRenderer: undefined
27
+ }
@@ -0,0 +1,23 @@
1
+ import { RichTextElement, RichTextLeaf } from './structure'
2
+ import { ReferenceRendererMap, RenderBlock, RenderElement, RenderLeaf } from './custom'
3
+ import { RichTextReference } from './RichTextReference'
4
+ import { RichTextReferenceMetadata } from './RichTextReferenceMetadata'
5
+
6
+ export type UndefinedReferenceHandler<
7
+ CustomElements extends RichTextElement = never,
8
+ CustomLeaves extends RichTextLeaf = RichTextLeaf,
9
+ Reference extends RichTextReference = RichTextReference
10
+ > = (referenceId: string) => void | RichTextReferenceMetadata<CustomElements, CustomLeaves, Reference>
11
+
12
+ export type RichTextRenderingOptions<
13
+ CustomElements extends RichTextElement = never,
14
+ CustomLeaves extends RichTextLeaf = RichTextLeaf,
15
+ Reference extends RichTextReference = RichTextReference,
16
+ > = {
17
+ renderElement?: RenderElement<CustomElements, CustomLeaves>
18
+ renderLeaf?: RenderLeaf<CustomLeaves>
19
+ renderBlock?: RenderBlock
20
+ referenceRenderers?: ReferenceRendererMap<any, CustomElements, CustomLeaves>
21
+ undefinedReferenceHandler?: UndefinedReferenceHandler<CustomElements, CustomLeaves, Reference>
22
+ attributeNamePrefix?: string
23
+ }
@@ -0,0 +1,111 @@
1
+ import type { RichTextElement, RichTextLeaf } from '../structure'
2
+
3
+ export type BuiltinElements<
4
+ CustomElements extends RichTextElement = never,
5
+ CustomLeaves extends RichTextLeaf = RichTextLeaf,
6
+ > =
7
+ | RichTextAnchorElement<CustomElements, CustomLeaves>
8
+ | RichTextHeadingElement<CustomElements, CustomLeaves>
9
+ | RichTextHorizontalRuleElement<CustomElements, CustomLeaves>
10
+ | RichTextListItemElement<CustomElements, CustomLeaves>
11
+ | RichTextOrderedListElement<CustomElements, CustomLeaves>
12
+ | RichTextParagraphElement<CustomElements, CustomLeaves>
13
+ | RichTextReferenceElement<CustomElements, CustomLeaves>
14
+ | RichTextScrollTargetElement<CustomElements, CustomLeaves>
15
+ | RichTextTableCellElement<CustomElements, CustomLeaves>
16
+ | RichTextTableElement<CustomElements, CustomLeaves>
17
+ | RichTextTableRowElement<CustomElements, CustomLeaves>
18
+ | RichTextUnorderedListElement<CustomElements, CustomLeaves>
19
+
20
+ export interface RichTextAnchorElement<
21
+ CustomElements extends RichTextElement = never,
22
+ CustomLeaves extends RichTextLeaf = RichTextLeaf,
23
+ > extends RichTextElement<CustomElements, CustomLeaves> {
24
+ type: 'anchor'
25
+ href: string
26
+ }
27
+
28
+ export interface RichTextHeadingElement<
29
+ CustomElements extends RichTextElement = never,
30
+ CustomLeaves extends RichTextLeaf = RichTextLeaf,
31
+ > extends RichTextElement<CustomElements, CustomLeaves> {
32
+ type: 'heading'
33
+ level: 1 | 2 | 3 | 4 | 5 | 6
34
+ isNumbered?: boolean
35
+ }
36
+
37
+ export interface RichTextOrderedListElement<
38
+ CustomElements extends RichTextElement = never,
39
+ CustomLeaves extends RichTextLeaf = RichTextLeaf,
40
+ > extends RichTextElement<CustomElements, CustomLeaves> {
41
+ type: 'orderedList'
42
+ }
43
+
44
+ export interface RichTextUnorderedListElement<
45
+ CustomElements extends RichTextElement = never,
46
+ CustomLeaves extends RichTextLeaf = RichTextLeaf,
47
+ > extends RichTextElement<CustomElements, CustomLeaves> {
48
+ type: 'unorderedList'
49
+ }
50
+
51
+ export interface RichTextListItemElement<
52
+ CustomElements extends RichTextElement = never,
53
+ CustomLeaves extends RichTextLeaf = RichTextLeaf,
54
+ > extends RichTextElement<CustomElements, CustomLeaves> {
55
+ type: 'listItem'
56
+ }
57
+
58
+ export interface RichTextHorizontalRuleElement<
59
+ CustomElements extends RichTextElement = never,
60
+ CustomLeaves extends RichTextLeaf = RichTextLeaf,
61
+ > extends RichTextElement<CustomElements, CustomLeaves> {
62
+ type: 'horizontalRule'
63
+ }
64
+
65
+ export interface RichTextParagraphElement<
66
+ CustomElements extends RichTextElement = never,
67
+ CustomLeaves extends RichTextLeaf = RichTextLeaf,
68
+ > extends RichTextElement<CustomElements, CustomLeaves> {
69
+ type: 'paragraph'
70
+ isNumbered?: boolean
71
+ }
72
+
73
+ export interface RichTextReferenceElement<
74
+ CustomElements extends RichTextElement = never,
75
+ CustomLeaves extends RichTextLeaf = RichTextLeaf,
76
+ > extends RichTextElement<CustomElements, CustomLeaves> {
77
+ type: 'reference'
78
+ referenceId: string
79
+ }
80
+
81
+ export interface RichTextScrollTargetElement<
82
+ CustomElements extends RichTextElement = never,
83
+ CustomLeaves extends RichTextLeaf = RichTextLeaf,
84
+ > extends RichTextElement<CustomElements, CustomLeaves> {
85
+ type: 'scrollTarget'
86
+ identifier: string
87
+ }
88
+
89
+ export interface RichTextTableElement<
90
+ CustomElements extends RichTextElement = never,
91
+ CustomLeaves extends RichTextLeaf = RichTextLeaf,
92
+ > extends RichTextElement<CustomElements, CustomLeaves> {
93
+ type: 'table'
94
+ }
95
+
96
+ export interface RichTextTableCellElement<
97
+ CustomElements extends RichTextElement = never,
98
+ CustomLeaves extends RichTextLeaf = RichTextLeaf,
99
+ > extends RichTextElement<CustomElements, CustomLeaves> {
100
+ type: 'tableCell'
101
+ headerScope?: 'row'
102
+ justify?: 'start' | 'center' | 'end'
103
+ }
104
+
105
+ export interface RichTextTableRowElement<
106
+ CustomElements extends RichTextElement = never,
107
+ CustomLeaves extends RichTextLeaf = RichTextLeaf,
108
+ > extends RichTextElement<CustomElements, CustomLeaves> {
109
+ type: 'tableRow'
110
+ headerScope?: 'table'
111
+ }
@@ -0,0 +1,33 @@
1
+ import type { RichTextLeaf } from '../structure'
2
+
3
+ export type BuiltinLeaves =
4
+ & RichTextBoldLeaf
5
+ & RichTextCodeLeaf
6
+ & RichTextHighlightLeaf
7
+ & RichTextItalicLeaf
8
+ & RichTextStrikeThroughLeaf
9
+ & RichTextUnderlineLeaf
10
+
11
+ export interface RichTextBoldLeaf extends RichTextLeaf {
12
+ isBold?: boolean
13
+ }
14
+
15
+ export interface RichTextCodeLeaf extends RichTextLeaf {
16
+ isCode?: boolean
17
+ }
18
+
19
+ export interface RichTextHighlightLeaf extends RichTextLeaf {
20
+ isHighlighted?: boolean
21
+ }
22
+
23
+ export interface RichTextItalicLeaf extends RichTextLeaf {
24
+ isItalic?: boolean
25
+ }
26
+
27
+ export interface RichTextStrikeThroughLeaf extends RichTextLeaf {
28
+ isStruckThrough?: boolean
29
+ }
30
+
31
+ export interface RichTextUnderlineLeaf extends RichTextLeaf {
32
+ isUnderlined?: boolean
33
+ }
@@ -0,0 +1,2 @@
1
+ export * from './BuiltinLeaves'
2
+ export * from './BuiltinElements'
@@ -0,0 +1,33 @@
1
+ import type { ComponentType, ReactElement } from 'react'
2
+ import type { BuiltinElements } from '../builtin'
3
+ import type { RichTextElement, RichTextLeaf } from '../structure'
4
+ import { RichTextReferenceFilledMetadata } from '../RichTextReferenceMetadata'
5
+ import type { RichTextReference } from '../RichTextReference'
6
+ import { RichTextBlock } from '../RichTextBlock'
7
+ import { RichTextRenderingOptions } from '../RichTextRenderingOptions'
8
+
9
+ export type ReferenceRendererProps<
10
+ Reference extends RichTextReference = RichTextReference,
11
+ CustomElements extends RichTextElement = never,
12
+ CustomLeaves extends RichTextLeaf = RichTextLeaf,
13
+ > =
14
+ & {
15
+ element: CustomElements | BuiltinElements<CustomElements, CustomLeaves>
16
+ children: ReactElement
17
+ formatVersion: number
18
+ block: RichTextBlock<CustomElements, CustomLeaves>
19
+ options: RichTextRenderingOptions<CustomElements, CustomLeaves>
20
+ }
21
+ & RichTextReferenceFilledMetadata<CustomElements, CustomLeaves, Reference>
22
+
23
+ export type ReferenceRenderer<
24
+ Reference extends RichTextReference = RichTextReference,
25
+ CustomElements extends RichTextElement = never,
26
+ CustomLeaves extends RichTextLeaf = RichTextLeaf,
27
+ > = ComponentType<ReferenceRendererProps<Reference, CustomElements, CustomLeaves>>
28
+
29
+ export type ReferenceRendererMap<
30
+ Reference extends RichTextReference = RichTextReference,
31
+ CustomElements extends RichTextElement = never,
32
+ CustomLeaves extends RichTextLeaf = RichTextLeaf,
33
+ > = Record<string, ReferenceRenderer<Reference, CustomElements, CustomLeaves>>
@@ -0,0 +1,8 @@
1
+ import { ComponentType, ReactNode } from 'react'
2
+
3
+ export type RenderBlockProps = {
4
+ block: unknown,
5
+ children?: ReactNode
6
+ }
7
+
8
+ export type RenderBlock = ComponentType<RenderBlockProps>
@@ -0,0 +1,37 @@
1
+ import { RichTextElement } from '../structure/RichTextElement'
2
+ import { RichTextLeaf } from '../structure/RichTextLeaf'
3
+ import { RichTextReference } from '../RichTextReference'
4
+ import { BuiltinElements } from '../builtin/BuiltinElements'
5
+ import { ComponentType, ReactElement } from 'react'
6
+ import { RichTextReferenceMetadata } from '../RichTextReferenceMetadata'
7
+ import { RichTextRenderingOptions } from '../RichTextRenderingOptions'
8
+ import { RichTextBlock } from '../RichTextBlock'
9
+ import { RenderChildren } from '../RenderChildren'
10
+
11
+ export type RenderElementProps<
12
+ CustomElements extends RichTextElement = never,
13
+ CustomLeaves extends RichTextLeaf = RichTextLeaf,
14
+ Reference extends RichTextReference = RichTextReference,
15
+ > =
16
+ & {
17
+ formatVersion: number
18
+ block: RichTextBlock<CustomElements, CustomLeaves>
19
+ element: CustomElements | BuiltinElements<CustomElements, CustomLeaves>
20
+ children: ReactElement
21
+ options: RichTextRenderingOptions<CustomElements, CustomLeaves>
22
+ fallback: ReactElement
23
+
24
+ renderChildren: RenderChildren<CustomElements, CustomLeaves>,
25
+
26
+ /**
27
+ * @deprecated To access the rendering options, use options. No need to pass it to renderChildren function.
28
+ */
29
+ renderChildrenOptions: RichTextRenderingOptions<CustomElements, CustomLeaves>
30
+ }
31
+ & RichTextReferenceMetadata<CustomElements, CustomLeaves, Reference>
32
+
33
+ export type RenderElement<
34
+ CustomElements extends RichTextElement = never,
35
+ CustomLeaves extends RichTextLeaf = RichTextLeaf,
36
+ Reference extends RichTextReference = RichTextReference,
37
+ > = ComponentType<RenderElementProps<CustomElements, CustomLeaves, Reference>>