@justeattakeaway/pie-textarea 0.0.0-snapshot-release-20240708103513
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 +93 -0
- package/custom-elements.json +173 -0
- package/declaration.d.ts +9 -0
- package/dist/index.d.ts +61 -0
- package/dist/index.js +68 -0
- package/dist/react.d.ts +66 -0
- package/dist/react.js +20 -0
- package/package.json +52 -0
- package/src/defs-react.ts +3 -0
- package/src/defs.ts +37 -0
- package/src/index.ts +82 -0
- package/src/react.ts +19 -0
- package/src/textarea.scss +93 -0
package/README.md
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img align="center" src="../../../readme_image.png" height="200" alt="">
|
|
3
|
+
</p>
|
|
4
|
+
|
|
5
|
+
<p align="center">
|
|
6
|
+
<a href="https://www.npmjs.com/@justeattakeaway/pie-textarea">
|
|
7
|
+
<img alt="GitHub Workflow Status" src="https://img.shields.io/npm/v/@justeattakeaway/pie-textarea.svg">
|
|
8
|
+
</a>
|
|
9
|
+
</p>
|
|
10
|
+
|
|
11
|
+
# Table of Contents
|
|
12
|
+
|
|
13
|
+
1. [Introduction](#pie-textarea)
|
|
14
|
+
2. [Installation](#installation)
|
|
15
|
+
3. [Importing the component](#importing-the-component)
|
|
16
|
+
4. [Peer Dependencies](#peer-dependencies)
|
|
17
|
+
5. [Props](#props)
|
|
18
|
+
6. [Contributing](#contributing)
|
|
19
|
+
|
|
20
|
+
## pie-textarea
|
|
21
|
+
|
|
22
|
+
`pie-textarea` is a Web Component built using the Lit library.
|
|
23
|
+
|
|
24
|
+
This component can be easily integrated into various frontend frameworks and customized through a set of properties.
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
## Installation
|
|
28
|
+
|
|
29
|
+
To install `pie-textarea` in your application, run the following on your command line:
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
# npm
|
|
33
|
+
$ npm i @justeattakeaway/pie-textarea
|
|
34
|
+
|
|
35
|
+
# yarn
|
|
36
|
+
$ yarn add @justeattakeaway/pie-textarea
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
For full information on using PIE components as part of an application, check out the [Getting Started Guide](https://github.com/justeattakeaway/pie/wiki/Getting-started-with-PIE-Web-Components).
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
### Importing the component
|
|
43
|
+
|
|
44
|
+
#### JavaScript
|
|
45
|
+
```js
|
|
46
|
+
// Default – for Native JS Applications, Vue, Angular, Svelte, etc.
|
|
47
|
+
import { PieTextarea } from '@justeattakeaway/pie-textarea';
|
|
48
|
+
|
|
49
|
+
// If you don't need to reference the imported object, you can simply
|
|
50
|
+
// import the module which registers the component as a custom element.
|
|
51
|
+
import '@justeattakeaway/pie-textarea';
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
#### React
|
|
55
|
+
```js
|
|
56
|
+
// React
|
|
57
|
+
// For React, you will need to import our React-specific component build
|
|
58
|
+
// which wraps the web component using @lit/react
|
|
59
|
+
import { PieTextarea } from '@justeattakeaway/pie-textarea/dist/react';
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
> [!NOTE]
|
|
63
|
+
> When using the React version of the component, please make sure to also
|
|
64
|
+
> include React as a [peer dependency](#peer-dependencies) in your project.
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
## Peer Dependencies
|
|
68
|
+
|
|
69
|
+
> [!IMPORTANT]
|
|
70
|
+
> When using `pie-textarea`, you will also need to include a couple of dependencies to ensure the component renders as expected. See [the PIE Wiki](https://github.com/justeattakeaway/pie/wiki/Getting-started-with-PIE-Web-Components#expected-dependencies) for more information and how to include these in your application.
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
## Props
|
|
74
|
+
|
|
75
|
+
| Property | Type | Default | Description |
|
|
76
|
+
| --- | --- | --- | --- |
|
|
77
|
+
| `disabled` | `boolean` | `false` | Indicates whether or not the textarea is disabled. |
|
|
78
|
+
| `size` | `"small"`, `"medium"`, `"large"` | `"medium"` | The size of the textarea field. |
|
|
79
|
+
| `resize` | `"auto"`, `"manual"` | `"auto"` | Controls the resizing behaviour of the textarea. |
|
|
80
|
+
|
|
81
|
+
In your markup or JSX, you can then use these to set the properties for the `pie-textarea` component:
|
|
82
|
+
|
|
83
|
+
```html
|
|
84
|
+
<!-- Native HTML -->
|
|
85
|
+
<pie-textarea></pie-textarea>
|
|
86
|
+
|
|
87
|
+
<!-- JSX -->
|
|
88
|
+
<PieTextarea></PieTextarea>
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## Contributing
|
|
92
|
+
|
|
93
|
+
Check out our [contributing guide](https://github.com/justeattakeaway/pie/wiki/Contributing-Guide) for more information on [local development](https://github.com/justeattakeaway/pie/wiki/Contributing-Guide#local-development) and how to run specific [component tests](https://github.com/justeattakeaway/pie/wiki/Contributing-Guide#testing).
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": "1.0.0",
|
|
3
|
+
"readme": "",
|
|
4
|
+
"modules": [
|
|
5
|
+
{
|
|
6
|
+
"kind": "javascript-module",
|
|
7
|
+
"path": "src/defs-react.js",
|
|
8
|
+
"declarations": [],
|
|
9
|
+
"exports": []
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
"kind": "javascript-module",
|
|
13
|
+
"path": "src/defs.js",
|
|
14
|
+
"declarations": [
|
|
15
|
+
{
|
|
16
|
+
"kind": "variable",
|
|
17
|
+
"name": "sizes",
|
|
18
|
+
"type": {
|
|
19
|
+
"text": "['small', 'medium', 'large']"
|
|
20
|
+
},
|
|
21
|
+
"default": "['small', 'medium', 'large']"
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"kind": "variable",
|
|
25
|
+
"name": "resizeModes",
|
|
26
|
+
"type": {
|
|
27
|
+
"text": "['auto', 'manual']"
|
|
28
|
+
},
|
|
29
|
+
"default": "['auto', 'manual']"
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
"kind": "variable",
|
|
33
|
+
"name": "defaultProps",
|
|
34
|
+
"type": {
|
|
35
|
+
"text": "DefaultProps"
|
|
36
|
+
},
|
|
37
|
+
"default": "{\n disabled: false,\n size: 'medium',\n resize: 'auto',\n}",
|
|
38
|
+
"description": "Default values for optional properties that have default fallback values in the component."
|
|
39
|
+
}
|
|
40
|
+
],
|
|
41
|
+
"exports": [
|
|
42
|
+
{
|
|
43
|
+
"kind": "js",
|
|
44
|
+
"name": "sizes",
|
|
45
|
+
"declaration": {
|
|
46
|
+
"name": "sizes",
|
|
47
|
+
"module": "src/defs.js"
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
"kind": "js",
|
|
52
|
+
"name": "resizeModes",
|
|
53
|
+
"declaration": {
|
|
54
|
+
"name": "resizeModes",
|
|
55
|
+
"module": "src/defs.js"
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
"kind": "js",
|
|
60
|
+
"name": "defaultProps",
|
|
61
|
+
"declaration": {
|
|
62
|
+
"name": "defaultProps",
|
|
63
|
+
"module": "src/defs.js"
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
]
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
"kind": "javascript-module",
|
|
70
|
+
"path": "src/index.js",
|
|
71
|
+
"declarations": [
|
|
72
|
+
{
|
|
73
|
+
"kind": "class",
|
|
74
|
+
"description": "",
|
|
75
|
+
"name": "PieTextarea",
|
|
76
|
+
"members": [
|
|
77
|
+
{
|
|
78
|
+
"kind": "field",
|
|
79
|
+
"name": "shadowRootOptions",
|
|
80
|
+
"type": {
|
|
81
|
+
"text": "object"
|
|
82
|
+
},
|
|
83
|
+
"static": true,
|
|
84
|
+
"default": "{ ...LitElement.shadowRootOptions, delegatesFocus: true }"
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
"kind": "field",
|
|
88
|
+
"name": "disabled",
|
|
89
|
+
"type": {
|
|
90
|
+
"text": "TextareaProps['disabled'] | undefined"
|
|
91
|
+
},
|
|
92
|
+
"privacy": "public",
|
|
93
|
+
"attribute": "disabled",
|
|
94
|
+
"reflects": true
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
"kind": "field",
|
|
98
|
+
"name": "size",
|
|
99
|
+
"privacy": "public",
|
|
100
|
+
"attribute": "size"
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
"kind": "field",
|
|
104
|
+
"name": "resize",
|
|
105
|
+
"privacy": "public",
|
|
106
|
+
"attribute": "resize"
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
"kind": "field",
|
|
110
|
+
"name": "_textarea",
|
|
111
|
+
"type": {
|
|
112
|
+
"text": "HTMLTextAreaElement"
|
|
113
|
+
},
|
|
114
|
+
"privacy": "private"
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
"kind": "method",
|
|
118
|
+
"name": "handleResize",
|
|
119
|
+
"privacy": "private"
|
|
120
|
+
}
|
|
121
|
+
],
|
|
122
|
+
"attributes": [
|
|
123
|
+
{
|
|
124
|
+
"name": "disabled",
|
|
125
|
+
"type": {
|
|
126
|
+
"text": "TextareaProps['disabled'] | undefined"
|
|
127
|
+
},
|
|
128
|
+
"fieldName": "disabled"
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
"name": "size",
|
|
132
|
+
"fieldName": "size"
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
"name": "resize",
|
|
136
|
+
"fieldName": "resize"
|
|
137
|
+
}
|
|
138
|
+
],
|
|
139
|
+
"mixins": [
|
|
140
|
+
{
|
|
141
|
+
"name": "RtlMixin",
|
|
142
|
+
"package": "@justeattakeaway/pie-webc-core"
|
|
143
|
+
}
|
|
144
|
+
],
|
|
145
|
+
"superclass": {
|
|
146
|
+
"name": "LitElement",
|
|
147
|
+
"package": "lit"
|
|
148
|
+
},
|
|
149
|
+
"tagName": "pie-textarea",
|
|
150
|
+
"customElement": true
|
|
151
|
+
}
|
|
152
|
+
],
|
|
153
|
+
"exports": [
|
|
154
|
+
{
|
|
155
|
+
"kind": "js",
|
|
156
|
+
"name": "*",
|
|
157
|
+
"declaration": {
|
|
158
|
+
"name": "*",
|
|
159
|
+
"package": "./defs"
|
|
160
|
+
}
|
|
161
|
+
},
|
|
162
|
+
{
|
|
163
|
+
"kind": "js",
|
|
164
|
+
"name": "PieTextarea",
|
|
165
|
+
"declaration": {
|
|
166
|
+
"name": "PieTextarea",
|
|
167
|
+
"module": "src/index.js"
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
]
|
|
171
|
+
}
|
|
172
|
+
]
|
|
173
|
+
}
|
package/declaration.d.ts
ADDED
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { ComponentDefaultPropsGeneric } from '@justeattakeaway/pie-webc-core';
|
|
2
|
+
import type { CSSResult } from 'lit';
|
|
3
|
+
import type { GenericConstructor } from '@justeattakeaway/pie-webc-core';
|
|
4
|
+
import type { LitElement } from 'lit';
|
|
5
|
+
import type { PropertyValues } from 'lit';
|
|
6
|
+
import type { RTLInterface } from '@justeattakeaway/pie-webc-core';
|
|
7
|
+
import type { TemplateResult } from 'lit-html';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* The default values for the `TextareaProps` that are required (i.e. they have a fallback value in the component).
|
|
11
|
+
*/
|
|
12
|
+
declare type DefaultProps = ComponentDefaultPropsGeneric<TextareaProps, 'disabled' | 'size' | 'resize'>;
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Default values for optional properties that have default fallback values in the component.
|
|
16
|
+
*/
|
|
17
|
+
export declare const defaultProps: DefaultProps;
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* @tagname pie-textarea
|
|
21
|
+
*/
|
|
22
|
+
export declare class PieTextarea extends PieTextarea_base implements TextareaProps {
|
|
23
|
+
static shadowRootOptions: {
|
|
24
|
+
delegatesFocus: boolean;
|
|
25
|
+
mode: ShadowRootMode;
|
|
26
|
+
slotAssignment?: SlotAssignmentMode | undefined;
|
|
27
|
+
};
|
|
28
|
+
disabled?: TextareaProps['disabled'];
|
|
29
|
+
size: "small" | "medium" | "large";
|
|
30
|
+
resize: "auto" | "manual";
|
|
31
|
+
private _textarea;
|
|
32
|
+
private handleResize;
|
|
33
|
+
updated(changedProperties: PropertyValues<this>): void;
|
|
34
|
+
render(): TemplateResult<1>;
|
|
35
|
+
static styles: CSSResult;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
declare const PieTextarea_base: GenericConstructor<RTLInterface> & typeof LitElement;
|
|
39
|
+
|
|
40
|
+
export declare const resizeModes: readonly ["auto", "manual"];
|
|
41
|
+
|
|
42
|
+
export declare const sizes: readonly ["small", "medium", "large"];
|
|
43
|
+
|
|
44
|
+
export declare interface TextareaProps {
|
|
45
|
+
/**
|
|
46
|
+
* Same as the HTML disabled attribute - indicates whether the textarea is disabled.
|
|
47
|
+
*/
|
|
48
|
+
disabled?: boolean;
|
|
49
|
+
/**
|
|
50
|
+
* The size of the textarea field. Can be `small`, `medium` or `large`. Defaults to `medium`.
|
|
51
|
+
*/
|
|
52
|
+
size?: typeof sizes[number];
|
|
53
|
+
/**
|
|
54
|
+
* The resize mode of the textarea. Can be `auto` or `manual`. Defaults to `auto`.
|
|
55
|
+
* When set to `auto`, the textarea will resize vertically as needed.
|
|
56
|
+
* When set to `manual`, the textarea will not resize automatically but can be resized by the user.
|
|
57
|
+
*/
|
|
58
|
+
resize?: typeof resizeModes[number];
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export { }
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { LitElement as p, html as v, unsafeCSS as g } from "lit";
|
|
2
|
+
import { property as c, query as b } from "lit/decorators.js";
|
|
3
|
+
import { RtlMixin as u, validPropertyValues as h, defineCustomElement as z } from "@justeattakeaway/pie-webc-core";
|
|
4
|
+
const m = `*,*: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-base: var(--dt-spacing-c);--textarea-padding-block-large: var(--dt-spacing-d);--textarea-padding-block-small: var(--dt-spacing-b);--textarea-padding-block: var(--textarea-padding-block-base);--textarea-inner-height-base: calc(var(--textarea-line-height) * 2);--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-inner-height-base) + (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(--textarea-padding-block-large)}.c-textareaWrapper[data-pie-size=small]{--textarea-padding-block: var(--textarea-padding-block-small)}.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)}
|
|
5
|
+
`, f = ["small", "medium", "large"], k = ["auto", "manual"], o = {
|
|
6
|
+
disabled: !1,
|
|
7
|
+
size: "medium",
|
|
8
|
+
resize: "auto"
|
|
9
|
+
};
|
|
10
|
+
var y = Object.defineProperty, W = Object.getOwnPropertyDescriptor, d = (n, e, i, r) => {
|
|
11
|
+
for (var a = r > 1 ? void 0 : r ? W(e, i) : e, s = n.length - 1, l; s >= 0; s--)
|
|
12
|
+
(l = n[s]) && (a = (r ? l(e, i, a) : l(a)) || a);
|
|
13
|
+
return r && a && y(e, i, a), a;
|
|
14
|
+
};
|
|
15
|
+
const x = "pie-textarea";
|
|
16
|
+
class t extends u(p) {
|
|
17
|
+
constructor() {
|
|
18
|
+
super(...arguments), this.size = o.size, this.resize = o.resize;
|
|
19
|
+
}
|
|
20
|
+
handleResize() {
|
|
21
|
+
this.resize === "auto" && (this._textarea.style.height = "auto", this._textarea.style.height = `${this._textarea.scrollHeight + 2}px`);
|
|
22
|
+
}
|
|
23
|
+
updated(e) {
|
|
24
|
+
this.resize === "auto" && (e.has("resize") || e.has("size")) && this.handleResize();
|
|
25
|
+
}
|
|
26
|
+
render() {
|
|
27
|
+
const {
|
|
28
|
+
disabled: e,
|
|
29
|
+
resize: i,
|
|
30
|
+
size: r
|
|
31
|
+
} = this;
|
|
32
|
+
return v`
|
|
33
|
+
<div
|
|
34
|
+
class="c-textareaWrapper"
|
|
35
|
+
data-test-id="pie-textarea-wrapper"
|
|
36
|
+
data-pie-size=${r}
|
|
37
|
+
data-pie-resize=${i}>
|
|
38
|
+
<textarea
|
|
39
|
+
data-test-id="pie-textarea"
|
|
40
|
+
@input=${this.handleResize}
|
|
41
|
+
?disabled=${e}
|
|
42
|
+
></textarea>
|
|
43
|
+
</div>`;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
t.shadowRootOptions = { ...p.shadowRootOptions, delegatesFocus: !0 };
|
|
47
|
+
t.styles = g(m);
|
|
48
|
+
d([
|
|
49
|
+
c({ type: Boolean, reflect: !0 })
|
|
50
|
+
], t.prototype, "disabled", 2);
|
|
51
|
+
d([
|
|
52
|
+
c({ type: String }),
|
|
53
|
+
h(x, f, o.size)
|
|
54
|
+
], t.prototype, "size", 2);
|
|
55
|
+
d([
|
|
56
|
+
c({ type: String }),
|
|
57
|
+
h(x, k, o.resize)
|
|
58
|
+
], t.prototype, "resize", 2);
|
|
59
|
+
d([
|
|
60
|
+
b("textarea")
|
|
61
|
+
], t.prototype, "_textarea", 2);
|
|
62
|
+
z(x, t);
|
|
63
|
+
export {
|
|
64
|
+
t as PieTextarea,
|
|
65
|
+
o as defaultProps,
|
|
66
|
+
k as resizeModes,
|
|
67
|
+
f as sizes
|
|
68
|
+
};
|
package/dist/react.d.ts
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { ComponentDefaultPropsGeneric } from '@justeattakeaway/pie-webc-core';
|
|
2
|
+
import type { CSSResult } from 'lit';
|
|
3
|
+
import type { GenericConstructor } from '@justeattakeaway/pie-webc-core';
|
|
4
|
+
import type { LitElement } from 'lit';
|
|
5
|
+
import type { PropertyValues } from 'lit';
|
|
6
|
+
import * as React_2 from 'react';
|
|
7
|
+
import type { RTLInterface } from '@justeattakeaway/pie-webc-core';
|
|
8
|
+
import type { TemplateResult } from 'lit-html';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* The default values for the `TextareaProps` that are required (i.e. they have a fallback value in the component).
|
|
12
|
+
*/
|
|
13
|
+
declare type DefaultProps = ComponentDefaultPropsGeneric<TextareaProps, 'disabled' | 'size' | 'resize'>;
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Default values for optional properties that have default fallback values in the component.
|
|
17
|
+
*/
|
|
18
|
+
export declare const defaultProps: DefaultProps;
|
|
19
|
+
|
|
20
|
+
export declare const PieTextarea: React_2.ForwardRefExoticComponent<TextareaProps & React_2.RefAttributes<PieTextarea_2> & ReactBaseType>;
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* @tagname pie-textarea
|
|
24
|
+
*/
|
|
25
|
+
declare class PieTextarea_2 extends PieTextarea_base implements TextareaProps {
|
|
26
|
+
static shadowRootOptions: {
|
|
27
|
+
delegatesFocus: boolean;
|
|
28
|
+
mode: ShadowRootMode;
|
|
29
|
+
slotAssignment?: SlotAssignmentMode | undefined;
|
|
30
|
+
};
|
|
31
|
+
disabled?: TextareaProps['disabled'];
|
|
32
|
+
size: "small" | "medium" | "large";
|
|
33
|
+
resize: "auto" | "manual";
|
|
34
|
+
private _textarea;
|
|
35
|
+
private handleResize;
|
|
36
|
+
updated(changedProperties: PropertyValues<this>): void;
|
|
37
|
+
render(): TemplateResult<1>;
|
|
38
|
+
static styles: CSSResult;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
declare const PieTextarea_base: GenericConstructor<RTLInterface> & typeof LitElement;
|
|
42
|
+
|
|
43
|
+
declare type ReactBaseType = React_2.HTMLAttributes<HTMLTextAreaElement>;
|
|
44
|
+
|
|
45
|
+
export declare const resizeModes: readonly ["auto", "manual"];
|
|
46
|
+
|
|
47
|
+
export declare const sizes: readonly ["small", "medium", "large"];
|
|
48
|
+
|
|
49
|
+
export declare interface TextareaProps {
|
|
50
|
+
/**
|
|
51
|
+
* Same as the HTML disabled attribute - indicates whether the textarea is disabled.
|
|
52
|
+
*/
|
|
53
|
+
disabled?: boolean;
|
|
54
|
+
/**
|
|
55
|
+
* The size of the textarea field. Can be `small`, `medium` or `large`. Defaults to `medium`.
|
|
56
|
+
*/
|
|
57
|
+
size?: typeof sizes[number];
|
|
58
|
+
/**
|
|
59
|
+
* The resize mode of the textarea. Can be `auto` or `manual`. Defaults to `auto`.
|
|
60
|
+
* When set to `auto`, the textarea will resize vertically as needed.
|
|
61
|
+
* When set to `manual`, the textarea will not resize automatically but can be resized by the user.
|
|
62
|
+
*/
|
|
63
|
+
resize?: typeof resizeModes[number];
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export { }
|
package/dist/react.js
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import * as e from "react";
|
|
2
|
+
import { createComponent as t } from "@lit/react";
|
|
3
|
+
import { PieTextarea as a } from "./index.js";
|
|
4
|
+
import { defaultProps as P, resizeModes as f, sizes as T } from "./index.js";
|
|
5
|
+
import "lit";
|
|
6
|
+
import "lit/decorators.js";
|
|
7
|
+
import "@justeattakeaway/pie-webc-core";
|
|
8
|
+
const r = t({
|
|
9
|
+
displayName: "PieTextarea",
|
|
10
|
+
elementClass: a,
|
|
11
|
+
react: e,
|
|
12
|
+
tagName: "pie-textarea",
|
|
13
|
+
events: {}
|
|
14
|
+
}), x = r;
|
|
15
|
+
export {
|
|
16
|
+
x as PieTextarea,
|
|
17
|
+
P as defaultProps,
|
|
18
|
+
f as resizeModes,
|
|
19
|
+
T as sizes
|
|
20
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@justeattakeaway/pie-textarea",
|
|
3
|
+
"description": "PIE Design System Textarea built using Web Components",
|
|
4
|
+
"version": "0.0.0-snapshot-release-20240708103513",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"module": "dist/index.js",
|
|
8
|
+
"types": "dist/index.d.ts",
|
|
9
|
+
"files": [
|
|
10
|
+
"custom-elements.json",
|
|
11
|
+
"src",
|
|
12
|
+
"dist",
|
|
13
|
+
"**/*.d.ts"
|
|
14
|
+
],
|
|
15
|
+
"pieMetadata": {
|
|
16
|
+
"componentStatus": "alpha"
|
|
17
|
+
},
|
|
18
|
+
"scripts": {
|
|
19
|
+
"build": "run -T vite build",
|
|
20
|
+
"build:react-wrapper": "npx build-react-wrapper",
|
|
21
|
+
"create:manifest": "yarn cem analyze --litelement",
|
|
22
|
+
"lint:scripts": "run -T eslint .",
|
|
23
|
+
"lint:scripts:fix": "yarn lint:scripts --fix",
|
|
24
|
+
"lint:style": "run -T stylelint ./src/**/*.{css,scss}",
|
|
25
|
+
"lint:style:fix": "yarn lint:style --fix",
|
|
26
|
+
"watch": "run -T vite build --watch",
|
|
27
|
+
"test": "echo \"Error: no test specified\" && exit 0",
|
|
28
|
+
"test:ci": "yarn test",
|
|
29
|
+
"test:browsers": "npx playwright test -c ./playwright-lit.config.ts",
|
|
30
|
+
"test:browsers:ci": "yarn test:browsers",
|
|
31
|
+
"test:visual": "run -T cross-env-shell PERCY_TOKEN=${PERCY_TOKEN_PIE_TEXTAREA} percy exec --allowed-hostname cloudfront.net -- npx playwright test -c ./playwright-lit-visual.config.ts",
|
|
32
|
+
"test:visual:ci": "yarn test:visual",
|
|
33
|
+
"test:browsers-setup": "npx playwright-lit-setup"
|
|
34
|
+
},
|
|
35
|
+
"author": "Just Eat Takeaway.com - Design System Team",
|
|
36
|
+
"license": "Apache-2.0",
|
|
37
|
+
"devDependencies": {
|
|
38
|
+
"@custom-elements-manifest/analyzer": "0.9.0",
|
|
39
|
+
"@justeattakeaway/pie-components-config": "0.16.0",
|
|
40
|
+
"cem-plugin-module-file-extensions": "0.0.5"
|
|
41
|
+
},
|
|
42
|
+
"dependencies": {
|
|
43
|
+
"@justeattakeaway/pie-webc-core": "0.23.0"
|
|
44
|
+
},
|
|
45
|
+
"volta": {
|
|
46
|
+
"extends": "../../../package.json"
|
|
47
|
+
},
|
|
48
|
+
"customElements": "custom-elements.json",
|
|
49
|
+
"sideEffects": [
|
|
50
|
+
"dist/*.js"
|
|
51
|
+
]
|
|
52
|
+
}
|
package/src/defs.ts
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { type ComponentDefaultPropsGeneric } from '@justeattakeaway/pie-webc-core';
|
|
2
|
+
|
|
3
|
+
export const sizes = ['small', 'medium', 'large'] as const;
|
|
4
|
+
export const resizeModes = ['auto', 'manual'] as const;
|
|
5
|
+
|
|
6
|
+
export interface TextareaProps {
|
|
7
|
+
/**
|
|
8
|
+
* Same as the HTML disabled attribute - indicates whether the textarea is disabled.
|
|
9
|
+
*/
|
|
10
|
+
disabled?: boolean;
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* The size of the textarea field. Can be `small`, `medium` or `large`. Defaults to `medium`.
|
|
14
|
+
*/
|
|
15
|
+
size?: typeof sizes[number];
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* The resize mode of the textarea. Can be `auto` or `manual`. Defaults to `auto`.
|
|
19
|
+
* When set to `auto`, the textarea will resize vertically as needed.
|
|
20
|
+
* When set to `manual`, the textarea will not resize automatically but can be resized by the user.
|
|
21
|
+
*/
|
|
22
|
+
resize?: typeof resizeModes[number];
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* The default values for the `TextareaProps` that are required (i.e. they have a fallback value in the component).
|
|
27
|
+
*/
|
|
28
|
+
type DefaultProps = ComponentDefaultPropsGeneric<TextareaProps, 'disabled' | 'size' | 'resize'>;
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Default values for optional properties that have default fallback values in the component.
|
|
32
|
+
*/
|
|
33
|
+
export const defaultProps: DefaultProps = {
|
|
34
|
+
disabled: false,
|
|
35
|
+
size: 'medium',
|
|
36
|
+
resize: 'auto',
|
|
37
|
+
};
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import {
|
|
2
|
+
LitElement, html, unsafeCSS, PropertyValues,
|
|
3
|
+
} from 'lit';
|
|
4
|
+
import { property, query } from 'lit/decorators.js';
|
|
5
|
+
|
|
6
|
+
import { validPropertyValues, RtlMixin, defineCustomElement } from '@justeattakeaway/pie-webc-core';
|
|
7
|
+
|
|
8
|
+
import styles from './textarea.scss?inline';
|
|
9
|
+
import {
|
|
10
|
+
TextareaProps, defaultProps, sizes, resizeModes,
|
|
11
|
+
} from './defs';
|
|
12
|
+
|
|
13
|
+
// Valid values available to consumers
|
|
14
|
+
export * from './defs';
|
|
15
|
+
|
|
16
|
+
const componentSelector = 'pie-textarea';
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* @tagname pie-textarea
|
|
20
|
+
*/
|
|
21
|
+
export class PieTextarea extends RtlMixin(LitElement) implements TextareaProps {
|
|
22
|
+
static shadowRootOptions = { ...LitElement.shadowRootOptions, delegatesFocus: true };
|
|
23
|
+
|
|
24
|
+
@property({ type: Boolean, reflect: true })
|
|
25
|
+
public disabled?: TextareaProps['disabled'];
|
|
26
|
+
|
|
27
|
+
@property({ type: String })
|
|
28
|
+
@validPropertyValues(componentSelector, sizes, defaultProps.size)
|
|
29
|
+
public size = defaultProps.size;
|
|
30
|
+
|
|
31
|
+
@property({ type: String })
|
|
32
|
+
@validPropertyValues(componentSelector, resizeModes, defaultProps.resize)
|
|
33
|
+
public resize = defaultProps.resize;
|
|
34
|
+
|
|
35
|
+
@query('textarea')
|
|
36
|
+
private _textarea!: HTMLTextAreaElement;
|
|
37
|
+
|
|
38
|
+
private handleResize () {
|
|
39
|
+
if (this.resize === 'auto') {
|
|
40
|
+
this._textarea.style.height = 'auto';
|
|
41
|
+
this._textarea.style.height = `${this._textarea.scrollHeight + 2}px`; // +2 for border thicknesses
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
updated (changedProperties: PropertyValues<this>) {
|
|
46
|
+
if (this.resize === 'auto' && (changedProperties.has('resize') || changedProperties.has('size'))) {
|
|
47
|
+
this.handleResize();
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
render () {
|
|
52
|
+
const {
|
|
53
|
+
disabled,
|
|
54
|
+
resize,
|
|
55
|
+
size,
|
|
56
|
+
} = this;
|
|
57
|
+
|
|
58
|
+
return html`
|
|
59
|
+
<div
|
|
60
|
+
class="c-textareaWrapper"
|
|
61
|
+
data-test-id="pie-textarea-wrapper"
|
|
62
|
+
data-pie-size=${size}
|
|
63
|
+
data-pie-resize=${resize}>
|
|
64
|
+
<textarea
|
|
65
|
+
data-test-id="pie-textarea"
|
|
66
|
+
@input=${this.handleResize}
|
|
67
|
+
?disabled=${disabled}
|
|
68
|
+
></textarea>
|
|
69
|
+
</div>`;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Renders a `CSSResult` generated from SCSS by Vite
|
|
73
|
+
static styles = unsafeCSS(styles);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
defineCustomElement(componentSelector, PieTextarea);
|
|
77
|
+
|
|
78
|
+
declare global {
|
|
79
|
+
interface HTMLElementTagNameMap {
|
|
80
|
+
[componentSelector]: PieTextarea;
|
|
81
|
+
}
|
|
82
|
+
}
|
package/src/react.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { createComponent } from '@lit/react';
|
|
3
|
+
import { PieTextarea as PieTextareaLit } from './index';
|
|
4
|
+
import { TextareaProps } from './defs';
|
|
5
|
+
|
|
6
|
+
export * from './defs';
|
|
7
|
+
|
|
8
|
+
const PieTextareaReact = createComponent({
|
|
9
|
+
displayName: 'PieTextarea',
|
|
10
|
+
elementClass: PieTextareaLit,
|
|
11
|
+
react: React,
|
|
12
|
+
tagName: 'pie-textarea',
|
|
13
|
+
events: {},
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
type ReactBaseType = React.HTMLAttributes<HTMLTextAreaElement>
|
|
17
|
+
|
|
18
|
+
export const PieTextarea = PieTextareaReact as React.ForwardRefExoticComponent<React.PropsWithoutRef<TextareaProps>
|
|
19
|
+
& React.RefAttributes<PieTextareaLit> & ReactBaseType>;
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
@use '@justeattakeaway/pie-css/scss' as p;
|
|
2
|
+
|
|
3
|
+
// Heights are being defined based on the line height of the text and the padding.
|
|
4
|
+
// Changing the `size` property affects the padding and therefore the height of the textarea.
|
|
5
|
+
// Default height is two lines of text.
|
|
6
|
+
// Minimum height in manual resize mode is one line of text.
|
|
7
|
+
// Maximum height in auto resize mode is six lines of text.
|
|
8
|
+
.c-textareaWrapper {
|
|
9
|
+
--textarea-line-height: calc(var(--dt-font-body-l-line-height) * 1px);
|
|
10
|
+
--textarea-border-thickness: 1px;
|
|
11
|
+
--textarea-resize: none;
|
|
12
|
+
--textarea-padding-inline: var(--dt-spacing-d);
|
|
13
|
+
--textarea-padding-block-base: var(--dt-spacing-c);
|
|
14
|
+
--textarea-padding-block-large: var(--dt-spacing-d);
|
|
15
|
+
--textarea-padding-block-small: var(--dt-spacing-b);
|
|
16
|
+
--textarea-padding-block: var(--textarea-padding-block-base);
|
|
17
|
+
--textarea-inner-height-base: calc(var(--textarea-line-height) * 2);
|
|
18
|
+
--textarea-background-color: var(--dt-color-container-default);
|
|
19
|
+
--textarea-border-color: var(--dt-color-interactive-form);
|
|
20
|
+
--textarea-content-color: var(--dt-color-content-default);
|
|
21
|
+
|
|
22
|
+
// Default height is two lines of text
|
|
23
|
+
--textarea-height: calc(var(--textarea-inner-height-base) + (var(--textarea-padding-block) * 2) + (var(--textarea-border-thickness) * 2));
|
|
24
|
+
|
|
25
|
+
line-height: 0; // Remove once there is text outside the textarea
|
|
26
|
+
|
|
27
|
+
textarea {
|
|
28
|
+
font-size: calc(var(--dt-font-body-l-size) * 1px);
|
|
29
|
+
line-height: var(--textarea-line-height);
|
|
30
|
+
font-family: var(--dt-font-body-l-family);
|
|
31
|
+
resize: var(--textarea-resize);
|
|
32
|
+
border: var(--textarea-border-thickness) solid var(--textarea-border-color);
|
|
33
|
+
background-color: var(--textarea-background-color);
|
|
34
|
+
color: var(--textarea-content-color);
|
|
35
|
+
|
|
36
|
+
border-radius: var(--dt-radius-rounded-c);
|
|
37
|
+
block-size: var(--textarea-height);
|
|
38
|
+
max-block-size: var(--textarea-max-height);
|
|
39
|
+
min-block-size: var(--textarea-min-height);
|
|
40
|
+
|
|
41
|
+
padding-block-start: var(--textarea-padding-block);
|
|
42
|
+
padding-block-end: var(--textarea-padding-block);
|
|
43
|
+
padding-inline-start: var(--textarea-padding-inline);
|
|
44
|
+
padding-inline-end: var(--textarea-padding-inline);
|
|
45
|
+
|
|
46
|
+
&[disabled] {
|
|
47
|
+
--textarea-background-color: var(--dt-color-disabled-01);
|
|
48
|
+
--textarea-border-color: var(--dt-color-disabled-01);
|
|
49
|
+
--textarea-content-color: var(--dt-color-content-disabled);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
@media (hover: hover) {
|
|
53
|
+
&:hover:not([disabled]) {
|
|
54
|
+
--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))));
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
&:focus-visible {
|
|
59
|
+
@include p.focus;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
&[data-pie-size="large"] {
|
|
64
|
+
--textarea-padding-block: var(--textarea-padding-block-large);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
&[data-pie-size="small"] {
|
|
68
|
+
--textarea-padding-block: var(--textarea-padding-block-small);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
&[data-pie-resize="manual"] {
|
|
72
|
+
--textarea-resize: vertical;
|
|
73
|
+
|
|
74
|
+
// Minimum is one line of text
|
|
75
|
+
--textarea-min-height: calc((var(--textarea-line-height) * 1) + (var(--textarea-padding-block) * 2) + (var(--textarea-border-thickness) * 2)); // One line of text
|
|
76
|
+
|
|
77
|
+
@media (pointer: coarse) {
|
|
78
|
+
// Fixed size for touch devices
|
|
79
|
+
--textarea-height: calc((var(--textarea-line-height) * 6) + (var(--textarea-padding-block) * 2) + (var(--textarea-border-thickness) * 2));
|
|
80
|
+
--textarea-min-height: calc((var(--textarea-line-height) * 6) + (var(--textarea-padding-block) * 2) + (var(--textarea-border-thickness) * 2));
|
|
81
|
+
--textarea-max-height: calc((var(--textarea-line-height) * 6) + (var(--textarea-padding-block) * 2) + (var(--textarea-border-thickness) * 2));
|
|
82
|
+
--textarea-resize: none;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
&[data-pie-resize="auto"] {
|
|
87
|
+
// Maximum is six lines of text
|
|
88
|
+
--textarea-max-height: calc((var(--textarea-line-height) * 6) + (var(--textarea-padding-block) * 2) + (var(--textarea-border-thickness) * 2));
|
|
89
|
+
|
|
90
|
+
// Minimum is two lines of text
|
|
91
|
+
--textarea-min-height: var(--textarea-height);
|
|
92
|
+
}
|
|
93
|
+
}
|