From a9e48682bf28f7ccfde9fdf79a97a2ecef8affbc Mon Sep 17 00:00:00 2001 From: Patty RoDee Date: Thu, 21 Dec 2017 18:21:14 -0800 Subject: [PATCH] feat(ripple): Add setUnbounded to foundation (#1826) Add setUnbounded to foundation, allowing a method to change whether a ripple is bounded or not. Modify the unbounded setter on the ripple implementation to use a local private method to solve closure compiler access control issues. --- packages/mdc-ripple/README.md | 1 + packages/mdc-ripple/foundation.js | 10 ++++++++++ packages/mdc-ripple/index.js | 18 ++++++++++++------ test/unit/mdc-ripple/foundation.test.js | 10 ++++++++++ 4 files changed, 33 insertions(+), 6 deletions(-) diff --git a/packages/mdc-ripple/README.md b/packages/mdc-ripple/README.md index 77141a9d536..b98e6b789a1 100644 --- a/packages/mdc-ripple/README.md +++ b/packages/mdc-ripple/README.md @@ -248,6 +248,7 @@ ripple to. The adapter API is as follows: | --- | --- | | `browserSupportsCssVars() => boolean` | Whether or not the given browser supports CSS Variables. When implementing this, please take the [Edge](#caveat-edge) and [Safari 9](#caveat-safari) considerations into account. We provide a `supportsCssVariables` function within the `util.js` which we recommend using, as it handles this for you. | | `isUnbounded() => boolean` | Whether or not the ripple should be considered unbounded. | +| `setUnbounded(unbounded: boolean) => void` | Adds the unbounded class when truthy, removes when falsy | | `isSurfaceActive() => boolean` | Whether or not the surface the ripple is acting upon is [active](https://www.w3.org/TR/css3-selectors/#useraction-pseudos). We use this to detect whether or not a keyboard event has activated the surface the ripple is on. This does not need to make use of `:active` (which is what we do); feel free to supply your own heuristics for it. | | `isSurfaceDisabled() => boolean` | Whether or not the ripple is attached to a disabled component. If true, the ripple will not activate. | | `addClass(className: string) => void` | Adds a class to the ripple surface | diff --git a/packages/mdc-ripple/foundation.js b/packages/mdc-ripple/foundation.js index eb78011068a..b79226b47be 100644 --- a/packages/mdc-ripple/foundation.js +++ b/packages/mdc-ripple/foundation.js @@ -503,6 +503,16 @@ class MDCRippleFoundation extends MDCFoundation { this.adapter_.updateCssVariable(VAR_TOP, `${this.unboundedCoords_.top}px`); } } + + /** @param {boolean} unbounded */ + setUnbounded(unbounded) { + const {UNBOUNDED} = MDCRippleFoundation.cssClasses; + if (unbounded) { + this.adapter_.addClass(UNBOUNDED); + } else { + this.adapter_.removeClass(UNBOUNDED); + } + } } export default MDCRippleFoundation; diff --git a/packages/mdc-ripple/index.js b/packages/mdc-ripple/index.js index a9b964ead82..d72eb78f0ff 100644 --- a/packages/mdc-ripple/index.js +++ b/packages/mdc-ripple/index.js @@ -82,13 +82,19 @@ class MDCRipple extends MDCComponent { /** @param {boolean} unbounded */ set unbounded(unbounded) { - const {UNBOUNDED} = MDCRippleFoundation.cssClasses; this.unbounded_ = Boolean(unbounded); - if (this.unbounded_) { - this.root_.classList.add(UNBOUNDED); - } else { - this.root_.classList.remove(UNBOUNDED); - } + this.setUnbounded_(); + } + + /** + * Closure Compiler throws an access control error when directly accessing a + * protected or private property inside a getter/setter, like unbounded above. + * By accessing the protected property inside a method, we solve that problem. + * That's why this function exists. + * @private + */ + setUnbounded_() { + this.foundation_.setUnbounded(this.unbounded_); } activate() { diff --git a/test/unit/mdc-ripple/foundation.test.js b/test/unit/mdc-ripple/foundation.test.js index 19a4d892f40..34ad2bb1d9a 100644 --- a/test/unit/mdc-ripple/foundation.test.js +++ b/test/unit/mdc-ripple/foundation.test.js @@ -255,3 +255,13 @@ testFoundation('#layout resets debounce latch when layout frame is run', ({found foundation.layout(); assert.equal(mockRaf.pendingFrames.length, 1); }); + +testFoundation('#setUnbounded adds unbounded class when unbounded is truthy', ({adapter, foundation}) => { + foundation.setUnbounded(true); + td.verify(adapter.addClass(cssClasses.UNBOUNDED)); +}); + +testFoundation('#setUnbounded removes unbounded class when unbounded is falsy', ({adapter, foundation}) => { + foundation.setUnbounded(false); + td.verify(adapter.removeClass(cssClasses.UNBOUNDED)); +});