@fleetbase/ember-ui
Version:
Fleetbase UI provides all the interface components, helpers, services and utilities for building a Fleetbase extension into the Console.
239 lines (211 loc) • 6.37 kB
JavaScript
import Component from '@glimmer/component';
import { inject as service } from '@ember/service';
import { tracked } from '@glimmer/tracking';
import { action } from '@ember/object';
/**
* Component representing a content panel with toggle functionality.
*
* @class ContentPanelComponent
* @extends Component
*/
export default class ContentPanelComponent extends Component {
abilities;
/**
* Indicates whether the content panel is currently open.
*
* @property {boolean} isOpen - Whether the content panel is open or closed.
* @default false
* @public
*/
isOpen = false;
/**
* Determines whether the toggle action should be triggered only when clicking on the caret (icon-container).
*
* @property {boolean} toggleOnCaretOnly - Whether to toggle the content panel only when clicking on the caret.
* @default false
* @public
*/
toggleOnCaretOnly = false;
/**
* Determines if the dropdown button should render in place.
*
* @property {boolean} dropdownButtonRenderInPlace - Whether the dropdown button should render in place..
* @default false
* @public
*/
dropdownButtonRenderInPlace = false;
/**
* Array of icon containers used for checking if the user clicked on or within a caret.
*
* @property {HTMLElement[]} iconContainers - Array of icon containers.
* @default []
* @private
*/
iconContainers = [];
permissionRequired = null;
disabled = false;
doesntHavePermissions = false;
/**
* Initializes the content panel component.
*
* @constructor
* @public
*/
constructor(owner, { open = false, toggleOnCaretOnly = false, dropdownButtonRenderInPlace = true, disabled = false, permission = null, onInsert }) {
super(...arguments);
this.disabled = false;
this.permissionRequired = permission;
this.disabled = disabled;
if (!disabled) {
this.disabled = this.doesntHavePermissions = permission && this.abilities.cannot(permission);
}
this.isOpen = open === true;
this.toggleOnCaretOnly = toggleOnCaretOnly === true;
this.dropdownButtonRenderInPlace = dropdownButtonRenderInPlace === true;
if (typeof onInsert === 'function') {
onInsert(this.context);
}
}
/**
* API context for content panel component
*
* @memberof ContentPanelComponent
*/
context = {
toggle: this.toggleDropdown.bind(this),
open: this.open.bind(this),
close: this.close.bind(this),
};
/**
* Toggles the content panel's open/closed state based on click events.
*
* @method toggle
* @param {Event} event - The click event.
* @returns {void}
* @public
*/
toggle(event) {
// Fire onclick
this.fireOnClick();
// Check if the click target is within any of the icon containers
const clickedOnCaret = this.iconContainers.length > 0 && this.iconContainers.some((iconContainerNode) => iconContainerNode.contains(event.target));
// If we only want to toggle via the caret (icon-container)
if (clickedOnCaret) {
this.fireOnClickCaret();
if (this.toggleOnCaretOnly) {
// Run toggle
this.toggleDropdown();
return;
}
} else {
this.fireOnClickPanelTitle();
}
// Do not toggle
if (this.toggleOnCaretOnly) {
return;
}
// Toggle dropdown
this.toggleDropdown();
}
/**
* Opens the content panel.
*
* @method open
* @returns {void}
* @public
*/
open() {
this.isOpen = true;
}
/**
* Closes the content panel.
*
* @method close
* @returns {void}
* @public
*/
close() {
this.isOpen = false;
}
/**
* Tracks an icon container node to be used for checking if the user clicked on or within a caret.
*
* @method trackIconContainer
* @param {HTMLElement} node - The icon container node.
* @returns {void}
* @public
*/
trackIconContainer(node) {
this.iconContainers.pushObject(node);
}
/**
* Handles the click event on a dropdown item.
*
* @method onDropdownItemClick
* @param {Object} action - The action associated with the clicked dropdown item.
* @param {Object} dd - The dropdown object.
* @returns {void}
* @public
*/
onDropdownItemClick(action, dd) {
if (typeof dd.actions === 'object' && typeof dd.actions.close === 'function') {
dd.actions.close();
}
if (typeof action.fn === 'function') {
action.fn(action.context);
}
if (typeof action.onClick === 'function') {
action.onClick(action.context);
}
}
/**
* Toggles the content panel's open/closed state and fires a callback.
*
* @method toggleDropdown
* @returns {void}
* @private
*/
toggleDropdown() {
this.isOpen = !this.isOpen;
// Fire callback on toggle
if (typeof this.args.onToggle === 'function') {
this.args.onToggle(this.isOpen);
}
}
/**
* Fires the onClick callback if provided.
*
* @method fireOnClick
* @returns {void}
* @private
*/
fireOnClick() {
if (typeof this.args.onClick === 'function') {
this.args.onClick(this.context);
}
}
/**
* Fires the onClickCaret callback if provided.
*
* @method fireOnClickCaret
* @returns {void}
* @private
*/
fireOnClickCaret() {
if (typeof this.args.onClickCaret === 'function') {
this.args.onClickCaret(this.context);
}
}
/**
* Fires the onClickPanelTitle callback if provided.
*
* @method fireOnClickPanelTitle
* @returns {void}
* @private
*/
fireOnClickPanelTitle() {
if (typeof this.args.onClickPanelTitle === 'function') {
this.args.onClickPanelTitle(this.context);
}
}
}