diff --git a/Gruntfile.js b/Gruntfile.js index 0f1da875..74634002 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -272,6 +272,8 @@ module.exports = function(grunt) { // Default task - prints to the console the tasks that are available to be run from the command line // grunt.registerTask('default', function() { + grunt.log.writeln('The Basic Web Components project now uses gulp rather than grunt.'); + /* grunt.log.writeln('grunt commands this project supports:\n'); grunt.log.writeln(' grunt build (builds consolidated basic-web-components.js, all package distributions, all documentation, and all tests)'); grunt.log.writeln(' grunt devbuild (same as build minus building the documentation)'); @@ -281,6 +283,7 @@ module.exports = function(grunt) { grunt.log.writeln(' grunt set-version:version (updates package.json version values and dependencies. Ex: grunt set-version:1.0.30)'); grunt.log.writeln(' grunt saucelabs (Runs SauceLabs tests. You must set environment variables SAUCE_USERNAME and SAUCE_ACCESS_KEY.)'); grunt.log.writeln(' grunt watch (builds and watches changes to project files)'); + */ }); // @@ -294,14 +297,14 @@ module.exports = function(grunt) { // // This task makes use of the buildList global array. // - grunt.registerTask('build', ['browserify:buildFiles', 'docs', 'jshint']); + // grunt.registerTask('build', ['browserify:buildFiles', 'docs', 'jshint']); // // The devbuild task is callable from the command line and is similar to the build task but doesn't // build the documentation files. This is meant as a quicker task for developers actively working // on code. // - grunt.registerTask('devbuild', ['browserify:buildFiles', 'jshint']); + // grunt.registerTask('devbuild', ['browserify:buildFiles', 'jshint']); // // The docs task is callable from the command line. This task builds each package's @@ -309,6 +312,7 @@ module.exports = function(grunt) { // // This task makes use of the docsList global array. // + /* grunt.registerTask('docs', function() { const done = this.async(); return mapAndChain(docsList, doc => buildMarkdownDoc(doc, grunt)) @@ -319,30 +323,31 @@ module.exports = function(grunt) { grunt.log.error(err) ); }); + */ // // The lint task is callable from the command line and executes the jshint task defined // in the Grunt config. This task looks for JavaScript warnings/errors. // - grunt.registerTask('lint', ['jshint']); + // grunt.registerTask('lint', ['jshint']); // // The saucelabs task is callable from the command line and executes unit tests on SauceLabs // - grunt.registerTask('saucelabs', ['connect', 'saucelabs-mocha']); + // grunt.registerTask('saucelabs', ['connect', 'saucelabs-mocha']); // // The test task is callable from the command line and executes the mocha task defined // in the Grunt config. This task executes the monorepo's test suite. // - grunt.registerTask('test', ['mocha']); + // grunt.registerTask('test', ['mocha']); // // The watch task is callable from the command line and executes the browserify:watch task // defined in the Grunt config. This task performs a build and then watches for changes // for instant update during development. // - grunt.registerTask('watch', ['browserify:watch']); + // grunt.registerTask('watch', ['browserify:watch']); // // The npm-publish task is callable from the command line and performs a publish operation diff --git a/README.md b/README.md index 86304076..8532114d 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,21 @@ +**NOTE** (2017 May 24): This project has been subsumed by the +[Elix](https://github.com/elix/elix) web components library. Elix has the +same core principles, but has an expanded, more open governance model which we +hope will help Elix find broad adoption. Elix uses the same mixin architecture +as Basic Web Components, and many of the components and mixins from Basic Web +Components are being migrated to Elix. We have stopped active development on +Basic Web Components so that we can concentrate on Elix. Thank you for your +support and interest in Basic Web Components, and apologies for any +inconvenience caused by this change. + # basic-web-components The Basic Web Components project seeks to provide a comprehensive set of solid, well-designed web components that implement very common user interface patterns. Each component can be used as is, or as the foundation for new components. -_Note: The master branch of this project targets **Shadow DOM version 1** and -**Custom Elements version 1**. Currently, the only browser that supports those +_The master branch of this project targets Shadow DOM version 1 and +Custom Elements version 1. Currently, the only browser that supports those specifications well enough is Google Chrome. That is currently the only browser in which all unit tests pass and all components work properly. We will be adding support for Safari Technology Preview and the version 1 polyfills as those diff --git a/gulp/lib/allPackages.js b/gulp/lib/allPackages.js new file mode 100644 index 00000000..fa406332 --- /dev/null +++ b/gulp/lib/allPackages.js @@ -0,0 +1,19 @@ +/*jslint node: true */ +'use strict'; + +const fs = require('fs'); +const path = require('path'); + +// +// allPackages is the global array of npm-publishable packages in this monorepo. +// This is all folders inside the ./packages folder that start with the prefix +// "basic-". +// +const PACKAGE_FOLDER = './packages'; +const allPackages = fs.readdirSync(PACKAGE_FOLDER).filter(fileName => { + const filePath = path.join(PACKAGE_FOLDER, fileName); + const stat = fs.statSync(filePath); + return stat && stat.isDirectory() && fileName.startsWith('basic-'); +}); + +module.exports = allPackages; \ No newline at end of file diff --git a/gulp/tasks/browserify.js b/gulp/tasks/browserify.js new file mode 100644 index 00000000..a5cc1901 --- /dev/null +++ b/gulp/tasks/browserify.js @@ -0,0 +1,126 @@ +/*jslint node: true */ +'use strict'; + +const gulp = require('gulp'); +const gutil = require('gulp-util'); +const glob = require('glob'); +const babelify = require('babelify') +const browserify = require('browserify'); +const watchify = require('watchify'); +const buffer = require('vinyl-buffer'); +const vinylStream = require('vinyl-source-stream'); +const sourceMaps = require('gulp-sourcemaps'); +const uglify = require('gulp-uglify'); +const allPackages = require('../lib/allPackages'); + +// +// Build the global buildList object for use in browserifyTask +// +function buildBuildList() { + const buildList = { + 'build/tests.js': allPackages.map(pkg => `packages/${pkg}/test/*.js`) + }; + allPackages.forEach(pkg => { + buildList[`packages/${pkg}/dist/${pkg}.js`] = [`packages/${pkg}/globals.js`]; + }); + buildList['packages/demos/dist/demos.js'] = ['packages/demos/src/*.js']; + return buildList; +} +const buildList = buildBuildList(); + +const watchifyTask = function(done) { + browserifyHelperTask(true, done); +} + +const browserifyTask = function(done) { + browserifyHelperTask(false, done); +} + +const browserifyHelperTask = function(watch, done) { + let processedCount = 0; + let bundlerCount = 0; + let bundlers = []; + + function bundleIt(bundler) { + bundler.bundler + .bundle() + .pipe(vinylStream(bundler.outputFile)) + .pipe(buffer()) // Convert to gulp pipeline + .pipe(sourceMaps.init({loadMaps : true})) // Strip inline source maps + .pipe(uglify()) // Minimize + .on('error', gutil.log) + .pipe(sourceMaps.write('./')) // Relative to bundler.outputDir below + .pipe(gulp.dest(bundler.outputDir)) + .on('end', function() { + gutil.log(`Processed ${bundler.source} and wrote ${bundler.outputDir}${bundler.outputFile}`); + processedCount++; + if (processedCount >= bundlerCount) { + if (watch) { + // Do not call task completion callback in the watch case + gutil.log('Now watching for changes...') + } + else { + done(); + } + } + }); + } + + gutil.log('Preparing build...'); + + for (let key in buildList) { + let entries = []; + + buildList[key].forEach(globItem => { + let a = glob.sync(globItem); + Array.prototype.push.apply(entries, a); + }); + + const props = watch ? { + entries: entries, + debug: true, + cache: {}, + packageCache: {}, + plugin: [watchify] + } : { + entries: entries, + debug: true + } + + let bundler = browserify(props); + if (watch) { + bundler.on('update', function() { + bundleIt(this.bundlerData); + }); + } + + let bundlerData = { + bundler: bundler, + source: entries, + outputFile: key.split('/').pop(), + outputDir: key.substring(0, key.lastIndexOf('/') + 1) + }; + + // Attach bundlerData to the bundler object so we can fetch + // details about the bundler in the update event + bundler.bundlerData = bundlerData; + + bundlers.push(bundlerData); + } + + bundlerCount = bundlers.length; + + bundlers.forEach(bundler => { + // + // Remember: we have .babelrc in the root specifying the ES2015 preset, + // and the babelify transform specified in package.json. + // This was necessary for the Grunt build. The following line is + // therefore unnecessary: + // + // bundler.bundler.transform(babelify, {presets: ['es2015']}); + + bundleIt(bundler); + }); +}; + +module.exports = {browserifyTask: browserifyTask, watchifyTask: watchifyTask}; \ No newline at end of file diff --git a/gulp/tasks/docs.js b/gulp/tasks/docs.js new file mode 100644 index 00000000..43161022 --- /dev/null +++ b/gulp/tasks/docs.js @@ -0,0 +1,184 @@ +/*jslint node: true */ +'use strict'; + +const fs = require('fs'); +const jsDocParse = require('jsdoc-parse'); +const dmd = require('dmd'); +const Readable = require('stream').Readable; +const gutil = require('gulp-util'); +const allPackages = require('../lib/allPackages'); + +// +// Build the global docsList array for use in building the package's README.md documentation +// +function buildDocsList() { + const packagesWithoutBuiltDocs = [ + 'basic-component-mixins', + 'basic-web-components' + ]; + const ary = allPackages.filter(item => { + return packagesWithoutBuiltDocs.indexOf(item) < 0; + }).map(item => { + return { + src: `packages/${item}/src/*.js`, + dest: `packages/${item}/README.md`}; + }); + + return ary.concat(buildMixinsDocsList()); +} +const docsList = buildDocsList(); + +// +// Build the portion of docsList that represents the individual source files within +// the basic-component-mixins directory. +// +function buildMixinsDocsList() { + return fs.readdirSync('packages/basic-component-mixins/src').filter(file => { + return file.indexOf('.js') == file.length - 3; + }).map(file => { + const fileRoot = file.replace('.js', ''); + return { + src: `packages/basic-component-mixins/src/${file}`, + dest: `packages/basic-component-mixins/docs/${fileRoot}.md` }; + }); +} + +function buildMarkdownDoc(docItem) { + gutil.log('Building ' + docItem.dest + ' from ' + docItem.src); + + return parseScriptToJSDocJSON(docItem.src) + .then(json => { + return mergeMixinDocs(json); + }) + .then(json => { + // Sort the array, leaving the order:0 item alone at the + // front of the list (the class identifier section) + json.sort((a, b) => { + if (a.order === 0) { return -1; } + if (b.order === 0) { return 1; } + + return a.name.localeCompare(b.name); + }); + + // Set the order value + json.map((item, index) => { + item.order = index; + }); + + // Convert the JSON to Markdown + return parseJSONToMarkdown(json); + }) + .then(function(string) { + // Write to the output markdown file + return new Promise(function(resolve, reject) { + fs.writeFile(docItem.dest, string, 'utf-8', function (err) { + if (err) { + return reject(err); + } + resolve(); + }); + }); + }); +} + +function parseScriptToJSDocJSON(src) { + return new Promise((resolve, reject) => { + // Start by parsing the jsdoc into a stream which will contain + // the jsdoc represented in JSON + const stream = jsDocParse({src: src}); + + // Convert the stream to jsdoc JSON + let string = ''; + stream.setEncoding('utf8'); + stream.on('data', chunk => { + string += chunk; + }) + .on('end', () => { + const json = JSON.parse(string); + resolve(json); + }) + .on('error', err => { + reject(err); + }); + }); +} + +function parseJSONToMarkdown(json) { + return new Promise(function(resolve, reject) { + // Create a new readable stream, holding the stringified JSON + let string = ''; + const s = new Readable(); + s._read = function noop() {}; + s.push(JSON.stringify(json)); + s.push(null); + + // Use dmd to create the markdown string which we will + // write to an output .md file (NYI) + const partials = [ + './gulp/templates/main.hbs', + './gulp/templates/scope.hbs', + './gulp/templates/mixes.hbs', + './gulp/templates/mixin-linked-type-list.hbs']; + const dmdStream = dmd({partial: partials, 'global-index-format': 'none', 'group-by': ['none']}); + s.pipe(dmdStream); + dmdStream.setEncoding('utf8'); + dmdStream.on('data', data => { + string += data; + }) + .on('end', () => { + // string now holds the markdown text + resolve(string); + }) + .on('error', err => { + reject(err); + }); + }); +} + +function mergeMixinDocs(componentJson) { + if (componentJson[0].mixes == null || componentJson[0].mixes === undefined) { + return componentJson; + } + + const mixins = componentJson[0].mixes.map(mixin => { + return 'packages/basic-component-mixins/src/' + mixin + '.js'; + }); + + const hostId = componentJson[0].id; + return mapAndChain(mixins, mixin => mergeMixinIntoBag(mixin, componentJson, hostId)) + .then(() => + componentJson + ); +} + +function mergeMixinIntoBag(mixinPath, componentJson, hostId) { + return parseScriptToJSDocJSON(mixinPath) + .then(mixinJson => { + for (let i = 1; i < mixinJson.length; i++) { + if (mixinJson[i].memberof != null && mixinJson[i].memberof != hostId) { + mixinJson[i].originalmemberof = mixinJson[i].memberof; + mixinJson[i].memberof = hostId; + } + componentJson.push(mixinJson[i]); + } + }); +} + +// Apply the given promise-returning function to each member of the array. +// Ensure each promise completes before starting the next one to avoid +// spinning up too many file operations at once. This is effectively like +// Promise.all(), while ensuring that the items are processed in a completely +// sequential order. +function mapAndChain(array, promiseFn) { + // Start the promise chain with a resolved promise. + return array.reduce((chain, item) => chain.then(() => promiseFn(item)), Promise.resolve()); +} + + +const docsTask = function() { + return mapAndChain(docsList, doc => buildMarkdownDoc(doc)) + .then(() => gutil.log('All documentation complete')) + .catch(err => gutil.log(`error: ${err}`)); +}; + +module.exports = docsTask; \ No newline at end of file diff --git a/gulp/tasks/help.js b/gulp/tasks/help.js new file mode 100644 index 00000000..f0af0996 --- /dev/null +++ b/gulp/tasks/help.js @@ -0,0 +1,24 @@ +/*jslint node: true */ +'use strict'; + +const gulp = require('gulp'); +const gutil = require('gulp-util'); + +// +// Help task - prints to the console the tasks that are available to be run from the command line +// +function helpTask() { + gutil.log(`gulp commands this project supports: + + gulp build (builds all packages, docs, and tests) + gulp devbuild (same as build minus building the documentation) + gulp docs (builds all packages README.md files) + gulp lint (runs jshint on all .js files) + gulp watch (builds and watches changes to project files) + `); + // gulp npm-publish:package-name|* (publishes packages/package-name or all packages (packages/*) to npm) + // gulp set-version:version (updates package.json version values and dependencies. Ex: gulp set-version:1.0.30) + // gulp saucelabs (Runs SauceLabs tests. You must set environment variables SAUCE_USERNAME and SAUCE_ACCESS_KEY.) +} + +module.exports = helpTask; \ No newline at end of file diff --git a/gulp/tasks/lint.js b/gulp/tasks/lint.js new file mode 100644 index 00000000..7ba04af6 --- /dev/null +++ b/gulp/tasks/lint.js @@ -0,0 +1,23 @@ +/*jslint node: true */ +'use strict'; + +const gulp = require('gulp'); +const gutil = require('gulp-util'); +const jshint = require('gulp-jshint'); + +const lintTask = function() { + const lintFiles = [ + 'gulpfile.js', + 'packages/**/*.js', + '!packages/**/dist/**', + '!packages/**/lib/**', + '!packages/**/bower_components/**', + 'test/**/*.js' + ]; + + return gulp.src(lintFiles) + .pipe(jshint()) + .pipe(jshint.reporter('default')); +} + +module.exports = lintTask; \ No newline at end of file diff --git a/gulp/templates/main.hbs b/gulp/templates/main.hbs new file mode 100644 index 00000000..9cc0bbd4 --- /dev/null +++ b/gulp/templates/main.hbs @@ -0,0 +1,3 @@ +# API Documentation +{{>main-index~}} +{{>all-docs~}} \ No newline at end of file diff --git a/gulp/templates/mixes.hbs b/gulp/templates/mixes.hbs new file mode 100644 index 00000000..42e144ae --- /dev/null +++ b/gulp/templates/mixes.hbs @@ -0,0 +1,3 @@ +{{#if mixes~}} + **Mixes**: {{>mixin-linked-type-list types=mixes delimiter=", " }} +{{/if}} \ No newline at end of file diff --git a/gulp/templates/mixin-linked-type-list.hbs b/gulp/templates/mixin-linked-type-list.hbs new file mode 100644 index 00000000..8a6cbd0f --- /dev/null +++ b/gulp/templates/mixin-linked-type-list.hbs @@ -0,0 +1,4 @@ +{{#each types~}} + [{{this}}](../basic-component-mixins/docs/{{this}}.md) + {{#unless @last}}{{{../../delimiter}}}{{/unless~}} +{{/each}} \ No newline at end of file diff --git a/gulp/templates/scope.hbs b/gulp/templates/scope.hbs new file mode 100644 index 00000000..0649a0d3 --- /dev/null +++ b/gulp/templates/scope.hbs @@ -0,0 +1,12 @@ +{{#if scope}} + **Kind**: {{#if (equal kind "event") ~}} + event emitted{{#if memberof}} by {{#if originalmemberof}}{{>link to=memberof}}. Defined by [{{originalmemberof}}](../basic-component-mixins/docs/{{originalmemberof}}.md) mixin.{{else~}} + {{>link to=memberof}}{{/if}}{{/if}} + {{else~}} + {{scope}} {{#if virtual}}abstract {{/if}}{{kindInThisContext}}{{#if memberof}} of {{#if originalmemberof}}{{>link to=memberof}}. Defined by [{{originalmemberof}}](../basic-component-mixins/docs/{{originalmemberof}}.md) mixin.{{else~}} + {{>link to=memberof}}{{/if}}{{/if}} + {{/if~}} + {{else~}} + {{#if isExported}}**Kind**: Exported {{kind}} + {{/if~}} +{{/if~}} \ No newline at end of file diff --git a/gulpfile.js b/gulpfile.js new file mode 100644 index 00000000..ff007a33 --- /dev/null +++ b/gulpfile.js @@ -0,0 +1,36 @@ +/*jslint node: true */ +'use strict'; + +const gulp = require('gulp'); + +const browserifyTask = require('./gulp/tasks/browserify').browserifyTask; +const watchifyTask = require('./gulp/tasks/browserify').watchifyTask; +const docsTask = require('./gulp/tasks/docs'); +const helpTask = require('./gulp/tasks/help'); +const lintTask = require('./gulp/tasks/lint'); + +// +// Naming convention for tasks: +// taskName[-taskDependency[-taskDependency-[...]]] +// +// Example: +// lint: Simply runs the lint task +// lint-browserify: Runs the lint task with a dependency on browserify +// lint-docs-browserify: Runs the lint taks with a dependency first on docs, +// then browserify +// + +// Private +gulp.task('browserify', [], browserifyTask); +gulp.task('docs-browserify', ['browserify'], docsTask); +gulp.task('help', [], helpTask); +gulp.task('lint-docs-browserify', ['docs-browserify'], lintTask); +gulp.task('lint-browserify', ['browserify'], lintTask); + +// Public +gulp.task('build', ['browserify', 'docs-browserify', 'lint-docs-browserify']); +gulp.task('devbuild', ['browserify', 'lint-browserify']); +gulp.task('default', ['help']); +gulp.task('docs', [], docsTask); +gulp.task('lint', [], lintTask); +gulp.task('watch', [], watchifyTask); diff --git a/package.json b/package.json index 03d87193..8c9ff61c 100644 --- a/package.json +++ b/package.json @@ -9,8 +9,12 @@ }, "author": "info@component.kitchen", "dependencies": { + "web-animations-js": "^2.2.1" + }, + "devDependencies": { "babel-preset-es2015": "^6.6.0", "babelify": "^7.3.0", + "browserify": "^13.1.1", "chai": "^3.5.0", "grunt": "^0.4.5", "grunt-browserify": "^4.0.1", @@ -20,10 +24,18 @@ "grunt-contrib-jshint": "^0.11.3", "grunt-contrib-watch": "^0.6.1", "grunt-jsdoc-to-markdown": "^1.2.0", - "grunt-mocha": "^0.4.15", + "grunt-mocha": "^1.0.2", "grunt-saucelabs": "^8.6.2", "grunt-shell": "^1.1.2", - "web-animations-js": "^2.2.1" + "gulp": "^3.9.1", + "gulp-jshint": "^2.0.3", + "gulp-rename": "^1.2.2", + "gulp-sourcemaps": "^2.2.0", + "gulp-uglify": "^2.0.0", + "gulp-util": "^3.0.7", + "vinyl-buffer": "^1.0.0", + "vinyl-source-stream": "^1.1.0", + "watchify": "^3.7.0" }, "browserify": { "transform": [ diff --git a/packages/basic-animation-stage/README.md b/packages/basic-animation-stage/README.md index 3456fd00..00ee4d2b 100644 --- a/packages/basic-animation-stage/README.md +++ b/packages/basic-animation-stage/README.md @@ -7,7 +7,7 @@ selection changes. The same animation can be shown at an arbitrary point, generally used to reflect a user-controlled touch or trackpad drag operation in progress. -[Live demo](http://basicwebcomponents.org/basic-web-components/packages/basic-animation-stage/) +[Live demo](http://basicwebcomponents.org/basic-web-components/packages/demos/animation-stage-with-dots.html) This component is intended to be used as a programmatic rendering surface for components which want to show transitional effects. diff --git a/packages/basic-animation-stage/dist/basic-animation-stage.js b/packages/basic-animation-stage/dist/basic-animation-stage.js index df3d71e3..2e7b1c28 100644 --- a/packages/basic-animation-stage/dist/basic-animation-stage.js +++ b/packages/basic-animation-stage/dist/basic-animation-stage.js @@ -1,3339 +1,3 @@ -(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o\n :host {\n overflow: hidden;\n position: relative;\n }\n\n #container ::slotted(*) {\n height: 100%;\n object-fit: contain;\n position: absolute;\n width: 100%;\n will-change: transform;\n }\n \n\n
\n \n
\n '; - } - }]); - - return AnimationStage; -}(base); - -customElements.define('basic-animation-stage', AnimationStage); -exports.default = AnimationStage; - -},{"../../basic-component-mixins/src/ContentItemsMixin":5,"../../basic-component-mixins/src/DistributedChildrenContentMixin":6,"../../basic-component-mixins/src/FractionalSelectionMixin":8,"../../basic-component-mixins/src/SelectionAnimationMixin":9,"../../basic-component-mixins/src/SelectionAriaActiveMixin":10,"../../basic-component-mixins/src/SingleSelectionMixin":13,"../../basic-component-mixins/src/symbols":17,"../../basic-element-base/src/ElementBase":19}],3:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); - -var _get = function get(object, property, receiver) { if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } }; - -var _safeAttributes = require('./safeAttributes'); - -var _safeAttributes2 = _interopRequireDefault(_safeAttributes); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - -function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } - -function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } - -// Memoized maps of attribute to property names and vice versa. -var attributeToPropertyNames = {}; -var propertyNamesToAttributes = {}; - -/* Exported function extends a base class with AttributeMarshalling. */ - -exports.default = function (base) { - - /** - * Mixin which marshalls attributes to properties and vice versa. - * - * If your component exposes a setter for a property, it's generally a good - * idea to let devs using your component be able to set that property in HTML - * via an element attribute. You can code that yourself by writing an - * `attributeChangedCallback`, or you can use this mixin to get a degree of - * automatic support. - * - * This mixin implements an `attributeChangedCallback` that will attempt to - * convert a change in an element attribute into a call to the corresponding - * property setter. Attributes typically follow hyphenated names ("foo-bar"), - * whereas properties typically use camelCase names ("fooBar"). This mixin - * respects that convention, automatically mapping the hyphenated attribute - * name to the corresponding camelCase property name. - * - * Example: You define a component using this mixin: - * - * class MyElement extends AttributeMarshallingMixin(HTMLElement) { - * get fooBar() { return this._fooBar; } - * set fooBar(value) { this._fooBar = value; } - * } - * customElements.define('my-element', MyElement); - * - * If someone then instantiates your component in HTML: - * - * - * - * Then, after the element has been upgraded, the `fooBar` setter will - * automatically be invoked with the initial value "Hello". - * - * For the time being, this mixin only supports string-valued properties. - * If you'd like to convert string attributes to other types (numbers, - * booleans), you need to implement `attributeChangedCallback` yourself. - */ - var AttributeMarshalling = function (_base) { - _inherits(AttributeMarshalling, _base); - - function AttributeMarshalling() { - _classCallCheck(this, AttributeMarshalling); - - return _possibleConstructorReturn(this, (AttributeMarshalling.__proto__ || Object.getPrototypeOf(AttributeMarshalling)).apply(this, arguments)); - } - - _createClass(AttributeMarshalling, [{ - key: 'attributeChangedCallback', - - - /* - * Handle a change to the attribute with the given name. - */ - value: function attributeChangedCallback(attributeName, oldValue, newValue) { - if (_get(AttributeMarshalling.prototype.__proto__ || Object.getPrototypeOf(AttributeMarshalling.prototype), 'attributeChangedCallback', this)) { - _get(AttributeMarshalling.prototype.__proto__ || Object.getPrototypeOf(AttributeMarshalling.prototype), 'attributeChangedCallback', this).call(this); - } - var propertyName = attributeToPropertyName(attributeName); - // If the attribute name corresponds to a property name, set the property. - // Ignore standard HTMLElement properties handled by the DOM. - if (propertyName in this && !(propertyName in HTMLElement.prototype)) { - this[propertyName] = newValue; - } - } - }, { - key: 'connectedCallback', - value: function connectedCallback() { - if (_get(AttributeMarshalling.prototype.__proto__ || Object.getPrototypeOf(AttributeMarshalling.prototype), 'connectedCallback', this)) { - _get(AttributeMarshalling.prototype.__proto__ || Object.getPrototypeOf(AttributeMarshalling.prototype), 'connectedCallback', this).call(this); - } - _safeAttributes2.default.connected(this); - } - }, { - key: 'reflectAttribute', - - - /** - * Set/unset the attribute with the indicated name. - * - * This method exists primarily to handle the case where an element wants to - * set a default property value that should be reflected as an attribute. An - * important limitation of custom element consturctors is that they cannot - * set attributes. A call to `reflectAttribute` during the constructor will - * be deferred until the element is connected to the document. - * - * @param {string} attribute - The name of the *attribute* (not property) to set. - * @param {object} value - The value to set. If null, the attribute will be removed. - */ - value: function reflectAttribute(attribute, value) { - return _safeAttributes2.default.setAttribute(this, attribute, value); - } - - /** - * Set/unset the class with the indicated name. - * - * This method exists primarily to handle the case where an element wants to - * set a default property value that should be reflected as as class. An - * important limitation of custom element consturctors is that they cannot - * set attributes, including the `class` attribute. A call to - * `reflectClass` during the constructor will be deferred until the element - * is connected to the document. - * - * @param {string} className - The name of the class to set. - * @param {object} value - True to set the class, false to remove it. - */ - - }, { - key: 'reflectClass', - value: function reflectClass(className, value) { - return _safeAttributes2.default.toggleClass(this, className, value); - } - }], [{ - key: 'observedAttributes', - get: function get() { - return attributesForClass(this); - } - }]); - - return AttributeMarshalling; - }(base); - - return AttributeMarshalling; -}; - -// Convert hyphenated foo-bar attribute name to camel case fooBar property name. - - -function attributeToPropertyName(attributeName) { - var propertyName = attributeToPropertyNames[attributeName]; - if (!propertyName) { - // Convert and memoize. - var hypenRegEx = /-([a-z])/g; - propertyName = attributeName.replace(hypenRegEx, function (match) { - return match[1].toUpperCase(); - }); - attributeToPropertyNames[attributeName] = propertyName; - } - return propertyName; -} - -function attributesForClass(classFn) { - - // We treat the element base classes as if they have no attributes, since we - // don't want to receive attributeChangedCallback for them. - if (classFn === HTMLElement || classFn === Object) { - return []; - } - - // Get attributes for parent class. - var baseClass = Object.getPrototypeOf(classFn.prototype).constructor; - var baseAttributes = attributesForClass(baseClass); - - // Get attributes for this class. - var propertyNames = Object.getOwnPropertyNames(classFn.prototype); - var setterNames = propertyNames.filter(function (propertyName) { - return typeof Object.getOwnPropertyDescriptor(classFn.prototype, propertyName).set === 'function'; - }); - var attributes = setterNames.map(function (setterName) { - return propertyNameToAttribute(setterName); - }); - - // Merge. - var diff = attributes.filter(function (attribute) { - return baseAttributes.indexOf(attribute) < 0; - }); - return baseAttributes.concat(diff); -} - -// Convert a camel case fooBar property name to a hyphenated foo-bar attribute. -function propertyNameToAttribute(propertyName) { - var attribute = propertyNamesToAttributes[propertyName]; - if (!attribute) { - // Convert and memoize. - var uppercaseRegEx = /([A-Z])/g; - attribute = propertyName.replace(uppercaseRegEx, '-$1').toLowerCase(); - } - return attribute; -} - -},{"./safeAttributes":16}],4:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - -function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } - -function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } - -/* Exported function extends a base class with Composable. */ -exports.default = function (base) { - - /** - * Mixin to make a class more easily composable with other mixins. - * - * This mixin contributes a `compose` method that applies a set of mixin - * functions and returns the resulting new class. This sugar can make the - * application of many mixins at once easier to read. - */ - var Composable = function (_base) { - _inherits(Composable, _base); - - function Composable() { - _classCallCheck(this, Composable); - - return _possibleConstructorReturn(this, (Composable.__proto__ || Object.getPrototypeOf(Composable)).apply(this, arguments)); - } - - _createClass(Composable, null, [{ - key: 'compose', - - - /** - * Apply a set of mixin functions or mixin objects to the present class and - * return the new class. - * - * Instead of writing: - * - * let MyClass = Mixin1(Mixin2(Mixin3(Mixin4(Mixin5(BaseClass))))); - * - * You can write: - * - * let MyClass = ComposableMixin(BaseClass).compose( - * Mixin1, - * Mixin2, - * Mixin3, - * Mixin4, - * Mixin5 - * ); - * - * This function can also take mixin objects. A mixin object is just a - * shorthand for a mixin function that creates a new subclass with the given - * members. The mixin object's members are *not* copied directly onto the - * prototype of the base class, as with traditional mixins. - * - * In addition to providing syntactic sugar, this mixin can be used to - * define a class in ES5, which lacks ES6's `class` keyword. - * - * @param {...mixins} mixins - A set of mixin functions or objects to apply. - */ - value: function compose() { - for (var _len = arguments.length, mixins = Array(_len), _key = 0; _key < _len; _key++) { - mixins[_key] = arguments[_key]; - } - - // We create a new subclass for each mixin in turn. The result becomes - // the base class extended by any subsequent mixins. It turns out that - // we can use Array.reduce() to concisely express this, using the current - // object as the seed for reduce(). - return mixins.reduce(composeClass, this); - } - }]); - - return Composable; - }(base); - - return Composable; -}; - -// Properties defined by Object that we don't want to mixin. - - -var NON_MIXABLE_OBJECT_PROPERTIES = ['constructor']; - -/* - * Apply the mixin to the given base class to return a new class. - * The mixin can either be a function that returns the modified class, or a - * plain object whose members will be copied to the new class' prototype. - */ -function composeClass(base, mixin) { - if (typeof mixin === 'function') { - // Mixin function - return mixin(base); - } else { - // Mixin object - var Subclass = function (_base2) { - _inherits(Subclass, _base2); - - function Subclass() { - _classCallCheck(this, Subclass); - - return _possibleConstructorReturn(this, (Subclass.__proto__ || Object.getPrototypeOf(Subclass)).apply(this, arguments)); - } - - return Subclass; - }(base); - - copyOwnProperties(mixin, Subclass.prototype, NON_MIXABLE_OBJECT_PROPERTIES); - return Subclass; - } -} - -/* - * Copy the given properties/methods to the target. - * Return the updated target. - */ -function copyOwnProperties(source, target) { - var ignorePropertyNames = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : []; - - Object.getOwnPropertyNames(source).forEach(function (name) { - if (ignorePropertyNames.indexOf(name) < 0) { - var descriptor = Object.getOwnPropertyDescriptor(source, name); - Object.defineProperty(target, name, descriptor); - } - }); - return target; -} - -},{}],5:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); - -var _get = function get(object, property, receiver) { if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } }; - -var _createSymbol = require('./createSymbol'); - -var _createSymbol2 = _interopRequireDefault(_createSymbol); - -var _toggleClass = require('./toggleClass'); - -var _toggleClass2 = _interopRequireDefault(_toggleClass); - -var _symbols = require('./symbols'); - -var _symbols2 = _interopRequireDefault(_symbols); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - -function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } - -function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } - -// Symbols for private data members on an element. -var itemsSymbol = (0, _createSymbol2.default)('items'); -var itemInitializedSymbol = (0, _createSymbol2.default)('itemInitialized'); - -/* Exported function extends a base class with ContentItems. */ - -exports.default = function (base) { - - /** - * Mixin which maps content semantics (elements) to list item semantics. - * - * Items differ from element contents in several ways: - * - * * They are often referenced via index. - * * They may have a selection state. - * * It's common to do work to initialize the appearance or state of a new - * item. - * * Auxiliary invisible child elements are filtered out and not counted as - * items. Auxiliary elements include link, script, style, and template - * elements. This filtering ensures that those auxiliary elements can be - * used in markup inside of a list without being treated as list items. - * - * This mixin expects a component to provide a `content` property returning a - * raw set of elements. You can provide that yourself, or use - * [DistributedChildrenContentMixin](DistributedChildrenContentMixin.md). - * - * The most commonly referenced property defined by this mixin is the `items` - * property. To avoid having to do work each time that property is requested, - * this mixin supports an optimized mode. If you invoke the `contentChanged` - * method when the set of items changes, the mixin concludes that you'll take - * care of notifying it of future changes, and turns on the optimization. With - * that on, the mixin saves a reference to the computed set of items, and will - * return that immediately on subsequent calls to the `items` property. If you - * use this mixin in conjunction with - * [DistributedChildrenContentMixin](DistributedChildrenContentMixin.md), the - * `contentChanged` method will be invoked for you when the element's children - * change, turning on the optimization automatically. - */ - var ContentItems = function (_base) { - _inherits(ContentItems, _base); - - function ContentItems() { - _classCallCheck(this, ContentItems); - - return _possibleConstructorReturn(this, (ContentItems.__proto__ || Object.getPrototypeOf(ContentItems)).apply(this, arguments)); - } - - _createClass(ContentItems, [{ - key: 'contentChanged', - value: function contentChanged() { - if (_get(ContentItems.prototype.__proto__ || Object.getPrototypeOf(ContentItems.prototype), 'contentChanged', this)) { - _get(ContentItems.prototype.__proto__ || Object.getPrototypeOf(ContentItems.prototype), 'contentChanged', this).call(this); - } - - // Since we got the contentChanged call, we'll assume we'll be notified if - // the set of items changes later. We turn on memoization of the items - // property by setting our internal property to null (instead of - // undefined). - this[itemsSymbol] = null; - - this[_symbols2.default.itemsChanged](); - } - - /** - * This method is invoked whenever a new item is added to the list. - * - * The default implementation of this method does nothing. You can override - * this to perform per-item initialization. - * - * @param {HTMLElement} item - The item that was added. - */ - - }, { - key: _symbols2.default.itemAdded, - value: function value(item) { - if (_get(ContentItems.prototype.__proto__ || Object.getPrototypeOf(ContentItems.prototype), _symbols2.default.itemAdded, this)) { - _get(ContentItems.prototype.__proto__ || Object.getPrototypeOf(ContentItems.prototype), _symbols2.default.itemAdded, this).call(this, item); - } - } - - /** - * The selection state for a single item has changed. - * - * Invoke this method to signal that the selected state of the indicated item - * has changed. By default, this applies a `selected` CSS class if the item - * is selected, and removed it if not selected. - * - * @param {HTMLElement} item - The item whose selection state has changed. - * @param {boolean} selected - True if the item is selected, false if not. - */ - - }, { - key: _symbols2.default.itemSelected, - value: function value(item, selected) { - if (_get(ContentItems.prototype.__proto__ || Object.getPrototypeOf(ContentItems.prototype), _symbols2.default.itemSelected, this)) { - _get(ContentItems.prototype.__proto__ || Object.getPrototypeOf(ContentItems.prototype), _symbols2.default.itemSelected, this).call(this, item, selected); - } - (0, _toggleClass2.default)(item, 'selected', selected); - } - - /** - * The current set of items in the list. See the top-level documentation for - * mixin for a description of how items differ from plain content. - * - * @type {HTMLElement[]} - */ - - }, { - key: _symbols2.default.itemsChanged, - - - /** - * This method is invoked when the underlying contents change. It is also - * invoked on component initialization – since the items have "changed" from - * being nothing. - */ - value: function value() { - var _this2 = this; - - if (_get(ContentItems.prototype.__proto__ || Object.getPrototypeOf(ContentItems.prototype), _symbols2.default.itemsChanged, this)) { - _get(ContentItems.prototype.__proto__ || Object.getPrototypeOf(ContentItems.prototype), _symbols2.default.itemsChanged, this).call(this); - } - - // Perform per-item initialization. - Array.prototype.forEach.call(this.items, function (item) { - if (!item[itemInitializedSymbol]) { - _this2[_symbols2.default.itemAdded](item); - item[itemInitializedSymbol] = true; - } - }); - - this.dispatchEvent(new CustomEvent('items-changed')); - } - - /** - * Fires when the items in the list change. - * - * @memberof ContentItems - * @event items-changed - */ - - }, { - key: 'items', - get: function get() { - var items = void 0; - if (this[itemsSymbol] == null) { - items = filterAuxiliaryElements(this.content); - // Note: test for *equality* with null; don't treat undefined as a match. - if (this[itemsSymbol] === null) { - // Memoize the set of items. - this[itemsSymbol] = items; - } - } else { - // Return the memoized items. - items = this[itemsSymbol]; - } - return items; - } - }]); - - return ContentItems; - }(base); - - return ContentItems; -}; - -// Return the given elements, filtering out auxiliary elements that aren't -// typically visible. Items which are not elements are returned as is. - - -function filterAuxiliaryElements(items) { - var auxiliaryTags = ['link', 'script', 'style', 'template']; - return [].filter.call(items, function (item) { - return !item.localName || auxiliaryTags.indexOf(item.localName) < 0; - }); -} - -},{"./createSymbol":14,"./symbols":17,"./toggleClass":18}],6:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); - -var _set = function set(object, property, value, receiver) { var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent !== null) { set(parent, property, value, receiver); } } else if ("value" in desc && desc.writable) { desc.value = value; } else { var setter = desc.set; if (setter !== undefined) { setter.call(receiver, value); } } return value; }; - -var _get = function get(object, property, receiver) { if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } }; - -var _microtask = require('./microtask'); - -var _microtask2 = _interopRequireDefault(_microtask); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - -function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } - -function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } - -/* Exported function extends a base class with DistributedChildrenContent. */ -exports.default = function (base) { - - /** - * Mixin which defines a component's content as its children, expanding any - * nodes distributed to the component's slots. - * - * This also provides notification of changes to a component's content. It - * will invoke a `contentChanged` method when the component is first - * instantiated, and whenever its distributed children change. This is an - * easy way to satisfy the Gold Standard checklist item for monitoring - * [Content Changes](https://github.com/webcomponents/gold-standard/wiki/Content-Changes). - * - * Example: - * - * ``` - * let base = DistributedChildrenContentMixin(DistributedChildrenMixin(HTMLElement)); - * class CountingElement extends base { - * - * constructor() { - * super(); - * let root = this.attachShadow({ mode: 'open' }); - * root.innerHTML = ``; - * } - * - * contentChanged() { - * // Count the component's children, both initially and when changed. - * this.count = this.distributedChildren.length; - * } - * - * } - * ``` - * - * Note that content change detection depends upon the element having at least - * one `slot` element in its shadow subtree. - * - * This mixin is intended for use with the - * [DistributedChildrenMixin](DistributedChildrenMixin.md). See that mixin for - * a discussion of how that works. This DistributedChildrenContentMixin - * provides an easy way of defining the "content" of a component as the - * component's distributed children. That in turn lets mixins like - * [ContentItemsMixin](ContentItemsMixin.md) manipulate the children as list - * items. - */ - var DistributedChildrenContent = function (_base) { - _inherits(DistributedChildrenContent, _base); - - function DistributedChildrenContent() { - _classCallCheck(this, DistributedChildrenContent); - - var _this = _possibleConstructorReturn(this, (DistributedChildrenContent.__proto__ || Object.getPrototypeOf(DistributedChildrenContent)).call(this)); - - if (_this.shadowRoot) { - // Listen to changes on all slots. - var slots = _this.shadowRoot.querySelectorAll('slot'); - slots.forEach(function (slot) { - return slot.addEventListener('slotchange', function (event) { - _this.contentChanged(); - }); - }); - } - - // Make an initial call to contentChanged() so that the component can do - // initialization that it normally does when content changes. - // - // This will invoke contentChanged() handlers in other mixins. In order - // that those mixins have a chance to complete their own initialization, - // we add the contentChanged() call to the microtask queue. - (0, _microtask2.default)(function () { - return _this.contentChanged(); - }); - return _this; - } - - /** - * Invoked when the contents of the component (including distributed - * children) have changed. - * - * This method is also invoked when a component is first instantiated; the - * contents have essentially "changed" from being nothing. This allows the - * component to perform initial processing of its children. - */ - - - _createClass(DistributedChildrenContent, [{ - key: 'contentChanged', - value: function contentChanged() { - if (_get(DistributedChildrenContent.prototype.__proto__ || Object.getPrototypeOf(DistributedChildrenContent.prototype), 'contentChanged', this)) { - _get(DistributedChildrenContent.prototype.__proto__ || Object.getPrototypeOf(DistributedChildrenContent.prototype), 'contentChanged', this).call(this); - } - var event = new CustomEvent('content-changed'); - this.dispatchEvent(event); - } - - /** - * The content of this component, defined to be the flattened array of - * children distributed to the component. - * - * @type {HTMLElement[]} - */ - - }, { - key: 'content', - get: function get() { - var distributedChildren = this.distributedChildren; - if (typeof distributedChildren === 'undefined') { - console.warn('DistributedChildrenContentMixin expects the component to define a "distributedChildren" property.'); - } - return distributedChildren; - }, - set: function set(value) { - if ('content' in base.prototype) { - _set(DistributedChildrenContent.prototype.__proto__ || Object.getPrototypeOf(DistributedChildrenContent.prototype), 'content', value, this); - } - // TODO: Set the children to the given value (which should be an array of - // elements)? - } - - /** - * This event is raised when the component's contents (including distributed - * children) have changed. - * - * @memberof DistributedChildrenContent - * @event content-changed - */ - - }]); - - return DistributedChildrenContent; - }(base); - - return DistributedChildrenContent; -}; - -},{"./microtask":15}],7:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); - -function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - -function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } - -function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } - -/* Exported function extends a base class with DistributedChildren. */ -exports.default = function (base) { - - /** - * Mixin which defines helpers for accessing a component's distributed - * children as a flattened array or string. - * - * The standard DOM API provides several ways of accessing child content: - * `children`, `childNodes`, and `textContent`. None of these functions are - * Shadow DOM aware. This mixin defines variations of those functions that - * *are* Shadow DOM aware. - * - * Example: you create a component `` that displays a number - * equal to the number of children placed inside that component. If someone - * instantiates your component like: - * - * - *
- *
- *
- *
- * - * Then the component should show "3", because there are three children. To - * calculate the number of children, the component can just calculate - * `this.children.length`. However, suppose someone instantiates your - * component inside one of their own components, and puts a `` element - * inside your component: - * - * - * - * - * - * If your component only looks at `this.children`, it will always see exactly - * one child — the `` element. But the user looking at the page will - * *see* any nodes distributed to that slot. To match what the user sees, your - * component should expand any `` elements it contains. - * - * That is the problem this mixin solves. After applying this mixin, your - * component code has access to `this.distributedChildren`, whose `length` - * will return the total number of all children distributed to your component - * in the composed tree. - * - * Note: The latest Custom Elements API design calls for a new function, - * `getAssignedNodes` that takes an optional `deep` parameter, that will solve - * this problem at the API level. - */ - var DistributedChildren = function (_base) { - _inherits(DistributedChildren, _base); - - function DistributedChildren() { - _classCallCheck(this, DistributedChildren); - - return _possibleConstructorReturn(this, (DistributedChildren.__proto__ || Object.getPrototypeOf(DistributedChildren)).apply(this, arguments)); - } - - _createClass(DistributedChildren, [{ - key: 'distributedChildren', - - - /** - * An in-order collection of distributed children, expanding any slot - * elements. Like the standard children property, this skips text nodes. - * - * @type {HTMLElement[]} - */ - get: function get() { - return expandContentElements(this.children, false); - } - - /** - * An in-order collection of distributed child nodes, expanding any slot - * elements. Like the standard childNodes property, this includes text - * nodes. - * - * @type {Node[]} - */ - - }, { - key: 'distributedChildNodes', - get: function get() { - return expandContentElements(this.childNodes, true); - } - - /** - * The concatenated text content of all distributed child nodes, expanding - * any slot elements. - * - * @type {string} - */ - - }, { - key: 'distributedTextContent', - get: function get() { - var strings = this.distributedChildNodes.map(function (child) { - return child.textContent; - }); - return strings.join(''); - } - }]); - - return DistributedChildren; - }(base); - - return DistributedChildren; -}; - -/* - * Given a array of nodes, return a new array with any content elements expanded - * to the nodes distributed to that content element. This rule is applied - * recursively. - * - * If includeTextNodes is true, text nodes will be included, as in the - * standard childNodes property; by default, this skips text nodes, like the - * standard children property. - */ - - -function expandContentElements(nodes, includeTextNodes) { - var _ref; - - var expanded = Array.prototype.map.call(nodes, function (node) { - // We want to see if the node is an instanceof HTMLSlotELement, but - // that class won't exist if the browser that doesn't support native - // Shadow DOM and if the Shadow DOM polyfill hasn't been loaded. Instead, - // we do a simplistic check to see if the tag name is "slot". - var isSlot = typeof HTMLSlotElement !== 'undefined' ? node instanceof HTMLSlotElement : node.localName === 'slot'; - if (isSlot) { - // Use the nodes assigned to this node instead. - var assignedNodes = node.assignedNodes({ flatten: true }); - return assignedNodes ? expandContentElements(assignedNodes, includeTextNodes) : []; - } else if (node instanceof HTMLElement) { - // Plain element; use as is. - return [node]; - } else if (node instanceof Text && includeTextNodes) { - // Text node. - return [node]; - } else { - // Comment, processing instruction, etc.; skip. - return []; - } - }); - var flattened = (_ref = []).concat.apply(_ref, _toConsumableArray(expanded)); - return flattened; -} - -},{}],8:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); - -var _set = function set(object, property, value, receiver) { var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent !== null) { set(parent, property, value, receiver); } } else if ("value" in desc && desc.writable) { desc.value = value; } else { var setter = desc.set; if (setter !== undefined) { setter.call(receiver, value); } } return value; }; - -var _get = function get(object, property, receiver) { if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } }; - -exports.default = mixin; - -var _createSymbol = require('./createSymbol'); - -var _createSymbol2 = _interopRequireDefault(_createSymbol); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - -function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } - -function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } - -// Symbols for private data members on an element. -var selectedFractionSymbol = (0, _createSymbol2.default)('selectedFraction'); - -/* Exported function extends a base class with FractionalSelection. */ -function mixin(base) { - - /** - * Adds support for fractional selection: treating a selection as a real - * number that combines an integer portion (an index into a list), and a - * fraction (indicating how far of the way we are to the next or previous - * item). - * - * This is useful in components that support incremental operations during - * dragging and swiping. Example: a carousel component has several items, and the - * currently selected item is item 3. The user begins swiping to the left, - * moving towards selecting item 4. Halfway through this operation, the - * fractional selection value is 3.5. - * - * This value permits communication between mixins like - * [SwipeDirectionMixin](./SwipeDirectionMixin.md) and - * [TrackpadDirectionMixin](./TrackpadDirectionMixin.md), which generate - * fractional selection values, and mixins like - * [SelectionAnimationMixin](./SelectionAnimationMixin.md), which can render - * selection at a fractional value. - */ - var FractionalSelection = function (_base) { - _inherits(FractionalSelection, _base); - - function FractionalSelection() { - _classCallCheck(this, FractionalSelection); - - return _possibleConstructorReturn(this, (FractionalSelection.__proto__ || Object.getPrototypeOf(FractionalSelection)).apply(this, arguments)); - } - - _createClass(FractionalSelection, [{ - key: 'connectedCallback', - value: function connectedCallback() { - if (_get(FractionalSelection.prototype.__proto__ || Object.getPrototypeOf(FractionalSelection.prototype), 'connectedCallback', this)) { - _get(FractionalSelection.prototype.__proto__ || Object.getPrototypeOf(FractionalSelection.prototype), 'connectedCallback', this).call(this); - } - this.selectedFraction = 0; - } - - /** - * A fractional value indicating how far the user has currently advanced to - * the next/previous item. E.g., a `selectedFraction` of 3.5 indicates the - * user is halfway between items 3 and 4. - * - * @type {number} - */ - - }, { - key: 'selectedFraction', - get: function get() { - return this[selectedFractionSymbol]; - }, - set: function set(value) { - this[selectedFractionSymbol] = value; - if ('selectedFraction' in base.prototype) { - _set(FractionalSelection.prototype.__proto__ || Object.getPrototypeOf(FractionalSelection.prototype), 'selectedFraction', value, this); - } - var event = new CustomEvent('selected-fraction-changed'); - this.dispatchEvent(event); - } - }]); - - return FractionalSelection; - }(base); - - return FractionalSelection; -} - -mixin.helpers = { - - /* - * Dampen a selection that goes past the beginning or end of a list. This is - * generally used to produce a visual effect of tension as the user tries to - * go further in a direction that has no more items. - * - * Example: suppose `itemCount` is 5, indicating a list of 5 items. The index of - * the last item is 4. If the `selection` parameter is 4.5, the user is trying - * to go past this last item. When a damping function is applied, the resulting - * value will be less than 4.5 (the actual value will be 4.25). When this - * selection state is rendered, the user will see that, each unit distance the - * drag travels has less and less visible effect. This is perceived as tension. - * - * @param {number} selection - A real number indicating a selection position - * @param {number} itemCount - An integer for the number of items in the list - * @returns {number} A real number representing the damped selection value. - */ - dampedSelection: function dampedSelection(selection, itemCount) { - var bound = itemCount - 1; - var damped = void 0; - if (selection < 0) { - // Trying to go past beginning of list. Apply tension from the left edge. - damped = -mixin.helpers.damping(-selection); - } else if (selection >= bound) { - // Trying to go past end of list. Apply tension from the right edge. - damped = bound + mixin.helpers.damping(selection - bound); - } else { - // No damping required. - damped = selection; - } - return damped; - }, - - - /* - * Calculate damping as a function of the distance past the minimum/maximum - * values. - * - * We want to asymptotically approach an absolute minimum of 1 unit - * below/above the actual minimum/maximum. This requires calculating a - * hyperbolic function. - * - * See http://www.wolframalpha.com/input/?i=y+%3D+-1%2F%28x%2B1%29+%2B+1 - * for the one we use. The only portion of that function we care about is when - * x is zero or greater. An important consideration is that the curve be - * tangent to the diagonal line x=y at (0, 0). This ensures smooth continuity - * with the normal drag behavior, in which the visible sliding is linear with - * the distance the touchpoint has been dragged. - */ - damping: function damping(x) { - var y = -1 / (x + 1) + 1; - return y; - }, - - - /* - * Return the current fractional selection value for the given element. - * - * This simply adds the element's `selectedIndex` and `selectedFraction` - * properties. - * - * @param {HTMLElement} element - An element that supports selection - */ - elementSelection: function elementSelection(element) { - var selectedIndex = element.selectedIndex; - if (selectedIndex < 0) { - // No selection - return; - } - var selectedFraction = element.selectedFraction || 0; - return selectedIndex + selectedFraction; - }, - - - /* - * Breaks a fractional selection into its integer and fractional parts. - * - * Example: if passed 3.5, this returns { index: 3, fraction: 5 }. - * - * @param {number} selection – A real number representing a selection point - * @returns {object} - An object with an `index` property holding the - * selection's integer component, and a `fraction` property holding the - * selection's fractional component. - */ - selectionParts: function selectionParts(selection) { - // Stupid IE doesn't have Math.trunc. - // const index = Math.trunc(selection); - var index = selection < 0 ? Math.ceil(selection) : Math.floor(selection); - var fraction = selection - index; - return { index: index, fraction: fraction }; - }, - - - /* - * Returns a fractional selection point after accounting for wrapping, ensuring - * that the integer portion of the selection stays between 0 and `itemCount`-1. - * That is, the integer portion will always be a valid index into the list. - * - * Example of wrapping past the end of the list: if `selection` is 5.5 and - * `itemCount` is 5, this returns 0.5. Example of wrapping past the beginning of - * the list: if `selection` is 0.5 and `itemCount` is 5, this returns 4.5. - * - * @param {number} selection - A real number representing a selection point - * @param {number} itemCount - The number of items in the list - * @returns {number} - The result of wrapping the selection point - */ - wrappedSelection: function wrappedSelection(selection, itemCount) { - // Handles possibility of negative mod. - // See http://stackoverflow.com/a/18618250/76472 - return (selection % itemCount + itemCount) % itemCount; - }, - - - /* - * Return the parts of a selection, first wrapping if necessary. - * - * @param {number} selection – A real number representing a selection point - * @param {number} itemCount - The number of items in the list - * @param {boolean} wrap – True if the selection should wrap to stay within the - * list - * @returns {object} – The parts of the selection, using the same format as - * `selectionParts`. - */ - wrappedSelectionParts: function wrappedSelectionParts(selection, itemCount, wrap) { - if (wrap) { - selection = mixin.helpers.wrappedSelection(selection, itemCount); - } - return mixin.helpers.selectionParts(selection); - } -}; - -},{"./createSymbol":14}],9:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); - -var _set = function set(object, property, value, receiver) { var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent !== null) { set(parent, property, value, receiver); } } else if ("value" in desc && desc.writable) { desc.value = value; } else { var setter = desc.set; if (setter !== undefined) { setter.call(receiver, value); } } return value; }; - -var _get = function get(object, property, receiver) { if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } }; - -exports.default = mixin; - -var _createSymbol = require('./createSymbol'); - -var _createSymbol2 = _interopRequireDefault(_createSymbol); - -var _FractionalSelectionMixin = require('./FractionalSelectionMixin'); - -var _FractionalSelectionMixin2 = _interopRequireDefault(_FractionalSelectionMixin); - -var _symbols = require('./symbols'); - -var _symbols2 = _interopRequireDefault(_symbols); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - -function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } - -function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } - -// Symbols for private data members on an element. -var animationSymbol = (0, _createSymbol2.default)('animation'); -var draggingSymbol = (0, _createSymbol2.default)('dragging'); -var lastAnimationSymbol = (0, _createSymbol2.default)('lastAnimation'); -var playingAnimationSymbol = (0, _createSymbol2.default)('animatingSelection'); -var previousSelectionSymbol = (0, _createSymbol2.default)('previousSelection'); -var selectionAnimationDurationSymbol = (0, _createSymbol2.default)('selectionAnimationDuration'); -var selectionAnimationEffectSymbol = (0, _createSymbol2.default)('selectionAnimationEffect'); -var selectionAnimationKeyframesSymbol = (0, _createSymbol2.default)('selectionAnimationKeyframes'); -var resetAnimationsOnNextRenderSymbol = (0, _createSymbol2.default)('resetAnimationsOnNextRender'); - -/* Exported function extends a base class with SelectionAnimation. */ -function mixin(base) { - - /** - * Mixin which uses animation to show transitions between selection states. - * - * This mixin can be used by components that want to provide visible - * animations when changing the selection. For example, a carousel component - * may want to define a sliding animation effect shown when moving between - * items. - * - * The animation is defined by a `selectionAnimationKeyframes` property; see - * that property for details on how to define these keyframes. This animation - * will be used in two ways. First, when moving strictly between items, the - * animation will play smoothly to show the selection changing. Second, the - * animation can be used to render the selection at a fixed point in the - * transition between states. E.g., if the user pauses halfway through - * dragging an element using [SwipeDirectionMixin](SwipeDirectionMixin.md) - * or [TrackpadDirectionMixin](TrackpadDirectionMixin.md)s, then the selection - * animation will be shown at the point exactly halfway through. - * - * This mixin expects a component to provide an `items` array of all elements - * in the list, which can be provided via - * [ContentItemsMixin](ContentItemsMixin.md). This mixin also expects - * `selectedIndex` and `selectedItem` properties, which can be provided via - * [SingleSelectionMixin](SingleSelectionMixin.md). - * - * This mixin supports a `selectionWraps` property. When true, the user can - * navigate forward from the last item in the list and wrap around to the - * first item, or navigate backward from the first item and wrap around to the - * last item. - * - * This mixin uses the Web Animations API. For use on browsers which - * do not support that API natively, you will need to load the - * [Web Animations polyfill](https://github.com/web-animations/web-animations-js). - */ - var SelectionAnimation = function (_base) { - _inherits(SelectionAnimation, _base); - - function SelectionAnimation() { - _classCallCheck(this, SelectionAnimation); - - // Set defaults. - var _this = _possibleConstructorReturn(this, (SelectionAnimation.__proto__ || Object.getPrototypeOf(SelectionAnimation)).call(this)); - - if (typeof _this.selectionAnimationDuration === 'undefined') { - _this.selectionAnimationDuration = _this[_symbols2.default.defaults].selectionAnimationDuration; - } - if (typeof _this.selectionAnimationEffect === 'undefined' && _this.selectionAnimationKeyframes == null) { - _this.selectionAnimationEffect = _this[_symbols2.default.defaults].selectionAnimationEffect; - } - - _this[_symbols2.default.dragging] = false; - return _this; - } - - _createClass(SelectionAnimation, [{ - key: _symbols2.default.itemAdded, - value: function value(item) { - // We mark new items in the list as explicitly visible to ARIA. Otherwise, - // when an item isn't visible on the screen, ARIA will assume the item is - // of no interest to the user, and leave it out of the accessibility tree. - // If the list contains 10 items, but only 3 are visible, a screen reader - // might then announce the list only has 3 items. To ensure that screen - // readers and other assistive technologies announce the correct total - // number of items, we explicitly mark all items as not hidden. This will - // expose them all in the accessibility tree, even the items which are - // currently not rendered. - // - // TODO: Generally speaking, this entire mixin assumes that the user can - // navigate through all items in a list. But an app could style an item as - // display:none or visibility:hidden because the user is not allowed to - // interact with that item at the moment. Support for this scenario should - // be added. This would entail changing all locations where a mixin - // function is counting items, iterating over the (visible) items, and - // showing or hiding items. Among other things, the code below to make - // items visible to ARIA would need to discriminate between items which - // are invisible because of animation state, or invisible because the user - // shouldn't interact with them. - item.setAttribute('aria-hidden', false); - } - }, { - key: _symbols2.default.itemsChanged, - value: function value() { - if (_get(SelectionAnimation.prototype.__proto__ || Object.getPrototypeOf(SelectionAnimation.prototype), _symbols2.default.itemsChanged, this)) { - _get(SelectionAnimation.prototype.__proto__ || Object.getPrototypeOf(SelectionAnimation.prototype), _symbols2.default.itemsChanged, this).call(this); - } - - _resetAnimations(this); - - // TODO: Also reset our notion of the last rendered selection? This comes - // up when a DOM removal causes the selected item to change position. - // this[previousSelectionSymbol] = null; - - renderSelection(this); - } - }, { - key: 'resetAnimations', - value: function resetAnimations() { - _resetAnimations(this); - } - - /** - * A fractional value indicating how far the user has currently advanced to - * the next/previous item. E.g., a `selectedFraction` of 3.5 indicates the - * user is halfway between items 3 and 4. - * - * For more details, see [FractionalSelectionMixin](FractionalSelectionMixin.md) - * mixin. - * - * @type {number} - */ - - }, { - key: _symbols2.default.defaults, - get: function get() { - var defaults = _get(SelectionAnimation.prototype.__proto__ || Object.getPrototypeOf(SelectionAnimation.prototype), _symbols2.default.defaults, this) || {}; - defaults.selectionAnimationDuration = 250; - defaults.selectionAnimationEffect = 'slide'; - return defaults; - } - - /* - * Provide backing for the dragging property. - * Also, when a drag begins, reset the animations. - */ - - }, { - key: _symbols2.default.dragging, - get: function get() { - return this[draggingSymbol]; - }, - set: function set(value) { - var previousValue = this[_symbols2.default.dragging]; - this[draggingSymbol] = value; - if (_symbols2.default.dragging in base.prototype) { - _set(SelectionAnimation.prototype.__proto__ || Object.getPrototypeOf(SelectionAnimation.prototype), _symbols2.default.dragging, value, this); - } - if (value && !previousValue) { - // Have begun a drag. - this[resetAnimationsOnNextRenderSymbol] = true; - } - } - }, { - key: 'selectedFraction', - get: function get() { - return _get(SelectionAnimation.prototype.__proto__ || Object.getPrototypeOf(SelectionAnimation.prototype), 'selectedFraction', this) || 0; - }, - set: function set(value) { - if ('selectedFraction' in base.prototype) { - _set(SelectionAnimation.prototype.__proto__ || Object.getPrototypeOf(SelectionAnimation.prototype), 'selectedFraction', value, this); - } - renderSelection(this, this.selectedIndex, value); - } - }, { - key: 'selectedIndex', - get: function get() { - return _get(SelectionAnimation.prototype.__proto__ || Object.getPrototypeOf(SelectionAnimation.prototype), 'selectedIndex', this); - }, - set: function set(index) { - if ('selectedIndex' in base.prototype) { - _set(SelectionAnimation.prototype.__proto__ || Object.getPrototypeOf(SelectionAnimation.prototype), 'selectedIndex', index, this); - } - renderSelection(this, index, 0); - } - - /** - * The duration of a selection animation in milliseconds. - * - * This measures the amount of time required for a selection animation to - * complete. This number remains constant, even if the number of items being - * animated increases. - * - * The default value is 250 milliseconds (a quarter a second). - * - * @type {number} - * @default 250 - */ - - }, { - key: 'selectionAnimationDuration', - get: function get() { - return this[selectionAnimationDurationSymbol]; - }, - set: function set(value) { - this[selectionAnimationDurationSymbol] = value; - if ('selectionAnimationDuration' in base.prototype) { - _set(SelectionAnimation.prototype.__proto__ || Object.getPrototypeOf(SelectionAnimation.prototype), 'selectionAnimationDuration', value, this); - } - } - - /** - * The name of a standard selection animation effect. - * - * This is a shorthand for setting the `selectionAnimationKeyframes` - * property to standard keyframes. Supported string values: - * - * * "crossfade" - * * "reveal" - * * "revealWithFade" - * * "showAdjacent" - * * "slide" - * * "slideWithGap" - * - * @type {string} - * @default "slide" - */ - - }, { - key: 'selectionAnimationEffect', - get: function get() { - return this[selectionAnimationEffectSymbol]; - }, - set: function set(value) { - this[selectionAnimationEffectSymbol] = value; - if ('selectionAnimationEffect' in base.prototype) { - _set(SelectionAnimation.prototype.__proto__ || Object.getPrototypeOf(SelectionAnimation.prototype), 'selectionAnimationEffect', value, this); - } - this.selectionAnimationKeyframes = mixin.standardEffectKeyframes[value]; - } - - /** - * The keyframes that define an animation that plays for an item when moving - * forward in the sequence. - * - * This is an array of CSS rules that will be applied. These are used as - * [keyframes](http://w3c.github.io/web-animations/#keyframes-section) - * to animate the item with the - * [Web Animations API](https://developer.mozilla.org/en-US/docs/Web/API/animation). - * - * The animation represents the state of the next item as it moves from - * completely unselected (offstage, usually right), to selected (center - * stage), to completely unselected (offstage, usually left). The center time - * of the animation should correspond to the item's quiscent selected state, - * typically in the center of the stage and at the item's largest size. - * - * The default forward animation is a smooth slide at full size from right to - * left. - * - * When moving the selection backward, this animation is played in reverse. - * - * @type {cssRules[]} - */ - - }, { - key: 'selectionAnimationKeyframes', - get: function get() { - // Standard animation slides left/right, keeps adjacent items out of view. - return this[selectionAnimationKeyframesSymbol]; - }, - set: function set(value) { - this[selectionAnimationKeyframesSymbol] = value; - if ('selectionAnimationKeyframes' in base.prototype) { - _set(SelectionAnimation.prototype.__proto__ || Object.getPrototypeOf(SelectionAnimation.prototype), 'selectionAnimationKeyframes', value, this); - } - _resetAnimations(this); - renderSelection(this); - } - }, { - key: 'selectionWraps', - get: function get() { - return _get(SelectionAnimation.prototype.__proto__ || Object.getPrototypeOf(SelectionAnimation.prototype), 'selectionWraps', this); - }, - set: function set(value) { - if ('selectionWraps' in base.prototype) { - _set(SelectionAnimation.prototype.__proto__ || Object.getPrototypeOf(SelectionAnimation.prototype), 'selectionWraps', value, this); - } - _resetAnimations(this); - renderSelection(this); - } - }]); - - return SelectionAnimation; - }(base); - - return SelectionAnimation; -} - -// We expose helpers on the mixin function that we want to be able to unit test. -// Since these are on the function, not on the class emitted by the function, -// they don't end up getting exposed on actual element instances. -mixin.helpers = { - - /* - * Calculate the animation fractions for an element's items at the given - * selection point. This is used when rendering the element's selection state - * instantaneously. - * - * This function considers the selectedIndex parameter, which can be a whole - * or fractional number, and determines which items will be visible at that - * index. This function then calculates a corresponding animation fraction: a - * number between 0 and 1 indicating how far through the selection animation - * an item should be shown, or null if the item should not be visible at that - * selection index. These fractions are returned as an array, where the - * animation fraction at position N corresponds to how item N should be shown. - */ - animationFractionsForSelection: function animationFractionsForSelection(element, selection) { - - var items = element.items; - if (!items) { - return; - } - - var itemCount = items.length; - var selectionWraps = element.selectionWraps; - - return items.map(function (item, itemIndex) { - // How many steps from the selection point to this item? - var steps = stepsToIndex(itemCount, selectionWraps, selection, itemIndex); - // To convert steps to animation fraction: - // steps animation fraction - // 1 0 (stage right) - // 0 0.5 (center stage) - // -1 1 (stage left) - var animationFraction = (1 - steps) / 2; - return animationFraction >= 0 && animationFraction <= 1 ? animationFraction : null; // Outside animation range - }); - }, - - - /* - * Calculate the animation timings that should be used to smoothly animate the - * element's items from one selection state to another. - * - * This returns an array of timings, where the timing at position N should be - * used to animate item N. If an item's timing is null, then that item should - * not take place in the animation, and should be hidden instead. - */ - effectTimingsForSelectionAnimation: function effectTimingsForSelectionAnimation(element, fromSelection, toSelection) { - - var items = element.items; - if (!items) { - return; - } - var itemCount = items.length; - var selectionWraps = element.selectionWraps; - var toIndex = _FractionalSelectionMixin2.default.helpers.wrappedSelectionParts(toSelection, itemCount, selectionWraps).index; - var totalSteps = stepsToIndex(itemCount, selectionWraps, fromSelection, toSelection); - var direction = totalSteps >= 0 ? 'normal' : 'reverse'; - var fill = 'both'; - var totalDuration = element.selectionAnimationDuration; - var stepDuration = totalSteps !== 0 ? totalDuration * 2 / Math.ceil(Math.abs(totalSteps)) : 0; // No steps required, animation will be instantenous. - - var timings = items.map(function (item, itemIndex) { - var steps = stepsToIndex(itemCount, selectionWraps, itemIndex, toSelection); - // If we include this item in the staggered sequence of animations we're - // creating, where would the item appear in the sequence? - var positionInSequence = totalSteps - steps; - if (totalSteps < 0) { - positionInSequence = -positionInSequence; - } - // So, is this item really included in the sequence? - if (Math.ceil(positionInSequence) >= 0 && positionInSequence <= Math.abs(totalSteps)) { - // Note that delay for first item will be negative. That will cause - // the animation to start halfway through, which is what we want. - var delay = stepDuration * (positionInSequence - 1) / 2; - var endDelay = itemIndex === toIndex ? -stepDuration / 2 : // Stop halfway through. - 0; // Play animation until end. - return { duration: stepDuration, direction: direction, fill: fill, delay: delay, endDelay: endDelay }; - } else { - return null; - } - }); - - return timings; - } -}; - -// Keyframes for standard selection animation effects. -mixin.standardEffectKeyframes = { - - // Simple crossfade - crossfade: [{ opacity: 0 }, { opacity: 1 }, { opacity: 0 }], - - // Reveal, as if sliding the top card off a deck of cards - reveal: [{ transform: 'translateX(0%)', zIndex: 0 }, { transform: 'translateX(0%)', zIndex: 1 }, { transform: 'translateX(-100%)', zIndex: 2 }], - - // Google Photos-style reveal-with-fade animation - revealWithFade: [{ transform: 'translateX(0%) scale(0.75)', opacity: 0, zIndex: 0 }, { transform: 'translateX(0%) scale(1.0)', opacity: 1, zIndex: 1 }, { transform: 'translateX(-100%) scale(1.0)', opacity: 1, zIndex: 2 }], - - // Carousel variant with a bit of off-stage elements showing - showAdjacent: [{ transform: 'translateX(78%) scale(0.7)', zIndex: 0 }, { transform: 'translateX(0%) scale(0.82)', zIndex: 1 }, { transform: 'translateX(-78%) scale(0.7)', zIndex: 0 }], - - // Simple slide - slide: [{ transform: 'translateX(100%)' }, { transform: 'translateX(-100%)' }], - - // Slide, with a gap between - slideWithGap: [{ transform: 'translateX(110%)' }, { transform: 'translateX(-110%)' }] - -}; - -/* - * Smoothly animate the selection between the indicated "from" and "to" - * indices. The former can be a fraction, e.g., when the user releases a finger - * to complete a touch drag, and the selection will snap to the closest whole - * index. - */ -function animateSelection(element, fromSelection, toSelection) { - - _resetAnimations(element); - - // Calculate the animation timings. - var items = element.items; - var keyframes = element.selectionAnimationKeyframes; - element[playingAnimationSymbol] = true; - var timings = mixin.helpers.effectTimingsForSelectionAnimation(element, fromSelection, toSelection); - - // Figure out which item will be the one *after* the one we're selecting. - var itemCount = items.length; - var selectionWraps = element.selectionWraps; - var selectionIndex = _FractionalSelectionMixin2.default.helpers.selectionParts(toSelection, itemCount, selectionWraps).index; - var totalSteps = stepsToIndex(itemCount, selectionWraps, fromSelection, toSelection); - var forward = totalSteps >= 0; - var nextUpIndex = selectionIndex + (forward ? 1 : -1); - if (selectionWraps) { - nextUpIndex = _FractionalSelectionMixin2.default.helpers.wrappedSelection(nextUpIndex, itemCount); - } else if (!isItemIndexInBounds(element, nextUpIndex)) { - nextUpIndex = null; // At start/end of list; don't have a next item to show. - } - - // Play the animations using those timings. - var lastAnimationDetails = void 0; - timings.forEach(function (timing, index) { - var item = items[index]; - if (timing) { - showItem(item, true); - var animation = item.animate(keyframes, timing); - element[animationSymbol][index] = animation; - if (index === nextUpIndex) { - // This item will be animated, so will already be in the desired state - // after the animation completes. - nextUpIndex = null; - } - if (timing.endDelay !== 0) { - // This is the animation for the item that will be left selected. - // We want to clean up when this animation completes. - lastAnimationDetails = { animation: animation, index: index, timing: timing, forward: forward }; - } - } else { - // This item doesn't participate in the animation. - showItem(item, false); - } - }); - - if (lastAnimationDetails != null) { - // Arrange for clean-up work to be performed. - lastAnimationDetails.nextUpIndex = nextUpIndex; - lastAnimationDetails.animation.onfinish = function (event) { - return selectionAnimationFinished(element, lastAnimationDetails); - }; - element[lastAnimationSymbol] = lastAnimationDetails.animation; - } else { - // Shouldn't happen -- we should always have at least one animation. - element[playingAnimationSymbol] = false; - } -} - -function getAnimationForItemIndex(element, index) { - if (element[animationSymbol] == null) { - // Not ready yet; - return null; - } - var animation = element[animationSymbol][index]; - if (!animation) { - var item = element.items[index]; - animation = item.animate(element.selectionAnimationKeyframes, { - duration: element.selectionAnimationDuration, - fill: 'both' - }); - animation.pause(); - element[animationSymbol][index] = animation; - } - return animation; -} - -function isItemIndexInBounds(element, index) { - return index >= 0 && element.items && index < element.items.length; -} - -/* - * Render the selection state of the element. - * - * This can be used to re-render a previous selection state (if the - * selectedIndex param is omitted), render the selection instantly at a given - * whole or fractional selection index, or animate to a given selection index. - * - * There are several distinct scenarios we need to cover: - * - * 1. Initial positioning, or repositioning after changing a property like - * selectionAnimationKeyframes that affects rendering. - * 2. Animate on selectedIndex change. This should override any animation/swipe - * already in progress. - * 3. Instantly render the current position of a drag operation in progress. - * 4. Complete a drag operation. If the drag wasn't far enough to affect - * selection, we'll just be restoring the selectedFraction to 0. - * - * If the list does not wrap, any selection position outside the list's bounds - * will be damped to produce a visual effect of tension. - */ -function renderSelection(element) { - var selectedIndex = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : element.selectedIndex; - var selectedFraction = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : element.selectedFraction; - - var itemCount = element.items ? element.items.length : 0; - if (itemCount === 0) { - // Nothing to render. - return; - } - if (selectedIndex < 0) { - // TODO: Handle no selection. - return; - } - var selection = selectedIndex + selectedFraction; - if (element.selectionWraps) { - // Apply wrapping to ensure consistent representation of selection. - selection = _FractionalSelectionMixin2.default.helpers.wrappedSelection(selection, itemCount); - } else { - // Apply damping if necessary. - selection = _FractionalSelectionMixin2.default.helpers.dampedSelection(selection, itemCount); - } - var previousSelection = element[previousSelectionSymbol]; - // TODO: If an item changes position in the DOM, we end up animating from - // its old index to its new index, but we really don't want to animate at all. - if (!element[_symbols2.default.dragging] && previousSelection != null && previousSelection !== selection) { - // Animate selection from previous state to new state. - animateSelection(element, previousSelection, selection); - } else if (selectedFraction === 0 && element[playingAnimationSymbol]) { - // Already in process of animating to fraction 0. During that process, - // ignore subsequent attempts to renderSelection to fraction 0. - return; - } else { - // Render current selection state instantly. - renderSelectionInstantly(element, selection); - } - element[previousSelectionSymbol] = selection; -} - -/* - * Instantly render (don't animate) the element's items at the given whole or - * fractional selection index. - */ -function renderSelectionInstantly(element, toSelection) { - if (element[resetAnimationsOnNextRenderSymbol]) { - _resetAnimations(element); - element[resetAnimationsOnNextRenderSymbol] = false; - } - var animationFractions = mixin.helpers.animationFractionsForSelection(element, toSelection); - animationFractions.map(function (animationFraction, index) { - var item = element.items[index]; - if (animationFraction != null) { - showItem(item, true); - setAnimationFraction(element, index, animationFraction); - } else { - showItem(item, false); - } - }); -} - -/* - * We maintain an array containing an animation per item. This is used for two - * reasons: - * - * * During a drag operation, we want to be able to reuse animations between - * drag updates. - * * When a selection animation completes, we need to be able to leave the - * visibile items in a paused state. Later, we'll want to be able to clean up - * those animations. - * - * Note that this array is sparse: it will only hold up from 0–3 animations at - * any given point. - */ -function _resetAnimations(element) { - var animations = element[animationSymbol]; - if (animations) { - // Cancel existing animations to remove the effects they're applying. - animations.forEach(function (animation, index) { - if (animation) { - animation.cancel(); - animations[index] = null; - } - }); - } - var itemCount = element.items ? element.items.length : 0; - if (!animations || animations.length !== itemCount) { - // Haven't animated before with this number of items; (re)create array. - element[animationSymbol] = new Array(itemCount); - } -} - -/* - * The last animation in our selection animation has completed. Clean up. - */ -function selectionAnimationFinished(element, details) { - - // When the last animation completes, show the next item in the direction - // we're going. Waiting to that until this point is a bit of a hack to avoid - // having a next item that's higher in the natural z-order obscure other items - // during animation. - var nextUpIndex = details.nextUpIndex; - if (nextUpIndex != null) { - if (element[animationSymbol][nextUpIndex]) { - // Cancel existing selection animation so we can construct a new one. - element[animationSymbol][nextUpIndex].cancel(); - element[animationSymbol][nextUpIndex] = null; - } - var animationFraction = details.forward ? 0 : 1; - setAnimationFraction(element, nextUpIndex, animationFraction); - showItem(element.items[nextUpIndex], true); - } - - element[lastAnimationSymbol].onfinish = null; - element[playingAnimationSymbol] = false; -} - -/* - * Pause the indicated animation and have it show the animation at the given - * fraction (between 0 and 1) of the way through the animation. - */ -function setAnimationFraction(element, itemIndex, fraction) { - var animation = getAnimationForItemIndex(element, itemIndex); - if (animation) { - var duration = element.selectionAnimationDuration; - if (duration) { - animation.currentTime = fraction * duration; - } - } -} - -function showItem(item, flag) { - item.style.visibility = flag ? 'visible' : 'hidden'; -} - -/* - * Figure out how many steps it will take to go from fromSelection to - * toSelection. To go from item 3 to item 4 is one step. - * - * If wrapping is allowed, then going from the last item to the first will take - * one step (forward), and going from the first item to the last will take one - * step (backward). - */ -function stepsToIndex(length, allowWrap, fromSelection, toSelection) { - var steps = toSelection - fromSelection; - // Wrapping only kicks in when list has more than 1 item. - if (allowWrap && length > 1) { - var wrapSteps = length - Math.abs(steps); - if (wrapSteps <= 1) { - // Special case - steps = steps < 0 ? wrapSteps : // Wrap forward from last item to first. - -wrapSteps; // Wrap backward from first item to last. - } - } - return steps; -} - -},{"./FractionalSelectionMixin":8,"./createSymbol":14,"./symbols":17}],10:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); - -var _set = function set(object, property, value, receiver) { var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent !== null) { set(parent, property, value, receiver); } } else if ("value" in desc && desc.writable) { desc.value = value; } else { var setter = desc.set; if (setter !== undefined) { setter.call(receiver, value); } } return value; }; - -var _get = function get(object, property, receiver) { if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } }; - -var _symbols = require('./symbols'); - -var _symbols2 = _interopRequireDefault(_symbols); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - -function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } - -function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } - -// Used to assign unique IDs to item elements without IDs. -var idCount = 0; - -/* Exported function extends a base class with SelectionAriaActive. */ - -exports.default = function (base) { - - /** - * Mixin which treats the selected item in a list as the active item in ARIA - * accessibility terms. - * - * Handling ARIA selection state properly is actually quite complex: - * - * * The items in the list need to be indicated as possible items via an ARIA - * `role` attribute value such as "option". - * * The selected item need to be marked as selected by setting the item's - * `aria-selected` attribute to true *and* the other items need be marked as - * *not* selected by setting `aria-selected` to false. - * * The outermost element with the keyboard focus needs to have attributes - * set on it so that the selection is knowable at the list level via the - * `aria-activedescendant` attribute. - * * Use of `aria-activedescendant` in turn requires that all items in the - * list have ID attributes assigned to them. - * - * This mixin tries to address all of the above requirements. To that end, - * this mixin will assign generated IDs to any item that doesn't already have - * an ID. - * - * ARIA relies on elements to provide `role` attributes. This mixin will apply - * a default role of "listbox" on the outer list if it doesn't already have an - * explicit role. Similarly, this mixin will apply a default role of "option" - * to any list item that does not already have a role specified. - * - * This mixin expects a set of members that manage the state of the selection: - * `[symbols.itemSelected]`, `itemAdded`, and `selectedIndex`. You can - * supply these yourself, or do so via - * [SingleSelectionMixin](SingleSelectionMixin.md). - */ - var SelectionAriaActive = function (_base) { - _inherits(SelectionAriaActive, _base); - - function SelectionAriaActive() { - _classCallCheck(this, SelectionAriaActive); - - return _possibleConstructorReturn(this, (SelectionAriaActive.__proto__ || Object.getPrototypeOf(SelectionAriaActive)).apply(this, arguments)); - } - - _createClass(SelectionAriaActive, [{ - key: 'connectedCallback', - value: function connectedCallback() { - if (_get(SelectionAriaActive.prototype.__proto__ || Object.getPrototypeOf(SelectionAriaActive.prototype), 'connectedCallback', this)) { - _get(SelectionAriaActive.prototype.__proto__ || Object.getPrototypeOf(SelectionAriaActive.prototype), 'connectedCallback', this).call(this); - } - // Set default ARIA role. - if (this.getAttribute('role') == null && this[_symbols2.default.defaults].role) { - this.setAttribute('role', this[_symbols2.default.defaults].role); - } - } - }, { - key: _symbols2.default.itemAdded, - value: function value(item) { - if (_get(SelectionAriaActive.prototype.__proto__ || Object.getPrototypeOf(SelectionAriaActive.prototype), _symbols2.default.itemAdded, this)) { - _get(SelectionAriaActive.prototype.__proto__ || Object.getPrototypeOf(SelectionAriaActive.prototype), _symbols2.default.itemAdded, this).call(this, item); - } - - if (!item.getAttribute('role')) { - // Assign a default ARIA role. - item.setAttribute('role', 'option'); - } - - // Ensure each item has an ID so we can set aria-activedescendant on the - // overall list whenever the selection changes. - // - // The ID will take the form of a base ID plus a unique integer. The base - // ID will be incorporate the component's own ID. E.g., if a component has - // ID "foo", then its items will have IDs that look like "_fooOption1". If - // the compnent has no ID itself, its items will get IDs that look like - // "_option1". Item IDs are prefixed with an underscore to differentiate - // them from manually-assigned IDs, and to minimize the potential for ID - // conflicts. - if (!item.id) { - var baseId = this.id ? "_" + this.id + "Option" : "_option"; - item.id = baseId + idCount++; - } - } - }, { - key: _symbols2.default.itemSelected, - value: function value(item, selected) { - if (_get(SelectionAriaActive.prototype.__proto__ || Object.getPrototypeOf(SelectionAriaActive.prototype), _symbols2.default.itemSelected, this)) { - _get(SelectionAriaActive.prototype.__proto__ || Object.getPrototypeOf(SelectionAriaActive.prototype), _symbols2.default.itemSelected, this).call(this, item, selected); - } - item.setAttribute('aria-selected', selected); - var itemId = item.id; - if (itemId && selected) { - this.setAttribute('aria-activedescendant', itemId); - } - } - }, { - key: _symbols2.default.defaults, - get: function get() { - var defaults = _get(SelectionAriaActive.prototype.__proto__ || Object.getPrototypeOf(SelectionAriaActive.prototype), _symbols2.default.defaults, this) || {}; - defaults.role = 'listbox'; - return defaults; - } - }, { - key: 'selectedItem', - get: function get() { - return _get(SelectionAriaActive.prototype.__proto__ || Object.getPrototypeOf(SelectionAriaActive.prototype), 'selectedItem', this); - }, - set: function set(item) { - if ('selectedItem' in base.prototype) { - _set(SelectionAriaActive.prototype.__proto__ || Object.getPrototypeOf(SelectionAriaActive.prototype), 'selectedItem', item, this); - } - if (item == null) { - // Selection was removed. - this.removeAttribute('aria-activedescendant'); - } - } - }]); - - return SelectionAriaActive; - }(base); - - return SelectionAriaActive; -}; - -},{"./symbols":17}],11:[function(require,module,exports){ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - -function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } - -function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } - -/* Exported function extends a base class with ShadowElementReferences. */ -exports.default = function (base) { - - /** - * Mixin to create references to elements in a component's Shadow DOM subtree. - * - * This adds a member on the component called `this.$` that can be used to - * reference shadow elements with IDs. E.g., if component's shadow contains an - * element `