import { html, PropertyValueMap, unsafeCSS } from "lit"; import { property, query } from "lit/decorators.js"; import eleStyle from "./f-progress-bar.scss?inline"; import globalStyle from "./f-progress-bar-global.scss?inline"; import { FRoot } from "../../mixins/components/f-root/f-root"; import { FDiv } from "../f-div/f-div"; import getCustomFillColor from "../../utils/get-custom-fill-color"; import { validateHTMLColor } from "validate-color"; import { validateHTMLColorName } from "validate-color"; import { flowElement } from "../../utils"; import { injectCss } from "@cldcvr/flow-core-config"; injectCss("f-progress-bar", globalStyle); export type FProgressBarState = | "primary" | "default" | "success" | "warning" | "danger" | `custom, ${string}`; export type FProgressBarWidthProp = "fill-container" | `${number}px`; export type FProgressBarValueProp = `${number}%`; @flowElement("f-progress-bar") export class FProgressBar extends FRoot { /** * css loaded from scss file */ static styles = [unsafeCSS(eleStyle), unsafeCSS(globalStyle), ...FDiv.styles]; /** * @attribute value of the fill section in progress-bar */ @property({ type: String, reflect: true }) value?: FProgressBarValueProp; /** * @attribute Variants are visual representations of progress bar. A progress bar can be round or block. */ @property({ type: String, reflect: true }) variant?: "block" | "curved" = "block"; /** * @attribute The medium size is the default and recommended option. */ @property({ type: String, reflect: true }) size?: "large" | "medium" | "small" | "x-small" = "medium"; /** * @attribute States are used to communicate purpose and it’s connotation. For example, a red color connotes danger, whereas a green color connotes success and so on. */ @property({ reflect: true, type: String }) state?: FProgressBarState = "default"; /** * @attribute By default progress bar takes full width of the parent container. User can change it using width property. */ @property({ reflect: true, type: String }) width?: FProgressBarWidthProp = "fill-container"; /** * progress-bar fill query selector */ @query(".f-progress-bar-fill") fProgressBarFill?: FDiv; /** * compyr height of the progress-bar */ get computedHeight() { if (this.size === "large") { return "16px"; } else if (this.size === "medium") { return "12px"; } else if (this.size === "small") { return "8px"; } else { return "4px"; } } /** * compute width of fill in the track */ get computedWidth() { if (this.width === "fill-container") { return "100%"; } else { return this.width; } } /** * validation for all atrributes */ validateProperties() { if ( this.state?.includes("custom") && this.fill && !validateHTMLColor(this.fill) && !validateHTMLColorName(this.fill) ) { throw new Error("f-progress-bar : enter correct color-name or color-code"); } } fill = ""; render() { /** * creating local fill variable out of state prop. */ this.fill = getCustomFillColor(this.state ?? ""); /** * validate */ this.validateProperties(); return html` `; } protected updated(changedProperties: PropertyValueMap | Map) { super.updated(changedProperties); if (this.fill && this.state?.includes("custom") && this.fProgressBarFill) { this.fProgressBarFill.style.background = this.fill; } } } /** * Required for typescript */ declare global { interface HTMLElementTagNameMap { "f-progress-bar": FProgressBar; } }