@functionalcms/svelte-components 4.16.0 → 4.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/dist/components/form/Button.svelte +118 -129
  2. package/dist/components/form/Button.svelte.d.ts +0 -3
  3. package/dist/components/form/ChoiceInput.svelte +37 -80
  4. package/dist/components/form/ChoiceInput.svelte.d.ts +1 -17
  5. package/dist/components/form/Dropzone.svelte +183 -0
  6. package/dist/components/form/Dropzone.svelte.d.ts +4 -0
  7. package/dist/components/form/Form.svelte +43 -95
  8. package/dist/components/form/Form.svelte.d.ts +8 -14
  9. package/dist/components/form/Input.svelte +3 -3
  10. package/dist/components/form/Input.svelte.d.ts +3 -3
  11. package/dist/components/form/Select.svelte +39 -73
  12. package/dist/components/form/Switch.svelte +17 -19
  13. package/dist/components/form/dropzone.d.ts +49 -0
  14. package/dist/components/form/dropzone.js +18 -0
  15. package/dist/components/form/form.d.ts +8 -10
  16. package/dist/components/form/form.js +1 -33
  17. package/dist/components/layouts/Tabs.svelte +3 -3
  18. package/dist/components/layouts/TwoColumnsLayout.svelte +1 -1
  19. package/dist/components/layouts/TwoColumnsLayout.svelte.d.ts +3 -2
  20. package/dist/components/menu/CollapsibleMenu.svelte +4 -1
  21. package/dist/components/presentation/Carousel.svelte +4 -2
  22. package/dist/index-server.d.ts +1 -1
  23. package/dist/index-server.js +1 -1
  24. package/dist/index.d.ts +2 -9
  25. package/dist/index.js +1 -8
  26. package/dist/index.server.d.ts +1 -1
  27. package/dist/index.server.js +1 -1
  28. package/dist/server-side/getRedirectPipeline.d.ts +6 -0
  29. package/dist/server-side/getRedirectPipeline.js +16 -0
  30. package/package.json +82 -86
  31. package/dist/components/form/dropzone/DefaultDropzone.svelte +0 -37
  32. package/dist/components/form/dropzone/DefaultDropzone.svelte.d.ts +0 -8
  33. package/dist/components/form/dropzone/Dropzone.svelte +0 -306
  34. package/dist/components/form/dropzone/Dropzone.svelte.d.ts +0 -4
  35. package/dist/components/form/dropzone/UseDropzone.d.ts +0 -3
  36. package/dist/components/form/dropzone/UseDropzone.js +0 -19
  37. package/dist/components/form/dropzone/attr-accept.d.ts +0 -12
  38. package/dist/components/form/dropzone/attr-accept.js +0 -29
  39. package/dist/components/form/dropzone/default.d.ts +0 -31
  40. package/dist/components/form/dropzone/default.js +0 -78
  41. package/dist/components/form/dropzone/types.d.ts +0 -62
  42. package/dist/components/form/dropzone/types.js +0 -1
  43. package/dist/components/form/utils.d.ts +0 -13
  44. package/dist/components/form/utils.js +0 -1
  45. package/dist/server-side/redirection.d.ts +0 -6
  46. package/dist/server-side/redirection.js +0 -16
  47. package/dist/translations/translator.d.ts +0 -2
  48. package/dist/translations/translator.js +0 -11
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 { ChoiceInputOption } from './components/form/utils.js';
32
+ export type { InputType, FieldType, 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
@@ -43,11 +43,8 @@ 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
45
  export { default as AntiBot } from './components/form/AntiBot.svelte';
46
+ export { default as Dropzone } from './components/form/Dropzone.svelte';
46
47
  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
48
  /*
52
49
  * Content
53
50
  */
@@ -60,7 +57,3 @@ export { listAllPosts, importPost } from './components/blog/blog.js';
60
57
  * Integrations
61
58
  */
62
59
  export { default as EasyTools } from './components/integrations/EasyTools.svelte';
63
- /**
64
- * Translations
65
- */
66
- export { translator, prefixedTranslator } from './translations/translator.js';
@@ -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';
@@ -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,6 @@
1
+ export interface Redirection {
2
+ pathname: string;
3
+ redirectTo: string;
4
+ }
5
+ declare const getRedirectPipeline: (redirections: Array<Redirection>) => ({ event, resolve }: any) => Promise<any>;
6
+ export default getRedirectPipeline;
@@ -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.16.0",
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": "^6.0.1",
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
- "file-selector": "^2.1.2",
57
- "npm-watch": "^0.13.0",
58
- "prettier": "^3.5.3",
59
- "prettier-plugin-svelte": "^3.3.3",
60
- "publint": "^0.3.12",
61
- "sass": "^1.83.4",
62
- "svelte": "^5.28.2",
63
- "svelte-check": "^4.1.7",
64
- "typescript": "^5.8.3",
65
- "typescript-eslint": "^8.31.1",
66
- "vite": "^6.3.4"
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
- "svelte-dropzone-runes": "^1.0.3",
74
- "sveltekit-superforms": "^2.25.0",
75
- "yup": "^1.6.1",
76
- "zod": "^3.25.56"
77
- },
78
- "peerDependencies": {
79
- "@sveltejs/kit": "^2.20.8",
80
- "svelte": "^5.28.2"
81
- },
82
- "type": "module",
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.0",
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}
@@ -1,4 +0,0 @@
1
- import type { DropzoneProps } from './types.js';
2
- declare const Dropzone: import("svelte").Component<DropzoneProps, {}, "inputElement" | "dropzoneElement">;
3
- type Dropzone = ReturnType<typeof Dropzone>;
4
- export default Dropzone;
@@ -1,3 +0,0 @@
1
- import type { DropzoneAreaEvents } from "./types.js";
2
- declare const useDropzone: (element: HTMLElement | undefined, events: DropzoneAreaEvents) => () => void;
3
- export default useDropzone;
@@ -1,19 +0,0 @@
1
- const useDropzone = (element, events) => {
2
- if (!element)
3
- return () => { };
4
- Object.entries(events)
5
- .forEach(([eventName, handler]) => {
6
- if (handler) {
7
- element.addEventListener(eventName, handler);
8
- }
9
- });
10
- return () => {
11
- Object.entries(events)
12
- .forEach(([eventName, handler]) => {
13
- if (handler) {
14
- element.removeEventListener(eventName, handler);
15
- }
16
- });
17
- };
18
- };
19
- export default useDropzone;
@@ -1,12 +0,0 @@
1
- /**
2
- * Check if the provided file type should be accepted by the input with accept attribute.
3
- * https://developer.mozilla.org/en-US/docs/Web/HTML/Element/Input#attr-accept
4
- *
5
- * Inspired by https://github.com/enyo/dropzone
6
- *
7
- * @param file {File} https://developer.mozilla.org/en-US/docs/Web/API/File
8
- * @param accept {string}
9
- * @returns {boolean}
10
- */
11
- import type { FromEventFileTypes, MimeTypes } from "./types.js";
12
- export default function (file: FromEventFileTypes, accept: MimeTypes[] | string[]): boolean;