@hashicorp/design-system-components
Version:
Helios Design System Components
115 lines (112 loc) • 6.05 kB
JavaScript
import Component from '@glimmer/component';
import { assert } from '@ember/debug';
import { hash } from '@ember/helper';
import { or } from 'ember-truth-helpers';
import style from 'ember-style-modifier';
import didInsert from '@ember/render-modifiers/modifiers/did-insert';
import { HdsDropdownPositionValues, HdsDropdownPositionToPlacementValues } from './types.js';
import HdsPopoverPrimitive from '../popover-primitive/index.js';
import HdsDropdownToggleButton from './toggle/button.js';
import HdsDropdownToggleIcon from './toggle/icon.js';
import HdsDropdownHeader from './header.js';
import HdsDropdownListItemCheckbox from './list-item/checkbox.js';
import HdsDropdownListItemCheckmark from './list-item/checkmark.js';
import HdsDropdownListItemCopyItem from './list-item/copy-item.js';
import HdsDropdownListItemDescription from './list-item/description.js';
import HdsDropdownListItemGeneric from './list-item/generic.js';
import HdsDropdownListItemInteractive from './list-item/interactive.js';
import HdsDropdownListItemRadio from './list-item/radio.js';
import HdsDropdownListItemSeparator from './list-item/separator.js';
import HdsDropdownListItemTitle from './list-item/title.js';
import HdsDropdownFooter from './footer.js';
import { precompileTemplate } from '@ember/template-compilation';
import { setComponentTemplate } from '@ember/component';
/**
* Copyright IBM Corp. 2021, 2025
* SPDX-License-Identifier: MPL-2.0
*/
const DEFAULT_POSITION = HdsDropdownPositionValues.BottomRight;
const POSITIONS = Object.values(HdsDropdownPositionValues);
class HdsDropdown extends Component {
get listPosition() {
const {
listPosition = DEFAULT_POSITION
} = this.args;
assert(`@listPosition for "Hds::Dropdown::Index" must be one of the following: ${POSITIONS.join(', ')}; received: ${listPosition}`, POSITIONS.includes(listPosition));
return listPosition;
}
get enableCollisionDetection() {
return this.args.enableCollisionDetection ?? false;
}
get matchToggleWidth() {
return this.args.matchToggleWidth ?? false;
}
get anchoredPositionOptions() {
// custom options specific for the `RichTooltip` component
// for details see the `hds-anchored-position` modifier
return {
placement: HdsDropdownPositionToPlacementValues[this.listPosition],
offsetOptions: 4,
enableCollisionDetection: this.enableCollisionDetection ? 'flip' : false,
matchToggleWidth: this.matchToggleWidth,
boundary: this.args.boundary
};
}
get classNames() {
const classes = ['hds-dropdown'];
// add a class based on the @isInline argument
if (this.args.isInline) {
classes.push('hds-dropdown--is-inline');
}
return classes.join(' ');
}
get classNamesContent() {
const classes = ['hds-dropdown__content'];
// add a class based on the @listPosition argument
// TODO: we preserved these classes to avoid introducing breaking changes for consumers who rely on these classes for tests, but we aim to remove them in the next major release
// context: https://github.com/hashicorp/design-system/pull/2309#discussion_r1706941892
classes.push(`hds-dropdown__content--position-${this.listPosition}`);
// add a class based on the @width or @matchToggleWidth arguments
if (this.args.width || this.args.matchToggleWidth) {
classes.push('hds-dropdown__content--fixed-width');
}
return classes.join(' ');
}
didInsertList = element => {
const checkmarkItems = element.querySelectorAll(`[role="option"]`);
if (checkmarkItems.length) {
const toggleButtonId = element.closest('.hds-dropdown')?.querySelector('.hds-dropdown-toggle-button')?.getAttribute('id');
element.setAttribute('role', 'listbox');
if (toggleButtonId) {
element.setAttribute('aria-labelledby', toggleButtonId);
}
}
};
static {
setComponentTemplate(precompileTemplate("<HdsPopoverPrimitive @isOpen={{@isOpen}} @onClose={{@onClose}} @onFocusOut={{@onFocusOut}} @boundary={{@boundary}} @enableClickEvents={{true}} as |PP|>\n <div class={{this.classNames}} ...attributes {{PP.setupPrimitiveContainer}}>\n {{yield (hash ToggleButton=(component HdsDropdownToggleButton isOpen=PP.isOpen setupPrimitiveToggle=PP.setupPrimitiveToggle) ToggleIcon=(component HdsDropdownToggleIcon isOpen=PP.isOpen setupPrimitiveToggle=PP.setupPrimitiveToggle) close=PP.hidePopover)}}\n <div tabindex=\"-1\" class={{this.classNamesContent}} {{style width=@width max-height=@height}} {{PP.setupPrimitivePopover anchoredPositionOptions=this.anchoredPositionOptions}}>\n {{#if (or PP.isOpen @preserveContentInDom)}}\n {{yield (hash Header=HdsDropdownHeader close=PP.hidePopover)}}\n <ul class=\"hds-dropdown__list\" {{didInsert this.didInsertList}}>\n {{yield (hash close=PP.hidePopover Checkbox=HdsDropdownListItemCheckbox Checkmark=HdsDropdownListItemCheckmark CopyItem=HdsDropdownListItemCopyItem Description=HdsDropdownListItemDescription Generic=HdsDropdownListItemGeneric Interactive=HdsDropdownListItemInteractive Radio=HdsDropdownListItemRadio Separator=HdsDropdownListItemSeparator Title=HdsDropdownListItemTitle)}}\n </ul>\n {{yield (hash close=PP.hidePopover Footer=HdsDropdownFooter)}}\n {{/if}}\n </div>\n </div>\n</HdsPopoverPrimitive>", {
strictMode: true,
scope: () => ({
HdsPopoverPrimitive,
hash,
HdsDropdownToggleButton,
HdsDropdownToggleIcon,
style,
or,
HdsDropdownHeader,
didInsert,
HdsDropdownListItemCheckbox,
HdsDropdownListItemCheckmark,
HdsDropdownListItemCopyItem,
HdsDropdownListItemDescription,
HdsDropdownListItemGeneric,
HdsDropdownListItemInteractive,
HdsDropdownListItemRadio,
HdsDropdownListItemSeparator,
HdsDropdownListItemTitle,
HdsDropdownFooter
})
}), this);
}
}
export { DEFAULT_POSITION, POSITIONS, HdsDropdown as default };
//# sourceMappingURL=index.js.map