@nysds/nys-textarea 1.12.0 → 1.13.1

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.
@@ -1,11 +1,11 @@
1
1
  import { LitElement as y, unsafeCSS as u, html as p } from "lit";
2
2
  import { property as a } from "lit/decorators.js";
3
3
  import { ifDefined as o } from "lit/directives/if-defined.js";
4
- const v = ':host{--_nys-textarea-width: 100%;--_nys-textarea-border-radius: var(--nys-radius-md, 4px);--_nys-textarea-border-width: var(--nys-border-width-sm, 1px);--_nys-textarea-border-color: var(--nys-color-neutral-400, #909395);--_nys-textarea-padding: var(--nys-space-100, 8px);--_nys-textarea-gap: var(--nys-space-50, 4px);--_nys-textarea-color: var(--nys-color-ink, #1b1b1b);--_nys-textarea-color--placeholder: var( --nys-color-text-weaker, var(--nys-color-neutral-500, #797c7f) );--_nys-textarea-outline-color--hover: var(--nys-color-neutral-900, #1b1b1b);--_nys-textarea-outline-width: var(--nys-border-width-sm, 1px);--_nys-textarea-outline-color--focus: var(--nys-color-focus, #004dd1);--_nys-textarea-background-color--disabled: var( --nys-color-neutral-10, #f6f6f6 );--_nys-textarea-border-color--disabled: var( --nys-color-neutral-200, #bec0c1 );--_nys-textarea-color--disabled: var( --nys-color-text-disabled, var(--nys-color-neutral-200, #bec0c1) );--_nys-textarea-font-family: var( --nys-font-family-ui, var( --nys-font-family-sans, "Proxima Nova", "Helvetica Neue", "Helvetica", "Arial", sans-serif ) );--_nys-textarea-font-size: var(--nys-font-size-ui-md, 16px);--_nys-textarea-font-weight: var(--nys-font-weight-regular, 400);--_nys-textarea-line-height: var(--nys-font-lineheight-ui-md, 24px);--nys-textarea-letterspacing-ui: var( --nys-font-letterspacing-ui-md, var(--nys-font-letterspacing-400, .044px) )}:host([width=sm]){--_nys-textarea-width: var(--nys-form-width-sm, 88px)}:host([width=md]){--_nys-textarea-width: var(--nys-form-width-md, 200px)}:host([width=lg]){--_nys-textarea-width: var(--nys-form-width-lg, 384px)}:host([width=full]){--_nys-textarea-width: 100%;flex:1}:host([showError]){--_nys-textarea-border-color: var(--nys-color-danger, #b52c2c)}.nys-textarea{font-weight:var(--_nys-textarea-font-weight);font-family:var(--_nys-textarea-font-family);line-height:var(--_nys-textarea-line-height);letter-spacing:var(--nys-textarea-letterspacing-ui);color:var(--_nys-textarea-color);gap:var(--_nys-textarea-gap);display:flex;flex-direction:column}.nys-textarea__textarea{color:var(--_nys-textarea-color);font-size:var(--_nys-textarea-font-size);font-family:var(--_nys-textarea-font-family);border-radius:var(--_nys-textarea-border-radius);border:solid var(--_nys-textarea-border-color) var(--_nys-textarea-border-width);padding:var(--_nys-textarea-padding);width:var(--_nys-textarea-width);line-height:var(--_nys-textarea-line-height);max-width:var(--_nys-textarea-width);box-sizing:border-box;-webkit-box-sizing:border-box;-moz-box-sizing:border-box}.nys-textarea__textarea::placeholder{color:var(--_nys-textarea-color--placeholder)}.nys-textarea__textarea.none{resize:none}.nys-textarea__textarea:hover:not(:disabled):not(:focus){outline:solid var(--_nys-textarea-outline-width) var(--_nys-textarea-outline-color--hover);border-color:var(--_nys-textarea-outline-color--hover)}.nys-textarea__textarea:focus{outline:solid var(--_nys-textarea-outline-width) var(--_nys-textarea-outline-color--focus);border-color:var(--_nys-textarea-outline-color--focus);caret-color:var(--_nys-textarea-outline-color--focus)}.nys-textarea__textarea:disabled,.nys-textarea__textarea:disabled::placeholder{background-color:var(--_nys-textarea-background-color--disabled);border-color:var(--_nys-textarea-border-color--disabled);color:var(--_nys-textarea-color--disabled);cursor:not-allowed}';
5
- var f = Object.defineProperty, s = (c, e, r, l) => {
4
+ const v = ':host{--_nys-textarea-width: 100%;--_nys-textarea-border-radius: var(--nys-radius-md, 4px);--_nys-textarea-border-width: var(--nys-border-width-sm, 1px);--_nys-textarea-border-color: var(--nys-color-neutral-400, #909395);--_nys-textarea-padding: var(--nys-space-200, 16px);--_nys-textarea-gap: var(--nys-space-50, 4px);--_nys-textarea-color: var(--nys-color-ink, #1b1b1b);--_nys-textarea-color--placeholder: var(--nys-color-text-weaker, var(--nys-color-neutral-500, #797c7f));--_nys-textarea-outline-color--hover: var(--nys-color-neutral-900, #1b1b1b);--_nys-textarea-outline-width: var(--nys-border-width-sm, 1px);--_nys-textarea-outline-color--focus: var(--nys-color-focus, #004dd1);--_nys-textarea-background-color--disabled: var(--nys-color-neutral-10, #f6f6f6);--_nys-textarea-border-color--disabled: var(--nys-color-neutral-200, #bec0c1);--_nys-textarea-color--disabled: var(--nys-color-text-disabled, var(--nys-color-neutral-200, #bec0c1));--_nys-textarea-font-family: var(--nys-font-family-ui, var(--nys-font-family-sans, "Proxima Nova", "Helvetica Neue", "Helvetica", "Arial", sans-serif));--_nys-textarea-font-size: var(--nys-font-size-ui-md, 16px);--_nys-textarea-font-weight: var(--nys-font-weight-regular, 400);--_nys-textarea-line-height: var(--nys-font-lineheight-ui-md, 24px);--nys-textarea-letterspacing-ui: var(--nys-font-letterspacing-ui-md, var(--nys-font-letterspacing-400, .044px))}:host([width=sm]){--_nys-textarea-width: var(--nys-form-width-sm, 88px)}:host([width=md]){--_nys-textarea-width: var(--nys-form-width-md, 200px)}:host([width=lg]){--_nys-textarea-width: var(--nys-form-width-lg, 384px)}:host([width=full]){--_nys-textarea-width: 100%;flex:1}:host([showError]){--_nys-textarea-border-color: var(--nys-color-danger, #b52c2c)}.nys-textarea{font-weight:var(--_nys-textarea-font-weight);font-family:var(--_nys-textarea-font-family);line-height:var(--_nys-textarea-line-height);letter-spacing:var(--nys-textarea-letterspacing-ui);color:var(--_nys-textarea-color);gap:var(--_nys-textarea-gap);display:flex;flex-direction:column}.nys-textarea__textarea{color:var(--_nys-textarea-color);font-size:var(--_nys-textarea-font-size);font-family:var(--_nys-textarea-font-family);border-radius:var(--_nys-textarea-border-radius);border:solid var(--_nys-textarea-border-color) var(--_nys-textarea-border-width);padding:var(--_nys-textarea-padding);width:var(--_nys-textarea-width);line-height:var(--_nys-textarea-line-height);max-width:var(--_nys-textarea-width);box-sizing:border-box;-webkit-box-sizing:border-box;-moz-box-sizing:border-box}.nys-textarea__textarea::placeholder{color:var(--_nys-textarea-color--placeholder)}.nys-textarea__textarea.none{resize:none}.nys-textarea__textarea:hover:not(:disabled):not(:focus):not([readonly]){outline:solid var(--_nys-textarea-outline-width) var(--_nys-textarea-outline-color--hover);border-color:var(--_nys-textarea-outline-color--hover)}.nys-textarea__textarea:focus:not([readonly]){outline:solid var(--_nys-textarea-outline-width) var(--_nys-textarea-outline-color--focus);border-color:var(--_nys-textarea-outline-color--focus);caret-color:var(--_nys-textarea-outline-color--focus)}.nys-textarea__textarea:disabled,.nys-textarea__textarea:disabled::placeholder{background-color:var(--_nys-textarea-background-color--disabled);border-color:var(--_nys-textarea-border-color--disabled);color:var(--_nys-textarea-color--disabled);cursor:not-allowed}';
5
+ var f = Object.defineProperty, s = (c, e, t, l) => {
6
6
  for (var i = void 0, d = c.length - 1, n; d >= 0; d--)
7
- (n = c[d]) && (i = n(e, r, i) || i);
8
- return i && f(e, r, i), i;
7
+ (n = c[d]) && (i = n(e, t, i) || i);
8
+ return i && f(e, t, i), i;
9
9
  };
10
10
  let x = 0;
11
11
  const h = class h extends y {
@@ -14,7 +14,10 @@ const h = class h extends y {
14
14
  super(), this.id = "", this.name = "", this.label = "", this.description = "", this.placeholder = "", this.value = "", this.disabled = !1, this.readonly = !1, this.required = !1, this.optional = !1, this.tooltip = "", this.inverted = !1, this.form = null, this.maxlength = null, this.width = "full", this.rows = 4, this.resize = "vertical", this.showError = !1, this.errorMessage = "", this._hasUserInteracted = !1, this._internals = this.attachInternals();
15
15
  }
16
16
  async updated(e) {
17
- await Promise.resolve(), e.has("rows") && (this.rows = this.rows ?? 4);
17
+ if (await Promise.resolve(), e.has("rows") && (this.rows = this.rows ?? 4), e.has("readonly") || e.has("required")) {
18
+ const t = this.shadowRoot?.querySelector("textarea");
19
+ t && (t.required = this.required && !this.readonly);
20
+ }
18
21
  }
19
22
  // Generate a unique ID if one is not provided
20
23
  connectedCallback() {
@@ -26,35 +29,43 @@ const h = class h extends y {
26
29
  firstUpdated() {
27
30
  this._setValue();
28
31
  }
29
- // This callback is automatically called when the parent form is reset.
30
- formResetCallback() {
31
- this.value = "";
32
- }
33
- // Form Integration
32
+ /**
33
+ * Form Integration
34
+ * --------------------------------------------------------------------------
35
+ */
34
36
  _setValue() {
35
37
  this._internals.setFormValue(this.value), this._manageRequire();
36
38
  }
37
39
  _manageRequire() {
38
40
  const e = this.shadowRoot?.querySelector("textarea");
39
41
  if (!e) return;
40
- const r = this.errorMessage || "This field is required";
41
- this.required && !this.value ? (this._internals.ariaRequired = "true", this._internals.setValidity({ valueMissing: !0 }, r, e)) : (this._internals.ariaRequired = "false", this._internals.setValidity({}), this._hasUserInteracted = !1);
42
+ const t = this.errorMessage || "This field is required";
43
+ this.required && !this.value ? (this._internals.ariaRequired = "true", this._internals.setValidity({ valueMissing: !0 }, t, e)) : (this._internals.ariaRequired = "false", this._internals.setValidity({}), this._hasUserInteracted = !1);
42
44
  }
43
45
  _setValidityMessage(e = "") {
44
- const r = this.shadowRoot?.querySelector("textarea");
45
- r && (this.showError = !!e, this.errorMessage?.trim() && e !== "" && (e = this.errorMessage), this._internals.setValidity(
46
+ const t = this.shadowRoot?.querySelector("textarea");
47
+ t && (this.showError = !!e, this.errorMessage?.trim() && e !== "" && (e = this.errorMessage), this._internals.setValidity(
46
48
  e ? { customError: !0 } : {},
47
49
  e,
48
- r
50
+ t
49
51
  ));
50
52
  }
51
53
  _validate() {
52
54
  const e = this.shadowRoot?.querySelector("textarea");
53
55
  if (!e) return;
54
- let r = e.validationMessage;
55
- this._setValidityMessage(r);
56
+ let t = e.validationMessage;
57
+ this._setValidityMessage(t);
56
58
  }
57
- // Functions
59
+ // This callback is automatically called when the parent form is reset.
60
+ formResetCallback() {
61
+ this.value = "";
62
+ const e = this.shadowRoot?.querySelector("textarea");
63
+ e && (e.value = "", e.setAttribute("aria-invalid", "false")), this.showError = !1, this._internals.setValidity({}), this.requestUpdate();
64
+ }
65
+ /**
66
+ * Functions
67
+ * --------------------------------------------------------------------------
68
+ */
58
69
  // This helper function is called to perform the element's native validation.
59
70
  checkValidity() {
60
71
  const e = this.shadowRoot?.querySelector("textarea");
@@ -62,19 +73,22 @@ const h = class h extends y {
62
73
  }
63
74
  _handleInvalid(e) {
64
75
  e.preventDefault(), this._hasUserInteracted = !0, this._validate();
65
- const r = this.shadowRoot?.querySelector("textarea");
66
- if (r) {
76
+ const t = this.shadowRoot?.querySelector("textarea");
77
+ if (t) {
67
78
  const l = this._internals.form;
68
79
  l ? Array.from(l.elements).find(
69
80
  (n) => typeof n.checkValidity == "function" && !n.checkValidity()
70
- ) === this && r.focus() : r.focus();
81
+ ) === this && t.focus() : t.focus();
71
82
  }
72
83
  }
73
- // Event Handlers
84
+ /**
85
+ * Event Handlers
86
+ * --------------------------------------------------------------------------
87
+ */
74
88
  // Handle input event to check pattern validity
75
89
  _handleInput(e) {
76
- const r = e.target;
77
- this.value = r.value, this._internals.setFormValue(this.value), this._hasUserInteracted && this._validate(), this.dispatchEvent(
90
+ const t = e.target;
91
+ this.value = t.value, this._internals.setFormValue(this.value), this._hasUserInteracted && this._validate(), this.dispatchEvent(
78
92
  new CustomEvent("nys-input", {
79
93
  detail: { id: this.id, value: this.value },
80
94
  bubbles: !0,
@@ -91,18 +105,18 @@ const h = class h extends y {
91
105
  this._hasUserInteracted || (this._hasUserInteracted = !0), this._validate(), this.dispatchEvent(new Event("nys-blur"));
92
106
  }
93
107
  _handleSelect(e) {
94
- const r = e.target;
95
- this.value = r.value, this.dispatchEvent(
108
+ const t = e.target;
109
+ this.value = t.value, this.dispatchEvent(
96
110
  new CustomEvent("nys-select", {
97
- detail: { value: this.value },
111
+ detail: { id: this.id, value: this.value },
98
112
  bubbles: !0,
99
113
  composed: !0
100
114
  })
101
115
  );
102
116
  }
103
117
  _handleSelectionChange(e) {
104
- const r = e.target;
105
- this.value = r.value, this.dispatchEvent(
118
+ const t = e.target;
119
+ this.value = t.value, this.dispatchEvent(
106
120
  new CustomEvent("nys-selectionchange", {
107
121
  detail: { id: this.id, value: this.value },
108
122
  bubbles: !0,
@@ -117,7 +131,7 @@ const h = class h extends y {
117
131
  for=${this.id + "--native"}
118
132
  label=${this.label}
119
133
  description=${this.description}
120
- flag=${this.required ? "required" : this.optional ? "optional" : ""}
134
+ flag=${this.required && !this.readonly ? "required" : this.optional ? "optional" : ""}
121
135
  tooltip=${this.tooltip}
122
136
  ?inverted=${this.inverted}
123
137
  >
@@ -129,7 +143,7 @@ const h = class h extends y {
129
143
  id=${this.id + "--native"}
130
144
  .value=${this.value}
131
145
  ?disabled=${this.disabled}
132
- ?required=${this.required}
146
+ ?required=${this.required && !this.readonly}
133
147
  ?readonly=${this.readonly}
134
148
  aria-disabled=${o(this.disabled ? "true" : void 0)}
135
149
  aria-required=${o(this.required ? "true" : void 0)}
@@ -156,66 +170,66 @@ const h = class h extends y {
156
170
  }
157
171
  };
158
172
  h.styles = u(v), h.formAssociated = !0;
159
- let t = h;
173
+ let r = h;
160
174
  s([
161
175
  a({ type: String, reflect: !0 })
162
- ], t.prototype, "id");
176
+ ], r.prototype, "id");
163
177
  s([
164
178
  a({ type: String, reflect: !0 })
165
- ], t.prototype, "name");
179
+ ], r.prototype, "name");
166
180
  s([
167
181
  a({ type: String })
168
- ], t.prototype, "label");
182
+ ], r.prototype, "label");
169
183
  s([
170
184
  a({ type: String })
171
- ], t.prototype, "description");
185
+ ], r.prototype, "description");
172
186
  s([
173
187
  a({ type: String })
174
- ], t.prototype, "placeholder");
188
+ ], r.prototype, "placeholder");
175
189
  s([
176
190
  a({ type: String })
177
- ], t.prototype, "value");
191
+ ], r.prototype, "value");
178
192
  s([
179
193
  a({ type: Boolean, reflect: !0 })
180
- ], t.prototype, "disabled");
194
+ ], r.prototype, "disabled");
181
195
  s([
182
196
  a({ type: Boolean, reflect: !0 })
183
- ], t.prototype, "readonly");
197
+ ], r.prototype, "readonly");
184
198
  s([
185
199
  a({ type: Boolean, reflect: !0 })
186
- ], t.prototype, "required");
200
+ ], r.prototype, "required");
187
201
  s([
188
202
  a({ type: Boolean, reflect: !0 })
189
- ], t.prototype, "optional");
203
+ ], r.prototype, "optional");
190
204
  s([
191
205
  a({ type: String })
192
- ], t.prototype, "tooltip");
206
+ ], r.prototype, "tooltip");
193
207
  s([
194
208
  a({ type: Boolean, reflect: !0 })
195
- ], t.prototype, "inverted");
209
+ ], r.prototype, "inverted");
196
210
  s([
197
211
  a({ type: String, reflect: !0 })
198
- ], t.prototype, "form");
212
+ ], r.prototype, "form");
199
213
  s([
200
214
  a({ type: Number })
201
- ], t.prototype, "maxlength");
215
+ ], r.prototype, "maxlength");
202
216
  s([
203
217
  a({ type: String, reflect: !0 })
204
- ], t.prototype, "width");
218
+ ], r.prototype, "width");
205
219
  s([
206
220
  a({ type: Number })
207
- ], t.prototype, "rows");
221
+ ], r.prototype, "rows");
208
222
  s([
209
223
  a({ type: String, reflect: !0 })
210
- ], t.prototype, "resize");
224
+ ], r.prototype, "resize");
211
225
  s([
212
226
  a({ type: Boolean, reflect: !0 })
213
- ], t.prototype, "showError");
227
+ ], r.prototype, "showError");
214
228
  s([
215
229
  a({ type: String })
216
- ], t.prototype, "errorMessage");
217
- customElements.get("nys-textarea") || customElements.define("nys-textarea", t);
230
+ ], r.prototype, "errorMessage");
231
+ customElements.get("nys-textarea") || customElements.define("nys-textarea", r);
218
232
  export {
219
- t as NysTextarea
233
+ r as NysTextarea
220
234
  };
221
235
  //# sourceMappingURL=nys-textarea.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"nys-textarea.js","sources":["../src/nys-textarea.ts"],"sourcesContent":["import { LitElement, html, unsafeCSS } from \"lit\";\nimport { property } from \"lit/decorators.js\";\nimport { ifDefined } from \"lit/directives/if-defined.js\";\n// @ts-ignore: SCSS module imported via bundler as inline\nimport styles from \"./nys-textarea.scss?inline\";\n\nlet textareaIdCounter = 0; // Counter for generating unique IDs\n\nexport class NysTextarea extends LitElement {\n static styles = unsafeCSS(styles);\n\n @property({ type: String, reflect: true }) id = \"\";\n @property({ type: String, reflect: true }) name = \"\";\n @property({ type: String }) label = \"\";\n @property({ type: String }) description = \"\";\n @property({ type: String }) placeholder = \"\";\n @property({ type: String }) value = \"\";\n @property({ type: Boolean, reflect: true }) disabled = false;\n @property({ type: Boolean, reflect: true }) readonly = false;\n @property({ type: Boolean, reflect: true }) required = false;\n @property({ type: Boolean, reflect: true }) optional = false;\n @property({ type: String }) tooltip = \"\";\n @property({ type: Boolean, reflect: true }) inverted = false;\n @property({ type: String, reflect: true }) form: string | null = null;\n @property({ type: Number }) maxlength: number | null = null;\n @property({ type: String, reflect: true }) width:\n | \"sm\"\n | \"md\"\n | \"lg\"\n | \"full\" = \"full\";\n @property({ type: Number }) rows = 4;\n @property({ type: String, reflect: true }) resize: \"vertical\" | \"none\" =\n \"vertical\";\n @property({ type: Boolean, reflect: true }) showError = false;\n @property({ type: String }) errorMessage = \"\";\n\n async updated(changedProperties: Map<string | number | symbol, unknown>) {\n await Promise.resolve();\n if (changedProperties.has(\"rows\")) {\n this.rows = this.rows ?? 4;\n }\n }\n\n private _hasUserInteracted = false; // need this flag for \"eager mode\"\n private _internals: ElementInternals;\n\n // Lifecycle updates\n static formAssociated = true; // allows use of elementInternals' API\n\n constructor() {\n super();\n this._internals = this.attachInternals();\n }\n\n // Generate a unique ID if one is not provided\n connectedCallback() {\n super.connectedCallback();\n if (!this.id) {\n this.id = `nys-textarea-${Date.now()}-${textareaIdCounter++}`;\n }\n this.addEventListener(\"invalid\", this._handleInvalid);\n }\n\n disconnectedCallback() {\n super.disconnectedCallback();\n this.removeEventListener(\"invalid\", this._handleInvalid);\n }\n\n firstUpdated() {\n // This ensures our element always participates in the form\n this._setValue();\n }\n\n // This callback is automatically called when the parent form is reset.\n formResetCallback() {\n this.value = \"\";\n }\n\n // Form Integration\n private _setValue() {\n this._internals.setFormValue(this.value);\n this._manageRequire();\n }\n\n private _manageRequire() {\n const textarea = this.shadowRoot?.querySelector(\"textarea\");\n\n if (!textarea) return;\n\n const message = this.errorMessage || \"This field is required\";\n const isInvalid = this.required && !this.value;\n\n if (isInvalid) {\n this._internals.ariaRequired = \"true\";\n this._internals.setValidity({ valueMissing: true }, message, textarea);\n } else {\n this._internals.ariaRequired = \"false\"; // Reset when valid\n this._internals.setValidity({});\n this._hasUserInteracted = false; // Reset lazy validation when valid\n }\n }\n\n private _setValidityMessage(message: string = \"\") {\n const textarea = this.shadowRoot?.querySelector(\"textarea\");\n if (!textarea) return;\n\n // Toggle the HTML <div> tag error message\n this.showError = !!message;\n // If user sets errorMessage, this will always override the native validation message\n if (this.errorMessage?.trim() && message !== \"\") {\n message = this.errorMessage;\n }\n\n this._internals.setValidity(\n message ? { customError: true } : {},\n message,\n textarea,\n );\n }\n\n private _validate() {\n const textarea = this.shadowRoot?.querySelector(\"textarea\");\n if (!textarea) return;\n\n // Get the native validation state\n let message = textarea.validationMessage;\n\n this._setValidityMessage(message);\n }\n\n // Functions\n // This helper function is called to perform the element's native validation.\n checkValidity(): boolean {\n const textarea = this.shadowRoot?.querySelector(\"textarea\");\n return textarea ? textarea.checkValidity() : true;\n }\n\n private _handleInvalid(event: Event) {\n event.preventDefault();\n this._hasUserInteracted = true; // Start aggressive mode due to form submission\n this._validate();\n\n const textarea = this.shadowRoot?.querySelector(\"textarea\");\n if (textarea) {\n // Focus only if this is the first invalid element (top-down approach)\n const form = this._internals.form;\n if (form) {\n const elements = Array.from(form.elements) as Array<\n HTMLElement & { checkValidity?: () => boolean }\n >;\n // Find the first element in the form that is invalid\n const firstInvalidElement = elements.find(\n (element) =>\n typeof element.checkValidity === \"function\" &&\n !element.checkValidity(),\n );\n if (firstInvalidElement === this) {\n textarea.focus();\n }\n } else {\n // If not part of a form, simply focus.\n textarea.focus();\n }\n }\n }\n\n // Event Handlers\n // Handle input event to check pattern validity\n private _handleInput(event: Event) {\n const textarea = event.target as HTMLInputElement;\n this.value = textarea.value;\n this._internals.setFormValue(this.value);\n\n // Field is invalid after unfocused, validate aggressively on each input (e.g. Eager mode: a combination of aggressive and lazy.)\n if (this._hasUserInteracted) {\n this._validate();\n }\n\n this.dispatchEvent(\n new CustomEvent(\"nys-input\", {\n detail: { id: this.id, value: this.value },\n bubbles: true,\n composed: true,\n }),\n );\n }\n\n // Handle focus event\n private _handleFocus() {\n this.dispatchEvent(new Event(\"nys-focus\"));\n }\n\n // Handle blur event\n private _handleBlur() {\n if (!this._hasUserInteracted) {\n this._hasUserInteracted = true; // At initial unfocus: if textarea is invalid, start aggressive mode\n }\n\n this._validate();\n this.dispatchEvent(new Event(\"nys-blur\"));\n }\n\n private _handleSelect(e: Event) {\n const select = e.target as HTMLSelectElement;\n this.value = select.value;\n this.dispatchEvent(\n new CustomEvent(\"nys-select\", {\n detail: { value: this.value },\n bubbles: true,\n composed: true,\n }),\n );\n }\n\n private _handleSelectionChange(e: Event) {\n const select = e.target as HTMLSelectElement;\n this.value = select.value;\n this.dispatchEvent(\n new CustomEvent(\"nys-selectionchange\", {\n detail: { id: this.id, value: this.value },\n bubbles: true,\n composed: true,\n }),\n );\n }\n\n render() {\n return html`\n <label class=\"nys-textarea\">\n <nys-label\n for=${this.id + \"--native\"}\n label=${this.label}\n description=${this.description}\n flag=${this.required ? \"required\" : this.optional ? \"optional\" : \"\"}\n tooltip=${this.tooltip}\n ?inverted=${this.inverted}\n >\n <slot name=\"description\" slot=\"description\">${this.description}</slot>\n </nys-label>\n <textarea\n class=\"nys-textarea__textarea ${this.resize}\"\n name=${this.name}\n id=${this.id + \"--native\"}\n .value=${this.value}\n ?disabled=${this.disabled}\n ?required=${this.required}\n ?readonly=${this.readonly}\n aria-disabled=${ifDefined(this.disabled ? \"true\" : undefined)}\n aria-required=${ifDefined(this.required ? \"true\" : undefined)}\n aria-label=${ifDefined(this.label || undefined)}\n aria-description=${ifDefined(this.description || undefined)}\n placeholder=${ifDefined(\n this.placeholder ? this.placeholder : undefined,\n )}\n maxlength=${ifDefined(this.maxlength ?? undefined)}\n .rows=${this.rows}\n form=${ifDefined(this.form || undefined)}\n @input=${this._handleInput}\n @focus=\"${this._handleFocus}\"\n @blur=\"${this._handleBlur}\"\n @select=\"${this._handleSelect}\"\n @selectionchange=\"${this._handleSelectionChange}\"\n ></textarea>\n <nys-errormessage\n ?showError=${this.showError}\n errorMessage=${this._internals.validationMessage || this.errorMessage}\n ></nys-errormessage>\n </label>\n `;\n }\n}\n\nif (!customElements.get(\"nys-textarea\")) {\n customElements.define(\"nys-textarea\", NysTextarea);\n}\n"],"names":["textareaIdCounter","_NysTextarea","LitElement","changedProperties","textarea","message","event","form","element","select","html","ifDefined","unsafeCSS","styles","NysTextarea","__decorateClass","property"],"mappings":"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"}
1
+ {"version":3,"file":"nys-textarea.js","sources":["../src/nys-textarea.ts"],"sourcesContent":["import { LitElement, html, unsafeCSS } from \"lit\";\nimport { property } from \"lit/decorators.js\";\nimport { ifDefined } from \"lit/directives/if-defined.js\";\n// @ts-ignore: SCSS module imported via bundler as inline\nimport styles from \"./nys-textarea.scss?inline\";\n\nlet textareaIdCounter = 0;\n\n/**\n * A multi-line text input for collecting longer responses like comments, descriptions, or feedback.\n * Form-associated with validation support via ElementInternals.\n *\n * Use for detailed responses needing multiple lines. For single-line input, use `nys-textinput`.\n * For predefined options, use `nys-select`, `nys-radiobutton`, or `nys-checkbox`.\n *\n * @summary Multi-line text input for comments, descriptions, and feedback.\n * @element nys-textarea\n *\n * @slot description - Custom HTML description content below the label.\n *\n * @fires nys-input - Fired on input change. Detail: `{id, value}`.\n * @fires nys-focus - Fired when textarea gains focus.\n * @fires nys-blur - Fired when textarea loses focus. Triggers validation.\n * @fires nys-select - Fired when user selects text. Detail: `{id, value}`.\n *\n * @example Basic textarea\n * ```html\n * <nys-textarea label=\"Comments\" rows=\"4\"></nys-textarea>\n * ```\n *\n * @example Required with description\n * ```html\n * <nys-textarea label=\"Describe the incident\" description=\"Please provide details\" required></nys-textarea>\n * ```\n */\n\nexport class NysTextarea extends LitElement {\n static styles = unsafeCSS(styles);\n\n /** Unique identifier. Auto-generated if not provided. */\n @property({ type: String, reflect: true }) id = \"\";\n\n /** Name for form submission. */\n @property({ type: String, reflect: true }) name = \"\";\n\n /** Visible label text. Required for accessibility. */\n @property({ type: String }) label = \"\";\n\n /** Helper text below label. Use slot for custom HTML. */\n @property({ type: String }) description = \"\";\n\n /** Placeholder text. Don't use as label replacement. */\n @property({ type: String }) placeholder = \"\";\n\n /** Current textarea value. */\n @property({ type: String }) value = \"\";\n\n /** Prevents interaction. */\n @property({ type: Boolean, reflect: true }) disabled = false;\n\n /** Makes textarea read-only but focusable. */\n @property({ type: Boolean, reflect: true }) readonly = false;\n\n /** Marks as required. Shows \"Required\" flag and validates on blur. */\n @property({ type: Boolean, reflect: true }) required = false;\n\n /** Shows \"Optional\" flag. Use when most fields are required. */\n @property({ type: Boolean, reflect: true }) optional = false;\n\n /** Tooltip text shown on hover/focus of info icon. */\n @property({ type: String }) tooltip = \"\";\n\n /** Adjusts colors for dark backgrounds. */\n @property({ type: Boolean, reflect: true }) inverted = false;\n\n /** Form `id` to associate with when textarea is outside form element. */\n @property({ type: String, reflect: true }) form: string | null = null;\n\n /** Maximum character length. */\n @property({ type: Number }) maxlength: number | null = null;\n\n /**\n * Textarea width: `sm` (88px), `md` (200px), `lg` (384px), `full` (100%, default).\n * @default \"full\"\n */\n @property({ type: String, reflect: true }) width:\n | \"sm\"\n | \"md\"\n | \"lg\"\n | \"full\" = \"full\";\n\n /**\n * Visible height in lines.\n * @default 4\n */\n @property({ type: Number }) rows = 4;\n\n /**\n * Resize behavior: `vertical` (default, user can resize height), `none` (fixed size).\n * @default \"vertical\"\n */\n @property({ type: String, reflect: true }) resize: \"vertical\" | \"none\" =\n \"vertical\";\n\n /** Shows error message when true. Set by validation or manually. */\n @property({ type: Boolean, reflect: true }) showError = false;\n\n /** Error message text. Shown only when `showError` is true. */\n @property({ type: String }) errorMessage = \"\";\n\n async updated(changedProperties: Map<string | number | symbol, unknown>) {\n await Promise.resolve();\n if (changedProperties.has(\"rows\")) {\n this.rows = this.rows ?? 4;\n }\n if (\n changedProperties.has(\"readonly\") ||\n changedProperties.has(\"required\")\n ) {\n const input = this.shadowRoot?.querySelector(\"textarea\");\n\n if (input) input.required = this.required && !this.readonly;\n }\n }\n\n private _hasUserInteracted = false; // need this flag for \"eager mode\"\n private _internals: ElementInternals;\n\n /**\n * Lifecycle methods\n * --------------------------------------------------------------------------\n */\n\n static formAssociated = true; // allows use of elementInternals' API\n\n constructor() {\n super();\n this._internals = this.attachInternals();\n }\n\n // Generate a unique ID if one is not provided\n connectedCallback() {\n super.connectedCallback();\n if (!this.id) {\n this.id = `nys-textarea-${Date.now()}-${textareaIdCounter++}`;\n }\n this.addEventListener(\"invalid\", this._handleInvalid);\n }\n\n disconnectedCallback() {\n super.disconnectedCallback();\n this.removeEventListener(\"invalid\", this._handleInvalid);\n }\n\n firstUpdated() {\n // This ensures our element always participates in the form\n this._setValue();\n }\n\n /**\n * Form Integration\n * --------------------------------------------------------------------------\n */\n\n private _setValue() {\n this._internals.setFormValue(this.value);\n this._manageRequire();\n }\n\n private _manageRequire() {\n const textarea = this.shadowRoot?.querySelector(\"textarea\");\n\n if (!textarea) return;\n\n const message = this.errorMessage || \"This field is required\";\n const isInvalid = this.required && !this.value;\n\n if (isInvalid) {\n this._internals.ariaRequired = \"true\";\n this._internals.setValidity({ valueMissing: true }, message, textarea);\n } else {\n this._internals.ariaRequired = \"false\"; // Reset when valid\n this._internals.setValidity({});\n this._hasUserInteracted = false; // Reset lazy validation when valid\n }\n }\n\n private _setValidityMessage(message: string = \"\") {\n const textarea = this.shadowRoot?.querySelector(\"textarea\");\n if (!textarea) return;\n\n // Toggle the HTML <div> tag error message\n this.showError = !!message;\n // If user sets errorMessage, this will always override the native validation message\n if (this.errorMessage?.trim() && message !== \"\") {\n message = this.errorMessage;\n }\n\n this._internals.setValidity(\n message ? { customError: true } : {},\n message,\n textarea,\n );\n }\n\n private _validate() {\n const textarea = this.shadowRoot?.querySelector(\"textarea\");\n if (!textarea) return;\n\n // Get the native validation state\n let message = textarea.validationMessage;\n\n this._setValidityMessage(message);\n }\n\n // This callback is automatically called when the parent form is reset.\n public formResetCallback() {\n this.value = \"\";\n\n const textarea = this.shadowRoot?.querySelector(\"textarea\");\n if (textarea) {\n textarea.value = \"\";\n textarea.setAttribute(\"aria-invalid\", \"false\");\n }\n\n // Reset validation UI\n this.showError = false;\n this._internals.setValidity({});\n\n // Re-render UI\n this.requestUpdate();\n }\n\n /**\n * Functions\n * --------------------------------------------------------------------------\n */\n\n // This helper function is called to perform the element's native validation.\n checkValidity(): boolean {\n const textarea = this.shadowRoot?.querySelector(\"textarea\");\n return textarea ? textarea.checkValidity() : true;\n }\n\n private _handleInvalid(event: Event) {\n event.preventDefault();\n this._hasUserInteracted = true; // Start aggressive mode due to form submission\n this._validate();\n\n const textarea = this.shadowRoot?.querySelector(\"textarea\");\n if (textarea) {\n // Focus only if this is the first invalid element (top-down approach)\n const form = this._internals.form;\n if (form) {\n const elements = Array.from(form.elements) as Array<\n HTMLElement & { checkValidity?: () => boolean }\n >;\n // Find the first element in the form that is invalid\n const firstInvalidElement = elements.find(\n (element) =>\n typeof element.checkValidity === \"function\" &&\n !element.checkValidity(),\n );\n if (firstInvalidElement === this) {\n textarea.focus();\n }\n } else {\n // If not part of a form, simply focus.\n textarea.focus();\n }\n }\n }\n\n /**\n * Event Handlers\n * --------------------------------------------------------------------------\n */\n\n // Handle input event to check pattern validity\n private _handleInput(event: Event) {\n const textarea = event.target as HTMLInputElement;\n this.value = textarea.value;\n this._internals.setFormValue(this.value);\n\n // Field is invalid after unfocused, validate aggressively on each input (e.g. Eager mode: a combination of aggressive and lazy.)\n if (this._hasUserInteracted) {\n this._validate();\n }\n\n this.dispatchEvent(\n new CustomEvent(\"nys-input\", {\n detail: { id: this.id, value: this.value },\n bubbles: true,\n composed: true,\n }),\n );\n }\n\n // Handle focus event\n private _handleFocus() {\n this.dispatchEvent(new Event(\"nys-focus\"));\n }\n\n // Handle blur event\n private _handleBlur() {\n if (!this._hasUserInteracted) {\n this._hasUserInteracted = true; // At initial unfocus: if textarea is invalid, start aggressive mode\n }\n\n this._validate();\n this.dispatchEvent(new Event(\"nys-blur\"));\n }\n\n private _handleSelect(e: Event) {\n const select = e.target as HTMLSelectElement;\n this.value = select.value;\n this.dispatchEvent(\n new CustomEvent(\"nys-select\", {\n detail: { id: this.id, value: this.value },\n bubbles: true,\n composed: true,\n }),\n );\n }\n\n private _handleSelectionChange(e: Event) {\n const select = e.target as HTMLSelectElement;\n this.value = select.value;\n this.dispatchEvent(\n new CustomEvent(\"nys-selectionchange\", {\n detail: { id: this.id, value: this.value },\n bubbles: true,\n composed: true,\n }),\n );\n }\n\n render() {\n return html`\n <label class=\"nys-textarea\">\n <nys-label\n for=${this.id + \"--native\"}\n label=${this.label}\n description=${this.description}\n flag=${this.required && !this.readonly\n ? \"required\"\n : this.optional\n ? \"optional\"\n : \"\"}\n tooltip=${this.tooltip}\n ?inverted=${this.inverted}\n >\n <slot name=\"description\" slot=\"description\">${this.description}</slot>\n </nys-label>\n <textarea\n class=\"nys-textarea__textarea ${this.resize}\"\n name=${this.name}\n id=${this.id + \"--native\"}\n .value=${this.value}\n ?disabled=${this.disabled}\n ?required=${this.required && !this.readonly}\n ?readonly=${this.readonly}\n aria-disabled=${ifDefined(this.disabled ? \"true\" : undefined)}\n aria-required=${ifDefined(this.required ? \"true\" : undefined)}\n aria-label=${ifDefined(this.label || undefined)}\n aria-description=${ifDefined(this.description || undefined)}\n placeholder=${ifDefined(\n this.placeholder ? this.placeholder : undefined,\n )}\n maxlength=${ifDefined(this.maxlength ?? undefined)}\n .rows=${this.rows}\n form=${ifDefined(this.form || undefined)}\n @input=${this._handleInput}\n @focus=\"${this._handleFocus}\"\n @blur=\"${this._handleBlur}\"\n @select=\"${this._handleSelect}\"\n @selectionchange=\"${this._handleSelectionChange}\"\n ></textarea>\n <nys-errormessage\n ?showError=${this.showError}\n errorMessage=${this._internals.validationMessage || this.errorMessage}\n ></nys-errormessage>\n </label>\n `;\n }\n}\n\nif (!customElements.get(\"nys-textarea\")) {\n customElements.define(\"nys-textarea\", NysTextarea);\n}\n"],"names":["textareaIdCounter","_NysTextarea","LitElement","changedProperties","input","textarea","message","event","form","element","select","html","ifDefined","unsafeCSS","styles","NysTextarea","__decorateClass","property"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nysds/nys-textarea",
3
- "version": "1.12.0",
3
+ "version": "1.13.1",
4
4
  "description": "The Textarea component from the NYS Design System.",
5
5
  "module": "dist/nys-textarea.js",
6
6
  "types": "dist/index.d.ts",
@@ -23,9 +23,9 @@
23
23
  "lit-analyze": "lit-analyzer '**/*.ts'"
24
24
  },
25
25
  "dependencies": {
26
- "@nysds/nys-icon": "^1.12.0",
27
- "@nysds/nys-label": "^1.12.0",
28
- "@nysds/nys-errormessage": "^1.12.0"
26
+ "@nysds/nys-icon": "^1.13.1",
27
+ "@nysds/nys-label": "^1.13.1",
28
+ "@nysds/nys-errormessage": "^1.13.1"
29
29
  },
30
30
  "devDependencies": {
31
31
  "lit": "^3.3.1",