@sierra-95/svelte-scaffold 1.0.9 → 1.0.10
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 +8 -8
- package/dist/Hooks/preview.d.ts +2 -1
- package/dist/Hooks/preview.js +4 -4
- package/dist/components/Core/Alerts/Backdrop/backdrop.svelte +26 -26
- package/dist/components/Core/Alerts/Modal/modal.svelte +40 -40
- package/dist/components/Core/Alerts/Toast/toast.css +38 -38
- package/dist/components/Core/Alerts/Toast/toast.svelte +32 -32
- package/dist/components/Core/Alerts/Wrapper/wrapper.svelte +18 -18
- package/dist/components/Core/Alerts/site-under-maintenance/site-under-maintenance.svelte +33 -33
- package/dist/components/Core/Form/Hr/hr.svelte +10 -10
- package/dist/components/Core/Form/Input/FileInput/fileInput.svelte +158 -158
- package/dist/components/Core/Form/Input/FileInput/preview.svelte +50 -50
- package/dist/components/Core/Form/Input/SearchBar/search.svelte +68 -68
- package/dist/components/Core/Form/Input/input/input.svelte +16 -16
- package/dist/components/Core/Form/Input/password/password.svelte +26 -26
- package/dist/components/Core/Menus/DropdownContainer/dropdown.svelte +94 -94
- package/dist/components/Core/Menus/MenuItem/menuItem.svelte +43 -43
- package/dist/components/Core/Menus/UserMenu/profile.svelte +34 -34
- package/dist/components/Core/others/Button/Flip/button.css +50 -50
- package/dist/components/Core/others/Button/Flip/button.svelte +79 -79
- package/dist/components/Core/others/Button/Marquee/button.css +36 -36
- package/dist/components/Core/others/Button/Marquee/button.svelte +58 -58
- package/dist/components/Core/others/Button/Swipe/button.css +32 -32
- package/dist/components/Core/others/Button/Swipe/button.svelte +57 -57
- package/dist/components/Core/others/Button/default/button.css +60 -60
- package/dist/components/Core/others/Button/default/button.svelte +124 -124
- package/dist/components/Core/others/Button/select/select.svelte +28 -28
- package/dist/components/Core/others/Button/theme/theme.css +121 -121
- package/dist/components/Core/others/Button/theme/theme.svelte +67 -67
- package/dist/components/Core/others/Button/times/times.svelte +24 -24
- package/dist/components/Core/others/Clock/Date/date.svelte +25 -25
- package/dist/components/Core/others/Clock/Time/time.svelte +35 -35
- package/dist/components/Core/others/Previews/Audio/audio.svelte +61 -61
- package/dist/components/Core/others/Previews/Document/documents.svelte +36 -36
- package/dist/components/Core/others/Previews/GenericFile/genericFile.svelte +25 -25
- package/dist/components/Core/others/Previews/Image/image.svelte +26 -26
- package/dist/components/Core/others/Previews/Video/video.svelte +28 -28
- package/dist/components/Core/others/Progress/CircularProgress/CircularProgress.svelte +55 -55
- package/dist/components/Core/others/Progress/CustomProgress/customProgress.svelte +64 -64
- package/dist/components/Core/others/Progress/LinearProgress/LinearProgress.css +60 -60
- package/dist/components/Core/others/Progress/LinearProgress/LinearProgress.svelte +86 -86
- package/dist/components/Modules/Editor/Hooks/extractContent.js +14 -14
- package/dist/components/Modules/Editor/Hooks/extractImage.js +30 -30
- package/dist/components/Modules/Editor/Hooks/insertImage.js +26 -26
- package/dist/components/Modules/Editor/Hooks/insertYoutube.js +34 -34
- package/dist/components/Modules/Editor/Marks/Links/links.svelte +78 -78
- package/dist/components/Modules/Editor/Marks/TextFormatting/textFormatting.svelte +32 -32
- package/dist/components/Modules/Editor/Nodes/Headings/heading.svelte +58 -58
- package/dist/components/Modules/Editor/Nodes/History/history.svelte +21 -21
- package/dist/components/Modules/Editor/Nodes/Images/images.svelte +85 -85
- package/dist/components/Modules/Editor/Nodes/Lists/lists.svelte +30 -30
- package/dist/components/Modules/Editor/Nodes/TextAlign/textAlign.svelte +55 -55
- package/dist/components/Modules/Editor/Nodes/TextColor/styles.css +18 -18
- package/dist/components/Modules/Editor/Nodes/TextColor/textColor.svelte +88 -88
- package/dist/components/Modules/Editor/Nodes/Youtube/youtube.svelte +32 -32
- package/dist/components/Modules/Editor/colors.js +21 -21
- package/dist/components/Modules/Editor/controls.svelte +71 -71
- package/dist/components/Modules/Editor/extensions.js +59 -59
- package/dist/components/Modules/Editor/main.svelte +41 -41
- package/dist/components/Modules/Editor/save.svelte +28 -28
- package/dist/components/Modules/Editor/styles/controls.css +68 -68
- package/dist/components/Modules/Editor/styles/main.css +42 -42
- package/dist/components/Modules/Editor/tools.js +22 -22
- package/dist/components/Modules/FilePicker/cloudStore.svelte +101 -98
- package/dist/components/Modules/FilePicker/controls.svelte +167 -141
- package/dist/components/Modules/FilePicker/controls.svelte.d.ts +4 -19
- package/dist/components/Modules/FilePicker/filePicker.svelte +59 -59
- package/dist/components/Modules/FilePicker/file_properties.svelte +33 -0
- package/dist/components/Modules/FilePicker/file_properties.svelte.d.ts +11 -0
- package/dist/components/Modules/FilePicker/previews.svelte +22 -22
- package/dist/components/Modules/Layout/Header/header.css +37 -37
- package/dist/components/Modules/Layout/Header/header.svelte +31 -31
- package/dist/components/Modules/Layout/Menu/menu.css +53 -53
- package/dist/components/Modules/Layout/Menu/menu.svelte +129 -129
- package/dist/components/Modules/Layout/background.svelte +28 -28
- package/dist/components/Modules/Layout/collapse.svelte +24 -24
- package/dist/components/Modules/Layout/main.css +31 -31
- package/dist/components/Modules/Layout/main.svelte +110 -110
- package/dist/global.css +246 -246
- package/dist/index.d.ts +1 -0
- package/dist/stores/core/general.js +4 -4
- package/dist/stores/core/ismobile.js +14 -14
- package/dist/stores/core/modal.js +35 -35
- package/dist/stores/modules/fileInput.d.ts +11 -4
- package/dist/stores/modules/fileInput.js +1 -1
- package/package.json +75 -75
|
@@ -1,32 +1,32 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import type { Editor } from "@tiptap/core";
|
|
3
|
-
|
|
4
|
-
export let editor: Editor;
|
|
5
|
-
|
|
6
|
-
const actions = [
|
|
7
|
-
{ name: 'bold', icon: 'bold' },
|
|
8
|
-
{ name: 'italic', icon: 'italic' },
|
|
9
|
-
{ name: 'underline', icon: 'underline' },
|
|
10
|
-
];
|
|
11
|
-
|
|
12
|
-
function runToggle(name: string) {
|
|
13
|
-
if (!editor) return;
|
|
14
|
-
const cmd = `toggle${name.charAt(0).toUpperCase() + name.slice(1)}`;
|
|
15
|
-
(editor.chain().focus() as any)[cmd]().run();
|
|
16
|
-
}
|
|
17
|
-
</script>
|
|
18
|
-
|
|
19
|
-
{#if editor}
|
|
20
|
-
<div style="display: flex; gap: 0.5rem">
|
|
21
|
-
{#each actions as { name, icon }}
|
|
22
|
-
<button
|
|
23
|
-
aria-label="Text Formatting: {name}"
|
|
24
|
-
title={name.charAt(0).toUpperCase() + name.slice(1)}
|
|
25
|
-
on:click={() => runToggle(name)}
|
|
26
|
-
class="{editor.isActive(name) ? 'active' : ''}"
|
|
27
|
-
>
|
|
28
|
-
<i class="fa fa-{icon}"></i>
|
|
29
|
-
</button>
|
|
30
|
-
{/each}
|
|
31
|
-
</div>
|
|
32
|
-
{/if}
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { Editor } from "@tiptap/core";
|
|
3
|
+
|
|
4
|
+
export let editor: Editor;
|
|
5
|
+
|
|
6
|
+
const actions = [
|
|
7
|
+
{ name: 'bold', icon: 'bold' },
|
|
8
|
+
{ name: 'italic', icon: 'italic' },
|
|
9
|
+
{ name: 'underline', icon: 'underline' },
|
|
10
|
+
];
|
|
11
|
+
|
|
12
|
+
function runToggle(name: string) {
|
|
13
|
+
if (!editor) return;
|
|
14
|
+
const cmd = `toggle${name.charAt(0).toUpperCase() + name.slice(1)}`;
|
|
15
|
+
(editor.chain().focus() as any)[cmd]().run();
|
|
16
|
+
}
|
|
17
|
+
</script>
|
|
18
|
+
|
|
19
|
+
{#if editor}
|
|
20
|
+
<div style="display: flex; gap: 0.5rem">
|
|
21
|
+
{#each actions as { name, icon }}
|
|
22
|
+
<button
|
|
23
|
+
aria-label="Text Formatting: {name}"
|
|
24
|
+
title={name.charAt(0).toUpperCase() + name.slice(1)}
|
|
25
|
+
on:click={() => runToggle(name)}
|
|
26
|
+
class="{editor.isActive(name) ? 'active' : ''}"
|
|
27
|
+
>
|
|
28
|
+
<i class="fa fa-{icon}"></i>
|
|
29
|
+
</button>
|
|
30
|
+
{/each}
|
|
31
|
+
</div>
|
|
32
|
+
{/if}
|
|
@@ -1,58 +1,58 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import { onMount } from "svelte";
|
|
3
|
-
import type { Editor } from "@tiptap/core";
|
|
4
|
-
import {DropdownContainer, MenuItem} from '../../../../../index.js';
|
|
5
|
-
|
|
6
|
-
export let editor: Editor;
|
|
7
|
-
|
|
8
|
-
let open = false;
|
|
9
|
-
|
|
10
|
-
const headingOptions = [
|
|
11
|
-
{ label: 'H1', value: 'heading', level: 1 as const },
|
|
12
|
-
{ label: 'H2', value: 'heading', level: 2 as const },
|
|
13
|
-
{ label: 'H3', value: 'heading', level: 3 as const },
|
|
14
|
-
{ label: 'H4', value: 'heading', level: 4 as const },
|
|
15
|
-
{ label: 'H5', value: 'heading', level: 5 as const },
|
|
16
|
-
{ label: 'H6', value: 'heading', level: 6 as const }
|
|
17
|
-
];
|
|
18
|
-
|
|
19
|
-
type HeadingOption = {
|
|
20
|
-
label: string;
|
|
21
|
-
value: string;
|
|
22
|
-
level: 1 | 2 | 3 | 4 | 5 | 6;
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
function applyHeading(option: HeadingOption) {
|
|
26
|
-
if (option.value === 'paragraph') {
|
|
27
|
-
editor.chain().focus().setParagraph().run();
|
|
28
|
-
} else {
|
|
29
|
-
editor.chain().focus().toggleHeading({ level: option.level }).run();
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
onMount(() => {
|
|
34
|
-
editor.chain().focus().toggleHeading({ level: 5 }).run();
|
|
35
|
-
});
|
|
36
|
-
</script>
|
|
37
|
-
|
|
38
|
-
{#if editor}
|
|
39
|
-
<DropdownContainer bind:open>
|
|
40
|
-
{#snippet dropdownTrigger()}
|
|
41
|
-
<button aria-label="Heading Options" on:click={() => (open = !open)} style="display: flex; align-items: center; gap: 4px;">
|
|
42
|
-
<h5 style="font-weight: bold;">H{editor.getAttributes('heading').level}</h5>
|
|
43
|
-
<i class="fa fa-chevron-down {open ? 'active' : ''}"></i>
|
|
44
|
-
</button>
|
|
45
|
-
{/snippet}
|
|
46
|
-
{#each headingOptions as option}
|
|
47
|
-
<MenuItem
|
|
48
|
-
active={option.level === editor.getAttributes('heading').level}
|
|
49
|
-
onclick={() => {
|
|
50
|
-
applyHeading(option);
|
|
51
|
-
open = false;
|
|
52
|
-
}}
|
|
53
|
-
>
|
|
54
|
-
{option.label}
|
|
55
|
-
</MenuItem>
|
|
56
|
-
{/each}
|
|
57
|
-
</DropdownContainer>
|
|
58
|
-
{/if}
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { onMount } from "svelte";
|
|
3
|
+
import type { Editor } from "@tiptap/core";
|
|
4
|
+
import {DropdownContainer, MenuItem} from '../../../../../index.js';
|
|
5
|
+
|
|
6
|
+
export let editor: Editor;
|
|
7
|
+
|
|
8
|
+
let open = false;
|
|
9
|
+
|
|
10
|
+
const headingOptions = [
|
|
11
|
+
{ label: 'H1', value: 'heading', level: 1 as const },
|
|
12
|
+
{ label: 'H2', value: 'heading', level: 2 as const },
|
|
13
|
+
{ label: 'H3', value: 'heading', level: 3 as const },
|
|
14
|
+
{ label: 'H4', value: 'heading', level: 4 as const },
|
|
15
|
+
{ label: 'H5', value: 'heading', level: 5 as const },
|
|
16
|
+
{ label: 'H6', value: 'heading', level: 6 as const }
|
|
17
|
+
];
|
|
18
|
+
|
|
19
|
+
type HeadingOption = {
|
|
20
|
+
label: string;
|
|
21
|
+
value: string;
|
|
22
|
+
level: 1 | 2 | 3 | 4 | 5 | 6;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
function applyHeading(option: HeadingOption) {
|
|
26
|
+
if (option.value === 'paragraph') {
|
|
27
|
+
editor.chain().focus().setParagraph().run();
|
|
28
|
+
} else {
|
|
29
|
+
editor.chain().focus().toggleHeading({ level: option.level }).run();
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
onMount(() => {
|
|
34
|
+
editor.chain().focus().toggleHeading({ level: 5 }).run();
|
|
35
|
+
});
|
|
36
|
+
</script>
|
|
37
|
+
|
|
38
|
+
{#if editor}
|
|
39
|
+
<DropdownContainer bind:open>
|
|
40
|
+
{#snippet dropdownTrigger()}
|
|
41
|
+
<button aria-label="Heading Options" on:click={() => (open = !open)} style="display: flex; align-items: center; gap: 4px;">
|
|
42
|
+
<h5 style="font-weight: bold;">H{editor.getAttributes('heading').level}</h5>
|
|
43
|
+
<i class="fa fa-chevron-down {open ? 'active' : ''}"></i>
|
|
44
|
+
</button>
|
|
45
|
+
{/snippet}
|
|
46
|
+
{#each headingOptions as option}
|
|
47
|
+
<MenuItem
|
|
48
|
+
active={option.level === editor.getAttributes('heading').level}
|
|
49
|
+
onclick={() => {
|
|
50
|
+
applyHeading(option);
|
|
51
|
+
open = false;
|
|
52
|
+
}}
|
|
53
|
+
>
|
|
54
|
+
{option.label}
|
|
55
|
+
</MenuItem>
|
|
56
|
+
{/each}
|
|
57
|
+
</DropdownContainer>
|
|
58
|
+
{/if}
|
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import type { Editor } from "@tiptap/core";
|
|
3
|
-
|
|
4
|
-
export let editor: Editor;
|
|
5
|
-
|
|
6
|
-
function undo() {
|
|
7
|
-
editor.chain().focus().undo().run();
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
function redo() {
|
|
11
|
-
editor.chain().focus().redo().run();
|
|
12
|
-
}
|
|
13
|
-
</script>
|
|
14
|
-
|
|
15
|
-
<button on:click={undo} aria-label="Undo" title="Undo" disabled={!editor.can().undo()}>
|
|
16
|
-
<i class="fa fa-undo"></i>
|
|
17
|
-
</button>
|
|
18
|
-
|
|
19
|
-
<button on:click={redo} aria-label="Redo" title="Redo" disabled={!editor.can().redo()}>
|
|
20
|
-
<i class="fa fa-redo"></i>
|
|
21
|
-
</button>
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { Editor } from "@tiptap/core";
|
|
3
|
+
|
|
4
|
+
export let editor: Editor;
|
|
5
|
+
|
|
6
|
+
function undo() {
|
|
7
|
+
editor.chain().focus().undo().run();
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
function redo() {
|
|
11
|
+
editor.chain().focus().redo().run();
|
|
12
|
+
}
|
|
13
|
+
</script>
|
|
14
|
+
|
|
15
|
+
<button on:click={undo} aria-label="Undo" title="Undo" disabled={!editor.can().undo()}>
|
|
16
|
+
<i class="fa fa-undo"></i>
|
|
17
|
+
</button>
|
|
18
|
+
|
|
19
|
+
<button on:click={redo} aria-label="Redo" title="Redo" disabled={!editor.can().redo()}>
|
|
20
|
+
<i class="fa fa-redo"></i>
|
|
21
|
+
</button>
|
|
@@ -1,85 +1,85 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import { insertImageAndMoveCursor } from '../../tools.js';
|
|
3
|
-
import {fileInputStore, resetFileInputStore, editorStore, setToastMessage, modalStore, Input, DropdownContainer, MenuItem} from '../../../../../index.js';
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
import type { Editor } from "@tiptap/core";
|
|
7
|
-
export let editor: Editor;
|
|
8
|
-
|
|
9
|
-
let openDropdown = false;
|
|
10
|
-
function handleInsertImage(){
|
|
11
|
-
if(
|
|
12
|
-
!$editorStore.r2_key ||
|
|
13
|
-
!$editorStore.serverGetUrl ||
|
|
14
|
-
!$editorStore.serverUploadUrl ||
|
|
15
|
-
!$editorStore.serverDeleteUrl
|
|
16
|
-
){
|
|
17
|
-
setToastMessage('error','File upload configuration is missing.');
|
|
18
|
-
return;
|
|
19
|
-
}
|
|
20
|
-
fileInputStore.update(store => ({
|
|
21
|
-
...store,
|
|
22
|
-
uploadType: ['image'],
|
|
23
|
-
disabledMenuItem: ['Music', 'Videos', 'Documents', 'Others'],
|
|
24
|
-
r2_key: $editorStore.r2_key,
|
|
25
|
-
serverGetUrl: $editorStore.serverGetUrl,
|
|
26
|
-
serverUploadUrl: $editorStore.serverUploadUrl,
|
|
27
|
-
serverDeleteUrl: $editorStore.serverDeleteUrl,
|
|
28
|
-
uploadModalOpen: true
|
|
29
|
-
}));
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
$: if (
|
|
33
|
-
$fileInputStore.submissionComplete &&
|
|
34
|
-
$fileInputStore.submissions.length > 0 &&
|
|
35
|
-
$fileInputStore.uploadModalOpen === false &&
|
|
36
|
-
editor
|
|
37
|
-
) {
|
|
38
|
-
const urlsToInsert = $fileInputStore.submissions.map(item => item.url);
|
|
39
|
-
|
|
40
|
-
for (const finalURL of urlsToInsert) {
|
|
41
|
-
insertImageAndMoveCursor(finalURL, editor);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
resetFileInputStore();
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
let value = ''
|
|
48
|
-
function enterURL(){
|
|
49
|
-
modalStore.update(m => ({
|
|
50
|
-
...m,
|
|
51
|
-
open: true,
|
|
52
|
-
title: 'Editor',
|
|
53
|
-
onConfirm: () => {
|
|
54
|
-
if (!isValidUrl(value)) {
|
|
55
|
-
setToastMessage('error', 'Please enter a valid image URL.');
|
|
56
|
-
return;
|
|
57
|
-
}
|
|
58
|
-
insertImageAndMoveCursor(value, editor);
|
|
59
|
-
value = ''
|
|
60
|
-
},
|
|
61
|
-
onCancel: () => { value = ''},
|
|
62
|
-
render: formContent
|
|
63
|
-
}));
|
|
64
|
-
}
|
|
65
|
-
function isValidUrl(value: string): boolean {
|
|
66
|
-
try {
|
|
67
|
-
const url = new URL(value);
|
|
68
|
-
return url.protocol === 'http:' || url.protocol === 'https:';
|
|
69
|
-
} catch {
|
|
70
|
-
return false;
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
</script>
|
|
74
|
-
{#snippet formContent()}
|
|
75
|
-
<Input label="Enter Image URL" id="image-url" bind:value={value}/>
|
|
76
|
-
{/snippet}
|
|
77
|
-
<DropdownContainer bind:open={openDropdown} width="150px">
|
|
78
|
-
{#snippet dropdownTrigger()}
|
|
79
|
-
<button aria-label="Insert Image" title="Insert File" on:click={() => openDropdown = !openDropdown}>
|
|
80
|
-
<i class="fa fa-file"></i>
|
|
81
|
-
</button>
|
|
82
|
-
{/snippet}
|
|
83
|
-
<MenuItem onclick={() => { handleInsertImage(); openDropdown = false; }}>File Picker</MenuItem>
|
|
84
|
-
<MenuItem onclick={() => { enterURL(); openDropdown = false; }}>Enter URL</MenuItem>
|
|
85
|
-
</DropdownContainer>
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { insertImageAndMoveCursor } from '../../tools.js';
|
|
3
|
+
import {fileInputStore, resetFileInputStore, editorStore, setToastMessage, modalStore, Input, DropdownContainer, MenuItem} from '../../../../../index.js';
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
import type { Editor } from "@tiptap/core";
|
|
7
|
+
export let editor: Editor;
|
|
8
|
+
|
|
9
|
+
let openDropdown = false;
|
|
10
|
+
function handleInsertImage(){
|
|
11
|
+
if(
|
|
12
|
+
!$editorStore.r2_key ||
|
|
13
|
+
!$editorStore.serverGetUrl ||
|
|
14
|
+
!$editorStore.serverUploadUrl ||
|
|
15
|
+
!$editorStore.serverDeleteUrl
|
|
16
|
+
){
|
|
17
|
+
setToastMessage('error','File upload configuration is missing.');
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
fileInputStore.update(store => ({
|
|
21
|
+
...store,
|
|
22
|
+
uploadType: ['image'],
|
|
23
|
+
disabledMenuItem: ['Music', 'Videos', 'Documents', 'Others'],
|
|
24
|
+
r2_key: $editorStore.r2_key,
|
|
25
|
+
serverGetUrl: $editorStore.serverGetUrl,
|
|
26
|
+
serverUploadUrl: $editorStore.serverUploadUrl,
|
|
27
|
+
serverDeleteUrl: $editorStore.serverDeleteUrl,
|
|
28
|
+
uploadModalOpen: true
|
|
29
|
+
}));
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
$: if (
|
|
33
|
+
$fileInputStore.submissionComplete &&
|
|
34
|
+
$fileInputStore.submissions.length > 0 &&
|
|
35
|
+
$fileInputStore.uploadModalOpen === false &&
|
|
36
|
+
editor
|
|
37
|
+
) {
|
|
38
|
+
const urlsToInsert = $fileInputStore.submissions.map(item => item.url);
|
|
39
|
+
|
|
40
|
+
for (const finalURL of urlsToInsert) {
|
|
41
|
+
insertImageAndMoveCursor(finalURL, editor);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
resetFileInputStore();
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
let value = ''
|
|
48
|
+
function enterURL(){
|
|
49
|
+
modalStore.update(m => ({
|
|
50
|
+
...m,
|
|
51
|
+
open: true,
|
|
52
|
+
title: 'Editor',
|
|
53
|
+
onConfirm: () => {
|
|
54
|
+
if (!isValidUrl(value)) {
|
|
55
|
+
setToastMessage('error', 'Please enter a valid image URL.');
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
insertImageAndMoveCursor(value, editor);
|
|
59
|
+
value = ''
|
|
60
|
+
},
|
|
61
|
+
onCancel: () => { value = ''},
|
|
62
|
+
render: formContent
|
|
63
|
+
}));
|
|
64
|
+
}
|
|
65
|
+
function isValidUrl(value: string): boolean {
|
|
66
|
+
try {
|
|
67
|
+
const url = new URL(value);
|
|
68
|
+
return url.protocol === 'http:' || url.protocol === 'https:';
|
|
69
|
+
} catch {
|
|
70
|
+
return false;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
</script>
|
|
74
|
+
{#snippet formContent()}
|
|
75
|
+
<Input label="Enter Image URL" id="image-url" bind:value={value}/>
|
|
76
|
+
{/snippet}
|
|
77
|
+
<DropdownContainer bind:open={openDropdown} width="150px">
|
|
78
|
+
{#snippet dropdownTrigger()}
|
|
79
|
+
<button aria-label="Insert Image" title="Insert File" on:click={() => openDropdown = !openDropdown}>
|
|
80
|
+
<i class="fa fa-file"></i>
|
|
81
|
+
</button>
|
|
82
|
+
{/snippet}
|
|
83
|
+
<MenuItem onclick={() => { handleInsertImage(); openDropdown = false; }}>File Picker</MenuItem>
|
|
84
|
+
<MenuItem onclick={() => { enterURL(); openDropdown = false; }}>Enter URL</MenuItem>
|
|
85
|
+
</DropdownContainer>
|
|
@@ -1,30 +1,30 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import type { Editor } from "@tiptap/core";
|
|
3
|
-
export let editor: Editor;
|
|
4
|
-
|
|
5
|
-
const toggleBullet = () => {
|
|
6
|
-
editor.chain().focus().toggleBulletList().run();
|
|
7
|
-
};
|
|
8
|
-
|
|
9
|
-
const toggleOrdered = () => {
|
|
10
|
-
editor.chain().focus().toggleOrderedList().run();
|
|
11
|
-
};
|
|
12
|
-
</script>
|
|
13
|
-
|
|
14
|
-
<div style="display: flex; gap: 0.5rem">
|
|
15
|
-
<button
|
|
16
|
-
aria-label="Bullet List"
|
|
17
|
-
title="Bullet List"
|
|
18
|
-
on:click={toggleBullet}
|
|
19
|
-
class="{editor?.isActive('bulletList') ? 'active' : ''}"
|
|
20
|
-
><i class="fa fa-list"></i>
|
|
21
|
-
</button>
|
|
22
|
-
|
|
23
|
-
<button
|
|
24
|
-
aria-label="Ordered List"
|
|
25
|
-
title="Ordered List"
|
|
26
|
-
on:click={toggleOrdered}
|
|
27
|
-
class="{editor?.isActive('orderedList') ? 'active' : ''}"
|
|
28
|
-
><i class="fa fa-list-ol"></i>
|
|
29
|
-
</button>
|
|
30
|
-
</div>
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { Editor } from "@tiptap/core";
|
|
3
|
+
export let editor: Editor;
|
|
4
|
+
|
|
5
|
+
const toggleBullet = () => {
|
|
6
|
+
editor.chain().focus().toggleBulletList().run();
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
const toggleOrdered = () => {
|
|
10
|
+
editor.chain().focus().toggleOrderedList().run();
|
|
11
|
+
};
|
|
12
|
+
</script>
|
|
13
|
+
|
|
14
|
+
<div style="display: flex; gap: 0.5rem">
|
|
15
|
+
<button
|
|
16
|
+
aria-label="Bullet List"
|
|
17
|
+
title="Bullet List"
|
|
18
|
+
on:click={toggleBullet}
|
|
19
|
+
class="{editor?.isActive('bulletList') ? 'active' : ''}"
|
|
20
|
+
><i class="fa fa-list"></i>
|
|
21
|
+
</button>
|
|
22
|
+
|
|
23
|
+
<button
|
|
24
|
+
aria-label="Ordered List"
|
|
25
|
+
title="Ordered List"
|
|
26
|
+
on:click={toggleOrdered}
|
|
27
|
+
class="{editor?.isActive('orderedList') ? 'active' : ''}"
|
|
28
|
+
><i class="fa fa-list-ol"></i>
|
|
29
|
+
</button>
|
|
30
|
+
</div>
|
|
@@ -1,55 +1,55 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import { onMount } from 'svelte';
|
|
3
|
-
import type { Editor } from "@tiptap/core";
|
|
4
|
-
import {DropdownContainer, MenuItem} from '../../../../../index.js'
|
|
5
|
-
|
|
6
|
-
export let editor: Editor;
|
|
7
|
-
|
|
8
|
-
let open = false;
|
|
9
|
-
|
|
10
|
-
const alignments = [
|
|
11
|
-
{ value: 'left', label: 'Left' },
|
|
12
|
-
{ value: 'center', label: 'Center' },
|
|
13
|
-
{ value: 'right', label: 'Right' },
|
|
14
|
-
{ value: 'justify', label: 'Justify' },
|
|
15
|
-
];
|
|
16
|
-
|
|
17
|
-
type AlignmentOption = {
|
|
18
|
-
value: string;
|
|
19
|
-
label: string;
|
|
20
|
-
};
|
|
21
|
-
|
|
22
|
-
function applyAlignment(option: AlignmentOption) {
|
|
23
|
-
editor?.chain().focus().setTextAlign(option.value).run();
|
|
24
|
-
}
|
|
25
|
-
onMount(() => {
|
|
26
|
-
applyAlignment({ value: 'left', label: 'Left' });
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
$: currentAlignment = editor
|
|
30
|
-
? alignments.find(a => editor.isActive({ textAlign: a.value })) || alignments[0]
|
|
31
|
-
: alignments[0];
|
|
32
|
-
|
|
33
|
-
</script>
|
|
34
|
-
|
|
35
|
-
{#if editor}
|
|
36
|
-
<DropdownContainer bind:open>
|
|
37
|
-
{#snippet dropdownTrigger()}
|
|
38
|
-
<button aria-label="Text Align Options" on:click={() => (open = !open)}>
|
|
39
|
-
<i class="fa-solid fa-align-{currentAlignment.value}"></i>
|
|
40
|
-
</button>
|
|
41
|
-
{/snippet}
|
|
42
|
-
{#each alignments as { value, label }}
|
|
43
|
-
<MenuItem
|
|
44
|
-
icon= "fa-align-{value}"
|
|
45
|
-
active={editor.isActive({ textAlign: value })}
|
|
46
|
-
onclick={() => {
|
|
47
|
-
applyAlignment({ value, label });
|
|
48
|
-
open = false;
|
|
49
|
-
}}
|
|
50
|
-
>
|
|
51
|
-
{label}
|
|
52
|
-
</MenuItem>
|
|
53
|
-
{/each}
|
|
54
|
-
</DropdownContainer>
|
|
55
|
-
{/if}
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { onMount } from 'svelte';
|
|
3
|
+
import type { Editor } from "@tiptap/core";
|
|
4
|
+
import {DropdownContainer, MenuItem} from '../../../../../index.js'
|
|
5
|
+
|
|
6
|
+
export let editor: Editor;
|
|
7
|
+
|
|
8
|
+
let open = false;
|
|
9
|
+
|
|
10
|
+
const alignments = [
|
|
11
|
+
{ value: 'left', label: 'Left' },
|
|
12
|
+
{ value: 'center', label: 'Center' },
|
|
13
|
+
{ value: 'right', label: 'Right' },
|
|
14
|
+
{ value: 'justify', label: 'Justify' },
|
|
15
|
+
];
|
|
16
|
+
|
|
17
|
+
type AlignmentOption = {
|
|
18
|
+
value: string;
|
|
19
|
+
label: string;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
function applyAlignment(option: AlignmentOption) {
|
|
23
|
+
editor?.chain().focus().setTextAlign(option.value).run();
|
|
24
|
+
}
|
|
25
|
+
onMount(() => {
|
|
26
|
+
applyAlignment({ value: 'left', label: 'Left' });
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
$: currentAlignment = editor
|
|
30
|
+
? alignments.find(a => editor.isActive({ textAlign: a.value })) || alignments[0]
|
|
31
|
+
: alignments[0];
|
|
32
|
+
|
|
33
|
+
</script>
|
|
34
|
+
|
|
35
|
+
{#if editor}
|
|
36
|
+
<DropdownContainer bind:open>
|
|
37
|
+
{#snippet dropdownTrigger()}
|
|
38
|
+
<button aria-label="Text Align Options" on:click={() => (open = !open)}>
|
|
39
|
+
<i class="fa-solid fa-align-{currentAlignment.value}"></i>
|
|
40
|
+
</button>
|
|
41
|
+
{/snippet}
|
|
42
|
+
{#each alignments as { value, label }}
|
|
43
|
+
<MenuItem
|
|
44
|
+
icon= "fa-align-{value}"
|
|
45
|
+
active={editor.isActive({ textAlign: value })}
|
|
46
|
+
onclick={() => {
|
|
47
|
+
applyAlignment({ value, label });
|
|
48
|
+
open = false;
|
|
49
|
+
}}
|
|
50
|
+
>
|
|
51
|
+
{label}
|
|
52
|
+
</MenuItem>
|
|
53
|
+
{/each}
|
|
54
|
+
</DropdownContainer>
|
|
55
|
+
{/if}
|
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
#editor-text-color .text-color-selector-dropdown {
|
|
2
|
-
display: grid;
|
|
3
|
-
grid-template-columns: repeat(6, 1fr);
|
|
4
|
-
gap: 5px;
|
|
5
|
-
padding: 5px;
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
#editor-text-color .color-swatch {
|
|
9
|
-
width: 20px;
|
|
10
|
-
height: 20px;
|
|
11
|
-
cursor: pointer;
|
|
12
|
-
border-radius: 50%;
|
|
13
|
-
transition: transform 0.1s ease-in-out;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
#editor-text-color .color-swatch:hover {
|
|
17
|
-
transform: scale(1.1);
|
|
18
|
-
}
|
|
1
|
+
#editor-text-color .text-color-selector-dropdown {
|
|
2
|
+
display: grid;
|
|
3
|
+
grid-template-columns: repeat(6, 1fr);
|
|
4
|
+
gap: 5px;
|
|
5
|
+
padding: 5px;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
#editor-text-color .color-swatch {
|
|
9
|
+
width: 20px;
|
|
10
|
+
height: 20px;
|
|
11
|
+
cursor: pointer;
|
|
12
|
+
border-radius: 50%;
|
|
13
|
+
transition: transform 0.1s ease-in-out;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
#editor-text-color .color-swatch:hover {
|
|
17
|
+
transform: scale(1.1);
|
|
18
|
+
}
|