@sierra-95/svelte-scaffold 1.0.32 → 1.0.34
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/components/Core/Alerts/Backdrop/backdrop.svelte +6 -12
- package/dist/components/Core/Alerts/Backdrop/backdrop.svelte.d.ts +1 -0
- package/dist/components/Core/Alerts/Wrapper/wrapper.svelte +9 -1
- package/dist/components/Core/Alerts/Wrapper/wrapper.svelte.d.ts +2 -0
- package/dist/components/Core/Form/Input/SearchBar/search.svelte +5 -14
- package/dist/components/Core/Menus/MenuItem/menuItem.svelte +2 -1
- package/dist/components/Core/Menus/MenuItem/menuItem.svelte.d.ts +1 -0
- package/dist/components/Core/Menus/Tabs/main.css +22 -0
- package/dist/components/Core/Menus/Tabs/main.svelte +45 -0
- package/dist/components/Core/Menus/Tabs/main.svelte.d.ts +12 -0
- package/dist/components/Core/others/Previews/Image/image.svelte +11 -4
- package/dist/components/Modules/Editor/Hooks/extractContent.d.ts +1 -1
- package/dist/components/Modules/Editor/Hooks/extractContent.js +3 -4
- package/dist/components/Modules/Editor/controls.svelte +38 -52
- package/dist/components/Modules/Editor/controls.svelte.d.ts +0 -2
- package/dist/components/Modules/Editor/export.svelte +30 -0
- package/dist/components/Modules/Editor/{save.svelte.d.ts → export.svelte.d.ts} +3 -5
- package/dist/components/Modules/Editor/main.svelte +1 -2
- package/dist/components/Modules/Editor/main.svelte.d.ts +0 -1
- package/dist/components/Modules/Editor/styles/controls.css +2 -13
- package/dist/components/Modules/Editor/styles/main.css +1 -1
- package/dist/components/Modules/Editor/tools.d.ts +1 -2
- package/dist/components/Modules/Editor/tools.js +1 -3
- package/dist/components/Modules/FilePicker/ActionsMenu/Actions.svelte +52 -0
- package/dist/components/Modules/FilePicker/ActionsMenu/Actions.svelte.d.ts +5 -0
- package/dist/components/Modules/FilePicker/ActionsMenu/delete_media.svelte +1 -1
- package/dist/components/Modules/FilePicker/ActionsMenu/download_media.svelte +1 -1
- package/dist/components/Modules/FilePicker/Cloud/cloudStore.svelte +26 -9
- package/dist/components/Modules/FilePicker/Cloud/previews.svelte +1 -1
- package/dist/components/Modules/FilePicker/main.svelte +26 -9
- package/dist/components/Modules/Layout/main.svelte +9 -7
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/stores/core/deviceWidth.d.ts +6 -0
- package/dist/stores/core/deviceWidth.js +26 -0
- package/dist/stores/modules/editor.d.ts +3 -0
- package/dist/stores/modules/editor.js +3 -0
- package/dist/stores/modules/fileInput.d.ts +1 -1
- package/dist/stores/modules/fileInput.js +1 -1
- package/package.json +1 -1
- package/dist/components/Core/Menus/UserMenu/profile.svelte +0 -35
- package/dist/components/Core/Menus/UserMenu/profile.svelte.d.ts +0 -11
- package/dist/components/Modules/Editor/Hooks/extractImage.d.ts +0 -7
- package/dist/components/Modules/Editor/Hooks/extractImage.js +0 -30
- package/dist/components/Modules/Editor/save.svelte +0 -28
- package/dist/components/Modules/FilePicker/controls.svelte +0 -95
- package/dist/components/Modules/FilePicker/controls.svelte.d.ts +0 -5
- package/dist/stores/core/ismobile.d.ts +0 -1
- package/dist/stores/core/ismobile.js +0 -14
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import { onMount, onDestroy } from "svelte";
|
|
3
|
-
import { browser } from "$app/environment";
|
|
4
2
|
|
|
5
3
|
let {
|
|
6
4
|
open = $bindable(false),
|
|
7
5
|
zIndex = 15,
|
|
6
|
+
onClose = () => {},
|
|
8
7
|
children
|
|
9
8
|
} = $props();
|
|
10
9
|
|
|
@@ -12,18 +11,10 @@
|
|
|
12
11
|
if (e.key === 'Escape' && open) {
|
|
13
12
|
e.preventDefault();
|
|
14
13
|
open = false;
|
|
14
|
+
onClose();
|
|
15
15
|
}
|
|
16
16
|
}
|
|
17
|
-
|
|
18
|
-
onMount(() => {
|
|
19
|
-
if (!browser) return;
|
|
20
|
-
window.addEventListener('keydown', handleEscape);
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
onDestroy(() => {
|
|
24
|
-
if (!browser) return;
|
|
25
|
-
window.removeEventListener('keydown', handleEscape);
|
|
26
|
-
});
|
|
17
|
+
|
|
27
18
|
</script>
|
|
28
19
|
<style>
|
|
29
20
|
#sierra-blur {
|
|
@@ -40,6 +31,9 @@
|
|
|
40
31
|
backdrop-filter: blur(2px);
|
|
41
32
|
}
|
|
42
33
|
</style>
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
<svelte:window on:keydown={handleEscape} />
|
|
43
37
|
{#if open}
|
|
44
38
|
<div id="sierra-blur" style="z-index: {zIndex};">
|
|
45
39
|
{@render children?.()}
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
padding = '20px',
|
|
4
4
|
minHeight = '100px',
|
|
5
5
|
maxWidth = '500px',
|
|
6
|
+
height = '',
|
|
6
7
|
children
|
|
7
8
|
} = $props();
|
|
8
9
|
</script>
|
|
@@ -14,6 +15,13 @@
|
|
|
14
15
|
width: 100%;
|
|
15
16
|
}
|
|
16
17
|
</style>
|
|
17
|
-
<div id="sierra-wrapper" role='none'
|
|
18
|
+
<div id="sierra-wrapper" role='none'
|
|
19
|
+
style="
|
|
20
|
+
max-width: {maxWidth};
|
|
21
|
+
min-height: {minHeight};
|
|
22
|
+
padding: {padding};
|
|
23
|
+
{height? `height: ${height}`:''}
|
|
24
|
+
"
|
|
25
|
+
onclick={e => e.stopPropagation()}>
|
|
18
26
|
{@render children?.()}
|
|
19
27
|
</div>
|
|
@@ -7,11 +7,13 @@ declare const Wrapper: import("svelte").Component<{
|
|
|
7
7
|
padding?: string;
|
|
8
8
|
minHeight?: string;
|
|
9
9
|
maxWidth?: string;
|
|
10
|
+
height?: string;
|
|
10
11
|
children: any;
|
|
11
12
|
}, {}, "">;
|
|
12
13
|
type $$ComponentProps = {
|
|
13
14
|
padding?: string;
|
|
14
15
|
minHeight?: string;
|
|
15
16
|
maxWidth?: string;
|
|
17
|
+
height?: string;
|
|
16
18
|
children: any;
|
|
17
19
|
};
|
|
@@ -1,7 +1,4 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import { onMount, onDestroy } from 'svelte';
|
|
3
|
-
import { browser } from '$app/environment';
|
|
4
|
-
|
|
1
|
+
<script lang="ts">
|
|
5
2
|
let {
|
|
6
3
|
width = '200px',
|
|
7
4
|
height = '40px',
|
|
@@ -21,16 +18,6 @@
|
|
|
21
18
|
onHotkey?.();
|
|
22
19
|
}
|
|
23
20
|
}
|
|
24
|
-
|
|
25
|
-
onMount(() => {
|
|
26
|
-
if (!enableHotkey || !browser) return;
|
|
27
|
-
window.addEventListener('keydown', handleKeydown);
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
onDestroy(() => {
|
|
31
|
-
if(!browser) return;
|
|
32
|
-
window.removeEventListener('keydown', handleKeydown);
|
|
33
|
-
});
|
|
34
21
|
</script>
|
|
35
22
|
<style>
|
|
36
23
|
#sierra-search-bar{
|
|
@@ -71,6 +58,10 @@
|
|
|
71
58
|
border-left: none;
|
|
72
59
|
}
|
|
73
60
|
</style>
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
<svelte:window on:keydown={handleKeydown} />
|
|
64
|
+
|
|
74
65
|
<main id="sierra-search-bar" role="none" style="height: {height}; display:flex; }">
|
|
75
66
|
|
|
76
67
|
<button
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
active = false,
|
|
5
5
|
disabled = false,
|
|
6
6
|
iconSize = '20px',
|
|
7
|
+
iconGap = '20px',
|
|
7
8
|
iconBg: iconBg = 'var(--primary-bg)',
|
|
8
9
|
children = null,
|
|
9
10
|
...rest
|
|
@@ -40,5 +41,5 @@
|
|
|
40
41
|
<i style="font-size: {iconSize}; color: {iconBg}"
|
|
41
42
|
class="fa {icon}"></i>
|
|
42
43
|
{/if}
|
|
43
|
-
<h4 style="margin-left: {icon ?
|
|
44
|
+
<h4 style="margin-left: {icon ? iconGap : '0'};">{@render children?.()}</h4>
|
|
44
45
|
</div>
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
#sierra-tabs {
|
|
2
|
+
position: relative;
|
|
3
|
+
background-color: var(--background-secondary);
|
|
4
|
+
}
|
|
5
|
+
#sierra-tabs .tab-row {
|
|
6
|
+
display: flex;
|
|
7
|
+
justify-content: space-between;
|
|
8
|
+
}
|
|
9
|
+
#sierra-tabs .tab {
|
|
10
|
+
display: flex;
|
|
11
|
+
align-items: center;
|
|
12
|
+
padding: 4px 16px;
|
|
13
|
+
border-radius: 4px 4px 0 0;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
#sierra-tabs .tab.active {
|
|
17
|
+
background-color: var(--background);
|
|
18
|
+
}
|
|
19
|
+
#sierra-tabs .tab-content{
|
|
20
|
+
padding: 1rem;
|
|
21
|
+
background-color: var(--background);
|
|
22
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { onMount } from 'svelte';
|
|
3
|
+
import './main.css';
|
|
4
|
+
|
|
5
|
+
let {
|
|
6
|
+
tabs,
|
|
7
|
+
snippets,
|
|
8
|
+
active = $bindable(),
|
|
9
|
+
iconBg = 'var(--primary-bg)',
|
|
10
|
+
iconSize = '15px',
|
|
11
|
+
boxShadow = false,
|
|
12
|
+
actions,
|
|
13
|
+
} = $props();
|
|
14
|
+
|
|
15
|
+
onMount(()=>{
|
|
16
|
+
if(!active && tabs?.length > 0){
|
|
17
|
+
active = tabs[0].key;
|
|
18
|
+
}
|
|
19
|
+
})
|
|
20
|
+
</script>
|
|
21
|
+
|
|
22
|
+
<div id="sierra-tabs" style="{boxShadow? 'box-shadow: var(--box-shadow)':''}">
|
|
23
|
+
<div class="tab-row">
|
|
24
|
+
<div style="display: flex;">
|
|
25
|
+
{#each tabs as tab}
|
|
26
|
+
<button
|
|
27
|
+
class="tab {active === tab.key ? 'active' : ''}"
|
|
28
|
+
onclick={() => active = tab.key}
|
|
29
|
+
>
|
|
30
|
+
{#if tab.icon}
|
|
31
|
+
<i style="font-size: {iconSize}; color: {iconBg}; margin-right: 8px;" class="fa {tab.icon}"></i>
|
|
32
|
+
{/if}
|
|
33
|
+
{tab.title}
|
|
34
|
+
</button>
|
|
35
|
+
{/each}
|
|
36
|
+
</div>
|
|
37
|
+
{@render actions?.()}
|
|
38
|
+
</div>
|
|
39
|
+
|
|
40
|
+
<div class="tab-content">
|
|
41
|
+
{#if snippets?.[active]}
|
|
42
|
+
{@render snippets[active]()}
|
|
43
|
+
{/if}
|
|
44
|
+
</div>
|
|
45
|
+
</div>
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import './main.css';
|
|
2
|
+
declare const Main: import("svelte").Component<{
|
|
3
|
+
tabs: any;
|
|
4
|
+
snippets: any;
|
|
5
|
+
active?: any;
|
|
6
|
+
iconBg?: string;
|
|
7
|
+
iconSize?: string;
|
|
8
|
+
boxShadow?: boolean;
|
|
9
|
+
actions: any;
|
|
10
|
+
}, {}, "active">;
|
|
11
|
+
type Main = ReturnType<typeof Main>;
|
|
12
|
+
export default Main;
|
|
@@ -16,7 +16,6 @@
|
|
|
16
16
|
|
|
17
17
|
function previewUrl(item: any): string | null {
|
|
18
18
|
if (!item) return null;
|
|
19
|
-
|
|
20
19
|
return isPreviewable(item)
|
|
21
20
|
? (urlsOnly ? (item).url : getPreviewUrlForMedia(item))
|
|
22
21
|
: null;
|
|
@@ -24,18 +23,26 @@
|
|
|
24
23
|
|
|
25
24
|
</script>
|
|
26
25
|
|
|
26
|
+
<style>
|
|
27
|
+
#sierra-preview-image img{
|
|
28
|
+
width: 100%;
|
|
29
|
+
height: 100px;
|
|
30
|
+
object-fit: cover;
|
|
31
|
+
}
|
|
32
|
+
</style>
|
|
33
|
+
|
|
27
34
|
{#snippet imageTag(url: string)}
|
|
28
|
-
<img src={url} alt={url}
|
|
35
|
+
<img src={url} alt={url} />
|
|
29
36
|
{/snippet}
|
|
30
37
|
|
|
31
38
|
{#if media.Images.length === 0}
|
|
32
39
|
<p>No images available.</p>
|
|
33
40
|
{:else}
|
|
34
|
-
<div style="display: flex; flex-wrap: wrap; gap: 1rem;">
|
|
41
|
+
<div id="sierra-preview-image" style="display: flex; flex-wrap: wrap; gap: 1rem;">
|
|
35
42
|
{#each media.Images as item}
|
|
36
43
|
<div on:click={() => toggleSelectForMedia(item, urlsOnly)} role="none" class="sierra-translate" style="position:relative; cursor: pointer; width: {previewUrl(item)? '150px':''}">
|
|
37
44
|
{#if previewUrl(item)}
|
|
38
|
-
{@render imageTag(item
|
|
45
|
+
{@render imageTag(previewUrl(item)!)}
|
|
39
46
|
{:else}
|
|
40
47
|
<Generic/>
|
|
41
48
|
{/if}
|
|
@@ -3,5 +3,5 @@
|
|
|
3
3
|
*/
|
|
4
4
|
export function exractContent(editor: import("@tiptap/core").Editor): Promise<{
|
|
5
5
|
json_content: import("@tiptap/core").DocumentType<Record<string, any> | undefined, import("@tiptap/core").NodeType<string, Record<string, any> | undefined, any, (import("@tiptap/core").NodeType<any, any, any, any> | import("@tiptap/core").TextType<import("@tiptap/core").MarkType<any, any>>)[]>[]>;
|
|
6
|
-
|
|
6
|
+
html_content: string;
|
|
7
7
|
} | undefined>;
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { setToastMessage } from '../../../../index.js';
|
|
2
|
-
import { extractImagesFromJSON } from '../tools.js';
|
|
3
2
|
/**
|
|
4
3
|
* @param {import('@tiptap/core').Editor} editor
|
|
5
4
|
*/
|
|
@@ -7,9 +6,9 @@ export async function exractContent(editor) {
|
|
|
7
6
|
if (!editor) return;
|
|
8
7
|
try {
|
|
9
8
|
const json_content = editor.getJSON();
|
|
10
|
-
const
|
|
11
|
-
return { json_content,
|
|
9
|
+
const html_content = editor.getHTML();
|
|
10
|
+
return { json_content, html_content};
|
|
12
11
|
}catch (error) {
|
|
13
|
-
setToastMessage('error', 'An error occurred while
|
|
12
|
+
setToastMessage('error', 'An error occurred while processing content.');
|
|
14
13
|
}
|
|
15
14
|
}
|
|
@@ -1,73 +1,59 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import {
|
|
3
3
|
TextFormatting, Headings, TextColor, TextAlign, Images, History, Youtube,
|
|
4
|
-
|
|
4
|
+
Export, Lists, Links
|
|
5
5
|
} from './tools.js';
|
|
6
6
|
import type { Editor } from "@tiptap/core";
|
|
7
7
|
import './styles/controls.css';
|
|
8
|
-
import {
|
|
8
|
+
import {Tabs} from '../../../index.js';
|
|
9
9
|
|
|
10
10
|
export let editor: Editor;
|
|
11
|
-
export let exportText: string;
|
|
12
|
-
export let content: any = {};
|
|
13
11
|
|
|
14
|
-
const
|
|
15
|
-
|
|
16
|
-
id: 'home',
|
|
17
|
-
label: 'Home',
|
|
18
|
-
icon: 'fa-home',
|
|
19
|
-
components: [
|
|
20
|
-
TextFormatting,
|
|
12
|
+
const HomeItems = [
|
|
13
|
+
TextFormatting,
|
|
21
14
|
History,
|
|
22
15
|
Headings,
|
|
23
16
|
TextColor,
|
|
24
17
|
TextAlign,
|
|
25
18
|
Lists,
|
|
26
|
-
]
|
|
27
|
-
},
|
|
28
|
-
{
|
|
29
|
-
id: 'insert',
|
|
30
|
-
label: 'Insert',
|
|
31
|
-
icon: 'fa-plus',
|
|
32
|
-
components: [
|
|
33
|
-
Images,
|
|
34
|
-
Links,
|
|
35
|
-
Youtube,
|
|
36
|
-
]
|
|
37
|
-
},
|
|
38
19
|
] as const;
|
|
39
|
-
|
|
40
|
-
type MenuItem = typeof menuItems[number];
|
|
41
|
-
type MenuId = MenuItem['id'];
|
|
42
|
-
|
|
43
|
-
let activeTab: MenuId = 'home';
|
|
44
|
-
</script>
|
|
45
20
|
|
|
21
|
+
const InsertItems = [
|
|
22
|
+
Images,
|
|
23
|
+
Links,
|
|
24
|
+
Youtube,
|
|
25
|
+
] as const;
|
|
26
|
+
</script>
|
|
46
27
|
|
|
47
|
-
|
|
48
|
-
<div
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
aria-label={item.label}
|
|
55
|
-
class={` ${activeTab === item.id ? 'active' : ''}`}
|
|
56
|
-
on:click={() => {activeTab = item.id}}
|
|
57
|
-
><i class="fa {item.icon}"></i><span hidden={$isMobile} style="margin-left: 5px;">{item.label}</span>
|
|
58
|
-
</button>
|
|
59
|
-
{/each}
|
|
28
|
+
{#snippet Home()}
|
|
29
|
+
<div id="controls">
|
|
30
|
+
<div class="controls-buttons">
|
|
31
|
+
{#each HomeItems as Component}
|
|
32
|
+
<Component {editor} />
|
|
33
|
+
{/each}
|
|
34
|
+
</div>
|
|
60
35
|
</div>
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
{#each item.components as Component}
|
|
36
|
+
{/snippet}
|
|
37
|
+
|
|
38
|
+
{#snippet Insert()}
|
|
39
|
+
<div id="controls">
|
|
40
|
+
<div class="controls-buttons">
|
|
41
|
+
{#each InsertItems as Component}
|
|
68
42
|
<Component {editor} />
|
|
69
43
|
{/each}
|
|
70
|
-
|
|
71
|
-
{/each}
|
|
44
|
+
</div>
|
|
72
45
|
</div>
|
|
73
|
-
|
|
46
|
+
{/snippet}
|
|
47
|
+
|
|
48
|
+
{#snippet actions()}
|
|
49
|
+
<Export {editor}/>
|
|
50
|
+
{/snippet}
|
|
51
|
+
|
|
52
|
+
<Tabs
|
|
53
|
+
tabs={[
|
|
54
|
+
{ key: 'Home', title: 'Home', icon: 'fa-home' },
|
|
55
|
+
{ key: 'Insert', title: 'Insert', icon: 'fa-plus' }
|
|
56
|
+
]}
|
|
57
|
+
snippets={{ Home, Insert }}
|
|
58
|
+
actions={actions}
|
|
59
|
+
/>
|
|
@@ -15,8 +15,6 @@ interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> =
|
|
|
15
15
|
}
|
|
16
16
|
declare const Controls: $$__sveltets_2_IsomorphicComponent<{
|
|
17
17
|
editor: Editor;
|
|
18
|
-
exportText: string;
|
|
19
|
-
content?: any;
|
|
20
18
|
}, {
|
|
21
19
|
[evt: string]: CustomEvent<any>;
|
|
22
20
|
}, {}, {}, string>;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { setToastMessage,isLoading, editorStore} from '../../../index.js';
|
|
3
|
+
import { exractContent } from './tools.js';
|
|
4
|
+
|
|
5
|
+
import type { Editor } from "@tiptap/core";
|
|
6
|
+
export let editor: Editor;
|
|
7
|
+
|
|
8
|
+
async function onSave() {
|
|
9
|
+
if(editor?.isEmpty) setToastMessage('warning','Editor is empty')
|
|
10
|
+
try {
|
|
11
|
+
isLoading.set(true);
|
|
12
|
+
const content = await exractContent(editor);
|
|
13
|
+
editorStore.update((state) => ({ ...state, content }));
|
|
14
|
+
$editorStore.onExport();
|
|
15
|
+
}catch (error) {
|
|
16
|
+
setToastMessage('error', 'An error occurred while processing content.');
|
|
17
|
+
} finally {
|
|
18
|
+
isLoading.set(false);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
$: if($editorStore.export){
|
|
23
|
+
editorStore.update( store =>{
|
|
24
|
+
store.export = false
|
|
25
|
+
return store;
|
|
26
|
+
})
|
|
27
|
+
onSave();
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
</script>
|
|
@@ -12,12 +12,10 @@ interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> =
|
|
|
12
12
|
};
|
|
13
13
|
z_$$bindings?: Bindings;
|
|
14
14
|
}
|
|
15
|
-
declare const
|
|
15
|
+
declare const Export: $$__sveltets_2_IsomorphicComponent<{
|
|
16
16
|
editor: Editor;
|
|
17
|
-
exportText: string;
|
|
18
|
-
content?: any;
|
|
19
17
|
}, {
|
|
20
18
|
[evt: string]: CustomEvent<any>;
|
|
21
19
|
}, {}, {}, string>;
|
|
22
|
-
type
|
|
23
|
-
export default
|
|
20
|
+
type Export = InstanceType<typeof Export>;
|
|
21
|
+
export default Export;
|
|
@@ -8,7 +8,6 @@
|
|
|
8
8
|
|
|
9
9
|
export let content: any = {};
|
|
10
10
|
export let readOnly: boolean = false;
|
|
11
|
-
export let exportText: string = 'Save';
|
|
12
11
|
|
|
13
12
|
let editor: Editor;
|
|
14
13
|
let element: HTMLElement;
|
|
@@ -36,7 +35,7 @@
|
|
|
36
35
|
|
|
37
36
|
<main id="editor">
|
|
38
37
|
{#if editor && !readOnly}
|
|
39
|
-
<Controls
|
|
38
|
+
<Controls {editor} />
|
|
40
39
|
{/if}
|
|
41
40
|
<div bind:this={element}></div>
|
|
42
41
|
</main>
|
|
@@ -15,7 +15,6 @@ interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> =
|
|
|
15
15
|
declare const Main: $$__sveltets_2_IsomorphicComponent<{
|
|
16
16
|
content?: any;
|
|
17
17
|
readOnly?: boolean;
|
|
18
|
-
exportText?: string;
|
|
19
18
|
}, {
|
|
20
19
|
[evt: string]: CustomEvent<any>;
|
|
21
20
|
}, {}, {}, string>;
|
|
@@ -1,11 +1,7 @@
|
|
|
1
1
|
#editor #controls{
|
|
2
|
-
margin: 0px 10px;
|
|
3
|
-
padding-top: 5px;
|
|
4
|
-
}
|
|
5
|
-
#editor #controls .controls {
|
|
6
2
|
margin-top: 5px;
|
|
7
3
|
position: relative;
|
|
8
|
-
background-color: var(--background-
|
|
4
|
+
background-color: var(--background-secondary);
|
|
9
5
|
border-radius: 15px;
|
|
10
6
|
}
|
|
11
7
|
|
|
@@ -15,19 +11,12 @@
|
|
|
15
11
|
align-items: center;
|
|
16
12
|
padding: 2px 10px;
|
|
17
13
|
gap: 10px;
|
|
18
|
-
position:
|
|
14
|
+
position: relative;
|
|
19
15
|
top: 0;
|
|
20
16
|
left: 0;
|
|
21
17
|
width: 100%;
|
|
22
|
-
opacity: 0;
|
|
23
|
-
pointer-events: none;
|
|
24
18
|
transition: opacity 0.2s ease;
|
|
25
19
|
}
|
|
26
|
-
#editor #controls .controls-buttons.active {
|
|
27
|
-
position: relative;
|
|
28
|
-
opacity: 1;
|
|
29
|
-
pointer-events: all;
|
|
30
|
-
}
|
|
31
20
|
#editor #controls button{
|
|
32
21
|
align-self: center;
|
|
33
22
|
}
|
|
@@ -7,8 +7,7 @@ export { default as Lists } from "./Nodes/Lists/lists.svelte";
|
|
|
7
7
|
export { default as TextFormatting } from "./Marks/TextFormatting/textFormatting.svelte";
|
|
8
8
|
export { default as Links } from "./Marks/Links/links.svelte";
|
|
9
9
|
export { default as History } from "./Nodes/History/history.svelte";
|
|
10
|
-
export { default as
|
|
10
|
+
export { default as Export } from "./export.svelte";
|
|
11
11
|
export { insertImageAndMoveCursor } from "./Hooks/insertImage.js";
|
|
12
12
|
export { addYoutubeVideo } from "./Hooks/insertYoutube.js";
|
|
13
|
-
export { extractImagesFromJSON } from "./Hooks/extractImage.js";
|
|
14
13
|
export { exractContent } from "./Hooks/extractContent.js";
|
|
@@ -13,11 +13,9 @@ export {default as Links} from './Marks/Links/links.svelte';
|
|
|
13
13
|
//functionality
|
|
14
14
|
export {default as History} from './Nodes/History/history.svelte';
|
|
15
15
|
|
|
16
|
-
|
|
17
16
|
//Export
|
|
18
|
-
export {default as
|
|
17
|
+
export {default as Export} from './export.svelte';
|
|
19
18
|
//Hooks
|
|
20
19
|
export {insertImageAndMoveCursor} from './Hooks/insertImage.js';
|
|
21
20
|
export {addYoutubeVideo} from './Hooks/insertYoutube.js';
|
|
22
|
-
export {extractImagesFromJSON} from './Hooks/extractImage.js';
|
|
23
21
|
export {exractContent} from './Hooks/extractContent.js';
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { onDestroy } from "svelte";
|
|
3
|
+
import {fileInputStore,resetFileInputStore, DropdownContainer, MenuItem, buttonRipple} from "../../../../index.js";
|
|
4
|
+
import FileProperties from "./file_properties.svelte";
|
|
5
|
+
import DownloadMedia from "./download_media.svelte";
|
|
6
|
+
import DeleteMedia from "./delete_media.svelte";
|
|
7
|
+
|
|
8
|
+
let {
|
|
9
|
+
processing = $bindable(),
|
|
10
|
+
} = $props();
|
|
11
|
+
|
|
12
|
+
function handleSelect() {
|
|
13
|
+
fileInputStore.update(store => ({
|
|
14
|
+
...store,
|
|
15
|
+
submissionComplete: true,
|
|
16
|
+
uploadModalOpen: false
|
|
17
|
+
}));
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const iconSize = '12px';
|
|
21
|
+
let showProperties = $state(false);
|
|
22
|
+
let openActionsMenu = $state(false);
|
|
23
|
+
let disableActions = $state(true);
|
|
24
|
+
$effect(() => {
|
|
25
|
+
if($fileInputStore.submissions.length > 0 && $fileInputStore.activeTab === 'Cloud'){
|
|
26
|
+
disableActions = false;
|
|
27
|
+
} else {
|
|
28
|
+
disableActions = true;
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
onDestroy(() => {
|
|
33
|
+
resetFileInputStore();
|
|
34
|
+
});
|
|
35
|
+
</script>
|
|
36
|
+
|
|
37
|
+
<FileProperties bind:showProperties />
|
|
38
|
+
<div style="display: flex; gap: 1rem; align-items: center; margin-right: 1rem">
|
|
39
|
+
<button hidden={$fileInputStore.manage || disableActions} title="Select" onclick={handleSelect} style="color: var(--primary-bg);" aria-label="Select submissions"><i class="fa fa-check-circle-o"></i></button>
|
|
40
|
+
{#snippet TriggerMenu()}
|
|
41
|
+
<button hidden={$fileInputStore.activeTab !== 'Cloud'} disabled={$fileInputStore.submissions.length === 0} use:buttonRipple class="w-10" aria-label="Ellipsis" onclick={() => (openActionsMenu = !openActionsMenu)}>
|
|
42
|
+
<i class="fa fa-bars"></i>
|
|
43
|
+
</button>
|
|
44
|
+
{/snippet}
|
|
45
|
+
<DropdownContainer bind:open={openActionsMenu} dropdownTrigger={TriggerMenu}>
|
|
46
|
+
<MenuItem iconBg="var(--primary-bg)" iconGap="10px" onclick={() => { showProperties = true; openActionsMenu = false; }} icon="fa-info-circle" iconSize={iconSize}>Properties</MenuItem>
|
|
47
|
+
<DownloadMedia {iconSize} bind:processing bind:openActionsMenu/>
|
|
48
|
+
<DeleteMedia {iconSize} bind:processing bind:openActionsMenu />
|
|
49
|
+
</DropdownContainer>
|
|
50
|
+
<button title="Cancel" onclick={resetFileInputStore} aria-label="Cancel"><i class="fa fa-xmark"></i></button>
|
|
51
|
+
</div>
|
|
52
|
+
|
|
@@ -65,4 +65,4 @@
|
|
|
65
65
|
}
|
|
66
66
|
</script>
|
|
67
67
|
|
|
68
|
-
<MenuItem onclick={handleDelete} icon="fa-trash-o" iconBg="var(--error-bg)" iconSize={iconSize}>Delete</MenuItem>
|
|
68
|
+
<MenuItem iconGap="10px" onclick={handleDelete} icon="fa-trash-o" iconBg="var(--error-bg)" iconSize={iconSize}>Delete</MenuItem>
|
|
@@ -72,4 +72,4 @@
|
|
|
72
72
|
}
|
|
73
73
|
</script>
|
|
74
74
|
|
|
75
|
-
<MenuItem onclick={handleDownload} icon="fa-download" iconBg="var(--
|
|
75
|
+
<MenuItem iconGap="10px" onclick={handleDownload} icon="fa-download" iconBg="var(--primary-bg)" iconSize={iconSize}>Download</MenuItem>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import { onMount } from 'svelte';
|
|
3
|
-
import { fileInputStore, User, setToastMessage, buttonRipple, isMobile } from '../../../../index.js';
|
|
3
|
+
import { fileInputStore, User, setToastMessage, buttonRipple, isMobile, isTablet } from '../../../../index.js';
|
|
4
4
|
import Previews from './previews.svelte';
|
|
5
5
|
import Storage from '../ActionsMenu/media_storage.svelte';
|
|
6
6
|
|
|
@@ -75,16 +75,33 @@
|
|
|
75
75
|
</script>
|
|
76
76
|
|
|
77
77
|
<style>
|
|
78
|
-
#sierra-cloud-store{
|
|
79
|
-
|
|
80
|
-
position: relative;
|
|
78
|
+
#sierra-cloud-store nav{
|
|
79
|
+
flex-direction: column;
|
|
81
80
|
}
|
|
82
81
|
#sierra-cloud-store .icon-active {
|
|
82
|
+
border-radius: 3px;
|
|
83
83
|
background-color: var(--menu-item-active);
|
|
84
84
|
}
|
|
85
|
+
#sierra-cloud-store i{
|
|
86
|
+
color: var(--icon-theme);
|
|
87
|
+
}
|
|
88
|
+
#sierra-cloud-store .icon-active i{
|
|
89
|
+
color: var(--primary-bg);
|
|
90
|
+
}
|
|
91
|
+
@media (max-width: 768px) {
|
|
92
|
+
#sierra-cloud-store {
|
|
93
|
+
flex-direction: column-reverse;
|
|
94
|
+
}
|
|
95
|
+
#sierra-cloud-store nav{
|
|
96
|
+
flex-direction: row;
|
|
97
|
+
}
|
|
98
|
+
#sierra-cloud-store nav button {
|
|
99
|
+
justify-content: center;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
85
102
|
</style>
|
|
86
103
|
<main id="sierra-cloud-store" style="display: flex; gap: 1rem; height: 100%; min-height: 300px;">
|
|
87
|
-
<nav style="display: flex;
|
|
104
|
+
<nav style="display: flex; gap: {$isMobile ? '1rem' : '0.5rem'}; padding-top: 1rem; background-color: var(--background); border-bottom-left-radius:5px;">
|
|
88
105
|
{#each tabs as tab}
|
|
89
106
|
<button
|
|
90
107
|
use:buttonRipple
|
|
@@ -95,16 +112,16 @@
|
|
|
95
112
|
}))
|
|
96
113
|
}
|
|
97
114
|
style="
|
|
98
|
-
width:100%; padding: 0.1rem 0.5rem;
|
|
99
|
-
{$fileInputStore.disabledMenuItem?.includes(tab.name) ? 'display: none;' : 'display: flex;align-items: center; gap: 0.5rem;'}
|
|
115
|
+
width:100%; padding:{$isMobile? '0.5rem':' 0.1rem 0.5rem'};
|
|
116
|
+
{$fileInputStore.disabledMenuItem?.includes(tab.name) ? 'display: none;' : 'display: flex; align-items: center; gap: 0.5rem;'}
|
|
100
117
|
"
|
|
101
118
|
class={`sierra-text-ellipsis ${$fileInputStore.activeMenu === tab.name ? 'icon-active' : ''}`}
|
|
102
119
|
>
|
|
103
|
-
<i class={tab.icon} style="font-size: {$isMobile ? '' : '10px'};
|
|
120
|
+
<i class={tab.icon} style="font-size: {$isMobile ? '15px' : '10px'}; "></i>
|
|
104
121
|
{$isMobile ? '' : tab.name}
|
|
105
122
|
</button>
|
|
106
123
|
{/each}
|
|
107
|
-
<Storage hidden={$isMobile} bind:this={childFunctionRef}/>
|
|
124
|
+
<Storage hidden={$isMobile || $isTablet} bind:this={childFunctionRef}/>
|
|
108
125
|
</nav>
|
|
109
126
|
<Previews {media} />
|
|
110
127
|
</main>
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
{:else}
|
|
34
34
|
<p>No media available.</p>
|
|
35
35
|
{/if}
|
|
36
|
-
<div hidden={itemCount === 0} style="position: absolute; bottom: 0; right: 0;padding: 2px 5px; box-shadow: var(--box-shadow); background: var(--background
|
|
36
|
+
<div hidden={itemCount === 0} style="position: absolute; bottom: 0; right: 0;padding: 2px 5px; box-shadow: var(--box-shadow); background: var(--background); z-index: 1;">
|
|
37
37
|
{itemCount} {itemCount === 1 ? 'item' : 'items'} selected ({totalSizeMB} MB)
|
|
38
38
|
</div>
|
|
39
39
|
</div>
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import {Backdrop,Wrapper,fileInputStore, FileInput, User, setToastMessage} from '../../../index.js'
|
|
2
|
+
import {Backdrop,Wrapper,fileInputStore, LinearProgress,FileInput, User, setToastMessage, Tabs} from '../../../index.js'
|
|
3
3
|
import CloudStore from './Cloud/cloudStore.svelte';
|
|
4
|
-
import
|
|
4
|
+
import Actions from './ActionsMenu/Actions.svelte';
|
|
5
5
|
|
|
6
6
|
let processing: boolean = false;
|
|
7
7
|
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
|
|
37
37
|
fileInputStore.update(store => {
|
|
38
38
|
store.selectedFiles = [];
|
|
39
|
-
store.activeTab = '
|
|
39
|
+
store.activeTab = 'Cloud';
|
|
40
40
|
store.requestReload = true;
|
|
41
41
|
return store;
|
|
42
42
|
});
|
|
@@ -48,13 +48,30 @@
|
|
|
48
48
|
}
|
|
49
49
|
</script>
|
|
50
50
|
|
|
51
|
+
|
|
52
|
+
{#snippet Cloud()}
|
|
53
|
+
<CloudStore bind:processing />
|
|
54
|
+
{/snippet}
|
|
55
|
+
|
|
56
|
+
{#snippet Upload()}
|
|
57
|
+
<FileInput bind:processing onclick={handleUpload} />
|
|
58
|
+
{/snippet}
|
|
59
|
+
|
|
60
|
+
{#snippet actions()}
|
|
61
|
+
<Actions bind:processing />
|
|
62
|
+
{/snippet}
|
|
63
|
+
|
|
51
64
|
<Backdrop bind:open={$fileInputStore.uploadModalOpen} zIndex={15}>
|
|
52
65
|
<Wrapper maxWidth="700px" minHeight="300px" padding="0px">
|
|
53
|
-
<
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
66
|
+
<Tabs
|
|
67
|
+
bind:active={$fileInputStore.activeTab}
|
|
68
|
+
tabs={[
|
|
69
|
+
{ key: 'Cloud', title: 'Cloud', icon: 'fa-cloud' },
|
|
70
|
+
{ key: 'Upload', title: 'Upload', icon: 'fa-plus' }
|
|
71
|
+
]}
|
|
72
|
+
snippets={{ Cloud, Upload }}
|
|
73
|
+
actions={actions}
|
|
74
|
+
/>
|
|
75
|
+
{#if processing}<LinearProgress />{/if}
|
|
59
76
|
</Wrapper>
|
|
60
77
|
</Backdrop>
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<script>
|
|
2
2
|
import './main.css';
|
|
3
3
|
import { onMount } from 'svelte';
|
|
4
|
-
import {LinearProgress, isLoading, isMobile, Modal, Toast, theme,FilePicker} from '../../../index.js'
|
|
4
|
+
import {LinearProgress, isLoading, isMobile, isTablet, Modal, Toast, theme,FilePicker} from '../../../index.js'
|
|
5
5
|
import Header from './Header/header.svelte';
|
|
6
6
|
import Menu from './Menu/menu.svelte';
|
|
7
7
|
import Background from './background.svelte';
|
|
@@ -23,10 +23,12 @@
|
|
|
23
23
|
toggleMenuSize = "25px",
|
|
24
24
|
} = $props();
|
|
25
25
|
|
|
26
|
-
|
|
26
|
+
let isSmallscreen = $state(true);
|
|
27
27
|
let isMenuOpen = $state(false);
|
|
28
|
+
|
|
28
29
|
$effect(() => {
|
|
29
|
-
|
|
30
|
+
isSmallscreen = $isMobile || $isTablet;
|
|
31
|
+
if (isSmallscreen) isMenuOpen = false;
|
|
30
32
|
if ($theme){
|
|
31
33
|
document.body.setAttribute('data-theme', $theme);
|
|
32
34
|
localStorage.setItem('theme', $theme);
|
|
@@ -35,7 +37,7 @@
|
|
|
35
37
|
|
|
36
38
|
onMount(() => {
|
|
37
39
|
if (typeof localStorage !== 'undefined') {
|
|
38
|
-
if(
|
|
40
|
+
if(!isSmallscreen){
|
|
39
41
|
const stored = localStorage.getItem('isMenuOpen');
|
|
40
42
|
if (stored === null) {
|
|
41
43
|
localStorage.setItem('isMenuOpen', 'true');
|
|
@@ -58,13 +60,13 @@
|
|
|
58
60
|
|
|
59
61
|
const toggleMenu = () => {
|
|
60
62
|
isMenuOpen = !isMenuOpen;
|
|
61
|
-
if(
|
|
63
|
+
if(isSmallscreen) return;
|
|
62
64
|
if (typeof localStorage !== 'undefined') {
|
|
63
65
|
localStorage.setItem('isMenuOpen', isMenuOpen.toString());
|
|
64
66
|
}
|
|
65
67
|
};
|
|
66
68
|
const closeMobileMenu = () => {
|
|
67
|
-
if (
|
|
69
|
+
if (isSmallscreen && isMenuOpen) isMenuOpen = false;
|
|
68
70
|
};
|
|
69
71
|
</script>
|
|
70
72
|
|
|
@@ -90,7 +92,7 @@
|
|
|
90
92
|
class="menu"
|
|
91
93
|
data-label="Menu Container"
|
|
92
94
|
style={
|
|
93
|
-
|
|
95
|
+
isSmallscreen
|
|
94
96
|
? `width:300px; transform: translateX(${isMenuOpen ? '0%' : '-100%'}); transition: transform 0.3s ease; position: fixed; left: 0; padding-bottom: 50px`
|
|
95
97
|
: `width: ${isMenuOpen ? '300px' : '70px'}; transition: width 0.3s ease;`
|
|
96
98
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -25,7 +25,7 @@ export { default as Toast } from './components/Core/Alerts/Toast/toast.svelte';
|
|
|
25
25
|
export { default as SiteUnderMaintenance } from './components/Core/Alerts/site-under-maintenance/site-under-maintenance.svelte';
|
|
26
26
|
export { default as MenuItem } from './components/Core/Menus/MenuItem/menuItem.svelte';
|
|
27
27
|
export { default as DropdownContainer } from './components/Core/Menus/DropdownContainer/dropdown.svelte';
|
|
28
|
-
export { default as
|
|
28
|
+
export { default as Tabs } from './components/Core/Menus/Tabs/main.svelte';
|
|
29
29
|
export { default as Time } from './components/Core/others/Clock/Time/time.svelte';
|
|
30
30
|
export { default as Date } from './components/Core/others/Clock/Date/date.svelte';
|
|
31
31
|
export { default as Hr } from './components/Core/Form/Hr/hr.svelte';
|
|
@@ -33,7 +33,7 @@ export { default as Editor } from './components/Modules/Editor/main.svelte';
|
|
|
33
33
|
export { default as Layout } from './components/Modules/Layout/main.svelte';
|
|
34
34
|
export { default as FilePicker } from './components/Modules/FilePicker/main.svelte';
|
|
35
35
|
export { isLoading, isLoggedIn, theme, } from './stores/core/general.js';
|
|
36
|
-
export { isMobile } from './stores/core/
|
|
36
|
+
export { isMobile, isTablet, isDesktop } from './stores/core/deviceWidth.js';
|
|
37
37
|
export { User, resetUserStore } from './stores/core/user.js';
|
|
38
38
|
export { modalStore, resetModalStore } from './stores/core/modal.js';
|
|
39
39
|
export { editorStore, resetEditorStore } from './stores/modules/editor.js';
|
package/dist/index.js
CHANGED
|
@@ -32,7 +32,7 @@ export { default as SiteUnderMaintenance } from './components/Core/Alerts/site-u
|
|
|
32
32
|
//Menus
|
|
33
33
|
export { default as MenuItem } from './components/Core/Menus/MenuItem/menuItem.svelte';
|
|
34
34
|
export { default as DropdownContainer } from './components/Core/Menus/DropdownContainer/dropdown.svelte';
|
|
35
|
-
export { default as
|
|
35
|
+
export { default as Tabs } from './components/Core/Menus/Tabs/main.svelte';
|
|
36
36
|
//others
|
|
37
37
|
export { default as Time } from './components/Core/others/Clock/Time/time.svelte';
|
|
38
38
|
export { default as Date } from './components/Core/others/Clock/Date/date.svelte';
|
|
@@ -44,7 +44,7 @@ export { default as FilePicker } from './components/Modules/FilePicker/main.svel
|
|
|
44
44
|
//#######################STORES########################
|
|
45
45
|
//Core
|
|
46
46
|
export { isLoading, isLoggedIn, theme, } from './stores/core/general.js';
|
|
47
|
-
export { isMobile } from './stores/core/
|
|
47
|
+
export { isMobile, isTablet, isDesktop } from './stores/core/deviceWidth.js';
|
|
48
48
|
export { User, resetUserStore } from './stores/core/user.js';
|
|
49
49
|
export { modalStore, resetModalStore } from './stores/core/modal.js';
|
|
50
50
|
//Modules
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export const isMobile: import("svelte/store").Writable<boolean>;
|
|
2
|
+
export const isTablet: import("svelte/store").Writable<boolean>;
|
|
3
|
+
export const isDesktop: import("svelte/store").Writable<boolean>;
|
|
4
|
+
export const BP_MOBILE: 480;
|
|
5
|
+
export const BP_TABLET: 768;
|
|
6
|
+
export const BP_DESKTOP: 1024;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { writable } from 'svelte/store';
|
|
2
|
+
import { browser } from '$app/environment';
|
|
3
|
+
|
|
4
|
+
export const isMobile = writable(true);
|
|
5
|
+
export const isTablet = writable(true);
|
|
6
|
+
export const isDesktop = writable(false);
|
|
7
|
+
|
|
8
|
+
export const BP_MOBILE = 480;
|
|
9
|
+
export const BP_TABLET = 768;
|
|
10
|
+
export const BP_DESKTOP = 1024;
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
if (browser) {
|
|
14
|
+
const updateDevice = () => {
|
|
15
|
+
const width = window.innerWidth;
|
|
16
|
+
|
|
17
|
+
isMobile.set(width < BP_MOBILE);
|
|
18
|
+
isTablet.set(width >= BP_MOBILE && width < BP_DESKTOP);
|
|
19
|
+
isDesktop.set(width >= BP_DESKTOP);
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
updateDevice();
|
|
23
|
+
window.addEventListener('resize', updateDevice);
|
|
24
|
+
|
|
25
|
+
// return () => window.removeEventListener('resize', updateDevice);
|
|
26
|
+
}
|
|
@@ -13,7 +13,7 @@ export type FileInputState = {
|
|
|
13
13
|
selectedFiles: File[];
|
|
14
14
|
sizeConstraint: number;
|
|
15
15
|
uploadType: Array<'image' | 'audio' | 'video' | 'documents' | 'others'>;
|
|
16
|
-
activeTab: '
|
|
16
|
+
activeTab: 'Cloud' | 'Upload';
|
|
17
17
|
activeMenu: 'Documents' | 'Music' | 'Pictures' | 'Videos' | 'Others';
|
|
18
18
|
disabledMenuItem: Array<'Music' | 'Documents' | 'Pictures' | 'Videos' | 'Others'> | null;
|
|
19
19
|
manage: boolean;
|
package/package.json
CHANGED
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import {DropdownContainer} from '../../../../index.js';
|
|
3
|
-
|
|
4
|
-
let {
|
|
5
|
-
top = '150%',
|
|
6
|
-
width = '300px',
|
|
7
|
-
iconSize = '30px',
|
|
8
|
-
iconBg = 'var(--primary-bg)',
|
|
9
|
-
user = $bindable({}),
|
|
10
|
-
open = $bindable(false),
|
|
11
|
-
children = null,
|
|
12
|
-
} = $props();
|
|
13
|
-
|
|
14
|
-
const handleClick = () => {
|
|
15
|
-
open = !open;
|
|
16
|
-
};
|
|
17
|
-
</script>
|
|
18
|
-
|
|
19
|
-
<DropdownContainer bind:open {top} {width}>
|
|
20
|
-
{#snippet dropdownTrigger()}
|
|
21
|
-
<button aria-label="none" onclick={handleClick}>
|
|
22
|
-
<i style="font-size: {iconSize}; color: {iconBg}" class="fa-solid fa-user"></i>
|
|
23
|
-
</button>
|
|
24
|
-
{/snippet}
|
|
25
|
-
<div style="padding:15px; border-bottom:1px solid var(--border);">
|
|
26
|
-
{#if Object.keys(user).length > 0}
|
|
27
|
-
{#each Object.entries(user) as [key, value], i}
|
|
28
|
-
<p>{value}</p>
|
|
29
|
-
{/each}
|
|
30
|
-
{:else}
|
|
31
|
-
<p>No user info</p>
|
|
32
|
-
{/if}
|
|
33
|
-
</div>
|
|
34
|
-
{@render children?.()}
|
|
35
|
-
</DropdownContainer>
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
declare const Profile: import("svelte").Component<{
|
|
2
|
-
top?: string;
|
|
3
|
-
width?: string;
|
|
4
|
-
iconSize?: string;
|
|
5
|
-
iconBg?: string;
|
|
6
|
-
user?: Record<string, any>;
|
|
7
|
-
open?: boolean;
|
|
8
|
-
children?: any;
|
|
9
|
-
}, {}, "open" | "user">;
|
|
10
|
-
type Profile = ReturnType<typeof Profile>;
|
|
11
|
-
export default Profile;
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Extract all image slugs from a Tiptap JSON document.
|
|
3
|
-
*
|
|
4
|
-
* @param {import('@tiptap/core').JSONContent} json - Tiptap JSON content
|
|
5
|
-
* @returns {string[]} - Array of image slugs
|
|
6
|
-
*/
|
|
7
|
-
export function extractImagesFromJSON(json: import("@tiptap/core").JSONContent): string[];
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Extract all image slugs from a Tiptap JSON document.
|
|
3
|
-
*
|
|
4
|
-
* @param {import('@tiptap/core').JSONContent} json - Tiptap JSON content
|
|
5
|
-
* @returns {string[]} - Array of image slugs
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
export function extractImagesFromJSON(json) {
|
|
9
|
-
const slugs = new Set();
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Recursively walk a node and collect image slugs
|
|
13
|
-
* @param {any} node - Node in the JSON tree
|
|
14
|
-
*/
|
|
15
|
-
|
|
16
|
-
function walk(node) {
|
|
17
|
-
if (!node) return;
|
|
18
|
-
if (node.type === 'image' && typeof node.attrs?.src === 'string') {
|
|
19
|
-
const url = node.attrs.src;
|
|
20
|
-
const slug = url.split('/').pop();
|
|
21
|
-
if (slug) slugs.add(slug);
|
|
22
|
-
}
|
|
23
|
-
if (node.content && Array.isArray(node.content)) {
|
|
24
|
-
node.content.forEach(walk);
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
walk(json);
|
|
29
|
-
return [...slugs];
|
|
30
|
-
}
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import { setToastMessage,isLoading, Button} from '../../../index.js';
|
|
3
|
-
import { exractContent } from './tools.js';
|
|
4
|
-
|
|
5
|
-
import type { Editor } from "@tiptap/core";
|
|
6
|
-
export let editor: Editor;
|
|
7
|
-
export let exportText: string;
|
|
8
|
-
export let content: any = {};
|
|
9
|
-
|
|
10
|
-
$: disabled = $isLoading || editor?.isEmpty;
|
|
11
|
-
|
|
12
|
-
async function onSave() {
|
|
13
|
-
try {
|
|
14
|
-
isLoading.set(true);
|
|
15
|
-
content = await exractContent(editor);
|
|
16
|
-
}catch (error) {
|
|
17
|
-
setToastMessage('error', 'An error occurred while saving.');
|
|
18
|
-
} finally {
|
|
19
|
-
isLoading.set(false);
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
</script>
|
|
24
|
-
|
|
25
|
-
<Button
|
|
26
|
-
onclick={onSave}
|
|
27
|
-
disabled={disabled}
|
|
28
|
-
>{exportText}</Button>
|
|
@@ -1,95 +0,0 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import {fileInputStore, LinearProgress, resetFileInputStore, DropdownContainer, MenuItem, buttonRipple} from "../../../index.js";
|
|
3
|
-
import FileProperties from "./ActionsMenu/file_properties.svelte";
|
|
4
|
-
import DownloadMedia from "./ActionsMenu/download_media.svelte";
|
|
5
|
-
import DeleteMedia from "./ActionsMenu/delete_media.svelte";
|
|
6
|
-
|
|
7
|
-
let {
|
|
8
|
-
processing = $bindable(),
|
|
9
|
-
} = $props();
|
|
10
|
-
|
|
11
|
-
const menuItems = [
|
|
12
|
-
{
|
|
13
|
-
id: 'cloud',
|
|
14
|
-
label: 'Cloud',
|
|
15
|
-
},
|
|
16
|
-
{
|
|
17
|
-
id: 'upload',
|
|
18
|
-
label: 'Upload',
|
|
19
|
-
},
|
|
20
|
-
] as const;
|
|
21
|
-
|
|
22
|
-
function handleSelect() {
|
|
23
|
-
fileInputStore.update(store => ({
|
|
24
|
-
...store,
|
|
25
|
-
submissionComplete: true,
|
|
26
|
-
uploadModalOpen: false
|
|
27
|
-
}));
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
const iconSize = '15px';
|
|
31
|
-
let showProperties = $state(false);
|
|
32
|
-
let openActionsMenu = $state(false);
|
|
33
|
-
let disableActions = $state(true);
|
|
34
|
-
$effect(() => {
|
|
35
|
-
if($fileInputStore.submissions.length > 0 && $fileInputStore.activeTab === 'cloud'){
|
|
36
|
-
disableActions = false;
|
|
37
|
-
} else {
|
|
38
|
-
disableActions = true;
|
|
39
|
-
}
|
|
40
|
-
});
|
|
41
|
-
</script>
|
|
42
|
-
|
|
43
|
-
<style>
|
|
44
|
-
.file-picker-controls {
|
|
45
|
-
display: flex;
|
|
46
|
-
flex-wrap: wrap;
|
|
47
|
-
justify-content: space-between;
|
|
48
|
-
gap : 1rem;
|
|
49
|
-
width: 100%;
|
|
50
|
-
padding: 0.5rem 1rem;
|
|
51
|
-
border-top-left-radius: 5px;
|
|
52
|
-
border-top-right-radius: 5px;
|
|
53
|
-
background-color: var(--background-tertiary);
|
|
54
|
-
}
|
|
55
|
-
#file-picker-controls i{
|
|
56
|
-
font-size: 18px;
|
|
57
|
-
}
|
|
58
|
-
#file-picker-controls button.active{
|
|
59
|
-
padding: 0.2rem 0.5rem;
|
|
60
|
-
border-radius: 3px;
|
|
61
|
-
background-color: var(--text);
|
|
62
|
-
color: var(--background);
|
|
63
|
-
}
|
|
64
|
-
</style>
|
|
65
|
-
|
|
66
|
-
<main id="file-picker-controls" style="display: flex; justify-content: space-between; gap:1rem;">
|
|
67
|
-
<div class="file-picker-controls">
|
|
68
|
-
<div style="display: flex; align-items: last baseline; gap:1rem;">
|
|
69
|
-
{#each menuItems as item, index (item.id)}
|
|
70
|
-
<button
|
|
71
|
-
class={$fileInputStore.activeTab === item.id ? 'active' : ''}
|
|
72
|
-
onclick={() => {fileInputStore.update(store => ({ ...store, activeTab: item.id }))}}
|
|
73
|
-
><span>{item.label}</span>
|
|
74
|
-
</button>
|
|
75
|
-
{/each}
|
|
76
|
-
</div>
|
|
77
|
-
<div style="display: flex; gap: 1rem; align-items: last baseline;">
|
|
78
|
-
<button hidden={$fileInputStore.manage || disableActions} title="Select" onclick={handleSelect} style="color: var(--primary-bg);" aria-label="Select submissions"><i class="fa fa-check-circle-o"></i></button>
|
|
79
|
-
{#snippet TriggerMenu()}
|
|
80
|
-
<button disabled={disableActions} use:buttonRipple class="w-10" aria-label="Ellipsis" onclick={() => (openActionsMenu = !openActionsMenu)}>
|
|
81
|
-
<i class="fa fa-bars"></i>
|
|
82
|
-
</button>
|
|
83
|
-
{/snippet}
|
|
84
|
-
<DropdownContainer bind:open={openActionsMenu} dropdownTrigger={TriggerMenu}>
|
|
85
|
-
<MenuItem onclick={() => { showProperties = true; openActionsMenu = false; }} icon="fa-info-circle" iconBg="var(--text)" iconSize={iconSize}>Properties</MenuItem>
|
|
86
|
-
<DownloadMedia {iconSize} bind:processing bind:openActionsMenu/>
|
|
87
|
-
<DeleteMedia {iconSize} bind:processing bind:openActionsMenu />
|
|
88
|
-
</DropdownContainer>
|
|
89
|
-
<button title="Cancel" onclick={resetFileInputStore} aria-label="Cancel"><i class="fa fa-times-circle"></i></button>
|
|
90
|
-
</div>
|
|
91
|
-
</div>
|
|
92
|
-
</main>
|
|
93
|
-
{#if processing}<LinearProgress />{/if}
|
|
94
|
-
|
|
95
|
-
<FileProperties bind:showProperties />
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export const isMobile: import("svelte/store").Writable<boolean>;
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import { writable } from 'svelte/store';
|
|
2
|
-
import { browser } from '$app/environment';
|
|
3
|
-
|
|
4
|
-
export const isMobile = writable(true);
|
|
5
|
-
|
|
6
|
-
if (browser) {
|
|
7
|
-
const updateIsMobile = () => {
|
|
8
|
-
isMobile.set(window.innerWidth < 768);
|
|
9
|
-
};
|
|
10
|
-
updateIsMobile();
|
|
11
|
-
window.addEventListener('resize', updateIsMobile);
|
|
12
|
-
|
|
13
|
-
// return () => window.removeEventListener('resize', updateIsMobile);
|
|
14
|
-
}
|