import { booleanAttribute, ChangeDetectionStrategy, Component, computed, input, model, ViewEncapsulation, } from "@angular/core"; import { setupInvalid } from "../../core/validation/setupInvalid"; @Component({ selector: "sd-textarea", changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, standalone: true, imports: [], template: `
@if (value()) {
{{ value() }} 
} @else if (placeholder()) { {{ placeholder() }} } @else {   }
@if (!readonly() && !disabled()) { } `, styles: [ /* language=SCSS */ ` @use "sass:map"; @use "../../../scss/commons/variables"; @use "../../../scss/commons/mixins"; sd-textarea { display: block; position: relative; > textarea, > ._contents { @include mixins.form-control-base(); resize: none; overflow: auto; width: 100%; border: 1px solid var(--trans-lighter); border-radius: var(--border-radius-default); background: var(--theme-secondary-lightest); &:focus { outline: none; border-color: var(--theme-primary-default); } &::-webkit-scrollbar { display: none; } &::-webkit-input-placeholder { color: var(--text-trans-lighter); } } &:not([data-sd-inset="true"]):not([data-sd-disabled="true"]) > ._contents { height: 0; max-height: 0; padding-top: 0; padding-bottom: 0; margin-top: 0; margin-bottom: 0; } @each $key, $val in map.get(variables.$vars, theme) { &[data-sd-theme="#{$key}"] { > textarea, > ._contents { background: var(--theme-#{$key}-lightest); } } } &[data-sd-size="sm"] { > textarea, > ._contents { padding: var(--gap-xs) var(--gap-sm); } } &[data-sd-size="lg"] { > textarea, > ._contents { padding: var(--gap-default) var(--gap-lg); } } &[data-sd-inline="true"] { display: inline-block; vertical-align: top; > textarea, > ._contents { width: auto; vertical-align: top; } } &[data-sd-inset="true"] { > ._contents { display: block; } > textarea { position: absolute; top: 0; left: 0; } > textarea, > ._contents { width: 100%; border: none; border-radius: 0; } > textarea:focus { outline: 1px solid var(--theme-primary-default); outline-offset: -1px; } } &[data-sd-disabled="true"] { > ._contents { display: block; background: var(--theme-gray-lightest); color: var(--text-trans-light); } &[data-sd-inset="true"] { > ._contents { background: var(--control-color); color: var(--text-trans-default); } } } } `, ], host: { "[attr.data-sd-disabled]": "disabled()", "[attr.data-sd-readonly]": "readonly()", "[attr.data-sd-inline]": "inline()", "[attr.data-sd-inset]": "inset()", "[attr.data-sd-size]": "size()", "[attr.data-sd-theme]": "theme()", }, }) export class SdTextarea { value = model(); placeholder = input(); title = input(); minRows = input(1); disabled = input(false, { transform: booleanAttribute }); readonly = input(false, { transform: booleanAttribute }); required = input(false, { transform: booleanAttribute }); inline = input(false, { transform: booleanAttribute }); inset = input(false, { transform: booleanAttribute }); size = input<"sm" | "lg">(); validatorFn = input<(value: string | undefined) => string | undefined>(); theme = input< "primary" | "secondary" | "info" | "success" | "warning" | "danger" | "gray" | "blue-gray" >(); inputStyle = input(); inputClass = input(); currRows = computed(() => Math.max(this.minRows(), this.value()?.split("\n").length ?? 1)); constructor() { setupInvalid(() => { const errorMessages: string[] = []; if (this.value() == null) { if (this.required()) { errorMessages.push("값을 입력하세요."); } } if (this.validatorFn()) { const message = this.validatorFn()!(this.value()); if (message != null) { errorMessages.push(message); } } return errorMessages.join("\r\n"); }); } onInput(event: Event): void { const inputEl = event.target as HTMLTextAreaElement; this.value.set(inputEl.value === "" ? undefined : inputEl.value); } }