mirror of
https://github.com/material-components/material-web.git
synced 2024-10-27 22:17:25 +03:00
Merge pull request #145 from material-components/typescript-updates
Update slider and snackbar to mdc v0.40 and typescript
This commit is contained in:
commit
960329a650
@ -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
61
packages/slider/README.md
Normal 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.
|
@ -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>`;
|
@ -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);
|
@ -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": {
|
||||
|
@ -20,4 +20,5 @@ limitations under the License.
|
||||
:host {
|
||||
display: inline-block;
|
||||
min-width: 120px;
|
||||
outline: none;
|
||||
}
|
204
packages/slider/src/mwc-slider.ts
Normal file
204
packages/slider/src/mwc-slider.ts
Normal 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();
|
||||
}
|
||||
}
|
10
packages/slider/tsconfig.json
Normal file
10
packages/slider/tsconfig.json
Normal file
@ -0,0 +1,10 @@
|
||||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"rootDir": "src",
|
||||
"outDir": "."
|
||||
},
|
||||
"include": [
|
||||
"src/*.ts"
|
||||
]
|
||||
}
|
61
packages/snackbar/README.md
Normal file
61
packages/snackbar/README.md
Normal 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.
|
@ -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>`;
|
@ -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);
|
@ -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": {
|
||||
|
159
packages/snackbar/src/mwc-snackbar.ts
Normal file
159
packages/snackbar/src/mwc-snackbar.ts
Normal 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);
|
||||
}
|
||||
}
|
10
packages/snackbar/tsconfig.json
Normal file
10
packages/snackbar/tsconfig.json
Normal file
@ -0,0 +1,10 @@
|
||||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"rootDir": "src",
|
||||
"outDir": "."
|
||||
},
|
||||
"include": [
|
||||
"src/*.ts"
|
||||
]
|
||||
}
|
Loading…
Reference in New Issue
Block a user