Skip to content

(maint) update to ember 5.12, modernize components and tests #55

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

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 10 additions & 10 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,25 @@

## Installation

* `git clone <repository-url>`
* `cd puppet-ivy-tabs`
* `yarn install`
- `git clone <repository-url>`
- `cd puppet-ivy-tabs`
- `yarn install`

## Linting

* `yarn lint`
* `yarn lint:fix`
- `yarn lint`
- `yarn lint:fix`

## Running tests

* `yarn test` – Runs the test suite on the current Ember version
* `yarn test:ember --server` – Runs the test suite in "watch mode"
* `yarn test:ember-compatibility` – Runs the test suite against multiple Ember versions
- `yarn test` – Runs the test suite on the current Ember version
- `yarn test:ember --server` – Runs the test suite in "watch mode"
- `yarn test:ember-compatibility` – Runs the test suite against multiple Ember versions

## Running the dummy application

* `yarn start`
* Visit the dummy application at [http://localhost:4200](http://localhost:4200).
- `yarn start`
- Visit the dummy application at [http://localhost:4200](http://localhost:4200).

For more information on using ember-cli, visit [https://cli.emberjs.com/release/](https://cli.emberjs.com/release/).

Expand Down
14 changes: 5 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,23 +1,20 @@
# @puppet/ivy-tabs

[![Build Status](https://travis-ci.org/IvyApp/ivy-tabs.svg?branch=master)](https://travis-ci.org/IvyApp/ivy-tabs)
[![Dependabot Status](https://api.dependabot.com/badges/status?host=github&repo=IvyApp/ivy-tabs)](https://dependabot.com)
[![Ember Observer Score](http://emberobserver.com/badges/ivy-tabs.svg)](http://emberobserver.com/addons/ivy-tabs)

A group of Ember.js Components that interact to create a [WAI-ARIA tab] interface.

Special thanks to [ic-tabs], which this addon is based on.
## Compatibility

* Ember.js v4.12 or above
* Ember CLI v4.12 or above
* Node.js v18 or above
- Ember.js v4.12 or above
- Ember CLI v4.12 or above
- Node.js v18 or above

## Installation

```sh
$ ember install ivy-tabs
```
ember install @puppet/ivy-tabs
```

## Usage

Expand Down Expand Up @@ -93,7 +90,6 @@ override the `activeClass` property of your ivy-tabs-tabpanel):
}
```


## Contributing

Fork this repo, make a new branch, and send a pull request. Make sure your
Expand Down
1 change: 1 addition & 0 deletions addon/components/ivy-tabs-tab.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
role="tab"
href="{{this.href}}"
{{on "click" this.handleClick}}
{{this.registerWithTabList}}
...attributes>
{{~yield~}}
</a>
33 changes: 15 additions & 18 deletions addon/components/ivy-tabs-tab.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import Component from '@glimmer/component';
import { once } from '@ember/runloop';
import { action } from '@ember/object';
import { modifier } from 'ember-modifier';
import { runTask } from 'ember-lifeline';

/**
* @module ivy-tabs
Expand All @@ -14,16 +15,14 @@ let ivyTabsTabCount = 0;
* @extends Ember.Component
*/
export default class IvyTabsTabComponent extends Component {
_registerWithTabList() {
this.args.tabList.registerTab(this);
if (this.isSelected) {
this.select();
}
}

_unregisterWithTabList() {
this.args.tabList.unregisterTab(this);
}
registerWithTabList = modifier(() => {
runTask(this, () => {
this.args.tabList.registerTab(this);
});
return () => {
this.args.tabList.unregisterTab(this);
};
});

/**
* Tells screenreaders which panel this tab controls.
Expand Down Expand Up @@ -85,7 +84,6 @@ export default class IvyTabsTabComponent extends Component {
constructor() {
super(...arguments);
this.uniqueSelector = `ivy-tabs-tab-${ivyTabsTabCount++}`;
once(this, this._registerWithTabList);
}

/**
Expand All @@ -106,7 +104,11 @@ export default class IvyTabsTabComponent extends Component {
@action
select() {
const onSelect = this.args.onSelect;
if (!this.isDestroying && typeof onSelect === 'function') {
if (
!this.isDestroying &&
!this.isDestroyed &&
typeof onSelect === 'function'
) {
onSelect(this.args.model);
}
}
Expand Down Expand Up @@ -189,9 +191,4 @@ export default class IvyTabsTabComponent extends Component {
}
return null;
}

willDestroy() {
super.willDestroy(...arguments);
once(this, this._unregisterWithTabList);
}
}
6 changes: 4 additions & 2 deletions addon/components/ivy-tabs-tablist.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
aria-label={{if this.effectiveAriaLabel this.effectiveAriaLabel}}
aria-multiselectable={{this.isMultiSelectable}}
...attributes
{{on "keydown" this.keyDown}}>
{{on "keydown" this.keyDown}}
{{this.registerWithTabsContainer}}>

{{~yield (hash tab=(component "ivy-tabs-tab" tabList=this))~}}
</ul>
Expand All @@ -22,7 +23,8 @@
aria-label={{if this.effectiveAriaLabel this.effectiveAriaLabel}}
aria-multiselectable={{this.isMultiSelectable}}
...attributes
{{on "keydown" this.keyDown}}>
{{on "keydown" this.keyDown}}
{{this.registerWithTabsContainer}}>

{{~yield (hash tab=(component "ivy-tabs-tab" tabList=this))~}}
</div>
Expand Down
66 changes: 37 additions & 29 deletions addon/components/ivy-tabs-tablist.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import Component from '@glimmer/component';
import { isNone, isEmpty } from '@ember/utils';
import { isNone } from '@ember/utils';
import { action } from '@ember/object';
import { tracked } from '@glimmer/tracking';
import { once, scheduleOnce } from '@ember/runloop';
import { modifier } from 'ember-modifier';
import { runTask } from 'ember-lifeline';

export const DOWN_ARROW = 40;
export const LEFT_ARROW = 37;
Expand All @@ -21,15 +22,17 @@ let instanceCount = 0;
* @extends Ember.Component
*/
export default class IvyTabsTabListComponent extends Component {
_registerWithTabsContainer() {
this.internalId = `ivy-tabs-list-${instanceCount++}`;
registerWithTabsContainer = modifier(() => {
this.args.tabsContainer.registerTabList(this);
once(this, this.selectTab);
}

_unregisterWithTabsContainer() {
this.args.tabsContainer.unregisterTabList(this);
}
// if none of the tabs are selected, try to select one
let selected = this.tabs.find((tab) => tab.isSelected);
if (!selected && this.tabs.length > 0) {
this.selectTab();
}
return () => {
this.args.tabsContainer.unregisterTabList(this);
};
});

/**
* Tells screenreaders that only one tab can be selected at a time.
Expand Down Expand Up @@ -71,17 +74,20 @@ export default class IvyTabsTabListComponent extends Component {
*
* @method focusSelectedTab
*/
@action
focusSelectedTab() {
this.selectedTab.focus();
if (!this.isDestroyed && !this.isDestroying) {
this.selectedTab.focus();
}
}

constructor() {
super(...arguments);
this._registerWithTabsContainer();
this.internalId = `ivy-tabs-list-${instanceCount++}`;
}

get isEmpty() {
return isEmpty(this.tabs);
return this.tabs.length === 0;
}

/**
Expand All @@ -108,7 +114,7 @@ export default class IvyTabsTabListComponent extends Component {
}

event.preventDefault();
scheduleOnce('afterRender', this, this.focusSelectedTab);
runTask(this, this.focusSelectedTab);
}

/**
Expand All @@ -117,16 +123,20 @@ export default class IvyTabsTabListComponent extends Component {
* @method registerTab
* @param {IvyTabs.IvyTabComponent} tab
*/
@action
registerTab(tab) {
this.tabs = this.tabs.concat(tab);
once(this, this.selectTab);
runTask(this, () => {
this.tabs = this.tabs.concat(tab);
this.selectTab();
});
}

/**
* Selects the next tab in the list, if any.
*
* @method selectNextTab
*/
@action
selectNextTab() {
const selectedTab = this.selectedTab;
const tabs = this.tabs;
Expand Down Expand Up @@ -155,6 +165,7 @@ export default class IvyTabsTabListComponent extends Component {
*
* @method selectPreviousTab
*/
@action
selectPreviousTab() {
const selectedTab = this.selectedTab;
const tabs = this.tabs;
Expand Down Expand Up @@ -194,6 +205,7 @@ export default class IvyTabsTabListComponent extends Component {
return this.args['aria-label'];
}

@action
selectTab() {
const selection = this.selection;

Expand All @@ -213,18 +225,20 @@ export default class IvyTabsTabListComponent extends Component {
selectTabByIndex(index) {
const tab = this.tabs[index];

if (tab) {
tab.select();
if (tab && tab.isSelected === false) {
runTask(tab, () => {
tab.select();
});
}
}

selectTabByModel(model) {
const tab = this.tabs.find((element) => {
return element.model === model;
});
const tab = this.tabs.find((element) => element.model === model);

if (tab) {
tab.select();
runTask(tab, () => {
tab.select();
});
}
}

Expand Down Expand Up @@ -253,8 +267,7 @@ export default class IvyTabsTabListComponent extends Component {
*/
unregisterTab(tab) {
const index = tab.index;

if (tab.isSelected) {
if (tab.isSelected && !this.isDestroying && !this.isDestroyed) {
if (index === 0) {
this.selectNextTab();
} else {
Expand All @@ -266,9 +279,4 @@ export default class IvyTabsTabListComponent extends Component {
return element !== tab;
});
}

willDestroy() {
super.willDestroy(...arguments);
this._unregisterWithTabsContainer();
}
}
2 changes: 1 addition & 1 deletion addon/components/ivy-tabs-tabpanel.hbs
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
<div class="ivy-tabs-tabpanel {{this.active}}" aria-hidden={{this.ariaHidden}} aria-labelledby={{this.ariaLabelledby}} role={{this.ariaRole}} tabindex={{if this.isSelected "0"}} id={{this.elementId}} ...attributes>
<div class="ivy-tabs-tabpanel {{this.active}}" aria-hidden={{this.ariaHidden}} aria-labelledby={{this.ariaLabelledby}} role={{this.ariaRole}} tabindex={{if this.isSelected "0"}} id={{this.elementId}} {{this.registerWithTabsContainer}} ...attributes>
{{yield}}
</div>
24 changes: 10 additions & 14 deletions addon/components/ivy-tabs-tabpanel.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import Component from '@glimmer/component';
import { once } from '@ember/runloop';
import { runTask } from 'ember-lifeline';
import { modifier } from 'ember-modifier';

/**
* @module ivy-tabs
Expand All @@ -13,13 +14,14 @@ let instanceCount = 0;
* @extends Ember.Component
*/
export default class IvyTabsPanelComponent extends Component {
_registerWithTabsContainer() {
this.args.tabsContainer.registerTabPanel(this);
}

_unregisterWithTabsContainer() {
this.args.tabsContainer.unregisterTabPanel(this);
}
registerWithTabsContainer = modifier(() => {
runTask(this, () => {
this.args.tabsContainer.registerTabPanel(this);
});
return () => {
this.args.tabsContainer.unregisterTabPanel(this);
};
});

/**
* Accessed as a className binding to apply the panel's `activeClass` CSS
Expand Down Expand Up @@ -89,7 +91,6 @@ export default class IvyTabsPanelComponent extends Component {
constructor() {
super(...arguments);
this.internalId = `ivy-tabs-panel-${instanceCount++}`;
once(this, this._registerWithTabsContainer);
}

/**
Expand Down Expand Up @@ -133,9 +134,4 @@ export default class IvyTabsPanelComponent extends Component {
}
return [];
}

willDestroy() {
super.willDestroy(...arguments);
once(this, this._unregisterWithTabsContainer);
}
}
Loading