Skip to content

Commit

Permalink
feat(limel-file): add component
Browse files Browse the repository at this point in the history
fix #303
  • Loading branch information
BregenzerK committed Mar 5, 2019
1 parent 6290099 commit 95da842
Show file tree
Hide file tree
Showing 3 changed files with 194 additions and 0 deletions.
13 changes: 13 additions & 0 deletions src/components/file/file.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
---
name: File
route: /file
menu: Components
---

# File

<limel-props name="limel-file" />

## Example

<limel-example name="limel-example-file" />
142 changes: 142 additions & 0 deletions src/components/file/file.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
import { MDCTextField } from '@lime-material/textfield';
import { Component, Element, Event, EventEmitter, Prop } from '@stencil/core';
import { createRandomString } from '../../util/random-string';
import { Chip } from '../chip-set/chip';

const CHIP_SET_TAG_NAME = 'limel-chip-set';
const DEFAULT_FILE_CHIP: Chip = {
id: null,
text: null,
removable: true,
icon: 'note',
iconColor: 'var(--lime-light-grey)',
};

@Component({
tag: 'limel-file',
shadow: true,
})
export class File {
@Prop()
public value: Chip;

@Prop({ reflectToAttr: true })
public label: string;

@Prop({ reflectToAttr: true })
public required: boolean = false;

/**
* True if the input should be disabled
*/
@Prop({ reflectToAttr: true })
public disabled: boolean = false;

/**
* Dispatched when a file is selected/deselected
*/
@Event()
private change: EventEmitter;

@Element()
private element: HTMLElement;

private fileInput: HTMLInputElement;
private fileInputId = createRandomString();
private chipSet;
private mdcTextField;

constructor() {
this.handleFileSelection = this.handleFileSelection.bind(this);
this.handleFileChange = this.handleFileChange.bind(this);
this.handleChipSetChange = this.handleChipSetChange.bind(this);
this.handleFileDrop = this.handleFileDrop.bind(this);
}

public componentDidLoad() {
this.fileInput = this.element.shadowRoot.getElementById(
this.fileInputId
) as HTMLInputElement;
this.chipSet = this.element.shadowRoot.querySelector(CHIP_SET_TAG_NAME);
this.mdcTextField = new MDCTextField(
this.chipSet.shadowRoot.querySelector('.mdc-text-field')
);
}

public componentDidUnload() {
if (this.mdcTextField) {
this.mdcTextField.destroy();
}
}

public render() {
const chipArray = this.value
? [{ ...DEFAULT_FILE_CHIP, ...this.value }]
: [];
return [
<input
id={this.fileInputId}
type="file"
onChange={this.handleFileChange}
hidden={true}
/>,
<limel-chip-set
disabled={this.disabled}
label={this.label}
required={this.required}
type="input"
value={chipArray}
onFocus={this.handleFileSelection}
onChange={this.handleChipSetChange}
onInteract={this.preventAndStop}
onDrop={this.handleFileDrop}
onDragEnter={this.preventAndStop}
onDragOver={this.preventAndStop}
/>,
];
}

private handleFileSelection(event) {
event.stopPropagation();
if (!this.value) {
this.fileInput.click();
}
}

private handleFileChange(event) {
if (this.fileInput.files.length > 0) {
event.stopPropagation();
this.handleFile(this.fileInput.files[0]);
}
}

private handleFile(file) {
this.change.emit(file);
this.chipSet.blur();
this.mdcTextField.valid = true;
}

private handleChipSetChange(event) {
event.stopPropagation();
const chip = !event.detail.length ? event.detail[0] : null;
this.chipSet.blur();
if (!chip) {
this.fileInput.value = '';
this.change.emit(chip);
if (this.required) {
this.mdcTextField.valid = false;
}
}
}

private handleFileDrop(event) {
this.preventAndStop(event);
const dataTransfer = event.dataTransfer;
this.handleFile(dataTransfer.files[0]);
}

private preventAndStop(event) {
event.stopPropagation();
event.preventDefault();
}
}
39 changes: 39 additions & 0 deletions src/examples/file/file.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { Component, State } from '@stencil/core';
import { Chip } from '../../components/chip-set/chip';

@Component({
tag: 'limel-example-file',
shadow: true,
})
export class FileExample {
@State()
private value: Chip = { id: 'bla', text: 'bla.jpg' };

@State()
private required = false;

public render() {
return [
<limel-switch
label="Toggle required"
value={this.required}
onChange={() => {
this.required = !this.required;
}}
/>,
<limel-file
label="File"
value={this.value}
required={this.required}
onChange={this.handleChange.bind(this)}
/>,
];
}

private handleChange(event) {
console.log('onChange', event.detail);
this.value = event.detail
? { id: event.detail.name, text: event.detail.name }
: null;
}
}

0 comments on commit 95da842

Please sign in to comment.