@esri/calcite-components
Version:
Web Components for Esri's Calcite Design System.
297 lines (296 loc) • 9.09 kB
JavaScript
/*!
* All material copyright ESRI, All Rights Reserved, unless otherwise specified.
* See https://github.com/Esri/calcite-components/blob/master/LICENSE.md for details.
*/
import { Component, Element, Event, h, Listen, Prop } from "@stencil/core";
/**
* @slot - A slot for adding `calcite-accordion-item`s. `calcite-accordion` cannot be nested, however calcite-accordion-item`s can.
*/
export class Accordion {
constructor() {
//--------------------------------------------------------------------------
//
// Public Properties
//
//--------------------------------------------------------------------------
/** specify the appearance - default (containing border), or minimal (no containing border), defaults to default */
this.appearance = "default";
/** specify the placement of the icon in the header, defaults to end */
this.iconPosition = "end";
/** specify the type of the icon in the header, defaults to chevron */
this.iconType = "chevron";
/** specify the scale of accordion, defaults to m */
this.scale = "m";
/** specify the selection mode - multi (allow any number of open items), single (allow one open item),
* or single-persist (allow and require one open item), defaults to multi */
this.selectionMode = "multi";
//--------------------------------------------------------------------------
//
// Private State/Props
//
//--------------------------------------------------------------------------
/** created list of Accordion items */
this.items = [];
/** keep track of whether the items have been sorted so we don't re-sort */
this.sorted = false;
this.sortItems = (items) => items.sort((a, b) => a.position - b.position).map((a) => a.item);
}
//--------------------------------------------------------------------------
//
// Lifecycle
//
//--------------------------------------------------------------------------
componentDidLoad() {
if (!this.sorted) {
this.items = this.sortItems(this.items);
this.sorted = true;
}
}
render() {
return (h("div", { class: {
"accordion--transparent": this.appearance === "transparent",
"accordion--minimal": this.appearance === "minimal",
accordion: this.appearance === "default"
} },
h("slot", null)));
}
//--------------------------------------------------------------------------
//
// Event Listeners
//
//--------------------------------------------------------------------------
calciteAccordionItemKeyEvent(e) {
const item = e.detail.item;
const parent = e.detail.parent;
if (this.el === parent) {
const key = item.key;
const itemToFocus = e.target;
const isFirstItem = this.itemIndex(itemToFocus) === 0;
const isLastItem = this.itemIndex(itemToFocus) === this.items.length - 1;
switch (key) {
case "ArrowDown":
if (isLastItem) {
this.focusFirstItem();
}
else {
this.focusNextItem(itemToFocus);
}
break;
case "ArrowUp":
if (isFirstItem) {
this.focusLastItem();
}
else {
this.focusPrevItem(itemToFocus);
}
break;
case "Home":
this.focusFirstItem();
break;
case "End":
this.focusLastItem();
break;
}
}
}
registerCalciteAccordionItem(e) {
const item = {
item: e.target,
parent: e.detail.parent,
position: e.detail.position
};
if (this.el === item.parent) {
this.items.push(item);
}
}
updateActiveItemOnChange(event) {
this.requestedAccordionItem = event.detail.requestedAccordionItem;
this.calciteAccordionChange.emit({
requestedAccordionItem: this.requestedAccordionItem
});
}
//--------------------------------------------------------------------------
//
// Private Methods
//
//--------------------------------------------------------------------------
focusFirstItem() {
const firstItem = this.items[0];
this.focusElement(firstItem);
}
focusLastItem() {
const lastItem = this.items[this.items.length - 1];
this.focusElement(lastItem);
}
focusNextItem(e) {
const index = this.itemIndex(e);
const nextItem = this.items[index + 1] || this.items[0];
this.focusElement(nextItem);
}
focusPrevItem(e) {
const index = this.itemIndex(e);
const prevItem = this.items[index - 1] || this.items[this.items.length - 1];
this.focusElement(prevItem);
}
itemIndex(e) {
return this.items.indexOf(e);
}
focusElement(item) {
const target = item;
target.focus();
}
static get is() { return "calcite-accordion"; }
static get encapsulation() { return "shadow"; }
static get originalStyleUrls() { return {
"$": ["accordion.scss"]
}; }
static get styleUrls() { return {
"$": ["accordion.css"]
}; }
static get properties() { return {
"appearance": {
"type": "string",
"mutable": false,
"complexType": {
"original": "AccordionAppearance",
"resolved": "\"default\" | \"minimal\" | \"transparent\"",
"references": {
"AccordionAppearance": {
"location": "import",
"path": "./interfaces"
}
}
},
"required": false,
"optional": false,
"docs": {
"tags": [],
"text": "specify the appearance - default (containing border), or minimal (no containing border), defaults to default"
},
"attribute": "appearance",
"reflect": true,
"defaultValue": "\"default\""
},
"iconPosition": {
"type": "string",
"mutable": false,
"complexType": {
"original": "Position",
"resolved": "\"end\" | \"start\"",
"references": {
"Position": {
"location": "import",
"path": "../interfaces"
}
}
},
"required": false,
"optional": false,
"docs": {
"tags": [],
"text": "specify the placement of the icon in the header, defaults to end"
},
"attribute": "icon-position",
"reflect": true,
"defaultValue": "\"end\""
},
"iconType": {
"type": "string",
"mutable": false,
"complexType": {
"original": "\"chevron\" | \"caret\" | \"plus-minus\"",
"resolved": "\"caret\" | \"chevron\" | \"plus-minus\"",
"references": {}
},
"required": false,
"optional": false,
"docs": {
"tags": [],
"text": "specify the type of the icon in the header, defaults to chevron"
},
"attribute": "icon-type",
"reflect": true,
"defaultValue": "\"chevron\""
},
"scale": {
"type": "string",
"mutable": false,
"complexType": {
"original": "Scale",
"resolved": "\"l\" | \"m\" | \"s\"",
"references": {
"Scale": {
"location": "import",
"path": "../interfaces"
}
}
},
"required": false,
"optional": false,
"docs": {
"tags": [],
"text": "specify the scale of accordion, defaults to m"
},
"attribute": "scale",
"reflect": true,
"defaultValue": "\"m\""
},
"selectionMode": {
"type": "string",
"mutable": false,
"complexType": {
"original": "\"multi\" | \"single\" | \"single-persist\"",
"resolved": "\"multi\" | \"single\" | \"single-persist\"",
"references": {}
},
"required": false,
"optional": false,
"docs": {
"tags": [],
"text": "specify the selection mode - multi (allow any number of open items), single (allow one open item),\nor single-persist (allow and require one open item), defaults to multi"
},
"attribute": "selection-mode",
"reflect": true,
"defaultValue": "\"multi\""
}
}; }
static get events() { return [{
"method": "calciteAccordionChange",
"name": "calciteAccordionChange",
"bubbles": true,
"cancelable": true,
"composed": true,
"docs": {
"tags": [{
"name": "internal",
"text": undefined
}],
"text": ""
},
"complexType": {
"original": "any",
"resolved": "any",
"references": {}
}
}]; }
static get elementRef() { return "el"; }
static get listeners() { return [{
"name": "calciteAccordionItemKeyEvent",
"method": "calciteAccordionItemKeyEvent",
"target": undefined,
"capture": false,
"passive": false
}, {
"name": "calciteAccordionItemRegister",
"method": "registerCalciteAccordionItem",
"target": undefined,
"capture": false,
"passive": false
}, {
"name": "calciteAccordionItemSelect",
"method": "updateActiveItemOnChange",
"target": undefined,
"capture": false,
"passive": false
}]; }
}