tyrell-react 1.0.0-RC10
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/LICENSE +21 -0
- package/README.md +410 -0
- package/dist/components/TyButton.d.ts +52 -0
- package/dist/components/TyButton.d.ts.map +1 -0
- package/dist/components/TyButton.js +76 -0
- package/dist/components/TyButton.js.map +1 -0
- package/dist/components/TyCalendar.d.ts +63 -0
- package/dist/components/TyCalendar.d.ts.map +1 -0
- package/dist/components/TyCalendar.js +128 -0
- package/dist/components/TyCalendar.js.map +1 -0
- package/dist/components/TyCalendarMonth.d.ts +32 -0
- package/dist/components/TyCalendarMonth.d.ts.map +1 -0
- package/dist/components/TyCalendarMonth.js +54 -0
- package/dist/components/TyCalendarMonth.js.map +1 -0
- package/dist/components/TyCalendarNavigation.d.ts +21 -0
- package/dist/components/TyCalendarNavigation.d.ts.map +1 -0
- package/dist/components/TyCalendarNavigation.js +50 -0
- package/dist/components/TyCalendarNavigation.js.map +1 -0
- package/dist/components/TyCheckbox.d.ts +39 -0
- package/dist/components/TyCheckbox.d.ts.map +1 -0
- package/dist/components/TyCheckbox.js +76 -0
- package/dist/components/TyCheckbox.js.map +1 -0
- package/dist/components/TyCopy.d.ts +21 -0
- package/dist/components/TyCopy.d.ts.map +1 -0
- package/dist/components/TyCopy.js +46 -0
- package/dist/components/TyCopy.js.map +1 -0
- package/dist/components/TyDatePicker.d.ts +45 -0
- package/dist/components/TyDatePicker.d.ts.map +1 -0
- package/dist/components/TyDatePicker.js +122 -0
- package/dist/components/TyDatePicker.js.map +1 -0
- package/dist/components/TyDropdown.d.ts +62 -0
- package/dist/components/TyDropdown.d.ts.map +1 -0
- package/dist/components/TyDropdown.js +124 -0
- package/dist/components/TyDropdown.js.map +1 -0
- package/dist/components/TyFileUpload.d.ts +31 -0
- package/dist/components/TyFileUpload.d.ts.map +1 -0
- package/dist/components/TyFileUpload.js +56 -0
- package/dist/components/TyFileUpload.js.map +1 -0
- package/dist/components/TyIcon.d.ts +17 -0
- package/dist/components/TyIcon.d.ts.map +1 -0
- package/dist/components/TyIcon.js +42 -0
- package/dist/components/TyIcon.js.map +1 -0
- package/dist/components/TyInput.d.ts +65 -0
- package/dist/components/TyInput.d.ts.map +1 -0
- package/dist/components/TyInput.js +134 -0
- package/dist/components/TyInput.js.map +1 -0
- package/dist/components/TyModal.d.ts +48 -0
- package/dist/components/TyModal.d.ts.map +1 -0
- package/dist/components/TyModal.js +120 -0
- package/dist/components/TyModal.js.map +1 -0
- package/dist/components/TyMultiselect.d.ts +57 -0
- package/dist/components/TyMultiselect.d.ts.map +1 -0
- package/dist/components/TyMultiselect.js +111 -0
- package/dist/components/TyMultiselect.js.map +1 -0
- package/dist/components/TyOption.d.ts +10 -0
- package/dist/components/TyOption.d.ts.map +1 -0
- package/dist/components/TyOption.js +29 -0
- package/dist/components/TyOption.js.map +1 -0
- package/dist/components/TyPopup.d.ts +24 -0
- package/dist/components/TyPopup.d.ts.map +1 -0
- package/dist/components/TyPopup.js +70 -0
- package/dist/components/TyPopup.js.map +1 -0
- package/dist/components/TyRadio.d.ts +20 -0
- package/dist/components/TyRadio.d.ts.map +1 -0
- package/dist/components/TyRadio.js +35 -0
- package/dist/components/TyRadio.js.map +1 -0
- package/dist/components/TyRadioGroup.d.ts +40 -0
- package/dist/components/TyRadioGroup.d.ts.map +1 -0
- package/dist/components/TyRadioGroup.js +61 -0
- package/dist/components/TyRadioGroup.js.map +1 -0
- package/dist/components/TyResizeObserver.d.ts +11 -0
- package/dist/components/TyResizeObserver.d.ts.map +1 -0
- package/dist/components/TyResizeObserver.js +28 -0
- package/dist/components/TyResizeObserver.js.map +1 -0
- package/dist/components/TyScrollContainer.d.ts +25 -0
- package/dist/components/TyScrollContainer.d.ts.map +1 -0
- package/dist/components/TyScrollContainer.js +61 -0
- package/dist/components/TyScrollContainer.js.map +1 -0
- package/dist/components/TyStep.d.ts +17 -0
- package/dist/components/TyStep.d.ts.map +1 -0
- package/dist/components/TyStep.js +35 -0
- package/dist/components/TyStep.js.map +1 -0
- package/dist/components/TySwitch.d.ts +35 -0
- package/dist/components/TySwitch.d.ts.map +1 -0
- package/dist/components/TySwitch.js +59 -0
- package/dist/components/TySwitch.js.map +1 -0
- package/dist/components/TyTab.d.ts +13 -0
- package/dist/components/TyTab.d.ts.map +1 -0
- package/dist/components/TyTab.js +34 -0
- package/dist/components/TyTab.js.map +1 -0
- package/dist/components/TyTabs.d.ts +23 -0
- package/dist/components/TyTabs.d.ts.map +1 -0
- package/dist/components/TyTabs.js +48 -0
- package/dist/components/TyTabs.js.map +1 -0
- package/dist/components/TyTag.d.ts +22 -0
- package/dist/components/TyTag.d.ts.map +1 -0
- package/dist/components/TyTag.js +51 -0
- package/dist/components/TyTag.js.map +1 -0
- package/dist/components/TyTextarea.d.ts +37 -0
- package/dist/components/TyTextarea.d.ts.map +1 -0
- package/dist/components/TyTextarea.js +116 -0
- package/dist/components/TyTextarea.js.map +1 -0
- package/dist/components/TyTooltip.d.ts +17 -0
- package/dist/components/TyTooltip.d.ts.map +1 -0
- package/dist/components/TyTooltip.js +41 -0
- package/dist/components/TyTooltip.js.map +1 -0
- package/dist/components/TyWizard.d.ts +26 -0
- package/dist/components/TyWizard.d.ts.map +1 -0
- package/dist/components/TyWizard.js +50 -0
- package/dist/components/TyWizard.js.map +1 -0
- package/dist/components/index.d.ts +112 -0
- package/dist/components/index.d.ts.map +1 -0
- package/dist/components/index.js +127 -0
- package/dist/components/index.js.map +1 -0
- package/dist/utils/react-version.d.ts +2 -0
- package/dist/utils/react-version.d.ts.map +1 -0
- package/dist/utils/react-version.js +8 -0
- package/dist/utils/react-version.js.map +1 -0
- package/dist/utils/use-boolean-prop.d.ts +36 -0
- package/dist/utils/use-boolean-prop.d.ts.map +1 -0
- package/dist/utils/use-boolean-prop.js +62 -0
- package/dist/utils/use-boolean-prop.js.map +1 -0
- package/dist/version.d.ts +3 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +6 -0
- package/dist/version.js.map +1 -0
- package/package.json +47 -0
- package/src/components/EventConventionTest.tsx +155 -0
- package/src/components/TyButton.tsx +157 -0
- package/src/components/TyCalendar.tsx +247 -0
- package/src/components/TyCalendarMonth.tsx +108 -0
- package/src/components/TyCalendarNavigation.tsx +91 -0
- package/src/components/TyCheckbox.tsx +147 -0
- package/src/components/TyCopy.tsx +83 -0
- package/src/components/TyDatePicker.tsx +215 -0
- package/src/components/TyDropdown.tsx +240 -0
- package/src/components/TyFileUpload.tsx +108 -0
- package/src/components/TyIcon.tsx +71 -0
- package/src/components/TyInput.tsx +239 -0
- package/src/components/TyModal.tsx +195 -0
- package/src/components/TyMultiselect.tsx +208 -0
- package/src/components/TyOption.tsx +47 -0
- package/src/components/TyPopup.tsx +116 -0
- package/src/components/TyRadio.tsx +61 -0
- package/src/components/TyRadioGroup.tsx +125 -0
- package/src/components/TyResizeObserver.tsx +54 -0
- package/src/components/TyScrollContainer.tsx +102 -0
- package/src/components/TyStep.tsx +71 -0
- package/src/components/TySwitch.tsx +114 -0
- package/src/components/TyTab.tsx +65 -0
- package/src/components/TyTabs.tsx +93 -0
- package/src/components/TyTag.tsx +86 -0
- package/src/components/TyTextarea.tsx +181 -0
- package/src/components/TyTooltip.tsx +83 -0
- package/src/components/TyWizard.tsx +99 -0
- package/src/components/index.ts +279 -0
- package/src/utils/react-version.ts +8 -0
- package/src/utils/use-boolean-prop.ts +62 -0
- package/src/version.ts +6 -0
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
import React, { useEffect, useRef, useCallback } from 'react';
|
|
2
|
+
import { needsPropertyBridge } from '../utils/react-version';
|
|
3
|
+
import { useBooleanProperty } from '../utils/use-boolean-prop';
|
|
4
|
+
|
|
5
|
+
// Type definitions for Ty Calendar component
|
|
6
|
+
export interface TyCalendarChangeEventDetail {
|
|
7
|
+
/** Selected month (1-12) */
|
|
8
|
+
month: number;
|
|
9
|
+
/** Selected year (4-digit) */
|
|
10
|
+
year: number;
|
|
11
|
+
/** Selected day (1-31) */
|
|
12
|
+
day: number;
|
|
13
|
+
/** Action that triggered the change: "select" */
|
|
14
|
+
action: 'select';
|
|
15
|
+
/** Source of the change: "day-click" */
|
|
16
|
+
source: 'day-click';
|
|
17
|
+
/** Complete day context from the calendar month */
|
|
18
|
+
dayContext: any;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface TyCalendarNavigateEventDetail {
|
|
22
|
+
/** Navigation target month (1-12) */
|
|
23
|
+
month: number;
|
|
24
|
+
/** Navigation target year (4-digit) */
|
|
25
|
+
year: number;
|
|
26
|
+
/** Action that triggered the navigation: "navigate" */
|
|
27
|
+
action: 'navigate';
|
|
28
|
+
/** Source of the change: "navigation" */
|
|
29
|
+
source: 'navigation';
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export interface TyCalendarProps extends Omit<React.HTMLAttributes<HTMLElement>, 'onChange'> {
|
|
33
|
+
/** Selected year (4-digit) */
|
|
34
|
+
year?: number | string;
|
|
35
|
+
|
|
36
|
+
/** Selected month (1-12) */
|
|
37
|
+
month?: number | string;
|
|
38
|
+
|
|
39
|
+
/** Selected day (1-31) */
|
|
40
|
+
day?: number | string;
|
|
41
|
+
|
|
42
|
+
/** Show navigation controls */
|
|
43
|
+
showNavigation?: boolean;
|
|
44
|
+
|
|
45
|
+
/** Stateless mode - no internal state management */
|
|
46
|
+
stateless?: boolean;
|
|
47
|
+
|
|
48
|
+
/** Calendar size */
|
|
49
|
+
size?: 'sm' | 'md' | 'lg';
|
|
50
|
+
|
|
51
|
+
/** Locale for date formatting */
|
|
52
|
+
locale?: string;
|
|
53
|
+
|
|
54
|
+
/** Calendar width */
|
|
55
|
+
width?: string | number;
|
|
56
|
+
|
|
57
|
+
/** Minimum calendar width */
|
|
58
|
+
minWidth?: string | number;
|
|
59
|
+
|
|
60
|
+
/** Maximum calendar width */
|
|
61
|
+
maxWidth?: string | number;
|
|
62
|
+
|
|
63
|
+
/** Form field name for form submission */
|
|
64
|
+
name?: string;
|
|
65
|
+
|
|
66
|
+
/** Form value (ISO date string) */
|
|
67
|
+
value?: string;
|
|
68
|
+
|
|
69
|
+
/** Function to render custom day content */
|
|
70
|
+
dayContentFn?: (dayContext: any) => HTMLElement | string;
|
|
71
|
+
|
|
72
|
+
/** Function to determine day CSS classes */
|
|
73
|
+
dayClassesFn?: (dayContext: any) => string[];
|
|
74
|
+
|
|
75
|
+
/** Custom CSS injection for render functions */
|
|
76
|
+
customCSS?: string;
|
|
77
|
+
|
|
78
|
+
/** Callback when a date is selected */
|
|
79
|
+
onChange?: (event: CustomEvent<TyCalendarChangeEventDetail>) => void;
|
|
80
|
+
|
|
81
|
+
/** Callback when navigation changes month/year */
|
|
82
|
+
onNavigate?: (event: CustomEvent<TyCalendarNavigateEventDetail>) => void;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// React wrapper for ty-calendar web component
|
|
86
|
+
export const TyCalendar = React.forwardRef<HTMLElement, TyCalendarProps>(
|
|
87
|
+
({
|
|
88
|
+
year,
|
|
89
|
+
month,
|
|
90
|
+
day,
|
|
91
|
+
showNavigation,
|
|
92
|
+
stateless,
|
|
93
|
+
size,
|
|
94
|
+
locale,
|
|
95
|
+
width,
|
|
96
|
+
minWidth,
|
|
97
|
+
maxWidth,
|
|
98
|
+
name,
|
|
99
|
+
value,
|
|
100
|
+
dayContentFn,
|
|
101
|
+
dayClassesFn,
|
|
102
|
+
customCSS,
|
|
103
|
+
onChange,
|
|
104
|
+
onNavigate,
|
|
105
|
+
...props
|
|
106
|
+
}, ref) => {
|
|
107
|
+
const elementRef = useRef<HTMLElement>(null);
|
|
108
|
+
|
|
109
|
+
// Handle ref forwarding
|
|
110
|
+
useEffect(() => {
|
|
111
|
+
if (ref && elementRef.current) {
|
|
112
|
+
if (typeof ref === 'function') {
|
|
113
|
+
ref(elementRef.current);
|
|
114
|
+
} else {
|
|
115
|
+
ref.current = elementRef.current;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}, [ref]);
|
|
119
|
+
|
|
120
|
+
// Handle change events (date selection)
|
|
121
|
+
const handleChange = useCallback((event: Event) => {
|
|
122
|
+
const customEvent = event as CustomEvent<TyCalendarChangeEventDetail>;
|
|
123
|
+
if (onChange) {
|
|
124
|
+
onChange(customEvent);
|
|
125
|
+
}
|
|
126
|
+
}, [onChange]);
|
|
127
|
+
|
|
128
|
+
// Handle navigate events (month/year navigation)
|
|
129
|
+
const handleNavigate = useCallback((event: Event) => {
|
|
130
|
+
const customEvent = event as CustomEvent<TyCalendarNavigateEventDetail>;
|
|
131
|
+
if (onNavigate) {
|
|
132
|
+
onNavigate(customEvent);
|
|
133
|
+
}
|
|
134
|
+
}, [onNavigate]);
|
|
135
|
+
|
|
136
|
+
// Set up event listeners
|
|
137
|
+
useEffect(() => {
|
|
138
|
+
const element = elementRef.current;
|
|
139
|
+
if (!element) return;
|
|
140
|
+
|
|
141
|
+
const listeners: Array<[string, EventListener]> = [];
|
|
142
|
+
|
|
143
|
+
if (onChange) {
|
|
144
|
+
element.addEventListener('change', handleChange);
|
|
145
|
+
listeners.push(['change', handleChange]);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
if (onNavigate) {
|
|
149
|
+
element.addEventListener('navigate', handleNavigate);
|
|
150
|
+
listeners.push(['navigate', handleNavigate]);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
return () => {
|
|
154
|
+
listeners.forEach(([eventName, handler]) => {
|
|
155
|
+
element.removeEventListener(eventName, handler);
|
|
156
|
+
});
|
|
157
|
+
};
|
|
158
|
+
}, [handleChange, handleNavigate, onChange, onNavigate]);
|
|
159
|
+
|
|
160
|
+
// Set function/object properties directly on the element. Required on
|
|
161
|
+
// React 18, which can't bridge non-string props onto custom elements.
|
|
162
|
+
// React 19+ handles function/object prop-to-property bridging natively.
|
|
163
|
+
useEffect(() => {
|
|
164
|
+
if (!needsPropertyBridge) return;
|
|
165
|
+
const element = elementRef.current;
|
|
166
|
+
if (!element) return;
|
|
167
|
+
|
|
168
|
+
// Day content function property (preferred over attribute)
|
|
169
|
+
if (dayContentFn) {
|
|
170
|
+
(element as any).dayContentFn = dayContentFn;
|
|
171
|
+
} else {
|
|
172
|
+
(element as any).dayContentFn = null;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// Day classes function property (preferred over attribute)
|
|
176
|
+
if (dayClassesFn) {
|
|
177
|
+
(element as any).dayClassesFn = dayClassesFn;
|
|
178
|
+
} else {
|
|
179
|
+
(element as any).dayClassesFn = null;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// Custom CSS property
|
|
183
|
+
if (customCSS) {
|
|
184
|
+
(element as any).customCSS = customCSS;
|
|
185
|
+
} else {
|
|
186
|
+
(element as any).customCSS = null;
|
|
187
|
+
}
|
|
188
|
+
}, [dayContentFn, dayClassesFn, customCSS]);
|
|
189
|
+
|
|
190
|
+
// Convert React props to web component attributes
|
|
191
|
+
const webComponentProps: Record<string, any> = {
|
|
192
|
+
...props,
|
|
193
|
+
ref: elementRef,
|
|
194
|
+
};
|
|
195
|
+
|
|
196
|
+
// Add optional attributes only if they have values
|
|
197
|
+
if (year !== undefined) {
|
|
198
|
+
webComponentProps.year = year.toString();
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
if (month !== undefined) {
|
|
202
|
+
webComponentProps.month = month.toString();
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
if (day !== undefined) {
|
|
206
|
+
webComponentProps.day = day.toString();
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
const isShowNavigation = useBooleanProperty(elementRef, 'showNavigation', showNavigation);
|
|
210
|
+
const isStateless = useBooleanProperty(elementRef, 'stateless', stateless);
|
|
211
|
+
|
|
212
|
+
if (isShowNavigation) webComponentProps['show-navigation'] = '';
|
|
213
|
+
if (isStateless) webComponentProps.stateless = '';
|
|
214
|
+
|
|
215
|
+
if (size) {
|
|
216
|
+
webComponentProps.size = size;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
if (locale) {
|
|
220
|
+
webComponentProps.locale = locale;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
if (width !== undefined) {
|
|
224
|
+
webComponentProps.width = width.toString();
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
if (minWidth !== undefined) {
|
|
228
|
+
webComponentProps['min-width'] = minWidth.toString();
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
if (maxWidth !== undefined) {
|
|
232
|
+
webComponentProps['max-width'] = maxWidth.toString();
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
if (name) {
|
|
236
|
+
webComponentProps.name = name;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
if (value) {
|
|
240
|
+
webComponentProps.value = value;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
return React.createElement('ty-calendar', webComponentProps);
|
|
244
|
+
}
|
|
245
|
+
);
|
|
246
|
+
|
|
247
|
+
TyCalendar.displayName = 'TyCalendar';
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import React, { useEffect, useRef } from 'react';
|
|
2
|
+
|
|
3
|
+
// Type definitions for Ty Calendar Month component
|
|
4
|
+
export interface TyCalendarMonthProps extends React.HTMLAttributes<HTMLElement> {
|
|
5
|
+
/** Display year */
|
|
6
|
+
displayYear?: number;
|
|
7
|
+
|
|
8
|
+
/** Display month (1-12) */
|
|
9
|
+
displayMonth?: number;
|
|
10
|
+
|
|
11
|
+
/** Locale for date formatting */
|
|
12
|
+
locale?: string;
|
|
13
|
+
|
|
14
|
+
/** Calendar size */
|
|
15
|
+
size?: 'sm' | 'md' | 'lg';
|
|
16
|
+
|
|
17
|
+
/** Width of calendar */
|
|
18
|
+
width?: string;
|
|
19
|
+
|
|
20
|
+
/** Minimum width */
|
|
21
|
+
minWidth?: string;
|
|
22
|
+
|
|
23
|
+
/** Maximum width */
|
|
24
|
+
maxWidth?: string;
|
|
25
|
+
|
|
26
|
+
/** Day click event handler */
|
|
27
|
+
onDayClick?: (event: CustomEvent<DayClickDetail>) => void;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export interface DayClickDetail {
|
|
31
|
+
dayContext: any; // DayContext type from calendar-utils
|
|
32
|
+
value: number;
|
|
33
|
+
year: number;
|
|
34
|
+
month: number;
|
|
35
|
+
day: number;
|
|
36
|
+
isHoliday?: boolean;
|
|
37
|
+
isToday?: boolean;
|
|
38
|
+
isWeekend: boolean;
|
|
39
|
+
isOtherMonth: boolean;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// React wrapper for ty-calendar-month web component
|
|
43
|
+
export const TyCalendarMonth = React.forwardRef<HTMLElement, TyCalendarMonthProps>(
|
|
44
|
+
({
|
|
45
|
+
displayYear,
|
|
46
|
+
displayMonth,
|
|
47
|
+
locale,
|
|
48
|
+
size,
|
|
49
|
+
width,
|
|
50
|
+
minWidth,
|
|
51
|
+
maxWidth,
|
|
52
|
+
onDayClick,
|
|
53
|
+
...props
|
|
54
|
+
}, ref) => {
|
|
55
|
+
const elementRef = useRef<HTMLElement>(null);
|
|
56
|
+
|
|
57
|
+
// Handle day click events
|
|
58
|
+
useEffect(() => {
|
|
59
|
+
const element = elementRef.current;
|
|
60
|
+
if (!element) return;
|
|
61
|
+
|
|
62
|
+
const handleDayClick = (event: Event) => {
|
|
63
|
+
if (onDayClick) {
|
|
64
|
+
onDayClick(event as CustomEvent<DayClickDetail>);
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
element.addEventListener('day-click', handleDayClick);
|
|
69
|
+
|
|
70
|
+
return () => {
|
|
71
|
+
element.removeEventListener('day-click', handleDayClick);
|
|
72
|
+
};
|
|
73
|
+
}, [onDayClick]);
|
|
74
|
+
|
|
75
|
+
// Combine refs if needed
|
|
76
|
+
useEffect(() => {
|
|
77
|
+
if (ref && elementRef.current) {
|
|
78
|
+
if (typeof ref === 'function') {
|
|
79
|
+
ref(elementRef.current);
|
|
80
|
+
} else {
|
|
81
|
+
ref.current = elementRef.current;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}, [ref]);
|
|
85
|
+
|
|
86
|
+
// Convert React props to web component attributes
|
|
87
|
+
const webComponentProps: Record<string, any> = {
|
|
88
|
+
...props,
|
|
89
|
+
ref: elementRef,
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
// Add attributes
|
|
93
|
+
if (displayYear !== undefined) webComponentProps['display-year'] = displayYear;
|
|
94
|
+
if (displayMonth !== undefined) webComponentProps['display-month'] = displayMonth;
|
|
95
|
+
if (locale) webComponentProps.locale = locale;
|
|
96
|
+
if (size) webComponentProps.size = size;
|
|
97
|
+
if (width) webComponentProps.width = width;
|
|
98
|
+
if (minWidth) webComponentProps['min-width'] = minWidth;
|
|
99
|
+
if (maxWidth) webComponentProps['max-width'] = maxWidth;
|
|
100
|
+
|
|
101
|
+
return React.createElement(
|
|
102
|
+
'ty-calendar-month',
|
|
103
|
+
webComponentProps
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
);
|
|
107
|
+
|
|
108
|
+
TyCalendarMonth.displayName = 'TyCalendarMonth';
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import React, { useEffect, useRef } from 'react';
|
|
2
|
+
|
|
3
|
+
// Type definitions for Ty Calendar Navigation component
|
|
4
|
+
export interface TyCalendarNavigationProps extends Omit<React.HTMLAttributes<HTMLElement>, 'onChange'> {
|
|
5
|
+
/** Display month (1-12) */
|
|
6
|
+
displayMonth?: number;
|
|
7
|
+
|
|
8
|
+
/** Display year */
|
|
9
|
+
displayYear?: number;
|
|
10
|
+
|
|
11
|
+
/** Locale for month name formatting */
|
|
12
|
+
locale?: string;
|
|
13
|
+
|
|
14
|
+
/** Navigation size */
|
|
15
|
+
size?: 'sm' | 'md' | 'lg';
|
|
16
|
+
|
|
17
|
+
/** Width of navigation */
|
|
18
|
+
width?: string;
|
|
19
|
+
|
|
20
|
+
/** Navigation change event handler */
|
|
21
|
+
onChange?: (event: CustomEvent<NavigationChangeDetail>) => void;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface NavigationChangeDetail {
|
|
25
|
+
month: number; // 1-12
|
|
26
|
+
year: number; // e.g., 2025
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// React wrapper for ty-calendar-navigation web component
|
|
30
|
+
export const TyCalendarNavigation = React.forwardRef<HTMLElement, TyCalendarNavigationProps>(
|
|
31
|
+
({
|
|
32
|
+
displayMonth,
|
|
33
|
+
displayYear,
|
|
34
|
+
locale,
|
|
35
|
+
size,
|
|
36
|
+
width,
|
|
37
|
+
onChange,
|
|
38
|
+
...props
|
|
39
|
+
}, ref) => {
|
|
40
|
+
const elementRef = useRef<HTMLElement>(null);
|
|
41
|
+
|
|
42
|
+
// Handle change events
|
|
43
|
+
useEffect(() => {
|
|
44
|
+
const element = elementRef.current;
|
|
45
|
+
if (!element) return;
|
|
46
|
+
|
|
47
|
+
const handleChange = (event: Event) => {
|
|
48
|
+
if (onChange) {
|
|
49
|
+
onChange(event as CustomEvent<NavigationChangeDetail>);
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
element.addEventListener('change', handleChange);
|
|
54
|
+
|
|
55
|
+
return () => {
|
|
56
|
+
element.removeEventListener('change', handleChange);
|
|
57
|
+
};
|
|
58
|
+
}, [onChange]);
|
|
59
|
+
|
|
60
|
+
// Combine refs if needed
|
|
61
|
+
useEffect(() => {
|
|
62
|
+
if (ref && elementRef.current) {
|
|
63
|
+
if (typeof ref === 'function') {
|
|
64
|
+
ref(elementRef.current);
|
|
65
|
+
} else {
|
|
66
|
+
ref.current = elementRef.current;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}, [ref]);
|
|
70
|
+
|
|
71
|
+
// Convert React props to web component attributes
|
|
72
|
+
const webComponentProps: Record<string, any> = {
|
|
73
|
+
...props,
|
|
74
|
+
ref: elementRef,
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
// Add attributes
|
|
78
|
+
if (displayMonth !== undefined) webComponentProps['display-month'] = displayMonth;
|
|
79
|
+
if (displayYear !== undefined) webComponentProps['display-year'] = displayYear;
|
|
80
|
+
if (locale) webComponentProps.locale = locale;
|
|
81
|
+
if (size) webComponentProps.size = size;
|
|
82
|
+
if (width) webComponentProps.width = width;
|
|
83
|
+
|
|
84
|
+
return React.createElement(
|
|
85
|
+
'ty-calendar-navigation',
|
|
86
|
+
webComponentProps
|
|
87
|
+
);
|
|
88
|
+
}
|
|
89
|
+
);
|
|
90
|
+
|
|
91
|
+
TyCalendarNavigation.displayName = 'TyCalendarNavigation';
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import React, { useEffect, useRef } from 'react';
|
|
2
|
+
import { useBooleanProperty } from '../utils/use-boolean-prop';
|
|
3
|
+
|
|
4
|
+
// Type definitions for Ty Checkbox component
|
|
5
|
+
export interface TyCheckboxProps extends Omit<React.HTMLAttributes<HTMLElement>, 'onChange' | 'onInput'> {
|
|
6
|
+
/** Checked state */
|
|
7
|
+
checked?: boolean;
|
|
8
|
+
|
|
9
|
+
/** Form field value when checked */
|
|
10
|
+
value?: string;
|
|
11
|
+
|
|
12
|
+
/** Form field name */
|
|
13
|
+
name?: string;
|
|
14
|
+
|
|
15
|
+
/** Disable the checkbox */
|
|
16
|
+
disabled?: boolean;
|
|
17
|
+
|
|
18
|
+
/** Required field */
|
|
19
|
+
required?: boolean;
|
|
20
|
+
|
|
21
|
+
/** Error message */
|
|
22
|
+
error?: string;
|
|
23
|
+
|
|
24
|
+
/** Checkbox size */
|
|
25
|
+
size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl';
|
|
26
|
+
|
|
27
|
+
/** Semantic styling variant */
|
|
28
|
+
flavor?: 'primary' | 'secondary' | 'success' | 'danger' | 'warning' | 'neutral';
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Fires when checkbox state changes (React convention)
|
|
32
|
+
* Maps to native 'input' event from ty-checkbox
|
|
33
|
+
*/
|
|
34
|
+
onChange?: (event: CustomEvent<TyCheckboxEventDetail>) => void;
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Fires on blur if value changed (native DOM behavior)
|
|
38
|
+
* Maps to native 'change' event from ty-checkbox
|
|
39
|
+
*/
|
|
40
|
+
onChangeCommit?: (event: CustomEvent<TyCheckboxEventDetail>) => void;
|
|
41
|
+
|
|
42
|
+
/** Checkbox label content */
|
|
43
|
+
children?: React.ReactNode;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export interface TyCheckboxEventDetail {
|
|
47
|
+
value: boolean;
|
|
48
|
+
checked: boolean;
|
|
49
|
+
formValue: string | null;
|
|
50
|
+
originalEvent: Event;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// React wrapper for ty-checkbox web component
|
|
54
|
+
export const TyCheckbox = React.forwardRef<HTMLElement, TyCheckboxProps>(
|
|
55
|
+
({
|
|
56
|
+
children,
|
|
57
|
+
checked,
|
|
58
|
+
value,
|
|
59
|
+
name,
|
|
60
|
+
disabled,
|
|
61
|
+
required,
|
|
62
|
+
error,
|
|
63
|
+
size,
|
|
64
|
+
flavor,
|
|
65
|
+
onChange,
|
|
66
|
+
onChangeCommit,
|
|
67
|
+
...props
|
|
68
|
+
}, ref) => {
|
|
69
|
+
const elementRef = useRef<HTMLElement>(null);
|
|
70
|
+
|
|
71
|
+
// Handle change events
|
|
72
|
+
useEffect(() => {
|
|
73
|
+
const element = elementRef.current;
|
|
74
|
+
if (!element) return;
|
|
75
|
+
|
|
76
|
+
// Map onChange to input event (React convention)
|
|
77
|
+
const handleInput = (event: Event) => {
|
|
78
|
+
if (onChange) {
|
|
79
|
+
onChange(event as CustomEvent<TyCheckboxEventDetail>);
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
// Map onChangeCommit to change event (blur behavior)
|
|
84
|
+
const handleChangeCommit = (event: Event) => {
|
|
85
|
+
if (onChangeCommit) {
|
|
86
|
+
onChangeCommit(event as CustomEvent<TyCheckboxEventDetail>);
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
// Map onChange → input event (React convention)
|
|
91
|
+
element.addEventListener('input', handleInput);
|
|
92
|
+
|
|
93
|
+
// Map onChangeCommit → change event (blur behavior)
|
|
94
|
+
element.addEventListener('change', handleChangeCommit);
|
|
95
|
+
|
|
96
|
+
return () => {
|
|
97
|
+
element.removeEventListener('input', handleInput);
|
|
98
|
+
element.removeEventListener('change', handleChangeCommit);
|
|
99
|
+
};
|
|
100
|
+
}, [onChange, onChangeCommit]);
|
|
101
|
+
|
|
102
|
+
// Combine refs if needed
|
|
103
|
+
useEffect(() => {
|
|
104
|
+
if (ref && elementRef.current) {
|
|
105
|
+
if (typeof ref === 'function') {
|
|
106
|
+
ref(elementRef.current);
|
|
107
|
+
} else {
|
|
108
|
+
ref.current = elementRef.current;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}, [ref]);
|
|
112
|
+
|
|
113
|
+
// Imperative property sync for boolean props (see use-boolean-prop.ts).
|
|
114
|
+
// React 18 sets boolean attributes as empty strings on first render but
|
|
115
|
+
// doesn't reliably remove them when the prop flips back to false on a
|
|
116
|
+
// custom element. React 19+ handles this natively.
|
|
117
|
+
const isChecked = useBooleanProperty(elementRef, 'checked', checked);
|
|
118
|
+
const isDisabled = useBooleanProperty(elementRef, 'disabled', disabled);
|
|
119
|
+
const isRequired = useBooleanProperty(elementRef, 'required', required);
|
|
120
|
+
|
|
121
|
+
// Convert React props to web component attributes
|
|
122
|
+
const webComponentProps: Record<string, any> = {
|
|
123
|
+
...props,
|
|
124
|
+
ref: elementRef,
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
// Add boolean attributes
|
|
128
|
+
if (isChecked) webComponentProps.checked = '';
|
|
129
|
+
if (isDisabled) webComponentProps.disabled = '';
|
|
130
|
+
if (isRequired) webComponentProps.required = '';
|
|
131
|
+
|
|
132
|
+
// Add string attributes
|
|
133
|
+
if (value) webComponentProps.value = value;
|
|
134
|
+
if (name) webComponentProps.name = name;
|
|
135
|
+
if (error) webComponentProps.error = error;
|
|
136
|
+
if (size) webComponentProps.size = size;
|
|
137
|
+
if (flavor) webComponentProps.flavor = flavor;
|
|
138
|
+
|
|
139
|
+
return React.createElement(
|
|
140
|
+
'ty-checkbox',
|
|
141
|
+
webComponentProps,
|
|
142
|
+
children
|
|
143
|
+
);
|
|
144
|
+
}
|
|
145
|
+
);
|
|
146
|
+
|
|
147
|
+
TyCheckbox.displayName = 'TyCheckbox';
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import React, { useEffect, useRef } from 'react';
|
|
2
|
+
import { useBooleanProperty } from '../utils/use-boolean-prop';
|
|
3
|
+
|
|
4
|
+
// Type definitions for Ty Copy component
|
|
5
|
+
export interface TyCopyProps extends Omit<React.HTMLAttributes<HTMLElement>, 'onChange'> {
|
|
6
|
+
/** Text to copy */
|
|
7
|
+
value?: string;
|
|
8
|
+
|
|
9
|
+
/** Field label */
|
|
10
|
+
label?: string;
|
|
11
|
+
|
|
12
|
+
/** Component size */
|
|
13
|
+
size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl';
|
|
14
|
+
|
|
15
|
+
/** Semantic styling variant */
|
|
16
|
+
flavor?: 'primary' | 'secondary' | 'success' | 'danger' | 'warning' | 'neutral';
|
|
17
|
+
|
|
18
|
+
/** Display format */
|
|
19
|
+
format?: 'text' | 'code';
|
|
20
|
+
|
|
21
|
+
/** Multi-line display */
|
|
22
|
+
multiline?: boolean;
|
|
23
|
+
|
|
24
|
+
/** Disable the field */
|
|
25
|
+
disabled?: boolean;
|
|
26
|
+
|
|
27
|
+
/** Required field */
|
|
28
|
+
required?: boolean;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// React wrapper for ty-copy web component
|
|
32
|
+
export const TyCopy = React.forwardRef<HTMLElement, TyCopyProps>(
|
|
33
|
+
({
|
|
34
|
+
value,
|
|
35
|
+
label,
|
|
36
|
+
size,
|
|
37
|
+
flavor,
|
|
38
|
+
format,
|
|
39
|
+
multiline,
|
|
40
|
+
disabled,
|
|
41
|
+
required,
|
|
42
|
+
...props
|
|
43
|
+
}, ref) => {
|
|
44
|
+
const elementRef = useRef<HTMLElement>(null);
|
|
45
|
+
|
|
46
|
+
// Handle ref forwarding
|
|
47
|
+
useEffect(() => {
|
|
48
|
+
if (ref && elementRef.current) {
|
|
49
|
+
if (typeof ref === 'function') {
|
|
50
|
+
ref(elementRef.current);
|
|
51
|
+
} else {
|
|
52
|
+
ref.current = elementRef.current;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}, [ref]);
|
|
56
|
+
|
|
57
|
+
const isMultiline = useBooleanProperty(elementRef, 'multiline', multiline);
|
|
58
|
+
const isDisabled = useBooleanProperty(elementRef, 'disabled', disabled);
|
|
59
|
+
const isRequired = useBooleanProperty(elementRef, 'required', required);
|
|
60
|
+
|
|
61
|
+
// Convert React props to web component attributes
|
|
62
|
+
const webComponentProps: Record<string, any> = {
|
|
63
|
+
...props,
|
|
64
|
+
ref: elementRef,
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
// Add string attributes
|
|
68
|
+
if (value) webComponentProps.value = value;
|
|
69
|
+
if (label) webComponentProps.label = label;
|
|
70
|
+
if (size) webComponentProps.size = size;
|
|
71
|
+
if (flavor) webComponentProps.flavor = flavor;
|
|
72
|
+
if (format) webComponentProps.format = format;
|
|
73
|
+
|
|
74
|
+
// Add boolean attributes
|
|
75
|
+
if (isMultiline) webComponentProps.multiline = '';
|
|
76
|
+
if (isDisabled) webComponentProps.disabled = '';
|
|
77
|
+
if (isRequired) webComponentProps.required = '';
|
|
78
|
+
|
|
79
|
+
return React.createElement('ty-copy', webComponentProps);
|
|
80
|
+
}
|
|
81
|
+
);
|
|
82
|
+
|
|
83
|
+
TyCopy.displayName = 'TyCopy';
|