@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,83 @@
1
+ /**
2
+ * @file RichTextEditorAutoLinkPlugin.tsx
3
+ * @input Uses `@lexical/react/LexicalAutoLinkPlugin` (`AutoLinkPlugin`,
4
+ * `createLinkMatcherWithRegExp`) and the shared URL/email matchers from
5
+ * `linkUtils`.
6
+ * @output Exports `RichTextEditorAutoLinkPlugin` and its props type, plus the
7
+ * default `DEFAULT_LINK_MATCHERS`.
8
+ * @position @blue-patterns/richtext. Drop into RichTextEditor's `plugins` slot to
9
+ * auto-linkify URLs and emails as they are typed or pasted, except inside
10
+ * a code block. Requires `AutoLinkNode` to be registered (it is, by
11
+ * default).
12
+ *
13
+ * SYNC: When modified, update:
14
+ * - /packages/richtext/src/index.ts (exports / barrel)
15
+ * - /packages/richtext/src/RichTextEditor.doc.mjs (usage notes)
16
+ * - /packages/richtext/src/RichTextEditor.test.tsx (tests)
17
+ * - /apps/storybook/stories/RichTextEditor.stories.tsx (story)
18
+ *
19
+ * NOTE: `lexical` and `@lexical/*` are OPTIONAL peer dependencies — install them
20
+ * to use this.
21
+ *
22
+ * COMPATIBILITY: the plugin is deliberately a thin pass-through so an
23
+ * application with its own link conventions can adopt it without forking. It
24
+ * uses the stock matcher shape (`createLinkMatcherWithRegExp` + `attributes`)
25
+ * and new-tab defaults, so a consumer supplies a richer matcher set — an
26
+ * application-specific identifier or ticket syntax, say — through the
27
+ * `matchers` prop without changing the contract. An application needing a
28
+ * hardened transform (expanded separators, say) substitutes its own plugin in
29
+ * the same slot; astryx stays on the upstream `AutoLinkPlugin`.
30
+ */
31
+ import { type LinkMatcher } from '@lexical/react/LexicalAutoLinkPlugin';
32
+ /**
33
+ * Attributes written onto every auto-created link so it opens in a new tab.
34
+ * `rel="noopener noreferrer"` is required whenever `target="_blank"` is set, to
35
+ * prevent reverse-tabnabbing.
36
+ */
37
+ export declare const NEW_TAB_LINK_ATTRIBUTES: {
38
+ readonly target: "_blank";
39
+ readonly rel: "noopener noreferrer";
40
+ };
41
+ /**
42
+ * Default matchers: bare URLs (defaulting to `https://` when scheme-less) and
43
+ * email addresses (as `mailto:` links). Both carry {@link NEW_TAB_LINK_ATTRIBUTES}.
44
+ * URLs are passed through {@link sanitizeUrl} so only http/https/mailto/tel
45
+ * schemes are ever written.
46
+ */
47
+ export declare const DEFAULT_LINK_MATCHERS: LinkMatcher[];
48
+ export interface RichTextEditorAutoLinkPluginProps {
49
+ /**
50
+ * Link matchers to use. Defaults to {@link DEFAULT_LINK_MATCHERS} (URLs +
51
+ * emails, opening in a new tab). Provide a custom array to recognize
52
+ * additional patterns (e.g. product-specific shortform references) — build
53
+ * each with `createLinkMatcherWithRegExp` from
54
+ * `@lexical/react/LexicalAutoLinkPlugin`.
55
+ */
56
+ matchers?: LinkMatcher[];
57
+ /**
58
+ * Called when a link is created, updated, or removed by auto-linking.
59
+ * Receives the new URL (or `null` when removed) and the previous URL.
60
+ */
61
+ onChange?: (url: string | null, prevUrl: string | null) => void;
62
+ }
63
+ /**
64
+ * Automatically converts typed/pasted URLs and email addresses into links.
65
+ * Render it inside the editor's `plugins` slot — it reaches the editor via
66
+ * `useLexicalComposerContext()`, so it must live within the editor's
67
+ * `LexicalComposer`. Requires `AutoLinkNode` (registered by default).
68
+ *
69
+ * @example
70
+ * ```
71
+ * import {RichTextEditor, RichTextEditorAutoLinkPlugin} from '@blue-patterns/richtext';
72
+ *
73
+ * <RichTextEditor
74
+ * label="Notes"
75
+ * plugins={<RichTextEditorAutoLinkPlugin />}
76
+ * />
77
+ * ```
78
+ */
79
+ export declare function RichTextEditorAutoLinkPlugin({ matchers, onChange, }: RichTextEditorAutoLinkPluginProps): import("react").JSX.Element;
80
+ export declare namespace RichTextEditorAutoLinkPlugin {
81
+ var displayName: string;
82
+ }
83
+ //# sourceMappingURL=RichTextEditorAutoLinkPlugin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RichTextEditorAutoLinkPlugin.d.ts","sourceRoot":"","sources":["../src/RichTextEditorAutoLinkPlugin.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAEH,OAAO,EAGL,KAAK,WAAW,EACjB,MAAM,sCAAsC,CAAC;AAK9C;;;;GAIG;AACH,eAAO,MAAM,uBAAuB;;;CAG1B,CAAC;AAEX;;;;;GAKG;AACH,eAAO,MAAM,qBAAqB,EAAE,WAAW,EAc9C,CAAC;AAMF,MAAM,WAAW,iCAAiC;IAChD;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE,WAAW,EAAE,CAAC;IACzB;;;OAGG;IACH,QAAQ,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;CACjE;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,4BAA4B,CAAC,EAC3C,QAAgC,EAChC,QAAQ,GACT,EAAE,iCAAiC,+BAQnC;yBAXe,4BAA4B"}
@@ -0,0 +1,99 @@
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
+ import { AutoLinkPlugin, createLinkMatcherWithRegExp } from '@lexical/react/LexicalAutoLinkPlugin';
36
+ import { $isCodeNode } from '@lexical/code';
37
+ import { URL_MATCHER, EMAIL_MATCHER, sanitizeUrl } from "./linkUtils.js";
38
+
39
+ /**
40
+ * Attributes written onto every auto-created link so it opens in a new tab.
41
+ * `rel="noopener noreferrer"` is required whenever `target="_blank"` is set, to
42
+ * prevent reverse-tabnabbing.
43
+ */
44
+ import { jsx as _jsx } from "react/jsx-runtime";
45
+ export const NEW_TAB_LINK_ATTRIBUTES = {
46
+ target: '_blank',
47
+ rel: 'noopener noreferrer'
48
+ };
49
+
50
+ /**
51
+ * Default matchers: bare URLs (defaulting to `https://` when scheme-less) and
52
+ * email addresses (as `mailto:` links). Both carry {@link NEW_TAB_LINK_ATTRIBUTES}.
53
+ * URLs are passed through {@link sanitizeUrl} so only http/https/mailto/tel
54
+ * schemes are ever written.
55
+ */
56
+ export const DEFAULT_LINK_MATCHERS = [text => {
57
+ const match = createLinkMatcherWithRegExp(URL_MATCHER, url => sanitizeUrl(url))(text);
58
+ return match ? {
59
+ ...match,
60
+ attributes: NEW_TAB_LINK_ATTRIBUTES
61
+ } : null;
62
+ }, text => {
63
+ const match = createLinkMatcherWithRegExp(EMAIL_MATCHER, email => `mailto:${email}`)(text);
64
+ return match ? {
65
+ ...match,
66
+ attributes: NEW_TAB_LINK_ATTRIBUTES
67
+ } : null;
68
+ }];
69
+
70
+ // Text in a code block is never linked. The upstream plugin registers again
71
+ // when this array changes. Keep it a module constant.
72
+ const EXCLUDE_PARENTS = [$isCodeNode];
73
+ /**
74
+ * Automatically converts typed/pasted URLs and email addresses into links.
75
+ * Render it inside the editor's `plugins` slot — it reaches the editor via
76
+ * `useLexicalComposerContext()`, so it must live within the editor's
77
+ * `LexicalComposer`. Requires `AutoLinkNode` (registered by default).
78
+ *
79
+ * @example
80
+ * ```
81
+ * import {RichTextEditor, RichTextEditorAutoLinkPlugin} from '@blue-patterns/richtext';
82
+ *
83
+ * <RichTextEditor
84
+ * label="Notes"
85
+ * plugins={<RichTextEditorAutoLinkPlugin />}
86
+ * />
87
+ * ```
88
+ */
89
+ export function RichTextEditorAutoLinkPlugin({
90
+ matchers = DEFAULT_LINK_MATCHERS,
91
+ onChange
92
+ }) {
93
+ return /*#__PURE__*/_jsx(AutoLinkPlugin, {
94
+ matchers: matchers,
95
+ onChange: onChange,
96
+ excludeParents: EXCLUDE_PARENTS
97
+ });
98
+ }
99
+ RichTextEditorAutoLinkPlugin.displayName = 'RichTextEditorAutoLinkPlugin';
@@ -0,0 +1,186 @@
1
+ /**
2
+ * @file RichTextEditorToolbar.tsx
3
+ * @input Uses React, @lexical/react (composer context), @lexical/rich-text,
4
+ * @lexical/selection, @lexical/list, @lexical/utils, and the lexical core
5
+ * command constants, plus Astryx Toolbar / IconButton / Selector /
6
+ * ToggleButton / Divider / Layout primitives, and the link popover in
7
+ * ToolbarLinkPopover.
8
+ * @output Exports RichTextEditorToolbar (a compact formatting toolbar with a
9
+ * RichText-owned 4px control gutter, a horizontally scrollable action row,
10
+ * and a link popover anchored to its Link button) and
11
+ * RichTextEditorToolbarProps, plus format and glyph helpers RichText shares
12
+ * internally.
13
+ * @position @blue-patterns/richtext. Drop into RichTextEditor's `toolbar` slot to
14
+ * add a flush top formatting toolbar. Themed via Astryx Toolbar, Selector,
15
+ * IconButton, and ToggleButton, so it inherits the active theme. Base props
16
+ * pass through to the Astryx Toolbar exactly as Toolbar places them
17
+ * (spec:AST-061/DEC-8).
18
+ *
19
+ * SYNC: When modified, update:
20
+ * - /packages/richtext/src/index.ts (exports)
21
+ * - /packages/richtext/src/RichTextEditor.doc.mjs (usage notes)
22
+ * - /packages/richtext/src/RichTextEditor.test.tsx (tests)
23
+ * - /apps/storybook/stories/RichTextEditor.stories.tsx (WithToolbar story)
24
+ *
25
+ * NOTE: `lexical` and `@lexical/*` are OPTIONAL peer dependencies — install them
26
+ * to use this.
27
+ * Behavior mirrors the Lexical playground toolbar (selection sync + format
28
+ * commands); the UI is built from Astryx primitives so it matches the theme.
29
+ *
30
+ * ICONS: Each control resolves its glyph through the core icon registry under a
31
+ * stable `richtext:*` key (see {@link RICHTEXT_ICON_KEYS}) for the active
32
+ * theme, falling back to the bundled inline SVGs below — the library seam
33
+ * `getExtendedIcon` documents. A theme restyles any glyph by naming its key:
34
+ * defineTheme({icons: {'richtext:bold': <MyBoldIcon />}});
35
+ * Undo and redo point backward and forward in time, so they mirror under RTL
36
+ * whichever glyph draws them.
37
+ */
38
+ import { type ReactNode, type Ref } from 'react';
39
+ import type { BaseProps } from '@blue-patterns/core';
40
+ import { type TranslatorFn } from '@blue-patterns/core/i18n';
41
+ import { type LexicalEditor, type NodeSelection, type RangeSelection } from 'lexical';
42
+ /**
43
+ * Stable icon-registry keys for the toolbar's controls. A theme overrides any
44
+ * of these by key: `defineTheme({icons: {'richtext:bold': <MyIcon />}})`.
45
+ * Keys are namespaced (`richtext:*`) to avoid collisions with the core
46
+ * semantic icon set.
47
+ */
48
+ export declare const RICHTEXT_ICON_KEYS: {
49
+ readonly bold: "richtext:bold";
50
+ readonly italic: "richtext:italic";
51
+ readonly underline: "richtext:underline";
52
+ readonly strikethrough: "richtext:strikethrough";
53
+ readonly code: "richtext:code";
54
+ readonly link: "richtext:link";
55
+ readonly paragraph: "richtext:paragraph";
56
+ readonly h1: "richtext:h1";
57
+ readonly h2: "richtext:h2";
58
+ readonly h3: "richtext:h3";
59
+ readonly quote: "richtext:quote";
60
+ readonly bullet: "richtext:bullet";
61
+ readonly number: "richtext:number";
62
+ readonly undo: "richtext:undo";
63
+ readonly redo: "richtext:redo";
64
+ };
65
+ /** The inline formats, in the order a toolbar offers them. */
66
+ export declare const INLINE_FORMAT_ACTIONS: readonly [{
67
+ readonly format: "bold";
68
+ readonly icon: "bold";
69
+ }, {
70
+ readonly format: "italic";
71
+ readonly icon: "italic";
72
+ }, {
73
+ readonly format: "underline";
74
+ readonly icon: "underline";
75
+ }, {
76
+ readonly format: "strikethrough";
77
+ readonly icon: "strikethrough";
78
+ }, {
79
+ readonly format: "code";
80
+ readonly icon: "code";
81
+ }];
82
+ export type InlineFormat = (typeof INLINE_FORMAT_ACTIONS)[number]['format'];
83
+ /** The inline formats' button labels. */
84
+ export declare function inlineFormatLabels(t: TranslatorFn): Record<InlineFormat, string>;
85
+ /**
86
+ * The inline formats a range or node selection carries, which their buttons
87
+ * show pressed. A selection of Markdown plugin nodes alone (a range around
88
+ * them, or a node selection from a click) shows their formats. Any other
89
+ * node selection, such as a rule, has none.
90
+ */
91
+ export declare function $inlineFormatsOf(selection: RangeSelection | NodeSelection): Set<InlineFormat>;
92
+ /** Toggles an inline format over the editor's selection. */
93
+ export declare function formatSelection(editor: LexicalEditor, format: InlineFormat): void;
94
+ export type ToolbarIconName = keyof typeof RICHTEXT_ICON_KEYS;
95
+ /** The glyph resolver for the active theme, as the toolbars draw glyphs. */
96
+ export declare function useToolbarIcon(): (name: ToolbarIconName) => ReactNode;
97
+ export interface RichTextEditorToolbarProps extends BaseProps<HTMLDivElement> {
98
+ /**
99
+ * Ref to the toolbar's root element. Base props pass through to the
100
+ * underlying Astryx `Toolbar`: the ref, `className`, `style`, and `xstyle`
101
+ * reach its root, and `data-*`, other `aria-*` attributes, and DOM
102
+ * handlers reach the `role="toolbar"` element inside it. The toolbar names
103
+ * itself, so pass `label` rather than `aria-label`.
104
+ */
105
+ ref?: Ref<HTMLDivElement>;
106
+ /**
107
+ * Accessible label for the toolbar element.
108
+ * @default 'Text formatting', translated for the active locale
109
+ */
110
+ label?: string;
111
+ /**
112
+ * Which heading levels to expose in the block-format selector, in order.
113
+ * @default ['h1', 'h2', 'h3']
114
+ */
115
+ headingLevels?: ReadonlyArray<'h1' | 'h2' | 'h3'>;
116
+ /**
117
+ * Toolbar size. Cascades to formatting controls and coordinates the
118
+ * Toolbar's internal padding.
119
+ * @default 'sm'
120
+ */
121
+ size?: 'sm' | 'md' | 'lg';
122
+ /**
123
+ * Whether to show the insert/edit-link button. By default, pressing it (or
124
+ * Cmd/Ctrl+K in the editor) opens an Astryx Popover anchored to the button:
125
+ * one URL field, applied with Enter, with Remove when the selection is in a
126
+ * link. The popover is not modal. Escape or Cancel closes it and returns
127
+ * focus and the selection to the editor; a URL that cannot be linked shows
128
+ * an error under the field, which keeps focus. With a collapsed selection,
129
+ * applying inserts the entered URL as link text at the caret; with a
130
+ * non-empty selection it links the selected text.
131
+ *
132
+ * Requires `LinkNode` to be registered (it is, by default) — no extra setup.
133
+ * The entered URL is sanitized (see `sanitizeUrl`) so only
134
+ * http/https/mailto/tel links are written.
135
+ * @default true
136
+ */
137
+ hasLink?: boolean;
138
+ /**
139
+ * Called to obtain a URL when the link button is pressed on a non-link
140
+ * selection. Return the URL string to link, or `null`/`''` to cancel.
141
+ * Receives the currently selected text as a hint. When omitted, the built-in
142
+ * link popover is used. This synchronous override is retained
143
+ * for consumers that already provide their own URL UI.
144
+ */
145
+ promptForUrl?: (selectedText: string) => string | null | undefined;
146
+ /**
147
+ * Whether links created via the toolbar open in a new tab. When `true`
148
+ * (default), the created link carries `target="_blank"` and
149
+ * `rel="noopener noreferrer"` — written into the link node's data (so it
150
+ * serializes and round-trips), not patched onto the DOM. Set `false` to
151
+ * create same-tab links.
152
+ * @default true
153
+ */
154
+ hasNewTabLinks?: boolean;
155
+ /**
156
+ * Extra items rendered at the end of the toolbar (after a divider). Use this
157
+ * to compose product-specific controls (e.g. mentions, AI) alongside the
158
+ * default formatting buttons.
159
+ */
160
+ endContent?: ReactNode;
161
+ }
162
+ /**
163
+ * A composable formatting toolbar for {@link RichTextEditor}, built from Astryx
164
+ * `Toolbar` / `ToggleButton` primitives so it matches the active theme. Reads
165
+ * the current selection to keep the active states in sync and dispatches the
166
+ * standard Lexical formatting commands.
167
+ *
168
+ * Render it inside the editor's `toolbar` slot — it uses
169
+ * `useLexicalComposerContext()` to reach the editor, so it must live within the
170
+ * `LexicalComposer` the editor sets up.
171
+ *
172
+ * @example
173
+ * ```
174
+ * import {RichTextEditor, RichTextEditorToolbar} from '@blue-patterns/richtext';
175
+ *
176
+ * <RichTextEditor
177
+ * label="Notes"
178
+ * toolbar={<RichTextEditorToolbar />}
179
+ * />
180
+ * ```
181
+ */
182
+ export declare function RichTextEditorToolbar({ label: labelFromProps, headingLevels, size, hasLink, promptForUrl, hasNewTabLinks, endContent, xstyle, ref, ...rest }: RichTextEditorToolbarProps): import("react").JSX.Element;
183
+ export declare namespace RichTextEditorToolbar {
184
+ var displayName: string;
185
+ }
186
+ //# sourceMappingURL=RichTextEditorToolbar.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RichTextEditorToolbar.d.ts","sourceRoot":"","sources":["../src/RichTextEditorToolbar.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AAEH,OAAO,EAKL,KAAK,SAAS,EACd,KAAK,GAAG,EACT,MAAM,OAAO,CAAC;AAmBf,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,qBAAqB,CAAC;AAenD,OAAO,EAAgB,KAAK,YAAY,EAAC,MAAM,0BAA0B,CAAC;AAC1E,OAAO,EAYL,KAAK,aAAa,EAClB,KAAK,aAAa,EAClB,KAAK,cAAc,EAGpB,MAAM,SAAS,CAAC;AAwEjB;;;;;GAKG;AACH,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;CAgBrB,CAAC;AAEX,8DAA8D;AAC9D,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;EAMxB,CAAC;AAEX,MAAM,MAAM,YAAY,GAAG,CAAC,OAAO,qBAAqB,CAAC,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,CAAC;AAE5E,yCAAyC;AACzC,wBAAgB,kBAAkB,CAChC,CAAC,EAAE,YAAY,GACd,MAAM,CAAC,YAAY,EAAE,MAAM,CAAC,CAS9B;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAC9B,SAAS,EAAE,cAAc,GAAG,aAAa,GACxC,GAAG,CAAC,YAAY,CAAC,CAanB;AAED,4DAA4D;AAC5D,wBAAgB,eAAe,CAC7B,MAAM,EAAE,aAAa,EACrB,MAAM,EAAE,YAAY,GACnB,IAAI,CAEN;AA4MD,MAAM,MAAM,eAAe,GAAG,MAAM,OAAO,kBAAkB,CAAC;AAkB9D,4EAA4E;AAC5E,wBAAgB,cAAc,IAAI,CAAC,IAAI,EAAE,eAAe,KAAK,SAAS,CAGrE;AAaD,MAAM,WAAW,0BAA2B,SAAQ,SAAS,CAAC,cAAc,CAAC;IAC3E;;;;;;OAMG;IACH,GAAG,CAAC,EAAE,GAAG,CAAC,cAAc,CAAC,CAAC;IAC1B;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,aAAa,CAAC,EAAE,aAAa,CAAC,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC,CAAC;IAClD;;;;OAIG;IACH,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;IAC1B;;;;;;;;;;;;;;OAcG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;;;;OAMG;IACH,YAAY,CAAC,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IACnE;;;;;;;OAOG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB;;;;OAIG;IACH,UAAU,CAAC,EAAE,SAAS,CAAC;CACxB;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,qBAAqB,CAAC,EACpC,KAAK,EAAE,cAAc,EACrB,aAAkC,EAClC,IAAW,EACX,OAAc,EACd,YAAY,EACZ,cAAqB,EACrB,UAAU,EACV,MAAM,EACN,GAAG,EACH,GAAG,IAAI,EACR,EAAE,0BAA0B,+BAyR5B;yBApSe,qBAAqB"}