import { attr, godown, StyleController, styles } from "@godown/element"; import { type TemplateResult, css, html } from "lit"; import { property } from "lit/decorators.js"; import { GlobalStyle, cssGlobalVars, scopePrefix } from "../../internal/global-style.js"; const defineName = "breath"; const cssScope = scopePrefix(defineName); const splitTextRegexp = /[\s,]+/; /** * {@linkcode Breath} render the text with a breathing effect. * * Dynamically generate a breathing effect based on the length of the split text. * * If there is not enough CSS variable, overrun elements will use the. * * godown was a css library in its earliest days, * and this is the component version of its first effect. * * Inspired by Vercel home page (2023). * * @slot - Breathing parts. * @category effect */ @godown(defineName) @styles( css` :host { ${cssScope}--deg: 60deg; ${cssScope}--1-1: hsl(0 70% 55%); ${cssScope}--1-2: hsl(30 90% 60%); ${cssScope}--2-1: hsl(130 70% 50%); ${cssScope}--2-2: hsl(180 60% 40%); ${cssScope}--3-1: hsl(270 80% 55%); ${cssScope}--3-2: hsl(210 90% 50%); ${cssScope}--1: linear-gradient(var(${cssScope}--deg), var(${cssScope}--1-1), var(${cssScope}--1-2)); ${cssScope}--2: linear-gradient(var(${cssScope}--deg), var(${cssScope}--2-1), var(${cssScope}--2-2)); ${cssScope}--3: linear-gradient(var(${cssScope}--deg), var(${cssScope}--3-1), var(${cssScope}--3-2)); } `, css` :host { margin: auto; width: fit-content; font-size: 2em; align-items: center; direction: ltr; } :host, :host([contents]) [part="root"] { display: flex; } [part="root"] { display: contents; } ::selection { background: none; } .rel { position: relative; font-weight: 800; font-size: inherit; letter-spacing: -0.05em; } `, css` .nocolor, .colorful { padding: 0 0.05em; box-sizing: border-box; display: inline-block; animation-iteration-count: infinite; color: transparent; -webkit-background-clip: text !important; background-clip: text !important; } .colorful { opacity: 0; animation-name: colorfulN; } .nocolor { position: absolute; top: 0; background: var(${cssGlobalVars.backgroundClip}); } `, ) class Breath extends GlobalStyle { /** * Strings or array of strings, * if array, divided each element into chunks, * otherwise split strings by whitespace. */ @property() content: string | string[]; /** * Effect duration. */ @property({ type: Number }) duration: number; constructor() { super(); new StyleController(this, () => this._computeStyle(this.getTexts().length)); } protected render(): TemplateResult<1> { const texts = this.getTexts(); return html`