tyrell-react 1.0.0-TC7
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 +386 -0
- package/dist/components/TyButton.d.ts +50 -0
- package/dist/components/TyButton.d.ts.map +1 -0
- package/dist/components/TyButton.js +63 -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 +122 -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 +68 -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 +42 -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 +114 -0
- package/dist/components/TyDatePicker.js.map +1 -0
- package/dist/components/TyDropdown.d.ts +51 -0
- package/dist/components/TyDropdown.d.ts.map +1 -0
- package/dist/components/TyDropdown.js +97 -0
- package/dist/components/TyDropdown.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 +41 -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 +92 -0
- package/dist/components/TyInput.js.map +1 -0
- package/dist/components/TyModal.d.ts +29 -0
- package/dist/components/TyModal.d.ts.map +1 -0
- package/dist/components/TyModal.js +74 -0
- package/dist/components/TyModal.js.map +1 -0
- package/dist/components/TyMultiselect.d.ts +51 -0
- package/dist/components/TyMultiselect.d.ts.map +1 -0
- package/dist/components/TyMultiselect.js +92 -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 +25 -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 +61 -0
- package/dist/components/TyPopup.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 +43 -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/TyTab.d.ts +13 -0
- package/dist/components/TyTab.d.ts.map +1 -0
- package/dist/components/TyTab.js +32 -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 +45 -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 +83 -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 +40 -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 +93 -0
- package/dist/components/index.d.ts.map +1 -0
- package/dist/components/index.js +106 -0
- package/dist/components/index.js.map +1 -0
- package/package.json +46 -0
- package/src/components/EventConventionTest.tsx +155 -0
- package/src/components/TyButton.tsx +140 -0
- package/src/components/TyCalendar.tsx +244 -0
- package/src/components/TyCalendarMonth.tsx +108 -0
- package/src/components/TyCalendarNavigation.tsx +91 -0
- package/src/components/TyCheckbox.tsx +138 -0
- package/src/components/TyCopy.tsx +78 -0
- package/src/components/TyDatePicker.tsx +216 -0
- package/src/components/TyDropdown.tsx +205 -0
- package/src/components/TyIcon.tsx +72 -0
- package/src/components/TyInput.tsx +194 -0
- package/src/components/TyModal.tsx +142 -0
- package/src/components/TyMultiselect.tsx +189 -0
- package/src/components/TyOption.tsx +42 -0
- package/src/components/TyPopup.tsx +111 -0
- package/src/components/TyResizeObserver.tsx +54 -0
- package/src/components/TyScrollContainer.tsx +87 -0
- package/src/components/TyStep.tsx +71 -0
- package/src/components/TyTab.tsx +63 -0
- package/src/components/TyTabs.tsx +93 -0
- package/src/components/TyTag.tsx +79 -0
- package/src/components/TyTextarea.tsx +144 -0
- package/src/components/TyTooltip.tsx +83 -0
- package/src/components/TyWizard.tsx +99 -0
- package/src/components/index.ts +230 -0
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import React, { useEffect, useRef } from 'react';
|
|
2
|
+
|
|
3
|
+
// Type definitions for Ty Tabs component
|
|
4
|
+
export interface TyTabsProps extends Omit<React.HTMLAttributes<HTMLElement>, 'onChange'> {
|
|
5
|
+
/** Content area width (accepts px or %) */
|
|
6
|
+
width?: string;
|
|
7
|
+
|
|
8
|
+
/** Total container height including buttons */
|
|
9
|
+
height?: string;
|
|
10
|
+
|
|
11
|
+
/** ID of currently active tab */
|
|
12
|
+
active?: string;
|
|
13
|
+
|
|
14
|
+
/** Position of tab buttons */
|
|
15
|
+
placement?: 'top' | 'bottom';
|
|
16
|
+
|
|
17
|
+
/** Tab change event handler */
|
|
18
|
+
onChange?: (event: CustomEvent<TabChangeDetail>) => void;
|
|
19
|
+
|
|
20
|
+
/** Tabs content (TyTab components) */
|
|
21
|
+
children?: React.ReactNode;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface TabChangeDetail {
|
|
25
|
+
activeId: string;
|
|
26
|
+
activeIndex: number;
|
|
27
|
+
previousId: string | null;
|
|
28
|
+
previousIndex: number | null;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// React wrapper for ty-tabs web component
|
|
32
|
+
export const TyTabs = React.forwardRef<HTMLElement, TyTabsProps>(
|
|
33
|
+
({
|
|
34
|
+
children,
|
|
35
|
+
width,
|
|
36
|
+
height,
|
|
37
|
+
active,
|
|
38
|
+
placement,
|
|
39
|
+
onChange,
|
|
40
|
+
...props
|
|
41
|
+
}, ref) => {
|
|
42
|
+
const elementRef = useRef<HTMLElement>(null);
|
|
43
|
+
|
|
44
|
+
// Handle change events
|
|
45
|
+
useEffect(() => {
|
|
46
|
+
const element = elementRef.current;
|
|
47
|
+
if (!element) return;
|
|
48
|
+
|
|
49
|
+
const handleChange = (event: Event) => {
|
|
50
|
+
if (onChange) {
|
|
51
|
+
onChange(event as CustomEvent<TabChangeDetail>);
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
element.addEventListener('ty-tab-change', handleChange);
|
|
56
|
+
|
|
57
|
+
return () => {
|
|
58
|
+
element.removeEventListener('ty-tab-change', handleChange);
|
|
59
|
+
};
|
|
60
|
+
}, [onChange]);
|
|
61
|
+
|
|
62
|
+
// Combine refs if needed
|
|
63
|
+
useEffect(() => {
|
|
64
|
+
if (ref && elementRef.current) {
|
|
65
|
+
if (typeof ref === 'function') {
|
|
66
|
+
ref(elementRef.current);
|
|
67
|
+
} else {
|
|
68
|
+
ref.current = elementRef.current;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}, [ref]);
|
|
72
|
+
|
|
73
|
+
// Convert React props to web component attributes
|
|
74
|
+
const webComponentProps: Record<string, any> = {
|
|
75
|
+
...props,
|
|
76
|
+
ref: elementRef,
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
// Add string attributes
|
|
80
|
+
if (width) webComponentProps.width = width;
|
|
81
|
+
if (height) webComponentProps.height = height;
|
|
82
|
+
if (active) webComponentProps.active = active;
|
|
83
|
+
if (placement) webComponentProps.placement = placement;
|
|
84
|
+
|
|
85
|
+
return React.createElement(
|
|
86
|
+
'ty-tabs',
|
|
87
|
+
webComponentProps,
|
|
88
|
+
children
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
);
|
|
92
|
+
|
|
93
|
+
TyTabs.displayName = 'TyTabs';
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import React, { useEffect, useRef, useCallback } from 'react';
|
|
2
|
+
|
|
3
|
+
// CSS custom properties that cascade into the shadow DOM for full color control
|
|
4
|
+
export interface TyTagCSSProperties extends React.CSSProperties {
|
|
5
|
+
'--tag-bg'?: string;
|
|
6
|
+
'--tag-color'?: string;
|
|
7
|
+
'--tag-border-color'?: string;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
// Type definitions for Ty Tag component
|
|
11
|
+
export interface TyTagProps extends Omit<React.HTMLAttributes<HTMLElement>, 'style' | 'onClick'> {
|
|
12
|
+
flavor?: 'primary' | 'secondary' | 'success' | 'danger' | 'warning' | 'neutral';
|
|
13
|
+
size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl';
|
|
14
|
+
notPill?: boolean;
|
|
15
|
+
clickable?: boolean;
|
|
16
|
+
dismissible?: boolean;
|
|
17
|
+
disabled?: boolean;
|
|
18
|
+
selected?: boolean;
|
|
19
|
+
value?: string;
|
|
20
|
+
style?: TyTagCSSProperties;
|
|
21
|
+
// click is a composed CustomEvent from the web component — React's onClick picks it up
|
|
22
|
+
onClick?: (event: CustomEvent) => void;
|
|
23
|
+
onTagDismiss?: (event: CustomEvent) => void;
|
|
24
|
+
children?: React.ReactNode;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// React wrapper for ty-tag web component
|
|
28
|
+
export const TyTag = React.forwardRef<HTMLElement, TyTagProps>(
|
|
29
|
+
({ children, onClick, onTagDismiss, notPill, clickable, dismissible, disabled, selected, ...props }, ref) => {
|
|
30
|
+
const elementRef = useRef<HTMLElement>(null);
|
|
31
|
+
|
|
32
|
+
const handleDismiss = useCallback((event: CustomEvent) => {
|
|
33
|
+
if (onTagDismiss) {
|
|
34
|
+
onTagDismiss(event);
|
|
35
|
+
}
|
|
36
|
+
}, [onTagDismiss]);
|
|
37
|
+
|
|
38
|
+
// dismiss is a custom event — React doesn't know about it, so we need a manual listener
|
|
39
|
+
useEffect(() => {
|
|
40
|
+
const element = elementRef.current;
|
|
41
|
+
if (!element || !onTagDismiss) return;
|
|
42
|
+
|
|
43
|
+
element.addEventListener('dismiss', handleDismiss as EventListener);
|
|
44
|
+
return () => {
|
|
45
|
+
element.removeEventListener('dismiss', handleDismiss as EventListener);
|
|
46
|
+
};
|
|
47
|
+
}, [handleDismiss, onTagDismiss]);
|
|
48
|
+
|
|
49
|
+
// Handle ref forwarding
|
|
50
|
+
useEffect(() => {
|
|
51
|
+
if (ref && elementRef.current) {
|
|
52
|
+
if (typeof ref === 'function') {
|
|
53
|
+
ref(elementRef.current);
|
|
54
|
+
} else {
|
|
55
|
+
ref.current = elementRef.current;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}, [ref]);
|
|
59
|
+
|
|
60
|
+
return React.createElement(
|
|
61
|
+
'ty-tag',
|
|
62
|
+
{
|
|
63
|
+
...props,
|
|
64
|
+
// click is dispatched as composed CustomEvent by the web component — React's
|
|
65
|
+
// synthetic onClick already catches it, so we just pass it through as onClick
|
|
66
|
+
...(onClick && { onClick }),
|
|
67
|
+
...(notPill && { 'not-pill': "" }),
|
|
68
|
+
...(clickable && { clickable: "" }),
|
|
69
|
+
...(dismissible && { dismissible: "" }),
|
|
70
|
+
...(disabled && { disabled: "" }),
|
|
71
|
+
...(selected && { selected: "" }),
|
|
72
|
+
ref: elementRef,
|
|
73
|
+
},
|
|
74
|
+
children
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
);
|
|
78
|
+
|
|
79
|
+
TyTag.displayName = 'TyTag';
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import React, { useEffect, useRef, useCallback } from 'react';
|
|
2
|
+
|
|
3
|
+
// Event detail structure for ty-textarea events
|
|
4
|
+
export interface TyTextareaEventDetail {
|
|
5
|
+
value: string; // textarea value
|
|
6
|
+
originalEvent: Event; // original DOM event
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
// Type definitions for Ty Textarea component
|
|
10
|
+
export interface TyTextareaProps extends Omit<React.HTMLAttributes<HTMLElement>, 'onChange' | 'onInput' | 'onFocus' | 'onBlur' | 'style'> {
|
|
11
|
+
style?: import('./TyInput').TyInputCSSProperties;
|
|
12
|
+
size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl';
|
|
13
|
+
value?: string;
|
|
14
|
+
placeholder?: string;
|
|
15
|
+
label?: string;
|
|
16
|
+
error?: string;
|
|
17
|
+
disabled?: boolean;
|
|
18
|
+
required?: boolean;
|
|
19
|
+
name?: string; // Important for HTMX/form compatibility
|
|
20
|
+
|
|
21
|
+
// Textarea-specific props
|
|
22
|
+
rows?: string | number;
|
|
23
|
+
cols?: string | number;
|
|
24
|
+
resize?: 'none' | 'both' | 'horizontal' | 'vertical';
|
|
25
|
+
minHeight?: string; // e.g., '100px' - converts to min-height
|
|
26
|
+
maxHeight?: string; // e.g., '500px' - converts to max-height
|
|
27
|
+
|
|
28
|
+
// React event handlers - override with our custom types
|
|
29
|
+
/**
|
|
30
|
+
* Fires on every keystroke (React convention)
|
|
31
|
+
* Maps to native 'input' event from ty-textarea
|
|
32
|
+
*/
|
|
33
|
+
onChange?: (event: CustomEvent<TyTextareaEventDetail>) => void;
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Fires on blur if value changed (native DOM behavior)
|
|
37
|
+
* Maps to native 'change' event from ty-textarea
|
|
38
|
+
*/
|
|
39
|
+
onChangeCommit?: (event: CustomEvent<TyTextareaEventDetail>) => void;
|
|
40
|
+
|
|
41
|
+
/** Standard focus event */
|
|
42
|
+
onFocus?: (event: FocusEvent) => void;
|
|
43
|
+
|
|
44
|
+
/** Standard blur event */
|
|
45
|
+
onBlur?: (event: FocusEvent) => void;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// React wrapper for ty-textarea web component
|
|
49
|
+
export const TyTextarea = React.forwardRef<HTMLElement, TyTextareaProps>(
|
|
50
|
+
({ onChange, onChangeCommit, onFocus, onBlur, disabled, required, minHeight, maxHeight, ...props }, ref) => {
|
|
51
|
+
const elementRef = useRef<HTMLElement>(null);
|
|
52
|
+
|
|
53
|
+
// Map onChange to input event (React convention)
|
|
54
|
+
const handleInput = useCallback((event: CustomEvent<TyTextareaEventDetail>) => {
|
|
55
|
+
if (onChange) {
|
|
56
|
+
onChange(event);
|
|
57
|
+
}
|
|
58
|
+
}, [onChange]);
|
|
59
|
+
|
|
60
|
+
// Map onChangeCommit to change event (blur behavior)
|
|
61
|
+
const handleChangeCommit = useCallback((event: CustomEvent<TyTextareaEventDetail>) => {
|
|
62
|
+
if (onChangeCommit) {
|
|
63
|
+
onChangeCommit(event);
|
|
64
|
+
}
|
|
65
|
+
}, [onChangeCommit]);
|
|
66
|
+
|
|
67
|
+
const handleFocus = useCallback((event: FocusEvent) => {
|
|
68
|
+
if (onFocus) {
|
|
69
|
+
onFocus(event);
|
|
70
|
+
}
|
|
71
|
+
}, [onFocus]);
|
|
72
|
+
|
|
73
|
+
const handleBlur = useCallback((event: FocusEvent) => {
|
|
74
|
+
if (onBlur) {
|
|
75
|
+
onBlur(event);
|
|
76
|
+
}
|
|
77
|
+
}, [onBlur]);
|
|
78
|
+
|
|
79
|
+
useEffect(() => {
|
|
80
|
+
const element = elementRef.current;
|
|
81
|
+
if (!element) return;
|
|
82
|
+
|
|
83
|
+
// Listen for custom input/change events from ty-textarea
|
|
84
|
+
// Map onChange → input event (React convention)
|
|
85
|
+
if (onChange) {
|
|
86
|
+
element.addEventListener('input', handleInput as EventListener);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Map onChangeCommit → change event (blur behavior)
|
|
90
|
+
if (onChangeCommit) {
|
|
91
|
+
element.addEventListener('change', handleChangeCommit as EventListener);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// Listen for standard focus/blur events
|
|
95
|
+
if (onFocus) {
|
|
96
|
+
element.addEventListener('focus', handleFocus as EventListener);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
if (onBlur) {
|
|
100
|
+
element.addEventListener('blur', handleBlur as EventListener);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return () => {
|
|
104
|
+
if (onChange) {
|
|
105
|
+
element.removeEventListener('input', handleInput as EventListener);
|
|
106
|
+
}
|
|
107
|
+
if (onChangeCommit) {
|
|
108
|
+
element.removeEventListener('change', handleChangeCommit as EventListener);
|
|
109
|
+
}
|
|
110
|
+
if (onFocus) {
|
|
111
|
+
element.removeEventListener('focus', handleFocus as EventListener);
|
|
112
|
+
}
|
|
113
|
+
if (onBlur) {
|
|
114
|
+
element.removeEventListener('blur', handleBlur as EventListener);
|
|
115
|
+
}
|
|
116
|
+
};
|
|
117
|
+
}, [handleInput, handleChangeCommit, handleFocus, handleBlur, onChange, onChangeCommit, onFocus, onBlur]);
|
|
118
|
+
|
|
119
|
+
// Handle ref forwarding
|
|
120
|
+
useEffect(() => {
|
|
121
|
+
if (ref && elementRef.current) {
|
|
122
|
+
if (typeof ref === 'function') {
|
|
123
|
+
ref(elementRef.current);
|
|
124
|
+
} else {
|
|
125
|
+
ref.current = elementRef.current;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}, [ref]);
|
|
129
|
+
|
|
130
|
+
return React.createElement(
|
|
131
|
+
'ty-textarea',
|
|
132
|
+
{
|
|
133
|
+
...props,
|
|
134
|
+
...(disabled && { disabled: "" }),
|
|
135
|
+
...(required && { required: "" }),
|
|
136
|
+
...(minHeight && { 'min-height': minHeight }), // Convert camelCase to kebab-case
|
|
137
|
+
...(maxHeight && { 'max-height': maxHeight }), // Convert camelCase to kebab-case
|
|
138
|
+
ref: elementRef,
|
|
139
|
+
}
|
|
140
|
+
);
|
|
141
|
+
}
|
|
142
|
+
);
|
|
143
|
+
|
|
144
|
+
TyTextarea.displayName = 'TyTextarea';
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import React, { useEffect, useRef } from 'react';
|
|
2
|
+
|
|
3
|
+
// Type definitions for Ty Tooltip component
|
|
4
|
+
export interface TyTooltipProps extends React.HTMLAttributes<HTMLElement> {
|
|
5
|
+
/** Tooltip positioning relative to the parent element */
|
|
6
|
+
placement?: 'top' | 'bottom' | 'left' | 'right';
|
|
7
|
+
|
|
8
|
+
/** Distance in pixels from the anchor element (default: 8) */
|
|
9
|
+
offset?: number;
|
|
10
|
+
|
|
11
|
+
/** Delay in milliseconds before showing tooltip (default: 600) */
|
|
12
|
+
delay?: number;
|
|
13
|
+
|
|
14
|
+
/** Disable the tooltip */
|
|
15
|
+
disabled?: boolean;
|
|
16
|
+
|
|
17
|
+
/** Semantic styling variant */
|
|
18
|
+
flavor?: 'dark' | 'light' | 'primary' | 'secondary' | 'success' | 'danger' | 'warning' | 'info' | 'neutral';
|
|
19
|
+
|
|
20
|
+
/** Tooltip content */
|
|
21
|
+
children?: React.ReactNode;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// React wrapper for ty-tooltip web component
|
|
25
|
+
export const TyTooltip = React.forwardRef<HTMLElement, TyTooltipProps>(
|
|
26
|
+
({
|
|
27
|
+
placement,
|
|
28
|
+
offset,
|
|
29
|
+
delay,
|
|
30
|
+
disabled,
|
|
31
|
+
flavor,
|
|
32
|
+
children,
|
|
33
|
+
...props
|
|
34
|
+
}, ref) => {
|
|
35
|
+
const elementRef = useRef<HTMLElement>(null);
|
|
36
|
+
|
|
37
|
+
// Handle ref forwarding
|
|
38
|
+
useEffect(() => {
|
|
39
|
+
if (ref && elementRef.current) {
|
|
40
|
+
if (typeof ref === 'function') {
|
|
41
|
+
ref(elementRef.current);
|
|
42
|
+
} else {
|
|
43
|
+
ref.current = elementRef.current;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}, [ref]);
|
|
47
|
+
|
|
48
|
+
// Convert React props to web component attributes
|
|
49
|
+
const webComponentProps: Record<string, any> = {
|
|
50
|
+
...props,
|
|
51
|
+
ref: elementRef,
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
// Add optional attributes only if they have values
|
|
55
|
+
if (placement) {
|
|
56
|
+
webComponentProps.placement = placement;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if (offset !== undefined) {
|
|
60
|
+
webComponentProps.offset = offset.toString();
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (delay !== undefined) {
|
|
64
|
+
webComponentProps.delay = delay.toString();
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
if (disabled) {
|
|
68
|
+
webComponentProps.disabled = ''; // Boolean attributes as empty string
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
if (flavor) {
|
|
72
|
+
webComponentProps.flavor = flavor;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return React.createElement(
|
|
76
|
+
'ty-tooltip',
|
|
77
|
+
webComponentProps,
|
|
78
|
+
children
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
);
|
|
82
|
+
|
|
83
|
+
TyTooltip.displayName = 'TyTooltip';
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import React, { useEffect, useRef } from 'react';
|
|
2
|
+
|
|
3
|
+
// Type definitions for Ty Wizard component
|
|
4
|
+
export interface TyWizardProps extends Omit<React.HTMLAttributes<HTMLElement>, 'onChange'> {
|
|
5
|
+
/** Content area width (accepts px or %) */
|
|
6
|
+
width?: string;
|
|
7
|
+
|
|
8
|
+
/** Total container height including step indicators */
|
|
9
|
+
height?: string;
|
|
10
|
+
|
|
11
|
+
/** ID of currently active step */
|
|
12
|
+
active?: string;
|
|
13
|
+
|
|
14
|
+
/** Comma-separated IDs of completed steps */
|
|
15
|
+
completed?: string;
|
|
16
|
+
|
|
17
|
+
/** Step indicator layout */
|
|
18
|
+
orientation?: 'horizontal' | 'vertical';
|
|
19
|
+
|
|
20
|
+
/** Step change event handler */
|
|
21
|
+
onStepChange?: (event: CustomEvent<WizardStepChangeDetail>) => void;
|
|
22
|
+
|
|
23
|
+
/** Wizard content (TyStep components) */
|
|
24
|
+
children?: React.ReactNode;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export interface WizardStepChangeDetail {
|
|
28
|
+
activeId: string;
|
|
29
|
+
activeIndex: number;
|
|
30
|
+
previousId: string | null;
|
|
31
|
+
previousIndex: number | null;
|
|
32
|
+
direction: 'forward' | 'backward' | 'none';
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// React wrapper for ty-wizard web component
|
|
36
|
+
export const TyWizard = React.forwardRef<HTMLElement, TyWizardProps>(
|
|
37
|
+
({
|
|
38
|
+
children,
|
|
39
|
+
width,
|
|
40
|
+
height,
|
|
41
|
+
active,
|
|
42
|
+
completed,
|
|
43
|
+
orientation,
|
|
44
|
+
onStepChange,
|
|
45
|
+
...props
|
|
46
|
+
}, ref) => {
|
|
47
|
+
const elementRef = useRef<HTMLElement>(null);
|
|
48
|
+
|
|
49
|
+
// Handle step change events
|
|
50
|
+
useEffect(() => {
|
|
51
|
+
const element = elementRef.current;
|
|
52
|
+
if (!element) return;
|
|
53
|
+
|
|
54
|
+
const handleStepChange = (event: Event) => {
|
|
55
|
+
if (onStepChange) {
|
|
56
|
+
onStepChange(event as CustomEvent<WizardStepChangeDetail>);
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
element.addEventListener('ty-wizard-step-change', handleStepChange);
|
|
61
|
+
|
|
62
|
+
return () => {
|
|
63
|
+
element.removeEventListener('ty-wizard-step-change', handleStepChange);
|
|
64
|
+
};
|
|
65
|
+
}, [onStepChange]);
|
|
66
|
+
|
|
67
|
+
// Combine refs if needed
|
|
68
|
+
useEffect(() => {
|
|
69
|
+
if (ref && elementRef.current) {
|
|
70
|
+
if (typeof ref === 'function') {
|
|
71
|
+
ref(elementRef.current);
|
|
72
|
+
} else {
|
|
73
|
+
ref.current = elementRef.current;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}, [ref]);
|
|
77
|
+
|
|
78
|
+
// Convert React props to web component attributes
|
|
79
|
+
const webComponentProps: Record<string, any> = {
|
|
80
|
+
...props,
|
|
81
|
+
ref: elementRef,
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
// Add string attributes
|
|
85
|
+
if (width) webComponentProps.width = width;
|
|
86
|
+
if (height) webComponentProps.height = height;
|
|
87
|
+
if (active) webComponentProps.active = active;
|
|
88
|
+
if (completed) webComponentProps.completed = completed;
|
|
89
|
+
if (orientation) webComponentProps.orientation = orientation;
|
|
90
|
+
|
|
91
|
+
return React.createElement(
|
|
92
|
+
'ty-wizard',
|
|
93
|
+
webComponentProps,
|
|
94
|
+
children
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
);
|
|
98
|
+
|
|
99
|
+
TyWizard.displayName = 'TyWizard';
|