267 lines
6.8 KiB
TypeScript
267 lines
6.8 KiB
TypeScript
import * as colors from './00colors.js';
|
|
import * as plugins from './00plugins.js';
|
|
|
|
import { DeesContextmenu } from './dees-contextmenu.js';
|
|
|
|
import {
|
|
customElement,
|
|
DeesElement,
|
|
type TemplateResult,
|
|
property,
|
|
html,
|
|
css,
|
|
unsafeCSS,
|
|
cssManager,
|
|
type CSSResult,
|
|
domtools,
|
|
} from '@design.estate/dees-element';
|
|
|
|
declare global {
|
|
interface HTMLElementTagNameMap {
|
|
'dees-input-fileupload': DeesInputFileupload;
|
|
}
|
|
}
|
|
|
|
@customElement('dees-input-fileupload')
|
|
export class DeesInputFileupload extends DeesElement {
|
|
public static demo = () =>
|
|
html`<dees-input-fileupload .label=${'Attachments'}></dees-input-fileupload>`;
|
|
|
|
// INSTANCE
|
|
public changeSubject = new domtools.plugins.smartrx.rxjs.Subject();
|
|
|
|
@property({
|
|
type: String,
|
|
})
|
|
public label: string = null;
|
|
|
|
@property({
|
|
type: String,
|
|
reflect: true,
|
|
})
|
|
public key: string;
|
|
|
|
@property({
|
|
attribute: false,
|
|
})
|
|
public value: File[] = [];
|
|
|
|
@property()
|
|
public state: 'idle' | 'dragOver' | 'dropped' | 'uploading' | 'completed' = 'idle';
|
|
|
|
@property({
|
|
type: Boolean,
|
|
})
|
|
public required: boolean = false;
|
|
|
|
@property({
|
|
type: Boolean,
|
|
})
|
|
public disabled: boolean = false;
|
|
|
|
@property({
|
|
type: String,
|
|
})
|
|
public buttonText: string = 'Upload File...';
|
|
|
|
constructor() {
|
|
super();
|
|
}
|
|
|
|
public static styles = [
|
|
cssManager.defaultStyles,
|
|
css`
|
|
:host {
|
|
position: relative;
|
|
display: grid;
|
|
margin: 10px 0px;
|
|
margin-bottom: 24px;
|
|
color: ${cssManager.bdTheme('#333', '#ccc')};
|
|
}
|
|
|
|
.hidden {
|
|
display: none;
|
|
}
|
|
|
|
.maincontainer {
|
|
position: relative;
|
|
border-radius: 3px;
|
|
padding: 8px;
|
|
background: ${cssManager.bdTheme('#fafafa', '#222222')};
|
|
color: ${cssManager.bdTheme('#333', '#ccc')};
|
|
border-top: 1px solid #ffffff10;
|
|
}
|
|
|
|
.maincontainer::after {
|
|
top: 2px;
|
|
right: 2px;
|
|
left: 2px;
|
|
bottom: 2px;
|
|
transform: scale3d(0.98, 0.9, 1);
|
|
position: absolute;
|
|
content: '';
|
|
display: block;
|
|
border: 2px dashed rgba(255, 255, 255, 0);
|
|
transition: all 0.2s;
|
|
pointer-events: none;
|
|
background: #00000000;
|
|
}
|
|
.maincontainer.dragOver::after {
|
|
transform: scale3d(1, 1, 1);
|
|
border: 2px dashed rgba(255, 255, 255, 0.3);
|
|
background: #00000080;
|
|
}
|
|
|
|
.label {
|
|
font-size: 14px;
|
|
margin-bottom: 8px;
|
|
}
|
|
|
|
.uploadButton {
|
|
position: relative;
|
|
padding: 8px;
|
|
max-width: 600px;
|
|
background: ${cssManager.bdTheme('#fafafa', '#333333')};
|
|
border-radius: 3px;
|
|
text-align: center;
|
|
font-size: 14px;
|
|
cursor: default;
|
|
}
|
|
|
|
.uploadButton:hover {
|
|
color: #fff;
|
|
background: ${unsafeCSS(colors.dark.blue)};
|
|
}
|
|
|
|
.uploadCandidate {
|
|
display: grid;
|
|
grid-template-columns: 48px auto;
|
|
background: #333;
|
|
padding: 8px 8px 8px 0px;
|
|
margin-bottom: 8px;
|
|
text-align: left;
|
|
border-radius: 3px;
|
|
color: ${cssManager.bdTheme('#666', '#ccc')};
|
|
font-family: 'Geist Sans', sans-serif;
|
|
cursor: default;
|
|
transition: all 0.2s;
|
|
border-top: 1px solid #ffffff10;
|
|
}
|
|
|
|
.uploadCandidate:last-child {
|
|
margin-bottom: 8px;
|
|
}
|
|
|
|
.uploadCandidate .icon {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
font-size: 16px;
|
|
}
|
|
|
|
.uploadCandidate:hover {
|
|
background: #393939;
|
|
}
|
|
|
|
.uploadCandidate .description {
|
|
font-size: 14px;
|
|
border-left: 1px solid #ffffff10;
|
|
padding-left: 8px;
|
|
}
|
|
`,
|
|
];
|
|
|
|
public render(): TemplateResult {
|
|
return html`
|
|
<div class="hidden">
|
|
<input type="file"></div>
|
|
</div>
|
|
${this.label ? html`<div class="label">${this.label}</div>` : null}
|
|
<div class="maincontainer ${this.state === 'dragOver' ? 'dragOver' : ''}">
|
|
${this.value.map(
|
|
(fileArg) => html`
|
|
<div class="uploadCandidate" @contextmenu=${eventArg => {
|
|
DeesContextmenu.openContextMenuWithOptions(eventArg, [{
|
|
iconName: 'trash',
|
|
name: 'Remove',
|
|
action: async () => {
|
|
this.value.splice(this.value.indexOf(fileArg), 1);
|
|
this.requestUpdate();
|
|
}
|
|
}]);
|
|
}}>
|
|
<div class="icon">
|
|
<dees-icon .iconFA=${'paperclip'}></dees-icon>
|
|
</div>
|
|
<div class="description">
|
|
<span style="font-weight: 600">${fileArg.name}</span><br />
|
|
<span style="font-weight: 400">${fileArg.size}</span>
|
|
</div>
|
|
</div> `
|
|
)}
|
|
<div class="uploadButton" @click=${
|
|
this.openFileSelector
|
|
}>
|
|
${this.buttonText}
|
|
</div>
|
|
</div>
|
|
`;
|
|
}
|
|
|
|
public async openFileSelector() {
|
|
const inputFile: HTMLInputElement = this.shadowRoot.querySelector('input[type="file"]');
|
|
inputFile.click();
|
|
this.state = 'idle';
|
|
this.buttonText = 'Upload more files...';
|
|
}
|
|
|
|
public async updateValue(eventArg: Event) {
|
|
const target: any = eventArg.target;
|
|
this.value = target.value;
|
|
this.changeSubject.next(this);
|
|
}
|
|
|
|
public firstUpdated() {
|
|
const inputFile: HTMLInputElement = this.shadowRoot.querySelector('input[type="file"]');
|
|
inputFile.addEventListener('change', (event: Event) => {
|
|
const target = event.target as HTMLInputElement;
|
|
for (const file of Array.from(target.files)) {
|
|
this.value.push(file);
|
|
}
|
|
this.requestUpdate();
|
|
console.log(`Got ${this.value.length} files!`);
|
|
// Reset the input value to allow selecting the same file again if needed
|
|
target.value = '';
|
|
});
|
|
|
|
// lets handle drag and drop
|
|
const dropArea = this.shadowRoot.querySelector('.maincontainer');
|
|
const handlerFunction = (eventArg: DragEvent) => {
|
|
eventArg.preventDefault();
|
|
switch (eventArg.type) {
|
|
case 'dragover':
|
|
this.state = 'dragOver';
|
|
this.buttonText = 'release to upload file...';
|
|
break;
|
|
case 'dragleave':
|
|
this.state = 'idle';
|
|
this.buttonText = 'Upload File...';
|
|
break;
|
|
case 'drop':
|
|
this.state = 'idle';
|
|
this.buttonText = 'Upload more files...';
|
|
}
|
|
console.log(eventArg);
|
|
for (const file of Array.from(eventArg.dataTransfer.files)) {
|
|
this.value.push(file);
|
|
this.requestUpdate();
|
|
}
|
|
console.log(`Got ${this.value.length} files!`);
|
|
};
|
|
dropArea.addEventListener('dragenter', handlerFunction, false);
|
|
dropArea.addEventListener('dragleave', handlerFunction, false);
|
|
dropArea.addEventListener('dragover', handlerFunction, false);
|
|
dropArea.addEventListener('drop', handlerFunction, false);
|
|
}
|
|
}
|