@justeattakeaway/pie-textarea 0.19.0 → 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, html as Q, unsafeCSS as ce } from "lit";
2
- import { property as l, query as Z } from "lit/decorators.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
3
  import { classMap as ue } from "lit/directives/class-map.js";
4
- import { ifDefined as y } from "lit/directives/if-defined.js";
4
+ import { ifDefined as g } from "lit/directives/if-defined.js";
5
5
  import { live as pe } from "lit/directives/live.js";
6
6
  import "@justeattakeaway/pie-assistive-text";
7
- import { FormControlMixin as he, RtlMixin as fe, DelegatesFocusMixin as xe, wrapNativeEvent as ve, validPropertyValues as H, safeCustomElement as ge } 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.19.0";
14
- let N = O;
15
- var w = typeof globalThis < "u" ? globalThis : typeof window < "u" ? window : typeof global < "u" ? global : typeof self < "u" ? self : {};
16
- function be(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;
19
+ var V, Z;
20
20
  function me() {
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() {
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, G = !1, T = !1, D = !0;
28
- if (typeof e != "function")
29
- throw new TypeError(t);
30
- i = U(i) || 0, S(n) && (G = !!n.leading, T = "maxWait" in n, W = T ? M(U(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), G ? 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 U(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
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-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"], Te = ["auto", "manual"], _e = ["default", "success", "error"], d = {
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 ze = /* @__PURE__ */ be(ye), ke = "*,*:after,*:before{box-sizing:inherit}:
119
119
  readonly: !1,
120
120
  required: !1
121
121
  };
122
- var Ce = Object.defineProperty, Se = Object.getOwnPropertyDescriptor, o = (t, s, g, f) => {
123
- for (var c = f > 1 ? void 0 : f ? Se(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 && Ce(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", V = "assistive-text";
128
- let a = class extends he(fe(xe(N))) {
127
+ const C = "pie-textarea", H = "assistive-text";
128
+ let r = class extends he(fe(xe(P))) {
129
129
  constructor() {
130
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 = ve(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 he(fe(xe(N))) {
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,10 +180,10 @@ let a = class extends he(fe(xe(N))) {
180
180
  this._throttledResize();
181
181
  }
182
182
  renderAssistiveText() {
183
- return Q`
183
+ return Y`
184
184
  <pie-assistive-text
185
- id="${V}"
186
- variant=${y(this.status)}
185
+ id="${H}"
186
+ variant=${g(this.status)}
187
187
  message=${this.assistiveText || ""}
188
188
  ?isVisuallyHidden=${!this.assistiveText}
189
189
  data-test-id="pie-textarea-assistive-text">
@@ -192,113 +192,118 @@ let a = class extends he(fe(xe(N))) {
192
192
  }
193
193
  render() {
194
194
  const {
195
- disabled: t,
196
- resize: s,
197
- size: g,
195
+ disabled: e,
196
+ resize: l,
197
+ size: b,
198
198
  autocomplete: f,
199
199
  autoFocus: c,
200
- name: b,
200
+ name: m,
201
201
  readonly: x,
202
202
  placeholder: E,
203
203
  value: I,
204
204
  required: F,
205
205
  status: k,
206
206
  assistiveText: R,
207
- maxlength: L
208
- } = this, M = {
207
+ maxlength: L,
208
+ rows: M
209
+ } = this, q = {
209
210
  "c-textareaWrapper": !0,
210
- "is-disabled": t,
211
+ "is-disabled": e,
211
212
  "is-readonly": x,
212
213
  "has-error": k === "error",
213
- [`c-textarea--resize-${s}`]: !0,
214
- [`c-textarea--${g}`]: !0
214
+ [`c-textarea--resize-${l}`]: !0,
215
+ [`c-textarea--${b}`]: !0
215
216
  };
216
- return Q`<div>
217
+ return Y`<div>
217
218
  <div
218
- class="${ue(M)}"
219
+ class="${ue(q)}"
219
220
  data-test-id="pie-textarea-wrapper">
220
221
  <textarea
221
222
  id="${C}"
222
223
  data-test-id="${C}"
223
- name=${y(b)}
224
- autocomplete=${y(f)}
225
- placeholder=${y(E)}
224
+ name=${g(m)}
225
+ autocomplete=${g(f)}
226
+ placeholder=${g(E)}
226
227
  .value=${pe(I)}
227
228
  ?autofocus=${c}
228
229
  ?readonly=${x}
229
230
  ?required=${F}
230
- ?disabled=${t}
231
- aria-describedby=${y(R ? V : void 0)}
231
+ ?disabled=${e}
232
+ aria-describedby=${g(R ? H : void 0)}
232
233
  aria-invalid=${k === "error" ? "true" : "false"}
233
- aria-errormessage="${y(k === "error" ? V : void 0)}"
234
+ aria-errormessage="${g(k === "error" ? H : void 0)}"
234
235
  @input=${this.handleInput}
235
236
  @change=${this.handleChange}
236
- maxlength=${y(L)}
237
+ maxlength=${g(L)}
238
+ rows=${g(M)}
237
239
  ></textarea>
238
240
  </div>
239
241
  ${this.renderAssistiveText()}
240
242
  </div>`;
241
243
  }
242
244
  };
243
- a.styles = ce(ke);
245
+ r.styles = ce(ke);
244
246
  o([
245
- l({ type: String })
246
- ], a.prototype, "value", 2);
247
+ s({ type: String })
248
+ ], r.prototype, "value", 2);
247
249
  o([
248
- l({ type: String })
249
- ], a.prototype, "defaultValue", 2);
250
+ s({ type: String })
251
+ ], r.prototype, "defaultValue", 2);
250
252
  o([
251
- l({ type: Boolean, reflect: !0 })
252
- ], a.prototype, "disabled", 2);
253
+ s({ type: Boolean, reflect: !0 })
254
+ ], r.prototype, "disabled", 2);
253
255
  o([
254
- l({ type: String }),
255
- H(C, $e, d.size)
256
- ], a.prototype, "size", 2);
256
+ s({ type: String }),
257
+ U(C, $e, d.size)
258
+ ], r.prototype, "size", 2);
257
259
  o([
258
- l({ type: String }),
259
- H(C, Te, d.resize)
260
- ], a.prototype, "resize", 2);
260
+ s({ type: String }),
261
+ U(C, _e, d.resize)
262
+ ], r.prototype, "resize", 2);
261
263
  o([
262
- l({ type: Boolean })
263
- ], a.prototype, "readonly", 2);
264
+ s({ type: Boolean })
265
+ ], r.prototype, "readonly", 2);
264
266
  o([
265
- l({ type: Boolean })
266
- ], a.prototype, "autoFocus", 2);
267
+ s({ type: Boolean })
268
+ ], r.prototype, "autoFocus", 2);
267
269
  o([
268
- l({ type: Boolean })
269
- ], a.prototype, "required", 2);
270
+ s({ type: Boolean })
271
+ ], r.prototype, "required", 2);
270
272
  o([
271
- l({ type: String }),
272
- H(C, _e, d.status)
273
- ], a.prototype, "status", 2);
273
+ s({ type: String }),
274
+ U(C, Te, d.status)
275
+ ], r.prototype, "status", 2);
274
276
  o([
275
- l({ type: String })
276
- ], a.prototype, "assistiveText", 2);
277
+ s({ type: String })
278
+ ], r.prototype, "assistiveText", 2);
277
279
  o([
278
- l({ type: String, reflect: !0 })
279
- ], a.prototype, "name", 2);
280
+ s({ type: String, reflect: !0 })
281
+ ], r.prototype, "name", 2);
280
282
  o([
281
- l({ type: String })
282
- ], a.prototype, "autocomplete", 2);
283
+ s({ type: String })
284
+ ], r.prototype, "autocomplete", 2);
283
285
  o([
284
- l({ type: String })
285
- ], a.prototype, "placeholder", 2);
286
+ s({ type: String })
287
+ ], r.prototype, "placeholder", 2);
286
288
  o([
287
- l({ type: Number })
288
- ], a.prototype, "maxlength", 2);
289
+ s({ type: Number })
290
+ ], r.prototype, "maxlength", 2);
289
291
  o([
290
- Z("textarea")
291
- ], a.prototype, "_textarea", 2);
292
+ s({ type: Number })
293
+ ], r.prototype, "rows", 2);
292
294
  o([
293
- Z("textarea")
294
- ], a.prototype, "focusTarget", 2);
295
- a = o([
295
+ ee("textarea")
296
+ ], r.prototype, "_textarea", 2);
297
+ o([
298
+ ee("textarea")
299
+ ], r.prototype, "focusTarget", 2);
300
+ r = o([
296
301
  ge("pie-textarea")
297
- ], a);
302
+ ], r);
298
303
  export {
299
- a as PieTextarea,
304
+ r as PieTextarea,
300
305
  d as defaultProps,
301
- Te as resizeModes,
306
+ _e as resizeModes,
302
307
  $e as sizes,
303
- _e as statusTypes
308
+ Te as statusTypes
304
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.19.0",
4
+ "version": "0.20.0",
5
5
  "repository": {
6
6
  "type": "git",
7
7
  "url": "https://github.com/justeattakeaway/pie",
@@ -45,7 +45,7 @@
45
45
  "devDependencies": {
46
46
  "@justeattakeaway/pie-components-config": "0.21.3",
47
47
  "@justeattakeaway/pie-css": "1.2.0",
48
- "@justeattakeaway/pie-monorepo-utils": "0.9.5",
48
+ "@justeattakeaway/pie-monorepo-utils": "0.9.6",
49
49
  "@types/lodash.throttle": "4.1.9"
50
50
  },
51
51
  "dependencies": {
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
@@ -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(() => {
@@ -217,6 +224,7 @@ export class PieTextarea extends FormControlMixin(RtlMixin(DelegatesFocusMixin(P
217
224
  status,
218
225
  assistiveText,
219
226
  maxlength,
227
+ rows,
220
228
  } = this;
221
229
 
222
230
  const classes = {
@@ -249,6 +257,7 @@ export class PieTextarea extends FormControlMixin(RtlMixin(DelegatesFocusMixin(P
249
257
  @input=${this.handleInput}
250
258
  @change=${this.handleChange}
251
259
  maxlength=${ifDefined(maxlength)}
260
+ rows=${ifDefined(rows)}
252
261
  ></textarea>
253
262
  </div>
254
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));