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
|
@@ -1,118 +1,41 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* ty-textarea - Enhanced textarea component with auto-resize functionality
|
|
3
|
-
*
|
|
4
|
-
* Features:
|
|
5
|
-
* - Auto-resize based on content
|
|
6
|
-
* - Form-associated custom element
|
|
7
|
-
* - Min/max height constraints
|
|
8
|
-
* - Size variants (xs, sm, md, lg, xl)
|
|
9
|
-
* - Validation states (error, required)
|
|
10
|
-
* - Manual resize control options
|
|
11
|
-
* - Accessibility support
|
|
12
|
-
*
|
|
13
|
-
* @example
|
|
14
|
-
* ```html
|
|
15
|
-
* <!-- Basic usage -->
|
|
16
|
-
* <ty-textarea label="Description" placeholder="Enter details..."></ty-textarea>
|
|
17
|
-
*
|
|
18
|
-
* <!-- With validation -->
|
|
19
|
-
* <ty-textarea
|
|
20
|
-
* label="Bio"
|
|
21
|
-
* required
|
|
22
|
-
* error="Bio is required"
|
|
23
|
-
* size="lg">
|
|
24
|
-
* </ty-textarea>
|
|
25
|
-
*
|
|
26
|
-
* <!-- With height constraints -->
|
|
27
|
-
* <ty-textarea
|
|
28
|
-
* min-height="100px"
|
|
29
|
-
* max-height="300px"
|
|
30
|
-
* placeholder="Auto-resizing textarea">
|
|
31
|
-
* </ty-textarea>
|
|
32
|
-
*
|
|
33
|
-
* <!-- Manual resize control -->
|
|
34
|
-
* <ty-textarea resize="vertical"></ty-textarea>
|
|
35
|
-
* ```
|
|
36
|
-
*
|
|
37
|
-
* @fires {CustomEvent<{value: string, originalEvent: Event}>} input - Emitted on input
|
|
38
|
-
* @fires {CustomEvent<{value: string, originalEvent: Event}>} change - Emitted on change
|
|
39
|
-
*/
|
|
40
1
|
import { TyComponent } from '../base/ty-component.js';
|
|
41
2
|
import { ensureStyles } from '../utils/styles.js';
|
|
42
3
|
import { textareaStyles } from '../styles/textarea.js';
|
|
43
4
|
import { CustomScrollbar, isCustomScrollbarEnabled } from '../utils/custom-scrollbar.js';
|
|
44
5
|
import { customScrollbarStyles } from '../styles/custom-scrollbar.js';
|
|
45
|
-
/**
|
|
46
|
-
* Required icon SVG (matches input.ts)
|
|
47
|
-
*/
|
|
48
6
|
const REQUIRED_ICON = `<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"></circle><line x1="12" y1="8" x2="12" y2="12"></line><line x1="12" y1="16" x2="12.01" y2="16"></line></svg>`;
|
|
49
7
|
export class TyTextarea extends TyComponent {
|
|
50
8
|
constructor() {
|
|
51
|
-
super();
|
|
52
|
-
// ============================================================================
|
|
53
|
-
// INTERNAL STATE - Not managed by PropertyManager
|
|
54
|
-
// NOTE: _internals provided by TyComponent base class
|
|
55
|
-
// ============================================================================
|
|
56
|
-
// DOM element references
|
|
9
|
+
super();
|
|
57
10
|
this._textareaEl = null;
|
|
58
11
|
this._dummyEl = null;
|
|
59
12
|
this._scrollbar = null;
|
|
60
|
-
// Focus state
|
|
61
13
|
this._isFocused = false;
|
|
62
|
-
/**
|
|
63
|
-
* Handle textarea input event
|
|
64
|
-
*/
|
|
65
14
|
this.handleInputEvent = (e) => {
|
|
66
15
|
const target = e.target;
|
|
67
16
|
const newValue = target.value;
|
|
68
|
-
// Update value via property (triggers proper lifecycle)
|
|
69
17
|
this.value = newValue;
|
|
70
|
-
// Trigger resize after state update
|
|
71
18
|
if (this._textareaEl && this._dummyEl) {
|
|
72
19
|
this.resizeTextarea(this._textareaEl, this._dummyEl);
|
|
73
20
|
}
|
|
74
|
-
// Emit custom events
|
|
75
21
|
this.emitValueEvents(e);
|
|
76
22
|
};
|
|
77
|
-
/**
|
|
78
|
-
* Handle textarea focus event
|
|
79
|
-
*/
|
|
80
23
|
this.handleFocusEvent = () => {
|
|
81
24
|
this._isFocused = true;
|
|
82
25
|
};
|
|
83
|
-
/**
|
|
84
|
-
* Handle textarea blur event
|
|
85
|
-
*/
|
|
86
26
|
this.handleBlurEvent = () => {
|
|
87
27
|
this._isFocused = false;
|
|
88
28
|
};
|
|
89
|
-
// Apply styles to shadow root
|
|
90
29
|
const shadow = this.shadowRoot;
|
|
91
30
|
ensureStyles(shadow, { css: textareaStyles, id: 'ty-textarea' });
|
|
92
|
-
// Add custom scrollbar styles
|
|
93
31
|
if (isCustomScrollbarEnabled()) {
|
|
94
32
|
ensureStyles(shadow, { css: customScrollbarStyles, id: 'ty-custom-scrollbar' });
|
|
95
33
|
}
|
|
96
34
|
}
|
|
97
|
-
// observedAttributes auto-generated by TyComponent from properties config
|
|
98
|
-
// ============================================================================
|
|
99
|
-
// TYCOMPONENT LIFECYCLE HOOKS
|
|
100
|
-
// ============================================================================
|
|
101
|
-
/**
|
|
102
|
-
* Called when component connects to DOM
|
|
103
|
-
* TyComponent already handled pre-connection property capture
|
|
104
|
-
*/
|
|
105
35
|
onConnect() {
|
|
106
|
-
// No special initialization needed - TyComponent handles everything
|
|
107
|
-
// Just render the component
|
|
108
36
|
}
|
|
109
|
-
/**
|
|
110
|
-
* Called when component disconnects from DOM
|
|
111
|
-
*/
|
|
112
37
|
onDisconnect() {
|
|
113
|
-
// Cleanup scrollbar
|
|
114
38
|
this._destroyScrollbar();
|
|
115
|
-
// Cleanup event listeners if needed
|
|
116
39
|
if (this._textareaEl) {
|
|
117
40
|
const newTextarea = this._textareaEl.cloneNode(true);
|
|
118
41
|
this._textareaEl.parentNode?.replaceChild(newTextarea, this._textareaEl);
|
|
@@ -120,23 +43,11 @@ export class TyTextarea extends TyComponent {
|
|
|
120
43
|
}
|
|
121
44
|
this._dummyEl = null;
|
|
122
45
|
}
|
|
123
|
-
/**
|
|
124
|
-
* Handle property changes - called BEFORE render
|
|
125
|
-
* This replaces the old attributeChangedCallback logic
|
|
126
|
-
*/
|
|
127
46
|
onPropertiesChanged(changes) {
|
|
128
|
-
// No special handling needed for textarea
|
|
129
|
-
// All property changes will trigger render() automatically if marked as visual
|
|
130
47
|
}
|
|
131
|
-
/**
|
|
132
|
-
* Override form value to return current value
|
|
133
|
-
*/
|
|
134
48
|
getFormValue() {
|
|
135
49
|
return this.getProperty('value') || null;
|
|
136
50
|
}
|
|
137
|
-
// ============================================================================
|
|
138
|
-
// PROPERTY ACCESSORS - Simplified with TyComponent
|
|
139
|
-
// ============================================================================
|
|
140
51
|
get value() { return this.getProperty('value'); }
|
|
141
52
|
set value(v) { this.setProperty('value', v); }
|
|
142
53
|
get name() { return this.getProperty('name'); }
|
|
@@ -171,10 +82,6 @@ export class TyTextarea extends TyComponent {
|
|
|
171
82
|
set minHeight(v) { this.setProperty('minHeight', v); }
|
|
172
83
|
get maxHeight() { return this.getProperty('maxHeight'); }
|
|
173
84
|
set maxHeight(v) { this.setProperty('maxHeight', v); }
|
|
174
|
-
// ===== HELPER METHODS =====
|
|
175
|
-
/**
|
|
176
|
-
* Extract font-related CSS properties from element
|
|
177
|
-
*/
|
|
178
85
|
getFontStyle(el) {
|
|
179
86
|
const computedStyle = window.getComputedStyle(el);
|
|
180
87
|
return {
|
|
@@ -186,9 +93,6 @@ export class TyTextarea extends TyComponent {
|
|
|
186
93
|
fontStyle: computedStyle.fontStyle
|
|
187
94
|
};
|
|
188
95
|
}
|
|
189
|
-
/**
|
|
190
|
-
* Extract spacing-related CSS properties from element
|
|
191
|
-
*/
|
|
192
96
|
getSpacingStyle(el) {
|
|
193
97
|
const computedStyle = window.getComputedStyle(el);
|
|
194
98
|
return {
|
|
@@ -201,23 +105,16 @@ export class TyTextarea extends TyComponent {
|
|
|
201
105
|
borderWidth: computedStyle.borderWidth
|
|
202
106
|
};
|
|
203
107
|
}
|
|
204
|
-
/**
|
|
205
|
-
* Setup the hidden dummy element for height measurement
|
|
206
|
-
*/
|
|
207
108
|
setupDummyElement(textareaEl) {
|
|
208
109
|
const root = this.shadowRoot;
|
|
209
110
|
const existingDummy = root.querySelector('.textarea-dummy');
|
|
210
|
-
// Remove existing dummy if present
|
|
211
111
|
if (existingDummy) {
|
|
212
112
|
existingDummy.remove();
|
|
213
113
|
}
|
|
214
|
-
// Create new dummy element
|
|
215
114
|
const dummyEl = document.createElement('pre');
|
|
216
115
|
const fontStyle = this.getFontStyle(textareaEl);
|
|
217
116
|
const spacingStyle = this.getSpacingStyle(textareaEl);
|
|
218
|
-
// Set dummy element class
|
|
219
117
|
dummyEl.className = 'textarea-dummy';
|
|
220
|
-
// Apply styles to match textarea
|
|
221
118
|
const style = dummyEl.style;
|
|
222
119
|
style.position = 'absolute';
|
|
223
120
|
style.top = '0';
|
|
@@ -228,24 +125,18 @@ export class TyTextarea extends TyComponent {
|
|
|
228
125
|
style.boxSizing = 'border-box';
|
|
229
126
|
style.overflow = 'hidden';
|
|
230
127
|
style.pointerEvents = 'none';
|
|
231
|
-
// Apply font styles
|
|
232
128
|
Object.entries(fontStyle).forEach(([prop, value]) => {
|
|
233
129
|
;
|
|
234
130
|
style[prop] = value;
|
|
235
131
|
});
|
|
236
|
-
// Apply spacing styles
|
|
237
132
|
Object.entries(spacingStyle).forEach(([prop, value]) => {
|
|
238
133
|
;
|
|
239
134
|
style[prop] = value;
|
|
240
135
|
});
|
|
241
|
-
// Append to shadow root
|
|
242
136
|
root.appendChild(dummyEl);
|
|
243
137
|
this._dummyEl = dummyEl;
|
|
244
138
|
return dummyEl;
|
|
245
139
|
}
|
|
246
|
-
/**
|
|
247
|
-
* Resize textarea based on dummy element content with min/max height constraints
|
|
248
|
-
*/
|
|
249
140
|
resizeTextarea(textareaEl, dummyEl) {
|
|
250
141
|
if (!textareaEl || !dummyEl)
|
|
251
142
|
return;
|
|
@@ -253,25 +144,18 @@ export class TyTextarea extends TyComponent {
|
|
|
253
144
|
const placeholder = this.placeholder;
|
|
254
145
|
const content = (value === '' && placeholder) ? placeholder : value + ' ';
|
|
255
146
|
const currentHeight = textareaEl.clientHeight;
|
|
256
|
-
// Set dummy content
|
|
257
147
|
dummyEl.textContent = content;
|
|
258
|
-
// Set dummy width to match textarea
|
|
259
148
|
dummyEl.style.width = `${textareaEl.clientWidth}px`;
|
|
260
|
-
// Get measured height
|
|
261
149
|
const measuredHeight = dummyEl.scrollHeight;
|
|
262
|
-
// Parse min/max heights
|
|
263
150
|
const minHeight = this.minHeight ? parseInt(this.minHeight.replace('px', ''), 10) : null;
|
|
264
151
|
const maxHeight = this.maxHeight ? parseInt(this.maxHeight.replace('px', ''), 10) : null;
|
|
265
|
-
// Apply constraints
|
|
266
152
|
let constrainedHeight = measuredHeight;
|
|
267
153
|
if (minHeight !== null)
|
|
268
154
|
constrainedHeight = Math.max(constrainedHeight, minHeight);
|
|
269
155
|
if (maxHeight !== null)
|
|
270
156
|
constrainedHeight = Math.min(constrainedHeight, maxHeight);
|
|
271
|
-
// Only update if height changed significantly (avoid micro-adjustments)
|
|
272
157
|
if (Math.abs(constrainedHeight - currentHeight) > 2) {
|
|
273
158
|
textareaEl.style.height = `${constrainedHeight}px`;
|
|
274
|
-
// Set overflow based on whether we hit max-height
|
|
275
159
|
const needsScroll = maxHeight !== null && measuredHeight >= maxHeight;
|
|
276
160
|
if (needsScroll) {
|
|
277
161
|
textareaEl.style.overflowY = 'auto';
|
|
@@ -282,22 +166,17 @@ export class TyTextarea extends TyComponent {
|
|
|
282
166
|
this._destroyScrollbar();
|
|
283
167
|
}
|
|
284
168
|
}
|
|
285
|
-
// Keep scrollbar thumb in sync after resize
|
|
286
169
|
this._scrollbar?.update();
|
|
287
170
|
}
|
|
288
|
-
// ============ Custom Scrollbar ============
|
|
289
171
|
_setupScrollbar(textareaEl) {
|
|
290
172
|
if (this._scrollbar || !isCustomScrollbarEnabled())
|
|
291
173
|
return;
|
|
292
|
-
// Hide native scrollbar (Firefox + Chrome/Safari via data attribute)
|
|
293
174
|
textareaEl.style.scrollbarWidth = 'none';
|
|
294
175
|
this.setAttribute('data-custom-scroll', '');
|
|
295
176
|
this._scrollbar = new CustomScrollbar(textareaEl, {
|
|
296
177
|
vertical: true,
|
|
297
178
|
horizontal: false
|
|
298
179
|
});
|
|
299
|
-
// Append track to the scroll region (position: relative) so it tracks the
|
|
300
|
-
// textarea edges and never overlaps the header/footer.
|
|
301
180
|
const scroll = this.shadowRoot.querySelector('.textarea-scroll');
|
|
302
181
|
if (scroll && this._scrollbar.trackY) {
|
|
303
182
|
scroll.appendChild(this._scrollbar.trackY);
|
|
@@ -309,21 +188,15 @@ export class TyTextarea extends TyComponent {
|
|
|
309
188
|
this._scrollbar.trackY?.remove();
|
|
310
189
|
this._scrollbar.destroy();
|
|
311
190
|
this._scrollbar = null;
|
|
312
|
-
// Restore native scrollbar
|
|
313
191
|
this.removeAttribute('data-custom-scroll');
|
|
314
192
|
if (this._textareaEl) {
|
|
315
193
|
this._textareaEl.style.scrollbarWidth = '';
|
|
316
194
|
}
|
|
317
195
|
}
|
|
318
|
-
/**
|
|
319
|
-
* Emit custom input and change events
|
|
320
|
-
*/
|
|
321
196
|
emitValueEvents(originalEvent) {
|
|
322
197
|
const value = this.value;
|
|
323
|
-
// Update form internals
|
|
324
198
|
this._internals.setFormValue(value || '');
|
|
325
199
|
this.updateValidity();
|
|
326
|
-
// Emit custom events
|
|
327
200
|
const data = {
|
|
328
201
|
bubbles: true,
|
|
329
202
|
composed: true,
|
|
@@ -332,15 +205,11 @@ export class TyTextarea extends TyComponent {
|
|
|
332
205
|
originalEvent
|
|
333
206
|
}
|
|
334
207
|
};
|
|
335
|
-
// Use setTimeout to ensure these fire after standard events
|
|
336
208
|
setTimeout(() => {
|
|
337
209
|
this.dispatchEvent(new CustomEvent('input', data));
|
|
338
210
|
this.dispatchEvent(new CustomEvent('change', data));
|
|
339
211
|
}, 0);
|
|
340
212
|
}
|
|
341
|
-
/**
|
|
342
|
-
* Build class list for textarea element
|
|
343
|
-
*/
|
|
344
213
|
buildClassList() {
|
|
345
214
|
const classes = [this.size];
|
|
346
215
|
if (this.disabled)
|
|
@@ -356,9 +225,6 @@ export class TyTextarea extends TyComponent {
|
|
|
356
225
|
classes.push(customClass);
|
|
357
226
|
return classes.join(' ');
|
|
358
227
|
}
|
|
359
|
-
/**
|
|
360
|
-
* Apply min/max height constraints to textarea element
|
|
361
|
-
*/
|
|
362
228
|
applyHeightConstraints(textareaEl) {
|
|
363
229
|
if (this.minHeight) {
|
|
364
230
|
textareaEl.style.minHeight = this.minHeight;
|
|
@@ -367,16 +233,12 @@ export class TyTextarea extends TyComponent {
|
|
|
367
233
|
textareaEl.style.maxHeight = this.maxHeight;
|
|
368
234
|
}
|
|
369
235
|
}
|
|
370
|
-
/**
|
|
371
|
-
* Setup event listeners for textarea
|
|
372
|
-
*/
|
|
373
236
|
setupTextareaEvents(textareaEl) {
|
|
374
237
|
textareaEl.addEventListener('input', this.handleInputEvent);
|
|
375
238
|
textareaEl.addEventListener('change', this.handleInputEvent);
|
|
376
239
|
textareaEl.addEventListener('focus', this.handleFocusEvent);
|
|
377
240
|
textareaEl.addEventListener('blur', this.handleBlurEvent);
|
|
378
241
|
}
|
|
379
|
-
// ===== RENDER =====
|
|
380
242
|
render() {
|
|
381
243
|
const root = this.shadowRoot;
|
|
382
244
|
const existingContainer = root.querySelector('.textarea-container');
|
|
@@ -384,8 +246,6 @@ export class TyTextarea extends TyComponent {
|
|
|
384
246
|
const existingTextarea = root.querySelector('textarea');
|
|
385
247
|
const existingError = root.querySelector('.error-message');
|
|
386
248
|
if (existingContainer && existingTextarea) {
|
|
387
|
-
// Update existing elements
|
|
388
|
-
// Update label
|
|
389
249
|
if (this.label) {
|
|
390
250
|
if (existingLabel) {
|
|
391
251
|
existingLabel.innerHTML = this.label +
|
|
@@ -396,32 +256,26 @@ export class TyTextarea extends TyComponent {
|
|
|
396
256
|
else if (existingLabel) {
|
|
397
257
|
existingLabel.style.display = 'none';
|
|
398
258
|
}
|
|
399
|
-
// Update textarea
|
|
400
259
|
existingTextarea.value = this.value || '';
|
|
401
260
|
existingTextarea.placeholder = this.placeholder || '';
|
|
402
261
|
existingTextarea.disabled = this.disabled;
|
|
403
262
|
existingTextarea.required = this.required;
|
|
404
263
|
existingTextarea.className = this.buildClassList();
|
|
405
|
-
// a11y: shadow <label> isn't linked to the control; name it directly.
|
|
406
264
|
if (this.label)
|
|
407
265
|
existingTextarea.setAttribute('aria-label', this.label);
|
|
408
266
|
else
|
|
409
267
|
existingTextarea.removeAttribute('aria-label');
|
|
410
|
-
// Set name for form association
|
|
411
268
|
if (this.name) {
|
|
412
269
|
existingTextarea.setAttribute('name', this.name);
|
|
413
270
|
}
|
|
414
271
|
else {
|
|
415
272
|
existingTextarea.removeAttribute('name');
|
|
416
273
|
}
|
|
417
|
-
// Set rows/cols
|
|
418
274
|
if (this.rows)
|
|
419
275
|
existingTextarea.setAttribute('rows', this.rows);
|
|
420
276
|
if (this.cols)
|
|
421
277
|
existingTextarea.setAttribute('cols', this.cols);
|
|
422
|
-
// Apply height constraints
|
|
423
278
|
this.applyHeightConstraints(existingTextarea);
|
|
424
|
-
// Update error message
|
|
425
279
|
if (this.error) {
|
|
426
280
|
if (!existingError) {
|
|
427
281
|
const errorEl = document.createElement('div');
|
|
@@ -435,13 +289,11 @@ export class TyTextarea extends TyComponent {
|
|
|
435
289
|
else if (existingError) {
|
|
436
290
|
existingError.remove();
|
|
437
291
|
}
|
|
438
|
-
// Setup dummy element and trigger resize
|
|
439
292
|
const dummyEl = this.setupDummyElement(existingTextarea);
|
|
440
293
|
setTimeout(() => this.resizeTextarea(existingTextarea, dummyEl), 0);
|
|
441
294
|
this._textareaEl = existingTextarea;
|
|
442
295
|
}
|
|
443
296
|
else {
|
|
444
|
-
// Create new structure
|
|
445
297
|
const container = document.createElement('div');
|
|
446
298
|
container.className = 'textarea-container';
|
|
447
299
|
const labelEl = document.createElement('label');
|
|
@@ -461,21 +313,15 @@ export class TyTextarea extends TyComponent {
|
|
|
461
313
|
textareaEl.required = this.required;
|
|
462
314
|
textareaEl.className = this.buildClassList();
|
|
463
315
|
if (this.label)
|
|
464
|
-
textareaEl.setAttribute('aria-label', this.label);
|
|
465
|
-
// Set name for form association
|
|
316
|
+
textareaEl.setAttribute('aria-label', this.label);
|
|
466
317
|
if (this.name) {
|
|
467
318
|
textareaEl.setAttribute('name', this.name);
|
|
468
319
|
}
|
|
469
|
-
// Set default or specified rows/cols
|
|
470
320
|
textareaEl.setAttribute('rows', this.rows || '3');
|
|
471
321
|
if (this.cols)
|
|
472
322
|
textareaEl.setAttribute('cols', this.cols);
|
|
473
|
-
// Apply height constraints
|
|
474
323
|
this.applyHeightConstraints(textareaEl);
|
|
475
|
-
// Setup event listeners
|
|
476
324
|
this.setupTextareaEvents(textareaEl);
|
|
477
|
-
// Build composer structure:
|
|
478
|
-
// .textarea-wrapper (border) > [.textarea-header > slot] · .textarea-scroll(textarea) · [.textarea-footer > slot]
|
|
479
325
|
const wrapperEl = document.createElement('div');
|
|
480
326
|
wrapperEl.className = 'textarea-wrapper';
|
|
481
327
|
const headerEl = document.createElement('div');
|
|
@@ -483,8 +329,6 @@ export class TyTextarea extends TyComponent {
|
|
|
483
329
|
const headerSlot = document.createElement('slot');
|
|
484
330
|
headerSlot.setAttribute('name', 'header');
|
|
485
331
|
headerEl.appendChild(headerSlot);
|
|
486
|
-
// Scroll region wraps only the textarea so the custom scrollbar can't
|
|
487
|
-
// overlap header/footer.
|
|
488
332
|
const scrollEl = document.createElement('div');
|
|
489
333
|
scrollEl.className = 'textarea-scroll';
|
|
490
334
|
scrollEl.appendChild(textareaEl);
|
|
@@ -496,8 +340,6 @@ export class TyTextarea extends TyComponent {
|
|
|
496
340
|
wrapperEl.appendChild(headerEl);
|
|
497
341
|
wrapperEl.appendChild(scrollEl);
|
|
498
342
|
wrapperEl.appendChild(footerEl);
|
|
499
|
-
// Collapse empty slots (no padding/divider) by toggling .has-content.
|
|
500
|
-
// slotchange fires on initial assignment too.
|
|
501
343
|
const syncSlot = (slot, region) => {
|
|
502
344
|
const update = () => region.classList.toggle('has-content', slot.assignedNodes({ flatten: true }).length > 0);
|
|
503
345
|
slot.addEventListener('slotchange', update);
|
|
@@ -507,7 +349,6 @@ export class TyTextarea extends TyComponent {
|
|
|
507
349
|
syncSlot(footerSlot, footerEl);
|
|
508
350
|
container.appendChild(labelEl);
|
|
509
351
|
container.appendChild(wrapperEl);
|
|
510
|
-
// Add error message if present
|
|
511
352
|
if (this.error) {
|
|
512
353
|
const errorEl = document.createElement('div');
|
|
513
354
|
errorEl.className = 'error-message';
|
|
@@ -515,17 +356,12 @@ export class TyTextarea extends TyComponent {
|
|
|
515
356
|
container.appendChild(errorEl);
|
|
516
357
|
}
|
|
517
358
|
root.appendChild(container);
|
|
518
|
-
// Setup dummy element and trigger initial resize
|
|
519
359
|
const dummyEl = this.setupDummyElement(textareaEl);
|
|
520
360
|
setTimeout(() => this.resizeTextarea(textareaEl, dummyEl), 0);
|
|
521
361
|
this._textareaEl = textareaEl;
|
|
522
362
|
}
|
|
523
|
-
// Reflect constraint validation to the owning <form>. Without this `required`
|
|
524
|
-
// is cosmetic — the inner shadow <textarea> can't block the outer form.
|
|
525
363
|
this.updateValidity();
|
|
526
364
|
}
|
|
527
|
-
/** required + empty => valueMissing; otherwise valid. Disabled fields are
|
|
528
|
-
* barred from constraint validation. */
|
|
529
365
|
updateValidity() {
|
|
530
366
|
const ta = this.shadowRoot?.querySelector('textarea');
|
|
531
367
|
if (this.disabled) {
|
|
@@ -542,11 +378,7 @@ export class TyTextarea extends TyComponent {
|
|
|
542
378
|
}
|
|
543
379
|
}
|
|
544
380
|
TyTextarea.formAssociated = true;
|
|
545
|
-
// ============================================================================
|
|
546
|
-
// PROPERTY CONFIGURATION - Declarative property lifecycle
|
|
547
|
-
// ============================================================================
|
|
548
381
|
TyTextarea.properties = {
|
|
549
|
-
// Core properties
|
|
550
382
|
value: {
|
|
551
383
|
type: 'string',
|
|
552
384
|
visual: true,
|
|
@@ -596,7 +428,6 @@ TyTextarea.properties = {
|
|
|
596
428
|
return v;
|
|
597
429
|
}
|
|
598
430
|
},
|
|
599
|
-
// Layout properties
|
|
600
431
|
rows: {
|
|
601
432
|
type: 'string',
|
|
602
433
|
visual: true,
|
|
@@ -633,8 +464,6 @@ TyTextarea.properties = {
|
|
|
633
464
|
default: ''
|
|
634
465
|
}
|
|
635
466
|
};
|
|
636
|
-
// Register the component
|
|
637
467
|
if (!customElements.get('ty-textarea')) {
|
|
638
468
|
customElements.define('ty-textarea', TyTextarea);
|
|
639
469
|
}
|
|
640
|
-
//# sourceMappingURL=textarea.js.map
|
|
@@ -1,13 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Tooltip Component
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* Follows the same shadow DOM pattern as other components.
|
|
6
|
-
*
|
|
7
|
-
* @example
|
|
8
|
-
* <ty-tooltip placement="top" flavor="primary" delay="600">
|
|
9
|
-
* Helpful tooltip text
|
|
10
|
-
* </ty-tooltip>
|
|
2
|
+
* Tooltip Component — shows content on hover/focus with smart positioning.
|
|
3
|
+
* The anchor is the tooltip's PARENT element; the popover itself lives in
|
|
4
|
+
* document.body (top layer), not in this element's shadow root.
|
|
11
5
|
*/
|
|
12
6
|
import { type Placement } from '../utils/positioning.js';
|
|
13
7
|
import type { Flavor } from '../types/common.js';
|
|
@@ -32,11 +26,9 @@ export interface TooltipAttributes {
|
|
|
32
26
|
export declare class TyTooltip extends HTMLElement {
|
|
33
27
|
/** Internal open state */
|
|
34
28
|
_open: boolean;
|
|
35
|
-
/** Observed attributes */
|
|
36
29
|
static get observedAttributes(): string[];
|
|
37
30
|
constructor();
|
|
38
31
|
connectedCallback(): void;
|
|
39
32
|
disconnectedCallback(): void;
|
|
40
33
|
attributeChangedCallback(name: string, _oldValue: string | null, newValue: string | null): void;
|
|
41
34
|
}
|
|
42
|
-
//# sourceMappingURL=tooltip.d.ts.map
|