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 Feb 20, 2019
1 parent 7b71bbd commit b697ad0
Show file tree
Hide file tree
Showing 3 changed files with 189 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" />
136 changes: 136 additions & 0 deletions src/components/file/file.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
import { MDCTextField } from '@lime-material/textfield';
import { Component, Element, Event, EventEmitter, Prop } from '@stencil/core';
import { Chip } from '../chip-set/chip';

const CHIP_SET_TAG_NAME = 'limel-chip-set';
const FILE_INPUT_ID = 'fileInput';
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()
public label: string;

@Prop()
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;

/**
* Dispatched when a file is interacted with
*/
@Event()
private interact: EventEmitter;

@Element()
private element: HTMLElement;

private fileInput: HTMLInputElement;
private chipSet;
private mdcTextField;

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

public componentDidLoad() {
this.fileInput = this.element.shadowRoot.getElementById(
FILE_INPUT_ID
) 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={FILE_INPUT_ID}
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}
/>,
];
}

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

private handleFileChange(event) {
if (this.fileInput.files.length > 0) {
event.stopPropagation();
const fileName = this.fileInput.files[0].name;
const chip: Chip = {
...DEFAULT_FILE_CHIP,
id: fileName,
text: fileName,
};
this.change.emit(chip);
this.chipSet.blur();
this.mdcTextField.valid = true;
}
}

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

private handleChipSetInteract(event) {
event.stopPropagation();
this.interact.emit(event.detail);
}
}
40 changes: 40 additions & 0 deletions src/examples/file/file.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
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)}
onInteract={event => {
console.log('onInteract', event.detail);
}}
/>,
];
}

private handleChange(event) {
console.log('onChange', event.detail);
this.value = event.detail;
}
}

0 comments on commit b697ad0

Please sign in to comment.