@justeattakeaway/pie-textarea 0.18.4 → 0.20.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.
package/README.md CHANGED
@@ -49,6 +49,7 @@ Ideally, you should install the component using the **`@justeattakeaway/pie-webc
49
49
  | `readonly` | `true`, `false` | When true, the user cannot edit the textarea. Not the same as disabled. See [MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/readonly). | `false` |
50
50
  | `required` | `true`, `false` | If true, textarea must have a value for valid form submission. Does not block form submission by itself. | `false` |
51
51
  | `resize` | `"auto"`, `"manual"` | Controls resizing behavior. `auto` resizes vertically as needed; `manual` allows user resizing but no auto resizing. | `"auto"` |
52
+ | `rows` | `number` | The number of visible text rows. Defaults to 2 when `resize` is `auto`, with a maximum of 6 rows. Can be set to 1 when `resize` is `manual` (no maximum height on desktop). On mobile, manual mode is fixed at 6 rows and cannot be resized. | `undefined` |
52
53
  | `size` | `"small"`, `"medium"`, `"large"` | Sets the visual size of the textarea. | `"medium"` |
53
54
  | `status` | `"default"`, `"error"`, `"success"` | Status of the component. If not `default`, `assistiveText` must be provided for accessibility. | `"default"` |
54
55
  | `value` | `string` | Value of the textarea (used in form key/value pairs). | `""` |
@@ -194,6 +194,15 @@
194
194
  "privacy": "public",
195
195
  "attribute": "maxlength"
196
196
  },
197
+ {
198
+ "kind": "field",
199
+ "name": "rows",
200
+ "type": {
201
+ "text": "TextareaProps['rows']"
202
+ },
203
+ "privacy": "public",
204
+ "attribute": "rows"
205
+ },
197
206
  {
198
207
  "kind": "field",
199
208
  "name": "_textarea",
@@ -403,6 +412,13 @@
403
412
  "text": "TextareaProps['maxlength']"
404
413
  },
405
414
  "fieldName": "maxlength"
415
+ },
416
+ {
417
+ "name": "rows",
418
+ "type": {
419
+ "text": "TextareaProps['rows']"
420
+ },
421
+ "fieldName": "rows"
406
422
  }
407
423
  ],
408
424
  "mixins": [
package/dist/index.d.ts CHANGED
@@ -11,7 +11,7 @@ import { TemplateResult } from 'lit-html';
11
11
  /**
12
12
  * The default values for the `TextareaProps` that are required (i.e. they have a fallback value in the component).
13
13
  */
14
- declare type DefaultProps = ComponentDefaultProps<TextareaProps, keyof Omit<TextareaProps, 'name' | 'autocomplete' | 'assistiveText' | 'defaultValue' | 'maxlength'>>;
14
+ declare type DefaultProps = ComponentDefaultProps<TextareaProps, keyof Omit<TextareaProps, 'name' | 'autocomplete' | 'assistiveText' | 'defaultValue' | 'maxlength' | 'rows'>>;
15
15
 
16
16
  /**
17
17
  * Default values for optional properties that have default fallback values in the component.
@@ -38,6 +38,7 @@ export declare class PieTextarea extends PieTextarea_base implements TextareaPro
38
38
  autocomplete: TextareaProps['autocomplete'];
39
39
  placeholder: TextareaProps['placeholder'];
40
40
  maxlength: TextareaProps['maxlength'];
41
+ rows: TextareaProps['rows'];
41
42
  private _textarea;
42
43
  focusTarget: HTMLElement;
43
44
  private _abortController;
@@ -152,6 +153,11 @@ export declare interface TextareaProps {
152
153
  * The maximum number of characters allowed in the textarea.
153
154
  */
154
155
  maxlength?: number;
156
+ /**
157
+ * The number of visible text rows. Defaults to 2 when resize is auto, with a maximum of 6 rows.
158
+ * Can be set to 1 when resize is manual (no maximum height on desktop). On mobile, manual mode is fixed at 6 rows and cannot be resized.
159
+ */
160
+ rows?: number;
155
161
  }
156
162
 
157
163
  export { }
package/dist/index.js CHANGED
@@ -1,114 +1,114 @@
1
- import { LitElement as de, nothing as ce, html as Q, unsafeCSS as ue } from "lit";
2
- import { property as l, query as Z } from "lit/decorators.js";
3
- import { classMap as pe } from "lit/directives/class-map.js";
4
- import { ifDefined as y } from "lit/directives/if-defined.js";
5
- import { live as he } from "lit/directives/live.js";
1
+ import { LitElement as de, html as Y, unsafeCSS as ce } from "lit";
2
+ import { property as s, query as ee } from "lit/decorators.js";
3
+ import { classMap as ue } from "lit/directives/class-map.js";
4
+ import { ifDefined as g } from "lit/directives/if-defined.js";
5
+ import { live as pe } from "lit/directives/live.js";
6
6
  import "@justeattakeaway/pie-assistive-text";
7
- import { FormControlMixin as fe, RtlMixin as xe, DelegatesFocusMixin as ve, wrapNativeEvent as ge, validPropertyValues as U, safeCustomElement as be } from "@justeattakeaway/pie-webc-core";
7
+ import { FormControlMixin as he, RtlMixin as fe, DelegatesFocusMixin as xe, wrapNativeEvent as ve, validPropertyValues as U, safeCustomElement as ge } from "@justeattakeaway/pie-webc-core";
8
8
  const O = class O extends de {
9
9
  willUpdate() {
10
10
  this.getAttribute("v") || this.setAttribute("v", O.v);
11
11
  }
12
12
  };
13
- O.v = "0.18.4";
14
- let V = O;
15
- var w = typeof globalThis < "u" ? globalThis : typeof window < "u" ? window : typeof global < "u" ? global : typeof self < "u" ? self : {};
16
- function me(t) {
17
- return t && t.__esModule && Object.prototype.hasOwnProperty.call(t, "default") ? t.default : t;
13
+ O.v = "0.20.0";
14
+ let P = O;
15
+ var j = typeof globalThis < "u" ? globalThis : typeof window < "u" ? window : typeof global < "u" ? global : typeof self < "u" ? self : {};
16
+ function be(e) {
17
+ return e && e.__esModule && Object.prototype.hasOwnProperty.call(e, "default") ? e.default : e;
18
18
  }
19
- var P, Y;
20
- function ye() {
21
- if (Y) return P;
22
- Y = 1;
23
- var t = "Expected a function", s = NaN, g = "[object Symbol]", f = /^\s+|\s+$/g, c = /^[-+]0x[0-9a-f]+$/i, b = /^0b[01]+$/i, x = /^0o[0-7]+$/i, E = parseInt, I = typeof w == "object" && w && w.Object === Object && w, F = typeof self == "object" && self && self.Object === Object && self, k = I || F || Function("return this")(), R = Object.prototype, L = R.toString, M = Math.max, ee = Math.min, q = function() {
19
+ var V, Z;
20
+ function me() {
21
+ if (Z) return V;
22
+ Z = 1;
23
+ var e = "Expected a function", l = NaN, b = "[object Symbol]", f = /^\s+|\s+$/g, c = /^[-+]0x[0-9a-f]+$/i, m = /^0b[01]+$/i, x = /^0o[0-7]+$/i, E = parseInt, I = typeof j == "object" && j && j.Object === Object && j, F = typeof self == "object" && self && self.Object === Object && self, k = I || F || Function("return this")(), R = Object.prototype, L = R.toString, M = Math.max, q = Math.min, D = function() {
24
24
  return k.Date.now();
25
25
  };
26
- function te(e, i, n) {
27
- var p, h, W, z, u, m, $ = 0, H = !1, T = !1, D = !0;
28
- if (typeof e != "function")
29
- throw new TypeError(t);
30
- i = G(i) || 0, S(n) && (H = !!n.leading, T = "maxWait" in n, W = T ? M(G(n.maxWait) || 0, i) : W, D = "trailing" in n ? !!n.trailing : D);
31
- function A(r) {
32
- var v = p, _ = h;
33
- return p = h = void 0, $ = r, z = e.apply(_, v), z;
26
+ function te(t, i, n) {
27
+ var p, h, S, z, u, y, $ = 0, K = !1, _ = !1, A = !0;
28
+ if (typeof t != "function")
29
+ throw new TypeError(e);
30
+ i = G(i) || 0, w(n) && (K = !!n.leading, _ = "maxWait" in n, S = _ ? M(G(n.maxWait) || 0, i) : S, A = "trailing" in n ? !!n.trailing : A);
31
+ function B(a) {
32
+ var v = p, T = h;
33
+ return p = h = void 0, $ = a, z = t.apply(T, v), z;
34
34
  }
35
- function oe(r) {
36
- return $ = r, u = setTimeout(j, i), H ? A(r) : z;
35
+ function oe(a) {
36
+ return $ = a, u = setTimeout(W, i), K ? B(a) : z;
37
37
  }
38
- function ne(r) {
39
- var v = r - m, _ = r - $, J = i - v;
40
- return T ? ee(J, W - _) : J;
38
+ function ne(a) {
39
+ var v = a - y, T = a - $, Q = i - v;
40
+ return _ ? q(Q, S - T) : Q;
41
41
  }
42
- function K(r) {
43
- var v = r - m, _ = r - $;
44
- return m === void 0 || v >= i || v < 0 || T && _ >= W;
42
+ function X(a) {
43
+ var v = a - y, T = a - $;
44
+ return y === void 0 || v >= i || v < 0 || _ && T >= S;
45
45
  }
46
- function j() {
47
- var r = q();
48
- if (K(r))
49
- return X(r);
50
- u = setTimeout(j, ne(r));
46
+ function W() {
47
+ var a = D();
48
+ if (X(a))
49
+ return J(a);
50
+ u = setTimeout(W, ne(a));
51
51
  }
52
- function X(r) {
53
- return u = void 0, D && p ? A(r) : (p = h = void 0, z);
52
+ function J(a) {
53
+ return u = void 0, A && p ? B(a) : (p = h = void 0, z);
54
54
  }
55
55
  function se() {
56
- u !== void 0 && clearTimeout(u), $ = 0, p = m = h = u = void 0;
56
+ u !== void 0 && clearTimeout(u), $ = 0, p = y = h = u = void 0;
57
57
  }
58
58
  function le() {
59
- return u === void 0 ? z : X(q());
59
+ return u === void 0 ? z : J(D());
60
60
  }
61
- function B() {
62
- var r = q(), v = K(r);
63
- if (p = arguments, h = this, m = r, v) {
61
+ function N() {
62
+ var a = D(), v = X(a);
63
+ if (p = arguments, h = this, y = a, v) {
64
64
  if (u === void 0)
65
- return oe(m);
66
- if (T)
67
- return u = setTimeout(j, i), A(m);
65
+ return oe(y);
66
+ if (_)
67
+ return u = setTimeout(W, i), B(y);
68
68
  }
69
- return u === void 0 && (u = setTimeout(j, i)), z;
69
+ return u === void 0 && (u = setTimeout(W, i)), z;
70
70
  }
71
- return B.cancel = se, B.flush = le, B;
71
+ return N.cancel = se, N.flush = le, N;
72
72
  }
73
- function re(e, i, n) {
73
+ function re(t, i, n) {
74
74
  var p = !0, h = !0;
75
- if (typeof e != "function")
76
- throw new TypeError(t);
77
- return S(n) && (p = "leading" in n ? !!n.leading : p, h = "trailing" in n ? !!n.trailing : h), te(e, i, {
75
+ if (typeof t != "function")
76
+ throw new TypeError(e);
77
+ return w(n) && (p = "leading" in n ? !!n.leading : p, h = "trailing" in n ? !!n.trailing : h), te(t, i, {
78
78
  leading: p,
79
79
  maxWait: i,
80
80
  trailing: h
81
81
  });
82
82
  }
83
- function S(e) {
84
- var i = typeof e;
85
- return !!e && (i == "object" || i == "function");
83
+ function w(t) {
84
+ var i = typeof t;
85
+ return !!t && (i == "object" || i == "function");
86
86
  }
87
- function ae(e) {
88
- return !!e && typeof e == "object";
87
+ function ae(t) {
88
+ return !!t && typeof t == "object";
89
89
  }
90
- function ie(e) {
91
- return typeof e == "symbol" || ae(e) && L.call(e) == g;
90
+ function ie(t) {
91
+ return typeof t == "symbol" || ae(t) && L.call(t) == b;
92
92
  }
93
- function G(e) {
94
- if (typeof e == "number")
95
- return e;
96
- if (ie(e))
97
- return s;
98
- if (S(e)) {
99
- var i = typeof e.valueOf == "function" ? e.valueOf() : e;
100
- e = S(i) ? i + "" : i;
93
+ function G(t) {
94
+ if (typeof t == "number")
95
+ return t;
96
+ if (ie(t))
97
+ return l;
98
+ if (w(t)) {
99
+ var i = typeof t.valueOf == "function" ? t.valueOf() : t;
100
+ t = w(i) ? i + "" : i;
101
101
  }
102
- if (typeof e != "string")
103
- return e === 0 ? e : +e;
104
- e = e.replace(f, "");
105
- var n = b.test(e);
106
- return n || x.test(e) ? E(e.slice(2), n ? 2 : 8) : c.test(e) ? s : +e;
102
+ if (typeof t != "string")
103
+ return t === 0 ? t : +t;
104
+ t = t.replace(f, "");
105
+ var n = m.test(t);
106
+ return n || x.test(t) ? E(t.slice(2), n ? 2 : 8) : c.test(t) ? l : +t;
107
107
  }
108
- return P = re, P;
108
+ return V = re, V;
109
109
  }
110
- var ze = ye();
111
- const ke = /* @__PURE__ */ me(ze), $e = "*,*:after,*:before{box-sizing:inherit}:host{display:block}.c-textareaWrapper{--textarea-line-height: calc(var(--dt-font-body-l-line-height) * 1px);--textarea-border-thickness: 1px;--textarea-resize: none;--textarea-padding-inline: var(--dt-spacing-c);--textarea-padding-block: var(--dt-spacing-b);--textarea-background-color: var(--dt-color-container-default);--textarea-border-color: var(--dt-color-border-form);--textarea-content-color: var(--dt-color-content-default);--textarea-placeholder-color: var(--dt-color-content-placeholder);--textarea-height: calc((var(--textarea-line-height) * 2) + (var(--textarea-padding-block) * 2));line-height:0;padding:var(--dt-spacing-a);border:var(--textarea-border-thickness) solid var(--textarea-border-color);background-color:var(--textarea-background-color);border-radius:var(--dt-radius-rounded-c);inline-size:100%}.c-textareaWrapper textarea{font-size:calc(var(--dt-font-body-l-size) * 1px);line-height:var(--textarea-line-height);font-family:var(--dt-font-body-l-family);resize:var(--textarea-resize);border:none;background-color:var(--textarea-background-color);color:var(--textarea-content-color);block-size:var(--textarea-height);max-block-size:var(--textarea-max-height);min-block-size:var(--textarea-min-height);inline-size:100%;padding-block-start:var(--textarea-padding-block);padding-block-end:var(--textarea-padding-block);padding-inline-start:var(--textarea-padding-inline);padding-inline-end:var(--textarea-padding-inline)}.c-textareaWrapper textarea:focus{box-shadow:none;outline:none}.c-textareaWrapper textarea::placeholder{color:var(--textarea-placeholder-color);opacity:1}.c-textareaWrapper.is-readonly{--textarea-background-color: var(--dt-color-container-subtle);--textarea-border-color: var(--dt-color-border-form)}.c-textareaWrapper.is-disabled{--textarea-background-color: var(--dt-color-disabled-01);--textarea-border-color: var(--dt-color-disabled-01);--textarea-content-color: var(--dt-color-content-disabled);--textarea-placeholder-color: var(--dt-color-content-disabled)}@media(hover:hover){.c-textareaWrapper:hover:not(.is-disabled,.is-readonly){--textarea-background-color: hsl(var(--dt-color-container-default-h), var(--dt-color-container-default-s), calc(var(--dt-color-container-default-l) + calc(-1 * var(--dt-color-hover-01))))}@supports (background-color: color-mix(in srgb,black,white)){.c-textareaWrapper:hover:not(.is-disabled,.is-readonly){--textarea-background-color: color-mix(in srgb, var(--dt-color-hover-01-bg) var(--dt-color-hover-01), var(--dt-color-container-default))}}}.c-textareaWrapper:focus-within{box-shadow:0 0 0 2px var(--dt-color-focus-inner),0 0 0 4px var(--dt-color-focus-outer);outline:none}.c-textareaWrapper.c-textarea--large{--textarea-padding-block: var(--dt-spacing-c)}.c-textareaWrapper.c-textarea--small{--textarea-padding-block: var(--dt-spacing-a)}.c-textareaWrapper.c-textarea--resize-manual{--textarea-resize: vertical;--textarea-min-height: calc((var(--textarea-line-height) * 1) + (var(--textarea-padding-block) * 2))}@media(pointer:coarse){.c-textareaWrapper.c-textarea--resize-manual{--textarea-height: calc((var(--textarea-line-height) * 6) + (var(--textarea-padding-block) * 2));--textarea-min-height: calc((var(--textarea-line-height) * 6) + (var(--textarea-padding-block) * 2));--textarea-max-height: calc((var(--textarea-line-height) * 6) + (var(--textarea-padding-block) * 2));--textarea-resize: none}}.c-textareaWrapper.c-textarea--resize-auto{--textarea-max-height: calc((var(--textarea-line-height) * 6) + (var(--textarea-padding-block) * 2));--textarea-min-height: var(--textarea-height)}.c-textareaWrapper.has-error{--textarea-border-color: var(--dt-color-support-error)}", Te = ["small", "medium", "large"], _e = ["auto", "manual"], Ce = ["default", "success", "error"], d = {
110
+ var ye = me();
111
+ const ze = /* @__PURE__ */ be(ye), ke = "*,*:after,*:before{box-sizing:inherit}:host{display:block}.c-textareaWrapper{--textarea-line-height: calc(var(--dt-font-body-l-line-height) * 1px);--textarea-border-thickness: 1px;--textarea-resize: none;--textarea-padding-inline: var(--dt-spacing-c);--textarea-padding-block: var(--dt-spacing-b);--textarea-background-color: var(--dt-color-container-default);--textarea-border-color: var(--dt-color-border-form);--textarea-content-color: var(--dt-color-content-default);--textarea-placeholder-color: var(--dt-color-content-placeholder);--textarea-height: calc((var(--textarea-line-height) * 2) + (var(--textarea-padding-block) * 2));line-height:0;padding:var(--dt-spacing-a);border:var(--textarea-border-thickness) solid var(--textarea-border-color);background-color:var(--textarea-background-color);border-radius:var(--dt-radius-rounded-c);inline-size:100%}.c-textareaWrapper textarea{font-size:calc(var(--dt-font-body-l-size) * 1px);line-height:var(--textarea-line-height);font-family:var(--dt-font-body-l-family);resize:var(--textarea-resize);border:none;background-color:var(--textarea-background-color);color:var(--textarea-content-color);block-size:var(--textarea-height);max-block-size:var(--textarea-max-height);min-block-size:var(--textarea-min-height);inline-size:100%;padding-block-start:var(--textarea-padding-block);padding-block-end:var(--textarea-padding-block);padding-inline-start:var(--textarea-padding-inline);padding-inline-end:var(--textarea-padding-inline)}.c-textareaWrapper textarea:focus{box-shadow:none;outline:none}.c-textareaWrapper textarea::placeholder{color:var(--textarea-placeholder-color);opacity:1}.c-textareaWrapper.is-readonly{--textarea-background-color: var(--dt-color-container-subtle);--textarea-border-color: var(--dt-color-border-form)}.c-textareaWrapper.is-disabled{--textarea-background-color: var(--dt-color-disabled-01);--textarea-border-color: var(--dt-color-disabled-01);--textarea-content-color: var(--dt-color-content-disabled);--textarea-placeholder-color: var(--dt-color-content-disabled)}@media(hover:hover){.c-textareaWrapper:hover:not(.is-disabled,.is-readonly){--textarea-background-color: hsl(var(--dt-color-container-default-h), var(--dt-color-container-default-s), calc(var(--dt-color-container-default-l) + calc(-1 * var(--dt-color-hover-01))))}@supports (background-color: color-mix(in srgb,black,white)){.c-textareaWrapper:hover:not(.is-disabled,.is-readonly){--textarea-background-color: color-mix(in srgb, var(--dt-color-hover-01-bg) var(--dt-color-hover-01), var(--dt-color-container-default))}}}.c-textareaWrapper:focus-within{box-shadow:0 0 0 2px var(--dt-color-focus-inner),0 0 0 4px var(--dt-color-focus-outer);outline:none}.c-textareaWrapper.c-textarea--large{--textarea-padding-block: var(--dt-spacing-c)}.c-textareaWrapper.c-textarea--small{--textarea-padding-block: var(--dt-spacing-a)}.c-textareaWrapper.c-textarea--resize-manual{--textarea-resize: vertical;--textarea-height: auto;--textarea-min-height: calc((var(--textarea-line-height) * 1) + (var(--textarea-padding-block) * 2))}@media(pointer:coarse){.c-textareaWrapper.c-textarea--resize-manual{--textarea-height: calc((var(--textarea-line-height) * 6) + (var(--textarea-padding-block) * 2));--textarea-min-height: calc((var(--textarea-line-height) * 6) + (var(--textarea-padding-block) * 2));--textarea-max-height: calc((var(--textarea-line-height) * 6) + (var(--textarea-padding-block) * 2));--textarea-resize: none}}.c-textareaWrapper.c-textarea--resize-auto{--textarea-max-height: calc((var(--textarea-line-height) * 6) + (var(--textarea-padding-block) * 2));--textarea-min-height: var(--textarea-height)}.c-textareaWrapper.has-error{--textarea-border-color: var(--dt-color-support-error)}", $e = ["small", "medium", "large"], _e = ["auto", "manual"], Te = ["default", "success", "error"], d = {
112
112
  disabled: !1,
113
113
  size: "medium",
114
114
  resize: "auto",
@@ -119,39 +119,39 @@ const ke = /* @__PURE__ */ me(ze), $e = "*,*:after,*:before{box-sizing:inherit}:
119
119
  readonly: !1,
120
120
  required: !1
121
121
  };
122
- var Se = Object.defineProperty, We = Object.getOwnPropertyDescriptor, o = (t, s, g, f) => {
123
- for (var c = f > 1 ? void 0 : f ? We(s, g) : s, b = t.length - 1, x; b >= 0; b--)
124
- (x = t[b]) && (c = (f ? x(s, g, c) : x(c)) || c);
125
- return f && c && Se(s, g, c), c;
122
+ var Ce = Object.defineProperty, we = Object.getOwnPropertyDescriptor, o = (e, l, b, f) => {
123
+ for (var c = f > 1 ? void 0 : f ? we(l, b) : l, m = e.length - 1, x; m >= 0; m--)
124
+ (x = e[m]) && (c = (f ? x(l, b, c) : x(c)) || c);
125
+ return f && c && Ce(l, b, c), c;
126
126
  };
127
- const C = "pie-textarea", N = "assistive-text";
128
- let a = class extends fe(xe(ve(V))) {
127
+ const C = "pie-textarea", H = "assistive-text";
128
+ let r = class extends he(fe(xe(P))) {
129
129
  constructor() {
130
- super(...arguments), this.value = d.value, this.disabled = d.disabled, this.size = d.size, this.resize = d.resize, this.readonly = d.readonly, this.autoFocus = d.autoFocus, this.required = d.required, this.status = d.status, this._throttledResize = ke(() => {
130
+ super(...arguments), this.value = d.value, this.disabled = d.disabled, this.size = d.size, this.resize = d.resize, this.readonly = d.readonly, this.autoFocus = d.autoFocus, this.required = d.required, this.status = d.status, this._throttledResize = ze(() => {
131
131
  this.resize === "auto" && (this._textarea.style.height = "auto", this._textarea.style.height = `${this._textarea.scrollHeight}px`);
132
- }, 100), this.handleInput = (t, s) => {
133
- t ? this.value = t.target.value : s && (this.value = s), this._internals.setFormValue(this.value), this.handleResize();
134
- }, this.handleChange = (t) => {
135
- const s = ge(t);
136
- this.dispatchEvent(s);
137
- }, this.handleKeyDown = (t) => {
138
- t.key === "Enter" && t.stopPropagation();
132
+ }, 100), this.handleInput = (e, l) => {
133
+ e ? this.value = e.target.value : l && (this.value = l), this._internals.setFormValue(this.value), this.handleResize();
134
+ }, this.handleChange = (e) => {
135
+ const l = ve(e);
136
+ this.dispatchEvent(l);
137
+ }, this.handleKeyDown = (e) => {
138
+ e.key === "Enter" && e.stopPropagation();
139
139
  };
140
140
  }
141
141
  connectedCallback() {
142
142
  super.connectedCallback(), this._abortController = new AbortController();
143
- const { signal: t } = this._abortController;
144
- window.addEventListener("resize", () => this.handleResize(), { signal: t });
143
+ const { signal: e } = this._abortController;
144
+ window.addEventListener("resize", () => this.handleResize(), { signal: e });
145
145
  }
146
146
  disconnectedCallback() {
147
147
  super.disconnectedCallback(), this._abortController.abort();
148
148
  }
149
149
  firstUpdated() {
150
- const { signal: t } = this._abortController;
151
- this._textarea.addEventListener("keydown", this.handleKeyDown, { signal: t }), this._internals.setFormValue(this.value);
150
+ const { signal: e } = this._abortController;
151
+ this._textarea.addEventListener("keydown", this.handleKeyDown, { signal: e }), this._internals.setFormValue(this.value);
152
152
  }
153
- updated(t) {
154
- t.has("value") && this.handleInput(null, this.value), this.resize === "auto" && (t.has("resize") || t.has("size")) && this.handleResize();
153
+ updated(e) {
154
+ e.has("value") && this.handleInput(null, this.value), this.resize === "auto" && (e.has("resize") || e.has("size") || e.has("rows")) && this.handleResize(), this.resize === "manual" && (e.has("rows") || e.has("size") || e.has("resize")) && (this._textarea.style.height = "");
155
155
  }
156
156
  /**
157
157
  * (Read-only) returns a ValidityState with the validity states that this element is in.
@@ -166,8 +166,8 @@ let a = class extends fe(xe(ve(V))) {
166
166
  * or because the disabled state changed on a <fieldset> that's an ancestor of this element.
167
167
  * @param disabled - The latest disabled state of the input.
168
168
  */
169
- formDisabledCallback(t) {
170
- this.disabled = t;
169
+ formDisabledCallback(e) {
170
+ this.disabled = e;
171
171
  }
172
172
  /**
173
173
  * Called when the form that owns this component is reset.
@@ -180,124 +180,130 @@ let a = class extends fe(xe(ve(V))) {
180
180
  this._throttledResize();
181
181
  }
182
182
  renderAssistiveText() {
183
- return this.assistiveText ? Q`
183
+ return Y`
184
184
  <pie-assistive-text
185
- id="${N}"
186
- variant=${y(this.status)}
185
+ id="${H}"
186
+ variant=${g(this.status)}
187
+ message=${this.assistiveText || ""}
188
+ ?isVisuallyHidden=${!this.assistiveText}
187
189
  data-test-id="pie-textarea-assistive-text">
188
- ${this.assistiveText}
189
190
  </pie-assistive-text>
190
- ` : ce;
191
+ `;
191
192
  }
192
193
  render() {
193
194
  const {
194
- disabled: t,
195
- resize: s,
196
- size: g,
195
+ disabled: e,
196
+ resize: l,
197
+ size: b,
197
198
  autocomplete: f,
198
199
  autoFocus: c,
199
- name: b,
200
+ name: m,
200
201
  readonly: x,
201
202
  placeholder: E,
202
203
  value: I,
203
204
  required: F,
204
205
  status: k,
205
206
  assistiveText: R,
206
- maxlength: L
207
- } = this, M = {
207
+ maxlength: L,
208
+ rows: M
209
+ } = this, q = {
208
210
  "c-textareaWrapper": !0,
209
- "is-disabled": t,
211
+ "is-disabled": e,
210
212
  "is-readonly": x,
211
213
  "has-error": k === "error",
212
- [`c-textarea--resize-${s}`]: !0,
213
- [`c-textarea--${g}`]: !0
214
+ [`c-textarea--resize-${l}`]: !0,
215
+ [`c-textarea--${b}`]: !0
214
216
  };
215
- return Q`<div>
217
+ return Y`<div>
216
218
  <div
217
- class="${pe(M)}"
219
+ class="${ue(q)}"
218
220
  data-test-id="pie-textarea-wrapper">
219
221
  <textarea
220
222
  id="${C}"
221
223
  data-test-id="${C}"
222
- name=${y(b)}
223
- autocomplete=${y(f)}
224
- placeholder=${y(E)}
225
- .value=${he(I)}
224
+ name=${g(m)}
225
+ autocomplete=${g(f)}
226
+ placeholder=${g(E)}
227
+ .value=${pe(I)}
226
228
  ?autofocus=${c}
227
229
  ?readonly=${x}
228
230
  ?required=${F}
229
- ?disabled=${t}
230
- aria-describedby=${y(R ? N : void 0)}
231
+ ?disabled=${e}
232
+ aria-describedby=${g(R ? H : void 0)}
231
233
  aria-invalid=${k === "error" ? "true" : "false"}
232
- aria-errormessage="${y(k === "error" ? N : void 0)}"
234
+ aria-errormessage="${g(k === "error" ? H : void 0)}"
233
235
  @input=${this.handleInput}
234
236
  @change=${this.handleChange}
235
- maxlength=${y(L)}
237
+ maxlength=${g(L)}
238
+ rows=${g(M)}
236
239
  ></textarea>
237
240
  </div>
238
241
  ${this.renderAssistiveText()}
239
242
  </div>`;
240
243
  }
241
244
  };
242
- a.styles = ue($e);
245
+ r.styles = ce(ke);
243
246
  o([
244
- l({ type: String })
245
- ], a.prototype, "value", 2);
247
+ s({ type: String })
248
+ ], r.prototype, "value", 2);
246
249
  o([
247
- l({ type: String })
248
- ], a.prototype, "defaultValue", 2);
250
+ s({ type: String })
251
+ ], r.prototype, "defaultValue", 2);
249
252
  o([
250
- l({ type: Boolean, reflect: !0 })
251
- ], a.prototype, "disabled", 2);
253
+ s({ type: Boolean, reflect: !0 })
254
+ ], r.prototype, "disabled", 2);
252
255
  o([
253
- l({ type: String }),
254
- U(C, Te, d.size)
255
- ], a.prototype, "size", 2);
256
+ s({ type: String }),
257
+ U(C, $e, d.size)
258
+ ], r.prototype, "size", 2);
256
259
  o([
257
- l({ type: String }),
260
+ s({ type: String }),
258
261
  U(C, _e, d.resize)
259
- ], a.prototype, "resize", 2);
262
+ ], r.prototype, "resize", 2);
260
263
  o([
261
- l({ type: Boolean })
262
- ], a.prototype, "readonly", 2);
264
+ s({ type: Boolean })
265
+ ], r.prototype, "readonly", 2);
263
266
  o([
264
- l({ type: Boolean })
265
- ], a.prototype, "autoFocus", 2);
267
+ s({ type: Boolean })
268
+ ], r.prototype, "autoFocus", 2);
266
269
  o([
267
- l({ type: Boolean })
268
- ], a.prototype, "required", 2);
270
+ s({ type: Boolean })
271
+ ], r.prototype, "required", 2);
269
272
  o([
270
- l({ type: String }),
271
- U(C, Ce, d.status)
272
- ], a.prototype, "status", 2);
273
+ s({ type: String }),
274
+ U(C, Te, d.status)
275
+ ], r.prototype, "status", 2);
273
276
  o([
274
- l({ type: String })
275
- ], a.prototype, "assistiveText", 2);
277
+ s({ type: String })
278
+ ], r.prototype, "assistiveText", 2);
276
279
  o([
277
- l({ type: String, reflect: !0 })
278
- ], a.prototype, "name", 2);
280
+ s({ type: String, reflect: !0 })
281
+ ], r.prototype, "name", 2);
279
282
  o([
280
- l({ type: String })
281
- ], a.prototype, "autocomplete", 2);
283
+ s({ type: String })
284
+ ], r.prototype, "autocomplete", 2);
282
285
  o([
283
- l({ type: String })
284
- ], a.prototype, "placeholder", 2);
286
+ s({ type: String })
287
+ ], r.prototype, "placeholder", 2);
285
288
  o([
286
- l({ type: Number })
287
- ], a.prototype, "maxlength", 2);
289
+ s({ type: Number })
290
+ ], r.prototype, "maxlength", 2);
288
291
  o([
289
- Z("textarea")
290
- ], a.prototype, "_textarea", 2);
292
+ s({ type: Number })
293
+ ], r.prototype, "rows", 2);
291
294
  o([
292
- Z("textarea")
293
- ], a.prototype, "focusTarget", 2);
294
- a = o([
295
- be("pie-textarea")
296
- ], a);
295
+ ee("textarea")
296
+ ], r.prototype, "_textarea", 2);
297
+ o([
298
+ ee("textarea")
299
+ ], r.prototype, "focusTarget", 2);
300
+ r = o([
301
+ ge("pie-textarea")
302
+ ], r);
297
303
  export {
298
- a as PieTextarea,
304
+ r as PieTextarea,
299
305
  d as defaultProps,
300
306
  _e as resizeModes,
301
- Te as sizes,
302
- Ce as statusTypes
307
+ $e as sizes,
308
+ Te as statusTypes
303
309
  };
package/dist/react.d.ts CHANGED
@@ -12,7 +12,7 @@ import { TemplateResult } from 'lit-html';
12
12
  /**
13
13
  * The default values for the `TextareaProps` that are required (i.e. they have a fallback value in the component).
14
14
  */
15
- declare type DefaultProps = ComponentDefaultProps<TextareaProps, keyof Omit<TextareaProps, 'name' | 'autocomplete' | 'assistiveText' | 'defaultValue' | 'maxlength'>>;
15
+ declare type DefaultProps = ComponentDefaultProps<TextareaProps, keyof Omit<TextareaProps, 'name' | 'autocomplete' | 'assistiveText' | 'defaultValue' | 'maxlength' | 'rows'>>;
16
16
 
17
17
  /**
18
18
  * Default values for optional properties that have default fallback values in the component.
@@ -41,6 +41,7 @@ declare class PieTextarea_2 extends PieTextarea_base implements TextareaProps, P
41
41
  autocomplete: TextareaProps['autocomplete'];
42
42
  placeholder: TextareaProps['placeholder'];
43
43
  maxlength: TextareaProps['maxlength'];
44
+ rows: TextareaProps['rows'];
44
45
  private _textarea;
45
46
  focusTarget: HTMLElement;
46
47
  private _abortController;
@@ -162,6 +163,11 @@ export declare interface TextareaProps {
162
163
  * The maximum number of characters allowed in the textarea.
163
164
  */
164
165
  maxlength?: number;
166
+ /**
167
+ * The number of visible text rows. Defaults to 2 when resize is auto, with a maximum of 6 rows.
168
+ * Can be set to 1 when resize is manual (no maximum height on desktop). On mobile, manual mode is fixed at 6 rows and cannot be resized.
169
+ */
170
+ rows?: number;
165
171
  }
166
172
 
167
173
  export { }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@justeattakeaway/pie-textarea",
3
3
  "description": "PIE Design System Textarea built using Web Components",
4
- "version": "0.18.4",
4
+ "version": "0.20.0",
5
5
  "repository": {
6
6
  "type": "git",
7
7
  "url": "https://github.com/justeattakeaway/pie",
@@ -44,13 +44,13 @@
44
44
  "license": "Apache-2.0",
45
45
  "devDependencies": {
46
46
  "@justeattakeaway/pie-components-config": "0.21.3",
47
- "@justeattakeaway/pie-css": "1.1.2",
48
- "@justeattakeaway/pie-monorepo-utils": "0.9.4",
47
+ "@justeattakeaway/pie-css": "1.2.0",
48
+ "@justeattakeaway/pie-monorepo-utils": "0.9.6",
49
49
  "@types/lodash.throttle": "4.1.9"
50
50
  },
51
51
  "dependencies": {
52
- "@justeattakeaway/pie-assistive-text": "0.11.35",
53
- "@justeattakeaway/pie-webc-core": "14.0.2",
52
+ "@justeattakeaway/pie-assistive-text": "1.0.0",
53
+ "@justeattakeaway/pie-webc-core": "15.0.0",
54
54
  "lodash.throttle": "4.1.1"
55
55
  },
56
56
  "customElements": "custom-elements.json",
package/src/defs.ts CHANGED
@@ -80,12 +80,18 @@ export interface TextareaProps {
80
80
  * The maximum number of characters allowed in the textarea.
81
81
  */
82
82
  maxlength?: number;
83
+
84
+ /**
85
+ * The number of visible text rows. Defaults to 2 when resize is auto, with a maximum of 6 rows.
86
+ * Can be set to 1 when resize is manual (no maximum height on desktop). On mobile, manual mode is fixed at 6 rows and cannot be resized.
87
+ */
88
+ rows?: number;
83
89
  }
84
90
 
85
91
  /**
86
92
  * The default values for the `TextareaProps` that are required (i.e. they have a fallback value in the component).
87
93
  */
88
- type DefaultProps = ComponentDefaultProps<TextareaProps, keyof Omit<TextareaProps, 'name' | 'autocomplete' | 'assistiveText' | 'defaultValue'| 'maxlength'>>;
94
+ type DefaultProps = ComponentDefaultProps<TextareaProps, keyof Omit<TextareaProps, 'name' | 'autocomplete' | 'assistiveText' | 'defaultValue' | 'maxlength' | 'rows'>>;
89
95
 
90
96
  /**
91
97
  * Default values for optional properties that have default fallback values in the component.
package/src/index.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import {
2
- html, unsafeCSS, type PropertyValues, nothing,
2
+ html, unsafeCSS, type PropertyValues,
3
3
  } from 'lit';
4
4
  import { PieElement } from '@justeattakeaway/pie-webc-core/src/internals/PieElement';
5
5
  import { property, query } from 'lit/decorators.js';
@@ -78,6 +78,9 @@ export class PieTextarea extends FormControlMixin(RtlMixin(DelegatesFocusMixin(P
78
78
  @property({ type: Number })
79
79
  public maxlength: TextareaProps['maxlength'];
80
80
 
81
+ @property({ type: Number })
82
+ public rows: TextareaProps['rows'];
83
+
81
84
  @query('textarea')
82
85
  private _textarea!: HTMLTextAreaElement;
83
86
 
@@ -109,9 +112,13 @@ export class PieTextarea extends FormControlMixin(RtlMixin(DelegatesFocusMixin(P
109
112
  this.handleInput(null, this.value);
110
113
  }
111
114
 
112
- if (this.resize === 'auto' && (changedProperties.has('resize') || changedProperties.has('size'))) {
115
+ if (this.resize === 'auto' && ((changedProperties.has('resize') || changedProperties.has('size')) || changedProperties.has('rows'))) {
113
116
  this.handleResize();
114
117
  }
118
+
119
+ if (this.resize === 'manual' && ((changedProperties.has('rows') || changedProperties.has('size') || changedProperties.has('resize')))) {
120
+ this._textarea.style.height = '';
121
+ }
115
122
  }
116
123
 
117
124
  private _throttledResize = throttle(() => {
@@ -191,16 +198,13 @@ export class PieTextarea extends FormControlMixin(RtlMixin(DelegatesFocusMixin(P
191
198
  };
192
199
 
193
200
  private renderAssistiveText () {
194
- if (!this.assistiveText) {
195
- return nothing;
196
- }
197
-
198
201
  return html`
199
202
  <pie-assistive-text
200
203
  id="${assistiveTextIdValue}"
201
204
  variant=${ifDefined(this.status)}
205
+ message=${this.assistiveText || ''}
206
+ ?isVisuallyHidden=${!this.assistiveText}
202
207
  data-test-id="pie-textarea-assistive-text">
203
- ${this.assistiveText}
204
208
  </pie-assistive-text>
205
209
  `;
206
210
  }
@@ -220,6 +224,7 @@ export class PieTextarea extends FormControlMixin(RtlMixin(DelegatesFocusMixin(P
220
224
  status,
221
225
  assistiveText,
222
226
  maxlength,
227
+ rows,
223
228
  } = this;
224
229
 
225
230
  const classes = {
@@ -252,6 +257,7 @@ export class PieTextarea extends FormControlMixin(RtlMixin(DelegatesFocusMixin(P
252
257
  @input=${this.handleInput}
253
258
  @change=${this.handleChange}
254
259
  maxlength=${ifDefined(maxlength)}
260
+ rows=${ifDefined(rows)}
255
261
  ></textarea>
256
262
  </div>
257
263
  ${this.renderAssistiveText()}
package/src/textarea.scss CHANGED
@@ -98,6 +98,7 @@
98
98
 
99
99
  &.c-textarea--resize-manual {
100
100
  --textarea-resize: vertical;
101
+ --textarea-height: auto;
101
102
 
102
103
  // Minimum is one line of text
103
104
  --textarea-min-height: calc((var(--textarea-line-height) * 1) + (var(--textarea-padding-block) * 2));