@justeattakeaway/pie-textarea 0.5.0 → 0.6.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/custom-elements.json +51 -1
- package/dist/index.d.ts +15 -1
- package/dist/index.js +170 -148
- package/dist/react.d.ts +15 -1
- package/dist/react.js +8 -7
- package/package.json +2 -1
- package/src/defs.ts +13 -1
- package/src/index.ts +40 -6
package/custom-elements.json
CHANGED
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"type": {
|
|
35
35
|
"text": "DefaultProps"
|
|
36
36
|
},
|
|
37
|
-
"default": "{\n disabled: false,\n size: 'medium',\n resize: 'auto',\n value: '',\n autoFocus: false,\n readonly: false,\n required: false,\n}",
|
|
37
|
+
"default": "{\n disabled: false,\n size: 'medium',\n resize: 'auto',\n label: '',\n value: '',\n autoFocus: false,\n readonly: false,\n required: false,\n}",
|
|
38
38
|
"description": "Default values for optional properties that have default fallback values in the component."
|
|
39
39
|
}
|
|
40
40
|
],
|
|
@@ -108,6 +108,21 @@
|
|
|
108
108
|
"privacy": "public",
|
|
109
109
|
"attribute": "resize"
|
|
110
110
|
},
|
|
111
|
+
{
|
|
112
|
+
"kind": "field",
|
|
113
|
+
"name": "label",
|
|
114
|
+
"privacy": "public",
|
|
115
|
+
"attribute": "label"
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
"kind": "field",
|
|
119
|
+
"name": "maxLength",
|
|
120
|
+
"type": {
|
|
121
|
+
"text": "TextareaProps['maxLength']"
|
|
122
|
+
},
|
|
123
|
+
"privacy": "public",
|
|
124
|
+
"attribute": "maxLength"
|
|
125
|
+
},
|
|
111
126
|
{
|
|
112
127
|
"kind": "field",
|
|
113
128
|
"name": "readonly",
|
|
@@ -203,6 +218,11 @@
|
|
|
203
218
|
"name": "handleResize",
|
|
204
219
|
"privacy": "private"
|
|
205
220
|
},
|
|
221
|
+
{
|
|
222
|
+
"kind": "method",
|
|
223
|
+
"name": "restrictInputLength",
|
|
224
|
+
"privacy": "private"
|
|
225
|
+
},
|
|
206
226
|
{
|
|
207
227
|
"kind": "field",
|
|
208
228
|
"name": "handleInput",
|
|
@@ -224,6 +244,25 @@
|
|
|
224
244
|
"kind": "field",
|
|
225
245
|
"name": "handleKeyDown",
|
|
226
246
|
"privacy": "private"
|
|
247
|
+
},
|
|
248
|
+
{
|
|
249
|
+
"kind": "method",
|
|
250
|
+
"name": "renderLabel",
|
|
251
|
+
"parameters": [
|
|
252
|
+
{
|
|
253
|
+
"name": "label",
|
|
254
|
+
"type": {
|
|
255
|
+
"text": "string"
|
|
256
|
+
}
|
|
257
|
+
},
|
|
258
|
+
{
|
|
259
|
+
"name": "maxLength",
|
|
260
|
+
"optional": true,
|
|
261
|
+
"type": {
|
|
262
|
+
"text": "number"
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
]
|
|
227
266
|
}
|
|
228
267
|
],
|
|
229
268
|
"events": [
|
|
@@ -259,6 +298,17 @@
|
|
|
259
298
|
"name": "resize",
|
|
260
299
|
"fieldName": "resize"
|
|
261
300
|
},
|
|
301
|
+
{
|
|
302
|
+
"name": "label",
|
|
303
|
+
"fieldName": "label"
|
|
304
|
+
},
|
|
305
|
+
{
|
|
306
|
+
"name": "maxLength",
|
|
307
|
+
"type": {
|
|
308
|
+
"text": "TextareaProps['maxLength']"
|
|
309
|
+
},
|
|
310
|
+
"fieldName": "maxLength"
|
|
311
|
+
},
|
|
262
312
|
{
|
|
263
313
|
"name": "readonly",
|
|
264
314
|
"fieldName": "readonly"
|
package/dist/index.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ import type { CSSResult } from 'lit';
|
|
|
3
3
|
import type { FormControlInterface } from '@justeattakeaway/pie-webc-core';
|
|
4
4
|
import type { GenericConstructor } from '@justeattakeaway/pie-webc-core';
|
|
5
5
|
import type { LitElement } from 'lit';
|
|
6
|
+
import type { nothing } from 'lit';
|
|
6
7
|
import type { PropertyValues } from 'lit';
|
|
7
8
|
import type { RTLInterface } from '@justeattakeaway/pie-webc-core';
|
|
8
9
|
import type { TemplateResult } from 'lit-html';
|
|
@@ -10,7 +11,7 @@ import type { TemplateResult } from 'lit-html';
|
|
|
10
11
|
/**
|
|
11
12
|
* The default values for the `TextareaProps` that are required (i.e. they have a fallback value in the component).
|
|
12
13
|
*/
|
|
13
|
-
declare type DefaultProps = ComponentDefaultProps<TextareaProps, keyof Omit<TextareaProps, 'name' | 'autocomplete'>>;
|
|
14
|
+
declare type DefaultProps = ComponentDefaultProps<TextareaProps, keyof Omit<TextareaProps, 'name' | 'autocomplete' | 'maxLength'>>;
|
|
14
15
|
|
|
15
16
|
/**
|
|
16
17
|
* Default values for optional properties that have default fallback values in the component.
|
|
@@ -32,6 +33,8 @@ export declare class PieTextarea extends PieTextarea_base implements TextareaPro
|
|
|
32
33
|
disabled: boolean;
|
|
33
34
|
size: "small" | "medium" | "large";
|
|
34
35
|
resize: "auto" | "manual";
|
|
36
|
+
label: string;
|
|
37
|
+
maxLength: TextareaProps['maxLength'];
|
|
35
38
|
readonly: boolean;
|
|
36
39
|
autoFocus: boolean;
|
|
37
40
|
required: boolean;
|
|
@@ -58,6 +61,7 @@ export declare class PieTextarea extends PieTextarea_base implements TextareaPro
|
|
|
58
61
|
formResetCallback(): void;
|
|
59
62
|
protected firstUpdated(): void;
|
|
60
63
|
private handleResize;
|
|
64
|
+
private restrictInputLength;
|
|
61
65
|
protected updated(changedProperties: PropertyValues<this>): void;
|
|
62
66
|
/**
|
|
63
67
|
* Handles data processing in response to the input event. The native input event is left to bubble up.
|
|
@@ -67,6 +71,7 @@ export declare class PieTextarea extends PieTextarea_base implements TextareaPro
|
|
|
67
71
|
private handleChange;
|
|
68
72
|
private handleKeyDown;
|
|
69
73
|
disconnectedCallback(): void;
|
|
74
|
+
renderLabel(label: string, maxLength?: number): TemplateResult<1> | typeof nothing;
|
|
70
75
|
render(): TemplateResult<1>;
|
|
71
76
|
static styles: CSSResult;
|
|
72
77
|
}
|
|
@@ -120,6 +125,15 @@ export declare interface TextareaProps {
|
|
|
120
125
|
* If true, the textarea is required to have a value before submitting the form. If there is no value, then the component validity state will be invalid.
|
|
121
126
|
*/
|
|
122
127
|
required?: boolean;
|
|
128
|
+
/**
|
|
129
|
+
* The label text for the textarea field.
|
|
130
|
+
*/
|
|
131
|
+
label?: string;
|
|
132
|
+
/**
|
|
133
|
+
* The maximum number of characters allowed in the textarea field.
|
|
134
|
+
* If the `label` property is not set, this property will have no effect.
|
|
135
|
+
*/
|
|
136
|
+
maxLength?: number;
|
|
123
137
|
}
|
|
124
138
|
|
|
125
139
|
export { }
|
package/dist/index.js
CHANGED
|
@@ -1,125 +1,127 @@
|
|
|
1
|
-
import { LitElement as
|
|
2
|
-
import { property as
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
1
|
+
import { LitElement as w, html as I, nothing as B, unsafeCSS as N } from "lit";
|
|
2
|
+
import { property as h, query as V } from "lit/decorators.js";
|
|
3
|
+
import { live as A } from "lit/directives/live.js";
|
|
4
|
+
import { FormControlMixin as K, RtlMixin as G, wrapNativeEvent as H, validPropertyValues as F, defineCustomElement as U } from "@justeattakeaway/pie-webc-core";
|
|
5
|
+
import { ifDefined as O } from "lit/directives/if-defined.js";
|
|
6
|
+
import "@justeattakeaway/pie-form-label";
|
|
7
|
+
var z = typeof globalThis < "u" ? globalThis : typeof window < "u" ? window : typeof global < "u" ? global : typeof self < "u" ? self : {};
|
|
8
|
+
function X(t) {
|
|
9
|
+
return t && t.__esModule && Object.prototype.hasOwnProperty.call(t, "default") ? t.default : t;
|
|
9
10
|
}
|
|
10
|
-
var R = "Expected a function",
|
|
11
|
-
return
|
|
11
|
+
var R = "Expected a function", C = 0 / 0, J = "[object Symbol]", Q = /^\s+|\s+$/g, Y = /^[-+]0x[0-9a-f]+$/i, Z = /^0b[01]+$/i, ee = /^0o[0-7]+$/i, te = parseInt, ae = typeof z == "object" && z && z.Object === Object && z, re = typeof self == "object" && self && self.Object === Object && self, ie = ae || re || Function("return this")(), ne = Object.prototype, oe = ne.toString, se = Math.max, le = Math.min, L = function() {
|
|
12
|
+
return ie.Date.now();
|
|
12
13
|
};
|
|
13
|
-
function
|
|
14
|
-
var
|
|
15
|
-
if (typeof
|
|
14
|
+
function de(t, e, a) {
|
|
15
|
+
var r, i, u, l, s, p, g = 0, m = !1, v = !1, _ = !0;
|
|
16
|
+
if (typeof t != "function")
|
|
16
17
|
throw new TypeError(R);
|
|
17
|
-
|
|
18
|
-
function
|
|
19
|
-
var f =
|
|
20
|
-
return
|
|
18
|
+
e = W(e) || 0, k(a) && (m = !!a.leading, v = "maxWait" in a, u = v ? se(W(a.maxWait) || 0, e) : u, _ = "trailing" in a ? !!a.trailing : _);
|
|
19
|
+
function $(n) {
|
|
20
|
+
var f = r, b = i;
|
|
21
|
+
return r = i = void 0, g = n, l = t.apply(b, f), l;
|
|
21
22
|
}
|
|
22
|
-
function D(
|
|
23
|
-
return
|
|
23
|
+
function D(n) {
|
|
24
|
+
return g = n, s = setTimeout(y, e), m ? $(n) : l;
|
|
24
25
|
}
|
|
25
|
-
function P(
|
|
26
|
-
var f =
|
|
27
|
-
return v ?
|
|
26
|
+
function P(n) {
|
|
27
|
+
var f = n - p, b = n - g, E = e - f;
|
|
28
|
+
return v ? le(E, u - b) : E;
|
|
28
29
|
}
|
|
29
|
-
function
|
|
30
|
-
var f =
|
|
31
|
-
return
|
|
30
|
+
function S(n) {
|
|
31
|
+
var f = n - p, b = n - g;
|
|
32
|
+
return p === void 0 || f >= e || f < 0 || v && b >= u;
|
|
32
33
|
}
|
|
33
|
-
function
|
|
34
|
-
var
|
|
35
|
-
if (
|
|
36
|
-
return
|
|
37
|
-
|
|
34
|
+
function y() {
|
|
35
|
+
var n = L();
|
|
36
|
+
if (S(n))
|
|
37
|
+
return T(n);
|
|
38
|
+
s = setTimeout(y, P(n));
|
|
38
39
|
}
|
|
39
|
-
function
|
|
40
|
-
return
|
|
41
|
-
}
|
|
42
|
-
function L() {
|
|
43
|
-
o !== void 0 && clearTimeout(o), x = 0, n = h = r = o = void 0;
|
|
40
|
+
function T(n) {
|
|
41
|
+
return s = void 0, _ && r ? $(n) : (r = i = void 0, l);
|
|
44
42
|
}
|
|
45
43
|
function M() {
|
|
46
|
-
|
|
44
|
+
s !== void 0 && clearTimeout(s), g = 0, r = p = i = s = void 0;
|
|
45
|
+
}
|
|
46
|
+
function q() {
|
|
47
|
+
return s === void 0 ? l : T(L());
|
|
47
48
|
}
|
|
48
|
-
function
|
|
49
|
-
var
|
|
50
|
-
if (
|
|
51
|
-
if (
|
|
52
|
-
return D(
|
|
49
|
+
function j() {
|
|
50
|
+
var n = L(), f = S(n);
|
|
51
|
+
if (r = arguments, i = this, p = n, f) {
|
|
52
|
+
if (s === void 0)
|
|
53
|
+
return D(p);
|
|
53
54
|
if (v)
|
|
54
|
-
return
|
|
55
|
+
return s = setTimeout(y, e), $(p);
|
|
55
56
|
}
|
|
56
|
-
return
|
|
57
|
+
return s === void 0 && (s = setTimeout(y, e)), l;
|
|
57
58
|
}
|
|
58
|
-
return
|
|
59
|
+
return j.cancel = M, j.flush = q, j;
|
|
59
60
|
}
|
|
60
|
-
function
|
|
61
|
-
var
|
|
62
|
-
if (typeof
|
|
61
|
+
function ce(t, e, a) {
|
|
62
|
+
var r = !0, i = !0;
|
|
63
|
+
if (typeof t != "function")
|
|
63
64
|
throw new TypeError(R);
|
|
64
|
-
return
|
|
65
|
-
leading:
|
|
66
|
-
maxWait:
|
|
67
|
-
trailing:
|
|
65
|
+
return k(a) && (r = "leading" in a ? !!a.leading : r, i = "trailing" in a ? !!a.trailing : i), de(t, e, {
|
|
66
|
+
leading: r,
|
|
67
|
+
maxWait: e,
|
|
68
|
+
trailing: i
|
|
68
69
|
});
|
|
69
70
|
}
|
|
70
|
-
function
|
|
71
|
-
var
|
|
72
|
-
return !!
|
|
71
|
+
function k(t) {
|
|
72
|
+
var e = typeof t;
|
|
73
|
+
return !!t && (e == "object" || e == "function");
|
|
73
74
|
}
|
|
74
|
-
function
|
|
75
|
-
return !!
|
|
75
|
+
function he(t) {
|
|
76
|
+
return !!t && typeof t == "object";
|
|
76
77
|
}
|
|
77
|
-
function ue(
|
|
78
|
-
return typeof
|
|
78
|
+
function ue(t) {
|
|
79
|
+
return typeof t == "symbol" || he(t) && oe.call(t) == J;
|
|
79
80
|
}
|
|
80
|
-
function
|
|
81
|
-
if (typeof
|
|
82
|
-
return
|
|
83
|
-
if (ue(
|
|
84
|
-
return
|
|
85
|
-
if (
|
|
86
|
-
var
|
|
87
|
-
|
|
88
|
-
}
|
|
89
|
-
if (typeof
|
|
90
|
-
return
|
|
91
|
-
|
|
92
|
-
var a =
|
|
93
|
-
return a ||
|
|
81
|
+
function W(t) {
|
|
82
|
+
if (typeof t == "number")
|
|
83
|
+
return t;
|
|
84
|
+
if (ue(t))
|
|
85
|
+
return C;
|
|
86
|
+
if (k(t)) {
|
|
87
|
+
var e = typeof t.valueOf == "function" ? t.valueOf() : t;
|
|
88
|
+
t = k(e) ? e + "" : e;
|
|
89
|
+
}
|
|
90
|
+
if (typeof t != "string")
|
|
91
|
+
return t === 0 ? t : +t;
|
|
92
|
+
t = t.replace(Q, "");
|
|
93
|
+
var a = Z.test(t);
|
|
94
|
+
return a || ee.test(t) ? te(t.slice(2), a ? 2 : 8) : Y.test(t) ? C : +t;
|
|
94
95
|
}
|
|
95
|
-
var
|
|
96
|
-
const
|
|
97
|
-
`,
|
|
96
|
+
var pe = ce;
|
|
97
|
+
const fe = /* @__PURE__ */ X(pe), ge = `*,*:after,*:before{box-sizing:inherit}.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-d);--textarea-padding-block: var(--dt-spacing-c);--textarea-background-color: var(--dt-color-container-default);--textarea-border-color: var(--dt-color-interactive-form);--textarea-content-color: var(--dt-color-content-default);--textarea-height: calc((var(--textarea-line-height) * 2) + (var(--textarea-padding-block) * 2) + (var(--textarea-border-thickness) * 2));line-height:0}.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:var(--textarea-border-thickness) solid var(--textarea-border-color);background-color:var(--textarea-background-color);color:var(--textarea-content-color);border-radius:var(--dt-radius-rounded-c);block-size:var(--textarea-height);max-block-size:var(--textarea-max-height);min-block-size:var(--textarea-min-height);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[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)}@media (hover: hover){.c-textareaWrapper textarea:hover:not([disabled]){--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))))}}.c-textareaWrapper textarea:focus-visible{box-shadow:0 0 0 2px var(--dt-color-focus-inner),0 0 0 4px var(--dt-color-focus-outer);outline:none}.c-textareaWrapper[data-pie-size=large]{--textarea-padding-block: var(--dt-spacing-d)}.c-textareaWrapper[data-pie-size=small]{--textarea-padding-block: var(--dt-spacing-b)}.c-textareaWrapper[data-pie-resize=manual]{--textarea-resize: vertical;--textarea-min-height: calc((var(--textarea-line-height) * 1) + (var(--textarea-padding-block) * 2) + (var(--textarea-border-thickness) * 2))}@media (pointer: coarse){.c-textareaWrapper[data-pie-resize=manual]{--textarea-height: calc((var(--textarea-line-height) * 6) + (var(--textarea-padding-block) * 2) + (var(--textarea-border-thickness) * 2));--textarea-min-height: calc((var(--textarea-line-height) * 6) + (var(--textarea-padding-block) * 2) + (var(--textarea-border-thickness) * 2));--textarea-max-height: calc((var(--textarea-line-height) * 6) + (var(--textarea-padding-block) * 2) + (var(--textarea-border-thickness) * 2));--textarea-resize: none}}.c-textareaWrapper[data-pie-resize=auto]{--textarea-max-height: calc((var(--textarea-line-height) * 6) + (var(--textarea-padding-block) * 2) + (var(--textarea-border-thickness) * 2));--textarea-min-height: var(--textarea-height)}
|
|
98
|
+
`, ve = ["small", "medium", "large"], xe = ["auto", "manual"], c = {
|
|
98
99
|
disabled: !1,
|
|
99
100
|
size: "medium",
|
|
100
101
|
resize: "auto",
|
|
102
|
+
label: "",
|
|
101
103
|
value: "",
|
|
102
104
|
autoFocus: !1,
|
|
103
105
|
readonly: !1,
|
|
104
106
|
required: !1
|
|
105
107
|
};
|
|
106
|
-
var
|
|
107
|
-
for (var
|
|
108
|
-
(l =
|
|
109
|
-
return
|
|
108
|
+
var be = Object.defineProperty, me = Object.getOwnPropertyDescriptor, d = (t, e, a, r) => {
|
|
109
|
+
for (var i = r > 1 ? void 0 : r ? me(e, a) : e, u = t.length - 1, l; u >= 0; u--)
|
|
110
|
+
(l = t[u]) && (i = (r ? l(e, a, i) : l(i)) || i);
|
|
111
|
+
return r && i && be(e, a, i), i;
|
|
110
112
|
};
|
|
111
|
-
const
|
|
112
|
-
class
|
|
113
|
+
const x = "pie-textarea";
|
|
114
|
+
class o extends K(G(w)) {
|
|
113
115
|
constructor() {
|
|
114
|
-
super(...arguments), this.value = c.value, this.disabled = c.disabled, this.size = c.size, this.resize = c.resize, this.readonly = c.readonly, this.autoFocus = c.autoFocus, this.required = c.required, this._throttledResize =
|
|
116
|
+
super(...arguments), this.value = c.value, this.disabled = c.disabled, this.size = c.size, this.resize = c.resize, this.label = c.label, this.readonly = c.readonly, this.autoFocus = c.autoFocus, this.required = c.required, this._throttledResize = fe(() => {
|
|
115
117
|
this.resize === "auto" && (this._textarea.style.height = "auto", this._textarea.style.height = `${this._textarea.scrollHeight + 2}px`);
|
|
116
|
-
}, 100), this.handleInput = (
|
|
117
|
-
this.value =
|
|
118
|
-
}, this.handleChange = (
|
|
119
|
-
const a =
|
|
118
|
+
}, 100), this.handleInput = (e) => {
|
|
119
|
+
this.value = e.target.value, this.restrictInputLength(), this._internals.setFormValue(this.value), this.handleResize();
|
|
120
|
+
}, this.handleChange = (e) => {
|
|
121
|
+
const a = H(e);
|
|
120
122
|
this.dispatchEvent(a);
|
|
121
|
-
}, this.handleKeyDown = (
|
|
122
|
-
|
|
123
|
+
}, this.handleKeyDown = (e) => {
|
|
124
|
+
e.key === "Enter" && e.stopPropagation();
|
|
123
125
|
};
|
|
124
126
|
}
|
|
125
127
|
/**
|
|
@@ -135,8 +137,8 @@ class s extends A(K(F)) {
|
|
|
135
137
|
* or because the disabled state changed on a <fieldset> that's an ancestor of this element.
|
|
136
138
|
* @param disabled - The latest disabled state of the input.
|
|
137
139
|
*/
|
|
138
|
-
formDisabledCallback(
|
|
139
|
-
this.disabled =
|
|
140
|
+
formDisabledCallback(e) {
|
|
141
|
+
this.disabled = e;
|
|
140
142
|
}
|
|
141
143
|
/**
|
|
142
144
|
* Called when the form that owns this component is reset.
|
|
@@ -146,88 +148,108 @@ class s extends A(K(F)) {
|
|
|
146
148
|
this.value = c.value, this._internals.setFormValue(this.value);
|
|
147
149
|
}
|
|
148
150
|
firstUpdated() {
|
|
149
|
-
this._internals.setFormValue(this.value), this._textarea.addEventListener("keydown", this.handleKeyDown);
|
|
151
|
+
this.restrictInputLength(), this._internals.setFormValue(this.value), this._textarea.addEventListener("keydown", this.handleKeyDown);
|
|
150
152
|
}
|
|
151
153
|
handleResize() {
|
|
152
154
|
this._throttledResize();
|
|
153
155
|
}
|
|
154
|
-
|
|
155
|
-
|
|
156
|
+
restrictInputLength() {
|
|
157
|
+
if (this.label.length && this.maxLength && this.value.length > this.maxLength) {
|
|
158
|
+
const e = this.value.slice(0, this.maxLength);
|
|
159
|
+
this._textarea.value = e, this.value = e;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
updated(e) {
|
|
163
|
+
e.has("value") && (this.restrictInputLength(), this._internals.setFormValue(this.value)), this.resize === "auto" && (e.has("resize") || e.has("size")) && this.handleResize();
|
|
156
164
|
}
|
|
157
165
|
disconnectedCallback() {
|
|
158
166
|
this._textarea.removeEventListener("keydown", this.handleKeyDown);
|
|
159
167
|
}
|
|
168
|
+
renderLabel(e, a) {
|
|
169
|
+
const r = a ? `${this.value.length}/${a}` : void 0;
|
|
170
|
+
return e != null && e.length ? I`<pie-form-label for="${x}" trailing=${O(r)}>${e}</pie-form-label>` : B;
|
|
171
|
+
}
|
|
160
172
|
render() {
|
|
161
173
|
const {
|
|
162
|
-
disabled:
|
|
174
|
+
disabled: e,
|
|
163
175
|
resize: a,
|
|
164
|
-
size:
|
|
165
|
-
autocomplete:
|
|
166
|
-
autoFocus:
|
|
176
|
+
size: r,
|
|
177
|
+
autocomplete: i,
|
|
178
|
+
autoFocus: u,
|
|
167
179
|
name: l,
|
|
168
|
-
readonly:
|
|
169
|
-
value:
|
|
170
|
-
required:
|
|
180
|
+
readonly: s,
|
|
181
|
+
value: p,
|
|
182
|
+
required: g,
|
|
183
|
+
label: m,
|
|
184
|
+
maxLength: v
|
|
171
185
|
} = this;
|
|
172
|
-
return
|
|
186
|
+
return I`
|
|
173
187
|
<div
|
|
174
188
|
class="c-textareaWrapper"
|
|
175
189
|
data-test-id="pie-textarea-wrapper"
|
|
176
|
-
data-pie-size="${
|
|
190
|
+
data-pie-size="${r}"
|
|
177
191
|
data-pie-resize="${a}">
|
|
192
|
+
${this.renderLabel(m, v)}
|
|
178
193
|
<textarea
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
?
|
|
185
|
-
?
|
|
194
|
+
id="${x}"
|
|
195
|
+
data-test-id="${x}"
|
|
196
|
+
name=${O(l)}
|
|
197
|
+
autocomplete=${O(i)}
|
|
198
|
+
.value=${A(p)}
|
|
199
|
+
?autofocus=${u}
|
|
200
|
+
?readonly=${s}
|
|
201
|
+
?required=${g}
|
|
202
|
+
?disabled=${e}
|
|
186
203
|
@input=${this.handleInput}
|
|
187
204
|
@change=${this.handleChange}
|
|
188
|
-
data-test-id="pie-textarea"
|
|
189
205
|
></textarea>
|
|
190
206
|
</div>`;
|
|
191
207
|
}
|
|
192
208
|
}
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
],
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
],
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
],
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
],
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
],
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
],
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
],
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
],
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
],
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
],
|
|
227
|
-
|
|
209
|
+
o.shadowRootOptions = { ...w.shadowRootOptions, delegatesFocus: !0 };
|
|
210
|
+
o.styles = N(ge);
|
|
211
|
+
d([
|
|
212
|
+
h({ type: String })
|
|
213
|
+
], o.prototype, "value", 2);
|
|
214
|
+
d([
|
|
215
|
+
h({ type: Boolean, reflect: !0 })
|
|
216
|
+
], o.prototype, "disabled", 2);
|
|
217
|
+
d([
|
|
218
|
+
h({ type: String }),
|
|
219
|
+
F(x, ve, c.size)
|
|
220
|
+
], o.prototype, "size", 2);
|
|
221
|
+
d([
|
|
222
|
+
h({ type: String }),
|
|
223
|
+
F(x, xe, c.resize)
|
|
224
|
+
], o.prototype, "resize", 2);
|
|
225
|
+
d([
|
|
226
|
+
h({ type: String })
|
|
227
|
+
], o.prototype, "label", 2);
|
|
228
|
+
d([
|
|
229
|
+
h({ type: Number })
|
|
230
|
+
], o.prototype, "maxLength", 2);
|
|
231
|
+
d([
|
|
232
|
+
h({ type: Boolean })
|
|
233
|
+
], o.prototype, "readonly", 2);
|
|
234
|
+
d([
|
|
235
|
+
h({ type: Boolean })
|
|
236
|
+
], o.prototype, "autoFocus", 2);
|
|
237
|
+
d([
|
|
238
|
+
h({ type: Boolean })
|
|
239
|
+
], o.prototype, "required", 2);
|
|
240
|
+
d([
|
|
241
|
+
h({ type: String })
|
|
242
|
+
], o.prototype, "name", 2);
|
|
243
|
+
d([
|
|
244
|
+
h({ type: String })
|
|
245
|
+
], o.prototype, "autocomplete", 2);
|
|
246
|
+
d([
|
|
247
|
+
V("textarea")
|
|
248
|
+
], o.prototype, "_textarea", 2);
|
|
249
|
+
U(x, o);
|
|
228
250
|
export {
|
|
229
|
-
|
|
251
|
+
o as PieTextarea,
|
|
230
252
|
c as defaultProps,
|
|
231
|
-
|
|
232
|
-
|
|
253
|
+
xe as resizeModes,
|
|
254
|
+
ve as sizes
|
|
233
255
|
};
|
package/dist/react.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ import type { CSSResult } from 'lit';
|
|
|
3
3
|
import type { FormControlInterface } from '@justeattakeaway/pie-webc-core';
|
|
4
4
|
import type { GenericConstructor } from '@justeattakeaway/pie-webc-core';
|
|
5
5
|
import type { LitElement } from 'lit';
|
|
6
|
+
import type { nothing } from 'lit';
|
|
6
7
|
import type { PropertyValues } from 'lit';
|
|
7
8
|
import * as React_2 from 'react';
|
|
8
9
|
import type { RTLInterface } from '@justeattakeaway/pie-webc-core';
|
|
@@ -11,7 +12,7 @@ import type { TemplateResult } from 'lit-html';
|
|
|
11
12
|
/**
|
|
12
13
|
* The default values for the `TextareaProps` that are required (i.e. they have a fallback value in the component).
|
|
13
14
|
*/
|
|
14
|
-
declare type DefaultProps = ComponentDefaultProps<TextareaProps, keyof Omit<TextareaProps, 'name' | 'autocomplete'>>;
|
|
15
|
+
declare type DefaultProps = ComponentDefaultProps<TextareaProps, keyof Omit<TextareaProps, 'name' | 'autocomplete' | 'maxLength'>>;
|
|
15
16
|
|
|
16
17
|
/**
|
|
17
18
|
* Default values for optional properties that have default fallback values in the component.
|
|
@@ -35,6 +36,8 @@ declare class PieTextarea_2 extends PieTextarea_base implements TextareaProps {
|
|
|
35
36
|
disabled: boolean;
|
|
36
37
|
size: "small" | "medium" | "large";
|
|
37
38
|
resize: "auto" | "manual";
|
|
39
|
+
label: string;
|
|
40
|
+
maxLength: TextareaProps['maxLength'];
|
|
38
41
|
readonly: boolean;
|
|
39
42
|
autoFocus: boolean;
|
|
40
43
|
required: boolean;
|
|
@@ -61,6 +64,7 @@ declare class PieTextarea_2 extends PieTextarea_base implements TextareaProps {
|
|
|
61
64
|
formResetCallback(): void;
|
|
62
65
|
protected firstUpdated(): void;
|
|
63
66
|
private handleResize;
|
|
67
|
+
private restrictInputLength;
|
|
64
68
|
protected updated(changedProperties: PropertyValues<this>): void;
|
|
65
69
|
/**
|
|
66
70
|
* Handles data processing in response to the input event. The native input event is left to bubble up.
|
|
@@ -70,6 +74,7 @@ declare class PieTextarea_2 extends PieTextarea_base implements TextareaProps {
|
|
|
70
74
|
private handleChange;
|
|
71
75
|
private handleKeyDown;
|
|
72
76
|
disconnectedCallback(): void;
|
|
77
|
+
renderLabel(label: string, maxLength?: number): TemplateResult<1> | typeof nothing;
|
|
73
78
|
render(): TemplateResult<1>;
|
|
74
79
|
static styles: CSSResult;
|
|
75
80
|
}
|
|
@@ -130,6 +135,15 @@ export declare interface TextareaProps {
|
|
|
130
135
|
* If true, the textarea is required to have a value before submitting the form. If there is no value, then the component validity state will be invalid.
|
|
131
136
|
*/
|
|
132
137
|
required?: boolean;
|
|
138
|
+
/**
|
|
139
|
+
* The label text for the textarea field.
|
|
140
|
+
*/
|
|
141
|
+
label?: string;
|
|
142
|
+
/**
|
|
143
|
+
* The maximum number of characters allowed in the textarea field.
|
|
144
|
+
* If the `label` property is not set, this property will have no effect.
|
|
145
|
+
*/
|
|
146
|
+
maxLength?: number;
|
|
133
147
|
}
|
|
134
148
|
|
|
135
149
|
export { }
|
package/dist/react.js
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import * as e from "react";
|
|
2
2
|
import { createComponent as t } from "@lit/react";
|
|
3
3
|
import { PieTextarea as a } from "./index.js";
|
|
4
|
-
import { defaultProps as
|
|
4
|
+
import { defaultProps as l, resizeModes as d, sizes as g } from "./index.js";
|
|
5
5
|
import "lit";
|
|
6
6
|
import "lit/decorators.js";
|
|
7
|
-
import "lit/directives/if-defined.js";
|
|
8
7
|
import "lit/directives/live.js";
|
|
9
8
|
import "@justeattakeaway/pie-webc-core";
|
|
9
|
+
import "lit/directives/if-defined.js";
|
|
10
|
+
import "@justeattakeaway/pie-form-label";
|
|
10
11
|
const r = t({
|
|
11
12
|
displayName: "PieTextarea",
|
|
12
13
|
elementClass: a,
|
|
@@ -18,10 +19,10 @@ const r = t({
|
|
|
18
19
|
onChange: "change"
|
|
19
20
|
// when the textarea value is changed.
|
|
20
21
|
}
|
|
21
|
-
}),
|
|
22
|
+
}), P = r;
|
|
22
23
|
export {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
24
|
+
P as PieTextarea,
|
|
25
|
+
l as defaultProps,
|
|
26
|
+
d as resizeModes,
|
|
27
|
+
g as sizes
|
|
27
28
|
};
|
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.
|
|
4
|
+
"version": "0.6.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"module": "dist/index.js",
|
|
@@ -41,6 +41,7 @@
|
|
|
41
41
|
"cem-plugin-module-file-extensions": "0.0.5"
|
|
42
42
|
},
|
|
43
43
|
"dependencies": {
|
|
44
|
+
"@justeattakeaway/pie-form-label": "0.14.0",
|
|
44
45
|
"@justeattakeaway/pie-webc-core": "0.24.0",
|
|
45
46
|
"lodash.throttle": "4.1.1"
|
|
46
47
|
},
|
package/src/defs.ts
CHANGED
|
@@ -54,12 +54,23 @@ export interface TextareaProps {
|
|
|
54
54
|
* If true, the textarea is required to have a value before submitting the form. If there is no value, then the component validity state will be invalid.
|
|
55
55
|
*/
|
|
56
56
|
required?: boolean;
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* The label text for the textarea field.
|
|
60
|
+
*/
|
|
61
|
+
label?: string;
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* The maximum number of characters allowed in the textarea field.
|
|
65
|
+
* If the `label` property is not set, this property will have no effect.
|
|
66
|
+
*/
|
|
67
|
+
maxLength?: number;
|
|
57
68
|
}
|
|
58
69
|
|
|
59
70
|
/**
|
|
60
71
|
* The default values for the `TextareaProps` that are required (i.e. they have a fallback value in the component).
|
|
61
72
|
*/
|
|
62
|
-
type DefaultProps = ComponentDefaultProps<TextareaProps, keyof Omit<TextareaProps, 'name'| 'autocomplete'>>;
|
|
73
|
+
type DefaultProps = ComponentDefaultProps<TextareaProps, keyof Omit<TextareaProps, 'name' | 'autocomplete' | 'maxLength'>>;
|
|
63
74
|
|
|
64
75
|
/**
|
|
65
76
|
* Default values for optional properties that have default fallback values in the component.
|
|
@@ -68,6 +79,7 @@ export const defaultProps: DefaultProps = {
|
|
|
68
79
|
disabled: false,
|
|
69
80
|
size: 'medium',
|
|
70
81
|
resize: 'auto',
|
|
82
|
+
label: '',
|
|
71
83
|
value: '',
|
|
72
84
|
autoFocus: false,
|
|
73
85
|
readonly: false,
|
package/src/index.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import {
|
|
2
|
-
LitElement, html, unsafeCSS, PropertyValues,
|
|
2
|
+
LitElement, html, unsafeCSS, PropertyValues, nothing,
|
|
3
3
|
} from 'lit';
|
|
4
|
+
|
|
4
5
|
import { property, query } from 'lit/decorators.js';
|
|
5
|
-
import { ifDefined } from 'lit/directives/if-defined.js';
|
|
6
6
|
import { live } from 'lit/directives/live.js';
|
|
7
7
|
import throttle from 'lodash.throttle';
|
|
8
8
|
|
|
@@ -10,11 +10,14 @@ import {
|
|
|
10
10
|
validPropertyValues, RtlMixin, defineCustomElement, FormControlMixin, wrapNativeEvent,
|
|
11
11
|
} from '@justeattakeaway/pie-webc-core';
|
|
12
12
|
|
|
13
|
+
import { ifDefined } from 'lit/directives/if-defined.js';
|
|
13
14
|
import styles from './textarea.scss?inline';
|
|
14
15
|
import {
|
|
15
16
|
TextareaProps, defaultProps, sizes, resizeModes,
|
|
16
17
|
} from './defs';
|
|
17
18
|
|
|
19
|
+
import '@justeattakeaway/pie-form-label';
|
|
20
|
+
|
|
18
21
|
// Valid values available to consumers
|
|
19
22
|
export * from './defs';
|
|
20
23
|
|
|
@@ -42,6 +45,12 @@ export class PieTextarea extends FormControlMixin(RtlMixin(LitElement)) implemen
|
|
|
42
45
|
@validPropertyValues(componentSelector, resizeModes, defaultProps.resize)
|
|
43
46
|
public resize = defaultProps.resize;
|
|
44
47
|
|
|
48
|
+
@property({ type: String })
|
|
49
|
+
public label = defaultProps.label;
|
|
50
|
+
|
|
51
|
+
@property({ type: Number })
|
|
52
|
+
public maxLength: TextareaProps['maxLength'];
|
|
53
|
+
|
|
45
54
|
@property({ type: Boolean })
|
|
46
55
|
public readonly = defaultProps.readonly;
|
|
47
56
|
|
|
@@ -96,6 +105,7 @@ export class PieTextarea extends FormControlMixin(RtlMixin(LitElement)) implemen
|
|
|
96
105
|
}
|
|
97
106
|
|
|
98
107
|
protected firstUpdated (): void {
|
|
108
|
+
this.restrictInputLength();
|
|
99
109
|
this._internals.setFormValue(this.value);
|
|
100
110
|
|
|
101
111
|
this._textarea.addEventListener('keydown', this.handleKeyDown);
|
|
@@ -105,14 +115,25 @@ export class PieTextarea extends FormControlMixin(RtlMixin(LitElement)) implemen
|
|
|
105
115
|
this._throttledResize();
|
|
106
116
|
}
|
|
107
117
|
|
|
108
|
-
|
|
109
|
-
if (this.
|
|
110
|
-
this.
|
|
118
|
+
private restrictInputLength () {
|
|
119
|
+
if (this.label.length && this.maxLength && this.value.length > this.maxLength) {
|
|
120
|
+
const trimmedValue = this.value.slice(0, this.maxLength);
|
|
121
|
+
// Ensures that the internal text area is correctly trimmed and synced with our value.
|
|
122
|
+
// The live() directive does not solve this for us.
|
|
123
|
+
this._textarea.value = trimmedValue;
|
|
124
|
+
this.value = trimmedValue;
|
|
111
125
|
}
|
|
126
|
+
}
|
|
112
127
|
|
|
128
|
+
protected updated (changedProperties: PropertyValues<this>) {
|
|
113
129
|
if (changedProperties.has('value')) {
|
|
130
|
+
this.restrictInputLength();
|
|
114
131
|
this._internals.setFormValue(this.value);
|
|
115
132
|
}
|
|
133
|
+
|
|
134
|
+
if (this.resize === 'auto' && (changedProperties.has('resize') || changedProperties.has('size'))) {
|
|
135
|
+
this.handleResize();
|
|
136
|
+
}
|
|
116
137
|
}
|
|
117
138
|
|
|
118
139
|
/**
|
|
@@ -121,6 +142,7 @@ export class PieTextarea extends FormControlMixin(RtlMixin(LitElement)) implemen
|
|
|
121
142
|
*/
|
|
122
143
|
private handleInput = (event: InputEvent) => {
|
|
123
144
|
this.value = (event.target as HTMLTextAreaElement).value;
|
|
145
|
+
this.restrictInputLength();
|
|
124
146
|
this._internals.setFormValue(this.value);
|
|
125
147
|
|
|
126
148
|
this.handleResize();
|
|
@@ -146,6 +168,14 @@ export class PieTextarea extends FormControlMixin(RtlMixin(LitElement)) implemen
|
|
|
146
168
|
this._textarea.removeEventListener('keydown', this.handleKeyDown);
|
|
147
169
|
}
|
|
148
170
|
|
|
171
|
+
renderLabel (label: string, maxLength?: number) {
|
|
172
|
+
const characterCount = maxLength ? `${this.value.length}/${maxLength}` : undefined;
|
|
173
|
+
|
|
174
|
+
return label?.length
|
|
175
|
+
? html`<pie-form-label for="${componentSelector}" trailing=${ifDefined(characterCount)}>${label}</pie-form-label>`
|
|
176
|
+
: nothing;
|
|
177
|
+
}
|
|
178
|
+
|
|
149
179
|
render () {
|
|
150
180
|
const {
|
|
151
181
|
disabled,
|
|
@@ -157,6 +187,8 @@ export class PieTextarea extends FormControlMixin(RtlMixin(LitElement)) implemen
|
|
|
157
187
|
readonly,
|
|
158
188
|
value,
|
|
159
189
|
required,
|
|
190
|
+
label,
|
|
191
|
+
maxLength,
|
|
160
192
|
} = this;
|
|
161
193
|
|
|
162
194
|
return html`
|
|
@@ -165,7 +197,10 @@ export class PieTextarea extends FormControlMixin(RtlMixin(LitElement)) implemen
|
|
|
165
197
|
data-test-id="pie-textarea-wrapper"
|
|
166
198
|
data-pie-size="${size}"
|
|
167
199
|
data-pie-resize="${resize}">
|
|
200
|
+
${this.renderLabel(label, maxLength)}
|
|
168
201
|
<textarea
|
|
202
|
+
id="${componentSelector}"
|
|
203
|
+
data-test-id="${componentSelector}"
|
|
169
204
|
name=${ifDefined(name)}
|
|
170
205
|
autocomplete=${ifDefined(autocomplete)}
|
|
171
206
|
.value=${live(value)}
|
|
@@ -175,7 +210,6 @@ export class PieTextarea extends FormControlMixin(RtlMixin(LitElement)) implemen
|
|
|
175
210
|
?disabled=${disabled}
|
|
176
211
|
@input=${this.handleInput}
|
|
177
212
|
@change=${this.handleChange}
|
|
178
|
-
data-test-id="pie-textarea"
|
|
179
213
|
></textarea>
|
|
180
214
|
</div>`;
|
|
181
215
|
}
|