Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(drawer): Convert JS to TypeScript #4390

Merged
merged 15 commits into from
Feb 14, 2019

Conversation

acdvorak
Copy link
Contributor

@acdvorak acdvorak commented Feb 9, 2019

Refs #4225

@codecov-io
Copy link

codecov-io commented Feb 9, 2019

Codecov Report

Merging #4390 into feat/typescript will increase coverage by 0.22%.
The diff coverage is 100%.

Impacted file tree graph

@@                Coverage Diff                 @@
##           feat/typescript   #4390      +/-   ##
==================================================
+ Coverage            98.68%   98.9%   +0.22%     
==================================================
  Files                   94      95       +1     
  Lines                 5987    6109     +122     
  Branches               805     802       -3     
==================================================
+ Hits                  5908    6042     +134     
+ Misses                  78      66      -12     
  Partials                 1       1
Impacted Files Coverage Δ
packages/mdc-drawer/dismissible/foundation.ts 100% <100%> (ø)
packages/mdc-dialog/util.ts 100% <100%> (ø) ⬆️
packages/mdc-drawer/index.ts 100% <100%> (ø)
packages/mdc-dialog/index.ts 100% <100%> (ø) ⬆️
packages/mdc-drawer/modal/foundation.ts 100% <100%> (ø)
packages/mdc-drawer/util.ts 100% <100%> (ø)
packages/mdc-base/component.ts 96.42% <0%> (ø) ⬆️
packages/mdc-textfield/character-counter/index.js
packages/mdc-select/icon/foundation.js
... and 27 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update b2fa9a5...1cd4d00. Read the comment docs.

@mdc-web-bot
Copy link
Collaborator

All 621 screenshot tests passed for commit ed69731 vs. feat/typescript! 💯🎉

@kfranqueiro kfranqueiro mentioned this pull request Feb 9, 2019
45 tasks
@mdc-web-bot
Copy link
Collaborator

All 621 screenshot tests passed for commit c8e9df4 vs. feat/typescript! 💯🎉

@mdc-web-bot
Copy link
Collaborator

All 621 screenshot tests passed for commit e7719ba vs. feat/typescript! 💯🎉

@mdc-web-bot
Copy link
Collaborator

All 621 screenshot tests passed for commit cf36082 vs. feat/typescript! 💯🎉

@mdc-web-bot
Copy link
Collaborator

All 621 screenshot tests passed for commit d53d1bc vs. feat/typescript! 💯🎉

packages/mdc-dialog/util.ts Outdated Show resolved Hide resolved
test/unit/mdc-dialog/util.test.js Outdated Show resolved Hide resolved
test/unit/mdc-drawer/dismissible.foundation.test.js Outdated Show resolved Hide resolved
test/unit/mdc-drawer/mdc-drawer.test.js Show resolved Hide resolved
test/unit/mdc-drawer/mdc-drawer.test.js Show resolved Hide resolved
test/unit/mdc-drawer/mdc-drawer.test.js Outdated Show resolved Hide resolved
test/unit/mdc-drawer/modal.foundation.test.js Show resolved Hide resolved
@mdc-web-bot
Copy link
Collaborator

All 621 screenshot tests passed for commit 01d0276 vs. feat/typescript! 💯🎉

@mdc-web-bot
Copy link
Collaborator

All 621 screenshot tests passed for commit d6d7132 vs. feat/typescript! 💯🎉

@mdc-web-bot
Copy link
Collaborator

All 621 screenshot tests passed for commit b6f32cd vs. feat/typescript! 💯🎉

@mdc-web-bot
Copy link
Collaborator

All 624 screenshot tests passed for commit b152591 vs. feat/typescript! 💯🎉

@mdc-web-bot
Copy link
Collaborator

All 624 screenshot tests passed for commit 24f442c vs. feat/typescript! 💯🎉

@mdc-web-bot
Copy link
Collaborator

All 624 screenshot tests passed for commit b34993e vs. feat/typescript! 💯🎉

packages/mdc-drawer/dismissible/foundation.ts Outdated Show resolved Hide resolved
const {OPENING, CLOSING, OPEN, ANIMATE, ROOT} = cssClasses;

// In Edge, transitionend on ripple pseudo-elements yields a target without classList, so check for Element first.
const isElement = evt.target instanceof Element;
if (!isElement || !this.adapter_.elementHasClass(/** @type {!Element} */ (evt.target), ROOT)) {
if (!isElement || !this.adapter_.elementHasClass(evt.target as Element, ROOT)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This would be a good place for a guard:

function isElement(element: any): element is Element {
  return element instanceof Element;
}

if (!this.adapter_.elementHasClass(isElement(evt.target), ROOT)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. instanceof checks make it harder to mock objects in unit tests, so I'm testing for the presence of classList instead.

class MDCDismissibleDrawerFoundation {
  handleTransitionEnd(evt: TransitionEvent) {
    // In Edge, transitionend on ripple pseudo-elements yields a target without classList, so check for Element first.
    const isRootElement = this.isElement_(evt.target) && this.adapter_.elementHasClass(evt.target, ROOT);
    if (!isRootElement) {
      return;
    }
  }

  private isElement_(element: unknown): element is Element {
    // In Edge, transitionend on ripple pseudo-elements yields a target without classList.
    return Boolean((element as Element).classList);
  }
}

packages/mdc-drawer/dismissible/foundation.ts Outdated Show resolved Hide resolved
packages/mdc-drawer/index.ts Outdated Show resolved Hide resolved
private scrim_!: Element | null; // assigned in initialSyncWithDOM()
private list_?: MDCList; // assigned in initialize()

private focusTrap_?: createFocusTrap.FocusTrap; // assigned in initialSyncWithDOM()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think change this to focusTrap_!, then below we don't have to the do focusTrap_!.active...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

focusTrap_ is undefined if the scrim is not present:

  initialSyncWithDOM() {
    const {MODAL} = MDCDismissibleDrawerFoundation.cssClasses;
    const {SCRIM_SELECTOR} = MDCDismissibleDrawerFoundation.strings;

    this.scrim_ = (this.root_.parentNode as Element).querySelector<HTMLElement>(SCRIM_SELECTOR);

    if (this.scrim_ && this.root_.classList.contains(MODAL)) {
      this.handleScrimClick_ = () => (this.foundation_ as MDCModalDrawerFoundation).handleScrimClick();
      this.scrim_.addEventListener('click', this.handleScrimClick_);
      this.focusTrap_ = util.createFocusTrapInstance(this.root_ as HTMLElement, this.focusTrapFactory_);
    }
  }

So we have to keep focusTrap_? and focusTrap_!.active

@mdc-web-bot
Copy link
Collaborator

All 624 screenshot tests passed for commit b5a06e5 vs. feat/typescript! 💯🎉

@@ -70,7 +70,7 @@ class MDCDialog extends MDCComponent<MDCDialogFoundation> {
private container_!: HTMLElement; // assigned in initialize()
private content_!: HTMLElement | null; // assigned in initialize()
private defaultButton_!: HTMLElement | null; // assigned in initialize()
private initialFocusEl_!: HTMLElement | null; // assigned in initialize()
private initialFocusEl_!: HTMLElement | undefined; // assigned in initialize()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems like a contradiction in terms. Isn't this effectively private initialFocusEl_?: HTMLElement?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Confusingly, the ! here has a slightly different meaning than when it's used after an expression.

When declaring member properties, ! is a "definite assignment assertion", meaning "I pinky swear that some value is assigned to this property, but it happens somewhere other than the constructor.

In an expression (e.g., querySelector('.foo')!), the bang means "this value will never be null or undefined."

You make a good point though; this can be shortened to private initialFocusEl_?: HTMLElement.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

@@ -93,7 +93,7 @@ class MDCDialog extends MDCComponent<MDCDialogFoundation> {
this.buttons_ = [].slice.call(this.root_.querySelectorAll<HTMLElement>(strings.BUTTON_SELECTOR));
this.defaultButton_ = this.root_.querySelector<HTMLElement>(strings.DEFAULT_BUTTON_SELECTOR);
this.focusTrapFactory_ = focusTrapFactory;
this.initialFocusEl_ = initialFocusEl as HTMLElement;
this.initialFocusEl_ = initialFocusEl as HTMLElement | undefined;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we cast to HTMLElement here when we're accepting Element above? Is there something we need from HTMLElement in particular?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was trying to make things simpler for Closure users (who typically pass an Element).

However, this method is called indirectly via the MDCComponent constructor (which takes an Element), so it actually shouldn't be an issue for them.

I'll change the type of the initialFocusEl arg to HTMLElement. The TypeScript compiler seems fine with it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

import {MDCList} from '@material/list/index';
import * as FocusTrapLib from 'focus-trap';

// TODO(acdvorak): Centralize this in mdc-base or mdc-dom?
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

RE this TODO: I wouldn't want to centralize a third-party dependency in a package that is depended upon by a large majority of our packages. Right now it's only a dependency of 2 packages.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair point. I'll remove it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

@mdc-web-bot
Copy link
Collaborator

All 624 screenshot tests passed for commit 1cd4d00 vs. feat/typescript! 💯🎉

@acdvorak acdvorak dismissed kfranqueiro’s stale review February 14, 2019 03:16

Addressed Ken's comments; Matt approved

@acdvorak acdvorak merged commit f8ba48f into feat/typescript Feb 14, 2019
@acdvorak acdvorak deleted the feat/typescript--drawer branch February 14, 2019 03:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants