@synergy-design-system/components
Version:
This package provides the base of the Synergy Design System as native web components. It uses [lit](https://www.lit.dev) and parts of [shoelace](https://shoelace.style/). Synergy officially supports the latest two versions of all major browsers (as define
387 lines (382 loc) • 12.2 kB
JavaScript
import {
textarea_custom_styles_default
} from "./chunk.SHIPVO7H.js";
import {
textarea_styles_default
} from "./chunk.FQWBH6B3.js";
import {
defaultValue
} from "./chunk.3NXKLKWH.js";
import {
form_control_custom_styles_default,
form_control_styles_default
} from "./chunk.G4URZQCL.js";
import {
FormControlController
} from "./chunk.HP2LEQRU.js";
import {
HasSlotController
} from "./chunk.WVVQK5TE.js";
import {
enableDefaultSettings
} from "./chunk.HYFCK7MM.js";
import {
watch
} from "./chunk.BVZQ6QSY.js";
import {
component_styles_default
} from "./chunk.NLYVOJGK.js";
import {
SynergyElement
} from "./chunk.3THJTCRO.js";
import {
__decorateClass
} from "./chunk.Z4XV3SMG.js";
// src/components/textarea/textarea.component.ts
import { classMap } from "lit/directives/class-map.js";
import { html } from "lit";
import { ifDefined } from "lit/directives/if-defined.js";
import { live } from "lit/directives/live.js";
import { property, query, state } from "lit/decorators.js";
var SynTextarea = class extends SynergyElement {
constructor() {
super(...arguments);
this.formControlController = new FormControlController(this, {
assumeInteractionOn: ["syn-blur", "syn-input"]
});
this.hasSlotController = new HasSlotController(this, "help-text", "label");
this.hasFocus = false;
this.title = "";
this.name = "";
this.value = "";
this.size = "medium";
this.label = "";
this.helpText = "";
this.placeholder = "";
this.rows = 4;
this.resize = "vertical";
this.disabled = false;
this.readonly = false;
this.form = "";
this.required = false;
this.spellcheck = true;
this.defaultValue = "";
}
/** Gets the validity state object */
get validity() {
return this.input.validity;
}
/** Gets the validation message */
get validationMessage() {
return this.input.validationMessage;
}
connectedCallback() {
super.connectedCallback();
this.resizeObserver = new ResizeObserver(() => this.setTextareaHeight());
this.updateComplete.then(() => {
this.setTextareaHeight();
this.resizeObserver.observe(this.input);
});
}
firstUpdated() {
this.formControlController.updateValidity();
}
disconnectedCallback() {
var _a;
super.disconnectedCallback();
if (this.input) {
(_a = this.resizeObserver) == null ? void 0 : _a.unobserve(this.input);
}
}
handleBlur() {
this.hasFocus = false;
this.emit("syn-blur");
}
handleChange() {
this.value = this.input.value;
this.setTextareaHeight();
this.emit("syn-change");
}
handleFocus() {
this.hasFocus = true;
this.emit("syn-focus");
}
handleInput() {
this.value = this.input.value;
this.emit("syn-input");
}
handleInvalid(event) {
this.formControlController.setValidity(false);
this.formControlController.emitInvalidEvent(event);
}
setTextareaHeight() {
if (this.resize === "auto") {
this.sizeAdjuster.style.height = `${this.input.clientHeight}px`;
this.input.style.height = "auto";
this.input.style.height = `${this.input.scrollHeight}px`;
} else {
this.input.style.height = "";
}
}
handleDisabledChange() {
this.formControlController.setValidity(this.disabled);
}
handleRowsChange() {
this.setTextareaHeight();
}
async handleValueChange() {
await this.updateComplete;
this.formControlController.updateValidity();
this.setTextareaHeight();
}
/** Sets focus on the textarea. */
focus(options) {
this.input.focus(options);
}
/** Removes focus from the textarea. */
blur() {
this.input.blur();
}
/** Selects all the text in the textarea. */
select() {
this.input.select();
}
/** Gets or sets the textarea's scroll position. */
scrollPosition(position) {
if (position) {
if (typeof position.top === "number") this.input.scrollTop = position.top;
if (typeof position.left === "number") this.input.scrollLeft = position.left;
return void 0;
}
return {
top: this.input.scrollTop,
left: this.input.scrollTop
};
}
/** Sets the start and end positions of the text selection (0-based). */
setSelectionRange(selectionStart, selectionEnd, selectionDirection = "none") {
this.input.setSelectionRange(selectionStart, selectionEnd, selectionDirection);
}
/** Replaces a range of text with a new string. */
setRangeText(replacement, start, end, selectMode = "preserve") {
const selectionStart = start != null ? start : this.input.selectionStart;
const selectionEnd = end != null ? end : this.input.selectionEnd;
this.input.setRangeText(replacement, selectionStart, selectionEnd, selectMode);
if (this.value !== this.input.value) {
this.value = this.input.value;
this.setTextareaHeight();
}
}
/** Checks for validity but does not show a validation message. Returns `true` when valid and `false` when invalid. */
checkValidity() {
return this.input.checkValidity();
}
/** Gets the associated form, if one exists. */
getForm() {
return this.formControlController.getForm();
}
/** Checks for validity and shows the browser's validation message if the control is invalid. */
reportValidity() {
return this.input.reportValidity();
}
/** Sets a custom validation message. Pass an empty string to restore validity. */
setCustomValidity(message) {
this.input.setCustomValidity(message);
this.formControlController.updateValidity();
}
render() {
const hasLabelSlot = this.hasSlotController.test("label");
const hasHelpTextSlot = this.hasSlotController.test("help-text");
const hasLabel = this.label ? true : !!hasLabelSlot;
const hasHelpText = this.helpText ? true : !!hasHelpTextSlot;
return html`
<div
part="form-control"
class=${classMap({
"form-control": true,
"form-control--small": this.size === "small",
"form-control--medium": this.size === "medium",
"form-control--large": this.size === "large",
"form-control--has-label": hasLabel,
"form-control--has-help-text": hasHelpText
})}
>
<label
part="form-control-label"
class="form-control__label"
for="input"
aria-hidden=${hasLabel ? "false" : "true"}
>
<slot name="label">${this.label}</slot>
</label>
<div part="form-control-input" class="form-control-input">
<div
part="base"
class=${classMap({
textarea: true,
"textarea--small": this.size === "small",
"textarea--medium": this.size === "medium",
"textarea--large": this.size === "large",
"textarea--standard": !this.readonly,
"textarea--readonly": this.readonly,
"textarea--disabled": this.disabled,
"textarea--focused": this.hasFocus,
"textarea--empty": !this.value,
"textarea--resize-none": this.resize === "none",
"textarea--resize-vertical": this.resize === "vertical",
"textarea--resize-auto": this.resize === "auto"
})}
>
<textarea
part="textarea"
id="input"
class="textarea__control"
title=${this.title}
name=${ifDefined(this.name)}
.value=${live(this.value)}
?disabled=${this.disabled}
?readonly=${this.readonly}
?required=${this.required}
placeholder=${ifDefined(this.placeholder)}
rows=${ifDefined(this.rows)}
minlength=${ifDefined(this.minlength)}
maxlength=${ifDefined(this.maxlength)}
autocapitalize=${ifDefined(this.autocapitalize)}
autocorrect=${ifDefined(this.autocorrect ? void 0 : "off")}
?autofocus=${this.autofocus}
spellcheck=${ifDefined(this.spellcheck)}
enterkeyhint=${ifDefined(this.enterkeyhint)}
inputmode=${ifDefined(this.inputmode)}
aria-describedby="help-text"
=${this.handleChange}
=${this.handleInput}
=${this.handleInvalid}
=${this.handleFocus}
=${this.handleBlur}
></textarea>
<!-- This "adjuster" exists to prevent layout shifting. https://github.com/shoelace-style/shoelace/issues/2180 -->
<div part="textarea-adjuster" class="textarea__size-adjuster" ?hidden=${this.resize !== "auto"}></div>
</div>
</div>
<div
part="form-control-help-text"
id="help-text"
class="form-control__help-text"
aria-hidden=${hasHelpText ? "false" : "true"}
>
<slot name="help-text">${this.helpText}</slot>
</div>
</div>
`;
}
};
SynTextarea.styles = [component_styles_default, form_control_styles_default, textarea_styles_default, form_control_custom_styles_default, textarea_custom_styles_default];
__decorateClass([
query(".textarea__control")
], SynTextarea.prototype, "input", 2);
__decorateClass([
query(".textarea__size-adjuster")
], SynTextarea.prototype, "sizeAdjuster", 2);
__decorateClass([
state()
], SynTextarea.prototype, "hasFocus", 2);
__decorateClass([
property({ reflect: true })
], SynTextarea.prototype, "title", 2);
__decorateClass([
property()
], SynTextarea.prototype, "name", 2);
__decorateClass([
property()
], SynTextarea.prototype, "value", 2);
__decorateClass([
property({ reflect: true })
], SynTextarea.prototype, "size", 2);
__decorateClass([
property()
], SynTextarea.prototype, "label", 2);
__decorateClass([
property({ attribute: "help-text" })
], SynTextarea.prototype, "helpText", 2);
__decorateClass([
property()
], SynTextarea.prototype, "placeholder", 2);
__decorateClass([
property({ type: Number })
], SynTextarea.prototype, "rows", 2);
__decorateClass([
property()
], SynTextarea.prototype, "resize", 2);
__decorateClass([
property({ type: Boolean, reflect: true })
], SynTextarea.prototype, "disabled", 2);
__decorateClass([
property({ type: Boolean, reflect: true })
], SynTextarea.prototype, "readonly", 2);
__decorateClass([
property({ reflect: true })
], SynTextarea.prototype, "form", 2);
__decorateClass([
property({ type: Boolean, reflect: true })
], SynTextarea.prototype, "required", 2);
__decorateClass([
property({ type: Number })
], SynTextarea.prototype, "minlength", 2);
__decorateClass([
property({ type: Number })
], SynTextarea.prototype, "maxlength", 2);
__decorateClass([
property()
], SynTextarea.prototype, "autocapitalize", 2);
__decorateClass([
property({
attribute: "autocorrect",
reflect: true,
converter: {
fromAttribute: (value) => value === "" || value === "on",
toAttribute: (value) => value ? "on" : "off"
},
type: Boolean
})
], SynTextarea.prototype, "autocorrect", 2);
__decorateClass([
property()
], SynTextarea.prototype, "autocomplete", 2);
__decorateClass([
property({ type: Boolean })
], SynTextarea.prototype, "autofocus", 2);
__decorateClass([
property()
], SynTextarea.prototype, "enterkeyhint", 2);
__decorateClass([
property({
type: Boolean,
converter: {
// Allow "true|false" attribute values but keep the property boolean
fromAttribute: (value) => !value || value === "false" ? false : true,
toAttribute: (value) => value ? "true" : "false"
}
})
], SynTextarea.prototype, "spellcheck", 2);
__decorateClass([
property()
], SynTextarea.prototype, "inputmode", 2);
__decorateClass([
defaultValue()
], SynTextarea.prototype, "defaultValue", 2);
__decorateClass([
watch("disabled", { waitUntilFirstUpdate: true })
], SynTextarea.prototype, "handleDisabledChange", 1);
__decorateClass([
watch("rows", { waitUntilFirstUpdate: true })
], SynTextarea.prototype, "handleRowsChange", 1);
__decorateClass([
watch("value", { waitUntilFirstUpdate: true })
], SynTextarea.prototype, "handleValueChange", 1);
SynTextarea = __decorateClass([
enableDefaultSettings("SynTextarea")
], SynTextarea);
export {
SynTextarea
};
//# sourceMappingURL=chunk.KGSP7LN2.js.map