@nuralyui/input 0.0.5 → 0.0.7
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/input.component.d.ts +70 -18
- package/input.component.d.ts.map +1 -1
- package/input.component.js +433 -139
- package/input.component.js.map +1 -1
- package/input.style.d.ts.map +1 -1
- package/input.style.js +246 -18
- package/input.style.js.map +1 -1
- package/{input.style.variable..d.ts → input.style.variable.d.ts} +1 -1
- package/input.style.variable.d.ts.map +1 -0
- package/{input.style.variable..js → input.style.variable.js} +78 -3
- package/input.style.variable.js.map +1 -0
- package/input.types.d.ts +38 -0
- package/input.types.d.ts.map +1 -0
- package/input.types.js +2 -0
- package/input.types.js.map +1 -0
- package/package.json +1 -1
- package/test/hy-input_test.js +1 -1
- package/test/hy-input_test.js.map +1 -1
- package/utils/index.d.ts +8 -0
- package/utils/index.d.ts.map +1 -0
- package/utils/index.js +8 -0
- package/utils/index.js.map +1 -0
- package/utils/input-renderers.d.ts +54 -0
- package/utils/input-renderers.d.ts.map +1 -0
- package/utils/input-renderers.js +174 -0
- package/utils/input-renderers.js.map +1 -0
- package/utils/input-validation.utils.d.ts +26 -0
- package/utils/input-validation.utils.d.ts.map +1 -0
- package/utils/input-validation.utils.js +105 -0
- package/utils/input-validation.utils.js.map +1 -0
- package/input.constant.d.ts +0 -18
- package/input.constant.d.ts.map +0 -1
- package/input.constant.js +0 -2
- package/input.constant.js.map +0 -1
- package/input.style.variable..d.ts.map +0 -1
- package/input.style.variable..js.map +0 -1
package/input.component.js
CHANGED
|
@@ -19,30 +19,54 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
19
19
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
20
20
|
});
|
|
21
21
|
};
|
|
22
|
-
import { LitElement, html
|
|
22
|
+
import { LitElement, html } from 'lit';
|
|
23
23
|
import { customElement, property, query, state } from 'lit/decorators.js';
|
|
24
24
|
import { styles } from './input.style.js';
|
|
25
|
-
import { EMPTY_STRING } from './input.
|
|
26
|
-
import { choose } from 'lit/directives/choose.js';
|
|
25
|
+
import { EMPTY_STRING } from './input.types.js';
|
|
27
26
|
import { NuralyUIBaseMixin } from '../../shared/base-mixin.js';
|
|
27
|
+
import { InputValidationUtils } from './utils/input-validation.utils.js';
|
|
28
|
+
import { InputRenderUtils } from './utils/input-renderers.js';
|
|
28
29
|
import '../icon/icon.component.js';
|
|
29
30
|
let NrInputElement = class NrInputElement extends NuralyUIBaseMixin(LitElement) {
|
|
30
31
|
constructor() {
|
|
31
32
|
super(...arguments);
|
|
32
33
|
this.disabled = false;
|
|
34
|
+
this.readonly = false;
|
|
33
35
|
this.state = "default" /* INPUT_STATE.Default */;
|
|
34
36
|
this.value = EMPTY_STRING;
|
|
35
37
|
this.size = "medium" /* INPUT_SIZE.Medium */;
|
|
38
|
+
this.variant = "underlined" /* INPUT_VARIANT.Underlined */;
|
|
36
39
|
this.type = "text" /* INPUT_TYPE.TEXT */;
|
|
37
40
|
this.placeholder = EMPTY_STRING;
|
|
38
41
|
this.autocomplete = 'off';
|
|
39
42
|
this.withCopy = false;
|
|
43
|
+
this.allowClear = false;
|
|
44
|
+
this.showCount = false;
|
|
40
45
|
this.inputType = EMPTY_STRING;
|
|
46
|
+
this.hasAddonBefore = false;
|
|
47
|
+
this.hasAddonAfter = false;
|
|
48
|
+
this.focused = false;
|
|
41
49
|
/**
|
|
42
50
|
* Required components that must be registered for this component to work properly
|
|
43
51
|
*/
|
|
44
52
|
this.requiredComponents = ['hy-icon'];
|
|
45
53
|
}
|
|
54
|
+
/**
|
|
55
|
+
* Get the character count display text
|
|
56
|
+
*/
|
|
57
|
+
get characterCountDisplay() {
|
|
58
|
+
const currentLength = this.value.length;
|
|
59
|
+
if (this.maxLength) {
|
|
60
|
+
return `${currentLength}/${this.maxLength}`;
|
|
61
|
+
}
|
|
62
|
+
return `${currentLength}`;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Check if character count is over the limit
|
|
66
|
+
*/
|
|
67
|
+
get isOverCharacterLimit() {
|
|
68
|
+
return this.maxLength ? this.value.length > this.maxLength : false;
|
|
69
|
+
}
|
|
46
70
|
/**
|
|
47
71
|
* Check for required dependencies when component is connected to DOM
|
|
48
72
|
*/
|
|
@@ -57,9 +81,16 @@ let NrInputElement = class NrInputElement extends NuralyUIBaseMixin(LitElement)
|
|
|
57
81
|
this.value = this.min;
|
|
58
82
|
}
|
|
59
83
|
}
|
|
84
|
+
// Validate numeric properties when they change
|
|
85
|
+
if (_changedProperties.has('type') ||
|
|
86
|
+
_changedProperties.has('min') ||
|
|
87
|
+
_changedProperties.has('max') ||
|
|
88
|
+
_changedProperties.has('step')) {
|
|
89
|
+
InputValidationUtils.validateNumericProperties(this.type, this.min, this.max, this.step);
|
|
90
|
+
}
|
|
60
91
|
}
|
|
61
92
|
updated(_changedProperties) {
|
|
62
|
-
if (_changedProperties.has('step') || _changedProperties.has('min') || _changedProperties.has('max')) {
|
|
93
|
+
if (_changedProperties.has('step') || _changedProperties.has('min') || _changedProperties.has('max') || _changedProperties.has('maxLength')) {
|
|
63
94
|
const input = this.input;
|
|
64
95
|
if (input) {
|
|
65
96
|
if (this.step)
|
|
@@ -74,63 +105,293 @@ let NrInputElement = class NrInputElement extends NuralyUIBaseMixin(LitElement)
|
|
|
74
105
|
input.setAttribute('max', this.max);
|
|
75
106
|
else
|
|
76
107
|
input.removeAttribute('max');
|
|
108
|
+
if (this.maxLength)
|
|
109
|
+
input.setAttribute('maxlength', this.maxLength.toString());
|
|
110
|
+
else
|
|
111
|
+
input.removeAttribute('maxlength');
|
|
77
112
|
}
|
|
78
113
|
}
|
|
79
114
|
}
|
|
80
|
-
|
|
81
|
-
this.
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
115
|
+
firstUpdated() {
|
|
116
|
+
this._checkInitialSlotContent();
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Check initial slot content on first render
|
|
120
|
+
*/
|
|
121
|
+
_checkInitialSlotContent() {
|
|
122
|
+
// Check for addon-before content
|
|
123
|
+
const addonBeforeElements = this.querySelectorAll('[slot="addon-before"]');
|
|
124
|
+
this.hasAddonBefore = addonBeforeElements.length > 0;
|
|
125
|
+
// Check for addon-after content
|
|
126
|
+
const addonAfterElements = this.querySelectorAll('[slot="addon-after"]');
|
|
127
|
+
this.hasAddonAfter = addonAfterElements.length > 0;
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Handle slot changes to determine addon visibility
|
|
131
|
+
*/
|
|
132
|
+
_handleSlotChange(e) {
|
|
133
|
+
const slot = e.target;
|
|
134
|
+
const slotName = slot.name;
|
|
135
|
+
if (slotName === 'addon-before') {
|
|
136
|
+
this.hasAddonBefore = slot.assignedElements().length > 0;
|
|
137
|
+
}
|
|
138
|
+
else if (slotName === 'addon-after') {
|
|
139
|
+
this.hasAddonAfter = slot.assignedElements().length > 0;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
// ========================================
|
|
143
|
+
// FOCUS MANAGEMENT METHODS
|
|
144
|
+
// ========================================
|
|
145
|
+
/**
|
|
146
|
+
* Focus the input with advanced options
|
|
147
|
+
*/
|
|
148
|
+
focus(options) {
|
|
149
|
+
if (!this.input)
|
|
150
|
+
return;
|
|
151
|
+
const focusOptions = Object.assign({ preventScroll: false }, options);
|
|
152
|
+
// Focus the input element
|
|
153
|
+
this.input.focus({ preventScroll: focusOptions.preventScroll });
|
|
154
|
+
// Handle cursor positioning
|
|
155
|
+
if (focusOptions.cursor !== undefined) {
|
|
156
|
+
this.setCursorPosition(focusOptions.cursor);
|
|
157
|
+
}
|
|
158
|
+
// Handle text selection
|
|
159
|
+
if (focusOptions.select) {
|
|
160
|
+
this.selectAll();
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Blur the input with advanced options
|
|
165
|
+
*/
|
|
166
|
+
blur(options) {
|
|
167
|
+
if (!this.input)
|
|
168
|
+
return;
|
|
169
|
+
const currentPosition = this.getCursorPosition();
|
|
170
|
+
this.input.blur();
|
|
171
|
+
// Restore cursor position if requested
|
|
172
|
+
if ((options === null || options === void 0 ? void 0 : options.restoreCursor) && currentPosition !== -1) {
|
|
173
|
+
// We'll restore it on next focus
|
|
174
|
+
this.input.dataset.restoreCursor = currentPosition.toString();
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Select all text in the input
|
|
179
|
+
*/
|
|
180
|
+
selectAll() {
|
|
181
|
+
if (!this.input)
|
|
182
|
+
return;
|
|
183
|
+
// Ensure the input is focused first
|
|
184
|
+
if (document.activeElement !== this.input) {
|
|
185
|
+
this.input.focus();
|
|
186
|
+
}
|
|
187
|
+
// Wait for next frame to ensure focus is complete
|
|
188
|
+
requestAnimationFrame(() => {
|
|
189
|
+
if (!this.input)
|
|
190
|
+
return;
|
|
191
|
+
this.input.select();
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Select a range of text in the input
|
|
196
|
+
*/
|
|
197
|
+
selectRange(start, end) {
|
|
198
|
+
if (!this.input)
|
|
199
|
+
return;
|
|
200
|
+
// Ensure the input is focused first
|
|
201
|
+
if (document.activeElement !== this.input) {
|
|
202
|
+
this.input.focus();
|
|
203
|
+
}
|
|
204
|
+
// Wait for next frame to ensure focus is complete
|
|
205
|
+
requestAnimationFrame(() => {
|
|
206
|
+
if (!this.input)
|
|
207
|
+
return;
|
|
208
|
+
const maxLength = this.input.value.length;
|
|
209
|
+
const validStart = Math.max(0, Math.min(start, maxLength));
|
|
210
|
+
const validEnd = Math.max(validStart, Math.min(end, maxLength));
|
|
211
|
+
this.input.setSelectionRange(validStart, validEnd);
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Get the current cursor position
|
|
216
|
+
*/
|
|
217
|
+
getCursorPosition() {
|
|
218
|
+
if (!this.input)
|
|
219
|
+
return -1;
|
|
220
|
+
return this.input.selectionStart || 0;
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Set the cursor position
|
|
224
|
+
*/
|
|
225
|
+
setCursorPosition(position) {
|
|
226
|
+
if (!this.input)
|
|
227
|
+
return;
|
|
228
|
+
// Ensure the input is focused first
|
|
229
|
+
if (document.activeElement !== this.input) {
|
|
230
|
+
this.input.focus();
|
|
231
|
+
}
|
|
232
|
+
requestAnimationFrame(() => {
|
|
233
|
+
if (!this.input)
|
|
234
|
+
return;
|
|
235
|
+
let pos;
|
|
236
|
+
const valueLength = this.value.length;
|
|
237
|
+
switch (position) {
|
|
238
|
+
case 'start':
|
|
239
|
+
pos = 0;
|
|
240
|
+
break;
|
|
241
|
+
case 'end':
|
|
242
|
+
pos = valueLength;
|
|
243
|
+
break;
|
|
244
|
+
case 'all':
|
|
245
|
+
this.selectAll();
|
|
246
|
+
return;
|
|
247
|
+
default:
|
|
248
|
+
pos = typeof position === 'number' ? Math.min(Math.max(0, position), valueLength) : 0;
|
|
249
|
+
}
|
|
250
|
+
this.input.setSelectionRange(pos, pos);
|
|
251
|
+
});
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* Get the currently selected text
|
|
255
|
+
*/
|
|
256
|
+
getSelectedText() {
|
|
257
|
+
if (!this.input)
|
|
258
|
+
return '';
|
|
259
|
+
const start = this.input.selectionStart || 0;
|
|
260
|
+
const end = this.input.selectionEnd || 0;
|
|
261
|
+
return this.value.substring(start, end);
|
|
262
|
+
}
|
|
263
|
+
/**
|
|
264
|
+
* Check if the input is currently focused
|
|
265
|
+
*/
|
|
266
|
+
isFocused() {
|
|
267
|
+
return this.focused && document.activeElement === this.input;
|
|
268
|
+
}
|
|
269
|
+
// ========================================
|
|
270
|
+
// EVENT HANDLING METHODS
|
|
271
|
+
// ========================================
|
|
272
|
+
/**
|
|
273
|
+
* Centralized event dispatcher to ensure consistent event structure
|
|
274
|
+
*/
|
|
275
|
+
_dispatchInputEvent(eventName, detail) {
|
|
276
|
+
this.dispatchEvent(new CustomEvent(eventName, {
|
|
277
|
+
detail,
|
|
89
278
|
bubbles: true
|
|
90
279
|
}));
|
|
91
280
|
}
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
281
|
+
_handleKeyDown(keyDownEvent) {
|
|
282
|
+
// Prevent all key input when readonly
|
|
283
|
+
if (this.readonly) {
|
|
284
|
+
const allowedReadonlyKeys = [
|
|
285
|
+
'Tab', 'Escape', 'ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown',
|
|
286
|
+
'Home', 'End', 'PageUp', 'PageDown'
|
|
287
|
+
];
|
|
288
|
+
if (keyDownEvent.ctrlKey || keyDownEvent.metaKey) {
|
|
289
|
+
const allowedCombinations = ['KeyA', 'KeyC'];
|
|
290
|
+
if (allowedCombinations.includes(keyDownEvent.code)) {
|
|
291
|
+
return;
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
if (!allowedReadonlyKeys.includes(keyDownEvent.key)) {
|
|
295
|
+
keyDownEvent.preventDefault();
|
|
296
|
+
return;
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
// Handle Enter key
|
|
300
|
+
if (keyDownEvent.key === 'Enter') {
|
|
301
|
+
this._dispatchInputEvent('nr-enter', {
|
|
302
|
+
target: keyDownEvent.target,
|
|
97
303
|
value: this.value,
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
304
|
+
originalEvent: keyDownEvent
|
|
305
|
+
});
|
|
306
|
+
return;
|
|
307
|
+
}
|
|
308
|
+
// Prevent non-numeric input for number type
|
|
309
|
+
if (this.type === "number" /* INPUT_TYPE.NUMBER */) {
|
|
310
|
+
InputValidationUtils.preventNonNumericInput(keyDownEvent, this.min);
|
|
311
|
+
if (keyDownEvent.defaultPrevented) {
|
|
312
|
+
this._dispatchInputEvent('nr-invalid-key', {
|
|
313
|
+
key: keyDownEvent.key,
|
|
314
|
+
target: keyDownEvent.target,
|
|
315
|
+
value: this.value,
|
|
316
|
+
originalEvent: keyDownEvent
|
|
317
|
+
});
|
|
318
|
+
}
|
|
319
|
+
}
|
|
103
320
|
}
|
|
104
321
|
_valueChange(e) {
|
|
322
|
+
if (this.readonly) {
|
|
323
|
+
e.preventDefault();
|
|
324
|
+
return;
|
|
325
|
+
}
|
|
105
326
|
const target = e.target;
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
327
|
+
const newValue = target.value;
|
|
328
|
+
// Check character limit
|
|
329
|
+
if (this.maxLength && newValue.length > this.maxLength) {
|
|
330
|
+
this._dispatchInputEvent('nr-character-limit-exceeded', {
|
|
331
|
+
value: newValue,
|
|
110
332
|
target: target,
|
|
333
|
+
limit: this.maxLength,
|
|
111
334
|
originalEvent: e
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
}
|
|
335
|
+
});
|
|
336
|
+
// Note: HTML maxlength attribute usually prevents this, but we dispatch event for awareness
|
|
337
|
+
}
|
|
338
|
+
if (this.type === "number" /* INPUT_TYPE.NUMBER */ && newValue) {
|
|
339
|
+
const validation = InputValidationUtils.validateNumericValue(newValue, this.min, this.max);
|
|
340
|
+
if (!validation.isValid) {
|
|
341
|
+
console.warn(validation.warnings[0]);
|
|
342
|
+
this._dispatchInputEvent('nr-validation-error', {
|
|
343
|
+
value: newValue,
|
|
344
|
+
target: target,
|
|
345
|
+
error: validation.warnings[0],
|
|
346
|
+
originalEvent: e
|
|
347
|
+
});
|
|
348
|
+
return;
|
|
349
|
+
}
|
|
350
|
+
validation.warnings.forEach(warning => console.warn(warning));
|
|
351
|
+
}
|
|
352
|
+
this.value = newValue;
|
|
353
|
+
this._dispatchInputEvent('nr-input', {
|
|
354
|
+
value: this.value,
|
|
355
|
+
target: target,
|
|
356
|
+
originalEvent: e
|
|
357
|
+
});
|
|
115
358
|
}
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
bubbles: true
|
|
125
|
-
}));
|
|
359
|
+
_focusEvent(e) {
|
|
360
|
+
this.focused = true;
|
|
361
|
+
// Handle cursor restoration if requested
|
|
362
|
+
const input = e.target;
|
|
363
|
+
if (input.dataset.restoreCursor) {
|
|
364
|
+
const position = parseInt(input.dataset.restoreCursor, 10);
|
|
365
|
+
this.setCursorPosition(position);
|
|
366
|
+
delete input.dataset.restoreCursor;
|
|
126
367
|
}
|
|
368
|
+
const focusDetail = {
|
|
369
|
+
focused: true,
|
|
370
|
+
cursorPosition: this.getCursorPosition(),
|
|
371
|
+
selectedText: this.getSelectedText()
|
|
372
|
+
};
|
|
373
|
+
this._dispatchInputEvent('nr-focus', Object.assign({ target: e.target, value: this.value }, focusDetail));
|
|
374
|
+
this._dispatchInputEvent('nr-focus-change', focusDetail);
|
|
375
|
+
}
|
|
376
|
+
_blurEvent(e) {
|
|
377
|
+
this.focused = false;
|
|
378
|
+
const focusDetail = {
|
|
379
|
+
focused: false,
|
|
380
|
+
cursorPosition: this.getCursorPosition(),
|
|
381
|
+
selectedText: this.getSelectedText()
|
|
382
|
+
};
|
|
383
|
+
this._dispatchInputEvent('nr-blur', Object.assign({ target: e.target, value: this.value }, focusDetail));
|
|
384
|
+
this._dispatchInputEvent('nr-focus-change', focusDetail);
|
|
127
385
|
}
|
|
128
386
|
_handleIconKeydown(keyDownEvent) {
|
|
129
387
|
if (keyDownEvent.key === 'Enter' || keyDownEvent.key === ' ') {
|
|
130
388
|
keyDownEvent.preventDefault();
|
|
131
389
|
const target = keyDownEvent.target;
|
|
132
390
|
if (target.id === 'copy-icon') {
|
|
133
|
-
this.
|
|
391
|
+
this._onCopy();
|
|
392
|
+
}
|
|
393
|
+
else if (target.id === 'clear-icon') {
|
|
394
|
+
this._onClear();
|
|
134
395
|
}
|
|
135
396
|
else if (target.id === 'password-icon') {
|
|
136
397
|
this._togglePasswordIcon();
|
|
@@ -145,43 +406,80 @@ let NrInputElement = class NrInputElement extends NuralyUIBaseMixin(LitElement)
|
|
|
145
406
|
}
|
|
146
407
|
}
|
|
147
408
|
}
|
|
148
|
-
|
|
409
|
+
_onCopy() {
|
|
149
410
|
return __awaiter(this, void 0, void 0, function* () {
|
|
150
411
|
try {
|
|
151
412
|
const input = this.shadowRoot.getElementById('input');
|
|
152
413
|
input.select();
|
|
153
414
|
yield navigator.clipboard.writeText(input.value);
|
|
154
|
-
this.
|
|
155
|
-
detail: { value: input.value },
|
|
156
|
-
bubbles: true
|
|
157
|
-
}));
|
|
415
|
+
this._dispatchInputEvent('nr-copy-success', { value: input.value });
|
|
158
416
|
}
|
|
159
417
|
catch (error) {
|
|
160
|
-
this.
|
|
161
|
-
detail: { error },
|
|
162
|
-
bubbles: true
|
|
163
|
-
}));
|
|
418
|
+
this._dispatchInputEvent('nr-copy-error', { error });
|
|
164
419
|
}
|
|
165
420
|
});
|
|
166
421
|
}
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
// Check if helper text slot has content
|
|
171
|
-
const helperSlot = (_a = this.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelector('slot[name="helper-text"]');
|
|
172
|
-
if (helperSlot && helperSlot.assignedNodes().length > 0) {
|
|
173
|
-
describedBy.push('helper-text');
|
|
422
|
+
_onClear() {
|
|
423
|
+
if (this.disabled || this.readonly) {
|
|
424
|
+
return;
|
|
174
425
|
}
|
|
175
|
-
|
|
426
|
+
const previousValue = this.value;
|
|
427
|
+
this.value = EMPTY_STRING;
|
|
428
|
+
// Update the input element value
|
|
429
|
+
if (this.input) {
|
|
430
|
+
this.input.value = EMPTY_STRING;
|
|
431
|
+
}
|
|
432
|
+
this._dispatchInputEvent('nr-clear', {
|
|
433
|
+
previousValue,
|
|
434
|
+
target: this.input
|
|
435
|
+
});
|
|
436
|
+
// Also dispatch input event for consistency
|
|
437
|
+
this._dispatchInputEvent('nr-input', {
|
|
438
|
+
value: this.value,
|
|
439
|
+
target: this.input,
|
|
440
|
+
action: 'clear'
|
|
441
|
+
});
|
|
176
442
|
}
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
443
|
+
// ========================================
|
|
444
|
+
// OPERATION METHODS
|
|
445
|
+
// ========================================
|
|
446
|
+
_increment() {
|
|
447
|
+
try {
|
|
448
|
+
this.input.stepUp();
|
|
449
|
+
this.value = this.input.value;
|
|
450
|
+
this._dispatchInputEvent('nr-input', {
|
|
451
|
+
value: this.value,
|
|
452
|
+
target: this.input,
|
|
453
|
+
action: 'increment'
|
|
454
|
+
});
|
|
455
|
+
}
|
|
456
|
+
catch (error) {
|
|
457
|
+
console.warn('Failed to increment value:', error);
|
|
458
|
+
this._dispatchInputEvent('nr-increment-error', {
|
|
459
|
+
error,
|
|
460
|
+
value: this.value,
|
|
461
|
+
target: this.input
|
|
462
|
+
});
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
_decrement() {
|
|
466
|
+
try {
|
|
467
|
+
this.input.stepDown();
|
|
468
|
+
this.value = this.input.value;
|
|
469
|
+
this._dispatchInputEvent('nr-input', {
|
|
470
|
+
value: this.value,
|
|
471
|
+
target: this.input,
|
|
472
|
+
action: 'decrement'
|
|
473
|
+
});
|
|
474
|
+
}
|
|
475
|
+
catch (error) {
|
|
476
|
+
console.warn('Failed to decrement value:', error);
|
|
477
|
+
this._dispatchInputEvent('nr-decrement-error', {
|
|
478
|
+
error,
|
|
479
|
+
value: this.value,
|
|
480
|
+
target: this.input
|
|
481
|
+
});
|
|
482
|
+
}
|
|
185
483
|
}
|
|
186
484
|
_togglePasswordIcon() {
|
|
187
485
|
if (this.inputType === "password" /* INPUT_TYPE.PASSWORD */) {
|
|
@@ -191,84 +489,56 @@ let NrInputElement = class NrInputElement extends NuralyUIBaseMixin(LitElement)
|
|
|
191
489
|
this.inputType = "password" /* INPUT_TYPE.PASSWORD */;
|
|
192
490
|
}
|
|
193
491
|
}
|
|
492
|
+
_getAriaDescribedBy() {
|
|
493
|
+
var _a;
|
|
494
|
+
const describedBy = [];
|
|
495
|
+
const helperSlot = (_a = this.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelector('slot[name="helper-text"]');
|
|
496
|
+
if (helperSlot && helperSlot.assignedNodes().length > 0) {
|
|
497
|
+
describedBy.push('helper-text');
|
|
498
|
+
}
|
|
499
|
+
return describedBy.join(' ') || '';
|
|
500
|
+
}
|
|
501
|
+
// ========================================
|
|
502
|
+
// RENDER METHODS
|
|
503
|
+
// ========================================
|
|
194
504
|
render() {
|
|
195
505
|
return html `
|
|
196
506
|
<slot name="label"></slot>
|
|
197
|
-
<div data-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
["warning" /* INPUT_STATE.Warning */, () => html `<hy-icon name="warning" id="warning-icon"></hy-icon>`],
|
|
226
|
-
["error" /* INPUT_STATE.Error */, () => html `<hy-icon name="exclamation-circle" id="error-icon"></hy-icon>`],
|
|
227
|
-
])}
|
|
228
|
-
${this.state == "default" /* INPUT_STATE.Default */ && this.type == "calendar" /* INPUT_TYPE.CALENDAR */
|
|
229
|
-
? html `<hy-icon name="calendar" type="regular" id="calendar-icon"></hy-icon>`
|
|
230
|
-
: nothing}
|
|
231
|
-
${this.type == "password" /* INPUT_TYPE.PASSWORD */
|
|
232
|
-
? choose(this.inputType, [
|
|
233
|
-
[
|
|
234
|
-
"text" /* INPUT_TYPE.TEXT */,
|
|
235
|
-
() => html `<hy-icon
|
|
236
|
-
name="eye-slash"
|
|
237
|
-
type="regular"
|
|
238
|
-
id="password-icon"
|
|
239
|
-
role="button"
|
|
240
|
-
aria-label="Hide password"
|
|
241
|
-
tabindex="0"
|
|
242
|
-
@click=${!this.disabled ? this._togglePasswordIcon : nothing}
|
|
243
|
-
@keydown=${this._handleIconKeydown}
|
|
244
|
-
></hy-icon>`,
|
|
245
|
-
],
|
|
246
|
-
[
|
|
247
|
-
"password" /* INPUT_TYPE.PASSWORD */,
|
|
248
|
-
() => html `<hy-icon
|
|
249
|
-
name="eye"
|
|
250
|
-
type="regular"
|
|
251
|
-
id="password-icon"
|
|
252
|
-
role="button"
|
|
253
|
-
aria-label="Show password"
|
|
254
|
-
tabindex="0"
|
|
255
|
-
@click=${!this.disabled ? this._togglePasswordIcon : nothing}
|
|
256
|
-
@keydown=${this._handleIconKeydown}
|
|
257
|
-
></hy-icon>`,
|
|
258
|
-
],
|
|
259
|
-
])
|
|
260
|
-
: this.type == "number" /* INPUT_TYPE.NUMBER */
|
|
261
|
-
? html `
|
|
262
|
-
<div id="number-icons">
|
|
263
|
-
${this.state != "default" /* INPUT_STATE.Default */ ? html `<span id="icons-separator">|</span>` : nothing}
|
|
264
|
-
<hy-icon name="minus" @click=${!this.disabled ? this._decrement : nothing}></hy-icon>
|
|
265
|
-
<span id="icons-separator">|</span>
|
|
266
|
-
<hy-icon name="plus" @click=${!this.disabled ? this._increment : nothing}></hy-icon>
|
|
267
|
-
</div>
|
|
268
|
-
`
|
|
269
|
-
: nothing}
|
|
507
|
+
<div class="input-wrapper" data-theme="${this.currentTheme}">
|
|
508
|
+
${InputRenderUtils.renderAddonBefore(this.hasAddonBefore, (e) => this._handleSlotChange(e))}
|
|
509
|
+
<div data-size=${this.size} id="input-container">
|
|
510
|
+
${InputRenderUtils.renderPrefix()}
|
|
511
|
+
<input
|
|
512
|
+
id="input"
|
|
513
|
+
.disabled=${this.disabled}
|
|
514
|
+
.readOnly=${this.readonly}
|
|
515
|
+
.value=${this.value}
|
|
516
|
+
.placeholder=${this.placeholder}
|
|
517
|
+
.type="${this.inputType}"
|
|
518
|
+
.autocomplete=${this.autocomplete}
|
|
519
|
+
aria-invalid=${this.state === "error" /* INPUT_STATE.Error */ ? 'true' : 'false'}
|
|
520
|
+
aria-describedby=${this._getAriaDescribedBy()}
|
|
521
|
+
@input=${this._valueChange}
|
|
522
|
+
@focus=${this._focusEvent}
|
|
523
|
+
@blur=${this._blurEvent}
|
|
524
|
+
@keydown=${this._handleKeyDown}
|
|
525
|
+
/>
|
|
526
|
+
${InputRenderUtils.renderSuffix()}
|
|
527
|
+
${InputRenderUtils.renderCopyIcon(this.withCopy, this.disabled, this.readonly, () => this._onCopy(), (e) => this._handleIconKeydown(e))}
|
|
528
|
+
${InputRenderUtils.renderClearIcon(this.allowClear, this.value, this.disabled, this.readonly, () => this._onClear(), (e) => this._handleIconKeydown(e))}
|
|
529
|
+
${InputRenderUtils.renderStateIcon(this.state)}
|
|
530
|
+
${InputRenderUtils.renderCalendarIcon(this.state, this.type)}
|
|
531
|
+
${InputRenderUtils.renderPasswordIcon(this.type, this.inputType, this.disabled, this.readonly, () => this._togglePasswordIcon(), (e) => this._handleIconKeydown(e))}
|
|
532
|
+
${InputRenderUtils.renderNumberIcons(this.type, this.state, this.disabled, this.readonly, () => this._increment(), () => this._decrement(), (e) => this._handleIconKeydown(e))}
|
|
533
|
+
</div>
|
|
534
|
+
${InputRenderUtils.renderAddonAfter(this.hasAddonAfter, (e) => this._handleSlotChange(e))}
|
|
270
535
|
</div>
|
|
271
536
|
<slot name="helper-text"></slot>
|
|
537
|
+
${this.showCount ? html `
|
|
538
|
+
<div class="character-count" ?data-over-limit=${this.isOverCharacterLimit}>
|
|
539
|
+
${this.characterCountDisplay}
|
|
540
|
+
</div>
|
|
541
|
+
` : ''}
|
|
272
542
|
`;
|
|
273
543
|
}
|
|
274
544
|
};
|
|
@@ -276,6 +546,9 @@ NrInputElement.styles = styles;
|
|
|
276
546
|
__decorate([
|
|
277
547
|
property({ type: Boolean, reflect: true })
|
|
278
548
|
], NrInputElement.prototype, "disabled", void 0);
|
|
549
|
+
__decorate([
|
|
550
|
+
property({ type: Boolean, reflect: true })
|
|
551
|
+
], NrInputElement.prototype, "readonly", void 0);
|
|
279
552
|
__decorate([
|
|
280
553
|
property({ type: String, reflect: true })
|
|
281
554
|
], NrInputElement.prototype, "state", void 0);
|
|
@@ -285,6 +558,9 @@ __decorate([
|
|
|
285
558
|
__decorate([
|
|
286
559
|
property({ type: String })
|
|
287
560
|
], NrInputElement.prototype, "size", void 0);
|
|
561
|
+
__decorate([
|
|
562
|
+
property({ type: String, reflect: true })
|
|
563
|
+
], NrInputElement.prototype, "variant", void 0);
|
|
288
564
|
__decorate([
|
|
289
565
|
property({ reflect: true })
|
|
290
566
|
], NrInputElement.prototype, "type", void 0);
|
|
@@ -306,9 +582,27 @@ __decorate([
|
|
|
306
582
|
__decorate([
|
|
307
583
|
property({ type: Boolean, reflect: true })
|
|
308
584
|
], NrInputElement.prototype, "withCopy", void 0);
|
|
585
|
+
__decorate([
|
|
586
|
+
property({ type: Boolean, reflect: true })
|
|
587
|
+
], NrInputElement.prototype, "allowClear", void 0);
|
|
588
|
+
__decorate([
|
|
589
|
+
property({ type: Boolean, reflect: true })
|
|
590
|
+
], NrInputElement.prototype, "showCount", void 0);
|
|
591
|
+
__decorate([
|
|
592
|
+
property({ type: Number })
|
|
593
|
+
], NrInputElement.prototype, "maxLength", void 0);
|
|
309
594
|
__decorate([
|
|
310
595
|
state()
|
|
311
596
|
], NrInputElement.prototype, "inputType", void 0);
|
|
597
|
+
__decorate([
|
|
598
|
+
state()
|
|
599
|
+
], NrInputElement.prototype, "hasAddonBefore", void 0);
|
|
600
|
+
__decorate([
|
|
601
|
+
state()
|
|
602
|
+
], NrInputElement.prototype, "hasAddonAfter", void 0);
|
|
603
|
+
__decorate([
|
|
604
|
+
state()
|
|
605
|
+
], NrInputElement.prototype, "focused", void 0);
|
|
312
606
|
__decorate([
|
|
313
607
|
query('#input')
|
|
314
608
|
], NrInputElement.prototype, "input", void 0);
|