@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,92 @@
1
+ /**
2
+ * @file RichTextView.tsx
3
+ * @input Uses React, Lexical (lexical + @lexical/react, composed through
4
+ * LexicalExtensionComposer), mergeProps from core utils, design tokens,
5
+ * TableScrollRegionPlugin
6
+ * @output Exports RichTextView component and RichTextViewProps
7
+ * @position Read-only renderer for serialized Lexical editor state, exposed to
8
+ * assistive technology as document content rather than a form field;
9
+ * exported from @blue-patterns/richtext
10
+ *
11
+ * SYNC: When modified, update these files to stay in sync:
12
+ * - /packages/richtext/src/RichTextEditor.test.tsx
13
+ * - /packages/richtext/src/index.ts
14
+ * - /apps/storybook/stories/RichTextEditor.stories.tsx
15
+ */
16
+ import { type ReactNode } from 'react';
17
+ import type { BaseProps } from '@blue-patterns/core';
18
+ import type { RichTextMarkdownExtension } from './markdownExtensions.js';
19
+ import type { CodeLanguage } from '@blue-patterns/core/CodeBlock';
20
+ import type { Klass, LexicalNode } from 'lexical';
21
+ export interface RichTextViewProps extends BaseProps {
22
+ /**
23
+ * Serialized editor state to render (a JSON string produced by
24
+ * `JSON.stringify(editorState.toJSON())`).
25
+ */
26
+ value: string;
27
+ /**
28
+ * Additional Lexical nodes to register beyond the default OSS set. Must match
29
+ * the nodes used to author `value` so custom node types deserialize.
30
+ */
31
+ nodes?: ReadonlyArray<Klass<LexicalNode>>;
32
+ /**
33
+ * Markdown plugins whose nodes this surface draws, each adopted with
34
+ * `createRichTextExtension` (spec:AST-064). A plugin node renders exactly as
35
+ * core `Markdown` renders it, and one whose plugin is not given here shows
36
+ * its source. Pass the extensions the content was converted with. Create
37
+ * them in a client module: they hold the plugins' functions, so they are not
38
+ * serializable props.
39
+ */
40
+ markdownExtensions?: ReadonlyArray<RichTextMarkdownExtension>;
41
+ /**
42
+ * CodeBlock language values a fence may name, each imported on its own,
43
+ * such as `graphql` from `@blue-patterns/core/CodeBlock/languages/graphql`,
44
+ * or made with `createCodeLanguage`. Pass the same list as `Markdown`'s
45
+ * `codeLanguages`, so reading and editing paint and label the same
46
+ * languages (spec:AST-061).
47
+ */
48
+ codeLanguages?: ReadonlyArray<CodeLanguage>;
49
+ /**
50
+ * Additional read-only plugins to render inside the composer (e.g. hover
51
+ * cards, decorators).
52
+ */
53
+ plugins?: ReactNode;
54
+ /** The Lexical composer namespace. @default 'astryx-view' */
55
+ namespace?: string;
56
+ /**
57
+ * Called when `value` cannot be parsed/rendered (e.g. malformed JSON, or
58
+ * state authored with node types not registered via `nodes`). A read-only
59
+ * view renders *persisted* content — exactly where stale or foreign-schema
60
+ * state shows up — so by default a parse failure renders `errorFallback`
61
+ * instead of throwing and taking down the host. Provide `onParseError` to log or
62
+ * report it.
63
+ */
64
+ onParseError?: (error: Error) => void;
65
+ /**
66
+ * What to render when `value` fails to parse/render. Defaults to `null`
67
+ * (renders nothing). Pass a node to show a placeholder/empty state.
68
+ * @default null
69
+ */
70
+ errorFallback?: ReactNode;
71
+ }
72
+ /**
73
+ * A read-only renderer for serialized Lexical content. Renders the same styled
74
+ * output as {@link RichTextEditor} without any editing affordances.
75
+ *
76
+ * The output is document content, not a form field: headings, lists and links
77
+ * keep their own roles for assistive technology, and the view takes no label.
78
+ * For a labelled, read-only field, use `<RichTextEditor isReadOnly />`. A
79
+ * table wider than the view scrolls inside a region named "Table" that takes a
80
+ * tab stop while it overflows, as core `Table` does.
81
+ *
82
+ * @example
83
+ * ```
84
+ * import {RichTextView} from '@blue-patterns/richtext';
85
+ * <RichTextView value={storedEditorStateJSON} />
86
+ * ```
87
+ */
88
+ export declare function RichTextView({ value, nodes, markdownExtensions, codeLanguages, plugins, namespace, onParseError, errorFallback, xstyle, className, style, ...rest }: RichTextViewProps): import("react").JSX.Element;
89
+ export declare namespace RichTextView {
90
+ var displayName: string;
91
+ }
92
+ //# sourceMappingURL=RichTextView.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RichTextView.d.ts","sourceRoot":"","sources":["../src/RichTextView.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAA8B,KAAK,SAAS,EAAC,MAAM,OAAO,CAAC;AAGlE,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,qBAAqB,CAAC;AAmBnD,OAAO,KAAK,EAAC,yBAAyB,EAAC,MAAM,sBAAsB,CAAC;AACpE,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,+BAA+B,CAAC;AAEhE,OAAO,KAAK,EAEV,KAAK,EACL,WAAW,EAEZ,MAAM,SAAS,CAAC;AAoDjB,MAAM,WAAW,iBAAkB,SAAQ,SAAS;IAClD;;;OAGG;IACH,KAAK,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,KAAK,CAAC,EAAE,aAAa,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC;IAC1C;;;;;;;OAOG;IACH,kBAAkB,CAAC,EAAE,aAAa,CAAC,yBAAyB,CAAC,CAAC;IAC9D;;;;;;OAMG;IACH,aAAa,CAAC,EAAE,aAAa,CAAC,YAAY,CAAC,CAAC;IAC5C;;;OAGG;IACH,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB,6DAA6D;IAC7D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;;;;OAOG;IACH,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IACtC;;;;OAIG;IACH,aAAa,CAAC,EAAE,SAAS,CAAC;CAC3B;AAyCD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,YAAY,CAAC,EAC3B,KAAK,EACL,KAAK,EACL,kBAAkB,EAClB,aAAa,EACb,OAAO,EACP,SAAyB,EACzB,YAAY,EACZ,aAAoB,EACpB,MAAM,EACN,SAAS,EACT,KAAK,EACL,GAAG,IAAI,EACR,EAAE,iBAAiB,+BA8HnB;yBA3Ie,YAAY"}
@@ -0,0 +1,267 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ 'use client';
4
+
5
+ /**
6
+ * @file RichTextView.tsx
7
+ * @input Uses React, Lexical (lexical + @lexical/react, composed through
8
+ * LexicalExtensionComposer), mergeProps from core utils, design tokens,
9
+ * TableScrollRegionPlugin
10
+ * @output Exports RichTextView component and RichTextViewProps
11
+ * @position Read-only renderer for serialized Lexical editor state, exposed to
12
+ * assistive technology as document content rather than a form field;
13
+ * exported from @blue-patterns/richtext
14
+ *
15
+ * SYNC: When modified, update these files to stay in sync:
16
+ * - /packages/richtext/src/RichTextEditor.test.tsx
17
+ * - /packages/richtext/src/index.ts
18
+ * - /apps/storybook/stories/RichTextEditor.stories.tsx
19
+ */
20
+ import { useEffect, useRef, useState } from 'react';
21
+ import * as stylex from '@stylexjs/stylex';
22
+ import { sharedEditorTheme } from "./editorTheme.js";
23
+ import { mergeProps } from '@blue-patterns/core/utils';
24
+ import '@blue-patterns/core/theme/tokens.stylex';
25
+ import { colorVars, typeScaleVars, typographyVars } from '@blue-patterns/core/theme/tokens.stylex';
26
+ import { LexicalExtensionComposer } from '@lexical/react/LexicalExtensionComposer';
27
+ import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';
28
+ import { RichTextPlugin } from '@lexical/react/LexicalRichTextPlugin';
29
+ import { ContentEditable } from '@lexical/react/LexicalContentEditable';
30
+ import { LexicalErrorBoundary } from '@lexical/react/LexicalErrorBoundary';
31
+ import { TablePlugin } from '@lexical/react/LexicalTablePlugin';
32
+ import { TableScrollRegionPlugin } from "./internal/TableScrollRegionPlugin.js";
33
+ import { TableColumnFloorPlugin } from "./internal/TableColumnFloorPlugin.js";
34
+ import { CodeBlockHeaderPlugin } from "./internal/CodeBlockHeaderPlugin.js";
35
+ import { CodeSyntaxPlugin } from "./internal/CodeSyntaxPlugin.js";
36
+ import { MarkdownExtensionsPlugin } from "./internal/MarkdownExtensionsPlugin.js";
37
+ import { TaskCheckboxPlugin } from "./internal/TaskCheckboxPlugin.js";
38
+ import { defineExtension } from 'lexical';
39
+ import { TextSemanticsExtension } from "./textSemantics.js";
40
+ // The same node set as the editor, so anything it writes renders here.
41
+ import { DEFAULT_NODES } from "./editorNodes.js";
42
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
43
+ const styles = {
44
+ root: {
45
+ kzqmXN: "xh8yej3",
46
+ kVAEAm: "x1n2onr6",
47
+ kMv6JI: "x9ynric",
48
+ kGuDYH: "xjm74w1",
49
+ kLWn49: "xw6l6zx",
50
+ kMwMTN: "x1tgivj0",
51
+ $$css: true
52
+ }
53
+ };
54
+
55
+ /**
56
+ * Lexical's `ContentEditable` renders `role="textbox"` and widget-only ARIA
57
+ * (`aria-autocomplete`, `aria-readonly`) even when the editor is not editable.
58
+ * A view renders document content, not a form field, so all three are cleared:
59
+ *
60
+ * - A textbox is a widget, so an unnamed one fails axe
61
+ * `aria-input-field-name` — and a view has no name to give, because it is
62
+ * content rather than a labelled input.
63
+ * - The widget role exposes the rendered document to assistive technology
64
+ * as a form field rather than as the content it is.
65
+ * - Widget-only ARIA is invalid without a widget role, so clearing only the
66
+ * role would trade `aria-input-field-name` for `aria-allowed-attr`.
67
+ *
68
+ * `role` must be `null`, not `undefined`: Lexical substitutes its `textbox`
69
+ * default for `undefined`. The ARIA keys reach the element through Lexical's
70
+ * trailing prop spread, which is why `undefined` clears them. A proposed
71
+ * upstream fix (facebook/lexical#9270) would make these overrides no-ops.
72
+ *
73
+ * A caller who wants read-only form-field semantics instead wants
74
+ * `<RichTextEditor isReadOnly />`, which is a labelled field by construction.
75
+ */
76
+ const VIEW_CONTENT_EDITABLE_PROPS = {
77
+ 'aria-autocomplete': undefined,
78
+ 'aria-readonly': undefined,
79
+ role: null
80
+ };
81
+
82
+ /** The view imports and exports no Markdown, so it uses no transformers. */
83
+ const NO_TRANSFORMERS = [];
84
+ /**
85
+ * Keeps the rendered content in sync with the `value` prop after mount.
86
+ *
87
+ * The editor's initial state is seeded once, when the composer mounts, so a
88
+ * plain `<RichTextView value={changingValue} />` would freeze at its first
89
+ * value — the content would never update when `value` changed. This plugin runs
90
+ * inside the composer context and re-applies `value` whenever it changes, so the
91
+ * read-only view stays reactive (e.g. previewing content edited elsewhere).
92
+ *
93
+ * The initial `value` is already applied via the extension's
94
+ * `$initialEditorState`, so we skip the first run to avoid a redundant re-parse
95
+ * on mount.
96
+ *
97
+ * This mirrors the canonical Lexical pattern for applying externally-sourced
98
+ * serialized state after mount: the Lexical Playground's ActionsPlugin does the
99
+ * same `editor.setEditorState(editor.parseEditorState(...))` from inside a
100
+ * plugin (see facebook/lexical
101
+ * packages/lexical-playground/src/plugins/ActionsPlugin/index.tsx). It is
102
+ * necessary because the composer builds the editor once and reads the initial
103
+ * state exactly once at that point, so a changed prop cannot re-seed the editor
104
+ * on its own. A read-only view has no history, so we skip the Playground's
105
+ * accompanying CLEAR_HISTORY_COMMAND.
106
+ *
107
+ * `parseEditorState` / `setEditorState` are methods on the editor instance, so
108
+ * this plugin needs no module-level Lexical imports of its own.
109
+ */
110
+ function SyncValuePlugin({
111
+ value
112
+ }) {
113
+ const [editor] = useLexicalComposerContext();
114
+ const isFirstRun = useRef(true);
115
+ useEffect(() => {
116
+ if (isFirstRun.current) {
117
+ isFirstRun.current = false;
118
+ return;
119
+ }
120
+ editor.setEditorState(editor.parseEditorState(value));
121
+ }, [editor, value]);
122
+ return null;
123
+ }
124
+
125
+ /**
126
+ * A read-only renderer for serialized Lexical content. Renders the same styled
127
+ * output as {@link RichTextEditor} without any editing affordances.
128
+ *
129
+ * The output is document content, not a form field: headings, lists and links
130
+ * keep their own roles for assistive technology, and the view takes no label.
131
+ * For a labelled, read-only field, use `<RichTextEditor isReadOnly />`. A
132
+ * table wider than the view scrolls inside a region named "Table" that takes a
133
+ * tab stop while it overflows, as core `Table` does.
134
+ *
135
+ * @example
136
+ * ```
137
+ * import {RichTextView} from '@blue-patterns/richtext';
138
+ * <RichTextView value={storedEditorStateJSON} />
139
+ * ```
140
+ */
141
+ export function RichTextView({
142
+ value,
143
+ nodes,
144
+ markdownExtensions,
145
+ codeLanguages,
146
+ plugins,
147
+ namespace = 'astryx-view',
148
+ onParseError,
149
+ errorFallback = null,
150
+ xstyle,
151
+ className,
152
+ style,
153
+ ...rest
154
+ }) {
155
+ const themeRef = useRef(null);
156
+ if (themeRef.current === null) {
157
+ themeRef.current = sharedEditorTheme();
158
+ }
159
+
160
+ // Built on first render (and again after an error, below) rather than per
161
+ // render: LexicalExtensionComposer re-creates the editor whenever the
162
+ // extension's identity changes, and `value` updates are applied in place by
163
+ // SyncValuePlugin instead.
164
+ const extensionRef = useRef(null);
165
+ const [hasError, setHasError] = useState(false);
166
+
167
+ // Reset the error state when the value changes so a corrected value recovers.
168
+ const lastValueRef = useRef(value);
169
+ if (lastValueRef.current !== value && hasError) {
170
+ lastValueRef.current = value;
171
+ setHasError(false);
172
+ } else {
173
+ lastValueRef.current = value;
174
+ }
175
+
176
+ // A parse failure is recorded during render (below, or from Lexical's
177
+ // `onError` while the composer builds the editor) but reported to the
178
+ // consumer only after commit. Updating this component's own state during
179
+ // render is allowed; running a consumer's callback is not — a callback that
180
+ // updates its own component would do so during another component's render,
181
+ // and StrictMode or a discarded concurrent render would repeat it or run it
182
+ // for output that never commits. This Effect synchronizes the consumer's
183
+ // `onParseError`, reporting each distinct failure exactly once.
184
+ const pendingErrorRef = useRef(null);
185
+ const reportedErrorRef = useRef(null);
186
+ useEffect(() => {
187
+ const error = pendingErrorRef.current;
188
+ if (error !== null && error !== reportedErrorRef.current) {
189
+ reportedErrorRef.current = error;
190
+ onParseError?.(error);
191
+ }
192
+ });
193
+ const handleError = error => {
194
+ pendingErrorRef.current = error;
195
+ setHasError(true);
196
+ };
197
+
198
+ // Validate `value` parses as JSON before handing it to Lexical. Malformed
199
+ // JSON would otherwise throw synchronously while the composer builds the
200
+ // editor and escape any error boundary, taking down the host on the render
201
+ // path.
202
+ if (!hasError) {
203
+ try {
204
+ JSON.parse(value);
205
+ } catch (err) {
206
+ handleError(err instanceof Error ? err : new Error(String(err)));
207
+ }
208
+ }
209
+ if (hasError) {
210
+ // The composer subtree is unmounted while the fallback renders. Drop the
211
+ // extension so that recovering from the error builds a fresh one, seeded
212
+ // with the corrected `value`.
213
+ extensionRef.current = null;
214
+ return /*#__PURE__*/_jsx("div", {
215
+ ...mergeProps(stylex.props(styles.root, xstyle), className, style),
216
+ ...rest,
217
+ children: errorFallback
218
+ });
219
+ }
220
+ if (extensionRef.current === null) {
221
+ extensionRef.current = defineExtension({
222
+ name: '@blue-patterns/richtext/RichTextView',
223
+ namespace,
224
+ theme: themeRef.current,
225
+ editable: false,
226
+ nodes: nodes ? [...DEFAULT_NODES, ...nodes] : [...DEFAULT_NODES],
227
+ // Struck text is a deletion.
228
+ dependencies: [TextSemanticsExtension],
229
+ $initialEditorState: value,
230
+ // A read-only view renders persisted content; a bad node/schema should not
231
+ // crash the host. Surface it via onParseError + fallback instead of re-throwing.
232
+ onError: handleError
233
+ });
234
+ }
235
+ return /*#__PURE__*/_jsx("div", {
236
+ ...mergeProps(stylex.props(styles.root, xstyle), className, style),
237
+ ...rest,
238
+ children: /*#__PURE__*/_jsxs(LexicalExtensionComposer, {
239
+ extension: extensionRef.current,
240
+ contentEditable: null,
241
+ children: [/*#__PURE__*/_jsx(SyncValuePlugin, {
242
+ value: value
243
+ }), /*#__PURE__*/_jsx(TablePlugin, {
244
+ hasCellMerge: false,
245
+ hasCellBackgroundColor: false,
246
+ hasTabHandler: false,
247
+ hasHorizontalScroll: true
248
+ }), /*#__PURE__*/_jsx(TableScrollRegionPlugin, {}), /*#__PURE__*/_jsx(TableColumnFloorPlugin, {}), /*#__PURE__*/_jsx(RichTextPlugin, {
249
+ contentEditable: /*#__PURE__*/_jsx(ContentEditable, {
250
+ ...VIEW_CONTENT_EDITABLE_PROPS
251
+ }),
252
+ placeholder: null,
253
+ ErrorBoundary: LexicalErrorBoundary
254
+ }), /*#__PURE__*/_jsx(CodeBlockHeaderPlugin, {
255
+ codeLanguages: codeLanguages
256
+ }), /*#__PURE__*/_jsx(CodeSyntaxPlugin, {
257
+ codeLanguages: codeLanguages
258
+ }), markdownExtensions != null && markdownExtensions.length > 0 ? /*#__PURE__*/_jsx(MarkdownExtensionsPlugin, {
259
+ extensions: markdownExtensions,
260
+ transformers: NO_TRANSFORMERS
261
+ }) : null, /*#__PURE__*/_jsx(TaskCheckboxPlugin, {
262
+ isReadOnly: true
263
+ }), plugins]
264
+ })
265
+ });
266
+ }
267
+ RichTextView.displayName = 'RichTextView';
@@ -0,0 +1,14 @@
1
+ /**
2
+ * @file codeLanguages.ts
3
+ * @input CodeLanguage values from @blue-patterns/core/CodeBlock
4
+ * @output listedLanguage, which finds the listed value a fence word names, and
5
+ * sameLanguages, which compares two lists entry by entry
6
+ * @position Shared by CodeSyntaxPlugin and CodeBlockHeaderPlugin, so RichText
7
+ * resolves a fence as Markdown does (component:Markdown FR30)
8
+ */
9
+ import type { CodeLanguage } from '@blue-patterns/core/CodeBlock';
10
+ /** The listed value whose identifiers include `word`; a later entry wins. */
11
+ export declare function listedLanguage(languages: ReadonlyArray<CodeLanguage> | undefined, word: string): CodeLanguage | undefined;
12
+ /** Whether two lists name the same values in the same order. */
13
+ export declare function sameLanguages(a: ReadonlyArray<CodeLanguage> | undefined, b: ReadonlyArray<CodeLanguage> | undefined): boolean;
14
+ //# sourceMappingURL=codeLanguages.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"codeLanguages.d.ts","sourceRoot":"","sources":["../src/codeLanguages.ts"],"names":[],"mappings":"AAEA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,+BAA+B,CAAC;AAEhE,6EAA6E;AAC7E,wBAAgB,cAAc,CAC5B,SAAS,EAAE,aAAa,CAAC,YAAY,CAAC,GAAG,SAAS,EAClD,IAAI,EAAE,MAAM,GACX,YAAY,GAAG,SAAS,CAU1B;AAED,gEAAgE;AAChE,wBAAgB,aAAa,CAC3B,CAAC,EAAE,aAAa,CAAC,YAAY,CAAC,GAAG,SAAS,EAC1C,CAAC,EAAE,aAAa,CAAC,YAAY,CAAC,GAAG,SAAS,GACzC,OAAO,CAQT"}
@@ -0,0 +1,34 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ /**
4
+ * @file codeLanguages.ts
5
+ * @input CodeLanguage values from @blue-patterns/core/CodeBlock
6
+ * @output listedLanguage, which finds the listed value a fence word names, and
7
+ * sameLanguages, which compares two lists entry by entry
8
+ * @position Shared by CodeSyntaxPlugin and CodeBlockHeaderPlugin, so RichText
9
+ * resolves a fence as Markdown does (component:Markdown FR30)
10
+ */
11
+
12
+ /** The listed value whose identifiers include `word`; a later entry wins. */
13
+ export function listedLanguage(languages, word) {
14
+ if (languages == null) {
15
+ return undefined;
16
+ }
17
+ for (let i = languages.length - 1; i >= 0; i--) {
18
+ if (languages[i].identifiers.includes(word)) {
19
+ return languages[i];
20
+ }
21
+ }
22
+ return undefined;
23
+ }
24
+
25
+ /** Whether two lists name the same values in the same order. */
26
+ export function sameLanguages(a, b) {
27
+ if (a === b) {
28
+ return true;
29
+ }
30
+ if (a == null || b == null || a.length !== b.length) {
31
+ return false;
32
+ }
33
+ return a.every((language, i) => language === b[i]);
34
+ }
@@ -0,0 +1,53 @@
1
+ /**
2
+ * @file codeLineTokens.ts
3
+ * @input Core CodeBlock's tokenizer (`tokenize`) and token line type.
4
+ * @output Exports CodeLineTokens, which keeps core CodeBlock's tokens for a
5
+ * block of code line by line and re-tokenizes only the lines an edit can
6
+ * change.
7
+ * @position Used by CodeSyntaxPlugin. Its tokens always equal what `tokenize`
8
+ * returns for the whole code. An edit re-tokenizes only its own line, and
9
+ * at most the line above it, for the built-in TypeScript, JavaScript,
10
+ * Python, and shell grammars while every line passes `standsAlone`;
11
+ * anything else re-tokenizes all of it. The checks follow those grammars'
12
+ * patterns in core CodeBlock's tokenizer.ts, and codeLineTokens.test.ts
13
+ * compares edits against a full `tokenize`, so a grammar change that
14
+ * breaks them fails there.
15
+ */
16
+ import { type CodeLanguage, type TokenLine } from '@blue-patterns/core/CodeBlock';
17
+ /**
18
+ * Core CodeBlock's tokens for a block of code, kept line by line with
19
+ * line-relative offsets, exactly as `tokenize` returns them for the whole
20
+ * code.
21
+ */
22
+ export declare class CodeLineTokens {
23
+ readonly language: string | CodeLanguage;
24
+ /** Where each line starts in the code. */
25
+ starts: number[];
26
+ /** Each line's tokens. */
27
+ tokens: TokenLine[];
28
+ private lines;
29
+ private readonly family;
30
+ /** Whether every line stands alone, so an edit re-tokenizes lines alone. */
31
+ private linesStandAlone;
32
+ constructor(text: string, language: string | CodeLanguage);
33
+ /** The code. */
34
+ get text(): string;
35
+ /** The line that holds `offset` in the code. */
36
+ lineAt(offset: number): number;
37
+ /**
38
+ * Replaces `removed` characters at `offset` in the code with `inserted`.
39
+ * Returns the lines it re-tokenized when the edit stays inside one line
40
+ * and every line still stands alone; otherwise it re-tokenizes all the
41
+ * code and returns null.
42
+ */
43
+ replace(offset: number, removed: number, inserted: string): number[] | null;
44
+ /**
45
+ * A line's tokens as `tokenize` finds them in the whole code. A function
46
+ * name is a name followed by `(` past any whitespace, line breaks
47
+ * included, so when the line ends in a name, the code up to the next
48
+ * visible character is tokenized with it.
49
+ */
50
+ private tokenizeLine;
51
+ private tokenizeAll;
52
+ }
53
+ //# sourceMappingURL=codeLineTokens.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"codeLineTokens.d.ts","sourceRoot":"","sources":["../src/codeLineTokens.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAEL,KAAK,YAAY,EACjB,KAAK,SAAS,EACf,MAAM,+BAA+B,CAAC;AAkFvC;;;;GAIG;AACH,qBAAa,cAAc;IACzB,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,YAAY,CAAC;IACzC,0CAA0C;IAC1C,MAAM,EAAE,MAAM,EAAE,CAAM;IACtB,0BAA0B;IAC1B,MAAM,EAAE,SAAS,EAAE,CAAM;IACzB,OAAO,CAAC,KAAK,CAAgB;IAC7B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAgB;IACvC,4EAA4E;IAC5E,OAAO,CAAC,eAAe,CAAS;gBAEpB,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,YAAY;IAOzD,gBAAgB;IAChB,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED,gDAAgD;IAChD,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM;IAc9B;;;;;OAKG;IACH,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,IAAI;IA+C3E;;;;;OAKG;IACH,OAAO,CAAC,YAAY;IAkBpB,OAAO,CAAC,WAAW;CAgBpB"}
@@ -0,0 +1,188 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ /**
4
+ * @file codeLineTokens.ts
5
+ * @input Core CodeBlock's tokenizer (`tokenize`) and token line type.
6
+ * @output Exports CodeLineTokens, which keeps core CodeBlock's tokens for a
7
+ * block of code line by line and re-tokenizes only the lines an edit can
8
+ * change.
9
+ * @position Used by CodeSyntaxPlugin. Its tokens always equal what `tokenize`
10
+ * returns for the whole code. An edit re-tokenizes only its own line, and
11
+ * at most the line above it, for the built-in TypeScript, JavaScript,
12
+ * Python, and shell grammars while every line passes `standsAlone`;
13
+ * anything else re-tokenizes all of it. The checks follow those grammars'
14
+ * patterns in core CodeBlock's tokenizer.ts, and codeLineTokens.test.ts
15
+ * compares edits against a full `tokenize`, so a grammar change that
16
+ * breaks them fails there.
17
+ */
18
+
19
+ import { tokenize } from '@blue-patterns/core/CodeBlock';
20
+ const FAMILIES = new Map([['typescript', 'javascript'], ['javascript', 'javascript'], ['tsx', 'javascript'], ['jsx', 'javascript'], ['ts', 'javascript'], ['js', 'javascript'], ['python', 'python'], ['py', 'python'], ['bash', 'shell'], ['sh', 'shell'], ['zsh', 'shell'], ['shell', 'shell']]);
21
+
22
+ /** What can open a string or comment that runs on past its line. */
23
+ const OPENERS = {
24
+ javascript: /['"`]|\/\*/,
25
+ python: /['"]/,
26
+ shell: /['"`]|\$\{|\$\(|<</
27
+ };
28
+
29
+ /** A line whose last visible character can end a function name. */
30
+ const NAME_END = /[\w$]\s*$/;
31
+
32
+ /**
33
+ * Whether the name that ends a line can change color with the code after
34
+ * it: its last visible character is a name character outside every string,
35
+ * comment, number, keyword, and constant, whose patterns come before
36
+ * function names.
37
+ */
38
+ function endsInOpenName(text, tokens) {
39
+ const last = text.trimEnd().length - 1;
40
+ return NAME_END.test(text) && !tokens.some(token => token.start <= last && token.end > last && token.type !== 'function' && token.type !== 'type');
41
+ }
42
+
43
+ /** A line's first visible character, or '' when it has none. */
44
+ function firstVisible(line) {
45
+ return /\S/.exec(line)?.[0] ?? '';
46
+ }
47
+
48
+ /**
49
+ * Whether a line's strings and comments all close on it. Their patterns
50
+ * match line breaks, so an opener left open can run on to a later line.
51
+ * Only a string or comment the tokenizer emitted shields an opener: one that
52
+ * another token swallowed, such as `/*` in the operator `+/*`, still counts
53
+ * as open. Python tries triple quotes first, so `"""` can pair with another
54
+ * line even where its quotes close as single strings on this one.
55
+ */
56
+ function standsAlone(text, tokens, family) {
57
+ if (family === 'python' && /'''|"""/.test(text)) {
58
+ return false;
59
+ }
60
+ const opener = OPENERS[family];
61
+ let position = 0;
62
+ for (const token of tokens) {
63
+ if (token.end > text.length) {
64
+ return false;
65
+ }
66
+ if (token.type === 'string' || token.type === 'comment') {
67
+ if (opener.test(text.slice(position, token.start))) {
68
+ return false;
69
+ }
70
+ position = token.end;
71
+ }
72
+ }
73
+ return !opener.test(text.slice(position));
74
+ }
75
+
76
+ /**
77
+ * Core CodeBlock's tokens for a block of code, kept line by line with
78
+ * line-relative offsets, exactly as `tokenize` returns them for the whole
79
+ * code.
80
+ */
81
+ export class CodeLineTokens {
82
+ /** Where each line starts in the code. */
83
+ starts = [];
84
+ /** Each line's tokens. */
85
+ tokens = [];
86
+ lines = [];
87
+ /** Whether every line stands alone, so an edit re-tokenizes lines alone. */
88
+ linesStandAlone = false;
89
+ constructor(text, language) {
90
+ this.language = language;
91
+ this.family = typeof language === 'string' ? FAMILIES.get(language) ?? null : null;
92
+ this.tokenizeAll(text);
93
+ }
94
+
95
+ /** The code. */
96
+ get text() {
97
+ return this.lines.join('\n');
98
+ }
99
+
100
+ /** The line that holds `offset` in the code. */
101
+ lineAt(offset) {
102
+ let low = 0;
103
+ let high = this.starts.length - 1;
104
+ while (low < high) {
105
+ const mid = low + high + 1 >>> 1;
106
+ if (this.starts[mid] <= offset) {
107
+ low = mid;
108
+ } else {
109
+ high = mid - 1;
110
+ }
111
+ }
112
+ return low;
113
+ }
114
+
115
+ /**
116
+ * Replaces `removed` characters at `offset` in the code with `inserted`.
117
+ * Returns the lines it re-tokenized when the edit stays inside one line
118
+ * and every line still stands alone; otherwise it re-tokenizes all the
119
+ * code and returns null.
120
+ */
121
+ replace(offset, removed, inserted) {
122
+ const line = this.lineAt(offset);
123
+ const before = this.lines[line];
124
+ const column = offset - this.starts[line];
125
+ if (this.family == null || !this.linesStandAlone || column + removed > before.length || inserted.includes('\n')) {
126
+ const text = this.text;
127
+ this.tokenizeAll(text.slice(0, offset) + inserted + text.slice(offset + removed));
128
+ return null;
129
+ }
130
+ const after = before.slice(0, column) + inserted + before.slice(column + removed);
131
+ this.lines[line] = after;
132
+ const tokens = this.tokenizeLine(line);
133
+ if (!standsAlone(after, tokens, this.family)) {
134
+ this.tokenizeAll(this.text);
135
+ return null;
136
+ }
137
+ this.tokens[line] = tokens;
138
+ for (let i = line + 1; i < this.starts.length; i++) {
139
+ this.starts[i] += inserted.length - removed;
140
+ }
141
+ const changed = [line];
142
+ // A name that ends an earlier line looks past blank lines for `(`, so a
143
+ // new first visible character here can change that name's color.
144
+ if (firstVisible(before) !== firstVisible(after)) {
145
+ let above = line - 1;
146
+ while (above >= 0 && firstVisible(this.lines[above]) === '') {
147
+ above--;
148
+ }
149
+ if (above >= 0 && endsInOpenName(this.lines[above], this.tokens[above] ?? [])) {
150
+ this.tokens[above] = this.tokenizeLine(above);
151
+ changed.unshift(above);
152
+ }
153
+ }
154
+ return changed;
155
+ }
156
+
157
+ /**
158
+ * A line's tokens as `tokenize` finds them in the whole code. A function
159
+ * name is a name followed by `(` past any whitespace, line breaks
160
+ * included, so when the line ends in a name, the code up to the next
161
+ * visible character is tokenized with it.
162
+ */
163
+ tokenizeLine(line) {
164
+ let text = this.lines[line];
165
+ if (NAME_END.test(text)) {
166
+ for (let next = line + 1; next < this.lines.length; next++) {
167
+ const visible = /\S/.exec(this.lines[next]);
168
+ text += '\n' + (visible == null ? this.lines[next] : this.lines[next].slice(0, visible.index + 1));
169
+ if (visible != null) {
170
+ break;
171
+ }
172
+ }
173
+ }
174
+ return tokenize(text, this.language)[0] ?? [];
175
+ }
176
+ tokenizeAll(text) {
177
+ this.lines = text.split('\n');
178
+ let start = 0;
179
+ this.starts = this.lines.map(line => {
180
+ const lineStart = start;
181
+ start += line.length + 1;
182
+ return lineStart;
183
+ });
184
+ this.tokens = tokenize(text, this.language);
185
+ const family = this.family;
186
+ this.linesStandAlone = family != null && this.lines.every((line, i) => standsAlone(line, this.tokens[i] ?? [], family));
187
+ }
188
+ }
@@ -0,0 +1,8 @@
1
+ import type { Klass, LexicalNode } from 'lexical';
2
+ /**
3
+ * The default OSS node set registered with the editor: headings, quotes,
4
+ * lists, links, code, and tables. Extend via the `nodes` prop / option rather
5
+ * than editing this list.
6
+ */
7
+ export declare const DEFAULT_NODES: ReadonlyArray<Klass<LexicalNode>>;
8
+ //# sourceMappingURL=editorNodes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"editorNodes.d.ts","sourceRoot":"","sources":["../src/editorNodes.ts"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EAAC,KAAK,EAAE,WAAW,EAAC,MAAM,SAAS,CAAC;AAGhD;;;;GAIG;AACH,eAAO,MAAM,aAAa,EAAE,aAAa,CAAC,KAAK,CAAC,WAAW,CAAC,CAgB3D,CAAC"}