tyrell-components 1.0.0-RC13 → 1.0.0-RC14
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 +1 -1
- package/css/tyrell-theme.css +167 -178
- package/css/tyrell.css +19 -0
- package/dist/tyrell-theme.css +167 -178
- package/dist/tyrell.css +19 -0
- package/dist/tyrell.js +1 -1
- package/lib/base/ty-component.d.ts +20 -10
- package/lib/base/ty-component.js +21 -144
- package/lib/components/button.d.ts +2 -16
- package/lib/components/button.js +0 -36
- package/lib/components/calendar-month.d.ts +2 -48
- package/lib/components/calendar-month.js +4 -166
- package/lib/components/calendar-navigation.d.ts +3 -48
- package/lib/components/calendar-navigation.js +3 -126
- package/lib/components/calendar.d.ts +3 -80
- package/lib/components/calendar.js +8 -230
- package/lib/components/checkbox.d.ts +4 -71
- package/lib/components/checkbox.js +7 -151
- package/lib/components/copy.d.ts +3 -56
- package/lib/components/copy.js +1 -120
- package/lib/components/date-picker.d.ts +13 -162
- package/lib/components/date-picker.js +41 -592
- package/lib/components/file-upload.d.ts +9 -15
- package/lib/components/file-upload.js +19 -41
- package/lib/components/icon.d.ts +3 -24
- package/lib/components/icon.js +1 -90
- package/lib/components/input.d.ts +7 -107
- package/lib/components/input.js +5 -193
- package/lib/components/modal.d.ts +17 -26
- package/lib/components/modal.js +57 -201
- package/lib/components/option.d.ts +2 -9
- package/lib/components/option.js +0 -48
- package/lib/components/popup.d.ts +2 -17
- package/lib/components/popup.js +8 -139
- package/lib/components/radio.d.ts +3 -23
- package/lib/components/radio.js +10 -65
- package/lib/components/resize-observer.d.ts +3 -30
- package/lib/components/resize-observer.js +12 -46
- package/lib/components/scroll-container.d.ts +2 -12
- package/lib/components/scroll-container.js +3 -46
- package/lib/components/select.d.ts +22 -153
- package/lib/components/select.js +33 -590
- package/lib/components/selected-tags.d.ts +4 -47
- package/lib/components/selected-tags.js +1 -95
- package/lib/components/step.d.ts +1 -6
- package/lib/components/step.js +0 -6
- package/lib/components/switch.d.ts +0 -11
- package/lib/components/switch.js +2 -36
- package/lib/components/tab.d.ts +1 -6
- package/lib/components/tab.js +0 -7
- package/lib/components/tabs.d.ts +5 -63
- package/lib/components/tabs.js +20 -283
- package/lib/components/tag.d.ts +2 -36
- package/lib/components/tag.js +5 -105
- package/lib/components/textarea.d.ts +6 -86
- package/lib/components/textarea.js +2 -173
- package/lib/components/tooltip.d.ts +3 -11
- package/lib/components/tooltip.js +24 -160
- package/lib/components/wizard.d.ts +6 -54
- package/lib/components/wizard.js +15 -228
- package/lib/icons/fontawesome/brands.d.ts +0 -1
- package/lib/icons/fontawesome/brands.js +0 -8
- package/lib/icons/fontawesome/regular.d.ts +0 -1
- package/lib/icons/fontawesome/regular.js +0 -8
- package/lib/icons/fontawesome/solid.d.ts +0 -1
- package/lib/icons/fontawesome/solid.js +0 -8
- package/lib/icons/heroicons/micro.d.ts +0 -1
- package/lib/icons/heroicons/micro.js +0 -8
- package/lib/icons/heroicons/mini.d.ts +0 -1
- package/lib/icons/heroicons/mini.js +0 -8
- package/lib/icons/heroicons/outline.d.ts +0 -1
- package/lib/icons/heroicons/outline.js +0 -8
- package/lib/icons/heroicons/solid.d.ts +0 -1
- package/lib/icons/heroicons/solid.js +0 -8
- package/lib/icons/lucide.d.ts +0 -1
- package/lib/icons/lucide.js +0 -1872
- package/lib/icons/material/filled.d.ts +0 -1
- package/lib/icons/material/filled.js +0 -10
- package/lib/icons/material/outlined.d.ts +0 -1
- package/lib/icons/material/outlined.js +0 -10
- package/lib/icons/material/round.d.ts +0 -1
- package/lib/icons/material/round.js +0 -10
- package/lib/icons/material/sharp.d.ts +0 -1
- package/lib/icons/material/sharp.js +0 -10
- package/lib/icons/material/two-tone.d.ts +0 -1
- package/lib/icons/material/two-tone.js +0 -10
- package/lib/index.d.ts +0 -1
- package/lib/index.js +0 -20
- package/lib/styles/button.d.ts +2 -20
- package/lib/styles/button.js +22 -122
- package/lib/styles/calendar-month.d.ts +1 -5
- package/lib/styles/calendar-month.js +4 -61
- package/lib/styles/calendar-navigation.d.ts +2 -6
- package/lib/styles/calendar-navigation.js +2 -27
- package/lib/styles/calendar.d.ts +1 -2
- package/lib/styles/calendar.js +1 -14
- package/lib/styles/checkbox.d.ts +0 -1
- package/lib/styles/checkbox.js +1 -23
- package/lib/styles/copy.d.ts +0 -1
- package/lib/styles/copy.js +2 -17
- package/lib/styles/custom-scrollbar.d.ts +1 -2
- package/lib/styles/custom-scrollbar.js +3 -18
- package/lib/styles/date-picker.d.ts +1 -5
- package/lib/styles/date-picker.js +35 -39
- package/lib/styles/file-upload.d.ts +1 -2
- package/lib/styles/file-upload.js +1 -16
- package/lib/styles/icon.d.ts +2 -6
- package/lib/styles/icon.js +7 -21
- package/lib/styles/input.d.ts +1 -6
- package/lib/styles/input.js +5 -54
- package/lib/styles/modal.d.ts +1 -2
- package/lib/styles/modal.js +21 -23
- package/lib/styles/option.d.ts +2 -6
- package/lib/styles/option.js +17 -12
- package/lib/styles/popup.d.ts +1 -2
- package/lib/styles/popup.js +26 -30
- package/lib/styles/radio.d.ts +0 -1
- package/lib/styles/radio.js +2 -16
- package/lib/styles/resize-observer.d.ts +1 -2
- package/lib/styles/resize-observer.js +0 -7
- package/lib/styles/scroll-container.d.ts +1 -2
- package/lib/styles/scroll-container.js +0 -19
- package/lib/styles/select-base.d.ts +0 -1
- package/lib/styles/select-base.js +68 -79
- package/lib/styles/select.d.ts +1 -2
- package/lib/styles/select.js +7 -15
- package/lib/styles/step.d.ts +1 -2
- package/lib/styles/step.js +0 -4
- package/lib/styles/switch.d.ts +0 -1
- package/lib/styles/switch.js +2 -20
- package/lib/styles/tab.d.ts +1 -2
- package/lib/styles/tab.js +0 -5
- package/lib/styles/tabs.d.ts +3 -11
- package/lib/styles/tabs.js +10 -48
- package/lib/styles/tag.d.ts +1 -5
- package/lib/styles/tag.js +2 -31
- package/lib/styles/textarea.d.ts +1 -2
- package/lib/styles/textarea.js +2 -45
- package/lib/styles/tooltip.d.ts +0 -1
- package/lib/styles/tooltip.js +0 -10
- package/lib/styles/wizard.d.ts +5 -21
- package/lib/styles/wizard.js +8 -88
- package/lib/types/common.d.ts +0 -2
- package/lib/types/common.js +0 -12
- package/lib/utils/calendar-utils.d.ts +4 -21
- package/lib/utils/calendar-utils.js +4 -177
- package/lib/utils/custom-scrollbar.d.ts +6 -20
- package/lib/utils/custom-scrollbar.js +1 -45
- package/lib/utils/flavor-sheet.d.ts +0 -1
- package/lib/utils/flavor-sheet.js +0 -23
- package/lib/utils/icon-registry.d.ts +0 -2
- package/lib/utils/icon-registry.js +1 -107
- package/lib/utils/icons.d.ts +0 -1
- package/lib/utils/icons.js +0 -9
- package/lib/utils/loader-registry.d.ts +0 -1
- package/lib/utils/loader-registry.js +0 -32
- package/lib/utils/locale.d.ts +2 -23
- package/lib/utils/locale.js +0 -86
- package/lib/utils/mobile.d.ts +0 -1
- package/lib/utils/mobile.js +0 -17
- package/lib/utils/number-format.d.ts +6 -3
- package/lib/utils/number-format.js +11 -67
- package/lib/utils/positioning.d.ts +50 -7
- package/lib/utils/positioning.js +52 -62
- package/lib/utils/property-capture.d.ts +5 -27
- package/lib/utils/property-capture.js +0 -108
- package/lib/utils/property-manager.d.ts +0 -1
- package/lib/utils/property-manager.js +0 -70
- package/lib/utils/resize-observer.d.ts +0 -1
- package/lib/utils/resize-observer.js +0 -36
- package/lib/utils/scroll-lock.d.ts +4 -11
- package/lib/utils/scroll-lock.js +0 -107
- package/lib/utils/styles.d.ts +0 -1
- package/lib/utils/styles.js +0 -24
- package/lib/version.d.ts +1 -2
- package/lib/version.js +1 -11
- package/package.json +2 -2
- package/lib/base/ty-component.d.ts.map +0 -1
- package/lib/base/ty-component.js.map +0 -1
- package/lib/components/button.d.ts.map +0 -1
- package/lib/components/button.js.map +0 -1
- package/lib/components/calendar-month.d.ts.map +0 -1
- package/lib/components/calendar-month.js.map +0 -1
- package/lib/components/calendar-navigation.d.ts.map +0 -1
- package/lib/components/calendar-navigation.js.map +0 -1
- package/lib/components/calendar.d.ts.map +0 -1
- package/lib/components/calendar.js.map +0 -1
- package/lib/components/checkbox.d.ts.map +0 -1
- package/lib/components/checkbox.js.map +0 -1
- package/lib/components/copy.d.ts.map +0 -1
- package/lib/components/copy.js.map +0 -1
- package/lib/components/date-picker.d.ts.map +0 -1
- package/lib/components/date-picker.js.map +0 -1
- package/lib/components/file-upload.d.ts.map +0 -1
- package/lib/components/file-upload.js.map +0 -1
- package/lib/components/icon.d.ts.map +0 -1
- package/lib/components/icon.js.map +0 -1
- package/lib/components/input.d.ts.map +0 -1
- package/lib/components/input.js.map +0 -1
- package/lib/components/modal.d.ts.map +0 -1
- package/lib/components/modal.js.map +0 -1
- package/lib/components/option.d.ts.map +0 -1
- package/lib/components/option.js.map +0 -1
- package/lib/components/popup.d.ts.map +0 -1
- package/lib/components/popup.js.map +0 -1
- package/lib/components/radio.d.ts.map +0 -1
- package/lib/components/radio.js.map +0 -1
- package/lib/components/resize-observer.d.ts.map +0 -1
- package/lib/components/resize-observer.js.map +0 -1
- package/lib/components/scroll-container.d.ts.map +0 -1
- package/lib/components/scroll-container.js.map +0 -1
- package/lib/components/select.d.ts.map +0 -1
- package/lib/components/select.js.map +0 -1
- package/lib/components/selected-tags.d.ts.map +0 -1
- package/lib/components/selected-tags.js.map +0 -1
- package/lib/components/step.d.ts.map +0 -1
- package/lib/components/step.js.map +0 -1
- package/lib/components/switch.d.ts.map +0 -1
- package/lib/components/switch.js.map +0 -1
- package/lib/components/tab.d.ts.map +0 -1
- package/lib/components/tab.js.map +0 -1
- package/lib/components/tabs.d.ts.map +0 -1
- package/lib/components/tabs.js.map +0 -1
- package/lib/components/tag.d.ts.map +0 -1
- package/lib/components/tag.js.map +0 -1
- package/lib/components/textarea.d.ts.map +0 -1
- package/lib/components/textarea.js.map +0 -1
- package/lib/components/tooltip.d.ts.map +0 -1
- package/lib/components/tooltip.js.map +0 -1
- package/lib/components/wizard.d.ts.map +0 -1
- package/lib/components/wizard.js.map +0 -1
- package/lib/icons/fontawesome/brands.d.ts.map +0 -1
- package/lib/icons/fontawesome/brands.js.map +0 -1
- package/lib/icons/fontawesome/regular.d.ts.map +0 -1
- package/lib/icons/fontawesome/regular.js.map +0 -1
- package/lib/icons/fontawesome/solid.d.ts.map +0 -1
- package/lib/icons/fontawesome/solid.js.map +0 -1
- package/lib/icons/heroicons/micro.d.ts.map +0 -1
- package/lib/icons/heroicons/micro.js.map +0 -1
- package/lib/icons/heroicons/mini.d.ts.map +0 -1
- package/lib/icons/heroicons/mini.js.map +0 -1
- package/lib/icons/heroicons/outline.d.ts.map +0 -1
- package/lib/icons/heroicons/outline.js.map +0 -1
- package/lib/icons/heroicons/solid.d.ts.map +0 -1
- package/lib/icons/heroicons/solid.js.map +0 -1
- package/lib/icons/lucide.d.ts.map +0 -1
- package/lib/icons/lucide.js.map +0 -1
- package/lib/icons/material/filled.d.ts.map +0 -1
- package/lib/icons/material/filled.js.map +0 -1
- package/lib/icons/material/outlined.d.ts.map +0 -1
- package/lib/icons/material/outlined.js.map +0 -1
- package/lib/icons/material/round.d.ts.map +0 -1
- package/lib/icons/material/round.js.map +0 -1
- package/lib/icons/material/sharp.d.ts.map +0 -1
- package/lib/icons/material/sharp.js.map +0 -1
- package/lib/icons/material/two-tone.d.ts.map +0 -1
- package/lib/icons/material/two-tone.js.map +0 -1
- package/lib/index.d.ts.map +0 -1
- package/lib/index.js.map +0 -1
- package/lib/styles/button.d.ts.map +0 -1
- package/lib/styles/button.js.map +0 -1
- package/lib/styles/calendar-month.d.ts.map +0 -1
- package/lib/styles/calendar-month.js.map +0 -1
- package/lib/styles/calendar-navigation.d.ts.map +0 -1
- package/lib/styles/calendar-navigation.js.map +0 -1
- package/lib/styles/calendar.d.ts.map +0 -1
- package/lib/styles/calendar.js.map +0 -1
- package/lib/styles/checkbox.d.ts.map +0 -1
- package/lib/styles/checkbox.js.map +0 -1
- package/lib/styles/copy.d.ts.map +0 -1
- package/lib/styles/copy.js.map +0 -1
- package/lib/styles/custom-scrollbar.d.ts.map +0 -1
- package/lib/styles/custom-scrollbar.js.map +0 -1
- package/lib/styles/date-picker.d.ts.map +0 -1
- package/lib/styles/date-picker.js.map +0 -1
- package/lib/styles/file-upload.d.ts.map +0 -1
- package/lib/styles/file-upload.js.map +0 -1
- package/lib/styles/icon.d.ts.map +0 -1
- package/lib/styles/icon.js.map +0 -1
- package/lib/styles/input.d.ts.map +0 -1
- package/lib/styles/input.js.map +0 -1
- package/lib/styles/modal.d.ts.map +0 -1
- package/lib/styles/modal.js.map +0 -1
- package/lib/styles/multiselect.d.ts +0 -8
- package/lib/styles/multiselect.d.ts.map +0 -1
- package/lib/styles/multiselect.js +0 -849
- package/lib/styles/multiselect.js.map +0 -1
- package/lib/styles/option.d.ts.map +0 -1
- package/lib/styles/option.js.map +0 -1
- package/lib/styles/popup.d.ts.map +0 -1
- package/lib/styles/popup.js.map +0 -1
- package/lib/styles/radio.d.ts.map +0 -1
- package/lib/styles/radio.js.map +0 -1
- package/lib/styles/resize-observer.d.ts.map +0 -1
- package/lib/styles/resize-observer.js.map +0 -1
- package/lib/styles/scroll-container.d.ts.map +0 -1
- package/lib/styles/scroll-container.js.map +0 -1
- package/lib/styles/select-base.d.ts.map +0 -1
- package/lib/styles/select-base.js.map +0 -1
- package/lib/styles/select.d.ts.map +0 -1
- package/lib/styles/select.js.map +0 -1
- package/lib/styles/step.d.ts.map +0 -1
- package/lib/styles/step.js.map +0 -1
- package/lib/styles/switch.d.ts.map +0 -1
- package/lib/styles/switch.js.map +0 -1
- package/lib/styles/tab.d.ts.map +0 -1
- package/lib/styles/tab.js.map +0 -1
- package/lib/styles/tabs.d.ts.map +0 -1
- package/lib/styles/tabs.js.map +0 -1
- package/lib/styles/tag.d.ts.map +0 -1
- package/lib/styles/tag.js.map +0 -1
- package/lib/styles/textarea.d.ts.map +0 -1
- package/lib/styles/textarea.js.map +0 -1
- package/lib/styles/tooltip.d.ts.map +0 -1
- package/lib/styles/tooltip.js.map +0 -1
- package/lib/styles/wizard.d.ts.map +0 -1
- package/lib/styles/wizard.js.map +0 -1
- package/lib/types/common.d.ts.map +0 -1
- package/lib/types/common.js.map +0 -1
- package/lib/utils/calendar-utils.d.ts.map +0 -1
- package/lib/utils/calendar-utils.js.map +0 -1
- package/lib/utils/custom-scrollbar.d.ts.map +0 -1
- package/lib/utils/custom-scrollbar.js.map +0 -1
- package/lib/utils/flavor-sheet.d.ts.map +0 -1
- package/lib/utils/flavor-sheet.js.map +0 -1
- package/lib/utils/icon-registry.d.ts.map +0 -1
- package/lib/utils/icon-registry.js.map +0 -1
- package/lib/utils/icons.d.ts.map +0 -1
- package/lib/utils/icons.js.map +0 -1
- package/lib/utils/loader-registry.d.ts.map +0 -1
- package/lib/utils/loader-registry.js.map +0 -1
- package/lib/utils/locale.d.ts.map +0 -1
- package/lib/utils/locale.js.map +0 -1
- package/lib/utils/mobile.d.ts.map +0 -1
- package/lib/utils/mobile.js.map +0 -1
- package/lib/utils/number-format.d.ts.map +0 -1
- package/lib/utils/number-format.js.map +0 -1
- package/lib/utils/parse-boolean.d.ts +0 -39
- package/lib/utils/parse-boolean.d.ts.map +0 -1
- package/lib/utils/parse-boolean.js +0 -58
- package/lib/utils/parse-boolean.js.map +0 -1
- package/lib/utils/positioning.d.ts.map +0 -1
- package/lib/utils/positioning.js.map +0 -1
- package/lib/utils/property-capture.d.ts.map +0 -1
- package/lib/utils/property-capture.js.map +0 -1
- package/lib/utils/property-manager.d.ts.map +0 -1
- package/lib/utils/property-manager.js.map +0 -1
- package/lib/utils/resize-observer.d.ts.map +0 -1
- package/lib/utils/resize-observer.js.map +0 -1
- package/lib/utils/scroll-lock.d.ts.map +0 -1
- package/lib/utils/scroll-lock.js.map +0 -1
- package/lib/utils/styles.d.ts.map +0 -1
- package/lib/utils/styles.js.map +0 -1
- package/lib/version.d.ts.map +0 -1
- package/lib/version.js.map +0 -1
package/lib/components/input.js
CHANGED
|
@@ -1,19 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* TyInput Web Component
|
|
3
|
-
* PORTED FROM: clj/ty/components/input.cljs
|
|
4
|
-
* Phase D: Complete with debounce feature for input and change events
|
|
5
|
-
*
|
|
6
|
-
* Enhanced input component with:
|
|
7
|
-
* - Label, error messages, semantic styling
|
|
8
|
-
* - Icon slots (start/end)
|
|
9
|
-
* - Numeric formatting with shadow values
|
|
10
|
-
* - Currency, percent, compact notation
|
|
11
|
-
* - Format-on-blur / raw-on-focus behavior
|
|
12
|
-
* - Debounce (0-5000ms) for input/change events
|
|
13
|
-
* - Immediate event firing on blur (cancels pending debounce)
|
|
14
|
-
*
|
|
15
|
-
* NOTE: Checkbox functionality is in separate ty-checkbox component
|
|
16
|
-
*/
|
|
17
1
|
import { TyComponent } from '../base/ty-component.js';
|
|
18
2
|
import { ensureStyles } from '../utils/styles.js';
|
|
19
3
|
import { syncCustomFlavorSheet } from '../utils/flavor-sheet.js';
|
|
@@ -21,70 +5,41 @@ import { inputStyles, inputCustomFlavorCss } from '../styles/input.js';
|
|
|
21
5
|
import { formatNumber, parseNumericValue, shouldFormat as shouldFormatType } from '../utils/number-format.js';
|
|
22
6
|
import { getEffectiveLocale, observeLocaleChanges } from '../utils/locale.js';
|
|
23
7
|
import { REQUIRED_ICON_SVG } from '../utils/icons.js';
|
|
24
|
-
/** Password reveal toggle icons (Lucide eye / eye-off) */
|
|
25
8
|
const EYE_ICON_SVG = `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M2.062 12.348a1 1 0 0 1 0-.696 10.75 10.75 0 0 1 19.876 0 1 1 0 0 1 0 .696 10.75 10.75 0 0 1-19.876 0"/><circle cx="12" cy="12" r="3"/></svg>`;
|
|
26
9
|
const EYE_OFF_ICON_SVG = `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M10.733 5.076a10.744 10.744 0 0 1 11.205 6.575 1 1 0 0 1 0 .696 10.747 10.747 0 0 1-1.444 2.49"/><path d="M14.084 14.158a3 3 0 0 1-4.242-4.242"/><path d="M17.479 17.499a10.75 10.75 0 0 1-15.417-5.151 1 1 0 0 1 0-.696 10.75 10.75 0 0 1 4.446-5.143"/><path d="m2 2 20 20"/></svg>`;
|
|
27
10
|
export class TyInput extends TyComponent {
|
|
28
11
|
constructor() {
|
|
29
|
-
super();
|
|
30
|
-
// ============================================================================
|
|
31
|
-
// INTERNAL STATE - Not managed by PropertyManager
|
|
32
|
-
// NOTE: _internals provided by TyComponent base class
|
|
33
|
-
// ============================================================================
|
|
34
|
-
// Shadow value - parsed numeric value for formatting
|
|
12
|
+
super();
|
|
35
13
|
this._shadowValue = null;
|
|
36
|
-
// Focus state - toggles format/raw display
|
|
37
14
|
this._isFocused = false;
|
|
38
|
-
// Listener setup tracking
|
|
39
15
|
this._listenersSetup = false;
|
|
40
|
-
// True when WE auto-set flavor to 'danger' because `error` was present, so we
|
|
41
|
-
// know to restore 'neutral' when the error clears (and not clobber a flavor
|
|
42
|
-
// the consumer set themselves).
|
|
43
16
|
this._errorAutoDanger = false;
|
|
44
17
|
this._customFlavorSheet = null;
|
|
45
|
-
// Store references to handlers for cleanup
|
|
46
18
|
this._inputHandler = null;
|
|
47
19
|
this._changeHandler = null;
|
|
48
20
|
this._focusHandler = null;
|
|
49
21
|
this._blurHandler = null;
|
|
50
|
-
// Debounce timers
|
|
51
22
|
this._inputDebounceTimer = null;
|
|
52
23
|
this._changeDebounceTimer = null;
|
|
53
|
-
// Apply styles to shadow root
|
|
54
24
|
const shadow = this.shadowRoot;
|
|
55
25
|
ensureStyles(shadow, { css: inputStyles, id: 'ty-input' });
|
|
56
26
|
}
|
|
57
|
-
/**
|
|
58
|
-
* Called when component connects to DOM
|
|
59
|
-
* TyComponent already handled pre-connection property capture
|
|
60
|
-
*/
|
|
61
27
|
onConnect() {
|
|
62
|
-
// Initialize shadow value from current value property
|
|
63
28
|
this.initializeShadowValue();
|
|
64
|
-
// NOTE: Event listeners are set up in render() after input element is created
|
|
65
|
-
// setupEventListeners() will be called after initial render
|
|
66
|
-
// Setup locale observer to watch for ancestor lang changes
|
|
67
29
|
this._localeObserver = observeLocaleChanges(this, () => {
|
|
68
30
|
this.render();
|
|
69
31
|
});
|
|
70
32
|
this._syncCustomFlavor();
|
|
71
33
|
}
|
|
72
|
-
/** Custom (non-built-in) flavors — see utils/flavor-sheet.ts. */
|
|
73
34
|
_syncCustomFlavor() {
|
|
74
35
|
this._customFlavorSheet = syncCustomFlavorSheet(this.shadowRoot, this._customFlavorSheet, this.flavor, ({ base }) => inputCustomFlavorCss(base));
|
|
75
36
|
}
|
|
76
|
-
/**
|
|
77
|
-
* Called when component disconnects from DOM
|
|
78
|
-
*/
|
|
79
37
|
onDisconnect() {
|
|
80
|
-
// Clean up event listeners
|
|
81
38
|
this.removeEventListeners();
|
|
82
|
-
// Cleanup locale observer
|
|
83
39
|
if (this._localeObserver) {
|
|
84
40
|
this._localeObserver();
|
|
85
41
|
this._localeObserver = undefined;
|
|
86
42
|
}
|
|
87
|
-
// Clear any pending debounce timers
|
|
88
43
|
if (this._inputDebounceTimer !== null) {
|
|
89
44
|
clearTimeout(this._inputDebounceTimer);
|
|
90
45
|
this._inputDebounceTimer = null;
|
|
@@ -94,13 +49,6 @@ export class TyInput extends TyComponent {
|
|
|
94
49
|
this._changeDebounceTimer = null;
|
|
95
50
|
}
|
|
96
51
|
}
|
|
97
|
-
// ============================================================================
|
|
98
|
-
// TYCOMPONENT LIFECYCLE HOOKS
|
|
99
|
-
// ============================================================================
|
|
100
|
-
/**
|
|
101
|
-
* Handle property changes - called BEFORE render
|
|
102
|
-
* This replaces the old attributeChangedCallback logic
|
|
103
|
-
*/
|
|
104
52
|
onPropertiesChanged(changes) {
|
|
105
53
|
for (const { name, newValue } of changes) {
|
|
106
54
|
switch (name) {
|
|
@@ -108,25 +56,20 @@ export class TyInput extends TyComponent {
|
|
|
108
56
|
this._syncCustomFlavor();
|
|
109
57
|
break;
|
|
110
58
|
case 'value':
|
|
111
|
-
// Parse to shadow value for numeric types
|
|
112
59
|
this._shadowValue = this.parseShadowValue(newValue || '');
|
|
113
60
|
break;
|
|
114
61
|
case 'type':
|
|
115
|
-
// Re-parse shadow value when type changes
|
|
116
62
|
const currentValue = this.getProperty('value') || '';
|
|
117
63
|
this._shadowValue = this.parseShadowValue(currentValue);
|
|
118
64
|
break;
|
|
119
65
|
case 'error':
|
|
120
66
|
if (newValue) {
|
|
121
|
-
// Auto-set flavor to danger when an error appears on a neutral field
|
|
122
67
|
if (this.getProperty('flavor') === 'neutral') {
|
|
123
68
|
this.setProperty('flavor', 'danger');
|
|
124
69
|
this._errorAutoDanger = true;
|
|
125
70
|
}
|
|
126
71
|
}
|
|
127
72
|
else if (this._errorAutoDanger) {
|
|
128
|
-
// Error cleared and WE were the ones who set danger → restore neutral
|
|
129
|
-
// (live validation passing should drop the danger styling).
|
|
130
73
|
if (this.getProperty('flavor') === 'danger') {
|
|
131
74
|
this.setProperty('flavor', 'neutral');
|
|
132
75
|
}
|
|
@@ -136,16 +79,10 @@ export class TyInput extends TyComponent {
|
|
|
136
79
|
}
|
|
137
80
|
}
|
|
138
81
|
}
|
|
139
|
-
/**
|
|
140
|
-
* Hook: Called when form is reset
|
|
141
|
-
* Clear shadow value and focus state
|
|
142
|
-
*/
|
|
143
82
|
onFormReset() {
|
|
144
|
-
// Reset shadow value to default (empty)
|
|
145
83
|
this._shadowValue = null;
|
|
146
|
-
|
|
84
|
+
this.initializeShadowValue();
|
|
147
85
|
this._isFocused = false;
|
|
148
|
-
// Clear any pending debounce timers
|
|
149
86
|
if (this._inputDebounceTimer !== null) {
|
|
150
87
|
clearTimeout(this._inputDebounceTimer);
|
|
151
88
|
this._inputDebounceTimer = null;
|
|
@@ -156,33 +93,20 @@ export class TyInput extends TyComponent {
|
|
|
156
93
|
}
|
|
157
94
|
this.render();
|
|
158
95
|
}
|
|
159
|
-
/**
|
|
160
|
-
* Override form value to return shadow value
|
|
161
|
-
* This ensures numeric types submit their parsed values
|
|
162
|
-
*/
|
|
163
96
|
getFormValue() {
|
|
164
97
|
const formValue = this._shadowValue !== null ? String(this._shadowValue) : null;
|
|
165
98
|
return formValue;
|
|
166
99
|
}
|
|
167
|
-
/**
|
|
168
|
-
* Initialize shadow value from the initial value attribute
|
|
169
|
-
*/
|
|
170
100
|
initializeShadowValue() {
|
|
171
101
|
const currentValue = this.getProperty('value');
|
|
172
102
|
if (currentValue) {
|
|
173
103
|
this._shadowValue = this.parseShadowValue(currentValue);
|
|
174
|
-
// Update form value
|
|
175
104
|
this._internals.setFormValue(this._shadowValue !== null ? String(this._shadowValue) : null);
|
|
176
105
|
}
|
|
177
106
|
}
|
|
178
|
-
/**
|
|
179
|
-
* Parse a string value to the appropriate shadow value type
|
|
180
|
-
*/
|
|
181
107
|
parseShadowValue(value) {
|
|
182
|
-
// Defensive check: ensure value is actually a string before calling .trim()
|
|
183
108
|
if (!value || typeof value !== 'string' || value.trim() === '')
|
|
184
109
|
return null;
|
|
185
|
-
// For numeric types, parse to number
|
|
186
110
|
if (shouldFormatType(this.type)) {
|
|
187
111
|
const parsed = parseNumericValue(value);
|
|
188
112
|
if (parsed !== null && this.precision === 0) {
|
|
@@ -190,37 +114,25 @@ export class TyInput extends TyComponent {
|
|
|
190
114
|
}
|
|
191
115
|
return parsed;
|
|
192
116
|
}
|
|
193
|
-
// For other types, keep as string
|
|
194
117
|
return value;
|
|
195
118
|
}
|
|
196
|
-
/**
|
|
197
|
-
* Check if current input should format numbers
|
|
198
|
-
*/
|
|
199
119
|
shouldFormat() {
|
|
200
120
|
return shouldFormatType(this.type) &&
|
|
201
121
|
!this._isFocused &&
|
|
202
122
|
this._shadowValue !== null &&
|
|
203
123
|
typeof this._shadowValue === 'number';
|
|
204
124
|
}
|
|
205
|
-
/**
|
|
206
|
-
* Get the format configuration for current input
|
|
207
|
-
*/
|
|
208
125
|
getFormatConfig() {
|
|
209
126
|
return {
|
|
210
127
|
type: this.type,
|
|
211
|
-
locale: this.locale,
|
|
128
|
+
locale: this.locale,
|
|
212
129
|
currency: this.currency,
|
|
213
130
|
precision: this.precision
|
|
214
131
|
};
|
|
215
132
|
}
|
|
216
|
-
/**
|
|
217
|
-
* Get the display value (formatted or raw)
|
|
218
|
-
*/
|
|
219
133
|
getDisplayValue() {
|
|
220
134
|
if (this.shouldFormat()) {
|
|
221
135
|
let valueToFormat = this._shadowValue;
|
|
222
|
-
// For percent: divide by 100 (user enters 15, displays as 15%)
|
|
223
|
-
// This matches ClojureScript behavior
|
|
224
136
|
if (this.type === 'percent') {
|
|
225
137
|
valueToFormat = valueToFormat / 100;
|
|
226
138
|
}
|
|
@@ -228,14 +140,8 @@ export class TyInput extends TyComponent {
|
|
|
228
140
|
}
|
|
229
141
|
return this._shadowValue !== null ? String(this._shadowValue) : '';
|
|
230
142
|
}
|
|
231
|
-
// ============================================================================
|
|
232
|
-
// PROPERTY ACCESSORS - Simplified with TyComponent
|
|
233
|
-
// NOTE: validateFlavor removed - now handled by property configuration
|
|
234
|
-
// ============================================================================
|
|
235
|
-
// Core properties - simple getProperty/setProperty pattern
|
|
236
143
|
get type() { return this.getProperty('type'); }
|
|
237
144
|
set type(v) { this.setProperty('type', v); }
|
|
238
|
-
// Value - special getter returns shadow value
|
|
239
145
|
get value() {
|
|
240
146
|
return this._shadowValue !== null ? String(this._shadowValue) : '';
|
|
241
147
|
}
|
|
@@ -256,26 +162,19 @@ export class TyInput extends TyComponent {
|
|
|
256
162
|
set size(v) { this.setProperty('size', v); }
|
|
257
163
|
get flavor() { return this.getProperty('flavor'); }
|
|
258
164
|
set flavor(v) { this.setProperty('flavor', v); }
|
|
259
|
-
// Numeric formatting properties
|
|
260
165
|
get currency() { return this.getProperty('currency'); }
|
|
261
166
|
set currency(v) { this.setProperty('currency', v); }
|
|
262
|
-
// Locale - special getter uses getEffectiveLocale()
|
|
263
167
|
get locale() {
|
|
264
168
|
return getEffectiveLocale(this, this.getProperty('locale'));
|
|
265
169
|
}
|
|
266
170
|
set locale(v) { this.setProperty('locale', v); }
|
|
267
171
|
get precision() { return this.getProperty('precision'); }
|
|
268
172
|
set precision(v) { this.setProperty('precision', v); }
|
|
269
|
-
// Debounce property
|
|
270
173
|
get debounce() { return this.getProperty('debounce'); }
|
|
271
174
|
set debounce(v) { this.setProperty('debounce', v); }
|
|
272
|
-
// Form property
|
|
273
175
|
get form() {
|
|
274
176
|
return this._internals.form;
|
|
275
177
|
}
|
|
276
|
-
/**
|
|
277
|
-
* Build CSS class list for input wrapper
|
|
278
|
-
*/
|
|
279
178
|
buildClassList() {
|
|
280
179
|
const classes = [this.size];
|
|
281
180
|
if (this.disabled)
|
|
@@ -286,9 +185,6 @@ export class TyInput extends TyComponent {
|
|
|
286
185
|
classes.push('error');
|
|
287
186
|
return classes.join(' ');
|
|
288
187
|
}
|
|
289
|
-
/**
|
|
290
|
-
* Dispatch input event (helper method for debouncing)
|
|
291
|
-
*/
|
|
292
188
|
dispatchInputEvent(rawValue, originalEvent) {
|
|
293
189
|
this.dispatchEvent(new CustomEvent('input', {
|
|
294
190
|
detail: {
|
|
@@ -301,9 +197,6 @@ export class TyInput extends TyComponent {
|
|
|
301
197
|
composed: true
|
|
302
198
|
}));
|
|
303
199
|
}
|
|
304
|
-
/**
|
|
305
|
-
* Dispatch change event (helper method for debouncing)
|
|
306
|
-
*/
|
|
307
200
|
dispatchChangeEvent(rawValue, originalEvent) {
|
|
308
201
|
this.dispatchEvent(new CustomEvent('change', {
|
|
309
202
|
detail: {
|
|
@@ -316,9 +209,6 @@ export class TyInput extends TyComponent {
|
|
|
316
209
|
composed: true
|
|
317
210
|
}));
|
|
318
211
|
}
|
|
319
|
-
/**
|
|
320
|
-
* Remove event listeners for cleanup
|
|
321
|
-
*/
|
|
322
212
|
removeEventListeners() {
|
|
323
213
|
if (!this._listenersSetup)
|
|
324
214
|
return;
|
|
@@ -328,7 +218,6 @@ export class TyInput extends TyComponent {
|
|
|
328
218
|
const inputEl = shadow.querySelector('input');
|
|
329
219
|
if (!inputEl)
|
|
330
220
|
return;
|
|
331
|
-
// Remove all event listeners using stored handler references
|
|
332
221
|
if (this._inputHandler) {
|
|
333
222
|
inputEl.removeEventListener('input', this._inputHandler);
|
|
334
223
|
this._inputHandler = null;
|
|
@@ -347,13 +236,9 @@ export class TyInput extends TyComponent {
|
|
|
347
236
|
}
|
|
348
237
|
this._listenersSetup = false;
|
|
349
238
|
}
|
|
350
|
-
/**
|
|
351
|
-
* Setup event listeners for input element
|
|
352
|
-
* IMPORTANT: Only called ONCE, not on every render (like ClojureScript)
|
|
353
|
-
*/
|
|
354
239
|
setupEventListeners() {
|
|
355
240
|
if (this._listenersSetup) {
|
|
356
|
-
return;
|
|
241
|
+
return;
|
|
357
242
|
}
|
|
358
243
|
const shadow = this.shadowRoot;
|
|
359
244
|
const inputEl = shadow.querySelector('input');
|
|
@@ -362,70 +247,51 @@ export class TyInput extends TyComponent {
|
|
|
362
247
|
console.warn('[TyInput.setupEventListeners] ⚠️ Input element not found!');
|
|
363
248
|
return;
|
|
364
249
|
}
|
|
365
|
-
// Create and store handler references for cleanup
|
|
366
|
-
// Input event - update shadow value and form (with debounce support)
|
|
367
250
|
this._inputHandler = (e) => {
|
|
368
|
-
// Stop native event from propagating - only our custom event should bubble
|
|
369
251
|
e.stopPropagation();
|
|
370
252
|
e.stopImmediatePropagation();
|
|
371
253
|
const target = e.target;
|
|
372
254
|
const rawValue = target.value;
|
|
373
|
-
// Parse to shadow value
|
|
374
255
|
this._shadowValue = this.parseShadowValue(rawValue);
|
|
375
|
-
// Update form value with shadow value
|
|
376
256
|
this._internals.setFormValue(this._shadowValue !== null ? String(this._shadowValue) : null);
|
|
377
257
|
this.updateValidity();
|
|
378
|
-
// Clear existing timer
|
|
379
258
|
if (this._inputDebounceTimer !== null) {
|
|
380
259
|
clearTimeout(this._inputDebounceTimer);
|
|
381
260
|
}
|
|
382
|
-
// If debounce is set, debounce the event
|
|
383
261
|
if (this.debounce > 0) {
|
|
384
262
|
this._inputDebounceTimer = window.setTimeout(() => {
|
|
385
|
-
// Use current value, not the captured rawValue
|
|
386
263
|
this.dispatchInputEvent(inputEl.value, e);
|
|
387
264
|
this._inputDebounceTimer = null;
|
|
388
265
|
}, this.debounce);
|
|
389
266
|
}
|
|
390
267
|
else {
|
|
391
|
-
// Fire immediately if no debounce
|
|
392
268
|
this.dispatchInputEvent(rawValue, e);
|
|
393
269
|
}
|
|
394
270
|
};
|
|
395
|
-
// Change event (with debounce support)
|
|
396
271
|
this._changeHandler = (e) => {
|
|
397
|
-
// Stop native event from propagating - only our custom event should bubble
|
|
398
272
|
e.stopPropagation();
|
|
399
273
|
e.stopImmediatePropagation();
|
|
400
274
|
const target = e.target;
|
|
401
275
|
const rawValue = target.value;
|
|
402
|
-
// Parse to shadow value
|
|
403
276
|
this._shadowValue = this.parseShadowValue(rawValue);
|
|
404
|
-
// Update form value
|
|
405
277
|
this._internals.setFormValue(this._shadowValue !== null ? String(this._shadowValue) : null);
|
|
406
278
|
this.updateValidity();
|
|
407
|
-
// Clear existing timer
|
|
408
279
|
if (this._changeDebounceTimer !== null) {
|
|
409
280
|
clearTimeout(this._changeDebounceTimer);
|
|
410
281
|
}
|
|
411
|
-
// If debounce is set, debounce the event
|
|
412
282
|
if (this.debounce > 0) {
|
|
413
283
|
this._changeDebounceTimer = window.setTimeout(() => {
|
|
414
|
-
// Use current value, not the captured rawValue
|
|
415
284
|
this.dispatchChangeEvent(inputEl.value, e);
|
|
416
285
|
this._changeDebounceTimer = null;
|
|
417
286
|
}, this.debounce);
|
|
418
287
|
}
|
|
419
288
|
else {
|
|
420
|
-
// Fire immediately if no debounce
|
|
421
289
|
this.dispatchChangeEvent(rawValue, e);
|
|
422
290
|
}
|
|
423
291
|
};
|
|
424
|
-
// Focus event - show raw value for numeric types
|
|
425
292
|
this._focusHandler = (e) => {
|
|
426
293
|
this._isFocused = true;
|
|
427
294
|
wrapperEl.classList.add('focused');
|
|
428
|
-
// For numeric types, show raw shadow value
|
|
429
295
|
if (shouldFormatType(this.type) && this._shadowValue !== null) {
|
|
430
296
|
inputEl.value = String(this._shadowValue);
|
|
431
297
|
}
|
|
@@ -435,17 +301,14 @@ export class TyInput extends TyComponent {
|
|
|
435
301
|
composed: true
|
|
436
302
|
}));
|
|
437
303
|
};
|
|
438
|
-
// Blur event - fire pending debounced events immediately, then show formatted value
|
|
439
304
|
this._blurHandler = (e) => {
|
|
440
305
|
const target = e.target;
|
|
441
306
|
const rawValue = target.value;
|
|
442
|
-
// Fire any pending debounced input event immediately on blur
|
|
443
307
|
if (this._inputDebounceTimer !== null) {
|
|
444
308
|
clearTimeout(this._inputDebounceTimer);
|
|
445
309
|
this._inputDebounceTimer = null;
|
|
446
310
|
this.dispatchInputEvent(rawValue, e);
|
|
447
311
|
}
|
|
448
|
-
// Fire any pending debounced change event immediately on blur
|
|
449
312
|
if (this._changeDebounceTimer !== null) {
|
|
450
313
|
clearTimeout(this._changeDebounceTimer);
|
|
451
314
|
this._changeDebounceTimer = null;
|
|
@@ -453,7 +316,6 @@ export class TyInput extends TyComponent {
|
|
|
453
316
|
}
|
|
454
317
|
this._isFocused = false;
|
|
455
318
|
wrapperEl.classList.remove('focused');
|
|
456
|
-
// For numeric types, show formatted value
|
|
457
319
|
if (this.shouldFormat()) {
|
|
458
320
|
inputEl.value = this.getDisplayValue();
|
|
459
321
|
}
|
|
@@ -463,18 +325,12 @@ export class TyInput extends TyComponent {
|
|
|
463
325
|
composed: true
|
|
464
326
|
}));
|
|
465
327
|
};
|
|
466
|
-
// Add event listeners
|
|
467
328
|
inputEl.addEventListener('input', this._inputHandler);
|
|
468
329
|
inputEl.addEventListener('change', this._changeHandler);
|
|
469
330
|
inputEl.addEventListener('focus', this._focusHandler);
|
|
470
331
|
inputEl.addEventListener('blur', this._blurHandler);
|
|
471
332
|
this._listenersSetup = true;
|
|
472
333
|
}
|
|
473
|
-
/**
|
|
474
|
-
* Render the input component with wrapper and slots
|
|
475
|
-
* Phase C: Uses getDisplayValue() for formatted output
|
|
476
|
-
*
|
|
477
|
-
*/
|
|
478
334
|
render() {
|
|
479
335
|
const shadow = this.shadowRoot;
|
|
480
336
|
const existingInput = shadow.querySelector('input');
|
|
@@ -482,19 +338,15 @@ export class TyInput extends TyComponent {
|
|
|
482
338
|
const existingLabel = shadow.querySelector('.ty-field-label');
|
|
483
339
|
const existingError = shadow.querySelector('.error-message');
|
|
484
340
|
const classes = this.buildClassList();
|
|
485
|
-
// Map input type (all numeric types use 'text' in DOM, others pass through)
|
|
486
341
|
const inputType = ['password', 'email', 'tel', 'url'].includes(this.type)
|
|
487
342
|
? this.type
|
|
488
343
|
: 'text';
|
|
489
|
-
// Set inputmode for mobile keyboard hint
|
|
490
344
|
const inputMode = shouldFormatType(this.type) ? 'decimal'
|
|
491
345
|
: this.type === 'email' ? 'email'
|
|
492
346
|
: this.type === 'tel' ? 'tel'
|
|
493
347
|
: this.type === 'url' ? 'url'
|
|
494
348
|
: undefined;
|
|
495
|
-
// Get display value (formatted or raw based on focus)
|
|
496
349
|
const displayValue = this.getDisplayValue();
|
|
497
|
-
// If input exists, just update properties (like ClojureScript does)
|
|
498
350
|
if (existingInput && existingWrapper) {
|
|
499
351
|
existingInput.type = inputType;
|
|
500
352
|
existingInput.value = displayValue;
|
|
@@ -504,9 +356,7 @@ export class TyInput extends TyComponent {
|
|
|
504
356
|
existingInput.inputMode = inputMode;
|
|
505
357
|
else
|
|
506
358
|
existingInput.removeAttribute('inputmode');
|
|
507
|
-
// Update wrapper classes
|
|
508
359
|
existingWrapper.className = `input-wrapper ${classes}`;
|
|
509
|
-
// Set disabled property AND manage attribute
|
|
510
360
|
existingInput.disabled = this.disabled;
|
|
511
361
|
if (this.disabled) {
|
|
512
362
|
existingInput.setAttribute('disabled', '');
|
|
@@ -514,7 +364,6 @@ export class TyInput extends TyComponent {
|
|
|
514
364
|
else {
|
|
515
365
|
existingInput.removeAttribute('disabled');
|
|
516
366
|
}
|
|
517
|
-
// Set required property AND manage attribute
|
|
518
367
|
existingInput.required = this.required;
|
|
519
368
|
if (this.required) {
|
|
520
369
|
existingInput.setAttribute('required', '');
|
|
@@ -522,26 +371,19 @@ export class TyInput extends TyComponent {
|
|
|
522
371
|
else {
|
|
523
372
|
existingInput.removeAttribute('required');
|
|
524
373
|
}
|
|
525
|
-
// a11y: the shadow <label> isn't programmatically linked to this input,
|
|
526
|
-
// so give the control an accessible name directly.
|
|
527
374
|
if (this.label)
|
|
528
375
|
existingInput.setAttribute('aria-label', this.label);
|
|
529
376
|
else
|
|
530
377
|
existingInput.removeAttribute('aria-label');
|
|
531
|
-
// ===== BUG FIX: Dynamic label creation =====
|
|
532
|
-
// Update or CREATE label if needed
|
|
533
378
|
if (this.label) {
|
|
534
379
|
if (existingLabel) {
|
|
535
|
-
// Label exists, just update it
|
|
536
380
|
existingLabel.innerHTML = `${this.label}${this.required ? `<span class="required-icon">${REQUIRED_ICON_SVG}</span>` : ''}`;
|
|
537
381
|
existingLabel.style.display = 'flex';
|
|
538
382
|
}
|
|
539
383
|
else {
|
|
540
|
-
// Label doesn't exist but we need one - CREATE IT!
|
|
541
384
|
const labelEl = document.createElement('label');
|
|
542
385
|
labelEl.className = 'ty-field-label';
|
|
543
386
|
labelEl.innerHTML = `${this.label}${this.required ? `<span class="required-icon">${REQUIRED_ICON_SVG}</span>` : ''}`;
|
|
544
|
-
// Insert label BEFORE the input-wrapper
|
|
545
387
|
const container = shadow.querySelector('.input-container');
|
|
546
388
|
if (container) {
|
|
547
389
|
container.insertBefore(labelEl, existingWrapper);
|
|
@@ -549,11 +391,9 @@ export class TyInput extends TyComponent {
|
|
|
549
391
|
}
|
|
550
392
|
}
|
|
551
393
|
else if (existingLabel) {
|
|
552
|
-
// No label text, hide existing label
|
|
553
394
|
;
|
|
554
395
|
existingLabel.style.display = 'none';
|
|
555
396
|
}
|
|
556
|
-
// Update error message
|
|
557
397
|
if (this.error) {
|
|
558
398
|
if (existingError) {
|
|
559
399
|
existingError.textContent = this.error;
|
|
@@ -570,7 +410,6 @@ export class TyInput extends TyComponent {
|
|
|
570
410
|
}
|
|
571
411
|
}
|
|
572
412
|
else {
|
|
573
|
-
// Create initial structure with wrapper and slots
|
|
574
413
|
const labelHtml = this.label ? `
|
|
575
414
|
<label class="ty-field-label">
|
|
576
415
|
${this.label}
|
|
@@ -602,31 +441,22 @@ export class TyInput extends TyComponent {
|
|
|
602
441
|
${errorHtml}
|
|
603
442
|
</div>
|
|
604
443
|
`;
|
|
605
|
-
// Set boolean properties after creating element
|
|
606
444
|
const inputEl = shadow.querySelector('input');
|
|
607
445
|
inputEl.disabled = this.disabled;
|
|
608
446
|
inputEl.required = this.required;
|
|
609
447
|
if (this.label)
|
|
610
|
-
inputEl.setAttribute('aria-label', this.label);
|
|
448
|
+
inputEl.setAttribute('aria-label', this.label);
|
|
611
449
|
this.setupPasswordToggle();
|
|
612
|
-
// Setup event listeners ONCE
|
|
613
450
|
this.setupEventListeners();
|
|
614
451
|
}
|
|
615
|
-
// Reflect constraint validation (required, etc.) to the owning <form>.
|
|
616
452
|
this.updateValidity();
|
|
617
453
|
}
|
|
618
|
-
/**
|
|
619
|
-
* Wire the password reveal toggle (rendered only for type="password").
|
|
620
|
-
* Toggles the NATIVE input's type between password/text — the component's
|
|
621
|
-
* `type` property stays "password" (form value and API unaffected).
|
|
622
|
-
*/
|
|
623
454
|
setupPasswordToggle() {
|
|
624
455
|
const shadow = this.shadowRoot;
|
|
625
456
|
const toggle = shadow.querySelector('.password-toggle');
|
|
626
457
|
const inputEl = shadow.querySelector('input');
|
|
627
458
|
if (!toggle || !inputEl)
|
|
628
459
|
return;
|
|
629
|
-
// Keep focus in the input while clicking the toggle
|
|
630
460
|
toggle.addEventListener('mousedown', (e) => e.preventDefault());
|
|
631
461
|
toggle.addEventListener('click', () => {
|
|
632
462
|
const reveal = inputEl.type === 'password';
|
|
@@ -636,12 +466,6 @@ export class TyInput extends TyComponent {
|
|
|
636
466
|
toggle.setAttribute('aria-pressed', String(reveal));
|
|
637
467
|
});
|
|
638
468
|
}
|
|
639
|
-
/**
|
|
640
|
-
* Reflect constraint validation to the owning <form> via ElementInternals.
|
|
641
|
-
* Without this `required` is only cosmetic — the inner shadow <input> can't
|
|
642
|
-
* block the outer form. Empty + required => valueMissing; otherwise valid.
|
|
643
|
-
* Disabled fields are barred from constraint validation.
|
|
644
|
-
*/
|
|
645
469
|
updateValidity() {
|
|
646
470
|
const inputEl = this.shadowRoot?.querySelector('input');
|
|
647
471
|
if (this.disabled) {
|
|
@@ -658,11 +482,7 @@ export class TyInput extends TyComponent {
|
|
|
658
482
|
}
|
|
659
483
|
}
|
|
660
484
|
TyInput.formAssociated = true;
|
|
661
|
-
// ============================================================================
|
|
662
|
-
// PROPERTY CONFIGURATION - Declarative property lifecycle
|
|
663
|
-
// ============================================================================
|
|
664
485
|
TyInput.properties = {
|
|
665
|
-
// Core properties
|
|
666
486
|
type: {
|
|
667
487
|
type: 'string',
|
|
668
488
|
visual: true,
|
|
@@ -726,7 +546,6 @@ TyInput.properties = {
|
|
|
726
546
|
type: 'string',
|
|
727
547
|
visual: true,
|
|
728
548
|
default: 'md',
|
|
729
|
-
// Fields come in exactly three sizes; legacy xs/xl map to sm/lg.
|
|
730
549
|
validate: (v) => ['sm', 'md', 'lg'].includes(v),
|
|
731
550
|
coerce: (v) => {
|
|
732
551
|
if (v === 'xs')
|
|
@@ -740,15 +559,11 @@ TyInput.properties = {
|
|
|
740
559
|
return v;
|
|
741
560
|
}
|
|
742
561
|
},
|
|
743
|
-
// Any string is accepted: built-ins get static CSS, other identifiers
|
|
744
|
-
// become custom flavors (see _syncCustomFlavor), garbage degrades to
|
|
745
|
-
// the default look.
|
|
746
562
|
flavor: {
|
|
747
563
|
type: 'string',
|
|
748
564
|
visual: true,
|
|
749
565
|
default: 'neutral'
|
|
750
566
|
},
|
|
751
|
-
// Numeric formatting properties
|
|
752
567
|
currency: {
|
|
753
568
|
type: 'string',
|
|
754
569
|
visual: true,
|
|
@@ -777,7 +592,6 @@ TyInput.properties = {
|
|
|
777
592
|
return Math.max(0, Math.min(10, Math.floor(num)));
|
|
778
593
|
}
|
|
779
594
|
},
|
|
780
|
-
// Debounce property
|
|
781
595
|
debounce: {
|
|
782
596
|
type: 'number',
|
|
783
597
|
default: 0,
|
|
@@ -793,8 +607,6 @@ TyInput.properties = {
|
|
|
793
607
|
}
|
|
794
608
|
}
|
|
795
609
|
};
|
|
796
|
-
// Register the custom element
|
|
797
610
|
if (!customElements.get('ty-input')) {
|
|
798
611
|
customElements.define('ty-input', TyInput);
|
|
799
612
|
}
|
|
800
|
-
//# sourceMappingURL=input.js.map
|
|
@@ -1,28 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Modal Component
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* Provides backdrop, focus management, scroll locking, and keyboard interaction
|
|
6
|
-
* without imposing any styling on content.
|
|
7
|
-
*
|
|
8
|
-
* Features:
|
|
9
|
-
* - Native dialog element wrapper
|
|
10
|
-
* - Dual API: declarative (open attribute) and imperative (show/hide methods)
|
|
11
|
-
* - Cancellable `beforeclose` lifecycle event for unsaved-state flows
|
|
12
|
-
* - Auto-hiding close button on hover (desktop only)
|
|
13
|
-
* - Scroll locking with unique modal IDs
|
|
14
|
-
* - Customizable backdrop via CSS variables
|
|
15
|
-
*
|
|
16
|
-
* @example
|
|
17
|
-
* <ty-modal id="my-modal">
|
|
18
|
-
* <div class="ty-elevated p-6 rounded-lg max-w-md">
|
|
19
|
-
* <h3 class="text-lg font-semibold mb-4">Modal Title</h3>
|
|
20
|
-
* <p class="ty-text- mb-4">Modal content here</p>
|
|
21
|
-
* <ty-button onclick="this.closest('ty-modal').hide()">
|
|
22
|
-
* Close
|
|
23
|
-
* </ty-button>
|
|
24
|
-
* </div>
|
|
25
|
-
* </ty-modal>
|
|
2
|
+
* Modal Component - wrapper around the native <dialog> element providing
|
|
3
|
+
* backdrop, scroll locking and keyboard interaction, without styling content.
|
|
4
|
+
* Closing runs through a cancellable `beforeclose` event (unsaved-state flows).
|
|
26
5
|
*/
|
|
27
6
|
/**
|
|
28
7
|
* Modal attributes configuration
|
|
@@ -68,11 +47,23 @@ export declare class TyModal extends HTMLElement {
|
|
|
68
47
|
hide?: (opts?: {
|
|
69
48
|
force?: boolean;
|
|
70
49
|
}) => void;
|
|
71
|
-
/** Observed attributes */
|
|
72
50
|
static get observedAttributes(): string[];
|
|
51
|
+
get open(): boolean;
|
|
52
|
+
set open(v: boolean);
|
|
53
|
+
get backdrop(): boolean;
|
|
54
|
+
set backdrop(v: boolean);
|
|
55
|
+
/** @deprecated Use preventOutsideClick — prevent-* wins when both are set. */
|
|
56
|
+
get closeOnOutsideClick(): boolean;
|
|
57
|
+
set closeOnOutsideClick(v: boolean);
|
|
58
|
+
/** @deprecated Use preventEscape — prevent-* wins when both are set. */
|
|
59
|
+
get closeOnEscape(): boolean;
|
|
60
|
+
set closeOnEscape(v: boolean);
|
|
61
|
+
get preventOutsideClick(): boolean;
|
|
62
|
+
set preventOutsideClick(v: boolean);
|
|
63
|
+
get preventEscape(): boolean;
|
|
64
|
+
set preventEscape(v: boolean);
|
|
73
65
|
constructor();
|
|
74
66
|
connectedCallback(): void;
|
|
75
67
|
disconnectedCallback(): void;
|
|
76
68
|
attributeChangedCallback(_name: string, _oldValue: string | null, _newValue: string | null): void;
|
|
77
69
|
}
|
|
78
|
-
//# sourceMappingURL=modal.d.ts.map
|