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