tyrell-react 1.0.0-RC12 → 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.
Files changed (135) hide show
  1. package/README.md +1 -0
  2. package/dist/components/TyButton.d.ts +1 -1
  3. package/dist/components/TyButton.d.ts.map +1 -1
  4. package/dist/components/TyButton.js +2 -1
  5. package/dist/components/TyButton.js.map +1 -1
  6. package/dist/components/TyCalendar.d.ts +5 -0
  7. package/dist/components/TyCalendar.d.ts.map +1 -1
  8. package/dist/components/TyCalendar.js +6 -10
  9. package/dist/components/TyCalendar.js.map +1 -1
  10. package/dist/components/TyCalendarMonth.d.ts +5 -0
  11. package/dist/components/TyCalendarMonth.d.ts.map +1 -1
  12. package/dist/components/TyCalendarMonth.js +5 -7
  13. package/dist/components/TyCalendarMonth.js.map +1 -1
  14. package/dist/components/TyCalendarNavigation.d.ts.map +1 -1
  15. package/dist/components/TyCalendarNavigation.js +2 -6
  16. package/dist/components/TyCalendarNavigation.js.map +1 -1
  17. package/dist/components/TyCheckbox.d.ts +4 -1
  18. package/dist/components/TyCheckbox.d.ts.map +1 -1
  19. package/dist/components/TyCheckbox.js +2 -9
  20. package/dist/components/TyCheckbox.js.map +1 -1
  21. package/dist/components/TyCopy.d.ts +4 -1
  22. package/dist/components/TyCopy.d.ts.map +1 -1
  23. package/dist/components/TyCopy.js +2 -7
  24. package/dist/components/TyCopy.js.map +1 -1
  25. package/dist/components/TyDatePicker.d.ts +14 -4
  26. package/dist/components/TyDatePicker.d.ts.map +1 -1
  27. package/dist/components/TyDatePicker.js +8 -13
  28. package/dist/components/TyDatePicker.js.map +1 -1
  29. package/dist/components/TyFileUpload.d.ts.map +1 -1
  30. package/dist/components/TyFileUpload.js +2 -2
  31. package/dist/components/TyFileUpload.js.map +1 -1
  32. package/dist/components/TyIcon.d.ts.map +1 -1
  33. package/dist/components/TyIcon.js +0 -4
  34. package/dist/components/TyIcon.js.map +1 -1
  35. package/dist/components/TyInput.d.ts +6 -2
  36. package/dist/components/TyInput.d.ts.map +1 -1
  37. package/dist/components/TyInput.js +2 -11
  38. package/dist/components/TyInput.js.map +1 -1
  39. package/dist/components/TyModal.d.ts +21 -2
  40. package/dist/components/TyModal.d.ts.map +1 -1
  41. package/dist/components/TyModal.js +21 -18
  42. package/dist/components/TyModal.js.map +1 -1
  43. package/dist/components/TyOption.d.ts +3 -3
  44. package/dist/components/TyOption.d.ts.map +1 -1
  45. package/dist/components/TyOption.js +2 -3
  46. package/dist/components/TyOption.js.map +1 -1
  47. package/dist/components/TyPopup.d.ts +4 -2
  48. package/dist/components/TyPopup.d.ts.map +1 -1
  49. package/dist/components/TyPopup.js +4 -10
  50. package/dist/components/TyPopup.js.map +1 -1
  51. package/dist/components/TyRadio.d.ts +4 -1
  52. package/dist/components/TyRadio.d.ts.map +1 -1
  53. package/dist/components/TyRadio.js +2 -1
  54. package/dist/components/TyRadio.js.map +1 -1
  55. package/dist/components/TyRadioGroup.d.ts +4 -1
  56. package/dist/components/TyRadioGroup.d.ts.map +1 -1
  57. package/dist/components/TyRadioGroup.js +2 -1
  58. package/dist/components/TyRadioGroup.js.map +1 -1
  59. package/dist/components/TyResizeObserver.d.ts.map +1 -1
  60. package/dist/components/TyResizeObserver.js +2 -5
  61. package/dist/components/TyResizeObserver.js.map +1 -1
  62. package/dist/components/TyScrollContainer.d.ts.map +1 -1
  63. package/dist/components/TyScrollContainer.js +2 -7
  64. package/dist/components/TyScrollContainer.js.map +1 -1
  65. package/dist/components/TySelect.d.ts +44 -2
  66. package/dist/components/TySelect.d.ts.map +1 -1
  67. package/dist/components/TySelect.js +34 -13
  68. package/dist/components/TySelect.js.map +1 -1
  69. package/dist/components/TyStep.d.ts.map +1 -1
  70. package/dist/components/TyStep.js +2 -6
  71. package/dist/components/TyStep.js.map +1 -1
  72. package/dist/components/TySwitch.d.ts +4 -1
  73. package/dist/components/TySwitch.d.ts.map +1 -1
  74. package/dist/components/TySwitch.js +2 -1
  75. package/dist/components/TySwitch.js.map +1 -1
  76. package/dist/components/TyTab.d.ts.map +1 -1
  77. package/dist/components/TyTab.js +2 -7
  78. package/dist/components/TyTab.js.map +1 -1
  79. package/dist/components/TyTabs.d.ts.map +1 -1
  80. package/dist/components/TyTabs.js +2 -6
  81. package/dist/components/TyTabs.js.map +1 -1
  82. package/dist/components/TyTag.d.ts +4 -1
  83. package/dist/components/TyTag.d.ts.map +1 -1
  84. package/dist/components/TyTag.js +2 -3
  85. package/dist/components/TyTag.js.map +1 -1
  86. package/dist/components/TyTextarea.d.ts.map +1 -1
  87. package/dist/components/TyTextarea.js +2 -7
  88. package/dist/components/TyTextarea.js.map +1 -1
  89. package/dist/components/TyTooltip.d.ts +7 -3
  90. package/dist/components/TyTooltip.d.ts.map +1 -1
  91. package/dist/components/TyTooltip.js +2 -5
  92. package/dist/components/TyTooltip.js.map +1 -1
  93. package/dist/components/TyWizard.d.ts.map +1 -1
  94. package/dist/components/TyWizard.js +2 -6
  95. package/dist/components/TyWizard.js.map +1 -1
  96. package/dist/components/index.d.ts +1 -1
  97. package/dist/components/index.d.ts.map +1 -1
  98. package/dist/components/index.js +3 -63
  99. package/dist/components/index.js.map +1 -1
  100. package/dist/utils/host-props.d.ts +11 -0
  101. package/dist/utils/host-props.d.ts.map +1 -0
  102. package/dist/utils/host-props.js +16 -0
  103. package/dist/utils/host-props.js.map +1 -0
  104. package/dist/version.d.ts +1 -1
  105. package/dist/version.js +1 -1
  106. package/package.json +1 -1
  107. package/src/components/TyButton.tsx +3 -2
  108. package/src/components/TyCalendar.tsx +14 -11
  109. package/src/components/TyCalendarMonth.tsx +11 -8
  110. package/src/components/TyCalendarNavigation.tsx +2 -7
  111. package/src/components/TyCheckbox.tsx +6 -11
  112. package/src/components/TyCopy.tsx +6 -9
  113. package/src/components/TyDatePicker.tsx +31 -19
  114. package/src/components/TyFileUpload.tsx +2 -3
  115. package/src/components/TyIcon.tsx +0 -5
  116. package/src/components/TyInput.tsx +8 -15
  117. package/src/components/TyModal.tsx +46 -22
  118. package/src/components/TyOption.tsx +5 -7
  119. package/src/components/TyPopup.tsx +12 -14
  120. package/src/components/TyRadio.tsx +6 -2
  121. package/src/components/TyRadioGroup.tsx +6 -2
  122. package/src/components/TyResizeObserver.tsx +2 -6
  123. package/src/components/TyScrollContainer.tsx +2 -9
  124. package/src/components/TySelect.tsx +88 -22
  125. package/src/components/TyStep.tsx +2 -7
  126. package/src/components/TySwitch.tsx +6 -2
  127. package/src/components/TyTab.tsx +2 -8
  128. package/src/components/TyTabs.tsx +2 -7
  129. package/src/components/TyTag.tsx +6 -5
  130. package/src/components/TyTextarea.tsx +2 -9
  131. package/src/components/TyTooltip.tsx +13 -9
  132. package/src/components/TyWizard.tsx +2 -7
  133. package/src/components/index.ts +3 -98
  134. package/src/utils/host-props.ts +14 -0
  135. package/src/version.ts +1 -1
@@ -1,8 +1,11 @@
1
1
  import React, { useEffect, useRef, useCallback } from 'react';
2
+ import { hostProps } from '../utils/host-props';
2
3
  import { needsPropertyBridge } from '../utils/react-version';
3
4
  import { useBooleanProperty } from '../utils/use-boolean-prop';
4
5
 
5
- // Type definitions for Ty Calendar component
6
+ type BuiltinFlavor = 'primary' | 'success' | 'danger' | 'warning' | 'neutral';
7
+ type ShadedFlavor = BuiltinFlavor | `${BuiltinFlavor}+` | `${BuiltinFlavor}-`;
8
+
6
9
  export interface TyCalendarChangeEventDetail {
7
10
  /** Selected month (1-12) */
8
11
  month: number;
@@ -47,7 +50,10 @@ export interface TyCalendarProps extends Omit<React.HTMLAttributes<HTMLElement>,
47
50
 
48
51
  /** Calendar size */
49
52
  size?: 'sm' | 'md' | 'lg';
50
-
53
+
54
+ /** Visual flavor for the selected/today day cells (nav stays neutral chrome) */
55
+ flavor?: ShadedFlavor | (string & {});
56
+
51
57
  /** Locale for date formatting */
52
58
  locale?: string;
53
59
 
@@ -91,7 +97,6 @@ export interface TyCalendarProps extends Omit<React.HTMLAttributes<HTMLElement>,
91
97
  onDayClick?: (event: CustomEvent) => void;
92
98
  }
93
99
 
94
- // React wrapper for ty-calendar web component
95
100
  export const TyCalendar = React.forwardRef<HTMLElement, TyCalendarProps>(
96
101
  ({
97
102
  year,
@@ -100,6 +105,7 @@ export const TyCalendar = React.forwardRef<HTMLElement, TyCalendarProps>(
100
105
  showNavigation,
101
106
  stateless,
102
107
  size,
108
+ flavor,
103
109
  locale,
104
110
  width,
105
111
  min,
@@ -118,7 +124,6 @@ export const TyCalendar = React.forwardRef<HTMLElement, TyCalendarProps>(
118
124
  }, ref) => {
119
125
  const elementRef = useRef<HTMLElement>(null);
120
126
 
121
- // Handle ref forwarding
122
127
  useEffect(() => {
123
128
  if (ref && elementRef.current) {
124
129
  if (typeof ref === 'function') {
@@ -129,7 +134,6 @@ export const TyCalendar = React.forwardRef<HTMLElement, TyCalendarProps>(
129
134
  }
130
135
  }, [ref]);
131
136
 
132
- // Handle change events (date selection)
133
137
  const handleChange = useCallback((event: Event) => {
134
138
  const customEvent = event as CustomEvent<TyCalendarChangeEventDetail>;
135
139
  if (onChange) {
@@ -137,7 +141,6 @@ export const TyCalendar = React.forwardRef<HTMLElement, TyCalendarProps>(
137
141
  }
138
142
  }, [onChange]);
139
143
 
140
- // Handle navigate events (month/year navigation)
141
144
  const handleNavigate = useCallback((event: Event) => {
142
145
  const customEvent = event as CustomEvent<TyCalendarNavigateEventDetail>;
143
146
  if (onNavigate) {
@@ -149,7 +152,6 @@ export const TyCalendar = React.forwardRef<HTMLElement, TyCalendarProps>(
149
152
  if (onDayClick) onDayClick(event as CustomEvent);
150
153
  }, [onDayClick]);
151
154
 
152
- // Set up event listeners
153
155
  useEffect(() => {
154
156
  const element = elementRef.current;
155
157
  if (!element) return;
@@ -200,7 +202,6 @@ export const TyCalendar = React.forwardRef<HTMLElement, TyCalendarProps>(
200
202
  (element as any).dayClassesFn = null;
201
203
  }
202
204
 
203
- // Custom CSS property
204
205
  if (customCSS) {
205
206
  (element as any).customCSS = customCSS;
206
207
  } else {
@@ -208,13 +209,11 @@ export const TyCalendar = React.forwardRef<HTMLElement, TyCalendarProps>(
208
209
  }
209
210
  }, [dayContentFn, dayClassesFn, customCSS]);
210
211
 
211
- // Convert React props to web component attributes
212
212
  const webComponentProps: Record<string, any> = {
213
- ...props,
213
+ ...hostProps(props),
214
214
  ref: elementRef,
215
215
  };
216
216
 
217
- // Add optional attributes only if they have values
218
217
  if (year !== undefined) {
219
218
  webComponentProps.year = year.toString();
220
219
  }
@@ -237,6 +236,10 @@ export const TyCalendar = React.forwardRef<HTMLElement, TyCalendarProps>(
237
236
  webComponentProps.size = size;
238
237
  }
239
238
 
239
+ if (flavor) {
240
+ webComponentProps.flavor = flavor;
241
+ }
242
+
240
243
  if (locale) {
241
244
  webComponentProps.locale = locale;
242
245
  }
@@ -1,6 +1,9 @@
1
1
  import React, { useEffect, useRef } from 'react';
2
+ import { hostProps } from '../utils/host-props';
3
+
4
+ type BuiltinFlavor = 'primary' | 'success' | 'danger' | 'warning' | 'neutral';
5
+ type ShadedFlavor = BuiltinFlavor | `${BuiltinFlavor}+` | `${BuiltinFlavor}-`;
2
6
 
3
- // Type definitions for Ty Calendar Month component
4
7
  export interface TyCalendarMonthProps extends React.HTMLAttributes<HTMLElement> {
5
8
  /** Display year */
6
9
  displayYear?: number;
@@ -13,7 +16,10 @@ export interface TyCalendarMonthProps extends React.HTMLAttributes<HTMLElement>
13
16
 
14
17
  /** Calendar size */
15
18
  size?: 'sm' | 'md' | 'lg';
16
-
19
+
20
+ /** Visual flavor for the selected/today day cells */
21
+ flavor?: ShadedFlavor | (string & {});
22
+
17
23
  /** Width of calendar */
18
24
  width?: string;
19
25
 
@@ -45,13 +51,13 @@ export interface DayClickDetail {
45
51
  isOtherMonth: boolean;
46
52
  }
47
53
 
48
- // React wrapper for ty-calendar-month web component
49
54
  export const TyCalendarMonth = React.forwardRef<HTMLElement, TyCalendarMonthProps>(
50
55
  ({
51
56
  displayYear,
52
57
  displayMonth,
53
58
  locale,
54
59
  size,
60
+ flavor,
55
61
  width,
56
62
  minWidth,
57
63
  maxWidth,
@@ -62,7 +68,6 @@ export const TyCalendarMonth = React.forwardRef<HTMLElement, TyCalendarMonthProp
62
68
  }, ref) => {
63
69
  const elementRef = useRef<HTMLElement>(null);
64
70
 
65
- // Handle day click events
66
71
  useEffect(() => {
67
72
  const element = elementRef.current;
68
73
  if (!element) return;
@@ -80,7 +85,6 @@ export const TyCalendarMonth = React.forwardRef<HTMLElement, TyCalendarMonthProp
80
85
  };
81
86
  }, [onDayClick]);
82
87
 
83
- // Combine refs if needed
84
88
  useEffect(() => {
85
89
  if (ref && elementRef.current) {
86
90
  if (typeof ref === 'function') {
@@ -91,17 +95,16 @@ export const TyCalendarMonth = React.forwardRef<HTMLElement, TyCalendarMonthProp
91
95
  }
92
96
  }, [ref]);
93
97
 
94
- // Convert React props to web component attributes
95
98
  const webComponentProps: Record<string, any> = {
96
- ...props,
99
+ ...hostProps(props),
97
100
  ref: elementRef,
98
101
  };
99
102
 
100
- // Add attributes
101
103
  if (displayYear !== undefined) webComponentProps['display-year'] = displayYear;
102
104
  if (displayMonth !== undefined) webComponentProps['display-month'] = displayMonth;
103
105
  if (locale) webComponentProps.locale = locale;
104
106
  if (size) webComponentProps.size = size;
107
+ if (flavor) webComponentProps.flavor = flavor;
105
108
  if (width) webComponentProps.width = width;
106
109
  if (min) webComponentProps.min = min;
107
110
  if (max) webComponentProps.max = max;
@@ -1,6 +1,6 @@
1
1
  import React, { useEffect, useRef } from 'react';
2
+ import { hostProps } from '../utils/host-props';
2
3
 
3
- // Type definitions for Ty Calendar Navigation component
4
4
  export interface TyCalendarNavigationProps extends Omit<React.HTMLAttributes<HTMLElement>, 'onChange'> {
5
5
  /** Display month (1-12) */
6
6
  displayMonth?: number;
@@ -32,7 +32,6 @@ export interface NavigationChangeDetail {
32
32
  year: number; // e.g., 2025
33
33
  }
34
34
 
35
- // React wrapper for ty-calendar-navigation web component
36
35
  export const TyCalendarNavigation = React.forwardRef<HTMLElement, TyCalendarNavigationProps>(
37
36
  ({
38
37
  displayMonth,
@@ -47,7 +46,6 @@ export const TyCalendarNavigation = React.forwardRef<HTMLElement, TyCalendarNavi
47
46
  }, ref) => {
48
47
  const elementRef = useRef<HTMLElement>(null);
49
48
 
50
- // Handle change events
51
49
  useEffect(() => {
52
50
  const element = elementRef.current;
53
51
  if (!element) return;
@@ -65,7 +63,6 @@ export const TyCalendarNavigation = React.forwardRef<HTMLElement, TyCalendarNavi
65
63
  };
66
64
  }, [onChange]);
67
65
 
68
- // Combine refs if needed
69
66
  useEffect(() => {
70
67
  if (ref && elementRef.current) {
71
68
  if (typeof ref === 'function') {
@@ -76,13 +73,11 @@ export const TyCalendarNavigation = React.forwardRef<HTMLElement, TyCalendarNavi
76
73
  }
77
74
  }, [ref]);
78
75
 
79
- // Convert React props to web component attributes
80
76
  const webComponentProps: Record<string, any> = {
81
- ...props,
77
+ ...hostProps(props),
82
78
  ref: elementRef,
83
79
  };
84
80
 
85
- // Add attributes
86
81
  if (displayMonth !== undefined) webComponentProps['display-month'] = displayMonth;
87
82
  if (displayYear !== undefined) webComponentProps['display-year'] = displayYear;
88
83
  if (locale) webComponentProps.locale = locale;
@@ -1,7 +1,10 @@
1
1
  import React, { useEffect, useRef } from 'react';
2
+ import { hostProps } from '../utils/host-props';
2
3
  import { useBooleanProperty } from '../utils/use-boolean-prop';
3
4
 
4
- // Type definitions for Ty Checkbox component
5
+ type BuiltinFlavor = 'primary' | 'success' | 'danger' | 'warning' | 'neutral';
6
+ type ShadedFlavor = BuiltinFlavor | `${BuiltinFlavor}+` | `${BuiltinFlavor}-`;
7
+
5
8
  export interface TyCheckboxProps extends Omit<React.HTMLAttributes<HTMLElement>, 'onChange' | 'onInput'> {
6
9
  /** Checked state */
7
10
  checked?: boolean;
@@ -28,7 +31,7 @@ export interface TyCheckboxProps extends Omit<React.HTMLAttributes<HTMLElement>,
28
31
  size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl';
29
32
 
30
33
  /** Semantic styling variant */
31
- flavor?: 'primary' | 'secondary' | 'success' | 'danger' | 'warning' | 'neutral';
34
+ flavor?: ShadedFlavor | (string & {});
32
35
 
33
36
  /**
34
37
  * Fires when checkbox state changes (React convention)
@@ -53,7 +56,6 @@ export interface TyCheckboxEventDetail {
53
56
  originalEvent: Event;
54
57
  }
55
58
 
56
- // React wrapper for ty-checkbox web component
57
59
  export const TyCheckbox = React.forwardRef<HTMLElement, TyCheckboxProps>(
58
60
  ({
59
61
  children,
@@ -72,7 +74,6 @@ export const TyCheckbox = React.forwardRef<HTMLElement, TyCheckboxProps>(
72
74
  }, ref) => {
73
75
  const elementRef = useRef<HTMLElement>(null);
74
76
 
75
- // Handle change events
76
77
  useEffect(() => {
77
78
  const element = elementRef.current;
78
79
  if (!element) return;
@@ -91,10 +92,8 @@ export const TyCheckbox = React.forwardRef<HTMLElement, TyCheckboxProps>(
91
92
  }
92
93
  };
93
94
 
94
- // Map onChange → input event (React convention)
95
95
  element.addEventListener('input', handleInput);
96
96
 
97
- // Map onChangeCommit → change event (blur behavior)
98
97
  element.addEventListener('change', handleChangeCommit);
99
98
 
100
99
  return () => {
@@ -103,7 +102,6 @@ export const TyCheckbox = React.forwardRef<HTMLElement, TyCheckboxProps>(
103
102
  };
104
103
  }, [onChange, onChangeCommit]);
105
104
 
106
- // Combine refs if needed
107
105
  useEffect(() => {
108
106
  if (ref && elementRef.current) {
109
107
  if (typeof ref === 'function') {
@@ -123,19 +121,16 @@ export const TyCheckbox = React.forwardRef<HTMLElement, TyCheckboxProps>(
123
121
  const isDisabled = useBooleanProperty(elementRef, 'disabled', disabled);
124
122
  const isRequired = useBooleanProperty(elementRef, 'required', required);
125
123
 
126
- // Convert React props to web component attributes
127
124
  const webComponentProps: Record<string, any> = {
128
- ...props,
125
+ ...hostProps(props),
129
126
  ref: elementRef,
130
127
  };
131
128
 
132
- // Add boolean attributes
133
129
  if (isChecked) webComponentProps.checked = '';
134
130
  if (isIndeterminate) webComponentProps.indeterminate = '';
135
131
  if (isDisabled) webComponentProps.disabled = '';
136
132
  if (isRequired) webComponentProps.required = '';
137
133
 
138
- // Add string attributes
139
134
  if (value) webComponentProps.value = value;
140
135
  if (name) webComponentProps.name = name;
141
136
  if (error) webComponentProps.error = error;
@@ -1,7 +1,10 @@
1
1
  import React, { useEffect, useRef } from 'react';
2
+ import { hostProps } from '../utils/host-props';
2
3
  import { useBooleanProperty } from '../utils/use-boolean-prop';
3
4
 
4
- // Type definitions for Ty Copy component
5
+ type BuiltinFlavor = 'primary' | 'success' | 'danger' | 'warning' | 'neutral';
6
+ type ShadedFlavor = BuiltinFlavor | `${BuiltinFlavor}+` | `${BuiltinFlavor}-`;
7
+
5
8
  export interface TyCopyProps extends Omit<React.HTMLAttributes<HTMLElement>, 'onChange'> {
6
9
  /** Text to copy */
7
10
  value?: string;
@@ -13,7 +16,7 @@ export interface TyCopyProps extends Omit<React.HTMLAttributes<HTMLElement>, 'on
13
16
  size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl';
14
17
 
15
18
  /** Semantic styling variant */
16
- flavor?: 'primary' | 'secondary' | 'success' | 'danger' | 'warning' | 'neutral';
19
+ flavor?: ShadedFlavor | (string & {});
17
20
 
18
21
  /** Display format */
19
22
  format?: 'text' | 'code';
@@ -34,7 +37,6 @@ export interface TyCopyProps extends Omit<React.HTMLAttributes<HTMLElement>, 'on
34
37
  onCopyError?: (event: CustomEvent) => void;
35
38
  }
36
39
 
37
- // React wrapper for ty-copy web component
38
40
  export const TyCopy = React.forwardRef<HTMLElement, TyCopyProps>(
39
41
  ({
40
42
  value,
@@ -51,7 +53,6 @@ export const TyCopy = React.forwardRef<HTMLElement, TyCopyProps>(
51
53
  }, ref) => {
52
54
  const elementRef = useRef<HTMLElement>(null);
53
55
 
54
- // Handle ref forwarding
55
56
  useEffect(() => {
56
57
  if (ref && elementRef.current) {
57
58
  if (typeof ref === 'function') {
@@ -62,7 +63,6 @@ export const TyCopy = React.forwardRef<HTMLElement, TyCopyProps>(
62
63
  }
63
64
  }, [ref]);
64
65
 
65
- // Custom events → React callbacks
66
66
  useEffect(() => {
67
67
  const el = elementRef.current;
68
68
  if (!el) return;
@@ -82,20 +82,17 @@ export const TyCopy = React.forwardRef<HTMLElement, TyCopyProps>(
82
82
  const isDisabled = useBooleanProperty(elementRef, 'disabled', disabled);
83
83
  const isRequired = useBooleanProperty(elementRef, 'required', required);
84
84
 
85
- // Convert React props to web component attributes
86
85
  const webComponentProps: Record<string, any> = {
87
- ...props,
86
+ ...hostProps(props),
88
87
  ref: elementRef,
89
88
  };
90
89
 
91
- // Add string attributes
92
90
  if (value) webComponentProps.value = value;
93
91
  if (label) webComponentProps.label = label;
94
92
  if (size) webComponentProps.size = size;
95
93
  if (flavor) webComponentProps.flavor = flavor;
96
94
  if (format) webComponentProps.format = format;
97
95
 
98
- // Add boolean attributes
99
96
  if (isMultiline) webComponentProps.multiline = '';
100
97
  if (isDisabled) webComponentProps.disabled = '';
101
98
  if (isRequired) webComponentProps.required = '';
@@ -1,8 +1,16 @@
1
1
  import React, { useEffect, useRef, useCallback } from 'react';
2
+ import { hostProps } from '../utils/host-props';
2
3
  import { needsPropertyBridge } from '../utils/react-version';
3
4
  import { useBooleanProperty } from '../utils/use-boolean-prop';
4
5
 
5
- // Type definitions for Ty DatePicker component
6
+ type BuiltinFlavor = 'primary' | 'success' | 'danger' | 'warning' | 'neutral';
7
+ type ShadedFlavor = BuiltinFlavor | `${BuiltinFlavor}+` | `${BuiltinFlavor}-`;
8
+ type Placement =
9
+ | 'top-start' | 'top' | 'top-end'
10
+ | 'right-start' | 'right' | 'right-end'
11
+ | 'bottom-start' | 'bottom' | 'bottom-end'
12
+ | 'left-start' | 'left' | 'left-end';
13
+
6
14
  export interface TyDatePickerEventDetail {
7
15
  /** The selected date value (ISO string or formatted string based on format) */
8
16
  value: string | null;
@@ -18,11 +26,11 @@ export interface TyDatePickerProps extends Omit<React.HTMLAttributes<HTMLElement
18
26
  /** The selected date value (ISO string or formatted string) */
19
27
  value?: string;
20
28
 
21
- /** Input size: "sm" | "md" | "lg" */
29
+ /** Field size — fields come in exactly three; legacy xs/xl map to sm/lg */
22
30
  size?: 'sm' | 'md' | 'lg';
23
31
 
24
- /** Visual flavor: "default" | "success" | "danger" | "warning" */
25
- flavor?: 'default' | 'success' | 'danger' | 'warning';
32
+ /** Visual flavor — built-in semantic, +/- shade, or a custom flavor backed by --ty-*-X tokens. Also tints the popup calendar's selected/today day. */
33
+ flavor?: 'default' | ShadedFlavor | (string & {});
26
34
 
27
35
  /** Label text displayed above the input */
28
36
  label?: string;
@@ -56,7 +64,10 @@ export interface TyDatePickerProps extends Omit<React.HTMLAttributes<HTMLElement
56
64
 
57
65
  /** Latest selectable date (ISO "YYYY-MM-DD") */
58
66
  max?: string;
59
-
67
+
68
+ /** Calendar popup placement, same vocabulary as ty-popup/ty-tooltip/ty-select: a side plus an optional cross-axis alignment (e.g. "bottom-start"). The calendar only lives above or below the field, so left/right degrade to auto-side with the alignment kept. Empty/unset = auto (below when it fits). */
69
+ placement?: Placement;
70
+
60
71
  /** Callback when the date value changes */
61
72
  onChange?: (event: CustomEvent<TyDatePickerEventDetail>) => void;
62
73
 
@@ -67,8 +78,12 @@ export interface TyDatePickerProps extends Omit<React.HTMLAttributes<HTMLElement
67
78
  onClose?: (event: CustomEvent<{}>) => void;
68
79
  }
69
80
 
70
- // React wrapper for ty-date-picker web component
71
- export const TyDatePicker = React.forwardRef<HTMLElement, TyDatePickerProps>(
81
+ /** The underlying custom element, typed with its imperative clear() method. */
82
+ export interface TyDatePickerElement extends HTMLElement {
83
+ clear(): void;
84
+ }
85
+
86
+ export const TyDatePicker = React.forwardRef<TyDatePickerElement, TyDatePickerProps>(
72
87
  ({
73
88
  value,
74
89
  size,
@@ -84,14 +99,14 @@ export const TyDatePicker = React.forwardRef<HTMLElement, TyDatePickerProps>(
84
99
  withTime,
85
100
  min,
86
101
  max,
102
+ placement,
87
103
  onChange,
88
104
  onOpen,
89
105
  onClose,
90
106
  ...props
91
107
  }, ref) => {
92
- const elementRef = useRef<HTMLElement>(null);
108
+ const elementRef = useRef<TyDatePickerElement>(null);
93
109
 
94
- // Handle ref forwarding
95
110
  useEffect(() => {
96
111
  if (ref && elementRef.current) {
97
112
  if (typeof ref === 'function') {
@@ -109,12 +124,10 @@ export const TyDatePicker = React.forwardRef<HTMLElement, TyDatePickerProps>(
109
124
  if (!needsPropertyBridge) return;
110
125
  const element = elementRef.current;
111
126
  if (element && value !== undefined) {
112
- // Set the value property directly on the element
113
127
  (element as any).value = value || '';
114
128
  }
115
129
  }, [value]);
116
130
 
117
- // Handle change events
118
131
  const handleChange = useCallback((event: Event) => {
119
132
  const customEvent = event as CustomEvent<TyDatePickerEventDetail>;
120
133
  if (onChange) {
@@ -122,10 +135,8 @@ export const TyDatePicker = React.forwardRef<HTMLElement, TyDatePickerProps>(
122
135
  }
123
136
  }, [onChange]);
124
137
 
125
- // Handle open/close events. Guard with `event.target === element` so
126
- // bubbled open/close events from popup-like descendants slotted inside
127
- // (rare for a date-picker, but defensive — same fix as TyModal/TyPopup)
128
- // don't fire the consumer's onOpen/onClose.
138
+ // Handle open/close events. See TyModal.tsx for why the
139
+ // `event.target === element` guard is still here.
129
140
  const handleOpen = useCallback((event: Event) => {
130
141
  if (event.target !== elementRef.current) return;
131
142
  if (onOpen) onOpen(event as CustomEvent<{}>);
@@ -136,7 +147,6 @@ export const TyDatePicker = React.forwardRef<HTMLElement, TyDatePickerProps>(
136
147
  if (onClose) onClose(event as CustomEvent<{}>);
137
148
  }, [onClose]);
138
149
 
139
- // Set up event listeners
140
150
  useEffect(() => {
141
151
  const element = elementRef.current;
142
152
  if (!element) return;
@@ -165,13 +175,11 @@ export const TyDatePicker = React.forwardRef<HTMLElement, TyDatePickerProps>(
165
175
  };
166
176
  }, [handleChange, handleOpen, handleClose, onChange, onOpen, onClose]);
167
177
 
168
- // Convert React props to web component attributes
169
178
  const webComponentProps: Record<string, any> = {
170
- ...props,
179
+ ...hostProps(props),
171
180
  ref: elementRef,
172
181
  };
173
182
 
174
- // Add optional attributes only if they have values
175
183
  if (value !== undefined) {
176
184
  webComponentProps.value = value;
177
185
  }
@@ -224,6 +232,10 @@ export const TyDatePicker = React.forwardRef<HTMLElement, TyDatePickerProps>(
224
232
  webComponentProps.max = max;
225
233
  }
226
234
 
235
+ if (placement) {
236
+ webComponentProps.placement = placement;
237
+ }
238
+
227
239
  return React.createElement('ty-date-picker', webComponentProps);
228
240
  }
229
241
  );
@@ -1,7 +1,7 @@
1
1
  import React, { useEffect, useRef } from 'react';
2
+ import { hostProps } from '../utils/host-props';
2
3
  import { useBooleanProperty } from '../utils/use-boolean-prop';
3
4
 
4
- // Type definitions for Ty File Upload component
5
5
  export interface TyFileUploadProps extends Omit<React.HTMLAttributes<HTMLElement>, 'onChange'> {
6
6
  /** Form field name — used as the FormData key */
7
7
  name?: string;
@@ -40,7 +40,6 @@ export interface TyFileUploadEventDetail {
40
40
  names: string[];
41
41
  }
42
42
 
43
- // React wrapper for ty-file-upload web component
44
43
  export const TyFileUpload = React.forwardRef<HTMLElement, TyFileUploadProps>(
45
44
  ({
46
45
  name,
@@ -87,7 +86,7 @@ export const TyFileUpload = React.forwardRef<HTMLElement, TyFileUploadProps>(
87
86
  const isRequired = useBooleanProperty(elementRef, 'required', required);
88
87
 
89
88
  const webComponentProps: Record<string, any> = {
90
- ...props,
89
+ ...hostProps(props),
91
90
  ref: elementRef,
92
91
  };
93
92
 
@@ -1,7 +1,6 @@
1
1
  import React, { useEffect, useRef } from 'react';
2
2
  import { useBooleanProperty } from '../utils/use-boolean-prop';
3
3
 
4
- // Type definitions for Ty Icon component
5
4
  export interface TyIconProps extends React.HTMLAttributes<HTMLElement> {
6
5
  /** Icon name from the icon registry (e.g., 'home', 'star', 'settings') */
7
6
  name: string;
@@ -22,12 +21,10 @@ export interface TyIconProps extends React.HTMLAttributes<HTMLElement> {
22
21
  className?: string;
23
22
  }
24
23
 
25
- // React wrapper for ty-icon web component
26
24
  export const TyIcon = React.forwardRef<HTMLElement, TyIconProps>(
27
25
  ({ name, size, spin, pulse, tempo, className, ...props }, ref) => {
28
26
  const elementRef = useRef<HTMLElement>(null);
29
27
 
30
- // Handle ref forwarding
31
28
  useEffect(() => {
32
29
  if (ref && elementRef.current) {
33
30
  if (typeof ref === 'function') {
@@ -41,14 +38,12 @@ export const TyIcon = React.forwardRef<HTMLElement, TyIconProps>(
41
38
  const isSpin = useBooleanProperty(elementRef, 'spin', spin);
42
39
  const isPulse = useBooleanProperty(elementRef, 'pulse', pulse);
43
40
 
44
- // Convert React props to web component attributes
45
41
  const webComponentProps: Record<string, any> = {
46
42
  ...props,
47
43
  name,
48
44
  ref: elementRef,
49
45
  };
50
46
 
51
- // Add optional attributes only if they have values
52
47
  if (size) {
53
48
  webComponentProps.size = size;
54
49
  }
@@ -1,8 +1,11 @@
1
1
  import React, { useEffect, useRef, useCallback } from 'react';
2
+ import { hostProps } from '../utils/host-props';
2
3
  import { needsPropertyBridge } from '../utils/react-version';
3
4
  import { useBooleanProperty } from '../utils/use-boolean-prop';
4
5
 
5
- // Event detail structure for ty-input events
6
+ type BuiltinFlavor = 'primary' | 'success' | 'danger' | 'warning' | 'neutral';
7
+ type ShadedFlavor = BuiltinFlavor | `${BuiltinFlavor}+` | `${BuiltinFlavor}-`;
8
+
6
9
  export interface TyInputEventDetail {
7
10
  value: any; // shadow value (processed/parsed)
8
11
  formattedValue: string; // user-visible formatted value
@@ -23,7 +26,6 @@ export interface TyInputCSSProperties extends React.CSSProperties {
23
26
  '--input-disabled-color'?: string;
24
27
  }
25
28
 
26
- // Type definitions for Ty Input component
27
29
  export interface TyInputProps extends Omit<React.HTMLAttributes<HTMLElement>, 'onChange' | 'onFocus' | 'onBlur' | 'style'> {
28
30
  style?: TyInputCSSProperties;
29
31
  /** Input type */
@@ -31,10 +33,11 @@ export interface TyInputProps extends Omit<React.HTMLAttributes<HTMLElement>, 'o
31
33
  | 'currency' | 'percent' | 'compact';
32
34
 
33
35
  /** Semantic styling variant */
34
- flavor?: 'primary' | 'secondary' | 'success' | 'danger' | 'warning' | 'neutral';
36
+ flavor?: ShadedFlavor | (string & {});
35
37
 
36
38
  /** Input size */
37
- size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl';
39
+ /** Field size — fields come in exactly three; legacy xs/xl map to sm/lg */
40
+ size?: 'sm' | 'md' | 'lg';
38
41
 
39
42
  /** Input value */
40
43
  value?: string;
@@ -91,7 +94,6 @@ export interface TyInputProps extends Omit<React.HTMLAttributes<HTMLElement>, 'o
91
94
  // One-time global warning flags so we don't spam the console.
92
95
  let _warnedOnInputProp = false;
93
96
 
94
- // React wrapper for ty-input web component
95
97
  export const TyInput = React.forwardRef<HTMLElement, TyInputProps>(
96
98
  ({ onChange, onChangeCommit, onFocus, onBlur, disabled, required, name, checked, debounce, ...props }, ref) => {
97
99
  const elementRef = useRef<HTMLElement>(null);
@@ -145,18 +147,14 @@ export const TyInput = React.forwardRef<HTMLElement, TyInputProps>(
145
147
  const element = elementRef.current;
146
148
  if (!element) return;
147
149
 
148
- // Listen for custom input/change events from ty-input
149
- // Map onChange → input event (React convention)
150
150
  if (onChange) {
151
151
  element.addEventListener('input', handleInput as EventListener);
152
152
  }
153
153
 
154
- // Map onChangeCommit → change event (blur behavior)
155
154
  if (onChangeCommit) {
156
155
  element.addEventListener('change', handleChangeCommit as EventListener);
157
156
  }
158
157
 
159
- // Listen for standard focus/blur events
160
158
  if (onFocus) {
161
159
  element.addEventListener('focus', handleFocus as EventListener);
162
160
  }
@@ -181,7 +179,6 @@ export const TyInput = React.forwardRef<HTMLElement, TyInputProps>(
181
179
  };
182
180
  }, [handleInput, handleChangeCommit, handleFocus, handleBlur, onChange, onChangeCommit, onFocus, onBlur]);
183
181
 
184
- // Handle ref forwarding
185
182
  useEffect(() => {
186
183
  if (ref && elementRef.current) {
187
184
  if (typeof ref === 'function') {
@@ -212,21 +209,17 @@ export const TyInput = React.forwardRef<HTMLElement, TyInputProps>(
212
209
  const isRequired = useBooleanProperty(elementRef, 'required', required);
213
210
  const isChecked = useBooleanProperty(elementRef, 'checked', checked);
214
211
 
215
- // Convert React props to web component attributes
216
212
  const webComponentProps: Record<string, any> = {
217
- ...props,
213
+ ...hostProps(props),
218
214
  ref: elementRef,
219
215
  };
220
216
 
221
- // Add conditional attributes
222
217
  if (isDisabled) webComponentProps.disabled = '';
223
218
  if (isRequired) webComponentProps.required = '';
224
219
  if (isChecked) webComponentProps.checked = '';
225
220
 
226
- // Add string attributes
227
221
  if (name) webComponentProps.name = name;
228
222
 
229
- // Add debounce attribute
230
223
  if (debounce !== undefined) webComponentProps.debounce = debounce;
231
224
 
232
225
  return React.createElement(