Skip to content

Commit

Permalink
Update bs-dropdown and related components to Glimmer component (ember…
Browse files Browse the repository at this point in the history
  • Loading branch information
SanderKnauff authored Nov 27, 2023
1 parent 380d308 commit 94ed264
Show file tree
Hide file tree
Showing 7 changed files with 114 additions and 116 deletions.
8 changes: 7 additions & 1 deletion addon/components/bs-dropdown.hbs
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
{{#let (element this.htmlTag) as |Tag|}}
<Tag class="{{this.containerClass}} {{if this.inNav "nav-item"}} {{if this.isOpen "show"}}" ...attributes>
<Tag
class="{{this.containerClass}}
{{if this.inNav "nav-item"}}
{{if this.isOpen "show"}}"
...attributes
{{did-update this.updateIsOpen @open}}
>
{{yield
(hash
button=(component (ensure-safe-component (bs-default @buttonComponent (component "bs-dropdown/button")))
Expand Down
50 changes: 27 additions & 23 deletions addon/components/bs-dropdown.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import { tagName } from '@ember-decorators/component';
import { action, computed } from '@ember/object';
import Component from '@ember/component';
import defaultValue from 'ember-bootstrap/utils/default-decorator';
import { action } from '@ember/object';
import Component from '@glimmer/component';
import { assert } from '@ember/debug';
import { getOwnConfig, macroCondition } from '@embroider/macros';
import deprecateSubclassing from 'ember-bootstrap/utils/deprecate-subclassing';
import { tracked } from '@glimmer/tracking';

const ESCAPE_KEYCODE = 27; // KeyboardEvent.which value for Escape (Esc) key
const SPACE_KEYCODE = 32; // KeyboardEvent.which value for space key
Expand Down Expand Up @@ -173,10 +172,9 @@ const SUPPORTED_KEYCODES = [
@class Dropdown
@namespace Components
@extends Ember.Component
@extends Component
@public
s*/
@tagName('')
@deprecateSubclassing
export default class Dropdown extends Component {
/**
Expand All @@ -187,8 +185,9 @@ export default class Dropdown extends Component {
* @type {string}
* @public
*/
@defaultValue
htmlTag = 'div';
get htmlTag() {
return this.args.htmlTag ?? 'div';
}

/**
* This property reflects the state of the dropdown, whether it is open or closed.
Expand All @@ -198,8 +197,7 @@ export default class Dropdown extends Component {
* @type boolean
* @private
*/
@defaultValue
isOpen = false;
@tracked isOpen = this.args.isOpen ?? false;

/**
* By default, clicking on an open dropdown menu will close it. Set this property to false for the menu to stay open.
Expand All @@ -209,8 +207,9 @@ export default class Dropdown extends Component {
* @type boolean
* @public
*/
@defaultValue
closeOnMenuClick = true;
get closeOnMenuClick() {
return this.args.closeOnMenuClick ?? true;
}

/**
* By default, the dropdown menu will expand downwards. Other options include, 'up', 'left' and 'right'
Expand All @@ -220,8 +219,9 @@ export default class Dropdown extends Component {
* @default 'down'
* @public
*/
@defaultValue
direction = 'down';
get direction() {
return this.args.direction ?? 'down';
}

/**
* Indicates the dropdown is being used as a navigation item dropdown.
Expand All @@ -241,7 +241,6 @@ export default class Dropdown extends Component {
* @readonly
* @private
*/
@computed('direction', 'hasButton', 'toggleElement.classList')
get containerClass() {
let dropDirectionClass = `drop${this.direction}`;
if (macroCondition(getOwnConfig().isBS5)) {
Expand All @@ -268,6 +267,7 @@ export default class Dropdown extends Component {
* @property toggleElement
* @private
*/
@tracked
toggleElement = null;

/**
Expand All @@ -276,6 +276,7 @@ export default class Dropdown extends Component {
* @readonly
* @private
*/
@tracked
menuElement = null;

/**
Expand All @@ -285,7 +286,6 @@ export default class Dropdown extends Component {
* @param {*} value
* @public
*/
onShow(value) {} // eslint-disable-line no-unused-vars

/**
* Action is called when dropdown is about to be hidden
Expand All @@ -295,7 +295,6 @@ export default class Dropdown extends Component {
* @param {*} value
* @public
*/
onHide(value) {} // eslint-disable-line no-unused-vars

@action
toggleDropdown() {
Expand All @@ -308,15 +307,15 @@ export default class Dropdown extends Component {

@action
openDropdown() {
this.set('isOpen', true);
this.onShow();
this.isOpen = true;
this.args.onShow?.();
}

@action
closeDropdown() {
if (this.onHide() === false) return;
if (this.args.onHide?.() === false) return;

this.set('isOpen', false);
this.isOpen = false;
}

/**
Expand Down Expand Up @@ -423,7 +422,7 @@ export default class Dropdown extends Component {
element instanceof HTMLElement,
);

this.set(`${type}Element`, element);
this[`${type}Element`] = element;
}

@action
Expand All @@ -433,7 +432,12 @@ export default class Dropdown extends Component {
type === 'toggle' || type === 'menu',
);

this.set(`${type}Element`, null);
this[`${type}Element`] = null;
}

@action
updateIsOpen(open) {
this.isOpen = open;
}

/**
Expand Down
88 changes: 45 additions & 43 deletions addon/components/bs-dropdown/menu.hbs
Original file line number Diff line number Diff line change
@@ -1,43 +1,45 @@
{{#if this._isOpen}}
{{#if this._renderInPlace}}
<div
class="dropdown-menu {{this.alignClass}} {{if this.isOpen "show"}}"
tabindex="-1"
...attributes
{{popper-tooltip this.toggleElement this.popperOptions}}
{{did-insert @registerChildElement "menu"}}
{{will-destroy @unregisterChildElement "menu"}}
{{create-ref "menuElement"}}
>
{{yield
(hash
item=(ensure-safe-component (bs-default @itemComponent (component "bs-dropdown/menu/item")))
link-to=(ensure-safe-component (bs-default @linkToComponent (component "bs-link-to" class="dropdown-item")))
linkTo=(ensure-safe-component (bs-default @linkToComponent (component "bs-link-to" class="dropdown-item")))
divider=(ensure-safe-component (bs-default @dividerComponent (component "bs-dropdown/menu/divider")))
)
}}
</div>
{{else}}
{{#in-element this.destinationElement insertBefore=null}}
<div
class="dropdown-menu {{this.alignClass}} {{if this.isOpen "show"}}"
tabindex="-1"
...attributes
{{popper-tooltip this.toggleElement this.popperOptions}}
{{did-insert @registerChildElement "menu"}}
{{will-destroy @unregisterChildElement "menu"}}
{{create-ref "menuElement"}}
>
{{yield
(hash
item=(ensure-safe-component (bs-default @itemComponent (component "bs-dropdown/menu/item")))
link-to=(ensure-safe-component (bs-default @linkToComponent (component "bs-link-to" class="dropdown-item")))
linkTo=(ensure-safe-component (bs-default @linkToComponent (component "bs-link-to" class="dropdown-item")))
divider=(ensure-safe-component (bs-default @dividerComponent (component "bs-dropdown/menu/divider")))
)
}}
</div>
{{/in-element}}
{{/if}}
{{/if}}
{{#if @isOpen}}
{{#if this._renderInPlace}}
<div
class="dropdown-menu {{this.alignClass}} {{if this.isOpen "show"}}"
tabindex="-1"
...attributes
{{popper-tooltip @toggleElement this.popperOptions}}
{{did-insert @registerChildElement "menu"}}
{{will-destroy @unregisterChildElement "menu"}}
{{did-update this.updateIsOpen @open}}
{{create-ref "menuElement"}}
>
{{yield
(hash
item=(ensure-safe-component (bs-default @itemComponent (component "bs-dropdown/menu/item")))
link-to=(ensure-safe-component (bs-default @linkToComponent (component "bs-link-to" class="dropdown-item")))
linkTo=(ensure-safe-component (bs-default @linkToComponent (component "bs-link-to" class="dropdown-item")))
divider=(ensure-safe-component (bs-default @dividerComponent (component "bs-dropdown/menu/divider")))
)
}}
</div>
{{else}}
{{#in-element this.destinationElement insertBefore=null}}
<div
class="dropdown-menu {{this.alignClass}} {{if this.isOpen "show"}}"
tabindex="-1"
...attributes
{{popper-tooltip @toggleElement this.popperOptions}}
{{did-insert @registerChildElement "menu"}}
{{will-destroy @unregisterChildElement "menu"}}
{{did-update this.updateIsOpen @open}}
{{create-ref "menuElement"}}
>
{{yield
(hash
item=(ensure-safe-component (bs-default @itemComponent (component "bs-dropdown/menu/item")))
link-to=(ensure-safe-component (bs-default @linkToComponent (component "bs-link-to" class="dropdown-item")))
linkTo=(ensure-safe-component (bs-default @linkToComponent (component "bs-link-to" class="dropdown-item")))
divider=(ensure-safe-component (bs-default @dividerComponent (component "bs-dropdown/menu/divider")))
)
}}
</div>
{{/in-element}}
{{/if}}
{{/if}}
50 changes: 22 additions & 28 deletions addon/components/bs-dropdown/menu.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import { tagName } from '@ember-decorators/component';
import { action, computed } from '@ember/object';
import Component from '@ember/component';
import { action } from '@ember/object';
import Component from '@glimmer/component';
import { next } from '@ember/runloop';
import { getDestinationElement } from 'ember-bootstrap/utils/dom';
import defaultValue from 'ember-bootstrap/utils/default-decorator';
import deprecateSubclassing from 'ember-bootstrap/utils/deprecate-subclassing';
import { ref } from 'ember-ref-bucket';
import { tracked } from '@glimmer/tracking';

/**
Component for the dropdown menu.
Expand All @@ -14,10 +13,9 @@ import { ref } from 'ember-ref-bucket';
@class DropdownMenu
@namespace Components
@extends Ember.Component
@extends Component
@public
*/
@tagName('')
@deprecateSubclassing
export default class DropdownMenu extends Component {
/**
Expand All @@ -33,7 +31,9 @@ export default class DropdownMenu extends Component {
* @type string
* @protected
*/
ariaRole = 'menu';
get ariaRole() {
return this.args.ariaRole ?? 'menu';
}

/**
* Alignment of the menu, either "left" or "right"
Expand All @@ -43,36 +43,38 @@ export default class DropdownMenu extends Component {
* @default left
* @public
*/
@defaultValue
align = 'left';
get align() {
return this.args.align ?? 'false';
}

/**
* @property direction
* @default 'down'
* @type string
* @private
*/
@defaultValue
direction = 'down';
get direction() {
return this.args.direction ?? 'down';
}

/**
* By default the menu is rendered in the same place as the dropdown. If you experience clipping
* By default, the menu is rendered in the same place as the dropdown. If you experience clipping
* issues, you can set this to false to render the menu in a wormhole at the top of the DOM.
*
* @property renderInPlace
* @type boolean
* @default true
* @public
*/
@defaultValue
renderInPlace = true;
get renderInPlace() {
return this.args.renderInPlace ?? true;
}

/**
* @property _renderInPlace
* @type boolean
* @private
*/
@computed('destinationElement', 'renderInPlace')
get _renderInPlace() {
return this.renderInPlace || !this.destinationElement;
}
Expand All @@ -85,38 +87,31 @@ export default class DropdownMenu extends Component {
* @readonly
* @private
*/
@computed
get destinationElement() {
return getDestinationElement(this);
}

@computed('align')
get alignClass() {
return this.align !== 'left' ? `dropdown-menu-${this.align}` : undefined;
}

@computed
get isOpen() {
return false;
}
@tracked
isOpen = this.args.isOpen;

set isOpen(value) {
@action
updateIsOpen(value) {
// delay removing the menu from DOM to allow (delegated Ember) event to fire for the menu's children
// Fixes https://github.com/kaliber5/ember-bootstrap/issues/660
next(() => {
if (this.isDestroying || this.isDestroyed) {
return;
}
this.set('_isOpen', value);
this.isOpen = value;
});
return value;
}

_isOpen = false;
flip = true;
_popperApi = null;

@computed('direction', 'align')
get popperPlacement() {
let placement = 'bottom-start';
let { direction, align } = this;
Expand Down Expand Up @@ -148,7 +143,6 @@ export default class DropdownMenu extends Component {
}
}

@computed('flip', 'popperPlacement')
get popperOptions() {
return {
placement: this.popperPlacement,
Expand Down
Loading

0 comments on commit 94ed264

Please sign in to comment.