diff --git a/src/components/multi-select/multi-select.mdx b/src/components/multi-select/multi-select.mdx deleted file mode 100644 index 43a9c94c8a..0000000000 --- a/src/components/multi-select/multi-select.mdx +++ /dev/null @@ -1,13 +0,0 @@ ---- -name: Multi Select -route: /multi-select -menu: Components ---- - -# Multi Select - - - -## Example - - diff --git a/src/components/select-multiple/select-multiple.scss b/src/components/select-multiple/select-multiple.scss new file mode 100644 index 0000000000..acf5aca1d0 --- /dev/null +++ b/src/components/select-multiple/select-multiple.scss @@ -0,0 +1,26 @@ +@import '../../style/variables'; + +@import '@lime-material-16px/form-field/mdc-form-field'; +@import '@lime-material-16px/checkbox/mdc-checkbox'; +@import "@lime-material-16px/floating-label/mdc-floating-label"; + +.multi-select { + position: relative; +} + +.multi-select-label { + padding-left: pxToRem(15); +} + +.mdc-form-field { + display: flex; +} + +.mdc-checkbox { + @include mdc-checkbox-ink-color(primary); + @include mdc-checkbox-container-colors(secondary, on-primary, secondary, on-primary); +} + +limel-collapsible-section { + --body-max-height: 70vh; +} diff --git a/src/components/select-multiple/select-multiple.tsx b/src/components/select-multiple/select-multiple.tsx new file mode 100644 index 0000000000..5899f6d860 --- /dev/null +++ b/src/components/select-multiple/select-multiple.tsx @@ -0,0 +1,147 @@ +import { MDCCheckbox } from '@lime-material-16px/checkbox'; +import { MDCFormField } from '@lime-material-16px/form-field'; +import { + Component, + Element, + Event, + EventEmitter, + Prop, + State, +} from '@stencil/core'; +import { Option } from '../../interface'; +import { createRandomString } from '../../util/random-string'; + +@Component({ + tag: 'limel-select-multiple', + shadow: true, + styleUrl: 'select-multiple.scss', +}) +export class SelectMultiple { + @Prop({ reflectToAttr: true }) + public disabled = false; + + @Prop({ reflectToAttr: true }) + public label: string; + + @Prop() + public value: Option[] = []; + + @Prop() + public options: Option[] = []; + + @Event() + private change: EventEmitter; + + @Element() + private limelMultiSelect: HTMLElement; + + @State() + private fieldId = createRandomString(); + + @State() + private mdcCheckboxes = []; + + public componentDidLoad() { + const elements = Array.from( + this.limelMultiSelect.shadowRoot.querySelectorAll( + '.multi-select .mdc-form-field' + ) + ); + + elements.forEach(element => { + const formField = new MDCFormField(element); + const checkbox = new MDCCheckbox(element.firstChild); + formField.input = checkbox; + this.mdcCheckboxes.push(checkbox); + }); + + this.onChange(); + } + + public render() { + return ( +
+ { + return option.text; + }) + .join(', ') + } + > +
+ {this.options.map((option: Option, index: number) => { + return this.renderCheckbox(index, option); + })} +
+
+
+ ); + } + + private renderCheckbox(index: number, option: Option) { + return ( +
+
+ +
+ + + +
+
+
+ +
+ ); + } + + private isOptionChecked(option: Option) { + return this.value.find(checkedOption => { + return checkedOption.value === option.value; + }); + } + + private onChange = (event?) => { + if (event) { + event.stopPropagation(); + } + + const checked = this.options.filter(option => { + const optionChecked = this.mdcCheckboxes.some(mdcCheckbox => { + return ( + mdcCheckbox.checked && mdcCheckbox.value === option.value + ); + }); + if (optionChecked) { + return option; + } + }); + this.change.emit(checked); + }; +} diff --git a/src/components/select/select.e2e.ts b/src/components/select-single/select-single.e2e.ts similarity index 88% rename from src/components/select/select.e2e.ts rename to src/components/select-single/select-single.e2e.ts index 332cdb1451..315366244b 100644 --- a/src/components/select/select.e2e.ts +++ b/src/components/select-single/select-single.e2e.ts @@ -9,17 +9,17 @@ import { newE2EPage } from '@stencil/core/testing'; // Matchers (expect-methods) for E2EElement (v0.13.0-9): // https://github.com/ionic-team/stencil/blob/a0250ffcbf5a2c657475a05052eac3a4690809d2/src/declarations/testing.ts#L5 -describe('limel-select', () => { +describe('limel-select-single', () => { let page; describe('with a label', () => { let limelSelect; let label; beforeEach(async () => { page = await createPage(` - + `); - limelSelect = await page.find('limel-select'); - label = await page.find('limel-select>>>.mdc-floating-label'); + limelSelect = await page.find('limel-select-single'); + label = await page.find('limel-select-single>>>.mdc-floating-label'); }); it('displays the correct label', () => { expect(label).toEqualText('Favourite Doctor'); @@ -43,11 +43,11 @@ describe('limel-select', () => { let innerSelect; beforeEach(async () => { page = await createPage(` - + `); - limelSelect = await page.find('limel-select'); - mdcSelect = await page.find('limel-select>>>.mdc-select'); - innerSelect = await page.find('limel-select>>>select'); + limelSelect = await page.find('limel-select-single'); + mdcSelect = await page.find('limel-select-single>>>.mdc-select'); + innerSelect = await page.find('limel-select-single>>>select'); }); it('is enabled', () => { expect(mdcSelect).not.toHaveClass('mdc-select--disabled'); @@ -80,11 +80,11 @@ describe('limel-select', () => { let innerSelect; beforeEach(async () => { page = await createPage(` - + `); - limelSelect = await page.find('limel-select'); - mdcSelect = await page.find('limel-select>>>.mdc-select'); - innerSelect = await page.find('limel-select>>>select'); + limelSelect = await page.find('limel-select-single'); + mdcSelect = await page.find('limel-select-single>>>.mdc-select'); + innerSelect = await page.find('limel-select-single>>>select'); }); it('is enabled', () => { expect(mdcSelect).not.toHaveClass('mdc-select--disabled'); @@ -117,11 +117,11 @@ describe('limel-select', () => { let innerSelect; beforeEach(async () => { page = await createPage(` - + `); - limelSelect = await page.find('limel-select'); - mdcSelect = await page.find('limel-select>>>.mdc-select'); - innerSelect = await page.find('limel-select>>>select'); + limelSelect = await page.find('limel-select-single'); + mdcSelect = await page.find('limel-select-single>>>.mdc-select'); + innerSelect = await page.find('limel-select-single>>>select'); }); it('is disabled', () => { expect(mdcSelect).toHaveClass('mdc-select--disabled'); @@ -160,9 +160,9 @@ describe('limel-select', () => { `); testWrapper = await page.find('select-test-wrapper'); - limelSelect = await page.find('limel-select'); - innerSelect = await page.find('limel-select>>>select'); - label = await page.find('limel-select>>>.mdc-floating-label'); + limelSelect = await page.find('limel-select-single'); + innerSelect = await page.find('limel-select-single>>>select'); + label = await page.find('limel-select-single>>>.mdc-floating-label'); }); it('has no options', async () => { const child = await innerSelect.find('option'); diff --git a/src/components/select/select.scss b/src/components/select-single/select-single.scss similarity index 100% rename from src/components/select/select.scss rename to src/components/select-single/select-single.scss diff --git a/src/components/select-single/select-single.tsx b/src/components/select-single/select-single.tsx new file mode 100644 index 0000000000..f0e03ded80 --- /dev/null +++ b/src/components/select-single/select-single.tsx @@ -0,0 +1,135 @@ +import { MDCSelect } from '@lime-material-16px/select'; +import { + Component, + Element, + Event, + EventEmitter, + Prop, + State, + Watch, +} from '@stencil/core'; +import { Option } from '../../interface'; + +@Component({ + tag: 'limel-select-single', + shadow: true, + styleUrl: 'select-single.scss', +}) +export class SelectSingle { + /** + * Set to `true` to disable the input. + */ + @Prop({ reflectToAttr: true }) + public disabled = false; + + /** + * The input label. + */ + @Prop({ reflectToAttr: true }) + public label: string; + + /** + * The currently selected item. + */ + @Prop() + public value: Option; + + @Prop() + public options: Option[] = []; + + @Event() + private change: EventEmitter