@flexiui/svelte-rich-text 0.0.61 → 0.0.63
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.
- package/README.md +14 -0
- package/dist/RichText.svelte +65 -69
- package/dist/RichText.svelte.d.ts +10 -83
- package/dist/getExtensions.d.ts +1 -0
- package/dist/getExtensions.js +2 -2
- package/dist/styles.css +9 -4
- package/dist/svelte-tiptap-extends/Editor.d.ts +4 -0
- package/dist/svelte-tiptap-extends/Editor.js +4 -0
- package/dist/svelte-tiptap-extends/EditorContent.svelte +62 -0
- package/dist/svelte-tiptap-extends/EditorContent.svelte.d.ts +15 -0
- package/dist/svelte-tiptap-extends/types.d.ts +10 -0
- package/dist/svelte-tiptap-extends/types.js +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -63,6 +63,18 @@ npm install @flexiui/svelte-rich-text
|
|
|
63
63
|
<RichText showToolbar={false} />
|
|
64
64
|
```
|
|
65
65
|
|
|
66
|
+
### With Content Wrapper Element
|
|
67
|
+
|
|
68
|
+
```svelte
|
|
69
|
+
<RichText contentWrapperAs="h1" />
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### Inline Node Mode
|
|
73
|
+
|
|
74
|
+
```svelte
|
|
75
|
+
<RichText inlineNodeMode={true} />
|
|
76
|
+
```
|
|
77
|
+
|
|
66
78
|
### With Node Limit
|
|
67
79
|
|
|
68
80
|
Limita el número de nodos de primer nivel que puede tener el documento.
|
|
@@ -215,6 +227,8 @@ Automáticamente convierte encabezados H1 adicionales en párrafos, permitiendo
|
|
|
215
227
|
| `customExtensions` | `any[]` | `[]` | Custom Tiptap extensions |
|
|
216
228
|
| `editorEvents` | `EditorEvents` | `{}` | Event handlers for editor events |
|
|
217
229
|
| `config` | `EditorConfig` | `{}` | Visual configuration options |
|
|
230
|
+
| `contentWrapperAs` | `T extends keyof SvelteHTMLElements` | `'div'` | HTML element type for content wrapper |
|
|
231
|
+
| `inlineNodeMode` | `boolean` | `false` | Enable inline node mode (uses inline document) |
|
|
218
232
|
|
|
219
233
|
## Editor Events
|
|
220
234
|
|
package/dist/RichText.svelte
CHANGED
|
@@ -1,49 +1,31 @@
|
|
|
1
|
-
<script lang="ts">
|
|
1
|
+
<script lang="ts" generics="T extends keyof SvelteHTMLElements = 'div'">
|
|
2
|
+
import type { SvelteHTMLElements } from 'svelte/elements';
|
|
2
3
|
import "./styles.css";
|
|
3
4
|
import "katex/dist/katex.min.css";
|
|
4
|
-
|
|
5
|
-
import { onMount, onDestroy, setContext } from "svelte";
|
|
5
|
+
import { onMount, onDestroy } from "svelte";
|
|
6
6
|
import type { Readable } from "svelte/store";
|
|
7
|
-
|
|
8
7
|
import { computePosition, offset, autoUpdate } from "@floating-ui/dom";
|
|
9
|
-
|
|
10
8
|
import {
|
|
11
9
|
Mathematics,
|
|
12
10
|
migrateMathStrings,
|
|
13
11
|
} from "@tiptap/extension-mathematics";
|
|
14
|
-
|
|
15
12
|
import { CharacterCount } from '@tiptap/extensions'
|
|
16
|
-
|
|
17
13
|
import { CellSelection } from "prosemirror-tables";
|
|
18
|
-
|
|
19
14
|
import {
|
|
20
15
|
createEditor,
|
|
21
16
|
Editor,
|
|
22
|
-
EditorContent,
|
|
17
|
+
// EditorContent,
|
|
23
18
|
BubbleMenu,
|
|
24
19
|
} from "svelte-tiptap";
|
|
25
20
|
|
|
21
|
+
import EditorContent from "./svelte-tiptap-extends/EditorContent.svelte";
|
|
26
22
|
import { getRichTextExtensions } from "./getExtensions";
|
|
27
|
-
|
|
28
23
|
import { rgbToHex } from "./utils";
|
|
29
24
|
|
|
30
|
-
import SpecialBox from "./Toolbar/action-buttons/marks/SpecialBox.svelte";
|
|
31
|
-
|
|
32
25
|
import MergeCellsBtn from "./Toolbar/action-buttons/MergeCellsBtn.svelte";
|
|
33
26
|
import SplitCellBtn from "./Toolbar/action-buttons/SplitCellBtn.svelte";
|
|
34
27
|
|
|
35
28
|
import HeadingBtn from "./Toolbar/action-buttons/nodes/HeadingBtn.svelte";
|
|
36
|
-
import HardBreakBtn from "./Toolbar/action-buttons/nodes/HardBreakBtn.svelte";
|
|
37
|
-
|
|
38
|
-
import CodeMarkBtn from "./Toolbar/action-buttons/marks/CodeMarkBtn.svelte";
|
|
39
|
-
import LinkBtn from "./Toolbar/action-buttons/marks/LinkBtn.svelte";
|
|
40
|
-
import Strike from "./Toolbar/action-buttons/marks/Strike.svelte";
|
|
41
|
-
import Underline from "./Toolbar/action-buttons/marks/Underline.svelte";
|
|
42
|
-
import Italic from "./Toolbar/action-buttons/marks/Italic.svelte";
|
|
43
|
-
import Bold from "./Toolbar/action-buttons/marks/Bold.svelte";
|
|
44
|
-
|
|
45
|
-
import HighlightDropdownBtn from "./Toolbar/dropdown-buttons/HighlightDropdownBtn.svelte";
|
|
46
|
-
import TextColorDropdownBtn from "./Toolbar/dropdown-buttons/TextColorDropdownBtn.svelte";
|
|
47
29
|
|
|
48
30
|
import LineHeightDropdown from "./Toolbar/dropdowns/LineHeightDropdown.svelte";
|
|
49
31
|
import ListBtn from "./Toolbar/action-buttons/nodes/ListBtn.svelte";
|
|
@@ -51,7 +33,11 @@
|
|
|
51
33
|
|
|
52
34
|
import RenderToolbarButton from "./Toolbar/RenderToolbarButton.svelte";
|
|
53
35
|
|
|
54
|
-
|
|
36
|
+
import { Document } from "@tiptap/extension-document";
|
|
37
|
+
|
|
38
|
+
const InlineDoc = Document.extend({ content: "inline*" })
|
|
39
|
+
|
|
40
|
+
interface Props {
|
|
55
41
|
id?: string;
|
|
56
42
|
className?: string;
|
|
57
43
|
editable?: boolean;
|
|
@@ -60,7 +46,8 @@
|
|
|
60
46
|
charactersLimit?: number;
|
|
61
47
|
limitWarningMessage?: string;
|
|
62
48
|
showToolbar?: boolean;
|
|
63
|
-
|
|
49
|
+
showCountersBar?: boolean;
|
|
50
|
+
toolbarAlign?: "left" | "center" | "right";
|
|
64
51
|
semanticHeadings?: boolean;
|
|
65
52
|
uniqueH1?: boolean;
|
|
66
53
|
toolbarConfig?: ToolbarConfig;
|
|
@@ -104,9 +91,10 @@
|
|
|
104
91
|
docTextColor?: string;
|
|
105
92
|
buttonStyle?: "accent-soft" | "accent-solid";
|
|
106
93
|
};
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
94
|
+
contentWrapperAs?: T;
|
|
95
|
+
inlineNodeMode?: boolean;
|
|
96
|
+
trailingNode?: boolean;
|
|
97
|
+
}
|
|
110
98
|
|
|
111
99
|
type ToolbarButton =
|
|
112
100
|
| string
|
|
@@ -138,6 +126,7 @@
|
|
|
138
126
|
charactersLimit,
|
|
139
127
|
limitWarningMessage,
|
|
140
128
|
showToolbar = true,
|
|
129
|
+
showCountersBar = true,
|
|
141
130
|
toolbarAlign = "center",
|
|
142
131
|
semanticHeadings = false,
|
|
143
132
|
uniqueH1 = false,
|
|
@@ -159,7 +148,10 @@
|
|
|
159
148
|
onPaste: () => {},
|
|
160
149
|
},
|
|
161
150
|
config,
|
|
162
|
-
|
|
151
|
+
contentWrapperAs = "div" as T,
|
|
152
|
+
inlineNodeMode = false,
|
|
153
|
+
trailingNode = true,
|
|
154
|
+
}: Props = $props();
|
|
163
155
|
|
|
164
156
|
let editor = $state() as Readable<Editor>;
|
|
165
157
|
|
|
@@ -241,7 +233,7 @@
|
|
|
241
233
|
|
|
242
234
|
const isAccentSoft = editorConfig.buttonStyle === "accent-soft";
|
|
243
235
|
let percentage = $derived.by(() => {
|
|
244
|
-
return $editor ?
|
|
236
|
+
return $editor ? (100 / charactersLimit) * $editor.storage.characterCount.characters() : 0
|
|
245
237
|
});
|
|
246
238
|
|
|
247
239
|
let toolbarGroups = $derived(
|
|
@@ -286,14 +278,13 @@
|
|
|
286
278
|
"rgb(255, 102, 142)",
|
|
287
279
|
];
|
|
288
280
|
|
|
289
|
-
const extensions = getRichTextExtensions({
|
|
290
|
-
editable: true,
|
|
291
|
-
|
|
281
|
+
const extensions = getRichTextExtensions({
|
|
282
|
+
editable: true,
|
|
283
|
+
trailingNode,
|
|
284
|
+
customExtensions: [
|
|
292
285
|
Mathematics.configure({
|
|
293
286
|
inlineOptions: {
|
|
294
287
|
onClick: (node, pos) => {
|
|
295
|
-
// you can do anything on click, e.g. open a dialog to edit the math node
|
|
296
|
-
// or just a prompt to edit the LaTeX code for a quick prototype
|
|
297
288
|
const katex = prompt(
|
|
298
289
|
"Update math LaTeX expression:",
|
|
299
290
|
node.attrs.latex,
|
|
@@ -321,7 +312,9 @@
|
|
|
321
312
|
},
|
|
322
313
|
}),
|
|
323
314
|
|
|
324
|
-
|
|
315
|
+
inlineNodeMode && InlineDoc,
|
|
316
|
+
|
|
317
|
+
CharacterCount.configure({
|
|
325
318
|
limit: charactersLimit,
|
|
326
319
|
}),
|
|
327
320
|
...customExtensions,
|
|
@@ -334,9 +327,9 @@
|
|
|
334
327
|
activeDropdownType = type;
|
|
335
328
|
|
|
336
329
|
if (tooltipVisible) {
|
|
337
|
-
hideDropdown();
|
|
330
|
+
hideDropdown();
|
|
338
331
|
} else {
|
|
339
|
-
hideDropdown();
|
|
332
|
+
hideDropdown();
|
|
340
333
|
currentTriggerEl = el;
|
|
341
334
|
tooltipVisible = true;
|
|
342
335
|
document.body.append(tooltip);
|
|
@@ -722,7 +715,7 @@
|
|
|
722
715
|
</header>
|
|
723
716
|
{/if}
|
|
724
717
|
|
|
725
|
-
<EditorContent editor={$editor} class="fl-rich-text-content" />
|
|
718
|
+
<EditorContent as={contentWrapperAs} editor={$editor} class="fl-rich-text-content" data-fl-editable="true" />
|
|
726
719
|
|
|
727
720
|
<!-- Warning message for node limit -->
|
|
728
721
|
{#if showLimitWarning && nodesLimit}
|
|
@@ -733,40 +726,43 @@
|
|
|
733
726
|
{/if}
|
|
734
727
|
|
|
735
728
|
<!-- Bottom bar showing node count -->
|
|
736
|
-
{#if
|
|
737
|
-
<div class="fl-
|
|
738
|
-
|
|
729
|
+
{#if showCountersBar || percentage >= 90}
|
|
730
|
+
<div class="fl-counters-bar">
|
|
731
|
+
<div class="fl-character-count" class:fl-character-count--warning={percentage >= 100}>
|
|
739
732
|
{#if charactersLimit}
|
|
740
|
-
<
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
</svg>
|
|
755
|
-
|
|
756
|
-
<span>
|
|
757
|
-
Characters count: {$editor?.storage?.characterCount?.characters()} / {charactersLimit}
|
|
758
|
-
</span>
|
|
759
|
-
|
|
760
|
-
<span>
|
|
761
|
-
Words count: {$editor?.storage?.characterCount?.words()}
|
|
762
|
-
</span>
|
|
763
|
-
</div>
|
|
733
|
+
<svg height="20" width="20" viewBox="0 0 20 20">
|
|
734
|
+
<circle r="10" cx="10" cy="10" fill="#ffffff30" />
|
|
735
|
+
<circle
|
|
736
|
+
r="5"
|
|
737
|
+
cx="10"
|
|
738
|
+
cy="10"
|
|
739
|
+
fill="transparent"
|
|
740
|
+
stroke="currentColor"
|
|
741
|
+
stroke-width="10"
|
|
742
|
+
stroke-dasharray={`calc(${percentage} * 31.4 / 100) 31.4`}
|
|
743
|
+
transform="rotate(-90) translate(-20)"
|
|
744
|
+
/>
|
|
745
|
+
<circle r="6" cx="10" cy="10" fill="var(--fl-editor-bg)" />
|
|
746
|
+
</svg>
|
|
764
747
|
{/if}
|
|
765
748
|
|
|
749
|
+
<span>
|
|
750
|
+
Characters: {$editor?.storage?.characterCount?.characters()}
|
|
751
|
+
{#if charactersLimit} / {charactersLimit}{/if}
|
|
752
|
+
</span>
|
|
753
|
+
</div>
|
|
766
754
|
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
755
|
+
{#if showCountersBar}
|
|
756
|
+
<span>
|
|
757
|
+
Words: {$editor?.storage?.characterCount?.words()}
|
|
758
|
+
</span>
|
|
759
|
+
{/if}
|
|
760
|
+
|
|
761
|
+
{#if nodesLimit}
|
|
762
|
+
<span class="fl-node-count-text">
|
|
763
|
+
Nodes: {currentNodeCount} / {nodesLimit}
|
|
764
|
+
</span>
|
|
765
|
+
{/if}
|
|
770
766
|
|
|
771
767
|
<!-- <div class="fl-node-count-progress">
|
|
772
768
|
<div
|
|
@@ -1,90 +1,17 @@
|
|
|
1
1
|
import { SvelteComponentTyped } from "svelte";
|
|
2
|
+
import type { SvelteHTMLElements } from 'svelte/elements';
|
|
2
3
|
import "./styles.css";
|
|
3
4
|
import "katex/dist/katex.min.css";
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
icon?: string;
|
|
8
|
-
name?: string;
|
|
9
|
-
};
|
|
10
|
-
type ToolbarSelect = {
|
|
11
|
-
select: ToolbarButton[];
|
|
12
|
-
name?: string;
|
|
13
|
-
tooltip?: string;
|
|
14
|
-
icon?: string;
|
|
15
|
-
type?: string;
|
|
16
|
-
};
|
|
17
|
-
type ToolbarItem = ToolbarButton | ToolbarSelect;
|
|
18
|
-
type ToolbarConfig = ToolbarItem[] | ToolbarItem[][];
|
|
19
|
-
type BubbleMenuConfig = ToolbarItem[] | ToolbarItem[][];
|
|
20
|
-
export interface Props {
|
|
21
|
-
id?: string;
|
|
22
|
-
className?: string;
|
|
23
|
-
editable?: boolean;
|
|
24
|
-
content?: string | {
|
|
25
|
-
type: string;
|
|
26
|
-
content: any[];
|
|
27
|
-
} | null;
|
|
28
|
-
nodesLimit?: number;
|
|
29
|
-
charactersLimit?: number;
|
|
30
|
-
limitWarningMessage?: string;
|
|
31
|
-
showToolbar?: boolean;
|
|
32
|
-
toolbarAlign?: string;
|
|
33
|
-
semanticHeadings?: boolean;
|
|
34
|
-
uniqueH1?: boolean;
|
|
35
|
-
toolbarConfig?: ToolbarConfig;
|
|
36
|
-
bubbleMenuConfig?: BubbleMenuConfig;
|
|
37
|
-
customExtensions?: any[];
|
|
38
|
-
editorEvents?: {
|
|
39
|
-
onTransaction?: (params: any) => void;
|
|
40
|
-
onBeforeCreate?: (params: any) => void;
|
|
41
|
-
onCreate?: (params: any) => void;
|
|
42
|
-
onUpdate: (params: any) => void;
|
|
43
|
-
onFocus?: (params: any) => void;
|
|
44
|
-
onBlur?: (params: any) => void;
|
|
45
|
-
onDestroy?: (params: any) => void;
|
|
46
|
-
onDrop?: (params: any) => void;
|
|
47
|
-
onDelete?: (params: any) => void;
|
|
48
|
-
onContentError?: (params: any) => void;
|
|
49
|
-
onSelectionUpdate?: (params: any) => void;
|
|
50
|
-
onPaste?: (params: any) => void;
|
|
51
|
-
};
|
|
52
|
-
config?: {
|
|
53
|
-
editorAccentColor?: string;
|
|
54
|
-
editorBgColor?: string;
|
|
55
|
-
editorRadius?: string;
|
|
56
|
-
toolbarStickyPosition?: number;
|
|
57
|
-
toolbarZIndex?: number;
|
|
58
|
-
toolbarBgColor?: string;
|
|
59
|
-
toolbarTextColor?: string;
|
|
60
|
-
toolbarPadding?: string;
|
|
61
|
-
toolbarJustifyContent?: string;
|
|
62
|
-
toolbarGap?: string;
|
|
63
|
-
toolbarBtnPadding?: string;
|
|
64
|
-
toolbarBtnRadius?: string;
|
|
65
|
-
toolbarBtnMinHeight?: string;
|
|
66
|
-
toolbarBtnMinWidth?: string;
|
|
67
|
-
docMaxWidth?: string;
|
|
68
|
-
docPadding?: string;
|
|
69
|
-
docBg?: string;
|
|
70
|
-
docMarginInline?: string;
|
|
71
|
-
docMarginBlock?: string;
|
|
72
|
-
docRadius?: string;
|
|
73
|
-
docTextColor?: string;
|
|
74
|
-
buttonStyle?: "accent-soft" | "accent-solid";
|
|
75
|
-
};
|
|
76
|
-
}
|
|
77
|
-
export type RichTextProps = Props;
|
|
78
|
-
declare const __propDef: {
|
|
79
|
-
props: Record<string, never>;
|
|
80
|
-
events: {
|
|
5
|
+
declare class __sveltets_Render<T extends keyof SvelteHTMLElements = 'div'> {
|
|
6
|
+
props(): Record<string, never>;
|
|
7
|
+
events(): {} & {
|
|
81
8
|
[evt: string]: CustomEvent<any>;
|
|
82
9
|
};
|
|
83
|
-
slots: {};
|
|
84
|
-
}
|
|
85
|
-
type
|
|
86
|
-
export type RichTextEvents =
|
|
87
|
-
export type RichTextSlots =
|
|
88
|
-
export default class RichText extends SvelteComponentTyped<
|
|
10
|
+
slots(): {};
|
|
11
|
+
}
|
|
12
|
+
export type RichTextProps<T extends keyof SvelteHTMLElements = 'div'> = ReturnType<__sveltets_Render<T>['props']>;
|
|
13
|
+
export type RichTextEvents<T extends keyof SvelteHTMLElements = 'div'> = ReturnType<__sveltets_Render<T>['events']>;
|
|
14
|
+
export type RichTextSlots<T extends keyof SvelteHTMLElements = 'div'> = ReturnType<__sveltets_Render<T>['slots']>;
|
|
15
|
+
export default class RichText<T extends keyof SvelteHTMLElements = 'div'> extends SvelteComponentTyped<RichTextProps<T>, RichTextEvents<T>, RichTextSlots<T>> {
|
|
89
16
|
}
|
|
90
17
|
export {};
|
package/dist/getExtensions.d.ts
CHANGED
package/dist/getExtensions.js
CHANGED
|
@@ -28,7 +28,7 @@ const DocHeading = Heading.extend({
|
|
|
28
28
|
},
|
|
29
29
|
}).configure({ levels: [1] });
|
|
30
30
|
export function getRichTextExtensions(options) {
|
|
31
|
-
const { editable = false, customExtensions = [] } = options ?? {};
|
|
31
|
+
const { editable = false, trailingNode = true, customExtensions = [] } = options ?? {};
|
|
32
32
|
return [
|
|
33
33
|
DocHeading,
|
|
34
34
|
Heading.configure({ levels: [2, 3, 4, 5, 6] }),
|
|
@@ -37,7 +37,7 @@ export function getRichTextExtensions(options) {
|
|
|
37
37
|
// fontSize: false
|
|
38
38
|
}),
|
|
39
39
|
StarterKit.configure({
|
|
40
|
-
trailingNode: false,
|
|
40
|
+
trailingNode: trailingNode ? undefined : false,
|
|
41
41
|
link: false,
|
|
42
42
|
bulletList: false,
|
|
43
43
|
listItem: false,
|
package/dist/styles.css
CHANGED
|
@@ -127,7 +127,8 @@
|
|
|
127
127
|
display: flex;
|
|
128
128
|
gap: 5px;
|
|
129
129
|
position: relative;
|
|
130
|
-
z-index:
|
|
130
|
+
z-index: var(--fl-toolbar-sticky-position, 10);
|
|
131
|
+
|
|
131
132
|
|
|
132
133
|
.fl-bubble-menu-mark-button {
|
|
133
134
|
border-radius: 9px;
|
|
@@ -540,7 +541,7 @@ button {
|
|
|
540
541
|
}
|
|
541
542
|
}
|
|
542
543
|
|
|
543
|
-
.fl-
|
|
544
|
+
.fl-counters-bar {
|
|
544
545
|
background: var(--fl-toolbar-bg, #242424);
|
|
545
546
|
border-top: 1px solid #333;
|
|
546
547
|
padding: 9px 12px;
|
|
@@ -551,12 +552,16 @@ button {
|
|
|
551
552
|
color: var(--fl-toolbar-text-color, currentColor);
|
|
552
553
|
border-bottom-left-radius: inherit;
|
|
553
554
|
border-bottom-right-radius: inherit;
|
|
555
|
+
|
|
556
|
+
span {
|
|
557
|
+
color: #ffffffab;
|
|
558
|
+
}
|
|
554
559
|
}
|
|
555
560
|
|
|
556
561
|
.fl-character-count {
|
|
557
562
|
display: flex;
|
|
558
563
|
align-items: center;
|
|
559
|
-
gap:
|
|
564
|
+
gap: 9px;
|
|
560
565
|
|
|
561
566
|
svg {
|
|
562
567
|
color: var(--fl-editor-accent-color);
|
|
@@ -565,7 +570,7 @@ button {
|
|
|
565
570
|
&.fl-character-count--warning {
|
|
566
571
|
color: #ff5c33;
|
|
567
572
|
|
|
568
|
-
svg {
|
|
573
|
+
svg, span {
|
|
569
574
|
color: currentColor;
|
|
570
575
|
}
|
|
571
576
|
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
<script lang="ts" generics="T extends keyof SvelteHTMLElements = 'div'">
|
|
2
|
+
import { onDestroy, onMount, tick } from 'svelte';
|
|
3
|
+
import type { SvelteHTMLElements } from 'svelte/elements';
|
|
4
|
+
import type { ComponentInputProps } from './types';
|
|
5
|
+
|
|
6
|
+
type Props = ComponentInputProps<{}> & SvelteHTMLElements[T] & {
|
|
7
|
+
as?: T;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
const { editor, children, class: className, as = 'div' as T, ...rest }: Props = $props();
|
|
11
|
+
let element: HTMLElement;
|
|
12
|
+
|
|
13
|
+
const init = async () => {
|
|
14
|
+
await tick();
|
|
15
|
+
if (!element) {
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
if (!editor?.options.element) {
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
if (editor.contentElement) {
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const editorElement = editor.options.element;
|
|
28
|
+
|
|
29
|
+
if (editorElement instanceof HTMLElement) {
|
|
30
|
+
element.append(...Array.from(editorElement.childNodes));
|
|
31
|
+
editor.setOptions({ element });
|
|
32
|
+
editor.contentElement = element;
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
onMount(init);
|
|
37
|
+
|
|
38
|
+
onDestroy(() => {
|
|
39
|
+
if (!editor) {
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
editor.contentElement = null;
|
|
44
|
+
|
|
45
|
+
const editorElement = editor.options.element;
|
|
46
|
+
|
|
47
|
+
if (editorElement instanceof HTMLElement && editorElement.firstChild) {
|
|
48
|
+
const newElement = document.createElement('div');
|
|
49
|
+
newElement.append(...Array.from(editorElement.childNodes));
|
|
50
|
+
|
|
51
|
+
editor.setOptions({
|
|
52
|
+
element: newElement,
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
</script>
|
|
57
|
+
|
|
58
|
+
<svelte:element this={as} bind:this={element} class={className} {...rest}>
|
|
59
|
+
{#if children}
|
|
60
|
+
{@render children()}
|
|
61
|
+
{/if}
|
|
62
|
+
</svelte:element>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { SvelteComponentTyped } from "svelte";
|
|
2
|
+
import type { SvelteHTMLElements } from 'svelte/elements';
|
|
3
|
+
declare class __sveltets_Render<T extends keyof SvelteHTMLElements = 'div'> {
|
|
4
|
+
props(): Record<string, never>;
|
|
5
|
+
events(): {} & {
|
|
6
|
+
[evt: string]: CustomEvent<any>;
|
|
7
|
+
};
|
|
8
|
+
slots(): {};
|
|
9
|
+
}
|
|
10
|
+
export type EditorContentProps<T extends keyof SvelteHTMLElements = 'div'> = ReturnType<__sveltets_Render<T>['props']>;
|
|
11
|
+
export type EditorContentEvents<T extends keyof SvelteHTMLElements = 'div'> = ReturnType<__sveltets_Render<T>['events']>;
|
|
12
|
+
export type EditorContentSlots<T extends keyof SvelteHTMLElements = 'div'> = ReturnType<__sveltets_Render<T>['slots']>;
|
|
13
|
+
export default class EditorContent<T extends keyof SvelteHTMLElements = 'div'> extends SvelteComponentTyped<EditorContentProps<T>, EditorContentEvents<T>, EditorContentSlots<T>> {
|
|
14
|
+
}
|
|
15
|
+
export {};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { Snippet } from 'svelte';
|
|
2
|
+
import type { Editor } from './Editor';
|
|
3
|
+
export interface TiptapNodeViewContext {
|
|
4
|
+
onDragStart: (event: DragEvent) => void;
|
|
5
|
+
}
|
|
6
|
+
export type ComponentInputProps<T> = Partial<T> & {
|
|
7
|
+
editor: Editor;
|
|
8
|
+
class?: string;
|
|
9
|
+
children?: Snippet;
|
|
10
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|