@nuralyui/textarea 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,670 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2023 Nuraly, Laabidi Aymen
4
+ * SPDX-License-Identifier: MIT
5
+ */
6
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
7
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
8
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
9
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
10
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
11
+ };
12
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
13
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
14
+ return new (P || (P = Promise))(function (resolve, reject) {
15
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
16
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
17
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
18
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
19
+ });
20
+ };
21
+ import { LitElement, html } from 'lit';
22
+ import { customElement, property, state, query } from 'lit/decorators.js';
23
+ import { styles } from './textarea.style.js';
24
+ import '../icon/icon.component.js';
25
+ import { TEXTAREA_DEFAULTS, EMPTY_STRING } from './textarea.types.js';
26
+ import { NuralyUIBaseMixin } from '../../shared/base-mixin.js';
27
+ import { TextareaValidationController, TextareaEventController } from './controllers/index.js';
28
+ /**
29
+ * Versatile textarea component with validation, resize options, and interactive features.
30
+ *
31
+ * @example
32
+ * ```html
33
+ * <nr-textarea placeholder="Enter your message"></nr-textarea>
34
+ * <nr-textarea rows="5" resize="vertical"></nr-textarea>
35
+ * <nr-textarea max-length="500" show-count></nr-textarea>
36
+ * ```
37
+ *
38
+ * @fires nr-textarea-change - Value changes
39
+ * @fires nr-focus - Textarea focused
40
+ * @fires nr-blur - Textarea blurred
41
+ * @fires nr-clear - Clear button clicked
42
+ * @fires nr-resize - Textarea resized
43
+ *
44
+ * @slot label - Textarea label
45
+ * @slot helper-text - Helper text
46
+ * @slot addon-before - Content before textarea
47
+ * @slot addon-after - Content after textarea
48
+ */
49
+ let NrTextareaElement = class NrTextareaElement extends NuralyUIBaseMixin(LitElement) {
50
+ constructor() {
51
+ super();
52
+ // Controllers
53
+ this.validationController = new TextareaValidationController(this);
54
+ this.eventController = new TextareaEventController(this);
55
+ /** Disables the textarea */
56
+ this.disabled = false;
57
+ /** Makes the textarea read-only */
58
+ this.readonly = false;
59
+ /** Visual state (default, success, warning, error) */
60
+ this.state = "default" /* TEXTAREA_STATE.Default */;
61
+ /** Current textarea value */
62
+ this.value = EMPTY_STRING;
63
+ /** Textarea size (small, medium, large) */
64
+ this.size = "medium" /* TEXTAREA_SIZE.Medium */;
65
+ /** Visual variant (outlined, underlined, filled) */
66
+ this.variant = "underlined" /* TEXTAREA_VARIANT.Underlined */;
67
+ /** Resize behavior (none, vertical, horizontal, both) */
68
+ this.resize = "vertical" /* TEXTAREA_RESIZE.Vertical */;
69
+ /** Number of visible text lines */
70
+ this.rows = TEXTAREA_DEFAULTS.ROWS;
71
+ /** Number of visible character columns */
72
+ this.cols = TEXTAREA_DEFAULTS.COLS;
73
+ /** Placeholder text */
74
+ this.placeholder = EMPTY_STRING;
75
+ /** HTML autocomplete attribute */
76
+ this.autocomplete = 'off';
77
+ /** Shows clear button */
78
+ this.allowClear = false;
79
+ /** Shows character counter */
80
+ this.showCount = false;
81
+ /** Auto-resize textarea based on content */
82
+ this.autoResize = false;
83
+ /** Array of validation rules */
84
+ this.rules = [];
85
+ /** Validate on change */
86
+ this.validateOnChange = true;
87
+ /** Validate on blur */
88
+ this.validateOnBlur = true;
89
+ /** Show validation status icon */
90
+ this.hasFeedback = false;
91
+ this.isFocused = false;
92
+ this.characterCount = 0;
93
+ // Initialize character count based on initial value
94
+ this.characterCount = this.value.length;
95
+ // Setup controller event listeners
96
+ this.setupControllerListeners();
97
+ }
98
+ /** Clearable alias for controller interface compatibility */
99
+ get clearable() {
100
+ return this.allowClear;
101
+ }
102
+ /**
103
+ * Setup controller event listeners
104
+ */
105
+ setupControllerListeners() {
106
+ // Validation events
107
+ this.addEventListener('textarea-validation', (e) => {
108
+ this.validationResult = e.detail.validationResult;
109
+ });
110
+ // Input events
111
+ this.addEventListener('textarea-input', (e) => {
112
+ this.handleControllerInput(e.detail.value);
113
+ });
114
+ // Focus/blur events
115
+ this.addEventListener('textarea-focus', () => {
116
+ this.isFocused = true;
117
+ });
118
+ this.addEventListener('textarea-blur', () => {
119
+ this.isFocused = false;
120
+ if (this.validateOnBlur) {
121
+ this.validationController.validateOnBlurIfEnabled();
122
+ }
123
+ });
124
+ // Clear events
125
+ this.addEventListener('textarea-clear', (e) => {
126
+ this.handleControllerClear(e.detail.previousValue);
127
+ });
128
+ }
129
+ /**
130
+ * Handle input from controller
131
+ */
132
+ handleControllerInput(newValue) {
133
+ // Handle max length
134
+ if (this.maxLength && newValue.length > this.maxLength) {
135
+ this.value = newValue.slice(0, this.maxLength);
136
+ }
137
+ else {
138
+ this.value = newValue;
139
+ }
140
+ this.characterCount = this.value.length;
141
+ this.autoResizeIfNeeded();
142
+ this.dispatchChangeEvent();
143
+ // Validate if change validation is enabled
144
+ if (this.validateOnChange) {
145
+ this.validationController.validateOnChangeIfEnabled(this.value);
146
+ }
147
+ }
148
+ /**
149
+ * Handle clear from controller
150
+ */
151
+ handleControllerClear(previousValue) {
152
+ this.characterCount = 0;
153
+ this.dispatchChangeEvent();
154
+ // Custom clear event for backward compatibility
155
+ this.dispatchEvent(new CustomEvent('nr-clear', {
156
+ detail: { value: this.value, previousValue },
157
+ bubbles: true
158
+ }));
159
+ }
160
+ connectedCallback() {
161
+ super.connectedCallback();
162
+ this.setupResizeObserver();
163
+ }
164
+ disconnectedCallback() {
165
+ super.disconnectedCallback();
166
+ this.cleanupResizeObserver();
167
+ }
168
+ firstUpdated(changedProperties) {
169
+ super.firstUpdated(changedProperties);
170
+ this.updateTextareaValue();
171
+ this.autoResizeIfNeeded();
172
+ // Setup resize observer for the textarea element
173
+ if (this.resizeObserver && this.textareaElement) {
174
+ this.resizeObserver.observe(this.textareaElement);
175
+ }
176
+ // Setup event controllers with DOM elements
177
+ this.eventController.setupEventListeners();
178
+ }
179
+ updated(changedProperties) {
180
+ super.updated(changedProperties);
181
+ if (changedProperties.has('value')) {
182
+ this.characterCount = this.value.length;
183
+ this.updateTextareaValue();
184
+ this.autoResizeIfNeeded();
185
+ }
186
+ if (changedProperties.has('autoResize')) {
187
+ this.autoResizeIfNeeded();
188
+ }
189
+ // Update validation rules if they changed
190
+ if (changedProperties.has('rules')) {
191
+ this.validationController.clearValidation();
192
+ if (this.rules.length > 0 && this.value) {
193
+ this.validationController.validate(this.value);
194
+ }
195
+ }
196
+ }
197
+ setupResizeObserver() {
198
+ if (typeof ResizeObserver !== 'undefined') {
199
+ this.resizeObserver = new ResizeObserver((entries) => {
200
+ for (const entry of entries) {
201
+ const { width, height } = entry.contentRect;
202
+ this.dispatchResizeEvent(width, height);
203
+ }
204
+ });
205
+ }
206
+ }
207
+ cleanupResizeObserver() {
208
+ if (this.resizeObserver) {
209
+ this.resizeObserver.disconnect();
210
+ this.resizeObserver = undefined;
211
+ }
212
+ }
213
+ updateTextareaValue() {
214
+ if (this.textareaElement && this.textareaElement.value !== this.value) {
215
+ this.textareaElement.value = this.value;
216
+ }
217
+ }
218
+ autoResizeIfNeeded() {
219
+ if (!this.autoResize || !this.textareaElement)
220
+ return;
221
+ // Reset height to auto to get the natural scroll height
222
+ this.textareaElement.style.height = 'auto';
223
+ const scrollHeight = this.textareaElement.scrollHeight;
224
+ // Apply min/max height constraints
225
+ let newHeight = scrollHeight;
226
+ if (this.minHeight && newHeight < this.minHeight) {
227
+ newHeight = this.minHeight;
228
+ }
229
+ if (this.maxHeight && newHeight > this.maxHeight) {
230
+ newHeight = this.maxHeight;
231
+ }
232
+ this.textareaElement.style.height = `${newHeight}px`;
233
+ }
234
+ /**
235
+ * Handle input event (now delegated to event controller via addEventListener)
236
+ */
237
+ handleInput(e) {
238
+ // This method is kept for backward compatibility but actual handling
239
+ // is now done through the event controller
240
+ this.eventController.handleInput(e);
241
+ }
242
+ /**
243
+ * Handle focus event (now delegated to event controller)
244
+ */
245
+ handleFocus(e) {
246
+ this.eventController.handleFocus(e);
247
+ // Dispatch legacy event for backward compatibility
248
+ this.dispatchEvent(new CustomEvent('nr-focus', {
249
+ detail: {
250
+ focused: true,
251
+ originalEvent: e
252
+ },
253
+ bubbles: true
254
+ }));
255
+ }
256
+ /**
257
+ * Handle blur event (now delegated to event controller)
258
+ */
259
+ handleBlur(e) {
260
+ this.eventController.handleBlur(e);
261
+ // Dispatch legacy event for backward compatibility
262
+ this.dispatchEvent(new CustomEvent('nr-blur', {
263
+ detail: {
264
+ focused: false,
265
+ originalEvent: e
266
+ },
267
+ bubbles: true
268
+ }));
269
+ }
270
+ /**
271
+ * Handle clear event (now delegated to event controller)
272
+ */
273
+ handleClear() {
274
+ this.eventController.handleClear();
275
+ }
276
+ dispatchChangeEvent() {
277
+ const detail = {
278
+ value: this.value,
279
+ length: this.characterCount,
280
+ exceedsMaxLength: this.maxLength ? this.characterCount > this.maxLength : false,
281
+ validation: this.validationResult
282
+ };
283
+ this.dispatchEvent(new CustomEvent('nr-textarea-change', {
284
+ detail,
285
+ bubbles: true
286
+ }));
287
+ }
288
+ dispatchResizeEvent(width, height) {
289
+ const detail = {
290
+ width,
291
+ height,
292
+ direction: this.resize
293
+ };
294
+ this.dispatchEvent(new CustomEvent('nr-resize', {
295
+ detail,
296
+ bubbles: true
297
+ }));
298
+ }
299
+ /**
300
+ * Focus the textarea with optional configuration
301
+ */
302
+ focus(options) {
303
+ this.eventController.focus();
304
+ // Handle cursor positioning if needed
305
+ if ((options === null || options === void 0 ? void 0 : options.cursor) !== undefined || (options === null || options === void 0 ? void 0 : options.select)) {
306
+ setTimeout(() => {
307
+ if (!this.textareaElement)
308
+ return;
309
+ if ((options === null || options === void 0 ? void 0 : options.cursor) !== undefined) {
310
+ if (typeof options.cursor === 'number') {
311
+ this.eventController.setCursorPosition(options.cursor);
312
+ }
313
+ else if (options.cursor === 'start') {
314
+ this.eventController.setCursorPosition(0);
315
+ }
316
+ else if (options.cursor === 'end') {
317
+ this.eventController.setCursorPosition(this.value.length);
318
+ }
319
+ else if (options.cursor === 'all') {
320
+ this.eventController.selectAll();
321
+ }
322
+ }
323
+ else if (options === null || options === void 0 ? void 0 : options.select) {
324
+ this.eventController.selectAll();
325
+ }
326
+ });
327
+ }
328
+ }
329
+ /**
330
+ * Blur the textarea
331
+ */
332
+ blur() {
333
+ this.eventController.blur();
334
+ }
335
+ /**
336
+ * Get validation status
337
+ */
338
+ getValidationResult() {
339
+ return this.validationController.validationResult;
340
+ }
341
+ /**
342
+ * Trigger validation manually (ValidatableComponent interface)
343
+ */
344
+ validate() {
345
+ return __awaiter(this, void 0, void 0, function* () {
346
+ const result = yield this.validationController.validate(this.value);
347
+ return result.isValid;
348
+ });
349
+ }
350
+ /**
351
+ * Clear validation state
352
+ */
353
+ clearValidation() {
354
+ this.validationController.clearValidation();
355
+ }
356
+ /**
357
+ * Clear the textarea value
358
+ */
359
+ clear() {
360
+ this.eventController.handleClear();
361
+ }
362
+ /**
363
+ * Add a validation rule (ValidatableComponent interface)
364
+ */
365
+ addRule(rule) {
366
+ this.validationController.addRule(rule);
367
+ }
368
+ /**
369
+ * Remove validation rules matching predicate (ValidatableComponent interface)
370
+ */
371
+ removeRule(predicate) {
372
+ this.validationController.removeRule(predicate);
373
+ }
374
+ /**
375
+ * Clear all validation rules (ValidatableComponent interface)
376
+ */
377
+ clearRules() {
378
+ this.validationController.clearRules();
379
+ }
380
+ /**
381
+ * Get current validation status (ValidatableComponent interface)
382
+ */
383
+ getValidationStatus() {
384
+ var _a;
385
+ const result = this.validationController.validationResult;
386
+ return {
387
+ isValid: (_a = result === null || result === void 0 ? void 0 : result.isValid) !== null && _a !== void 0 ? _a : true,
388
+ errors: (result === null || result === void 0 ? void 0 : result.level) === 'error' ? result.messages : [],
389
+ warnings: (result === null || result === void 0 ? void 0 : result.level) === 'warning' ? result.messages : []
390
+ };
391
+ }
392
+ /**
393
+ * Check if the textarea value is valid
394
+ */
395
+ isValid() {
396
+ return this.validationController.isValid();
397
+ }
398
+ // Form integration methods (FormFieldCapable interface)
399
+ /**
400
+ * Check validity (HTML form API compatibility)
401
+ */
402
+ checkValidity() {
403
+ return this.validationController.isValid();
404
+ }
405
+ /**
406
+ * Report validity (HTML form API compatibility)
407
+ */
408
+ reportValidity() {
409
+ const isValid = this.validationController.isValid();
410
+ if (!isValid) {
411
+ // Trigger validation to show error messages
412
+ this.validationController.validate(this.value);
413
+ }
414
+ return isValid;
415
+ }
416
+ /**
417
+ * Set custom validity message (HTML form API compatibility)
418
+ */
419
+ setCustomValidity(message) {
420
+ if (message) {
421
+ // Add custom validation rule
422
+ this.validationController.addRule({
423
+ validator: () => false,
424
+ message,
425
+ level: 'error',
426
+ blocking: true
427
+ });
428
+ }
429
+ else {
430
+ // Remove custom validation rules
431
+ this.validationController.removeRule(rule => rule.message === message);
432
+ }
433
+ }
434
+ /**
435
+ * Trigger validation manually (enhanced version)
436
+ */
437
+ validateTextarea() {
438
+ return __awaiter(this, void 0, void 0, function* () {
439
+ const result = yield this.validationController.validate(this.value);
440
+ return result.isValid;
441
+ });
442
+ }
443
+ /**
444
+ * Set validation state externally (for form integration)
445
+ */
446
+ setValidationStatus(result) {
447
+ this.validationResult = result;
448
+ // Update state based on validation result
449
+ if (result.level === 'error') {
450
+ this.state = "error" /* TEXTAREA_STATE.Error */;
451
+ }
452
+ else if (result.level === 'warning') {
453
+ this.state = "warning" /* TEXTAREA_STATE.Warning */;
454
+ }
455
+ else if (result.isValid) {
456
+ this.state = "success" /* TEXTAREA_STATE.Success */;
457
+ }
458
+ this.requestUpdate();
459
+ }
460
+ renderLabel() {
461
+ return html `
462
+ <div class="textarea-label">
463
+ <slot name="label"></slot>
464
+ ${this.required ? html `<span class="required-indicator">*</span>` : ''}
465
+ </div>
466
+ `;
467
+ }
468
+ renderTextarea() {
469
+ return html `
470
+ <textarea
471
+ class="textarea-element"
472
+ .value=${this.value}
473
+ .disabled=${this.disabled}
474
+ .readOnly=${this.readonly}
475
+ .required=${this.required || false}
476
+ .rows=${this.rows}
477
+ .cols=${this.cols}
478
+ .placeholder=${this.placeholder}
479
+ .autocomplete=${this.autocomplete}
480
+ .name=${this.name || ''}
481
+ maxlength=${this.maxLength || ''}
482
+ style="resize: ${this.resize}"
483
+ @input=${this.handleInput}
484
+ @focus=${this.handleFocus}
485
+ @blur=${this.handleBlur}
486
+ ></textarea>
487
+ `;
488
+ }
489
+ renderValidationIcon() {
490
+ if (!this.hasFeedback || !this.validationResult)
491
+ return '';
492
+ const iconName = this.validationResult.level === 'error' ? 'error' :
493
+ this.validationResult.level === 'warning' ? 'warning' : 'check-circle';
494
+ return html `
495
+ <nr-icon
496
+ class="validation-icon ${this.validationResult.level}"
497
+ name="${iconName}"
498
+ size="small"
499
+ ></nr-icon>
500
+ `;
501
+ }
502
+ renderClearButton() {
503
+ if (!this.allowClear || !this.value || this.disabled || this.readonly)
504
+ return '';
505
+ return html `
506
+ <button
507
+ class="clear-button"
508
+ type="button"
509
+ @click=${this.handleClear}
510
+ aria-label="Clear textarea"
511
+ >
512
+ <nr-icon name="x" size="small"></nr-icon>
513
+ </button>
514
+ `;
515
+ }
516
+ renderCharacterCount() {
517
+ if (!this.showCount)
518
+ return '';
519
+ const maxText = this.maxLength ? ` / ${this.maxLength}` : '';
520
+ const isOverLimit = this.maxLength && this.characterCount > this.maxLength;
521
+ return html `
522
+ <div class="character-count ${isOverLimit ? 'over-limit' : ''}">
523
+ ${this.characterCount}${maxText}
524
+ </div>
525
+ `;
526
+ }
527
+ renderHelperText() {
528
+ var _a, _b;
529
+ const hasHelperSlot = (_a = this.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelector('slot[name="helper-text"]');
530
+ const hasHelperSlotContent = hasHelperSlot === null || hasHelperSlot === void 0 ? void 0 : hasHelperSlot.assignedNodes().length;
531
+ const hasValidationMessages = (_b = this.validationResult) === null || _b === void 0 ? void 0 : _b.messages.length;
532
+ if (!hasHelperSlotContent && !hasValidationMessages)
533
+ return '';
534
+ return html `
535
+ <div class="helper-text">
536
+ ${hasValidationMessages ?
537
+ this.validationResult.messages.map(msg => html `<div class="validation-message ${this.validationResult.level}">${msg}</div>`) :
538
+ html `<slot name="helper-text"></slot>`}
539
+ </div>
540
+ `;
541
+ }
542
+ render() {
543
+ const classes = [
544
+ 'textarea-container',
545
+ `size-${this.size}`,
546
+ `variant-${this.variant}`,
547
+ `state-${this.state}`,
548
+ this.isFocused ? 'focused' : '',
549
+ this.disabled ? 'disabled' : '',
550
+ this.readonly ? 'readonly' : '',
551
+ this.validationResult ? `validation-${this.validationResult.level}` : ''
552
+ ].filter(Boolean).join(' ');
553
+ return html `
554
+ <div class="${classes}">
555
+ ${this.renderLabel()}
556
+
557
+ <div class="textarea-wrapper">
558
+ <div class="addon-before">
559
+ <slot name="addon-before"></slot>
560
+ </div>
561
+
562
+ <div class="textarea-input-container">
563
+ ${this.renderTextarea()}
564
+ ${this.renderValidationIcon()}
565
+ ${this.renderClearButton()}
566
+ </div>
567
+
568
+ <div class="addon-after">
569
+ <slot name="addon-after"></slot>
570
+ </div>
571
+ </div>
572
+
573
+ <div class="textarea-footer">
574
+ ${this.renderHelperText()}
575
+ ${this.renderCharacterCount()}
576
+ </div>
577
+ </div>
578
+ `;
579
+ }
580
+ };
581
+ NrTextareaElement.styles = styles;
582
+ __decorate([
583
+ query('textarea')
584
+ ], NrTextareaElement.prototype, "textareaElement", void 0);
585
+ __decorate([
586
+ property({ type: Boolean, reflect: true })
587
+ ], NrTextareaElement.prototype, "disabled", void 0);
588
+ __decorate([
589
+ property({ type: Boolean, reflect: true })
590
+ ], NrTextareaElement.prototype, "readonly", void 0);
591
+ __decorate([
592
+ property({ type: String, reflect: true })
593
+ ], NrTextareaElement.prototype, "state", void 0);
594
+ __decorate([
595
+ property({ type: String })
596
+ ], NrTextareaElement.prototype, "value", void 0);
597
+ __decorate([
598
+ property({ type: String })
599
+ ], NrTextareaElement.prototype, "size", void 0);
600
+ __decorate([
601
+ property({ type: String, reflect: true })
602
+ ], NrTextareaElement.prototype, "variant", void 0);
603
+ __decorate([
604
+ property({ type: String })
605
+ ], NrTextareaElement.prototype, "resize", void 0);
606
+ __decorate([
607
+ property({ type: Number })
608
+ ], NrTextareaElement.prototype, "rows", void 0);
609
+ __decorate([
610
+ property({ type: Number })
611
+ ], NrTextareaElement.prototype, "cols", void 0);
612
+ __decorate([
613
+ property({ type: String })
614
+ ], NrTextareaElement.prototype, "placeholder", void 0);
615
+ __decorate([
616
+ property({ type: String })
617
+ ], NrTextareaElement.prototype, "autocomplete", void 0);
618
+ __decorate([
619
+ property({ type: String })
620
+ ], NrTextareaElement.prototype, "name", void 0);
621
+ __decorate([
622
+ property({ type: Boolean })
623
+ ], NrTextareaElement.prototype, "required", void 0);
624
+ __decorate([
625
+ property({ type: Boolean, reflect: true })
626
+ ], NrTextareaElement.prototype, "allowClear", void 0);
627
+ __decorate([
628
+ property({ type: Boolean, reflect: true })
629
+ ], NrTextareaElement.prototype, "showCount", void 0);
630
+ __decorate([
631
+ property({ type: Number })
632
+ ], NrTextareaElement.prototype, "maxLength", void 0);
633
+ __decorate([
634
+ property({ type: Number })
635
+ ], NrTextareaElement.prototype, "minHeight", void 0);
636
+ __decorate([
637
+ property({ type: Number })
638
+ ], NrTextareaElement.prototype, "maxHeight", void 0);
639
+ __decorate([
640
+ property({ type: Boolean })
641
+ ], NrTextareaElement.prototype, "autoResize", void 0);
642
+ __decorate([
643
+ property({ type: Array })
644
+ ], NrTextareaElement.prototype, "rules", void 0);
645
+ __decorate([
646
+ property({ type: Boolean, attribute: 'validate-on-change' })
647
+ ], NrTextareaElement.prototype, "validateOnChange", void 0);
648
+ __decorate([
649
+ property({ type: Boolean, attribute: 'validate-on-blur' })
650
+ ], NrTextareaElement.prototype, "validateOnBlur", void 0);
651
+ __decorate([
652
+ property({ type: Boolean, attribute: 'has-feedback' })
653
+ ], NrTextareaElement.prototype, "hasFeedback", void 0);
654
+ __decorate([
655
+ property({ type: String, attribute: 'validation-message' })
656
+ ], NrTextareaElement.prototype, "validationMessage", void 0);
657
+ __decorate([
658
+ state()
659
+ ], NrTextareaElement.prototype, "isFocused", void 0);
660
+ __decorate([
661
+ state()
662
+ ], NrTextareaElement.prototype, "validationResult", void 0);
663
+ __decorate([
664
+ state()
665
+ ], NrTextareaElement.prototype, "characterCount", void 0);
666
+ NrTextareaElement = __decorate([
667
+ customElement('nr-textarea')
668
+ ], NrTextareaElement);
669
+ export { NrTextareaElement };
670
+ //# sourceMappingURL=textarea.component.js.map