Skip to content

Commit

Permalink
Update bs-tab and related components to Glimmer component (ember-boot…
Browse files Browse the repository at this point in the history
…strap#2034)

* Update bs-tab and related components to Glimmer component

* Rename `view` parameter in filter function to `child`

Co-authored-by: Jeldrik Hanschke <[email protected]>

* Replace `Array#filter()[0]` call with `Array#find()`

Co-authored-by: Jeldrik Hanschke <[email protected]>

---------

Co-authored-by: Jeldrik Hanschke <[email protected]>
  • Loading branch information
SanderKnauff and jelhan authored Dec 5, 2023
1 parent 9e7c590 commit 46dc67f
Show file tree
Hide file tree
Showing 4 changed files with 135 additions and 102 deletions.
20 changes: 10 additions & 10 deletions addon/components/bs-tab.hbs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
<div ...attributes>
<div ...attributes {{did-update this.listenToActiveId @activeId}}>
{{#if this.customTabs}}
{{yield
(hash
pane=(component (ensure-safe-component (bs-default @paneComponent (component "bs-tab/pane"))) parent=this activeId=this.isActiveId fade=this.fade fadeTransition=this.fadeTransition)
activeId=this.isActiveId
pane=(component (ensure-safe-component (bs-default @paneComponent (component "bs-tab/pane"))) parent=this activeId=this.activeId fade=this.fade fadeTransition=this.fadeTransition registerChild=this.registerChild unregisterChild=this.unregisterChild)
activeId=this.activeId
select=this.select
)
}}
Expand All @@ -12,7 +12,7 @@
<NavComponent @type={{this.type}} role="tablist" as |Nav|>
{{#each this.navItems as |item|}}
{{#if item.isGroup}}
<Nav.dropdown class={{if (bs-contains item.childIds this.isActiveId) "active"}} role="presentation" as |DD|>
<Nav.dropdown class={{if (bs-contains item.childIds this.activeId) "active"}} role="presentation" as |DD|>
<DD.toggle>{{item.groupTitle}} <span class="caret"></span></DD.toggle>
<DD.menu as |Menu|>
{{#each item.children as |subItem|}}
Expand All @@ -21,7 +21,7 @@
<a
href="#{{subItem.id}}"
role="tab"
class="dropdown-item {{if (bs-eq this.isActiveId subItem.id) "active"}}"
class="dropdown-item {{if (bs-eq this.activeId subItem.id) "active"}}"
{{on "click" (fn this.select subItem.id)}}
>
{{subItem.title}}
Expand All @@ -31,12 +31,12 @@
</DD.menu>
</Nav.dropdown>
{{else}}
<Nav.item @active={{bs-eq item.id this.isActiveId}} role="presentation">
<Nav.item @active={{bs-eq item.id this.activeId}} role="presentation">
<a
href="#{{item.id}}"
role="tab"
class="nav-link {{if (bs-eq this.isActiveId item.id) "active"}}"
aria-selected={{if (bs-eq this.isActiveId item.id) "true" "false"}}
class="nav-link {{if (bs-eq this.activeId item.id) "active"}}"
aria-selected={{if (bs-eq this.activeId item.id) "true" "false"}}
{{on "click" (fn this.select item.id)}}
>
{{item.title}}
Expand All @@ -50,8 +50,8 @@
<div class="tab-content">
{{yield
(hash
pane=(component (ensure-safe-component (bs-default @paneComponent (component "bs-tab/pane"))) parent=this activeId=this.isActiveId fade=this.fade fadeTransition=this.fadeTransition)
activeId=this.isActiveId
pane=(component (ensure-safe-component (bs-default @paneComponent (component "bs-tab/pane"))) parent=this activeId=this.activeId fade=this.fade fadeTransition=this.fadeTransition registerChild=this.registerChild unregisterChild=this.unregisterChild)
activeId=this.activeId
select=this.select
)
}}
Expand Down
110 changes: 64 additions & 46 deletions addon/components/bs-tab.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,10 @@
import { tagName } from '@ember-decorators/component';
import { action, computed } from '@ember/object';
import { filter, oneWay } from '@ember/object/computed';
import Component from '@ember/component';
import { action } from '@ember/object';
import Component from '@glimmer/component';
import { isPresent } from '@ember/utils';
import { A } from '@ember/array';
import ComponentParent from 'ember-bootstrap/mixins/component-parent';
import TabPane from 'ember-bootstrap/components/bs-tab/pane';
import listenTo from 'ember-bootstrap/utils/cp/listen-to';
import defaultValue from 'ember-bootstrap/utils/default-decorator';
import deprecateSubclassing from 'ember-bootstrap/utils/deprecate-subclassing';
import { tracked } from '@glimmer/tracking';
import { schedule } from '@ember/runloop';

/**
Tab component for dynamic tab functionality that mimics the behaviour of Bootstrap's tab.js plugin,
Expand Down Expand Up @@ -56,10 +52,10 @@ import deprecateSubclassing from 'ember-bootstrap/utils/deprecate-subclassing';
### Custom tabs
When having the tab pane's `title` as the tab navigation title is not sufficient, for example because you want to
integrate some other dynamic content, maybe even other components in the tab navigation item, then you have to setup
integrate some other dynamic content, maybe even other components in the tab navigation item, then you have to set up
your navigation by yourself.
Set `customTabs` to true to deactivate the automatic tab navigation generation. Then setup your navigation, probably
Set `customTabs` to true to deactivate the automatic tab navigation generation. Then set up your navigation, probably
using a [Components.Nav](Components.Nav.html) component. The tab component yields the `activeId` property as well as
its `select` action, which you would have to use to manually set the `active` state of the navigation items and to
trigger the selection of the different tab panes, using their ids:
Expand Down Expand Up @@ -110,13 +106,11 @@ import deprecateSubclassing from 'ember-bootstrap/utils/deprecate-subclassing';
@class Tab
@namespace Components
@extends Ember.Component
@uses Mixins.ComponentParent
@extends Component
@public
*/
@tagName('')
@deprecateSubclassing
export default class Tab extends Component.extend(ComponentParent) {
export default class Tab extends Component {
/**
* Type of nav, either "pills" or "tabs"
*
Expand All @@ -125,8 +119,9 @@ export default class Tab extends Component.extend(ComponentParent) {
* @default 'tabs'
* @public
*/
@defaultValue
type = 'tabs';
get type() {
return this.args.type ?? 'tabs';
}

/**
* @property paneComponent
Expand All @@ -141,20 +136,24 @@ export default class Tab extends Component.extend(ComponentParent) {
*/

/**
* By default the tabs will be automatically generated using the available [TabPane](Components.TabPane.html)
* components. If set to true, you can deactivate this and setup the tabs manually. See the example above.
* By default, the tabs will be automatically generated using the available [TabPane](Components.TabPane.html)
* components. If set to true, you can deactivate this and set up the tabs manually. See the example above.
*
* @property customTabs
* @type boolean
* @default false
* @public
*/
@defaultValue
customTabs = false;
get customTabs() {
return this.args.customTabs ?? false;
}

@tracked
children = [];

/**
* The id (`id`) of the active [TabPane](Components.TabPane.html).
* By default the first tab will be active, but this can be changed by setting this property
* By default, the first tab will be active, but this can be changed by setting this property
*
* ```hbs
* {{#bs-tab activeId="pane2"}}
Expand All @@ -174,15 +173,16 @@ export default class Tab extends Component.extend(ComponentParent) {
* @type string
* @public
*/
@oneWay('childPanes.firstObject.id')
activeId;
get activeId() {
return this.selectedId ?? this.childPanes[0]?.id;
}

/**
* @property isActiveId
* @property selectedId
* @private
*/
@listenTo('activeId')
isActiveId;
@tracked
selectedId;

/**
* Set to false to disable the fade animation when switching tabs.
Expand All @@ -192,19 +192,21 @@ export default class Tab extends Component.extend(ComponentParent) {
* @default true
* @public
*/
@defaultValue
fade = true;
get fade() {
return this.args.fade ?? true;
}

/**
* The duration of the fade animation
*
* @property fadeDuration
* @type integer
* @type number
* @default 150
* @public
*/
@defaultValue
fadeDuration = 150;
get fadeDuration() {
return this.args.fadeDuration ?? 150;
}

/**
* This action is called when switching the active tab, with the new and previous pane id
Expand All @@ -215,7 +217,6 @@ export default class Tab extends Component.extend(ComponentParent) {
* @event onChange
* @public
*/
onChange() {}

/**
* All `TabPane` child components
Expand All @@ -225,10 +226,9 @@ export default class Tab extends Component.extend(ComponentParent) {
* @readonly
* @private
*/
@filter('children', function (view) {
return view instanceof TabPane;
})
childPanes;
get childPanes() {
return this.children.filter((child) => child instanceof TabPane);
}

/**
* Array of objects that define the tab structure
Expand All @@ -238,23 +238,22 @@ export default class Tab extends Component.extend(ComponentParent) {
* @readonly
* @private
*/
@computed('childPanes.@each.{id,title,group}')
get navItems() {
let items = A();
let items = [];
this.childPanes.forEach((pane) => {
let groupTitle = pane.get('groupTitle');
let item = pane.getProperties('id', 'title');
let groupTitle = pane.groupTitle;
let item = { id: pane.id, title: pane.title };
if (isPresent(groupTitle)) {
let group = items.findBy('groupTitle', groupTitle);
let group = items.find((item) => item.groupTitle === groupTitle);
if (group) {
group.children.push(item);
group.childIds.push(item.id);
} else {
items.push({
isGroup: true,
groupTitle,
children: A([item]),
childIds: A([item.id]),
children: [item],
childIds: [item.id],
});
}
} else {
Expand All @@ -266,10 +265,29 @@ export default class Tab extends Component.extend(ComponentParent) {

@action
select(id) {
let previous = this.isActiveId;
if (this.onChange(id, previous) !== false) {
let previous = this.activeId;
if (this.args.onChange?.(id, previous) !== false) {
// change active tab when `onChange` does not return false
this.set('isActiveId', id);
this.selectedId = id;
}
}

@action
registerChild(element) {
schedule('actions', this, () => {
this.children = [...this.children, element];
});
}

@action
unregisterChild(element) {
schedule('actions', this, () => {
this.children = this.children.filter((value) => value !== element);
});
}

@action
listenToActiveId() {
this.selectedId = this.args.activeId;
}
}
2 changes: 2 additions & 0 deletions addon/components/bs-tab/pane.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
role="tabpanel"
...attributes
{{create-ref "mainNode"}}
{{did-insert this.updateActive @active}}
{{did-update this.showHide this.isActive}}
>
{{yield}}
</div>
Loading

0 comments on commit 46dc67f

Please sign in to comment.