@seorii/tiptap 0.2.22 → 0.3.0-next.2
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/plugin/table/util.d.ts +2 -2
- package/dist/tiptap/Bubble.svelte +171 -92
- package/dist/tiptap/Bubble.svelte.d.ts +2 -9
- package/dist/tiptap/Command.svelte +125 -59
- package/dist/tiptap/Command.svelte.d.ts +1 -3
- package/dist/tiptap/Floating.svelte +67 -41
- package/dist/tiptap/TipTap.svelte +205 -132
- package/dist/tiptap/TipTap.svelte.d.ts +2 -23
- package/dist/tiptap/ToolbarButton.svelte +22 -18
- package/dist/tiptap/ToolbarButton.svelte.d.ts +2 -13
- package/dist/tiptap/tiptap.d.ts +1 -1
- package/dist/tiptap/tiptap.js +87 -76
- package/package.json +53 -53
- package/dist/plugin/command/stores.d.ts +0 -14
|
@@ -6,9 +6,9 @@ export declare const findTable: (selection: Selection) => {
|
|
|
6
6
|
pos: number;
|
|
7
7
|
start: number;
|
|
8
8
|
depth: number;
|
|
9
|
-
node: Node;
|
|
9
|
+
node: import("prosemirror-model").Node;
|
|
10
10
|
} | undefined;
|
|
11
|
-
export declare const isCellSelection: (selection: any) =>
|
|
11
|
+
export declare const isCellSelection: (selection: any) => selection is CellSelection;
|
|
12
12
|
export declare const isTableAnySelected: (selection: any) => false | number[];
|
|
13
13
|
export declare const isColumnSelected: (columnIndex: number) => (selection: any) => boolean;
|
|
14
14
|
export declare const isRowSelected: (rowIndex: number) => (selection: any) => boolean;
|
|
@@ -1,45 +1,82 @@
|
|
|
1
|
-
<script>
|
|
2
|
-
import {
|
|
3
|
-
import '
|
|
4
|
-
import
|
|
5
|
-
import
|
|
6
|
-
import
|
|
7
|
-
import
|
|
8
|
-
import
|
|
9
|
-
import
|
|
10
|
-
import
|
|
11
|
-
import
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
let
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { BubbleMenu } from 'svelte-tiptap';
|
|
3
|
+
import { getContext, tick } from 'svelte';
|
|
4
|
+
import 'tippy.js/animations/shift-away-subtle.css';
|
|
5
|
+
import ToolbarButton from './ToolbarButton.svelte';
|
|
6
|
+
import { isTableAnySelected } from '../plugin/table/util';
|
|
7
|
+
import deleteTable from '../plugin/table/deleteTable';
|
|
8
|
+
import setMath from './setMath';
|
|
9
|
+
import { Button, Icon, IconButton, Input, List, OneLine, Paper, Render } from 'nunui';
|
|
10
|
+
import i18n from '../i18n';
|
|
11
|
+
import ColorPicker from 'svelte-awesome-color-picker';
|
|
12
|
+
import { isTextSelection } from '@tiptap/core';
|
|
13
|
+
|
|
14
|
+
let { colors = [], editable, override, children } = $props();
|
|
15
|
+
|
|
16
|
+
const editor = getContext<{ v: any }>('editor');
|
|
17
|
+
const tiptap = $derived(editor.v);
|
|
18
|
+
|
|
19
|
+
let selection = $state(null);
|
|
20
|
+
let table = $state(false);
|
|
21
|
+
let sel = $state('');
|
|
22
|
+
let _sel = $state('');
|
|
23
|
+
let link = $state(false);
|
|
24
|
+
let href = $state('');
|
|
25
|
+
|
|
26
|
+
$effect(() => {
|
|
27
|
+
selection = tiptap?.state?.selection;
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
$effect(() => {
|
|
31
|
+
table = isTableAnySelected(selection);
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
$effect(() => {
|
|
35
|
+
sel = selection?.from + '-' + selection?.to;
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
$effect(() => {
|
|
39
|
+
if (tiptap && sel !== _sel) {
|
|
40
|
+
_sel = sel;
|
|
41
|
+
link = false;
|
|
42
|
+
href = tiptap.getAttributes('link').href || '';
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
$effect(() => {
|
|
47
|
+
if (tiptap && link) {
|
|
48
|
+
if (href) {
|
|
49
|
+
tiptap.chain().setLink({ href }).run();
|
|
50
|
+
} else if (tiptap.getAttributes('link').href) {
|
|
51
|
+
tiptap.chain().unsetLink().run();
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
const shouldShow = ({ view, state, from, to }) => {
|
|
57
|
+
const { doc, selection } = state;
|
|
58
|
+
const { empty } = selection;
|
|
59
|
+
|
|
60
|
+
const isEmptyTextBlock = !doc.textBetween(from, to).length && isTextSelection(state.selection);
|
|
61
|
+
|
|
62
|
+
return !(empty || isEmptyTextBlock);
|
|
63
|
+
};
|
|
35
64
|
</script>
|
|
36
65
|
|
|
37
|
-
{#if
|
|
38
|
-
<BubbleMenu
|
|
39
|
-
|
|
66
|
+
{#if tiptap}
|
|
67
|
+
<BubbleMenu
|
|
68
|
+
editor={tiptap}
|
|
69
|
+
updateDelay={50}
|
|
70
|
+
{shouldShow}
|
|
71
|
+
tippyOptions={{
|
|
72
|
+
moveTransition: 'transform 0.2s cubic-bezier(1,.5,0,.85)',
|
|
73
|
+
animation: 'shift-away-subtle',
|
|
74
|
+
duration: [200, 50]
|
|
75
|
+
}}
|
|
76
|
+
>
|
|
40
77
|
{#if override}
|
|
41
78
|
<main>
|
|
42
|
-
<
|
|
79
|
+
<Render it={override} />
|
|
43
80
|
</main>
|
|
44
81
|
{:else}
|
|
45
82
|
<main>
|
|
@@ -51,52 +88,80 @@ const shouldShow = ({ view, state, from, to }) => {
|
|
|
51
88
|
</p>
|
|
52
89
|
<Input placeholder="url" fullWidth bind:value={href} autofocus />
|
|
53
90
|
<div>
|
|
54
|
-
<Button
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
91
|
+
<Button
|
|
92
|
+
tabindex="0"
|
|
93
|
+
transparent
|
|
94
|
+
small
|
|
95
|
+
onclick={() => {
|
|
96
|
+
href = '';
|
|
97
|
+
tiptap.chain().focus().unsetLink().run();
|
|
98
|
+
tick().then(() => (link = false));
|
|
99
|
+
}}
|
|
100
|
+
>{i18n('delete')}
|
|
59
101
|
</Button>
|
|
60
|
-
<Button tabindex="0" transparent small
|
|
61
|
-
|
|
102
|
+
<Button tabindex="0" transparent small onclick={() => (link = false)}
|
|
103
|
+
>{i18n('close')}</Button
|
|
104
|
+
>
|
|
62
105
|
</div>
|
|
63
106
|
</div>
|
|
64
107
|
{:else if table}
|
|
65
108
|
{#if table.length > 1}
|
|
66
|
-
<ToolbarButton icon="cell_merge" handler={() =>
|
|
109
|
+
<ToolbarButton icon="cell_merge" handler={() => tiptap.commands.mergeCells()} />
|
|
67
110
|
{:else}
|
|
68
|
-
<ToolbarButton icon="splitscreen_left" handler={() =>
|
|
111
|
+
<ToolbarButton icon="splitscreen_left" handler={() => tiptap.commands.splitCell()} />
|
|
69
112
|
{/if}
|
|
70
|
-
<ToolbarButton
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
<ToolbarButton
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
<ToolbarButton
|
|
113
|
+
<ToolbarButton
|
|
114
|
+
icon="keyboard_double_arrow_left"
|
|
115
|
+
handler={() => tiptap.chain().focus().addColumnBefore().run()}
|
|
116
|
+
/>
|
|
117
|
+
<ToolbarButton
|
|
118
|
+
icon="keyboard_double_arrow_right"
|
|
119
|
+
handler={() => tiptap.chain().focus().addColumnAfter().run()}
|
|
120
|
+
/>
|
|
121
|
+
<ToolbarButton
|
|
122
|
+
icon="keyboard_double_arrow_up"
|
|
123
|
+
handler={() => tiptap.chain().focus().addRowBefore().run()}
|
|
124
|
+
/>
|
|
125
|
+
<ToolbarButton
|
|
126
|
+
icon="keyboard_double_arrow_down"
|
|
127
|
+
handler={() => tiptap.chain().focus().addRowAfter().run()}
|
|
128
|
+
/>
|
|
129
|
+
<ToolbarButton icon="close" handler={() => deleteTable({ editor: tiptap })} />
|
|
79
130
|
{:else}
|
|
80
131
|
{#if editable}
|
|
81
|
-
<
|
|
82
|
-
|
|
132
|
+
<Paper hover bl>
|
|
133
|
+
{#snippet target()}
|
|
134
|
+
<IconButton size="1.2em" icon="format_align_left" />
|
|
135
|
+
{/snippet}
|
|
83
136
|
<div style="margin: -6px;font-size: 0.6em">
|
|
84
137
|
<List>
|
|
85
|
-
<OneLine
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
<OneLine
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
138
|
+
<OneLine
|
|
139
|
+
icon="format_align_left"
|
|
140
|
+
title={i18n('alignLeft')}
|
|
141
|
+
onclick={() => tiptap.chain().focus().setTextAlign('left').run()}
|
|
142
|
+
active={tiptap.isActive({ textAlign: 'left' })}
|
|
143
|
+
/>
|
|
144
|
+
<OneLine
|
|
145
|
+
icon="format_align_center"
|
|
146
|
+
title={i18n('alignCenter')}
|
|
147
|
+
onclick={() => tiptap.chain().focus().setTextAlign('center').run()}
|
|
148
|
+
active={tiptap.isActive({ textAlign: 'center' })}
|
|
149
|
+
/>
|
|
150
|
+
<OneLine
|
|
151
|
+
icon="format_align_right"
|
|
152
|
+
title={i18n('alignRight')}
|
|
153
|
+
onclick={() => tiptap.chain().focus().setTextAlign('right').run()}
|
|
154
|
+
active={tiptap.isActive({ textAlign: 'right' })}
|
|
155
|
+
/>
|
|
156
|
+
<OneLine
|
|
157
|
+
icon="format_align_justify"
|
|
158
|
+
title={i18n('alignJustify')}
|
|
159
|
+
onclick={() => tiptap.chain().focus().setTextAlign('justify').run()}
|
|
160
|
+
active={tiptap.isActive({ textAlign: 'justify' })}
|
|
161
|
+
/>
|
|
97
162
|
</List>
|
|
98
163
|
</div>
|
|
99
|
-
</
|
|
164
|
+
</Paper>
|
|
100
165
|
{/if}
|
|
101
166
|
<ToolbarButton icon="format_bold" prop="bold" />
|
|
102
167
|
<ToolbarButton icon="format_italic" prop="italic" />
|
|
@@ -106,41 +171,55 @@ const shouldShow = ({ view, state, from, to }) => {
|
|
|
106
171
|
<ToolbarButton icon="subscript" prop="subscript" />
|
|
107
172
|
<ToolbarButton icon="border_color" prop="highlight" />
|
|
108
173
|
{#if editable}
|
|
109
|
-
<ToolbarButton icon="functions" handler={() => setMath(
|
|
174
|
+
<ToolbarButton icon="functions" handler={() => setMath(tiptap)} />
|
|
110
175
|
{/if}
|
|
111
|
-
<
|
|
112
|
-
|
|
176
|
+
<Paper bl hover>
|
|
177
|
+
{#snippet target()}
|
|
178
|
+
<IconButton size="1.2em" icon="palette" />
|
|
179
|
+
{/snippet}
|
|
113
180
|
<div style="font-size: 0.6em">
|
|
114
181
|
<List>
|
|
115
|
-
<Button small outlined
|
|
182
|
+
<Button small outlined onclick={() => tiptap.chain().focus().unsetColor().run()}>
|
|
116
183
|
{i18n('default')}
|
|
117
184
|
</Button>
|
|
118
|
-
<
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
185
|
+
<Paper bl hover>
|
|
186
|
+
{#snippet target()}
|
|
187
|
+
<Button
|
|
188
|
+
small
|
|
189
|
+
outlined
|
|
190
|
+
onclick={() => tiptap.chain().focus().unsetColor().run()}
|
|
191
|
+
>
|
|
192
|
+
<Icon colorize />
|
|
193
|
+
</Button>
|
|
194
|
+
{/snippet}
|
|
195
|
+
<ColorPicker
|
|
196
|
+
isDialog={false}
|
|
197
|
+
oninput={(event) => {
|
|
198
|
+
tiptap.chain().focus().setColor(event.detail.hex).run();
|
|
199
|
+
}}
|
|
200
|
+
/>
|
|
201
|
+
</Paper>
|
|
127
202
|
{#each colors as color}
|
|
128
|
-
<Button
|
|
129
|
-
|
|
130
|
-
|
|
203
|
+
<Button
|
|
204
|
+
small
|
|
205
|
+
outlined
|
|
206
|
+
onclick={() => tiptap.chain().focus().setColor(color).run()}
|
|
207
|
+
style="margin-right:4px"
|
|
208
|
+
>
|
|
131
209
|
<span
|
|
132
|
-
style="width: 20px; height: 16px; background: {color}; border-radius: 4px;display: inline-block;margin-bottom: -2px"
|
|
210
|
+
style="width: 20px; height: 16px; background: {color}; border-radius: 4px;display: inline-block;margin-bottom: -2px"
|
|
211
|
+
></span>
|
|
133
212
|
</Button>
|
|
134
213
|
{/each}
|
|
135
214
|
</List>
|
|
136
215
|
</div>
|
|
137
|
-
</
|
|
216
|
+
</Paper>
|
|
138
217
|
{#if editable}
|
|
139
218
|
<ToolbarButton icon="code" prop="code" />
|
|
140
|
-
<ToolbarButton icon="link" prop="link" handler={() => link = true} />
|
|
219
|
+
<ToolbarButton icon="link" prop="link" handler={() => (link = true)} />
|
|
141
220
|
{/if}
|
|
142
221
|
{/if}
|
|
143
|
-
<
|
|
222
|
+
<Render it={children} />
|
|
144
223
|
</main>
|
|
145
224
|
{/if}
|
|
146
225
|
</BubbleMenu>
|
|
@@ -179,4 +258,4 @@ main > :global(*):last-child {
|
|
|
179
258
|
margin-top: 0.6em;
|
|
180
259
|
display: flex;
|
|
181
260
|
justify-content: flex-end;
|
|
182
|
-
}</style>
|
|
261
|
+
}</style>
|
|
@@ -1,18 +1,11 @@
|
|
|
1
1
|
import { SvelteComponentTyped } from "svelte";
|
|
2
2
|
import 'tippy.js/animations/shift-away-subtle.css';
|
|
3
3
|
declare const __propDef: {
|
|
4
|
-
props:
|
|
5
|
-
colors?: any[] | undefined;
|
|
6
|
-
editable: any;
|
|
7
|
-
override: any;
|
|
8
|
-
};
|
|
4
|
+
props: Record<string, never>;
|
|
9
5
|
events: {
|
|
10
6
|
[evt: string]: CustomEvent<any>;
|
|
11
7
|
};
|
|
12
|
-
slots: {
|
|
13
|
-
override: {};
|
|
14
|
-
default: {};
|
|
15
|
-
};
|
|
8
|
+
slots: {};
|
|
16
9
|
};
|
|
17
10
|
export type BubbleProps = typeof __propDef.props;
|
|
18
11
|
export type BubbleEvents = typeof __propDef.events;
|
|
@@ -1,102 +1,168 @@
|
|
|
1
|
-
<script>
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
}
|
|
14
|
-
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { Button, IconButton, Input, List, OneLine, TwoLine } from 'nunui';
|
|
3
|
+
import { getContext } from 'svelte';
|
|
4
|
+
import {
|
|
5
|
+
slashVisible,
|
|
6
|
+
slashItems,
|
|
7
|
+
slashLocaltion,
|
|
8
|
+
slashProps,
|
|
9
|
+
slashDetail,
|
|
10
|
+
slashSelection
|
|
11
|
+
} from '../plugin/command/stores';
|
|
12
|
+
import { fly, slide } from 'svelte/transition';
|
|
13
|
+
import { quartOut } from 'svelte/easing';
|
|
14
|
+
import i18n from '../i18n';
|
|
15
|
+
|
|
16
|
+
const editor = getContext<{ v: any }>('editor');
|
|
17
|
+
const tiptap = $derived(editor.v);
|
|
18
|
+
let { selectedIndex = 0 } = $props();
|
|
19
|
+
|
|
20
|
+
let height = $state(0),
|
|
21
|
+
elements = $state([]);
|
|
22
|
+
let input = $state(''),
|
|
23
|
+
focus: any = $state(null);
|
|
24
|
+
|
|
25
|
+
$effect(() => {
|
|
26
|
+
if ($slashVisible) input = '';
|
|
27
|
+
});
|
|
28
|
+
$effect(() => {
|
|
29
|
+
focus;
|
|
30
|
+
setTimeout(() => focus?.focus?.(), 100);
|
|
31
|
+
});
|
|
15
32
|
</script>
|
|
16
33
|
|
|
17
34
|
<svelte:window bind:innerHeight={height} />
|
|
18
35
|
|
|
19
36
|
{#if $slashVisible}
|
|
20
|
-
<div class="scrim"
|
|
21
|
-
<main
|
|
37
|
+
<div class="scrim" onclick={() => ($slashVisible = false)} />
|
|
38
|
+
<main
|
|
39
|
+
style="left: {$slashLocaltion.x}px; top: {$slashLocaltion.y + $slashLocaltion.height + 384 >
|
|
40
|
+
height
|
|
22
41
|
? $slashLocaltion.y - $slashLocaltion.height - 384
|
|
23
|
-
: $slashLocaltion.y + $slashLocaltion.height}px;"
|
|
42
|
+
: $slashLocaltion.y + $slashLocaltion.height}px;"
|
|
43
|
+
transition:fly={{ y: 10, duration: 200, easing: quartOut }}
|
|
44
|
+
>
|
|
24
45
|
{#if $slashDetail === 'emoji'}
|
|
25
46
|
<div class="list">
|
|
26
47
|
<List>
|
|
27
|
-
{#each $slashItems as { title, command }, i(title)}
|
|
28
|
-
<div transition:slide={{duration: 400, easing: quartOut}}>
|
|
29
|
-
<OneLine
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
48
|
+
{#each $slashItems as { title, command }, i (title)}
|
|
49
|
+
<div transition:slide={{ duration: 400, easing: quartOut }}>
|
|
50
|
+
<OneLine
|
|
51
|
+
onclick={() => {
|
|
52
|
+
command?.($slashProps);
|
|
53
|
+
setTimeout(() => tiptap.commands.focus());
|
|
54
|
+
}}
|
|
55
|
+
bind:this={elements[i]}
|
|
56
|
+
{title}
|
|
57
|
+
active={selectedIndex === i}
|
|
58
|
+
/>
|
|
33
59
|
</div>
|
|
34
60
|
{/each}
|
|
35
61
|
{#if !$slashItems.length}
|
|
36
|
-
<div class="section"
|
|
37
|
-
|
|
62
|
+
<div class="section" transition:slide={{ duration: 400, easing: quartOut }}>
|
|
63
|
+
{i18n('noResult')}
|
|
64
|
+
</div>
|
|
38
65
|
{/if}
|
|
39
66
|
</List>
|
|
40
67
|
</div>
|
|
41
68
|
{:else if $slashDetail?.type === 'code'}
|
|
42
69
|
<div class="detail">
|
|
43
70
|
<header>
|
|
44
|
-
<IconButton icon="arrow_back"
|
|
71
|
+
<IconButton icon="arrow_back" onclick={() => ($slashDetail = null)} />
|
|
45
72
|
<div class="title">{i18n('insertCode')}</div>
|
|
46
73
|
</header>
|
|
47
74
|
<div>
|
|
48
|
-
<Button
|
|
75
|
+
<Button
|
|
76
|
+
small
|
|
77
|
+
onclick={() => {
|
|
78
|
+
$slashSelection?.();
|
|
79
|
+
$slashDetail.handler(undefined);
|
|
80
|
+
}}>{i18n('auto')}</Button
|
|
81
|
+
>
|
|
49
82
|
{#each ['cpp', 'python', 'java'] as lang}
|
|
50
|
-
<Button
|
|
83
|
+
<Button
|
|
84
|
+
small
|
|
85
|
+
outlined
|
|
86
|
+
onclick={() => {
|
|
87
|
+
$slashSelection?.();
|
|
88
|
+
$slashDetail.handler(lang);
|
|
89
|
+
}}>{lang}</Button
|
|
90
|
+
>
|
|
51
91
|
{/each}
|
|
52
92
|
</div>
|
|
53
93
|
</div>
|
|
54
94
|
{:else if $slashDetail}
|
|
55
95
|
<div class="detail">
|
|
56
96
|
<header>
|
|
57
|
-
<IconButton icon="arrow_back"
|
|
97
|
+
<IconButton icon="arrow_back" onclick={() => ($slashDetail = null)} />
|
|
58
98
|
<div class="title">{$slashDetail.title}</div>
|
|
59
99
|
</header>
|
|
60
|
-
<Input
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
100
|
+
<Input
|
|
101
|
+
placeholder={$slashDetail.placeholder}
|
|
102
|
+
fullWidth
|
|
103
|
+
bind:value={input}
|
|
104
|
+
bind:input={focus}
|
|
105
|
+
onsubmit={() => {
|
|
106
|
+
$slashSelection?.();
|
|
107
|
+
$slashDetail.handler(input);
|
|
108
|
+
}}
|
|
109
|
+
/>
|
|
65
110
|
<footer>
|
|
66
|
-
<Button
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
111
|
+
<Button
|
|
112
|
+
tabindex="0"
|
|
113
|
+
transparent
|
|
114
|
+
small
|
|
115
|
+
onclick={() => {
|
|
116
|
+
input = '';
|
|
117
|
+
$slashDetail = null;
|
|
118
|
+
}}
|
|
119
|
+
>{i18n('cancel')}
|
|
70
120
|
</Button>
|
|
71
|
-
<Button
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
121
|
+
<Button
|
|
122
|
+
tabindex="0"
|
|
123
|
+
transparent
|
|
124
|
+
small
|
|
125
|
+
onclick={() => {
|
|
126
|
+
$slashSelection?.();
|
|
127
|
+
$slashDetail.handler(input);
|
|
128
|
+
}}
|
|
129
|
+
>{i18n('insert')}
|
|
76
130
|
</Button>
|
|
77
131
|
</footer>
|
|
78
132
|
</div>
|
|
79
133
|
{:else}
|
|
80
134
|
<div class="list">
|
|
81
135
|
<List>
|
|
82
|
-
{#each $slashItems as { section, list }, j(section)}
|
|
83
|
-
{@const lastCount = $slashItems
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
136
|
+
{#each $slashItems as { section, list }, j (section)}
|
|
137
|
+
{@const lastCount = $slashItems
|
|
138
|
+
.slice(0, j)
|
|
139
|
+
.reduce((acc, cur) => acc + cur.list.length, 0)}
|
|
140
|
+
<div class="section" transition:slide={{ duration: 400, easing: quartOut }}>
|
|
141
|
+
{section}
|
|
142
|
+
</div>
|
|
143
|
+
<div transition:slide={{ duration: 400, easing: quartOut }}>
|
|
144
|
+
{#each list || [] as { title, subtitle, icon, command, section }, i (title)}
|
|
145
|
+
<div transition:slide={{ duration: 400, easing: quartOut }}>
|
|
146
|
+
<TwoLine
|
|
147
|
+
onmouseenter={() => (selectedIndex = i + lastCount)}
|
|
148
|
+
onclick={() => {
|
|
149
|
+
command?.($slashProps);
|
|
150
|
+
setTimeout(() => tiptap.commands.focus());
|
|
151
|
+
}}
|
|
152
|
+
bind:this={elements[i + lastCount]}
|
|
153
|
+
{icon}
|
|
154
|
+
{title}
|
|
155
|
+
subtitle={subtitle || ''}
|
|
156
|
+
active={selectedIndex === i + lastCount}
|
|
157
|
+
/>
|
|
93
158
|
</div>
|
|
94
159
|
{/each}
|
|
95
160
|
</div>
|
|
96
161
|
{/each}
|
|
97
162
|
{#if !$slashItems.length}
|
|
98
|
-
<div class="section"
|
|
99
|
-
|
|
163
|
+
<div class="section" transition:slide={{ duration: 400, easing: quartOut }}>
|
|
164
|
+
{i18n('noResult')}
|
|
165
|
+
</div>
|
|
100
166
|
{/if}
|
|
101
167
|
</List>
|
|
102
168
|
</div>
|
|
@@ -136,12 +202,12 @@ main {
|
|
|
136
202
|
.list {
|
|
137
203
|
color: var(--primary-dark7);
|
|
138
204
|
}
|
|
139
|
-
.list :global
|
|
205
|
+
.list :global .title {
|
|
140
206
|
font-size: 0.7em !important;
|
|
141
207
|
font-weight: 300 !important;
|
|
142
208
|
margin-bottom: 4px;
|
|
143
209
|
}
|
|
144
|
-
.list :global
|
|
210
|
+
.list :global .subtitle {
|
|
145
211
|
font-size: 0.8em !important;
|
|
146
212
|
font-weight: 300 !important;
|
|
147
213
|
color: var(--primary-dark1);
|
|
@@ -170,4 +236,4 @@ footer {
|
|
|
170
236
|
margin-top: 0.6em;
|
|
171
237
|
display: flex;
|
|
172
238
|
justify-content: flex-end;
|
|
173
|
-
}</style>
|
|
239
|
+
}</style>
|