@seorii/tiptap 0.3.0-next.9 → 0.4.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.
- package/dist/i18n/index.d.ts +106 -6
- package/dist/i18n/index.js +56 -11
- package/dist/index.d.ts +2 -1
- package/dist/index.js +2 -1
- package/dist/plugin/command/emoji.d.ts +3 -17
- package/dist/plugin/command/emoji.js +51 -24
- package/dist/plugin/command/stores.svelte.d.ts +52 -0
- package/dist/plugin/command/stores.svelte.js +69 -0
- package/dist/plugin/command/suggest.d.ts +6 -19
- package/dist/plugin/command/suggest.js +149 -49
- package/dist/plugin/embed.d.ts +2 -2
- package/dist/plugin/embed.js +6 -2
- package/dist/plugin/iframe.js +1 -1
- package/dist/plugin/image/dragdrop.d.ts +2 -0
- package/dist/plugin/image/dragdrop.js +126 -15
- package/dist/plugin/image/index.js +4 -3
- package/dist/plugin/indent.js +0 -1
- package/dist/plugin/orderedlist/index.d.ts +1 -1
- package/dist/plugin/orderedlist/index.js +1 -1
- package/dist/plugin/orderedlist/{korean.scss → korean.css} +2 -2
- package/dist/plugin/resize/index.d.ts +8 -0
- package/dist/plugin/resize/index.js +454 -0
- package/dist/plugin/table/index.d.ts +1 -1
- package/dist/plugin/table/index.js +19 -11
- package/dist/plugin/table/style/{cell.scss → cell.css} +6 -5
- package/dist/plugin/table/style/{grip.scss → grip.css} +14 -19
- package/dist/plugin/table/style/resize.css +28 -0
- package/dist/plugin/table/style/{table.scss → table.css} +15 -17
- package/dist/plugin/table/style.css +4 -0
- package/dist/plugin/table/tableCell/index.js +2 -4
- package/dist/plugin/table/tableHeader/index.js +1 -2
- package/dist/plugin/upload/skeleton/UploadSkeleton.svelte +97 -0
- package/dist/plugin/upload/skeleton/UploadSkeleton.svelte.d.ts +5 -0
- package/dist/plugin/upload/skeleton/index.d.ts +30 -0
- package/dist/plugin/upload/skeleton/index.js +147 -0
- package/dist/plugin/youtube.js +1 -1
- package/dist/tiptap/Bubble.svelte +231 -92
- package/dist/tiptap/Bubble.svelte.d.ts +9 -6
- package/dist/tiptap/Command.svelte +160 -158
- package/dist/tiptap/Command.svelte.d.ts +2 -3
- package/dist/tiptap/Floating.svelte +51 -24
- package/dist/tiptap/Floating.svelte.d.ts +1 -0
- package/dist/tiptap/TipTap.svelte +302 -140
- package/dist/tiptap/TipTap.svelte.d.ts +10 -3
- package/dist/tiptap/ToolbarButton.svelte +30 -10
- package/dist/tiptap/ToolbarButton.svelte.d.ts +10 -6
- package/dist/tiptap/setMath.d.ts +2 -1
- package/dist/tiptap/setMath.js +74 -12
- package/dist/tiptap/tiptap.d.ts +9 -1
- package/dist/tiptap/tiptap.js +172 -16
- package/package.json +63 -57
- package/dist/plugin/command/stores.d.ts +0 -13
- package/dist/plugin/command/stores.js +0 -7
- package/dist/plugin/table/style/resize.scss +0 -26
- package/dist/plugin/table/style.scss +0 -4
|
@@ -1,23 +1,45 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import { BubbleMenu } from 'svelte-tiptap';
|
|
3
|
-
import { getContext, tick } from 'svelte';
|
|
3
|
+
import { flushSync, getContext, tick, untrack } from 'svelte';
|
|
4
4
|
import 'tippy.js/animations/shift-away-subtle.css';
|
|
5
5
|
import ToolbarButton from './ToolbarButton.svelte';
|
|
6
6
|
import { isTableAnySelected } from '../plugin/table/util';
|
|
7
7
|
import deleteTable from '../plugin/table/deleteTable';
|
|
8
8
|
import setMath from './setMath';
|
|
9
9
|
import { Button, Icon, IconButton, Input, List, OneLine, Paper, Render } from 'nunui';
|
|
10
|
-
import
|
|
10
|
+
import defaultI18n, { I18N_CONTEXT, type I18nTranslate } from '../i18n';
|
|
11
11
|
import ColorPicker from 'svelte-awesome-color-picker';
|
|
12
12
|
import { isTextSelection } from '@tiptap/core';
|
|
13
|
+
import { NodeSelection, type EditorState, type Selection } from '@tiptap/pm/state';
|
|
14
|
+
import type { EditorView } from '@tiptap/pm/view';
|
|
13
15
|
|
|
14
|
-
|
|
16
|
+
type Props = {
|
|
17
|
+
colors?: string[];
|
|
18
|
+
editable?: boolean;
|
|
19
|
+
override?: any;
|
|
20
|
+
docked?: boolean;
|
|
21
|
+
children?: any;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
let { colors = [], editable, override, docked = false, children }: Props = $props();
|
|
15
25
|
|
|
16
26
|
const editor = getContext<{ v: any; c: number }>('editor');
|
|
27
|
+
const i18nFromContext = getContext<I18nTranslate | undefined>(I18N_CONTEXT);
|
|
28
|
+
const i18n: I18nTranslate = (...args) =>
|
|
29
|
+
i18nFromContext ? i18nFromContext(...args) : defaultI18n(...args);
|
|
17
30
|
const tiptap = $derived(editor.v);
|
|
31
|
+
const currentTextColor = $derived.by(() => {
|
|
32
|
+
editor.c;
|
|
33
|
+
const color = tiptap?.getAttributes('textStyle')?.color;
|
|
34
|
+
return typeof color === 'string' ? color.trim().toLowerCase() : '';
|
|
35
|
+
});
|
|
36
|
+
const hasTextColor = $derived.by(() => {
|
|
37
|
+
editor.c;
|
|
38
|
+
return !!tiptap?.getAttributes('textStyle')?.color;
|
|
39
|
+
});
|
|
18
40
|
|
|
19
|
-
let selection = $state(null);
|
|
20
|
-
let table = $state(false);
|
|
41
|
+
let selection = $state<Selection | null>(null);
|
|
42
|
+
let table = $state<number[] | false>(false);
|
|
21
43
|
let sel = $state('');
|
|
22
44
|
let _sel = $state('');
|
|
23
45
|
let link = $state(false);
|
|
@@ -25,6 +47,7 @@
|
|
|
25
47
|
|
|
26
48
|
$effect(() => {
|
|
27
49
|
let _ = editor.c;
|
|
50
|
+
flushSync();
|
|
28
51
|
selection = tiptap?.state?.selection;
|
|
29
52
|
});
|
|
30
53
|
|
|
@@ -45,19 +68,46 @@
|
|
|
45
68
|
});
|
|
46
69
|
|
|
47
70
|
$effect(() => {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
71
|
+
const _href = href;
|
|
72
|
+
untrack(() => {
|
|
73
|
+
if (tiptap && link) {
|
|
74
|
+
if (href) {
|
|
75
|
+
tiptap.chain().setLink({ href: _href }).run();
|
|
76
|
+
} else if (tiptap.getAttributes('link').href) {
|
|
77
|
+
tiptap.chain().unsetLink().run();
|
|
78
|
+
}
|
|
53
79
|
}
|
|
54
|
-
}
|
|
80
|
+
});
|
|
55
81
|
});
|
|
56
82
|
|
|
57
|
-
const shouldShow = ({
|
|
83
|
+
const shouldShow = ({
|
|
84
|
+
state,
|
|
85
|
+
view,
|
|
86
|
+
from,
|
|
87
|
+
to
|
|
88
|
+
}: {
|
|
89
|
+
view: EditorView;
|
|
90
|
+
state: EditorState;
|
|
91
|
+
from: number;
|
|
92
|
+
to: number;
|
|
93
|
+
}) => {
|
|
94
|
+
if (!tiptap?.isEditable) return false;
|
|
95
|
+
|
|
58
96
|
const { doc, selection } = state;
|
|
59
97
|
const { empty } = selection;
|
|
60
98
|
|
|
99
|
+
if (selection instanceof NodeSelection && selection.node.isBlock) {
|
|
100
|
+
const nodeDom = view.nodeDOM(from);
|
|
101
|
+
if (
|
|
102
|
+
nodeDom instanceof Element &&
|
|
103
|
+
(nodeDom.hasAttribute('data-hide-bubble-menu') ||
|
|
104
|
+
nodeDom.getAttribute('data-bubble-menu') === 'false' ||
|
|
105
|
+
Boolean(nodeDom.querySelector('[data-hide-bubble-menu], [data-bubble-menu="false"]')))
|
|
106
|
+
) {
|
|
107
|
+
return false;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
61
111
|
const isEmptyTextBlock = !doc.textBetween(from, to).length && isTextSelection(state.selection);
|
|
62
112
|
|
|
63
113
|
return !(empty || isEmptyTextBlock);
|
|
@@ -65,32 +115,23 @@
|
|
|
65
115
|
</script>
|
|
66
116
|
|
|
67
117
|
{#if tiptap}
|
|
68
|
-
|
|
69
|
-
editor={tiptap}
|
|
70
|
-
updateDelay={50}
|
|
71
|
-
{shouldShow}
|
|
72
|
-
tippyOptions={{
|
|
73
|
-
moveTransition: 'transform 0.2s cubic-bezier(1,.5,0,.85)',
|
|
74
|
-
animation: 'shift-away-subtle',
|
|
75
|
-
duration: [200, 50]
|
|
76
|
-
}}
|
|
77
|
-
>
|
|
118
|
+
{#snippet toolbar()}
|
|
78
119
|
{#if override}
|
|
79
|
-
<main>
|
|
120
|
+
<main class:docked>
|
|
80
121
|
<Render it={override} />
|
|
81
122
|
</main>
|
|
82
123
|
{:else}
|
|
83
|
-
<main>
|
|
124
|
+
<main class:docked>
|
|
84
125
|
{#if link}
|
|
85
126
|
<div class="link">
|
|
86
127
|
<p>
|
|
87
128
|
<Icon icon="link" />
|
|
88
129
|
{i18n('link')}
|
|
89
130
|
</p>
|
|
90
|
-
<Input placeholder="url"
|
|
131
|
+
<Input placeholder="url" bind:value={href} autofocus />
|
|
91
132
|
<div>
|
|
92
133
|
<Button
|
|
93
|
-
tabindex=
|
|
134
|
+
tabindex={0}
|
|
94
135
|
transparent
|
|
95
136
|
small
|
|
96
137
|
onclick={() => {
|
|
@@ -100,7 +141,7 @@
|
|
|
100
141
|
}}
|
|
101
142
|
>{i18n('delete')}
|
|
102
143
|
</Button>
|
|
103
|
-
<Button tabindex=
|
|
144
|
+
<Button tabindex={0} transparent small onclick={() => (link = false)}
|
|
104
145
|
>{i18n('close')}</Button
|
|
105
146
|
>
|
|
106
147
|
</div>
|
|
@@ -130,11 +171,11 @@
|
|
|
130
171
|
<ToolbarButton icon="close" handler={() => deleteTable({ editor: tiptap })} />
|
|
131
172
|
{:else}
|
|
132
173
|
{#if editable}
|
|
133
|
-
<Paper hover bl>
|
|
174
|
+
<Paper hover bl remap>
|
|
134
175
|
{#snippet target()}
|
|
135
176
|
<IconButton size="1.2em" icon="format_align_left" />
|
|
136
177
|
{/snippet}
|
|
137
|
-
<div
|
|
178
|
+
<div class="menu-list align-menu">
|
|
138
179
|
<List>
|
|
139
180
|
<OneLine
|
|
140
181
|
icon="format_align_left"
|
|
@@ -172,15 +213,21 @@
|
|
|
172
213
|
<ToolbarButton icon="subscript" prop="subscript" />
|
|
173
214
|
<ToolbarButton icon="border_color" prop="highlight" />
|
|
174
215
|
{#if editable}
|
|
175
|
-
<ToolbarButton icon="functions" handler={() => setMath(tiptap)} />
|
|
216
|
+
<ToolbarButton icon="functions" prop="math_inline" handler={() => setMath(tiptap)} />
|
|
176
217
|
{/if}
|
|
177
|
-
<Paper bl
|
|
218
|
+
<Paper bl remap>
|
|
178
219
|
{#snippet target()}
|
|
179
220
|
<IconButton size="1.2em" icon="palette" />
|
|
180
221
|
{/snippet}
|
|
181
|
-
<div
|
|
222
|
+
<div class="menu-list">
|
|
182
223
|
<div class="colors">
|
|
183
|
-
<Button
|
|
224
|
+
<Button
|
|
225
|
+
small
|
|
226
|
+
outlined
|
|
227
|
+
active={!hasTextColor}
|
|
228
|
+
class={!hasTextColor ? 'color-active' : undefined}
|
|
229
|
+
onclick={() => tiptap.chain().focus().unsetColor().run()}
|
|
230
|
+
>
|
|
184
231
|
{i18n('default')}
|
|
185
232
|
</Button>
|
|
186
233
|
<Paper bl remap block>
|
|
@@ -189,12 +236,14 @@
|
|
|
189
236
|
small
|
|
190
237
|
full
|
|
191
238
|
outlined
|
|
239
|
+
active={hasTextColor}
|
|
240
|
+
class={hasTextColor ? 'color-active' : undefined}
|
|
192
241
|
onclick={() => tiptap.chain().focus().unsetColor().run()}
|
|
193
242
|
>
|
|
194
|
-
<Icon
|
|
243
|
+
<Icon icon="palette" />
|
|
195
244
|
</Button>
|
|
196
245
|
{/snippet}
|
|
197
|
-
<div
|
|
246
|
+
<div role="presentation" onmousedown={(event) => event.stopPropagation()}>
|
|
198
247
|
<ColorPicker
|
|
199
248
|
isDialog={false}
|
|
200
249
|
onInput={(event) => {
|
|
@@ -203,16 +252,15 @@
|
|
|
203
252
|
/>
|
|
204
253
|
</div>
|
|
205
254
|
</Paper>
|
|
206
|
-
{#each colors as color}
|
|
255
|
+
{#each colors as color (color)}
|
|
207
256
|
<Button
|
|
208
257
|
small
|
|
209
258
|
outlined
|
|
259
|
+
active={currentTextColor === color.toLowerCase()}
|
|
260
|
+
class={currentTextColor === color.toLowerCase() ? 'color-active' : undefined}
|
|
210
261
|
onclick={() => tiptap.chain().focus().setColor(color).run()}
|
|
211
262
|
>
|
|
212
|
-
<span
|
|
213
|
-
style:background={color}
|
|
214
|
-
class="pal"
|
|
215
|
-
></span>
|
|
263
|
+
<span style:background={color} class="pal"></span>
|
|
216
264
|
</Button>
|
|
217
265
|
{/each}
|
|
218
266
|
</div>
|
|
@@ -226,57 +274,148 @@
|
|
|
226
274
|
<Render it={children} />
|
|
227
275
|
</main>
|
|
228
276
|
{/if}
|
|
229
|
-
|
|
277
|
+
{/snippet}
|
|
278
|
+
|
|
279
|
+
{#if docked && tiptap.isEditable}
|
|
280
|
+
<div class="docked-menu">
|
|
281
|
+
{@render toolbar()}
|
|
282
|
+
</div>
|
|
283
|
+
{:else}
|
|
284
|
+
<BubbleMenu
|
|
285
|
+
editor={tiptap}
|
|
286
|
+
updateDelay={50}
|
|
287
|
+
{shouldShow}
|
|
288
|
+
tippyOptions={{
|
|
289
|
+
moveTransition: 'transform 0.2s cubic-bezier(1,.5,0,.85)',
|
|
290
|
+
animation: 'shift-away-subtle',
|
|
291
|
+
duration: [200, 50]
|
|
292
|
+
}}
|
|
293
|
+
>
|
|
294
|
+
{@render toolbar()}
|
|
295
|
+
</BubbleMenu>
|
|
296
|
+
{/if}
|
|
230
297
|
{/if}
|
|
231
298
|
|
|
232
|
-
<style>
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
.
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
299
|
+
<style>
|
|
300
|
+
main {
|
|
301
|
+
box-shadow:
|
|
302
|
+
0 10px 24px rgba(22, 37, 63, 0.14),
|
|
303
|
+
0 2px 8px rgba(22, 37, 63, 0.1);
|
|
304
|
+
background: var(--surface, #fff);
|
|
305
|
+
border: 1px solid var(--primary-light2, #d5dff3);
|
|
306
|
+
color: var(--on-surface, #000);
|
|
307
|
+
padding: 8px 10px;
|
|
308
|
+
border-radius: 12px;
|
|
309
|
+
display: flex;
|
|
310
|
+
flex-wrap: nowrap;
|
|
311
|
+
gap: 4px;
|
|
312
|
+
align-items: center;
|
|
313
|
+
justify-content: center;
|
|
314
|
+
font-size: 1.2em;
|
|
315
|
+
& > :global(*) {
|
|
316
|
+
margin: 0;
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
.docked-menu {
|
|
321
|
+
position: sticky;
|
|
322
|
+
top: var(--tiptap-toolbar-sticky-top, 8px);
|
|
323
|
+
z-index: 40;
|
|
324
|
+
display: flex;
|
|
325
|
+
justify-content: center;
|
|
326
|
+
margin-bottom: 10px;
|
|
327
|
+
padding: 4px 0;
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
main.docked {
|
|
331
|
+
width: 100%;
|
|
332
|
+
justify-content: flex-start;
|
|
333
|
+
border-radius: 14px;
|
|
334
|
+
overflow-x: auto;
|
|
335
|
+
overflow-y: hidden;
|
|
336
|
+
backdrop-filter: blur(10px) saturate(1.15);
|
|
337
|
+
-webkit-backdrop-filter: blur(10px) saturate(1.15);
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
main:not(.docked) {
|
|
341
|
+
overflow-x: auto;
|
|
342
|
+
overflow-y: hidden;
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
main.docked > :global(*) {
|
|
346
|
+
flex-shrink: 0;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
main.docked :global(button) {
|
|
350
|
+
font-size: 1.08em;
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
main.docked > :global(main.i) {
|
|
354
|
+
display: flex;
|
|
355
|
+
align-items: center;
|
|
356
|
+
line-height: 1;
|
|
357
|
+
transform: translateY(-1px);
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
.menu-list {
|
|
361
|
+
font-size: 0.6em;
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
.align-menu {
|
|
365
|
+
margin: -6px;
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
main.docked .menu-list {
|
|
369
|
+
font-size: 0.72em;
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
@media (max-width: 768px) {
|
|
373
|
+
main {
|
|
374
|
+
font-size: 1.05em;
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
.link {
|
|
379
|
+
display: flex;
|
|
380
|
+
flex-direction: column;
|
|
381
|
+
font-size: 0.7em;
|
|
382
|
+
|
|
383
|
+
& p {
|
|
384
|
+
margin: 0 0 0.6em 0;
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
& div {
|
|
388
|
+
margin-top: 0.6em;
|
|
389
|
+
display: flex;
|
|
390
|
+
justify-content: flex-end;
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
.colors {
|
|
395
|
+
display: grid;
|
|
396
|
+
grid-template-columns: 1fr 1fr 1fr;
|
|
397
|
+
gap: 4px;
|
|
398
|
+
|
|
399
|
+
& > :global(:first-child) {
|
|
400
|
+
grid-column: 1/3;
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
& :global(button.color-active) {
|
|
404
|
+
box-shadow: inset 0 0 0 1px var(--primary-dark2, #2d4b8f);
|
|
405
|
+
background: color-mix(in srgb, var(--primary-light1, #eef3ff) 65%, var(--surface, #fff));
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
& :global(button.color-active .pal) {
|
|
409
|
+
outline: 1px solid color-mix(in srgb, var(--on-surface, #111) 65%, transparent);
|
|
410
|
+
outline-offset: 1px;
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
.pal {
|
|
415
|
+
width: 20px;
|
|
416
|
+
height: 16px;
|
|
417
|
+
border-radius: 4px;
|
|
418
|
+
display: inline-block;
|
|
419
|
+
margin-bottom: -2px;
|
|
420
|
+
}
|
|
421
|
+
</style>
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import 'tippy.js/animations/shift-away-subtle.css';
|
|
2
|
-
|
|
3
|
-
colors?:
|
|
4
|
-
editable
|
|
5
|
-
override
|
|
6
|
-
|
|
7
|
-
|
|
2
|
+
type Props = {
|
|
3
|
+
colors?: string[];
|
|
4
|
+
editable?: boolean;
|
|
5
|
+
override?: any;
|
|
6
|
+
docked?: boolean;
|
|
7
|
+
children?: any;
|
|
8
|
+
};
|
|
9
|
+
declare const Bubble: import("svelte").Component<Props, {}, "">;
|
|
10
|
+
type Bubble = ReturnType<typeof Bubble>;
|
|
8
11
|
export default Bubble;
|