@rhds/elements
Version:
Red Hat Design System Elements
352 lines • 16.5 kB
JavaScript
var _RhAccordion_instances, _a, _RhAccordion_ctx_get, _RhAccordion_expandedIndex, _RhAccordion_headerIndex, _RhAccordion_initialized, _RhAccordion_logger, _RhAccordion_mo, _RhAccordion_init, _RhAccordion_activeHeader_get, _RhAccordion_updateActiveHeader, _RhAccordion_panelForHeader, _RhAccordion_expandHeader, _RhAccordion_expandPanel, _RhAccordion_collapseHeader, _RhAccordion_collapsePanel, _RhAccordion_onChange, _RhAccordion_allHeaders, _RhAccordion_allPanels, _RhAccordion_getIndex;
var RhAccordion_1;
import { __classPrivateFieldGet, __classPrivateFieldSet, __decorate } from "tslib";
import { LitElement, html } from 'lit';
import { classMap } from 'lit/directives/class-map.js';
import { customElement } from 'lit/decorators/custom-element.js';
import { property } from 'lit/decorators/property.js';
import { observed } from '@patternfly/pfe-core/decorators/observed.js';
import { provide } from '@lit/context';
import { RovingTabindexController } from '@patternfly/pfe-core/controllers/roving-tabindex-controller.js';
import { colorContextConsumer } from '../../lib/context/color/consumer.js';
import { colorContextProvider } from '../../lib/context/color/provider.js';
import { NumberListConverter, ComposedEvent } from '@patternfly/pfe-core';
import { Logger } from '@patternfly/pfe-core/controllers/logger.js';
import { RhAccordionHeader, AccordionHeaderChangeEvent } from './rh-accordion-header.js';
import { RhAccordionPanel } from './rh-accordion-panel.js';
import { context } from './context.js';
import { css } from "lit";
const styles = css `:host{--_border-color:var(--rh-color-border-subtle-on-light, #c7c7c7);color:var(--rh-color-text-primary-on-light,#151515);background-color:var(--rh-color-surface-lightest,#fff)}.dark{--_border-color:var(--rh-color-border-subtle-on-dark, #707070)}#container{display:contents}::slotted(rh-accordion-header:first-child){display:block;border-block:1px solid var(--_border-color)}::slotted(rh-accordion-header:not(:first-child)){display:block;border-block-end:1px solid var(--_border-color)}::slotted(rh-accordion-header:is([expanded])){display:block;border-block-end:0;box-shadow:var(--rh-box-shadow-sm,0 2px 4px 0 rgba(21,21,21,.2))}::slotted(rh-accordion-panel:is([expanded])){display:block;border-block-end:1px solid var(--_border-color);box-shadow:var(--rh-box-shadow-sm,0 2px 4px 0 rgba(21,21,21,.2))}`;
export class AccordionExpandEvent extends ComposedEvent {
constructor(toggle, panel) {
super('expand');
this.toggle = toggle;
this.panel = panel;
}
}
export class AccordionCollapseEvent extends ComposedEvent {
constructor(toggle, panel) {
super('collapse');
this.toggle = toggle;
this.panel = panel;
}
}
/**
* An accordion is a stacked list of panels which allows users to expand or collapse information when selected. They feature panels that consist of a section text label and a caret icon that collapses or expands to reveal more information.
*
* @summary Expands or collapses a stacked list of panels
*
* @fires {AccordionExpandEvent} expand - when a panel expands
* @fires {AccordionCollapseEvent} collapse - when a panel collapses
*
*
* @slot
* Place the `rh-accordion-header` and `rh-accordion-panel` elements here.
*
* @attr accents
* Position accents in the header either inline or bottom
* {@default inline}
*
*/
let RhAccordion = RhAccordion_1 = _a = class RhAccordion extends LitElement {
constructor() {
super(...arguments);
_RhAccordion_instances.add(this);
this.large = false;
this.bordered = true;
this.expandedSets = new Set();
_RhAccordion_expandedIndex.set(this, []);
_RhAccordion_headerIndex.set(this, new RovingTabindexController(this));
// actually is read in #init, by the `||=` operator
// eslint-disable-next-line no-unused-private-class-members
_RhAccordion_initialized.set(this, false);
_RhAccordion_logger.set(this, new Logger(this));
_RhAccordion_mo.set(this, new MutationObserver(() => __classPrivateFieldGet(this, _RhAccordion_instances, "m", _RhAccordion_init).call(this)));
this.ctx = __classPrivateFieldGet(this, _RhAccordion_instances, "a", _RhAccordion_ctx_get);
}
static isAccordion(target) {
return target instanceof RhAccordion_1;
}
static isHeader(target) {
return target instanceof RhAccordionHeader;
}
static isPanel(target) {
return target instanceof RhAccordionPanel;
}
static isAccordionChangeEvent(event) {
return event instanceof AccordionHeaderChangeEvent;
}
/**
* Sets and reflects the currently expanded accordion 0-based indexes.
* Use commas to separate multiple indexes.
* ```html
* <pf-accordion expanded-index="1,2">
* ...
* </pf-accordion>
* ```
*/
get expandedIndex() {
return __classPrivateFieldGet(this, _RhAccordion_expandedIndex, "f");
}
set expandedIndex(value) {
const old = __classPrivateFieldGet(this, _RhAccordion_expandedIndex, "f");
__classPrivateFieldSet(this, _RhAccordion_expandedIndex, value, "f");
if (JSON.stringify(old) !== JSON.stringify(value)) {
this.requestUpdate('expandedIndex', old);
this.collapseAll().then(async () => {
for (const i of this.expandedIndex) {
await this.expand(i, this);
}
});
}
}
connectedCallback() {
super.connectedCallback();
this.addEventListener('change', __classPrivateFieldGet(this, _RhAccordion_instances, "m", _RhAccordion_onChange));
__classPrivateFieldGet(this, _RhAccordion_mo, "f").observe(this, { childList: true });
__classPrivateFieldGet(this, _RhAccordion_instances, "m", _RhAccordion_init).call(this);
}
render() {
const { on = '' } = this;
return html `
<div id="container" class="${classMap({ [on]: !!on })}"><slot></slot></div>
`;
}
async firstUpdated() {
const { headers } = this;
headers.forEach((header, index) => {
if (header.expanded) {
__classPrivateFieldGet(this, _RhAccordion_instances, "m", _RhAccordion_expandHeader).call(this, header, index);
const panel = __classPrivateFieldGet(this, _RhAccordion_instances, "m", _RhAccordion_panelForHeader).call(this, header);
if (panel) {
__classPrivateFieldGet(this, _RhAccordion_instances, "m", _RhAccordion_expandPanel).call(this, panel);
}
}
});
this.ctx = __classPrivateFieldGet(this, _RhAccordion_instances, "a", _RhAccordion_ctx_get);
}
async getUpdateComplete() {
const c = await super.getUpdateComplete();
const results = await Promise.all([
...__classPrivateFieldGet(this, _RhAccordion_instances, "m", _RhAccordion_allHeaders).call(this).map(x => x.updateComplete),
...__classPrivateFieldGet(this, _RhAccordion_instances, "m", _RhAccordion_allPanels).call(this).map(x => x.updateComplete),
]);
return c && results.every(Boolean);
}
get headers() {
return __classPrivateFieldGet(this, _RhAccordion_instances, "m", _RhAccordion_allHeaders).call(this);
}
get panels() {
return __classPrivateFieldGet(this, _RhAccordion_instances, "m", _RhAccordion_allPanels).call(this);
}
updateAccessibility() {
const { headers } = this;
// For each header in the accordion, attach the aria connections
headers.forEach(header => {
const panel = __classPrivateFieldGet(this, _RhAccordion_instances, "m", _RhAccordion_panelForHeader).call(this, header);
if (panel) {
header.setAttribute('aria-controls', panel.id);
panel.setAttribute('aria-labelledby', header.id);
panel.hidden = !panel.expanded;
}
});
}
/**
* Accepts a 0-based index value (integer) for the set of accordion items to expand or collapse.
*/
async toggle(index) {
const { headers } = this;
const header = headers[index];
if (!header.expanded) {
await this.expand(index);
}
else {
await this.collapse(index);
}
}
/**
* Accepts a 0-based index value (integer) for the set of accordion items to expand.
* Accepts an optional parent accordion to search for headers and panels.
*/
async expand(index, parentAccordion) {
const allHeaders = __classPrivateFieldGet(this, _RhAccordion_instances, "m", _RhAccordion_allHeaders).call(this, parentAccordion);
const header = allHeaders[index];
if (!header) {
return;
}
const panel = __classPrivateFieldGet(this, _RhAccordion_instances, "m", _RhAccordion_panelForHeader).call(this, header);
if (!panel) {
return;
}
// If the header and panel exist, open both
__classPrivateFieldGet(this, _RhAccordion_instances, "m", _RhAccordion_expandHeader).call(this, header, index),
__classPrivateFieldGet(this, _RhAccordion_instances, "m", _RhAccordion_expandPanel).call(this, panel),
header.focus();
this.dispatchEvent(new AccordionExpandEvent(header, panel));
await this.updateComplete;
}
/**
* Expands all accordion items.
*/
async expandAll() {
this.headers.forEach(header => __classPrivateFieldGet(this, _RhAccordion_instances, "m", _RhAccordion_expandHeader).call(this, header));
this.panels.forEach(panel => __classPrivateFieldGet(this, _RhAccordion_instances, "m", _RhAccordion_expandPanel).call(this, panel));
await this.updateComplete;
}
/**
* Accepts a 0-based index value (integer) for the set of accordion items to collapse.
*/
async collapse(index) {
const header = this.headers.at(index);
const panel = this.panels.at(index);
if (!header || !panel) {
return;
}
__classPrivateFieldGet(this, _RhAccordion_instances, "m", _RhAccordion_collapseHeader).call(this, header);
__classPrivateFieldGet(this, _RhAccordion_instances, "m", _RhAccordion_collapsePanel).call(this, panel);
this.dispatchEvent(new AccordionCollapseEvent(header, panel));
await this.updateComplete;
}
/**
* Collapses all accordion items.
*/
async collapseAll() {
this.headers.forEach(header => __classPrivateFieldGet(this, _RhAccordion_instances, "m", _RhAccordion_collapseHeader).call(this, header));
this.panels.forEach(panel => __classPrivateFieldGet(this, _RhAccordion_instances, "m", _RhAccordion_collapsePanel).call(this, panel));
await this.updateComplete;
}
};
_RhAccordion_expandedIndex = new WeakMap();
_RhAccordion_headerIndex = new WeakMap();
_RhAccordion_initialized = new WeakMap();
_RhAccordion_logger = new WeakMap();
_RhAccordion_mo = new WeakMap();
_RhAccordion_instances = new WeakSet();
_RhAccordion_ctx_get = function _RhAccordion_ctx_get() {
const accents = this.accents ? this.accents : 'inline';
return { accents };
};
_RhAccordion_init =
/**
* Initialize the accordion by connecting headers and panels
* with aria controls and labels; set up the default disclosure
* state if not set by the author; and check the URL for default
* open
*/
async function _RhAccordion_init() {
__classPrivateFieldSet(this, _RhAccordion_initialized, __classPrivateFieldGet(this, _RhAccordion_initialized, "f") || !!await this.updateComplete, "f");
__classPrivateFieldGet(this, _RhAccordion_headerIndex, "f").initItems(this.headers);
// Event listener to the accordion header after the accordion has been initialized to add the roving tabindex
this.addEventListener('focusin', __classPrivateFieldGet(this, _RhAccordion_instances, "m", _RhAccordion_updateActiveHeader));
this.updateAccessibility();
};
_RhAccordion_activeHeader_get = function _RhAccordion_activeHeader_get() {
const { headers } = this;
const index = headers.findIndex(header => header.matches(':focus,:focus-within'));
return index > -1 ? headers.at(index) : undefined;
};
_RhAccordion_updateActiveHeader = function _RhAccordion_updateActiveHeader() {
if (__classPrivateFieldGet(this, _RhAccordion_instances, "a", _RhAccordion_activeHeader_get)) {
__classPrivateFieldGet(this, _RhAccordion_headerIndex, "f").setActiveItem(__classPrivateFieldGet(this, _RhAccordion_instances, "a", _RhAccordion_activeHeader_get));
}
};
_RhAccordion_panelForHeader = function _RhAccordion_panelForHeader(header) {
const next = header.nextElementSibling;
if (!RhAccordion_1.isPanel(next)) {
return void __classPrivateFieldGet(this, _RhAccordion_logger, "f").error('Sibling element to a header needs to be a panel');
}
else {
return next;
}
};
_RhAccordion_expandHeader = function _RhAccordion_expandHeader(header, index = __classPrivateFieldGet(this, _RhAccordion_instances, "m", _RhAccordion_getIndex).call(this, header)) {
// If this index is not already listed in the expandedSets array, add it
this.expandedSets.add(index);
__classPrivateFieldSet(this, _RhAccordion_expandedIndex, [...this.expandedSets], "f");
header.expanded = true;
};
_RhAccordion_expandPanel = function _RhAccordion_expandPanel(panel) {
panel.expanded = true;
panel.hidden = false;
};
_RhAccordion_collapseHeader = async function _RhAccordion_collapseHeader(header, index = __classPrivateFieldGet(this, _RhAccordion_instances, "m", _RhAccordion_getIndex).call(this, header)) {
if (!this.expandedSets) {
await this.updateComplete;
}
this.expandedSets.delete(index);
header.expanded = false;
await header.updateComplete;
};
_RhAccordion_collapsePanel = async function _RhAccordion_collapsePanel(panel) {
await panel.updateComplete;
if (!panel.expanded) {
return;
}
panel.expanded = false;
panel.hidden = true;
};
_RhAccordion_onChange = function _RhAccordion_onChange(event) {
if (RhAccordion_1.isAccordionChangeEvent(event)) {
const index = __classPrivateFieldGet(this, _RhAccordion_instances, "m", _RhAccordion_getIndex).call(this, event.target);
if (event.expanded) {
this.expand(index, event.accordion);
}
else {
this.collapse(index);
}
}
};
_RhAccordion_allHeaders = function _RhAccordion_allHeaders(accordion = this) {
return Array.from(accordion.children).filter((x) => x instanceof RhAccordionHeader);
};
_RhAccordion_allPanels = function _RhAccordion_allPanels(accordion = this) {
return Array.from(accordion.children).filter((x => RhAccordion_1.isPanel(x)));
};
_RhAccordion_getIndex = function _RhAccordion_getIndex(el) {
if (RhAccordion_1.isHeader(el)) {
return this.headers.findIndex(header => header.id === el.id);
}
if (RhAccordion_1.isPanel(el)) {
return this.panels.findIndex(panel => panel.id === el.id);
}
__classPrivateFieldGet(this, _RhAccordion_logger, "f").warn('The #getIndex method expects to receive a header or panel element.');
return -1;
};
RhAccordion.version = '{{version}}';
RhAccordion.styles = [styles];
__decorate([
property({
attribute: true,
reflect: true,
})
], RhAccordion.prototype, "accents", void 0);
__decorate([
property({
attribute: 'expanded-index',
converter: NumberListConverter,
})
], RhAccordion.prototype, "expandedIndex", null);
__decorate([
observed(function largeChanged() {
[...this.headers, ...this.panels].forEach(el => el.toggleAttribute('large', this.large));
}),
property({ reflect: true, type: Boolean })
], RhAccordion.prototype, "large", void 0);
__decorate([
property({ reflect: true, type: Boolean })
], RhAccordion.prototype, "bordered", void 0);
__decorate([
colorContextProvider(),
property({ reflect: true, attribute: 'color-palette' })
], RhAccordion.prototype, "colorPalette", void 0);
__decorate([
colorContextConsumer()
], RhAccordion.prototype, "on", void 0);
__decorate([
provide({ context })
], RhAccordion.prototype, "ctx", void 0);
RhAccordion = RhAccordion_1 = __decorate([
customElement('rh-accordion')
], RhAccordion);
export { RhAccordion };
//# sourceMappingURL=rh-accordion.js.map