this._trackMouseEvent());
+ }
+
private onPointerUp(ev: PointerEvent): void {
// Retain focus on input element after mouse up to enable keyboard interactions
this.input.focus();
@@ -190,14 +228,31 @@ export class Slider extends Focusable {
this.dispatchChangeEvent();
}
+ private onMouseUp = (ev: MouseEvent): void => {
+ // Retain focus on input element after mouse up to enable keyboard interactions
+ this.input.focus();
+ this.currentMouseEvent = ev;
+ document.removeEventListener('mousemove', this.onMouseMove);
+ document.removeEventListener('mouseup', this.onMouseUp);
+ requestAnimationFrame(() => {
+ this.handleHighlight = false;
+ this.dragging = false;
+ this.dispatchChangeEvent();
+ });
+ };
+
private onPointerMove(ev: PointerEvent): void {
if (!this.dragging) {
return;
}
this.value = this.calculateHandlePosition(ev);
- this.dispatchInputEvent();
}
+ private onMouseMove = (ev: MouseEvent): void => {
+ this.currentMouseEvent = ev;
+ this.dispatchInputEvent();
+ };
+
private onPointerCancel(ev: PointerEvent): void {
this.dragging = false;
this.handle.releasePointerCapture(ev.pointerId);
@@ -218,6 +273,20 @@ export class Slider extends Focusable {
this.dispatchInputEvent();
}
+ private onTrackMouseDown(ev: MouseEvent): void {
+ if (this.supportsPointerEvent) {
+ return;
+ }
+ if (ev.target === this.handle || this.disabled) {
+ return;
+ }
+ document.addEventListener('mousemove', this.onMouseMove);
+ document.addEventListener('mouseup', this.onMouseUp);
+ this.dragging = true;
+ this.currentMouseEvent = ev;
+ this._trackMouseEvent();
+ }
+
/**
* Keep the slider value property in sync with the input element's value
*/
@@ -243,7 +312,7 @@ export class Slider extends Focusable {
* @param: PointerEvent on slider
* @return: Slider value that correlates to the position under the pointer
*/
- private calculateHandlePosition(ev: PointerEvent): number {
+ private calculateHandlePosition(ev: PointerEvent | MouseEvent): number {
const rect = this.getBoundingClientRect();
const minOffset = rect.left;
const offset = ev.clientX;
diff --git a/packages/slider/stories/slider.stories.ts b/packages/slider/stories/slider.stories.ts
index 579890f066..cbb9cb4cfd 100644
--- a/packages/slider/stories/slider.stories.ts
+++ b/packages/slider/stories/slider.stories.ts
@@ -101,7 +101,7 @@ storiesOf('Slider', module)
.add('Focus tab demo', () => {
const value = number('Value', 50);
const min = number('Min', 0);
- const max = number('Min', 100);
+ const max = number('Max', 100);
const step = number('Step', 1);
return html`
diff --git a/packages/slider/test/slider.test.ts b/packages/slider/test/slider.test.ts
index 29397baea9..1b6ab923f1 100644
--- a/packages/slider/test/slider.test.ts
+++ b/packages/slider/test/slider.test.ts
@@ -12,7 +12,17 @@ governing permissions and limitations under the License.
import '../';
import { Slider } from '../';
-import { fixture, elementUpdated, html, expect } from '@open-wc/testing';
+import {
+ fixture,
+ elementUpdated,
+ html,
+ expect,
+ nextFrame,
+} from '@open-wc/testing';
+
+type TestableSliderType = {
+ supportsPointerEvent: boolean;
+};
describe('Slider', () => {
it('loads', async () => {
@@ -94,6 +104,7 @@ describe('Slider', () => {
pointerId: 2,
})
);
+ document.dispatchEvent(new MouseEvent('mouseup'));
await elementUpdated(el);
expect(el.dragging).to.be.false;
@@ -120,6 +131,61 @@ describe('Slider', () => {
expect(el.dragging).to.be.false;
expect(pointerId).to.equal(3);
});
+ it('will fallback to mouse events', async () => {
+ const el = await fixture(
+ html`
+
+ `
+ );
+ const supportsPointerEvent = ((el as unknown) as TestableSliderType)
+ .supportsPointerEvent;
+ ((el as unknown) as TestableSliderType).supportsPointerEvent = false;
+
+ await elementUpdated(el);
+
+ expect(el.value).to.equal(10);
+
+ const handle = el.shadowRoot
+ ? (el.shadowRoot.querySelector('#handle') as HTMLDivElement)
+ : (el as Slider);
+
+ handle.dispatchEvent(
+ new MouseEvent('mousedown', {
+ clientX: 131,
+ })
+ );
+ await elementUpdated(el);
+ await nextFrame();
+ await nextFrame();
+
+ expect(el.value).to.equal(5);
+
+ await elementUpdated(el);
+
+ document.dispatchEvent(
+ new MouseEvent('mousemove', {
+ clientX: 200,
+ })
+ );
+ await elementUpdated(el);
+ await nextFrame();
+ await nextFrame();
+
+ expect(el.value).to.equal(8);
+
+ document.dispatchEvent(
+ new MouseEvent('mouseup', {
+ clientX: 131,
+ })
+ );
+ await elementUpdated(el);
+ await nextFrame();
+ await nextFrame();
+
+ expect(el.value).to.equal(5);
+
+ ((el as unknown) as TestableSliderType).supportsPointerEvent = supportsPointerEvent;
+ });
it('will `trackPointerDown` on `#controls`', async () => {
let pointerId = -1;
const el = await fixture(
@@ -151,6 +217,34 @@ describe('Slider', () => {
expect(pointerId).to.equal(4);
expect(el.value).to.equal(1);
});
+ it('will fallback to `trackMouseDown` on `#controls`', async () => {
+ const el = await fixture(
+ html`
+
+ `
+ );
+ const supportsPointerEvent = ((el as unknown) as TestableSliderType)
+ .supportsPointerEvent;
+ ((el as unknown) as TestableSliderType).supportsPointerEvent = false;
+
+ await elementUpdated(el);
+
+ expect(el.value).to.equal(10);
+
+ const controls = el.shadowRoot
+ ? (el.shadowRoot.querySelector('#controls') as HTMLDivElement)
+ : (el as Slider);
+
+ controls.dispatchEvent(
+ new MouseEvent('mousedown', {
+ clientX: 50,
+ })
+ );
+ await elementUpdated(el);
+
+ expect(el.value).to.equal(1);
+ ((el as unknown) as TestableSliderType).supportsPointerEvent = supportsPointerEvent;
+ });
it('can be disabled', async () => {
let pointerId = -1;
const el = await fixture(
diff --git a/scripts/process-spectrum-css.js b/scripts/process-spectrum-css.js
index 2deb94faf8..a283111a00 100755
--- a/scripts/process-spectrum-css.js
+++ b/scripts/process-spectrum-css.js
@@ -17,6 +17,7 @@ const path = require('path');
const chalk = require('chalk');
const fs = require('fs-extra');
const postcss = require('postcss');
+const { postCSSPlugins } = require('./css-processing');
const postcssSpectrumPlugin = require('./process-spectrum-postcss-plugin');
const reporter = require('postcss-reporter');
@@ -25,9 +26,21 @@ const componentRoot = path.resolve(__dirname, '../packages');
async function processComponent(componentPath) {
const configPath = path.join(componentPath, 'spectrum-config.js');
const spectrumConfig = require(configPath);
- const inputCssPath = require.resolve(
- `@adobe/spectrum-css/dist/components/${spectrumConfig.spectrum}/index-vars.css`
- );
+ let inputCssPath;
+ let packageCss = false;
+ try {
+ inputCssPath = require.resolve(
+ `@spectrum-css/${spectrumConfig.spectrum}/dist/index-vars.css`
+ );
+ packageCss = true;
+ } catch (e) {
+ console.log(
+ `${spectrumConfig.spectrum} uses the repo level Spectrum CSS import...`
+ );
+ inputCssPath = require.resolve(
+ `@adobe/spectrum-css/dist/components/${spectrumConfig.spectrum}/index-vars.css`
+ );
+ }
const inputCss = await fs.readFile(inputCssPath);
console.log(chalk.bold.green(`- ${spectrumConfig.spectrum}`));
return Promise.all(
@@ -37,6 +50,7 @@ async function processComponent(componentPath) {
`spectrum-${component.name}.css`
);
const outputCss = await postcss([
+ ...(packageCss ? postCSSPlugins() : []),
postcssSpectrumPlugin({ component }),
reporter(),
]).process(inputCss, {
diff --git a/yarn.lock b/yarn.lock
index 63778bbe05..afbcc7ab73 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1990,6 +1990,11 @@
resolved "https://registry.yarnpkg.com/@sinonjs/text-encoding/-/text-encoding-0.7.1.tgz#8da5c6530915653f3a1f38fd5f101d8c3f8079c5"
integrity sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==
+"@spectrum-css/actionbar@^2.0.0-alpha.6":
+ version "2.0.0-alpha.6"
+ resolved "https://registry.yarnpkg.com/@spectrum-css/actionbar/-/actionbar-2.0.0-alpha.6.tgz#03e1f38f265d0e90447e692d135619ec8515c494"
+ integrity sha512-VgK9efs0Wejg9JrmYY+qG9ptL+JkqPuw0e00yRTPoS3/J//pTUlR2maoRTpOWk2BSjb49b2VRPCTQnLbKPo6MA==
+
"@storybook/addon-a11y@5.2.1":
version "5.2.1"
resolved "https://registry.yarnpkg.com/@storybook/addon-a11y/-/addon-a11y-5.2.1.tgz#4ab013ea7910189cdbfc2dbfecdd6c2dab5f04d8"
@@ -11085,6 +11090,11 @@ memory-fs@^0.4.0, memory-fs@^0.4.1:
errno "^0.1.3"
readable-stream "^2.0.1"
+memorystream@^0.3.1:
+ version "0.3.1"
+ resolved "https://registry.yarnpkg.com/memorystream/-/memorystream-0.3.1.tgz#86d7090b30ce455d63fbae12dda51a47ddcaf9b2"
+ integrity sha1-htcJCzDORV1j+64S3aUaR93K+bI=
+
meow@5.0.0, meow@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/meow/-/meow-5.0.0.tgz#dfc73d63a9afc714a5e371760eb5c88b91078aa4"
@@ -11791,6 +11801,21 @@ npm-pick-manifest@^3.0.0:
npm-package-arg "^6.0.0"
semver "^5.4.1"
+npm-run-all@^4.1.5:
+ version "4.1.5"
+ resolved "https://registry.yarnpkg.com/npm-run-all/-/npm-run-all-4.1.5.tgz#04476202a15ee0e2e214080861bff12a51d98fba"
+ integrity sha512-Oo82gJDAVcaMdi3nuoKFavkIHBRVqQ1qvMb+9LHk/cF4P6B2m8aP04hGf7oL6wZ9BuGwX1onlLhpuoofSyoQDQ==
+ dependencies:
+ ansi-styles "^3.2.1"
+ chalk "^2.4.1"
+ cross-spawn "^6.0.5"
+ memorystream "^0.3.1"
+ minimatch "^3.0.4"
+ pidtree "^0.3.0"
+ read-pkg "^3.0.0"
+ shell-quote "^1.6.1"
+ string.prototype.padend "^3.0.0"
+
npm-run-path@^2.0.0:
version "2.0.2"
resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f"
@@ -12536,6 +12561,11 @@ picomatch@^2.0.4, picomatch@^2.0.5:
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.0.7.tgz#514169d8c7cd0bdbeecc8a2609e34a7163de69f6"
integrity sha512-oLHIdio3tZ0qH76NybpeneBhYVj0QFTfXEFTc/B3zKQspYfYYkWYgFsmzo+4kvId/bQRcNkVeguI3y+CD22BtA==
+pidtree@^0.3.0:
+ version "0.3.0"
+ resolved "https://registry.yarnpkg.com/pidtree/-/pidtree-0.3.0.tgz#f6fada10fccc9f99bf50e90d0b23d72c9ebc2e6b"
+ integrity sha512-9CT4NFlDcosssyg8KVFltgokyKZIFjoBxw8CTGy+5F38Y1eQWrt8tRayiUOXE+zVKQnYu5BR8JjCtvK3BcnBhg==
+
pify@^2.0.0, pify@^2.3.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c"
@@ -15135,7 +15165,7 @@ shebang-regex@^1.0.0:
resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3"
integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=
-shell-quote@1.7.2:
+shell-quote@1.7.2, shell-quote@^1.6.1:
version "1.7.2"
resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.7.2.tgz#67a7d02c76c9da24f99d20808fcaded0e0e04be2"
integrity sha512-mRz/m/JVscCrkMyPqHc/bczi3OQHkLTqXHEFu0zDhK/qfv3UcOA4SVmRCLmos4bhjr9ekVQubj/R7waKapmiQg==