@astryxdesign/richtext 0.7.11 → 0.7.12-canary.ccb4a6d
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.
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"editorTheme.d.ts","sourceRoot":"","sources":["../src/editorTheme.ts"],"names":[],"mappings":"AA2BA,OAAO,KAAK,EAAC,kBAAkB,EAAC,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"editorTheme.d.ts","sourceRoot":"","sources":["../src/editorTheme.ts"],"names":[],"mappings":"AA2BA,OAAO,KAAK,EAAC,kBAAkB,EAAC,MAAM,SAAS,CAAC;AAschD;;;GAGG;AACH,wBAAgB,iBAAiB,IAAI,kBAAkB,CAgEtD"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@astryxdesign/richtext",
|
|
3
3
|
"displayName": "Rich Text",
|
|
4
|
-
"version": "0.7.
|
|
4
|
+
"version": "0.7.12-canary.ccb4a6d",
|
|
5
5
|
"description": "Astryx rich text — a Lexical-based rich text editor and viewer, styled with Astryx design tokens.",
|
|
6
6
|
"author": "Meta Open Source",
|
|
7
7
|
"license": "MIT",
|
|
@@ -66,7 +66,7 @@
|
|
|
66
66
|
},
|
|
67
67
|
"peerDependencies": {
|
|
68
68
|
"@stylexjs/stylex": ">=0.10.0",
|
|
69
|
-
"@astryxdesign/core": "0.7.
|
|
69
|
+
"@astryxdesign/core": "0.7.12-canary.ccb4a6d",
|
|
70
70
|
"react": ">=19.0.0",
|
|
71
71
|
"react-dom": ">=19.0.0",
|
|
72
72
|
"lexical": "^0.52.0",
|
|
@@ -125,6 +125,8 @@
|
|
|
125
125
|
}
|
|
126
126
|
},
|
|
127
127
|
"devDependencies": {
|
|
128
|
+
"@astryxdesign/a11y-spec": "0.7.12-canary.ccb4a6d",
|
|
129
|
+
"@astryxdesign/cli": "0.7.12-canary.ccb4a6d",
|
|
128
130
|
"@babel/cli": "^7.29.7",
|
|
129
131
|
"@babel/core": "^7.29.7",
|
|
130
132
|
"@babel/preset-react": "^7.29.7",
|
|
@@ -143,9 +145,7 @@
|
|
|
143
145
|
"@lexical/utils": "^0.52.0",
|
|
144
146
|
"@stylexjs/babel-plugin": "^0.19.0",
|
|
145
147
|
"@testing-library/react": "^16.3.2",
|
|
146
|
-
"lexical": "^0.52.0"
|
|
147
|
-
"@astryxdesign/a11y-spec": "0.0.0",
|
|
148
|
-
"@astryxdesign/cli": "0.7.11"
|
|
148
|
+
"lexical": "^0.52.0"
|
|
149
149
|
},
|
|
150
150
|
"scripts": {
|
|
151
151
|
"api:report": "node ../../scripts/api-report/cli.mjs --package .",
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
/** @type {import('@astryxdesign/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. 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,92 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
/** @type {import('@astryxdesign/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 an Astryx Dialog that adds, updates or removes a link and keeps the editor selection. 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 Dialog 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
|
+
};
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
/** @type {import('@astryxdesign/cli/authoring').ComponentDoc} */
|
|
4
|
+
|
|
5
|
+
export const docs = {
|
|
6
|
+
name: 'RichTextView',
|
|
7
|
+
displayName: 'Rich Text View',
|
|
8
|
+
category: 'Content',
|
|
9
|
+
keywords: [
|
|
10
|
+
'richtext',
|
|
11
|
+
'rich text',
|
|
12
|
+
'viewer',
|
|
13
|
+
'read-only',
|
|
14
|
+
'lexical',
|
|
15
|
+
'render',
|
|
16
|
+
'serialized',
|
|
17
|
+
],
|
|
18
|
+
props: [
|
|
19
|
+
{
|
|
20
|
+
name: 'value',
|
|
21
|
+
type: 'string',
|
|
22
|
+
description:
|
|
23
|
+
'Serialized editor state to render: the JSON string from JSON.stringify(editorState.toJSON()). The view updates when value changes.',
|
|
24
|
+
required: true,
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
name: 'nodes',
|
|
28
|
+
type: 'ReadonlyArray<Klass<LexicalNode>>',
|
|
29
|
+
description:
|
|
30
|
+
'Lexical nodes to register beyond the default set. Pass the same nodes the content was authored with, so custom node types deserialize.',
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
name: 'markdownExtensions',
|
|
34
|
+
type: 'ReadonlyArray<RichTextMarkdownExtension>',
|
|
35
|
+
description:
|
|
36
|
+
'Markdown plugins whose nodes this view draws, each adopted with createRichTextExtension. A plugin node renders as core Markdown renders it; a node whose plugin is not passed shows its source. Pass the extensions the content was converted with, created in a client module.',
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
name: 'codeLanguages',
|
|
40
|
+
type: 'ReadonlyArray<CodeLanguage>',
|
|
41
|
+
description:
|
|
42
|
+
"CodeBlock languages a fence may name, such as graphql from @astryxdesign/core/CodeBlock/languages/graphql. Pass the same list as Markdown's codeLanguages, so reading and editing label and paint the same languages.",
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
name: 'plugins',
|
|
46
|
+
type: 'ReactNode',
|
|
47
|
+
description:
|
|
48
|
+
'Read-only Lexical plugins to render inside the view, such as hover cards or decorators.',
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
name: 'namespace',
|
|
52
|
+
type: 'string',
|
|
53
|
+
description: 'The Lexical composer namespace.',
|
|
54
|
+
default: "'astryx-view'",
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
name: 'onParseError',
|
|
58
|
+
type: '(error: Error) => void',
|
|
59
|
+
description:
|
|
60
|
+
'Called when value cannot be parsed or rendered, for example malformed JSON or a node type that is not registered through nodes. Use it to log or report the failure.',
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
name: 'errorFallback',
|
|
64
|
+
type: 'ReactNode',
|
|
65
|
+
description:
|
|
66
|
+
'What to render when value cannot be parsed or rendered. The view renders it instead of throwing.',
|
|
67
|
+
default: 'null',
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
name: 'xstyle',
|
|
71
|
+
type: 'StyleXStyles',
|
|
72
|
+
description: 'StyleX styles for the view root.',
|
|
73
|
+
},
|
|
74
|
+
],
|
|
75
|
+
usage: {
|
|
76
|
+
description:
|
|
77
|
+
'Renders serialized RichTextEditor content read-only, with the same nodes, tables, code blocks and Markdown plugin nodes the editor draws. Ships from @astryxdesign/richtext, with lexical and @lexical/* as optional peer dependencies.',
|
|
78
|
+
bestPractices: [
|
|
79
|
+
{
|
|
80
|
+
guidance: true,
|
|
81
|
+
description:
|
|
82
|
+
'Store editorState.toJSON() from RichTextEditor onChange, and pass the stringified JSON as value.',
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
guidance: true,
|
|
86
|
+
description:
|
|
87
|
+
'Register the same custom nodes and markdownExtensions on the editor and the view, so stored content round-trips.',
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
guidance: true,
|
|
91
|
+
description:
|
|
92
|
+
'Pass onParseError and an errorFallback when the stored content can come from an older or a foreign schema. By default a parse failure renders nothing instead of throwing.',
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
guidance: false,
|
|
96
|
+
description:
|
|
97
|
+
'Use RichTextView to render Markdown source; use core Markdown for that.',
|
|
98
|
+
},
|
|
99
|
+
],
|
|
100
|
+
},
|
|
101
|
+
};
|
package/src/editorTheme.ts
CHANGED
|
@@ -62,9 +62,10 @@ const editorTheme = stylex.create({
|
|
|
62
62
|
// Lexical marks every top-level block `dir="auto"`, which picks each
|
|
63
63
|
// block's direction from its first strong character: a Hebrew paragraph in
|
|
64
64
|
// an English document flips to the right, an English one in an Arabic
|
|
65
|
-
// document to the left.
|
|
66
|
-
// them
|
|
67
|
-
//
|
|
65
|
+
// document to the left. Here blocks take the direction of the surface
|
|
66
|
+
// around them, and bidi inside a block still follows the Unicode
|
|
67
|
+
// algorithm. Core Markdown differs: it gives each block the direction of
|
|
68
|
+
// its own text.
|
|
68
69
|
providerDirection: {
|
|
69
70
|
direction: 'inherit',
|
|
70
71
|
},
|