@functionalcms/svelte-components 4.16.1 → 4.19.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/components/form/Button.svelte +118 -129
- package/dist/components/form/Button.svelte.d.ts +0 -3
- package/dist/components/form/ChoiceInput.svelte +37 -80
- package/dist/components/form/ChoiceInput.svelte.d.ts +1 -17
- package/dist/components/form/Dropzone.svelte +183 -0
- package/dist/components/form/Dropzone.svelte.d.ts +4 -0
- package/dist/components/form/Form.svelte +43 -95
- package/dist/components/form/Form.svelte.d.ts +8 -14
- package/dist/components/form/Input.svelte +3 -3
- package/dist/components/form/Input.svelte.d.ts +3 -3
- package/dist/components/form/Select.svelte +39 -73
- package/dist/components/form/Switch.svelte +17 -19
- package/dist/components/form/dropzone.d.ts +49 -0
- package/dist/components/form/dropzone.js +18 -0
- package/dist/components/form/form.d.ts +32 -11
- package/dist/components/form/form.js +29 -33
- package/dist/components/layouts/Tabs.svelte +3 -3
- package/dist/components/layouts/TwoColumnsLayout.svelte +1 -1
- package/dist/components/layouts/TwoColumnsLayout.svelte.d.ts +3 -2
- package/dist/components/menu/CollapsibleMenu.svelte +4 -1
- package/dist/components/presentation/Carousel.svelte +4 -2
- package/dist/index-server.d.ts +1 -1
- package/dist/index-server.js +1 -1
- package/dist/index.d.ts +2 -9
- package/dist/index.js +2 -8
- package/dist/index.server.d.ts +1 -1
- package/dist/index.server.js +1 -1
- package/dist/server-side/getRedirectPipeline.d.ts +6 -0
- package/dist/server-side/getRedirectPipeline.js +16 -0
- package/package.json +82 -86
- package/dist/components/form/dropzone/DefaultDropzone.svelte +0 -37
- package/dist/components/form/dropzone/DefaultDropzone.svelte.d.ts +0 -8
- package/dist/components/form/dropzone/Dropzone.svelte +0 -306
- package/dist/components/form/dropzone/Dropzone.svelte.d.ts +0 -4
- package/dist/components/form/dropzone/UseDropzone.d.ts +0 -3
- package/dist/components/form/dropzone/UseDropzone.js +0 -19
- package/dist/components/form/dropzone/attr-accept.d.ts +0 -12
- package/dist/components/form/dropzone/attr-accept.js +0 -29
- package/dist/components/form/dropzone/default.d.ts +0 -31
- package/dist/components/form/dropzone/default.js +0 -78
- package/dist/components/form/dropzone/types.d.ts +0 -62
- package/dist/components/form/dropzone/types.js +0 -1
- package/dist/components/form/utils.d.ts +0 -13
- package/dist/components/form/utils.js +0 -1
- package/dist/server-side/redirection.d.ts +0 -6
- package/dist/server-side/redirection.js +0 -16
- package/dist/translations/translator.d.ts +0 -2
- package/dist/translations/translator.js +0 -11
|
@@ -24,12 +24,14 @@
|
|
|
24
24
|
perPage = 1,
|
|
25
25
|
slideGaps = '20px;',
|
|
26
26
|
disableDrag = false,
|
|
27
|
-
css = {slide: "", container: ""}
|
|
27
|
+
css = {slide: "", container: ""},
|
|
28
|
+
loop = false
|
|
28
29
|
}: Props = $props();
|
|
29
30
|
|
|
30
31
|
let options: EmblaOptionsType = {
|
|
31
|
-
loop:
|
|
32
|
+
loop: loop,
|
|
32
33
|
};
|
|
34
|
+
|
|
33
35
|
if(disableDrag) {
|
|
34
36
|
options.watchDrag = false;
|
|
35
37
|
}
|
package/dist/index-server.d.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
export { authenticationHandle } from './auth/authenticationHandle.js';
|
|
2
2
|
export { default as authorizationHandle } from './auth/authorizationHandle.js';
|
|
3
3
|
export { default as errorHandler } from './auth/errorHandle.js';
|
|
4
|
-
export { default as getRedirection } from './server-side/redirection.js';
|
|
5
4
|
export { redisSessionProvider } from './auth/redisSessionProvider.js';
|
|
6
5
|
export { machineAuthenticationProvider } from './auth/machineAuthenticationProvider.js';
|
|
7
6
|
export { userAuthenticationProvider } from './auth/userAuthenticationProvider.js';
|
|
@@ -9,3 +8,4 @@ export { getBlobService, getCommunicationService, getDataService, getTemplateSer
|
|
|
9
8
|
export type { RedirectResponse } from './auth/RedirectResponse.js';
|
|
10
9
|
export { createMachineTokenApprovedLocals } from './auth/getMachineAccessToken.js';
|
|
11
10
|
export { isHuman } from './components/form/AntiBot.js';
|
|
11
|
+
export { default as getRedirectPipeline } from './server-side/getRedirectPipeline.js';
|
package/dist/index-server.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
export { authenticationHandle } from './auth/authenticationHandle.js';
|
|
2
2
|
export { default as authorizationHandle } from './auth/authorizationHandle.js';
|
|
3
3
|
export { default as errorHandler } from './auth/errorHandle.js';
|
|
4
|
-
export { default as getRedirection } from './server-side/redirection.js';
|
|
5
4
|
export { redisSessionProvider } from './auth/redisSessionProvider.js';
|
|
6
5
|
export { machineAuthenticationProvider } from './auth/machineAuthenticationProvider.js';
|
|
7
6
|
export { userAuthenticationProvider } from './auth/userAuthenticationProvider.js';
|
|
8
7
|
export { getBlobService, getCommunicationService, getDataService, getTemplateService, getWebsiteService, getAIService, getAuthService, } from './server-side/getServices.js';
|
|
9
8
|
export { createMachineTokenApprovedLocals } from './auth/getMachineAccessToken.js';
|
|
10
9
|
export { isHuman } from './components/form/AntiBot.js';
|
|
10
|
+
export { default as getRedirectPipeline } from './server-side/getRedirectPipeline.js';
|
package/dist/index.d.ts
CHANGED
|
@@ -29,17 +29,10 @@ export { default as Button } from './components/form/Button.svelte';
|
|
|
29
29
|
export { default as Input } from './components/form/Input.svelte';
|
|
30
30
|
export { default as Switch } from './components/form/Switch.svelte';
|
|
31
31
|
export { default as ChoiceInput } from './components/form/ChoiceInput.svelte';
|
|
32
|
-
export type
|
|
32
|
+
export { InputType, FieldType, LabelSize, type Field } from './components/form/form.js';
|
|
33
33
|
export { default as AntiBot } from './components/form/AntiBot.svelte';
|
|
34
|
+
export { default as Dropzone } from './components/form/Dropzone.svelte';
|
|
34
35
|
export { default as Select } from './components/form/Select.svelte';
|
|
35
|
-
export { default as Form } from './components/form/Form.svelte';
|
|
36
|
-
export { type Field, serialize, createForm, readForm, mapEntiresToOptions } from './components/form/form.js';
|
|
37
|
-
export { default as Dropzone } from './components/form/dropzone/Dropzone.svelte';
|
|
38
|
-
export * from './components/form/dropzone/types.js';
|
|
39
36
|
export { default as Markdown } from './components/content/Markdown.svelte';
|
|
40
37
|
export { type BlogPost, listAllPosts, importPost } from './components/blog/blog.js';
|
|
41
38
|
export { default as EasyTools } from './components/integrations/EasyTools.svelte';
|
|
42
|
-
/**
|
|
43
|
-
* Translations
|
|
44
|
-
*/
|
|
45
|
-
export { translator, prefixedTranslator } from './translations/translator.js';
|
package/dist/index.js
CHANGED
|
@@ -42,12 +42,10 @@ export { default as Button } from './components/form/Button.svelte';
|
|
|
42
42
|
export { default as Input } from './components/form/Input.svelte';
|
|
43
43
|
export { default as Switch } from './components/form/Switch.svelte';
|
|
44
44
|
export { default as ChoiceInput } from './components/form/ChoiceInput.svelte';
|
|
45
|
+
export { InputType, FieldType, LabelSize } from './components/form/form.js';
|
|
45
46
|
export { default as AntiBot } from './components/form/AntiBot.svelte';
|
|
47
|
+
export { default as Dropzone } from './components/form/Dropzone.svelte';
|
|
46
48
|
export { default as Select } from './components/form/Select.svelte';
|
|
47
|
-
export { default as Form } from './components/form/Form.svelte';
|
|
48
|
-
export { serialize, createForm, readForm, mapEntiresToOptions } from './components/form/form.js';
|
|
49
|
-
export { default as Dropzone } from './components/form/dropzone/Dropzone.svelte';
|
|
50
|
-
export * from './components/form/dropzone/types.js';
|
|
51
49
|
/*
|
|
52
50
|
* Content
|
|
53
51
|
*/
|
|
@@ -60,7 +58,3 @@ export { listAllPosts, importPost } from './components/blog/blog.js';
|
|
|
60
58
|
* Integrations
|
|
61
59
|
*/
|
|
62
60
|
export { default as EasyTools } from './components/integrations/EasyTools.svelte';
|
|
63
|
-
/**
|
|
64
|
-
* Translations
|
|
65
|
-
*/
|
|
66
|
-
export { translator, prefixedTranslator } from './translations/translator.js';
|
package/dist/index.server.d.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
export { authenticationHandle } from './auth/authenticationHandle.ts';
|
|
2
2
|
export { default as authorizationHandle } from './auth/authorizationHandle.ts';
|
|
3
3
|
export { default as errorHandler } from './auth/errorHandle.ts';
|
|
4
|
-
export { default as getRedirection } from './server-side/redirection.ts';
|
|
5
4
|
export { redisSessionProvider } from './auth/redisSessionProvider.ts';
|
|
6
5
|
export { machineAuthenticationProvider } from './auth/machineAuthenticationProvider.ts';
|
|
7
6
|
export { userAuthenticationProvider } from './auth/userAuthenticationProvider.ts';
|
|
@@ -9,3 +8,4 @@ export { getBlobService, getCommunicationService, getDataService, getTemplateSer
|
|
|
9
8
|
export type { RedirectResponse } from './auth/RedirectResponse.ts';
|
|
10
9
|
export { createMachineTokenApprovedLocals } from './auth/getMachineAccessToken.ts';
|
|
11
10
|
export { isHuman } from './components/form/AntiBot.ts';
|
|
11
|
+
export { default as getRedirectPipeline } from './server-side/getRedirectPipeline.js';
|
package/dist/index.server.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
export { authenticationHandle } from './auth/authenticationHandle.ts';
|
|
2
2
|
export { default as authorizationHandle } from './auth/authorizationHandle.ts';
|
|
3
3
|
export { default as errorHandler } from './auth/errorHandle.ts';
|
|
4
|
-
export { default as getRedirection } from './server-side/redirection.ts';
|
|
5
4
|
export { redisSessionProvider } from './auth/redisSessionProvider.ts';
|
|
6
5
|
export { machineAuthenticationProvider } from './auth/machineAuthenticationProvider.ts';
|
|
7
6
|
export { userAuthenticationProvider } from './auth/userAuthenticationProvider.ts';
|
|
8
7
|
export { getBlobService, getCommunicationService, getDataService, getTemplateService, getWebsiteService, getAIService, getAuthService, } from './server-side/getServices.ts';
|
|
9
8
|
export { createMachineTokenApprovedLocals } from './auth/getMachineAccessToken.ts';
|
|
10
9
|
export { isHuman } from './components/form/AntiBot.ts';
|
|
10
|
+
export { default as getRedirectPipeline } from './server-side/getRedirectPipeline.js';
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { redirect } from '@sveltejs/kit';
|
|
2
|
+
const getRedirectPipeline = (redirections) => {
|
|
3
|
+
const redirectionPipeline = async ({ event, resolve }) => {
|
|
4
|
+
const url = event.url.pathname;
|
|
5
|
+
const elem = redirections.find((element) => element.pathname === url);
|
|
6
|
+
if (elem) {
|
|
7
|
+
const redirectToUrl = encodeURI(elem.redirectTo);
|
|
8
|
+
redirect(302, redirectToUrl);
|
|
9
|
+
}
|
|
10
|
+
else {
|
|
11
|
+
return await resolve(event);
|
|
12
|
+
}
|
|
13
|
+
};
|
|
14
|
+
return redirectionPipeline;
|
|
15
|
+
};
|
|
16
|
+
export default getRedirectPipeline;
|
package/package.json
CHANGED
|
@@ -1,86 +1,82 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@functionalcms/svelte-components",
|
|
3
|
-
"version": "4.
|
|
4
|
-
"watch": {
|
|
5
|
-
"build": {
|
|
6
|
-
"patterns": [
|
|
7
|
-
"src"
|
|
8
|
-
],
|
|
9
|
-
"extensions": "ts,svelte,scss",
|
|
10
|
-
"legacyWatch": false
|
|
11
|
-
}
|
|
12
|
-
},
|
|
13
|
-
"scripts": {
|
|
14
|
-
"dev": "vite dev",
|
|
15
|
-
"build-css": "sass ./src/lib/css/functional.scss ./css/functional.css --style compressed",
|
|
16
|
-
"build": "npm run build-css && vite build && npm run package",
|
|
17
|
-
"preview": "vite preview",
|
|
18
|
-
"package": "svelte-kit sync && svelte-package && publint",
|
|
19
|
-
"prepublishOnly": "npm run build-css && npm run package",
|
|
20
|
-
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
|
|
21
|
-
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
|
|
22
|
-
"lint": "eslint . && prettier --check .",
|
|
23
|
-
"format": "prettier --write .",
|
|
24
|
-
"watch": "npm-watch build"
|
|
25
|
-
},
|
|
26
|
-
"exports": {
|
|
27
|
-
".": {
|
|
28
|
-
"types": "./dist/index.d.ts",
|
|
29
|
-
"svelte": "./dist/index.js"
|
|
30
|
-
},
|
|
31
|
-
"./index-server.js": {
|
|
32
|
-
"types": "./dist/index-server.d.ts",
|
|
33
|
-
"svelte": "./dist/index-server.js"
|
|
34
|
-
},
|
|
35
|
-
"./css": "./css/*.css",
|
|
36
|
-
"./package.json": "./package.json"
|
|
37
|
-
},
|
|
38
|
-
"files": [
|
|
39
|
-
"dist",
|
|
40
|
-
"css",
|
|
41
|
-
"!dist/css/**/*.*",
|
|
42
|
-
"!dist/**/*.test.*",
|
|
43
|
-
"!dist/**/*.spec.*"
|
|
44
|
-
],
|
|
45
|
-
"devDependencies": {
|
|
46
|
-
"@eslint/compat": "^1.2.9",
|
|
47
|
-
"@eslint/js": "^9.26.0",
|
|
48
|
-
"@functionalcms/services": "^0.12.0",
|
|
49
|
-
"@sveltejs/adapter-auto": "^
|
|
50
|
-
"@sveltejs/package": "^2.3.11",
|
|
51
|
-
"@sveltejs/vite-plugin-svelte": "^5.0.3",
|
|
52
|
-
"autoprefixer": "^10.4.21",
|
|
53
|
-
"eslint": "^9.26.0",
|
|
54
|
-
"eslint-config-prettier": "^10.1.2",
|
|
55
|
-
"eslint-plugin-svelte": "^3.5.1",
|
|
56
|
-
"
|
|
57
|
-
"
|
|
58
|
-
"prettier": "^3.
|
|
59
|
-
"
|
|
60
|
-
"
|
|
61
|
-
"
|
|
62
|
-
"svelte": "^
|
|
63
|
-
"
|
|
64
|
-
"typescript": "^
|
|
65
|
-
"
|
|
66
|
-
"
|
|
67
|
-
},
|
|
68
|
-
"dependencies": {
|
|
69
|
-
"embla-carousel-svelte": "^8.6.0",
|
|
70
|
-
"ioredis": "^5.6.1",
|
|
71
|
-
"marked": "^15.0.11",
|
|
72
|
-
"oauth4webapi": "^3.5.0"
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
"
|
|
76
|
-
"
|
|
77
|
-
},
|
|
78
|
-
"
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
"main": "./dist/index.js",
|
|
84
|
-
"svelte": "./dist/index.js",
|
|
85
|
-
"types": "./dist/index.d.ts"
|
|
86
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@functionalcms/svelte-components",
|
|
3
|
+
"version": "4.19.2",
|
|
4
|
+
"watch": {
|
|
5
|
+
"build": {
|
|
6
|
+
"patterns": [
|
|
7
|
+
"src"
|
|
8
|
+
],
|
|
9
|
+
"extensions": "ts,svelte,scss",
|
|
10
|
+
"legacyWatch": false
|
|
11
|
+
}
|
|
12
|
+
},
|
|
13
|
+
"scripts": {
|
|
14
|
+
"dev": "vite dev",
|
|
15
|
+
"build-css": "sass ./src/lib/css/functional.scss ./css/functional.css --style compressed",
|
|
16
|
+
"build": "npm run build-css && vite build && npm run package",
|
|
17
|
+
"preview": "vite preview",
|
|
18
|
+
"package": "svelte-kit sync && svelte-package && publint",
|
|
19
|
+
"prepublishOnly": "npm run build-css && npm run package",
|
|
20
|
+
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
|
|
21
|
+
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
|
|
22
|
+
"lint": "eslint . && prettier --check .",
|
|
23
|
+
"format": "prettier --write .",
|
|
24
|
+
"watch": "npm-watch build"
|
|
25
|
+
},
|
|
26
|
+
"exports": {
|
|
27
|
+
".": {
|
|
28
|
+
"types": "./dist/index.d.ts",
|
|
29
|
+
"svelte": "./dist/index.js"
|
|
30
|
+
},
|
|
31
|
+
"./index-server.js": {
|
|
32
|
+
"types": "./dist/index-server.d.ts",
|
|
33
|
+
"svelte": "./dist/index-server.js"
|
|
34
|
+
},
|
|
35
|
+
"./css": "./css/*.css",
|
|
36
|
+
"./package.json": "./package.json"
|
|
37
|
+
},
|
|
38
|
+
"files": [
|
|
39
|
+
"dist",
|
|
40
|
+
"css",
|
|
41
|
+
"!dist/css/**/*.*",
|
|
42
|
+
"!dist/**/*.test.*",
|
|
43
|
+
"!dist/**/*.spec.*"
|
|
44
|
+
],
|
|
45
|
+
"devDependencies": {
|
|
46
|
+
"@eslint/compat": "^1.2.9",
|
|
47
|
+
"@eslint/js": "^9.26.0",
|
|
48
|
+
"@functionalcms/services": "^0.12.0",
|
|
49
|
+
"@sveltejs/adapter-auto": "^4.0.0",
|
|
50
|
+
"@sveltejs/package": "^2.3.11",
|
|
51
|
+
"@sveltejs/vite-plugin-svelte": "^5.0.3",
|
|
52
|
+
"autoprefixer": "^10.4.21",
|
|
53
|
+
"eslint": "^9.26.0",
|
|
54
|
+
"eslint-config-prettier": "^10.1.2",
|
|
55
|
+
"eslint-plugin-svelte": "^3.5.1",
|
|
56
|
+
"npm-watch": "^0.13.0",
|
|
57
|
+
"prettier": "^3.5.3",
|
|
58
|
+
"prettier-plugin-svelte": "^3.3.3",
|
|
59
|
+
"publint": "^0.3.12",
|
|
60
|
+
"sass": "^1.83.4",
|
|
61
|
+
"svelte": "^5.28.2",
|
|
62
|
+
"svelte-check": "^4.1.7",
|
|
63
|
+
"typescript": "^5.8.3",
|
|
64
|
+
"typescript-eslint": "^8.31.1",
|
|
65
|
+
"vite": "^6.3.4",
|
|
66
|
+
"@sveltejs/kit": "^2.20.8"
|
|
67
|
+
},
|
|
68
|
+
"dependencies": {
|
|
69
|
+
"embla-carousel-svelte": "^8.6.0",
|
|
70
|
+
"ioredis": "^5.6.1",
|
|
71
|
+
"marked": "^15.0.11",
|
|
72
|
+
"oauth4webapi": "^3.5.0"
|
|
73
|
+
},
|
|
74
|
+
"peerDependencies": {
|
|
75
|
+
"@sveltejs/kit": "^2.20.8",
|
|
76
|
+
"svelte": "^5.28.2"
|
|
77
|
+
},
|
|
78
|
+
"type": "module",
|
|
79
|
+
"main": "./dist/index.js",
|
|
80
|
+
"svelte": "./dist/index.js",
|
|
81
|
+
"types": "./dist/index.d.ts"
|
|
82
|
+
}
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import type { Snippet } from 'svelte';
|
|
3
|
-
import type { CustomDropzoneProps } from './types.js';
|
|
4
|
-
interface DefaultDropzone extends CustomDropzoneProps {
|
|
5
|
-
defaultDropzoneElement: HTMLElement | undefined;
|
|
6
|
-
children: Snippet;
|
|
7
|
-
}
|
|
8
|
-
let { defaultDropzoneElement = $bindable(), children, ...props }: DefaultDropzone = $props();
|
|
9
|
-
</script>
|
|
10
|
-
|
|
11
|
-
<div bind:this={defaultDropzoneElement} class="dropzone" {...props}>
|
|
12
|
-
{@render children()}
|
|
13
|
-
</div>
|
|
14
|
-
|
|
15
|
-
<style>
|
|
16
|
-
.dropzone {
|
|
17
|
-
flex: 1;
|
|
18
|
-
display: flex;
|
|
19
|
-
flex-direction: column;
|
|
20
|
-
align-items: center;
|
|
21
|
-
padding: 20px;
|
|
22
|
-
border-width: 2px;
|
|
23
|
-
border-radius: 2px;
|
|
24
|
-
border-color: #eeeeee;
|
|
25
|
-
border-style: dashed;
|
|
26
|
-
background-color: #fafafa;
|
|
27
|
-
color: #bdbdbd;
|
|
28
|
-
outline: none;
|
|
29
|
-
transition: border 0.24s ease-in-out;
|
|
30
|
-
}
|
|
31
|
-
.dropzone:hover {
|
|
32
|
-
border-color: #2196f3;
|
|
33
|
-
}
|
|
34
|
-
.dropzone:focus {
|
|
35
|
-
border-color: #2196f3;
|
|
36
|
-
}
|
|
37
|
-
</style>
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import type { Snippet } from 'svelte';
|
|
2
|
-
import type { CustomDropzoneProps } from './types.js';
|
|
3
|
-
interface DefaultDropzone extends CustomDropzoneProps {
|
|
4
|
-
defaultDropzoneElement: HTMLElement | undefined;
|
|
5
|
-
children: Snippet;
|
|
6
|
-
}
|
|
7
|
-
declare const DefaultDropzone: import("svelte").Component<DefaultDropzone, {}, "defaultDropzoneElement">;
|
|
8
|
-
export default DefaultDropzone;
|
|
@@ -1,306 +0,0 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import { fromEvent } from 'file-selector';
|
|
3
|
-
import {
|
|
4
|
-
checkFiles,
|
|
5
|
-
generateErrorMessage,
|
|
6
|
-
isEventWithFiles,
|
|
7
|
-
isIeOrEdge,
|
|
8
|
-
isPropagationStopped
|
|
9
|
-
} from './default.js';
|
|
10
|
-
import type {
|
|
11
|
-
DropzoneEventHandler,
|
|
12
|
-
DropzoneProps,
|
|
13
|
-
FromEventFileTypes,
|
|
14
|
-
RejectedFile
|
|
15
|
-
} from './types.js';
|
|
16
|
-
import type { EventHandler } from 'svelte/elements';
|
|
17
|
-
import DefaultDropzone from './DefaultDropzone.svelte';
|
|
18
|
-
import useDropzone from './UseDropzone.js';
|
|
19
|
-
|
|
20
|
-
let {
|
|
21
|
-
accept,
|
|
22
|
-
disabled = false,
|
|
23
|
-
maxFileCountPerUpload = Infinity,
|
|
24
|
-
maxSize = Infinity,
|
|
25
|
-
minSize = 0,
|
|
26
|
-
multiple = false,
|
|
27
|
-
dropzoneText = undefined,
|
|
28
|
-
preventDropOnDocument = true,
|
|
29
|
-
disableDropzoneClick = false,
|
|
30
|
-
disableDropzoneKeydown = false,
|
|
31
|
-
disableDropzoneDrag = false,
|
|
32
|
-
name = '',
|
|
33
|
-
appendOnDrop = false,
|
|
34
|
-
inputElement = $bindable(),
|
|
35
|
-
required = false,
|
|
36
|
-
dropzoneElement = $bindable(),
|
|
37
|
-
CustomDropzone,
|
|
38
|
-
children,
|
|
39
|
-
onDragenter,
|
|
40
|
-
onDragover,
|
|
41
|
-
onDragleave,
|
|
42
|
-
onDrop,
|
|
43
|
-
onFileDialogCancel
|
|
44
|
-
}: DropzoneProps = $props();
|
|
45
|
-
|
|
46
|
-
let isFileDialogActive: boolean = $state(false);
|
|
47
|
-
|
|
48
|
-
let defaultDropzoneElement: HTMLElement | undefined = $state();
|
|
49
|
-
|
|
50
|
-
let dropzoneRef: HTMLElement | undefined = $derived(dropzoneElement || defaultDropzoneElement);
|
|
51
|
-
|
|
52
|
-
let dragTargetsRef: EventTarget[] = $state([]);
|
|
53
|
-
async function getFileFromEvent<T extends FromEventFileTypes>(
|
|
54
|
-
event: Event
|
|
55
|
-
): Promise<{ acceptedFiles: T[]; rejectedFiles: RejectedFile<T>[] }> {
|
|
56
|
-
if (isPropagationStopped(event)) {
|
|
57
|
-
return { acceptedFiles: [], rejectedFiles: [] };
|
|
58
|
-
}
|
|
59
|
-
const files = (await fromEvent(event)) as T[];
|
|
60
|
-
const acceptedFiles: T[] = [];
|
|
61
|
-
const rejectedFiles: RejectedFile<T>[] = [];
|
|
62
|
-
|
|
63
|
-
files.forEach((file) => {
|
|
64
|
-
const { isAccepted, errors } = checkFiles({ file, accept, minSize, maxSize });
|
|
65
|
-
if (multiple && files.length > maxFileCountPerUpload) {
|
|
66
|
-
rejectedFiles.push({
|
|
67
|
-
file,
|
|
68
|
-
errors: [...errors, generateErrorMessage('TOO_MANY_FILES', { maxFileCountPerUpload })]
|
|
69
|
-
});
|
|
70
|
-
return;
|
|
71
|
-
}
|
|
72
|
-
if (!multiple && isAccepted && acceptedFiles.length > 0) {
|
|
73
|
-
rejectedFiles.push({
|
|
74
|
-
file,
|
|
75
|
-
errors: [generateErrorMessage('CANNOT_UPLOAD_MULTIPLE_FILES')]
|
|
76
|
-
});
|
|
77
|
-
return;
|
|
78
|
-
}
|
|
79
|
-
if (isAccepted) {
|
|
80
|
-
acceptedFiles.push(file);
|
|
81
|
-
return;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
rejectedFiles.push({ file, errors });
|
|
85
|
-
});
|
|
86
|
-
|
|
87
|
-
return { acceptedFiles, rejectedFiles };
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
async function triggerEventWithFiles<T extends FromEventFileTypes>(
|
|
91
|
-
event: Event,
|
|
92
|
-
callbackToTrigger: DropzoneEventHandler<T> | undefined
|
|
93
|
-
) {
|
|
94
|
-
const files = await getFileFromEvent<T>(event);
|
|
95
|
-
if (!files) return { acceptedFiles: [], rejectedFiles: [] };
|
|
96
|
-
const { acceptedFiles, rejectedFiles } = files;
|
|
97
|
-
callbackToTrigger?.({ acceptedFiles, rejectedFiles, event });
|
|
98
|
-
|
|
99
|
-
return files;
|
|
100
|
-
}
|
|
101
|
-
// Fn for opening the file dialog programmatically
|
|
102
|
-
function openFileDialog() {
|
|
103
|
-
if (inputElement) {
|
|
104
|
-
isFileDialogActive = true;
|
|
105
|
-
inputElement.click();
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
// open the file dialog when SPACE/ENTER occurs on the dropzone
|
|
110
|
-
function onDropzoneKeyDown(event: KeyboardEvent) {
|
|
111
|
-
const target = event.target as HTMLElement | null;
|
|
112
|
-
const dropzoneElementType = target?.getAttribute('drozone-element-type');
|
|
113
|
-
// Ignore keyboard events bubbling up the DOM tree
|
|
114
|
-
if (target?.id !== 'dropzone-element' && dropzoneElementType === 'dropzone-element') {
|
|
115
|
-
return;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
if (event.keyCode === 32 || event.keyCode === 13) {
|
|
119
|
-
event.preventDefault();
|
|
120
|
-
openFileDialog();
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
// open the file dialog when click occurs on the dropzone
|
|
125
|
-
function onDropzoneClick() {
|
|
126
|
-
if (disableDropzoneClick) {
|
|
127
|
-
return;
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
// In IE11/Edge the file-browser dialog is blocking, therefore, use setTimeout()
|
|
131
|
-
// to ensure React can handle state changes
|
|
132
|
-
// See: https://github.com/react-dropzone/react-dropzone/issues/450
|
|
133
|
-
if (isIeOrEdge()) {
|
|
134
|
-
setTimeout(openFileDialog, 0);
|
|
135
|
-
} else {
|
|
136
|
-
openFileDialog();
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
const onDropzoneDragEnter: EventHandler<DragEvent> = async (event) => {
|
|
140
|
-
event.preventDefault();
|
|
141
|
-
|
|
142
|
-
const target = event.target;
|
|
143
|
-
if (target) dragTargetsRef = [...dragTargetsRef, target];
|
|
144
|
-
|
|
145
|
-
if (isEventWithFiles(event)) {
|
|
146
|
-
await triggerEventWithFiles(event, onDragenter);
|
|
147
|
-
}
|
|
148
|
-
};
|
|
149
|
-
|
|
150
|
-
const onDropzoneDragOver: EventHandler<DragEvent> = async (event) => {
|
|
151
|
-
event.preventDefault();
|
|
152
|
-
|
|
153
|
-
if (event.dataTransfer) {
|
|
154
|
-
try {
|
|
155
|
-
event.dataTransfer.dropEffect = 'copy';
|
|
156
|
-
} catch {} /* eslint-disable-line no-empty */
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
if (isEventWithFiles(event)) {
|
|
160
|
-
await triggerEventWithFiles(event, onDragover);
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
return false;
|
|
164
|
-
};
|
|
165
|
-
|
|
166
|
-
const onDropzoneDragLeave: EventHandler<DragEvent> = async (event) => {
|
|
167
|
-
event.preventDefault();
|
|
168
|
-
|
|
169
|
-
// Only deactivate once the dropzone and all children have been left
|
|
170
|
-
const targets = dragTargetsRef.filter(
|
|
171
|
-
(target) => dropzoneRef && dropzoneRef.contains(target as Node)
|
|
172
|
-
);
|
|
173
|
-
// Make sure to remove a target present multiple times only once
|
|
174
|
-
// (Firefox may fire dragenter/dragleave multiple times on the same element)
|
|
175
|
-
const target = event.target as HTMLElement;
|
|
176
|
-
const targetIdx = targets.indexOf(target);
|
|
177
|
-
if (targetIdx !== -1) {
|
|
178
|
-
targets.splice(targetIdx, 1);
|
|
179
|
-
}
|
|
180
|
-
dragTargetsRef = targets;
|
|
181
|
-
if (targets.length > 0) {
|
|
182
|
-
return;
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
if (isEventWithFiles(event)) {
|
|
186
|
-
await triggerEventWithFiles(event, onDragleave);
|
|
187
|
-
}
|
|
188
|
-
};
|
|
189
|
-
|
|
190
|
-
const onDropzoneDrop = async (event: DragEvent | Event) => {
|
|
191
|
-
event.preventDefault();
|
|
192
|
-
isFileDialogActive = false;
|
|
193
|
-
dragTargetsRef = [];
|
|
194
|
-
if (isEventWithFiles(event)) {
|
|
195
|
-
const { acceptedFiles } = await triggerEventWithFiles(event, onDrop);
|
|
196
|
-
if ('dataTransfer' in event && event.dataTransfer && inputElement) {
|
|
197
|
-
const dataTransfer = new DataTransfer();
|
|
198
|
-
const incomingFiles = acceptedFiles;
|
|
199
|
-
incomingFiles.forEach((v) => dataTransfer.items.add(v));
|
|
200
|
-
if (appendOnDrop) {
|
|
201
|
-
for(const file of inputElement.files || []) {
|
|
202
|
-
dataTransfer.items.add(file);
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
inputElement.files = dataTransfer.files;
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
event.stopPropagation();
|
|
209
|
-
};
|
|
210
|
-
|
|
211
|
-
let getHandler = $derived(<T extends Event>(fn: EventHandler<T>) => (disabled ? null : fn));
|
|
212
|
-
let getKeyboardEventHandle = $derived(<T extends Event>(fn: EventHandler<T>) =>
|
|
213
|
-
disableDropzoneKeydown ? null : getHandler(fn)
|
|
214
|
-
);
|
|
215
|
-
let getDragEventHandler = $derived((fn: EventHandler<DragEvent>) =>
|
|
216
|
-
disableDropzoneDrag ? null : getHandler(fn)
|
|
217
|
-
);
|
|
218
|
-
|
|
219
|
-
let defaultPlaceholderString = $derived(
|
|
220
|
-
dropzoneText ||
|
|
221
|
-
(multiple
|
|
222
|
-
? "Drag 'n' drop some files here, or click to select files"
|
|
223
|
-
: "Drag 'n' drop a file here, or click to select a file")
|
|
224
|
-
);
|
|
225
|
-
|
|
226
|
-
// allow the entire document to be a drag target
|
|
227
|
-
function onWindowDragOver(event: DragEvent) {
|
|
228
|
-
if (preventDropOnDocument) {
|
|
229
|
-
event.preventDefault();
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
function onWindowDrop(event: DragEvent) {
|
|
234
|
-
const target = event.target as HTMLElement;
|
|
235
|
-
if (!preventDropOnDocument) {
|
|
236
|
-
return;
|
|
237
|
-
}
|
|
238
|
-
if (dropzoneRef?.contains(target)) {
|
|
239
|
-
// If we intercepted an event for our instance, let it propagate down to the instance's onDrop handler
|
|
240
|
-
return;
|
|
241
|
-
}
|
|
242
|
-
event.preventDefault();
|
|
243
|
-
dragTargetsRef = [];
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
function onInputElementClick(event: MouseEvent) {
|
|
247
|
-
event.stopPropagation();
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
function onInputElementCancel(event: Event) {
|
|
251
|
-
isFileDialogActive = false;
|
|
252
|
-
onFileDialogCancel?.();
|
|
253
|
-
}
|
|
254
|
-
const dropzoneProps = $derived({
|
|
255
|
-
'data-drozone-element-type': 'dropzone-element',
|
|
256
|
-
id: 'dropzone-element',
|
|
257
|
-
tabindex: 0,
|
|
258
|
-
role: 'button',
|
|
259
|
-
onkeydown: getKeyboardEventHandle(onDropzoneKeyDown),
|
|
260
|
-
onclick: getHandler(onDropzoneClick)
|
|
261
|
-
});
|
|
262
|
-
const dropzoneAreaProps = $derived({
|
|
263
|
-
dragenter: getDragEventHandler(onDropzoneDragEnter),
|
|
264
|
-
dragover: getDragEventHandler(onDropzoneDragOver),
|
|
265
|
-
dragleave: getDragEventHandler(onDropzoneDragLeave),
|
|
266
|
-
drop: getDragEventHandler(onDropzoneDrop)
|
|
267
|
-
});
|
|
268
|
-
|
|
269
|
-
$effect(() => {
|
|
270
|
-
const unsubscribe = useDropzone(dropzoneRef, dropzoneAreaProps);
|
|
271
|
-
return () => unsubscribe();
|
|
272
|
-
});
|
|
273
|
-
</script>
|
|
274
|
-
|
|
275
|
-
<svelte:window on:dragover={onWindowDragOver} on:drop={onWindowDrop} />
|
|
276
|
-
|
|
277
|
-
{#snippet dropzoneInput()}
|
|
278
|
-
<input
|
|
279
|
-
accept={accept?.join(',')}
|
|
280
|
-
{multiple}
|
|
281
|
-
{required}
|
|
282
|
-
type="file"
|
|
283
|
-
{name}
|
|
284
|
-
autocomplete="off"
|
|
285
|
-
tabindex="-1"
|
|
286
|
-
onchange={onDropzoneDrop}
|
|
287
|
-
onclick={onInputElementClick}
|
|
288
|
-
bind:this={inputElement}
|
|
289
|
-
style="display: none;"
|
|
290
|
-
oncancel={onInputElementCancel}
|
|
291
|
-
/>
|
|
292
|
-
{/snippet}
|
|
293
|
-
{#if CustomDropzone}
|
|
294
|
-
{@render CustomDropzone(dropzoneProps)}
|
|
295
|
-
|
|
296
|
-
{@render dropzoneInput()}
|
|
297
|
-
{:else}
|
|
298
|
-
<DefaultDropzone bind:defaultDropzoneElement {...dropzoneProps}>
|
|
299
|
-
{@render dropzoneInput()}
|
|
300
|
-
{#if children}
|
|
301
|
-
{@render children()}
|
|
302
|
-
{:else}
|
|
303
|
-
<p>{defaultPlaceholderString}</p>
|
|
304
|
-
{/if}
|
|
305
|
-
</DefaultDropzone>
|
|
306
|
-
{/if}
|