@flexiui/svelte-rich-text 0.0.40 → 0.0.42
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/dist/RichText.svelte +24 -91
- package/dist/extensions/Audio.d.ts +22 -7
- package/dist/extensions/Audio.js +80 -88
- package/dist/extensions/AudioPlayer.svelte +2 -1
- package/dist/extensions/AudioPlayerWrapper.svelte +6 -0
- package/dist/extensions/Placeholder.d.ts +27 -0
- package/dist/extensions/Placeholder.js +61 -0
- package/dist/extensions/Table/TableCellNodeView.svelte +5 -6
- package/dist/getExtensions.js +8 -0
- package/dist/index.d.ts +3 -1
- package/dist/index.js +3 -1
- package/dist/styles.css +11 -39
- package/package.json +1 -1
package/dist/RichText.svelte
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
Mathematics,
|
|
4
4
|
migrateMathStrings,
|
|
5
5
|
} from "@tiptap/extension-mathematics";
|
|
6
|
+
|
|
6
7
|
import { HEADINGS, rgbToHex } from "./utils";
|
|
7
8
|
import "./styles.css";
|
|
8
9
|
import "katex/dist/katex.min.css";
|
|
@@ -97,90 +98,9 @@
|
|
|
97
98
|
...(config ?? {}),
|
|
98
99
|
});
|
|
99
100
|
|
|
100
|
-
// const extensions = [
|
|
101
|
-
// // Color.configure({ types: [TextStyle.name, ListItem.name] }),
|
|
102
|
-
// Highlight.configure({ multicolor: true }),
|
|
103
|
-
// TextStyleKit,
|
|
104
|
-
// StarterKit.configure({
|
|
105
|
-
// // Disable an included extension
|
|
106
|
-
// trailingNode: false,
|
|
107
|
-
// link: false,
|
|
108
|
-
// bulletList: false,
|
|
109
|
-
// listItem: false,
|
|
110
|
-
// orderedList: false,
|
|
111
|
-
// listKeymap: false,
|
|
112
|
-
// }),
|
|
113
|
-
// EnhancedLink,
|
|
114
|
-
// Audio.configure({
|
|
115
|
-
// HTMLAttributes: { class: "audio-player" },
|
|
116
|
-
// }),
|
|
117
|
-
// Image.configure({
|
|
118
|
-
// inline: true,
|
|
119
|
-
// }),
|
|
120
|
-
// ListKit,
|
|
121
|
-
// TextAlign.configure({
|
|
122
|
-
// types: [
|
|
123
|
-
// "heading",
|
|
124
|
-
// "paragraph",
|
|
125
|
-
// "bulletList",
|
|
126
|
-
// "taskList",
|
|
127
|
-
// "listItem",
|
|
128
|
-
// "blockquote",
|
|
129
|
-
// ],
|
|
130
|
-
// }),
|
|
131
|
-
// Mathematics.configure({
|
|
132
|
-
// inlineOptions: {
|
|
133
|
-
// onClick: (node, pos) => {
|
|
134
|
-
// // you can do anything on click, e.g. open a dialog to edit the math node
|
|
135
|
-
// // or just a prompt to edit the LaTeX code for a quick prototype
|
|
136
|
-
// const katex = prompt(
|
|
137
|
-
// "Update math LaTeX expression:",
|
|
138
|
-
// node.attrs.latex
|
|
139
|
-
// );
|
|
140
|
-
// if (katex) {
|
|
141
|
-
// $editor
|
|
142
|
-
// .chain()
|
|
143
|
-
// .setNodeSelection(pos)
|
|
144
|
-
// .updateInlineMath({ latex: katex })
|
|
145
|
-
// .focus()
|
|
146
|
-
// .run();
|
|
147
|
-
// }
|
|
148
|
-
// },
|
|
149
|
-
// },
|
|
150
|
-
// blockOptions: {
|
|
151
|
-
// // optional options for the block math node
|
|
152
|
-
// },
|
|
153
|
-
// katexOptions: {
|
|
154
|
-
// displayMode: false,
|
|
155
|
-
// throwOnError: false,
|
|
156
|
-
// macros: {
|
|
157
|
-
// "\\RR": "\\mathbb{R}",
|
|
158
|
-
// "\\ZZ": "\\mathbb{Z}",
|
|
159
|
-
// },
|
|
160
|
-
// },
|
|
161
|
-
// }),
|
|
162
|
-
// NodeLineHeight,
|
|
163
|
-
// MediaGridExtension,
|
|
164
|
-
// MediaGridItemExtension,
|
|
165
|
-
// TableKit.configure({
|
|
166
|
-
// table: {
|
|
167
|
-
// HTMLAttributes: { class: "fl-table-editable" },
|
|
168
|
-
// resizable: true,
|
|
169
|
-
// },
|
|
170
|
-
// }),
|
|
171
|
-
// CustomTableCell.configure({
|
|
172
|
-
// HTMLAttributes: { class: "fl-cell-editable" },
|
|
173
|
-
// }),
|
|
174
|
-
// CustomTableHeader.configure({
|
|
175
|
-
// HTMLAttributes: { class: "fl-cell-editable" },
|
|
176
|
-
// }),
|
|
177
|
-
// ...customExtensions,
|
|
178
|
-
// ];
|
|
179
|
-
|
|
180
101
|
const extensions = getRichTextExtensions({
|
|
181
102
|
editable: true,
|
|
182
103
|
customExtensions: [
|
|
183
|
-
...customExtensions,
|
|
184
104
|
Mathematics.configure({
|
|
185
105
|
inlineOptions: {
|
|
186
106
|
onClick: (node, pos) => {
|
|
@@ -211,7 +131,8 @@
|
|
|
211
131
|
"\\ZZ": "\\mathbb{Z}",
|
|
212
132
|
},
|
|
213
133
|
},
|
|
214
|
-
})
|
|
134
|
+
}),
|
|
135
|
+
...customExtensions,
|
|
215
136
|
]
|
|
216
137
|
});
|
|
217
138
|
|
|
@@ -674,16 +595,22 @@
|
|
|
674
595
|
<button
|
|
675
596
|
type="button"
|
|
676
597
|
onclick={(e) => toogleDropdown(e.currentTarget, "headings-dropdown")}
|
|
677
|
-
class:is-active={$editor.isActive("heading")}
|
|
598
|
+
class:is-active={$editor.isActive("heading") || $editor.isActive("h1")}
|
|
678
599
|
aria-label="Heading"
|
|
679
600
|
>
|
|
680
|
-
{#each HEADINGS as heading}
|
|
681
|
-
{#if $editor.isActive("heading", { level: Number(heading.level) })}
|
|
682
|
-
{@html heading.icon}
|
|
683
|
-
{/if}
|
|
684
|
-
{/each}
|
|
685
601
|
|
|
686
|
-
|
|
602
|
+
|
|
603
|
+
{#if $editor.isActive("heading")}
|
|
604
|
+
{#each HEADINGS as heading}
|
|
605
|
+
{#if $editor.isActive("heading", { level: Number(heading.level) })}
|
|
606
|
+
{@html heading.icon}
|
|
607
|
+
{/if}
|
|
608
|
+
{/each}
|
|
609
|
+
{:else if $editor.isActive("h1")}
|
|
610
|
+
{@html HEADINGS[0].icon}
|
|
611
|
+
{/if}
|
|
612
|
+
|
|
613
|
+
{#if !$editor.isActive("heading") && !$editor.isActive("h1")}
|
|
687
614
|
<svg
|
|
688
615
|
width="24"
|
|
689
616
|
height="24"
|
|
@@ -1365,7 +1292,7 @@
|
|
|
1365
1292
|
aria-label="Audio"
|
|
1366
1293
|
class:is-active={$editor.isActive("audio")}
|
|
1367
1294
|
>
|
|
1368
|
-
|
|
1295
|
+
<svg style="transform: scale(1.1);" fill="#e8eaed" width="24px" viewBox="0 -960 960 960" height="24px" xmlns="http://www.w3.org/2000/svg"><path d="M400-120q-66 0-113-47t-47-113q0-66 47-113t113-47q23 0 42.5 5.5T480-418v-422h240v160H560v400q0 66-47 113t-113 47Z"></path></svg>
|
|
1369
1296
|
</button>
|
|
1370
1297
|
</div>
|
|
1371
1298
|
|
|
@@ -1542,8 +1469,9 @@
|
|
|
1542
1469
|
type="button"
|
|
1543
1470
|
onclick={() =>
|
|
1544
1471
|
$editor.chain().focus().toggleHeading({ level: 1 }).run()}
|
|
1545
|
-
class={$editor.isActive("heading", { level: 1 }) ? "is-active" : ""}
|
|
1472
|
+
class={($editor.isActive("heading", { level: 1 }) || $editor.isActive("h1")) ? "is-active" : ""}
|
|
1546
1473
|
aria-label="H1"
|
|
1474
|
+
disabled={!$editor.isActive("h1")}
|
|
1547
1475
|
>
|
|
1548
1476
|
<svg
|
|
1549
1477
|
width="24"
|
|
@@ -1563,6 +1491,7 @@
|
|
|
1563
1491
|
$editor.chain().focus().toggleHeading({ level: 2 }).run()}
|
|
1564
1492
|
class={$editor.isActive("heading", { level: 2 }) ? "is-active" : ""}
|
|
1565
1493
|
aria-label="H2"
|
|
1494
|
+
disabled={$editor.isActive("h1")}
|
|
1566
1495
|
>
|
|
1567
1496
|
<svg
|
|
1568
1497
|
width="16"
|
|
@@ -1582,6 +1511,7 @@
|
|
|
1582
1511
|
$editor.chain().focus().toggleHeading({ level: 3 }).run()}
|
|
1583
1512
|
class={$editor.isActive("heading", { level: 3 }) ? "is-active" : ""}
|
|
1584
1513
|
aria-label="H3"
|
|
1514
|
+
disabled={$editor.isActive("h1")}
|
|
1585
1515
|
>
|
|
1586
1516
|
<svg
|
|
1587
1517
|
width="16"
|
|
@@ -1601,6 +1531,7 @@
|
|
|
1601
1531
|
$editor.chain().focus().toggleHeading({ level: 4 }).run()}
|
|
1602
1532
|
class={$editor.isActive("heading", { level: 4 }) ? "is-active" : ""}
|
|
1603
1533
|
aria-label="H4"
|
|
1534
|
+
disabled={$editor.isActive("h1")}
|
|
1604
1535
|
>
|
|
1605
1536
|
<svg
|
|
1606
1537
|
width="16"
|
|
@@ -1620,6 +1551,7 @@
|
|
|
1620
1551
|
$editor.chain().focus().toggleHeading({ level: 5 }).run()}
|
|
1621
1552
|
class={$editor.isActive("heading", { level: 5 }) ? "is-active" : ""}
|
|
1622
1553
|
aria-label="H5"
|
|
1554
|
+
disabled={$editor.isActive("h1")}
|
|
1623
1555
|
>
|
|
1624
1556
|
<svg
|
|
1625
1557
|
width="16"
|
|
@@ -1639,6 +1571,7 @@
|
|
|
1639
1571
|
$editor.chain().focus().toggleHeading({ level: 6 }).run()}
|
|
1640
1572
|
class={$editor.isActive("heading", { level: 6 }) ? "is-active" : ""}
|
|
1641
1573
|
aria-label="H6"
|
|
1574
|
+
disabled={$editor.isActive("h1")}
|
|
1642
1575
|
>
|
|
1643
1576
|
<svg
|
|
1644
1577
|
width="16"
|
|
@@ -3,27 +3,42 @@ export interface AudioOptions {
|
|
|
3
3
|
inline: boolean;
|
|
4
4
|
allowBase64: boolean;
|
|
5
5
|
HTMLAttributes: Record<string, any>;
|
|
6
|
+
bgColor: string;
|
|
7
|
+
textColor: string;
|
|
8
|
+
borderRadius: string;
|
|
9
|
+
accentColor: string;
|
|
10
|
+
accentColorPaused: string;
|
|
11
|
+
seekBarBgColor: string;
|
|
12
|
+
playBtnBgColor: string;
|
|
13
|
+
playBtnTextColor: string;
|
|
14
|
+
colorPlay: string;
|
|
15
|
+
maxWidth: string;
|
|
6
16
|
}
|
|
7
17
|
export interface SetAudioOptions {
|
|
8
18
|
src: string;
|
|
9
19
|
controls?: boolean;
|
|
10
20
|
autoplay?: boolean;
|
|
11
21
|
loop?: boolean;
|
|
22
|
+
bgColor?: string;
|
|
23
|
+
textColor?: string;
|
|
24
|
+
borderRadius?: string;
|
|
25
|
+
accentColor?: string;
|
|
26
|
+
accentColorPaused?: string;
|
|
27
|
+
seekBarBgColor?: string;
|
|
28
|
+
playBtnBgColor?: string;
|
|
29
|
+
playBtnTextColor?: string;
|
|
12
30
|
colorPlay?: string;
|
|
13
|
-
colorBar?: string;
|
|
14
31
|
maxWidth?: string;
|
|
15
32
|
}
|
|
16
33
|
declare module '@tiptap/core' {
|
|
17
34
|
interface Commands<ReturnType> {
|
|
18
35
|
audio: {
|
|
19
|
-
/**
|
|
20
|
-
* Añade un elemento de audio personalizado
|
|
21
|
-
* @example
|
|
22
|
-
* editor.commands.setAudio({ src: '/audio.mp3', controls: true })
|
|
23
|
-
*/
|
|
24
36
|
setAudio: (options: SetAudioOptions) => ReturnType;
|
|
25
37
|
};
|
|
26
38
|
}
|
|
27
39
|
}
|
|
28
|
-
|
|
40
|
+
/**
|
|
41
|
+
* Solo acepta: 
|
|
42
|
+
*/
|
|
43
|
+
export declare const audioInputRegex: RegExp;
|
|
29
44
|
export declare const Audio: Node<AudioOptions, any>;
|
package/dist/extensions/Audio.js
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
|
-
import { Node, mergeAttributes, nodeInputRule } from '@tiptap/core';
|
|
1
|
+
import { Node, mergeAttributes, nodeInputRule, } from '@tiptap/core';
|
|
2
|
+
import { Plugin } from '@tiptap/pm/state';
|
|
2
3
|
import { SvelteNodeViewRenderer } from 'svelte-tiptap';
|
|
3
4
|
import AudioPlayer from './AudioPlayerWrapper.svelte';
|
|
4
|
-
|
|
5
|
+
/**
|
|
6
|
+
* Solo acepta: 
|
|
7
|
+
*/
|
|
8
|
+
export const audioInputRegex = /(?:^|\s)(!\[audio\]\((\S+?)\))$/;
|
|
5
9
|
export const Audio = Node.create({
|
|
6
10
|
name: 'audio',
|
|
7
11
|
addOptions() {
|
|
@@ -9,6 +13,17 @@ export const Audio = Node.create({
|
|
|
9
13
|
inline: false,
|
|
10
14
|
allowBase64: false,
|
|
11
15
|
HTMLAttributes: {},
|
|
16
|
+
// 🎨 Defaults configurables para configure()
|
|
17
|
+
bgColor: '#8989891f',
|
|
18
|
+
textColor: 'currentColor',
|
|
19
|
+
borderRadius: '18px',
|
|
20
|
+
accentColor: '#5e17eb',
|
|
21
|
+
accentColorPaused: '#fff',
|
|
22
|
+
seekBarBgColor: '#8d8d8d3a',
|
|
23
|
+
playBtnBgColor: '#8d8d8d26',
|
|
24
|
+
playBtnTextColor: 'currentColor',
|
|
25
|
+
colorPlay: '#5d5d5dc9',
|
|
26
|
+
maxWidth: '100%',
|
|
12
27
|
};
|
|
13
28
|
},
|
|
14
29
|
inline() {
|
|
@@ -21,109 +36,58 @@ export const Audio = Node.create({
|
|
|
21
36
|
draggable: true,
|
|
22
37
|
addAttributes() {
|
|
23
38
|
return {
|
|
24
|
-
src: {
|
|
25
|
-
|
|
26
|
-
},
|
|
27
|
-
|
|
28
|
-
default: true,
|
|
29
|
-
parseHTML: el => el.hasAttribute('controls'),
|
|
30
|
-
renderHTML: attrs => (attrs.controls ? { controls: true } : {}),
|
|
31
|
-
},
|
|
32
|
-
autoplay: {
|
|
33
|
-
default: false,
|
|
34
|
-
parseHTML: el => el.hasAttribute('autoplay'),
|
|
35
|
-
renderHTML: attrs => (attrs.autoplay ? { autoplay: true } : {}),
|
|
36
|
-
},
|
|
37
|
-
loop: {
|
|
38
|
-
default: false,
|
|
39
|
-
parseHTML: el => el.hasAttribute('loop'),
|
|
40
|
-
renderHTML: attrs => (attrs.loop ? { loop: true } : {}),
|
|
41
|
-
},
|
|
39
|
+
src: { default: null },
|
|
40
|
+
controls: { default: true },
|
|
41
|
+
autoplay: { default: false },
|
|
42
|
+
loop: { default: false },
|
|
42
43
|
id: {
|
|
43
|
-
default: `fl-audio-player-${Math.random().toString(36).
|
|
44
|
-
|
|
45
|
-
renderHTML: attrs => ({
|
|
46
|
-
'data-id': attrs.id,
|
|
47
|
-
}),
|
|
44
|
+
default: `fl-audio-player-${Math.random().toString(36).slice(2)}`,
|
|
45
|
+
renderHTML: attrs => ({ 'data-id': attrs.id }),
|
|
48
46
|
},
|
|
49
47
|
bgColor: {
|
|
50
|
-
default:
|
|
51
|
-
|
|
52
|
-
renderHTML: attrs => ({
|
|
53
|
-
'data-bg-color': attrs.bgColor,
|
|
54
|
-
}),
|
|
48
|
+
default: this.options.bgColor,
|
|
49
|
+
renderHTML: a => ({ 'data-bg-color': a.bgColor }),
|
|
55
50
|
},
|
|
56
51
|
textColor: {
|
|
57
|
-
default:
|
|
58
|
-
|
|
59
|
-
renderHTML: attrs => ({
|
|
60
|
-
'data-text-color': attrs.textColor,
|
|
61
|
-
}),
|
|
52
|
+
default: this.options.textColor,
|
|
53
|
+
renderHTML: a => ({ 'data-text-color': a.textColor }),
|
|
62
54
|
},
|
|
63
55
|
borderRadius: {
|
|
64
|
-
default:
|
|
65
|
-
|
|
66
|
-
renderHTML: attrs => ({
|
|
67
|
-
'data-border-radius': attrs.borderRadius,
|
|
68
|
-
}),
|
|
56
|
+
default: this.options.borderRadius,
|
|
57
|
+
renderHTML: a => ({ 'data-border-radius': a.borderRadius }),
|
|
69
58
|
},
|
|
70
59
|
accentColor: {
|
|
71
|
-
default:
|
|
72
|
-
|
|
73
|
-
renderHTML: attrs => ({
|
|
74
|
-
'data-accent-color': attrs.accentColor,
|
|
75
|
-
}),
|
|
60
|
+
default: this.options.accentColor,
|
|
61
|
+
renderHTML: a => ({ 'data-accent-color': a.accentColor }),
|
|
76
62
|
},
|
|
77
63
|
accentColorPaused: {
|
|
78
|
-
default:
|
|
79
|
-
|
|
80
|
-
renderHTML: attrs => ({
|
|
81
|
-
'data-accent-color-paused': attrs.accentColorPaused,
|
|
82
|
-
}),
|
|
64
|
+
default: this.options.accentColorPaused,
|
|
65
|
+
renderHTML: a => ({ 'data-accent-color-paused': a.accentColorPaused }),
|
|
83
66
|
},
|
|
84
67
|
seekBarBgColor: {
|
|
85
|
-
default:
|
|
86
|
-
|
|
87
|
-
renderHTML: attrs => ({
|
|
88
|
-
'data-seek-bar-bg-color': attrs.seekBarBgColor,
|
|
89
|
-
}),
|
|
68
|
+
default: this.options.seekBarBgColor,
|
|
69
|
+
renderHTML: a => ({ 'data-seek-bar-bg-color': a.seekBarBgColor }),
|
|
90
70
|
},
|
|
91
71
|
playBtnBgColor: {
|
|
92
|
-
default:
|
|
93
|
-
|
|
94
|
-
renderHTML: attrs => ({
|
|
95
|
-
'data-play-btn-bg-color': attrs.playBtnBgColor,
|
|
96
|
-
}),
|
|
72
|
+
default: this.options.playBtnBgColor,
|
|
73
|
+
renderHTML: a => ({ 'data-play-btn-bg-color': a.playBtnBgColor }),
|
|
97
74
|
},
|
|
98
75
|
playBtnTextColor: {
|
|
99
|
-
default:
|
|
100
|
-
|
|
101
|
-
renderHTML: attrs => ({
|
|
102
|
-
'data-play-btn-text-color': attrs.playBtnTextColor,
|
|
103
|
-
}),
|
|
76
|
+
default: this.options.playBtnTextColor,
|
|
77
|
+
renderHTML: a => ({ 'data-play-btn-text-color': a.playBtnTextColor }),
|
|
104
78
|
},
|
|
105
79
|
colorPlay: {
|
|
106
|
-
default:
|
|
107
|
-
|
|
108
|
-
renderHTML: attrs => ({
|
|
109
|
-
'data-color-play': attrs.colorPlay,
|
|
110
|
-
}),
|
|
80
|
+
default: this.options.colorPlay,
|
|
81
|
+
renderHTML: a => ({ 'data-color-play': a.colorPlay }),
|
|
111
82
|
},
|
|
112
83
|
maxWidth: {
|
|
113
|
-
default:
|
|
114
|
-
|
|
115
|
-
renderHTML: attrs => ({
|
|
116
|
-
'data-max-width': attrs.maxWidth,
|
|
117
|
-
}),
|
|
84
|
+
default: this.options.maxWidth,
|
|
85
|
+
renderHTML: a => ({ 'data-max-width': a.maxWidth }),
|
|
118
86
|
},
|
|
119
87
|
};
|
|
120
88
|
},
|
|
121
89
|
parseHTML() {
|
|
122
|
-
return [
|
|
123
|
-
{
|
|
124
|
-
tag: 'fl-audio-player',
|
|
125
|
-
},
|
|
126
|
-
];
|
|
90
|
+
return [{ tag: 'fl-audio-player' }];
|
|
127
91
|
},
|
|
128
92
|
renderHTML({ HTMLAttributes }) {
|
|
129
93
|
return [
|
|
@@ -136,24 +100,52 @@ export const Audio = Node.create({
|
|
|
136
100
|
},
|
|
137
101
|
addCommands() {
|
|
138
102
|
return {
|
|
139
|
-
setAudio: options => ({ commands }) => {
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
});
|
|
144
|
-
},
|
|
103
|
+
setAudio: options => ({ commands }) => commands.insertContent({
|
|
104
|
+
type: this.name,
|
|
105
|
+
attrs: options,
|
|
106
|
+
}),
|
|
145
107
|
};
|
|
146
108
|
},
|
|
109
|
+
/**
|
|
110
|
+
* ✍️ Al escribir: 
|
|
111
|
+
*/
|
|
147
112
|
addInputRules() {
|
|
148
113
|
return [
|
|
149
114
|
nodeInputRule({
|
|
150
|
-
find:
|
|
115
|
+
find: audioInputRegex,
|
|
151
116
|
type: this.type,
|
|
152
117
|
getAttributes: match => {
|
|
153
|
-
const [, ,
|
|
118
|
+
const [, , src] = match;
|
|
154
119
|
return { src, controls: true };
|
|
155
120
|
},
|
|
156
121
|
}),
|
|
157
122
|
];
|
|
158
123
|
},
|
|
124
|
+
/**
|
|
125
|
+
* 📋 Al pegar: 
|
|
126
|
+
*/
|
|
127
|
+
addProseMirrorPlugins() {
|
|
128
|
+
return [
|
|
129
|
+
new Plugin({
|
|
130
|
+
props: {
|
|
131
|
+
handlePaste: (view, event) => {
|
|
132
|
+
const text = event.clipboardData?.getData('text/plain');
|
|
133
|
+
if (!text)
|
|
134
|
+
return false;
|
|
135
|
+
const match = text.match(/!\[audio\]\((\S+?)\)/);
|
|
136
|
+
if (!match)
|
|
137
|
+
return false;
|
|
138
|
+
const [, src] = match;
|
|
139
|
+
const { state, dispatch } = view;
|
|
140
|
+
const { from, to } = state.selection;
|
|
141
|
+
dispatch(state.tr.replaceRangeWith(from, to, this.type.create({
|
|
142
|
+
src,
|
|
143
|
+
controls: true,
|
|
144
|
+
})));
|
|
145
|
+
return true;
|
|
146
|
+
},
|
|
147
|
+
},
|
|
148
|
+
}),
|
|
149
|
+
];
|
|
150
|
+
},
|
|
159
151
|
});
|
|
@@ -498,7 +498,7 @@ style={styleVars}
|
|
|
498
498
|
|
|
499
499
|
.audio-player {
|
|
500
500
|
--player-primary-color: #5e17eb;
|
|
501
|
-
--player-bg-color: #
|
|
501
|
+
--player-bg-color: #8989891f;
|
|
502
502
|
--player-border-radius: 18px;
|
|
503
503
|
--player-seekbar-bg: #8d8d8d3a;
|
|
504
504
|
--player-seekbar-height: 6px;
|
|
@@ -516,6 +516,7 @@ style={styleVars}
|
|
|
516
516
|
width: 100%;
|
|
517
517
|
box-sizing: border-box;
|
|
518
518
|
color: var(--player-text-color);
|
|
519
|
+
margin-block: 1em;
|
|
519
520
|
|
|
520
521
|
&.playing {
|
|
521
522
|
.audio-player-wave {
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { Editor } from '@tiptap/core';
|
|
2
|
+
import { Extension } from '@tiptap/core';
|
|
3
|
+
import type { Node as ProsemirrorNode } from '@tiptap/pm/model';
|
|
4
|
+
export interface PlaceholderOptions {
|
|
5
|
+
emptyEditorClass: string;
|
|
6
|
+
emptyNodeClass: string;
|
|
7
|
+
placeholder: ((props: {
|
|
8
|
+
editor: Editor;
|
|
9
|
+
node: ProsemirrorNode;
|
|
10
|
+
pos: number;
|
|
11
|
+
hasAnchor: boolean;
|
|
12
|
+
}) => string) | string;
|
|
13
|
+
showOnlyWhenEditable: boolean;
|
|
14
|
+
showOnlyCurrent: boolean | ((props: {
|
|
15
|
+
editor: Editor;
|
|
16
|
+
node: ProsemirrorNode;
|
|
17
|
+
pos: number;
|
|
18
|
+
hasAnchor: boolean;
|
|
19
|
+
}) => boolean);
|
|
20
|
+
includeChildren: boolean | ((props: {
|
|
21
|
+
editor: Editor;
|
|
22
|
+
node: ProsemirrorNode;
|
|
23
|
+
pos: number;
|
|
24
|
+
hasAnchor: boolean;
|
|
25
|
+
}) => boolean);
|
|
26
|
+
}
|
|
27
|
+
export declare const Placeholder: Extension<PlaceholderOptions, any>;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { Extension, isNodeEmpty } from '@tiptap/core';
|
|
2
|
+
import { Plugin, PluginKey } from '@tiptap/pm/state';
|
|
3
|
+
import { Decoration, DecorationSet } from '@tiptap/pm/view';
|
|
4
|
+
export const Placeholder = Extension.create({
|
|
5
|
+
name: 'placeholder',
|
|
6
|
+
addOptions() {
|
|
7
|
+
return {
|
|
8
|
+
emptyEditorClass: 'is-editor-empty',
|
|
9
|
+
emptyNodeClass: 'is-empty',
|
|
10
|
+
placeholder: 'Write something …',
|
|
11
|
+
showOnlyWhenEditable: true,
|
|
12
|
+
showOnlyCurrent: true,
|
|
13
|
+
includeChildren: false,
|
|
14
|
+
};
|
|
15
|
+
},
|
|
16
|
+
addProseMirrorPlugins() {
|
|
17
|
+
return [
|
|
18
|
+
new Plugin({
|
|
19
|
+
key: new PluginKey('placeholder'),
|
|
20
|
+
props: {
|
|
21
|
+
decorations: ({ doc, selection }) => {
|
|
22
|
+
const active = this.editor.isEditable || !this.options.showOnlyWhenEditable;
|
|
23
|
+
const { anchor } = selection;
|
|
24
|
+
const decorations = [];
|
|
25
|
+
if (!active) {
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
const isEmptyDoc = this.editor.isEmpty;
|
|
29
|
+
doc.descendants((node, pos) => {
|
|
30
|
+
const hasAnchor = anchor >= pos && anchor <= pos + node.nodeSize;
|
|
31
|
+
const isEmpty = !node.isLeaf && isNodeEmpty(node);
|
|
32
|
+
// Evaluamos showOnlyCurrent dinámico
|
|
33
|
+
const showCurrent = typeof this.options.showOnlyCurrent === 'function'
|
|
34
|
+
? this.options.showOnlyCurrent({ editor: this.editor, node, pos, hasAnchor })
|
|
35
|
+
: this.options.showOnlyCurrent;
|
|
36
|
+
// Evaluamos includeChildren dinámico
|
|
37
|
+
const includeChildren = typeof this.options.includeChildren === 'function'
|
|
38
|
+
? this.options.includeChildren({ editor: this.editor, node, pos, hasAnchor })
|
|
39
|
+
: this.options.includeChildren;
|
|
40
|
+
if ((hasAnchor || !showCurrent) && isEmpty) {
|
|
41
|
+
const classes = [this.options.emptyNodeClass];
|
|
42
|
+
if (isEmptyDoc) {
|
|
43
|
+
classes.push(this.options.emptyEditorClass);
|
|
44
|
+
}
|
|
45
|
+
const decoration = Decoration.node(pos, pos + node.nodeSize, {
|
|
46
|
+
class: classes.join(' '),
|
|
47
|
+
'data-placeholder': typeof this.options.placeholder === 'function'
|
|
48
|
+
? this.options.placeholder({ editor: this.editor, node, pos, hasAnchor })
|
|
49
|
+
: this.options.placeholder,
|
|
50
|
+
});
|
|
51
|
+
decorations.push(decoration);
|
|
52
|
+
}
|
|
53
|
+
return includeChildren;
|
|
54
|
+
});
|
|
55
|
+
return DecorationSet.create(doc, decorations);
|
|
56
|
+
},
|
|
57
|
+
},
|
|
58
|
+
}),
|
|
59
|
+
];
|
|
60
|
+
},
|
|
61
|
+
});
|
|
@@ -47,14 +47,13 @@
|
|
|
47
47
|
}
|
|
48
48
|
|
|
49
49
|
editor.on("update", ({ transaction }) => {
|
|
50
|
-
|
|
51
|
-
if (node.type.name !== "tableCell" && node.type.name !== "tableHeader")
|
|
50
|
+
if (node?.type?.name !== "tableCell" && node?.type?.name !== "tableHeader")
|
|
52
51
|
return;
|
|
53
52
|
|
|
54
53
|
const nodeEl = editor.view.nodeDOM(getPos());
|
|
55
|
-
console.log(nodeEl);
|
|
54
|
+
// console.log(nodeEl);
|
|
56
55
|
|
|
57
|
-
console.log("update", transaction);
|
|
56
|
+
// console.log("update", transaction);
|
|
58
57
|
|
|
59
58
|
const attrs = node.attrs;
|
|
60
59
|
const { colspan, rowspan, colwidth } = attrs;
|
|
@@ -510,7 +509,7 @@
|
|
|
510
509
|
justify-content: center;
|
|
511
510
|
padding: 0;
|
|
512
511
|
color: #ffffff;
|
|
513
|
-
background: #
|
|
512
|
+
background: #8989891f;
|
|
514
513
|
border: none;
|
|
515
514
|
outline: 1px solid #6e6e6e;
|
|
516
515
|
z-index: 5;
|
|
@@ -539,7 +538,7 @@
|
|
|
539
538
|
letter-spacing: 2px;
|
|
540
539
|
padding: 0;
|
|
541
540
|
color: #ffffff;
|
|
542
|
-
background: #
|
|
541
|
+
background: #8989891f;
|
|
543
542
|
border: none;
|
|
544
543
|
outline: 1px solid #6e6e6e;
|
|
545
544
|
z-index: 5;
|
package/dist/getExtensions.js
CHANGED
|
@@ -14,9 +14,16 @@ import { MediaGridItemExtension } from "./extensions/MediaGrid/MediaGridItem";
|
|
|
14
14
|
import { CustomTableCell } from "./extensions/Table/CustomTableCell";
|
|
15
15
|
import { CustomTableHeader } from "./extensions/Table/CustomTableHeader";
|
|
16
16
|
import { EnhancedLink } from "./extensions/EnhancedLink";
|
|
17
|
+
import { Heading } from "@tiptap/extension-heading";
|
|
18
|
+
const DocHeading = Heading.extend({
|
|
19
|
+
name: "h1",
|
|
20
|
+
group: "none", // <- prevent it from being considered as a `block` in the body of the document
|
|
21
|
+
}).configure({ levels: [1] });
|
|
17
22
|
export function getRichTextExtensions(options) {
|
|
18
23
|
const { editable = false, customExtensions = [] } = options ?? {};
|
|
19
24
|
return [
|
|
25
|
+
DocHeading,
|
|
26
|
+
Heading.configure({ levels: [2, 3, 4, 5, 6] }),
|
|
20
27
|
Highlight.configure({ multicolor: true }),
|
|
21
28
|
TextStyleKit,
|
|
22
29
|
StarterKit.configure({
|
|
@@ -35,6 +42,7 @@ export function getRichTextExtensions(options) {
|
|
|
35
42
|
ListKit,
|
|
36
43
|
TextAlign.configure({
|
|
37
44
|
types: [
|
|
45
|
+
"h1",
|
|
38
46
|
"heading",
|
|
39
47
|
"paragraph",
|
|
40
48
|
"bulletList",
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
1
|
import RichText from './RichText.svelte';
|
|
2
2
|
import { renderHTMLFromJSON } from './renderRichText';
|
|
3
|
-
|
|
3
|
+
import { Placeholder as PlaceholderExt } from './extensions/Placeholder';
|
|
4
|
+
import { Audio as AudioExt } from './extensions/Audio';
|
|
5
|
+
export { RichText, PlaceholderExt, AudioExt, renderHTMLFromJSON };
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
1
|
import RichText from './RichText.svelte';
|
|
2
2
|
import { renderHTMLFromJSON } from './renderRichText';
|
|
3
|
-
|
|
3
|
+
import { Placeholder as PlaceholderExt } from './extensions/Placeholder';
|
|
4
|
+
import { Audio as AudioExt } from './extensions/Audio';
|
|
5
|
+
export { RichText, PlaceholderExt, AudioExt, renderHTMLFromJSON };
|
package/dist/styles.css
CHANGED
|
@@ -35,42 +35,6 @@
|
|
|
35
35
|
margin-bottom: 0;
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
-
/* Heading styles */
|
|
39
|
-
/* h1,
|
|
40
|
-
h2,
|
|
41
|
-
h3,
|
|
42
|
-
h4,
|
|
43
|
-
h5,
|
|
44
|
-
h6 {
|
|
45
|
-
line-height: 1.3;
|
|
46
|
-
margin-top: 1.5rem;
|
|
47
|
-
text-wrap: pretty;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
h1,
|
|
51
|
-
h2 {
|
|
52
|
-
margin-top: 1.5rem;
|
|
53
|
-
margin-bottom: 1.5rem;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
h1 {
|
|
57
|
-
font-size: 1.4rem;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
h2 {
|
|
61
|
-
font-size: 1.2rem;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
h3 {
|
|
65
|
-
font-size: 1.1rem;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
h4,
|
|
69
|
-
h5,
|
|
70
|
-
h6 {
|
|
71
|
-
font-size: 1rem;
|
|
72
|
-
} */
|
|
73
|
-
|
|
74
38
|
/* Code and preformatted text styles */
|
|
75
39
|
code {
|
|
76
40
|
background-color: var(--purple-light);
|
|
@@ -255,6 +219,14 @@
|
|
|
255
219
|
cursor: ew-resize;
|
|
256
220
|
cursor: col-resize;
|
|
257
221
|
}
|
|
222
|
+
|
|
223
|
+
.is-empty::before {
|
|
224
|
+
color: #8a8a8aa8;
|
|
225
|
+
content: attr(data-placeholder);
|
|
226
|
+
float: left;
|
|
227
|
+
height: 0;
|
|
228
|
+
pointer-events: none;
|
|
229
|
+
}
|
|
258
230
|
}
|
|
259
231
|
|
|
260
232
|
.fl-rich-text-content {
|
|
@@ -276,6 +248,7 @@
|
|
|
276
248
|
max-width: var(--fl-doc-max-width, 1024px);
|
|
277
249
|
margin-inline: var(--fl-doc-margin-inline, auto);
|
|
278
250
|
margin-block: var(--fl-doc-margin-block, 2rem);
|
|
251
|
+
box-sizing: border-box;
|
|
279
252
|
}
|
|
280
253
|
|
|
281
254
|
.fl-toolbar-dropdown-panel {
|
|
@@ -496,7 +469,6 @@
|
|
|
496
469
|
min-height: 32px;
|
|
497
470
|
|
|
498
471
|
& button {
|
|
499
|
-
background: transparent;
|
|
500
472
|
border: none;
|
|
501
473
|
display: flex;
|
|
502
474
|
align-items: center;
|
|
@@ -507,10 +479,10 @@
|
|
|
507
479
|
min-height: 18px;
|
|
508
480
|
min-width: 18px;
|
|
509
481
|
border-radius: 100%;
|
|
510
|
-
background: #
|
|
482
|
+
background: #8989891f;
|
|
511
483
|
|
|
512
484
|
&:hover {
|
|
513
|
-
background:
|
|
485
|
+
background: #89898966;
|
|
514
486
|
}
|
|
515
487
|
|
|
516
488
|
& svg {
|