@jack-henry/jh-elements 2.0.0-beta.12 → 2.0.0-beta.13
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/components/input/input.js +296 -247
- package/components/input-password/input-password.js +64 -54
- package/components/input-search/input-search.js +11 -8
- package/components/input-textarea/input-textarea.js +67 -175
- package/components/list-item/list-item.js +4 -1
- package/components/select/filtering.js +92 -0
- package/components/select/select.js +660 -0
- package/components/toast/toast.js +1 -5
- package/custom-elements.json +786 -161
- package/index.d.ts +2 -0
- package/package.json +1 -1
|
@@ -11,7 +11,7 @@ let id = 0;
|
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
13
|
* @cssprop --jh-input-label-color-text - The label text color. Defaults to `--jh-color-content-primary-enabled`.
|
|
14
|
-
* @cssprop --jh-input-field-color-background - The input field background-color. Defaults to `--jh-color-container-primary-enabled`.
|
|
14
|
+
* @cssprop --jh-input-field-color-background - The input field background-color when in an editable state. This property does not apply when the component is set to `readonly`. Defaults to `--jh-color-container-primary-enabled`.
|
|
15
15
|
* @cssprop --jh-input-field-color-border-enabled - The input field border-color. Defaults to `--jh-border-control-color`.
|
|
16
16
|
* @cssprop --jh-input-field-border-radius - The input field border radius. Defaults to `--jh-border-radius-100`.
|
|
17
17
|
* @cssprop --jh-input-color-focus - The input field outline when it receives keyboard focus. Defaults to `--jh-border-focus-color`.
|
|
@@ -91,8 +91,18 @@ export class JhInput extends LitElement {
|
|
|
91
91
|
// alphanumeric characters -> usernames, product codes, etc.
|
|
92
92
|
'*': /[A-Za-z0-9]/,
|
|
93
93
|
};
|
|
94
|
-
|
|
95
|
-
#
|
|
94
|
+
|
|
95
|
+
get #inputEl() {
|
|
96
|
+
return this.renderRoot?.querySelector('input');
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
get #leftSlot() {
|
|
100
|
+
return this.renderRoot?.querySelector('slot[name="jh-input-left"]');
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
get #rightSlot() {
|
|
104
|
+
return this.renderRoot?.querySelector('slot[name="jh-input-right"]');
|
|
105
|
+
}
|
|
96
106
|
|
|
97
107
|
static get styles() {
|
|
98
108
|
return css`
|
|
@@ -107,14 +117,7 @@ export class JhInput extends LitElement {
|
|
|
107
117
|
line-height: var(--input-helper-regular-line-height);
|
|
108
118
|
display: inline-block;
|
|
109
119
|
width: 100%;
|
|
110
|
-
--jh-button-size: var(--jh-dimension-800);
|
|
111
|
-
/* input padding + slot padding */
|
|
112
|
-
--padding-with-left-slotted-content: calc(
|
|
113
|
-
var(--jh-dimension-400) + var(--jh-dimension-200)
|
|
114
|
-
);
|
|
115
|
-
--padding-with-right-slotted-content: calc(
|
|
116
|
-
var(--jh-dimension-400) + var(--jh-dimension-200)
|
|
117
|
-
);
|
|
120
|
+
--jh-button-size: var(--jh-dimension-800);
|
|
118
121
|
--input-value-color-text: var(
|
|
119
122
|
--jh-input-value-color-text,
|
|
120
123
|
var(--jh-color-content-primary-enabled)
|
|
@@ -146,13 +149,14 @@ export class JhInput extends LitElement {
|
|
|
146
149
|
:host([show-char-count]) .helper-text {
|
|
147
150
|
display: inline-block;
|
|
148
151
|
}
|
|
149
|
-
.input-container {
|
|
150
|
-
position: relative;
|
|
151
|
-
}
|
|
152
152
|
:host([label]) .input-container {
|
|
153
153
|
margin-top: var(--jh-dimension-200);
|
|
154
154
|
}
|
|
155
|
-
|
|
155
|
+
|
|
156
|
+
/* Flex wrapper */
|
|
157
|
+
.input-wrapper {
|
|
158
|
+
display: flex;
|
|
159
|
+
align-items: center;
|
|
156
160
|
background-color: var(
|
|
157
161
|
--jh-input-field-color-background,
|
|
158
162
|
var(--jh-color-container-primary-enabled)
|
|
@@ -161,123 +165,78 @@ export class JhInput extends LitElement {
|
|
|
161
165
|
border-style: var(--jh-border-control-style);
|
|
162
166
|
border-color: var(
|
|
163
167
|
--jh-input-field-color-border-enabled,
|
|
164
|
-
|
|
165
|
-
|
|
168
|
+
var(--jh-border-control-color)
|
|
169
|
+
);
|
|
166
170
|
border-radius: var(
|
|
167
171
|
--jh-input-field-border-radius,
|
|
168
172
|
var(--jh-border-radius-100)
|
|
169
173
|
);
|
|
170
|
-
|
|
171
|
-
font-family: var(--jh-font-body-regular-1-font-family);
|
|
172
|
-
font-weight: var(--jh-font-body-regular-1-font-weight);
|
|
173
|
-
font-size: var(--jh-font-body-regular-1-font-size);
|
|
174
|
-
line-height: var(--jh-font-body-regular-1-line-height);
|
|
175
|
-
padding: var(--jh-dimension-0) var(--jh-dimension-400) var(--jh-dimension-0) var(--jh-dimension-400);
|
|
174
|
+
padding: var(--jh-dimension-0) var(--jh-dimension-400);
|
|
176
175
|
box-sizing: border-box;
|
|
177
176
|
width: 100%;
|
|
178
177
|
}
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
.jh-input-left {
|
|
183
|
-
padding-left: calc(var(--padding-with-left-slotted-content) + var(--jh-input-left-width));
|
|
184
|
-
}
|
|
185
|
-
/* slot styles */
|
|
186
|
-
::slotted(*),
|
|
187
|
-
::slotted(*) {
|
|
188
|
-
position: absolute;
|
|
189
|
-
display: flex;
|
|
190
|
-
align-items: center;
|
|
191
|
-
justify-content: center;
|
|
192
|
-
}
|
|
193
|
-
::slotted([slot='jh-input-left']) {
|
|
194
|
-
left: var(--jh-dimension-400);
|
|
195
|
-
}
|
|
196
|
-
::slotted([slot='jh-input-right']) {
|
|
197
|
-
right: var(--jh-dimension-400);
|
|
198
|
-
}
|
|
199
|
-
::slotted([slot='jh-input-left']){
|
|
200
|
-
top: var(--jh-input-left-top);
|
|
201
|
-
}
|
|
202
|
-
::slotted([slot='jh-input-right']) {
|
|
203
|
-
top: var(--jh-input-right-top);
|
|
204
|
-
}
|
|
205
|
-
/* clear button */
|
|
206
|
-
.clear-button {
|
|
207
|
-
right: var(--jh-dimension-400);
|
|
208
|
-
--jh-button-border-radius: var(--jh-input-clear-border-radius);
|
|
209
|
-
--jh-button-color-background-tertiary-enabled: var(--jh-input-clear-color-background-enabled);
|
|
210
|
-
--jh-button-color-border-tertiary-enabled: var(--jh-input-clear-color-border-enabled);
|
|
211
|
-
--jh-button-icon-color-fill-tertiary-enabled: var(--jh-input-clear-icon-color-fill-enabled);
|
|
212
|
-
--jh-button-color-background-tertiary-focus: var(--jh-input-clear-color-background-focus);
|
|
213
|
-
--jh-button-color-border-tertiary-focus: var(--jh-input-clear-color-border-focus);
|
|
214
|
-
--jh-button-color-focus: var(--jh-input-clear-color-focus);
|
|
215
|
-
--jh-button-icon-color-fill-tertiary-focus: var(--jh-input-clear-icon-color-fill-focus);
|
|
216
|
-
--jh-button-color-background-tertiary-hover: var(--jh-input-clear-color-background-hover);
|
|
217
|
-
--jh-button-color-border-tertiary-hover: var(--jh-input-clear-color-border-hover);
|
|
218
|
-
--jh-button-icon-color-fill-tertiary-hover: var(--jh-input-clear-icon-color-fill-hover);
|
|
219
|
-
--jh-button-color-background-tertiary-active: var(--jh-input-clear-color-background-active);
|
|
220
|
-
--jh-button-color-border-tertiary-active: var(--jh-input-clear-color-border-active);
|
|
221
|
-
--jh-button-icon-color-fill-tertiary-active: var(--jh-input-clear-icon-color-fill-active);
|
|
222
|
-
display: none;
|
|
223
|
-
position: absolute;
|
|
224
|
-
}
|
|
225
|
-
.display-clear-button .clear-button {
|
|
226
|
-
display: inherit;
|
|
227
|
-
}
|
|
228
|
-
:host([size='small']) .clear-button {
|
|
229
|
-
top: 4px;
|
|
230
|
-
}
|
|
231
|
-
:host([size='medium']) .clear-button {
|
|
232
|
-
top: 8px;
|
|
233
|
-
}
|
|
234
|
-
:host([size='large']) .clear-button {
|
|
235
|
-
top: 12px;
|
|
236
|
-
}
|
|
237
|
-
.jh-input-right ~ .clear-button {
|
|
238
|
-
right: calc(var(--padding-with-right-slotted-content) + var(--jh-input-right-width));
|
|
239
|
-
}
|
|
240
|
-
.display-clear-button input {
|
|
241
|
-
padding-right: calc(var(--padding-with-right-slotted-content) + var(--jh-dimension-800));
|
|
242
|
-
}
|
|
243
|
-
.display-clear-button .jh-input-right {
|
|
244
|
-
padding-right: calc(var(--padding-with-right-slotted-content) + var(--jh-input-right-width) + var(--jh-dimension-800) + var(--jh-dimension-200));
|
|
245
|
-
}
|
|
246
|
-
/* Sizes */
|
|
247
|
-
:host([size='small']) input {
|
|
178
|
+
|
|
179
|
+
/* Sizes on input wrapper */
|
|
180
|
+
:host([size='small']) .input-wrapper {
|
|
248
181
|
height: var(--jh-dimension-1000);
|
|
249
182
|
}
|
|
250
|
-
:host([size='medium']) input {
|
|
183
|
+
:host([size='medium']) .input-wrapper {
|
|
251
184
|
height: var(--jh-dimension-1200);
|
|
252
185
|
}
|
|
253
|
-
:host([size='large']) input {
|
|
186
|
+
:host([size='large']) .input-wrapper {
|
|
254
187
|
height: var(--jh-dimension-1400);
|
|
255
188
|
}
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
189
|
+
|
|
190
|
+
/* Input element — no border, grows to fill */
|
|
191
|
+
input {
|
|
192
|
+
flex: 1;
|
|
193
|
+
min-width: 0;
|
|
194
|
+
border: none;
|
|
195
|
+
background: transparent;
|
|
196
|
+
outline: none;
|
|
197
|
+
padding: 0;
|
|
198
|
+
color: var(--input-value-color-text);
|
|
199
|
+
font-family: var(--jh-font-body-regular-1-font-family);
|
|
200
|
+
font-weight: var(--jh-font-body-regular-1-font-weight);
|
|
201
|
+
font-size: var(--jh-font-body-regular-1-font-size);
|
|
202
|
+
line-height: var(--jh-font-body-regular-1-line-height);
|
|
203
|
+
height: 100%;
|
|
261
204
|
}
|
|
262
|
-
|
|
263
|
-
|
|
205
|
+
:host([readonly]) input {
|
|
206
|
+
height: auto;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/* Slot wrappers */
|
|
210
|
+
.slot-wrapper {
|
|
211
|
+
display: none;
|
|
212
|
+
align-items: center;
|
|
213
|
+
flex-shrink: 0;
|
|
264
214
|
}
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
215
|
+
slot[name="jh-input-left"] {
|
|
216
|
+
display: none;
|
|
217
|
+
align-items: center;
|
|
218
|
+
flex-shrink: 0;
|
|
219
|
+
padding-right: var(--jh-dimension-200);
|
|
269
220
|
}
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
);
|
|
221
|
+
slot[name="jh-input-right"] {
|
|
222
|
+
display: none;
|
|
223
|
+
align-items: center;
|
|
224
|
+
flex-shrink: 0;
|
|
225
|
+
padding-left: var(--jh-dimension-200);
|
|
275
226
|
}
|
|
276
|
-
|
|
277
|
-
|
|
227
|
+
slot[name="jh-input-left"].display-slot,
|
|
228
|
+
slot[name="jh-input-right"].display-slot {
|
|
229
|
+
display: flex;
|
|
278
230
|
}
|
|
279
|
-
|
|
280
|
-
|
|
231
|
+
|
|
232
|
+
/* Slotted content alignment */
|
|
233
|
+
::slotted(*) {
|
|
234
|
+
display: flex;
|
|
235
|
+
align-items: center;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/* States on input wrapper */
|
|
239
|
+
.input-wrapper:active {
|
|
281
240
|
border-color: var(
|
|
282
241
|
--jh-input-field-color-border-active,
|
|
283
242
|
var(--jh-color-content-brand-active)
|
|
@@ -286,13 +245,15 @@ export class JhInput extends LitElement {
|
|
|
286
245
|
:host([disabled]) {
|
|
287
246
|
opacity: var(--jh-input-opacity-disabled, var(--jh-opacity-disabled));
|
|
288
247
|
}
|
|
289
|
-
:host([disabled]) input {
|
|
248
|
+
:host([disabled]) .input-wrapper {
|
|
290
249
|
border-color: var(
|
|
291
250
|
--jh-input-field-color-border-disabled,
|
|
292
251
|
var(--jh-border-control-color)
|
|
293
252
|
);
|
|
294
253
|
}
|
|
295
|
-
|
|
254
|
+
|
|
255
|
+
/* Focus-visible on wrapper when input is focused */
|
|
256
|
+
.input-wrapper:has(input:focus-visible) {
|
|
296
257
|
border-color: var(
|
|
297
258
|
--jh-input-field-color-border-focus,
|
|
298
259
|
var(--jh-color-content-brand-hover)
|
|
@@ -305,13 +266,16 @@ export class JhInput extends LitElement {
|
|
|
305
266
|
outline-width: var(--jh-border-focus-width);
|
|
306
267
|
outline-offset: 1px;
|
|
307
268
|
}
|
|
308
|
-
input:
|
|
269
|
+
input:focus-visible {
|
|
270
|
+
outline: none;
|
|
271
|
+
}
|
|
272
|
+
.input-wrapper:hover {
|
|
309
273
|
border-color: var(
|
|
310
274
|
--jh-input-field-color-border-hover,
|
|
311
275
|
var(--jh-color-content-brand-hover)
|
|
312
276
|
);
|
|
313
277
|
}
|
|
314
|
-
:host([invalid]) input {
|
|
278
|
+
:host([invalid]) .input-wrapper {
|
|
315
279
|
border-width: var(--jh-border-error-width);
|
|
316
280
|
border-style: var(--jh-border-error-style);
|
|
317
281
|
border-color: var(
|
|
@@ -319,20 +283,72 @@ export class JhInput extends LitElement {
|
|
|
319
283
|
var(--jh-border-error-color)
|
|
320
284
|
);
|
|
321
285
|
}
|
|
322
|
-
|
|
323
|
-
|
|
286
|
+
|
|
287
|
+
/* Clear button */
|
|
288
|
+
.clear-button {
|
|
289
|
+
--jh-button-border-radius: var(--jh-input-clear-border-radius);
|
|
290
|
+
--jh-button-color-background-tertiary-enabled: var(--jh-input-clear-color-background-enabled);
|
|
291
|
+
--jh-button-color-border-tertiary-enabled: var(--jh-input-clear-color-border-enabled);
|
|
292
|
+
--jh-button-icon-color-fill-tertiary-enabled: var(--jh-input-clear-icon-color-fill-enabled);
|
|
293
|
+
--jh-button-color-background-tertiary-focus: var(--jh-input-clear-color-background-focus);
|
|
294
|
+
--jh-button-color-border-tertiary-focus: var(--jh-input-clear-color-border-focus);
|
|
295
|
+
--jh-button-color-focus: var(--jh-input-clear-color-focus);
|
|
296
|
+
--jh-button-icon-color-fill-tertiary-focus: var(--jh-input-clear-icon-color-fill-focus);
|
|
297
|
+
--jh-button-color-background-tertiary-hover: var(--jh-input-clear-color-background-hover);
|
|
298
|
+
--jh-button-color-border-tertiary-hover: var(--jh-input-clear-color-border-hover);
|
|
299
|
+
--jh-button-icon-color-fill-tertiary-hover: var(--jh-input-clear-icon-color-fill-hover);
|
|
300
|
+
--jh-button-color-background-tertiary-active: var(--jh-input-clear-color-background-active);
|
|
301
|
+
--jh-button-color-border-tertiary-active: var(--jh-input-clear-color-border-active);
|
|
302
|
+
--jh-button-icon-color-fill-tertiary-active: var(--jh-input-clear-icon-color-fill-active);
|
|
303
|
+
display: none;
|
|
304
|
+
flex-shrink: 0;
|
|
305
|
+
}
|
|
306
|
+
.display-clear-button .clear-button {
|
|
307
|
+
display: flex;
|
|
308
|
+
margin-left: var(--jh-dimension-200);
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
/* Readonly styles */
|
|
312
|
+
:host([readonly]) .input-wrapper {
|
|
324
313
|
height: auto;
|
|
325
314
|
background-color: transparent;
|
|
326
315
|
border: none;
|
|
327
316
|
padding-left: 0;
|
|
328
317
|
padding-right: 0;
|
|
329
318
|
}
|
|
319
|
+
|
|
330
320
|
/* Override Chrome autofill styles */
|
|
331
321
|
input:autofill {
|
|
332
322
|
-webkit-text-fill-color: var(--input-value-color-text);
|
|
333
323
|
caret-color: var(--input-value-color-text);
|
|
334
324
|
background-clip: text;
|
|
335
325
|
}
|
|
326
|
+
|
|
327
|
+
/* Footer */
|
|
328
|
+
.footer-content {
|
|
329
|
+
margin: var(--jh-dimension-200) 0 0 0;
|
|
330
|
+
gap: var(--jh-dimension-200);
|
|
331
|
+
display: flex;
|
|
332
|
+
justify-content: space-between;
|
|
333
|
+
}
|
|
334
|
+
.footer-content:has(.counter):not(:has(.error-text)) {
|
|
335
|
+
justify-content: flex-end;
|
|
336
|
+
}
|
|
337
|
+
.counter {
|
|
338
|
+
color: var(--jh-input-counter-color-text,
|
|
339
|
+
var(--jh-color-content-secondary-enabled)
|
|
340
|
+
);
|
|
341
|
+
}
|
|
342
|
+
.error-text {
|
|
343
|
+
color: var(
|
|
344
|
+
--jh-input-error-color-text,
|
|
345
|
+
var(--jh-color-content-negative-enabled)
|
|
346
|
+
);
|
|
347
|
+
}
|
|
348
|
+
p {
|
|
349
|
+
margin: 0;
|
|
350
|
+
}
|
|
351
|
+
|
|
336
352
|
/* Optional/Required/Show-indicator */
|
|
337
353
|
:host([show-indicator]) span {
|
|
338
354
|
color: var(
|
|
@@ -350,7 +366,6 @@ export class JhInput extends LitElement {
|
|
|
350
366
|
var(--jh-color-content-negative-enabled)
|
|
351
367
|
);
|
|
352
368
|
}
|
|
353
|
-
|
|
354
369
|
`;
|
|
355
370
|
}
|
|
356
371
|
|
|
@@ -478,12 +493,15 @@ export class JhInput extends LitElement {
|
|
|
478
493
|
|
|
479
494
|
disconnectedCallback() {
|
|
480
495
|
super.disconnectedCallback();
|
|
481
|
-
this.#resizeObserver.disconnect();
|
|
482
496
|
if (this.inputMask) {
|
|
483
497
|
this.removeEventListener('jh-select', this.#setSelection);
|
|
484
498
|
}
|
|
485
499
|
}
|
|
486
500
|
|
|
501
|
+
get uniqueId() {
|
|
502
|
+
return this.#id;
|
|
503
|
+
}
|
|
504
|
+
|
|
487
505
|
firstUpdated() {
|
|
488
506
|
// attach event listeners to show/hide clear button
|
|
489
507
|
if (this.showClearButton) {
|
|
@@ -494,9 +512,43 @@ export class JhInput extends LitElement {
|
|
|
494
512
|
['mouseenter', 'mouseleave'].forEach(e => {
|
|
495
513
|
inputContainer.addEventListener(e, this.#toggleFocus.bind(this));
|
|
496
514
|
});
|
|
497
|
-
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
if (this.#leftSlot) this.#leftSlot.classList.toggle('display-slot', this.#checkSlotContent(this.#leftSlot));
|
|
518
|
+
if (this.#rightSlot) this.#rightSlot.classList.toggle('display-slot', this.#checkSlotContent(this.#rightSlot));
|
|
519
|
+
|
|
520
|
+
// clicking the wrapper should focus the input
|
|
521
|
+
const wrapper = this.shadowRoot.querySelector('.input-wrapper');
|
|
522
|
+
wrapper?.addEventListener('mousedown', (e) => {
|
|
523
|
+
if (e.target === wrapper || e.target.tagName === 'SLOT') {
|
|
524
|
+
//if the input already has focus, don't do anything. Prevent default to avoid flickering of the focus ring.
|
|
525
|
+
if (this.shadowRoot.activeElement === this.#inputEl) {
|
|
526
|
+
e.preventDefault();
|
|
527
|
+
} else {
|
|
528
|
+
//otherwise set focus to the input.
|
|
529
|
+
e.preventDefault();
|
|
530
|
+
this.#inputEl?.focus();
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
});
|
|
498
534
|
}
|
|
499
535
|
|
|
536
|
+
#checkSlotContent(slot) {
|
|
537
|
+
// Slotted and fallback elements
|
|
538
|
+
const slottedElements = slot.assignedElements({ flatten: true });
|
|
539
|
+
if (slottedElements.length > 0) {
|
|
540
|
+
return true;
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
// Slotted and fallback text nodes that are not just whitespace
|
|
544
|
+
if (slot.assignedNodes({ flatten: true }).some(
|
|
545
|
+
(node) => node.nodeType === Node.TEXT_NODE && node.textContent.trim() !== ''
|
|
546
|
+
)) {
|
|
547
|
+
return true;
|
|
548
|
+
}
|
|
549
|
+
return false;
|
|
550
|
+
}
|
|
551
|
+
|
|
500
552
|
#toggleFocus(e) {
|
|
501
553
|
if (this.disabled || this.readonly || !this.showClearButton) {
|
|
502
554
|
return;
|
|
@@ -593,7 +645,7 @@ export class JhInput extends LitElement {
|
|
|
593
645
|
);
|
|
594
646
|
}
|
|
595
647
|
|
|
596
|
-
|
|
648
|
+
_handleInput(e) {
|
|
597
649
|
this.value = e.target.value;
|
|
598
650
|
let inputType = e.inputType;
|
|
599
651
|
this.#deletedChar = inputType === 'deleteContentBackward' || inputType === 'deleteByCut' || inputType === 'deleteContentForward';
|
|
@@ -608,7 +660,7 @@ export class JhInput extends LitElement {
|
|
|
608
660
|
}
|
|
609
661
|
}
|
|
610
662
|
|
|
611
|
-
|
|
663
|
+
_handleKeydown(e) {
|
|
612
664
|
const value = e.target.value;
|
|
613
665
|
let selectionStart = e.target.selectionStart;
|
|
614
666
|
let selectionEnd = e.target.selectionEnd;
|
|
@@ -1010,9 +1062,27 @@ export class JhInput extends LitElement {
|
|
|
1010
1062
|
this.#selectedText.selectionStart = null;
|
|
1011
1063
|
}
|
|
1012
1064
|
}
|
|
1065
|
+
|
|
1066
|
+
// Handle slot visibility updates
|
|
1067
|
+
if (changedProperties.has('hideLeftSlot')) {
|
|
1068
|
+
this.#updateSlotVisibility(this.#leftSlot);
|
|
1069
|
+
}
|
|
1070
|
+
if (changedProperties.has('hideRightSlot')) {
|
|
1071
|
+
this.#updateSlotVisibility(this.#rightSlot);
|
|
1072
|
+
}
|
|
1073
|
+
if (changedProperties.has('readonly')) {
|
|
1074
|
+
this.#updateSlotVisibility(this.#leftSlot);
|
|
1075
|
+
this.#updateSlotVisibility(this.#rightSlot);
|
|
1076
|
+
}
|
|
1077
|
+
}
|
|
1078
|
+
|
|
1079
|
+
#updateSlotVisibility(slot) {
|
|
1080
|
+
if (slot) {
|
|
1081
|
+
slot.classList.toggle('display-slot', this.#checkSlotContent(slot));
|
|
1082
|
+
}
|
|
1013
1083
|
}
|
|
1014
1084
|
|
|
1015
|
-
|
|
1085
|
+
_handleChange() {
|
|
1016
1086
|
let payload = {
|
|
1017
1087
|
'value': this.value,
|
|
1018
1088
|
}
|
|
@@ -1024,7 +1094,7 @@ export class JhInput extends LitElement {
|
|
|
1024
1094
|
this.#dispatch('jh-change', payload);
|
|
1025
1095
|
}
|
|
1026
1096
|
|
|
1027
|
-
|
|
1097
|
+
_handleSelect(e) {
|
|
1028
1098
|
const selectedString = e.target.value.substring(
|
|
1029
1099
|
e.target.selectionStart,
|
|
1030
1100
|
e.target.selectionEnd
|
|
@@ -1040,11 +1110,11 @@ export class JhInput extends LitElement {
|
|
|
1040
1110
|
}
|
|
1041
1111
|
}
|
|
1042
1112
|
|
|
1043
|
-
|
|
1113
|
+
_handleMaxlength() {
|
|
1044
1114
|
this.#dispatch('jh-maxlength');
|
|
1045
1115
|
}
|
|
1046
1116
|
|
|
1047
|
-
|
|
1117
|
+
_handleClearButtonClick() {
|
|
1048
1118
|
let previousValue = this.value;
|
|
1049
1119
|
// clear input value
|
|
1050
1120
|
this.value = '';
|
|
@@ -1063,115 +1133,67 @@ export class JhInput extends LitElement {
|
|
|
1063
1133
|
);
|
|
1064
1134
|
}
|
|
1065
1135
|
|
|
1066
|
-
|
|
1067
|
-
#resizeObserver = new ResizeObserver((entries) => {
|
|
1068
|
-
let inputEl = this.shadowRoot.querySelector('input');
|
|
1069
|
-
|
|
1070
|
-
for (let entry of entries) {
|
|
1071
|
-
let slottedEl = entry.target;
|
|
1072
|
-
let slottedElWidth = entry.borderBoxSize[0].inlineSize;
|
|
1073
|
-
let slottedElHeight = entry.borderBoxSize[0].blockSize;
|
|
1074
|
-
|
|
1075
|
-
this.style.setProperty(`--${slottedEl.slot}-width`, `${slottedElWidth}px`);
|
|
1076
|
-
|
|
1077
|
-
this.style.setProperty(`--${slottedEl.slot}-top`, `${(inputEl.offsetHeight - slottedElHeight) / 2}px`);
|
|
1078
|
-
}
|
|
1079
|
-
});
|
|
1080
|
-
|
|
1081
|
-
#handleSlotChange(e) {
|
|
1136
|
+
_handleSlotChange(e) {
|
|
1082
1137
|
let newSlottedElement = e.target.assignedElements()[0];
|
|
1083
|
-
let
|
|
1138
|
+
let slot = e.target;
|
|
1084
1139
|
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
this.#resizeObserver.unobserve(this.#activeSlottedElement.get(slotName));
|
|
1140
|
+
if (slot.name !== 'jh-input-left' && slot.name !== 'jh-input-right') {
|
|
1141
|
+
return;
|
|
1088
1142
|
}
|
|
1143
|
+
|
|
1144
|
+
let hasContent = this.#checkSlotContent(slot);
|
|
1145
|
+
slot.classList.toggle('display-slot', hasContent);
|
|
1089
1146
|
|
|
1090
|
-
if
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
if (newSlottedElement.tagName.startsWith('JH-ICON')) {
|
|
1094
|
-
newSlottedElement.setAttribute('size', 'medium');
|
|
1095
|
-
}
|
|
1096
|
-
this.#resizeObserver.observe(newSlottedElement);
|
|
1147
|
+
// Set icon size if applicable
|
|
1148
|
+
if (newSlottedElement?.tagName.startsWith('JH-ICON')) {
|
|
1149
|
+
newSlottedElement.setAttribute('size', 'medium');
|
|
1097
1150
|
}
|
|
1098
|
-
this.#addClass(slotName, newSlottedElement);
|
|
1099
1151
|
}
|
|
1100
1152
|
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1153
|
+
renderLeftSlot() {
|
|
1154
|
+
if (this.hideLeftSlot) return null;
|
|
1155
|
+
return html`
|
|
1156
|
+
<slot name="jh-input-left" @slotchange=${this._handleSlotChange}></slot>
|
|
1157
|
+
`;
|
|
1158
|
+
}
|
|
1104
1159
|
|
|
1105
|
-
|
|
1106
|
-
if (
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
}
|
|
1160
|
+
renderRightSlot() {
|
|
1161
|
+
if (this.hideRightSlot) return null;
|
|
1162
|
+
return html`
|
|
1163
|
+
<slot name="jh-input-right" @slotchange=${this._handleSlotChange}></slot>
|
|
1164
|
+
`;
|
|
1111
1165
|
}
|
|
1112
1166
|
|
|
1113
|
-
|
|
1114
|
-
if (this.
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1167
|
+
renderClearButton() {
|
|
1168
|
+
if (!this.showClearButton || !this.value || this.disabled) return null;
|
|
1169
|
+
return html`
|
|
1170
|
+
<jh-button
|
|
1171
|
+
size="small" appearance="tertiary" class="clear-button"
|
|
1172
|
+
accessible-label=${ifDefined(this.accessibleLabelClearButton)}
|
|
1173
|
+
@click=${this._handleClearButtonClick}>
|
|
1174
|
+
<slot name="jh-input-clear-button" slot="jh-button-icon">
|
|
1175
|
+
<jh-icon-circle-xmark slot="jh-button-icon" aria-hidden="true" size="medium"></jh-icon-circle-xmark>
|
|
1176
|
+
</slot>
|
|
1177
|
+
</jh-button>
|
|
1124
1178
|
`;
|
|
1125
|
-
|
|
1126
|
-
const clearBtn = this.showClearButton && this.value && !this.disabled
|
|
1127
|
-
? html`
|
|
1128
|
-
<jh-button
|
|
1129
|
-
size="small" appearance="tertiary" class="clear-button"
|
|
1130
|
-
accessible-label=${ifDefined(this.accessibleLabelClearButton)}
|
|
1131
|
-
@click=${this.#handleClearButtonClick}>
|
|
1132
|
-
<slot name="jh-input-clear-button" slot="jh-button-icon">
|
|
1133
|
-
<jh-icon-circle-xmark slot="jh-button-icon" aria-hidden="true" size="medium"></jh-icon-circle-xmark>
|
|
1134
|
-
</slot>
|
|
1135
|
-
</jh-button>
|
|
1136
|
-
`
|
|
1137
|
-
: null;
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
const rightSlot = this.hideRightSlot
|
|
1141
|
-
? null
|
|
1142
|
-
: html`<slot
|
|
1143
|
-
name="jh-input-right"
|
|
1144
|
-
@slotchange=${this.#handleSlotChange}
|
|
1145
|
-
></slot>
|
|
1146
|
-
`;
|
|
1147
|
-
|
|
1148
|
-
return html`${leftSlot}${clearBtn}${rightSlot}`;
|
|
1149
1179
|
}
|
|
1150
1180
|
|
|
1151
|
-
|
|
1181
|
+
_getDescribedby() {
|
|
1152
1182
|
let describedbyString = '';
|
|
1153
1183
|
|
|
1154
1184
|
if (this.errorText) {
|
|
1155
|
-
describedbyString += `jh-input-error-${this
|
|
1185
|
+
describedbyString += `jh-input-error-${this.uniqueId}`;
|
|
1156
1186
|
}
|
|
1157
1187
|
if (this.helperText) {
|
|
1158
|
-
describedbyString += ` jh-input-helper-${this
|
|
1159
|
-
}
|
|
1160
|
-
if (this.showCharCount) {
|
|
1161
|
-
describedbyString += ` jh-input-counter-${this.#id}`;
|
|
1188
|
+
describedbyString += ` jh-input-helper-${this.uniqueId}`;
|
|
1162
1189
|
}
|
|
1163
1190
|
return describedbyString;
|
|
1164
1191
|
}
|
|
1165
1192
|
|
|
1166
|
-
|
|
1193
|
+
renderLabel() {
|
|
1167
1194
|
let label;
|
|
1168
1195
|
let indicator;
|
|
1169
1196
|
let helperText;
|
|
1170
|
-
let input;
|
|
1171
|
-
let footer;
|
|
1172
|
-
let errorText;
|
|
1173
|
-
let charCount;
|
|
1174
|
-
let describedby;
|
|
1175
1197
|
|
|
1176
1198
|
if (this.label) {
|
|
1177
1199
|
if (this.showIndicator) {
|
|
@@ -1184,17 +1206,24 @@ export class JhInput extends LitElement {
|
|
|
1184
1206
|
|
|
1185
1207
|
if (this.helperText) {
|
|
1186
1208
|
helperText = html`
|
|
1187
|
-
<p id="jh-input-helper-${this
|
|
1209
|
+
<p id="jh-input-helper-${this.uniqueId}" class="helper-text">
|
|
1188
1210
|
${this.helperText}
|
|
1189
1211
|
</p>
|
|
1190
1212
|
`;
|
|
1191
1213
|
}
|
|
1192
1214
|
|
|
1193
1215
|
label = html`
|
|
1194
|
-
<label for="jh-input-${this
|
|
1216
|
+
<label for="jh-input-${this.uniqueId}">${this.label}${indicator}</label>
|
|
1195
1217
|
${helperText}
|
|
1196
1218
|
`;
|
|
1197
1219
|
}
|
|
1220
|
+
return label;
|
|
1221
|
+
}
|
|
1222
|
+
|
|
1223
|
+
renderFooter() {
|
|
1224
|
+
let footer;
|
|
1225
|
+
let errorText;
|
|
1226
|
+
let charCount;
|
|
1198
1227
|
|
|
1199
1228
|
if (this.showCharCount) {
|
|
1200
1229
|
let valueLength = this.value ? this.value.length : 0;
|
|
@@ -1204,7 +1233,7 @@ export class JhInput extends LitElement {
|
|
|
1204
1233
|
}`;
|
|
1205
1234
|
|
|
1206
1235
|
if (valueLength && valueLength === Number(this.maxlength)) {
|
|
1207
|
-
this
|
|
1236
|
+
this._handleMaxlength();
|
|
1208
1237
|
}
|
|
1209
1238
|
|
|
1210
1239
|
charCount = html`
|
|
@@ -1214,7 +1243,7 @@ export class JhInput extends LitElement {
|
|
|
1214
1243
|
|
|
1215
1244
|
if (this.invalid && this.errorText) {
|
|
1216
1245
|
errorText = html`
|
|
1217
|
-
<p id="jh-input-error-${this
|
|
1246
|
+
<p id="jh-input-error-${this.uniqueId}" class="error-text">
|
|
1218
1247
|
${this.errorText}
|
|
1219
1248
|
</p>
|
|
1220
1249
|
`;
|
|
@@ -1228,42 +1257,62 @@ export class JhInput extends LitElement {
|
|
|
1228
1257
|
</div>
|
|
1229
1258
|
`;
|
|
1230
1259
|
}
|
|
1260
|
+
return footer;
|
|
1261
|
+
}
|
|
1262
|
+
|
|
1263
|
+
renderInput() {
|
|
1264
|
+
let describedby;
|
|
1231
1265
|
|
|
1232
|
-
if (helperText || errorText
|
|
1233
|
-
describedby = this
|
|
1266
|
+
if (this.helperText || (this.errorText && this.invalid)) {
|
|
1267
|
+
describedby = this._getDescribedby();
|
|
1234
1268
|
}
|
|
1235
1269
|
|
|
1236
|
-
|
|
1270
|
+
const leftSlot = this.readonly ? null : this.renderLeftSlot();
|
|
1271
|
+
const rightSlot = this.readonly ? null : this.renderRightSlot();
|
|
1272
|
+
const clearButton = this.readonly ? null : this.renderClearButton();
|
|
1273
|
+
|
|
1274
|
+
return html`
|
|
1237
1275
|
<div class="input-container">
|
|
1238
|
-
<input
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
this.
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1276
|
+
<div class="input-wrapper">
|
|
1277
|
+
${leftSlot}
|
|
1278
|
+
<input
|
|
1279
|
+
id="jh-input-${this.uniqueId}"
|
|
1280
|
+
aria-describedby=${describedby}
|
|
1281
|
+
aria-invalid=${ifDefined(this.invalid ? 'true' : null)}
|
|
1282
|
+
aria-label=${ifDefined(
|
|
1283
|
+
this.accessibleLabel === '' ? null : this.accessibleLabel
|
|
1284
|
+
)}
|
|
1285
|
+
autocomplete=${ifDefined(
|
|
1286
|
+
this.autocomplete === '' ? null : this.autocomplete
|
|
1287
|
+
)}
|
|
1288
|
+
?disabled=${this.disabled}
|
|
1289
|
+
enterkeyhint=${ifDefined(
|
|
1290
|
+
this.enterkeyhint === '' ? null : this.enterkeyhint
|
|
1291
|
+
)}
|
|
1292
|
+
inputmode=${ifDefined(this.inputmode === '' ? null : this.inputmode)}
|
|
1293
|
+
maxlength=${ifDefined(this.maxlength === '' ? null : this.maxlength)}
|
|
1294
|
+
minlength=${ifDefined(this.minlength === '' ? null : this.minlength)}
|
|
1295
|
+
name=${ifDefined(this.name === '' ? null : this.name)}
|
|
1296
|
+
?readonly=${this.readonly}
|
|
1297
|
+
?required=${this.required}
|
|
1298
|
+
type="text"
|
|
1299
|
+
.value=${this.value}
|
|
1300
|
+
@keydown=${this.inputMask ? this._handleKeydown : null}
|
|
1301
|
+
@change=${this._handleChange}
|
|
1302
|
+
@input=${this._handleInput}
|
|
1303
|
+
@select=${this._handleSelect}
|
|
1304
|
+
/>
|
|
1305
|
+
${clearButton}
|
|
1306
|
+
${rightSlot}
|
|
1307
|
+
</div>
|
|
1265
1308
|
</div>
|
|
1266
1309
|
`;
|
|
1310
|
+
}
|
|
1311
|
+
|
|
1312
|
+
render() {
|
|
1313
|
+
const label = this.renderLabel();
|
|
1314
|
+
const input = this.renderInput();
|
|
1315
|
+
const footer = this.renderFooter();
|
|
1267
1316
|
|
|
1268
1317
|
return html`
|
|
1269
1318
|
${label} ${input} ${footer}
|