tyrell-react 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.
Files changed (120) hide show
  1. package/dist/components/TyButton.d.ts +1 -1
  2. package/dist/components/TyButton.d.ts.map +1 -1
  3. package/dist/components/TyCalendar.d.ts +1 -1
  4. package/dist/components/TyCalendar.d.ts.map +1 -1
  5. package/dist/components/TyCalendar.js +0 -8
  6. package/dist/components/TyCalendar.js.map +1 -1
  7. package/dist/components/TyCalendarMonth.d.ts +1 -1
  8. package/dist/components/TyCalendarMonth.d.ts.map +1 -1
  9. package/dist/components/TyCalendarMonth.js +0 -5
  10. package/dist/components/TyCalendarMonth.js.map +1 -1
  11. package/dist/components/TyCalendarNavigation.d.ts.map +1 -1
  12. package/dist/components/TyCalendarNavigation.js +0 -5
  13. package/dist/components/TyCalendarNavigation.js.map +1 -1
  14. package/dist/components/TyCheckbox.d.ts +1 -1
  15. package/dist/components/TyCheckbox.d.ts.map +1 -1
  16. package/dist/components/TyCheckbox.js +0 -8
  17. package/dist/components/TyCheckbox.js.map +1 -1
  18. package/dist/components/TyCopy.d.ts +1 -1
  19. package/dist/components/TyCopy.d.ts.map +1 -1
  20. package/dist/components/TyCopy.js +0 -6
  21. package/dist/components/TyCopy.js.map +1 -1
  22. package/dist/components/TyDatePicker.d.ts +4 -1
  23. package/dist/components/TyDatePicker.d.ts.map +1 -1
  24. package/dist/components/TyDatePicker.js +6 -12
  25. package/dist/components/TyDatePicker.js.map +1 -1
  26. package/dist/components/TyFileUpload.d.ts.map +1 -1
  27. package/dist/components/TyFileUpload.js +0 -1
  28. package/dist/components/TyFileUpload.js.map +1 -1
  29. package/dist/components/TyIcon.d.ts.map +1 -1
  30. package/dist/components/TyIcon.js +0 -4
  31. package/dist/components/TyIcon.js.map +1 -1
  32. package/dist/components/TyInput.d.ts +1 -1
  33. package/dist/components/TyInput.d.ts.map +1 -1
  34. package/dist/components/TyInput.js +0 -10
  35. package/dist/components/TyInput.js.map +1 -1
  36. package/dist/components/TyModal.d.ts +16 -2
  37. package/dist/components/TyModal.d.ts.map +1 -1
  38. package/dist/components/TyModal.js +17 -17
  39. package/dist/components/TyModal.js.map +1 -1
  40. package/dist/components/TyOption.d.ts +1 -1
  41. package/dist/components/TyOption.d.ts.map +1 -1
  42. package/dist/components/TyOption.js +0 -2
  43. package/dist/components/TyOption.js.map +1 -1
  44. package/dist/components/TyPopup.d.ts +4 -2
  45. package/dist/components/TyPopup.d.ts.map +1 -1
  46. package/dist/components/TyPopup.js +2 -9
  47. package/dist/components/TyPopup.js.map +1 -1
  48. package/dist/components/TyRadio.d.ts +1 -1
  49. package/dist/components/TyRadio.d.ts.map +1 -1
  50. package/dist/components/TyRadioGroup.d.ts +1 -1
  51. package/dist/components/TyRadioGroup.d.ts.map +1 -1
  52. package/dist/components/TyResizeObserver.d.ts.map +1 -1
  53. package/dist/components/TyResizeObserver.js +0 -4
  54. package/dist/components/TyResizeObserver.js.map +1 -1
  55. package/dist/components/TyScrollContainer.d.ts.map +1 -1
  56. package/dist/components/TyScrollContainer.js +0 -6
  57. package/dist/components/TyScrollContainer.js.map +1 -1
  58. package/dist/components/TySelect.d.ts +6 -3
  59. package/dist/components/TySelect.d.ts.map +1 -1
  60. package/dist/components/TySelect.js +3 -7
  61. package/dist/components/TySelect.js.map +1 -1
  62. package/dist/components/TyStep.d.ts.map +1 -1
  63. package/dist/components/TyStep.js +0 -5
  64. package/dist/components/TyStep.js.map +1 -1
  65. package/dist/components/TySwitch.d.ts +1 -1
  66. package/dist/components/TySwitch.d.ts.map +1 -1
  67. package/dist/components/TyTab.d.ts.map +1 -1
  68. package/dist/components/TyTab.js +0 -6
  69. package/dist/components/TyTab.js.map +1 -1
  70. package/dist/components/TyTabs.d.ts.map +1 -1
  71. package/dist/components/TyTabs.js +0 -5
  72. package/dist/components/TyTabs.js.map +1 -1
  73. package/dist/components/TyTag.d.ts +1 -1
  74. package/dist/components/TyTag.d.ts.map +1 -1
  75. package/dist/components/TyTag.js +0 -2
  76. package/dist/components/TyTag.js.map +1 -1
  77. package/dist/components/TyTextarea.d.ts.map +1 -1
  78. package/dist/components/TyTextarea.js +0 -6
  79. package/dist/components/TyTextarea.js.map +1 -1
  80. package/dist/components/TyTooltip.d.ts +4 -3
  81. package/dist/components/TyTooltip.d.ts.map +1 -1
  82. package/dist/components/TyTooltip.js +0 -4
  83. package/dist/components/TyTooltip.js.map +1 -1
  84. package/dist/components/TyWizard.d.ts.map +1 -1
  85. package/dist/components/TyWizard.js +0 -5
  86. package/dist/components/TyWizard.js.map +1 -1
  87. package/dist/components/index.d.ts.map +1 -1
  88. package/dist/components/index.js +2 -62
  89. package/dist/components/index.js.map +1 -1
  90. package/dist/version.d.ts +1 -1
  91. package/dist/version.js +1 -1
  92. package/package.json +1 -1
  93. package/src/components/TyButton.tsx +1 -1
  94. package/src/components/TyCalendar.tsx +1 -10
  95. package/src/components/TyCalendarMonth.tsx +1 -7
  96. package/src/components/TyCalendarNavigation.tsx +0 -6
  97. package/src/components/TyCheckbox.tsx +1 -10
  98. package/src/components/TyCopy.tsx +1 -8
  99. package/src/components/TyDatePicker.tsx +17 -14
  100. package/src/components/TyFileUpload.tsx +0 -2
  101. package/src/components/TyIcon.tsx +0 -5
  102. package/src/components/TyInput.tsx +1 -13
  103. package/src/components/TyModal.tsx +36 -21
  104. package/src/components/TyOption.tsx +1 -4
  105. package/src/components/TyPopup.tsx +10 -13
  106. package/src/components/TyRadio.tsx +1 -1
  107. package/src/components/TyRadioGroup.tsx +1 -1
  108. package/src/components/TyResizeObserver.tsx +0 -5
  109. package/src/components/TyScrollContainer.tsx +0 -8
  110. package/src/components/TySelect.tsx +13 -12
  111. package/src/components/TyStep.tsx +0 -6
  112. package/src/components/TySwitch.tsx +1 -1
  113. package/src/components/TyTab.tsx +0 -7
  114. package/src/components/TyTabs.tsx +0 -6
  115. package/src/components/TyTag.tsx +1 -4
  116. package/src/components/TyTextarea.tsx +0 -8
  117. package/src/components/TyTooltip.tsx +8 -8
  118. package/src/components/TyWizard.tsx +0 -6
  119. package/src/components/index.ts +2 -97
  120. package/src/version.ts +1 -1
@@ -1,10 +1,9 @@
1
1
  import React, { useEffect, useRef } from 'react';
2
2
  import { hostProps } from '../utils/host-props';
3
3
 
4
- type BuiltinFlavor = 'primary' | 'secondary' | 'success' | 'danger' | 'warning' | 'neutral';
4
+ type BuiltinFlavor = 'primary' | 'success' | 'danger' | 'warning' | 'neutral';
5
5
  type ShadedFlavor = BuiltinFlavor | `${BuiltinFlavor}+` | `${BuiltinFlavor}-`;
6
6
 
7
- // Type definitions for Ty Calendar Month component
8
7
  export interface TyCalendarMonthProps extends React.HTMLAttributes<HTMLElement> {
9
8
  /** Display year */
10
9
  displayYear?: number;
@@ -52,7 +51,6 @@ export interface DayClickDetail {
52
51
  isOtherMonth: boolean;
53
52
  }
54
53
 
55
- // React wrapper for ty-calendar-month web component
56
54
  export const TyCalendarMonth = React.forwardRef<HTMLElement, TyCalendarMonthProps>(
57
55
  ({
58
56
  displayYear,
@@ -70,7 +68,6 @@ export const TyCalendarMonth = React.forwardRef<HTMLElement, TyCalendarMonthProp
70
68
  }, ref) => {
71
69
  const elementRef = useRef<HTMLElement>(null);
72
70
 
73
- // Handle day click events
74
71
  useEffect(() => {
75
72
  const element = elementRef.current;
76
73
  if (!element) return;
@@ -88,7 +85,6 @@ export const TyCalendarMonth = React.forwardRef<HTMLElement, TyCalendarMonthProp
88
85
  };
89
86
  }, [onDayClick]);
90
87
 
91
- // Combine refs if needed
92
88
  useEffect(() => {
93
89
  if (ref && elementRef.current) {
94
90
  if (typeof ref === 'function') {
@@ -99,13 +95,11 @@ export const TyCalendarMonth = React.forwardRef<HTMLElement, TyCalendarMonthProp
99
95
  }
100
96
  }, [ref]);
101
97
 
102
- // Convert React props to web component attributes
103
98
  const webComponentProps: Record<string, any> = {
104
99
  ...hostProps(props),
105
100
  ref: elementRef,
106
101
  };
107
102
 
108
- // Add attributes
109
103
  if (displayYear !== undefined) webComponentProps['display-year'] = displayYear;
110
104
  if (displayMonth !== undefined) webComponentProps['display-month'] = displayMonth;
111
105
  if (locale) webComponentProps.locale = locale;
@@ -1,7 +1,6 @@
1
1
  import React, { useEffect, useRef } from 'react';
2
2
  import { hostProps } from '../utils/host-props';
3
3
 
4
- // Type definitions for Ty Calendar Navigation component
5
4
  export interface TyCalendarNavigationProps extends Omit<React.HTMLAttributes<HTMLElement>, 'onChange'> {
6
5
  /** Display month (1-12) */
7
6
  displayMonth?: number;
@@ -33,7 +32,6 @@ export interface NavigationChangeDetail {
33
32
  year: number; // e.g., 2025
34
33
  }
35
34
 
36
- // React wrapper for ty-calendar-navigation web component
37
35
  export const TyCalendarNavigation = React.forwardRef<HTMLElement, TyCalendarNavigationProps>(
38
36
  ({
39
37
  displayMonth,
@@ -48,7 +46,6 @@ export const TyCalendarNavigation = React.forwardRef<HTMLElement, TyCalendarNavi
48
46
  }, ref) => {
49
47
  const elementRef = useRef<HTMLElement>(null);
50
48
 
51
- // Handle change events
52
49
  useEffect(() => {
53
50
  const element = elementRef.current;
54
51
  if (!element) return;
@@ -66,7 +63,6 @@ export const TyCalendarNavigation = React.forwardRef<HTMLElement, TyCalendarNavi
66
63
  };
67
64
  }, [onChange]);
68
65
 
69
- // Combine refs if needed
70
66
  useEffect(() => {
71
67
  if (ref && elementRef.current) {
72
68
  if (typeof ref === 'function') {
@@ -77,13 +73,11 @@ export const TyCalendarNavigation = React.forwardRef<HTMLElement, TyCalendarNavi
77
73
  }
78
74
  }, [ref]);
79
75
 
80
- // Convert React props to web component attributes
81
76
  const webComponentProps: Record<string, any> = {
82
77
  ...hostProps(props),
83
78
  ref: elementRef,
84
79
  };
85
80
 
86
- // Add attributes
87
81
  if (displayMonth !== undefined) webComponentProps['display-month'] = displayMonth;
88
82
  if (displayYear !== undefined) webComponentProps['display-year'] = displayYear;
89
83
  if (locale) webComponentProps.locale = locale;
@@ -2,10 +2,9 @@ import React, { useEffect, useRef } from 'react';
2
2
  import { hostProps } from '../utils/host-props';
3
3
  import { useBooleanProperty } from '../utils/use-boolean-prop';
4
4
 
5
- type BuiltinFlavor = 'primary' | 'secondary' | 'success' | 'danger' | 'warning' | 'neutral';
5
+ type BuiltinFlavor = 'primary' | 'success' | 'danger' | 'warning' | 'neutral';
6
6
  type ShadedFlavor = BuiltinFlavor | `${BuiltinFlavor}+` | `${BuiltinFlavor}-`;
7
7
 
8
- // Type definitions for Ty Checkbox component
9
8
  export interface TyCheckboxProps extends Omit<React.HTMLAttributes<HTMLElement>, 'onChange' | 'onInput'> {
10
9
  /** Checked state */
11
10
  checked?: boolean;
@@ -57,7 +56,6 @@ export interface TyCheckboxEventDetail {
57
56
  originalEvent: Event;
58
57
  }
59
58
 
60
- // React wrapper for ty-checkbox web component
61
59
  export const TyCheckbox = React.forwardRef<HTMLElement, TyCheckboxProps>(
62
60
  ({
63
61
  children,
@@ -76,7 +74,6 @@ export const TyCheckbox = React.forwardRef<HTMLElement, TyCheckboxProps>(
76
74
  }, ref) => {
77
75
  const elementRef = useRef<HTMLElement>(null);
78
76
 
79
- // Handle change events
80
77
  useEffect(() => {
81
78
  const element = elementRef.current;
82
79
  if (!element) return;
@@ -95,10 +92,8 @@ export const TyCheckbox = React.forwardRef<HTMLElement, TyCheckboxProps>(
95
92
  }
96
93
  };
97
94
 
98
- // Map onChange → input event (React convention)
99
95
  element.addEventListener('input', handleInput);
100
96
 
101
- // Map onChangeCommit → change event (blur behavior)
102
97
  element.addEventListener('change', handleChangeCommit);
103
98
 
104
99
  return () => {
@@ -107,7 +102,6 @@ export const TyCheckbox = React.forwardRef<HTMLElement, TyCheckboxProps>(
107
102
  };
108
103
  }, [onChange, onChangeCommit]);
109
104
 
110
- // Combine refs if needed
111
105
  useEffect(() => {
112
106
  if (ref && elementRef.current) {
113
107
  if (typeof ref === 'function') {
@@ -127,19 +121,16 @@ export const TyCheckbox = React.forwardRef<HTMLElement, TyCheckboxProps>(
127
121
  const isDisabled = useBooleanProperty(elementRef, 'disabled', disabled);
128
122
  const isRequired = useBooleanProperty(elementRef, 'required', required);
129
123
 
130
- // Convert React props to web component attributes
131
124
  const webComponentProps: Record<string, any> = {
132
125
  ...hostProps(props),
133
126
  ref: elementRef,
134
127
  };
135
128
 
136
- // Add boolean attributes
137
129
  if (isChecked) webComponentProps.checked = '';
138
130
  if (isIndeterminate) webComponentProps.indeterminate = '';
139
131
  if (isDisabled) webComponentProps.disabled = '';
140
132
  if (isRequired) webComponentProps.required = '';
141
133
 
142
- // Add string attributes
143
134
  if (value) webComponentProps.value = value;
144
135
  if (name) webComponentProps.name = name;
145
136
  if (error) webComponentProps.error = error;
@@ -2,10 +2,9 @@ import React, { useEffect, useRef } from 'react';
2
2
  import { hostProps } from '../utils/host-props';
3
3
  import { useBooleanProperty } from '../utils/use-boolean-prop';
4
4
 
5
- type BuiltinFlavor = 'primary' | 'secondary' | 'success' | 'danger' | 'warning' | 'neutral';
5
+ type BuiltinFlavor = 'primary' | 'success' | 'danger' | 'warning' | 'neutral';
6
6
  type ShadedFlavor = BuiltinFlavor | `${BuiltinFlavor}+` | `${BuiltinFlavor}-`;
7
7
 
8
- // Type definitions for Ty Copy component
9
8
  export interface TyCopyProps extends Omit<React.HTMLAttributes<HTMLElement>, 'onChange'> {
10
9
  /** Text to copy */
11
10
  value?: string;
@@ -38,7 +37,6 @@ export interface TyCopyProps extends Omit<React.HTMLAttributes<HTMLElement>, 'on
38
37
  onCopyError?: (event: CustomEvent) => void;
39
38
  }
40
39
 
41
- // React wrapper for ty-copy web component
42
40
  export const TyCopy = React.forwardRef<HTMLElement, TyCopyProps>(
43
41
  ({
44
42
  value,
@@ -55,7 +53,6 @@ export const TyCopy = React.forwardRef<HTMLElement, TyCopyProps>(
55
53
  }, ref) => {
56
54
  const elementRef = useRef<HTMLElement>(null);
57
55
 
58
- // Handle ref forwarding
59
56
  useEffect(() => {
60
57
  if (ref && elementRef.current) {
61
58
  if (typeof ref === 'function') {
@@ -66,7 +63,6 @@ export const TyCopy = React.forwardRef<HTMLElement, TyCopyProps>(
66
63
  }
67
64
  }, [ref]);
68
65
 
69
- // Custom events → React callbacks
70
66
  useEffect(() => {
71
67
  const el = elementRef.current;
72
68
  if (!el) return;
@@ -86,20 +82,17 @@ export const TyCopy = React.forwardRef<HTMLElement, TyCopyProps>(
86
82
  const isDisabled = useBooleanProperty(elementRef, 'disabled', disabled);
87
83
  const isRequired = useBooleanProperty(elementRef, 'required', required);
88
84
 
89
- // Convert React props to web component attributes
90
85
  const webComponentProps: Record<string, any> = {
91
86
  ...hostProps(props),
92
87
  ref: elementRef,
93
88
  };
94
89
 
95
- // Add string attributes
96
90
  if (value) webComponentProps.value = value;
97
91
  if (label) webComponentProps.label = label;
98
92
  if (size) webComponentProps.size = size;
99
93
  if (flavor) webComponentProps.flavor = flavor;
100
94
  if (format) webComponentProps.format = format;
101
95
 
102
- // Add boolean attributes
103
96
  if (isMultiline) webComponentProps.multiline = '';
104
97
  if (isDisabled) webComponentProps.disabled = '';
105
98
  if (isRequired) webComponentProps.required = '';
@@ -3,10 +3,14 @@ import { hostProps } from '../utils/host-props';
3
3
  import { needsPropertyBridge } from '../utils/react-version';
4
4
  import { useBooleanProperty } from '../utils/use-boolean-prop';
5
5
 
6
- type BuiltinFlavor = 'primary' | 'secondary' | 'success' | 'danger' | 'warning' | 'neutral';
6
+ type BuiltinFlavor = 'primary' | 'success' | 'danger' | 'warning' | 'neutral';
7
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';
8
13
 
9
- // Type definitions for Ty DatePicker component
10
14
  export interface TyDatePickerEventDetail {
11
15
  /** The selected date value (ISO string or formatted string based on format) */
12
16
  value: string | null;
@@ -60,7 +64,10 @@ export interface TyDatePickerProps extends Omit<React.HTMLAttributes<HTMLElement
60
64
 
61
65
  /** Latest selectable date (ISO "YYYY-MM-DD") */
62
66
  max?: string;
63
-
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
+
64
71
  /** Callback when the date value changes */
65
72
  onChange?: (event: CustomEvent<TyDatePickerEventDetail>) => void;
66
73
 
@@ -76,7 +83,6 @@ export interface TyDatePickerElement extends HTMLElement {
76
83
  clear(): void;
77
84
  }
78
85
 
79
- // React wrapper for ty-date-picker web component
80
86
  export const TyDatePicker = React.forwardRef<TyDatePickerElement, TyDatePickerProps>(
81
87
  ({
82
88
  value,
@@ -93,6 +99,7 @@ export const TyDatePicker = React.forwardRef<TyDatePickerElement, TyDatePickerPr
93
99
  withTime,
94
100
  min,
95
101
  max,
102
+ placement,
96
103
  onChange,
97
104
  onOpen,
98
105
  onClose,
@@ -100,7 +107,6 @@ export const TyDatePicker = React.forwardRef<TyDatePickerElement, TyDatePickerPr
100
107
  }, ref) => {
101
108
  const elementRef = useRef<TyDatePickerElement>(null);
102
109
 
103
- // Handle ref forwarding
104
110
  useEffect(() => {
105
111
  if (ref && elementRef.current) {
106
112
  if (typeof ref === 'function') {
@@ -118,12 +124,10 @@ export const TyDatePicker = React.forwardRef<TyDatePickerElement, TyDatePickerPr
118
124
  if (!needsPropertyBridge) return;
119
125
  const element = elementRef.current;
120
126
  if (element && value !== undefined) {
121
- // Set the value property directly on the element
122
127
  (element as any).value = value || '';
123
128
  }
124
129
  }, [value]);
125
130
 
126
- // Handle change events
127
131
  const handleChange = useCallback((event: Event) => {
128
132
  const customEvent = event as CustomEvent<TyDatePickerEventDetail>;
129
133
  if (onChange) {
@@ -131,10 +135,8 @@ export const TyDatePicker = React.forwardRef<TyDatePickerElement, TyDatePickerPr
131
135
  }
132
136
  }, [onChange]);
133
137
 
134
- // Handle open/close events. Guard with `event.target === element` so
135
- // bubbled open/close events from popup-like descendants slotted inside
136
- // (rare for a date-picker, but defensive — same fix as TyModal/TyPopup)
137
- // 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.
138
140
  const handleOpen = useCallback((event: Event) => {
139
141
  if (event.target !== elementRef.current) return;
140
142
  if (onOpen) onOpen(event as CustomEvent<{}>);
@@ -145,7 +147,6 @@ export const TyDatePicker = React.forwardRef<TyDatePickerElement, TyDatePickerPr
145
147
  if (onClose) onClose(event as CustomEvent<{}>);
146
148
  }, [onClose]);
147
149
 
148
- // Set up event listeners
149
150
  useEffect(() => {
150
151
  const element = elementRef.current;
151
152
  if (!element) return;
@@ -174,13 +175,11 @@ export const TyDatePicker = React.forwardRef<TyDatePickerElement, TyDatePickerPr
174
175
  };
175
176
  }, [handleChange, handleOpen, handleClose, onChange, onOpen, onClose]);
176
177
 
177
- // Convert React props to web component attributes
178
178
  const webComponentProps: Record<string, any> = {
179
179
  ...hostProps(props),
180
180
  ref: elementRef,
181
181
  };
182
182
 
183
- // Add optional attributes only if they have values
184
183
  if (value !== undefined) {
185
184
  webComponentProps.value = value;
186
185
  }
@@ -233,6 +232,10 @@ export const TyDatePicker = React.forwardRef<TyDatePickerElement, TyDatePickerPr
233
232
  webComponentProps.max = max;
234
233
  }
235
234
 
235
+ if (placement) {
236
+ webComponentProps.placement = placement;
237
+ }
238
+
236
239
  return React.createElement('ty-date-picker', webComponentProps);
237
240
  }
238
241
  );
@@ -2,7 +2,6 @@ import React, { useEffect, useRef } from 'react';
2
2
  import { hostProps } from '../utils/host-props';
3
3
  import { useBooleanProperty } from '../utils/use-boolean-prop';
4
4
 
5
- // Type definitions for Ty File Upload component
6
5
  export interface TyFileUploadProps extends Omit<React.HTMLAttributes<HTMLElement>, 'onChange'> {
7
6
  /** Form field name — used as the FormData key */
8
7
  name?: string;
@@ -41,7 +40,6 @@ export interface TyFileUploadEventDetail {
41
40
  names: string[];
42
41
  }
43
42
 
44
- // React wrapper for ty-file-upload web component
45
43
  export const TyFileUpload = React.forwardRef<HTMLElement, TyFileUploadProps>(
46
44
  ({
47
45
  name,
@@ -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
  }
@@ -3,10 +3,9 @@ import { hostProps } from '../utils/host-props';
3
3
  import { needsPropertyBridge } from '../utils/react-version';
4
4
  import { useBooleanProperty } from '../utils/use-boolean-prop';
5
5
 
6
- type BuiltinFlavor = 'primary' | 'secondary' | 'success' | 'danger' | 'warning' | 'neutral';
6
+ type BuiltinFlavor = 'primary' | 'success' | 'danger' | 'warning' | 'neutral';
7
7
  type ShadedFlavor = BuiltinFlavor | `${BuiltinFlavor}+` | `${BuiltinFlavor}-`;
8
8
 
9
- // Event detail structure for ty-input events
10
9
  export interface TyInputEventDetail {
11
10
  value: any; // shadow value (processed/parsed)
12
11
  formattedValue: string; // user-visible formatted value
@@ -27,7 +26,6 @@ export interface TyInputCSSProperties extends React.CSSProperties {
27
26
  '--input-disabled-color'?: string;
28
27
  }
29
28
 
30
- // Type definitions for Ty Input component
31
29
  export interface TyInputProps extends Omit<React.HTMLAttributes<HTMLElement>, 'onChange' | 'onFocus' | 'onBlur' | 'style'> {
32
30
  style?: TyInputCSSProperties;
33
31
  /** Input type */
@@ -96,7 +94,6 @@ export interface TyInputProps extends Omit<React.HTMLAttributes<HTMLElement>, 'o
96
94
  // One-time global warning flags so we don't spam the console.
97
95
  let _warnedOnInputProp = false;
98
96
 
99
- // React wrapper for ty-input web component
100
97
  export const TyInput = React.forwardRef<HTMLElement, TyInputProps>(
101
98
  ({ onChange, onChangeCommit, onFocus, onBlur, disabled, required, name, checked, debounce, ...props }, ref) => {
102
99
  const elementRef = useRef<HTMLElement>(null);
@@ -150,18 +147,14 @@ export const TyInput = React.forwardRef<HTMLElement, TyInputProps>(
150
147
  const element = elementRef.current;
151
148
  if (!element) return;
152
149
 
153
- // Listen for custom input/change events from ty-input
154
- // Map onChange → input event (React convention)
155
150
  if (onChange) {
156
151
  element.addEventListener('input', handleInput as EventListener);
157
152
  }
158
153
 
159
- // Map onChangeCommit → change event (blur behavior)
160
154
  if (onChangeCommit) {
161
155
  element.addEventListener('change', handleChangeCommit as EventListener);
162
156
  }
163
157
 
164
- // Listen for standard focus/blur events
165
158
  if (onFocus) {
166
159
  element.addEventListener('focus', handleFocus as EventListener);
167
160
  }
@@ -186,7 +179,6 @@ export const TyInput = React.forwardRef<HTMLElement, TyInputProps>(
186
179
  };
187
180
  }, [handleInput, handleChangeCommit, handleFocus, handleBlur, onChange, onChangeCommit, onFocus, onBlur]);
188
181
 
189
- // Handle ref forwarding
190
182
  useEffect(() => {
191
183
  if (ref && elementRef.current) {
192
184
  if (typeof ref === 'function') {
@@ -217,21 +209,17 @@ export const TyInput = React.forwardRef<HTMLElement, TyInputProps>(
217
209
  const isRequired = useBooleanProperty(elementRef, 'required', required);
218
210
  const isChecked = useBooleanProperty(elementRef, 'checked', checked);
219
211
 
220
- // Convert React props to web component attributes
221
212
  const webComponentProps: Record<string, any> = {
222
213
  ...hostProps(props),
223
214
  ref: elementRef,
224
215
  };
225
216
 
226
- // Add conditional attributes
227
217
  if (isDisabled) webComponentProps.disabled = '';
228
218
  if (isRequired) webComponentProps.required = '';
229
219
  if (isChecked) webComponentProps.checked = '';
230
220
 
231
- // Add string attributes
232
221
  if (name) webComponentProps.name = name;
233
222
 
234
- // Add debounce attribute
235
223
  if (debounce !== undefined) webComponentProps.debounce = debounce;
236
224
 
237
225
  return React.createElement(
@@ -3,7 +3,6 @@ import { hostProps } from '../utils/host-props';
3
3
  import { useBooleanProperty, coerceBool } from '../utils/use-boolean-prop';
4
4
  import { needsPropertyBridge } from '../utils/react-version';
5
5
 
6
- // Event detail structure for modal events
7
6
  export interface TyModalEventDetail {
8
7
  reason?: 'programmatic' | 'native' | 'backdrop' | 'escape' | 'close-button';
9
8
  returnValue?: string;
@@ -19,7 +18,6 @@ export interface TyModalBeforeCloseDetail {
19
18
  reason: 'programmatic' | 'backdrop' | 'escape' | 'close-button' | 'native';
20
19
  }
21
20
 
22
- // Type definitions for Ty Modal component
23
21
  export interface TyModalProps extends React.HTMLAttributes<HTMLElement> {
24
22
  /** Controls modal visibility */
25
23
  open?: boolean;
@@ -27,12 +25,28 @@ export interface TyModalProps extends React.HTMLAttributes<HTMLElement> {
27
25
  /** Show backdrop behind modal (default: true) */
28
26
  backdrop?: boolean;
29
27
 
30
- /** Allow closing modal by clicking backdrop (default: true) */
28
+ /**
29
+ * @deprecated Use `preventOutsideClick` — string-boolean attrs are being
30
+ * phased out. Still works; prevent-* wins when both are set.
31
+ */
31
32
  closeOnOutsideClick?: boolean;
32
33
 
33
- /** Allow closing modal with Escape key (default: true) */
34
+ /**
35
+ * @deprecated Use `preventEscape` — string-boolean attrs are being phased
36
+ * out. Still works; prevent-* wins when both are set.
37
+ */
34
38
  closeOnEscape?: boolean;
35
39
 
40
+ /** Backdrop clicks no longer close the modal (also hides the built-in ✕) */
41
+ preventOutsideClick?: boolean;
42
+
43
+ /**
44
+ * ESC no longer closes the modal (keydown is consumed, so the browser's
45
+ * double-ESC anti-trap never fires). A fully guarded modal must render its
46
+ * own close control — WCAG 2.1.2.
47
+ */
48
+ preventEscape?: boolean;
49
+
36
50
  /**
37
51
  * Accessible name — sets aria-label on the internal <dialog>. The dialog
38
52
  * gets role="dialog" for free, but nothing names it unless you set this.
@@ -52,7 +66,6 @@ export interface TyModalProps extends React.HTMLAttributes<HTMLElement> {
52
66
  children?: React.ReactNode;
53
67
  }
54
68
 
55
- // Ref interface for imperative methods
56
69
  export interface TyModalRef {
57
70
  show: () => void;
58
71
  /**
@@ -64,13 +77,14 @@ export interface TyModalRef {
64
77
  element: HTMLElement | null;
65
78
  }
66
79
 
67
- // React wrapper for ty-modal web component
68
80
  export const TyModal = React.forwardRef<TyModalRef, TyModalProps>(
69
81
  ({
70
82
  open,
71
83
  backdrop,
72
84
  closeOnOutsideClick,
73
85
  closeOnEscape,
86
+ preventOutsideClick,
87
+ preventEscape,
74
88
  label,
75
89
  onOpen,
76
90
  onClose,
@@ -80,7 +94,6 @@ export const TyModal = React.forwardRef<TyModalRef, TyModalProps>(
80
94
  }, ref) => {
81
95
  const elementRef = useRef<HTMLElement>(null);
82
96
 
83
- // Expose imperative methods through ref
84
97
  useImperativeHandle(ref, () => ({
85
98
  show: () => {
86
99
  if (elementRef.current && typeof (elementRef.current as any).show === 'function') {
@@ -95,17 +108,12 @@ export const TyModal = React.forwardRef<TyModalRef, TyModalProps>(
95
108
  element: elementRef.current,
96
109
  }), []);
97
110
 
98
- // Handle modal events.
99
- //
100
- // ty-dropdown, ty-multiselect, ty-date-picker etc. dispatch their own
101
- // `open`/`close` custom events with `bubbles: true, composed: true` when
102
- // their internal popups toggle. Those events bubble up through the
103
- // modal's slotted content and land on the ty-modal host — same event
104
- // type, same listener. Without the `event.target === element` guard, an
105
- // `onClose={() => setIsOpen(false)}` callback would fire every time the
106
- // user closes a dropdown inside the modal, and the React state flip
107
- // would close the modal. Core's modal.ts already applies the same guard
108
- // on its internal <dialog>.onclose; this is the React-layer mirror.
111
+ // Popup lifecycle events (`open`/`close`, plus `beforeclose` on the modal)
112
+ // no longer bubble — core dispatches them non-composed on the element
113
+ // itself, like the native <dialog> events they mirror, so a dropdown or
114
+ // nested modal closing inside this one can't reach these listeners. The
115
+ // `event.target === element` guard stays as belt-and-braces for consumers
116
+ // pinned to an older tyrell-components.
109
117
  useEffect(() => {
110
118
  const element = elementRef.current;
111
119
  if (!element) return;
@@ -125,7 +133,6 @@ export const TyModal = React.forwardRef<TyModalRef, TyModalProps>(
125
133
  if (onBeforeClose) onBeforeClose(event);
126
134
  };
127
135
 
128
- // Listen for custom modal events
129
136
  if (onOpen) {
130
137
  element.addEventListener('open', handleOpen as EventListener);
131
138
  }
@@ -170,9 +177,10 @@ export const TyModal = React.forwardRef<TyModalRef, TyModalProps>(
170
177
  setIf('backdrop', backdrop);
171
178
  setIf('closeOnOutsideClick', closeOnOutsideClick);
172
179
  setIf('closeOnEscape', closeOnEscape);
173
- }, [backdrop, closeOnOutsideClick, closeOnEscape]);
180
+ setIf('preventOutsideClick', preventOutsideClick);
181
+ setIf('preventEscape', preventEscape);
182
+ }, [backdrop, closeOnOutsideClick, closeOnEscape, preventOutsideClick, preventEscape]);
174
183
 
175
- // Convert React props to web component attributes
176
184
  const webComponentProps: Record<string, any> = {
177
185
  ...hostProps(props),
178
186
  ref: elementRef,
@@ -191,6 +199,13 @@ export const TyModal = React.forwardRef<TyModalRef, TyModalProps>(
191
199
  if (closeOnEscape !== undefined && !coerceBool(closeOnEscape)) {
192
200
  webComponentProps['close-on-escape'] = 'false';
193
201
  }
202
+ // Presence booleans: render the bare attribute only when true
203
+ if (preventOutsideClick !== undefined && coerceBool(preventOutsideClick)) {
204
+ webComponentProps['prevent-outside-click'] = '';
205
+ }
206
+ if (preventEscape !== undefined && coerceBool(preventEscape)) {
207
+ webComponentProps['prevent-escape'] = '';
208
+ }
194
209
  if (label) webComponentProps.label = label;
195
210
 
196
211
  return React.createElement(
@@ -2,7 +2,6 @@ import React, { useEffect, useRef } from 'react';
2
2
  import { hostProps } from '../utils/host-props';
3
3
  import { useBooleanProperty } from '../utils/use-boolean-prop';
4
4
 
5
- // Type definitions for Ty Option component
6
5
  export interface TyOptionProps extends React.HTMLAttributes<HTMLElement> {
7
6
  value?: string;
8
7
 
@@ -14,7 +13,7 @@ export interface TyOptionProps extends React.HTMLAttributes<HTMLElement> {
14
13
  label?: string;
15
14
 
16
15
  /** Semantic flavor — carried onto ty-selected-options chips */
17
- flavor?: 'primary' | 'secondary' | 'success' | 'danger' | 'warning' | 'neutral' | 'info';
16
+ flavor?: 'primary' | 'success' | 'danger' | 'warning' | 'neutral' | 'info';
18
17
 
19
18
  disabled?: boolean;
20
19
  selected?: boolean;
@@ -22,12 +21,10 @@ export interface TyOptionProps extends React.HTMLAttributes<HTMLElement> {
22
21
  children?: React.ReactNode;
23
22
  }
24
23
 
25
- // React wrapper for ty-option web component
26
24
  export const TyOption = React.forwardRef<HTMLElement, TyOptionProps>(
27
25
  ({ children, label, flavor, disabled, selected, hidden, ...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') {