import { html, PropertyValueMap, unsafeCSS } from "lit";
import { property, query } from "lit/decorators.js";
import eleStyle from "./f-accordion.scss?inline";
import globalStyle from "./f-accordion-global.scss?inline";
import { FRoot } from "../../mixins/components/f-root/f-root";
import { FDiv, FDivPaddingProp } from "../f-div/f-div";
import { flowElement } from "./../../utils";
import { injectCss } from "@cldcvr/flow-core-config";
injectCss("f-accordion", globalStyle);
export type FAccordionBodyHeightProp = `${number}px` | `${number}%` | `${number}vh`;
export type FAccordionCustomEvent = {
value: boolean;
};
export type FAccordionPadding = FDivPaddingProp;
@flowElement("f-accordion")
export class FAccordion extends FRoot {
/**
* css loaded from scss file
*/
static styles = [unsafeCSS(eleStyle), unsafeCSS(globalStyle), ...FDiv.styles];
/**
* @attribute toggle accordion
*/
@property({ reflect: true, type: Boolean })
open?: boolean = false;
/**
* @attribute
*/
@property({ reflect: true, type: String })
icon?: "chevron" | "caret" | "plus" | "none" = "chevron";
/**
* @attribute
*/
@property({ reflect: true, type: String, attribute: "icon-size" })
iconSize?: "x-small" | "small" | "medium" | "large" = "small";
/**
* @attribute placement of icon on left or right
*/
@property({ reflect: true, type: String, attribute: "icon-placement" })
iconPlacement?: "right" | "left" = "right";
/**
* @attribute placement of icon on left or right
*/
@property({ reflect: true, type: String, attribute: "max-height" })
maxHeight?: FAccordionBodyHeightProp;
/**
* @attribute padding applies on header slot container.
*/
@property({
type: String,
reflect: true,
attribute: "header-padding"
})
headerPadding?: FAccordionPadding = "medium";
/**
* @attribute padding applies on body slot container.
*/
@property({
type: String,
reflect: true,
attribute: "body-padding"
})
bodyPadding?: FAccordionPadding = "none medium";
@query(".f-accordion")
fAccordionBody?: FDiv;
@query(".f-accordion-header")
fAccordionHeader?: FDiv;
/**
* identify icon-name from string
*/
get iconName() {
return this.icon === "caret"
? "i-caret-down"
: this.icon === "chevron"
? "i-chevron-down"
: this.open
? "i-minus"
: "i-plus";
}
/**
* toggle accordion
*/
toggleAccordion() {
this.open = !this.open;
this.dispatchToggleEvent(this.open);
}
/**
* changeState
*/
stateChange(mouseState: "enter" | "leave") {
if (this.fAccordionHeader) {
if (mouseState === "enter") {
this.fAccordionHeader.style.background = "var(--color-surface-default-hover)";
} else {
this.fAccordionHeader.style.background = "transparent";
}
}
}
/**
* toggle event dispatch
* @param value boolean
*/
dispatchToggleEvent(value: boolean) {
const event = new CustomEvent("toggle", {
detail: {
value
},
bubbles: true,
composed: true
});
this.dispatchEvent(event);
}
/**
* handling max-height of body
*/
handleAccordionBody() {
if (this.fAccordionBody) {
if (this.maxHeight) {
if (this.open) {
this.fAccordionBody.style.setProperty("max-height", this.maxHeight, "important");
this.fAccordionBody.style.setProperty("overflow-y", "scroll", "important");
} else {
this.fAccordionBody.style.setProperty("max-height", "0px", "important");
}
}
}
}
render() {
// render accordion-icon
const accordionIcon = html`
`;
return html`
`;
}
protected updated(changedProperties: PropertyValueMap | Map) {
super.updated(changedProperties);
this.handleAccordionBody();
}
}
/**
* Required for typescript
*/
declare global {
interface HTMLElementTagNameMap {
"f-accordion": FAccordion;
}
}