@byline/richtext-lexical 3.4.0 → 3.5.0

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 (32) hide show
  1. package/dist/field/extensions/admonition/admonition-commands.d.ts +25 -0
  2. package/dist/field/extensions/admonition/admonition-commands.js +4 -0
  3. package/dist/field/extensions/admonition/admonition-extension.d.ts +2 -3
  4. package/dist/field/extensions/admonition/admonition-extension.js +138 -24
  5. package/dist/field/extensions/admonition/admonition-node.css +112 -0
  6. package/dist/field/extensions/admonition/admonition-node.d.ts +26 -14
  7. package/dist/field/extensions/admonition/admonition-node.js +121 -72
  8. package/dist/field/extensions/admonition/index.js +1 -0
  9. package/dist/field/extensions/admonition/node-types.d.ts +10 -4
  10. package/dist/field/extensions/floating-text-format/index.d.ts +8 -1
  11. package/dist/field/extensions/floating-text-format/index.js +6 -4
  12. package/dist/field/markdown/transformers.js +15 -15
  13. package/package.json +5 -5
  14. package/src/field/extensions/admonition/admonition-commands.ts +31 -0
  15. package/src/field/extensions/admonition/admonition-extension.tsx +248 -37
  16. package/src/field/extensions/admonition/admonition-node.css +113 -0
  17. package/src/field/extensions/admonition/admonition-node.tsx +172 -93
  18. package/src/field/extensions/admonition/index.ts +4 -8
  19. package/src/field/extensions/admonition/node-types.ts +10 -10
  20. package/src/field/extensions/floating-text-format/index.tsx +19 -3
  21. package/src/field/markdown/admonition-roundtrip.test.node.ts +110 -0
  22. package/src/field/markdown/transformers.ts +51 -25
  23. package/dist/field/extensions/admonition/admonition-node-component.css +0 -119
  24. package/dist/field/extensions/admonition/admonition-node-component.d.ts +0 -17
  25. package/dist/field/extensions/admonition/admonition-node-component.js +0 -196
  26. package/dist/field/extensions/admonition/icons/danger-icon.d.ts +0 -7
  27. package/dist/field/extensions/admonition/icons/index.d.ts +0 -4
  28. package/dist/field/extensions/admonition/icons/note-icon.d.ts +0 -7
  29. package/dist/field/extensions/admonition/icons/tip-icon.d.ts +0 -7
  30. package/dist/field/extensions/admonition/icons/warning-icon.d.ts +0 -7
  31. package/src/field/extensions/admonition/admonition-node-component.css +0 -115
  32. package/src/field/extensions/admonition/admonition-node-component.tsx +0 -257
@@ -24,6 +24,7 @@ import {
24
24
  $convertFromMarkdownString,
25
25
  $convertToMarkdownString,
26
26
  type ElementTransformer,
27
+ LINK,
27
28
  type MultilineElementTransformer,
28
29
  TEXT_FORMAT_TRANSFORMERS,
29
30
  TRANSFORMERS,
@@ -41,7 +42,7 @@ import {
41
42
  TableNode,
42
43
  TableRowNode,
43
44
  } from '@lexical/table'
44
- import { $isParagraphNode, $isTextNode } from 'lexical'
45
+ import { $createParagraphNode, $isParagraphNode, $isTextNode } from 'lexical'
45
46
 
46
47
  import {
47
48
  $createAdmonitionNode,
@@ -202,20 +203,32 @@ const mapToTableCells = (textContent: string): Array<TableCellNode> | null => {
202
203
  // ---------------------------------------------------------------------------
203
204
  // Admonitions → Docusaurus directive syntax: :::type[Title] … :::
204
205
  //
205
- // AdmonitionNode is a DecoratorNode whose body is a *nested* LexicalEditor
206
- // (a bare `createEditor()` — paragraph/text/linebreak only). So the body is
207
- // converted with an inline-only transformer set that matches what the nested
208
- // editor can hold; block constructs in the body are intentionally not
209
- // round-tripped because the node can't represent them anyway.
206
+ // Markdown format hat-tip: this mirrors Docusaurus admonitions
207
+ // https://docusaurus.io/docs/markdown-features/admonitions which in turn
208
+ // follow the remark-directive "generic directives" proposal
209
+ // (https://github.com/remarkjs/remark-directive). We support the four
210
+ // Docusaurus types (note / tip / warning / danger) and the optional
211
+ // `[Title]` on the opening fence.
212
+ //
213
+ // AdmonitionNode is an ElementNode whose body lives as real children in the
214
+ // main editor tree, so the body round-trips through the *same* markdown
215
+ // engine — no second editor, no second transformer registry. The body is
216
+ // deliberately restricted to formatted text + links (paragraphs only): the
217
+ // `ADMONITION_BODY_TRANSFORMERS` set never imports block constructs, and the
218
+ // extension's structure transform strips anything richer that slips in via
219
+ // paste. Type/title ride the opening fence, not the body.
210
220
  // ---------------------------------------------------------------------------
211
221
 
212
222
  const ADMONITION_TYPES: ReadonlySet<string> = new Set(['note', 'tip', 'warning', 'danger'])
213
223
  const ADMONITION_START_REG_EXP = /^:::(note|tip|warning|danger)(?:\[([^\]]*)\])?\s*$/
214
224
  const ADMONITION_END_REG_EXP = /^:::\s*$/
215
225
 
216
- // Inline-only the nested admonition editor has no block nodes beyond the
217
- // default paragraph, so importing headings/lists/tables into it would fail.
218
- const ADMONITION_BODY_TRANSFORMERS: Array<Transformer> = [...TEXT_FORMAT_TRANSFORMERS]
226
+ // Body restriction: inline text formatting + links. Paragraph splitting on
227
+ // blank lines is inherent to the markdown importer/exporter, so multi-
228
+ // paragraph bodies round-trip without any element transformer. Excluding the
229
+ // block transformers here is what keeps headings / lists / tables / nested
230
+ // admonitions out of an admonition body at parse time.
231
+ const ADMONITION_BODY_TRANSFORMERS: Array<Transformer> = [...TEXT_FORMAT_TRANSFORMERS, LINK]
219
232
 
220
233
  export const ADMONITION: MultilineElementTransformer = {
221
234
  dependencies: [AdmonitionNode],
@@ -226,18 +239,21 @@ export const ADMONITION: MultilineElementTransformer = {
226
239
  const type = node.getAdmonitionType()
227
240
  const title = node.getTitle()
228
241
 
229
- // Convert the nested editor's content to markdown in its own read context.
230
- let body = ''
231
- node.__content.read(() => {
232
- body = $convertToMarkdownString(ADMONITION_BODY_TRANSFORMERS).trim()
233
- })
242
+ // The body is real children of `node` export its subtree directly with
243
+ // the same engine.
244
+ const body = $convertToMarkdownString(ADMONITION_BODY_TRANSFORMERS, node).trim()
234
245
 
235
246
  const heading = title ? `:::${type}[${title}]` : `:::${type}`
236
247
  return body ? `${heading}\n${body}\n:::` : `${heading}\n:::`
237
248
  },
238
249
  regExpStart: ADMONITION_START_REG_EXP,
239
- regExpEnd: ADMONITION_END_REG_EXP,
240
- replace: (rootNode, children, startMatch, _endMatch, linesInBetween) => {
250
+ // `optional` is required for the as-you-type shortcut path to run this
251
+ // transformer at all: runMultilineElementTransformers skips any multiline
252
+ // transformer whose regExpEnd is non-optional (the closing ::: hasn't been
253
+ // typed yet when the start line fires). The toggle/import path still honours
254
+ // the explicit ::: end when present, falling back to EOF only if it's absent.
255
+ regExpEnd: { optional: true, regExp: ADMONITION_END_REG_EXP },
256
+ replace: (rootNode, children, startMatch, _endMatch, linesInBetween, isImport) => {
241
257
  const rawType = startMatch[1]
242
258
  if (!ADMONITION_TYPES.has(rawType)) {
243
259
  return false
@@ -247,21 +263,31 @@ export const ADMONITION: MultilineElementTransformer = {
247
263
 
248
264
  const node = $createAdmonitionNode({ admonitionType, title })
249
265
 
250
- // Import path: body arrives as the lines between the fences. Populate the
251
- // nested editor synchronously so it's flushed before render/serialize.
252
- if (!children && linesInBetween != null) {
266
+ if (children != null) {
267
+ // As-you-type shortcut path: the lines between the fences arrive as
268
+ // already-parsed nodes move them into the body. The structure
269
+ // transform normalises anything outside the allowed subset.
270
+ node.append(...children)
271
+ } else if (linesInBetween != null) {
272
+ // Import / toggle path: body arrives as raw text between the fences.
253
273
  const body = linesInBetween.join('\n').trim()
254
274
  if (body) {
255
- node.__content.update(
256
- () => {
257
- $convertFromMarkdownString(body, ADMONITION_BODY_TRANSFORMERS)
258
- },
259
- { discrete: true }
260
- )
275
+ $convertFromMarkdownString(body, ADMONITION_BODY_TRANSFORMERS, node)
261
276
  }
262
277
  }
263
278
 
279
+ // Never leave the shadow root empty (no place for the caret to land).
280
+ if (node.getChildrenSize() === 0) {
281
+ node.append($createParagraphNode())
282
+ }
283
+
264
284
  rootNode.append(node)
285
+
286
+ // Drop the caret into the body on the live shortcut path; the bulk import
287
+ // path manages selection itself.
288
+ if (!isImport) {
289
+ node.selectStart()
290
+ }
265
291
  },
266
292
  type: 'multiline-element',
267
293
  }
@@ -1,119 +0,0 @@
1
- .LexicalEditor__admonition .Admonition__container {
2
- border: 1px solid #666;
3
- border-radius: 2px;
4
- margin-top: .5rem;
5
- margin-bottom: 1.5rem;
6
- padding: 8px;
7
- position: relative;
8
- }
9
-
10
- .LexicalEditor__admonition .Admonition__container.focused {
11
- outline: 2px solid #3c84f4;
12
- }
13
-
14
- .LexicalEditor__admonition .Admonition__container .admonition-edit-button {
15
- z-index: 1;
16
- color: #fff;
17
- cursor: pointer;
18
- -webkit-user-select: none;
19
- user-select: none;
20
- background-color: #00000080;
21
- border: 1px solid #ffffff4d;
22
- border-radius: 5px;
23
- min-width: 60px;
24
- margin: 0 auto;
25
- padding: 3px 4px;
26
- font-size: .9rem;
27
- display: block;
28
- position: absolute;
29
- top: 8px;
30
- right: 12px;
31
- }
32
-
33
- .LexicalEditor__admonition .Admonition__container .admonition-edit-button:hover {
34
- background-color: #3c84f480;
35
- }
36
-
37
- .LexicalEditor__admonition .AdmonitionNode__header {
38
- align-items: center;
39
- margin-bottom: .75rem;
40
- font-size: 1.5rem;
41
- font-weight: bold;
42
- display: flex;
43
- }
44
-
45
- .LexicalEditor__admonition .AdmonitionNode__content {
46
- position: relative;
47
- }
48
-
49
- .LexicalEditor__admonition .AdmonitionNode__contentEditable {
50
- color: #000;
51
- background-color: #f4f4f4;
52
- min-width: 100%;
53
- display: block;
54
- position: relative;
55
- overflow: hidden;
56
- }
57
-
58
- .LexicalEditor__admonition .AdmonitionNode__contentEditable .tree-view-output {
59
- border-radius: 0;
60
- margin: 0;
61
- }
62
-
63
- .LexicalEditor__admonition .admonition-content-button:hover {
64
- background-color: #3c84f480;
65
- }
66
-
67
- .LexicalEditor__admonition .AdmonitionNode__contentEditable {
68
- resize: none;
69
- cursor: text;
70
- caret-color: #050505;
71
- -moz-tab-size: 1;
72
- tab-size: 1;
73
- -webkit-user-select: text;
74
- user-select: text;
75
- white-space: pre-wrap;
76
- word-break: break-word;
77
- border: 0;
78
- outline: 0;
79
- min-height: 20px;
80
- padding: 10px;
81
- font-size: 16px;
82
- line-height: 1.4em;
83
- display: block;
84
- position: relative;
85
- }
86
-
87
- .AdmonitionNode__contentEditable p {
88
- margin-bottom: .25em;
89
- }
90
-
91
- .Admonition__placeholder {
92
- color: #888;
93
- text-overflow: ellipsis;
94
- top: 10px;
95
- left: 10px;
96
- right: unset;
97
- -webkit-user-select: none;
98
- user-select: none;
99
- white-space: nowrap;
100
- pointer-events: none;
101
- font-size: 12px;
102
- display: inline-block;
103
- position: absolute;
104
- overflow: hidden;
105
- }
106
-
107
- .dark .AdmonitionNode__contentEditable {
108
- color: #eee;
109
- caret-color: auto;
110
- }
111
-
112
- .dark .LexicalEditor__admonition .AdmonitionNode__contentEditable {
113
- background-color: #222;
114
- }
115
-
116
- .dark .AdmonitionNode__placeholder {
117
- color: #888;
118
- }
119
-
@@ -1,17 +0,0 @@
1
- /**
2
- * This Source Code is subject to the terms of the Mozilla Public
3
- * License, v. 2.0. If a copy of the MPL was not distributed with this
4
- * file, You can obtain one at http://mozilla.org/MPL/2.0/.
5
- *
6
- * Copyright (c) Infonomic Company Limited
7
- */
8
- import type * as React from 'react';
9
- import type { LexicalEditor, NodeKey } from 'lexical';
10
- import type { AdmonitionType } from './node-types';
11
- import './admonition-node-component.css';
12
- export default function AdmonitionNodeComponent({ admonitionType, title, content, nodeKey, }: {
13
- admonitionType: AdmonitionType;
14
- title: string;
15
- content: LexicalEditor;
16
- nodeKey: NodeKey;
17
- }): React.JSX.Element;
@@ -1,196 +0,0 @@
1
- "use client";
2
- import { jsx, jsxs } from "react/jsx-runtime";
3
- import { Suspense, useCallback, useEffect, useRef, useState } from "react";
4
- import { useLexicalComposerContext } from "@lexical/react/LexicalComposerContext";
5
- import { LexicalErrorBoundary } from "@lexical/react/LexicalErrorBoundary";
6
- import { HistoryPlugin } from "@lexical/react/LexicalHistoryPlugin";
7
- import { LexicalNestedComposer } from "@lexical/react/LexicalNestedComposer";
8
- import { OnChangePlugin } from "@lexical/react/LexicalOnChangePlugin";
9
- import { RichTextPlugin } from "@lexical/react/LexicalRichTextPlugin";
10
- import { useLexicalNodeSelection } from "@lexical/react/useLexicalNodeSelection";
11
- import { mergeRegister } from "@lexical/utils";
12
- import classnames from "classnames";
13
- import { $getNodeByKey, $getSelection, $isNodeSelection, $setSelection, COMMAND_PRIORITY_LOW, KEY_BACKSPACE_COMMAND, KEY_DELETE_COMMAND, KEY_ENTER_COMMAND, KEY_ESCAPE_COMMAND, SELECTION_CHANGE_COMMAND } from "lexical";
14
- import { useEditorConfig } from "../../config/editor-config-context.js";
15
- import { ContentEditable } from "../../content-editable.js";
16
- import { useSharedHistoryContext } from "../../context/shared-history-context.js";
17
- import { useSharedOnChange } from "../../context/shared-on-change-context.js";
18
- import { Placeholder } from "../../ui/placeholder.js";
19
- import { FloatingTextFormatToolbarPlugin } from "../floating-text-format/index.js";
20
- import { FloatingLinkEditorPlugin } from "../link/floating-link-editor.js";
21
- import { LinkPlugin } from "../link/link-extension.js";
22
- import { AdmonitionModal } from "./admonition-modal.js";
23
- import { $isAdmonitionNode } from "./admonition-node.js";
24
- import { DangerIcon, NoteIcon, TipIcon, WarningIcon } from "./icons/index.js";
25
- import "./admonition-node-component.css";
26
- const icons = {
27
- note: NoteIcon,
28
- tip: TipIcon,
29
- warning: WarningIcon,
30
- danger: DangerIcon
31
- };
32
- function AdmonitionNodeComponent({ admonitionType, title, content, nodeKey }) {
33
- const [open, setOpen] = useState(false);
34
- const [editor] = useLexicalComposerContext();
35
- const buttonRef = useRef(null);
36
- const { historyState } = useSharedHistoryContext();
37
- const [isSelected, setSelected, _clearSelection] = useLexicalNodeSelection(nodeKey);
38
- const [selection, setSelection] = useState(null);
39
- const { uuid } = useEditorConfig();
40
- const { onChange } = useSharedOnChange();
41
- const editorState = editor.getEditorState();
42
- const activeEditorRef = useRef(null);
43
- const node = editorState.read(()=>$getNodeByKey(nodeKey));
44
- const onDelete = useCallback((payload)=>{
45
- if (isSelected && $isNodeSelection($getSelection())) {
46
- const event = payload;
47
- event.preventDefault();
48
- const node = $getNodeByKey(nodeKey);
49
- if ($isAdmonitionNode(node)) node?.remove();
50
- setSelected(false);
51
- }
52
- return false;
53
- }, [
54
- isSelected,
55
- nodeKey,
56
- setSelected
57
- ]);
58
- const onEnter = useCallback((event)=>{
59
- const latestSelection = $getSelection();
60
- if (isSelected && $isNodeSelection(latestSelection) && 1 === latestSelection.getNodes().length) {
61
- $setSelection(null);
62
- event.preventDefault();
63
- content.focus();
64
- return true;
65
- }
66
- return false;
67
- }, [
68
- content,
69
- isSelected
70
- ]);
71
- const onEscape = useCallback((event)=>{
72
- if (activeEditorRef.current === content || buttonRef.current === event.target) {
73
- $setSelection(null);
74
- editor.update(()=>{
75
- setSelected(true);
76
- const parentRootElement = editor.getRootElement();
77
- if (null !== parentRootElement) parentRootElement.focus();
78
- });
79
- return true;
80
- }
81
- return false;
82
- }, [
83
- content,
84
- editor,
85
- setSelected
86
- ]);
87
- useEffect(()=>{
88
- let isMounted = true;
89
- const unregister = mergeRegister(editor.registerUpdateListener(({ editorState })=>{
90
- if (isMounted) setSelection(editorState.read(()=>$getSelection()));
91
- }), editor.registerCommand(SELECTION_CHANGE_COMMAND, (_, activeEditor)=>{
92
- activeEditorRef.current = activeEditor;
93
- return false;
94
- }, COMMAND_PRIORITY_LOW), editor.registerCommand(KEY_DELETE_COMMAND, onDelete, COMMAND_PRIORITY_LOW), editor.registerCommand(KEY_BACKSPACE_COMMAND, onDelete, COMMAND_PRIORITY_LOW), editor.registerCommand(KEY_ENTER_COMMAND, onEnter, COMMAND_PRIORITY_LOW), editor.registerCommand(KEY_ESCAPE_COMMAND, onEscape, COMMAND_PRIORITY_LOW));
95
- return ()=>{
96
- isMounted = false;
97
- unregister();
98
- };
99
- }, [
100
- editor,
101
- onDelete,
102
- onEnter,
103
- onEscape
104
- ]);
105
- const draggable = isSelected && $isNodeSelection(selection);
106
- const isFocused = isSelected;
107
- const handleToggleModal = ()=>{
108
- if (null != uuid) setOpen(!open);
109
- };
110
- const handleUpdateAdmonition = ({ admonitionType, title })=>{
111
- setOpen(false);
112
- if (null != title && null != admonitionType) {
113
- const admonitionPayload = {
114
- admonitionType,
115
- title
116
- };
117
- editor.update(()=>{
118
- node.update(admonitionPayload);
119
- });
120
- } else console.error('Error: unable to find image source from document.');
121
- };
122
- const classNames = classnames('Admonition__container', {
123
- focused: isFocused
124
- }, {
125
- draggable: $isNodeSelection(selection)
126
- });
127
- const Icon = icons[admonitionType];
128
- return /*#__PURE__*/ jsxs(Suspense, {
129
- fallback: null,
130
- children: [
131
- /*#__PURE__*/ jsxs("div", {
132
- draggable: draggable,
133
- className: classNames,
134
- children: [
135
- /*#__PURE__*/ jsx("button", {
136
- type: "button",
137
- className: "admonition-edit-button",
138
- ref: buttonRef,
139
- onClick: handleToggleModal,
140
- children: "Edit"
141
- }),
142
- /*#__PURE__*/ jsxs("div", {
143
- className: "AdmonitionNode__header",
144
- children: [
145
- /*#__PURE__*/ jsx(Icon, {}),
146
- /*#__PURE__*/ jsx("div", {
147
- children: title
148
- })
149
- ]
150
- }),
151
- /*#__PURE__*/ jsx("div", {
152
- className: "AdmonitionNode__content",
153
- children: /*#__PURE__*/ jsxs(LexicalNestedComposer, {
154
- initialEditor: content,
155
- children: [
156
- /*#__PURE__*/ jsx(OnChangePlugin, {
157
- ignoreSelectionChange: true,
158
- onChange: (_nestedEditorState, _nestedEditor, nestedTags)=>{
159
- const editorState = editor.getEditorState();
160
- if (null != onChange) onChange(editorState, editor, nestedTags);
161
- }
162
- }),
163
- /*#__PURE__*/ jsx(LinkPlugin, {}),
164
- /*#__PURE__*/ jsx(FloatingLinkEditorPlugin, {}),
165
- /*#__PURE__*/ jsx(FloatingTextFormatToolbarPlugin, {}),
166
- /*#__PURE__*/ jsx(HistoryPlugin, {
167
- externalHistoryState: historyState
168
- }),
169
- /*#__PURE__*/ jsx(RichTextPlugin, {
170
- contentEditable: /*#__PURE__*/ jsx(ContentEditable, {
171
- className: "AdmonitionNode__contentEditable"
172
- }),
173
- placeholder: /*#__PURE__*/ jsx(Placeholder, {
174
- className: "Admonition__placeholder",
175
- children: "Enter some text..."
176
- }),
177
- ErrorBoundary: LexicalErrorBoundary
178
- })
179
- ]
180
- })
181
- })
182
- ]
183
- }),
184
- null != uuid && uuid.length > 0 && /*#__PURE__*/ jsx(AdmonitionModal, {
185
- open: open,
186
- onClose: handleToggleModal,
187
- onSubmit: handleUpdateAdmonition,
188
- data: {
189
- title,
190
- admonitionType
191
- }
192
- })
193
- ]
194
- });
195
- }
196
- export default AdmonitionNodeComponent;
@@ -1,7 +0,0 @@
1
- import type React from 'react';
2
- import './danger-icon.css';
3
- interface Props {
4
- className?: string;
5
- }
6
- export declare function DangerIcon({ className, ...rest }: Props): React.JSX.Element;
7
- export {};
@@ -1,4 +0,0 @@
1
- export * from './danger-icon';
2
- export * from './note-icon';
3
- export * from './tip-icon';
4
- export * from './warning-icon';
@@ -1,7 +0,0 @@
1
- import type React from 'react';
2
- import './note-icon.css';
3
- interface Props {
4
- className?: string;
5
- }
6
- export declare function NoteIcon({ className, ...rest }: Props): React.JSX.Element;
7
- export {};
@@ -1,7 +0,0 @@
1
- import type React from 'react';
2
- import './tip-icon.css';
3
- interface Props {
4
- className?: string;
5
- }
6
- export declare function TipIcon({ className, ...rest }: Props): React.JSX.Element;
7
- export {};
@@ -1,7 +0,0 @@
1
- import type React from 'react';
2
- import './warning-icon.css';
3
- interface Props {
4
- className?: string;
5
- }
6
- export declare function WarningIcon({ className, ...rest }: Props): React.JSX.Element;
7
- export {};
@@ -1,115 +0,0 @@
1
- .LexicalEditor__admonition .Admonition__container {
2
- position: relative;
3
- margin-top: 0.5rem;
4
- margin-bottom: 1.5rem;
5
- padding: 8px;
6
- border: solid 1px #666666;
7
- border-radius: 2px;
8
- }
9
-
10
- .LexicalEditor__admonition .Admonition__container.focused {
11
- outline: 2px solid rgb(60, 132, 244);
12
- /* user-select: none; */
13
- }
14
-
15
- .LexicalEditor__admonition .Admonition__container .admonition-edit-button {
16
- display: block;
17
- position: absolute;
18
- z-index: 1;
19
- font-size: 0.9rem;
20
- top: 8px;
21
- right: 12px;
22
- padding: 3px 4px;
23
- margin: 0 auto;
24
- border: 1px solid rgba(255, 255, 255, 0.3);
25
- border-radius: 5px;
26
- background-color: rgba(0, 0, 0, 0.5);
27
- min-width: 60px;
28
- color: #fff;
29
- cursor: pointer;
30
- user-select: none;
31
- }
32
-
33
- .LexicalEditor__admonition .Admonition__container .admonition-edit-button:hover {
34
- background-color: rgba(60, 132, 244, 0.5);
35
- }
36
-
37
- .LexicalEditor__admonition .AdmonitionNode__header {
38
- display: flex;
39
- align-items: center;
40
- font-weight: bold;
41
- font-size: 1.5rem;
42
- margin-bottom: 0.75rem;
43
- }
44
-
45
- .LexicalEditor__admonition .AdmonitionNode__content {
46
- position: relative;
47
- }
48
-
49
- .LexicalEditor__admonition .AdmonitionNode__contentEditable {
50
- display: block;
51
- position: relative;
52
- background-color: #f4f4f4;
53
- min-width: 100%;
54
- color: #000;
55
- overflow: hidden;
56
- }
57
-
58
- .LexicalEditor__admonition .AdmonitionNode__contentEditable .tree-view-output {
59
- margin: 0;
60
- border-radius: 0;
61
- }
62
-
63
- .LexicalEditor__admonition .admonition-content-button:hover {
64
- background-color: rgba(60, 132, 244, 0.5);
65
- }
66
-
67
- .LexicalEditor__admonition .AdmonitionNode__contentEditable {
68
- min-height: 20px;
69
- border: 0px;
70
- resize: none;
71
- cursor: text;
72
- caret-color: rgb(5, 5, 5);
73
- display: block;
74
- position: relative;
75
- tab-size: 1;
76
- outline: 0px;
77
- padding: 10px;
78
- user-select: text;
79
- font-size: 16px;
80
- line-height: 1.4em;
81
- white-space: pre-wrap;
82
- word-break: break-word;
83
- }
84
-
85
- .AdmonitionNode__contentEditable p {
86
- margin-bottom: 0.25em;
87
- }
88
-
89
- .Admonition__placeholder {
90
- font-size: 12px;
91
- color: #888;
92
- overflow: hidden;
93
- position: absolute;
94
- text-overflow: ellipsis;
95
- top: 10px;
96
- left: 10px;
97
- right: unset;
98
- user-select: none;
99
- white-space: nowrap;
100
- display: inline-block;
101
- pointer-events: none;
102
- }
103
-
104
- .dark .AdmonitionNode__contentEditable {
105
- color: #eeeeee;
106
- caret-color: auto;
107
- }
108
-
109
- .dark .LexicalEditor__admonition .AdmonitionNode__contentEditable {
110
- background-color: #222222;
111
- }
112
-
113
- .dark .AdmonitionNode__placeholder {
114
- color: #888;
115
- }