@georapbox/files-dropzone-element 2.1.1 → 3.0.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 (49) hide show
  1. package/.editorconfig +15 -0
  2. package/.nvmrc +1 -0
  3. package/.prettierignore +6 -0
  4. package/.prettierrc +11 -0
  5. package/.vscode/extensions.json +8 -0
  6. package/.vscode/settings.json +8 -0
  7. package/.zed/settings.json +9 -0
  8. package/CHANGELOG.md +144 -0
  9. package/README.md +119 -103
  10. package/custom-elements-manifest.config.mjs +48 -0
  11. package/dist/custom-elements.json +509 -0
  12. package/dist/files-dropzone-defined.d.ts +1 -1
  13. package/dist/files-dropzone-defined.d.ts.map +1 -1
  14. package/dist/files-dropzone-defined.js +5 -5
  15. package/dist/files-dropzone-defined.js.map +4 -4
  16. package/dist/files-dropzone.d.ts +55 -68
  17. package/dist/files-dropzone.d.ts.map +1 -1
  18. package/dist/files-dropzone.js +5 -5
  19. package/dist/files-dropzone.js.map +4 -4
  20. package/dist/files-selector.d.ts +9 -0
  21. package/dist/files-selector.d.ts.map +1 -0
  22. package/dist/{utils/is-valid-file.d.ts → is-valid-file.d.ts} +1 -1
  23. package/dist/is-valid-file.d.ts.map +1 -0
  24. package/docs/css/main.css +190 -0
  25. package/docs/css/water.css +674 -0
  26. package/docs/favicon-32x32.png +0 -0
  27. package/docs/index.html +144 -0
  28. package/docs/js/main.js +154 -0
  29. package/docs/lib/files-dropzone.js +93 -0
  30. package/docs/lib/highlight/highlight-github.css +160 -0
  31. package/docs/lib/highlight/highlight.min.js +1160 -0
  32. package/eslint.config.mjs +42 -0
  33. package/package.json +52 -30
  34. package/scripts/build.mjs +32 -0
  35. package/scripts/copy-build-to-docs.mjs +17 -0
  36. package/scripts/dev.mjs +24 -0
  37. package/src/files-dropzone-defined.js +1 -1
  38. package/src/files-dropzone.js +70 -89
  39. package/test/files-dropzone-upgrade.test.js +39 -0
  40. package/test/files-dropzone.test.js +397 -0
  41. package/test/files-selector.test.js +96 -0
  42. package/test/is-valid-file.test.js +78 -0
  43. package/tsconfig.json +15 -0
  44. package/web-test-runner.config.js +13 -0
  45. package/dist/utils/files-selector.d.ts +0 -2
  46. package/dist/utils/files-selector.d.ts.map +0 -1
  47. package/dist/utils/is-valid-file.d.ts.map +0 -1
  48. /package/src/{utils/files-selector.js → files-selector.js} +0 -0
  49. /package/src/{utils/is-valid-file.js → is-valid-file.js} +0 -0
@@ -0,0 +1,144 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta http-equiv="X-UA-Compatible" content="IE=edge">
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
7
+ <meta name="color-scheme" content="light dark">
8
+ <title>&lt;files-dropzone&gt;</title>
9
+ <meta name="description" content="A custom element that creates a drag and drop zone for files">
10
+ <link rel="icon" type="image/png" sizes="32x32" href="favicon-32x32.png">
11
+ <link rel="stylesheet" href="lib/highlight/highlight-github.css">
12
+ <link rel="stylesheet" href="css/water.css">
13
+ <link rel="stylesheet" href="css/main.css">
14
+ <script src="lib/highlight/highlight.min.js" defer></script>
15
+ <script type="module" src="js/main.js"></script>
16
+ </head>
17
+ <body class="no-js">
18
+ <script>document.body.classList.remove('no-js');</script>
19
+
20
+ <main class="container">
21
+ <noscript>
22
+ <div class="noscript-banner">This demo requires JavaScript to work.</div>
23
+ </noscript>
24
+
25
+ <h1>&lt;files-dropzone&gt;</h1>
26
+
27
+ <div class="component-description">
28
+ <p>A custom element that creates a drag and drop zone for files.</p>
29
+ <p><a href="https://github.com/georapbox/files-dropzone-element" target="_blank" rel="noreferrer noopener">Source code &amp; documentation</a></p>
30
+ </div>
31
+
32
+ <h2 data-hide="no-js">Demo</h2>
33
+
34
+ <p data-hide="no-js">
35
+ <small><em>This is just a demo dropzone. Dropped files are not uploaded anywhere.</em></small>
36
+ </p>
37
+
38
+ <div class="dropzone-container" data-hide="no-js">
39
+ <files-dropzone></files-dropzone>
40
+ </div>
41
+
42
+ <details data-hide="no-js" open>
43
+ <summary>Dropped files</summary>
44
+
45
+ <p class="console-info">
46
+ <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor" class="bi bi-info-lg" viewBox="0 0 16 16">
47
+ <path d="m9.708 6.075-3.024.379-.108.502.595.108c.387.093.464.232.38.619l-.975 4.577c-.255 1.183.14 1.74 1.067 1.74.72 0 1.554-.332 1.933-.789l.116-.549c-.263.232-.65.325-.905.325-.363 0-.494-.255-.402-.704l1.323-6.208Zm.091-2.755a1.32 1.32 0 1 1-2.64 0 1.32 1.32 0 0 1 2.64 0Z"/>
48
+ </svg>
49
+ <em>Open the browser's console to watch emitted events with more info of the dropped files.</em>
50
+ </p>
51
+
52
+ <div class="dropped-files" id="droppedFiles"></div>
53
+ </details>
54
+
55
+ <details data-hide="no-js" open>
56
+ <summary>Customize component</summary>
57
+
58
+ <pre><code class="code-preview" id="codePreview"></code></pre>
59
+
60
+ <form autocomplete="off">
61
+ <fieldset>
62
+ <legend>Attributes</legend>
63
+
64
+ <div class="form-row">
65
+ <div class="form-col">
66
+ <label for="accept">accept</label>
67
+ <input type="text" id="accept" name="accept" list="acceptDatalist" placeholder="eg. image/*,.txt,application/pdf" data-attr>
68
+
69
+ <datalist id="acceptDatalist">
70
+ <option value="application/*"></option>
71
+ <option value="text/*"></option>
72
+ <option value="image/*"></option>
73
+ <option value="audio/*"></option>
74
+ <option value="video/*"></option>
75
+ <option value=".txt"></option>
76
+ <option value=".png"></option>
77
+ <option value=".jpg"></option>
78
+ <option value=".mp3"></option>
79
+ <option value=".mp4"></option>
80
+ <option value=".pdf"></option>
81
+ <option value=".html"></option>
82
+ <option value=".css"></option>
83
+ </datalist>
84
+ </div>
85
+
86
+ <div class="form-col">
87
+ <label for="max-files">max-files</label>
88
+ <input type="number" id="max-files" name="max-files" min="1" step="1" data-attr>
89
+ </div>
90
+ </div>
91
+
92
+ <div class="form-row">
93
+ <div class="form-col">
94
+ <label for="max-size">max-size (bytes)</label>
95
+ <input type="number" id="max-size" name="max-size" min="0" step="1024" data-attr>
96
+ </div>
97
+
98
+ <div class="form-col">
99
+ <label for="min-size">min-size (bytes)</label>
100
+ <input type="number" id="min-size" name="min-size" min="0" step="1024" data-attr>
101
+ </div>
102
+ </div>
103
+
104
+ <div class="form-row" style="gap: 1rem;">
105
+ <div>
106
+ <input type="checkbox" id="disabled" name="disabled" data-attr>
107
+ <label for="disabled">disabled</label>
108
+ </div>
109
+
110
+ <div>
111
+ <input type="checkbox" id="multiple" name="multiple" data-attr>
112
+ <label for="multiple">multiple</label>
113
+ </div>
114
+
115
+ <div>
116
+ <input type="checkbox" id="no-style" name="no-style" data-attr>
117
+ <label for="no-style">no-style</label>
118
+ </div>
119
+ </div>
120
+ </fieldset>
121
+
122
+ <fieldset>
123
+ <legend>Slots</legend>
124
+
125
+ <div class="form-row">
126
+ <div class="form-col">
127
+ <label for="slot">Default slot</label>
128
+ <input type="text" id="slot" name="slot" data-slot="default">
129
+ <p style="margin: 0;"><small><em>For the demo purposes, the slot is plain text. However, in reality you can use any valid HTML.</em></small></p>
130
+ </div>
131
+ </div>
132
+ </fieldset>
133
+ </form>
134
+
135
+ <button type="button" id="openFileDialogBtn" class="open-file-dialog-btn">
136
+ Open file dialog programmatically
137
+ </button>
138
+ </details>
139
+
140
+ <h2>License</h2>
141
+ <p>Licensed under the <a href="https://github.com/georapbox/files-dropzone-element/blob/main/LICENSE" target="_blank" rel="noreferrer noopener">The MIT License (MIT)</a></p>
142
+ </main>
143
+ </body>
144
+ </html>
@@ -0,0 +1,154 @@
1
+ const url = window.location.href;
2
+ const isLocalhost = url.includes('127.0.0.1') || url.includes('localhost');
3
+ const componentUrl = isLocalhost ? '../../dist/files-dropzone.js' : '../lib/files-dropzone.js';
4
+
5
+ try {
6
+ const { FilesDropzone } = await import(componentUrl);
7
+ FilesDropzone.define();
8
+ } catch (err) {
9
+ console.error(err);
10
+ }
11
+
12
+ const droppedFilesList = document.getElementById('droppedFiles');
13
+ const codePreview = document.getElementById('codePreview');
14
+ const form = document.querySelector('form');
15
+ const dropzone = document.querySelector('files-dropzone');
16
+ const openFileDialogBtn = document.getElementById('openFileDialogBtn');
17
+
18
+ codePreview.textContent = '<files-dropzone></files-dropzone>';
19
+
20
+ window.hljs.highlightElement(codePreview);
21
+
22
+ function createCodePreview(dropzone) {
23
+ return dropzone.outerHTML.replace(/=""/g, '');
24
+ }
25
+
26
+ function createFilesList(files, status) {
27
+ if (!files.length) {
28
+ return;
29
+ }
30
+
31
+ const INITIAL_FILES_COUNT = 50;
32
+
33
+ const container = document.createElement('div');
34
+
35
+ const title = Object.assign(document.createElement('h3'), {
36
+ className: 'dropped-files__title',
37
+ textContent: `${status === 'accepted' ? 'Accepted' : 'Rejected'} files (${files.length})`
38
+ });
39
+
40
+ const list = Object.assign(document.createElement('ul'), {
41
+ className: 'dropped-files__list'
42
+ });
43
+
44
+ files.forEach((item, index) => {
45
+ const file = status === 'accepted' ? item : item.file;
46
+
47
+ const listItem = Object.assign(document.createElement('li'), {
48
+ className: `dropped-files__list-item dropped-files__list-item--${status}`,
49
+ hidden: index >= INITIAL_FILES_COUNT
50
+ });
51
+
52
+ const fileInfo = document.createElement('div');
53
+ fileInfo.append(document.createTextNode(file.name));
54
+
55
+ const fileSize = document.createElement('span');
56
+ fileSize.className = 'dropped-files__file-size';
57
+ fileSize.textContent = ` - ${file.size} bytes`;
58
+
59
+ fileInfo.appendChild(fileSize);
60
+ listItem.appendChild(fileInfo);
61
+
62
+ if (status === 'rejected') {
63
+ const errorsList = document.createElement('ul');
64
+ errorsList.className = 'dropped-files__errors';
65
+
66
+ item.errors.forEach(({ message }) => {
67
+ const errorItem = document.createElement('li');
68
+ errorItem.textContent = message;
69
+ errorsList.appendChild(errorItem);
70
+ });
71
+
72
+ listItem.appendChild(errorsList);
73
+ }
74
+
75
+ list.appendChild(listItem);
76
+ });
77
+
78
+ const showAllBtn = Object.assign(document.createElement('button'), {
79
+ type: 'button',
80
+ className: 'dropped-files__show-all',
81
+ textContent: 'Show all'
82
+ });
83
+
84
+ container.appendChild(title);
85
+ container.appendChild(list);
86
+
87
+ if (files.length > INITIAL_FILES_COUNT) {
88
+ container.appendChild(showAllBtn);
89
+ }
90
+
91
+ return container;
92
+ }
93
+
94
+ droppedFilesList.addEventListener('click', evt => {
95
+ const target = evt.target;
96
+
97
+ if (target.matches('.dropped-files__show-all')) {
98
+ target.previousElementSibling.querySelectorAll('li').forEach(item => (item.hidden = false));
99
+ target.remove();
100
+ }
101
+ });
102
+
103
+ form.addEventListener('input', evt => {
104
+ const target = evt.target;
105
+ const { name, value } = target;
106
+
107
+ if (target.hasAttribute('data-slot')) {
108
+ dropzone.textContent = value;
109
+ }
110
+
111
+ if (target.hasAttribute('data-attr')) {
112
+ switch (target.type) {
113
+ case 'checkbox':
114
+ target.checked ? dropzone.setAttribute(name, '') : dropzone.removeAttribute(name);
115
+ break;
116
+ default:
117
+ value ? dropzone.setAttribute(name, value) : dropzone.removeAttribute(name);
118
+ }
119
+ }
120
+
121
+ codePreview.textContent = createCodePreview(dropzone);
122
+
123
+ window.hljs.highlightElement(codePreview);
124
+ });
125
+
126
+ document.addEventListener('dropzone-drop', evt => {
127
+ console.log('dropzone-drop ->', evt.detail);
128
+
129
+ const { acceptedFiles, rejectedFiles } = evt.detail;
130
+ const acceptedFilesList = createFilesList(acceptedFiles, 'accepted');
131
+ const rejectedFilesList = createFilesList(rejectedFiles, 'rejected');
132
+
133
+ droppedFilesList.replaceChildren();
134
+
135
+ if (acceptedFilesList) {
136
+ droppedFilesList.appendChild(acceptedFilesList);
137
+ }
138
+
139
+ if (rejectedFilesList) {
140
+ droppedFilesList.appendChild(rejectedFilesList);
141
+ }
142
+ });
143
+
144
+ document.addEventListener('dropzone-error', evt => {
145
+ console.log('dropzone-error ->', evt.detail.error);
146
+ });
147
+
148
+ openFileDialogBtn.addEventListener('click', () => {
149
+ dropzone.openFileDialog();
150
+
151
+ if (dropzone.hasAttribute('disabled')) {
152
+ alert('Dropzone is disabled. File dialog will not open programmatically.');
153
+ }
154
+ });
@@ -0,0 +1,93 @@
1
+ /*!
2
+ * @georapbox/files-dropzone-element
3
+ * A custom element that creates a drag and drop zone for files
4
+ *
5
+ * @version 3.0.0
6
+ * @homepage https://github.com/georapbox/files-dropzone-element#readme
7
+ * @author George Raptis <georapbox@gmail.com>
8
+ * @license MIT
9
+ */
10
+ function c(o,e=""){if(!e)return!0;let t=[...new Set(e.split(",").map(r=>r.trim()).filter(Boolean))],i=o.type,s=i.replace(/\/.*$/,"");for(let r of t)if(r.charAt(0)==="."){if(o.name.toLowerCase().indexOf(r.toLowerCase(),o.name.length-r.length)!==-1)return!0}else if(/\/\*$/.test(r)){if(s===r.replace(/\/.*$/,""))return!0}else if(i===r)return!0;return!1}var v=new Map([["aac","audio/aac"],["abw","application/x-abiword"],["arc","application/x-freearc"],["avif","image/avif"],["avi","video/x-msvideo"],["azw","application/vnd.amazon.ebook"],["bin","application/octet-stream"],["bmp","image/bmp"],["bz","application/x-bzip"],["bz2","application/x-bzip2"],["cda","application/x-cdf"],["csh","application/x-csh"],["css","text/css"],["csv","text/csv"],["doc","application/msword"],["docx","application/vnd.openxmlformats-officedocument.wordprocessingml.document"],["eot","application/vnd.ms-fontobject"],["epub","application/epub+zip"],["gz","application/gzip"],["gif","image/gif"],["heic","image/heic"],["heif","image/heif"],["htm","text/html"],["html","text/html"],["ico","image/vnd.microsoft.icon"],["ics","text/calendar"],["jar","application/java-archive"],["jpeg","image/jpeg"],["jpg","image/jpeg"],["jxl","image/jxl"],["js","text/javascript"],["json","application/json"],["jsonld","application/ld+json"],["markdown","text/markdown"],["md","text/markdown"],["mid","audio/midi"],["midi","audio/midi"],["mjs","text/javascript"],["mp3","audio/mpeg"],["mp4","video/mp4"],["mpeg","video/mpeg"],["mpkg","application/vnd.apple.installer+xml"],["odp","application/vnd.oasis.opendocument.presentation"],["ods","application/vnd.oasis.opendocument.spreadsheet"],["odt","application/vnd.oasis.opendocument.text"],["oga","audio/ogg"],["ogv","video/ogg"],["ogx","application/ogg"],["opus","audio/opus"],["otf","font/otf"],["png","image/png"],["pdf","application/pdf"],["php","application/x-httpd-php"],["ppt","application/vnd.ms-powerpoint"],["pptx","application/vnd.openxmlformats-officedocument.presentationml.presentation"],["rar","application/vnd.rar"],["rtf","application/rtf"],["sh","application/x-sh"],["svg","image/svg+xml"],["swf","application/x-shockwave-flash"],["tar","application/x-tar"],["tif","image/tiff"],["tiff","image/tiff"],["ts","video/mp2t"],["ttf","font/ttf"],["txt","text/plain"],["vsd","application/vnd.visio"],["wav","audio/wav"],["weba","audio/webm"],["webm","video/webm"],["webp","image/webp"],["woff","font/woff"],["woff2","font/woff2"],["xhtml","application/xhtml+xml"],["xls","application/vnd.ms-excel"],["xlsx","application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"],["xml","application/xml"],["xul","application/vnd.mozilla.xul+xml"],["zip","application/zip"],["7z","application/x-7z-compressed"],["mkv","video/x-matroska"],["mov","video/quicktime"],["msg","application/vnd.ms-outlook"]]),f=[".DS_Store","Thumbs.db"],E=o=>{let{name:e}=o;if(e&&e.lastIndexOf(".")!==-1&&!o.type){let i=(e.split(".").pop()||"").toLowerCase(),s=v.get(i);s&&Object.defineProperty(o,"type",{value:s,writable:!1,configurable:!1,enumerable:!0})}return o},m=(o,e)=>{let t=E(o);if(typeof t.path!="string"){let{webkitRelativePath:i}=o;Object.defineProperty(t,"path",{value:typeof e=="string"?e:i||o.name,writable:!1,configurable:!1,enumerable:!0})}return t},h=async o=>await new Promise((e,t)=>{o.readEntries(e,t)}),z=async o=>{let e=[],t=await h(o);for(;t.length>0;)e.push(...t),t=await h(o);return e},x=o=>new Promise((e,t)=>{o.file(i=>e(m(i,o.fullPath)),t)}),y=async o=>{let e=[],t=[];for(let i of o){if(i.kind!=="file")continue;let s=i.getAsEntry?i.getAsEntry():i.webkitGetAsEntry();t.push(s)}for(;t.length>0;){let i=t.shift();if(i)if(i.isFile){let s=await x(i);f.indexOf(s.name)===-1&&e.push(s)}else i.isDirectory&&t.push(...await z(i.createReader()));else continue}return e},u=async o=>{let e=[];for(let t of o)f.indexOf(t.name)===-1&&e.push(m(t));return e},a=async o=>o.dataTransfer?o.dataTransfer.items?await y(o.dataTransfer.items):await u(o.dataTransfer.files):await u(o.target.files);var w=String.raw,O=String.raw,b=document.createElement("template"),L=w`
11
+ *,
12
+ *::before,
13
+ *::after {
14
+ box-sizing: border-box;
15
+ }
16
+
17
+ :host([hidden]),
18
+ [hidden] {
19
+ display: none !important;
20
+ }
21
+
22
+ :host {
23
+ --dropzone-border-width: 2px;
24
+ --dropzone-border-style: dashed;
25
+ --dropzone-border-radius: 0.25rem;
26
+ --dropzone-border-color: #6c757d;
27
+ --dropzone-border-color-dragover: #0d6efd;
28
+ --dropzone-border-color-hover: var(--dropzone-border-color-dragover);
29
+ --dropzone-background-color: #ffffff;
30
+ --dropzone-background-color-dragover: #f4f4f5;
31
+ --dropzone-background-color-hover: var(--dropzone-background-color-dragover);
32
+ --dropzone-body-color: #3f3f46;
33
+ --dropzone-body-color-dragover: var(--dropzone-body-color);
34
+ --dropzone-body-color-hover: var(--dropzone-body-color-dragover);
35
+ --dropzone-focus-shadow-rgb: 49, 132, 253;
36
+ --dropzone-focus-box-shadow: 0 0 0 0.25rem rgba(var(--dropzone-focus-shadow-rgb), 0.5);
37
+ --transition-duration: 0.2s; /* for backwards compatibility */
38
+ --dropzone-transition-duration: var(--transition-duration);
39
+
40
+ display: block;
41
+ }
42
+
43
+ :host(:not([no-style])) .dropzone {
44
+ border: var(--dropzone-border-width) var(--dropzone-border-style) var(--dropzone-border-color);
45
+ border-radius: var(--dropzone-border-radius);
46
+ padding: 3rem 1rem;
47
+ overflow: hidden;
48
+ background-color: var(--dropzone-background-color);
49
+ color: var(--dropzone-body-color);
50
+ text-align: center;
51
+ cursor: pointer;
52
+ transition:
53
+ border var(--dropzone-transition-duration) ease-in-out,
54
+ background-color var(--dropzone-transition-duration) ease-in-out,
55
+ color var(--dropzone-transition-duration) ease-in-out,
56
+ box-shadow var(--dropzone-transition-duration) ease-in-out;
57
+ }
58
+
59
+ :host(:not([no-style])[disabled]) .dropzone {
60
+ opacity: 0.8;
61
+ cursor: not-allowed;
62
+ user-select: none;
63
+ }
64
+
65
+ :host(:not([no-style]):not([disabled])) .dropzone--dragover {
66
+ border-color: var(--dropzone-border-color-dragover);
67
+ background-color: var(--dropzone-background-color-dragover);
68
+ color: var(--dropzone-body-color-dragover);
69
+ }
70
+
71
+ :host(:not([no-style]):not([disabled])) .dropzone:focus-visible {
72
+ outline: none;
73
+ box-shadow: var(--dropzone-focus-box-shadow);
74
+ }
75
+
76
+ @media (hover: hover) {
77
+ :host(:not([no-style]):not([disabled])) .dropzone:not(.dropzone--dragover):hover {
78
+ border-color: var(--dropzone-border-color-hover);
79
+ background-color: var(--dropzone-background-color-hover);
80
+ color: var(--dropzone-body-color-hover);
81
+ }
82
+ }
83
+ `;b.innerHTML=O`
84
+ <style>
85
+ ${L}
86
+ </style>
87
+
88
+ <input type="file" id="file-input" hidden />
89
+
90
+ <div part="dropzone" class="dropzone" id="dropzone" tabindex="0" role="button" aria-disabled="false">
91
+ <slot><span>Drag 'n' drop files here, or click to select files</span></slot>
92
+ </div>
93
+ `;var g=class o extends HTMLElement{static ERROR_CODES={FILE_DIALOG_OPEN_FAILED:"FILE_DIALOG_OPEN_FAILED",FILE_INPUT_CHANGE_FAILED:"FILE_INPUT_CHANGE_FAILED",DROP_EVENT_PROCESSING_FAILED:"DROP_EVENT_PROCESSING_FAILED",UNKNOWN_ERROR:"UNKNOWN_ERROR"};static REJECTION_CODES={TOO_MANY_FILES:"TOO_MANY_FILES",FILE_TOO_LARGE:"FILE_TOO_LARGE",FILE_TOO_SMALL:"FILE_TOO_SMALL",INVALID_MIME_TYPE:"INVALID_MIME_TYPE"};#t=null;#e=null;constructor(){super(),this.shadowRoot||this.attachShadow({mode:"open",delegatesFocus:!0}).appendChild(b.content.cloneNode(!0)),this.shadowRoot&&(this.#t=this.shadowRoot.getElementById("file-input"),this.#e=this.shadowRoot.getElementById("dropzone"))}static get observedAttributes(){return["accept","disabled","multiple"]}attributeChangedCallback(e,t,i){e==="accept"&&t!==i&&this.#t&&(this.#t.accept=this.accept),e==="disabled"&&t!==i&&this.#t&&(this.#t.disabled=this.disabled,this.disabled?(this.#e?.removeAttribute("tabindex"),this.#e?.setAttribute("aria-disabled","true")):(this.#e?.setAttribute("tabindex","0"),this.#e?.setAttribute("aria-disabled","false"))),e==="multiple"&&t!==i&&this.#t&&(this.#t.multiple=this.multiple)}connectedCallback(){this.#i("accept"),this.#i("disabled"),this.#i("maxFiles"),this.#i("maxSize"),this.#i("minSize"),this.#i("multiple"),this.#i("autoFocus"),this.#i("noStyle"),this.#t?.addEventListener("change",this.#r),this.#e?.addEventListener("dragenter",this.#s),this.#e?.addEventListener("dragover",this.#n),this.#e?.addEventListener("dragleave",this.#a),this.#e?.addEventListener("drop",this.#d),this.#e?.addEventListener("click",this.#l),this.#e?.addEventListener("keyup",this.#p),this.autoFocus&&this.#e?.focus()}disconnectedCallback(){this.#t?.removeEventListener("change",this.#r),this.#e?.removeEventListener("dragenter",this.#s),this.#e?.removeEventListener("dragover",this.#n),this.#e?.removeEventListener("dragleave",this.#a),this.#e?.removeEventListener("drop",this.#d),this.#e?.removeEventListener("click",this.#l),this.#e?.removeEventListener("keyup",this.#p)}get accept(){return this.getAttribute("accept")||""}set accept(e){this.setAttribute("accept",e!=null?e.toString():e)}get disabled(){return this.hasAttribute("disabled")}set disabled(e){this.toggleAttribute("disabled",!!e)}get maxFiles(){let e=Number(this.getAttribute("max-files"))||0;return e<=0?1/0:Math.floor(Math.abs(e))}set maxFiles(e){this.setAttribute("max-files",e!=null?e.toString():e)}get maxSize(){let e=this.getAttribute("max-size");if(e===null)return 1/0;let t=Number(e);return Number.isNaN(t)?1/0:t}set maxSize(e){this.setAttribute("max-size",e!=null?e.toString():e)}get minSize(){let e=this.getAttribute("min-size");if(e===null)return 0;let t=Number(e);return Number.isNaN(t)?0:t}set minSize(e){this.setAttribute("min-size",e!=null?e.toString():e)}get multiple(){return this.hasAttribute("multiple")}set multiple(e){this.toggleAttribute("multiple",!!e)}get autoFocus(){return this.hasAttribute("auto-focus")}set autoFocus(e){this.toggleAttribute("auto-focus",!!e)}get noStyle(){return this.hasAttribute("no-style")}set noStyle(e){this.toggleAttribute("no-style",!!e)}#o(e,t,{cancelable:i=!1}={}){let s={bubbles:!0,composed:!0,cancelable:i},r=t===void 0?new Event(e,s):new CustomEvent(e,{...s,detail:t});return this.dispatchEvent(r)}#r=async e=>{try{this.#c(await a(e))}catch(t){this.#o("dropzone-error",{code:o.ERROR_CODES.FILE_INPUT_CHANGE_FAILED,error:t})}};#s=()=>{this.disabled||this.#o("dropzone-dragenter")};#n=e=>{if(e.preventDefault(),this.disabled){e.dataTransfer.dropEffect="none";return}e.dataTransfer.dropEffect="copy",this.#e&&(this.#e.classList.add("dropzone--dragover"),this.#e.part.add("dropzone--dragover")),this.#o("dropzone-dragover")};#a=()=>{this.disabled||(this.#e&&(this.#e.classList.remove("dropzone--dragover"),this.#e.part.remove("dropzone--dragover")),this.#o("dropzone-dragleave"))};#d=async e=>{if(!this.disabled){e.preventDefault(),this.#e&&(this.#e.classList.remove("dropzone--dragover"),this.#e.part.remove("dropzone--dragover"));try{this.#c(await a(e))}catch(t){this.#o("dropzone-error",{code:o.ERROR_CODES.DROP_EVENT_PROCESSING_FAILED,error:t})}}};#l=()=>{this.disabled||this.openFileDialog()};#p=e=>{this.disabled||(e.key===" "||e.key==="Enter")&&this.openFileDialog()};#c(e){if(!Array.isArray(e)||!e.length)return;let t=[],i=[],s=e.length;if(!this.multiple&&s>1)for(let r of e)i.push({file:r,errors:[{code:o.REJECTION_CODES.TOO_MANY_FILES,message:"Too many files selected. Only 1 file is allowed."}]});else if(this.multiple&&s>this.maxFiles)for(let r of e)i.push({file:r,errors:[{code:o.REJECTION_CODES.TOO_MANY_FILES,message:`Too many files selected. Only ${this.maxFiles} ${this.maxFiles>1?"files are":"file is"} allowed.`}]});else for(let r of e){let d=c(r,this.accept),l=r.size>this.maxSize,p=r.size<this.minSize;if(d&&!l&&!p)t.push(r);else{let n=[];d||n.push({code:o.REJECTION_CODES.INVALID_MIME_TYPE,message:`File type "${r.type}" is not accepted.`}),l&&n.push({code:o.REJECTION_CODES.FILE_TOO_LARGE,message:`File size ${r.size} exceeds the maximum size of ${this.maxSize}.`}),p&&n.push({code:o.REJECTION_CODES.FILE_TOO_SMALL,message:`File size ${r.size} is smaller than the minimum size of ${this.minSize}.`}),i.push({file:r,errors:n})}}this.#o("dropzone-drop",{acceptedFiles:t,rejectedFiles:i}),t.length>0&&this.#o("dropzone-drop-accepted",{acceptedFiles:t}),i.length>0&&this.#o("dropzone-drop-rejected",{rejectedFiles:i}),this.#t&&(this.#t.value=this.#t.defaultValue)}openFileDialog(){if(!(this.disabled||!this.#t)){if("showPicker"in HTMLInputElement.prototype&&typeof this.#t.showPicker=="function"){try{this.#t.showPicker()}catch(e){this.#o("dropzone-error",{code:o.ERROR_CODES.FILE_DIALOG_OPEN_FAILED,error:e})}return}this.#t.click()}}#i(e){let t=this;if(Object.hasOwn(t,e)){let i=t[e];delete t[e],t[e]=i}}static define(e="files-dropzone"){typeof window>"u"||window.customElements.get(e)||window.customElements.define(e,o)}};export{g as FilesDropzone};
@@ -0,0 +1,160 @@
1
+ pre code.hljs {
2
+ display: block;
3
+ overflow-x: auto;
4
+ padding: 1em;
5
+ }
6
+
7
+ code.hljs {
8
+ padding: 3px 5px;
9
+ }
10
+
11
+ :root {
12
+ --italic: italic;
13
+ --bold: 700;
14
+ }
15
+
16
+ /*!
17
+ * Theme: GitHub
18
+ * Description: Light theme as seen on github.com
19
+ * Author: github.com
20
+ * Maintainer: @Hirse
21
+ * Updated: 2021-05-15
22
+ *
23
+ * Outdated base version: https://github.com/primer/github-syntax-light
24
+ * Current colors taken from GitHub's CSS
25
+ */
26
+ :root {
27
+ --text-color: #24292e;
28
+ --background-color: #ffffff;
29
+ --keyword-color: #d73a49;
30
+ --title-color: #6f42c1;
31
+ --syntax-color: #005cc5;
32
+ --string-color: #032f62;
33
+ --built-in-color: #e36209;
34
+ --code-color: #6a737d;
35
+ --name-color: #22863a;
36
+ --subst-color: #24292e;
37
+ --section-color: #005cc5;
38
+ --bullet-color: #735c0f;
39
+ --emphasis-color: #24292e;
40
+ --strong-color: #24292e;
41
+ --addition-color: #22863a;
42
+ --deletion-color: #b31d28;
43
+ --addition-background: #f0fff4;
44
+ --deletion-background: #ffeef0;
45
+ }
46
+
47
+ @media (prefers-color-scheme: dark) {
48
+ :root {
49
+ --text-color: #c9d1d9;
50
+ --background-color: #0d1117;
51
+ --keyword-color: #ff7b72;
52
+ --title-color: #d2a8ff;
53
+ --syntax-color: #79c0ff;
54
+ --string-color: #a5d6ff;
55
+ --built-in-color: #ffa657;
56
+ --code-color: #8b949e;
57
+ --name-color: #7ee787;
58
+ --subst-color: #c9d1d9;
59
+ --section-color: #1f6feb;
60
+ --bullet-color: #f2cc60;
61
+ --emphasis-color: #c9d1d9;
62
+ --strong-color: #c9d1d9;
63
+ --addition-color: #aff5b4;
64
+ --deletion-color: #ffdcd7;
65
+ --addition-background: #033a16;
66
+ --deletion-background: #67060c;
67
+ }
68
+ }
69
+
70
+ .hljs {
71
+ color: var(--text-color);
72
+ background: var(--background-color);
73
+ }
74
+
75
+ .hljs-doctag,
76
+ .hljs-keyword,
77
+ .hljs-meta .hljs-keyword,
78
+ .hljs-template-tag,
79
+ .hljs-template-variable,
80
+ .hljs-type,
81
+ .hljs-variable.language_ {
82
+ color: var(--keyword-color);
83
+ }
84
+
85
+ .hljs-title,
86
+ .hljs-title.class_,
87
+ .hljs-title.class_.inherited__,
88
+ .hljs-title.function_ {
89
+ color: var(--title-color);
90
+ }
91
+
92
+ .hljs-attr,
93
+ .hljs-attribute,
94
+ .hljs-literal,
95
+ .hljs-meta,
96
+ .hljs-number,
97
+ .hljs-operator,
98
+ .hljs-selector-attr,
99
+ .hljs-selector-class,
100
+ .hljs-selector-id,
101
+ .hljs-variable {
102
+ color: var(--syntax-color);
103
+ }
104
+
105
+ .hljs-meta .hljs-string,
106
+ .hljs-regexp,
107
+ .hljs-string {
108
+ color: var(--string-color);
109
+ }
110
+
111
+ .hljs-built_in,
112
+ .hljs-symbol {
113
+ color: var(--built-in-color);
114
+ }
115
+
116
+ .hljs-code,
117
+ .hljs-comment,
118
+ .hljs-formula {
119
+ color: var(--code-color);
120
+ }
121
+
122
+ .hljs-name,
123
+ .hljs-quote,
124
+ .hljs-selector-pseudo,
125
+ .hljs-selector-tag {
126
+ color: var(--name-color);
127
+ }
128
+
129
+ .hljs-subst {
130
+ color: var(--subst-color);
131
+ }
132
+
133
+ .hljs-section {
134
+ color: var(--section-color);
135
+ font-weight: var(--bold);
136
+ }
137
+
138
+ .hljs-bullet {
139
+ color: var(--bullet-color);
140
+ }
141
+
142
+ .hljs-emphasis {
143
+ color: var(--emphasis-color);
144
+ font-style: var(--italic);
145
+ }
146
+
147
+ .hljs-strong {
148
+ color: var(--strong-color);
149
+ font-weight: var(--bold);
150
+ }
151
+
152
+ .hljs-addition {
153
+ color: var(--addition-color);
154
+ background-color: var(--addition-background);
155
+ }
156
+
157
+ .hljs-deletion {
158
+ color: var(--deletion-color);
159
+ background-color: var(--deletion-background);
160
+ }