import { Component, Element, Host, Prop, h, Watch } from '@stencil/core' import { TextAnimationType } from './meta/types' import { TypographyTagType } from '@type/text' import { TypographyTruncateType } from '@type/text' import { TypographyType, TypographyVariants } from '@type/typography' import { typographyDefaultsVariant } from './meta/variants' import RandomText from '@common/yugop' /** * @slot default - Add `text string` to this slot, **avoid** to add `HTML elements` or `components` here. */ @Component( { tag: 'mds-text', styleUrl: 'mds-text.css', shadow: true, } ) export class MdsText { private cssTextAnimationSpeed: number = 2 private cssTextAnimationPlaceholderChar: string = ' ' private randomTextOptions = { speed: this.cssTextAnimationSpeed, placeholderChar: this.cssTextAnimationPlaceholderChar, frameOffset: 10, charOffset: 20, charStep: 15, } private randomText:RandomText @Element() host: HTMLMdsTextElement /** * Specifies if the text is animated when it is rendered */ @Prop() readonly animation?: TextAnimationType = 'none' /** * Specifies the HTML tag of the element */ @Prop({ mutable: true, reflect: true }) tag: TypographyTagType /** * Specifies the text string to the component instead of passing an HTML node */ @Prop({ reflect: true }) readonly text?: string /** * Specifies if the text shoud be truncated or should behave as a normal text */ @Prop({ reflect: true }) readonly truncate?: TypographyTruncateType /** * Specifies the font typography of the element */ @Prop({ reflect: true }) readonly typography: TypographyType = 'detail' /** * Specifies the variant for `typography` */ @Prop({ reflect: true }) readonly variant?: TypographyVariants private animateText = (text: string): void => { const textElement = this.host.shadowRoot?.querySelector('.text') as HTMLElement this.randomTextOptions.speed = this.cssTextAnimationSpeed this.randomTextOptions.placeholderChar = this.cssTextAnimationPlaceholderChar // console.info('animateText', this.cssTextAnimationPlaceholderChar) this.randomText = new RandomText({ str: text, onProgress: (str: string) => { textElement.innerHTML = str }, ...this.randomTextOptions, }) this.randomText.start() } private updateCSSCustomProps = (): void => { if (typeof window === 'undefined') return const elementStyles = window.getComputedStyle(this.host) this.cssTextAnimationSpeed = Number(elementStyles.getPropertyValue('--mds-text-animation-speed')) const placeholderChar = elementStyles.getPropertyValue('--mds-text-animation-placeholder-char') if (placeholderChar === '" "' || placeholderChar === '\' \'') { this.cssTextAnimationPlaceholderChar = ' ' return } this.cssTextAnimationPlaceholderChar = placeholderChar } componentWillRender (): void { const { tag } = typographyDefaultsVariant[this.typography] this.tag = this.tag ?? tag as TypographyTagType } componentDidLoad (): void { if (this.animation === 'yugop') this.updateCSSCustomProps() } @Watch('text') textHandler (newValue?: string): void { if (this.animation === 'none') { return } if (this.randomText) { this.randomText.stop() } if (newValue) { this.animateText(newValue) } } render () { return ( { !this.text ? : this.text } ) } }