@justeattakeaway/pie-text-input 0.28.3 → 0.28.4

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
@@ -1,42 +1,290 @@
1
- <p align="center">
2
- <img align="center" src="../../../readme_image.png" height="200" alt="">
3
- </p>
1
+ # @justeattakeaway/pie-text-input
2
+ [Source Code](https://github.com/justeattakeaway/pie/tree/main/packages/components/pie-text-input) | [Design Documentation](https://pie.design/components/text-input) | [NPM](https://www.npmjs.com/package/@justeattakeaway/pie-text-input)
4
3
 
5
- <p align="center">
4
+ <p>
6
5
  <a href="https://www.npmjs.com/@justeattakeaway/pie-text-input">
7
6
  <img alt="GitHub Workflow Status" src="https://img.shields.io/npm/v/@justeattakeaway/pie-text-input.svg">
8
7
  </a>
9
8
  </p>
10
9
 
11
- ## pie-text-input
12
-
13
- `pie-text-input` is a Web Component built using the Lit library.
10
+ `@justeattakeaway/pie-text-input` is a Web Component built using the Lit library. It offers a simple and accessible interactive text input component for web applications.
14
11
 
15
- This component can be easily integrated into various frontend frameworks and customized through a set of properties.
12
+ ## Table of Contents
16
13
 
14
+ - [Installation](#installation)
15
+ - [Documentation](#documentation)
16
+ - [Properties](#properties)
17
+ - [Slots](#slots)
18
+ - [CSS Variables](#css-variables)
19
+ - [Events](#events)
20
+ - [Forms Usage](#forms-usage)
21
+ - [Validation](#validation)
22
+ - [Displaying error messages](#displaying-error-messages)
23
+ - [Labelling](#labelling)
24
+ - [Usage Examples](#usage-examples)
25
+ - [Questions and Support](#questions-and-support)
26
+ - [Contributing](#contributing)
17
27
 
18
28
  ## Installation
19
29
 
20
- To install `pie-text-input` in your application, run the following on your command line:
30
+ > To install any of our web components in your application, we would suggest following the [getting started guide](https://webc.pie.design/?path=/docs/introduction-getting-started--docs) to set up your project.
31
+
32
+ Ideally, you should install the component using the **`@justeattakeaway/pie-webc`** package, which includes all of the components. Or you can install the individual component package.
33
+
34
+ ## Documentation
35
+
36
+ ### Properties
37
+ | Prop | Options | Description | Default |
38
+ |----------------|---------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------|
39
+ | `assistiveText`| `string` | Allows assistive text to be displayed below the input element. Must be provided if using a non-default status. | `undefined` |
40
+ | `autoFocus` | `true`, `false` | If true, the input will be focused on the first render. Only one element should have `autofocus`. | `false` |
41
+ | `autocomplete` | `string` | Allows the user to enable or disable autocomplete functionality. See [MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/autocomplete) for more. | `undefined` |
42
+ | `defaultValue` | `string` | During a form reset, the default value will replace the current value. This prop is not normally needed. | `undefined` |
43
+ | `disabled` | `true`, `false` | When true, the user cannot edit or interact with the control. | `false` |
44
+ | `inputmode` | `"none"`, `"text"`, `"tel"`, `"url"`, `"email"`, `"numeric"`, `"decimal"`, `"search"` | Hint to browsers for the type of virtual keyboard to use. See [MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#inputmode). | `undefined` |
45
+ | `max` | `number` | The maximum value (only for type `number`). If exceeded, the input is invalid. | `undefined` |
46
+ | `maxlength` | `number` | Maximum number of characters allowed (for text, url, tel, email, and password types). | `undefined` |
47
+ | `min` | `number` | The minimum value (only for type `number`). If below this, the input is invalid. | `undefined` |
48
+ | `minlength` | `number` | Minimum number of characters required (for text, url, tel, email, and password types). | `undefined` |
49
+ | `name` | `string` | Name of the input (used in form key/value pairs). | `undefined` |
50
+ | `pattern` | `string` | Regular expression that the input value should match. | `undefined` |
51
+ | `placeholder` | `string` | Placeholder text when input is empty (for text, url, tel, email, and password types). | `undefined` |
52
+ | `readonly` | `true`, `false` | When true, the input is not editable (but not disabled). See [MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/readonly). | `false` |
53
+ | `required` | `true`, `false` | If true, input must have a value to pass validation. Does not prevent form submission by itself. | `false` |
54
+ | `size` | `"small"`, `"medium"`, `"large"` | The size of the input field. | `"medium"` |
55
+ | `status` | `"default"`, `"error"`, `"success"` | The status of the input. If not `default`, `assistiveText` must be provided for accessibility. | `"default"` |
56
+ | `step` | `number` | Amount by which value changes when using up/down arrows (only for type `number`). | `undefined` |
57
+ | `type` | `"text"`, `"number"`, `"password"`, `"url"`, `"email"`, `"tel"` | The type of HTML input to render. | `"text"` |
58
+ | `value` | `string` | The value of the input (used in form key/value pairs). | `""` |
59
+
60
+ ### Slots
61
+ | Slot | Description |
62
+ |----------------|-----------------------------------------------------------------------------------------------------|
63
+ | `leadingIcon` | An icon to display at the start of the input.<br>Do not use at the same time as `leadingText`. |
64
+ | `leadingText` | Short text to display at the start of the input.<br>Wrap the text in a `<span>`.<br>Do not use at the same time as `leadingIcon`. |
65
+ | `trailingIcon` | An icon to display at the end of the input.<br>Do not use at the same time as `trailingText`. |
66
+ | `trailingText` | Short text to display at the end of the input.<br>Wrap the text in a `<span>`.<br>Do not use at the same time as `trailingIcon`. |
67
+
68
+ ### CSS Variables
69
+ This component does not expose any CSS variables for style overrides.
70
+
71
+ ### Events
72
+
73
+ | Event | Description |
74
+ |----------|-----------------------------------------------------------------------|
75
+ | `change` | Fires when the input loses focus after the value has been changed. |
76
+ | `input` | Fires when the input value is changed. |
77
+
78
+ ## Forms Usage
79
+
80
+ It is essential that when using the text input inside of a form, you provide a `name` attribute. HTML forms create key/value pairs for input data based on the `name` attribute, which is crucial for native form submission.
81
+
82
+ ### Validation
83
+ The text input component utilizes the [constraint validation API](https://developer.mozilla.org/en-US/docs/Web/HTML/Constraint_validation) to provide a queryable validity state for consumers. This means that the component's validity can be checked via a `validity` getter.
84
+
85
+ #### Example:
86
+ ```js
87
+ const textInput = document.querySelector('pie-text-input');
88
+ console.log(textInput.validity.valid);
89
+ ```
21
90
 
22
- _Note: Versions of this component prior to v0.19.0 were named `pie-input`._
91
+ This getter can be useful for reducing the amount of validation code in your application. For example, if you want to create a text input that should be at least 2 characters long, at most 5 characters long, and requires a value, you can set the `minlength`, `maxlength`, and `required` properties on the component. You can then check the validity of the input in your application code:
23
92
 
24
- ```bash
25
- npm i @justeattakeaway/pie-text-input
93
+ ```html
94
+ <pie-text-input
95
+ id="my-input"
96
+ name="my-input"
97
+ minlength="2"
98
+ maxlength="5"
99
+ required></pie-text-input>
26
100
  ```
27
- ```bash
28
- yarn add @justeattakeaway/pie-text-input
101
+
102
+ ```js
103
+ const textInput = document.querySelector('pie-text-input');
104
+ const isValid = textInput.validity.valid;
105
+
106
+ // We could use this to drive the status and assistiveText properties on our input (this would likely be inside a submit event handler in a real application)
107
+ if (!isValid) {
108
+ textInput.status = 'error';
109
+ textInput.assistiveText = 'Please enter a value between 2 and 5 characters long';
110
+ }
29
111
  ```
30
112
 
31
- 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).
113
+ These concepts work just as well inside a Vue or React application. Below is a similar implementation for validating a number input in a React application.
32
114
 
33
- ## Documentation
115
+ > Using the constraint validation API we provide is completely optional. Feel free to use whatever form of validation best suits your application's needs. The validity state of an input will not interfere with the form submission or page behaviour.
116
+
117
+ ```js
118
+ // Very simplified example
119
+ const [favouriteNumber, setFavouriteNumber] = useState('');
120
+ const [favouriteNumberValidationMessage, setFavouriteNumberValidationMessage] = useState('');
121
+
122
+ const favouriteNumberRef = useRef<HTMLInputElement>(null);
123
+
124
+ const handleFavouriteNumberInput = (event: InputEvent) => {
125
+ setFavouriteNumber((event.target as HTMLInputElement).value);
126
+ };
127
+
128
+ const handleSubmit = (event: React.FormEvent<HTMLFormElement>) => {
129
+ event.preventDefault();
130
+
131
+ let validationMessage = '';
132
+ const inputElement = favouriteNumberRef.current;
133
+
134
+ if (inputElement) {
135
+ if (inputElement.validity.rangeUnderflow) {
136
+ validationMessage = 'The favourite number is too low. Please pick a number between -5 and 200.';
137
+ } else if (inputElement.validity.rangeOverflow) {
138
+ validationMessage = 'The favourite number is too high. Please pick a number between -5 and 200.';
139
+ }
140
+ }
141
+
142
+ setFavouriteNumberValidationMessage(validationMessage);
143
+ };
144
+ ```
145
+ ```tsx
146
+ // Very simplified example
147
+ <form id="testForm" onSubmit={handleSubmit} novalidate>
148
+ <PieFormLabel id="favouriteNumberLabel" for="favouriteNumber">
149
+ Favourite Number:
150
+ </PieFormLabel>
151
+ <PieTextInput
152
+ aria-labelledby="favouriteNumberLabel"
153
+ id="favouriteNumber"
154
+ data-test-id="favouriteNumber"
155
+ name="favouriteNumber"
156
+ min={-5}
157
+ max={200}
158
+ value={favouriteNumber}
159
+ onInput={handleFavouriteNumberInput as any}
160
+ type="number"
161
+ ref={favouriteNumberRef}
162
+ assistiveText={favouriteNumberValidationMessage}
163
+ status={favouriteNumberValidationMessage ? 'error' : 'success'}>
164
+ <IconNumberSymbol slot="leadingIcon"></IconNumberSymbol>
165
+ </PieTextInput>
166
+
167
+ <PieButton data-test-id="submit-btn" type="submit">Submit</PieButton>
168
+ </form>
169
+ ```
34
170
 
35
- Visit [Text Input | PIE Design System](https://pie.design/components/text-input/code) to view more information on this component.
171
+ #### Displaying error messages
172
+ As mentioned earlier, we suggest consumers disable native HTML validation using the `novalidate` attribute on the form element. This will prevent the browser from displaying its own validation messages, allowing you to control the validation experience for your users.
173
+
174
+ To display validation messages, you can use the `assistiveText` and `status` properties on the text input component. The `assistiveText` property is used to display a message below the input, and the `status` property is used to set the visual state of the input. The `status` property can be set to `error` or `success`, or you can omit providing a status to display the assistive text in a neutral state.
175
+
176
+ ```html
177
+ <pie-text-input
178
+ name="firstName"
179
+ assistiveText="Please provide a first name"
180
+ status="error">
181
+ </pie-text-input>
182
+ ```
183
+
184
+ Displaying success messages works in the same way, but with the `status` property set to `success`.
185
+
186
+ ```html
187
+ <pie-text-input
188
+ name="firstName"
189
+ assistiveText="First name provided"
190
+ status="success">
191
+ </pie-text-input>
192
+ ```
193
+
194
+ ### Labelling
195
+ Please use the [form label](https://webc.pie.design/?path=/docs/components-form-label) component for adding a label to the text input. Similar to native HTML, the label should be a sibling of the input component and reference the input's `id` attribute using the `for` attribute.
196
+
197
+ The usage of `aria-labelledby` is very important so that screen readers will announce the label when the input is focused. This is especially important for users who rely on screen readers to navigate the web.
198
+
199
+ ```html
200
+ <pie-form-label id="first-name-label" for="first-name">First name:</pie-form-label>
201
+ <pie-text-input aria-labelledby="first-name-label" id="first-name" name="first-name"></pie-text-input>
202
+ ```
203
+
204
+ If you do not need to use a visual label, you must still provide an `aria-label` attribute to the text input. This is important for screen reader users as it will announce the purpose of the input when it is focused, even if a visual label is not used.
205
+
206
+ ```html
207
+ <pie-text-input aria-label="First name" name="first-name"></pie-text-input>
208
+ ```
209
+
210
+ ## Usage Examples
211
+
212
+ > When using icons, we recommend using [@justeattakeaway/pie-icons-webc](https://www.npmjs.com/package/@justeattakeaway/pie-icons-webc) to ensure consistency with the rest of the design system.
213
+
214
+ **For HTML:**
215
+
216
+ ```js
217
+ // import as module into a js file e.g. main.js
218
+ import '@justeattakeaway/pie-webc/components/card.js';
219
+ import '@justeattakeaway/pie-icons-webc/dist/IconPlaceholder.js';
220
+ ```
221
+
222
+ ```html
223
+ <pie-text-input
224
+ autocomplete="on"
225
+ autoFocus
226
+ inputmode="text"
227
+ maxlength="8"
228
+ minlength="4"
229
+ name="myinput"
230
+ pattern="[a-z]{4,8}"
231
+ placeholder="Please enter a value"
232
+ readonly
233
+ type="text"
234
+ value="">
235
+ <icon-placeholder slot="leadingIcon"></icon-placeholder>
236
+ </pie-text-input>
237
+ <script type="module" src="/main.js"></script>
238
+ ```
239
+
240
+ **For Native JS Applications, Vue, Angular, Svelte etc.:**
241
+
242
+ ```js
243
+ // Vue templates (using Nuxt 3)
244
+ import '@justeattakeaway/pie-webc/components/text-input.js';
245
+ import '@justeattakeaway/pie-icons-webc/dist/IconPlaceholder.js';
246
+
247
+ <pie-text-input
248
+ autocomplete="on"
249
+ autoFocus
250
+ inputmode="text"
251
+ maxlength="8"
252
+ minlength="4"
253
+ name="myinput"
254
+ pattern="[a-z]{4,8}"
255
+ placeholder="Please enter a value"
256
+ readonly
257
+ type="text"
258
+ value="">
259
+ <icon-placeholder slot="leadingIcon"></icon-placeholder>
260
+ </pie-text-input>
261
+ ```
262
+
263
+ **For React Applications:**
264
+
265
+ ```jsx
266
+ import { PieTextInput } from '@justeattakeaway/pie-webc/react/text-input.js';
267
+ import { IconPlaceholder } from '@justeattakeaway/pie-icons-webc/dist/react/IconPlaceholder.js';
268
+
269
+ <PieTextInput
270
+ autocomplete="on"
271
+ autoFocus
272
+ inputmode="text"
273
+ maxlength="8"
274
+ minlength="4"
275
+ name="myinput"
276
+ pattern="[a-z]{4,8}"
277
+ placeholder="Please enter a value"
278
+ readonly
279
+ type="text"
280
+ value="">
281
+ <IconPlaceholder slot="leadingIcon"></IconPlaceholder>
282
+ </PieTextInput>
283
+ ```
36
284
 
37
- ## Questions
285
+ ## Questions and Support
38
286
 
39
- Please head to [FAQs | PIE Design System](https://pie.design/support/contact-us/) to see our FAQs and get in touch.
287
+ If you work at Just Eat Takeaway.com, please contact us on **#help-designsystem**. Otherwise, please raise an issue on [Github](https://github.com/justeattakeaway/pie/issues).
40
288
 
41
289
  ## Contributing
42
290
 
@@ -50,7 +50,7 @@
50
50
  "type": {
51
51
  "text": "DefaultProps"
52
52
  },
53
- "default": "{\r\n type: 'text',\r\n value: '',\r\n size: 'medium',\r\n status: 'default',\r\n disabled: false,\r\n readonly: false,\r\n}",
53
+ "default": "{\n type: 'text',\n value: '',\n size: 'medium',\n status: 'default',\n disabled: false,\n readonly: false,\n}",
54
54
  "description": "Default values for optional properties that have default fallback values in the component."
55
55
  }
56
56
  ],
@@ -322,7 +322,7 @@
322
322
  "text": "ValidityState"
323
323
  },
324
324
  "privacy": "public",
325
- "description": "(Read-only) returns a ValidityState with the validity states that this element is in.\r\nhttps://developer.mozilla.org/en-US/docs/Web/API/HTMLObjectElement/validity",
325
+ "description": "(Read-only) returns a ValidityState with the validity states that this element is in.\nhttps://developer.mozilla.org/en-US/docs/Web/API/HTMLObjectElement/validity",
326
326
  "readonly": true
327
327
  },
328
328
  {
@@ -343,7 +343,7 @@
343
343
  "description": "The latest disabled state of the input."
344
344
  }
345
345
  ],
346
- "description": "Called after the disabled state of the element changes,\r\neither because the disabled attribute of this element was added or removed;\r\nor because the disabled state changed on a <fieldset> that's an ancestor of this element."
346
+ "description": "Called after the disabled state of the element changes,\neither because the disabled attribute of this element was added or removed;\nor because the disabled state changed on a <fieldset> that's an ancestor of this element."
347
347
  },
348
348
  {
349
349
  "kind": "method",
@@ -354,7 +354,7 @@
354
354
  "text": "void"
355
355
  }
356
356
  },
357
- "description": "Called when the form that owns this component is reset.\r\nResets the value to the default value."
357
+ "description": "Called when the form that owns this component is reset.\nResets the value to the default value."
358
358
  },
359
359
  {
360
360
  "kind": "field",
package/dist/index.js CHANGED
@@ -10,7 +10,7 @@ const z = class z extends ft {
10
10
  this.getAttribute("v") || this.setAttribute("v", z.v);
11
11
  }
12
12
  };
13
- z.v = "0.28.3";
13
+ z.v = "0.28.4";
14
14
  let X = z;
15
15
  const _t = "*,*:after,*:before{box-sizing:inherit}.c-textInput{--input-padding-block: var(--dt-spacing-c);--input-padding-inline: var(--dt-spacing-d);--input-gap: var(--dt-spacing-d);--input-text-color: var(--dt-color-content-default);--input-text-color-leading-trailing-content: var(--dt-color-content-default);--input-text-color-placeholder: var(--dt-color-content-placeholder);--input-border-color: var(--dt-color-border-form);--input-container-color: var(--dt-color-container-default);--input-radius: var(--dt-radius-rounded-c);--input-font-size: calc(var(--dt-font-body-l-size) * 1px);--input-line-height: calc(var(--dt-font-body-l-line-height) * 1px);--input-height: 48px;--input-cursor: text;--icon-display-override: block;--icon-size-override: 24px;height:var(--input-height);border:1px solid var(--input-border-color);border-radius:var(--input-radius);padding-inline-start:var(--input-padding-inline);padding-inline-end:var(--input-padding-inline);padding-block-start:var(--input-padding-block);padding-block-end:var(--input-padding-block);font-size:var(--input-font-size);line-height:var(--input-line-height);display:flex;flex-wrap:nowrap;align-items:center;background-color:var(--input-container-color);color:var(--input-text-color-leading-trailing-content);cursor:var(--input-cursor)}.c-textInput.c-textInput--large{--input-padding-block: var(--dt-spacing-d);--input-height: 56px}.c-textInput.c-textInput--small{--input-padding-block: var(--dt-spacing-b);--input-height: 40px}.c-textInput.c-textInput--error{--input-border-color: var(--dt-color-support-error)}.c-textInput ::slotted([slot=leadingText]),.c-textInput ::slotted([slot=leadingIcon]){margin-inline-end:var(--input-gap)}.c-textInput ::slotted([slot=trailingText]),.c-textInput ::slotted([slot=trailingIcon]){margin-inline-start:var(--input-gap)}@supports (gap: var(--input-gap)){.c-textInput{gap:var(--input-gap)}.c-textInput ::slotted([slot=leadingText]),.c-textInput ::slotted([slot=leadingIcon]){margin-inline-end:0}.c-textInput ::slotted([slot=trailingText]),.c-textInput ::slotted([slot=trailingIcon]){margin-inline-start:0}}.c-textInput:not(.is-disabled) ::slotted([slot=leadingIcon]),.c-textInput:not(.is-disabled) ::slotted([slot=trailingIcon]){color:var(--dt-color-content-subdued)}@media (hover: hover){.c-textInput:hover{--input-container-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-textInput:hover{--input-container-color: color-mix(in srgb, var(--dt-color-hover-01-bg) var(--dt-color-hover-01), var(--dt-color-container-default))}}}.c-textInput.c-textInput--readonly{--input-container-color: var(--dt-color-container-subtle);--input-border-color: var(--dt-color-border-form)}.c-textInput.is-disabled.c-textInput--readonly,.c-textInput.is-disabled{--input-container-color: var(--dt-color-disabled-01);--input-border-color: var(--dt-color-disabled-01);--input-text-color: var(--dt-color-content-disabled);--input-text-color-placeholder: var(--dt-color-content-disabled);--input-text-color-leading-trailing-content: var(--dt-color-content-disabled);--input-cursor: auto}.c-textInput:focus-within{box-shadow:0 0 0 2px var(--dt-color-focus-inner),0 0 0 4px var(--dt-color-focus-outer);outline:none}input{border:0;outline:0;height:24px;padding:0;color:var(--input-text-color);width:100%;font-size:var(--input-font-size);font-family:inherit;background:none;cursor:inherit;-webkit-appearance:none;-moz-appearance:none;appearance:none}input::placeholder{color:var(--input-text-color-placeholder);opacity:1}input:disabled{-webkit-text-fill-color:var(--input-text-color);color:var(--input-text-color);-webkit-opacity:1;opacity:1}input[type=number]:not([step])::-webkit-inner-spin-button,input[type=number]:not([step])::-webkit-outer-spin-button{-webkit-appearance:none;margin:0}input[type=number]:not([step]){-moz-appearance:textfield}", Ht = ["text", "number", "password", "url", "email", "tel"], Zt = ["none", "text", "tel", "url", "email", "numeric", "decimal", "search"], zt = ["default", "success", "error"], Wt = ["small", "medium", "large"], w = {
16
16
  type: "text",
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@justeattakeaway/pie-text-input",
3
3
  "description": "PIE Design System Input built using Web Components",
4
- "version": "0.28.3",
4
+ "version": "0.28.4",
5
5
  "repository": {
6
6
  "type": "git",
7
7
  "url": "https://github.com/justeattakeaway/pie",
@@ -41,13 +41,13 @@
41
41
  "@custom-elements-manifest/analyzer": "0.9.0",
42
42
  "@justeattakeaway/pie-components-config": "0.20.1",
43
43
  "@justeattakeaway/pie-css": "0.16.0",
44
- "@justeattakeaway/pie-icons-webc": "1.11.0",
44
+ "@justeattakeaway/pie-icons-webc": "1.11.1",
45
45
  "@justeattakeaway/pie-monorepo-utils": "0.5.1",
46
46
  "@justeattakeaway/pie-wrapper-react": "0.14.3",
47
47
  "cem-plugin-module-file-extensions": "0.0.5"
48
48
  },
49
49
  "dependencies": {
50
- "@justeattakeaway/pie-assistive-text": "0.10.3",
50
+ "@justeattakeaway/pie-assistive-text": "0.10.4",
51
51
  "@justeattakeaway/pie-webc-core": "1.0.0",
52
52
  "element-internals-polyfill": "1.3.11"
53
53
  },