// @ts-check import { encodeHTML } from "./html.js"; import { flexLayout } from "./render.js"; class Card { /** * Creates a new card instance. * * @param {object} args Card arguments. * @param {number=} args.width Card width. * @param {number=} args.height Card height. * @param {number=} args.border_radius Card border radius. * @param {string=} args.customTitle Card custom title. * @param {string=} args.defaultTitle Card default title. * @param {string=} args.titlePrefixIcon Card title prefix icon. * @param {object} [args.colors={}] Card colors arguments. * @param {string=} args.colors.titleColor Card title color. * @param {string=} args.colors.textColor Card text color. * @param {string=} args.colors.iconColor Card icon color. * @param {string|string[]=} args.colors.bgColor Card background color. * @param {string=} args.colors.borderColor Card border color. */ constructor({ width = 100, height = 100, border_radius = 4.5, colors = {}, customTitle, defaultTitle = "", titlePrefixIcon, }) { this.width = width; this.height = height; this.hideBorder = false; this.hideTitle = false; this.border_radius = border_radius; // returns theme based colors with proper overrides and defaults this.colors = colors; this.title = customTitle === undefined ? encodeHTML(defaultTitle) : encodeHTML(customTitle); this.css = ""; this.paddingX = 25; this.paddingY = 35; this.titlePrefixIcon = titlePrefixIcon; this.animations = true; this.a11yTitle = ""; this.a11yDesc = ""; } /** * @returns {void} */ disableAnimations() { this.animations = false; } /** * @param {Object} props The props object. * @param {string} props.title Accessibility title. * @param {string} props.desc Accessibility description. * @returns {void} */ setAccessibilityLabel({ title, desc }) { this.a11yTitle = title; this.a11yDesc = desc; } /** * @param {string} value The CSS to add to the card. * @returns {void} */ setCSS(value) { this.css = value; } /** * @param {boolean} value Whether to hide the border or not. * @returns {void} */ setHideBorder(value) { this.hideBorder = value; } /** * @param {boolean} value Whether to hide the title or not. * @returns {void} */ setHideTitle(value) { this.hideTitle = value; if (value) { this.height -= 30; } } /** * @param {string} text The title to set. * @returns {void} */ setTitle(text) { this.title = text; } /** * @returns {string} The rendered card title. */ renderTitle() { const titleText = ` ${this.title} `; const prefixIcon = ` ${this.titlePrefixIcon} `; return ` ${flexLayout({ items: [this.titlePrefixIcon ? prefixIcon : "", titleText], gap: 25, }).join("")} `; } /** * @returns {string} The rendered card gradient. */ renderGradient() { if (typeof this.colors.bgColor !== "object") { return ""; } const gradients = this.colors.bgColor.slice(1); return typeof this.colors.bgColor === "object" ? ` ${gradients.map((grad, index) => { let offset = (index * 100) / (gradients.length - 1); return ``; })} ` : ""; } /** * Retrieves css animations for a card. * * @returns {string} Animation css. */ getAnimations = () => { return ` /* Animations */ @keyframes scaleInAnimation { from { transform: translate(-5px, 5px) scale(0); } to { transform: translate(-5px, 5px) scale(1); } } @keyframes fadeInAnimation { from { opacity: 0; } to { opacity: 1; } } `; }; /** * @param {string} body The inner body of the card. * @returns {string} The rendered card. */ render(body) { return ` ${this.a11yTitle} ${this.a11yDesc} ${this.renderGradient()} ${this.hideTitle ? "" : this.renderTitle()} ${body} `; } } export { Card }; export default Card;