diff --git a/.eslintrc.json b/.eslintrc.json index 87bdb6a9..c061d105 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -12,6 +12,9 @@ } } }, + "parserOptions": { + "ecmaVersion": 2024 + }, "rules": { "no-console": [ "warn", diff --git a/src/components/TextArea/index.js b/src/components/TextArea/index.js new file mode 100644 index 00000000..6730b85f --- /dev/null +++ b/src/components/TextArea/index.js @@ -0,0 +1,83 @@ +import { Component } from 'pet-dex-utilities'; +import './index.scss'; + +const events = [ + 'name:change', + 'placeholder:change', + 'maxLength:change', + 'required:change', + 'error', +]; + +const html = ` +
+ + +
+`; + +export default function TextArea({ + name = '', + placeholder = '', + maxLength, + required = true, +}) { + Component.call(this, { html, events }); + const $textarea = this.selected.get('textarea'); + const $resizeTrigger = this.selected.get('resize-trigger'); + + this.setName(name); + this.setPlaceholder(placeholder); + this.setRequired(required); + if (maxLength) this.setMaxLength(maxLength); + + function autoResize() { + $resizeTrigger.innerText = $textarea.value; + + $textarea.style.height = 'auto'; + $textarea.style.height = `${$resizeTrigger.offsetHeight}px`; + } + + this.listen('mount', () => { + $textarea.addEventListener('focus', () => + $textarea.classList.remove('textarea__input--error'), + ); + $textarea.addEventListener('input', autoResize); + window.addEventListener('resize', autoResize); + }); + + this.listen('unmount', () => { + $textarea.removeEventListener('focus', () => + $textarea.classList.remove('textarea__input--error'), + ); + $textarea.removeEventListener('input', autoResize); + window.removeEventListener('resize', autoResize); + }); +} + +TextArea.prototype = Object.assign(TextArea.prototype, Component.prototype, { + setName(name = '') { + this.selected.get('textarea').name = name; + this.emit('name:change', name); + }, + setPlaceholder(placeholder = '') { + this.selected.get('textarea').placeholder = placeholder; + this.emit('placeholder:change', placeholder); + }, + setMaxLength(maxLength) { + const $textArea = this.selected.get('textarea'); + + if (maxLength) $textArea.maxLength = maxLength; + else $textArea.removeAttribute('maxlength'); + + this.emit('maxLength:change', maxLength ?? Infinity); + }, + setRequired(required = true) { + this.selected.get('textarea').required = required; + this.emit('required:change', required); + }, + error() { + this.selected.get('textarea').classList.add('textarea__input--error'); + this.emit('error'); + }, +}); diff --git a/src/components/TextArea/index.scss b/src/components/TextArea/index.scss new file mode 100644 index 00000000..f9912465 --- /dev/null +++ b/src/components/TextArea/index.scss @@ -0,0 +1,56 @@ +@use '~styles/fonts.scss' as fonts; +@use '~styles/colors.scss' as colors; + +.textarea { + position: relative; + + &__input, + &__trigger { + width: 100%; + + font-family: fonts.$fifthFont; + font-size: fonts.$sm; + line-height: 1; + } + + &__input { + overflow: hidden; + + padding-bottom: 1.4rem; + + border: unset; + border-bottom: 0.1rem solid colors.$gray400; + + position: relative; + z-index: 1; + + outline-color: transparent; + + transition: 0.2s ease-in-out outline; + + resize: none; + + &::placeholder { + color: colors.$gray400; + } + + &:focus { + outline-color: colors.$primary200; + } + + &--error { + color: colors.$secondary100; + + background: colors.$error100; + } + } + + &__trigger { + display: block; + + position: absolute; + top: 0; + + visibility: hidden; + } +} diff --git a/src/stories/TextArea.stories.js b/src/stories/TextArea.stories.js new file mode 100644 index 00000000..7d30561a --- /dev/null +++ b/src/stories/TextArea.stories.js @@ -0,0 +1,26 @@ +import Textarea from '../components/TextArea'; + +export default { + title: 'Components/TextArea', + render: (args) => { + const textarea = new Textarea(args); + const $container = document.createElement('div'); + textarea.mount($container); + + return $container; + }, + argTypes: { + name: { control: 'text', default: '' }, + placeholder: { control: 'text', default: '' }, + maxLength: { control: 'number', default: 524288 }, + required: { control: 'boolean', default: true }, + }, +}; + +export const Default = { + args: { + name: 'textarea', + placeholder: 'Escreva o cuidado especial', + required: true, + }, +}; diff --git a/src/styles/fonts.scss b/src/styles/fonts.scss index 6c510fff..e63a9c76 100644 --- a/src/styles/fonts.scss +++ b/src/styles/fonts.scss @@ -2,6 +2,7 @@ $primaryFont: 'Montserrat', sans-serif; $secondaryFont: 'Wix Madefor Display', sans-serif; $tertiaryFont: 'Helvetica', sans-serif; $fourthFont: 'Noto Sans', sans-serif; +$fifthFont: 'Poppins', sans-serif; $xs: 1.4rem; $sm: 1.6rem;