standard-ui/components/dist/textarea.js
2021-07-18 17:05:41 +05:30

200 lines
5.5 KiB
JavaScript

const smTextarea = document.createElement('template')
smTextarea.innerHTML = `
<style>
*,
*::before,
*::after {
padding: 0;
margin: 0;
-webkit-box-sizing: border-box;
box-sizing: border-box;
}
::-moz-focus-inner{
border: none;
}
.hide{
opacity: 0 !important;
}
:host{
display: grid;
--accent-color: #4d2588;
--text-color: 17, 17, 17;
--background-color: 255, 255, 255;
--danger-color: red;
--border-radius: 0.3rem;
--background: rgba(var(--text-color), 0.06);
--padding: initial;
--max-height: 8rem;
}
:host([variant="outlined"]) .textarea {
box-shadow: 0 0 0 0.1rem rgba(var(--text-color), 0.4) inset;
background: rgba(var(--background-color), 1);
}
.textarea{
display: grid;
position: relative;
cursor: text;
min-width: 0;
text-align: left;
overflow: hidden auto;
grid-template-columns: 1fr;
align-items: stretch;
max-height: var(--max-height);
background: var(--background);
border-radius: var(--border-radius);
padding: var(--padding);
}
.textarea::after,
textarea{
padding: 0.7rem 1rem;
width: 100%;
min-width: 1em;
font: inherit;
color: inherit;
resize: none;
grid-area: 2/1;
justify-self: stretch;
background: none;
appearance: none;
border: none;
outline: none;
line-height: 1.5;
overflow: hidden;
}
.textarea::after{
content: attr(data-value) ' ';
visibility: hidden;
white-space: pre-wrap;
overflow-wrap: break-word;
word-wrap: break-word;
hyphens: auto;
}
.readonly{
pointer-events: none;
}
.textarea:focus-within:not(.readonly){
box-shadow: 0 0 0 0.1rem var(--accent-color) inset;
}
.placeholder{
position: absolute;
margin: 0.7rem 1rem;
opacity: .7;
font-weight: 400;
font-size: 1rem;
line-height: 1.5;
pointer-events: none;
user-select: none;
}
:host([disabled]) .textarea{
cursor: not-allowed;
opacity: 0.6;
}
@media (any-hover: hover){
::-webkit-scrollbar{
width: 0.5rem;
height: 0.5rem;
}
::-webkit-scrollbar-thumb{
background: rgba(var(--text-color), 0.3);
border-radius: 1rem;
&:hover{
background: rgba(var(--text-color), 0.5);
}
}
}
</style>
<label class="textarea" part="textarea">
<span class="placeholder"></span>
<textarea rows="1"></textarea>
</label>
`;
customElements.define('sm-textarea',
class extends HTMLElement {
constructor() {
super()
this.attachShadow({
mode: 'open'
}).append(smTextarea.content.cloneNode(true))
this.textarea = this.shadowRoot.querySelector('textarea')
this.textareaBox = this.shadowRoot.querySelector('.textarea')
this.placeholder = this.shadowRoot.querySelector('.placeholder')
this.reflectedAttributes = ['disabled', 'required', 'readonly', 'rows', 'minlength', 'maxlength']
this.reset = this.reset.bind(this)
this.focusIn = this.focusIn.bind(this)
this.fireEvent = this.fireEvent.bind(this)
this.checkInput = this.checkInput.bind(this)
}
static get observedAttributes() {
return ['disabled', 'value', 'placeholder', 'required', 'readonly', 'rows', 'minlength', 'maxlength']
}
get value() {
return this.textarea.value
}
set value(val) {
this.setAttribute('value', val)
this.fireEvent()
}
get disabled() {
return this.hasAttribute('disabled')
}
set disabled(val) {
if (val) {
this.setAttribute('disabled', '')
} else {
this.removeAttribute('disabled')
}
}
get isValid() {
return this.textarea.checkValidity()
}
reset(){
this.setAttribute('value', '')
}
focusIn(){
this.textarea.focus()
}
fireEvent(){
let event = new Event('input', {
bubbles: true,
cancelable: true,
composed: true
});
this.dispatchEvent(event);
}
checkInput(){
if (!this.hasAttribute('placeholder') || this.getAttribute('placeholder') === '')
return;
if (this.textarea.value !== '') {
this.placeholder.classList.add('hide')
} else {
this.placeholder.classList.remove('hide')
}
}
connectedCallback() {
this.textarea.addEventListener('input', e => {
this.textareaBox.dataset.value = this.textarea.value
this.checkInput()
})
}
attributeChangedCallback(name, oldValue, newValue) {
if (this.reflectedAttributes.includes(name)) {
if (this.hasAttribute(name)) {
this.textarea.setAttribute(name, this.getAttribute(name) ? this.getAttribute(name) : '')
}
else {
this.textContent.removeAttribute(name)
}
}
else if (name === 'placeholder') {
this.placeholder.textContent = this.getAttribute('placeholder')
}
else if (name === 'value') {
this.textarea.value = newValue;
this.textareaBox.dataset.value = newValue
this.checkInput()
}
}
})