Merge pull request #145 from material-components/typescript-updates

Update slider and snackbar to mdc v0.40 and typescript
This commit is contained in:
Daniel Freedman 2018-10-29 14:18:23 -07:00 committed by GitHub
commit 960329a650
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 514 additions and 254 deletions

View File

@ -18,8 +18,6 @@ import {BaseElement, html, property, observer, query, customElement, Adapter, Fo
import {style} from './mwc-linear-progress-css.js';
import MDCLinearProgressFoundation from '@material/linear-progress/foundation.js';
const {PRIMARY_BAR_SELECTOR, BUFFER_SELECTOR} = MDCLinearProgressFoundation.strings;
export interface LinearProgressFoundation extends Foundation {
setDeterminate(value: boolean): void;
setProgress(value: number): void;
@ -49,13 +47,13 @@ export class LinearProgress extends BaseElement {
@query('.mdc-linear-progress')
protected mdcRoot!: HTMLElement
@query(PRIMARY_BAR_SELECTOR)
@query('.mdc-linear-progress__primary-bar')
protected primaryBar!: HTMLElement
@query(BUFFER_SELECTOR)
@query('.mdc-linear-progress__buffer')
protected bufferElement!: HTMLElement
@property({type: Boolean})
@property({type: Boolean, reflect: true})
@observer(function(this: LinearProgress, value: boolean) {
this.mdcFoundation.setDeterminate(value);
})
@ -73,12 +71,13 @@ export class LinearProgress extends BaseElement {
})
buffer = 0;
@property({type: Boolean})
@property({type: Boolean, reflect: true})
@observer(function(this: LinearProgress, value: boolean) {
this.mdcFoundation.setReverse(value);
})
reverse = 0;
reverse = false;
@property({type: Boolean, reflect: true})
@observer(function(this: LinearProgress, value: boolean) {
if (value) {
this.mdcFoundation.close();
@ -86,7 +85,6 @@ export class LinearProgress extends BaseElement {
this.mdcFoundation.open();
}
})
@property({type: Boolean, reflect: true})
closed = false;
renderStyle() {

61
packages/slider/README.md Normal file
View File

@ -0,0 +1,61 @@
# mwc-slider
A [Material Components](https://material.io/components/) icon implementation using [Web Components](https://www.webcomponents.org/introduction)
## Getting started
* The easiest way to try out mwc-slider is to use one of these online tools:
* Runs in all [supported](#supported-browsers) browsers: [StackBlitz](https://stackblitz.com/edit/mwc-icon-example?file=index.js), [Glitch](https://glitch.com/edit/#!/mwc-icon-example?path=index.html)
* Runs in browsers with [JavaScript Modules](https://caniuse.com/#search=modules): [JSBin](http://jsbin.com/qibisux/edit?html,output),
[CodePen](https://codepen.io/azakus/pen/deZLja).
* You can also copy [this HTML file](https://gist.githubusercontent.com/azakus/f01e9fc2ed04e781ad5a52ded7b296e7/raw/266f2f4f91cbfe89b2acc6ec63957b1a3cfe9b39/index.html) into a local file and run it in any browser that supports [JavaScript Modules]((https://caniuse.com/#search=modules)).
* When you're ready to use mwc-slider in a project, install it via [npm](https://www.npmjs.com/). To run the project in the browser, a module-compatible toolctain is required. We recommend installing the [Polymer CLI](https://github.com/Polymer/polymer-cli) and using its development server as follows.
1. Ensure the webcomponents polyfills are included in your HTML page
- Install webcomponents polyfills
```npm i @webcomponents/webcomponentsjs```
- Add webcomponents polyfills to your HTML page
```<script src="@webcomponents/webcomponentsjs/webcomponents-loader.js"></script>```
1. Add mwc-slider to your project:
```npm i @material/mwc-slider```
1. Import the mwc-slider definition into your HTML page:
```<script type="module" src="@material/mwc-slider/index.js"></script>```
Or into your module script:
```import {Slider} from "@material/mwc-slider"```
1. Create an instance of mwc-slider in your HTML page, or via any framework that [supports rendering Custom Elements](https://custom-elements-everywhere.com/):
```<mwc-slider></mwc-slider>```
1. Install the Polymer CLI:
```npm i -g polymer-cli```
1. Run the development server and open a browser pointing to its URL:
```polymer serve```
> mwc-slider is published on [npm](https://www.npmjs.com/package/@material/mwc-slider) using JavaScript Modules.
This means it can take advantage of the standard native JavaScript module loader available in all current major browsers.
>
> However, since mwc-slider uses npm convention to reference dependencies by name, a light transform to rewrite specifiers to URLs is required to get it to run in the browser. The polymer-cli's development server `polymer serve` automatically handles this transform.
Tools like [WebPack](https://webpack.js.org/) and [Rollup](https://rollupjs.org/) can also be used to serve and/or bundle mwc-slider.
## Supported Browsers
The last 2 versions of all modern browsers are supported, including
Chrome, Safari, Opera, Firefox, Edge. In addition, Internet Explorer 11 is also supported.

View File

@ -1,20 +0,0 @@
/**
@license
Copyright 2018 Google Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
import {html} from '@polymer/lit-element/lit-element.js';
export const style = html`<style>@keyframes mdc-slider-emphasize{0%{animation-timing-function:ease-out}50%{animation-timing-function:ease-in;transform:scale(0.85)}100%{transform:scale(0.571)}}.mdc-slider{position:relative;width:100%;height:48px;cursor:pointer;touch-action:pan-x;-webkit-tap-highlight-color:rgba(0,0,0,0)}.mdc-slider:not(.mdc-slider--disabled) .mdc-slider__track{background-color:#018786;background-color:var(--mdc-theme-secondary, #018786)}.mdc-slider:not(.mdc-slider--disabled) .mdc-slider__track-container{background-color:rgba(1,135,134,0.26)}.mdc-slider:not(.mdc-slider--disabled) .mdc-slider__track-marker::after,.mdc-slider:not(.mdc-slider--disabled) .mdc-slider__track-marker-container::after{background-color:#018786;background-color:var(--mdc-theme-secondary, #018786)}.mdc-slider:not(.mdc-slider--disabled) .mdc-slider__thumb{fill:#018786;fill:var(--mdc-theme-secondary, #018786);stroke:#018786;stroke:var(--mdc-theme-secondary, #018786)}.mdc-slider:not(.mdc-slider--disabled) .mdc-slider__focus-ring{background-color:#018786;background-color:var(--mdc-theme-secondary, #018786)}.mdc-slider:not(.mdc-slider--disabled) .mdc-slider__pin{background-color:#018786;background-color:var(--mdc-theme-secondary, #018786)}.mdc-slider:not(.mdc-slider--disabled) .mdc-slider__pin{color:#fff;color:var(--mdc-theme-text-primary-on-dark, #fff)}.mdc-slider--disabled{cursor:auto}.mdc-slider--disabled .mdc-slider__track{background-color:#9a9a9a}.mdc-slider--disabled .mdc-slider__track-container{background-color:rgba(154,154,154,0.26)}.mdc-slider--disabled .mdc-slider__track-marker::after,.mdc-slider--disabled .mdc-slider__track-marker-container::after{background-color:#9a9a9a}.mdc-slider--disabled .mdc-slider__thumb{fill:#9a9a9a;stroke:#9a9a9a}.mdc-slider--disabled .mdc-slider__thumb{stroke:#fff;stroke:var(--mdc-slider-bg-color-behind-component, #fff)}.mdc-slider:focus{outline:none}.mdc-slider__track-container{position:absolute;top:50%;width:100%;height:2px;overflow:hidden}.mdc-slider__track{position:absolute;width:100%;height:100%;transform-origin:left top;will-change:transform}.mdc-slider[dir="rtl"] .mdc-slider__track,[dir="rtl"] .mdc-slider .mdc-slider__track{transform-origin:right top}.mdc-slider__track-marker-container{display:flex;margin-right:0;margin-left:-1px;visibility:hidden}.mdc-slider[dir="rtl"] .mdc-slider__track-marker-container,[dir="rtl"] .mdc-slider .mdc-slider__track-marker-container{margin-right:-1px;margin-left:0}.mdc-slider__track-marker-container::after{display:block;width:2px;height:2px;content:""}.mdc-slider__track-marker{flex:1}.mdc-slider__track-marker::after{display:block;width:2px;height:2px;content:""}.mdc-slider__track-marker:first-child::after{width:3px}.mdc-slider__thumb-container{position:absolute;top:15px;left:0;width:21px;height:100%;user-select:none;will-change:transform}.mdc-slider__thumb{position:absolute;top:0;left:0;transform:scale(0.571);transition:transform 100ms ease-out, fill 100ms ease-out, stroke 100ms ease-out;stroke-width:3.5}.mdc-slider__focus-ring{width:21px;height:21px;transition:transform 266.67ms ease-out, opacity 266.67ms ease-out, background-color 266.67ms ease-out;border-radius:50%;opacity:0}.mdc-slider__pin{display:flex;position:absolute;top:0;left:0;align-items:center;justify-content:center;width:26px;height:26px;margin-top:-2px;margin-left:-2px;transform:rotate(-45deg) scale(0) translate(0, 0);transition:transform 100ms ease-out;border-radius:50% 50% 50% 0%;z-index:1}.mdc-slider__pin-value-marker{font-family:Roboto,sans-serif;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;font-size:.875rem;line-height:1.25rem;font-weight:400;letter-spacing:.01786em;text-decoration:inherit;text-transform:inherit;transform:rotate(45deg)}.mdc-slider--active .mdc-slider__thumb{transform:scale3d(1, 1, 1)}.mdc-slider--focus .mdc-slider__thumb{animation:mdc-slider-emphasize 266.67ms linear}.mdc-slider--focus .mdc-slider__focus-ring{transform:scale3d(1.55, 1.55, 1.55);opacity:.25}.mdc-slider--in-transit .mdc-slider__thumb{transition-delay:140ms}.mdc-slider--in-transit .mdc-slider__thumb-container,.mdc-slider--in-transit .mdc-slider__track,.mdc-slider:focus:not(.mdc-slider--active) .mdc-slider__thumb-container,.mdc-slider:focus:not(.mdc-slider--active) .mdc-slider__track{transition:transform 80ms ease}.mdc-slider--discrete.mdc-slider--active .mdc-slider__thumb{transform:scale(calc(12 / 21))}.mdc-slider--discrete.mdc-slider--active .mdc-slider__pin{transform:rotate(-45deg) scale(1) translate(19px, -20px)}.mdc-slider--discrete.mdc-slider--focus .mdc-slider__thumb{animation:none}.mdc-slider--discrete.mdc-slider--display-markers .mdc-slider__track-marker-container{visibility:visible}:host{display:inline-block;min-width:120px}
</style>`;

View File

@ -1,101 +0,0 @@
/**
@license
Copyright 2018 Google Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
import {FormableComponentElement, MDCWebComponentMixin, html} from '@material/mwc-base/formable-component-element.js';
import {classMap} from 'lit-html/directives/classMap.js';
import {style} from './mwc-slider-css.js';
import {MDCSlider} from '@material/slider';
export class MDCWCSlider extends MDCWebComponentMixin(MDCSlider) {}
export class Slider extends FormableComponentElement {
static get ComponentClass() {
return MDCWCSlider;
}
static get componentSelector() {
return '.mdc-slider';
}
static get properties() {
return {
disabled: {type: Boolean},
step: {type: Number},
min: {type: Number},
max: {type: Number},
value: {type: Number},
discrete: {type: Boolean},
markers: {type: Boolean},
};
}
constructor() {
super();
this._asyncComponent = true;
this.disabled = false;
this.step = 0;
this.min = 0;
this.max = 10;
this.value = 0;
this.discrete = false;
this.markers = false;
}
static get formElementSelector() {
return '.mdc-slider';
}
_makeComponent() {
super._makeComponent();
this._componentRoot.addEventListener('MDCSlider:input', (e) => {
this.value = e.detail.value;
});
}
renderStyle() {
return style;
}
// TODO(sorvell) #css: needs a default width
render() {
const {disabled, step, min, max, value, discrete, markers} = this;
const hostClassInfo = {
'mdc-slider--discrete': discrete,
'mdc-slider--display-markers': markers && discrete,
};
return html`
${this.renderStyle()}
<div class="mdc-slider ${classMap(hostClassInfo)}" tabindex="0" role="slider"
aria-valuemin="${min}" aria-valuemax="${max}" aria-valuenow="${value}"
aria-disabled="${disabled}" data-step="${step}">
<div class="mdc-slider__track-container">
<div class="mdc-slider__track"></div>
${discrete && markers ? html`<div class="mdc-slider__track-marker-container"></div>` : ''}
</div>
<div class="mdc-slider__thumb-container">
${discrete ? html`<div class="mdc-slider__pin">
<span class="mdc-slider__pin-value-marker"></span>
</div>` : ''}
<svg class="mdc-slider__thumb" width="21" height="21">
<circle cx="10.5" cy="10.5" r="7.875"></circle>
</svg>
<div class="mdc-slider__focus-ring"></div>
</div>
</div>`;
}
}
customElements.define('mwc-slider', Slider);

View File

@ -10,7 +10,7 @@
"license": "Apache-2.0",
"dependencies": {
"@material/mwc-base": "^0.3.1",
"@material/slider": "^0.35.0",
"@material/slider": "^0.40.0",
"@polymer/lit-element": "^0.6.2"
},
"publishConfig": {

View File

@ -20,4 +20,5 @@ limitations under the License.
:host {
display: inline-block;
min-width: 120px;
outline: none;
}

View File

@ -0,0 +1,204 @@
/**
@license
Copyright 2018 Google Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
import {FormElement, html, property, observer, query, customElement, Adapter, Foundation} from '@material/mwc-base/form-element.js';
import {classMap} from 'lit-html/directives/classMap.js';
import {repeat} from 'lit-html/directives/repeat.js';
import {style} from './mwc-slider-css.js';
import MDCSliderFoundation from '@material/slider/foundation.js';
const {INPUT_EVENT, CHANGE_EVENT} = MDCSliderFoundation.strings;
export interface SliderFoundation extends Foundation {
layout(): void;
getValue(): number;
setValue(value: number): void;
getMax(): number;
setMax(value: number): void;
getMin(): number;
setMin(value: number): void;
getStep(): number;
setStep(value: number): void;
isDisabled(): boolean;
setDisabled(value: boolean): void;
setupTrackMarker(): void;
}
export declare var SliderFoundation: {
prototype: SliderFoundation;
new(adapter: Adapter): SliderFoundation;
}
declare global {
interface HTMLElementTagNameMap {
'mwc-slider': Slider;
}
}
@customElement('mwc-slider' as any)
export class Slider extends FormElement {
protected mdcFoundation!: SliderFoundation;
protected readonly mdcFoundationClass: typeof SliderFoundation = MDCSliderFoundation;
@query('.mdc-slider')
protected mdcRoot!: HTMLElement
@query('.mdc-slider')
protected formElement!: HTMLElement;
@query('.mdc-slider__thumb-container')
protected thumbContainer!: HTMLElement;
@query('.mdc-slider__track')
protected trackElement!: HTMLElement;
@query('.mdc-slider__pin-value-marker')
protected pinMarker!: HTMLElement;
@query('.mdc-slider__track-marker-container')
protected trackMarkerContainer!: HTMLElement;
@property({type: Number})
@observer(function(this: Slider, value: number) {1
this.mdcFoundation.setValue(value);
})
value = 0;
@property({type: Number})
@observer(function(this: Slider, value: number) {
this.mdcFoundation.setMin(value);
})
min = 0;
@property({type: Number})
@observer(function(this: Slider, value: number) {
this.mdcFoundation.setMax(value);
})
max = 100;
@property({type: Number})
@observer(function(this: Slider, value: number) {
this.mdcFoundation.setStep(value);
})
step = 0;
@property({type: Boolean, reflect: true})
@observer(function(this: Slider, value: boolean) {
this.mdcFoundation.setDisabled(value);
})
disabled = false;
@property({type: Boolean, reflect: true})
discrete = false;
@property({type: Boolean, reflect: true})
@observer(function(this: Slider) {
this.mdcFoundation.setupTrackMarker();
})
markers = false;
@property({type: Number})
private _numMarkers = 0;
renderStyle() {
return style;
}
// TODO(sorvell) #css: needs a default width
render() {
const {value, min, max, step, disabled, discrete, markers, _numMarkers} = this;
const hostClassInfo = {
'mdc-slider--discrete': discrete,
'mdc-slider--display-markers': markers && discrete,
};
return html`
${this.renderStyle()}
<div class="mdc-slider ${classMap(hostClassInfo)}" tabindex="0" role="slider"
aria-valuemin="${min}" aria-valuemax="${max}" aria-valuenow="${value}"
aria-disabled="${disabled}" data-step="${step}">
<div class="mdc-slider__track-container">
<div class="mdc-slider__track"></div>
${discrete && markers ? html`<div class="mdc-slider__track-marker-container">
${repeat(new Array(_numMarkers), () => html`<div class="mdc-slider__track-marker"></div>`)}
</div>` : ''}
</div>
<div class="mdc-slider__thumb-container">
<!-- TODO: use cache() directive -->
${discrete ? html`<div class="mdc-slider__pin">
<span class="mdc-slider__pin-value-marker"></span>
</div>` : ''}
<svg class="mdc-slider__thumb" width="21" height="21">
<circle cx="10.5" cy="10.5" r="7.875"></circle>
</svg>
<div class="mdc-slider__focus-ring"></div>
</div>
</div>`;
}
protected createAdapter() {
return {
...super.createAdapter(),
getAttribute: (name: string) => this.mdcRoot.getAttribute(name),
setAttribute: (name: string, value: string) => this.mdcRoot.setAttribute(name, value),
removeAttribute: (name: string) => this.mdcRoot.removeAttribute(name),
computeBoundingRect: () => this.mdcRoot.getBoundingClientRect(),
getTabIndex: () => this.mdcRoot.tabIndex,
registerInteractionHandler: (type: string, handler: EventListener) =>
this.mdcRoot.addEventListener(type, handler),
deregisterInteractionHandler: (type: string, handler: EventListener) =>
this.mdcRoot.removeEventListener(type, handler),
registerThumbContainerInteractionHandler: (type: string, handler: EventListener) =>
this.thumbContainer.addEventListener(type, handler),
deregisterThumbContainerInteractionHandler: (type: string, handler: EventListener) =>
this.thumbContainer.removeEventListener(type, handler),
registerBodyInteractionHandler: (type: string, handler: EventListener) =>
document.body.addEventListener(type, handler),
deregisterBodyInteractionHandler: (type: string, handler: EventListener) =>
document.body.removeEventListener(type, handler),
registerResizeHandler: (handler: EventListener) =>
window.addEventListener('resize', handler),
deregisterResizeHandler: (handler: EventListener) =>
window.removeEventListener('resize', handler),
notifyInput: () => {
const value = this.mdcFoundation.getValue();
if (value !== this.value) {
this.value = value;
this.dispatchEvent(new CustomEvent(INPUT_EVENT, {detail: this, bubbles: true, cancelable: true}));
}
},
notifyChange: () => {
this.dispatchEvent(new CustomEvent(CHANGE_EVENT, {detail: this, bubbles: true, cancelable: true}));
},
setThumbContainerStyleProperty: (propertyName: string, value: string) =>
this.thumbContainer.style.setProperty(propertyName, value),
setTrackStyleProperty: (propertyName: string, value: string) =>
this.trackElement.style.setProperty(propertyName, value),
setMarkerValue: (value: number) => this.pinMarker.innerText = value.toString(),
appendTrackMarkers: (numMarkers: number) => this._numMarkers = numMarkers,
removeTrackMarkers: () => {},
setLastTrackMarkersStyleProperty: (propertyName: string, value: string) =>
// We remove and append new nodes, thus, the last track marker must be dynamically found.
(this.mdcRoot.querySelector('.mdc-slider__track-marker:last-child') as HTMLElement).
style.setProperty(propertyName, value),
isRTL: () => getComputedStyle(this.mdcRoot).direction === 'rtl',
};
}
layout() {
this.mdcFoundation.layout();
}
}

View File

@ -0,0 +1,10 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"rootDir": "src",
"outDir": "."
},
"include": [
"src/*.ts"
]
}

View File

@ -0,0 +1,61 @@
# mwc-snackbar
A [Material Components](https://material.io/components/) icon implementation using [Web Components](https://www.webcomponents.org/introduction)
## Getting started
* The easiest way to try out mwc-snackbar is to use one of these online tools:
* Runs in all [supported](#supported-browsers) browsers: [StackBlitz](https://stackblitz.com/edit/mwc-icon-example?file=index.js), [Glitch](https://glitch.com/edit/#!/mwc-icon-example?path=index.html)
* Runs in browsers with [JavaScript Modules](https://caniuse.com/#search=modules): [JSBin](http://jsbin.com/qibisux/edit?html,output),
[CodePen](https://codepen.io/azakus/pen/deZLja).
* You can also copy [this HTML file](https://gist.githubusercontent.com/azakus/f01e9fc2ed04e781ad5a52ded7b296e7/raw/266f2f4f91cbfe89b2acc6ec63957b1a3cfe9b39/index.html) into a local file and run it in any browser that supports [JavaScript Modules]((https://caniuse.com/#search=modules)).
* When you're ready to use mwc-snackbar in a project, install it via [npm](https://www.npmjs.com/). To run the project in the browser, a module-compatible toolctain is required. We recommend installing the [Polymer CLI](https://github.com/Polymer/polymer-cli) and using its development server as follows.
1. Ensure the webcomponents polyfills are included in your HTML page
- Install webcomponents polyfills
```npm i @webcomponents/webcomponentsjs```
- Add webcomponents polyfills to your HTML page
```<script src="@webcomponents/webcomponentsjs/webcomponents-loader.js"></script>```
1. Add mwc-snackbar to your project:
```npm i @material/mwc-snackbar```
1. Import the mwc-snackbar definition into your HTML page:
```<script type="module" src="@material/mwc-snackbar/index.js"></script>```
Or into your module script:
```import {Snackbar} from "@material/mwc-snackbar"```
1. Create an instance of mwc-snackbar in your HTML page, or via any framework that [supports rendering Custom Elements](https://custom-elements-everywhere.com/):
```<mwc-snackbar></mwc-snackbar>```
1. Install the Polymer CLI:
```npm i -g polymer-cli```
1. Run the development server and open a browser pointing to its URL:
```polymer serve```
> mwc-snackbar is published on [npm](https://www.npmjs.com/package/@material/mwc-snackbar) using JavaScript Modules.
This means it can take advantage of the standard native JavaScript module loader available in all current major browsers.
>
> However, since mwc-snackbar uses npm convention to reference dependencies by name, a light transform to rewrite specifiers to URLs is required to get it to run in the browser. The polymer-cli's development server `polymer serve` automatically handles this transform.
Tools like [WebPack](https://webpack.js.org/) and [Rollup](https://rollupjs.org/) can also be used to serve and/or bundle mwc-snackbar.
## Supported Browsers
The last 2 versions of all modern browsers are supported, including
Chrome, Safari, Opera, Firefox, Edge. In addition, Internet Explorer 11 is also supported.

View File

@ -1,20 +0,0 @@
/**
@license
Copyright 2018 Google Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
import {html} from '@polymer/lit-element/lit-element.js';
export const style = html`<style>.mdc-snackbar{display:flex;position:fixed;bottom:0;left:50%;align-items:center;justify-content:flex-start;box-sizing:border-box;padding-right:24px;padding-left:24px;transform:translate(-50%, 100%);transition:transform .25s 0ms cubic-bezier(0.4, 0, 1, 1);background-color:#323232;pointer-events:none;will-change:transform}@media (max-width: 599px){.mdc-snackbar{left:0;width:100%;transform:translate(0, 100%)}}@media (min-width: 600px){.mdc-snackbar{min-width:288px;max-width:568px;border-radius:2px}}@media (min-width: 600px){.mdc-snackbar--align-start{left:24px;right:initial;bottom:24px;transform:translate(0, 200%)}[dir="rtl"] .mdc-snackbar--align-start,.mdc-snackbar--align-start[dir="rtl"]{left:initial;right:24px}}@media (max-width: 599px){.mdc-snackbar--align-start{bottom:0;left:0;width:100%;transform:translate(0, 100%)}}.mdc-snackbar--active{transform:translate(0);transition:transform .25s 0ms cubic-bezier(0, 0, 0.2, 1);pointer-events:auto}.mdc-snackbar--active:not(.mdc-snackbar--align-start){transform:translate(-50%, 0)}@media (max-width: 599px){.mdc-snackbar--active:not(.mdc-snackbar--align-start){bottom:0;left:0;width:100%;transform:translate(0)}}.mdc-snackbar__action-wrapper{padding-left:24px;padding-right:0}[dir="rtl"] .mdc-snackbar__action-wrapper,.mdc-snackbar__action-wrapper[dir="rtl"]{padding-left:0;padding-right:24px}.mdc-snackbar--action-on-bottom{flex-direction:column}.mdc-snackbar__text{font-family:Roboto,sans-serif;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;font-size:1rem;line-height:1.5rem;font-weight:400;letter-spacing:.03125em;text-decoration:inherit;text-transform:inherit;margin-left:0;margin-right:auto;display:flex;align-items:center;height:48px;transition:opacity .3s 0ms cubic-bezier(0.4, 0, 1, 1);opacity:0;color:#fff}.mdc-snackbar[dir="rtl"] .mdc-snackbar__text,[dir="rtl"] .mdc-snackbar .mdc-snackbar__text{margin-left:auto;margin-right:0}@media (min-width: 600px){.mdc-snackbar__text{padding-left:0;padding-right:24px}[dir="rtl"] .mdc-snackbar__text,.mdc-snackbar__text[dir="rtl"]{padding-left:24px;padding-right:0}}.mdc-snackbar--action-on-bottom .mdc-snackbar__text{margin-right:inherit}.mdc-snackbar--action-on-bottom .mdc-snackbar__action-wrapper{margin-left:auto;margin-right:0;flex-direction:column;justify-content:flex-start;margin-top:-12px;margin-bottom:8px}[dir="rtl"] .mdc-snackbar--action-on-bottom .mdc-snackbar__action-wrapper,.mdc-snackbar--action-on-bottom .mdc-snackbar__action-wrapper[dir="rtl"]{margin-left:0;margin-right:auto}.mdc-snackbar--multiline .mdc-snackbar__text{height:80px}.mdc-snackbar__action-button{font-family:Roboto,sans-serif;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;font-size:.875rem;line-height:2.25rem;font-weight:500;letter-spacing:.08929em;text-decoration:none;text-transform:uppercase;color:#018786;color:var(--mdc-theme-secondary, #018786);padding:0;transition:opacity .3s 0ms cubic-bezier(0.4, 0, 1, 1);border:none;outline:none;background-color:transparent;opacity:0;user-select:none;-webkit-appearance:none;visibility:hidden}.mdc-snackbar__action-button::-moz-focus-inner{border:0}.mdc-snackbar__action-button:hover{cursor:pointer}.mdc-snackbar__action-button:not([aria-hidden]){visibility:inherit}.mdc-snackbar--active .mdc-snackbar__text,.mdc-snackbar--active .mdc-snackbar__action-button:not([aria-hidden]){transition:opacity .3s 0ms cubic-bezier(0.4, 0, 1, 1);opacity:1}.mdc-snackbar--multiline.mdc-snackbar--action-on-bottom .mdc-snackbar__text{margin:0}
</style>`;

View File

@ -1,103 +0,0 @@
/**
@license
Copyright 2018 Google Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
import {ComponentElement, MDCWebComponentMixin, html} from '@material/mwc-base/component-element.js';
import {style} from './mwc-snackbar-css.js';
import {MDCSnackbar} from '@material/snackbar';
export class MDCWCSnackbar extends MDCWebComponentMixin(MDCSnackbar) {}
export class Snackbar extends ComponentElement {
static get ComponentClass() {
return MDCWCSnackbar;
}
static get componentSelector() {
return '.mdc-snackbar';
}
static get properties() {
return {
message: {type: String},
timeout: {type: Number},
multiline: {type: Boolean},
actionText: {type: String},
actionOnBottom: {type: Boolean},
dismissesOnAction: {type: Boolean},
};
}
constructor() {
super();
this._asyncComponent = true;
this.message = '';
this.actionText = '';
this.timeout = -1;
this.multiline = false;
this.actionOnBottom = false;
this.dismissesOnAction = true;
this._boundActionHandler = this._actionHandler.bind(this);
}
renderStyle() {
return style;
}
render() {
return html`${this.renderStyle()}
<div class="mdc-snackbar"
aria-live="assertive"
aria-atomic="true"
aria-hidden="true">
<div class="mdc-snackbar__text"></div>
<div class="mdc-snackbar__action-wrapper">
<button type="button" class="mdc-snackbar__action-button"></button>
</div>
</div>`;
}
show(data) {
this.componentReady().then((component) => {
const options = {
message: this.message,
actionText: this.actionText,
multiline: this.multiLine,
actionOnBottom: this.actionOnBottom,
actionHandler: this._boundActionHandler,
};
if (this.timeout >= 0) {
options.timeout = this.timeout;
}
component.show(Object.assign(options, data));
});
}
_actionHandler() {
this.dispatchEvent(new CustomEvent('MDCSnackbar:action'));
}
get dismissesOnAction() {
return this._component && this._component.dismissesOnAction;
}
set dismissesOnAction(value) {
this.componentReady().then((component) => {
component.dismissesOnAction = value;
});
}
}
customElements.define('mwc-snackbar', Snackbar);

View File

@ -10,7 +10,7 @@
"license": "Apache-2.0",
"dependencies": {
"@material/mwc-base": "^0.3.1",
"@material/snackbar": "^0.35.0",
"@material/snackbar": "^0.40.0",
"@polymer/lit-element": "^0.6.2"
},
"publishConfig": {

View File

@ -0,0 +1,159 @@
/**
@license
Copyright 2018 Google Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
import {BaseElement, html, property, query, customElement, Adapter, Foundation} from '@material/mwc-base/base-element.js';
import {style} from './mwc-snackbar-css.js';
import MDCSnackbarFoundation from '@material/snackbar/foundation.js';
import {getCorrectEventName} from '@material/animation/index.js';
const {SHOW_EVENT, HIDE_EVENT} = MDCSnackbarFoundation.strings;
export interface ActionData {
message?: string;
timeout?: number;
actionText?: string,
multiline?: boolean,
actionOnBottom?: boolean,
actionHandler?: Function,
}
export interface SnackbarFoundation extends Foundation {
dismissesOnAction(): boolean;
setDismissOnAction(value: boolean): void;
show(data: ActionData): void;
}
export declare var SnackbarFoundation: {
prototype: SnackbarFoundation;
new(adapter: Adapter): SnackbarFoundation;
}
declare global {
interface HTMLElementTagNameMap {
'mwc-snackbar': Snackbar;
}
}
@customElement('mwc-snackbar' as any)
export class Snackbar extends BaseElement {
protected mdcFoundation!: SnackbarFoundation;
protected readonly mdcFoundationClass: typeof SnackbarFoundation = MDCSnackbarFoundation;
@query('.mdc-snackbar')
protected mdcRoot!: HTMLElement
@query('.mdc-snackbar__action-button')
protected actionButton!: HTMLElement
@query('.mdc-snackbar__text')
protected textElement!: HTMLElement
@property()
message = '';
@property({type: Number})
timeout = 0;
@property({})
actionText = '';
@property({type: Boolean, reflect: true})
multiline = false;
@property({type: Boolean, reflect: true})
actionOnBottom = false;
protected boundActionHandler = this._actionHandler.bind(this);
renderStyle() {
return style;
}
render() {
return html`${this.renderStyle()}
<div class="mdc-snackbar"
aria-live="assertive"
aria-atomic="true"
aria-hidden="true">
<div class="mdc-snackbar__text"></div>
<div class="mdc-snackbar__action-wrapper">
<button type="button" class="mdc-snackbar__action-button"></button>
</div>
</div>`;
}
protected createAdapter() {
return {
...super.createAdapter(),
setAriaHidden: () => this.mdcRoot.setAttribute('aria-hidden', 'true'),
unsetAriaHidden: () => this.mdcRoot.removeAttribute('aria-hidden'),
setActionAriaHidden: () => this.actionButton.setAttribute('aria-hidden', 'true'),
unsetActionAriaHidden: () => this.actionButton.removeAttribute('aria-hidden'),
setActionText: (text: string) => this.actionButton.textContent = text,
setMessageText: (text: string) => this.textElement.textContent = text,
setFocus: () => this.actionButton.focus(),
isFocused: () => this.shadowRoot!.activeElement === this.actionButton,
visibilityIsHidden: () => document.hidden,
registerCapturedBlurHandler: (handler: EventListener) =>
this.actionButton.addEventListener('blur', handler, true),
deregisterCapturedBlurHandler: (handler: EventListener) =>
this.actionButton.removeEventListener('blur', handler, true),
registerVisibilityChangeHandler: (handler: EventListener) =>
document.addEventListener('visibilitychange', handler),
deregisterVisibilityChangeHandler: (handler: EventListener) =>
document.removeEventListener('visibilitychange', handler),
registerCapturedInteractionHandler: (evtType: string, handler: EventListener) =>
document.body.addEventListener(evtType, handler, true),
deregisterCapturedInteractionHandler: (evtType: string, handler: EventListener) =>
document.body.removeEventListener(evtType, handler, true),
registerActionClickHandler: (handler: EventListener) =>
this.actionButton.addEventListener('click', handler),
deregisterActionClickHandler: (handler: EventListener) =>
this.actionButton.removeEventListener('click', handler),
registerTransitionEndHandler: (handler: EventListener) =>
this.mdcRoot.addEventListener(getCorrectEventName(window, 'transitionend'), handler),
deregisterTransitionEndHandler: (handler: EventListener) =>
this.mdcRoot.removeEventListener(getCorrectEventName(window, 'transitionend'), handler),
notifyShow: () => this.dispatchEvent(new CustomEvent(SHOW_EVENT, {bubbles: true, cancelable: true})),
notifyHide: () => this.dispatchEvent(new CustomEvent(HIDE_EVENT, {bubbles: true, cancelable: true})),
};
}
_actionHandler() {
this.dispatchEvent(new CustomEvent('MDCSnackbar:action'));
}
show(data: ActionData) {
const options: ActionData = {
message: this.message,
timeout: this.timeout,
actionText: this.actionText,
multiline: this.multiline,
actionOnBottom: this.actionOnBottom,
actionHandler: this.boundActionHandler,
};
this.mdcFoundation.show(Object.assign(options, data));
}
get dismissesOnAction() {
return this.mdcFoundation.dismissesOnAction();
}
set dismissesOnAction(dismissesOnAction) {
this.mdcFoundation.setDismissOnAction(dismissesOnAction);
}
}

View File

@ -0,0 +1,10 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"rootDir": "src",
"outDir": "."
},
"include": [
"src/*.ts"
]
}