|
7 | 7 | import { getCurrentText } from '$lib/richText/getText'; |
8 | 8 | // import CodeBlockTypeAhead from '$lib/richText/plugins/CodeBlockTypeAhead.svelte'; |
9 | 9 | import EmojiPlugin from '$lib/richText/plugins/Emoji.svelte'; |
10 | | - import PlainTextIndentPlugin from '$lib/richText/plugins/PlainTextIndentPlugin.svelte'; |
11 | | - import MarkdownTransitionPlugin from '$lib/richText/plugins/markdownTransition'; |
| 10 | + import IndentPlugin from '$lib/richText/plugins/IndentPlugin.svelte'; |
12 | 11 | import OnChangePlugin, { type OnChangeCallback } from '$lib/richText/plugins/onChange.svelte'; |
13 | 12 | import OnInput, { type OnInputCallback } from '$lib/richText/plugins/onInput.svelte'; |
14 | 13 | import { insertTextAtCaret, setEditorText } from '$lib/richText/selection'; |
|
26 | 25 | Composer, |
27 | 26 | ContentEditable, |
28 | 27 | RichTextPlugin, |
29 | | - ListPlugin, |
30 | | - CheckListPlugin, |
31 | 28 | AutoFocusPlugin, |
32 | 29 | PlaceHolder, |
33 | | - HashtagPlugin, |
34 | | - PlainTextPlugin, |
35 | | - AutoLinkPlugin, |
36 | | - FloatingLinkEditorPlugin, |
37 | | - CodeHighlightPlugin, |
38 | | - CodeActionMenuPlugin, |
39 | 30 | MarkdownShortcutPlugin, |
40 | | - ALL_TRANSFORMERS, |
41 | | - LinkPlugin, |
42 | 31 | HistoryPlugin |
43 | 32 | } from 'svelte-lexical'; |
44 | 33 |
|
45 | 34 | interface Props { |
46 | 35 | namespace: string; |
47 | | - plaintext: boolean; |
48 | 36 | onError: (error: unknown) => void; |
49 | 37 | styleContext: 'client-editor' | 'chat-input'; |
50 | 38 | plugins?: Snippet; |
|
70 | 58 | let { |
71 | 59 | disabled, |
72 | 60 | namespace, |
73 | | - plaintext, |
74 | 61 | onError, |
75 | 62 | minHeight, |
76 | 63 | maxHeight, |
|
109 | 96 | let editorDiv: HTMLDivElement | undefined = $state(); |
110 | 97 | let emojiPlugin = $state<ReturnType<typeof EmojiPlugin>>(); |
111 | 98 |
|
112 | | - // TODO: Change this plugin in favor of a toggle button. |
113 | | - const markdownTransitionPlugin = new MarkdownTransitionPlugin(wrapCountValue); |
114 | | -
|
115 | 99 | const isDisabled = $derived(disabled ?? false); |
116 | 100 |
|
117 | 101 | $effect(() => { |
|
128 | 112 | $effect(() => { |
129 | 113 | if (composer) { |
130 | 114 | const editor = composer.getEditor(); |
131 | | - markdownTransitionPlugin.setEditor(editor); |
132 | | - } |
133 | | - }); |
134 | | -
|
135 | | - $effect(() => { |
136 | | - markdownTransitionPlugin.setMarkdown(!plaintext); |
137 | | - }); |
138 | | -
|
139 | | - $effect(() => { |
140 | | - if (wrapCountValue) { |
141 | | - markdownTransitionPlugin.setMaxLength(wrapCountValue); |
142 | | - } |
143 | | - }); |
144 | | -
|
145 | | - $effect(() => { |
146 | | - if (composer) { |
147 | | - const editor = composer.getEditor(); |
148 | | - const unregidterKeyDown = editor.registerCommand<KeyboardEvent | null>( |
| 115 | + const unregisterKeyDown = editor.registerCommand<KeyboardEvent | null>( |
149 | 116 | KEY_DOWN_COMMAND, |
150 | 117 | (e) => { |
151 | 118 | if (emojiPlugin?.isBusy()) { |
|
173 | 140 | ); |
174 | 141 |
|
175 | 142 | return () => { |
176 | | - unregidterKeyDown(); |
| 143 | + unregisterKeyDown(); |
177 | 144 | unregisterFocus(); |
178 | 145 | unregisterBlur(); |
179 | 146 | }; |
|
187 | 154 | }); |
188 | 155 |
|
189 | 156 | async function updateInitialtext(initialText: string | undefined) { |
| 157 | + if (!composer) return; |
| 158 | +
|
| 159 | + // Set initial text if provided and editor is empty |
190 | 160 | if (initialText) { |
191 | 161 | const currentText = await getPlaintext(); |
192 | 162 | if (currentText?.trim() === '') { |
|
197 | 167 |
|
198 | 168 | export function getPlaintext(): Promise<string | undefined> { |
199 | 169 | return new Promise((resolve) => { |
200 | | - if (composer) { |
201 | | - const editor = composer.getEditor(); |
202 | | - editor?.read(() => { |
203 | | - const text = getCurrentText(!plaintext, wrapCountValue); |
204 | | - resolve(text); |
205 | | - }); |
| 170 | + if (!composer) { |
| 171 | + resolve(undefined); |
| 172 | + return; |
206 | 173 | } |
| 174 | + const editor = composer.getEditor(); |
| 175 | + editor.read(() => { |
| 176 | + const text = getCurrentText(true, wrapCountValue); |
| 177 | + resolve(text); |
| 178 | + }); |
207 | 179 | }); |
208 | 180 | } |
209 | 181 |
|
|
213 | 185 | resolve(0); |
214 | 186 | return; |
215 | 187 | } |
216 | | - composer.getEditor()?.read(() => { |
| 188 | + const editor = composer.getEditor(); |
| 189 | + editor.read(() => { |
217 | 190 | const root = getRoot(); |
218 | 191 | const count = root.getChildren().filter(isParagraphNode).length; |
219 | 192 | resolve(count); |
|
226 | 199 | return; |
227 | 200 | } |
228 | 201 | const editor = composer.getEditor(); |
229 | | - editor?.update(() => { |
| 202 | + editor.update(() => { |
230 | 203 | const root = getRoot(); |
231 | 204 | root.clear(); |
232 | 205 | }); |
|
239 | 212 | const editor = composer.getEditor(); |
240 | 213 | // We should be able to use `editor.focus()` here, but for some reason |
241 | 214 | // it only works after the input has already been focused. |
242 | | - editor.getRootElement()?.focus(); |
| 215 | + const rootElement = editor.getRootElement(); |
| 216 | + rootElement?.focus(); |
243 | 217 | } |
244 | 218 |
|
245 | 219 | export function wrapAll() { |
|
282 | 256 | class="lexical-container lexical-{styleContext} scrollbar" |
283 | 257 | bind:this={editorDiv} |
284 | 258 | use:focusable={{ button: true }} |
285 | | - class:plain-text={plaintext} |
286 | 259 | class:disabled={isDisabled} |
287 | 260 | style:min-height={minHeight} |
288 | 261 | style:max-height={maxHeight} |
|
305 | 278 | <EmojiPlugin bind:this={emojiPlugin} /> |
306 | 279 |
|
307 | 280 | <OnChangePlugin |
308 | | - markdown={!plaintext} |
| 281 | + markdown |
309 | 282 | onChange={(newValue, changeUpToAnchor, textAfterAnchor) => { |
310 | 283 | value = newValue; |
311 | 284 | onChange?.(newValue, changeUpToAnchor, textAfterAnchor); |
|
314 | 287 | /> |
315 | 288 |
|
316 | 289 | {#if onInput} |
317 | | - <OnInput markdown={!plaintext} {onInput} maxLength={wrapCountValue} /> |
| 290 | + <OnInput markdown {onInput} maxLength={wrapCountValue} /> |
318 | 291 | {/if} |
319 | 292 |
|
320 | | - {#if plaintext} |
321 | | - <PlainTextPlugin /> |
322 | | - <PlainTextIndentPlugin /> |
323 | | - <!-- <CodeBlockTypeAhead /> --> |
324 | | - <MarkdownShortcutPlugin transformers={[INLINE_CODE_TRANSFORMER]} /> |
325 | | - {:else} |
326 | | - <AutoLinkPlugin /> |
327 | | - <CheckListPlugin /> |
328 | | - <CodeActionMenuPlugin anchorElem={editorDiv} /> |
329 | | - <CodeHighlightPlugin /> |
330 | | - <FloatingLinkEditorPlugin anchorElem={editorDiv} /> |
331 | | - <HashtagPlugin /> |
332 | | - <ListPlugin /> |
333 | | - <LinkPlugin /> |
334 | | - <MarkdownShortcutPlugin transformers={ALL_TRANSFORMERS} /> |
335 | | - <RichTextPlugin /> |
336 | | - {/if} |
| 293 | + <RichTextPlugin /> |
| 294 | + <IndentPlugin /> |
| 295 | + <MarkdownShortcutPlugin transformers={[INLINE_CODE_TRANSFORMER]} /> |
| 296 | + |
337 | 297 | {#if autoFocus} |
338 | 298 | <AutoFocusPlugin /> |
339 | 299 | {/if} |
|
355 | 315 | background-color: var(--clr-bg-1); |
356 | 316 | } |
357 | 317 |
|
358 | | - .editor-scroller { |
359 | | - display: flex; |
360 | | - z-index: 0; |
361 | | - position: relative; |
362 | | - flex-direction: column; |
363 | | - height: 100%; |
364 | | - overflow: auto; |
365 | | - border: 0; |
366 | | - outline: 0; |
367 | | - /* It's unclear why the resizer is on by default on this element. */ |
368 | | - resize: none; |
369 | | - } |
370 | | -
|
371 | 318 | .editor { |
372 | 319 | z-index: -1; |
373 | 320 | position: relative; |
|
0 commit comments