@blue-patterns/richtext 0.0.0-stage → 0.7.18

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 (201) hide show
  1. package/CHANGELOG.md +275 -0
  2. package/LICENSE +22 -0
  3. package/README.md +88 -2
  4. package/astryx.integration.mjs +11 -0
  5. package/blocks/RichTextEditorShowcase.template.mjs +13 -0
  6. package/blocks/RichTextEditorShowcase.tsx +19 -0
  7. package/dist/RichTextEditor.d.ts +282 -0
  8. package/dist/RichTextEditor.d.ts.map +1 -0
  9. package/dist/RichTextEditor.js +657 -0
  10. package/dist/RichTextEditorAutoLinkPlugin.d.ts +83 -0
  11. package/dist/RichTextEditorAutoLinkPlugin.d.ts.map +1 -0
  12. package/dist/RichTextEditorAutoLinkPlugin.js +99 -0
  13. package/dist/RichTextEditorToolbar.d.ts +186 -0
  14. package/dist/RichTextEditorToolbar.d.ts.map +1 -0
  15. package/dist/RichTextEditorToolbar.js +688 -0
  16. package/dist/RichTextView.d.ts +92 -0
  17. package/dist/RichTextView.d.ts.map +1 -0
  18. package/dist/RichTextView.js +267 -0
  19. package/dist/codeLanguages.d.ts +14 -0
  20. package/dist/codeLanguages.d.ts.map +1 -0
  21. package/dist/codeLanguages.js +34 -0
  22. package/dist/codeLineTokens.d.ts +53 -0
  23. package/dist/codeLineTokens.d.ts.map +1 -0
  24. package/dist/codeLineTokens.js +188 -0
  25. package/dist/editorNodes.d.ts +8 -0
  26. package/dist/editorNodes.d.ts.map +1 -0
  27. package/dist/editorNodes.js +30 -0
  28. package/dist/editorTheme.d.ts +7 -0
  29. package/dist/editorTheme.d.ts.map +1 -0
  30. package/dist/editorTheme.js +328 -0
  31. package/dist/index.d.ts +31 -0
  32. package/dist/index.d.ts.map +1 -0
  33. package/dist/index.js +28 -0
  34. package/dist/internal/CodeBackspacePlugin.d.ts +2 -0
  35. package/dist/internal/CodeBackspacePlugin.d.ts.map +1 -0
  36. package/dist/internal/CodeBackspacePlugin.js +70 -0
  37. package/dist/internal/CodeBlockHeaderPlugin.d.ts +11 -0
  38. package/dist/internal/CodeBlockHeaderPlugin.d.ts.map +1 -0
  39. package/dist/internal/CodeBlockHeaderPlugin.js +204 -0
  40. package/dist/internal/CodePastePlugin.d.ts +5 -0
  41. package/dist/internal/CodePastePlugin.d.ts.map +1 -0
  42. package/dist/internal/CodePastePlugin.js +104 -0
  43. package/dist/internal/CodeSyntaxPlugin.d.ts +8 -0
  44. package/dist/internal/CodeSyntaxPlugin.d.ts.map +1 -0
  45. package/dist/internal/CodeSyntaxPlugin.js +397 -0
  46. package/dist/internal/CodeTabPlugin.d.ts +2 -0
  47. package/dist/internal/CodeTabPlugin.d.ts.map +1 -0
  48. package/dist/internal/CodeTabPlugin.js +256 -0
  49. package/dist/internal/DisabledLinkGuardPlugin.d.ts +4 -0
  50. package/dist/internal/DisabledLinkGuardPlugin.d.ts.map +1 -0
  51. package/dist/internal/DisabledLinkGuardPlugin.js +93 -0
  52. package/dist/internal/ImageSourceCaretPlugin.d.ts +3 -0
  53. package/dist/internal/ImageSourceCaretPlugin.d.ts.map +1 -0
  54. package/dist/internal/ImageSourceCaretPlugin.js +105 -0
  55. package/dist/internal/ListItemShortcutsPlugin.d.ts +6 -0
  56. package/dist/internal/ListItemShortcutsPlugin.d.ts.map +1 -0
  57. package/dist/internal/ListItemShortcutsPlugin.js +314 -0
  58. package/dist/internal/MarkdownExtensionsPlugin.d.ts +17 -0
  59. package/dist/internal/MarkdownExtensionsPlugin.d.ts.map +1 -0
  60. package/dist/internal/MarkdownExtensionsPlugin.js +185 -0
  61. package/dist/internal/SelectAllScopePlugin.d.ts +2 -0
  62. package/dist/internal/SelectAllScopePlugin.d.ts.map +1 -0
  63. package/dist/internal/SelectAllScopePlugin.js +67 -0
  64. package/dist/internal/TableColumnFloorPlugin.d.ts +12 -0
  65. package/dist/internal/TableColumnFloorPlugin.d.ts.map +1 -0
  66. package/dist/internal/TableColumnFloorPlugin.js +84 -0
  67. package/dist/internal/TablePastePlugin.d.ts +9 -0
  68. package/dist/internal/TablePastePlugin.d.ts.map +1 -0
  69. package/dist/internal/TablePastePlugin.js +183 -0
  70. package/dist/internal/TableScrollRegionPlugin.d.ts +9 -0
  71. package/dist/internal/TableScrollRegionPlugin.d.ts.map +1 -0
  72. package/dist/internal/TableScrollRegionPlugin.js +95 -0
  73. package/dist/internal/TaskCheckboxPlugin.d.ts +7 -0
  74. package/dist/internal/TaskCheckboxPlugin.d.ts.map +1 -0
  75. package/dist/internal/TaskCheckboxPlugin.js +193 -0
  76. package/dist/internal/ToolbarLinkPopover.d.ts +74 -0
  77. package/dist/internal/ToolbarLinkPopover.d.ts.map +1 -0
  78. package/dist/internal/ToolbarLinkPopover.js +292 -0
  79. package/dist/linkEditing.d.ts +6 -0
  80. package/dist/linkEditing.d.ts.map +1 -0
  81. package/dist/linkEditing.js +20 -0
  82. package/dist/linkForm.d.ts +28 -0
  83. package/dist/linkForm.d.ts.map +1 -0
  84. package/dist/linkForm.js +137 -0
  85. package/dist/linkUtils.d.ts +27 -0
  86. package/dist/linkUtils.d.ts.map +1 -0
  87. package/dist/linkUtils.js +101 -0
  88. package/dist/markdown.d.ts +17 -0
  89. package/dist/markdown.d.ts.map +1 -0
  90. package/dist/markdown.js +17 -0
  91. package/dist/markdownCharacterReferences.d.ts +135 -0
  92. package/dist/markdownCharacterReferences.d.ts.map +1 -0
  93. package/dist/markdownCharacterReferences.js +1127 -0
  94. package/dist/markdownCodeFence.d.ts +4 -0
  95. package/dist/markdownCodeFence.d.ts.map +1 -0
  96. package/dist/markdownCodeFence.js +167 -0
  97. package/dist/markdownExtensionNode.d.ts +88 -0
  98. package/dist/markdownExtensionNode.d.ts.map +1 -0
  99. package/dist/markdownExtensionNode.js +248 -0
  100. package/dist/markdownExtensions.d.ts +115 -0
  101. package/dist/markdownExtensions.d.ts.map +1 -0
  102. package/dist/markdownExtensions.js +392 -0
  103. package/dist/markdownHardLineBreak.d.ts +25 -0
  104. package/dist/markdownHardLineBreak.d.ts.map +1 -0
  105. package/dist/markdownHardLineBreak.js +59 -0
  106. package/dist/markdownHeading.d.ts +20 -0
  107. package/dist/markdownHeading.d.ts.map +1 -0
  108. package/dist/markdownHeading.js +30 -0
  109. package/dist/markdownLink.d.ts +5 -0
  110. package/dist/markdownLink.d.ts.map +1 -0
  111. package/dist/markdownLink.js +80 -0
  112. package/dist/markdownListExport.d.ts +3 -0
  113. package/dist/markdownListExport.d.ts.map +1 -0
  114. package/dist/markdownListExport.js +68 -0
  115. package/dist/markdownListIndentation.d.ts +8 -0
  116. package/dist/markdownListIndentation.d.ts.map +1 -0
  117. package/dist/markdownListIndentation.js +101 -0
  118. package/dist/markdownOrderedList.d.ts +3 -0
  119. package/dist/markdownOrderedList.d.ts.map +1 -0
  120. package/dist/markdownOrderedList.js +51 -0
  121. package/dist/markdownQuote.d.ts +22 -0
  122. package/dist/markdownQuote.d.ts.map +1 -0
  123. package/dist/markdownQuote.js +32 -0
  124. package/dist/markdownSerializers.d.ts +49 -0
  125. package/dist/markdownSerializers.d.ts.map +1 -0
  126. package/dist/markdownSerializers.js +83 -0
  127. package/dist/markdownSource.d.ts +71 -0
  128. package/dist/markdownSource.d.ts.map +1 -0
  129. package/dist/markdownSource.js +804 -0
  130. package/dist/markdownSpaceRuns.d.ts +24 -0
  131. package/dist/markdownSpaceRuns.d.ts.map +1 -0
  132. package/dist/markdownSpaceRuns.js +147 -0
  133. package/dist/markdownTable.d.ts +35 -0
  134. package/dist/markdownTable.d.ts.map +1 -0
  135. package/dist/markdownTable.js +227 -0
  136. package/dist/markdownTaskList.d.ts +48 -0
  137. package/dist/markdownTaskList.d.ts.map +1 -0
  138. package/dist/markdownTaskList.js +166 -0
  139. package/dist/markdownThematicBreak.d.ts +3 -0
  140. package/dist/markdownThematicBreak.d.ts.map +1 -0
  141. package/dist/markdownThematicBreak.js +55 -0
  142. package/dist/privateAttributes/layerPortalBoundary.stylex.d.ts +12 -0
  143. package/dist/privateAttributes/layerPortalBoundary.stylex.d.ts.map +1 -0
  144. package/dist/privateAttributes/layerPortalBoundary.stylex.js +16 -0
  145. package/dist/richtext.css +213 -0
  146. package/dist/textSemantics.d.ts +3 -0
  147. package/dist/textSemantics.d.ts.map +1 -0
  148. package/dist/textSemantics.js +87 -0
  149. package/package.json +158 -3
  150. package/src/RichTextEditor.doc.mjs +308 -0
  151. package/src/RichTextEditor.tsx +1109 -0
  152. package/src/RichTextEditorAutoLinkPlugin.doc.mjs +43 -0
  153. package/src/RichTextEditorAutoLinkPlugin.tsx +126 -0
  154. package/src/RichTextEditorToolbar.doc.mjs +92 -0
  155. package/src/RichTextEditorToolbar.tsx +871 -0
  156. package/src/RichTextView.doc.mjs +101 -0
  157. package/src/RichTextView.tsx +351 -0
  158. package/src/codeLanguages.ts +42 -0
  159. package/src/codeLineTokens.ts +241 -0
  160. package/src/doc-mjs.d.ts +23 -0
  161. package/src/editorNodes.ts +44 -0
  162. package/src/editorTheme.ts +550 -0
  163. package/src/index.ts +59 -0
  164. package/src/internal/CodeBackspacePlugin.tsx +96 -0
  165. package/src/internal/CodeBlockHeaderPlugin.tsx +282 -0
  166. package/src/internal/CodePastePlugin.tsx +144 -0
  167. package/src/internal/CodeSyntaxPlugin.tsx +493 -0
  168. package/src/internal/CodeTabPlugin.tsx +298 -0
  169. package/src/internal/DisabledLinkGuardPlugin.tsx +93 -0
  170. package/src/internal/ImageSourceCaretPlugin.tsx +159 -0
  171. package/src/internal/ListItemShortcutsPlugin.tsx +404 -0
  172. package/src/internal/MarkdownExtensionsPlugin.tsx +289 -0
  173. package/src/internal/SelectAllScopePlugin.tsx +86 -0
  174. package/src/internal/TableColumnFloorPlugin.tsx +99 -0
  175. package/src/internal/TablePastePlugin.tsx +223 -0
  176. package/src/internal/TableScrollRegionPlugin.tsx +107 -0
  177. package/src/internal/TaskCheckboxPlugin.tsx +246 -0
  178. package/src/internal/ToolbarLinkPopover.tsx +392 -0
  179. package/src/linkEditing.ts +20 -0
  180. package/src/linkForm.tsx +156 -0
  181. package/src/linkUtils.ts +106 -0
  182. package/src/markdown.ts +25 -0
  183. package/src/markdownCharacterReferences.ts +1137 -0
  184. package/src/markdownCodeFence.ts +216 -0
  185. package/src/markdownExtensionNode.ts +339 -0
  186. package/src/markdownExtensions.ts +496 -0
  187. package/src/markdownHardLineBreak.ts +73 -0
  188. package/src/markdownHeading.ts +33 -0
  189. package/src/markdownLink.ts +86 -0
  190. package/src/markdownListExport.ts +85 -0
  191. package/src/markdownListIndentation.ts +105 -0
  192. package/src/markdownOrderedList.ts +60 -0
  193. package/src/markdownQuote.ts +35 -0
  194. package/src/markdownSerializers.ts +108 -0
  195. package/src/markdownSource.ts +1045 -0
  196. package/src/markdownSpaceRuns.ts +164 -0
  197. package/src/markdownTable.ts +309 -0
  198. package/src/markdownTaskList.ts +222 -0
  199. package/src/markdownThematicBreak.ts +66 -0
  200. package/src/privateAttributes/layerPortalBoundary.stylex.ts +18 -0
  201. package/src/textSemantics.ts +104 -0
@@ -0,0 +1,43 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ /** @type {import('@blue-patterns/cli/authoring').ComponentDoc} */
4
+
5
+ export const docs = {
6
+ name: 'RichTextEditorAutoLinkPlugin',
7
+ subComponentOf: 'RichTextEditor',
8
+ description:
9
+ 'Turns typed and pasted URLs and email addresses into links, in the plugins slot of RichTextEditor.',
10
+ displayName: 'Rich Text Editor Auto-Link Plugin',
11
+ keywords: ['richtext', 'autolink', 'link', 'url', 'email', 'plugin'],
12
+ props: [
13
+ {
14
+ name: 'matchers',
15
+ type: 'LinkMatcher[]',
16
+ description:
17
+ 'Link matchers to use. The default recognizes URLs and email addresses and opens the links in a new tab. Build extra matchers with createLinkMatcherWithRegExp from @lexical/react/LexicalAutoLinkPlugin.',
18
+ default: 'DEFAULT_LINK_MATCHERS',
19
+ },
20
+ {
21
+ name: 'onChange',
22
+ type: '(url: string | null, prevUrl: string | null) => void',
23
+ description:
24
+ 'Called when auto-linking creates, updates or removes a link. It gets the new URL, or null when the link is removed, and the previous URL.',
25
+ },
26
+ ],
27
+ usage: {
28
+ description:
29
+ "Turns typed and pasted URLs and email addresses into links. Text inside a code block stays code and is never linked. Render it in RichTextEditor's plugins slot; it reaches the editor through the editor's Lexical composer and uses AutoLinkNode, which the editor registers by default.",
30
+ bestPractices: [
31
+ {
32
+ guidance: true,
33
+ description:
34
+ 'Pass it as plugins={<RichTextEditorAutoLinkPlugin />}. Its links open in a new tab, with target="_blank" and rel="noopener noreferrer" in the node.',
35
+ },
36
+ {
37
+ guidance: false,
38
+ description:
39
+ "Render it outside RichTextEditor's plugins slot: it needs the editor's Lexical composer.",
40
+ },
41
+ ],
42
+ },
43
+ };
@@ -0,0 +1,126 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ 'use client';
4
+
5
+ /**
6
+ * @file RichTextEditorAutoLinkPlugin.tsx
7
+ * @input Uses `@lexical/react/LexicalAutoLinkPlugin` (`AutoLinkPlugin`,
8
+ * `createLinkMatcherWithRegExp`) and the shared URL/email matchers from
9
+ * `linkUtils`.
10
+ * @output Exports `RichTextEditorAutoLinkPlugin` and its props type, plus the
11
+ * default `DEFAULT_LINK_MATCHERS`.
12
+ * @position @blue-patterns/richtext. Drop into RichTextEditor's `plugins` slot to
13
+ * auto-linkify URLs and emails as they are typed or pasted, except inside
14
+ * a code block. Requires `AutoLinkNode` to be registered (it is, by
15
+ * default).
16
+ *
17
+ * SYNC: When modified, update:
18
+ * - /packages/richtext/src/index.ts (exports / barrel)
19
+ * - /packages/richtext/src/RichTextEditor.doc.mjs (usage notes)
20
+ * - /packages/richtext/src/RichTextEditor.test.tsx (tests)
21
+ * - /apps/storybook/stories/RichTextEditor.stories.tsx (story)
22
+ *
23
+ * NOTE: `lexical` and `@lexical/*` are OPTIONAL peer dependencies — install them
24
+ * to use this.
25
+ *
26
+ * COMPATIBILITY: the plugin is deliberately a thin pass-through so an
27
+ * application with its own link conventions can adopt it without forking. It
28
+ * uses the stock matcher shape (`createLinkMatcherWithRegExp` + `attributes`)
29
+ * and new-tab defaults, so a consumer supplies a richer matcher set — an
30
+ * application-specific identifier or ticket syntax, say — through the
31
+ * `matchers` prop without changing the contract. An application needing a
32
+ * hardened transform (expanded separators, say) substitutes its own plugin in
33
+ * the same slot; astryx stays on the upstream `AutoLinkPlugin`.
34
+ */
35
+
36
+ import {
37
+ AutoLinkPlugin,
38
+ createLinkMatcherWithRegExp,
39
+ type LinkMatcher,
40
+ } from '@lexical/react/LexicalAutoLinkPlugin';
41
+ import {$isCodeNode} from '@lexical/code';
42
+ import type {ElementNode} from 'lexical';
43
+ import {URL_MATCHER, EMAIL_MATCHER, sanitizeUrl} from './linkUtils';
44
+
45
+ /**
46
+ * Attributes written onto every auto-created link so it opens in a new tab.
47
+ * `rel="noopener noreferrer"` is required whenever `target="_blank"` is set, to
48
+ * prevent reverse-tabnabbing.
49
+ */
50
+ export const NEW_TAB_LINK_ATTRIBUTES = {
51
+ target: '_blank',
52
+ rel: 'noopener noreferrer',
53
+ } as const;
54
+
55
+ /**
56
+ * Default matchers: bare URLs (defaulting to `https://` when scheme-less) and
57
+ * email addresses (as `mailto:` links). Both carry {@link NEW_TAB_LINK_ATTRIBUTES}.
58
+ * URLs are passed through {@link sanitizeUrl} so only http/https/mailto/tel
59
+ * schemes are ever written.
60
+ */
61
+ export const DEFAULT_LINK_MATCHERS: LinkMatcher[] = [
62
+ text => {
63
+ const match = createLinkMatcherWithRegExp(URL_MATCHER, url =>
64
+ sanitizeUrl(url),
65
+ )(text);
66
+ return match ? {...match, attributes: NEW_TAB_LINK_ATTRIBUTES} : null;
67
+ },
68
+ text => {
69
+ const match = createLinkMatcherWithRegExp(
70
+ EMAIL_MATCHER,
71
+ email => `mailto:${email}`,
72
+ )(text);
73
+ return match ? {...match, attributes: NEW_TAB_LINK_ATTRIBUTES} : null;
74
+ },
75
+ ];
76
+
77
+ // Text in a code block is never linked. The upstream plugin registers again
78
+ // when this array changes. Keep it a module constant.
79
+ const EXCLUDE_PARENTS: ((parent: ElementNode) => boolean)[] = [$isCodeNode];
80
+
81
+ export interface RichTextEditorAutoLinkPluginProps {
82
+ /**
83
+ * Link matchers to use. Defaults to {@link DEFAULT_LINK_MATCHERS} (URLs +
84
+ * emails, opening in a new tab). Provide a custom array to recognize
85
+ * additional patterns (e.g. product-specific shortform references) — build
86
+ * each with `createLinkMatcherWithRegExp` from
87
+ * `@lexical/react/LexicalAutoLinkPlugin`.
88
+ */
89
+ matchers?: LinkMatcher[];
90
+ /**
91
+ * Called when a link is created, updated, or removed by auto-linking.
92
+ * Receives the new URL (or `null` when removed) and the previous URL.
93
+ */
94
+ onChange?: (url: string | null, prevUrl: string | null) => void;
95
+ }
96
+
97
+ /**
98
+ * Automatically converts typed/pasted URLs and email addresses into links.
99
+ * Render it inside the editor's `plugins` slot — it reaches the editor via
100
+ * `useLexicalComposerContext()`, so it must live within the editor's
101
+ * `LexicalComposer`. Requires `AutoLinkNode` (registered by default).
102
+ *
103
+ * @example
104
+ * ```
105
+ * import {RichTextEditor, RichTextEditorAutoLinkPlugin} from '@blue-patterns/richtext';
106
+ *
107
+ * <RichTextEditor
108
+ * label="Notes"
109
+ * plugins={<RichTextEditorAutoLinkPlugin />}
110
+ * />
111
+ * ```
112
+ */
113
+ export function RichTextEditorAutoLinkPlugin({
114
+ matchers = DEFAULT_LINK_MATCHERS,
115
+ onChange,
116
+ }: RichTextEditorAutoLinkPluginProps) {
117
+ return (
118
+ <AutoLinkPlugin
119
+ matchers={matchers}
120
+ onChange={onChange}
121
+ excludeParents={EXCLUDE_PARENTS}
122
+ />
123
+ );
124
+ }
125
+
126
+ RichTextEditorAutoLinkPlugin.displayName = 'RichTextEditorAutoLinkPlugin';
@@ -0,0 +1,92 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ /** @type {import('@blue-patterns/cli/authoring').ComponentDoc} */
4
+
5
+ export const docs = {
6
+ name: 'RichTextEditorToolbar',
7
+ subComponentOf: 'RichTextEditor',
8
+ description: 'Formatting toolbar for the toolbar slot of RichTextEditor.',
9
+ displayName: 'Rich Text Editor Toolbar',
10
+ keywords: ['richtext', 'toolbar', 'formatting', 'bold', 'link', 'heading'],
11
+ props: [
12
+ {
13
+ name: 'ref',
14
+ type: 'Ref<HTMLDivElement>',
15
+ description:
16
+ 'Ref to the toolbar\'s root element. The ref, className, style and xstyle reach the root of the Astryx Toolbar it renders; data-*, other aria-* attributes and DOM handlers reach its role="toolbar" element.',
17
+ },
18
+ {
19
+ name: 'label',
20
+ type: 'string',
21
+ description:
22
+ 'Accessible label for the toolbar element. Pass label rather than aria-label.',
23
+ default: "'Text formatting' (translated)",
24
+ },
25
+ {
26
+ name: 'headingLevels',
27
+ type: "ReadonlyArray<'h1' | 'h2' | 'h3'>",
28
+ description:
29
+ 'Which heading levels the block-format selector offers, in order.',
30
+ default: "['h1', 'h2', 'h3']",
31
+ },
32
+ {
33
+ name: 'size',
34
+ type: "'sm' | 'md' | 'lg'",
35
+ description:
36
+ "Size of the toolbar's controls; it also sets the toolbar's padding.",
37
+ default: "'sm'",
38
+ },
39
+ {
40
+ name: 'hasLink',
41
+ type: 'boolean',
42
+ description:
43
+ 'Whether to show the link button. It opens a link popover anchored to the button, with one URL field applied with Enter and Remove when the selection is in a link. The popover is not modal; Escape or Cancel returns focus and the selection to the editor. With a collapsed selection the URL is inserted as link text; otherwise the selected text is linked. Only http, https, mailto and tel URLs are written.',
44
+ default: 'true',
45
+ },
46
+ {
47
+ name: 'promptForUrl',
48
+ type: '(selectedText: string) => string | null | undefined',
49
+ description:
50
+ 'A synchronous URL prompt that replaces the built-in link popover when the link button is pressed on a selection that is not a link. It gets the selected text; return the URL, or null or an empty string to cancel.',
51
+ },
52
+ {
53
+ name: 'hasNewTabLinks',
54
+ type: 'boolean',
55
+ description:
56
+ 'Whether links made with the toolbar open in a new tab. When true, target="_blank" and rel="noopener noreferrer" are written into the link node, so they serialize.',
57
+ default: 'true',
58
+ },
59
+ {
60
+ name: 'endContent',
61
+ type: 'ReactNode',
62
+ description:
63
+ 'Extra items at the end of the toolbar, after a divider, such as mention or AI controls.',
64
+ },
65
+ {
66
+ name: 'xstyle',
67
+ type: 'StyleXStyles',
68
+ description: "StyleX styles for the toolbar's root.",
69
+ },
70
+ ],
71
+ usage: {
72
+ description:
73
+ "A formatting toolbar for RichTextEditor, built from Astryx Toolbar, Selector and ToggleButton controls: undo and redo, a block-format selector for paragraphs, headings, lists and quotes, inline bold, italic, underline, strikethrough and code, and links. Render it in the editor's toolbar slot; it reaches the editor through the editor's Lexical composer, so it must live inside it.",
74
+ bestPractices: [
75
+ {
76
+ guidance: true,
77
+ description:
78
+ 'Pass it as toolbar={<RichTextEditorToolbar />}. The slot places it at the top of the field, before the editing surface, in the right keyboard order.',
79
+ },
80
+ {
81
+ guidance: true,
82
+ description:
83
+ "Restyle a glyph from a theme by its richtext:* icon key (see RICHTEXT_ICON_KEYS), for example defineTheme({icons: {'richtext:bold': <MyBoldIcon />}}).",
84
+ },
85
+ {
86
+ guidance: false,
87
+ description:
88
+ "Render it outside RichTextEditor's toolbar slot: it needs the editor's Lexical composer.",
89
+ },
90
+ ],
91
+ },
92
+ };