@trimble-oss/moduswebcomponents
Version:
Modus Web Components is a modern, accessible UI library built with Stencil JS that provides reusable web components following Trimble's Modus design system. This updated version focuses on improved flexibility, enhanced theming options, comprehensive cust
272 lines (271 loc) • 11.9 kB
JavaScript
import { h, Host, } from "@stencil/core";
import { handleShadowDOMStyles } from "../base-component";
import { convertPropsToClasses, convertPropsToDescriptionDivClasses, convertPropsToTitleChildDivClasses, convertPropsToTitleDivClasses, } from "./modus-wc-collapse.tailwind";
import { generateRandomId, inheritAriaAttributes } from "../utils";
/**
* A customizable collapse component used for showing and hiding content.
*
* The component supports a 'header' and 'content' `<slot>` for injecting custom HTML.
*/
export class ModusWcCollapse {
constructor() {
this.inheritedAttributes = {};
/** When true, renders a border-bottom on the collapse component. */
this.bordered = false;
/** Controls chevron placement. */
this.chevronPosition = 'right';
/** Custom CSS class to apply to the outer div. */
this.customClass = '';
/** Controls whether the collapse is expanded or not. */
this.expanded = false;
this.handleToggle = (event) => {
const detailsElement = event.currentTarget;
const isOpen = detailsElement.open;
if (this.expanded !== isOpen) {
this.expanded = isOpen;
this.expandedChange.emit({ expanded: isOpen });
}
};
}
expandedChanged(newValue) {
if (this.detailsRef && this.detailsRef.open !== newValue) {
this.detailsRef.open = newValue;
}
}
componentWillLoad() {
// Auto-inject CSS if component is used inside user's shadow DOM
handleShadowDOMStyles(this.el);
if (!this.collapseId) {
this.collapseId = generateRandomId();
}
this.inheritedAttributes = inheritAriaAttributes(this.el);
}
getOuterDivClasses() {
var _a, _b;
const classList = ['modus-wc-collapse modus-wc-collapse-arrow'];
const propClasses = convertPropsToClasses({
bordered: this.bordered,
expanded: this.expanded,
});
// The order CSS classes are added matters to CSS specificity
if (propClasses)
classList.push(propClasses);
classList.push(`modus-wc-chevron-${this.chevronPosition}`);
if (!((_a = this.options) === null || _a === void 0 ? void 0 : _a.startIcon) && this.chevronPosition !== 'left') {
classList.push('no-leading-icons');
}
if (((_b = this.options) === null || _b === void 0 ? void 0 : _b.startIcon) && this.chevronPosition === 'left') {
classList.push('has-start-icon');
}
if (this.customClass)
classList.push(this.customClass);
return classList.join(' ');
}
// istanbul ignore next
getTitleClasses() {
var _a;
const classList = [
'modus-wc-collapse-title modus-wc-inline-flex modus-wc-items-center modus-wc-justify-between modus-wc-min-h-4',
];
const paddingClass = convertPropsToTitleDivClasses({
size: (_a = this.options) === null || _a === void 0 ? void 0 : _a.size,
});
if (paddingClass)
classList.push(paddingClass);
return classList.join(' ');
}
// istanbul ignore next
getTitleChildDivClasses() {
var _a;
const classList = [
'modus-wc-title-main-row modus-wc-inline-flex modus-wc-items-center',
];
const titleFontSize = convertPropsToTitleChildDivClasses({
size: (_a = this.options) === null || _a === void 0 ? void 0 : _a.size,
});
if (titleFontSize)
classList.push(titleFontSize);
return classList.join(' ');
}
// istanbul ignore next
getDescriptionDivClasses() {
var _a;
const classList = ['description modus-wc-font-light'];
const descriptionFontSize = convertPropsToDescriptionDivClasses({
size: (_a = this.options) === null || _a === void 0 ? void 0 : _a.size,
});
if (descriptionFontSize)
classList.push(descriptionFontSize);
return classList.join(' ');
}
render() {
var _a;
const baseId = this.collapseId;
const titleId = `${baseId}-title`;
const contentId = `${baseId}-content`;
return (h(Host, { key: '066210e7a999faf40422efe7bc50281975585fad' }, h("details", Object.assign({ key: '6ea85a85f00b3328dc744a2ba4b58abfd64ce534', class: this.getOuterDivClasses(), open: this.expanded, onToggle: this.handleToggle, ref: (el) => (this.detailsRef = el) }, this.inheritedAttributes), h("summary", { key: 'e5f2f7edbbbbc4e2b520ade5cd5eddc9e9fcb5bd', class: this.getTitleClasses(), id: titleId }, this.options ? (h("div", { class: "modus-wc-summary-main-content" }, this.options.startIcon && (h("modus-wc-icon", { "aria-label": this.options.startIconAriaLabel, class: "title-start-icon", decorative: !this.options.startIconAriaLabel, name: this.options.startIcon, size: this.options.size })), h("div", { class: "modus-wc-title-main-content" }, h("div", { class: this.getTitleChildDivClasses() }, this.options.icon && (h("modus-wc-icon", { "aria-label": this.options.iconAriaLabel, decorative: !this.options.iconAriaLabel, name: this.options.icon, size: this.options.size })), this.options.title)), this.options.endIcon && (h("div", { class: "modus-wc-title-end-content" }, h("modus-wc-icon", { "aria-label": this.options.endIconAriaLabel, class: "title-end-icon", decorative: !this.options.endIconAriaLabel, name: this.options.endIcon, size: this.options.size }))))) : (h("slot", { name: "header" }))), this.expanded && ((_a = this.options) === null || _a === void 0 ? void 0 : _a.description) && (h("div", { key: 'b13862fde0e208df6598d1bfd54977e8d3fd6b6d', class: `modus-wc-collapse-description ${this.getDescriptionDivClasses()}` }, this.options.description)), h("div", { key: '40538c27af9f30b527e52ae40d4ac6c5a65b366a', "aria-labelledby": titleId, class: "modus-wc-collapse-content modus-wc-cursor-default", id: contentId }, h("slot", { key: 'c0563a96763e89fe916748a9155590d6074cadbc', name: "content" })))));
}
static get is() { return "modus-wc-collapse"; }
static get originalStyleUrls() {
return {
"$": ["modus-wc-collapse.scss"]
};
}
static get styleUrls() {
return {
"$": ["modus-wc-collapse.css"]
};
}
static get properties() {
return {
"bordered": {
"type": "boolean",
"attribute": "bordered",
"mutable": false,
"complexType": {
"original": "boolean",
"resolved": "boolean | undefined",
"references": {}
},
"required": false,
"optional": true,
"docs": {
"tags": [],
"text": "When true, renders a border-bottom on the collapse component."
},
"getter": false,
"setter": false,
"reflect": false,
"defaultValue": "false"
},
"chevronPosition": {
"type": "string",
"attribute": "chevron-position",
"mutable": false,
"complexType": {
"original": "'left' | 'right'",
"resolved": "\"left\" | \"right\" | undefined",
"references": {}
},
"required": false,
"optional": true,
"docs": {
"tags": [],
"text": "Controls chevron placement."
},
"getter": false,
"setter": false,
"reflect": false,
"defaultValue": "'right'"
},
"customClass": {
"type": "string",
"attribute": "custom-class",
"mutable": false,
"complexType": {
"original": "string",
"resolved": "string | undefined",
"references": {}
},
"required": false,
"optional": true,
"docs": {
"tags": [],
"text": "Custom CSS class to apply to the outer div."
},
"getter": false,
"setter": false,
"reflect": false,
"defaultValue": "''"
},
"expanded": {
"type": "boolean",
"attribute": "expanded",
"mutable": true,
"complexType": {
"original": "boolean",
"resolved": "boolean | undefined",
"references": {}
},
"required": false,
"optional": true,
"docs": {
"tags": [],
"text": "Controls whether the collapse is expanded or not."
},
"getter": false,
"setter": false,
"reflect": false,
"defaultValue": "false"
},
"collapseId": {
"type": "string",
"attribute": "collapse-id",
"mutable": true,
"complexType": {
"original": "string",
"resolved": "string | undefined",
"references": {}
},
"required": false,
"optional": true,
"docs": {
"tags": [],
"text": "A unique identifier used to set the id attributes of various elements."
},
"getter": false,
"setter": false,
"reflect": false
},
"options": {
"type": "unknown",
"attribute": "options",
"mutable": false,
"complexType": {
"original": "ICollapseOptions",
"resolved": "ICollapseOptions | undefined",
"references": {
"ICollapseOptions": {
"location": "local",
"path": "/home/runner/work/modus-wc-2.0/modus-wc-2.0/src/components/modus-wc-collapse/modus-wc-collapse.tsx",
"id": "src/components/modus-wc-collapse/modus-wc-collapse.tsx::ICollapseOptions"
}
}
},
"required": false,
"optional": true,
"docs": {
"tags": [],
"text": "Configuration options for rendering the pre-laid out collapse component.\nDo not set this prop if you intend to use the 'header' slot."
},
"getter": false,
"setter": false
}
};
}
static get events() {
return [{
"method": "expandedChange",
"name": "expandedChange",
"bubbles": true,
"cancelable": true,
"composed": true,
"docs": {
"tags": [],
"text": "Event emitted when the expanded prop is internally changed."
},
"complexType": {
"original": "{ expanded: boolean }",
"resolved": "{ expanded: boolean; }",
"references": {}
}
}];
}
static get elementRef() { return "el"; }
static get watchers() {
return [{
"propName": "expanded",
"methodName": "expandedChanged"
}];
}
}